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