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/primitive2d/polypolygonprimitive2d.hxx>
28 #include <basegfx/polygon/b2dpolypolygontools.hxx>
29 #include <basegfx/tools/canvastools.hxx>
30 #include <drawinglayer/primitive2d/fillgradientprimitive2d.hxx>
31 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
32 #include <drawinglayer/primitive2d/fillhatchprimitive2d.hxx>
33 #include <basegfx/matrix/b2dhommatrix.hxx>
34 #include <drawinglayer/primitive2d/fillgraphicprimitive2d.hxx>
35 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
36 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
37 #include <basegfx/matrix/b2dhommatrixtools.hxx>
38 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
39 #include <drawinglayer/geometry/viewinformation2d.hxx>
40 #include <vcl/graph.hxx>
41 
42 //////////////////////////////////////////////////////////////////////////////
43 
44 using namespace com::sun::star;
45 
46 //////////////////////////////////////////////////////////////////////////////
47 
48 namespace drawinglayer
49 {
50 	namespace primitive2d
51 	{
52 		Primitive2DSequence PolyPolygonHairlinePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
53 		{
54 			const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
55 			const sal_uInt32 nCount(aPolyPolygon.count());
56 
57 			if(nCount)
58 			{
59 				Primitive2DSequence aRetval(nCount);
60 
61 				for(sal_uInt32 a(0L); a < nCount; a++)
62 				{
63 					aRetval[a] = Primitive2DReference(new PolygonHairlinePrimitive2D(aPolyPolygon.getB2DPolygon(a), getBColor()));
64 				}
65 
66 				return aRetval;
67 			}
68 			else
69 			{
70 				return Primitive2DSequence();
71 			}
72 		}
73 
74 		PolyPolygonHairlinePrimitive2D::PolyPolygonHairlinePrimitive2D(const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::BColor& rBColor)
75 		:	BufferedDecompositionPrimitive2D(),
76 			maPolyPolygon(rPolyPolygon),
77 			maBColor(rBColor)
78 		{
79 		}
80 
81 		bool PolyPolygonHairlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
82 		{
83 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
84 			{
85 				const PolyPolygonHairlinePrimitive2D& rCompare = (PolyPolygonHairlinePrimitive2D&)rPrimitive;
86 
87 				return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
88 					&& getBColor() == rCompare.getBColor());
89 			}
90 
91 			return false;
92 		}
93 
94 		basegfx::B2DRange PolyPolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
95 		{
96 			// return range
97 			return basegfx::tools::getRange(getB2DPolyPolygon());
98 		}
99 
100 		// provide unique ID
101 		ImplPrimitrive2DIDBlock(PolyPolygonHairlinePrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONHAIRLINEPRIMITIVE2D)
102 
103 	} // end of namespace primitive2d
104 } // end of namespace drawinglayer
105 
106 //////////////////////////////////////////////////////////////////////////////
107 
108 namespace drawinglayer
109 {
110 	namespace primitive2d
111 	{
112 		Primitive2DSequence PolyPolygonMarkerPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
113 		{
114 			const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
115 			const sal_uInt32 nCount(aPolyPolygon.count());
116 
117 			if(nCount)
118 			{
119 				Primitive2DSequence aRetval(nCount);
120 
121 				for(sal_uInt32 a(0L); a < nCount; a++)
122 				{
123 					aRetval[a] = Primitive2DReference(
124                         new PolygonMarkerPrimitive2D(
125                             aPolyPolygon.getB2DPolygon(a),
126                             getRGBColorA(),
127                             getRGBColorB(),
128                             getDiscreteDashLength()));
129 				}
130 
131 				return aRetval;
132 			}
133 			else
134 			{
135 				return Primitive2DSequence();
136 			}
137 		}
138 
139 		PolyPolygonMarkerPrimitive2D::PolyPolygonMarkerPrimitive2D(
140 			const basegfx::B2DPolyPolygon& rPolyPolygon,
141 			const basegfx::BColor& rRGBColorA,
142 			const basegfx::BColor& rRGBColorB,
143 			double fDiscreteDashLength)
144 		:	BufferedDecompositionPrimitive2D(),
145 			maPolyPolygon(rPolyPolygon),
146 			maRGBColorA(rRGBColorA),
147 			maRGBColorB(rRGBColorB),
148 			mfDiscreteDashLength(fDiscreteDashLength)
149 		{
150 		}
151 
152 		bool PolyPolygonMarkerPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
153 		{
154 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
155 			{
156 				const PolyPolygonMarkerPrimitive2D& rCompare = (PolyPolygonMarkerPrimitive2D&)rPrimitive;
157 
158 				return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
159 					&& getRGBColorA() == rCompare.getRGBColorA()
160 					&& getRGBColorB() == rCompare.getRGBColorB()
161 					&& getDiscreteDashLength() == rCompare.getDiscreteDashLength());
162 			}
163 
164 			return false;
165 		}
166 
167 		basegfx::B2DRange PolyPolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
168 		{
169 			// return range
170 			return basegfx::tools::getRange(getB2DPolyPolygon());
171 		}
172 
173 		// provide unique ID
174 		ImplPrimitrive2DIDBlock(PolyPolygonMarkerPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONMARKERPRIMITIVE2D)
175 
176 	} // end of namespace primitive2d
177 } // end of namespace drawinglayer
178 
179 //////////////////////////////////////////////////////////////////////////////
180 
181 namespace drawinglayer
182 {
183 	namespace primitive2d
184 	{
185 		Primitive2DSequence PolyPolygonStrokePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
186 		{
187 			const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
188 			const sal_uInt32 nCount(aPolyPolygon.count());
189 
190 			if(nCount)
191 			{
192 				Primitive2DSequence aRetval(nCount);
193 
194 				for(sal_uInt32 a(0L); a < nCount; a++)
195 				{
196 					aRetval[a] = Primitive2DReference(
197                         new PolygonStrokePrimitive2D(
198                             aPolyPolygon.getB2DPolygon(a), getLineAttribute(), getStrokeAttribute()));
199 				}
200 
201 				return aRetval;
202 			}
203 			else
204 			{
205 				return Primitive2DSequence();
206 			}
207 		}
208 
209 		PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D(
210 			const basegfx::B2DPolyPolygon& rPolyPolygon,
211   			const attribute::LineAttribute& rLineAttribute,
212 			const attribute::StrokeAttribute& rStrokeAttribute)
213 		:	BufferedDecompositionPrimitive2D(),
214 			maPolyPolygon(rPolyPolygon),
215             maLineAttribute(rLineAttribute),
216 			maStrokeAttribute(rStrokeAttribute)
217 		{
218 		}
219 
220 		PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D(
221 			const basegfx::B2DPolyPolygon& rPolyPolygon,
222   			const attribute::LineAttribute& rLineAttribute)
223 		:	BufferedDecompositionPrimitive2D(),
224 			maPolyPolygon(rPolyPolygon),
225             maLineAttribute(rLineAttribute),
226 			maStrokeAttribute()
227 		{
228 		}
229 
230 		bool PolyPolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
231 		{
232 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
233 			{
234 				const PolyPolygonStrokePrimitive2D& rCompare = (PolyPolygonStrokePrimitive2D&)rPrimitive;
235 
236 				return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
237 					&& getLineAttribute() == rCompare.getLineAttribute()
238 					&& getStrokeAttribute() == rCompare.getStrokeAttribute());
239 			}
240 
241 			return false;
242 		}
243 
244 		basegfx::B2DRange PolyPolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
245 		{
246 			// get range of it (subdivided)
247 			basegfx::B2DRange aRetval(basegfx::tools::getRange(getB2DPolyPolygon()));
248 
249 			// if width, grow by line width
250 			if(getLineAttribute().getWidth())
251 			{
252 				aRetval.grow(getLineAttribute().getWidth() / 2.0);
253 			}
254 
255 			return aRetval;
256 		}
257 
258 		// provide unique ID
259 		ImplPrimitrive2DIDBlock(PolyPolygonStrokePrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONSTROKEPRIMITIVE2D)
260 
261 	} // end of namespace primitive2d
262 } // end of namespace drawinglayer
263 
264 //////////////////////////////////////////////////////////////////////////////
265 
266 namespace drawinglayer
267 {
268 	namespace primitive2d
269 	{
270 		Primitive2DSequence PolyPolygonStrokeArrowPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
271 		{
272 			const basegfx::B2DPolyPolygon aPolyPolygon(getB2DPolyPolygon());
273 			const sal_uInt32 nCount(aPolyPolygon.count());
274 
275 			if(nCount)
276 			{
277 				Primitive2DSequence aRetval(nCount);
278 
279 				for(sal_uInt32 a(0L); a < nCount; a++)
280 				{
281 					const basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(a));
282 
283 					if(aPolygon.isClosed())
284 					{
285 						// no need for PolygonStrokeArrowPrimitive2D when polygon is closed
286 						aRetval[a] = Primitive2DReference(
287                             new PolygonStrokePrimitive2D(aPolygon, getLineAttribute(), getStrokeAttribute()));
288 					}
289 					else
290 					{
291 						aRetval[a] = Primitive2DReference(
292                             new PolygonStrokeArrowPrimitive2D(aPolygon, getLineAttribute(),
293                                 getStrokeAttribute(), getStart(), getEnd()));
294 					}
295 				}
296 
297 				return aRetval;
298 			}
299 			else
300 			{
301 				return Primitive2DSequence();
302 			}
303 		}
304 
305 		PolyPolygonStrokeArrowPrimitive2D::PolyPolygonStrokeArrowPrimitive2D(
306 			const basegfx::B2DPolyPolygon& rPolyPolygon,
307    			const attribute::LineAttribute& rLineAttribute,
308 			const attribute::StrokeAttribute& rStrokeAttribute,
309 			const attribute::LineStartEndAttribute& rStart,
310 			const attribute::LineStartEndAttribute& rEnd)
311 		:	PolyPolygonStrokePrimitive2D(rPolyPolygon, rLineAttribute, rStrokeAttribute),
312 			maStart(rStart),
313 			maEnd(rEnd)
314 		{
315 		}
316 
317 		PolyPolygonStrokeArrowPrimitive2D::PolyPolygonStrokeArrowPrimitive2D(
318 			const basegfx::B2DPolyPolygon& rPolyPolygon,
319    			const attribute::LineAttribute& rLineAttribute,
320 			const attribute::LineStartEndAttribute& rStart,
321 			const attribute::LineStartEndAttribute& rEnd)
322 		:	PolyPolygonStrokePrimitive2D(rPolyPolygon, rLineAttribute),
323 			maStart(rStart),
324 			maEnd(rEnd)
325 		{
326 		}
327 
328 		bool PolyPolygonStrokeArrowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
329 		{
330 			if(PolyPolygonStrokePrimitive2D::operator==(rPrimitive))
331 			{
332 				const PolyPolygonStrokeArrowPrimitive2D& rCompare = (PolyPolygonStrokeArrowPrimitive2D&)rPrimitive;
333 
334 				return (getStart() == rCompare.getStart()
335 					&& getEnd() == rCompare.getEnd());
336 			}
337 
338 			return false;
339 		}
340 
341 		basegfx::B2DRange PolyPolygonStrokeArrowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
342 		{
343 			basegfx::B2DRange aRetval;
344 
345 			if(getStart().isActive() || getEnd().isActive())
346 			{
347 				// use decomposition when line start/end is used
348 				return BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
349 			}
350 			else
351 			{
352 				// get range from parent
353 				return PolyPolygonStrokePrimitive2D::getB2DRange(rViewInformation);
354 			}
355 		}
356 
357 		// provide unique ID
358 		ImplPrimitrive2DIDBlock(PolyPolygonStrokeArrowPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONSTROKEARROWPRIMITIVE2D)
359 
360 	} // end of namespace primitive2d
361 } // end of namespace drawinglayer
362 
363 //////////////////////////////////////////////////////////////////////////////
364 
365 namespace drawinglayer
366 {
367 	namespace primitive2d
368 	{
369 		PolyPolygonColorPrimitive2D::PolyPolygonColorPrimitive2D(
370 			const basegfx::B2DPolyPolygon& rPolyPolygon,
371 			const basegfx::BColor& rBColor)
372 		:	BasePrimitive2D(),
373 			maPolyPolygon(rPolyPolygon),
374 			maBColor(rBColor)
375 		{
376 		}
377 
378 		bool PolyPolygonColorPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
379 		{
380 			if(BasePrimitive2D::operator==(rPrimitive))
381 			{
382 				const PolyPolygonColorPrimitive2D& rCompare = (PolyPolygonColorPrimitive2D&)rPrimitive;
383 
384 				return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
385 					&& getBColor() == rCompare.getBColor());
386 			}
387 
388 			return false;
389 		}
390 
391 		basegfx::B2DRange PolyPolygonColorPrimitive2D::getB2DRange(const geometry::ViewInformation2D& /*rViewInformation*/) const
392 		{
393 			// return range
394 			return basegfx::tools::getRange(getB2DPolyPolygon());
395 		}
396 
397 		// provide unique ID
398 		ImplPrimitrive2DIDBlock(PolyPolygonColorPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D)
399 
400 	} // end of namespace primitive2d
401 } // end of namespace drawinglayer
402 
403 //////////////////////////////////////////////////////////////////////////////
404 
405 namespace drawinglayer
406 {
407 	namespace primitive2d
408 	{
409 		Primitive2DSequence PolyPolygonGradientPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
410 		{
411             if(!getFillGradient().isDefault())
412             {
413 			    // create SubSequence with FillGradientPrimitive2D
414 			    const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
415 			    FillGradientPrimitive2D* pNewGradient = new FillGradientPrimitive2D(aPolyPolygonRange, getFillGradient());
416 			    const Primitive2DReference xSubRef(pNewGradient);
417 			    const Primitive2DSequence aSubSequence(&xSubRef, 1L);
418 
419 			    // create mask primitive
420 			    MaskPrimitive2D* pNewMask = new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence);
421 			    const Primitive2DReference xRef(pNewMask);
422 
423                 return Primitive2DSequence(&xRef, 1);
424             }
425             else
426             {
427                 return Primitive2DSequence();
428             }
429 		}
430 
431 		PolyPolygonGradientPrimitive2D::PolyPolygonGradientPrimitive2D(
432 			const basegfx::B2DPolyPolygon& rPolyPolygon,
433 			const attribute::FillGradientAttribute& rFillGradient)
434 		:	BufferedDecompositionPrimitive2D(),
435 			maPolyPolygon(rPolyPolygon),
436 			maFillGradient(rFillGradient)
437 		{
438 		}
439 
440 		bool PolyPolygonGradientPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
441 		{
442 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
443 			{
444 				const PolyPolygonGradientPrimitive2D& rCompare = (PolyPolygonGradientPrimitive2D&)rPrimitive;
445 
446 				return (getFillGradient() == rCompare.getFillGradient());
447 			}
448 
449 			return false;
450 		}
451 
452 		// provide unique ID
453 		ImplPrimitrive2DIDBlock(PolyPolygonGradientPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D)
454 
455 	} // end of namespace primitive2d
456 } // end of namespace drawinglayer
457 
458 //////////////////////////////////////////////////////////////////////////////
459 
460 namespace drawinglayer
461 {
462 	namespace primitive2d
463 	{
464 		Primitive2DSequence PolyPolygonHatchPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
465 		{
466             if(!getFillHatch().isDefault())
467             {
468 			    // create SubSequence with FillHatchPrimitive2D
469 			    const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
470 			    FillHatchPrimitive2D* pNewHatch = new FillHatchPrimitive2D(aPolyPolygonRange, getBackgroundColor(), getFillHatch());
471 			    const Primitive2DReference xSubRef(pNewHatch);
472 			    const Primitive2DSequence aSubSequence(&xSubRef, 1L);
473 
474 			    // create mask primitive
475 			    MaskPrimitive2D* pNewMask = new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence);
476 			    const Primitive2DReference xRef(pNewMask);
477 
478                 return Primitive2DSequence(&xRef, 1);
479             }
480             else
481             {
482                 return Primitive2DSequence();
483             }
484 		}
485 
486 		PolyPolygonHatchPrimitive2D::PolyPolygonHatchPrimitive2D(
487 			const basegfx::B2DPolyPolygon& rPolyPolygon,
488 			const basegfx::BColor& rBackgroundColor,
489 			const attribute::FillHatchAttribute& rFillHatch)
490 		:	BufferedDecompositionPrimitive2D(),
491 			maPolyPolygon(rPolyPolygon),
492 			maBackgroundColor(rBackgroundColor),
493 			maFillHatch(rFillHatch)
494 		{
495 		}
496 
497 		bool PolyPolygonHatchPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
498 		{
499 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
500 			{
501 				const PolyPolygonHatchPrimitive2D& rCompare = (PolyPolygonHatchPrimitive2D&)rPrimitive;
502 
503 				return (getBackgroundColor() == rCompare.getBackgroundColor()
504 					&& getFillHatch() == rCompare.getFillHatch());
505 			}
506 
507 			return false;
508 		}
509 
510 		// provide unique ID
511 		ImplPrimitrive2DIDBlock(PolyPolygonHatchPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D)
512 
513 	} // end of namespace primitive2d
514 } // end of namespace drawinglayer
515 
516 //////////////////////////////////////////////////////////////////////////////
517 
518 namespace drawinglayer
519 {
520 	namespace primitive2d
521 	{
522 		Primitive2DSequence PolyPolygonGraphicPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
523 		{
524             if(!getFillGraphic().isDefault())
525             {
526                 const Graphic& rGraphic = getFillGraphic().getGraphic();
527                 const GraphicType aType(rGraphic.GetType());
528 
529                 // is there a bitmap or a metafile (do we have content)?
530                 if(GRAPHIC_BITMAP == aType || GRAPHIC_GDIMETAFILE == aType)
531                 {
532                     const Size aPrefSize(rGraphic.GetPrefSize());
533 
534                     // does content have a size?
535                     if(aPrefSize.Width() && aPrefSize.Height())
536                     {
537                         // create SubSequence with FillGraphicPrimitive2D based on polygon range
538                         const basegfx::B2DRange aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
539                         const basegfx::B2DHomMatrix aNewObjectTransform(
540                             basegfx::tools::createScaleTranslateB2DHomMatrix(
541                                 aPolyPolygonRange.getRange(),
542                                 aPolyPolygonRange.getMinimum()));
543                         const Primitive2DReference xSubRef(
544                             new FillGraphicPrimitive2D(
545                                 aNewObjectTransform,
546                                 getFillGraphic()));
547 
548                         // embed to mask primitive
549                         const Primitive2DReference xRef(
550                             new MaskPrimitive2D(
551                                 getB2DPolyPolygon(),
552                                 Primitive2DSequence(&xSubRef, 1)));
553 
554                         return Primitive2DSequence(&xRef, 1);
555                     }
556                 }
557             }
558 
559             return Primitive2DSequence();
560 		}
561 
562 		PolyPolygonGraphicPrimitive2D::PolyPolygonGraphicPrimitive2D(
563 			const basegfx::B2DPolyPolygon& rPolyPolygon,
564 			const attribute::FillGraphicAttribute& rFillGraphic)
565 		:	BufferedDecompositionPrimitive2D(),
566 			maPolyPolygon(rPolyPolygon),
567 			maFillGraphic(rFillGraphic)
568 		{
569 		}
570 
571 		bool PolyPolygonGraphicPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
572 		{
573 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
574 			{
575 				const PolyPolygonGraphicPrimitive2D& rCompare = (PolyPolygonGraphicPrimitive2D&)rPrimitive;
576 
577 				return (getFillGraphic() == rCompare.getFillGraphic());
578 			}
579 
580 			return false;
581 		}
582 
583 		// provide unique ID
584 		ImplPrimitrive2DIDBlock(PolyPolygonGraphicPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D)
585 
586 	} // end of namespace primitive2d
587 } // end of namespace drawinglayer
588 
589 //////////////////////////////////////////////////////////////////////////////
590 
591 namespace drawinglayer
592 {
593     namespace primitive2d
594     {
595         Primitive2DSequence PolyPolygonSelectionPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
596         {
597             Primitive2DSequence aRetval;
598 
599             if(getTransparence() < 1.0 && getB2DPolyPolygon().count())
600             {
601                 if(getFill() && getB2DPolyPolygon().isClosed())
602                 {
603                     // create fill primitive
604                     const Primitive2DReference aFill(
605                         new PolyPolygonColorPrimitive2D(
606                             getB2DPolyPolygon(),
607                             getColor()));
608 
609                     aRetval = Primitive2DSequence(&aFill, 1);
610                 }
611 
612                 if(getDiscreteGrow() > 0.0)
613                 {
614                     const attribute::LineAttribute aLineAttribute(
615                         getColor(),
616                         getDiscreteGrow() * getDiscreteUnit() * 2.0);
617                     const Primitive2DReference aFatLine(
618                         new PolyPolygonStrokePrimitive2D(
619                             getB2DPolyPolygon(),
620                             aLineAttribute));
621 
622                     appendPrimitive2DReferenceToPrimitive2DSequence(aRetval, aFatLine);
623                 }
624 
625                 // embed filled to transparency (if used)
626                 if(aRetval.getLength() && getTransparence() > 0.0)
627                 {
628                     const Primitive2DReference aTrans(
629                         new UnifiedTransparencePrimitive2D(
630                             aRetval,
631                             getTransparence()));
632 
633                     aRetval = Primitive2DSequence(&aTrans, 1);
634                 }
635             }
636 
637             return aRetval;
638         }
639 
640         PolyPolygonSelectionPrimitive2D::PolyPolygonSelectionPrimitive2D(
641             const basegfx::B2DPolyPolygon& rPolyPolygon,
642             const basegfx::BColor& rColor,
643             double fTransparence,
644             double fDiscreteGrow,
645             bool bFill)
646         :   DiscreteMetricDependentPrimitive2D(),
647             maPolyPolygon(rPolyPolygon),
648             maColor(rColor),
649             mfTransparence(fTransparence),
650             mfDiscreteGrow(fabs(fDiscreteGrow)),
651             mbFill(bFill)
652         {
653         }
654 
655         bool PolyPolygonSelectionPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
656         {
657             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
658             {
659                 const PolyPolygonSelectionPrimitive2D& rCompare = (PolyPolygonSelectionPrimitive2D&)rPrimitive;
660 
661                 return (getB2DPolyPolygon() == rCompare.getB2DPolyPolygon()
662                     && getColor() == rCompare.getColor()
663                     && getTransparence() == rCompare.getTransparence()
664                     && getDiscreteGrow() == rCompare.getDiscreteGrow()
665                     && getFill() == rCompare.getFill());
666             }
667 
668             return false;
669         }
670 
671         basegfx::B2DRange PolyPolygonSelectionPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
672         {
673             basegfx::B2DRange aRetval(basegfx::tools::getRange(getB2DPolyPolygon()));
674 
675             if(getDiscreteGrow() > 0.0)
676             {
677                 // get the current DiscreteUnit (not sure if getDiscreteUnit() is updated here, better go safe way)
678                 const double fDiscreteUnit((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
679 
680                 aRetval.grow(fDiscreteUnit * getDiscreteGrow());
681             }
682 
683             return aRetval;
684         }
685 
686         // provide unique ID
687         ImplPrimitrive2DIDBlock(PolyPolygonSelectionPrimitive2D, PRIMITIVE2D_ID_POLYPOLYGONSELECTIONPRIMITIVE2D)
688 
689     } // end of namespace primitive2d
690 } // end of namespace drawinglayer
691 
692 //////////////////////////////////////////////////////////////////////////////
693 // eof
694