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