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 its 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
getNamePropertyObjectTransformation()92 			const ::rtl::OUString& getNamePropertyObjectTransformation()
93 			{
94 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ObjectTransformation"));
95 				return s_sNameProperty;
96 			}
97 
getNamePropertyViewTransformation()98 			const ::rtl::OUString& getNamePropertyViewTransformation()
99 			{
100 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ViewTransformation"));
101 				return s_sNameProperty;
102 			}
103 
getNamePropertyViewport()104 			const ::rtl::OUString& getNamePropertyViewport()
105 			{
106 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Viewport"));
107 				return s_sNameProperty;
108 			}
109 
getNamePropertyTime()110 			const ::rtl::OUString& getNamePropertyTime()
111 			{
112 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("Time"));
113 				return s_sNameProperty;
114 			}
115 
getNamePropertyVisualizedPage()116 			const ::rtl::OUString& getNamePropertyVisualizedPage()
117 			{
118 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("VisualizedPage"));
119 				return s_sNameProperty;
120 			}
121 
getNamePropertyReducedDisplayQuality()122 			const ::rtl::OUString& getNamePropertyReducedDisplayQuality()
123 			{
124 				static ::rtl::OUString s_sNameProperty(RTL_CONSTASCII_USTRINGPARAM("ReducedDisplayQuality"));
125 				return s_sNameProperty;
126 			}
127 
impInterpretPropertyValues(const uno::Sequence<beans::PropertyValue> & rViewParameters)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 
impFillViewInformationFromContent()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:
ImpViewInformation2D(const basegfx::B2DHomMatrix & rObjectTransformation,const basegfx::B2DHomMatrix & rViewTransformation,const basegfx::B2DRange & rViewport,const uno::Reference<drawing::XDrawPage> & rxDrawPage,double fViewTime,const uno::Sequence<beans::PropertyValue> & rExtendedParameters)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 
ImpViewInformation2D(const uno::Sequence<beans::PropertyValue> & rViewParameters)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 
ImpViewInformation2D()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 
getObjectTransformation() const320 			const basegfx::B2DHomMatrix& getObjectTransformation() const
321 			{
322 				return maObjectTransformation;
323 			}
324 
getViewTransformation() const325 			const basegfx::B2DHomMatrix& getViewTransformation() const
326 			{
327 				return maViewTransformation;
328 			}
329 
getViewport() const330 			const basegfx::B2DRange& getViewport() const
331 			{
332 				return maViewport;
333 			}
334 
getDiscreteViewport() const335 			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 
getObjectToViewTransformation() const349 			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 
getInverseObjectToViewTransformation() const363 			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 
getViewTime() const378 			double getViewTime() const
379 			{
380 				return mfViewTime;
381 			}
382 
getVisualizedPage() const383 			const uno::Reference< drawing::XDrawPage >& getVisualizedPage() const
384 			{
385 				return mxVisualizedPage;
386 			}
387 
getReducedDisplayQuality() const388 			bool getReducedDisplayQuality() const
389 			{
390 				return mbReducedDisplayQuality;
391 			}
392 
getViewInformationSequence() const393 			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 
getExtendedInformationSequence() const403 			const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
404 			{
405 				return mxExtendedInformation;
406 			}
407 
operator ==(const ImpViewInformation2D & rCandidate) const408 			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 
get_global_default()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 	{
ViewInformation2D(const basegfx::B2DHomMatrix & rObjectTransformation,const basegfx::B2DHomMatrix & rViewTransformation,const basegfx::B2DRange & rViewport,const uno::Reference<drawing::XDrawPage> & rxDrawPage,double fViewTime,const uno::Sequence<beans::PropertyValue> & rExtendedParameters)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 
ViewInformation2D(const uno::Sequence<beans::PropertyValue> & rViewParameters)459 		ViewInformation2D::ViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
460 		:	mpViewInformation2D(new ImpViewInformation2D(rViewParameters))
461 		{
462 		}
463 
ViewInformation2D()464 		ViewInformation2D::ViewInformation2D()
465 		:	mpViewInformation2D(ImpViewInformation2D::get_global_default())
466 		{
467 			mpViewInformation2D->mnRefCount++;
468 		}
469 
ViewInformation2D(const ViewInformation2D & rCandidate)470 		ViewInformation2D::ViewInformation2D(const ViewInformation2D& rCandidate)
471 		:	mpViewInformation2D(rCandidate.mpViewInformation2D)
472 		{
473 			::osl::Mutex m_mutex;
474 			mpViewInformation2D->mnRefCount++;
475 		}
476 
~ViewInformation2D()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 
isDefault() const491 		bool ViewInformation2D::isDefault() const
492 		{
493 			return mpViewInformation2D == ImpViewInformation2D::get_global_default();
494 		}
495 
operator =(const ViewInformation2D & rCandidate)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 
operator ==(const ViewInformation2D & rCandidate) const515 		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 
getObjectTransformation() const530 		const basegfx::B2DHomMatrix& ViewInformation2D::getObjectTransformation() const
531 		{
532 			return mpViewInformation2D->getObjectTransformation();
533 		}
534 
getViewTransformation() const535 		const basegfx::B2DHomMatrix& ViewInformation2D::getViewTransformation() const
536 		{
537 			return mpViewInformation2D->getViewTransformation();
538 		}
539 
getViewport() const540 		const basegfx::B2DRange& ViewInformation2D::getViewport() const
541 		{
542 			return mpViewInformation2D->getViewport();
543 		}
544 
getViewTime() const545 		double ViewInformation2D::getViewTime() const
546 		{
547 			return mpViewInformation2D->getViewTime();
548 		}
549 
getVisualizedPage() const550 		const uno::Reference< drawing::XDrawPage >& ViewInformation2D::getVisualizedPage() const
551 		{
552 			return mpViewInformation2D->getVisualizedPage();
553 		}
554 
getObjectToViewTransformation() const555 		const basegfx::B2DHomMatrix& ViewInformation2D::getObjectToViewTransformation() const
556 		{
557 			return mpViewInformation2D->getObjectToViewTransformation();
558 		}
559 
getInverseObjectToViewTransformation() const560 		const basegfx::B2DHomMatrix& ViewInformation2D::getInverseObjectToViewTransformation() const
561 		{
562 			return mpViewInformation2D->getInverseObjectToViewTransformation();
563 		}
564 
getDiscreteViewport() const565 		const basegfx::B2DRange& ViewInformation2D::getDiscreteViewport() const
566 		{
567 			return mpViewInformation2D->getDiscreteViewport();
568 		}
569 
getReducedDisplayQuality() const570 		bool ViewInformation2D::getReducedDisplayQuality() const
571 		{
572 			return mpViewInformation2D->getReducedDisplayQuality();
573 		}
574 
getViewInformationSequence() const575 		const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getViewInformationSequence() const
576 		{
577 			return mpViewInformation2D->getViewInformationSequence();
578 		}
579 
getExtendedInformationSequence() const580 		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