Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License. You may obtain a copy of the License at
8 : : * http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * The Initial Developer of the Original Code is
16 : : * Fridrich Strba <fridrich.strba@bluewin.ch>
17 : : * Thorsten Behrens <tbehrens@novell.com>
18 : : *
19 : : * Contributor(s):
20 : : *
21 : : * Alternatively, the contents of this file may be used under the terms of
22 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
23 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
24 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
25 : : * instead of those above.
26 : : */
27 : :
28 : : #include "parserfragments.hxx"
29 : : #include "spirit_supplements.hxx"
30 : : #include "gfxtypes.hxx"
31 : :
32 : : #include <basegfx/tools/canvastools.hxx>
33 : : #include <com/sun/star/geometry/AffineMatrix2D.hpp>
34 : :
35 : : #include <string.h>
36 : : #include <limits.h>
37 : : #include <boost/bind.hpp>
38 : : #include <boost/spirit/include/classic.hpp>
39 : : #include <boost/spirit/include/classic_while.hpp>
40 : : #include <numeric>
41 : : #include <algorithm>
42 : :
43 : : #include "units.hxx"
44 : : #include "tokenmap.hxx"
45 : : #include "sal/log.hxx"
46 : :
47 : : using namespace ::com::sun::star;
48 : :
49 : : namespace svgi
50 : : {
51 : :
52 : 0 : inline sal_uInt8 hex2int( char val )
53 : : {
54 [ # # ][ # # ]: 0 : return val <= '9' ? val-'0' : (val < 'a' ? val+10-'A' : val+10-'a');
55 : : }
56 : :
57 : 0 : void setFourBitColor( double& rChannel, char nChar )
58 : : {
59 : 0 : const sal_uInt8 nVal(hex2int(nChar));
60 : : OSL_TRACE( "setFourBitCOlor %d color", nVal );
61 : 0 : rChannel = (nVal*16+nVal)/255.0;
62 : 0 : }
63 : :
64 : 0 : void setEightBitColor( double& rChannel, const char* pStart, const char* )
65 : : {
66 : 0 : const sal_uInt8 nVal0(hex2int(pStart[0]));
67 : 0 : const sal_uInt8 nVal1(hex2int(pStart[1]));
68 : : OSL_TRACE( "setEightbitCOlor %d, %d color", nVal0, nVal1 );
69 : 0 : rChannel = (nVal0*16+nVal1)/255.0;
70 : 0 : }
71 : :
72 : 0 : void setIntColor( double& rChannel, sal_uInt8 nVal )
73 : : {
74 : : OSL_TRACE( "setIntColor %d color", nVal );
75 : 0 : rChannel = nVal/255.0;
76 : 0 : }
77 : :
78 : 0 : void setPercentColor( double& rChannel, double nVal )
79 : : {
80 : 0 : rChannel = nVal/100.0;
81 : : SAL_INFO("svg", "setPercentColor " << nVal << " " << rChannel);
82 : 0 : }
83 : :
84 : 0 : void calcRotation(std::vector<geometry::AffineMatrix2D>& rTransforms,
85 : : geometry::AffineMatrix2D& rCurrTransform,
86 : : double fRotationAngle)
87 : : {
88 [ # # ]: 0 : ::basegfx::B2DHomMatrix aCurr;
89 [ # # ]: 0 : aCurr.translate(-rCurrTransform.m02,-rCurrTransform.m12);
90 [ # # ]: 0 : aCurr.rotate(fRotationAngle*M_PI/180);
91 [ # # ]: 0 : aCurr.translate(rCurrTransform.m02,rCurrTransform.m12);
92 : :
93 : : OSL_TRACE("calcRotation - fRotationAngle - %f", fRotationAngle);
94 : : rTransforms.push_back(
95 : : basegfx::unotools::affineMatrixFromHomMatrix(
96 : : rCurrTransform,
97 [ # # ][ # # ]: 0 : aCurr));
[ # # ]
98 : 0 : }
99 : :
100 : 0 : void calcSkewX(std::vector<geometry::AffineMatrix2D>& rTransforms,
101 : : double fSkewAngle)
102 : : {
103 : 0 : geometry::AffineMatrix2D aMat(1.0,tan(fSkewAngle*M_PI/180),0.0,
104 : 0 : 0.0,1.0,0.0);
105 [ # # ]: 0 : rTransforms.push_back(aMat);
106 : 0 : }
107 : :
108 : 0 : void calcSkewY(std::vector<geometry::AffineMatrix2D>& rTransforms,
109 : : double fSkewAngle)
110 : : {
111 : : geometry::AffineMatrix2D aMat(1.0,0.0,0.0,
112 : 0 : tan(fSkewAngle*M_PI/180),1.0,0.0);
113 [ # # ]: 0 : rTransforms.push_back(aMat);
114 : 0 : }
115 : :
116 : 0 : void assign_twice(double& r_oVal1, double& r_oVal2, const double& rInVal )
117 : : {
118 : 0 : r_oVal1 = r_oVal2 = rInVal;
119 : 0 : }
120 : :
121 : 0 : geometry::AffineMatrix2D multiplyMatrix( const geometry::AffineMatrix2D& rLHS,
122 : : const geometry::AffineMatrix2D& rRHS )
123 : : {
124 [ # # ]: 0 : basegfx::B2DHomMatrix aLHS;
125 [ # # ]: 0 : basegfx::B2DHomMatrix aRHS;
126 : :
127 [ # # ]: 0 : basegfx::unotools::homMatrixFromAffineMatrix(aLHS,rLHS);
128 [ # # ]: 0 : basegfx::unotools::homMatrixFromAffineMatrix(aRHS,rRHS);
129 : :
130 [ # # ]: 0 : aRHS*=aLHS;
131 : :
132 : 0 : geometry::AffineMatrix2D aRet;
133 [ # # ][ # # ]: 0 : return basegfx::unotools::affineMatrixFromHomMatrix(aRet,aRHS);
[ # # ]
134 : : }
135 : :
136 : : namespace
137 : : {
138 : 0 : struct ColorGrammar : public ::boost::spirit::classic::grammar< ColorGrammar >
139 : : {
140 : : public:
141 : : ARGBColor& m_rColor;
142 : 0 : explicit ColorGrammar( ARGBColor& rColor ) : m_rColor(rColor) {}
143 : : template< typename ScannerT >
144 : 0 : struct definition
145 : : {
146 : : ::boost::spirit::classic::rule< ScannerT > colorExpression;
147 : 0 : definition( const ColorGrammar& self )
148 : 0 : {
149 : : using namespace ::boost::spirit::classic;
150 : :
151 : : int_parser<sal_uInt8,10,1,3> byte_p;
152 [ # # ][ # # ]: 0 : colorExpression =
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
153 : : (
154 : : // the #rrggbb form
155 : : ('#' >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
156 : : boost::ref(self.m_rColor.r),_1,_2)]
157 : : >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
158 : : boost::ref(self.m_rColor.g),_1,_2)]
159 : : >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
160 : : boost::ref(self.m_rColor.b),_1,_2)])
161 : : |
162 : : // the #rgb form
163 : : ('#' >> xdigit_p[boost::bind(&setFourBitColor,
164 : : boost::ref(self.m_rColor.r),_1)]
165 : : >> xdigit_p[boost::bind(&setFourBitColor,
166 : : boost::ref(self.m_rColor.g),_1)]
167 : : >> xdigit_p[boost::bind(&setFourBitColor,
168 : : boost::ref(self.m_rColor.b),_1)])
169 : : |
170 : : // rgb() form
171 : : (str_p("rgb")
172 : : >> '(' >>
173 : : (
174 : : // rgb(int,int,int)
175 : : (byte_p[boost::bind(&setIntColor,
176 : : boost::ref(self.m_rColor.r),_1)] >> ',' >>
177 : : byte_p[boost::bind(&setIntColor,
178 : : boost::ref(self.m_rColor.g),_1)] >> ',' >>
179 : : byte_p[boost::bind(&setIntColor,
180 : : boost::ref(self.m_rColor.b),_1)])
181 : : |
182 : : // rgb(double,double,double)
183 : : (real_p[assign_a(self.m_rColor.r)] >> ',' >>
184 : : real_p[assign_a(self.m_rColor.g)] >> ',' >>
185 : : real_p[assign_a(self.m_rColor.b)])
186 : : |
187 : : // rgb(percent,percent,percent)
188 : : (real_p[boost::bind(&setPercentColor,
189 : : boost::ref(self.m_rColor.r),_1)] >> "%," >>
190 : : real_p[boost::bind(&setPercentColor,
191 : : boost::ref(self.m_rColor.g),_1)] >> "%," >>
192 : : real_p[boost::bind(&setPercentColor,
193 : : boost::ref(self.m_rColor.b),_1)] >> "%")
194 : : )
195 : : >> ')')
196 : : );
197 : 0 : }
198 : 0 : ::boost::spirit::classic::rule<ScannerT> const& start() const { return colorExpression; }
199 : : };
200 : : };
201 : : }
202 : :
203 : 0 : bool parseColor( const char* sColor, ARGBColor& rColor )
204 : : {
205 : : using namespace ::boost::spirit::classic;
206 : :
207 [ # # # # ]: 0 : if( parse(sColor,
208 : 0 : ColorGrammar(rColor) >> end_p,
209 [ # # ]: 0 : space_p).full )
210 : : {
211 : : // free-form color found & parsed
212 : 0 : return true;
213 : : }
214 : :
215 : : // no free-form color - maybe a color name?
216 : : // trim white space before
217 [ # # ][ # # ]: 0 : while( *sColor &&
[ # # ][ # # ]
[ # # ][ # # ]
218 : : (*sColor==' ' || *sColor=='\t' || *sColor=='\r' || *sColor=='\n') )
219 : 0 : ++sColor;
220 : : // trim white space after
221 : 0 : int nLen=strlen(sColor)-1;
222 [ # # ][ # # ]: 0 : while( nLen &&
[ # # ][ # # ]
[ # # ][ # # ]
223 : 0 : (sColor[nLen]==' ' || sColor[nLen]=='\t' || sColor[nLen]=='\r' || sColor[nLen]=='\n') )
224 : 0 : --nLen;
225 [ # # # # : 0 : switch (getTokenId(sColor, nLen+1))
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
226 : : {
227 : 0 : case XML_ALICEBLUE: rColor = ARGBColor(240,248,255); return true;
228 : 0 : case XML_ANTIQUEWHITE: rColor = ARGBColor(250,235,215); return true;
229 : 0 : case XML_AQUA: rColor = ARGBColor(0,255,255); return true;
230 : 0 : case XML_AQUAMARINE: rColor = ARGBColor(127,255,212); return true;
231 : 0 : case XML_AZURE: rColor = ARGBColor(240,255,255); return true;
232 : 0 : case XML_BEIGE: rColor = ARGBColor(245,245,220); return true;
233 : 0 : case XML_BISQUE: rColor = ARGBColor(255,228,196); return true;
234 : 0 : case XML_BLACK: rColor = ARGBColor(0,0,0); return true;
235 : 0 : case XML_BLANCHEDALMOND: rColor = ARGBColor(255,235,205); return true;
236 : 0 : case XML_BLUE: rColor = ARGBColor(0,0,255); return true;
237 : 0 : case XML_BLUEVIOLET: rColor = ARGBColor(138,43,226); return true;
238 : 0 : case XML_BROWN: rColor = ARGBColor(165,42,42); return true;
239 : 0 : case XML_BURLYWOOD: rColor = ARGBColor(222,184,135); return true;
240 : 0 : case XML_CADETBLUE: rColor = ARGBColor(95,158,160); return true;
241 : 0 : case XML_CHARTREUSE: rColor = ARGBColor(127,255,0); return true;
242 : 0 : case XML_CHOCOLATE: rColor = ARGBColor(210,105,30); return true;
243 : 0 : case XML_CORAL: rColor = ARGBColor(255,127,80); return true;
244 : 0 : case XML_CORNFLOWERBLUE: rColor = ARGBColor(100,149,237); return true;
245 : 0 : case XML_CORNSILK: rColor = ARGBColor(255,248,220); return true;
246 : 0 : case XML_CRIMSON: rColor = ARGBColor(220,20,60); return true;
247 : 0 : case XML_CYAN: rColor = ARGBColor(0,255,255); return true;
248 : 0 : case XML_DARKBLUE: rColor = ARGBColor(0,0,139); return true;
249 : 0 : case XML_DARKCYAN: rColor = ARGBColor(0,139,139); return true;
250 : 0 : case XML_DARKGOLDENROD: rColor = ARGBColor(184,134,11); return true;
251 : 0 : case XML_DARKGRAY: rColor = ARGBColor(169,169,169); return true;
252 : 0 : case XML_DARKGREEN: rColor = ARGBColor(0,100,0); return true;
253 : 0 : case XML_DARKGREY: rColor = ARGBColor(169,169,169); return true;
254 : 0 : case XML_DARKKHAKI: rColor = ARGBColor(189,183,107); return true;
255 : 0 : case XML_DARKMAGENTA: rColor = ARGBColor(139,0,139); return true;
256 : 0 : case XML_DARKOLIVEGREEN: rColor = ARGBColor(85,107,47); return true;
257 : 0 : case XML_DARKORANGE: rColor = ARGBColor(255,140,0); return true;
258 : 0 : case XML_DARKORCHID: rColor = ARGBColor(153,50,204); return true;
259 : 0 : case XML_DARKRED: rColor = ARGBColor(139,0,0); return true;
260 : 0 : case XML_DARKSALMON: rColor = ARGBColor(233,150,122); return true;
261 : 0 : case XML_DARKSEAGREEN: rColor = ARGBColor(143,188,143); return true;
262 : 0 : case XML_DARKSLATEBLUE: rColor = ARGBColor(72,61,139); return true;
263 : 0 : case XML_DARKSLATEGRAY: rColor = ARGBColor(47,79,79); return true;
264 : 0 : case XML_DARKSLATEGREY: rColor = ARGBColor(47,79,79); return true;
265 : 0 : case XML_DARKTURQUOISE: rColor = ARGBColor(0,206,209); return true;
266 : 0 : case XML_DARKVIOLET: rColor = ARGBColor(148,0,211); return true;
267 : 0 : case XML_DEEPPINK: rColor = ARGBColor(255,20,147); return true;
268 : 0 : case XML_DEEPSKYBLUE: rColor = ARGBColor(0,191,255); return true;
269 : 0 : case XML_DIMGRAY: rColor = ARGBColor(105,105,105); return true;
270 : 0 : case XML_DIMGREY: rColor = ARGBColor(105,105,105); return true;
271 : 0 : case XML_DODGERBLUE: rColor = ARGBColor(30,144,255); return true;
272 : 0 : case XML_FIREBRICK: rColor = ARGBColor(178,34,34); return true;
273 : 0 : case XML_FLORALWHITE: rColor = ARGBColor(255,250,240); return true;
274 : 0 : case XML_FORESTGREEN: rColor = ARGBColor(34,139,34); return true;
275 : 0 : case XML_FUCHSIA: rColor = ARGBColor(255,0,255); return true;
276 : 0 : case XML_GAINSBORO: rColor = ARGBColor(220,220,220); return true;
277 : 0 : case XML_GHOSTWHITE: rColor = ARGBColor(248,248,255); return true;
278 : 0 : case XML_GOLD: rColor = ARGBColor(255,215,0); return true;
279 : 0 : case XML_GOLDENROD: rColor = ARGBColor(218,165,32); return true;
280 : 0 : case XML_GRAY: rColor = ARGBColor(128,128,128); return true;
281 : 0 : case XML_GREY: rColor = ARGBColor(128,128,128); return true;
282 : 0 : case XML_GREEN: rColor = ARGBColor(0,128,0); return true;
283 : 0 : case XML_GREENYELLOW: rColor = ARGBColor(173,255,47); return true;
284 : 0 : case XML_HONEYDEW: rColor = ARGBColor(240,255,240); return true;
285 : 0 : case XML_HOTPINK: rColor = ARGBColor(255,105,180); return true;
286 : 0 : case XML_INDIANRED: rColor = ARGBColor(205,92,92); return true;
287 : 0 : case XML_INDIGO: rColor = ARGBColor(75,0,130); return true;
288 : 0 : case XML_IVORY: rColor = ARGBColor(255,255,240); return true;
289 : 0 : case XML_KHAKI: rColor = ARGBColor(240,230,140); return true;
290 : 0 : case XML_LAVENDER: rColor = ARGBColor(230,230,250); return true;
291 : 0 : case XML_LAVENDERBLUSH: rColor = ARGBColor(255,240,245); return true;
292 : 0 : case XML_LAWNGREEN: rColor = ARGBColor(124,252,0); return true;
293 : 0 : case XML_LEMONCHIFFON: rColor = ARGBColor(255,250,205); return true;
294 : 0 : case XML_LIGHTBLUE: rColor = ARGBColor(173,216,230); return true;
295 : 0 : case XML_LIGHTCORAL: rColor = ARGBColor(240,128,128); return true;
296 : 0 : case XML_LIGHTCYAN: rColor = ARGBColor(224,255,255); return true;
297 : 0 : case XML_LIGHTGOLDENRODYELLOW: rColor = ARGBColor(250,250,210); return true;
298 : 0 : case XML_LIGHTGRAY: rColor = ARGBColor(211,211,211); return true;
299 : 0 : case XML_LIGHTGREEN: rColor = ARGBColor(144,238,144); return true;
300 : 0 : case XML_LIGHTGREY: rColor = ARGBColor(211,211,211); return true;
301 : 0 : case XML_LIGHTPINK: rColor = ARGBColor(255,182,193); return true;
302 : 0 : case XML_LIGHTSALMON: rColor = ARGBColor(255,160,122); return true;
303 : 0 : case XML_LIGHTSEAGREEN: rColor = ARGBColor(32,178,170); return true;
304 : 0 : case XML_LIGHTSKYBLUE: rColor = ARGBColor(135,206,250); return true;
305 : 0 : case XML_LIGHTSLATEGRAY: rColor = ARGBColor(119,136,153); return true;
306 : 0 : case XML_LIGHTSLATEGREY: rColor = ARGBColor(119,136,153); return true;
307 : 0 : case XML_LIGHTSTEELBLUE: rColor = ARGBColor(176,196,222); return true;
308 : 0 : case XML_LIGHTYELLOW: rColor = ARGBColor(255,255,224); return true;
309 : 0 : case XML_LIME: rColor = ARGBColor(0,255,0); return true;
310 : 0 : case XML_LIMEGREEN: rColor = ARGBColor(50,205,50); return true;
311 : 0 : case XML_LINEN: rColor = ARGBColor(250,240,230); return true;
312 : 0 : case XML_MAGENTA: rColor = ARGBColor(255,0,255); return true;
313 : 0 : case XML_MAROON: rColor = ARGBColor(128,0,0); return true;
314 : 0 : case XML_MEDIUMAQUAMARINE: rColor = ARGBColor(102,205,170); return true;
315 : 0 : case XML_MEDIUMBLUE: rColor = ARGBColor(0,0,205); return true;
316 : 0 : case XML_MEDIUMORCHID: rColor = ARGBColor(186,85,211); return true;
317 : 0 : case XML_MEDIUMPURPLE: rColor = ARGBColor(147,112,219); return true;
318 : 0 : case XML_MEDIUMSEAGREEN: rColor = ARGBColor(60,179,113); return true;
319 : 0 : case XML_MEDIUMSLATEBLUE: rColor = ARGBColor(123,104,238); return true;
320 : 0 : case XML_MEDIUMSPRINGGREEN: rColor = ARGBColor(0,250,154); return true;
321 : 0 : case XML_MEDIUMTURQUOISE: rColor = ARGBColor(72,209,204); return true;
322 : 0 : case XML_MEDIUMVIOLETRED: rColor = ARGBColor(199,21,133); return true;
323 : 0 : case XML_MIDNIGHTBLUE: rColor = ARGBColor(25,25,112); return true;
324 : 0 : case XML_MINTCREAM: rColor = ARGBColor(245,255,250); return true;
325 : 0 : case XML_MISTYROSE: rColor = ARGBColor(255,228,225); return true;
326 : 0 : case XML_MOCCASIN: rColor = ARGBColor(255,228,181); return true;
327 : 0 : case XML_NAVAJOWHITE: rColor = ARGBColor(255,222,173); return true;
328 : 0 : case XML_NAVY: rColor = ARGBColor(0,0,128); return true;
329 : 0 : case XML_OLDLACE: rColor = ARGBColor(253,245,230); return true;
330 : 0 : case XML_OLIVE: rColor = ARGBColor(128,128,0); return true;
331 : 0 : case XML_OLIVEDRAB: rColor = ARGBColor(107,142,35); return true;
332 : 0 : case XML_ORANGE: rColor = ARGBColor(255,165,0); return true;
333 : 0 : case XML_ORANGERED: rColor = ARGBColor(255,69,0); return true;
334 : 0 : case XML_ORCHID: rColor = ARGBColor(218,112,214); return true;
335 : 0 : case XML_PALEGOLDENROD: rColor = ARGBColor(238,232,170); return true;
336 : 0 : case XML_PALEGREEN: rColor = ARGBColor(152,251,152); return true;
337 : 0 : case XML_PALETURQUOISE: rColor = ARGBColor(175,238,238); return true;
338 : 0 : case XML_PALEVIOLETRED: rColor = ARGBColor(219,112,147); return true;
339 : 0 : case XML_PAPAYAWHIP: rColor = ARGBColor(255,239,213); return true;
340 : 0 : case XML_PEACHPUFF: rColor = ARGBColor(255,218,185); return true;
341 : 0 : case XML_PERU: rColor = ARGBColor(205,133,63); return true;
342 : 0 : case XML_PINK: rColor = ARGBColor(255,192,203); return true;
343 : 0 : case XML_PLUM: rColor = ARGBColor(221,160,221); return true;
344 : 0 : case XML_POWDERBLUE: rColor = ARGBColor(176,224,230); return true;
345 : 0 : case XML_PURPLE: rColor = ARGBColor(128,0,128); return true;
346 : 0 : case XML_RED: rColor = ARGBColor(255,0,0); return true;
347 : 0 : case XML_ROSYBROWN: rColor = ARGBColor(188,143,143); return true;
348 : 0 : case XML_ROYALBLUE: rColor = ARGBColor(65,105,225); return true;
349 : 0 : case XML_SADDLEBROWN: rColor = ARGBColor(139,69,19); return true;
350 : 0 : case XML_SALMON: rColor = ARGBColor(250,128,114); return true;
351 : 0 : case XML_SANDYBROWN: rColor = ARGBColor(244,164,96); return true;
352 : 0 : case XML_SEAGREEN: rColor = ARGBColor(46,139,87); return true;
353 : 0 : case XML_SEASHELL: rColor = ARGBColor(255,245,238); return true;
354 : 0 : case XML_SIENNA: rColor = ARGBColor(160,82,45); return true;
355 : 0 : case XML_SILVER: rColor = ARGBColor(192,192,192); return true;
356 : 0 : case XML_SKYBLUE: rColor = ARGBColor(135,206,235); return true;
357 : 0 : case XML_SLATEBLUE: rColor = ARGBColor(106,90,205); return true;
358 : 0 : case XML_SLATEGRAY: rColor = ARGBColor(112,128,144); return true;
359 : 0 : case XML_SLATEGREY: rColor = ARGBColor(112,128,144); return true;
360 : 0 : case XML_SNOW: rColor = ARGBColor(255,250,250); return true;
361 : 0 : case XML_SPRINGGREEN: rColor = ARGBColor(0,255,127); return true;
362 : 0 : case XML_STEELBLUE: rColor = ARGBColor(70,130,180); return true;
363 : 0 : case XML_TAN: rColor = ARGBColor(210,180,140); return true;
364 : 0 : case XML_TEAL: rColor = ARGBColor(0,128,128); return true;
365 : 0 : case XML_THISTLE: rColor = ARGBColor(216,191,216); return true;
366 : 0 : case XML_TOMATO: rColor = ARGBColor(255,99,71); return true;
367 : 0 : case XML_TURQUOISE: rColor = ARGBColor(64,224,208); return true;
368 : 0 : case XML_VIOLET: rColor = ARGBColor(238,130,238); return true;
369 : 0 : case XML_WHEAT: rColor = ARGBColor(245,222,179); return true;
370 : 0 : case XML_WHITE: rColor = ARGBColor(255,255,255); return true;
371 : 0 : case XML_WHITESMOKE: rColor = ARGBColor(245,245,245); return true;
372 : 0 : case XML_YELLOW: rColor = ARGBColor(255,255,0); return true;
373 : 0 : case XML_YELLOWGREEN: rColor = ARGBColor(154,205,50); return true;
374 : :
375 : : default:
376 : 0 : return false; // no color at all, I'd guess.
377 : : }
378 : : }
379 : :
380 : 0 : bool parseOpacity (const char* sOpacity, ARGBColor& rColor )
381 : : {
382 : : using namespace ::boost::spirit::classic;
383 : :
384 [ # # ][ # # ]: 0 : if( parse(sOpacity,
385 : : // Begin grammar
386 : : (
387 : 0 : real_p[assign_a(rColor.a)]
388 [ # # ]: 0 : ) >> end_p,
389 : : // End grammar
390 [ # # ]: 0 : space_p).full )
391 : : {
392 : 0 : return true;
393 : : }
394 : 0 : return false;
395 : : }
396 : :
397 : : //////////////////////////////////////////////////////////////
398 : :
399 : 0 : bool parseTransform( const char* sTransform, basegfx::B2DHomMatrix& rTransform )
400 : : {
401 : : using namespace ::boost::spirit::classic;
402 : :
403 : 0 : double fRefOffsetX(0.0);
404 : 0 : double fRefOffsetY(0.0);
405 : 0 : bool bRefTransform(false);
406 : :
407 : 0 : double fRotationAngle=0.0;
408 : 0 : double fSkewAngle=0.0;
409 : 0 : geometry::AffineMatrix2D aIdentityTransform;
410 : 0 : geometry::AffineMatrix2D aCurrTransform;
411 [ # # ]: 0 : std::vector<geometry::AffineMatrix2D> aTransforms;
412 : 0 : aIdentityTransform.m00 = 1.0; aIdentityTransform.m11 = 1.0;
413 : 0 : aCurrTransform = aIdentityTransform;
414 : :
415 : : const bool bRes = parse(sTransform,
416 : : // Begin grammar
417 : : (
418 : : // identity transform
419 : : str_p("none")
420 : : |
421 : : // the ref() form
422 : : (str_p("ref")
423 [ # # ]: 0 : >> '('
424 [ # # ][ # # ]: 0 : >> str_p("svg")[assign_a(bRefTransform,true)]
[ # # ][ # # ]
425 [ # # ][ # # ]: 0 : >> !(real_p[assign_a(fRefOffsetX)] >> (',' | eps_p) >>
[ # # ]
426 [ # # ][ # # ]: 0 : real_p[assign_a(fRefOffsetY)])
[ # # ][ # # ]
[ # # ][ # # ]
427 [ # # ][ # # ]: 0 : >> ')')
[ # # ]
428 : : |
429 : : // the transform-list form
430 : : (list_p(
431 : : (
432 : : // matrix(a,b,c,d,e,f)
433 : : (str_p("matrix")
434 [ # # ]: 0 : >> '('
435 [ # # ][ # # ]: 0 : >> real_p[assign_a(aCurrTransform.m00)] >> (',' | eps_p)
[ # # ][ # # ]
[ # # ]
436 [ # # ][ # # ]: 0 : >> real_p[assign_a(aCurrTransform.m10)] >> (',' | eps_p)
[ # # ][ # # ]
[ # # ]
437 [ # # ][ # # ]: 0 : >> real_p[assign_a(aCurrTransform.m01)] >> (',' | eps_p)
[ # # ][ # # ]
[ # # ]
438 [ # # ][ # # ]: 0 : >> real_p[assign_a(aCurrTransform.m11)] >> (',' | eps_p)
[ # # ][ # # ]
[ # # ]
439 [ # # ][ # # ]: 0 : >> real_p[assign_a(aCurrTransform.m02)] >> (',' | eps_p)
[ # # ][ # # ]
[ # # ]
440 [ # # ][ # # ]: 0 : >> real_p[assign_a(aCurrTransform.m12)]
[ # # ]
441 [ # # ][ # # ]: 0 : >> ')')[push_back_a(aTransforms,aCurrTransform)]
[ # # ]
442 : : |
443 : : // translate(x,[y])
444 : : (str_p("translate")
445 [ # # ]: 0 : >> '('
446 : : >> real_p[boost::bind(&assign_twice,
447 : : boost::ref(aCurrTransform.m02),
448 [ # # ][ # # ]: 0 : boost::ref(aCurrTransform.m12),_1)]
[ # # ][ # # ]
[ # # ]
449 [ # # ][ # # ]: 0 : >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m12)])
[ # # ][ # # ]
[ # # ][ # # ]
450 [ # # ][ # # ]: 0 : >> ')')[push_back_a(aTransforms,aCurrTransform)]
[ # # ][ # # ]
[ # # ]
451 : : |
452 : : // scale(x,[y])
453 : : (str_p("scale")
454 [ # # ]: 0 : >> '('
455 : : >> real_p[boost::bind(&assign_twice,
456 : : boost::ref(aCurrTransform.m00),
457 [ # # ][ # # ]: 0 : boost::ref(aCurrTransform.m11),_1)]
[ # # ][ # # ]
[ # # ]
458 [ # # ][ # # ]: 0 : >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m11)])
[ # # ][ # # ]
[ # # ][ # # ]
459 [ # # ][ # # ]: 0 : >> ')')[push_back_a(aTransforms,aCurrTransform)]
[ # # ][ # # ]
[ # # ]
460 : : |
461 : : // rotate(phi,[cx, cy])
462 : : (str_p("rotate")
463 [ # # ]: 0 : >> '('
464 [ # # ][ # # ]: 0 : >> real_p[assign_a(fRotationAngle)]
[ # # ]
465 [ # # ][ # # ]: 0 : >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m02)]
[ # # ]
466 [ # # ][ # # ]: 0 : >> real_p[assign_a(aCurrTransform.m12)])
[ # # ][ # # ]
[ # # ][ # # ]
467 [ # # ]: 0 : >> ')')[boost::bind(&calcRotation,
468 : : boost::ref(aTransforms),
469 : : boost::ref(aCurrTransform),
470 [ # # ][ # # ]: 0 : boost::cref(fRotationAngle))]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
471 : : |
472 : : // skewX(phi)
473 : : (str_p("skewX")
474 [ # # ]: 0 : >> '('
475 [ # # ][ # # ]: 0 : >> real_p[assign_a(fSkewAngle)]
[ # # ]
476 [ # # ]: 0 : >> ')')[boost::bind(&calcSkewX,
477 : : boost::ref(aTransforms),
478 [ # # ][ # # ]: 0 : boost::cref(fSkewAngle))]
[ # # ][ # # ]
[ # # ][ # # ]
479 : : |
480 : : // skewY(phi)
481 : : (str_p("skewY")
482 [ # # ]: 0 : >> '('
483 [ # # ][ # # ]: 0 : >> real_p[assign_a(fSkewAngle)]
[ # # ]
484 [ # # ]: 0 : >> ')')[boost::bind(&calcSkewY,
485 : : boost::ref(aTransforms),
486 [ # # ][ # # ]: 0 : boost::cref(fSkewAngle))]
[ # # ][ # # ]
[ # # ][ # # ]
487 : : // reset current transform after every push
488 [ # # ][ # # ]: 0 : )[assign_a(aCurrTransform,aIdentityTransform)],
489 : : // list delimiter is either ',' or space
490 [ # # ][ # # ]: 0 : ',' | eps_p ))
[ # # ][ # # ]
491 [ # # ]: 0 : ) >> end_p,
492 : : // End grammar
493 [ # # ][ # # ]: 0 : space_p).full;
494 : :
495 [ # # ]: 0 : if( !bRes )
496 : 0 : return false;
497 : :
498 : : // fold all transformations into one
499 : : const geometry::AffineMatrix2D aTotalTransform(
500 : : std::accumulate(aTransforms.begin(),
501 : : aTransforms.end(),
502 : : aIdentityTransform,
503 [ # # ]: 0 : &multiplyMatrix));
504 : :
505 : : basegfx::unotools::homMatrixFromAffineMatrix(
506 : : rTransform,
507 [ # # ]: 0 : aTotalTransform);
508 : :
509 : : // TODO(F1): handle the ref case
510 : 0 : return bRes;
511 : : }
512 : :
513 : : //////////////////////////////////////////////////////////////
514 : :
515 : 0 : bool parseViewBox( const char* sViewbox, basegfx::B2DRange& rRect )
516 : : {
517 : : using namespace ::boost::spirit::classic;
518 : :
519 : 0 : double x=0.0,y=0.0,w=0.0,h=0.0;
520 : :
521 : : const bool bRes = parse(sViewbox,
522 : : // Begin grammar
523 : : (
524 : : // either comma- or space-delimited list of four doubles
525 [ # # ][ # # ]: 0 : real_p[assign_a(x)] >> (',' | eps_p) >>
[ # # ]
526 [ # # ][ # # ]: 0 : real_p[assign_a(y)] >> (',' | eps_p) >>
[ # # ][ # # ]
[ # # ]
527 [ # # ][ # # ]: 0 : real_p[assign_a(w)] >> (',' | eps_p) >>
[ # # ][ # # ]
[ # # ]
528 [ # # ][ # # ]: 0 : real_p[assign_a(h)] >> end_p
[ # # ][ # # ]
529 : : ),
530 : : // End grammar
531 [ # # ][ # # ]: 0 : space_p).full;
532 : :
533 [ # # ]: 0 : if( !bRes )
534 : 0 : return false;
535 : :
536 [ # # ]: 0 : rRect = basegfx::B2DRange(x,y,x+w,y+h);
537 : :
538 : 0 : return true;
539 : : }
540 : :
541 : : //////////////////////////////////////////////////////////////
542 : :
543 : 0 : bool parseDashArray( const char* sDashArray, std::vector<double>& rOutputVector )
544 : : {
545 : : using namespace ::boost::spirit::classic;
546 : :
547 : 0 : rOutputVector.clear();
548 : : return parse(sDashArray,
549 : : // Begin grammar
550 : : (
551 : : // parse comma-delimited list of doubles (have to use the
552 : : // 'direct' variant, as otherwise spirit refactors our
553 : : // parser to push both real num and comma to push_back_a)
554 : : list_p.direct
555 : : (
556 [ # # ]: 0 : real_p[push_back_a(rOutputVector)],
557 : : // list delimiter is either ',' or space
558 : : ',' | eps_p
559 [ # # ]: 0 : )
560 [ # # ]: 0 : ) >> end_p,
561 : : // End grammar
562 [ # # ][ # # ]: 0 : space_p).full;
563 : : }
564 : :
565 : : //////////////////////////////////////////////////////////////
566 : :
567 : 0 : bool parsePaintUri( std::pair<const char*,const char*>& o_rPaintUri,
568 : : std::pair<ARGBColor,bool>& io_rColor,
569 : : const char* sPaintUri )
570 : : {
571 : : using namespace ::boost::spirit::classic;
572 : :
573 : : const bool bRes = parse(sPaintUri,
574 : : // Begin grammar
575 : : (
576 [ # # ][ # # ]: 0 : str_p("url(") >> !( str_p("'") | str_p("\"") ) >> ("#") >>
[ # # ][ # # ]
[ # # ][ # # ]
577 [ # # ][ # # ]: 0 : (+alnum_p)[assign_a(o_rPaintUri)] >>
[ # # ][ # # ]
578 [ # # ][ # # ]: 0 : !( str_p("'") | str_p("\"") ) >> str_p(")") >>
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
579 [ # # ][ # # ]: 0 : *( str_p("none")[assign_a(io_rColor.second,false)] |
580 [ # # ][ # # ]: 0 : str_p("currentColor")[assign_a(io_rColor.second,true)] |
[ # # ][ # # ]
581 [ # # ]: 0 : ColorGrammar(io_rColor.first)
582 : : // TODO(F1): named color
583 [ # # ][ # # ]: 0 : )
[ # # ]
584 [ # # ]: 0 : ) >> end_p,
585 : : // End grammar
586 [ # # ][ # # ]: 0 : space_p).full;
587 : :
588 : 0 : return bRes;
589 : : }
590 : :
591 : : //////////////////////////////////////////////////////////////
592 : :
593 : 0 : bool parseXlinkHref( const char* sXlinkHref, std::string& data )
594 : : {
595 : : using namespace ::boost::spirit::classic;
596 : :
597 [ # # ]: 0 : data.erase(data.begin(),data.end());
598 : :
599 [ # # ]: 0 : std::string sLink(sXlinkHref);
600 : :
601 [ # # ][ # # ]: 0 : if (!sLink.compare(0,5,"data:"))
602 : : {
603 : : // the inplace "data" uri
604 : 0 : size_t position = sLink.rfind(',');
605 [ # # ][ # # ]: 0 : if (position > 0 && position < std::string::npos)
606 : : {
607 [ # # ][ # # ]: 0 : data = sLink.substr(position+1);
608 : : OSL_TRACE("%s", data.c_str());
609 : 0 : return true;
610 : : }
611 : : }
612 : :
613 : 0 : return false;
614 : : }
615 : :
616 [ + - ][ + - ]: 18 : } // namespace svgi
617 : :
618 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|