1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
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>
36 using namespace com::sun::star
;
39 namespace drawinglayer
43 void PolyPolygonHairlinePrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& /*rViewInformation*/) const
45 const basegfx::B2DPolyPolygon
aPolyPolygon(getB2DPolyPolygon());
46 const sal_uInt32
nCount(aPolyPolygon
.count());
50 for(sal_uInt32
a(0); a
< nCount
; a
++)
52 rContainer
.push_back(new PolygonHairlinePrimitive2D(aPolyPolygon
.getB2DPolygon(a
), getBColor()));
57 PolyPolygonHairlinePrimitive2D::PolyPolygonHairlinePrimitive2D(const basegfx::B2DPolyPolygon
& rPolyPolygon
, const basegfx::BColor
& rBColor
)
58 : BufferedDecompositionPrimitive2D(),
59 maPolyPolygon(rPolyPolygon
),
64 bool PolyPolygonHairlinePrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
66 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive
))
68 const PolyPolygonHairlinePrimitive2D
& rCompare
= static_cast<const PolyPolygonHairlinePrimitive2D
&>(rPrimitive
);
70 return (getB2DPolyPolygon() == rCompare
.getB2DPolyPolygon()
71 && getBColor() == rCompare
.getBColor());
77 basegfx::B2DRange
PolyPolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D
& /*rViewInformation*/) const
80 return basegfx::utils::getRange(getB2DPolyPolygon());
84 ImplPrimitive2DIDBlock(PolyPolygonHairlinePrimitive2D
, PRIMITIVE2D_ID_POLYPOLYGONHAIRLINEPRIMITIVE2D
)
86 } // end of namespace primitive2d
87 } // end of namespace drawinglayer
90 namespace drawinglayer
94 void PolyPolygonMarkerPrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& /*rViewInformation*/) const
96 const basegfx::B2DPolyPolygon
aPolyPolygon(getB2DPolyPolygon());
97 const sal_uInt32
nCount(aPolyPolygon
.count());
101 for(sal_uInt32
a(0); a
< nCount
; a
++)
103 rContainer
.push_back(
104 new PolygonMarkerPrimitive2D(
105 aPolyPolygon
.getB2DPolygon(a
),
108 getDiscreteDashLength()));
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
)
126 bool PolyPolygonMarkerPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
128 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive
))
130 const PolyPolygonMarkerPrimitive2D
& rCompare
= static_cast<const PolyPolygonMarkerPrimitive2D
&>(rPrimitive
);
132 return (getB2DPolyPolygon() == rCompare
.getB2DPolyPolygon()
133 && getRGBColorA() == rCompare
.getRGBColorA()
134 && getRGBColorB() == rCompare
.getRGBColorB()
135 && getDiscreteDashLength() == rCompare
.getDiscreteDashLength());
141 basegfx::B2DRange
PolyPolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D
& /*rViewInformation*/) const
144 return basegfx::utils::getRange(getB2DPolyPolygon());
148 ImplPrimitive2DIDBlock(PolyPolygonMarkerPrimitive2D
, PRIMITIVE2D_ID_POLYPOLYGONMARKERPRIMITIVE2D
)
150 } // end of namespace primitive2d
151 } // end of namespace drawinglayer
154 namespace drawinglayer
156 namespace primitive2d
158 void PolyPolygonStrokePrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& /*rViewInformation*/) const
160 const basegfx::B2DPolyPolygon
aPolyPolygon(getB2DPolyPolygon());
161 const sal_uInt32
nCount(aPolyPolygon
.count());
165 for(sal_uInt32
a(0); a
< nCount
; a
++)
167 rContainer
.push_back(
168 new PolygonStrokePrimitive2D(
169 aPolyPolygon
.getB2DPolygon(a
), getLineAttribute(), getStrokeAttribute()));
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
)
185 PolyPolygonStrokePrimitive2D::PolyPolygonStrokePrimitive2D(
186 const basegfx::B2DPolyPolygon
& rPolyPolygon
,
187 const attribute::LineAttribute
& rLineAttribute
)
188 : BufferedDecompositionPrimitive2D(),
189 maPolyPolygon(rPolyPolygon
),
190 maLineAttribute(rLineAttribute
),
195 bool PolyPolygonStrokePrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
197 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive
))
199 const PolyPolygonStrokePrimitive2D
& rCompare
= static_cast<const PolyPolygonStrokePrimitive2D
&>(rPrimitive
);
201 return (getB2DPolyPolygon() == rCompare
.getB2DPolyPolygon()
202 && getLineAttribute() == rCompare
.getLineAttribute()
203 && getStrokeAttribute() == rCompare
.getStrokeAttribute());
209 basegfx::B2DRange
PolyPolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D
& /*rViewInformation*/) const
211 // get range of it (subdivided)
212 basegfx::B2DRange
aRetval(basegfx::utils::getRange(getB2DPolyPolygon()));
214 // if width, grow by line width
215 if(getLineAttribute().getWidth())
217 aRetval
.grow(getLineAttribute().getWidth() / 2.0);
224 ImplPrimitive2DIDBlock(PolyPolygonStrokePrimitive2D
, PRIMITIVE2D_ID_POLYPOLYGONSTROKEPRIMITIVE2D
)
226 } // end of namespace primitive2d
227 } // end of namespace drawinglayer
230 namespace drawinglayer
232 namespace primitive2d
234 PolyPolygonColorPrimitive2D::PolyPolygonColorPrimitive2D(
235 const basegfx::B2DPolyPolygon
& rPolyPolygon
,
236 const basegfx::BColor
& rBColor
)
238 maPolyPolygon(rPolyPolygon
),
243 bool PolyPolygonColorPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
245 if(BasePrimitive2D::operator==(rPrimitive
))
247 const PolyPolygonColorPrimitive2D
& rCompare
= static_cast<const PolyPolygonColorPrimitive2D
&>(rPrimitive
);
249 return (getB2DPolyPolygon() == rCompare
.getB2DPolyPolygon()
250 && getBColor() == rCompare
.getBColor());
256 basegfx::B2DRange
PolyPolygonColorPrimitive2D::getB2DRange(const geometry::ViewInformation2D
& /*rViewInformation*/) const
259 return basegfx::utils::getRange(getB2DPolyPolygon());
263 ImplPrimitive2DIDBlock(PolyPolygonColorPrimitive2D
, PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D
)
265 } // end of namespace primitive2d
266 } // end of namespace drawinglayer
269 namespace drawinglayer
271 namespace primitive2d
273 void PolyPolygonGradientPrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& /*rViewInformation*/) const
275 if(!getFillGradient().isDefault())
277 // create SubSequence with FillGradientPrimitive2D
278 const basegfx::B2DRange
aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
279 FillGradientPrimitive2D
* pNewGradient
= new FillGradientPrimitive2D(
281 getDefinitionRange(),
283 const Primitive2DReference
xSubRef(pNewGradient
);
284 const Primitive2DContainer aSubSequence
{ xSubRef
};
286 // create mask primitive
287 rContainer
.push_back(new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence
));
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
)
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
)
312 bool PolyPolygonGradientPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
314 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive
))
316 const PolyPolygonGradientPrimitive2D
& rCompare
= static_cast<const PolyPolygonGradientPrimitive2D
&>(rPrimitive
);
318 return (getB2DPolyPolygon() == rCompare
.getB2DPolyPolygon()
319 && getDefinitionRange() == rCompare
.getDefinitionRange()
320 && getFillGradient() == rCompare
.getFillGradient());
327 ImplPrimitive2DIDBlock(PolyPolygonGradientPrimitive2D
, PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D
)
329 } // end of namespace primitive2d
330 } // end of namespace drawinglayer
333 namespace drawinglayer
335 namespace primitive2d
337 void PolyPolygonHatchPrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& /*rViewInformation*/) const
339 if(!getFillHatch().isDefault())
341 // create SubSequence with FillHatchPrimitive2D
342 const basegfx::B2DRange
aPolyPolygonRange(getB2DPolyPolygon().getB2DRange());
343 FillHatchPrimitive2D
* pNewHatch
= new FillHatchPrimitive2D(
345 getDefinitionRange(),
346 getBackgroundColor(),
348 const Primitive2DReference
xSubRef(pNewHatch
);
349 const Primitive2DContainer aSubSequence
{ xSubRef
};
351 // create mask primitive
352 rContainer
.push_back(new MaskPrimitive2D(getB2DPolyPolygon(), aSubSequence
));
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
)
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
)
381 bool PolyPolygonHatchPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
383 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive
))
385 const PolyPolygonHatchPrimitive2D
& rCompare
= static_cast<const PolyPolygonHatchPrimitive2D
&>(rPrimitive
);
387 return (getB2DPolyPolygon() == rCompare
.getB2DPolyPolygon()
388 && getDefinitionRange() == rCompare
.getDefinitionRange()
389 && getBackgroundColor() == rCompare
.getBackgroundColor()
390 && getFillHatch() == rCompare
.getFillHatch());
397 ImplPrimitive2DIDBlock(PolyPolygonHatchPrimitive2D
, PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D
)
399 } // end of namespace primitive2d
400 } // end of namespace drawinglayer
403 namespace drawinglayer
405 namespace primitive2d
407 void PolyPolygonGraphicPrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& /*rViewInformation*/) const
409 if(!getFillGraphic().isDefault())
411 const Graphic
& rGraphic
= getFillGraphic().getGraphic();
412 const GraphicType
aType(rGraphic
.GetType());
414 // is there a bitmap or a metafile (do we have content)?
415 if(GraphicType::Bitmap
== aType
|| GraphicType::GdiMetafile
== aType
)
417 const Size
aPrefSize(rGraphic
.GetPrefSize());
419 // does content have a size?
420 if(aPrefSize
.Width() && aPrefSize
.Height())
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
;
430 if(aOutRange
!= getDefinitionRange())
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());
441 const basegfx::B2DHomMatrix
aFromDefinitionRangeToGlobal(
442 basegfx::utils::createScaleTranslateB2DHomMatrix(
443 getDefinitionRange().getRange(),
444 getDefinitionRange().getMinimum()));
446 aAdaptedRange
.transform(aFromDefinitionRangeToGlobal
);
448 basegfx::B2DHomMatrix
aFromGlobalToOutRange(
449 basegfx::utils::createScaleTranslateB2DHomMatrix(
450 aOutRange
.getRange(),
451 aOutRange
.getMinimum()));
452 aFromGlobalToOutRange
.invert();
454 aAdaptedRange
.transform(aFromGlobalToOutRange
);
456 const drawinglayer::attribute::FillGraphicAttribute
aAdaptedFillGraphicAttribute(
457 getFillGraphic().getGraphic(),
459 getFillGraphic().getTiling(),
460 getFillGraphic().getOffsetX(),
461 getFillGraphic().getOffsetY());
463 xSubRef
= new FillGraphicPrimitive2D(
465 aAdaptedFillGraphicAttribute
);
469 xSubRef
= new FillGraphicPrimitive2D(
474 // embed to mask primitive
475 rContainer
.push_back(
478 Primitive2DContainer
{ xSubRef
}));
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
)
495 bool PolyPolygonGraphicPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
497 if(BufferedDecompositionPrimitive2D::operator==(rPrimitive
))
499 const PolyPolygonGraphicPrimitive2D
& rCompare
= static_cast<const PolyPolygonGraphicPrimitive2D
&>(rPrimitive
);
501 return (getB2DPolyPolygon() == rCompare
.getB2DPolyPolygon()
502 && getDefinitionRange() == rCompare
.getDefinitionRange()
503 && getFillGraphic() == rCompare
.getFillGraphic());
510 ImplPrimitive2DIDBlock(PolyPolygonGraphicPrimitive2D
, PRIMITIVE2D_ID_POLYPOLYGONGRAPHICPRIMITIVE2D
)
512 } // end of namespace primitive2d
513 } // end of namespace drawinglayer
516 namespace drawinglayer
518 namespace primitive2d
520 void PolyPolygonSelectionPrimitive2D::create2DDecomposition(Primitive2DContainer
& rContainer
, const geometry::ViewInformation2D
& /*rViewInformation*/) const
522 if(getTransparence() >= 1.0 || !getB2DPolyPolygon().count())
525 Primitive2DContainer aRetval
;
527 if(getFill() && getB2DPolyPolygon().isClosed())
529 // create fill primitive
530 const Primitive2DReference
aFill(
531 new PolyPolygonColorPrimitive2D(
535 aRetval
= Primitive2DContainer
{ aFill
};
538 if(getDiscreteGrow() > 0.0)
540 const attribute::LineAttribute
aLineAttribute(
542 getDiscreteGrow() * getDiscreteUnit() * 2.0);
543 const Primitive2DReference
aFatLine(
544 new PolyPolygonStrokePrimitive2D(
548 aRetval
.push_back(aFatLine
);
551 // embed filled to transparency (if used)
552 if(!aRetval
.empty() && getTransparence() > 0.0)
554 const Primitive2DReference
aTrans(
555 new UnifiedTransparencePrimitive2D(
559 aRetval
= Primitive2DContainer
{ aTrans
};
562 rContainer
.insert(rContainer
.end(), aRetval
.begin(), aRetval
.end());
565 PolyPolygonSelectionPrimitive2D::PolyPolygonSelectionPrimitive2D(
566 const basegfx::B2DPolyPolygon
& rPolyPolygon
,
567 const basegfx::BColor
& rColor
,
568 double fTransparence
,
569 double fDiscreteGrow
,
571 : DiscreteMetricDependentPrimitive2D(),
572 maPolyPolygon(rPolyPolygon
),
574 mfTransparence(fTransparence
),
575 mfDiscreteGrow(fabs(fDiscreteGrow
)),
580 bool PolyPolygonSelectionPrimitive2D::operator==(const BasePrimitive2D
& rPrimitive
) const
582 if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive
))
584 const PolyPolygonSelectionPrimitive2D
& rCompare
= static_cast<const PolyPolygonSelectionPrimitive2D
&>(rPrimitive
);
586 return (getB2DPolyPolygon() == rCompare
.getB2DPolyPolygon()
587 && getColor() == rCompare
.getColor()
588 && getTransparence() == rCompare
.getTransparence()
589 && getDiscreteGrow() == rCompare
.getDiscreteGrow()
590 && getFill() == rCompare
.getFill());
596 basegfx::B2DRange
PolyPolygonSelectionPrimitive2D::getB2DRange(const geometry::ViewInformation2D
& rViewInformation
) const
598 basegfx::B2DRange
aRetval(basegfx::utils::getRange(getB2DPolyPolygon()));
600 if(getDiscreteGrow() > 0.0)
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());
605 aRetval
.grow(fDiscreteUnit
* getDiscreteGrow());
612 ImplPrimitive2DIDBlock(PolyPolygonSelectionPrimitive2D
, PRIMITIVE2D_ID_POLYPOLYGONSELECTIONPRIMITIVE2D
)
614 } // end of namespace primitive2d
615 } // end of namespace drawinglayer
617 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */