1<?php 2 3namespace Mpdf\Barcode; 4 5/** 6 * CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. 7 */ 8class Code39 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\BarcodeInterface 9{ 10 11 /** 12 * @param string $code 13 * @param float $printRatio 14 * @param bool $extended 15 * @param bool $checksum 16 */ 17 public function __construct($code, $printRatio, $extended = false, $checksum = false) 18 { 19 $this->init($code, $printRatio, $extended, $checksum); 20 21 $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) 22 $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) 23 $this->data['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) 24 $this->data['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) 25 $this->data['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) 26 } 27 28 /** 29 * @param string $code 30 * @param float $printRatio 31 * @param bool $extended 32 * @param bool $checksum 33 * 34 * @return mixed[] 35 */ 36 private function init($code, $printRatio, $extended, $checksum) 37 { 38 $chr = [ 39 '0' => '111221211', 40 '1' => '211211112', 41 '2' => '112211112', 42 '3' => '212211111', 43 '4' => '111221112', 44 '5' => '211221111', 45 '6' => '112221111', 46 '7' => '111211212', 47 '8' => '211211211', 48 '9' => '112211211', 49 'A' => '211112112', 50 'B' => '112112112', 51 'C' => '212112111', 52 'D' => '111122112', 53 'E' => '211122111', 54 'F' => '112122111', 55 'G' => '111112212', 56 'H' => '211112211', 57 'I' => '112112211', 58 'J' => '111122211', 59 'K' => '211111122', 60 'L' => '112111122', 61 'M' => '212111121', 62 'N' => '111121122', 63 'O' => '211121121', 64 'P' => '112121121', 65 'Q' => '111111222', 66 'R' => '211111221', 67 'S' => '112111221', 68 'T' => '111121221', 69 'U' => '221111112', 70 'V' => '122111112', 71 'W' => '222111111', 72 'X' => '121121112', 73 'Y' => '221121111', 74 'Z' => '122121111', 75 '-' => '121111212', 76 '.' => '221111211', 77 ' ' => '122111211', 78 '$' => '121212111', 79 '/' => '121211121', 80 '+' => '121112121', 81 '%' => '111212121', 82 '*' => '121121211', 83 ]; 84 85 $code = strtoupper($code); 86 $checkdigit = ''; 87 88 if ($extended) { 89 // extended mode 90 $code = $this->encodeExt($code); 91 } 92 93 if ($code === false) { 94 throw new \Mpdf\Barcode\BarcodeException('Invalid CODE39 barcode value'); 95 } 96 97 if ($checksum) { 98 // checksum 99 $checkdigit = $this->checksum($code); 100 $code .= $checkdigit; 101 } 102 // add star$this->>datat and stop codes 103 $code = '*' . $code . '*'; 104 105 $bararray = ['code' => $code, 'maxw' => 0, 'maxh' => 1, 'bcode' => []]; 106 $k = 0; 107 $clen = strlen($code); 108 for ($i = 0; $i < $clen; ++$i) { 109 $char = $code[$i]; 110 if (!isset($chr[$char])) { 111 // invalid character 112 throw new \Mpdf\Barcode\BarcodeException('Invalid CODE39 barcode value'); 113 } 114 for ($j = 0; $j < 9; ++$j) { 115 if (($j % 2) == 0) { 116 $t = true; // bar 117 } else { 118 $t = false; // space 119 } 120 $x = $chr[$char][$j]; 121 if ($x == 2) { 122 $w = $printRatio; 123 } else { 124 $w = 1; 125 } 126 127 $bararray['bcode'][$k] = ['t' => $t, 'w' => $w, 'h' => 1, 'p' => 0]; 128 $bararray['maxw'] += $w; 129 ++$k; 130 } 131 $bararray['bcode'][$k] = ['t' => false, 'w' => 1, 'h' => 1, 'p' => 0]; 132 $bararray['maxw'] += 1; 133 ++$k; 134 } 135 136 $bararray['checkdigit'] = $checkdigit; 137 138 $this->data = $bararray; 139 } 140 141 /** 142 * Encode a string to be used for CODE 39 Extended mode. 143 * 144 * @param string $code 145 * @return string 146 */ 147 protected function encodeExt($code) 148 { 149 $encode = [ 150 chr(0) => '%U', chr(1) => '$A', chr(2) => '$B', chr(3) => '$C', 151 chr(4) => '$D', chr(5) => '$E', chr(6) => '$F', chr(7) => '$G', 152 chr(8) => '$H', chr(9) => '$I', chr(10) => '$J', chr(11) => '£K', 153 chr(12) => '$L', chr(13) => '$M', chr(14) => '$N', chr(15) => '$O', 154 chr(16) => '$P', chr(17) => '$Q', chr(18) => '$R', chr(19) => '$S', 155 chr(20) => '$T', chr(21) => '$U', chr(22) => '$V', chr(23) => '$W', 156 chr(24) => '$X', chr(25) => '$Y', chr(26) => '$Z', chr(27) => '%A', 157 chr(28) => '%B', chr(29) => '%C', chr(30) => '%D', chr(31) => '%E', 158 chr(32) => ' ', chr(33) => '/A', chr(34) => '/B', chr(35) => '/C', 159 chr(36) => '/D', chr(37) => '/E', chr(38) => '/F', chr(39) => '/G', 160 chr(40) => '/H', chr(41) => '/I', chr(42) => '/J', chr(43) => '/K', 161 chr(44) => '/L', chr(45) => '-', chr(46) => '.', chr(47) => '/O', 162 chr(48) => '0', chr(49) => '1', chr(50) => '2', chr(51) => '3', 163 chr(52) => '4', chr(53) => '5', chr(54) => '6', chr(55) => '7', 164 chr(56) => '8', chr(57) => '9', chr(58) => '/Z', chr(59) => '%F', 165 chr(60) => '%G', chr(61) => '%H', chr(62) => '%I', chr(63) => '%J', 166 chr(64) => '%V', chr(65) => 'A', chr(66) => 'B', chr(67) => 'C', 167 chr(68) => 'D', chr(69) => 'E', chr(70) => 'F', chr(71) => 'G', 168 chr(72) => 'H', chr(73) => 'I', chr(74) => 'J', chr(75) => 'K', 169 chr(76) => 'L', chr(77) => 'M', chr(78) => 'N', chr(79) => 'O', 170 chr(80) => 'P', chr(81) => 'Q', chr(82) => 'R', chr(83) => 'S', 171 chr(84) => 'T', chr(85) => 'U', chr(86) => 'V', chr(87) => 'W', 172 chr(88) => 'X', chr(89) => 'Y', chr(90) => 'Z', chr(91) => '%K', 173 chr(92) => '%L', chr(93) => '%M', chr(94) => '%N', chr(95) => '%O', 174 chr(96) => '%W', chr(97) => '+A', chr(98) => '+B', chr(99) => '+C', 175 chr(100) => '+D', chr(101) => '+E', chr(102) => '+F', chr(103) => '+G', 176 chr(104) => '+H', chr(105) => '+I', chr(106) => '+J', chr(107) => '+K', 177 chr(108) => '+L', chr(109) => '+M', chr(110) => '+N', chr(111) => '+O', 178 chr(112) => '+P', chr(113) => '+Q', chr(114) => '+R', chr(115) => '+S', 179 chr(116) => '+T', chr(117) => '+U', chr(118) => '+V', chr(119) => '+W', 180 chr(120) => '+X', chr(121) => '+Y', chr(122) => '+Z', chr(123) => '%P', 181 chr(124) => '%Q', chr(125) => '%R', chr(126) => '%S', chr(127) => '%T' 182 ]; 183 184 $code_ext = ''; 185 $clen = strlen($code); 186 187 for ($i = 0; $i < $clen; ++$i) { 188 189 if (ord($code[$i]) > 127) { 190 throw new \Mpdf\Barcode\BarcodeException('Invalid CODE39 barcode value'); 191 } 192 193 $code_ext .= $encode[$code[$i]]; 194 } 195 196 return $code_ext; 197 } 198 199 /** 200 * Calculate CODE 39 checksum (modulo 43). 201 * 202 * @param string $code 203 * @return string mixed 204 */ 205 protected function checksum($code) 206 { 207 $chars = [ 208 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 209 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 210 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 211 'W', 'X', 'Y', 'Z', '-', '.', ' ', '$', '/', '+', '%' 212 ]; 213 214 $sum = 0; 215 $clen = strlen($code); 216 217 for ($i = 0; $i < $clen; ++$i) { 218 $k = array_keys($chars, $code[$i]); 219 $sum += $k[0]; 220 } 221 222 $j = ($sum % 43); 223 224 return $chars[$j]; 225 } 226 227 /** 228 * @inheritdoc 229 */ 230 public function getType() 231 { 232 return 'CODE39'; 233 } 234 235} 236