1<?php
2
3namespace Mpdf\Barcode;
4
5/**
6 * CODE11 barcodes.
7 * Used primarily for labeling telecommunications equipment
8 */
9class Code11 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\BarcodeInterface
10{
11
12	/**
13	 * @param string $code
14	 * @param float $printRatio
15	 */
16	public function __construct($code, $printRatio)
17	{
18		$this->init($code, $printRatio);
19
20		$this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
21		$this->data['nom-H'] = 10;  // Nominal value for Height of Full bar in mm (non-spec.)
22		$this->data['lightmL'] = 10; // LEFT light margin =  x X-dim (spec.)
23		$this->data['lightmR'] = 10; // RIGHT light margin =  x X-dim (spec.)
24		$this->data['lightTB'] = 0; // TOP/BOTTOM light margin =  x X-dim (non-spec.)
25	}
26
27	/**
28	 * @param string $code
29	 * @param float $printRatio
30	 */
31	private function init($code, $printRatio)
32	{
33		$chr = [
34			'0' => '111121',
35			'1' => '211121',
36			'2' => '121121',
37			'3' => '221111',
38			'4' => '112121',
39			'5' => '212111',
40			'6' => '122111',
41			'7' => '111221',
42			'8' => '211211',
43			'9' => '211111',
44			'-' => '112111',
45			'S' => '112211'
46		];
47
48		$bararray = ['code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => []];
49
50		$k = 0;
51
52		$len = strlen($code);
53		// calculate check digit C
54
55		$p = 1;
56		$check = 0;
57
58		for ($i = ($len - 1); $i >= 0; --$i) {
59			$digit = $code[$i];
60			if ($digit == '-') {
61				$dval = 10;
62			} else {
63				$dval = (int) $digit;
64			}
65			$check += ($dval * $p);
66			++$p;
67			if ($p > 10) {
68				$p = 1;
69			}
70		}
71
72		$check %= 11;
73
74		if ($check == 10) {
75			$check = '-';
76		}
77
78		$code .= $check;
79		$checkdigit = $check;
80
81		if ($len > 10) {
82			// calculate check digit K
83			$p = 1;
84			$check = 0;
85			for ($i = $len; $i >= 0; --$i) {
86				$digit = $code[$i];
87				if ($digit == '-') {
88					$dval = 10;
89				} else {
90					$dval = (int) $digit;
91				}
92				$check += ($dval * $p);
93				++$p;
94				if ($p > 9) {
95					$p = 1;
96				}
97			}
98			$check %= 11;
99			$code .= $check;
100			$checkdigit .= $check;
101			++$len;
102		}
103
104		$code = 'S' . $code . 'S';
105		$len += 3;
106
107		for ($i = 0; $i < $len; ++$i) {
108			if (!isset($chr[$code[$i]])) {
109				throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE11 barcode value', $code[$i]));
110			}
111			$seq = $chr[$code[$i]];
112			for ($j = 0; $j < 6; ++$j) {
113				if (($j % 2) == 0) {
114					$t = true; // bar
115				} else {
116					$t = false; // space
117				}
118				$x = $seq[$j];
119				if ($x == 2) {
120					$w = $printRatio;
121				} else {
122					$w = 1;
123				}
124				$bararray['bcode'][$k] = ['t' => $t, 'w' => $w, 'h' => 1, 'p' => 0];
125				$bararray['maxw'] += $w;
126				++$k;
127			}
128		}
129
130		$bararray['checkdigit'] = $checkdigit;
131
132		$this->data = $bararray;
133	}
134
135	/**
136	 * @inheritdoc
137	 */
138	public function getType()
139	{
140		return 'CODE11';
141	}
142
143}
144