.
//
// 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
//============================================================+
require_once __DIR__ . '/../MpdfException.php';
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);
$checkdigit = '';
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[48] = '131112'; // 0
$chr[49] = '111213'; // 1
$chr[50] = '111312'; // 2
$chr[51] = '111411'; // 3
$chr[52] = '121113'; // 4
$chr[53] = '121212'; // 5
$chr[54] = '121311'; // 6
$chr[55] = '111114'; // 7
$chr[56] = '131211'; // 8
$chr[57] = '141111'; // 9
$chr[65] = '211113'; // A
$chr[66] = '211212'; // B
$chr[67] = '211311'; // C
$chr[68] = '221112'; // D
$chr[69] = '221211'; // E
$chr[70] = '231111'; // F
$chr[71] = '112113'; // G
$chr[72] = '112212'; // H
$chr[73] = '112311'; // I
$chr[74] = '122112'; // J
$chr[75] = '132111'; // K
$chr[76] = '111123'; // L
$chr[77] = '111222'; // M
$chr[78] = '111321'; // N
$chr[79] = '121122'; // O
$chr[80] = '131121'; // P
$chr[81] = '212112'; // Q
$chr[82] = '212211'; // R
$chr[83] = '211122'; // S
$chr[84] = '211221'; // T
$chr[85] = '221121'; // U
$chr[86] = '222111'; // V
$chr[87] = '112122'; // W
$chr[88] = '112221'; // X
$chr[89] = '122121'; // Y
$chr[90] = '123111'; // Z
$chr[45] = '121131'; // -
$chr[46] = '311112'; // .
$chr[32] = '311211'; //
$chr[36] = '321111'; // $
$chr[47] = '112131'; // /
$chr[43] = '113121'; // +
$chr[37] = '211131'; // %
$chr[128] = '121221'; // ($)
$chr[129] = '311121'; // (/)
$chr[130] = '122211'; // (+)
$chr[131] = '312111'; // (%)
$chr[42] = '111141'; // start-stop
$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
$code_ext .= $this->checksum_code93($code_ext);
// add start and stop codes
$code = '*' . $code_ext . '*';
$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
$k = 0;
$clen = strlen($code);
for ($i = 0; $i < $clen; ++$i) {
$char = ord($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;
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(131) . chr(129) . chr(130), '<=>?');
$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];
$checksum = $c . $k;
// resto respecial characters
$checksum = strtr($checksum, '<=>?', chr(128) . chr(131) . chr(129) . chr(130));
return $checksum;
}
/**
* 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';
$checkdigit = '';
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';
$checkdigit = '';
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';
$checkdigit = '';
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.