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

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

3,441 lines 129.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // svg class modified for mPDF version 6.0 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 // If you wish to use Automatic Font selection within SVG's. change this definition to true.
12 // This selects different fonts for different scripts used in text.
13 // This can be enabled/disabled independently of the use of Automatic Font selection within mPDF generally.
14 // Choice of font is determined by the config_script2lang.php and config_lang2fonts.php files, the same as for mPDF generally.
15 if (!defined("_SVG_AUTOFONT")) { define("_SVG_AUTOFONT", false); }
16
17 // Enable a limited use of classes within SVG <text> elements by setting this to true.
18 // This allows recognition of a "class" attribute on a <text> element.
19 // The CSS style for that class should be outside the SVG, and cannot use any other selectors (i.e. only .class {} can be defined)
20 // <style> definitions within the SVG code will be recognised if the SVG is included as an inline item within the HTML code passed to mPDF.
21 // The style property should be pertinent to SVG e.g. use fill:red rather than color:red
22 // Only the properties currently supported for SVG text can be specified:
23 // fill, fill-opacity, stroke, stroke-opacity, stroke-linecap, stroke-linejoin, stroke-width, stroke-dasharray, stroke-dashoffset
24 // font-family, font-size, font-weight, font-variant, font-style, opacity, text-anchor
25 if (!defined("_SVG_CLASSES")) { define("_SVG_CLASSES", false); }
26
27
28
29
30 // NB UNITS - Works in pixels as main units - converting to PDF units when outputing to PDF string
31 // and on returning size
32
33 class SVG {
34
35 var $svg_font; // array - holds content of SVG fonts defined in image // mPDF 6
36 var $svg_gradient; // array - contient les infos sur les gradient fill du svg class� par id du svg
37 var $svg_shadinglist; // array - contient les ids des objet shading
38 var $svg_info; // array contenant les infos du svg voulue par l'utilisateur
39 var $svg_attribs; // array - holds all attributes of root <svg> tag
40 var $svg_style; // array contenant les style de groupes du svg
41 var $svg_string; // String contenant le tracage du svg en lui m�me.
42 var $txt_data; // array - holds string info to write txt to image
43 var $txt_style; // array - current text style
44 var $mpdf_ref;
45 var $xbase;
46 var $ybase;
47 var $svg_error;
48 var $subPathInit;
49 var $spxstart;
50 var $spystart;
51 var $kp; // convert pixels to PDF units
52 var $pathBBox;
53
54 var $script2lang;
55 var $viet;
56 var $pashto;
57 var $urdu;
58 var $persian;
59 var $sindhi;
60
61 var $textlength; // mPDF 5.7.4
62 var $texttotallength; // mPDF 5.7.4
63 var $textoutput; // mPDF 5.7.4
64 var $textanchor; // mPDF 5.7.4
65 var $textXorigin; // mPDF 5.7.4
66 var $textYorigin; // mPDF 5.7.4
67 var $textjuststarted; // mPDF 5.7.4
68 var $intext; // mPDF 5.7.4
69
70 function SVG(&$mpdf){
71 $this->svg_font = array(); // mPDF 6
72 $this->svg_gradient = array();
73 $this->svg_shadinglist = array();
74 $this->txt_data = array();
75 $this->svg_string = '';
76 $this->svg_info = array();
77 $this->svg_attribs = array();
78 $this->xbase = 0;
79 $this->ybase = 0;
80 $this->svg_error = false;
81 $this->subPathInit = false;
82 $this->dashesUsed = false;
83 $this->mpdf_ref =& $mpdf;
84
85 $this->textlength = 0; // mPDF 5.7.4
86 $this->texttotallength = 0; // mPDF 5.7.4
87 $this->textoutput = ''; // mPDF 5.7.4
88 $this->textanchor = 'start'; // mPDF 5.7.4
89 $this->textXorigin = 0; // mPDF 5.7.4
90 $this->textYorigin = 0; // mPDF 5.7.4
91 $this->textjuststarted = false; // mPDF 5.7.4
92 $this->intext = false; // mPDF 5.7.4
93
94 $this->kp = 72 / $mpdf->img_dpi; // constant To convert pixels to pts/PDF units
95 $this->kf = 1; // constant To convert font size if re-mapped
96 $this->pathBBox = array();
97
98 $this->svg_style = array(
99 array(
100 'fill' => 'black',
101 'fill-opacity' => 1, // remplissage opaque par defaut
102 'fill-rule' => 'nonzero', // mode de remplissage par defaut
103 'stroke' => 'none', // pas de trait par defaut
104 'stroke-linecap' => 'butt', // style de langle par defaut
105 'stroke-linejoin' => 'miter',
106 'stroke-miterlimit' => 4, // limite de langle par defaut
107 'stroke-opacity' => 1, // trait opaque par defaut
108 'stroke-width' => 1,
109 'stroke-dasharray' => 0,
110 'stroke-dashoffset' => 0,
111 'color' => ''
112 )
113 );
114
115 $this->txt_style = array(
116 array(
117 'fill' => 'black', // pas de remplissage par defaut
118 'font-family' => $mpdf->default_font,
119 'font-size' => $mpdf->default_font_size, // ****** this is pts
120 'font-weight' => 'normal', // normal | bold
121 'font-style' => 'normal', // italic | normal
122 'text-anchor' => 'start', // alignment: start, middle, end
123 'fill-opacity' => 1, // remplissage opaque par defaut
124 'fill-rule' => 'nonzero', // mode de remplissage par defaut
125 'stroke' => 'none', // pas de trait par defaut
126 'stroke-opacity' => 1, // trait opaque par defaut
127 'stroke-width' => 1,
128 'color' => ''
129 )
130 );
131
132
133
134 }
135
136 // mPDF 5.7.4 Embedded image
137 function svgImage($attribs) {
138 // x and y are coordinates
139 $x = (isset($attribs['x']) ? $attribs['x'] : 0);
140 $y = (isset($attribs['y']) ? $attribs['y'] : 0);
141 // preserveAspectRatio
142 $par = (isset($attribs['preserveAspectRatio']) ? $attribs['preserveAspectRatio'] : 'xMidYMid meet');
143 // width and height are <lengths> - Required attributes
144 $wset = (isset($attribs['width']) ? $attribs['width'] : 0);
145 $hset = (isset($attribs['height']) ? $attribs['height'] : 0);
146 $w = $this->mpdf_ref->ConvertSize($wset,$this->svg_info['w']*(25.4/$this->mpdf_ref->dpi),$this->mpdf_ref->FontSize,false);
147 $h = $this->mpdf_ref->ConvertSize($hset,$this->svg_info['h']*(25.4/$this->mpdf_ref->dpi),$this->mpdf_ref->FontSize,false);
148 if ($w==0 || $h==0) { return; }
149 // Convert to pixels = SVG units
150 $w *= 1/(25.4/$this->mpdf_ref->dpi);
151 $h *= 1/(25.4/$this->mpdf_ref->dpi);
152
153 $srcpath = $attribs['xlink:href'];
154 $orig_srcpath = '';
155 if (trim($srcpath) != '' && substr($srcpath,0,4)=='var:') {
156 $orig_srcpath = $srcpath;
157 $this->mpdf_ref->GetFullPath($srcpath);
158 }
159
160 // Image file (does not allow vector images i.e. WMF/SVG)
161 // mPDF 6 Added $this->mpdf_ref->interpolateImages
162 $info = $this->mpdf_ref->_getImage($srcpath, true, false, $orig_srcpath, $this->mpdf_ref->interpolateImages);
163 if(!$info) return;
164
165 // x,y,w,h define the reference rectangle
166 $img_h = $h;
167 $img_w = $w;
168 $img_x = $x;
169 $img_y = $y;
170 $meetOrSlice = 'meet';
171
172 // preserveAspectRatio
173 $ar = preg_split('/\s+/', strtolower($par));
174 if ($ar[0]!='none') { // If "none" need to do nothing
175 // Force uniform scaling
176 if (isset($ar[1]) && $ar[1]=='slice') { $meetOrSlice = 'slice'; }
177 else { $meetOrSlice = 'meet'; }
178 if ($info['h']/$info['w'] > $h/$w) {
179 if ($meetOrSlice == 'meet') { // the entire viewBox is visible within the viewport
180 $img_w = $img_h * $info['w']/$info['h'];
181 }
182 else { // the entire viewport is covered by the viewBox
183 $img_h = $img_w * $info['h']/$info['w'];
184 }
185 }
186 else if ($info['h']/$info['w'] < $h/$w) {
187 if ($meetOrSlice == 'meet') { // the entire viewBox is visible within the viewport
188 $img_h = $img_w * $info['h']/$info['w'];
189 }
190 else { // the entire viewport is covered by the viewBox
191 $img_w = $img_h * $info['w']/$info['h'];
192 }
193 }
194 if ($ar[0]=='xminymin') {
195 // do nothing to x
196 // do nothing to y
197 }
198 else if ($ar[0]=='xmidymin') {
199 $img_x += $w/2 - $img_w/2; // xMid
200 // do nothing to y
201 }
202 else if ($ar[0]=='xmaxymin') {
203 $img_x += $w - $img_w; // xMax
204 // do nothing to y
205 }
206 else if ($ar[0]=='xminymid') {
207 // do nothing to x
208 $img_y += $h/2 - $img_h/2; // yMid
209 }
210 else if ($ar[0]=='xmaxymid') {
211 $img_x += $w - $img_w; // xMax
212 $img_y += $h/2 - $img_h/2; // yMid
213 }
214 else if ($ar[0]=='xminymax') {
215 // do nothing to x
216 $img_y += $h - $img_h; // yMax
217 }
218 else if ($ar[0]=='xmidymax') {
219 $img_x += $w/2 - $img_w/2; // xMid
220 $img_y += $h - $img_h; // yMax
221 }
222 else if ($ar[0]=='xmaxymax') {
223 $img_x += $w - $img_w; // xMax
224 $img_y += $h - $img_h; // yMax
225 }
226 else { // xMidYMid (the default)
227 $img_x += $w/2 - $img_w/2; // xMid
228 $img_y += $h/2 - $img_h/2; // yMid
229 }
230 }
231
232 // Output
233 if ($meetOrSlice == 'slice') { // need to add a clipping path to reference rectangle
234 $s = ' q 0 w '; // Line width=0
235 $s .= sprintf('%.3F %.3F m ', ($x)*$this->kp, (-($y+$h))*$this->kp); // start point TL before the arc
236 $s .= sprintf('%.3F %.3F l ', ($x)*$this->kp, (-($y))*$this->kp); // line to BL
237 $s .= sprintf('%.3F %.3F l ', ($x+$w)*$this->kp, (-($y))*$this->kp); // line to BR
238 $s .= sprintf('%.3F %.3F l ', ($x+$w)*$this->kp, (-($y+$h))*$this->kp); // line to TR
239 $s .= sprintf('%.3F %.3F l ', ($x)*$this->kp, (-($y+$h))*$this->kp); // line to TL
240 $s .= ' W n '; // Ends path no-op & Sets the clipping path
241 $this->svgWriteString($s);
242 }
243
244 $outstring = sprintf(" q %.3F 0 0 %.3F %.3F %.3F cm /I%d Do Q ",$img_w*$this->kp, $img_h*$this->kp, $img_x*$this->kp, -($img_y+$img_h)*$this->kp, $info['i'] );
245 $this->svgWriteString($outstring);
246
247 if ($meetOrSlice == 'slice') { // need to end clipping path
248 $this->svgWriteString(' Q ');
249 }
250 }
251
252
253 function svgGradient($gradient_info, $attribs, $element){
254 $n = count($this->mpdf_ref->gradients)+1;
255
256 // Get bounding dimensions of element
257 $w = 100;
258 $h = 100;
259 $x_offset = 0;
260 $y_offset = 0;
261 if ($element=='rect') {
262 $w = $attribs['width'];
263 $h = $attribs['height'];
264 $x_offset = $attribs['x'];
265 $y_offset = $attribs['y'];
266 }
267 else if ($element=='ellipse') {
268 $w = $attribs['rx']*2;
269 $h = $attribs['ry']*2;
270 $x_offset = $attribs['cx']-$attribs['rx'];
271 $y_offset = $attribs['cy']-$attribs['ry'];
272 }
273 else if ($element=='circle') {
274 $w = $attribs['r']*2;
275 $h = $attribs['r']*2;
276 $x_offset = $attribs['cx']-$attribs['r'];
277 $y_offset = $attribs['cy']-$attribs['r'];
278 }
279 else if ($element=='polygon') {
280 $pts = preg_split('/[ ,]+/', trim($attribs['points']));
281 $maxr=$maxb=0;
282 $minl=$mint=999999;
283 for ($i=0;$i<count($pts); $i++) {
284 if ($i % 2 == 0) { // x values
285 $minl = min($minl,$pts[$i]);
286 $maxr = max($maxr,$pts[$i]);
287 }
288 else { // y values
289 $mint = min($mint,$pts[$i]);
290 $maxb = max($maxb,$pts[$i]);
291 }
292 }
293 $w = $maxr-$minl;
294 $h = $maxb-$mint;
295 $x_offset = $minl;
296 $y_offset = $mint;
297 }
298 else if ($element=='path') {
299 if (is_array($this->pathBBox) && $this->pathBBox[2]>0) {
300 $w = $this->pathBBox[2];
301 $h = $this->pathBBox[3];
302 $x_offset = $this->pathBBox[0];
303 $y_offset = $this->pathBBox[1];
304 }
305 else {
306 preg_match_all('/([a-z]|[A-Z])([ ,\-.\d]+)*/', $attribs['d'], $commands, PREG_SET_ORDER);
307 $maxr=$maxb=0;
308 $minl=$mint=999999;
309 foreach($commands as $c){
310 if(count($c)==3){
311 list($tmp, $cmd, $arg) = $c;
312 if ($cmd=='M' || $cmd=='L' || $cmd=='C' || $cmd=='S' || $cmd=='Q' || $cmd=='T') {
313 $pts = preg_split('/[ ,]+/', trim($arg));
314 for ($i=0;$i<count($pts); $i++) {
315 if ($i % 2 == 0) { // x values
316 $minl = min($minl,$pts[$i]);
317 $maxr = max($maxr,$pts[$i]);
318 }
319 else { // y values
320 $mint = min($mint,$pts[$i]);
321 $maxb = max($maxb,$pts[$i]);
322 }
323 }
324 }
325 if ($cmd=='H') { // sets new x
326 $minl = min($minl,$arg);
327 $maxr = max($maxr,$arg);
328 }
329 if ($cmd=='V') { // sets new y
330 $mint = min($mint,$arg);
331 $maxb = max($maxb,$arg);
332 }
333 }
334 }
335 $w = $maxr-$minl;
336 $h = $maxb-$mint;
337 $x_offset = $minl;
338 $y_offset = $mint;
339 }
340 }
341 if (!$w || $w==-999999) { $w = 100; }
342 if (!$h || $h==-999999) { $h = 100; }
343 if ($x_offset==999999) { $x_offset = 0; }
344 if ($y_offset==999999) { $y_offset = 0; }
345
346 // TRANSFORMATIONS
347 $transformations = '';
348 if (isset($gradient_info['transform'])){
349 preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)\((.*?)\)/is',$gradient_info['transform'],$m);
350 if (count($m[0])) {
351 for($i=0; $i<count($m[0]); $i++) {
352 $c = strtolower($m[1][$i]);
353 $v = trim($m[2][$i]);
354 $vv = preg_split('/[ ,]+/',$v);
355 if ($c=='matrix' && count($vv)==6) {
356 // Note angle of rotation is reversed (from SVG to PDF), so vv[1] and vv[2] are negated
357 // cf svgDefineStyle()
358 $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);
359 }
360 else if ($c=='translate' && count($vv)) {
361 $tm[4] = $vv[0];
362 if (count($vv)==2) { $t_y = -$vv[1]; }
363 else { $t_y = 0; }
364 $tm[5] = $t_y;
365 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $tm[4]*$this->kp, $tm[5]*$this->kp);
366 }
367 else if ($c=='scale' && count($vv)) {
368 if (count($vv)==2) { $s_y = $vv[1]; }
369 else { $s_y = $vv[0]; }
370 $tm[0] = $vv[0];
371 $tm[3] = $s_y;
372 $transformations .= sprintf(' %.3F 0 0 %.3F 0 0 cm ', $tm[0], $tm[3]);
373 }
374 else if ($c=='rotate' && count($vv)) {
375 $tm[0] = cos(deg2rad(-$vv[0]));
376 $tm[1] = sin(deg2rad(-$vv[0]));
377 $tm[2] = -$tm[1];
378 $tm[3] = $tm[0];
379 if (count($vv)==3) {
380 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $vv[1]*$this->kp, -$vv[2]*$this->kp);
381 }
382 $transformations .= sprintf(' %.3F %.3F %.3F %.3F 0 0 cm ', $tm[0], $tm[1], $tm[2], $tm[3]);
383 if (count($vv)==3) {
384 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', -$vv[1]*$this->kp, $vv[2]*$this->kp);
385 }
386 }
387 else if ($c=='skewx' && count($vv)) {
388 $tm[2] = tan(deg2rad(-$vv[0]));
389 $transformations .= sprintf(' 1 0 %.3F 1 0 0 cm ', $tm[2]);
390 }
391 else if ($c=='skewy' && count($vv)) {
392 $tm[1] = tan(deg2rad(-$vv[0]));
393 $transformations .= sprintf(' 1 %.3F 0 1 0 0 cm ', $tm[1]);
394 }
395
396 }
397 }
398 }
399
400
401 $return = "";
402
403 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
404 if ($transformations) { $return .= $transformations; }
405 }
406 $spread = 'P'; // pad
407 if (isset($gradient_info['spread'])) {
408 if (strtolower($gradient_info['spread'])=='reflect') { $spread = 'F'; } // reflect
409 else if (strtolower($gradient_info['spread'])=='repeat') { $spread = 'R'; } // repeat
410 }
411
412
413 for ($i=0; $i<(count($gradient_info['color'])); $i++) {
414 if (stristr($gradient_info['color'][$i]['offset'], '%')!== false) { $gradient_info['color'][$i]['offset'] = ($gradient_info['color'][$i]['offset']+0)/100; }
415 if (isset($gradient_info['color'][($i+1)]['offset']) && stristr($gradient_info['color'][($i+1)]['offset'], '%')!== false) { $gradient_info['color'][($i+1)]['offset'] = ($gradient_info['color'][($i+1)]['offset']+0)/100; }
416 if ($gradient_info['color'][$i]['offset']<0) { $gradient_info['color'][$i]['offset'] = 0; }
417 if ($gradient_info['color'][$i]['offset']>1) { $gradient_info['color'][$i]['offset'] = 1; }
418 if ($i>0) {
419 if ($gradient_info['color'][$i]['offset']<$gradient_info['color'][($i-1)]['offset']) {
420 $gradient_info['color'][$i]['offset']=$gradient_info['color'][($i-1)]['offset'];
421 }
422 }
423 }
424
425 if (isset($gradient_info['color'][0]['offset']) && $gradient_info['color'][0]['offset']>0) {
426 array_unshift($gradient_info['color'], $gradient_info['color'][0]);
427 $gradient_info['color'][0]['offset'] = 0;
428 }
429 $ns = count($gradient_info['color']);
430 if (isset($gradient_info['color'][($ns-1)]['offset']) && $gradient_info['color'][($ns-1)]['offset']<1) {
431 $gradient_info['color'][] = $gradient_info['color'][($ns-1)];
432 $gradient_info['color'][($ns)]['offset'] = 1;
433 }
434 $ns = count($gradient_info['color']);
435
436
437
438
439 if ($gradient_info['type'] == 'linear'){
440 // mPDF 4.4.003
441 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
442 if (isset($gradient_info['info']['x1'])) { $gradient_info['info']['x1'] = ($gradient_info['info']['x1']-$x_offset) / $w; }
443 if (isset($gradient_info['info']['y1'])) { $gradient_info['info']['y1'] = ($gradient_info['info']['y1']-$y_offset) / $h; }
444 if (isset($gradient_info['info']['x2'])) { $gradient_info['info']['x2'] = ($gradient_info['info']['x2']-$x_offset) / $w; }
445 if (isset($gradient_info['info']['y2'])) { $gradient_info['info']['y2'] = ($gradient_info['info']['y2']-$y_offset) / $h; }
446 }
447 if (isset($gradient_info['info']['x1'])) { $x1 = $gradient_info['info']['x1']; }
448 else { $x1 = 0; }
449 if (isset($gradient_info['info']['y1'])) { $y1 = $gradient_info['info']['y1']; }
450 else { $y1 = 0; }
451 if (isset($gradient_info['info']['x2'])) { $x2 = $gradient_info['info']['x2']; }
452 else { $x2 = 1; }
453 if (isset($gradient_info['info']['y2'])) { $y2 = $gradient_info['info']['y2']; }
454 else { $y2 = 0; } // mPDF 6
455
456 if (stristr($x1, '%')!== false) { $x1 = ($x1+0)/100; }
457 if (stristr($x2, '%')!== false) { $x2 = ($x2+0)/100; }
458 if (stristr($y1, '%')!== false) { $y1 = ($y1+0)/100; }
459 if (stristr($y2, '%')!== false) { $y2 = ($y2+0)/100; }
460
461 // mPDF 5.0.042
462 $bboxw = $w;
463 $bboxh = $h;
464 $usex = $x_offset;
465 $usey = $y_offset;
466 $usew = $bboxw;
467 $useh = $bboxh;
468 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
469 $angle = rad2deg(atan2(($gradient_info['info']['y2']-$gradient_info['info']['y1']), ($gradient_info['info']['x2']-$gradient_info['info']['x1'])));
470 if ($angle < 0) { $angle += 360; }
471 else if ($angle > 360) { $angle -= 360; }
472 if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) {
473 if ($w >= $h) {
474 $y1 *= $h/$w ;
475 $y2 *= $h/$w ;
476 $usew = $useh = $bboxw;
477 }
478 else {
479 $x1 *= $w/$h ;
480 $x2 *= $w/$h ;
481 $usew = $useh = $bboxh;
482 }
483 }
484 }
485 $a = $usew; // width
486 $d = -$useh; // height
487 $e = $usex; // x- offset
488 $f = -$usey; // -y-offset
489
490 $return .= sprintf('%.3F 0 0 %.3F %.3F %.3F cm ', $a*$this->kp, $d*$this->kp, $e*$this->kp, $f*$this->kp);
491
492 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='objectboundingbox') {
493 if ($transformations) { $return .= $transformations; }
494 }
495
496 $trans = false;
497
498 if ($spread=='R' || $spread=='F') { // Repeat / Reflect
499 $offs = array();
500 for($i=0;$i<$ns;$i++) {
501 $offs[$i] = $gradient_info['color'][$i]['offset'];
502 }
503 $gp = 0;
504 $inside=true;
505 while($inside) {
506 $gp++;
507 for($i=0;$i<$ns;$i++) {
508 if ($spread=='F' && ($gp % 2) == 1) { // Reflect
509 $gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][(($ns*($gp-1))+($ns-$i-1))];
510 $tmp = $gp+(1-$offs[($ns-$i-1)]) ;
511 $gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp;
512 }
513 else { // Reflect
514 $gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][$i];
515 $tmp = $gp+$offs[$i] ;
516 $gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp;
517 }
518 // IF STILL INSIDE BOX OR STILL VALID
519 // Point on axis to test
520 $px1 = $x1 + ($x2-$x1)*$tmp;
521 $py1 = $y1 + ($y2-$y1)*$tmp;
522 // Get perpendicular axis
523 $alpha = atan2($y2-$y1, $x2-$x1);
524 $alpha += M_PI/2; // rotate 90 degrees
525 // Get arbitrary point to define line perpendicular to axis
526 $px2 = $px1+cos($alpha);
527 $py2 = $py1+sin($alpha);
528
529 $res1 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 0, 1); // $x=0 vert axis
530 $res2 = _testIntersect($px1, $py1, $px2, $py2, 1, 0, 1, 1); // $x=1 vert axis
531 $res3 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 1, 0); // $y=0 horiz axis
532 $res4 = _testIntersect($px1, $py1, $px2, $py2, 0, 1, 1, 1); // $y=1 horiz axis
533 if (!$res1 && !$res2 && !$res3 && !$res4) { $inside = false; }
534 }
535 }
536
537 $inside=true;
538 $gp = 0;
539 while($inside) {
540 $gp++;
541 $newarr = array();
542 for($i=0;$i<$ns;$i++) {
543 if ($spread=='F') { // Reflect
544 $newarr[$i] = $gradient_info['color'][($ns-$i-1)];
545 if (($gp % 2) == 1) {
546 $tmp = -$gp+(1-$offs[($ns-$i-1)]);
547 $newarr[$i]['offset'] = $tmp;
548 }
549 else {
550 $tmp = -$gp+$offs[$i];
551 $newarr[$i]['offset'] = $tmp;
552 }
553 }
554 else { // Reflect
555 $newarr[$i] = $gradient_info['color'][$i];
556 $tmp = -$gp+$offs[$i];
557 $newarr[$i]['offset'] = $tmp;
558 }
559
560 // IF STILL INSIDE BOX OR STILL VALID
561 // Point on axis to test
562 $px1 = $x1 + ($x2-$x1)*$tmp;
563 $py1 = $y1 + ($y2-$y1)*$tmp;
564 // Get perpendicular axis
565 $alpha = atan2($y2-$y1, $x2-$x1);
566 $alpha += M_PI/2; // rotate 90 degrees
567 // Get arbitrary point to define line perpendicular to axis
568 $px2 = $px1+cos($alpha);
569 $py2 = $py1+sin($alpha);
570
571 $res1 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 0, 1); // $x=0 vert axis
572 $res2 = _testIntersect($px1, $py1, $px2, $py2, 1, 0, 1, 1); // $x=1 vert axis
573 $res3 = _testIntersect($px1, $py1, $px2, $py2, 0, 0, 1, 0); // $y=0 horiz axis
574 $res4 = _testIntersect($px1, $py1, $px2, $py2, 0, 1, 1, 1); // $y=1 horiz axis
575 if (!$res1 && !$res2 && !$res3 && !$res4) { $inside = false; }
576 }
577 for($i=($ns-1);$i>=0;$i--) {
578 if (isset($newarr[$i]['offset'])) array_unshift($gradient_info['color'], $newarr[$i]);
579 }
580 }
581 }
582
583 // Gradient STOPs
584 $stops = count($gradient_info['color']);
585 if ($stops < 2) { return ''; }
586
587 $range = $gradient_info['color'][count($gradient_info['color'])-1]['offset']-$gradient_info['color'][0]['offset'];
588 $min = $gradient_info['color'][0]['offset'];
589
590 for ($i=0; $i<($stops); $i++) {
591 if (!$gradient_info['color'][$i]['color']) {
592 if ($gradient_info['colorspace']=='RGB') $gradient_info['color'][$i]['color'] = '0 0 0';
593 else if ($gradient_info['colorspace']=='Gray') $gradient_info['color'][$i]['color'] = '0';
594 else if ($gradient_info['colorspace']=='CMYK') $gradient_info['color'][$i]['color'] = '1 1 1 1';
595 }
596 $offset = ($gradient_info['color'][$i]['offset'] - $min)/$range;
597 $this->mpdf_ref->gradients[$n]['stops'][] = array(
598 'col' => $gradient_info['color'][$i]['color'],
599 'opacity' => $gradient_info['color'][$i]['opacity'],
600 'offset' => $offset);
601 if ($gradient_info['color'][$i]['opacity']<1) { $trans = true; }
602 }
603 $grx1 = $x1 + ($x2-$x1)*$gradient_info['color'][0]['offset'];
604 $gry1 = $y1 + ($y2-$y1)*$gradient_info['color'][0]['offset'];
605 $grx2 = $x1 + ($x2-$x1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
606 $gry2 = $y1 + ($y2-$y1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
607
608 $this->mpdf_ref->gradients[$n]['coords']=array($grx1, $gry1, $grx2, $gry2);
609
610 $this->mpdf_ref->gradients[$n]['colorspace'] = $gradient_info['colorspace'];
611
612 $this->mpdf_ref->gradients[$n]['type'] = 2;
613 $this->mpdf_ref->gradients[$n]['fo'] = true;
614
615 $this->mpdf_ref->gradients[$n]['extend']=array('true','true');
616 if ($trans) {
617 $this->mpdf_ref->gradients[$n]['trans'] = true;
618 $return .= ' /TGS'.($n).' gs ';
619 }
620 $return .= ' /Sh'.($n).' sh ';
621 $return .= " Q\n";
622 }
623 else if ($gradient_info['type'] == 'radial'){
624 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
625 if ($w > $h) { $h = $w; }
626 else { $w = $h; }
627 if (isset($gradient_info['info']['x0'])) { $gradient_info['info']['x0'] = ($gradient_info['info']['x0']-$x_offset) / $w; }
628 if (isset($gradient_info['info']['y0'])) { $gradient_info['info']['y0'] = ($gradient_info['info']['y0']-$y_offset) / $h; }
629 if (isset($gradient_info['info']['x1'])) { $gradient_info['info']['x1'] = ($gradient_info['info']['x1']-$x_offset) / $w; }
630 if (isset($gradient_info['info']['y1'])) { $gradient_info['info']['y1'] = ($gradient_info['info']['y1']-$y_offset) / $h; }
631 if (isset($gradient_info['info']['r'])) { $gradient_info['info']['rx'] = $gradient_info['info']['r'] / $w; }
632 if (isset($gradient_info['info']['r'])) { $gradient_info['info']['ry'] = $gradient_info['info']['r'] / $h; }
633 }
634
635 if (isset($gradient_info['info']['x0'])) { $x0 = $gradient_info['info']['x0']; }
636 else { $x0 = 0.5; }
637 if (isset($gradient_info['info']['y0'])) { $y0 = $gradient_info['info']['y0']; }
638 else { $y0 = 0.5; }
639 if (isset($gradient_info['info']['rx'])) { $rx = $gradient_info['info']['rx']; }
640 else if (isset($gradient_info['info']['r'])) { $rx = $gradient_info['info']['r']; }
641 else { $rx = 0.5; }
642 if (isset($gradient_info['info']['ry'])) { $ry = $gradient_info['info']['ry']; }
643 else if (isset($gradient_info['info']['r'])) { $ry = $gradient_info['info']['r']; }
644 else { $ry = 0.5; }
645 if (isset($gradient_info['info']['x1'])) { $x1 = $gradient_info['info']['x1']; }
646 else { $x1 = $x0; }
647 if (isset($gradient_info['info']['y1'])) { $y1 = $gradient_info['info']['y1']; }
648 else { $y1 = $y0; }
649
650 if (stristr($x1, '%')!== false) { $x1 = ($x1+0)/100; }
651 if (stristr($x0, '%')!== false) { $x0 = ($x0+0)/100; }
652 if (stristr($y1, '%')!== false) { $y1 = ($y1+0)/100; }
653 if (stristr($y0, '%')!== false) { $y0 = ($y0+0)/100; }
654 if (stristr($rx, '%')!== false) { $rx = ($rx+0)/100; }
655 if (stristr($ry, '%')!== false) { $ry = ($ry+0)/100; }
656
657 $bboxw = $w;
658 $bboxh = $h;
659 $usex = $x_offset;
660 $usey = $y_offset;
661 $usew = $bboxw;
662 $useh = $bboxh;
663 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='userspaceonuse') {
664 $angle = rad2deg(atan2(($gradient_info['info']['y0']-$gradient_info['info']['y1']), ($gradient_info['info']['x0']-$gradient_info['info']['x1'])));
665 if ($angle < 0) { $angle += 360; }
666 else if ($angle > 360) { $angle -= 360; }
667 if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) {
668 if ($w >= $h) {
669 $y1 *= $h/$w ;
670 $y0 *= $h/$w ;
671 $rx *= $h/$w ;
672 $ry *= $h/$w ;
673 $usew = $useh = $bboxw;
674 }
675 else {
676 $x1 *= $w/$h ;
677 $x0 *= $w/$h ;
678 $rx *= $w/$h ;
679 $ry *= $w/$h ;
680 $usew = $useh = $bboxh;
681 }
682 }
683 }
684 $a = $usew; // width
685 $d = -$useh; // height
686 $e = $usex; // x- offset
687 $f = -$usey; // -y-offset
688
689 $r = $rx;
690
691
692 $return .= sprintf('%.3F 0 0 %.3F %.3F %.3F cm ', $a*$this->kp, $d*$this->kp, $e*$this->kp, $f*$this->kp);
693
694 // mPDF 5.0.039
695 if (isset($gradient_info['units']) && strtolower($gradient_info['units'])=='objectboundingbox') {
696 if ($transformations) { $return .= $transformations; }
697 }
698
699 // mPDF 5.7.4
700 // x1 and y1 (fx, fy) should be inside the circle defined by x0 y0 (cx, cy)
701 // "If the point defined by fx and fy lies outside the circle defined by cx, cy and r, then the user agent shall set
702 // the focal point to the intersection of the line from (cx, cy) to (fx, fy) with the circle defined by cx, cy and r."
703 while (pow(($x1-$x0),2) + pow(($y1 - $y0),2) >= pow($r,2)) {
704 // Gradually move along fx,fy towards cx,cy in 100'ths until meets criteria
705 $x1 -= ($x1-$x0)/100;
706 $y1 -= ($y1-$y0)/100;
707 }
708
709
710 if ($spread=='R' || $spread=='F') { // Repeat / Reflect
711 $offs = array();
712 for($i=0;$i<$ns;$i++) {
713 $offs[$i] = $gradient_info['color'][$i]['offset'];
714 }
715 $gp = 0;
716 $inside=true;
717 while($inside) {
718 $gp++;
719 for($i=0;$i<$ns;$i++) {
720 if ($spread=='F' && ($gp % 2) == 1) { // Reflect
721 $gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][(($ns*($gp-1))+($ns-$i-1))];
722 $tmp = $gp+(1-$offs[($ns-$i-1)]) ;
723 $gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp;
724 }
725 else { // Reflect
726 $gradient_info['color'][(($ns*$gp)+$i)] = $gradient_info['color'][$i];
727 $tmp = $gp+$offs[$i] ;
728 $gradient_info['color'][(($ns*$gp)+$i)]['offset'] = $tmp;
729 }
730 // IF STILL INSIDE BOX OR STILL VALID
731 // TEST IF circle (perimeter) intersects with
732 // or is enclosed
733 // Point on axis to test
734 $px = $x1 + ($x0-$x1)*$tmp;
735 $py = $y1 + ($y0-$y1)*$tmp;
736 $pr = $r*$tmp;
737 $res = _testIntersectCircle($px, $py, $pr);
738 if (!$res) { $inside = false; }
739 }
740 }
741 }
742
743 // Gradient STOPs
744 $stops = count($gradient_info['color']);
745 if ($stops < 2) { return ''; }
746
747 $range = $gradient_info['color'][count($gradient_info['color'])-1]['offset']-$gradient_info['color'][0]['offset'];
748 $min = $gradient_info['color'][0]['offset'];
749
750 for ($i=0; $i<($stops); $i++) {
751 if (!$gradient_info['color'][$i]['color']) {
752 if ($gradient_info['colorspace']=='RGB') $gradient_info['color'][$i]['color'] = '0 0 0';
753 else if ($gradient_info['colorspace']=='Gray') $gradient_info['color'][$i]['color'] = '0';
754 else if ($gradient_info['colorspace']=='CMYK') $gradient_info['color'][$i]['color'] = '1 1 1 1';
755 }
756 $offset = ($gradient_info['color'][$i]['offset'] - $min)/$range;
757 $this->mpdf_ref->gradients[$n]['stops'][] = array(
758 'col' => $gradient_info['color'][$i]['color'],
759 'opacity' => $gradient_info['color'][$i]['opacity'],
760 'offset' => $offset);
761 if ($gradient_info['color'][$i]['opacity']<1) { $trans = true; }
762 }
763 $grx1 = $x1 + ($x0-$x1)*$gradient_info['color'][0]['offset'];
764 $gry1 = $y1 + ($y0-$y1)*$gradient_info['color'][0]['offset'];
765 $grx2 = $x1 + ($x0-$x1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
766 $gry2 = $y1 + ($y0-$y1)*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
767 $grir = $r*$gradient_info['color'][0]['offset'];
768 $grr = $r*$gradient_info['color'][count($gradient_info['color'])-1]['offset'];
769
770 $this->mpdf_ref->gradients[$n]['coords']=array($grx1, $gry1, $grx2, $gry2, abs($grr), abs($grir) );
771
772 $this->mpdf_ref->gradients[$n]['colorspace'] = $gradient_info['colorspace'];
773
774 $this->mpdf_ref->gradients[$n]['type'] = 3;
775 $this->mpdf_ref->gradients[$n]['fo'] = true;
776
777 $this->mpdf_ref->gradients[$n]['extend']=array('true','true');
778 if (isset($trans) && $trans) {
779 $this->mpdf_ref->gradients[$n]['trans'] = true;
780 $return .= ' /TGS'.($n).' gs ';
781 }
782 $return .= ' /Sh'.($n).' sh ';
783 $return .= " Q\n";
784
785
786 }
787
788 return $return;
789 }
790
791
792 function svgOffset ($attribs){
793 // save all <svg> tag attributes
794 $this->svg_attribs = $attribs;
795 if(isset($this->svg_attribs['viewBox'])) {
796 $vb = preg_split('/\s+/is', trim($this->svg_attribs['viewBox']));
797 if (count($vb)==4) {
798 $this->svg_info['x'] = $vb[0];
799 $this->svg_info['y'] = $vb[1];
800 $this->svg_info['w'] = $vb[2];
801 $this->svg_info['h'] = $vb[3];
802 // return;
803 }
804 }
805 $svg_w = 0;
806 $svg_h = 0;
807 if (isset($attribs['width']) && $attribs['width']) $svg_w = $this->mpdf_ref->ConvertSize($attribs['width']); // mm (interprets numbers as pixels)
808 if (isset($attribs['height']) && $attribs['height']) $svg_h = $this->mpdf_ref->ConvertSize($attribs['height']); // mm
809
810 ///*
811 // mPDF 5.0.005
812 if (isset($this->svg_info['w']) && $this->svg_info['w']) { // if 'w' set by viewBox
813 if ($svg_w) { // if width also set, use these values to determine to set size of "pixel"
814 $this->kp *= ($svg_w/0.2645) / $this->svg_info['w'];
815 $this->kf = ($svg_w/0.2645) / $this->svg_info['w'];
816 }
817 else if ($svg_h) {
818 $this->kp *= ($svg_h/0.2645) / $this->svg_info['h'];
819 $this->kf = ($svg_h/0.2645) / $this->svg_info['h'];
820 }
821 return;
822 }
823 //*/
824
825 // Added to handle file without height or width specified
826 if (!$svg_w && !$svg_h) { $svg_w = $svg_h = $this->mpdf_ref->blk[$this->mpdf_ref->blklvl]['inner_width'] ; } // DEFAULT
827 if (!$svg_w) { $svg_w = $svg_h; }
828 if (!$svg_h) { $svg_h = $svg_w; }
829
830 $this->svg_info['x'] = 0;
831 $this->svg_info['y'] = 0;
832 $this->svg_info['w'] = $svg_w/0.2645; // mm->pixels
833 $this->svg_info['h'] = $svg_h/0.2645; // mm->pixels
834
835 }
836
837
838 //
839 // check if points are within svg, if not, set to max
840 function svg_overflow($x,$y)
841 {
842 $x2 = $x;
843 $y2 = $y;
844 if(isset($this->svg_attribs['overflow']))
845 {
846 if($this->svg_attribs['overflow'] == 'hidden')
847 {
848 // Not sure if this is supposed to strip off units, but since I dont use any I will omlt this step
849 $svg_w = preg_replace("/([0-9\.]*)(.*)/i","$1",$this->svg_attribs['width']);
850 $svg_h = preg_replace("/([0-9\.]*)(.*)/i","$1",$this->svg_attribs['height']);
851
852 // $xmax = floor($this->svg_attribs['width']);
853 $xmax = floor($svg_w);
854 $xmin = 0;
855 // $ymax = floor(($this->svg_attribs['height'] * -1));
856 $ymax = floor(($svg_h * -1));
857 $ymin = 0;
858
859 if($x > $xmax) $x2 = $xmax; // right edge
860 if($x < $xmin) $x2 = $xmin; // left edge
861 if($y < $ymax) $y2 = $ymax; // bottom
862 if($y > $ymin) $y2 = $ymin; // top
863
864 }
865 }
866
867
868 return array( 'x' => $x2, 'y' => $y2);
869 }
870
871
872
873 function svgDefineStyle($critere_style){
874
875 $tmp = count($this->svg_style)-1;
876 $current_style = $this->svg_style[$tmp];
877
878 unset($current_style['transformations']);
879
880 // TRANSFORM SCALE
881 $transformations = '';
882 if (isset($critere_style['transform'])){
883 preg_match_all('/(matrix|translate|scale|rotate|skewX|skewY)\((.*?)\)/is',$critere_style['transform'],$m);
884 if (count($m[0])) {
885 for($i=0; $i<count($m[0]); $i++) {
886 $c = strtolower($m[1][$i]);
887 $v = trim($m[2][$i]);
888 $vv = preg_split('/[ ,]+/',$v);
889 if ($c=='matrix' && count($vv)==6) {
890 // mPDF 5.0.039
891 // Note angle of rotation is reversed (from SVG to PDF), so vv[1] and vv[2] are negated
892 $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);
893
894 /*
895 // The long way of doing this??
896 // need to reverse angle of rotation from SVG to PDF
897 $sx=sqrt(pow($vv[0],2)+pow($vv[2],2));
898 if ($vv[0] < 0) { $sx *= -1; } // change sign
899 $sy=sqrt(pow($vv[1],2)+pow($vv[3],2));
900 if ($vv[3] < 0) { $sy *= -1; } // change sign
901
902 // rotation angle is
903 $t=atan2($vv[1],$vv[3]);
904 $t=atan2(-$vv[2],$vv[0]); // Should be the same value or skew has been applied
905
906 // Reverse angle
907 $t *= -1;
908
909 // Rebuild matrix
910 $ma = $sx * cos($t);
911 $mb = $sy * sin($t);
912 $mc = -$sx * sin($t);
913 $md = $sy * cos($t);
914
915 // $transformations .= sprintf(' %.3F %.3F %.3F %.3F %.3F %.3F cm ', $ma, $mb, $mc, $md, $vv[4]*$this->kp, -$vv[5]*$this->kp);
916 */
917
918 }
919 else if ($c=='translate' && count($vv)) {
920 $tm[4] = $vv[0];
921 if (count($vv)==2) { $t_y = -$vv[1]; }
922 else { $t_y = 0; }
923 $tm[5] = $t_y;
924 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $tm[4]*$this->kp, $tm[5]*$this->kp);
925 }
926 else if ($c=='scale' && count($vv)) {
927 if (count($vv)==2) { $s_y = $vv[1]; }
928 else { $s_y = $vv[0]; }
929 $tm[0] = $vv[0];
930 $tm[3] = $s_y;
931 $transformations .= sprintf(' %.3F 0 0 %.3F 0 0 cm ', $tm[0], $tm[3]);
932 }
933 else if ($c=='rotate' && count($vv)) {
934 $tm[0] = cos(deg2rad(-$vv[0]));
935 $tm[1] = sin(deg2rad(-$vv[0]));
936 $tm[2] = -$tm[1];
937 $tm[3] = $tm[0];
938 if (count($vv)==3) {
939 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', $vv[1]*$this->kp, -$vv[2]*$this->kp);
940 }
941 $transformations .= sprintf(' %.3F %.3F %.3F %.3F 0 0 cm ', $tm[0], $tm[1], $tm[2], $tm[3]);
942 if (count($vv)==3) {
943 $transformations .= sprintf(' 1 0 0 1 %.3F %.3F cm ', -$vv[1]*$this->kp, $vv[2]*$this->kp);
944 }
945 }
946 else if ($c=='skewx' && count($vv)) {
947 $tm[2] = tan(deg2rad(-$vv[0]));
948 $transformations .= sprintf(' 1 0 %.3F 1 0 0 cm ', $tm[2]);
949 }
950 else if ($c=='skewy' && count($vv)) {
951 $tm[1] = tan(deg2rad(-$vv[0]));
952 $transformations .= sprintf(' 1 %.3F 0 1 0 0 cm ', $tm[1]);
953 }
954
955 }
956 }
957 $current_style['transformations'] = $transformations;
958 }
959
960 if (isset($critere_style['style'])){
961 if (preg_match('/fill:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/i',$critere_style['style'], $m)) { // mPDF 5.7.2
962 $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);
963 }
964 else { $tmp = preg_replace("/(.*)fill:\s*([a-z0-9#_()]*|none)(.*)/i","$2",$critere_style['style']);
965 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['fill'] = $tmp; }
966 }
967
968 // mPDF 5.7.2
969 if ((preg_match("/[^-]opacity:\s*([a-z0-9.]*|none)/i",$critere_style['style'], $m) ||
970 preg_match("/^opacity:\s*([a-z0-9.]*|none)/i",$critere_style['style'], $m)) && $m[1]!='inherit') {
971 $current_style['fill-opacity'] = $m[1];
972 $current_style['stroke-opacity'] = $m[1];
973 }
974
975 $tmp = preg_replace("/(.*)fill-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
976 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['fill-opacity'] = $tmp;}
977
978 $tmp = preg_replace("/(.*)fill-rule:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
979 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['fill-rule'] = $tmp;}
980
981 if (preg_match('/stroke:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
982 $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);
983 }
984 else { $tmp = preg_replace("/(.*)stroke:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
985 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['stroke'] = $tmp; }
986 }
987
988 $tmp = preg_replace("/(.*)stroke-linecap:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
989 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-linecap'] = $tmp;}
990
991 $tmp = preg_replace("/(.*)stroke-linejoin:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
992 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-linejoin'] = $tmp;}
993
994 $tmp = preg_replace("/(.*)stroke-miterlimit:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
995 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-miterlimit'] = $tmp;}
996
997 $tmp = preg_replace("/(.*)stroke-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
998 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-opacity'] = $tmp; }
999
1000 $tmp = preg_replace("/(.*)stroke-width:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1001 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-width'] = $tmp;}
1002
1003 $tmp = preg_replace("/(.*)stroke-dasharray:\s*([a-z0-9., ]*|none)(.*)/i","$2",$critere_style['style']);
1004 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-dasharray'] = $tmp;}
1005
1006 $tmp = preg_replace("/(.*)stroke-dashoffset:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
1007 if ($tmp && $tmp!='inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-dashoffset'] = $tmp;}
1008
1009 }
1010 // mPDF 5.7.2
1011 if(isset($critere_style['opacity']) && $critere_style['opacity']!= 'inherit'){
1012 $current_style['fill-opacity'] = $critere_style['opacity'];
1013 $current_style['stroke-opacity'] = $critere_style['opacity'];
1014 }
1015
1016 if(isset($critere_style['fill']) && $critere_style['fill']!= 'inherit'){
1017 $current_style['fill'] = $critere_style['fill'];
1018 }
1019
1020 if(isset($critere_style['fill-opacity']) && $critere_style['fill-opacity']!= 'inherit'){
1021 $current_style['fill-opacity'] = $critere_style['fill-opacity'];
1022 }
1023
1024 if(isset($critere_style['fill-rule']) && $critere_style['fill-rule']!= 'inherit'){
1025 $current_style['fill-rule'] = $critere_style['fill-rule'];
1026 }
1027
1028 if(isset($critere_style['stroke']) && $critere_style['stroke']!= 'inherit'){
1029 $current_style['stroke'] = $critere_style['stroke'];
1030 }
1031
1032 if(isset($critere_style['stroke-linecap']) && $critere_style['stroke-linecap']!= 'inherit'){
1033 $current_style['stroke-linecap'] = $critere_style['stroke-linecap'];
1034 }
1035
1036 if(isset($critere_style['stroke-linejoin']) && $critere_style['stroke-linejoin']!= 'inherit'){
1037 $current_style['stroke-linejoin'] = $critere_style['stroke-linejoin'];
1038 }
1039
1040 if(isset($critere_style['stroke-miterlimit']) && $critere_style['stroke-miterlimit']!= 'inherit'){
1041 $current_style['stroke-miterlimit'] = $critere_style['stroke-miterlimit'];
1042 }
1043
1044 if(isset($critere_style['stroke-opacity']) && $critere_style['stroke-opacity']!= 'inherit'){
1045 $current_style['stroke-opacity'] = $critere_style['stroke-opacity'];
1046 }
1047
1048 if(isset($critere_style['stroke-width']) && $critere_style['stroke-width']!= 'inherit'){
1049 $current_style['stroke-width'] = $critere_style['stroke-width'];
1050 }
1051
1052 if(isset($critere_style['stroke-dasharray']) && $critere_style['stroke-dasharray']!= 'inherit'){
1053 $current_style['stroke-dasharray'] = $critere_style['stroke-dasharray'];
1054 }
1055 if(isset($critere_style['stroke-dashoffset']) && $critere_style['stroke-dashoffset']!= 'inherit'){
1056 $current_style['stroke-dashoffset'] = $critere_style['stroke-dashoffset'];
1057 }
1058
1059 // Used as indirect setting for currentColor
1060 if(isset($critere_style['color']) && $critere_style['color'] != 'inherit'){
1061 $current_style['color'] = $critere_style['color'];
1062 }
1063
1064 return $current_style;
1065
1066 }
1067
1068 //
1069 // Cette fonction ecrit le style dans le stream svg.
1070 function svgStyle($critere_style, $attribs, $element){
1071 $path_style = '';
1072 $fill_gradient = '';
1073 $w = '';
1074 $style = '';
1075 if (substr_count($critere_style['fill'],'url')>0 && $element != 'line'){
1076 //
1077 // couleur degrad�
1078 $id_gradient = preg_replace("/url\(#([\w_]*)\)/i","$1",$critere_style['fill']);
1079 if ($id_gradient != $critere_style['fill']) {
1080 if (isset($this->svg_gradient[$id_gradient])) {
1081 $fill_gradient = $this->svgGradient($this->svg_gradient[$id_gradient], $attribs, $element);
1082 if ($fill_gradient) {
1083 $path_style = "q ";
1084 $w = "W";
1085 $style .= 'N';
1086 }
1087 }
1088 }
1089
1090 }
1091 // Used as indirect setting for currentColor
1092 else if (strtolower($critere_style['fill']) == 'currentcolor' && $element != 'line'){
1093 $col = $this->mpdf_ref->ConvertColor($critere_style['color']);
1094 if ($col) {
1095 if ($col{0}==5) { $critere_style['fill-opacity'] = ord($col{4}/100); } // RGBa
1096 if ($col{0}==6) { $critere_style['fill-opacity'] = ord($col{5}/100); } // CMYKa
1097 $path_style .= $this->mpdf_ref->SetFColor($col, true).' ';
1098 $style .= 'F';
1099 }
1100 }
1101 else if ($critere_style['fill'] != 'none' && $element != 'line'){
1102 $col = $this->mpdf_ref->ConvertColor($critere_style['fill']);
1103 if ($col) {
1104 if ($col{0}==5) { $critere_style['fill-opacity'] = ord($col{4}/100); } // RGBa
1105 if ($col{0}==6) { $critere_style['fill-opacity'] = ord($col{5}/100); } // CMYKa
1106 $path_style .= $this->mpdf_ref->SetFColor($col, true).' ';
1107 $style .= 'F';
1108 }
1109 }
1110 if (substr_count($critere_style['stroke'],'url')>0){
1111 /*
1112 // Cannot put a gradient on a "stroke" in PDF?
1113 $id_gradient = preg_replace("/url\(#([\w_]*)\)/i","$1",$critere_style['stroke']);
1114 if ($id_gradient != $critere_style['stroke']) {
1115 if (isset($this->svg_gradient[$id_gradient])) {
1116 $fill_gradient = $this->svgGradient($this->svg_gradient[$id_gradient], $attribs, $element);
1117 if ($fill_gradient) {
1118 $path_style = "q ";
1119 $w = "W";
1120 $style .= 'D';
1121 }
1122 }
1123 }
1124 */
1125 }
1126 // Used as indirect setting for currentColor
1127 else if (strtolower($critere_style['stroke']) == 'currentcolor'){
1128 $col = $this->mpdf_ref->ConvertColor($critere_style['color']);
1129 if ($col) {
1130 if ($col{0}==5) { $critere_style['stroke-opacity'] = ord($col{4}/100); } // RGBa
1131 if ($col{0}==6) { $critere_style['stroke-opacity'] = ord($col{5}/100); } // CMYKa
1132 $path_style .= $this->mpdf_ref->SetDColor($col, true).' ';
1133 $style .= 'D';
1134 $lw = $this->ConvertSVGSizePixels($critere_style['stroke-width']);
1135 $path_style .= sprintf('%.3F w ',$lw*$this->kp);
1136 }
1137 }
1138 else if ($critere_style['stroke'] != 'none'){
1139 $col = $this->mpdf_ref->ConvertColor($critere_style['stroke']);
1140 if ($col) {
1141 // mPDF 5.0.051
1142 // mPDF 5.3.74
1143 if ($col{0}==5) { $critere_style['stroke-opacity'] = ord($col{4}/100); } // RGBa
1144 if ($col{0}==6) { $critere_style['stroke-opacity'] = ord($col{5}/100); } // CMYKa
1145 $path_style .= $this->mpdf_ref->SetDColor($col, true).' ';
1146 $style .= 'D';
1147 $lw = $this->ConvertSVGSizePixels($critere_style['stroke-width']);
1148 $path_style .= sprintf('%.3F w ',$lw*$this->kp);
1149 }
1150 }
1151
1152
1153 if ($critere_style['stroke'] != 'none'){
1154 if ($critere_style['stroke-linejoin'] == 'miter'){
1155 $path_style .= ' 0 j ';
1156 }
1157 else if ($critere_style['stroke-linejoin'] == 'round'){
1158 $path_style .= ' 1 j ';
1159 }
1160 else if ($critere_style['stroke-linejoin'] == 'bevel'){
1161 $path_style .= ' 2 j ';
1162 }
1163
1164 if ($critere_style['stroke-linecap'] == 'butt'){
1165 $path_style .= ' 0 J ';
1166 }
1167 else if ($critere_style['stroke-linecap'] == 'round'){
1168 $path_style .= ' 1 J ';
1169 }
1170 else if ($critere_style['stroke-linecap'] == 'square'){
1171 $path_style .= ' 2 J ';
1172 }
1173
1174 if (isset($critere_style['stroke-miterlimit'])){
1175 if ($critere_style['stroke-miterlimit'] == 'none'){
1176 }
1177 else if (preg_match('/^[\d.]+$/',$critere_style['stroke-miterlimit'])) {
1178 $path_style .= sprintf('%.2F M ',$critere_style['stroke-miterlimit']);
1179 }
1180 }
1181 if (isset($critere_style['stroke-dasharray'])){
1182 $off = 0;
1183 $d = preg_split('/[ ,]/',$critere_style['stroke-dasharray']);
1184 if (count($d) == 1 && $d[0]==0) {
1185 $path_style .= '[] 0 d ';
1186 }
1187 else {
1188 if (count($d) % 2 == 1) { $d = array_merge($d, $d); } // 5, 3, 1 => 5,3,1,5,3,1 OR 3 => 3,3
1189 $arr = '';
1190 for($i=0; $i<count($d); $i+=2) {
1191 $arr .= sprintf('%.3F %.3F ', $d[$i]*$this->kp, $d[$i+1]*$this->kp);
1192 }
1193 if (isset($critere_style['stroke-dashoffset'])){ $off = $critere_style['stroke-dashoffset'] + 0; }
1194 $path_style .= sprintf('[%s] %.3F d ', $arr, $off*$this->kp);
1195 }
1196 }
1197 }
1198
1199 if ($critere_style['fill-rule']=='evenodd') { $fr = '*'; }
1200 else { $fr = ''; }
1201
1202 if (isset($critere_style['fill-opacity'])) {
1203 $opacity = 1;
1204 if ($critere_style['fill-opacity'] == 0) { $opacity = 0; }
1205 else if ($critere_style['fill-opacity'] > 1) { $opacity = 1; }
1206 else if ($critere_style['fill-opacity'] > 0) { $opacity = $critere_style['fill-opacity']; }
1207 else if ($critere_style['fill-opacity'] < 0) { $opacity = 0; }
1208 $gs = $this->mpdf_ref->AddExtGState(array('ca'=>$opacity, 'BM'=>'/Normal'));
1209 $this->mpdf_ref->extgstates[$gs]['fo'] = true;
1210 $path_style .= sprintf(' /GS%d gs ', $gs);
1211 }
1212
1213 if (isset($critere_style['stroke-opacity'])) {
1214 $opacity = 1;
1215 if ($critere_style['stroke-opacity'] == 0) { $opacity = 0; }
1216 else if ($critere_style['stroke-opacity'] > 1) { $opacity = 1; }
1217 else if ($critere_style['stroke-opacity'] > 0) { $opacity = $critere_style['stroke-opacity']; }
1218 else if ($critere_style['stroke-opacity'] < 0) { $opacity = 0; }
1219 $gs = $this->mpdf_ref->AddExtGState(array('CA'=>$opacity, 'BM'=>'/Normal'));
1220 $this->mpdf_ref->extgstates[$gs]['fo'] = true;
1221 $path_style .= sprintf(' /GS%d gs ', $gs);
1222 }
1223
1224 switch ($style){
1225 case 'F':
1226 $op = 'f';
1227 break;
1228 case 'FD':
1229 $op = 'B';
1230 break;
1231 case 'ND':
1232 $op = 'S';
1233 break;
1234 case 'D':
1235 $op = 'S';
1236 break;
1237 default:
1238 $op = 'n';
1239 }
1240
1241 $prestyle = $path_style.' ';
1242 $poststyle = $w.' '. $op.$fr.' '.$fill_gradient."\n";
1243 return array($prestyle,$poststyle);
1244
1245 }
1246
1247 // fonction retracant les <path />
1248 function svgPath($command, $arguments){
1249 $path_cmd = '';
1250 $newsubpath = false;
1251 // mPDF 5.0.039
1252 $minl = $this->pathBBox[0];
1253 $mint = $this->pathBBox[1];
1254 $maxr = $this->pathBBox[2]+$this->pathBBox[0];
1255 $maxb = $this->pathBBox[3]+$this->pathBBox[1];
1256
1257 $start = array($this->xbase, -$this->ybase);
1258
1259 preg_match_all('/[\-^]?[\d.]+(e[\-]?[\d]+){0,1}/i', $arguments, $a, PREG_SET_ORDER);
1260
1261 // if the command is a capital letter, the coords go absolute, otherwise relative
1262 if(strtolower($command) == $command) $relative = true;
1263 else $relative = false;
1264
1265
1266 $ile_argumentow = count($a);
1267
1268 // each command may have different needs for arguments [1 to 8]
1269
1270 switch(strtolower($command)){
1271 case 'm': // move
1272 for($i = 0; $i<$ile_argumentow; $i+=2){
1273 $x = $a[$i][0];
1274 $y = $a[$i+1][0];
1275 if($relative){
1276 $pdfx = ($this->xbase + $x);
1277 $pdfy = ($this->ybase - $y);
1278 $this->xbase += $x;
1279 $this->ybase += -$y;
1280 }
1281 else{
1282 $pdfx = $x;
1283 $pdfy = -$y ;
1284 $this->xbase = $x;
1285 $this->ybase = -$y;
1286 }
1287 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1288 $minl = min($minl,$pdf_pt['x']);
1289 $maxr = max($maxr,$pdf_pt['x']);
1290 $mint = min($mint,-$pdf_pt['y']);
1291 $maxb = max($maxb,-$pdf_pt['y']);
1292 if($i == 0) $path_cmd .= sprintf('%.3F %.3F m ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1293 else $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1294 // mPDF 4.4.003 Save start points of subpath
1295 if ($this->subPathInit) {
1296 $this->spxstart = $this->xbase;
1297 $this->spystart = $this->ybase;
1298 $this->subPathInit = false;
1299 }
1300 }
1301 break;
1302 case 'l': // a simple line
1303 for($i = 0; $i<$ile_argumentow; $i+=2){
1304 $x = ($a[$i][0]);
1305 $y = ($a[$i+1][0]);
1306 if($relative){
1307 $pdfx = ($this->xbase + $x);
1308 $pdfy = ($this->ybase - $y);
1309 $this->xbase += $x;
1310 $this->ybase += -$y;
1311 }
1312 else{
1313 $pdfx = $x ;
1314 $pdfy = -$y ;
1315 $this->xbase = $x;
1316 $this->ybase = -$y;
1317 }
1318 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1319 $minl = min($minl,$pdf_pt['x']);
1320 $maxr = max($maxr,$pdf_pt['x']);
1321 $mint = min($mint,-$pdf_pt['y']);
1322 $maxb = max($maxb,-$pdf_pt['y']);
1323 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1324 }
1325 break;
1326 case 'h': // a very simple horizontal line
1327 for($i = 0; $i<$ile_argumentow; $i++){
1328 $x = ($a[$i][0]);
1329 if($relative){
1330 $y = 0;
1331 $pdfx = ($this->xbase + $x) ;
1332 $pdfy = ($this->ybase - $y) ;
1333 $this->xbase += $x;
1334 $this->ybase += -$y;
1335 }
1336 else{
1337 $y = -$this->ybase;
1338 $pdfx = $x;
1339 $pdfy = -$y;
1340 $this->xbase = $x;
1341 $this->ybase = -$y;
1342 }
1343 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1344 $minl = min($minl,$pdf_pt['x']);
1345 $maxr = max($maxr,$pdf_pt['x']);
1346 $mint = min($mint,-$pdf_pt['y']);
1347 $maxb = max($maxb,-$pdf_pt['y']);
1348 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1349 }
1350 break;
1351 case 'v': // the simplest line, vertical
1352 for($i = 0; $i<$ile_argumentow; $i++){
1353 $y = ($a[$i][0]);
1354 if($relative){
1355 $x = 0;
1356 $pdfx = ($this->xbase + $x);
1357 $pdfy = ($this->ybase - $y);
1358 $this->xbase += $x;
1359 $this->ybase += -$y;
1360 }
1361 else{
1362 $x = $this->xbase;
1363 $pdfx = $x;
1364 $pdfy = -$y;
1365 $this->xbase = $x;
1366 $this->ybase = -$y;
1367 }
1368 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1369 $minl = min($minl,$pdf_pt['x']);
1370 $maxr = max($maxr,$pdf_pt['x']);
1371 $mint = min($mint,-$pdf_pt['y']);
1372 $maxb = max($maxb,-$pdf_pt['y']);
1373 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1374 }
1375 break;
1376 case 's': // bezier with first vertex equal first control
1377 // mPDF 4.4.003
1378 if (!($this->lastcommand == 'C' || $this->lastcommand == 'c' || $this->lastcommand == 'S' || $this->lastcommand == 's')) {
1379 $this->lastcontrolpoints = array(0,0);
1380 }
1381 for($i = 0; $i<$ile_argumentow; $i += 4){
1382 $x1 = $this->lastcontrolpoints[0];
1383 $y1 = $this->lastcontrolpoints[1];
1384 $x2 = ($a[$i][0]);
1385 $y2 = ($a[$i+1][0]);
1386 $x = ($a[$i+2][0]);
1387 $y = ($a[$i+3][0]);
1388 if($relative){
1389 $pdfx1 = ($this->xbase + $x1);
1390 $pdfy1 = ($this->ybase - $y1);
1391 $pdfx2 = ($this->xbase + $x2);
1392 $pdfy2 = ($this->ybase - $y2);
1393 $pdfx = ($this->xbase + $x);
1394 $pdfy = ($this->ybase - $y);
1395 $this->xbase += $x;
1396 $this->ybase += -$y;
1397 }
1398 else{
1399 $pdfx1 = $this->xbase + $x1;
1400 $pdfy1 = $this->ybase -$y1;
1401 $pdfx2 = $x2;
1402 $pdfy2 = -$y2;
1403 $pdfx = $x;
1404 $pdfy = -$y;
1405 $this->xbase = $x;
1406 $this->ybase = -$y;
1407 }
1408 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1409
1410 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1411
1412 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1413 $bx = calc_bezier_bbox($start, $curves);
1414 $minl = min($minl,$bx[0]);
1415 $maxr = max($maxr,$bx[2]);
1416 $mint = min($mint,$bx[1]);
1417 $maxb = max($maxb,$bx[3]);
1418
1419 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1420 {
1421 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1422 }
1423 else
1424 {
1425 $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);
1426 }
1427
1428 }
1429 break;
1430 case 'c': // bezier with second vertex equal second control
1431 for($i = 0; $i<$ile_argumentow; $i += 6){
1432 $x1 = ($a[$i][0]);
1433 $y1 = ($a[$i+1][0]);
1434 $x2 = ($a[$i+2][0]);
1435 $y2 = ($a[$i+3][0]);
1436 $x = ($a[$i+4][0]);
1437 $y = ($a[$i+5][0]);
1438
1439
1440 if($relative){
1441 $pdfx1 = ($this->xbase + $x1);
1442 $pdfy1 = ($this->ybase - $y1);
1443 $pdfx2 = ($this->xbase + $x2);
1444 $pdfy2 = ($this->ybase - $y2);
1445 $pdfx = ($this->xbase + $x);
1446 $pdfy = ($this->ybase - $y);
1447 $this->xbase += $x;
1448 $this->ybase += -$y;
1449 }
1450 else{
1451 $pdfx1 = $x1;
1452 $pdfy1 = -$y1;
1453 $pdfx2 = $x2;
1454 $pdfy2 = -$y2;
1455 $pdfx = $x;
1456 $pdfy = -$y;
1457 $this->xbase = $x;
1458 $this->ybase = -$y;
1459 }
1460 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1461 // $pdf_pt2 = $this->svg_overflow($pdfx2,$pdfy2);
1462 // $pdf_pt1 = $this->svg_overflow($pdfx1,$pdfy1);
1463 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1464
1465 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1466 $bx = calc_bezier_bbox($start, $curves);
1467 $minl = min($minl,$bx[0]);
1468 $maxr = max($maxr,$bx[2]);
1469 $mint = min($mint,$bx[1]);
1470 $maxb = max($maxb,$bx[3]);
1471
1472 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1473 {
1474 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1475 }
1476 else
1477 {
1478 $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);
1479 }
1480
1481 }
1482 break;
1483
1484 case 'q': // bezier quadratic avec point de control
1485 for($i = 0; $i<$ile_argumentow; $i += 4){
1486 $x1 = ($a[$i][0]);
1487 $y1 = ($a[$i+1][0]);
1488 $x = ($a[$i+2][0]);
1489 $y = ($a[$i+3][0]);
1490 if($relative){
1491 $pdfx = ($this->xbase + $x);
1492 $pdfy = ($this->ybase - $y);
1493
1494 $pdfx1 = ($this->xbase + ($x1*2/3));
1495 $pdfy1 = ($this->ybase - ($y1*2/3));
1496 // mPDF 4.4.003
1497 $pdfx2 = $pdfx1 + 1/3 *($x);
1498 $pdfy2 = $pdfy1 + 1/3 *(-$y) ;
1499
1500 $this->xbase += $x;
1501 $this->ybase += -$y;
1502 }
1503 else{
1504 $pdfx = $x;
1505 $pdfy = -$y;
1506
1507 $pdfx1 = ($this->xbase+(($x1-$this->xbase)*2/3));
1508 $pdfy1 = ($this->ybase-(($y1+$this->ybase)*2/3));
1509
1510 $pdfx2 = ($x+(($x1-$x)*2/3));
1511 $pdfy2 = (-$y-(($y1-$y)*2/3));
1512
1513 // mPDF 4.4.003
1514 $pdfx2 = $pdfx1 + 1/3 *($x - $this->xbase);
1515 $pdfy2 = $pdfy1 + 1/3 *(-$y - $this->ybase) ;
1516
1517 $this->xbase = $x;
1518 $this->ybase = -$y;
1519 }
1520 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1521
1522 $pdf_pt = $this->svg_overflow($pdfx,$pdfy);
1523
1524 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1525 $bx = calc_bezier_bbox($start, $curves);
1526 $minl = min($minl,$bx[0]);
1527 $maxr = max($maxr,$bx[2]);
1528 $mint = min($mint,$bx[1]);
1529 $maxb = max($maxb,$bx[3]);
1530
1531 if( ($pdf_pt['x'] != $pdfx) || ($pdf_pt['y'] != $pdfy) )
1532 {
1533 $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x']*$this->kp, $pdf_pt['y']*$this->kp);
1534 }
1535 else
1536 {
1537 $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);
1538 }
1539 }
1540 break;
1541 case 't': // bezier quadratic avec point de control simetrique a lancien point de control
1542 if (!($this->lastcommand == 'Q' || $this->lastcommand == 'q' || $this->lastcommand == 'T' || $this->lastcommand == 't')) {
1543 $this->lastcontrolpoints = array(0,0);
1544 }
1545 for($i = 0; $i<$ile_argumentow; $i += 2){
1546 $x = ($a[$i][0]);
1547 $y = ($a[$i+1][0]);
1548
1549 $x1 = $this->lastcontrolpoints[0];
1550 $y1 = $this->lastcontrolpoints[1];
1551
1552 if($relative){
1553 $pdfx = ($this->xbase + $x);
1554 $pdfy = ($this->ybase - $y);
1555
1556 $pdfx1 = ($this->xbase + ($x1));
1557 $pdfy1 = ($this->ybase - ($y1));
1558 // mPDF 4.4.003
1559 $pdfx2 = $pdfx1 + 1/3 *($x);
1560 $pdfy2 = $pdfy1 + 1/3 *(-$y) ;
1561
1562 $this->xbase += $x;
1563 $this->ybase += -$y;
1564 }
1565 else{
1566 $pdfx = $x;
1567 $pdfy = -$y;
1568
1569 $pdfx1 = ($this->xbase + ($x1));
1570 $pdfy1 = ($this->ybase - ($y1));
1571 // mPDF 4.4.003
1572 $pdfx2 = $pdfx1 + 1/3 *($x - $this->xbase);
1573 $pdfy2 = $pdfy1 + 1/3 *(-$y - $this->ybase) ;
1574
1575 $this->xbase = $x;
1576 $this->ybase = -$y;
1577 }
1578
1579 $this->lastcontrolpoints = array(($pdfx-$pdfx2),-($pdfy-$pdfy2)); // mPDF 4.4.003 always relative
1580
1581 $curves = array($pdfx1,-$pdfy1,$pdfx2,-$pdfy2,$pdfx,-$pdfy);
1582 $bx = calc_bezier_bbox($start, $curves);
1583 $minl = min($minl,$bx[0]);
1584 $maxr = max($maxr,$bx[2]);
1585 $mint = min($mint,$bx[1]);
1586 $maxb = max($maxb,$bx[3]);
1587
1588 $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);
1589 }
1590
1591 break;
1592 case 'a': // Elliptical arc
1593 for($i = 0; $i<$ile_argumentow; $i += 7){
1594 $rx = ($a[$i][0]);
1595 $ry = ($a[$i+1][0]);
1596 $angle = ($a[$i+2][0]); //x-axis-rotation
1597 $largeArcFlag = ($a[$i+3][0]);
1598 $sweepFlag = ($a[$i+4][0]);
1599 $x2 = ($a[$i+5][0]);
1600 $y2 = ($a[$i+6][0]);
1601 $x1 = $this->xbase;
1602 $y1 = -$this->ybase;
1603 if($relative){
1604 $x2 = $this->xbase + $x2;
1605 $y2 = -$this->ybase + $y2;
1606 $this->xbase += ($a[$i+5][0]);
1607 $this->ybase += -($a[$i+6][0]);
1608 }
1609 else{
1610 $this->xbase = $x2;
1611 $this->ybase = -$y2;
1612 }
1613 list($pcmd, $bounds) = $this->Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag);
1614 $minl = min($minl,$x2,min($bounds[0]));
1615 $maxr = max($maxr,$x2,max($bounds[0]));
1616 $mint = min($mint,$y2,min($bounds[1]));
1617 $maxb = max($maxb,$y2,max($bounds[1]));
1618 $path_cmd .= $pcmd;
1619
1620 }
1621 break;
1622 case'z':
1623 $path_cmd .= 'h ';
1624 $this->subPathInit = true;
1625 $newsubpath = true;
1626 $this->xbase = $this->spxstart;
1627 $this->ybase = $this->spystart;
1628 break;
1629 default:
1630 break;
1631 }
1632
1633 if (!$newsubpath) { $this->subPathInit = false; }
1634 $this->lastcommand = $command;
1635 // mPDF 5.0.039
1636 $this->pathBBox[0] = $minl;
1637 $this->pathBBox[1] = $mint;
1638 $this->pathBBox[2] = $maxr - $this->pathBBox[0];
1639 $this->pathBBox[3] = $maxb - $this->pathBBox[1];
1640 return $path_cmd;
1641
1642 }
1643
1644 function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) {
1645
1646 $bounds = array(0=>array($x1,$x2),1=>array($y1,$y2));
1647 // 1. Treat out-of-range parameters as described in
1648 // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
1649 // If the endpoints (x1, y1) and (x2, y2) are identical, then this
1650 // is equivalent to omitting the elliptical arc segment entirely
1651 if ($x1 == $x2 && $y1 == $y2) return array('', $bounds); // mPD 5.0.040
1652
1653 // If rX = 0 or rY = 0 then this arc is treated as a straight line
1654 // segment (a "lineto") joining the endpoints.
1655 if ($rx == 0.0 || $ry == 0.0) {
1656 // return array(Lineto(x2, y2), $bounds);
1657 }
1658
1659 // If rX or rY have negative signs, these are dropped; the absolute
1660 // value is used instead.
1661 if ($rx<0.0) $rx = -$rx;
1662 if ($ry<0.0) $ry = -$ry;
1663
1664 // 2. convert to center parameterization as shown in
1665 // http://www.w3.org/TR/SVG/implnote.html
1666 $sinPhi = sin(deg2rad($angle));
1667 $cosPhi = cos(deg2rad($angle));
1668
1669 $x1dash = $cosPhi * ($x1-$x2)/2.0 + $sinPhi * ($y1-$y2)/2.0;
1670 $y1dash = -$sinPhi * ($x1-$x2)/2.0 + $cosPhi * ($y1-$y2)/2.0;
1671
1672
1673 $numerator = $rx*$rx*$ry*$ry - $rx*$rx*$y1dash*$y1dash - $ry*$ry*$x1dash*$x1dash;
1674
1675 if ($numerator < 0.0) {
1676 // If rX , rY and are such that there is no solution (basically,
1677 // the ellipse is not big enough to reach from (x1, y1) to (x2,
1678 // y2)) then the ellipse is scaled up uniformly until there is
1679 // exactly one solution (until the ellipse is just big enough).
1680
1681 // -> find factor s, such that numerator' with rx'=s*rx and
1682 // ry'=s*ry becomes 0 :
1683 $s = sqrt(1.0 - $numerator/($rx*$rx*$ry*$ry));
1684
1685 $rx *= $s;
1686 $ry *= $s;
1687 $root = 0.0;
1688
1689 }
1690 else {
1691 $root = ($largeArcFlag == $sweepFlag ? -1.0 : 1.0) * sqrt( $numerator/($rx*$rx*$y1dash*$y1dash+$ry*$ry*$x1dash*$x1dash) );
1692 }
1693
1694 $cxdash = $root*$rx*$y1dash/$ry;
1695 $cydash = -$root*$ry*$x1dash/$rx;
1696
1697 $cx = $cosPhi * $cxdash - $sinPhi * $cydash + ($x1+$x2)/2.0;
1698 $cy = $sinPhi * $cxdash + $cosPhi * $cydash + ($y1+$y2)/2.0;
1699
1700
1701 $theta1 = $this->CalcVectorAngle(1.0, 0.0, ($x1dash-$cxdash)/$rx, ($y1dash-$cydash)/$ry);
1702 $dtheta = $this->CalcVectorAngle(($x1dash-$cxdash)/$rx, ($y1dash-$cydash)/$ry, (-$x1dash-$cxdash)/$rx, (-$y1dash-$cydash)/$ry);
1703 if (!$sweepFlag && $dtheta>0)
1704 $dtheta -= 2.0*M_PI;
1705 else if ($sweepFlag && $dtheta<0)
1706 $dtheta += 2.0*M_PI;
1707
1708 // 3. convert into cubic bezier segments <= 90deg
1709 $segments = ceil(abs($dtheta/(M_PI/2.0)));
1710 $delta = $dtheta/$segments;
1711 $t = 8.0/3.0 * sin($delta/4.0) * sin($delta/4.0) / sin($delta/2.0);
1712 $coords = array();
1713 for ($i = 0; $i < $segments; $i++) {
1714 $cosTheta1 = cos($theta1);
1715 $sinTheta1 = sin($theta1);
1716 $theta2 = $theta1 + $delta;
1717 $cosTheta2 = cos($theta2);
1718 $sinTheta2 = sin($theta2);
1719
1720 // a) calculate endpoint of the segment:
1721 $xe = $cosPhi * $rx*$cosTheta2 - $sinPhi * $ry*$sinTheta2 + $cx;
1722 $ye = $sinPhi * $rx*$cosTheta2 + $cosPhi * $ry*$sinTheta2 + $cy;
1723
1724 // b) calculate gradients at start/end points of segment:
1725 $dx1 = $t * ( - $cosPhi * $rx*$sinTheta1 - $sinPhi * $ry*$cosTheta1);
1726 $dy1 = $t * ( - $sinPhi * $rx*$sinTheta1 + $cosPhi * $ry*$cosTheta1);
1727
1728 $dxe = $t * ( $cosPhi * $rx*$sinTheta2 + $sinPhi * $ry*$cosTheta2);
1729 $dye = $t * ( $sinPhi * $rx*$sinTheta2 - $cosPhi * $ry*$cosTheta2);
1730
1731 // c) draw the cubic bezier:
1732 $coords[$i] = array(($x1+$dx1), ($y1+$dy1), ($xe+$dxe), ($ye+$dye), $xe, $ye);
1733
1734 // do next segment
1735 $theta1 = $theta2;
1736 $x1 = $xe;
1737 $y1 = $ye;
1738 }
1739 $path = ' ';
1740 foreach($coords AS $c) {
1741 $cpx1 = $c[0];
1742 $cpy1 = $c[1];
1743 $cpx2 = $c[2];
1744 $cpy2 = $c[3];
1745 $x2 = $c[4];
1746 $y2 = $c[5];
1747 $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";
1748
1749 // mPDF 5.0.040
1750 $bounds[0][] = $c[4];
1751 $bounds[1][] = $c[5];
1752 }
1753 return array($path, $bounds); // mPD 5.0.040
1754 }
1755
1756
1757 function CalcVectorAngle($ux, $uy, $vx, $vy) {
1758 $ta = atan2($uy, $ux);
1759 $tb = atan2($vy, $vx);
1760 if ($tb >= $ta)
1761 return ($tb-$ta);
1762 return (6.28318530718 - ($ta-$tb));
1763 }
1764
1765
1766 function ConvertSVGSizePixels($size=5,$maxsize='x'){
1767 // maxsize in pixels (user units) or 'y' or 'x'
1768 // e.g. $w = $this->ConvertSVGSizePixels($arguments['w'],$this->svg_info['w']*(25.4/$this->mpdf_ref->dpi));
1769 // usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
1770 // Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
1771 // For text $maxsize = Fontsize
1772 // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
1773
1774 if ($maxsize == 'y') { $maxsize = $this->svg_info['h']; }
1775 else if ($maxsize == 'x') { $maxsize = $this->svg_info['w']; }
1776 $maxsize *= (25.4/$this->mpdf_ref->dpi); // convert pixels to mm
1777 $fontsize=$this->mpdf_ref->FontSize / $this->kf;
1778 //Return as pixels
1779 $size = $this->mpdf_ref->ConvertSize($size,$maxsize,$fontsize,false) * 1/(25.4/$this->mpdf_ref->dpi);
1780 return $size;
1781 }
1782
1783 function ConvertSVGSizePts($size=5){
1784 // usefontsize - setfalse for e.g. margins - will ignore fontsize for % values
1785 // Depends of maxsize value to make % work properly. Usually maxsize == pagewidth
1786 // For text $maxsize = Fontsize
1787 // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize
1788 $maxsize=$this->mpdf_ref->FontSize;
1789 //Return as pts
1790 $size = $this->mpdf_ref->ConvertSize($size,$maxsize,false,true) * 72/25.4;
1791 return $size;
1792 }
1793
1794
1795 //
1796 // fonction retracant les <rect />
1797 function svgRect($arguments){
1798
1799 if ($arguments['h']==0 || $arguments['w']==0) { return ''; }
1800
1801 $x = $this->ConvertSVGSizePixels($arguments['x'],'x'); // mPDF 4.4.003
1802 $y = $this->ConvertSVGSizePixels($arguments['y'],'y'); // mPDF 4.4.003
1803 $h = $this->ConvertSVGSizePixels($arguments['h'],'y'); // mPDF 4.4.003
1804 $w = $this->ConvertSVGSizePixels($arguments['w'],'x'); // mPDF 4.4.003
1805 $rx = $this->ConvertSVGSizePixels($arguments['rx'],'x'); // mPDF 4.4.003
1806 $ry = $this->ConvertSVGSizePixels($arguments['ry'],'y'); // mPDF 4.4.003
1807
1808 if ($rx > $w/2) { $rx = $w/2; } // mPDF 4.4.003
1809 if ($ry > $h/2) { $ry = $h/2; } // mPDF 4.4.003
1810
1811 if ($rx>0 and $ry == 0){$ry = $rx;}
1812 if ($ry>0 and $rx == 0){$rx = $ry;}
1813
1814 if ($rx == 0 and $ry == 0){
1815 // trace un rectangle sans angle arrondit
1816 $path_cmd = sprintf('%.3F %.3F m ', ($x*$this->kp), -($y*$this->kp));
1817 $path_cmd .= sprintf('%.3F %.3F l ', (($x+$w)*$this->kp), -($y*$this->kp));
1818 $path_cmd .= sprintf('%.3F %.3F l ', (($x+$w)*$this->kp), -(($y+$h)*$this->kp));
1819 $path_cmd .= sprintf('%.3F %.3F l ', ($x)*$this->kp, -(($y+$h)*$this->kp));
1820 $path_cmd .= sprintf('%.3F %.3F l h ', ($x*$this->kp), -($y*$this->kp));
1821
1822
1823 }
1824 else {
1825 // trace un rectangle avec les arrondit
1826 // les points de controle du bezier sont deduis grace a la constante kappa
1827 $kappa = 4*(sqrt(2)-1)/3;
1828
1829 $kx = $kappa*$rx;
1830 $ky = $kappa*$ry;
1831
1832 $path_cmd = sprintf('%.3F %.3F m ', ($x+$rx)*$this->kp, -$y*$this->kp);
1833 $path_cmd .= sprintf('%.3F %.3F l ', ($x+($w-$rx))*$this->kp, -$y*$this->kp);
1834 $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 );
1835 $path_cmd .= sprintf('%.3F %.3F l ', ($x+$w)*$this->kp, (-$y+(-$h+$ry))*$this->kp);
1836 $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 );
1837
1838 $path_cmd .= sprintf('%.3F %.3F l ', ($x+$rx)*$this->kp, (-$y+(-$h))*$this->kp);
1839 $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 );
1840 $path_cmd .= sprintf('%.3F %.3F l ', $x*$this->kp, (-$y+(-$ry))*$this->kp);
1841 $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 );
1842
1843
1844 }
1845 return $path_cmd;
1846 }
1847
1848 //
1849 // fonction retracant les <ellipse /> et <circle />
1850 // le cercle est trac� grave a 4 bezier cubic, les poitn de controles
1851 // sont deduis grace a la constante kappa * rayon
1852 function svgEllipse($arguments){
1853 if ($arguments['rx']==0 || $arguments['ry']==0) { return ''; }
1854
1855 $kappa = 4*(sqrt(2)-1)/3;
1856
1857 $cx = $this->ConvertSVGSizePixels($arguments['cx'],'x');
1858 $cy = $this->ConvertSVGSizePixels($arguments['cy'],'y');
1859 $rx = $this->ConvertSVGSizePixels($arguments['rx'],'x');
1860 $ry = $this->ConvertSVGSizePixels($arguments['ry'],'y');
1861
1862 $x1 = $cx;
1863 $y1 = -$cy+$ry;
1864
1865 $x2 = $cx+$rx;
1866 $y2 = -$cy;
1867
1868 $x3 = $cx;
1869 $y3 = -$cy-$ry;
1870
1871 $x4 = $cx-$rx;
1872 $y4 = -$cy;
1873
1874 $path_cmd = sprintf('%.3F %.3F m ', $x1*$this->kp, $y1*$this->kp);
1875 $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);
1876 $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);
1877 $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);
1878 $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);
1879 $path_cmd .= 'h ';
1880
1881 return $path_cmd;
1882
1883 }
1884
1885 //
1886 // fonction retracant les <polyline /> et les <line />
1887 function svgPolyline($arguments,$ispolyline=true){
1888 if ($ispolyline) {
1889 $xbase = $arguments[0] ;
1890 $ybase = - $arguments[1] ;
1891 }
1892 else {
1893 if ($arguments[0]==$arguments[2] && $arguments[1]==$arguments[3]) { return ''; } // Zero length line
1894 $xbase = $this->ConvertSVGSizePixels($arguments[0],'x');
1895 $ybase = - $this->ConvertSVGSizePixels($arguments[1],'y');
1896 }
1897 $path_cmd = sprintf('%.3F %.3F m ', $xbase*$this->kp, $ybase*$this->kp);
1898 for ($i = 2; $i<count($arguments);$i += 2) {
1899 if ($ispolyline) {
1900 $tmp_x = $arguments[$i] ;
1901 $tmp_y = - $arguments[($i+1)] ;
1902 }
1903 else {
1904 $tmp_x = $this->ConvertSVGSizePixels($arguments[$i],'x') ;
1905 $tmp_y = - $this->ConvertSVGSizePixels($arguments[($i+1)],'y') ;
1906 }
1907 $path_cmd .= sprintf('%.3F %.3F l ', $tmp_x*$this->kp, $tmp_y*$this->kp);
1908 }
1909
1910 // $path_cmd .= 'h '; // ?? In error - don't close subpath here
1911 return $path_cmd;
1912
1913 }
1914
1915 //
1916 // fonction retracant les <polygone />
1917 function svgPolygon($arguments){
1918 $xbase = $arguments[0] ;
1919 $ybase = - $arguments[1] ;
1920 $path_cmd = sprintf('%.3F %.3F m ', $xbase*$this->kp, $ybase*$this->kp);
1921 for ($i = 2; $i<count($arguments);$i += 2) {
1922 $tmp_x = $arguments[$i] ;
1923 $tmp_y = - $arguments[($i+1)] ;
1924
1925 $path_cmd .= sprintf('%.3F %.3F l ', $tmp_x*$this->kp, $tmp_y*$this->kp);
1926
1927 }
1928 $path_cmd .= sprintf('%.3F %.3F l ', $xbase*$this->kp, $ybase*$this->kp);
1929 $path_cmd .= 'h ';
1930 return $path_cmd;
1931
1932 }
1933
1934 //
1935 // write string to image
1936 function svgText() {
1937 // $tmp = count($this->txt_style)-1;
1938 $current_style = $this->txt_style[count($this->txt_style)-1]; // mPDF 5.7.4
1939 $style = '';
1940 $op = '';
1941 $render = -1;
1942 if(isset($this->txt_data[2])) {
1943 // mPDF 6
1944 // If using SVG Font
1945 if (isset($this->svg_font[$current_style['font-family']])) {
1946 // select font
1947 $style = 'R';
1948 $style .= (isset($current_style['font-weight']) && $current_style['font-weight'] == 'bold')?'B':'';
1949 $style .= (isset($current_style['font-style']) && $current_style['font-style'] == 'italic')?'I':'';
1950 $style .= (isset($current_style['font-variant']) && $current_style['font-variant'] == 'small-caps')?'S':'';
1951
1952 $fontsize = $current_style['font-size'] * $this->mpdf_ref->dpi / 72;
1953 if (isset($this->svg_font[$current_style['font-family']][$style])) {
1954 $svg_font = $this->svg_font[$current_style['font-family']][$style];
1955 }
1956 else if (isset($this->svg_font[$current_style['font-family']]['R'])) {
1957 $svg_font = $this->svg_font[$current_style['font-family']]['R'];
1958 }
1959
1960 if (!isset($svg_font['units-per-em']) || $svg_font['units-per-em']<1) { $svg_font['units-per-em'] = 1000; }
1961 $units_per_em = $svg_font['units-per-em'];
1962 $scale = $fontsize / $units_per_em;
1963 $stroke_width = $current_style['stroke-width'];
1964 $stroke_width /= $scale;
1965
1966 $opacitystr = '';
1967 $fopacity = 1;
1968 if (isset($current_style['fill-opacity'])) {
1969 if ($current_style['fill-opacity'] == 0) { $fopacity = 0; }
1970 else if ($current_style['fill-opacity'] > 1) { $fopacity = 1; }
1971 else if ($current_style['fill-opacity'] > 0) { $fopacity = $current_style['fill-opacity']; }
1972 else if ($current_style['fill-opacity'] < 0) { $fopacity = 0; }
1973 }
1974 $sopacity = 1;
1975 if (isset($current_style['stroke-opacity'])) {
1976 if ($current_style['stroke-opacity'] == 0) { $sopacity = 0; }
1977 else if ($current_style['stroke-opacity'] > 1) { $sopacity = 1; }
1978 else if ($current_style['stroke-opacity'] > 0) { $sopacity = $current_style['stroke-opacity']; }
1979 else if ($current_style['stroke-opacity'] < 0) { $sopacity = 0; }
1980 }
1981 $gs = $this->mpdf_ref->AddExtGState(array('ca'=>$fopacity, 'CA'=>$sopacity, 'BM'=>'/Normal'));
1982 $this->mpdf_ref->extgstates[$gs]['fo'] = true;
1983 $opacitystr = sprintf(' /GS%d gs ', $gs);
1984
1985 $fillstr = '';
1986 if (isset($current_style['fill']) && $current_style['fill']!='none') {
1987 $col = $this->mpdf_ref->ConvertColor($current_style['fill']);
1988 $fillstr = $this->mpdf_ref->SetFColor($col, true);
1989 $render = "0"; // Fill (only)
1990 $op = 'f';
1991 }
1992 $strokestr = '';
1993 if ($stroke_width>0 && $current_style['stroke']!='none') {
1994 $scol = $this->mpdf_ref->ConvertColor($current_style['stroke']);
1995 if ($scol) {
1996 $strokestr .= $this->mpdf_ref->SetDColor($scol, true).' ';
1997 }
1998 $linewidth = $this->ConvertSVGSizePixels($stroke_width);
1999 if ($linewidth > 0) {
2000 $strokestr .= sprintf('%.3F w 0 J 0 j ',$linewidth*$this->kp);
2001 if ($render == -1) { $render = "1"; } // stroke only
2002 else { $render = "2"; } // fill and stroke
2003 $op .= 'S';
2004 }
2005 }
2006 if ($render == -1) { return ''; }
2007 if ($op == 'fS') { $op = 'B'; }
2008
2009 $x = $this->txt_data[0]; // mPDF 5.7.4
2010 $y = $this->txt_data[1]; // mPDF 5.7.4
2011 $txt = $this->txt_data[2];
2012
2013 $txt = preg_replace('/\f/','',$txt);
2014 $txt = preg_replace('/\r/','',$txt);
2015 $txt = preg_replace('/\n/',' ',$txt);
2016 $txt = preg_replace('/\t/',' ',$txt);
2017 $txt = preg_replace("/[ ]+/u",' ',$txt);
2018
2019 if ($this->textjuststarted) { $txt = ltrim($txt); } // mPDF 5.7.4
2020 $this->textjuststarted = false; // mPDF 5.7.4
2021
2022 $txt = $this->mpdf_ref->purify_utf8_text($txt);
2023 if ($this->mpdf_ref->text_input_as_HTML) {
2024 $txt = $this->mpdf_ref->all_entities_to_utf8($txt);
2025 }
2026
2027 $nb=mb_strlen($txt, 'UTF-8');
2028 $i=0;
2029 $sw = 0;
2030 $subpath_cmd = '';
2031 while($i<$nb) {
2032 //Get next character
2033 $char = mb_substr($txt,$i,1,'UTF-8');
2034
2035
2036 if (isset($svg_font['glyphs'][$char])) {
2037 $d = $svg_font['glyphs'][$char]['d'];
2038 if (isset($svg_font['glyphs'][$char]['horiz-adv-x'])) { $horiz_adv_x = $svg_font['glyphs'][$char]['horiz-adv-x']; }
2039 else { $horiz_adv_x = $svg_font['horiz-adv-x']; } // missing glyph width
2040 }
2041 else {
2042 $d = $svg_font['d'];
2043 $horiz_adv_x = $svg_font['horiz-adv-x']; // missing glyph width
2044 }
2045 preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $d, $commands, PREG_SET_ORDER);
2046 $subpath_cmd .= sprintf('q %.4F 0 0 %.4F mPDF-AXS(%.4F) %.4F cm ', $scale, -$scale, ($x + $sw*$scale)*$this->kp, -$y*$this->kp);
2047
2048 $this->subPathInit = true;
2049 $this->pathBBox = array(999999,999999,-999999,-999999);
2050 foreach($commands as $cmd){
2051 if(count($cmd)==3 || (isset($cmd[2]) && $cmd[2]=='')){
2052 list($tmp, $command, $arguments) = $cmd;
2053 }
2054 else{
2055 list($tmp, $command) = $cmd;
2056 $arguments = '';
2057 }
2058
2059 $subpath_cmd .= $this->svgPath($command, $arguments);
2060 }
2061 $subpath_cmd .= $op . ' Q ';
2062 if ($this->pathBBox[2]==-1999998) { $this->pathBBox[2] = 100; }
2063 if ($this->pathBBox[3]==-1999998) { $this->pathBBox[3] = 100; }
2064 if ($this->pathBBox[0]==999999) { $this->pathBBox[0] = 0; }
2065 if ($this->pathBBox[1]==999999) { $this->pathBBox[1] = 0; }
2066
2067
2068 $sw += $horiz_adv_x;
2069 $i++;
2070 }
2071
2072 $sw *= $scale; // convert stringwidth to units
2073
2074 // mPDF 5.7.4
2075 $this->textlength = $sw;
2076 $this->texttotallength += $this->textlength;
2077
2078 $path_cmd = sprintf('q %s %s Tr %s %s ',$opacitystr,$render,$fillstr,$strokestr);
2079 $path_cmd .= $subpath_cmd;
2080 $path_cmd .= 'Q ';
2081
2082 unset($this->txt_data[0], $this->txt_data[1], $this->txt_data[2]);
2083 return $path_cmd;
2084 }
2085
2086 // select font
2087 $style .= ($current_style['font-weight'] == 'bold')?'B':'';
2088 $style .= ($current_style['font-style'] == 'italic')?'I':'';
2089 $size = $current_style['font-size']*$this->kf;
2090
2091 $current_style['font-family'] = $this->mpdf_ref->SetFont($current_style['font-family'],$style,$size,false);
2092 $this->mpdf_ref->CurrentFont['fo'] = true;
2093
2094 $opacitystr = '';
2095 // mPDF 6
2096 $fopacity = 1;
2097 if (isset($current_style['fill-opacity'])) {
2098 if ($current_style['fill-opacity'] == 0) { $fopacity = 0; }
2099 else if ($current_style['fill-opacity'] > 1) { $fopacity = 1; }
2100 else if ($current_style['fill-opacity'] > 0) { $fopacity = $current_style['fill-opacity']; }
2101 else if ($current_style['fill-opacity'] < 0) { $fopacity = 0; }
2102 }
2103 $sopacity = 1;
2104 if (isset($current_style['stroke-opacity'])) {
2105 if ($current_style['stroke-opacity'] == 0) { $sopacity = 0; }
2106 else if ($current_style['stroke-opacity'] > 1) { $sopacity = 1; }
2107 else if ($current_style['stroke-opacity'] > 0) { $sopacity = $current_style['stroke-opacity']; }
2108 else if ($current_style['stroke-opacity'] < 0) { $sopacity = 0; }
2109 }
2110 $gs = $this->mpdf_ref->AddExtGState(array('ca'=>$fopacity, 'CA'=>$sopacity, 'BM'=>'/Normal'));
2111 $this->mpdf_ref->extgstates[$gs]['fo'] = true;
2112 $opacitystr = sprintf(' /GS%d gs ', $gs);
2113
2114 $fillstr = '';
2115 if (isset($current_style['fill']) && $current_style['fill']!='none') {
2116 $col = $this->mpdf_ref->ConvertColor($current_style['fill']);
2117 $fillstr = $this->mpdf_ref->SetFColor($col, true);
2118 $render = "0"; // Fill (only)
2119 }
2120 $strokestr = '';
2121 if (isset($current_style['stroke-width']) && $current_style['stroke-width']>0 && $current_style['stroke']!='none') {
2122 $scol = $this->mpdf_ref->ConvertColor($current_style['stroke']);
2123 if ($scol) {
2124 $strokestr .= $this->mpdf_ref->SetDColor($scol, true).' ';
2125 }
2126 $linewidth = $this->ConvertSVGSizePixels($current_style['stroke-width']);
2127 if ($linewidth > 0) {
2128 $strokestr .= sprintf('%.3F w 1 J 1 j ',$linewidth*$this->kp);
2129 if ($render == -1) { $render = "1"; } // stroke only
2130 else { $render = "2"; } // fill and stroke
2131 }
2132 }
2133 if ($render == -1) { return ''; }
2134
2135 $x = $this->txt_data[0]; // mPDF 5.7.4
2136 $y = $this->txt_data[1]; // mPDF 5.7.4
2137 $txt = $this->txt_data[2];
2138
2139 $txt = preg_replace('/\f/','',$txt);
2140 $txt = preg_replace('/\r/','',$txt);
2141 $txt = preg_replace('/\n/',' ',$txt);
2142 $txt = preg_replace('/\t/',' ',$txt);
2143 $txt = preg_replace("/[ ]+/u",' ',$txt);
2144
2145 if ($this->textjuststarted) { $txt = ltrim($txt); } // mPDF 5.7.4
2146 $this->textjuststarted = false; // mPDF 5.7.4
2147
2148 $txt = $this->mpdf_ref->purify_utf8_text($txt);
2149 if ($this->mpdf_ref->text_input_as_HTML) {
2150 $txt = $this->mpdf_ref->all_entities_to_utf8($txt);
2151 }
2152
2153 if ($this->mpdf_ref->usingCoreFont) { $txt = mb_convert_encoding($txt,$this->mpdf_ref->mb_enc,'UTF-8'); }
2154 if (preg_match("/([".$this->mpdf_ref->pregRTLchars."])/u", $txt)) { $this->mpdf_ref->biDirectional = true; }
2155
2156 $textvar = 0;
2157 $save_OTLtags = $this->mpdf_ref->OTLtags;
2158 $this->mpdf_ref->OTLtags = array();
2159 if ($this->mpdf_ref->useKerning) {
2160 if ($this->mpdf_ref->CurrentFont['haskernGPOS']) {
2161 if (isset($this->mpdf_ref->OTLtags['Plus'])) { $this->mpdf_ref->OTLtags['Plus'] .= ' kern'; }
2162 else { $this->mpdf_ref->OTLtags['Plus'] = ' kern'; }
2163 }
2164 else { $textvar = ($textvar | FC_KERNING); }
2165 }
2166
2167 // Use OTL OpenType Table Layout - GSUB & GPOS
2168 if (isset($this->mpdf_ref->CurrentFont['useOTL']) && $this->mpdf_ref->CurrentFont['useOTL']) {
2169 $txt = $this->mpdf_ref->otl->applyOTL($txt, $this->mpdf_ref->CurrentFont['useOTL']);
2170 $OTLdata = $this->mpdf_ref->otl->OTLdata;
2171 }
2172 $this->mpdf_ref->OTLtags = $save_OTLtags ;
2173
2174 $this->mpdf_ref->magic_reverse_dir($txt, $this->mpdf_ref->directionality, $OTLdata);
2175
2176 $this->mpdf_ref->CurrentFont['used']= true;
2177
2178 $sw = $this->mpdf_ref->GetStringWidth($txt, true, $OTLdata, $textvar); // also adds characters to subset
2179
2180 // mPDF 5.7.4
2181 $this->textlength = $sw * 1/(25.4/$this->mpdf_ref->dpi);
2182 $this->texttotallength += $this->textlength;
2183
2184 $pdfx = $x *$this->kp;
2185 $pdfy = -$y *$this->kp;
2186
2187 $aixextra = sprintf(' /F%d %.3F Tf %s %s Tr %s %s ',$this->mpdf_ref->CurrentFont['i'],$this->mpdf_ref->FontSizePt,$opacitystr,$render,$fillstr,$strokestr);
2188
2189 $path_cmd = 'q 1 0 0 1 mPDF-AXS(0.00) 0 cm '; // Align X-shift
2190 $path_cmd .= $this->mpdf_ref->Text($pdfx,$pdfy,$txt,$OTLdata,$textvar,$aixextra,'SVG',true);
2191 $path_cmd .= " Q\n";
2192
2193 unset($this->txt_data[0], $this->txt_data[1], $this->txt_data[2]);
2194
2195 if (isset($current_style['font-size-parent'])) {
2196 $this->mpdf_ref->SetFontSize($current_style['font-size-parent']);
2197 }
2198 }
2199 else { return ' '; }
2200 // Reset font // mPDF 5.7.4
2201 $prev_style = $this->txt_style[count($this->txt_style)-1];
2202 $style = '';
2203 $style .= ($prev_style['font-weight'] == 'bold')?'B':'';
2204 $style .= ($prev_style['font-style'] == 'italic')?'I':'';
2205 $size = $prev_style['font-size']*$this->kf;
2206 $this->mpdf_ref->SetFont($prev_style['font-family'],$style,$size,false);
2207
2208 return $path_cmd;
2209 }
2210
2211
2212 function svgDefineTxtStyle($critere_style)
2213 {
2214 // get copy of current/default txt style, and modify it with supplied attributes
2215 $tmp = count($this->txt_style)-1;
2216 $current_style = $this->txt_style[$tmp];
2217 if (isset($critere_style['style'])){
2218 if (preg_match('/fill:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
2219 $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);
2220 }
2221 else { $tmp = preg_replace("/(.*)fill:\s*([a-z0-9#_()]*|none)(.*)/i","$2",$critere_style['style']);
2222 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['fill'] = $tmp; }
2223 }
2224
2225 // mPDF 6
2226 if (preg_match("/[^-]opacity:\s*([a-z0-9.]*|none)/i",$critere_style['style'], $m) ||
2227 preg_match("/^opacity:\s*([a-z0-9.]*|none)/i",$critere_style['style'], $m)) {
2228 $current_style['fill-opacity'] = $m[1];
2229 $current_style['stroke-opacity'] = $m[1];
2230 }
2231
2232 $tmp = preg_replace("/(.*)fill-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
2233 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['fill-opacity'] = $tmp;}
2234
2235 $tmp = preg_replace("/(.*)fill-rule:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
2236 if ($tmp != $critere_style['style'] && $tmp!=$critere_style['style']){ $current_style['fill-rule'] = $tmp;}
2237
2238 if (preg_match('/stroke:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/',$critere_style['style'], $m)) {
2239 $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);
2240 }
2241 else { $tmp = preg_replace("/(.*)stroke:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
2242 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['stroke'] = $tmp; }
2243 }
2244
2245 $tmp = preg_replace("/(.*)stroke-linecap:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
2246 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-linecap'] = $tmp;}
2247
2248 $tmp = preg_replace("/(.*)stroke-linejoin:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
2249 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-linejoin'] = $tmp;}
2250
2251 $tmp = preg_replace("/(.*)stroke-miterlimit:\s*([a-z0-9#]*|none)(.*)/i","$2",$critere_style['style']);
2252 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-miterlimit'] = $tmp;}
2253
2254 $tmp = preg_replace("/(.*)stroke-opacity:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
2255 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-opacity'] = $tmp; }
2256
2257 $tmp = preg_replace("/(.*)stroke-width:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
2258 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-width'] = $tmp;}
2259
2260 $tmp = preg_replace("/(.*)stroke-dasharray:\s*([a-z0-9., ]*|none)(.*)/i","$2",$critere_style['style']);
2261 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-dasharray'] = $tmp;}
2262
2263 $tmp = preg_replace("/(.*)stroke-dashoffset:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
2264 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $current_style['stroke-dashoffset'] = $tmp;}
2265
2266 $tmp = preg_replace("/(.*)font-family:\s*([a-z0-9.\"' ,\-]*|none)(.*)/i","$2",$critere_style['style']);
2267 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $critere_style['font-family'] = $tmp;}
2268
2269 $tmp = preg_replace("/(.*)font-size:\s*([a-z0-9.]*|none)(.*)/i","$2",$critere_style['style']);
2270 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $critere_style['font-size'] = $tmp;}
2271
2272 $tmp = preg_replace("/(.*)font-weight:\s*([a-z0-9.]*|normal)(.*)/i","$2",$critere_style['style']);
2273 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $critere_style['font-weight'] = $tmp;}
2274
2275 $tmp = preg_replace("/(.*)font-style:\s*([a-z0-9.]*|normal)(.*)/i","$2",$critere_style['style']);
2276 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $critere_style['font-style'] = $tmp;}
2277
2278 $tmp = preg_replace("/(.*)font-variant:\s*([a-z0-9.]*|normal)(.*)/i","$2",$critere_style['style']);
2279 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $critere_style['font-variant'] = $tmp;}
2280
2281 $tmp = preg_replace("/(.*)text-anchor:\s*(start|middle|end)(.*)/i","$2",$critere_style['style']);
2282 if ($tmp && $tmp != 'inherit' && $tmp!=$critere_style['style']){ $critere_style['text-anchor'] = $tmp;}
2283
2284 }
2285 if (isset($critere_style['font'])){
2286
2287 // [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]?<'font-size'> [ / <'line-height'> ]? <'font-family'> ]
2288
2289 $tmp = preg_replace("/(.*)(italic|oblique)(.*)/i","$2",$critere_style['font']);
2290 if ($tmp != $critere_style['font']){
2291 if($tmp == 'oblique'){
2292 $tmp = 'italic';
2293 }
2294 $current_style['font-style'] = $tmp;
2295 }
2296 $tmp = preg_replace("/(.*)(bold|bolder)(.*)/i","$2",$critere_style['font']);
2297 if ($tmp != $critere_style['font']){
2298 if($tmp == 'bolder'){
2299 $tmp = 'bold';
2300 }
2301 $current_style['font-weight'] = $tmp;
2302 }
2303
2304 $tmp = preg_replace("/(.*)(small\-caps)(.*)/i","$2",$critere_style['font']);
2305 if ($tmp != $critere_style['font']){
2306 $current_style['font-variant'] = $tmp;
2307 }
2308
2309 // select digits not followed by percent sign nor preceeded by forward slash
2310 $tmp = preg_replace("/(.*)\b(\d+)[\b|\/](.*)/i","$2",$critere_style['font']);
2311 if ($tmp != $critere_style['font']){
2312 $current_style['font-size'] = $this->ConvertSVGSizePts($tmp);
2313 $this->mpdf_ref->SetFont('','',$current_style['font-size'],false);
2314 }
2315
2316 }
2317
2318 // mPDF 6
2319 if(isset($critere_style['opacity']) && $critere_style['opacity']!='inherit'){
2320 $current_style['fill-opacity'] = $critere_style['opacity'];
2321 $current_style['stroke-opacity'] = $critere_style['opacity'];
2322 }
2323 // mPDF 6
2324 if(isset($critere_style['stroke-opacity']) && $critere_style['stroke-opacity']!='inherit'){
2325 $current_style['stroke-opacity'] = $critere_style['stroke-opacity'];
2326 }
2327 // mPDF 6
2328 if(isset($critere_style['fill-opacity']) && $critere_style['fill-opacity']!='inherit'){
2329 $current_style['fill-opacity'] = $critere_style['fill-opacity'];
2330 }
2331 if(isset($critere_style['fill']) && $critere_style['fill']!='inherit'){
2332 $current_style['fill'] = $critere_style['fill'];
2333 }
2334 if(isset($critere_style['stroke']) && $critere_style['stroke']!='inherit'){
2335 $current_style['stroke'] = $critere_style['stroke'];
2336 }
2337 if(isset($critere_style['stroke-width']) && $critere_style['stroke-width']!='inherit'){
2338 $current_style['stroke-width'] = $critere_style['stroke-width'];
2339 }
2340
2341 if(isset($critere_style['font-style']) && $critere_style['font-style']!='inherit'){
2342 if(strtolower($critere_style['font-style']) == 'oblique')
2343 {
2344 $critere_style['font-style'] = 'italic';
2345 }
2346 $current_style['font-style'] = $critere_style['font-style'];
2347 }
2348
2349 if(isset($critere_style['font-weight']) && $critere_style['font-weight']!='inherit'){
2350 if(strtolower($critere_style['font-weight']) == 'bolder')
2351 {
2352 $critere_style['font-weight'] = 'bold';
2353 }
2354 $current_style['font-weight'] = $critere_style['font-weight'];
2355 }
2356
2357 if(isset($critere_style['font-variant']) && $critere_style['font-variant']!='inherit'){
2358 $current_style['font-variant'] = $critere_style['font-variant'];
2359 }
2360
2361 if(isset($critere_style['font-size']) && $critere_style['font-size']!='inherit'){
2362 if (strpos($critere_style['font-size'], '%')!==false) {
2363 $current_style['font-size-parent'] = $current_style['font-size'];
2364 }
2365 $current_style['font-size'] = $this->ConvertSVGSizePts($critere_style['font-size']);
2366 $this->mpdf_ref->SetFont('','',$current_style['font-size'],false);
2367 }
2368
2369 if(isset($critere_style['font-family']) && $critere_style['font-family']!='inherit'){
2370 $v = $critere_style['font-family'];
2371 $aux_fontlist = explode(",",$v);
2372 $found = 0;
2373
2374 $svgfontstyle = 'R';
2375 $svgfontstyle .= (isset($current_style['font-weight']) && $current_style['font-weight'] == 'bold')?'B':'';
2376 $svgfontstyle .= (isset($current_style['font-style']) && $current_style['font-style'] == 'italic')?'I':'';
2377 $svgfontstyle .= (isset($current_style['font-variant']) && $current_style['font-variant'] == 'small-caps')?'S':'';
2378
2379 foreach($aux_fontlist AS $f) {
2380 $fonttype = trim($f);
2381 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
2382 $fonttype = preg_replace('/ /','',$fonttype);
2383 $v = strtolower(trim($fonttype));
2384 if (isset($this->mpdf_ref->fonttrans[$v]) && $this->mpdf_ref->fonttrans[$v]) { $v = $this->mpdf_ref->fonttrans[$v]; }
2385 if ((!$this->mpdf_ref->usingCoreFont && in_array($v,$this->mpdf_ref->available_unifonts)) ||
2386 ($this->mpdf_ref->usingCoreFont && in_array($v,array('courier','times','helvetica','arial'))) ||
2387 in_array($v, array('sjis','uhc','big5','gb')) || isset($this->svg_font[$v][$svgfontstyle ])) { // mPDF 6
2388 $current_style['font-family'] = $v;
2389 $found = 1;
2390 break;
2391 }
2392 }
2393 if (!$found) {
2394 foreach($aux_fontlist AS $f) {
2395 $fonttype = trim($f);
2396 $fonttype = preg_replace('/["\']*(.*?)["\']*/','\\1',$fonttype);
2397 $fonttype = preg_replace('/ /','',$fonttype);
2398 $v = strtolower(trim($fonttype));
2399 if (isset($this->mpdf_ref->fonttrans[$v]) && $this->mpdf_ref->fonttrans[$v]) { $v = $this->mpdf_ref->fonttrans[$v]; }
2400 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) || isset($this->svg_font[$v][$svgfontstyle ])) { // mPDF 6
2401 $current_style['font-family'] = $v;
2402 break;
2403 }
2404 }
2405 }
2406 }
2407 if(isset($critere_style['text-anchor']) && $critere_style['text-anchor']!='inherit'){
2408 $current_style['text-anchor'] = $critere_style['text-anchor'];
2409 }
2410
2411 // add current style to text style array (will remove it later after writing text to svg_string)
2412 array_push($this->txt_style,$current_style);
2413 }
2414
2415
2416
2417 //
2418 // fonction ajoutant un gradient
2419 function svgAddGradient($id,$array_gradient){
2420
2421 $this->svg_gradient[$id] = $array_gradient;
2422
2423 }
2424 //
2425 // Ajoute une couleur dans le gradient correspondant
2426
2427 //
2428 // function ecrivant dans le svgstring
2429 function svgWriteString($content){
2430
2431 $this->svg_string .= $content;
2432
2433 }
2434
2435
2436
2437 // analise le svg et renvoie aux fonctions precedente our le traitement
2438 function ImageSVG($data){
2439 // Try to clean up the start of the file
2440 // removing DOCTYPE fails with this:
2441 /*
2442 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd"
2443 [
2444 <!ELEMENT Paragraph (#PCDATA)>
2445 ]>
2446 */
2447 //$data = preg_replace('/<!DOCTYPE.*? >/is', '', $data);
2448 //$data = preg_replace('/<\?xml.*? >/is', '', $data);
2449
2450 $data = preg_replace('/^.*?<svg([> ])/is', '<svg\\1', $data); // mPDF 5.7.4
2451
2452 $data = preg_replace('/<!--.*?-->/is', '', $data); // mPDF 5.7.4
2453
2454 // Converts < to &lt; when not a tag
2455 $data = preg_replace('/<([^!?\/a-zA-Z_:])/i','&lt;\\1',$data ); // mPDF 5.7.4
2456
2457 if (_SVG_AUTOFONT) { $data = $this->markScriptToLang($data); }
2458
2459 $this->svg_info = array();
2460 $last_gradid = ''; // mPDF 6
2461 $last_svg_fontid = ''; // mPDF 6
2462 $last_svg_fontdefw = ''; // mPDF 6
2463 $last_svg_fontstyle = ''; // mPDF 6
2464
2465 if (preg_match('/<!ENTITY/si',$data)) {
2466 // Get User-defined entities
2467 preg_match_all('/<!ENTITY\s+([a-z]+)\s+\"(.*?)\">/si',$data, $ent);
2468 // Replace entities
2469 for ($i=0; $i<count($ent[0]); $i++) {
2470 $data = preg_replace('/&'.preg_quote($ent[1][$i],'/').';/is', $ent[2][$i], $data);
2471 }
2472 }
2473
2474 if (preg_match('/xlink:href\s*=/si',$data)) {
2475 // GRADIENTS
2476 // Get links
2477 preg_match_all('/(<(linearGradient|radialgradient)[^>]*)xlink:href\s*=\s*["\']#(.*?)["\'](.*?)\/>/si',$data, $links);
2478 if (count($links[0])) { $links[5] = array(); }
2479 // Delete links from data - keeping in $links
2480 for ($i=0; $i<count($links[0]); $i++) {
2481 $links[5][$i] = 'tmpLink'.RAND(100000,9999999);
2482 $data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', '<MYLINKS'.$links[5][$i].'>' , $data);
2483 }
2484 // Get targets
2485 preg_match_all('/<(linearGradient|radialgradient)([^>]*)id\s*=\s*["\'](.*?)["\'](.*?)>(.*?)<\/(linearGradient|radialgradient)>/si',$data, $m);
2486 $targets = array();
2487 $stops = array();
2488 // keeping in $targets
2489 for ($i=0; $i<count($m[0]); $i++) {
2490 $stops[$m[3][$i]] = $m[5][$i];
2491 }
2492 // Add back links this time as targets (gradients)
2493 for ($i=0; $i<count($links[0]); $i++) {
2494 $def = $links[1][$i] .' '.$links[4][$i].'>'. $stops[$links[3][$i]].'</'.$links[2][$i] .'>' ;
2495 $data = preg_replace('/<MYLINKS'.$links[5][$i].'>/is', $def , $data);
2496 }
2497
2498 // mPDF 5.7.4
2499 // <TREF>
2500 preg_match_all('/<tref ([^>]*)xlink:href\s*=\s*["\']#([^>]*?)["\']([^>]*)\/>/si',$data, $links);
2501 for ($i=0; $i<count($links[0]); $i++) {
2502
2503 // Get the item to use from defs
2504 $insert = '';
2505 if (preg_match('/<text [^>]*id\s*=\s*["\']'.$links[2][$i].'["\'][^>]*>(.*?)<\/text>/si',$data, $m)) {
2506 $insert = $m[1];
2507 }
2508 if ($insert) {
2509 $data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', $insert, $data);
2510 }
2511 }
2512
2513 // mPDF 5.7.2
2514 // <USE>
2515 preg_match_all('/<use ([^>]*)xlink:href\s*=\s*["\']#([^>]*?)["\']([^>]*)\/>/si',$data, $links);
2516 for ($i=0; $i<count($links[0]); $i++) {
2517
2518 // Get the item to use from defs
2519 $insert = '';
2520 if (preg_match('/<([a-zA-Z]*) [^>]*id\s*=\s*["\']'.$links[2][$i].'["\'][^>]*\/>/si',$data, $m)) {
2521 $insert = $m[0];
2522 }
2523 if (!$insert && preg_match('/<([a-zA-Z]*) [^>]*id\s*=\s*["\']'.$links[2][$i].'["\']/si',$data, $m)) {
2524
2525 if (preg_match('/<'.$m[1].'[^>]*id\s*=\s*["\']'.$links[2][$i].'["\'][^>]*>.*?<\/'.$m[1].'>/si',$data, $m)) {
2526 $insert = $m[0];
2527 }
2528 }
2529
2530 if ($insert) {
2531
2532 $inners = $links[1][$i] . ' ' . $links[3][$i];
2533 // Change x,y coords to translate()
2534 if (preg_match('/y\s*=\s*["\']([^>]*?)["\']/', $inners, $m)) { $y = $m[1]; }
2535 else { $y = 0; }
2536 if (preg_match('/x\s*=\s*["\']([^>]*?)["\']/', $inners, $m)) { $x = $m[1]; }
2537 else { $x = 0; }
2538 if ($x || $y) {
2539 $inners = preg_replace('/(y|x)\s*=\s*["\']([^>]*?)["\']/', '', $inners);
2540 if (preg_match('/transform\s*=\s*["\']([^>]*?)["\']/', $inners, $m)) {
2541 if (preg_match('/translate\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/', $m[1], $mm)) {
2542 $transform = $m[1]; // transform="...."
2543 $x += $mm[1];
2544 $y += $mm[2];
2545 $transform = preg_replace('/'.preg_quote($mm[0],'/').'/', '', $transform);
2546 $transform = 'transform="'.$transform.' translate('.$x.', '.$y.')"';
2547 $inners = preg_replace('/'.preg_quote($m[0],'/').'/is', $transform, $inners);
2548 }
2549 else {
2550 $inners = preg_replace('/'.preg_quote($m[0],'/').'/is', 'transform="'.$m[1].' translate('.$x.', '.$y.')"', $inners);
2551 }
2552 }
2553 else {
2554 $inners .= ' transform="translate('.$x.', '.$y.')"';
2555 }
2556 }
2557 }
2558 $replacement = '<g '.$inners.'>'.$insert.'</g>';
2559 $data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', $replacement, $data);
2560 }
2561 preg_match_all('/<use ([^>]*)xlink:href\s*=\s*["\']#([^>]*?)["\']([^>]*)>\s*<\/use>/si',$data, $links);
2562 for ($i=0; $i<count($links[0]); $i++) {
2563
2564 // Get the item to use from defs
2565 $insert = '';
2566 if (preg_match('/<([a-zA-Z]*) [^>]*id\s*=\s*["\']'.$links[2][$i].'["\'][^>]*\/>/si',$data, $m)) {
2567 $insert = $m[0];
2568 }
2569 if (!$insert && preg_match('/<([a-zA-Z]*) [^>]*id\s*=\s*["\']'.$links[2][$i].'["\']/si',$data, $m)) {
2570
2571 if (preg_match('/<'.$m[1].'[^>]*id\s*=\s*["\']'.$links[2][$i].'["\'][^>]*>.*?<\/'.$m[1].'>/si',$data, $m)) {
2572 $insert = $m[0];
2573 }
2574 }
2575
2576 if ($insert) {
2577
2578 $inners = $links[1][$i] . ' ' . $links[3][$i];
2579 // Change x,y coords to translate()
2580 if (preg_match('/y\s*=\s*["\']([^>]*?)["\']/', $inners, $m)) { $y = $m[1]; }
2581 else { $y = 0; }
2582 if (preg_match('/x\s*=\s*["\']([^>]*?)["\']/', $inners, $m)) { $x = $m[1]; }
2583 else { $x = 0; }
2584 if ($x || $y) {
2585 $inners = preg_replace('/(y|x)\s*=\s*["\']([^>]*?)["\']/', '', $inners);
2586 if (preg_match('/transform\s*=\s*["\']([^>]*?)["\']/', $inners, $m)) {
2587 if (preg_match('/translate\(\s*([0-9\.]+)\s*,\s*([0-9\.]+)\s*\)/', $m[1], $mm)) {
2588 $transform = $m[1]; // transform="...."
2589 $x += $mm[1];
2590 $y += $mm[2];
2591 $transform = preg_replace('/'.preg_quote($mm[0],'/').'/', '', $transform);
2592 $transform = 'transform="'.$transform.' translate('.$x.', '.$y.')"';
2593 $inners = preg_replace('/'.preg_quote($m[0],'/').'/is', $transform, $inners);
2594 }
2595 else {
2596 $inners = preg_replace('/'.preg_quote($m[0],'/').'/is', 'transform="'.$m[1].' translate('.$x.', '.$y.')"', $inners);
2597 }
2598 }
2599 else {
2600 $inners .= ' transform="translate('.$x.', '.$y.')"';
2601 }
2602 }
2603 $replacement = '<g '.$inners.'>'.$insert.'</g>';
2604 $data = preg_replace('/'.preg_quote($links[0][$i],'/').'/is', $replacement, $data);
2605
2606
2607 }
2608 }
2609 }
2610
2611 // Removes <pattern>
2612 $data = preg_replace('/<pattern.*?<\/pattern>/is', '', $data);
2613 // Removes <marker>
2614 $data = preg_replace('/<marker.*?<\/marker>/is', '', $data);
2615
2616 $this->svg_info['data'] = $data;
2617
2618 $this->svg_string = '';
2619
2620 //
2621 // chargement unique des fonctions
2622 if(!function_exists("xml_svg2pdf_start")){
2623
2624 function xml_svg2pdf_start($parser, $name, $attribs){
2625 //
2626 // definition
2627 global $svg_class, $last_gradid, $last_svg_fontid, $last_svg_fontdefw, $last_svg_fontstyle; // mPDF 6
2628
2629 // mPDF 6
2630 if (strtolower($name) == 'font'){
2631 $last_svg_fontid = '';
2632 if (isset($attribs['horiz-adv-x']) && $attribs['horiz-adv-x']) {
2633 $last_svg_fontdefw = $attribs['horiz-adv-x'];
2634 }
2635 return;
2636 }
2637 // mPDF 6
2638 else if (strtolower($name) == 'font-face'){
2639 $last_svg_fontstyle = 'R';
2640 $last_svg_fontstyle .= (isset($attribs['font-weight']) && $attribs['font-weight'] == 'bold')?'B':'';
2641 $last_svg_fontstyle .= (isset($attribs['font-style']) && $attribs['font-style'] == 'italic')?'I':'';
2642 $last_svg_fontstyle .= (isset($attribs['font-variant']) && $attribs['font-variant'] == 'small-caps')?'S':'';
2643
2644 if (isset($attribs['font-family']) && $attribs['font-family']) {
2645 $tmp_svg_font = array(
2646 'units-per-em' => (isset($attribs['units-per-em']) ? $attribs['units-per-em'] : ''),
2647 'd' => '',
2648 'glyphs' => array()
2649 );
2650 $last_svg_fontid = strtolower($attribs['font-family']);
2651 if ($last_svg_fontdefw) { $tmp_svg_font['horiz-adv-x'] = $last_svg_fontdefw; }
2652 else { $tmp_svg_font['horiz-adv-x'] = 500; }
2653 $svg_class->svg_font[$last_svg_fontid][$last_svg_fontstyle] = $tmp_svg_font;
2654 }
2655 return;
2656 }
2657 // mPDF 6
2658 else if (strtolower($name) == 'missing-glyph'){
2659 if ($last_svg_fontid && isset($attribs['horiz-adv-x'])) {
2660 $svg_class->svg_font[$last_svg_fontid][$last_svg_fontstyle]['horiz-adv-x'] = (isset($attribs['horiz-adv-x']) ? $attribs['horiz-adv-x'] : '');
2661 $svg_class->svg_font[$last_svg_fontid][$last_svg_fontstyle]['d'] = (isset($attribs['d']) ? $attribs['d'] : '');
2662 }
2663 return;
2664 }
2665 // mPDF 6
2666 else if (strtolower($name) == 'glyph'){
2667 if ($last_svg_fontid && isset($attribs['unicode'])) {
2668 $svg_class->svg_font[$last_svg_fontid][$last_svg_fontstyle]['glyphs'][$attribs['unicode']] = array(
2669 'horiz-adv-x' => (isset($attribs['horiz-adv-x']) ? $attribs['horiz-adv-x'] : $last_svg_fontdefw),
2670 'd' => (isset($attribs['d']) ? $attribs['d'] : ''),
2671 );
2672 }
2673 return;
2674 }
2675 // mPDF 5.7.2
2676 else if (strtolower($name) == 'lineargradient'){
2677 $tmp_gradient = array(
2678 'type' => 'linear',
2679 'transform' => (isset($attribs['gradientTransform']) ? $attribs['gradientTransform'] : ''),
2680 'units' => (isset($attribs['gradientUnits']) ? $attribs['gradientUnits'] : ''),
2681 'spread' => (isset($attribs['spreadMethod']) ? $attribs['spreadMethod'] : ''),
2682 'color' => array()
2683 );
2684 if (isset($attribs['x1'])) $tmp_gradient['info']['x1'] = $attribs['x1'] ;
2685 if (isset($attribs['y1'])) $tmp_gradient['info']['y1'] = $attribs['y1'] ;
2686 if (isset($attribs['x2'])) $tmp_gradient['info']['x2'] = $attribs['x2'] ;
2687 if (isset($attribs['y2'])) $tmp_gradient['info']['y2'] = $attribs['y2'] ;
2688 $last_gradid = $attribs['id'];
2689 $svg_class->svgAddGradient($attribs['id'],$tmp_gradient);
2690 return;
2691 }
2692 else if (strtolower($name) == 'radialgradient'){
2693 $tmp_gradient = array(
2694 'type' => 'radial',
2695 'transform' => (isset($attribs['gradientTransform']) ? $attribs['gradientTransform'] : ''),
2696 'units' => (isset($attribs['gradientUnits']) ? $attribs['gradientUnits'] : ''),
2697 'spread' => (isset($attribs['spreadMethod']) ? $attribs['spreadMethod'] : ''),
2698 'color' => array()
2699 );
2700 if (isset($attribs['cx'])) $tmp_gradient['info']['x0'] = $attribs['cx'] ;
2701 if (isset($attribs['cy'])) $tmp_gradient['info']['y0'] = $attribs['cy'] ;
2702 if (isset($attribs['fx'])) $tmp_gradient['info']['x1'] = $attribs['fx'] ;
2703 if (isset($attribs['fy'])) $tmp_gradient['info']['y1'] = $attribs['fy'] ;
2704 if (isset($attribs['r'])) $tmp_gradient['info']['r'] = $attribs['r'] ;
2705 $last_gradid = $attribs['id'];
2706 $svg_class->svgAddGradient($attribs['id'],$tmp_gradient);
2707 return;
2708 }
2709 else if (strtolower($name) == 'stop'){
2710 if (!$last_gradid) break;
2711 $color = '#000000';
2712 if (isset($attribs['style']) AND preg_match('/stop-color:\s*([^;]*)/i',$attribs['style'],$m)) {
2713 $color = trim($m[1]);
2714 } else if (isset($attribs['stop-color']) && $attribs['stop-color']) {
2715 $color = $attribs['stop-color'];
2716 }
2717 $col = $svg_class->mpdf_ref->ConvertColor($color);
2718 if (!$col) { $col = $svg_class->mpdf_ref->ConvertColor('#000000'); } // In case "transparent" or "inherit" returned
2719 if ($col{0}==3 || $col{0}==5) { // RGB
2720 $color_final = sprintf('%.3F %.3F %.3F',ord($col{1})/255,ord($col{2})/255,ord($col{3})/255);
2721 $svg_class->svg_gradient[$last_gradid]['colorspace']='RGB';
2722 }
2723 else if ($col{0}==4 || $col{0}==6) { // CMYK
2724 $color_final = sprintf('%.3F %.3F %.3F %.3F',ord($col{1})/100,ord($col{2})/100,ord($col{3})/100,ord($col{4})/100);
2725 $svg_class->svg_gradient[$last_gradid]['colorspace']='CMYK';
2726 }
2727 else if ($col{0}==1) { // Grayscale
2728 $color_final = sprintf('%.3F',ord($col{1})/255);
2729 $svg_class->svg_gradient[$last_gradid]['colorspace']='Gray';
2730 }
2731
2732 $stop_opacity = 1;
2733 if (isset($attribs['style']) AND preg_match('/stop-opacity:\s*([0-9.]*)/i',$attribs['style'],$m)) {
2734 $stop_opacity = $m[1];
2735 } else if (isset($attribs['stop-opacity'])) {
2736 $stop_opacity = $attribs['stop-opacity'];
2737 }
2738 else if ($col{0}==5) { // RGBa
2739 $stop_opacity = ord($col{4}/100);
2740 }
2741 else if ($col{0}==6) { // CMYKa
2742 $stop_opacity = ord($col{5}/100);
2743 }
2744
2745 $tmp_color = array(
2746 'color' => $color_final,
2747 'offset' => (isset($attribs['offset']) ? $attribs['offset'] : ''),
2748 'opacity' => $stop_opacity
2749 );
2750 array_push($svg_class->svg_gradient[$last_gradid]['color'],$tmp_color);
2751 return;
2752 }
2753 if ($svg_class->inDefs) { return; }
2754
2755 $svg_class->xbase = 0;
2756 $svg_class->ybase = 0;
2757 switch (strtolower($name)){
2758
2759 // Don't output stuff inside <defs>
2760 case 'defs':
2761 $svg_class->inDefs = true;
2762 return;
2763
2764 case 'svg':
2765 $svg_class->svgOffset($attribs);
2766 break;
2767
2768 case 'path':
2769 $path = $attribs['d'];
2770 preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $path, $commands, PREG_SET_ORDER);
2771 $path_cmd = '';
2772 $svg_class->subPathInit = true;
2773 $svg_class->pathBBox = array(999999,999999,-999999,-999999);
2774 foreach($commands as $c){
2775 if((isset($c) && count($c)==3) || (isset($c[2]) && $c[2]=='')){
2776 list($tmp, $command, $arguments) = $c;
2777 }
2778 else{
2779 list($tmp, $command) = $c;
2780 $arguments = '';
2781 }
2782
2783 $path_cmd .= $svg_class->svgPath($command, $arguments);
2784 }
2785 if ($svg_class->pathBBox[2]==-1999998) { $svg_class->pathBBox[2] = 100; }
2786 if ($svg_class->pathBBox[3]==-1999998) { $svg_class->pathBBox[3] = 100; }
2787 if ($svg_class->pathBBox[0]==999999) { $svg_class->pathBBox[0] = 0; }
2788 if ($svg_class->pathBBox[1]==999999) { $svg_class->pathBBox[1] = 0; }
2789 $critere_style = $attribs;
2790 unset($critere_style['d']);
2791 $path_style = $svg_class->svgDefineStyle($critere_style);
2792 break;
2793
2794 case 'rect':
2795 if (!isset($attribs['x'])) {$attribs['x'] = 0;}
2796 if (!isset($attribs['y'])) {$attribs['y'] = 0;}
2797 if (!isset($attribs['rx'])) {$attribs['rx'] = 0;}
2798 if (!isset($attribs['ry'])) {$attribs['ry'] = 0;}
2799 $arguments = array();
2800 if (isset($attribs['x'])) $arguments['x'] = $attribs['x'];
2801 if (isset($attribs['y'])) $arguments['y'] = $attribs['y'];
2802 if (isset($attribs['width'])) $arguments['w'] = $attribs['width'];
2803 if (isset($attribs['height'])) $arguments['h'] = $attribs['height'];
2804 if (isset($attribs['rx'])) $arguments['rx'] = $attribs['rx'];
2805 if (isset($attribs['ry'])) $arguments['ry'] = $attribs['ry'];
2806 $path_cmd = $svg_class->svgRect($arguments);
2807 $critere_style = $attribs;
2808 unset($critere_style['x'],$critere_style['y'],$critere_style['rx'],$critere_style['ry'],$critere_style['height'],$critere_style['width']);
2809 $path_style = $svg_class->svgDefineStyle($critere_style);
2810 break;
2811
2812 case 'circle':
2813 if (!isset($attribs['cx'])) {$attribs['cx'] = 0;}
2814 if (!isset($attribs['cy'])) {$attribs['cy'] = 0;}
2815 $arguments = array();
2816 if (isset($attribs['cx'])) $arguments['cx'] = $attribs['cx'];
2817 if (isset($attribs['cy'])) $arguments['cy'] = $attribs['cy'];
2818 if (isset($attribs['r'])) $arguments['rx'] = $attribs['r'];
2819 if (isset($attribs['r'])) $arguments['ry'] = $attribs['r'];
2820 $path_cmd = $svg_class->svgEllipse($arguments);
2821 $critere_style = $attribs;
2822 unset($critere_style['cx'],$critere_style['cy'],$critere_style['r']);
2823 $path_style = $svg_class->svgDefineStyle($critere_style);
2824 break;
2825
2826 case 'ellipse':
2827 if (!isset($attribs['cx'])) {$attribs['cx'] = 0;}
2828 if (!isset($attribs['cy'])) {$attribs['cy'] = 0;}
2829 $arguments = array();
2830 if (isset($attribs['cx'])) $arguments['cx'] = $attribs['cx'];
2831 if (isset($attribs['cy'])) $arguments['cy'] = $attribs['cy'];
2832 if (isset($attribs['rx'])) $arguments['rx'] = $attribs['rx'];
2833 if (isset($attribs['ry'])) $arguments['ry'] = $attribs['ry'];
2834 $path_cmd = $svg_class->svgEllipse($arguments);
2835 $critere_style = $attribs;
2836 unset($critere_style['cx'],$critere_style['cy'],$critere_style['rx'],$critere_style['ry']);
2837 $path_style = $svg_class->svgDefineStyle($critere_style);
2838 break;
2839
2840 case 'line':
2841 $arguments = array();
2842 $arguments[0] = (isset($attribs['x1']) ? $attribs['x1'] : '');
2843 $arguments[1] = (isset($attribs['y1']) ? $attribs['y1'] : '');
2844 $arguments[2] = (isset($attribs['x2']) ? $attribs['x2'] : '');
2845 $arguments[3] = (isset($attribs['y2']) ? $attribs['y2'] : '');
2846 $path_cmd = $svg_class->svgPolyline($arguments,false);
2847 $critere_style = $attribs;
2848 unset($critere_style['x1'],$critere_style['y1'],$critere_style['x2'],$critere_style['y2']);
2849 $path_style = $svg_class->svgDefineStyle($critere_style);
2850 break;
2851
2852 case 'polyline':
2853 $path = $attribs['points'];
2854 preg_match_all('/[0-9\-\.]*/',$path, $tmp, PREG_SET_ORDER);
2855 $arguments = array();
2856 for ($i=0;$i<count($tmp);$i++){
2857 if ($tmp[$i][0] !=''){
2858 array_push($arguments, $tmp[$i][0]);
2859 }
2860 }
2861 $path_cmd = $svg_class->svgPolyline($arguments);
2862 $critere_style = $attribs;
2863 unset($critere_style['points']);
2864 $path_style = $svg_class->svgDefineStyle($critere_style);
2865 break;
2866
2867 case 'polygon':
2868 $path = $attribs['points'];
2869 preg_match_all('/([\-]*[0-9\.]+)/',$path, $tmp);
2870 $arguments = array();
2871 for ($i=0;$i<count($tmp[0]);$i++){
2872 if ($tmp[0][$i] !=''){
2873 array_push($arguments, $tmp[0][$i]);
2874 }
2875 }
2876 $path_cmd = $svg_class->svgPolygon($arguments);
2877 // definition du style de la forme:
2878 $critere_style = $attribs;
2879 unset($critere_style['points']);
2880 $path_style = $svg_class->svgDefineStyle($critere_style);
2881 break;
2882
2883 // mPDF 5.7.4 Embedded image
2884 case 'image':
2885 if (isset($attribs['xlink:href']) && $attribs['xlink:href']) {
2886 $svg_class->svgImage($attribs);
2887 }
2888 break;
2889
2890
2891 case 'a':
2892 if (isset($attribs['xlink:href'])) {
2893 unset($attribs['xlink:href']); // this should be a hyperlink
2894 // not handled like a xlink:href in other elements
2895 } // then continue like a <g>
2896 case 'g':
2897 $array_style = $svg_class->svgDefineStyle($attribs);
2898 if (isset($array_style['transformations']) && $array_style['transformations']) {
2899 // If in the middle of <text> element, add to textoutput, else WriteString
2900 if ($svg_class->intext) { $svg_class->textoutput .= ' q '.$array_style['transformations']; } // mPDF 5.7.4
2901 else { $svg_class->svgWriteString(' q '.$array_style['transformations']); }
2902 }
2903 array_push($svg_class->svg_style,$array_style);
2904
2905 $svg_class->svgDefineTxtStyle($attribs);
2906
2907 break;
2908
2909 case 'text':
2910 $svg_class->textlength = 0; // mPDF 5.7.4
2911 $svg_class->texttotallength = 0; // mPDF 5.7.4
2912 $svg_class->textoutput = ''; // mPDF 5.7.4
2913 $svg_class->textanchor = 'start'; // mPDF 5.7.4
2914 $svg_class->textXorigin = 0; // mPDF 5.7.4
2915 $svg_class->textYorigin = 0; // mPDF 5.7.4
2916
2917 $svg_class->intext = true; // mPDF 5.7.4
2918
2919 $styl = '';
2920 if (_SVG_CLASSES && isset($attribs['class']) && $attribs['class']) {
2921 $classes = preg_split('/\s+/',trim($attribs['class']));
2922 foreach($classes AS $class) {
2923 if (isset($svg_class->mpdf_ref->cssmgr->CSS['CLASS>>'.strtoupper($class)])) {
2924 $c = $svg_class->mpdf_ref->cssmgr->CSS['CLASS>>'.strtoupper($class)];
2925 foreach($c AS $prop=>$val) {
2926 $styl .= strtolower($prop).':'.$val.';';
2927 }
2928 }
2929 }
2930 }
2931
2932 if (_SVG_AUTOFONT && isset($attribs['lang']) && $attribs['lang']) {
2933 if (!$svg_class->mpdf_ref->usingCoreFont) {
2934 if ($attribs['lang'] != $svg_class->mpdf_ref->default_lang) {
2935 list ($coreSuitable,$mpdf_unifont) = GetLangOpts($attribs['lang'], $svg_class->mpdf_ref->useAdobeCJK, $svg_class->mpdf_ref->fontdata);
2936 if ($mpdf_unifont) { $styl .= 'font-family:'.$mpdf_unifont.';'; }
2937 }
2938 }
2939 }
2940
2941 if ($styl) {
2942 if (isset($attribs['style'])) { $attribs['style'] = $styl . $attribs['style']; }
2943 else { $attribs['style'] = $styl; }
2944 }
2945
2946 $array_style = $svg_class->svgDefineStyle($attribs);
2947 if ($array_style['transformations']) {
2948 $svg_class->textoutput .= ' q '.$array_style['transformations']; // mPDF 5.7.4
2949 }
2950 array_push($svg_class->svg_style,$array_style);
2951
2952 $svg_class->txt_data = array();
2953 $x = isset($attribs['x']) ? $svg_class->ConvertSVGSizePixels($attribs['x'],'x') : 0; // mPDF 5.7.4
2954 $y = isset($attribs['y']) ? $svg_class->ConvertSVGSizePixels($attribs['y'],'y') : 0; // mPDF 5.7.4
2955 $x += isset($attribs['dx']) ? $svg_class->ConvertSVGSizePixels($attribs['dx'],'x') : 0; // mPDF 5.7.4
2956 $y += isset($attribs['dy']) ? $svg_class->ConvertSVGSizePixels($attribs['dy'],'y') : 0; // mPDF 5.7.4
2957
2958 $svg_class->txt_data[0] = $x; // mPDF 5.7.4
2959 $svg_class->txt_data[1] = $y; // mPDF 5.7.4
2960 $critere_style = $attribs;
2961 unset($critere_style['x'], $critere_style['y']);
2962 $svg_class->svgDefineTxtStyle($critere_style);
2963
2964 $svg_class->textanchor = $svg_class->txt_style[count($svg_class->txt_style)-1]['text-anchor']; // mPDF 5.7.4
2965 $svg_class->textXorigin = $svg_class->txt_data[0]; // mPDF 5.7.4
2966 $svg_class->textYorigin = $svg_class->txt_data[1]; // mPDF 5.7.4
2967 $svg_class->textjuststarted = true; // mPDF 5.7.4
2968
2969 break;
2970
2971 // mPDF 5.7.4
2972 case 'tspan':
2973
2974 // OUTPUT CHUNK(s) UP To NOW (svgText updates $svg_class->textlength)
2975 $p_cmd = $svg_class->svgText();
2976 $svg_class->textoutput .= $p_cmd;
2977 $tmp = count($svg_class->svg_style)-1;
2978 $current_style = $svg_class->svg_style[$tmp];
2979
2980 $styl = '';
2981 if (_SVG_CLASSES && isset($attribs['class']) && $attribs['class']) {
2982 $classes = preg_split('/\s+/',trim($attribs['class']));
2983 foreach($classes AS $class) {
2984 if (isset($svg_class->mpdf_ref->cssmgr->CSS['CLASS>>'.strtoupper($class)])) {
2985 $c = $svg_class->mpdf_ref->cssmgr->CSS['CLASS>>'.strtoupper($class)];
2986 foreach($c AS $prop=>$val) {
2987 $styl .= strtolower($prop).':'.$val.';';
2988 }
2989 }
2990 }
2991 }
2992
2993 if (_SVG_AUTOFONT && isset($attribs['lang']) && $attribs['lang']) {
2994 if (!$svg_class->mpdf_ref->usingCoreFont) {
2995 if ($attribs['lang'] != $svg_class->mpdf_ref->default_lang) {
2996 list ($coreSuitable,$mpdf_unifont) = GetLangOpts($attribs['lang'], $svg_class->mpdf_ref->useAdobeCJK, $svg_class->mpdf_ref->fontdata);
2997 if ($mpdf_unifont) { $styl .= 'font-family:'.$mpdf_unifont.';'; }
2998 }
2999 }
3000 }
3001
3002 if ($styl) {
3003 if (isset($attribs['style'])) { $attribs['style'] = $styl . $attribs['style']; }
3004 else { $attribs['style'] = $styl; }
3005 }
3006
3007 $array_style = $svg_class->svgDefineStyle($attribs);
3008
3009 $svg_class->txt_data = array();
3010
3011
3012 // If absolute position adjustment (x or y), creates new block of text for text-alignment
3013 if (isset($attribs['x']) || isset($attribs['y'])) {
3014 // If text-anchor middle|end, adjust
3015 if ($svg_class->textanchor == 'end') { $tx = -$svg_class->texttotallength; }
3016 else if ($svg_class->textanchor == 'middle') { $tx = -$svg_class->texttotallength/2; }
3017 else { $tx = 0; }
3018 while(preg_match('/mPDF-AXS\((.*?)\)/',$svg_class->textoutput,$m)) {
3019 if ($tx) {
3020 $txk = $m[1] + ($tx*$svg_class->kp);
3021 $svg_class->textoutput = preg_replace('/mPDF-AXS\((.*?)\)/', sprintf('%.4F', $txk) ,$svg_class->textoutput,1);
3022 }
3023 else {
3024 $svg_class->textoutput = preg_replace('/mPDF-AXS\((.*?)\)/','\\1',$svg_class->textoutput,1);
3025 }
3026 }
3027
3028 $svg_class->svgWriteString($svg_class->textoutput);
3029
3030 $svg_class->textXorigin += $svg_class->textlength;
3031 $currentX = $svg_class->textXorigin;
3032 $currentY = $svg_class->textYorigin;
3033 $svg_class->textlength = 0;
3034 $svg_class->texttotallength = 0;
3035 $svg_class->textoutput = '';
3036
3037 $x = isset($attribs['x']) ? $svg_class->ConvertSVGSizePixels($attribs['x'],'x') : $currentX;
3038 $y = isset($attribs['y']) ? $svg_class->ConvertSVGSizePixels($attribs['y'],'y') : $currentY;
3039
3040 $svg_class->txt_data[0] = $x;
3041 $svg_class->txt_data[1] = $y;
3042 $critere_style = $attribs;
3043 unset($critere_style['x'], $critere_style['y']);
3044 $svg_class->svgDefineTxtStyle($critere_style);
3045
3046 $svg_class->textanchor = $svg_class->txt_style[count($svg_class->txt_style)-1]['text-anchor'];
3047 $svg_class->textXorigin = $x;
3048 $svg_class->textYorigin = $y;
3049
3050 }
3051 else {
3052
3053 $svg_class->textXorigin += $svg_class->textlength;
3054 $currentX = $svg_class->textXorigin;
3055 $currentY = $svg_class->textYorigin;
3056
3057 $currentX += isset($attribs['dx']) ? $svg_class->ConvertSVGSizePixels($attribs['dx'],'x') : 0;
3058 $currentY += isset($attribs['dy']) ? $svg_class->ConvertSVGSizePixels($attribs['dy'],'y') : 0;
3059
3060 $svg_class->txt_data[0] = $currentX;
3061 $svg_class->txt_data[1] = $currentY;
3062 $critere_style = $attribs;
3063 unset($critere_style['x'], $critere_style['y']);
3064 $svg_class->svgDefineTxtStyle($critere_style);
3065 $svg_class->textXorigin = $currentX;
3066 $svg_class->textYorigin = $currentY;
3067
3068 }
3069
3070 if ($array_style['transformations']) {
3071 $svg_class->textoutput .= ' q '.$array_style['transformations'];
3072 }
3073 array_push($svg_class->svg_style,$array_style);
3074
3075 break;
3076 }
3077
3078 //
3079 //insertion des path et du style dans le flux de donn� general.
3080 if (isset($path_cmd) && $path_cmd) {
3081 // mPDF 5.0
3082 list($prestyle,$poststyle) = $svg_class->svgStyle($path_style, $attribs, strtolower($name));
3083 if (isset($path_style['transformations']) && $path_style['transformations']) { // transformation on an element
3084 $svg_class->svgWriteString(" q ".$path_style['transformations']. $prestyle . $path_cmd . $poststyle . " Q\n");
3085 }
3086 else {
3087 $svg_class->svgWriteString(" q ".$prestyle . $path_cmd . $poststyle ." Q\n"); // mPDF 5.7.4
3088 }
3089 }
3090 }
3091
3092 function characterData($parser, $data)
3093 {
3094 global $svg_class;
3095 if ($svg_class->inDefs) { return; } // mPDF 5.7.2
3096 if(isset($svg_class->txt_data[2])) {
3097 $svg_class->txt_data[2] .= $data;
3098 }
3099 else {
3100 $svg_class->txt_data[2] = $data;
3101 $svg_class->txt_data[0] = $svg_class->textXorigin ;
3102 $svg_class->txt_data[1] = $svg_class->textYorigin ; }
3103 }
3104
3105
3106 function xml_svg2pdf_end($parser, $name){
3107 global $svg_class;
3108 // mPDF 5.7.2
3109 // Don't output stuff inside <defs>
3110 if ($name == 'defs') {
3111 $svg_class->inDefs = false;
3112 return;
3113 }
3114 if ($svg_class->inDefs) { return; }
3115 switch($name){
3116
3117 case "g":
3118 case "a":
3119 if ($svg_class->intext) {
3120 $p_cmd = $svg_class->svgText();
3121 $svg_class->textoutput .= $p_cmd;
3122 }
3123
3124 $tmp = count($svg_class->svg_style)-1;
3125 $current_style = $svg_class->svg_style[$tmp];
3126 if ($current_style['transformations']) {
3127 // If in the middle of <text> element, add to textoutput, else WriteString
3128 if ($svg_class->intext) { $svg_class->textoutput .= " Q\n"; } // mPDF 5.7.4
3129 else { $svg_class->svgWriteString(" Q\n"); }
3130 }
3131 array_pop($svg_class->svg_style);
3132 array_pop($svg_class->txt_style);
3133 if ($svg_class->intext) {
3134 $svg_class->textXorigin += $svg_class->textlength;
3135 $svg_class->textlength = 0;
3136 }
3137
3138 break;
3139 case 'font':
3140 $last_svg_fontdefw = '';
3141 break;
3142 case 'font-face':
3143 $last_svg_fontid = '';
3144 $last_svg_fontstyle = '';
3145 break;
3146 case 'radialgradient':
3147 case 'lineargradient':
3148 $last_gradid = '';
3149 break;
3150 case "text":
3151 $svg_class->txt_data[2] = rtrim($svg_class->txt_data[2]); // mPDF 5.7.4
3152 $path_cmd = $svg_class->svgText();
3153 $svg_class->textoutput .= $path_cmd; // mPDF 5.7.4
3154 $tmp = count($svg_class->svg_style)-1;
3155 $current_style = $svg_class->svg_style[$tmp];
3156 if ($current_style['transformations']) {
3157 $svg_class->textoutput .= " Q\n"; // mPDF 5.7.4
3158 }
3159 array_pop($svg_class->svg_style);
3160 array_pop($svg_class->txt_style); // mPDF 5.7.4
3161
3162 // mPDF 5.7.4
3163 // If text-anchor middle|end, adjust
3164 if ($svg_class->textanchor == 'end') { $tx = -$svg_class->texttotallength; }
3165 else if ($svg_class->textanchor == 'middle') { $tx = -$svg_class->texttotallength/2; }
3166 else { $tx = 0; }
3167 while(preg_match('/mPDF-AXS\((.*?)\)/',$svg_class->textoutput,$m)) {
3168 if ($tx) {
3169 $txk = $m[1] + ($tx*$svg_class->kp);
3170 $svg_class->textoutput = preg_replace('/mPDF-AXS\((.*?)\)/', sprintf('%.4F', $txk) ,$svg_class->textoutput,1);
3171 }
3172 else {
3173 $svg_class->textoutput = preg_replace('/mPDF-AXS\((.*?)\)/','\\1',$svg_class->textoutput,1);
3174 }
3175 }
3176
3177 $svg_class->svgWriteString($svg_class->textoutput);
3178 $svg_class->textlength = 0;
3179 $svg_class->texttotallength = 0;
3180 $svg_class->textoutput = '';
3181 $svg_class->intext = false; // mPDF 5.7.4
3182
3183 break;
3184 // mPDF 5.7.4
3185 case "tspan":
3186 $p_cmd = $svg_class->svgText();
3187 $svg_class->textoutput .= $p_cmd;
3188 $tmp = count($svg_class->svg_style)-1;
3189 $current_style = $svg_class->svg_style[$tmp];
3190 if ($current_style['transformations']) {
3191 $svg_class->textoutput .= " Q\n";
3192 }
3193 array_pop($svg_class->svg_style);
3194 array_pop($svg_class->txt_style);
3195
3196 $svg_class->textXorigin += $svg_class->textlength;
3197 $svg_class->textlength = 0;
3198
3199 break;
3200 }
3201
3202 }
3203
3204 }
3205
3206 $svg2pdf_xml='';
3207 global $svg_class;
3208 $svg_class = $this;
3209 // Don't output stuff inside <defs>
3210 $svg_class->inDefs = false;
3211 $svg2pdf_xml_parser = xml_parser_create("utf-8");
3212 xml_parser_set_option($svg2pdf_xml_parser, XML_OPTION_CASE_FOLDING, false);
3213 xml_set_element_handler($svg2pdf_xml_parser, "xml_svg2pdf_start", "xml_svg2pdf_end");
3214 xml_set_character_data_handler($svg2pdf_xml_parser, "characterData");
3215 xml_parse($svg2pdf_xml_parser, $data);
3216 if ($this->svg_error) { return false; }
3217 else {
3218 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);
3219 }
3220
3221 }
3222
3223
3224
3225 // AUTOFONT =========================
3226 function markScriptToLang($html) {
3227 if ($this->mpdf_ref->onlyCoreFonts) { return $html; }
3228 if (empty($this->script2lang)) {
3229 if (!empty($this->mpdf_ref->script2lang)) {
3230 $this->script2lang = $this->mpdf_ref->script2lang;
3231 $this->viet = $this->mpdf_ref->viet;
3232 $this->pashto = $this->mpdf_ref->pashto;
3233 $this->urdu = $this->mpdf_ref->urdu;
3234 $this->persian = $this->mpdf_ref->persian;
3235 $this->sindhi = $this->mpdf_ref->sindhi;
3236 }
3237 else {
3238 include(_MPDF_PATH.'config_script2lang.php');
3239 }
3240 }
3241
3242 $n = '';
3243 $a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
3244 foreach($a as $i => $e) {
3245 if($i%2==0) {
3246 $e = strcode2utf($e);
3247 $e = $this->mpdf_ref->lesser_entity_decode($e);
3248
3249 $earr = $this->mpdf_ref->UTF8StringToArray($e, false);
3250
3251 $scriptblock = 0;
3252 $scriptblocks = array();
3253 $scriptblocks[0] = 0;
3254 $chardata = array();
3255 $subchunk = 0;
3256 $charctr = 0;
3257 foreach($earr as $char) {
3258 $ucd_record = UCDN::get_ucd_record($char);
3259 $sbl = $ucd_record[6];
3260
3261 if ($sbl && $sbl != 40 && $sbl != 102) {
3262 if ($scriptblock == 0) { $scriptblock = $sbl; $scriptblocks[$subchunk] = $scriptblock; }
3263 else if ($scriptblock > 0 && $scriptblock != $sbl) {
3264 // NEW (non-common) Script encountered in this chunk.
3265 // Start a new subchunk
3266 $subchunk++;
3267 $scriptblock = $sbl;
3268 $charctr = 0;
3269 $scriptblocks[$subchunk] = $scriptblock;
3270 }
3271 }
3272
3273 $chardata[$subchunk][$charctr]['script'] = $sbl;
3274 $chardata[$subchunk][$charctr]['uni'] = $char;
3275 $charctr++;
3276 }
3277
3278 // If scriptblock[x] = common & non-baseScript
3279 // and scriptblock[x+1] = baseScript
3280 // Move common script from end of x to start of x+1
3281 for($sch=0;$sch<$subchunk;$sch++) {
3282 if ($scriptblocks[$sch] > 0 && $scriptblocks[$sch] != $this->mpdf_ref->baseScript && $scriptblocks[$sch+1] == $this->mpdf_ref->baseScript) {
3283 $end = count($chardata[$sch])-1;
3284 while($chardata[$sch][$end]['script'] == 0 && $end > 1) { // common script
3285 $tmp = array_pop($chardata[$sch]);
3286 array_unshift($chardata[$sch+1],$tmp);
3287 $end--;
3288 }
3289 }
3290 }
3291
3292 $o = '';
3293 for($sch=0;$sch<=$subchunk;$sch++) {
3294 if (isset($chardata[$sch])) {
3295 $s = '';
3296 for ($j=0;$j<count($chardata[$sch]);$j++) {
3297 $s.=code2utf($chardata[$sch][$j]['uni']);
3298 }
3299 // ZZZ99 Undo lesser_entity_decode as above - but only for <>&
3300 $s = str_replace("&","&amp;",$s);
3301 $s = str_replace("<","&lt;",$s);
3302 $s = str_replace(">","&gt;",$s);
3303
3304 if (substr($a[$i-1],0,5)!='<text' && substr($a[$i-1],0,5)!='<tspa') { continue; } // <tspan> or <text> only
3305
3306 $lang = '';
3307 // Check Vietnamese if Latin script - even if Basescript
3308 if ($scriptblocks[$sch] == UCDN::SCRIPT_LATIN && $this->mpdf_ref->autoVietnamese && preg_match("/([".$this->viet."])/u", $s)) {
3309 $lang="vi";
3310 }
3311 // Check Arabic for different languages if Arabic script - even if Basescript
3312 else if ($scriptblocks[$sch] == UCDN::SCRIPT_ARABIC && $this->mpdf_ref->autoArabic) {
3313 if (preg_match("/[".$this->sindhi ."]/u", $s) ) {
3314 $lang="sd";
3315 }
3316 else if (preg_match("/[".$this->urdu ."]/u", $s) ) {
3317 $lang="ur";
3318 }
3319 else if (preg_match("/[".$this->pashto ."]/u", $s) ) {
3320 $lang="ps";
3321 }
3322 else if (preg_match("/[".$this->persian ."]/u", $s) ) {
3323 $lang="fa";
3324 }
3325 else if ($this->mpdf_ref->baseScript != UCDN::SCRIPT_ARABIC && isset($this->script2lang[$scriptblocks[$sch]])) {
3326 $lang="'.$this->script2lang[$scriptblocks[$sch]].'";
3327 }
3328 }
3329 // Identify Script block if not Basescript, and mark up as language
3330 else if ($scriptblocks[$sch] > 0 && $scriptblocks[$sch] != $this->mpdf_ref->baseScript && isset($this->script2lang[$scriptblocks[$sch]])) {
3331 $lang=$this->script2lang[$scriptblocks[$sch]];
3332 }
3333 if ($lang) {
3334 $o .= '<tspan lang="'.$lang.'">'.$s.'</tspan>';
3335 }
3336 else { $o .= $s; }
3337
3338 }
3339 }
3340
3341 $a[$i] = $o;
3342 }
3343 else {
3344 $a[$i] = '<'.$e.'>';
3345 }
3346 }
3347 $n = implode('',$a);
3348 return $n;
3349 }
3350
3351
3352 }
3353
3354 // END OF CLASS
3355 // END OF CLASS
3356 // END OF CLASS
3357
3358
3359 function calc_bezier_bbox($start, $c) {
3360 $P0 = array($start[0],$start[1]);
3361 $P1 = array($c[0],$c[1]);
3362 $P2 = array($c[2],$c[3]);
3363 $P3 = array($c[4],$c[5]);
3364 $bounds = array();
3365 $bounds[0][] = $P0[0];
3366 $bounds[1][] = $P0[1];
3367 $bounds[0][] = $P3[0];
3368 $bounds[1][] = $P3[1];
3369 for ($i=0;$i<=1;$i++) {
3370 $b = 6 * $P0[$i] - 12 * $P1[$i] + 6 * $P2[$i];
3371 $a = -3 * $P0[$i] + 9 * $P1[$i] - 9 * $P2[$i] + 3 * $P3[$i];
3372 $c = 3 * $P1[$i] - 3 * $P0[$i];
3373 if ($a == 0) {
3374 if ($b == 0) { continue; }
3375 $t = -$c / $b;
3376 if ($t>0 && $t<1) {
3377 $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]);
3378 }
3379 continue;
3380 }
3381 $b2ac = pow($b, 2) - 4 * $c * $a;
3382 if ($b2ac < 0) { continue; }
3383 $t1 = (-$b + sqrt($b2ac))/(2 * $a);
3384 if ($t1>0 && $t1<1) {
3385 $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]);
3386 }
3387 $t2 = (-$b - sqrt($b2ac))/(2 * $a);
3388 if ($t2>0 && $t2<1) {
3389 $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]);
3390 }
3391 }
3392 $x = min($bounds[0]);
3393 $x2 = max($bounds[0]);
3394 $y = min($bounds[1]);
3395 $y2 = max($bounds[1]);
3396 return array($x, $y, $x2, $y2);
3397 }
3398
3399 function _testIntersectCircle($cx, $cy, $cr) {
3400 // Tests whether a circle fully encloses a rectangle 0,0,1,1
3401 // to see if any further radial gradients need adding (SVG)
3402 // If centre of circle is inside 0,0,1,1 square
3403 if ($cx >= 0 && $cx <= 1 && $cy >= 0 && $cy <= 1) {
3404 $maxd = 1.5;
3405 }
3406 // distance to four corners
3407 else {
3408 $d1 = sqrt(pow(($cy-0),2) + pow(($cx-0),2));
3409 $d2 = sqrt(pow(($cy-1),2) + pow(($cx-0),2));
3410 $d3 = sqrt(pow(($cy-0),2) + pow(($cx-1),2));
3411 $d4 = sqrt(pow(($cy-1),2) + pow(($cx-1),2));
3412 $maxd = max($d1,$d2,$d3,$d4);
3413 }
3414 if ($cr < $maxd) { return true; }
3415 else { return false; }
3416 }
3417
3418 function _testIntersect($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4) {
3419 // Tests whether line (x1, y1) and (x2, y2) [a gradient axis (perpendicular)]
3420 // intersects with a specific line segment (x3, y3) and (x4, y4)
3421 $a1 = $y2-$y1;
3422 $b1 = $x1-$x2;
3423 $c1 = $a1*$x1+$b1*$y1;
3424 $a2 = $y4-$y3;
3425 $b2 = $x3-$x4;
3426 $c2 = $a2*$x3+$b2*$y3;
3427 $det = $a1*$b2 - $a2*$b1;
3428 if($det == 0){ //Lines are parallel
3429 return false;
3430 }
3431 else{
3432 $x = ($b2*$c1 - $b1*$c2)/$det;
3433 $y = ($a1*$c2 - $a2*$c1)/$det;
3434 if ($x >= $x3 && $x <= $x4 && $y >= $y3 && $y <= $y4) { return true; }
3435 }
3436 return false;
3437 }
3438
3439
3440
3441 ?>