]> git.immae.eu Git - github/wallabag/wallabag.git/blob - inc/3rdparty/libraries/mpdf/classes/svg.php
removed unnecessary fonts
[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+)\)/i',$critere_style['style'], $m)) { // mPDF 5.7.2
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 // mPDF 5.7.2
819 if (preg_match("/[^-]opacity:\s*([a-z0-9.]*|none)/i",$critere_style['style'], $m) ||
820 preg_match("/^opacity:\s*([a-z0-9.]*|none)/i",$critere_style['style'], $m)) {
821 $current_style['fill-opacity'] = $m[1];
822 $current_style['stroke-opacity'] = $m[1];
823 }
824
825 $tmp = preg_replace("/(.*)fill-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
826 if ($tmp != $critere_style['style']){ $current_style['fill-opacity'] = $tmp;}
827
828 $tmp = preg_replace("/(.*)fill-rule:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
829 if ($tmp != $critere_style['style']){ $current_style['fill-rule'] = $tmp;}
830
831 if (preg_match('/stroke:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
832 $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);
833 }
834 else { $tmp = preg_replace("/(.*)stroke:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
835 if ($tmp != $critere_style['style']){ $current_style['stroke'] = $tmp; }
836 }
837
838 $tmp = preg_replace("/(.*)stroke-linecap:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
839 if ($tmp != $critere_style['style']){ $current_style['stroke-linecap'] = $tmp;}
840
841 $tmp = preg_replace("/(.*)stroke-linejoin:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
842 if ($tmp != $critere_style['style']){ $current_style['stroke-linejoin'] = $tmp;}
843
844 $tmp = preg_replace("/(.*)stroke-miterlimit:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
845 if ($tmp != $critere_style['style']){ $current_style['stroke-miterlimit'] = $tmp;}
846
847 $tmp = preg_replace("/(.*)stroke-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
848 if ($tmp != $critere_style['style']){ $current_style['stroke-opacity'] = $tmp; }
849
850 $tmp = preg_replace("/(.*)stroke-width:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
851 if ($tmp != $critere_style['style']){ $current_style['stroke-width'] = $tmp;}
852
853 // mPDF 4.4.003
854 $tmp = preg_replace("/(.*)stroke-dasharray:\s*([a-z0-9., ]*|none)(.*)/i","$2",$critere_style['style']);
855 if ($tmp != $critere_style['style']){ $current_style['stroke-dasharray'] = $tmp;}
856
857 // mPDF 4.4.003
858 $tmp = preg_replace("/(.*)stroke-dashoffset:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
859 if ($tmp != $critere_style['style']){ $current_style['stroke-dashoffset'] = $tmp;}
860
861 }
862 // mPDF 5.7.2
863 if(isset($critere_style['opacity'])){
864 $current_style['fill-opacity'] = $critere_style['opacity'];
865 $current_style['stroke-opacity'] = $critere_style['opacity'];
866 }
867
868 if(isset($critere_style['fill'])){
869 $current_style['fill'] = $critere_style['fill'];
870 }
871
872 if(isset($critere_style['fill-opacity'])){
873 $current_style['fill-opacity'] = $critere_style['fill-opacity'];
874 }
875
876 if(isset($critere_style['fill-rule'])){
877 $current_style['fill-rule'] = $critere_style['fill-rule'];
878 }
879
880 if(isset($critere_style['stroke'])){
881 $current_style['stroke'] = $critere_style['stroke'];
882 }
883
884 if(isset($critere_style['stroke-linecap'])){
885 $current_style['stroke-linecap'] = $critere_style['stroke-linecap'];
886 }
887
888 if(isset($critere_style['stroke-linejoin'])){
889 $current_style['stroke-linejoin'] = $critere_style['stroke-linejoin'];
890 }
891
892 if(isset($critere_style['stroke-miterlimit'])){
893 $current_style['stroke-miterlimit'] = $critere_style['stroke-miterlimit'];
894 }
895
896 if(isset($critere_style['stroke-opacity'])){
897 $current_style['stroke-opacity'] = $critere_style['stroke-opacity'];
898 }
899
900 if(isset($critere_style['stroke-width'])){
901 $current_style['stroke-width'] = $critere_style['stroke-width'];
902 }
903
904 // mPDF 4.4.003
905 if(isset($critere_style['stroke-dasharray'])){
906 $current_style['stroke-dasharray'] = $critere_style['stroke-dasharray'];
907 }
908 if(isset($critere_style['stroke-dashoffset'])){
909 $current_style['stroke-dashoffset'] = $critere_style['stroke-dashoffset'];
910 }
911
912 // mPDF 4.4.005 Used as indirect setting for currentColor
913 if(isset($critere_style['color']) && $critere_style['color'] != 'inherit'){
914 $current_style['color'] = $critere_style['color'];
915 }
916
917 return $current_style;
918
919 }
920
921 //
922 // Cette fonction ecrit le style dans le stream svg.
923 function svgStyle($critere_style, $attribs, $element){
924 $path_style = '';
925 if (substr_count($critere_style['fill'],'url')>0 && $element != 'line'){
926 //
927 // couleur degradé
928 $id_gradient = preg_replace("/url\(#([\w_]*)\)/i","$1",$critere_style['fill']);
929 if ($id_gradient != $critere_style['fill']) {
930 if (isset($this->svg_gradient[$id_gradient])) {
931 $fill_gradient = $this->svgGradient($this->svg_gradient[$id_gradient], $attribs, $element);
932 if ($fill_gradient) { // mPDF 4.4.003
933 $path_style = "q ";
934 $w = "W";
935 $style .= 'N';
936 }
937 }
938 }
939
940 }
941 // mPDF 4.4.005 Used as indirect setting for currentColor
942 else if (strtolower($critere_style['fill']) == 'currentcolor' && $element != 'line'){
943 $col = $this->mpdf_ref->ConvertColor($critere_style['color']);
944 if ($col) {
945 // mPDF 5.0.051
946 // mPDF 5.3.74
947 if ($col{0}==5) { $critere_style['fill-opacity'] = ord($col{4}/100); } // RGBa
948 if ($col{0}==6) { $critere_style['fill-opacity'] = ord($col{5}/100); } // CMYKa
949 $path_style .= $this->mpdf_ref->SetFColor($col, true).' '; // mPDF 5.0.051
950 $style .= 'F';
951 }
952 }
953 else if ($critere_style['fill'] != 'none' && $element != 'line'){
954 $col = $this->mpdf_ref->ConvertColor($critere_style['fill']);
955 if ($col) {
956 // mPDF 5.0.051
957 // mPDF 5.3.74
958 if ($col{0}==5) { $critere_style['fill-opacity'] = ord($col{4}/100); } // RGBa
959 if ($col{0}==6) { $critere_style['fill-opacity'] = ord($col{5}/100); } // CMYKa
960 $path_style .= $this->mpdf_ref->SetFColor($col, true).' '; // mPDF 5.0.051
961 $style .= 'F';
962 }
963 }
964
965 // mPDF 5.0.040
966 if (substr_count($critere_style['stroke'],'url')>0){
967 /*
968 // Cannot put a gradient on a "stroke" in PDF?
969 $id_gradient = preg_replace("/url\(#([\w_]*)\)/i","$1",$critere_style['stroke']);
970 if ($id_gradient != $critere_style['stroke']) {
971 if (isset($this->svg_gradient[$id_gradient])) {
972 $fill_gradient = $this->svgGradient($this->svg_gradient[$id_gradient], $attribs, $element);
973 if ($fill_gradient) {
974 $path_style = "q ";
975 $w = "W";
976 $style .= 'D';
977 }
978 }
979 }
980 */
981 }
982 // mPDF 4.4.005 Used as indirect setting for currentColor
983 else if (strtolower($critere_style['stroke']) == 'currentcolor'){
984 $col = $this->mpdf_ref->ConvertColor($critere_style['color']);
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']);
993 $path_style .= sprintf('%.3F w ',$lw*$this->kp);
994 }
995 }
996 else if ($critere_style['stroke'] != 'none'){
997 $col = $this->mpdf_ref->ConvertColor($critere_style['stroke']);
998 if ($col) {
999 // mPDF 5.0.051
1000 // mPDF 5.3.74
1001 if ($col{0}==5) { $critere_style['stroke-opacity'] = ord($col{4}/100); } // RGBa
1002 if ($col{0}==6) { $critere_style['stroke-opacity'] = ord($col{5}/100); } // CMYKa
1003 $path_style .= $this->mpdf_ref->SetDColor($col, true).' '; // mPDF 5.0.051
1004 $style .= 'D';
1005 $lw = $this->ConvertSVGSizePixels($critere_style['stroke-width']); // mPDF 4.4.003
1006 $path_style .= sprintf('%.3F w ',$lw*$this->kp);
1007 }
1008 }
1009
1010
1011 if ($critere_style['stroke'] != 'none'){
1012 if ($critere_style['stroke-linejoin'] == 'miter'){
1013 $path_style .= ' 0 j ';
1014 }
1015 else if ($critere_style['stroke-linejoin'] == 'round'){
1016 $path_style .= ' 1 j ';
1017 }
1018 else if ($critere_style['stroke-linejoin'] == 'bevel'){
1019 $path_style .= ' 2 j ';
1020 }
1021
1022 if ($critere_style['stroke-linecap'] == 'butt'){
1023 $path_style .= ' 0 J ';
1024 }
1025 else if ($critere_style['stroke-linecap'] == 'round'){
1026 $path_style .= ' 1 J ';
1027 }
1028 else if ($critere_style['stroke-linecap'] == 'square'){
1029 $path_style .= ' 2 J ';
1030 }
1031
1032 if (isset($critere_style['stroke-miterlimit'])){
1033 if ($critere_style['stroke-miterlimit'] == 'none'){
1034 }
1035 else if (preg_match('/^[\d.]+$/',$critere_style['stroke-miterlimit'])) {
1036 $path_style .= sprintf('%.2F M ',$critere_style['stroke-miterlimit']);
1037 }
1038 }
1039 // mPDF 4.4.003
1040 if (isset($critere_style['stroke-dasharray'])){
1041 $off = 0;
1042 $d = preg_split('/[ ,]/',$critere_style['stroke-dasharray']);
1043 if (count($d) == 1 && $d[0]==0) {
1044 $path_style .= '[] 0 d ';
1045 }
1046 else {
1047 if (count($d) % 2 == 1) { $d = array_merge($d, $d); } // 5, 3, 1 => 5,3,1,5,3,1 OR 3 => 3,3
1048 $arr = '';
1049 for($i=0; $i<count($d); $i+=2) {
1050 $arr .= sprintf('%.3F %.3F ', $d[$i]*$this->kp, $d[$i+1]*$this->kp);
1051 }
1052 if (isset($critere_style['stroke-dashoffset'])){ $off = $critere_style['stroke-dashoffset'] + 0; }
1053 $path_style .= sprintf('[%s] %.3F d ', $arr, $off*$this->kp);
1054 }
1055 }
1056 }
1057
1058 // mPDF 4.4.003
1059 if ($critere_style['fill-rule']=='evenodd') { $fr = '*'; }
1060 else { $fr = ''; }
1061
1062 // mPDF 4.4.003
1063 if (isset($critere_style['fill-opacity'])) {
1064 $opacity = 1;
1065 if ($critere_style['fill-opacity'] == 0) { $opacity = 0; }
1066 else if ($critere_style['fill-opacity'] > 1) { $opacity = 1; }
1067 else if ($critere_style['fill-opacity'] > 0) { $opacity = $critere_style['fill-opacity']; }
1068 else if ($critere_style['fill-opacity'] < 0) { $opacity = 0; }
1069 $gs = $this->mpdf_ref->AddExtGState(array('ca'=>$opacity, 'BM'=>'/Normal'));
1070 $this->mpdf_ref->extgstates[$gs]['fo'] = true; // mPDF 5.0.039
1071 $path_style .= sprintf(' /GS%d gs ', $gs);
1072 }
1073
1074 // mPDF 4.4.003
1075 if (isset($critere_style['stroke-opacity'])) {
1076 $opacity = 1;
1077 if ($critere_style['stroke-opacity'] == 0) { $opacity = 0; }
1078 else if ($critere_style['stroke-opacity'] > 1) { $opacity = 1; }
1079 else if ($critere_style['stroke-opacity'] > 0) { $opacity = $critere_style['stroke-opacity']; }
1080 else if ($critere_style['stroke-opacity'] < 0) { $opacity = 0; }
1081 $gs = $this->mpdf_ref->AddExtGState(array('CA'=>$opacity, 'BM'=>'/Normal'));
1082 $this->mpdf_ref->extgstates[$gs]['fo'] = true; // mPDF 5.0.039
1083 $path_style .= sprintf(' /GS%d gs ', $gs);
1084 }
1085
1086 switch ($style){
1087 case 'F':
1088 $op = 'f';
1089 break;
1090 case 'FD':
1091 $op = 'B';
1092 break;
1093 case 'ND':
1094 $op = 'S';
1095 break;
1096 case 'D':
1097 $op = 'S';
1098 break;
1099 default:
1100 $op = 'n';
1101 }
1102
1103 // mPDF 5.0
1104 $prestyle = $path_style.' ';
1105 $poststyle = $w.' '. $op.$fr.' '.$fill_gradient."\n";
1106 return array($prestyle,$poststyle);
1107
1108 }
1109
1110 //
1111 // fonction retracant les <path />
1112 function svgPath($command, $arguments){
1113 $path_cmd = '';
1114 $newsubpath = false; // mPDF 4.4.003
1115 // mPDF 5.0.039
1116 $minl = $this->pathBBox[0];
1117 $mint = $this->pathBBox[1];
1118 $maxr = $this->pathBBox[2]+$this->pathBBox[0];
1119 $maxb = $this->pathBBox[3]+$this->pathBBox[1];
1120 // mPDF 5.0.040
1121 $start = array($this->xbase, -$this->ybase);
1122
1123 // mPDF 4.4.003
1124 preg_match_all('/[\-^]?[\d.]+(e[\-]?[\d]+){0,1}/i', $arguments, $a, PREG_SET_ORDER);
1125
1126 // if the command is a capital letter, the coords go absolute, otherwise relative
1127 if(strtolower($command) == $command) $relative = true;
1128 else $relative = false;
1129
1130
1131 $ile_argumentow = count($a);
1132
1133 // each command may have different needs for arguments [1 to 8]
1134
1135 switch(strtolower($command)){
1136 case 'm': // move
1137 for($i = 0; $i<$ile_argumentow; $i+=2){
1138 $x = $a[$i][0];
1139 $y = $a[$i+1][0];
1140 if($relative){
1141 $pdfx = ($this->xbase + $x);
1142 $pdfy = ($this->ybase - $y);
1143 $this->xbase += $x;
1144 $this->ybase += -$y;
1145 }
1146 else{
1147 $pdfx = $x;
1148 $pdfy = -$y ;
1149 $this->xbase = $x;
1150 $this->ybase = -$y;
1151 }
1152 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1153 // mPDF 5.0.039
1154 $minl = min($minl,$pdf_pt['x']);
1155 $maxr = max($maxr,$pdf_pt['x']);
1156 $mint = min($mint,-$pdf_pt['y']);
1157 $maxb = max($maxb,-$pdf_pt['y']);
1158 if($i == 0) $path_cmd .= sprintf('%.3F %.3F m ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1159 else $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1160 // mPDF 4.4.003 Save start points of subpath
1161 if ($this->subPathInit) {
1162 $this->spxstart = $this->xbase;
1163 $this->spystart = $this->ybase;
1164 $this->subPathInit = false;
1165 }
1166 }
1167 break;
1168 case 'l': // a simple line
1169 for($i = 0; $i<$ile_argumentow; $i+=2){
1170 $x = ($a[$i][0]);
1171 $y = ($a[$i+1][0]);
1172 if($relative){
1173 $pdfx = ($this->xbase + $x);
1174 $pdfy = ($this->ybase - $y);
1175 $this->xbase += $x;
1176 $this->ybase += -$y;
1177 }
1178 else{
1179 $pdfx = $x ;
1180 $pdfy = -$y ;
1181 $this->xbase = $x;
1182 $this->ybase = -$y;
1183 }
1184 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1185 // mPDF 5.0.039
1186 $minl = min($minl,$pdf_pt['x']);
1187 $maxr = max($maxr,$pdf_pt['x']);
1188 $mint = min($mint,-$pdf_pt['y']);
1189 $maxb = max($maxb,-$pdf_pt['y']);
1190 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1191 }
1192 break;
1193 case 'h': // a very simple horizontal line
1194 for($i = 0; $i<$ile_argumentow; $i++){
1195 $x = ($a[$i][0]);
1196 if($relative){
1197 $y = 0;
1198 $pdfx = ($this->xbase + $x) ;
1199 $pdfy = ($this->ybase - $y) ;
1200 $this->xbase += $x;
1201 $this->ybase += -$y;
1202 }
1203 else{
1204 $y = -$this->ybase;
1205 $pdfx = $x;
1206 $pdfy = -$y;
1207 $this->xbase = $x;
1208 $this->ybase = -$y;
1209 }
1210 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1211 // mPDF 5.0.039
1212 $minl = min($minl,$pdf_pt['x']);
1213 $maxr = max($maxr,$pdf_pt['x']);
1214 $mint = min($mint,-$pdf_pt['y']);
1215 $maxb = max($maxb,-$pdf_pt['y']);
1216 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1217 }
1218 break;
1219 case 'v': // the simplest line, vertical
1220 for($i = 0; $i<$ile_argumentow; $i++){
1221 $y = ($a[$i][0]);
1222 if($relative){
1223 $x = 0;
1224 $pdfx = ($this->xbase + $x);
1225 $pdfy = ($this->ybase - $y);
1226 $this->xbase += $x;
1227 $this->ybase += -$y;
1228 }
1229 else{
1230 $x = $this->xbase;
1231 $pdfx = $x;
1232 $pdfy = -$y;
1233 $this->xbase = $x;
1234 $this->ybase = -$y;
1235 }
1236 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1237 // mPDF 5.0.039
1238 $minl = min($minl,$pdf_pt['x']);
1239 $maxr = max($maxr,$pdf_pt['x']);
1240 $mint = min($mint,-$pdf_pt['y']);
1241 $maxb = max($maxb,-$pdf_pt['y']);
1242 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1243 }
1244 break;
1245 case 's': // bezier with first vertex equal first control
1246 // mPDF 4.4.003
1247 if (!($this->lastcommand == 'C' || $this->lastcommand == 'c' || $this->lastcommand == 'S' || $this->lastcommand == 's')) {
1248 $this->lastcontrolpoints = array(0,0);
1249 }
1250 for($i = 0; $i<$ile_argumentow; $i += 4){
1251 $x1 = $this->lastcontrolpoints[0];
1252 $y1 = $this->lastcontrolpoints[1];
1253 $x2 = ($a[$i][0]);
1254 $y2 = ($a[$i+1][0]);
1255 $x = ($a[$i+2][0]);
1256 $y = ($a[$i+3][0]);
1257 if($relative){
1258 $pdfx1 = ($this->xbase + $x1);
1259 $pdfy1 = ($this->ybase - $y1);
1260 $pdfx2 = ($this->xbase + $x2);
1261 $pdfy2 = ($this->ybase - $y2);
1262 $pdfx = ($this->xbase + $x);
1263 $pdfy = ($this->ybase - $y);
1264 $this->xbase += $x;
1265 $this->ybase += -$y;
1266 }
1267 else{
1268 $pdfx1 = $this->xbase + $x1;
1269 $pdfy1 = $this->ybase -$y1;
1270 $pdfx2 = $x2;
1271 $pdfy2 = -$y2;
1272 $pdfx = $x;
1273 $pdfy = -$y;
1274 $this->xbase = $x;
1275 $this->ybase = -$y;
1276 }
1277 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1278
1279 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1280
1281 // mPDF 5.0.040
1282 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1283 $bx = calc_bezier_bbox($start, $curves);
1284 $minl = min($minl,$bx[0]);
1285 $maxr = max($maxr,$bx[2]);
1286 $mint = min($mint,$bx[1]);
1287 $maxb = max($maxb,$bx[3]);
1288
1289 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1290 {
1291 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1292 }
1293 else
1294 {
1295 $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);
1296 }
1297
1298 }
1299 break;
1300 case 'c': // bezier with second vertex equal second control
1301 for($i = 0; $i<$ile_argumentow; $i += 6){
1302 $x1 = ($a[$i][0]);
1303 $y1 = ($a[$i+1][0]);
1304 $x2 = ($a[$i+2][0]);
1305 $y2 = ($a[$i+3][0]);
1306 $x = ($a[$i+4][0]);
1307 $y = ($a[$i+5][0]);
1308
1309
1310 if($relative){
1311 $pdfx1 = ($this->xbase + $x1);
1312 $pdfy1 = ($this->ybase - $y1);
1313 $pdfx2 = ($this->xbase + $x2);
1314 $pdfy2 = ($this->ybase - $y2);
1315 $pdfx = ($this->xbase + $x);
1316 $pdfy = ($this->ybase - $y);
1317 $this->xbase += $x;
1318 $this->ybase += -$y;
1319 }
1320 else{
1321 $pdfx1 = $x1;
1322 $pdfy1 = -$y1;
1323 $pdfx2 = $x2;
1324 $pdfy2 = -$y2;
1325 $pdfx = $x;
1326 $pdfy = -$y;
1327 $this->xbase = $x;
1328 $this->ybase = -$y;
1329 }
1330 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1331 // $pdf_pt2 = $this->svg_overflow($pdfx2,$pdfy2);
1332 // $pdf_pt1 = $this->svg_overflow($pdfx1,$pdfy1);
1333 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1334
1335 // mPDF 5.0.040
1336 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1337 $bx = calc_bezier_bbox($start, $curves);
1338 $minl = min($minl,$bx[0]);
1339 $maxr = max($maxr,$bx[2]);
1340 $mint = min($mint,$bx[1]);
1341 $maxb = max($maxb,$bx[3]);
1342
1343 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1344 {
1345 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1346 }
1347 else
1348 {
1349 $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);
1350 }
1351
1352 }
1353 break;
1354
1355 case 'q': // bezier quadratic avec point de control
1356 for($i = 0; $i<$ile_argumentow; $i += 4){
1357 $x1 = ($a[$i][0]);
1358 $y1 = ($a[$i+1][0]);
1359 $x = ($a[$i+2][0]);
1360 $y = ($a[$i+3][0]);
1361 if($relative){
1362 $pdfx = ($this->xbase + $x);
1363 $pdfy = ($this->ybase - $y);
1364
1365 $pdfx1 = ($this->xbase + ($x1*2/3));
1366 $pdfy1 = ($this->ybase - ($y1*2/3));
1367 // mPDF 4.4.003
1368 $pdfx2 = $pdfx1 + 1/3 *($x);
1369 $pdfy2 = $pdfy1 + 1/3 *(-$y) ;
1370
1371 $this->xbase += $x;
1372 $this->ybase += -$y;
1373 }
1374 else{
1375 $pdfx = $x;
1376 $pdfy = -$y;
1377
1378 $pdfx1 = ($this->xbase+(($x1-$this->xbase)*2/3));
1379 $pdfy1 = ($this->ybase-(($y1+$this->ybase)*2/3));
1380
1381 $pdfx2 = ($x+(($x1-$x)*2/3));
1382 $pdfy2 = (-$y-(($y1-$y)*2/3));
1383
1384 // mPDF 4.4.003
1385 $pdfx2 = $pdfx1 + 1/3 *($x - $this->xbase);
1386 $pdfy2 = $pdfy1 + 1/3 *(-$y - $this->ybase) ;
1387
1388 $this->xbase = $x;
1389 $this->ybase = -$y;
1390 }
1391 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1392
1393 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1394
1395 // mPDF 5.0.040
1396 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1397 $bx = calc_bezier_bbox($start, $curves);
1398 $minl = min($minl,$bx[0]);
1399 $maxr = max($maxr,$bx[2]);
1400 $mint = min($mint,$bx[1]);
1401 $maxb = max($maxb,$bx[3]);
1402
1403 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1404 {
1405 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1406 }
1407 else
1408 {
1409 $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);
1410 }
1411 }
1412 break;
1413 case 't': // bezier quadratic avec point de control simetrique a lancien point de control
1414 // mPDF 4.4.003
1415 if (!($this->lastcommand == 'Q' || $this->lastcommand == 'q' || $this->lastcommand == 'T' || $this->lastcommand == 't')) {
1416 $this->lastcontrolpoints = array(0,0);
1417 }
1418 for($i = 0; $i<$ile_argumentow; $i += 2){
1419 $x = ($a[$i][0]);
1420 $y = ($a[$i+1][0]);
1421
1422 $x1 = $this->lastcontrolpoints[0];
1423 $y1 = $this->lastcontrolpoints[1];
1424
1425 if($relative){
1426 $pdfx = ($this->xbase + $x);
1427 $pdfy = ($this->ybase - $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);
1433 $pdfy2 = $pdfy1 + 1/3 *(-$y) ;
1434
1435 $this->xbase += $x;
1436 $this->ybase += -$y;
1437 }
1438 else{
1439 $pdfx = $x;
1440 $pdfy = -$y;
1441
1442 $pdfx1 = ($this->xbase + ($x1)); // mPDF 4.4.003
1443 $pdfy1 = ($this->ybase - ($y1)); // mPDF 4.4.003
1444 // mPDF 4.4.003
1445 $pdfx2 = $pdfx1 + 1/3 *($x - $this->xbase);
1446 $pdfy2 = $pdfy1 + 1/3 *(-$y - $this->ybase) ;
1447
1448 $this->xbase = $x;
1449 $this->ybase = -$y;
1450 }
1451
1452 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1453
1454 // mPDF 5.0.040
1455 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1456 $bx = calc_bezier_bbox($start, $curves);
1457 $minl = min($minl,$bx[0]);
1458 $maxr = max($maxr,$bx[2]);
1459 $mint = min($mint,$bx[1]);
1460 $maxb = max($maxb,$bx[3]);
1461
1462 $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);
1463 }
1464
1465 break;
1466 case 'a': // Elliptical arc
1467 for($i = 0; $i<$ile_argumentow; $i += 7){
1468 $rx = ($a[$i][0]);
1469 $ry = ($a[$i+1][0]);
1470 $angle = ($a[$i+2][0]); //x-axis-rotation
1471 $largeArcFlag = ($a[$i+3][0]);
1472 $sweepFlag = ($a[$i+4][0]);
1473 $x2 = ($a[$i+5][0]);
1474 $y2 = ($a[$i+6][0]);
1475 $x1 = $this->xbase;
1476 $y1 = -$this->ybase;
1477 if($relative){
1478 $x2 = $this->xbase + $x2;
1479 $y2 = -$this->ybase + $y2;
1480 $this->xbase += ($a[$i+5][0]);
1481 $this->ybase += -($a[$i+6][0]);
1482 }
1483 else{
1484 $this->xbase = $x2;
1485 $this->ybase = -$y2;
1486 }
1487 // mPDF 5.0.039 // mPDF 5.0.040
1488 list($pcmd, $bounds) = $this->Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag);
1489 $minl = min($minl,$x2,min($bounds[0]));
1490 $maxr = max($maxr,$x2,max($bounds[0]));
1491 $mint = min($mint,$y2,min($bounds[1]));
1492 $maxb = max($maxb,$y2,max($bounds[1]));
1493 $path_cmd .= $pcmd;
1494
1495 }
1496 break;
1497 case'z':
1498 $path_cmd .= 'h ';
1499 // mPDF 4.4.003
1500 $this->subPathInit = true;
1501 $newsubpath = true;
1502 $this->xbase = $this->spxstart;
1503 $this->ybase = $this->spystart;
1504 break;
1505 default:
1506 break;
1507 }
1508
1509 if (!$newsubpath) { $this->subPathInit = false; } // mPDF 4.4.003
1510 $this->lastcommand = $command;
1511 // mPDF 5.0.039
1512 $this->pathBBox[0] = $minl;
1513 $this->pathBBox[1] = $mint;
1514 $this->pathBBox[2] = $maxr - $this->pathBBox[0];
1515 $this->pathBBox[3] = $maxb - $this->pathBBox[1];
1516 return $path_cmd;
1517
1518 }
1519
1520 function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) {
1521
1522 // mPDF 5.0.040
1523 $bounds = array(0=>array($x1,$x2),1=>array($y1,$y2));
1524 // 1. Treat out-of-range parameters as described in
1525 // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
1526 // If the endpoints (x1, y1) and (x2, y2) are identical, then this
1527 // is equivalent to omitting the elliptical arc segment entirely
1528 if ($x1 == $x2 && $y1 == $y2) return array('', $bounds); // mPD 5.0.040
1529
1530 // If rX = 0 or rY = 0 then this arc is treated as a straight line
1531 // segment (a "lineto") joining the endpoints.
1532 if ($rx == 0.0 || $ry == 0.0) {
1533 // return array(Lineto(x2, y2), $bounds); // mPD 5.0.040
1534 }
1535
1536 // If rX or rY have negative signs, these are dropped; the absolute
1537 // value is used instead.
1538 if ($rx<0.0) $rx = -$rx;
1539 if ($ry<0.0) $ry = -$ry;
1540
1541 // 2. convert to center parameterization as shown in
1542 // http://www.w3.org/TR/SVG/implnote.html
1543 $sinPhi = sin(deg2rad($angle));
1544 $cosPhi = cos(deg2rad($angle));
1545
1546 $x1dash = $cosPhi * ($x1-$x2)/2.0 + $sinPhi * ($y1-$y2)/2.0;
1547 $y1dash = -$sinPhi * ($x1-$x2)/2.0 + $cosPhi * ($y1-$y2)/2.0;
1548
1549
1550 $numerator = $rx*$rx*$ry*$ry - $rx*$rx*$y1dash*$y1dash - $ry*$ry*$x1dash*$x1dash;
1551
1552 if ($numerator < 0.0) {
1553 // If rX , rY and are such that there is no solution (basically,
1554 // the ellipse is not big enough to reach from (x1, y1) to (x2,
1555 // y2)) then the ellipse is scaled up uniformly until there is
1556 // exactly one solution (until the ellipse is just big enough).
1557
1558 // -> find factor s, such that numerator' with rx'=s*rx and
1559 // ry'=s*ry becomes 0 :
1560 $s = sqrt(1.0 - $numerator/($rx*$rx*$ry*$ry));
1561
1562 $rx *= $s;
1563 $ry *= $s;
1564 $root = 0.0;
1565
1566 }
1567 else {
1568 $root = ($largeArcFlag == $sweepFlag ? -1.0 : 1.0) * sqrt( $numerator/($rx*$rx*$y1dash*$y1dash+$ry*$ry*$x1dash*$x1dash) );
1569 }
1570
1571 $cxdash = $root*$rx*$y1dash/$ry;
1572 $cydash = -$root*$ry*$x1dash/$rx;
1573
1574 $cx = $cosPhi * $cxdash - $sinPhi * $cydash + ($x1+$x2)/2.0;
1575 $cy = $sinPhi * $cxdash + $cosPhi * $cydash + ($y1+$y2)/2.0;
1576
1577
1578 $theta1 = $this->CalcVectorAngle(1.0, 0.0, ($x1dash-$cxdash)/$rx, ($y1dash-$cydash)/$ry);
1579 $dtheta = $this->CalcVectorAngle(($x1dash-$cxdash)/$rx, ($y1dash-$cydash)/$ry, (-$x1dash-$cxdash)/$rx, (-$y1dash-$cydash)/$ry);
1580 if (!$sweepFlag && $dtheta>0)
1581 $dtheta -= 2.0*M_PI;
1582 else if ($sweepFlag && $dtheta<0)
1583 $dtheta += 2.0*M_PI;
1584
1585 // 3. convert into cubic bezier segments <= 90deg
1586 $segments = ceil(abs($dtheta/(M_PI/2.0)));
1587 $delta = $dtheta/$segments;
1588 $t = 8.0/3.0 * sin($delta/4.0) * sin($delta/4.0) / sin($delta/2.0);
1589 $coords = array();
1590 for ($i = 0; $i < $segments; $i++) {
1591 $cosTheta1 = cos($theta1);
1592 $sinTheta1 = sin($theta1);
1593 $theta2 = $theta1 + $delta;
1594 $cosTheta2 = cos($theta2);
1595 $sinTheta2 = sin($theta2);
1596
1597 // a) calculate endpoint of the segment:
1598 $xe = $cosPhi * $rx*$cosTheta2 - $sinPhi * $ry*$sinTheta2 + $cx;
1599 $ye = $sinPhi * $rx*$cosTheta2 + $cosPhi * $ry*$sinTheta2 + $cy;
1600
1601 // b) calculate gradients at start/end points of segment:
1602 $dx1 = $t * ( - $cosPhi * $rx*$sinTheta1 - $sinPhi * $ry*$cosTheta1);
1603 $dy1 = $t * ( - $sinPhi * $rx*$sinTheta1 + $cosPhi * $ry*$cosTheta1);
1604
1605 $dxe = $t * ( $cosPhi * $rx*$sinTheta2 + $sinPhi * $ry*$cosTheta2);
1606 $dye = $t * ( $sinPhi * $rx*$sinTheta2 - $cosPhi * $ry*$cosTheta2);
1607
1608 // c) draw the cubic bezier:
1609 $coords[$i] = array(($x1+$dx1), ($y1+$dy1), ($xe+$dxe), ($ye+$dye), $xe, $ye);
1610
1611 // do next segment
1612 $theta1 = $theta2;
1613 $x1 = $xe;
1614 $y1 = $ye;
1615 }
1616 $path = ' ';
1617 foreach($coords AS $c) {
1618 $cpx1 = $c[0];
1619 $cpy1 = $c[1];
1620 $cpx2 = $c[2];
1621 $cpy2 = $c[3];
1622 $x2 = $c[4];
1623 $y2 = $c[5];
1624 $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";
1625
1626 // mPDF 5.0.040
1627 $bounds[0][] = $c[4];
1628 $bounds[1][] = $c[5];
1629 }
1630 return array($path, $bounds); // mPD 5.0.040
1631 }
1632
1633
1634 function CalcVectorAngle($ux, $uy, $vx, $vy) {
1635 $ta = atan2($uy, $ux);
1636 $tb = atan2($vy, $vx);
1637 if ($tb >= $ta)
1638 return ($tb-$ta);
1639 return (6.28318530718 - ($ta-$tb));
1640 }
1641
1642
1643 // mPDF 4.4.003
1644 function ConvertSVGSizePixels($size=5,$maxsize='x'){
1645 // maxsize in pixels (user units) or 'y' or 'x'
1646 // e.g. $w = $this->ConvertSVGSizePixels($arguments['w'],$this->svg_info['w']*(25.4/$this->mpdf_ref->dpi));
1647 // usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
1648 // Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
1649 // For text $maxsize = Fontsize
1650 // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
1651
1652 if ($maxsize == 'y') { $maxsize = $this->svg_info['h']; }
1653 else if ($maxsize == 'x') { $maxsize = $this->svg_info['w']; }
1654 $maxsize *= (25.4/$this->mpdf_ref->dpi); // convert pixels to mm
1655 $fontsize=$this->mpdf_ref->FontSize;
1656 //Return as pixels
1657 $size = $this->mpdf_ref->ConvertSize($size,$maxsize,$fontsize,false) * 1/(25.4/$this->mpdf_ref->dpi);
1658 return $size;
1659 }
1660
1661 // mPDF 4.4.003
1662 function ConvertSVGSizePts($size=5){
1663 // usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
1664 // Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
1665 // For text $maxsize = Fontsize
1666 // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
1667 $maxsize=$this->mpdf_ref->FontSize;
1668 //Return as pts
1669 $size = $this->mpdf_ref->ConvertSize($size,$maxsize,false,true) * 72/25.4;
1670 return $size;
1671 }
1672
1673
1674 //
1675 // fonction retracant les <rect />
1676 function svgRect($arguments){
1677
1678 if ($arguments['h']==0 || $arguments['w']==0) { return ''; } // mPDF 4.4.003
1679
1680 $x = $this->ConvertSVGSizePixels($arguments['x'],'x'); // mPDF 4.4.003
1681 $y = $this->ConvertSVGSizePixels($arguments['y'],'y'); // mPDF 4.4.003
1682 $h = $this->ConvertSVGSizePixels($arguments['h'],'y'); // mPDF 4.4.003
1683 $w = $this->ConvertSVGSizePixels($arguments['w'],'x'); // mPDF 4.4.003
1684 $rx = $this->ConvertSVGSizePixels($arguments['rx'],'x'); // mPDF 4.4.003
1685 $ry = $this->ConvertSVGSizePixels($arguments['ry'],'y'); // mPDF 4.4.003
1686
1687 if ($rx > $w/2) { $rx = $w/2; } // mPDF 4.4.003
1688 if ($ry > $h/2) { $ry = $h/2; } // mPDF 4.4.003
1689
1690 if ($rx>0 and $ry == 0){$ry = $rx;}
1691 if ($ry>0 and $rx == 0){$rx = $ry;}
1692
1693 if ($rx == 0 and $ry == 0){
1694 // trace un rectangle sans angle arrondit
1695 $path_cmd = sprintf('%.3F %.3F m ', ($x*$this->kp), -($y*$this->kp));
1696 $path_cmd .= sprintf('%.3F %.3F l ', (($x+$w)*$this->kp), -($y*$this->kp));
1697 $path_cmd .= sprintf('%.3F %.3F l ', (($x+$w)*$this->kp), -(($y+$h)*$this->kp));
1698 $path_cmd .= sprintf('%.3F %.3F l ', ($x)*$this->kp, -(($y+$h)*$this->kp));
1699 $path_cmd .= sprintf('%.3F %.3F l h ', ($x*$this->kp), -($y*$this->kp));
1700
1701
1702 }
1703 else {
1704 // trace un rectangle avec les arrondit
1705 // les points de controle du bezier sont deduis grace a la constante kappa
1706 $kappa = 4*(sqrt(2)-1)/3;
1707
1708 $kx = $kappa*$rx;
1709 $ky = $kappa*$ry;
1710
1711 $path_cmd = sprintf('%.3F %.3F m ', ($x+$rx)*$this->kp, -$y*$this->kp);
1712 $path_cmd .= sprintf('%.3F %.3F l ', ($x+($w-$rx))*$this->kp, -$y*$this->kp);
1713 $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 );
1714 $path_cmd .= sprintf('%.3F %.3F l ', ($x+$w)*$this->kp, (-$y+(-$h+$ry))*$this->kp);
1715 $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 );
1716
1717 $path_cmd .= sprintf('%.3F %.3F l ', ($x+$rx)*$this->kp, (-$y+(-$h))*$this->kp);
1718 $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 );
1719 $path_cmd .= sprintf('%.3F %.3F l ', $x*$this->kp, (-$y+(-$ry))*$this->kp);
1720 $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 );
1721
1722
1723 }
1724 return $path_cmd;
1725 }
1726
1727 //
1728 // fonction retracant les <ellipse /> et <circle />
1729 // le cercle est tracé grave a 4 bezier cubic, les poitn de controles
1730 // sont deduis grace a la constante kappa * rayon
1731 function svgEllipse($arguments){
1732 if ($arguments['rx']==0 || $arguments['ry']==0) { return ''; } // mPDF 4.4.003
1733
1734 $kappa = 4*(sqrt(2)-1)/3;
1735
1736 $cx = $this->ConvertSVGSizePixels($arguments['cx'],'x'); // mPDF 4.4.003
1737 $cy = $this->ConvertSVGSizePixels($arguments['cy'],'y'); // mPDF 4.4.003
1738 $rx = $this->ConvertSVGSizePixels($arguments['rx'],'x'); // mPDF 4.4.003
1739 $ry = $this->ConvertSVGSizePixels($arguments['ry'],'y'); // mPDF 4.4.003
1740
1741 $x1 = $cx;
1742 $y1 = -$cy+$ry;
1743
1744 $x2 = $cx+$rx;
1745 $y2 = -$cy;
1746
1747 $x3 = $cx;
1748 $y3 = -$cy-$ry;
1749
1750 $x4 = $cx-$rx;
1751 $y4 = -$cy;
1752
1753 $path_cmd = sprintf('%.3F %.3F m ', $x1*$this->kp, $y1*$this->kp);
1754 $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);
1755 $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);
1756 $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);
1757 $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);
1758 $path_cmd .= 'h ';
1759
1760 return $path_cmd;
1761
1762 }
1763
1764 //
1765 // fonction retracant les <polyline /> et les <line />
1766 function svgPolyline($arguments,$ispolyline=true){
1767 if ($ispolyline) {
1768 $xbase = $arguments[0] ;
1769 $ybase = - $arguments[1] ;
1770 }
1771 else {
1772 if ($arguments[0]==$arguments[2] && $arguments[1]==$arguments[3]) { return ''; } // mPDF 4.4.003 Zero length line
1773 $xbase = $this->ConvertSVGSizePixels($arguments[0],'x'); // mPDF 4.4.003
1774 $ybase = - $this->ConvertSVGSizePixels($arguments[1],'y'); // mPDF 4.4.003
1775 }
1776 $path_cmd = sprintf('%.3F %.3F m ', $xbase*$this->kp, $ybase*$this->kp);
1777 for ($i = 2; $i<count($arguments);$i += 2) {
1778 if ($ispolyline) {
1779 $tmp_x = $arguments[$i] ;
1780 $tmp_y = - $arguments[($i+1)] ;
1781 }
1782 else {
1783 $tmp_x = $this->ConvertSVGSizePixels($arguments[$i],'x') ; // mPDF 4.4.003
1784 $tmp_y = - $this->ConvertSVGSizePixels($arguments[($i+1)],'y') ; // mPDF 4.4.003
1785 }
1786 $path_cmd .= sprintf('%.3F %.3F l ', $tmp_x*$this->kp, $tmp_y*$this->kp);
1787 }
1788
1789 // $path_cmd .= 'h '; // ?? In error - don't close subpath here
1790 return $path_cmd;
1791
1792 }
1793
1794 //
1795 // fonction retracant les <polygone />
1796 function svgPolygon($arguments){
1797 $xbase = $arguments[0] ;
1798 $ybase = - $arguments[1] ;
1799 $path_cmd = sprintf('%.3F %.3F m ', $xbase*$this->kp, $ybase*$this->kp);
1800 for ($i = 2; $i<count($arguments);$i += 2) {
1801 $tmp_x = $arguments[$i] ;
1802 $tmp_y = - $arguments[($i+1)] ;
1803
1804 $path_cmd .= sprintf('%.3F %.3F l ', $tmp_x*$this->kp, $tmp_y*$this->kp);
1805
1806 }
1807 $path_cmd .= sprintf('%.3F %.3F l ', $xbase*$this->kp, $ybase*$this->kp);
1808 $path_cmd .= 'h ';
1809 return $path_cmd;
1810
1811 }
1812
1813 //
1814 // write string to image
1815 function svgText() {
1816 // $tmp = count($this->txt_style)-1;
1817 $current_style = array_pop($this->txt_style);
1818 $style = '';
1819 $render = -1;
1820 if(isset($this->txt_data[2]))
1821 {
1822 // select font
1823 $style .= ($current_style['font-weight'] == 'bold')?'B':'';
1824 $style .= ($current_style['font-style'] == 'italic')?'I':'';
1825 $size = $current_style['font-size']*$this->kf; // mPDF 5.0.039
1826
1827 // mPDF 5.0
1828 $current_style['font-family'] = $this->mpdf_ref->SetFont($current_style['font-family'],$style,$size,false);
1829 $this->mpdf_ref->CurrentFont['fo'] = true; // mPDF 5.0.039
1830
1831
1832 // mPDF 5.0.041
1833 $opacitystr = '';
1834 $opacity = 1;
1835 if (isset($current_style['fill-opacity'])) {
1836 if ($current_style['fill-opacity'] == 0) { $opacity = 0; }
1837 else if ($current_style['fill-opacity'] > 1) { $opacity = 1; }
1838 else if ($current_style['fill-opacity'] > 0) { $opacity = $current_style['fill-opacity']; }
1839 else if ($current_style['fill-opacity'] < 0) { $opacity = 0; }
1840 }
1841 $gs = $this->mpdf_ref->AddExtGState(array('ca'=>$opacity, 'BM'=>'/Normal'));
1842 $this->mpdf_ref->extgstates[$gs]['fo'] = true; // mPDF 5.0.039
1843 $opacitystr = sprintf(' /GS%d gs ', $gs);
1844
1845 // mPDF 5.0.051
1846 $fillstr = '';
1847 if (isset($current_style['fill']) && $current_style['fill']!='none') {
1848 $col = $this->mpdf_ref->ConvertColor($current_style['fill']);
1849 // mPDF 5.0.051
1850 $fillstr = $this->mpdf_ref->SetFColor($col, true);
1851 $render = "0"; // Fill (only)
1852 }
1853 $strokestr = '';
1854 if (isset($current_style['stroke-width']) && $current_style['stroke-width']>0 && $current_style['stroke']!='none') {
1855 $scol = $this->mpdf_ref->ConvertColor($current_style['stroke']);
1856 if ($scol) {
1857 $strokestr .= $this->mpdf_ref->SetDColor($scol, true).' '; // mPDF 5.0.051
1858 }
1859 $linewidth = $this->ConvertSVGSizePixels($current_style['stroke-width']);
1860 if ($linewidth > 0) {
1861 $strokestr .= sprintf('%.3F w 1 J 1 j ',$linewidth*$this->kp);
1862 if ($render == -1) { $render = "1"; } // stroke only
1863 else { $render = "2"; } // fill and stroke
1864 }
1865 }
1866 if ($render == -1) { return ''; }
1867
1868 $x = $this->ConvertSVGSizePixels($this->txt_data[0],'x'); // mPDF 4.4.003
1869 $y = $this->ConvertSVGSizePixels($this->txt_data[1],'y'); // mPDF 4.4.003
1870 $txt = $this->txt_data[2];
1871
1872 // mPDF 4.4.003
1873 $txt = preg_replace('/\f/','',$txt);
1874 $txt = preg_replace('/\r/','',$txt);
1875 $txt = preg_replace('/\n/',' ',$txt);
1876 $txt = preg_replace('/\t/',' ',$txt);
1877 $txt = preg_replace("/[ ]+/u",' ',$txt);
1878
1879 $txt = trim($txt);
1880
1881 $txt = $this->mpdf_ref->purify_utf8_text($txt);
1882 if ($this->mpdf_ref->text_input_as_HTML) {
1883 $txt = $this->mpdf_ref->all_entities_to_utf8($txt);
1884 }
1885
1886 // mPDF 5.0
1887 if ($this->mpdf_ref->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mpdf_ref->mb_enc,'UTF-8'); }
1888 if (preg_match("/([".$this->mpdf_ref->pregRTLchars."])/u", $txt)) { $this->mpdf_ref->biDirectional = true; } // mPDF 4.4.003
1889
1890 $this->mpdf_ref->magic_reverse_dir($txt, true, 'ltr'); // mPDF 5.0.054
1891 $this->mpdf_ref->ConvertIndic($txt);
1892
1893
1894 if ($current_style['text-anchor']=='middle') {
1895 $tw = $this->mpdf_ref->GetStringWidth($txt)*_MPDFK/2; // mPDF 4.4.003 // mPDF 5.4.09
1896 }
1897 else if ($current_style['text-anchor']=='end') {
1898 $tw = $this->mpdf_ref->GetStringWidth($txt)*_MPDFK; // mPDF 4.4.003 // mPDF 5.4.09
1899 }
1900 else $tw = 0;
1901
1902 if (!$this->mpdf_ref->usingCoreFont) {
1903 $this->mpdf_ref->UTF8StringToArray($txt); // mPDF 5.0 adds chars to subset list
1904 $txt= $this->mpdf_ref->UTF8ToUTF16BE($txt, false);
1905 }
1906 $txt='('.$this->mpdf_ref->_escape($txt).')';
1907 $this->mpdf_ref->CurrentFont['used']= true;
1908
1909 $pdfx = $x - $tw/$this->kp; // mPDF 4.4.009
1910 $pdfy = -$y ;
1911 $xbase = $x;
1912 $ybase = -$y;
1913
1914 // mPDF 5.7.2
1915 $path_cmd = sprintf('q BT /F%d %.3F Tf %s %.3F %.3F Td %s Tr %s %s %s Tj ET Q ',$this->mpdf_ref->CurrentFont['i'], $this->mpdf_ref->FontSizePt, $opacitystr, $pdfx*$this->kp,$pdfy*$this->kp,$render,$fillstr,$strokestr,$txt)."\n";
1916 unset($this->txt_data[0], $this->txt_data[1],$this->txt_data[2]);
1917
1918 if (isset($current_style['font-size-parent'])) {
1919 $this->mpdf_ref->SetFontSize($current_style['font-size-parent']);
1920 }
1921 }
1922 else
1923 {
1924 return ' ';
1925 }
1926 return $path_cmd;
1927 }
1928
1929
1930 function svgDefineTxtStyle($critere_style)
1931 {
1932 // get copy of current/default txt style, and modify it with supplied attributes
1933 $tmp = count($this->txt_style)-1;
1934 $current_style = $this->txt_style[$tmp];
1935 if (isset($critere_style['style'])){
1936 if (preg_match('/fill:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
1937 $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);
1938 }
1939 else { $tmp = preg_replace("/(.*)fill:\s*([a-z0-9#_()]*|none)(.*)/i","$2",$critere_style['style']);
1940 if ($tmp != $critere_style['style']){ $current_style['fill'] = $tmp; }
1941 }
1942
1943 $tmp = preg_replace("/(.*)fill-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1944 if ($tmp != $critere_style['style']){ $current_style['fill-opacity'] = $tmp;}
1945
1946 $tmp = preg_replace("/(.*)fill-rule:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1947 if ($tmp != $critere_style['style']){ $current_style['fill-rule'] = $tmp;}
1948
1949 if (preg_match('/stroke:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
1950 $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);
1951 }
1952 else { $tmp = preg_replace("/(.*)stroke:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1953 if ($tmp != $critere_style['style']){ $current_style['stroke'] = $tmp; }
1954 }
1955
1956 $tmp = preg_replace("/(.*)stroke-linecap:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1957 if ($tmp != $critere_style['style']){ $current_style['stroke-linecap'] = $tmp;}
1958
1959 $tmp = preg_replace("/(.*)stroke-linejoin:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1960 if ($tmp != $critere_style['style']){ $current_style['stroke-linejoin'] = $tmp;}
1961
1962 $tmp = preg_replace("/(.*)stroke-miterlimit:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
1963 if ($tmp != $critere_style['style']){ $current_style['stroke-miterlimit'] = $tmp;}
1964
1965 $tmp = preg_replace("/(.*)stroke-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1966 if ($tmp != $critere_style['style']){ $current_style['stroke-opacity'] = $tmp; }
1967
1968 $tmp = preg_replace("/(.*)stroke-width:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1969 if ($tmp != $critere_style['style']){ $current_style['stroke-width'] = $tmp;}
1970
1971 $tmp = preg_replace("/(.*)stroke-dasharray:\s*([a-z0-9., ]*|none)(.*)/i","$2",$critere_style['style']);
1972 if ($tmp != $critere_style['style']){ $current_style['stroke-dasharray'] = $tmp;}
1973
1974 $tmp = preg_replace("/(.*)stroke-dashoffset:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1975 if ($tmp != $critere_style['style']){ $current_style['stroke-dashoffset'] = $tmp;}
1976
1977 // mPDF 5.7.2
1978 $tmp = preg_replace("/(.*)font-family:\s*([a-z0-9.\"' ,\-]*|none)(.*)/i","$2",$critere_style['style']);
1979 if ($tmp != $critere_style['style']){ $critere_style['font-family'] = $tmp;}
1980
1981 $tmp = preg_replace("/(.*)font-size:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1982 if ($tmp != $critere_style['style']){ $critere_style['font-size'] = $tmp;}
1983
1984 $tmp = preg_replace("/(.*)font-weight:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1985 if ($tmp != $critere_style['style']){ $critere_style['font-weight'] = $tmp;}
1986
1987 $tmp = preg_replace("/(.*)font-style:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1988 if ($tmp != $critere_style['style']){ $critere_style['font-style'] = $tmp;}
1989
1990 }
1991
1992 if (isset($critere_style['font'])){
1993
1994 // [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]?<'font-size'> [ / <'line-height'> ]? <'font-family'> ]
1995
1996 $tmp = preg_replace("/(.*)(italic|oblique)(.*)/i","$2",$critere_style['font']);
1997 if ($tmp != $critere_style['font']){
1998 if($tmp == 'oblique'){
1999 $tmp = 'italic';
2000 }
2001 $current_style['font-style'] = $tmp;
2002 }
2003 $tmp = preg_replace("/(.*)(bold|bolder)(.*)/i","$2",$critere_style['font']);
2004 if ($tmp != $critere_style['font']){
2005 if($tmp == 'bolder'){
2006 $tmp = 'bold';
2007 }
2008 $current_style['font-weight'] = $tmp;
2009 }
2010
2011 // select digits not followed by percent sign nor preceeded by forward slash
2012 $tmp = preg_replace("/(.*)\b(\d+)[\b|\/](.*)/i","$2",$critere_style['font']);
2013 if ($tmp != $critere_style['font']){
2014 $current_style['font-size'] = $this->ConvertSVGSizePts($tmp);
2015 $this->mpdf_ref->SetFont('','',$current_style['font-size'],false);
2016 }
2017
2018 }
2019
2020 if(isset($critere_style['fill'])){
2021 $current_style['fill'] = $critere_style['fill'];
2022 }
2023 if(isset($critere_style['stroke'])){
2024 $current_style['stroke'] = $critere_style['stroke'];
2025 }
2026 if(isset($critere_style['stroke-width'])){
2027 $current_style['stroke-width'] = $critere_style['stroke-width'];
2028 }
2029
2030 if(isset($critere_style['font-style'])){
2031 if(strtolower($critere_style['font-style']) == 'oblique')
2032 {
2033 $critere_style['font-style'] = 'italic';
2034 }
2035 $current_style['font-style'] = $critere_style['font-style'];
2036 }
2037
2038 if(isset($critere_style['font-weight'])){
2039 if(strtolower($critere_style['font-weight']) == 'bolder')
2040 {
2041 $critere_style['font-weight'] = 'bold';
2042 }
2043 $current_style['font-weight'] = $critere_style['font-weight'];
2044 }
2045
2046 if(isset($critere_style['font-size'])){
2047 // mPDF 5.4.12
2048 if (strpos($critere_style['font-size'], '%')!==false) {
2049 $current_style['font-size-parent'] = $current_style['font-size'];
2050 }
2051 $current_style['font-size'] = $this->ConvertSVGSizePts($critere_style['font-size']);
2052 $this->mpdf_ref->SetFont('','',$current_style['font-size'],false);
2053 }
2054
2055 if(isset($critere_style['font-family'])){
2056 $v = $critere_style['font-family'];
2057 $aux_fontlist = explode(",",$v);
2058 $found = 0;
2059 foreach($aux_fontlist AS $f) {
2060 $fonttype = trim($f);
2061 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
2062 $fonttype = preg_replace('/ /','',$fonttype);
2063 $v = strtolower(trim($fonttype));
2064 if (isset($this->mpdf_ref->fonttrans[$v]) && $this->mpdf_ref->fonttrans[$v]) { $v = $this->mpdf_ref->fonttrans[$v]; }
2065 if ((!$this->mpdf_ref->usingCoreFont && in_array($v,$this->mpdf_ref->available_unifonts)) ||
2066 ($this->mpdf_ref->usingCoreFont && in_array($v,array('courier','times','helvetica','arial'))) ||
2067 in_array($v, array('sjis','uhc','big5','gb'))) {
2068 $current_style['font-family'] = $v;
2069 $found = 1;
2070 break;
2071 }
2072 }
2073 if (!$found) {
2074 foreach($aux_fontlist AS $f) {
2075 $fonttype = trim($f);
2076 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
2077 $fonttype = preg_replace('/ /','',$fonttype);
2078 $v = strtolower(trim($fonttype));
2079 if (isset($this->mpdf_ref->fonttrans[$v]) && $this->mpdf_ref->fonttrans[$v]) { $v = $this->mpdf_ref->fonttrans[$v]; }
2080 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) ) {
2081 $current_style['font-family'] = $v;
2082 break;
2083 }
2084 }
2085 }
2086 }
2087
2088 if(isset($critere_style['text-anchor'])){
2089 $current_style['text-anchor'] = $critere_style['text-anchor'];
2090 }
2091
2092 // add current style to text style array (will remove it later after writing text to svg_string)
2093 array_push($this->txt_style,$current_style);
2094 }
2095
2096
2097
2098 //
2099 // fonction ajoutant un gradient
2100 function svgAddGradient($id,$array_gradient){
2101
2102 $this->svg_gradient[$id] = $array_gradient;
2103
2104 }
2105 //
2106 // Ajoute une couleur dans le gradient correspondant
2107
2108 //
2109 // function ecrivant dans le svgstring
2110 function svgWriteString($content){
2111
2112 $this->svg_string .= $content;
2113
2114 }
2115
2116
2117
2118 // analise le svg et renvoie aux fonctions precedente our le traitement
2119 function ImageSVG($data){
2120 $this->svg_info = array();
2121
2122 // mPDF 4.4.006
2123 if (preg_match('/<!ENTITY/si',$data)) {
2124 // Get User-defined entities
2125 preg_match_all('/<!ENTITY\s+([a-z]+)\s+\"(.*?)\">/si',$data, $ent);
2126 // Replace entities
2127 for ($i=0; $i<count($ent[0]); $i++) {
2128 $data = preg_replace('/&'.preg_quote($ent[1][$i],'/').';/is', $ent[2][$i], $data);
2129 }
2130 }
2131
2132
2133 if (preg_match('/xlink:href=/si',$data)) {
2134 // GRADIENTS
2135 // Get links
2136 preg_match_all('/(<(linearGradient|radialgradient)[^>]*)xlink:href=["\']#(.*?)["\'](.*?)\/>/si',$data, $links);
2137 if (count($links[0])) { $links[5] = array(); }
2138 // Delete links from data - keeping in $links
2139 for ($i=0; $i<count($links[0]); $i++) {
2140 $links[5][$i] = 'tmpLink'.RAND(100000,9999999);
2141 $data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', '<MYLINKS'.$links[5][$i].'>' , $data);
2142 }
2143 // Get targets
2144 preg_match_all('/<(linearGradient|radialgradient)([^>]*)id=["\'](.*?)["\'](.*?)>(.*?)<\/(linearGradient|radialgradient)>/si',$data, $m);
2145 $targets = array();
2146 $stops = array();
2147 // keeping in $targets
2148 for ($i=0; $i<count($m[0]); $i++) {
2149 $stops[$m[3][$i]] = $m[5][$i];
2150 }
2151 // Add back links this time as targets (gradients)
2152 for ($i=0; $i<count($links[0]); $i++) {
2153 $def = $links[1][$i] .' '.$links[4][$i].'>'. $stops[$links[3][$i]].'</'.$links[2][$i] .'>' ;
2154 $data = preg_replace('/<MYLINKS'.$links[5][$i].'>/is', $def , $data);
2155 }
2156
2157 // mPDF 5.7.2
2158 // <USE>
2159 preg_match_all('/<use ([^>]*)xlink:href=["\']#([^>]*?)["\']([^>]*)\/>/si',$data, $links);
2160 for ($i=0; $i<count($links[0]); $i++) {
2161
2162 // Get the item to use from defs
2163 $insert = '';
2164 if (preg_match('/<([a-zA-Z]*) [^>]*id=["\']'.$links[2][$i].'["\'][^>]*\/>/si',$data, $m)) {
2165 $insert = $m[0];
2166 }
2167 if (!$insert && preg_match('/<([a-zA-Z]*) [^>]*id=["\']'.$links[2][$i].'["\']/si',$data, $m)) {
2168
2169 if (preg_match('/<'.$m[1].'[^>]*id=["\']'.$links[2][$i].'["\'][^>]*>.*?<\/'.$m[1].'>/si',$data, $m)) {
2170 $insert = $m[0];
2171 }
2172 }
2173
2174 if ($insert) {
2175
2176 $inners = $links[1][$i] . ' ' . $links[3][$i];
2177 // Change x,y coords to translate()
2178 if (preg_match('/y=["\']([^>]*?)["\']/', $inners, $m)) { $y = $m[1]; }
2179 else { $y = 0; }
2180 if (preg_match('/x=["\']([^>]*?)["\']/', $inners, $m)) { $x = $m[1]; }
2181 else { $x = 0; }
2182 if ($x || $y) {
2183 $inners = preg_replace('/(y|x)=["\']([^>]*?)["\']/', '', $inners);
2184 if (preg_match('/transform=["\']([^>]*?)["\']/', $inners, $m)) {
2185 if (preg_match('/translate\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/', $m[1], $mm)) {
2186 $transform = $m[1]; // transform="...."
2187 $x += $mm[1];
2188 $y += $mm[2];
2189 $transform = preg_replace('/'.preg_quote($mm[0],'/').'/', '', $transform);
2190 $transform = 'transform="'.$transform.' translate('.$x.', '.$y.')"';
2191 $inners = preg_replace('/'.preg_quote($m[0],'/').'/is', $transform, $inners);
2192 }
2193 else {
2194 $inners = preg_replace('/'.preg_quote($m[0],'/').'/is', 'transform="'.$m[1].' translate('.$x.', '.$y.')"', $inners);
2195 }
2196 }
2197 else {
2198 $inners .= ' transform="translate('.$x.', '.$y.')"';
2199 }
2200 }
2201 }
2202 $replacement = '<g '.$inners.'>'.$insert.'</g>';
2203 $data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', $replacement, $data);
2204 }
2205 preg_match_all('/<use ([^>]*)xlink:href=["\']#([^>]*?)["\']([^>]*)>\s*<\/use>/si',$data, $links);
2206 for ($i=0; $i<count($links[0]); $i++) {
2207
2208 // Get the item to use from defs
2209 $insert = '';
2210 if (preg_match('/<([a-zA-Z]*) [^>]*id=["\']'.$links[2][$i].'["\'][^>]*\/>/si',$data, $m)) {
2211 $insert = $m[0];
2212 }
2213 if (!$insert && preg_match('/<([a-zA-Z]*) [^>]*id=["\']'.$links[2][$i].'["\']/si',$data, $m)) {
2214
2215 if (preg_match('/<'.$m[1].'[^>]*id=["\']'.$links[2][$i].'["\'][^>]*>.*?<\/'.$m[1].'>/si',$data, $m)) {
2216 $insert = $m[0];
2217 }
2218 }
2219
2220 if ($insert) {
2221
2222 $inners = $links[1][$i] . ' ' . $links[3][$i];
2223 // Change x,y coords to translate()
2224 if (preg_match('/y=["\']([^>]*?)["\']/', $inners, $m)) { $y = $m[1]; }
2225 else { $y = 0; }
2226 if (preg_match('/x=["\']([^>]*?)["\']/', $inners, $m)) { $x = $m[1]; }
2227 else { $x = 0; }
2228 if ($x || $y) {
2229 $inners = preg_replace('/(y|x)=["\']([^>]*?)["\']/', '', $inners);
2230 if (preg_match('/transform=["\']([^>]*?)["\']/', $inners, $m)) {
2231 if (preg_match('/translate\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/', $m[1], $mm)) {
2232 $transform = $m[1]; // transform="...."
2233 $x += $mm[1];
2234 $y += $mm[2];
2235 $transform = preg_replace('/'.preg_quote($mm[0],'/').'/', '', $transform);
2236 $transform = 'transform="'.$transform.' translate('.$x.', '.$y.')"';
2237 $inners = preg_replace('/'.preg_quote($m[0],'/').'/is', $transform, $inners);
2238 }
2239 else {
2240 $inners = preg_replace('/'.preg_quote($m[0],'/').'/is', 'transform="'.$m[1].' translate('.$x.', '.$y.')"', $inners);
2241 }
2242 }
2243 else {
2244 $inners .= ' transform="translate('.$x.', '.$y.')"';
2245 }
2246 }
2247 $replacement = '<g '.$inners.'>'.$insert.'</g>';
2248 $data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', $replacement, $data);
2249
2250
2251 }
2252 }
2253 }
2254 // Removes <pattern>
2255 $data = preg_replace('/<pattern.*?<\/pattern>/is', '', $data);
2256 // Removes <marker>
2257 $data = preg_replace('/<marker.*?<\/marker>/is', '', $data);
2258
2259 $this->svg_info['data'] = $data;
2260
2261 $this->svg_string = '';
2262
2263 //
2264 // chargement unique des fonctions
2265 if(!function_exists("xml_svg2pdf_start")){
2266
2267 function xml_svg2pdf_start($parser, $name, $attribs){
2268 //
2269 // definition
2270 global $svg_class, $last_gradid;
2271
2272 // mPDF 5.7.2
2273 if (strtolower($name) == 'lineargradient'){
2274 $tmp_gradient = array(
2275 'type' => 'linear',
2276 'info' => array(
2277 'x1' => $attribs['x1'],
2278 'y1' => $attribs['y1'],
2279 'x2' => $attribs['x2'],
2280 'y2' => $attribs['y2']
2281 ),
2282 'transform' => $attribs['gradientTransform'],
2283 'units' => $attribs['gradientUnits'],
2284 'spread' => $attribs['spreadMethod'],
2285 'color' => array()
2286 );
2287 $last_gradid = $attribs['id'];
2288 $svg_class->svgAddGradient($attribs['id'],$tmp_gradient);
2289 return;
2290 }
2291 else if (strtolower($name) == 'radialgradient'){
2292 $tmp_gradient = array(
2293 'type' => 'radial',
2294 'info' => array(
2295 'x0' => $attribs['cx'],
2296 'y0' => $attribs['cy'],
2297 'x1' => $attribs['fx'],
2298 'y1' => $attribs['fy'],
2299 'r' => $attribs['r']
2300 ),
2301 'transform' => $attribs['gradientTransform'],
2302 'units' => $attribs['gradientUnits'],
2303 'spread' => $attribs['spreadMethod'],
2304 'color' => array()
2305 );
2306 $last_gradid = $attribs['id'];
2307 $svg_class->svgAddGradient($attribs['id'],$tmp_gradient);
2308 return;
2309 }
2310 else if (strtolower($name) == 'stop'){
2311 if (!$last_gradid) break;
2312 if (isset($attribs['style']) AND preg_match('/stop-color:\s*([^;]*)/i',$attribs['style'],$m)) {
2313 $color = trim($m[1]);
2314 } else if (isset($attribs['stop-color'])) {
2315 $color = $attribs['stop-color'];
2316 }
2317 $col = $svg_class->mpdf_ref->ConvertColor($color);
2318
2319 if ($col{0}==3 || $col{0}==5) { // RGB
2320 $color_final = sprintf('%.3F %.3F %.3F',ord($col{1})/255,ord($col{2})/255,ord($col{3})/255);
2321 $svg_class->svg_gradient[$last_gradid]['colorspace']='RGB';
2322 }
2323 else if ($col{0}==4 || $col{0}==6) { // CMYK
2324 $color_final = sprintf('%.3F %.3F %.3F %.3F',ord($col{1})/100,ord($col{2})/100,ord($col{3})/100,ord($col{4})/100);
2325 $svg_class->svg_gradient[$last_gradid]['colorspace']='CMYK';
2326 }
2327 else if ($col{0}==1) { // Grayscale
2328 $color_final = sprintf('%.3F',ord($col{1})/255);
2329 $svg_class->svg_gradient[$last_gradid]['colorspace']='Gray';
2330 }
2331
2332 $stop_opacity = 1;
2333 if (isset($attribs['style']) AND preg_match('/stop-opacity:\s*([0-9.]*)/i',$attribs['style'],$m)) {
2334 $stop_opacity = $m[1];
2335 } else if (isset($attribs['stop-opacity'])) {
2336 $stop_opacity = $attribs['stop-opacity'];
2337 }
2338 else if ($col{0}==5) { // RGBa
2339 $stop_opacity = ord($col{4}/100);
2340 }
2341 else if ($col{0}==6) { // CMYKa
2342 $stop_opacity = ord($col{5}/100);
2343 }
2344
2345 $tmp_color = array(
2346 'color' => $color_final,
2347 'offset' => $attribs['offset'],
2348 'opacity' => $stop_opacity
2349 );
2350 array_push($svg_class->svg_gradient[$last_gradid]['color'],$tmp_color);
2351 return;
2352 }
2353 if ($svg_class->inDefs) { return; }
2354
2355 $svg_class->xbase = 0;
2356 $svg_class->ybase = 0;
2357 switch (strtolower($name)){
2358
2359 // mPDF 5.0.039 - Don't output stuff inside <defs>
2360 case 'defs':
2361 $svg_class->inDefs = true;
2362 return;
2363
2364 case 'svg':
2365 $svg_class->svgOffset($attribs);
2366 break;
2367
2368 case 'path':
2369 $path = $attribs['d'];
2370 // mPDF 5.6.65
2371 preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $path, $commands, PREG_SET_ORDER);
2372 $path_cmd = '';
2373 $svg_class->subPathInit = true;
2374 // mPDF 5.0.039
2375 $svg_class->pathBBox = array(999999,999999,-999999,-999999);
2376 foreach($commands as $c){
2377 if(count($c)==3 || $c[2]==''){
2378 list($tmp, $command, $arguments) = $c;
2379 }
2380 else{
2381 list($tmp, $command) = $c;
2382 $arguments = '';
2383 }
2384
2385 $path_cmd .= $svg_class->svgPath($command, $arguments);
2386 }
2387 // mPDF 5.0.039
2388 if ($svg_class->pathBBox[2]==-1999998) { $svg_class->pathBBox[2] = 100; }
2389 if ($svg_class->pathBBox[3]==-1999998) { $svg_class->pathBBox[3] = 100; }
2390 if ($svg_class->pathBBox[0]==999999) { $svg_class->pathBBox[0] = 0; }
2391 if ($svg_class->pathBBox[1]==999999) { $svg_class->pathBBox[1] = 0; }
2392 $critere_style = $attribs;
2393 unset($critere_style['d']);
2394 $path_style = $svg_class->svgDefineStyle($critere_style);
2395 break;
2396
2397 case 'rect':
2398 if (!isset($attribs['x'])) {$attribs['x'] = 0;}
2399 if (!isset($attribs['y'])) {$attribs['y'] = 0;}
2400 if (!isset($attribs['rx'])) {$attribs['rx'] = 0;}
2401 if (!isset($attribs['ry'])) {$attribs['ry'] = 0;}
2402 $arguments = array(
2403 'x' => $attribs['x'],
2404 'y' => $attribs['y'],
2405 'w' => $attribs['width'],
2406 'h' => $attribs['height'],
2407 'rx' => $attribs['rx'],
2408 'ry' => $attribs['ry']
2409 );
2410 $path_cmd = $svg_class->svgRect($arguments);
2411 $critere_style = $attribs;
2412 unset($critere_style['x'],$critere_style['y'],$critere_style['rx'],$critere_style['ry'],$critere_style['height'],$critere_style['width']);
2413 $path_style = $svg_class->svgDefineStyle($critere_style);
2414 break;
2415
2416 case 'circle':
2417 if (!isset($attribs['cx'])) {$attribs['cx'] = 0;}
2418 if (!isset($attribs['cy'])) {$attribs['cy'] = 0;}
2419 $arguments = array(
2420 'cx' => $attribs['cx'],
2421 'cy' => $attribs['cy'],
2422 'rx' => $attribs['r'],
2423 'ry' => $attribs['r']
2424 );
2425 $path_cmd = $svg_class->svgEllipse($arguments);
2426 $critere_style = $attribs;
2427 unset($critere_style['cx'],$critere_style['cy'],$critere_style['r']);
2428 $path_style = $svg_class->svgDefineStyle($critere_style);
2429 break;
2430
2431 case 'ellipse':
2432 if (!isset($attribs['cx'])) {$attribs['cx'] = 0;}
2433 if (!isset($attribs['cy'])) {$attribs['cy'] = 0;}
2434 $arguments = array(
2435 'cx' => $attribs['cx'],
2436 'cy' => $attribs['cy'],
2437 'rx' => $attribs['rx'],
2438 'ry' => $attribs['ry']
2439 );
2440 $path_cmd = $svg_class->svgEllipse($arguments);
2441 $critere_style = $attribs;
2442 unset($critere_style['cx'],$critere_style['cy'],$critere_style['rx'],$critere_style['ry']);
2443 $path_style = $svg_class->svgDefineStyle($critere_style);
2444 break;
2445
2446 case 'line':
2447 $arguments = array($attribs['x1'],$attribs['y1'],$attribs['x2'],$attribs['y2']);
2448 $path_cmd = $svg_class->svgPolyline($arguments,false); // mPDF 4.4.003
2449 $critere_style = $attribs;
2450 unset($critere_style['x1'],$critere_style['y1'],$critere_style['x2'],$critere_style['y2']);
2451 $path_style = $svg_class->svgDefineStyle($critere_style);
2452 break;
2453
2454 case 'polyline':
2455 $path = $attribs['points'];
2456 preg_match_all('/[0-9\-\.]*/',$path, $tmp, PREG_SET_ORDER);
2457 $arguments = array();
2458 for ($i=0;$i<count($tmp);$i++){
2459 if ($tmp[$i][0] !=''){
2460 array_push($arguments, $tmp[$i][0]);
2461 }
2462 }
2463 $path_cmd = $svg_class->svgPolyline($arguments);
2464 $critere_style = $attribs;
2465 unset($critere_style['points']);
2466 $path_style = $svg_class->svgDefineStyle($critere_style);
2467 break;
2468
2469 case 'polygon':
2470 $path = $attribs['points'];
2471 preg_match_all('/([\-]*[0-9\.]+)/',$path, $tmp);
2472 $arguments = array();
2473 for ($i=0;$i<count($tmp[0]);$i++){
2474 if ($tmp[0][$i] !=''){
2475 array_push($arguments, $tmp[0][$i]);
2476 }
2477 }
2478 $path_cmd = $svg_class->svgPolygon($arguments);
2479 // definition du style de la forme:
2480 $critere_style = $attribs;
2481 unset($critere_style['points']);
2482 $path_style = $svg_class->svgDefineStyle($critere_style);
2483 break;
2484
2485 case 'a':
2486 if (isset($attribs['xlink:href'])) {
2487 unset($attribs['xlink:href']); // this should be a hyperlink
2488 // not handled like a xlink:href in other elements
2489 } // then continue like a <g>
2490 case 'g':
2491 $array_style = $svg_class->svgDefineStyle($attribs);
2492 if ($array_style['transformations']) {
2493 $svg_class->svgWriteString(' q '.$array_style['transformations']);
2494 }
2495 array_push($svg_class->svg_style,$array_style);
2496
2497 $svg_class->svgDefineTxtStyle($attribs); // mPDF 4.4.003
2498
2499 break;
2500
2501 case 'text':
2502 $array_style = $svg_class->svgDefineStyle($attribs);
2503 if ($array_style['transformations']) {
2504 $svg_class->svgWriteString(' q '.$array_style['transformations']);
2505 }
2506 array_push($svg_class->svg_style,$array_style);
2507
2508 $svg_class->txt_data = array();
2509 $svg_class->txt_data[0] = $attribs['x'];
2510 $svg_class->txt_data[1] = $attribs['y'];
2511 $critere_style = $attribs;
2512 unset($critere_style['x'], $critere_style['y']);
2513 $svg_class->svgDefineTxtStyle($critere_style);
2514 break;
2515 }
2516
2517 //
2518 //insertion des path et du style dans le flux de donné general.
2519 if (isset($path_cmd) && $path_cmd) { // mPDF 4.4.003
2520 // mPDF 5.0
2521 list($prestyle,$poststyle) = $svg_class->svgStyle($path_style, $attribs, strtolower($name));
2522 if ($path_style['transformations']) { // transformation on an element
2523 $svg_class->svgWriteString(" q ".$path_style['transformations']. " $prestyle $path_cmd $poststyle" . " Q\n");
2524 }
2525 else {
2526 $svg_class->svgWriteString("$prestyle $path_cmd $poststyle\n");
2527 }
2528 }
2529 }
2530
2531 function characterData($parser, $data)
2532 {
2533 global $svg_class;
2534 if ($svg_class->inDefs) { return; } // mPDF 5.7.2
2535 if(isset($svg_class->txt_data[2])) {
2536 $svg_class->txt_data[2] .= $data;
2537 }
2538 else {
2539 $svg_class->txt_data[2] = $data;
2540 }
2541 }
2542
2543
2544 function xml_svg2pdf_end($parser, $name){
2545 global $svg_class;
2546 // Don't output stuff inside <defs>
2547 // mPDF 5.7.2
2548 if ($name == 'defs') {
2549 $svg_class->inDefs = false;
2550 return;
2551 }
2552 if ($svg_class->inDefs) { return; }
2553 switch($name){
2554
2555 case "g":
2556 case "a":
2557 $tmp = count($svg_class->svg_style)-1;
2558 $current_style = $svg_class->svg_style[$tmp];
2559 if ($current_style['transformations']) {
2560 $svg_class->svgWriteString(" Q\n");
2561 }
2562 array_pop($svg_class->svg_style);
2563
2564 array_pop($svg_class->txt_style); // mPDF 4.4.003
2565
2566 break;
2567 case 'radialgradient':
2568 case 'lineargradient':
2569 $last_gradid = '';
2570 break;
2571 case "text":
2572 $path_cmd = $svg_class->svgText();
2573 // echo 'path >> '.$path_cmd."<br><br>";
2574 // echo "style >> ".$get_style[1]."<br><br>";
2575 $svg_class->svgWriteString($path_cmd);
2576 // mPDF 4.4.003
2577 $tmp = count($svg_class->svg_style)-1;
2578 $current_style = $svg_class->svg_style[$tmp];
2579 if ($current_style['transformations']) {
2580 $svg_class->svgWriteString(" Q\n");
2581 }
2582 array_pop($svg_class->svg_style);
2583
2584 break;
2585 }
2586 // mPDF 5.0.039 - Don't output stuff inside <defs>
2587 if ($name == 'defs') {
2588 $svg_class->inDefs = false;
2589 }
2590
2591 }
2592
2593 }
2594
2595 $svg2pdf_xml='';
2596 global $svg_class;
2597 $svg_class = $this;
2598 // mPDF 5.0.039 - Don't output stuff inside <defs>
2599 $svg_class->inDefs = false;
2600 $svg2pdf_xml_parser = xml_parser_create("utf-8");
2601 xml_parser_set_option($svg2pdf_xml_parser, XML_OPTION_CASE_FOLDING, false);
2602 xml_set_element_handler($svg2pdf_xml_parser, "xml_svg2pdf_start", "xml_svg2pdf_end");
2603 xml_set_character_data_handler($svg2pdf_xml_parser, "characterData");
2604 xml_parse($svg2pdf_xml_parser, $data);
2605 // mPDF 4.4.003
2606 if ($this->svg_error) { return false; }
2607 else {
2608 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);
2609 }
2610
2611 }
2612
2613 }
2614
2615 // END OF CLASS
2616
2617
2618 // mPDF 5.0.040
2619 function calc_bezier_bbox($start, $c) {
2620 $P0 = array($start[0],$start[1]);
2621 $P1 = array($c[0],$c[1]);
2622 $P2 = array($c[2],$c[3]);
2623 $P3 = array($c[4],$c[5]);
2624 $bounds = array();
2625 $bounds[0][] = $P0[0];
2626 $bounds[1][] = $P0[1];
2627 $bounds[0][] = $P3[0];
2628 $bounds[1][] = $P3[1];
2629 for ($i=0;$i<=1;$i++) {
2630 $b = 6 * $P0[$i] - 12 * $P1[$i] + 6 * $P2[$i];
2631 $a = -3 * $P0[$i] + 9 * $P1[$i] - 9 * $P2[$i] + 3 * $P3[$i];
2632 $c = 3 * $P1[$i] - 3 * $P0[$i];
2633 if ($a == 0) {
2634 if ($b == 0) { continue; }
2635 $t = -$c / $b;
2636 if ($t>0 && $t<1) {
2637 $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]);
2638 }
2639 continue;
2640 }
2641 $b2ac = pow($b, 2) - 4 * $c * $a;
2642 if ($b2ac < 0) { continue; }
2643 $t1 = (-$b + sqrt($b2ac))/(2 * $a);
2644 if ($t1>0 && $t1<1) {
2645 $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]);
2646 }
2647 $t2 = (-$b - sqrt($b2ac))/(2 * $a);
2648 if ($t2>0 && $t2<1) {
2649 $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]);
2650 }
2651 }
2652 $x = min($bounds[0]);
2653 $x2 = max($bounds[0]);
2654 $y = min($bounds[1]);
2655 $y2 = max($bounds[1]);
2656 return array($x, $y, $x2, $y2);
2657 }
2658
2659 // mPDF 5.0.040
2660 function _testIntersectCircle($cx, $cy, $cr) {
2661 // Tests whether a circle fully encloses a rectangle 0,0,1,1
2662 // to see if any further radial gradients need adding (SVG)
2663 // If centre of circle is inside 0,0,1,1 square
2664 if ($cx >= 0 && $cx <= 1 && $cy >= 0 && $cy <= 1) {
2665 $maxd = 1.5;
2666 }
2667 // distance to four corners
2668 else {
2669 $d1 = sqrt(pow(($cy-0),2) + pow(($cx-0),2));
2670 $d2 = sqrt(pow(($cy-1),2) + pow(($cx-0),2));
2671 $d3 = sqrt(pow(($cy-0),2) + pow(($cx-1),2));
2672 $d4 = sqrt(pow(($cy-1),2) + pow(($cx-1),2));
2673 $maxd = max($d1,$d2,$d3,$d4);
2674 }
2675 if ($cr < $maxd) { return true; }
2676 else { return false; }
2677 }
2678
2679 // mPDF 5.0.040
2680 function _testIntersect($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4) {
2681 // Tests whether line (x1, y1) and (x2, y2) [a gradient axis (perpendicular)]
2682 // intersects with a specific line segment (x3, y3) and (x4, y4)
2683 $a1 = $y2-$y1;
2684 $b1 = $x1-$x2;
2685 $c1 = $a1*$x1+$b1*$y1;
2686 $a2 = $y4-$y3;
2687 $b2 = $x3-$x4;
2688 $c2 = $a2*$x3+$b2*$y3;
2689 $det = $a1*$b2 - $a2*$b1;
2690 if($det == 0){ //Lines are parallel
2691 return false;
2692 }
2693 else{
2694 $x = ($b2*$c1 - $b1*$c2)/$det;
2695 $y = ($a1*$c2 - $a2*$c1)/$det;
2696 if ($x >= $x3 && $x <= $x4 && $y >= $y3 && $y <= $y4) { return true; }
2697 }
2698 return false;
2699 }
2700
2701
2702
2703 ?>