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