1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svgtools.hxx>
21 #include <sal/log.hxx>
22 #include <osl/thread.h>
23 #include <tools/color.hxx>
24 #include <basegfx/matrix/b2dhommatrix.hxx>
25 #include <basegfx/matrix/b2dhommatrixtools.hxx>
26 #include <svgtoken.hxx>
27 #include <unordered_map>
33 // common non-token strings
34 const OUString
commonStrings::aStrUserSpaceOnUse("userSpaceOnUse");
35 const OUString
commonStrings::aStrObjectBoundingBox("objectBoundingBox");
36 const OUString
commonStrings::aStrNonzero("nonzero");
37 const OUString
commonStrings::aStrEvenOdd("evenodd");
39 basegfx::B2DHomMatrix
SvgAspectRatio::createLinearMapping(const basegfx::B2DRange
& rTarget
, const basegfx::B2DRange
& rSource
)
41 basegfx::B2DHomMatrix aRetval
;
42 const double fSWidth(rSource
.getWidth());
43 const double fSHeight(rSource
.getHeight());
44 const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth
));
45 const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight
));
47 // transform from source state to unit range
48 aRetval
.translate(-rSource
.getMinX(), -rSource
.getMinY());
50 (bNoSWidth
? 1.0 : 1.0 / fSWidth
) * rTarget
.getWidth(),
51 (bNoSHeight
? 1.0 : 1.0 / fSHeight
) * rTarget
.getHeight());
53 // transform from unit rage to target range
54 aRetval
.translate(rTarget
.getMinX(), rTarget
.getMinY());
59 basegfx::B2DHomMatrix
SvgAspectRatio::createMapping(const basegfx::B2DRange
& rTarget
, const basegfx::B2DRange
& rSource
) const
61 // removed !isSet() from below. Due to correct defaults in the constructor an instance
62 // of this class is perfectly useful without being set by any importer
63 if(Align_none
== getSvgAlign())
65 // create linear mapping (default)
66 return createLinearMapping(rTarget
, rSource
);
69 basegfx::B2DHomMatrix aRetval
;
71 const double fSWidth(rSource
.getWidth());
72 const double fSHeight(rSource
.getHeight());
73 const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth
));
74 const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight
));
75 const double fScaleX((bNoSWidth
? 1.0 : 1.0 / fSWidth
) * rTarget
.getWidth());
76 const double fScaleY((bNoSHeight
? 1.0 : 1.0 / fSHeight
) * rTarget
.getHeight());
77 const double fScale(isMeetOrSlice() ? std::min(fScaleX
, fScaleY
) : std::max(fScaleX
, fScaleY
));
79 // remove source translation, apply scale
80 aRetval
.translate(-rSource
.getMinX(), -rSource
.getMinY());
81 aRetval
.scale(fScale
, fScale
);
83 // evaluate horizontal alignment
84 const double fNewWidth(fSWidth
* fScale
);
94 const double fFreeSpace(rTarget
.getWidth() - fNewWidth
);
95 fTransX
= fFreeSpace
* 0.5;
103 const double fFreeSpace(rTarget
.getWidth() - fNewWidth
);
104 fTransX
= fFreeSpace
;
110 // evaluate vertical alignment
111 const double fNewHeight(fSHeight
* fScale
);
114 switch(getSvgAlign())
121 const double fFreeSpace(rTarget
.getHeight() - fNewHeight
);
122 fTransY
= fFreeSpace
* 0.5;
130 const double fFreeSpace(rTarget
.getHeight() - fNewHeight
);
131 fTransY
= fFreeSpace
;
137 // add target translation
139 rTarget
.getMinX() + fTransX
,
140 rTarget
.getMinY() + fTransY
);
145 double SvgNumber::solveNonPercentage(const InfoProvider
& rInfoProvider
) const
153 return mfNumber
* rInfoProvider
.getCurrentFontSizeInherited();
157 return mfNumber
* rInfoProvider
.getCurrentXHeightInherited() * 0.5;
169 double fRetval(mfNumber
);
173 case Unit_pt
: fRetval
*= F_SVG_PIXEL_PER_INCH
/ 72.0; break;
174 case Unit_pc
: fRetval
*= F_SVG_PIXEL_PER_INCH
/ 6.0; break;
175 case Unit_cm
: fRetval
*= F_SVG_PIXEL_PER_INCH
/ 2.54; break;
176 case Unit_mm
: fRetval
*= 0.1 * F_SVG_PIXEL_PER_INCH
/ 2.54; break;
177 case Unit_in
: fRetval
*= F_SVG_PIXEL_PER_INCH
; break;
185 SAL_WARN("svgio", "Design error, this case should have been handled in the caller");
190 OSL_ENSURE(false, "Do not use with percentage! ");
197 OSL_ENSURE(false, "SvgNumber not set (!)");
201 double SvgNumber::solve(const InfoProvider
& rInfoProvider
, NumberType aNumberType
) const
220 return solveNonPercentage( rInfoProvider
);
224 double fRetval(mfNumber
* 0.01);
225 basegfx::B2DRange aViewPort
= rInfoProvider
.getCurrentViewPort();
227 if ( aViewPort
.isEmpty() )
229 SAL_WARN("svgio", "Design error, this case should have been handled in the caller");
230 // no viewPort, assume a normal page size (A4)
231 aViewPort
= basegfx::B2DRange(
234 210.0 * F_SVG_PIXEL_PER_INCH
/ 2.54,
235 297.0 * F_SVG_PIXEL_PER_INCH
/ 2.54);
239 if ( !aViewPort
.isEmpty() )
241 if(xcoordinate
== aNumberType
)
243 // it's a x-coordinate, relative to current width (w)
244 fRetval
*= aViewPort
.getWidth();
246 else if(ycoordinate
== aNumberType
)
248 // it's a y-coordinate, relative to current height (h)
249 fRetval
*= aViewPort
.getHeight();
253 // it's a length, relative to sqrt(w*w + h*h)/sqrt(2)
254 const double fCurrentWidth(aViewPort
.getWidth());
255 const double fCurrentHeight(aViewPort
.getHeight());
256 const double fCurrentLength(
257 sqrt(fCurrentWidth
* fCurrentWidth
+ fCurrentHeight
* fCurrentHeight
)/sqrt(2.0));
259 fRetval
*= fCurrentLength
;
273 OSL_ENSURE(false, "SvgNumber not set (!)");
277 bool SvgNumber::isPositive() const
279 return basegfx::fTools::moreOrEqual(mfNumber
, 0.0);
282 void skip_char(const OUString
& rCandidate
, sal_Unicode nChar
, sal_Int32
& nPos
, const sal_Int32 nLen
)
284 while(nPos
< nLen
&& nChar
== rCandidate
[nPos
])
290 void skip_char(const OUString
& rCandidate
, sal_Unicode nCharA
, sal_Unicode nCharB
, sal_Int32
& nPos
, const sal_Int32 nLen
)
292 while(nPos
< nLen
&& (nCharA
== rCandidate
[nPos
] || nCharB
== rCandidate
[nPos
]))
298 void copySign(const OUString
& rCandidate
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
302 const sal_Unicode
aChar(rCandidate
[nPos
]);
304 if('+' == aChar
|| '-' == aChar
)
306 rTarget
.append(aChar
);
312 void copyNumber(const OUString
& rCandidate
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
314 bool bOnNumber(true);
316 while(bOnNumber
&& nPos
< nLen
)
318 const sal_Unicode
aChar(rCandidate
[nPos
]);
320 bOnNumber
= ('0' <= aChar
&& '9' >= aChar
) || '.' == aChar
;
324 rTarget
.append(aChar
);
330 void copyHex(const OUString
& rCandidate
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
334 while(bOnHex
&& nPos
< nLen
)
336 const sal_Unicode
aChar(rCandidate
[nPos
]);
338 bOnHex
= ('0' <= aChar
&& '9' >= aChar
)
339 || ('A' <= aChar
&& 'F' >= aChar
)
340 || ('a' <= aChar
&& 'f' >= aChar
);
344 rTarget
.append(aChar
);
350 void copyString(const OUString
& rCandidate
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
354 while(bOnChar
&& nPos
< nLen
)
356 const sal_Unicode
aChar(rCandidate
[nPos
]);
358 bOnChar
= ('a' <= aChar
&& 'z' >= aChar
)
359 || ('A' <= aChar
&& 'Z' >= aChar
)
364 rTarget
.append(aChar
);
370 void copyToLimiter(const OUString
& rCandidate
, sal_Unicode nLimiter
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
372 while(nPos
< nLen
&& nLimiter
!= rCandidate
[nPos
])
374 rTarget
.append(rCandidate
[nPos
]);
379 bool readNumber(const OUString
& rCandidate
, sal_Int32
& nPos
, double& fNum
, const sal_Int32 nLen
)
385 copySign(rCandidate
, nPos
, aNum
, nLen
);
386 copyNumber(rCandidate
, nPos
, aNum
, nLen
);
390 const sal_Unicode
aChar(rCandidate
[nPos
]);
392 if('e' == aChar
|| 'E' == aChar
)
394 // try to read exponential number, but be careful. I had
395 // a case where dx="2em" was used, thus the 'e' was consumed
396 // by error. First try if there are numbers after the 'e',
397 // safe current state
399 const OUStringBuffer
aNum2(aNum
);
400 const sal_Int32
nPosAfterE(nPos
);
403 copySign(rCandidate
, nPos
, aNum
, nLen
);
404 copyNumber(rCandidate
, nPos
, aNum
, nLen
);
406 if(nPosAfterE
== nPos
)
408 // no number after 'e', go back. Do not
409 // return false, it's still a valid integer number
418 rtl_math_ConversionStatus eStatus
;
420 fNum
= rtl::math::stringToDouble(
421 aNum
.makeStringAndClear(), '.', ',',
424 return eStatus
== rtl_math_ConversionStatus_Ok
;
431 SvgUnit
readUnit(const OUString
& rCandidate
, sal_Int32
& nPos
, const sal_Int32 nLen
)
433 SvgUnit
aRetval(Unit_px
);
437 const sal_Unicode
aCharA(rCandidate
[nPos
]);
441 const sal_Unicode
aCharB(rCandidate
[nPos
+ 1]);
442 bool bTwoCharValid(false);
450 // 'em' Relative to current font size
452 bTwoCharValid
= true;
454 else if('x' == aCharB
)
456 // 'ex' Relative to current font x-height
458 bTwoCharValid
= true;
466 // 'px' UserUnit (default)
467 bTwoCharValid
= true;
469 else if('t' == aCharB
)
473 bTwoCharValid
= true;
475 else if('c' == aCharB
)
479 bTwoCharValid
= true;
487 // 'in' == 96 px, since CSS 2.1
489 bTwoCharValid
= true;
497 // 'cm' == 37.79527559 px
499 bTwoCharValid
= true;
507 // 'mm' == 3.779528 px
509 bTwoCharValid
= true;
524 // percent used, relative to current
526 aRetval
= Unit_percent
;
534 bool readNumberAndUnit(const OUString
& rCandidate
, sal_Int32
& nPos
, SvgNumber
& aNum
, const sal_Int32 nLen
)
538 if(readNumber(rCandidate
, nPos
, fNum
, nLen
))
540 skip_char(rCandidate
, ' ', nPos
, nLen
);
541 aNum
= SvgNumber(fNum
, readUnit(rCandidate
, nPos
, nLen
));
549 bool readAngle(const OUString
& rCandidate
, sal_Int32
& nPos
, double& fAngle
, const sal_Int32 nLen
)
551 if(readNumber(rCandidate
, nPos
, fAngle
, nLen
))
553 skip_char(rCandidate
, ' ', nPos
, nLen
);
560 } aType(deg
); // degrees is default
564 const sal_Unicode
aChar(rCandidate
[nPos
]);
565 static const char aStrGrad
[] = "grad";
566 static const char aStrRad
[] = "rad";
573 if(rCandidate
.matchIgnoreAsciiCase(aStrGrad
, nPos
))
576 nPos
+= strlen(aStrGrad
);
584 if(rCandidate
.matchIgnoreAsciiCase(aStrRad
, nPos
))
587 nPos
+= strlen(aStrRad
);
595 // convert to radians
598 fAngle
= basegfx::deg2rad(fAngle
);
600 else if(grad
== aType
)
602 // looks like 100 grad is 90 degrees
603 fAngle
*= F_PI
/ 200.0;
612 sal_Int32
read_hex(sal_Unicode nChar
)
614 if(nChar
>= '0' && nChar
<= '9')
618 else if(nChar
>= 'A' && nChar
<= 'F')
620 return 10 + sal_Int32(nChar
- u
'A');
622 else if(nChar
>= 'a' && nChar
<= 'f')
624 return 10 + sal_Int32(nChar
- u
'a');
633 bool match_colorKeyword(basegfx::BColor
& rColor
, const OUString
& rName
, bool bCaseIndependent
)
635 typedef std::unordered_map
< OUString
, Color
> ColorTokenMapper
;
636 typedef std::pair
< OUString
, Color
> ColorTokenValueType
;
637 static const ColorTokenMapper aColorTokenMapperList
{
638 { ColorTokenValueType(OUString("aliceblue"), Color(240, 248, 255)) },
639 { ColorTokenValueType(OUString("antiquewhite"), Color(250, 235, 215) ) },
640 { ColorTokenValueType(OUString("aqua"), Color( 0, 255, 255) ) },
641 { ColorTokenValueType(OUString("aquamarine"), Color(127, 255, 212) ) },
642 { ColorTokenValueType(OUString("azure"), Color(240, 255, 255) ) },
643 { ColorTokenValueType(OUString("beige"), Color(245, 245, 220) ) },
644 { ColorTokenValueType(OUString("bisque"), Color(255, 228, 196) ) },
645 { ColorTokenValueType(OUString("black"), Color( 0, 0, 0) ) },
646 { ColorTokenValueType(OUString("blanchedalmond"), Color(255, 235, 205) ) },
647 { ColorTokenValueType(OUString("blue"), Color( 0, 0, 255) ) },
648 { ColorTokenValueType(OUString("blueviolet"), Color(138, 43, 226) ) },
649 { ColorTokenValueType(OUString("brown"), Color(165, 42, 42) ) },
650 { ColorTokenValueType(OUString("burlywood"), Color(222, 184, 135) ) },
651 { ColorTokenValueType(OUString("cadetblue"), Color( 95, 158, 160) ) },
652 { ColorTokenValueType(OUString("chartreuse"), Color(127, 255, 0) ) },
653 { ColorTokenValueType(OUString("chocolate"), Color(210, 105, 30) ) },
654 { ColorTokenValueType(OUString("coral"), Color(255, 127, 80) ) },
655 { ColorTokenValueType(OUString("cornflowerblue"), Color(100, 149, 237) ) },
656 { ColorTokenValueType(OUString("cornsilk"), Color(255, 248, 220) ) },
657 { ColorTokenValueType(OUString("crimson"), Color(220, 20, 60) ) },
658 { ColorTokenValueType(OUString("cyan"), Color( 0, 255, 255) ) },
659 { ColorTokenValueType(OUString("darkblue"), Color( 0, 0, 139) ) },
660 { ColorTokenValueType(OUString("darkcyan"), Color( 0, 139, 139) ) },
661 { ColorTokenValueType(OUString("darkgoldenrod"), Color(184, 134, 11) ) },
662 { ColorTokenValueType(OUString("darkgray"), Color(169, 169, 169) ) },
663 { ColorTokenValueType(OUString("darkgreen"), Color( 0, 100, 0) ) },
664 { ColorTokenValueType(OUString("darkgrey"), Color(169, 169, 169) ) },
665 { ColorTokenValueType(OUString("darkkhaki"), Color(189, 183, 107) ) },
666 { ColorTokenValueType(OUString("darkmagenta"), Color(139, 0, 139) ) },
667 { ColorTokenValueType(OUString("darkolivegreen"), Color( 85, 107, 47) ) },
668 { ColorTokenValueType(OUString("darkorange"), Color(255, 140, 0) ) },
669 { ColorTokenValueType(OUString("darkorchid"), Color(153, 50, 204) ) },
670 { ColorTokenValueType(OUString("darkred"), Color(139, 0, 0) ) },
671 { ColorTokenValueType(OUString("darksalmon"), Color(233, 150, 122) ) },
672 { ColorTokenValueType(OUString("darkseagreen"), Color(143, 188, 143) ) },
673 { ColorTokenValueType(OUString("darkslateblue"), Color( 72, 61, 139) ) },
674 { ColorTokenValueType(OUString("darkslategray"), Color( 47, 79, 79) ) },
675 { ColorTokenValueType(OUString("darkslategrey"), Color( 47, 79, 79) ) },
676 { ColorTokenValueType(OUString("darkturquoise"), Color( 0, 206, 209) ) },
677 { ColorTokenValueType(OUString("darkviolet"), Color(148, 0, 211) ) },
678 { ColorTokenValueType(OUString("deeppink"), Color(255, 20, 147) ) },
679 { ColorTokenValueType(OUString("deepskyblue"), Color( 0, 191, 255) ) },
680 { ColorTokenValueType(OUString("dimgray"), Color(105, 105, 105) ) },
681 { ColorTokenValueType(OUString("dimgrey"), Color(105, 105, 105) ) },
682 { ColorTokenValueType(OUString("dodgerblue"), Color( 30, 144, 255) ) },
683 { ColorTokenValueType(OUString("firebrick"), Color(178, 34, 34) ) },
684 { ColorTokenValueType(OUString("floralwhite"), Color(255, 250, 240) ) },
685 { ColorTokenValueType(OUString("forestgreen"), Color( 34, 139, 34) ) },
686 { ColorTokenValueType(OUString("fuchsia"), Color(255, 0, 255) ) },
687 { ColorTokenValueType(OUString("gainsboro"), Color(220, 220, 220) ) },
688 { ColorTokenValueType(OUString("ghostwhite"), Color(248, 248, 255) ) },
689 { ColorTokenValueType(OUString("gold"), Color(255, 215, 0) ) },
690 { ColorTokenValueType(OUString("goldenrod"), Color(218, 165, 32) ) },
691 { ColorTokenValueType(OUString("gray"), Color(128, 128, 128) ) },
692 { ColorTokenValueType(OUString("grey"), Color(128, 128, 128) ) },
693 { ColorTokenValueType(OUString("green"), Color(0, 128, 0) ) },
694 { ColorTokenValueType(OUString("greenyellow"), Color(173, 255, 47) ) },
695 { ColorTokenValueType(OUString("honeydew"), Color(240, 255, 240) ) },
696 { ColorTokenValueType(OUString("hotpink"), Color(255, 105, 180) ) },
697 { ColorTokenValueType(OUString("indianred"), Color(205, 92, 92) ) },
698 { ColorTokenValueType(OUString("indigo"), Color( 75, 0, 130) ) },
699 { ColorTokenValueType(OUString("ivory"), Color(255, 255, 240) ) },
700 { ColorTokenValueType(OUString("khaki"), Color(240, 230, 140) ) },
701 { ColorTokenValueType(OUString("lavender"), Color(230, 230, 250) ) },
702 { ColorTokenValueType(OUString("lavenderblush"), Color(255, 240, 245) ) },
703 { ColorTokenValueType(OUString("lawngreen"), Color(124, 252, 0) ) },
704 { ColorTokenValueType(OUString("lemonchiffon"), Color(255, 250, 205) ) },
705 { ColorTokenValueType(OUString("lightblue"), Color(173, 216, 230) ) },
706 { ColorTokenValueType(OUString("lightcoral"), Color(240, 128, 128) ) },
707 { ColorTokenValueType(OUString("lightcyan"), Color(224, 255, 255) ) },
708 { ColorTokenValueType(OUString("lightgoldenrodyellow"), Color(250, 250, 210) ) },
709 { ColorTokenValueType(OUString("lightgray"), Color(211, 211, 211) ) },
710 { ColorTokenValueType(OUString("lightgreen"), Color(144, 238, 144) ) },
711 { ColorTokenValueType(OUString("lightgrey"), Color(211, 211, 211) ) },
712 { ColorTokenValueType(OUString("lightpink"), Color(255, 182, 193) ) },
713 { ColorTokenValueType(OUString("lightsalmon"), Color(255, 160, 122) ) },
714 { ColorTokenValueType(OUString("lightseagreen"), Color( 32, 178, 170) ) },
715 { ColorTokenValueType(OUString("lightskyblue"), Color(135, 206, 250) ) },
716 { ColorTokenValueType(OUString("lightslategray"), Color(119, 136, 153) ) },
717 { ColorTokenValueType(OUString("lightslategrey"), Color(119, 136, 153) ) },
718 { ColorTokenValueType(OUString("lightsteelblue"), Color(176, 196, 222) ) },
719 { ColorTokenValueType(OUString("lightyellow"), Color(255, 255, 224) ) },
720 { ColorTokenValueType(OUString("lime"), Color( 0, 255, 0) ) },
721 { ColorTokenValueType(OUString("limegreen"), Color( 50, 205, 50) ) },
722 { ColorTokenValueType(OUString("linen"), Color(250, 240, 230) ) },
723 { ColorTokenValueType(OUString("magenta"), Color(255, 0, 255) ) },
724 { ColorTokenValueType(OUString("maroon"), Color(128, 0, 0) ) },
725 { ColorTokenValueType(OUString("mediumaquamarine"), Color(102, 205, 170) ) },
726 { ColorTokenValueType(OUString("mediumblue"), Color( 0, 0, 205) ) },
727 { ColorTokenValueType(OUString("mediumorchid"), Color(186, 85, 211) ) },
728 { ColorTokenValueType(OUString("mediumpurple"), Color(147, 112, 219) ) },
729 { ColorTokenValueType(OUString("mediumseagreen"), Color( 60, 179, 113) ) },
730 { ColorTokenValueType(OUString("mediumslateblue"), Color(123, 104, 238) ) },
731 { ColorTokenValueType(OUString("mediumspringgreen"), Color( 0, 250, 154) ) },
732 { ColorTokenValueType(OUString("mediumturquoise"), Color( 72, 209, 204) ) },
733 { ColorTokenValueType(OUString("mediumvioletred"), Color(199, 21, 133) ) },
734 { ColorTokenValueType(OUString("midnightblue"), Color( 25, 25, 112) ) },
735 { ColorTokenValueType(OUString("mintcream"), Color(245, 255, 250) ) },
736 { ColorTokenValueType(OUString("mistyrose"), Color(255, 228, 225) ) },
737 { ColorTokenValueType(OUString("moccasin"), Color(255, 228, 181) ) },
738 { ColorTokenValueType(OUString("navajowhite"), Color(255, 222, 173) ) },
739 { ColorTokenValueType(OUString("navy"), Color( 0, 0, 128) ) },
740 { ColorTokenValueType(OUString("oldlace"), Color(253, 245, 230) ) },
741 { ColorTokenValueType(OUString("olive"), Color(128, 128, 0) ) },
742 { ColorTokenValueType(OUString("olivedrab"), Color(107, 142, 35) ) },
743 { ColorTokenValueType(OUString("orange"), Color(255, 165, 0) ) },
744 { ColorTokenValueType(OUString("orangered"), Color(255, 69, 0) ) },
745 { ColorTokenValueType(OUString("orchid"), Color(218, 112, 214) ) },
746 { ColorTokenValueType(OUString("palegoldenrod"), Color(238, 232, 170) ) },
747 { ColorTokenValueType(OUString("palegreen"), Color(152, 251, 152) ) },
748 { ColorTokenValueType(OUString("paleturquoise"), Color(175, 238, 238) ) },
749 { ColorTokenValueType(OUString("palevioletred"), Color(219, 112, 147) ) },
750 { ColorTokenValueType(OUString("papayawhip"), Color(255, 239, 213) ) },
751 { ColorTokenValueType(OUString("peachpuff"), Color(255, 218, 185) ) },
752 { ColorTokenValueType(OUString("peru"), Color(205, 133, 63) ) },
753 { ColorTokenValueType(OUString("pink"), Color(255, 192, 203) ) },
754 { ColorTokenValueType(OUString("plum"), Color(221, 160, 221) ) },
755 { ColorTokenValueType(OUString("powderblue"), Color(176, 224, 230) ) },
756 { ColorTokenValueType(OUString("purple"), Color(128, 0, 128) ) },
757 { ColorTokenValueType(OUString("red"), Color(255, 0, 0) ) },
758 { ColorTokenValueType(OUString("rosybrown"), Color(188, 143, 143) ) },
759 { ColorTokenValueType(OUString("royalblue"), Color( 65, 105, 225) ) },
760 { ColorTokenValueType(OUString("saddlebrown"), Color(139, 69, 19) ) },
761 { ColorTokenValueType(OUString("salmon"), Color(250, 128, 114) ) },
762 { ColorTokenValueType(OUString("sandybrown"), Color(244, 164, 96) ) },
763 { ColorTokenValueType(OUString("seagreen"), Color( 46, 139, 87) ) },
764 { ColorTokenValueType(OUString("seashell"), Color(255, 245, 238) ) },
765 { ColorTokenValueType(OUString("sienna"), Color(160, 82, 45) ) },
766 { ColorTokenValueType(OUString("silver"), Color(192, 192, 192) ) },
767 { ColorTokenValueType(OUString("skyblue"), Color(135, 206, 235) ) },
768 { ColorTokenValueType(OUString("slateblue"), Color(106, 90, 205) ) },
769 { ColorTokenValueType(OUString("slategray"), Color(112, 128, 144) ) },
770 { ColorTokenValueType(OUString("slategrey"), Color(112, 128, 144) ) },
771 { ColorTokenValueType(OUString("snow"), Color(255, 250, 250) ) },
772 { ColorTokenValueType(OUString("springgreen"), Color( 0, 255, 127) ) },
773 { ColorTokenValueType(OUString("steelblue"), Color( 70, 130, 180) ) },
774 { ColorTokenValueType(OUString("tan"), Color(210, 180, 140) ) },
775 { ColorTokenValueType(OUString("teal"), Color( 0, 128, 128) ) },
776 { ColorTokenValueType(OUString("thistle"), Color(216, 191, 216) ) },
777 { ColorTokenValueType(OUString("tomato"), Color(255, 99, 71) ) },
778 { ColorTokenValueType(OUString("turquoise"), Color( 64, 224, 208) ) },
779 { ColorTokenValueType(OUString("violet"), Color(238, 130, 238) ) },
780 { ColorTokenValueType(OUString("wheat"), Color(245, 222, 179) ) },
781 { ColorTokenValueType(OUString("white"), Color(255, 255, 255) ) },
782 { ColorTokenValueType(OUString("whitesmoke"), Color(245, 245, 245) ) },
783 { ColorTokenValueType(OUString("yellow"), Color(255, 255, 0) ) },
784 { ColorTokenValueType(OUString("yellowgreen"), Color(154, 205, 50) ) },
787 ColorTokenMapper::const_iterator
aResult(aColorTokenMapperList
.find(rName
));
789 if(bCaseIndependent
&& aResult
== aColorTokenMapperList
.end())
791 // also try case independent match (e.g. for Css styles)
792 aResult
= aColorTokenMapperList
.find(rName
.toAsciiLowerCase());
795 if(aResult
== aColorTokenMapperList
.end())
801 rColor
= aResult
->second
.getBColor();
806 bool read_color(const OUString
& rCandidate
, basegfx::BColor
& rColor
, bool bCaseIndependent
, SvgNumber
& rOpacity
)
808 const sal_Int32
nLen(rCandidate
.getLength());
812 const sal_Unicode
aChar(rCandidate
[0]);
813 const double fFactor(1.0 / 255.0);
821 copyHex(rCandidate
, nPos
, aNum
, nLen
);
822 const sal_Int32
nLength(aNum
.getLength());
826 const sal_Int32
nR(read_hex(aNum
[0]));
827 const sal_Int32
nG(read_hex(aNum
[1]));
828 const sal_Int32
nB(read_hex(aNum
[2]));
830 rColor
.setRed((nR
| (nR
<< 4)) * fFactor
);
831 rColor
.setGreen((nG
| (nG
<< 4)) * fFactor
);
832 rColor
.setBlue((nB
| (nB
<< 4)) * fFactor
);
836 else if(6 == nLength
)
838 const sal_Int32
nR1(read_hex(aNum
[0]));
839 const sal_Int32
nR2(read_hex(aNum
[1]));
840 const sal_Int32
nG1(read_hex(aNum
[2]));
841 const sal_Int32
nG2(read_hex(aNum
[3]));
842 const sal_Int32
nB1(read_hex(aNum
[4]));
843 const sal_Int32
nB2(read_hex(aNum
[5]));
845 rColor
.setRed((nR2
| (nR1
<< 4)) * fFactor
);
846 rColor
.setGreen((nG2
| (nG1
<< 4)) * fFactor
);
847 rColor
.setBlue((nB2
| (nB1
<< 4)) * fFactor
);
854 static const char aStrRgb
[] = "rgb";
856 if(rCandidate
.matchIgnoreAsciiCase(aStrRgb
, 0))
858 // rgb/rgba definition
859 sal_Int32
nPos(strlen(aStrRgb
));
860 bool bIsRGBA
= false;
862 if('a' == rCandidate
[nPos
])
864 //Delete the 'a' from 'rbga'
865 skip_char(rCandidate
, 'a', nPos
, nPos
+ 1);
869 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
872 if(readNumber(rCandidate
, nPos
, fR
, nLen
))
874 skip_char(rCandidate
, ' ', nPos
, nLen
);
878 const sal_Unicode
aPercentChar(rCandidate
[nPos
]);
879 const bool bIsPercent('%' == aPercentChar
);
884 skip_char(rCandidate
, '%', nPos
, nLen
);
887 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
889 if(readNumber(rCandidate
, nPos
, fG
, nLen
))
895 skip_char(rCandidate
, '%', nPos
, nLen
);
898 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
900 if(readNumber(rCandidate
, nPos
, fB
, nLen
))
906 skip_char(rCandidate
, '%', nPos
, nLen
);
909 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
911 if(readNumber(rCandidate
, nPos
, fA
, nLen
))
915 const double fFac(bIsPercent
? 0.01 : 1);
916 rOpacity
= SvgNumber(fA
* fFac
);
920 skip_char(rCandidate
, '%', nPos
, nLen
);
929 const double fFac(bIsPercent
? 0.01 : fFactor
);
931 rColor
.setRed(fR
* fFac
);
932 rColor
.setGreen(fG
* fFac
);
933 rColor
.setBlue(fB
* fFac
);
935 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
945 if(match_colorKeyword(rColor
, rCandidate
, bCaseIndependent
))
956 basegfx::B2DRange
readViewBox(const OUString
& rCandidate
, InfoProvider
const & rInfoProvider
)
958 const sal_Int32
nLen(rCandidate
.getLength());
964 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
966 if(readNumberAndUnit(rCandidate
, nPos
, aMinX
, nLen
))
969 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
971 if(readNumberAndUnit(rCandidate
, nPos
, aMinY
, nLen
))
974 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
976 if(readNumberAndUnit(rCandidate
, nPos
, aWidth
, nLen
))
979 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
981 if(readNumberAndUnit(rCandidate
, nPos
, aHeight
, nLen
))
983 double fX(aMinX
.solve(rInfoProvider
, xcoordinate
));
984 double fY(aMinY
.solve(rInfoProvider
, ycoordinate
));
985 double fW(aWidth
.solve(rInfoProvider
,xcoordinate
));
986 double fH(aHeight
.solve(rInfoProvider
,ycoordinate
));
987 return basegfx::B2DRange(fX
,fY
,fX
+fW
,fY
+fH
);
994 return basegfx::B2DRange();
997 basegfx::B2DHomMatrix
readTransform(const OUString
& rCandidate
, InfoProvider
const & rInfoProvider
)
999 basegfx::B2DHomMatrix aMatrix
;
1000 const sal_Int32
nLen(rCandidate
.getLength());
1005 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1009 const sal_Unicode
aChar(rCandidate
[nPos
]);
1010 const sal_Int32
nInitPos(nPos
);
1011 static const char aStrMatrix
[] = "matrix";
1012 static const char aStrTranslate
[] = "translate";
1013 static const char aStrScale
[] = "scale";
1014 static const char aStrRotate
[] = "rotate";
1015 static const char aStrSkewX
[] = "skewX";
1016 static const char aStrSkewY
[] = "skewY";
1022 if(rCandidate
.match(aStrMatrix
, nPos
))
1025 nPos
+= strlen(aStrMatrix
);
1026 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1028 basegfx::B2DHomMatrix aNew
;
1030 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1032 aNew
.set(0, 0, aVal
.solve(rInfoProvider
)); // Element A
1033 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1035 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1037 aNew
.set(1, 0, aVal
.solve(rInfoProvider
)); // Element B
1038 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1040 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1042 aNew
.set(0, 1, aVal
.solve(rInfoProvider
)); // Element C
1043 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1045 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1047 aNew
.set(1, 1, aVal
.solve(rInfoProvider
)); // Element D
1048 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1050 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1052 aNew
.set(0, 2, aVal
.solve(rInfoProvider
, xcoordinate
)); // Element E
1053 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1055 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1057 aNew
.set(1, 2, aVal
.solve(rInfoProvider
, ycoordinate
)); // Element F
1058 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1059 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1061 // caution: String is evaluated from left to right, but matrix multiplication
1062 // in SVG is right to left, so put the new transformation before the current
1063 // one by multiplicating from the right side
1064 aMatrix
= aMatrix
* aNew
;
1076 if(rCandidate
.match(aStrTranslate
, nPos
))
1078 // translate element
1079 nPos
+= strlen(aStrTranslate
);
1080 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1083 if(readNumberAndUnit(rCandidate
, nPos
, aTransX
, nLen
))
1085 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1087 readNumberAndUnit(rCandidate
, nPos
, aTransY
, nLen
);
1088 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1089 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1091 aMatrix
= aMatrix
* basegfx::utils::createTranslateB2DHomMatrix(
1092 aTransX
.solve(rInfoProvider
, xcoordinate
),
1093 aTransY
.solve(rInfoProvider
, ycoordinate
));
1100 if(rCandidate
.match(aStrScale
, nPos
))
1103 nPos
+= strlen(aStrScale
);
1104 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1107 if(readNumberAndUnit(rCandidate
, nPos
, aScaleX
, nLen
))
1109 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1110 SvgNumber
aScaleY(aScaleX
);
1111 readNumberAndUnit(rCandidate
, nPos
, aScaleY
, nLen
);
1112 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1113 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1115 aMatrix
= aMatrix
* basegfx::utils::createScaleB2DHomMatrix(
1116 aScaleX
.solve(rInfoProvider
),
1117 aScaleY
.solve(rInfoProvider
));
1120 else if(rCandidate
.match(aStrSkewX
, nPos
))
1123 nPos
+= strlen(aStrSkewX
);
1124 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1127 if(readAngle(rCandidate
, nPos
, fSkewX
, nLen
))
1129 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1130 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1132 aMatrix
= aMatrix
* basegfx::utils::createShearXB2DHomMatrix(tan(fSkewX
));
1135 else if(rCandidate
.match(aStrSkewY
, nPos
))
1138 nPos
+= strlen(aStrSkewY
);
1139 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1142 if(readAngle(rCandidate
, nPos
, fSkewY
, nLen
))
1144 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1145 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1147 aMatrix
= aMatrix
* basegfx::utils::createShearYB2DHomMatrix(tan(fSkewY
));
1154 if(rCandidate
.match(aStrRotate
, nPos
))
1157 nPos
+= strlen(aStrRotate
);
1158 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1161 if(readAngle(rCandidate
, nPos
, fAngle
, nLen
))
1163 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1165 readNumberAndUnit(rCandidate
, nPos
, aX
, nLen
);
1166 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1168 readNumberAndUnit(rCandidate
, nPos
, aY
, nLen
);
1169 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1170 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1172 const double fX(aX
.isSet() ? aX
.solve(rInfoProvider
, xcoordinate
) : 0.0);
1173 const double fY(aY
.isSet() ? aY
.solve(rInfoProvider
, ycoordinate
) : 0.0);
1175 if(!basegfx::fTools::equalZero(fX
) || !basegfx::fTools::equalZero(fY
))
1177 // rotate around point
1178 aMatrix
= aMatrix
* basegfx::utils::createRotateAroundPoint(fX
, fY
, fAngle
);
1183 aMatrix
= aMatrix
* basegfx::utils::createRotateB2DHomMatrix(fAngle
);
1191 if(nInitPos
== nPos
)
1193 OSL_ENSURE(false, "Could not interpret on current position (!)");
1202 bool readSingleNumber(const OUString
& rCandidate
, SvgNumber
& aNum
)
1204 const sal_Int32
nLen(rCandidate
.getLength());
1207 return readNumberAndUnit(rCandidate
, nPos
, aNum
, nLen
);
1210 bool readLocalUrl(const OUString
& rCandidate
, OUString
& rURL
)
1212 static const char aStrUrl
[] = "url";
1214 if(rCandidate
.startsWith(aStrUrl
))
1216 const sal_Int32
nLen(rCandidate
.getLength());
1217 sal_Int32
nPos(strlen(aStrUrl
));
1219 skip_char(rCandidate
, '(', '#', nPos
, nLen
);
1220 OUStringBuffer aTokenValue
;
1221 copyToLimiter(rCandidate
, ')', nPos
, aTokenValue
, nLen
);
1222 rURL
= aTokenValue
.makeStringAndClear();
1230 bool readSvgPaint(const OUString
& rCandidate
, SvgPaint
& rSvgPaint
,
1231 OUString
& rURL
, bool bCaseIndependent
, SvgNumber
& rOpacity
)
1233 if( !rCandidate
.isEmpty() )
1235 basegfx::BColor aColor
;
1237 if(read_color(rCandidate
, aColor
, bCaseIndependent
, rOpacity
))
1239 rSvgPaint
= SvgPaint(aColor
, true, true);
1244 if(rCandidate
.startsWith("none"))
1246 rSvgPaint
= SvgPaint(aColor
, true, false, false);
1249 else if(readLocalUrl(rCandidate
, rURL
))
1251 /// Url is copied to rURL, but needs to be solved outside this helper
1254 else if(rCandidate
.startsWith("currentColor"))
1256 rSvgPaint
= SvgPaint(aColor
, true, true, true);
1265 bool readSvgNumberVector(const OUString
& rCandidate
, SvgNumberVector
& rSvgNumberVector
)
1267 const sal_Int32
nLen(rCandidate
.getLength());
1268 rSvgNumberVector
.clear();
1274 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1276 while(readNumberAndUnit(rCandidate
, nPos
, aNum
, nLen
))
1278 rSvgNumberVector
.push_back(aNum
);
1279 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1282 return !rSvgNumberVector
.empty();
1288 SvgAspectRatio
readSvgAspectRatio(const OUString
& rCandidate
)
1290 const sal_Int32
nLen(rCandidate
.getLength());
1295 SvgAlign
aSvgAlign(Align_xMidYMid
);
1296 bool bMeetOrSlice(true);
1297 bool bChanged(false);
1301 const sal_Int32
nInitPos(nPos
);
1302 skip_char(rCandidate
, ' ', nPos
, nLen
);
1303 OUStringBuffer aTokenName
;
1304 copyString(rCandidate
, nPos
, aTokenName
, nLen
);
1306 if(!aTokenName
.isEmpty())
1308 switch(StrToSVGToken(aTokenName
.makeStringAndClear(), false))
1317 aSvgAlign
= Align_none
;
1321 case SVGTokenXMinYMin
:
1323 aSvgAlign
= Align_xMinYMin
;
1327 case SVGTokenXMidYMin
:
1329 aSvgAlign
= Align_xMidYMin
;
1333 case SVGTokenXMaxYMin
:
1335 aSvgAlign
= Align_xMaxYMin
;
1339 case SVGTokenXMinYMid
:
1341 aSvgAlign
= Align_xMinYMid
;
1345 case SVGTokenXMidYMid
:
1347 aSvgAlign
= Align_xMidYMid
;
1351 case SVGTokenXMaxYMid
:
1353 aSvgAlign
= Align_xMaxYMid
;
1357 case SVGTokenXMinYMax
:
1359 aSvgAlign
= Align_xMinYMax
;
1363 case SVGTokenXMidYMax
:
1365 aSvgAlign
= Align_xMidYMax
;
1369 case SVGTokenXMaxYMax
:
1371 aSvgAlign
= Align_xMaxYMax
;
1377 bMeetOrSlice
= true;
1383 bMeetOrSlice
= false;
1394 if(nInitPos
== nPos
)
1396 OSL_ENSURE(false, "Could not interpret on current position (!)");
1403 return SvgAspectRatio(aSvgAlign
, bMeetOrSlice
);
1407 return SvgAspectRatio();
1410 bool readSvgStringVector(const OUString
& rCandidate
, SvgStringVector
& rSvgStringVector
)
1412 rSvgStringVector
.clear();
1413 const sal_Int32
nLen(rCandidate
.getLength());
1418 OUStringBuffer aTokenValue
;
1419 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1423 copyToLimiter(rCandidate
, ',', nPos
, aTokenValue
, nLen
);
1424 skip_char(rCandidate
, ',', ' ', nPos
, nLen
);
1425 const OUString aString
= aTokenValue
.makeStringAndClear();
1427 if(!aString
.isEmpty())
1429 rSvgStringVector
.push_back(aString
);
1434 return !rSvgStringVector
.empty();
1437 void readImageLink(const OUString
& rCandidate
, OUString
& rXLink
, OUString
& rUrl
, OUString
& rMimeType
, OUString
& rData
)
1444 if('#' == rCandidate
[0])
1447 rXLink
= rCandidate
.copy(1);
1451 static const char aStrData
[] = "data:";
1453 if(rCandidate
.match(aStrData
, 0))
1456 sal_Int32
nPos(strlen(aStrData
));
1457 sal_Int32
nLen(rCandidate
.getLength());
1458 OUStringBuffer aBuffer
;
1461 skip_char(rCandidate
, ' ', nPos
, nLen
);
1462 copyToLimiter(rCandidate
, ';', nPos
, aBuffer
, nLen
);
1463 skip_char(rCandidate
, ' ', ';', nPos
, nLen
);
1464 rMimeType
= aBuffer
.makeStringAndClear();
1466 if(!rMimeType
.isEmpty() && nPos
< nLen
)
1468 if(rMimeType
.startsWith("image"))
1471 OUString
aData(rCandidate
.copy(nPos
));
1472 static const char aStrBase64
[] = "base64";
1474 if(aData
.startsWith(aStrBase64
))
1477 nPos
= strlen(aStrBase64
);
1478 nLen
= aData
.getLength();
1480 skip_char(aData
, ' ', ',', nPos
, nLen
);
1484 rData
= aData
.copy(nPos
);
1492 // Url (path and filename)
1498 OUString
convert(const OUString
& rCandidate
, sal_Unicode nPattern
, sal_Unicode nNew
, bool bRemove
)
1500 const sal_Int32
nLen(rCandidate
.getLength());
1505 OUStringBuffer aBuffer
;
1506 bool bChanged(false);
1510 const sal_Unicode
aChar(rCandidate
[nPos
]);
1512 if(nPattern
== aChar
)
1518 aBuffer
.append(nNew
);
1523 aBuffer
.append(aChar
);
1531 return aBuffer
.makeStringAndClear();
1539 OUString
removeBlockComments(const OUString
& rCandidate
)
1541 const sal_Int32
nLen(rCandidate
.getLength());
1546 OUStringBuffer aBuffer
;
1547 bool bChanged(false);
1548 sal_Int32
nInsideComment(0);
1549 const sal_Unicode
aCommentSlash('/');
1550 const sal_Unicode
aCommentStar('*');
1554 const sal_Unicode
aChar(rCandidate
[nPos
]);
1555 const bool bStart(aCommentSlash
== aChar
&& nPos
+ 1 < nLen
&& aCommentStar
== rCandidate
[nPos
+ 1]);
1556 const bool bEnd(aCommentStar
== aChar
&& nPos
+ 1 < nLen
&& aCommentSlash
== rCandidate
[nPos
+ 1]);
1573 aBuffer
.append(aChar
);
1582 return aBuffer
.makeStringAndClear();
1589 OUString
consolidateContiguousSpace(const OUString
& rCandidate
)
1591 const sal_Int32
nLen(rCandidate
.getLength());
1596 OUStringBuffer aBuffer
;
1597 bool bInsideSpace(false);
1598 const sal_Unicode
aSpace(' ');
1602 const sal_Unicode
aChar(rCandidate
[nPos
]);
1606 bInsideSpace
= true;
1612 bInsideSpace
= false;
1613 aBuffer
.append(aSpace
);
1616 aBuffer
.append(aChar
);
1624 aBuffer
.append(aSpace
);
1627 if(aBuffer
.getLength() != nLen
)
1629 return aBuffer
.makeStringAndClear();
1636 OUString
whiteSpaceHandlingDefault(const OUString
& rCandidate
)
1638 const sal_Unicode
aNewline('\n');
1639 const sal_Unicode
aTab('\t');
1640 const sal_Unicode
aSpace(' ');
1642 // remove all newline characters
1643 OUString
aRetval(convert(rCandidate
, aNewline
, aNewline
, true));
1645 // convert tab to space
1646 aRetval
= convert(aRetval
, aTab
, aSpace
, false);
1648 // strip of all leading and trailing spaces
1649 aRetval
= aRetval
.trim();
1651 // consolidate contiguous space
1652 aRetval
= consolidateContiguousSpace(aRetval
);
1657 OUString
whiteSpaceHandlingPreserve(const OUString
& rCandidate
)
1659 const sal_Unicode
aNewline('\n');
1660 const sal_Unicode
aTab('\t');
1661 const sal_Unicode
aSpace(' ');
1663 // convert newline to space
1664 convert(rCandidate
, aNewline
, aSpace
, false);
1666 // convert tab to space
1667 convert(rCandidate
, aTab
, aSpace
, false);
1672 ::std::vector
< double > solveSvgNumberVector(const SvgNumberVector
& rInput
, const InfoProvider
& rInfoProvider
)
1674 ::std::vector
< double > aRetval
;
1678 const double nCount(rInput
.size());
1679 aRetval
.reserve(nCount
);
1681 for(sal_uInt32
a(0); a
< nCount
; a
++)
1683 aRetval
.push_back(rInput
[a
].solve(rInfoProvider
));
1690 } // end of namespace svgreader
1691 } // end of namespace svgio
1693 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */