New Company Setup 'Barcodes On Stock' implemented. Rep303 shows barcodes if set.
[fa-stable.git] / reporting / includes / barcodes.php
1 <?php
2 //============================================================+
3 // File name   : barcodes.php
4 // Begin       : 2008-06-09
5 // Last Update : 2008-07-16
6 // Version     : 1.0.002
7 // License     : GNU LGPL (http://www.gnu.org/copyleft/lesser.html)
8 //      ----------------------------------------------------------------------------
9 //  Copyright (C) 2008  Nicola Asuni - Tecnick.com S.r.l.
10 //      
11 //      This program is free software: you can redistribute it and/or modify
12 //      it under the terms of the GNU Lesser General Public License as published by
13 //      the Free Software Foundation, either version 2.1 of the License, or
14 //      (at your option) any later version.
15 //      
16 //      This program is distributed in the hope that it will be useful,
17 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
18 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 //      GNU Lesser General Public License for more details.
20 //      
21 //      You should have received a copy of the GNU Lesser General Public License
22 //      along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 //      
24 //      See LICENSE.TXT file for more information.
25 //  ----------------------------------------------------------------------------
26 //
27 // Description : PHP class to creates array representations for 
28 //               common 1D barcodes to be used with TCPDF.
29 //
30 // Author: Nicola Asuni
31 //
32 // (c) Copyright:
33 //               Nicola Asuni
34 //               Tecnick.com S.r.l.
35 //               Via della Pace, 11
36 //               09044 Quartucciu (CA)
37 //               ITALY
38 //               www.tecnick.com
39 //               info@tecnick.com
40 //============================================================+
41
42 /**
43  * PHP class to creates array representations for common 1D barcodes to be used with TCPDF.
44  * @package com.tecnick.tcpdf
45  * @abstract Functions for generating string representation of common 1D barcodes.
46  * @author Nicola Asuni
47  * @copyright 2008 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
48  * @link http://www.tcpdf.org
49  * @license http://www.gnu.org/copyleft/lesser.html LGPL
50  * @version 1.0.001
51  */
52
53         /**
54         * PHP class to creates array representations for common 1D barcodes to be used with TCPDF (http://www.tcpdf.org).<br>
55         * @name TCPDFBarcode
56         * @package com.tecnick.tcpdf
57         * @version 1.0.001
58         * @author Nicola Asuni
59         * @link http://www.tcpdf.org
60         * @license http://www.gnu.org/copyleft/lesser.html LGPL
61         */
62 class TCPDFBarcode {
63         
64         /**
65          * @var array representation of barcode.
66          * @access protected
67          */
68         var $barcode_array;
69                 
70         /**
71          * This is the class constructor. 
72          * Return an array representations for common 1D barcodes:<ul>
73          * <li>$arrcode["code"] code to be printed on text label</li>
74          * <li>$arrcode["maxh"] max bar height</li>
75          * <li>$arrcode["maxw"] max bar width</li>
76          * <li>$arrcode["bcode"][$k] single bar or space in $k position</li>
77          * <li>$arrcode["bcode"][$k]["t"] bar type: true = bar, false = space.</li>
78          * <li>$arrcode["bcode"][$k]["w"] bar width in units.</li>
79          * <li>$arrcode["bcode"][$k]["h"] bar height in units.</li>
80          * <li>$arrcode["bcode"][$k]["p"] bar top position (0 = top, 1 = middle)</li></ul>
81          * @param string $code code to print
82          * @param string $type type of barcode: <ul><li>C39 : CODE 39</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED with checksum</li><li>I25 : Interleaved 2 of 5</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extension</li><li>EAN5 : 5-Digits UPC-Based Extension</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>POSTNET : POSTNET</li><li>CODABAR : CODABAR</li></ul>
83          */
84         function __construct($code, $type) {
85                 $this->setBarcode($code, $type);
86         }
87         
88         /** 
89          * Return an array representations of barcode.
90          * @return array
91          */
92         function getBarcodeArray() {
93                 return $this->barcode_array;
94         }
95         
96         /** 
97          * Set the barcode.
98          * @param string $code code to print
99          * @param string $type type of barcode: <ul><li>C39 : CODE 39</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED with checksum</li><li>I25 : Interleaved 2 of 5</li><li>C128A : CODE 128 A</li><li>C128B : CODE 128 B</li><li>C128C : CODE 128 C</li><li>EAN2 : 2-Digits UPC-Based Extension</li><li>EAN5 : 5-Digits UPC-Based Extension</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>POSTNET : POSTNET</li><li>CODABAR : CODABAR</li></ul>
100          * @return array
101          */
102         function setBarcode($code, $type) {
103                 switch (strtoupper($type)) {
104                         case "C39": { // CODE 39
105                                 $arrcode = $this->barcode_code39($code, false, false);
106                                 break;
107                         }
108                         case "C39+": { // CODE 39 with checksum
109                                 $arrcode = $this->barcode_code39($code, false, true);
110                                 break;
111                         }
112                         case "C39E": { // CODE 39 EXTENDED
113                                 $arrcode = $this->barcode_code39($code, true, false);
114                                 break;
115                         }
116                         case "C39E+": { // CODE 39 EXTENDED with checksum
117                                 $arrcode = $this->barcode_code39($code, true, true);
118                                 break;
119                         }
120                         case "I25": { // Interleaved 2 of 5
121                                 $arrcode = $this->barcode_i25($code);
122                                 break;
123                         }
124                         case "C128A": { // CODE 128 A
125                                 $arrcode = $this->barcode_c128($code, "A");
126                                 break;
127                         }
128                         case "C128B": { // CODE 128 B
129                                 $arrcode = $this->barcode_c128($code, "B");
130                                 break;
131                         }
132                         case "C128C": { // CODE 128 C
133                                 $arrcode = $this->barcode_c128($code, "C");
134                                 break;
135                         }
136                         case 'EAN2': { // 2-Digits UPC-Based Extension
137                                 $arrcode = $this->barcode_eanext($code, 2);
138                                 break;
139                         }
140                         case 'EAN5': { // 5-Digits UPC-Based Extension
141                                 $arrcode = $this->barcode_eanext($code, 5);
142                                 break;
143                         }
144                         case 'EAN8': { // EAN 8
145                                 $arrcode = $this->barcode_eanupc($code, 8);
146                                 break;
147                         }
148                         case 'EAN13': { // EAN 13
149                                 $arrcode = $this->barcode_eanupc($code, 13);
150                                 break;
151                         }
152                         case 'UPCA': { // UPC-A
153                                 $arrcode = $this->barcode_eanupc($code, 12);
154                                 break;
155                         }
156                         case 'UPCE': { // UPC-E
157                                 $arrcode = $this->barcode_eanupc($code, 6);
158                                 break;
159                         }
160                         case "POSTNET": { // POSTNET
161                                 $arrcode = $this->barcode_postnet($code);
162                                 break;
163                         }
164                         case "CODABAR": { // CODABAR
165                                 $arrcode = $this->barcode_codabar($code);
166                                 break;
167                         }
168                         default: {
169                                 $this->barcode_array = false;
170                         }
171                 }
172                 $this->barcode_array = $arrcode;
173         }
174         
175         /**
176          * CODE 39
177          * @param string $code code to represent.
178          * @param boolean $checksum if true add a checksum to the code
179          * @return array barcode representation.
180          * @access protected
181          */
182         function barcode_code39($code, $extended=false, $checksum=false) {
183                 $chr['0'] = '111221211';
184                 $chr['1'] = '211211112';
185                 $chr['2'] = '112211112';
186                 $chr['3'] = '212211111';
187                 $chr['4'] = '111221112';
188                 $chr['5'] = '211221111';
189                 $chr['6'] = '112221111';
190                 $chr['7'] = '111211212';
191                 $chr['8'] = '211211211';
192                 $chr['9'] = '112211211';
193                 $chr['A'] = '211112112';
194                 $chr['B'] = '112112112';
195                 $chr['C'] = '212112111';
196                 $chr['D'] = '111122112';
197                 $chr['E'] = '211122111';
198                 $chr['F'] = '112122111';
199                 $chr['G'] = '111112212';
200                 $chr['H'] = '211112211';
201                 $chr['I'] = '112112211';
202                 $chr['J'] = '111122211';
203                 $chr['K'] = '211111122';
204                 $chr['L'] = '112111122';
205                 $chr['M'] = '212111121';
206                 $chr['N'] = '111121122';
207                 $chr['O'] = '211121121';
208                 $chr['P'] = '112121121';
209                 $chr['Q'] = '111111222';
210                 $chr['R'] = '211111221';
211                 $chr['S'] = '112111221';
212                 $chr['T'] = '111121221';
213                 $chr['U'] = '221111112';
214                 $chr['V'] = '122111112';
215                 $chr['W'] = '222111111';
216                 $chr['X'] = '121121112';
217                 $chr['Y'] = '221121111';
218                 $chr['Z'] = '122121111';
219                 $chr['-'] = '121111212';
220                 $chr['.'] = '221111211';
221                 $chr[' '] = '122111211';
222                 $chr['*'] = '121121211';
223                 $chr['$'] = '121212111';
224                 $chr['/'] = '121211121';
225                 $chr['+'] = '121112121';
226                 $chr['%'] = '111212121';
227                 
228                 $code = strtoupper($code);
229                 if ($extended) {
230                         // extended mode
231                         $code = $this->encode_code39_ext($code);
232                 }
233                 if ($code === false) {
234                         return false;
235                 }
236                 if ($checksum) {
237                         // checksum
238                         $code .= $this->checksum_code39($code);
239                 }
240                 // add start and stop codes
241                 $code = "*".$code."*";
242                 
243                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
244                 $k = 0;
245                 for($i=0; $i < strlen($code); $i++) {
246                         $char = $code{$i};
247                         if(!isset($chr[$char])) {
248                                 // invalid character
249                                 return false;
250                         }
251                         for($j=0; $j < 9; $j++) {
252                                 if (($j % 2) == 0) {
253                                         $t = true; // bar
254                                 } else {
255                                         $t = false; // space
256                                 }
257                                 $w = $chr[$char]{$j};
258                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
259                                 $bararray["maxw"] += $w;
260                                 $k++;
261                         }
262                         $bararray["bcode"][$k] = array("t" => false, "w" => 1, "h" => 1, "p" => 0);
263                         $bararray["maxw"] += 1;
264                         $k++;
265                 }
266                 return $bararray;
267         }
268         
269         /**
270          * Encode a string to be used for CODE 39 Extended mode.
271          * @param string $code code to represent.
272          * @return encoded string.
273          * @access protected
274          */
275         function encode_code39_ext($code) {
276                 $encode = array(
277                         chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
278                         chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
279                         chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
280                         chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
281                         chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
282                         chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
283                         chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
284                         chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
285                         chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
286                         chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
287                         chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
288                         chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
289                         chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
290                         chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
291                         chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
292                         chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
293                         chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
294                         chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
295                         chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
296                         chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
297                         chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
298                         chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
299                         chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
300                         chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
301                         chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
302                         chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
303                         chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
304                         chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
305                         chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
306                         chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
307                         chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
308                         chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
309                 $code_ext = '';
310                 for ($i = 0 ; $i < strlen($code); $i++) {
311                         if (ord($code{$i}) > 127) {
312                                 return false;
313                         }
314                         $code_ext .= $encode[$code{$i}];
315                 }
316                 return $code_ext;
317         }
318         
319         /**
320          * Calculate CODE 39 checksum (modulo 43).
321          * @param string $code code to represent.
322          * @return char checksum.
323          * @access protected
324          */
325         function checksum_code39($code) {
326                 $chars = array(
327                         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
328                         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
329                         'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
330                         'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
331                 $sum = 0;
332                 for ($i=0 ; $i < strlen($code); $i++) {
333                         $k = array_keys($chars, $code{$i});
334                         $sum += $k[0];
335                 }
336                 $j = ($sum % 43);
337                 return $chars[$j];
338         }
339         
340         /**
341          * Interleaved 2 of 5 barcodes. 
342          * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
343          * @param string $code code to represent.
344          * @param boolean $checksum if true add a checksum to the code
345          * @return array barcode representation.
346          * @access protected
347          */
348         function barcode_i25($code) {
349                 $chr['0'] = '11221';
350                 $chr['1'] = '21112';
351                 $chr['2'] = '12112';
352                 $chr['3'] = '22111';
353                 $chr['4'] = '11212';
354                 $chr['5'] = '21211';
355                 $chr['6'] = '12211';
356                 $chr['7'] = '11122';
357                 $chr['8'] = '21121';
358                 $chr['9'] = '12121';
359                 $chr['A'] = '11';
360                 $chr['Z'] = '21';
361                 
362                 if((strlen($code) % 2) != 0) {
363                         // add leading zero if code-length is odd
364                         $code = '0'.$code;
365                 }
366                 // add start and stop codes
367                 $code = 'AA'.strtolower($code).'ZA';
368                         
369                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
370                 $k = 0;
371                 for($i=0; $i < strlen($code); $i=$i+2) {
372                         $char_bar = $code{$i};
373                         $char_space = $code{$i+1};
374                         if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) {
375                                 // invalid character
376                                 return false;
377                         }
378                         // create a bar-space sequence
379                         $seq = "";
380                         for($s=0; $s < strlen($chr[$char_bar]); $s++){
381                                 $seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s};
382                         }
383                         for($j=0; $j < strlen($seq); $j++) {
384                                 if (($j % 2) == 0) {
385                                         $t = true; // bar
386                                 } else {
387                                         $t = false; // space
388                                 }
389                                 $w = $seq{$j};
390                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
391                                 $bararray["maxw"] += $w;
392                                 $k++;
393                         }
394                 }
395                 return $bararray;
396         }
397         
398         /**
399          * C128 barcodes. 
400          * 
401          * @param string $code code to represent.
402          * @param string $type barcode type: A, B or C
403          * @return array barcode representation.
404          * @access protected
405          */
406         function barcode_c128($code, $type="B") {
407                 $chr = array(
408                         '212222', /* 00 */
409                         '222122', /* 01 */
410                         '222221', /* 02 */
411                         '121223', /* 03 */
412                         '121322', /* 04 */
413                         '131222', /* 05 */
414                         '122213', /* 06 */
415                         '122312', /* 07 */
416                         '132212', /* 08 */
417                         '221213', /* 09 */
418                         '221312', /* 10 */
419                         '231212', /* 11 */
420                         '112232', /* 12 */
421                         '122132', /* 13 */
422                         '122231', /* 14 */
423                         '113222', /* 15 */
424                         '123122', /* 16 */
425                         '123221', /* 17 */
426                         '223211', /* 18 */
427                         '221132', /* 19 */
428                         '221231', /* 20 */
429                         '213212', /* 21 */
430                         '223112', /* 22 */
431                         '312131', /* 23 */
432                         '311222', /* 24 */
433                         '321122', /* 25 */
434                         '321221', /* 26 */
435                         '312212', /* 27 */
436                         '322112', /* 28 */
437                         '322211', /* 29 */
438                         '212123', /* 30 */
439                         '212321', /* 31 */
440                         '232121', /* 32 */
441                         '111323', /* 33 */
442                         '131123', /* 34 */
443                         '131321', /* 35 */
444                         '112313', /* 36 */
445                         '132113', /* 37 */
446                         '132311', /* 38 */
447                         '211313', /* 39 */
448                         '231113', /* 40 */
449                         '231311', /* 41 */
450                         '112133', /* 42 */
451                         '112331', /* 43 */
452                         '132131', /* 44 */
453                         '113123', /* 45 */
454                         '113321', /* 46 */
455                         '133121', /* 47 */
456                         '313121', /* 48 */
457                         '211331', /* 49 */
458                         '231131', /* 50 */
459                         '213113', /* 51 */
460                         '213311', /* 52 */
461                         '213131', /* 53 */
462                         '311123', /* 54 */
463                         '311321', /* 55 */
464                         '331121', /* 56 */
465                         '312113', /* 57 */
466                         '312311', /* 58 */
467                         '332111', /* 59 */
468                         '314111', /* 60 */
469                         '221411', /* 61 */
470                         '431111', /* 62 */
471                         '111224', /* 63 */
472                         '111422', /* 64 */
473                         '121124', /* 65 */
474                         '121421', /* 66 */
475                         '141122', /* 67 */
476                         '141221', /* 68 */
477                         '112214', /* 69 */
478                         '112412', /* 70 */
479                         '122114', /* 71 */
480                         '122411', /* 72 */
481                         '142112', /* 73 */
482                         '142211', /* 74 */
483                         '241211', /* 75 */
484                         '221114', /* 76 */
485                         '413111', /* 77 */
486                         '241112', /* 78 */
487                         '134111', /* 79 */
488                         '111242', /* 80 */
489                         '121142', /* 81 */
490                         '121241', /* 82 */
491                         '114212', /* 83 */
492                         '124112', /* 84 */
493                         '124211', /* 85 */
494                         '411212', /* 86 */
495                         '421112', /* 87 */
496                         '421211', /* 88 */
497                         '212141', /* 89 */
498                         '214121', /* 90 */
499                         '412121', /* 91 */
500                         '111143', /* 92 */
501                         '111341', /* 93 */
502                         '131141', /* 94 */
503                         '114113', /* 95 */
504                         '114311', /* 96 */
505                         '411113', /* 97 */
506                         '411311', /* 98 */
507                         '113141', /* 99 */
508                         '114131', /* 100 */
509                         '311141', /* 101 */
510                         '411131', /* 102 */
511                         '211412', /* 103 START A */
512                         '211214', /* 104 START B  */
513                         '211232', /* 105 START C  */
514                         '233111',       /* STOP */
515                         '200000'        /* END */
516                 );
517                 $keys = "";
518                 switch(strtoupper($type)) {
519                         case "A": {
520                                 $startid = 103;
521                                 $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
522                                 for($i = 0; $i < 32; $i++) {
523                                         $keys .= chr($i);
524                                 }
525                                 break;
526                         }
527                         case "B": {
528                                 $startid = 104;
529                                 $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127);
530                                 break;
531                         }
532                         case "C": {
533                                 $startid = 105;
534                                 $keys = "";
535                                 if ((strlen($code) % 2) != 0) {
536                                         //echo "The length of barcode value must be even ($code). You must pad the number with zeros.\n";
537                                         return false;
538                                 }
539                                 for($i = 0; $i <= 99; $i++) {
540                                         $keys .= chr($i);
541                                 }
542                                 $new_code = "";
543                                 for ($i=0; $i < (strlen($code) / 2); $i++) {
544                                         $new_code .= chr(intval($code{(2 * $i)}.$code{(2 * $i + 1)}));
545                                 }
546                                 $code = $new_code;
547                                 break;
548                         }
549                         default: {
550                                 return false;
551                         }
552                 }
553                 // calculate check character
554                 $sum = $startid;
555                 for ($i=0; $i < strlen($code); $i++) {
556                         $sum +=  (strpos($keys, $code{$i}) * ($i+1));
557                 }
558                 $check = ($sum % 103);
559                 
560                 // add start, check and stop codes
561                 $code = chr($startid).$code.chr($check).chr(106).chr(107);
562                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
563                 $k = 0;
564                 $len = strlen($code);
565                 for($i=0; $i < $len; $i++) {
566                         $ck = strpos($keys, $code{$i});
567                         if (($i == 0) OR ($i > ($len-4))) {
568                                 $seq = $chr[ord($code{$i})];
569                         } elseif(($ck >= 0) AND isset($chr[$ck])) {
570                                         $seq = $chr[$ck];
571                         } else {
572                                 // invalid character
573                                 return false;
574                         }
575                         for($j=0; $j < 6; $j++) {
576                                 if (($j % 2) == 0) {
577                                         $t = true; // bar
578                                 } else {
579                                         $t = false; // space
580                                 }
581                                 $w = $seq{$j};
582                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
583                                 $bararray["maxw"] += $w;
584                                 $k++;
585                         }
586                 }
587                 return $bararray;               
588         }
589
590         /**
591          * EAN13 and UPC-A barcodes.
592          * EAN13: European Article Numbering international retail product code
593          * UPC-A: Universal product code seen on almost all retail products in the USA and Canada
594          * UPC-E: Short version of UPC symbol
595          * @param $code (string) code to represent.
596          * @param $len (string) barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A
597          * @return array barcode representation.
598          * @protected
599          */
600         protected function barcode_eanupc($code, $len=13) {
601                 $upce = false;
602                 if ($len == 6) {
603                         $len = 12; // UPC-A
604                         $upce = true; // UPC-E mode
605                 }
606                 $data_len = $len - 1;
607                 //Padding
608                 $code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
609                 $code_len = strlen($code);
610                 // calculate check digit
611                 $sum_a = 0;
612                 for ($i = 1; $i < $data_len; $i+=2) {
613                         $sum_a += $code{$i};
614                 }
615                 if ($len > 12) {
616                         $sum_a *= 3;
617                 }
618                 $sum_b = 0;
619                 for ($i = 0; $i < $data_len; $i+=2) {
620                         $sum_b += ($code{$i});
621                 }
622                 if ($len < 13) {
623                         $sum_b *= 3;
624                 }
625                 $r = ($sum_a + $sum_b) % 10;
626                 if($r > 0) {
627                         $r = (10 - $r);
628                 }
629                 if ($code_len == $data_len) {
630                         // add check digit
631                         $code .= $r;
632                 } elseif ($r !== intval($code{$data_len})) {
633                         // wrong checkdigit
634                         return false;
635                 }
636                 if ($len == 12) {
637                         // UPC-A
638                         $code = '0'.$code;
639                         ++$len;
640                 }
641                 if ($upce) {
642                         // convert UPC-A to UPC-E
643                         $tmp = substr($code, 4, 3);
644                         if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
645                                 // manufacturer code ends in 000, 100, or 200
646                                 $upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1);
647                         } else {
648                                 $tmp = substr($code, 5, 2);
649                                 if ($tmp == '00') {
650                                         // manufacturer code ends in 00
651                                         $upce_code = substr($code, 2, 3).substr($code, 10, 2).'3';
652                                 } else {
653                                         $tmp = substr($code, 6, 1);
654                                         if ($tmp == '0') {
655                                                 // manufacturer code ends in 0
656                                                 $upce_code = substr($code, 2, 4).substr($code, 11, 1).'4';
657                                         } else {
658                                                 // manufacturer code does not end in zero
659                                                 $upce_code = substr($code, 2, 5).substr($code, 11, 1);
660                                         }
661                                 }
662                         }
663                 }
664                 //Convert digits to bars
665                 $codes = array(
666                         'A'=>array( // left odd parity
667                                 '0'=>'0001101',
668                                 '1'=>'0011001',
669                                 '2'=>'0010011',
670                                 '3'=>'0111101',
671                                 '4'=>'0100011',
672                                 '5'=>'0110001',
673                                 '6'=>'0101111',
674                                 '7'=>'0111011',
675                                 '8'=>'0110111',
676                                 '9'=>'0001011'),
677                         'B'=>array( // left even parity
678                                 '0'=>'0100111',
679                                 '1'=>'0110011',
680                                 '2'=>'0011011',
681                                 '3'=>'0100001',
682                                 '4'=>'0011101',
683                                 '5'=>'0111001',
684                                 '6'=>'0000101',
685                                 '7'=>'0010001',
686                                 '8'=>'0001001',
687                                 '9'=>'0010111'),
688                         'C'=>array( // right
689                                 '0'=>'1110010',
690                                 '1'=>'1100110',
691                                 '2'=>'1101100',
692                                 '3'=>'1000010',
693                                 '4'=>'1011100',
694                                 '5'=>'1001110',
695                                 '6'=>'1010000',
696                                 '7'=>'1000100',
697                                 '8'=>'1001000',
698                                 '9'=>'1110100')
699                 );
700                 $parities = array(
701                         '0'=>array('A','A','A','A','A','A'),
702                         '1'=>array('A','A','B','A','B','B'),
703                         '2'=>array('A','A','B','B','A','B'),
704                         '3'=>array('A','A','B','B','B','A'),
705                         '4'=>array('A','B','A','A','B','B'),
706                         '5'=>array('A','B','B','A','A','B'),
707                         '6'=>array('A','B','B','B','A','A'),
708                         '7'=>array('A','B','A','B','A','B'),
709                         '8'=>array('A','B','A','B','B','A'),
710                         '9'=>array('A','B','B','A','B','A')
711                 );
712                 $upce_parities = array();
713                 $upce_parities[0] = array(
714                         '0'=>array('B','B','B','A','A','A'),
715                         '1'=>array('B','B','A','B','A','A'),
716                         '2'=>array('B','B','A','A','B','A'),
717                         '3'=>array('B','B','A','A','A','B'),
718                         '4'=>array('B','A','B','B','A','A'),
719                         '5'=>array('B','A','A','B','B','A'),
720                         '6'=>array('B','A','A','A','B','B'),
721                         '7'=>array('B','A','B','A','B','A'),
722                         '8'=>array('B','A','B','A','A','B'),
723                         '9'=>array('B','A','A','B','A','B')
724                 );
725                 $upce_parities[1] = array(
726                         '0'=>array('A','A','A','B','B','B'),
727                         '1'=>array('A','A','B','A','B','B'),
728                         '2'=>array('A','A','B','B','A','B'),
729                         '3'=>array('A','A','B','B','B','A'),
730                         '4'=>array('A','B','A','A','B','B'),
731                         '5'=>array('A','B','B','A','A','B'),
732                         '6'=>array('A','B','B','B','A','A'),
733                         '7'=>array('A','B','A','B','A','B'),
734                         '8'=>array('A','B','A','B','B','A'),
735                         '9'=>array('A','B','B','A','B','A')
736                 );
737                 $k = 0;
738                 $seq = '101'; // left guard bar
739                 if ($upce) {
740                         $bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
741                         $p = $upce_parities[$code[1]][$r];
742                         for ($i = 0; $i < 6; ++$i) {
743                                 $seq .= $codes[$p[$i]][$upce_code{$i}];
744                         }
745                         $seq .= '010101'; // right guard bar
746                 } else {
747                         $bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
748                         $half_len = intval(ceil($len / 2));
749                         if ($len == 8) {
750                                 for ($i = 0; $i < $half_len; ++$i) {
751                                         $seq .= $codes['A'][$code{$i}];
752                                 }
753                         } else {
754                                 $p = $parities[$code[0]];
755                                 for ($i = 1; $i < $half_len; ++$i) {
756                                         $seq .= $codes[$p[$i-1]][$code{$i}];
757                                 }
758                         }
759                         $seq .= '01010'; // center guard bar
760                         for ($i = $half_len; $i < $len; ++$i) {
761                                 $seq .= $codes['C'][$code{$i}];
762                         }
763                         $seq .= '101'; // right guard bar
764                 }
765                 $clen = strlen($seq);
766                 $w = 0;
767                 for ($i = 0; $i < $clen; ++$i) {
768                         $w += 1;
769                         if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
770                                 if ($seq{$i} == '1') {
771                                         $t = true; // bar
772                                 } else {
773                                         $t = false; // space
774                                 }
775                                 $bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
776                                 $bararray['maxw'] += $w;
777                                 ++$k;
778                                 $w = 0;
779                         }
780                 }
781                 return $bararray;
782         }
783
784         /**
785          * POSTNET barcodes.
786          * @param string $code zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD.
787          * @return array barcode representation.
788          * @access protected
789          */
790         function barcode_postnet($code) {
791                 // bar lenght
792                 $barlen = Array(
793                         0 => Array(2,2,1,1,1),
794                         1 => Array(1,1,1,2,2),
795                         2 => Array(1,1,2,1,2),
796                         3 => Array(1,1,2,2,1),
797                         4 => Array(1,2,1,1,2),
798                         5 => Array(1,2,1,2,1),
799                         6 => Array(1,2,2,1,1),
800                         7 => Array(2,1,1,1,2),
801                         8 => Array(2,1,1,2,1),
802                         9 => Array(2,1,2,1,1)
803                 );
804                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 2, "bcode" => array());
805                 $k = 0;
806                 $code = str_replace("-", "", $code);
807                 $code = str_replace(" ", "", $code);
808                 $len = strlen($code);
809                 // calculate checksum
810                 $sum = 0;
811                 for($i=0; $i < $len; $i++) {
812                         $sum += intval($code{$i});
813                 }
814                 if(($sum % 10) == 0) {
815                         return false;
816                 }
817                 $code .= "".(10 - ($sum % 10))."";
818                 $len = strlen($code);
819                 // start bar
820                 $bararray["bcode"][$k++] = array("t" => 1, "w" => 1, "h" => 2, "p" => 0);
821                 $bararray["bcode"][$k++] = array("t" => 0, "w" => 1, "h" => 2, "p" => 0);
822                 $bararray["maxw"] += 2;
823                 for ($i=0; $i < $len; $i++) {
824                         for ($j=0; $j < 5; $j++) {
825                                 $h = $barlen[$code{$i}][$j];
826                                 $p = floor(1 / $h);
827                                 $bararray["bcode"][$k++] = array("t" => 1, "w" => 1, "h" => $h, "p" => $p);
828                                 $bararray["bcode"][$k++] = array("t" => 0, "w" => 1, "h" => 2, "p" => 0);
829                                 $bararray["maxw"] += 2;
830                         }
831                 }
832                 // end bar
833                 $bararray["bcode"][$k++] = array("t" => 1, "w" => 1, "h" => 2, "p" => 0);
834                 $bararray["maxw"] += 1;
835                 return $bararray;
836         }
837         
838         /**
839          * CODABAR barcodes.
840          * @param string $code code to represent.
841          * @return array barcode representation.
842          * @access protected
843          */
844         function barcode_codabar($code) {
845                 $chr = array(
846                         '0' => '11111221',
847                         '1' => '11112211',
848                         '2' => '11121121',
849                         '3' => '22111111',
850                         '4' => '11211211',
851                         '5' => '21111211',
852                         '6' => '12111121',
853                         '7' => '12112111',
854                         '8' => '12211111',
855                         '9' => '21121111',
856                         '-' => '11122111',
857                         '$' => '11221111',
858                         ':' => '21112121',
859                         '/' => '21211121',
860                         '.' => '21212111',
861                         '+' => '11222221',
862                         'A' => '11221211',
863                         'B' => '12121121',
864                         'C' => '11121221',
865                         'D' => '11122211'
866                 );
867                 
868                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
869                 $k = 0;
870                 $w = 0;
871                 $seq = "";
872                 $code = "A".strtoupper($code)."A";
873                 $len = strlen($code);
874                 for($i=0; $i < $len; $i++) {
875                         if (!isset($chr[$code{$i}])) {
876                                 return false;
877                         }
878                         $seq = $chr[$code{$i}];
879                         for($j=0; $j < 8; $j++) {
880                                 if (($j % 2) == 0) {
881                                         $t = true; // bar
882                                 } else {
883                                         $t = false; // space
884                                 }
885                                 $w = $seq{$j};
886                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
887                                 $bararray["maxw"] += $w;
888                                 $k++;
889                         }
890                 }
891                 return $bararray;
892         }
893         
894 } // end of class
895
896 //============================================================+
897 // END OF FILE                                                 
898 //============================================================+