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