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