File indexing completed on 2025-03-02 05:29:11
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Barcode 0017 * @subpackage Object 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id: Code25.php 20096 2010-01-06 02:05:09Z bkarwin $ 0021 */ 0022 0023 /** 0024 * @see Zend_Barcode_Object_ObjectAbstract 0025 */ 0026 // require_once 'Zend/Barcode/Object/ObjectAbstract.php'; 0027 0028 /** 0029 * @see Zend_Validate_Barcode 0030 */ 0031 // require_once 'Zend/Validate/Barcode.php'; 0032 0033 /** 0034 * Class for generate Code128 barcode 0035 * 0036 * @category Zend 0037 * @package Zend_Barcode 0038 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0039 * @license http://framework.zend.com/license/new-bsd New BSD License 0040 */ 0041 class Zend_Barcode_Object_Code128 extends Zend_Barcode_Object_ObjectAbstract 0042 { 0043 /** 0044 * Drawing of checksum 0045 * (even if it's sometime optional, most of time it's required) 0046 * @var boolean 0047 */ 0048 protected $_withChecksum = true; 0049 0050 /** 0051 * @var array 0052 */ 0053 protected $_convertedText = array(); 0054 0055 protected $_codingMap = array( 0056 0 => "11011001100", 1 => "11001101100", 2 => "11001100110", 0057 3 => "10010011000", 4 => "10010001100", 5 => "10001001100", 0058 6 => "10011001000", 7 => "10011000100", 8 => "10001100100", 0059 9 => "11001001000", 10 => "11001000100", 11 => "11000100100", 0060 12 => "10110011100", 13 => "10011011100", 14 => "10011001110", 0061 15 => "10111001100", 16 => "10011101100", 17 => "10011100110", 0062 18 => "11001110010", 19 => "11001011100", 20 => "11001001110", 0063 21 => "11011100100", 22 => "11001110100", 23 => "11101101110", 0064 24 => "11101001100", 25 => "11100101100", 26 => "11100100110", 0065 27 => "11101100100", 28 => "11100110100", 29 => "11100110010", 0066 30 => "11011011000", 31 => "11011000110", 32 => "11000110110", 0067 33 => "10100011000", 34 => "10001011000", 35 => "10001000110", 0068 36 => "10110001000", 37 => "10001101000", 38 => "10001100010", 0069 39 => "11010001000", 40 => "11000101000", 41 => "11000100010", 0070 42 => "10110111000", 43 => "10110001110", 44 => "10001101110", 0071 45 => "10111011000", 46 => "10111000110", 47 => "10001110110", 0072 48 => "11101110110", 49 => "11010001110", 50 => "11000101110", 0073 51 => "11011101000", 52 => "11011100010", 53 => "11011101110", 0074 54 => "11101011000", 55 => "11101000110", 56 => "11100010110", 0075 57 => "11101101000", 58 => "11101100010", 59 => "11100011010", 0076 60 => "11101111010", 61 => "11001000010", 62 => "11110001010", 0077 63 => "10100110000", 64 => "10100001100", 65 => "10010110000", 0078 66 => "10010000110", 67 => "10000101100", 68 => "10000100110", 0079 69 => "10110010000", 70 => "10110000100", 71 => "10011010000", 0080 72 => "10011000010", 73 => "10000110100", 74 => "10000110010", 0081 75 => "11000010010", 76 => "11001010000", 77 => "11110111010", 0082 78 => "11000010100", 79 => "10001111010", 80 => "10100111100", 0083 81 => "10010111100", 82 => "10010011110", 83 => "10111100100", 0084 84 => "10011110100", 85 => "10011110010", 86 => "11110100100", 0085 87 => "11110010100", 88 => "11110010010", 89 => "11011011110", 0086 90 => "11011110110", 91 => "11110110110", 92 => "10101111000", 0087 93 => "10100011110", 94 => "10001011110", 95 => "10111101000", 0088 96 => "10111100010", 97 => "11110101000", 98 => "11110100010", 0089 99 => "10111011110", 100 => "10111101110", 101 => "11101011110", 0090 102 => "11110101110", 0091 103 => "11010000100", 104 => "11010010000", 105 => "11010011100", 0092 106 => "1100011101011"); 0093 0094 /** 0095 * Character sets ABC 0096 * @var array 0097 */ 0098 protected $_charSets = array( 0099 'A' => array( 0100 ' ', '!', '"', '#', '$', '%', '&', "'", 0101 '(', ')', '*', '+', ',', '-', '.', '/', 0102 '0', '1', '2', '3', '4', '5', '6', '7', 0103 '8', '9', ':', ';', '<', '=', '>', '?', 0104 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 0105 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 0106 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 0107 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', 0108 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0109 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0110 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0111 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0112 'FNC3', 'FNC2', 'SHIFT', 'Code C', 'Code B', 'FNC4', 'FNC1', 0113 'START A', 'START B', 'START C', 'STOP'), 0114 'B' => array( 0115 ' ', '!', '"', '#', '$', '%', '&', "'", 0116 '(', ')', '*', '+', ',', '-', '.', '/', 0117 '0', '1', '2', '3', '4', '5', '6', '7', 0118 '8', '9', ':', ';', '<', '=', '>', '?', 0119 '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 0120 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 0121 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 0122 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', 0123 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 0124 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 0125 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 0126 'x', 'y', 'z', '{', '|', '}', '~', 0x7F, 0127 'FNC3', 'FNC2', 'SHIFT', 'Code C', 'FNC4', 'Code A', 'FNC1', 0128 'START A', 'START B', 'START C', 'STOP',), 0129 'C' => array( 0130 '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', 0131 '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', 0132 '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', 0133 '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', 0134 '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', 0135 '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', 0136 '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', 0137 '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', 0138 '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', 0139 '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', 0140 'Code B', 'Code A', 'FNC1', 'START A', 'START B', 'START C', 'STOP')); 0141 /*'A' => array( 0142 ' '=>0, '!'=>1, '"'=>2, '#'=>3, '$'=>4, '%'=>5, '&'=>6, "'"=>7, 0143 '('=>8, ')'=>9, '*'=>10, '+'=>11, ','=>12, '-'=>13, '.'=>14, '/'=>15, 0144 '0'=>16, '1'=>17, '2'=>18, '3'=>19, '4'=>20, '5'=>21, '6'=>22, '7'=>23, 0145 '8'=>24, '9'=>25, ':'=>26, ';'=>27, '<'=>28, '='=>29, '>'=>30, '?'=>31, 0146 '@'=>32, 'A'=>33, 'B'=>34, 'C'=>35, 'D'=>36, 'E'=>37, 'F'=>38, 'G'=>39, 0147 'H'=>40, 'I'=>41, 'J'=>42, 'K'=>43, 'L'=>44, 'M'=>45, 'N'=>46, 'O'=>47, 0148 'P'=>48, 'Q'=>49, 'R'=>50, 'S'=>51, 'T'=>52, 'U'=>53, 'V'=>54, 'W'=>55, 0149 'X'=>56, 'Y'=>57, 'Z'=>58, '['=>59, '\\'=>60, ']'=>61, '^'=>62, '_'=>63, 0150 0x00=>64, 0x01=>65, 0x02=>66, 0x03=>67, 0x04=>68, 0x05=>69, 0x06=>70, 0x07=>71, 0151 0x08=>72, 0x09=>73, 0x0A=>74, 0x0B=>75, 0x0C=>76, 0x0D=>77, 0x0E=>78, 0x0F=>79, 0152 0x10=>80, 0x11=>81, 0x12=>82, 0x13=>83, 0x14=>84, 0x15=>85, 0x16=>86, 0x17=>87, 0153 0x18=>88, 0x19=>89, 0x1A=>90, 0x1B=>91, 0x1C=>92, 0x1D=>93, 0x1E=>94, 0x1F=>95, 0154 'FNC3'=>96, 'FNC2'=>97, 'SHIFT'=>98, 'Code C'=>99, 'Code B'=>100, 'FNC4'=>101, 'FNC1'=>102, 'START A'=>103, 0155 'START B'=>104, 'START C'=>105, 'STOP'=>106), 0156 'B' => array( 0157 ' '=>0, '!'=>1, '"'=>2, '#'=>3, '$'=>4, '%'=>5, '&'=>6, "'"=>7, 0158 '('=>8, ')'=>9, '*'=>10, '+'=>11, ','=>12, '-'=>13, '.'=>14, '/'=>15, 0159 '0'=>16, '1'=>17, '2'=>18, '3'=>19, '4'=>20, '5'=>21, '6'=>22, '7'=>23, 0160 '8'=>24, '9'=>25, ':'=>26, ';'=>27, '<'=>28, '='=>29, '>'=>30, '?'=>31, 0161 '@'=>32, 'A'=>33, 'B'=>34, 'C'=>35, 'D'=>36, 'E'=>37, 'F'=>38, 'G'=>39, 0162 'H'=>40, 'I'=>41, 'J'=>42, 'K'=>43, 'L'=>44, 'M'=>45, 'N'=>46, 'O'=>47, 0163 'P'=>48, 'Q'=>49, 'R'=>50, 'S'=>51, 'T'=>52, 'U'=>53, 'V'=>54, 'W'=>55, 0164 'X'=>56, 'Y'=>57, 'Z'=>58, '['=>59, '\\'=>60, ']'=>61, '^'=>62, '_'=>63, 0165 '`' =>64, 'a'=>65, 'b'=>66, 'c'=>67, 'd'=>68, 'e'=>69, 'f'=>70, 'g'=>71, 0166 'h'=>72, 'i'=>73, 'j'=>74, 'k'=>75, 'l'=>76, 'm'=>77, 'n'=>78, 'o'=>79, 0167 'p'=>80, 'q'=>81, 'r'=>82, 's'=>83, 't'=>84, 'u'=>85, 'v'=>86, 'w'=>87, 0168 'x'=>88, 'y'=>89, 'z'=>90, '{'=>91, '|'=>92, '}'=>93, '~'=>94, 0x7F=>95, 0169 'FNC3'=>96, 'FNC2'=>97, 'SHIFT'=>98, 'Code C'=>99, 'FNC4'=>100, 'Code A'=>101, 'FNC1'=>102, 'START A'=>103, 0170 'START B'=>104, 'START C'=>105, 'STOP'=>106,), 0171 'C' => array( 0172 '00'=>0, '01'=>1, '02'=>2, '03'=>3, '04'=>4, '05'=>5, '06'=>6, '07'=>7, '08'=>8, '09'=>9, 0173 '10'=>10, '11'=>11, '12'=>12, '13'=>13, '14'=>14, '15'=>15, '16'=>16, '17'=>17, '18'=>18, '19'=>19, 0174 '20'=>20, '21'=>21, '22'=>22, '23'=>23, '24'=>24, '25'=>25, '26'=>26, '27'=>27, '28'=>28, '29'=>29, 0175 '30'=>30, '31'=>31, '32'=>32, '33'=>33, '34'=>34, '35'=>35, '36'=>36, '37'=>37, '38'=>38, '39'=>39, 0176 '40'=>40, '41'=>41, '42'=>42, '43'=>43, '44'=>44, '45'=>45, '46'=>46, '47'=>47, '48'=>48, '49'=>49, 0177 '50'=>50, '51'=>51, '52'=>52, '53'=>53, '54'=>54, '55'=>55, '56'=>56, '57'=>57, '58'=>58, '59'=>59, 0178 '60'=>60, '61'=>61, '62'=>62, '63'=>63, '64'=>64, '65'=>65, '66'=>66, '67'=>67, '68'=>68, '69'=>69, 0179 '70'=>70, '71'=>71, '72'=>72, '73'=>73, '74'=>74, '75'=>75, '76'=>76, '77'=>77, '78'=>78, '79'=>79, 0180 '80'=>80, '81'=>81, '82'=>82, '83'=>83, '84'=>84, '85'=>85, '86'=>86, '87'=>87, '88'=>88, '89'=>89, 0181 '90'=>90, '91'=>91, '92'=>92, '93'=>93, '94'=>94, '95'=>95, '96'=>96, '97'=>97, '98'=>98, '99'=>99, 0182 'Code B'=>100, 'Code A'=>101, 'FNC1'=>102, 'START A'=>103, 'START B'=>104, 'START C'=>105, 'STOP'=>106));*/ 0183 0184 /** 0185 * Width of the barcode (in pixels) 0186 * @return integer 0187 */ 0188 protected function _calculateBarcodeWidth() 0189 { 0190 $quietZone = $this->getQuietZone(); 0191 // Each characters contain 11 bars... 0192 $characterLength = 11 * $this->_barThinWidth * $this->_factor; 0193 $convertedChars = count($this->_convertToBarcodeChars($this->getText())); 0194 if ($this->_withChecksum) { 0195 $convertedChars++; 0196 } 0197 $encodedData = $convertedChars * $characterLength; 0198 // ...except the STOP character (13) 0199 $encodedData += $characterLength + 2 * $this->_barThinWidth * $this->_factor; 0200 $width = $quietZone + $encodedData + $quietZone; 0201 return $width; 0202 } 0203 0204 /** 0205 * Partial check of code128 barcode 0206 * @return void 0207 */ 0208 protected function _checkParams() 0209 { 0210 } 0211 0212 /** 0213 * Prepare array to draw barcode 0214 * @return array 0215 */ 0216 protected function _prepareBarcode() 0217 { 0218 $barcodeTable = array(); 0219 0220 $convertedChars = $this->_convertToBarcodeChars($this->getText()); 0221 0222 if ($this->_withChecksum) { 0223 $convertedChars[] = $this->getChecksum($this->getText()); 0224 } 0225 0226 // STOP CHARACTER 0227 $convertedChars[] = 106; 0228 0229 foreach ($convertedChars as $barcodeChar) { 0230 $barcodePattern = $this->_codingMap[$barcodeChar]; 0231 foreach (str_split($barcodePattern) as $c) { 0232 $barcodeTable[] = array($c, $this->_barThinWidth, 0, 1); 0233 } 0234 } 0235 return $barcodeTable; 0236 } 0237 0238 /** 0239 * Checks if the next $length chars of $string starting at $pos are numeric. 0240 * Returns false if the end of the string is reached. 0241 * @param string $string String to search 0242 * @param int $pos Starting position 0243 * @param int $length Length to search 0244 * @return bool 0245 */ 0246 protected static function _isDigit($string, $pos, $length = 2) 0247 { 0248 if ($pos + $length > strlen($string)) { 0249 return false; 0250 } 0251 0252 for ($i = $pos; $i < $pos + $length; $i++) { 0253 if (!is_numeric($string[$i])) { 0254 return false; 0255 } 0256 } 0257 return true; 0258 } 0259 0260 /** 0261 * Convert string to barcode string 0262 * 0263 * @param $string 0264 * @return array 0265 */ 0266 protected function _convertToBarcodeChars($string) 0267 { 0268 $string = (string) $string; 0269 if (!strlen($string)) { 0270 return array(); 0271 } 0272 0273 if (isset($this->_convertedText[md5($string)])) { 0274 return $this->_convertedText[md5($string)]; 0275 } 0276 0277 $currentCharset = null; 0278 $sum = 0; 0279 $fak = 0; 0280 $result = array(); 0281 0282 for ($pos = 0; $pos < strlen($string); $pos++) { 0283 $char = $string[$pos]; 0284 $code = null; 0285 0286 if (self::_isDigit($string, $pos, 4) && $currentCharset != 'C' 0287 || self::_isDigit($string, $pos, 2) && $currentCharset == 'C') { 0288 /** 0289 * Switch to C if the next 4 chars are numeric or stay C if the next 2 0290 * chars are numeric 0291 */ 0292 if ($currentCharset != 'C') { 0293 if ($pos == 0) { 0294 $code = array_search("START C", $this->_charSets['C']); 0295 } else { 0296 $code = array_search("Code C", $this->_charSets[$currentCharset]); 0297 } 0298 $result[] = $code; 0299 $currentCharset = 'C'; 0300 } 0301 } else if (in_array($char, $this->_charSets['B']) && $currentCharset != 'B' 0302 && !(in_array($char, $this->_charSets['A']) && $currentCharset == 'A')) { 0303 /** 0304 * Switch to B as B contains the char and B is not the current charset. 0305 */ 0306 if ($pos == 0) { 0307 $code = array_search("START B", $this->_charSets['B']); 0308 } else { 0309 $code = array_search("Code B", $this->_charSets[$currentCharset]); 0310 } 0311 $result[] = $code; 0312 $currentCharset = 'B'; 0313 } else if (array_key_exists($char, $this->_charSets['A']) && $currentCharset != 'A' 0314 && !(array_key_exists($char, $this->_charSets['B']) && $currentCharset == 'B')) { 0315 /** 0316 * Switch to C as C contains the char and C is not the current charset. 0317 */ 0318 if ($pos == 0) { 0319 $code = array_search("START A", $this->_charSets['A']); 0320 } else { 0321 $code =array_search("Code A", $this->_charSets[$currentCharset]); 0322 } 0323 $result[] = $code; 0324 $currentCharset = 'A'; 0325 } 0326 0327 if ($currentCharset == 'C') { 0328 $code = array_search(substr($string, $pos, 2), $this->_charSets['C']); 0329 $pos++; //Two chars from input 0330 } else { 0331 $code = array_search($string[$pos], $this->_charSets[$currentCharset]); 0332 } 0333 $result[] = $code; 0334 } 0335 0336 $this->_convertedText[md5($string)] = $result; 0337 return $result; 0338 } 0339 0340 /** 0341 * Set text to encode 0342 * @param string $value 0343 * @return Zend_Barcode_Object 0344 */ 0345 public function setText($value) 0346 { 0347 $this->_text = $value; 0348 return $this; 0349 } 0350 0351 /** 0352 * Retrieve text to encode 0353 * @return string 0354 */ 0355 public function getText() 0356 { 0357 return $this->_text; 0358 } 0359 0360 /** 0361 * Get barcode checksum 0362 * 0363 * @param string $text 0364 * @return int 0365 */ 0366 public function getChecksum($text) 0367 { 0368 $tableOfChars = $this->_convertToBarcodeChars($text); 0369 0370 $sum = $tableOfChars[0]; 0371 unset($tableOfChars[0]); 0372 0373 $k = 1; 0374 foreach ($tableOfChars as $char) { 0375 $sum += ($k++) * $char; 0376 } 0377 0378 $checksum = $sum % 103; 0379 0380 return $checksum; 0381 } 0382 0383 /** 0384 * Standard validation for most of barcode objects 0385 * 0386 * @param string $value 0387 * @param array $options 0388 * @return bool 0389 */ 0390 protected function _validateText($value, $options = array()) 0391 { 0392 // @TODO: add code128 validator 0393 return true; 0394 } 0395 }