LCOV - code coverage report
Current view: top level - libreoffice/svgio/source/svgreader - svgstyleattributes.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 1011 0.0 %
Date: 2012-12-27 Functions: 0 58 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10