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