xref: /AOO41X/main/svx/source/sdr/overlay/overlaytools.cxx (revision 5b073cc73f469eeafd4f39090bb6a267e5cc1ca6)
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_svx.hxx"
26 
27 #include <svx/sdr/overlay/overlaytools.hxx>
28 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
29 #include <basegfx/matrix/b2dhommatrix.hxx>
30 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
31 #include <basegfx/polygon/b2dpolygon.hxx>
32 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
33 #include <basegfx/polygon/b2dpolygontools.hxx>
34 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
35 #include <drawinglayer/geometry/viewinformation2d.hxx>
36 #include <basegfx/matrix/b2dhommatrixtools.hxx>
37 #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
38 #include <vcl/svapp.hxx>
39 
40 //////////////////////////////////////////////////////////////////////////////
41 
42 namespace drawinglayer
43 {
44     namespace primitive2d
45     {
46         OverlayBitmapExPrimitive::OverlayBitmapExPrimitive(
47             const BitmapEx& rBitmapEx,
48             const basegfx::B2DPoint& rBasePosition,
49             sal_uInt16 nCenterX,
50             sal_uInt16 nCenterY)
51         :   DiscreteMetricDependentPrimitive2D(),
52             maBitmapEx(rBitmapEx),
53             maBasePosition(rBasePosition),
54             mnCenterX(nCenterX),
55             mnCenterY(nCenterY)
56         {}
57 
58         Primitive2DSequence OverlayBitmapExPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
59         {
60             Primitive2DSequence aRetval;
61             const Size aBitmapSize(getBitmapEx().GetSizePixel());
62 
63             if(aBitmapSize.Width() && aBitmapSize.Height() && basegfx::fTools::more(getDiscreteUnit(), 0.0))
64             {
65                 // calculate back from internal bitmap's extreme coordinates (the edges)
66                 // to logical coordinates. Only use a unified scaling value (getDiscreteUnit(),
67                 // the prepared one which expresses how many logic units form a discrete unit)
68                 // for this step. This primitive is to be displayed always unscaled (in it's pixel size)
69                 // and unrotated, more like a marker
70                 const double fLeft(((0.0 - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX());
71                 const double fTop(((0.0 - getCenterY()) * getDiscreteUnit()) + getBasePosition().getY());
72                 const double fRight(((aBitmapSize.getWidth() - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX());
73                 const double fBottom(((aBitmapSize.getHeight() - getCenterY()) * getDiscreteUnit()) + getBasePosition().getY());
74 
75                 // create a BitmapPrimitive2D using those positions
76                 basegfx::B2DHomMatrix aTransform;
77 
78                 aTransform.set(0, 0, fRight - fLeft);
79                 aTransform.set(1, 1, fBottom - fTop);
80                 aTransform.set(0, 2, fLeft);
81                 aTransform.set(1, 2, fTop);
82 
83                 const Primitive2DReference aPrimitive(new BitmapPrimitive2D(getBitmapEx(), aTransform));
84                 aRetval = Primitive2DSequence(&aPrimitive, 1);
85             }
86 
87             return aRetval;
88         }
89 
90         bool OverlayBitmapExPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
91         {
92             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
93             {
94                 const OverlayBitmapExPrimitive& rCompare = static_cast< const OverlayBitmapExPrimitive& >(rPrimitive);
95 
96                 return (getBitmapEx() == rCompare.getBitmapEx()
97                     && getBasePosition() == rCompare.getBasePosition()
98                     && getCenterX() == rCompare.getCenterX()
99                     && getCenterY() == rCompare.getCenterY());
100             }
101 
102             return false;
103         }
104 
105         ImplPrimitrive2DIDBlock(OverlayBitmapExPrimitive, PRIMITIVE2D_ID_OVERLAYBITMAPEXPRIMITIVE)
106 
107     } // end of namespace primitive2d
108 } // end of namespace drawinglayer
109 
110 //////////////////////////////////////////////////////////////////////////////
111 
112 namespace drawinglayer
113 {
114     namespace primitive2d
115     {
116         OverlayCrosshairPrimitive::OverlayCrosshairPrimitive(
117             const basegfx::B2DPoint& rBasePosition,
118             const basegfx::BColor& rRGBColorA,
119             const basegfx::BColor& rRGBColorB,
120             double fDiscreteDashLength)
121         :   ViewportDependentPrimitive2D(),
122             maBasePosition(rBasePosition),
123             maRGBColorA(rRGBColorA),
124             maRGBColorB(rRGBColorB),
125             mfDiscreteDashLength(fDiscreteDashLength)
126         {}
127 
128         Primitive2DSequence OverlayCrosshairPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
129         {
130             // use the prepared Viewport information accessible using getViewport()
131             Primitive2DSequence aRetval;
132 
133             if(!getViewport().isEmpty())
134             {
135                 aRetval.realloc(2);
136                 basegfx::B2DPolygon aPolygon;
137 
138                 aPolygon.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY()));
139                 aPolygon.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY()));
140 
141                 aRetval[0] = Primitive2DReference(
142                     new PolygonMarkerPrimitive2D(
143                         aPolygon,
144                         getRGBColorA(),
145                         getRGBColorB(),
146                         getDiscreteDashLength()));
147 
148                 aPolygon.clear();
149                 aPolygon.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY()));
150                 aPolygon.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY()));
151 
152                 aRetval[1] = Primitive2DReference(
153                     new PolygonMarkerPrimitive2D(
154                         aPolygon,
155                         getRGBColorA(),
156                         getRGBColorB(),
157                         getDiscreteDashLength()));
158             }
159 
160             return aRetval;
161         }
162 
163         bool OverlayCrosshairPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
164         {
165             if(ViewportDependentPrimitive2D::operator==(rPrimitive))
166             {
167                 const OverlayCrosshairPrimitive& rCompare = static_cast< const OverlayCrosshairPrimitive& >(rPrimitive);
168 
169                 return (getBasePosition() == rCompare.getBasePosition()
170                     && getRGBColorA() == rCompare.getRGBColorA()
171                     && getRGBColorB() == rCompare.getRGBColorB()
172                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
173             }
174 
175             return false;
176         }
177 
178         ImplPrimitrive2DIDBlock(OverlayCrosshairPrimitive, PRIMITIVE2D_ID_OVERLAYCROSSHAIRPRIMITIVE)
179 
180     } // end of namespace primitive2d
181 } // end of namespace drawinglayer
182 
183 //////////////////////////////////////////////////////////////////////////////
184 
185 namespace drawinglayer
186 {
187     namespace primitive2d
188     {
189         OverlayRectanglePrimitive::OverlayRectanglePrimitive(
190             const basegfx::B2DRange& rObjectRange,
191             const basegfx::BColor& rColor,
192             double fTransparence,
193             double fDiscreteGrow,
194             double fDiscreteShrink,
195             double fRotation)
196         :   DiscreteMetricDependentPrimitive2D(),
197             maObjectRange(rObjectRange),
198             maColor(rColor),
199             mfTransparence(fTransparence),
200             mfDiscreteGrow(fDiscreteGrow),
201             mfDiscreteShrink(fDiscreteShrink),
202             mfRotation(fRotation)
203         {}
204 
205         Primitive2DSequence OverlayRectanglePrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
206         {
207             Primitive2DSequence aRetval;
208             basegfx::B2DRange aInnerRange(getObjectRange());
209 
210             if(!aInnerRange.isEmpty() && basegfx::fTools::more(getDiscreteUnit(), 0.0) && getTransparence() <= 1.0)
211             {
212                 basegfx::B2DRange aInnerRange(getObjectRange());
213                 basegfx::B2DRange aOuterRange(getObjectRange());
214 
215                 // grow/shrink inner/outer polygons
216                 aOuterRange.grow(getDiscreteUnit() * getDiscreteGrow());
217                 aInnerRange.grow(getDiscreteUnit() * -getDiscreteShrink());
218 
219                 // convert to polygons
220                 const double fFullGrow(getDiscreteGrow() + getDiscreteShrink());
221                 const double fRelativeRadiusX(fFullGrow / aOuterRange.getWidth());
222                 const double fRelativeRadiusY(fFullGrow / aOuterRange.getHeight());
223                 basegfx::B2DPolygon aOuterPolygon(
224                     basegfx::tools::createPolygonFromRect(
225                         aOuterRange,
226                         fRelativeRadiusX,
227                         fRelativeRadiusY));
228                 basegfx::B2DPolygon aInnerPolygon(
229                     basegfx::tools::createPolygonFromRect(
230                         aInnerRange));
231 
232                 // apply evtl. existing rotation
233                 if(!basegfx::fTools::equalZero(getRotation()))
234                 {
235                     const basegfx::B2DHomMatrix aTransform(basegfx::tools::createRotateAroundPoint(
236                         getObjectRange().getMinX(), getObjectRange().getMinY(), getRotation()));
237 
238                     aOuterPolygon.transform(aTransform);
239                     aInnerPolygon.transform(aTransform);
240                 }
241 
242                 // create filled primitive
243                 basegfx::B2DPolyPolygon aPolyPolygon;
244 
245                 aPolyPolygon.append(aOuterPolygon);
246                 aPolyPolygon.append(aInnerPolygon);
247 
248                 if(Application::GetSettings().GetStyleSettings().GetHighContrastMode())
249                 {
250                     // for high contrast, use hatch
251                     const basegfx::BColor aHighContrastLineColor(Application::GetSettings().GetStyleSettings().GetFontColor().getBColor());
252                     const basegfx::BColor aEmptyColor(0.0, 0.0, 0.0);
253                     const double fHatchRotation(45 * F_PI180);
254                     const double fDiscreteHatchDistance(3.0);
255                     const drawinglayer::attribute::FillHatchAttribute aFillHatchAttribute(
256                         drawinglayer::attribute::HATCHSTYLE_SINGLE,
257                         fDiscreteHatchDistance * getDiscreteUnit(),
258                         fHatchRotation - getRotation(),
259                         aHighContrastLineColor,
260                         3, // same default as VCL, a minimum of three discrete units (pixels) offset
261                         false);
262                     const Primitive2DReference aHatch(
263                         new PolyPolygonHatchPrimitive2D(
264                             aPolyPolygon,
265                             aEmptyColor,
266                             aFillHatchAttribute));
267 
268                     aRetval = Primitive2DSequence(&aHatch, 1);
269                 }
270                 else
271                 {
272                     // create fill primitive
273                     const Primitive2DReference aFill(
274                         new PolyPolygonColorPrimitive2D(
275                             aPolyPolygon,
276                             getColor()));
277 
278                     aRetval = Primitive2DSequence(&aFill, 1);
279 
280                     // embed filled to transparency (if used)
281                     if(getTransparence() > 0.0)
282                     {
283                         const Primitive2DReference aFillTransparent(
284                             new UnifiedTransparencePrimitive2D(
285                                 aRetval,
286                                 getTransparence()));
287 
288                         aRetval = Primitive2DSequence(&aFillTransparent, 1);
289                     }
290                 }
291             }
292 
293             return aRetval;
294         }
295 
296         bool OverlayRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
297         {
298             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
299             {
300                 const OverlayRectanglePrimitive& rCompare = static_cast< const OverlayRectanglePrimitive& >(rPrimitive);
301 
302                 return (getObjectRange() == rCompare.getObjectRange()
303                     && getColor() == rCompare.getColor()
304                     && getTransparence() == rCompare.getTransparence()
305                     && getDiscreteGrow() == rCompare.getDiscreteGrow()
306                     && getDiscreteShrink() == rCompare.getDiscreteShrink()
307                     && getRotation() == rCompare.getRotation());
308             }
309 
310             return false;
311         }
312 
313         ImplPrimitrive2DIDBlock(OverlayRectanglePrimitive, PRIMITIVE2D_ID_OVERLAYRECTANGLEPRIMITIVE)
314 
315     } // end of namespace primitive2d
316 } // end of namespace drawinglayer
317 
318 //////////////////////////////////////////////////////////////////////////////
319 
320 namespace drawinglayer
321 {
322     namespace primitive2d
323     {
324         OverlayHelplineStripedPrimitive::OverlayHelplineStripedPrimitive(
325             const basegfx::B2DPoint& rBasePosition,
326             HelplineStyle eStyle,
327             const basegfx::BColor& rRGBColorA,
328             const basegfx::BColor& rRGBColorB,
329             double fDiscreteDashLength)
330         :   ViewportDependentPrimitive2D(),
331             maBasePosition(rBasePosition),
332             meStyle(eStyle),
333             maRGBColorA(rRGBColorA),
334             maRGBColorB(rRGBColorB),
335             mfDiscreteDashLength(fDiscreteDashLength)
336         {}
337 
338         Primitive2DSequence OverlayHelplineStripedPrimitive::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
339         {
340             // use the prepared Viewport information accessible using getViewport()
341             Primitive2DSequence aRetval;
342 
343             if(!getViewport().isEmpty())
344             {
345                 switch(getStyle())
346                 {
347                     case HELPLINESTYLE_VERTICAL :
348                     {
349                         aRetval.realloc(1);
350                         basegfx::B2DPolygon aLine;
351 
352                         aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY()));
353                         aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY()));
354 
355                         aRetval[0] = Primitive2DReference(
356                             new PolygonMarkerPrimitive2D(
357                                 aLine,
358                                 getRGBColorA(),
359                                 getRGBColorB(),
360                                 getDiscreteDashLength()));
361                         break;
362                     }
363 
364                     case HELPLINESTYLE_HORIZONTAL :
365                     {
366                         aRetval.realloc(1);
367                         basegfx::B2DPolygon aLine;
368 
369                         aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY()));
370                         aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY()));
371 
372                         aRetval[0] = Primitive2DReference(
373                             new PolygonMarkerPrimitive2D(
374                                 aLine,
375                                 getRGBColorA(),
376                                 getRGBColorB(),
377                                 getDiscreteDashLength()));
378                         break;
379                     }
380 
381                     default: // case HELPLINESTYLE_POINT :
382                     {
383                         const double fDiscreteUnit((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
384                         aRetval.realloc(2);
385                         basegfx::B2DPolygon aLineA, aLineB;
386 
387                         aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() - fDiscreteUnit));
388                         aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() + fDiscreteUnit));
389 
390                         aRetval[0] = Primitive2DReference(
391                             new PolygonMarkerPrimitive2D(
392                                 aLineA,
393                                 getRGBColorA(),
394                                 getRGBColorB(),
395                                 getDiscreteDashLength()));
396 
397                         aLineB.append(basegfx::B2DPoint(getBasePosition().getX() - fDiscreteUnit, getBasePosition().getY()));
398                         aLineB.append(basegfx::B2DPoint(getBasePosition().getX() + fDiscreteUnit, getBasePosition().getY()));
399 
400                         aRetval[1] = Primitive2DReference(
401                             new PolygonMarkerPrimitive2D(
402                                 aLineB,
403                                 getRGBColorA(),
404                                 getRGBColorB(),
405                                 getDiscreteDashLength()));
406 
407                         break;
408                     }
409                 }
410             }
411 
412             return aRetval;
413         }
414 
415         bool OverlayHelplineStripedPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
416         {
417             if(ViewportDependentPrimitive2D::operator==(rPrimitive))
418             {
419                 const OverlayHelplineStripedPrimitive& rCompare = static_cast< const OverlayHelplineStripedPrimitive& >(rPrimitive);
420 
421                 return (getBasePosition() == rCompare.getBasePosition()
422                     && getStyle() == rCompare.getStyle()
423                     && getRGBColorA() == rCompare.getRGBColorA()
424                     && getRGBColorB() == rCompare.getRGBColorB()
425                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
426             }
427 
428             return false;
429         }
430 
431         ImplPrimitrive2DIDBlock(OverlayHelplineStripedPrimitive, PRIMITIVE2D_ID_OVERLAYHELPLINESTRIPEDPRIMITIVE)
432 
433     } // end of namespace primitive2d
434 } // end of namespace drawinglayer
435 
436 //////////////////////////////////////////////////////////////////////////////
437 
438 namespace drawinglayer
439 {
440     namespace primitive2d
441     {
442         OverlayRollingRectanglePrimitive::OverlayRollingRectanglePrimitive(
443             const basegfx::B2DRange& aRollingRectangle,
444             const basegfx::BColor& rRGBColorA,
445             const basegfx::BColor& rRGBColorB,
446             double fDiscreteDashLength)
447         :   ViewportDependentPrimitive2D(),
448             maRollingRectangle(aRollingRectangle),
449             maRGBColorA(rRGBColorA),
450             maRGBColorB(rRGBColorB),
451             mfDiscreteDashLength(fDiscreteDashLength)
452         {}
453 
454         Primitive2DSequence OverlayRollingRectanglePrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
455         {
456             // use the prepared Viewport information accessible using getViewport()
457             Primitive2DSequence aRetval;
458 
459             if(!getViewport().isEmpty())
460             {
461                 basegfx::B2DPolygon aLine;
462                 aRetval.realloc(8);
463 
464                 // Left lines
465                 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMinY()));
466                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY()));
467                 aRetval[0] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
468 
469                 aLine.clear();
470                 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMaxY()));
471                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY()));
472                 aRetval[1] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
473 
474                 // Right lines
475                 aLine.clear();
476                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY()));
477                 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMinY()));
478                 aRetval[2] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
479 
480                 aLine.clear();
481                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY()));
482                 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMaxY()));
483                 aRetval[3] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
484 
485                 // Top lines
486                 aLine.clear();
487                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMinY()));
488                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY()));
489                 aRetval[4] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
490 
491                 aLine.clear();
492                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMinY()));
493                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY()));
494                 aRetval[5] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
495 
496                 // Bottom lines
497                 aLine.clear();
498                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY()));
499                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMaxY()));
500                 aRetval[6] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
501 
502                 aLine.clear();
503                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY()));
504                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMaxY()));
505                 aRetval[7] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
506             }
507 
508             return aRetval;
509         }
510 
511         bool OverlayRollingRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
512         {
513             if(ViewportDependentPrimitive2D::operator==(rPrimitive))
514             {
515                 const OverlayRollingRectanglePrimitive& rCompare = static_cast< const OverlayRollingRectanglePrimitive& >(rPrimitive);
516 
517                 return (getRollingRectangle() == rCompare.getRollingRectangle()
518                     && getRGBColorA() == rCompare.getRGBColorA()
519                     && getRGBColorB() == rCompare.getRGBColorB()
520                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
521             }
522 
523             return false;
524         }
525 
526         ImplPrimitrive2DIDBlock(OverlayRollingRectanglePrimitive, PRIMITIVE2D_ID_OVERLAYROLLINGRECTANGLEPRIMITIVE)
527 
528     } // end of namespace primitive2d
529 } // end of namespace drawinglayer
530 
531 //////////////////////////////////////////////////////////////////////////////
532 // eof
533