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