1*ddde725dSArmin Le Grand /************************************************************** 2*ddde725dSArmin Le Grand * 3*ddde725dSArmin Le Grand * Licensed to the Apache Software Foundation (ASF) under one 4*ddde725dSArmin Le Grand * or more contributor license agreements. See the NOTICE file 5*ddde725dSArmin Le Grand * distributed with this work for additional information 6*ddde725dSArmin Le Grand * regarding copyright ownership. The ASF licenses this file 7*ddde725dSArmin Le Grand * to you under the Apache License, Version 2.0 (the 8*ddde725dSArmin Le Grand * "License"); you may not use this file except in compliance 9*ddde725dSArmin Le Grand * with the License. You may obtain a copy of the License at 10*ddde725dSArmin Le Grand * 11*ddde725dSArmin Le Grand * http://www.apache.org/licenses/LICENSE-2.0 12*ddde725dSArmin Le Grand * 13*ddde725dSArmin Le Grand * Unless required by applicable law or agreed to in writing, 14*ddde725dSArmin Le Grand * software distributed under the License is distributed on an 15*ddde725dSArmin Le Grand * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*ddde725dSArmin Le Grand * KIND, either express or implied. See the License for the 17*ddde725dSArmin Le Grand * specific language governing permissions and limitations 18*ddde725dSArmin Le Grand * under the License. 19*ddde725dSArmin Le Grand * 20*ddde725dSArmin Le Grand *************************************************************/ 21*ddde725dSArmin Le Grand 22*ddde725dSArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove 23*ddde725dSArmin Le Grand #include "precompiled_svgio.hxx" 24*ddde725dSArmin Le Grand 25*ddde725dSArmin Le Grand #include <svgio/svgreader/svgstyleattributes.hxx> 26*ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/transformprimitive2d.hxx> 27*ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> 28*ddde725dSArmin Le Grand #include <svgio/svgreader/svgnode.hxx> 29*ddde725dSArmin Le Grand #include <svgio/svgreader/svgdocument.hxx> 30*ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/svggradientprimitive2d.hxx> 31*ddde725dSArmin Le Grand #include <svgio/svgreader/svggradientnode.hxx> 32*ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx> 33*ddde725dSArmin Le Grand #include <basegfx/vector/b2enums.hxx> 34*ddde725dSArmin Le Grand #include <drawinglayer/processor2d/linegeometryextractor2d.hxx> 35*ddde725dSArmin Le Grand #include <drawinglayer/processor2d/textaspolygonextractor2d.hxx> 36*ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolypolygoncutter.hxx> 37*ddde725dSArmin Le Grand #include <svgio/svgreader/svgclippathnode.hxx> 38*ddde725dSArmin Le Grand #include <svgio/svgreader/svgmasknode.hxx> 39*ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolypolygoncutter.hxx> 40*ddde725dSArmin Le Grand #include <basegfx/polygon/b2dpolypolygontools.hxx> 41*ddde725dSArmin Le Grand #include <svgio/svgreader/svgmarkernode.hxx> 42*ddde725dSArmin Le Grand #include <basegfx/curve/b2dcubicbezier.hxx> 43*ddde725dSArmin Le Grand #include <svgio/svgreader/svgpatternnode.hxx> 44*ddde725dSArmin Le Grand #include <drawinglayer/primitive2d/patternfillprimitive2d.hxx> 45*ddde725dSArmin Le Grand 46*ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 47*ddde725dSArmin Le Grand 48*ddde725dSArmin Le Grand namespace svgio 49*ddde725dSArmin Le Grand { 50*ddde725dSArmin Le Grand namespace svgreader 51*ddde725dSArmin Le Grand { 52*ddde725dSArmin Le Grand basegfx::B2DLineJoin StrokeLinejoinToB2DLineJoin(StrokeLinejoin aStrokeLinejoin) 53*ddde725dSArmin Le Grand { 54*ddde725dSArmin Le Grand if(StrokeLinejoin_round == aStrokeLinejoin) 55*ddde725dSArmin Le Grand { 56*ddde725dSArmin Le Grand return basegfx::B2DLINEJOIN_ROUND; 57*ddde725dSArmin Le Grand } 58*ddde725dSArmin Le Grand else if(StrokeLinejoin_bevel == aStrokeLinejoin) 59*ddde725dSArmin Le Grand { 60*ddde725dSArmin Le Grand return basegfx::B2DLINEJOIN_BEVEL; 61*ddde725dSArmin Le Grand } 62*ddde725dSArmin Le Grand 63*ddde725dSArmin Le Grand return basegfx::B2DLINEJOIN_MITER; 64*ddde725dSArmin Le Grand } 65*ddde725dSArmin Le Grand 66*ddde725dSArmin Le Grand FontStretch getWider(FontStretch aSource) 67*ddde725dSArmin Le Grand { 68*ddde725dSArmin Le Grand switch(aSource) 69*ddde725dSArmin Le Grand { 70*ddde725dSArmin Le Grand case FontStretch_ultra_condensed: aSource = FontStretch_extra_condensed; break; 71*ddde725dSArmin Le Grand case FontStretch_extra_condensed: aSource = FontStretch_condensed; break; 72*ddde725dSArmin Le Grand case FontStretch_condensed: aSource = FontStretch_semi_condensed; break; 73*ddde725dSArmin Le Grand case FontStretch_semi_condensed: aSource = FontStretch_normal; break; 74*ddde725dSArmin Le Grand case FontStretch_normal: aSource = FontStretch_semi_expanded; break; 75*ddde725dSArmin Le Grand case FontStretch_semi_expanded: aSource = FontStretch_expanded; break; 76*ddde725dSArmin Le Grand case FontStretch_expanded: aSource = FontStretch_extra_expanded; break; 77*ddde725dSArmin Le Grand case FontStretch_extra_expanded: aSource = FontStretch_ultra_expanded; break; 78*ddde725dSArmin Le Grand } 79*ddde725dSArmin Le Grand 80*ddde725dSArmin Le Grand return aSource; 81*ddde725dSArmin Le Grand } 82*ddde725dSArmin Le Grand 83*ddde725dSArmin Le Grand FontStretch getNarrower(FontStretch aSource) 84*ddde725dSArmin Le Grand { 85*ddde725dSArmin Le Grand switch(aSource) 86*ddde725dSArmin Le Grand { 87*ddde725dSArmin Le Grand case FontStretch_extra_condensed: aSource = FontStretch_ultra_condensed; break; 88*ddde725dSArmin Le Grand case FontStretch_condensed: aSource = FontStretch_extra_condensed; break; 89*ddde725dSArmin Le Grand case FontStretch_semi_condensed: aSource = FontStretch_condensed; break; 90*ddde725dSArmin Le Grand case FontStretch_normal: aSource = FontStretch_semi_condensed; break; 91*ddde725dSArmin Le Grand case FontStretch_semi_expanded: aSource = FontStretch_normal; break; 92*ddde725dSArmin Le Grand case FontStretch_expanded: aSource = FontStretch_semi_expanded; break; 93*ddde725dSArmin Le Grand case FontStretch_extra_expanded: aSource = FontStretch_expanded; break; 94*ddde725dSArmin Le Grand case FontStretch_ultra_expanded: aSource = FontStretch_extra_expanded; break; 95*ddde725dSArmin Le Grand } 96*ddde725dSArmin Le Grand 97*ddde725dSArmin Le Grand return aSource; 98*ddde725dSArmin Le Grand } 99*ddde725dSArmin Le Grand 100*ddde725dSArmin Le Grand FontWeight getBolder(FontWeight aSource) 101*ddde725dSArmin Le Grand { 102*ddde725dSArmin Le Grand switch(aSource) 103*ddde725dSArmin Le Grand { 104*ddde725dSArmin Le Grand case FontWeight_100: aSource = FontWeight_200; break; 105*ddde725dSArmin Le Grand case FontWeight_200: aSource = FontWeight_300; break; 106*ddde725dSArmin Le Grand case FontWeight_300: aSource = FontWeight_400; break; 107*ddde725dSArmin Le Grand case FontWeight_400: aSource = FontWeight_500; break; 108*ddde725dSArmin Le Grand case FontWeight_500: aSource = FontWeight_600; break; 109*ddde725dSArmin Le Grand case FontWeight_600: aSource = FontWeight_700; break; 110*ddde725dSArmin Le Grand case FontWeight_700: aSource = FontWeight_800; break; 111*ddde725dSArmin Le Grand case FontWeight_800: aSource = FontWeight_900; break; 112*ddde725dSArmin Le Grand } 113*ddde725dSArmin Le Grand 114*ddde725dSArmin Le Grand return aSource; 115*ddde725dSArmin Le Grand } 116*ddde725dSArmin Le Grand 117*ddde725dSArmin Le Grand FontWeight getLighter(FontWeight aSource) 118*ddde725dSArmin Le Grand { 119*ddde725dSArmin Le Grand switch(aSource) 120*ddde725dSArmin Le Grand { 121*ddde725dSArmin Le Grand case FontWeight_200: aSource = FontWeight_100; break; 122*ddde725dSArmin Le Grand case FontWeight_300: aSource = FontWeight_200; break; 123*ddde725dSArmin Le Grand case FontWeight_400: aSource = FontWeight_300; break; 124*ddde725dSArmin Le Grand case FontWeight_500: aSource = FontWeight_400; break; 125*ddde725dSArmin Le Grand case FontWeight_600: aSource = FontWeight_500; break; 126*ddde725dSArmin Le Grand case FontWeight_700: aSource = FontWeight_600; break; 127*ddde725dSArmin Le Grand case FontWeight_800: aSource = FontWeight_700; break; 128*ddde725dSArmin Le Grand case FontWeight_900: aSource = FontWeight_800; break; 129*ddde725dSArmin Le Grand } 130*ddde725dSArmin Le Grand 131*ddde725dSArmin Le Grand return aSource; 132*ddde725dSArmin Le Grand } 133*ddde725dSArmin Le Grand 134*ddde725dSArmin Le Grand ::FontWeight getVclFontWeight(FontWeight aSource) 135*ddde725dSArmin Le Grand { 136*ddde725dSArmin Le Grand ::FontWeight nRetval(WEIGHT_NORMAL); 137*ddde725dSArmin Le Grand 138*ddde725dSArmin Le Grand switch(aSource) 139*ddde725dSArmin Le Grand { 140*ddde725dSArmin Le Grand case FontWeight_100: nRetval = WEIGHT_ULTRALIGHT; break; 141*ddde725dSArmin Le Grand case FontWeight_200: nRetval = WEIGHT_LIGHT; break; 142*ddde725dSArmin Le Grand case FontWeight_300: nRetval = WEIGHT_SEMILIGHT; break; 143*ddde725dSArmin Le Grand case FontWeight_400: nRetval = WEIGHT_NORMAL; break; 144*ddde725dSArmin Le Grand case FontWeight_500: nRetval = WEIGHT_MEDIUM; break; 145*ddde725dSArmin Le Grand case FontWeight_600: nRetval = WEIGHT_SEMIBOLD; break; 146*ddde725dSArmin Le Grand case FontWeight_700: nRetval = WEIGHT_BOLD; break; 147*ddde725dSArmin Le Grand case FontWeight_800: nRetval = WEIGHT_ULTRABOLD; break; 148*ddde725dSArmin Le Grand case FontWeight_900: nRetval = WEIGHT_BLACK; break; 149*ddde725dSArmin Le Grand } 150*ddde725dSArmin Le Grand 151*ddde725dSArmin Le Grand return nRetval; 152*ddde725dSArmin Le Grand } 153*ddde725dSArmin Le Grand 154*ddde725dSArmin Le Grand void SvgStyleAttributes::readStyle(const rtl::OUString& rCandidate) 155*ddde725dSArmin Le Grand { 156*ddde725dSArmin Le Grand const sal_Int32 nLen(rCandidate.getLength()); 157*ddde725dSArmin Le Grand sal_Int32 nPos(0); 158*ddde725dSArmin Le Grand 159*ddde725dSArmin Le Grand while(nPos < nLen) 160*ddde725dSArmin Le Grand { 161*ddde725dSArmin Le Grand const sal_Int32 nInitPos(nPos); 162*ddde725dSArmin Le Grand skip_char(rCandidate, sal_Unicode(' '), nPos, nLen); 163*ddde725dSArmin Le Grand rtl::OUStringBuffer aTokenName; 164*ddde725dSArmin Le Grand copyString(rCandidate, nPos, aTokenName, nLen); 165*ddde725dSArmin Le Grand 166*ddde725dSArmin Le Grand if(aTokenName.getLength()) 167*ddde725dSArmin Le Grand { 168*ddde725dSArmin Le Grand skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(':'), nPos, nLen); 169*ddde725dSArmin Le Grand rtl::OUStringBuffer aTokenValue; 170*ddde725dSArmin Le Grand copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aTokenValue, nLen); 171*ddde725dSArmin Le Grand skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen); 172*ddde725dSArmin Le Grand const rtl::OUString aOUTokenName(aTokenName.makeStringAndClear()); 173*ddde725dSArmin Le Grand const rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear()); 174*ddde725dSArmin Le Grand 175*ddde725dSArmin Le Grand parseStyleAttribute(aOUTokenName, StrToSVGToken(aOUTokenName), aOUTokenValue); 176*ddde725dSArmin Le Grand } 177*ddde725dSArmin Le Grand 178*ddde725dSArmin Le Grand if(nInitPos == nPos) 179*ddde725dSArmin Le Grand { 180*ddde725dSArmin Le Grand OSL_ENSURE(false, "Could not interpret on current position (!)"); 181*ddde725dSArmin Le Grand nPos++; 182*ddde725dSArmin Le Grand } 183*ddde725dSArmin Le Grand } 184*ddde725dSArmin Le Grand } 185*ddde725dSArmin Le Grand 186*ddde725dSArmin Le Grand void SvgStyleAttributes::checkForCssStyle(const rtl::OUString& rClassStr) const 187*ddde725dSArmin Le Grand { 188*ddde725dSArmin Le Grand if(!mpCssStyleParent) 189*ddde725dSArmin Le Grand { 190*ddde725dSArmin Le Grand const SvgDocument& rDocument = mrOwner.getDocument(); 191*ddde725dSArmin Le Grand const SvgStyleAttributes* pNew = 0; 192*ddde725dSArmin Le Grand 193*ddde725dSArmin Le Grand if(rDocument.hasSvgStyleAttributesById()) 194*ddde725dSArmin Le Grand { 195*ddde725dSArmin Le Grand if(mrOwner.getClass()) 196*ddde725dSArmin Le Grand { 197*ddde725dSArmin Le Grand rtl::OUString aId(rtl::OUString::createFromAscii(".")); 198*ddde725dSArmin Le Grand aId = aId + *mrOwner.getClass(); 199*ddde725dSArmin Le Grand pNew = rDocument.findSvgStyleAttributesById(aId); 200*ddde725dSArmin Le Grand 201*ddde725dSArmin Le Grand if(!pNew) 202*ddde725dSArmin Le Grand { 203*ddde725dSArmin Le Grand aId = rClassStr + aId; 204*ddde725dSArmin Le Grand 205*ddde725dSArmin Le Grand pNew = rDocument.findSvgStyleAttributesById(aId); 206*ddde725dSArmin Le Grand } 207*ddde725dSArmin Le Grand } 208*ddde725dSArmin Le Grand else if(mrOwner.getId()) 209*ddde725dSArmin Le Grand { 210*ddde725dSArmin Le Grand pNew = rDocument.findSvgStyleAttributesById(*mrOwner.getId()); 211*ddde725dSArmin Le Grand } 212*ddde725dSArmin Le Grand 213*ddde725dSArmin Le Grand if(pNew) 214*ddde725dSArmin Le Grand { 215*ddde725dSArmin Le Grand // found css style, set as parent 216*ddde725dSArmin Le Grand const_cast< SvgStyleAttributes* >(this)->mpCssStyleParent = pNew; 217*ddde725dSArmin Le Grand } 218*ddde725dSArmin Le Grand } 219*ddde725dSArmin Le Grand } 220*ddde725dSArmin Le Grand } 221*ddde725dSArmin Le Grand 222*ddde725dSArmin Le Grand const SvgStyleAttributes* SvgStyleAttributes::getParentStyle() const 223*ddde725dSArmin Le Grand { 224*ddde725dSArmin Le Grand if(mpCssStyleParent) 225*ddde725dSArmin Le Grand { 226*ddde725dSArmin Le Grand return mpCssStyleParent; 227*ddde725dSArmin Le Grand } 228*ddde725dSArmin Le Grand 229*ddde725dSArmin Le Grand if(mrOwner.getParent()) 230*ddde725dSArmin Le Grand { 231*ddde725dSArmin Le Grand return mrOwner.getParent()->getSvgStyleAttributes(); 232*ddde725dSArmin Le Grand } 233*ddde725dSArmin Le Grand 234*ddde725dSArmin Le Grand return 0; 235*ddde725dSArmin Le Grand } 236*ddde725dSArmin Le Grand 237*ddde725dSArmin Le Grand void SvgStyleAttributes::add_text( 238*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 239*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rSource) const 240*ddde725dSArmin Le Grand { 241*ddde725dSArmin Le Grand if(rSource.hasElements()) 242*ddde725dSArmin Le Grand { 243*ddde725dSArmin Le Grand // at this point the primitives in rSource are of type TextSimplePortionPrimitive2D 244*ddde725dSArmin Le Grand // or TextDecoratedPortionPrimitive2D and have the Fill Color (pAttributes->getFill()) 245*ddde725dSArmin Le Grand // set. When another fill is used and also evtl. stroke is set it gets necessary to 246*ddde725dSArmin Le Grand // dismantle to geometry and add needed primitives 247*ddde725dSArmin Le Grand const basegfx::BColor* pFill = getFill(); 248*ddde725dSArmin Le Grand const SvgGradientNode* pFillGradient = getSvgGradientNodeFill(); 249*ddde725dSArmin Le Grand const SvgPatternNode* pFillPattern = getSvgPatternNodeFill(); 250*ddde725dSArmin Le Grand const basegfx::BColor* pStroke = getStroke(); 251*ddde725dSArmin Le Grand const SvgGradientNode* pStrokeGradient = getSvgGradientNodeStroke(); 252*ddde725dSArmin Le Grand const SvgPatternNode* pStrokePattern = getSvgPatternNodeStroke(); 253*ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aMergedArea; 254*ddde725dSArmin Le Grand 255*ddde725dSArmin Le Grand if(pFillGradient || pFillPattern || pStroke || pStrokeGradient || pStrokePattern) 256*ddde725dSArmin Le Grand { 257*ddde725dSArmin Le Grand // text geometry is needed, create 258*ddde725dSArmin Le Grand // use neutral ViewInformation and create LineGeometryExtractor2D 259*ddde725dSArmin Le Grand const drawinglayer::geometry::ViewInformation2D aViewInformation2D; 260*ddde725dSArmin Le Grand drawinglayer::processor2d::TextAsPolygonExtractor2D aExtractor(aViewInformation2D); 261*ddde725dSArmin Le Grand 262*ddde725dSArmin Le Grand // proccess 263*ddde725dSArmin Le Grand aExtractor.process(rSource); 264*ddde725dSArmin Le Grand 265*ddde725dSArmin Le Grand // get results 266*ddde725dSArmin Le Grand const drawinglayer::processor2d::TextAsPolygonDataNodeVector& rResult = aExtractor.getTarget(); 267*ddde725dSArmin Le Grand const sal_uInt32 nResultCount(rResult.size()); 268*ddde725dSArmin Le Grand basegfx::B2DPolyPolygonVector aTextFillVector; 269*ddde725dSArmin Le Grand aTextFillVector.reserve(nResultCount); 270*ddde725dSArmin Le Grand 271*ddde725dSArmin Le Grand for(sal_uInt32 a(0); a < nResultCount; a++) 272*ddde725dSArmin Le Grand { 273*ddde725dSArmin Le Grand const drawinglayer::processor2d::TextAsPolygonDataNode& rCandidate = rResult[a]; 274*ddde725dSArmin Le Grand 275*ddde725dSArmin Le Grand if(rCandidate.getIsFilled()) 276*ddde725dSArmin Le Grand { 277*ddde725dSArmin Le Grand aTextFillVector.push_back(rCandidate.getB2DPolyPolygon()); 278*ddde725dSArmin Le Grand } 279*ddde725dSArmin Le Grand } 280*ddde725dSArmin Le Grand 281*ddde725dSArmin Le Grand if(!aTextFillVector.empty()) 282*ddde725dSArmin Le Grand { 283*ddde725dSArmin Le Grand aMergedArea = basegfx::tools::mergeToSinglePolyPolygon(aTextFillVector); 284*ddde725dSArmin Le Grand } 285*ddde725dSArmin Le Grand } 286*ddde725dSArmin Le Grand 287*ddde725dSArmin Le Grand const bool bStrokeUsed(pStroke || pStrokeGradient || pStrokePattern); 288*ddde725dSArmin Le Grand 289*ddde725dSArmin Le Grand // add fill. Use geometry even for simple color fill when stroke 290*ddde725dSArmin Le Grand // is used, else text rendering and the geometry-based stroke will 291*ddde725dSArmin Le Grand // normally not really match optically due to divrese system text 292*ddde725dSArmin Le Grand // renderers 293*ddde725dSArmin Le Grand if(aMergedArea.count() && (pFillGradient || pFillPattern || bStrokeUsed)) 294*ddde725dSArmin Le Grand { 295*ddde725dSArmin Le Grand // create text fill content based on geometry 296*ddde725dSArmin Le Grand add_fill(aMergedArea, rTarget, aMergedArea.getB2DRange()); 297*ddde725dSArmin Le Grand } 298*ddde725dSArmin Le Grand else if(pFill) 299*ddde725dSArmin Le Grand { 300*ddde725dSArmin Le Grand // add the already prepared primitives for single color fill 301*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, rSource); 302*ddde725dSArmin Le Grand } 303*ddde725dSArmin Le Grand 304*ddde725dSArmin Le Grand // add stroke 305*ddde725dSArmin Le Grand if(aMergedArea.count() && bStrokeUsed) 306*ddde725dSArmin Le Grand { 307*ddde725dSArmin Le Grand // create text stroke content 308*ddde725dSArmin Le Grand add_stroke(aMergedArea, rTarget, aMergedArea.getB2DRange()); 309*ddde725dSArmin Le Grand } 310*ddde725dSArmin Le Grand } 311*ddde725dSArmin Le Grand } 312*ddde725dSArmin Le Grand 313*ddde725dSArmin Le Grand void SvgStyleAttributes::add_fillGradient( 314*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPath, 315*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 316*ddde725dSArmin Le Grand const SvgGradientNode& rFillGradient, 317*ddde725dSArmin Le Grand const basegfx::B2DRange& rGeoRange) const 318*ddde725dSArmin Le Grand { 319*ddde725dSArmin Le Grand // create fill content 320*ddde725dSArmin Le Grand drawinglayer::primitive2d::SvgGradientEntryVector aSvgGradientEntryVector; 321*ddde725dSArmin Le Grand 322*ddde725dSArmin Le Grand // get the color stops 323*ddde725dSArmin Le Grand rFillGradient.collectGradientEntries(aSvgGradientEntryVector); 324*ddde725dSArmin Le Grand 325*ddde725dSArmin Le Grand if(!aSvgGradientEntryVector.empty()) 326*ddde725dSArmin Le Grand { 327*ddde725dSArmin Le Grand basegfx::B2DHomMatrix aGeoToUnit; 328*ddde725dSArmin Le Grand 329*ddde725dSArmin Le Grand if(rFillGradient.getGradientTransform()) 330*ddde725dSArmin Le Grand { 331*ddde725dSArmin Le Grand aGeoToUnit = *rFillGradient.getGradientTransform(); 332*ddde725dSArmin Le Grand } 333*ddde725dSArmin Le Grand 334*ddde725dSArmin Le Grand if(userSpaceOnUse == rFillGradient.getGradientUnits()) 335*ddde725dSArmin Le Grand { 336*ddde725dSArmin Le Grand aGeoToUnit.translate(-rGeoRange.getMinX(), -rGeoRange.getMinY()); 337*ddde725dSArmin Le Grand aGeoToUnit.scale(1.0 / rGeoRange.getWidth(), 1.0 / rGeoRange.getHeight()); 338*ddde725dSArmin Le Grand } 339*ddde725dSArmin Le Grand 340*ddde725dSArmin Le Grand if(SVGTokenLinearGradient == rFillGradient.getType()) 341*ddde725dSArmin Le Grand { 342*ddde725dSArmin Le Grand basegfx::B2DPoint aStart(0.0, 0.0); 343*ddde725dSArmin Le Grand basegfx::B2DPoint aEnd(1.0, 0.0); 344*ddde725dSArmin Le Grand 345*ddde725dSArmin Le Grand if(userSpaceOnUse == rFillGradient.getGradientUnits()) 346*ddde725dSArmin Le Grand { 347*ddde725dSArmin Le Grand // all possible units 348*ddde725dSArmin Le Grand aStart.setX(rFillGradient.getX1().solve(mrOwner, xcoordinate)); 349*ddde725dSArmin Le Grand aStart.setY(rFillGradient.getY1().solve(mrOwner, ycoordinate)); 350*ddde725dSArmin Le Grand aEnd.setX(rFillGradient.getX2().solve(mrOwner, xcoordinate)); 351*ddde725dSArmin Le Grand aEnd.setY(rFillGradient.getY2().solve(mrOwner, ycoordinate)); 352*ddde725dSArmin Le Grand } 353*ddde725dSArmin Le Grand else 354*ddde725dSArmin Le Grand { 355*ddde725dSArmin Le Grand // fractions or percent relative to object bounds 356*ddde725dSArmin Le Grand const SvgNumber X1(rFillGradient.getX1()); 357*ddde725dSArmin Le Grand const SvgNumber Y1(rFillGradient.getY1()); 358*ddde725dSArmin Le Grand const SvgNumber X2(rFillGradient.getX2()); 359*ddde725dSArmin Le Grand const SvgNumber Y2(rFillGradient.getY2()); 360*ddde725dSArmin Le Grand 361*ddde725dSArmin Le Grand aStart.setX(Unit_percent == X1.getUnit() ? X1.getNumber() * 0.01 : X1.getNumber()); 362*ddde725dSArmin Le Grand aStart.setY(Unit_percent == Y1.getUnit() ? Y1.getNumber() * 0.01 : Y1.getNumber()); 363*ddde725dSArmin Le Grand aEnd.setX(Unit_percent == X2.getUnit() ? X2.getNumber() * 0.01 : X2.getNumber()); 364*ddde725dSArmin Le Grand aEnd.setY(Unit_percent == Y2.getUnit() ? Y2.getNumber() * 0.01 : Y2.getNumber()); 365*ddde725dSArmin Le Grand } 366*ddde725dSArmin Le Grand 367*ddde725dSArmin Le Grand if(!aGeoToUnit.isIdentity()) 368*ddde725dSArmin Le Grand { 369*ddde725dSArmin Le Grand aStart *= aGeoToUnit; 370*ddde725dSArmin Le Grand aEnd *= aGeoToUnit; 371*ddde725dSArmin Le Grand } 372*ddde725dSArmin Le Grand 373*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( 374*ddde725dSArmin Le Grand rTarget, 375*ddde725dSArmin Le Grand new drawinglayer::primitive2d::SvgLinearGradientPrimitive2D( 376*ddde725dSArmin Le Grand rPath, 377*ddde725dSArmin Le Grand aSvgGradientEntryVector, 378*ddde725dSArmin Le Grand aStart, 379*ddde725dSArmin Le Grand aEnd, 380*ddde725dSArmin Le Grand rFillGradient.getSpreadMethod())); 381*ddde725dSArmin Le Grand } 382*ddde725dSArmin Le Grand else 383*ddde725dSArmin Le Grand { 384*ddde725dSArmin Le Grand basegfx::B2DPoint aStart(0.5, 0.5); 385*ddde725dSArmin Le Grand basegfx::B2DPoint aFocal; 386*ddde725dSArmin Le Grand double fRadius(0.5); 387*ddde725dSArmin Le Grand const SvgNumber* pFx = rFillGradient.getFx(); 388*ddde725dSArmin Le Grand const SvgNumber* pFy = rFillGradient.getFy(); 389*ddde725dSArmin Le Grand const bool bFocal(pFx || pFy); 390*ddde725dSArmin Le Grand 391*ddde725dSArmin Le Grand if(userSpaceOnUse == rFillGradient.getGradientUnits()) 392*ddde725dSArmin Le Grand { 393*ddde725dSArmin Le Grand // all possible units 394*ddde725dSArmin Le Grand aStart.setX(rFillGradient.getCx().solve(mrOwner, xcoordinate)); 395*ddde725dSArmin Le Grand aStart.setY(rFillGradient.getCy().solve(mrOwner, ycoordinate)); 396*ddde725dSArmin Le Grand fRadius = rFillGradient.getR().solve(mrOwner, length); 397*ddde725dSArmin Le Grand 398*ddde725dSArmin Le Grand if(bFocal) 399*ddde725dSArmin Le Grand { 400*ddde725dSArmin Le Grand aFocal.setX(pFx ? pFx->solve(mrOwner, xcoordinate) : aStart.getX()); 401*ddde725dSArmin Le Grand aFocal.setY(pFy ? pFy->solve(mrOwner, ycoordinate) : aStart.getY()); 402*ddde725dSArmin Le Grand } 403*ddde725dSArmin Le Grand } 404*ddde725dSArmin Le Grand else 405*ddde725dSArmin Le Grand { 406*ddde725dSArmin Le Grand // fractions or percent relative to object bounds 407*ddde725dSArmin Le Grand const SvgNumber Cx(rFillGradient.getCx()); 408*ddde725dSArmin Le Grand const SvgNumber Cy(rFillGradient.getCy()); 409*ddde725dSArmin Le Grand const SvgNumber R(rFillGradient.getR()); 410*ddde725dSArmin Le Grand 411*ddde725dSArmin Le Grand aStart.setX(Unit_percent == Cx.getUnit() ? Cx.getNumber() * 0.01 : Cx.getNumber()); 412*ddde725dSArmin Le Grand aStart.setY(Unit_percent == Cy.getUnit() ? Cy.getNumber() * 0.01 : Cy.getNumber()); 413*ddde725dSArmin Le Grand fRadius = (Unit_percent == R.getUnit()) ? R.getNumber() * 0.01 : R.getNumber(); 414*ddde725dSArmin Le Grand 415*ddde725dSArmin Le Grand if(bFocal) 416*ddde725dSArmin Le Grand { 417*ddde725dSArmin Le Grand aFocal.setX(pFx ? (Unit_percent == pFx->getUnit() ? pFx->getNumber() * 0.01 : pFx->getNumber()) : aStart.getX()); 418*ddde725dSArmin Le Grand aFocal.setY(pFy ? (Unit_percent == pFy->getUnit() ? pFy->getNumber() * 0.01 : pFy->getNumber()) : aStart.getY()); 419*ddde725dSArmin Le Grand } 420*ddde725dSArmin Le Grand } 421*ddde725dSArmin Le Grand 422*ddde725dSArmin Le Grand if(!aGeoToUnit.isIdentity()) 423*ddde725dSArmin Le Grand { 424*ddde725dSArmin Le Grand aStart *= aGeoToUnit; 425*ddde725dSArmin Le Grand fRadius = (aGeoToUnit * basegfx::B2DVector(fRadius, 0.0)).getLength(); 426*ddde725dSArmin Le Grand 427*ddde725dSArmin Le Grand if(bFocal) 428*ddde725dSArmin Le Grand { 429*ddde725dSArmin Le Grand aFocal *= aGeoToUnit; 430*ddde725dSArmin Le Grand } 431*ddde725dSArmin Le Grand } 432*ddde725dSArmin Le Grand 433*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( 434*ddde725dSArmin Le Grand rTarget, 435*ddde725dSArmin Le Grand new drawinglayer::primitive2d::SvgRadialGradientPrimitive2D( 436*ddde725dSArmin Le Grand rPath, 437*ddde725dSArmin Le Grand aSvgGradientEntryVector, 438*ddde725dSArmin Le Grand aStart, 439*ddde725dSArmin Le Grand fRadius, 440*ddde725dSArmin Le Grand rFillGradient.getSpreadMethod(), 441*ddde725dSArmin Le Grand bFocal ? &aFocal : 0)); 442*ddde725dSArmin Le Grand } 443*ddde725dSArmin Le Grand } 444*ddde725dSArmin Le Grand } 445*ddde725dSArmin Le Grand 446*ddde725dSArmin Le Grand void SvgStyleAttributes::add_fillPatternTransform( 447*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPath, 448*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 449*ddde725dSArmin Le Grand const SvgPatternNode& rFillPattern, 450*ddde725dSArmin Le Grand const basegfx::B2DRange& rGeoRange) const 451*ddde725dSArmin Le Grand { 452*ddde725dSArmin Le Grand // prepare fill polyPolygon with given pattern, check for patternTransform 453*ddde725dSArmin Le Grand if(rFillPattern.getPatternTransform() && !rFillPattern.getPatternTransform()->isIdentity()) 454*ddde725dSArmin Le Grand { 455*ddde725dSArmin Le Grand // PatternTransform is active; Handle by filling the inverse transformed 456*ddde725dSArmin Le Grand // path and back-transforming the result 457*ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aPath(rPath); 458*ddde725dSArmin Le Grand basegfx::B2DHomMatrix aInv(*rFillPattern.getPatternTransform()); 459*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence aNewTarget; 460*ddde725dSArmin Le Grand 461*ddde725dSArmin Le Grand aInv.invert(); 462*ddde725dSArmin Le Grand aPath.transform(aInv); 463*ddde725dSArmin Le Grand add_fillPattern(aPath, aNewTarget, rFillPattern, aPath.getB2DRange()); 464*ddde725dSArmin Le Grand 465*ddde725dSArmin Le Grand if(aNewTarget.hasElements()) 466*ddde725dSArmin Le Grand { 467*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( 468*ddde725dSArmin Le Grand rTarget, 469*ddde725dSArmin Le Grand new drawinglayer::primitive2d::TransformPrimitive2D( 470*ddde725dSArmin Le Grand *rFillPattern.getPatternTransform(), 471*ddde725dSArmin Le Grand aNewTarget)); 472*ddde725dSArmin Le Grand } 473*ddde725dSArmin Le Grand } 474*ddde725dSArmin Le Grand else 475*ddde725dSArmin Le Grand { 476*ddde725dSArmin Le Grand // no patternTransform, create fillPattern directly 477*ddde725dSArmin Le Grand add_fillPattern(rPath, rTarget, rFillPattern, rGeoRange); 478*ddde725dSArmin Le Grand } 479*ddde725dSArmin Le Grand } 480*ddde725dSArmin Le Grand 481*ddde725dSArmin Le Grand void SvgStyleAttributes::add_fillPattern( 482*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPath, 483*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 484*ddde725dSArmin Le Grand const SvgPatternNode& rFillPattern, 485*ddde725dSArmin Le Grand const basegfx::B2DRange& rGeoRange) const 486*ddde725dSArmin Le Grand { 487*ddde725dSArmin Le Grand // fill polyPolygon with given pattern 488*ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DSequence& rPrimitives = rFillPattern.getPatternPrimitives(); 489*ddde725dSArmin Le Grand 490*ddde725dSArmin Le Grand if(rPrimitives.hasElements()) 491*ddde725dSArmin Le Grand { 492*ddde725dSArmin Le Grand double fTargetWidth(rGeoRange.getWidth()); 493*ddde725dSArmin Le Grand double fTargetHeight(rGeoRange.getHeight()); 494*ddde725dSArmin Le Grand 495*ddde725dSArmin Le Grand if(fTargetWidth > 0.0 && fTargetHeight > 0.0) 496*ddde725dSArmin Le Grand { 497*ddde725dSArmin Le Grand // get relative values from pattern 498*ddde725dSArmin Le Grand double fX(0.0); 499*ddde725dSArmin Le Grand double fY(0.0); 500*ddde725dSArmin Le Grand double fW(0.0); 501*ddde725dSArmin Le Grand double fH(0.0); 502*ddde725dSArmin Le Grand 503*ddde725dSArmin Le Grand rFillPattern.getValuesRelative(fX, fY, fW, fH, rGeoRange, mrOwner); 504*ddde725dSArmin Le Grand 505*ddde725dSArmin Le Grand if(fW > 0.0 && fH > 0.0) 506*ddde725dSArmin Le Grand { 507*ddde725dSArmin Le Grand // build the reference range relative to the rGeoRange 508*ddde725dSArmin Le Grand const basegfx::B2DRange aReferenceRange(fX, fY, fX + fW, fY + fH); 509*ddde725dSArmin Le Grand 510*ddde725dSArmin Le Grand // find out how the content is mapped to the reference range 511*ddde725dSArmin Le Grand basegfx::B2DHomMatrix aMapPrimitivesToUnitRange; 512*ddde725dSArmin Le Grand const basegfx::B2DRange* pViewBox = rFillPattern.getViewBox(); 513*ddde725dSArmin Le Grand 514*ddde725dSArmin Le Grand if(pViewBox) 515*ddde725dSArmin Le Grand { 516*ddde725dSArmin Le Grand // use viewBox/preserveAspectRatio 517*ddde725dSArmin Le Grand const SvgAspectRatio& rRatio = rFillPattern.getSvgAspectRatio(); 518*ddde725dSArmin Le Grand const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0); 519*ddde725dSArmin Le Grand 520*ddde725dSArmin Le Grand if(rRatio.isSet()) 521*ddde725dSArmin Le Grand { 522*ddde725dSArmin Le Grand // let mapping be created from SvgAspectRatio 523*ddde725dSArmin Le Grand aMapPrimitivesToUnitRange = rRatio.createMapping(aUnitRange, *pViewBox); 524*ddde725dSArmin Le Grand } 525*ddde725dSArmin Le Grand else 526*ddde725dSArmin Le Grand { 527*ddde725dSArmin Le Grand // choose default mapping 528*ddde725dSArmin Le Grand aMapPrimitivesToUnitRange = rRatio.createLinearMapping(aUnitRange, *pViewBox); 529*ddde725dSArmin Le Grand } 530*ddde725dSArmin Le Grand } 531*ddde725dSArmin Le Grand else 532*ddde725dSArmin Le Grand { 533*ddde725dSArmin Le Grand // use patternContentUnits 534*ddde725dSArmin Le Grand const SvgUnits aPatternContentUnits(rFillPattern.getPatternContentUnits() ? *rFillPattern.getPatternContentUnits() : userSpaceOnUse); 535*ddde725dSArmin Le Grand 536*ddde725dSArmin Le Grand if(userSpaceOnUse == aPatternContentUnits) 537*ddde725dSArmin Le Grand { 538*ddde725dSArmin Le Grand // create relative mapping to unit coordinates 539*ddde725dSArmin Le Grand aMapPrimitivesToUnitRange.scale(1.0 / (fW * fTargetWidth), 1.0 / (fH * fTargetHeight)); 540*ddde725dSArmin Le Grand } 541*ddde725dSArmin Le Grand else 542*ddde725dSArmin Le Grand { 543*ddde725dSArmin Le Grand aMapPrimitivesToUnitRange.scale(1.0 / fW, 1.0 / fH); 544*ddde725dSArmin Le Grand } 545*ddde725dSArmin Le Grand } 546*ddde725dSArmin Le Grand 547*ddde725dSArmin Le Grand // apply aMapPrimitivesToUnitRange to content when used 548*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence aPrimitives(rPrimitives); 549*ddde725dSArmin Le Grand 550*ddde725dSArmin Le Grand if(!aMapPrimitivesToUnitRange.isIdentity()) 551*ddde725dSArmin Le Grand { 552*ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xRef( 553*ddde725dSArmin Le Grand new drawinglayer::primitive2d::TransformPrimitive2D( 554*ddde725dSArmin Le Grand aMapPrimitivesToUnitRange, 555*ddde725dSArmin Le Grand aPrimitives)); 556*ddde725dSArmin Le Grand 557*ddde725dSArmin Le Grand aPrimitives = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); 558*ddde725dSArmin Le Grand } 559*ddde725dSArmin Le Grand 560*ddde725dSArmin Le Grand // embed in PatternFillPrimitive2D 561*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( 562*ddde725dSArmin Le Grand rTarget, 563*ddde725dSArmin Le Grand new drawinglayer::primitive2d::PatternFillPrimitive2D( 564*ddde725dSArmin Le Grand rPath, 565*ddde725dSArmin Le Grand aPrimitives, 566*ddde725dSArmin Le Grand aReferenceRange)); 567*ddde725dSArmin Le Grand } 568*ddde725dSArmin Le Grand } 569*ddde725dSArmin Le Grand } 570*ddde725dSArmin Le Grand } 571*ddde725dSArmin Le Grand 572*ddde725dSArmin Le Grand void SvgStyleAttributes::add_fill( 573*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPath, 574*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 575*ddde725dSArmin Le Grand const basegfx::B2DRange& rGeoRange) const 576*ddde725dSArmin Le Grand { 577*ddde725dSArmin Le Grand const basegfx::BColor* pFill = getFill(); 578*ddde725dSArmin Le Grand const SvgGradientNode* pFillGradient = getSvgGradientNodeFill(); 579*ddde725dSArmin Le Grand const SvgPatternNode* pFillPattern = getSvgPatternNodeFill(); 580*ddde725dSArmin Le Grand 581*ddde725dSArmin Le Grand if(pFill || pFillGradient || pFillPattern) 582*ddde725dSArmin Le Grand { 583*ddde725dSArmin Le Grand const double fFillOpacity(getFillOpacity().solve(mrOwner, length)); 584*ddde725dSArmin Le Grand 585*ddde725dSArmin Le Grand if(basegfx::fTools::more(fFillOpacity, 0.0)) 586*ddde725dSArmin Le Grand { 587*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence aNewFill; 588*ddde725dSArmin Le Grand 589*ddde725dSArmin Le Grand if(pFillGradient) 590*ddde725dSArmin Le Grand { 591*ddde725dSArmin Le Grand // create fill content with SVG gradient primitive 592*ddde725dSArmin Le Grand add_fillGradient(rPath, aNewFill, *pFillGradient, rGeoRange); 593*ddde725dSArmin Le Grand } 594*ddde725dSArmin Le Grand else if(pFillPattern) 595*ddde725dSArmin Le Grand { 596*ddde725dSArmin Le Grand // create fill content with SVG pattern primitive 597*ddde725dSArmin Le Grand add_fillPatternTransform(rPath, aNewFill, *pFillPattern, rGeoRange); 598*ddde725dSArmin Le Grand } 599*ddde725dSArmin Le Grand else // if(pFill) 600*ddde725dSArmin Le Grand { 601*ddde725dSArmin Le Grand // create fill content 602*ddde725dSArmin Le Grand aNewFill.realloc(1); 603*ddde725dSArmin Le Grand aNewFill[0] = new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( 604*ddde725dSArmin Le Grand rPath, 605*ddde725dSArmin Le Grand *pFill); 606*ddde725dSArmin Le Grand } 607*ddde725dSArmin Le Grand 608*ddde725dSArmin Le Grand if(aNewFill.hasElements()) 609*ddde725dSArmin Le Grand { 610*ddde725dSArmin Le Grand if(basegfx::fTools::less(fFillOpacity, 1.0)) 611*ddde725dSArmin Le Grand { 612*ddde725dSArmin Le Grand // embed in UnifiedTransparencePrimitive2D 613*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( 614*ddde725dSArmin Le Grand rTarget, 615*ddde725dSArmin Le Grand new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( 616*ddde725dSArmin Le Grand aNewFill, 617*ddde725dSArmin Le Grand 1.0 - fFillOpacity)); 618*ddde725dSArmin Le Grand } 619*ddde725dSArmin Le Grand else 620*ddde725dSArmin Le Grand { 621*ddde725dSArmin Le Grand // append 622*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewFill); 623*ddde725dSArmin Le Grand } 624*ddde725dSArmin Le Grand } 625*ddde725dSArmin Le Grand } 626*ddde725dSArmin Le Grand } 627*ddde725dSArmin Le Grand } 628*ddde725dSArmin Le Grand 629*ddde725dSArmin Le Grand void SvgStyleAttributes::add_stroke( 630*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPath, 631*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 632*ddde725dSArmin Le Grand const basegfx::B2DRange& rGeoRange) const 633*ddde725dSArmin Le Grand { 634*ddde725dSArmin Le Grand const basegfx::BColor* pStroke = getStroke(); 635*ddde725dSArmin Le Grand const SvgGradientNode* pStrokeGradient = getSvgGradientNodeStroke(); 636*ddde725dSArmin Le Grand const SvgPatternNode* pStrokePattern = getSvgPatternNodeStroke(); 637*ddde725dSArmin Le Grand 638*ddde725dSArmin Le Grand if(pStroke || pStrokeGradient || pStrokePattern) 639*ddde725dSArmin Le Grand { 640*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence aNewStroke; 641*ddde725dSArmin Le Grand const double fStrokeOpacity(getStrokeOpacity().solve(mrOwner, length)); 642*ddde725dSArmin Le Grand 643*ddde725dSArmin Le Grand if(basegfx::fTools::more(fStrokeOpacity, 0.0)) 644*ddde725dSArmin Le Grand { 645*ddde725dSArmin Le Grand // get stroke width; SVG does not use 0.0 == hairline, so 0.0 is no line at all 646*ddde725dSArmin Le Grand const double fStrokeWidth(getStrokeWidth().isSet() ? getStrokeWidth().solve(mrOwner, length) : 1.0); 647*ddde725dSArmin Le Grand 648*ddde725dSArmin Le Grand if(basegfx::fTools::more(fStrokeWidth, 0.0)) 649*ddde725dSArmin Le Grand { 650*ddde725dSArmin Le Grand // get LineJoin and stroke array 651*ddde725dSArmin Le Grand const basegfx::B2DLineJoin aB2DLineJoin(StrokeLinejoinToB2DLineJoin(getStrokeLinejoin())); 652*ddde725dSArmin Le Grand ::std::vector< double > aDashArray; 653*ddde725dSArmin Le Grand 654*ddde725dSArmin Le Grand if(!getStrokeDasharray().empty()) 655*ddde725dSArmin Le Grand { 656*ddde725dSArmin Le Grand aDashArray = solveSvgNumberVector(getStrokeDasharray(), mrOwner, length); 657*ddde725dSArmin Le Grand } 658*ddde725dSArmin Le Grand 659*ddde725dSArmin Le Grand // todo: Handle getStrokeDashOffset() 660*ddde725dSArmin Le Grand // todo: Handle getStrokeLinecap() 661*ddde725dSArmin Le Grand 662*ddde725dSArmin Le Grand // prepare line attribute 663*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DReference aNewLinePrimitive; 664*ddde725dSArmin Le Grand const drawinglayer::attribute::LineAttribute aLineAttribute( 665*ddde725dSArmin Le Grand pStroke ? *pStroke : basegfx::BColor(0.0, 0.0, 0.0), 666*ddde725dSArmin Le Grand fStrokeWidth, 667*ddde725dSArmin Le Grand aB2DLineJoin); 668*ddde725dSArmin Le Grand 669*ddde725dSArmin Le Grand if(aDashArray.empty()) 670*ddde725dSArmin Le Grand { 671*ddde725dSArmin Le Grand aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( 672*ddde725dSArmin Le Grand rPath, 673*ddde725dSArmin Le Grand aLineAttribute); 674*ddde725dSArmin Le Grand } 675*ddde725dSArmin Le Grand else 676*ddde725dSArmin Le Grand { 677*ddde725dSArmin Le Grand const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashArray); 678*ddde725dSArmin Le Grand 679*ddde725dSArmin Le Grand aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D( 680*ddde725dSArmin Le Grand rPath, 681*ddde725dSArmin Le Grand aLineAttribute, 682*ddde725dSArmin Le Grand aDashArray); 683*ddde725dSArmin Le Grand } 684*ddde725dSArmin Le Grand 685*ddde725dSArmin Le Grand if(pStrokeGradient || pStrokePattern) 686*ddde725dSArmin Le Grand { 687*ddde725dSArmin Le Grand // put primitive into Primitive2DReference and Primitive2DSequence 688*ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DSequence aSeq(&aNewLinePrimitive, 1); 689*ddde725dSArmin Le Grand 690*ddde725dSArmin Le Grand // use neutral ViewInformation and create LineGeometryExtractor2D 691*ddde725dSArmin Le Grand const drawinglayer::geometry::ViewInformation2D aViewInformation2D; 692*ddde725dSArmin Le Grand drawinglayer::processor2d::LineGeometryExtractor2D aExtractor(aViewInformation2D); 693*ddde725dSArmin Le Grand 694*ddde725dSArmin Le Grand // proccess 695*ddde725dSArmin Le Grand aExtractor.process(aSeq); 696*ddde725dSArmin Le Grand 697*ddde725dSArmin Le Grand // check for fill rsults 698*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygonVector& rLineFillVector(aExtractor.getExtractedLineFills()); 699*ddde725dSArmin Le Grand 700*ddde725dSArmin Le Grand if(!aExtractor.getExtractedLineFills().empty()) 701*ddde725dSArmin Le Grand { 702*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon aMergedArea( 703*ddde725dSArmin Le Grand basegfx::tools::mergeToSinglePolyPolygon( 704*ddde725dSArmin Le Grand aExtractor.getExtractedLineFills())); 705*ddde725dSArmin Le Grand 706*ddde725dSArmin Le Grand if(aMergedArea.count()) 707*ddde725dSArmin Le Grand { 708*ddde725dSArmin Le Grand if(pStrokeGradient) 709*ddde725dSArmin Le Grand { 710*ddde725dSArmin Le Grand // create fill content with SVG gradient primitive. Use original GeoRange, 711*ddde725dSArmin Le Grand // e.g. from circle without LineWidth 712*ddde725dSArmin Le Grand add_fillGradient(aMergedArea, aNewStroke, *pStrokeGradient, rGeoRange); 713*ddde725dSArmin Le Grand } 714*ddde725dSArmin Le Grand else // if(pStrokePattern) 715*ddde725dSArmin Le Grand { 716*ddde725dSArmin Le Grand // create fill content with SVG pattern primitive. Use GeoRange 717*ddde725dSArmin Le Grand // from the expanded data, e.g. circle with extended geo by half linewidth 718*ddde725dSArmin Le Grand add_fillPatternTransform(aMergedArea, aNewStroke, *pStrokePattern, aMergedArea.getB2DRange()); 719*ddde725dSArmin Le Grand } 720*ddde725dSArmin Le Grand } 721*ddde725dSArmin Le Grand } 722*ddde725dSArmin Le Grand } 723*ddde725dSArmin Le Grand else // if(pStroke) 724*ddde725dSArmin Le Grand { 725*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aNewStroke, aNewLinePrimitive); 726*ddde725dSArmin Le Grand } 727*ddde725dSArmin Le Grand 728*ddde725dSArmin Le Grand if(aNewStroke.hasElements()) 729*ddde725dSArmin Le Grand { 730*ddde725dSArmin Le Grand if(basegfx::fTools::less(fStrokeOpacity, 1.0)) 731*ddde725dSArmin Le Grand { 732*ddde725dSArmin Le Grand // embed in UnifiedTransparencePrimitive2D 733*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( 734*ddde725dSArmin Le Grand rTarget, 735*ddde725dSArmin Le Grand new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( 736*ddde725dSArmin Le Grand aNewStroke, 737*ddde725dSArmin Le Grand 1.0 - fStrokeOpacity)); 738*ddde725dSArmin Le Grand } 739*ddde725dSArmin Le Grand else 740*ddde725dSArmin Le Grand { 741*ddde725dSArmin Le Grand // append 742*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewStroke); 743*ddde725dSArmin Le Grand } 744*ddde725dSArmin Le Grand } 745*ddde725dSArmin Le Grand } 746*ddde725dSArmin Le Grand } 747*ddde725dSArmin Le Grand } 748*ddde725dSArmin Le Grand } 749*ddde725dSArmin Le Grand 750*ddde725dSArmin Le Grand double get_markerRotation( 751*ddde725dSArmin Le Grand const SvgMarkerNode& rMarker, 752*ddde725dSArmin Le Grand const basegfx::B2DPolygon& rPolygon, 753*ddde725dSArmin Le Grand const sal_uInt32 nIndex) 754*ddde725dSArmin Le Grand { 755*ddde725dSArmin Le Grand double fAngle(0.0); 756*ddde725dSArmin Le Grand const sal_uInt32 nPointCount(rPolygon.count()); 757*ddde725dSArmin Le Grand 758*ddde725dSArmin Le Grand if(nPointCount) 759*ddde725dSArmin Le Grand { 760*ddde725dSArmin Le Grand if(rMarker.getOrientAuto()) 761*ddde725dSArmin Le Grand { 762*ddde725dSArmin Le Grand const bool bPrev(rPolygon.isClosed() || nIndex > 0); 763*ddde725dSArmin Le Grand basegfx::B2DCubicBezier aSegment; 764*ddde725dSArmin Le Grand basegfx::B2DVector aPrev; 765*ddde725dSArmin Le Grand basegfx::B2DVector aNext; 766*ddde725dSArmin Le Grand 767*ddde725dSArmin Le Grand if(bPrev) 768*ddde725dSArmin Le Grand { 769*ddde725dSArmin Le Grand rPolygon.getBezierSegment((nIndex - 1) % nPointCount, aSegment); 770*ddde725dSArmin Le Grand aPrev = aSegment.getTangent(1.0); 771*ddde725dSArmin Le Grand } 772*ddde725dSArmin Le Grand 773*ddde725dSArmin Le Grand const bool bNext(rPolygon.isClosed() || nIndex + 1 < nPointCount); 774*ddde725dSArmin Le Grand 775*ddde725dSArmin Le Grand if(bNext) 776*ddde725dSArmin Le Grand { 777*ddde725dSArmin Le Grand rPolygon.getBezierSegment(nIndex % nPointCount, aSegment); 778*ddde725dSArmin Le Grand aNext = aSegment.getTangent(0.0); 779*ddde725dSArmin Le Grand } 780*ddde725dSArmin Le Grand 781*ddde725dSArmin Le Grand if(bPrev && bNext) 782*ddde725dSArmin Le Grand { 783*ddde725dSArmin Le Grand fAngle = atan2(aPrev.getY() + aNext.getY(), aPrev.getX() + aNext.getX()); 784*ddde725dSArmin Le Grand } 785*ddde725dSArmin Le Grand else if(bPrev) 786*ddde725dSArmin Le Grand { 787*ddde725dSArmin Le Grand fAngle = atan2(aPrev.getY(), aPrev.getX()); 788*ddde725dSArmin Le Grand } 789*ddde725dSArmin Le Grand else if(bNext) 790*ddde725dSArmin Le Grand { 791*ddde725dSArmin Le Grand fAngle = atan2(aNext.getY(), aNext.getX()); 792*ddde725dSArmin Le Grand } 793*ddde725dSArmin Le Grand } 794*ddde725dSArmin Le Grand else 795*ddde725dSArmin Le Grand { 796*ddde725dSArmin Le Grand fAngle = rMarker.getAngle(); 797*ddde725dSArmin Le Grand } 798*ddde725dSArmin Le Grand } 799*ddde725dSArmin Le Grand 800*ddde725dSArmin Le Grand return fAngle; 801*ddde725dSArmin Le Grand } 802*ddde725dSArmin Le Grand 803*ddde725dSArmin Le Grand bool SvgStyleAttributes::prepare_singleMarker( 804*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives, 805*ddde725dSArmin Le Grand basegfx::B2DHomMatrix& rMarkerTransform, 806*ddde725dSArmin Le Grand basegfx::B2DRange& rClipRange, 807*ddde725dSArmin Le Grand const SvgMarkerNode& rMarker) const 808*ddde725dSArmin Le Grand { 809*ddde725dSArmin Le Grand // reset return values 810*ddde725dSArmin Le Grand rMarkerTransform.identity(); 811*ddde725dSArmin Le Grand rClipRange.reset(); 812*ddde725dSArmin Le Grand 813*ddde725dSArmin Le Grand // get marker primitive representation 814*ddde725dSArmin Le Grand rMarkerPrimitives = rMarker.getMarkerPrimitives(); 815*ddde725dSArmin Le Grand 816*ddde725dSArmin Le Grand if(rMarkerPrimitives.hasElements()) 817*ddde725dSArmin Le Grand { 818*ddde725dSArmin Le Grand basegfx::B2DRange aPrimitiveRange; 819*ddde725dSArmin Le Grand 820*ddde725dSArmin Le Grand if(rMarker.getViewBox()) 821*ddde725dSArmin Le Grand { 822*ddde725dSArmin Le Grand aPrimitiveRange = *rMarker.getViewBox(); 823*ddde725dSArmin Le Grand } 824*ddde725dSArmin Le Grand else 825*ddde725dSArmin Le Grand { 826*ddde725dSArmin Le Grand aPrimitiveRange = drawinglayer::primitive2d::getB2DRangeFromPrimitive2DSequence( 827*ddde725dSArmin Le Grand rMarkerPrimitives, 828*ddde725dSArmin Le Grand drawinglayer::geometry::ViewInformation2D()); 829*ddde725dSArmin Le Grand } 830*ddde725dSArmin Le Grand 831*ddde725dSArmin Le Grand if(aPrimitiveRange.getWidth() > 0.0 && aPrimitiveRange.getHeight() > 0.0) 832*ddde725dSArmin Le Grand { 833*ddde725dSArmin Le Grand double fTargetWidth(rMarker.getMarkerWidth().isSet() ? rMarker.getMarkerWidth().solve(mrOwner, xcoordinate) : 0.0); 834*ddde725dSArmin Le Grand double fTargetHeight(rMarker.getMarkerHeight().isSet() ? rMarker.getMarkerHeight().solve(mrOwner, xcoordinate) : 0.0); 835*ddde725dSArmin Le Grand 836*ddde725dSArmin Le Grand if(SvgMarkerNode::strokeWidth == rMarker.getMarkerUnits()) 837*ddde725dSArmin Le Grand { 838*ddde725dSArmin Le Grand // relative to strokeWidth 839*ddde725dSArmin Le Grand const double fStrokeWidth(getStrokeWidth().isSet() ? getStrokeWidth().solve(mrOwner, length) : 1.0); 840*ddde725dSArmin Le Grand 841*ddde725dSArmin Le Grand fTargetWidth *= fStrokeWidth; 842*ddde725dSArmin Le Grand fTargetHeight *= fStrokeWidth; 843*ddde725dSArmin Le Grand } 844*ddde725dSArmin Le Grand 845*ddde725dSArmin Le Grand if(fTargetWidth > 0.0 && fTargetHeight > 0.0) 846*ddde725dSArmin Le Grand { 847*ddde725dSArmin Le Grand const basegfx::B2DRange aTargetRange(0.0, 0.0, fTargetWidth, fTargetHeight); 848*ddde725dSArmin Le Grand 849*ddde725dSArmin Le Grand // subbstract refX, refY first, it's in marker local coordinates 850*ddde725dSArmin Le Grand rMarkerTransform.translate( 851*ddde725dSArmin Le Grand rMarker.getRefX().isSet() ? -rMarker.getRefX().solve(mrOwner, xcoordinate) : 0.0, 852*ddde725dSArmin Le Grand rMarker.getRefY().isSet() ? -rMarker.getRefY().solve(mrOwner, ycoordinate) : 0.0); 853*ddde725dSArmin Le Grand 854*ddde725dSArmin Le Grand // create mapping 855*ddde725dSArmin Le Grand const SvgAspectRatio& rRatio = rMarker.getSvgAspectRatio(); 856*ddde725dSArmin Le Grand 857*ddde725dSArmin Le Grand if(rRatio.isSet()) 858*ddde725dSArmin Le Grand { 859*ddde725dSArmin Le Grand // let mapping be created from SvgAspectRatio 860*ddde725dSArmin Le Grand rMarkerTransform = rRatio.createMapping(aTargetRange, aPrimitiveRange) * rMarkerTransform; 861*ddde725dSArmin Le Grand 862*ddde725dSArmin Le Grand if(rRatio.isMeetOrSlice()) 863*ddde725dSArmin Le Grand { 864*ddde725dSArmin Le Grand // need to clip 865*ddde725dSArmin Le Grand rClipRange = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0); 866*ddde725dSArmin Le Grand } 867*ddde725dSArmin Le Grand } 868*ddde725dSArmin Le Grand else 869*ddde725dSArmin Le Grand { 870*ddde725dSArmin Le Grand // choose default mapping 871*ddde725dSArmin Le Grand rMarkerTransform = rRatio.createLinearMapping(aTargetRange, aPrimitiveRange) * rMarkerTransform; 872*ddde725dSArmin Le Grand } 873*ddde725dSArmin Le Grand 874*ddde725dSArmin Le Grand return true; 875*ddde725dSArmin Le Grand } 876*ddde725dSArmin Le Grand } 877*ddde725dSArmin Le Grand } 878*ddde725dSArmin Le Grand 879*ddde725dSArmin Le Grand return false; 880*ddde725dSArmin Le Grand } 881*ddde725dSArmin Le Grand 882*ddde725dSArmin Le Grand void SvgStyleAttributes::add_singleMarker( 883*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 884*ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives, 885*ddde725dSArmin Le Grand const basegfx::B2DHomMatrix& rMarkerTransform, 886*ddde725dSArmin Le Grand const basegfx::B2DRange& rClipRange, 887*ddde725dSArmin Le Grand const SvgMarkerNode& rMarker, 888*ddde725dSArmin Le Grand const basegfx::B2DPolygon& rCandidate, 889*ddde725dSArmin Le Grand const sal_uInt32 nIndex) const 890*ddde725dSArmin Le Grand { 891*ddde725dSArmin Le Grand const sal_uInt32 nPointCount(rCandidate.count()); 892*ddde725dSArmin Le Grand 893*ddde725dSArmin Le Grand if(nPointCount) 894*ddde725dSArmin Le Grand { 895*ddde725dSArmin Le Grand // get and apply rotation 896*ddde725dSArmin Le Grand basegfx::B2DHomMatrix aCombinedTransform(rMarkerTransform); 897*ddde725dSArmin Le Grand aCombinedTransform.rotate(get_markerRotation(rMarker, rCandidate, nIndex)); 898*ddde725dSArmin Le Grand 899*ddde725dSArmin Le Grand // get and apply target position 900*ddde725dSArmin Le Grand const basegfx::B2DPoint aPoint(rCandidate.getB2DPoint(nIndex % nPointCount)); 901*ddde725dSArmin Le Grand aCombinedTransform.translate(aPoint.getX(), aPoint.getY()); 902*ddde725dSArmin Le Grand 903*ddde725dSArmin Le Grand // add marker 904*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence( 905*ddde725dSArmin Le Grand rTarget, 906*ddde725dSArmin Le Grand new drawinglayer::primitive2d::TransformPrimitive2D( 907*ddde725dSArmin Le Grand aCombinedTransform, 908*ddde725dSArmin Le Grand rMarkerPrimitives)); 909*ddde725dSArmin Le Grand } 910*ddde725dSArmin Le Grand } 911*ddde725dSArmin Le Grand 912*ddde725dSArmin Le Grand void SvgStyleAttributes::add_markers( 913*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPath, 914*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget) const 915*ddde725dSArmin Le Grand { 916*ddde725dSArmin Le Grand // try to access linked markers 917*ddde725dSArmin Le Grand const SvgMarkerNode* pStart = accessMarkerStartXLink(); 918*ddde725dSArmin Le Grand const SvgMarkerNode* pMid = accessMarkerMidXLink(); 919*ddde725dSArmin Le Grand const SvgMarkerNode* pEnd = accessMarkerEndXLink(); 920*ddde725dSArmin Le Grand 921*ddde725dSArmin Le Grand if(pStart || pMid || pEnd) 922*ddde725dSArmin Le Grand { 923*ddde725dSArmin Le Grand const sal_uInt32 nCount(rPath.count()); 924*ddde725dSArmin Le Grand 925*ddde725dSArmin Le Grand for (sal_uInt32 a(0); a < nCount; a++) 926*ddde725dSArmin Le Grand { 927*ddde725dSArmin Le Grand const basegfx::B2DPolygon aCandidate(rPath.getB2DPolygon(a)); 928*ddde725dSArmin Le Grand const sal_uInt32 nPointCount(aCandidate.count()); 929*ddde725dSArmin Le Grand 930*ddde725dSArmin Le Grand if(nPointCount) 931*ddde725dSArmin Le Grand { 932*ddde725dSArmin Le Grand const sal_uInt32 nMarkerCount(aCandidate.isClosed() ? nPointCount + 1 : nPointCount); 933*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence aMarkerPrimitives; 934*ddde725dSArmin Le Grand basegfx::B2DHomMatrix aMarkerTransform; 935*ddde725dSArmin Le Grand basegfx::B2DRange aClipRange; 936*ddde725dSArmin Le Grand const SvgMarkerNode* pPrepared = 0; 937*ddde725dSArmin Le Grand 938*ddde725dSArmin Le Grand if(pStart) 939*ddde725dSArmin Le Grand { 940*ddde725dSArmin Le Grand if(prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pStart)) 941*ddde725dSArmin Le Grand { 942*ddde725dSArmin Le Grand pPrepared = pStart; 943*ddde725dSArmin Le Grand add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, 0); 944*ddde725dSArmin Le Grand } 945*ddde725dSArmin Le Grand } 946*ddde725dSArmin Le Grand 947*ddde725dSArmin Le Grand if(pMid && nMarkerCount > 2) 948*ddde725dSArmin Le Grand { 949*ddde725dSArmin Le Grand if(pMid == pPrepared || prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pMid)) 950*ddde725dSArmin Le Grand { 951*ddde725dSArmin Le Grand pPrepared = pMid; 952*ddde725dSArmin Le Grand 953*ddde725dSArmin Le Grand for(sal_uInt32 a(1); a < nMarkerCount - 1; a++) 954*ddde725dSArmin Le Grand { 955*ddde725dSArmin Le Grand add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, a); 956*ddde725dSArmin Le Grand } 957*ddde725dSArmin Le Grand } 958*ddde725dSArmin Le Grand } 959*ddde725dSArmin Le Grand 960*ddde725dSArmin Le Grand if(pEnd) 961*ddde725dSArmin Le Grand { 962*ddde725dSArmin Le Grand if(pEnd == pPrepared || prepare_singleMarker(aMarkerPrimitives, aMarkerTransform, aClipRange, *pEnd)) 963*ddde725dSArmin Le Grand { 964*ddde725dSArmin Le Grand pPrepared = pEnd; 965*ddde725dSArmin Le Grand add_singleMarker(rTarget, aMarkerPrimitives, aMarkerTransform, aClipRange, *pPrepared, aCandidate, nMarkerCount - 1); 966*ddde725dSArmin Le Grand } 967*ddde725dSArmin Le Grand } 968*ddde725dSArmin Le Grand } 969*ddde725dSArmin Le Grand } 970*ddde725dSArmin Le Grand } 971*ddde725dSArmin Le Grand } 972*ddde725dSArmin Le Grand 973*ddde725dSArmin Le Grand void SvgStyleAttributes::add_path( 974*ddde725dSArmin Le Grand const basegfx::B2DPolyPolygon& rPath, 975*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget) const 976*ddde725dSArmin Le Grand { 977*ddde725dSArmin Le Grand const bool bIsLine(1 == rPath.count() 978*ddde725dSArmin Le Grand && !rPath.areControlPointsUsed() 979*ddde725dSArmin Le Grand && 2 == rPath.getB2DPolygon(0).count()); 980*ddde725dSArmin Le Grand 981*ddde725dSArmin Le Grand if(!rPath.count()) 982*ddde725dSArmin Le Grand { 983*ddde725dSArmin Le Grand return; 984*ddde725dSArmin Le Grand } 985*ddde725dSArmin Le Grand 986*ddde725dSArmin Le Grand const basegfx::B2DRange aGeoRange(rPath.getB2DRange()); 987*ddde725dSArmin Le Grand 988*ddde725dSArmin Le Grand if(aGeoRange.isEmpty()) 989*ddde725dSArmin Le Grand { 990*ddde725dSArmin Le Grand return; 991*ddde725dSArmin Le Grand } 992*ddde725dSArmin Le Grand 993*ddde725dSArmin Le Grand if(!bIsLine && // not for lines 994*ddde725dSArmin Le Grand (basegfx::fTools::equalZero(aGeoRange.getWidth()) 995*ddde725dSArmin Le Grand || basegfx::fTools::equalZero(aGeoRange.getHeight()))) 996*ddde725dSArmin Le Grand { 997*ddde725dSArmin Le Grand return; 998*ddde725dSArmin Le Grand } 999*ddde725dSArmin Le Grand 1000*ddde725dSArmin Le Grand const double fOpacity(getOpacity().getNumber()); 1001*ddde725dSArmin Le Grand 1002*ddde725dSArmin Le Grand if(basegfx::fTools::equalZero(fOpacity)) 1003*ddde725dSArmin Le Grand { 1004*ddde725dSArmin Le Grand return; 1005*ddde725dSArmin Le Grand } 1006*ddde725dSArmin Le Grand 1007*ddde725dSArmin Le Grand if(!bIsLine) 1008*ddde725dSArmin Le Grand { 1009*ddde725dSArmin Le Grand basegfx::B2DPolyPolygon aPath(rPath); 1010*ddde725dSArmin Le Grand const bool bNeedToCheckClipRule(SVGTokenPath == mrOwner.getType() || SVGTokenPolygon == mrOwner.getType()); 1011*ddde725dSArmin Le Grand const bool bClipPathIsNonzero(!bIsLine && bNeedToCheckClipRule && mbIsClipPathContent && mbClipRule); 1012*ddde725dSArmin Le Grand const bool bFillRuleIsNonzero(!bIsLine && bNeedToCheckClipRule && !mbIsClipPathContent && getFillRule()); 1013*ddde725dSArmin Le Grand 1014*ddde725dSArmin Le Grand if(bClipPathIsNonzero || bFillRuleIsNonzero) 1015*ddde725dSArmin Le Grand { 1016*ddde725dSArmin Le Grand // nonzero is wanted, solve geometrically (see description on basegfx) 1017*ddde725dSArmin Le Grand aPath = basegfx::tools::createNonzeroConform(aPath); 1018*ddde725dSArmin Le Grand } 1019*ddde725dSArmin Le Grand 1020*ddde725dSArmin Le Grand add_fill(aPath, rTarget, aGeoRange); 1021*ddde725dSArmin Le Grand } 1022*ddde725dSArmin Le Grand 1023*ddde725dSArmin Le Grand add_stroke(rPath, rTarget, aGeoRange); 1024*ddde725dSArmin Le Grand 1025*ddde725dSArmin Le Grand // Svg supports markers for path, polygon, polyline and line 1026*ddde725dSArmin Le Grand if(SVGTokenPath == mrOwner.getType() || // path 1027*ddde725dSArmin Le Grand SVGTokenPolygon == mrOwner.getType() || // polygon, polyline 1028*ddde725dSArmin Le Grand SVGTokenLine == mrOwner.getType()) // line 1029*ddde725dSArmin Le Grand { 1030*ddde725dSArmin Le Grand // try to add markers 1031*ddde725dSArmin Le Grand add_markers(rPath, rTarget); 1032*ddde725dSArmin Le Grand } 1033*ddde725dSArmin Le Grand } 1034*ddde725dSArmin Le Grand 1035*ddde725dSArmin Le Grand void SvgStyleAttributes::add_postProcess( 1036*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence& rTarget, 1037*ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DSequence& rSource, 1038*ddde725dSArmin Le Grand const basegfx::B2DHomMatrix* pTransform) const 1039*ddde725dSArmin Le Grand { 1040*ddde725dSArmin Le Grand if(rSource.hasElements()) 1041*ddde725dSArmin Le Grand { 1042*ddde725dSArmin Le Grand const double fOpacity(getOpacity().getNumber()); 1043*ddde725dSArmin Le Grand 1044*ddde725dSArmin Le Grand if(basegfx::fTools::equalZero(fOpacity)) 1045*ddde725dSArmin Le Grand { 1046*ddde725dSArmin Le Grand return; 1047*ddde725dSArmin Le Grand } 1048*ddde725dSArmin Le Grand 1049*ddde725dSArmin Le Grand drawinglayer::primitive2d::Primitive2DSequence aSource(rSource); 1050*ddde725dSArmin Le Grand 1051*ddde725dSArmin Le Grand if(basegfx::fTools::less(fOpacity, 1.0)) 1052*ddde725dSArmin Le Grand { 1053*ddde725dSArmin Le Grand // embed in UnifiedTransparencePrimitive2D 1054*ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xRef( 1055*ddde725dSArmin Le Grand new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D( 1056*ddde725dSArmin Le Grand aSource, 1057*ddde725dSArmin Le Grand 1.0 - fOpacity)); 1058*ddde725dSArmin Le Grand 1059*ddde725dSArmin Le Grand aSource = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); 1060*ddde725dSArmin Le Grand } 1061*ddde725dSArmin Le Grand 1062*ddde725dSArmin Le Grand if(getClipPathXLink().getLength()) 1063*ddde725dSArmin Le Grand { 1064*ddde725dSArmin Le Grand // try to access linked ClipPath 1065*ddde725dSArmin Le Grand const SvgClipPathNode* mpClip = dynamic_cast< const SvgClipPathNode* >(mrOwner.getDocument().findSvgNodeById(getClipPathXLink())); 1066*ddde725dSArmin Le Grand 1067*ddde725dSArmin Le Grand if(mpClip) 1068*ddde725dSArmin Le Grand { 1069*ddde725dSArmin Le Grand mpClip->apply(aSource); 1070*ddde725dSArmin Le Grand } 1071*ddde725dSArmin Le Grand } 1072*ddde725dSArmin Le Grand 1073*ddde725dSArmin Le Grand if(aSource.hasElements()) // test again, applied clipPath may have lead to empty geometry 1074*ddde725dSArmin Le Grand { 1075*ddde725dSArmin Le Grand if(getMaskXLink().getLength()) 1076*ddde725dSArmin Le Grand { 1077*ddde725dSArmin Le Grand // try to access linked Mask 1078*ddde725dSArmin Le Grand const SvgMaskNode* mpMask = dynamic_cast< const SvgMaskNode* >(mrOwner.getDocument().findSvgNodeById(getMaskXLink())); 1079*ddde725dSArmin Le Grand 1080*ddde725dSArmin Le Grand if(mpMask) 1081*ddde725dSArmin Le Grand { 1082*ddde725dSArmin Le Grand mpMask->apply(aSource); 1083*ddde725dSArmin Le Grand } 1084*ddde725dSArmin Le Grand } 1085*ddde725dSArmin Le Grand 1086*ddde725dSArmin Le Grand if(aSource.hasElements()) // test again, applied mask may have lead to empty geometry 1087*ddde725dSArmin Le Grand { 1088*ddde725dSArmin Le Grand if(pTransform) 1089*ddde725dSArmin Le Grand { 1090*ddde725dSArmin Le Grand // create embedding group element with transformation 1091*ddde725dSArmin Le Grand const drawinglayer::primitive2d::Primitive2DReference xRef( 1092*ddde725dSArmin Le Grand new drawinglayer::primitive2d::TransformPrimitive2D( 1093*ddde725dSArmin Le Grand *pTransform, 1094*ddde725dSArmin Le Grand aSource)); 1095*ddde725dSArmin Le Grand 1096*ddde725dSArmin Le Grand aSource = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1); 1097*ddde725dSArmin Le Grand } 1098*ddde725dSArmin Le Grand 1099*ddde725dSArmin Le Grand // append to current target 1100*ddde725dSArmin Le Grand drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSource); 1101*ddde725dSArmin Le Grand } 1102*ddde725dSArmin Le Grand } 1103*ddde725dSArmin Le Grand } 1104*ddde725dSArmin Le Grand } 1105*ddde725dSArmin Le Grand 1106*ddde725dSArmin Le Grand SvgStyleAttributes::SvgStyleAttributes(SvgNode& rOwner) 1107*ddde725dSArmin Le Grand : mrOwner(rOwner), 1108*ddde725dSArmin Le Grand mpCssStyleParent(0), 1109*ddde725dSArmin Le Grand maFill(), 1110*ddde725dSArmin Le Grand maStroke(), 1111*ddde725dSArmin Le Grand maStopColor(basegfx::BColor(0.0, 0.0, 0.0), true), 1112*ddde725dSArmin Le Grand maStrokeWidth(), 1113*ddde725dSArmin Le Grand maStopOpacity(), 1114*ddde725dSArmin Le Grand mpSvgGradientNodeFill(0), 1115*ddde725dSArmin Le Grand mpSvgGradientNodeStroke(0), 1116*ddde725dSArmin Le Grand mpSvgPatternNodeFill(0), 1117*ddde725dSArmin Le Grand mpSvgPatternNodeStroke(0), 1118*ddde725dSArmin Le Grand maFillOpacity(), 1119*ddde725dSArmin Le Grand maStrokeDasharray(), 1120*ddde725dSArmin Le Grand maStrokeDashOffset(), 1121*ddde725dSArmin Le Grand maStrokeLinecap(StrokeLinecap_notset), 1122*ddde725dSArmin Le Grand maStrokeLinejoin(StrokeLinejoin_notset), 1123*ddde725dSArmin Le Grand maStrokeMiterLimit(), 1124*ddde725dSArmin Le Grand maStrokeOpacity(), 1125*ddde725dSArmin Le Grand maFontFamily(), 1126*ddde725dSArmin Le Grand maFontSize(), 1127*ddde725dSArmin Le Grand maFontStretch(FontStretch_notset), 1128*ddde725dSArmin Le Grand maFontStyle(FontStyle_notset), 1129*ddde725dSArmin Le Grand maFontVariant(FontVariant_notset), 1130*ddde725dSArmin Le Grand maFontWeight(FontWeight_notset), 1131*ddde725dSArmin Le Grand maTextAlign(TextAlign_notset), 1132*ddde725dSArmin Le Grand maTextDecoration(TextDecoration_notset), 1133*ddde725dSArmin Le Grand maTextAnchor(TextAnchor_notset), 1134*ddde725dSArmin Le Grand maColor(), 1135*ddde725dSArmin Le Grand maOpacity(1.0), 1136*ddde725dSArmin Le Grand maClipPathXLink(), 1137*ddde725dSArmin Le Grand maMaskXLink(), 1138*ddde725dSArmin Le Grand maMarkerStartXLink(), 1139*ddde725dSArmin Le Grand mpMarkerStartXLink(0), 1140*ddde725dSArmin Le Grand maMarkerMidXLink(), 1141*ddde725dSArmin Le Grand mpMarkerMidXLink(0), 1142*ddde725dSArmin Le Grand maMarkerEndXLink(), 1143*ddde725dSArmin Le Grand mpMarkerEndXLink(0), 1144*ddde725dSArmin Le Grand maFillRule(true), 1145*ddde725dSArmin Le Grand maFillRuleSet(false), 1146*ddde725dSArmin Le Grand mbIsClipPathContent(SVGTokenClipPathNode == mrOwner.getType()), 1147*ddde725dSArmin Le Grand mbClipRule(true) 1148*ddde725dSArmin Le Grand { 1149*ddde725dSArmin Le Grand if(!mbIsClipPathContent) 1150*ddde725dSArmin Le Grand { 1151*ddde725dSArmin Le Grand const SvgStyleAttributes* pParentStyle = getParentStyle(); 1152*ddde725dSArmin Le Grand 1153*ddde725dSArmin Le Grand if(pParentStyle) 1154*ddde725dSArmin Le Grand { 1155*ddde725dSArmin Le Grand mbIsClipPathContent = pParentStyle->mbIsClipPathContent; 1156*ddde725dSArmin Le Grand } 1157*ddde725dSArmin Le Grand } 1158*ddde725dSArmin Le Grand } 1159*ddde725dSArmin Le Grand 1160*ddde725dSArmin Le Grand SvgStyleAttributes::~SvgStyleAttributes() 1161*ddde725dSArmin Le Grand { 1162*ddde725dSArmin Le Grand } 1163*ddde725dSArmin Le Grand 1164*ddde725dSArmin Le Grand void SvgStyleAttributes::parseStyleAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent) 1165*ddde725dSArmin Le Grand { 1166*ddde725dSArmin Le Grand switch(aSVGToken) 1167*ddde725dSArmin Le Grand { 1168*ddde725dSArmin Le Grand case SVGTokenFill: 1169*ddde725dSArmin Le Grand { 1170*ddde725dSArmin Le Grand SvgPaint aSvgPaint; 1171*ddde725dSArmin Le Grand rtl::OUString aURL; 1172*ddde725dSArmin Le Grand bool bUseCurrent(false); 1173*ddde725dSArmin Le Grand 1174*ddde725dSArmin Le Grand if(readSvgPaint(aContent, aSvgPaint, aURL)) 1175*ddde725dSArmin Le Grand { 1176*ddde725dSArmin Le Grand setFill(aSvgPaint); 1177*ddde725dSArmin Le Grand } 1178*ddde725dSArmin Le Grand else if(aURL.getLength()) 1179*ddde725dSArmin Le Grand { 1180*ddde725dSArmin Le Grand const SvgNode* pNode = mrOwner.getDocument().findSvgNodeById(aURL); 1181*ddde725dSArmin Le Grand 1182*ddde725dSArmin Le Grand if(pNode) 1183*ddde725dSArmin Le Grand { 1184*ddde725dSArmin Le Grand if(SVGTokenLinearGradient == pNode->getType() || SVGTokenRadialGradient == pNode->getType()) 1185*ddde725dSArmin Le Grand { 1186*ddde725dSArmin Le Grand setSvgGradientNodeFill(static_cast< const SvgGradientNode* >(pNode)); 1187*ddde725dSArmin Le Grand } 1188*ddde725dSArmin Le Grand else if(SVGTokenPattern == pNode->getType()) 1189*ddde725dSArmin Le Grand { 1190*ddde725dSArmin Le Grand setSvgPatternNodeFill(static_cast< const SvgPatternNode* >(pNode)); 1191*ddde725dSArmin Le Grand } 1192*ddde725dSArmin Le Grand } 1193*ddde725dSArmin Le Grand } 1194*ddde725dSArmin Le Grand break; 1195*ddde725dSArmin Le Grand } 1196*ddde725dSArmin Le Grand case SVGTokenFillOpacity: 1197*ddde725dSArmin Le Grand { 1198*ddde725dSArmin Le Grand SvgNumber aNum; 1199*ddde725dSArmin Le Grand 1200*ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 1201*ddde725dSArmin Le Grand { 1202*ddde725dSArmin Le Grand if(aNum.isPositive()) 1203*ddde725dSArmin Le Grand { 1204*ddde725dSArmin Le Grand setFillOpacity(aNum); 1205*ddde725dSArmin Le Grand } 1206*ddde725dSArmin Le Grand } 1207*ddde725dSArmin Le Grand break; 1208*ddde725dSArmin Le Grand } 1209*ddde725dSArmin Le Grand case SVGTokenFillRule: 1210*ddde725dSArmin Le Grand { 1211*ddde725dSArmin Le Grand if(aContent.getLength()) 1212*ddde725dSArmin Le Grand { 1213*ddde725dSArmin Le Grand if(aContent.match(commonStrings::aStrNonzero)) 1214*ddde725dSArmin Le Grand { 1215*ddde725dSArmin Le Grand maFillRule = true; 1216*ddde725dSArmin Le Grand maFillRuleSet = true; 1217*ddde725dSArmin Le Grand } 1218*ddde725dSArmin Le Grand else if(aContent.match(commonStrings::aStrEvenOdd)) 1219*ddde725dSArmin Le Grand { 1220*ddde725dSArmin Le Grand maFillRule = false; 1221*ddde725dSArmin Le Grand maFillRuleSet = true; 1222*ddde725dSArmin Le Grand } 1223*ddde725dSArmin Le Grand } 1224*ddde725dSArmin Le Grand break; 1225*ddde725dSArmin Le Grand } 1226*ddde725dSArmin Le Grand case SVGTokenStroke: 1227*ddde725dSArmin Le Grand { 1228*ddde725dSArmin Le Grand SvgPaint aSvgPaint; 1229*ddde725dSArmin Le Grand rtl::OUString aURL; 1230*ddde725dSArmin Le Grand 1231*ddde725dSArmin Le Grand if(readSvgPaint(aContent, aSvgPaint, aURL)) 1232*ddde725dSArmin Le Grand { 1233*ddde725dSArmin Le Grand setStroke(aSvgPaint); 1234*ddde725dSArmin Le Grand } 1235*ddde725dSArmin Le Grand else if(aURL.getLength()) 1236*ddde725dSArmin Le Grand { 1237*ddde725dSArmin Le Grand const SvgNode* pNode = mrOwner.getDocument().findSvgNodeById(aURL); 1238*ddde725dSArmin Le Grand 1239*ddde725dSArmin Le Grand if(pNode) 1240*ddde725dSArmin Le Grand { 1241*ddde725dSArmin Le Grand if(SVGTokenLinearGradient == pNode->getType() || SVGTokenRadialGradient == pNode->getType()) 1242*ddde725dSArmin Le Grand { 1243*ddde725dSArmin Le Grand setSvgGradientNodeStroke(static_cast< const SvgGradientNode* >(pNode)); 1244*ddde725dSArmin Le Grand } 1245*ddde725dSArmin Le Grand else if(SVGTokenPattern == pNode->getType()) 1246*ddde725dSArmin Le Grand { 1247*ddde725dSArmin Le Grand setSvgPatternNodeStroke(static_cast< const SvgPatternNode* >(pNode)); 1248*ddde725dSArmin Le Grand } 1249*ddde725dSArmin Le Grand } 1250*ddde725dSArmin Le Grand } 1251*ddde725dSArmin Le Grand break; 1252*ddde725dSArmin Le Grand } 1253*ddde725dSArmin Le Grand case SVGTokenStrokeDasharray: 1254*ddde725dSArmin Le Grand { 1255*ddde725dSArmin Le Grand if(aContent.getLength()) 1256*ddde725dSArmin Le Grand { 1257*ddde725dSArmin Le Grand SvgNumberVector aVector; 1258*ddde725dSArmin Le Grand 1259*ddde725dSArmin Le Grand if(readSvgNumberVector(aContent, aVector)) 1260*ddde725dSArmin Le Grand { 1261*ddde725dSArmin Le Grand setStrokeDasharray(aVector); 1262*ddde725dSArmin Le Grand } 1263*ddde725dSArmin Le Grand } 1264*ddde725dSArmin Le Grand break; 1265*ddde725dSArmin Le Grand } 1266*ddde725dSArmin Le Grand case SVGTokenStrokeDashoffset: 1267*ddde725dSArmin Le Grand { 1268*ddde725dSArmin Le Grand SvgNumber aNum; 1269*ddde725dSArmin Le Grand 1270*ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 1271*ddde725dSArmin Le Grand { 1272*ddde725dSArmin Le Grand if(aNum.isPositive()) 1273*ddde725dSArmin Le Grand { 1274*ddde725dSArmin Le Grand setStrokeDashOffset(aNum); 1275*ddde725dSArmin Le Grand } 1276*ddde725dSArmin Le Grand } 1277*ddde725dSArmin Le Grand break; 1278*ddde725dSArmin Le Grand } 1279*ddde725dSArmin Le Grand case SVGTokenStrokeLinecap: 1280*ddde725dSArmin Le Grand { 1281*ddde725dSArmin Le Grand if(aContent.getLength()) 1282*ddde725dSArmin Le Grand { 1283*ddde725dSArmin Le Grand static rtl::OUString aStrButt(rtl::OUString::createFromAscii("butt")); 1284*ddde725dSArmin Le Grand static rtl::OUString aStrRound(rtl::OUString::createFromAscii("round")); 1285*ddde725dSArmin Le Grand static rtl::OUString aStrSquare(rtl::OUString::createFromAscii("square")); 1286*ddde725dSArmin Le Grand 1287*ddde725dSArmin Le Grand if(aContent.match(aStrButt)) 1288*ddde725dSArmin Le Grand { 1289*ddde725dSArmin Le Grand setStrokeLinecap(StrokeLinecap_butt); 1290*ddde725dSArmin Le Grand } 1291*ddde725dSArmin Le Grand else if(aContent.match(aStrRound)) 1292*ddde725dSArmin Le Grand { 1293*ddde725dSArmin Le Grand setStrokeLinecap(StrokeLinecap_round); 1294*ddde725dSArmin Le Grand } 1295*ddde725dSArmin Le Grand else if(aContent.match(aStrSquare)) 1296*ddde725dSArmin Le Grand { 1297*ddde725dSArmin Le Grand setStrokeLinecap(StrokeLinecap_square); 1298*ddde725dSArmin Le Grand } 1299*ddde725dSArmin Le Grand } 1300*ddde725dSArmin Le Grand break; 1301*ddde725dSArmin Le Grand } 1302*ddde725dSArmin Le Grand case SVGTokenStrokeLinejoin: 1303*ddde725dSArmin Le Grand { 1304*ddde725dSArmin Le Grand if(aContent.getLength()) 1305*ddde725dSArmin Le Grand { 1306*ddde725dSArmin Le Grand static rtl::OUString aStrMiter(rtl::OUString::createFromAscii("miter")); 1307*ddde725dSArmin Le Grand static rtl::OUString aStrRound(rtl::OUString::createFromAscii("round")); 1308*ddde725dSArmin Le Grand static rtl::OUString aStrBevel(rtl::OUString::createFromAscii("bevel")); 1309*ddde725dSArmin Le Grand 1310*ddde725dSArmin Le Grand if(aContent.match(aStrMiter)) 1311*ddde725dSArmin Le Grand { 1312*ddde725dSArmin Le Grand setStrokeLinejoin(StrokeLinejoin_miter); 1313*ddde725dSArmin Le Grand } 1314*ddde725dSArmin Le Grand else if(aContent.match(aStrRound)) 1315*ddde725dSArmin Le Grand { 1316*ddde725dSArmin Le Grand setStrokeLinejoin(StrokeLinejoin_round); 1317*ddde725dSArmin Le Grand } 1318*ddde725dSArmin Le Grand else if(aContent.match(aStrBevel)) 1319*ddde725dSArmin Le Grand { 1320*ddde725dSArmin Le Grand setStrokeLinejoin(StrokeLinejoin_bevel); 1321*ddde725dSArmin Le Grand } 1322*ddde725dSArmin Le Grand } 1323*ddde725dSArmin Le Grand break; 1324*ddde725dSArmin Le Grand } 1325*ddde725dSArmin Le Grand case SVGTokenStrokeMiterlimit: 1326*ddde725dSArmin Le Grand { 1327*ddde725dSArmin Le Grand SvgNumber aNum; 1328*ddde725dSArmin Le Grand 1329*ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 1330*ddde725dSArmin Le Grand { 1331*ddde725dSArmin Le Grand if(aNum.isPositive()) 1332*ddde725dSArmin Le Grand { 1333*ddde725dSArmin Le Grand setStrokeMiterLimit(aNum); 1334*ddde725dSArmin Le Grand } 1335*ddde725dSArmin Le Grand } 1336*ddde725dSArmin Le Grand break; 1337*ddde725dSArmin Le Grand } 1338*ddde725dSArmin Le Grand case SVGTokenStrokeOpacity: 1339*ddde725dSArmin Le Grand { 1340*ddde725dSArmin Le Grand SvgNumber aNum; 1341*ddde725dSArmin Le Grand 1342*ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 1343*ddde725dSArmin Le Grand { 1344*ddde725dSArmin Le Grand if(aNum.isPositive()) 1345*ddde725dSArmin Le Grand { 1346*ddde725dSArmin Le Grand setStrokeOpacity(aNum); 1347*ddde725dSArmin Le Grand } 1348*ddde725dSArmin Le Grand } 1349*ddde725dSArmin Le Grand break; 1350*ddde725dSArmin Le Grand } 1351*ddde725dSArmin Le Grand case SVGTokenStrokeWidth: 1352*ddde725dSArmin Le Grand { 1353*ddde725dSArmin Le Grand SvgNumber aNum; 1354*ddde725dSArmin Le Grand 1355*ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 1356*ddde725dSArmin Le Grand { 1357*ddde725dSArmin Le Grand if(aNum.isPositive()) 1358*ddde725dSArmin Le Grand { 1359*ddde725dSArmin Le Grand setStrokeWidth(aNum); 1360*ddde725dSArmin Le Grand } 1361*ddde725dSArmin Le Grand } 1362*ddde725dSArmin Le Grand break; 1363*ddde725dSArmin Le Grand } 1364*ddde725dSArmin Le Grand case SVGTokenStopColor: 1365*ddde725dSArmin Le Grand { 1366*ddde725dSArmin Le Grand SvgPaint aSvgPaint; 1367*ddde725dSArmin Le Grand rtl::OUString aURL; 1368*ddde725dSArmin Le Grand 1369*ddde725dSArmin Le Grand if(readSvgPaint(aContent, aSvgPaint, aURL)) 1370*ddde725dSArmin Le Grand { 1371*ddde725dSArmin Le Grand setStopColor(aSvgPaint); 1372*ddde725dSArmin Le Grand } 1373*ddde725dSArmin Le Grand break; 1374*ddde725dSArmin Le Grand } 1375*ddde725dSArmin Le Grand case SVGTokenStopOpacity: 1376*ddde725dSArmin Le Grand { 1377*ddde725dSArmin Le Grand SvgNumber aNum; 1378*ddde725dSArmin Le Grand 1379*ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 1380*ddde725dSArmin Le Grand { 1381*ddde725dSArmin Le Grand if(aNum.isPositive()) 1382*ddde725dSArmin Le Grand { 1383*ddde725dSArmin Le Grand setStopOpacity(aNum); 1384*ddde725dSArmin Le Grand } 1385*ddde725dSArmin Le Grand } 1386*ddde725dSArmin Le Grand break; 1387*ddde725dSArmin Le Grand } 1388*ddde725dSArmin Le Grand case SVGTokenFont: 1389*ddde725dSArmin Le Grand { 1390*ddde725dSArmin Le Grand bool bBla = true; 1391*ddde725dSArmin Le Grand break; 1392*ddde725dSArmin Le Grand } 1393*ddde725dSArmin Le Grand case SVGTokenFontFamily: 1394*ddde725dSArmin Le Grand { 1395*ddde725dSArmin Le Grand SvgStringVector aSvgStringVector; 1396*ddde725dSArmin Le Grand 1397*ddde725dSArmin Le Grand if(readSvgStringVector(aContent, aSvgStringVector)) 1398*ddde725dSArmin Le Grand { 1399*ddde725dSArmin Le Grand setFontFamily(aSvgStringVector); 1400*ddde725dSArmin Le Grand } 1401*ddde725dSArmin Le Grand break; 1402*ddde725dSArmin Le Grand } 1403*ddde725dSArmin Le Grand case SVGTokenFontSize: 1404*ddde725dSArmin Le Grand { 1405*ddde725dSArmin Le Grand SvgNumber aNum; 1406*ddde725dSArmin Le Grand 1407*ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 1408*ddde725dSArmin Le Grand { 1409*ddde725dSArmin Le Grand setFontSize(aNum); 1410*ddde725dSArmin Le Grand } 1411*ddde725dSArmin Le Grand break; 1412*ddde725dSArmin Le Grand } 1413*ddde725dSArmin Le Grand case SVGTokenFontSizeAdjust: 1414*ddde725dSArmin Le Grand { 1415*ddde725dSArmin Le Grand bool bBla = true; 1416*ddde725dSArmin Le Grand break; 1417*ddde725dSArmin Le Grand } 1418*ddde725dSArmin Le Grand case SVGTokenFontStretch: 1419*ddde725dSArmin Le Grand { 1420*ddde725dSArmin Le Grand if(aContent.getLength()) 1421*ddde725dSArmin Le Grand { 1422*ddde725dSArmin Le Grand static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal")); 1423*ddde725dSArmin Le Grand static rtl::OUString aStrWider(rtl::OUString::createFromAscii("wider")); 1424*ddde725dSArmin Le Grand static rtl::OUString aStrNarrower(rtl::OUString::createFromAscii("narrower")); 1425*ddde725dSArmin Le Grand static rtl::OUString aStrUltra_condensed(rtl::OUString::createFromAscii("ultra-condensed")); 1426*ddde725dSArmin Le Grand static rtl::OUString aStrExtra_condensed(rtl::OUString::createFromAscii("extra-condensed")); 1427*ddde725dSArmin Le Grand static rtl::OUString aStrCondensed(rtl::OUString::createFromAscii("condensed")); 1428*ddde725dSArmin Le Grand static rtl::OUString aStrSemi_condensed(rtl::OUString::createFromAscii("semi-condensed")); 1429*ddde725dSArmin Le Grand static rtl::OUString aStrSemi_expanded(rtl::OUString::createFromAscii("semi-expanded")); 1430*ddde725dSArmin Le Grand static rtl::OUString aStrExpanded(rtl::OUString::createFromAscii("expanded")); 1431*ddde725dSArmin Le Grand static rtl::OUString aStrExtra_expanded(rtl::OUString::createFromAscii("extra-expanded")); 1432*ddde725dSArmin Le Grand static rtl::OUString aStrUltra_expanded(rtl::OUString::createFromAscii("ultra-expanded")); 1433*ddde725dSArmin Le Grand 1434*ddde725dSArmin Le Grand if(aContent.match(aStrNormal)) 1435*ddde725dSArmin Le Grand { 1436*ddde725dSArmin Le Grand setFontStretch(FontStretch_normal); 1437*ddde725dSArmin Le Grand } 1438*ddde725dSArmin Le Grand else if(aContent.match(aStrWider)) 1439*ddde725dSArmin Le Grand { 1440*ddde725dSArmin Le Grand setFontStretch(FontStretch_wider); 1441*ddde725dSArmin Le Grand } 1442*ddde725dSArmin Le Grand else if(aContent.match(aStrNarrower)) 1443*ddde725dSArmin Le Grand { 1444*ddde725dSArmin Le Grand setFontStretch(FontStretch_narrower); 1445*ddde725dSArmin Le Grand } 1446*ddde725dSArmin Le Grand else if(aContent.match(aStrUltra_condensed)) 1447*ddde725dSArmin Le Grand { 1448*ddde725dSArmin Le Grand setFontStretch(FontStretch_ultra_condensed); 1449*ddde725dSArmin Le Grand } 1450*ddde725dSArmin Le Grand else if(aContent.match(aStrExtra_condensed)) 1451*ddde725dSArmin Le Grand { 1452*ddde725dSArmin Le Grand setFontStretch(FontStretch_extra_condensed); 1453*ddde725dSArmin Le Grand } 1454*ddde725dSArmin Le Grand else if(aContent.match(aStrCondensed)) 1455*ddde725dSArmin Le Grand { 1456*ddde725dSArmin Le Grand setFontStretch(FontStretch_condensed); 1457*ddde725dSArmin Le Grand } 1458*ddde725dSArmin Le Grand else if(aContent.match(aStrSemi_condensed)) 1459*ddde725dSArmin Le Grand { 1460*ddde725dSArmin Le Grand setFontStretch(FontStretch_semi_condensed); 1461*ddde725dSArmin Le Grand } 1462*ddde725dSArmin Le Grand else if(aContent.match(aStrSemi_expanded)) 1463*ddde725dSArmin Le Grand { 1464*ddde725dSArmin Le Grand setFontStretch(FontStretch_semi_expanded); 1465*ddde725dSArmin Le Grand } 1466*ddde725dSArmin Le Grand else if(aContent.match(aStrExpanded)) 1467*ddde725dSArmin Le Grand { 1468*ddde725dSArmin Le Grand setFontStretch(FontStretch_expanded); 1469*ddde725dSArmin Le Grand } 1470*ddde725dSArmin Le Grand else if(aContent.match(aStrExtra_expanded)) 1471*ddde725dSArmin Le Grand { 1472*ddde725dSArmin Le Grand setFontStretch(FontStretch_extra_expanded); 1473*ddde725dSArmin Le Grand } 1474*ddde725dSArmin Le Grand else if(aContent.match(aStrUltra_expanded)) 1475*ddde725dSArmin Le Grand { 1476*ddde725dSArmin Le Grand setFontStretch(FontStretch_ultra_expanded); 1477*ddde725dSArmin Le Grand } 1478*ddde725dSArmin Le Grand } 1479*ddde725dSArmin Le Grand break; 1480*ddde725dSArmin Le Grand } 1481*ddde725dSArmin Le Grand case SVGTokenFontStyle: 1482*ddde725dSArmin Le Grand { 1483*ddde725dSArmin Le Grand if(aContent.getLength()) 1484*ddde725dSArmin Le Grand { 1485*ddde725dSArmin Le Grand static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal")); 1486*ddde725dSArmin Le Grand static rtl::OUString aStrItalic(rtl::OUString::createFromAscii("italic")); 1487*ddde725dSArmin Le Grand static rtl::OUString aStrOblique(rtl::OUString::createFromAscii("oblique")); 1488*ddde725dSArmin Le Grand 1489*ddde725dSArmin Le Grand if(aContent.match(aStrNormal)) 1490*ddde725dSArmin Le Grand { 1491*ddde725dSArmin Le Grand setFontStyle(FontStyle_normal); 1492*ddde725dSArmin Le Grand } 1493*ddde725dSArmin Le Grand else if(aContent.match(aStrItalic)) 1494*ddde725dSArmin Le Grand { 1495*ddde725dSArmin Le Grand setFontStyle(FontStyle_italic); 1496*ddde725dSArmin Le Grand } 1497*ddde725dSArmin Le Grand else if(aContent.match(aStrOblique)) 1498*ddde725dSArmin Le Grand { 1499*ddde725dSArmin Le Grand setFontStyle(FontStyle_oblique); 1500*ddde725dSArmin Le Grand } 1501*ddde725dSArmin Le Grand } 1502*ddde725dSArmin Le Grand break; 1503*ddde725dSArmin Le Grand } 1504*ddde725dSArmin Le Grand case SVGTokenFontVariant: 1505*ddde725dSArmin Le Grand { 1506*ddde725dSArmin Le Grand if(aContent.getLength()) 1507*ddde725dSArmin Le Grand { 1508*ddde725dSArmin Le Grand static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal")); 1509*ddde725dSArmin Le Grand static rtl::OUString aStrSmallCaps(rtl::OUString::createFromAscii("small-caps")); 1510*ddde725dSArmin Le Grand 1511*ddde725dSArmin Le Grand if(aContent.match(aStrNormal)) 1512*ddde725dSArmin Le Grand { 1513*ddde725dSArmin Le Grand setFontVariant(FontVariant_normal); 1514*ddde725dSArmin Le Grand } 1515*ddde725dSArmin Le Grand else if(aContent.match(aStrSmallCaps)) 1516*ddde725dSArmin Le Grand { 1517*ddde725dSArmin Le Grand setFontVariant(FontVariant_small_caps); 1518*ddde725dSArmin Le Grand } 1519*ddde725dSArmin Le Grand } 1520*ddde725dSArmin Le Grand break; 1521*ddde725dSArmin Le Grand } 1522*ddde725dSArmin Le Grand case SVGTokenFontWeight: 1523*ddde725dSArmin Le Grand { 1524*ddde725dSArmin Le Grand if(aContent.getLength()) 1525*ddde725dSArmin Le Grand { 1526*ddde725dSArmin Le Grand static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal")); 1527*ddde725dSArmin Le Grand static rtl::OUString aStrBold(rtl::OUString::createFromAscii("bold")); 1528*ddde725dSArmin Le Grand static rtl::OUString aStrBolder(rtl::OUString::createFromAscii("bolder")); 1529*ddde725dSArmin Le Grand static rtl::OUString aStrLighter(rtl::OUString::createFromAscii("lighter")); 1530*ddde725dSArmin Le Grand static rtl::OUString aStr100(rtl::OUString::createFromAscii("100")); 1531*ddde725dSArmin Le Grand static rtl::OUString aStr200(rtl::OUString::createFromAscii("200")); 1532*ddde725dSArmin Le Grand static rtl::OUString aStr300(rtl::OUString::createFromAscii("300")); 1533*ddde725dSArmin Le Grand static rtl::OUString aStr400(rtl::OUString::createFromAscii("400")); 1534*ddde725dSArmin Le Grand static rtl::OUString aStr500(rtl::OUString::createFromAscii("500")); 1535*ddde725dSArmin Le Grand static rtl::OUString aStr600(rtl::OUString::createFromAscii("600")); 1536*ddde725dSArmin Le Grand static rtl::OUString aStr700(rtl::OUString::createFromAscii("700")); 1537*ddde725dSArmin Le Grand static rtl::OUString aStr800(rtl::OUString::createFromAscii("800")); 1538*ddde725dSArmin Le Grand static rtl::OUString aStr900(rtl::OUString::createFromAscii("900")); 1539*ddde725dSArmin Le Grand 1540*ddde725dSArmin Le Grand if(aContent.match(aStr100)) 1541*ddde725dSArmin Le Grand { 1542*ddde725dSArmin Le Grand setFontWeight(FontWeight_100); 1543*ddde725dSArmin Le Grand } 1544*ddde725dSArmin Le Grand else if(aContent.match(aStr200)) 1545*ddde725dSArmin Le Grand { 1546*ddde725dSArmin Le Grand setFontWeight(FontWeight_200); 1547*ddde725dSArmin Le Grand } 1548*ddde725dSArmin Le Grand else if(aContent.match(aStr300)) 1549*ddde725dSArmin Le Grand { 1550*ddde725dSArmin Le Grand setFontWeight(FontWeight_300); 1551*ddde725dSArmin Le Grand } 1552*ddde725dSArmin Le Grand else if(aContent.match(aStr400) || aContent.match(aStrNormal)) 1553*ddde725dSArmin Le Grand { 1554*ddde725dSArmin Le Grand setFontWeight(FontWeight_400); 1555*ddde725dSArmin Le Grand } 1556*ddde725dSArmin Le Grand else if(aContent.match(aStr500)) 1557*ddde725dSArmin Le Grand { 1558*ddde725dSArmin Le Grand setFontWeight(FontWeight_500); 1559*ddde725dSArmin Le Grand } 1560*ddde725dSArmin Le Grand else if(aContent.match(aStr600)) 1561*ddde725dSArmin Le Grand { 1562*ddde725dSArmin Le Grand setFontWeight(FontWeight_600); 1563*ddde725dSArmin Le Grand } 1564*ddde725dSArmin Le Grand else if(aContent.match(aStr700) || aContent.match(aStrBold)) 1565*ddde725dSArmin Le Grand { 1566*ddde725dSArmin Le Grand setFontWeight(FontWeight_700); 1567*ddde725dSArmin Le Grand } 1568*ddde725dSArmin Le Grand else if(aContent.match(aStr800)) 1569*ddde725dSArmin Le Grand { 1570*ddde725dSArmin Le Grand setFontWeight(FontWeight_800); 1571*ddde725dSArmin Le Grand } 1572*ddde725dSArmin Le Grand else if(aContent.match(aStr900)) 1573*ddde725dSArmin Le Grand { 1574*ddde725dSArmin Le Grand setFontWeight(FontWeight_900); 1575*ddde725dSArmin Le Grand } 1576*ddde725dSArmin Le Grand else if(aContent.match(aStrBolder)) 1577*ddde725dSArmin Le Grand { 1578*ddde725dSArmin Le Grand setFontWeight(FontWeight_bolder); 1579*ddde725dSArmin Le Grand } 1580*ddde725dSArmin Le Grand else if(aContent.match(aStrLighter)) 1581*ddde725dSArmin Le Grand { 1582*ddde725dSArmin Le Grand setFontWeight(FontWeight_lighter); 1583*ddde725dSArmin Le Grand } 1584*ddde725dSArmin Le Grand } 1585*ddde725dSArmin Le Grand break; 1586*ddde725dSArmin Le Grand } 1587*ddde725dSArmin Le Grand case SVGTokenDirection: 1588*ddde725dSArmin Le Grand { 1589*ddde725dSArmin Le Grand bool bBla = true; 1590*ddde725dSArmin Le Grand break; 1591*ddde725dSArmin Le Grand } 1592*ddde725dSArmin Le Grand case SVGTokenLetterSpacing: 1593*ddde725dSArmin Le Grand { 1594*ddde725dSArmin Le Grand bool bBla = true; 1595*ddde725dSArmin Le Grand break; 1596*ddde725dSArmin Le Grand } 1597*ddde725dSArmin Le Grand case SVGTokenTextDecoration: 1598*ddde725dSArmin Le Grand { 1599*ddde725dSArmin Le Grand if(aContent.getLength()) 1600*ddde725dSArmin Le Grand { 1601*ddde725dSArmin Le Grand static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none")); 1602*ddde725dSArmin Le Grand static rtl::OUString aStrUnderline(rtl::OUString::createFromAscii("underline")); 1603*ddde725dSArmin Le Grand static rtl::OUString aStrOverline(rtl::OUString::createFromAscii("overline")); 1604*ddde725dSArmin Le Grand static rtl::OUString aStrLineThrough(rtl::OUString::createFromAscii("line-through")); 1605*ddde725dSArmin Le Grand static rtl::OUString aStrBlink(rtl::OUString::createFromAscii("blink")); 1606*ddde725dSArmin Le Grand 1607*ddde725dSArmin Le Grand if(aContent.match(aStrNone)) 1608*ddde725dSArmin Le Grand { 1609*ddde725dSArmin Le Grand setTextDecoration(TextDecoration_none); 1610*ddde725dSArmin Le Grand } 1611*ddde725dSArmin Le Grand else if(aContent.match(aStrUnderline)) 1612*ddde725dSArmin Le Grand { 1613*ddde725dSArmin Le Grand setTextDecoration(TextDecoration_underline); 1614*ddde725dSArmin Le Grand } 1615*ddde725dSArmin Le Grand else if(aContent.match(aStrOverline)) 1616*ddde725dSArmin Le Grand { 1617*ddde725dSArmin Le Grand setTextDecoration(TextDecoration_overline); 1618*ddde725dSArmin Le Grand } 1619*ddde725dSArmin Le Grand else if(aContent.match(aStrLineThrough)) 1620*ddde725dSArmin Le Grand { 1621*ddde725dSArmin Le Grand setTextDecoration(TextDecoration_line_through); 1622*ddde725dSArmin Le Grand } 1623*ddde725dSArmin Le Grand else if(aContent.match(aStrBlink)) 1624*ddde725dSArmin Le Grand { 1625*ddde725dSArmin Le Grand setTextDecoration(TextDecoration_blink); 1626*ddde725dSArmin Le Grand } 1627*ddde725dSArmin Le Grand } 1628*ddde725dSArmin Le Grand break; 1629*ddde725dSArmin Le Grand } 1630*ddde725dSArmin Le Grand case SVGTokenUnicodeBidi: 1631*ddde725dSArmin Le Grand { 1632*ddde725dSArmin Le Grand bool bBla = true; 1633*ddde725dSArmin Le Grand break; 1634*ddde725dSArmin Le Grand } 1635*ddde725dSArmin Le Grand case SVGTokenWordSpacing: 1636*ddde725dSArmin Le Grand { 1637*ddde725dSArmin Le Grand bool bBla = true; 1638*ddde725dSArmin Le Grand break; 1639*ddde725dSArmin Le Grand } 1640*ddde725dSArmin Le Grand case SVGTokenTextAnchor: 1641*ddde725dSArmin Le Grand { 1642*ddde725dSArmin Le Grand if(aContent.getLength()) 1643*ddde725dSArmin Le Grand { 1644*ddde725dSArmin Le Grand static rtl::OUString aStrStart(rtl::OUString::createFromAscii("start")); 1645*ddde725dSArmin Le Grand static rtl::OUString aStrMiddle(rtl::OUString::createFromAscii("middle")); 1646*ddde725dSArmin Le Grand static rtl::OUString aStrEnd(rtl::OUString::createFromAscii("end")); 1647*ddde725dSArmin Le Grand 1648*ddde725dSArmin Le Grand if(aContent.match(aStrStart)) 1649*ddde725dSArmin Le Grand { 1650*ddde725dSArmin Le Grand setTextAnchor(TextAnchor_start); 1651*ddde725dSArmin Le Grand } 1652*ddde725dSArmin Le Grand else if(aContent.match(aStrMiddle)) 1653*ddde725dSArmin Le Grand { 1654*ddde725dSArmin Le Grand setTextAnchor(TextAnchor_middle); 1655*ddde725dSArmin Le Grand } 1656*ddde725dSArmin Le Grand else if(aContent.match(aStrEnd)) 1657*ddde725dSArmin Le Grand { 1658*ddde725dSArmin Le Grand setTextAnchor(TextAnchor_end); 1659*ddde725dSArmin Le Grand } 1660*ddde725dSArmin Le Grand } 1661*ddde725dSArmin Le Grand break; 1662*ddde725dSArmin Le Grand } 1663*ddde725dSArmin Le Grand case SVGTokenTextAlign: 1664*ddde725dSArmin Le Grand { 1665*ddde725dSArmin Le Grand if(aContent.getLength()) 1666*ddde725dSArmin Le Grand { 1667*ddde725dSArmin Le Grand static rtl::OUString aStrLeft(rtl::OUString::createFromAscii("left")); 1668*ddde725dSArmin Le Grand static rtl::OUString aStrRight(rtl::OUString::createFromAscii("right")); 1669*ddde725dSArmin Le Grand static rtl::OUString aStrCenter(rtl::OUString::createFromAscii("center")); 1670*ddde725dSArmin Le Grand static rtl::OUString aStrJustify(rtl::OUString::createFromAscii("justify")); 1671*ddde725dSArmin Le Grand 1672*ddde725dSArmin Le Grand if(aContent.match(aStrLeft)) 1673*ddde725dSArmin Le Grand { 1674*ddde725dSArmin Le Grand setTextAlign(TextAlign_left); 1675*ddde725dSArmin Le Grand } 1676*ddde725dSArmin Le Grand else if(aContent.match(aStrRight)) 1677*ddde725dSArmin Le Grand { 1678*ddde725dSArmin Le Grand setTextAlign(TextAlign_right); 1679*ddde725dSArmin Le Grand } 1680*ddde725dSArmin Le Grand else if(aContent.match(aStrCenter)) 1681*ddde725dSArmin Le Grand { 1682*ddde725dSArmin Le Grand setTextAlign(TextAlign_center); 1683*ddde725dSArmin Le Grand } 1684*ddde725dSArmin Le Grand else if(aContent.match(aStrJustify)) 1685*ddde725dSArmin Le Grand { 1686*ddde725dSArmin Le Grand setTextAlign(TextAlign_justify); 1687*ddde725dSArmin Le Grand } 1688*ddde725dSArmin Le Grand } 1689*ddde725dSArmin Le Grand break; 1690*ddde725dSArmin Le Grand } 1691*ddde725dSArmin Le Grand case SVGTokenColor: 1692*ddde725dSArmin Le Grand { 1693*ddde725dSArmin Le Grand SvgPaint aSvgPaint; 1694*ddde725dSArmin Le Grand rtl::OUString aURL; 1695*ddde725dSArmin Le Grand 1696*ddde725dSArmin Le Grand if(readSvgPaint(aContent, aSvgPaint, aURL)) 1697*ddde725dSArmin Le Grand { 1698*ddde725dSArmin Le Grand setColor(aSvgPaint); 1699*ddde725dSArmin Le Grand } 1700*ddde725dSArmin Le Grand break; 1701*ddde725dSArmin Le Grand } 1702*ddde725dSArmin Le Grand case SVGTokenOpacity: 1703*ddde725dSArmin Le Grand { 1704*ddde725dSArmin Le Grand SvgNumber aNum; 1705*ddde725dSArmin Le Grand 1706*ddde725dSArmin Le Grand if(readSingleNumber(aContent, aNum)) 1707*ddde725dSArmin Le Grand { 1708*ddde725dSArmin Le Grand setOpacity(SvgNumber(basegfx::clamp(aNum.getNumber(), 0.0, 1.0), aNum.getUnit(), aNum.isSet())); 1709*ddde725dSArmin Le Grand } 1710*ddde725dSArmin Le Grand break; 1711*ddde725dSArmin Le Grand } 1712*ddde725dSArmin Le Grand case SVGTokenClipPathProperty: 1713*ddde725dSArmin Le Grand { 1714*ddde725dSArmin Le Grand readLocalUrl(aContent, maClipPathXLink); 1715*ddde725dSArmin Le Grand break; 1716*ddde725dSArmin Le Grand } 1717*ddde725dSArmin Le Grand case SVGTokenMask: 1718*ddde725dSArmin Le Grand { 1719*ddde725dSArmin Le Grand readLocalUrl(aContent, maMaskXLink); 1720*ddde725dSArmin Le Grand break; 1721*ddde725dSArmin Le Grand } 1722*ddde725dSArmin Le Grand case SVGTokenClipRule: 1723*ddde725dSArmin Le Grand { 1724*ddde725dSArmin Le Grand if(aContent.getLength()) 1725*ddde725dSArmin Le Grand { 1726*ddde725dSArmin Le Grand if(aContent.match(commonStrings::aStrNonzero)) 1727*ddde725dSArmin Le Grand { 1728*ddde725dSArmin Le Grand mbClipRule = true; 1729*ddde725dSArmin Le Grand } 1730*ddde725dSArmin Le Grand else if(aContent.match(commonStrings::aStrEvenOdd)) 1731*ddde725dSArmin Le Grand { 1732*ddde725dSArmin Le Grand mbClipRule = false; 1733*ddde725dSArmin Le Grand } 1734*ddde725dSArmin Le Grand } 1735*ddde725dSArmin Le Grand break; 1736*ddde725dSArmin Le Grand } 1737*ddde725dSArmin Le Grand case SVGTokenMarker: 1738*ddde725dSArmin Le Grand { 1739*ddde725dSArmin Le Grand readLocalUrl(aContent, maMarkerEndXLink); 1740*ddde725dSArmin Le Grand maMarkerStartXLink = maMarkerMidXLink = maMarkerEndXLink; 1741*ddde725dSArmin Le Grand break; 1742*ddde725dSArmin Le Grand } 1743*ddde725dSArmin Le Grand case SVGTokenMarkerStart: 1744*ddde725dSArmin Le Grand { 1745*ddde725dSArmin Le Grand readLocalUrl(aContent, maMarkerStartXLink); 1746*ddde725dSArmin Le Grand break; 1747*ddde725dSArmin Le Grand } 1748*ddde725dSArmin Le Grand case SVGTokenMarkerMid: 1749*ddde725dSArmin Le Grand { 1750*ddde725dSArmin Le Grand readLocalUrl(aContent, maMarkerMidXLink); 1751*ddde725dSArmin Le Grand break; 1752*ddde725dSArmin Le Grand } 1753*ddde725dSArmin Le Grand case SVGTokenMarkerEnd: 1754*ddde725dSArmin Le Grand { 1755*ddde725dSArmin Le Grand readLocalUrl(aContent, maMarkerEndXLink); 1756*ddde725dSArmin Le Grand break; 1757*ddde725dSArmin Le Grand } 1758*ddde725dSArmin Le Grand } 1759*ddde725dSArmin Le Grand } 1760*ddde725dSArmin Le Grand 1761*ddde725dSArmin Le Grand const basegfx::BColor* SvgStyleAttributes::getFill() const 1762*ddde725dSArmin Le Grand { 1763*ddde725dSArmin Le Grand if(mbIsClipPathContent) 1764*ddde725dSArmin Le Grand { 1765*ddde725dSArmin Le Grand static basegfx::BColor aBlack(0.0, 0.0, 0.0); 1766*ddde725dSArmin Le Grand 1767*ddde725dSArmin Le Grand return &aBlack; 1768*ddde725dSArmin Le Grand } 1769*ddde725dSArmin Le Grand else if(maFill.isSet()) 1770*ddde725dSArmin Le Grand { 1771*ddde725dSArmin Le Grand if(maFill.isCurrent()) 1772*ddde725dSArmin Le Grand { 1773*ddde725dSArmin Le Grand return getColor(); 1774*ddde725dSArmin Le Grand } 1775*ddde725dSArmin Le Grand else if(maFill.isOn()) 1776*ddde725dSArmin Le Grand { 1777*ddde725dSArmin Le Grand return &maFill.getBColor(); 1778*ddde725dSArmin Le Grand } 1779*ddde725dSArmin Le Grand } 1780*ddde725dSArmin Le Grand else 1781*ddde725dSArmin Le Grand { 1782*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1783*ddde725dSArmin Le Grand 1784*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1785*ddde725dSArmin Le Grand { 1786*ddde725dSArmin Le Grand return pSvgStyleAttributes->getFill(); 1787*ddde725dSArmin Le Grand } 1788*ddde725dSArmin Le Grand } 1789*ddde725dSArmin Le Grand 1790*ddde725dSArmin Le Grand return 0; 1791*ddde725dSArmin Le Grand } 1792*ddde725dSArmin Le Grand 1793*ddde725dSArmin Le Grand const basegfx::BColor* SvgStyleAttributes::getStroke() const 1794*ddde725dSArmin Le Grand { 1795*ddde725dSArmin Le Grand if(mbIsClipPathContent) 1796*ddde725dSArmin Le Grand { 1797*ddde725dSArmin Le Grand return 0; 1798*ddde725dSArmin Le Grand } 1799*ddde725dSArmin Le Grand else if(maStroke.isSet()) 1800*ddde725dSArmin Le Grand { 1801*ddde725dSArmin Le Grand if(maStroke.isCurrent()) 1802*ddde725dSArmin Le Grand { 1803*ddde725dSArmin Le Grand return getColor(); 1804*ddde725dSArmin Le Grand } 1805*ddde725dSArmin Le Grand else if(maStroke.isOn()) 1806*ddde725dSArmin Le Grand { 1807*ddde725dSArmin Le Grand return &maStroke.getBColor(); 1808*ddde725dSArmin Le Grand } 1809*ddde725dSArmin Le Grand } 1810*ddde725dSArmin Le Grand else 1811*ddde725dSArmin Le Grand { 1812*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1813*ddde725dSArmin Le Grand 1814*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1815*ddde725dSArmin Le Grand { 1816*ddde725dSArmin Le Grand return pSvgStyleAttributes->getStroke(); 1817*ddde725dSArmin Le Grand } 1818*ddde725dSArmin Le Grand } 1819*ddde725dSArmin Le Grand 1820*ddde725dSArmin Le Grand return 0; 1821*ddde725dSArmin Le Grand } 1822*ddde725dSArmin Le Grand 1823*ddde725dSArmin Le Grand const basegfx::BColor& SvgStyleAttributes::getStopColor() const 1824*ddde725dSArmin Le Grand { 1825*ddde725dSArmin Le Grand if(maStopColor.isCurrent()) 1826*ddde725dSArmin Le Grand { 1827*ddde725dSArmin Le Grand return *getColor(); 1828*ddde725dSArmin Le Grand } 1829*ddde725dSArmin Le Grand else 1830*ddde725dSArmin Le Grand { 1831*ddde725dSArmin Le Grand return maStopColor.getBColor(); 1832*ddde725dSArmin Le Grand } 1833*ddde725dSArmin Le Grand } 1834*ddde725dSArmin Le Grand 1835*ddde725dSArmin Le Grand const SvgGradientNode* SvgStyleAttributes::getSvgGradientNodeFill() const 1836*ddde725dSArmin Le Grand { 1837*ddde725dSArmin Le Grand if(mbIsClipPathContent) 1838*ddde725dSArmin Le Grand { 1839*ddde725dSArmin Le Grand return 0; 1840*ddde725dSArmin Le Grand } 1841*ddde725dSArmin Le Grand else if(mpSvgGradientNodeFill) 1842*ddde725dSArmin Le Grand { 1843*ddde725dSArmin Le Grand return mpSvgGradientNodeFill; 1844*ddde725dSArmin Le Grand } 1845*ddde725dSArmin Le Grand else 1846*ddde725dSArmin Le Grand { 1847*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1848*ddde725dSArmin Le Grand 1849*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1850*ddde725dSArmin Le Grand { 1851*ddde725dSArmin Le Grand return pSvgStyleAttributes->getSvgGradientNodeFill(); 1852*ddde725dSArmin Le Grand } 1853*ddde725dSArmin Le Grand } 1854*ddde725dSArmin Le Grand 1855*ddde725dSArmin Le Grand return 0; 1856*ddde725dSArmin Le Grand } 1857*ddde725dSArmin Le Grand 1858*ddde725dSArmin Le Grand const SvgGradientNode* SvgStyleAttributes::getSvgGradientNodeStroke() const 1859*ddde725dSArmin Le Grand { 1860*ddde725dSArmin Le Grand if(mbIsClipPathContent) 1861*ddde725dSArmin Le Grand { 1862*ddde725dSArmin Le Grand return 0; 1863*ddde725dSArmin Le Grand } 1864*ddde725dSArmin Le Grand else if(mpSvgGradientNodeStroke) 1865*ddde725dSArmin Le Grand { 1866*ddde725dSArmin Le Grand return mpSvgGradientNodeStroke; 1867*ddde725dSArmin Le Grand } 1868*ddde725dSArmin Le Grand else 1869*ddde725dSArmin Le Grand { 1870*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1871*ddde725dSArmin Le Grand 1872*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1873*ddde725dSArmin Le Grand { 1874*ddde725dSArmin Le Grand return pSvgStyleAttributes->getSvgGradientNodeStroke(); 1875*ddde725dSArmin Le Grand } 1876*ddde725dSArmin Le Grand } 1877*ddde725dSArmin Le Grand 1878*ddde725dSArmin Le Grand return 0; 1879*ddde725dSArmin Le Grand } 1880*ddde725dSArmin Le Grand 1881*ddde725dSArmin Le Grand const SvgPatternNode* SvgStyleAttributes::getSvgPatternNodeFill() const 1882*ddde725dSArmin Le Grand { 1883*ddde725dSArmin Le Grand if(mbIsClipPathContent) 1884*ddde725dSArmin Le Grand { 1885*ddde725dSArmin Le Grand return 0; 1886*ddde725dSArmin Le Grand } 1887*ddde725dSArmin Le Grand else if(mpSvgPatternNodeFill) 1888*ddde725dSArmin Le Grand { 1889*ddde725dSArmin Le Grand return mpSvgPatternNodeFill; 1890*ddde725dSArmin Le Grand } 1891*ddde725dSArmin Le Grand else 1892*ddde725dSArmin Le Grand { 1893*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1894*ddde725dSArmin Le Grand 1895*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1896*ddde725dSArmin Le Grand { 1897*ddde725dSArmin Le Grand return pSvgStyleAttributes->getSvgPatternNodeFill(); 1898*ddde725dSArmin Le Grand } 1899*ddde725dSArmin Le Grand } 1900*ddde725dSArmin Le Grand 1901*ddde725dSArmin Le Grand return 0; 1902*ddde725dSArmin Le Grand } 1903*ddde725dSArmin Le Grand 1904*ddde725dSArmin Le Grand const SvgPatternNode* SvgStyleAttributes::getSvgPatternNodeStroke() const 1905*ddde725dSArmin Le Grand { 1906*ddde725dSArmin Le Grand if(mbIsClipPathContent) 1907*ddde725dSArmin Le Grand { 1908*ddde725dSArmin Le Grand return 0; 1909*ddde725dSArmin Le Grand } 1910*ddde725dSArmin Le Grand else if(mpSvgPatternNodeStroke) 1911*ddde725dSArmin Le Grand { 1912*ddde725dSArmin Le Grand return mpSvgPatternNodeStroke; 1913*ddde725dSArmin Le Grand } 1914*ddde725dSArmin Le Grand else 1915*ddde725dSArmin Le Grand { 1916*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1917*ddde725dSArmin Le Grand 1918*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1919*ddde725dSArmin Le Grand { 1920*ddde725dSArmin Le Grand return pSvgStyleAttributes->getSvgPatternNodeStroke(); 1921*ddde725dSArmin Le Grand } 1922*ddde725dSArmin Le Grand } 1923*ddde725dSArmin Le Grand 1924*ddde725dSArmin Le Grand return 0; 1925*ddde725dSArmin Le Grand } 1926*ddde725dSArmin Le Grand 1927*ddde725dSArmin Le Grand const SvgNumber SvgStyleAttributes::getStrokeWidth() const 1928*ddde725dSArmin Le Grand { 1929*ddde725dSArmin Le Grand if(mbIsClipPathContent) 1930*ddde725dSArmin Le Grand { 1931*ddde725dSArmin Le Grand return SvgNumber(0.0); 1932*ddde725dSArmin Le Grand } 1933*ddde725dSArmin Le Grand else if(maStrokeWidth.isSet()) 1934*ddde725dSArmin Le Grand { 1935*ddde725dSArmin Le Grand return maStrokeWidth; 1936*ddde725dSArmin Le Grand } 1937*ddde725dSArmin Le Grand 1938*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1939*ddde725dSArmin Le Grand 1940*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1941*ddde725dSArmin Le Grand { 1942*ddde725dSArmin Le Grand return pSvgStyleAttributes->getStrokeWidth(); 1943*ddde725dSArmin Le Grand } 1944*ddde725dSArmin Le Grand 1945*ddde725dSArmin Le Grand // default is 1 1946*ddde725dSArmin Le Grand return SvgNumber(1.0); 1947*ddde725dSArmin Le Grand } 1948*ddde725dSArmin Le Grand 1949*ddde725dSArmin Le Grand const SvgNumber SvgStyleAttributes::getStopOpacity() const 1950*ddde725dSArmin Le Grand { 1951*ddde725dSArmin Le Grand if(maStopOpacity.isSet()) 1952*ddde725dSArmin Le Grand { 1953*ddde725dSArmin Le Grand return maStopOpacity; 1954*ddde725dSArmin Le Grand } 1955*ddde725dSArmin Le Grand 1956*ddde725dSArmin Le Grand // default is 1 1957*ddde725dSArmin Le Grand return SvgNumber(1.0); 1958*ddde725dSArmin Le Grand } 1959*ddde725dSArmin Le Grand 1960*ddde725dSArmin Le Grand const SvgNumber SvgStyleAttributes::getFillOpacity() const 1961*ddde725dSArmin Le Grand { 1962*ddde725dSArmin Le Grand if(mbIsClipPathContent) 1963*ddde725dSArmin Le Grand { 1964*ddde725dSArmin Le Grand return SvgNumber(1.0); 1965*ddde725dSArmin Le Grand } 1966*ddde725dSArmin Le Grand else if(maFillOpacity.isSet()) 1967*ddde725dSArmin Le Grand { 1968*ddde725dSArmin Le Grand return maFillOpacity; 1969*ddde725dSArmin Le Grand } 1970*ddde725dSArmin Le Grand 1971*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1972*ddde725dSArmin Le Grand 1973*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1974*ddde725dSArmin Le Grand { 1975*ddde725dSArmin Le Grand return pSvgStyleAttributes->getFillOpacity(); 1976*ddde725dSArmin Le Grand } 1977*ddde725dSArmin Le Grand 1978*ddde725dSArmin Le Grand // default is 1 1979*ddde725dSArmin Le Grand return SvgNumber(1.0); 1980*ddde725dSArmin Le Grand } 1981*ddde725dSArmin Le Grand 1982*ddde725dSArmin Le Grand bool SvgStyleAttributes::getFillRule() const 1983*ddde725dSArmin Le Grand { 1984*ddde725dSArmin Le Grand if(maFillRuleSet) 1985*ddde725dSArmin Le Grand { 1986*ddde725dSArmin Le Grand return maFillRule; 1987*ddde725dSArmin Le Grand } 1988*ddde725dSArmin Le Grand 1989*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 1990*ddde725dSArmin Le Grand 1991*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 1992*ddde725dSArmin Le Grand { 1993*ddde725dSArmin Le Grand return pSvgStyleAttributes->getFillRule(); 1994*ddde725dSArmin Le Grand } 1995*ddde725dSArmin Le Grand 1996*ddde725dSArmin Le Grand // default is NonZero 1997*ddde725dSArmin Le Grand return true; 1998*ddde725dSArmin Le Grand } 1999*ddde725dSArmin Le Grand 2000*ddde725dSArmin Le Grand void SvgStyleAttributes::setFillRule(const bool* pFillRule) 2001*ddde725dSArmin Le Grand { 2002*ddde725dSArmin Le Grand if(pFillRule) 2003*ddde725dSArmin Le Grand { 2004*ddde725dSArmin Le Grand maFillRuleSet = true; 2005*ddde725dSArmin Le Grand maFillRule = *pFillRule; 2006*ddde725dSArmin Le Grand } 2007*ddde725dSArmin Le Grand else 2008*ddde725dSArmin Le Grand { 2009*ddde725dSArmin Le Grand maFillRuleSet = false; 2010*ddde725dSArmin Le Grand } 2011*ddde725dSArmin Le Grand } 2012*ddde725dSArmin Le Grand 2013*ddde725dSArmin Le Grand const SvgNumberVector& SvgStyleAttributes::getStrokeDasharray() const 2014*ddde725dSArmin Le Grand { 2015*ddde725dSArmin Le Grand if(!maStrokeDasharray.empty()) 2016*ddde725dSArmin Le Grand { 2017*ddde725dSArmin Le Grand return maStrokeDasharray; 2018*ddde725dSArmin Le Grand } 2019*ddde725dSArmin Le Grand 2020*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2021*ddde725dSArmin Le Grand 2022*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2023*ddde725dSArmin Le Grand { 2024*ddde725dSArmin Le Grand return pSvgStyleAttributes->getStrokeDasharray(); 2025*ddde725dSArmin Le Grand } 2026*ddde725dSArmin Le Grand 2027*ddde725dSArmin Le Grand // default empty 2028*ddde725dSArmin Le Grand return maStrokeDasharray; 2029*ddde725dSArmin Le Grand } 2030*ddde725dSArmin Le Grand 2031*ddde725dSArmin Le Grand const SvgNumber SvgStyleAttributes::getStrokeDashOffset() const 2032*ddde725dSArmin Le Grand { 2033*ddde725dSArmin Le Grand if(maStrokeDashOffset.isSet()) 2034*ddde725dSArmin Le Grand { 2035*ddde725dSArmin Le Grand return maStrokeDashOffset; 2036*ddde725dSArmin Le Grand } 2037*ddde725dSArmin Le Grand 2038*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2039*ddde725dSArmin Le Grand 2040*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2041*ddde725dSArmin Le Grand { 2042*ddde725dSArmin Le Grand return pSvgStyleAttributes->getStrokeDashOffset(); 2043*ddde725dSArmin Le Grand } 2044*ddde725dSArmin Le Grand 2045*ddde725dSArmin Le Grand // default is 0 2046*ddde725dSArmin Le Grand return SvgNumber(0.0); 2047*ddde725dSArmin Le Grand } 2048*ddde725dSArmin Le Grand 2049*ddde725dSArmin Le Grand const StrokeLinecap SvgStyleAttributes::getStrokeLinecap() const 2050*ddde725dSArmin Le Grand { 2051*ddde725dSArmin Le Grand if(maStrokeLinecap != StrokeLinecap_notset) 2052*ddde725dSArmin Le Grand { 2053*ddde725dSArmin Le Grand return maStrokeLinecap; 2054*ddde725dSArmin Le Grand } 2055*ddde725dSArmin Le Grand 2056*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2057*ddde725dSArmin Le Grand 2058*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2059*ddde725dSArmin Le Grand { 2060*ddde725dSArmin Le Grand return pSvgStyleAttributes->getStrokeLinecap(); 2061*ddde725dSArmin Le Grand } 2062*ddde725dSArmin Le Grand 2063*ddde725dSArmin Le Grand // default is StrokeLinecap_butt 2064*ddde725dSArmin Le Grand return StrokeLinecap_butt; 2065*ddde725dSArmin Le Grand } 2066*ddde725dSArmin Le Grand 2067*ddde725dSArmin Le Grand const StrokeLinejoin SvgStyleAttributes::getStrokeLinejoin() const 2068*ddde725dSArmin Le Grand { 2069*ddde725dSArmin Le Grand if(maStrokeLinejoin != StrokeLinejoin_notset) 2070*ddde725dSArmin Le Grand { 2071*ddde725dSArmin Le Grand return maStrokeLinejoin; 2072*ddde725dSArmin Le Grand } 2073*ddde725dSArmin Le Grand 2074*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2075*ddde725dSArmin Le Grand 2076*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2077*ddde725dSArmin Le Grand { 2078*ddde725dSArmin Le Grand return pSvgStyleAttributes->getStrokeLinejoin(); 2079*ddde725dSArmin Le Grand } 2080*ddde725dSArmin Le Grand 2081*ddde725dSArmin Le Grand // default is StrokeLinejoin_butt 2082*ddde725dSArmin Le Grand return StrokeLinejoin_miter; 2083*ddde725dSArmin Le Grand } 2084*ddde725dSArmin Le Grand 2085*ddde725dSArmin Le Grand const SvgNumber SvgStyleAttributes::getStrokeMiterLimit() const 2086*ddde725dSArmin Le Grand { 2087*ddde725dSArmin Le Grand if(maStrokeMiterLimit.isSet()) 2088*ddde725dSArmin Le Grand { 2089*ddde725dSArmin Le Grand return maStrokeMiterLimit; 2090*ddde725dSArmin Le Grand } 2091*ddde725dSArmin Le Grand 2092*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2093*ddde725dSArmin Le Grand 2094*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2095*ddde725dSArmin Le Grand { 2096*ddde725dSArmin Le Grand return pSvgStyleAttributes->getStrokeMiterLimit(); 2097*ddde725dSArmin Le Grand } 2098*ddde725dSArmin Le Grand 2099*ddde725dSArmin Le Grand // default is 4 2100*ddde725dSArmin Le Grand return SvgNumber(4.0); 2101*ddde725dSArmin Le Grand } 2102*ddde725dSArmin Le Grand 2103*ddde725dSArmin Le Grand const SvgNumber SvgStyleAttributes::getStrokeOpacity() const 2104*ddde725dSArmin Le Grand { 2105*ddde725dSArmin Le Grand if(maStrokeOpacity.isSet()) 2106*ddde725dSArmin Le Grand { 2107*ddde725dSArmin Le Grand return maStrokeOpacity; 2108*ddde725dSArmin Le Grand } 2109*ddde725dSArmin Le Grand 2110*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2111*ddde725dSArmin Le Grand 2112*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2113*ddde725dSArmin Le Grand { 2114*ddde725dSArmin Le Grand return pSvgStyleAttributes->getStrokeOpacity(); 2115*ddde725dSArmin Le Grand } 2116*ddde725dSArmin Le Grand 2117*ddde725dSArmin Le Grand // default is 1 2118*ddde725dSArmin Le Grand return SvgNumber(1.0); 2119*ddde725dSArmin Le Grand } 2120*ddde725dSArmin Le Grand 2121*ddde725dSArmin Le Grand const SvgStringVector& SvgStyleAttributes::getFontFamily() const 2122*ddde725dSArmin Le Grand { 2123*ddde725dSArmin Le Grand if(!maFontFamily.empty()) 2124*ddde725dSArmin Le Grand { 2125*ddde725dSArmin Le Grand return maFontFamily; 2126*ddde725dSArmin Le Grand } 2127*ddde725dSArmin Le Grand 2128*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2129*ddde725dSArmin Le Grand 2130*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2131*ddde725dSArmin Le Grand { 2132*ddde725dSArmin Le Grand return pSvgStyleAttributes->getFontFamily(); 2133*ddde725dSArmin Le Grand } 2134*ddde725dSArmin Le Grand 2135*ddde725dSArmin Le Grand // default is empty 2136*ddde725dSArmin Le Grand return maFontFamily; 2137*ddde725dSArmin Le Grand } 2138*ddde725dSArmin Le Grand 2139*ddde725dSArmin Le Grand const SvgNumber SvgStyleAttributes::getFontSize() const 2140*ddde725dSArmin Le Grand { 2141*ddde725dSArmin Le Grand if(maFontSize.isSet()) 2142*ddde725dSArmin Le Grand { 2143*ddde725dSArmin Le Grand return maFontSize; 2144*ddde725dSArmin Le Grand } 2145*ddde725dSArmin Le Grand 2146*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2147*ddde725dSArmin Le Grand 2148*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2149*ddde725dSArmin Le Grand { 2150*ddde725dSArmin Le Grand return pSvgStyleAttributes->getFontSize(); 2151*ddde725dSArmin Le Grand } 2152*ddde725dSArmin Le Grand 2153*ddde725dSArmin Le Grand // default is 'medium' 2154*ddde725dSArmin Le Grand return SvgNumber(12.0); 2155*ddde725dSArmin Le Grand } 2156*ddde725dSArmin Le Grand 2157*ddde725dSArmin Le Grand const FontStretch SvgStyleAttributes::getFontStretch() const 2158*ddde725dSArmin Le Grand { 2159*ddde725dSArmin Le Grand if(maFontStretch != FontStretch_notset) 2160*ddde725dSArmin Le Grand { 2161*ddde725dSArmin Le Grand if(FontStretch_wider != maFontStretch && FontStretch_narrower != maFontStretch) 2162*ddde725dSArmin Le Grand { 2163*ddde725dSArmin Le Grand return maFontStretch; 2164*ddde725dSArmin Le Grand } 2165*ddde725dSArmin Le Grand } 2166*ddde725dSArmin Le Grand 2167*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2168*ddde725dSArmin Le Grand 2169*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2170*ddde725dSArmin Le Grand { 2171*ddde725dSArmin Le Grand FontStretch aInherited = pSvgStyleAttributes->getFontStretch(); 2172*ddde725dSArmin Le Grand 2173*ddde725dSArmin Le Grand if(FontStretch_wider == maFontStretch) 2174*ddde725dSArmin Le Grand { 2175*ddde725dSArmin Le Grand aInherited = getWider(aInherited); 2176*ddde725dSArmin Le Grand } 2177*ddde725dSArmin Le Grand else if(FontStretch_narrower == maFontStretch) 2178*ddde725dSArmin Le Grand { 2179*ddde725dSArmin Le Grand aInherited = getNarrower(aInherited); 2180*ddde725dSArmin Le Grand } 2181*ddde725dSArmin Le Grand 2182*ddde725dSArmin Le Grand return aInherited; 2183*ddde725dSArmin Le Grand } 2184*ddde725dSArmin Le Grand 2185*ddde725dSArmin Le Grand // default is FontStretch_normal 2186*ddde725dSArmin Le Grand return FontStretch_normal; 2187*ddde725dSArmin Le Grand } 2188*ddde725dSArmin Le Grand 2189*ddde725dSArmin Le Grand const FontStyle SvgStyleAttributes::getFontStyle() const 2190*ddde725dSArmin Le Grand { 2191*ddde725dSArmin Le Grand if(maFontStyle != FontStyle_notset) 2192*ddde725dSArmin Le Grand { 2193*ddde725dSArmin Le Grand return maFontStyle; 2194*ddde725dSArmin Le Grand } 2195*ddde725dSArmin Le Grand 2196*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2197*ddde725dSArmin Le Grand 2198*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2199*ddde725dSArmin Le Grand { 2200*ddde725dSArmin Le Grand return pSvgStyleAttributes->getFontStyle(); 2201*ddde725dSArmin Le Grand } 2202*ddde725dSArmin Le Grand 2203*ddde725dSArmin Le Grand // default is FontStyle_normal 2204*ddde725dSArmin Le Grand return FontStyle_normal; 2205*ddde725dSArmin Le Grand } 2206*ddde725dSArmin Le Grand 2207*ddde725dSArmin Le Grand const FontWeight SvgStyleAttributes::getFontWeight() const 2208*ddde725dSArmin Le Grand { 2209*ddde725dSArmin Le Grand if(maFontWeight != FontWeight_notset) 2210*ddde725dSArmin Le Grand { 2211*ddde725dSArmin Le Grand if(FontWeight_bolder != maFontWeight && FontWeight_lighter != maFontWeight) 2212*ddde725dSArmin Le Grand { 2213*ddde725dSArmin Le Grand return maFontWeight; 2214*ddde725dSArmin Le Grand } 2215*ddde725dSArmin Le Grand } 2216*ddde725dSArmin Le Grand 2217*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2218*ddde725dSArmin Le Grand 2219*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2220*ddde725dSArmin Le Grand { 2221*ddde725dSArmin Le Grand FontWeight aInherited = pSvgStyleAttributes->getFontWeight(); 2222*ddde725dSArmin Le Grand 2223*ddde725dSArmin Le Grand if(FontWeight_bolder == maFontWeight) 2224*ddde725dSArmin Le Grand { 2225*ddde725dSArmin Le Grand aInherited = getBolder(aInherited); 2226*ddde725dSArmin Le Grand } 2227*ddde725dSArmin Le Grand else if(FontWeight_lighter == maFontWeight) 2228*ddde725dSArmin Le Grand { 2229*ddde725dSArmin Le Grand aInherited = getLighter(aInherited); 2230*ddde725dSArmin Le Grand } 2231*ddde725dSArmin Le Grand 2232*ddde725dSArmin Le Grand return aInherited; 2233*ddde725dSArmin Le Grand } 2234*ddde725dSArmin Le Grand 2235*ddde725dSArmin Le Grand // default is FontWeight_400 (FontWeight_normal) 2236*ddde725dSArmin Le Grand return FontWeight_400; 2237*ddde725dSArmin Le Grand } 2238*ddde725dSArmin Le Grand 2239*ddde725dSArmin Le Grand const TextAlign SvgStyleAttributes::getTextAlign() const 2240*ddde725dSArmin Le Grand { 2241*ddde725dSArmin Le Grand if(maTextAlign != TextAlign_notset) 2242*ddde725dSArmin Le Grand { 2243*ddde725dSArmin Le Grand return maTextAlign; 2244*ddde725dSArmin Le Grand } 2245*ddde725dSArmin Le Grand 2246*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2247*ddde725dSArmin Le Grand 2248*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2249*ddde725dSArmin Le Grand { 2250*ddde725dSArmin Le Grand return pSvgStyleAttributes->getTextAlign(); 2251*ddde725dSArmin Le Grand } 2252*ddde725dSArmin Le Grand 2253*ddde725dSArmin Le Grand // default is TextAlign_left 2254*ddde725dSArmin Le Grand return TextAlign_left; 2255*ddde725dSArmin Le Grand } 2256*ddde725dSArmin Le Grand 2257*ddde725dSArmin Le Grand const SvgStyleAttributes* SvgStyleAttributes::getTextDecorationDefiningSvgStyleAttributes() const 2258*ddde725dSArmin Le Grand { 2259*ddde725dSArmin Le Grand if(maTextDecoration != TextDecoration_notset) 2260*ddde725dSArmin Le Grand { 2261*ddde725dSArmin Le Grand return this; 2262*ddde725dSArmin Le Grand } 2263*ddde725dSArmin Le Grand 2264*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2265*ddde725dSArmin Le Grand 2266*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2267*ddde725dSArmin Le Grand { 2268*ddde725dSArmin Le Grand return pSvgStyleAttributes->getTextDecorationDefiningSvgStyleAttributes(); 2269*ddde725dSArmin Le Grand } 2270*ddde725dSArmin Le Grand 2271*ddde725dSArmin Le Grand // default is 0 2272*ddde725dSArmin Le Grand return 0; 2273*ddde725dSArmin Le Grand } 2274*ddde725dSArmin Le Grand 2275*ddde725dSArmin Le Grand const TextDecoration SvgStyleAttributes::getTextDecoration() const 2276*ddde725dSArmin Le Grand { 2277*ddde725dSArmin Le Grand const SvgStyleAttributes* pDefining = getTextDecorationDefiningSvgStyleAttributes(); 2278*ddde725dSArmin Le Grand 2279*ddde725dSArmin Le Grand if(pDefining) 2280*ddde725dSArmin Le Grand { 2281*ddde725dSArmin Le Grand return pDefining->maTextDecoration; 2282*ddde725dSArmin Le Grand } 2283*ddde725dSArmin Le Grand else 2284*ddde725dSArmin Le Grand { 2285*ddde725dSArmin Le Grand // default is TextDecoration_none 2286*ddde725dSArmin Le Grand return TextDecoration_none; 2287*ddde725dSArmin Le Grand } 2288*ddde725dSArmin Le Grand } 2289*ddde725dSArmin Le Grand 2290*ddde725dSArmin Le Grand const TextAnchor SvgStyleAttributes::getTextAnchor() const 2291*ddde725dSArmin Le Grand { 2292*ddde725dSArmin Le Grand if(maTextAnchor != TextAnchor_notset) 2293*ddde725dSArmin Le Grand { 2294*ddde725dSArmin Le Grand return maTextAnchor; 2295*ddde725dSArmin Le Grand } 2296*ddde725dSArmin Le Grand 2297*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2298*ddde725dSArmin Le Grand 2299*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2300*ddde725dSArmin Le Grand { 2301*ddde725dSArmin Le Grand return pSvgStyleAttributes->getTextAnchor(); 2302*ddde725dSArmin Le Grand } 2303*ddde725dSArmin Le Grand 2304*ddde725dSArmin Le Grand // default is TextAnchor_start 2305*ddde725dSArmin Le Grand return TextAnchor_start; 2306*ddde725dSArmin Le Grand } 2307*ddde725dSArmin Le Grand 2308*ddde725dSArmin Le Grand const basegfx::BColor* SvgStyleAttributes::getColor() const 2309*ddde725dSArmin Le Grand { 2310*ddde725dSArmin Le Grand if(maColor.isSet()) 2311*ddde725dSArmin Le Grand { 2312*ddde725dSArmin Le Grand if(maColor.isCurrent()) 2313*ddde725dSArmin Le Grand { 2314*ddde725dSArmin Le Grand OSL_ENSURE(false, "Svg error: current color uses current color (!)"); 2315*ddde725dSArmin Le Grand return 0; 2316*ddde725dSArmin Le Grand } 2317*ddde725dSArmin Le Grand else if(maColor.isOn()) 2318*ddde725dSArmin Le Grand { 2319*ddde725dSArmin Le Grand return &maColor.getBColor(); 2320*ddde725dSArmin Le Grand } 2321*ddde725dSArmin Le Grand } 2322*ddde725dSArmin Le Grand else 2323*ddde725dSArmin Le Grand { 2324*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2325*ddde725dSArmin Le Grand 2326*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2327*ddde725dSArmin Le Grand { 2328*ddde725dSArmin Le Grand return pSvgStyleAttributes->getColor(); 2329*ddde725dSArmin Le Grand } 2330*ddde725dSArmin Le Grand } 2331*ddde725dSArmin Le Grand 2332*ddde725dSArmin Le Grand return 0; 2333*ddde725dSArmin Le Grand } 2334*ddde725dSArmin Le Grand 2335*ddde725dSArmin Le Grand const rtl::OUString SvgStyleAttributes::getMarkerStartXLink() const 2336*ddde725dSArmin Le Grand { 2337*ddde725dSArmin Le Grand if(maMarkerStartXLink.getLength()) 2338*ddde725dSArmin Le Grand { 2339*ddde725dSArmin Le Grand return maMarkerStartXLink; 2340*ddde725dSArmin Le Grand } 2341*ddde725dSArmin Le Grand 2342*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2343*ddde725dSArmin Le Grand 2344*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2345*ddde725dSArmin Le Grand { 2346*ddde725dSArmin Le Grand return pSvgStyleAttributes->getMarkerStartXLink(); 2347*ddde725dSArmin Le Grand } 2348*ddde725dSArmin Le Grand 2349*ddde725dSArmin Le Grand return rtl::OUString(); 2350*ddde725dSArmin Le Grand } 2351*ddde725dSArmin Le Grand 2352*ddde725dSArmin Le Grand const SvgMarkerNode* SvgStyleAttributes::accessMarkerStartXLink() const 2353*ddde725dSArmin Le Grand { 2354*ddde725dSArmin Le Grand if(!mpMarkerStartXLink) 2355*ddde725dSArmin Le Grand { 2356*ddde725dSArmin Le Grand const rtl::OUString aMarker(getMarkerStartXLink()); 2357*ddde725dSArmin Le Grand 2358*ddde725dSArmin Le Grand if(aMarker.getLength()) 2359*ddde725dSArmin Le Grand { 2360*ddde725dSArmin Le Grand const_cast< SvgStyleAttributes* >(this)->mpMarkerStartXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerStartXLink())); 2361*ddde725dSArmin Le Grand } 2362*ddde725dSArmin Le Grand } 2363*ddde725dSArmin Le Grand 2364*ddde725dSArmin Le Grand return mpMarkerStartXLink; 2365*ddde725dSArmin Le Grand } 2366*ddde725dSArmin Le Grand 2367*ddde725dSArmin Le Grand const rtl::OUString SvgStyleAttributes::getMarkerMidXLink() const 2368*ddde725dSArmin Le Grand { 2369*ddde725dSArmin Le Grand if(maMarkerMidXLink.getLength()) 2370*ddde725dSArmin Le Grand { 2371*ddde725dSArmin Le Grand return maMarkerMidXLink; 2372*ddde725dSArmin Le Grand } 2373*ddde725dSArmin Le Grand 2374*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2375*ddde725dSArmin Le Grand 2376*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2377*ddde725dSArmin Le Grand { 2378*ddde725dSArmin Le Grand return pSvgStyleAttributes->getMarkerMidXLink(); 2379*ddde725dSArmin Le Grand } 2380*ddde725dSArmin Le Grand 2381*ddde725dSArmin Le Grand return rtl::OUString(); 2382*ddde725dSArmin Le Grand } 2383*ddde725dSArmin Le Grand 2384*ddde725dSArmin Le Grand const SvgMarkerNode* SvgStyleAttributes::accessMarkerMidXLink() const 2385*ddde725dSArmin Le Grand { 2386*ddde725dSArmin Le Grand if(!mpMarkerMidXLink) 2387*ddde725dSArmin Le Grand { 2388*ddde725dSArmin Le Grand const rtl::OUString aMarker(getMarkerMidXLink()); 2389*ddde725dSArmin Le Grand 2390*ddde725dSArmin Le Grand if(aMarker.getLength()) 2391*ddde725dSArmin Le Grand { 2392*ddde725dSArmin Le Grand const_cast< SvgStyleAttributes* >(this)->mpMarkerMidXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerMidXLink())); 2393*ddde725dSArmin Le Grand } 2394*ddde725dSArmin Le Grand } 2395*ddde725dSArmin Le Grand 2396*ddde725dSArmin Le Grand return mpMarkerMidXLink; 2397*ddde725dSArmin Le Grand } 2398*ddde725dSArmin Le Grand 2399*ddde725dSArmin Le Grand const rtl::OUString SvgStyleAttributes::getMarkerEndXLink() const 2400*ddde725dSArmin Le Grand { 2401*ddde725dSArmin Le Grand if(maMarkerEndXLink.getLength()) 2402*ddde725dSArmin Le Grand { 2403*ddde725dSArmin Le Grand return maMarkerEndXLink; 2404*ddde725dSArmin Le Grand } 2405*ddde725dSArmin Le Grand 2406*ddde725dSArmin Le Grand const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle(); 2407*ddde725dSArmin Le Grand 2408*ddde725dSArmin Le Grand if(pSvgStyleAttributes) 2409*ddde725dSArmin Le Grand { 2410*ddde725dSArmin Le Grand return pSvgStyleAttributes->getMarkerEndXLink(); 2411*ddde725dSArmin Le Grand } 2412*ddde725dSArmin Le Grand 2413*ddde725dSArmin Le Grand return rtl::OUString(); 2414*ddde725dSArmin Le Grand } 2415*ddde725dSArmin Le Grand 2416*ddde725dSArmin Le Grand const SvgMarkerNode* SvgStyleAttributes::accessMarkerEndXLink() const 2417*ddde725dSArmin Le Grand { 2418*ddde725dSArmin Le Grand if(!mpMarkerEndXLink) 2419*ddde725dSArmin Le Grand { 2420*ddde725dSArmin Le Grand const rtl::OUString aMarker(getMarkerEndXLink()); 2421*ddde725dSArmin Le Grand 2422*ddde725dSArmin Le Grand if(aMarker.getLength()) 2423*ddde725dSArmin Le Grand { 2424*ddde725dSArmin Le Grand const_cast< SvgStyleAttributes* >(this)->mpMarkerEndXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerEndXLink())); 2425*ddde725dSArmin Le Grand } 2426*ddde725dSArmin Le Grand } 2427*ddde725dSArmin Le Grand 2428*ddde725dSArmin Le Grand return mpMarkerEndXLink; 2429*ddde725dSArmin Le Grand } 2430*ddde725dSArmin Le Grand 2431*ddde725dSArmin Le Grand } // end of namespace svgreader 2432*ddde725dSArmin Le Grand } // end of namespace svgio 2433*ddde725dSArmin Le Grand 2434*ddde725dSArmin Le Grand ////////////////////////////////////////////////////////////////////////////// 2435*ddde725dSArmin Le Grand // eof 2436