PageRenderTime 543ms CodeModel.GetById 101ms app.highlight 319ms RepoModel.GetById 103ms app.codeStats 1ms

/framework/lib/classes/PHPExcel/Shared/PDF/barcodes.php

https://bitbucket.org/designbyheart/original
PHP | 1969 lines | 1591 code | 37 blank | 341 comment | 195 complexity | 84339878993325c7228b6b22fb4e9f22 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2//============================================================+
   3// File name   : barcodes.php
   4// Version     : 1.0.011
   5// Begin       : 2008-06-09
   6// Last Update : 2010-08-08
   7// Author      : Nicola Asuni - Tecnick.com S.r.l - Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
   8// License     : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
   9// -------------------------------------------------------------------
  10// Copyright (C) 2008-2010  Nicola Asuni - Tecnick.com S.r.l.
  11//
  12// This file is part of TCPDF software library.
  13//
  14// TCPDF is free software: you can redistribute it and/or modify it
  15// under the terms of the GNU Lesser General Public License as
  16// published by the Free Software Foundation, either version 3 of the
  17// License, or (at your option) any later version.
  18//
  19// TCPDF is distributed in the hope that it will be useful, but
  20// WITHOUT ANY WARRANTY; without even the implied warranty of
  21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  22// See the GNU Lesser General Public License for more details.
  23//
  24// You should have received a copy of the GNU Lesser General Public License
  25// along with TCPDF.  If not, see <http://www.gnu.org/licenses/>.
  26//
  27// See LICENSE.TXT file for more information.
  28// -------------------------------------------------------------------
  29//
  30// Description : PHP class to creates array representations for
  31//               common 1D barcodes to be used with TCPDF.
  32//
  33//============================================================+
  34
  35/**
  36 * PHP class to creates array representations for common 1D barcodes to be used with TCPDF.
  37 * @package com.tecnick.tcpdf
  38 * @abstract Functions for generating string representation of common 1D barcodes.
  39 * @author Nicola Asuni
  40 * @copyright 2008-2009 Nicola Asuni - Tecnick.com S.r.l (www.tecnick.com) Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com
  41 * @link http://www.tcpdf.org
  42 * @license http://www.gnu.org/copyleft/lesser.html LGPL
  43 * @version 1.0.011
  44 */
  45
  46	/**
  47	* PHP class to creates array representations for common 1D barcodes to be used with TCPDF (http://www.tcpdf.org).<br>
  48	* @name TCPDFBarcode
  49	* @package com.tecnick.tcpdf
  50	* @version 1.0.011
  51	* @author Nicola Asuni
  52	* @link http://www.tcpdf.org
  53	* @license http://www.gnu.org/copyleft/lesser.html LGPL
  54	*/
  55class TCPDFBarcode {
  56
  57	/**
  58	 * @var array representation of barcode.
  59	 * @access protected
  60	 */
  61	protected $barcode_array;
  62
  63	/**
  64	 * This is the class constructor.
  65	 * Return an array representations for common 1D barcodes:<ul>
  66	 * <li>$arrcode['code'] code to be printed on text label</li>
  67	 * <li>$arrcode['maxh'] max bar height</li>
  68	 * <li>$arrcode['maxw'] max bar width</li>
  69	 * <li>$arrcode['bcode'][$k] single bar or space in $k position</li>
  70	 * <li>$arrcode['bcode'][$k]['t'] bar type: true = bar, false = space.</li>
  71	 * <li>$arrcode['bcode'][$k]['w'] bar width in units.</li>
  72	 * <li>$arrcode['bcode'][$k]['h'] bar height in units.</li>
  73	 * <li>$arrcode['bcode'][$k]['p'] bar top position (0 = top, 1 = middle)</li></ul>
  74	 * @param string $code code to print
  75 	 * @param string $type type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</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 Extention</li><li>EAN5 : 5-Digits UPC-Based Extention</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul>
  76	 */
  77	public function __construct($code, $type) {
  78		$this->setBarcode($code, $type);
  79	}
  80
  81	/**
  82	 * Return an array representations of barcode.
  83 	 * @return array
  84	 */
  85	public function getBarcodeArray() {
  86		return $this->barcode_array;
  87	}
  88
  89	/**
  90	 * Set the barcode.
  91	 * @param string $code code to print
  92 	 * @param string $type type of barcode: <ul><li>C39 : CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.</li><li>C39+ : CODE 39 with checksum</li><li>C39E : CODE 39 EXTENDED</li><li>C39E+ : CODE 39 EXTENDED + CHECKSUM</li><li>C93 : CODE 93 - USS-93</li><li>S25 : Standard 2 of 5</li><li>S25+ : Standard 2 of 5 + CHECKSUM</li><li>I25 : Interleaved 2 of 5</li><li>I25+ : Interleaved 2 of 5 + CHECKSUM</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 Extention</li><li>EAN5 : 5-Digits UPC-Based Extention</li><li>EAN8 : EAN 8</li><li>EAN13 : EAN 13</li><li>UPCA : UPC-A</li><li>UPCE : UPC-E</li><li>MSI : MSI (Variation of Plessey code)</li><li>MSI+ : MSI + CHECKSUM (modulo 11)</li><li>POSTNET : POSTNET</li><li>PLANET : PLANET</li><li>RMS4CC : RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)</li><li>KIX : KIX (Klant index - Customer index)</li><li>IMB: Intelligent Mail Barcode - Onecode - USPS-B-3200</li><li>CODABAR : CODABAR</li><li>CODE11 : CODE 11</li><li>PHARMA : PHARMACODE</li><li>PHARMA2T : PHARMACODE TWO-TRACKS</li></ul>
  93 	 * @return array
  94	 */
  95	public function setBarcode($code, $type) {
  96		switch (strtoupper($type)) {
  97			case 'C39': { // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
  98				$arrcode = $this->barcode_code39($code, false, false);
  99				break;
 100			}
 101			case 'C39+': { // CODE 39 with checksum
 102				$arrcode = $this->barcode_code39($code, false, true);
 103				break;
 104			}
 105			case 'C39E': { // CODE 39 EXTENDED
 106				$arrcode = $this->barcode_code39($code, true, false);
 107				break;
 108			}
 109			case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM
 110				$arrcode = $this->barcode_code39($code, true, true);
 111				break;
 112			}
 113			case 'C93': { // CODE 93 - USS-93
 114				$arrcode = $this->barcode_code93($code);
 115				break;
 116			}
 117			case 'S25': { // Standard 2 of 5
 118				$arrcode = $this->barcode_s25($code, false);
 119				break;
 120			}
 121			case 'S25+': { // Standard 2 of 5 + CHECKSUM
 122				$arrcode = $this->barcode_s25($code, true);
 123				break;
 124			}
 125			case 'I25': { // Interleaved 2 of 5
 126				$arrcode = $this->barcode_i25($code, false);
 127				break;
 128			}
 129			case 'I25+': { // Interleaved 2 of 5 + CHECKSUM
 130				$arrcode = $this->barcode_i25($code, true);
 131				break;
 132			}
 133			case 'C128A': { // CODE 128 A
 134				$arrcode = $this->barcode_c128($code, 'A');
 135				break;
 136			}
 137			case 'C128B': { // CODE 128 B
 138				$arrcode = $this->barcode_c128($code, 'B');
 139				break;
 140			}
 141			case 'C128C': { // CODE 128 C
 142				$arrcode = $this->barcode_c128($code, 'C');
 143				break;
 144			}
 145			case 'EAN2': { // 2-Digits UPC-Based Extention
 146				$arrcode = $this->barcode_eanext($code, 2);
 147				break;
 148			}
 149			case 'EAN5': { // 5-Digits UPC-Based Extention
 150				$arrcode = $this->barcode_eanext($code, 5);
 151				break;
 152			}
 153			case 'EAN8': { // EAN 8
 154				$arrcode = $this->barcode_eanupc($code, 8);
 155				break;
 156			}
 157			case 'EAN13': { // EAN 13
 158				$arrcode = $this->barcode_eanupc($code, 13);
 159				break;
 160			}
 161			case 'UPCA': { // UPC-A
 162				$arrcode = $this->barcode_eanupc($code, 12);
 163				break;
 164			}
 165			case 'UPCE': { // UPC-E
 166				$arrcode = $this->barcode_eanupc($code, 6);
 167				break;
 168			}
 169			case 'MSI': { // MSI (Variation of Plessey code)
 170				$arrcode = $this->barcode_msi($code, false);
 171				break;
 172			}
 173			case 'MSI+': { // MSI + CHECKSUM (modulo 11)
 174				$arrcode = $this->barcode_msi($code, true);
 175				break;
 176			}
 177			case 'POSTNET': { // POSTNET
 178				$arrcode = $this->barcode_postnet($code, false);
 179				break;
 180			}
 181			case 'PLANET': { // PLANET
 182				$arrcode = $this->barcode_postnet($code, true);
 183				break;
 184			}
 185			case 'RMS4CC': { // RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
 186				$arrcode = $this->barcode_rms4cc($code, false);
 187				break;
 188			}
 189			case 'KIX': { // KIX (Klant index - Customer index)
 190				$arrcode = $this->barcode_rms4cc($code, true);
 191				break;
 192			}
 193			case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
 194				$arrcode = $this->barcode_imb($code);
 195				break;
 196			}
 197			case 'CODABAR': { // CODABAR
 198				$arrcode = $this->barcode_codabar($code);
 199				break;
 200			}
 201			case 'CODE11': { // CODE 11
 202				$arrcode = $this->barcode_code11($code);
 203				break;
 204			}
 205			case 'PHARMA': { // PHARMACODE
 206				$arrcode = $this->barcode_pharmacode($code);
 207				break;
 208			}
 209			case 'PHARMA2T': { // PHARMACODE TWO-TRACKS
 210				$arrcode = $this->barcode_pharmacode2t($code);
 211				break;
 212			}
 213			default: {
 214				$this->barcode_array = false;
 215				$arrcode = false;
 216				break;
 217			}
 218		}
 219		$this->barcode_array = $arrcode;
 220	}
 221
 222	/**
 223	 * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
 224	 * General-purpose code in very wide use world-wide
 225	 * @param string $code code to represent.
 226	 * @param boolean $checksum if true add a checksum to the code
 227	 * @return array barcode representation.
 228	 * @access protected
 229	 */
 230	protected function barcode_code39($code, $extended=false, $checksum=false) {
 231		$chr['0'] = '111221211';
 232		$chr['1'] = '211211112';
 233		$chr['2'] = '112211112';
 234		$chr['3'] = '212211111';
 235		$chr['4'] = '111221112';
 236		$chr['5'] = '211221111';
 237		$chr['6'] = '112221111';
 238		$chr['7'] = '111211212';
 239		$chr['8'] = '211211211';
 240		$chr['9'] = '112211211';
 241		$chr['A'] = '211112112';
 242		$chr['B'] = '112112112';
 243		$chr['C'] = '212112111';
 244		$chr['D'] = '111122112';
 245		$chr['E'] = '211122111';
 246		$chr['F'] = '112122111';
 247		$chr['G'] = '111112212';
 248		$chr['H'] = '211112211';
 249		$chr['I'] = '112112211';
 250		$chr['J'] = '111122211';
 251		$chr['K'] = '211111122';
 252		$chr['L'] = '112111122';
 253		$chr['M'] = '212111121';
 254		$chr['N'] = '111121122';
 255		$chr['O'] = '211121121';
 256		$chr['P'] = '112121121';
 257		$chr['Q'] = '111111222';
 258		$chr['R'] = '211111221';
 259		$chr['S'] = '112111221';
 260		$chr['T'] = '111121221';
 261		$chr['U'] = '221111112';
 262		$chr['V'] = '122111112';
 263		$chr['W'] = '222111111';
 264		$chr['X'] = '121121112';
 265		$chr['Y'] = '221121111';
 266		$chr['Z'] = '122121111';
 267		$chr['-'] = '121111212';
 268		$chr['.'] = '221111211';
 269		$chr[' '] = '122111211';
 270		$chr['$'] = '121212111';
 271		$chr['/'] = '121211121';
 272		$chr['+'] = '121112121';
 273		$chr['%'] = '111212121';
 274		$chr['*'] = '121121211';
 275
 276		$code = strtoupper($code);
 277		if ($extended) {
 278			// extended mode
 279			$code = $this->encode_code39_ext($code);
 280		}
 281		if ($code === false) {
 282			return false;
 283		}
 284		if ($checksum) {
 285			// checksum
 286			$code .= $this->checksum_code39($code);
 287		}
 288		// add start and stop codes
 289		$code = '*'.$code.'*';
 290
 291		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
 292		$k = 0;
 293		$clen = strlen($code);
 294		for ($i = 0; $i < $clen; ++$i) {
 295			$char = $code{$i};
 296			if(!isset($chr[$char])) {
 297				// invalid character
 298				return false;
 299			}
 300			for ($j = 0; $j < 9; ++$j) {
 301				if (($j % 2) == 0) {
 302					$t = true; // bar
 303				} else {
 304					$t = false; // space
 305				}
 306				$w = $chr[$char]{$j};
 307				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
 308				$bararray['maxw'] += $w;
 309				++$k;
 310			}
 311			$bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
 312			$bararray['maxw'] += 1;
 313			++$k;
 314		}
 315		return $bararray;
 316	}
 317
 318	/**
 319	 * Encode a string to be used for CODE 39 Extended mode.
 320	 * @param string $code code to represent.
 321	 * @return encoded string.
 322	 * @access protected
 323	 */
 324	protected function encode_code39_ext($code) {
 325		$encode = array(
 326			chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
 327			chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
 328			chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
 329			chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
 330			chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
 331			chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
 332			chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
 333			chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
 334			chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
 335			chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
 336			chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
 337			chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
 338			chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
 339			chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
 340			chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
 341			chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
 342			chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
 343			chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
 344			chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
 345			chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
 346			chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
 347			chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
 348			chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
 349			chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
 350			chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
 351			chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
 352			chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
 353			chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
 354			chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
 355			chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
 356			chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
 357			chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
 358		$code_ext = '';
 359		$clen = strlen($code);
 360		for ($i = 0 ; $i < $clen; ++$i) {
 361			if (ord($code{$i}) > 127) {
 362				return false;
 363			}
 364			$code_ext .= $encode[$code{$i}];
 365		}
 366		return $code_ext;
 367	}
 368
 369	/**
 370	 * Calculate CODE 39 checksum (modulo 43).
 371	 * @param string $code code to represent.
 372	 * @return char checksum.
 373	 * @access protected
 374	 */
 375	protected function checksum_code39($code) {
 376		$chars = array(
 377			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 378			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
 379			'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
 380			'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
 381		$sum = 0;
 382		$clen = strlen($code);
 383		for ($i = 0 ; $i < $clen; ++$i) {
 384			$k = array_keys($chars, $code{$i});
 385			$sum += $k[0];
 386		}
 387		$j = ($sum % 43);
 388		return $chars[$j];
 389	}
 390
 391	/**
 392	 * CODE 93 - USS-93
 393	 * Compact code similar to Code 39
 394	 * @param string $code code to represent.
 395	 * @param boolean $checksum if true add a checksum to the code
 396	 * @return array barcode representation.
 397	 * @access protected
 398	 */
 399	protected function barcode_code93($code) {
 400		$chr['0'] = '131112';
 401		$chr['1'] = '111213';
 402		$chr['2'] = '111312';
 403		$chr['3'] = '111411';
 404		$chr['4'] = '121113';
 405		$chr['5'] = '121212';
 406		$chr['6'] = '121311';
 407		$chr['7'] = '111114';
 408		$chr['8'] = '131211';
 409		$chr['9'] = '141111';
 410		$chr['A'] = '211113';
 411		$chr['B'] = '211212';
 412		$chr['C'] = '211311';
 413		$chr['D'] = '221112';
 414		$chr['E'] = '221211';
 415		$chr['F'] = '231111';
 416		$chr['G'] = '112113';
 417		$chr['H'] = '112212';
 418		$chr['I'] = '112311';
 419		$chr['J'] = '122112';
 420		$chr['K'] = '132111';
 421		$chr['L'] = '111123';
 422		$chr['M'] = '111222';
 423		$chr['N'] = '111321';
 424		$chr['O'] = '121122';
 425		$chr['P'] = '131121';
 426		$chr['Q'] = '212112';
 427		$chr['R'] = '212211';
 428		$chr['S'] = '211122';
 429		$chr['T'] = '211221';
 430		$chr['U'] = '221121';
 431		$chr['V'] = '222111';
 432		$chr['W'] = '112122';
 433		$chr['X'] = '112221';
 434		$chr['Y'] = '122121';
 435		$chr['Z'] = '123111';
 436		$chr['-'] = '121131';
 437		$chr['.'] = '311112';
 438		$chr[' '] = '311211';
 439		$chr['$'] = '321111';
 440		$chr['/'] = '112131';
 441		$chr['+'] = '113121';
 442		$chr['%'] = '211131';
 443		$chr[128] = '121221'; // ($)
 444		$chr[129] = '311121'; // (/)
 445		$chr[130] = '122211'; // (+)
 446		$chr[131] = '312111'; // (%)
 447		$chr['*'] = '111141';
 448		$code = strtoupper($code);
 449		$encode = array(
 450			chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C',
 451			chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G',
 452			chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K',
 453			chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O',
 454			chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S',
 455			chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W',
 456			chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A',
 457			chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E',
 458			chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C',
 459			chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G',
 460			chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K',
 461			chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O',
 462			chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
 463			chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
 464			chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F',
 465			chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J',
 466			chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
 467			chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
 468			chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
 469			chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
 470			chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
 471			chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
 472			chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K',
 473			chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O',
 474			chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C',
 475			chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G',
 476			chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K',
 477			chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O',
 478			chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S',
 479			chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W',
 480			chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P',
 481			chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T');
 482		$code_ext = '';
 483		$clen = strlen($code);
 484		for ($i = 0 ; $i < $clen; ++$i) {
 485			if (ord($code{$i}) > 127) {
 486				return false;
 487			}
 488			$code_ext .= $encode[$code{$i}];
 489		}
 490		// checksum
 491		$code .= $this->checksum_code93($code);
 492		// add start and stop codes
 493		$code = '*'.$code.'*';
 494		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
 495		$k = 0;
 496		$clen = strlen($code);
 497		for ($i = 0; $i < $clen; ++$i) {
 498			$char = $code{$i};
 499			if(!isset($chr[$char])) {
 500				// invalid character
 501				return false;
 502			}
 503			for ($j = 0; $j < 6; ++$j) {
 504				if (($j % 2) == 0) {
 505					$t = true; // bar
 506				} else {
 507					$t = false; // space
 508				}
 509				$w = $chr[$char]{$j};
 510				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
 511				$bararray['maxw'] += $w;
 512				++$k;
 513			}
 514		}
 515		$bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
 516		$bararray['maxw'] += 1;
 517		++$k;
 518		return $bararray;
 519	}
 520
 521	/**
 522	 * Calculate CODE 93 checksum (modulo 47).
 523	 * @param string $code code to represent.
 524	 * @return string checksum code.
 525	 * @access protected
 526	 */
 527	protected function checksum_code93($code) {
 528		$chars = array(
 529			'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
 530			'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
 531			'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
 532			'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
 533		// translate special characters
 534		$code = strtr($code, chr(128).chr(129).chr(130).chr(131), '$/+%');
 535		$len = strlen($code);
 536		// calculate check digit C
 537		$p = 1;
 538		$check = 0;
 539		for ($i = ($len - 1); $i >= 0; --$i) {
 540			$k = array_keys($chars, $code{$i});
 541			$check += ($k[0] * $p);
 542			++$p;
 543			if ($p > 20) {
 544				$p = 1;
 545			}
 546		}
 547		$check %= 47;
 548		$c = $chars[$check];
 549		$code .= $c;
 550		// calculate check digit K
 551		$p = 1;
 552		$check = 0;
 553		for ($i = $len; $i >= 0; --$i) {
 554			$k = array_keys($chars, $code{$i});
 555			$check += ($k[0] * $p);
 556			++$p;
 557			if ($p > 15) {
 558				$p = 1;
 559			}
 560		}
 561		$check %= 47;
 562		$k = $chars[$check];
 563		return $c.$k;
 564	}
 565
 566	/**
 567	 * Checksum for standard 2 of 5 barcodes.
 568	 * @param string $code code to process.
 569	 * @return int checksum.
 570	 * @access protected
 571	 */
 572	protected function checksum_s25($code) {
 573		$len = strlen($code);
 574		$sum = 0;
 575		for ($i = 0; $i < $len; $i+=2) {
 576			$sum += $code{$i};
 577		}
 578		$sum *= 3;
 579		for ($i = 1; $i < $len; $i+=2) {
 580			$sum += ($code{$i});
 581		}
 582		$r = $sum % 10;
 583		if($r > 0) {
 584			$r = (10 - $r);
 585		}
 586		return $r;
 587	}
 588
 589	/**
 590	 * MSI.
 591	 * Variation of Plessey code, with similar applications
 592	 * Contains digits (0 to 9) and encodes the data only in the width of bars.
 593	 * @param string $code code to represent.
 594	 * @param boolean $checksum if true add a checksum to the code (modulo 11)
 595	 * @return array barcode representation.
 596	 * @access protected
 597	 */
 598	protected function barcode_msi($code, $checksum=false) {
 599		$chr['0'] = '100100100100';
 600		$chr['1'] = '100100100110';
 601		$chr['2'] = '100100110100';
 602		$chr['3'] = '100100110110';
 603		$chr['4'] = '100110100100';
 604		$chr['5'] = '100110100110';
 605		$chr['6'] = '100110110100';
 606		$chr['7'] = '100110110110';
 607		$chr['8'] = '110100100100';
 608		$chr['9'] = '110100100110';
 609		$chr['A'] = '110100110100';
 610		$chr['B'] = '110100110110';
 611		$chr['C'] = '110110100100';
 612		$chr['D'] = '110110100110';
 613		$chr['E'] = '110110110100';
 614		$chr['F'] = '110110110110';
 615		if ($checksum) {
 616			// add checksum
 617			$clen = strlen($code);
 618			$p = 2;
 619			$check = 0;
 620			for ($i = ($clen - 1); $i >= 0; --$i) {
 621				$check += (hexdec($code{$i}) * $p);
 622				++$p;
 623				if ($p > 7) {
 624					$p = 2;
 625				}
 626			}
 627			$check %= 11;
 628			if ($check > 0) {
 629				$check = 11 - $check;
 630			}
 631			$code .= $check;
 632		}
 633		$seq = '110'; // left guard
 634		$clen = strlen($code);
 635		for ($i = 0; $i < $clen; ++$i) {
 636			$digit = $code{$i};
 637			if (!isset($chr[$digit])) {
 638				// invalid character
 639				return false;
 640			}
 641			$seq .= $chr[$digit];
 642		}
 643		$seq .= '1001'; // right guard
 644		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
 645		return $this->binseq_to_array($seq, $bararray);
 646	}
 647
 648	/**
 649	 * Standard 2 of 5 barcodes.
 650	 * Used in airline ticket marking, photofinishing
 651	 * Contains digits (0 to 9) and encodes the data only in the width of bars.
 652	 * @param string $code code to represent.
 653	 * @param boolean $checksum if true add a checksum to the code
 654	 * @return array barcode representation.
 655	 * @access protected
 656	 */
 657	protected function barcode_s25($code, $checksum=false) {
 658		$chr['0'] = '10101110111010';
 659		$chr['1'] = '11101010101110';
 660		$chr['2'] = '10111010101110';
 661		$chr['3'] = '11101110101010';
 662		$chr['4'] = '10101110101110';
 663		$chr['5'] = '11101011101010';
 664		$chr['6'] = '10111011101010';
 665		$chr['7'] = '10101011101110';
 666		$chr['8'] = '10101110111010';
 667		$chr['9'] = '10111010111010';
 668		if ($checksum) {
 669			// add checksum
 670			$code .= $this->checksum_s25($code);
 671		}
 672		if((strlen($code) % 2) != 0) {
 673			// add leading zero if code-length is odd
 674			$code = '0'.$code;
 675		}
 676		$seq = '11011010';
 677		$clen = strlen($code);
 678		for ($i = 0; $i < $clen; ++$i) {
 679			$digit = $code{$i};
 680			if (!isset($chr[$digit])) {
 681				// invalid character
 682				return false;
 683			}
 684			$seq .= $chr[$digit];
 685		}
 686		$seq .= '1101011';
 687		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
 688		return $this->binseq_to_array($seq, $bararray);
 689	}
 690
 691	/**
 692	 * Convert binary barcode sequence to TCPDF barcode array
 693	 * @param string $seq barcode as binary sequence
 694	 * òparam array $bararray TCPDF barcode array to fill up
 695	 * @return array barcode representation.
 696	 * @access protected
 697	 */
 698	protected function binseq_to_array($seq, $bararray) {
 699		$len = strlen($seq);
 700		$w = 0;
 701		$k = 0;
 702		for ($i = 0; $i < $len; ++$i) {
 703			$w += 1;
 704			if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
 705				if ($seq{$i} == '1') {
 706					$t = true; // bar
 707				} else {
 708					$t = false; // space
 709				}
 710				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
 711				$bararray['maxw'] += $w;
 712				++$k;
 713				$w = 0;
 714			}
 715		}
 716		return $bararray;
 717	}
 718
 719	/**
 720	 * Interleaved 2 of 5 barcodes.
 721	 * Compact numeric code, widely used in industry, air cargo
 722	 * Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
 723	 * @param string $code code to represent.
 724	 * @param boolean $checksum if true add a checksum to the code
 725	 * @return array barcode representation.
 726	 * @access protected
 727	 */
 728	protected function barcode_i25($code, $checksum=false) {
 729		$chr['0'] = '11221';
 730		$chr['1'] = '21112';
 731		$chr['2'] = '12112';
 732		$chr['3'] = '22111';
 733		$chr['4'] = '11212';
 734		$chr['5'] = '21211';
 735		$chr['6'] = '12211';
 736		$chr['7'] = '11122';
 737		$chr['8'] = '21121';
 738		$chr['9'] = '12121';
 739		$chr['A'] = '11';
 740		$chr['Z'] = '21';
 741		if ($checksum) {
 742			// add checksum
 743			$code .= $this->checksum_s25($code);
 744		}
 745		if((strlen($code) % 2) != 0) {
 746			// add leading zero if code-length is odd
 747			$code = '0'.$code;
 748		}
 749		// add start and stop codes
 750		$code = 'AA'.strtolower($code).'ZA';
 751
 752		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
 753		$k = 0;
 754		$clen = strlen($code);
 755		for ($i = 0; $i < $clen; $i = ($i + 2)) {
 756			$char_bar = $code{$i};
 757			$char_space = $code{$i+1};
 758			if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) {
 759				// invalid character
 760				return false;
 761			}
 762			// create a bar-space sequence
 763			$seq = '';
 764			$chrlen = strlen($chr[$char_bar]);
 765			for ($s = 0; $s < $chrlen; $s++){
 766				$seq .= $chr[$char_bar]{$s} . $chr[$char_space]{$s};
 767			}
 768			$seqlen = strlen($seq);
 769			for ($j = 0; $j < $seqlen; ++$j) {
 770				if (($j % 2) == 0) {
 771					$t = true; // bar
 772				} else {
 773					$t = false; // space
 774				}
 775				$w = $seq{$j};
 776				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
 777				$bararray['maxw'] += $w;
 778				++$k;
 779			}
 780		}
 781		return $bararray;
 782	}
 783
 784	/**
 785	 * C128 barcodes.
 786	 * Very capable code, excellent density, high reliability; in very wide use world-wide
 787	 * @param string $code code to represent.
 788	 * @param string $type barcode type: A, B or C
 789	 * @return array barcode representation.
 790	 * @access protected
 791	 */
 792	protected function barcode_c128($code, $type='B') {
 793		$chr = array(
 794			'212222', /* 00 */
 795			'222122', /* 01 */
 796			'222221', /* 02 */
 797			'121223', /* 03 */
 798			'121322', /* 04 */
 799			'131222', /* 05 */
 800			'122213', /* 06 */
 801			'122312', /* 07 */
 802			'132212', /* 08 */
 803			'221213', /* 09 */
 804			'221312', /* 10 */
 805			'231212', /* 11 */
 806			'112232', /* 12 */
 807			'122132', /* 13 */
 808			'122231', /* 14 */
 809			'113222', /* 15 */
 810			'123122', /* 16 */
 811			'123221', /* 17 */
 812			'223211', /* 18 */
 813			'221132', /* 19 */
 814			'221231', /* 20 */
 815			'213212', /* 21 */
 816			'223112', /* 22 */
 817			'312131', /* 23 */
 818			'311222', /* 24 */
 819			'321122', /* 25 */
 820			'321221', /* 26 */
 821			'312212', /* 27 */
 822			'322112', /* 28 */
 823			'322211', /* 29 */
 824			'212123', /* 30 */
 825			'212321', /* 31 */
 826			'232121', /* 32 */
 827			'111323', /* 33 */
 828			'131123', /* 34 */
 829			'131321', /* 35 */
 830			'112313', /* 36 */
 831			'132113', /* 37 */
 832			'132311', /* 38 */
 833			'211313', /* 39 */
 834			'231113', /* 40 */
 835			'231311', /* 41 */
 836			'112133', /* 42 */
 837			'112331', /* 43 */
 838			'132131', /* 44 */
 839			'113123', /* 45 */
 840			'113321', /* 46 */
 841			'133121', /* 47 */
 842			'313121', /* 48 */
 843			'211331', /* 49 */
 844			'231131', /* 50 */
 845			'213113', /* 51 */
 846			'213311', /* 52 */
 847			'213131', /* 53 */
 848			'311123', /* 54 */
 849			'311321', /* 55 */
 850			'331121', /* 56 */
 851			'312113', /* 57 */
 852			'312311', /* 58 */
 853			'332111', /* 59 */
 854			'314111', /* 60 */
 855			'221411', /* 61 */
 856			'431111', /* 62 */
 857			'111224', /* 63 */
 858			'111422', /* 64 */
 859			'121124', /* 65 */
 860			'121421', /* 66 */
 861			'141122', /* 67 */
 862			'141221', /* 68 */
 863			'112214', /* 69 */
 864			'112412', /* 70 */
 865			'122114', /* 71 */
 866			'122411', /* 72 */
 867			'142112', /* 73 */
 868			'142211', /* 74 */
 869			'241211', /* 75 */
 870			'221114', /* 76 */
 871			'413111', /* 77 */
 872			'241112', /* 78 */
 873			'134111', /* 79 */
 874			'111242', /* 80 */
 875			'121142', /* 81 */
 876			'121241', /* 82 */
 877			'114212', /* 83 */
 878			'124112', /* 84 */
 879			'124211', /* 85 */
 880			'411212', /* 86 */
 881			'421112', /* 87 */
 882			'421211', /* 88 */
 883			'212141', /* 89 */
 884			'214121', /* 90 */
 885			'412121', /* 91 */
 886			'111143', /* 92 */
 887			'111341', /* 93 */
 888			'131141', /* 94 */
 889			'114113', /* 95 */
 890			'114311', /* 96 */
 891			'411113', /* 97 */
 892			'411311', /* 98 */
 893			'113141', /* 99 */
 894			'114131', /* 100 */
 895			'311141', /* 101 */
 896			'411131', /* 102 */
 897			'211412', /* 103 START A */
 898			'211214', /* 104 START B  */
 899			'211232', /* 105 START C  */
 900			'233111', /* STOP */
 901			'200000'  /* END */
 902		);
 903		$keys = '';
 904		switch(strtoupper($type)) {
 905			case 'A': {
 906				$startid = 103;
 907				$keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
 908				for ($i = 0; $i < 32; ++$i) {
 909					$keys .= chr($i);
 910				}
 911				break;
 912			}
 913			case 'B': {
 914				$startid = 104;
 915				$keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.chr(127);
 916				break;
 917			}
 918			case 'C': {
 919				$startid = 105;
 920				$keys = '';
 921				if ((strlen($code) % 2) != 0) {
 922					// The length of barcode value must be even ($code). You must pad the number with zeros
 923					return false;
 924				}
 925				for ($i = 0; $i <= 99; ++$i) {
 926					$keys .= chr($i);
 927				}
 928				$new_code = '';
 929				$hclen = (strlen($code) / 2);
 930				for ($i = 0; $i < $hclen; ++$i) {
 931					$new_code .= chr(intval($code{(2 * $i)}.$code{(2 * $i + 1)}));
 932				}
 933				$code = $new_code;
 934				break;
 935			}
 936			default: {
 937				return false;
 938			}
 939		}
 940		// calculate check character
 941		$sum = $startid;
 942		$clen = strlen($code);
 943		for ($i = 0; $i < $clen; ++$i) {
 944			$sum +=  (strpos($keys, $code{$i}) * ($i+1));
 945		}
 946		$check = ($sum % 103);
 947		// add start, check and stop codes
 948		$code = chr($startid).$code.chr($check).chr(106).chr(107);
 949		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
 950		$k = 0;
 951		$len = strlen($code);
 952		for ($i = 0; $i < $len; ++$i) {
 953			$ck = strpos($keys, $code{$i});
 954			if (($i == 0) OR ($i > ($len-4))) {
 955				$char_num = ord($code{$i});
 956				$seq = $chr[$char_num];
 957			} elseif(($ck >= 0) AND isset($chr[$ck])) {
 958					$seq = $chr[$ck];
 959			} else {
 960				// invalid character
 961				return false;
 962			}
 963			for ($j = 0; $j < 6; ++$j) {
 964				if (($j % 2) == 0) {
 965					$t = true; // bar
 966				} else {
 967					$t = false; // space
 968				}
 969				$w = $seq{$j};
 970				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
 971				$bararray['maxw'] += $w;
 972				++$k;
 973			}
 974		}
 975		return $bararray;
 976	}
 977
 978	/**
 979	 * EAN13 and UPC-A barcodes.
 980	 * EAN13: European Article Numbering international retail product code
 981	 * UPC-A: Universal product code seen on almost all retail products in the USA and Canada
 982	 * UPC-E: Short version of UPC symbol
 983	 * @param string $code code to represent.
 984	 * @param string $len barcode type: 6 = UPC-E, 8 = EAN8, 13 = EAN13, 12 = UPC-A
 985	 * @return array barcode representation.
 986	 * @access protected
 987	 */
 988	protected function barcode_eanupc($code, $len=13) {
 989		$upce = false;
 990		if ($len == 6) {
 991			$len = 12; // UPC-A
 992			$upce = true; // UPC-E mode
 993		}
 994		$data_len = $len - 1;
 995		//Padding
 996		$code = str_pad($code, $data_len, '0', STR_PAD_LEFT);
 997		$code_len = strlen($code);
 998		// calculate check digit
 999		$sum_a = 0;
1000		for ($i = 1; $i < $data_len; $i+=2) {
1001			$sum_a += $code{$i};
1002		}
1003		if ($len > 12) {
1004			$sum_a *= 3;
1005		}
1006		$sum_b = 0;
1007		for ($i = 0; $i < $data_len; $i+=2) {
1008			$sum_b += ($code{$i});
1009		}
1010		if ($len < 13) {
1011			$sum_b *= 3;
1012		}
1013		$r = ($sum_a + $sum_b) % 10;
1014		if($r > 0) {
1015			$r = (10 - $r);
1016		}
1017		if ($code_len == $data_len) {
1018			// add check digit
1019			$code .= $r;
1020		} elseif ($r !== intval($code{$data_len})) {
1021			// wrong checkdigit
1022			return false;
1023		}
1024		if ($len == 12) {
1025			// UPC-A
1026			$code = '0'.$code;
1027			++$len;
1028		}
1029		if ($upce) {
1030			// convert UPC-A to UPC-E
1031			$tmp = substr($code, 4, 3);
1032			if (($tmp == '000') OR ($tmp == '100') OR ($tmp == '200')) {
1033				// manufacturer code ends in 000, 100, or 200
1034				$upce_code = substr($code, 2, 2).substr($code, 9, 3).substr($code, 4, 1);
1035			} else {
1036				$tmp = substr($code, 5, 2);
1037				if ($tmp == '00') {
1038					// manufacturer code ends in 00
1039					$upce_code = substr($code, 2, 3).substr($code, 10, 2).'3';
1040				} else {
1041					$tmp = substr($code, 6, 1);
1042					if ($tmp == '0') {
1043						// manufacturer code ends in 0
1044						$upce_code = substr($code, 2, 4).substr($code, 11, 1).'4';
1045					} else {
1046						// manufacturer code does not end in zero
1047						$upce_code = substr($code, 2, 5).substr($code, 11, 1);
1048					}
1049				}
1050			}
1051		}
1052		//Convert digits to bars
1053		$codes = array(
1054			'A'=>array( // left odd parity
1055				'0'=>'0001101',
1056				'1'=>'0011001',
1057				'2'=>'0010011',
1058				'3'=>'0111101',
1059				'4'=>'0100011',
1060				'5'=>'0110001',
1061				'6'=>'0101111',
1062				'7'=>'0111011',
1063				'8'=>'0110111',
1064				'9'=>'0001011'),
1065			'B'=>array( // left even parity
1066				'0'=>'0100111',
1067				'1'=>'0110011',
1068				'2'=>'0011011',
1069				'3'=>'0100001',
1070				'4'=>'0011101',
1071				'5'=>'0111001',
1072				'6'=>'0000101',
1073				'7'=>'0010001',
1074				'8'=>'0001001',
1075				'9'=>'0010111'),
1076			'C'=>array( // right
1077				'0'=>'1110010',
1078				'1'=>'1100110',
1079				'2'=>'1101100',
1080				'3'=>'1000010',
1081				'4'=>'1011100',
1082				'5'=>'1001110',
1083				'6'=>'1010000',
1084				'7'=>'1000100',
1085				'8'=>'1001000',
1086				'9'=>'1110100')
1087		);
1088		$parities = array(
1089			'0'=>array('A','A','A','A','A','A'),
1090			'1'=>array('A','A','B','A','B','B'),
1091			'2'=>array('A','A','B','B','A','B'),
1092			'3'=>array('A','A','B','B','B','A'),
1093			'4'=>array('A','B','A','A','B','B'),
1094			'5'=>array('A','B','B','A','A','B'),
1095			'6'=>array('A','B','B','B','A','A'),
1096			'7'=>array('A','B','A','B','A','B'),
1097			'8'=>array('A','B','A','B','B','A'),
1098			'9'=>array('A','B','B','A','B','A')
1099		);
1100		$upce_parities = array();
1101		$upce_parities[0] = array(
1102			'0'=>array('B','B','B','A','A','A'),
1103			'1'=>array('B','B','A','B','A','A'),
1104			'2'=>array('B','B','A','A','B','A'),
1105			'3'=>array('B','B','A','A','A','B'),
1106			'4'=>array('B','A','B','B','A','A'),
1107			'5'=>array('B','A','A','B','B','A'),
1108			'6'=>array('B','A','A','A','B','B'),
1109			'7'=>array('B','A','B','A','B','A'),
1110			'8'=>array('B','A','B','A','A','B'),
1111			'9'=>array('B','A','A','B','A','B')
1112		);
1113		$upce_parities[1] = array(
1114			'0'=>array('A','A','A','B','B','B'),
1115			'1'=>array('A','A','B','A','B','B'),
1116			'2'=>array('A','A','B','B','A','B'),
1117			'3'=>array('A','A','B','B','B','A'),
1118			'4'=>array('A','B','A','A','B','B'),
1119			'5'=>array('A','B','B','A','A','B'),
1120			'6'=>array('A','B','B','B','A','A'),
1121			'7'=>array('A','B','A','B','A','B'),
1122			'8'=>array('A','B','A','B','B','A'),
1123			'9'=>array('A','B','B','A','B','A')
1124		);
1125		$k = 0;
1126		$seq = '101'; // left guard bar
1127		if ($upce) {
1128			$bararray = array('code' => $upce_code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1129			$p = $upce_parities[$code{1}][$r];
1130			for ($i = 0; $i < 6; ++$i) {
1131				$seq .= $codes[$p[$i]][$upce_code{$i}];
1132			}
1133			$seq .= '010101'; // right guard bar
1134		} else {
1135			$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1136			$half_len = ceil($len / 2);
1137			if ($len == 8) {
1138				for ($i = 0; $i < $half_len; ++$i) {
1139					$seq .= $codes['A'][$code{$i}];
1140				}
1141			} else {
1142				$p = $parities[$code{0}];
1143				for ($i = 1; $i < $half_len; ++$i) {
1144					$seq .= $codes[$p[$i-1]][$code{$i}];
1145				}
1146			}
1147			$seq .= '01010'; // center guard bar
1148			for ($i = $half_len; $i < $len; ++$i) {
1149				$seq .= $codes['C'][$code{$i}];
1150			}
1151			$seq .= '101'; // right guard bar
1152		}
1153		$clen = strlen($seq);
1154		$w = 0;
1155		for ($i = 0; $i < $clen; ++$i) {
1156			$w += 1;
1157			if (($i == ($clen - 1)) OR (($i < ($clen - 1)) AND ($seq{$i} != $seq{($i+1)}))) {
1158				if ($seq{$i} == '1') {
1159					$t = true; // bar
1160				} else {
1161					$t = false; // space
1162				}
1163				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1164				$bararray['maxw'] += $w;
1165				++$k;
1166				$w = 0;
1167			}
1168		}
1169		return $bararray;
1170	}
1171
1172	/**
1173	 * UPC-Based Extentions
1174	 * 2-Digit Ext.: Used to indicate magazines and newspaper issue numbers
1175	 * 5-Digit Ext.: Used to mark suggested retail price of books
1176	 * @param string $code code to represent.
1177	 * @param string $len barcode type: 2 = 2-Digit, 5 = 5-Digit
1178	 * @return array barcode representation.
1179	 * @access protected
1180	 */
1181	protected function barcode_eanext($code, $len=5) {
1182		//Padding
1183		$code = str_pad($code, $len, '0', STR_PAD_LEFT);
1184		// calculate check digit
1185		if ($len == 2) {
1186			$r = $code % 4;
1187		} elseif ($len == 5) {
1188			$r = (3 * ($code{0} + $code{2} + $code{4})) + (9 * ($code{1} + $code{3}));
1189			$r %= 10;
1190		} else {
1191			return false;
1192		}
1193		//Convert digits to bars
1194		$codes = array(
1195			'A'=>array( // left odd parity
1196				'0'=>'0001101',
1197				'1'=>'0011001',
1198				'2'=>'0010011',
1199				'3'=>'0111101',
1200				'4'=>'0100011',
1201				'5'=>'0110001',
1202				'6'=>'0101111',
1203				'7'=>'0111011',
1204				'8'=>'0110111',
1205				'9'=>'0001011'),
1206			'B'=>array( // left even parity
1207				'0'=>'0100111',
1208				'1'=>'0110011',
1209				'2'=>'0011011',
1210				'3'=>'0100001',
1211				'4'=>'0011101',
1212				'5'=>'0111001',
1213				'6'=>'0000101',
1214				'7'=>'0010001',
1215				'8'=>'0001001',
1216				'9'=>'0010111')
1217		);
1218		$parities = array();
1219		$parities[2] = array(
1220			'0'=>array('A','A'),
1221			'1'=>array('A','B'),
1222			'2'=>array('B','A'),
1223			'3'=>array('B','B')
1224		);
1225		$parities[5] = array(
1226			'0'=>array('B','B','A','A','A'),
1227			'1'=>array('B','A','B','A','A'),
1228			'2'=>array('B','A','A','B','A'),
1229			'3'=>array('B','A','A','A','B'),
1230			'4'=>array('A','B','B','A','A'),
1231			'5'=>array('A','A','B','B','A'),
1232			'6'=>array('A','A','A','B','B'),
1233			'7'=>array('A','B','A','B','A'),
1234			'8'=>array('A','B','A','A','B'),
1235			'9'=>array('A','A','B','A','B')
1236		);
1237		$p = $parities[$len][$r];
1238		$seq = '1011'; // left guard bar
1239		$seq .= $codes[$p[0]][$code{0}];
1240		for ($i = 1; $i < $len; ++$i) {
1241			$seq .= '01'; // separator
1242			$seq .= $codes[$p[$i]][$code{$i}];
1243		}
1244		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1245		return $this->binseq_to_array($seq, $bararray);
1246	}
1247
1248	/**
1249	 * POSTNET and PLANET barcodes.
1250	 * Used by U.S. Postal Service for automated mail sorting
1251	 * @param string $code zip code to represent. Must be a string containing a zip code of the form DDDDD or DDDDD-DDDD.
1252	 * @param boolean $planet if true print the PLANET barcode, otherwise print POSTNET
1253	 * @return array barcode representation.
1254	 * @access protected
1255	 */
1256	protected function barcode_postnet($code, $planet=false) {
1257		// bar lenght
1258		if ($planet) {
1259			$barlen = Array(
1260				0 => Array(1,1,2,2,2),
1261				1 => Array(2,2,2,1,1),
1262				2 => Array(2,2,1,2,1),
1263				3 => Array(2,2,1,1,2),
1264				4 => Array(2,1,2,2,1),
1265				5 => Array(2,1,2,1,2),
1266				6 => Array(2,1,1,2,2),
1267				7 => Array(1,2,2,2,1),
1268				8 => Array(1,2,2,1,2),
1269				9 => Array(1,2,1,2,2)
1270			);
1271		} else {
1272			$barlen = Array(
1273				0 => Array(2,2,1,1,1),
1274				1 => Array(1,1,1,2,2),
1275				2 => Array(1,1,2,1,2),
1276				3 => Array(1,1,2,2,1),
1277				4 => Array(1,2,1,1,2),
1278				5 => Array(1,2,1,2,1),
1279				6 => Array(1,2,2,1,1),
1280				7 => Array(2,1,1,1,2),
1281				8 => Array(2,1,1,2,1),
1282				9 => Array(2,1,2,1,1)
1283			);
1284		}
1285		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
1286		$k = 0;
1287		$code = str_replace('-', '', $code);
1288		$code = str_replace(' ', '', $code);
1289		$len = strlen($code);
1290		// calculate checksum
1291		$sum = 0;
1292		for ($i = 0; $i < $len; ++$i) {
1293			$sum += intval($code{$i});
1294		}
1295		$chkd = ($sum % 10);
1296		if($chkd > 0) {
1297			$chkd = (10 - $chkd);
1298		}
1299		$code .= $chkd;
1300		$len = strlen($code);
1301		// start bar
1302		$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1303		$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1304		$bararray['maxw'] += 2;
1305		for ($i = 0; $i < $len; ++$i) {
1306			for ($j = 0; $j < 5; ++$j) {
1307				$h = $barlen[$code{$i}][$j];
1308				$p = floor(1 / $h);
1309				$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
1310				$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1311				$bararray['maxw'] += 2;
1312			}
1313		}
1314		// end bar
1315		$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1316		$bararray['maxw'] += 1;
1317		return $bararray;
1318	}
1319
1320	/**
1321	 * RMS4CC - CBC - KIX
1322	 * RMS4CC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code) - KIX (Klant index - Customer index)
1323	 * RM4SCC is the name of the barcode symbology used by the Royal Mail for its Cleanmail service.
1324	 * @param string $code code to print
1325	 * @param boolean $kix if true prints the KIX variation (doesn't use the start and end symbols, and the checksum) - in this case the house number must be sufficed with an X and placed at the end of the code.
1326	 * @return array barcode representation.
1327	 * @access protected
1328	 */
1329	protected function barcode_rms4cc($code, $kix=false) {
1330		$notkix = !$kix;
1331		// bar mode
1332		// 1 = pos 1, length 2
1333		// 2 = pos 1, length 3
1334		// 3 = pos 2, length 1
1335		// 4 = pos 2, length 2
1336		$barmode = array(
1337			'0' => array(3,3,2,2),
1338			'1' => array(3,4,1,2),
1339			'2' => array(3,4,2,1),
1340			'3' => array(4,3,1,2),
1341			'4' => array(4,3,2,1),
1342			'5' => array(4,4,1,1),
1343			'6' => array(3,1,4,2),
1344			'7' => array(3,2,3,2),
1345			'8' => array(3,2,4,1),
1346			'9' => array(4,1,3,2),
1347			'A' => array(4,1,4,1),
1348			'B' => array(4,2,3,1),
1349			'C' => array(3,1,2,4),
1350			'D' => array(3,2,1,4),
1351			'E' => array(3,2,2,3),
1352			'F' => array(4,1,1,4),
1353			'G' => array(4,1,2,3),
1354			'H' => array(4,2,1,3),
1355			'I' => array(1,3,4,2),
1356			'J' => array(1,4,3,2),
1357			'K' => array(1,4,4,1),
1358			'L' => array(2,3,3,2),
1359			'M' => array(2,3,4,1),
1360			'N' => array(2,4,3,1),
1361			'O' => array(1,3,2,4),
1362			'P' => array(1,4,1,4),
1363			'Q' => array(1,4,2,3),
1364			'R' => array(2,3,1,4),
1365			'S' => array(2,3,2,3),
1366			'T' => array(2,4,1,3),
1367			'U' => array(1,1,4,4),
1368			'V' => array(1,2,3,4),
1369			'W' => array(1,2,4,3),
1370			'X' => array(2,1,3,4),
1371			'Y' => array(2,1,4,3),
1372			'Z' => array(2,2,3,3)
1373		);
1374		$code = strtoupper($code);
1375		$len = strlen($code);
1376		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 3, 'bcode' => array());
1377		if ($notkix) {
1378			// table for checksum calculation (row,col)
1379			$checktable = array(
1380				'0' => array(1,1),
1381				'1' => array(1,2),
1382				'2' => array(1,3),
1383				'3' => array(1,4),
1384				'4' => array(1,5),
1385				'5' => array(1,0),
1386				'6' => array(2,1),
1387				'7' => array(2,2),
1388				'8' => array(2,3),
1389				'9' => array(2,4),
1390				'A' => array(2,5),
1391				'B' => array(2,0),
1392				'C' => array(3,1),
1393				'D' => array(3,2),
1394				'E' => array(3,3),
1395				'F' => array(3,4),
1396				'G' => array(3,5),
1397				'H' => array(3,0),
1398				'I' => array(4,1),
1399				'J' => array(4,2),
1400				'K' => array(4,3),
1401				'L' => array(4,4),
1402				'M' => array(4,5),
1403				'N' => array(4,0),
1404				'O' => array(5,1),
1405				'P' => array(5,2),
1406				'Q' => array(5,3),
1407				'R' => array(5,4),
1408				'S' => array(5,5),
1409				'T' => array(5,0),
1410				'U' => array(0,1),
1411				'V' => array(0,2),
1412				'W' => array(0,3),
1413				'X' => array(0,4),
1414				'Y' => array(0,5),
1415				'Z' => array(0,0)
1416			);
1417			$row = 0;
1418			$col = 0;
1419			for ($i = 0; $i < $len; ++$i) {
1420				$row += $checktable[$code{$i}][0];
1421				$col += $checktable[$code{$i}][1];
1422			}
1423			$row %= 6;
1424			$col %= 6;
1425			$chk = array_keys($checktable, array($row,$col));
1426			$code .= $chk[0];
1427			++$len;
1428		}
1429		$k = 0;
1430		if ($notkix) {
1431			// start bar
1432			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 2, 'p' => 0);
1433			$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1434			$bararray['maxw'] += 2;
1435		}
1436		for ($i = 0; $i < $len; ++$i) {
1437			for ($j = 0; $j < 4; ++$j) {
1438				switch ($barmode[$code{$i}][$j]) {
1439					case 1: {
1440						$p = 0;
1441						$h = 2;
1442						break;
1443					}
1444					case 2: {
1445						$p = 0;
1446						$h = 3;
1447						break;
1448					}
1449					case 3: {
1450						$p = 1;
1451						$h = 1;
1452						break;
1453					}
1454					case 4: {
1455						$p = 1;
1456						$h = 2;
1457						break;
1458					}
1459				}
1460				$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => $h, 'p' => $p);
1461				$bararray['bcode'][$k++] = array('t' => 0, 'w' => 1, 'h' => 2, 'p' => 0);
1462				$bararray['maxw'] += 2;
1463			}
1464		}
1465		if ($notkix) {
1466			// stop bar
1467			$bararray['bcode'][$k++] = array('t' => 1, 'w' => 1, 'h' => 3, 'p' => 0);
1468			$bararray['maxw'] += 1;
1469		}
1470		return $bararray;
1471	}
1472
1473	/**
1474	 * CODABAR barcodes.
1475	 * Older code often used in library systems, sometimes in blood banks
1476	 * @param string $code code to represent.
1477	 * @return array barcode representation.
1478	 * @access protected
1479	 */
1480	protected function barcode_codabar($code) {
1481		$chr = array(
1482			'0' => '11111221',
1483			'1' => '11112211',
1484			'2' => '11121121',
1485			'3' => '22111111',
1486			'4' => '11211211',
1487			'5' => '21111211',
1488			'6' => '12111121',
1489			'7' => '12112111',
1490			'8' => '12211111',
1491			'9' => '21121111',
1492			'-' => '11122111',
1493			'$' => '11221111',
1494			':' => '21112121',
1495			'/' => '21211121',
1496			'.' => '21212111',
1497			'+' => '11222221',
1498			'A' => '11221211',
1499			'B' => '12121121',
1500			'C' => '11121221',
1501			'D' => '11122211'
1502		);
1503		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1504		$k = 0;
1505		$w = 0;
1506		$seq = '';
1507		$code = 'A'.strtoupper($code).'A';
1508		$len = strlen($code);
1509		for ($i = 0; $i < $len; ++$i) {
1510			if (!isset($chr[$code{$i}])) {
1511				return false;
1512			}
1513			$seq = $chr[$code{$i}];
1514			for ($j = 0; $j < 8; ++$j) {
1515				if (($j % 2) == 0) {
1516					$t = true; // bar
1517				} else {
1518					$t = false; // space
1519				}
1520				$w = $seq{$j};
1521				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1522				$bararray['maxw'] += $w;
1523				++$k;
1524			}
1525		}
1526		return $bararray;
1527	}
1528
1529	/**
1530	 * CODE11 barcodes.
1531	 * Used primarily for labeling telecommunications equipment
1532	 * @param string $code code to represent.
1533	 * @return array barcode representation.
1534	 * @access protected
1535	 */
1536	protected function barcode_code11($code) {
1537		$chr = array(
1538			'0' => '111121',
1539			'1' => '211121',
1540			'2' => '121121',
1541			'3' => '221111',
1542			'4' => '112121',
1543			'5' => '212111',
1544			'6' => '122111',
1545			'7' => '111221',
1546			'8' => '211211',
1547			'9' => '211111',
1548			'-' => '112111',
1549			'S' => '112211'
1550		);
1551
1552		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1553		$k = 0;
1554		$w = 0;
1555		$seq = '';
1556		$len = strlen($code);
1557		// calculate check digit C
1558		$p = 1;
1559		$check = 0;
1560		for ($i = ($len - 1); $i >= 0; --$i) {
1561			$digit = $code{$i};
1562			if ($digit == '-') {
1563				$dval = 10;
1564			} else {
1565				$dval = intval($digit);
1566			}
1567			$check += ($dval * $p);
1568			++$p;
1569			if ($p > 10) {
1570				$p = 1;
1571			}
1572		}
1573		$check %= 11;
1574		if ($check == 10) {
1575			$check = '-';
1576		}
1577		$code .= $check;
1578		if ($len > 10) {
1579			// calculate check digit K
1580			$p = 1;
1581			$check = 0;
1582			for ($i = $len; $i >= 0; --$i) {
1583				$digit = $code{$i};
1584				if ($digit == '-') {
1585					$dval = 10;
1586				} else {
1587					$dval = intval($digit);
1588				}
1589				$check += ($dval * $p);
1590				++$p;
1591				if ($p > 9) {
1592					$p = 1;
1593				}
1594			}
1595			$check %= 11;
1596			$code .= $check;
1597			++$len;
1598		}
1599		$code = 'S'.$code.'S';
1600		$len += 3;
1601		for ($i = 0; $i < $len; ++$i) {
1602			if (!isset($chr[$code{$i}])) {
1603				return false;
1604			}
1605			$seq = $chr[$code{$i}];
1606			for ($j = 0; $j < 6; ++$j) {
1607				if (($j % 2) == 0) {
1608					$t = true; // bar
1609				} else {
1610					$t = false; // space
1611				}
1612				$w = $seq{$j};
1613				$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
1614				$bararray['maxw'] += $w;
1615				++$k;
1616			}
1617		}
1618		return $bararray;
1619	}
1620
1621	/**
1622	 * Pharmacode
1623	 * Contains digits (0 to 9)
1624	 * @param string $code code to represent.
1625	 * @return array barcode representation.
1626	 * @access protected
1627	 */
1628	protected function barcode_pharmacode($code) {
1629		$seq = '';
1630		$code = intval($code);
1631		while ($code > 0) {
1632			if (($code % 2) == 0) {
1633				$seq .= '11100';
1634				$code -= 2;
1635			} else {
1636				$seq .= '100';
1637				$code -= 1;
1638			}
1639			$code /= 2;
1640		}
1641		$seq = substr($seq, 0, -2);
1642		$seq = strrev($seq);
1643		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
1644		return $this->binseq_to_array($seq, $bararray);
1645	}
1646
1647	/**
1648	 * Pharmacode two-track
1649	 * Contains digits (0 to 9)
1650	 * @param string $code code to represent.
1651	 * @return array barcode representation.
1652	 * @access protected
1653	 */
1654	protected function barcode_pharmacode2t($code) {
1655		$seq = '';
1656		$code = intval($code);
1657		do {
1658			switch ($code % 3) {
1659				case 0: {
1660					$seq .= '3';
1661					$code = ($code - 3) / 3;
1662					break;
1663				}
1664				case 1: {
1665					$seq .= '1';
1666					$code = ($code - 1) / 3;
1667					break;
1668				}
1669				case 2: {
1670					$seq .= '2';
1671					$code = ($code - 2) / 3;
1672					break;
1673				}
1674			}
1675		} while($code != 0);
1676		$seq = strrev($seq);
1677		$k = 0;
1678		$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 2, 'bcode' => array());
1679		$len = strlen($seq);
1680		for ($i = 0; $i < $len; ++$i) {
1681			switch ($seq{$i}) {
1682				case '1': {
1683					$p = 1;
1684					$h = 1;
1685					break;
1686				}
1687				case '2': {
1688					$p = 0;
1689					$h = 1;
1690					break;
1691				}
1692				case '3': {
1693					$p = 0;
1694					$h = 2;
1695					break;
1696	

Large files files are truncated, but you can click here to view the full file