PluginProbe
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin / 2.4.5
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin v2.4.5
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 / grad.php

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

976 lines 34.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class grad
4 {
5
6 var $mpdf = null;
7
8 public function __construct(mPDF $mpdf)
9 {
10 $this->mpdf = $mpdf;
11 }
12
13 // mPDF 5.3.A1
14 function CoonsPatchMesh($x, $y, $w, $h, $patch_array = array(), $x_min = 0, $x_max = 1, $y_min = 0, $y_max = 1, $colspace = 'RGB', $return = false)
15 {
16 $s = ' q ';
17 $s.=sprintf(' %.3F %.3F %.3F %.3F re W n ', $x * _MPDFK, ($this->mpdf->h - $y) * _MPDFK, $w * _MPDFK, -$h * _MPDFK);
18 $s.=sprintf(' %.3F 0 0 %.3F %.3F %.3F cm ', $w * _MPDFK, $h * _MPDFK, $x * _MPDFK, ($this->mpdf->h - ($y + $h)) * _MPDFK);
19 $n = count($this->mpdf->gradients) + 1;
20 $this->mpdf->gradients[$n]['type'] = 6; //coons patch mesh
21 $this->mpdf->gradients[$n]['colorspace'] = $colspace; //coons patch mesh
22 $bpcd = 65535; //16 BitsPerCoordinate
23 $trans = false;
24 $this->mpdf->gradients[$n]['stream'] = '';
25 for ($i = 0; $i < count($patch_array); $i++) {
26 $this->mpdf->gradients[$n]['stream'].=chr($patch_array[$i]['f']); //start with the edge flag as 8 bit
27 for ($j = 0; $j < count($patch_array[$i]['points']); $j++) {
28 //each point as 16 bit
29 if (($j % 2) == 1) { // Y coordinate (adjusted as input is From top left)
30 $patch_array[$i]['points'][$j] = (($patch_array[$i]['points'][$j] - $y_min) / ($y_max - $y_min)) * $bpcd;
31 $patch_array[$i]['points'][$j] = $bpcd - $patch_array[$i]['points'][$j];
32 } else {
33 $patch_array[$i]['points'][$j] = (($patch_array[$i]['points'][$j] - $x_min) / ($x_max - $x_min)) * $bpcd;
34 }
35 if ($patch_array[$i]['points'][$j] < 0)
36 $patch_array[$i]['points'][$j] = 0;
37 if ($patch_array[$i]['points'][$j] > $bpcd)
38 $patch_array[$i]['points'][$j] = $bpcd;
39 $this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j] / 256));
40 $this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j] % 256));
41 }
42 for ($j = 0; $j < count($patch_array[$i]['colors']); $j++) {
43 //each color component as 8 bit
44 if ($colspace == 'RGB') {
45 $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][1]);
46 $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][2]);
47 $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][3]);
48 if (isset($patch_array[$i]['colors'][$j][4]) && ord($patch_array[$i]['colors'][$j][4]) < 100) {
49 $trans = true;
50 }
51 } else if ($colspace == 'CMYK') {
52 $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][1]) * 2.55);
53 $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][2]) * 2.55);
54 $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][3]) * 2.55);
55 $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][4]) * 2.55);
56 if (isset($patch_array[$i]['colors'][$j][5]) && ord($patch_array[$i]['colors'][$j][5]) < 100) {
57 $trans = true;
58 }
59 } else if ($colspace == 'Gray') {
60 $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][1]);
61 if ($patch_array[$i]['colors'][$j][2] == 1) {
62 $trans = true;
63 } // transparency converted from rgba or cmyka()
64 }
65 }
66 }
67 // TRANSPARENCY
68 if ($trans) {
69 $this->mpdf->gradients[$n]['stream_trans'] = '';
70 for ($i = 0; $i < count($patch_array); $i++) {
71 $this->mpdf->gradients[$n]['stream_trans'].=chr($patch_array[$i]['f']);
72 for ($j = 0; $j < count($patch_array[$i]['points']); $j++) {
73 //each point as 16 bit
74 $this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j] / 256));
75 $this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j] % 256));
76 }
77 for ($j = 0; $j < count($patch_array[$i]['colors']); $j++) {
78 //each color component as 8 bit // OPACITY
79 if ($colspace == 'RGB') {
80 $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][4]) * 2.55));
81 } else if ($colspace == 'CMYK') {
82 $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][5]) * 2.55));
83 } else if ($colspace == 'Gray') {
84 $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][3]) * 2.55));
85 }
86 }
87 }
88 $this->mpdf->gradients[$n]['trans'] = true;
89 $s .= ' /TGS' . $n . ' gs ';
90 }
91 //paint the gradient
92 $s .= '/Sh' . $n . ' sh' . "\n";
93 //restore previous Graphic State
94 $s .= 'Q' . "\n";
95 if ($return) {
96 return $s;
97 } else {
98 $this->mpdf->_out($s);
99 }
100 }
101
102 // type = linear:2; radial: 3;
103 // Linear: $coords - array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg).
104 // The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
105 // Radial: $coords - array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1,
106 // (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg).
107 // (fx, fy) should be inside the circle, otherwise some areas will not be defined
108 // $col = array(R,G,B/255); or array(G/255); or array(C,M,Y,K/100)
109 // $stops = array('col'=>$col [, 'opacity'=>0-1] [, 'offset'=>0-1])
110 function Gradient($x, $y, $w, $h, $type, $stops = array(), $colorspace = 'RGB', $coords = '', $extend = '', $return = false, $is_mask = false)
111 {
112 if (strtoupper(substr($type, 0, 1)) == 'L') {
113 $type = 2;
114 } // linear
115 else if (strtoupper(substr($type, 0, 1)) == 'R') {
116 $type = 3;
117 } // radial
118 if ($colorspace != 'CMYK' && $colorspace != 'Gray') {
119 $colorspace = 'RGB';
120 }
121 $bboxw = $w;
122 $bboxh = $h;
123 $usex = $x;
124 $usey = $y;
125 $usew = $bboxw;
126 $useh = $bboxh;
127
128 if ($type < 1) {
129 $type = 2;
130 }
131 if ($coords[0] !== false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $coords[0], $m)) {
132 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
133 if ($tmp) {
134 $coords[0] = $tmp / $w;
135 }
136 }
137 if ($coords[1] !== false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $coords[1], $m)) {
138 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
139 if ($tmp) {
140 $coords[1] = 1 - ($tmp / $h);
141 }
142 }
143 // LINEAR
144 if ($type == 2) {
145 $angle = (isset($coords[4]) ? $coords[4] : false);
146 $repeat = (isset($coords[5]) ? $coords[5] : false);
147 // ALL POINTS SET (default for custom mPDF linear gradient) - no -moz
148 if ($coords[0] !== false && $coords[1] !== false && $coords[2] !== false && $coords[3] !== false) {
149 // do nothing - coords used as they are
150 }
151
152 // If both a <point> and <angle> are defined, the gradient axis starts from the point and runs along the angle. The end point is
153 // defined as before - in this case start points may not be in corners, and axis may not correctly fall in the right quadrant.
154 // NO end points (Angle defined & Start points)
155 else if ($angle !== false && $coords[0] !== false && $coords[1] !== false && $coords[2] === false && $coords[3] === false) {
156 if ($angle == 0 || $angle == 360) {
157 $coords[3] = $coords[1];
158 if ($coords[0] == 1)
159 $coords[2] = 2;
160 else
161 $coords[2] = 1;
162 }
163 else if ($angle == 90) {
164 $coords[2] = $coords[0];
165 $coords[3] = 1;
166 if ($coords[1] == 1)
167 $coords[3] = 2;
168 else
169 $coords[3] = 1;
170 }
171 else if ($angle == 180) {
172 if ($coords[4] == 0)
173 $coords[2] = -1;
174 else
175 $coords[2] = 0;
176 $coords[3] = $coords[1];
177 }
178 else if ($angle == 270) {
179 $coords[2] = $coords[0];
180 if ($coords[1] == 0)
181 $coords[3] = -1;
182 else
183 $coords[3] = 0;
184 }
185 else {
186 $endx = 1;
187 $endy = 1;
188 if ($angle <= 90) {
189 if ($angle <= 45) {
190 $endy = tan(deg2rad($angle));
191 } else {
192 $endx = tan(deg2rad(90 - $angle));
193 }
194 $b = atan2(($endy * $bboxh), ($endx * $bboxw));
195 $ny = 1 - $coords[1] - (tan($b) * (1 - $coords[0]));
196 $tx = sin($b) * cos($b) * $ny;
197 $ty = cos($b) * cos($b) * $ny;
198 $coords[2] = 1 + $tx;
199 $coords[3] = 1 - $ty;
200 } else if ($angle <= 180) {
201 if ($angle <= 135) {
202 $endx = tan(deg2rad($angle - 90));
203 } else {
204 $endy = tan(deg2rad(180 - $angle));
205 }
206 $b = atan2(($endy * $bboxh), ($endx * $bboxw));
207 $ny = 1 - $coords[1] - (tan($b) * ($coords[0]));
208 $tx = sin($b) * cos($b) * $ny;
209 $ty = cos($b) * cos($b) * $ny;
210 $coords[2] = -$tx;
211 $coords[3] = 1 - $ty;
212 } else if ($angle <= 270) {
213 if ($angle <= 225) {
214 $endy = tan(deg2rad($angle - 180));
215 } else {
216 $endx = tan(deg2rad(270 - $angle));
217 }
218 $b = atan2(($endy * $bboxh), ($endx * $bboxw));
219 $ny = $coords[1] - (tan($b) * ($coords[0]));
220 $tx = sin($b) * cos($b) * $ny;
221 $ty = cos($b) * cos($b) * $ny;
222 $coords[2] = -$tx;
223 $coords[3] = $ty;
224 } else {
225 if ($angle <= 315) {
226 $endx = tan(deg2rad($angle - 270));
227 } else {
228 $endy = tan(deg2rad(360 - $angle));
229 }
230 $b = atan2(($endy * $bboxh), ($endx * $bboxw));
231 $ny = $coords[1] - (tan($b) * (1 - $coords[0]));
232 $tx = sin($b) * cos($b) * $ny;
233 $ty = cos($b) * cos($b) * $ny;
234 $coords[2] = 1 + $tx;
235 $coords[3] = $ty;
236 }
237 }
238 }
239
240 // -moz If the first parameter is only an <angle>, the gradient axis starts from the box's corner that would ensure the
241 // axis goes through the box. The axis runs along the specified angle. The end point of the axis is defined such that the
242 // farthest corner of the box from the starting point is perpendicular to the gradient axis at that point.
243 // NO end points or Start points (Angle defined)
244 else if ($angle !== false && $coords[0] === false && $coords[1] === false) {
245 if ($angle == 0 || $angle == 360) {
246 $coords[0] = 0;
247 $coords[1] = 0;
248 $coords[2] = 1;
249 $coords[3] = 0;
250 } else if ($angle == 90) {
251 $coords[0] = 0;
252 $coords[1] = 0;
253 $coords[2] = 0;
254 $coords[3] = 1;
255 } else if ($angle == 180) {
256 $coords[0] = 1;
257 $coords[1] = 0;
258 $coords[2] = 0;
259 $coords[3] = 0;
260 } else if ($angle == 270) {
261 $coords[0] = 0;
262 $coords[1] = 1;
263 $coords[2] = 0;
264 $coords[3] = 0;
265 } else {
266 if ($angle <= 90) {
267 $coords[0] = 0;
268 $coords[1] = 0;
269 if ($angle <= 45) {
270 $endx = 1;
271 $endy = tan(deg2rad($angle));
272 } else {
273 $endx = tan(deg2rad(90 - $angle));
274 $endy = 1;
275 }
276 } else if ($angle <= 180) {
277 $coords[0] = 1;
278 $coords[1] = 0;
279 if ($angle <= 135) {
280 $endx = tan(deg2rad($angle - 90));
281 $endy = 1;
282 } else {
283 $endx = 1;
284 $endy = tan(deg2rad(180 - $angle));
285 }
286 } else if ($angle <= 270) {
287 $coords[0] = 1;
288 $coords[1] = 1;
289 if ($angle <= 225) {
290 $endx = 1;
291 $endy = tan(deg2rad($angle - 180));
292 } else {
293 $endx = tan(deg2rad(270 - $angle));
294 $endy = 1;
295 }
296 } else {
297 $coords[0] = 0;
298 $coords[1] = 1;
299 if ($angle <= 315) {
300 $endx = tan(deg2rad($angle - 270));
301 $endy = 1;
302 } else {
303 $endx = 1;
304 $endy = tan(deg2rad(360 - $angle));
305 }
306 }
307 $b = atan2(($endy * $bboxh), ($endx * $bboxw));
308 $h2 = $bboxh - ($bboxh * tan($b));
309 $px = $bboxh + ($h2 * sin($b) * cos($b));
310 $py = ($bboxh * tan($b)) + ($h2 * sin($b) * sin($b));
311 $x1 = $px / $bboxh;
312 $y1 = $py / $bboxh;
313 if ($angle <= 90) {
314 $coords[2] = $x1;
315 $coords[3] = $y1;
316 } else if ($angle <= 180) {
317 $coords[2] = 1 - $x1;
318 $coords[3] = $y1;
319 } else if ($angle <= 270) {
320 $coords[2] = 1 - $x1;
321 $coords[3] = 1 - $y1;
322 } else {
323 $coords[2] = $x1;
324 $coords[3] = 1 - $y1;
325 }
326 }
327 }
328 // -moz If the first parameter to the gradient function is only a <point>, the gradient axis starts from the specified point,
329 // and ends at the point you would get if you rotated the starting point by 180 degrees about the center of the box that the
330 // gradient is to be applied to.
331 // NO angle and NO end points (Start points defined)
332 else if ((!isset($angle) || $angle === false) && $coords[0] !== false && $coords[1] !== false) { // should have start and end defined
333 $coords[2] = 1 - $coords[0];
334 $coords[3] = 1 - $coords[1];
335 $angle = rad2deg(atan2($coords[3] - $coords[1], $coords[2] - $coords[0]));
336 if ($angle < 0) {
337 $angle += 360;
338 } else if ($angle > 360) {
339 $angle -= 360;
340 }
341 if ($angle != 0 && $angle != 360 && $angle != 90 && $angle != 180 && $angle != 270) {
342 if ($w >= $h) {
343 $coords[1] *= $h / $w;
344 $coords[3] *= $h / $w;
345 $usew = $useh = $bboxw;
346 $usey -= ($w - $h);
347 } else {
348 $coords[0] *= $w / $h;
349 $coords[2] *= $w / $h;
350 $usew = $useh = $bboxh;
351 }
352 }
353 }
354
355 // -moz If neither a <point> or <angle> is specified, i.e. the entire function consists of only <stop> values, the gradient
356 // axis starts from the top of the box and runs vertically downwards, ending at the bottom of the box.
357 else { // default values T2B
358 // All values are set in parseMozGradient - so won't appear here
359 $coords = array(0, 0, 1, 0); // default for original linear gradient (L2R)
360 }
361 $s = ' q';
362 $s .= sprintf(' %.3F %.3F %.3F %.3F re W n', $x * _MPDFK, ($this->mpdf->h - $y) * _MPDFK, $w * _MPDFK, -$h * _MPDFK) . "\n";
363 $s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $usew * _MPDFK, $useh * _MPDFK, $usex * _MPDFK, ($this->mpdf->h - ($usey + $useh)) * _MPDFK) . "\n";
364 }
365
366 // RADIAL
367 else if ($type == 3) {
368 $radius = (isset($coords[4]) ? $coords[4] : false);
369 $angle = (isset($coords[5]) ? $coords[5] : false); // ?? no effect
370 $shape = (isset($coords[6]) ? $coords[6] : false);
371 $size = (isset($coords[7]) ? $coords[7] : false);
372 $repeat = (isset($coords[8]) ? $coords[8] : false);
373 // ALL POINTS AND RADIUS SET (default for custom mPDF radial gradient) - no -moz
374 if ($coords[0] !== false && $coords[1] !== false && $coords[2] !== false && $coords[3] !== false && $coords[4] !== false) {
375 // do nothing - coords used as they are
376 }
377 // If a <point> is defined
378 else if ($shape !== false && $size !== false) {
379 if ($coords[2] == false) {
380 $coords[2] = $coords[0];
381 }
382 if ($coords[3] == false) {
383 $coords[3] = $coords[1];
384 }
385 // ELLIPSE
386 if ($shape == 'ellipse') {
387 $corner1 = sqrt(pow($coords[0], 2) + pow($coords[1], 2));
388 $corner2 = sqrt(pow($coords[0], 2) + pow((1 - $coords[1]), 2));
389 $corner3 = sqrt(pow((1 - $coords[0]), 2) + pow($coords[1], 2));
390 $corner4 = sqrt(pow((1 - $coords[0]), 2) + pow((1 - $coords[1]), 2));
391 if ($size == 'closest-side') {
392 $radius = min($coords[0], $coords[1], (1 - $coords[0]), (1 - $coords[1]));
393 } else if ($size == 'closest-corner') {
394 $radius = min($corner1, $corner2, $corner3, $corner4);
395 } else if ($size == 'farthest-side') {
396 $radius = max($coords[0], $coords[1], (1 - $coords[0]), (1 - $coords[1]));
397 } else {
398 $radius = max($corner1, $corner2, $corner3, $corner4);
399 } // farthest corner (default)
400 }
401 // CIRCLE
402 else if ($shape == 'circle') {
403 if ($w >= $h) {
404 $coords[1] = $coords[3] = ($coords[1] * $h / $w);
405 $corner1 = sqrt(pow($coords[0], 2) + pow($coords[1], 2));
406 $corner2 = sqrt(pow($coords[0], 2) + pow((($h / $w) - $coords[1]), 2));
407 $corner3 = sqrt(pow((1 - $coords[0]), 2) + pow($coords[1], 2));
408 $corner4 = sqrt(pow((1 - $coords[0]), 2) + pow((($h / $w) - $coords[1]), 2));
409 if ($size == 'closest-side') {
410 $radius = min($coords[0], $coords[1], (1 - $coords[0]), (($h / $w) - $coords[1]));
411 } else if ($size == 'closest-corner') {
412 $radius = min($corner1, $corner2, $corner3, $corner4);
413 } else if ($size == 'farthest-side') {
414 $radius = max($coords[0], $coords[1], (1 - $coords[0]), (($h / $w) - $coords[1]));
415 } else if ($size == 'farthest-corner') {
416 $radius = max($corner1, $corner2, $corner3, $corner4);
417 } // farthest corner (default)
418 $usew = $useh = $bboxw;
419 $usey -= ($w - $h);
420 } else {
421 $coords[0] = $coords[2] = ($coords[0] * $w / $h);
422 $corner1 = sqrt(pow($coords[0], 2) + pow($coords[1], 2));
423 $corner2 = sqrt(pow($coords[0], 2) + pow((1 - $coords[1]), 2));
424 $corner3 = sqrt(pow((($w / $h) - $coords[0]), 2) + pow($coords[1], 2));
425 $corner4 = sqrt(pow((($w / $h) - $coords[0]), 2) + pow((1 - $coords[1]), 2));
426 if ($size == 'closest-side') {
427 $radius = min($coords[0], $coords[1], (($w / $h) - $coords[0]), (1 - $coords[1]));
428 } else if ($size == 'closest-corner') {
429 $radius = min($corner1, $corner2, $corner3, $corner4);
430 } else if ($size == 'farthest-side') {
431 $radius = max($coords[0], $coords[1], (($w / $h) - $coords[0]), (1 - $coords[1]));
432 } else if ($size == 'farthest-corner') {
433 $radius = max($corner1, $corner2, $corner3, $corner4);
434 } // farthest corner (default)
435 $usew = $useh = $bboxh;
436 }
437 }
438 if ($radius == 0) {
439 $radius = 0.001;
440 } // to prevent error
441 $coords[4] = $radius;
442 }
443
444 // -moz If entire function consists of only <stop> values
445 else { // default values
446 // All values are set in parseMozGradient - so won't appear here
447 $coords = array(0.5, 0.5, 0.5, 0.5); // default for radial gradient (centred)
448 }
449 $s = ' q';
450 $s .= sprintf(' %.3F %.3F %.3F %.3F re W n', $x * _MPDFK, ($this->mpdf->h - $y) * _MPDFK, $w * _MPDFK, -$h * _MPDFK) . "\n";
451 $s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $usew * _MPDFK, $useh * _MPDFK, $usex * _MPDFK, ($this->mpdf->h - ($usey + $useh)) * _MPDFK) . "\n";
452 }
453
454 $n = count($this->mpdf->gradients) + 1;
455 $this->mpdf->gradients[$n]['type'] = $type;
456 $this->mpdf->gradients[$n]['colorspace'] = $colorspace;
457 $trans = false;
458 $this->mpdf->gradients[$n]['is_mask'] = $is_mask;
459 if ($is_mask) {
460 $trans = true;
461 }
462 if (count($stops) == 1) {
463 $stops[1] = $stops[0];
464 }
465 if (!isset($stops[0]['offset'])) {
466 $stops[0]['offset'] = 0;
467 }
468 if (!isset($stops[(count($stops) - 1)]['offset'])) {
469 $stops[(count($stops) - 1)]['offset'] = 1;
470 }
471
472 // Fix stop-offsets set as absolute lengths
473 if ($type == 2) {
474 $axisx = ($coords[2] - $coords[0]) * $usew;
475 $axisy = ($coords[3] - $coords[1]) * $useh;
476 $axis_length = sqrt(pow($axisx, 2) + pow($axisy, 2));
477 } else {
478 $axis_length = $coords[4] * $usew;
479 } // Absolute lengths are meaningless for an ellipse - Firefox uses Width as reference
480
481 for ($i = 0; $i < count($stops); $i++) {
482 if (isset($stops[$i]['offset']) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $stops[$i]['offset'], $m)) {
483 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
484 $stops[$i]['offset'] = $tmp / $axis_length;
485 }
486 }
487
488
489 if (isset($stops[0]['offset']) && $stops[0]['offset'] > 0) {
490 $firststop = $stops[0];
491 $firststop['offset'] = 0;
492 array_unshift($stops, $firststop);
493 }
494 if (!$repeat && isset($stops[(count($stops) - 1)]['offset']) && $stops[(count($stops) - 1)]['offset'] < 1) {
495 $endstop = $stops[(count($stops) - 1)];
496 $endstop['offset'] = 1;
497 $stops[] = $endstop;
498 }
499 if ($stops[0]['offset'] > $stops[(count($stops) - 1)]['offset']) {
500 $stops[0]['offset'] = 0;
501 $stops[(count($stops) - 1)]['offset'] = 1;
502 }
503
504 for ($i = 0; $i < count($stops); $i++) {
505 // mPDF 5.3.74
506 if ($colorspace == 'CMYK') {
507 $this->mpdf->gradients[$n]['stops'][$i]['col'] = sprintf('%.3F %.3F %.3F %.3F', (ord($stops[$i]['col'][1]) / 100), (ord($stops[$i]['col'][2]) / 100), (ord($stops[$i]['col'][3]) / 100), (ord($stops[$i]['col'][4]) / 100));
508 } else if ($colorspace == 'Gray') {
509 $this->mpdf->gradients[$n]['stops'][$i]['col'] = sprintf('%.3F', (ord($stops[$i]['col'][1]) / 255));
510 } else {
511 $this->mpdf->gradients[$n]['stops'][$i]['col'] = sprintf('%.3F %.3F %.3F', (ord($stops[$i]['col'][1]) / 255), (ord($stops[$i]['col'][2]) / 255), (ord($stops[$i]['col'][3]) / 255));
512 }
513 if (!isset($stops[$i]['opacity'])) {
514 $stops[$i]['opacity'] = 1;
515 } else if ($stops[$i]['opacity'] > 1 || $stops[$i]['opacity'] < 0) {
516 $stops[$i]['opacity'] = 1;
517 } else if ($stops[$i]['opacity'] < 1) {
518 $trans = true;
519 }
520 $this->mpdf->gradients[$n]['stops'][$i]['opacity'] = $stops[$i]['opacity'];
521 // OFFSET
522 if ($i > 0 && $i < (count($stops) - 1)) {
523 if (!isset($stops[$i]['offset']) || (isset($stops[$i + 1]['offset']) && $stops[$i]['offset'] > $stops[$i + 1]['offset']) || $stops[$i]['offset'] < $stops[$i - 1]['offset']) {
524 if (isset($stops[$i - 1]['offset']) && isset($stops[$i + 1]['offset'])) {
525 $stops[$i]['offset'] = ($stops[$i - 1]['offset'] + $stops[$i + 1]['offset']) / 2;
526 } else {
527 for ($j = ($i + 1); $j < count($stops); $j++) {
528 if (isset($stops[$j]['offset'])) {
529 break;
530 }
531 }
532 $int = ($stops[$j]['offset'] - $stops[($i - 1)]['offset']) / ($j - $i + 1);
533 for ($f = 0; $f < ($j - $i - 1); $f++) {
534 $stops[($i + $f)]['offset'] = $stops[($i + $f - 1)]['offset'] + ($int);
535 }
536 }
537 }
538 }
539 $this->mpdf->gradients[$n]['stops'][$i]['offset'] = $stops[$i]['offset'];
540 $this->mpdf->gradients[$n]['stops'][$i]['offset'] = $stops[$i]['offset'];
541 }
542
543 if ($repeat) {
544 $ns = count($this->mpdf->gradients[$n]['stops']);
545 $offs = array();
546 for ($i = 0; $i < $ns; $i++) {
547 $offs[$i] = $this->mpdf->gradients[$n]['stops'][$i]['offset'];
548 }
549 $gp = 0;
550 $inside = true;
551 while ($inside) {
552 $gp++;
553 for ($i = 0; $i < $ns; $i++) {
554 $this->mpdf->gradients[$n]['stops'][(($ns * $gp) + $i)] = $this->mpdf->gradients[$n]['stops'][(($ns * ($gp - 1)) + $i)];
555 $tmp = $this->mpdf->gradients[$n]['stops'][(($ns * ($gp - 1)) + ($ns - 1))]['offset'] + $offs[$i];
556 if ($tmp < 1) {
557 $this->mpdf->gradients[$n]['stops'][(($ns * $gp) + $i)]['offset'] = $tmp;
558 } else {
559 $this->mpdf->gradients[$n]['stops'][(($ns * $gp) + $i)]['offset'] = 1;
560 $inside = false;
561 break(2);
562 }
563 }
564 }
565 }
566
567 if ($trans) {
568 $this->mpdf->gradients[$n]['trans'] = true;
569 $s .= ' /TGS' . $n . ' gs ';
570 }
571 if (!is_array($extend) || count($extend) < 1) {
572 $extend = array('true', 'true'); // These are supposed to be quoted - appear in PDF file as text
573 }
574 $this->mpdf->gradients[$n]['coords'] = $coords;
575 $this->mpdf->gradients[$n]['extend'] = $extend;
576 //paint the gradient
577 $s .= '/Sh' . $n . ' sh ' . "\n";
578 //restore previous Graphic State
579 $s .= ' Q ' . "\n";
580 if ($return) {
581 return $s;
582 } else {
583 $this->mpdf->_out($s);
584 }
585 }
586
587 function parseMozGradient($bg)
588 {
589 // background[-image]: -moz-linear-gradient(left, #c7Fdde 20%, #FF0000 );
590 // background[-image]: linear-gradient(left, #c7Fdde 20%, #FF0000 ); // CSS3
591 if (preg_match('/repeating-/', $bg)) {
592 $repeat = true;
593 } else {
594 $repeat = false;
595 }
596 if (preg_match('/linear-gradient\((.*)\)/', $bg, $m)) {
597 $g = array();
598 $g['type'] = 2;
599 $g['colorspace'] = 'RGB';
600 $g['extend'] = array('true', 'true');
601 $v = trim($m[1]);
602 // Change commas inside e.g. rgb(x,x,x)
603 while (preg_match('/(\([^\)]*?),/', $v)) {
604 $v = preg_replace('/(\([^\)]*?),/', '\\1@', $v);
605 }
606 // Remove spaces inside e.g. rgb(x, x, x)
607 while (preg_match('/(\([^\)]*?)[ ]/', $v)) {
608 $v = preg_replace('/(\([^\)]*?)[ ]/', '\\1', $v);
609 }
610 $bgr = preg_split('/\s*,\s*/', $v);
611 for ($i = 0; $i < count($bgr); $i++) {
612 $bgr[$i] = preg_replace('/@/', ',', $bgr[$i]);
613 }
614 // Is first part $bgr[0] a valid point/angle?
615 $first = preg_split('/\s+/', trim($bgr[0]));
616 if (preg_match('/(left|center|right|bottom|top|deg|grad|rad)/i', $bgr[0]) && !preg_match('/(<#|rgb|rgba|hsl|hsla)/i', $bgr[0])) {
617 $startStops = 1;
618 } else if (trim($first[(count($first) - 1)]) === "0") {
619 $startStops = 1;
620 } else {
621 $check = $this->mpdf->ConvertColor($first[0]);
622 if ($check)
623 $startStops = 0;
624 else
625 $startStops = 1;
626 }
627 // first part a valid point/angle?
628 if ($startStops == 1) { // default values
629 // [<point> || <angle>,] = [<% em px left center right bottom top> || <deg grad rad 0>,]
630 if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i', $bgr[0], $m)) {
631 $angle = $m[1] + 0;
632 if (strtolower($m[2]) == 'deg') {
633 $angle = $angle;
634 } else if (strtolower($m[2]) == 'grad') {
635 $angle *= (360 / 400);
636 } else if (strtolower($m[2]) == 'rad') {
637 $angle = rad2deg($angle);
638 }
639 while ($angle < 0) {
640 $angle += 360;
641 }
642 $angle = ($angle % 360);
643 } else if (trim($first[(count($first) - 1)]) === "0") {
644 $angle = 0;
645 }
646 if (preg_match('/left/i', $bgr[0])) {
647 $startx = 0;
648 } else if (preg_match('/right/i', $bgr[0])) {
649 $startx = 1;
650 }
651 if (preg_match('/top/i', $bgr[0])) {
652 $starty = 1;
653 } else if (preg_match('/bottom/i', $bgr[0])) {
654 $starty = 0;
655 }
656 // Check for %? ?% or %%
657 if (preg_match('/(\d+)[%]/i', $first[0], $m)) {
658 $startx = $m[1] / 100;
659 } else if (!isset($startx) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $first[0], $m)) {
660 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
661 if ($tmp) {
662 $startx = $m[1];
663 }
664 }
665 if (isset($first[1]) && preg_match('/(\d+)[%]/i', $first[1], $m)) {
666 $starty = 1 - ($m[1] / 100);
667 } else if (!isset($starty) && isset($first[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $first[1], $m)) {
668 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
669 if ($tmp) {
670 $starty = $m[1];
671 }
672 }
673 if (isset($startx) && !isset($starty)) {
674 $starty = 0.5;
675 }
676 if (!isset($startx) && isset($starty)) {
677 $startx = 0.5;
678 }
679 }
680 // If neither a <point> or <angle> is specified, i.e. the entire function consists of only <stop> values, the gradient axis starts from the top of the box and runs vertically downwards, ending at the bottom of the box.
681 else { // default values T2B
682 $starty = 1;
683 $startx = 0.5;
684 $endy = 0;
685 $endx = 0.5;
686 }
687 $coords = array();
688 if (!isset($startx)) {
689 $startx = false;
690 }
691 if (!isset($starty)) {
692 $starty = false;
693 }
694 if (!isset($endx)) {
695 $endx = false;
696 }
697 if (!isset($endy)) {
698 $endy = false;
699 }
700 if (!isset($angle)) {
701 $angle = false;
702 }
703 $g['coords'] = array($startx, $starty, $endx, $endy, $angle, $repeat);
704 $g['stops'] = array();
705 for ($i = $startStops; $i < count($bgr); $i++) {
706 $stop = array();
707 // parse stops
708 $el = preg_split('/\s+/', trim($bgr[$i]));
709 // mPDF 5.3.74
710 $col = $this->mpdf->ConvertColor($el[0]);
711 if ($col) {
712 $stop['col'] = $col;
713 } else {
714 $stop['col'] = $col = $this->mpdf->ConvertColor(255);
715 }
716 if ($col[0] == 1)
717 $g['colorspace'] = 'Gray';
718 else if ($col[0] == 4 || $col[0] == 6)
719 $g['colorspace'] = 'CMYK';
720 if ($col[0] == 5) {
721 $stop['opacity'] = ord($col[4]) / 100;
722 } // transparency from rgba()
723 else if ($col[0] == 6) {
724 $stop['opacity'] = ord($col[5]) / 100;
725 } // transparency from cmyka()
726 else if ($col[0] == 1 && $col[2] == 1) {
727 $stop['opacity'] = ord($col[3]) / 100;
728 } // transparency converted from rgba or cmyka()
729
730 if (isset($el[1]) && preg_match('/(\d+)[%]/', $el[1], $m)) {
731 $stop['offset'] = $m[1] / 100;
732 if ($stop['offset'] > 1) {
733 unset($stop['offset']);
734 }
735 } else if (isset($el[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $el[1], $m)) {
736 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
737 if ($tmp) {
738 $stop['offset'] = $m[1];
739 }
740 }
741 $g['stops'][] = $stop;
742 }
743 if (count($g['stops'])) {
744 return $g;
745 }
746 } else if (preg_match('/radial-gradient\((.*)\)/', $bg, $m)) {
747 $g = array();
748 $g['type'] = 3;
749 $g['colorspace'] = 'RGB';
750 $g['extend'] = array('true', 'true');
751 $v = trim($m[1]);
752 // Change commas inside e.g. rgb(x,x,x)
753 while (preg_match('/(\([^\)]*?),/', $v)) {
754 $v = preg_replace('/(\([^\)]*?),/', '\\1@', $v);
755 }
756 // Remove spaces inside e.g. rgb(x, x, x)
757 while (preg_match('/(\([^\)]*?)[ ]/', $v)) {
758 $v = preg_replace('/(\([^\)]*?)[ ]/', '\\1', $v);
759 }
760 $bgr = preg_split('/\s*,\s*/', $v);
761 for ($i = 0; $i < count($bgr); $i++) {
762 $bgr[$i] = preg_replace('/@/', ',', $bgr[$i]);
763 }
764
765 // Is first part $bgr[0] a valid point/angle?
766 $startStops = 0;
767 $pos_angle = false;
768 $shape_size = false;
769 $first = preg_split('/\s+/', trim($bgr[0]));
770 $checkCol = $this->mpdf->ConvertColor($first[0]);
771 if (preg_match('/(left|center|right|bottom|top|deg|grad|rad)/i', $bgr[0]) && !preg_match('/(<#|rgb|rgba|hsl|hsla)/i', $bgr[0])) {
772 $startStops = 1;
773 $pos_angle = $bgr[0];
774 } else if (trim($first[(count($first) - 1)]) === "0") {
775 $startStops = 1;
776 $pos_angle = $bgr[0];
777 } else if (preg_match('/(circle|ellipse|closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i', $bgr[0])) {
778 $startStops = 1;
779 $shape_size = $bgr[0];
780 } else if (!$checkCol) {
781 $startStops = 1;
782 $pos_angle = $bgr[0];
783 }
784 if (preg_match('/(circle|ellipse|closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i', $bgr[1])) {
785 $startStops = 2;
786 $shape_size = $bgr[1];
787 }
788
789 // If valid point/angle?
790 if ($pos_angle) { // default values
791 // [<point> || <angle>,] = [<% em px left center right bottom top> || <deg grad rad 0>,]
792 if (preg_match('/left/i', $pos_angle)) {
793 $startx = 0;
794 } else if (preg_match('/right/i', $pos_angle)) {
795 $startx = 1;
796 }
797 if (preg_match('/top/i', $pos_angle)) {
798 $starty = 1;
799 } else if (preg_match('/bottom/i', $pos_angle)) {
800 $starty = 0;
801 }
802 // Check for %? ?% or %%
803 if (preg_match('/(\d+)[%]/i', $first[0], $m)) {
804 $startx = $m[1] / 100;
805 } else if (!isset($startx) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $first[0], $m)) {
806 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
807 if ($tmp) {
808 $startx = $m[1];
809 }
810 }
811 if (isset($first[1]) && preg_match('/(\d+)[%]/i', $first[1], $m)) {
812 $starty = 1 - ($m[1] / 100);
813 } else if (!isset($starty) && isset($first[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $first[1], $m)) {
814 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
815 if ($tmp) {
816 $starty = $m[1];
817 }
818 }
819
820 /*
821 // ?? Angle has no effect in radial gradient (does not exist in CSS3 spec.)
822 if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$pos_angle,$m)) {
823 $angle = $m[1] + 0;
824 if (strtolower($m[2])=='deg') { $angle = $angle; }
825 else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
826 else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
827 while($angle < 0) { $angle += 360; }
828 $angle = ($angle % 360);
829 }
830 */
831 if (!isset($starty)) {
832 $starty = 0.5;
833 }
834 if (!isset($startx)) {
835 $startx = 0.5;
836 }
837 }
838 // If neither a <point> or <angle> is specified, i.e. the entire function consists of only <stop> values, the gradient axis starts from the top of the box and runs vertically downwards, ending at the bottom of the box.
839 else { // default values Center
840 $starty = 0.5;
841 $startx = 0.5;
842 $endy = 0.5;
843 $endx = 0.5;
844 }
845
846 // If valid shape/size?
847 $shape = 'ellipse'; // default
848 $size = 'farthest-corner'; // default
849 if ($shape_size) { // default values
850 if (preg_match('/(circle|ellipse)/i', $shape_size, $m)) {
851 $shape = $m[1];
852 }
853 if (preg_match('/(closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i', $shape_size, $m)) {
854 $size = $m[1];
855 if ($size == 'contain') {
856 $size = 'closest-side';
857 } else if ($size == 'cover') {
858 $size = 'farthest-corner';
859 }
860 }
861 }
862
863 $coords = array();
864 if (!isset($startx)) {
865 $startx = false;
866 }
867 if (!isset($starty)) {
868 $starty = false;
869 }
870 if (!isset($endx)) {
871 $endx = false;
872 }
873 if (!isset($endy)) {
874 $endy = false;
875 }
876 if (!isset($radius)) {
877 $radius = false;
878 }
879 if (!isset($angle)) {
880 $angle = 0;
881 }
882 $g['coords'] = array($startx, $starty, $endx, $endy, $radius, $angle, $shape, $size, $repeat);
883
884 $g['stops'] = array();
885 for ($i = $startStops; $i < count($bgr); $i++) {
886 $stop = array();
887 // parse stops
888 $el = preg_split('/\s+/', trim($bgr[$i]));
889 // mPDF 5.3.74
890 $col = $this->mpdf->ConvertColor($el[0]);
891 if ($col) {
892 $stop['col'] = $col;
893 } else {
894 $stop['col'] = $col = $this->mpdf->ConvertColor(255);
895 }
896 if ($col[0] == 1)
897 $g['colorspace'] = 'Gray';
898 else if ($col[0] == 4 || $col[0] == 6)
899 $g['colorspace'] = 'CMYK';
900 if ($col[0] == 5) {
901 $stop['opacity'] = ord($col[4]) / 100;
902 } // transparency from rgba()
903 else if ($col[0] == 6) {
904 $stop['opacity'] = ord($col[5]) / 100;
905 } // transparency from cmyka()
906 else if ($col[0] == 1 && $col[2] == 1) {
907 $stop['opacity'] = ord($col[3]) / 100;
908 } // transparency converted from rgba or cmyka()
909
910 if (isset($el[1]) && preg_match('/(\d+)[%]/', $el[1], $m)) {
911 $stop['offset'] = $m[1] / 100;
912 if ($stop['offset'] > 1) {
913 unset($stop['offset']);
914 }
915 } else if (isset($el[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $el[1], $m)) {
916 $tmp = $this->mpdf->ConvertSize($m[1], $this->mpdf->w, $this->mpdf->FontSize, false);
917 $stop['offset'] = $el[1];
918 }
919 $g['stops'][] = $stop;
920 }
921 if (count($g['stops'])) {
922 return $g;
923 }
924 }
925 return array();
926 }
927
928 function parseBackgroundGradient($bg)
929 {
930 // background-gradient: linear #00FFFF #FFFF00 0 0.5 1 0.5; or
931 // background-gradient: radial #00FFFF #FFFF00 0.5 0.5 1 1 1.2;
932
933 $v = trim($bg);
934 $bgr = preg_split('/\s+/', $v);
935 $g = array();
936 if (count($bgr) > 6) {
937 if (strtoupper(substr($bgr[0], 0, 1)) == 'L' && count($bgr) == 7) { // linear
938 $g['type'] = 2;
939 //$coords = array(0,0,1,1 ); // 0 0 1 0 or 0 1 1 1 is L 2 R; 1,1,0,1 is R2L; 1,1,1,0 is T2B; 1,0,1,1 is B2T
940 // Linear: $coords - array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg).
941 // The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
942 $g['coords'] = array($bgr[3], $bgr[4], $bgr[5], $bgr[6]);
943 } else if (count($bgr) == 8) { // radial
944 $g['type'] = 3;
945 // Radial: $coords - array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1,
946 // (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg).
947 // (fx, fy) should be inside the circle, otherwise some areas will not be defined
948 $g['coords'] = array($bgr[3], $bgr[4], $bgr[5], $bgr[6], $bgr[7]);
949 }
950 $g['colorspace'] = 'RGB';
951 // mPDF 5.3.74
952 $cor = $this->mpdf->ConvertColor($bgr[1]);
953 if ($cor[0] == 1)
954 $g['colorspace'] = 'Gray';
955 else if ($cor[0] == 4 || $cor[0] == 6)
956 $g['colorspace'] = 'CMYK';
957 if ($cor) {
958 $g['col'] = $cor;
959 } else {
960 $g['col'] = $this->mpdf->ConvertColor(255);
961 }
962 $cor = $this->mpdf->ConvertColor($bgr[2]);
963 if ($cor) {
964 $g['col2'] = $cor;
965 } else {
966 $g['col2'] = $this->mpdf->ConvertColor(255);
967 }
968 $g['extend'] = array('true', 'true');
969 $g['stops'] = array(array('col' => $g['col'], 'opacity' => 1, 'offset' => 0), array('col' => $g['col2'], 'opacity' => 1, 'offset' => 1));
970 return $g;
971 }
972 return false;
973 }
974
975 }
976