.
//
// See LICENSE.TXT file for more information.
// ----------------------------------------------------------------------------
//
// Description : PHP class to creates array representations for
// common 1D barcodes to be used with TCPDF.
//
// Author: Nicola Asuni
//
// (c) Copyright:
// Nicola Asuni
// Tecnick.com S.r.l.
// Via della Pace, 11
// 09044 Quartucciu (CA)
// ITALY
// www.tecnick.com
// info@tecnick.com
//============================================================+
class PDFBarcode {
protected $barcode_array;
protected $gapwidth;
protected $print_ratio;
protected $daft;
public function __construct() {
}
public function getBarcodeArray($code, $type, $pr='') {
$this->setBarcode($code, $type, $pr);
return $this->barcode_array;
}
public function getChecksum($code, $type) {
$this->setBarcode($code, $type);
if (!$this->barcode_array) { return ''; }
else { return $this->barcode_array['checkdigit']; }
}
public function setBarcode($code, $type, $pr='') {
$this->print_ratio = 1;
switch (strtoupper($type)) {
case 'ISBN':
case 'ISSN':
case 'EAN13': { // EAN 13
$arrcode = $this->barcode_eanupc($code, 13);
$arrcode['lightmL'] = 11; // LEFT light margin = x X-dim (http://www.gs1uk.org)
$arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org)
$arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
$arrcode['nom-H'] = 25.93; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org)
break;
}
case 'UPCA': { // UPC-A
$arrcode = $this->barcode_eanupc($code, 12);
$arrcode['lightmL'] = 9; // LEFT light margin = x X-dim (http://www.gs1uk.org)
$arrcode['lightmR'] = 9; // RIGHT light margin = x X-dim (http://www.gs1uk.org)
$arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
$arrcode['nom-H'] = 25.91; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org)
break;
}
case 'UPCE': { // UPC-E
$arrcode = $this->barcode_eanupc($code, 6);
$arrcode['lightmL'] = 9; // LEFT light margin = x X-dim (http://www.gs1uk.org)
$arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org)
$arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
$arrcode['nom-H'] = 25.93; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org)
break;
}
case 'EAN8': { // EAN 8
$arrcode = $this->barcode_eanupc($code, 8);
$arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (http://www.gs1uk.org)
$arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (http://www.gs1uk.org)
$arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
$arrcode['nom-H'] = 21.64; // Nominal bar height in mm incl. numerals (http://www.gs1uk.org)
break;
}
case 'EAN2': { // 2-Digits UPC-Based Extention
$arrcode = $this->barcode_eanext($code, 2);
$arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (estimated)
$arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (estimated)
$arrcode['sepM'] = 9; // SEPARATION margin = x X-dim (http://web.archive.org/web/19990501035133/http://www.uc-council.org/d36-d.htm)
$arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
$arrcode['nom-H'] = 20; // Nominal bar height in mm incl. numerals (estimated) not used when combined
break;
}
case 'EAN5': { // 5-Digits UPC-Based Extention
$arrcode = $this->barcode_eanext($code, 5);
$arrcode['lightmL'] = 7; // LEFT light margin = x X-dim (estimated)
$arrcode['lightmR'] = 7; // RIGHT light margin = x X-dim (estimated)
$arrcode['sepM'] = 9; // SEPARATION margin = x X-dim (http://web.archive.org/web/19990501035133/http://www.uc-council.org/d36-d.htm)
$arrcode['nom-X'] = 0.33; // Nominal value for X-dim in mm (http://www.gs1uk.org)
$arrcode['nom-H'] = 20; // Nominal bar height in mm incl. numerals (estimated) not used when combined
break;
}
case 'IMB': { // IMB - Intelligent Mail Barcode - Onecode - USPS-B-3200
$xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
$bpi = 22; // Bars per inch
// Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
$this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
$this->daft = array('D'=>2, 'A'=>2, 'F'=>3, 'T'=>1); // Descender; Ascender; Full; Tracker bar heights
$arrcode = $this->barcode_imb($code);
$arrcode['nom-X'] = $xdim ;
$arrcode['nom-H'] = 3.68; // Nominal value for Height of Full bar in mm (spec.)
// USPS-B-3200 Revision C = 4.623
// USPS-B-3200 Revision E = 3.68
$arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (spec.)
$arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (spec.)
$arrcode['quietTB'] = 0.711; // TOP/BOTTOM Quiet margin = mm (spec.)
break;
}
case 'RM4SCC': { // RM4SCC (Royal Mail 4-state Customer Code) - CBC (Customer Bar Code)
$xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
$bpi = 22; // Bars per inch
// Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
$this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
$this->daft = array('D'=>5, 'A'=>5, 'F'=>8, 'T'=>2); // Descender; Ascender; Full; Tracker bar heights
$arrcode = $this->barcode_rm4scc($code, false);
$arrcode['nom-X'] = $xdim ;
$arrcode['nom-H'] = 5.0; // Nominal value for Height of Full bar in mm (spec.)
$arrcode['quietL'] = 2; // LEFT Quiet margin = mm (spec.)
$arrcode['quietR'] = 2; // RIGHT Quiet margin = mm (spec.)
$arrcode['quietTB'] = 2; // TOP/BOTTOM Quiet margin = mm (spec?)
break;
}
case 'KIX': { // KIX (Klant index - Customer index)
$xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
$bpi = 22; // Bars per inch
// Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
$this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
$this->daft = array('D'=>5, 'A'=>5, 'F'=>8, 'T'=>2); // Descender; Ascender; Full; Tracker bar heights
$arrcode = $this->barcode_rm4scc($code, true);
$arrcode['nom-X'] = $xdim ;
$arrcode['nom-H'] = 5.0; // Nominal value for Height of Full bar in mm (? spec.)
$arrcode['quietL'] = 2; // LEFT Quiet margin = mm (spec.)
$arrcode['quietR'] = 2; // RIGHT Quiet margin = mm (spec.)
$arrcode['quietTB'] = 2; // TOP/BOTTOM Quiet margin = mm (spec.)
break;
}
case 'POSTNET': { // POSTNET
$xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
$bpi = 22; // Bars per inch
// Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
$this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
$arrcode = $this->barcode_postnet($code, false);
$arrcode['nom-X'] = $xdim ;
$arrcode['nom-H'] = 3.175; // Nominal value for Height of Full bar in mm (spec.)
$arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (?spec.)
$arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (?spec.)
$arrcode['quietTB'] = 1.016; // TOP/BOTTOM Quiet margin = mm (?spec.)
break;
}
case 'PLANET': { // PLANET
$xdim = 0.508; // Nominal value for X-dim (bar width) in mm (spec.)
$bpi = 22; // Bars per inch
// Ratio of Nominal value for width of spaces in mm / Nominal value for X-dim (bar width) in mm based on bars per inch
$this->gapwidth = ((25.4/$bpi) - $xdim)/$xdim;
$arrcode = $this->barcode_postnet($code, true);
$arrcode['nom-X'] = $xdim ;
$arrcode['nom-H'] = 3.175; // Nominal value for Height of Full bar in mm (spec.)
$arrcode['quietL'] = 3.175; // LEFT Quiet margin = mm (?spec.)
$arrcode['quietR'] = 3.175; // RIGHT Quiet margin = mm (?spec.)
$arrcode['quietTB'] = 1.016; // TOP/BOTTOM Quiet margin = mm (?spec.)
break;
}
case 'C93': { // CODE 93 - USS-93
$arrcode = $this->barcode_code93($code);
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
break;
}
case 'CODE11': { // CODE 11
if ($pr > 0) { $this->print_ratio = $pr; }
else { $this->print_ratio = 3; } // spec: Pr= 1:2.24 - 1:3.5
$arrcode = $this->barcode_code11($code);
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
break;
}
case 'MSI': // MSI (Variation of Plessey code)
case 'MSI+': { // MSI + CHECKSUM (modulo 11)
if (strtoupper($type)=='MSI') { $arrcode = $this->barcode_msi($code, false); }
if (strtoupper($type)=='MSI+') { $arrcode = $this->barcode_msi($code, true); }
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 12; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 12; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
break;
}
case 'CODABAR': { // CODABAR
if ($pr > 0) { $this->print_ratio = $pr; }
else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50)
if (strtoupper($type)=='CODABAR') { $arrcode = $this->barcode_codabar($code); }
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
break;
}
case 'C128A': // CODE 128 A
case 'C128B': // CODE 128 B
case 'C128C': // CODE 128 C
case 'EAN128A': // EAN 128 A
case 'EAN128B': // EAN 128 B
case 'EAN128C': { // EAN 128 C
if (strtoupper($type)=='C128A') { $arrcode = $this->barcode_c128($code, 'A'); }
if (strtoupper($type)=='C128B') { $arrcode = $this->barcode_c128($code, 'B'); }
if (strtoupper($type)=='C128C') { $arrcode = $this->barcode_c128($code, 'C'); }
if (strtoupper($type)=='EAN128A') { $arrcode = $this->barcode_c128($code, 'A', true); }
if (strtoupper($type)=='EAN128B') { $arrcode = $this->barcode_c128($code, 'B', true); }
if (strtoupper($type)=='EAN128C') { $arrcode = $this->barcode_c128($code, 'C', true); }
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
break;
}
case 'C39': // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
case 'C39+': // CODE 39 with checksum
case 'C39E': // CODE 39 EXTENDED
case 'C39E+': { // CODE 39 EXTENDED + CHECKSUM
if ($pr > 0) { $this->print_ratio = $pr; }
else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50)
$code = str_replace(chr(194).chr(160), ' ', $code); // mPDF 5.3.95 (for utf-8 encoded)
$code = str_replace(chr(160), ' ', $code); // mPDF 5.3.95 (for win-1252)
if (strtoupper($type)=='C39') { $arrcode = $this->barcode_code39($code, false, false); }
if (strtoupper($type)=='C39+') { $arrcode = $this->barcode_code39($code, false, true); }
if (strtoupper($type)=='C39E') { $arrcode = $this->barcode_code39($code, true, false); }
if (strtoupper($type)=='C39E+') { $arrcode = $this->barcode_code39($code, true, true); }
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
break;
}
case 'S25': // Standard 2 of 5
case 'S25+': { // Standard 2 of 5 + CHECKSUM
if ($pr > 0) { $this->print_ratio = $pr; }
else { $this->print_ratio = 3; } // spec: Pr=1:3/1:4.5
if (strtoupper($type)=='S25') { $arrcode = $this->barcode_s25($code, false); }
if (strtoupper($type)=='S25+') { $arrcode = $this->barcode_s25($code, true); }
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
break;
}
case 'I25': // Interleaved 2 of 5
case 'I25+': { // Interleaved 2 of 5 + CHECKSUM
if ($pr > 0) { $this->print_ratio = $pr; }
else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50)
if (strtoupper($type)=='I25') { $arrcode = $this->barcode_i25($code, false); }
if (strtoupper($type)=='I25+') { $arrcode = $this->barcode_i25($code, true); }
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.)
break;
}
case 'I25B': // Interleaved 2 of 5 + Bearer bars
case 'I25B+': { // Interleaved 2 of 5 + CHECKSUM + Bearer bars
if ($pr > 0) { $this->print_ratio = $pr; }
else { $this->print_ratio = 2.5; } // spec: Pr= 1:2 - 1:3 (>2.2 if X<0.50)
if (strtoupper($type)=='I25B') { $arrcode = $this->barcode_i25($code, false); }
if (strtoupper($type)=='I25B+') { $arrcode = $this->barcode_i25($code, true); }
if ($arrcode == false) { break; }
$arrcode['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.)
$arrcode['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.)
$arrcode['lightmL'] = 10; // LEFT light margin = x X-dim (spec.)
$arrcode['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.)
$arrcode['lightTB'] = 2; // TOP/BOTTOM light margin = x X-dim (non-spec.) - used for bearer bars
break;
}
default: {
$this->barcode_array = false;
}
}
$this->barcode_array = $arrcode;
}
/**
* CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9.
*/
protected function barcode_code39($code, $extended=false, $checksum=false) {
$chr['0'] = '111221211';
$chr['1'] = '211211112';
$chr['2'] = '112211112';
$chr['3'] = '212211111';
$chr['4'] = '111221112';
$chr['5'] = '211221111';
$chr['6'] = '112221111';
$chr['7'] = '111211212';
$chr['8'] = '211211211';
$chr['9'] = '112211211';
$chr['A'] = '211112112';
$chr['B'] = '112112112';
$chr['C'] = '212112111';
$chr['D'] = '111122112';
$chr['E'] = '211122111';
$chr['F'] = '112122111';
$chr['G'] = '111112212';
$chr['H'] = '211112211';
$chr['I'] = '112112211';
$chr['J'] = '111122211';
$chr['K'] = '211111122';
$chr['L'] = '112111122';
$chr['M'] = '212111121';
$chr['N'] = '111121122';
$chr['O'] = '211121121';
$chr['P'] = '112121121';
$chr['Q'] = '111111222';
$chr['R'] = '211111221';
$chr['S'] = '112111221';
$chr['T'] = '111121221';
$chr['U'] = '221111112';
$chr['V'] = '122111112';
$chr['W'] = '222111111';
$chr['X'] = '121121112';
$chr['Y'] = '221121111';
$chr['Z'] = '122121111';
$chr['-'] = '121111212';
$chr['.'] = '221111211';
$chr[' '] = '122111211';
$chr['$'] = '121212111';
$chr['/'] = '121211121';
$chr['+'] = '121112121';
$chr['%'] = '111212121';
$chr['*'] = '121121211';
$code = strtoupper($code);
if ($extended) {
// extended mode
$code = $this->encode_code39_ext($code);
}
if ($code === false) {
return false;
}
if ($checksum) {
// checksum
$checkdigit = $this->checksum_code39($code);
$code .= $checkdigit ;
}
// add start and stop codes
$code = '*'.$code.'*';
$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
$k = 0;
$clen = strlen($code);
for ($i = 0; $i < $clen; ++$i) {
$char = $code[$i];
if(!isset($chr[$char])) {
// invalid character
return false;
}
for ($j = 0; $j < 9; ++$j) {
if (($j % 2) == 0) {
$t = true; // bar
} else {
$t = false; // space
}
$x = $chr[$char][$j];
if ($x == 2) { $w = $this->print_ratio; }
else { $w = 1; }
$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
$bararray['maxw'] += $w;
++$k;
}
$bararray['bcode'][$k] = array('t' => false, 'w' => 1, 'h' => 1, 'p' => 0);
$bararray['maxw'] += 1;
++$k;
}
$bararray['checkdigit'] = $checkdigit;
return $bararray;
}
/**
* Encode a string to be used for CODE 39 Extended mode.
*/
protected function encode_code39_ext($code) {
$encode = array(
chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C',
chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G',
chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K',
chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O',
chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S',
chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W',
chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A',
chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E',
chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C',
chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G',
chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K',
chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O',
chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F',
chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J',
chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K',
chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O',
chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C',
chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G',
chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K',
chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O',
chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S',
chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W',
chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P',
chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T');
$code_ext = '';
$clen = strlen($code);
for ($i = 0 ; $i < $clen; ++$i) {
if (ord($code[$i]) > 127) {
return false;
}
$code_ext .= $encode[$code[$i]];
}
return $code_ext;
}
/**
* Calculate CODE 39 checksum (modulo 43).
*/
protected function checksum_code39($code) {
$chars = array(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
$sum = 0;
$clen = strlen($code);
for ($i = 0 ; $i < $clen; ++$i) {
$k = array_keys($chars, $code[$i]);
$sum += $k[0];
}
$j = ($sum % 43);
return $chars[$j];
}
/**
* CODE 93 - USS-93
* Compact code similar to Code 39
*/
protected function barcode_code93($code) {
$chr['0'] = '131112';
$chr['1'] = '111213';
$chr['2'] = '111312';
$chr['3'] = '111411';
$chr['4'] = '121113';
$chr['5'] = '121212';
$chr['6'] = '121311';
$chr['7'] = '111114';
$chr['8'] = '131211';
$chr['9'] = '141111';
$chr['A'] = '211113';
$chr['B'] = '211212';
$chr['C'] = '211311';
$chr['D'] = '221112';
$chr['E'] = '221211';
$chr['F'] = '231111';
$chr['G'] = '112113';
$chr['H'] = '112212';
$chr['I'] = '112311';
$chr['J'] = '122112';
$chr['K'] = '132111';
$chr['L'] = '111123';
$chr['M'] = '111222';
$chr['N'] = '111321';
$chr['O'] = '121122';
$chr['P'] = '131121';
$chr['Q'] = '212112';
$chr['R'] = '212211';
$chr['S'] = '211122';
$chr['T'] = '211221';
$chr['U'] = '221121';
$chr['V'] = '222111';
$chr['W'] = '112122';
$chr['X'] = '112221';
$chr['Y'] = '122121';
$chr['Z'] = '123111';
$chr['-'] = '121131';
$chr['.'] = '311112';
$chr[' '] = '311211';
$chr['$'] = '321111';
$chr['/'] = '112131';
$chr['+'] = '113121';
$chr['%'] = '211131';
$chr[128] = '121221'; // ($)
$chr[129] = '311121'; // (/)
$chr[130] = '122211'; // (+)
$chr[131] = '312111'; // (%)
$chr['*'] = '111141';
$code = strtoupper($code);
$encode = array(
chr(0) => chr(131).'U', chr(1) => chr(128).'A', chr(2) => chr(128).'B', chr(3) => chr(128).'C',
chr(4) => chr(128).'D', chr(5) => chr(128).'E', chr(6) => chr(128).'F', chr(7) => chr(128).'G',
chr(8) => chr(128).'H', chr(9) => chr(128).'I', chr(10) => chr(128).'J', chr(11) => '£K',
chr(12) => chr(128).'L', chr(13) => chr(128).'M', chr(14) => chr(128).'N', chr(15) => chr(128).'O',
chr(16) => chr(128).'P', chr(17) => chr(128).'Q', chr(18) => chr(128).'R', chr(19) => chr(128).'S',
chr(20) => chr(128).'T', chr(21) => chr(128).'U', chr(22) => chr(128).'V', chr(23) => chr(128).'W',
chr(24) => chr(128).'X', chr(25) => chr(128).'Y', chr(26) => chr(128).'Z', chr(27) => chr(131).'A',
chr(28) => chr(131).'B', chr(29) => chr(131).'C', chr(30) => chr(131).'D', chr(31) => chr(131).'E',
chr(32) => ' ', chr(33) => chr(129).'A', chr(34) => chr(129).'B', chr(35) => chr(129).'C',
chr(36) => chr(129).'D', chr(37) => chr(129).'E', chr(38) => chr(129).'F', chr(39) => chr(129).'G',
chr(40) => chr(129).'H', chr(41) => chr(129).'I', chr(42) => chr(129).'J', chr(43) => chr(129).'K',
chr(44) => chr(129).'L', chr(45) => '-', chr(46) => '.', chr(47) => chr(129).'O',
chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3',
chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7',
chr(56) => '8', chr(57) => '9', chr(58) => chr(129).'Z', chr(59) => chr(131).'F',
chr(60) => chr(131).'G', chr(61) => chr(131).'H', chr(62) => chr(131).'I', chr(63) => chr(131).'J',
chr(64) => chr(131).'V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C',
chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G',
chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K',
chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O',
chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S',
chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W',
chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => chr(131).'K',
chr(92) => chr(131).'L', chr(93) => chr(131).'M', chr(94) => chr(131).'N', chr(95) => chr(131).'O',
chr(96) => chr(131).'W', chr(97) => chr(130).'A', chr(98) => chr(130).'B', chr(99) => chr(130).'C',
chr(100) => chr(130).'D', chr(101) => chr(130).'E', chr(102) => chr(130).'F', chr(103) => chr(130).'G',
chr(104) => chr(130).'H', chr(105) => chr(130).'I', chr(106) => chr(130).'J', chr(107) => chr(130).'K',
chr(108) => chr(130).'L', chr(109) => chr(130).'M', chr(110) => chr(130).'N', chr(111) => chr(130).'O',
chr(112) => chr(130).'P', chr(113) => chr(130).'Q', chr(114) => chr(130).'R', chr(115) => chr(130).'S',
chr(116) => chr(130).'T', chr(117) => chr(130).'U', chr(118) => chr(130).'V', chr(119) => chr(130).'W',
chr(120) => chr(130).'X', chr(121) => chr(130).'Y', chr(122) => chr(130).'Z', chr(123) => chr(131).'P',
chr(124) => chr(131).'Q', chr(125) => chr(131).'R', chr(126) => chr(131).'S', chr(127) => chr(131).'T');
$code_ext = '';
$clen = strlen($code);
for ($i = 0 ; $i < $clen; ++$i) {
if (ord($code[$i]) > 127) {
return false;
}
$code_ext .= $encode[$code[$i]];
}
// checksum
$checkdigit = $this->checksum_code93($code);
$code .= $checkdigit ;
// add start and stop codes
$code = '*'.$code.'*';
$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
$k = 0;
$clen = strlen($code);
for ($i = 0; $i < $clen; ++$i) {
$char = $code[$i];
if(!isset($chr[$char])) {
// invalid character
return false;
}
for ($j = 0; $j < 6; ++$j) {
if (($j % 2) == 0) {
$t = true; // bar
} else {
$t = false; // space
}
$w = $chr[$char][$j];
$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
$bararray['maxw'] += $w;
++$k;
}
}
$bararray['bcode'][$k] = array('t' => true, 'w' => 1, 'h' => 1, 'p' => 0);
$bararray['maxw'] += 1;
++$k;
$bararray['checkdigit'] = $checkdigit;
return $bararray;
}
/**
* Calculate CODE 93 checksum (modulo 47).
*/
protected function checksum_code93($code) {
$chars = array(
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%');
// translate special characters
$code = strtr($code, chr(128).chr(129).chr(130).chr(131), '$/+%');
$len = strlen($code);
// calculate check digit C
$p = 1;
$check = 0;
for ($i = ($len - 1); $i >= 0; --$i) {
$k = array_keys($chars, $code[$i]);
$check += ($k[0] * $p);
++$p;
if ($p > 20) {
$p = 1;
}
}
$check %= 47;
$c = $chars[$check];
$code .= $c;
// calculate check digit K
$p = 1;
$check = 0;
for ($i = $len; $i >= 0; --$i) {
$k = array_keys($chars, $code[$i]);
$check += ($k[0] * $p);
++$p;
if ($p > 15) {
$p = 1;
}
}
$check %= 47;
$k = $chars[$check];
return $c.$k;
}
/**
* Checksum for standard 2 of 5 barcodes.
*/
protected function checksum_s25($code) {
$len = strlen($code);
$sum = 0;
for ($i = 0; $i < $len; $i+=2) {
$sum += $code[$i];
}
$sum *= 3;
for ($i = 1; $i < $len; $i+=2) {
$sum += ($code[$i]);
}
$r = $sum % 10;
if($r > 0) {
$r = (10 - $r);
}
return $r;
}
/**
* MSI.
* Variation of Plessey code, with similar applications
* Contains digits (0 to 9) and encodes the data only in the width of bars.
*/
protected function barcode_msi($code, $checksum=false) {
$chr['0'] = '100100100100';
$chr['1'] = '100100100110';
$chr['2'] = '100100110100';
$chr['3'] = '100100110110';
$chr['4'] = '100110100100';
$chr['5'] = '100110100110';
$chr['6'] = '100110110100';
$chr['7'] = '100110110110';
$chr['8'] = '110100100100';
$chr['9'] = '110100100110';
$chr['A'] = '110100110100';
$chr['B'] = '110100110110';
$chr['C'] = '110110100100';
$chr['D'] = '110110100110';
$chr['E'] = '110110110100';
$chr['F'] = '110110110110';
if ($checksum) {
// add checksum
$clen = strlen($code);
$p = 2;
$check = 0;
for ($i = ($clen - 1); $i >= 0; --$i) {
$check += (hexdec($code[$i]) * $p);
++$p;
if ($p > 7) {
$p = 2;
}
}
$check %= 11;
if ($check > 0) {
$check = 11 - $check;
}
$code .= $check;
$checkdigit = $check;
}
$seq = '110'; // left guard
$clen = strlen($code);
for ($i = 0; $i < $clen; ++$i) {
$digit = $code[$i];
if (!isset($chr[$digit])) {
// invalid character
return false;
}
$seq .= $chr[$digit];
}
$seq .= '1001'; // right guard
$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
$bararray['checkdigit'] = $checkdigit;
return $this->binseq_to_array($seq, $bararray);
}
/**
* Standard 2 of 5 barcodes.
* Used in airline ticket marking, photofinishing
* Contains digits (0 to 9) and encodes the data only in the width of bars.
*/
protected function barcode_s25($code, $checksum=false) {
$chr['0'] = '10101110111010';
$chr['1'] = '11101010101110';
$chr['2'] = '10111010101110';
$chr['3'] = '11101110101010';
$chr['4'] = '10101110101110';
$chr['5'] = '11101011101010';
$chr['6'] = '10111011101010';
$chr['7'] = '10101011101110';
$chr['8'] = '10101110111010';
$chr['9'] = '10111010111010';
if ($checksum) {
// add checksum
$checkdigit = $this->checksum_s25($code);
$code .= $checkdigit ;
}
if((strlen($code) % 2) != 0) {
// add leading zero if code-length is odd
$code = '0'.$code;
}
$seq = '11011010';
$clen = strlen($code);
for ($i = 0; $i < $clen; ++$i) {
$digit = $code[$i];
if (!isset($chr[$digit])) {
// invalid character
return false;
}
$seq .= $chr[$digit];
}
$seq .= '1101011';
$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
$bararray['checkdigit'] = $checkdigit;
return $this->binseq_to_array($seq, $bararray);
}
/**
* Convert binary barcode sequence to barcode array
*/
protected function binseq_to_array($seq, $bararray) {
$len = strlen($seq);
$w = 0;
$k = 0;
for ($i = 0; $i < $len; ++$i) {
$w += 1;
if (($i == ($len - 1)) OR (($i < ($len - 1)) AND ($seq[$i] != $seq[($i+1)]))) {
if ($seq[$i] == '1') {
$t = true; // bar
} else {
$t = false; // space
}
$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
$bararray['maxw'] += $w;
++$k;
$w = 0;
}
}
return $bararray;
}
/**
* Interleaved 2 of 5 barcodes.
* Compact numeric code, widely used in industry, air cargo
* Contains digits (0 to 9) and encodes the data in the width of both bars and spaces.
*/
protected function barcode_i25($code, $checksum=false) {
$chr['0'] = '11221';
$chr['1'] = '21112';
$chr['2'] = '12112';
$chr['3'] = '22111';
$chr['4'] = '11212';
$chr['5'] = '21211';
$chr['6'] = '12211';
$chr['7'] = '11122';
$chr['8'] = '21121';
$chr['9'] = '12121';
$chr['A'] = '11';
$chr['Z'] = '21';
if ($checksum) {
// add checksum
$checkdigit = $this->checksum_s25($code);
$code .= $checkdigit ;
}
if((strlen($code) % 2) != 0) {
// add leading zero if code-length is odd
$code = '0'.$code;
}
// add start and stop codes
$code = 'AA'.strtolower($code).'ZA';
$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
$k = 0;
$clen = strlen($code);
for ($i = 0; $i < $clen; $i = ($i + 2)) {
$char_bar = $code[$i];
$char_space = $code[$i+1];
if((!isset($chr[$char_bar])) OR (!isset($chr[$char_space]))) {
// invalid character
return false;
}
// create a bar-space sequence
$seq = '';
$chrlen = strlen($chr[$char_bar]);
for ($s = 0; $s < $chrlen; $s++){
$seq .= $chr[$char_bar][$s] . $chr[$char_space][$s];
}
$seqlen = strlen($seq);
for ($j = 0; $j < $seqlen; ++$j) {
if (($j % 2) == 0) {
$t = true; // bar
} else {
$t = false; // space
}
$x = $seq[$j];
if ($x == 2) { $w = $this->print_ratio; }
else { $w = 1; }
$bararray['bcode'][$k] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
$bararray['maxw'] += $w;
++$k;
}
}
$bararray['checkdigit'] = $checkdigit;
return $bararray;
}
/**
* C128 barcodes.
* Very capable code, excellent density, high reliability; in very wide use world-wide
*/
protected function barcode_c128($code, $type='B', $ean=false) {
$code = strcode2utf($code); // mPDF 5.7.1 Allows e.g.