Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
21 : #include <basegfx/tools/canvastools.hxx>
22 : #include <basegfx/polygon/b2dpolygontools.hxx>
23 : #include <basegfx/polygon/b2dpolypolygontools.hxx>
24 : #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
25 : #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
26 : #include <drawinglayer/geometry/viewinformation2d.hxx>
27 : #include <basegfx/polygon/b2dlinegeometry.hxx>
28 : #include <com/sun/star/drawing/LineCap.hpp>
29 :
30 : //////////////////////////////////////////////////////////////////////////////
31 :
32 : using namespace com::sun::star;
33 :
34 : //////////////////////////////////////////////////////////////////////////////
35 :
36 : namespace drawinglayer
37 : {
38 : namespace primitive2d
39 : {
40 2443 : PolygonHairlinePrimitive2D::PolygonHairlinePrimitive2D(
41 : const basegfx::B2DPolygon& rPolygon,
42 : const basegfx::BColor& rBColor)
43 : : BasePrimitive2D(),
44 : maPolygon(rPolygon),
45 2443 : maBColor(rBColor)
46 : {
47 2443 : }
48 :
49 12 : bool PolygonHairlinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
50 : {
51 12 : if(BasePrimitive2D::operator==(rPrimitive))
52 : {
53 12 : const PolygonHairlinePrimitive2D& rCompare = (PolygonHairlinePrimitive2D&)rPrimitive;
54 :
55 12 : return (getB2DPolygon() == rCompare.getB2DPolygon()
56 12 : && getBColor() == rCompare.getBColor());
57 : }
58 :
59 0 : return false;
60 : }
61 :
62 37 : basegfx::B2DRange PolygonHairlinePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
63 : {
64 : // this is a hairline, thus the line width is view-dependent. Get range of polygon
65 : // as base size
66 37 : basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange());
67 :
68 37 : if(!aRetval.isEmpty())
69 : {
70 : // Calculate view-dependent hairline width
71 37 : const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
72 37 : const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
73 :
74 37 : if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
75 : {
76 37 : aRetval.grow(fDiscreteHalfLineWidth);
77 37 : }
78 : }
79 :
80 : // return range
81 37 : return aRetval;
82 : }
83 :
84 : // provide unique ID
85 2443 : ImplPrimitrive2DIDBlock(PolygonHairlinePrimitive2D, PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D)
86 :
87 : } // end of namespace primitive2d
88 : } // end of namespace drawinglayer
89 :
90 : //////////////////////////////////////////////////////////////////////////////
91 :
92 : namespace drawinglayer
93 : {
94 : namespace primitive2d
95 : {
96 0 : Primitive2DSequence PolygonMarkerPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
97 : {
98 : // calculate logic DashLength
99 0 : const basegfx::B2DVector aDashVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(getDiscreteDashLength(), 0.0));
100 0 : const double fLogicDashLength(aDashVector.getX());
101 :
102 0 : if(fLogicDashLength > 0.0 && !getRGBColorA().equal(getRGBColorB()))
103 : {
104 : // apply dashing; get line and gap snippets
105 0 : ::std::vector< double > aDash;
106 0 : basegfx::B2DPolyPolygon aDashedPolyPolyA;
107 0 : basegfx::B2DPolyPolygon aDashedPolyPolyB;
108 :
109 0 : aDash.push_back(fLogicDashLength);
110 0 : aDash.push_back(fLogicDashLength);
111 0 : basegfx::tools::applyLineDashing(getB2DPolygon(), aDash, &aDashedPolyPolyA, &aDashedPolyPolyB, 2.0 * fLogicDashLength);
112 :
113 : // prepare return value
114 0 : Primitive2DSequence aRetval(2);
115 :
116 0 : aRetval[0] = Primitive2DReference(new PolyPolygonHairlinePrimitive2D(aDashedPolyPolyA, getRGBColorA()));
117 0 : aRetval[1] = Primitive2DReference(new PolyPolygonHairlinePrimitive2D(aDashedPolyPolyB, getRGBColorB()));
118 :
119 0 : return aRetval;
120 : }
121 : else
122 : {
123 0 : const Primitive2DReference xRef(new PolygonHairlinePrimitive2D(getB2DPolygon(), getRGBColorA()));
124 0 : return Primitive2DSequence(&xRef, 1L);
125 0 : }
126 : }
127 :
128 0 : PolygonMarkerPrimitive2D::PolygonMarkerPrimitive2D(
129 : const basegfx::B2DPolygon& rPolygon,
130 : const basegfx::BColor& rRGBColorA,
131 : const basegfx::BColor& rRGBColorB,
132 : double fDiscreteDashLength)
133 : : BufferedDecompositionPrimitive2D(),
134 : maPolygon(rPolygon),
135 : maRGBColorA(rRGBColorA),
136 : maRGBColorB(rRGBColorB),
137 : mfDiscreteDashLength(fDiscreteDashLength),
138 0 : maLastInverseObjectToViewTransformation()
139 : {
140 0 : }
141 :
142 0 : bool PolygonMarkerPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
143 : {
144 0 : if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
145 : {
146 0 : const PolygonMarkerPrimitive2D& rCompare = (PolygonMarkerPrimitive2D&)rPrimitive;
147 :
148 0 : return (getB2DPolygon() == rCompare.getB2DPolygon()
149 0 : && getRGBColorA() == rCompare.getRGBColorA()
150 0 : && getRGBColorB() == rCompare.getRGBColorB()
151 0 : && getDiscreteDashLength() == rCompare.getDiscreteDashLength());
152 : }
153 :
154 0 : return false;
155 : }
156 :
157 0 : basegfx::B2DRange PolygonMarkerPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
158 : {
159 : // this is a hairline, thus the line width is view-dependent. Get range of polygon
160 : // as base size
161 0 : basegfx::B2DRange aRetval(getB2DPolygon().getB2DRange());
162 :
163 0 : if(!aRetval.isEmpty())
164 : {
165 : // Calculate view-dependent hairline width
166 0 : const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
167 0 : const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
168 :
169 0 : if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
170 : {
171 0 : aRetval.grow(fDiscreteHalfLineWidth);
172 0 : }
173 : }
174 :
175 : // return range
176 0 : return aRetval;
177 : }
178 :
179 0 : Primitive2DSequence PolygonMarkerPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
180 : {
181 0 : ::osl::MutexGuard aGuard( m_aMutex );
182 0 : bool bNeedNewDecomposition(false);
183 :
184 0 : if(getBuffered2DDecomposition().hasElements())
185 : {
186 0 : if(rViewInformation.getInverseObjectToViewTransformation() != maLastInverseObjectToViewTransformation)
187 : {
188 0 : bNeedNewDecomposition = true;
189 : }
190 : }
191 :
192 0 : if(bNeedNewDecomposition)
193 : {
194 : // conditions of last local decomposition have changed, delete
195 0 : const_cast< PolygonMarkerPrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DSequence());
196 : }
197 :
198 0 : if(!getBuffered2DDecomposition().hasElements())
199 : {
200 : // remember last used InverseObjectToViewTransformation
201 0 : PolygonMarkerPrimitive2D* pThat = const_cast< PolygonMarkerPrimitive2D* >(this);
202 0 : pThat->maLastInverseObjectToViewTransformation = rViewInformation.getInverseObjectToViewTransformation();
203 : }
204 :
205 : // use parent implementation
206 0 : return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
207 : }
208 :
209 : // provide unique ID
210 0 : ImplPrimitrive2DIDBlock(PolygonMarkerPrimitive2D, PRIMITIVE2D_ID_POLYGONMARKERPRIMITIVE2D)
211 :
212 : } // end of namespace primitive2d
213 : } // end of namespace drawinglayer
214 :
215 : //////////////////////////////////////////////////////////////////////////////
216 :
217 : namespace drawinglayer
218 : {
219 : namespace primitive2d
220 : {
221 94 : Primitive2DSequence PolygonStrokePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
222 : {
223 94 : if(getB2DPolygon().count())
224 : {
225 : // #i102241# try to simplify before usage
226 94 : const basegfx::B2DPolygon aB2DPolygon(basegfx::tools::simplifyCurveSegments(getB2DPolygon()));
227 94 : basegfx::B2DPolyPolygon aHairLinePolyPolygon;
228 :
229 94 : if(getStrokeAttribute().isDefault() || 0.0 == getStrokeAttribute().getFullDotDashLen())
230 : {
231 : // no line dashing, just copy
232 86 : aHairLinePolyPolygon.append(aB2DPolygon);
233 : }
234 : else
235 : {
236 : // apply LineStyle
237 : basegfx::tools::applyLineDashing(
238 8 : aB2DPolygon, getStrokeAttribute().getDotDashArray(),
239 16 : &aHairLinePolyPolygon, 0, getStrokeAttribute().getFullDotDashLen());
240 : }
241 :
242 94 : const sal_uInt32 nCount(aHairLinePolyPolygon.count());
243 :
244 94 : if(!getLineAttribute().isDefault() && getLineAttribute().getWidth())
245 : {
246 : // create fat line data
247 80 : const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0);
248 80 : const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin());
249 80 : const com::sun::star::drawing::LineCap aLineCap(getLineAttribute().getLineCap());
250 80 : basegfx::B2DPolyPolygon aAreaPolyPolygon;
251 :
252 160 : for(sal_uInt32 a(0L); a < nCount; a++)
253 : {
254 : // New version of createAreaGeometry; now creates bezier polygons
255 : aAreaPolyPolygon.append(basegfx::tools::createAreaGeometry(
256 : aHairLinePolyPolygon.getB2DPolygon(a),
257 : fHalfLineWidth,
258 : aLineJoin,
259 80 : aLineCap));
260 : }
261 :
262 : // prepare return value
263 80 : Primitive2DSequence aRetval(aAreaPolyPolygon.count());
264 :
265 : // create primitive
266 160 : for(sal_uInt32 b(0L); b < aAreaPolyPolygon.count(); b++)
267 : {
268 : // put into single polyPolygon primitives to make clear that this is NOT meant
269 : // to be painted as a single PolyPolygon (XORed as fill rule). Alternatively, a
270 : // melting process may be used here one day.
271 80 : const basegfx::B2DPolyPolygon aNewPolyPolygon(aAreaPolyPolygon.getB2DPolygon(b));
272 : static bool bTestByUsingRandomColor(false);
273 : const basegfx::BColor aColor(bTestByUsingRandomColor
274 0 : ? basegfx::BColor(rand() / 32767.0, rand() / 32767.0, rand() / 32767.0)
275 80 : : getLineAttribute().getColor());
276 80 : const Primitive2DReference xRef(new PolyPolygonColorPrimitive2D(aNewPolyPolygon, aColor));
277 80 : aRetval[b] = xRef;
278 80 : }
279 :
280 80 : return aRetval;
281 : }
282 : else
283 : {
284 : // prepare return value
285 : const Primitive2DReference xRef(
286 : new PolyPolygonHairlinePrimitive2D(
287 : aHairLinePolyPolygon,
288 14 : getLineAttribute().getColor()));
289 :
290 14 : return Primitive2DSequence(&xRef, 1);
291 94 : }
292 : }
293 : else
294 : {
295 0 : return Primitive2DSequence();
296 : }
297 : }
298 :
299 146 : PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(
300 : const basegfx::B2DPolygon& rPolygon,
301 : const attribute::LineAttribute& rLineAttribute,
302 : const attribute::StrokeAttribute& rStrokeAttribute)
303 : : BufferedDecompositionPrimitive2D(),
304 : maPolygon(rPolygon),
305 : maLineAttribute(rLineAttribute),
306 146 : maStrokeAttribute(rStrokeAttribute)
307 : {
308 146 : }
309 :
310 12 : PolygonStrokePrimitive2D::PolygonStrokePrimitive2D(
311 : const basegfx::B2DPolygon& rPolygon,
312 : const attribute::LineAttribute& rLineAttribute)
313 : : BufferedDecompositionPrimitive2D(),
314 : maPolygon(rPolygon),
315 : maLineAttribute(rLineAttribute),
316 12 : maStrokeAttribute()
317 : {
318 12 : }
319 :
320 0 : bool PolygonStrokePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
321 : {
322 0 : if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
323 : {
324 0 : const PolygonStrokePrimitive2D& rCompare = (PolygonStrokePrimitive2D&)rPrimitive;
325 :
326 0 : return (getB2DPolygon() == rCompare.getB2DPolygon()
327 0 : && getLineAttribute() == rCompare.getLineAttribute()
328 0 : && getStrokeAttribute() == rCompare.getStrokeAttribute());
329 : }
330 :
331 0 : return false;
332 : }
333 :
334 207 : basegfx::B2DRange PolygonStrokePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
335 : {
336 207 : basegfx::B2DRange aRetval;
337 :
338 207 : if(getLineAttribute().getWidth())
339 : {
340 125 : bool bUseDecomposition(false);
341 :
342 125 : if(basegfx::B2DLINEJOIN_MITER == getLineAttribute().getLineJoin())
343 : {
344 : // if line is mitered, use parent call since mitered line
345 : // geometry may use more space than the geometry grown by half line width
346 80 : bUseDecomposition = true;
347 : }
348 :
349 125 : if(!bUseDecomposition && com::sun::star::drawing::LineCap_SQUARE == getLineAttribute().getLineCap())
350 : {
351 : // when drawing::LineCap_SQUARE is used the below method to grow the polygon
352 : // range by half line width will not work, so use decomposition. Interestingly,
353 : // the grow method below works perfectly for LineCap_ROUND since the grow is in
354 : // all directions and the rounded cap needs the same grow in all directions independent
355 : // from it's orientation. Unfortunately this is not the case for drawing::LineCap_SQUARE
356 0 : bUseDecomposition = true;
357 : }
358 :
359 125 : if(bUseDecomposition)
360 : {
361 : // get correct range by using the decomposition fallback, reasons see above cases
362 80 : aRetval = BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
363 : }
364 : else
365 : {
366 : // for all other B2DLINEJOIN_* get the range from the base geometry
367 : // and expand by half the line width
368 45 : aRetval = getB2DPolygon().getB2DRange();
369 45 : aRetval.grow(getLineAttribute().getWidth() * 0.5);
370 : }
371 : }
372 : else
373 : {
374 : // this is a hairline, thus the line width is view-dependent. Get range of polygon
375 : // as base size
376 82 : aRetval = getB2DPolygon().getB2DRange();
377 :
378 82 : if(!aRetval.isEmpty())
379 : {
380 : // Calculate view-dependent hairline width
381 82 : const basegfx::B2DVector aDiscreteSize(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 0.0));
382 82 : const double fDiscreteHalfLineWidth(aDiscreteSize.getLength() * 0.5);
383 :
384 82 : if(basegfx::fTools::more(fDiscreteHalfLineWidth, 0.0))
385 : {
386 82 : aRetval.grow(fDiscreteHalfLineWidth);
387 82 : }
388 : }
389 : }
390 :
391 207 : return aRetval;
392 : }
393 :
394 : // provide unique ID
395 51 : ImplPrimitrive2DIDBlock(PolygonStrokePrimitive2D, PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D)
396 :
397 : } // end of namespace primitive2d
398 : } // end of namespace drawinglayer
399 :
400 : //////////////////////////////////////////////////////////////////////////////
401 :
402 : namespace drawinglayer
403 : {
404 : namespace primitive2d
405 : {
406 0 : Primitive2DSequence PolygonWavePrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
407 : {
408 0 : Primitive2DSequence aRetval;
409 :
410 0 : if(getB2DPolygon().count())
411 : {
412 0 : const bool bHasWidth(!basegfx::fTools::equalZero(getWaveWidth()));
413 0 : const bool bHasHeight(!basegfx::fTools::equalZero(getWaveHeight()));
414 :
415 0 : if(bHasWidth && bHasHeight)
416 : {
417 : // create waveline curve
418 0 : const basegfx::B2DPolygon aWaveline(basegfx::tools::createWaveline(getB2DPolygon(), getWaveWidth(), getWaveHeight()));
419 0 : const Primitive2DReference xRef(new PolygonStrokePrimitive2D(aWaveline, getLineAttribute(), getStrokeAttribute()));
420 0 : aRetval = Primitive2DSequence(&xRef, 1);
421 : }
422 : else
423 : {
424 : // flat waveline, decompose to simple line primitive
425 0 : const Primitive2DReference xRef(new PolygonStrokePrimitive2D(getB2DPolygon(), getLineAttribute(), getStrokeAttribute()));
426 0 : aRetval = Primitive2DSequence(&xRef, 1);
427 : }
428 : }
429 :
430 0 : return aRetval;
431 : }
432 :
433 0 : PolygonWavePrimitive2D::PolygonWavePrimitive2D(
434 : const basegfx::B2DPolygon& rPolygon,
435 : const attribute::LineAttribute& rLineAttribute,
436 : const attribute::StrokeAttribute& rStrokeAttribute,
437 : double fWaveWidth,
438 : double fWaveHeight)
439 : : PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute),
440 : mfWaveWidth(fWaveWidth),
441 0 : mfWaveHeight(fWaveHeight)
442 : {
443 0 : if(mfWaveWidth < 0.0)
444 : {
445 0 : mfWaveWidth = 0.0;
446 : }
447 :
448 0 : if(mfWaveHeight < 0.0)
449 : {
450 0 : mfWaveHeight = 0.0;
451 : }
452 0 : }
453 :
454 0 : PolygonWavePrimitive2D::PolygonWavePrimitive2D(
455 : const basegfx::B2DPolygon& rPolygon,
456 : const attribute::LineAttribute& rLineAttribute,
457 : double fWaveWidth,
458 : double fWaveHeight)
459 : : PolygonStrokePrimitive2D(rPolygon, rLineAttribute),
460 : mfWaveWidth(fWaveWidth),
461 0 : mfWaveHeight(fWaveHeight)
462 : {
463 0 : if(mfWaveWidth < 0.0)
464 : {
465 0 : mfWaveWidth = 0.0;
466 : }
467 :
468 0 : if(mfWaveHeight < 0.0)
469 : {
470 0 : mfWaveHeight = 0.0;
471 : }
472 0 : }
473 :
474 0 : bool PolygonWavePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
475 : {
476 0 : if(PolygonStrokePrimitive2D::operator==(rPrimitive))
477 : {
478 0 : const PolygonWavePrimitive2D& rCompare = (PolygonWavePrimitive2D&)rPrimitive;
479 :
480 0 : return (getWaveWidth() == rCompare.getWaveWidth()
481 0 : && getWaveHeight() == rCompare.getWaveHeight());
482 : }
483 :
484 0 : return false;
485 : }
486 :
487 0 : basegfx::B2DRange PolygonWavePrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
488 : {
489 : // get range of parent
490 0 : basegfx::B2DRange aRetval(PolygonStrokePrimitive2D::getB2DRange(rViewInformation));
491 :
492 : // if WaveHeight, grow by it
493 0 : if(basegfx::fTools::more(getWaveHeight(), 0.0))
494 : {
495 0 : aRetval.grow(getWaveHeight());
496 : }
497 :
498 : // if line width, grow by it
499 0 : if(basegfx::fTools::more(getLineAttribute().getWidth(), 0.0))
500 : {
501 0 : aRetval.grow(getLineAttribute().getWidth() * 0.5);
502 : }
503 :
504 0 : return aRetval;
505 : }
506 :
507 : // provide unique ID
508 0 : ImplPrimitrive2DIDBlock(PolygonWavePrimitive2D, PRIMITIVE2D_ID_POLYGONWAVEPRIMITIVE2D)
509 :
510 : } // end of namespace primitive2d
511 : } // end of namespace drawinglayer
512 :
513 : //////////////////////////////////////////////////////////////////////////////
514 :
515 : namespace drawinglayer
516 : {
517 : namespace primitive2d
518 : {
519 1 : Primitive2DSequence PolygonStrokeArrowPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
520 : {
521 : // copy local polygon, it may be changed
522 1 : basegfx::B2DPolygon aLocalPolygon(getB2DPolygon());
523 1 : aLocalPolygon.removeDoublePoints();
524 1 : basegfx::B2DPolyPolygon aArrowA;
525 1 : basegfx::B2DPolyPolygon aArrowB;
526 :
527 1 : if(!aLocalPolygon.isClosed() && aLocalPolygon.count() > 1)
528 : {
529 : // apply arrows
530 1 : const double fPolyLength(basegfx::tools::getLength(aLocalPolygon));
531 1 : double fStart(0.0);
532 1 : double fEnd(0.0);
533 1 : double fStartOverlap(0.0);
534 1 : double fEndOverlap(0.0);
535 :
536 1 : if(!getStart().isDefault() && getStart().isActive())
537 : {
538 : // create start arrow primitive and consume
539 : aArrowA = basegfx::tools::createAreaGeometryForLineStartEnd(
540 0 : aLocalPolygon, getStart().getB2DPolyPolygon(), true, getStart().getWidth(),
541 0 : fPolyLength, getStart().isCentered() ? 0.5 : 0.0, &fStart);
542 :
543 : // create some overlapping, compromise between straight and peaked markers
544 : // for marker width 0.3cm and marker line width 0.02cm
545 0 : fStartOverlap = getStart().getWidth() / 15.0;
546 : }
547 :
548 1 : if(!getEnd().isDefault() && getEnd().isActive())
549 : {
550 : // create end arrow primitive and consume
551 : aArrowB = basegfx::tools::createAreaGeometryForLineStartEnd(
552 2 : aLocalPolygon, getEnd().getB2DPolyPolygon(), false, getEnd().getWidth(),
553 3 : fPolyLength, getEnd().isCentered() ? 0.5 : 0.0, &fEnd);
554 :
555 : // create some overlapping
556 1 : fEndOverlap = getEnd().getWidth() / 15.0;
557 : }
558 :
559 1 : if(0.0 != fStart || 0.0 != fEnd)
560 : {
561 : // build new poly, consume something from old poly
562 1 : aLocalPolygon = basegfx::tools::getSnippetAbsolute(aLocalPolygon, fStart-fStartOverlap, fPolyLength - fEnd + fEndOverlap, fPolyLength);
563 : }
564 : }
565 :
566 : // prepare return value
567 1 : Primitive2DSequence aRetval(1L + (aArrowA.count() ? 1L : 0L) + (aArrowB.count() ? 1L : 0L));
568 1 : sal_uInt32 nInd(0L);
569 :
570 : // add shaft
571 : const Primitive2DReference xRefShaft(new
572 : PolygonStrokePrimitive2D(
573 1 : aLocalPolygon, getLineAttribute(), getStrokeAttribute()));
574 1 : aRetval[nInd++] = xRefShaft;
575 :
576 1 : if(aArrowA.count())
577 : {
578 : const Primitive2DReference xRefA(
579 : new PolyPolygonColorPrimitive2D(
580 0 : aArrowA, getLineAttribute().getColor()));
581 0 : aRetval[nInd++] = xRefA;
582 : }
583 :
584 1 : if(aArrowB.count())
585 : {
586 : const Primitive2DReference xRefB(
587 : new PolyPolygonColorPrimitive2D(
588 1 : aArrowB, getLineAttribute().getColor()));
589 1 : aRetval[nInd++] = xRefB;
590 : }
591 :
592 1 : return aRetval;
593 : }
594 :
595 1 : PolygonStrokeArrowPrimitive2D::PolygonStrokeArrowPrimitive2D(
596 : const basegfx::B2DPolygon& rPolygon,
597 : const attribute::LineAttribute& rLineAttribute,
598 : const attribute::StrokeAttribute& rStrokeAttribute,
599 : const attribute::LineStartEndAttribute& rStart,
600 : const attribute::LineStartEndAttribute& rEnd)
601 : : PolygonStrokePrimitive2D(rPolygon, rLineAttribute, rStrokeAttribute),
602 : maStart(rStart),
603 1 : maEnd(rEnd)
604 : {
605 1 : }
606 :
607 0 : bool PolygonStrokeArrowPrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const
608 : {
609 0 : if(PolygonStrokePrimitive2D::operator==(rPrimitive))
610 : {
611 0 : const PolygonStrokeArrowPrimitive2D& rCompare = (PolygonStrokeArrowPrimitive2D&)rPrimitive;
612 :
613 0 : return (getStart() == rCompare.getStart()
614 0 : && getEnd() == rCompare.getEnd());
615 : }
616 :
617 0 : return false;
618 : }
619 :
620 4 : basegfx::B2DRange PolygonStrokeArrowPrimitive2D::getB2DRange(const geometry::ViewInformation2D& rViewInformation) const
621 : {
622 4 : basegfx::B2DRange aRetval;
623 :
624 4 : if(getStart().isActive() || getEnd().isActive())
625 : {
626 : // use decomposition when line start/end is used
627 4 : return BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
628 : }
629 : else
630 : {
631 : // get range from parent
632 0 : return PolygonStrokePrimitive2D::getB2DRange(rViewInformation);
633 : }
634 : }
635 :
636 : // provide unique ID
637 2 : ImplPrimitrive2DIDBlock(PolygonStrokeArrowPrimitive2D, PRIMITIVE2D_ID_POLYGONSTROKEARROWPRIMITIVE2D)
638 :
639 : } // end of namespace primitive2d
640 : } // end of namespace drawinglayer
641 :
642 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|