Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

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