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