1*ddde725dSArmin Le Grand /**************************************************************
2*ddde725dSArmin Le Grand  *
3*ddde725dSArmin Le Grand  * Licensed to the Apache Software Foundation (ASF) under one
4*ddde725dSArmin Le Grand  * or more contributor license agreements.  See the NOTICE file
5*ddde725dSArmin Le Grand  * distributed with this work for additional information
6*ddde725dSArmin Le Grand  * regarding copyright ownership.  The ASF licenses this file
7*ddde725dSArmin Le Grand  * to you under the Apache License, Version 2.0 (the
8*ddde725dSArmin Le Grand  * "License"); you may not use this file except in compliance
9*ddde725dSArmin Le Grand  * with the License.  You may obtain a copy of the License at
10*ddde725dSArmin Le Grand  *
11*ddde725dSArmin Le Grand  *   http://www.apache.org/licenses/LICENSE-2.0
12*ddde725dSArmin Le Grand  *
13*ddde725dSArmin Le Grand  * Unless required by applicable law or agreed to in writing,
14*ddde725dSArmin Le Grand  * software distributed under the License is distributed on an
15*ddde725dSArmin Le Grand  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*ddde725dSArmin Le Grand  * KIND, either express or implied.  See the License for the
17*ddde725dSArmin Le Grand  * specific language governing permissions and limitations
18*ddde725dSArmin Le Grand  * under the License.
19*ddde725dSArmin Le Grand  *
20*ddde725dSArmin Le Grand  *************************************************************/
21*ddde725dSArmin Le Grand 
22*ddde725dSArmin Le Grand // MARKER(update_precomp.py): autogen include statement, do not remove
23*ddde725dSArmin Le Grand #include "precompiled_svgio.hxx"
24*ddde725dSArmin Le Grand 
25*ddde725dSArmin Le Grand #include <svgio/svgreader/svgtools.hxx>
26*ddde725dSArmin Le Grand #include <osl/thread.h>
27*ddde725dSArmin Le Grand #include <tools/color.hxx>
28*ddde725dSArmin Le Grand #include <basegfx/matrix/b2dhommatrix.hxx>
29*ddde725dSArmin Le Grand #include <basegfx/matrix/b2dhommatrixtools.hxx>
30*ddde725dSArmin Le Grand #include <svgio/svgreader/svgtoken.hxx>
31*ddde725dSArmin Le Grand #include <hash_map>
32*ddde725dSArmin Le Grand 
33*ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
34*ddde725dSArmin Le Grand 
35*ddde725dSArmin Le Grand namespace svgio
36*ddde725dSArmin Le Grand {
37*ddde725dSArmin Le Grand     namespace svgreader
38*ddde725dSArmin Le Grand     {
39*ddde725dSArmin Le Grand #ifdef DBG_UTIL
40*ddde725dSArmin Le Grand         void myAssert(const rtl::OUString& rMessage)
41*ddde725dSArmin Le Grand         {
42*ddde725dSArmin Le Grand             rtl::OString aMessage2;
43*ddde725dSArmin Le Grand 
44*ddde725dSArmin Le Grand             rMessage.convertToString(&aMessage2, osl_getThreadTextEncoding(), RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR|RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR);
45*ddde725dSArmin Le Grand             OSL_ENSURE(false, aMessage2.getStr());
46*ddde725dSArmin Le Grand         }
47*ddde725dSArmin Le Grand #endif
48*ddde725dSArmin Le Grand 
49*ddde725dSArmin Le Grand         // common non-token strings
50*ddde725dSArmin Le Grand         const rtl::OUString commonStrings::aStrUserSpaceOnUse(rtl::OUString::createFromAscii("userSpaceOnUse"));
51*ddde725dSArmin Le Grand         const rtl::OUString commonStrings::aStrObjectBoundingBox(rtl::OUString::createFromAscii("objectBoundingBox"));
52*ddde725dSArmin Le Grand         const rtl::OUString commonStrings::aStrNonzero(rtl::OUString::createFromAscii("nonzero"));
53*ddde725dSArmin Le Grand         const rtl::OUString commonStrings::aStrEvenOdd(rtl::OUString::createFromAscii("evenodd"));
54*ddde725dSArmin Le Grand 
55*ddde725dSArmin Le Grand         basegfx::B2DHomMatrix SvgAspectRatio::createLinearMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource)
56*ddde725dSArmin Le Grand         {
57*ddde725dSArmin Le Grand             basegfx::B2DHomMatrix aRetval;
58*ddde725dSArmin Le Grand             const double fSWidth(rSource.getWidth());
59*ddde725dSArmin Le Grand             const double fSHeight(rSource.getHeight());
60*ddde725dSArmin Le Grand             const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth));
61*ddde725dSArmin Le Grand             const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight));
62*ddde725dSArmin Le Grand 
63*ddde725dSArmin Le Grand             // transform from source state to unit range
64*ddde725dSArmin Le Grand             aRetval.translate(-rSource.getMinX(), -rSource.getMinY());
65*ddde725dSArmin Le Grand             aRetval.scale(
66*ddde725dSArmin Le Grand                 (bNoSWidth ? 1.0 : 1.0 / fSWidth) * rTarget.getWidth(),
67*ddde725dSArmin Le Grand                 (bNoSHeight ? 1.0 : 1.0 / fSHeight) * rTarget.getHeight());
68*ddde725dSArmin Le Grand 
69*ddde725dSArmin Le Grand             // transform from unit rage to target range
70*ddde725dSArmin Le Grand             aRetval.translate(rTarget.getMinX(), rTarget.getMinY());
71*ddde725dSArmin Le Grand 
72*ddde725dSArmin Le Grand             return aRetval;
73*ddde725dSArmin Le Grand         }
74*ddde725dSArmin Le Grand 
75*ddde725dSArmin Le Grand         basegfx::B2DHomMatrix SvgAspectRatio::createMapping(const basegfx::B2DRange& rTarget, const basegfx::B2DRange& rSource) const
76*ddde725dSArmin Le Grand         {
77*ddde725dSArmin Le Grand             if(!isSet() || Align_none == getSvgAlign())
78*ddde725dSArmin Le Grand             {
79*ddde725dSArmin Le Grand                 // create linear mapping (default)
80*ddde725dSArmin Le Grand                 return createLinearMapping(rTarget, rSource);
81*ddde725dSArmin Le Grand             }
82*ddde725dSArmin Le Grand 
83*ddde725dSArmin Le Grand             basegfx::B2DHomMatrix aRetval;
84*ddde725dSArmin Le Grand 
85*ddde725dSArmin Le Grand             const double fSWidth(rSource.getWidth());
86*ddde725dSArmin Le Grand             const double fSHeight(rSource.getHeight());
87*ddde725dSArmin Le Grand             const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth));
88*ddde725dSArmin Le Grand             const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight));
89*ddde725dSArmin Le Grand             const double fScaleX((bNoSWidth ? 1.0 : 1.0 / fSWidth) * rTarget.getWidth());
90*ddde725dSArmin Le Grand             const double fScaleY((bNoSHeight ? 1.0 : 1.0 / fSHeight) * rTarget.getHeight());
91*ddde725dSArmin Le Grand             const double fScale(isMeetOrSlice() ? std::min(fScaleX, fScaleY) : std::max(fScaleX, fScaleY));
92*ddde725dSArmin Le Grand 
93*ddde725dSArmin Le Grand             // remove source translation, apply scale
94*ddde725dSArmin Le Grand             aRetval.translate(-rSource.getMinX(), -rSource.getMinY());
95*ddde725dSArmin Le Grand             aRetval.scale(fScale, fScale);
96*ddde725dSArmin Le Grand 
97*ddde725dSArmin Le Grand             // evaluate horizontal alignment
98*ddde725dSArmin Le Grand             const double fNewWidth(fSWidth * fScale);
99*ddde725dSArmin Le Grand             double fTransX(0.0);
100*ddde725dSArmin Le Grand 
101*ddde725dSArmin Le Grand             switch(getSvgAlign())
102*ddde725dSArmin Le Grand             {
103*ddde725dSArmin Le Grand                 case Align_xMidYMin:
104*ddde725dSArmin Le Grand                 case Align_xMidYMid:
105*ddde725dSArmin Le Grand                 case Align_xMidYMax:
106*ddde725dSArmin Le Grand                 {
107*ddde725dSArmin Le Grand                     // centerX
108*ddde725dSArmin Le Grand                     const double fFreeSpace(rTarget.getWidth() - fNewWidth);
109*ddde725dSArmin Le Grand                     fTransX = fFreeSpace * 0.5;
110*ddde725dSArmin Le Grand                     break;
111*ddde725dSArmin Le Grand                 }
112*ddde725dSArmin Le Grand                 case Align_xMaxYMin:
113*ddde725dSArmin Le Grand                 case Align_xMaxYMid:
114*ddde725dSArmin Le Grand                 case Align_xMaxYMax:
115*ddde725dSArmin Le Grand                 {
116*ddde725dSArmin Le Grand                     // Right align
117*ddde725dSArmin Le Grand                     const double fFreeSpace(rTarget.getWidth() - fNewWidth);
118*ddde725dSArmin Le Grand                     fTransX = fFreeSpace;
119*ddde725dSArmin Le Grand                     break;
120*ddde725dSArmin Le Grand                 }
121*ddde725dSArmin Le Grand             }
122*ddde725dSArmin Le Grand 
123*ddde725dSArmin Le Grand             // evaluate vertical alignment
124*ddde725dSArmin Le Grand             const double fNewHeight(fSHeight * fScale);
125*ddde725dSArmin Le Grand             double fTransY(0.0);
126*ddde725dSArmin Le Grand 
127*ddde725dSArmin Le Grand             switch(getSvgAlign())
128*ddde725dSArmin Le Grand             {
129*ddde725dSArmin Le Grand                 case Align_xMinYMid:
130*ddde725dSArmin Le Grand                 case Align_xMidYMid:
131*ddde725dSArmin Le Grand                 case Align_xMaxYMid:
132*ddde725dSArmin Le Grand                 {
133*ddde725dSArmin Le Grand                     // centerY
134*ddde725dSArmin Le Grand                     const double fFreeSpace(rTarget.getHeight() - fNewHeight);
135*ddde725dSArmin Le Grand                     fTransY = fFreeSpace * 0.5;
136*ddde725dSArmin Le Grand                     break;
137*ddde725dSArmin Le Grand                 }
138*ddde725dSArmin Le Grand                 case Align_xMinYMax:
139*ddde725dSArmin Le Grand                 case Align_xMidYMax:
140*ddde725dSArmin Le Grand                 case Align_xMaxYMax:
141*ddde725dSArmin Le Grand                 {
142*ddde725dSArmin Le Grand                     // Bottom align
143*ddde725dSArmin Le Grand                     const double fFreeSpace(rTarget.getHeight() - fNewHeight);
144*ddde725dSArmin Le Grand                     fTransY = fFreeSpace;
145*ddde725dSArmin Le Grand                     break;
146*ddde725dSArmin Le Grand                 }
147*ddde725dSArmin Le Grand             }
148*ddde725dSArmin Le Grand 
149*ddde725dSArmin Le Grand             // add target translation
150*ddde725dSArmin Le Grand             aRetval.translate(
151*ddde725dSArmin Le Grand                 rTarget.getMinX() + fTransX,
152*ddde725dSArmin Le Grand                 rTarget.getMinY() + fTransY);
153*ddde725dSArmin Le Grand 
154*ddde725dSArmin Le Grand             return aRetval;
155*ddde725dSArmin Le Grand         }
156*ddde725dSArmin Le Grand 
157*ddde725dSArmin Le Grand         double SvgNumber::solve(const InfoProvider& rInfoProvider, NumberType aNumberType) const
158*ddde725dSArmin Le Grand         {
159*ddde725dSArmin Le Grand             if(isSet())
160*ddde725dSArmin Le Grand             {
161*ddde725dSArmin Le Grand                 switch(meUnit)
162*ddde725dSArmin Le Grand                 {
163*ddde725dSArmin Le Grand                     case Unit_em:
164*ddde725dSArmin Le Grand                     {
165*ddde725dSArmin Le Grand                         return mfNumber * rInfoProvider.getCurrentFontSize();
166*ddde725dSArmin Le Grand                         break;
167*ddde725dSArmin Le Grand                     }
168*ddde725dSArmin Le Grand                     case Unit_ex:
169*ddde725dSArmin Le Grand                     {
170*ddde725dSArmin Le Grand                         return mfNumber * rInfoProvider.getCurrentXHeight() * 0.5;
171*ddde725dSArmin Le Grand                         break;
172*ddde725dSArmin Le Grand                     }
173*ddde725dSArmin Le Grand                     case Unit_px:
174*ddde725dSArmin Le Grand                     {
175*ddde725dSArmin Le Grand                         return mfNumber;
176*ddde725dSArmin Le Grand                         break;
177*ddde725dSArmin Le Grand                     }
178*ddde725dSArmin Le Grand                     case Unit_pt:
179*ddde725dSArmin Le Grand                     case Unit_pc:
180*ddde725dSArmin Le Grand                     case Unit_cm:
181*ddde725dSArmin Le Grand                     case Unit_mm:
182*ddde725dSArmin Le Grand                     case Unit_in:
183*ddde725dSArmin Le Grand                     {
184*ddde725dSArmin Le Grand                         double fRetval(mfNumber);
185*ddde725dSArmin Le Grand 
186*ddde725dSArmin Le Grand                         switch(meUnit)
187*ddde725dSArmin Le Grand                         {
188*ddde725dSArmin Le Grand                             case Unit_pt: fRetval *= 1.25; break;
189*ddde725dSArmin Le Grand                             case Unit_pc: fRetval *= 15.0; break;
190*ddde725dSArmin Le Grand                             case Unit_cm: fRetval *= 35.43307; break;
191*ddde725dSArmin Le Grand                             case Unit_mm: fRetval *= 3.543307; break;
192*ddde725dSArmin Le Grand                             case Unit_in: fRetval *= 90.0; break;
193*ddde725dSArmin Le Grand                         }
194*ddde725dSArmin Le Grand 
195*ddde725dSArmin Le Grand                         return fRetval;
196*ddde725dSArmin Le Grand                         break;
197*ddde725dSArmin Le Grand                     }
198*ddde725dSArmin Le Grand                     case Unit_percent:
199*ddde725dSArmin Le Grand                     {
200*ddde725dSArmin Le Grand                         double fRetval(mfNumber * 0.01);
201*ddde725dSArmin Le Grand                         const basegfx::B2DRange* pViewPort = rInfoProvider.getCurrentViewPort();
202*ddde725dSArmin Le Grand 
203*ddde725dSArmin Le Grand                         if(!pViewPort)
204*ddde725dSArmin Le Grand                         {
205*ddde725dSArmin Le Grand                             // no viewPort, assume a normal page size (A4)
206*ddde725dSArmin Le Grand                             static basegfx::B2DRange aDinA4Range(
207*ddde725dSArmin Le Grand                                 0.0,
208*ddde725dSArmin Le Grand                                 0.0,
209*ddde725dSArmin Le Grand                                 210.0 * 3.543307,
210*ddde725dSArmin Le Grand                                 297.0 * 3.543307);
211*ddde725dSArmin Le Grand 
212*ddde725dSArmin Le Grand                             pViewPort = &aDinA4Range;
213*ddde725dSArmin Le Grand                         }
214*ddde725dSArmin Le Grand 
215*ddde725dSArmin Le Grand                         if(pViewPort)
216*ddde725dSArmin Le Grand                         {
217*ddde725dSArmin Le Grand                             if(xcoordinate == aNumberType)
218*ddde725dSArmin Le Grand                             {
219*ddde725dSArmin Le Grand                                 // it's a x-coordinate, relative to current width (w)
220*ddde725dSArmin Le Grand                                 fRetval *= pViewPort->getWidth();
221*ddde725dSArmin Le Grand                             }
222*ddde725dSArmin Le Grand                             else if(ycoordinate == aNumberType)
223*ddde725dSArmin Le Grand                             {
224*ddde725dSArmin Le Grand                                 // it's a y-coordinate, relative to current height (h)
225*ddde725dSArmin Le Grand                                 fRetval *= pViewPort->getHeight();
226*ddde725dSArmin Le Grand                             }
227*ddde725dSArmin Le Grand                             else // length
228*ddde725dSArmin Le Grand                             {
229*ddde725dSArmin Le Grand                                 // it's a length, relative to sqrt(w*w + h*h)/sqrt(2)
230*ddde725dSArmin Le Grand                                 const double fCurrentWidth(pViewPort->getWidth());
231*ddde725dSArmin Le Grand                                 const double fCurrentHeight(pViewPort->getHeight());
232*ddde725dSArmin Le Grand                                 const double fCurrentLength(
233*ddde725dSArmin Le Grand                                     sqrt(fCurrentWidth * fCurrentWidth + fCurrentHeight * fCurrentHeight)/sqrt(2.0));
234*ddde725dSArmin Le Grand 
235*ddde725dSArmin Le Grand                                 fRetval *= fCurrentLength;
236*ddde725dSArmin Le Grand                             }
237*ddde725dSArmin Le Grand                         }
238*ddde725dSArmin Le Grand 
239*ddde725dSArmin Le Grand                         return fRetval;
240*ddde725dSArmin Le Grand                         break;
241*ddde725dSArmin Le Grand                     }
242*ddde725dSArmin Le Grand                 }
243*ddde725dSArmin Le Grand             }
244*ddde725dSArmin Le Grand 
245*ddde725dSArmin Le Grand             /// not set
246*ddde725dSArmin Le Grand             OSL_ENSURE(false, "SvgNumber not set (!)");
247*ddde725dSArmin Le Grand             return 0.0;
248*ddde725dSArmin Le Grand         }
249*ddde725dSArmin Le Grand 
250*ddde725dSArmin Le Grand         bool SvgNumber::isPositive() const
251*ddde725dSArmin Le Grand         {
252*ddde725dSArmin Le Grand             return basegfx::fTools::moreOrEqual(mfNumber, 0.0);
253*ddde725dSArmin Le Grand         }
254*ddde725dSArmin Le Grand 
255*ddde725dSArmin Le Grand         void skip_char(const rtl::OUString& rCandidate, const sal_Unicode& rChar, sal_Int32& nPos, const sal_Int32 nLen)
256*ddde725dSArmin Le Grand         {
257*ddde725dSArmin Le Grand             while(nPos < nLen && rChar == rCandidate[nPos])
258*ddde725dSArmin Le Grand             {
259*ddde725dSArmin Le Grand                 nPos++;
260*ddde725dSArmin Le Grand             }
261*ddde725dSArmin Le Grand         }
262*ddde725dSArmin Le Grand 
263*ddde725dSArmin Le Grand         void skip_char(const rtl::OUString& rCandidate, const sal_Unicode& rCharA, const sal_Unicode& rCharB, sal_Int32& nPos, const sal_Int32 nLen)
264*ddde725dSArmin Le Grand         {
265*ddde725dSArmin Le Grand             while(nPos < nLen && (rCharA == rCandidate[nPos] || rCharB == rCandidate[nPos]))
266*ddde725dSArmin Le Grand             {
267*ddde725dSArmin Le Grand                 nPos++;
268*ddde725dSArmin Le Grand             }
269*ddde725dSArmin Le Grand         }
270*ddde725dSArmin Le Grand 
271*ddde725dSArmin Le Grand         void copySign(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen)
272*ddde725dSArmin Le Grand         {
273*ddde725dSArmin Le Grand             if(nPos < nLen)
274*ddde725dSArmin Le Grand             {
275*ddde725dSArmin Le Grand                 const sal_Unicode aChar(rCandidate[nPos]);
276*ddde725dSArmin Le Grand 
277*ddde725dSArmin Le Grand                 if(sal_Unicode('+') == aChar || sal_Unicode('-') == aChar)
278*ddde725dSArmin Le Grand                 {
279*ddde725dSArmin Le Grand                     rTarget.append(aChar);
280*ddde725dSArmin Le Grand                     nPos++;
281*ddde725dSArmin Le Grand                 }
282*ddde725dSArmin Le Grand             }
283*ddde725dSArmin Le Grand         }
284*ddde725dSArmin Le Grand 
285*ddde725dSArmin Le Grand         void copyNumber(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen)
286*ddde725dSArmin Le Grand         {
287*ddde725dSArmin Le Grand             bool bOnNumber(true);
288*ddde725dSArmin Le Grand 
289*ddde725dSArmin Le Grand             while(bOnNumber && nPos < nLen)
290*ddde725dSArmin Le Grand             {
291*ddde725dSArmin Le Grand                 const sal_Unicode aChar(rCandidate[nPos]);
292*ddde725dSArmin Le Grand 
293*ddde725dSArmin Le Grand                 bOnNumber = (sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar) || sal_Unicode('.') == aChar;
294*ddde725dSArmin Le Grand 
295*ddde725dSArmin Le Grand                 if(bOnNumber)
296*ddde725dSArmin Le Grand                 {
297*ddde725dSArmin Le Grand                     rTarget.append(aChar);
298*ddde725dSArmin Le Grand                     nPos++;
299*ddde725dSArmin Le Grand                 }
300*ddde725dSArmin Le Grand             }
301*ddde725dSArmin Le Grand         }
302*ddde725dSArmin Le Grand 
303*ddde725dSArmin Le Grand         void copyHex(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen)
304*ddde725dSArmin Le Grand         {
305*ddde725dSArmin Le Grand             bool bOnHex(true);
306*ddde725dSArmin Le Grand 
307*ddde725dSArmin Le Grand             while(bOnHex && nPos < nLen)
308*ddde725dSArmin Le Grand             {
309*ddde725dSArmin Le Grand                 const sal_Unicode aChar(rCandidate[nPos]);
310*ddde725dSArmin Le Grand 
311*ddde725dSArmin Le Grand                 bOnHex = (sal_Unicode('0') <= aChar && sal_Unicode('9') >= aChar)
312*ddde725dSArmin Le Grand                     || (sal_Unicode('A') <= aChar && sal_Unicode('F') >= aChar)
313*ddde725dSArmin Le Grand                     || (sal_Unicode('a') <= aChar && sal_Unicode('f') >= aChar);
314*ddde725dSArmin Le Grand 
315*ddde725dSArmin Le Grand                 if(bOnHex)
316*ddde725dSArmin Le Grand                 {
317*ddde725dSArmin Le Grand                     rTarget.append(aChar);
318*ddde725dSArmin Le Grand                     nPos++;
319*ddde725dSArmin Le Grand                 }
320*ddde725dSArmin Le Grand             }
321*ddde725dSArmin Le Grand         }
322*ddde725dSArmin Le Grand 
323*ddde725dSArmin Le Grand         void copyString(const rtl::OUString& rCandidate, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen)
324*ddde725dSArmin Le Grand         {
325*ddde725dSArmin Le Grand             bool bOnChar(true);
326*ddde725dSArmin Le Grand 
327*ddde725dSArmin Le Grand             while(bOnChar && nPos < nLen)
328*ddde725dSArmin Le Grand             {
329*ddde725dSArmin Le Grand                 const sal_Unicode aChar(rCandidate[nPos]);
330*ddde725dSArmin Le Grand 
331*ddde725dSArmin Le Grand                 bOnChar = (sal_Unicode('a') <= aChar && sal_Unicode('z') >= aChar)
332*ddde725dSArmin Le Grand                     || (sal_Unicode('A') <= aChar && sal_Unicode('Z') >= aChar)
333*ddde725dSArmin Le Grand                     || sal_Unicode('-') == aChar;
334*ddde725dSArmin Le Grand 
335*ddde725dSArmin Le Grand                 if(bOnChar)
336*ddde725dSArmin Le Grand                 {
337*ddde725dSArmin Le Grand                     rTarget.append(aChar);
338*ddde725dSArmin Le Grand                     nPos++;
339*ddde725dSArmin Le Grand                 }
340*ddde725dSArmin Le Grand             }
341*ddde725dSArmin Le Grand         }
342*ddde725dSArmin Le Grand 
343*ddde725dSArmin Le Grand         void copyToLimiter(const rtl::OUString& rCandidate, const sal_Unicode& rLimiter, sal_Int32& nPos, rtl::OUStringBuffer& rTarget, const sal_Int32 nLen)
344*ddde725dSArmin Le Grand         {
345*ddde725dSArmin Le Grand             while(nPos < nLen && rLimiter != rCandidate[nPos])
346*ddde725dSArmin Le Grand             {
347*ddde725dSArmin Le Grand                 rTarget.append(rCandidate[nPos]);
348*ddde725dSArmin Le Grand                 nPos++;
349*ddde725dSArmin Le Grand             }
350*ddde725dSArmin Le Grand         }
351*ddde725dSArmin Le Grand 
352*ddde725dSArmin Le Grand         bool readNumber(const rtl::OUString& rCandidate, sal_Int32& nPos, double& fNum, const sal_Int32 nLen)
353*ddde725dSArmin Le Grand         {
354*ddde725dSArmin Le Grand             if(nPos < nLen)
355*ddde725dSArmin Le Grand             {
356*ddde725dSArmin Le Grand                 rtl::OUStringBuffer aNum;
357*ddde725dSArmin Le Grand 
358*ddde725dSArmin Le Grand                 copySign(rCandidate, nPos, aNum, nLen);
359*ddde725dSArmin Le Grand                 copyNumber(rCandidate, nPos, aNum, nLen);
360*ddde725dSArmin Le Grand 
361*ddde725dSArmin Le Grand                 if(nPos < nLen)
362*ddde725dSArmin Le Grand                 {
363*ddde725dSArmin Le Grand                     const sal_Unicode aChar(rCandidate[nPos]);
364*ddde725dSArmin Le Grand 
365*ddde725dSArmin Le Grand                     if(sal_Unicode('e') == aChar || sal_Unicode('E') == aChar)
366*ddde725dSArmin Le Grand                     {
367*ddde725dSArmin Le Grand                         // try to read exponential number, but be careful. I had
368*ddde725dSArmin Le Grand                         // a case where dx="2em" was used, thus the 'e' was consumed
369*ddde725dSArmin Le Grand                         // by error. First try if there are numbers after the 'e',
370*ddde725dSArmin Le Grand                         // safe current state
371*ddde725dSArmin Le Grand                         nPos++;
372*ddde725dSArmin Le Grand                         const rtl::OUStringBuffer aNum2(aNum);
373*ddde725dSArmin Le Grand                         const sal_Int32 nPosAfterE(nPos);
374*ddde725dSArmin Le Grand 
375*ddde725dSArmin Le Grand                         aNum.append(aChar);
376*ddde725dSArmin Le Grand                         copySign(rCandidate, nPos, aNum, nLen);
377*ddde725dSArmin Le Grand                         copyNumber(rCandidate, nPos, aNum, nLen);
378*ddde725dSArmin Le Grand 
379*ddde725dSArmin Le Grand                         if(nPosAfterE == nPos)
380*ddde725dSArmin Le Grand                         {
381*ddde725dSArmin Le Grand                             // no number after 'e', go back. Do not
382*ddde725dSArmin Le Grand                             // return false, it's still a valid integer number
383*ddde725dSArmin Le Grand                             aNum = aNum2;
384*ddde725dSArmin Le Grand                             nPos--;
385*ddde725dSArmin Le Grand                         }
386*ddde725dSArmin Le Grand                     }
387*ddde725dSArmin Le Grand                 }
388*ddde725dSArmin Le Grand 
389*ddde725dSArmin Le Grand                 if(aNum.getLength())
390*ddde725dSArmin Le Grand                 {
391*ddde725dSArmin Le Grand                     rtl_math_ConversionStatus eStatus;
392*ddde725dSArmin Le Grand 
393*ddde725dSArmin Le Grand                     fNum = rtl::math::stringToDouble(
394*ddde725dSArmin Le Grand                         aNum.makeStringAndClear(), (sal_Unicode)('.'), (sal_Unicode)(','),
395*ddde725dSArmin Le Grand                         &eStatus, 0);
396*ddde725dSArmin Le Grand 
397*ddde725dSArmin Le Grand                     return eStatus == rtl_math_ConversionStatus_Ok;
398*ddde725dSArmin Le Grand                 }
399*ddde725dSArmin Le Grand             }
400*ddde725dSArmin Le Grand 
401*ddde725dSArmin Le Grand             return false;
402*ddde725dSArmin Le Grand         }
403*ddde725dSArmin Le Grand 
404*ddde725dSArmin Le Grand         SvgUnit readUnit(const rtl::OUString& rCandidate, sal_Int32& nPos, const sal_Int32 nLen)
405*ddde725dSArmin Le Grand         {
406*ddde725dSArmin Le Grand             SvgUnit aRetval(Unit_px);
407*ddde725dSArmin Le Grand 
408*ddde725dSArmin Le Grand             if(nPos < nLen)
409*ddde725dSArmin Le Grand             {
410*ddde725dSArmin Le Grand                 const sal_Unicode aCharA(rCandidate[nPos]);
411*ddde725dSArmin Le Grand 
412*ddde725dSArmin Le Grand                 if(nPos + 1 < nLen)
413*ddde725dSArmin Le Grand                 {
414*ddde725dSArmin Le Grand                     const sal_Unicode aCharB(rCandidate[nPos + 1]);
415*ddde725dSArmin Le Grand                     bool bTwoCharValid(false);
416*ddde725dSArmin Le Grand 
417*ddde725dSArmin Le Grand                     switch(aCharA)
418*ddde725dSArmin Le Grand                     {
419*ddde725dSArmin Le Grand                         case sal_Unicode('e') :
420*ddde725dSArmin Le Grand                         {
421*ddde725dSArmin Le Grand                             if(sal_Unicode('m') == aCharB)
422*ddde725dSArmin Le Grand                             {
423*ddde725dSArmin Le Grand                                 // 'em' Relative to current font size
424*ddde725dSArmin Le Grand                                 aRetval = Unit_em;
425*ddde725dSArmin Le Grand                                 bTwoCharValid = true;
426*ddde725dSArmin Le Grand                             }
427*ddde725dSArmin Le Grand                             else if(sal_Unicode('x') == aCharB)
428*ddde725dSArmin Le Grand                             {
429*ddde725dSArmin Le Grand                                 // 'ex' Relative to current font x-height
430*ddde725dSArmin Le Grand                                 aRetval = Unit_ex;
431*ddde725dSArmin Le Grand                                 bTwoCharValid = true;
432*ddde725dSArmin Le Grand                             }
433*ddde725dSArmin Le Grand                             break;
434*ddde725dSArmin Le Grand                         }
435*ddde725dSArmin Le Grand                         case sal_Unicode('p') :
436*ddde725dSArmin Le Grand                         {
437*ddde725dSArmin Le Grand                             if(sal_Unicode('x') == aCharB)
438*ddde725dSArmin Le Grand                             {
439*ddde725dSArmin Le Grand                                 // 'px' UserUnit (default)
440*ddde725dSArmin Le Grand                                 bTwoCharValid = true;
441*ddde725dSArmin Le Grand                             }
442*ddde725dSArmin Le Grand                             else if(sal_Unicode('t') == aCharB)
443*ddde725dSArmin Le Grand                             {
444*ddde725dSArmin Le Grand                                 // 'pt' == 1.25 px
445*ddde725dSArmin Le Grand                                 aRetval = Unit_pt;
446*ddde725dSArmin Le Grand                                 bTwoCharValid = true;
447*ddde725dSArmin Le Grand                             }
448*ddde725dSArmin Le Grand                             else if(sal_Unicode('c') == aCharB)
449*ddde725dSArmin Le Grand                             {
450*ddde725dSArmin Le Grand                                 // 'pc' == 15 px
451*ddde725dSArmin Le Grand                                 aRetval = Unit_pc;
452*ddde725dSArmin Le Grand                                 bTwoCharValid = true;
453*ddde725dSArmin Le Grand                             }
454*ddde725dSArmin Le Grand                             break;
455*ddde725dSArmin Le Grand                         }
456*ddde725dSArmin Le Grand                         case sal_Unicode('i') :
457*ddde725dSArmin Le Grand                         {
458*ddde725dSArmin Le Grand                             if(sal_Unicode('n') == aCharB)
459*ddde725dSArmin Le Grand                             {
460*ddde725dSArmin Le Grand                                 // 'in' == 90 px
461*ddde725dSArmin Le Grand                                 aRetval = Unit_in;
462*ddde725dSArmin Le Grand                                 bTwoCharValid = true;
463*ddde725dSArmin Le Grand                             }
464*ddde725dSArmin Le Grand                             break;
465*ddde725dSArmin Le Grand                         }
466*ddde725dSArmin Le Grand                         case sal_Unicode('c') :
467*ddde725dSArmin Le Grand                         {
468*ddde725dSArmin Le Grand                             if(sal_Unicode('m') == aCharB)
469*ddde725dSArmin Le Grand                             {
470*ddde725dSArmin Le Grand                                 // 'cm' == 35.43307 px
471*ddde725dSArmin Le Grand                                 aRetval = Unit_cm;
472*ddde725dSArmin Le Grand                                 bTwoCharValid = true;
473*ddde725dSArmin Le Grand                             }
474*ddde725dSArmin Le Grand                             break;
475*ddde725dSArmin Le Grand                         }
476*ddde725dSArmin Le Grand                         case sal_Unicode('m') :
477*ddde725dSArmin Le Grand                         {
478*ddde725dSArmin Le Grand                             if(sal_Unicode('m') == aCharB)
479*ddde725dSArmin Le Grand                             {
480*ddde725dSArmin Le Grand                                 // 'mm' == 3.543307 px
481*ddde725dSArmin Le Grand                                 aRetval = Unit_mm;
482*ddde725dSArmin Le Grand                                 bTwoCharValid = true;
483*ddde725dSArmin Le Grand                             }
484*ddde725dSArmin Le Grand                             break;
485*ddde725dSArmin Le Grand                         }
486*ddde725dSArmin Le Grand                     }
487*ddde725dSArmin Le Grand 
488*ddde725dSArmin Le Grand                     if(bTwoCharValid)
489*ddde725dSArmin Le Grand                     {
490*ddde725dSArmin Le Grand                         nPos += 2;
491*ddde725dSArmin Le Grand                     }
492*ddde725dSArmin Le Grand                 }
493*ddde725dSArmin Le Grand                 else
494*ddde725dSArmin Le Grand                 {
495*ddde725dSArmin Le Grand                     if(sal_Unicode('%') == aCharA)
496*ddde725dSArmin Le Grand                     {
497*ddde725dSArmin Le Grand                         // percent used, relative to current
498*ddde725dSArmin Le Grand                         nPos++;
499*ddde725dSArmin Le Grand                         aRetval = Unit_percent;
500*ddde725dSArmin Le Grand                     }
501*ddde725dSArmin Le Grand                 }
502*ddde725dSArmin Le Grand             }
503*ddde725dSArmin Le Grand 
504*ddde725dSArmin Le Grand             return aRetval;
505*ddde725dSArmin Le Grand         }
506*ddde725dSArmin Le Grand 
507*ddde725dSArmin Le Grand         bool readNumberAndUnit(const rtl::OUString& rCandidate, sal_Int32& nPos, SvgNumber& aNum, const sal_Int32 nLen)
508*ddde725dSArmin Le Grand         {
509*ddde725dSArmin Le Grand             double fNum(0.0);
510*ddde725dSArmin Le Grand 
511*ddde725dSArmin Le Grand             if(readNumber(rCandidate, nPos, fNum, nLen))
512*ddde725dSArmin Le Grand             {
513*ddde725dSArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen);
514*ddde725dSArmin Le Grand                 aNum = SvgNumber(fNum, readUnit(rCandidate, nPos, nLen));
515*ddde725dSArmin Le Grand 
516*ddde725dSArmin Le Grand                 return true;
517*ddde725dSArmin Le Grand             }
518*ddde725dSArmin Le Grand 
519*ddde725dSArmin Le Grand             return false;
520*ddde725dSArmin Le Grand         }
521*ddde725dSArmin Le Grand 
522*ddde725dSArmin Le Grand         bool readAngle(const rtl::OUString& rCandidate, sal_Int32& nPos, double& fAngle, const sal_Int32 nLen)
523*ddde725dSArmin Le Grand         {
524*ddde725dSArmin Le Grand             if(readNumber(rCandidate, nPos, fAngle, nLen))
525*ddde725dSArmin Le Grand             {
526*ddde725dSArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), nPos, nLen);
527*ddde725dSArmin Le Grand 
528*ddde725dSArmin Le Grand                 enum DegreeType
529*ddde725dSArmin Le Grand                 {
530*ddde725dSArmin Le Grand                     deg,
531*ddde725dSArmin Le Grand                     grad,
532*ddde725dSArmin Le Grand                     rad
533*ddde725dSArmin Le Grand                 } aType(deg); // degrees is default
534*ddde725dSArmin Le Grand 
535*ddde725dSArmin Le Grand                 if(nPos < nLen)
536*ddde725dSArmin Le Grand                 {
537*ddde725dSArmin Le Grand                     const sal_Unicode aChar(rCandidate[nPos]);
538*ddde725dSArmin Le Grand                     static rtl::OUString aStrGrad(rtl::OUString::createFromAscii("grad"));
539*ddde725dSArmin Le Grand                     static rtl::OUString aStrRad(rtl::OUString::createFromAscii("rad"));
540*ddde725dSArmin Le Grand 
541*ddde725dSArmin Le Grand                     switch(aChar)
542*ddde725dSArmin Le Grand                     {
543*ddde725dSArmin Le Grand                         case sal_Unicode('g') :
544*ddde725dSArmin Le Grand                         case sal_Unicode('G') :
545*ddde725dSArmin Le Grand                         {
546*ddde725dSArmin Le Grand                             if(rCandidate.matchIgnoreAsciiCase(aStrGrad, nPos))
547*ddde725dSArmin Le Grand                             {
548*ddde725dSArmin Le Grand                                 // angle in grad
549*ddde725dSArmin Le Grand                                 nPos += aStrGrad.getLength();
550*ddde725dSArmin Le Grand                             }
551*ddde725dSArmin Le Grand                             break;
552*ddde725dSArmin Le Grand                         }
553*ddde725dSArmin Le Grand                         case sal_Unicode('r') :
554*ddde725dSArmin Le Grand                         case sal_Unicode('R') :
555*ddde725dSArmin Le Grand                         {
556*ddde725dSArmin Le Grand                             if(rCandidate.matchIgnoreAsciiCase(aStrRad, nPos))
557*ddde725dSArmin Le Grand                             {
558*ddde725dSArmin Le Grand                                 // angle in radians
559*ddde725dSArmin Le Grand                                 nPos += aStrRad.getLength();
560*ddde725dSArmin Le Grand                             }
561*ddde725dSArmin Le Grand                             break;
562*ddde725dSArmin Le Grand                         }
563*ddde725dSArmin Le Grand                     }
564*ddde725dSArmin Le Grand                 }
565*ddde725dSArmin Le Grand 
566*ddde725dSArmin Le Grand                 // convert to radians
567*ddde725dSArmin Le Grand                 if(deg == aType)
568*ddde725dSArmin Le Grand                 {
569*ddde725dSArmin Le Grand                     fAngle *= F_PI / 180.0;
570*ddde725dSArmin Le Grand                 }
571*ddde725dSArmin Le Grand                 else if(grad == aType)
572*ddde725dSArmin Le Grand                 {
573*ddde725dSArmin Le Grand                     // looks like 100 grad is 90 degrees
574*ddde725dSArmin Le Grand                     fAngle *= F_PI / 200.0;
575*ddde725dSArmin Le Grand                 }
576*ddde725dSArmin Le Grand 
577*ddde725dSArmin Le Grand                 return true;
578*ddde725dSArmin Le Grand             }
579*ddde725dSArmin Le Grand 
580*ddde725dSArmin Le Grand             return false;
581*ddde725dSArmin Le Grand         }
582*ddde725dSArmin Le Grand 
583*ddde725dSArmin Le Grand         sal_Int32 read_hex(const sal_Unicode& rChar)
584*ddde725dSArmin Le Grand         {
585*ddde725dSArmin Le Grand             if(rChar >= sal_Unicode('0') && rChar <=sal_Unicode('9'))
586*ddde725dSArmin Le Grand             {
587*ddde725dSArmin Le Grand                 return sal_Int32(rChar - sal_Unicode('0'));
588*ddde725dSArmin Le Grand             }
589*ddde725dSArmin Le Grand             else if(rChar >= sal_Unicode('A') && rChar <=sal_Unicode('F'))
590*ddde725dSArmin Le Grand             {
591*ddde725dSArmin Le Grand                 return 10 + sal_Int32(rChar - sal_Unicode('A'));
592*ddde725dSArmin Le Grand             }
593*ddde725dSArmin Le Grand             else if(rChar >= sal_Unicode('a') && rChar <=sal_Unicode('f'))
594*ddde725dSArmin Le Grand             {
595*ddde725dSArmin Le Grand                 return 10 + sal_Int32(rChar - sal_Unicode('a'));
596*ddde725dSArmin Le Grand             }
597*ddde725dSArmin Le Grand             else
598*ddde725dSArmin Le Grand             {
599*ddde725dSArmin Le Grand                 // error
600*ddde725dSArmin Le Grand                 return 0;
601*ddde725dSArmin Le Grand             }
602*ddde725dSArmin Le Grand         }
603*ddde725dSArmin Le Grand 
604*ddde725dSArmin Le Grand         bool match_colorKeyword(basegfx::BColor& rColor, const rtl::OUString& rName)
605*ddde725dSArmin Le Grand         {
606*ddde725dSArmin Le Grand             typedef std::hash_map< rtl::OUString, Color, rtl::OUStringHash > ColorTokenMapper;
607*ddde725dSArmin Le Grand             typedef std::pair< rtl::OUString, Color > ColorTokenValueType;
608*ddde725dSArmin Le Grand             ColorTokenMapper aColorTokenMapperList;
609*ddde725dSArmin Le Grand 
610*ddde725dSArmin Le Grand             if(aColorTokenMapperList.empty())
611*ddde725dSArmin Le Grand             {
612*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aliceblue"), Color(240, 248, 255)));
613*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("antiquewhite"), Color(250, 235, 215)));
614*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aqua"), Color( 0, 255, 255)));
615*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("aquamarine"), Color(127, 255, 212)));
616*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("azure"), Color(240, 255, 255)));
617*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("beige"), Color(245, 245, 220)));
618*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("bisque"), Color(255, 228, 196)));
619*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("black"), Color( 0, 0, 0)));
620*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blanchedalmond"), Color(255, 235, 205)));
621*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blue"), Color( 0, 0, 255)));
622*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("blueviolet"), Color(138, 43, 226)));
623*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("brown"), Color(165, 42, 42)));
624*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("burlywood"), Color(222, 184, 135)));
625*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cadetblue"), Color( 95, 158, 160)));
626*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("chartreuse"), Color(127, 255, 0)));
627*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("chocolate"), Color(210, 105, 30)));
628*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("coral"), Color(255, 127, 80)));
629*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cornflowerblue"), Color(100, 149, 237)));
630*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cornsilk"), Color(255, 248, 220)));
631*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("crimson"), Color(220, 20, 60)));
632*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("cyan"), Color( 0, 255, 255)));
633*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkblue"), Color( 0, 0, 139)));
634*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkcyan"), Color( 0, 139, 139)));
635*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgoldenrod"), Color(184, 134, 11)));
636*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgray"), Color(169, 169, 169)));
637*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgreen"), Color( 0, 100, 0)));
638*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkgrey"), Color(169, 169, 169)));
639*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkkhaki"), Color(189, 183, 107)));
640*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkmagenta"), Color(139, 0, 139)));
641*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkolivegreen"), Color( 85, 107, 47)));
642*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkorange"), Color(255, 140, 0)));
643*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkorchid"), Color(153, 50, 204)));
644*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkred"), Color(139, 0, 0)));
645*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darksalmon"), Color(233, 150, 122)));
646*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkseagreen"), Color(143, 188, 143)));
647*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslateblue"), Color( 72, 61, 139)));
648*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslategray"), Color( 47, 79, 79)));
649*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkslategrey"), Color( 47, 79, 79)));
650*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkturquoise"), Color( 0, 206, 209)));
651*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("darkviolet"), Color(148, 0, 211)));
652*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("deeppink"), Color(255, 20, 147)));
653*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("deepskyblue"), Color( 0, 191, 255)));
654*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dimgray"), Color(105, 105, 105)));
655*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dimgrey"), Color(105, 105, 105)));
656*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("dodgerblue"), Color( 30, 144, 255)));
657*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("firebrick"), Color(178, 34, 34)));
658*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("floralwhite"), Color(255, 250, 240)));
659*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("forestgreen"), Color( 34, 139, 34)));
660*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("fuchsia"), Color(255, 0, 255)));
661*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gainsboro"), Color(220, 220, 220)));
662*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("ghostwhite"), Color(248, 248, 255)));
663*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gold"), Color(255, 215, 0)));
664*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("goldenrod"), Color(218, 165, 32)));
665*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("gray"), Color(128, 128, 128)));
666*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("grey"), Color(128, 128, 128)));
667*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("green"), Color(0, 128, 0)));
668*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("greenyellow"), Color(173, 255, 47)));
669*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("honeydew"), Color(240, 255, 240)));
670*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("hotpink"), Color(255, 105, 180)));
671*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("indianred"), Color(205, 92, 92)));
672*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("indigo"), Color( 75, 0, 130)));
673*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("ivory"), Color(255, 255, 240)));
674*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("khaki"), Color(240, 230, 140)));
675*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lavender"), Color(230, 230, 250)));
676*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lavenderblush"), Color(255, 240, 245)));
677*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lawngreen"), Color(124, 252, 0)));
678*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lemonchiffon"), Color(255, 250, 205)));
679*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightblue"), Color(173, 216, 230)));
680*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightcoral"), Color(240, 128, 128)));
681*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightcyan"), Color(224, 255, 255)));
682*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgoldenrodyellow"), Color(250, 250, 210)));
683*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgray"), Color(211, 211, 211)));
684*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgreen"), Color(144, 238, 144)));
685*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightgrey"), Color(211, 211, 211)));
686*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightpink"), Color(255, 182, 193)));
687*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightsalmon"), Color(255, 160, 122)));
688*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightseagreen"), Color( 32, 178, 170)));
689*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightskyblue"), Color(135, 206, 250)));
690*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightslategray"), Color(119, 136, 153)));
691*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightslategrey"), Color(119, 136, 153)));
692*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightsteelblue"), Color(176, 196, 222)));
693*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lightyellow"), Color(255, 255, 224)));
694*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("lime"), Color( 0, 255, 0)));
695*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("limegreen"), Color( 50, 205, 50)));
696*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("linen"), Color(250, 240, 230)));
697*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("magenta"), Color(255, 0, 255)));
698*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("maroon"), Color(128, 0, 0)));
699*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumaquamarine"), Color(102, 205, 170)));
700*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumblue"), Color( 0, 0, 205)));
701*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumorchid"), Color(186, 85, 211)));
702*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumpurple"), Color(147, 112, 219)));
703*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumseagreen"), Color( 60, 179, 113)));
704*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumslateblue"), Color(123, 104, 238)));
705*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumspringgreen"), Color( 0, 250, 154)));
706*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumturquoise"), Color( 72, 209, 204)));
707*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mediumvioletred"), Color(199, 21, 133)));
708*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("midnightblue"), Color( 25, 25, 112)));
709*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mintcream"), Color(245, 255, 250)));
710*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("mistyrose"), Color(255, 228, 225)));
711*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("moccasin"), Color(255, 228, 181)));
712*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("navajowhite"), Color(255, 222, 173)));
713*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("navy"), Color( 0, 0, 128)));
714*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("oldlace"), Color(253, 245, 230)));
715*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("olive"), Color(128, 128, 0)));
716*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("olivedrab"), Color(107, 142, 35)));
717*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orange"), Color(255, 165, 0)));
718*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orangered"), Color(255, 69, 0)));
719*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("orchid"), Color(218, 112, 214)));
720*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palegoldenrod"), Color(238, 232, 170)));
721*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palegreen"), Color(152, 251, 152)));
722*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("paleturquoise"), Color(175, 238, 238)));
723*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("palevioletred"), Color(219, 112, 147)));
724*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("papayawhip"), Color(255, 239, 213)));
725*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("peachpuff"), Color(255, 218, 185)));
726*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("peru"), Color(205, 133, 63)));
727*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("pink"), Color(255, 192, 203)));
728*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("plum"), Color(221, 160, 221)));
729*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("powderblue"), Color(176, 224, 230)));
730*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("purple"), Color(128, 0, 128)));
731*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("red"), Color(255, 0, 0)));
732*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("rosybrown"), Color(188, 143, 143)));
733*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("royalblue"), Color( 65, 105, 225)));
734*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("saddlebrown"), Color(139, 69, 19)));
735*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("salmon"), Color(250, 128, 114)));
736*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("sandybrown"), Color(244, 164, 96)));
737*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("seagreen"), Color( 46, 139, 87)));
738*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("seashell"), Color(255, 245, 238)));
739*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("sienna"), Color(160, 82, 45)));
740*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("silver"), Color(192, 192, 192)));
741*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("skyblue"), Color(135, 206, 235)));
742*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slateblue"), Color(106, 90, 205)));
743*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slategray"), Color(112, 128, 144)));
744*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("slategrey"), Color(112, 128, 144)));
745*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("snow"), Color(255, 250, 250)));
746*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("springgreen"), Color( 0, 255, 127)));
747*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("steelblue"), Color( 70, 130, 180)));
748*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("tan"), Color(210, 180, 140)));
749*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("teal"), Color( 0, 128, 128)));
750*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("thistle"), Color(216, 191, 216)));
751*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("tomato"), Color(255, 99, 71)));
752*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("turquoise"), Color( 64, 224, 208)));
753*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("violet"), Color(238, 130, 238)));
754*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("wheat"), Color(245, 222, 179)));
755*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("white"), Color(255, 255, 255)));
756*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("whitesmoke"), Color(245, 245, 245)));
757*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("yellow"), Color(255, 255, 0)));
758*ddde725dSArmin Le Grand                 aColorTokenMapperList.insert(ColorTokenValueType(rtl::OUString::createFromAscii("yellowgreen"), Color(154, 205, 50)));
759*ddde725dSArmin Le Grand             }
760*ddde725dSArmin Le Grand 
761*ddde725dSArmin Le Grand             const ColorTokenMapper::const_iterator aResult(aColorTokenMapperList.find(rName));
762*ddde725dSArmin Le Grand 
763*ddde725dSArmin Le Grand             if(aResult == aColorTokenMapperList.end())
764*ddde725dSArmin Le Grand             {
765*ddde725dSArmin Le Grand                 return false;
766*ddde725dSArmin Le Grand             }
767*ddde725dSArmin Le Grand             else
768*ddde725dSArmin Le Grand             {
769*ddde725dSArmin Le Grand                 rColor = aResult->second.getBColor();
770*ddde725dSArmin Le Grand                 return true;
771*ddde725dSArmin Le Grand             }
772*ddde725dSArmin Le Grand         }
773*ddde725dSArmin Le Grand 
774*ddde725dSArmin Le Grand         bool read_color(const rtl::OUString& rCandidate, basegfx::BColor& rColor)
775*ddde725dSArmin Le Grand         {
776*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
777*ddde725dSArmin Le Grand 
778*ddde725dSArmin Le Grand             if(nLen)
779*ddde725dSArmin Le Grand             {
780*ddde725dSArmin Le Grand                 const sal_Unicode aChar(rCandidate[0]);
781*ddde725dSArmin Le Grand                 const double fFactor(1.0 / 255.0);
782*ddde725dSArmin Le Grand 
783*ddde725dSArmin Le Grand                 if(aChar == sal_Unicode('#'))
784*ddde725dSArmin Le Grand                 {
785*ddde725dSArmin Le Grand                     // hex definition
786*ddde725dSArmin Le Grand                     rtl::OUStringBuffer aNum;
787*ddde725dSArmin Le Grand                     sal_Int32 nPos(1);
788*ddde725dSArmin Le Grand 
789*ddde725dSArmin Le Grand                     copyHex(rCandidate, nPos, aNum, nLen);
790*ddde725dSArmin Le Grand                     const sal_Int32 nLength(aNum.getLength());
791*ddde725dSArmin Le Grand 
792*ddde725dSArmin Le Grand                     if(3 == nLength)
793*ddde725dSArmin Le Grand                     {
794*ddde725dSArmin Le Grand                         const sal_Int32 nR(read_hex(aNum.charAt(0)));
795*ddde725dSArmin Le Grand                         const sal_Int32 nG(read_hex(aNum.charAt(1)));
796*ddde725dSArmin Le Grand                         const sal_Int32 nB(read_hex(aNum.charAt(2)));
797*ddde725dSArmin Le Grand 
798*ddde725dSArmin Le Grand                         rColor.setRed((nR | (nR << 4)) * fFactor);
799*ddde725dSArmin Le Grand                         rColor.setGreen((nG | (nG << 4)) * fFactor);
800*ddde725dSArmin Le Grand                         rColor.setBlue((nB | (nB << 4)) * fFactor);
801*ddde725dSArmin Le Grand 
802*ddde725dSArmin Le Grand                         return true;
803*ddde725dSArmin Le Grand                     }
804*ddde725dSArmin Le Grand                     else if(6 == nLength)
805*ddde725dSArmin Le Grand                     {
806*ddde725dSArmin Le Grand                         const sal_Int32 nR1(read_hex(aNum.charAt(0)));
807*ddde725dSArmin Le Grand                         const sal_Int32 nR2(read_hex(aNum.charAt(1)));
808*ddde725dSArmin Le Grand                         const sal_Int32 nG1(read_hex(aNum.charAt(2)));
809*ddde725dSArmin Le Grand                         const sal_Int32 nG2(read_hex(aNum.charAt(3)));
810*ddde725dSArmin Le Grand                         const sal_Int32 nB1(read_hex(aNum.charAt(4)));
811*ddde725dSArmin Le Grand                         const sal_Int32 nB2(read_hex(aNum.charAt(5)));
812*ddde725dSArmin Le Grand 
813*ddde725dSArmin Le Grand                         rColor.setRed((nR2 | (nR1 << 4)) * fFactor);
814*ddde725dSArmin Le Grand                         rColor.setGreen((nG2 | (nG1 << 4)) * fFactor);
815*ddde725dSArmin Le Grand                         rColor.setBlue((nB2 | (nB1 << 4)) * fFactor);
816*ddde725dSArmin Le Grand 
817*ddde725dSArmin Le Grand                         return true;
818*ddde725dSArmin Le Grand                     }
819*ddde725dSArmin Le Grand                 }
820*ddde725dSArmin Le Grand                 else
821*ddde725dSArmin Le Grand                 {
822*ddde725dSArmin Le Grand                     static rtl::OUString aStrRgb(rtl::OUString::createFromAscii("rgb"));
823*ddde725dSArmin Le Grand 
824*ddde725dSArmin Le Grand                     if(rCandidate.matchIgnoreAsciiCase(aStrRgb, 0))
825*ddde725dSArmin Le Grand                     {
826*ddde725dSArmin Le Grand                         // rgb definition
827*ddde725dSArmin Le Grand                         sal_Int32 nPos(aStrRgb.getLength());
828*ddde725dSArmin Le Grand                         skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen);
829*ddde725dSArmin Le Grand                         double fR(0.0);
830*ddde725dSArmin Le Grand 
831*ddde725dSArmin Le Grand                         if(readNumber(rCandidate, nPos, fR, nLen))
832*ddde725dSArmin Le Grand                         {
833*ddde725dSArmin Le Grand                             skip_char(rCandidate, sal_Unicode(' '), nPos, nLen);
834*ddde725dSArmin Le Grand 
835*ddde725dSArmin Le Grand                             if(nPos < nLen)
836*ddde725dSArmin Le Grand                             {
837*ddde725dSArmin Le Grand                                 const sal_Unicode aChar(rCandidate[nPos]);
838*ddde725dSArmin Le Grand                                 const bool bIsPercent(sal_Unicode('%') == aChar);
839*ddde725dSArmin Le Grand                                 double fG(0.0);
840*ddde725dSArmin Le Grand 
841*ddde725dSArmin Le Grand                                 if(bIsPercent)
842*ddde725dSArmin Le Grand                                 {
843*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode('%'), nPos, nLen);
844*ddde725dSArmin Le Grand                                 }
845*ddde725dSArmin Le Grand 
846*ddde725dSArmin Le Grand                                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
847*ddde725dSArmin Le Grand 
848*ddde725dSArmin Le Grand                                 if(readNumber(rCandidate, nPos, fG, nLen))
849*ddde725dSArmin Le Grand                                 {
850*ddde725dSArmin Le Grand                                     double fB(0.0);
851*ddde725dSArmin Le Grand 
852*ddde725dSArmin Le Grand                                     if(bIsPercent)
853*ddde725dSArmin Le Grand                                     {
854*ddde725dSArmin Le Grand                                         skip_char(rCandidate, sal_Unicode('%'), nPos, nLen);
855*ddde725dSArmin Le Grand                                     }
856*ddde725dSArmin Le Grand 
857*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
858*ddde725dSArmin Le Grand 
859*ddde725dSArmin Le Grand                                     if(readNumber(rCandidate, nPos, fB, nLen))
860*ddde725dSArmin Le Grand                                     {
861*ddde725dSArmin Le Grand                                         const double fFac(bIsPercent ? 0.01 : fFactor);
862*ddde725dSArmin Le Grand 
863*ddde725dSArmin Le Grand                                         rColor.setRed(fR * fFac);
864*ddde725dSArmin Le Grand                                         rColor.setGreen(fG * fFac);
865*ddde725dSArmin Le Grand                                         rColor.setBlue(fB * fFac);
866*ddde725dSArmin Le Grand 
867*ddde725dSArmin Le Grand                                         if(bIsPercent)
868*ddde725dSArmin Le Grand                                         {
869*ddde725dSArmin Le Grand                                             skip_char(rCandidate, sal_Unicode('%'), nPos, nLen);
870*ddde725dSArmin Le Grand                                         }
871*ddde725dSArmin Le Grand 
872*ddde725dSArmin Le Grand                                         skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen);
873*ddde725dSArmin Le Grand                                         return true;
874*ddde725dSArmin Le Grand                                     }
875*ddde725dSArmin Le Grand                                 }
876*ddde725dSArmin Le Grand                             }
877*ddde725dSArmin Le Grand                         }
878*ddde725dSArmin Le Grand                     }
879*ddde725dSArmin Le Grand                     else
880*ddde725dSArmin Le Grand                     {
881*ddde725dSArmin Le Grand                         // color keyword
882*ddde725dSArmin Le Grand                         if(match_colorKeyword(rColor, rCandidate))
883*ddde725dSArmin Le Grand                         {
884*ddde725dSArmin Le Grand                             return true;
885*ddde725dSArmin Le Grand                         }
886*ddde725dSArmin Le Grand                     }
887*ddde725dSArmin Le Grand                 }
888*ddde725dSArmin Le Grand             }
889*ddde725dSArmin Le Grand 
890*ddde725dSArmin Le Grand             return false;
891*ddde725dSArmin Le Grand         }
892*ddde725dSArmin Le Grand 
893*ddde725dSArmin Le Grand         basegfx::B2DRange readViewBox(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider)
894*ddde725dSArmin Le Grand         {
895*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
896*ddde725dSArmin Le Grand 
897*ddde725dSArmin Le Grand             if(nLen)
898*ddde725dSArmin Le Grand             {
899*ddde725dSArmin Le Grand                 sal_Int32 nPos(0);
900*ddde725dSArmin Le Grand                 SvgNumber aMinX;
901*ddde725dSArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
902*ddde725dSArmin Le Grand 
903*ddde725dSArmin Le Grand                 if(readNumberAndUnit(rCandidate, nPos, aMinX, nLen))
904*ddde725dSArmin Le Grand                 {
905*ddde725dSArmin Le Grand                     SvgNumber aMinY;
906*ddde725dSArmin Le Grand                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
907*ddde725dSArmin Le Grand 
908*ddde725dSArmin Le Grand                     if(readNumberAndUnit(rCandidate, nPos, aMinY, nLen))
909*ddde725dSArmin Le Grand                     {
910*ddde725dSArmin Le Grand                         SvgNumber aWidth;
911*ddde725dSArmin Le Grand                         skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
912*ddde725dSArmin Le Grand 
913*ddde725dSArmin Le Grand                         if(readNumberAndUnit(rCandidate, nPos, aWidth, nLen))
914*ddde725dSArmin Le Grand                         {
915*ddde725dSArmin Le Grand                             SvgNumber aHeight;
916*ddde725dSArmin Le Grand                             skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
917*ddde725dSArmin Le Grand 
918*ddde725dSArmin Le Grand                             if(readNumberAndUnit(rCandidate, nPos, aHeight, nLen))
919*ddde725dSArmin Le Grand                             {
920*ddde725dSArmin Le Grand                                 return basegfx::B2DRange(
921*ddde725dSArmin Le Grand                                     aMinX.solve(rInfoProvider, xcoordinate),
922*ddde725dSArmin Le Grand                                     aMinY.solve(rInfoProvider, ycoordinate),
923*ddde725dSArmin Le Grand                                     aWidth.solve(rInfoProvider, xcoordinate),
924*ddde725dSArmin Le Grand                                     aHeight.solve(rInfoProvider, ycoordinate));
925*ddde725dSArmin Le Grand                             }
926*ddde725dSArmin Le Grand                         }
927*ddde725dSArmin Le Grand                     }
928*ddde725dSArmin Le Grand                 }
929*ddde725dSArmin Le Grand             }
930*ddde725dSArmin Le Grand 
931*ddde725dSArmin Le Grand             return basegfx::B2DRange();
932*ddde725dSArmin Le Grand         }
933*ddde725dSArmin Le Grand 
934*ddde725dSArmin Le Grand         basegfx::B2DHomMatrix readTransform(const rtl::OUString& rCandidate, InfoProvider& rInfoProvider)
935*ddde725dSArmin Le Grand         {
936*ddde725dSArmin Le Grand             basegfx::B2DHomMatrix aMatrix;
937*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
938*ddde725dSArmin Le Grand 
939*ddde725dSArmin Le Grand             if(nLen)
940*ddde725dSArmin Le Grand             {
941*ddde725dSArmin Le Grand                 sal_Int32 nPos(0);
942*ddde725dSArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
943*ddde725dSArmin Le Grand 
944*ddde725dSArmin Le Grand                 while(nPos < nLen)
945*ddde725dSArmin Le Grand                 {
946*ddde725dSArmin Le Grand                     const sal_Unicode aChar(rCandidate[nPos]);
947*ddde725dSArmin Le Grand                     const sal_Int32 nInitPos(nPos);
948*ddde725dSArmin Le Grand                     static rtl::OUString aStrMatrix(rtl::OUString::createFromAscii("matrix"));
949*ddde725dSArmin Le Grand                     static rtl::OUString aStrTranslate(rtl::OUString::createFromAscii("translate"));
950*ddde725dSArmin Le Grand                     static rtl::OUString aStrScale(rtl::OUString::createFromAscii("scale"));
951*ddde725dSArmin Le Grand                     static rtl::OUString aStrRotate(rtl::OUString::createFromAscii("rotate"));
952*ddde725dSArmin Le Grand                     static rtl::OUString aStrSkewX(rtl::OUString::createFromAscii("skewX"));
953*ddde725dSArmin Le Grand                     static rtl::OUString aStrSkewY(rtl::OUString::createFromAscii("skewY"));
954*ddde725dSArmin Le Grand 
955*ddde725dSArmin Le Grand                     switch(aChar)
956*ddde725dSArmin Le Grand                     {
957*ddde725dSArmin Le Grand                         case sal_Unicode('m') :
958*ddde725dSArmin Le Grand                         {
959*ddde725dSArmin Le Grand                             if(rCandidate.match(aStrMatrix, nPos))
960*ddde725dSArmin Le Grand                             {
961*ddde725dSArmin Le Grand                                 // matrix element
962*ddde725dSArmin Le Grand                                 nPos += aStrMatrix.getLength();
963*ddde725dSArmin Le Grand                                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen);
964*ddde725dSArmin Le Grand                                 SvgNumber aVal;
965*ddde725dSArmin Le Grand                                 basegfx::B2DHomMatrix aNew;
966*ddde725dSArmin Le Grand 
967*ddde725dSArmin Le Grand                                 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen))
968*ddde725dSArmin Le Grand                                 {
969*ddde725dSArmin Le Grand                                     aNew.set(0, 0, aVal.solve(rInfoProvider)); // Element A
970*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
971*ddde725dSArmin Le Grand 
972*ddde725dSArmin Le Grand                                     if(readNumberAndUnit(rCandidate, nPos, aVal, nLen))
973*ddde725dSArmin Le Grand                                     {
974*ddde725dSArmin Le Grand                                         aNew.set(1, 0, aVal.solve(rInfoProvider)); // Element B
975*ddde725dSArmin Le Grand                                         skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
976*ddde725dSArmin Le Grand 
977*ddde725dSArmin Le Grand                                         if(readNumberAndUnit(rCandidate, nPos, aVal, nLen))
978*ddde725dSArmin Le Grand                                         {
979*ddde725dSArmin Le Grand                                             aNew.set(0, 1, aVal.solve(rInfoProvider)); // Element C
980*ddde725dSArmin Le Grand                                             skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
981*ddde725dSArmin Le Grand 
982*ddde725dSArmin Le Grand                                             if(readNumberAndUnit(rCandidate, nPos, aVal, nLen))
983*ddde725dSArmin Le Grand                                             {
984*ddde725dSArmin Le Grand                                                 aNew.set(1, 1, aVal.solve(rInfoProvider)); // Element D
985*ddde725dSArmin Le Grand                                                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
986*ddde725dSArmin Le Grand 
987*ddde725dSArmin Le Grand                                                 if(readNumberAndUnit(rCandidate, nPos, aVal, nLen))
988*ddde725dSArmin Le Grand                                                 {
989*ddde725dSArmin Le Grand                                                     aNew.set(0, 2, aVal.solve(rInfoProvider, xcoordinate)); // Element E
990*ddde725dSArmin Le Grand                                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
991*ddde725dSArmin Le Grand 
992*ddde725dSArmin Le Grand                                                     if(readNumberAndUnit(rCandidate, nPos, aVal, nLen))
993*ddde725dSArmin Le Grand                                                     {
994*ddde725dSArmin Le Grand                                                         aNew.set(1, 2, aVal.solve(rInfoProvider, ycoordinate)); // Element F
995*ddde725dSArmin Le Grand                                                         skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen);
996*ddde725dSArmin Le Grand                                                         skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
997*ddde725dSArmin Le Grand 
998*ddde725dSArmin Le Grand                                                         // caution: String is evaluated from left to right, but matrix multiplication
999*ddde725dSArmin Le Grand                                                         // in SVG is right to left, so put the new transformation before the current
1000*ddde725dSArmin Le Grand                                                         // one by multiplicating from the right side
1001*ddde725dSArmin Le Grand                                                         aMatrix = aMatrix * aNew;
1002*ddde725dSArmin Le Grand                                                     }
1003*ddde725dSArmin Le Grand                                                 }
1004*ddde725dSArmin Le Grand                                             }
1005*ddde725dSArmin Le Grand                                         }
1006*ddde725dSArmin Le Grand                                     }
1007*ddde725dSArmin Le Grand                                 }
1008*ddde725dSArmin Le Grand                             }
1009*ddde725dSArmin Le Grand                             break;
1010*ddde725dSArmin Le Grand                         }
1011*ddde725dSArmin Le Grand                         case sal_Unicode('t') :
1012*ddde725dSArmin Le Grand                         {
1013*ddde725dSArmin Le Grand                             if(rCandidate.match(aStrTranslate, nPos))
1014*ddde725dSArmin Le Grand                             {
1015*ddde725dSArmin Le Grand                                 // translate element
1016*ddde725dSArmin Le Grand                                 nPos += aStrTranslate.getLength();
1017*ddde725dSArmin Le Grand                                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen);
1018*ddde725dSArmin Le Grand                                 SvgNumber aTransX;
1019*ddde725dSArmin Le Grand 
1020*ddde725dSArmin Le Grand                                 if(readNumberAndUnit(rCandidate, nPos, aTransX, nLen))
1021*ddde725dSArmin Le Grand                                 {
1022*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1023*ddde725dSArmin Le Grand                                     SvgNumber aTransY;
1024*ddde725dSArmin Le Grand                                     readNumberAndUnit(rCandidate, nPos, aTransY, nLen);
1025*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen);
1026*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1027*ddde725dSArmin Le Grand 
1028*ddde725dSArmin Le Grand                                     aMatrix = aMatrix * basegfx::tools::createTranslateB2DHomMatrix(
1029*ddde725dSArmin Le Grand                                         aTransX.solve(rInfoProvider, xcoordinate),
1030*ddde725dSArmin Le Grand                                         aTransY.solve(rInfoProvider, ycoordinate));
1031*ddde725dSArmin Le Grand                                 }
1032*ddde725dSArmin Le Grand                             }
1033*ddde725dSArmin Le Grand                             break;
1034*ddde725dSArmin Le Grand                         }
1035*ddde725dSArmin Le Grand                         case sal_Unicode('s') :
1036*ddde725dSArmin Le Grand                         {
1037*ddde725dSArmin Le Grand                             if(rCandidate.match(aStrScale, nPos))
1038*ddde725dSArmin Le Grand                             {
1039*ddde725dSArmin Le Grand                                 // scale element
1040*ddde725dSArmin Le Grand                                 nPos += aStrScale.getLength();
1041*ddde725dSArmin Le Grand                                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen);
1042*ddde725dSArmin Le Grand                                 SvgNumber aScaleX;
1043*ddde725dSArmin Le Grand 
1044*ddde725dSArmin Le Grand                                 if(readNumberAndUnit(rCandidate, nPos, aScaleX, nLen))
1045*ddde725dSArmin Le Grand                                 {
1046*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1047*ddde725dSArmin Le Grand                                     SvgNumber aScaleY(aScaleX);
1048*ddde725dSArmin Le Grand                                     readNumberAndUnit(rCandidate, nPos, aScaleY, nLen);
1049*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen);
1050*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1051*ddde725dSArmin Le Grand 
1052*ddde725dSArmin Le Grand                                     aMatrix = aMatrix * basegfx::tools::createScaleB2DHomMatrix(
1053*ddde725dSArmin Le Grand                                         aScaleX.solve(rInfoProvider),
1054*ddde725dSArmin Le Grand                                         aScaleY.solve(rInfoProvider));
1055*ddde725dSArmin Le Grand                                 }
1056*ddde725dSArmin Le Grand                             }
1057*ddde725dSArmin Le Grand                             else if(rCandidate.match(aStrSkewX, nPos))
1058*ddde725dSArmin Le Grand                             {
1059*ddde725dSArmin Le Grand                                 // skewx element
1060*ddde725dSArmin Le Grand                                 nPos += aStrSkewX.getLength();
1061*ddde725dSArmin Le Grand                                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen);
1062*ddde725dSArmin Le Grand                                 double fSkewX(0.0);
1063*ddde725dSArmin Le Grand 
1064*ddde725dSArmin Le Grand                                 if(readAngle(rCandidate, nPos, fSkewX, nLen))
1065*ddde725dSArmin Le Grand                                 {
1066*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen);
1067*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1068*ddde725dSArmin Le Grand 
1069*ddde725dSArmin Le Grand                                     aMatrix = aMatrix * basegfx::tools::createShearXB2DHomMatrix(tan(fSkewX));
1070*ddde725dSArmin Le Grand                                 }
1071*ddde725dSArmin Le Grand                             }
1072*ddde725dSArmin Le Grand                             else if(rCandidate.match(aStrSkewY, nPos))
1073*ddde725dSArmin Le Grand                             {
1074*ddde725dSArmin Le Grand                                 // skewy element
1075*ddde725dSArmin Le Grand                                 nPos += aStrSkewY.getLength();
1076*ddde725dSArmin Le Grand                                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen);
1077*ddde725dSArmin Le Grand                                 double fSkewY(0.0);
1078*ddde725dSArmin Le Grand 
1079*ddde725dSArmin Le Grand                                 if(readAngle(rCandidate, nPos, fSkewY, nLen))
1080*ddde725dSArmin Le Grand                                 {
1081*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen);
1082*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1083*ddde725dSArmin Le Grand 
1084*ddde725dSArmin Le Grand                                     aMatrix = aMatrix * basegfx::tools::createShearYB2DHomMatrix(tan(fSkewY));
1085*ddde725dSArmin Le Grand                                 }
1086*ddde725dSArmin Le Grand                             }
1087*ddde725dSArmin Le Grand                             break;
1088*ddde725dSArmin Le Grand                         }
1089*ddde725dSArmin Le Grand                         case sal_Unicode('r') :
1090*ddde725dSArmin Le Grand                         {
1091*ddde725dSArmin Le Grand                             if(rCandidate.match(aStrRotate, nPos))
1092*ddde725dSArmin Le Grand                             {
1093*ddde725dSArmin Le Grand                                 // rotate element
1094*ddde725dSArmin Le Grand                                 nPos += aStrRotate.getLength();
1095*ddde725dSArmin Le Grand                                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode('('), nPos, nLen);
1096*ddde725dSArmin Le Grand                                 double fAngle(0.0);
1097*ddde725dSArmin Le Grand 
1098*ddde725dSArmin Le Grand                                 if(readAngle(rCandidate, nPos, fAngle, nLen))
1099*ddde725dSArmin Le Grand                                 {
1100*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1101*ddde725dSArmin Le Grand                                     SvgNumber aX;
1102*ddde725dSArmin Le Grand                                     readNumberAndUnit(rCandidate, nPos, aX, nLen);
1103*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1104*ddde725dSArmin Le Grand                                     SvgNumber aY;
1105*ddde725dSArmin Le Grand                                     readNumberAndUnit(rCandidate, nPos, aY, nLen);
1106*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(')'), nPos, nLen);
1107*ddde725dSArmin Le Grand                                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1108*ddde725dSArmin Le Grand 
1109*ddde725dSArmin Le Grand                                     const double fX(aX.isSet() ? aX.solve(rInfoProvider, xcoordinate) : 0.0);
1110*ddde725dSArmin Le Grand                                     const double fY(aY.isSet() ? aY.solve(rInfoProvider, ycoordinate) : 0.0);
1111*ddde725dSArmin Le Grand 
1112*ddde725dSArmin Le Grand                                     if(!basegfx::fTools::equalZero(fX) || !basegfx::fTools::equalZero(fY))
1113*ddde725dSArmin Le Grand                                     {
1114*ddde725dSArmin Le Grand                                         // rotate around point
1115*ddde725dSArmin Le Grand                                         aMatrix = aMatrix * basegfx::tools::createRotateAroundPoint(fX, fY, fAngle);
1116*ddde725dSArmin Le Grand                                     }
1117*ddde725dSArmin Le Grand                                     else
1118*ddde725dSArmin Le Grand                                     {
1119*ddde725dSArmin Le Grand                                         // rotate
1120*ddde725dSArmin Le Grand                                         aMatrix = aMatrix * basegfx::tools::createRotateB2DHomMatrix(fAngle);
1121*ddde725dSArmin Le Grand                                     }
1122*ddde725dSArmin Le Grand                                 }
1123*ddde725dSArmin Le Grand                             }
1124*ddde725dSArmin Le Grand                             break;
1125*ddde725dSArmin Le Grand                         }
1126*ddde725dSArmin Le Grand                     }
1127*ddde725dSArmin Le Grand 
1128*ddde725dSArmin Le Grand                     if(nInitPos == nPos)
1129*ddde725dSArmin Le Grand                     {
1130*ddde725dSArmin Le Grand                         OSL_ENSURE(false, "Could not interpret on current position (!)");
1131*ddde725dSArmin Le Grand                         nPos++;
1132*ddde725dSArmin Le Grand                     }
1133*ddde725dSArmin Le Grand                 }
1134*ddde725dSArmin Le Grand             }
1135*ddde725dSArmin Le Grand 
1136*ddde725dSArmin Le Grand             return aMatrix;
1137*ddde725dSArmin Le Grand         }
1138*ddde725dSArmin Le Grand 
1139*ddde725dSArmin Le Grand         bool readSingleNumber(const rtl::OUString& rCandidate, SvgNumber& aNum)
1140*ddde725dSArmin Le Grand         {
1141*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
1142*ddde725dSArmin Le Grand             sal_Int32 nPos(0);
1143*ddde725dSArmin Le Grand 
1144*ddde725dSArmin Le Grand             return readNumberAndUnit(rCandidate, nPos, aNum, nLen);
1145*ddde725dSArmin Le Grand         }
1146*ddde725dSArmin Le Grand 
1147*ddde725dSArmin Le Grand         bool readLocalUrl(const rtl::OUString& rCandidate, rtl::OUString& rURL)
1148*ddde725dSArmin Le Grand         {
1149*ddde725dSArmin Le Grand             static rtl::OUString aStrUrl(rtl::OUString::createFromAscii("url"));
1150*ddde725dSArmin Le Grand 
1151*ddde725dSArmin Le Grand             if(rCandidate.match(aStrUrl, 0))
1152*ddde725dSArmin Le Grand             {
1153*ddde725dSArmin Le Grand                 const sal_Int32 nLen(rCandidate.getLength());
1154*ddde725dSArmin Le Grand                 sal_Int32 nPos(aStrUrl.getLength());
1155*ddde725dSArmin Le Grand 
1156*ddde725dSArmin Le Grand                 skip_char(rCandidate, sal_Unicode('('), sal_Unicode('#'), nPos, nLen);
1157*ddde725dSArmin Le Grand                 rtl::OUStringBuffer aTokenValue;
1158*ddde725dSArmin Le Grand                 copyToLimiter(rCandidate, sal_Unicode(')'), nPos, aTokenValue, nLen);
1159*ddde725dSArmin Le Grand                 rURL = aTokenValue.makeStringAndClear();
1160*ddde725dSArmin Le Grand 
1161*ddde725dSArmin Le Grand                 return true;
1162*ddde725dSArmin Le Grand             }
1163*ddde725dSArmin Le Grand 
1164*ddde725dSArmin Le Grand             return false;
1165*ddde725dSArmin Le Grand         }
1166*ddde725dSArmin Le Grand 
1167*ddde725dSArmin Le Grand         bool readSvgPaint(const rtl::OUString& rCandidate, SvgPaint& rSvgPaint, rtl::OUString& rURL)
1168*ddde725dSArmin Le Grand         {
1169*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
1170*ddde725dSArmin Le Grand 
1171*ddde725dSArmin Le Grand             if(nLen)
1172*ddde725dSArmin Le Grand             {
1173*ddde725dSArmin Le Grand                 basegfx::BColor aColor;
1174*ddde725dSArmin Le Grand 
1175*ddde725dSArmin Le Grand                 if(read_color(rCandidate, aColor))
1176*ddde725dSArmin Le Grand                 {
1177*ddde725dSArmin Le Grand                     rSvgPaint = SvgPaint(aColor, true, true);
1178*ddde725dSArmin Le Grand                     return true;
1179*ddde725dSArmin Le Grand                 }
1180*ddde725dSArmin Le Grand                 else
1181*ddde725dSArmin Le Grand                 {
1182*ddde725dSArmin Le Grand                     static rtl::OUString aStrNone(rtl::OUString::createFromAscii("none"));
1183*ddde725dSArmin Le Grand                     static rtl::OUString aStrCurrentColor(rtl::OUString::createFromAscii("currentColor"));
1184*ddde725dSArmin Le Grand 
1185*ddde725dSArmin Le Grand                     if(rCandidate.match(aStrNone, 0))
1186*ddde725dSArmin Le Grand                     {
1187*ddde725dSArmin Le Grand                         rSvgPaint = SvgPaint(aColor, true, false, false);
1188*ddde725dSArmin Le Grand                         return true;
1189*ddde725dSArmin Le Grand                     }
1190*ddde725dSArmin Le Grand                     else if(readLocalUrl(rCandidate, rURL))
1191*ddde725dSArmin Le Grand                     {
1192*ddde725dSArmin Le Grand                         /// Url is copied to rURL, but needs to be solved outside this helper
1193*ddde725dSArmin Le Grand                         return false;
1194*ddde725dSArmin Le Grand                     }
1195*ddde725dSArmin Le Grand                     else if(rCandidate.match(aStrCurrentColor, 0))
1196*ddde725dSArmin Le Grand                     {
1197*ddde725dSArmin Le Grand                         rSvgPaint = SvgPaint(aColor, true, true, true);
1198*ddde725dSArmin Le Grand                         return true;
1199*ddde725dSArmin Le Grand                     }
1200*ddde725dSArmin Le Grand                 }
1201*ddde725dSArmin Le Grand             }
1202*ddde725dSArmin Le Grand 
1203*ddde725dSArmin Le Grand             return false;
1204*ddde725dSArmin Le Grand         }
1205*ddde725dSArmin Le Grand 
1206*ddde725dSArmin Le Grand         bool readSvgNumberVector(const rtl::OUString& rCandidate, SvgNumberVector& rSvgNumberVector)
1207*ddde725dSArmin Le Grand         {
1208*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
1209*ddde725dSArmin Le Grand             rSvgNumberVector.clear();
1210*ddde725dSArmin Le Grand 
1211*ddde725dSArmin Le Grand             if(nLen)
1212*ddde725dSArmin Le Grand             {
1213*ddde725dSArmin Le Grand                 sal_Int32 nPos(0);
1214*ddde725dSArmin Le Grand                 SvgNumber aNum;
1215*ddde725dSArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1216*ddde725dSArmin Le Grand 
1217*ddde725dSArmin Le Grand                 while(readNumberAndUnit(rCandidate, nPos, aNum, nLen))
1218*ddde725dSArmin Le Grand                 {
1219*ddde725dSArmin Le Grand                     rSvgNumberVector.push_back(aNum);
1220*ddde725dSArmin Le Grand                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1221*ddde725dSArmin Le Grand                 }
1222*ddde725dSArmin Le Grand 
1223*ddde725dSArmin Le Grand                 return !rSvgNumberVector.empty();
1224*ddde725dSArmin Le Grand             }
1225*ddde725dSArmin Le Grand 
1226*ddde725dSArmin Le Grand             return false;
1227*ddde725dSArmin Le Grand         }
1228*ddde725dSArmin Le Grand 
1229*ddde725dSArmin Le Grand         SvgAspectRatio readSvgAspectRatio(const rtl::OUString& rCandidate)
1230*ddde725dSArmin Le Grand         {
1231*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
1232*ddde725dSArmin Le Grand 
1233*ddde725dSArmin Le Grand             if(nLen)
1234*ddde725dSArmin Le Grand             {
1235*ddde725dSArmin Le Grand                 sal_Int32 nPos(0);
1236*ddde725dSArmin Le Grand                 SvgAlign aSvgAlign(Align_xMidYMid);
1237*ddde725dSArmin Le Grand                 bool bDefer(false);
1238*ddde725dSArmin Le Grand                 bool bMeetOrSlice(true);
1239*ddde725dSArmin Le Grand                 bool bChanged(false);
1240*ddde725dSArmin Le Grand 
1241*ddde725dSArmin Le Grand                 while(nPos < nLen)
1242*ddde725dSArmin Le Grand                 {
1243*ddde725dSArmin Le Grand                     const sal_Int32 nInitPos(nPos);
1244*ddde725dSArmin Le Grand                     skip_char(rCandidate, sal_Unicode(' '), nPos, nLen);
1245*ddde725dSArmin Le Grand                     rtl::OUStringBuffer aTokenName;
1246*ddde725dSArmin Le Grand                     copyString(rCandidate, nPos, aTokenName, nLen);
1247*ddde725dSArmin Le Grand 
1248*ddde725dSArmin Le Grand                     if(aTokenName.getLength())
1249*ddde725dSArmin Le Grand                     {
1250*ddde725dSArmin Le Grand                         switch(StrToSVGToken(aTokenName.makeStringAndClear()))
1251*ddde725dSArmin Le Grand                         {
1252*ddde725dSArmin Le Grand                             case SVGTokenDefer:
1253*ddde725dSArmin Le Grand                             {
1254*ddde725dSArmin Le Grand                                 bDefer = true;
1255*ddde725dSArmin Le Grand                                 bChanged = true;
1256*ddde725dSArmin Le Grand                                 break;
1257*ddde725dSArmin Le Grand                             }
1258*ddde725dSArmin Le Grand                             case SVGTokenNone:
1259*ddde725dSArmin Le Grand                             {
1260*ddde725dSArmin Le Grand                                 aSvgAlign = Align_none;
1261*ddde725dSArmin Le Grand                                 bChanged = true;
1262*ddde725dSArmin Le Grand                                 break;
1263*ddde725dSArmin Le Grand                             }
1264*ddde725dSArmin Le Grand                             case SVGTokenXMinYMin:
1265*ddde725dSArmin Le Grand                             {
1266*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMinYMin;
1267*ddde725dSArmin Le Grand                                 bChanged = true;
1268*ddde725dSArmin Le Grand                                 break;
1269*ddde725dSArmin Le Grand                             }
1270*ddde725dSArmin Le Grand                             case SVGTokenXMidYMin:
1271*ddde725dSArmin Le Grand                             {
1272*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMidYMin;
1273*ddde725dSArmin Le Grand                                 bChanged = true;
1274*ddde725dSArmin Le Grand                                 break;
1275*ddde725dSArmin Le Grand                             }
1276*ddde725dSArmin Le Grand                             case SVGTokenXMaxYMin:
1277*ddde725dSArmin Le Grand                             {
1278*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMaxYMin;
1279*ddde725dSArmin Le Grand                                 bChanged = true;
1280*ddde725dSArmin Le Grand                                 break;
1281*ddde725dSArmin Le Grand                             }
1282*ddde725dSArmin Le Grand                             case SVGTokenXMinYMid:
1283*ddde725dSArmin Le Grand                             {
1284*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMinYMid;
1285*ddde725dSArmin Le Grand                                 bChanged = true;
1286*ddde725dSArmin Le Grand                                 break;
1287*ddde725dSArmin Le Grand                             }
1288*ddde725dSArmin Le Grand                             case SVGTokenXMidYMid:
1289*ddde725dSArmin Le Grand                             {
1290*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMidYMid;
1291*ddde725dSArmin Le Grand                                 bChanged = true;
1292*ddde725dSArmin Le Grand                                 break;
1293*ddde725dSArmin Le Grand                             }
1294*ddde725dSArmin Le Grand                             case SVGTokenXMaxYMid:
1295*ddde725dSArmin Le Grand                             {
1296*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMaxYMid;
1297*ddde725dSArmin Le Grand                                 bChanged = true;
1298*ddde725dSArmin Le Grand                                 break;
1299*ddde725dSArmin Le Grand                             }
1300*ddde725dSArmin Le Grand                             case SVGTokenXMinYMax:
1301*ddde725dSArmin Le Grand                             {
1302*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMinYMax;
1303*ddde725dSArmin Le Grand                                 bChanged = true;
1304*ddde725dSArmin Le Grand                                 break;
1305*ddde725dSArmin Le Grand                             }
1306*ddde725dSArmin Le Grand                             case SVGTokenXMidYMax:
1307*ddde725dSArmin Le Grand                             {
1308*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMidYMax;
1309*ddde725dSArmin Le Grand                                 bChanged = true;
1310*ddde725dSArmin Le Grand                                 break;
1311*ddde725dSArmin Le Grand                             }
1312*ddde725dSArmin Le Grand                             case SVGTokenXMaxYMax:
1313*ddde725dSArmin Le Grand                             {
1314*ddde725dSArmin Le Grand                                 aSvgAlign = Align_xMaxYMax;
1315*ddde725dSArmin Le Grand                                 bChanged = true;
1316*ddde725dSArmin Le Grand                                 break;
1317*ddde725dSArmin Le Grand                             }
1318*ddde725dSArmin Le Grand                             case SVGTokenMeet:
1319*ddde725dSArmin Le Grand                             {
1320*ddde725dSArmin Le Grand                                 bMeetOrSlice = true;
1321*ddde725dSArmin Le Grand                                 bChanged = true;
1322*ddde725dSArmin Le Grand                                 break;
1323*ddde725dSArmin Le Grand                             }
1324*ddde725dSArmin Le Grand                             case SVGTokenSlice:
1325*ddde725dSArmin Le Grand                             {
1326*ddde725dSArmin Le Grand                                 bMeetOrSlice = false;
1327*ddde725dSArmin Le Grand                                 bChanged = true;
1328*ddde725dSArmin Le Grand                                 break;
1329*ddde725dSArmin Le Grand                             }
1330*ddde725dSArmin Le Grand                         }
1331*ddde725dSArmin Le Grand                     }
1332*ddde725dSArmin Le Grand 
1333*ddde725dSArmin Le Grand                     if(nInitPos == nPos)
1334*ddde725dSArmin Le Grand                     {
1335*ddde725dSArmin Le Grand                         OSL_ENSURE(false, "Could not interpret on current position (!)");
1336*ddde725dSArmin Le Grand                         nPos++;
1337*ddde725dSArmin Le Grand                     }
1338*ddde725dSArmin Le Grand                 }
1339*ddde725dSArmin Le Grand 
1340*ddde725dSArmin Le Grand                 if(bChanged)
1341*ddde725dSArmin Le Grand                 {
1342*ddde725dSArmin Le Grand                     return SvgAspectRatio(aSvgAlign, bDefer, bMeetOrSlice);
1343*ddde725dSArmin Le Grand                 }
1344*ddde725dSArmin Le Grand             }
1345*ddde725dSArmin Le Grand 
1346*ddde725dSArmin Le Grand             return SvgAspectRatio();
1347*ddde725dSArmin Le Grand         }
1348*ddde725dSArmin Le Grand 
1349*ddde725dSArmin Le Grand         bool readSvgStringVector(const rtl::OUString& rCandidate, SvgStringVector& rSvgStringVector)
1350*ddde725dSArmin Le Grand         {
1351*ddde725dSArmin Le Grand             rSvgStringVector.clear();
1352*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
1353*ddde725dSArmin Le Grand 
1354*ddde725dSArmin Le Grand             if(nLen)
1355*ddde725dSArmin Le Grand             {
1356*ddde725dSArmin Le Grand                 sal_Int32 nPos(0);
1357*ddde725dSArmin Le Grand                 rtl::OUStringBuffer aTokenValue;
1358*ddde725dSArmin Le Grand                 skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1359*ddde725dSArmin Le Grand 
1360*ddde725dSArmin Le Grand                 while(nPos < nLen)
1361*ddde725dSArmin Le Grand                 {
1362*ddde725dSArmin Le Grand                     copyToLimiter(rCandidate, sal_Unicode(','), nPos, aTokenValue, nLen);
1363*ddde725dSArmin Le Grand                     skip_char(rCandidate, sal_Unicode(','), sal_Unicode(' '), nPos, nLen);
1364*ddde725dSArmin Le Grand                     const rtl::OUString aString = aTokenValue.makeStringAndClear();
1365*ddde725dSArmin Le Grand 
1366*ddde725dSArmin Le Grand                     if(aString.getLength())
1367*ddde725dSArmin Le Grand                     {
1368*ddde725dSArmin Le Grand                         rSvgStringVector.push_back(aString);
1369*ddde725dSArmin Le Grand                     }
1370*ddde725dSArmin Le Grand                 }
1371*ddde725dSArmin Le Grand             }
1372*ddde725dSArmin Le Grand 
1373*ddde725dSArmin Le Grand             return !rSvgStringVector.empty();
1374*ddde725dSArmin Le Grand         }
1375*ddde725dSArmin Le Grand 
1376*ddde725dSArmin Le Grand         void readImageLink(const rtl::OUString& rCandidate, rtl::OUString& rXLink, rtl::OUString& rUrl, rtl::OUString& rMimeType, rtl::OUString& rData)
1377*ddde725dSArmin Le Grand         {
1378*ddde725dSArmin Le Grand             rXLink = rUrl = rMimeType = rData = rtl::OUString();
1379*ddde725dSArmin Le Grand 
1380*ddde725dSArmin Le Grand             if(sal_Unicode('#') == rCandidate[0])
1381*ddde725dSArmin Le Grand             {
1382*ddde725dSArmin Le Grand                 // local link
1383*ddde725dSArmin Le Grand                 rXLink = rCandidate.copy(1);
1384*ddde725dSArmin Le Grand             }
1385*ddde725dSArmin Le Grand             else
1386*ddde725dSArmin Le Grand             {
1387*ddde725dSArmin Le Grand                 static rtl::OUString aStrData(rtl::OUString::createFromAscii("data:"));
1388*ddde725dSArmin Le Grand 
1389*ddde725dSArmin Le Grand                 if(rCandidate.match(aStrData, 0))
1390*ddde725dSArmin Le Grand                 {
1391*ddde725dSArmin Le Grand                     // embedded data
1392*ddde725dSArmin Le Grand                     sal_Int32 nPos(aStrData.getLength());
1393*ddde725dSArmin Le Grand                     sal_Int32 nLen(rCandidate.getLength());
1394*ddde725dSArmin Le Grand                     rtl::OUStringBuffer aBuffer;
1395*ddde725dSArmin Le Grand 
1396*ddde725dSArmin Le Grand                     // read mime type
1397*ddde725dSArmin Le Grand                     skip_char(rCandidate, sal_Unicode(' '), nPos, nLen);
1398*ddde725dSArmin Le Grand                     copyToLimiter(rCandidate, sal_Unicode(';'), nPos, aBuffer, nLen);
1399*ddde725dSArmin Le Grand                     skip_char(rCandidate, sal_Unicode(' '), sal_Unicode(';'), nPos, nLen);
1400*ddde725dSArmin Le Grand                     rMimeType = aBuffer.makeStringAndClear();
1401*ddde725dSArmin Le Grand 
1402*ddde725dSArmin Le Grand                     if(rMimeType.getLength() && nPos < nLen)
1403*ddde725dSArmin Le Grand                     {
1404*ddde725dSArmin Le Grand                         static rtl::OUString aStrImage(rtl::OUString::createFromAscii("image"));
1405*ddde725dSArmin Le Grand 
1406*ddde725dSArmin Le Grand                         if(rMimeType.match(aStrImage, 0))
1407*ddde725dSArmin Le Grand                         {
1408*ddde725dSArmin Le Grand                             // image data
1409*ddde725dSArmin Le Grand                             rtl::OUString aData(rCandidate.copy(nPos));
1410*ddde725dSArmin Le Grand                             static rtl::OUString aStrBase64(rtl::OUString::createFromAscii("base64"));
1411*ddde725dSArmin Le Grand 
1412*ddde725dSArmin Le Grand                             if(aData.match(aStrBase64, 0))
1413*ddde725dSArmin Le Grand                             {
1414*ddde725dSArmin Le Grand                                 // base64 encoded
1415*ddde725dSArmin Le Grand                                 nPos = aStrBase64.getLength();
1416*ddde725dSArmin Le Grand                                 nLen = aData.getLength();
1417*ddde725dSArmin Le Grand 
1418*ddde725dSArmin Le Grand                                 skip_char(aData, sal_Unicode(' '), sal_Unicode(','), nPos, nLen);
1419*ddde725dSArmin Le Grand 
1420*ddde725dSArmin Le Grand                                 if(nPos < nLen)
1421*ddde725dSArmin Le Grand                                 {
1422*ddde725dSArmin Le Grand                                     rData = aData.copy(nPos);
1423*ddde725dSArmin Le Grand                                 }
1424*ddde725dSArmin Le Grand                             }
1425*ddde725dSArmin Le Grand                         }
1426*ddde725dSArmin Le Grand                     }
1427*ddde725dSArmin Le Grand                 }
1428*ddde725dSArmin Le Grand                 else
1429*ddde725dSArmin Le Grand                 {
1430*ddde725dSArmin Le Grand                     // Url (path and filename)
1431*ddde725dSArmin Le Grand                     rUrl = rCandidate;
1432*ddde725dSArmin Le Grand                 }
1433*ddde725dSArmin Le Grand             }
1434*ddde725dSArmin Le Grand         }
1435*ddde725dSArmin Le Grand 
1436*ddde725dSArmin Le Grand         rtl::OUString convert(const rtl::OUString& rCandidate, const sal_Unicode& rPattern, const sal_Unicode& rNew, bool bRemove)
1437*ddde725dSArmin Le Grand         {
1438*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
1439*ddde725dSArmin Le Grand 
1440*ddde725dSArmin Le Grand             if(nLen)
1441*ddde725dSArmin Le Grand             {
1442*ddde725dSArmin Le Grand                 sal_Int32 nPos(0);
1443*ddde725dSArmin Le Grand                 rtl::OUStringBuffer aBuffer;
1444*ddde725dSArmin Le Grand                 bool bChanged(false);
1445*ddde725dSArmin Le Grand 
1446*ddde725dSArmin Le Grand                 while(nPos < nLen)
1447*ddde725dSArmin Le Grand                 {
1448*ddde725dSArmin Le Grand                     const sal_Unicode aChar(rCandidate[nPos]);
1449*ddde725dSArmin Le Grand 
1450*ddde725dSArmin Le Grand                     if(rPattern == aChar)
1451*ddde725dSArmin Le Grand                     {
1452*ddde725dSArmin Le Grand                         bChanged = true;
1453*ddde725dSArmin Le Grand 
1454*ddde725dSArmin Le Grand                         if(!bRemove)
1455*ddde725dSArmin Le Grand                         {
1456*ddde725dSArmin Le Grand                             aBuffer.append(rNew);
1457*ddde725dSArmin Le Grand                         }
1458*ddde725dSArmin Le Grand                     }
1459*ddde725dSArmin Le Grand                     else
1460*ddde725dSArmin Le Grand                     {
1461*ddde725dSArmin Le Grand                         aBuffer.append(aChar);
1462*ddde725dSArmin Le Grand                     }
1463*ddde725dSArmin Le Grand 
1464*ddde725dSArmin Le Grand                     nPos++;
1465*ddde725dSArmin Le Grand                 }
1466*ddde725dSArmin Le Grand 
1467*ddde725dSArmin Le Grand                 if(bChanged)
1468*ddde725dSArmin Le Grand                 {
1469*ddde725dSArmin Le Grand                     return aBuffer.makeStringAndClear();
1470*ddde725dSArmin Le Grand                 }
1471*ddde725dSArmin Le Grand             }
1472*ddde725dSArmin Le Grand 
1473*ddde725dSArmin Le Grand             return rCandidate;
1474*ddde725dSArmin Le Grand         }
1475*ddde725dSArmin Le Grand 
1476*ddde725dSArmin Le Grand         rtl::OUString consolidateContiguosSpace(const rtl::OUString& rCandidate)
1477*ddde725dSArmin Le Grand         {
1478*ddde725dSArmin Le Grand             const sal_Int32 nLen(rCandidate.getLength());
1479*ddde725dSArmin Le Grand 
1480*ddde725dSArmin Le Grand             if(nLen)
1481*ddde725dSArmin Le Grand             {
1482*ddde725dSArmin Le Grand                 sal_Int32 nPos(0);
1483*ddde725dSArmin Le Grand                 rtl::OUStringBuffer aBuffer;
1484*ddde725dSArmin Le Grand                 bool bInsideSpace(false);
1485*ddde725dSArmin Le Grand                 const sal_Unicode aSpace(' ');
1486*ddde725dSArmin Le Grand 
1487*ddde725dSArmin Le Grand                 while(nPos < nLen)
1488*ddde725dSArmin Le Grand                 {
1489*ddde725dSArmin Le Grand                     const sal_Unicode aChar(rCandidate[nPos]);
1490*ddde725dSArmin Le Grand 
1491*ddde725dSArmin Le Grand                     if(aSpace == aChar)
1492*ddde725dSArmin Le Grand                     {
1493*ddde725dSArmin Le Grand                         bInsideSpace = true;
1494*ddde725dSArmin Le Grand                     }
1495*ddde725dSArmin Le Grand                     else
1496*ddde725dSArmin Le Grand                     {
1497*ddde725dSArmin Le Grand                         if(bInsideSpace)
1498*ddde725dSArmin Le Grand                         {
1499*ddde725dSArmin Le Grand                             bInsideSpace = false;
1500*ddde725dSArmin Le Grand                             aBuffer.append(aSpace);
1501*ddde725dSArmin Le Grand                         }
1502*ddde725dSArmin Le Grand 
1503*ddde725dSArmin Le Grand                         aBuffer.append(aChar);
1504*ddde725dSArmin Le Grand                     }
1505*ddde725dSArmin Le Grand 
1506*ddde725dSArmin Le Grand                     nPos++;
1507*ddde725dSArmin Le Grand                 }
1508*ddde725dSArmin Le Grand 
1509*ddde725dSArmin Le Grand                 if(bInsideSpace)
1510*ddde725dSArmin Le Grand                 {
1511*ddde725dSArmin Le Grand                     aBuffer.append(aSpace);
1512*ddde725dSArmin Le Grand                 }
1513*ddde725dSArmin Le Grand 
1514*ddde725dSArmin Le Grand                 if(aBuffer.getLength() != nLen)
1515*ddde725dSArmin Le Grand                 {
1516*ddde725dSArmin Le Grand                     return aBuffer.makeStringAndClear();
1517*ddde725dSArmin Le Grand                 }
1518*ddde725dSArmin Le Grand             }
1519*ddde725dSArmin Le Grand 
1520*ddde725dSArmin Le Grand             return rCandidate;
1521*ddde725dSArmin Le Grand         }
1522*ddde725dSArmin Le Grand 
1523*ddde725dSArmin Le Grand         rtl::OUString whiteSpaceHandlingDefault(const rtl::OUString& rCandidate)
1524*ddde725dSArmin Le Grand         {
1525*ddde725dSArmin Le Grand             const sal_Unicode aNewline('\n');
1526*ddde725dSArmin Le Grand             const sal_Unicode aTab('\t');
1527*ddde725dSArmin Le Grand             const sal_Unicode aSpace(' ');
1528*ddde725dSArmin Le Grand 
1529*ddde725dSArmin Le Grand             // remove all newline characters
1530*ddde725dSArmin Le Grand             rtl::OUString aRetval(convert(rCandidate, aNewline, aNewline, true));
1531*ddde725dSArmin Le Grand 
1532*ddde725dSArmin Le Grand             // convert tab to space
1533*ddde725dSArmin Le Grand             aRetval = convert(aRetval, aTab, aSpace, false);
1534*ddde725dSArmin Le Grand 
1535*ddde725dSArmin Le Grand             // strip of all leading and trailing spaces
1536*ddde725dSArmin Le Grand             aRetval = aRetval.trim();
1537*ddde725dSArmin Le Grand 
1538*ddde725dSArmin Le Grand             // consolidate contiguos space
1539*ddde725dSArmin Le Grand             aRetval = consolidateContiguosSpace(aRetval);
1540*ddde725dSArmin Le Grand 
1541*ddde725dSArmin Le Grand             return aRetval;
1542*ddde725dSArmin Le Grand         }
1543*ddde725dSArmin Le Grand 
1544*ddde725dSArmin Le Grand         rtl::OUString whiteSpaceHandlingPreserve(const rtl::OUString& rCandidate)
1545*ddde725dSArmin Le Grand         {
1546*ddde725dSArmin Le Grand             const sal_Unicode aNewline('\n');
1547*ddde725dSArmin Le Grand             const sal_Unicode aTab('\t');
1548*ddde725dSArmin Le Grand             const sal_Unicode aSpace(' ');
1549*ddde725dSArmin Le Grand 
1550*ddde725dSArmin Le Grand             // convert newline to space
1551*ddde725dSArmin Le Grand             rtl::OUString aRetval(convert(rCandidate, aNewline, aSpace, false));
1552*ddde725dSArmin Le Grand 
1553*ddde725dSArmin Le Grand             // convert tab to space
1554*ddde725dSArmin Le Grand             aRetval = convert(rCandidate, aTab, aSpace, false);
1555*ddde725dSArmin Le Grand 
1556*ddde725dSArmin Le Grand             return rCandidate;
1557*ddde725dSArmin Le Grand         }
1558*ddde725dSArmin Le Grand 
1559*ddde725dSArmin Le Grand         ::std::vector< double > solveSvgNumberVector(const SvgNumberVector& rInput, const InfoProvider& rInfoProvider, NumberType aNumberType)
1560*ddde725dSArmin Le Grand         {
1561*ddde725dSArmin Le Grand             ::std::vector< double > aRetval;
1562*ddde725dSArmin Le Grand 
1563*ddde725dSArmin Le Grand             if(!rInput.empty())
1564*ddde725dSArmin Le Grand             {
1565*ddde725dSArmin Le Grand                 const double nCount(rInput.size());
1566*ddde725dSArmin Le Grand                 aRetval.reserve(nCount);
1567*ddde725dSArmin Le Grand 
1568*ddde725dSArmin Le Grand                 for(sal_uInt32 a(0); a < nCount; a++)
1569*ddde725dSArmin Le Grand                 {
1570*ddde725dSArmin Le Grand                     aRetval.push_back(rInput[a].solve(rInfoProvider, aNumberType));
1571*ddde725dSArmin Le Grand                 }
1572*ddde725dSArmin Le Grand             }
1573*ddde725dSArmin Le Grand 
1574*ddde725dSArmin Le Grand             return aRetval;
1575*ddde725dSArmin Le Grand         }
1576*ddde725dSArmin Le Grand 
1577*ddde725dSArmin Le Grand     } // end of namespace svgreader
1578*ddde725dSArmin Le Grand } // end of namespace svgio
1579*ddde725dSArmin Le Grand 
1580*ddde725dSArmin Le Grand //////////////////////////////////////////////////////////////////////////////
1581*ddde725dSArmin Le Grand // eof
1582