PluginProbe
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin / trunk
PDF & Print by BestWebSoft – WordPress Posts and Pages PDF Generator Plugin vtrunk
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
← All changes | mpdf/classes/grad.php +975 -723 1.7.1trunk View file →
@@ -1,723 +1,975 @@
1 -<?php
2 -
3 -class grad {
4 -
5 -var $mpdf = null;
6 -
7 -function grad(&$mpdf) {
8 - $this->mpdf = $mpdf;
9 -}
10 -
11 -// mPDF 5.3.A1
12 -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){
13 - $s=' q ';
14 - $s.=sprintf(' %.3F %.3F %.3F %.3F re W n ', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK);
15 - $s.=sprintf(' %.3F 0 0 %.3F %.3F %.3F cm ', $w*_MPDFK, $h*_MPDFK, $x*_MPDFK, ($this->mpdf->h-($y+$h))*_MPDFK);
16 - $n = count($this->mpdf->gradients)+1;
17 - $this->mpdf->gradients[$n]['type'] = 6; //coons patch mesh
18 - $this->mpdf->gradients[$n]['colorspace'] = $colspace; //coons patch mesh
19 - $bpcd=65535; //16 BitsPerCoordinate
20 - $trans = false;
21 - $this->mpdf->gradients[$n]['stream']='';
22 - for($i=0;$i<count($patch_array);$i++){
23 - $this->mpdf->gradients[$n]['stream'].=chr($patch_array[$i]['f']); //start with the edge flag as 8 bit
24 - for($j=0;$j<count($patch_array[$i]['points']);$j++){
25 - //each point as 16 bit
26 - if (($j % 2) == 1) { // Y coordinate (adjusted as input is From top left)
27 - $patch_array[$i]['points'][$j]=(($patch_array[$i]['points'][$j]-$y_min)/($y_max-$y_min))*$bpcd;
28 - $patch_array[$i]['points'][$j]=$bpcd-$patch_array[$i]['points'][$j];
29 - }
30 - else {
31 - $patch_array[$i]['points'][$j]=(($patch_array[$i]['points'][$j]-$x_min)/($x_max-$x_min))*$bpcd;
32 - }
33 - if($patch_array[$i]['points'][$j]<0) $patch_array[$i]['points'][$j]=0;
34 - if($patch_array[$i]['points'][$j]>$bpcd) $patch_array[$i]['points'][$j]=$bpcd;
35 - $this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j]/256));
36 - $this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j]%256));
37 - }
38 - for($j=0;$j<count($patch_array[$i]['colors']);$j++){
39 - //each color component as 8 bit
40 - if ($colspace=='RGB') {
41 - $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][1]);
42 - $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][2]);
43 - $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][3]);
44 - if (isset($patch_array[$i]['colors'][$j][4]) && ord($patch_array[$i]['colors'][$j][4])<100) { $trans = true; }
45 - }
46 - else if ($colspace=='CMYK') {
47 - $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][1])*2.55);
48 - $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][2])*2.55);
49 - $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][3])*2.55);
50 - $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][4])*2.55);
51 - if (isset($patch_array[$i]['colors'][$j][5]) && ord($patch_array[$i]['colors'][$j][5])<100) { $trans = true; }
52 - }
53 - else if ($colspace=='Gray') {
54 - $this->mpdf->gradients[$n]['stream'].=($patch_array[$i]['colors'][$j][1]);
55 - if ($patch_array[$i]['colors'][$j][2]==1) { $trans = true; } // transparency converted from rgba or cmyka()
56 - }
57 - }
58 - }
59 - // TRANSPARENCY
60 - if ($trans) {
61 - $this->mpdf->gradients[$n]['stream_trans']='';
62 - for($i=0;$i<count($patch_array);$i++){
63 - $this->mpdf->gradients[$n]['stream_trans'].=chr($patch_array[$i]['f']);
64 - for($j=0;$j<count($patch_array[$i]['points']);$j++){
65 - //each point as 16 bit
66 - $this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j]/256));
67 - $this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j]%256));
68 - }
69 - for($j=0;$j<count($patch_array[$i]['colors']);$j++){
70 - //each color component as 8 bit // OPACITY
71 - if ($colspace=='RGB') {
72 - $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][4])*2.55));
73 - }
74 - else if ($colspace=='CMYK') {
75 - $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][5])*2.55));
76 - }
77 - else if ($colspace=='Gray') {
78 - $this->mpdf->gradients[$n]['stream_trans'].=chr(intval(ord($patch_array[$i]['colors'][$j][3])*2.55));
79 - }
80 - }
81 - }
82 - $this->mpdf->gradients[$n]['trans'] = true;
83 - $s .= ' /TGS'.$n.' gs ';
84 - }
85 - //paint the gradient
86 - $s .= '/Sh'.$n.' sh'."\n";
87 - //restore previous Graphic State
88 - $s .= 'Q'."\n";
89 - if ($return) { return $s; }
90 - else { $this->mpdf->_out($s); }
91 -}
92 -
93 -
94 -// type = linear:2; radial: 3;
95 -// Linear: $coords - array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg).
96 -// The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
97 -// Radial: $coords - array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1,
98 -// (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg).
99 -// (fx, fy) should be inside the circle, otherwise some areas will not be defined
100 -// $col = array(R,G,B/255); or array(G/255); or array(C,M,Y,K/100)
101 -// $stops = array('col'=>$col [, 'opacity'=>0-1] [, 'offset'=>0-1])
102 -function Gradient($x, $y, $w, $h, $type, $stops=array(), $colorspace='RGB', $coords='', $extend='', $return=false, $is_mask=false) {
103 - if (strtoupper(substr($type,0,1)) == 'L') { $type = 2; } // linear
104 - else if (strtoupper(substr($type,0,1)) == 'R') { $type = 3; } // radial
105 - if ($colorspace != 'CMYK' && $colorspace != 'Gray') {
106 - $colorspace = 'RGB';
107 - }
108 - $bboxw = $w;
109 - $bboxh = $h;
110 - $usex = $x;
111 - $usey = $y;
112 - $usew = $bboxw;
113 - $useh = $bboxh;
114 - if ($type < 1) { $type = 2; }
115 - if ($coords[0]!==false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$coords[0],$m)) {
116 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
117 - if ($tmp) { $coords[0] = $tmp/$w; }
118 - }
119 - if ($coords[1]!==false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$coords[1],$m)) {
120 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
121 - if ($tmp) { $coords[1] = 1-($tmp/$h); }
122 - }
123 - // LINEAR
124 - if ($type == 2) {
125 - $angle = $coords[4];
126 - $repeat = $coords[5];
127 - // ALL POINTS SET (default for custom mPDF linear gradient) - no -moz
128 - if ($coords[0]!==false && $coords[1]!==false && $coords[2]!==false && $coords[3]!==false) {
129 - // do nothing - coords used as they are
130 - }
131 -
132 - // If both a <point> and <angle> are defined, the gradient axis starts from the point and runs along the angle. The end point is
133 - // defined as before - in this case start points may not be in corners, and axis may not correctly fall in the right quadrant.
134 - // NO end points (Angle defined & Start points)
135 - else if ($angle!==false && $coords[0]!==false && $coords[1]!==false && $coords[2]===false && $coords[3]===false) {
136 - if ($angle==0 || $angle==360) { $coords[3]=$coords[1]; if ($coords[0]==1) $coords[2]=2; else $coords[2]=1; }
137 - else if ($angle==90) { $coords[2]=$coords[0]; $coords[3]=1; if ($coords[1]==1) $coords[3]=2; else $coords[3]=1; }
138 - else if ($angle==180) { if ($coords[4]==0) $coords[2]=-1; else $coords[2]=0; $coords[3]=$coords[1]; }
139 - else if ($angle==270) { $coords[2]=$coords[0]; if ($coords[1]==0) $coords[3]=-1; else $coords[3]=0; }
140 - else {
141 - $endx=1; $endy=1;
142 - if ($angle <=90) {
143 - if ($angle <=45) { $endy=tan(deg2rad($angle)); }
144 - else { $endx=tan(deg2rad(90-$angle)); }
145 - $b = atan2(($endy*$bboxh), ($endx*$bboxw));
146 - $ny = 1 - $coords[1] - (tan($b) * (1-$coords[0]));
147 - $tx = sin($b) * cos($b) * $ny;
148 - $ty = cos($b) * cos($b) * $ny;
149 - $coords[2] = 1+$tx; $coords[3] = 1-$ty;
150 - }
151 - else if ($angle <=180) {
152 - if ($angle <=135) { $endx=tan(deg2rad($angle-90)); }
153 - else { $endy=tan(deg2rad(180-$angle)); }
154 - $b = atan2(($endy*$bboxh), ($endx*$bboxw));
155 - $ny = 1 - $coords[1] - (tan($b) * ($coords[0]));
156 - $tx = sin($b) * cos($b) * $ny;
157 - $ty = cos($b) * cos($b) * $ny;
158 - $coords[2] = -$tx; $coords[3] = 1-$ty;
159 - }
160 - else if ($angle <=270) {
161 - if ($angle <=225) { $endy=tan(deg2rad($angle-180)); }
162 - else { $endx=tan(deg2rad(270-$angle)); }
163 - $b = atan2(($endy*$bboxh), ($endx*$bboxw));
164 - $ny = $coords[1] - (tan($b) * ($coords[0]));
165 - $tx = sin($b) * cos($b) * $ny;
166 - $ty = cos($b) * cos($b) * $ny;
167 - $coords[2] = -$tx; $coords[3] = $ty;
168 - }
169 - else {
170 - if ($angle <=315) { $endx=tan(deg2rad($angle-270)); }
171 - else { $endy=tan(deg2rad(360-$angle)); }
172 - $b = atan2(($endy*$bboxh), ($endx*$bboxw));
173 - $ny = $coords[1] - (tan($b) * (1-$coords[0]));
174 - $tx = sin($b) * cos($b) * $ny;
175 - $ty = cos($b) * cos($b) * $ny;
176 - $coords[2] = 1+$tx; $coords[3] = $ty;
177 -
178 - }
179 - }
180 - }
181 -
182 - // -moz If the first parameter is only an <angle>, the gradient axis starts from the box's corner that would ensure the
183 - // axis goes through the box. The axis runs along the specified angle. The end point of the axis is defined such that the
184 - // farthest corner of the box from the starting point is perpendicular to the gradient axis at that point.
185 - // NO end points or Start points (Angle defined)
186 - else if ($angle!==false && $coords[0]===false && $coords[1]===false) {
187 - if ($angle==0 || $angle==360) { $coords[0]=0; $coords[1]=0; $coords[2]=1; $coords[3]=0; }
188 - else if ($angle==90) { $coords[0]=0; $coords[1]=0; $coords[2]=0; $coords[3]=1; }
189 - else if ($angle==180) { $coords[0]=1; $coords[1]=0; $coords[2]=0; $coords[3]=0; }
190 - else if ($angle==270) { $coords[0]=0; $coords[1]=1; $coords[2]=0; $coords[3]=0; }
191 - else {
192 - if ($angle <=90) {
193 - $coords[0]=0; $coords[1]=0;
194 - if ($angle <=45) { $endx=1; $endy=tan(deg2rad($angle)); }
195 - else { $endx=tan(deg2rad(90-$angle)); $endy=1; }
196 - }
197 - else if ($angle <=180) {
198 - $coords[0]=1; $coords[1]=0;
199 - if ($angle <=135) { $endx=tan(deg2rad($angle-90)); $endy=1; }
200 - else { $endx=1; $endy=tan(deg2rad(180-$angle)); }
201 - }
202 - else if ($angle <=270) {
203 - $coords[0]=1; $coords[1]=1;
204 - if ($angle <=225) { $endx=1; $endy=tan(deg2rad($angle-180)); }
205 - else { $endx=tan(deg2rad(270-$angle)); $endy=1; }
206 - }
207 - else {
208 - $coords[0]=0; $coords[1]=1;
209 - if ($angle <=315) { $endx=tan(deg2rad($angle-270)); $endy=1; }
210 - else { $endx=1; $endy=tan(deg2rad(360-$angle)); }
211 - }
212 - $b = atan2(($endy*$bboxh), ($endx*$bboxw));
213 - $h2 = $bboxh - ($bboxh * tan($b));
214 - $px = $bboxh + ($h2 * sin($b) * cos($b));
215 - $py = ($bboxh * tan($b)) + ($h2 * sin($b) * sin($b));
216 - $x1 = $px / $bboxh;
217 - $y1 = $py / $bboxh;
218 - if ($angle <=90) { $coords[2] = $x1; $coords[3] = $y1; }
219 - else if ($angle <=180) { $coords[2] = 1-$x1; $coords[3] = $y1; }
220 - else if ($angle <=270) { $coords[2] = 1-$x1; $coords[3] = 1-$y1; }
221 - else { $coords[2] = $x1; $coords[3] = 1-$y1; }
222 - }
223 - }
224 - // -moz If the first parameter to the gradient function is only a <point>, the gradient axis starts from the specified point,
225 - // 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
226 - // gradient is to be applied to.
227 - // NO angle and NO end points (Start points defined)
228 - else if ((!isset($angle) || $angle===false) && $coords[0]!==false && $coords[1]!==false) { // should have start and end defined
229 - $coords[2] = 1-$coords[0]; $coords[3] = 1-$coords[1];
230 - $angle = rad2deg(atan2($coords[3]-$coords[1],$coords[2]-$coords[0]));
231 - if ($angle < 0) { $angle += 360; }
232 - else if ($angle > 360) { $angle -= 360; }
233 - if ($angle!=0 && $angle!=360 && $angle!=90 && $angle!=180 && $angle!=270) {
234 - if ($w >= $h) {
235 - $coords[1] *= $h/$w ;
236 - $coords[3] *= $h/$w ;
237 - $usew = $useh = $bboxw;
238 - $usey -= ($w-$h);
239 - }
240 - else {
241 - $coords[0] *= $w/$h ;
242 - $coords[2] *= $w/$h ;
243 - $usew = $useh = $bboxh;
244 - }
245 - }
246 - }
247 -
248 - // -moz If neither a <point> or <angle> is specified, i.e. the entire function consists of only <stop> values, the gradient
249 - // axis starts from the top of the box and runs vertically downwards, ending at the bottom of the box.
250 - else { // default values T2B
251 - // All values are set in parseMozGradient - so won't appear here
252 - $coords = array(0,0,1,0); // default for original linear gradient (L2R)
253 - }
254 - $s = ' q';
255 - $s .= sprintf(' %.3F %.3F %.3F %.3F re W n', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK)."\n";
256 - $s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $usew*_MPDFK, $useh*_MPDFK, $usex*_MPDFK, ($this->mpdf->h-($usey+$useh))*_MPDFK)."\n";
257 - }
258 -
259 - // RADIAL
260 - else if ($type == 3) {
261 - $radius = $coords[4];
262 - $angle = $coords[5]; // ?? no effect
263 - $shape = $coords[6];
264 - $size = $coords[7];
265 - $repeat = $coords[8];
266 - // ALL POINTS AND RADIUS SET (default for custom mPDF radial gradient) - no -moz
267 - if ($coords[0]!==false && $coords[1]!==false && $coords[2]!==false && $coords[3]!==false && $coords[4]!==false) {
268 - // do nothing - coords used as they are
269 - }
270 - // If a <point> is defined
271 - else if ($shape!==false && $size!==false) {
272 - if ($coords[2]==false) { $coords[2] = $coords[0]; }
273 - if ($coords[3]==false) { $coords[3] = $coords[1]; }
274 - // ELLIPSE
275 - if ($shape=='ellipse') {
276 - $corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
277 - $corner2 = sqrt(pow($coords[0],2) + pow((1-$coords[1]),2));
278 - $corner3 = sqrt(pow((1-$coords[0]),2) + pow($coords[1],2));
279 - $corner4 = sqrt(pow((1-$coords[0]),2) + pow((1-$coords[1]),2));
280 - if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (1-$coords[0]), (1-$coords[1])); }
281 - else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
282 - else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (1-$coords[0]), (1-$coords[1])); }
283 - else { $radius = max($corner1, $corner2, $corner3, $corner4); } // farthest corner (default)
284 - }
285 - // CIRCLE
286 - else if ($shape=='circle') {
287 - if ($w >= $h) {
288 - $coords[1] = $coords[3] = ($coords[1] * $h/$w) ;
289 - $corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
290 - $corner2 = sqrt(pow($coords[0],2) + pow((($h/$w)-$coords[1]),2));
291 - $corner3 = sqrt(pow((1-$coords[0]),2) + pow($coords[1],2));
292 - $corner4 = sqrt(pow((1-$coords[0]),2) + pow((($h/$w)-$coords[1]),2));
293 - if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (1-$coords[0]), (($h/$w)-$coords[1])); }
294 - else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
295 - else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (1-$coords[0]), (($h/$w)-$coords[1])); }
296 - else if ($size=='farthest-corner') { $radius = max($corner1, $corner2, $corner3, $corner4); } // farthest corner (default)
297 - $usew = $useh = $bboxw;
298 - $usey -= ($w-$h);
299 - }
300 - else {
301 - $coords[0] = $coords[2] = ($coords[0] * $w/$h) ;
302 - $corner1 = sqrt(pow($coords[0],2) + pow($coords[1],2));
303 - $corner2 = sqrt(pow($coords[0],2) + pow((1-$coords[1]),2));
304 - $corner3 = sqrt(pow((($w/$h)-$coords[0]),2) + pow($coords[1],2));
305 - $corner4 = sqrt(pow((($w/$h)-$coords[0]),2) + pow((1-$coords[1]),2));
306 - if ($size=='closest-side') { $radius = min($coords[0], $coords[1], (($w/$h)-$coords[0]), (1-$coords[1])); }
307 - else if ($size=='closest-corner') { $radius = min($corner1, $corner2, $corner3, $corner4); }
308 - else if ($size=='farthest-side') { $radius = max($coords[0], $coords[1], (($w/$h)-$coords[0]), (1-$coords[1])); }
309 - else if ($size=='farthest-corner') { $radius = max($corner1, $corner2, $corner3, $corner4); } // farthest corner (default)
310 - $usew = $useh = $bboxh;
311 - }
312 - }
313 - if ($radius==0) { $radius=0.001; } // to prevent error
314 - $coords[4] = $radius;
315 - }
316 -
317 - // -moz If entire function consists of only <stop> values
318 - else { // default values
319 - // All values are set in parseMozGradient - so won't appear here
320 - $coords = array(0.5,0.5,0.5,0.5); // default for radial gradient (centred)
321 - }
322 - $s = ' q';
323 - $s .= sprintf(' %.3F %.3F %.3F %.3F re W n', $x*_MPDFK, ($this->mpdf->h-$y)*_MPDFK, $w*_MPDFK, -$h*_MPDFK)."\n";
324 - $s .= sprintf(' %.3F 0 0 %.3F %.3F %.3F cm', $usew*_MPDFK, $useh*_MPDFK, $usex*_MPDFK, ($this->mpdf->h-($usey+$useh))*_MPDFK)."\n";
325 - }
326 -
327 - $n = count($this->mpdf->gradients) + 1;
328 - $this->mpdf->gradients[$n]['type'] = $type;
329 - $this->mpdf->gradients[$n]['colorspace'] = $colorspace;
330 - $trans = false;
331 - $this->mpdf->gradients[$n]['is_mask'] = $is_mask;
332 - if ($is_mask) { $trans = true; }
333 - if (count($stops) == 1) { $stops[1] = $stops[0]; }
334 - if (!isset($stops[0]['offset'])) { $stops[0]['offset'] = 0; }
335 - if (!isset($stops[(count($stops)-1)]['offset'])) { $stops[(count($stops)-1)]['offset'] = 1; }
336 -
337 - // Fix stop-offsets set as absolute lengths
338 - if ($type==2) {
339 - $axisx = ($coords[2]-$coords[0])*$usew;
340 - $axisy = ($coords[3]-$coords[1])*$useh;
341 - $axis_length = sqrt(pow($axisx,2) + pow($axisy,2));
342 - }
343 - else { $axis_length = $coords[4]*$usew; } // Absolute lengths are meaningless for an ellipse - Firefox uses Width as reference
344 -
345 - for($i=0;$i<count($stops);$i++) {
346 - if (isset($stops[$i]['offset']) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$stops[$i]['offset'],$m)) {
347 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
348 - $stops[$i]['offset'] = $tmp/$axis_length;
349 - }
350 - }
351 -
352 -
353 - if (isset($stops[0]['offset']) && $stops[0]['offset']>0) {
354 - $firststop = $stops[0];
355 - $firststop['offset'] = 0;
356 - array_unshift($stops, $firststop);
357 - }
358 - if (!$repeat && isset($stops[(count($stops)-1)]['offset']) && $stops[(count($stops)-1)]['offset']<1) {
359 - $endstop = $stops[(count($stops)-1)];
360 - $endstop['offset'] = 1;
361 - $stops[] = $endstop;
362 - }
363 - if ($stops[0]['offset'] > $stops[(count($stops)-1)]['offset']) {
364 - $stops[0]['offset'] = 0;
365 - $stops[(count($stops)-1)]['offset'] = 1;
366 - }
367 -
368 - for($i=0;$i<count($stops);$i++) {
369 - // mPDF 5.3.74
370 - if ($colorspace == 'CMYK') {
371 - $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));
372 - }
373 - else if ($colorspace == 'Gray') {
374 - $this->mpdf->gradients[$n]['stops'][$i]['col'] = sprintf('%.3F', (ord($stops[$i]['col']{1})/255));
375 - }
376 - else {
377 - $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));
378 - }
379 - if (!isset($stops[$i]['opacity'])) { $stops[$i]['opacity'] = 1; }
380 - else if ($stops[$i]['opacity'] > 1 || $stops[$i]['opacity'] < 0) { $stops[$i]['opacity'] = 1; }
381 - else if ($stops[$i]['opacity'] < 1) {
382 - $trans = true;
383 - }
384 - $this->mpdf->gradients[$n]['stops'][$i]['opacity'] = $stops[$i]['opacity'];
385 - // OFFSET
386 - if ($i>0 && $i<(count($stops)-1)) {
387 - if (!isset($stops[$i]['offset']) || (isset($stops[$i+1]['offset']) && $stops[$i]['offset']>$stops[$i+1]['offset']) || $stops[$i]['offset']<$stops[$i-1]['offset']) {
388 - if (isset($stops[$i-1]['offset']) && isset($stops[$i+1]['offset'])) {
389 - $stops[$i]['offset'] = ($stops[$i-1]['offset']+$stops[$i+1]['offset'])/2;
390 - }
391 - else {
392 - for($j=($i+1);$j<count($stops);$j++) {
393 - if(isset($stops[$j]['offset'])) { break; }
394 - }
395 - $int = ($stops[$j]['offset'] - $stops[($i-1)]['offset'])/($j-$i+1);
396 - for($f=0;$f<($j-$i-1);$f++) {
397 - $stops[($i+$f)]['offset'] = $stops[($i+$f-1)]['offset'] + ($int);
398 - }
399 - }
400 - }
401 - }
402 - $this->mpdf->gradients[$n]['stops'][$i]['offset'] = $stops[$i]['offset'];
403 - $this->mpdf->gradients[$n]['stops'][$i]['offset'] = $stops[$i]['offset'];
404 - }
405 -
406 - if ($repeat) {
407 - $ns = count($this->mpdf->gradients[$n]['stops']);
408 - $offs = array();
409 - for($i=0;$i<$ns;$i++) {
410 - $offs[$i] = $this->mpdf->gradients[$n]['stops'][$i]['offset'];
411 - }
412 - $gp = 0;
413 - $inside=true;
414 - while($inside) {
415 - $gp++;
416 - for($i=0;$i<$ns;$i++) {
417 - $this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)] = $this->mpdf->gradients[$n]['stops'][(($ns*($gp-1))+$i)];
418 - $tmp = $this->mpdf->gradients[$n]['stops'][(($ns*($gp-1))+($ns-1))]['offset']+$offs[$i] ;
419 - if ($tmp < 1) { $this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)]['offset'] = $tmp; }
420 - else {
421 - $this->mpdf->gradients[$n]['stops'][(($ns*$gp)+$i)]['offset'] = 1;
422 - $inside = false;
423 - break(2);
424 - }
425 - }
426 - }
427 - }
428 -
429 - if ($trans) {
430 - $this->mpdf->gradients[$n]['trans'] = true;
431 - $s .= ' /TGS'.$n.' gs ';
432 - }
433 - if (!is_array($extend) || count($extend) <1) {
434 - $extend=array('true', 'true'); // These are supposed to be quoted - appear in PDF file as text
435 - }
436 - $this->mpdf->gradients[$n]['coords'] = $coords;
437 - $this->mpdf->gradients[$n]['extend'] = $extend;
438 - //paint the gradient
439 - $s .= '/Sh'.$n.' sh '."\n";
440 - //restore previous Graphic State
441 - $s .= ' Q '."\n";
442 - if ($return) { return $s; }
443 - else { $this->mpdf->_out($s); }
444 -}
445 -
446 -
447 -function parseMozGradient($bg) {
448 - // background[-image]: -moz-linear-gradient(left, #c7Fdde 20%, #FF0000 );
449 - // background[-image]: linear-gradient(left, #c7Fdde 20%, #FF0000 ); // CSS3
450 - if (preg_match('/repeating-/',$bg)) { $repeat = true; }
451 - else { $repeat = false; }
452 - if (preg_match('/linear-gradient\((.*)\)/',$bg,$m)) {
453 - $g = array();
454 - $g['type'] = 2;
455 - $g['colorspace'] = 'RGB';
456 - $g['extend'] = array('true','true');
457 - $v = trim($m[1]);
458 - // Change commas inside e.g. rgb(x,x,x)
459 - while(preg_match('/(\([^\)]*?),/',$v)) { $v = preg_replace('/(\([^\)]*?),/','\\1@',$v); }
460 - // Remove spaces inside e.g. rgb(x, x, x)
461 - while(preg_match('/(\([^\)]*?)[ ]/',$v)) { $v = preg_replace('/(\([^\)]*?)[ ]/','\\1',$v); }
462 - $bgr = preg_split('/\s*,\s*/',$v);
463 - for($i=0;$i<count($bgr);$i++) { $bgr[$i] = preg_replace('/@/', ',', $bgr[$i]); }
464 - // Is first part $bgr[0] a valid point/angle?
465 - $first = preg_split('/\s+/',trim($bgr[0]));
466 - if (preg_match('/(left|center|right|bottom|top|deg|grad|rad)/i',$bgr[0]) && !preg_match('/(<#|rgb|rgba|hsl|hsla)/i',$bgr[0])) {
467 - $startStops = 1;
468 - }
469 - else if (trim($first[(count($first)-1)]) === "0") {
470 - $startStops = 1;
471 - }
472 - else {
473 - $check = $this->mpdf->ConvertColor($first[0]);
474 - if ($check) $startStops = 0;
475 - else $startStops = 1;
476 - }
477 - // first part a valid point/angle?
478 - if ($startStops == 1) { // default values
479 - // [<point> || <angle>,] = [<% em px left center right bottom top> || <deg grad rad 0>,]
480 - if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$bgr[0],$m)) {
481 - $angle = $m[1] + 0;
482 - if (strtolower($m[2])=='deg') { $angle = $angle; }
483 - else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
484 - else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
485 - while($angle < 0) { $angle += 360; }
486 - $angle = ($angle % 360);
487 - }
488 - else if (trim($first[(count($first)-1)]) === "0") { $angle = 0; }
489 - if (preg_match('/left/i',$bgr[0])) { $startx = 0; }
490 - else if (preg_match('/right/i',$bgr[0])) { $startx = 1; }
491 - if (preg_match('/top/i',$bgr[0])) { $starty = 1; }
492 - else if (preg_match('/bottom/i',$bgr[0])) { $starty = 0; }
493 - // Check for %? ?% or %%
494 - if (preg_match('/(\d+)[%]/i',$first[0],$m)) { $startx = $m[1]/100; }
495 - else if (!isset($startx) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[0],$m)) {
496 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
497 - if ($tmp) { $startx = $m[1]; }
498 - }
499 - if (isset($first[1]) && preg_match('/(\d+)[%]/i',$first[1],$m)) { $starty = 1 - ($m[1]/100); }
500 - else if (!isset($starty) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[1],$m)) {
501 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
502 - if ($tmp) { $starty = $m[1]; }
503 - }
504 - if (isset($startx) && !isset($starty)) { $starty = 0.5; }
505 - if (!isset($startx) && isset($starty)) { $startx = 0.5; }
506 -
507 - }
508 - // 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.
509 - else { // default values T2B
510 - $starty = 1; $startx = 0.5;
511 - $endy = 0; $endx = 0.5;
512 - }
513 - $coords = array();
514 - if (!isset($startx)) { $startx = false; }
515 - if (!isset($starty)) { $starty = false; }
516 - if (!isset($endx)) { $endx = false; }
517 - if (!isset($endy)) { $endy = false; }
518 - if (!isset($angle)) { $angle = false; }
519 - $g['coords'] = array($startx ,$starty ,$endx ,$endy, $angle, $repeat );
520 - $g['stops'] = array();
521 - for($i=$startStops;$i<count($bgr);$i++) {
522 - $stop = array();
523 - // parse stops
524 - $el = preg_split('/\s+/',trim($bgr[$i]));
525 - // mPDF 5.3.74
526 - $col = $this->mpdf->ConvertColor($el[0]);
527 - if ($col) { $stop['col'] = $col; }
528 - else { $stop['col'] = $col = $this->mpdf->ConvertColor(255); }
529 - if ($col{0}==1) $g['colorspace'] = 'Gray';
530 - else if ($col{0}==4 || $col{0}==6) $g['colorspace'] = 'CMYK';
531 - if ($col{0}==5) { $stop['opacity'] = ord($col{4})/100; } // transparency from rgba()
532 - else if ($col{0}==6) { $stop['opacity'] = ord($col{5})/100; } // transparency from cmyka()
533 - else if ($col{0}==1 && $col{2}==1) { $stop['opacity'] = ord($col{3})/100; } // transparency converted from rgba or cmyka()
534 -
535 - if (isset($el[1]) && preg_match('/(\d+)[%]/',$el[1],$m)) {
536 - $stop['offset'] = $m[1]/100;
537 - if ($stop['offset']>1) { unset($stop['offset']); }
538 - }
539 - else if (isset($el[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$el[1],$m)) {
540 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
541 - if ($tmp) { $stop['offset'] = $m[1]; }
542 - }
543 - $g['stops'][] = $stop;
544 - }
545 - if (count($g['stops'] )) { return $g; }
546 - }
547 - else if (preg_match('/radial-gradient\((.*)\)/',$bg,$m)) {
548 - $g = array();
549 - $g['type'] = 3;
550 - $g['colorspace'] = 'RGB';
551 - $g['extend'] = array('true','true');
552 - $v = trim($m[1]);
553 - // Change commas inside e.g. rgb(x,x,x)
554 - while(preg_match('/(\([^\)]*?),/',$v)) { $v = preg_replace('/(\([^\)]*?),/','\\1@',$v); }
555 - // Remove spaces inside e.g. rgb(x, x, x)
556 - while(preg_match('/(\([^\)]*?)[ ]/',$v)) { $v = preg_replace('/(\([^\)]*?)[ ]/','\\1',$v); }
557 - $bgr = preg_split('/\s*,\s*/',$v);
558 - for($i=0;$i<count($bgr);$i++) { $bgr[$i] = preg_replace('/@/', ',', $bgr[$i]); }
559 -
560 - // Is first part $bgr[0] a valid point/angle?
561 - $startStops = 0;
562 - $pos_angle = false;
563 - $shape_size = false;
564 - $first = preg_split('/\s+/',trim($bgr[0]));
565 - $checkCol = $this->mpdf->ConvertColor($first[0]);
566 - if (preg_match('/(left|center|right|bottom|top|deg|grad|rad)/i',$bgr[0]) && !preg_match('/(<#|rgb|rgba|hsl|hsla)/i',$bgr[0])) {
567 - $startStops=1;
568 - $pos_angle = $bgr[0];
569 - }
570 - else if (trim($first[(count($first)-1)]) === "0") {
571 - $startStops=1;
572 - $pos_angle = $bgr[0];
573 - }
574 - else if (preg_match('/(circle|ellipse|closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$bgr[0])) {
575 - $startStops=1;
576 - $shape_size = $bgr[0];
577 - }
578 - else if (!$checkCol) {
579 - $startStops=1;
580 - $pos_angle = $bgr[0];
581 - }
582 - if (preg_match('/(circle|ellipse|closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$bgr[1])) {
583 - $startStops=2;
584 - $shape_size = $bgr[1];
585 - }
586 -
587 - // If valid point/angle?
588 - if ($pos_angle) { // default values
589 - // [<point> || <angle>,] = [<% em px left center right bottom top> || <deg grad rad 0>,]
590 - if (preg_match('/left/i',$pos_angle)) { $startx = 0; }
591 - else if (preg_match('/right/i',$pos_angle)) { $startx = 1; }
592 - if (preg_match('/top/i',$pos_angle)) { $starty = 1; }
593 - else if (preg_match('/bottom/i',$pos_angle)) { $starty = 0; }
594 - // Check for %? ?% or %%
595 - if (preg_match('/(\d+)[%]/i',$first[0],$m)) { $startx = $m[1]/100; }
596 - else if (!isset($startx) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[0],$m)) {
597 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
598 - if ($tmp) { $startx = $m[1]; }
599 - }
600 - if (isset($first[1]) && preg_match('/(\d+)[%]/i',$first[1],$m)) { $starty = 1 - ($m[1]/100); }
601 - else if (!isset($starty) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$first[1],$m)) {
602 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
603 - if ($tmp) { $starty = $m[1]; }
604 - }
605 -
606 -/*
607 - // ?? Angle has no effect in radial gradient (does not exist in CSS3 spec.)
608 - if (preg_match('/([\-]*[0-9\.]+)(deg|grad|rad)/i',$pos_angle,$m)) {
609 - $angle = $m[1] + 0;
610 - if (strtolower($m[2])=='deg') { $angle = $angle; }
611 - else if (strtolower($m[2])=='grad') { $angle *= (360/400); }
612 - else if (strtolower($m[2])=='rad') { $angle = rad2deg($angle); }
613 - while($angle < 0) { $angle += 360; }
614 - $angle = ($angle % 360);
615 - }
616 -*/
617 - if (!isset($starty)) { $starty = 0.5; }
618 - if (!isset($startx)) { $startx = 0.5; }
619 -
620 - }
621 - // 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.
622 - else { // default values Center
623 - $starty = 0.5; $startx = 0.5;
624 - $endy = 0.5; $endx = 0.5;
625 - }
626 -
627 - // If valid shape/size?
628 - $shape = 'ellipse'; // default
629 - $size = 'farthest-corner'; // default
630 - if ($shape_size) { // default values
631 - if (preg_match('/(circle|ellipse)/i',$shape_size, $m)) {
632 - $shape = $m[1];
633 - }
634 - if (preg_match('/(closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/i',$shape_size, $m)) {
635 - $size = $m[1];
636 - if ($size=='contain') { $size = 'closest-side'; }
637 - else if ($size=='cover') { $size = 'farthest-corner'; }
638 - }
639 - }
640 -
641 - $coords = array();
642 - if (!isset($startx)) { $startx = false; }
643 - if (!isset($starty)) { $starty = false; }
644 - if (!isset($endx)) { $endx = false; }
645 - if (!isset($endy)) { $endy = false; }
646 - if (!isset($radius)) { $radius = false; }
647 - if (!isset($angle)) { $angle = 0; }
648 - $g['coords'] = array($startx ,$starty ,$endx ,$endy, $radius, $angle, $shape, $size, $repeat );
649 -
650 - $g['stops'] = array();
651 - for($i=$startStops;$i<count($bgr);$i++) {
652 - $stop = array();
653 - // parse stops
654 - $el = preg_split('/\s+/',trim($bgr[$i]));
655 - // mPDF 5.3.74
656 - $col = $this->mpdf->ConvertColor($el[0]);
657 - if ($col) { $stop['col'] = $col; }
658 - else { $stop['col'] = $col = $this->mpdf->ConvertColor(255); }
659 - if ($col{0}==1) $g['colorspace'] = 'Gray';
660 - else if ($col{0}==4 || $col{0}==6) $g['colorspace'] = 'CMYK';
661 - if ($col{0}==5) { $stop['opacity'] = ord($col{4})/100; } // transparency from rgba()
662 - else if ($col{0}==6) { $stop['opacity'] = ord($col{5})/100; } // transparency from cmyka()
663 - else if ($col{0}==1 && $col{2}==1) { $stop['opacity'] = ord($col{3})/100; } // transparency converted from rgba or cmyka()
664 -
665 - if (isset($el[1]) && preg_match('/(\d+)[%]/',$el[1],$m)) {
666 - $stop['offset'] = $m[1]/100;
667 - if ($stop['offset']>1) { unset($stop['offset']); }
668 - }
669 - else if (isset($el[1]) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i',$el[1],$m)) {
670 - $tmp = $this->mpdf->ConvertSize($m[1],$this->mpdf->w,$this->mpdf->FontSize,false);
671 - $stop['offset'] = $el[1];
672 - }
673 - $g['stops'][] = $stop;
674 - }
675 - if (count($g['stops'] )) { return $g; }
676 - }
677 - return array();
678 -}
679 -
680 -function parseBackgroundGradient($bg) {
681 - // background-gradient: linear #00FFFF #FFFF00 0 0.5 1 0.5; or
682 - // background-gradient: radial #00FFFF #FFFF00 0.5 0.5 1 1 1.2;
683 -
684 - $v = trim($bg);
685 - $bgr = preg_split('/\s+/',$v);
686 - $g = array();
687 - if (count($bgr)> 6) {
688 - if (strtoupper(substr($bgr[0],0,1)) == 'L' && count($bgr)==7) { // linear
689 - $g['type'] = 2;
690 - //$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
691 - // Linear: $coords - array of the form (x1, y1, x2, y2) which defines the gradient vector (see linear_gradient_coords.jpg).
692 - // The default value is from left to right (x1=0, y1=0, x2=1, y2=0).
693 - $g['coords'] = array($bgr[3], $bgr[4], $bgr[5], $bgr[6]);
694 - }
695 - else if (count($bgr)==8) { // radial
696 - $g['type'] = 3;
697 - // Radial: $coords - array of the form (fx, fy, cx, cy, r) where (fx, fy) is the starting point of the gradient with color1,
698 - // (cx, cy) is the center of the circle with color2, and r is the radius of the circle (see radial_gradient_coords.jpg).
699 - // (fx, fy) should be inside the circle, otherwise some areas will not be defined
700 - $g['coords'] = array($bgr[3], $bgr[4], $bgr[5], $bgr[6], $bgr[7]);
701 - }
702 - $g['colorspace'] = 'RGB';
703 - // mPDF 5.3.74
704 - $cor = $this->mpdf->ConvertColor($bgr[1]);
705 - if ($cor{0}==1) $g['colorspace'] = 'Gray';
706 - else if ($cor{0}==4 || $cor{0}==6) $g['colorspace'] = 'CMYK';
707 - if ($cor) { $g['col'] = $cor; }
708 - else { $g['col'] = $this->mpdf->ConvertColor(255); }
709 - $cor = $this->mpdf->ConvertColor($bgr[2]);
710 - if ($cor) { $g['col2'] = $cor; }
711 - else { $g['col2'] = $this->mpdf->ConvertColor(255); }
712 - $g['extend'] = array('true','true');
713 - $g['stops'] = array(array('col'=>$g['col'], 'opacity'=>1, 'offset'=>0), array('col'=>$g['col2'], 'opacity'=>1, 'offset'=>1));
714 - return $g;
715 - }
716 - return false;
717 -}
718 -
719 -
720 -
721 -}
722 -
723 -?>
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 +}