4454ec997255512af2d5883215f324b7b79f3e7a
[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>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>POSTNET : POSTNET</li><li>CODABAR : CODABAR</li></ul>
83          */
84         function TCPDFBarcode($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>EAN13 : EAN 13</li><li>UPCA : UPC-A</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 "EAN13": { // EAN 13
137                                 $arrcode = $this->barcode_ean13($code, 13);
138                                 break;
139                         }
140                         case "UPCA": { // UPC-A
141                                 $arrcode = $this->barcode_ean13($code, 12);
142                                 break;
143                         }
144                         case "POSTNET": { // POSTNET
145                                 $arrcode = $this->barcode_postnet($code);
146                                 break;
147                         }
148                         case "CODABAR": { // CODABAR
149                                 $arrcode = $this->barcode_codabar($code);
150                                 break;
151                         }
152                         default: {
153                                 $this->barcode_array = false;
154                         }
155                 }
156                 $this->barcode_array = $arrcode;
157         }
158         
159         /**
160          * CODE 39
161          * @param string $code code to represent.
162          * @param boolean $checksum if true add a checksum to the code
163          * @return array barcode representation.
164          * @access protected
165          */
166         function barcode_code39($code, $extended=false, $checksum=false) {
167                 $chr['0'] = '111221211';
168                 $chr['1'] = '211211112';
169                 $chr['2'] = '112211112';
170                 $chr['3'] = '212211111';
171                 $chr['4'] = '111221112';
172                 $chr['5'] = '211221111';
173                 $chr['6'] = '112221111';
174                 $chr['7'] = '111211212';
175                 $chr['8'] = '211211211';
176                 $chr['9'] = '112211211';
177                 $chr['A'] = '211112112';
178                 $chr['B'] = '112112112';
179                 $chr['C'] = '212112111';
180                 $chr['D'] = '111122112';
181                 $chr['E'] = '211122111';
182                 $chr['F'] = '112122111';
183                 $chr['G'] = '111112212';
184                 $chr['H'] = '211112211';
185                 $chr['I'] = '112112211';
186                 $chr['J'] = '111122211';
187                 $chr['K'] = '211111122';
188                 $chr['L'] = '112111122';
189                 $chr['M'] = '212111121';
190                 $chr['N'] = '111121122';
191                 $chr['O'] = '211121121';
192                 $chr['P'] = '112121121';
193                 $chr['Q'] = '111111222';
194                 $chr['R'] = '211111221';
195                 $chr['S'] = '112111221';
196                 $chr['T'] = '111121221';
197                 $chr['U'] = '221111112';
198                 $chr['V'] = '122111112';
199                 $chr['W'] = '222111111';
200                 $chr['X'] = '121121112';
201                 $chr['Y'] = '221121111';
202                 $chr['Z'] = '122121111';
203                 $chr['-'] = '121111212';
204                 $chr['.'] = '221111211';
205                 $chr[' '] = '122111211';
206                 $chr['*'] = '121121211';
207                 $chr['$'] = '121212111';
208                 $chr['/'] = '121211121';
209                 $chr['+'] = '121112121';
210                 $chr['%'] = '111212121';
211                 
212                 $code = strtoupper($code);
213                 if ($extended) {
214                         // extended mode
215                         $code = $this->encode_code39_ext($code);
216                 }
217                 if ($code === false) {
218                         return false;
219                 }
220                 if ($checksum) {
221                         // checksum
222                         $code .= $this->checksum_code39($code);
223                 }
224                 // add start and stop codes
225                 $code = "*".$code."*";
226                 
227                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
228                 $k = 0;
229                 for($i=0; $i < strlen($code); $i++) {
230                         $char = $code{$i};
231                         if(!isset($chr[$char])) {
232                                 // invalid character
233                                 return false;
234                         }
235                         for($j=0; $j < 9; $j++) {
236                                 if (($j % 2) == 0) {
237                                         $t = true; // bar
238                                 } else {
239                                         $t = false; // space
240                                 }
241                                 $w = $chr[$char]{$j};
242                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
243                                 $bararray["maxw"] += $w;
244                                 $k++;
245                         }
246                         $bararray["bcode"][$k] = array("t" => false, "w" => 1, "h" => 1, "p" => 0);
247                         $bararray["maxw"] += 1;
248                         $k++;
249                 }
250                 return $bararray;
251         }
252         
253         /**
254          * Encode a string to be used for CODE 39 Extended mode.
255          * @param string $code code to represent.
256          * @return encoded string.
257          * @access protected
258          */
259         function encode_code39_ext($code) {
260                 $encode = array(
261                         chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
262                         chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
263                         chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
264                         chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
265                         chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
266                         chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
267                         chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
268                         chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
269                         chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
270                         chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
271                         chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
272                         chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
273                         chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
274                         chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
275                         chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
276                         chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
277                         chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
278                         chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
279                         chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
280                         chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
281                         chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
282                         chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
283                         chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
284                         chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
285                         chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
286                         chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
287                         chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
288                         chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
289                         chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
290                         chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
291                         chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
292                         chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
293                 $code_ext = '';
294                 for ($i = 0 ; $i < strlen($code); $i++) {
295                         if (ord($code{$i}) > 127) {
296                                 return false;
297                         }
298                         $code_ext .= $encode[$code{$i}];
299                 }
300                 return $code_ext;
301         }
302         
303         /**
304          * Calculate CODE 39 checksum (modulo 43).
305          * @param string $code code to represent.
306          * @return char checksum.
307          * @access protected
308          */
309         function checksum_code39($code) {
310                 $chars = array(
311                         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
312                         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
313                         'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
314                         'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
315                 $sum = 0;
316                 for ($i=0 ; $i < strlen($code); $i++) {
317                         $k = array_keys($chars, $code{$i});
318                         $sum += $k[0];
319                 }
320                 $j = ($sum % 43);
321                 return $chars[$j];
322         }
323         
324         /**
325          * Interleaved 2 of 5 barcodes. 
326          * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
327          * @param string $code code to represent.
328          * @param boolean $checksum if true add a checksum to the code
329          * @return array barcode representation.
330          * @access protected
331          */
332         function barcode_i25($code) {
333                 $chr['0'] = '11221';
334                 $chr['1'] = '21112';
335                 $chr['2'] = '12112';
336                 $chr['3'] = '22111';
337                 $chr['4'] = '11212';
338                 $chr['5'] = '21211';
339                 $chr['6'] = '12211';
340                 $chr['7'] = '11122';
341                 $chr['8'] = '21121';
342                 $chr['9'] = '12121';
343                 $chr['A'] = '11';
344                 $chr['Z'] = '21';
345                 
346                 if((strlen($code) % 2) != 0) {
347                         // add leading zero if code-length is odd
348                         $code = '0'.$code;
349                 }
350                 // add start and stop codes
351                 $code = 'AA'.strtolower($code).'ZA';
352                         
353                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
354                 $k = 0;
355                 for($i=0; $i < strlen($code); $i=$i+2) {
356                         $char_bar = $code{$i};
357                         $char_space = $code{$i+1};
358                         if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) {
359                                 // invalid character
360                                 return false;
361                         }
362                         // create a bar-space sequence
363                         $seq = "";
364                         for($s=0; $s < strlen($chr[$char_bar]); $s++){
365                                 $seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s};
366                         }
367                         for($j=0; $j < strlen($seq); $j++) {
368                                 if (($j % 2) == 0) {
369                                         $t = true; // bar
370                                 } else {
371                                         $t = false; // space
372                                 }
373                                 $w = $seq{$j};
374                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
375                                 $bararray["maxw"] += $w;
376                                 $k++;
377                         }
378                 }
379                 return $bararray;
380         }
381         
382         /**
383          * C128 barcodes. 
384          * 
385          * @param string $code code to represent.
386          * @param string $type barcode type: A, B or C
387          * @return array barcode representation.
388          * @access protected
389          */
390         function barcode_c128($code, $type="B") {
391                 $chr = array(
392                         '212222', /* 00 */
393                         '222122', /* 01 */
394                         '222221', /* 02 */
395                         '121223', /* 03 */
396                         '121322', /* 04 */
397                         '131222', /* 05 */
398                         '122213', /* 06 */
399                         '122312', /* 07 */
400                         '132212', /* 08 */
401                         '221213', /* 09 */
402                         '221312', /* 10 */
403                         '231212', /* 11 */
404                         '112232', /* 12 */
405                         '122132', /* 13 */
406                         '122231', /* 14 */
407                         '113222', /* 15 */
408                         '123122', /* 16 */
409                         '123221', /* 17 */
410                         '223211', /* 18 */
411                         '221132', /* 19 */
412                         '221231', /* 20 */
413                         '213212', /* 21 */
414                         '223112', /* 22 */
415                         '312131', /* 23 */
416                         '311222', /* 24 */
417                         '321122', /* 25 */
418                         '321221', /* 26 */
419                         '312212', /* 27 */
420                         '322112', /* 28 */
421                         '322211', /* 29 */
422                         '212123', /* 30 */
423                         '212321', /* 31 */
424                         '232121', /* 32 */
425                         '111323', /* 33 */
426                         '131123', /* 34 */
427                         '131321', /* 35 */
428                         '112313', /* 36 */
429                         '132113', /* 37 */
430                         '132311', /* 38 */
431                         '211313', /* 39 */
432                         '231113', /* 40 */
433                         '231311', /* 41 */
434                         '112133', /* 42 */
435                         '112331', /* 43 */
436                         '132131', /* 44 */
437                         '113123', /* 45 */
438                         '113321', /* 46 */
439                         '133121', /* 47 */
440                         '313121', /* 48 */
441                         '211331', /* 49 */
442                         '231131', /* 50 */
443                         '213113', /* 51 */
444                         '213311', /* 52 */
445                         '213131', /* 53 */
446                         '311123', /* 54 */
447                         '311321', /* 55 */
448                         '331121', /* 56 */
449                         '312113', /* 57 */
450                         '312311', /* 58 */
451                         '332111', /* 59 */
452                         '314111', /* 60 */
453                         '221411', /* 61 */
454                         '431111', /* 62 */
455                         '111224', /* 63 */
456                         '111422', /* 64 */
457                         '121124', /* 65 */
458                         '121421', /* 66 */
459                         '141122', /* 67 */
460                         '141221', /* 68 */
461                         '112214', /* 69 */
462                         '112412', /* 70 */
463                         '122114', /* 71 */
464                         '122411', /* 72 */
465                         '142112', /* 73 */
466                         '142211', /* 74 */
467                         '241211', /* 75 */
468                         '221114', /* 76 */
469                         '413111', /* 77 */
470                         '241112', /* 78 */
471                         '134111', /* 79 */
472                         '111242', /* 80 */
473                         '121142', /* 81 */
474                         '121241', /* 82 */
475                         '114212', /* 83 */
476                         '124112', /* 84 */
477                         '124211', /* 85 */
478                         '411212', /* 86 */
479                         '421112', /* 87 */
480                         '421211', /* 88 */
481                         '212141', /* 89 */
482                         '214121', /* 90 */
483                         '412121', /* 91 */
484                         '111143', /* 92 */
485                         '111341', /* 93 */
486                         '131141', /* 94 */
487                         '114113', /* 95 */
488                         '114311', /* 96 */
489                         '411113', /* 97 */
490                         '411311', /* 98 */
491                         '113141', /* 99 */
492                         '114131', /* 100 */
493                         '311141', /* 101 */
494                         '411131', /* 102 */
495                         '211412', /* 103 START A */
496                         '211214', /* 104 START B  */
497                         '211232', /* 105 START C  */
498                         '233111',       /* STOP */
499                         '200000'        /* END */
500                 );
501                 $keys = "";
502                 switch(strtoupper($type)) {
503                         case "A": {
504                                 $startid = 103;
505                                 $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
506                                 for($i = 0; $i < 32; $i++) {
507                                         $keys .= chr($i);
508                                 }
509                                 break;
510                         }
511                         case "B": {
512                                 $startid = 104;
513                                 $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127);
514                                 break;
515                         }
516                         case "C": {
517                                 $startid = 105;
518                                 $keys = "";
519                                 if ((strlen($code) % 2) != 0) {
520                                         //echo "The length of barcode value must be even ($code). You must pad the number with zeros.\n";
521                                         return false;
522                                 }
523                                 for($i = 0; $i <= 99; $i++) {
524                                         $keys .= chr($i);
525                                 }
526                                 $new_code = "";
527                                 for ($i=0; $i < (strlen($code) / 2); $i++) {
528                                         $new_code .= chr(intval($code{(2 * $i)}.$code{(2 * $i + 1)}));
529                                 }
530                                 $code = $new_code;
531                                 break;
532                         }
533                         default: {
534                                 return false;
535                         }
536                 }
537                 // calculate check character
538                 $sum = $startid;
539                 for ($i=0; $i < strlen($code); $i++) {
540                         $sum +=  (strpos($keys, $code{$i}) * ($i+1));
541                 }
542                 $check = ($sum % 103);
543                 
544                 // add start, check and stop codes
545                 $code = chr($startid).$code.chr($check).chr(106).chr(107);
546                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
547                 $k = 0;
548                 $len = strlen($code);
549                 for($i=0; $i < $len; $i++) {
550                         $ck = strpos($keys, $code{$i});
551                         if (($i == 0) OR ($i > ($len-4))) {
552                                 $seq = $chr[ord($code{$i})];
553                         } elseif(($ck >= 0) AND isset($chr[$ck])) {
554                                         $seq = $chr[$ck];
555                         } else {
556                                 // invalid character
557                                 return false;
558                         }
559                         for($j=0; $j < 6; $j++) {
560                                 if (($j % 2) == 0) {
561                                         $t = true; // bar
562                                 } else {
563                                         $t = false; // space
564                                 }
565                                 $w = $seq{$j};
566                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
567                                 $bararray["maxw"] += $w;
568                                 $k++;
569                         }
570                 }
571                 return $bararray;               
572         }
573         
574         /**
575          * EAN13 and UPC-A barcodes.
576          * @param string $code code to represent.
577          * @param string $len barcode type: 13 = EAN13, 12 = UPC-A
578          * @return array barcode representation.
579          * @access protected
580          */
581         function barcode_ean13($code, $len=13) {
582                 //Padding
583                 $code = str_pad($code, $len-1, '0', STR_PAD_LEFT);
584                 if($len == 12) {
585                         $code = '0'.$code;
586                 }
587                 // add check digit
588                 if(strlen($code) == 12) {
589                         $sum=0;
590                         for($i=1;$i<=11;$i+=2) {
591                                 $sum += (3 * $code{$i});
592                         }
593                         for($i=0; $i <= 10; $i+=2) {
594                                 $sum += ($code{$i});
595                         }
596                         $r = $sum % 10;
597                         if($r > 0) {
598                                 $r = (10 - $r);
599                         }
600                         $code .= $r;
601                 } else { // test checkdigit
602                         $sum = 0;
603                         for($i=1; $i <= 11; $i+=2) {
604                                 $sum += (3 * $code{$i});
605                         }
606                         for($i=0; $i <= 10; $i+=2) {
607                                 $sum += $code{$i};
608                         }
609                         if ((($sum + $code{12}) % 10) != 0) {
610                                 return false;
611                         }
612                 }
613                 //Convert digits to bars
614                 $codes = array(
615                         'A'=>array(
616                                 '0'=>'0001101',
617                                 '1'=>'0011001',
618                                 '2'=>'0010011',
619                                 '3'=>'0111101',
620                                 '4'=>'0100011',
621                                 '5'=>'0110001',
622                                 '6'=>'0101111',
623                                 '7'=>'0111011',
624                                 '8'=>'0110111',
625                                 '9'=>'0001011'),
626                         'B'=>array(
627                                 '0'=>'0100111',
628                                 '1'=>'0110011',
629                                 '2'=>'0011011',
630                                 '3'=>'0100001',
631                                 '4'=>'0011101',
632                                 '5'=>'0111001',
633                                 '6'=>'0000101',
634                                 '7'=>'0010001',
635                                 '8'=>'0001001',
636                                 '9'=>'0010111'),
637                         'C'=>array(
638                                 '0'=>'1110010',
639                                 '1'=>'1100110',
640                                 '2'=>'1101100',
641                                 '3'=>'1000010',
642                                 '4'=>'1011100',
643                                 '5'=>'1001110',
644                                 '6'=>'1010000',
645                                 '7'=>'1000100',
646                                 '8'=>'1001000',
647                                 '9'=>'1110100')
648                 );
649                 $parities = array(
650                         '0'=>array('A','A','A','A','A','A'),
651                         '1'=>array('A','A','B','A','B','B'),
652                         '2'=>array('A','A','B','B','A','B'),
653                         '3'=>array('A','A','B','B','B','A'),
654                         '4'=>array('A','B','A','A','B','B'),
655                         '5'=>array('A','B','B','A','A','B'),
656                         '6'=>array('A','B','B','B','A','A'),
657                         '7'=>array('A','B','A','B','A','B'),
658                         '8'=>array('A','B','A','B','B','A'),
659                         '9'=>array('A','B','B','A','B','A')
660                 );
661                 
662                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
663                 $k = 0;
664                 $seq = '101';
665                 $p = $parities[$code{0}];
666                 for($i=1; $i < 7; $i++) {
667                         $seq .= $codes[$p[$i-1]][$code{$i}];
668                 }
669                 $seq .= '01010';
670                 for($i=7; $i < 13; $i++) {
671                         $seq .= $codes['C'][$code{$i}];
672                 }
673                 $seq .= '101';
674                 $len = strlen($seq);
675                 $w = 0;
676                 for($i=0; $i < $len; $i++) {
677                         $w += 1;
678                         if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
679                                 if ($seq{$i} == '1') {
680                                         $t = true; // bar
681                                 } else {
682                                         $t = false; // space
683                                 }
684                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
685                                 $bararray["maxw"] += $w;
686                                 $k++;
687                                 $w = 0;
688                         }
689                 }
690                 return $bararray;
691         }
692         
693         /**
694          * POSTNET barcodes.
695          * @param string $code zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD.
696          * @return array barcode representation.
697          * @access protected
698          */
699         function barcode_postnet($code) {
700                 // bar lenght
701                 $barlen = Array(
702                         0 => Array(2,2,1,1,1),
703                         1 => Array(1,1,1,2,2),
704                         2 => Array(1,1,2,1,2),
705                         3 => Array(1,1,2,2,1),
706                         4 => Array(1,2,1,1,2),
707                         5 => Array(1,2,1,2,1),
708                         6 => Array(1,2,2,1,1),
709                         7 => Array(2,1,1,1,2),
710                         8 => Array(2,1,1,2,1),
711                         9 => Array(2,1,2,1,1)
712                 );
713                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 2, "bcode" => array());
714                 $k = 0;
715                 $code = str_replace("-", "", $code);
716                 $code = str_replace(" ", "", $code);
717                 $len = strlen($code);
718                 // calculate checksum
719                 $sum = 0;
720                 for($i=0; $i < $len; $i++) {
721                         $sum += intval($code{$i});
722                 }
723                 if(($sum % 10) == 0) {
724                         return false;
725                 }
726                 $code .= "".(10 - ($sum % 10))."";
727                 $len = strlen($code);
728                 // start bar
729                 $bararray["bcode"][$k++] = array("t" => 1, "w" => 1, "h" => 2, "p" => 0);
730                 $bararray["bcode"][$k++] = array("t" => 0, "w" => 1, "h" => 2, "p" => 0);
731                 $bararray["maxw"] += 2;
732                 for ($i=0; $i < $len; $i++) {
733                         for ($j=0; $j < 5; $j++) {
734                                 $h = $barlen[$code{$i}][$j];
735                                 $p = floor(1 / $h);
736                                 $bararray["bcode"][$k++] = array("t" => 1, "w" => 1, "h" => $h, "p" => $p);
737                                 $bararray["bcode"][$k++] = array("t" => 0, "w" => 1, "h" => 2, "p" => 0);
738                                 $bararray["maxw"] += 2;
739                         }
740                 }
741                 // end bar
742                 $bararray["bcode"][$k++] = array("t" => 1, "w" => 1, "h" => 2, "p" => 0);
743                 $bararray["maxw"] += 1;
744                 return $bararray;
745         }
746         
747         /**
748          * CODABAR barcodes.
749          * @param string $code code to represent.
750          * @return array barcode representation.
751          * @access protected
752          */
753         function barcode_codabar($code) {
754                 $chr = array(
755                         '0' => '11111221',
756                         '1' => '11112211',
757                         '2' => '11121121',
758                         '3' => '22111111',
759                         '4' => '11211211',
760                         '5' => '21111211',
761                         '6' => '12111121',
762                         '7' => '12112111',
763                         '8' => '12211111',
764                         '9' => '21121111',
765                         '-' => '11122111',
766                         '$' => '11221111',
767                         ':' => '21112121',
768                         '/' => '21211121',
769                         '.' => '21212111',
770                         '+' => '11222221',
771                         'A' => '11221211',
772                         'B' => '12121121',
773                         'C' => '11121221',
774                         'D' => '11122211'
775                 );
776                 
777                 $bararray = array("code" => $code, "maxw" => 0, "maxh" => 1, "bcode" => array());
778                 $k = 0;
779                 $w = 0;
780                 $seq = "";
781                 $code = "A".strtoupper($code)."A";
782                 $len = strlen($code);
783                 for($i=0; $i < $len; $i++) {
784                         if (!isset($chr[$code{$i}])) {
785                                 return false;
786                         }
787                         $seq = $chr[$code{$i}];
788                         for($j=0; $j < 8; $j++) {
789                                 if (($j % 2) == 0) {
790                                         $t = true; // bar
791                                 } else {
792                                         $t = false; // space
793                                 }
794                                 $w = $seq{$j};
795                                 $bararray["bcode"][$k] = array("t" => $t, "w" => $w, "h" => 1, "p" => 0);
796                                 $bararray["maxw"] += $w;
797                                 $k++;
798                         }
799                 }
800                 return $bararray;
801         }
802         
803 } // end of class
804
805 //============================================================+
806 // END OF FILE                                                 
807 //============================================================+