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