xref: /trunk/main/svx/source/sdr/overlay/overlaytools.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 #include <svx/sdr/overlay/overlaytools.hxx>
32 #include <svx/sdr/primitive2d/svx_primitivetypes2d.hxx>
33 #include <basegfx/matrix/b2dhommatrix.hxx>
34 #include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
35 #include <basegfx/polygon/b2dpolygon.hxx>
36 #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
37 #include <basegfx/polygon/b2dpolygontools.hxx>
38 #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
39 #include <drawinglayer/geometry/viewinformation2d.hxx>
40 #include <basegfx/matrix/b2dhommatrixtools.hxx>
41 
42 //////////////////////////////////////////////////////////////////////////////
43 
44 namespace drawinglayer
45 {
46     namespace primitive2d
47     {
48         OverlayBitmapExPrimitive::OverlayBitmapExPrimitive(
49             const BitmapEx& rBitmapEx,
50             const basegfx::B2DPoint& rBasePosition,
51             sal_uInt16 nCenterX,
52             sal_uInt16 nCenterY)
53         :   DiscreteMetricDependentPrimitive2D(),
54             maBitmapEx(rBitmapEx),
55             maBasePosition(rBasePosition),
56             mnCenterX(nCenterX),
57             mnCenterY(nCenterY)
58         {}
59 
60         Primitive2DSequence OverlayBitmapExPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
61         {
62             Primitive2DSequence aRetval;
63             const Size aBitmapSize(getBitmapEx().GetSizePixel());
64 
65             if(aBitmapSize.Width() && aBitmapSize.Height() && basegfx::fTools::more(getDiscreteUnit(), 0.0))
66             {
67                 // calculate back from internal bitmap's extreme coordinates (the edges)
68                 // to logical coordinates. Only use a unified scaling value (getDiscreteUnit(),
69                 // the prepared one which expresses how many logic units form a discrete unit)
70                 // for this step. This primitive is to be displayed always unscaled (in it's pixel size)
71                 // and unrotated, more like a marker
72                 const double fLeft(((0.0 - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX());
73                 const double fTop(((0.0 - getCenterY()) * getDiscreteUnit()) + getBasePosition().getY());
74                 const double fRight((((aBitmapSize.getWidth() - 1.0) - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX());
75                 const double fBottom((((aBitmapSize.getHeight() - 1.0) - getCenterY()) * getDiscreteUnit()) + getBasePosition().getY());
76 
77                 // create a BitmapPrimitive2D using those positions
78                 basegfx::B2DHomMatrix aTransform;
79 
80                 aTransform.set(0, 0, fRight - fLeft);
81                 aTransform.set(1, 1, fBottom - fTop);
82                 aTransform.set(0, 2, fLeft);
83                 aTransform.set(1, 2, fTop);
84 
85                 const Primitive2DReference aPrimitive(new BitmapPrimitive2D(getBitmapEx(), aTransform));
86                 aRetval = Primitive2DSequence(&aPrimitive, 1);
87             }
88 
89             return aRetval;
90         }
91 
92         bool OverlayBitmapExPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
93         {
94             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
95             {
96                 const OverlayBitmapExPrimitive& rCompare = static_cast< const OverlayBitmapExPrimitive& >(rPrimitive);
97 
98                 return (getBitmapEx() == rCompare.getBitmapEx()
99                     && getBasePosition() == rCompare.getBasePosition()
100                     && getCenterX() == rCompare.getCenterX()
101                     && getCenterY() == rCompare.getCenterY());
102             }
103 
104             return false;
105         }
106 
107         ImplPrimitrive2DIDBlock(OverlayBitmapExPrimitive, PRIMITIVE2D_ID_OVERLAYBITMAPEXPRIMITIVE)
108 
109     } // end of namespace primitive2d
110 } // end of namespace drawinglayer
111 
112 //////////////////////////////////////////////////////////////////////////////
113 
114 namespace drawinglayer
115 {
116     namespace primitive2d
117     {
118         OverlayCrosshairPrimitive::OverlayCrosshairPrimitive(
119             const basegfx::B2DPoint& rBasePosition,
120             const basegfx::BColor& rRGBColorA,
121             const basegfx::BColor& rRGBColorB,
122             double fDiscreteDashLength)
123         :   ViewportDependentPrimitive2D(),
124             maBasePosition(rBasePosition),
125             maRGBColorA(rRGBColorA),
126             maRGBColorB(rRGBColorB),
127             mfDiscreteDashLength(fDiscreteDashLength)
128         {}
129 
130         Primitive2DSequence OverlayCrosshairPrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
131         {
132             // use the prepared Viewport information accessible using getViewport()
133             Primitive2DSequence aRetval;
134 
135             if(!getViewport().isEmpty())
136             {
137                 aRetval.realloc(2);
138                 basegfx::B2DPolygon aPolygon;
139 
140                 aPolygon.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY()));
141                 aPolygon.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY()));
142 
143                 aRetval[0] = Primitive2DReference(
144                     new PolygonMarkerPrimitive2D(
145                         aPolygon,
146                         getRGBColorA(),
147                         getRGBColorB(),
148                         getDiscreteDashLength()));
149 
150                 aPolygon.clear();
151                 aPolygon.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY()));
152                 aPolygon.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY()));
153 
154                 aRetval[1] = Primitive2DReference(
155                     new PolygonMarkerPrimitive2D(
156                         aPolygon,
157                         getRGBColorA(),
158                         getRGBColorB(),
159                         getDiscreteDashLength()));
160             }
161 
162             return aRetval;
163         }
164 
165         bool OverlayCrosshairPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
166         {
167             if(ViewportDependentPrimitive2D::operator==(rPrimitive))
168             {
169                 const OverlayCrosshairPrimitive& rCompare = static_cast< const OverlayCrosshairPrimitive& >(rPrimitive);
170 
171                 return (getBasePosition() == rCompare.getBasePosition()
172                     && getRGBColorA() == rCompare.getRGBColorA()
173                     && getRGBColorB() == rCompare.getRGBColorB()
174                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
175             }
176 
177             return false;
178         }
179 
180         ImplPrimitrive2DIDBlock(OverlayCrosshairPrimitive, PRIMITIVE2D_ID_OVERLAYCROSSHAIRPRIMITIVE)
181 
182     } // end of namespace primitive2d
183 } // end of namespace drawinglayer
184 
185 //////////////////////////////////////////////////////////////////////////////
186 
187 namespace drawinglayer
188 {
189     namespace primitive2d
190     {
191         OverlayHatchRectanglePrimitive::OverlayHatchRectanglePrimitive(
192             const basegfx::B2DRange& rObjectRange,
193             double fDiscreteHatchDistance,
194             double fHatchRotation,
195             const basegfx::BColor& rHatchColor,
196             double fDiscreteGrow,
197             double fDiscreteShrink,
198             double fRotation)
199         :   DiscreteMetricDependentPrimitive2D(),
200             maObjectRange(rObjectRange),
201             mfDiscreteHatchDistance(fDiscreteHatchDistance),
202             mfHatchRotation(fHatchRotation),
203             maHatchColor(rHatchColor),
204             mfDiscreteGrow(fDiscreteGrow),
205             mfDiscreteShrink(fDiscreteShrink),
206             mfRotation(fRotation)
207         {}
208 
209         Primitive2DSequence OverlayHatchRectanglePrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
210         {
211             Primitive2DSequence aRetval;
212 
213             if(basegfx::fTools::more(getDiscreteUnit(), 0.0))
214             {
215                 basegfx::B2DRange aInnerRange(getObjectRange());
216                 basegfx::B2DRange aOuterRange(getObjectRange());
217                 basegfx::B2DPolyPolygon aHatchPolyPolygon;
218 
219                 aOuterRange.grow(getDiscreteUnit() * getDiscreteGrow());
220                 aInnerRange.grow(getDiscreteUnit() * -getDiscreteShrink());
221 
222                 aHatchPolyPolygon.append(basegfx::tools::createPolygonFromRect(aOuterRange));
223 
224                 if(!aInnerRange.isEmpty())
225                 {
226                     aHatchPolyPolygon.append(basegfx::tools::createPolygonFromRect(aInnerRange));
227                 }
228 
229                 if(!basegfx::fTools::equalZero(getRotation()))
230                 {
231                     const basegfx::B2DHomMatrix aTransform(basegfx::tools::createRotateAroundPoint(
232                         getObjectRange().getMinX(), getObjectRange().getMinY(), getRotation()));
233 
234                     aHatchPolyPolygon.transform(aTransform);
235                 }
236 
237                 const basegfx::BColor aEmptyColor(0.0, 0.0, 0.0);
238                 const drawinglayer::attribute::FillHatchAttribute aFillHatchAttribute(
239                     drawinglayer::attribute::HATCHSTYLE_SINGLE,
240                     getDiscreteHatchDistance() * getDiscreteUnit(),
241                     getHatchRotation() - getRotation(),
242                     getHatchColor(),
243                     false);
244                 const Primitive2DReference aPrimitive(
245                     new PolyPolygonHatchPrimitive2D(
246                         aHatchPolyPolygon,
247                         aEmptyColor,
248                         aFillHatchAttribute));
249 
250                 aRetval = Primitive2DSequence(&aPrimitive, 1);
251             }
252 
253             return aRetval;
254         }
255 
256         bool OverlayHatchRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
257         {
258             if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
259             {
260                 const OverlayHatchRectanglePrimitive& rCompare = static_cast< const OverlayHatchRectanglePrimitive& >(rPrimitive);
261 
262                 return (getObjectRange() == rCompare.getObjectRange()
263                     && getDiscreteHatchDistance() == rCompare.getDiscreteHatchDistance()
264                     && getHatchRotation() == rCompare.getHatchRotation()
265                     && getHatchColor() == rCompare.getHatchColor()
266                     && getDiscreteGrow() == rCompare.getDiscreteGrow()
267                     && getDiscreteShrink() == rCompare.getDiscreteShrink()
268                     && getRotation() == rCompare.getRotation());
269             }
270 
271             return false;
272         }
273 
274         ImplPrimitrive2DIDBlock(OverlayHatchRectanglePrimitive, PRIMITIVE2D_ID_OVERLAYHATCHRECTANGLEPRIMITIVE)
275 
276     } // end of namespace primitive2d
277 } // end of namespace drawinglayer
278 
279 //////////////////////////////////////////////////////////////////////////////
280 
281 namespace drawinglayer
282 {
283     namespace primitive2d
284     {
285         OverlayHelplineStripedPrimitive::OverlayHelplineStripedPrimitive(
286             const basegfx::B2DPoint& rBasePosition,
287             HelplineStyle eStyle,
288             const basegfx::BColor& rRGBColorA,
289             const basegfx::BColor& rRGBColorB,
290             double fDiscreteDashLength)
291         :   ViewportDependentPrimitive2D(),
292             maBasePosition(rBasePosition),
293             meStyle(eStyle),
294             maRGBColorA(rRGBColorA),
295             maRGBColorB(rRGBColorB),
296             mfDiscreteDashLength(fDiscreteDashLength)
297         {}
298 
299         Primitive2DSequence OverlayHelplineStripedPrimitive::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
300         {
301             // use the prepared Viewport information accessible using getViewport()
302             Primitive2DSequence aRetval;
303 
304             if(!getViewport().isEmpty())
305             {
306                 switch(getStyle())
307                 {
308                     case HELPLINESTYLE_VERTICAL :
309                     {
310                         aRetval.realloc(1);
311                         basegfx::B2DPolygon aLine;
312 
313                         aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY()));
314                         aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY()));
315 
316                         aRetval[0] = Primitive2DReference(
317                             new PolygonMarkerPrimitive2D(
318                                 aLine,
319                                 getRGBColorA(),
320                                 getRGBColorB(),
321                                 getDiscreteDashLength()));
322                         break;
323                     }
324 
325                     case HELPLINESTYLE_HORIZONTAL :
326                     {
327                         aRetval.realloc(1);
328                         basegfx::B2DPolygon aLine;
329 
330                         aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY()));
331                         aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY()));
332 
333                         aRetval[0] = Primitive2DReference(
334                             new PolygonMarkerPrimitive2D(
335                                 aLine,
336                                 getRGBColorA(),
337                                 getRGBColorB(),
338                                 getDiscreteDashLength()));
339                         break;
340                     }
341 
342                     default: // case HELPLINESTYLE_POINT :
343                     {
344                         const double fDiscreteUnit((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
345                         aRetval.realloc(2);
346                         basegfx::B2DPolygon aLineA, aLineB;
347 
348                         aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() - fDiscreteUnit));
349                         aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() + fDiscreteUnit));
350 
351                         aRetval[0] = Primitive2DReference(
352                             new PolygonMarkerPrimitive2D(
353                                 aLineA,
354                                 getRGBColorA(),
355                                 getRGBColorB(),
356                                 getDiscreteDashLength()));
357 
358                         aLineB.append(basegfx::B2DPoint(getBasePosition().getX() - fDiscreteUnit, getBasePosition().getY()));
359                         aLineB.append(basegfx::B2DPoint(getBasePosition().getX() + fDiscreteUnit, getBasePosition().getY()));
360 
361                         aRetval[1] = Primitive2DReference(
362                             new PolygonMarkerPrimitive2D(
363                                 aLineB,
364                                 getRGBColorA(),
365                                 getRGBColorB(),
366                                 getDiscreteDashLength()));
367 
368                         break;
369                     }
370                 }
371             }
372 
373             return aRetval;
374         }
375 
376         bool OverlayHelplineStripedPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
377         {
378             if(ViewportDependentPrimitive2D::operator==(rPrimitive))
379             {
380                 const OverlayHelplineStripedPrimitive& rCompare = static_cast< const OverlayHelplineStripedPrimitive& >(rPrimitive);
381 
382                 return (getBasePosition() == rCompare.getBasePosition()
383                     && getStyle() == rCompare.getStyle()
384                     && getRGBColorA() == rCompare.getRGBColorA()
385                     && getRGBColorB() == rCompare.getRGBColorB()
386                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
387             }
388 
389             return false;
390         }
391 
392         ImplPrimitrive2DIDBlock(OverlayHelplineStripedPrimitive, PRIMITIVE2D_ID_OVERLAYHELPLINESTRIPEDPRIMITIVE)
393 
394     } // end of namespace primitive2d
395 } // end of namespace drawinglayer
396 
397 //////////////////////////////////////////////////////////////////////////////
398 
399 namespace drawinglayer
400 {
401     namespace primitive2d
402     {
403         OverlayRollingRectanglePrimitive::OverlayRollingRectanglePrimitive(
404             const basegfx::B2DRange& aRollingRectangle,
405             const basegfx::BColor& rRGBColorA,
406             const basegfx::BColor& rRGBColorB,
407             double fDiscreteDashLength)
408         :   ViewportDependentPrimitive2D(),
409             maRollingRectangle(aRollingRectangle),
410             maRGBColorA(rRGBColorA),
411             maRGBColorB(rRGBColorB),
412             mfDiscreteDashLength(fDiscreteDashLength)
413         {}
414 
415         Primitive2DSequence OverlayRollingRectanglePrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
416         {
417             // use the prepared Viewport information accessible using getViewport()
418             Primitive2DSequence aRetval;
419 
420             if(!getViewport().isEmpty())
421             {
422                 basegfx::B2DPolygon aLine;
423                 aRetval.realloc(8);
424 
425                 // Left lines
426                 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMinY()));
427                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY()));
428                 aRetval[0] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
429 
430                 aLine.clear();
431                 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMaxY()));
432                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY()));
433                 aRetval[1] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
434 
435                 // Right lines
436                 aLine.clear();
437                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY()));
438                 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMinY()));
439                 aRetval[2] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
440 
441                 aLine.clear();
442                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY()));
443                 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMaxY()));
444                 aRetval[3] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
445 
446                 // Top lines
447                 aLine.clear();
448                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMinY()));
449                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY()));
450                 aRetval[4] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
451 
452                 aLine.clear();
453                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMinY()));
454                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY()));
455                 aRetval[5] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
456 
457                 // Bottom lines
458                 aLine.clear();
459                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY()));
460                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMaxY()));
461                 aRetval[6] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
462 
463                 aLine.clear();
464                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY()));
465                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMaxY()));
466                 aRetval[7] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
467             }
468 
469             return aRetval;
470         }
471 
472         bool OverlayRollingRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
473         {
474             if(ViewportDependentPrimitive2D::operator==(rPrimitive))
475             {
476                 const OverlayRollingRectanglePrimitive& rCompare = static_cast< const OverlayRollingRectanglePrimitive& >(rPrimitive);
477 
478                 return (getRollingRectangle() == rCompare.getRollingRectangle()
479                     && getRGBColorA() == rCompare.getRGBColorA()
480                     && getRGBColorB() == rCompare.getRGBColorB()
481                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
482             }
483 
484             return false;
485         }
486 
487         ImplPrimitrive2DIDBlock(OverlayRollingRectanglePrimitive, PRIMITIVE2D_ID_OVERLAYROLLINGRECTANGLEPRIMITIVE)
488 
489     } // end of namespace primitive2d
490 } // end of namespace drawinglayer
491 
492 //////////////////////////////////////////////////////////////////////////////
493 // eof
494