You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by al...@apache.org on 2011/12/01 17:26:53 UTC

svn commit: r1209140 [7/11] - in /incubator/ooo/branches/alg/svgreplacement/main: ./ basegfx/inc/basegfx/matrix/ basegfx/inc/basegfx/polygon/ basegfx/source/polygon/ cppcanvas/source/mtfrenderer/ drawinglayer/ drawinglayer/inc/drawinglayer/primitive2d/...

Added: incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx?rev=1209140&view=auto
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx (added)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstyleattributes.cxx Thu Dec  1 16:25:17 2011
@@ -0,0 +1,1655 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svgio.hxx"
+
+#include <svgio/svgreader/svgstyleattributes.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
+#include <svgio/svgreader/svgnode.hxx>
+#include <svgio/svgreader/svgdocument.hxx>
+#include <drawinglayer/primitive2d/svggradientprimitive2d.hxx>
+#include <svgio/svgreader/svggradientnode.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <basegfx/vector/b2enums.hxx>
+#include <drawinglayer/processor2d/linegeometryextractor2d.hxx>
+#include <drawinglayer/processor2d/textaspolygonextractor2d.hxx>
+#include <basegfx/polygon/b2dpolypolygoncutter.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace svgio
+{
+    namespace svgreader
+    {
+        basegfx::B2DLineJoin StrokeLinejoinToB2DLineJoin(StrokeLinejoin aStrokeLinejoin)
+        {
+            if(StrokeLinejoin_round == aStrokeLinejoin)
+            {
+                return basegfx::B2DLINEJOIN_ROUND;
+            }
+            else if(StrokeLinejoin_bevel == aStrokeLinejoin)
+            {
+                return basegfx::B2DLINEJOIN_BEVEL;
+            }
+
+            return basegfx::B2DLINEJOIN_MITER;
+        }
+
+        FontStretch getWider(FontStretch aSource)
+        {
+            switch(aSource)
+            {
+                case FontStretch_ultra_condensed: aSource = FontStretch_extra_condensed; break;
+                case FontStretch_extra_condensed: aSource = FontStretch_condensed; break;
+                case FontStretch_condensed: aSource = FontStretch_semi_condensed; break;
+                case FontStretch_semi_condensed: aSource = FontStretch_normal; break;
+                case FontStretch_normal: aSource = FontStretch_semi_expanded; break;
+                case FontStretch_semi_expanded: aSource = FontStretch_expanded; break;
+                case FontStretch_expanded: aSource = FontStretch_extra_expanded; break;
+                case FontStretch_extra_expanded: aSource = FontStretch_ultra_expanded; break;
+            }
+
+            return aSource;
+        }
+        
+        FontStretch getNarrower(FontStretch aSource)
+        {
+            switch(aSource)
+            {
+                case FontStretch_extra_condensed: aSource = FontStretch_ultra_condensed; break;
+                case FontStretch_condensed: aSource = FontStretch_extra_condensed; break;
+                case FontStretch_semi_condensed: aSource = FontStretch_condensed; break;
+                case FontStretch_normal: aSource = FontStretch_semi_condensed; break;
+                case FontStretch_semi_expanded: aSource = FontStretch_normal; break;
+                case FontStretch_expanded: aSource = FontStretch_semi_expanded; break;
+                case FontStretch_extra_expanded: aSource = FontStretch_expanded; break;
+                case FontStretch_ultra_expanded: aSource = FontStretch_extra_expanded; break;
+            }
+
+            return aSource;
+        }
+
+        FontWeight getBolder(FontWeight aSource)
+        {
+            switch(aSource)
+            {
+                case FontWeight_100: aSource = FontWeight_200; break;
+                case FontWeight_200: aSource = FontWeight_300; break;
+                case FontWeight_300: aSource = FontWeight_400; break;
+                case FontWeight_400: aSource = FontWeight_500; break;
+                case FontWeight_500: aSource = FontWeight_600; break;
+                case FontWeight_600: aSource = FontWeight_700; break;
+                case FontWeight_700: aSource = FontWeight_800; break;
+                case FontWeight_800: aSource = FontWeight_900; break;
+            }
+
+            return aSource;
+        }
+
+        FontWeight getLighter(FontWeight aSource)
+        {
+            switch(aSource)
+            {
+                case FontWeight_200: aSource = FontWeight_100; break;
+                case FontWeight_300: aSource = FontWeight_200; break;
+                case FontWeight_400: aSource = FontWeight_300; break;
+                case FontWeight_500: aSource = FontWeight_400; break;
+                case FontWeight_600: aSource = FontWeight_500; break;
+                case FontWeight_700: aSource = FontWeight_600; break;
+                case FontWeight_800: aSource = FontWeight_700; break;
+                case FontWeight_900: aSource = FontWeight_800; break;
+            }
+
+            return aSource;
+        }
+
+        ::FontWeight getVclFontWeight(FontWeight aSource)
+        {
+            ::FontWeight nRetval(WEIGHT_NORMAL);
+
+            switch(aSource)
+            {
+                case FontWeight_100: nRetval = WEIGHT_ULTRALIGHT; break;
+                case FontWeight_200: nRetval = WEIGHT_LIGHT; break;
+                case FontWeight_300: nRetval = WEIGHT_SEMILIGHT; break;
+                case FontWeight_400: nRetval = WEIGHT_NORMAL; break;
+                case FontWeight_500: nRetval = WEIGHT_MEDIUM; break;
+                case FontWeight_600: nRetval = WEIGHT_SEMIBOLD; break;
+                case FontWeight_700: nRetval = WEIGHT_BOLD; break;
+                case FontWeight_800: nRetval = WEIGHT_ULTRABOLD; break;
+                case FontWeight_900: nRetval = WEIGHT_BLACK; break;
+            }
+
+            return nRetval;
+        }
+
+        void SvgStyleAttributes::readStyle(const rtl::OUString& rCandidate)
+        {
+            const sal_Int32 nLen(rCandidate.getLength());
+            sal_Int32 nPos(0);
+
+            while(nPos < nLen)
+            {
+                const sal_Int32 nInitPos(nPos);
+                skip_char(rCandidate, sal_Unicode(' '), nPos, nLen);
+                rtl::OUStringBuffer aTokenName;
+                copyString(rCandidate, nPos, aTokenName, nLen);
+                
+                if(aTokenName.getLength())
+                {
+                    skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(':'), nPos, nLen);
+                    rtl::OUStringBuffer aTokenValue;
+                    copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aTokenValue, nLen);
+                    skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen);
+                    const rtl::OUString aOUTokenName(aTokenName.makeStringAndClear());
+                    const rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear());
+                
+                    parseStyleAttribute(aOUTokenName, StrToSVGToken(aOUTokenName), aOUTokenValue);
+                }
+
+                if(nInitPos == nPos)
+                {
+                    OSL_ENSURE(false, "Could not interpret on current position (!)");
+                    nPos++;
+                }
+            }
+        }
+
+        void SvgStyleAttributes::checkForCssStyle(const rtl::OUString& rClassStr) const
+        {
+            if(!mpCssStyleParent && mrOwner.getClass())
+            {
+                const SvgDocument& rDocument = mrOwner.getDocument();
+
+                if(rDocument.hasSvgStyleAttributesById())
+                {
+                    rtl::OUString aId(rtl::OUString::createFromAscii("."));
+                    aId = aId + *mrOwner.getClass();
+                    
+                    const SvgStyleAttributes* pNew = rDocument.findSvgStyleAttributesById(aId);
+
+                    if(!pNew)
+                    {
+                        aId = rClassStr + aId;
+                    
+                        pNew = rDocument.findSvgStyleAttributesById(aId);
+                    }
+
+                    if(pNew)
+                    {
+                        // found css style, set as parent
+                        const_cast< SvgStyleAttributes* >(this)->mpCssStyleParent = pNew;
+                    }
+                }
+            }
+        }
+
+        const SvgStyleAttributes* SvgStyleAttributes::getParentStyle() const 
+        { 
+            if(mpCssStyleParent)
+            {
+                return mpCssStyleParent;
+            }
+
+            if(mrOwner.getParent()) 
+            {
+                return mrOwner.getParent()->getSvgStyleAttributes(); 
+            }
+
+            return 0; 
+        }
+
+        void SvgStyleAttributes::add_text(
+            drawinglayer::primitive2d::Primitive2DVector& rTarget, 
+            drawinglayer::primitive2d::Primitive2DVector& rSource) const
+        {
+            if(!rSource.empty())
+            {
+                // at this point the primitives in rSource are of type TextSimplePortionPrimitive2D
+                // or TextDecoratedPortionPrimitive2D and have the Fill Color (pAttributes->getFill())
+                // set. When another fill is used and also evtl. stroke is set it gets necessary to
+                // dismantle to geometry and add needed primitives
+                const basegfx::BColor* pFill = getFill();
+                const SvgGradientNode* pFillGradient = getSvgGradientNodeFill();
+                const basegfx::BColor* pStroke = getStroke();
+                const SvgGradientNode* pStrokeGradient = getSvgGradientNodeStroke();
+                basegfx::B2DPolyPolygon aMergedArea;
+                
+                // put primitives into Primitive2DSequence to have clear owner definitions
+                const drawinglayer::primitive2d::Primitive2DSequence aSeq(drawinglayer::primitive2d::Primitive2DVectorToPrimitive2DSequence(rSource));
+
+                if(pFillGradient || pStroke || pStrokeGradient)
+                {
+                    // text geometry is needed, create
+                    // use neutral ViewInformation and create LineGeometryExtractor2D
+                    const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
+                    drawinglayer::processor2d::TextAsPolygonExtractor2D aExtractor(aViewInformation2D);
+
+                    // proccess
+                    aExtractor.process(aSeq);
+
+                    // get results
+                    const drawinglayer::processor2d::TextAsPolygonDataNodeVector& rResult = aExtractor.getTarget();
+                    const sal_uInt32 nResultCount(rResult.size());
+                    basegfx::B2DPolyPolygonVector aTextFillVector;
+                    aTextFillVector.reserve(nResultCount);
+
+                    for(sal_uInt32 a(0); a < nResultCount; a++)
+                    {
+                        const drawinglayer::processor2d::TextAsPolygonDataNode& rCandidate = rResult[a];
+
+                        if(rCandidate.getIsFilled())
+                        {
+                            aTextFillVector.push_back(rCandidate.getB2DPolyPolygon());
+                        }
+                    }
+
+                    if(!aTextFillVector.empty())
+                    {
+                        aMergedArea = basegfx::tools::mergeToSinglePolyPolygon(aTextFillVector);
+                    }
+                }
+
+                const bool bStrokeUsed(pStroke || pStrokeGradient);
+
+                // add fill. Use geometry even for simple color fill when stroke
+                // is used, else text rendering and the geometry-based stroke will
+                // normally not really match optically due to divrese system text
+                // renderers
+                if(aMergedArea.count() && (pFillGradient || bStrokeUsed))
+                {
+                    // create text fill content based on geometry
+                    add_fill(aMergedArea, rTarget, aMergedArea.getB2DRange());
+                }
+                else if(pFill)
+                {
+                    // add the already prepared primitives for single color fill
+                    rTarget.push_back(new drawinglayer::primitive2d::GroupPrimitive2D(aSeq));
+                }
+
+                // add stroke
+                if(aMergedArea.count() && bStrokeUsed)
+                {
+                    // create text stroke content
+                    add_stroke(aMergedArea, rTarget, aMergedArea.getB2DRange());
+                }
+            }
+        }
+
+        void SvgStyleAttributes::add_fillGradient(
+            const basegfx::B2DPolyPolygon& rPath, 
+            drawinglayer::primitive2d::Primitive2DVector& rTarget, 
+            const SvgGradientNode& rFillGradient,
+            const basegfx::B2DRange& rGeoRange) const
+        {
+            // create fill content
+            drawinglayer::primitive2d::SvgGradientEntryVector aSvgGradientEntryVector;
+                    
+            // get the color stops
+            rFillGradient.collectGradientEntries(aSvgGradientEntryVector);
+
+            if(!aSvgGradientEntryVector.empty())
+            {
+                basegfx::B2DHomMatrix aGeoToUnit;
+
+                if(rFillGradient.getGradientTransform())
+                {
+                    aGeoToUnit = *rFillGradient.getGradientTransform();
+                }
+
+                if(userSpaceOnUse == rFillGradient.getGradientUnits())
+                {
+                    aGeoToUnit.translate(-rGeoRange.getMinX(), -rGeoRange.getMinY());
+                    aGeoToUnit.scale(1.0 / rGeoRange.getWidth(), 1.0 / rGeoRange.getHeight());
+                }
+
+                if(SVGTokenLinearGradient == rFillGradient.getType())
+                {
+                    basegfx::B2DPoint aStart(0.0, 0.0);
+                    basegfx::B2DPoint aEnd(1.0, 0.0);
+
+                    if(userSpaceOnUse == rFillGradient.getGradientUnits())
+                    {
+                        // all possible units
+                        aStart.setX(rFillGradient.getX1().solve(mrOwner, xcoordinate));
+                        aStart.setY(rFillGradient.getY1().solve(mrOwner, ycoordinate));
+                        aEnd.setX(rFillGradient.getX2().solve(mrOwner, xcoordinate));
+                        aEnd.setY(rFillGradient.getY2().solve(mrOwner, ycoordinate));
+                    }
+                    else
+                    {
+                        // fractions or percent relative to object bounds
+                        const SvgNumber X1(rFillGradient.getX1());
+                        const SvgNumber Y1(rFillGradient.getY1());
+                        const SvgNumber X2(rFillGradient.getX2());
+                        const SvgNumber Y2(rFillGradient.getY2());
+
+                        aStart.setX(Unit_percent == X1.getUnit() ? X1.getNumber() * 0.01 : X1.getNumber());
+                        aStart.setY(Unit_percent == Y1.getUnit() ? Y1.getNumber() * 0.01 : Y1.getNumber());
+                        aEnd.setX(Unit_percent == X2.getUnit() ? X2.getNumber() * 0.01 : X2.getNumber());
+                        aEnd.setY(Unit_percent == Y2.getUnit() ? Y2.getNumber() * 0.01 : Y2.getNumber());
+                    }
+    
+                    if(!aGeoToUnit.isIdentity())
+                    {
+                        aStart *= aGeoToUnit;
+                        aEnd *= aGeoToUnit;
+                    }
+
+                    rTarget.push_back(
+                        new drawinglayer::primitive2d::SvgLinearGradientPrimitive2D(
+                            rPath, 
+                            aSvgGradientEntryVector,
+                            aStart,
+                            aEnd,
+                            rFillGradient.getSpreadMethod()));
+                }
+                else
+                {
+                    basegfx::B2DPoint aStart(0.5, 0.5);
+                    basegfx::B2DPoint aFocal;
+                    double fRadius(0.5);
+                    const SvgNumber* pFx = rFillGradient.getFx();
+                    const SvgNumber* pFy = rFillGradient.getFy();
+                    const bool bFocal(pFx || pFy);
+
+                    if(userSpaceOnUse == rFillGradient.getGradientUnits())
+                    {
+                        // all possible units
+                        aStart.setX(rFillGradient.getCx().solve(mrOwner, xcoordinate));
+                        aStart.setY(rFillGradient.getCy().solve(mrOwner, ycoordinate));
+                        fRadius = rFillGradient.getR().solve(mrOwner, length);
+                        
+                        if(bFocal)
+                        {
+                            aFocal.setX(pFx ? pFx->solve(mrOwner, xcoordinate) : aStart.getX());
+                            aFocal.setY(pFy ? pFy->solve(mrOwner, ycoordinate) : aStart.getY());
+                        }
+                    }
+                    else
+                    {
+                        // fractions or percent relative to object bounds
+                        const SvgNumber Cx(rFillGradient.getCx());
+                        const SvgNumber Cy(rFillGradient.getCy());
+                        const SvgNumber R(rFillGradient.getR());
+
+                        aStart.setX(Unit_percent == Cx.getUnit() ? Cx.getNumber() * 0.01 : Cx.getNumber());
+                        aStart.setY(Unit_percent == Cy.getUnit() ? Cy.getNumber() * 0.01 : Cy.getNumber());
+                        fRadius = (Unit_percent == R.getUnit()) ? R.getNumber() * 0.01 : R.getNumber();
+
+                        if(bFocal)
+                        {
+                            aFocal.setX(pFx ? (Unit_percent == pFx->getUnit() ? pFx->getNumber() * 0.01 : pFx->getNumber()) : aStart.getX());
+                            aFocal.setY(pFy ? (Unit_percent == pFy->getUnit() ? pFy->getNumber() * 0.01 : pFy->getNumber()) : aStart.getY());
+                        }
+                    }
+                            
+                    if(!aGeoToUnit.isIdentity())
+                    {
+                        aStart *= aGeoToUnit;
+                        fRadius = (aGeoToUnit * basegfx::B2DVector(fRadius, 0.0)).getLength();
+
+                        if(bFocal)
+                        {
+                            aFocal *= aGeoToUnit;
+                        }
+                    }
+
+                    rTarget.push_back(
+                        new drawinglayer::primitive2d::SvgRadialGradientPrimitive2D(
+                            rPath, 
+                            aSvgGradientEntryVector,
+                            aStart,
+                            fRadius,
+                            rFillGradient.getSpreadMethod(),
+                            bFocal ? &aFocal : 0));
+                }
+            }
+        }
+
+        void SvgStyleAttributes::add_fill(
+            const basegfx::B2DPolyPolygon& rPath, 
+            drawinglayer::primitive2d::Primitive2DVector& rTarget,
+            const basegfx::B2DRange& rGeoRange) const
+        {
+            const basegfx::BColor* pFill = getFill();
+            const SvgGradientNode* pFillGradient = getSvgGradientNodeFill();
+
+            if(pFill || pFillGradient)
+            {
+                const double fFillOpacity(getFillOpacity().solve(mrOwner, length));
+
+                if(basegfx::fTools::more(fFillOpacity, 0.0))
+                {
+                    drawinglayer::primitive2d::Primitive2DVector aNewFill;
+
+                    if(pFillGradient)
+                    {
+                        // create fill content with SVG gradient primitive
+                        add_fillGradient(rPath, aNewFill, *pFillGradient, rGeoRange);
+                    }
+                    else // if(pFill)
+                    {
+                        // create fill content
+                        aNewFill.push_back(
+                            new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
+                                rPath, 
+                                *pFill));
+                    }
+
+                    if(!aNewFill.empty())
+                    {
+                        if(basegfx::fTools::less(fFillOpacity, 1.0))
+                        {
+                            // embed in UnifiedTransparencePrimitive2D
+                            rTarget.push_back(
+                                new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+                                    Primitive2DVectorToPrimitive2DSequence(aNewFill),
+                                    1.0 - fFillOpacity));
+                        }
+                        else
+                        {
+                            // append
+                            rTarget.insert(rTarget.end(), aNewFill.begin(), aNewFill.end());
+                        }
+                    }
+                }
+            }
+        }
+
+        void SvgStyleAttributes::add_stroke(
+            const basegfx::B2DPolyPolygon& rPath, 
+            drawinglayer::primitive2d::Primitive2DVector& rTarget,
+            const basegfx::B2DRange& rGeoRange) const
+        {
+            const basegfx::BColor* pStroke = getStroke();
+            const SvgGradientNode* pStrokeGradient = getSvgGradientNodeStroke();
+
+            if(pStroke || pStrokeGradient)
+            {
+                drawinglayer::primitive2d::Primitive2DVector aNewStroke;
+                const double fStrokeOpacity(getStrokeOpacity().solve(mrOwner, length));
+
+                if(basegfx::fTools::more(fStrokeOpacity, 0.0))
+                {
+                    // get stroke width; SVG does not use 0.0 == hairline, so 0.0 is no line at all
+                    const double fStrokeWidth(getStrokeWidth().isSet() ? getStrokeWidth().solve(mrOwner, length) : 1.0);
+
+                    if(basegfx::fTools::more(fStrokeWidth, 0.0))
+                    {
+                        // get LineJoin and stroke array
+                        const basegfx::B2DLineJoin aB2DLineJoin(StrokeLinejoinToB2DLineJoin(getStrokeLinejoin()));
+                        ::std::vector< double > aDashArray;
+                    
+                        if(!getStrokeDasharray().empty())
+                        {
+                            aDashArray = solveSvgNumberVector(getStrokeDasharray(), mrOwner, length);
+                        }
+
+                        // todo: Handle getStrokeDashOffset()
+                        // todo: Handle getStrokeLinecap()
+                        
+                        // prepare line attribute
+                        drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D* pNewLinePrimitive = 0;
+                        const drawinglayer::attribute::LineAttribute aLineAttribute(
+                            pStroke ? *pStroke : basegfx::BColor(0.0, 0.0, 0.0),
+                            fStrokeWidth,
+                            aB2DLineJoin);
+
+                        if(aDashArray.empty())
+                        {
+                            pNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
+                                rPath, 
+                                aLineAttribute);
+                        }
+                        else
+                        {
+                            const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashArray);
+
+                            pNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
+                                rPath, 
+                                aLineAttribute,
+                                aDashArray);
+                        }
+
+                        if(pStrokeGradient)
+                        {
+                            // put primitive into Primitive2DReference and Primitive2DSequence
+                            const drawinglayer::primitive2d::Primitive2DReference aRef(pNewLinePrimitive);
+                            const drawinglayer::primitive2d::Primitive2DSequence aSeq(&aRef, 1);
+
+                            // use neutral ViewInformation and create LineGeometryExtractor2D
+                            const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
+                            drawinglayer::processor2d::LineGeometryExtractor2D aExtractor(aViewInformation2D);
+
+                            // proccess
+                            aExtractor.process(aSeq);
+
+                            // check for fill rsults
+                            const basegfx::B2DPolyPolygonVector& rLineFillVector(aExtractor.getExtractedLineFills());
+
+                            if(!aExtractor.getExtractedLineFills().empty())
+                            {
+                                const basegfx::B2DPolyPolygon aMergedArea(
+                                    basegfx::tools::mergeToSinglePolyPolygon(
+                                        aExtractor.getExtractedLineFills()));
+
+                                if(aMergedArea.count())
+                                {
+                                    // create fill content with SVG gradient primitive
+                                    add_fillGradient(aMergedArea, aNewStroke, *pStrokeGradient, rGeoRange);
+                                }
+                            }
+                        }
+                        else // if(pStroke)
+                        {
+                            aNewStroke.push_back(pNewLinePrimitive);
+                        }
+
+                        if(!aNewStroke.empty())
+                        {
+                            if(basegfx::fTools::less(fStrokeOpacity, 1.0))
+                            {
+                                // embed in UnifiedTransparencePrimitive2D
+                                rTarget.push_back(
+                                    new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
+                                        Primitive2DVectorToPrimitive2DSequence(aNewStroke),
+                                        1.0 - fStrokeOpacity));
+                            }
+                            else
+                            {
+                                // append
+                                rTarget.insert(rTarget.end(), aNewStroke.begin(), aNewStroke.end());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        void SvgStyleAttributes::add_path(
+            const basegfx::B2DPolyPolygon& rPath, 
+            drawinglayer::primitive2d::Primitive2DVector& rTarget, 
+            const basegfx::B2DHomMatrix* pTransform) const
+        {
+            const bool bIsLine(1 == rPath.count()
+                && !rPath.areControlPointsUsed()
+                && 2 == rPath.getB2DPolygon(0).count());
+
+            if(!rPath.count())
+            {
+                return;
+            }
+
+            const basegfx::B2DRange aGeoRange(rPath.getB2DRange());
+
+            if(aGeoRange.isEmpty())
+            {
+                return;
+            }
+
+            if(!bIsLine && // not for lines
+                (basegfx::fTools::equalZero(aGeoRange.getWidth()) 
+                || basegfx::fTools::equalZero(aGeoRange.getHeight())))
+            {
+                return;
+            }
+
+            drawinglayer::primitive2d::Primitive2DVector aNewPrimitives;
+
+            if(!bIsLine)
+            {
+                add_fill(rPath, aNewPrimitives, aGeoRange);
+            }
+
+            add_stroke(rPath, aNewPrimitives, aGeoRange);
+
+            if(pTransform && !aNewPrimitives.empty())
+            {
+                // embed in transformation
+                rTarget.push_back(
+                    new drawinglayer::primitive2d::TransformPrimitive2D(
+                        *pTransform,
+                        Primitive2DVectorToPrimitive2DSequence(aNewPrimitives)));
+            }
+            else
+            {
+                // just append
+                rTarget.insert(rTarget.end(), aNewPrimitives.begin(), aNewPrimitives.end());
+            }
+        }
+
+        SvgStyleAttributes::SvgStyleAttributes(SvgNode& rOwner)
+        :   mrOwner(rOwner),
+            mpCssStyleParent(0),
+            maFill(),
+            maStroke(),
+            maStopColor(basegfx::BColor(0.0, 0.0, 0.0), true),
+            maStrokeWidth(),
+            maStopOpacity(),
+            mpSvgGradientNodeFill(0),
+            mpSvgGradientNodeStroke(0),
+            maFillOpacity(),
+            maStrokeDasharray(),
+            maStrokeDashOffset(),
+            maStrokeLinecap(StrokeLinecap_notset),
+            maStrokeLinejoin(StrokeLinejoin_notset),
+            maStrokeMiterLimit(),
+            maStrokeOpacity(),
+            maFontFamily(),
+            maFontSize(),
+            maFontStretch(FontStretch_notset),
+            maFontStyle(FontStyle_notset),
+            maFontVariant(FontVariant_notset),
+            maFontWeight(FontWeight_notset),
+            maTextAlign(TextAlign_notset),
+            maTextDecoration(TextDecoration_notset),
+            maTextAnchor(TextAnchor_notset),
+            
+            maFillRule(true),
+            maFillRuleSet(false)
+        {
+        }
+
+        SvgStyleAttributes::~SvgStyleAttributes()
+        {
+        }
+
+        void SvgStyleAttributes::parseStyleAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
+        {
+            switch(aSVGToken)
+            {
+                case SVGTokenFill:
+                {
+                    SvgPaint aSvgPaint;
+                    rtl::OUString aURL;
+
+                    if(readSvgPaint(aContent, aSvgPaint, aURL))
+                    {
+                        setFill(aSvgPaint);
+                    }
+                    else if(aURL.getLength())
+                    {
+                        const SvgGradientNode* pNode = dynamic_cast< const SvgGradientNode* >(mrOwner.getDocument().findSvgNodeById(aURL));
+
+                        if(pNode)
+                        {
+                            setSvgGradientNodeFill(pNode);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenFillOpacity:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        if(aNum.isPositive())
+                        {
+                            setFillOpacity(aNum);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenFillRule:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrNonzero(rtl::OUString::createFromAscii("nonzero"));
+                        static rtl::OUString aStrEvenOdd(rtl::OUString::createFromAscii("evenodd"));
+
+                        if(aContent.match(aStrNonzero))
+                        {
+                            maFillRule = true;
+                            maFillRuleSet = true;
+                        }
+                        else if(aContent.match(aStrEvenOdd))
+                        {
+                            maFillRule = false;
+                            maFillRuleSet = true;
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStroke:
+                {
+                    SvgPaint aSvgPaint;
+                    rtl::OUString aURL;
+
+                    if(readSvgPaint(aContent, aSvgPaint, aURL))
+                    {
+                        setStroke(aSvgPaint);
+                    }
+                    else if(aURL.getLength())
+                    {
+                        const SvgGradientNode* pNode = dynamic_cast< const SvgGradientNode* >(mrOwner.getDocument().findSvgNodeById(aURL));
+
+                        if(pNode)
+                        {
+                            setSvgGradientNodeStroke(pNode);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStrokeDasharray:
+                {
+                    if(aContent.getLength())
+                    {
+                        SvgNumberVector aVector;
+
+                        if(readSvgNumberVector(aContent, aVector))
+                        {
+                            setStrokeDasharray(aVector);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStrokeDashoffset:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        if(aNum.isPositive())
+                        {
+                            setStrokeDashOffset(aNum);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStrokeLinecap:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrButt(rtl::OUString::createFromAscii("butt"));
+                        static rtl::OUString aStrRound(rtl::OUString::createFromAscii("round"));
+                        static rtl::OUString aStrSquare(rtl::OUString::createFromAscii("square"));
+
+                        if(aContent.match(aStrButt))
+                        {
+                            setStrokeLinecap(StrokeLinecap_butt);
+                        }
+                        else if(aContent.match(aStrRound))
+                        {
+                            setStrokeLinecap(StrokeLinecap_round);
+                        }
+                        else if(aContent.match(aStrSquare))
+                        {
+                            setStrokeLinecap(StrokeLinecap_square);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStrokeLinejoin:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrMiter(rtl::OUString::createFromAscii("miter"));
+                        static rtl::OUString aStrRound(rtl::OUString::createFromAscii("round"));
+                        static rtl::OUString aStrBevel(rtl::OUString::createFromAscii("bevel"));
+
+                        if(aContent.match(aStrMiter))
+                        {
+                            setStrokeLinejoin(StrokeLinejoin_miter);
+                        }
+                        else if(aContent.match(aStrRound))
+                        {
+                            setStrokeLinejoin(StrokeLinejoin_round);
+                        }
+                        else if(aContent.match(aStrBevel))
+                        {
+                            setStrokeLinejoin(StrokeLinejoin_bevel);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStrokeMiterlimit:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        if(aNum.isPositive())
+                        {
+                            setStrokeMiterLimit(aNum);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStrokeOpacity:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        if(aNum.isPositive())
+                        {
+                            setStrokeOpacity(aNum);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStrokeWidth:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        if(aNum.isPositive())
+                        {
+                            setStrokeWidth(aNum);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenStopColor:
+                {
+                    SvgPaint aSvgPaint;
+                    rtl::OUString aURL;
+
+                    if(readSvgPaint(aContent, aSvgPaint, aURL))
+                    {
+                        setStopColor(aSvgPaint);
+                    }
+                    break;
+                }
+                case SVGTokenStopOpacity:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        if(aNum.isPositive())
+                        {
+                            setStopOpacity(aNum);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenFont:
+                {
+                    bool bBla = true;
+                    break;
+                }
+                case SVGTokenFontFamily:
+                {
+                    SvgStringVector aSvgStringVector;
+
+                    if(readSvgStringVector(aContent, aSvgStringVector))
+                    {
+                        setFontFamily(aSvgStringVector);
+                    }
+                    break;
+                }
+                case SVGTokenFontSize:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        setFontSize(aNum);
+                    }
+                    break;
+                }
+                case SVGTokenFontSizeAdjust:
+                {
+                    bool bBla = true;
+                    break;
+                }
+                case SVGTokenFontStretch:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal"));
+                        static rtl::OUString aStrWider(rtl::OUString::createFromAscii("wider"));
+                        static rtl::OUString aStrNarrower(rtl::OUString::createFromAscii("narrower"));
+                        static rtl::OUString aStrUltra_condensed(rtl::OUString::createFromAscii("ultra-condensed"));
+                        static rtl::OUString aStrExtra_condensed(rtl::OUString::createFromAscii("extra-condensed"));
+                        static rtl::OUString aStrCondensed(rtl::OUString::createFromAscii("condensed"));
+                        static rtl::OUString aStrSemi_condensed(rtl::OUString::createFromAscii("semi-condensed"));
+                        static rtl::OUString aStrSemi_expanded(rtl::OUString::createFromAscii("semi-expanded"));
+                        static rtl::OUString aStrExpanded(rtl::OUString::createFromAscii("expanded"));
+                        static rtl::OUString aStrExtra_expanded(rtl::OUString::createFromAscii("extra-expanded"));
+                        static rtl::OUString aStrUltra_expanded(rtl::OUString::createFromAscii("ultra-expanded"));
+
+                        if(aContent.match(aStrNormal))
+                        {
+                            setFontStretch(FontStretch_normal);
+                        }
+                        else if(aContent.match(aStrWider))
+                        {
+                            setFontStretch(FontStretch_wider);
+                        }
+                        else if(aContent.match(aStrNarrower))
+                        {
+                            setFontStretch(FontStretch_narrower);
+                        }
+                        else if(aContent.match(aStrUltra_condensed))
+                        {
+                            setFontStretch(FontStretch_ultra_condensed);
+                        }
+                        else if(aContent.match(aStrExtra_condensed))
+                        {
+                            setFontStretch(FontStretch_extra_condensed);
+                        }
+                        else if(aContent.match(aStrCondensed))
+                        {
+                            setFontStretch(FontStretch_condensed);
+                        }
+                        else if(aContent.match(aStrSemi_condensed))
+                        {
+                            setFontStretch(FontStretch_semi_condensed);
+                        }
+                        else if(aContent.match(aStrSemi_expanded))
+                        {
+                            setFontStretch(FontStretch_semi_expanded);
+                        }
+                        else if(aContent.match(aStrExpanded))
+                        {
+                            setFontStretch(FontStretch_expanded);
+                        }
+                        else if(aContent.match(aStrExtra_expanded))
+                        {
+                            setFontStretch(FontStretch_extra_expanded);
+                        }
+                        else if(aContent.match(aStrUltra_expanded))
+                        {
+                            setFontStretch(FontStretch_ultra_expanded);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenFontStyle:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal"));
+                        static rtl::OUString aStrItalic(rtl::OUString::createFromAscii("italic"));
+                        static rtl::OUString aStrOblique(rtl::OUString::createFromAscii("oblique"));
+
+                        if(aContent.match(aStrNormal))
+                        {
+                            setFontStyle(FontStyle_normal);
+                        }
+                        else if(aContent.match(aStrItalic))
+                        {
+                            setFontStyle(FontStyle_italic);
+                        }
+                        else if(aContent.match(aStrOblique))
+                        {
+                            setFontStyle(FontStyle_oblique);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenFontVariant:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal"));
+                        static rtl::OUString aStrSmallCaps(rtl::OUString::createFromAscii("small-caps"));
+
+                        if(aContent.match(aStrNormal))
+                        {
+                            setFontVariant(FontVariant_normal);
+                        }
+                        else if(aContent.match(aStrSmallCaps))
+                        {
+                            setFontVariant(FontVariant_small_caps);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenFontWeight:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal"));
+                        static rtl::OUString aStrBold(rtl::OUString::createFromAscii("bold"));
+                        static rtl::OUString aStrBolder(rtl::OUString::createFromAscii("bolder"));
+                        static rtl::OUString aStrLighter(rtl::OUString::createFromAscii("lighter"));
+                        static rtl::OUString aStr100(rtl::OUString::createFromAscii("100"));
+                        static rtl::OUString aStr200(rtl::OUString::createFromAscii("200"));
+                        static rtl::OUString aStr300(rtl::OUString::createFromAscii("300"));
+                        static rtl::OUString aStr400(rtl::OUString::createFromAscii("400"));
+                        static rtl::OUString aStr500(rtl::OUString::createFromAscii("500"));
+                        static rtl::OUString aStr600(rtl::OUString::createFromAscii("600"));
+                        static rtl::OUString aStr700(rtl::OUString::createFromAscii("700"));
+                        static rtl::OUString aStr800(rtl::OUString::createFromAscii("800"));
+                        static rtl::OUString aStr900(rtl::OUString::createFromAscii("900"));
+
+                        if(aContent.match(aStr100))
+                        {
+                            setFontWeight(FontWeight_100);
+                        }
+                        else if(aContent.match(aStr200))
+                        {
+                            setFontWeight(FontWeight_200);
+                        }
+                        else if(aContent.match(aStr300))
+                        {
+                            setFontWeight(FontWeight_300);
+                        }
+                        else if(aContent.match(aStr400) || aContent.match(aStrNormal))
+                        {
+                            setFontWeight(FontWeight_400);
+                        }
+                        else if(aContent.match(aStr500))
+                        {
+                            setFontWeight(FontWeight_500);
+                        }
+                        else if(aContent.match(aStr600))
+                        {
+                            setFontWeight(FontWeight_600);
+                        }
+                        else if(aContent.match(aStr700) || aContent.match(aStrBold))
+                        {
+                            setFontWeight(FontWeight_700);
+                        }
+                        else if(aContent.match(aStr800))
+                        {
+                            setFontWeight(FontWeight_800);
+                        }
+                        else if(aContent.match(aStr900))
+                        {
+                            setFontWeight(FontWeight_900);
+                        }
+                        else if(aContent.match(aStrBolder))
+                        {
+                            setFontWeight(FontWeight_bolder);
+                        }
+                        else if(aContent.match(aStrLighter))
+                        {
+                            setFontWeight(FontWeight_lighter);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenDirection:
+                {
+                    bool bBla = true;
+                    break;
+                }
+                case SVGTokenLetterSpacing:
+                {
+                    bool bBla = true;
+                    break;
+                }
+                case SVGTokenTextDecoration:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none"));
+                        static rtl::OUString aStrUnderline(rtl::OUString::createFromAscii("underline"));
+                        static rtl::OUString aStrOverline(rtl::OUString::createFromAscii("overline"));
+                        static rtl::OUString aStrLineThrough(rtl::OUString::createFromAscii("line-through"));
+                        static rtl::OUString aStrBlink(rtl::OUString::createFromAscii("blink"));
+
+                        if(aContent.match(aStrNone))
+                        {
+                            setTextDecoration(TextDecoration_none);
+                        }
+                        else if(aContent.match(aStrUnderline))
+                        {
+                            setTextDecoration(TextDecoration_underline);
+                        }
+                        else if(aContent.match(aStrOverline))
+                        {
+                            setTextDecoration(TextDecoration_overline);
+                        }
+                        else if(aContent.match(aStrLineThrough))
+                        {
+                            setTextDecoration(TextDecoration_line_through);
+                        }
+                        else if(aContent.match(aStrBlink))
+                        {
+                            setTextDecoration(TextDecoration_blink);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenUnicodeBidi:
+                {
+                    bool bBla = true;
+                    break;
+                }
+                case SVGTokenWordSpacing:
+                {
+                    bool bBla = true;
+                    break;
+                }
+                case SVGTokenTextAnchor:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrStart(rtl::OUString::createFromAscii("start"));
+                        static rtl::OUString aStrMiddle(rtl::OUString::createFromAscii("middle"));
+                        static rtl::OUString aStrEnd(rtl::OUString::createFromAscii("end"));
+
+                        if(aContent.match(aStrStart))
+                        {
+                            setTextAnchor(TextAnchor_start);
+                        }
+                        else if(aContent.match(aStrMiddle))
+                        {
+                            setTextAnchor(TextAnchor_middle);
+                        }
+                        else if(aContent.match(aStrEnd))
+                        {
+                            setTextAnchor(TextAnchor_end);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenTextAlign:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrLeft(rtl::OUString::createFromAscii("left"));
+                        static rtl::OUString aStrRight(rtl::OUString::createFromAscii("right"));
+                        static rtl::OUString aStrCenter(rtl::OUString::createFromAscii("center"));
+                        static rtl::OUString aStrJustify(rtl::OUString::createFromAscii("justify"));
+
+                        if(aContent.match(aStrLeft))
+                        {
+                            setTextAlign(TextAlign_left);
+                        }
+                        else if(aContent.match(aStrRight))
+                        {
+                            setTextAlign(TextAlign_right);
+                        }
+                        else if(aContent.match(aStrCenter))
+                        {
+                            setTextAlign(TextAlign_center);
+                        }
+                        else if(aContent.match(aStrJustify))
+                        {
+                            setTextAlign(TextAlign_justify);
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+
+        const basegfx::BColor* SvgStyleAttributes::getFill() const 
+        { 
+            if(maFill.isSet()) 
+            {
+                if(maFill.isOn()) 
+                {
+                    return &maFill.getBColor();
+                }
+            }
+            else
+            {
+                const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+                if(pSvgStyleAttributes)
+                {
+                    return pSvgStyleAttributes->getFill();
+                }
+            }
+
+            return 0;
+        }
+
+        const basegfx::BColor* SvgStyleAttributes::getStroke() const 
+        { 
+            if(maStroke.isSet()) 
+            {
+                if(maStroke.isOn()) 
+                {
+                    return &maStroke.getBColor();
+                }
+            }
+            else
+            {
+                const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+                if(pSvgStyleAttributes)
+                {
+                    return pSvgStyleAttributes->getStroke();
+                }
+            }
+
+            return 0;
+        }
+
+        const SvgGradientNode* SvgStyleAttributes::getSvgGradientNodeFill() const 
+        { 
+            if(mpSvgGradientNodeFill)
+            {
+                return mpSvgGradientNodeFill; 
+            }
+            else
+            {
+                const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+                if(pSvgStyleAttributes)
+                {
+                    return pSvgStyleAttributes->getSvgGradientNodeFill();
+                }
+            }
+
+            return 0;
+        }
+
+        const SvgGradientNode* SvgStyleAttributes::getSvgGradientNodeStroke() const 
+        { 
+            if(mpSvgGradientNodeStroke)
+            {
+                return mpSvgGradientNodeStroke; 
+            }
+            else
+            {
+                const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+                if(pSvgStyleAttributes)
+                {
+                    return pSvgStyleAttributes->getSvgGradientNodeStroke();
+                }
+            }
+
+            return 0;
+        }
+
+        const SvgNumber SvgStyleAttributes::getStrokeWidth() const 
+        { 
+            if(maStrokeWidth.isSet()) 
+            {
+                return maStrokeWidth; 
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getStrokeWidth(); 
+            }
+
+            // default is 1
+            return SvgNumber(1.0); 
+        }
+
+        const SvgNumber SvgStyleAttributes::getStopOpacity() const 
+        { 
+            if(maStopOpacity.isSet()) 
+            {
+                return maStopOpacity; 
+            }
+            
+            // default is 1
+            return SvgNumber(1.0); 
+        }
+
+        const SvgNumber SvgStyleAttributes::getFillOpacity() const 
+        { 
+            if(maFillOpacity.isSet()) 
+            {
+                return maFillOpacity; 
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getFillOpacity(); 
+            }
+
+            // default is 1
+            return SvgNumber(1.0); 
+        }
+
+        bool SvgStyleAttributes::getFillRule() const
+        {
+            if(maFillRuleSet)
+            {
+                return maFillRule;
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getFillRule(); 
+            }
+
+            // default is NonZero
+            return true; 
+        }
+
+        void SvgStyleAttributes::setFillRule(const bool* pFillRule)
+        {
+            if(pFillRule)
+            {
+                maFillRuleSet = true;
+                maFillRule = *pFillRule;
+            }
+            else
+            {
+                maFillRuleSet = false;
+            }
+        }
+
+        const SvgNumberVector& SvgStyleAttributes::getStrokeDasharray() const
+        {
+            if(!maStrokeDasharray.empty())
+            {
+                return maStrokeDasharray;
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getStrokeDasharray(); 
+            }
+
+            // default empty
+            return maStrokeDasharray; 
+        }
+
+        const SvgNumber SvgStyleAttributes::getStrokeDashOffset() const 
+        { 
+            if(maStrokeDashOffset.isSet()) 
+            {
+                return maStrokeDashOffset; 
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getStrokeDashOffset(); 
+            }
+
+            // default is 0
+            return SvgNumber(0.0); 
+        }
+
+        const StrokeLinecap SvgStyleAttributes::getStrokeLinecap() const
+        {
+            if(maStrokeLinecap != StrokeLinecap_notset)
+            {
+                return maStrokeLinecap;
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getStrokeLinecap(); 
+            }
+
+            // default is StrokeLinecap_butt
+            return StrokeLinecap_butt; 
+        }
+
+        const StrokeLinejoin SvgStyleAttributes::getStrokeLinejoin() const
+        {
+            if(maStrokeLinejoin != StrokeLinejoin_notset)
+            {
+                return maStrokeLinejoin;
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getStrokeLinejoin(); 
+            }
+
+            // default is StrokeLinejoin_butt
+            return StrokeLinejoin_miter; 
+        }
+
+        const SvgNumber SvgStyleAttributes::getStrokeMiterLimit() const 
+        { 
+            if(maStrokeMiterLimit.isSet()) 
+            {
+                return maStrokeMiterLimit; 
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getStrokeMiterLimit(); 
+            }
+
+            // default is 4
+            return SvgNumber(4.0); 
+        }
+
+        const SvgNumber SvgStyleAttributes::getStrokeOpacity() const 
+        { 
+            if(maStrokeOpacity.isSet()) 
+            {
+                return maStrokeOpacity; 
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getStrokeOpacity(); 
+            }
+
+            // default is 1
+            return SvgNumber(1.0); 
+        }
+
+        const SvgStringVector& SvgStyleAttributes::getFontFamily() const 
+        { 
+            if(!maFontFamily.empty()) 
+            {
+                return maFontFamily; 
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getFontFamily(); 
+            }
+
+            // default is empty
+            return maFontFamily; 
+        }
+
+        const SvgNumber SvgStyleAttributes::getFontSize() const 
+        { 
+            if(maFontSize.isSet()) 
+            {
+                return maFontSize; 
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getFontSize(); 
+            }
+
+            // default is 'medium'
+            return SvgNumber(12.0); 
+        }
+
+        const FontStretch SvgStyleAttributes::getFontStretch() const
+        {
+            if(maFontStretch != FontStretch_notset)
+            {
+                if(FontStretch_wider != maFontStretch && FontStretch_narrower != maFontStretch)
+                {
+                    return maFontStretch;
+                }
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                FontStretch aInherited = pSvgStyleAttributes->getFontStretch();
+
+                if(FontStretch_wider == maFontStretch)
+                {
+                    aInherited = getWider(aInherited);
+                }
+                else if(FontStretch_narrower == maFontStretch)
+                {
+                    aInherited = getNarrower(aInherited);
+                }
+
+                return aInherited;
+            }
+
+            // default is FontStretch_normal
+            return FontStretch_normal; 
+        }
+
+        const FontStyle SvgStyleAttributes::getFontStyle() const
+        {
+            if(maFontStyle != FontStyle_notset)
+            {
+                return maFontStyle;
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getFontStyle(); 
+            }
+
+            // default is FontStyle_normal
+            return FontStyle_normal; 
+        }
+
+        const FontWeight SvgStyleAttributes::getFontWeight() const
+        {
+            if(maFontWeight != FontWeight_notset)
+            {
+                if(FontWeight_bolder != maFontWeight && FontWeight_lighter != maFontWeight)
+                {
+                    return maFontWeight;
+                }
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                FontWeight aInherited = pSvgStyleAttributes->getFontWeight();
+
+                if(FontWeight_bolder == maFontWeight)
+                {
+                    aInherited = getBolder(aInherited);
+                }
+                else if(FontWeight_lighter == maFontWeight)
+                {
+                    aInherited = getLighter(aInherited);
+                }
+
+                return aInherited;
+            }
+
+            // default is FontWeight_400 (FontWeight_normal)
+            return FontWeight_400; 
+        }
+
+        const TextAlign SvgStyleAttributes::getTextAlign() const
+        {
+            if(maTextAlign != TextAlign_notset)
+            {
+                return maTextAlign;
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getTextAlign(); 
+            }
+
+            // default is TextAlign_left
+            return TextAlign_left; 
+        }
+
+        const SvgStyleAttributes* SvgStyleAttributes::getTextDecorationDefiningSvgStyleAttributes() const
+        {
+            if(maTextDecoration != TextDecoration_notset)
+            {
+                return this;
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getTextDecorationDefiningSvgStyleAttributes(); 
+            }
+
+            // default is 0
+            return 0; 
+        }
+
+        const TextDecoration SvgStyleAttributes::getTextDecoration() const
+        {
+            const SvgStyleAttributes* pDefining = getTextDecorationDefiningSvgStyleAttributes();
+
+            if(pDefining)
+            {
+                return pDefining->maTextDecoration;
+            }
+            else
+            {
+                // default is TextDecoration_none
+                return TextDecoration_none; 
+            }
+        }
+
+        const TextAnchor SvgStyleAttributes::getTextAnchor() const
+        {
+            if(maTextAnchor != TextAnchor_notset)
+            {
+                return maTextAnchor;
+            }
+            
+            const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
+
+            if(pSvgStyleAttributes)
+            {
+                return pSvgStyleAttributes->getTextAnchor(); 
+            }
+
+            // default is TextAnchor_start
+            return TextAnchor_start; 
+        }
+
+    } // end of namespace svgreader
+} // end of namespace svgio
+
+//////////////////////////////////////////////////////////////////////////////
+// eof

Added: incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstylenode.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstylenode.cxx?rev=1209140&view=auto
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstylenode.cxx (added)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgstylenode.cxx Thu Dec  1 16:25:17 2011
@@ -0,0 +1,114 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svgio.hxx"
+
+#include <svgio/svgreader/svgstylenode.hxx>
+#include <svgio/svgreader/svgdocument.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace svgio
+{
+    namespace svgreader
+    {
+        SvgStyleNode::SvgStyleNode(
+            SvgDocument& rDocument,
+            SvgNode* pParent)
+        :   SvgNode(SVGTokenStyle, rDocument, pParent),
+            maSvgStyleAttributes(),
+            mbTextCss(false)
+        {
+        }
+
+        SvgStyleNode::~SvgStyleNode()
+        {
+            while(!maSvgStyleAttributes.empty())
+            {
+                delete *(maSvgStyleAttributes.end() - 1);
+                maSvgStyleAttributes.pop_back();
+            }
+        }
+
+        void SvgStyleNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
+        {
+            // call parent
+            SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
+
+            // parse own
+            switch(aSVGToken)
+            {
+                case SVGTokenType:
+                {
+                    if(aContent.getLength())
+                    {
+                        static rtl::OUString aStrTextCss(rtl::OUString::createFromAscii("text/css"));
+
+                        if(aContent.match(aStrTextCss))
+                        {
+                            setTextCss(true);
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+
+        void SvgStyleNode::addCssStyleSheet(const rtl::OUString& aContent)
+        {
+            const sal_Int32 nLen(aContent.getLength());
+
+            if(nLen)
+            {
+                sal_Int32 nPos(0);
+                rtl::OUStringBuffer aTokenValue;
+
+                copyToLimiter(aContent, sal_Unicode('{'), nPos, aTokenValue, nLen);
+                const rtl::OUString aStyleName = aTokenValue.makeStringAndClear().trim();
+
+                if(aStyleName.getLength())
+                {
+                    skip_char(aContent, sal_Unicode(' '), sal_Unicode('{'), nPos, nLen);
+                    copyToLimiter(aContent, sal_Unicode('}'), nPos, aTokenValue, nLen);
+                    const rtl::OUString aStyleContent = aTokenValue.makeStringAndClear().trim();
+
+                    if(aStyleContent.getLength())
+                    {
+                        // create new style
+                        SvgStyleAttributes* pNewStyle = new SvgStyleAttributes(*this);
+                        maSvgStyleAttributes.push_back(pNewStyle);
+
+                        // fill with content
+                        pNewStyle->readStyle(aStyleContent);
+
+                        // register new style at document
+                        const_cast< SvgDocument& >(getDocument()).addSvgStyleAttributesToMapper(aStyleName, *pNewStyle);
+                    }
+                }
+            }
+        }
+
+    } // end of namespace svgreader
+} // end of namespace svgio
+
+//////////////////////////////////////////////////////////////////////////////
+// eof

Added: incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgsvgnode.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgsvgnode.cxx?rev=1209140&view=auto
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgsvgnode.cxx (added)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgsvgnode.cxx Thu Dec  1 16:25:17 2011
@@ -0,0 +1,295 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svgio.hxx"
+
+#include <svgio/svgreader/svgsvgnode.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace svgio
+{
+    namespace svgreader
+    {
+        SvgSvgNode::SvgSvgNode(
+            SvgDocument& rDocument,
+            SvgNode* pParent)
+        :   SvgNode(SVGTokenSvg, rDocument, pParent),
+            maSvgStyleAttributes(*this),
+            mpViewBox(0),
+            maSvgAspectRatio(),
+            maX(),
+            maY(),
+            maWidth(),
+            maHeight(),
+            maVersion()
+        {
+            if(!getParent())
+            {
+                // initial fill is black
+                maSvgStyleAttributes.setFill(SvgPaint(basegfx::BColor(0.0, 0.0, 0.0), true, true));
+            }
+        }
+
+        SvgSvgNode::~SvgSvgNode()
+        {
+            if(mpViewBox) delete mpViewBox;
+        }
+
+        const SvgStyleAttributes* SvgSvgNode::getSvgStyleAttributes() const
+        {
+            return &maSvgStyleAttributes;
+        }
+
+        void SvgSvgNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
+        {
+            // call parent
+            SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
+
+            // read style attributes
+            maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
+
+            // parse own
+            switch(aSVGToken)
+            {
+                case SVGTokenStyle:
+                {
+                    maSvgStyleAttributes.readStyle(aContent);
+                    break;
+                }
+                case SVGTokenViewBox:
+                {
+                    const basegfx::B2DRange aRange(readViewBox(aContent, *this));
+
+                    if(!aRange.isEmpty())
+                    {
+                        setViewBox(&aRange);
+                    }
+                    break;
+                }
+                case SVGTokenPreserveAspectRatio:
+                {
+                    setSvgAspectRatio(readSvgAspectRatio(aContent));
+                    break;
+                }
+                case SVGTokenX:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        setX(aNum);
+                    }
+                    break;
+                }
+                case SVGTokenY:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        setY(aNum);
+                    }
+                    break;
+                }
+                case SVGTokenWidth:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        if(aNum.isPositive())
+                        {
+                            setWidth(aNum);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenHeight:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        if(aNum.isPositive())
+                        {
+                            setHeight(aNum);
+                        }
+                    }
+                    break;
+                }
+                case SVGTokenVersion:
+                {
+                    SvgNumber aNum;
+
+                    if(readSingleNumber(aContent, aNum))
+                    {
+                        setVersion(aNum);
+                    }
+                    break;
+                }
+            }
+        }
+
+        void SvgSvgNode::decomposeSvgNode(drawinglayer::primitive2d::Primitive2DVector& rTarget, bool bReferenced) const
+        {
+            drawinglayer::primitive2d::Primitive2DVector aNewTarget;
+
+            // decompose childs
+            SvgNode::decomposeSvgNode(aNewTarget, bReferenced);
+
+            if(!aNewTarget.empty())
+            {
+                // pack into Primitive2DSequence to ensure ownership
+                const drawinglayer::primitive2d::Primitive2DSequence aSequence(Primitive2DVectorToPrimitive2DSequence(aNewTarget));
+
+                if(getParent())
+                {
+                    if(getViewBox())
+                    {
+                        // Svg defines that with no width or no height the viewBox content is empty,
+                        // so both need to exist
+                        if(!basegfx::fTools::equalZero(getViewBox()->getWidth()) && !basegfx::fTools::equalZero(getViewBox()->getHeight()))
+                        {
+                            // create target range homing x,y, width and height as given
+                            const double fX(getX().isSet() ? getX().solve(*this, xcoordinate) : 0.0);
+                            const double fY(getY().isSet() ? getY().solve(*this, ycoordinate) : 0.0);
+                            const double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : getViewBox()->getWidth());
+                            const double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : getViewBox()->getHeight());
+                            const basegfx::B2DRange aTarget(fX, fY, fX + fW, fY + fH);
+
+                            if(aTarget.equal(*getViewBox()))
+                            {
+                                // no mapping needed, append
+                                rTarget.push_back(
+                                    new drawinglayer::primitive2d::GroupPrimitive2D(
+                                        aSequence));
+                            }
+                            else
+                            {
+                                // create mapping
+                                const SvgAspectRatio& rRatio = getSvgAspectRatio();
+
+                                if(rRatio.isSet())
+                                {
+                                    // let mapping be created from SvgAspectRatio
+                                    const basegfx::B2DHomMatrix aEmbeddingTransform(
+                                        rRatio.createMapping(aTarget, *getViewBox()));
+
+                                    // prepare embedding in transformation
+                                    drawinglayer::primitive2d::TransformPrimitive2D* pNew = 
+                                        new drawinglayer::primitive2d::TransformPrimitive2D(
+                                            aEmbeddingTransform,
+                                            aSequence);
+
+                                    if(rRatio.isMeetOrSlice())
+                                    {
+                                        // embed in transformation
+                                        rTarget.push_back(pNew);
+                                    }
+                                    else
+                                    {
+                                        // need to embed in MaskPrimitive2D, too
+                                        const drawinglayer::primitive2d::Primitive2DReference xRef(pNew);
+
+                                        rTarget.push_back(
+                                            new drawinglayer::primitive2d::MaskPrimitive2D(
+                                                basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aTarget)),
+                                                drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1)));
+                                    }
+                                }
+                                else
+                                {
+                                    // choose default mapping
+                                    const basegfx::B2DHomMatrix aEmbeddingTransform(
+                                        rRatio.createLinearMapping(
+                                            aTarget, *getViewBox()));
+                                    
+                                    // embed in transformation
+                                    rTarget.push_back(
+                                        new drawinglayer::primitive2d::TransformPrimitive2D(
+                                            aEmbeddingTransform,
+                                            aSequence));
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        // no viewBox, append
+                        rTarget.push_back(
+                            new drawinglayer::primitive2d::GroupPrimitive2D(
+                                aSequence));
+                    }
+                }
+                else
+                {
+                    // Outermost SVG element; create target range homing width and height as given.
+                    // SVG defines that x,y has no meanig for the outermost SVG element. Use a fallback
+                    // width and height of 8x8 cm (8 * 35.43307px)
+                    const double fFallbackMetric(8.0 * 35.43307);
+                    double fW(getWidth().isSet() ? getWidth().solve(*this, xcoordinate) : fFallbackMetric);
+                    double fH(getHeight().isSet() ? getHeight().solve(*this, ycoordinate) : fFallbackMetric);
+
+                    // Svg defines that a negative value is an error and that 0.0 disables rendering
+                    if(basegfx::fTools::more(fW, 0.0) && basegfx::fTools::more(fH, 0.0))
+                    {
+                        // append embedded in transform primitive to scale to 1/100th mm
+                        // where 1 mm == 3.543307 px
+                        const double fScaleTo100thmm(100.0 / 3.543307);
+                        basegfx::B2DHomMatrix aTransform(
+                            basegfx::tools::createScaleB2DHomMatrix(
+                                fScaleTo100thmm,
+                                fScaleTo100thmm));
+
+                        rTarget.push_back(
+                            new drawinglayer::primitive2d::TransformPrimitive2D(
+                                aTransform,
+                                aSequence));
+                    }
+                }
+            }
+        }
+
+        const basegfx::B2DRange* SvgSvgNode::getCurrentViewPort() const
+        {
+            if(getViewBox())
+            {
+                return getViewBox();
+            }
+            else
+            {
+                return SvgNode::getCurrentViewPort();
+            }
+        }
+
+    } // end of namespace svgreader
+} // end of namespace svgio
+
+//////////////////////////////////////////////////////////////////////////////
+// eof

Added: incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgsymbolnode.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgsymbolnode.cxx?rev=1209140&view=auto
==============================================================================
--- incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgsymbolnode.cxx (added)
+++ incubator/ooo/branches/alg/svgreplacement/main/svgio/source/svgreader/svgsymbolnode.cxx Thu Dec  1 16:25:17 2011
@@ -0,0 +1,93 @@
+/**************************************************************
+ * 
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * 
+ *************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svgio.hxx"
+
+#include <svgio/svgreader/svgsymbolnode.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace svgio
+{
+    namespace svgreader
+    {
+        SvgSymbolNode::SvgSymbolNode(
+            SvgDocument& rDocument,
+            SvgNode* pParent)
+        :   SvgNode(SVGTokenSvg, rDocument, pParent),
+            maSvgStyleAttributes(*this),
+            mpViewBox(0),
+            maSvgAspectRatio()
+        {
+        }
+
+        SvgSymbolNode::~SvgSymbolNode()
+        {
+            if(mpViewBox) delete mpViewBox;
+        }
+
+        const SvgStyleAttributes* SvgSymbolNode::getSvgStyleAttributes() const
+        {
+            return &maSvgStyleAttributes;
+        }
+
+        void SvgSymbolNode::parseAttribute(const rtl::OUString& rTokenName, SVGToken aSVGToken, const rtl::OUString& aContent)
+        {
+            // call parent
+            SvgNode::parseAttribute(rTokenName, aSVGToken, aContent);
+
+            // read style attributes
+            maSvgStyleAttributes.parseStyleAttribute(rTokenName, aSVGToken, aContent);
+
+            // parse own
+            switch(aSVGToken)
+            {
+                case SVGTokenStyle:
+                {
+                    maSvgStyleAttributes.readStyle(aContent);
+                    break;
+                }
+                case SVGTokenViewBox:
+                {
+                    const basegfx::B2DRange aRange(readViewBox(aContent, *this));
+
+                    if(!aRange.isEmpty())
+                    {
+                        setViewBox(&aRange);
+                    }
+                    break;
+                }
+                case SVGTokenPreserveAspectRatio:
+                {
+                    setSvgAspectRatio(readSvgAspectRatio(aContent));
+                    break;
+                }
+            }
+        }
+
+    } // end of namespace svgreader
+} // end of namespace svgio
+
+//////////////////////////////////////////////////////////////////////////////
+// eof