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