3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Barcode\
Object;
13 * Class for generate Code128 barcode
15 class Code128
extends AbstractObject
19 * (even if it's sometime optional, most of time it's required)
22 protected $withChecksum = true;
27 protected $convertedText = array();
29 protected $codingMap = array(
30 0 => "11011001100", 1 => "11001101100", 2 => "11001100110",
31 3 => "10010011000", 4 => "10010001100", 5 => "10001001100",
32 6 => "10011001000", 7 => "10011000100", 8 => "10001100100",
33 9 => "11001001000", 10 => "11001000100", 11 => "11000100100",
34 12 => "10110011100", 13 => "10011011100", 14 => "10011001110",
35 15 => "10111001100", 16 => "10011101100", 17 => "10011100110",
36 18 => "11001110010", 19 => "11001011100", 20 => "11001001110",
37 21 => "11011100100", 22 => "11001110100", 23 => "11101101110",
38 24 => "11101001100", 25 => "11100101100", 26 => "11100100110",
39 27 => "11101100100", 28 => "11100110100", 29 => "11100110010",
40 30 => "11011011000", 31 => "11011000110", 32 => "11000110110",
41 33 => "10100011000", 34 => "10001011000", 35 => "10001000110",
42 36 => "10110001000", 37 => "10001101000", 38 => "10001100010",
43 39 => "11010001000", 40 => "11000101000", 41 => "11000100010",
44 42 => "10110111000", 43 => "10110001110", 44 => "10001101110",
45 45 => "10111011000", 46 => "10111000110", 47 => "10001110110",
46 48 => "11101110110", 49 => "11010001110", 50 => "11000101110",
47 51 => "11011101000", 52 => "11011100010", 53 => "11011101110",
48 54 => "11101011000", 55 => "11101000110", 56 => "11100010110",
49 57 => "11101101000", 58 => "11101100010", 59 => "11100011010",
50 60 => "11101111010", 61 => "11001000010", 62 => "11110001010",
51 63 => "10100110000", 64 => "10100001100", 65 => "10010110000",
52 66 => "10010000110", 67 => "10000101100", 68 => "10000100110",
53 69 => "10110010000", 70 => "10110000100", 71 => "10011010000",
54 72 => "10011000010", 73 => "10000110100", 74 => "10000110010",
55 75 => "11000010010", 76 => "11001010000", 77 => "11110111010",
56 78 => "11000010100", 79 => "10001111010", 80 => "10100111100",
57 81 => "10010111100", 82 => "10010011110", 83 => "10111100100",
58 84 => "10011110100", 85 => "10011110010", 86 => "11110100100",
59 87 => "11110010100", 88 => "11110010010", 89 => "11011011110",
60 90 => "11011110110", 91 => "11110110110", 92 => "10101111000",
61 93 => "10100011110", 94 => "10001011110", 95 => "10111101000",
62 96 => "10111100010", 97 => "11110101000", 98 => "11110100010",
63 99 => "10111011110", 100 => "10111101110", 101 => "11101011110",
65 103 => "11010000100", 104 => "11010010000", 105 => "11010011100",
66 106 => "1100011101011");
72 protected $charSets = array(
74 ' ', '!', '"', '#', '$', '%', '&', "'",
75 '(', ')', '*', '+', ',', '-', '.', '/',
76 '0', '1', '2', '3', '4', '5', '6', '7',
77 '8', '9', ':', ';', '<', '=', '>', '?',
78 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
79 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
80 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
81 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
82 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
83 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
84 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
85 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
86 'FNC3', 'FNC2', 'SHIFT', 'Code C', 'Code B', 'FNC4', 'FNC1',
87 'START A', 'START B', 'START C', 'STOP'),
89 ' ', '!', '"', '#', '$', '%', '&', "'",
90 '(', ')', '*', '+', ',', '-', '.', '/',
91 '0', '1', '2', '3', '4', '5', '6', '7',
92 '8', '9', ':', ';', '<', '=', '>', '?',
93 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
94 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
95 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
96 'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
97 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
98 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
99 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
100 'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
101 'FNC3', 'FNC2', 'SHIFT', 'Code C', 'FNC4', 'Code A', 'FNC1',
102 'START A', 'START B', 'START C', 'STOP',),
104 '00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
105 '10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
106 '20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
107 '30', '31', '32', '33', '34', '35', '36', '37', '38', '39',
108 '40', '41', '42', '43', '44', '45', '46', '47', '48', '49',
109 '50', '51', '52', '53', '54', '55', '56', '57', '58', '59',
110 '60', '61', '62', '63', '64', '65', '66', '67', '68', '69',
111 '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
112 '80', '81', '82', '83', '84', '85', '86', '87', '88', '89',
113 '90', '91', '92', '93', '94', '95', '96', '97', '98', '99',
114 'Code B', 'Code A', 'FNC1', 'START A', 'START B', 'START C', 'STOP'));
117 * Width of the barcode (in pixels)
120 protected function calculateBarcodeWidth()
122 $quietZone = $this->getQuietZone();
123 // Each characters contain 11 bars...
124 $characterLength = 11 * $this->barThinWidth
* $this->factor
;
125 $convertedChars = count($this->convertToBarcodeChars($this->getText()));
126 if ($this->withChecksum
) {
129 $encodedData = $convertedChars * $characterLength;
130 // ...except the STOP character (13)
131 $encodedData +
= $characterLength +
2 * $this->barThinWidth
* $this->factor
;
132 $width = $quietZone +
$encodedData +
$quietZone;
137 * Partial check of code128 barcode
140 protected function checkSpecificParams()
145 * Prepare array to draw barcode
148 protected function prepareBarcode()
150 $barcodeTable = array();
152 $convertedChars = $this->convertToBarcodeChars($this->getText());
154 if ($this->withChecksum
) {
155 $convertedChars[] = $this->getChecksum($this->getText());
159 $convertedChars[] = 106;
161 foreach ($convertedChars as $barcodeChar) {
162 $barcodePattern = $this->codingMap
[$barcodeChar];
163 foreach (str_split($barcodePattern) as $c) {
164 $barcodeTable[] = array($c, $this->barThinWidth
, 0, 1);
167 return $barcodeTable;
171 * Checks if the next $length chars of $string starting at $pos are numeric.
172 * Returns false if the end of the string is reached.
173 * @param string $string String to search
174 * @param int $pos Starting position
175 * @param int $length Length to search
178 protected static function _isDigit($string, $pos, $length = 2)
180 if ($pos +
$length > strlen($string)) {
184 for ($i = $pos; $i < $pos +
$length; $i++
) {
185 if (!is_numeric($string[$i])) {
193 * Convert string to barcode string
194 * @param string $string
197 protected function convertToBarcodeChars($string)
199 $string = (string) $string;
200 if (!strlen($string)) {
204 if (isset($this->convertedText
[md5($string)])) {
205 return $this->convertedText
[md5($string)];
208 $currentCharset = null;
211 for ($pos = 0; $pos < strlen($string); $pos++
) {
212 $char = $string[$pos];
215 if (static::_isDigit($string, $pos, 4) && $currentCharset != 'C'
216 ||
static::_isDigit($string, $pos, 2) && $currentCharset == 'C') {
218 * Switch to C if the next 4 chars are numeric or stay C if the next 2
221 if ($currentCharset != 'C') {
223 $code = array_search("START C", $this->charSets
['C']);
225 $code = array_search("Code C", $this->charSets
[$currentCharset]);
228 $currentCharset = 'C';
230 } elseif (in_array($char, $this->charSets
['B']) && $currentCharset != 'B'
231 && !(in_array($char, $this->charSets
['A']) && $currentCharset == 'A')) {
233 * Switch to B as B contains the char and B is not the current charset.
236 $code = array_search("START B", $this->charSets
['B']);
238 $code = array_search("Code B", $this->charSets
[$currentCharset]);
241 $currentCharset = 'B';
242 } elseif (array_key_exists($char, $this->charSets
['A']) && $currentCharset != 'A'
243 && !(array_key_exists($char, $this->charSets
['B']) && $currentCharset == 'B')) {
245 * Switch to C as C contains the char and C is not the current charset.
248 $code = array_search("START A", $this->charSets
['A']);
250 $code =array_search("Code A", $this->charSets
[$currentCharset]);
253 $currentCharset = 'A';
256 if ($currentCharset == 'C') {
257 $code = array_search(substr($string, $pos, 2), $this->charSets
['C']);
258 $pos++
; //Two chars from input
260 $code = array_search($string[$pos], $this->charSets
[$currentCharset]);
265 $this->convertedText
[md5($string)] = $result;
271 * @param string $value
274 public function setText($value)
276 $this->text
= $value;
281 * Retrieve text to encode
284 public function getText()
290 * Get barcode checksum
292 * @param string $text
295 public function getChecksum($text)
297 $tableOfChars = $this->convertToBarcodeChars($text);
299 $sum = $tableOfChars[0];
300 unset($tableOfChars[0]);
303 foreach ($tableOfChars as $char) {
304 $sum +
= ($k++
) * $char;
307 $checksum = $sum %
103;