|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 //============================================================+ 00003 // File name : datamatrix.php 00004 // Version : 1.0.001 00005 // Begin : 2010-06-07 00006 // Last Update : 2011-09-14 00007 // Author : Nicola Asuni - Tecnick.com S.r.l - Via Della Pace, 11 - 09044 - Quartucciu (CA) - ITALY - www.tecnick.com - info@tecnick.com 00008 // License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html) 00009 // ------------------------------------------------------------------- 00010 // Copyright (C) 2010-2011 Nicola Asuni - Tecnick.com S.r.l. 00011 // 00012 // This file is part of TCPDF software library. 00013 // 00014 // TCPDF is free software: you can redistribute it and/or modify it 00015 // under the terms of the GNU Lesser General Public License as 00016 // published by the Free Software Foundation, either version 3 of the 00017 // License, or (at your option) any later version. 00018 // 00019 // TCPDF is distributed in the hope that it will be useful, but 00020 // WITHOUT ANY WARRANTY; without even the implied warranty of 00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00022 // See the GNU Lesser General Public License for more details. 00023 // 00024 // You should have received a copy of the GNU Lesser General Public License 00025 // along with TCPDF. If not, see <http://www.gnu.org/licenses/>. 00026 // 00027 // See LICENSE.TXT file for more information. 00028 // ------------------------------------------------------------------- 00029 // 00030 // DESCRIPTION : 00031 // 00032 // Class to create DataMatrix ECC 200 barcode arrays for TCPDF class. 00033 // DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code. 00034 //============================================================+ 00035 00046 // custom definitions 00047 if (!defined('DATAMATRIXDEFS')) { 00048 00052 define('DATAMATRIXDEFS', true); 00053 00054 // ----------------------------------------------------- 00055 00056 } // end of custom definitions 00057 00058 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*# 00059 00060 00064 define('ENC_ASCII', 0); 00065 00069 define('ENC_C40', 1); 00070 00074 define('ENC_TXT', 2); 00075 00079 define('ENC_X12', 3); 00080 00084 define('ENC_EDF', 4); 00085 00089 define('ENC_BASE256', 5); 00090 00094 define('ENC_ASCII_EXT', 6); 00095 00099 define('ENC_ASCII_NUM', 7); 00100 00110 class Datamatrix { 00111 00116 protected $barcode_array = array(); 00117 00122 protected $last_enc = ENC_ASCII; 00123 00145 protected $symbattr = array( 00146 // square form --------------------------------------------------------------------------------------- 00147 array(0x00a,0x00a,0x008,0x008,0x00a,0x00a,0x008,0x008,0x001,0x001,0x001,0x003,0x005,0x001,0x003,0x005), // 10x10 00148 array(0x00c,0x00c,0x00a,0x00a,0x00c,0x00c,0x00a,0x00a,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 12x12 00149 array(0x00e,0x00e,0x00c,0x00c,0x00e,0x00e,0x00c,0x00c,0x001,0x001,0x001,0x008,0x00a,0x001,0x008,0x00a), // 14x14 00150 array(0x010,0x010,0x00e,0x00e,0x010,0x010,0x00e,0x00e,0x001,0x001,0x001,0x00c,0x00c,0x001,0x00c,0x00c), // 16x16 00151 array(0x012,0x012,0x010,0x010,0x012,0x012,0x010,0x010,0x001,0x001,0x001,0x012,0x00e,0x001,0x012,0x00e), // 18x18 00152 array(0x014,0x014,0x012,0x012,0x014,0x014,0x012,0x012,0x001,0x001,0x001,0x016,0x012,0x001,0x016,0x012), // 20x20 00153 array(0x016,0x016,0x014,0x014,0x016,0x016,0x014,0x014,0x001,0x001,0x001,0x01e,0x014,0x001,0x01e,0x014), // 22x22 00154 array(0x018,0x018,0x016,0x016,0x018,0x018,0x016,0x016,0x001,0x001,0x001,0x024,0x018,0x001,0x024,0x018), // 24x24 00155 array(0x01a,0x01a,0x018,0x018,0x01a,0x01a,0x018,0x018,0x001,0x001,0x001,0x02c,0x01c,0x001,0x02c,0x01c), // 26x26 00156 array(0x020,0x020,0x01c,0x01c,0x010,0x010,0x00e,0x00e,0x002,0x002,0x004,0x03e,0x024,0x001,0x03e,0x024), // 32x32 00157 array(0x024,0x024,0x020,0x020,0x012,0x012,0x010,0x010,0x002,0x002,0x004,0x056,0x02a,0x001,0x056,0x02a), // 36x36 00158 array(0x028,0x028,0x024,0x024,0x014,0x014,0x012,0x012,0x002,0x002,0x004,0x072,0x030,0x001,0x072,0x030), // 40x40 00159 array(0x02c,0x02c,0x028,0x028,0x016,0x016,0x014,0x014,0x002,0x002,0x004,0x090,0x038,0x001,0x090,0x038), // 44x44 00160 array(0x030,0x030,0x02c,0x02c,0x018,0x018,0x016,0x016,0x002,0x002,0x004,0x0ae,0x044,0x001,0x0ae,0x044), // 48x48 00161 array(0x034,0x034,0x030,0x030,0x01a,0x01a,0x018,0x018,0x002,0x002,0x004,0x0cc,0x054,0x002,0x066,0x02a), // 52x52 00162 array(0x040,0x040,0x038,0x038,0x010,0x010,0x00e,0x00e,0x004,0x004,0x010,0x118,0x070,0x002,0x08c,0x038), // 64x64 00163 array(0x048,0x048,0x040,0x040,0x012,0x012,0x010,0x010,0x004,0x004,0x010,0x170,0x090,0x004,0x05c,0x024), // 72x72 00164 array(0x050,0x050,0x048,0x048,0x014,0x014,0x012,0x012,0x004,0x004,0x010,0x1c8,0x0c0,0x004,0x072,0x030), // 80x80 00165 array(0x058,0x058,0x050,0x050,0x016,0x016,0x014,0x014,0x004,0x004,0x010,0x240,0x0e0,0x004,0x090,0x038), // 88x88 00166 array(0x060,0x060,0x058,0x058,0x018,0x018,0x016,0x016,0x004,0x004,0x010,0x2b8,0x110,0x004,0x0ae,0x044), // 96x96 00167 array(0x068,0x068,0x060,0x060,0x01a,0x01a,0x018,0x018,0x004,0x004,0x010,0x330,0x150,0x006,0x088,0x038), // 104x104 00168 array(0x078,0x078,0x06c,0x06c,0x014,0x014,0x012,0x012,0x006,0x006,0x024,0x41a,0x198,0x006,0x0af,0x044), // 120x120 00169 array(0x084,0x084,0x078,0x078,0x016,0x016,0x014,0x014,0x006,0x006,0x024,0x518,0x1f0,0x008,0x0a3,0x03e), // 132x132 00170 array(0x090,0x090,0x084,0x084,0x018,0x018,0x016,0x016,0x006,0x006,0x024,0x616,0x26c,0x00a,0x09c,0x03e), // 144x144 00171 // rectangular form (currently unused) --------------------------------------------------------------------------- 00172 array(0x008,0x012,0x006,0x010,0x008,0x012,0x006,0x010,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 8x18 00173 array(0x008,0x020,0x006,0x01c,0x008,0x010,0x006,0x00e,0x001,0x002,0x002,0x00a,0x00b,0x001,0x00a,0x00b), // 8x32 00174 array(0x00c,0x01a,0x00a,0x018,0x00c,0x01a,0x00a,0x018,0x001,0x001,0x001,0x010,0x00e,0x001,0x010,0x00e), // 12x26 00175 array(0x00c,0x024,0x00a,0x020,0x00c,0x012,0x00a,0x010,0x001,0x002,0x002,0x00c,0x012,0x001,0x00c,0x012), // 12x36 00176 array(0x010,0x024,0x00e,0x020,0x010,0x012,0x00e,0x010,0x001,0x002,0x002,0x020,0x018,0x001,0x020,0x018), // 16x36 00177 array(0x010,0x030,0x00e,0x02c,0x010,0x018,0x00e,0x016,0x001,0x002,0x002,0x031,0x01c,0x001,0x031,0x01c) // 16x48 00178 ); 00179 00184 protected $chset_id = array(ENC_C40 => 'C40', ENC_TXT => 'TXT', ENC_X12 =>'X12'); 00185 00190 protected $chset = array( 00191 'C40' => array( // Basic set for C40 ---------------------------------------------------------------------------- 00192 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 00193 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, // 00194 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, // 00195 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27),// 00196 'TXT' => array( // Basic set for TEXT --------------------------------------------------------------------------- 00197 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 00198 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x61=>0x0e,0x62=>0x0f,0x63=>0x10,0x64=>0x11,0x65=>0x12,0x66=>0x13, // 00199 0x67=>0x14,0x68=>0x15,0x69=>0x16,0x6a=>0x17,0x6b=>0x18,0x6c=>0x19,0x6d=>0x1a,0x6e=>0x1b,0x6f=>0x1c,0x70=>0x1d, // 00200 0x71=>0x1e,0x72=>0x1f,0x73=>0x20,0x74=>0x21,0x75=>0x22,0x76=>0x23,0x77=>0x24,0x78=>0x25,0x79=>0x26,0x7a=>0x27),// 00201 'SH1' => array( // Shift 1 set ---------------------------------------------------------------------------------- 00202 0x00=>0x00,0x01=>0x01,0x02=>0x02,0x03=>0x03,0x04=>0x04,0x05=>0x05,0x06=>0x06,0x07=>0x07,0x08=>0x08,0x09=>0x09, // 00203 0x0a=>0x0a,0x0b=>0x0b,0x0c=>0x0c,0x0d=>0x0d,0x0e=>0x0e,0x0f=>0x0f,0x10=>0x10,0x11=>0x11,0x12=>0x12,0x13=>0x13, // 00204 0x14=>0x14,0x15=>0x15,0x16=>0x16,0x17=>0x17,0x18=>0x18,0x19=>0x19,0x1a=>0x1a,0x1b=>0x1b,0x1c=>0x1c,0x1d=>0x1d, // 00205 0x1e=>0x1e,0x1f=>0x1f), // 00206 'SH2' => array( // Shift 2 set ---------------------------------------------------------------------------------- 00207 0x21=>0x00,0x22=>0x01,0x23=>0x02,0x24=>0x03,0x25=>0x04,0x26=>0x05,0x27=>0x06,0x28=>0x07,0x29=>0x08,0x2a=>0x09, // 00208 0x2b=>0x0a,0x2c=>0x0b,0x2d=>0x0c,0x2e=>0x0d,0x2f=>0x0e,0x3a=>0x0f,0x3b=>0x10,0x3c=>0x11,0x3d=>0x12,0x3e=>0x13, // 00209 0x3f=>0x14,0x40=>0x15,0x5b=>0x16,0x5c=>0x17,0x5d=>0x18,0x5e=>0x19,0x5f=>0x1a,'F1'=>0x1b,'US'=>0x1e), // 00210 'S3C' => array( // Shift 3 set for C40 -------------------------------------------------------------------------- 00211 0x60=>0x00,0x61=>0x01,0x62=>0x02,0x63=>0x03,0x64=>0x04,0x65=>0x05,0x66=>0x06,0x67=>0x07,0x68=>0x08,0x69=>0x09, // 00212 0x6a=>0x0a,0x6b=>0x0b,0x6c=>0x0c,0x6d=>0x0d,0x6e=>0x0e,0x6f=>0x0f,0x70=>0x10,0x71=>0x11,0x72=>0x12,0x73=>0x13, // 00213 0x74=>0x14,0x75=>0x15,0x76=>0x16,0x77=>0x17,0x78=>0x18,0x79=>0x19,0x7a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, // 00214 0x7e=>0x1e,0x7f=>0x1f), 00215 'S3T' => array( // Shift 3 set for TEXT ------------------------------------------------------------------------- 00216 0x60=>0x00,0x41=>0x01,0x42=>0x02,0x43=>0x03,0x44=>0x04,0x45=>0x05,0x46=>0x06,0x47=>0x07,0x48=>0x08,0x49=>0x09, // 00217 0x4a=>0x0a,0x4b=>0x0b,0x4c=>0x0c,0x4d=>0x0d,0x4e=>0x0e,0x4f=>0x0f,0x50=>0x10,0x51=>0x11,0x52=>0x12,0x53=>0x13, // 00218 0x54=>0x14,0x55=>0x15,0x56=>0x16,0x57=>0x17,0x58=>0x18,0x59=>0x19,0x5a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, // 00219 0x7e=>0x1e,0x7f=>0x1f), // 00220 'X12' => array( // Set for X12 ---------------------------------------------------------------------------------- 00221 0x0d=>0x00,0x2a=>0x01,0x3e=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, // 00222 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, // 00223 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, // 00224 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27) // 00225 ); 00226 00227 // ----------------------------------------------------------------------------- 00228 00235 public function __construct($code) { 00236 $barcode_array = array(); 00237 if ((is_null($code)) OR ($code == '\0') OR ($code == '')) { 00238 return false; 00239 } 00240 // get data codewords 00241 $cw = $this->getHighLevelEncoding($code); 00242 // number of data codewords 00243 $nd = count($cw); 00244 // check size 00245 if ($nd > 1558) { 00246 return false; 00247 } 00248 // get minimum required matrix size. 00249 foreach ($this->symbattr as $params) { 00250 if ($params[11] >= $nd) { 00251 break; 00252 } 00253 } 00254 if ($params[11] < $nd) { 00255 // too much data 00256 return false; 00257 } elseif ($params[11] > $nd) { 00258 // add padding 00259 if ($this->last_enc == ENC_EDF) { 00260 // switch to ASCII encoding 00261 $cw[] = 124; 00262 ++$nd; 00263 } elseif (($this->last_enc != ENC_ASCII) AND ($this->last_enc != ENC_BASE256)) { 00264 // switch to ASCII encoding 00265 $cw[] = 254; 00266 ++$nd; 00267 } 00268 if ($params[11] > $nd) { 00269 // add first pad 00270 $cw[] = 129; 00271 ++$nd; 00272 // add remaining pads 00273 for ($i = $nd; $i <= $params[11]; ++$i) { 00274 $cw[] = $this->get253StateCodeword(129, $i); 00275 } 00276 } 00277 } 00278 // add error correction codewords 00279 $cw = $this->getErrorCorrection($cw, $params[13], $params[14], $params[15]); 00280 // initialize empty arrays 00281 $grid = array_fill(0, ($params[2] * $params[3]), 0); 00282 // get placement map 00283 $places = $this->getPlacemetMap($params[2], $params[3]); 00284 // fill the grid with data 00285 $grid = array(); 00286 $i = 0; 00287 // region data row max index 00288 $rdri = ($params[4] - 1); 00289 // region data column max index 00290 $rdci = ($params[5] - 1); 00291 // for each vertical region 00292 for ($vr = 0; $vr < $params[9]; ++$vr) { 00293 // for each row on region 00294 for ($r = 0; $r < $params[4]; ++$r) { 00295 // get row 00296 $row = (($vr * $params[4]) + $r); 00297 // for each horizontal region 00298 for ($hr = 0; $hr < $params[8]; ++$hr) { 00299 // for each column on region 00300 for ($c = 0; $c < $params[5]; ++$c) { 00301 // get column 00302 $col = (($hr * $params[5]) + $c); 00303 // braw bits by case 00304 if ($r == 0) { 00305 // top finder pattern 00306 if ($c % 2) { 00307 $grid[$row][$col] = 0; 00308 } else { 00309 $grid[$row][$col] = 1; 00310 } 00311 } elseif ($r == $rdri) { 00312 // bottom finder pattern 00313 $grid[$row][$col] = 1; 00314 } elseif ($c == 0) { 00315 // left finder pattern 00316 $grid[$row][$col] = 1; 00317 } elseif ($c == $rdci) { 00318 // right finder pattern 00319 if ($r % 2) { 00320 $grid[$row][$col] = 1; 00321 } else { 00322 $grid[$row][$col] = 0; 00323 } 00324 } else { // data bit 00325 if ($places[$i] < 2) { 00326 $grid[$row][$col] = $places[$i]; 00327 } else { 00328 // codeword ID 00329 $cw_id = (floor($places[$i] / 10) - 1); 00330 // codeword BIT mask 00331 $cw_bit = pow(2, (8 - ($places[$i] % 10))); 00332 $grid[$row][$col] = (($cw[$cw_id] & $cw_bit) == 0) ? 0 : 1; 00333 } 00334 ++$i; 00335 } 00336 } 00337 } 00338 } 00339 } 00340 $this->barcode_array['num_rows'] = $params[0]; 00341 $this->barcode_array['num_cols'] = $params[1]; 00342 $this->barcode_array['bcode'] = $grid; 00343 } 00344 00350 public function getBarcodeArray() { 00351 return $this->barcode_array; 00352 } 00353 00364 protected function getGFProduct($a, $b, $log, $alog, $gf) { 00365 if (($a == 0) OR ($b == 0)) { 00366 return 0; 00367 } 00368 return $alog[($log[$a] + $log[$b]) % ($gf - 1)]; 00369 } 00370 00382 protected function getErrorCorrection($wd, $nb, $nd, $nc, $gf=256, $pp=301) { 00383 // generate the log ($log) and antilog ($alog) tables 00384 $log[0] = 0; 00385 $alog[0] = 1; 00386 for ($i = 1; $i < $gf; ++$i) { 00387 $alog[$i] = ($alog[($i - 1)] * 2); 00388 if ($alog[$i] >= $gf) { 00389 $alog[$i] ^= $pp; 00390 } 00391 $log[$alog[$i]] = $i; 00392 } 00393 ksort($log); 00394 // generate the polynomial coefficients (c) 00395 $c = array_fill(0, ($nc + 1), 0); 00396 $c[0] = 1; 00397 for ($i = 1; $i <= $nc; ++$i) { 00398 $c[$i] = $c[($i-1)]; 00399 for ($j = ($i - 1); $j >= 1; --$j) { 00400 $c[$j] = $c[($j - 1)] ^ $this->getGFProduct($c[$j], $alog[$i], $log, $alog, $gf); 00401 } 00402 $c[0] = $this->getGFProduct($c[0], $alog[$i], $log, $alog, $gf); 00403 } 00404 ksort($c); 00405 // total number of data codewords 00406 $num_wd = ($nb * $nd); 00407 // total number of error codewords 00408 $num_we = ($nb * $nc); 00409 // for each block 00410 for ($b = 0; $b < $nb; ++$b) { 00411 // create interleaved data block 00412 $block = array(); 00413 for ($n = $b; $n < $num_wd; $n += $nb) { 00414 $block[] = $wd[$n]; 00415 } 00416 // initialize error codewords 00417 $we = array_fill(0, ($nc + 1), 0); 00418 // calculate error correction codewords for this block 00419 for ($i = 0; $i < $nd; ++$i) { 00420 $k = ($we[0] ^ $block[$i]); 00421 for ($j = 0; $j < $nc; ++$j) { 00422 $we[$j] = ($we[($j + 1)] ^ $this->getGFProduct($k, $c[($nc - $j - 1)], $log, $alog, $gf)); 00423 } 00424 } 00425 // add error codewords at the end of data codewords 00426 $j = 0; 00427 for ($i = $b; $i < $num_we; $i += $nb) { 00428 $wd[($num_wd + $i)] = $we[$j]; 00429 ++$j; 00430 } 00431 } 00432 // reorder codewords 00433 ksort($wd); 00434 return $wd; 00435 } 00436 00444 protected function get253StateCodeword($cwpad, $cwpos) { 00445 $pad = ($cwpad + (((149 * $cwpos) % 253) + 1)); 00446 if ($pad > 254) { 00447 $pad -= 254; 00448 } 00449 return $pad; 00450 } 00451 00459 protected function get255StateCodeword($cwpad, $cwpos) { 00460 $pad = ($cwpad + (((149 * $cwpos) % 255) + 1)); 00461 if ($pad > 255) { 00462 $pad -= 256; 00463 } 00464 return $pad; 00465 } 00466 00474 protected function isCharMode($chr, $mode) { 00475 $status = false; 00476 switch ($mode) { 00477 case ENC_ASCII: { // ASCII character 0 to 127 00478 $status = (($chr >= 0) AND ($chr <= 127)); 00479 break; 00480 } 00481 case ENC_C40: { // Upper-case alphanumeric 00482 $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 65) AND ($chr <= 90))); 00483 break; 00484 } 00485 case ENC_TXT: { // Lower-case alphanumeric 00486 $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 97) AND ($chr <= 122))); 00487 break; 00488 } 00489 case ENC_X12: { // ANSI X12 00490 $status = (($chr == 13) OR ($chr == 42) OR ($chr == 62)); 00491 break; 00492 } 00493 case ENC_EDF: { // ASCII character 32 to 94 00494 $status = (($chr >= 32) AND ($chr <= 94)); 00495 break; 00496 } 00497 case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page) 00498 $status = (($chr == 232) OR ($chr == 233) OR ($chr == 234) OR ($chr == 241)); 00499 break; 00500 } 00501 case ENC_ASCII_EXT: { // ASCII character 128 to 255 00502 $status = (($chr >= 128) AND ($chr <= 255)); 00503 break; 00504 } 00505 case ENC_ASCII_NUM: { // ASCII digits 00506 $status = (($chr >= 48) AND ($chr <= 57)); 00507 break; 00508 } 00509 } 00510 return $status; 00511 } 00512 00521 protected function lookAheadTest($data, $pos, $mode) { 00522 $data_length = strlen($data); 00523 if ($pos >= $data_length) { 00524 return $mode; 00525 } 00526 $charscount = 0; // count processed chars 00527 // STEP J 00528 if ($mode == ENC_ASCII) { 00529 $numch = array(0, 1, 1, 1, 1, 1.25); 00530 } else { 00531 $numch = array(1, 2, 2, 2, 2, 2.25); 00532 $numch[$mode] = 0; 00533 } 00534 while (true) { 00535 // STEP K 00536 if (($pos + $charscount) == $data_length) { 00537 if ($numch[ENC_ASCII] <= ceil(min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) { 00538 return ENC_ASCII; 00539 } 00540 if ($numch[ENC_BASE256] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) { 00541 return ENC_BASE256; 00542 } 00543 if ($numch[ENC_EDF] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256]))) { 00544 return ENC_EDF; 00545 } 00546 if ($numch[ENC_TXT] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) { 00547 return ENC_TXT; 00548 } 00549 if ($numch[ENC_X12] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256]))) { 00550 return ENC_X12; 00551 } 00552 return ENC_C40; 00553 } 00554 // get char 00555 $chr = ord($data{($pos + $charscount)}); 00556 $charscount++; 00557 // STEP L 00558 if ($this->isCharMode($chr, ENC_ASCII_NUM)) { 00559 $numch[ENC_ASCII] += (1 / 2); 00560 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 00561 $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]); 00562 $numch[ENC_ASCII] += 2; 00563 } else { 00564 $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]); 00565 $numch[ENC_ASCII] += 1; 00566 } 00567 // STEP M 00568 if ($this->isCharMode($chr, ENC_C40)) { 00569 $numch[ENC_C40] += (2 / 3); 00570 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 00571 $numch[ENC_C40] += (8 / 3); 00572 } else { 00573 $numch[ENC_C40] += (4 / 3); 00574 } 00575 // STEP N 00576 if ($this->isCharMode($chr, ENC_TXT)) { 00577 $numch[ENC_TXT] += (2 / 3); 00578 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 00579 $numch[ENC_TXT] += (8 / 3); 00580 } else { 00581 $numch[ENC_TXT] += (4 / 3); 00582 } 00583 // STEP O 00584 if ($this->isCharMode($chr, ENC_X12) OR $this->isCharMode($chr, ENC_C40)) { 00585 $numch[ENC_X12] += (2 / 3); 00586 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 00587 $numch[ENC_X12] += (13 / 3); 00588 } else { 00589 $numch[ENC_X12] += (10 / 3); 00590 } 00591 // STEP P 00592 if ($this->isCharMode($chr, ENC_EDF)) { 00593 $numch[ENC_EDF] += (3 / 4); 00594 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) { 00595 $numch[ENC_EDF] += (17 / 4); 00596 } else { 00597 $numch[ENC_EDF] += (13 / 4); 00598 } 00599 // STEP Q 00600 if ($this->isCharMode($chr, ENC_BASE256)) { 00601 $numch[ENC_BASE256] += 4; 00602 } else { 00603 $numch[ENC_BASE256] += 1; 00604 } 00605 // STEP R 00606 if ($charscount >= 4) { 00607 if (($numch[ENC_ASCII] + 1) <= min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) { 00608 return ENC_ASCII; 00609 } 00610 if ((($numch[ENC_BASE256] + 1) <= $numch[ENC_ASCII]) 00611 OR (($numch[ENC_BASE256] + 1) < min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) { 00612 return ENC_BASE256; 00613 } 00614 if (($numch[ENC_EDF] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256])) { 00615 return ENC_EDF; 00616 } 00617 if (($numch[ENC_TXT] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) { 00618 return ENC_TXT; 00619 } 00620 if (($numch[ENC_X12] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) { 00621 return ENC_X12; 00622 } 00623 if (($numch[ENC_C40] + 1) < min($numch[ENC_ASCII], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) { 00624 if ($numch[ENC_C40] < $numch[ENC_X12]) { 00625 return ENC_C40; 00626 } 00627 if ($numch[ENC_C40] == $numch[ENC_X12]) { 00628 $k = ($pos + $charscount + 1); 00629 while ($k < $data_length) { 00630 $tmpchr = ord($data{$k}); 00631 if ($this->isCharMode($tmpchr, ENC_X12)) { 00632 return ENC_X12; 00633 } elseif (!($this->isCharMode($tmpchr, ENC_X12) OR $this->isCharMode($tmpchr, ENC_C40))) { 00634 break; 00635 } 00636 ++$k; 00637 } 00638 return ENC_C40; 00639 } 00640 } 00641 } 00642 } // end of while 00643 } 00644 00651 protected function getSwitchEncodingCodeword($mode) { 00652 switch ($mode) { 00653 case ENC_ASCII: { // ASCII character 0 to 127 00654 $cw = 254; 00655 break; 00656 } 00657 case ENC_C40: { // Upper-case alphanumeric 00658 $cw = 230; 00659 break; 00660 } 00661 case ENC_TXT: { // Lower-case alphanumeric 00662 $cw = 239; 00663 break; 00664 } 00665 case ENC_X12: { // ANSI X12 00666 $cw = 238; 00667 break; 00668 } 00669 case ENC_EDF: { // ASCII character 32 to 94 00670 $cw = 240; 00671 break; 00672 } 00673 case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page) 00674 $cw = 231; 00675 break; 00676 } 00677 } 00678 return $cw; 00679 } 00680 00687 protected function getMaxDataCodewords($numcw) { 00688 foreach ($this->symbattr as $key => $matrix) { 00689 if ($matrix[11] >= $numcw) { 00690 return $matrix[11]; 00691 } 00692 } 00693 return 0; 00694 } 00695 00702 protected function getHighLevelEncoding($data) { 00703 // STEP A. Start in ASCII encodation. 00704 $enc = ENC_ASCII; // current encoding mode 00705 $pos = 0; // current position 00706 $cw = array(); // array of codewords to be returned 00707 $cw_num = 0; // number of data codewords 00708 $data_lenght = strlen($data); // number of chars 00709 while ($pos < $data_lenght) { 00710 switch ($enc) { 00711 case ENC_ASCII: { // STEP B. While in ASCII encodation 00712 if (($data_lenght > 1) AND ($pos < ($data_lenght - 1)) AND ($this->isCharMode(ord($data{($pos)}), ENC_ASCII_NUM) AND $this->isCharMode(ord($data{($pos + 1)}), ENC_ASCII_NUM))) { 00713 // 1. If the next data sequence is at least 2 consecutive digits, encode the next two digits as a double digit in ASCII mode. 00714 $cw[] = (intval(substr($data, $pos, 2)) + 130); 00715 ++$cw_num; 00716 $pos += 2; 00717 } else { 00718 // 2. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. 00719 $newenc = $this->lookAheadTest($data, $pos, $enc); 00720 if ($newenc != $enc) { 00721 // switch to new encoding 00722 $enc = $newenc; 00723 $cw[] = $this->getSwitchEncodingCodeword($enc); 00724 ++$cw_num; 00725 } else { 00726 // get new byte 00727 $chr = ord($data{($pos)}); 00728 ++$pos; 00729 if ($this->isCharMode($chr, ENC_ASCII_EXT)) { 00730 // 3. If the next data character is extended ASCII (greater than 127) encode it in ASCII mode first using the Upper Shift (value 235) character. 00731 $cw[] = 235; 00732 $cw[] = ($chr - 127); 00733 $cw_num += 2; 00734 } else { 00735 // 4. Otherwise process the next data character in ASCII encodation. 00736 $cw[] = ($chr + 1); 00737 ++$cw_num; 00738 } 00739 } 00740 } 00741 break; 00742 } 00743 case ENC_C40 : // Upper-case alphanumeric 00744 case ENC_TXT : // Lower-case alphanumeric 00745 case ENC_X12 : { // ANSI X12 00746 $temp_cw = array(); 00747 $p = 0; 00748 $epos = $pos; 00749 // get charset ID 00750 $set_id = $this->chset_id[$enc]; 00751 // get basic charset for current encoding 00752 $charset = $this->chset[$set_id]; 00753 do { 00754 // 2. process the next character in C40 encodation. 00755 $chr = ord($data{($epos)}); 00756 ++$epos; 00757 // check for extended character 00758 if ($chr & 0x80) { 00759 if ($enc == ENC_X12) { 00760 return false; 00761 } 00762 $chr = ($chr & 0x7f); 00763 $temp_cw[] = 1; // shift 2 00764 $temp_cw[] = 30; // upper shift 00765 $p += 2; 00766 } 00767 if (isset($charset[$chr])) { 00768 $temp_cw[] = $charset[$chr]; 00769 ++$p; 00770 } else { 00771 if (isset($this->chset['SH1'][$chr])) { 00772 $temp_cw[] = 0; // shift 1 00773 $shiftset = $this->chset['SH1']; 00774 } elseif (isset($chr, $this->chset['SH2'][$chr])) { 00775 $temp_cw[] = 1; // shift 2 00776 $shiftset = $this->chset['SH2']; 00777 } elseif (($enc == ENC_C40) AND isset($this->chset['S3C'][$chr])) { 00778 $temp_cw[] = 2; // shift 3 00779 $shiftset = $this->chset['S3C']; 00780 } elseif (($enc == ENC_TXT) AND isset($this->chset['S3T'][$chr])) { 00781 $temp_cw[] = 2; // shift 3 00782 $shiftset = $this->chset['S3T']; 00783 } else { 00784 return false; 00785 } 00786 $temp_cw[] = $shiftset[$chr]; 00787 $p += 2; 00788 } 00789 if ($p >= 3) { 00790 $c1 = array_shift($temp_cw); 00791 $c2 = array_shift($temp_cw); 00792 $c3 = array_shift($temp_cw); 00793 $p -= 3; 00794 $tmp = ((1600 * $c1) + (40 * $c2) + $c3 + 1); 00795 $cw[] = ($tmp >> 8); 00796 $cw[] = ($tmp % 256); 00797 $cw_num += 2; 00798 $pos = $epos; 00799 // 1. If the C40 encoding is at the point of starting a new double symbol character and if the look-ahead test (starting at step J) indicates another mode, switch to that mode. 00800 $newenc = $this->lookAheadTest($data, $pos, $enc); 00801 if ($newenc != $enc) { 00802 $enc = $newenc; 00803 $cw[] = $this->getSwitchEncodingCodeword($enc); 00804 ++$cw_num; 00805 break; 00806 } 00807 } 00808 } while (($p > 0) AND ($epos < $data_lenght)); 00809 // process last data (if any) 00810 if ($p > 0) { 00811 // get remaining number of data symbols 00812 $cwr = ($this->getMaxDataCodewords($cw_num + 2) - $cw_num); 00813 if (($cwr == 1) AND ($p == 1)) { 00814 // d. If one symbol character remains and one C40 value (data character) remains to be encoded 00815 $c1 = array_shift($temp_cw); 00816 --$p; 00817 $cw[] = ($c1 + 1); 00818 ++$cw_num; 00819 } elseif (($cwr == 2) AND ($p == 1)) { 00820 // c. If two symbol characters remain and only one C40 value (data character) remains to be encoded 00821 $c1 = array_shift($temp_cw); 00822 --$p; 00823 $cw[] = 254; 00824 $cw[] = ($c1 + 1); 00825 $cw_num += 2; 00826 } elseif (($cwr == 2) AND ($p == 2)) { 00827 // b. If two symbol characters remain and two C40 values remain to be encoded 00828 $c1 = array_shift($temp_cw); 00829 $c2 = array_shift($temp_cw); 00830 $p -= 2; 00831 $tmp = ((1600 * $c1) + (40 * $c2) + 1); 00832 $cw[] = ($tmp >> 8); 00833 $cw[] = ($tmp % 256); 00834 $cw_num += 2; 00835 } else { 00836 // switch to ASCII encoding 00837 $enc = ENC_ASCII; 00838 $cw[] = $this->getSwitchEncodingCodeword($enc); 00839 ++$cw_num; 00840 } 00841 } 00842 break; 00843 } 00844 case ENC_EDF: { // F. While in EDIFACT (EDF) encodation 00845 // initialize temporary array with 0 lenght 00846 $temp_cw = array(); 00847 $epos = $pos; 00848 $field_lenght = 0; 00849 while ($epos < $data_lenght) { 00850 // 2. process the next character in EDIFACT encodation. 00851 $chr = ord($data{($epos)}); 00852 ++$epos; 00853 $temp_cw[] = $chr; 00854 ++$field_lenght; 00855 if (($field_lenght == 4) OR ($epos == $data_lenght)) { 00856 if ($field_lenght < 4) { 00857 // set unlatch character 00858 $temp_cw[] = 0x1f; 00859 ++$field_lenght; 00860 $enc = ENC_ASCII; 00861 // fill empty characters 00862 for ($i = $field_lenght; $i < 4; ++$i) { 00863 $temp_cw[] = 0; 00864 } 00865 } 00866 // encodes four data characters in three codewords 00867 $cw[] = (($temp_cw[0] & 0x3F) << 2) + (($temp_cw[1] & 0x30) >> 4); 00868 $cw[] = (($temp_cw[1] & 0x0F) << 4) + (($temp_cw[2] & 0x3C) >> 2); 00869 $cw[] = (($temp_cw[2] & 0x03) << 6) + ($temp_cw[3] & 0x3F); 00870 $cw_num += 3; 00871 $temp_cw = array(); 00872 $pos = $epos; 00873 $field_lenght = 0; 00874 } 00875 // 1. If the EDIFACT encoding is at the point of starting a new triple symbol character and if the look-ahead test (starting at step J) indicates another mode, switch to that mode. 00876 if ($field_lenght == 0) { 00877 // get remaining number of data symbols 00878 $cwr = ($this->getMaxDataCodewords($cw_num + 2) - $cw_num); 00879 if ($cwr < 3) { 00880 // return to ascii without unlatch 00881 $enc = ENC_ASCII; 00882 break; // exit from EDIFACT mode 00883 } else { 00884 $newenc = $this->lookAheadTest($data, $pos, $enc); 00885 if ($newenc != $enc) { 00886 // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. 00887 $enc = $newenc; 00888 $cw[] = $this->getSwitchEncodingCodeword($enc); 00889 ++$cw_num; 00890 break; // exit from EDIFACT mode 00891 } 00892 } 00893 } 00894 } 00895 break; 00896 } 00897 case ENC_BASE256: { // G. While in Base 256 (B256) encodation 00898 // initialize temporary array with 0 lenght 00899 $temp_cw = array(); 00900 $field_lenght = 0; 00901 while (($pos < $data_lenght) AND ($field_lenght <= 1555)) { 00902 $newenc = $this->lookAheadTest($data, $pos, $enc); 00903 if ($newenc != $enc) { 00904 // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode. 00905 $enc = $newenc; 00906 $cw[] = $this->getSwitchEncodingCodeword($enc); 00907 ++$cw_num; 00908 break; // exit from B256 mode 00909 } else { 00910 // 2. Otherwise, process the next character in Base 256 encodation. 00911 $chr = ord($data{($pos)}); 00912 ++$pos; 00913 $temp_cw[] = $chr; 00914 ++$field_lenght; 00915 } 00916 } 00917 // set field lenght 00918 if ($field_lenght <= 249) { 00919 $cw[] = $field_lenght; 00920 ++$cw_num; 00921 } else { 00922 $cw[] = (floor($field_lenght / 250) + 249); 00923 $cw[] = ($field_lenght % 250); 00924 $cw_num += 2; 00925 } 00926 if (!empty($temp_cw)) { 00927 // add B256 field 00928 foreach ($temp_cw as $p => $cht) { 00929 $cw[] = $this->get255StateCodeword($chr, ($cw_num + $p)); 00930 } 00931 } 00932 break; 00933 } 00934 } // end of switch enc 00935 } // end of while 00936 // set last used encoding 00937 $this->last_enc = $enc; 00938 return $cw; 00939 } 00940 00954 protected function placeModule($marr, $nrow, $ncol, $row, $col, $chr, $bit) { 00955 if ($row < 0) { 00956 $row += $nrow; 00957 $col += (4 - (($nrow + 4) % 8)); 00958 } 00959 if ($col < 0) { 00960 $col += $ncol; 00961 $row += (4 - (($ncol + 4) % 8)); 00962 } 00963 $marr[(($row * $ncol) + $col)] = ((10 * $chr) + $bit); 00964 return $marr; 00965 } 00966 00979 protected function placeUtah($marr, $nrow, $ncol, $row, $col, $chr) { 00980 $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-2, $chr, 1); 00981 $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-1, $chr, 2); 00982 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-2, $chr, 3); 00983 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-1, $chr, 4); 00984 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col, $chr, 5); 00985 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-2, $chr, 6); 00986 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-1, $chr, 7); 00987 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col, $chr, 8); 00988 return $marr; 00989 } 00990 01001 protected function placeCornerA($marr, $nrow, $ncol, $chr) { 01002 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1); 01003 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 1, $chr, 2); 01004 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 2, $chr, 3); 01005 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); 01006 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); 01007 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6); 01008 $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7); 01009 $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8); 01010 return $marr; 01011 } 01012 01023 protected function placeCornerB($marr, $nrow, $ncol, $chr) { 01024 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1); 01025 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2); 01026 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3); 01027 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-4, $chr, 4); 01028 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 5); 01029 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 6); 01030 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 7); 01031 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8); 01032 return $marr; 01033 } 01034 01045 protected function placeCornerC($marr, $nrow, $ncol, $chr) { 01046 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1); 01047 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2); 01048 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3); 01049 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); 01050 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); 01051 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6); 01052 $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7); 01053 $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8); 01054 return $marr; 01055 } 01056 01067 protected function placeCornerD($marr, $nrow, $ncol, $chr) { 01068 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1); 01069 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, $ncol-1, $chr, 2); 01070 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 3); 01071 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4); 01072 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5); 01073 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-3, $chr, 6); 01074 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-2, $chr, 7); 01075 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8); 01076 return $marr; 01077 } 01078 01079 01088 protected function getPlacemetMap($nrow, $ncol) { 01089 // initialize array with zeros 01090 $marr = array_fill(0, ($nrow * $ncol), 0); 01091 // set starting values 01092 $chr = 1; 01093 $row = 4; 01094 $col = 0; 01095 do { 01096 // repeatedly first check for one of the special corner cases, then 01097 if (($row == $nrow) AND ($col == 0)) { 01098 $marr = $this->placeCornerA($marr, $nrow, $ncol, $chr); 01099 ++$chr; 01100 } 01101 if (($row == ($nrow - 2)) AND ($col == 0) AND ($ncol % 4)) { 01102 $marr = $this->placeCornerB($marr, $nrow, $ncol, $chr); 01103 ++$chr; 01104 } 01105 if (($row == ($nrow - 2)) AND ($col == 0) AND (($ncol % 8) == 4)) { 01106 $marr = $this->placeCornerC($marr, $nrow, $ncol, $chr); 01107 ++$chr; 01108 } 01109 if (($row == ($nrow + 4)) AND ($col == 2) AND (!($ncol % 8))) { 01110 $marr = $this->placeCornerD($marr, $nrow, $ncol, $chr); 01111 ++$chr; 01112 } 01113 // sweep upward diagonally, inserting successive characters, 01114 do { 01115 if (($row < $nrow) AND ($col >= 0) AND (!$marr[(($row * $ncol) + $col)])) { 01116 $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr); 01117 ++$chr; 01118 } 01119 $row -= 2; 01120 $col += 2; 01121 } while (($row >= 0) AND ($col < $ncol)); 01122 ++$row; 01123 $col += 3; 01124 // & then sweep downward diagonally, inserting successive characters,... 01125 do { 01126 if (($row >= 0) AND ($col < $ncol) AND (!$marr[(($row * $ncol) + $col)])) { 01127 $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr); 01128 ++$chr; 01129 } 01130 $row += 2; 01131 $col -= 2; 01132 } while (($row < $nrow) AND ($col >= 0)); 01133 $row += 3; 01134 ++$col; 01135 // ... until the entire array is scanned 01136 } while (($row < $nrow) OR ($col < $ncol)); 01137 // lastly, if the lower righthand corner is untouched, fill in fixed pattern 01138 if (!$marr[(($nrow * $ncol) - 1)]) { 01139 $marr[(($nrow * $ncol) - 1)] = 1; 01140 $marr[(($nrow * $ncol) - $ncol - 2)] = 1; 01141 } 01142 return $marr; 01143 } 01144 01145 } // end DataMatrix class 01146 //============================================================+ 01147 // END OF FILE 01148 //============================================================+