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