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