Update ooo320-m1
[ooovba.git] / filter / source / svg / parserfragments.cxx
blob4e2c1b8f4c554dff068645aedd1edaf6a87f4a21
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * Author:
6 * Fridrich Strba <fridrich.strba@bluewin.ch>
7 * Thorsten Behrens <tbehrens@novell.com>
9 * Copyright (C) 2008, Novell Inc.
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
14 ************************************************************************/
16 // MARKER(update_precomp.py): autogen include statement, do not remove
17 #include "precompiled_filter.hxx"
19 #include "parserfragments.hxx"
20 #include "spirit_supplements.hxx"
21 #include "gfxtypes.hxx"
23 #include <basegfx/tools/canvastools.hxx>
24 #include <com/sun/star/geometry/AffineMatrix2D.hpp>
26 #include <string.h>
27 #include <limits.h>
28 #include <boost/bind.hpp>
29 #include <boost/spirit.hpp>
30 #include <boost/spirit/dynamic/while.hpp>
31 #include <numeric>
32 #include <algorithm>
34 #include "units.hxx"
35 #include "tokenmap.hxx"
37 using namespace ::com::sun::star;
39 namespace svgi
42 inline sal_uInt8 hex2int( char val )
44 return val <= '9' ? val-'0' : (val < 'a' ? val+10-'A' : val+10-'a');
47 void setFourBitColor( double& rChannel, char nChar )
49 const sal_uInt8 nVal(hex2int(nChar));
50 OSL_TRACE( "setFourBitCOlor %d color", nVal );
51 rChannel = (nVal*16+nVal)/255.0;
54 void setEightBitColor( double& rChannel, const char* pStart, const char* )
56 const sal_uInt8 nVal0(hex2int(pStart[0]));
57 const sal_uInt8 nVal1(hex2int(pStart[1]));
58 OSL_TRACE( "setEightbitCOlor %d, %d color", nVal0, nVal1 );
59 rChannel = (nVal0*16+nVal1)/255.0;
62 void setIntColor( double& rChannel, sal_uInt8 nVal )
64 OSL_TRACE( "setIntColor %d color", nVal );
65 rChannel = nVal/255.0;
68 void calcRotation(std::vector<geometry::AffineMatrix2D>& rTransforms,
69 geometry::AffineMatrix2D& rCurrTransform,
70 double fRotationAngle)
72 ::basegfx::B2DHomMatrix aCurr;
73 aCurr.translate(-rCurrTransform.m02,-rCurrTransform.m12);
74 aCurr.rotate(fRotationAngle*M_PI/180);
75 aCurr.translate(rCurrTransform.m02,rCurrTransform.m12);
77 OSL_TRACE("calcRotation - fRotationAngle - %f", fRotationAngle);
78 rTransforms.push_back(
79 basegfx::unotools::affineMatrixFromHomMatrix(
80 rCurrTransform,
81 aCurr));
84 void calcSkewX(std::vector<geometry::AffineMatrix2D>& rTransforms,
85 double fSkewAngle)
87 geometry::AffineMatrix2D aMat(1.0,0.0,0.0,
88 tan(fSkewAngle*M_PI/180),1.0,0.0);
89 rTransforms.push_back(aMat);
92 void calcSkewY(std::vector<geometry::AffineMatrix2D>& rTransforms,
93 double fSkewAngle)
95 geometry::AffineMatrix2D aMat(1.0,tan(fSkewAngle*M_PI/180),0.0,
96 0.0,1.0,0.0);
97 rTransforms.push_back(aMat);
100 void assign_twice(double& r_oVal1, double& r_oVal2, const double& rInVal )
102 r_oVal1 = r_oVal2 = rInVal;
105 geometry::AffineMatrix2D multiplyMatrix( const geometry::AffineMatrix2D& rLHS,
106 const geometry::AffineMatrix2D& rRHS )
108 basegfx::B2DHomMatrix aLHS;
109 basegfx::B2DHomMatrix aRHS;
111 basegfx::unotools::homMatrixFromAffineMatrix(aLHS,rLHS);
112 basegfx::unotools::homMatrixFromAffineMatrix(aRHS,rRHS);
114 aRHS*=aLHS;
116 geometry::AffineMatrix2D aRet;
117 return basegfx::unotools::affineMatrixFromHomMatrix(aRet,aRHS);
120 namespace
122 struct ColorGrammar : public ::boost::spirit::grammar< ColorGrammar >
124 public:
125 ARGBColor& m_rColor;
126 explicit ColorGrammar( ARGBColor& rColor ) : m_rColor(rColor) {}
127 template< typename ScannerT >
128 struct definition
130 ::boost::spirit::rule< ScannerT > colorExpression;
131 definition( const ColorGrammar& self )
133 using namespace ::boost::spirit;
135 int_parser<sal_uInt8,10,1,3> byte_p;
136 colorExpression =
138 // the #rrggbb form
139 ('#' >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
140 boost::ref(self.m_rColor.r),_1,_2)]
141 >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
142 boost::ref(self.m_rColor.g),_1,_2)]
143 >> (xdigit_p >> xdigit_p)[boost::bind(&setEightBitColor,
144 boost::ref(self.m_rColor.b),_1,_2)])
146 // the #rgb form
147 ('#' >> xdigit_p[boost::bind(&setFourBitColor,
148 boost::ref(self.m_rColor.r),_1)]
149 >> xdigit_p[boost::bind(&setFourBitColor,
150 boost::ref(self.m_rColor.g),_1)]
151 >> xdigit_p[boost::bind(&setFourBitColor,
152 boost::ref(self.m_rColor.b),_1)])
154 // rgb() form
155 (str_p("rgb")
156 >> '(' >>
158 // rgb(int,int,int)
159 (byte_p[boost::bind(&setIntColor,
160 boost::ref(self.m_rColor.r),_1)] >> ',' >>
161 byte_p[boost::bind(&setIntColor,
162 boost::ref(self.m_rColor.g),_1)] >> ',' >>
163 byte_p[boost::bind(&setIntColor,
164 boost::ref(self.m_rColor.b),_1)])
166 // rgb(double,double,double)
167 (real_p[assign_a(self.m_rColor.r)] >> ',' >>
168 real_p[assign_a(self.m_rColor.g)] >> ',' >>
169 real_p[assign_a(self.m_rColor.b)])
171 >> ')')
174 ::boost::spirit::rule<ScannerT> const& start() const { return colorExpression; }
179 bool parseColor( const char* sColor, ARGBColor& rColor )
181 using namespace ::boost::spirit;
183 if( parse(sColor,
184 ColorGrammar(rColor) >> end_p,
185 space_p).full )
187 // free-form color found & parsed
188 return true;
191 // no free-form color - maybe a color name?
192 // trim white space before
193 while( *sColor &&
194 (*sColor==' ' || *sColor=='\t' || *sColor=='\r' || *sColor=='\n') )
195 ++sColor;
196 // trim white space after
197 int nLen=strlen(sColor)-1;
198 while( nLen &&
199 (sColor[nLen]==' ' || sColor[nLen]=='\t' || sColor[nLen]=='\r' || sColor[nLen]=='\n') )
200 --nLen;
201 switch (getTokenId(sColor, nLen+1))
203 case XML_ALICEBLUE: rColor = ARGBColor(240,248,255); return true;
204 case XML_ANTIQUEWHITE: rColor = ARGBColor(250,235,215); return true;
205 case XML_AQUA: rColor = ARGBColor(0,255,255); return true;
206 case XML_AQUAMARINE: rColor = ARGBColor(127,255,212); return true;
207 case XML_AZURE: rColor = ARGBColor(240,255,255); return true;
208 case XML_BEIGE: rColor = ARGBColor(245,245,220); return true;
209 case XML_BISQUE: rColor = ARGBColor(255,228,196); return true;
210 case XML_BLACK: rColor = ARGBColor(0,0,0); return true;
211 case XML_BLANCHEDALMOND: rColor = ARGBColor(255,235,205); return true;
212 case XML_BLUE: rColor = ARGBColor(0,0,255); return true;
213 case XML_BLUEVIOLET: rColor = ARGBColor(138,43,226); return true;
214 case XML_BROWN: rColor = ARGBColor(165,42,42); return true;
215 case XML_BURLYWOOD: rColor = ARGBColor(222,184,135); return true;
216 case XML_CADETBLUE: rColor = ARGBColor(95,158,160); return true;
217 case XML_CHARTREUSE: rColor = ARGBColor(127,255,0); return true;
218 case XML_CHOCOLATE: rColor = ARGBColor(210,105,30); return true;
219 case XML_CORAL: rColor = ARGBColor(255,127,80); return true;
220 case XML_CORNFLOWERBLUE: rColor = ARGBColor(100,149,237); return true;
221 case XML_CORNSILK: rColor = ARGBColor(255,248,220); return true;
222 case XML_CRIMSON: rColor = ARGBColor(220,20,60); return true;
223 case XML_CYAN: rColor = ARGBColor(0,255,255); return true;
224 case XML_DARKBLUE: rColor = ARGBColor(0,0,139); return true;
225 case XML_DARKCYAN: rColor = ARGBColor(0,139,139); return true;
226 case XML_DARKGOLDENROD: rColor = ARGBColor(184,134,11); return true;
227 case XML_DARKGRAY: rColor = ARGBColor(169,169,169); return true;
228 case XML_DARKGREEN: rColor = ARGBColor(0,100,0); return true;
229 case XML_DARKGREY: rColor = ARGBColor(169,169,169); return true;
230 case XML_DARKKHAKI: rColor = ARGBColor(189,183,107); return true;
231 case XML_DARKMAGENTA: rColor = ARGBColor(139,0,139); return true;
232 case XML_DARKOLIVEGREEN: rColor = ARGBColor(85,107,47); return true;
233 case XML_DARKORANGE: rColor = ARGBColor(255,140,0); return true;
234 case XML_DARKORCHID: rColor = ARGBColor(153,50,204); return true;
235 case XML_DARKRED: rColor = ARGBColor(139,0,0); return true;
236 case XML_DARKSALMON: rColor = ARGBColor(233,150,122); return true;
237 case XML_DARKSEAGREEN: rColor = ARGBColor(143,188,143); return true;
238 case XML_DARKSLATEBLUE: rColor = ARGBColor(72,61,139); return true;
239 case XML_DARKSLATEGRAY: rColor = ARGBColor(47,79,79); return true;
240 case XML_DARKSLATEGREY: rColor = ARGBColor(47,79,79); return true;
241 case XML_DARKTURQUOISE: rColor = ARGBColor(0,206,209); return true;
242 case XML_DARKVIOLET: rColor = ARGBColor(148,0,211); return true;
243 case XML_DEEPPINK: rColor = ARGBColor(255,20,147); return true;
244 case XML_DEEPSKYBLUE: rColor = ARGBColor(0,191,255); return true;
245 case XML_DIMGRAY: rColor = ARGBColor(105,105,105); return true;
246 case XML_DIMGREY: rColor = ARGBColor(105,105,105); return true;
247 case XML_DODGERBLUE: rColor = ARGBColor(30,144,255); return true;
248 case XML_FIREBRICK: rColor = ARGBColor(178,34,34); return true;
249 case XML_FLORALWHITE: rColor = ARGBColor(255,250,240); return true;
250 case XML_FORESTGREEN: rColor = ARGBColor(34,139,34); return true;
251 case XML_FUCHSIA: rColor = ARGBColor(255,0,255); return true;
252 case XML_GAINSBORO: rColor = ARGBColor(220,220,220); return true;
253 case XML_GHOSTWHITE: rColor = ARGBColor(248,248,255); return true;
254 case XML_GOLD: rColor = ARGBColor(255,215,0); return true;
255 case XML_GOLDENROD: rColor = ARGBColor(218,165,32); return true;
256 case XML_GRAY: rColor = ARGBColor(128,128,128); return true;
257 case XML_GREY: rColor = ARGBColor(128,128,128); return true;
258 case XML_GREEN: rColor = ARGBColor(0,128,0); return true;
259 case XML_GREENYELLOW: rColor = ARGBColor(173,255,47); return true;
260 case XML_HONEYDEW: rColor = ARGBColor(240,255,240); return true;
261 case XML_HOTPINK: rColor = ARGBColor(255,105,180); return true;
262 case XML_INDIANRED: rColor = ARGBColor(205,92,92); return true;
263 case XML_INDIGO: rColor = ARGBColor(75,0,130); return true;
264 case XML_IVORY: rColor = ARGBColor(255,255,240); return true;
265 case XML_KHAKI: rColor = ARGBColor(240,230,140); return true;
266 case XML_LAVENDER: rColor = ARGBColor(230,230,250); return true;
267 case XML_LAVENDERBLUSH: rColor = ARGBColor(255,240,245); return true;
268 case XML_LAWNGREEN: rColor = ARGBColor(124,252,0); return true;
269 case XML_LEMONCHIFFON: rColor = ARGBColor(255,250,205); return true;
270 case XML_LIGHTBLUE: rColor = ARGBColor(173,216,230); return true;
271 case XML_LIGHTCORAL: rColor = ARGBColor(240,128,128); return true;
272 case XML_LIGHTCYAN: rColor = ARGBColor(224,255,255); return true;
273 case XML_LIGHTGOLDENRODYELLOW: rColor = ARGBColor(250,250,210); return true;
274 case XML_LIGHTGRAY: rColor = ARGBColor(211,211,211); return true;
275 case XML_LIGHTGREEN: rColor = ARGBColor(144,238,144); return true;
276 case XML_LIGHTGREY: rColor = ARGBColor(211,211,211); return true;
277 case XML_LIGHTPINK: rColor = ARGBColor(255,182,193); return true;
278 case XML_LIGHTSALMON: rColor = ARGBColor(255,160,122); return true;
279 case XML_LIGHTSEAGREEN: rColor = ARGBColor(32,178,170); return true;
280 case XML_LIGHTSKYBLUE: rColor = ARGBColor(135,206,250); return true;
281 case XML_LIGHTSLATEGRAY: rColor = ARGBColor(119,136,153); return true;
282 case XML_LIGHTSLATEGREY: rColor = ARGBColor(119,136,153); return true;
283 case XML_LIGHTSTEELBLUE: rColor = ARGBColor(176,196,222); return true;
284 case XML_LIGHTYELLOW: rColor = ARGBColor(255,255,224); return true;
285 case XML_LIME: rColor = ARGBColor(0,255,0); return true;
286 case XML_LIMEGREEN: rColor = ARGBColor(50,205,50); return true;
287 case XML_LINEN: rColor = ARGBColor(250,240,230); return true;
288 case XML_MAGENTA: rColor = ARGBColor(255,0,255); return true;
289 case XML_MAROON: rColor = ARGBColor(128,0,0); return true;
290 case XML_MEDIUMAQUAMARINE: rColor = ARGBColor(102,205,170); return true;
291 case XML_MEDIUMBLUE: rColor = ARGBColor(0,0,205); return true;
292 case XML_MEDIUMORCHID: rColor = ARGBColor(186,85,211); return true;
293 case XML_MEDIUMPURPLE: rColor = ARGBColor(147,112,219); return true;
294 case XML_MEDIUMSEAGREEN: rColor = ARGBColor(60,179,113); return true;
295 case XML_MEDIUMSLATEBLUE: rColor = ARGBColor(123,104,238); return true;
296 case XML_MEDIUMSPRINGGREEN: rColor = ARGBColor(0,250,154); return true;
297 case XML_MEDIUMTURQUOISE: rColor = ARGBColor(72,209,204); return true;
298 case XML_MEDIUMVIOLETRED: rColor = ARGBColor(199,21,133); return true;
299 case XML_MIDNIGHTBLUE: rColor = ARGBColor(25,25,112); return true;
300 case XML_MINTCREAM: rColor = ARGBColor(245,255,250); return true;
301 case XML_MISTYROSE: rColor = ARGBColor(255,228,225); return true;
302 case XML_MOCCASIN: rColor = ARGBColor(255,228,181); return true;
303 case XML_NAVAJOWHITE: rColor = ARGBColor(255,222,173); return true;
304 case XML_NAVY: rColor = ARGBColor(0,0,128); return true;
305 case XML_OLDLACE: rColor = ARGBColor(253,245,230); return true;
306 case XML_OLIVE: rColor = ARGBColor(128,128,0); return true;
307 case XML_OLIVEDRAB: rColor = ARGBColor(107,142,35); return true;
308 case XML_ORANGE: rColor = ARGBColor(255,165,0); return true;
309 case XML_ORANGERED: rColor = ARGBColor(255,69,0); return true;
310 case XML_ORCHID: rColor = ARGBColor(218,112,214); return true;
311 case XML_PALEGOLDENROD: rColor = ARGBColor(238,232,170); return true;
312 case XML_PALEGREEN: rColor = ARGBColor(152,251,152); return true;
313 case XML_PALETURQUOISE: rColor = ARGBColor(175,238,238); return true;
314 case XML_PALEVIOLETRED: rColor = ARGBColor(219,112,147); return true;
315 case XML_PAPAYAWHIP: rColor = ARGBColor(255,239,213); return true;
316 case XML_PEACHPUFF: rColor = ARGBColor(255,218,185); return true;
317 case XML_PERU: rColor = ARGBColor(205,133,63); return true;
318 case XML_PINK: rColor = ARGBColor(255,192,203); return true;
319 case XML_PLUM: rColor = ARGBColor(221,160,221); return true;
320 case XML_POWDERBLUE: rColor = ARGBColor(176,224,230); return true;
321 case XML_PURPLE: rColor = ARGBColor(128,0,128); return true;
322 case XML_RED: rColor = ARGBColor(255,0,0); return true;
323 case XML_ROSYBROWN: rColor = ARGBColor(188,143,143); return true;
324 case XML_ROYALBLUE: rColor = ARGBColor(65,105,225); return true;
325 case XML_SADDLEBROWN: rColor = ARGBColor(139,69,19); return true;
326 case XML_SALMON: rColor = ARGBColor(250,128,114); return true;
327 case XML_SANDYBROWN: rColor = ARGBColor(244,164,96); return true;
328 case XML_SEAGREEN: rColor = ARGBColor(46,139,87); return true;
329 case XML_SEASHELL: rColor = ARGBColor(255,245,238); return true;
330 case XML_SIENNA: rColor = ARGBColor(160,82,45); return true;
331 case XML_SILVER: rColor = ARGBColor(192,192,192); return true;
332 case XML_SKYBLUE: rColor = ARGBColor(135,206,235); return true;
333 case XML_SLATEBLUE: rColor = ARGBColor(106,90,205); return true;
334 case XML_SLATEGRAY: rColor = ARGBColor(112,128,144); return true;
335 case XML_SLATEGREY: rColor = ARGBColor(112,128,144); return true;
336 case XML_SNOW: rColor = ARGBColor(255,250,250); return true;
337 case XML_SPRINGGREEN: rColor = ARGBColor(0,255,127); return true;
338 case XML_STEELBLUE: rColor = ARGBColor(70,130,180); return true;
339 case XML_TAN: rColor = ARGBColor(210,180,140); return true;
340 case XML_TEAL: rColor = ARGBColor(0,128,128); return true;
341 case XML_THISTLE: rColor = ARGBColor(216,191,216); return true;
342 case XML_TOMATO: rColor = ARGBColor(255,99,71); return true;
343 case XML_TURQUOISE: rColor = ARGBColor(64,224,208); return true;
344 case XML_VIOLET: rColor = ARGBColor(238,130,238); return true;
345 case XML_WHEAT: rColor = ARGBColor(245,222,179); return true;
346 case XML_WHITE: rColor = ARGBColor(255,255,255); return true;
347 case XML_WHITESMOKE: rColor = ARGBColor(245,245,245); return true;
348 case XML_YELLOW: rColor = ARGBColor(255,255,0); return true;
349 case XML_YELLOWGREEN: rColor = ARGBColor(154,205,50); return true;
351 default:
352 return false; // no color at all, I'd guess.
356 bool parseOpacity (const char* sOpacity, ARGBColor& rColor )
358 using namespace ::boost::spirit;
360 if( parse(sOpacity,
361 // Begin grammar
363 real_p[assign_a(rColor.a)]
364 ) >> end_p,
365 // End grammar
366 space_p).full )
368 return true;
370 return false;
373 //////////////////////////////////////////////////////////////
375 bool parseTransform( const char* sTransform, basegfx::B2DHomMatrix& rTransform )
377 using namespace ::boost::spirit;
379 double fRefOffsetX(0.0);
380 double fRefOffsetY(0.0);
381 bool bRefTransform(false);
383 double fRotationAngle=0.0;
384 double fSkewAngle=0.0;
385 geometry::AffineMatrix2D aIdentityTransform;
386 geometry::AffineMatrix2D aCurrTransform;
387 std::vector<geometry::AffineMatrix2D> aTransforms;
388 aIdentityTransform.m00 = 1.0; aIdentityTransform.m11 = 1.0;
389 aCurrTransform = aIdentityTransform;
391 const bool bRes = parse(sTransform,
392 // Begin grammar
394 // identity transform
395 str_p("none")
397 // the ref() form
398 (str_p("ref")
399 >> '('
400 >> str_p("svg")[assign_a(bRefTransform,true)]
401 >> !(real_p[assign_a(fRefOffsetX)] >> (',' | eps_p) >>
402 real_p[assign_a(fRefOffsetY)])
403 >> ')')
405 // the transform-list form
406 (list_p(
408 // matrix(a,b,c,d,e,f)
409 (str_p("matrix")
410 >> '('
411 >> real_p[assign_a(aCurrTransform.m00)] >> (',' | eps_p)
412 >> real_p[assign_a(aCurrTransform.m10)] >> (',' | eps_p)
413 >> real_p[assign_a(aCurrTransform.m01)] >> (',' | eps_p)
414 >> real_p[assign_a(aCurrTransform.m11)] >> (',' | eps_p)
415 >> real_p[assign_a(aCurrTransform.m02)] >> (',' | eps_p)
416 >> real_p[assign_a(aCurrTransform.m12)]
417 >> ')')[push_back_a(aTransforms,aCurrTransform)]
419 // translate(x,[y])
420 (str_p("translate")
421 >> '('
422 >> real_p[boost::bind(&assign_twice,
423 boost::ref(aCurrTransform.m02),
424 boost::ref(aCurrTransform.m12),_1)]
425 >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m12)])
426 >> ')')[push_back_a(aTransforms,aCurrTransform)]
428 // scale(x,[y])
429 (str_p("scale")
430 >> '('
431 >> real_p[boost::bind(&assign_twice,
432 boost::ref(aCurrTransform.m00),
433 boost::ref(aCurrTransform.m11),_1)]
434 >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m11)])
435 >> ')')[push_back_a(aTransforms,aCurrTransform)]
437 // rotate(phi,[cx, cy])
438 (str_p("rotate")
439 >> '('
440 >> real_p[assign_a(fRotationAngle)]
441 >> !((',' | eps_p) >> real_p[assign_a(aCurrTransform.m02)]
442 >> real_p[assign_a(aCurrTransform.m12)])
443 >> ')')[boost::bind(&calcRotation,
444 boost::ref(aTransforms),
445 boost::ref(aCurrTransform),
446 boost::cref(fRotationAngle))]
448 // skewX(phi)
449 (str_p("skewX")
450 >> '('
451 >> real_p[assign_a(fSkewAngle)]
452 >> ')')[boost::bind(&calcSkewX,
453 boost::ref(aTransforms),
454 boost::cref(fSkewAngle))]
456 // skewY(phi)
457 (str_p("skewY")
458 >> '('
459 >> real_p[assign_a(fSkewAngle)]
460 >> ')')[boost::bind(&calcSkewY,
461 boost::ref(aTransforms),
462 boost::cref(fSkewAngle))]
463 // reset current transform after every push
464 )[assign_a(aCurrTransform,aIdentityTransform)],
465 // list delimiter is either ',' or space
466 ',' | eps_p ))
467 ) >> end_p,
468 // End grammar
469 space_p).full;
471 if( !bRes )
472 return false;
474 // fold all transformations into one
475 const geometry::AffineMatrix2D aTotalTransform(
476 std::accumulate(aTransforms.begin(),
477 aTransforms.end(),
478 aIdentityTransform,
479 &multiplyMatrix));
481 basegfx::unotools::homMatrixFromAffineMatrix(
482 rTransform,
483 aTotalTransform);
485 // TODO(F1): handle the ref case
486 return bRes;
489 //////////////////////////////////////////////////////////////
491 bool parseViewBox( const char* sViewbox, basegfx::B2DRange& rRect )
493 using namespace ::boost::spirit;
495 double x=0.0,y=0.0,w=0.0,h=0.0;
497 const bool bRes = parse(sViewbox,
498 // Begin grammar
500 // either comma- or space-delimited list of four doubles
501 real_p[assign_a(x)] >> (',' | eps_p) >>
502 real_p[assign_a(y)] >> (',' | eps_p) >>
503 real_p[assign_a(w)] >> (',' | eps_p) >>
504 real_p[assign_a(h)] >> end_p
506 // End grammar
507 space_p).full;
509 if( !bRes )
510 return false;
512 rRect = basegfx::B2DRange(x,y,x+w,y+h);
514 return true;
517 //////////////////////////////////////////////////////////////
519 bool parseDashArray( const char* sDashArray, std::vector<double>& rOutputVector )
521 using namespace ::boost::spirit;
523 rOutputVector.clear();
524 return parse(sDashArray,
525 // Begin grammar
527 // parse comma-delimited list of doubles (have to use the
528 // 'direct' variant, as otherwise spirit refactors our
529 // parser to push both real num and comma to push_back_a)
530 list_p.direct
532 real_p[push_back_a(rOutputVector)],
533 // list delimiter is either ',' or space
534 ',' | eps_p
536 ) >> end_p,
537 // End grammar
538 space_p).full;
541 //////////////////////////////////////////////////////////////
543 bool parsePaintUri( std::pair<const char*,const char*>& o_rPaintUri,
544 std::pair<ARGBColor,bool>& io_rColor,
545 const char* sPaintUri )
547 using namespace ::boost::spirit;
549 const bool bRes = parse(sPaintUri,
550 // Begin grammar
552 str_p("url(#") >>
553 (+alnum_p)[assign_a(o_rPaintUri)] >>
554 str_p(")") >>
555 *( str_p("none")[assign_a(io_rColor.second,false)] |
556 str_p("currentColor")[assign_a(io_rColor.second,true)] |
557 ColorGrammar(io_rColor.first)
558 // TODO(F1): named color
560 ) >> end_p,
561 // End grammar
562 space_p).full;
564 return bRes;
567 //////////////////////////////////////////////////////////////
569 namespace
571 void appendChar( std::string& str, char character)
573 str.append(1,character);
577 bool parseXlinkHref( const char* sXlinkHref, std::string& data )
579 using namespace ::boost::spirit;
581 data.erase(data.begin(),data.end());
583 std::string sLink(sXlinkHref);
585 if (!sLink.compare(0,5,"data:"))
587 // the inplace "data" uri
588 size_t position = sLink.rfind(',');
589 if (position > 0 && position < std::string::npos)
591 data = sLink.substr(position+1);
592 OSL_TRACE("%s", data.c_str());
593 return true;
597 return false;
600 } // namespace svgi