xref: /trunk/main/svx/source/table/viewcontactoftableobj.cxx (revision a893be29343ee97512d484e6e8fefa91df2b44cb)
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:
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
82             const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
83             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 
92         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 
137         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:
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
210             const basegfx::B2DHomMatrix& getTransform() const { return maTransform; }
211             const SvxBorderLine& getLeftLine() const { return maLeftLine; }
212             const SvxBorderLine& getBottomLine() const { return maBottomLine; }
213             const SvxBorderLine& getRightLine() const { return maRightLine; }
214             const SvxBorderLine& getTopLine() const { return maTopLine; }
215             bool getLeftIsOutside() const { return mbLeftIsOutside; }
216             bool getBottomIsOutside() const { return mbBottomIsOutside; }
217             bool getRightIsOutside() const { return mbRightIsOutside; }
218             bool getTopIsOutside() const { return mbTopIsOutside; }
219             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 
228         sal_uInt16 getBorderLineOutWidth(const SvxBorderLine& rLineA)
229         {
230             return (1 == rLineA.GetOutWidth() ? 0 : rLineA.GetOutWidth());
231         }
232 
233         sal_uInt16 getBorderLineDistance(const SvxBorderLine& rLineA)
234         {
235             return (1 == rLineA.GetDistance() ? 0 : rLineA.GetDistance());
236         }
237 
238         sal_uInt16 getBorderLineInWidth(const SvxBorderLine& rLineA)
239         {
240             return (1 == rLineA.GetInWidth() ? 0 : rLineA.GetInWidth());
241         }
242 
243         sal_uInt16 getBorderLineWidth(const SvxBorderLine& rLineA)
244         {
245             return getBorderLineOutWidth(rLineA) + getBorderLineDistance(rLineA) + getBorderLineInWidth(rLineA);
246         }
247 
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 
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 
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 
289         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 
467         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     {
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 
544         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 
722         ViewContactOfTableObj::ViewContactOfTableObj(::sdr::table::SdrTableObj& rTableObj)
723         :   ViewContactOfSdrObj(rTableObj)
724         {
725         }
726 
727         ViewContactOfTableObj::~ViewContactOfTableObj()
728         {
729         }
730     } // end of namespace contact
731 } // end of namespace sdr
732 
733 //////////////////////////////////////////////////////////////////////////////
734 // eof
735