]> git.immae.eu Git - github/wallabag/wallabag.git/blob - inc/3rdparty/libraries/mpdf/classes/svg.php
add pdf and mobi libraries
[github/wallabag/wallabag.git] / inc / 3rdparty / libraries / mpdf / classes / svg.php
1 <?php
2 // svg class modified for mPDF version 4.4.003 by Ian Back: based on -
3 // svg2pdf fpdf class
4 // sylvain briand (syb@godisaduck.com), modified by rick trevino (rtrevino1@yahoo.com)
5 // http://www.godisaduck.com/svg2pdf_with_fpdf
6 // http://rhodopsin.blogspot.com
7 //
8 // cette class etendue est open source, toute modification devra cependant etre repertoriée~
9
10
11 // NB UNITS - Works in pixels as main units - converting to PDF units when outputing to PDF string
12 // and on returning size
13
14 class SVG {
15
16 var $svg_gradient; // array - contient les infos sur les gradient fill du svg classé par id du svg
17 var $svg_shadinglist; // array - contient les ids des objet shading
18 var $svg_info; // array contenant les infos du svg voulue par l'utilisateur
19 var $svg_attribs; // array - holds all attributes of root <svg> tag
20 var $svg_style; // array contenant les style de groupes du svg
21 var $svg_string; // String contenant le tracage du svg en lui même.
22 var $txt_data; // array - holds string info to write txt to image
23 var $txt_style; // array - current text style
24 var $mpdf_ref;
25 var $xbase; // mPDF 4.4.003
26 var $ybase; // mPDF 4.4.003
27 var $svg_error; // mPDF 4.4.003
28 var $subPathInit; // mPDF 4.4.003
29 var $spxstart; // mPDF 4.4.003
30 var $spystart; // mPDF 4.4.003
31 var $kp; // mPDF 4.4.003 convert pixels to PDF units
32 var $pathBBox; // mPDF 5.0.039
33
34 function SVG(&$mpdf){
35 $this->svg_gradient = array();
36 $this->svg_shadinglist = array();
37 $this->txt_data = array();
38 $this->svg_string = '';
39 $this->svg_info = array();
40 $this->svg_attribs = array();
41 $this->xbase = 0;
42 $this->ybase = 0;
43 $this->svg_error = false;
44 $this->subPathInit = false; // mPDF 4.4.003
45 $this->dashesUsed = false; // mPDF 5.0
46 $this->mpdf_ref =& $mpdf;
47
48 $this->kp = 72 / $mpdf->img_dpi; // mPDF 4.4.003 constant To convert pixels to pts/PDF units
49 $this->kf = 1; // mPDF 5.0.039 constant To convert font size if re-mapped
50 $this->pathBBox = array(); // mPDF 5.0.039
51
52 $this->svg_style = array(
53 array(
54 'fill' => 'black', // mPDF 4.4.008
55 'fill-opacity' => 1, // remplissage opaque par defaut
56 'fill-rule' => 'nonzero', // mode de remplissage par defaut
57 'stroke' => 'none', // pas de trait par defaut
58 'stroke-linecap' => 'butt', // style de langle par defaut
59 'stroke-linejoin' => 'miter', //
60 'stroke-miterlimit' => 4, // limite de langle par defaut
61 'stroke-opacity' => 1, // trait opaque par defaut
62 'stroke-width' => 1, // mPDF 4.4.011
63 'stroke-dasharray' => 0, // mPDF 4.4.003
64 'stroke-dashoffset' => 0, // mPDF 4.4.003
65 'color' => '' // mPDF 4.4.005
66 )
67 );
68
69 $this->txt_style = array(
70 array(
71 'fill' => 'black', // pas de remplissage par defaut
72 'font-family' => $mpdf->default_font,
73 'font-size' => $mpdf->default_font_size, // ****** this is pts
74 'font-weight' => 'normal', // normal | bold
75 'font-style' => 'normal', // italic | normal
76 'text-anchor' => 'start', // alignment: start, middle, end
77 /* mPDF 5.0.041 */
78 'fill-opacity' => 1, // remplissage opaque par defaut
79 'fill-rule' => 'nonzero', // mode de remplissage par defaut
80 'stroke' => 'none', // pas de trait par defaut
81 'stroke-opacity' => 1, // trait opaque par defaut
82 'stroke-width' => 1, // mPDF 4.4.011
83 'color' => '' // mPDF 4.4.005
84 )
85 );
86
87
88
89 }
90
91 function svgGradient($gradient_info, $attribs, $element){
92 $n = count($this->mpdf_ref->gradients)+1;
93
94 // Get bounding dimensions of element
95 $w = 100;
96 $h = 100;
97 $x_offset = 0;
98 $y_offset = 0;
99 if ($element=='rect') {
100 $w = $attribs['width'];
101 $h = $attribs['height'];
102 $x_offset = $attribs['x'];
103 $y_offset = $attribs['y'];
104 }
105 else if ($element=='ellipse') {
106 $w = $attribs['rx']*2;
107 $h = $attribs['ry']*2;
108 $x_offset = $attribs['cx']-$attribs['rx'];
109 $y_offset = $attribs['cy']-$attribs['ry'];
110 }
111 else if ($element=='circle') {
112 $w = $attribs['r']*2;
113 $h = $attribs['r']*2;
114 $x_offset = $attribs['cx']-$attribs['r'];
115 $y_offset = $attribs['cy']-$attribs['r'];
116 }
117 else if ($element=='polygon') {
118 $pts = preg_split('/[ ,]+/', trim($attribs['points']));
119 $maxr=$maxb=0;
120 $minl=$mint=999999;
121 for ($i=0;$i<count($pts); $i++) {
122 if ($i % 2 == 0) { // x values
123 $minl = min($minl,$pts[$i]);
124 $maxr = max($maxr,$pts[$i]);
125 }
126 else { // y values
127 $mint = min($mint,$pts[$i]);
128 $maxb = max($maxb,$pts[$i]);
129 }
130 }
131 $w = $maxr-$minl;
132 $h = $maxb-$mint;
133 $x_offset = $minl;
134 $y_offset = $mint;
135 }
136 else if ($element=='path') {
137 // mPDF 5.0.039
138 if (is_array($this->pathBBox) && $this->pathBBox[2]>0) {
139 $w = $this->pathBBox[2];
140 $h = $this->pathBBox[3];
141 $x_offset = $this->pathBBox[0];
142 $y_offset = $this->pathBBox[1];
143 }
144 else {
145 preg_match_all('/([a-z]|[A-Z])([ ,\-.\d]+)*/', $attribs['d'], $commands, PREG_SET_ORDER);
146 $maxr=$maxb=0;
147 $minl=$mint=999999;
148 foreach($commands as $c){
149 if(count($c)==3){
150 list($tmp, $cmd, $arg) = $c;
151 if ($cmd=='M' || $cmd=='L' || $cmd=='C' || $cmd=='S' || $cmd=='Q' || $cmd=='T') {
152 $pts = preg_split('/[ ,]+/', trim($arg));
153 for ($i=0;$i<count($pts); $i++) {
154 if ($i % 2 == 0) { // x values
155 $minl = min($minl,$pts[$i]);
156 $maxr = max($maxr,$pts[$i]);
157 }
158 else { // y values
159 $mint = min($mint,$pts[$i]);
160 $maxb = max($maxb,$pts[$i]);
161 }
162 }
163 }
164 if ($cmd=='H') { // sets new x
165 $minl = min($minl,$arg);
166 $maxr = max($maxr,$arg);
167 }
168 if ($cmd=='V') { // sets new y
169 $mint = min($mint,$arg);
170 $maxb = max($maxb,$arg);
171 }
172 }
173 }
174 $w = $maxr-$minl;
175 $h = $maxb-$mint;
176 $x_offset = $minl;
177 $y_offset = $mint;
178 }
179 }
180 if (!$w || $w==-999999) { $w = 100; }
181 if (!$h || $h==-999999) { $h = 100; }
182 if ($x_offset==999999) { $x_offset = 0; }
183 if ($y_offset==999999) { $y_offset = 0; }
184
185 // mPDF 4.5.010
186 // TRANSFORMATIONS
187 $transformations = '';
188 if (isset($gradient_info['transform'])){
189 preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)\((.*?)\)/is',$gradient_info['transform'],$m);
190 if (count($m[0])) {
191 for($i=0; $i<count($m[0]); $i++) {
192 $c = strtolower($m[1][$i]);
193 $v = trim($m[2][$i]);
194 $vv = preg_split('/[ ,]+/',$v);
195 if ($c=='matrix' && count($vv)==6) {
196 // mPDF 5.0.039
197 // Note angle of rotation is reversed (from SVG to PDF), so vv[1] and vv[2] are negated
198 // cf svgDefineStyle()
199 $transformations .= sprintf(' %.3F %.3F %.3F %.3F %.3F %.3F cm ', $vv[0], -$vv[1], -$vv[2], $vv[3], $vv[4]*$this->kp, -$vv[5]*$this->kp);
200 }
201 else if ($c=='translate' && count($vv)) {
202 $tm[4] = $vv[0];
203 if (count($vv)==2) { $t_y = -$vv[1]; }
204 else { $t_y = 0; }
205 $tm[5] = $t_y;
206 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $tm[4]*$this->kp, $tm[5]*$this->kp);
207 }
208 else if ($c=='scale' && count($vv)) {
209 if (count($vv)==2) { $s_y = $vv[1]; }
210 else { $s_y = $vv[0]; }
211 $tm[0] = $vv[0];
212 $tm[3] = $s_y;
213 $transformations .= sprintf(' %.3F 0 0 %.3F 0 0 cm ', $tm[0], $tm[3]);
214 }
215 else if ($c=='rotate' && count($vv)) {
216 $tm[0] = cos(deg2rad(-$vv[0]));
217 $tm[1] = sin(deg2rad(-$vv[0]));
218 $tm[2] = -$tm[1];
219 $tm[3] = $tm[0];
220 if (count($vv)==3) {
221 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $vv[1]*$this->kp, -$vv[2]*$this->kp);
222 }
223 $transformations .= sprintf(' %.3F %.3F %.3F %.3F 0 0 cm ', $tm[0], $tm[1], $tm[2], $tm[3]);
224 if (count($vv)==3) {
225 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', -$vv[1]*$this->kp, $vv[2]*$this->kp);
226 }
227 }
228 else if ($c=='skewx' && count($vv)) {
229 $tm[2] = tan(deg2rad(-$vv[0]));
230 $transformations .= sprintf(' 1 0 %.3F 1 0 0 cm ', $tm[2]);
231 }
232 else if ($c=='skewy' && count($vv)) {
233 $tm[1] = tan(deg2rad(-$vv[0]));
234 $transformations .= sprintf(' 1 %.3F 0 1 0 0 cm ', $tm[1]);
235 }
236
237 }
238 }
239 }
240
241
242 $return = "";
243
244 // mPDF 5.0.039
245 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
246 if ($transformations) { $return .= $transformations; }
247 }
248 // mPDF 5.0.040
249 $spread = 'P'; // pad
250 if (isset($gradient_info['spread'])) {
251 if (strtolower($gradient_info['spread'])=='reflect') { $spread = 'F'; } // reflect
252 else if (strtolower($gradient_info['spread'])=='repeat') { $spread = 'R'; } // repeat
253 }
254
255
256 for ($i=0; $i<(count($gradient_info['color'])); $i++) {
257 if (stristr($gradient_info['color'][$i]['offset'], '%')!== false) { $gradient_info['color'][$i]['offset'] = ($gradient_info['color'][$i]['offset']+0)/100; }
258 if (stristr($gradient_info['color'][($i+1)]['offset'], '%')!== false) { $gradient_info['color'][($i+1)]['offset'] = ($gradient_info['color'][($i+1)]['offset']+0)/100; }
259 if ($gradient_info['color'][$i]['offset']<0) { $gradient_info['color'][$i]['offset'] = 0; }
260 if ($gradient_info['color'][$i]['offset']>1) { $gradient_info['color'][$i]['offset'] = 1; }
261 if ($i>0) {
262 if ($gradient_info['color'][$i]['offset']<$gradient_info['color'][($i-1)]['offset']) {
263 $gradient_info['color'][$i]['offset']=$gradient_info['color'][($i-1)]['offset'];
264 }
265 }
266 }
267
268 if ($gradient_info['color'][0]['offset']>0) {
269 array_unshift($gradient_info['color'], $gradient_info['color'][0]);
270 $gradient_info['color'][0]['offset'] = 0;
271 }
272 $ns = count($gradient_info['color']);
273 if ($gradient_info['color'][($ns-1)]['offset']<1) {
274 $gradient_info['color'][] = $gradient_info['color'][($ns-1)];
275 $gradient_info['color'][($ns)]['offset'] = 1;
276 }
277 $ns = count($gradient_info['color']);
278
279
280
281
282 if ($gradient_info['type'] == 'linear'){
283 // mPDF 4.4.003
284 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
285 if (isset($gradient_info['info']['x1'])) { $gradient_info['info']['x1'] = ($gradient_info['info']['x1']-$x_offset) / $w; }
286 if (isset($gradient_info['info']['y1'])) { $gradient_info['info']['y1'] = ($gradient_info['info']['y1']-$y_offset) / $h; }
287 if (isset($gradient_info['info']['x2'])) { $gradient_info['info']['x2'] = ($gradient_info['info']['x2']-$x_offset) / $w; }
288 if (isset($gradient_info['info']['y2'])) { $gradient_info['info']['y2'] = ($gradient_info['info']['y2']-$y_offset) / $h; }
289 }
290 if (isset($gradient_info['info']['x1'])) { $x1 = $gradient_info['info']['x1']; }
291 else { $x1 = 0; }
292 if (isset($gradient_info['info']['y1'])) { $y1 = $gradient_info['info']['y1']; }
293 else { $y1 = 0; }
294 if (isset($gradient_info['info']['x2'])) { $x2 = $gradient_info['info']['x2']; }
295 else { $x2 = 1; }
296 if (isset($gradient_info['info']['y2'])) { $y2 = $gradient_info['info']['y2']; }
297 else { $y2 = 0; }
298
299 if (stristr($x1, '%')!== false) { $x1 = ($x1+0)/100; }
300 if (stristr($x2, '%')!== false) { $x2 = ($x2+0)/100; }
301 if (stristr($y1, '%')!== false) { $y1 = ($y1+0)/100; }
302 if (stristr($y2, '%')!== false) { $y2 = ($y2+0)/100; }
303
304 // mPDF 5.0.042
305 $bboxw = $w;
306 $bboxh = $h;
307 $usex = $x_offset;
308 $usey = $y_offset;
309 $usew = $bboxw;
310 $useh = $bboxh;
311 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
312 $angle = rad2deg(atan2(($gradient_info['info']['y2']-$gradient_info['info']['y1']), ($gradient_info['info']['x2']-$gradient_info['info']['x1'])));
313 if ($angle < 0) { $angle += 360; }
314 else if ($angle > 360) { $angle -= 360; }
315 if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) {
316 if ($w >= $h) {
317 $y1 *= $h/$w ;
318 $y2 *= $h/$w ;
319 $usew = $useh = $bboxw;
320 }
321 else {
322 $x1 *= $w/$h ;
323 $x2 *= $w/$h ;
324 $usew = $useh = $bboxh;
325 }
326 }
327 }
328 $a = $usew; // width
329 $d = -$useh; // height
330 $e = $usex; // x- offset
331 $f = -$usey; // -y-offset
332
333 $return .= sprintf('%.3F 0 0 %.3F %.3F %.3F cm ', $a*$this->kp, $d*$this->kp, $e*$this->kp, $f*$this->kp);
334
335 // mPDF 5.0.039
336 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='objectboundingbox') {
337 if ($transformations) { $return .= $transformations; }
338 }
339
340 // mPDF 5.0.020
341 $trans = false;
342
343 // mPDF 5.0.040
344 if ($spread=='R' || $spread=='F') { // Repeat / Reflect
345 $offs = array();
346 for($i=0;$i<$ns;$i++) {
347 $offs[$i] = $gradient_info['color'][$i]['offset'];
348 }
349 $gp = 0;
350 $inside=true;
351 while($inside) {
352 $gp++;
353 for($i=0;$i<$ns;$i++) {
354 if ($spread=='F' && ($gp % 2) == 1) { // Reflect
355 $gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][(($ns*($gp-1))+($ns-$i-1))];
356 $tmp = $gp+(1-$offs[($ns-$i-1)]) ;
357 $gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp;
358 }
359 else { // Reflect
360 $gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][$i];
361 $tmp = $gp+$offs[$i] ;
362 $gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp;
363 }
364 // IF STILL INSIDE BOX OR STILL VALID
365 // Point on axis to test
366 $px1 = $x1 + ($x2-$x1)*$tmp;
367 $py1 = $y1 + ($y2-$y1)*$tmp;
368 // Get perpendicular axis
369 $alpha = atan2($y2-$y1, $x2-$x1);
370 $alpha += M_PI/2; // rotate 90 degrees
371 // Get arbitrary point to define line perpendicular to axis
372 $px2 = $px1+cos($alpha);
373 $py2 = $py1+sin($alpha);
374
375 $res1 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 0, 1); // $x=0 vert axis
376 $res2 = _testIntersect($px1, $py1, $px2, $py2, 1, 0, 1, 1); // $x=1 vert axis
377 $res3 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 1, 0); // $y=0 horiz axis
378 $res4 = _testIntersect($px1, $py1, $px2, $py2, 0, 1, 1, 1); // $y=1 horiz axis
379 if (!$res1 && !$res2 && !$res3 && !$res4) { $inside = false; }
380 }
381 }
382
383 $inside=true;
384 $gp = 0;
385 while($inside) {
386 $gp++;
387 $newarr = array();
388 for($i=0;$i<$ns;$i++) {
389 if ($spread=='F') { // Reflect
390 $newarr[$i] = $gradient_info['color'][($ns-$i-1)];
391 if (($gp % 2) == 1) {
392 $tmp = -$gp+(1-$offs[($ns-$i-1)]);
393 $newarr[$i]['offset'] = $tmp;
394 }
395 else {
396 $tmp = -$gp+$offs[$i];
397 $newarr[$i]['offset'] = $tmp;
398 }
399 }
400 else { // Reflect
401 $newarr[$i] = $gradient_info['color'][$i];
402 $tmp = -$gp+$offs[$i];
403 $newarr[$i]['offset'] = $tmp;
404 }
405
406 // IF STILL INSIDE BOX OR STILL VALID
407 // Point on axis to test
408 $px1 = $x1 + ($x2-$x1)*$tmp;
409 $py1 = $y1 + ($y2-$y1)*$tmp;
410 // Get perpendicular axis
411 $alpha = atan2($y2-$y1, $x2-$x1);
412 $alpha += M_PI/2; // rotate 90 degrees
413 // Get arbitrary point to define line perpendicular to axis
414 $px2 = $px1+cos($alpha);
415 $py2 = $py1+sin($alpha);
416
417 $res1 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 0, 1); // $x=0 vert axis
418 $res2 = _testIntersect($px1, $py1, $px2, $py2, 1, 0, 1, 1); // $x=1 vert axis
419 $res3 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 1, 0); // $y=0 horiz axis
420 $res4 = _testIntersect($px1, $py1, $px2, $py2, 0, 1, 1, 1); // $y=1 horiz axis
421 if (!$res1 && !$res2 && !$res3 && !$res4) { $inside = false; }
422 }
423 for($i=($ns-1);$i>=0;$i--) {
424 if (isset($newarr[$i]['offset'])) array_unshift($gradient_info['color'], $newarr[$i]);
425 }
426 }
427 }
428
429 // mPDF 4.4.007 Gradient STOPs
430 $stops = count($gradient_info['color']);
431 if ($stops < 2) { return ''; }
432
433 // mPDF 5.0.042
434 $range = $gradient_info['color'][count($gradient_info['color'])-1]['offset']-$gradient_info['color'][0]['offset'];
435 $min = $gradient_info['color'][0]['offset'];
436
437 for ($i=0; $i<($stops); $i++) {
438 // mPDF 5.0.051
439 if (!$gradient_info['color'][$i]['color']) {
440 if ($gradient_info['colorspace']=='RGB') $gradient_info['color'][$i]['color'] = '0 0 0';
441 else if ($gradient_info['colorspace']=='Gray') $gradient_info['color'][$i]['color'] = '0';
442 else if ($gradient_info['colorspace']=='CMYK') $gradient_info['color'][$i]['color'] = '1 1 1 1';
443 }
444 $offset = ($gradient_info['color'][$i]['offset'] - $min)/$range;
445 $this->mpdf_ref->gradients[$n]['stops'][] = array(
446 'col' => $gradient_info['color'][$i]['color'],
447 'opacity' => $gradient_info['color'][$i]['opacity'],
448 'offset' => $offset);
449 if ($gradient_info['color'][$i]['opacity']<1) { $trans = true; }
450 }
451 $grx1 = $x1 + ($x2-$x1)*$gradient_info['color'][0]['offset'];
452 $gry1 = $y1 + ($y2-$y1)*$gradient_info['color'][0]['offset'];
453 $grx2 = $x1 + ($x2-$x1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
454 $gry2 = $y1 + ($y2-$y1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
455
456 $this->mpdf_ref->gradients[$n]['coords']=array($grx1, $gry1, $grx2, $gry2);
457
458 $this->mpdf_ref->gradients[$n]['colorspace'] = $gradient_info['colorspace']; // mPDF 5.0.051
459
460 $this->mpdf_ref->gradients[$n]['type'] = 2;
461 $this->mpdf_ref->gradients[$n]['fo'] = true;
462
463 $this->mpdf_ref->gradients[$n]['extend']=array('true','true');
464 if ($trans) {
465 $this->mpdf_ref->gradients[$n]['trans'] = true;
466 $return .= ' /TGS'.($n).' gs ';
467 }
468 $return .= ' /Sh'.($n).' sh ';
469 $return .= " Q\n";
470 }
471 else if ($gradient_info['type'] == 'radial'){
472 // mPDF 4.4.003
473 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
474 if ($w > $h) { $h = $w; }
475 else { $w = $h; }
476 if (isset($gradient_info['info']['x0'])) { $gradient_info['info']['x0'] = ($gradient_info['info']['x0']-$x_offset) / $w; }
477 if (isset($gradient_info['info']['y0'])) { $gradient_info['info']['y0'] = ($gradient_info['info']['y0']-$y_offset) / $h; }
478 if (isset($gradient_info['info']['x1'])) { $gradient_info['info']['x1'] = ($gradient_info['info']['x1']-$x_offset) / $w; }
479 if (isset($gradient_info['info']['y1'])) { $gradient_info['info']['y1'] = ($gradient_info['info']['y1']-$y_offset) / $h; }
480 if (isset($gradient_info['info']['r'])) { $gradient_info['info']['rx'] = $gradient_info['info']['r'] / $w; }
481 if (isset($gradient_info['info']['r'])) { $gradient_info['info']['ry'] = $gradient_info['info']['r'] / $h; }
482 }
483
484 if ($gradient_info['info']['x0'] || $gradient_info['info']['x0']===0) { $x0 = $gradient_info['info']['x0']; }
485 else { $x0 = 0.5; }
486 if ($gradient_info['info']['y0'] || $gradient_info['info']['y0']===0) { $y0 = $gradient_info['info']['y0']; }
487 else { $y0 = 0.5; }
488 if ($gradient_info['info']['rx'] || $gradient_info['info']['rx']===0) { $rx = $gradient_info['info']['rx']; }
489 else if ($gradient_info['info']['r'] || $gradient_info['info']['r']===0) { $rx = $gradient_info['info']['r']; }
490 else { $rx = 0.5; }
491 if ($gradient_info['info']['ry'] || $gradient_info['info']['ry']===0) { $ry = $gradient_info['info']['ry']; }
492 else if ($gradient_info['info']['r'] || $gradient_info['info']['r']===0) { $ry = $gradient_info['info']['r']; }
493 else { $ry = 0.5; }
494 if ($gradient_info['info']['x1'] || $gradient_info['info']['x1']===0) { $x1 = $gradient_info['info']['x1']; }
495 else { $x1 = $x0; }
496 if ($gradient_info['info']['y1'] || $gradient_info['info']['y1']===0) { $y1 = $gradient_info['info']['y1']; }
497 else { $y1 = $y0; }
498
499 if (stristr($x1, '%')!== false) { $x1 = ($x1+0)/100; }
500 if (stristr($x0, '%')!== false) { $x0 = ($x0+0)/100; }
501 if (stristr($y1, '%')!== false) { $y1 = ($y1+0)/100; }
502 if (stristr($y0, '%')!== false) { $y0 = ($y0+0)/100; }
503 if (stristr($rx, '%')!== false) { $rx = ($rx+0)/100; }
504 if (stristr($ry, '%')!== false) { $ry = ($ry+0)/100; }
505
506 // mPDF 5.0.043
507 $bboxw = $w;
508 $bboxh = $h;
509 $usex = $x_offset;
510 $usey = $y_offset;
511 $usew = $bboxw;
512 $useh = $bboxh;
513 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
514 $angle = rad2deg(atan2(($gradient_info['info']['y0']-$gradient_info['info']['y1']), ($gradient_info['info']['x0']-$gradient_info['info']['x1'])));
515 if ($angle < 0) { $angle += 360; }
516 else if ($angle > 360) { $angle -= 360; }
517 if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) {
518 if ($w >= $h) {
519 $y1 *= $h/$w ;
520 $y0 *= $h/$w ;
521 $rx *= $h/$w ;
522 $ry *= $h/$w ;
523 $usew = $useh = $bboxw;
524 }
525 else {
526 $x1 *= $w/$h ;
527 $x0 *= $w/$h ;
528 $rx *= $w/$h ;
529 $ry *= $w/$h ;
530 $usew = $useh = $bboxh;
531 }
532 }
533 }
534 $a = $usew; // width
535 $d = -$useh; // height
536 $e = $usex; // x- offset
537 $f = -$usey; // -y-offset
538
539 $r = $rx;
540
541
542 $return .= sprintf('%.3F 0 0 %.3F %.3F %.3F cm ', $a*$this->kp, $d*$this->kp, $e*$this->kp, $f*$this->kp);
543
544 // mPDF 5.0.039
545 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='objectboundingbox') {
546 if ($transformations) { $return .= $transformations; }
547 }
548
549 // x1 and y1 (fx, fy) should be inside the circle defined by x0 y0 and r else error in mPDF
550 while (pow(($x1-$x0),2) + pow(($y1 - $y0),2) >= pow($r,2)) { $r += 0.05; }
551
552 // mPDF 5.0.040
553 if ($spread=='R' || $spread=='F') { // Repeat / Reflect
554 $offs = array();
555 for($i=0;$i<$ns;$i++) {
556 $offs[$i] = $gradient_info['color'][$i]['offset'];
557 }
558 $gp = 0;
559 $inside=true;
560 while($inside) {
561 $gp++;
562 for($i=0;$i<$ns;$i++) {
563 if ($spread=='F' && ($gp % 2) == 1) { // Reflect
564 $gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][(($ns*($gp-1))+($ns-$i-1))];
565 $tmp = $gp+(1-$offs[($ns-$i-1)]) ;
566 $gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp;
567 }
568 else { // Reflect
569 $gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][$i];
570 $tmp = $gp+$offs[$i] ;
571 $gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp;
572 }
573 // IF STILL INSIDE BOX OR STILL VALID
574 // TEST IF circle (perimeter) intersects with
575 // or is enclosed
576 // Point on axis to test
577 $px = $x1 + ($x0-$x1)*$tmp;
578 $py = $y1 + ($y0-$y1)*$tmp;
579 $pr = $r*$tmp;
580 $res = _testIntersectCircle($px, $py, $pr);
581 if (!$res) { $inside = false; }
582 }
583 }
584 }
585
586 // mPDF 4.4.007 Gradient STOPs
587 $stops = count($gradient_info['color']);
588 if ($stops < 2) { return ''; }
589
590 // mPDF 5.0.043
591 $range = $gradient_info['color'][count($gradient_info['color'])-1]['offset']-$gradient_info['color'][0]['offset'];
592 $min = $gradient_info['color'][0]['offset'];
593
594 for ($i=0; $i<($stops); $i++) {
595 // mPDF 5.0.051
596 if (!$gradient_info['color'][$i]['color']) {
597 if ($gradient_info['colorspace']=='RGB') $gradient_info['color'][$i]['color'] = '0 0 0';
598 else if ($gradient_info['colorspace']=='Gray') $gradient_info['color'][$i]['color'] = '0';
599 else if ($gradient_info['colorspace']=='CMYK') $gradient_info['color'][$i]['color'] = '1 1 1 1';
600 }
601 $offset = ($gradient_info['color'][$i]['offset'] - $min)/$range;
602 $this->mpdf_ref->gradients[$n]['stops'][] = array(
603 'col' => $gradient_info['color'][$i]['color'],
604 'opacity' => $gradient_info['color'][$i]['opacity'],
605 'offset' => $offset);
606 if ($gradient_info['color'][$i]['opacity']<1) { $trans = true; }
607 }
608 $grx1 = $x1 + ($x0-$x1)*$gradient_info['color'][0]['offset'];
609 $gry1 = $y1 + ($y0-$y1)*$gradient_info['color'][0]['offset'];
610 $grx2 = $x1 + ($x0-$x1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
611 $gry2 = $y1 + ($y0-$y1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
612 $grir = $r*$gradient_info['color'][0]['offset'];
613 $grr = $r*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
614
615 $this->mpdf_ref->gradients[$n]['coords']=array($grx1, $gry1, $grx2, $gry2, abs($grr), abs($grir) );
616
617 $grx1 = $x1 + ($x0-$x1)*$first_stop;
618 $gry1 = $y1 + ($y0-$y1)*$first_stop;
619 $grx2 = $x1 + ($x0-$x1)*$last_stop;
620 $gry2 = $y1 + ($y0-$y1)*$last_stop;
621 $grir = $r*$first_stop;
622 $grr = $r*$last_stop;
623 $this->mpdf_ref->gradients[$n]['colorspace'] = $gradient_info['colorspace']; // mPDF 5.0.051
624
625 $this->mpdf_ref->gradients[$n]['type'] = 3;
626 $this->mpdf_ref->gradients[$n]['fo'] = true;
627
628 $this->mpdf_ref->gradients[$n]['extend']=array('true','true');
629 if ($trans) {
630 $this->mpdf_ref->gradients[$n]['trans'] = true;
631 $return .= ' /TGS'.($n).' gs ';
632 }
633 $return .= ' /Sh'.($n).' sh ';
634 $return .= " Q\n";
635
636
637 }
638
639 return $return;
640 }
641
642
643 function svgOffset ($attribs){
644 // save all <svg> tag attributes
645 $this->svg_attribs = $attribs;
646 if(isset($this->svg_attribs['viewBox'])) {
647 $vb = preg_split('/\s+/is', trim($this->svg_attribs['viewBox']));
648 if (count($vb)==4) {
649 $this->svg_info['x'] = $vb[0];
650 $this->svg_info['y'] = $vb[1];
651 $this->svg_info['w'] = $vb[2];
652 $this->svg_info['h'] = $vb[3];
653 // return; // mPDF 5.0.005
654 }
655 }
656
657 $svg_w = $this->mpdf_ref->ConvertSize($attribs['width']); // mm (interprets numbers as pixels)
658 $svg_h = $this->mpdf_ref->ConvertSize($attribs['height']); // mm
659
660 ///*
661 // mPDF 5.0.005
662 if ($this->svg_info['w']) { // if 'w' set by viewBox
663 if ($svg_w) { // if width also set, use these values to determine to set size of "pixel"
664 $this->kp *= ($svg_w/0.2645) / $this->svg_info['w'];
665 $this->kf = ($svg_w/0.2645) / $this->svg_info['w']; // mPDF 5.0.039
666 }
667 else if ($svg_h) {
668 $this->kp *= ($svg_h/0.2645) / $this->svg_info['h'];
669 $this->kf = ($svg_h/0.2645) / $this->svg_info['h']; // mPDF 5.0.039
670 }
671 return;
672 }
673 //*/
674
675 // Added to handle file without height or width specified
676 if (!$svg_w && !$svg_h) { $svg_w = $svg_h = $this->mpdf_ref->blk[$this->mpdf_ref->blklvl]['inner_width'] ; } // DEFAULT
677 if (!$svg_w) { $svg_w = $svg_h; }
678 if (!$svg_h) { $svg_h = $svg_w; }
679
680 $this->svg_info['x'] = 0;
681 $this->svg_info['y'] = 0;
682 $this->svg_info['w'] = $svg_w/0.2645; // mm->pixels
683 $this->svg_info['h'] = $svg_h/0.2645; // mm->pixels
684
685 }
686
687
688 //
689 // check if points are within svg, if not, set to max
690 function svg_overflow($x,$y)
691 {
692 $x2 = $x;
693 $y2 = $y;
694 if(isset($this->svg_attribs['overflow']))
695 {
696 if($this->svg_attribs['overflow'] == 'hidden')
697 {
698 // Not sure if this is supposed to strip off units, but since I dont use any I will omlt this step
699 $svg_w = preg_replace("/([0-9\.]*)(.*)/i","$1",$this->svg_attribs['width']);
700 $svg_h = preg_replace("/([0-9\.]*)(.*)/i","$1",$this->svg_attribs['height']);
701
702 // $xmax = floor($this->svg_attribs['width']);
703 $xmax = floor($svg_w);
704 $xmin = 0;
705 // $ymax = floor(($this->svg_attribs['height'] * -1));
706 $ymax = floor(($svg_h * -1));
707 $ymin = 0;
708
709 if($x > $xmax) $x2 = $xmax; // right edge
710 if($x < $xmin) $x2 = $xmin; // left edge
711 if($y < $ymax) $y2 = $ymax; // bottom
712 if($y > $ymin) $y2 = $ymin; // top
713
714 }
715 }
716
717
718 return array( 'x' => $x2, 'y' => $y2);
719 }
720
721
722
723 function svgDefineStyle($critere_style){
724
725 $tmp = count($this->svg_style)-1;
726 $current_style = $this->svg_style[$tmp];
727
728 unset($current_style['transformations']);
729
730 // TRANSFORM SCALE
731 $transformations = '';
732 if (isset($critere_style['transform'])){
733 preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)\((.*?)\)/is',$critere_style['transform'],$m);
734 if (count($m[0])) {
735 for($i=0; $i<count($m[0]); $i++) {
736 $c = strtolower($m[1][$i]);
737 $v = trim($m[2][$i]);
738 $vv = preg_split('/[ ,]+/',$v);
739 if ($c=='matrix' && count($vv)==6) {
740 // mPDF 5.0.039
741 // Note angle of rotation is reversed (from SVG to PDF), so vv[1] and vv[2] are negated
742 $transformations .= sprintf(' %.3F %.3F %.3F %.3F %.3F %.3F cm ', $vv[0], -$vv[1], -$vv[2], $vv[3], $vv[4]*$this->kp, -$vv[5]*$this->kp);
743
744 /*
745 // The long way of doing this??
746 // need to reverse angle of rotation from SVG to PDF
747 $sx=sqrt(pow($vv[0],2)+pow($vv[2],2));
748 if ($vv[0] < 0) { $sx *= -1; } // change sign
749 $sy=sqrt(pow($vv[1],2)+pow($vv[3],2));
750 if ($vv[3] < 0) { $sy *= -1; } // change sign
751
752 // rotation angle is
753 $t=atan2($vv[1],$vv[3]);
754 $t=atan2(-$vv[2],$vv[0]); // Should be the same value or skew has been applied
755
756 // Reverse angle
757 $t *= -1;
758
759 // Rebuild matrix
760 $ma = $sx * cos($t);
761 $mb = $sy * sin($t);
762 $mc = -$sx * sin($t);
763 $md = $sy * cos($t);
764
765 // $transformations .= sprintf(' %.3F %.3F %.3F %.3F %.3F %.3F cm ', $ma, $mb, $mc, $md, $vv[4]*$this->kp, -$vv[5]*$this->kp);
766 */
767
768 }
769 else if ($c=='translate' && count($vv)) {
770 $tm[4] = $vv[0];
771 if (count($vv)==2) { $t_y = -$vv[1]; }
772 else { $t_y = 0; }
773 $tm[5] = $t_y;
774 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $tm[4]*$this->kp, $tm[5]*$this->kp);
775 }
776 else if ($c=='scale' && count($vv)) {
777 if (count($vv)==2) { $s_y = $vv[1]; }
778 else { $s_y = $vv[0]; }
779 $tm[0] = $vv[0];
780 $tm[3] = $s_y;
781 $transformations .= sprintf(' %.3F 0 0 %.3F 0 0 cm ', $tm[0], $tm[3]);
782 }
783 else if ($c=='rotate' && count($vv)) {
784 $tm[0] = cos(deg2rad(-$vv[0]));
785 $tm[1] = sin(deg2rad(-$vv[0]));
786 $tm[2] = -$tm[1];
787 $tm[3] = $tm[0];
788 if (count($vv)==3) {
789 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $vv[1]*$this->kp, -$vv[2]*$this->kp);
790 }
791 $transformations .= sprintf(' %.3F %.3F %.3F %.3F 0 0 cm ', $tm[0], $tm[1], $tm[2], $tm[3]);
792 if (count($vv)==3) {
793 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', -$vv[1]*$this->kp, $vv[2]*$this->kp);
794 }
795 }
796 else if ($c=='skewx' && count($vv)) {
797 $tm[2] = tan(deg2rad(-$vv[0]));
798 $transformations .= sprintf(' 1 0 %.3F 1 0 0 cm ', $tm[2]);
799 }
800 else if ($c=='skewy' && count($vv)) {
801 $tm[1] = tan(deg2rad(-$vv[0]));
802 $transformations .= sprintf(' 1 %.3F 0 1 0 0 cm ', $tm[1]);
803 }
804
805 }
806 }
807 $current_style['transformations'] = $transformations;
808 }
809
810 if (isset($critere_style['style'])){
811 if (preg_match('/fill:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
812 $current_style['fill'] = '#'.str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT);
813 }
814 else { $tmp = preg_replace("/(.*)fill:\s*([a-z0-9#_()]*|none)(.*)/i","$2",$critere_style['style']); // mPDF 4.4.003
815 if ($tmp != $critere_style['style']){ $current_style['fill'] = $tmp; }
816 }
817
818 $tmp = preg_replace("/(.*)fill-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
819 if ($tmp != $critere_style['style']){ $current_style['fill-opacity'] = $tmp;}
820
821 $tmp = preg_replace("/(.*)fill-rule:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
822 if ($tmp != $critere_style['style']){ $current_style['fill-rule'] = $tmp;}
823
824 if (preg_match('/stroke:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
825 $current_style['stroke'] = '#'.str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT);
826 }
827 else { $tmp = preg_replace("/(.*)stroke:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
828 if ($tmp != $critere_style['style']){ $current_style['stroke'] = $tmp; }
829 }
830
831 $tmp = preg_replace("/(.*)stroke-linecap:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
832 if ($tmp != $critere_style['style']){ $current_style['stroke-linecap'] = $tmp;}
833
834 $tmp = preg_replace("/(.*)stroke-linejoin:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
835 if ($tmp != $critere_style['style']){ $current_style['stroke-linejoin'] = $tmp;}
836
837 $tmp = preg_replace("/(.*)stroke-miterlimit:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
838 if ($tmp != $critere_style['style']){ $current_style['stroke-miterlimit'] = $tmp;}
839
840 $tmp = preg_replace("/(.*)stroke-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
841 if ($tmp != $critere_style['style']){ $current_style['stroke-opacity'] = $tmp; }
842
843 $tmp = preg_replace("/(.*)stroke-width:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
844 if ($tmp != $critere_style['style']){ $current_style['stroke-width'] = $tmp;}
845
846 // mPDF 4.4.003
847 $tmp = preg_replace("/(.*)stroke-dasharray:\s*([a-z0-9., ]*|none)(.*)/i","$2",$critere_style['style']);
848 if ($tmp != $critere_style['style']){ $current_style['stroke-dasharray'] = $tmp;}
849
850 // mPDF 4.4.003
851 $tmp = preg_replace("/(.*)stroke-dashoffset:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
852 if ($tmp != $critere_style['style']){ $current_style['stroke-dashoffset'] = $tmp;}
853
854 }
855 if(isset($critere_style['fill'])){
856 $current_style['fill'] = $critere_style['fill'];
857 }
858
859 if(isset($critere_style['fill-opacity'])){
860 $current_style['fill-opacity'] = $critere_style['fill-opacity'];
861 }
862
863 if(isset($critere_style['fill-rule'])){
864 $current_style['fill-rule'] = $critere_style['fill-rule'];
865 }
866
867 if(isset($critere_style['stroke'])){
868 $current_style['stroke'] = $critere_style['stroke'];
869 }
870
871 if(isset($critere_style['stroke-linecap'])){
872 $current_style['stroke-linecap'] = $critere_style['stroke-linecap'];
873 }
874
875 if(isset($critere_style['stroke-linejoin'])){
876 $current_style['stroke-linejoin'] = $critere_style['stroke-linejoin'];
877 }
878
879 if(isset($critere_style['stroke-miterlimit'])){
880 $current_style['stroke-miterlimit'] = $critere_style['stroke-miterlimit'];
881 }
882
883 if(isset($critere_style['stroke-opacity'])){
884 $current_style['stroke-opacity'] = $critere_style['stroke-opacity'];
885 }
886
887 if(isset($critere_style['stroke-width'])){
888 $current_style['stroke-width'] = $critere_style['stroke-width'];
889 }
890
891 // mPDF 4.4.003
892 if(isset($critere_style['stroke-dasharray'])){
893 $current_style['stroke-dasharray'] = $critere_style['stroke-dasharray'];
894 }
895 if(isset($critere_style['stroke-dashoffset'])){
896 $current_style['stroke-dashoffset'] = $critere_style['stroke-dashoffset'];
897 }
898
899 // mPDF 4.4.005 Used as indirect setting for currentColor
900 if(isset($critere_style['color']) && $critere_style['color'] != 'inherit'){
901 $current_style['color'] = $critere_style['color'];
902 }
903
904 return $current_style;
905
906 }
907
908 //
909 // Cette fonction ecrit le style dans le stream svg.
910 function svgStyle($critere_style, $attribs, $element){
911 $path_style = '';
912 if (substr_count($critere_style['fill'],'url')>0){
913 //
914 // couleur degradé
915 $id_gradient = preg_replace("/url\(#([\w_]*)\)/i","$1",$critere_style['fill']);
916 if ($id_gradient != $critere_style['fill']) {
917 if (isset($this->svg_gradient[$id_gradient])) {
918 $fill_gradient = $this->svgGradient($this->svg_gradient[$id_gradient], $attribs, $element);
919 if ($fill_gradient) { // mPDF 4.4.003
920 $path_style = "q ";
921 $w = "W";
922 $style .= 'N';
923 }
924 }
925 }
926
927 }
928 // mPDF 4.4.005 Used as indirect setting for currentColor
929 else if (strtolower($critere_style['fill']) == 'currentcolor'){
930 $col = $this->mpdf_ref->ConvertColor($critere_style['color']);
931 if ($col) {
932 // mPDF 5.0.051
933 // mPDF 5.3.74
934 if ($col{0}==5) { $critere_style['fill-opacity'] = ord($col{4}/100); } // RGBa
935 if ($col{0}==6) { $critere_style['fill-opacity'] = ord($col{5}/100); } // CMYKa
936 $path_style .= $this->mpdf_ref->SetFColor($col, true).' '; // mPDF 5.0.051
937 $style .= 'F';
938 }
939 }
940 else if ($critere_style['fill'] != 'none'){
941 $col = $this->mpdf_ref->ConvertColor($critere_style['fill']);
942 if ($col) {
943 // mPDF 5.0.051
944 // mPDF 5.3.74
945 if ($col{0}==5) { $critere_style['fill-opacity'] = ord($col{4}/100); } // RGBa
946 if ($col{0}==6) { $critere_style['fill-opacity'] = ord($col{5}/100); } // CMYKa
947 $path_style .= $this->mpdf_ref->SetFColor($col, true).' '; // mPDF 5.0.051
948 $style .= 'F';
949 }
950 }
951
952 // mPDF 5.0.040
953 if (substr_count($critere_style['stroke'],'url')>0){
954 /*
955 // Cannot put a gradient on a "stroke" in PDF?
956 $id_gradient = preg_replace("/url\(#([\w_]*)\)/i","$1",$critere_style['stroke']);
957 if ($id_gradient != $critere_style['stroke']) {
958 if (isset($this->svg_gradient[$id_gradient])) {
959 $fill_gradient = $this->svgGradient($this->svg_gradient[$id_gradient], $attribs, $element);
960 if ($fill_gradient) {
961 $path_style = "q ";
962 $w = "W";
963 $style .= 'D';
964 }
965 }
966 }
967 */
968 }
969 // mPDF 4.4.005 Used as indirect setting for currentColor
970 else if (strtolower($critere_style['stroke']) == 'currentcolor'){
971 $col = $this->mpdf_ref->ConvertColor($critere_style['color']);
972 if ($col) {
973 // mPDF 5.0.051
974 // mPDF 5.3.74
975 if ($col{0}==5) { $critere_style['stroke-opacity'] = ord($col{4}/100); } // RGBa
976 if ($col{0}==6) { $critere_style['stroke-opacity'] = ord($col{5}/100); } // CMYKa
977 $path_style .= $this->mpdf_ref->SetDColor($col, true).' '; // mPDF 5.0.051
978 $style .= 'D';
979 $lw = $this->ConvertSVGSizePixels($critere_style['stroke-width']);
980 $path_style .= sprintf('%.3F w ',$lw*$this->kp);
981 }
982 }
983 else if ($critere_style['stroke'] != 'none'){
984 $col = $this->mpdf_ref->ConvertColor($critere_style['stroke']);
985 if ($col) {
986 // mPDF 5.0.051
987 // mPDF 5.3.74
988 if ($col{0}==5) { $critere_style['stroke-opacity'] = ord($col{4}/100); } // RGBa
989 if ($col{0}==6) { $critere_style['stroke-opacity'] = ord($col{5}/100); } // CMYKa
990 $path_style .= $this->mpdf_ref->SetDColor($col, true).' '; // mPDF 5.0.051
991 $style .= 'D';
992 $lw = $this->ConvertSVGSizePixels($critere_style['stroke-width']); // mPDF 4.4.003
993 $path_style .= sprintf('%.3F w ',$lw*$this->kp);
994 }
995 }
996
997
998 if ($critere_style['stroke'] != 'none'){
999 if ($critere_style['stroke-linejoin'] == 'miter'){
1000 $path_style .= ' 0 j ';
1001 }
1002 else if ($critere_style['stroke-linejoin'] == 'round'){
1003 $path_style .= ' 1 j ';
1004 }
1005 else if ($critere_style['stroke-linejoin'] == 'bevel'){
1006 $path_style .= ' 2 j ';
1007 }
1008
1009 if ($critere_style['stroke-linecap'] == 'butt'){
1010 $path_style .= ' 0 J ';
1011 }
1012 else if ($critere_style['stroke-linecap'] == 'round'){
1013 $path_style .= ' 1 J ';
1014 }
1015 else if ($critere_style['stroke-linecap'] == 'square'){
1016 $path_style .= ' 2 J ';
1017 }
1018
1019 if (isset($critere_style['stroke-miterlimit'])){
1020 if ($critere_style['stroke-miterlimit'] == 'none'){
1021 }
1022 else if (preg_match('/^[\d.]+$/',$critere_style['stroke-miterlimit'])) {
1023 $path_style .= sprintf('%.2F M ',$critere_style['stroke-miterlimit']);
1024 }
1025 }
1026 // mPDF 4.4.003
1027 if (isset($critere_style['stroke-dasharray'])){
1028 $off = 0;
1029 $d = preg_split('/[ ,]/',$critere_style['stroke-dasharray']);
1030 if (count($d) == 1 && $d[0]==0) {
1031 $path_style .= '[] 0 d ';
1032 }
1033 else {
1034 if (count($d) % 2 == 1) { $d = array_merge($d, $d); } // 5, 3, 1 => 5,3,1,5,3,1 OR 3 => 3,3
1035 $arr = '';
1036 for($i=0; $i<count($d); $i+=2) {
1037 $arr .= sprintf('%.3F %.3F ', $d[$i]*$this->kp, $d[$i+1]*$this->kp);
1038 }
1039 if (isset($critere_style['stroke-dashoffset'])){ $off = $critere_style['stroke-dashoffset'] + 0; }
1040 $path_style .= sprintf('[%s] %.3F d ', $arr, $off*$this->kp);
1041 }
1042 }
1043 }
1044
1045 // mPDF 4.4.003
1046 if ($critere_style['fill-rule']=='evenodd') { $fr = '*'; }
1047 else { $fr = ''; }
1048
1049 // mPDF 4.4.003
1050 if (isset($critere_style['fill-opacity'])) {
1051 $opacity = 1;
1052 if ($critere_style['fill-opacity'] == 0) { $opacity = 0; }
1053 else if ($critere_style['fill-opacity'] > 1) { $opacity = 1; }
1054 else if ($critere_style['fill-opacity'] > 0) { $opacity = $critere_style['fill-opacity']; }
1055 else if ($critere_style['fill-opacity'] < 0) { $opacity = 0; }
1056 $gs = $this->mpdf_ref->AddExtGState(array('ca'=>$opacity, 'BM'=>'/Normal'));
1057 $this->mpdf_ref->extgstates[$gs]['fo'] = true; // mPDF 5.0.039
1058 $path_style .= sprintf(' /GS%d gs ', $gs);
1059 }
1060
1061 // mPDF 4.4.003
1062 if (isset($critere_style['stroke-opacity'])) {
1063 $opacity = 1;
1064 if ($critere_style['stroke-opacity'] == 0) { $opacity = 0; }
1065 else if ($critere_style['stroke-opacity'] > 1) { $opacity = 1; }
1066 else if ($critere_style['stroke-opacity'] > 0) { $opacity = $critere_style['stroke-opacity']; }
1067 else if ($critere_style['stroke-opacity'] < 0) { $opacity = 0; }
1068 $gs = $this->mpdf_ref->AddExtGState(array('CA'=>$opacity, 'BM'=>'/Normal'));
1069 $this->mpdf_ref->extgstates[$gs]['fo'] = true; // mPDF 5.0.039
1070 $path_style .= sprintf(' /GS%d gs ', $gs);
1071 }
1072
1073 switch ($style){
1074 case 'F':
1075 $op = 'f';
1076 break;
1077 case 'FD':
1078 $op = 'B';
1079 break;
1080 case 'ND':
1081 $op = 'S';
1082 break;
1083 case 'D':
1084 $op = 'S';
1085 break;
1086 default:
1087 $op = 'n';
1088 }
1089
1090 // mPDF 5.0
1091 $prestyle = $path_style.' ';
1092 $poststyle = $w.' '. $op.$fr.' '.$fill_gradient."\n";
1093 return array($prestyle,$poststyle);
1094
1095 }
1096
1097 //
1098 // fonction retracant les <path />
1099 function svgPath($command, $arguments){
1100 $path_cmd = '';
1101 $newsubpath = false; // mPDF 4.4.003
1102 // mPDF 5.0.039
1103 $minl = $this->pathBBox[0];
1104 $mint = $this->pathBBox[1];
1105 $maxr = $this->pathBBox[2]+$this->pathBBox[0];
1106 $maxb = $this->pathBBox[3]+$this->pathBBox[1];
1107 // mPDF 5.0.040
1108 $start = array($this->xbase, -$this->ybase);
1109
1110 // mPDF 4.4.003
1111 preg_match_all('/[\-^]?[\d.]+(e[\-]?[\d]+){0,1}/i', $arguments, $a, PREG_SET_ORDER);
1112
1113 // if the command is a capital letter, the coords go absolute, otherwise relative
1114 if(strtolower($command) == $command) $relative = true;
1115 else $relative = false;
1116
1117
1118 $ile_argumentow = count($a);
1119
1120 // each command may have different needs for arguments [1 to 8]
1121
1122 switch(strtolower($command)){
1123 case 'm': // move
1124 for($i = 0; $i<$ile_argumentow; $i+=2){
1125 $x = $a[$i][0];
1126 $y = $a[$i+1][0];
1127 if($relative){
1128 $pdfx = ($this->xbase + $x);
1129 $pdfy = ($this->ybase - $y);
1130 $this->xbase += $x;
1131 $this->ybase += -$y;
1132 }
1133 else{
1134 $pdfx = $x;
1135 $pdfy = -$y ;
1136 $this->xbase = $x;
1137 $this->ybase = -$y;
1138 }
1139 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1140 // mPDF 5.0.039
1141 $minl = min($minl,$pdf_pt['x']);
1142 $maxr = max($maxr,$pdf_pt['x']);
1143 $mint = min($mint,-$pdf_pt['y']);
1144 $maxb = max($maxb,-$pdf_pt['y']);
1145 if($i == 0) $path_cmd .= sprintf('%.3F %.3F m ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1146 else $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1147 // mPDF 4.4.003 Save start points of subpath
1148 if ($this->subPathInit) {
1149 $this->spxstart = $this->xbase;
1150 $this->spystart = $this->ybase;
1151 $this->subPathInit = false;
1152 }
1153 }
1154 break;
1155 case 'l': // a simple line
1156 for($i = 0; $i<$ile_argumentow; $i+=2){
1157 $x = ($a[$i][0]);
1158 $y = ($a[$i+1][0]);
1159 if($relative){
1160 $pdfx = ($this->xbase + $x);
1161 $pdfy = ($this->ybase - $y);
1162 $this->xbase += $x;
1163 $this->ybase += -$y;
1164 }
1165 else{
1166 $pdfx = $x ;
1167 $pdfy = -$y ;
1168 $this->xbase = $x;
1169 $this->ybase = -$y;
1170 }
1171 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1172 // mPDF 5.0.039
1173 $minl = min($minl,$pdf_pt['x']);
1174 $maxr = max($maxr,$pdf_pt['x']);
1175 $mint = min($mint,-$pdf_pt['y']);
1176 $maxb = max($maxb,-$pdf_pt['y']);
1177 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1178 }
1179 break;
1180 case 'h': // a very simple horizontal line
1181 for($i = 0; $i<$ile_argumentow; $i++){
1182 $x = ($a[$i][0]);
1183 if($relative){
1184 $y = 0;
1185 $pdfx = ($this->xbase + $x) ;
1186 $pdfy = ($this->ybase - $y) ;
1187 $this->xbase += $x;
1188 $this->ybase += -$y;
1189 }
1190 else{
1191 $y = -$this->ybase;
1192 $pdfx = $x;
1193 $pdfy = -$y;
1194 $this->xbase = $x;
1195 $this->ybase = -$y;
1196 }
1197 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1198 // mPDF 5.0.039
1199 $minl = min($minl,$pdf_pt['x']);
1200 $maxr = max($maxr,$pdf_pt['x']);
1201 $mint = min($mint,-$pdf_pt['y']);
1202 $maxb = max($maxb,-$pdf_pt['y']);
1203 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1204 }
1205 break;
1206 case 'v': // the simplest line, vertical
1207 for($i = 0; $i<$ile_argumentow; $i++){
1208 $y = ($a[$i][0]);
1209 if($relative){
1210 $x = 0;
1211 $pdfx = ($this->xbase + $x);
1212 $pdfy = ($this->ybase - $y);
1213 $this->xbase += $x;
1214 $this->ybase += -$y;
1215 }
1216 else{
1217 $x = $this->xbase;
1218 $pdfx = $x;
1219 $pdfy = -$y;
1220 $this->xbase = $x;
1221 $this->ybase = -$y;
1222 }
1223 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1224 // mPDF 5.0.039
1225 $minl = min($minl,$pdf_pt['x']);
1226 $maxr = max($maxr,$pdf_pt['x']);
1227 $mint = min($mint,-$pdf_pt['y']);
1228 $maxb = max($maxb,-$pdf_pt['y']);
1229 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1230 }
1231 break;
1232 case 's': // bezier with first vertex equal first control
1233 // mPDF 4.4.003
1234 if (!($this->lastcommand == 'C' || $this->lastcommand == 'c' || $this->lastcommand == 'S' || $this->lastcommand == 's')) {
1235 $this->lastcontrolpoints = array(0,0);
1236 }
1237 for($i = 0; $i<$ile_argumentow; $i += 4){
1238 $x1 = $this->lastcontrolpoints[0];
1239 $y1 = $this->lastcontrolpoints[1];
1240 $x2 = ($a[$i][0]);
1241 $y2 = ($a[$i+1][0]);
1242 $x = ($a[$i+2][0]);
1243 $y = ($a[$i+3][0]);
1244 if($relative){
1245 $pdfx1 = ($this->xbase + $x1);
1246 $pdfy1 = ($this->ybase - $y1);
1247 $pdfx2 = ($this->xbase + $x2);
1248 $pdfy2 = ($this->ybase - $y2);
1249 $pdfx = ($this->xbase + $x);
1250 $pdfy = ($this->ybase - $y);
1251 $this->xbase += $x;
1252 $this->ybase += -$y;
1253 }
1254 else{
1255 $pdfx1 = $this->xbase + $x1;
1256 $pdfy1 = $this->ybase -$y1;
1257 $pdfx2 = $x2;
1258 $pdfy2 = -$y2;
1259 $pdfx = $x;
1260 $pdfy = -$y;
1261 $this->xbase = $x;
1262 $this->ybase = -$y;
1263 }
1264 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1265
1266 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1267
1268 // mPDF 5.0.040
1269 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1270 $bx = calc_bezier_bbox($start, $curves);
1271 $minl = min($minl,$bx[0]);
1272 $maxr = max($maxr,$bx[2]);
1273 $mint = min($mint,$bx[1]);
1274 $maxb = max($maxb,$bx[3]);
1275
1276 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1277 {
1278 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1279 }
1280 else
1281 {
1282 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1*$this->kp, $pdfy1*$this->kp, $pdfx2*$this->kp, $pdfy2*$this->kp, $pdfx*$this->kp, $pdfy*$this->kp);
1283 }
1284
1285 }
1286 break;
1287 case 'c': // bezier with second vertex equal second control
1288 for($i = 0; $i<$ile_argumentow; $i += 6){
1289 $x1 = ($a[$i][0]);
1290 $y1 = ($a[$i+1][0]);
1291 $x2 = ($a[$i+2][0]);
1292 $y2 = ($a[$i+3][0]);
1293 $x = ($a[$i+4][0]);
1294 $y = ($a[$i+5][0]);
1295
1296
1297 if($relative){
1298 $pdfx1 = ($this->xbase + $x1);
1299 $pdfy1 = ($this->ybase - $y1);
1300 $pdfx2 = ($this->xbase + $x2);
1301 $pdfy2 = ($this->ybase - $y2);
1302 $pdfx = ($this->xbase + $x);
1303 $pdfy = ($this->ybase - $y);
1304 $this->xbase += $x;
1305 $this->ybase += -$y;
1306 }
1307 else{
1308 $pdfx1 = $x1;
1309 $pdfy1 = -$y1;
1310 $pdfx2 = $x2;
1311 $pdfy2 = -$y2;
1312 $pdfx = $x;
1313 $pdfy = -$y;
1314 $this->xbase = $x;
1315 $this->ybase = -$y;
1316 }
1317 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1318 // $pdf_pt2 = $this->svg_overflow($pdfx2,$pdfy2);
1319 // $pdf_pt1 = $this->svg_overflow($pdfx1,$pdfy1);
1320 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1321
1322 // mPDF 5.0.040
1323 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1324 $bx = calc_bezier_bbox($start, $curves);
1325 $minl = min($minl,$bx[0]);
1326 $maxr = max($maxr,$bx[2]);
1327 $mint = min($mint,$bx[1]);
1328 $maxb = max($maxb,$bx[3]);
1329
1330 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1331 {
1332 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1333 }
1334 else
1335 {
1336 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1*$this->kp, $pdfy1*$this->kp, $pdfx2*$this->kp, $pdfy2*$this->kp, $pdfx*$this->kp, $pdfy*$this->kp);
1337 }
1338
1339 }
1340 break;
1341
1342 case 'q': // bezier quadratic avec point de control
1343 for($i = 0; $i<$ile_argumentow; $i += 4){
1344 $x1 = ($a[$i][0]);
1345 $y1 = ($a[$i+1][0]);
1346 $x = ($a[$i+2][0]);
1347 $y = ($a[$i+3][0]);
1348 if($relative){
1349 $pdfx = ($this->xbase + $x);
1350 $pdfy = ($this->ybase - $y);
1351
1352 $pdfx1 = ($this->xbase + ($x1*2/3));
1353 $pdfy1 = ($this->ybase - ($y1*2/3));
1354 // mPDF 4.4.003
1355 $pdfx2 = $pdfx1 + 1/3 *($x);
1356 $pdfy2 = $pdfy1 + 1/3 *(-$y) ;
1357
1358 $this->xbase += $x;
1359 $this->ybase += -$y;
1360 }
1361 else{
1362 $pdfx = $x;
1363 $pdfy = -$y;
1364
1365 $pdfx1 = ($this->xbase+(($x1-$this->xbase)*2/3));
1366 $pdfy1 = ($this->ybase-(($y1+$this->ybase)*2/3));
1367
1368 $pdfx2 = ($x+(($x1-$x)*2/3));
1369 $pdfy2 = (-$y-(($y1-$y)*2/3));
1370
1371 // mPDF 4.4.003
1372 $pdfx2 = $pdfx1 + 1/3 *($x - $this->xbase);
1373 $pdfy2 = $pdfy1 + 1/3 *(-$y - $this->ybase) ;
1374
1375 $this->xbase = $x;
1376 $this->ybase = -$y;
1377 }
1378 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1379
1380 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1381
1382 // mPDF 5.0.040
1383 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1384 $bx = calc_bezier_bbox($start, $curves);
1385 $minl = min($minl,$bx[0]);
1386 $maxr = max($maxr,$bx[2]);
1387 $mint = min($mint,$bx[1]);
1388 $maxb = max($maxb,$bx[3]);
1389
1390 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1391 {
1392 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1393 }
1394 else
1395 {
1396 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1*$this->kp, $pdfy1*$this->kp, $pdfx2*$this->kp, $pdfy2*$this->kp, $pdfx*$this->kp, $pdfy*$this->kp);
1397 }
1398 }
1399 break;
1400 case 't': // bezier quadratic avec point de control simetrique a lancien point de control
1401 // mPDF 4.4.003
1402 if (!($this->lastcommand == 'Q' || $this->lastcommand == 'q' || $this->lastcommand == 'T' || $this->lastcommand == 't')) {
1403 $this->lastcontrolpoints = array(0,0);
1404 }
1405 for($i = 0; $i<$ile_argumentow; $i += 2){
1406 $x = ($a[$i][0]);
1407 $y = ($a[$i+1][0]);
1408
1409 $x1 = $this->lastcontrolpoints[0];
1410 $y1 = $this->lastcontrolpoints[1];
1411
1412 if($relative){
1413 $pdfx = ($this->xbase + $x);
1414 $pdfy = ($this->ybase - $y);
1415
1416 $pdfx1 = ($this->xbase + ($x1)); // mPDF 4.4.003
1417 $pdfy1 = ($this->ybase - ($y1)); // mPDF 4.4.003
1418 // mPDF 4.4.003
1419 $pdfx2 = $pdfx1 + 1/3 *($x);
1420 $pdfy2 = $pdfy1 + 1/3 *(-$y) ;
1421
1422 $this->xbase += $x;
1423 $this->ybase += -$y;
1424 }
1425 else{
1426 $pdfx = $x;
1427 $pdfy = -$y;
1428
1429 $pdfx1 = ($this->xbase + ($x1)); // mPDF 4.4.003
1430 $pdfy1 = ($this->ybase - ($y1)); // mPDF 4.4.003
1431 // mPDF 4.4.003
1432 $pdfx2 = $pdfx1 + 1/3 *($x - $this->xbase);
1433 $pdfy2 = $pdfy1 + 1/3 *(-$y - $this->ybase) ;
1434
1435 $this->xbase = $x;
1436 $this->ybase = -$y;
1437 }
1438
1439 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1440
1441 // mPDF 5.0.040
1442 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1443 $bx = calc_bezier_bbox($start, $curves);
1444 $minl = min($minl,$bx[0]);
1445 $maxr = max($maxr,$bx[2]);
1446 $mint = min($mint,$bx[1]);
1447 $maxb = max($maxb,$bx[3]);
1448
1449 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1*$this->kp, $pdfy1*$this->kp, $pdfx2*$this->kp, $pdfy2*$this->kp, $pdfx*$this->kp, $pdfy*$this->kp);
1450 }
1451
1452 break;
1453 case 'a': // Elliptical arc
1454 for($i = 0; $i<$ile_argumentow; $i += 7){
1455 $rx = ($a[$i][0]);
1456 $ry = ($a[$i+1][0]);
1457 $angle = ($a[$i+2][0]); //x-axis-rotation
1458 $largeArcFlag = ($a[$i+3][0]);
1459 $sweepFlag = ($a[$i+4][0]);
1460 $x2 = ($a[$i+5][0]);
1461 $y2 = ($a[$i+6][0]);
1462 $x1 = $this->xbase;
1463 $y1 = -$this->ybase;
1464 if($relative){
1465 $x2 = $this->xbase + $x2;
1466 $y2 = -$this->ybase + $y2;
1467 $this->xbase += ($a[$i+5][0]);
1468 $this->ybase += -($a[$i+6][0]);
1469 }
1470 else{
1471 $this->xbase = $x2;
1472 $this->ybase = -$y2;
1473 }
1474 // mPDF 5.0.039 // mPDF 5.0.040
1475 list($pcmd, $bounds) = $this->Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag);
1476 $minl = min($minl,$x2,min($bounds[0]));
1477 $maxr = max($maxr,$x2,max($bounds[0]));
1478 $mint = min($mint,$y2,min($bounds[1]));
1479 $maxb = max($maxb,$y2,max($bounds[1]));
1480 $path_cmd .= $pcmd;
1481
1482 }
1483 break;
1484 case'z':
1485 $path_cmd .= 'h ';
1486 // mPDF 4.4.003
1487 $this->subPathInit = true;
1488 $newsubpath = true;
1489 $this->xbase = $this->spxstart;
1490 $this->ybase = $this->spystart;
1491 break;
1492 default:
1493 break;
1494 }
1495
1496 if (!$newsubpath) { $this->subPathInit = false; } // mPDF 4.4.003
1497 $this->lastcommand = $command;
1498 // mPDF 5.0.039
1499 $this->pathBBox[0] = $minl;
1500 $this->pathBBox[1] = $mint;
1501 $this->pathBBox[2] = $maxr - $this->pathBBox[0];
1502 $this->pathBBox[3] = $maxb - $this->pathBBox[1];
1503 return $path_cmd;
1504
1505 }
1506
1507 function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) {
1508
1509 // mPDF 5.0.040
1510 $bounds = array(0=>array($x1,$x2),1=>array($y1,$y2));
1511 // 1. Treat out-of-range parameters as described in
1512 // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
1513 // If the endpoints (x1, y1) and (x2, y2) are identical, then this
1514 // is equivalent to omitting the elliptical arc segment entirely
1515 if ($x1 == $x2 && $y1 == $y2) return array('', $bounds); // mPD 5.0.040
1516
1517 // If rX = 0 or rY = 0 then this arc is treated as a straight line
1518 // segment (a "lineto") joining the endpoints.
1519 if ($rx == 0.0 || $ry == 0.0) {
1520 // return array(Lineto(x2, y2), $bounds); // mPD 5.0.040
1521 }
1522
1523 // If rX or rY have negative signs, these are dropped; the absolute
1524 // value is used instead.
1525 if ($rx<0.0) $rx = -$rx;
1526 if ($ry<0.0) $ry = -$ry;
1527
1528 // 2. convert to center parameterization as shown in
1529 // http://www.w3.org/TR/SVG/implnote.html
1530 $sinPhi = sin(deg2rad($angle));
1531 $cosPhi = cos(deg2rad($angle));
1532
1533 $x1dash = $cosPhi * ($x1-$x2)/2.0 + $sinPhi * ($y1-$y2)/2.0;
1534 $y1dash = -$sinPhi * ($x1-$x2)/2.0 + $cosPhi * ($y1-$y2)/2.0;
1535
1536
1537 $numerator = $rx*$rx*$ry*$ry - $rx*$rx*$y1dash*$y1dash - $ry*$ry*$x1dash*$x1dash;
1538
1539 if ($numerator < 0.0) {
1540 // If rX , rY and are such that there is no solution (basically,
1541 // the ellipse is not big enough to reach from (x1, y1) to (x2,
1542 // y2)) then the ellipse is scaled up uniformly until there is
1543 // exactly one solution (until the ellipse is just big enough).
1544
1545 // -> find factor s, such that numerator' with rx'=s*rx and
1546 // ry'=s*ry becomes 0 :
1547 $s = sqrt(1.0 - $numerator/($rx*$rx*$ry*$ry));
1548
1549 $rx *= $s;
1550 $ry *= $s;
1551 $root = 0.0;
1552
1553 }
1554 else {
1555 $root = ($largeArcFlag == $sweepFlag ? -1.0 : 1.0) * sqrt( $numerator/($rx*$rx*$y1dash*$y1dash+$ry*$ry*$x1dash*$x1dash) );
1556 }
1557
1558 $cxdash = $root*$rx*$y1dash/$ry;
1559 $cydash = -$root*$ry*$x1dash/$rx;
1560
1561 $cx = $cosPhi * $cxdash - $sinPhi * $cydash + ($x1+$x2)/2.0;
1562 $cy = $sinPhi * $cxdash + $cosPhi * $cydash + ($y1+$y2)/2.0;
1563
1564
1565 $theta1 = $this->CalcVectorAngle(1.0, 0.0, ($x1dash-$cxdash)/$rx, ($y1dash-$cydash)/$ry);
1566 $dtheta = $this->CalcVectorAngle(($x1dash-$cxdash)/$rx, ($y1dash-$cydash)/$ry, (-$x1dash-$cxdash)/$rx, (-$y1dash-$cydash)/$ry);
1567 if (!$sweepFlag && $dtheta>0)
1568 $dtheta -= 2.0*M_PI;
1569 else if ($sweepFlag && $dtheta<0)
1570 $dtheta += 2.0*M_PI;
1571
1572 // 3. convert into cubic bezier segments <= 90deg
1573 $segments = ceil(abs($dtheta/(M_PI/2.0)));
1574 $delta = $dtheta/$segments;
1575 $t = 8.0/3.0 * sin($delta/4.0) * sin($delta/4.0) / sin($delta/2.0);
1576 $coords = array();
1577 for ($i = 0; $i < $segments; $i++) {
1578 $cosTheta1 = cos($theta1);
1579 $sinTheta1 = sin($theta1);
1580 $theta2 = $theta1 + $delta;
1581 $cosTheta2 = cos($theta2);
1582 $sinTheta2 = sin($theta2);
1583
1584 // a) calculate endpoint of the segment:
1585 $xe = $cosPhi * $rx*$cosTheta2 - $sinPhi * $ry*$sinTheta2 + $cx;
1586 $ye = $sinPhi * $rx*$cosTheta2 + $cosPhi * $ry*$sinTheta2 + $cy;
1587
1588 // b) calculate gradients at start/end points of segment:
1589 $dx1 = $t * ( - $cosPhi * $rx*$sinTheta1 - $sinPhi * $ry*$cosTheta1);
1590 $dy1 = $t * ( - $sinPhi * $rx*$sinTheta1 + $cosPhi * $ry*$cosTheta1);
1591
1592 $dxe = $t * ( $cosPhi * $rx*$sinTheta2 + $sinPhi * $ry*$cosTheta2);
1593 $dye = $t * ( $sinPhi * $rx*$sinTheta2 - $cosPhi * $ry*$cosTheta2);
1594
1595 // c) draw the cubic bezier:
1596 $coords[$i] = array(($x1+$dx1), ($y1+$dy1), ($xe+$dxe), ($ye+$dye), $xe, $ye);
1597
1598 // do next segment
1599 $theta1 = $theta2;
1600 $x1 = $xe;
1601 $y1 = $ye;
1602 }
1603 $path = ' ';
1604 foreach($coords AS $c) {
1605 $cpx1 = $c[0];
1606 $cpy1 = $c[1];
1607 $cpx2 = $c[2];
1608 $cpy2 = $c[3];
1609 $x2 = $c[4];
1610 $y2 = $c[5];
1611 $path .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $cpx1*$this->kp, -$cpy1*$this->kp, $cpx2*$this->kp, -$cpy2*$this->kp, $x2*$this->kp, -$y2*$this->kp) ."\n";
1612
1613 // mPDF 5.0.040
1614 $bounds[0][] = $c[4];
1615 $bounds[1][] = $c[5];
1616 }
1617 return array($path, $bounds); // mPD 5.0.040
1618 }
1619
1620
1621 function CalcVectorAngle($ux, $uy, $vx, $vy) {
1622 $ta = atan2($uy, $ux);
1623 $tb = atan2($vy, $vx);
1624 if ($tb >= $ta)
1625 return ($tb-$ta);
1626 return (6.28318530718 - ($ta-$tb));
1627 }
1628
1629
1630 // mPDF 4.4.003
1631 function ConvertSVGSizePixels($size=5,$maxsize='x'){
1632 // maxsize in pixels (user units) or 'y' or 'x'
1633 // e.g. $w = $this->ConvertSVGSizePixels($arguments['w'],$this->svg_info['w']*(25.4/$this->mpdf_ref->dpi));
1634 // usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
1635 // Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
1636 // For text $maxsize = Fontsize
1637 // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
1638
1639 if ($maxsize == 'y') { $maxsize = $this->svg_info['h']; }
1640 else if ($maxsize == 'x') { $maxsize = $this->svg_info['w']; }
1641 $maxsize *= (25.4/$this->mpdf_ref->dpi); // convert pixels to mm
1642 $fontsize=$this->mpdf_ref->FontSize;
1643 //Return as pixels
1644 $size = $this->mpdf_ref->ConvertSize($size,$maxsize,$fontsize,false) * 1/(25.4/$this->mpdf_ref->dpi);
1645 return $size;
1646 }
1647
1648 // mPDF 4.4.003
1649 function ConvertSVGSizePts($size=5){
1650 // usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
1651 // Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
1652 // For text $maxsize = Fontsize
1653 // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
1654 $maxsize=$this->mpdf_ref->FontSize;
1655 //Return as pts
1656 $size = $this->mpdf_ref->ConvertSize($size,$maxsize,false,true) * 72/25.4;
1657 return $size;
1658 }
1659
1660
1661 //
1662 // fonction retracant les <rect />
1663 function svgRect($arguments){
1664
1665 if ($arguments['h']==0 || $arguments['w']==0) { return ''; } // mPDF 4.4.003
1666
1667 $x = $this->ConvertSVGSizePixels($arguments['x'],'x'); // mPDF 4.4.003
1668 $y = $this->ConvertSVGSizePixels($arguments['y'],'y'); // mPDF 4.4.003
1669 $h = $this->ConvertSVGSizePixels($arguments['h'],'y'); // mPDF 4.4.003
1670 $w = $this->ConvertSVGSizePixels($arguments['w'],'x'); // mPDF 4.4.003
1671 $rx = $this->ConvertSVGSizePixels($arguments['rx'],'x'); // mPDF 4.4.003
1672 $ry = $this->ConvertSVGSizePixels($arguments['ry'],'y'); // mPDF 4.4.003
1673
1674 if ($rx > $w/2) { $rx = $w/2; } // mPDF 4.4.003
1675 if ($ry > $h/2) { $ry = $h/2; } // mPDF 4.4.003
1676
1677 if ($rx>0 and $ry == 0){$ry = $rx;}
1678 if ($ry>0 and $rx == 0){$rx = $ry;}
1679
1680 if ($rx == 0 and $ry == 0){
1681 // trace un rectangle sans angle arrondit
1682 $path_cmd = sprintf('%.3F %.3F m ', ($x*$this->kp), -($y*$this->kp));
1683 $path_cmd .= sprintf('%.3F %.3F l ', (($x+$w)*$this->kp), -($y*$this->kp));
1684 $path_cmd .= sprintf('%.3F %.3F l ', (($x+$w)*$this->kp), -(($y+$h)*$this->kp));
1685 $path_cmd .= sprintf('%.3F %.3F l ', ($x)*$this->kp, -(($y+$h)*$this->kp));
1686 $path_cmd .= sprintf('%.3F %.3F l h ', ($x*$this->kp), -($y*$this->kp));
1687
1688
1689 }
1690 else {
1691 // trace un rectangle avec les arrondit
1692 // les points de controle du bezier sont deduis grace a la constante kappa
1693 $kappa = 4*(sqrt(2)-1)/3;
1694
1695 $kx = $kappa*$rx;
1696 $ky = $kappa*$ry;
1697
1698 $path_cmd = sprintf('%.3F %.3F m ', ($x+$rx)*$this->kp, -$y*$this->kp);
1699 $path_cmd .= sprintf('%.3F %.3F l ', ($x+($w-$rx))*$this->kp, -$y*$this->kp);
1700 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x+($w-$rx+$kx))*$this->kp, -$y*$this->kp, ($x+$w)*$this->kp, (-$y+(-$ry+$ky))*$this->kp, ($x+$w)*$this->kp, (-$y+(-$ry))*$this->kp );
1701 $path_cmd .= sprintf('%.3F %.3F l ', ($x+$w)*$this->kp, (-$y+(-$h+$ry))*$this->kp);
1702 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x+$w)*$this->kp, (-$y+(-$h-$ky+$ry))*$this->kp, ($x+($w-$rx+$kx))*$this->kp, (-$y+(-$h))*$this->kp, ($x+($w-$rx))*$this->kp, (-$y+(-$h))*$this->kp );
1703
1704 $path_cmd .= sprintf('%.3F %.3F l ', ($x+$rx)*$this->kp, (-$y+(-$h))*$this->kp);
1705 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x+($rx-$kx))*$this->kp, (-$y+(-$h))*$this->kp, $x*$this->kp, (-$y+(-$h-$ky+$ry))*$this->kp, $x*$this->kp, (-$y+(-$h+$ry))*$this->kp );
1706 $path_cmd .= sprintf('%.3F %.3F l ', $x*$this->kp, (-$y+(-$ry))*$this->kp);
1707 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c h ', $x*$this->kp, (-$y+(-$ry+$ky))*$this->kp, ($x+($rx-$kx))*$this->kp, -$y*$this->kp, ($x+$rx)*$this->kp, -$y*$this->kp );
1708
1709
1710 }
1711 return $path_cmd;
1712 }
1713
1714 //
1715 // fonction retracant les <ellipse /> et <circle />
1716 // le cercle est tracé grave a 4 bezier cubic, les poitn de controles
1717 // sont deduis grace a la constante kappa * rayon
1718 function svgEllipse($arguments){
1719 if ($arguments['rx']==0 || $arguments['ry']==0) { return ''; } // mPDF 4.4.003
1720
1721 $kappa = 4*(sqrt(2)-1)/3;
1722
1723 $cx = $this->ConvertSVGSizePixels($arguments['cx'],'x'); // mPDF 4.4.003
1724 $cy = $this->ConvertSVGSizePixels($arguments['cy'],'y'); // mPDF 4.4.003
1725 $rx = $this->ConvertSVGSizePixels($arguments['rx'],'x'); // mPDF 4.4.003
1726 $ry = $this->ConvertSVGSizePixels($arguments['ry'],'y'); // mPDF 4.4.003
1727
1728 $x1 = $cx;
1729 $y1 = -$cy+$ry;
1730
1731 $x2 = $cx+$rx;
1732 $y2 = -$cy;
1733
1734 $x3 = $cx;
1735 $y3 = -$cy-$ry;
1736
1737 $x4 = $cx-$rx;
1738 $y4 = -$cy;
1739
1740 $path_cmd = sprintf('%.3F %.3F m ', $x1*$this->kp, $y1*$this->kp);
1741 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x1+($rx*$kappa))*$this->kp, $y1*$this->kp, $x2*$this->kp, ($y2+($ry*$kappa))*$this->kp, $x2*$this->kp, $y2*$this->kp);
1742 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x2*$this->kp, ($y2-($ry*$kappa))*$this->kp, ($x3+($rx*$kappa))*$this->kp, $y3*$this->kp, $x3*$this->kp, $y3*$this->kp);
1743 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', ($x3-($rx*$kappa))*$this->kp, $y3*$this->kp, $x4*$this->kp, ($y4-($ry*$kappa))*$this->kp, $x4*$this->kp, $y4*$this->kp);
1744 $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $x4*$this->kp, ($y4+($ry*$kappa))*$this->kp, ($x1-($rx*$kappa))*$this->kp, $y1*$this->kp, $x1*$this->kp, $y1*$this->kp);
1745 $path_cmd .= 'h ';
1746
1747 return $path_cmd;
1748
1749 }
1750
1751 //
1752 // fonction retracant les <polyline /> et les <line />
1753 function svgPolyline($arguments,$ispolyline=true){
1754 if ($ispolyline) {
1755 $xbase = $arguments[0] ;
1756 $ybase = - $arguments[1] ;
1757 }
1758 else {
1759 if ($arguments[0]==$arguments[2] && $arguments[1]==$arguments[3]) { return ''; } // mPDF 4.4.003 Zero length line
1760 $xbase = $this->ConvertSVGSizePixels($arguments[0],'x'); // mPDF 4.4.003
1761 $ybase = - $this->ConvertSVGSizePixels($arguments[1],'y'); // mPDF 4.4.003
1762 }
1763 $path_cmd = sprintf('%.3F %.3F m ', $xbase*$this->kp, $ybase*$this->kp);
1764 for ($i = 2; $i<count($arguments);$i += 2) {
1765 if ($ispolyline) {
1766 $tmp_x = $arguments[$i] ;
1767 $tmp_y = - $arguments[($i+1)] ;
1768 }
1769 else {
1770 $tmp_x = $this->ConvertSVGSizePixels($arguments[$i],'x') ; // mPDF 4.4.003
1771 $tmp_y = - $this->ConvertSVGSizePixels($arguments[($i+1)],'y') ; // mPDF 4.4.003
1772 }
1773 $path_cmd .= sprintf('%.3F %.3F l ', $tmp_x*$this->kp, $tmp_y*$this->kp);
1774 }
1775
1776 // $path_cmd .= 'h '; // ?? In error - don't close subpath here
1777 return $path_cmd;
1778
1779 }
1780
1781 //
1782 // fonction retracant les <polygone />
1783 function svgPolygon($arguments){
1784 $xbase = $arguments[0] ;
1785 $ybase = - $arguments[1] ;
1786 $path_cmd = sprintf('%.3F %.3F m ', $xbase*$this->kp, $ybase*$this->kp);
1787 for ($i = 2; $i<count($arguments);$i += 2) {
1788 $tmp_x = $arguments[$i] ;
1789 $tmp_y = - $arguments[($i+1)] ;
1790
1791 $path_cmd .= sprintf('%.3F %.3F l ', $tmp_x*$this->kp, $tmp_y*$this->kp);
1792
1793 }
1794 $path_cmd .= sprintf('%.3F %.3F l ', $xbase*$this->kp, $ybase*$this->kp);
1795 $path_cmd .= 'h ';
1796 return $path_cmd;
1797
1798 }
1799
1800 //
1801 // write string to image
1802 function svgText() {
1803 // $tmp = count($this->txt_style)-1;
1804 $current_style = array_pop($this->txt_style);
1805 $style = '';
1806 $render = -1;
1807 if(isset($this->txt_data[2]))
1808 {
1809 // select font
1810 $style .= ($current_style['font-weight'] == 'bold')?'B':'';
1811 $style .= ($current_style['font-style'] == 'italic')?'I':'';
1812 $size = $current_style['font-size']*$this->kf; // mPDF 5.0.039
1813
1814 // mPDF 5.0
1815 $current_style['font-family'] = $this->mpdf_ref->SetFont($current_style['font-family'],$style,$size,false);
1816 $this->mpdf_ref->CurrentFont['fo'] = true; // mPDF 5.0.039
1817
1818
1819 // mPDF 5.0.041
1820 $opacitystr = '';
1821 $opacity = 1;
1822 if (isset($current_style['fill-opacity'])) {
1823 if ($current_style['fill-opacity'] == 0) { $opacity = 0; }
1824 else if ($current_style['fill-opacity'] > 1) { $opacity = 1; }
1825 else if ($current_style['fill-opacity'] > 0) { $opacity = $current_style['fill-opacity']; }
1826 else if ($current_style['fill-opacity'] < 0) { $opacity = 0; }
1827 }
1828 $gs = $this->mpdf_ref->AddExtGState(array('ca'=>$opacity, 'BM'=>'/Normal'));
1829 $this->mpdf_ref->extgstates[$gs]['fo'] = true; // mPDF 5.0.039
1830 $opacitystr = sprintf(' /GS%d gs ', $gs);
1831
1832 // mPDF 5.0.051
1833 $fillstr = '';
1834 if (isset($current_style['fill']) && $current_style['fill']!='none') {
1835 $col = $this->mpdf_ref->ConvertColor($current_style['fill']);
1836 // mPDF 5.0.051
1837 $fillstr = $this->mpdf_ref->SetFColor($col, true);
1838 $render = "0"; // Fill (only)
1839 }
1840 $strokestr = '';
1841 if (isset($current_style['stroke-width']) && $current_style['stroke-width']>0 && $current_style['stroke']!='none') {
1842 $scol = $this->mpdf_ref->ConvertColor($current_style['stroke']);
1843 if ($scol) {
1844 $strokestr .= $this->mpdf_ref->SetDColor($scol, true).' '; // mPDF 5.0.051
1845 }
1846 $linewidth = $this->ConvertSVGSizePixels($current_style['stroke-width']);
1847 if ($linewidth > 0) {
1848 $strokestr .= sprintf('%.3F w 1 J 1 j ',$linewidth*$this->kp);
1849 if ($render == -1) { $render = "1"; } // stroke only
1850 else { $render = "2"; } // fill and stroke
1851 }
1852 }
1853 if ($render == -1) { return ''; }
1854
1855 $x = $this->ConvertSVGSizePixels($this->txt_data[0],'x'); // mPDF 4.4.003
1856 $y = $this->ConvertSVGSizePixels($this->txt_data[1],'y'); // mPDF 4.4.003
1857 $txt = $this->txt_data[2];
1858
1859 // mPDF 4.4.003
1860 $txt = preg_replace('/\f/','',$txt);
1861 $txt = preg_replace('/\r/','',$txt);
1862 $txt = preg_replace('/\n/',' ',$txt);
1863 $txt = preg_replace('/\t/',' ',$txt);
1864 $txt = preg_replace("/[ ]+/u",' ',$txt);
1865
1866 $txt = trim($txt);
1867
1868 $txt = $this->mpdf_ref->purify_utf8_text($txt);
1869 if ($this->mpdf_ref->text_input_as_HTML) {
1870 $txt = $this->mpdf_ref->all_entities_to_utf8($txt);
1871 }
1872
1873 // mPDF 5.0
1874 if ($this->mpdf_ref->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mpdf_ref->mb_enc,'UTF-8'); }
1875 if (preg_match("/([".$this->mpdf_ref->pregRTLchars."])/u", $txt)) { $this->mpdf_ref->biDirectional = true; } // mPDF 4.4.003
1876
1877 $this->mpdf_ref->magic_reverse_dir($txt, true, 'ltr'); // mPDF 5.0.054
1878 $this->mpdf_ref->ConvertIndic($txt);
1879
1880
1881 if ($current_style['text-anchor']=='middle') {
1882 $tw = $this->mpdf_ref->GetStringWidth($txt)*_MPDFK/2; // mPDF 4.4.003 // mPDF 5.4.09
1883 }
1884 else if ($current_style['text-anchor']=='end') {
1885 $tw = $this->mpdf_ref->GetStringWidth($txt)*_MPDFK; // mPDF 4.4.003 // mPDF 5.4.09
1886 }
1887 else $tw = 0;
1888
1889 if (!$this->mpdf_ref->usingCoreFont) {
1890 $this->mpdf_ref->UTF8StringToArray($txt); // mPDF 5.0 adds chars to subset list
1891 $txt= $this->mpdf_ref->UTF8ToUTF16BE($txt, false);
1892 }
1893 $txt='('.$this->mpdf_ref->_escape($txt).')';
1894 $this->mpdf_ref->CurrentFont['used']= true;
1895
1896 $pdfx = $x - $tw/$this->kp; // mPDF 4.4.009
1897 $pdfy = -$y ;
1898 $xbase = $x;
1899 $ybase = -$y;
1900
1901 // mPDF 5.0.041
1902 // mPDF 5.0.051
1903 $path_cmd = sprintf('q BT /F%d %s %.3F Tf %.3F %.3F Td %s Tr %s %s %s Tj ET Q ',$this->mpdf_ref->CurrentFont['i'],$opacitystr, $this->mpdf_ref->FontSizePt,$pdfx*$this->kp,$pdfy*$this->kp,$render,$fillstr,$strokestr,$txt)."\n";
1904 unset($this->txt_data[0], $this->txt_data[1],$this->txt_data[2]);
1905
1906 // mPDF 5.4.12
1907 if (isset($current_style['font-size-parent'])) {
1908 $this->mpdf_ref->SetFontSize($current_style['font-size-parent']);
1909 }
1910 }
1911 else
1912 {
1913 return ' ';
1914 }
1915 // $path_cmd .= 'h '; // mPDF 5.0
1916 return $path_cmd;
1917 }
1918
1919
1920 function svgDefineTxtStyle($critere_style)
1921 {
1922 // get copy of current/default txt style, and modify it with supplied attributes
1923 $tmp = count($this->txt_style)-1;
1924 $current_style = $this->txt_style[$tmp];
1925 if (isset($critere_style['style'])){
1926 if (preg_match('/fill:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
1927 $current_style['fill'] = '#'.str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT);
1928 }
1929 else { $tmp = preg_replace("/(.*)fill:\s*([a-z0-9#_()]*|none)(.*)/i","$2",$critere_style['style']);
1930 if ($tmp != $critere_style['style']){ $current_style['fill'] = $tmp; }
1931 }
1932
1933 $tmp = preg_replace("/(.*)fill-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1934 if ($tmp != $critere_style['style']){ $current_style['fill-opacity'] = $tmp;}
1935
1936 $tmp = preg_replace("/(.*)fill-rule:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1937 if ($tmp != $critere_style['style']){ $current_style['fill-rule'] = $tmp;}
1938
1939 if (preg_match('/stroke:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
1940 $current_style['stroke'] = '#'.str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT).str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT);
1941 }
1942 else { $tmp = preg_replace("/(.*)stroke:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1943 if ($tmp != $critere_style['style']){ $current_style['stroke'] = $tmp; }
1944 }
1945
1946 $tmp = preg_replace("/(.*)stroke-linecap:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1947 if ($tmp != $critere_style['style']){ $current_style['stroke-linecap'] = $tmp;}
1948
1949 $tmp = preg_replace("/(.*)stroke-linejoin:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1950 if ($tmp != $critere_style['style']){ $current_style['stroke-linejoin'] = $tmp;}
1951
1952 $tmp = preg_replace("/(.*)stroke-miterlimit:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1953 if ($tmp != $critere_style['style']){ $current_style['stroke-miterlimit'] = $tmp;}
1954
1955 $tmp = preg_replace("/(.*)stroke-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1956 if ($tmp != $critere_style['style']){ $current_style['stroke-opacity'] = $tmp; }
1957
1958 $tmp = preg_replace("/(.*)stroke-width:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1959 if ($tmp != $critere_style['style']){ $current_style['stroke-width'] = $tmp;}
1960
1961 $tmp = preg_replace("/(.*)stroke-dasharray:\s*([a-z0-9., ]*|none)(.*)/i","$2",$critere_style['style']);
1962 if ($tmp != $critere_style['style']){ $current_style['stroke-dasharray'] = $tmp;}
1963
1964 $tmp = preg_replace("/(.*)stroke-dashoffset:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1965 if ($tmp != $critere_style['style']){ $current_style['stroke-dashoffset'] = $tmp;}
1966
1967 // mPDF 5.0.039
1968 $tmp = preg_replace("/(.*)font-family:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1969 if ($tmp != $critere_style['style']){ $critere_style['font-family'] = $tmp;}
1970
1971 $tmp = preg_replace("/(.*)font-size:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1972 if ($tmp != $critere_style['style']){ $critere_style['font-size'] = $tmp;}
1973
1974 $tmp = preg_replace("/(.*)font-weight:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1975 if ($tmp != $critere_style['style']){ $critere_style['font-weight'] = $tmp;}
1976
1977 $tmp = preg_replace("/(.*)font-style:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1978 if ($tmp != $critere_style['style']){ $critere_style['font-style'] = $tmp;}
1979
1980 }
1981
1982 if (isset($critere_style['font'])){
1983
1984 // [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]?<'font-size'> [ / <'line-height'> ]? <'font-family'> ]
1985
1986 $tmp = preg_replace("/(.*)(italic|oblique)(.*)/i","$2",$critere_style['font']);
1987 if ($tmp != $critere_style['font']){
1988 if($tmp == 'oblique'){
1989 $tmp = 'italic';
1990 }
1991 $current_style['font-style'] = $tmp;
1992 }
1993 $tmp = preg_replace("/(.*)(bold|bolder)(.*)/i","$2",$critere_style['font']);
1994 if ($tmp != $critere_style['font']){
1995 if($tmp == 'bolder'){
1996 $tmp = 'bold';
1997 }
1998 $current_style['font-weight'] = $tmp;
1999 }
2000
2001 // select digits not followed by percent sign nor preceeded by forward slash
2002 $tmp = preg_replace("/(.*)\b(\d+)[\b|\/](.*)/i","$2",$critere_style['font']);
2003 if ($tmp != $critere_style['font']){
2004 $current_style['font-size'] = $this->ConvertSVGSizePts($tmp);
2005 $this->mpdf_ref->SetFont('','',$current_style['font-size'],false);
2006 }
2007
2008 }
2009
2010 if(isset($critere_style['fill'])){
2011 $current_style['fill'] = $critere_style['fill'];
2012 }
2013 if(isset($critere_style['stroke'])){
2014 $current_style['stroke'] = $critere_style['stroke'];
2015 }
2016 if(isset($critere_style['stroke-width'])){
2017 $current_style['stroke-width'] = $critere_style['stroke-width'];
2018 }
2019
2020 if(isset($critere_style['font-style'])){
2021 if(strtolower($critere_style['font-style']) == 'oblique')
2022 {
2023 $critere_style['font-style'] = 'italic';
2024 }
2025 $current_style['font-style'] = $critere_style['font-style'];
2026 }
2027
2028 if(isset($critere_style['font-weight'])){
2029 if(strtolower($critere_style['font-weight']) == 'bolder')
2030 {
2031 $critere_style['font-weight'] = 'bold';
2032 }
2033 $current_style['font-weight'] = $critere_style['font-weight'];
2034 }
2035
2036 if(isset($critere_style['font-size'])){
2037 // mPDF 5.4.12
2038 if (strpos($critere_style['font-size'], '%')!==false) {
2039 $current_style['font-size-parent'] = $current_style['font-size'];
2040 }
2041 $current_style['font-size'] = $this->ConvertSVGSizePts($critere_style['font-size']);
2042 $this->mpdf_ref->SetFont('','',$current_style['font-size'],false);
2043 }
2044
2045 if(isset($critere_style['font-family'])){
2046 $v = $critere_style['font-family'];
2047 $aux_fontlist = explode(",",$v);
2048 $found = 0;
2049 foreach($aux_fontlist AS $f) {
2050 $fonttype = trim($f);
2051 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
2052 $fonttype = preg_replace('/ /','',$fonttype);
2053 $v = strtolower(trim($fonttype));
2054 if (isset($this->mpdf_ref->fonttrans[$v]) && $this->mpdf_ref->fonttrans[$v]) { $v = $this->mpdf_ref->fonttrans[$v]; }
2055 if ((!$this->mpdf_ref->usingCoreFont && in_array($v,$this->mpdf_ref->available_unifonts)) ||
2056 ($this->mpdf_ref->usingCoreFont && in_array($v,array('courier','times','helvetica','arial'))) ||
2057 in_array($v, array('sjis','uhc','big5','gb'))) {
2058 $current_style['font-family'] = $v;
2059 $found = 1;
2060 break;
2061 }
2062 }
2063 if (!$found) {
2064 foreach($aux_fontlist AS $f) {
2065 $fonttype = trim($f);
2066 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
2067 $fonttype = preg_replace('/ /','',$fonttype);
2068 $v = strtolower(trim($fonttype));
2069 if (isset($this->mpdf_ref->fonttrans[$v]) && $this->mpdf_ref->fonttrans[$v]) { $v = $this->mpdf_ref->fonttrans[$v]; }
2070 if (in_array($v,$this->mpdf_ref->sans_fonts) || in_array($v,$this->mpdf_ref->serif_fonts) || in_array($v,$this->mpdf_ref->mono_fonts) ) {
2071 $current_style['font-family'] = $v;
2072 break;
2073 }
2074 }
2075 }
2076 }
2077
2078 if(isset($critere_style['text-anchor'])){
2079 $current_style['text-anchor'] = $critere_style['text-anchor'];
2080 }
2081
2082 // add current style to text style array (will remove it later after writing text to svg_string)
2083 array_push($this->txt_style,$current_style);
2084 }
2085
2086
2087
2088 //
2089 // fonction ajoutant un gradient
2090 function svgAddGradient($id,$array_gradient){
2091
2092 $this->svg_gradient[$id] = $array_gradient;
2093
2094 }
2095 //
2096 // Ajoute une couleur dans le gradient correspondant
2097
2098 //
2099 // function ecrivant dans le svgstring
2100 function svgWriteString($content){
2101
2102 $this->svg_string .= $content;
2103
2104 }
2105
2106
2107
2108 // analise le svg et renvoie aux fonctions precedente our le traitement
2109 function ImageSVG($data){
2110 $this->svg_info = array();
2111
2112 // mPDF 4.4.006
2113 if (preg_match('/<!ENTITY/si',$data)) {
2114 // Get User-defined entities
2115 preg_match_all('/<!ENTITY\s+([a-z]+)\s+\"(.*?)\">/si',$data, $ent);
2116 // Replace entities
2117 for ($i=0; $i<count($ent[0]); $i++) {
2118 $data = preg_replace('/&'.preg_quote($ent[1][$i],'/').';/is', $ent[2][$i], $data);
2119 }
2120 }
2121
2122
2123 // mPDF 4.4.003
2124 if (preg_match('/xlink:href=/si',$data)) {
2125 // Get links
2126 preg_match_all('/(<(linearGradient|radialgradient)[^>]*)xlink:href=["\']#(.*?)["\'](.*?)\/>/si',$data, $links);
2127 if (count($links[0])) { $links[5] = array(); } // mPDF 4.5.010
2128 // Delete links from data - keeping in $links
2129 for ($i=0; $i<count($links[0]); $i++) {
2130 $links[5][$i] = 'tmpLink'.RAND(100000,9999999); // mPDF 4.5.010
2131 $data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', '<MYLINKS'.$links[5][$i].'>' , $data); // mPDF 4.5.010
2132 }
2133 // Get targets
2134 preg_match_all('/<(linearGradient|radialgradient)([^>]*)id=["\'](.*?)["\'](.*?)>(.*?)<\/(linearGradient|radialgradient)>/si',$data, $m);
2135 $targets = array();
2136 $stops = array();
2137 // keeping in $targets
2138 for ($i=0; $i<count($m[0]); $i++) {
2139 $stops[$m[3][$i]] = $m[5][$i];
2140 }
2141 // Add back links this time as targets (gradients)
2142 for ($i=0; $i<count($links[0]); $i++) {
2143 $def = $links[1][$i] .' '.$links[4][$i].'>'. $stops[$links[3][$i]].'</'.$links[2][$i] .'>' ; // mPDF 4.5.010
2144 $data = preg_replace('/<MYLINKS'.$links[5][$i].'>/is', $def , $data); // mPDF 4.5.010
2145 }
2146 }
2147 // mPDF 4.4.003 - Removes <pattern>
2148 $data = preg_replace('/<pattern.*?<\/pattern>/is', '', $data);
2149 // mPDF 4.4.003 - Removes <marker>
2150 $data = preg_replace('/<marker.*?<\/marker>/is', '', $data);
2151
2152 $this->svg_info['data'] = $data;
2153
2154 $this->svg_string = '';
2155
2156 //
2157 // chargement unique des fonctions
2158 if(!function_exists("xml_svg2pdf_start")){ // mPDF 5.3.76
2159
2160 function xml_svg2pdf_start($parser, $name, $attribs){
2161 //
2162 // definition
2163 global $svg_class, $last_gradid;
2164
2165 // mPDF 4.4.003
2166 $svg_class->xbase = 0;
2167 $svg_class->ybase = 0;
2168 switch (strtolower($name)){
2169
2170 // mPDF 5.0.039 - Don't output stuff inside <defs>
2171 case 'defs':
2172 $svg_class->inDefs = true;
2173 return;
2174
2175 case 'svg':
2176 $svg_class->svgOffset($attribs);
2177 break;
2178
2179 case 'path':
2180 $path = $attribs['d'];
2181 // mPDF 5.6.65
2182 preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $path, $commands, PREG_SET_ORDER);
2183 $path_cmd = '';
2184 $svg_class->subPathInit = true;
2185 // mPDF 5.0.039
2186 $svg_class->pathBBox = array(999999,999999,-999999,-999999);
2187 foreach($commands as $c){
2188 if(count($c)==3 || $c[2]==''){
2189 list($tmp, $command, $arguments) = $c;
2190 }
2191 else{
2192 list($tmp, $command) = $c;
2193 $arguments = '';
2194 }
2195
2196 $path_cmd .= $svg_class->svgPath($command, $arguments);
2197 }
2198 // mPDF 5.0.039
2199 if ($svg_class->pathBBox[2]==-1999998) { $svg_class->pathBBox[2] = 100; }
2200 if ($svg_class->pathBBox[3]==-1999998) { $svg_class->pathBBox[3] = 100; }
2201 if ($svg_class->pathBBox[0]==999999) { $svg_class->pathBBox[0] = 0; }
2202 if ($svg_class->pathBBox[1]==999999) { $svg_class->pathBBox[1] = 0; }
2203 $critere_style = $attribs;
2204 unset($critere_style['d']);
2205 $path_style = $svg_class->svgDefineStyle($critere_style);
2206 break;
2207
2208 case 'rect':
2209 if (!isset($attribs['x'])) {$attribs['x'] = 0;}
2210 if (!isset($attribs['y'])) {$attribs['y'] = 0;}
2211 if (!isset($attribs['rx'])) {$attribs['rx'] = 0;}
2212 if (!isset($attribs['ry'])) {$attribs['ry'] = 0;}
2213 $arguments = array(
2214 'x' => $attribs['x'],
2215 'y' => $attribs['y'],
2216 'w' => $attribs['width'],
2217 'h' => $attribs['height'],
2218 'rx' => $attribs['rx'],
2219 'ry' => $attribs['ry']
2220 );
2221 $path_cmd = $svg_class->svgRect($arguments);
2222 $critere_style = $attribs;
2223 unset($critere_style['x'],$critere_style['y'],$critere_style['rx'],$critere_style['ry'],$critere_style['height'],$critere_style['width']);
2224 $path_style = $svg_class->svgDefineStyle($critere_style);
2225 break;
2226
2227 case 'circle':
2228 if (!isset($attribs['cx'])) {$attribs['cx'] = 0;}
2229 if (!isset($attribs['cy'])) {$attribs['cy'] = 0;}
2230 $arguments = array(
2231 'cx' => $attribs['cx'],
2232 'cy' => $attribs['cy'],
2233 'rx' => $attribs['r'],
2234 'ry' => $attribs['r']
2235 );
2236 $path_cmd = $svg_class->svgEllipse($arguments);
2237 $critere_style = $attribs;
2238 unset($critere_style['cx'],$critere_style['cy'],$critere_style['r']);
2239 $path_style = $svg_class->svgDefineStyle($critere_style);
2240 break;
2241
2242 case 'ellipse':
2243 if (!isset($attribs['cx'])) {$attribs['cx'] = 0;}
2244 if (!isset($attribs['cy'])) {$attribs['cy'] = 0;}
2245 $arguments = array(
2246 'cx' => $attribs['cx'],
2247 'cy' => $attribs['cy'],
2248 'rx' => $attribs['rx'],
2249 'ry' => $attribs['ry']
2250 );
2251 $path_cmd = $svg_class->svgEllipse($arguments);
2252 $critere_style = $attribs;
2253 unset($critere_style['cx'],$critere_style['cy'],$critere_style['rx'],$critere_style['ry']);
2254 $path_style = $svg_class->svgDefineStyle($critere_style);
2255 break;
2256
2257 case 'line':
2258 $arguments = array($attribs['x1'],$attribs['y1'],$attribs['x2'],$attribs['y2']);
2259 $path_cmd = $svg_class->svgPolyline($arguments,false); // mPDF 4.4.003
2260 $critere_style = $attribs;
2261 unset($critere_style['x1'],$critere_style['y1'],$critere_style['x2'],$critere_style['y2']);
2262 $path_style = $svg_class->svgDefineStyle($critere_style);
2263 break;
2264
2265 case 'polyline':
2266 $path = $attribs['points'];
2267 preg_match_all('/[0-9\-\.]*/',$path, $tmp, PREG_SET_ORDER);
2268 $arguments = array();
2269 for ($i=0;$i<count($tmp);$i++){
2270 if ($tmp[$i][0] !=''){
2271 array_push($arguments, $tmp[$i][0]);
2272 }
2273 }
2274 $path_cmd = $svg_class->svgPolyline($arguments);
2275 $critere_style = $attribs;
2276 unset($critere_style['points']);
2277 $path_style = $svg_class->svgDefineStyle($critere_style);
2278 break;
2279
2280 case 'polygon':
2281 $path = $attribs['points'];
2282 preg_match_all('/([\-]*[0-9\.]+)/',$path, $tmp);
2283 $arguments = array();
2284 for ($i=0;$i<count($tmp[0]);$i++){
2285 if ($tmp[0][$i] !=''){
2286 array_push($arguments, $tmp[0][$i]);
2287 }
2288 }
2289 $path_cmd = $svg_class->svgPolygon($arguments);
2290 // definition du style de la forme:
2291 $critere_style = $attribs;
2292 unset($critere_style['points']);
2293 $path_style = $svg_class->svgDefineStyle($critere_style);
2294 break;
2295
2296 case 'lineargradient':
2297 $tmp_gradient = array(
2298 'type' => 'linear',
2299 'info' => array(
2300 'x1' => $attribs['x1'],
2301 'y1' => $attribs['y1'],
2302 'x2' => $attribs['x2'],
2303 'y2' => $attribs['y2']
2304 ),
2305 'transform' => $attribs['gradientTransform'],
2306 'units' => $attribs['gradientUnits'], /* mPDF 4.4.003 */
2307 'spread' => $attribs['spreadMethod'], /* mPDF 5.0.040 */
2308 'color' => array()
2309 );
2310
2311 $last_gradid = $attribs['id'];
2312 $svg_class->svgAddGradient($attribs['id'],$tmp_gradient);
2313 break;
2314
2315 case 'radialgradient':
2316 $tmp_gradient = array(
2317 'type' => 'radial',
2318 'info' => array(
2319 'x0' => $attribs['cx'],
2320 'y0' => $attribs['cy'],
2321 'x1' => $attribs['fx'],
2322 'y1' => $attribs['fy'],
2323 'r' => $attribs['r']
2324 ),
2325 'transform' => $attribs['gradientTransform'],
2326 'units' => $attribs['gradientUnits'], /* mPDF 4.4.003 */
2327 'spread' => $attribs['spreadMethod'], /* mPDF 5.0.040 */
2328 'color' => array()
2329 );
2330
2331 $last_gradid = $attribs['id'];
2332
2333 $svg_class->svgAddGradient($attribs['id'],$tmp_gradient);
2334
2335 break;
2336
2337 case 'stop':
2338 if (!$last_gradid) break;
2339 // mPDF 4.4.003 // mPDF 5.0.040
2340 if (isset($attribs['style']) AND preg_match('/stop-color:\s*([^;]*)/i',$attribs['style'],$m)) {
2341 $color = trim($m[1]);
2342 } else if (isset($attribs['stop-color'])) {
2343 $color = $attribs['stop-color'];
2344 }
2345 $col = $svg_class->mpdf_ref->ConvertColor($color);
2346
2347 // mPDF 5.0.051
2348 // mPDF 5.3.74
2349 if ($col{0}==3 || $col{0}==5) { // RGB
2350 $color_final = sprintf('%.3F %.3F %.3F',ord($col{1})/255,ord($col{2})/255,ord($col{3})/255);
2351 $svg_class->svg_gradient[$last_gradid]['colorspace']='RGB';
2352 }
2353 else if ($col{0}==4 || $col{0}==6) { // CMYK
2354 $color_final = sprintf('%.3F %.3F %.3F %.3F',ord($col{1})/100,ord($col{2})/100,ord($col{3})/100,ord($col{4})/100);
2355 $svg_class->svg_gradient[$last_gradid]['colorspace']='CMYK';
2356 }
2357 else if ($col{0}==1) { // Grayscale
2358 $color_final = sprintf('%.3F',ord($col{1})/255);
2359 $svg_class->svg_gradient[$last_gradid]['colorspace']='Gray';
2360 }
2361
2362
2363 // mPDF 5.0.020
2364 $stop_opacity = 1;
2365 // mPDF 4.4.003
2366 if (isset($attribs['style']) AND preg_match('/stop-opacity:\s*([0-9.]*)/i',$attribs['style'],$m)) {
2367 $stop_opacity = $m[1];
2368 } else if (isset($attribs['stop-opacity'])) {
2369 $stop_opacity = $attribs['stop-opacity'];
2370 }
2371 // mPDF 5.0.051
2372 // mPDF 5.3.74
2373 else if ($col{0}==5) { // RGBa
2374 $stop_opacity = ord($col{4}/100);
2375 }
2376 else if ($col{0}==6) { // CMYKa
2377 $stop_opacity = ord($col{5}/100);
2378 }
2379
2380 $tmp_color = array(
2381 'color' => $color_final,
2382 'offset' => $attribs['offset'],
2383 'opacity' => $stop_opacity
2384 );
2385 array_push($svg_class->svg_gradient[$last_gradid]['color'],$tmp_color);
2386 break;
2387
2388
2389 case 'a':
2390 if (isset($attribs['xlink:href'])) {
2391 unset($attribs['xlink:href']); // this should be a hyperlink
2392 // not handled like a xlink:href in other elements
2393 } // then continue like a <g>
2394 case 'g':
2395 $array_style = $svg_class->svgDefineStyle($attribs);
2396 if ($array_style['transformations']) {
2397 $svg_class->svgWriteString(' q '.$array_style['transformations']);
2398 }
2399 array_push($svg_class->svg_style,$array_style);
2400
2401 $svg_class->svgDefineTxtStyle($attribs); // mPDF 4.4.003
2402
2403 break;
2404
2405 case 'text':
2406 // mPDF 4.4.003
2407 $array_style = $svg_class->svgDefineStyle($attribs);
2408 if ($array_style['transformations']) {
2409 $svg_class->svgWriteString(' q '.$array_style['transformations']);
2410 }
2411 array_push($svg_class->svg_style,$array_style);
2412
2413 $svg_class->txt_data = array();
2414 $svg_class->txt_data[0] = $attribs['x'];
2415 $svg_class->txt_data[1] = $attribs['y'];
2416 $critere_style = $attribs;
2417 unset($critere_style['x'], $critere_style['y']);
2418 $svg_class->svgDefineTxtStyle($critere_style);
2419 break;
2420 }
2421
2422 //
2423 //insertion des path et du style dans le flux de donné general.
2424 if (isset($path_cmd) && $path_cmd) { // mPDF 4.4.003
2425 // mPDF 5.0
2426 list($prestyle,$poststyle) = $svg_class->svgStyle($path_style, $attribs, strtolower($name));
2427 if ($path_style['transformations']) { // transformation on an element
2428 $svg_class->svgWriteString(" q ".$path_style['transformations']. " $prestyle $path_cmd $poststyle" . " Q\n");
2429 }
2430 else {
2431 $svg_class->svgWriteString("$prestyle $path_cmd $poststyle\n");
2432 }
2433 }
2434 }
2435
2436 function characterData($parser, $data)
2437 {
2438 global $svg_class;
2439 if(isset($svg_class->txt_data[2])) {
2440 $svg_class->txt_data[2] .= $data;
2441 }
2442 else {
2443 $svg_class->txt_data[2] = $data;
2444 }
2445 }
2446
2447
2448 function xml_svg2pdf_end($parser, $name){
2449 global $svg_class;
2450 switch($name){
2451
2452 case "g":
2453 case "a":
2454 $tmp = count($svg_class->svg_style)-1;
2455 $current_style = $svg_class->svg_style[$tmp];
2456 if ($current_style['transformations']) {
2457 $svg_class->svgWriteString(" Q\n");
2458 }
2459 array_pop($svg_class->svg_style);
2460
2461 array_pop($svg_class->txt_style); // mPDF 4.4.003
2462
2463 break;
2464 case 'radialgradient':
2465 case 'lineargradient':
2466 $last_gradid = '';
2467 break;
2468 case "text":
2469 $path_cmd = $svg_class->svgText();
2470 // echo 'path >> '.$path_cmd."<br><br>";
2471 // echo "style >> ".$get_style[1]."<br><br>";
2472 $svg_class->svgWriteString($path_cmd);
2473 // mPDF 4.4.003
2474 $tmp = count($svg_class->svg_style)-1;
2475 $current_style = $svg_class->svg_style[$tmp];
2476 if ($current_style['transformations']) {
2477 $svg_class->svgWriteString(" Q\n");
2478 }
2479 array_pop($svg_class->svg_style);
2480
2481 break;
2482 }
2483 // mPDF 5.0.039 - Don't output stuff inside <defs>
2484 if ($name == 'defs') {
2485 $svg_class->inDefs = false;
2486 }
2487
2488 }
2489
2490 }
2491
2492 $svg2pdf_xml='';
2493 global $svg_class;
2494 $svg_class = $this;
2495 // mPDF 5.0.039 - Don't output stuff inside <defs>
2496 $svg_class->inDefs = false;
2497 $svg2pdf_xml_parser = xml_parser_create("utf-8");
2498 xml_parser_set_option($svg2pdf_xml_parser, XML_OPTION_CASE_FOLDING, false);
2499 xml_set_element_handler($svg2pdf_xml_parser, "xml_svg2pdf_start", "xml_svg2pdf_end");
2500 xml_set_character_data_handler($svg2pdf_xml_parser, "characterData");
2501 xml_parse($svg2pdf_xml_parser, $data);
2502 // mPDF 4.4.003
2503 if ($this->svg_error) { return false; }
2504 else {
2505 return array('x'=>$this->svg_info['x']*$this->kp,'y'=>-$this->svg_info['y']*$this->kp,'w'=>$this->svg_info['w']*$this->kp,'h'=>-$this->svg_info['h']*$this->kp,'data'=>$svg_class->svg_string);
2506 }
2507
2508 }
2509
2510 }
2511
2512 // END OF CLASS
2513
2514
2515 // mPDF 5.0.040
2516 function calc_bezier_bbox($start, $c) {
2517 $P0 = array($start[0],$start[1]);
2518 $P1 = array($c[0],$c[1]);
2519 $P2 = array($c[2],$c[3]);
2520 $P3 = array($c[4],$c[5]);
2521 $bounds = array();
2522 $bounds[0][] = $P0[0];
2523 $bounds[1][] = $P0[1];
2524 $bounds[0][] = $P3[0];
2525 $bounds[1][] = $P3[1];
2526 for ($i=0;$i<=1;$i++) {
2527 $b = 6 * $P0[$i] - 12 * $P1[$i] + 6 * $P2[$i];
2528 $a = -3 * $P0[$i] + 9 * $P1[$i] - 9 * $P2[$i] + 3 * $P3[$i];
2529 $c = 3 * $P1[$i] - 3 * $P0[$i];
2530 if ($a == 0) {
2531 if ($b == 0) { continue; }
2532 $t = -$c / $b;
2533 if ($t>0 && $t<1) {
2534 $bounds[$i][] = (pow((1-$t),3) * $P0[$i] + 3 * pow((1-$t),2) * $t * $P1[$i] + 3 * (1-$t) * pow($t,2) * $P2[$i] + pow($t,3) * $P3[$i]);
2535 }
2536 continue;
2537 }
2538 $b2ac = pow($b, 2) - 4 * $c * $a;
2539 if ($b2ac < 0) { continue; }
2540 $t1 = (-$b + sqrt($b2ac))/(2 * $a);
2541 if ($t1>0 && $t1<1) {
2542 $bounds[$i][] = (pow((1-$t1),3) * $P0[$i] + 3 * pow((1-$t1),2) * $t1 * $P1[$i] + 3 * (1-$t1) * pow($t1,2) * $P2[$i] + pow($t1,3) * $P3[$i]);
2543 }
2544 $t2 = (-$b - sqrt($b2ac))/(2 * $a);
2545 if ($t2>0 && $t2<1) {
2546 $bounds[$i][] = (pow((1-$t2),3) * $P0[$i] + 3 * pow((1-$t2),2) * $t2 * $P1[$i] + 3 * (1-$t2) * pow($t2,2) * $P2[$i] + pow($t2,3) * $P3[$i]);
2547 }
2548 }
2549 $x = min($bounds[0]);
2550 $x2 = max($bounds[0]);
2551 $y = min($bounds[1]);
2552 $y2 = max($bounds[1]);
2553 return array($x, $y, $x2, $y2);
2554 }
2555
2556 // mPDF 5.0.040
2557 function _testIntersectCircle($cx, $cy, $cr) {
2558 // Tests whether a circle fully encloses a rectangle 0,0,1,1
2559 // to see if any further radial gradients need adding (SVG)
2560 // If centre of circle is inside 0,0,1,1 square
2561 if ($cx >= 0 && $cx <= 1 && $cy >= 0 && $cy <= 1) {
2562 $maxd = 1.5;
2563 }
2564 // distance to four corners
2565 else {
2566 $d1 = sqrt(pow(($cy-0),2) + pow(($cx-0),2));
2567 $d2 = sqrt(pow(($cy-1),2) + pow(($cx-0),2));
2568 $d3 = sqrt(pow(($cy-0),2) + pow(($cx-1),2));
2569 $d4 = sqrt(pow(($cy-1),2) + pow(($cx-1),2));
2570 $maxd = max($d1,$d2,$d3,$d4);
2571 }
2572 if ($cr < $maxd) { return true; }
2573 else { return false; }
2574 }
2575
2576 // mPDF 5.0.040
2577 function _testIntersect($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4) {
2578 // Tests whether line (x1, y1) and (x2, y2) [a gradient axis (perpendicular)]
2579 // intersects with a specific line segment (x3, y3) and (x4, y4)
2580 $a1 = $y2-$y1;
2581 $b1 = $x1-$x2;
2582 $c1 = $a1*$x1+$b1*$y1;
2583 $a2 = $y4-$y3;
2584 $b2 = $x3-$x4;
2585 $c2 = $a2*$x3+$b2*$y3;
2586 $det = $a1*$b2 - $a2*$b1;
2587 if($det == 0){ //Lines are parallel
2588 return false;
2589 }
2590 else{
2591 $x = ($b2*$c1 - $b1*$c2)/$det;
2592 $y = ($a1*$c2 - $a2*$c1)/$det;
2593 if ($x >= $x3 && $x <= $x4 && $y >= $y3 && $y <= $y4) { return true; }
2594 }
2595 return false;
2596 }
2597
2598
2599
2600 ?>