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/primitive2d/polypolygonprimitive2d.hxx>
21 #include <basegfx/polygon/b2dpolypolygontools.hxx>
22 #include <basegfx/utils/canvastools.hxx>
23 #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
24 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
25 #include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx>
26 #include <basegfx/matrix/b2dhommatrix.hxx>
27 #include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
28 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
29 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
30 #include <basegfx/matrix/b2dhommatrixtools.hxx>
31 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
32 #include <drawinglayer/geometry/viewinformation2d.hxx>
33 #include <vcl/graph.hxx>
34 
35 
36 using namespace com::sun::star;
37 
38 
39 namespace drawinglayer
40 {
41     namespace primitive2d
42     {
create2DDecomposition(Primitive2DContainer & rContainer,const geometry::ViewInformation2D &) const43         void PolyPolygonHairlinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
44         {
45             const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
46             const sal_uInt32 nCount(aPolyPolygon.count());
47 
48             if(nCount)
49             {
50                 for(sal_uInt32 a(0); a < nCount; a++)
51                 {
52                     rContainer.push_back(new PolygonHairlinePrimitive2D(aPolyPolygon.getB2DPolygon(a), getBColor()));
53                 }
54             }
55         }
56 
PolyPolygonHairlinePrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::BColor & rBColor)57         PolyPolygonHairlinePrimitive2D::PolyPolygonHairlinePrimitive2D(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rBColor)
58         :   BufferedDecompositionPrimitive2D(),
59             maPolyPolygon(rPolyPolygon),
60             maBColor(rBColor)
61         {
62         }
63 
operator ==(const BasePrimitive2D & rPrimitive) const64         bool PolyPolygonHairlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
65         {
66             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
67             {
68                 const PolyPolygonHairlinePrimitive2D& rCompare = static_cast<const PolyPolygonHairlinePrimitive2D&>(rPrimitive);
69 
70                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
71                     && getBColor() == rCompare.getBColor());
72             }
73 
74             return false;
75         }
76 
getB2DRange(const geometry::ViewInformation2D &) const77         basegfx::B2DRange PolyPolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
78         {
79             // return range
80             return basegfx::utils::getRange(getB2DPolyPolygon());
81         }
82 
83         // provide unique ID
84         ImplPrimitive2DIDBlock(PolyPolygonHairlinePrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONHAIRLINEPRIMITIVE2D)
85 
86     } // end of namespace primitive2d
87 } // end of namespace drawinglayer
88 
89 
90 namespace drawinglayer
91 {
92     namespace primitive2d
93     {
create2DDecomposition(Primitive2DContainer & rContainer,const geometry::ViewInformation2D &) const94         void PolyPolygonMarkerPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
95         {
96             const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
97             const sal_uInt32 nCount(aPolyPolygon.count());
98 
99             if(nCount)
100             {
101                 for(sal_uInt32 a(0); a < nCount; a++)
102                 {
103                     rContainer.push_back(
104                         new PolygonMarkerPrimitive2D(
105                             aPolyPolygon.getB2DPolygon(a),
106                             getRGBColorA(),
107                             getRGBColorB(),
108                             getDiscreteDashLength()));
109                 }
110             }
111         }
112 
PolyPolygonMarkerPrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::BColor & rRGBColorA,const basegfx::BColor & rRGBColorB,double fDiscreteDashLength)113         PolyPolygonMarkerPrimitive2D::PolyPolygonMarkerPrimitive2D(
114             const basegfx::B2DPolyPolygon& rPolyPolygon,
115             const basegfx::BColor& rRGBColorA,
116             const basegfx::BColor& rRGBColorB,
117             double fDiscreteDashLength)
118         :   BufferedDecompositionPrimitive2D(),
119             maPolyPolygon(rPolyPolygon),
120             maRGBColorA(rRGBColorA),
121             maRGBColorB(rRGBColorB),
122             mfDiscreteDashLength(fDiscreteDashLength)
123         {
124         }
125 
operator ==(const BasePrimitive2D & rPrimitive) const126         bool PolyPolygonMarkerPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
127         {
128             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
129             {
130                 const PolyPolygonMarkerPrimitive2D& rCompare = static_cast<const PolyPolygonMarkerPrimitive2D&>(rPrimitive);
131 
132                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
133                     && getRGBColorA() == rCompare.getRGBColorA()
134                     && getRGBColorB() == rCompare.getRGBColorB()
135                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
136             }
137 
138             return false;
139         }
140 
getB2DRange(const geometry::ViewInformation2D &) const141         basegfx::B2DRange PolyPolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
142         {
143             // return range
144             return basegfx::utils::getRange(getB2DPolyPolygon());
145         }
146 
147         // provide unique ID
148         ImplPrimitive2DIDBlock(PolyPolygonMarkerPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONMARKERPRIMITIVE2D)
149 
150     } // end of namespace primitive2d
151 } // end of namespace drawinglayer
152 
153 
154 namespace drawinglayer
155 {
156     namespace primitive2d
157     {
create2DDecomposition(Primitive2DContainer & rContainer,const geometry::ViewInformation2D &) const158         void PolyPolygonStrokePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
159         {
160             const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
161             const sal_uInt32 nCount(aPolyPolygon.count());
162 
163             if(nCount)
164             {
165                 for(sal_uInt32 a(0); a < nCount; a++)
166                 {
167                     rContainer.push_back(
168                         new PolygonStrokePrimitive2D(
169                             aPolyPolygon.getB2DPolygon(a), getLineAttribute(), getStrokeAttribute()));
170                 }
171             }
172         }
173 
PolyPolygonStrokePrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const attribute::LineAttribute & rLineAttribute,const attribute::StrokeAttribute & rStrokeAttribute)174         PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D(
175             const basegfx::B2DPolyPolygon& rPolyPolygon,
176             const attribute::LineAttribute& rLineAttribute,
177             const attribute::StrokeAttribute& rStrokeAttribute)
178         :   BufferedDecompositionPrimitive2D(),
179             maPolyPolygon(rPolyPolygon),
180             maLineAttribute(rLineAttribute),
181             maStrokeAttribute(rStrokeAttribute)
182         {
183         }
184 
PolyPolygonStrokePrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const attribute::LineAttribute & rLineAttribute)185         PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D(
186             const basegfx::B2DPolyPolygon& rPolyPolygon,
187             const attribute::LineAttribute& rLineAttribute)
188         :   BufferedDecompositionPrimitive2D(),
189             maPolyPolygon(rPolyPolygon),
190             maLineAttribute(rLineAttribute),
191             maStrokeAttribute()
192         {
193         }
194 
operator ==(const BasePrimitive2D & rPrimitive) const195         bool PolyPolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
196         {
197             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
198             {
199                 const PolyPolygonStrokePrimitive2D& rCompare = static_cast<const PolyPolygonStrokePrimitive2D&>(rPrimitive);
200 
201                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
202                     && getLineAttribute() == rCompare.getLineAttribute()
203                     && getStrokeAttribute() == rCompare.getStrokeAttribute());
204             }
205 
206             return false;
207         }
208 
getB2DRange(const geometry::ViewInformation2D &) const209         basegfx::B2DRange PolyPolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
210         {
211             // get range of it (subdivided)
212             basegfx::B2DRange aRetval(basegfx::utils::getRange(getB2DPolyPolygon()));
213 
214             // if width, grow by line width
215             if(getLineAttribute().getWidth())
216             {
217                 aRetval.grow(getLineAttribute().getWidth() / 2.0);
218             }
219 
220             return aRetval;
221         }
222 
223         // provide unique ID
224         ImplPrimitive2DIDBlock(PolyPolygonStrokePrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONSTROKEPRIMITIVE2D)
225 
226     } // end of namespace primitive2d
227 } // end of namespace drawinglayer
228 
229 
230 namespace drawinglayer
231 {
232     namespace primitive2d
233     {
PolyPolygonColorPrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::BColor & rBColor)234         PolyPolygonColorPrimitive2D::PolyPolygonColorPrimitive2D(
235             const basegfx::B2DPolyPolygon& rPolyPolygon,
236             const basegfx::BColor& rBColor)
237         :   BasePrimitive2D(),
238             maPolyPolygon(rPolyPolygon),
239             maBColor(rBColor)
240         {
241         }
242 
operator ==(const BasePrimitive2D & rPrimitive) const243         bool PolyPolygonColorPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
244         {
245             if(BasePrimitive2D::operator==(rPrimitive))
246             {
247                 const PolyPolygonColorPrimitive2D& rCompare = static_cast<const PolyPolygonColorPrimitive2D&>(rPrimitive);
248 
249                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
250                     && getBColor() == rCompare.getBColor());
251             }
252 
253             return false;
254         }
255 
getB2DRange(const geometry::ViewInformation2D &) const256         basegfx::B2DRange PolyPolygonColorPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
257         {
258             // return range
259             return basegfx::utils::getRange(getB2DPolyPolygon());
260         }
261 
262         // provide unique ID
263         ImplPrimitive2DIDBlock(PolyPolygonColorPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D)
264 
265     } // end of namespace primitive2d
266 } // end of namespace drawinglayer
267 
268 
269 namespace drawinglayer
270 {
271     namespace primitive2d
272     {
create2DDecomposition(Primitive2DContainer & rContainer,const geometry::ViewInformation2D &) const273         void PolyPolygonGradientPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
274         {
275             if(!getFillGradient().isDefault())
276             {
277                 // create SubSequence with FillGradientPrimitive2D
278                 const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
279                 FillGradientPrimitive2D* pNewGradient = new FillGradientPrimitive2D(
280                     aPolyPolygonRange,
281                     getDefinitionRange(),
282                     getFillGradient());
283                 const Primitive2DReference xSubRef(pNewGradient);
284                 const Primitive2DContainer aSubSequence { xSubRef };
285 
286                 // create mask primitive
287                 rContainer.push_back(new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence));
288             }
289         }
290 
PolyPolygonGradientPrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const attribute::FillGradientAttribute & rFillGradient)291         PolyPolygonGradientPrimitive2D::PolyPolygonGradientPrimitive2D(
292             const basegfx::B2DPolyPolygon& rPolyPolygon,
293             const attribute::FillGradientAttribute& rFillGradient)
294         :   BufferedDecompositionPrimitive2D(),
295             maPolyPolygon(rPolyPolygon),
296             maDefinitionRange(rPolyPolygon.getB2DRange()),
297             maFillGradient(rFillGradient)
298         {
299         }
300 
PolyPolygonGradientPrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::B2DRange & rDefinitionRange,const attribute::FillGradientAttribute & rFillGradient)301         PolyPolygonGradientPrimitive2D::PolyPolygonGradientPrimitive2D(
302             const basegfx::B2DPolyPolygon& rPolyPolygon,
303             const basegfx::B2DRange& rDefinitionRange,
304             const attribute::FillGradientAttribute& rFillGradient)
305         :   BufferedDecompositionPrimitive2D(),
306             maPolyPolygon(rPolyPolygon),
307             maDefinitionRange(rDefinitionRange),
308             maFillGradient(rFillGradient)
309         {
310         }
311 
operator ==(const BasePrimitive2D & rPrimitive) const312         bool PolyPolygonGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
313         {
314             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
315             {
316                 const PolyPolygonGradientPrimitive2D& rCompare = static_cast<const PolyPolygonGradientPrimitive2D&>(rPrimitive);
317 
318                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
319                     && getDefinitionRange() == rCompare.getDefinitionRange()
320                     && getFillGradient() == rCompare.getFillGradient());
321             }
322 
323             return false;
324         }
325 
326         // provide unique ID
327         ImplPrimitive2DIDBlock(PolyPolygonGradientPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D)
328 
329     } // end of namespace primitive2d
330 } // end of namespace drawinglayer
331 
332 
333 namespace drawinglayer
334 {
335     namespace primitive2d
336     {
create2DDecomposition(Primitive2DContainer & rContainer,const geometry::ViewInformation2D &) const337         void PolyPolygonHatchPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
338         {
339             if(!getFillHatch().isDefault())
340             {
341                 // create SubSequence with FillHatchPrimitive2D
342                 const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
343                 FillHatchPrimitive2D* pNewHatch = new FillHatchPrimitive2D(
344                     aPolyPolygonRange,
345                     getDefinitionRange(),
346                     getBackgroundColor(),
347                     getFillHatch());
348                 const Primitive2DReference xSubRef(pNewHatch);
349                 const Primitive2DContainer aSubSequence { xSubRef };
350 
351                 // create mask primitive
352                 rContainer.push_back(new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence));
353             }
354         }
355 
PolyPolygonHatchPrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::BColor & rBackgroundColor,const attribute::FillHatchAttribute & rFillHatch)356         PolyPolygonHatchPrimitive2D::PolyPolygonHatchPrimitive2D(
357             const basegfx::B2DPolyPolygon& rPolyPolygon,
358             const basegfx::BColor& rBackgroundColor,
359             const attribute::FillHatchAttribute& rFillHatch)
360         :   BufferedDecompositionPrimitive2D(),
361             maPolyPolygon(rPolyPolygon),
362             maDefinitionRange(rPolyPolygon.getB2DRange()),
363             maBackgroundColor(rBackgroundColor),
364             maFillHatch(rFillHatch)
365         {
366         }
367 
PolyPolygonHatchPrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::B2DRange & rDefinitionRange,const basegfx::BColor & rBackgroundColor,const attribute::FillHatchAttribute & rFillHatch)368         PolyPolygonHatchPrimitive2D::PolyPolygonHatchPrimitive2D(
369             const basegfx::B2DPolyPolygon& rPolyPolygon,
370             const basegfx::B2DRange& rDefinitionRange,
371             const basegfx::BColor& rBackgroundColor,
372             const attribute::FillHatchAttribute& rFillHatch)
373         :   BufferedDecompositionPrimitive2D(),
374             maPolyPolygon(rPolyPolygon),
375             maDefinitionRange(rDefinitionRange),
376             maBackgroundColor(rBackgroundColor),
377             maFillHatch(rFillHatch)
378         {
379         }
380 
operator ==(const BasePrimitive2D & rPrimitive) const381         bool PolyPolygonHatchPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
382         {
383             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
384             {
385                 const PolyPolygonHatchPrimitive2D& rCompare = static_cast<const PolyPolygonHatchPrimitive2D&>(rPrimitive);
386 
387                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
388                     && getDefinitionRange() == rCompare.getDefinitionRange()
389                     && getBackgroundColor() == rCompare.getBackgroundColor()
390                     && getFillHatch() == rCompare.getFillHatch());
391             }
392 
393             return false;
394         }
395 
396         // provide unique ID
397         ImplPrimitive2DIDBlock(PolyPolygonHatchPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D)
398 
399     } // end of namespace primitive2d
400 } // end of namespace drawinglayer
401 
402 
403 namespace drawinglayer
404 {
405     namespace primitive2d
406     {
create2DDecomposition(Primitive2DContainer & rContainer,const geometry::ViewInformation2D &) const407         void PolyPolygonGraphicPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
408         {
409             if(!getFillGraphic().isDefault())
410             {
411                 const Graphic& rGraphic = getFillGraphic().getGraphic();
412                 const GraphicType aType(rGraphic.GetType());
413 
414                 // is there a bitmap or a metafile (do we have content)?
415                 if(GraphicType::Bitmap == aType || GraphicType::GdiMetafile == aType)
416                 {
417                     const Size aPrefSize(rGraphic.GetPrefSize());
418 
419                     // does content have a size?
420                     if(aPrefSize.Width() && aPrefSize.Height())
421                     {
422                         // create SubSequence with FillGraphicPrimitive2D based on polygon range
423                         const basegfx::B2DRange aOutRange(getB2DPolyPolygon().getB2DRange());
424                         const basegfx::B2DHomMatrix aNewObjectTransform(
425                             basegfx::utils::createScaleTranslateB2DHomMatrix(
426                                 aOutRange.getRange(),
427                                 aOutRange.getMinimum()));
428                         Primitive2DReference xSubRef;
429 
430                         if(aOutRange != getDefinitionRange())
431                         {
432                             // we want to paint (tiled) content which is defined relative to DefinitionRange
433                             // with the same tiling and offset(s) in the traget range of the geometry (the
434                             // polygon). The range given in the local FillGraphicAttribute defines the position
435                             // of the graphic in unit coordinates relative to the DefinitionRange. Transform
436                             // this using DefinitionRange to get to the global definition and then with the
437                             // inverse transformation from the target range to go to unit coordinates relative
438                             // to that traget coordinate system.
439                             basegfx::B2DRange aAdaptedRange(getFillGraphic().getGraphicRange());
440 
441                             const basegfx::B2DHomMatrix aFromDefinitionRangeToGlobal(
442                                 basegfx::utils::createScaleTranslateB2DHomMatrix(
443                                     getDefinitionRange().getRange(),
444                                     getDefinitionRange().getMinimum()));
445 
446                             aAdaptedRange.transform(aFromDefinitionRangeToGlobal);
447 
448                             basegfx::B2DHomMatrix aFromGlobalToOutRange(
449                                 basegfx::utils::createScaleTranslateB2DHomMatrix(
450                                     aOutRange.getRange(),
451                                     aOutRange.getMinimum()));
452                             aFromGlobalToOutRange.invert();
453 
454                             aAdaptedRange.transform(aFromGlobalToOutRange);
455 
456                             const drawinglayer::attribute::FillGraphicAttribute aAdaptedFillGraphicAttribute(
457                                 getFillGraphic().getGraphic(),
458                                 aAdaptedRange,
459                                 getFillGraphic().getTiling(),
460                                 getFillGraphic().getOffsetX(),
461                                 getFillGraphic().getOffsetY());
462 
463                             xSubRef = new FillGraphicPrimitive2D(
464                                 aNewObjectTransform,
465                                 aAdaptedFillGraphicAttribute);
466                         }
467                         else
468                         {
469                             xSubRef = new FillGraphicPrimitive2D(
470                                 aNewObjectTransform,
471                                 getFillGraphic());
472                         }
473 
474                         // embed to mask primitive
475                         rContainer.push_back(
476                             new MaskPrimitive2D(
477                                 getB2DPolyPolygon(),
478                                 Primitive2DContainer { xSubRef }));
479                     }
480                 }
481             }
482         }
483 
PolyPolygonGraphicPrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::B2DRange & rDefinitionRange,const attribute::FillGraphicAttribute & rFillGraphic)484         PolyPolygonGraphicPrimitive2D::PolyPolygonGraphicPrimitive2D(
485             const basegfx::B2DPolyPolygon& rPolyPolygon,
486             const basegfx::B2DRange& rDefinitionRange,
487             const attribute::FillGraphicAttribute& rFillGraphic)
488         :   BufferedDecompositionPrimitive2D(),
489             maPolyPolygon(rPolyPolygon),
490             maDefinitionRange(rDefinitionRange),
491             maFillGraphic(rFillGraphic)
492         {
493         }
494 
operator ==(const BasePrimitive2D & rPrimitive) const495         bool PolyPolygonGraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
496         {
497             if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
498             {
499                 const PolyPolygonGraphicPrimitive2D& rCompare = static_cast<const PolyPolygonGraphicPrimitive2D&>(rPrimitive);
500 
501                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
502                     && getDefinitionRange() == rCompare.getDefinitionRange()
503                     && getFillGraphic() == rCompare.getFillGraphic());
504             }
505 
506             return false;
507         }
508 
509         // provide unique ID
510         ImplPrimitive2DIDBlock(PolyPolygonGraphicPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D)
511 
512     } // end of namespace primitive2d
513 } // end of namespace drawinglayer
514 
515 
516 namespace drawinglayer
517 {
518     namespace primitive2d
519     {
create2DDecomposition(Primitive2DContainer & rContainer,const geometry::ViewInformation2D &) const520         void PolyPolygonSelectionPrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const
521         {
522             if(getTransparence() >= 1.0 || !getB2DPolyPolygon().count())
523                 return;
524 
525             Primitive2DContainer aRetval;
526 
527             if(getFill() && getB2DPolyPolygon().isClosed())
528             {
529                 // create fill primitive
530                 const Primitive2DReference aFill(
531                     new PolyPolygonColorPrimitive2D(
532                         getB2DPolyPolygon(),
533                         getColor()));
534 
535                 aRetval = Primitive2DContainer { aFill };
536             }
537 
538             if(getDiscreteGrow() > 0.0)
539             {
540                 const attribute::LineAttribute aLineAttribute(
541                     getColor(),
542                     getDiscreteGrow() * getDiscreteUnit() * 2.0);
543                 const Primitive2DReference aFatLine(
544                     new PolyPolygonStrokePrimitive2D(
545                         getB2DPolyPolygon(),
546                         aLineAttribute));
547 
548                 aRetval.push_back(aFatLine);
549             }
550 
551             // embed filled to transparency (if used)
552             if(!aRetval.empty() && getTransparence() > 0.0)
553             {
554                 const Primitive2DReference aTrans(
555                     new UnifiedTransparencePrimitive2D(
556                         aRetval,
557                         getTransparence()));
558 
559                 aRetval = Primitive2DContainer { aTrans };
560             }
561 
562             rContainer.insert(rContainer.end(), aRetval.begin(), aRetval.end());
563         }
564 
PolyPolygonSelectionPrimitive2D(const basegfx::B2DPolyPolygon & rPolyPolygon,const basegfx::BColor & rColor,double fTransparence,double fDiscreteGrow,bool bFill)565         PolyPolygonSelectionPrimitive2D::PolyPolygonSelectionPrimitive2D(
566             const basegfx::B2DPolyPolygon& rPolyPolygon,
567             const basegfx::BColor& rColor,
568             double fTransparence,
569             double fDiscreteGrow,
570             bool bFill)
571         :   DiscreteMetricDependentPrimitive2D(),
572             maPolyPolygon(rPolyPolygon),
573             maColor(rColor),
574             mfTransparence(fTransparence),
575             mfDiscreteGrow(fabs(fDiscreteGrow)),
576             mbFill(bFill)
577         {
578         }
579 
operator ==(const BasePrimitive2D & rPrimitive) const580         bool PolyPolygonSelectionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
581         {
582             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
583             {
584                 const PolyPolygonSelectionPrimitive2D& rCompare = static_cast<const PolyPolygonSelectionPrimitive2D&>(rPrimitive);
585 
586                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
587                     && getColor() == rCompare.getColor()
588                     && getTransparence() == rCompare.getTransparence()
589                     && getDiscreteGrow() == rCompare.getDiscreteGrow()
590                     && getFill() == rCompare.getFill());
591             }
592 
593             return false;
594         }
595 
getB2DRange(const geometry::ViewInformation2D & rViewInformation) const596         basegfx::B2DRange PolyPolygonSelectionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
597         {
598             basegfx::B2DRange aRetval(basegfx::utils::getRange(getB2DPolyPolygon()));
599 
600             if(getDiscreteGrow() > 0.0)
601             {
602                 // get the current DiscreteUnit (not sure if getDiscreteUnit() is updated here, better go safe way)
603                 const double fDiscreteUnit((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
604 
605                 aRetval.grow(fDiscreteUnit * getDiscreteGrow());
606             }
607 
608             return aRetval;
609         }
610 
611         // provide unique ID
612         ImplPrimitive2DIDBlock(PolyPolygonSelectionPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONSELECTIONPRIMITIVE2D)
613 
614     } // end of namespace primitive2d
615 } // end of namespace drawinglayer
616 
617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
618