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