1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 #include "viewcontactoftableobj.hxx"
32 #include <svx/svdotable.hxx>
33 #include <com/sun/star/table/XTable.hpp>
34 #include <basegfx/polygon/b2dpolygontools.hxx>
35 #include <basegfx/polygon/b2dpolygon.hxx>
36 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
37 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
38 #include <drawinglayer/primitive2d/groupprimitive2d.hxx>
39 #include <svx/sdr/primitive2d/sdrdecompositiontools.hxx>
40 #include <svx/sdr/primitive2d/sdrattributecreator.hxx>
41 #include <basegfx/matrix/b2dhommatrix.hxx>
42 #include <svx/sdr/attribute/sdrtextattribute.hxx>
43 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
44 #include <editeng/borderline.hxx>
45 #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx>
46 #include <svx/sdr/attribute/sdrfilltextattribute.hxx>
47 #include <drawinglayer/attribute/sdrlineattribute.hxx>
48 #include <drawinglayer/attribute/sdrshadowattribute.hxx>
49 #include <drawinglayer/primitive2d/sdrdecompositiontools2d.hxx>
50 #include <basegfx/matrix/b2dhommatrixtools.hxx>
51 
52 #include "cell.hxx"
53 #include "tablelayouter.hxx"
54 
55 //////////////////////////////////////////////////////////////////////////////
56 
57 using namespace com::sun::star;
58 
59 //////////////////////////////////////////////////////////////////////////////
60 
61 namespace drawinglayer
62 {
63 	namespace primitive2d
64 	{
65 		class SdrCellPrimitive2D : public BufferedDecompositionPrimitive2D
66 		{
67 		private:
68 			basegfx::B2DHomMatrix						maTransform;
69 			attribute::SdrFillTextAttribute				maSdrFTAttribute;
70 
71 		protected:
72 			// local decomposition.
73 			virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const;
74 
75 		public:
76 			SdrCellPrimitive2D(
77 				const basegfx::B2DHomMatrix& rTransform,
78 				const attribute::SdrFillTextAttribute& rSdrFTAttribute)
79 			:	BufferedDecompositionPrimitive2D(),
80 				maTransform(rTransform),
81 				maSdrFTAttribute(rSdrFTAttribute)
82 			{
83 			}
84 
85 			// data access
86 			const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
87 			const attribute::SdrFillTextAttribute& getSdrFTAttribute() const { return maSdrFTAttribute; }
88 
89 			// compare operator
90 			virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
91 
92 			// provide unique ID
93 			DeclPrimitrive2DIDBlock()
94 		};
95 
96 		Primitive2DSequence SdrCellPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*aViewInformation*/) const
97 		{
98 			// prepare unit polygon
99 			Primitive2DSequence aRetval;
100 			const basegfx::B2DPolyPolygon aUnitPolyPolygon(basegfx::tools::createUnitPolygon());
101 
102 			// add fill
103 			if(!getSdrFTAttribute().getFill().isDefault())
104 			{
105 				appendPrimitive2DReferenceToPrimitive2DSequence(aRetval,
106 					createPolyPolygonFillPrimitive(
107 						aUnitPolyPolygon,
108 						getTransform(),
109 						getSdrFTAttribute().getFill(),
110 						getSdrFTAttribute().getFillFloatTransGradient()));
111 			}
112             else
113             {
114                 // if no fill create one for HitTest and BoundRect fallback
115                 appendPrimitive2DReferenceToPrimitive2DSequence(aRetval,
116                     createHiddenGeometryPrimitives2D(
117                         true,
118                         aUnitPolyPolygon,
119                         getTransform()));
120             }
121 
122 			// add text
123 			if(!getSdrFTAttribute().getText().isDefault())
124 			{
125 				appendPrimitive2DReferenceToPrimitive2DSequence(aRetval,
126 					createTextPrimitive(
127 						aUnitPolyPolygon,
128 						getTransform(),
129 						getSdrFTAttribute().getText(),
130 						attribute::SdrLineAttribute(),
131 						true,
132 						false,
133 						false));
134 			}
135 
136 			return aRetval;
137 		}
138 
139 		bool SdrCellPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
140 		{
141 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
142 			{
143 				const SdrCellPrimitive2D& rCompare = (SdrCellPrimitive2D&)rPrimitive;
144 
145 				return (getTransform() == rCompare.getTransform()
146 					&& getSdrFTAttribute() == rCompare.getSdrFTAttribute());
147 			}
148 
149 			return false;
150 		}
151 
152 		// provide unique ID
153 		ImplPrimitrive2DIDBlock(SdrCellPrimitive2D, PRIMITIVE2D_ID_SDRCELLPRIMITIVE2D)
154 
155 	} // end of namespace primitive2d
156 } // end of namespace drawinglayer
157 
158 //////////////////////////////////////////////////////////////////////////////
159 
160 namespace drawinglayer
161 {
162 	namespace primitive2d
163 	{
164 		class SdrBorderlinePrimitive2D : public BufferedDecompositionPrimitive2D
165 		{
166 		private:
167 			basegfx::B2DHomMatrix						maTransform;
168 			SvxBorderLine								maLeftLine;
169 			SvxBorderLine								maBottomLine;
170 			SvxBorderLine								maRightLine;
171 			SvxBorderLine								maTopLine;
172 
173 			// bitfield
174 			unsigned									mbLeftIsOutside : 1;
175 			unsigned									mbBottomIsOutside : 1;
176 			unsigned									mbRightIsOutside : 1;
177 			unsigned									mbTopIsOutside : 1;
178 			unsigned									mbInTwips : 1;
179 
180 		protected:
181 			// local decomposition.
182 			virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const;
183 
184 		public:
185 			SdrBorderlinePrimitive2D(
186 				const basegfx::B2DHomMatrix& rTransform,
187 				const SvxBorderLine& rLeftLine,
188 				const SvxBorderLine& rBottomLine,
189 				const SvxBorderLine& rRightLine,
190 				const SvxBorderLine& rTopLine,
191 				bool bLeftIsOutside,
192 				bool bBottomIsOutside,
193 				bool bRightIsOutside,
194 				bool bTopIsOutside,
195 				bool bInTwips)
196 			:	BufferedDecompositionPrimitive2D(),
197 				maTransform(rTransform),
198 				maLeftLine(rLeftLine),
199 				maBottomLine(rBottomLine),
200 				maRightLine(rRightLine),
201 				maTopLine(rTopLine),
202 				mbLeftIsOutside(bLeftIsOutside),
203 				mbBottomIsOutside(bBottomIsOutside),
204 				mbRightIsOutside(bRightIsOutside),
205 				mbTopIsOutside(bTopIsOutside),
206 				mbInTwips(bInTwips)
207 			{
208 			}
209 
210 
211 			// data access
212 			const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
213 			const SvxBorderLine& getLeftLine() const { return maLeftLine; }
214 			const SvxBorderLine& getBottomLine() const { return maBottomLine; }
215 			const SvxBorderLine& getRightLine() const { return maRightLine; }
216 			const SvxBorderLine& getTopLine() const { return maTopLine; }
217 			bool getLeftIsOutside() const { return mbLeftIsOutside; }
218 			bool getBottomIsOutside() const { return mbBottomIsOutside; }
219 			bool getRightIsOutside() const { return mbRightIsOutside; }
220 			bool getTopIsOutside() const { return mbTopIsOutside; }
221 			bool getInTwips() const { return mbInTwips; }
222 
223 			// compare operator
224 			virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
225 
226 			// provide unique ID
227 			DeclPrimitrive2DIDBlock()
228 		};
229 
230 		sal_uInt16 getBorderLineOutWidth(const SvxBorderLine& rLineA)
231 		{
232 			return (1 == rLineA.GetOutWidth() ? 0 : rLineA.GetOutWidth());
233 		}
234 
235 		sal_uInt16 getBorderLineDistance(const SvxBorderLine& rLineA)
236 		{
237 			return (1 == rLineA.GetDistance() ? 0 : rLineA.GetDistance());
238 		}
239 
240 		sal_uInt16 getBorderLineInWidth(const SvxBorderLine& rLineA)
241 		{
242 			return (1 == rLineA.GetInWidth() ? 0 : rLineA.GetInWidth());
243 		}
244 
245 		sal_uInt16 getBorderLineWidth(const SvxBorderLine& rLineA)
246 		{
247 			return getBorderLineOutWidth(rLineA) + getBorderLineDistance(rLineA) + getBorderLineInWidth(rLineA);
248 		}
249 
250 		double getInnerExtend(const SvxBorderLine& rLineA, bool bSideToUse)
251 		{
252 			if(!rLineA.isEmpty())
253 			{
254 				if(rLineA.isDouble())
255 				{
256 					// reduce to inner edge of associated matching line
257 					return -((getBorderLineWidth(rLineA) / 2.0) - (bSideToUse ? getBorderLineOutWidth(rLineA) : getBorderLineInWidth(rLineA)));
258 				}
259 				else
260 				{
261 					// extend to overlap with single line
262 					return getBorderLineWidth(rLineA) / 2.0;
263 				}
264 			}
265 
266 			return 0.0;
267 		}
268 
269 		double getOuterExtend(const SvxBorderLine& rLineA)
270 		{
271 			if(!rLineA.isEmpty())
272 			{
273 				// extend to overlap with single line
274 				return getBorderLineWidth(rLineA) / 2.0;
275 			}
276 
277 			return 0.0;
278 		}
279 
280 		double getChangedValue(sal_uInt16 nValue, bool bChangeToMM)
281 		{
282 			if(1 == nValue)
283 				return 1.0;
284 
285 			if(bChangeToMM)
286 				return nValue * (127.0 / 72.0);
287 
288 			return (double)nValue;
289 		}
290 
291 		Primitive2DSequence SdrBorderlinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*aViewInformation*/) const
292 		{
293 			Primitive2DSequence xRetval(4);
294 			sal_uInt32 nInsert(0);
295 			const double fTwipsToMM(getInTwips() ? (127.0 / 72.0) : 1.0);
296 
297 			if(!getLeftLine().isEmpty())
298 			{
299 				// create left line from top to bottom
300 				const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 0.0));
301 				const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(0.0, 1.0));
302 
303 				if(!aStart.equal(aEnd))
304 				{
305 					const double fExtendIS(getInnerExtend(getTopLine(), false));
306 					const double fExtendIE(getInnerExtend(getBottomLine(), true));
307 					double fExtendOS(0.0);
308 					double fExtendOE(0.0);
309 
310 					if(getLeftIsOutside())
311 					{
312 						if(getTopIsOutside())
313 						{
314 							fExtendOS = getOuterExtend(getTopLine());
315 						}
316 
317 						if(getBottomIsOutside())
318 						{
319 							fExtendOE = getOuterExtend(getBottomLine());
320 						}
321 					}
322 
323 					xRetval[nInsert++] = Primitive2DReference(new BorderLinePrimitive2D(
324 						aStart,
325 						aEnd,
326 						getChangedValue(getLeftLine().GetOutWidth(), getInTwips()),
327 						getChangedValue(getLeftLine().GetDistance(), getInTwips()),
328 						getChangedValue(getLeftLine().GetInWidth(), getInTwips()),
329 						fExtendIS * fTwipsToMM,
330 						fExtendIE * fTwipsToMM,
331 						fExtendOS * fTwipsToMM,
332 						fExtendOE * fTwipsToMM,
333 						true,
334 						getLeftIsOutside(),
335 						getLeftLine().GetColor().getBColor()));
336 				}
337 			}
338 
339 			if(!getBottomLine().isEmpty())
340 			{
341 				// create bottom line from left to right
342 				const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 1.0));
343 				const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 1.0));
344 
345 				if(!aStart.equal(aEnd))
346 				{
347 					const double fExtendIS(getInnerExtend(getLeftLine(), true));
348 					const double fExtendIE(getInnerExtend(getRightLine(), false));
349 					double fExtendOS(0.0);
350 					double fExtendOE(0.0);
351 
352 					if(getBottomIsOutside())
353 					{
354 						if(getLeftIsOutside())
355 						{
356 							fExtendOS = getOuterExtend(getLeftLine());
357 						}
358 
359 						if(getRightIsOutside())
360 						{
361 							fExtendOE = getOuterExtend(getRightLine());
362 						}
363 					}
364 
365 					xRetval[nInsert++] = Primitive2DReference(new BorderLinePrimitive2D(
366 						aStart,
367 						aEnd,
368 						getChangedValue(getBottomLine().GetOutWidth(), getInTwips()),
369 						getChangedValue(getBottomLine().GetDistance(), getInTwips()),
370 						getChangedValue(getBottomLine().GetInWidth(), getInTwips()),
371 						fExtendIS * fTwipsToMM,
372 						fExtendIE * fTwipsToMM,
373 						fExtendOS * fTwipsToMM,
374 						fExtendOE * fTwipsToMM,
375 						true,
376 						getBottomIsOutside(),
377 						getBottomLine().GetColor().getBColor()));
378 				}
379 			}
380 
381 			if(!getRightLine().isEmpty())
382 			{
383 				// create right line from top to bottom
384 				const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(1.0, 0.0));
385 				const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 1.0));
386 
387 				if(!aStart.equal(aEnd))
388 				{
389 					const double fExtendIS(getInnerExtend(getTopLine(), false));
390 					const double fExtendIE(getInnerExtend(getBottomLine(), true));
391 					double fExtendOS(0.0);
392 					double fExtendOE(0.0);
393 
394 					if(getRightIsOutside())
395 					{
396 						if(getTopIsOutside())
397 						{
398 							fExtendOS = getOuterExtend(getTopLine());
399 						}
400 
401 						if(getBottomIsOutside())
402 						{
403 							fExtendOE = getOuterExtend(getBottomLine());
404 						}
405 					}
406 
407 					xRetval[nInsert++] = Primitive2DReference(new BorderLinePrimitive2D(
408 						aStart,
409 						aEnd,
410 						getChangedValue(getRightLine().GetOutWidth(), getInTwips()),
411 						getChangedValue(getRightLine().GetDistance(), getInTwips()),
412 						getChangedValue(getRightLine().GetInWidth(), getInTwips()),
413 						fExtendOS * fTwipsToMM,
414 						fExtendOE * fTwipsToMM,
415 						fExtendIS * fTwipsToMM,
416 						fExtendIE * fTwipsToMM,
417 						getRightIsOutside(),
418 						true,
419 						getRightLine().GetColor().getBColor()));
420 				}
421 			}
422 
423 			if(!getTopLine().isEmpty())
424 			{
425 				// create top line from left to right
426 				const basegfx::B2DPoint aStart(getTransform() * basegfx::B2DPoint(0.0, 0.0));
427 				const basegfx::B2DPoint aEnd(getTransform() * basegfx::B2DPoint(1.0, 0.0));
428 
429 				if(!aStart.equal(aEnd))
430 				{
431 					const double fExtendIS(getInnerExtend(getLeftLine(), true));
432 					const double fExtendIE(getInnerExtend(getRightLine(), false));
433 					double fExtendOS(0.0);
434 					double fExtendOE(0.0);
435 
436 					if(getTopIsOutside())
437 					{
438 						if(getLeftIsOutside())
439 						{
440 							fExtendOS = getOuterExtend(getLeftLine());
441 						}
442 
443 						if(getRightIsOutside())
444 						{
445 							fExtendOE = getOuterExtend(getRightLine());
446 						}
447 					}
448 
449 					xRetval[nInsert++] = Primitive2DReference(new BorderLinePrimitive2D(
450 						aStart,
451 						aEnd,
452 						getChangedValue(getTopLine().GetOutWidth(), getInTwips()),
453 						getChangedValue(getTopLine().GetDistance(), getInTwips()),
454 						getChangedValue(getTopLine().GetInWidth(), getInTwips()),
455 						fExtendOS * fTwipsToMM,
456 						fExtendOE * fTwipsToMM,
457 						fExtendIS * fTwipsToMM,
458 						fExtendIE * fTwipsToMM,
459 						getTopIsOutside(),
460 						true,
461 						getTopLine().GetColor().getBColor()));
462 				}
463 			}
464 
465 			xRetval.realloc(nInsert);
466 			return xRetval;
467 		}
468 
469 		bool SdrBorderlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
470 		{
471 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
472 			{
473 				const SdrBorderlinePrimitive2D& rCompare = (SdrBorderlinePrimitive2D&)rPrimitive;
474 
475 				return (getTransform() == rCompare.getTransform()
476 					&& getLeftLine() == rCompare.getLeftLine()
477 					&& getBottomLine() == rCompare.getBottomLine()
478 					&& getRightLine() == rCompare.getRightLine()
479 					&& getTopLine() == rCompare.getTopLine()
480 					&& getLeftIsOutside() == rCompare.getLeftIsOutside()
481 					&& getBottomIsOutside() == rCompare.getBottomIsOutside()
482 					&& getRightIsOutside() == rCompare.getRightIsOutside()
483 					&& getTopIsOutside() == rCompare.getTopIsOutside()
484 					&& getInTwips() == rCompare.getInTwips());
485 			}
486 
487 			return false;
488 		}
489 
490 		// provide unique ID
491 		ImplPrimitrive2DIDBlock(SdrBorderlinePrimitive2D, PRIMITIVE2D_ID_SDRBORDERLINEPRIMITIVE2D)
492 
493 	} // end of namespace primitive2d
494 } // end of namespace drawinglayer
495 
496 //////////////////////////////////////////////////////////////////////////////
497 
498 namespace sdr
499 {
500 	namespace contact
501 	{
502 		void impGetLine(SvxBorderLine& aLine, const sdr::table::TableLayouter& rLayouter, sal_Int32 nX, sal_Int32 nY, bool bHorizontal, sal_Int32 nColCount, sal_Int32 nRowCount, bool bIsRTL)
503 		{
504 			if(nX >= 0 && nX <= nColCount && nY >= 0 && nY <= nRowCount)
505 			{
506 				const SvxBorderLine* pLine = rLayouter.getBorderLine(nX, nY, bHorizontal);
507 
508 				if(pLine)
509 				{
510 					// copy line content
511 					aLine = *pLine;
512 
513 					// check for mirroring. This shall always be done when it is
514 					// not a top- or rightmost line
515 					bool bMirror(aLine.isDouble());
516 
517 					if(bMirror)
518 					{
519 						if(bHorizontal)
520 						{
521 							// mirror all bottom lines
522 							bMirror = (0 != nY);
523 						}
524 						else
525 						{
526 							// mirror all left lines
527 							bMirror = (bIsRTL ? 0 != nX : nX != nColCount);
528 						}
529 					}
530 
531 					if(bMirror)
532 					{
533 						aLine.SetOutWidth(pLine->GetInWidth());
534 						aLine.SetInWidth(pLine->GetOutWidth());
535 					}
536 
537 					return;
538 				}
539 			}
540 
541 			// no success, copy empty line
542 			const SvxBorderLine aEmptyLine;
543 			aLine = aEmptyLine;
544 		}
545 
546 		drawinglayer::primitive2d::Primitive2DSequence ViewContactOfTableObj::createViewIndependentPrimitive2DSequence() const
547         {
548 			const sdr::table::SdrTableObj& rTableObj = GetTableObj();
549             const uno::Reference< com::sun::star::table::XTable > xTable = rTableObj.getTable();
550 
551             if(xTable.is())
552             {
553                 // create primitive representation for table
554 	            drawinglayer::primitive2d::Primitive2DSequence xRetval;
555                 const sal_Int32 nRowCount(xTable->getRowCount());
556                 const sal_Int32 nColCount(xTable->getColumnCount());
557                 const sal_Int32 nAllCount(nRowCount * nColCount);
558 
559                 if(nAllCount)
560                 {
561 					const sdr::table::TableLayouter& rTableLayouter = rTableObj.getTableLayouter();
562 					const bool bIsRTL(com::sun::star::text::WritingMode_RL_TB == rTableObj.GetWritingMode());
563                 	sdr::table::CellPos aCellPos;
564 					sdr::table::CellRef xCurrentCell;
565 					basegfx::B2IRectangle aCellArea;
566 
567 		            // create range using the model data directly. This is in SdrTextObj::aRect which i will access using
568                     // GetGeoRect() to not trigger any calculations. It's the unrotated geometry.
569 		            const Rectangle& rObjectRectangle(rTableObj.GetGeoRect());
570 		            const basegfx::B2DRange aObjectRange(rObjectRectangle.Left(), rObjectRectangle.Top(), rObjectRectangle.Right(), rObjectRectangle.Bottom());
571 
572 					// for each cell we need potentially a cell primitive and a border primitive
573 					// (e.g. single cell). Prepare sequences and input counters
574 					drawinglayer::primitive2d::Primitive2DSequence xCellSequence(nAllCount);
575 					drawinglayer::primitive2d::Primitive2DSequence xBorderSequence(nAllCount);
576 					sal_uInt32 nCellInsert(0);
577 					sal_uInt32 nBorderInsert(0);
578 
579 					// variables for border lines
580 					SvxBorderLine aLeftLine;
581 					SvxBorderLine aBottomLine;
582 					SvxBorderLine aRightLine;
583 					SvxBorderLine aTopLine;
584 
585 					// create single primitives per cell
586 					for(aCellPos.mnRow = 0; aCellPos.mnRow < nRowCount; aCellPos.mnRow++)
587                     {
588 		                for(aCellPos.mnCol = 0; aCellPos.mnCol < nColCount; aCellPos.mnCol++)
589                         {
590 							xCurrentCell.set(dynamic_cast< sdr::table::Cell* >(xTable->getCellByPosition(aCellPos.mnCol, aCellPos.mnRow).get()));
591 
592 							if(xCurrentCell.is() && !xCurrentCell->isMerged())
593 							{
594 								if(rTableLayouter.getCellArea(aCellPos, aCellArea))
595 								{
596 									// create cell transformation matrix
597 									basegfx::B2DHomMatrix aCellMatrix;
598 									aCellMatrix.set(0, 0, (double)aCellArea.getWidth());
599 									aCellMatrix.set(1, 1, (double)aCellArea.getHeight());
600 									aCellMatrix.set(0, 2, (double)aCellArea.getMinX() + aObjectRange.getMinX());
601 									aCellMatrix.set(1, 2, (double)aCellArea.getMinY() + aObjectRange.getMinY());
602 
603 									// handle cell fillings and text
604 									const SfxItemSet& rCellItemSet = xCurrentCell->GetItemSet();
605 									const sal_uInt32 nTextIndex(nColCount * aCellPos.mnRow + aCellPos.mnCol);
606 									const SdrText* pSdrText = rTableObj.getText(nTextIndex);
607 									drawinglayer::attribute::SdrFillTextAttribute aAttribute;
608 
609 									if(pSdrText)
610 									{
611 										// #i101508# take cell's local text frame distances into account
612 										const sal_Int32 nLeft(xCurrentCell->GetTextLeftDistance());
613 										const sal_Int32 nRight(xCurrentCell->GetTextRightDistance());
614 										const sal_Int32 nUpper(xCurrentCell->GetTextUpperDistance());
615 										const sal_Int32 nLower(xCurrentCell->GetTextLowerDistance());
616 
617 										aAttribute = drawinglayer::primitive2d::createNewSdrFillTextAttribute(
618 											rCellItemSet,
619 											pSdrText,
620 											&nLeft,
621 											&nUpper,
622 											&nRight,
623 											&nLower);
624 									}
625 									else
626 									{
627 										aAttribute = drawinglayer::primitive2d::createNewSdrFillTextAttribute(
628 											rCellItemSet,
629 											pSdrText);
630 									}
631 
632                                     // always create cell primitives for BoundRect and HitTest
633 									{
634 										const drawinglayer::primitive2d::Primitive2DReference xCellReference(
635 											new drawinglayer::primitive2d::SdrCellPrimitive2D(
636 												aCellMatrix, aAttribute));
637 										xCellSequence[nCellInsert++] = xCellReference;
638 									}
639 
640 									// handle cell borders
641 									const sal_Int32 nX(bIsRTL ? nColCount - aCellPos.mnCol : aCellPos.mnCol);
642 									const sal_Int32 nY(aCellPos.mnRow);
643 
644 									// get access values for X,Y at the cell's end
645 									const sal_Int32 nXSpan(xCurrentCell->getColumnSpan());
646 									const sal_Int32 nYSpan(xCurrentCell->getRowSpan());
647 									const sal_Int32 nXRight(bIsRTL ? nX - nXSpan : nX + nXSpan);
648 									const sal_Int32 nYBottom(nY + nYSpan);
649 
650 									// get basic lines
651 									impGetLine(aLeftLine, rTableLayouter, nX, nY, false, nColCount, nRowCount, bIsRTL);
652 									impGetLine(aBottomLine, rTableLayouter, nX, nYBottom, true, nColCount, nRowCount, bIsRTL);
653 									impGetLine(aRightLine, rTableLayouter, nXRight, nY, false, nColCount, nRowCount, bIsRTL);
654 									impGetLine(aTopLine, rTableLayouter, nX, nY, true, nColCount, nRowCount, bIsRTL);
655 
656 									// create the primtive containing all data for one cell with borders
657 									xBorderSequence[nBorderInsert++] = drawinglayer::primitive2d::Primitive2DReference(
658 										new drawinglayer::primitive2d::SdrBorderlinePrimitive2D(
659 											aCellMatrix,
660 											aLeftLine,
661 											aBottomLine,
662 											aRightLine,
663 											aTopLine,
664 											bIsRTL ? nX == nColCount : 0 == nX,
665 											nRowCount == nYBottom,
666 											bIsRTL ? 0 == nXRight : nXRight == nColCount,
667 											0 == nY,
668 											true));
669 								}
670 							}
671                         }
672 					}
673 
674 					// no empty references; reallocate sequences by used count
675 					xCellSequence.realloc(nCellInsert);
676 					xBorderSequence.realloc(nBorderInsert);
677 
678 					// append to target. We want fillings and text first
679 					xRetval = xCellSequence;
680 					drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(xRetval, xBorderSequence);
681 				}
682 
683 				if(xRetval.hasElements())
684 				{
685 					// check and create evtl. shadow for created content
686 	           		const SfxItemSet& rObjectItemSet = rTableObj.GetMergedItemSet();
687 					const drawinglayer::attribute::SdrShadowAttribute aNewShadowAttribute(
688 						drawinglayer::primitive2d::createNewSdrShadowAttribute(rObjectItemSet));
689 
690 					if(!aNewShadowAttribute.isDefault())
691 					{
692 						xRetval = drawinglayer::primitive2d::createEmbeddedShadowPrimitive(xRetval, aNewShadowAttribute);
693 					}
694 				}
695 
696 				return xRetval;
697 			}
698 			else
699 			{
700 				// take unrotated snap rect (direct model data) for position and size
701 				const Rectangle& rRectangle = rTableObj.GetGeoRect();
702 				const basegfx::B2DRange aObjectRange(
703 					rRectangle.Left(), rRectangle.Top(),
704 					rRectangle.Right(), rRectangle.Bottom());
705 
706 				// create object matrix
707 				const GeoStat& rGeoStat(rTableObj.GetGeoStat());
708 				const double fShearX(rGeoStat.nShearWink ? tan((36000 - rGeoStat.nShearWink) * F_PI18000) : 0.0);
709 				const double fRotate(rGeoStat.nDrehWink ? (36000 - rGeoStat.nDrehWink) * F_PI18000 : 0.0);
710 				const basegfx::B2DHomMatrix aObjectMatrix(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
711 					aObjectRange.getWidth(), aObjectRange.getHeight(), fShearX, fRotate,
712 					aObjectRange.getMinX(), aObjectRange.getMinY()));
713 
714 				// credate an invisible outline for the cases where no visible content exists
715 	            const drawinglayer::primitive2d::Primitive2DReference xReference(
716 					drawinglayer::primitive2d::createHiddenGeometryPrimitives2D(
717 						false,
718 						aObjectMatrix));
719 
720 				return drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
721 			}
722         }
723 
724 		ViewContactOfTableObj::ViewContactOfTableObj(::sdr::table::SdrTableObj& rTableObj)
725 		:	ViewContactOfSdrObj(rTableObj)
726 		{
727 		}
728 
729 		ViewContactOfTableObj::~ViewContactOfTableObj()
730 		{
731 		}
732 	} // end of namespace contact
733 } // end of namespace sdr
734 
735 //////////////////////////////////////////////////////////////////////////////
736 // eof
737