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() - getCenterX()) * getDiscreteUnit()) + getBasePosition().getX());
71                 const double fBottom(((aBitmapSize.getHeight() - 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                     3, // same default as VCL, a minimum of three discrete units (pixels) offset
240 					false);
241                 const Primitive2DReference aPrimitive(
242                     new PolyPolygonHatchPrimitive2D(
243                         aHatchPolyPolygon,
244                         aEmptyColor,
245                         aFillHatchAttribute));
246 
247                 aRetval = Primitive2DSequence(&aPrimitive, 1);
248             }
249 
250             return aRetval;
251 		}
252 
253 		bool OverlayHatchRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
254 		{
255 			if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
256 			{
257 				const OverlayHatchRectanglePrimitive& rCompare = static_cast< const OverlayHatchRectanglePrimitive& >(rPrimitive);
258 
259 				return (getObjectRange() == rCompare.getObjectRange()
260 					&& getDiscreteHatchDistance() == rCompare.getDiscreteHatchDistance()
261 					&& getHatchRotation() == rCompare.getHatchRotation()
262 					&& getHatchColor() == rCompare.getHatchColor()
263 					&& getDiscreteGrow() == rCompare.getDiscreteGrow()
264 					&& getDiscreteShrink() == rCompare.getDiscreteShrink()
265 					&& getRotation() == rCompare.getRotation());
266 			}
267 
268 			return false;
269 		}
270 
271 		ImplPrimitrive2DIDBlock(OverlayHatchRectanglePrimitive, PRIMITIVE2D_ID_OVERLAYHATCHRECTANGLEPRIMITIVE)
272 
273 	} // end of namespace primitive2d
274 } // end of namespace drawinglayer
275 
276 //////////////////////////////////////////////////////////////////////////////
277 
278 namespace drawinglayer
279 {
280 	namespace primitive2d
281 	{
282         OverlayHelplineStripedPrimitive::OverlayHelplineStripedPrimitive(
283             const basegfx::B2DPoint& rBasePosition,
284             HelplineStyle eStyle,
285 			const basegfx::BColor& rRGBColorA,
286 			const basegfx::BColor& rRGBColorB,
287 			double fDiscreteDashLength)
288         :   ViewportDependentPrimitive2D(),
289 			maBasePosition(rBasePosition),
290             meStyle(eStyle),
291 			maRGBColorA(rRGBColorA),
292 			maRGBColorB(rRGBColorB),
293 			mfDiscreteDashLength(fDiscreteDashLength)
294         {}
295 
296 		Primitive2DSequence OverlayHelplineStripedPrimitive::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
297 		{
298             // use the prepared Viewport information accessible using getViewport()
299             Primitive2DSequence aRetval;
300 
301             if(!getViewport().isEmpty())
302             {
303 			    switch(getStyle())
304 			    {
305 				    case HELPLINESTYLE_VERTICAL :
306 				    {
307                         aRetval.realloc(1);
308                         basegfx::B2DPolygon aLine;
309 
310                         aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMinY()));
311 					    aLine.append(basegfx::B2DPoint(getBasePosition().getX(), getViewport().getMaxY()));
312 
313                         aRetval[0] = Primitive2DReference(
314                             new PolygonMarkerPrimitive2D(
315                                 aLine,
316                                 getRGBColorA(),
317                                 getRGBColorB(),
318                                 getDiscreteDashLength()));
319 					    break;
320 				    }
321 
322 				    case HELPLINESTYLE_HORIZONTAL :
323 				    {
324                         aRetval.realloc(1);
325                         basegfx::B2DPolygon aLine;
326 
327                         aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getBasePosition().getY()));
328 					    aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getBasePosition().getY()));
329 
330                         aRetval[0] = Primitive2DReference(
331                             new PolygonMarkerPrimitive2D(
332                                 aLine,
333                                 getRGBColorA(),
334                                 getRGBColorB(),
335                                 getDiscreteDashLength()));
336 					    break;
337 				    }
338 
339                     default: // case HELPLINESTYLE_POINT :
340 				    {
341             			const double fDiscreteUnit((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0)).getLength());
342                         aRetval.realloc(2);
343                         basegfx::B2DPolygon aLineA, aLineB;
344 
345 					    aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() - fDiscreteUnit));
346 					    aLineA.append(basegfx::B2DPoint(getBasePosition().getX(), getBasePosition().getY() + fDiscreteUnit));
347 
348                         aRetval[0] = Primitive2DReference(
349                             new PolygonMarkerPrimitive2D(
350                                 aLineA,
351                                 getRGBColorA(),
352                                 getRGBColorB(),
353                                 getDiscreteDashLength()));
354 
355 					    aLineB.append(basegfx::B2DPoint(getBasePosition().getX() - fDiscreteUnit, getBasePosition().getY()));
356 					    aLineB.append(basegfx::B2DPoint(getBasePosition().getX() + fDiscreteUnit, getBasePosition().getY()));
357 
358                         aRetval[1] = Primitive2DReference(
359                             new PolygonMarkerPrimitive2D(
360                                 aLineB,
361                                 getRGBColorA(),
362                                 getRGBColorB(),
363                                 getDiscreteDashLength()));
364 
365 					    break;
366 				    }
367 			    }
368             }
369 
370             return aRetval;
371 		}
372 
373 		bool OverlayHelplineStripedPrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
374 		{
375 			if(ViewportDependentPrimitive2D::operator==(rPrimitive))
376 			{
377 				const OverlayHelplineStripedPrimitive& rCompare = static_cast< const OverlayHelplineStripedPrimitive& >(rPrimitive);
378 
379 				return (getBasePosition() == rCompare.getBasePosition()
380                     && getStyle() == rCompare.getStyle()
381 					&& getRGBColorA() == rCompare.getRGBColorA()
382 					&& getRGBColorB() == rCompare.getRGBColorB()
383                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
384 			}
385 
386 			return false;
387 		}
388 
389 		ImplPrimitrive2DIDBlock(OverlayHelplineStripedPrimitive, PRIMITIVE2D_ID_OVERLAYHELPLINESTRIPEDPRIMITIVE)
390 
391 	} // end of namespace primitive2d
392 } // end of namespace drawinglayer
393 
394 //////////////////////////////////////////////////////////////////////////////
395 
396 namespace drawinglayer
397 {
398 	namespace primitive2d
399 	{
400         OverlayRollingRectanglePrimitive::OverlayRollingRectanglePrimitive(
401             const basegfx::B2DRange& aRollingRectangle,
402 			const basegfx::BColor& rRGBColorA,
403 			const basegfx::BColor& rRGBColorB,
404 			double fDiscreteDashLength)
405         :   ViewportDependentPrimitive2D(),
406 			maRollingRectangle(aRollingRectangle),
407 			maRGBColorA(rRGBColorA),
408 			maRGBColorB(rRGBColorB),
409 			mfDiscreteDashLength(fDiscreteDashLength)
410         {}
411 
412 		Primitive2DSequence OverlayRollingRectanglePrimitive::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
413 		{
414             // use the prepared Viewport information accessible using getViewport()
415             Primitive2DSequence aRetval;
416 
417             if(!getViewport().isEmpty())
418             {
419                 basegfx::B2DPolygon aLine;
420                 aRetval.realloc(8);
421 
422 				// Left lines
423                 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMinY()));
424                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY()));
425                 aRetval[0] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
426 
427                 aLine.clear();
428                 aLine.append(basegfx::B2DPoint(getViewport().getMinX(), getRollingRectangle().getMaxY()));
429                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY()));
430                 aRetval[1] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
431 
432 				// Right lines
433                 aLine.clear();
434                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY()));
435                 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMinY()));
436                 aRetval[2] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
437 
438                 aLine.clear();
439                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY()));
440                 aLine.append(basegfx::B2DPoint(getViewport().getMaxX(), getRollingRectangle().getMaxY()));
441                 aRetval[3] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
442 
443 				// Top lines
444                 aLine.clear();
445                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMinY()));
446                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMinY()));
447                 aRetval[4] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
448 
449                 aLine.clear();
450                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMinY()));
451                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMinY()));
452                 aRetval[5] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
453 
454 				// Bottom lines
455                 aLine.clear();
456                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getRollingRectangle().getMaxY()));
457                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMinX(), getViewport().getMaxY()));
458                 aRetval[6] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
459 
460                 aLine.clear();
461                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getRollingRectangle().getMaxY()));
462                 aLine.append(basegfx::B2DPoint(getRollingRectangle().getMaxX(), getViewport().getMaxY()));
463                 aRetval[7] = Primitive2DReference(new PolygonMarkerPrimitive2D(aLine, getRGBColorA(), getRGBColorB(), getDiscreteDashLength()));
464             }
465 
466             return aRetval;
467 		}
468 
469 		bool OverlayRollingRectanglePrimitive::operator==( const BasePrimitive2D& rPrimitive ) const
470 		{
471 			if(ViewportDependentPrimitive2D::operator==(rPrimitive))
472 			{
473 				const OverlayRollingRectanglePrimitive& rCompare = static_cast< const OverlayRollingRectanglePrimitive& >(rPrimitive);
474 
475 				return (getRollingRectangle() == rCompare.getRollingRectangle()
476 					&& getRGBColorA() == rCompare.getRGBColorA()
477 					&& getRGBColorB() == rCompare.getRGBColorB()
478                     && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
479 			}
480 
481 			return false;
482 		}
483 
484 		ImplPrimitrive2DIDBlock(OverlayRollingRectanglePrimitive, PRIMITIVE2D_ID_OVERLAYROLLINGRECTANGLEPRIMITIVE)
485 
486 	} // end of namespace primitive2d
487 } // end of namespace drawinglayer
488 
489 //////////////////////////////////////////////////////////////////////////////
490 // eof
491