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 <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 <unordered_map>
33 void myAssert(const OUString
& rMessage
)
37 rMessage
.convertToString(&aMessage2
, osl_getThreadTextEncoding(), RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
|RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR
);
38 OSL_ENSURE(false, aMessage2
.getStr());
42 // common non-token strings
43 const OUString
commonStrings::aStrUserSpaceOnUse("userSpaceOnUse");
44 const OUString
commonStrings::aStrObjectBoundingBox("objectBoundingBox");
45 const OUString
commonStrings::aStrNonzero("nonzero");
46 const OUString
commonStrings::aStrEvenOdd("evenodd");
48 basegfx::B2DHomMatrix
SvgAspectRatio::createLinearMapping(const basegfx::B2DRange
& rTarget
, const basegfx::B2DRange
& rSource
)
50 basegfx::B2DHomMatrix aRetval
;
51 const double fSWidth(rSource
.getWidth());
52 const double fSHeight(rSource
.getHeight());
53 const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth
));
54 const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight
));
56 // transform from source state to unit range
57 aRetval
.translate(-rSource
.getMinX(), -rSource
.getMinY());
59 (bNoSWidth
? 1.0 : 1.0 / fSWidth
) * rTarget
.getWidth(),
60 (bNoSHeight
? 1.0 : 1.0 / fSHeight
) * rTarget
.getHeight());
62 // transform from unit rage to target range
63 aRetval
.translate(rTarget
.getMinX(), rTarget
.getMinY());
68 basegfx::B2DHomMatrix
SvgAspectRatio::createMapping(const basegfx::B2DRange
& rTarget
, const basegfx::B2DRange
& rSource
) const
70 if(!isSet() || Align_none
== getSvgAlign())
72 // create linear mapping (default)
73 return createLinearMapping(rTarget
, rSource
);
76 basegfx::B2DHomMatrix aRetval
;
78 const double fSWidth(rSource
.getWidth());
79 const double fSHeight(rSource
.getHeight());
80 const bool bNoSWidth(basegfx::fTools::equalZero(fSWidth
));
81 const bool bNoSHeight(basegfx::fTools::equalZero(fSHeight
));
82 const double fScaleX((bNoSWidth
? 1.0 : 1.0 / fSWidth
) * rTarget
.getWidth());
83 const double fScaleY((bNoSHeight
? 1.0 : 1.0 / fSHeight
) * rTarget
.getHeight());
84 const double fScale(isMeetOrSlice() ? std::min(fScaleX
, fScaleY
) : std::max(fScaleX
, fScaleY
));
86 // remove source translation, apply scale
87 aRetval
.translate(-rSource
.getMinX(), -rSource
.getMinY());
88 aRetval
.scale(fScale
, fScale
);
90 // evaluate horizontal alignment
91 const double fNewWidth(fSWidth
* fScale
);
101 const double fFreeSpace(rTarget
.getWidth() - fNewWidth
);
102 fTransX
= fFreeSpace
* 0.5;
110 const double fFreeSpace(rTarget
.getWidth() - fNewWidth
);
111 fTransX
= fFreeSpace
;
117 // evaluate vertical alignment
118 const double fNewHeight(fSHeight
* fScale
);
121 switch(getSvgAlign())
128 const double fFreeSpace(rTarget
.getHeight() - fNewHeight
);
129 fTransY
= fFreeSpace
* 0.5;
137 const double fFreeSpace(rTarget
.getHeight() - fNewHeight
);
138 fTransY
= fFreeSpace
;
144 // add target translation
146 rTarget
.getMinX() + fTransX
,
147 rTarget
.getMinY() + fTransY
);
152 double SvgNumber::solveNonPercentage(const InfoProvider
& rInfoProvider
) const
160 return mfNumber
* rInfoProvider
.getCurrentFontSizeInherited();
164 return mfNumber
* rInfoProvider
.getCurrentXHeightInherited() * 0.5;
176 double fRetval(mfNumber
);
180 case Unit_pt
: fRetval
*= F_SVG_PIXEL_PER_INCH
/ 72.0; break;
181 case Unit_pc
: fRetval
*= F_SVG_PIXEL_PER_INCH
/ 6.0; break;
182 case Unit_cm
: fRetval
*= F_SVG_PIXEL_PER_INCH
/ 2.54; break;
183 case Unit_mm
: fRetval
*= 0.1 * F_SVG_PIXEL_PER_INCH
/ 2.54; break;
184 case Unit_in
: fRetval
*= F_SVG_PIXEL_PER_INCH
; break;
192 OSL_ENSURE(false, "Do not use with percentage! ");
199 OSL_ENSURE(false, "SvgNumber not set (!)");
203 double SvgNumber::solve(const InfoProvider
& rInfoProvider
, NumberType aNumberType
) const
221 return solveNonPercentage( rInfoProvider
);
225 double fRetval(mfNumber
* 0.01);
226 basegfx::B2DRange aViewPort
= rInfoProvider
.getCurrentViewPort();
228 if ( aViewPort
.isEmpty() )
231 myAssert(OUString("Design error, this case should have been handled in the caller"));
233 // no viewPort, assume a normal page size (A4)
234 aViewPort
= basegfx::B2DRange(
237 210.0 * F_SVG_PIXEL_PER_INCH
/ 2.54,
238 297.0 * F_SVG_PIXEL_PER_INCH
/ 2.54);
242 if ( !aViewPort
.isEmpty() )
244 if(xcoordinate
== aNumberType
)
246 // it's a x-coordinate, relative to current width (w)
247 fRetval
*= aViewPort
.getWidth();
249 else if(ycoordinate
== aNumberType
)
251 // it's a y-coordinate, relative to current height (h)
252 fRetval
*= aViewPort
.getHeight();
256 // it's a length, relative to sqrt(w*w + h*h)/sqrt(2)
257 const double fCurrentWidth(aViewPort
.getWidth());
258 const double fCurrentHeight(aViewPort
.getHeight());
259 const double fCurrentLength(
260 sqrt(fCurrentWidth
* fCurrentWidth
+ fCurrentHeight
* fCurrentHeight
)/sqrt(2.0));
262 fRetval
*= fCurrentLength
;
276 OSL_ENSURE(false, "SvgNumber not set (!)");
280 bool SvgNumber::isPositive() const
282 return basegfx::fTools::moreOrEqual(mfNumber
, 0.0);
285 void skip_char(const OUString
& rCandidate
, const sal_Unicode
& rChar
, sal_Int32
& nPos
, const sal_Int32 nLen
)
287 while(nPos
< nLen
&& rChar
== rCandidate
[nPos
])
293 void skip_char(const OUString
& rCandidate
, const sal_Unicode
& rCharA
, const sal_Unicode
& rCharB
, sal_Int32
& nPos
, const sal_Int32 nLen
)
295 while(nPos
< nLen
&& (rCharA
== rCandidate
[nPos
] || rCharB
== rCandidate
[nPos
]))
301 void copySign(const OUString
& rCandidate
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
305 const sal_Unicode
aChar(rCandidate
[nPos
]);
307 if('+' == aChar
|| '-' == aChar
)
309 rTarget
.append(aChar
);
315 void copyNumber(const OUString
& rCandidate
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
317 bool bOnNumber(true);
319 while(bOnNumber
&& nPos
< nLen
)
321 const sal_Unicode
aChar(rCandidate
[nPos
]);
323 bOnNumber
= ('0' <= aChar
&& '9' >= aChar
) || '.' == aChar
;
327 rTarget
.append(aChar
);
333 void copyHex(const OUString
& rCandidate
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
337 while(bOnHex
&& nPos
< nLen
)
339 const sal_Unicode
aChar(rCandidate
[nPos
]);
341 bOnHex
= ('0' <= aChar
&& '9' >= aChar
)
342 || ('A' <= aChar
&& 'F' >= aChar
)
343 || ('a' <= aChar
&& 'f' >= aChar
);
347 rTarget
.append(aChar
);
353 void copyString(const OUString
& rCandidate
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
357 while(bOnChar
&& nPos
< nLen
)
359 const sal_Unicode
aChar(rCandidate
[nPos
]);
361 bOnChar
= ('a' <= aChar
&& 'z' >= aChar
)
362 || ('A' <= aChar
&& 'Z' >= aChar
)
367 rTarget
.append(aChar
);
373 void copyToLimiter(const OUString
& rCandidate
, const sal_Unicode
& rLimiter
, sal_Int32
& nPos
, OUStringBuffer
& rTarget
, const sal_Int32 nLen
)
375 while(nPos
< nLen
&& rLimiter
!= rCandidate
[nPos
])
377 rTarget
.append(rCandidate
[nPos
]);
382 bool readNumber(const OUString
& rCandidate
, sal_Int32
& nPos
, double& fNum
, const sal_Int32 nLen
)
388 copySign(rCandidate
, nPos
, aNum
, nLen
);
389 copyNumber(rCandidate
, nPos
, aNum
, nLen
);
393 const sal_Unicode
aChar(rCandidate
[nPos
]);
395 if('e' == aChar
|| 'E' == aChar
)
397 // try to read exponential number, but be careful. I had
398 // a case where dx="2em" was used, thus the 'e' was consumed
399 // by error. First try if there are numbers after the 'e',
400 // safe current state
402 const OUStringBuffer
aNum2(aNum
);
403 const sal_Int32
nPosAfterE(nPos
);
406 copySign(rCandidate
, nPos
, aNum
, nLen
);
407 copyNumber(rCandidate
, nPos
, aNum
, nLen
);
409 if(nPosAfterE
== nPos
)
411 // no number after 'e', go back. Do not
412 // return false, it's still a valid integer number
421 rtl_math_ConversionStatus eStatus
;
423 fNum
= rtl::math::stringToDouble(
424 aNum
.makeStringAndClear(), '.', ',',
427 return eStatus
== rtl_math_ConversionStatus_Ok
;
434 SvgUnit
readUnit(const OUString
& rCandidate
, sal_Int32
& nPos
, const sal_Int32 nLen
)
436 SvgUnit
aRetval(Unit_px
);
440 const sal_Unicode
aCharA(rCandidate
[nPos
]);
444 const sal_Unicode
aCharB(rCandidate
[nPos
+ 1]);
445 bool bTwoCharValid(false);
449 case sal_Unicode('e') :
453 // 'em' Relative to current font size
455 bTwoCharValid
= true;
457 else if('x' == aCharB
)
459 // 'ex' Relative to current font x-height
461 bTwoCharValid
= true;
465 case sal_Unicode('p') :
469 // 'px' UserUnit (default)
470 bTwoCharValid
= true;
472 else if('t' == aCharB
)
476 bTwoCharValid
= true;
478 else if('c' == aCharB
)
482 bTwoCharValid
= true;
486 case sal_Unicode('i') :
492 bTwoCharValid
= true;
496 case sal_Unicode('c') :
500 // 'cm' == 35.43307 px
502 bTwoCharValid
= true;
506 case sal_Unicode('m') :
510 // 'mm' == 3.543307 px
512 bTwoCharValid
= true;
527 // percent used, relative to current
529 aRetval
= Unit_percent
;
537 bool readNumberAndUnit(const OUString
& rCandidate
, sal_Int32
& nPos
, SvgNumber
& aNum
, const sal_Int32 nLen
)
541 if(readNumber(rCandidate
, nPos
, fNum
, nLen
))
543 skip_char(rCandidate
, ' ', nPos
, nLen
);
544 aNum
= SvgNumber(fNum
, readUnit(rCandidate
, nPos
, nLen
));
552 bool readAngle(const OUString
& rCandidate
, sal_Int32
& nPos
, double& fAngle
, const sal_Int32 nLen
)
554 if(readNumber(rCandidate
, nPos
, fAngle
, nLen
))
556 skip_char(rCandidate
, ' ', nPos
, nLen
);
563 } aType(deg
); // degrees is default
567 const sal_Unicode
aChar(rCandidate
[nPos
]);
568 static const char aStrGrad
[] = "grad";
569 static const char aStrRad
[] = "rad";
573 case sal_Unicode('g') :
574 case sal_Unicode('G') :
576 if(rCandidate
.matchIgnoreAsciiCase(aStrGrad
, nPos
))
579 nPos
+= strlen(aStrGrad
);
584 case sal_Unicode('r') :
585 case sal_Unicode('R') :
587 if(rCandidate
.matchIgnoreAsciiCase(aStrRad
, nPos
))
590 nPos
+= strlen(aStrRad
);
598 // convert to radians
601 fAngle
*= F_PI
/ 180.0;
603 else if(grad
== aType
)
605 // looks like 100 grad is 90 degrees
606 fAngle
*= F_PI
/ 200.0;
615 sal_Int32
read_hex(const sal_Unicode
& rChar
)
617 if(rChar
>= '0' && rChar
<= '9')
619 return sal_Int32(rChar
- sal_Unicode('0'));
621 else if(rChar
>= 'A' && rChar
<= 'F')
623 return 10 + sal_Int32(rChar
- sal_Unicode('A'));
625 else if(rChar
>= 'a' && rChar
<= 'f')
627 return 10 + sal_Int32(rChar
- sal_Unicode('a'));
636 bool match_colorKeyword(basegfx::BColor
& rColor
, const OUString
& rName
, bool bCaseIndependent
)
638 typedef std::unordered_map
< OUString
, Color
,
640 ::std::equal_to
< OUString
>
642 typedef std::pair
< OUString
, Color
> ColorTokenValueType
;
643 ColorTokenMapper aColorTokenMapperList
;
645 if(aColorTokenMapperList
.empty())
647 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("aliceblue"), Color(240, 248, 255)));
648 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("antiquewhite"), Color(250, 235, 215)));
649 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("aqua"), Color( 0, 255, 255)));
650 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("aquamarine"), Color(127, 255, 212)));
651 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("azure"), Color(240, 255, 255)));
652 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("beige"), Color(245, 245, 220)));
653 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("bisque"), Color(255, 228, 196)));
654 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("black"), Color( 0, 0, 0)));
655 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("blanchedalmond"), Color(255, 235, 205)));
656 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("blue"), Color( 0, 0, 255)));
657 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("blueviolet"), Color(138, 43, 226)));
658 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("brown"), Color(165, 42, 42)));
659 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("burlywood"), Color(222, 184, 135)));
660 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("cadetblue"), Color( 95, 158, 160)));
661 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("chartreuse"), Color(127, 255, 0)));
662 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("chocolate"), Color(210, 105, 30)));
663 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("coral"), Color(255, 127, 80)));
664 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("cornflowerblue"), Color(100, 149, 237)));
665 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("cornsilk"), Color(255, 248, 220)));
666 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("crimson"), Color(220, 20, 60)));
667 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("cyan"), Color( 0, 255, 255)));
668 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkblue"), Color( 0, 0, 139)));
669 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkcyan"), Color( 0, 139, 139)));
670 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkgoldenrod"), Color(184, 134, 11)));
671 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkgray"), Color(169, 169, 169)));
672 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkgreen"), Color( 0, 100, 0)));
673 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkgrey"), Color(169, 169, 169)));
674 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkkhaki"), Color(189, 183, 107)));
675 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkmagenta"), Color(139, 0, 139)));
676 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkolivegreen"), Color( 85, 107, 47)));
677 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkorange"), Color(255, 140, 0)));
678 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkorchid"), Color(153, 50, 204)));
679 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkred"), Color(139, 0, 0)));
680 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darksalmon"), Color(233, 150, 122)));
681 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkseagreen"), Color(143, 188, 143)));
682 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkslateblue"), Color( 72, 61, 139)));
683 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkslategray"), Color( 47, 79, 79)));
684 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkslategrey"), Color( 47, 79, 79)));
685 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkturquoise"), Color( 0, 206, 209)));
686 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("darkviolet"), Color(148, 0, 211)));
687 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("deeppink"), Color(255, 20, 147)));
688 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("deepskyblue"), Color( 0, 191, 255)));
689 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("dimgray"), Color(105, 105, 105)));
690 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("dimgrey"), Color(105, 105, 105)));
691 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("dodgerblue"), Color( 30, 144, 255)));
692 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("firebrick"), Color(178, 34, 34)));
693 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("floralwhite"), Color(255, 250, 240)));
694 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("forestgreen"), Color( 34, 139, 34)));
695 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("fuchsia"), Color(255, 0, 255)));
696 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("gainsboro"), Color(220, 220, 220)));
697 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("ghostwhite"), Color(248, 248, 255)));
698 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("gold"), Color(255, 215, 0)));
699 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("goldenrod"), Color(218, 165, 32)));
700 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("gray"), Color(128, 128, 128)));
701 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("grey"), Color(128, 128, 128)));
702 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("green"), Color(0, 128, 0)));
703 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("greenyellow"), Color(173, 255, 47)));
704 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("honeydew"), Color(240, 255, 240)));
705 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("hotpink"), Color(255, 105, 180)));
706 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("indianred"), Color(205, 92, 92)));
707 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("indigo"), Color( 75, 0, 130)));
708 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("ivory"), Color(255, 255, 240)));
709 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("khaki"), Color(240, 230, 140)));
710 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lavender"), Color(230, 230, 250)));
711 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lavenderblush"), Color(255, 240, 245)));
712 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lawngreen"), Color(124, 252, 0)));
713 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lemonchiffon"), Color(255, 250, 205)));
714 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightblue"), Color(173, 216, 230)));
715 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightcoral"), Color(240, 128, 128)));
716 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightcyan"), Color(224, 255, 255)));
717 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightgoldenrodyellow"), Color(250, 250, 210)));
718 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightgray"), Color(211, 211, 211)));
719 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightgreen"), Color(144, 238, 144)));
720 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightgrey"), Color(211, 211, 211)));
721 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightpink"), Color(255, 182, 193)));
722 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightsalmon"), Color(255, 160, 122)));
723 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightseagreen"), Color( 32, 178, 170)));
724 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightskyblue"), Color(135, 206, 250)));
725 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightslategray"), Color(119, 136, 153)));
726 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightslategrey"), Color(119, 136, 153)));
727 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightsteelblue"), Color(176, 196, 222)));
728 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lightyellow"), Color(255, 255, 224)));
729 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("lime"), Color( 0, 255, 0)));
730 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("limegreen"), Color( 50, 205, 50)));
731 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("linen"), Color(250, 240, 230)));
732 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("magenta"), Color(255, 0, 255)));
733 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("maroon"), Color(128, 0, 0)));
734 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumaquamarine"), Color(102, 205, 170)));
735 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumblue"), Color( 0, 0, 205)));
736 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumorchid"), Color(186, 85, 211)));
737 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumpurple"), Color(147, 112, 219)));
738 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumseagreen"), Color( 60, 179, 113)));
739 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumslateblue"), Color(123, 104, 238)));
740 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumspringgreen"), Color( 0, 250, 154)));
741 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumturquoise"), Color( 72, 209, 204)));
742 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mediumvioletred"), Color(199, 21, 133)));
743 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("midnightblue"), Color( 25, 25, 112)));
744 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mintcream"), Color(245, 255, 250)));
745 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("mistyrose"), Color(255, 228, 225)));
746 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("moccasin"), Color(255, 228, 181)));
747 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("navajowhite"), Color(255, 222, 173)));
748 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("navy"), Color( 0, 0, 128)));
749 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("oldlace"), Color(253, 245, 230)));
750 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("olive"), Color(128, 128, 0)));
751 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("olivedrab"), Color(107, 142, 35)));
752 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("orange"), Color(255, 165, 0)));
753 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("orangered"), Color(255, 69, 0)));
754 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("orchid"), Color(218, 112, 214)));
755 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("palegoldenrod"), Color(238, 232, 170)));
756 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("palegreen"), Color(152, 251, 152)));
757 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("paleturquoise"), Color(175, 238, 238)));
758 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("palevioletred"), Color(219, 112, 147)));
759 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("papayawhip"), Color(255, 239, 213)));
760 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("peachpuff"), Color(255, 218, 185)));
761 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("peru"), Color(205, 133, 63)));
762 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("pink"), Color(255, 192, 203)));
763 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("plum"), Color(221, 160, 221)));
764 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("powderblue"), Color(176, 224, 230)));
765 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("purple"), Color(128, 0, 128)));
766 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("red"), Color(255, 0, 0)));
767 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("rosybrown"), Color(188, 143, 143)));
768 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("royalblue"), Color( 65, 105, 225)));
769 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("saddlebrown"), Color(139, 69, 19)));
770 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("salmon"), Color(250, 128, 114)));
771 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("sandybrown"), Color(244, 164, 96)));
772 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("seagreen"), Color( 46, 139, 87)));
773 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("seashell"), Color(255, 245, 238)));
774 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("sienna"), Color(160, 82, 45)));
775 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("silver"), Color(192, 192, 192)));
776 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("skyblue"), Color(135, 206, 235)));
777 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("slateblue"), Color(106, 90, 205)));
778 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("slategray"), Color(112, 128, 144)));
779 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("slategrey"), Color(112, 128, 144)));
780 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("snow"), Color(255, 250, 250)));
781 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("springgreen"), Color( 0, 255, 127)));
782 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("steelblue"), Color( 70, 130, 180)));
783 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("tan"), Color(210, 180, 140)));
784 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("teal"), Color( 0, 128, 128)));
785 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("thistle"), Color(216, 191, 216)));
786 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("tomato"), Color(255, 99, 71)));
787 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("turquoise"), Color( 64, 224, 208)));
788 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("violet"), Color(238, 130, 238)));
789 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("wheat"), Color(245, 222, 179)));
790 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("white"), Color(255, 255, 255)));
791 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("whitesmoke"), Color(245, 245, 245)));
792 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("yellow"), Color(255, 255, 0)));
793 aColorTokenMapperList
.insert(ColorTokenValueType(OUString("yellowgreen"), Color(154, 205, 50)));
796 ColorTokenMapper::const_iterator
aResult(aColorTokenMapperList
.find(rName
));
798 if(bCaseIndependent
&& aResult
== aColorTokenMapperList
.end())
800 // also try case independent match (e.g. for Css styles)
801 aResult
= aColorTokenMapperList
.find(rName
.toAsciiLowerCase());
804 if(aResult
== aColorTokenMapperList
.end())
810 rColor
= aResult
->second
.getBColor();
815 bool read_color(const OUString
& rCandidate
, basegfx::BColor
& rColor
, bool bCaseIndependent
)
817 const sal_Int32
nLen(rCandidate
.getLength());
821 const sal_Unicode
aChar(rCandidate
[0]);
822 const double fFactor(1.0 / 255.0);
830 copyHex(rCandidate
, nPos
, aNum
, nLen
);
831 const sal_Int32
nLength(aNum
.getLength());
835 const sal_Int32
nR(read_hex(aNum
[0]));
836 const sal_Int32
nG(read_hex(aNum
[1]));
837 const sal_Int32
nB(read_hex(aNum
[2]));
839 rColor
.setRed((nR
| (nR
<< 4)) * fFactor
);
840 rColor
.setGreen((nG
| (nG
<< 4)) * fFactor
);
841 rColor
.setBlue((nB
| (nB
<< 4)) * fFactor
);
845 else if(6 == nLength
)
847 const sal_Int32
nR1(read_hex(aNum
[0]));
848 const sal_Int32
nR2(read_hex(aNum
[1]));
849 const sal_Int32
nG1(read_hex(aNum
[2]));
850 const sal_Int32
nG2(read_hex(aNum
[3]));
851 const sal_Int32
nB1(read_hex(aNum
[4]));
852 const sal_Int32
nB2(read_hex(aNum
[5]));
854 rColor
.setRed((nR2
| (nR1
<< 4)) * fFactor
);
855 rColor
.setGreen((nG2
| (nG1
<< 4)) * fFactor
);
856 rColor
.setBlue((nB2
| (nB1
<< 4)) * fFactor
);
863 static const char aStrRgb
[] = "rgb";
865 if(rCandidate
.matchIgnoreAsciiCase(aStrRgb
, 0))
868 sal_Int32
nPos(strlen(aStrRgb
));
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
))
902 const double fFac(bIsPercent
? 0.01 : fFactor
);
904 rColor
.setRed(fR
* fFac
);
905 rColor
.setGreen(fG
* fFac
);
906 rColor
.setBlue(fB
* fFac
);
910 skip_char(rCandidate
, '%', nPos
, nLen
);
913 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
923 if(match_colorKeyword(rColor
, rCandidate
, bCaseIndependent
))
934 basegfx::B2DRange
readViewBox(const OUString
& rCandidate
, InfoProvider
& rInfoProvider
)
936 const sal_Int32
nLen(rCandidate
.getLength());
942 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
944 if(readNumberAndUnit(rCandidate
, nPos
, aMinX
, nLen
))
947 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
949 if(readNumberAndUnit(rCandidate
, nPos
, aMinY
, nLen
))
952 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
954 if(readNumberAndUnit(rCandidate
, nPos
, aWidth
, nLen
))
957 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
959 if(readNumberAndUnit(rCandidate
, nPos
, aHeight
, nLen
))
961 double fX(aMinX
.solve(rInfoProvider
, xcoordinate
));
962 double fY(aMinY
.solve(rInfoProvider
, ycoordinate
));
963 double fW(aWidth
.solve(rInfoProvider
,xcoordinate
));
964 double fH(aHeight
.solve(rInfoProvider
,ycoordinate
));
965 return basegfx::B2DRange(fX
,fY
,fX
+fW
,fY
+fH
);
972 return basegfx::B2DRange();
975 basegfx::B2DHomMatrix
readTransform(const OUString
& rCandidate
, InfoProvider
& rInfoProvider
)
977 basegfx::B2DHomMatrix aMatrix
;
978 const sal_Int32
nLen(rCandidate
.getLength());
983 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
987 const sal_Unicode
aChar(rCandidate
[nPos
]);
988 const sal_Int32
nInitPos(nPos
);
989 static const char aStrMatrix
[] = "matrix";
990 static const char aStrTranslate
[] = "translate";
991 static const char aStrScale
[] = "scale";
992 static const char aStrRotate
[] = "rotate";
993 static const char aStrSkewX
[] = "skewX";
994 static const char aStrSkewY
[] = "skewY";
998 case sal_Unicode('m') :
1000 if(rCandidate
.match(aStrMatrix
, nPos
))
1003 nPos
+= strlen(aStrMatrix
);
1004 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1006 basegfx::B2DHomMatrix aNew
;
1008 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1010 aNew
.set(0, 0, aVal
.solve(rInfoProvider
)); // Element A
1011 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1013 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1015 aNew
.set(1, 0, aVal
.solve(rInfoProvider
)); // Element B
1016 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1018 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1020 aNew
.set(0, 1, aVal
.solve(rInfoProvider
)); // Element C
1021 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1023 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1025 aNew
.set(1, 1, aVal
.solve(rInfoProvider
)); // Element D
1026 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1028 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1030 aNew
.set(0, 2, aVal
.solve(rInfoProvider
, xcoordinate
)); // Element E
1031 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1033 if(readNumberAndUnit(rCandidate
, nPos
, aVal
, nLen
))
1035 aNew
.set(1, 2, aVal
.solve(rInfoProvider
, ycoordinate
)); // Element F
1036 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1037 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1039 // caution: String is evaluated from left to right, but matrix multiplication
1040 // in SVG is right to left, so put the new transformation before the current
1041 // one by multiplicating from the right side
1042 aMatrix
= aMatrix
* aNew
;
1052 case sal_Unicode('t') :
1054 if(rCandidate
.match(aStrTranslate
, nPos
))
1056 // translate element
1057 nPos
+= strlen(aStrTranslate
);
1058 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1061 if(readNumberAndUnit(rCandidate
, nPos
, aTransX
, nLen
))
1063 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1065 readNumberAndUnit(rCandidate
, nPos
, aTransY
, nLen
);
1066 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1067 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1069 aMatrix
= aMatrix
* basegfx::tools::createTranslateB2DHomMatrix(
1070 aTransX
.solve(rInfoProvider
, xcoordinate
),
1071 aTransY
.solve(rInfoProvider
, ycoordinate
));
1076 case sal_Unicode('s') :
1078 if(rCandidate
.match(aStrScale
, nPos
))
1081 nPos
+= strlen(aStrScale
);
1082 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1085 if(readNumberAndUnit(rCandidate
, nPos
, aScaleX
, nLen
))
1087 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1088 SvgNumber
aScaleY(aScaleX
);
1089 readNumberAndUnit(rCandidate
, nPos
, aScaleY
, nLen
);
1090 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1091 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1093 aMatrix
= aMatrix
* basegfx::tools::createScaleB2DHomMatrix(
1094 aScaleX
.solve(rInfoProvider
),
1095 aScaleY
.solve(rInfoProvider
));
1098 else if(rCandidate
.match(aStrSkewX
, nPos
))
1101 nPos
+= strlen(aStrSkewX
);
1102 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1105 if(readAngle(rCandidate
, nPos
, fSkewX
, nLen
))
1107 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1108 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1110 aMatrix
= aMatrix
* basegfx::tools::createShearXB2DHomMatrix(tan(fSkewX
));
1113 else if(rCandidate
.match(aStrSkewY
, nPos
))
1116 nPos
+= strlen(aStrSkewY
);
1117 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1120 if(readAngle(rCandidate
, nPos
, fSkewY
, nLen
))
1122 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1123 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1125 aMatrix
= aMatrix
* basegfx::tools::createShearYB2DHomMatrix(tan(fSkewY
));
1130 case sal_Unicode('r') :
1132 if(rCandidate
.match(aStrRotate
, nPos
))
1135 nPos
+= strlen(aStrRotate
);
1136 skip_char(rCandidate
, ' ', '(', nPos
, nLen
);
1139 if(readAngle(rCandidate
, nPos
, fAngle
, nLen
))
1141 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1143 readNumberAndUnit(rCandidate
, nPos
, aX
, nLen
);
1144 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1146 readNumberAndUnit(rCandidate
, nPos
, aY
, nLen
);
1147 skip_char(rCandidate
, ' ', ')', nPos
, nLen
);
1148 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1150 const double fX(aX
.isSet() ? aX
.solve(rInfoProvider
, xcoordinate
) : 0.0);
1151 const double fY(aY
.isSet() ? aY
.solve(rInfoProvider
, ycoordinate
) : 0.0);
1153 if(!basegfx::fTools::equalZero(fX
) || !basegfx::fTools::equalZero(fY
))
1155 // rotate around point
1156 aMatrix
= aMatrix
* basegfx::tools::createRotateAroundPoint(fX
, fY
, fAngle
);
1161 aMatrix
= aMatrix
* basegfx::tools::createRotateB2DHomMatrix(fAngle
);
1169 if(nInitPos
== nPos
)
1171 OSL_ENSURE(false, "Could not interpret on current position (!)");
1180 bool readSingleNumber(const OUString
& rCandidate
, SvgNumber
& aNum
)
1182 const sal_Int32
nLen(rCandidate
.getLength());
1185 return readNumberAndUnit(rCandidate
, nPos
, aNum
, nLen
);
1188 bool readLocalUrl(const OUString
& rCandidate
, OUString
& rURL
)
1190 static const char aStrUrl
[] = "url";
1192 if(rCandidate
.startsWith(aStrUrl
))
1194 const sal_Int32
nLen(rCandidate
.getLength());
1195 sal_Int32
nPos(strlen(aStrUrl
));
1197 skip_char(rCandidate
, '(', '#', nPos
, nLen
);
1198 OUStringBuffer aTokenValue
;
1199 copyToLimiter(rCandidate
, ')', nPos
, aTokenValue
, nLen
);
1200 rURL
= aTokenValue
.makeStringAndClear();
1208 bool readSvgPaint(const OUString
& rCandidate
, SvgPaint
& rSvgPaint
, OUString
& rURL
, bool bCaseIndependent
)
1210 if( !rCandidate
.isEmpty() )
1212 basegfx::BColor aColor
;
1214 if(read_color(rCandidate
, aColor
, bCaseIndependent
))
1216 rSvgPaint
= SvgPaint(aColor
, true, true);
1221 if(rCandidate
.startsWith("none"))
1223 rSvgPaint
= SvgPaint(aColor
, true, false, false);
1226 else if(readLocalUrl(rCandidate
, rURL
))
1228 /// Url is copied to rURL, but needs to be solved outside this helper
1231 else if(rCandidate
.startsWith("currentColor"))
1233 rSvgPaint
= SvgPaint(aColor
, true, true, true);
1242 bool readSvgNumberVector(const OUString
& rCandidate
, SvgNumberVector
& rSvgNumberVector
)
1244 const sal_Int32
nLen(rCandidate
.getLength());
1245 rSvgNumberVector
.clear();
1251 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1253 while(readNumberAndUnit(rCandidate
, nPos
, aNum
, nLen
))
1255 rSvgNumberVector
.push_back(aNum
);
1256 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1259 return !rSvgNumberVector
.empty();
1265 SvgAspectRatio
readSvgAspectRatio(const OUString
& rCandidate
)
1267 const sal_Int32
nLen(rCandidate
.getLength());
1272 SvgAlign
aSvgAlign(Align_xMidYMid
);
1274 bool bMeetOrSlice(true);
1275 bool bChanged(false);
1279 const sal_Int32
nInitPos(nPos
);
1280 skip_char(rCandidate
, ' ', nPos
, nLen
);
1281 OUStringBuffer aTokenName
;
1282 copyString(rCandidate
, nPos
, aTokenName
, nLen
);
1284 if(!aTokenName
.isEmpty())
1286 switch(StrToSVGToken(aTokenName
.makeStringAndClear(), false))
1296 aSvgAlign
= Align_none
;
1300 case SVGTokenXMinYMin
:
1302 aSvgAlign
= Align_xMinYMin
;
1306 case SVGTokenXMidYMin
:
1308 aSvgAlign
= Align_xMidYMin
;
1312 case SVGTokenXMaxYMin
:
1314 aSvgAlign
= Align_xMaxYMin
;
1318 case SVGTokenXMinYMid
:
1320 aSvgAlign
= Align_xMinYMid
;
1324 case SVGTokenXMidYMid
:
1326 aSvgAlign
= Align_xMidYMid
;
1330 case SVGTokenXMaxYMid
:
1332 aSvgAlign
= Align_xMaxYMid
;
1336 case SVGTokenXMinYMax
:
1338 aSvgAlign
= Align_xMinYMax
;
1342 case SVGTokenXMidYMax
:
1344 aSvgAlign
= Align_xMidYMax
;
1348 case SVGTokenXMaxYMax
:
1350 aSvgAlign
= Align_xMaxYMax
;
1356 bMeetOrSlice
= true;
1362 bMeetOrSlice
= false;
1373 if(nInitPos
== nPos
)
1375 OSL_ENSURE(false, "Could not interpret on current position (!)");
1382 return SvgAspectRatio(aSvgAlign
, bDefer
, bMeetOrSlice
);
1386 return SvgAspectRatio();
1389 bool readSvgStringVector(const OUString
& rCandidate
, SvgStringVector
& rSvgStringVector
)
1391 rSvgStringVector
.clear();
1392 const sal_Int32
nLen(rCandidate
.getLength());
1397 OUStringBuffer aTokenValue
;
1398 skip_char(rCandidate
, ' ', ',', nPos
, nLen
);
1402 copyToLimiter(rCandidate
, ',', nPos
, aTokenValue
, nLen
);
1403 skip_char(rCandidate
, ',', ' ', nPos
, nLen
);
1404 const OUString aString
= aTokenValue
.makeStringAndClear();
1406 if(!aString
.isEmpty())
1408 rSvgStringVector
.push_back(aString
);
1413 return !rSvgStringVector
.empty();
1416 void readImageLink(const OUString
& rCandidate
, OUString
& rXLink
, OUString
& rUrl
, OUString
& rMimeType
, OUString
& rData
)
1423 if('#' == rCandidate
[0])
1426 rXLink
= rCandidate
.copy(1);
1430 static const char aStrData
[] = "data:";
1432 if(rCandidate
.match(aStrData
, 0))
1435 sal_Int32
nPos(strlen(aStrData
));
1436 sal_Int32
nLen(rCandidate
.getLength());
1437 OUStringBuffer aBuffer
;
1440 skip_char(rCandidate
, ' ', nPos
, nLen
);
1441 copyToLimiter(rCandidate
, ';', nPos
, aBuffer
, nLen
);
1442 skip_char(rCandidate
, ' ', ';', nPos
, nLen
);
1443 rMimeType
= aBuffer
.makeStringAndClear();
1445 if(!rMimeType
.isEmpty() && nPos
< nLen
)
1447 static const char aStrImage
[] = "image";
1449 if(rMimeType
.match(aStrImage
, 0))
1452 OUString
aData(rCandidate
.copy(nPos
));
1453 static const char aStrBase64
[] = "base64";
1455 if(aData
.match(aStrBase64
, 0))
1458 nPos
= strlen(aStrBase64
);
1459 nLen
= aData
.getLength();
1461 skip_char(aData
, ' ', ',', nPos
, nLen
);
1465 rData
= aData
.copy(nPos
);
1473 // Url (path and filename)
1479 OUString
convert(const OUString
& rCandidate
, const sal_Unicode
& rPattern
, const sal_Unicode
& rNew
, bool bRemove
)
1481 const sal_Int32
nLen(rCandidate
.getLength());
1486 OUStringBuffer aBuffer
;
1487 bool bChanged(false);
1491 const sal_Unicode
aChar(rCandidate
[nPos
]);
1493 if(rPattern
== aChar
)
1499 aBuffer
.append(rNew
);
1504 aBuffer
.append(aChar
);
1512 return aBuffer
.makeStringAndClear();
1520 OUString
removeBlockComments(const OUString
& rCandidate
)
1522 const sal_Int32
nLen(rCandidate
.getLength());
1527 OUStringBuffer aBuffer
;
1528 bool bChanged(false);
1529 sal_Int32
nInsideComment(0);
1530 const sal_Unicode
aCommentSlash('/');
1531 const sal_Unicode
aCommentStar('*');
1535 const sal_Unicode
aChar(rCandidate
[nPos
]);
1536 const bool bStart(aCommentSlash
== aChar
&& nPos
+ 1 < nLen
&& aCommentStar
== rCandidate
[nPos
+ 1]);
1537 const bool bEnd(aCommentStar
== aChar
&& nPos
+ 1 < nLen
&& aCommentSlash
== rCandidate
[nPos
+ 1]);
1554 aBuffer
.append(aChar
);
1563 return aBuffer
.makeStringAndClear();
1570 OUString
consolidateContiguosSpace(const OUString
& rCandidate
)
1572 const sal_Int32
nLen(rCandidate
.getLength());
1577 OUStringBuffer aBuffer
;
1578 bool bInsideSpace(false);
1579 const sal_Unicode
aSpace(' ');
1583 const sal_Unicode
aChar(rCandidate
[nPos
]);
1587 bInsideSpace
= true;
1593 bInsideSpace
= false;
1594 aBuffer
.append(aSpace
);
1597 aBuffer
.append(aChar
);
1605 aBuffer
.append(aSpace
);
1608 if(aBuffer
.getLength() != nLen
)
1610 return aBuffer
.makeStringAndClear();
1617 OUString
whiteSpaceHandlingDefault(const OUString
& rCandidate
)
1619 const sal_Unicode
aNewline('\n');
1620 const sal_Unicode
aTab('\t');
1621 const sal_Unicode
aSpace(' ');
1623 // remove all newline characters
1624 OUString
aRetval(convert(rCandidate
, aNewline
, aNewline
, true));
1626 // convert tab to space
1627 aRetval
= convert(aRetval
, aTab
, aSpace
, false);
1629 // strip of all leading and trailing spaces
1630 aRetval
= aRetval
.trim();
1632 // consolidate contiguos space
1633 aRetval
= consolidateContiguosSpace(aRetval
);
1638 OUString
whiteSpaceHandlingPreserve(const OUString
& rCandidate
)
1640 const sal_Unicode
aNewline('\n');
1641 const sal_Unicode
aTab('\t');
1642 const sal_Unicode
aSpace(' ');
1644 // convert newline to space
1645 OUString
aRetval(convert(rCandidate
, aNewline
, aSpace
, false));
1647 // convert tab to space
1648 aRetval
= convert(rCandidate
, aTab
, aSpace
, false);
1653 ::std::vector
< double > solveSvgNumberVector(const SvgNumberVector
& rInput
, const InfoProvider
& rInfoProvider
, NumberType aNumberType
)
1655 ::std::vector
< double > aRetval
;
1659 const double nCount(rInput
.size());
1660 aRetval
.reserve(nCount
);
1662 for(sal_uInt32
a(0); a
< nCount
; a
++)
1664 aRetval
.push_back(rInput
[a
].solve(rInfoProvider
, aNumberType
));
1671 } // end of namespace svgreader
1672 } // end of namespace svgio
1674 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */