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