xref: /trunk/main/svx/source/sdr/primitive2d/sdrtextprimitive2d.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "precompiled_svx.hxx"
29 #include <svx/sdr/primitive2d/sdrtextprimitive2d.hxx>
30 #include <svx/svdotext.hxx>
31 #include <basegfx/color/bcolor.hxx>
32 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
33 #include <drawinglayer/primitive2d/texthierarchyprimitive2d.hxx>
34 #include <editeng/outlobj.hxx>
35 #include <editeng/editobj.hxx>
36 #include <editeng/flditem.hxx>
37 #include <drawinglayer/geometry/viewinformation2d.hxx>
38 #include <svx/unoapi.hxx>
39 #include <svx/svdpage.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdoutl.hxx>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 
44 //////////////////////////////////////////////////////////////////////////////
45 
46 using namespace com::sun::star;
47 
48 //////////////////////////////////////////////////////////////////////////////
49 
50 namespace
51 {
52     sal_Int16 getPageNumber(const uno::Reference< drawing::XDrawPage >& rxDrawPage)
53     {
54         sal_Int16 nRetval(0);
55         uno::Reference< beans::XPropertySet > xSet(rxDrawPage, uno::UNO_QUERY);
56 
57         if (xSet.is())
58         {
59             try
60             {
61                 const uno::Any aNumber(xSet->getPropertyValue(::rtl::OUString::createFromAscii("Number")));
62                 aNumber >>= nRetval;
63             }
64             catch(const uno::Exception&)
65             {
66                 OSL_ASSERT(false);
67             }
68         }
69 
70         return nRetval;
71     }
72 
73     sal_Int16 getPageCount(const uno::Reference< drawing::XDrawPage >& rxDrawPage)
74     {
75         sal_Int16 nRetval(0);
76         SdrPage* pPage = GetSdrPageFromXDrawPage(rxDrawPage);
77 
78         if(pPage && pPage->GetModel())
79         {
80             if( (pPage->GetPageNum() == 0) && !pPage->IsMasterPage() )
81             {
82                 // handout page!
83                 return pPage->GetModel()->getHandoutPageCount();
84             }
85             else
86             {
87                 const sal_uInt16 nPageCount(pPage->GetModel()->GetPageCount());
88                 nRetval = ((sal_Int16)nPageCount - 1) / 2;
89             }
90         }
91 
92         return nRetval;
93     }
94 } // end of anonymous namespace
95 
96 //////////////////////////////////////////////////////////////////////////////
97 
98 namespace drawinglayer
99 {
100     namespace primitive2d
101     {
102         // support for XTEXT_PAINTSHAPE_BEGIN/XTEXT_PAINTSHAPE_END Metafile comments
103         // for slideshow. This uses TextHierarchyBlockPrimitive2D to mark a text block.
104         // ATM there is only one text block per SdrObject, this may get more in the future
105         Primitive2DSequence SdrTextPrimitive2D::encapsulateWithTextHierarchyBlockPrimitive2D(const Primitive2DSequence& rCandidate) const
106         {
107             Primitive2DReference xReference(new TextHierarchyBlockPrimitive2D(rCandidate));
108             Primitive2DSequence xRetval(&xReference, 1);
109 
110             return xRetval;
111         }
112 
113         SdrTextPrimitive2D::SdrTextPrimitive2D(
114             const SdrText* pSdrText,
115             const OutlinerParaObject& rOutlinerParaObject)
116         :   BufferedDecompositionPrimitive2D(),
117             mrSdrText(const_cast< SdrText* >(pSdrText)),
118             maOutlinerParaObject(rOutlinerParaObject),
119             mxLastVisualizingPage(),
120             mnLastPageNumber(0),
121             mnLastPageCount(0),
122             maLastTextBackgroundColor(),
123             mbContainsPageField(false),
124             mbContainsPageCountField(false),
125             mbContainsOtherFields(false)
126         {
127             const EditTextObject& rETO = maOutlinerParaObject.GetTextObject();
128 
129             mbContainsPageField = rETO.HasField(SvxPageField::StaticType());
130             mbContainsPageCountField = rETO.HasField(SvxPagesField::StaticType());
131             mbContainsOtherFields = rETO.HasField(SvxHeaderField::StaticType())
132                 || rETO.HasField(SvxFooterField::StaticType())
133                 || rETO.HasField(SvxDateTimeField::StaticType())
134                 || rETO.HasField(SvxAuthorField::StaticType());
135         }
136 
137         bool SdrTextPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
138         {
139             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
140             {
141                 const SdrTextPrimitive2D& rCompare = (SdrTextPrimitive2D&)rPrimitive;
142 
143                 return (
144 
145                     // compare OPO and content, but not WrongList
146                     getOutlinerParaObject() == rCompare.getOutlinerParaObject()
147 
148                     // also compare WrongList (not-persistent data, but visualized)
149                     && getOutlinerParaObject().isWrongListEqual(rCompare.getOutlinerParaObject()));
150             }
151 
152             return false;
153         }
154 
155         Primitive2DSequence SdrTextPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
156         {
157             uno::Reference< drawing::XDrawPage > xCurrentlyVisualizingPage;
158             bool bCurrentlyVisualizingPageIsSet(false);
159             Color aNewTextBackgroundColor;
160             bool bNewTextBackgroundColorIsSet(false);
161             sal_Int16 nCurrentlyValidPageNumber(0);
162             sal_Int16 nCurrentlyValidPageCount(0);
163 
164             if(getBuffered2DDecomposition().hasElements())
165             {
166                 bool bDoDelete(false);
167 
168                 // check visualized page
169                 if(mbContainsPageField || mbContainsPageCountField || mbContainsOtherFields)
170                 {
171                     // get visualized page and remember
172                     xCurrentlyVisualizingPage = rViewInformation.getVisualizedPage();
173                     bCurrentlyVisualizingPageIsSet = true;
174 
175                     if(xCurrentlyVisualizingPage != mxLastVisualizingPage)
176                     {
177                         bDoDelete = true;
178                     }
179 
180                     // #i98870# check visualized PageNumber
181                     if(!bDoDelete && mbContainsPageField)
182                     {
183                         nCurrentlyValidPageNumber = getPageNumber(xCurrentlyVisualizingPage);
184 
185                         if(nCurrentlyValidPageNumber != mnLastPageNumber)
186                         {
187                             bDoDelete = true;
188                         }
189                     }
190 
191                     // #i98870# check visualized PageCount, too
192                     if(!bDoDelete && mbContainsPageCountField)
193                     {
194                         nCurrentlyValidPageCount = getPageCount(xCurrentlyVisualizingPage);
195 
196                         if(nCurrentlyValidPageCount != mnLastPageCount)
197                         {
198                             bDoDelete = true;
199                         }
200                     }
201                 }
202 
203                 // #i101443#  check change of TextBackgroundolor
204                 if(!bDoDelete && getSdrText() && getSdrText()->GetModel())
205                 {
206                     SdrOutliner& rDrawOutliner = getSdrText()->GetModel()->GetDrawOutliner(0);
207                     aNewTextBackgroundColor = rDrawOutliner.GetBackgroundColor();
208                     bNewTextBackgroundColorIsSet = true;
209 
210                     if(aNewTextBackgroundColor != maLastTextBackgroundColor)
211                     {
212                         bDoDelete = true;
213                     }
214                 }
215 
216                 if(bDoDelete)
217                 {
218                     const_cast< SdrTextPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
219                 }
220             }
221 
222             if(!getBuffered2DDecomposition().hasElements())
223             {
224                 if(!bCurrentlyVisualizingPageIsSet && mbContainsPageField)
225                 {
226                     xCurrentlyVisualizingPage = rViewInformation.getVisualizedPage();
227                 }
228 
229                 if(!nCurrentlyValidPageNumber && mbContainsPageField)
230                 {
231                     nCurrentlyValidPageNumber = getPageNumber(xCurrentlyVisualizingPage);
232                 }
233 
234                 if(!nCurrentlyValidPageCount && mbContainsPageCountField)
235                 {
236                     nCurrentlyValidPageCount = getPageCount(xCurrentlyVisualizingPage);
237                 }
238 
239                 if(!bNewTextBackgroundColorIsSet && getSdrText() && getSdrText()->GetModel())
240                 {
241                     SdrOutliner& rDrawOutliner = getSdrText()->GetModel()->GetDrawOutliner(0);
242                     aNewTextBackgroundColor = rDrawOutliner.GetBackgroundColor();
243                 }
244 
245                 const_cast< SdrTextPrimitive2D* >(this)->mxLastVisualizingPage = xCurrentlyVisualizingPage;
246                 const_cast< SdrTextPrimitive2D* >(this)->mnLastPageNumber = nCurrentlyValidPageNumber;
247                 const_cast< SdrTextPrimitive2D* >(this)->mnLastPageCount = nCurrentlyValidPageCount;
248                 const_cast< SdrTextPrimitive2D* >(this)->maLastTextBackgroundColor = aNewTextBackgroundColor;
249             }
250 
251             // call parent
252             return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
253         }
254     } // end of namespace primitive2d
255 } // end of namespace drawinglayer
256 
257 //////////////////////////////////////////////////////////////////////////////
258 
259 namespace drawinglayer
260 {
261     namespace primitive2d
262     {
263         Primitive2DSequence SdrContourTextPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const
264         {
265             Primitive2DSequence aRetval;
266             getSdrText()->GetObject().impDecomposeContourTextPrimitive(aRetval, *this, aViewInformation);
267 
268             return encapsulateWithTextHierarchyBlockPrimitive2D(aRetval);
269         }
270 
271         SdrContourTextPrimitive2D::SdrContourTextPrimitive2D(
272             const SdrText* pSdrText,
273             const OutlinerParaObject& rOutlinerParaObject,
274             const basegfx::B2DPolyPolygon& rUnitPolyPolygon,
275             const basegfx::B2DHomMatrix& rObjectTransform)
276         :   SdrTextPrimitive2D(pSdrText, rOutlinerParaObject),
277             maUnitPolyPolygon(rUnitPolyPolygon),
278             maObjectTransform(rObjectTransform)
279         {
280         }
281 
282         bool SdrContourTextPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
283         {
284             if(SdrTextPrimitive2D::operator==(rPrimitive))
285             {
286                 const SdrContourTextPrimitive2D& rCompare = (SdrContourTextPrimitive2D&)rPrimitive;
287 
288                 return (getUnitPolyPolygon() == rCompare.getUnitPolyPolygon()
289                     && getObjectTransform() == rCompare.getObjectTransform());
290             }
291 
292             return false;
293         }
294 
295         SdrTextPrimitive2D* SdrContourTextPrimitive2D::createTransformedClone(const basegfx::B2DHomMatrix& rTransform) const
296         {
297             return new SdrContourTextPrimitive2D(
298                 getSdrText(),
299                 getOutlinerParaObject(),
300                 getUnitPolyPolygon(),
301                 rTransform * getObjectTransform());
302         }
303 
304         // provide unique ID
305         ImplPrimitrive2DIDBlock(SdrContourTextPrimitive2D, PRIMITIVE2D_ID_SDRCONTOURTEXTPRIMITIVE2D)
306 
307     } // end of namespace primitive2d
308 } // end of namespace drawinglayer
309 
310 //////////////////////////////////////////////////////////////////////////////
311 
312 namespace drawinglayer
313 {
314     namespace primitive2d
315     {
316         Primitive2DSequence SdrPathTextPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const
317         {
318             Primitive2DSequence aRetval;
319             getSdrText()->GetObject().impDecomposePathTextPrimitive(aRetval, *this, aViewInformation);
320 
321             return encapsulateWithTextHierarchyBlockPrimitive2D(aRetval);
322         }
323 
324         SdrPathTextPrimitive2D::SdrPathTextPrimitive2D(
325             const SdrText* pSdrText,
326             const OutlinerParaObject& rOutlinerParaObject,
327             const basegfx::B2DPolyPolygon& rPathPolyPolygon,
328             const attribute::SdrFormTextAttribute& rSdrFormTextAttribute)
329         :   SdrTextPrimitive2D(pSdrText, rOutlinerParaObject),
330             maPathPolyPolygon(rPathPolyPolygon),
331             maSdrFormTextAttribute(rSdrFormTextAttribute)
332         {
333         }
334 
335         bool SdrPathTextPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
336         {
337             if(SdrTextPrimitive2D::operator==(rPrimitive))
338             {
339                 const SdrPathTextPrimitive2D& rCompare = (SdrPathTextPrimitive2D&)rPrimitive;
340 
341                 return (getPathPolyPolygon() == rCompare.getPathPolyPolygon()
342                     && getSdrFormTextAttribute() == rCompare.getSdrFormTextAttribute());
343             }
344 
345             return false;
346         }
347 
348         SdrTextPrimitive2D* SdrPathTextPrimitive2D::createTransformedClone(const basegfx::B2DHomMatrix& rTransform) const
349         {
350             basegfx::B2DPolyPolygon aNewPolyPolygon(getPathPolyPolygon());
351             aNewPolyPolygon.transform(rTransform);
352 
353             return new SdrPathTextPrimitive2D(
354                 getSdrText(),
355                 getOutlinerParaObject(),
356                 aNewPolyPolygon,
357                 getSdrFormTextAttribute());
358         }
359 
360         // provide unique ID
361         ImplPrimitrive2DIDBlock(SdrPathTextPrimitive2D, PRIMITIVE2D_ID_SDRPATHTEXTPRIMITIVE2D)
362 
363     } // end of namespace primitive2d
364 } // end of namespace drawinglayer
365 
366 //////////////////////////////////////////////////////////////////////////////
367 
368 namespace drawinglayer
369 {
370     namespace primitive2d
371     {
372         Primitive2DSequence SdrBlockTextPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const
373         {
374             Primitive2DSequence aRetval;
375             getSdrText()->GetObject().impDecomposeBlockTextPrimitive(aRetval, *this, aViewInformation);
376 
377             return encapsulateWithTextHierarchyBlockPrimitive2D(aRetval);
378         }
379 
380         SdrBlockTextPrimitive2D::SdrBlockTextPrimitive2D(
381             const SdrText* pSdrText,
382             const OutlinerParaObject& rOutlinerParaObject,
383             const basegfx::B2DHomMatrix& rTextRangeTransform,
384             SdrTextHorzAdjust aSdrTextHorzAdjust,
385             SdrTextVertAdjust aSdrTextVertAdjust,
386             bool bFixedCellHeight,
387             bool bUnlimitedPage,
388             bool bCellText,
389             bool bWordWrap,
390             bool bClipOnBounds)
391         :   SdrTextPrimitive2D(pSdrText, rOutlinerParaObject),
392             maTextRangeTransform(rTextRangeTransform),
393             maSdrTextHorzAdjust(aSdrTextHorzAdjust),
394             maSdrTextVertAdjust(aSdrTextVertAdjust),
395             mbFixedCellHeight(bFixedCellHeight),
396             mbUnlimitedPage(bUnlimitedPage),
397             mbCellText(bCellText),
398             mbWordWrap(bWordWrap),
399             mbClipOnBounds(bClipOnBounds)
400         {
401         }
402 
403         bool SdrBlockTextPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
404         {
405             if(SdrTextPrimitive2D::operator==(rPrimitive))
406             {
407                 const SdrBlockTextPrimitive2D& rCompare = (SdrBlockTextPrimitive2D&)rPrimitive;
408 
409                 return (getTextRangeTransform() == rCompare.getTextRangeTransform()
410                     && getSdrTextHorzAdjust() == rCompare.getSdrTextHorzAdjust()
411                     && getSdrTextVertAdjust() == rCompare.getSdrTextVertAdjust()
412                     && isFixedCellHeight() == rCompare.isFixedCellHeight()
413                     && getUnlimitedPage() == rCompare.getUnlimitedPage()
414                     && getCellText() == rCompare.getCellText()
415                     && getWordWrap() == rCompare.getWordWrap()
416                     && getClipOnBounds() == rCompare.getClipOnBounds());
417             }
418 
419             return false;
420         }
421 
422         SdrTextPrimitive2D* SdrBlockTextPrimitive2D::createTransformedClone(const basegfx::B2DHomMatrix& rTransform) const
423         {
424             return new SdrBlockTextPrimitive2D(
425                 getSdrText(),
426                 getOutlinerParaObject(),
427                 rTransform * getTextRangeTransform(),
428                 getSdrTextHorzAdjust(),
429                 getSdrTextVertAdjust(),
430                 isFixedCellHeight(),
431                 getUnlimitedPage(),
432                 getCellText(),
433                 getWordWrap(),
434                 getClipOnBounds());
435         }
436 
437         // provide unique ID
438         ImplPrimitrive2DIDBlock(SdrBlockTextPrimitive2D, PRIMITIVE2D_ID_SDRBLOCKTEXTPRIMITIVE2D)
439 
440     } // end of namespace primitive2d
441 } // end of namespace drawinglayer
442 
443 //////////////////////////////////////////////////////////////////////////////
444 
445 namespace drawinglayer
446 {
447     namespace primitive2d
448     {
449         Primitive2DSequence SdrStretchTextPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& aViewInformation) const
450         {
451             Primitive2DSequence aRetval;
452             getSdrText()->GetObject().impDecomposeStretchTextPrimitive(aRetval, *this, aViewInformation);
453 
454             return encapsulateWithTextHierarchyBlockPrimitive2D(aRetval);
455         }
456 
457         SdrStretchTextPrimitive2D::SdrStretchTextPrimitive2D(
458             const SdrText* pSdrText,
459             const OutlinerParaObject& rOutlinerParaObject,
460             const basegfx::B2DHomMatrix& rTextRangeTransform,
461             bool bFixedCellHeight)
462         :   SdrTextPrimitive2D(pSdrText, rOutlinerParaObject),
463             maTextRangeTransform(rTextRangeTransform),
464             mbFixedCellHeight(bFixedCellHeight)
465         {
466         }
467 
468         bool SdrStretchTextPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
469         {
470             if(SdrTextPrimitive2D::operator==(rPrimitive))
471             {
472                 const SdrStretchTextPrimitive2D& rCompare = (SdrStretchTextPrimitive2D&)rPrimitive;
473 
474                 return (getTextRangeTransform() == rCompare.getTextRangeTransform()
475                     && isFixedCellHeight() == rCompare.isFixedCellHeight());
476             }
477 
478             return false;
479         }
480 
481         SdrTextPrimitive2D* SdrStretchTextPrimitive2D::createTransformedClone(const basegfx::B2DHomMatrix& rTransform) const
482         {
483             return new SdrStretchTextPrimitive2D(
484                 getSdrText(),
485                 getOutlinerParaObject(),
486                 rTransform * getTextRangeTransform(),
487                 isFixedCellHeight());
488         }
489 
490         // provide unique ID
491         ImplPrimitrive2DIDBlock(SdrStretchTextPrimitive2D, PRIMITIVE2D_ID_SDRSTRETCHTEXTPRIMITIVE2D)
492 
493     } // end of namespace primitive2d
494 } // end of namespace drawinglayer
495 
496 //////////////////////////////////////////////////////////////////////////////
497 // eof
498