1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <drawinglayer/geometry/viewinformation2d.hxx>
21 #include <basegfx/matrix/b2dhommatrix.hxx>
22 #include <basegfx/range/b2drange.hxx>
23 #include <basegfx/utils/canvastools.hxx>
24 #include <com/sun/star/beans/PropertyValue.hpp>
25 #include <com/sun/star/drawing/XDrawPage.hpp>
26 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
27 #include <com/sun/star/geometry/RealRectangle2D.hpp>
28 #include <rtl/instance.hxx>
29 #include <com/sun/star/uno/Sequence.hxx>
30 
31 
32 using namespace com::sun::star;
33 
34 
35 namespace drawinglayer
36 {
37     namespace geometry
38     {
39         class ImpViewInformation2D
40         {
41         private:
42             // ViewInformation2D implementation can change refcount, so we have only
43             // two memory regions for pairs of ViewInformation2D/ImpViewInformation2D
44             friend class ::drawinglayer::geometry::ViewInformation2D;
45 
46         protected:
47             // the object transformation
48             basegfx::B2DHomMatrix                       maObjectTransformation;
49 
50             // the view transformation
51             basegfx::B2DHomMatrix                       maViewTransformation;
52 
53             // the ObjectToView and it's inverse, both on demand from ObjectTransformation
54             // and ViewTransformation
55             basegfx::B2DHomMatrix                       maObjectToViewTransformation;
56             basegfx::B2DHomMatrix                       maInverseObjectToViewTransformation;
57 
58             // the visible range and the on-demand one in ViewCoordinates
59             basegfx::B2DRange                           maViewport;
60             basegfx::B2DRange                           maDiscreteViewport;
61 
62             // the DrawPage which is target of visualisation. This is needed e.g. for
63             // the view-dependent decomposition of PageNumber TextFields.
64             // This parameter is buffered here, but mainly resides in mxExtendedInformation,
65             // so it will be interpreted, but held there. It will also not be added
66             // to mxExtendedInformation in impFillViewInformationFromContent (it's there already)
67             uno::Reference< drawing::XDrawPage >        mxVisualizedPage;
68 
69             // the point in time
70             double                                      mfViewTime;
71 
72             bool                                        mbReducedDisplayQuality : 1;
73 
74             // the complete PropertyValue representation (if already created)
75             uno::Sequence< beans::PropertyValue >       mxViewInformation;
76 
77             // the extra PropertyValues; not represented by ViewTransformation,
78             // Viewport, VisualizedPage or ViewTime
79             uno::Sequence< beans::PropertyValue >       mxExtendedInformation;
80 
81             // the local UNO API strings
getNamePropertyObjectTransformation()82             static OUString getNamePropertyObjectTransformation()
83             {
84                 return "ObjectTransformation";
85             }
86 
getNamePropertyViewTransformation()87             static OUString getNamePropertyViewTransformation()
88             {
89                 return "ViewTransformation";
90             }
91 
getNamePropertyViewport()92             static OUString getNamePropertyViewport()
93             {
94                 return "Viewport";
95             }
96 
getNamePropertyTime()97             static OUString getNamePropertyTime()
98             {
99                 return "Time";
100             }
101 
getNamePropertyVisualizedPage()102             static OUString getNamePropertyVisualizedPage()
103             {
104                 return "VisualizedPage";
105             }
106 
getNamePropertyReducedDisplayQuality()107             static OUString getNamePropertyReducedDisplayQuality()
108             {
109                 return "ReducedDisplayQuality";
110             }
111 
impInterpretPropertyValues(const uno::Sequence<beans::PropertyValue> & rViewParameters)112             void impInterpretPropertyValues(const uno::Sequence< beans::PropertyValue >& rViewParameters)
113             {
114                 if(rViewParameters.hasElements())
115                 {
116                     const sal_Int32 nCount(rViewParameters.getLength());
117                     sal_Int32 nExtendedInsert(0);
118 
119                     // prepare extended information for filtering. Maximum size is nCount
120                     mxExtendedInformation.realloc(nCount);
121 
122                     for(sal_Int32 a(0); a < nCount; a++)
123                     {
124                         const beans::PropertyValue& rProp = rViewParameters[a];
125 
126                         if(rProp.Name == getNamePropertyReducedDisplayQuality())
127                         {
128                             // extra information; add to filtered information
129                             mxExtendedInformation[nExtendedInsert++] = rProp;
130 
131                             // for performance reasons, also cache content locally
132                             bool bSalBool(false);
133                             rProp.Value >>= bSalBool;
134                             mbReducedDisplayQuality = bSalBool;
135                         }
136                         else if(rProp.Name == getNamePropertyObjectTransformation())
137                         {
138                             css::geometry::AffineMatrix2D aAffineMatrix2D;
139                             rProp.Value >>= aAffineMatrix2D;
140                             basegfx::unotools::homMatrixFromAffineMatrix(maObjectTransformation, aAffineMatrix2D);
141                         }
142                         else if(rProp.Name == getNamePropertyViewTransformation())
143                         {
144                             css::geometry::AffineMatrix2D aAffineMatrix2D;
145                             rProp.Value >>= aAffineMatrix2D;
146                             basegfx::unotools::homMatrixFromAffineMatrix(maViewTransformation, aAffineMatrix2D);
147                         }
148                         else if(rProp.Name == getNamePropertyViewport())
149                         {
150                             css::geometry::RealRectangle2D aViewport;
151                             rProp.Value >>= aViewport;
152                             maViewport = basegfx::unotools::b2DRectangleFromRealRectangle2D(aViewport);
153                         }
154                         else if(rProp.Name == getNamePropertyTime())
155                         {
156                             rProp.Value >>= mfViewTime;
157                         }
158                         else if(rProp.Name == getNamePropertyVisualizedPage())
159                         {
160                             rProp.Value >>= mxVisualizedPage;
161                         }
162                         else
163                         {
164                             // extra information; add to filtered information
165                             mxExtendedInformation[nExtendedInsert++] = rProp;
166                         }
167                     }
168 
169                     // extra information size is now known; realloc to final size
170                     mxExtendedInformation.realloc(nExtendedInsert);
171                 }
172             }
173 
impFillViewInformationFromContent()174             void impFillViewInformationFromContent()
175             {
176                 const bool bObjectTransformationUsed(!maObjectTransformation.isIdentity());
177                 const bool bViewTransformationUsed(!maViewTransformation.isIdentity());
178                 const bool bViewportUsed(!maViewport.isEmpty());
179                 const bool bTimeUsed(0.0 < mfViewTime);
180                 const bool bVisualizedPageUsed(mxVisualizedPage.is());
181                 const bool bReducedDisplayQualityUsed(mbReducedDisplayQuality);
182                 const bool bExtraInformation(mxExtendedInformation.hasElements());
183                 sal_uInt32 nIndex(0);
184                 const sal_uInt32 nCount(
185                     (bObjectTransformationUsed ? 1 : 0) +
186                     (bViewTransformationUsed ? 1 : 0) +
187                     (bViewportUsed ? 1 : 0) +
188                     (bTimeUsed ? 1 : 0) +
189                     (bVisualizedPageUsed ? 1 : 0) +
190                     (bReducedDisplayQualityUsed ? 1 : 0) +
191                     (bExtraInformation ? mxExtendedInformation.getLength() : 0));
192 
193                 mxViewInformation.realloc(nCount);
194 
195                 if(bObjectTransformationUsed)
196                 {
197                     css::geometry::AffineMatrix2D aAffineMatrix2D;
198                     basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maObjectTransformation);
199                     mxViewInformation[nIndex].Name = getNamePropertyObjectTransformation();
200                     mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
201                     nIndex++;
202                 }
203 
204                 if(bViewTransformationUsed)
205                 {
206                     css::geometry::AffineMatrix2D aAffineMatrix2D;
207                     basegfx::unotools::affineMatrixFromHomMatrix(aAffineMatrix2D, maViewTransformation);
208                     mxViewInformation[nIndex].Name = getNamePropertyViewTransformation();
209                     mxViewInformation[nIndex].Value <<= aAffineMatrix2D;
210                     nIndex++;
211                 }
212 
213                 if(bViewportUsed)
214                 {
215                     const css::geometry::RealRectangle2D aViewport(basegfx::unotools::rectangle2DFromB2DRectangle(maViewport));
216                     mxViewInformation[nIndex].Name = getNamePropertyViewport();
217                     mxViewInformation[nIndex].Value <<= aViewport;
218                     nIndex++;
219                 }
220 
221                 if(bTimeUsed)
222                 {
223                     mxViewInformation[nIndex].Name = getNamePropertyTime();
224                     mxViewInformation[nIndex].Value <<= mfViewTime;
225                     nIndex++;
226                 }
227 
228                 if(bVisualizedPageUsed)
229                 {
230                     mxViewInformation[nIndex].Name = getNamePropertyVisualizedPage();
231                     mxViewInformation[nIndex].Value <<= mxVisualizedPage;
232                     nIndex++;
233                 }
234 
235                 if(bExtraInformation)
236                 {
237                     const sal_Int32 nExtra(mxExtendedInformation.getLength());
238 
239                     for(sal_Int32 a(0); a < nExtra; a++)
240                     {
241                         mxViewInformation[nIndex++] = mxExtendedInformation[a];
242                     }
243                 }
244             }
245 
246         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)247             ImpViewInformation2D(
248                 const basegfx::B2DHomMatrix& rObjectTransformation,
249                 const basegfx::B2DHomMatrix& rViewTransformation,
250                 const basegfx::B2DRange& rViewport,
251                 const uno::Reference< drawing::XDrawPage >& rxDrawPage,
252                 double fViewTime,
253                 const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
254             :   maObjectTransformation(rObjectTransformation),
255                 maViewTransformation(rViewTransformation),
256                 maObjectToViewTransformation(),
257                 maInverseObjectToViewTransformation(),
258                 maViewport(rViewport),
259                 maDiscreteViewport(),
260                 mxVisualizedPage(rxDrawPage),
261                 mfViewTime(fViewTime),
262                 mbReducedDisplayQuality(false),
263                 mxViewInformation(),
264                 mxExtendedInformation()
265             {
266                 impInterpretPropertyValues(rExtendedParameters);
267             }
268 
ImpViewInformation2D(const uno::Sequence<beans::PropertyValue> & rViewParameters)269             explicit ImpViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
270             :   maObjectTransformation(),
271                 maViewTransformation(),
272                 maObjectToViewTransformation(),
273                 maInverseObjectToViewTransformation(),
274                 maViewport(),
275                 maDiscreteViewport(),
276                 mxVisualizedPage(),
277                 mfViewTime(),
278                 mbReducedDisplayQuality(false),
279                 mxViewInformation(rViewParameters),
280                 mxExtendedInformation()
281             {
282                 impInterpretPropertyValues(rViewParameters);
283             }
284 
ImpViewInformation2D()285             ImpViewInformation2D()
286             :   maObjectTransformation(),
287                 maViewTransformation(),
288                 maObjectToViewTransformation(),
289                 maInverseObjectToViewTransformation(),
290                 maViewport(),
291                 maDiscreteViewport(),
292                 mxVisualizedPage(),
293                 mfViewTime(),
294                 mbReducedDisplayQuality(false),
295                 mxViewInformation(),
296                 mxExtendedInformation()
297             {
298             }
299 
getObjectTransformation() const300             const basegfx::B2DHomMatrix& getObjectTransformation() const
301             {
302                 return maObjectTransformation;
303             }
304 
getViewTransformation() const305             const basegfx::B2DHomMatrix& getViewTransformation() const
306             {
307                 return maViewTransformation;
308             }
309 
getViewport() const310             const basegfx::B2DRange& getViewport() const
311             {
312                 return maViewport;
313             }
314 
getDiscreteViewport() const315             const basegfx::B2DRange& getDiscreteViewport() const
316             {
317                 if(maDiscreteViewport.isEmpty() && !maViewport.isEmpty())
318                 {
319                     basegfx::B2DRange aDiscreteViewport(maViewport);
320                     aDiscreteViewport.transform(getViewTransformation());
321                     const_cast< ImpViewInformation2D* >(this)->maDiscreteViewport = aDiscreteViewport;
322                 }
323 
324                 return maDiscreteViewport;
325             }
326 
getObjectToViewTransformation() const327             const basegfx::B2DHomMatrix& getObjectToViewTransformation() const
328             {
329                 if(maObjectToViewTransformation.isIdentity() &&
330                     (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity()))
331                 {
332                     basegfx::B2DHomMatrix aObjectToView(maViewTransformation * maObjectTransformation);
333                     const_cast< ImpViewInformation2D* >(this)->maObjectToViewTransformation = aObjectToView;
334                 }
335 
336                 return maObjectToViewTransformation;
337             }
338 
getInverseObjectToViewTransformation() const339             const basegfx::B2DHomMatrix& getInverseObjectToViewTransformation() const
340             {
341                 if(maInverseObjectToViewTransformation.isIdentity() &&
342                     (!maObjectTransformation.isIdentity() || !maViewTransformation.isIdentity()))
343                 {
344                     basegfx::B2DHomMatrix aInverseObjectToView(maViewTransformation * maObjectTransformation);
345                     aInverseObjectToView.invert();
346                     const_cast< ImpViewInformation2D* >(this)->maInverseObjectToViewTransformation = aInverseObjectToView;
347                 }
348 
349                 return maInverseObjectToViewTransformation;
350             }
351 
getViewTime() const352             double getViewTime() const
353             {
354                 return mfViewTime;
355             }
356 
getVisualizedPage() const357             const uno::Reference< drawing::XDrawPage >& getVisualizedPage() const
358             {
359                 return mxVisualizedPage;
360             }
361 
getReducedDisplayQuality() const362             bool getReducedDisplayQuality() const
363             {
364                 return mbReducedDisplayQuality;
365             }
366 
getViewInformationSequence() const367             const uno::Sequence< beans::PropertyValue >& getViewInformationSequence() const
368             {
369                 if(!mxViewInformation.hasElements())
370                 {
371                     const_cast< ImpViewInformation2D* >(this)->impFillViewInformationFromContent();
372                 }
373 
374                 return mxViewInformation;
375             }
376 
getExtendedInformationSequence() const377             const uno::Sequence< beans::PropertyValue >& getExtendedInformationSequence() const
378             {
379                 return mxExtendedInformation;
380             }
381 
operator ==(const ImpViewInformation2D & rCandidate) const382             bool operator==(const ImpViewInformation2D& rCandidate) const
383             {
384                 return (maObjectTransformation == rCandidate.maObjectTransformation
385                     && maViewTransformation == rCandidate.maViewTransformation
386                     && maViewport == rCandidate.maViewport
387                     && mxVisualizedPage == rCandidate.mxVisualizedPage
388                     && mfViewTime == rCandidate.mfViewTime
389                     && mxExtendedInformation == rCandidate.mxExtendedInformation);
390             }
391         };
392     } // end of anonymous namespace
393 } // end of namespace drawinglayer
394 
395 
396 namespace drawinglayer
397 {
398     namespace geometry
399     {
400         namespace
401         {
402             struct theGlobalDefault :
403                 public rtl::Static< ViewInformation2D::ImplType, theGlobalDefault > {};
404         }
405 
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)406         ViewInformation2D::ViewInformation2D(
407             const basegfx::B2DHomMatrix& rObjectTransformation,
408             const basegfx::B2DHomMatrix& rViewTransformation,
409             const basegfx::B2DRange& rViewport,
410             const uno::Reference< drawing::XDrawPage >& rxDrawPage,
411             double fViewTime,
412             const uno::Sequence< beans::PropertyValue >& rExtendedParameters)
413         :   mpViewInformation2D(ImpViewInformation2D(
414                 rObjectTransformation,
415                 rViewTransformation,
416                 rViewport,
417                 rxDrawPage,
418                 fViewTime,
419                 rExtendedParameters))
420         {
421         }
422 
ViewInformation2D(const uno::Sequence<beans::PropertyValue> & rViewParameters)423         ViewInformation2D::ViewInformation2D(const uno::Sequence< beans::PropertyValue >& rViewParameters)
424         :   mpViewInformation2D(ImpViewInformation2D(rViewParameters))
425         {
426         }
427 
ViewInformation2D()428         ViewInformation2D::ViewInformation2D()
429         :   mpViewInformation2D(theGlobalDefault::get())
430         {
431         }
432 
433         ViewInformation2D::ViewInformation2D(const ViewInformation2D&) = default;
434 
435         ViewInformation2D::ViewInformation2D(ViewInformation2D&&) = default;
436 
437         ViewInformation2D::~ViewInformation2D() = default;
438 
439         ViewInformation2D& ViewInformation2D::operator=(const ViewInformation2D&) = default;
440 
441         ViewInformation2D& ViewInformation2D::operator=(ViewInformation2D&&) = default;
442 
operator ==(const ViewInformation2D & rCandidate) const443         bool ViewInformation2D::operator==(const ViewInformation2D& rCandidate) const
444         {
445             return rCandidate.mpViewInformation2D == mpViewInformation2D;
446         }
447 
getObjectTransformation() const448         const basegfx::B2DHomMatrix& ViewInformation2D::getObjectTransformation() const
449         {
450             return mpViewInformation2D->getObjectTransformation();
451         }
452 
getViewTransformation() const453         const basegfx::B2DHomMatrix& ViewInformation2D::getViewTransformation() const
454         {
455             return mpViewInformation2D->getViewTransformation();
456         }
457 
getViewport() const458         const basegfx::B2DRange& ViewInformation2D::getViewport() const
459         {
460             return mpViewInformation2D->getViewport();
461         }
462 
getViewTime() const463         double ViewInformation2D::getViewTime() const
464         {
465             return mpViewInformation2D->getViewTime();
466         }
467 
getVisualizedPage() const468         const uno::Reference< drawing::XDrawPage >& ViewInformation2D::getVisualizedPage() const
469         {
470             return mpViewInformation2D->getVisualizedPage();
471         }
472 
getObjectToViewTransformation() const473         const basegfx::B2DHomMatrix& ViewInformation2D::getObjectToViewTransformation() const
474         {
475             return mpViewInformation2D->getObjectToViewTransformation();
476         }
477 
getInverseObjectToViewTransformation() const478         const basegfx::B2DHomMatrix& ViewInformation2D::getInverseObjectToViewTransformation() const
479         {
480             return mpViewInformation2D->getInverseObjectToViewTransformation();
481         }
482 
getDiscreteViewport() const483         const basegfx::B2DRange& ViewInformation2D::getDiscreteViewport() const
484         {
485             return mpViewInformation2D->getDiscreteViewport();
486         }
487 
getReducedDisplayQuality() const488         bool ViewInformation2D::getReducedDisplayQuality() const
489         {
490             return mpViewInformation2D->getReducedDisplayQuality();
491         }
492 
getViewInformationSequence() const493         const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getViewInformationSequence() const
494         {
495             return mpViewInformation2D->getViewInformationSequence();
496         }
497 
getExtendedInformationSequence() const498         const uno::Sequence< beans::PropertyValue >& ViewInformation2D::getExtendedInformationSequence() const
499         {
500             return mpViewInformation2D->getExtendedInformationSequence();
501         }
502     } // end of namespace geometry
503 } // end of namespace drawinglayer
504 
505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
506