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