protected function barcode_c128($code, $type = '')
{
$chr = array('212222', '222122', '222221', '121223', '121322', '131222', '122213', '122312', '132212', '221213', '221312', '231212', '112232', '122132', '122231', '113222', '123122', '123221', '223211', '221132', '221231', '213212', '223112', '312131', '311222', '321122', '321221', '312212', '322112', '322211', '212123', '212321', '232121', '111323', '131123', '131321', '112313', '132113', '132311', '211313', '231113', '231311', '112133', '112331', '132131', '113123', '113321', '133121', '313121', '211331', '231131', '213113', '213311', '213131', '311123', '311321', '331121', '312113', '312311', '332111', '314111', '221411', '431111', '111224', '111422', '121124', '121421', '141122', '141221', '112214', '112412', '122114', '122411', '142112', '142211', '241211', '221114', '413111', '241112', '134111', '111242', '121142', '121241', '114212', '124112', '124211', '411212', '421112', '421211', '212141', '214121', '412121', '111143', '111341', '131141', '114113', '114311', '411113', '411311', '113141', '114131', '311141', '411131', '211412', '211214', '211232', '233111', '200000');
// ASCII characters for code A (ASCII 00 - 95)
$keys_a = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_';
$keys_a .= chr(0) . chr(1) . chr(2) . chr(3) . chr(4) . chr(5) . chr(6) . chr(7) . chr(8) . chr(9);
$keys_a .= chr(10) . chr(11) . chr(12) . chr(13) . chr(14) . chr(15) . chr(16) . chr(17) . chr(18) . chr(19);
$keys_a .= chr(20) . chr(21) . chr(22) . chr(23) . chr(24) . chr(25) . chr(26) . chr(27) . chr(28) . chr(29);
$keys_a .= chr(30) . chr(31);
// ASCII characters for code B (ASCII 32 - 127)
$keys_b = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' . chr(127);
// special codes
$fnc_a = array(241 => 102, 242 => 97, 243 => 96, 244 => 101);
$fnc_b = array(241 => 102, 242 => 97, 243 => 96, 244 => 100);
// array of symbols
$code_data = array();
// length of the code
$len = strlen($code);
switch (strtoupper($type)) {
case 'A':
// MODE A
$startid = 103;
for ($i = 0; $i < $len; ++$i) {
$char = $code[$i];
$char_id = ord($char);
if ($char_id >= 241 and $char_id <= 244) {
$code_data[] = $fnc_a[$char_id];
} elseif ($char_id >= 0 and $char_id <= 95) {
$code_data[] = strpos($keys_a, $char);
} else {
throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
}
}
break;
case 'B':
// MODE B
$startid = 104;
for ($i = 0; $i < $len; ++$i) {
$char = $code[$i];
$char_id = ord($char);
if ($char_id >= 241 and $char_id <= 244) {
$code_data[] = $fnc_b[$char_id];
} elseif ($char_id >= 32 and $char_id <= 127) {
$code_data[] = strpos($keys_b, $char);
} else {
throw new InvalidCharacterException('Char ' . $char . ' is unsupported');
}
}
break;
case 'C':
// MODE C
$startid = 105;
if (ord($code[0]) == 241) {
$code_data[] = 102;
$code = substr($code, 1);
--$len;
}
if ($len % 2 != 0) {
throw new InvalidLengthException('Length must be even');
}
for ($i = 0; $i < $len; $i += 2) {
$chrnum = $code[$i] . $code[$i + 1];
if (preg_match('/([0-9]{2})/', $chrnum) > 0) {
$code_data[] = intval($chrnum);
} else {
throw new InvalidCharacterException();
}
}
break;
default:
// MODE AUTO
// split code into sequences
$sequence = array();
// get numeric sequences (if any)
$numseq = array();
preg_match_all('/([0-9]{4,})/', $code, $numseq, PREG_OFFSET_CAPTURE);
if (isset($numseq[1]) and !empty($numseq[1])) {
$end_offset = 0;
foreach ($numseq[1] as $val) {
$offset = $val[1];
if ($offset > $end_offset) {
// non numeric sequence
$sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset, $offset - $end_offset)));
}
// numeric sequence
$slen = strlen($val[0]);
if ($slen % 2 != 0) {
// the length must be even
--$slen;
}
$sequence[] = array('C', substr($code, $offset, $slen), $slen);
$end_offset = $offset + $slen;
}
if ($end_offset < $len) {
$sequence = array_merge($sequence, $this->get128ABsequence(substr($code, $end_offset)));
}
} else {
// text code (non C mode)
$sequence = array_merge($sequence, $this->get128ABsequence($code));
}
// process the sequence
foreach ($sequence as $key => $seq) {
switch ($seq[0]) {
case 'A':
if ($key == 0) {
$startid = 103;
} elseif ($sequence[$key - 1][0] != 'A') {
if ($seq[2] == 1 and $key > 0 and $sequence[$key - 1][0] == 'B' and !isset($sequence[$key - 1][3])) {
// single character shift
$code_data[] = 98;
// mark shift
$sequence[$key][3] = true;
} elseif (!isset($sequence[$key - 1][3])) {
$code_data[] = 101;
}
}
for ($i = 0; $i < $seq[2]; ++$i) {
$char = $seq[1][$i];
$char_id = ord($char);
if ($char_id >= 241 and $char_id <= 244) {
$code_data[] = $fnc_a[$char_id];
} else {
$code_data[] = strpos($keys_a, $char);
}
}
break;
case 'B':
if ($key == 0) {
$tmpchr = ord($seq[1][0]);
if ($seq[2] == 1 and $tmpchr >= 241 and $tmpchr <= 244 and isset($sequence[$key + 1]) and $sequence[$key + 1][0] != 'B') {
switch ($sequence[$key + 1][0]) {
case 'A':
$startid = 103;
$sequence[$key][0] = 'A';
$code_data[] = $fnc_a[$tmpchr];
break;
case 'C':
$startid = 105;
$sequence[$key][0] = 'C';
$code_data[] = $fnc_a[$tmpchr];
break;
}
break;
} else {
$startid = 104;
}
} elseif ($sequence[$key - 1][0] != 'B') {
if ($seq[2] == 1 and $key > 0 and $sequence[$key - 1][0] == 'A' and !isset($sequence[$key - 1][3])) {
// single character shift
$code_data[] = 98;
// mark shift
$sequence[$key][3] = true;
} elseif (!isset($sequence[$key - 1][3])) {
$code_data[] = 100;
}
}
for ($i = 0; $i < $seq[2]; ++$i) {
$char = $seq[1][$i];
$char_id = ord($char);
if ($char_id >= 241 and $char_id <= 244) {
$code_data[] = $fnc_b[$char_id];
} else {
$code_data[] = strpos($keys_b, $char);
}
}
break;
case 'C':
if ($key == 0) {
$startid = 105;
} elseif ($sequence[$key - 1][0] != 'C') {
$code_data[] = 99;
}
for ($i = 0; $i < $seq[2]; $i += 2) {
$chrnum = $seq[1][$i] . $seq[1][$i + 1];
$code_data[] = intval($chrnum);
}
break;
}
}
}
// calculate check character
$sum = $startid;
foreach ($code_data as $key => $val) {
$sum += $val * ($key + 1);
}
// add check character
$code_data[] = $sum % 103;
// add stop sequence
$code_data[] = 106;
$code_data[] = 107;
// add start code at the beginning
array_unshift($code_data, $startid);
// build barcode array
$bararray = array('code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => array());
foreach ($code_data as $val) {
$seq = $chr[$val];
for ($j = 0; $j < 6; ++$j) {
if ($j % 2 == 0) {
$t = true;
// bar
} else {
$t = false;
// space
}
$w = $seq[$j];
$bararray['bcode'][] = array('t' => $t, 'w' => $w, 'h' => 1, 'p' => 0);
$bararray['maxw'] += $w;
}
}
return $bararray;
}