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