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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_drawinglayer.hxx"
30 
31 #include <drawinglayer/geometry/viewinformation2d.hxx>
32 #include <basegfx/matrix/b2dhommatrix.hxx>
33 #include <basegfx/range/b2drange.hxx>
34 #include <osl/mutex.hxx>
35 #include <basegfx/tools/canvastools.hxx>
36 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
37 #include <com/sun/star/geometry/RealRectangle2D.hpp>
38 
39 //////////////////////////////////////////////////////////////////////////////
40 
41 using namespace com::sun::star;
42 
43 //////////////////////////////////////////////////////////////////////////////
44 
45 namespace drawinglayer
46 {
47 	namespace geometry
48 	{
49 		class ImpViewInformation2D
50 		{
51 		private:
52 			// ViewInformation2D implementation can change refcount, so we have only
53 			// two memory regions for pairs of ViewInformation2D/ImpViewInformation2D
54 			friend class ::drawinglayer::geometry::ViewInformation2D;
55 
56 			// the refcounter. 0 means exclusively used
57 			sal_uInt32									mnRefCount;
58 
59 		protected:
60             // the object transformation
61 			basegfx::B2DHomMatrix						maObjectTransformation;
62 
63             // the view transformation
64 			basegfx::B2DHomMatrix						maViewTransformation;
65 
66             // the ObjectToView and it's inverse, both on demand from ObjectTransformation
67             // and ViewTransformation
68 			basegfx::B2DHomMatrix						maObjectToViewTransformation;
69 			basegfx::B2DHomMatrix						maInverseObjectToViewTransformation;
70 
71             // the visible range and the on-demand one in ViewCoordinates
72 			basegfx::B2DRange							maViewport;
73 			basegfx::B2DRange							maDiscreteViewport;
74 
75 			// the DrawPage which is target of visualisation. This is needed e.g. for
76 			// the view-dependent decomposition of PageNumber TextFields.
77             // This parameter is buffered here, but mainly resides in mxExtendedInformation,
78             // so it will be interpreted, but held there. It will also not be added
79             // to mxExtendedInformation in impFillViewInformationFromContent (it's there already)
80 			uno::Reference< drawing::XDrawPage >		mxVisualizedPage;
81 
82 			// the point in time
83 			double										mfViewTime;
84 
85             // bitfield
86             bool                                        mbReducedDisplayQuality : 1;
87 
88 			// the complete PropertyValue representation (if already created)
89 			uno::Sequence< beans::PropertyValue >		mxViewInformation;
90 
91 			// the extra PropertyValues; not represented by ViewTransformation,
92 			// Viewport, VisualizedPage or ViewTime
93 			uno::Sequence< beans::PropertyValue >		mxExtendedInformation;
94 
95 			// the local UNO API strings
96 			const ::rtl::OUString& getNamePropertyObjectTransformation()
97 			{
98 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation"));
99 				return s_sNameProperty;
100 			}
101 
102 			const ::rtl::OUString& getNamePropertyViewTransformation()
103 			{
104 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ViewTransformation"));
105 				return s_sNameProperty;
106 			}
107 
108 			const ::rtl::OUString& getNamePropertyViewport()
109 			{
110 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Viewport"));
111 				return s_sNameProperty;
112 			}
113 
114 			const ::rtl::OUString& getNamePropertyTime()
115 			{
116 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Time"));
117 				return s_sNameProperty;
118 			}
119 
120 			const ::rtl::OUString& getNamePropertyVisualizedPage()
121 			{
122 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("VisualizedPage"));
123 				return s_sNameProperty;
124 			}
125 
126 			const ::rtl::OUString& getNamePropertyReducedDisplayQuality()
127 			{
128 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ReducedDisplayQuality"));
129 				return s_sNameProperty;
130 			}
131 
132 			void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters)
133 			{
134 				if(rViewParameters.hasElements())
135 				{
136 					const sal_Int32 nCount(rViewParameters.getLength());
137 					sal_Int32 nExtendedInsert(0);
138 
139 					// prepare extended information for filtering. Maximum size is nCount
140 					mxExtendedInformation.realloc(nCount);
141 
142 					for(sal_Int32 a(0); a < nCount; a++)
143 					{
144 						const beans::PropertyValue& rProp = rViewParameters[a];
145 
146 						if(rProp.Name == getNamePropertyReducedDisplayQuality())
147 						{
148                             // extra information; add to filtered information
149 							mxExtendedInformation[nExtendedInsert++] = rProp;
150 
151                             // for performance reasons, also cache content locally
152                             sal_Bool bSalBool(false);
153 							rProp.Value >>= bSalBool;
154                             mbReducedDisplayQuality = bSalBool;
155 						}
156 						else if(rProp.Name == getNamePropertyObjectTransformation())
157 						{
158 							com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
159 							rProp.Value >>= aAffineMatrix2D;
160 							basegfx::unotools::homMatrixFromAffineMatrix(maObjectTransformation, aAffineMatrix2D);
161 						}
162 						else if(rProp.Name == getNamePropertyViewTransformation())
163 						{
164 							com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
165 							rProp.Value >>= aAffineMatrix2D;
166 							basegfx::unotools::homMatrixFromAffineMatrix(maViewTransformation, aAffineMatrix2D);
167 						}
168 						else if(rProp.Name == getNamePropertyViewport())
169 						{
170 							com::sun::star::geometry::RealRectangle2D aViewport;
171 							rProp.Value >>= aViewport;
172 							maViewport = basegfx::unotools::b2DRectangleFromRealRectangle2D(aViewport);
173 						}
174 						else if(rProp.Name == getNamePropertyTime())
175 						{
176 							rProp.Value >>= mfViewTime;
177 						}
178 						else if(rProp.Name == getNamePropertyVisualizedPage())
179 						{
180 							rProp.Value >>= mxVisualizedPage;
181 						}
182 						else
183 						{
184 							// extra information; add to filtered information
185 							mxExtendedInformation[nExtendedInsert++] = rProp;
186 						}
187 					}
188 
189 					// extra information size is now known; realloc to final size
190 					mxExtendedInformation.realloc(nExtendedInsert);
191 				}
192 			}
193 
194 			void impFillViewInformationFromContent()
195 			{
196 				uno::Sequence< beans::PropertyValue > xRetval;
197 				const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
198 				const bool bViewTransformationUsed(!maViewTransformation.isIdentity());
199 				const bool bViewportUsed(!maViewport.isEmpty());
200 				const bool bTimeUsed(0.0 < mfViewTime);
201 				const bool bVisualizedPageUsed(mxVisualizedPage.is());
202                 const bool bReducedDisplayQualityUsed(true == mbReducedDisplayQuality);
203 				const bool bExtraInformation(mxExtendedInformation.hasElements());
204 				sal_uInt32 nIndex(0);
205 				const sal_uInt32 nCount(
206 					(bObjectTransformationUsed ? 1 : 0) +
207 					(bViewTransformationUsed ? 1 : 0) +
208 					(bViewportUsed ? 1 : 0) +
209 					(bTimeUsed ? 1 : 0) +
210 					(bVisualizedPageUsed ? 1 : 0) +
211                     (bReducedDisplayQualityUsed ? 1 : 0) +
212 					(bExtraInformation ? mxExtendedInformation.getLength() : 0));
213 
214 				mxViewInformation.realloc(nCount);
215 
216 				if(bObjectTransformationUsed)
217 				{
218 					com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
219 					basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maObjectTransformation);
220 					mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation();
221 					mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
222 					nIndex++;
223 				}
224 
225 				if(bViewTransformationUsed)
226 				{
227 					com::sun::star::geometry::AffineMatrix2D aAffineMatrix2D;
228 					basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maViewTransformation);
229 					mxViewInformation[nIndex].Name = getNamePropertyViewTransformation();
230 					mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
231 					nIndex++;
232 				}
233 
234 				if(bViewportUsed)
235 				{
236 					const com::sun::star::geometry::RealRectangle2D aViewport(basegfx::unotools::rectangle2DFromB2DRectangle(maViewport));
237 					mxViewInformation[nIndex].Name = getNamePropertyViewport();
238 					mxViewInformation[nIndex].Value <<= aViewport;
239 					nIndex++;
240 				}
241 
242 				if(bTimeUsed)
243 				{
244 					mxViewInformation[nIndex].Name = getNamePropertyTime();
245 					mxViewInformation[nIndex].Value <<= mfViewTime;
246 					nIndex++;
247 				}
248 
249 				if(bVisualizedPageUsed)
250 				{
251 					mxViewInformation[nIndex].Name = getNamePropertyVisualizedPage();
252 					mxViewInformation[nIndex].Value <<= mxVisualizedPage;
253 					nIndex++;
254 				}
255 
256 				if(bExtraInformation)
257 				{
258 					const sal_Int32 nExtra(mxExtendedInformation.getLength());
259 
260 					for(sal_Int32 a(0); a < nExtra; a++)
261 					{
262 						mxViewInformation[nIndex++] = mxExtendedInformation[a];
263 					}
264 				}
265 			}
266 
267 		public:
268 			ImpViewInformation2D(
269 				const basegfx::B2DHomMatrix& rObjectTransformation,
270 				const basegfx::B2DHomMatrix& rViewTransformation,
271 				const basegfx::B2DRange& rViewport,
272 				const uno::Reference< drawing::XDrawPage >& rxDrawPage,
273 				double fViewTime,
274 				const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
275 			:	mnRefCount(0),
276 				maObjectTransformation(rObjectTransformation),
277 				maViewTransformation(rViewTransformation),
278                 maObjectToViewTransformation(),
279                 maInverseObjectToViewTransformation(),
280 				maViewport(rViewport),
281 				maDiscreteViewport(),
282 				mxVisualizedPage(rxDrawPage),
283 				mfViewTime(fViewTime),
284                 mbReducedDisplayQuality(false),
285 				mxViewInformation(),
286 				mxExtendedInformation()
287 			{
288 				impInterpretPropertyValues(rExtendedParameters);
289 			}
290 
291 			ImpViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
292 			:	mnRefCount(0),
293 				maObjectTransformation(),
294 				maViewTransformation(),
295                 maObjectToViewTransformation(),
296                 maInverseObjectToViewTransformation(),
297 				maViewport(),
298 				maDiscreteViewport(),
299 				mxVisualizedPage(),
300 				mfViewTime(),
301                 mbReducedDisplayQuality(false),
302 				mxViewInformation(rViewParameters),
303 				mxExtendedInformation()
304 			{
305 				impInterpretPropertyValues(rViewParameters);
306 			}
307 
308 			ImpViewInformation2D()
309 			:	mnRefCount(0),
310 				maObjectTransformation(),
311 				maViewTransformation(),
312                 maObjectToViewTransformation(),
313                 maInverseObjectToViewTransformation(),
314 				maViewport(),
315 				maDiscreteViewport(),
316 				mxVisualizedPage(),
317 				mfViewTime(),
318                 mbReducedDisplayQuality(false),
319 				mxViewInformation(),
320 				mxExtendedInformation()
321 			{
322 			}
323 
324 			const basegfx::B2DHomMatrix& getObjectTransformation() const
325             {
326                 return maObjectTransformation;
327             }
328 
329 			const basegfx::B2DHomMatrix& getViewTransformation() const
330             {
331                 return maViewTransformation;
332             }
333 
334 			const basegfx::B2DRange& getViewport() const
335             {
336                 return maViewport;
337             }
338 
339 			const basegfx::B2DRange& getDiscreteViewport() const
340 			{
341 			    ::osl::Mutex m_mutex;
342 
343 				if(maDiscreteViewport.isEmpty() && !maViewport.isEmpty())
344 				{
345 					basegfx::B2DRange aDiscreteViewport(maViewport);
346 					aDiscreteViewport.transform(getViewTransformation());
347 					const_cast< ImpViewInformation2D* >(this)->maDiscreteViewport = aDiscreteViewport;
348 				}
349 
350 				return maDiscreteViewport;
351 			}
352 
353     		const basegfx::B2DHomMatrix& getObjectToViewTransformation() const
354             {
355 			    ::osl::Mutex m_mutex;
356 
357 				if(maObjectToViewTransformation.isIdentity() &&
358                     (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity()))
359 				{
360     				basegfx::B2DHomMatrix aObjectToView(maViewTransformation * maObjectTransformation);
361 					const_cast< ImpViewInformation2D* >(this)->maObjectToViewTransformation = aObjectToView;
362 				}
363 
364 				return maObjectToViewTransformation;
365             }
366 
367     		const basegfx::B2DHomMatrix& getInverseObjectToViewTransformation() const
368             {
369 			    ::osl::Mutex m_mutex;
370 
371 				if(maInverseObjectToViewTransformation.isIdentity() &&
372                     (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity()))
373 				{
374     				basegfx::B2DHomMatrix aInverseObjectToView(maViewTransformation * maObjectTransformation);
375                     aInverseObjectToView.invert();
376 					const_cast< ImpViewInformation2D* >(this)->maInverseObjectToViewTransformation = aInverseObjectToView;
377 				}
378 
379 				return maInverseObjectToViewTransformation;
380             }
381 
382 			double getViewTime() const
383             {
384                 return mfViewTime;
385             }
386 
387 			const uno::Reference< drawing::XDrawPage >& getVisualizedPage() const
388 			{
389 				return mxVisualizedPage;
390 			}
391 
392             bool getReducedDisplayQuality() const
393             {
394                 return mbReducedDisplayQuality;
395             }
396 
397 			const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const
398 			{
399 				if(!mxViewInformation.hasElements())
400 				{
401 					const_cast< ImpViewInformation2D* >(this)->impFillViewInformationFromContent();
402 				}
403 
404 				return mxViewInformation;
405 			}
406 
407 			const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
408 			{
409 				return mxExtendedInformation;
410 			}
411 
412 			bool operator==(const ImpViewInformation2D& rCandidate) const
413 			{
414 				return (maObjectTransformation == rCandidate.maObjectTransformation
415                     && maViewTransformation == rCandidate.maViewTransformation
416 					&& maViewport == rCandidate.maViewport
417 					&& mxVisualizedPage == rCandidate.mxVisualizedPage
418 					&& mfViewTime == rCandidate.mfViewTime
419 					&& mxExtendedInformation == rCandidate.mxExtendedInformation);
420 			}
421 
422 			static ImpViewInformation2D* get_global_default()
423             {
424                 static ImpViewInformation2D* pDefault = 0;
425 
426                 if(!pDefault)
427                 {
428                     pDefault = new ImpViewInformation2D();
429 
430                     // never delete; start with RefCount 1, not 0
431     			    pDefault->mnRefCount++;
432                 }
433 
434                 return pDefault;
435             }
436 		};
437 	} // end of anonymous namespace
438 } // end of namespace drawinglayer
439 
440 //////////////////////////////////////////////////////////////////////////////
441 
442 namespace drawinglayer
443 {
444 	namespace geometry
445 	{
446 		ViewInformation2D::ViewInformation2D(
447 			const basegfx::B2DHomMatrix& rObjectTransformation,
448 			const basegfx::B2DHomMatrix& rViewTransformation,
449 			const basegfx::B2DRange& rViewport,
450 			const uno::Reference< drawing::XDrawPage >& rxDrawPage,
451 			double fViewTime,
452 			const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
453 		:	mpViewInformation2D(new ImpViewInformation2D(
454                 rObjectTransformation,
455                 rViewTransformation,
456                 rViewport,
457                 rxDrawPage,
458                 fViewTime,
459                 rExtendedParameters))
460 		{
461 		}
462 
463 		ViewInformation2D::ViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
464 		:	mpViewInformation2D(new ImpViewInformation2D(rViewParameters))
465 		{
466 		}
467 
468 		ViewInformation2D::ViewInformation2D()
469         :	mpViewInformation2D(ImpViewInformation2D::get_global_default())
470 		{
471 			mpViewInformation2D->mnRefCount++;
472 		}
473 
474 		ViewInformation2D::ViewInformation2D(const ViewInformation2D& rCandidate)
475 		:	mpViewInformation2D(rCandidate.mpViewInformation2D)
476 		{
477 		    ::osl::Mutex m_mutex;
478 			mpViewInformation2D->mnRefCount++;
479 		}
480 
481 		ViewInformation2D::~ViewInformation2D()
482 		{
483 		    ::osl::Mutex m_mutex;
484 
485 			if(mpViewInformation2D->mnRefCount)
486 			{
487 				mpViewInformation2D->mnRefCount--;
488 			}
489 			else
490 			{
491 				delete mpViewInformation2D;
492 			}
493 		}
494 
495         bool ViewInformation2D::isDefault() const
496         {
497             return mpViewInformation2D == ImpViewInformation2D::get_global_default();
498         }
499 
500 		ViewInformation2D& ViewInformation2D::operator=(const ViewInformation2D& rCandidate)
501 		{
502 		    ::osl::Mutex m_mutex;
503 
504 			if(mpViewInformation2D->mnRefCount)
505 			{
506 				mpViewInformation2D->mnRefCount--;
507 			}
508 			else
509 			{
510 				delete mpViewInformation2D;
511 			}
512 
513 			mpViewInformation2D = rCandidate.mpViewInformation2D;
514 			mpViewInformation2D->mnRefCount++;
515 
516 			return *this;
517 		}
518 
519 		bool ViewInformation2D::operator==(const ViewInformation2D& rCandidate) const
520 		{
521 			if(rCandidate.mpViewInformation2D == mpViewInformation2D)
522 			{
523 				return true;
524 			}
525 
526 			if(rCandidate.isDefault() != isDefault())
527 			{
528 				return false;
529 			}
530 
531 			return (*rCandidate.mpViewInformation2D == *mpViewInformation2D);
532 		}
533 
534 		const basegfx::B2DHomMatrix& ViewInformation2D::getObjectTransformation() const
535         {
536 			return mpViewInformation2D->getObjectTransformation();
537         }
538 
539 		const basegfx::B2DHomMatrix& ViewInformation2D::getViewTransformation() const
540 		{
541 			return mpViewInformation2D->getViewTransformation();
542 		}
543 
544 		const basegfx::B2DRange& ViewInformation2D::getViewport() const
545 		{
546 			return mpViewInformation2D->getViewport();
547 		}
548 
549 		double ViewInformation2D::getViewTime() const
550 		{
551 			return mpViewInformation2D->getViewTime();
552 		}
553 
554 		const uno::Reference< drawing::XDrawPage >& ViewInformation2D::getVisualizedPage() const
555 		{
556 			return mpViewInformation2D->getVisualizedPage();
557 		}
558 
559 		const basegfx::B2DHomMatrix& ViewInformation2D::getObjectToViewTransformation() const
560         {
561 			return mpViewInformation2D->getObjectToViewTransformation();
562         }
563 
564 		const basegfx::B2DHomMatrix& ViewInformation2D::getInverseObjectToViewTransformation() const
565         {
566 			return mpViewInformation2D->getInverseObjectToViewTransformation();
567         }
568 
569         const basegfx::B2DRange& ViewInformation2D::getDiscreteViewport() const
570 		{
571 			return mpViewInformation2D->getDiscreteViewport();
572 		}
573 
574         bool ViewInformation2D::getReducedDisplayQuality() const
575         {
576             return mpViewInformation2D->getReducedDisplayQuality();
577         }
578 
579 		const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getViewInformationSequence() const
580 		{
581 			return mpViewInformation2D->getViewInformationSequence();
582 		}
583 
584 		const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getExtendedInformationSequence() const
585 		{
586 			return mpViewInformation2D->getExtendedInformationSequence();
587 		}
588 	} // end of namespace geometry
589 } // end of namespace drawinglayer
590 
591 //////////////////////////////////////////////////////////////////////////////
592 // eof
593