| @@ -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 | +} | |