PageRenderTime 47ms CodeModel.GetById 16ms app.highlight 23ms RepoModel.GetById 1ms app.codeStats 1ms

/library/Zend/Barcode/Object/Code128.php

https://bitbucket.org/nosen/jelly2
PHP | 391 lines | 215 code | 30 blank | 146 comment | 42 complexity | 14fd91ba4fbe2315e6aa8fe87e0c8f5f MD5 | raw file
  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-2011 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 */
 26require_once 'Zend/Barcode/Object/ObjectAbstract.php';
 27
 28/**
 29 * @see Zend_Validate_Barcode
 30 */
 31require_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-2011 Zend Technologies USA Inc. (http://www.zend.com)
 39 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 40 */
 41class 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, $this->_barThinWidth, 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 String to search
242     * @param int    $pos Starting position
243     * @param int    $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}