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