PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / trunk
Matomo Analytics – Powerful, Privacy-First Insights for WordPress vtrunk
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / vendor / tecnickcom / tcpdf / include / barcodes / datamatrix.php
matomo / app / vendor / tecnickcom / tcpdf / include / barcodes Last commit date
datamatrix.php 2 months ago pdf417.php 2 months ago qrcode.php 2 months ago
datamatrix.php
1465 lines
1 <?php
2
3 namespace {
4 //============================================================+
5 // File name : datamatrix.php
6 // Version : 1.0.008
7 // Begin : 2010-06-07
8 // Last Update : 2014-05-06
9 // Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
10 // License : GNU-LGPL v3 (https://www.gnu.org/copyleft/lesser.html)
11 // -------------------------------------------------------------------
12 // Copyright (C) 2010-2014 2026 Nicola Asuni - Tecnick.com LTD
13 //
14 // This file is part of TCPDF software library.
15 //
16 // TCPDF is free software: you can redistribute it and/or modify it
17 // under the terms of the GNU Lesser General Public License as
18 // published by the Free Software Foundation, either version 3 of the
19 // License, or (at your option) any later version.
20 //
21 // TCPDF is distributed in the hope that it will be useful, but
22 // WITHOUT ANY WARRANTY; without even the implied warranty of
23 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24 // See the GNU Lesser General Public License for more details.
25 //
26 // You should have received a copy of the GNU Lesser General Public License
27 // along with TCPDF. If not, see <https://www.gnu.org/licenses/>.
28 //
29 // See LICENSE.TXT file for more information.
30 // -------------------------------------------------------------------
31 //
32 // DESCRIPTION :
33 //
34 // Class to create DataMatrix ECC 200 barcode arrays for TCPDF class.
35 // DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code.
36 //============================================================+
37 /**
38 * @file
39 * Class to create DataMatrix ECC 200 barcode arrays for TCPDF class.
40 * DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code.
41 *
42 * @package com.tecnick.tcpdf
43 * @author Nicola Asuni
44 * @version 1.0.008
45 */
46 // custom definitions
47 if (!\defined('DATAMATRIXDEFS')) {
48 /**
49 * Indicate that definitions for this class are set
50 */
51 \define('DATAMATRIXDEFS', \true);
52 // -----------------------------------------------------
53 }
54 // end of custom definitions
55 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
56 /**
57 * ASCII encoding: ASCII character 0 to 127 (1 byte per CW)
58 */
59 \define('ENC_ASCII', 0);
60 /**
61 * C40 encoding: Upper-case alphanumeric (3/2 bytes per CW)
62 */
63 \define('ENC_C40', 1);
64 /**
65 * TEXT encoding: Lower-case alphanumeric (3/2 bytes per CW)
66 */
67 \define('ENC_TXT', 2);
68 /**
69 * X12 encoding: ANSI X12 (3/2 byte per CW)
70 */
71 \define('ENC_X12', 3);
72 /**
73 * EDIFACT encoding: ASCII character 32 to 94 (4/3 bytes per CW)
74 */
75 \define('ENC_EDF', 4);
76 /**
77 * BASE 256 encoding: ASCII character 0 to 255 (1 byte per CW)
78 */
79 \define('ENC_BASE256', 5);
80 /**
81 * ASCII extended encoding: ASCII character 128 to 255 (1/2 byte per CW)
82 */
83 \define('ENC_ASCII_EXT', 6);
84 /**
85 * ASCII number encoding: ASCII digits (2 bytes per CW)
86 */
87 \define('ENC_ASCII_NUM', 7);
88 /**
89 * @class Datamatrix
90 * Class to create DataMatrix ECC 200 barcode arrays for TCPDF class.
91 * DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code.
92 *
93 * @package com.tecnick.tcpdf
94 * @author Nicola Asuni
95 * @version 1.0.004
96 */
97 class Datamatrix
98 {
99 /**
100 * Barcode array to be returned which is readable by TCPDF.
101 * @protected
102 */
103 protected $barcode_array = array();
104 /**
105 * Store last used encoding for data codewords.
106 * @protected
107 */
108 protected $last_enc = \ENC_ASCII;
109 /**
110 * Table of Data Matrix ECC 200 Symbol Attributes:<ul>
111 * <li>total matrix rows (including finder pattern)</li>
112 * <li>total matrix cols (including finder pattern)</li>
113 * <li>total matrix rows (without finder pattern)</li>
114 * <li>total matrix cols (without finder pattern)</li>
115 * <li>region data rows (with finder pattern)</li>
116 * <li>region data col (with finder pattern)</li>
117 * <li>region data rows (without finder pattern)</li>
118 * <li>region data col (without finder pattern)</li>
119 * <li>horizontal regions</li>
120 * <li>vertical regions</li>
121 * <li>regions</li>
122 * <li>data codewords</li>
123 * <li>error codewords</li>
124 * <li>blocks</li>
125 * <li>data codewords per block</li>
126 * <li>error codewords per block</li>
127 * </ul>
128 * @protected
129 */
130 protected $symbattr = array(
131 // square form ---------------------------------------------------------------------------------------
132 array(0xa, 0xa, 0x8, 0x8, 0xa, 0xa, 0x8, 0x8, 0x1, 0x1, 0x1, 0x3, 0x5, 0x1, 0x3, 0x5),
133 // 10x10
134 array(0xc, 0xc, 0xa, 0xa, 0xc, 0xc, 0xa, 0xa, 0x1, 0x1, 0x1, 0x5, 0x7, 0x1, 0x5, 0x7),
135 // 12x12
136 array(0xe, 0xe, 0xc, 0xc, 0xe, 0xe, 0xc, 0xc, 0x1, 0x1, 0x1, 0x8, 0xa, 0x1, 0x8, 0xa),
137 // 14x14
138 array(0x10, 0x10, 0xe, 0xe, 0x10, 0x10, 0xe, 0xe, 0x1, 0x1, 0x1, 0xc, 0xc, 0x1, 0xc, 0xc),
139 // 16x16
140 array(0x12, 0x12, 0x10, 0x10, 0x12, 0x12, 0x10, 0x10, 0x1, 0x1, 0x1, 0x12, 0xe, 0x1, 0x12, 0xe),
141 // 18x18
142 array(0x14, 0x14, 0x12, 0x12, 0x14, 0x14, 0x12, 0x12, 0x1, 0x1, 0x1, 0x16, 0x12, 0x1, 0x16, 0x12),
143 // 20x20
144 array(0x16, 0x16, 0x14, 0x14, 0x16, 0x16, 0x14, 0x14, 0x1, 0x1, 0x1, 0x1e, 0x14, 0x1, 0x1e, 0x14),
145 // 22x22
146 array(0x18, 0x18, 0x16, 0x16, 0x18, 0x18, 0x16, 0x16, 0x1, 0x1, 0x1, 0x24, 0x18, 0x1, 0x24, 0x18),
147 // 24x24
148 array(0x1a, 0x1a, 0x18, 0x18, 0x1a, 0x1a, 0x18, 0x18, 0x1, 0x1, 0x1, 0x2c, 0x1c, 0x1, 0x2c, 0x1c),
149 // 26x26
150 array(0x20, 0x20, 0x1c, 0x1c, 0x10, 0x10, 0xe, 0xe, 0x2, 0x2, 0x4, 0x3e, 0x24, 0x1, 0x3e, 0x24),
151 // 32x32
152 array(0x24, 0x24, 0x20, 0x20, 0x12, 0x12, 0x10, 0x10, 0x2, 0x2, 0x4, 0x56, 0x2a, 0x1, 0x56, 0x2a),
153 // 36x36
154 array(0x28, 0x28, 0x24, 0x24, 0x14, 0x14, 0x12, 0x12, 0x2, 0x2, 0x4, 0x72, 0x30, 0x1, 0x72, 0x30),
155 // 40x40
156 array(0x2c, 0x2c, 0x28, 0x28, 0x16, 0x16, 0x14, 0x14, 0x2, 0x2, 0x4, 0x90, 0x38, 0x1, 0x90, 0x38),
157 // 44x44
158 array(0x30, 0x30, 0x2c, 0x2c, 0x18, 0x18, 0x16, 0x16, 0x2, 0x2, 0x4, 0xae, 0x44, 0x1, 0xae, 0x44),
159 // 48x48
160 array(0x34, 0x34, 0x30, 0x30, 0x1a, 0x1a, 0x18, 0x18, 0x2, 0x2, 0x4, 0xcc, 0x54, 0x2, 0x66, 0x2a),
161 // 52x52
162 array(0x40, 0x40, 0x38, 0x38, 0x10, 0x10, 0xe, 0xe, 0x4, 0x4, 0x10, 0x118, 0x70, 0x2, 0x8c, 0x38),
163 // 64x64
164 array(0x48, 0x48, 0x40, 0x40, 0x12, 0x12, 0x10, 0x10, 0x4, 0x4, 0x10, 0x170, 0x90, 0x4, 0x5c, 0x24),
165 // 72x72
166 array(0x50, 0x50, 0x48, 0x48, 0x14, 0x14, 0x12, 0x12, 0x4, 0x4, 0x10, 0x1c8, 0xc0, 0x4, 0x72, 0x30),
167 // 80x80
168 array(0x58, 0x58, 0x50, 0x50, 0x16, 0x16, 0x14, 0x14, 0x4, 0x4, 0x10, 0x240, 0xe0, 0x4, 0x90, 0x38),
169 // 88x88
170 array(0x60, 0x60, 0x58, 0x58, 0x18, 0x18, 0x16, 0x16, 0x4, 0x4, 0x10, 0x2b8, 0x110, 0x4, 0xae, 0x44),
171 // 96x96
172 array(0x68, 0x68, 0x60, 0x60, 0x1a, 0x1a, 0x18, 0x18, 0x4, 0x4, 0x10, 0x330, 0x150, 0x6, 0x88, 0x38),
173 // 104x104
174 array(0x78, 0x78, 0x6c, 0x6c, 0x14, 0x14, 0x12, 0x12, 0x6, 0x6, 0x24, 0x41a, 0x198, 0x6, 0xaf, 0x44),
175 // 120x120
176 array(0x84, 0x84, 0x78, 0x78, 0x16, 0x16, 0x14, 0x14, 0x6, 0x6, 0x24, 0x518, 0x1f0, 0x8, 0xa3, 0x3e),
177 // 132x132
178 array(0x90, 0x90, 0x84, 0x84, 0x18, 0x18, 0x16, 0x16, 0x6, 0x6, 0x24, 0x616, 0x26c, 0xa, 0x9c, 0x3e),
179 // 144x144
180 // rectangular form (currently unused) ---------------------------------------------------------------------------
181 array(0x8, 0x12, 0x6, 0x10, 0x8, 0x12, 0x6, 0x10, 0x1, 0x1, 0x1, 0x5, 0x7, 0x1, 0x5, 0x7),
182 // 8x18
183 array(0x8, 0x20, 0x6, 0x1c, 0x8, 0x10, 0x6, 0xe, 0x1, 0x2, 0x2, 0xa, 0xb, 0x1, 0xa, 0xb),
184 // 8x32
185 array(0xc, 0x1a, 0xa, 0x18, 0xc, 0x1a, 0xa, 0x18, 0x1, 0x1, 0x1, 0x10, 0xe, 0x1, 0x10, 0xe),
186 // 12x26
187 array(0xc, 0x24, 0xa, 0x20, 0xc, 0x12, 0xa, 0x10, 0x1, 0x2, 0x2, 0xc, 0x12, 0x1, 0xc, 0x12),
188 // 12x36
189 array(0x10, 0x24, 0xe, 0x20, 0x10, 0x12, 0xe, 0x10, 0x1, 0x2, 0x2, 0x20, 0x18, 0x1, 0x20, 0x18),
190 // 16x36
191 array(0x10, 0x30, 0xe, 0x2c, 0x10, 0x18, 0xe, 0x16, 0x1, 0x2, 0x2, 0x31, 0x1c, 0x1, 0x31, 0x1c),
192 );
193 /**
194 * Map encodation modes whit character sets.
195 * @protected
196 */
197 protected $chset_id = array(\ENC_C40 => 'C40', \ENC_TXT => 'TXT', \ENC_X12 => 'X12');
198 /**
199 * Basic set of characters for each encodation mode.
200 * @protected
201 */
202 protected $chset = array(
203 'C40' => array(
204 // Basic set for C40 ----------------------------------------------------------------------------
205 'S1' => 0x0,
206 'S2' => 0x1,
207 'S3' => 0x2,
208 0x20 => 0x3,
209 0x30 => 0x4,
210 0x31 => 0x5,
211 0x32 => 0x6,
212 0x33 => 0x7,
213 0x34 => 0x8,
214 0x35 => 0x9,
215 //
216 0x36 => 0xa,
217 0x37 => 0xb,
218 0x38 => 0xc,
219 0x39 => 0xd,
220 0x41 => 0xe,
221 0x42 => 0xf,
222 0x43 => 0x10,
223 0x44 => 0x11,
224 0x45 => 0x12,
225 0x46 => 0x13,
226 //
227 0x47 => 0x14,
228 0x48 => 0x15,
229 0x49 => 0x16,
230 0x4a => 0x17,
231 0x4b => 0x18,
232 0x4c => 0x19,
233 0x4d => 0x1a,
234 0x4e => 0x1b,
235 0x4f => 0x1c,
236 0x50 => 0x1d,
237 //
238 0x51 => 0x1e,
239 0x52 => 0x1f,
240 0x53 => 0x20,
241 0x54 => 0x21,
242 0x55 => 0x22,
243 0x56 => 0x23,
244 0x57 => 0x24,
245 0x58 => 0x25,
246 0x59 => 0x26,
247 0x5a => 0x27,
248 ),
249 //
250 'TXT' => array(
251 // Basic set for TEXT ---------------------------------------------------------------------------
252 'S1' => 0x0,
253 'S2' => 0x1,
254 'S3' => 0x2,
255 0x20 => 0x3,
256 0x30 => 0x4,
257 0x31 => 0x5,
258 0x32 => 0x6,
259 0x33 => 0x7,
260 0x34 => 0x8,
261 0x35 => 0x9,
262 //
263 0x36 => 0xa,
264 0x37 => 0xb,
265 0x38 => 0xc,
266 0x39 => 0xd,
267 0x61 => 0xe,
268 0x62 => 0xf,
269 0x63 => 0x10,
270 0x64 => 0x11,
271 0x65 => 0x12,
272 0x66 => 0x13,
273 //
274 0x67 => 0x14,
275 0x68 => 0x15,
276 0x69 => 0x16,
277 0x6a => 0x17,
278 0x6b => 0x18,
279 0x6c => 0x19,
280 0x6d => 0x1a,
281 0x6e => 0x1b,
282 0x6f => 0x1c,
283 0x70 => 0x1d,
284 //
285 0x71 => 0x1e,
286 0x72 => 0x1f,
287 0x73 => 0x20,
288 0x74 => 0x21,
289 0x75 => 0x22,
290 0x76 => 0x23,
291 0x77 => 0x24,
292 0x78 => 0x25,
293 0x79 => 0x26,
294 0x7a => 0x27,
295 ),
296 //
297 'SH1' => array(
298 // Shift 1 set ----------------------------------------------------------------------------------
299 0x0 => 0x0,
300 0x1 => 0x1,
301 0x2 => 0x2,
302 0x3 => 0x3,
303 0x4 => 0x4,
304 0x5 => 0x5,
305 0x6 => 0x6,
306 0x7 => 0x7,
307 0x8 => 0x8,
308 0x9 => 0x9,
309 //
310 0xa => 0xa,
311 0xb => 0xb,
312 0xc => 0xc,
313 0xd => 0xd,
314 0xe => 0xe,
315 0xf => 0xf,
316 0x10 => 0x10,
317 0x11 => 0x11,
318 0x12 => 0x12,
319 0x13 => 0x13,
320 //
321 0x14 => 0x14,
322 0x15 => 0x15,
323 0x16 => 0x16,
324 0x17 => 0x17,
325 0x18 => 0x18,
326 0x19 => 0x19,
327 0x1a => 0x1a,
328 0x1b => 0x1b,
329 0x1c => 0x1c,
330 0x1d => 0x1d,
331 //
332 0x1e => 0x1e,
333 0x1f => 0x1f,
334 ),
335 //
336 'SH2' => array(
337 // Shift 2 set ----------------------------------------------------------------------------------
338 0x21 => 0x0,
339 0x22 => 0x1,
340 0x23 => 0x2,
341 0x24 => 0x3,
342 0x25 => 0x4,
343 0x26 => 0x5,
344 0x27 => 0x6,
345 0x28 => 0x7,
346 0x29 => 0x8,
347 0x2a => 0x9,
348 //
349 0x2b => 0xa,
350 0x2c => 0xb,
351 0x2d => 0xc,
352 0x2e => 0xd,
353 0x2f => 0xe,
354 0x3a => 0xf,
355 0x3b => 0x10,
356 0x3c => 0x11,
357 0x3d => 0x12,
358 0x3e => 0x13,
359 //
360 0x3f => 0x14,
361 0x40 => 0x15,
362 0x5b => 0x16,
363 0x5c => 0x17,
364 0x5d => 0x18,
365 0x5e => 0x19,
366 0x5f => 0x1a,
367 'F1' => 0x1b,
368 'US' => 0x1e,
369 ),
370 //
371 'S3C' => array(
372 // Shift 3 set for C40 --------------------------------------------------------------------------
373 0x60 => 0x0,
374 0x61 => 0x1,
375 0x62 => 0x2,
376 0x63 => 0x3,
377 0x64 => 0x4,
378 0x65 => 0x5,
379 0x66 => 0x6,
380 0x67 => 0x7,
381 0x68 => 0x8,
382 0x69 => 0x9,
383 //
384 0x6a => 0xa,
385 0x6b => 0xb,
386 0x6c => 0xc,
387 0x6d => 0xd,
388 0x6e => 0xe,
389 0x6f => 0xf,
390 0x70 => 0x10,
391 0x71 => 0x11,
392 0x72 => 0x12,
393 0x73 => 0x13,
394 //
395 0x74 => 0x14,
396 0x75 => 0x15,
397 0x76 => 0x16,
398 0x77 => 0x17,
399 0x78 => 0x18,
400 0x79 => 0x19,
401 0x7a => 0x1a,
402 0x7b => 0x1b,
403 0x7c => 0x1c,
404 0x7d => 0x1d,
405 //
406 0x7e => 0x1e,
407 0x7f => 0x1f,
408 ),
409 'S3T' => array(
410 // Shift 3 set for TEXT -------------------------------------------------------------------------
411 0x60 => 0x0,
412 0x41 => 0x1,
413 0x42 => 0x2,
414 0x43 => 0x3,
415 0x44 => 0x4,
416 0x45 => 0x5,
417 0x46 => 0x6,
418 0x47 => 0x7,
419 0x48 => 0x8,
420 0x49 => 0x9,
421 //
422 0x4a => 0xa,
423 0x4b => 0xb,
424 0x4c => 0xc,
425 0x4d => 0xd,
426 0x4e => 0xe,
427 0x4f => 0xf,
428 0x50 => 0x10,
429 0x51 => 0x11,
430 0x52 => 0x12,
431 0x53 => 0x13,
432 //
433 0x54 => 0x14,
434 0x55 => 0x15,
435 0x56 => 0x16,
436 0x57 => 0x17,
437 0x58 => 0x18,
438 0x59 => 0x19,
439 0x5a => 0x1a,
440 0x7b => 0x1b,
441 0x7c => 0x1c,
442 0x7d => 0x1d,
443 //
444 0x7e => 0x1e,
445 0x7f => 0x1f,
446 ),
447 //
448 'X12' => array(
449 // Set for X12 ----------------------------------------------------------------------------------
450 0xd => 0x0,
451 0x2a => 0x1,
452 0x3e => 0x2,
453 0x20 => 0x3,
454 0x30 => 0x4,
455 0x31 => 0x5,
456 0x32 => 0x6,
457 0x33 => 0x7,
458 0x34 => 0x8,
459 0x35 => 0x9,
460 //
461 0x36 => 0xa,
462 0x37 => 0xb,
463 0x38 => 0xc,
464 0x39 => 0xd,
465 0x41 => 0xe,
466 0x42 => 0xf,
467 0x43 => 0x10,
468 0x44 => 0x11,
469 0x45 => 0x12,
470 0x46 => 0x13,
471 //
472 0x47 => 0x14,
473 0x48 => 0x15,
474 0x49 => 0x16,
475 0x4a => 0x17,
476 0x4b => 0x18,
477 0x4c => 0x19,
478 0x4d => 0x1a,
479 0x4e => 0x1b,
480 0x4f => 0x1c,
481 0x50 => 0x1d,
482 //
483 0x51 => 0x1e,
484 0x52 => 0x1f,
485 0x53 => 0x20,
486 0x54 => 0x21,
487 0x55 => 0x22,
488 0x56 => 0x23,
489 0x57 => 0x24,
490 0x58 => 0x25,
491 0x59 => 0x26,
492 0x5a => 0x27,
493 ),
494 );
495 // -----------------------------------------------------------------------------
496 /**
497 * This is the class constructor.
498 * Creates a datamatrix object
499 * @param string $code Code to represent using Datamatrix.
500 * @public
501 */
502 public function __construct($code)
503 {
504 $barcode_array = array();
505 if (\is_null($code) or $code == '\\0' or $code == '') {
506 return \false;
507 }
508 // get data codewords
509 $cw = $this->getHighLevelEncoding($code);
510 // number of data codewords
511 $nd = \count($cw);
512 // check size
513 if ($nd > 1558) {
514 return \false;
515 }
516 // get minimum required matrix size.
517 foreach ($this->symbattr as $params) {
518 if ($params[11] >= $nd) {
519 break;
520 }
521 }
522 if ($params[11] < $nd) {
523 // too much data
524 return \false;
525 } elseif ($params[11] > $nd) {
526 // add padding
527 if ($params[11] - $nd > 1 and $cw[$nd - 1] != 254) {
528 if ($this->last_enc == \ENC_EDF) {
529 // switch to ASCII encoding
530 $cw[] = 124;
531 ++$nd;
532 } elseif ($this->last_enc != \ENC_ASCII and $this->last_enc != \ENC_BASE256) {
533 // switch to ASCII encoding
534 $cw[] = 254;
535 ++$nd;
536 }
537 }
538 if ($params[11] > $nd) {
539 // add first pad
540 $cw[] = 129;
541 ++$nd;
542 // add remaining pads
543 for ($i = $nd; $i < $params[11]; ++$i) {
544 $cw[] = $this->get253StateCodeword(129, $i);
545 }
546 }
547 }
548 // add error correction codewords
549 $cw = $this->getErrorCorrection($cw, $params[13], $params[14], $params[15]);
550 // initialize empty arrays
551 $grid = \array_fill(0, $params[2] * $params[3], 0);
552 // get placement map
553 $places = $this->getPlacementMap($params[2], $params[3]);
554 // fill the grid with data
555 $grid = array();
556 $i = 0;
557 // region data row max index
558 $rdri = $params[4] - 1;
559 // region data column max index
560 $rdci = $params[5] - 1;
561 // for each vertical region
562 for ($vr = 0; $vr < $params[9]; ++$vr) {
563 // for each row on region
564 for ($r = 0; $r < $params[4]; ++$r) {
565 // get row
566 $row = $vr * $params[4] + $r;
567 // for each horizontal region
568 for ($hr = 0; $hr < $params[8]; ++$hr) {
569 // for each column on region
570 for ($c = 0; $c < $params[5]; ++$c) {
571 // get column
572 $col = $hr * $params[5] + $c;
573 // braw bits by case
574 if ($r == 0) {
575 // top finder pattern
576 if ($c % 2) {
577 $grid[$row][$col] = 0;
578 } else {
579 $grid[$row][$col] = 1;
580 }
581 } elseif ($r == $rdri) {
582 // bottom finder pattern
583 $grid[$row][$col] = 1;
584 } elseif ($c == 0) {
585 // left finder pattern
586 $grid[$row][$col] = 1;
587 } elseif ($c == $rdci) {
588 // right finder pattern
589 if ($r % 2) {
590 $grid[$row][$col] = 1;
591 } else {
592 $grid[$row][$col] = 0;
593 }
594 } else {
595 // data bit
596 if ($places[$i] < 2) {
597 $grid[$row][$col] = $places[$i];
598 } else {
599 // codeword ID
600 $cw_id = \floor($places[$i] / 10) - 1;
601 // codeword BIT mask
602 $cw_bit = \pow(2, 8 - $places[$i] % 10);
603 $grid[$row][$col] = ($cw[$cw_id] & $cw_bit) == 0 ? 0 : 1;
604 }
605 ++$i;
606 }
607 }
608 }
609 }
610 }
611 $this->barcode_array['num_rows'] = $params[0];
612 $this->barcode_array['num_cols'] = $params[1];
613 $this->barcode_array['bcode'] = $grid;
614 }
615 /**
616 * Returns a barcode array which is readable by TCPDF
617 * @return array barcode array readable by TCPDF;
618 * @public
619 */
620 public function getBarcodeArray()
621 {
622 return $this->barcode_array;
623 }
624 /**
625 * Product of two numbers in a Power-of-Two Galois Field
626 * @param int $a first number to multiply.
627 * @param int $b second number to multiply.
628 * @param array $log Log table.
629 * @param array $alog Anti-Log table.
630 * @param int $gf Number of Factors of the Reed-Solomon polynomial.
631 * @return int product
632 * @protected
633 */
634 protected function getGFProduct($a, $b, $log, $alog, $gf)
635 {
636 if ($a == 0 or $b == 0) {
637 return 0;
638 }
639 return $alog[($log[$a] + $log[$b]) % ($gf - 1)];
640 }
641 /**
642 * Add error correction codewords to data codewords array (ANNEX E).
643 * @param array $wd Array of datacodewords.
644 * @param int $nb Number of blocks.
645 * @param int $nd Number of data codewords per block.
646 * @param int $nc Number of correction codewords per block.
647 * @param int $gf numner of fields on log/antilog table (power of 2).
648 * @param int $pp The value of its prime modulus polynomial (301 for ECC200).
649 * @return array data codewords + error codewords
650 * @protected
651 */
652 protected function getErrorCorrection($wd, $nb, $nd, $nc, $gf = 256, $pp = 301)
653 {
654 // generate the log ($log) and antilog ($alog) tables
655 $log[0] = 0;
656 $alog[0] = 1;
657 for ($i = 1; $i < $gf; ++$i) {
658 $alog[$i] = $alog[$i - 1] * 2;
659 if ($alog[$i] >= $gf) {
660 $alog[$i] ^= $pp;
661 }
662 $log[$alog[$i]] = $i;
663 }
664 \ksort($log);
665 // generate the polynomial coefficients (c)
666 $c = \array_fill(0, $nc + 1, 0);
667 $c[0] = 1;
668 for ($i = 1; $i <= $nc; ++$i) {
669 $c[$i] = $c[$i - 1];
670 for ($j = $i - 1; $j >= 1; --$j) {
671 $c[$j] = $c[$j - 1] ^ $this->getGFProduct($c[$j], $alog[$i], $log, $alog, $gf);
672 }
673 $c[0] = $this->getGFProduct($c[0], $alog[$i], $log, $alog, $gf);
674 }
675 \ksort($c);
676 // total number of data codewords
677 $num_wd = $nb * $nd;
678 // total number of error codewords
679 $num_we = $nb * $nc;
680 // for each block
681 for ($b = 0; $b < $nb; ++$b) {
682 // create interleaved data block
683 $block = array();
684 for ($n = $b; $n < $num_wd; $n += $nb) {
685 $block[] = $wd[$n];
686 }
687 // initialize error codewords
688 $we = \array_fill(0, $nc + 1, 0);
689 // calculate error correction codewords for this block
690 for ($i = 0; $i < $nd; ++$i) {
691 $k = $we[0] ^ $block[$i];
692 for ($j = 0; $j < $nc; ++$j) {
693 $we[$j] = $we[$j + 1] ^ $this->getGFProduct($k, $c[$nc - $j - 1], $log, $alog, $gf);
694 }
695 }
696 // add error codewords at the end of data codewords
697 $j = 0;
698 for ($i = $b; $i < $num_we; $i += $nb) {
699 $wd[$num_wd + $i] = $we[$j];
700 ++$j;
701 }
702 }
703 // reorder codewords
704 \ksort($wd);
705 return $wd;
706 }
707 /**
708 * Return the 253-state codeword
709 * @param int $cwpad Pad codeword.
710 * @param int $cwpos Number of data codewords from the beginning of encoded data.
711 * @return int pad codeword
712 * @protected
713 */
714 protected function get253StateCodeword($cwpad, $cwpos)
715 {
716 $pad = $cwpad + (149 * $cwpos % 253 + 1);
717 if ($pad > 254) {
718 $pad -= 254;
719 }
720 return $pad;
721 }
722 /**
723 * Return the 255-state codeword
724 * @param int $cwpad Pad codeword.
725 * @param int $cwpos Number of data codewords from the beginning of encoded data.
726 * @return int pad codeword
727 * @protected
728 */
729 protected function get255StateCodeword($cwpad, $cwpos)
730 {
731 $pad = $cwpad + (149 * $cwpos % 255 + 1);
732 if ($pad > 255) {
733 $pad -= 256;
734 }
735 return $pad;
736 }
737 /**
738 * Returns true if the char belongs to the selected mode
739 * @param int $chr Character (byte) to check.
740 * @param int $mode Current encoding mode.
741 * @return boolean true if the char is of the selected mode.
742 * @protected
743 */
744 protected function isCharMode($chr, $mode)
745 {
746 $status = \false;
747 switch ($mode) {
748 case \ENC_ASCII:
749 // ASCII character 0 to 127
750 $status = ($chr >= 0 and $chr <= 127);
751 break;
752 case \ENC_C40:
753 // Upper-case alphanumeric
754 $status = ($chr == 32 or $chr >= 48 and $chr <= 57 or $chr >= 65 and $chr <= 90);
755 break;
756 case \ENC_TXT:
757 // Lower-case alphanumeric
758 $status = ($chr == 32 or $chr >= 48 and $chr <= 57 or $chr >= 97 and $chr <= 122);
759 break;
760 case \ENC_X12:
761 // ANSI X12
762 $status = ($chr == 13 or $chr == 42 or $chr == 62);
763 break;
764 case \ENC_EDF:
765 // ASCII character 32 to 94
766 $status = ($chr >= 32 and $chr <= 94);
767 break;
768 case \ENC_BASE256:
769 // Function character (FNC1, Structured Append, Reader Program, or Code Page)
770 $status = ($chr == 232 or $chr == 233 or $chr == 234 or $chr == 241);
771 break;
772 case \ENC_ASCII_EXT:
773 // ASCII character 128 to 255
774 $status = ($chr >= 128 and $chr <= 255);
775 break;
776 case \ENC_ASCII_NUM:
777 // ASCII digits
778 $status = ($chr >= 48 and $chr <= 57);
779 break;
780 }
781 return $status;
782 }
783 /**
784 * The look-ahead test scans the data to be encoded to find the best mode (Annex P - steps from J to S).
785 * @param string $data data to encode
786 * @param int $pos current position
787 * @param int $mode current encoding mode
788 * @return int encoding mode
789 * @protected
790 */
791 protected function lookAheadTest($data, $pos, $mode)
792 {
793 $data_length = \strlen($data);
794 if ($pos >= $data_length) {
795 return $mode;
796 }
797 $charscount = 0;
798 // count processed chars
799 // STEP J
800 if ($mode == \ENC_ASCII) {
801 $numch = array(0, 1, 1, 1, 1, 1.25);
802 } else {
803 $numch = array(1, 2, 2, 2, 2, 2.25);
804 $numch[$mode] = 0;
805 }
806 while (\true) {
807 // STEP K
808 if ($pos + $charscount == $data_length) {
809 if ($numch[\ENC_ASCII] <= \ceil(\min($numch[\ENC_C40], $numch[\ENC_TXT], $numch[\ENC_X12], $numch[\ENC_EDF], $numch[\ENC_BASE256]))) {
810 return \ENC_ASCII;
811 }
812 if ($numch[\ENC_BASE256] < \ceil(\min($numch[\ENC_ASCII], $numch[\ENC_C40], $numch[\ENC_TXT], $numch[\ENC_X12], $numch[\ENC_EDF]))) {
813 return \ENC_BASE256;
814 }
815 if ($numch[\ENC_EDF] < \ceil(\min($numch[\ENC_ASCII], $numch[\ENC_C40], $numch[\ENC_TXT], $numch[\ENC_X12], $numch[\ENC_BASE256]))) {
816 return \ENC_EDF;
817 }
818 if ($numch[\ENC_TXT] < \ceil(\min($numch[\ENC_ASCII], $numch[\ENC_C40], $numch[\ENC_X12], $numch[\ENC_EDF], $numch[\ENC_BASE256]))) {
819 return \ENC_TXT;
820 }
821 if ($numch[\ENC_X12] < \ceil(\min($numch[\ENC_ASCII], $numch[\ENC_C40], $numch[\ENC_TXT], $numch[\ENC_EDF], $numch[\ENC_BASE256]))) {
822 return \ENC_X12;
823 }
824 return \ENC_C40;
825 }
826 // get char
827 $chr = \ord($data[$pos + $charscount]);
828 $charscount++;
829 // STEP L
830 if ($this->isCharMode($chr, \ENC_ASCII_NUM)) {
831 $numch[\ENC_ASCII] += 1 / 2;
832 } elseif ($this->isCharMode($chr, \ENC_ASCII_EXT)) {
833 $numch[\ENC_ASCII] = \ceil($numch[\ENC_ASCII]);
834 $numch[\ENC_ASCII] += 2;
835 } else {
836 $numch[\ENC_ASCII] = \ceil($numch[\ENC_ASCII]);
837 $numch[\ENC_ASCII] += 1;
838 }
839 // STEP M
840 if ($this->isCharMode($chr, \ENC_C40)) {
841 $numch[\ENC_C40] += 2 / 3;
842 } elseif ($this->isCharMode($chr, \ENC_ASCII_EXT)) {
843 $numch[\ENC_C40] += 8 / 3;
844 } else {
845 $numch[\ENC_C40] += 4 / 3;
846 }
847 // STEP N
848 if ($this->isCharMode($chr, \ENC_TXT)) {
849 $numch[\ENC_TXT] += 2 / 3;
850 } elseif ($this->isCharMode($chr, \ENC_ASCII_EXT)) {
851 $numch[\ENC_TXT] += 8 / 3;
852 } else {
853 $numch[\ENC_TXT] += 4 / 3;
854 }
855 // STEP O
856 if ($this->isCharMode($chr, \ENC_X12) or $this->isCharMode($chr, \ENC_C40)) {
857 $numch[\ENC_X12] += 2 / 3;
858 } elseif ($this->isCharMode($chr, \ENC_ASCII_EXT)) {
859 $numch[\ENC_X12] += 13 / 3;
860 } else {
861 $numch[\ENC_X12] += 10 / 3;
862 }
863 // STEP P
864 if ($this->isCharMode($chr, \ENC_EDF)) {
865 $numch[\ENC_EDF] += 3 / 4;
866 } elseif ($this->isCharMode($chr, \ENC_ASCII_EXT)) {
867 $numch[\ENC_EDF] += 17 / 4;
868 } else {
869 $numch[\ENC_EDF] += 13 / 4;
870 }
871 // STEP Q
872 if ($this->isCharMode($chr, \ENC_BASE256)) {
873 $numch[\ENC_BASE256] += 4;
874 } else {
875 $numch[\ENC_BASE256] += 1;
876 }
877 // STEP R
878 if ($charscount >= 4) {
879 if ($numch[\ENC_ASCII] + 1 <= \min($numch[\ENC_C40], $numch[\ENC_TXT], $numch[\ENC_X12], $numch[\ENC_EDF], $numch[\ENC_BASE256])) {
880 return \ENC_ASCII;
881 }
882 if ($numch[\ENC_BASE256] + 1 <= $numch[\ENC_ASCII] or $numch[\ENC_BASE256] + 1 < \min($numch[\ENC_C40], $numch[\ENC_TXT], $numch[\ENC_X12], $numch[\ENC_EDF])) {
883 return \ENC_BASE256;
884 }
885 if ($numch[\ENC_EDF] + 1 < \min($numch[\ENC_ASCII], $numch[\ENC_C40], $numch[\ENC_TXT], $numch[\ENC_X12], $numch[\ENC_BASE256])) {
886 return \ENC_EDF;
887 }
888 if ($numch[\ENC_TXT] + 1 < \min($numch[\ENC_ASCII], $numch[\ENC_C40], $numch[\ENC_X12], $numch[\ENC_EDF], $numch[\ENC_BASE256])) {
889 return \ENC_TXT;
890 }
891 if ($numch[\ENC_X12] + 1 < \min($numch[\ENC_ASCII], $numch[\ENC_C40], $numch[\ENC_TXT], $numch[\ENC_EDF], $numch[\ENC_BASE256])) {
892 return \ENC_X12;
893 }
894 if ($numch[\ENC_C40] + 1 < \min($numch[\ENC_ASCII], $numch[\ENC_TXT], $numch[\ENC_EDF], $numch[\ENC_BASE256])) {
895 if ($numch[\ENC_C40] < $numch[\ENC_X12]) {
896 return \ENC_C40;
897 }
898 if ($numch[\ENC_C40] == $numch[\ENC_X12]) {
899 $k = $pos + $charscount + 1;
900 while ($k < $data_length) {
901 $tmpchr = \ord($data[$k]);
902 if ($this->isCharMode($tmpchr, \ENC_X12)) {
903 return \ENC_X12;
904 } elseif (!($this->isCharMode($tmpchr, \ENC_X12) or $this->isCharMode($tmpchr, \ENC_C40))) {
905 break;
906 }
907 ++$k;
908 }
909 return \ENC_C40;
910 }
911 }
912 }
913 }
914 // end of while
915 }
916 /**
917 * Get the switching codeword to a new encoding mode (latch codeword)
918 * @param int $mode New encoding mode.
919 * @return int Switch codeword.
920 * @protected
921 */
922 protected function getSwitchEncodingCodeword($mode)
923 {
924 switch ($mode) {
925 case \ENC_ASCII:
926 // ASCII character 0 to 127
927 $cw = 254;
928 if ($this->last_enc == \ENC_EDF) {
929 $cw = 124;
930 }
931 break;
932 case \ENC_C40:
933 // Upper-case alphanumeric
934 $cw = 230;
935 break;
936 case \ENC_TXT:
937 // Lower-case alphanumeric
938 $cw = 239;
939 break;
940 case \ENC_X12:
941 // ANSI X12
942 $cw = 238;
943 break;
944 case \ENC_EDF:
945 // ASCII character 32 to 94
946 $cw = 240;
947 break;
948 case \ENC_BASE256:
949 // Function character (FNC1, Structured Append, Reader Program, or Code Page)
950 $cw = 231;
951 break;
952 }
953 return $cw;
954 }
955 /**
956 * Choose the minimum matrix size and return the max number of data codewords.
957 * @param int $numcw Number of current codewords.
958 * @return int number of data codewords in matrix
959 * @protected
960 */
961 protected function getMaxDataCodewords($numcw)
962 {
963 foreach ($this->symbattr as $key => $matrix) {
964 if ($matrix[11] >= $numcw) {
965 return $matrix[11];
966 }
967 }
968 return 0;
969 }
970 /**
971 * Get high level encoding using the minimum symbol data characters for ECC 200
972 * @param string $data data to encode
973 * @return array of codewords
974 * @protected
975 */
976 protected function getHighLevelEncoding($data)
977 {
978 // STEP A. Start in ASCII encodation.
979 $enc = \ENC_ASCII;
980 // current encoding mode
981 $pos = 0;
982 // current position
983 $cw = array();
984 // array of codewords to be returned
985 $cw_num = 0;
986 // number of data codewords
987 $data_length = \strlen($data);
988 // number of chars
989 while ($pos < $data_length) {
990 // set last used encoding
991 $this->last_enc = $enc;
992 switch ($enc) {
993 case \ENC_ASCII:
994 // STEP B. While in ASCII encodation
995 if ($data_length > 1 and $pos < $data_length - 1 and ($this->isCharMode(\ord($data[$pos]), \ENC_ASCII_NUM) and $this->isCharMode(\ord($data[$pos + 1]), \ENC_ASCII_NUM))) {
996 // 1. If the next data sequence is at least 2 consecutive digits, encode the next two digits as a double digit in ASCII mode.
997 $cw[] = \intval(\substr($data, $pos, 2)) + 130;
998 ++$cw_num;
999 $pos += 2;
1000 } else {
1001 // 2. If the look-ahead test (starting at step J) indicates another mode, switch to that mode.
1002 $newenc = $this->lookAheadTest($data, $pos, $enc);
1003 if ($newenc != $enc) {
1004 // switch to new encoding
1005 $enc = $newenc;
1006 $cw[] = $this->getSwitchEncodingCodeword($enc);
1007 ++$cw_num;
1008 } else {
1009 // get new byte
1010 $chr = \ord($data[$pos]);
1011 ++$pos;
1012 if ($this->isCharMode($chr, \ENC_ASCII_EXT)) {
1013 // 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.
1014 $cw[] = 235;
1015 $cw[] = $chr - 127;
1016 $cw_num += 2;
1017 } else {
1018 // 4. Otherwise process the next data character in ASCII encodation.
1019 $cw[] = $chr + 1;
1020 ++$cw_num;
1021 }
1022 }
1023 }
1024 break;
1025 case \ENC_C40:
1026 // Upper-case alphanumeric
1027 case \ENC_TXT:
1028 // Lower-case alphanumeric
1029 case \ENC_X12:
1030 // ANSI X12
1031 $temp_cw = array();
1032 $p = 0;
1033 $epos = $pos;
1034 // get charset ID
1035 $set_id = $this->chset_id[$enc];
1036 // get basic charset for current encoding
1037 $charset = $this->chset[$set_id];
1038 do {
1039 // 2. process the next character in C40 encodation.
1040 $chr = \ord($data[$epos]);
1041 ++$epos;
1042 // check for extended character
1043 if ($chr & 0x80) {
1044 if ($enc == \ENC_X12) {
1045 return \false;
1046 }
1047 $chr = $chr & 0x7f;
1048 $temp_cw[] = 1;
1049 // shift 2
1050 $temp_cw[] = 30;
1051 // upper shift
1052 $p += 2;
1053 }
1054 if (isset($charset[$chr])) {
1055 $temp_cw[] = $charset[$chr];
1056 ++$p;
1057 } else {
1058 if (isset($this->chset['SH1'][$chr])) {
1059 $temp_cw[] = 0;
1060 // shift 1
1061 $shiftset = $this->chset['SH1'];
1062 } elseif (isset($this->chset['SH2'][$chr])) {
1063 $temp_cw[] = 1;
1064 // shift 2
1065 $shiftset = $this->chset['SH2'];
1066 } elseif ($enc == \ENC_C40 and isset($this->chset['S3C'][$chr])) {
1067 $temp_cw[] = 2;
1068 // shift 3
1069 $shiftset = $this->chset['S3C'];
1070 } elseif ($enc == \ENC_TXT and isset($this->chset['S3T'][$chr])) {
1071 $temp_cw[] = 2;
1072 // shift 3
1073 $shiftset = $this->chset['S3T'];
1074 } else {
1075 return \false;
1076 }
1077 $temp_cw[] = $shiftset[$chr];
1078 $p += 2;
1079 }
1080 if ($p >= 3) {
1081 $c1 = \array_shift($temp_cw);
1082 $c2 = \array_shift($temp_cw);
1083 $c3 = \array_shift($temp_cw);
1084 $p -= 3;
1085 $tmp = 1600 * $c1 + 40 * $c2 + $c3 + 1;
1086 $cw[] = $tmp >> 8;
1087 $cw[] = $tmp % 256;
1088 $cw_num += 2;
1089 $pos = $epos;
1090 // 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.
1091 $newenc = $this->lookAheadTest($data, $pos, $enc);
1092 if ($newenc != $enc) {
1093 // switch to new encoding
1094 $enc = $newenc;
1095 if ($enc != \ENC_ASCII) {
1096 // set unlatch character
1097 $cw[] = $this->getSwitchEncodingCodeword(\ENC_ASCII);
1098 ++$cw_num;
1099 }
1100 $cw[] = $this->getSwitchEncodingCodeword($enc);
1101 ++$cw_num;
1102 $pos -= $p;
1103 $p = 0;
1104 break;
1105 }
1106 }
1107 } while ($p > 0 and $epos < $data_length);
1108 // process last data (if any)
1109 if ($p > 0) {
1110 // get remaining number of data symbols
1111 $cwr = $this->getMaxDataCodewords($cw_num) - $cw_num;
1112 if ($cwr == 1 and $p == 1) {
1113 // d. If one symbol character remains and one C40 value (data character) remains to be encoded
1114 $c1 = \array_shift($temp_cw);
1115 --$p;
1116 $cw[] = $chr + 1;
1117 ++$cw_num;
1118 $pos = $epos;
1119 $enc = \ENC_ASCII;
1120 $this->last_enc = $enc;
1121 } elseif ($cwr == 2 and $p == 1) {
1122 // c. If two symbol characters remain and only one C40 value (data character) remains to be encoded
1123 $c1 = \array_shift($temp_cw);
1124 --$p;
1125 $cw[] = 254;
1126 $cw[] = $chr + 1;
1127 $cw_num += 2;
1128 $pos = $epos;
1129 $enc = \ENC_ASCII;
1130 $this->last_enc = $enc;
1131 } elseif ($cwr == 2 and $p == 2) {
1132 // b. If two symbol characters remain and two C40 values remain to be encoded
1133 $c1 = \array_shift($temp_cw);
1134 $c2 = \array_shift($temp_cw);
1135 $p -= 2;
1136 $tmp = 1600 * $c1 + 40 * $c2 + 1;
1137 $cw[] = $tmp >> 8;
1138 $cw[] = $tmp % 256;
1139 $cw_num += 2;
1140 $pos = $epos;
1141 $enc = \ENC_ASCII;
1142 $this->last_enc = $enc;
1143 } else {
1144 // switch to ASCII encoding
1145 if ($enc != \ENC_ASCII) {
1146 $enc = \ENC_ASCII;
1147 $this->last_enc = $enc;
1148 $cw[] = $this->getSwitchEncodingCodeword($enc);
1149 ++$cw_num;
1150 $pos = $epos - $p;
1151 }
1152 }
1153 }
1154 break;
1155 case \ENC_EDF:
1156 // F. While in EDIFACT (EDF) encodation
1157 // initialize temporary array with 0 length
1158 $temp_cw = array();
1159 $epos = $pos;
1160 $field_length = 0;
1161 $newenc = $enc;
1162 do {
1163 // 2. process the next character in EDIFACT encodation.
1164 $chr = \ord($data[$epos]);
1165 if ($this->isCharMode($chr, \ENC_EDF)) {
1166 ++$epos;
1167 $temp_cw[] = $chr;
1168 ++$field_length;
1169 }
1170 if ($field_length == 4 or $epos == $data_length or !$this->isCharMode($chr, \ENC_EDF)) {
1171 if ($epos == $data_length and $field_length < 3) {
1172 $enc = \ENC_ASCII;
1173 $cw[] = $this->getSwitchEncodingCodeword($enc);
1174 ++$cw_num;
1175 break;
1176 }
1177 if ($field_length < 4) {
1178 // set unlatch character
1179 $temp_cw[] = 0x1f;
1180 ++$field_length;
1181 // fill empty characters
1182 for ($i = $field_length; $i < 4; ++$i) {
1183 $temp_cw[] = 0;
1184 }
1185 $enc = \ENC_ASCII;
1186 $this->last_enc = $enc;
1187 }
1188 // encodes four data characters in three codewords
1189 $tcw = (($temp_cw[0] & 0x3f) << 2) + (($temp_cw[1] & 0x30) >> 4);
1190 if ($tcw > 0) {
1191 $cw[] = $tcw;
1192 $cw_num++;
1193 }
1194 $tcw = (($temp_cw[1] & 0xf) << 4) + (($temp_cw[2] & 0x3c) >> 2);
1195 if ($tcw > 0) {
1196 $cw[] = $tcw;
1197 $cw_num++;
1198 }
1199 $tcw = (($temp_cw[2] & 0x3) << 6) + ($temp_cw[3] & 0x3f);
1200 if ($tcw > 0) {
1201 $cw[] = $tcw;
1202 $cw_num++;
1203 }
1204 $temp_cw = array();
1205 $pos = $epos;
1206 $field_length = 0;
1207 if ($enc == \ENC_ASCII) {
1208 break;
1209 // exit from EDIFACT mode
1210 }
1211 }
1212 } while ($epos < $data_length);
1213 break;
1214 case \ENC_BASE256:
1215 // G. While in Base 256 (B256) encodation
1216 // initialize temporary array with 0 length
1217 $temp_cw = array();
1218 $field_length = 0;
1219 while ($pos < $data_length and $field_length <= 1555) {
1220 $newenc = $this->lookAheadTest($data, $pos, $enc);
1221 if ($newenc != $enc) {
1222 // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode.
1223 $enc = $newenc;
1224 break;
1225 // exit from B256 mode
1226 } else {
1227 // 2. Otherwise, process the next character in Base 256 encodation.
1228 $chr = \ord($data[$pos]);
1229 ++$pos;
1230 $temp_cw[] = $chr;
1231 ++$field_length;
1232 }
1233 }
1234 // set field length
1235 if ($field_length <= 249) {
1236 $cw[] = $this->get255StateCodeword($field_length, $cw_num + 1);
1237 ++$cw_num;
1238 } else {
1239 $cw[] = $this->get255StateCodeword(\floor($field_length / 250) + 249, $cw_num + 1);
1240 $cw[] = $this->get255StateCodeword($field_length % 250, $cw_num + 2);
1241 $cw_num += 2;
1242 }
1243 if (!empty($temp_cw)) {
1244 // add B256 field
1245 foreach ($temp_cw as $p => $cht) {
1246 $cw[] = $this->get255StateCodeword($cht, $cw_num + $p + 1);
1247 }
1248 }
1249 break;
1250 }
1251 // end of switch enc
1252 }
1253 // end of while
1254 return $cw;
1255 }
1256 /**
1257 * Places "chr+bit" with appropriate wrapping within array[].
1258 * (Annex F - ECC 200 symbol character placement)
1259 * @param array $marr Array of symbols.
1260 * @param int $nrow Number of rows.
1261 * @param int $ncol Number of columns.
1262 * @param int $row Row number.
1263 * @param int $col Column number.
1264 * @param int $chr Char byte.
1265 * @param int $bit Bit.
1266 * @return array
1267 * @protected
1268 */
1269 protected function placeModule($marr, $nrow, $ncol, $row, $col, $chr, $bit)
1270 {
1271 if ($row < 0) {
1272 $row += $nrow;
1273 $col += 4 - ($nrow + 4) % 8;
1274 }
1275 if ($col < 0) {
1276 $col += $ncol;
1277 $row += 4 - ($ncol + 4) % 8;
1278 }
1279 $marr[$row * $ncol + $col] = 10 * $chr + $bit;
1280 return $marr;
1281 }
1282 /**
1283 * Places the 8 bits of a utah-shaped symbol character.
1284 * (Annex F - ECC 200 symbol character placement)
1285 * @param array $marr Array of symbols.
1286 * @param int $nrow Number of rows.
1287 * @param int $ncol Number of columns.
1288 * @param int $row Row number.
1289 * @param int $col Column number.
1290 * @param int $chr Char byte.
1291 * @return array
1292 * @protected
1293 */
1294 protected function placeUtah($marr, $nrow, $ncol, $row, $col, $chr)
1295 {
1296 $marr = $this->placeModule($marr, $nrow, $ncol, $row - 2, $col - 2, $chr, 1);
1297 $marr = $this->placeModule($marr, $nrow, $ncol, $row - 2, $col - 1, $chr, 2);
1298 $marr = $this->placeModule($marr, $nrow, $ncol, $row - 1, $col - 2, $chr, 3);
1299 $marr = $this->placeModule($marr, $nrow, $ncol, $row - 1, $col - 1, $chr, 4);
1300 $marr = $this->placeModule($marr, $nrow, $ncol, $row - 1, $col, $chr, 5);
1301 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col - 2, $chr, 6);
1302 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col - 1, $chr, 7);
1303 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col, $chr, 8);
1304 return $marr;
1305 }
1306 /**
1307 * Places the 8 bits of the first special corner case.
1308 * (Annex F - ECC 200 symbol character placement)
1309 * @param array $marr Array of symbols.
1310 * @param int $nrow Number of rows.
1311 * @param int $ncol Number of columns.
1312 * @param int $chr Char byte.
1313 * @return array
1314 * @protected
1315 */
1316 protected function placeCornerA($marr, $nrow, $ncol, $chr)
1317 {
1318 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 1, 0, $chr, 1);
1319 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 1, 1, $chr, 2);
1320 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 1, 2, $chr, 3);
1321 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 2, $chr, 4);
1322 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 1, $chr, 5);
1323 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol - 1, $chr, 6);
1324 $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol - 1, $chr, 7);
1325 $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol - 1, $chr, 8);
1326 return $marr;
1327 }
1328 /**
1329 * Places the 8 bits of the second special corner case.
1330 * (Annex F - ECC 200 symbol character placement)
1331 * @param array $marr Array of symbols.
1332 * @param int $nrow Number of rows.
1333 * @param int $ncol Number of columns.
1334 * @param int $chr Char byte.
1335 * @return array
1336 * @protected
1337 */
1338 protected function placeCornerB($marr, $nrow, $ncol, $chr)
1339 {
1340 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 3, 0, $chr, 1);
1341 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 2, 0, $chr, 2);
1342 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 1, 0, $chr, 3);
1343 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 4, $chr, 4);
1344 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 3, $chr, 5);
1345 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 2, $chr, 6);
1346 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 1, $chr, 7);
1347 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol - 1, $chr, 8);
1348 return $marr;
1349 }
1350 /**
1351 * Places the 8 bits of the third special corner case.
1352 * (Annex F - ECC 200 symbol character placement)
1353 * @param array $marr Array of symbols.
1354 * @param int $nrow Number of rows.
1355 * @param int $ncol Number of columns.
1356 * @param int $chr Char byte.
1357 * @return array
1358 * @protected
1359 */
1360 protected function placeCornerC($marr, $nrow, $ncol, $chr)
1361 {
1362 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 3, 0, $chr, 1);
1363 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 2, 0, $chr, 2);
1364 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 1, 0, $chr, 3);
1365 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 2, $chr, 4);
1366 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 1, $chr, 5);
1367 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol - 1, $chr, 6);
1368 $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol - 1, $chr, 7);
1369 $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol - 1, $chr, 8);
1370 return $marr;
1371 }
1372 /**
1373 * Places the 8 bits of the fourth special corner case.
1374 * (Annex F - ECC 200 symbol character placement)
1375 * @param array $marr Array of symbols.
1376 * @param int $nrow Number of rows.
1377 * @param int $ncol Number of columns.
1378 * @param int $chr Char byte.
1379 * @return array
1380 * @protected
1381 */
1382 protected function placeCornerD($marr, $nrow, $ncol, $chr)
1383 {
1384 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 1, 0, $chr, 1);
1385 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow - 1, $ncol - 1, $chr, 2);
1386 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 3, $chr, 3);
1387 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 2, $chr, 4);
1388 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol - 1, $chr, 5);
1389 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol - 3, $chr, 6);
1390 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol - 2, $chr, 7);
1391 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol - 1, $chr, 8);
1392 return $marr;
1393 }
1394 /**
1395 * Build a placement map.
1396 * (Annex F - ECC 200 symbol character placement)
1397 * @param int $nrow Number of rows.
1398 * @param int $ncol Number of columns.
1399 * @return array
1400 * @protected
1401 */
1402 protected function getPlacementMap($nrow, $ncol)
1403 {
1404 // initialize array with zeros
1405 $marr = \array_fill(0, $nrow * $ncol, 0);
1406 // set starting values
1407 $chr = 1;
1408 $row = 4;
1409 $col = 0;
1410 do {
1411 // repeatedly first check for one of the special corner cases, then
1412 if ($row == $nrow and $col == 0) {
1413 $marr = $this->placeCornerA($marr, $nrow, $ncol, $chr);
1414 ++$chr;
1415 }
1416 if ($row == $nrow - 2 and $col == 0 and $ncol % 4) {
1417 $marr = $this->placeCornerB($marr, $nrow, $ncol, $chr);
1418 ++$chr;
1419 }
1420 if ($row == $nrow - 2 and $col == 0 and $ncol % 8 == 4) {
1421 $marr = $this->placeCornerC($marr, $nrow, $ncol, $chr);
1422 ++$chr;
1423 }
1424 if ($row == $nrow + 4 and $col == 2 and !($ncol % 8)) {
1425 $marr = $this->placeCornerD($marr, $nrow, $ncol, $chr);
1426 ++$chr;
1427 }
1428 // sweep upward diagonally, inserting successive characters,
1429 do {
1430 if ($row < $nrow and $col >= 0 and !$marr[$row * $ncol + $col]) {
1431 $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr);
1432 ++$chr;
1433 }
1434 $row -= 2;
1435 $col += 2;
1436 } while ($row >= 0 and $col < $ncol);
1437 ++$row;
1438 $col += 3;
1439 // & then sweep downward diagonally, inserting successive characters,...
1440 do {
1441 if ($row >= 0 and $col < $ncol and !$marr[$row * $ncol + $col]) {
1442 $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr);
1443 ++$chr;
1444 }
1445 $row += 2;
1446 $col -= 2;
1447 } while ($row < $nrow and $col >= 0);
1448 $row += 3;
1449 ++$col;
1450 // ... until the entire array is scanned
1451 } while ($row < $nrow or $col < $ncol);
1452 // lastly, if the lower righthand corner is untouched, fill in fixed pattern
1453 if (!$marr[$nrow * $ncol - 1]) {
1454 $marr[$nrow * $ncol - 1] = 1;
1455 $marr[$nrow * $ncol - $ncol - 2] = 1;
1456 }
1457 return $marr;
1458 }
1459 }
1460 // end DataMatrix class
1461 //============================================================+
1462 // END OF FILE
1463 //============================================================+
1464 }
1465