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