1 <?php
2 
3 namespace jucksearm\barcode\lib;
4 
5 use jucksearm\barcode\lib\Barcode2D;
6 
7 class PDF417Factory
8 {
9 	private $_attributes;
10 	private $_borderPx = 1;
11 	private $_marginPx = 5;
12 	private $_scalePx = 1;
13 
14 	public function __construct()
15 	{
16 		$this->_attributes = [
17 			'code'   => null,
18 			'file'   => null,
19 			'size'   => 100,
20 			'margin' => 1,
21 			'color'  => '000',
22 		];
23 	}
24 
25 	public function __set($name, $value)
26 	{
27 		$setter = 'set' . $name;
28         if (method_exists($this, $setter)) {
29             // set property
30             $this->$setter($value);
31 
32             return;
33          }
34 	}
35 
36 	public function __get($name)
37 	{
38 		$getter = 'get' . $name;
39         if (method_exists($this, $getter)) {
40             // read property
41             return $this->$getter();
42         }
43 	}
44 
45 	public function setAttribute($name, $value)
46 	{
47 		if ($value === null) return;
48 
49 		$this->_attributes[$name] = $value;
50 	}
51 
52 	public function getAttribute($name)
53 	{
54 		return $this->_attributes[$name];
55 	}
56 
57 	public function setAttributes($attrs = [])
58 	{
59 		array_merge($this->_attributes, $attrs);
60 	}
61 
62 	public function getAttributes()
63 	{
64 		return $this->_attributes;
65 	}
66 
67 	public function setCode($value)
68 	{
69 		$this->setAttribute('code', $value);
70 		return $this;
71 	}
72 
73 	public function getCode()
74 	{
75 		return $this->getAttribute('code');
76 	}
77 
78 	public function setFile($value)
79 	{
80 		$this->setAttribute('file', $value);
81 		return $this;
82 	}
83 
84 	public function getFile()
85 	{
86 		return $this->getAttribute('file');
87 	}
88 
89 	public function setSize($value)
90 	{
91 		$this->setAttribute('size', $value);
92 		return $this;
93 	}
94 
95 	public function getSize()
96 	{
97 		return $this->getAttribute('size') * $this->_scalePx;
98 	}
99 
100 	public function setMargin($value)
101 	{
102 		$this->setAttribute('margin', $value);
103 		return $this;
104 	}
105 
106 	public function getMargin()
107 	{
108 		return $this->getAttribute('margin');
109 	}
110 
111 	public function setColor($value)
112 	{
113 		$this->setAttribute('color', $value);
114 		return $this;
115 	}
116 
117 	public function getColor()
118 	{
119 		return $this->getAttribute('color');
120 	}
121 
122 	public function getBarcode()
123 	{
124 		return new Barcode2D($this->code, 'PDF417');
125 	}
126 
127 	public function getHexColor()
128 	{
129 		$color = $this->color;
130 
131 		return '#'.$color;
132 	}
133 
134 	public function getRgbColor()
135 	{
136 		$color = $this->color;
137 
138 		if (strlen($color) > 3) {
139 			$r = hexdec(substr($color, 0, 2));
140 			$g = hexdec(substr($color, 2, 2));
141 			$b = hexdec(substr($color, 4, 2));
142 		} else {
143 			$r = hexdec(substr($color, 0, 1).substr($color, 0, 1));
144 			$g = hexdec(substr($color, 1, 1).substr($color, 1, 1));
145 			$b = hexdec(substr($color, 2, 1).substr($color, 2, 1));
146 		}
147 
148 		return [$r, $g, $b];
149 	}
150 
151 	private function getScale()
152 	{
153 		$scale = [];
154 		$bcd = $this->barcode->getBarcodeArray();
155 
156 		if ($this->size < $bcd['num_cols'])
157 			throw new \Exception('This size not render.');
158 
159 		if ($this->margin > 0) {
160 			$scale['frameX'] = $this->size - ($this->_borderPx * 2);
161 			$scale['margin'] = round($this->size * ($this->margin / 100));
162 			$scale['area'] = $scale['frameX'] - (($scale['margin'] * 2));
163 			$scale['size'] = floor($scale['area'] / $bcd['num_cols']);
164 			$scale['posX'] = $scale['margin'] + floor(($scale['area'] - ($bcd['num_cols'] * $scale['size'])) / 2);
165 			$scale['posY'] = $scale['posX'];
166 			$scale['frameY'] = ($bcd['num_rows'] * $scale['size']) + ($scale['posY'] * 2);
167 		} else {
168 			$scale['frameX'] = $this->size;
169 			$scale['margin'] = 0;
170 			$scale['area'] = $this->size;
171 			$scale['size'] = floor($scale['area'] / $bcd['num_cols']);
172 			$scale['posX'] = floor(($scale['frameX'] - ($bcd['num_cols'] * $scale['size'])) / 2);
173 			$scale['posY'] = $scale['posX'];
174 			$scale['frameY'] = ($bcd['num_rows'] * $scale['size']) + ($scale['posY'] * 2);
175 		}
176 // exit;
177 
178 
179 		return (object) $scale;
180 	}
181 
182 	public function getPDF417HtmlData()
183 	{
184 		$bcd = $this->barcode->getBarcodeArray();
185 		$color = $this->hexColor;
186 		$scale = $this->scale;
187 
188 		if ($this->margin > 0) {
189 			$pdf417Data = '<div style="position:absolute; border: solid '.$this->_borderPx.'px '.$this->hexColor.'; width:'.$scale->frameX.'px; height:'.$scale->frameY.'px">';
190 		} else {
191 			$pdf417Data = '<div style="position:absolute; width:'.$scale->frameX.'px; height:'.$scale->frameY.'px">';
192 		}
193 
194 		$pdf417Data .= '<div style="font-size:0;position:absolute; width:'.($scale->size * $bcd['num_cols']).'px;height:'.($scale->size * $bcd['num_rows']).'px; top:'.$scale->posY.'px; left:'.$scale->posX.'px" z-index:1;>'."\n";
195 
196 		$w = $scale->size;
197 		$h = $scale->size;
198 
199 		// print bars
200 		$y = 0;
201 		// for each row
202 		for ($r = 0; $r < $bcd['num_rows']; ++$r) {
203 			$x = 0;
204 			// for each column
205 			for ($c = 0; $c < $bcd['num_cols']; ++$c) {
206 				if ($bcd['bcode'][$r][$c] == 1) {
207 					// draw a single barcode cell
208 					$pdf417Data .= '<div style="background-color:'.$color.';width:'.$w.'px;height:'.$h.'px;position:absolute;left:'.$x.'px;top:'.$y.'px;">&nbsp;</div>'."\n";
209 				}
210 				$x += $w;
211 			}
212 			$y += $h;
213 		}
214 
215 		$pdf417Data .= '</div>'."\n";
216 
217 		$pdf417Data .= '</div>'."\n";
218 
219 		return $pdf417Data;
220 	}
221 
222 	public function getPDF417PngData()
223 	{
224 		$bcd = $this->barcode->getBarcodeArray();
225 		$this->_borderPx = 0;
226 		$color = $this->rgbColor;
227 		$scale = $this->scale;
228 
229 		$w = $bcd['num_cols'] * $scale->size;
230 		$h = $bcd['num_rows'] * $scale->size;
231 
232 		if (function_exists('imagecreate')) {
233 			$png = imagecreate($w, $h);
234 			$bgcol = imagecolorallocate($png, 255, 255, 255);
235 			imagecolortransparent($png, $bgcol);
236 			$fgcol = imagecolorallocate($png, $color[0], $color[1], $color[2]);
237 		} else {
238 			return false;
239 		}
240 
241 		// print bars
242 		$y = 0;
243 		// for each row
244 		for ($r = 0; $r < $bcd['num_rows']; ++$r) {
245 			$x = 0;
246 			// for each column
247 			for ($c = 0; $c < $bcd['num_cols']; ++$c) {
248 				if ($bcd['bcode'][$r][$c] == 1) {
249 					imagefilledrectangle($png, $x, $y, ($x + $scale->size - 1), ($y + $scale->size - 1), $fgcol);
250 				}
251 				$x += $scale->size;
252 			}
253 			$y += $scale->size;
254 		}
255 
256 		$frame = imagecreatetruecolor($scale->frameX, $scale->frameY);
257 		$blank = imagecreate($this->size, $this->size);
258 		imagecolorallocate($blank, 255, 255, 255);
259 		imagecopyresampled($frame, $blank, 0, 0, 0, 0, imagesx($blank), imagesy($blank), imagesx($blank), imagesy($blank));
260 		imagedestroy($blank);
261 		imagecopyresampled($frame, $png, $scale->posX, $scale->posY, 0, 0, imagesx($png), imagesy($png), imagesx($png), imagesy($png));
262 		imagedestroy($png);
263 
264 		if ($this->file === null) {
265 			ob_start();
266 			imagepng($frame);
267 			$pdf417Data = ob_get_clean();
268 		} else {
269 			preg_match("/\.png$/", $this->file, $output);
270 			if (count($output) == 0)
271 				throw new \Exception('Incorrect file extension format.');
272 
273 			$filePath = explode(DIRECTORY_SEPARATOR, $this->file);
274 			if (count($filePath) == 1 ) {
275 				$savePath = dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.$this->file;
276 			} else {
277 				$savePath = $this->file;
278 			}
279 
280 			if (!@imagepng($frame, $savePath))
281 				throw new \Exception('Not found save path.');
282 
283 			$pdf417Data = file_get_contents($savePath);
284 		}
285 
286 		imagedestroy($frame);
287 
288 		return $pdf417Data;
289 	}
290 
291 	public function getPDF417SvgData()
292 	{
293 		$bcd = $this->barcode->getBarcodeArray();
294 		$color = $this->hexColor;
295 		$scale = $this->scale;
296 
297 		$w = $bcd['num_cols'] * $scale->size;
298 		$h = $bcd['num_rows'] * $scale->size;
299 
300 		$repstr = array("\0" => '', '&' => '&amp;', '<' => '&lt;', '>' => '&gt;');
301 		$pdf417Data = '<'.'?'.'xml version="1.0" standalone="no"'.'?'.'>'."\n";
302 		$pdf417Data .= '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'."\n";
303 		$pdf417Data .= '<svg width="'.$scale->frameX.'" height="'.$scale->frameY.'" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">'."\n";
304 		$pdf417Data .= "\t".'<desc>'.strtr($bcd['code'], $repstr).'</desc>'."\n";
305 
306 		if ($this->margin > 0) {
307 			$pdf417Data .= "\t".'<g id="border" fill="none" stroke="'.$color.'">'."\n";
308 			$pdf417Data .= "\t\t".'<rect height="'.$scale->frameY.'" width="'.$scale->frameX.'" y="0" x="0" />'."\n";
309 			$pdf417Data .= "\t".'</g>'."\n";
310 		}
311 
312 		$pdf417Data .= "\t".'<g id="bars" fill="'.$color.'" stroke="none">'."\n";
313 		// print bars
314 		$y = $scale->posY;
315 		// for each row
316 		for ($r = 0; $r < $bcd['num_rows']; ++$r) {
317 			$x = $scale->posX;
318 			// for each column
319 			for ($c = 0; $c < $bcd['num_cols']; ++$c) {
320 				if ($bcd['bcode'][$r][$c] == 1) {
321 					// draw a single barcode cell
322 					$pdf417Data .= "\t\t".'<rect x="'.$x.'" y="'.$y.'" width="'.$scale->size.'" height="'.$scale->size.'" />'."\n";
323 				}
324 				$x += $scale->size;
325 			}
326 			$y += $scale->size;
327 		}
328 		$pdf417Data .= "\t".'</g>'."\n";
329 
330 		$pdf417Data .= '</svg>'."\n";
331 
332 		if ($this->file != null) {
333 			preg_match("/\.svg$/", $this->file, $output);
334 			if (count($output) == 0)
335 				throw new \Exception('Incorrect file extension format.');
336 
337 			$filePath = explode(DIRECTORY_SEPARATOR, $this->file);
338 			if (count($filePath) == 1 ) {
339 				$savePath = dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'tmp'.DIRECTORY_SEPARATOR.$this->file;
340 			} else {
341 				$savePath = $this->file;
342 			}
343 
344 			if (!@file_put_contents($savePath, $pdf417Data))
345 				throw new \Exception('Not found save path.');
346 		}
347 
348 		return $pdf417Data;
349 	}
350 
351 	public function renderHTML()
352 	{
353 		$pdf417Data = $this->getPDF417HtmlData();
354 
355 		header('Content-Type: text/html');
356 		header('Content-Length: '.strlen($pdf417Data));
357 		header('Cache-Control: no-cache');
358 		header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
359 
360 		echo $pdf417Data;
361 	}
362 
363 	public function renderPNG()
364 	{
365 		$pdf417Data = $this->getPDF417PngData();
366 
367 		header('Content-Type: image/png');
368 		header('Content-Length: '.strlen($pdf417Data));
369 		header('Cache-Control: no-cache');
370 		header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
371 
372 		echo $pdf417Data;
373 	}
374 
375 	public function renderSVG()
376 	{
377 		$pdf417Data = $this->getPDF417SvgData();
378 
379 		header('Content-Type: image/svg+xml');
380 		header('Content-Length: '.strlen($pdf417Data));
381 		header('Cache-Control: no-cache');
382 		header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
383 
384 		echo $pdf417Data;
385 	}
386 }