xref: /trunk/main/svgio/source/svgreader/svgstyleattributes.cxx (revision cf6516809c57e1bb0a940545cca99cdad54d4ce2)
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     {
StrokeLinejoinToB2DLineJoin(StrokeLinejoin aStrokeLinejoin)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 
StrokeLinecapToDrawingLineCap(StrokeLinecap aStrokeLinecap)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 
getWider(FontStretch aSource)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 
getNarrower(FontStretch aSource)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 
getBolder(FontWeight aSource)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 
getLighter(FontWeight aSource)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 
getVclFontWeight(FontWeight aSource)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 
readCssStyle(const rtl::OUString & rCandidate)183*52cb04b8SArmin Le Grand         void SvgStyleAttributes::readCssStyle(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             {
190*52cb04b8SArmin Le Grand                 // get TokenName
191ddde725dSArmin Le Grand                 rtl::OUStringBuffer aTokenName;
192*52cb04b8SArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen);
193ddde725dSArmin Le Grand                 copyString(rCandidate, nPos, aTokenName, nLen);
194ddde725dSArmin Le Grand 
195*52cb04b8SArmin Le Grand                 if(!aTokenName.getLength())
196ddde725dSArmin Le Grand                 {
197*52cb04b8SArmin Le Grand                     // if no TokenName advance one by force to avoid death loop, continue
198*52cb04b8SArmin Le Grand                     OSL_ENSURE(false, "Could not interpret on current position, advancing one byte (!)");
199*52cb04b8SArmin Le Grand                     nPos++;
200*52cb04b8SArmin Le Grand                     continue;
201*52cb04b8SArmin Le Grand                 }
202*52cb04b8SArmin Le Grand 
203*52cb04b8SArmin Le Grand                 // get TokenValue
204ddde725dSArmin Le Grand                 rtl::OUStringBuffer aTokenValue;
205*52cb04b8SArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(':'), nPos, nLen);
206ddde725dSArmin Le Grand                 copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aTokenValue, nLen);
207ddde725dSArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen);
208*52cb04b8SArmin Le Grand 
209*52cb04b8SArmin Le Grand                 if(!aTokenValue.getLength())
210*52cb04b8SArmin Le Grand                 {
211*52cb04b8SArmin Le Grand                     // no value - continue
212*52cb04b8SArmin Le Grand                     continue;
213*52cb04b8SArmin Le Grand                 }
214*52cb04b8SArmin Le Grand 
215*52cb04b8SArmin Le Grand                 // generate OUStrings
216ddde725dSArmin Le Grand                 const rtl::OUString aOUTokenName(aTokenName.makeStringAndClear());
2179d01bcdeSArmin Le Grand                 rtl::OUString aOUTokenValue(aTokenValue.makeStringAndClear());
2189d01bcdeSArmin Le Grand 
2199d01bcdeSArmin Le Grand                 // check for '!important' CssStyle mark, currently not supported
220*52cb04b8SArmin Le Grand                 // but needs to be extracted for correct parsing
2219d01bcdeSArmin Le Grand                 static rtl::OUString aTokenImportant(RTL_CONSTASCII_USTRINGPARAM("!important"));
2229d01bcdeSArmin Le Grand                 const sal_Int32 nIndexTokenImportant(aOUTokenValue.indexOf(aTokenImportant));
2239d01bcdeSArmin Le Grand 
2249d01bcdeSArmin Le Grand                 if(-1 != nIndexTokenImportant)
2259d01bcdeSArmin Le Grand                 {
2269d01bcdeSArmin Le Grand                     // if there currently just remove it and remove spaces to have the value only
2279d01bcdeSArmin Le Grand                     rtl::OUString aNewOUTokenValue;
2289d01bcdeSArmin Le Grand 
2299d01bcdeSArmin Le Grand                     if(nIndexTokenImportant > 0)
2309d01bcdeSArmin Le Grand                     {
2319d01bcdeSArmin Le Grand                         // copy content before token
2329d01bcdeSArmin Le Grand                         aNewOUTokenValue += aOUTokenValue.copy(0, nIndexTokenImportant);
2339d01bcdeSArmin Le Grand                     }
2349d01bcdeSArmin Le Grand 
2359d01bcdeSArmin Le Grand                     if(aOUTokenValue.getLength() > nIndexTokenImportant + aTokenImportant.getLength())
2369d01bcdeSArmin Le Grand                     {
2379d01bcdeSArmin Le Grand                         // copy content after token
2389d01bcdeSArmin Le Grand                         aNewOUTokenValue += aOUTokenValue.copy(nIndexTokenImportant + aTokenImportant.getLength());
2399d01bcdeSArmin Le Grand                     }
2409d01bcdeSArmin Le Grand 
2419d01bcdeSArmin Le Grand                     // remove spaces
2429d01bcdeSArmin Le Grand                     aOUTokenValue = aNewOUTokenValue.trim();
2439d01bcdeSArmin Le Grand                 }
244ddde725dSArmin Le Grand 
245*52cb04b8SArmin Le Grand                 // valid token-value pair, parse it
246*52cb04b8SArmin Le Grand                 parseStyleAttribute(aOUTokenName, StrToSVGToken(aOUTokenName, true), aOUTokenValue, true);
247ddde725dSArmin Le Grand             }
248ddde725dSArmin Le Grand         }
249ddde725dSArmin Le Grand 
getParentStyle() const250ddde725dSArmin Le Grand         const SvgStyleAttributes* SvgStyleAttributes::getParentStyle() const
251ddde725dSArmin Le Grand         {
25250b37974SArmin Le Grand             if(getCssStyleParent())
253ddde725dSArmin Le Grand             {
25450b37974SArmin Le Grand                 return getCssStyleParent();
255ddde725dSArmin Le Grand             }
256ddde725dSArmin Le Grand 
2574374d266SArmin Le Grand             if(mrOwner.supportsParentStyle() && mrOwner.getParent())
258ddde725dSArmin Le Grand             {
259ddde725dSArmin Le Grand                 return mrOwner.getParent()->getSvgStyleAttributes();
260ddde725dSArmin Le Grand             }
261ddde725dSArmin Le Grand 
262ddde725dSArmin Le Grand             return 0;
263ddde725dSArmin Le Grand         }
264ddde725dSArmin Le Grand 
add_text(drawinglayer::primitive2d::Primitive2DSequence & rTarget,drawinglayer::primitive2d::Primitive2DSequence & rSource) const265ddde725dSArmin Le Grand         void SvgStyleAttributes::add_text(
266ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
267ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rSource) const
268ddde725dSArmin Le Grand         {
269ddde725dSArmin Le Grand             if(rSource.hasElements())
270ddde725dSArmin Le Grand             {
271ddde725dSArmin Le Grand                 // at this point the primitives in rSource are of type TextSimplePortionPrimitive2D
272ddde725dSArmin Le Grand                 // or TextDecoratedPortionPrimitive2D and have the Fill Color (pAttributes->getFill())
273ddde725dSArmin Le Grand                 // set. When another fill is used and also evtl. stroke is set it gets necessary to
274ddde725dSArmin Le Grand                 // dismantle to geometry and add needed primitives
275ddde725dSArmin Le Grand                 const basegfx::BColor* pFill = getFill();
276ddde725dSArmin Le Grand                 const SvgGradientNode* pFillGradient = getSvgGradientNodeFill();
277ddde725dSArmin Le Grand                 const SvgPatternNode* pFillPattern = getSvgPatternNodeFill();
278ddde725dSArmin Le Grand                 const basegfx::BColor* pStroke = getStroke();
279ddde725dSArmin Le Grand                 const SvgGradientNode* pStrokeGradient = getSvgGradientNodeStroke();
280ddde725dSArmin Le Grand                 const SvgPatternNode* pStrokePattern = getSvgPatternNodeStroke();
281ddde725dSArmin Le Grand                 basegfx::B2DPolyPolygon aMergedArea;
282ddde725dSArmin Le Grand 
283ddde725dSArmin Le Grand                 if(pFillGradient || pFillPattern || pStroke || pStrokeGradient || pStrokePattern)
284ddde725dSArmin Le Grand                 {
285ddde725dSArmin Le Grand                     // text geometry is needed, create
286ddde725dSArmin Le Grand                     // use neutral ViewInformation and create LineGeometryExtractor2D
287ddde725dSArmin Le Grand                     const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
288ddde725dSArmin Le Grand                     drawinglayer::processor2d::TextAsPolygonExtractor2D aExtractor(aViewInformation2D);
289ddde725dSArmin Le Grand 
29086e1cf34SPedro Giffuni                     // process
291ddde725dSArmin Le Grand                     aExtractor.process(rSource);
292ddde725dSArmin Le Grand 
293ddde725dSArmin Le Grand                     // get results
294ddde725dSArmin Le Grand                     const drawinglayer::processor2d::TextAsPolygonDataNodeVector& rResult = aExtractor.getTarget();
295ddde725dSArmin Le Grand                     const sal_uInt32 nResultCount(rResult.size());
296ddde725dSArmin Le Grand                     basegfx::B2DPolyPolygonVector aTextFillVector;
297ddde725dSArmin Le Grand                     aTextFillVector.reserve(nResultCount);
298ddde725dSArmin Le Grand 
299ddde725dSArmin Le Grand                     for(sal_uInt32 a(0); a < nResultCount; a++)
300ddde725dSArmin Le Grand                     {
301ddde725dSArmin Le Grand                         const drawinglayer::processor2d::TextAsPolygonDataNode& rCandidate = rResult[a];
302ddde725dSArmin Le Grand 
303ddde725dSArmin Le Grand                         if(rCandidate.getIsFilled())
304ddde725dSArmin Le Grand                         {
305ddde725dSArmin Le Grand                             aTextFillVector.push_back(rCandidate.getB2DPolyPolygon());
306ddde725dSArmin Le Grand                         }
307ddde725dSArmin Le Grand                     }
308ddde725dSArmin Le Grand 
309ddde725dSArmin Le Grand                     if(!aTextFillVector.empty())
310ddde725dSArmin Le Grand                     {
311ddde725dSArmin Le Grand                         aMergedArea = basegfx::tools::mergeToSinglePolyPolygon(aTextFillVector);
312ddde725dSArmin Le Grand                     }
313ddde725dSArmin Le Grand                 }
314ddde725dSArmin Le Grand 
315ddde725dSArmin Le Grand                 const bool bStrokeUsed(pStroke || pStrokeGradient || pStrokePattern);
316ddde725dSArmin Le Grand 
317ddde725dSArmin Le Grand                 // add fill. Use geometry even for simple color fill when stroke
318ddde725dSArmin Le Grand                 // is used, else text rendering and the geometry-based stroke will
319ddde725dSArmin Le Grand                 // normally not really match optically due to divrese system text
320ddde725dSArmin Le Grand                 // renderers
321ddde725dSArmin Le Grand                 if(aMergedArea.count() && (pFillGradient || pFillPattern || bStrokeUsed))
322ddde725dSArmin Le Grand                 {
323ddde725dSArmin Le Grand                     // create text fill content based on geometry
324ddde725dSArmin Le Grand                     add_fill(aMergedArea, rTarget, aMergedArea.getB2DRange());
325ddde725dSArmin Le Grand                 }
326ddde725dSArmin Le Grand                 else if(pFill)
327ddde725dSArmin Le Grand                 {
328ddde725dSArmin Le Grand                     // add the already prepared primitives for single color fill
329ddde725dSArmin Le Grand                     drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, rSource);
330ddde725dSArmin Le Grand                 }
331ddde725dSArmin Le Grand 
332ddde725dSArmin Le Grand                 // add stroke
333ddde725dSArmin Le Grand                 if(aMergedArea.count() && bStrokeUsed)
334ddde725dSArmin Le Grand                 {
335ddde725dSArmin Le Grand                     // create text stroke content
336ddde725dSArmin Le Grand                     add_stroke(aMergedArea, rTarget, aMergedArea.getB2DRange());
337ddde725dSArmin Le Grand                 }
338ddde725dSArmin Le Grand             }
339ddde725dSArmin Le Grand         }
340ddde725dSArmin Le Grand 
add_fillGradient(const basegfx::B2DPolyPolygon & rPath,drawinglayer::primitive2d::Primitive2DSequence & rTarget,const SvgGradientNode & rFillGradient,const basegfx::B2DRange & rGeoRange) const341ddde725dSArmin Le Grand         void SvgStyleAttributes::add_fillGradient(
342ddde725dSArmin Le Grand             const basegfx::B2DPolyPolygon& rPath,
343ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
344ddde725dSArmin Le Grand             const SvgGradientNode& rFillGradient,
345ddde725dSArmin Le Grand             const basegfx::B2DRange& rGeoRange) const
346ddde725dSArmin Le Grand         {
347ddde725dSArmin Le Grand             // create fill content
348ddde725dSArmin Le Grand             drawinglayer::primitive2d::SvgGradientEntryVector aSvgGradientEntryVector;
349ddde725dSArmin Le Grand 
350ddde725dSArmin Le Grand             // get the color stops
351ddde725dSArmin Le Grand             rFillGradient.collectGradientEntries(aSvgGradientEntryVector);
352ddde725dSArmin Le Grand 
353ddde725dSArmin Le Grand             if(!aSvgGradientEntryVector.empty())
354ddde725dSArmin Le Grand             {
355ddde725dSArmin Le Grand                 basegfx::B2DHomMatrix aGeoToUnit;
35601e92ad6SArmin Le Grand                 basegfx::B2DHomMatrix aGradientTransform;
357ddde725dSArmin Le Grand 
358ddde725dSArmin Le Grand                 if(rFillGradient.getGradientTransform())
359ddde725dSArmin Le Grand                 {
36001e92ad6SArmin Le Grand                     aGradientTransform = *rFillGradient.getGradientTransform();
361ddde725dSArmin Le Grand                 }
362ddde725dSArmin Le Grand 
363ddde725dSArmin Le Grand                 if(userSpaceOnUse == rFillGradient.getGradientUnits())
364ddde725dSArmin Le Grand                 {
365ddde725dSArmin Le Grand                     aGeoToUnit.translate(-rGeoRange.getMinX(), -rGeoRange.getMinY());
366ddde725dSArmin Le Grand                     aGeoToUnit.scale(1.0 / rGeoRange.getWidth(), 1.0 / rGeoRange.getHeight());
367ddde725dSArmin Le Grand                 }
368ddde725dSArmin Le Grand 
369ddde725dSArmin Le Grand                 if(SVGTokenLinearGradient == rFillGradient.getType())
370ddde725dSArmin Le Grand                 {
371ddde725dSArmin Le Grand                     basegfx::B2DPoint aStart(0.0, 0.0);
372ddde725dSArmin Le Grand                     basegfx::B2DPoint aEnd(1.0, 0.0);
373ddde725dSArmin Le Grand 
374ddde725dSArmin Le Grand                     if(userSpaceOnUse == rFillGradient.getGradientUnits())
375ddde725dSArmin Le Grand                     {
376ddde725dSArmin Le Grand                         // all possible units
377ddde725dSArmin Le Grand                         aStart.setX(rFillGradient.getX1().solve(mrOwner, xcoordinate));
378ddde725dSArmin Le Grand                         aStart.setY(rFillGradient.getY1().solve(mrOwner, ycoordinate));
379ddde725dSArmin Le Grand                         aEnd.setX(rFillGradient.getX2().solve(mrOwner, xcoordinate));
380ddde725dSArmin Le Grand                         aEnd.setY(rFillGradient.getY2().solve(mrOwner, ycoordinate));
381ddde725dSArmin Le Grand                     }
382ddde725dSArmin Le Grand                     else
383ddde725dSArmin Le Grand                     {
384ddde725dSArmin Le Grand                         // fractions or percent relative to object bounds
385ddde725dSArmin Le Grand                         const SvgNumber X1(rFillGradient.getX1());
386ddde725dSArmin Le Grand                         const SvgNumber Y1(rFillGradient.getY1());
387ddde725dSArmin Le Grand                         const SvgNumber X2(rFillGradient.getX2());
388ddde725dSArmin Le Grand                         const SvgNumber Y2(rFillGradient.getY2());
389ddde725dSArmin Le Grand 
390ddde725dSArmin Le Grand                         aStart.setX(Unit_percent == X1.getUnit() ? X1.getNumber() * 0.01 : X1.getNumber());
391ddde725dSArmin Le Grand                         aStart.setY(Unit_percent == Y1.getUnit() ? Y1.getNumber() * 0.01 : Y1.getNumber());
392ddde725dSArmin Le Grand                         aEnd.setX(Unit_percent == X2.getUnit() ? X2.getNumber() * 0.01 : X2.getNumber());
393ddde725dSArmin Le Grand                         aEnd.setY(Unit_percent == Y2.getUnit() ? Y2.getNumber() * 0.01 : Y2.getNumber());
394ddde725dSArmin Le Grand                     }
395ddde725dSArmin Le Grand 
396ddde725dSArmin Le Grand                     if(!aGeoToUnit.isIdentity())
397ddde725dSArmin Le Grand                     {
398ddde725dSArmin Le Grand                         aStart *= aGeoToUnit;
399ddde725dSArmin Le Grand                         aEnd *= aGeoToUnit;
400ddde725dSArmin Le Grand                     }
401ddde725dSArmin Le Grand 
402ddde725dSArmin Le Grand                     drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(
403ddde725dSArmin Le Grand                         rTarget,
404ddde725dSArmin Le Grand                         new drawinglayer::primitive2d::SvgLinearGradientPrimitive2D(
40501e92ad6SArmin Le Grand                             aGradientTransform,
406ddde725dSArmin Le Grand                             rPath,
407ddde725dSArmin Le Grand                             aSvgGradientEntryVector,
408ddde725dSArmin Le Grand                             aStart,
409ddde725dSArmin Le Grand                             aEnd,
410804e0487SArmin Le Grand                             userSpaceOnUse != rFillGradient.getGradientUnits(),
411ddde725dSArmin Le Grand                             rFillGradient.getSpreadMethod()));
412ddde725dSArmin Le Grand                 }
413ddde725dSArmin Le Grand                 else
414ddde725dSArmin Le Grand                 {
415ddde725dSArmin Le Grand                     basegfx::B2DPoint aStart(0.5, 0.5);
416ddde725dSArmin Le Grand                     basegfx::B2DPoint aFocal;
417ddde725dSArmin Le Grand                     double fRadius(0.5);
418ddde725dSArmin Le Grand                     const SvgNumber* pFx = rFillGradient.getFx();
419ddde725dSArmin Le Grand                     const SvgNumber* pFy = rFillGradient.getFy();
420ddde725dSArmin Le Grand                     const bool bFocal(pFx || pFy);
421ddde725dSArmin Le Grand 
422ddde725dSArmin Le Grand                     if(userSpaceOnUse == rFillGradient.getGradientUnits())
423ddde725dSArmin Le Grand                     {
424ddde725dSArmin Le Grand                         // all possible units
425ddde725dSArmin Le Grand                         aStart.setX(rFillGradient.getCx().solve(mrOwner, xcoordinate));
426ddde725dSArmin Le Grand                         aStart.setY(rFillGradient.getCy().solve(mrOwner, ycoordinate));
427ddde725dSArmin Le Grand                         fRadius = rFillGradient.getR().solve(mrOwner, length);
428ddde725dSArmin Le Grand 
429ddde725dSArmin Le Grand                         if(bFocal)
430ddde725dSArmin Le Grand                         {
431ddde725dSArmin Le Grand                             aFocal.setX(pFx ? pFx->solve(mrOwner, xcoordinate) : aStart.getX());
432ddde725dSArmin Le Grand                             aFocal.setY(pFy ? pFy->solve(mrOwner, ycoordinate) : aStart.getY());
433ddde725dSArmin Le Grand                         }
434ddde725dSArmin Le Grand                     }
435ddde725dSArmin Le Grand                     else
436ddde725dSArmin Le Grand                     {
437ddde725dSArmin Le Grand                         // fractions or percent relative to object bounds
438ddde725dSArmin Le Grand                         const SvgNumber Cx(rFillGradient.getCx());
439ddde725dSArmin Le Grand                         const SvgNumber Cy(rFillGradient.getCy());
440ddde725dSArmin Le Grand                         const SvgNumber R(rFillGradient.getR());
441ddde725dSArmin Le Grand 
442ddde725dSArmin Le Grand                         aStart.setX(Unit_percent == Cx.getUnit() ? Cx.getNumber() * 0.01 : Cx.getNumber());
443ddde725dSArmin Le Grand                         aStart.setY(Unit_percent == Cy.getUnit() ? Cy.getNumber() * 0.01 : Cy.getNumber());
444ddde725dSArmin Le Grand                         fRadius = (Unit_percent == R.getUnit()) ? R.getNumber() * 0.01 : R.getNumber();
445ddde725dSArmin Le Grand 
446ddde725dSArmin Le Grand                         if(bFocal)
447ddde725dSArmin Le Grand                         {
448ddde725dSArmin Le Grand                             aFocal.setX(pFx ? (Unit_percent == pFx->getUnit() ? pFx->getNumber() * 0.01 : pFx->getNumber()) : aStart.getX());
449ddde725dSArmin Le Grand                             aFocal.setY(pFy ? (Unit_percent == pFy->getUnit() ? pFy->getNumber() * 0.01 : pFy->getNumber()) : aStart.getY());
450ddde725dSArmin Le Grand                         }
451ddde725dSArmin Le Grand                     }
452ddde725dSArmin Le Grand 
453ddde725dSArmin Le Grand                     if(!aGeoToUnit.isIdentity())
454ddde725dSArmin Le Grand                     {
455ddde725dSArmin Le Grand                         aStart *= aGeoToUnit;
456ddde725dSArmin Le Grand                         fRadius = (aGeoToUnit * basegfx::B2DVector(fRadius, 0.0)).getLength();
457ddde725dSArmin Le Grand 
458ddde725dSArmin Le Grand                         if(bFocal)
459ddde725dSArmin Le Grand                         {
460ddde725dSArmin Le Grand                             aFocal *= aGeoToUnit;
461ddde725dSArmin Le Grand                         }
462ddde725dSArmin Le Grand                     }
463ddde725dSArmin Le Grand 
464ddde725dSArmin Le Grand                     drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(
465ddde725dSArmin Le Grand                         rTarget,
466ddde725dSArmin Le Grand                         new drawinglayer::primitive2d::SvgRadialGradientPrimitive2D(
46701e92ad6SArmin Le Grand                             aGradientTransform,
468ddde725dSArmin Le Grand                             rPath,
469ddde725dSArmin Le Grand                             aSvgGradientEntryVector,
470ddde725dSArmin Le Grand                             aStart,
471ddde725dSArmin Le Grand                             fRadius,
472804e0487SArmin Le Grand                             userSpaceOnUse != rFillGradient.getGradientUnits(),
473ddde725dSArmin Le Grand                             rFillGradient.getSpreadMethod(),
474ddde725dSArmin Le Grand                             bFocal ? &aFocal : 0));
475ddde725dSArmin Le Grand                 }
476ddde725dSArmin Le Grand             }
477ddde725dSArmin Le Grand         }
478ddde725dSArmin Le Grand 
add_fillPatternTransform(const basegfx::B2DPolyPolygon & rPath,drawinglayer::primitive2d::Primitive2DSequence & rTarget,const SvgPatternNode & rFillPattern,const basegfx::B2DRange & rGeoRange) const479ddde725dSArmin Le Grand         void SvgStyleAttributes::add_fillPatternTransform(
480ddde725dSArmin Le Grand             const basegfx::B2DPolyPolygon& rPath,
481ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
482ddde725dSArmin Le Grand             const SvgPatternNode& rFillPattern,
483ddde725dSArmin Le Grand             const basegfx::B2DRange& rGeoRange) const
484ddde725dSArmin Le Grand         {
485ddde725dSArmin Le Grand             // prepare fill polyPolygon with given pattern, check for patternTransform
486ddde725dSArmin Le Grand             if(rFillPattern.getPatternTransform() && !rFillPattern.getPatternTransform()->isIdentity())
487ddde725dSArmin Le Grand             {
488ddde725dSArmin Le Grand                 // PatternTransform is active; Handle by filling the inverse transformed
489ddde725dSArmin Le Grand                 // path and back-transforming the result
490ddde725dSArmin Le Grand                 basegfx::B2DPolyPolygon aPath(rPath);
491ddde725dSArmin Le Grand                 basegfx::B2DHomMatrix aInv(*rFillPattern.getPatternTransform());
492ddde725dSArmin Le Grand                 drawinglayer::primitive2d::Primitive2DSequence aNewTarget;
493ddde725dSArmin Le Grand 
494ddde725dSArmin Le Grand                 aInv.invert();
495ddde725dSArmin Le Grand                 aPath.transform(aInv);
496ddde725dSArmin Le Grand                 add_fillPattern(aPath, aNewTarget, rFillPattern, aPath.getB2DRange());
497ddde725dSArmin Le Grand 
498ddde725dSArmin Le Grand                 if(aNewTarget.hasElements())
499ddde725dSArmin Le Grand                 {
500ddde725dSArmin Le Grand                     drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(
501ddde725dSArmin Le Grand                         rTarget,
502ddde725dSArmin Le Grand                         new drawinglayer::primitive2d::TransformPrimitive2D(
503ddde725dSArmin Le Grand                             *rFillPattern.getPatternTransform(),
504ddde725dSArmin Le Grand                             aNewTarget));
505ddde725dSArmin Le Grand                 }
506ddde725dSArmin Le Grand             }
507ddde725dSArmin Le Grand             else
508ddde725dSArmin Le Grand             {
509ddde725dSArmin Le Grand                 // no patternTransform, create fillPattern directly
510ddde725dSArmin Le Grand                 add_fillPattern(rPath, rTarget, rFillPattern, rGeoRange);
511ddde725dSArmin Le Grand             }
512ddde725dSArmin Le Grand         }
513ddde725dSArmin Le Grand 
add_fillPattern(const basegfx::B2DPolyPolygon & rPath,drawinglayer::primitive2d::Primitive2DSequence & rTarget,const SvgPatternNode & rFillPattern,const basegfx::B2DRange & rGeoRange) const514ddde725dSArmin Le Grand         void SvgStyleAttributes::add_fillPattern(
515ddde725dSArmin Le Grand             const basegfx::B2DPolyPolygon& rPath,
516ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
517ddde725dSArmin Le Grand             const SvgPatternNode& rFillPattern,
518ddde725dSArmin Le Grand             const basegfx::B2DRange& rGeoRange) const
519ddde725dSArmin Le Grand         {
520ddde725dSArmin Le Grand             // fill polyPolygon with given pattern
521ddde725dSArmin Le Grand             const drawinglayer::primitive2d::Primitive2DSequence& rPrimitives = rFillPattern.getPatternPrimitives();
522ddde725dSArmin Le Grand 
523ddde725dSArmin Le Grand             if(rPrimitives.hasElements())
524ddde725dSArmin Le Grand             {
525ddde725dSArmin Le Grand                 double fTargetWidth(rGeoRange.getWidth());
526ddde725dSArmin Le Grand                 double fTargetHeight(rGeoRange.getHeight());
527ddde725dSArmin Le Grand 
528ddde725dSArmin Le Grand                 if(fTargetWidth > 0.0 && fTargetHeight > 0.0)
529ddde725dSArmin Le Grand                 {
530ddde725dSArmin Le Grand                     // get relative values from pattern
531ddde725dSArmin Le Grand                     double fX(0.0);
532ddde725dSArmin Le Grand                     double fY(0.0);
533ddde725dSArmin Le Grand                     double fW(0.0);
534ddde725dSArmin Le Grand                     double fH(0.0);
535ddde725dSArmin Le Grand 
536ddde725dSArmin Le Grand                     rFillPattern.getValuesRelative(fX, fY, fW, fH, rGeoRange, mrOwner);
537ddde725dSArmin Le Grand 
538ddde725dSArmin Le Grand                     if(fW > 0.0 && fH > 0.0)
539ddde725dSArmin Le Grand                     {
540ddde725dSArmin Le Grand                         // build the reference range relative to the rGeoRange
541ddde725dSArmin Le Grand                         const basegfx::B2DRange aReferenceRange(fX, fY, fX + fW, fY + fH);
542ddde725dSArmin Le Grand 
543ddde725dSArmin Le Grand                         // find out how the content is mapped to the reference range
544ddde725dSArmin Le Grand                         basegfx::B2DHomMatrix aMapPrimitivesToUnitRange;
545ddde725dSArmin Le Grand                         const basegfx::B2DRange* pViewBox = rFillPattern.getViewBox();
546ddde725dSArmin Le Grand 
547ddde725dSArmin Le Grand                         if(pViewBox)
548ddde725dSArmin Le Grand                         {
549ddde725dSArmin Le Grand                             // use viewBox/preserveAspectRatio
550ddde725dSArmin Le Grand                             const SvgAspectRatio& rRatio = rFillPattern.getSvgAspectRatio();
551ddde725dSArmin Le Grand                             const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
552ddde725dSArmin Le Grand 
553ddde725dSArmin Le Grand                             if(rRatio.isSet())
554ddde725dSArmin Le Grand                             {
555ddde725dSArmin Le Grand                                 // let mapping be created from SvgAspectRatio
556ddde725dSArmin Le Grand                                 aMapPrimitivesToUnitRange = rRatio.createMapping(aUnitRange, *pViewBox);
557ddde725dSArmin Le Grand                             }
558ddde725dSArmin Le Grand                             else
559ddde725dSArmin Le Grand                             {
560ddde725dSArmin Le Grand                                 // choose default mapping
561ddde725dSArmin Le Grand                                 aMapPrimitivesToUnitRange = rRatio.createLinearMapping(aUnitRange, *pViewBox);
562ddde725dSArmin Le Grand                             }
563ddde725dSArmin Le Grand                         }
564ddde725dSArmin Le Grand                         else
565ddde725dSArmin Le Grand                         {
566ddde725dSArmin Le Grand                             // use patternContentUnits
567ddde725dSArmin Le Grand                             const SvgUnits aPatternContentUnits(rFillPattern.getPatternContentUnits() ? *rFillPattern.getPatternContentUnits() : userSpaceOnUse);
568ddde725dSArmin Le Grand 
569ddde725dSArmin Le Grand                             if(userSpaceOnUse == aPatternContentUnits)
570ddde725dSArmin Le Grand                             {
571ddde725dSArmin Le Grand                                 // create relative mapping to unit coordinates
572ddde725dSArmin Le Grand                                 aMapPrimitivesToUnitRange.scale(1.0 / (fW * fTargetWidth), 1.0 / (fH * fTargetHeight));
573ddde725dSArmin Le Grand                             }
574ddde725dSArmin Le Grand                             else
575ddde725dSArmin Le Grand                             {
576ddde725dSArmin Le Grand                                 aMapPrimitivesToUnitRange.scale(1.0 / fW, 1.0 / fH);
577ddde725dSArmin Le Grand                             }
578ddde725dSArmin Le Grand                         }
579ddde725dSArmin Le Grand 
580ddde725dSArmin Le Grand                         // apply aMapPrimitivesToUnitRange to content when used
581ddde725dSArmin Le Grand                         drawinglayer::primitive2d::Primitive2DSequence aPrimitives(rPrimitives);
582ddde725dSArmin Le Grand 
583ddde725dSArmin Le Grand                         if(!aMapPrimitivesToUnitRange.isIdentity())
584ddde725dSArmin Le Grand                         {
585ddde725dSArmin Le Grand                             const drawinglayer::primitive2d::Primitive2DReference xRef(
586ddde725dSArmin Le Grand                                 new drawinglayer::primitive2d::TransformPrimitive2D(
587ddde725dSArmin Le Grand                                     aMapPrimitivesToUnitRange,
588ddde725dSArmin Le Grand                                     aPrimitives));
589ddde725dSArmin Le Grand 
590ddde725dSArmin Le Grand                             aPrimitives = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
591ddde725dSArmin Le Grand                         }
592ddde725dSArmin Le Grand 
593ddde725dSArmin Le Grand                         // embed in PatternFillPrimitive2D
594ddde725dSArmin Le Grand                         drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(
595ddde725dSArmin Le Grand                             rTarget,
596ddde725dSArmin Le Grand                             new drawinglayer::primitive2d::PatternFillPrimitive2D(
597ddde725dSArmin Le Grand                                 rPath,
598ddde725dSArmin Le Grand                                 aPrimitives,
599ddde725dSArmin Le Grand                                 aReferenceRange));
600ddde725dSArmin Le Grand                     }
601ddde725dSArmin Le Grand                 }
602ddde725dSArmin Le Grand             }
603ddde725dSArmin Le Grand         }
604ddde725dSArmin Le Grand 
add_fill(const basegfx::B2DPolyPolygon & rPath,drawinglayer::primitive2d::Primitive2DSequence & rTarget,const basegfx::B2DRange & rGeoRange) const605ddde725dSArmin Le Grand         void SvgStyleAttributes::add_fill(
606ddde725dSArmin Le Grand             const basegfx::B2DPolyPolygon& rPath,
607ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
608ddde725dSArmin Le Grand             const basegfx::B2DRange& rGeoRange) const
609ddde725dSArmin Le Grand         {
610ddde725dSArmin Le Grand             const basegfx::BColor* pFill = getFill();
611ddde725dSArmin Le Grand             const SvgGradientNode* pFillGradient = getSvgGradientNodeFill();
612ddde725dSArmin Le Grand             const SvgPatternNode* pFillPattern = getSvgPatternNodeFill();
613ddde725dSArmin Le Grand 
614ddde725dSArmin Le Grand             if(pFill || pFillGradient || pFillPattern)
615ddde725dSArmin Le Grand             {
616ddde725dSArmin Le Grand                 const double fFillOpacity(getFillOpacity().solve(mrOwner, length));
617ddde725dSArmin Le Grand 
618ddde725dSArmin Le Grand                 if(basegfx::fTools::more(fFillOpacity, 0.0))
619ddde725dSArmin Le Grand                 {
620ddde725dSArmin Le Grand                     drawinglayer::primitive2d::Primitive2DSequence aNewFill;
621ddde725dSArmin Le Grand 
622ddde725dSArmin Le Grand                     if(pFillGradient)
623ddde725dSArmin Le Grand                     {
624ddde725dSArmin Le Grand                         // create fill content with SVG gradient primitive
625ddde725dSArmin Le Grand                         add_fillGradient(rPath, aNewFill, *pFillGradient, rGeoRange);
626ddde725dSArmin Le Grand                     }
627ddde725dSArmin Le Grand                     else if(pFillPattern)
628ddde725dSArmin Le Grand                     {
629ddde725dSArmin Le Grand                         // create fill content with SVG pattern primitive
630ddde725dSArmin Le Grand                         add_fillPatternTransform(rPath, aNewFill, *pFillPattern, rGeoRange);
631ddde725dSArmin Le Grand                     }
632ddde725dSArmin Le Grand                     else // if(pFill)
633ddde725dSArmin Le Grand                     {
634ddde725dSArmin Le Grand                         // create fill content
635ddde725dSArmin Le Grand                         aNewFill.realloc(1);
636ddde725dSArmin Le Grand                         aNewFill[0] = new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D(
637ddde725dSArmin Le Grand                             rPath,
638ddde725dSArmin Le Grand                             *pFill);
639ddde725dSArmin Le Grand                     }
640ddde725dSArmin Le Grand 
641ddde725dSArmin Le Grand                     if(aNewFill.hasElements())
642ddde725dSArmin Le Grand                     {
643ddde725dSArmin Le Grand                         if(basegfx::fTools::less(fFillOpacity, 1.0))
644ddde725dSArmin Le Grand                         {
645ddde725dSArmin Le Grand                             // embed in UnifiedTransparencePrimitive2D
646ddde725dSArmin Le Grand                             drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(
647ddde725dSArmin Le Grand                                 rTarget,
648ddde725dSArmin Le Grand                                 new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
649ddde725dSArmin Le Grand                                     aNewFill,
650ddde725dSArmin Le Grand                                     1.0 - fFillOpacity));
651ddde725dSArmin Le Grand                         }
652ddde725dSArmin Le Grand                         else
653ddde725dSArmin Le Grand                         {
654ddde725dSArmin Le Grand                             // append
655ddde725dSArmin Le Grand                             drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewFill);
656ddde725dSArmin Le Grand                         }
657ddde725dSArmin Le Grand                     }
658ddde725dSArmin Le Grand                 }
659ddde725dSArmin Le Grand             }
660ddde725dSArmin Le Grand         }
661ddde725dSArmin Le Grand 
add_stroke(const basegfx::B2DPolyPolygon & rPath,drawinglayer::primitive2d::Primitive2DSequence & rTarget,const basegfx::B2DRange & rGeoRange) const662ddde725dSArmin Le Grand         void SvgStyleAttributes::add_stroke(
663ddde725dSArmin Le Grand             const basegfx::B2DPolyPolygon& rPath,
664ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
665ddde725dSArmin Le Grand             const basegfx::B2DRange& rGeoRange) const
666ddde725dSArmin Le Grand         {
667ddde725dSArmin Le Grand             const basegfx::BColor* pStroke = getStroke();
668ddde725dSArmin Le Grand             const SvgGradientNode* pStrokeGradient = getSvgGradientNodeStroke();
669ddde725dSArmin Le Grand             const SvgPatternNode* pStrokePattern = getSvgPatternNodeStroke();
670ddde725dSArmin Le Grand 
671ddde725dSArmin Le Grand             if(pStroke || pStrokeGradient || pStrokePattern)
672ddde725dSArmin Le Grand             {
673ddde725dSArmin Le Grand                 drawinglayer::primitive2d::Primitive2DSequence aNewStroke;
674ddde725dSArmin Le Grand                 const double fStrokeOpacity(getStrokeOpacity().solve(mrOwner, length));
675ddde725dSArmin Le Grand 
676ddde725dSArmin Le Grand                 if(basegfx::fTools::more(fStrokeOpacity, 0.0))
677ddde725dSArmin Le Grand                 {
678ddde725dSArmin Le Grand                     // get stroke width; SVG does not use 0.0 == hairline, so 0.0 is no line at all
679ddde725dSArmin Le Grand                     const double fStrokeWidth(getStrokeWidth().isSet() ? getStrokeWidth().solve(mrOwner, length) : 1.0);
680ddde725dSArmin Le Grand 
681ddde725dSArmin Le Grand                     if(basegfx::fTools::more(fStrokeWidth, 0.0))
682ddde725dSArmin Le Grand                     {
6835aaf853bSArmin Le Grand                         // get LineJoin, LineCap and stroke array
684ddde725dSArmin Le Grand                         const basegfx::B2DLineJoin aB2DLineJoin(StrokeLinejoinToB2DLineJoin(getStrokeLinejoin()));
6855aaf853bSArmin Le Grand                         const com::sun::star::drawing::LineCap aLineCap(StrokeLinecapToDrawingLineCap(getStrokeLinecap()));
686ddde725dSArmin Le Grand                         ::std::vector< double > aDashArray;
687ddde725dSArmin Le Grand 
688ddde725dSArmin Le Grand                         if(!getStrokeDasharray().empty())
689ddde725dSArmin Le Grand                         {
690ddde725dSArmin Le Grand                             aDashArray = solveSvgNumberVector(getStrokeDasharray(), mrOwner, length);
691ddde725dSArmin Le Grand                         }
692ddde725dSArmin Le Grand 
693ddde725dSArmin Le Grand                         // todo: Handle getStrokeDashOffset()
694ddde725dSArmin Le Grand 
695ddde725dSArmin Le Grand                         // prepare line attribute
696ddde725dSArmin Le Grand                         drawinglayer::primitive2d::Primitive2DReference aNewLinePrimitive;
697ddde725dSArmin Le Grand                         const drawinglayer::attribute::LineAttribute aLineAttribute(
698ddde725dSArmin Le Grand                             pStroke ? *pStroke : basegfx::BColor(0.0, 0.0, 0.0),
699ddde725dSArmin Le Grand                             fStrokeWidth,
7005aaf853bSArmin Le Grand                             aB2DLineJoin,
7015aaf853bSArmin Le Grand                             aLineCap);
702ddde725dSArmin Le Grand 
703ddde725dSArmin Le Grand                         if(aDashArray.empty())
704ddde725dSArmin Le Grand                         {
705ddde725dSArmin Le Grand                             aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
706ddde725dSArmin Le Grand                                 rPath,
707ddde725dSArmin Le Grand                                 aLineAttribute);
708ddde725dSArmin Le Grand                         }
709ddde725dSArmin Le Grand                         else
710ddde725dSArmin Le Grand                         {
711ddde725dSArmin Le Grand                             const drawinglayer::attribute::StrokeAttribute aStrokeAttribute(aDashArray);
712ddde725dSArmin Le Grand 
713ddde725dSArmin Le Grand                             aNewLinePrimitive = new drawinglayer::primitive2d::PolyPolygonStrokePrimitive2D(
714ddde725dSArmin Le Grand                                 rPath,
715ddde725dSArmin Le Grand                                 aLineAttribute,
716ddde725dSArmin Le Grand                                 aDashArray);
717ddde725dSArmin Le Grand                         }
718ddde725dSArmin Le Grand 
719ddde725dSArmin Le Grand                         if(pStrokeGradient || pStrokePattern)
720ddde725dSArmin Le Grand                         {
721ddde725dSArmin Le Grand                             // put primitive into Primitive2DReference and Primitive2DSequence
722ddde725dSArmin Le Grand                             const drawinglayer::primitive2d::Primitive2DSequence aSeq(&aNewLinePrimitive, 1);
723ddde725dSArmin Le Grand 
724ddde725dSArmin Le Grand                             // use neutral ViewInformation and create LineGeometryExtractor2D
725ddde725dSArmin Le Grand                             const drawinglayer::geometry::ViewInformation2D aViewInformation2D;
726ddde725dSArmin Le Grand                             drawinglayer::processor2d::LineGeometryExtractor2D aExtractor(aViewInformation2D);
727ddde725dSArmin Le Grand 
72886e1cf34SPedro Giffuni                             // process
729ddde725dSArmin Le Grand                             aExtractor.process(aSeq);
730ddde725dSArmin Le Grand 
731ddde725dSArmin Le Grand                             // check for fill rsults
732ddde725dSArmin Le Grand                             const basegfx::B2DPolyPolygonVector& rLineFillVector(aExtractor.getExtractedLineFills());
733ddde725dSArmin Le Grand 
734e2bf1e9dSArmin Le Grand                             if(!rLineFillVector.empty())
735ddde725dSArmin Le Grand                             {
736ddde725dSArmin Le Grand                                 const basegfx::B2DPolyPolygon aMergedArea(
737ddde725dSArmin Le Grand                                     basegfx::tools::mergeToSinglePolyPolygon(
738e2bf1e9dSArmin Le Grand                                         rLineFillVector));
739ddde725dSArmin Le Grand 
740ddde725dSArmin Le Grand                                 if(aMergedArea.count())
741ddde725dSArmin Le Grand                                 {
742ddde725dSArmin Le Grand                                     if(pStrokeGradient)
743ddde725dSArmin Le Grand                                     {
744ddde725dSArmin Le Grand                                         // create fill content with SVG gradient primitive. Use original GeoRange,
745ddde725dSArmin Le Grand                                         // e.g. from circle without LineWidth
746ddde725dSArmin Le Grand                                         add_fillGradient(aMergedArea, aNewStroke, *pStrokeGradient, rGeoRange);
747ddde725dSArmin Le Grand                                     }
748ddde725dSArmin Le Grand                                     else // if(pStrokePattern)
749ddde725dSArmin Le Grand                                     {
750ddde725dSArmin Le Grand                                         // create fill content with SVG pattern primitive. Use GeoRange
751ddde725dSArmin Le Grand                                         // from the expanded data, e.g. circle with extended geo by half linewidth
752ddde725dSArmin Le Grand                                         add_fillPatternTransform(aMergedArea, aNewStroke, *pStrokePattern, aMergedArea.getB2DRange());
753ddde725dSArmin Le Grand                                     }
754ddde725dSArmin Le Grand                                 }
755ddde725dSArmin Le Grand                             }
756ddde725dSArmin Le Grand                         }
757ddde725dSArmin Le Grand                         else // if(pStroke)
758ddde725dSArmin Le Grand                         {
759ddde725dSArmin Le Grand                             drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(aNewStroke, aNewLinePrimitive);
760ddde725dSArmin Le Grand                         }
761ddde725dSArmin Le Grand 
762ddde725dSArmin Le Grand                         if(aNewStroke.hasElements())
763ddde725dSArmin Le Grand                         {
764ddde725dSArmin Le Grand                             if(basegfx::fTools::less(fStrokeOpacity, 1.0))
765ddde725dSArmin Le Grand                             {
766ddde725dSArmin Le Grand                                 // embed in UnifiedTransparencePrimitive2D
767ddde725dSArmin Le Grand                                 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(
768ddde725dSArmin Le Grand                                     rTarget,
769ddde725dSArmin Le Grand                                     new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
770ddde725dSArmin Le Grand                                         aNewStroke,
771ddde725dSArmin Le Grand                                         1.0 - fStrokeOpacity));
772ddde725dSArmin Le Grand                             }
773ddde725dSArmin Le Grand                             else
774ddde725dSArmin Le Grand                             {
775ddde725dSArmin Le Grand                                 // append
776ddde725dSArmin Le Grand                                 drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aNewStroke);
777ddde725dSArmin Le Grand                             }
778ddde725dSArmin Le Grand                         }
779ddde725dSArmin Le Grand                     }
780ddde725dSArmin Le Grand                 }
781ddde725dSArmin Le Grand             }
782ddde725dSArmin Le Grand         }
783ddde725dSArmin Le Grand 
prepare_singleMarker(drawinglayer::primitive2d::Primitive2DSequence & rMarkerPrimitives,basegfx::B2DHomMatrix & rMarkerTransform,basegfx::B2DRange & rClipRange,const SvgMarkerNode & rMarker) const784ddde725dSArmin Le Grand         bool SvgStyleAttributes::prepare_singleMarker(
785ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rMarkerPrimitives,
786ddde725dSArmin Le Grand             basegfx::B2DHomMatrix& rMarkerTransform,
787ddde725dSArmin Le Grand             basegfx::B2DRange& rClipRange,
788ddde725dSArmin Le Grand             const SvgMarkerNode& rMarker) const
789ddde725dSArmin Le Grand         {
790ddde725dSArmin Le Grand             // reset return values
791ddde725dSArmin Le Grand             rMarkerTransform.identity();
792ddde725dSArmin Le Grand             rClipRange.reset();
793ddde725dSArmin Le Grand 
794ddde725dSArmin Le Grand             // get marker primitive representation
795ddde725dSArmin Le Grand             rMarkerPrimitives = rMarker.getMarkerPrimitives();
796ddde725dSArmin Le Grand 
797ddde725dSArmin Le Grand             if(rMarkerPrimitives.hasElements())
798ddde725dSArmin Le Grand             {
799ae8097f3SArmin Le Grand                 basegfx::B2DRange aPrimitiveRange(0.0, 0.0, 1.0, 1.0);
800ae8097f3SArmin Le Grand                 const basegfx::B2DRange* pViewBox = rMarker.getViewBox();
801ddde725dSArmin Le Grand 
802ae8097f3SArmin Le Grand                 if(pViewBox)
803ddde725dSArmin Le Grand                 {
804ae8097f3SArmin Le Grand                     aPrimitiveRange = *pViewBox;
805ddde725dSArmin Le Grand                 }
806ddde725dSArmin Le Grand 
807ddde725dSArmin Le Grand                 if(aPrimitiveRange.getWidth() > 0.0 && aPrimitiveRange.getHeight() > 0.0)
808ddde725dSArmin Le Grand                 {
809ae8097f3SArmin Le Grand                     double fTargetWidth(rMarker.getMarkerWidth().isSet() ? rMarker.getMarkerWidth().solve(mrOwner, xcoordinate) : 3.0);
810ae8097f3SArmin Le Grand                     double fTargetHeight(rMarker.getMarkerHeight().isSet() ? rMarker.getMarkerHeight().solve(mrOwner, xcoordinate) : 3.0);
811ae8097f3SArmin Le Grand                     const bool bStrokeWidth(SvgMarkerNode::strokeWidth == rMarker.getMarkerUnits());
812ddde725dSArmin Le Grand                     const double fStrokeWidth(getStrokeWidth().isSet() ? getStrokeWidth().solve(mrOwner, length) : 1.0);
813ddde725dSArmin Le Grand 
814ae8097f3SArmin Le Grand                     if(bStrokeWidth)
815ae8097f3SArmin Le Grand                     {
816ae8097f3SArmin Le Grand                         // relative to strokeWidth
817ddde725dSArmin Le Grand                         fTargetWidth *= fStrokeWidth;
818ddde725dSArmin Le Grand                         fTargetHeight *= fStrokeWidth;
819ddde725dSArmin Le Grand                     }
820ddde725dSArmin Le Grand 
821ddde725dSArmin Le Grand                     if(fTargetWidth > 0.0 && fTargetHeight > 0.0)
822ddde725dSArmin Le Grand                     {
823ddde725dSArmin Le Grand                         // create mapping
824ae8097f3SArmin Le Grand                         const basegfx::B2DRange aTargetRange(0.0, 0.0, fTargetWidth, fTargetHeight);
825ddde725dSArmin Le Grand                         const SvgAspectRatio& rRatio = rMarker.getSvgAspectRatio();
826ddde725dSArmin Le Grand 
827ddde725dSArmin Le Grand                         if(rRatio.isSet())
828ddde725dSArmin Le Grand                         {
829ddde725dSArmin Le Grand                             // let mapping be created from SvgAspectRatio
830ae8097f3SArmin Le Grand                             rMarkerTransform = rRatio.createMapping(aTargetRange, aPrimitiveRange);
831ddde725dSArmin Le Grand 
832ddde725dSArmin Le Grand                             if(rRatio.isMeetOrSlice())
833ddde725dSArmin Le Grand                             {
834ddde725dSArmin Le Grand                                 // need to clip
835ae8097f3SArmin Le Grand                                 rClipRange = aPrimitiveRange;
836ae8097f3SArmin Le Grand                             }
837ae8097f3SArmin Le Grand                         }
838ae8097f3SArmin Le Grand                         else
839ae8097f3SArmin Le Grand                         {
840ae8097f3SArmin Le Grand                             if(!pViewBox)
841ae8097f3SArmin Le Grand                             {
842ae8097f3SArmin Le Grand                                 if(bStrokeWidth)
843ae8097f3SArmin Le Grand                                 {
844ae8097f3SArmin Le Grand                                     // adapt to strokewidth if needed
845ae8097f3SArmin Le Grand                                     rMarkerTransform.scale(fStrokeWidth, fStrokeWidth);
846ddde725dSArmin Le Grand                                 }
847ddde725dSArmin Le Grand                             }
848ddde725dSArmin Le Grand                             else
849ddde725dSArmin Le Grand                             {
850ddde725dSArmin Le Grand                                 // choose default mapping
851ae8097f3SArmin Le Grand                                 rMarkerTransform = rRatio.createLinearMapping(aTargetRange, aPrimitiveRange);
852ddde725dSArmin Le Grand                             }
853ae8097f3SArmin Le Grand                         }
854ae8097f3SArmin Le Grand 
855ae8097f3SArmin Le Grand                         // get and apply reference point. Initially it's in marker local coordinate system
856ae8097f3SArmin Le Grand                         basegfx::B2DPoint aRefPoint(
857ae8097f3SArmin Le Grand                             rMarker.getRefX().isSet() ? rMarker.getRefX().solve(mrOwner, xcoordinate) : 0.0,
858ae8097f3SArmin Le Grand                             rMarker.getRefY().isSet() ? rMarker.getRefY().solve(mrOwner, ycoordinate) : 0.0);
859ae8097f3SArmin Le Grand 
860ae8097f3SArmin Le Grand                         // apply MarkerTransform to have it in mapped coordinates
861ae8097f3SArmin Le Grand                         aRefPoint *= rMarkerTransform;
862ae8097f3SArmin Le Grand 
863ae8097f3SArmin Le Grand                         // apply by moving RepPoint to (0.0)
864ae8097f3SArmin Le Grand                         rMarkerTransform.translate(-aRefPoint.getX(), -aRefPoint.getY());
865ddde725dSArmin Le Grand 
866ddde725dSArmin Le Grand                         return true;
867ddde725dSArmin Le Grand                     }
868ddde725dSArmin Le Grand                 }
869ddde725dSArmin Le Grand             }
870ddde725dSArmin Le Grand 
871ddde725dSArmin Le Grand             return false;
872ddde725dSArmin Le Grand         }
873ddde725dSArmin Le Grand 
add_markers(const basegfx::B2DPolyPolygon & rPath,drawinglayer::primitive2d::Primitive2DSequence & rTarget,const basegfx::tools::PointIndexSet * pHelpPointIndices) const874ddde725dSArmin Le Grand         void SvgStyleAttributes::add_markers(
875ddde725dSArmin Le Grand             const basegfx::B2DPolyPolygon& rPath,
8761f882ec4SArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
8771f882ec4SArmin Le Grand             const basegfx::tools::PointIndexSet* pHelpPointIndices) const
878ddde725dSArmin Le Grand         {
879ddde725dSArmin Le Grand             // try to access linked markers
880ddde725dSArmin Le Grand             const SvgMarkerNode* pStart = accessMarkerStartXLink();
881ddde725dSArmin Le Grand             const SvgMarkerNode* pMid = accessMarkerMidXLink();
882ddde725dSArmin Le Grand             const SvgMarkerNode* pEnd = accessMarkerEndXLink();
883ddde725dSArmin Le Grand 
884ddde725dSArmin Le Grand             if(pStart || pMid || pEnd)
885ddde725dSArmin Le Grand             {
886facb0eb6SArmin Le Grand                 const sal_uInt32 nSubPathCount(rPath.count());
887ddde725dSArmin Le Grand 
888facb0eb6SArmin Le Grand                 if(nSubPathCount)
889ddde725dSArmin Le Grand                 {
890facb0eb6SArmin Le Grand                     // remember prepared marker; pStart, pMid and pEnd may all be equal when
891facb0eb6SArmin Le Grand                     // only 'marker' was used instead of 'marker-start', 'marker-mid' or 'marker-end',
892facb0eb6SArmin Le Grand                     // see 'case SVGTokenMarker' in this file; thus in this case only one common
893facb0eb6SArmin Le Grand                     // marker in primitive form will be prepared
894ddde725dSArmin Le Grand                     const SvgMarkerNode* pPrepared = 0;
895ddde725dSArmin Le Grand 
896facb0eb6SArmin Le Grand                     // values for the prepared marker, results of prepare_singleMarker
897facb0eb6SArmin Le Grand                     drawinglayer::primitive2d::Primitive2DSequence aPreparedMarkerPrimitives;
898facb0eb6SArmin Le Grand                     basegfx::B2DHomMatrix aPreparedMarkerTransform;
899facb0eb6SArmin Le Grand                     basegfx::B2DRange aPreparedMarkerClipRange;
900facb0eb6SArmin Le Grand 
901facb0eb6SArmin Le Grand                     for (sal_uInt32 a(0); a < nSubPathCount; a++)
902ddde725dSArmin Le Grand                     {
903facb0eb6SArmin Le Grand                         // iterate over sub-paths
904facb0eb6SArmin Le Grand                         const basegfx::B2DPolygon aSubPolygonPath(rPath.getB2DPolygon(a));
905facb0eb6SArmin Le Grand                         const sal_uInt32 nSubPolygonPointCount(aSubPolygonPath.count());
906facb0eb6SArmin Le Grand                         const bool bSubPolygonPathIsClosed(aSubPolygonPath.isClosed());
907facb0eb6SArmin Le Grand 
908facb0eb6SArmin Le Grand                         if(nSubPolygonPointCount)
909ddde725dSArmin Le Grand                         {
910facb0eb6SArmin Le Grand                             // for each sub-path, create one marker per point (when closed, two markers
911facb0eb6SArmin Le Grand                             // need to pe created for the 1st point)
912facb0eb6SArmin Le Grand                             const sal_uInt32 nTargetMarkerCount(bSubPolygonPathIsClosed ? nSubPolygonPointCount + 1 : nSubPolygonPointCount);
913facb0eb6SArmin Le Grand 
914facb0eb6SArmin Le Grand                             for (sal_uInt32 b(0); b < nTargetMarkerCount; b++)
915facb0eb6SArmin Le Grand                             {
916facb0eb6SArmin Le Grand                                 const bool bIsFirstMarker(!a && !b);
917facb0eb6SArmin Le Grand                                 const bool bIsLastMarker(nSubPathCount - 1 == a && nTargetMarkerCount - 1 == b);
918facb0eb6SArmin Le Grand                                 const SvgMarkerNode* pNeeded = 0;
919facb0eb6SArmin Le Grand 
920facb0eb6SArmin Le Grand                                 if(bIsFirstMarker)
921facb0eb6SArmin Le Grand                                 {
922facb0eb6SArmin Le Grand                                     // 1st point in 1st sub-polygon, use pStart
923facb0eb6SArmin Le Grand                                     pNeeded = pStart;
924facb0eb6SArmin Le Grand                                 }
925facb0eb6SArmin Le Grand                                 else if(bIsLastMarker)
926facb0eb6SArmin Le Grand                                 {
927facb0eb6SArmin Le Grand                                     // last point in last sub-polygon, use pEnd
928facb0eb6SArmin Le Grand                                     pNeeded = pEnd;
929facb0eb6SArmin Le Grand                                 }
930facb0eb6SArmin Le Grand                                 else
931facb0eb6SArmin Le Grand                                 {
932facb0eb6SArmin Le Grand                                     // anything in-between, use pMid
933facb0eb6SArmin Le Grand                                     pNeeded = pMid;
934facb0eb6SArmin Le Grand                                 }
935facb0eb6SArmin Le Grand 
9361f882ec4SArmin Le Grand                                 if(pHelpPointIndices && !pHelpPointIndices->empty())
9371f882ec4SArmin Le Grand                                 {
9381f882ec4SArmin Le Grand                                     const basegfx::tools::PointIndexSet::const_iterator aFound(
9391f882ec4SArmin Le Grand                                         pHelpPointIndices->find(basegfx::tools::PointIndex(a, b)));
9401f882ec4SArmin Le Grand 
9411f882ec4SArmin Le Grand                                     if(aFound != pHelpPointIndices->end())
9421f882ec4SArmin Le Grand                                     {
9431f882ec4SArmin Le Grand                                         // this point is a pure helper point; do not create a marker for it
9441f882ec4SArmin Le Grand                                         continue;
9451f882ec4SArmin Le Grand                                     }
9461f882ec4SArmin Le Grand                                 }
9471f882ec4SArmin Le Grand 
948facb0eb6SArmin Le Grand                                 if(!pNeeded)
949facb0eb6SArmin Le Grand                                 {
950facb0eb6SArmin Le Grand                                     // no marker needs to be created for this point
951facb0eb6SArmin Le Grand                                     continue;
952facb0eb6SArmin Le Grand                                 }
953facb0eb6SArmin Le Grand 
954facb0eb6SArmin Le Grand                                 if(pPrepared != pNeeded)
955facb0eb6SArmin Le Grand                                 {
956facb0eb6SArmin Le Grand                                     // if needed marker is not yet prepared, do it now
957facb0eb6SArmin Le Grand                                     if(prepare_singleMarker(aPreparedMarkerPrimitives, aPreparedMarkerTransform, aPreparedMarkerClipRange, *pNeeded))
958facb0eb6SArmin Le Grand                                     {
959facb0eb6SArmin Le Grand                                         pPrepared = pNeeded;
960facb0eb6SArmin Le Grand                                     }
961facb0eb6SArmin Le Grand                                     else
962facb0eb6SArmin Le Grand                                     {
963facb0eb6SArmin Le Grand                                         // error: could not prepare given marker
964facb0eb6SArmin Le Grand                                         OSL_ENSURE(false, "OOps, could not prepare given marker as primitives (!)");
965facb0eb6SArmin Le Grand                                         pPrepared = 0;
966facb0eb6SArmin Le Grand                                         continue;
967ddde725dSArmin Le Grand                                     }
968ddde725dSArmin Le Grand                                 }
969ddde725dSArmin Le Grand 
970facb0eb6SArmin Le Grand                                 // prepare complete transform
971facb0eb6SArmin Le Grand                                 basegfx::B2DHomMatrix aCombinedTransform(aPreparedMarkerTransform);
972ddde725dSArmin Le Grand 
973facb0eb6SArmin Le Grand                                 // get rotation
974facb0eb6SArmin Le Grand                                 if(pPrepared->getOrientAuto())
975ddde725dSArmin Le Grand                                 {
976facb0eb6SArmin Le Grand                                     const sal_uInt32 nPointIndex(b % nSubPolygonPointCount);
977facb0eb6SArmin Le Grand 
978facb0eb6SArmin Le Grand                                     // get entering and leaving tangents; this will search backward/froward
979facb0eb6SArmin Le Grand                                     // in the polygon to find tangents unequal to zero, skipping empty edges
980facb0eb6SArmin Le Grand                                     // see basegfx descriptions)
981facb0eb6SArmin Le Grand                                     // Hint: Mozilla, Inkscape and others use only leaving tangent for start marker
982facb0eb6SArmin Le Grand                                     // and entering tangent for end marker. To achieve this (if wanted) it is possibe
983facb0eb6SArmin Le Grand                                     // to make the fetch of aEntering/aLeaving dependent on bIsFirstMarker/bIsLastMarker.
984facb0eb6SArmin Le Grand                                     // This is not done here, see comment 14 in task #1232379#
985facb0eb6SArmin Le Grand                                     // or http://www.w3.org/TR/SVG/painting.html#OrientAttribute
986facb0eb6SArmin Le Grand                                     basegfx::B2DVector aEntering(
987facb0eb6SArmin Le Grand                                         basegfx::tools::getTangentEnteringPoint(
988facb0eb6SArmin Le Grand                                             aSubPolygonPath,
989facb0eb6SArmin Le Grand                                             nPointIndex));
990facb0eb6SArmin Le Grand                                     basegfx::B2DVector aLeaving(
991facb0eb6SArmin Le Grand                                         basegfx::tools::getTangentLeavingPoint(
992facb0eb6SArmin Le Grand                                             aSubPolygonPath,
993facb0eb6SArmin Le Grand                                             nPointIndex));
994facb0eb6SArmin Le Grand                                     const bool bEntering(!aEntering.equalZero());
995facb0eb6SArmin Le Grand                                     const bool bLeaving(!aLeaving.equalZero());
996facb0eb6SArmin Le Grand 
997facb0eb6SArmin Le Grand                                     if(bEntering || bLeaving)
998facb0eb6SArmin Le Grand                                     {
999facb0eb6SArmin Le Grand                                         basegfx::B2DVector aSum(0.0, 0.0);
1000facb0eb6SArmin Le Grand 
1001facb0eb6SArmin Le Grand                                         if(bEntering)
1002facb0eb6SArmin Le Grand                                         {
1003facb0eb6SArmin Le Grand                                             aSum += aEntering.normalize();
1004ddde725dSArmin Le Grand                                         }
1005ddde725dSArmin Le Grand 
1006facb0eb6SArmin Le Grand                                         if(bLeaving)
1007ddde725dSArmin Le Grand                                         {
1008facb0eb6SArmin Le Grand                                             aSum += aLeaving.normalize();
1009facb0eb6SArmin Le Grand                                         }
1010facb0eb6SArmin Le Grand 
1011facb0eb6SArmin Le Grand                                         if(!aSum.equalZero())
1012ddde725dSArmin Le Grand                                         {
1013facb0eb6SArmin Le Grand                                             const double fAngle(atan2(aSum.getY(), aSum.getX()));
1014facb0eb6SArmin Le Grand 
1015facb0eb6SArmin Le Grand                                             // apply rotation
1016facb0eb6SArmin Le Grand                                             aCombinedTransform.rotate(fAngle);
1017facb0eb6SArmin Le Grand                                         }
1018facb0eb6SArmin Le Grand                                     }
1019facb0eb6SArmin Le Grand                                 }
1020facb0eb6SArmin Le Grand                                 else
1021facb0eb6SArmin Le Grand                                 {
1022facb0eb6SArmin Le Grand                                     // apply rotation
1023facb0eb6SArmin Le Grand                                     aCombinedTransform.rotate(pPrepared->getAngle());
1024facb0eb6SArmin Le Grand                                 }
1025facb0eb6SArmin Le Grand 
1026facb0eb6SArmin Le Grand                                 // get and apply target position
1027facb0eb6SArmin Le Grand                                 const basegfx::B2DPoint aPoint(aSubPolygonPath.getB2DPoint(b % nSubPolygonPointCount));
1028facb0eb6SArmin Le Grand 
1029facb0eb6SArmin Le Grand                                 aCombinedTransform.translate(aPoint.getX(), aPoint.getY());
1030facb0eb6SArmin Le Grand 
1031facb0eb6SArmin Le Grand                                 // prepare marker
1032facb0eb6SArmin Le Grand                                 drawinglayer::primitive2d::Primitive2DReference xMarker(
1033facb0eb6SArmin Le Grand                                     new drawinglayer::primitive2d::TransformPrimitive2D(
1034facb0eb6SArmin Le Grand                                         aCombinedTransform,
1035facb0eb6SArmin Le Grand                                         aPreparedMarkerPrimitives));
1036facb0eb6SArmin Le Grand 
1037facb0eb6SArmin Le Grand                                 if(!aPreparedMarkerClipRange.isEmpty())
1038facb0eb6SArmin Le Grand                                 {
1039facb0eb6SArmin Le Grand                                     // marker needs to be clipped, it's bigger as the mapping
1040facb0eb6SArmin Le Grand                                     basegfx::B2DPolyPolygon aClipPolygon(basegfx::tools::createPolygonFromRect(aPreparedMarkerClipRange));
1041facb0eb6SArmin Le Grand 
1042facb0eb6SArmin Le Grand                                     aClipPolygon.transform(aCombinedTransform);
1043facb0eb6SArmin Le Grand                                     xMarker = new drawinglayer::primitive2d::MaskPrimitive2D(
1044facb0eb6SArmin Le Grand                                         aClipPolygon,
1045facb0eb6SArmin Le Grand                                         drawinglayer::primitive2d::Primitive2DSequence(&xMarker, 1));
1046facb0eb6SArmin Le Grand                                 }
1047facb0eb6SArmin Le Grand 
1048facb0eb6SArmin Le Grand                                 // add marker
1049facb0eb6SArmin Le Grand                                 drawinglayer::primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(rTarget, xMarker);
1050ddde725dSArmin Le Grand                             }
1051ddde725dSArmin Le Grand                         }
1052ddde725dSArmin Le Grand                     }
1053ddde725dSArmin Le Grand                 }
1054ddde725dSArmin Le Grand             }
1055ddde725dSArmin Le Grand         }
1056ddde725dSArmin Le Grand 
add_path(const basegfx::B2DPolyPolygon & rPath,drawinglayer::primitive2d::Primitive2DSequence & rTarget,const basegfx::tools::PointIndexSet * pHelpPointIndices) const1057ddde725dSArmin Le Grand         void SvgStyleAttributes::add_path(
1058ddde725dSArmin Le Grand             const basegfx::B2DPolyPolygon& rPath,
10591f882ec4SArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
10601f882ec4SArmin Le Grand             const basegfx::tools::PointIndexSet* pHelpPointIndices) const
1061ddde725dSArmin Le Grand         {
1062ddde725dSArmin Le Grand             if(!rPath.count())
1063ddde725dSArmin Le Grand             {
1064ee346260SArmin Le Grand                 // no geometry at all
1065ddde725dSArmin Le Grand                 return;
1066ddde725dSArmin Le Grand             }
1067ddde725dSArmin Le Grand 
1068ddde725dSArmin Le Grand             const basegfx::B2DRange aGeoRange(rPath.getB2DRange());
1069ddde725dSArmin Le Grand 
1070ddde725dSArmin Le Grand             if(aGeoRange.isEmpty())
1071ddde725dSArmin Le Grand             {
1072ee346260SArmin Le Grand                 // no geometry range
1073ddde725dSArmin Le Grand                 return;
1074ddde725dSArmin Le Grand             }
1075ddde725dSArmin Le Grand 
1076ddde725dSArmin Le Grand             const double fOpacity(getOpacity().getNumber());
1077ddde725dSArmin Le Grand 
1078ddde725dSArmin Le Grand             if(basegfx::fTools::equalZero(fOpacity))
1079ddde725dSArmin Le Grand             {
1080ee346260SArmin Le Grand                 // not visible
1081ddde725dSArmin Le Grand                 return;
1082ddde725dSArmin Le Grand             }
1083ddde725dSArmin Le Grand 
1084ee346260SArmin Le Grand             // check if it's a line
1085ee346260SArmin Le Grand             const bool bNoWidth(basegfx::fTools::equalZero(aGeoRange.getWidth()));
1086ee346260SArmin Le Grand             const bool bNoHeight(basegfx::fTools::equalZero(aGeoRange.getHeight()));
1087ee346260SArmin Le Grand             const bool bIsTwoPointLine(1 == rPath.count()
1088ee346260SArmin Le Grand                 && !rPath.areControlPointsUsed()
1089ee346260SArmin Le Grand                 && 2 == rPath.getB2DPolygon(0).count());
1090ee346260SArmin Le Grand             const bool bIsLine(bIsTwoPointLine || bNoWidth || bNoHeight);
1091ee346260SArmin Le Grand 
1092ddde725dSArmin Le Grand             if(!bIsLine)
1093ddde725dSArmin Le Grand             {
1094ee346260SArmin Le Grand                 // create fill
1095ddde725dSArmin Le Grand                 basegfx::B2DPolyPolygon aPath(rPath);
1096ddde725dSArmin Le Grand                 const bool bNeedToCheckClipRule(SVGTokenPath == mrOwner.getType() || SVGTokenPolygon == mrOwner.getType());
109750b37974SArmin Le Grand                 const bool bClipPathIsNonzero(!bIsLine && bNeedToCheckClipRule && mbIsClipPathContent && FillRule_nonzero == maClipRule);
109850b37974SArmin Le Grand                 const bool bFillRuleIsNonzero(!bIsLine && bNeedToCheckClipRule && !mbIsClipPathContent && FillRule_nonzero == getFillRule());
1099ddde725dSArmin Le Grand 
1100ddde725dSArmin Le Grand                 if(bClipPathIsNonzero || bFillRuleIsNonzero)
1101ddde725dSArmin Le Grand                 {
1102ddde725dSArmin Le Grand                     // nonzero is wanted, solve geometrically (see description on basegfx)
1103ddde725dSArmin Le Grand                     aPath = basegfx::tools::createNonzeroConform(aPath);
1104ddde725dSArmin Le Grand                 }
1105ddde725dSArmin Le Grand 
1106ddde725dSArmin Le Grand                 add_fill(aPath, rTarget, aGeoRange);
1107ddde725dSArmin Le Grand             }
1108ddde725dSArmin Le Grand 
1109ee346260SArmin Le Grand             // create stroke
1110ddde725dSArmin Le Grand             add_stroke(rPath, rTarget, aGeoRange);
1111ddde725dSArmin Le Grand 
1112ddde725dSArmin Le Grand             // Svg supports markers for path, polygon, polyline and line
1113ddde725dSArmin Le Grand             if(SVGTokenPath == mrOwner.getType() ||         // path
1114ddde725dSArmin Le Grand                 SVGTokenPolygon == mrOwner.getType() ||     // polygon, polyline
1115ddde725dSArmin Le Grand                 SVGTokenLine == mrOwner.getType())          // line
1116ddde725dSArmin Le Grand             {
1117ddde725dSArmin Le Grand                 // try to add markers
11181f882ec4SArmin Le Grand                 add_markers(rPath, rTarget, pHelpPointIndices);
1119ddde725dSArmin Le Grand             }
1120ddde725dSArmin Le Grand         }
1121ddde725dSArmin Le Grand 
add_postProcess(drawinglayer::primitive2d::Primitive2DSequence & rTarget,const drawinglayer::primitive2d::Primitive2DSequence & rSource,const basegfx::B2DHomMatrix * pTransform) const1122ddde725dSArmin Le Grand         void SvgStyleAttributes::add_postProcess(
1123ddde725dSArmin Le Grand             drawinglayer::primitive2d::Primitive2DSequence& rTarget,
1124ddde725dSArmin Le Grand             const drawinglayer::primitive2d::Primitive2DSequence& rSource,
1125ddde725dSArmin Le Grand             const basegfx::B2DHomMatrix* pTransform) const
1126ddde725dSArmin Le Grand         {
1127ddde725dSArmin Le Grand             if(rSource.hasElements())
1128ddde725dSArmin Le Grand             {
1129ddde725dSArmin Le Grand                 const double fOpacity(getOpacity().getNumber());
1130ddde725dSArmin Le Grand 
1131ddde725dSArmin Le Grand                 if(basegfx::fTools::equalZero(fOpacity))
1132ddde725dSArmin Le Grand                 {
1133ddde725dSArmin Le Grand                     return;
1134ddde725dSArmin Le Grand                 }
1135ddde725dSArmin Le Grand 
1136ddde725dSArmin Le Grand                 drawinglayer::primitive2d::Primitive2DSequence aSource(rSource);
1137ddde725dSArmin Le Grand 
1138ddde725dSArmin Le Grand                 if(basegfx::fTools::less(fOpacity, 1.0))
1139ddde725dSArmin Le Grand                 {
1140ddde725dSArmin Le Grand                     // embed in UnifiedTransparencePrimitive2D
1141ddde725dSArmin Le Grand                     const drawinglayer::primitive2d::Primitive2DReference xRef(
1142ddde725dSArmin Le Grand                         new drawinglayer::primitive2d::UnifiedTransparencePrimitive2D(
1143ddde725dSArmin Le Grand                             aSource,
1144ddde725dSArmin Le Grand                             1.0 - fOpacity));
1145ddde725dSArmin Le Grand 
1146ddde725dSArmin Le Grand                     aSource = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
1147ddde725dSArmin Le Grand                 }
1148ddde725dSArmin Le Grand 
1149a275c134SArmin Le Grand                 if(pTransform)
1150a275c134SArmin Le Grand                 {
1151a275c134SArmin Le Grand                     // create embedding group element with transformation. This applies the given
1152a275c134SArmin Le Grand                     // transformation to the graphical content, but *not* to mask and/or clip (as needed)
1153a275c134SArmin Le Grand                     const drawinglayer::primitive2d::Primitive2DReference xRef(
1154a275c134SArmin Le Grand                         new drawinglayer::primitive2d::TransformPrimitive2D(
1155a275c134SArmin Le Grand                             *pTransform,
1156a275c134SArmin Le Grand                             aSource));
1157a275c134SArmin Le Grand 
1158a275c134SArmin Le Grand                     aSource = drawinglayer::primitive2d::Primitive2DSequence(&xRef, 1);
1159a275c134SArmin Le Grand                 }
1160a275c134SArmin Le Grand 
1161ddde725dSArmin Le Grand                 if(getClipPathXLink().getLength())
1162ddde725dSArmin Le Grand                 {
1163ddde725dSArmin Le Grand                     // try to access linked ClipPath
1164ddde725dSArmin Le Grand                     const SvgClipPathNode* mpClip = dynamic_cast< const SvgClipPathNode* >(mrOwner.getDocument().findSvgNodeById(getClipPathXLink()));
1165ddde725dSArmin Le Grand 
1166ddde725dSArmin Le Grand                     if(mpClip)
1167ddde725dSArmin Le Grand                     {
1168e90e3a55SArmin Le Grand                         // #i124852# transform may be needed when userSpaceOnUse
1169e90e3a55SArmin Le Grand                         mpClip->apply(aSource, pTransform);
1170ddde725dSArmin Le Grand                     }
1171ddde725dSArmin Le Grand                 }
1172ddde725dSArmin Le Grand 
1173ddde725dSArmin Le Grand                 if(aSource.hasElements()) // test again, applied clipPath may have lead to empty geometry
1174ddde725dSArmin Le Grand                 {
1175ddde725dSArmin Le Grand                     if(getMaskXLink().getLength())
1176ddde725dSArmin Le Grand                     {
1177ddde725dSArmin Le Grand                         // try to access linked Mask
1178ddde725dSArmin Le Grand                         const SvgMaskNode* mpMask = dynamic_cast< const SvgMaskNode* >(mrOwner.getDocument().findSvgNodeById(getMaskXLink()));
1179ddde725dSArmin Le Grand 
1180ddde725dSArmin Le Grand                         if(mpMask)
1181ddde725dSArmin Le Grand                         {
1182e90e3a55SArmin Le Grand                             // #i124852# transform may be needed when userSpaceOnUse
1183e90e3a55SArmin Le Grand                             mpMask->apply(aSource, pTransform);
1184ddde725dSArmin Le Grand                         }
1185ddde725dSArmin Le Grand                     }
1186ddde725dSArmin Le Grand 
1187ddde725dSArmin Le Grand                     if(aSource.hasElements()) // test again, applied mask may have lead to empty geometry
1188ddde725dSArmin Le Grand                     {
1189ddde725dSArmin Le Grand                         // append to current target
1190ddde725dSArmin Le Grand                         drawinglayer::primitive2d::appendPrimitive2DSequenceToPrimitive2DSequence(rTarget, aSource);
1191ddde725dSArmin Le Grand                     }
1192ddde725dSArmin Le Grand                 }
1193ddde725dSArmin Le Grand             }
1194ddde725dSArmin Le Grand         }
1195ddde725dSArmin Le Grand 
SvgStyleAttributes(SvgNode & rOwner)1196ddde725dSArmin Le Grand         SvgStyleAttributes::SvgStyleAttributes(SvgNode& rOwner)
1197ddde725dSArmin Le Grand         :   mrOwner(rOwner),
1198ddde725dSArmin Le Grand             mpCssStyleParent(0),
1199ddde725dSArmin Le Grand             maFill(),
1200ddde725dSArmin Le Grand             maStroke(),
1201ddde725dSArmin Le Grand             maStopColor(basegfx::BColor(0.0, 0.0, 0.0), true),
1202ddde725dSArmin Le Grand             maStrokeWidth(),
1203ddde725dSArmin Le Grand             maStopOpacity(),
1204ddde725dSArmin Le Grand             mpSvgGradientNodeFill(0),
1205ddde725dSArmin Le Grand             mpSvgGradientNodeStroke(0),
1206ddde725dSArmin Le Grand             mpSvgPatternNodeFill(0),
1207ddde725dSArmin Le Grand             mpSvgPatternNodeStroke(0),
1208ddde725dSArmin Le Grand             maFillOpacity(),
1209ddde725dSArmin Le Grand             maStrokeDasharray(),
1210ddde725dSArmin Le Grand             maStrokeDashOffset(),
1211ddde725dSArmin Le Grand             maStrokeLinecap(StrokeLinecap_notset),
1212ddde725dSArmin Le Grand             maStrokeLinejoin(StrokeLinejoin_notset),
1213ddde725dSArmin Le Grand             maStrokeMiterLimit(),
1214ddde725dSArmin Le Grand             maStrokeOpacity(),
1215ddde725dSArmin Le Grand             maFontFamily(),
1216ddde725dSArmin Le Grand             maFontSize(),
1217ddde725dSArmin Le Grand             maFontStretch(FontStretch_notset),
1218ddde725dSArmin Le Grand             maFontStyle(FontStyle_notset),
1219ddde725dSArmin Le Grand             maFontVariant(FontVariant_notset),
1220ddde725dSArmin Le Grand             maFontWeight(FontWeight_notset),
1221ddde725dSArmin Le Grand             maTextAlign(TextAlign_notset),
1222ddde725dSArmin Le Grand             maTextDecoration(TextDecoration_notset),
1223ddde725dSArmin Le Grand             maTextAnchor(TextAnchor_notset),
1224ddde725dSArmin Le Grand             maColor(),
1225ddde725dSArmin Le Grand             maOpacity(1.0),
1226025b0597SArmin Le Grand             maTitle(),
1227025b0597SArmin Le Grand             maDesc(),
1228ddde725dSArmin Le Grand             maClipPathXLink(),
1229ddde725dSArmin Le Grand             maMaskXLink(),
1230ddde725dSArmin Le Grand             maMarkerStartXLink(),
1231ddde725dSArmin Le Grand             mpMarkerStartXLink(0),
1232ddde725dSArmin Le Grand             maMarkerMidXLink(),
1233ddde725dSArmin Le Grand             mpMarkerMidXLink(0),
1234ddde725dSArmin Le Grand             maMarkerEndXLink(),
1235ddde725dSArmin Le Grand             mpMarkerEndXLink(0),
123650b37974SArmin Le Grand             maFillRule(FillRule_notset),
123750b37974SArmin Le Grand             maClipRule(FillRule_nonzero),
123886d02030SArmin Le Grand             maBaselineShift(BaselineShift_Baseline),
123986d02030SArmin Le Grand             maBaselineShiftNumber(0),
12405bc9d783SArmin Le Grand             mbIsClipPathContent(SVGTokenClipPathNode == mrOwner.getType()),
12415bc9d783SArmin Le Grand             mbStrokeDasharraySet(false)
1242ddde725dSArmin Le Grand         {
1243ddde725dSArmin Le Grand             if(!mbIsClipPathContent)
1244ddde725dSArmin Le Grand             {
1245ddde725dSArmin Le Grand                 const SvgStyleAttributes* pParentStyle = getParentStyle();
1246ddde725dSArmin Le Grand 
1247ddde725dSArmin Le Grand                 if(pParentStyle)
1248ddde725dSArmin Le Grand                 {
1249ddde725dSArmin Le Grand                     mbIsClipPathContent = pParentStyle->mbIsClipPathContent;
1250ddde725dSArmin Le Grand                 }
1251ddde725dSArmin Le Grand             }
1252ddde725dSArmin Le Grand         }
1253ddde725dSArmin Le Grand 
~SvgStyleAttributes()1254ddde725dSArmin Le Grand         SvgStyleAttributes::~SvgStyleAttributes()
1255ddde725dSArmin Le Grand         {
1256ddde725dSArmin Le Grand         }
1257ddde725dSArmin Le Grand 
parseStyleAttribute(const rtl::OUString &,SVGToken aSVGToken,const rtl::OUString & aContent,bool bCaseIndependent)1258*52cb04b8SArmin Le Grand         void SvgStyleAttributes::parseStyleAttribute(
1259*52cb04b8SArmin Le Grand             const rtl::OUString& /* rTokenName */,
1260*52cb04b8SArmin Le Grand             SVGToken aSVGToken,
1261*52cb04b8SArmin Le Grand             const rtl::OUString& aContent,
1262*52cb04b8SArmin Le Grand             bool bCaseIndependent)
1263ddde725dSArmin Le Grand         {
1264ddde725dSArmin Le Grand             switch(aSVGToken)
1265ddde725dSArmin Le Grand             {
1266ddde725dSArmin Le Grand                 case SVGTokenFill:
1267ddde725dSArmin Le Grand                 {
1268ddde725dSArmin Le Grand                     SvgPaint aSvgPaint;
1269ddde725dSArmin Le Grand                     rtl::OUString aURL;
1270ddde725dSArmin Le Grand 
1271*52cb04b8SArmin Le Grand                     if(readSvgPaint(aContent, aSvgPaint, aURL, bCaseIndependent))
1272ddde725dSArmin Le Grand                     {
1273ddde725dSArmin Le Grand                         setFill(aSvgPaint);
1274ddde725dSArmin Le Grand                     }
1275ddde725dSArmin Le Grand                     else if(aURL.getLength())
1276ddde725dSArmin Le Grand                     {
1277ddde725dSArmin Le Grand                         const SvgNode* pNode = mrOwner.getDocument().findSvgNodeById(aURL);
1278ddde725dSArmin Le Grand 
1279ddde725dSArmin Le Grand                         if(pNode)
1280ddde725dSArmin Le Grand                         {
1281ddde725dSArmin Le Grand                             if(SVGTokenLinearGradient == pNode->getType() || SVGTokenRadialGradient  == pNode->getType())
1282ddde725dSArmin Le Grand                             {
1283ddde725dSArmin Le Grand                                 setSvgGradientNodeFill(static_cast< const SvgGradientNode* >(pNode));
1284ddde725dSArmin Le Grand                             }
1285ddde725dSArmin Le Grand                             else if(SVGTokenPattern == pNode->getType())
1286ddde725dSArmin Le Grand                             {
1287ddde725dSArmin Le Grand                                 setSvgPatternNodeFill(static_cast< const SvgPatternNode* >(pNode));
1288ddde725dSArmin Le Grand                             }
1289ddde725dSArmin Le Grand                         }
1290ddde725dSArmin Le Grand                     }
1291ddde725dSArmin Le Grand                     break;
1292ddde725dSArmin Le Grand                 }
1293ddde725dSArmin Le Grand                 case SVGTokenFillOpacity:
1294ddde725dSArmin Le Grand                 {
1295ddde725dSArmin Le Grand                     SvgNumber aNum;
1296ddde725dSArmin Le Grand 
1297ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
1298ddde725dSArmin Le Grand                     {
1299ddde725dSArmin Le Grand                         if(aNum.isPositive())
1300ddde725dSArmin Le Grand                         {
1301ddde725dSArmin Le Grand                             setFillOpacity(aNum);
1302ddde725dSArmin Le Grand                         }
1303ddde725dSArmin Le Grand                     }
1304ddde725dSArmin Le Grand                     break;
1305ddde725dSArmin Le Grand                 }
1306ddde725dSArmin Le Grand                 case SVGTokenFillRule:
1307ddde725dSArmin Le Grand                 {
1308ddde725dSArmin Le Grand                     if(aContent.getLength())
1309ddde725dSArmin Le Grand                     {
1310ddde725dSArmin Le Grand                         if(aContent.match(commonStrings::aStrNonzero))
1311ddde725dSArmin Le Grand                         {
131250b37974SArmin Le Grand                             maFillRule = FillRule_nonzero;
1313ddde725dSArmin Le Grand                         }
1314ddde725dSArmin Le Grand                         else if(aContent.match(commonStrings::aStrEvenOdd))
1315ddde725dSArmin Le Grand                         {
131650b37974SArmin Le Grand                             maFillRule = FillRule_evenodd;
1317ddde725dSArmin Le Grand                         }
1318ddde725dSArmin Le Grand                     }
1319ddde725dSArmin Le Grand                     break;
1320ddde725dSArmin Le Grand                 }
1321ddde725dSArmin Le Grand                 case SVGTokenStroke:
1322ddde725dSArmin Le Grand                 {
1323ddde725dSArmin Le Grand                     SvgPaint aSvgPaint;
1324ddde725dSArmin Le Grand                     rtl::OUString aURL;
1325ddde725dSArmin Le Grand 
1326*52cb04b8SArmin Le Grand                     if(readSvgPaint(aContent, aSvgPaint, aURL, bCaseIndependent))
1327ddde725dSArmin Le Grand                     {
1328ddde725dSArmin Le Grand                         setStroke(aSvgPaint);
1329ddde725dSArmin Le Grand                     }
1330ddde725dSArmin Le Grand                     else if(aURL.getLength())
1331ddde725dSArmin Le Grand                     {
1332ddde725dSArmin Le Grand                         const SvgNode* pNode = mrOwner.getDocument().findSvgNodeById(aURL);
1333ddde725dSArmin Le Grand 
1334ddde725dSArmin Le Grand                         if(pNode)
1335ddde725dSArmin Le Grand                         {
1336ddde725dSArmin Le Grand                             if(SVGTokenLinearGradient == pNode->getType() || SVGTokenRadialGradient  == pNode->getType())
1337ddde725dSArmin Le Grand                             {
1338ddde725dSArmin Le Grand                                 setSvgGradientNodeStroke(static_cast< const SvgGradientNode* >(pNode));
1339ddde725dSArmin Le Grand                             }
1340ddde725dSArmin Le Grand                             else if(SVGTokenPattern == pNode->getType())
1341ddde725dSArmin Le Grand                             {
1342ddde725dSArmin Le Grand                                 setSvgPatternNodeStroke(static_cast< const SvgPatternNode* >(pNode));
1343ddde725dSArmin Le Grand                             }
1344ddde725dSArmin Le Grand                         }
1345ddde725dSArmin Le Grand                     }
1346ddde725dSArmin Le Grand                     break;
1347ddde725dSArmin Le Grand                 }
1348ddde725dSArmin Le Grand                 case SVGTokenStrokeDasharray:
1349ddde725dSArmin Le Grand                 {
1350ddde725dSArmin Le Grand                     if(aContent.getLength())
1351ddde725dSArmin Le Grand                     {
13525bc9d783SArmin Le Grand                         static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none"));
1353ddde725dSArmin Le Grand                         SvgNumberVector aVector;
1354ddde725dSArmin Le Grand 
13555bc9d783SArmin Le Grand                         if(aContent.match(aStrNone))
13565bc9d783SArmin Le Grand                         {
13575bc9d783SArmin Le Grand                             // #121221# The special value 'none' needs to be handled
13585bc9d783SArmin Le Grand                             // in the sense that *when* it is set, the parent shall not
13595bc9d783SArmin Le Grand                             // be used. Before this was only dependent on the array being
13605bc9d783SArmin Le Grand                             // empty
13615bc9d783SArmin Le Grand                             setStrokeDasharraySet(true);
13625bc9d783SArmin Le Grand                         }
13635bc9d783SArmin Le Grand                         else if(readSvgNumberVector(aContent, aVector))
1364ddde725dSArmin Le Grand                         {
1365ddde725dSArmin Le Grand                             setStrokeDasharray(aVector);
1366ddde725dSArmin Le Grand                         }
1367ddde725dSArmin Le Grand                     }
1368ddde725dSArmin Le Grand                     break;
1369ddde725dSArmin Le Grand                 }
1370ddde725dSArmin Le Grand                 case SVGTokenStrokeDashoffset:
1371ddde725dSArmin Le Grand                 {
1372ddde725dSArmin Le Grand                     SvgNumber aNum;
1373ddde725dSArmin Le Grand 
1374ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
1375ddde725dSArmin Le Grand                     {
1376ddde725dSArmin Le Grand                         if(aNum.isPositive())
1377ddde725dSArmin Le Grand                         {
1378ddde725dSArmin Le Grand                             setStrokeDashOffset(aNum);
1379ddde725dSArmin Le Grand                         }
1380ddde725dSArmin Le Grand                     }
1381ddde725dSArmin Le Grand                     break;
1382ddde725dSArmin Le Grand                 }
1383ddde725dSArmin Le Grand                 case SVGTokenStrokeLinecap:
1384ddde725dSArmin Le Grand                 {
1385ddde725dSArmin Le Grand                     if(aContent.getLength())
1386ddde725dSArmin Le Grand                     {
1387ddde725dSArmin Le Grand                         static rtl::OUString aStrButt(rtl::OUString::createFromAscii("butt"));
1388ddde725dSArmin Le Grand                         static rtl::OUString aStrRound(rtl::OUString::createFromAscii("round"));
1389ddde725dSArmin Le Grand                         static rtl::OUString aStrSquare(rtl::OUString::createFromAscii("square"));
1390ddde725dSArmin Le Grand 
1391ddde725dSArmin Le Grand                         if(aContent.match(aStrButt))
1392ddde725dSArmin Le Grand                         {
1393ddde725dSArmin Le Grand                             setStrokeLinecap(StrokeLinecap_butt);
1394ddde725dSArmin Le Grand                         }
1395ddde725dSArmin Le Grand                         else if(aContent.match(aStrRound))
1396ddde725dSArmin Le Grand                         {
1397ddde725dSArmin Le Grand                             setStrokeLinecap(StrokeLinecap_round);
1398ddde725dSArmin Le Grand                         }
1399ddde725dSArmin Le Grand                         else if(aContent.match(aStrSquare))
1400ddde725dSArmin Le Grand                         {
1401ddde725dSArmin Le Grand                             setStrokeLinecap(StrokeLinecap_square);
1402ddde725dSArmin Le Grand                         }
1403ddde725dSArmin Le Grand                     }
1404ddde725dSArmin Le Grand                     break;
1405ddde725dSArmin Le Grand                 }
1406ddde725dSArmin Le Grand                 case SVGTokenStrokeLinejoin:
1407ddde725dSArmin Le Grand                 {
1408ddde725dSArmin Le Grand                     if(aContent.getLength())
1409ddde725dSArmin Le Grand                     {
1410ddde725dSArmin Le Grand                         static rtl::OUString aStrMiter(rtl::OUString::createFromAscii("miter"));
1411ddde725dSArmin Le Grand                         static rtl::OUString aStrRound(rtl::OUString::createFromAscii("round"));
1412ddde725dSArmin Le Grand                         static rtl::OUString aStrBevel(rtl::OUString::createFromAscii("bevel"));
1413ddde725dSArmin Le Grand 
1414ddde725dSArmin Le Grand                         if(aContent.match(aStrMiter))
1415ddde725dSArmin Le Grand                         {
1416ddde725dSArmin Le Grand                             setStrokeLinejoin(StrokeLinejoin_miter);
1417ddde725dSArmin Le Grand                         }
1418ddde725dSArmin Le Grand                         else if(aContent.match(aStrRound))
1419ddde725dSArmin Le Grand                         {
1420ddde725dSArmin Le Grand                             setStrokeLinejoin(StrokeLinejoin_round);
1421ddde725dSArmin Le Grand                         }
1422ddde725dSArmin Le Grand                         else if(aContent.match(aStrBevel))
1423ddde725dSArmin Le Grand                         {
1424ddde725dSArmin Le Grand                             setStrokeLinejoin(StrokeLinejoin_bevel);
1425ddde725dSArmin Le Grand                         }
1426ddde725dSArmin Le Grand                     }
1427ddde725dSArmin Le Grand                     break;
1428ddde725dSArmin Le Grand                 }
1429ddde725dSArmin Le Grand                 case SVGTokenStrokeMiterlimit:
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                             setStrokeMiterLimit(aNum);
1438ddde725dSArmin Le Grand                         }
1439ddde725dSArmin Le Grand                     }
1440ddde725dSArmin Le Grand                     break;
1441ddde725dSArmin Le Grand                 }
1442ddde725dSArmin Le Grand                 case SVGTokenStrokeOpacity:
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                             setStrokeOpacity(aNum);
1451ddde725dSArmin Le Grand                         }
1452ddde725dSArmin Le Grand                     }
1453ddde725dSArmin Le Grand                     break;
1454ddde725dSArmin Le Grand                 }
1455ddde725dSArmin Le Grand                 case SVGTokenStrokeWidth:
1456ddde725dSArmin Le Grand                 {
1457ddde725dSArmin Le Grand                     SvgNumber aNum;
1458ddde725dSArmin Le Grand 
1459ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
1460ddde725dSArmin Le Grand                     {
1461ddde725dSArmin Le Grand                         if(aNum.isPositive())
1462ddde725dSArmin Le Grand                         {
1463ddde725dSArmin Le Grand                             setStrokeWidth(aNum);
1464ddde725dSArmin Le Grand                         }
1465ddde725dSArmin Le Grand                     }
1466ddde725dSArmin Le Grand                     break;
1467ddde725dSArmin Le Grand                 }
1468ddde725dSArmin Le Grand                 case SVGTokenStopColor:
1469ddde725dSArmin Le Grand                 {
1470ddde725dSArmin Le Grand                     SvgPaint aSvgPaint;
1471ddde725dSArmin Le Grand                     rtl::OUString aURL;
1472ddde725dSArmin Le Grand 
1473*52cb04b8SArmin Le Grand                     if(readSvgPaint(aContent, aSvgPaint, aURL, bCaseIndependent))
1474ddde725dSArmin Le Grand                     {
1475ddde725dSArmin Le Grand                         setStopColor(aSvgPaint);
1476ddde725dSArmin Le Grand                     }
1477ddde725dSArmin Le Grand                     break;
1478ddde725dSArmin Le Grand                 }
1479ddde725dSArmin Le Grand                 case SVGTokenStopOpacity:
1480ddde725dSArmin Le Grand                 {
1481ddde725dSArmin Le Grand                     SvgNumber aNum;
1482ddde725dSArmin Le Grand 
1483ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
1484ddde725dSArmin Le Grand                     {
1485ddde725dSArmin Le Grand                         if(aNum.isPositive())
1486ddde725dSArmin Le Grand                         {
1487ddde725dSArmin Le Grand                             setStopOpacity(aNum);
1488ddde725dSArmin Le Grand                         }
1489ddde725dSArmin Le Grand                     }
1490ddde725dSArmin Le Grand                     break;
1491ddde725dSArmin Le Grand                 }
1492ddde725dSArmin Le Grand                 case SVGTokenFont:
1493ddde725dSArmin Le Grand                 {
1494ddde725dSArmin Le Grand                     break;
1495ddde725dSArmin Le Grand                 }
1496ddde725dSArmin Le Grand                 case SVGTokenFontFamily:
1497ddde725dSArmin Le Grand                 {
1498ddde725dSArmin Le Grand                     SvgStringVector aSvgStringVector;
1499ddde725dSArmin Le Grand 
1500ddde725dSArmin Le Grand                     if(readSvgStringVector(aContent, aSvgStringVector))
1501ddde725dSArmin Le Grand                     {
1502ddde725dSArmin Le Grand                         setFontFamily(aSvgStringVector);
1503ddde725dSArmin Le Grand                     }
1504ddde725dSArmin Le Grand                     break;
1505ddde725dSArmin Le Grand                 }
1506ddde725dSArmin Le Grand                 case SVGTokenFontSize:
1507ddde725dSArmin Le Grand                 {
1508ddde725dSArmin Le Grand                     SvgNumber aNum;
1509ddde725dSArmin Le Grand 
1510ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
1511ddde725dSArmin Le Grand                     {
1512ddde725dSArmin Le Grand                         setFontSize(aNum);
1513ddde725dSArmin Le Grand                     }
1514ddde725dSArmin Le Grand                     break;
1515ddde725dSArmin Le Grand                 }
1516ddde725dSArmin Le Grand                 case SVGTokenFontSizeAdjust:
1517ddde725dSArmin Le Grand                 {
1518ddde725dSArmin Le Grand                     break;
1519ddde725dSArmin Le Grand                 }
1520ddde725dSArmin Le Grand                 case SVGTokenFontStretch:
1521ddde725dSArmin Le Grand                 {
1522ddde725dSArmin Le Grand                     if(aContent.getLength())
1523ddde725dSArmin Le Grand                     {
1524ddde725dSArmin Le Grand                         static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal"));
1525ddde725dSArmin Le Grand                         static rtl::OUString aStrWider(rtl::OUString::createFromAscii("wider"));
1526ddde725dSArmin Le Grand                         static rtl::OUString aStrNarrower(rtl::OUString::createFromAscii("narrower"));
1527ddde725dSArmin Le Grand                         static rtl::OUString aStrUltra_condensed(rtl::OUString::createFromAscii("ultra-condensed"));
1528ddde725dSArmin Le Grand                         static rtl::OUString aStrExtra_condensed(rtl::OUString::createFromAscii("extra-condensed"));
1529ddde725dSArmin Le Grand                         static rtl::OUString aStrCondensed(rtl::OUString::createFromAscii("condensed"));
1530ddde725dSArmin Le Grand                         static rtl::OUString aStrSemi_condensed(rtl::OUString::createFromAscii("semi-condensed"));
1531ddde725dSArmin Le Grand                         static rtl::OUString aStrSemi_expanded(rtl::OUString::createFromAscii("semi-expanded"));
1532ddde725dSArmin Le Grand                         static rtl::OUString aStrExpanded(rtl::OUString::createFromAscii("expanded"));
1533ddde725dSArmin Le Grand                         static rtl::OUString aStrExtra_expanded(rtl::OUString::createFromAscii("extra-expanded"));
1534ddde725dSArmin Le Grand                         static rtl::OUString aStrUltra_expanded(rtl::OUString::createFromAscii("ultra-expanded"));
1535ddde725dSArmin Le Grand 
1536ddde725dSArmin Le Grand                         if(aContent.match(aStrNormal))
1537ddde725dSArmin Le Grand                         {
1538ddde725dSArmin Le Grand                             setFontStretch(FontStretch_normal);
1539ddde725dSArmin Le Grand                         }
1540ddde725dSArmin Le Grand                         else if(aContent.match(aStrWider))
1541ddde725dSArmin Le Grand                         {
1542ddde725dSArmin Le Grand                             setFontStretch(FontStretch_wider);
1543ddde725dSArmin Le Grand                         }
1544ddde725dSArmin Le Grand                         else if(aContent.match(aStrNarrower))
1545ddde725dSArmin Le Grand                         {
1546ddde725dSArmin Le Grand                             setFontStretch(FontStretch_narrower);
1547ddde725dSArmin Le Grand                         }
1548ddde725dSArmin Le Grand                         else if(aContent.match(aStrUltra_condensed))
1549ddde725dSArmin Le Grand                         {
1550ddde725dSArmin Le Grand                             setFontStretch(FontStretch_ultra_condensed);
1551ddde725dSArmin Le Grand                         }
1552ddde725dSArmin Le Grand                         else if(aContent.match(aStrExtra_condensed))
1553ddde725dSArmin Le Grand                         {
1554ddde725dSArmin Le Grand                             setFontStretch(FontStretch_extra_condensed);
1555ddde725dSArmin Le Grand                         }
1556ddde725dSArmin Le Grand                         else if(aContent.match(aStrCondensed))
1557ddde725dSArmin Le Grand                         {
1558ddde725dSArmin Le Grand                             setFontStretch(FontStretch_condensed);
1559ddde725dSArmin Le Grand                         }
1560ddde725dSArmin Le Grand                         else if(aContent.match(aStrSemi_condensed))
1561ddde725dSArmin Le Grand                         {
1562ddde725dSArmin Le Grand                             setFontStretch(FontStretch_semi_condensed);
1563ddde725dSArmin Le Grand                         }
1564ddde725dSArmin Le Grand                         else if(aContent.match(aStrSemi_expanded))
1565ddde725dSArmin Le Grand                         {
1566ddde725dSArmin Le Grand                             setFontStretch(FontStretch_semi_expanded);
1567ddde725dSArmin Le Grand                         }
1568ddde725dSArmin Le Grand                         else if(aContent.match(aStrExpanded))
1569ddde725dSArmin Le Grand                         {
1570ddde725dSArmin Le Grand                             setFontStretch(FontStretch_expanded);
1571ddde725dSArmin Le Grand                         }
1572ddde725dSArmin Le Grand                         else if(aContent.match(aStrExtra_expanded))
1573ddde725dSArmin Le Grand                         {
1574ddde725dSArmin Le Grand                             setFontStretch(FontStretch_extra_expanded);
1575ddde725dSArmin Le Grand                         }
1576ddde725dSArmin Le Grand                         else if(aContent.match(aStrUltra_expanded))
1577ddde725dSArmin Le Grand                         {
1578ddde725dSArmin Le Grand                             setFontStretch(FontStretch_ultra_expanded);
1579ddde725dSArmin Le Grand                         }
1580ddde725dSArmin Le Grand                     }
1581ddde725dSArmin Le Grand                     break;
1582ddde725dSArmin Le Grand                 }
1583ddde725dSArmin Le Grand                 case SVGTokenFontStyle:
1584ddde725dSArmin Le Grand                 {
1585ddde725dSArmin Le Grand                     if(aContent.getLength())
1586ddde725dSArmin Le Grand                     {
1587ddde725dSArmin Le Grand                         static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal"));
1588ddde725dSArmin Le Grand                         static rtl::OUString aStrItalic(rtl::OUString::createFromAscii("italic"));
1589ddde725dSArmin Le Grand                         static rtl::OUString aStrOblique(rtl::OUString::createFromAscii("oblique"));
1590ddde725dSArmin Le Grand 
1591ddde725dSArmin Le Grand                         if(aContent.match(aStrNormal))
1592ddde725dSArmin Le Grand                         {
1593ddde725dSArmin Le Grand                             setFontStyle(FontStyle_normal);
1594ddde725dSArmin Le Grand                         }
1595ddde725dSArmin Le Grand                         else if(aContent.match(aStrItalic))
1596ddde725dSArmin Le Grand                         {
1597ddde725dSArmin Le Grand                             setFontStyle(FontStyle_italic);
1598ddde725dSArmin Le Grand                         }
1599ddde725dSArmin Le Grand                         else if(aContent.match(aStrOblique))
1600ddde725dSArmin Le Grand                         {
1601ddde725dSArmin Le Grand                             setFontStyle(FontStyle_oblique);
1602ddde725dSArmin Le Grand                         }
1603ddde725dSArmin Le Grand                     }
1604ddde725dSArmin Le Grand                     break;
1605ddde725dSArmin Le Grand                 }
1606ddde725dSArmin Le Grand                 case SVGTokenFontVariant:
1607ddde725dSArmin Le Grand                 {
1608ddde725dSArmin Le Grand                     if(aContent.getLength())
1609ddde725dSArmin Le Grand                     {
1610ddde725dSArmin Le Grand                         static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal"));
1611ddde725dSArmin Le Grand                         static rtl::OUString aStrSmallCaps(rtl::OUString::createFromAscii("small-caps"));
1612ddde725dSArmin Le Grand 
1613ddde725dSArmin Le Grand                         if(aContent.match(aStrNormal))
1614ddde725dSArmin Le Grand                         {
1615ddde725dSArmin Le Grand                             setFontVariant(FontVariant_normal);
1616ddde725dSArmin Le Grand                         }
1617ddde725dSArmin Le Grand                         else if(aContent.match(aStrSmallCaps))
1618ddde725dSArmin Le Grand                         {
1619ddde725dSArmin Le Grand                             setFontVariant(FontVariant_small_caps);
1620ddde725dSArmin Le Grand                         }
1621ddde725dSArmin Le Grand                     }
1622ddde725dSArmin Le Grand                     break;
1623ddde725dSArmin Le Grand                 }
1624ddde725dSArmin Le Grand                 case SVGTokenFontWeight:
1625ddde725dSArmin Le Grand                 {
1626ddde725dSArmin Le Grand                     if(aContent.getLength())
1627ddde725dSArmin Le Grand                     {
1628ddde725dSArmin Le Grand                         static rtl::OUString aStrNormal(rtl::OUString::createFromAscii("normal"));
1629ddde725dSArmin Le Grand                         static rtl::OUString aStrBold(rtl::OUString::createFromAscii("bold"));
1630ddde725dSArmin Le Grand                         static rtl::OUString aStrBolder(rtl::OUString::createFromAscii("bolder"));
1631ddde725dSArmin Le Grand                         static rtl::OUString aStrLighter(rtl::OUString::createFromAscii("lighter"));
1632ddde725dSArmin Le Grand                         static rtl::OUString aStr100(rtl::OUString::createFromAscii("100"));
1633ddde725dSArmin Le Grand                         static rtl::OUString aStr200(rtl::OUString::createFromAscii("200"));
1634ddde725dSArmin Le Grand                         static rtl::OUString aStr300(rtl::OUString::createFromAscii("300"));
1635ddde725dSArmin Le Grand                         static rtl::OUString aStr400(rtl::OUString::createFromAscii("400"));
1636ddde725dSArmin Le Grand                         static rtl::OUString aStr500(rtl::OUString::createFromAscii("500"));
1637ddde725dSArmin Le Grand                         static rtl::OUString aStr600(rtl::OUString::createFromAscii("600"));
1638ddde725dSArmin Le Grand                         static rtl::OUString aStr700(rtl::OUString::createFromAscii("700"));
1639ddde725dSArmin Le Grand                         static rtl::OUString aStr800(rtl::OUString::createFromAscii("800"));
1640ddde725dSArmin Le Grand                         static rtl::OUString aStr900(rtl::OUString::createFromAscii("900"));
1641ddde725dSArmin Le Grand 
1642ddde725dSArmin Le Grand                         if(aContent.match(aStr100))
1643ddde725dSArmin Le Grand                         {
1644ddde725dSArmin Le Grand                             setFontWeight(FontWeight_100);
1645ddde725dSArmin Le Grand                         }
1646ddde725dSArmin Le Grand                         else if(aContent.match(aStr200))
1647ddde725dSArmin Le Grand                         {
1648ddde725dSArmin Le Grand                             setFontWeight(FontWeight_200);
1649ddde725dSArmin Le Grand                         }
1650ddde725dSArmin Le Grand                         else if(aContent.match(aStr300))
1651ddde725dSArmin Le Grand                         {
1652ddde725dSArmin Le Grand                             setFontWeight(FontWeight_300);
1653ddde725dSArmin Le Grand                         }
1654ddde725dSArmin Le Grand                         else if(aContent.match(aStr400) || aContent.match(aStrNormal))
1655ddde725dSArmin Le Grand                         {
1656ddde725dSArmin Le Grand                             setFontWeight(FontWeight_400);
1657ddde725dSArmin Le Grand                         }
1658ddde725dSArmin Le Grand                         else if(aContent.match(aStr500))
1659ddde725dSArmin Le Grand                         {
1660ddde725dSArmin Le Grand                             setFontWeight(FontWeight_500);
1661ddde725dSArmin Le Grand                         }
1662ddde725dSArmin Le Grand                         else if(aContent.match(aStr600))
1663ddde725dSArmin Le Grand                         {
1664ddde725dSArmin Le Grand                             setFontWeight(FontWeight_600);
1665ddde725dSArmin Le Grand                         }
1666ddde725dSArmin Le Grand                         else if(aContent.match(aStr700) || aContent.match(aStrBold))
1667ddde725dSArmin Le Grand                         {
1668ddde725dSArmin Le Grand                             setFontWeight(FontWeight_700);
1669ddde725dSArmin Le Grand                         }
1670ddde725dSArmin Le Grand                         else if(aContent.match(aStr800))
1671ddde725dSArmin Le Grand                         {
1672ddde725dSArmin Le Grand                             setFontWeight(FontWeight_800);
1673ddde725dSArmin Le Grand                         }
1674ddde725dSArmin Le Grand                         else if(aContent.match(aStr900))
1675ddde725dSArmin Le Grand                         {
1676ddde725dSArmin Le Grand                             setFontWeight(FontWeight_900);
1677ddde725dSArmin Le Grand                         }
1678ddde725dSArmin Le Grand                         else if(aContent.match(aStrBolder))
1679ddde725dSArmin Le Grand                         {
1680ddde725dSArmin Le Grand                             setFontWeight(FontWeight_bolder);
1681ddde725dSArmin Le Grand                         }
1682ddde725dSArmin Le Grand                         else if(aContent.match(aStrLighter))
1683ddde725dSArmin Le Grand                         {
1684ddde725dSArmin Le Grand                             setFontWeight(FontWeight_lighter);
1685ddde725dSArmin Le Grand                         }
1686ddde725dSArmin Le Grand                     }
1687ddde725dSArmin Le Grand                     break;
1688ddde725dSArmin Le Grand                 }
1689ddde725dSArmin Le Grand                 case SVGTokenDirection:
1690ddde725dSArmin Le Grand                 {
1691ddde725dSArmin Le Grand                     break;
1692ddde725dSArmin Le Grand                 }
1693ddde725dSArmin Le Grand                 case SVGTokenLetterSpacing:
1694ddde725dSArmin Le Grand                 {
1695ddde725dSArmin Le Grand                     break;
1696ddde725dSArmin Le Grand                 }
1697ddde725dSArmin Le Grand                 case SVGTokenTextDecoration:
1698ddde725dSArmin Le Grand                 {
1699ddde725dSArmin Le Grand                     if(aContent.getLength())
1700ddde725dSArmin Le Grand                     {
1701ddde725dSArmin Le Grand                         static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none"));
1702ddde725dSArmin Le Grand                         static rtl::OUString aStrUnderline(rtl::OUString::createFromAscii("underline"));
1703ddde725dSArmin Le Grand                         static rtl::OUString aStrOverline(rtl::OUString::createFromAscii("overline"));
1704ddde725dSArmin Le Grand                         static rtl::OUString aStrLineThrough(rtl::OUString::createFromAscii("line-through"));
1705ddde725dSArmin Le Grand                         static rtl::OUString aStrBlink(rtl::OUString::createFromAscii("blink"));
1706ddde725dSArmin Le Grand 
1707ddde725dSArmin Le Grand                         if(aContent.match(aStrNone))
1708ddde725dSArmin Le Grand                         {
1709ddde725dSArmin Le Grand                             setTextDecoration(TextDecoration_none);
1710ddde725dSArmin Le Grand                         }
1711ddde725dSArmin Le Grand                         else if(aContent.match(aStrUnderline))
1712ddde725dSArmin Le Grand                         {
1713ddde725dSArmin Le Grand                             setTextDecoration(TextDecoration_underline);
1714ddde725dSArmin Le Grand                         }
1715ddde725dSArmin Le Grand                         else if(aContent.match(aStrOverline))
1716ddde725dSArmin Le Grand                         {
1717ddde725dSArmin Le Grand                             setTextDecoration(TextDecoration_overline);
1718ddde725dSArmin Le Grand                         }
1719ddde725dSArmin Le Grand                         else if(aContent.match(aStrLineThrough))
1720ddde725dSArmin Le Grand                         {
1721ddde725dSArmin Le Grand                             setTextDecoration(TextDecoration_line_through);
1722ddde725dSArmin Le Grand                         }
1723ddde725dSArmin Le Grand                         else if(aContent.match(aStrBlink))
1724ddde725dSArmin Le Grand                         {
1725ddde725dSArmin Le Grand                             setTextDecoration(TextDecoration_blink);
1726ddde725dSArmin Le Grand                         }
1727ddde725dSArmin Le Grand                     }
1728ddde725dSArmin Le Grand                     break;
1729ddde725dSArmin Le Grand                 }
1730ddde725dSArmin Le Grand                 case SVGTokenUnicodeBidi:
1731ddde725dSArmin Le Grand                 {
1732ddde725dSArmin Le Grand                     break;
1733ddde725dSArmin Le Grand                 }
1734ddde725dSArmin Le Grand                 case SVGTokenWordSpacing:
1735ddde725dSArmin Le Grand                 {
1736ddde725dSArmin Le Grand                     break;
1737ddde725dSArmin Le Grand                 }
1738ddde725dSArmin Le Grand                 case SVGTokenTextAnchor:
1739ddde725dSArmin Le Grand                 {
1740ddde725dSArmin Le Grand                     if(aContent.getLength())
1741ddde725dSArmin Le Grand                     {
1742ddde725dSArmin Le Grand                         static rtl::OUString aStrStart(rtl::OUString::createFromAscii("start"));
1743ddde725dSArmin Le Grand                         static rtl::OUString aStrMiddle(rtl::OUString::createFromAscii("middle"));
1744ddde725dSArmin Le Grand                         static rtl::OUString aStrEnd(rtl::OUString::createFromAscii("end"));
1745ddde725dSArmin Le Grand 
1746ddde725dSArmin Le Grand                         if(aContent.match(aStrStart))
1747ddde725dSArmin Le Grand                         {
1748ddde725dSArmin Le Grand                             setTextAnchor(TextAnchor_start);
1749ddde725dSArmin Le Grand                         }
1750ddde725dSArmin Le Grand                         else if(aContent.match(aStrMiddle))
1751ddde725dSArmin Le Grand                         {
1752ddde725dSArmin Le Grand                             setTextAnchor(TextAnchor_middle);
1753ddde725dSArmin Le Grand                         }
1754ddde725dSArmin Le Grand                         else if(aContent.match(aStrEnd))
1755ddde725dSArmin Le Grand                         {
1756ddde725dSArmin Le Grand                             setTextAnchor(TextAnchor_end);
1757ddde725dSArmin Le Grand                         }
1758ddde725dSArmin Le Grand                     }
1759ddde725dSArmin Le Grand                     break;
1760ddde725dSArmin Le Grand                 }
1761ddde725dSArmin Le Grand                 case SVGTokenTextAlign:
1762ddde725dSArmin Le Grand                 {
1763ddde725dSArmin Le Grand                     if(aContent.getLength())
1764ddde725dSArmin Le Grand                     {
1765ddde725dSArmin Le Grand                         static rtl::OUString aStrLeft(rtl::OUString::createFromAscii("left"));
1766ddde725dSArmin Le Grand                         static rtl::OUString aStrRight(rtl::OUString::createFromAscii("right"));
1767ddde725dSArmin Le Grand                         static rtl::OUString aStrCenter(rtl::OUString::createFromAscii("center"));
1768ddde725dSArmin Le Grand                         static rtl::OUString aStrJustify(rtl::OUString::createFromAscii("justify"));
1769ddde725dSArmin Le Grand 
1770ddde725dSArmin Le Grand                         if(aContent.match(aStrLeft))
1771ddde725dSArmin Le Grand                         {
1772ddde725dSArmin Le Grand                             setTextAlign(TextAlign_left);
1773ddde725dSArmin Le Grand                         }
1774ddde725dSArmin Le Grand                         else if(aContent.match(aStrRight))
1775ddde725dSArmin Le Grand                         {
1776ddde725dSArmin Le Grand                             setTextAlign(TextAlign_right);
1777ddde725dSArmin Le Grand                         }
1778ddde725dSArmin Le Grand                         else if(aContent.match(aStrCenter))
1779ddde725dSArmin Le Grand                         {
1780ddde725dSArmin Le Grand                             setTextAlign(TextAlign_center);
1781ddde725dSArmin Le Grand                         }
1782ddde725dSArmin Le Grand                         else if(aContent.match(aStrJustify))
1783ddde725dSArmin Le Grand                         {
1784ddde725dSArmin Le Grand                             setTextAlign(TextAlign_justify);
1785ddde725dSArmin Le Grand                         }
1786ddde725dSArmin Le Grand                     }
1787ddde725dSArmin Le Grand                     break;
1788ddde725dSArmin Le Grand                 }
1789ddde725dSArmin Le Grand                 case SVGTokenColor:
1790ddde725dSArmin Le Grand                 {
1791ddde725dSArmin Le Grand                     SvgPaint aSvgPaint;
1792ddde725dSArmin Le Grand                     rtl::OUString aURL;
1793ddde725dSArmin Le Grand 
1794*52cb04b8SArmin Le Grand                     if(readSvgPaint(aContent, aSvgPaint, aURL, bCaseIndependent))
1795ddde725dSArmin Le Grand                     {
1796ddde725dSArmin Le Grand                         setColor(aSvgPaint);
1797ddde725dSArmin Le Grand                     }
1798ddde725dSArmin Le Grand                     break;
1799ddde725dSArmin Le Grand                 }
1800ddde725dSArmin Le Grand                 case SVGTokenOpacity:
1801ddde725dSArmin Le Grand                 {
1802ddde725dSArmin Le Grand                     SvgNumber aNum;
1803ddde725dSArmin Le Grand 
1804ddde725dSArmin Le Grand                     if(readSingleNumber(aContent, aNum))
1805ddde725dSArmin Le Grand                     {
1806ddde725dSArmin Le Grand                         setOpacity(SvgNumber(basegfx::clamp(aNum.getNumber(), 0.0, 1.0), aNum.getUnit(), aNum.isSet()));
1807ddde725dSArmin Le Grand                     }
1808ddde725dSArmin Le Grand                     break;
1809ddde725dSArmin Le Grand                 }
1810025b0597SArmin Le Grand                 case SVGTokenTitle:
1811025b0597SArmin Le Grand                 {
1812025b0597SArmin Le Grand                     setTitle(aContent);
1813025b0597SArmin Le Grand                     break;
1814025b0597SArmin Le Grand                 }
1815025b0597SArmin Le Grand                 case SVGTokenDesc:
1816025b0597SArmin Le Grand                 {
1817025b0597SArmin Le Grand                     setDesc(aContent);
1818025b0597SArmin Le Grand                     break;
1819025b0597SArmin Le Grand                 }
1820ddde725dSArmin Le Grand                 case SVGTokenClipPathProperty:
1821ddde725dSArmin Le Grand                 {
1822ddde725dSArmin Le Grand                     readLocalUrl(aContent, maClipPathXLink);
1823ddde725dSArmin Le Grand                     break;
1824ddde725dSArmin Le Grand                 }
1825ddde725dSArmin Le Grand                 case SVGTokenMask:
1826ddde725dSArmin Le Grand                 {
1827ddde725dSArmin Le Grand                     readLocalUrl(aContent, maMaskXLink);
1828ddde725dSArmin Le Grand                     break;
1829ddde725dSArmin Le Grand                 }
1830ddde725dSArmin Le Grand                 case SVGTokenClipRule:
1831ddde725dSArmin Le Grand                 {
1832ddde725dSArmin Le Grand                     if(aContent.getLength())
1833ddde725dSArmin Le Grand                     {
1834ddde725dSArmin Le Grand                         if(aContent.match(commonStrings::aStrNonzero))
1835ddde725dSArmin Le Grand                         {
183650b37974SArmin Le Grand                             maClipRule = FillRule_nonzero;
1837ddde725dSArmin Le Grand                         }
1838ddde725dSArmin Le Grand                         else if(aContent.match(commonStrings::aStrEvenOdd))
1839ddde725dSArmin Le Grand                         {
184050b37974SArmin Le Grand                             maClipRule = FillRule_evenodd;
1841ddde725dSArmin Le Grand                         }
1842ddde725dSArmin Le Grand                     }
1843ddde725dSArmin Le Grand                     break;
1844ddde725dSArmin Le Grand                 }
1845ddde725dSArmin Le Grand                 case SVGTokenMarker:
1846ddde725dSArmin Le Grand                 {
1847ddde725dSArmin Le Grand                     readLocalUrl(aContent, maMarkerEndXLink);
1848ddde725dSArmin Le Grand                     maMarkerStartXLink = maMarkerMidXLink = maMarkerEndXLink;
1849ddde725dSArmin Le Grand                     break;
1850ddde725dSArmin Le Grand                 }
1851ddde725dSArmin Le Grand                 case SVGTokenMarkerStart:
1852ddde725dSArmin Le Grand                 {
1853ddde725dSArmin Le Grand                     readLocalUrl(aContent, maMarkerStartXLink);
1854ddde725dSArmin Le Grand                     break;
1855ddde725dSArmin Le Grand                 }
1856ddde725dSArmin Le Grand                 case SVGTokenMarkerMid:
1857ddde725dSArmin Le Grand                 {
1858ddde725dSArmin Le Grand                     readLocalUrl(aContent, maMarkerMidXLink);
1859ddde725dSArmin Le Grand                     break;
1860ddde725dSArmin Le Grand                 }
1861ddde725dSArmin Le Grand                 case SVGTokenMarkerEnd:
1862ddde725dSArmin Le Grand                 {
1863ddde725dSArmin Le Grand                     readLocalUrl(aContent, maMarkerEndXLink);
1864ddde725dSArmin Le Grand                     break;
1865ddde725dSArmin Le Grand                 }
186601e92ad6SArmin Le Grand                 case SVGTokenDisplay:
186701e92ad6SArmin Le Grand                 {
186801e92ad6SArmin Le Grand                     // There may be display:none statements inside of style defines, e.g. the following line:
186901e92ad6SArmin Le Grand                     // style="display:none"
187001e92ad6SArmin Le Grand                     // taken from a svg example; this needs to be parsed and set at the owning node. Do not call
187101e92ad6SArmin Le Grand                     // mrOwner.parseAttribute(...) here, this would lead to a recursion
187201e92ad6SArmin Le Grand                     if(aContent.getLength())
187301e92ad6SArmin Le Grand                     {
187401e92ad6SArmin Le Grand                         mrOwner.setDisplay(getDisplayFromContent(aContent));
187501e92ad6SArmin Le Grand                     }
187601e92ad6SArmin Le Grand                     break;
187701e92ad6SArmin Le Grand                 }
187886d02030SArmin Le Grand                 case SVGTokenBaselineShift:
187986d02030SArmin Le Grand                 {
188086d02030SArmin Le Grand                     if(aContent.getLength())
188186d02030SArmin Le Grand                     {
188286d02030SArmin Le Grand                         static rtl::OUString aStrSub(rtl::OUString::createFromAscii("sub"));
188386d02030SArmin Le Grand                         static rtl::OUString aStrSuper(rtl::OUString::createFromAscii("super"));
188486d02030SArmin Le Grand                         SvgNumber aNum;
188586d02030SArmin Le Grand 
188686d02030SArmin Le Grand                         if(aContent.match(aStrSub))
188786d02030SArmin Le Grand                         {
188886d02030SArmin Le Grand                             setBaselineShift(BaselineShift_Sub);
188986d02030SArmin Le Grand                         }
189086d02030SArmin Le Grand                         else if(aContent.match(aStrSuper))
189186d02030SArmin Le Grand                         {
189286d02030SArmin Le Grand                             setBaselineShift(BaselineShift_Super);
189386d02030SArmin Le Grand                         }
189486d02030SArmin Le Grand                         else if(readSingleNumber(aContent, aNum))
189586d02030SArmin Le Grand                         {
189686d02030SArmin Le Grand                             setBaselineShiftNumber(aNum);
189786d02030SArmin Le Grand 
189886d02030SArmin Le Grand                             if(Unit_percent == aNum.getUnit())
189986d02030SArmin Le Grand                             {
190086d02030SArmin Le Grand                                 setBaselineShift(BaselineShift_Percentage);
190186d02030SArmin Le Grand                             }
190286d02030SArmin Le Grand                             else
190386d02030SArmin Le Grand                             {
190486d02030SArmin Le Grand                                 setBaselineShift(BaselineShift_Length);
190586d02030SArmin Le Grand                             }
190686d02030SArmin Le Grand                         }
190786d02030SArmin Le Grand                         else
190886d02030SArmin Le Grand                         {
190986d02030SArmin Le Grand                             // no BaselineShift or inherit (which is automatically)
191086d02030SArmin Le Grand                             setBaselineShift(BaselineShift_Baseline);
191186d02030SArmin Le Grand                         }
191286d02030SArmin Le Grand                     }
191386d02030SArmin Le Grand                     break;
191486d02030SArmin Le Grand                 }
1915e2bf1e9dSArmin Le Grand                 default:
1916e2bf1e9dSArmin Le Grand                 {
1917e2bf1e9dSArmin Le Grand                     break;
1918e2bf1e9dSArmin Le Grand                 }
1919ddde725dSArmin Le Grand             }
1920ddde725dSArmin Le Grand         }
1921ddde725dSArmin Le Grand 
19224374d266SArmin Le Grand         // #125258# ask if fill is a direct hard attribute (no hierarchy)
isFillSet() const19234374d266SArmin Le Grand         bool SvgStyleAttributes::isFillSet() const
19244374d266SArmin Le Grand         {
19254374d266SArmin Le Grand             if(mbIsClipPathContent)
19264374d266SArmin Le Grand             {
19274374d266SArmin Le Grand                 return false;
19284374d266SArmin Le Grand             }
19294374d266SArmin Le Grand             else if(maFill.isSet())
19304374d266SArmin Le Grand             {
19314374d266SArmin Le Grand                 return true;
19324374d266SArmin Le Grand             }
19334374d266SArmin Le Grand 
19344374d266SArmin Le Grand             return false;
19354374d266SArmin Le Grand         }
19364374d266SArmin Le Grand 
getFill() const1937ddde725dSArmin Le Grand         const basegfx::BColor* SvgStyleAttributes::getFill() const
1938ddde725dSArmin Le Grand         {
1939ddde725dSArmin Le Grand             if(mbIsClipPathContent)
1940ddde725dSArmin Le Grand             {
1941ddde725dSArmin Le Grand                 static basegfx::BColor aBlack(0.0, 0.0, 0.0);
1942ddde725dSArmin Le Grand 
1943ddde725dSArmin Le Grand                 return &aBlack;
1944ddde725dSArmin Le Grand             }
1945ddde725dSArmin Le Grand             else if(maFill.isSet())
1946ddde725dSArmin Le Grand             {
1947ddde725dSArmin Le Grand                 if(maFill.isCurrent())
1948ddde725dSArmin Le Grand                 {
1949ddde725dSArmin Le Grand                     return getColor();
1950ddde725dSArmin Le Grand                 }
1951ddde725dSArmin Le Grand                 else if(maFill.isOn())
1952ddde725dSArmin Le Grand                 {
1953ddde725dSArmin Le Grand                     return &maFill.getBColor();
1954ddde725dSArmin Le Grand                 }
1955ddde725dSArmin Le Grand             }
1956ddde725dSArmin Le Grand             else
1957ddde725dSArmin Le Grand             {
1958ddde725dSArmin Le Grand                 const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
1959ddde725dSArmin Le Grand 
1960ddde725dSArmin Le Grand                 if(pSvgStyleAttributes)
1961ddde725dSArmin Le Grand                 {
1962ddde725dSArmin Le Grand                     return pSvgStyleAttributes->getFill();
1963ddde725dSArmin Le Grand                 }
1964ddde725dSArmin Le Grand             }
1965ddde725dSArmin Le Grand 
1966ddde725dSArmin Le Grand             return 0;
1967ddde725dSArmin Le Grand         }
1968ddde725dSArmin Le Grand 
getStroke() const1969ddde725dSArmin Le Grand         const basegfx::BColor* SvgStyleAttributes::getStroke() const
1970ddde725dSArmin Le Grand         {
1971ddde725dSArmin Le Grand             if(mbIsClipPathContent)
1972ddde725dSArmin Le Grand             {
1973ddde725dSArmin Le Grand                 return 0;
1974ddde725dSArmin Le Grand             }
1975ddde725dSArmin Le Grand             else if(maStroke.isSet())
1976ddde725dSArmin Le Grand             {
1977ddde725dSArmin Le Grand                 if(maStroke.isCurrent())
1978ddde725dSArmin Le Grand                 {
1979ddde725dSArmin Le Grand                     return getColor();
1980ddde725dSArmin Le Grand                 }
1981ddde725dSArmin Le Grand                 else if(maStroke.isOn())
1982ddde725dSArmin Le Grand                 {
1983ddde725dSArmin Le Grand                     return &maStroke.getBColor();
1984ddde725dSArmin Le Grand                 }
1985ddde725dSArmin Le Grand             }
1986ddde725dSArmin Le Grand             else
1987ddde725dSArmin Le Grand             {
1988ddde725dSArmin Le Grand                 const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
1989ddde725dSArmin Le Grand 
1990ddde725dSArmin Le Grand                 if(pSvgStyleAttributes)
1991ddde725dSArmin Le Grand                 {
1992ddde725dSArmin Le Grand                     return pSvgStyleAttributes->getStroke();
1993ddde725dSArmin Le Grand                 }
1994ddde725dSArmin Le Grand             }
1995ddde725dSArmin Le Grand 
1996ddde725dSArmin Le Grand             return 0;
1997ddde725dSArmin Le Grand         }
1998ddde725dSArmin Le Grand 
getStopColor() const1999ddde725dSArmin Le Grand         const basegfx::BColor& SvgStyleAttributes::getStopColor() const
2000ddde725dSArmin Le Grand         {
2001ddde725dSArmin Le Grand             if(maStopColor.isCurrent())
2002ddde725dSArmin Le Grand             {
2003ddde725dSArmin Le Grand                 return *getColor();
2004ddde725dSArmin Le Grand             }
2005ddde725dSArmin Le Grand             else
2006ddde725dSArmin Le Grand             {
2007ddde725dSArmin Le Grand                 return maStopColor.getBColor();
2008ddde725dSArmin Le Grand             }
2009ddde725dSArmin Le Grand         }
2010ddde725dSArmin Le Grand 
getSvgGradientNodeFill() const2011ddde725dSArmin Le Grand         const SvgGradientNode* SvgStyleAttributes::getSvgGradientNodeFill() const
2012ddde725dSArmin Le Grand         {
2013ddde725dSArmin Le Grand             if(mbIsClipPathContent)
2014ddde725dSArmin Le Grand             {
2015ddde725dSArmin Le Grand                 return 0;
2016ddde725dSArmin Le Grand             }
2017ddde725dSArmin Le Grand             else if(mpSvgGradientNodeFill)
2018ddde725dSArmin Le Grand             {
2019ddde725dSArmin Le Grand                 return mpSvgGradientNodeFill;
2020ddde725dSArmin Le Grand             }
2021ddde725dSArmin Le Grand             else
2022ddde725dSArmin Le Grand             {
2023ddde725dSArmin Le Grand                 const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2024ddde725dSArmin Le Grand 
2025ddde725dSArmin Le Grand                 if(pSvgStyleAttributes)
2026ddde725dSArmin Le Grand                 {
2027ddde725dSArmin Le Grand                     return pSvgStyleAttributes->getSvgGradientNodeFill();
2028ddde725dSArmin Le Grand                 }
2029ddde725dSArmin Le Grand             }
2030ddde725dSArmin Le Grand 
2031ddde725dSArmin Le Grand             return 0;
2032ddde725dSArmin Le Grand         }
2033ddde725dSArmin Le Grand 
getSvgGradientNodeStroke() const2034ddde725dSArmin Le Grand         const SvgGradientNode* SvgStyleAttributes::getSvgGradientNodeStroke() const
2035ddde725dSArmin Le Grand         {
2036ddde725dSArmin Le Grand             if(mbIsClipPathContent)
2037ddde725dSArmin Le Grand             {
2038ddde725dSArmin Le Grand                 return 0;
2039ddde725dSArmin Le Grand             }
2040ddde725dSArmin Le Grand             else if(mpSvgGradientNodeStroke)
2041ddde725dSArmin Le Grand             {
2042ddde725dSArmin Le Grand                 return mpSvgGradientNodeStroke;
2043ddde725dSArmin Le Grand             }
2044ddde725dSArmin Le Grand             else
2045ddde725dSArmin Le Grand             {
2046ddde725dSArmin Le Grand                 const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2047ddde725dSArmin Le Grand 
2048ddde725dSArmin Le Grand                 if(pSvgStyleAttributes)
2049ddde725dSArmin Le Grand                 {
2050ddde725dSArmin Le Grand                     return pSvgStyleAttributes->getSvgGradientNodeStroke();
2051ddde725dSArmin Le Grand                 }
2052ddde725dSArmin Le Grand             }
2053ddde725dSArmin Le Grand 
2054ddde725dSArmin Le Grand             return 0;
2055ddde725dSArmin Le Grand         }
2056ddde725dSArmin Le Grand 
getSvgPatternNodeFill() const2057ddde725dSArmin Le Grand         const SvgPatternNode* SvgStyleAttributes::getSvgPatternNodeFill() const
2058ddde725dSArmin Le Grand         {
2059ddde725dSArmin Le Grand             if(mbIsClipPathContent)
2060ddde725dSArmin Le Grand             {
2061ddde725dSArmin Le Grand                 return 0;
2062ddde725dSArmin Le Grand             }
2063ddde725dSArmin Le Grand             else if(mpSvgPatternNodeFill)
2064ddde725dSArmin Le Grand             {
2065ddde725dSArmin Le Grand                 return mpSvgPatternNodeFill;
2066ddde725dSArmin Le Grand             }
2067ddde725dSArmin Le Grand             else
2068ddde725dSArmin Le Grand             {
2069ddde725dSArmin Le Grand                 const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2070ddde725dSArmin Le Grand 
2071ddde725dSArmin Le Grand                 if(pSvgStyleAttributes)
2072ddde725dSArmin Le Grand                 {
2073ddde725dSArmin Le Grand                     return pSvgStyleAttributes->getSvgPatternNodeFill();
2074ddde725dSArmin Le Grand                 }
2075ddde725dSArmin Le Grand             }
2076ddde725dSArmin Le Grand 
2077ddde725dSArmin Le Grand             return 0;
2078ddde725dSArmin Le Grand         }
2079ddde725dSArmin Le Grand 
getSvgPatternNodeStroke() const2080ddde725dSArmin Le Grand         const SvgPatternNode* SvgStyleAttributes::getSvgPatternNodeStroke() const
2081ddde725dSArmin Le Grand         {
2082ddde725dSArmin Le Grand             if(mbIsClipPathContent)
2083ddde725dSArmin Le Grand             {
2084ddde725dSArmin Le Grand                 return 0;
2085ddde725dSArmin Le Grand             }
2086ddde725dSArmin Le Grand             else if(mpSvgPatternNodeStroke)
2087ddde725dSArmin Le Grand             {
2088ddde725dSArmin Le Grand                 return mpSvgPatternNodeStroke;
2089ddde725dSArmin Le Grand             }
2090ddde725dSArmin Le Grand             else
2091ddde725dSArmin Le Grand             {
2092ddde725dSArmin Le Grand                 const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2093ddde725dSArmin Le Grand 
2094ddde725dSArmin Le Grand                 if(pSvgStyleAttributes)
2095ddde725dSArmin Le Grand                 {
2096ddde725dSArmin Le Grand                     return pSvgStyleAttributes->getSvgPatternNodeStroke();
2097ddde725dSArmin Le Grand                 }
2098ddde725dSArmin Le Grand             }
2099ddde725dSArmin Le Grand 
2100ddde725dSArmin Le Grand             return 0;
2101ddde725dSArmin Le Grand         }
2102ddde725dSArmin Le Grand 
getStrokeWidth() const21030813cdfdSArmin Le Grand         SvgNumber SvgStyleAttributes::getStrokeWidth() const
2104ddde725dSArmin Le Grand         {
2105ddde725dSArmin Le Grand             if(mbIsClipPathContent)
2106ddde725dSArmin Le Grand             {
2107ddde725dSArmin Le Grand                 return SvgNumber(0.0);
2108ddde725dSArmin Le Grand             }
2109ddde725dSArmin Le Grand             else if(maStrokeWidth.isSet())
2110ddde725dSArmin Le Grand             {
2111ddde725dSArmin Le Grand                 return maStrokeWidth;
2112ddde725dSArmin Le Grand             }
2113ddde725dSArmin Le Grand 
2114ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2115ddde725dSArmin Le Grand 
2116ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2117ddde725dSArmin Le Grand             {
2118ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getStrokeWidth();
2119ddde725dSArmin Le Grand             }
2120ddde725dSArmin Le Grand 
2121ddde725dSArmin Le Grand             // default is 1
2122ddde725dSArmin Le Grand             return SvgNumber(1.0);
2123ddde725dSArmin Le Grand         }
2124ddde725dSArmin Le Grand 
getStopOpacity() const21250813cdfdSArmin Le Grand         SvgNumber SvgStyleAttributes::getStopOpacity() const
2126ddde725dSArmin Le Grand         {
2127ddde725dSArmin Le Grand             if(maStopOpacity.isSet())
2128ddde725dSArmin Le Grand             {
2129ddde725dSArmin Le Grand                 return maStopOpacity;
2130ddde725dSArmin Le Grand             }
2131ddde725dSArmin Le Grand 
2132ddde725dSArmin Le Grand             // default is 1
2133ddde725dSArmin Le Grand             return SvgNumber(1.0);
2134ddde725dSArmin Le Grand         }
2135ddde725dSArmin Le Grand 
getFillOpacity() const21360813cdfdSArmin Le Grand         SvgNumber SvgStyleAttributes::getFillOpacity() const
2137ddde725dSArmin Le Grand         {
2138ddde725dSArmin Le Grand             if(mbIsClipPathContent)
2139ddde725dSArmin Le Grand             {
2140ddde725dSArmin Le Grand                 return SvgNumber(1.0);
2141ddde725dSArmin Le Grand             }
2142ddde725dSArmin Le Grand             else if(maFillOpacity.isSet())
2143ddde725dSArmin Le Grand             {
2144ddde725dSArmin Le Grand                 return maFillOpacity;
2145ddde725dSArmin Le Grand             }
2146ddde725dSArmin Le Grand 
2147ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2148ddde725dSArmin Le Grand 
2149ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2150ddde725dSArmin Le Grand             {
2151ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getFillOpacity();
2152ddde725dSArmin Le Grand             }
2153ddde725dSArmin Le Grand 
2154ddde725dSArmin Le Grand             // default is 1
2155ddde725dSArmin Le Grand             return SvgNumber(1.0);
2156ddde725dSArmin Le Grand         }
2157ddde725dSArmin Le Grand 
getFillRule() const21580813cdfdSArmin Le Grand         FillRule SvgStyleAttributes::getFillRule() const
2159ddde725dSArmin Le Grand         {
216050b37974SArmin Le Grand             if(FillRule_notset != maFillRule)
2161ddde725dSArmin Le Grand             {
2162ddde725dSArmin Le Grand                 return maFillRule;
2163ddde725dSArmin Le Grand             }
2164ddde725dSArmin Le Grand 
2165ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2166ddde725dSArmin Le Grand 
2167ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2168ddde725dSArmin Le Grand             {
2169ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getFillRule();
2170ddde725dSArmin Le Grand             }
2171ddde725dSArmin Le Grand 
2172ddde725dSArmin Le Grand             // default is NonZero
217350b37974SArmin Le Grand             return FillRule_nonzero;
2174ddde725dSArmin Le Grand         }
2175ddde725dSArmin Le Grand 
getStrokeDasharray() const2176ddde725dSArmin Le Grand         const SvgNumberVector& SvgStyleAttributes::getStrokeDasharray() const
2177ddde725dSArmin Le Grand         {
2178ddde725dSArmin Le Grand             if(!maStrokeDasharray.empty())
2179ddde725dSArmin Le Grand             {
2180ddde725dSArmin Le Grand                 return maStrokeDasharray;
2181ddde725dSArmin Le Grand             }
21825bc9d783SArmin Le Grand             else if(getStrokeDasharraySet())
21835bc9d783SArmin Le Grand             {
21845bc9d783SArmin Le Grand                 // #121221# is set to empty *by purpose*, do not visit parent styles
21855bc9d783SArmin Le Grand                 return maStrokeDasharray;
21865bc9d783SArmin Le Grand             }
2187ddde725dSArmin Le Grand 
2188ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2189ddde725dSArmin Le Grand 
2190ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2191ddde725dSArmin Le Grand             {
2192ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getStrokeDasharray();
2193ddde725dSArmin Le Grand             }
2194ddde725dSArmin Le Grand 
2195ddde725dSArmin Le Grand             // default empty
2196ddde725dSArmin Le Grand             return maStrokeDasharray;
2197ddde725dSArmin Le Grand         }
2198ddde725dSArmin Le Grand 
getStrokeDashOffset() const21990813cdfdSArmin Le Grand         SvgNumber SvgStyleAttributes::getStrokeDashOffset() const
2200ddde725dSArmin Le Grand         {
2201ddde725dSArmin Le Grand             if(maStrokeDashOffset.isSet())
2202ddde725dSArmin Le Grand             {
2203ddde725dSArmin Le Grand                 return maStrokeDashOffset;
2204ddde725dSArmin Le Grand             }
2205ddde725dSArmin Le Grand 
2206ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2207ddde725dSArmin Le Grand 
2208ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2209ddde725dSArmin Le Grand             {
2210ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getStrokeDashOffset();
2211ddde725dSArmin Le Grand             }
2212ddde725dSArmin Le Grand 
2213ddde725dSArmin Le Grand             // default is 0
2214ddde725dSArmin Le Grand             return SvgNumber(0.0);
2215ddde725dSArmin Le Grand         }
2216ddde725dSArmin Le Grand 
getStrokeLinecap() const22170813cdfdSArmin Le Grand         StrokeLinecap SvgStyleAttributes::getStrokeLinecap() const
2218ddde725dSArmin Le Grand         {
2219ddde725dSArmin Le Grand             if(maStrokeLinecap != StrokeLinecap_notset)
2220ddde725dSArmin Le Grand             {
2221ddde725dSArmin Le Grand                 return maStrokeLinecap;
2222ddde725dSArmin Le Grand             }
2223ddde725dSArmin Le Grand 
2224ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2225ddde725dSArmin Le Grand 
2226ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2227ddde725dSArmin Le Grand             {
2228ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getStrokeLinecap();
2229ddde725dSArmin Le Grand             }
2230ddde725dSArmin Le Grand 
2231ddde725dSArmin Le Grand             // default is StrokeLinecap_butt
2232ddde725dSArmin Le Grand             return StrokeLinecap_butt;
2233ddde725dSArmin Le Grand         }
2234ddde725dSArmin Le Grand 
getStrokeLinejoin() const22350813cdfdSArmin Le Grand         StrokeLinejoin SvgStyleAttributes::getStrokeLinejoin() const
2236ddde725dSArmin Le Grand         {
2237ddde725dSArmin Le Grand             if(maStrokeLinejoin != StrokeLinejoin_notset)
2238ddde725dSArmin Le Grand             {
2239ddde725dSArmin Le Grand                 return maStrokeLinejoin;
2240ddde725dSArmin Le Grand             }
2241ddde725dSArmin Le Grand 
2242ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2243ddde725dSArmin Le Grand 
2244ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2245ddde725dSArmin Le Grand             {
2246ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getStrokeLinejoin();
2247ddde725dSArmin Le Grand             }
2248ddde725dSArmin Le Grand 
2249ddde725dSArmin Le Grand             // default is StrokeLinejoin_butt
2250ddde725dSArmin Le Grand             return StrokeLinejoin_miter;
2251ddde725dSArmin Le Grand         }
2252ddde725dSArmin Le Grand 
getStrokeMiterLimit() const22530813cdfdSArmin Le Grand         SvgNumber SvgStyleAttributes::getStrokeMiterLimit() const
2254ddde725dSArmin Le Grand         {
2255ddde725dSArmin Le Grand             if(maStrokeMiterLimit.isSet())
2256ddde725dSArmin Le Grand             {
2257ddde725dSArmin Le Grand                 return maStrokeMiterLimit;
2258ddde725dSArmin Le Grand             }
2259ddde725dSArmin Le Grand 
2260ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2261ddde725dSArmin Le Grand 
2262ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2263ddde725dSArmin Le Grand             {
2264ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getStrokeMiterLimit();
2265ddde725dSArmin Le Grand             }
2266ddde725dSArmin Le Grand 
2267ddde725dSArmin Le Grand             // default is 4
2268ddde725dSArmin Le Grand             return SvgNumber(4.0);
2269ddde725dSArmin Le Grand         }
2270ddde725dSArmin Le Grand 
getStrokeOpacity() const22710813cdfdSArmin Le Grand         SvgNumber SvgStyleAttributes::getStrokeOpacity() const
2272ddde725dSArmin Le Grand         {
2273ddde725dSArmin Le Grand             if(maStrokeOpacity.isSet())
2274ddde725dSArmin Le Grand             {
2275ddde725dSArmin Le Grand                 return maStrokeOpacity;
2276ddde725dSArmin Le Grand             }
2277ddde725dSArmin Le Grand 
2278ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2279ddde725dSArmin Le Grand 
2280ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2281ddde725dSArmin Le Grand             {
2282ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getStrokeOpacity();
2283ddde725dSArmin Le Grand             }
2284ddde725dSArmin Le Grand 
2285ddde725dSArmin Le Grand             // default is 1
2286ddde725dSArmin Le Grand             return SvgNumber(1.0);
2287ddde725dSArmin Le Grand         }
2288ddde725dSArmin Le Grand 
getFontFamily() const2289ddde725dSArmin Le Grand         const SvgStringVector& SvgStyleAttributes::getFontFamily() const
2290ddde725dSArmin Le Grand         {
2291ddde725dSArmin Le Grand             if(!maFontFamily.empty())
2292ddde725dSArmin Le Grand             {
2293ddde725dSArmin Le Grand                 return maFontFamily;
2294ddde725dSArmin Le Grand             }
2295ddde725dSArmin Le Grand 
2296ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2297ddde725dSArmin Le Grand 
2298ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2299ddde725dSArmin Le Grand             {
2300ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getFontFamily();
2301ddde725dSArmin Le Grand             }
2302ddde725dSArmin Le Grand 
2303ddde725dSArmin Le Grand             // default is empty
2304ddde725dSArmin Le Grand             return maFontFamily;
2305ddde725dSArmin Le Grand         }
2306ddde725dSArmin Le Grand 
getFontSize() const23070813cdfdSArmin Le Grand         SvgNumber SvgStyleAttributes::getFontSize() const
2308ddde725dSArmin Le Grand         {
2309ddde725dSArmin Le Grand             if(maFontSize.isSet())
2310ddde725dSArmin Le Grand             {
231186d02030SArmin Le Grand                 // #122524# Handle Unit_percent realtive to parent FontSize (see SVG1.1
231286d02030SArmin Le Grand                 // spec 10.10 Font selection properties �font-size�, lastline (klick 'normative
231386d02030SArmin Le Grand                 // definition of the property')
231486d02030SArmin Le Grand                 if(Unit_percent == maFontSize.getUnit())
231586d02030SArmin Le Grand                 {
231686d02030SArmin Le Grand                     const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
231786d02030SArmin Le Grand 
231886d02030SArmin Le Grand                     if(pSvgStyleAttributes)
231986d02030SArmin Le Grand                     {
232086d02030SArmin Le Grand                         const SvgNumber aParentNumber = pSvgStyleAttributes->getFontSize();
232186d02030SArmin Le Grand 
232286d02030SArmin Le Grand                         return SvgNumber(
232386d02030SArmin Le Grand                             aParentNumber.getNumber() * maFontSize.getNumber() * 0.01,
232486d02030SArmin Le Grand                             aParentNumber.getUnit(),
232586d02030SArmin Le Grand                             true);
232686d02030SArmin Le Grand                     }
232786d02030SArmin Le Grand                 }
232886d02030SArmin Le Grand 
2329ddde725dSArmin Le Grand                 return maFontSize;
2330ddde725dSArmin Le Grand             }
2331ddde725dSArmin Le Grand 
2332ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2333ddde725dSArmin Le Grand 
2334ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2335ddde725dSArmin Le Grand             {
2336ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getFontSize();
2337ddde725dSArmin Le Grand             }
2338ddde725dSArmin Le Grand 
2339ddde725dSArmin Le Grand             // default is 'medium'
2340ddde725dSArmin Le Grand             return SvgNumber(12.0);
2341ddde725dSArmin Le Grand         }
2342ddde725dSArmin Le Grand 
getFontStretch() const23430813cdfdSArmin Le Grand         FontStretch SvgStyleAttributes::getFontStretch() const
2344ddde725dSArmin Le Grand         {
2345ddde725dSArmin Le Grand             if(maFontStretch != FontStretch_notset)
2346ddde725dSArmin Le Grand             {
2347ddde725dSArmin Le Grand                 if(FontStretch_wider != maFontStretch && FontStretch_narrower != maFontStretch)
2348ddde725dSArmin Le Grand                 {
2349ddde725dSArmin Le Grand                     return maFontStretch;
2350ddde725dSArmin Le Grand                 }
2351ddde725dSArmin Le Grand             }
2352ddde725dSArmin Le Grand 
2353ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2354ddde725dSArmin Le Grand 
2355ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2356ddde725dSArmin Le Grand             {
2357ddde725dSArmin Le Grand                 FontStretch aInherited = pSvgStyleAttributes->getFontStretch();
2358ddde725dSArmin Le Grand 
2359ddde725dSArmin Le Grand                 if(FontStretch_wider == maFontStretch)
2360ddde725dSArmin Le Grand                 {
2361ddde725dSArmin Le Grand                     aInherited = getWider(aInherited);
2362ddde725dSArmin Le Grand                 }
2363ddde725dSArmin Le Grand                 else if(FontStretch_narrower == maFontStretch)
2364ddde725dSArmin Le Grand                 {
2365ddde725dSArmin Le Grand                     aInherited = getNarrower(aInherited);
2366ddde725dSArmin Le Grand                 }
2367ddde725dSArmin Le Grand 
2368ddde725dSArmin Le Grand                 return aInherited;
2369ddde725dSArmin Le Grand             }
2370ddde725dSArmin Le Grand 
2371ddde725dSArmin Le Grand             // default is FontStretch_normal
2372ddde725dSArmin Le Grand             return FontStretch_normal;
2373ddde725dSArmin Le Grand         }
2374ddde725dSArmin Le Grand 
getFontStyle() const23750813cdfdSArmin Le Grand         FontStyle SvgStyleAttributes::getFontStyle() const
2376ddde725dSArmin Le Grand         {
2377ddde725dSArmin Le Grand             if(maFontStyle != FontStyle_notset)
2378ddde725dSArmin Le Grand             {
2379ddde725dSArmin Le Grand                 return maFontStyle;
2380ddde725dSArmin Le Grand             }
2381ddde725dSArmin Le Grand 
2382ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2383ddde725dSArmin Le Grand 
2384ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2385ddde725dSArmin Le Grand             {
2386ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getFontStyle();
2387ddde725dSArmin Le Grand             }
2388ddde725dSArmin Le Grand 
2389ddde725dSArmin Le Grand             // default is FontStyle_normal
2390ddde725dSArmin Le Grand             return FontStyle_normal;
2391ddde725dSArmin Le Grand         }
2392ddde725dSArmin Le Grand 
getFontWeight() const23930813cdfdSArmin Le Grand         FontWeight SvgStyleAttributes::getFontWeight() const
2394ddde725dSArmin Le Grand         {
2395ddde725dSArmin Le Grand             if(maFontWeight != FontWeight_notset)
2396ddde725dSArmin Le Grand             {
2397ddde725dSArmin Le Grand                 if(FontWeight_bolder != maFontWeight && FontWeight_lighter != maFontWeight)
2398ddde725dSArmin Le Grand                 {
2399ddde725dSArmin Le Grand                     return maFontWeight;
2400ddde725dSArmin Le Grand                 }
2401ddde725dSArmin Le Grand             }
2402ddde725dSArmin Le Grand 
2403ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2404ddde725dSArmin Le Grand 
2405ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2406ddde725dSArmin Le Grand             {
2407ddde725dSArmin Le Grand                 FontWeight aInherited = pSvgStyleAttributes->getFontWeight();
2408ddde725dSArmin Le Grand 
2409ddde725dSArmin Le Grand                 if(FontWeight_bolder == maFontWeight)
2410ddde725dSArmin Le Grand                 {
2411ddde725dSArmin Le Grand                     aInherited = getBolder(aInherited);
2412ddde725dSArmin Le Grand                 }
2413ddde725dSArmin Le Grand                 else if(FontWeight_lighter == maFontWeight)
2414ddde725dSArmin Le Grand                 {
2415ddde725dSArmin Le Grand                     aInherited = getLighter(aInherited);
2416ddde725dSArmin Le Grand                 }
2417ddde725dSArmin Le Grand 
2418ddde725dSArmin Le Grand                 return aInherited;
2419ddde725dSArmin Le Grand             }
2420ddde725dSArmin Le Grand 
2421ddde725dSArmin Le Grand             // default is FontWeight_400 (FontWeight_normal)
2422ddde725dSArmin Le Grand             return FontWeight_400;
2423ddde725dSArmin Le Grand         }
2424ddde725dSArmin Le Grand 
getTextAlign() const24250813cdfdSArmin Le Grand         TextAlign SvgStyleAttributes::getTextAlign() const
2426ddde725dSArmin Le Grand         {
2427ddde725dSArmin Le Grand             if(maTextAlign != TextAlign_notset)
2428ddde725dSArmin Le Grand             {
2429ddde725dSArmin Le Grand                 return maTextAlign;
2430ddde725dSArmin Le Grand             }
2431ddde725dSArmin Le Grand 
2432ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2433ddde725dSArmin Le Grand 
2434ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2435ddde725dSArmin Le Grand             {
2436ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getTextAlign();
2437ddde725dSArmin Le Grand             }
2438ddde725dSArmin Le Grand 
2439ddde725dSArmin Le Grand             // default is TextAlign_left
2440ddde725dSArmin Le Grand             return TextAlign_left;
2441ddde725dSArmin Le Grand         }
2442ddde725dSArmin Le Grand 
getTextDecorationDefiningSvgStyleAttributes() const2443ddde725dSArmin Le Grand         const SvgStyleAttributes* SvgStyleAttributes::getTextDecorationDefiningSvgStyleAttributes() const
2444ddde725dSArmin Le Grand         {
2445ddde725dSArmin Le Grand             if(maTextDecoration != TextDecoration_notset)
2446ddde725dSArmin Le Grand             {
2447ddde725dSArmin Le Grand                 return this;
2448ddde725dSArmin Le Grand             }
2449ddde725dSArmin Le Grand 
2450ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2451ddde725dSArmin Le Grand 
2452ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2453ddde725dSArmin Le Grand             {
2454ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getTextDecorationDefiningSvgStyleAttributes();
2455ddde725dSArmin Le Grand             }
2456ddde725dSArmin Le Grand 
2457ddde725dSArmin Le Grand             // default is 0
2458ddde725dSArmin Le Grand             return 0;
2459ddde725dSArmin Le Grand         }
2460ddde725dSArmin Le Grand 
getTextDecoration() const24610813cdfdSArmin Le Grand         TextDecoration SvgStyleAttributes::getTextDecoration() const
2462ddde725dSArmin Le Grand         {
2463ddde725dSArmin Le Grand             const SvgStyleAttributes* pDefining = getTextDecorationDefiningSvgStyleAttributes();
2464ddde725dSArmin Le Grand 
2465ddde725dSArmin Le Grand             if(pDefining)
2466ddde725dSArmin Le Grand             {
2467ddde725dSArmin Le Grand                 return pDefining->maTextDecoration;
2468ddde725dSArmin Le Grand             }
2469ddde725dSArmin Le Grand             else
2470ddde725dSArmin Le Grand             {
2471ddde725dSArmin Le Grand                 // default is TextDecoration_none
2472ddde725dSArmin Le Grand                 return TextDecoration_none;
2473ddde725dSArmin Le Grand             }
2474ddde725dSArmin Le Grand         }
2475ddde725dSArmin Le Grand 
getTextAnchor() const24760813cdfdSArmin Le Grand         TextAnchor SvgStyleAttributes::getTextAnchor() const
2477ddde725dSArmin Le Grand         {
2478ddde725dSArmin Le Grand             if(maTextAnchor != TextAnchor_notset)
2479ddde725dSArmin Le Grand             {
2480ddde725dSArmin Le Grand                 return maTextAnchor;
2481ddde725dSArmin Le Grand             }
2482ddde725dSArmin Le Grand 
2483ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2484ddde725dSArmin Le Grand 
2485ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2486ddde725dSArmin Le Grand             {
2487ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getTextAnchor();
2488ddde725dSArmin Le Grand             }
2489ddde725dSArmin Le Grand 
2490ddde725dSArmin Le Grand             // default is TextAnchor_start
2491ddde725dSArmin Le Grand             return TextAnchor_start;
2492ddde725dSArmin Le Grand         }
2493ddde725dSArmin Le Grand 
getColor() const2494ddde725dSArmin Le Grand         const basegfx::BColor* SvgStyleAttributes::getColor() const
2495ddde725dSArmin Le Grand         {
2496ddde725dSArmin Le Grand             if(maColor.isSet())
2497ddde725dSArmin Le Grand             {
2498ddde725dSArmin Le Grand                 if(maColor.isCurrent())
2499ddde725dSArmin Le Grand                 {
2500ddde725dSArmin Le Grand                     OSL_ENSURE(false, "Svg error: current color uses current color (!)");
2501ddde725dSArmin Le Grand                     return 0;
2502ddde725dSArmin Le Grand                 }
2503ddde725dSArmin Le Grand                 else if(maColor.isOn())
2504ddde725dSArmin Le Grand                 {
2505ddde725dSArmin Le Grand                     return &maColor.getBColor();
2506ddde725dSArmin Le Grand                 }
2507ddde725dSArmin Le Grand             }
2508ddde725dSArmin Le Grand             else
2509ddde725dSArmin Le Grand             {
2510ddde725dSArmin Le Grand                 const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2511ddde725dSArmin Le Grand 
2512ddde725dSArmin Le Grand                 if(pSvgStyleAttributes)
2513ddde725dSArmin Le Grand                 {
2514ddde725dSArmin Le Grand                     return pSvgStyleAttributes->getColor();
2515ddde725dSArmin Le Grand                 }
2516ddde725dSArmin Le Grand             }
2517ddde725dSArmin Le Grand 
2518ddde725dSArmin Le Grand             return 0;
2519ddde725dSArmin Le Grand         }
2520ddde725dSArmin Le Grand 
getMarkerStartXLink() const25210813cdfdSArmin Le Grand         rtl::OUString SvgStyleAttributes::getMarkerStartXLink() const
2522ddde725dSArmin Le Grand         {
2523ddde725dSArmin Le Grand             if(maMarkerStartXLink.getLength())
2524ddde725dSArmin Le Grand             {
2525ddde725dSArmin Le Grand                 return maMarkerStartXLink;
2526ddde725dSArmin Le Grand             }
2527ddde725dSArmin Le Grand 
2528ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2529ddde725dSArmin Le Grand 
2530ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2531ddde725dSArmin Le Grand             {
2532ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getMarkerStartXLink();
2533ddde725dSArmin Le Grand             }
2534ddde725dSArmin Le Grand 
2535ddde725dSArmin Le Grand             return rtl::OUString();
2536ddde725dSArmin Le Grand         }
2537ddde725dSArmin Le Grand 
accessMarkerStartXLink() const2538ddde725dSArmin Le Grand         const SvgMarkerNode* SvgStyleAttributes::accessMarkerStartXLink() const
2539ddde725dSArmin Le Grand         {
2540ddde725dSArmin Le Grand             if(!mpMarkerStartXLink)
2541ddde725dSArmin Le Grand             {
2542ddde725dSArmin Le Grand                 const rtl::OUString aMarker(getMarkerStartXLink());
2543ddde725dSArmin Le Grand 
2544ddde725dSArmin Le Grand                 if(aMarker.getLength())
2545ddde725dSArmin Le Grand                 {
2546ddde725dSArmin Le Grand                     const_cast< SvgStyleAttributes* >(this)->mpMarkerStartXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerStartXLink()));
2547ddde725dSArmin Le Grand                 }
2548ddde725dSArmin Le Grand             }
2549ddde725dSArmin Le Grand 
2550ddde725dSArmin Le Grand             return mpMarkerStartXLink;
2551ddde725dSArmin Le Grand         }
2552ddde725dSArmin Le Grand 
getMarkerMidXLink() const25530813cdfdSArmin Le Grand         rtl::OUString SvgStyleAttributes::getMarkerMidXLink() const
2554ddde725dSArmin Le Grand         {
2555ddde725dSArmin Le Grand             if(maMarkerMidXLink.getLength())
2556ddde725dSArmin Le Grand             {
2557ddde725dSArmin Le Grand                 return maMarkerMidXLink;
2558ddde725dSArmin Le Grand             }
2559ddde725dSArmin Le Grand 
2560ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2561ddde725dSArmin Le Grand 
2562ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2563ddde725dSArmin Le Grand             {
2564ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getMarkerMidXLink();
2565ddde725dSArmin Le Grand             }
2566ddde725dSArmin Le Grand 
2567ddde725dSArmin Le Grand             return rtl::OUString();
2568ddde725dSArmin Le Grand         }
2569ddde725dSArmin Le Grand 
accessMarkerMidXLink() const2570ddde725dSArmin Le Grand         const SvgMarkerNode* SvgStyleAttributes::accessMarkerMidXLink() const
2571ddde725dSArmin Le Grand         {
2572ddde725dSArmin Le Grand             if(!mpMarkerMidXLink)
2573ddde725dSArmin Le Grand             {
2574ddde725dSArmin Le Grand                 const rtl::OUString aMarker(getMarkerMidXLink());
2575ddde725dSArmin Le Grand 
2576ddde725dSArmin Le Grand                 if(aMarker.getLength())
2577ddde725dSArmin Le Grand                 {
2578ddde725dSArmin Le Grand                     const_cast< SvgStyleAttributes* >(this)->mpMarkerMidXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerMidXLink()));
2579ddde725dSArmin Le Grand                 }
2580ddde725dSArmin Le Grand             }
2581ddde725dSArmin Le Grand 
2582ddde725dSArmin Le Grand             return mpMarkerMidXLink;
2583ddde725dSArmin Le Grand         }
2584ddde725dSArmin Le Grand 
getMarkerEndXLink() const25850813cdfdSArmin Le Grand         rtl::OUString SvgStyleAttributes::getMarkerEndXLink() const
2586ddde725dSArmin Le Grand         {
2587ddde725dSArmin Le Grand             if(maMarkerEndXLink.getLength())
2588ddde725dSArmin Le Grand             {
2589ddde725dSArmin Le Grand                 return maMarkerEndXLink;
2590ddde725dSArmin Le Grand             }
2591ddde725dSArmin Le Grand 
2592ddde725dSArmin Le Grand             const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
2593ddde725dSArmin Le Grand 
2594ddde725dSArmin Le Grand             if(pSvgStyleAttributes)
2595ddde725dSArmin Le Grand             {
2596ddde725dSArmin Le Grand                 return pSvgStyleAttributes->getMarkerEndXLink();
2597ddde725dSArmin Le Grand             }
2598ddde725dSArmin Le Grand 
2599ddde725dSArmin Le Grand             return rtl::OUString();
2600ddde725dSArmin Le Grand         }
2601ddde725dSArmin Le Grand 
accessMarkerEndXLink() const2602ddde725dSArmin Le Grand         const SvgMarkerNode* SvgStyleAttributes::accessMarkerEndXLink() const
2603ddde725dSArmin Le Grand         {
2604ddde725dSArmin Le Grand             if(!mpMarkerEndXLink)
2605ddde725dSArmin Le Grand             {
2606ddde725dSArmin Le Grand                 const rtl::OUString aMarker(getMarkerEndXLink());
2607ddde725dSArmin Le Grand 
2608ddde725dSArmin Le Grand                 if(aMarker.getLength())
2609ddde725dSArmin Le Grand                 {
2610ddde725dSArmin Le Grand                     const_cast< SvgStyleAttributes* >(this)->mpMarkerEndXLink = dynamic_cast< const SvgMarkerNode* >(mrOwner.getDocument().findSvgNodeById(getMarkerEndXLink()));
2611ddde725dSArmin Le Grand                 }
2612ddde725dSArmin Le Grand             }
2613ddde725dSArmin Le Grand 
2614ddde725dSArmin Le Grand             return mpMarkerEndXLink;
2615ddde725dSArmin Le Grand         }
2616ddde725dSArmin Le Grand 
getBaselineShiftNumber() const261786d02030SArmin Le Grand         SvgNumber SvgStyleAttributes::getBaselineShiftNumber() const
261886d02030SArmin Le Grand         {
261986d02030SArmin Le Grand             // #122524# Handle Unit_percent realtive to parent BaselineShift
262086d02030SArmin Le Grand             if(Unit_percent == maBaselineShiftNumber.getUnit())
262186d02030SArmin Le Grand             {
262286d02030SArmin Le Grand                 const SvgStyleAttributes* pSvgStyleAttributes = getParentStyle();
262386d02030SArmin Le Grand 
262486d02030SArmin Le Grand                 if(pSvgStyleAttributes)
262586d02030SArmin Le Grand                 {
262686d02030SArmin Le Grand                     const SvgNumber aParentNumber = pSvgStyleAttributes->getBaselineShiftNumber();
262786d02030SArmin Le Grand 
262886d02030SArmin Le Grand                     return SvgNumber(
262986d02030SArmin Le Grand                         aParentNumber.getNumber() * maBaselineShiftNumber.getNumber() * 0.01,
263086d02030SArmin Le Grand                         aParentNumber.getUnit(),
263186d02030SArmin Le Grand                         true);
263286d02030SArmin Le Grand                 }
263386d02030SArmin Le Grand             }
263486d02030SArmin Le Grand 
263586d02030SArmin Le Grand             return maBaselineShiftNumber;
263686d02030SArmin Le Grand         }
2637ddde725dSArmin Le Grand     } // end of namespace svgreader
2638ddde725dSArmin Le Grand } // end of namespace svgio
2639ddde725dSArmin Le Grand 
2640ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
2641ddde725dSArmin Le Grand // eof
2642