web/lib/Zend/Barcode/Object/Code128.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Barcode
       
    17  * @subpackage Object
       
    18  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    19  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    20  * @version    $Id: Code25.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    21  */
       
    22 
       
    23 /**
       
    24  * @see Zend_Barcode_Object_ObjectAbstract
       
    25  */
       
    26 require_once 'Zend/Barcode/Object/ObjectAbstract.php';
       
    27 
       
    28 /**
       
    29  * @see Zend_Validate_Barcode
       
    30  */
       
    31 require_once 'Zend/Validate/Barcode.php';
       
    32 
       
    33 /**
       
    34  * Class for generate Code128 barcode
       
    35  *
       
    36  * @category   Zend
       
    37  * @package    Zend_Barcode
       
    38  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    39  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    40  */
       
    41 class Zend_Barcode_Object_Code128 extends Zend_Barcode_Object_ObjectAbstract
       
    42 {
       
    43     /**
       
    44      * Drawing of checksum
       
    45      * (even if it's sometime optional, most of time it's required)
       
    46      * @var boolean
       
    47      */
       
    48     protected $_withChecksum = true;
       
    49 
       
    50     /**
       
    51 	 * @var array
       
    52 	 */
       
    53 	protected $_convertedText = array();
       
    54 
       
    55     protected $_codingMap = array(
       
    56                  0 => "11011001100",   1 => "11001101100",   2 => "11001100110",
       
    57                  3 => "10010011000",   4 => "10010001100",   5 => "10001001100",
       
    58                  6 => "10011001000",   7 => "10011000100",   8 => "10001100100",
       
    59                  9 => "11001001000",  10 => "11001000100",  11 => "11000100100",
       
    60                 12 => "10110011100",  13 => "10011011100",  14 => "10011001110",
       
    61                 15 => "10111001100",  16 => "10011101100",  17 => "10011100110",
       
    62                 18 => "11001110010",  19 => "11001011100",  20 => "11001001110",
       
    63                 21 => "11011100100",  22 => "11001110100",  23 => "11101101110",
       
    64                 24 => "11101001100",  25 => "11100101100",  26 => "11100100110",
       
    65                 27 => "11101100100",  28 => "11100110100",  29 => "11100110010",
       
    66                 30 => "11011011000",  31 => "11011000110",  32 => "11000110110",
       
    67                 33 => "10100011000",  34 => "10001011000",  35 => "10001000110",
       
    68                 36 => "10110001000",  37 => "10001101000",  38 => "10001100010",
       
    69                 39 => "11010001000",  40 => "11000101000",  41 => "11000100010",
       
    70                 42 => "10110111000",  43 => "10110001110",  44 => "10001101110",
       
    71                 45 => "10111011000",  46 => "10111000110",  47 => "10001110110",
       
    72                 48 => "11101110110",  49 => "11010001110",  50 => "11000101110",
       
    73                 51 => "11011101000",  52 => "11011100010",  53 => "11011101110",
       
    74                 54 => "11101011000",  55 => "11101000110",  56 => "11100010110",
       
    75                 57 => "11101101000",  58 => "11101100010",  59 => "11100011010",
       
    76                 60 => "11101111010",  61 => "11001000010",  62 => "11110001010",
       
    77                 63 => "10100110000",  64 => "10100001100",  65 => "10010110000",
       
    78                 66 => "10010000110",  67 => "10000101100",  68 => "10000100110",
       
    79                 69 => "10110010000",  70 => "10110000100",  71 => "10011010000",
       
    80                 72 => "10011000010",  73 => "10000110100",  74 => "10000110010",
       
    81                 75 => "11000010010",  76 => "11001010000",  77 => "11110111010",
       
    82                 78 => "11000010100",  79 => "10001111010",  80 => "10100111100",
       
    83                 81 => "10010111100",  82 => "10010011110",  83 => "10111100100",
       
    84                 84 => "10011110100",  85 => "10011110010",  86 => "11110100100",
       
    85                 87 => "11110010100",  88 => "11110010010",  89 => "11011011110",
       
    86                 90 => "11011110110",  91 => "11110110110",  92 => "10101111000",
       
    87                 93 => "10100011110",  94 => "10001011110",  95 => "10111101000",
       
    88                 96 => "10111100010",  97 => "11110101000",  98 => "11110100010",
       
    89                 99 => "10111011110", 100 => "10111101110", 101 => "11101011110",
       
    90                102 => "11110101110",
       
    91                103 => "11010000100", 104 => "11010010000", 105 => "11010011100",
       
    92                106 => "1100011101011");
       
    93 
       
    94     /**
       
    95     * Character sets ABC
       
    96     * @var array
       
    97     */
       
    98     protected $_charSets = array(
       
    99         'A' => array(
       
   100             ' ', '!', '"', '#', '$', '%', '&', "'",
       
   101             '(', ')', '*', '+', ',', '-', '.', '/',
       
   102             '0', '1', '2', '3', '4', '5', '6', '7',
       
   103             '8', '9', ':', ';', '<', '=', '>', '?',
       
   104             '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
       
   105             'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
       
   106             'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
       
   107             'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
       
   108             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
       
   109             0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
       
   110             0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
       
   111             0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
       
   112             'FNC3', 'FNC2', 'SHIFT', 'Code C', 'Code B', 'FNC4', 'FNC1',
       
   113             'START A', 'START B', 'START C', 'STOP'),
       
   114         'B' => array(
       
   115             ' ', '!', '"', '#', '$', '%', '&', "'",
       
   116             '(', ')', '*', '+', ',', '-', '.', '/',
       
   117             '0', '1', '2', '3', '4', '5', '6', '7',
       
   118             '8', '9', ':', ';', '<', '=', '>', '?',
       
   119             '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
       
   120             'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
       
   121             'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
       
   122             'X', 'Y', 'Z', '[', '\\', ']', '^', '_',
       
   123             '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
       
   124             'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
       
   125             'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
       
   126             'x', 'y', 'z', '{', '|', '}', '~', 0x7F,
       
   127             'FNC3', 'FNC2', 'SHIFT', 'Code C', 'FNC4', 'Code A', 'FNC1',
       
   128             'START A', 'START B', 'START C', 'STOP',),
       
   129         'C' => array(
       
   130             '00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
       
   131             '10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
       
   132             '20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
       
   133             '30', '31', '32', '33', '34', '35', '36', '37', '38', '39',
       
   134             '40', '41', '42', '43', '44', '45', '46', '47', '48', '49',
       
   135             '50', '51', '52', '53', '54', '55', '56', '57', '58', '59',
       
   136             '60', '61', '62', '63', '64', '65', '66', '67', '68', '69',
       
   137             '70', '71', '72', '73', '74', '75', '76', '77', '78', '79',
       
   138             '80', '81', '82', '83', '84', '85', '86', '87', '88', '89',
       
   139             '90', '91', '92', '93', '94', '95', '96', '97', '98', '99',
       
   140             'Code B', 'Code A', 'FNC1', 'START A', 'START B', 'START C', 'STOP'));
       
   141     /*'A' => array(
       
   142       ' '=>0, '!'=>1, '"'=>2, '#'=>3, '$'=>4, '%'=>5, '&'=>6, "'"=>7,
       
   143       '('=>8, ')'=>9, '*'=>10, '+'=>11, ','=>12, '-'=>13, '.'=>14, '/'=>15,
       
   144       '0'=>16, '1'=>17, '2'=>18, '3'=>19, '4'=>20, '5'=>21, '6'=>22, '7'=>23,
       
   145       '8'=>24, '9'=>25, ':'=>26, ';'=>27, '<'=>28, '='=>29, '>'=>30, '?'=>31,
       
   146       '@'=>32, 'A'=>33, 'B'=>34, 'C'=>35, 'D'=>36, 'E'=>37, 'F'=>38, 'G'=>39,
       
   147       'H'=>40, 'I'=>41, 'J'=>42, 'K'=>43, 'L'=>44, 'M'=>45, 'N'=>46, 'O'=>47,
       
   148       'P'=>48, 'Q'=>49, 'R'=>50, 'S'=>51, 'T'=>52, 'U'=>53, 'V'=>54, 'W'=>55,
       
   149       'X'=>56, 'Y'=>57, 'Z'=>58, '['=>59, '\\'=>60, ']'=>61, '^'=>62, '_'=>63,
       
   150       0x00=>64, 0x01=>65, 0x02=>66, 0x03=>67, 0x04=>68, 0x05=>69, 0x06=>70, 0x07=>71,
       
   151       0x08=>72, 0x09=>73, 0x0A=>74, 0x0B=>75, 0x0C=>76, 0x0D=>77, 0x0E=>78, 0x0F=>79,
       
   152       0x10=>80, 0x11=>81, 0x12=>82, 0x13=>83, 0x14=>84, 0x15=>85, 0x16=>86, 0x17=>87,
       
   153       0x18=>88, 0x19=>89, 0x1A=>90, 0x1B=>91, 0x1C=>92, 0x1D=>93, 0x1E=>94, 0x1F=>95,
       
   154       'FNC3'=>96, 'FNC2'=>97, 'SHIFT'=>98, 'Code C'=>99, 'Code B'=>100, 'FNC4'=>101, 'FNC1'=>102, 'START A'=>103,
       
   155       'START B'=>104, 'START C'=>105, 'STOP'=>106),
       
   156     'B' => array(
       
   157       ' '=>0, '!'=>1, '"'=>2, '#'=>3, '$'=>4, '%'=>5, '&'=>6, "'"=>7,
       
   158       '('=>8, ')'=>9, '*'=>10, '+'=>11, ','=>12, '-'=>13, '.'=>14, '/'=>15,
       
   159       '0'=>16, '1'=>17, '2'=>18, '3'=>19, '4'=>20, '5'=>21, '6'=>22, '7'=>23,
       
   160       '8'=>24, '9'=>25, ':'=>26, ';'=>27, '<'=>28, '='=>29, '>'=>30, '?'=>31,
       
   161       '@'=>32, 'A'=>33, 'B'=>34, 'C'=>35, 'D'=>36, 'E'=>37, 'F'=>38, 'G'=>39,
       
   162       'H'=>40, 'I'=>41, 'J'=>42, 'K'=>43, 'L'=>44, 'M'=>45, 'N'=>46, 'O'=>47,
       
   163       'P'=>48, 'Q'=>49, 'R'=>50, 'S'=>51, 'T'=>52, 'U'=>53, 'V'=>54, 'W'=>55,
       
   164       'X'=>56, 'Y'=>57, 'Z'=>58, '['=>59, '\\'=>60, ']'=>61, '^'=>62, '_'=>63,
       
   165       '`' =>64, 'a'=>65, 'b'=>66, 'c'=>67, 'd'=>68, 'e'=>69, 'f'=>70, 'g'=>71,
       
   166       'h'=>72, 'i'=>73, 'j'=>74, 'k'=>75, 'l'=>76, 'm'=>77, 'n'=>78, 'o'=>79,
       
   167       'p'=>80, 'q'=>81, 'r'=>82, 's'=>83, 't'=>84, 'u'=>85, 'v'=>86, 'w'=>87,
       
   168       'x'=>88, 'y'=>89, 'z'=>90, '{'=>91, '|'=>92, '}'=>93, '~'=>94, 0x7F=>95,
       
   169       'FNC3'=>96, 'FNC2'=>97, 'SHIFT'=>98, 'Code C'=>99, 'FNC4'=>100, 'Code A'=>101, 'FNC1'=>102, 'START A'=>103,
       
   170       'START B'=>104, 'START C'=>105, 'STOP'=>106,),
       
   171     'C' => array(
       
   172       '00'=>0, '01'=>1, '02'=>2, '03'=>3, '04'=>4, '05'=>5, '06'=>6, '07'=>7, '08'=>8, '09'=>9,
       
   173       '10'=>10, '11'=>11, '12'=>12, '13'=>13, '14'=>14, '15'=>15, '16'=>16, '17'=>17, '18'=>18, '19'=>19,
       
   174       '20'=>20, '21'=>21, '22'=>22, '23'=>23, '24'=>24, '25'=>25, '26'=>26, '27'=>27, '28'=>28, '29'=>29,
       
   175       '30'=>30, '31'=>31, '32'=>32, '33'=>33, '34'=>34, '35'=>35, '36'=>36, '37'=>37, '38'=>38, '39'=>39,
       
   176       '40'=>40, '41'=>41, '42'=>42, '43'=>43, '44'=>44, '45'=>45, '46'=>46, '47'=>47, '48'=>48, '49'=>49,
       
   177       '50'=>50, '51'=>51, '52'=>52, '53'=>53, '54'=>54, '55'=>55, '56'=>56, '57'=>57, '58'=>58, '59'=>59,
       
   178       '60'=>60, '61'=>61, '62'=>62, '63'=>63, '64'=>64, '65'=>65, '66'=>66, '67'=>67, '68'=>68, '69'=>69,
       
   179       '70'=>70, '71'=>71, '72'=>72, '73'=>73, '74'=>74, '75'=>75, '76'=>76, '77'=>77, '78'=>78, '79'=>79,
       
   180       '80'=>80, '81'=>81, '82'=>82, '83'=>83, '84'=>84, '85'=>85, '86'=>86, '87'=>87, '88'=>88, '89'=>89,
       
   181       '90'=>90, '91'=>91, '92'=>92, '93'=>93, '94'=>94, '95'=>95, '96'=>96, '97'=>97, '98'=>98, '99'=>99,
       
   182       'Code B'=>100, 'Code A'=>101, 'FNC1'=>102, 'START A'=>103, 'START B'=>104, 'START C'=>105, 'STOP'=>106));*/
       
   183 
       
   184     /**
       
   185      * Width of the barcode (in pixels)
       
   186      * @return integer
       
   187      */
       
   188     protected function _calculateBarcodeWidth()
       
   189     {
       
   190         $quietZone = $this->getQuietZone();
       
   191         // Each characters contain 11 bars...
       
   192         $characterLength = 11 * $this->_barThinWidth * $this->_factor;
       
   193         $convertedChars = count($this->_convertToBarcodeChars($this->getText()));
       
   194         if ($this->_withChecksum) {
       
   195         	$convertedChars++;
       
   196         }
       
   197         $encodedData = $convertedChars * $characterLength;
       
   198         // ...except the STOP character (13)
       
   199         $encodedData += $characterLength + 2 * $this->_barThinWidth * $this->_factor;
       
   200         $width = $quietZone + $encodedData + $quietZone;
       
   201         return $width;
       
   202     }
       
   203 
       
   204     /**
       
   205      * Partial check of code128 barcode
       
   206      * @return void
       
   207      */
       
   208     protected function _checkParams()
       
   209     {
       
   210     }
       
   211 
       
   212     /**
       
   213      * Prepare array to draw barcode
       
   214      * @return array
       
   215      */
       
   216     protected function _prepareBarcode()
       
   217     {
       
   218         $barcodeTable = array();
       
   219 
       
   220         $convertedChars = $this->_convertToBarcodeChars($this->getText());
       
   221 
       
   222         if ($this->_withChecksum) {
       
   223         	$convertedChars[] = $this->getChecksum($this->getText());
       
   224         }
       
   225 
       
   226         // STOP CHARACTER
       
   227         $convertedChars[] = 106;
       
   228 
       
   229         foreach ($convertedChars as $barcodeChar) {
       
   230             $barcodePattern = $this->_codingMap[$barcodeChar];
       
   231             foreach (str_split($barcodePattern) as $c) {
       
   232                 $barcodeTable[] = array($c, 1, 0, 1);
       
   233             }
       
   234         }
       
   235         return $barcodeTable;
       
   236     }
       
   237 
       
   238     /**
       
   239      * Checks if the next $length chars of $string starting at $pos are numeric.
       
   240      * Returns false if the end of the string is reached.
       
   241      * @param $string String to search
       
   242      * @param $pos Starting position
       
   243      * @param $length Length to search
       
   244      * @return bool
       
   245      */
       
   246     protected static function _isDigit($string, $pos, $length = 2)
       
   247     {
       
   248 	    if ($pos + $length > strlen($string)) {
       
   249 	       return false;
       
   250 	    }
       
   251 
       
   252 		for ($i = $pos; $i < $pos + $length; $i++) {
       
   253 		      if (!is_numeric($string[$i])) {
       
   254 		          return false;
       
   255 		      }
       
   256 		}
       
   257 		return true;
       
   258 	}
       
   259 
       
   260     /**
       
   261      * Convert string to barcode string
       
   262      * @return array
       
   263      */
       
   264     protected function _convertToBarcodeChars($string)
       
   265     {
       
   266     	$string = (string) $string;
       
   267     	if (!strlen($string)) {
       
   268     		return array();
       
   269     	}
       
   270 
       
   271     	if (isset($this->_convertedText[md5($string)])) {
       
   272     		return $this->_convertedText[md5($string)];
       
   273     	}
       
   274 
       
   275         $currentCharset = null;
       
   276         $sum = 0;
       
   277         $fak = 0;
       
   278         $result = array();
       
   279 
       
   280         for ($pos = 0; $pos < strlen($string); $pos++) {
       
   281             $char = $string[$pos];
       
   282             $code = null;
       
   283 
       
   284             if (self::_isDigit($string, $pos, 4) && $currentCharset != 'C'
       
   285              || self::_isDigit($string, $pos, 2) && $currentCharset == 'C') {
       
   286                 /**
       
   287                  * Switch to C if the next 4 chars are numeric or stay C if the next 2
       
   288                  * chars are numeric
       
   289                  */
       
   290                 if ($currentCharset != 'C') {
       
   291                     if ($pos == 0) {
       
   292                         $code = array_search("START C", $this->_charSets['C']);
       
   293                     } else {
       
   294                         $code = array_search("Code C", $this->_charSets[$currentCharset]);
       
   295                     }
       
   296                     $result[] = $code;
       
   297                     $currentCharset = 'C';
       
   298                 }
       
   299             } else if (in_array($char, $this->_charSets['B']) && $currentCharset != 'B'
       
   300                   && !(in_array($char, $this->_charSets['A']) && $currentCharset == 'A')) {
       
   301                 /**
       
   302                  * Switch to B as B contains the char and B is not the current charset.
       
   303                  */
       
   304                 if ($pos == 0) {
       
   305                     $code = array_search("START B", $this->_charSets['B']);
       
   306                 } else {
       
   307                     $code = array_search("Code B", $this->_charSets[$currentCharset]);
       
   308                 }
       
   309                 $result[] = $code;
       
   310                 $currentCharset = 'B';
       
   311             } else if (array_key_exists($char, $this->_charSets['A']) && $currentCharset != 'A'
       
   312                   && !(array_key_exists($char, $this->_charSets['B']) && $currentCharset == 'B')) {
       
   313                 /**
       
   314                  * Switch to C as C contains the char and C is not the current charset.
       
   315                  */
       
   316                 if ($pos == 0) {
       
   317                     $code = array_search("START A", $this->_charSets['A']);
       
   318                 } else {
       
   319                     $code =array_search("Code A", $this->_charSets[$currentCharset]);
       
   320                 }
       
   321                 $result[] = $code;
       
   322                 $currentCharset = 'A';
       
   323             }
       
   324 
       
   325             if ($currentCharset == 'C') {
       
   326                 $code = array_search(substr($string, $pos, 2), $this->_charSets['C']);
       
   327                 $pos++; //Two chars from input
       
   328             } else {
       
   329                 $code = array_search($string[$pos], $this->_charSets[$currentCharset]);
       
   330             }
       
   331             $result[] = $code;
       
   332         }
       
   333 
       
   334         $this->_convertedText[md5($string)] = $result;
       
   335         return $result;
       
   336     }
       
   337 
       
   338     /**
       
   339      * Set text to encode
       
   340      * @param string $value
       
   341      * @return Zend_Barcode_Object
       
   342      */
       
   343     public function setText($value)
       
   344     {
       
   345         $this->_text = $value;
       
   346         return $this;
       
   347     }
       
   348 
       
   349     /**
       
   350      * Retrieve text to encode
       
   351      * @return string
       
   352      */
       
   353     public function getText()
       
   354     {
       
   355         return $this->_text;
       
   356     }
       
   357 
       
   358     /**
       
   359      * Get barcode checksum
       
   360      *
       
   361      * @param  string $text
       
   362      * @return int
       
   363      */
       
   364     public function getChecksum($text)
       
   365     {
       
   366     	$tableOfChars = $this->_convertToBarcodeChars($text);
       
   367 
       
   368     	$sum = $tableOfChars[0];
       
   369     	unset($tableOfChars[0]);
       
   370 
       
   371     	$k = 1;
       
   372     	foreach ($tableOfChars as $char) {
       
   373     		$sum += ($k++) * $char;
       
   374     	}
       
   375 
       
   376     	$checksum = $sum % 103;
       
   377 
       
   378         return $checksum;
       
   379     }
       
   380 
       
   381     /**
       
   382      * Standard validation for most of barcode objects
       
   383      * @param string $value
       
   384      * @param array  $options
       
   385      */
       
   386     protected function _validateText($value, $options = array())
       
   387     {
       
   388     	// @TODO: add code128 validator
       
   389     	return true;
       
   390     }
       
   391 }