1464702f4SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3464702f4SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4464702f4SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5464702f4SAndrew Rist  * distributed with this work for additional information
6464702f4SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7464702f4SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8464702f4SAndrew Rist  * "License"); you may not use this file except in compliance
9464702f4SAndrew Rist  * with the License.  You may obtain a copy of the License at
10464702f4SAndrew Rist  *
11464702f4SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12464702f4SAndrew Rist  *
13464702f4SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14464702f4SAndrew Rist  * software distributed under the License is distributed on an
15464702f4SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16464702f4SAndrew Rist  * KIND, either express or implied.  See the License for the
17464702f4SAndrew Rist  * specific language governing permissions and limitations
18464702f4SAndrew Rist  * under the License.
19464702f4SAndrew Rist  *
20464702f4SAndrew Rist  *************************************************************/
21464702f4SAndrew Rist 
22464702f4SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_drawinglayer.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
28cdf0e10cSrcweir #include <basegfx/tools/canvastools.hxx>
29cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
30cdf0e10cSrcweir #include <basegfx/polygon/b2dpolypolygontools.hxx>
31cdf0e10cSrcweir #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
32cdf0e10cSrcweir #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
33cdf0e10cSrcweir #include <drawinglayer/geometry/viewinformation2d.hxx>
34cdf0e10cSrcweir #include <basegfx/polygon/b2dlinegeometry.hxx>
355aaf853bSArmin Le Grand #include <com/sun/star/drawing/LineCap.hpp>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
38cdf0e10cSrcweir 
39cdf0e10cSrcweir using namespace com::sun::star;
40cdf0e10cSrcweir 
41cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
42cdf0e10cSrcweir 
43cdf0e10cSrcweir namespace drawinglayer
44cdf0e10cSrcweir {
45cdf0e10cSrcweir 	namespace primitive2d
46cdf0e10cSrcweir 	{
PolygonHairlinePrimitive2D(const basegfx::B2DPolygon & rPolygon,const basegfx::BColor & rBColor)47cdf0e10cSrcweir 		PolygonHairlinePrimitive2D::PolygonHairlinePrimitive2D(
48cdf0e10cSrcweir 			const basegfx::B2DPolygon& rPolygon,
49cdf0e10cSrcweir 			const basegfx::BColor& rBColor)
50cdf0e10cSrcweir 		:	BasePrimitive2D(),
51cdf0e10cSrcweir 			maPolygon(rPolygon),
52cdf0e10cSrcweir 			maBColor(rBColor)
53cdf0e10cSrcweir 		{
54cdf0e10cSrcweir 		}
55cdf0e10cSrcweir 
operator ==(const BasePrimitive2D & rPrimitive) const56cdf0e10cSrcweir 		bool PolygonHairlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
57cdf0e10cSrcweir 		{
58cdf0e10cSrcweir 			if(BasePrimitive2D::operator==(rPrimitive))
59cdf0e10cSrcweir 			{
60cdf0e10cSrcweir 				const PolygonHairlinePrimitive2D& rCompare = (PolygonHairlinePrimitive2D&)rPrimitive;
61cdf0e10cSrcweir 
62cdf0e10cSrcweir 				return (getB2DPolygon() == rCompare.getB2DPolygon()
63cdf0e10cSrcweir 					&& getBColor() == rCompare.getBColor());
64cdf0e10cSrcweir 			}
65cdf0e10cSrcweir 
66cdf0e10cSrcweir 			return false;
67cdf0e10cSrcweir 		}
68cdf0e10cSrcweir 
getB2DRange(const geometry::ViewInformation2D & rViewInformation) const69cdf0e10cSrcweir 		basegfx::B2DRange PolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
70cdf0e10cSrcweir 		{
71cdf0e10cSrcweir             // this is a hairline, thus the line width is view-dependent. Get range of polygon
72cdf0e10cSrcweir             // as base size
73cdf0e10cSrcweir 	        basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange());
74cdf0e10cSrcweir 
75cdf0e10cSrcweir             if(!aRetval.isEmpty())
76cdf0e10cSrcweir             {
77cdf0e10cSrcweir                 // Calculate view-dependent hairline width
78cdf0e10cSrcweir                 const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
79cdf0e10cSrcweir                 const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
80cdf0e10cSrcweir 
81cdf0e10cSrcweir                 if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
82cdf0e10cSrcweir                 {
83cdf0e10cSrcweir 		            aRetval.grow(fDiscreteHalfLineWidth);
84cdf0e10cSrcweir                 }
85cdf0e10cSrcweir             }
86cdf0e10cSrcweir 
87cdf0e10cSrcweir             // return range
88cdf0e10cSrcweir 			return aRetval;
89cdf0e10cSrcweir 		}
90cdf0e10cSrcweir 
91cdf0e10cSrcweir 		// provide unique ID
92cdf0e10cSrcweir 		ImplPrimitrive2DIDBlock(PolygonHairlinePrimitive2D, PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D)
93cdf0e10cSrcweir 
94cdf0e10cSrcweir 	} // end of namespace primitive2d
95cdf0e10cSrcweir } // end of namespace drawinglayer
96cdf0e10cSrcweir 
97cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
98cdf0e10cSrcweir 
99cdf0e10cSrcweir namespace drawinglayer
100cdf0e10cSrcweir {
101cdf0e10cSrcweir 	namespace primitive2d
102cdf0e10cSrcweir 	{
create2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const103cdf0e10cSrcweir 		Primitive2DSequence PolygonMarkerPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
104cdf0e10cSrcweir 		{
105cdf0e10cSrcweir 			// calculate logic DashLength
106cdf0e10cSrcweir 			const basegfx::B2DVector aDashVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(getDiscreteDashLength(), 0.0));
107cdf0e10cSrcweir 			const double fLogicDashLength(aDashVector.getX());
108cdf0e10cSrcweir 
109cdf0e10cSrcweir 			if(fLogicDashLength > 0.0 && !getRGBColorA().equal(getRGBColorB()))
110cdf0e10cSrcweir 			{
111cdf0e10cSrcweir 				// apply dashing; get line and gap snippets
112cdf0e10cSrcweir 				::std::vector< double > aDash;
113cdf0e10cSrcweir 				basegfx::B2DPolyPolygon aDashedPolyPolyA;
114cdf0e10cSrcweir 				basegfx::B2DPolyPolygon aDashedPolyPolyB;
115cdf0e10cSrcweir 
116cdf0e10cSrcweir 				aDash.push_back(fLogicDashLength);
117cdf0e10cSrcweir 				aDash.push_back(fLogicDashLength);
118cdf0e10cSrcweir 				basegfx::tools::applyLineDashing(getB2DPolygon(), aDash, &aDashedPolyPolyA, &aDashedPolyPolyB, 2.0 * fLogicDashLength);
119cdf0e10cSrcweir 
120cdf0e10cSrcweir 				// prepare return value
121cdf0e10cSrcweir 				Primitive2DSequence aRetval(2);
122cdf0e10cSrcweir 
123cdf0e10cSrcweir 				aRetval[0] = Primitive2DReference(new PolyPolygonHairlinePrimitive2D(aDashedPolyPolyA, getRGBColorA()));
124cdf0e10cSrcweir 				aRetval[1] = Primitive2DReference(new PolyPolygonHairlinePrimitive2D(aDashedPolyPolyB, getRGBColorB()));
125cdf0e10cSrcweir 
126cdf0e10cSrcweir 				return aRetval;
127cdf0e10cSrcweir 			}
128cdf0e10cSrcweir 			else
129cdf0e10cSrcweir 			{
130cdf0e10cSrcweir 				const Primitive2DReference xRef(new PolygonHairlinePrimitive2D(getB2DPolygon(), getRGBColorA()));
131cdf0e10cSrcweir 				return Primitive2DSequence(&xRef, 1L);
132cdf0e10cSrcweir 			}
133cdf0e10cSrcweir 		}
134cdf0e10cSrcweir 
PolygonMarkerPrimitive2D(const basegfx::B2DPolygon & rPolygon,const basegfx::BColor & rRGBColorA,const basegfx::BColor & rRGBColorB,double fDiscreteDashLength)135cdf0e10cSrcweir 		PolygonMarkerPrimitive2D::PolygonMarkerPrimitive2D(
136cdf0e10cSrcweir 			const basegfx::B2DPolygon& rPolygon,
137cdf0e10cSrcweir 			const basegfx::BColor& rRGBColorA,
138cdf0e10cSrcweir 			const basegfx::BColor& rRGBColorB,
139cdf0e10cSrcweir 			double fDiscreteDashLength)
140cdf0e10cSrcweir 		:	BufferedDecompositionPrimitive2D(),
141cdf0e10cSrcweir 			maPolygon(rPolygon),
142cdf0e10cSrcweir 			maRGBColorA(rRGBColorA),
143cdf0e10cSrcweir 			maRGBColorB(rRGBColorB),
144cdf0e10cSrcweir 			mfDiscreteDashLength(fDiscreteDashLength),
145cdf0e10cSrcweir 			maLastInverseObjectToViewTransformation()
146cdf0e10cSrcweir 		{
147cdf0e10cSrcweir 		}
148cdf0e10cSrcweir 
operator ==(const BasePrimitive2D & rPrimitive) const149cdf0e10cSrcweir 		bool PolygonMarkerPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
150cdf0e10cSrcweir 		{
151cdf0e10cSrcweir 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
152cdf0e10cSrcweir 			{
153cdf0e10cSrcweir 				const PolygonMarkerPrimitive2D& rCompare = (PolygonMarkerPrimitive2D&)rPrimitive;
154cdf0e10cSrcweir 
155cdf0e10cSrcweir 				return (getB2DPolygon() == rCompare.getB2DPolygon()
156cdf0e10cSrcweir 					&& getRGBColorA() == rCompare.getRGBColorA()
157cdf0e10cSrcweir 					&& getRGBColorB() == rCompare.getRGBColorB()
158cdf0e10cSrcweir 					&& getDiscreteDashLength() == rCompare.getDiscreteDashLength());
159cdf0e10cSrcweir 			}
160cdf0e10cSrcweir 
161cdf0e10cSrcweir 			return false;
162cdf0e10cSrcweir 		}
163cdf0e10cSrcweir 
getB2DRange(const geometry::ViewInformation2D & rViewInformation) const164cdf0e10cSrcweir 		basegfx::B2DRange PolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
165cdf0e10cSrcweir 		{
166cdf0e10cSrcweir             // this is a hairline, thus the line width is view-dependent. Get range of polygon
167cdf0e10cSrcweir             // as base size
168cdf0e10cSrcweir 	        basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange());
169cdf0e10cSrcweir 
170cdf0e10cSrcweir             if(!aRetval.isEmpty())
171cdf0e10cSrcweir             {
172cdf0e10cSrcweir                 // Calculate view-dependent hairline width
173cdf0e10cSrcweir                 const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
174cdf0e10cSrcweir                 const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
175cdf0e10cSrcweir 
176cdf0e10cSrcweir                 if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
177cdf0e10cSrcweir                 {
178cdf0e10cSrcweir 		            aRetval.grow(fDiscreteHalfLineWidth);
179cdf0e10cSrcweir                 }
180cdf0e10cSrcweir             }
181cdf0e10cSrcweir 
182cdf0e10cSrcweir             // return range
183cdf0e10cSrcweir 			return aRetval;
184cdf0e10cSrcweir 		}
185cdf0e10cSrcweir 
get2DDecomposition(const geometry::ViewInformation2D & rViewInformation) const186cdf0e10cSrcweir 		Primitive2DSequence PolygonMarkerPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
187cdf0e10cSrcweir 		{
188cdf0e10cSrcweir 			::osl::MutexGuard aGuard( m_aMutex );
189cdf0e10cSrcweir 			bool bNeedNewDecomposition(false);
190cdf0e10cSrcweir 
191cdf0e10cSrcweir 			if(getBuffered2DDecomposition().hasElements())
192cdf0e10cSrcweir 			{
193cdf0e10cSrcweir 				if(rViewInformation.getInverseObjectToViewTransformation() != maLastInverseObjectToViewTransformation)
194cdf0e10cSrcweir 				{
195cdf0e10cSrcweir 					bNeedNewDecomposition = true;
196cdf0e10cSrcweir 				}
197cdf0e10cSrcweir 			}
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 			if(bNeedNewDecomposition)
200cdf0e10cSrcweir 			{
201cdf0e10cSrcweir 				// conditions of last local decomposition have changed, delete
202cdf0e10cSrcweir 				const_cast< PolygonMarkerPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
203cdf0e10cSrcweir 			}
204cdf0e10cSrcweir 
205cdf0e10cSrcweir 			if(!getBuffered2DDecomposition().hasElements())
206cdf0e10cSrcweir 			{
207cdf0e10cSrcweir 				// remember last used InverseObjectToViewTransformation
208cdf0e10cSrcweir 				PolygonMarkerPrimitive2D* pThat = const_cast< PolygonMarkerPrimitive2D* >(this);
209cdf0e10cSrcweir 				pThat->maLastInverseObjectToViewTransformation = rViewInformation.getInverseObjectToViewTransformation();
210cdf0e10cSrcweir 			}
211cdf0e10cSrcweir 
212cdf0e10cSrcweir 			// use parent implementation
213cdf0e10cSrcweir 			return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
214cdf0e10cSrcweir 		}
215cdf0e10cSrcweir 
216cdf0e10cSrcweir 		// provide unique ID
217cdf0e10cSrcweir 		ImplPrimitrive2DIDBlock(PolygonMarkerPrimitive2D, PRIMITIVE2D_ID_POLYGONMARKERPRIMITIVE2D)
218cdf0e10cSrcweir 
219cdf0e10cSrcweir 	} // end of namespace primitive2d
220cdf0e10cSrcweir } // end of namespace drawinglayer
221cdf0e10cSrcweir 
222cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
223cdf0e10cSrcweir 
224cdf0e10cSrcweir namespace drawinglayer
225cdf0e10cSrcweir {
226cdf0e10cSrcweir 	namespace primitive2d
227cdf0e10cSrcweir 	{
create2DDecomposition(const geometry::ViewInformation2D &) const228cdf0e10cSrcweir 		Primitive2DSequence PolygonStrokePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
229cdf0e10cSrcweir 		{
230cdf0e10cSrcweir 			if(getB2DPolygon().count())
231cdf0e10cSrcweir 			{
232cdf0e10cSrcweir                 // #i102241# try to simplify before usage
233cdf0e10cSrcweir                 const basegfx::B2DPolygon aB2DPolygon(basegfx::tools::simplifyCurveSegments(getB2DPolygon()));
234cdf0e10cSrcweir 				basegfx::B2DPolyPolygon aHairLinePolyPolygon;
235cdf0e10cSrcweir 
236cdf0e10cSrcweir 				if(getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen())
237cdf0e10cSrcweir 				{
238cdf0e10cSrcweir                     // no line dashing, just copy
239cdf0e10cSrcweir 					aHairLinePolyPolygon.append(aB2DPolygon);
240cdf0e10cSrcweir 				}
241cdf0e10cSrcweir 				else
242cdf0e10cSrcweir 				{
243cdf0e10cSrcweir 				    // apply LineStyle
244cdf0e10cSrcweir 				    basegfx::tools::applyLineDashing(
245cdf0e10cSrcweir                         aB2DPolygon, getStrokeAttribute().getDotDashArray(),
246cdf0e10cSrcweir                         &aHairLinePolyPolygon, 0, getStrokeAttribute().getFullDotDashLen());
247cdf0e10cSrcweir 				}
248cdf0e10cSrcweir 
249cdf0e10cSrcweir                 const sal_uInt32 nCount(aHairLinePolyPolygon.count());
250cdf0e10cSrcweir 
251cdf0e10cSrcweir                 if(!getLineAttribute().isDefault() && getLineAttribute().getWidth())
252cdf0e10cSrcweir 				{
253cdf0e10cSrcweir                     // create fat line data
254cdf0e10cSrcweir 					const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0);
255cdf0e10cSrcweir 					const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin());
2565aaf853bSArmin Le Grand                     const com::sun::star::drawing::LineCap aLineCap(getLineAttribute().getLineCap());
257cdf0e10cSrcweir 					basegfx::B2DPolyPolygon aAreaPolyPolygon;
258cdf0e10cSrcweir 
259cdf0e10cSrcweir 					for(sal_uInt32 a(0L); a < nCount; a++)
260cdf0e10cSrcweir 					{
261cdf0e10cSrcweir                         // New version of createAreaGeometry; now creates bezier polygons
262cdf0e10cSrcweir                         aAreaPolyPolygon.append(basegfx::tools::createAreaGeometry(
2635aaf853bSArmin Le Grand 							aHairLinePolyPolygon.getB2DPolygon(a),
2645aaf853bSArmin Le Grand                             fHalfLineWidth,
2655aaf853bSArmin Le Grand                             aLineJoin,
2665aaf853bSArmin Le Grand                             aLineCap));
267cdf0e10cSrcweir 					}
268cdf0e10cSrcweir 
269cdf0e10cSrcweir 					// prepare return value
270cdf0e10cSrcweir 					Primitive2DSequence aRetval(aAreaPolyPolygon.count());
271cdf0e10cSrcweir 
272cdf0e10cSrcweir 					// create primitive
273cdf0e10cSrcweir 					for(sal_uInt32 b(0L); b < aAreaPolyPolygon.count(); b++)
274cdf0e10cSrcweir 					{
275cdf0e10cSrcweir 						// put into single polyPolygon primitives to make clear that this is NOT meant
276cdf0e10cSrcweir 						// to be painted as a single PolyPolygon (XORed as fill rule). Alternatively, a
277cdf0e10cSrcweir 						// melting process may be used here one day.
278cdf0e10cSrcweir 						const basegfx::B2DPolyPolygon aNewPolyPolygon(aAreaPolyPolygon.getB2DPolygon(b));
279cdf0e10cSrcweir     					static bool bTestByUsingRandomColor(false);
280cdf0e10cSrcweir                         const basegfx::BColor aColor(bTestByUsingRandomColor
281cdf0e10cSrcweir                             ? basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)
282cdf0e10cSrcweir                             : getLineAttribute().getColor());
283cdf0e10cSrcweir 						const Primitive2DReference xRef(new PolyPolygonColorPrimitive2D(aNewPolyPolygon, aColor));
284cdf0e10cSrcweir 						aRetval[b] = xRef;
285cdf0e10cSrcweir 					}
286cdf0e10cSrcweir 
287cdf0e10cSrcweir 					return aRetval;
288cdf0e10cSrcweir 				}
289cdf0e10cSrcweir 				else
290cdf0e10cSrcweir 				{
291cdf0e10cSrcweir 					// prepare return value
292cdf0e10cSrcweir 					const Primitive2DReference xRef(
293cdf0e10cSrcweir                         new PolyPolygonHairlinePrimitive2D(
294cdf0e10cSrcweir                             aHairLinePolyPolygon,
295cdf0e10cSrcweir                             getLineAttribute().getColor()));
296cdf0e10cSrcweir 
297cdf0e10cSrcweir                     return Primitive2DSequence(&xRef, 1);
298cdf0e10cSrcweir 				}
299cdf0e10cSrcweir 			}
300cdf0e10cSrcweir 			else
301cdf0e10cSrcweir 			{
302cdf0e10cSrcweir 				return Primitive2DSequence();
303cdf0e10cSrcweir 			}
304cdf0e10cSrcweir 		}
305cdf0e10cSrcweir 
PolygonStrokePrimitive2D(const basegfx::B2DPolygon & rPolygon,const attribute::LineAttribute & rLineAttribute,const attribute::StrokeAttribute & rStrokeAttribute)306cdf0e10cSrcweir 		PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(
307cdf0e10cSrcweir 			const basegfx::B2DPolygon& rPolygon,
308cdf0e10cSrcweir             const attribute::LineAttribute& rLineAttribute,
309cdf0e10cSrcweir 			const attribute::StrokeAttribute& rStrokeAttribute)
310cdf0e10cSrcweir 		:	BufferedDecompositionPrimitive2D(),
311cdf0e10cSrcweir 			maPolygon(rPolygon),
312cdf0e10cSrcweir             maLineAttribute(rLineAttribute),
313cdf0e10cSrcweir 			maStrokeAttribute(rStrokeAttribute)
314cdf0e10cSrcweir 		{
315cdf0e10cSrcweir 		}
316cdf0e10cSrcweir 
PolygonStrokePrimitive2D(const basegfx::B2DPolygon & rPolygon,const attribute::LineAttribute & rLineAttribute)317cdf0e10cSrcweir 		PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(
318cdf0e10cSrcweir 			const basegfx::B2DPolygon& rPolygon,
319cdf0e10cSrcweir             const attribute::LineAttribute& rLineAttribute)
320cdf0e10cSrcweir 		:	BufferedDecompositionPrimitive2D(),
321cdf0e10cSrcweir 			maPolygon(rPolygon),
322cdf0e10cSrcweir             maLineAttribute(rLineAttribute),
323cdf0e10cSrcweir 			maStrokeAttribute()
324cdf0e10cSrcweir 		{
325cdf0e10cSrcweir 		}
326cdf0e10cSrcweir 
operator ==(const BasePrimitive2D & rPrimitive) const327cdf0e10cSrcweir 		bool PolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
328cdf0e10cSrcweir 		{
329cdf0e10cSrcweir 			if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
330cdf0e10cSrcweir 			{
331cdf0e10cSrcweir 				const PolygonStrokePrimitive2D& rCompare = (PolygonStrokePrimitive2D&)rPrimitive;
332cdf0e10cSrcweir 
333cdf0e10cSrcweir 				return (getB2DPolygon() == rCompare.getB2DPolygon()
334cdf0e10cSrcweir 					&& getLineAttribute() == rCompare.getLineAttribute()
335cdf0e10cSrcweir 					&& getStrokeAttribute() == rCompare.getStrokeAttribute());
336cdf0e10cSrcweir 			}
337cdf0e10cSrcweir 
338cdf0e10cSrcweir 			return false;
339cdf0e10cSrcweir 		}
340cdf0e10cSrcweir 
getB2DRange(const geometry::ViewInformation2D & rViewInformation) const341cdf0e10cSrcweir 		basegfx::B2DRange PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
342cdf0e10cSrcweir 		{
343cdf0e10cSrcweir             basegfx::B2DRange aRetval;
344cdf0e10cSrcweir 
345cdf0e10cSrcweir             if(getLineAttribute().getWidth())
346cdf0e10cSrcweir             {
3475aaf853bSArmin Le Grand                 bool bUseDecomposition(false);
3485aaf853bSArmin Le Grand 
349cdf0e10cSrcweir                 if(basegfx::B2DLINEJOIN_MITER == getLineAttribute().getLineJoin())
350cdf0e10cSrcweir                 {
351cdf0e10cSrcweir                     // if line is mitered, use parent call since mitered line
352cdf0e10cSrcweir                     // geometry may use more space than the geometry grown by half line width
3535aaf853bSArmin Le Grand                     bUseDecomposition = true;
3545aaf853bSArmin Le Grand                 }
3555aaf853bSArmin Le Grand 
3565aaf853bSArmin Le Grand                 if(!bUseDecomposition && com::sun::star::drawing::LineCap_SQUARE == getLineAttribute().getLineCap())
3575aaf853bSArmin Le Grand                 {
3585aaf853bSArmin Le Grand                     // when drawing::LineCap_SQUARE is used the below method to grow the polygon
3595aaf853bSArmin Le Grand                     // range by half line width will not work, so use decomposition. Interestingly,
3605aaf853bSArmin Le Grand                     // the grow method below works perfectly for LineCap_ROUND since the grow is in
3615aaf853bSArmin Le Grand                     // all directions and the rounded cap needs the same grow in all directions independent
3625aaf853bSArmin Le Grand                     // from it's orientation. Unfortunately this is not the case for drawing::LineCap_SQUARE
3635aaf853bSArmin Le Grand                     bUseDecomposition = true;
3645aaf853bSArmin Le Grand                 }
3655aaf853bSArmin Le Grand 
3665aaf853bSArmin Le Grand                 if(bUseDecomposition)
3675aaf853bSArmin Le Grand                 {
3685aaf853bSArmin Le Grand                     // get correct range by using the decomposition fallback, reasons see above cases
3695aaf853bSArmin Le Grand                     aRetval = BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
370cdf0e10cSrcweir                 }
371cdf0e10cSrcweir                 else
372cdf0e10cSrcweir                 {
373cdf0e10cSrcweir                     // for all other B2DLINEJOIN_* get the range from the base geometry
374cdf0e10cSrcweir                     // and expand by half the line width
375cdf0e10cSrcweir 			        aRetval = getB2DPolygon().getB2DRange();
376cdf0e10cSrcweir 			        aRetval.grow(getLineAttribute().getWidth() * 0.5);
377cdf0e10cSrcweir                 }
378cdf0e10cSrcweir             }
379cdf0e10cSrcweir             else
380cdf0e10cSrcweir             {
381cdf0e10cSrcweir                 // this is a hairline, thus the line width is view-dependent. Get range of polygon
382cdf0e10cSrcweir                 // as base size
383cdf0e10cSrcweir     	        aRetval = getB2DPolygon().getB2DRange();
384cdf0e10cSrcweir 
385cdf0e10cSrcweir                 if(!aRetval.isEmpty())
386cdf0e10cSrcweir                 {
387cdf0e10cSrcweir                     // Calculate view-dependent hairline width
388cdf0e10cSrcweir                     const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
389cdf0e10cSrcweir                     const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
390cdf0e10cSrcweir 
391cdf0e10cSrcweir                     if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
392cdf0e10cSrcweir                     {
393cdf0e10cSrcweir 			            aRetval.grow(fDiscreteHalfLineWidth);
394cdf0e10cSrcweir                     }
395cdf0e10cSrcweir                 }
396cdf0e10cSrcweir             }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir             return aRetval;
399cdf0e10cSrcweir 		}
400cdf0e10cSrcweir 
401cdf0e10cSrcweir 		// provide unique ID
402cdf0e10cSrcweir 		ImplPrimitrive2DIDBlock(PolygonStrokePrimitive2D, PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D)
403cdf0e10cSrcweir 
404cdf0e10cSrcweir 	} // end of namespace primitive2d
405cdf0e10cSrcweir } // end of namespace drawinglayer
406cdf0e10cSrcweir 
407cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
408cdf0e10cSrcweir 
409cdf0e10cSrcweir namespace drawinglayer
410cdf0e10cSrcweir {
411cdf0e10cSrcweir 	namespace primitive2d
412cdf0e10cSrcweir 	{
create2DDecomposition(const geometry::ViewInformation2D &) const413cdf0e10cSrcweir 		Primitive2DSequence PolygonWavePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
414cdf0e10cSrcweir 		{
415cdf0e10cSrcweir 			Primitive2DSequence aRetval;
416cdf0e10cSrcweir 
417cdf0e10cSrcweir 			if(getB2DPolygon().count())
418cdf0e10cSrcweir 			{
419cdf0e10cSrcweir 				const bool bHasWidth(!basegfx::fTools::equalZero(getWaveWidth()));
420cdf0e10cSrcweir 				const bool bHasHeight(!basegfx::fTools::equalZero(getWaveHeight()));
421cdf0e10cSrcweir 
422cdf0e10cSrcweir 				if(bHasWidth && bHasHeight)
423cdf0e10cSrcweir 				{
424cdf0e10cSrcweir 					// create waveline curve
425cdf0e10cSrcweir 					const basegfx::B2DPolygon aWaveline(basegfx::tools::createWaveline(getB2DPolygon(), getWaveWidth(), getWaveHeight()));
426cdf0e10cSrcweir 					const Primitive2DReference xRef(new PolygonStrokePrimitive2D(aWaveline, getLineAttribute(), getStrokeAttribute()));
427cdf0e10cSrcweir 					aRetval = Primitive2DSequence(&xRef, 1);
428cdf0e10cSrcweir 				}
429cdf0e10cSrcweir 				else
430cdf0e10cSrcweir 				{
431cdf0e10cSrcweir 					// flat waveline, decompose to simple line primitive
432cdf0e10cSrcweir 					const Primitive2DReference xRef(new PolygonStrokePrimitive2D(getB2DPolygon(), getLineAttribute(), getStrokeAttribute()));
433cdf0e10cSrcweir 					aRetval = Primitive2DSequence(&xRef, 1);
434cdf0e10cSrcweir 				}
435cdf0e10cSrcweir 			}
436cdf0e10cSrcweir 
437cdf0e10cSrcweir 			return aRetval;
438cdf0e10cSrcweir 		}
439cdf0e10cSrcweir 
PolygonWavePrimitive2D(const basegfx::B2DPolygon & rPolygon,const attribute::LineAttribute & rLineAttribute,const attribute::StrokeAttribute & rStrokeAttribute,double fWaveWidth,double fWaveHeight)440cdf0e10cSrcweir 		PolygonWavePrimitive2D::PolygonWavePrimitive2D(
441cdf0e10cSrcweir 			const basegfx::B2DPolygon& rPolygon,
442cdf0e10cSrcweir             const attribute::LineAttribute& rLineAttribute,
443cdf0e10cSrcweir 			const attribute::StrokeAttribute& rStrokeAttribute,
444cdf0e10cSrcweir 			double fWaveWidth,
445cdf0e10cSrcweir 			double fWaveHeight)
446cdf0e10cSrcweir 		:	PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute),
447cdf0e10cSrcweir 			mfWaveWidth(fWaveWidth),
448cdf0e10cSrcweir 			mfWaveHeight(fWaveHeight)
449cdf0e10cSrcweir 		{
450cdf0e10cSrcweir 			if(mfWaveWidth < 0.0)
451cdf0e10cSrcweir 			{
452cdf0e10cSrcweir 				mfWaveWidth = 0.0;
453cdf0e10cSrcweir 			}
454cdf0e10cSrcweir 
455cdf0e10cSrcweir 			if(mfWaveHeight < 0.0)
456cdf0e10cSrcweir 			{
457cdf0e10cSrcweir 				mfWaveHeight = 0.0;
458cdf0e10cSrcweir 			}
459cdf0e10cSrcweir 		}
460cdf0e10cSrcweir 
PolygonWavePrimitive2D(const basegfx::B2DPolygon & rPolygon,const attribute::LineAttribute & rLineAttribute,double fWaveWidth,double fWaveHeight)461cdf0e10cSrcweir 		PolygonWavePrimitive2D::PolygonWavePrimitive2D(
462cdf0e10cSrcweir 			const basegfx::B2DPolygon& rPolygon,
463cdf0e10cSrcweir             const attribute::LineAttribute& rLineAttribute,
464cdf0e10cSrcweir 			double fWaveWidth,
465cdf0e10cSrcweir 			double fWaveHeight)
466cdf0e10cSrcweir 		:	PolygonStrokePrimitive2D(rPolygon, rLineAttribute),
467cdf0e10cSrcweir 			mfWaveWidth(fWaveWidth),
468cdf0e10cSrcweir 			mfWaveHeight(fWaveHeight)
469cdf0e10cSrcweir 		{
470cdf0e10cSrcweir 			if(mfWaveWidth < 0.0)
471cdf0e10cSrcweir 			{
472cdf0e10cSrcweir 				mfWaveWidth = 0.0;
473cdf0e10cSrcweir 			}
474cdf0e10cSrcweir 
475cdf0e10cSrcweir 			if(mfWaveHeight < 0.0)
476cdf0e10cSrcweir 			{
477cdf0e10cSrcweir 				mfWaveHeight = 0.0;
478cdf0e10cSrcweir 			}
479cdf0e10cSrcweir 		}
480cdf0e10cSrcweir 
operator ==(const BasePrimitive2D & rPrimitive) const481cdf0e10cSrcweir 		bool PolygonWavePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
482cdf0e10cSrcweir 		{
483cdf0e10cSrcweir 			if(PolygonStrokePrimitive2D::operator==(rPrimitive))
484cdf0e10cSrcweir 			{
485cdf0e10cSrcweir 				const PolygonWavePrimitive2D& rCompare = (PolygonWavePrimitive2D&)rPrimitive;
486cdf0e10cSrcweir 
487cdf0e10cSrcweir 				return (getWaveWidth() == rCompare.getWaveWidth()
488cdf0e10cSrcweir 					&& getWaveHeight() == rCompare.getWaveHeight());
489cdf0e10cSrcweir 			}
490cdf0e10cSrcweir 
491cdf0e10cSrcweir 			return false;
492cdf0e10cSrcweir 		}
493cdf0e10cSrcweir 
getB2DRange(const geometry::ViewInformation2D & rViewInformation) const494cdf0e10cSrcweir 		basegfx::B2DRange PolygonWavePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
495cdf0e10cSrcweir 		{
496cdf0e10cSrcweir 			// get range of parent
497cdf0e10cSrcweir     		basegfx::B2DRange aRetval(PolygonStrokePrimitive2D::getB2DRange(rViewInformation));
498cdf0e10cSrcweir 
499cdf0e10cSrcweir 			// if WaveHeight, grow by it
500cdf0e10cSrcweir 			if(basegfx::fTools::more(getWaveHeight(), 0.0))
501cdf0e10cSrcweir 			{
502cdf0e10cSrcweir 				aRetval.grow(getWaveHeight());
503cdf0e10cSrcweir 			}
504cdf0e10cSrcweir 
505cdf0e10cSrcweir 			// if line width, grow by it
506cdf0e10cSrcweir 			if(basegfx::fTools::more(getLineAttribute().getWidth(), 0.0))
507cdf0e10cSrcweir 			{
508cdf0e10cSrcweir 				aRetval.grow(getLineAttribute().getWidth() * 0.5);
509cdf0e10cSrcweir 			}
510cdf0e10cSrcweir 
511cdf0e10cSrcweir 			return aRetval;
512cdf0e10cSrcweir 		}
513cdf0e10cSrcweir 
514cdf0e10cSrcweir 		// provide unique ID
515cdf0e10cSrcweir 		ImplPrimitrive2DIDBlock(PolygonWavePrimitive2D, PRIMITIVE2D_ID_POLYGONWAVEPRIMITIVE2D)
516cdf0e10cSrcweir 
517cdf0e10cSrcweir 	} // end of namespace primitive2d
518cdf0e10cSrcweir } // end of namespace drawinglayer
519cdf0e10cSrcweir 
520cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
521cdf0e10cSrcweir 
522cdf0e10cSrcweir namespace drawinglayer
523cdf0e10cSrcweir {
524cdf0e10cSrcweir 	namespace primitive2d
525cdf0e10cSrcweir 	{
create2DDecomposition(const geometry::ViewInformation2D &) const526cdf0e10cSrcweir 		Primitive2DSequence PolygonStrokeArrowPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
527cdf0e10cSrcweir 		{
528cdf0e10cSrcweir 			// copy local polygon, it may be changed
529cdf0e10cSrcweir 			basegfx::B2DPolygon aLocalPolygon(getB2DPolygon());
530cdf0e10cSrcweir 			basegfx::B2DPolyPolygon aArrowA;
531cdf0e10cSrcweir 			basegfx::B2DPolyPolygon aArrowB;
532cdf0e10cSrcweir 
533cdf0e10cSrcweir 			if(!aLocalPolygon.isClosed())
534cdf0e10cSrcweir 			{
535cdf0e10cSrcweir 				// apply arrows
536cdf0e10cSrcweir 				const double fPolyLength(basegfx::tools::getLength(aLocalPolygon));
537cdf0e10cSrcweir 				double fStart(0.0);
538cdf0e10cSrcweir 				double fEnd(0.0);
539*88e7420bSRegina Henschel                 double fStartOverlap(0.0);
540*88e7420bSRegina Henschel                 double fEndOverlap(0.0);
541cdf0e10cSrcweir 
542cdf0e10cSrcweir 				if(!getStart().isDefault() && getStart().isActive())
543cdf0e10cSrcweir 				{
544cdf0e10cSrcweir 					// create start arrow primitive and consume
545cdf0e10cSrcweir 					aArrowA = basegfx::tools::createAreaGeometryForLineStartEnd(
546cdf0e10cSrcweir 						aLocalPolygon, getStart().getB2DPolyPolygon(), true, getStart().getWidth(),
547cdf0e10cSrcweir 						fPolyLength, getStart().isCentered() ? 0.5 : 0.0, &fStart);
548cdf0e10cSrcweir 
549*88e7420bSRegina Henschel                     // create some overlapping, compromise between straight and peaked markers
550*88e7420bSRegina Henschel                     // best for marker width 0.3cm and marker line width 0.02cm
551*88e7420bSRegina Henschel                     fStartOverlap = getStart().getWidth() / 15.0;
552cdf0e10cSrcweir 				}
553cdf0e10cSrcweir 
554cdf0e10cSrcweir 				if(!getEnd().isDefault() && getEnd().isActive())
555cdf0e10cSrcweir 				{
556cdf0e10cSrcweir 					// create end arrow primitive and consume
557cdf0e10cSrcweir 					aArrowB = basegfx::tools::createAreaGeometryForLineStartEnd(
558cdf0e10cSrcweir 						aLocalPolygon, getEnd().getB2DPolyPolygon(), false, getEnd().getWidth(),
559cdf0e10cSrcweir 						fPolyLength, getEnd().isCentered() ? 0.5 : 0.0, &fEnd);
560cdf0e10cSrcweir 
561cdf0e10cSrcweir 					// create some overlapping
562*88e7420bSRegina Henschel                     fEndOverlap = getEnd().getWidth() / 15.0;
563cdf0e10cSrcweir 				}
564cdf0e10cSrcweir 
565cdf0e10cSrcweir 				if(0.0 != fStart || 0.0 != fEnd)
566cdf0e10cSrcweir 				{
567cdf0e10cSrcweir 					// build new poly, consume something from old poly
568*88e7420bSRegina Henschel                     aLocalPolygon = basegfx::tools::getSnippetAbsolute(aLocalPolygon, fStart-fStartOverlap, fPolyLength - fEnd + fEndOverlap, fPolyLength);
569cdf0e10cSrcweir 				}
570cdf0e10cSrcweir 			}
571cdf0e10cSrcweir 
572cdf0e10cSrcweir 			// prepare return value
573cdf0e10cSrcweir 			Primitive2DSequence aRetval(1L + (aArrowA.count() ? 1L : 0L) + (aArrowB.count() ? 1L : 0L));
574cdf0e10cSrcweir 			sal_uInt32 nInd(0L);
575cdf0e10cSrcweir 
576cdf0e10cSrcweir 			// add shaft
577cdf0e10cSrcweir 			const Primitive2DReference xRefShaft(new
578cdf0e10cSrcweir                 PolygonStrokePrimitive2D(
579cdf0e10cSrcweir                     aLocalPolygon, getLineAttribute(), getStrokeAttribute()));
580cdf0e10cSrcweir 			aRetval[nInd++] = xRefShaft;
581cdf0e10cSrcweir 
582cdf0e10cSrcweir 			if(aArrowA.count())
583cdf0e10cSrcweir 			{
584cdf0e10cSrcweir 				const Primitive2DReference xRefA(
585cdf0e10cSrcweir                     new PolyPolygonColorPrimitive2D(
586cdf0e10cSrcweir                         aArrowA, getLineAttribute().getColor()));
587cdf0e10cSrcweir 				aRetval[nInd++] = xRefA;
588cdf0e10cSrcweir 			}
589cdf0e10cSrcweir 
590cdf0e10cSrcweir 			if(aArrowB.count())
591cdf0e10cSrcweir 			{
592cdf0e10cSrcweir 				const Primitive2DReference xRefB(
593cdf0e10cSrcweir                     new PolyPolygonColorPrimitive2D(
594cdf0e10cSrcweir                         aArrowB, getLineAttribute().getColor()));
595cdf0e10cSrcweir 				aRetval[nInd++] = xRefB;
596cdf0e10cSrcweir 			}
597cdf0e10cSrcweir 
598cdf0e10cSrcweir 			return aRetval;
599cdf0e10cSrcweir 		}
600cdf0e10cSrcweir 
PolygonStrokeArrowPrimitive2D(const basegfx::B2DPolygon & rPolygon,const attribute::LineAttribute & rLineAttribute,const attribute::StrokeAttribute & rStrokeAttribute,const attribute::LineStartEndAttribute & rStart,const attribute::LineStartEndAttribute & rEnd)601cdf0e10cSrcweir 		PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D(
602cdf0e10cSrcweir 			const basegfx::B2DPolygon& rPolygon,
603cdf0e10cSrcweir             const attribute::LineAttribute& rLineAttribute,
604cdf0e10cSrcweir 			const attribute::StrokeAttribute& rStrokeAttribute,
605cdf0e10cSrcweir 			const attribute::LineStartEndAttribute& rStart,
606cdf0e10cSrcweir 			const attribute::LineStartEndAttribute& rEnd)
607cdf0e10cSrcweir 		:	PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute),
608cdf0e10cSrcweir 			maStart(rStart),
609cdf0e10cSrcweir 			maEnd(rEnd)
610cdf0e10cSrcweir 		{
611cdf0e10cSrcweir 		}
612cdf0e10cSrcweir 
PolygonStrokeArrowPrimitive2D(const basegfx::B2DPolygon & rPolygon,const attribute::LineAttribute & rLineAttribute,const attribute::LineStartEndAttribute & rStart,const attribute::LineStartEndAttribute & rEnd)613cdf0e10cSrcweir 		PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D(
614cdf0e10cSrcweir 			const basegfx::B2DPolygon& rPolygon,
615cdf0e10cSrcweir             const attribute::LineAttribute& rLineAttribute,
616cdf0e10cSrcweir 			const attribute::LineStartEndAttribute& rStart,
617cdf0e10cSrcweir 			const attribute::LineStartEndAttribute& rEnd)
618cdf0e10cSrcweir 		:	PolygonStrokePrimitive2D(rPolygon, rLineAttribute),
619cdf0e10cSrcweir 			maStart(rStart),
620cdf0e10cSrcweir 			maEnd(rEnd)
621cdf0e10cSrcweir 		{
622cdf0e10cSrcweir 		}
623cdf0e10cSrcweir 
operator ==(const BasePrimitive2D & rPrimitive) const624cdf0e10cSrcweir 		bool PolygonStrokeArrowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
625cdf0e10cSrcweir 		{
626cdf0e10cSrcweir 			if(PolygonStrokePrimitive2D::operator==(rPrimitive))
627cdf0e10cSrcweir 			{
628cdf0e10cSrcweir 				const PolygonStrokeArrowPrimitive2D& rCompare = (PolygonStrokeArrowPrimitive2D&)rPrimitive;
629cdf0e10cSrcweir 
630cdf0e10cSrcweir 				return (getStart() == rCompare.getStart()
631cdf0e10cSrcweir 					&& getEnd() == rCompare.getEnd());
632cdf0e10cSrcweir 			}
633cdf0e10cSrcweir 
634cdf0e10cSrcweir 			return false;
635cdf0e10cSrcweir 		}
636cdf0e10cSrcweir 
getB2DRange(const geometry::ViewInformation2D & rViewInformation) const637cdf0e10cSrcweir 		basegfx::B2DRange PolygonStrokeArrowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
638cdf0e10cSrcweir 		{
639cdf0e10cSrcweir 			basegfx::B2DRange aRetval;
640cdf0e10cSrcweir 
641cdf0e10cSrcweir 			if(getStart().isActive() || getEnd().isActive())
642cdf0e10cSrcweir 			{
643cdf0e10cSrcweir 				// use decomposition when line start/end is used
644cdf0e10cSrcweir 				return BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
645cdf0e10cSrcweir 			}
646cdf0e10cSrcweir 			else
647cdf0e10cSrcweir 			{
648cdf0e10cSrcweir 				// get range from parent
649cdf0e10cSrcweir 				return PolygonStrokePrimitive2D::getB2DRange(rViewInformation);
650cdf0e10cSrcweir 			}
651cdf0e10cSrcweir 		}
652cdf0e10cSrcweir 
653cdf0e10cSrcweir 		// provide unique ID
654cdf0e10cSrcweir 		ImplPrimitrive2DIDBlock(PolygonStrokeArrowPrimitive2D, PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D)
655cdf0e10cSrcweir 
656cdf0e10cSrcweir 	} // end of namespace primitive2d
657cdf0e10cSrcweir } // end of namespace drawinglayer
658cdf0e10cSrcweir 
659cdf0e10cSrcweir //////////////////////////////////////////////////////////////////////////////
660cdf0e10cSrcweir // eof
661