1<?php
2
3namespace Mpdf\Barcode;
4
5/**
6 * Interleaved 2 of 5 barcodes.
7 * Compact numeric code, widely used in industry, air cargo
8 * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
9 */
10class I25 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\BarcodeInterface
11{
12
13	/**
14	 * @param string $code
15	 * @param float $topBottomMargin
16	 * @param float $printRatio
17	 * @param bool $checksum
18	 */
19	public function __construct($code, $topBottomMargin, $printRatio, $checksum = false, $quiet_zone_left = null, $quiet_zone_right = null)
20	{
21		$this->init($code, $printRatio, $checksum);
22
23		$this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
24		$this->data['nom-H'] = 10;  // Nominal value for Height of Full bar in mm (non-spec.)
25		$this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 10); // LEFT light margin =  x X-dim (spec.)
26		$this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 10); // RIGHT light margin =  x X-dim (spec.)
27		$this->data['lightTB'] = $topBottomMargin; // TOP/BOTTOM light margin =  x X-dim (non-spec.)
28	}
29
30	/**
31	 * @param string $code
32	 * @param float $printRatio
33	 * @param bool $checksum
34	 */
35	private function init($code, $printRatio, $checksum)
36	{
37		$chr = [
38			'0' => '11221',
39			'1' => '21112',
40			'2' => '12112',
41			'3' => '22111',
42			'4' => '11212',
43			'5' => '21211',
44			'6' => '12211',
45			'7' => '11122',
46			'8' => '21121',
47			'9' => '12121',
48			'A' => '11',
49			'Z' => '21',
50		];
51
52		$checkdigit = '';
53		if ($checksum) {
54			// add checksum
55			$checkdigit = $this->checksum($code);
56			$code .= $checkdigit;
57		}
58		if ((strlen($code) % 2) != 0) {
59			// add leading zero if code-length is odd
60			$code = '0' . $code;
61		}
62		// add start and stop codes
63		$code = 'AA' . strtolower($code) . 'ZA';
64
65		$bararray = ['code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => []];
66		$k = 0;
67		$clen = strlen($code);
68		for ($i = 0; $i < $clen; $i = ($i + 2)) {
69			$charBar = $code[$i];
70			$charSpace = $code[$i + 1];
71			if ((!isset($chr[$charBar])) or (!isset($chr[$charSpace]))) {
72				// invalid character
73				throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid I25 barcode value "%s"', $code));
74			}
75			// create a bar-space sequence
76			$seq = '';
77			$chrlen = strlen($chr[$charBar]);
78			for ($s = 0; $s < $chrlen; $s++) {
79				$seq .= $chr[$charBar][$s] . $chr[$charSpace][$s];
80			}
81			$seqlen = strlen($seq);
82			for ($j = 0; $j < $seqlen; ++$j) {
83				if (($j % 2) == 0) {
84					$t = true; // bar
85				} else {
86					$t = false; // space
87				}
88				$x = $seq[$j];
89				if ($x == 2) {
90					$w = $printRatio;
91				} else {
92					$w = 1;
93				}
94
95				$bararray['bcode'][$k] = ['t' => $t, 'w' => $w, 'h' => 1, 'p' => 0];
96				$bararray['maxw'] += $w;
97				++$k;
98			}
99		}
100		$bararray['checkdigit'] = $checkdigit;
101
102		$this->data = $bararray;
103	}
104
105	/**
106	 * Checksum for standard 2 of 5 barcodes.
107	 *
108	 * @param string $code
109	 * @return int
110	 */
111	private function checksum($code)
112	{
113		$len = strlen($code);
114		$sum = 0;
115		for ($i = 0; $i < $len; $i += 2) {
116			$sum += $code[$i];
117		}
118		$sum *= 3;
119		for ($i = 1; $i < $len; $i += 2) {
120			$sum += ($code[$i]);
121		}
122		$r = $sum % 10;
123		if ($r > 0) {
124			$r = (10 - $r);
125		}
126		return $r;
127	}
128
129	/**
130	 * @inheritdoc
131	 */
132	public function getType()
133	{
134		return 'I25';
135	}
136
137}
138