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