PluginProbe
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin / 1.7
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin v1.7
trunk 1.5 1.6 1.7 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 All 71 releases
pdf-print / mpdf / classes / svg.php

svg.php in PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin 1.7, at mpdf/classes/svg.php

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