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