PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 2.2.0
GiveWP – Donation Plugin and Fundraising Platform v2.2.0
4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / libraries / tcpdf / include / barcodes / datamatrix.php
give / includes / libraries / tcpdf / include / barcodes Last commit date
datamatrix.php 8 years ago pdf417.php 7 years ago qrcode.php 8 years ago
datamatrix.php
1177 lines
1 <?php
2 //============================================================+
3 // File name : datamatrix.php
4 // Version : 1.0.008
5 // Begin : 2010-06-07
6 // Last Update : 2014-05-06
7 // Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
8 // License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
9 // -------------------------------------------------------------------
10 // Copyright (C) 2010-2014 Nicola Asuni - Tecnick.com LTD
11 //
12 // This file is part of TCPDF software library.
13 //
14 // TCPDF is free software: you can redistribute it and/or modify it
15 // under the terms of the GNU Lesser General Public License as
16 // published by the Free Software Foundation, either version 3 of the
17 // License, or (at your option) any later version.
18 //
19 // TCPDF is distributed in the hope that it will be useful, but
20 // WITHOUT ANY WARRANTY; without even the implied warranty of
21 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 // See the GNU Lesser General Public License for more details.
23 //
24 // You should have received a copy of the GNU Lesser General Public License
25 // along with TCPDF. If not, see <http://www.gnu.org/licenses/>.
26 //
27 // See LICENSE.TXT file for more information.
28 // -------------------------------------------------------------------
29 //
30 // DESCRIPTION :
31 //
32 // Class to create DataMatrix ECC 200 barcode arrays for TCPDF class.
33 // DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code.
34 //============================================================+
35
36 /**
37 * @file
38 * Class to create DataMatrix ECC 200 barcode arrays for TCPDF class.
39 * DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code.
40 *
41 * @package com.tecnick.tcpdf
42 * @author Nicola Asuni
43 * @version 1.0.008
44 */
45
46 // custom definitions
47 if (!defined('DATAMATRIXDEFS')) {
48
49 /**
50 * Indicate that definitions for this class are set
51 */
52 define('DATAMATRIXDEFS', true);
53
54 // -----------------------------------------------------
55
56 } // end of custom definitions
57
58 // #*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#
59
60
61 /**
62 * ASCII encoding: ASCII character 0 to 127 (1 byte per CW)
63 */
64 define('ENC_ASCII', 0);
65
66 /**
67 * C40 encoding: Upper-case alphanumeric (3/2 bytes per CW)
68 */
69 define('ENC_C40', 1);
70
71 /**
72 * TEXT encoding: Lower-case alphanumeric (3/2 bytes per CW)
73 */
74 define('ENC_TXT', 2);
75
76 /**
77 * X12 encoding: ANSI X12 (3/2 byte per CW)
78 */
79 define('ENC_X12', 3);
80
81 /**
82 * EDIFACT encoding: ASCII character 32 to 94 (4/3 bytes per CW)
83 */
84 define('ENC_EDF', 4);
85
86 /**
87 * BASE 256 encoding: ASCII character 0 to 255 (1 byte per CW)
88 */
89 define('ENC_BASE256', 5);
90
91 /**
92 * ASCII extended encoding: ASCII character 128 to 255 (1/2 byte per CW)
93 */
94 define('ENC_ASCII_EXT', 6);
95
96 /**
97 * ASCII number encoding: ASCII digits (2 bytes per CW)
98 */
99 define('ENC_ASCII_NUM', 7);
100
101 /**
102 * @class Datamatrix
103 * Class to create DataMatrix ECC 200 barcode arrays for TCPDF class.
104 * DataMatrix (ISO/IEC 16022:2006) is a 2-dimensional bar code.
105 *
106 * @package com.tecnick.tcpdf
107 * @author Nicola Asuni
108 * @version 1.0.004
109 */
110 class Datamatrix {
111
112 /**
113 * Barcode array to be returned which is readable by TCPDF.
114 * @protected
115 */
116 protected $barcode_array = array();
117
118 /**
119 * Store last used encoding for data codewords.
120 * @protected
121 */
122 protected $last_enc = ENC_ASCII;
123
124 /**
125 * Table of Data Matrix ECC 200 Symbol Attributes:<ul>
126 * <li>total matrix rows (including finder pattern)</li>
127 * <li>total matrix cols (including finder pattern)</li>
128 * <li>total matrix rows (without finder pattern)</li>
129 * <li>total matrix cols (without finder pattern)</li>
130 * <li>region data rows (with finder pattern)</li>
131 * <li>region data col (with finder pattern)</li>
132 * <li>region data rows (without finder pattern)</li>
133 * <li>region data col (without finder pattern)</li>
134 * <li>horizontal regions</li>
135 * <li>vertical regions</li>
136 * <li>regions</li>
137 * <li>data codewords</li>
138 * <li>error codewords</li>
139 * <li>blocks</li>
140 * <li>data codewords per block</li>
141 * <li>error codewords per block</li>
142 * </ul>
143 * @protected
144 */
145 protected $symbattr = array(
146 // square form ---------------------------------------------------------------------------------------
147 array(0x00a,0x00a,0x008,0x008,0x00a,0x00a,0x008,0x008,0x001,0x001,0x001,0x003,0x005,0x001,0x003,0x005), // 10x10
148 array(0x00c,0x00c,0x00a,0x00a,0x00c,0x00c,0x00a,0x00a,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 12x12
149 array(0x00e,0x00e,0x00c,0x00c,0x00e,0x00e,0x00c,0x00c,0x001,0x001,0x001,0x008,0x00a,0x001,0x008,0x00a), // 14x14
150 array(0x010,0x010,0x00e,0x00e,0x010,0x010,0x00e,0x00e,0x001,0x001,0x001,0x00c,0x00c,0x001,0x00c,0x00c), // 16x16
151 array(0x012,0x012,0x010,0x010,0x012,0x012,0x010,0x010,0x001,0x001,0x001,0x012,0x00e,0x001,0x012,0x00e), // 18x18
152 array(0x014,0x014,0x012,0x012,0x014,0x014,0x012,0x012,0x001,0x001,0x001,0x016,0x012,0x001,0x016,0x012), // 20x20
153 array(0x016,0x016,0x014,0x014,0x016,0x016,0x014,0x014,0x001,0x001,0x001,0x01e,0x014,0x001,0x01e,0x014), // 22x22
154 array(0x018,0x018,0x016,0x016,0x018,0x018,0x016,0x016,0x001,0x001,0x001,0x024,0x018,0x001,0x024,0x018), // 24x24
155 array(0x01a,0x01a,0x018,0x018,0x01a,0x01a,0x018,0x018,0x001,0x001,0x001,0x02c,0x01c,0x001,0x02c,0x01c), // 26x26
156 array(0x020,0x020,0x01c,0x01c,0x010,0x010,0x00e,0x00e,0x002,0x002,0x004,0x03e,0x024,0x001,0x03e,0x024), // 32x32
157 array(0x024,0x024,0x020,0x020,0x012,0x012,0x010,0x010,0x002,0x002,0x004,0x056,0x02a,0x001,0x056,0x02a), // 36x36
158 array(0x028,0x028,0x024,0x024,0x014,0x014,0x012,0x012,0x002,0x002,0x004,0x072,0x030,0x001,0x072,0x030), // 40x40
159 array(0x02c,0x02c,0x028,0x028,0x016,0x016,0x014,0x014,0x002,0x002,0x004,0x090,0x038,0x001,0x090,0x038), // 44x44
160 array(0x030,0x030,0x02c,0x02c,0x018,0x018,0x016,0x016,0x002,0x002,0x004,0x0ae,0x044,0x001,0x0ae,0x044), // 48x48
161 array(0x034,0x034,0x030,0x030,0x01a,0x01a,0x018,0x018,0x002,0x002,0x004,0x0cc,0x054,0x002,0x066,0x02a), // 52x52
162 array(0x040,0x040,0x038,0x038,0x010,0x010,0x00e,0x00e,0x004,0x004,0x010,0x118,0x070,0x002,0x08c,0x038), // 64x64
163 array(0x048,0x048,0x040,0x040,0x012,0x012,0x010,0x010,0x004,0x004,0x010,0x170,0x090,0x004,0x05c,0x024), // 72x72
164 array(0x050,0x050,0x048,0x048,0x014,0x014,0x012,0x012,0x004,0x004,0x010,0x1c8,0x0c0,0x004,0x072,0x030), // 80x80
165 array(0x058,0x058,0x050,0x050,0x016,0x016,0x014,0x014,0x004,0x004,0x010,0x240,0x0e0,0x004,0x090,0x038), // 88x88
166 array(0x060,0x060,0x058,0x058,0x018,0x018,0x016,0x016,0x004,0x004,0x010,0x2b8,0x110,0x004,0x0ae,0x044), // 96x96
167 array(0x068,0x068,0x060,0x060,0x01a,0x01a,0x018,0x018,0x004,0x004,0x010,0x330,0x150,0x006,0x088,0x038), // 104x104
168 array(0x078,0x078,0x06c,0x06c,0x014,0x014,0x012,0x012,0x006,0x006,0x024,0x41a,0x198,0x006,0x0af,0x044), // 120x120
169 array(0x084,0x084,0x078,0x078,0x016,0x016,0x014,0x014,0x006,0x006,0x024,0x518,0x1f0,0x008,0x0a3,0x03e), // 132x132
170 array(0x090,0x090,0x084,0x084,0x018,0x018,0x016,0x016,0x006,0x006,0x024,0x616,0x26c,0x00a,0x09c,0x03e), // 144x144
171 // rectangular form (currently unused) ---------------------------------------------------------------------------
172 array(0x008,0x012,0x006,0x010,0x008,0x012,0x006,0x010,0x001,0x001,0x001,0x005,0x007,0x001,0x005,0x007), // 8x18
173 array(0x008,0x020,0x006,0x01c,0x008,0x010,0x006,0x00e,0x001,0x002,0x002,0x00a,0x00b,0x001,0x00a,0x00b), // 8x32
174 array(0x00c,0x01a,0x00a,0x018,0x00c,0x01a,0x00a,0x018,0x001,0x001,0x001,0x010,0x00e,0x001,0x010,0x00e), // 12x26
175 array(0x00c,0x024,0x00a,0x020,0x00c,0x012,0x00a,0x010,0x001,0x002,0x002,0x00c,0x012,0x001,0x00c,0x012), // 12x36
176 array(0x010,0x024,0x00e,0x020,0x010,0x012,0x00e,0x010,0x001,0x002,0x002,0x020,0x018,0x001,0x020,0x018), // 16x36
177 array(0x010,0x030,0x00e,0x02c,0x010,0x018,0x00e,0x016,0x001,0x002,0x002,0x031,0x01c,0x001,0x031,0x01c) // 16x48
178 );
179
180 /**
181 * Map encodation modes whit character sets.
182 * @protected
183 */
184 protected $chset_id = array(ENC_C40 => 'C40', ENC_TXT => 'TXT', ENC_X12 =>'X12');
185
186 /**
187 * Basic set of characters for each encodation mode.
188 * @protected
189 */
190 protected $chset = array(
191 'C40' => array( // Basic set for C40 ----------------------------------------------------------------------------
192 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, //
193 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, //
194 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, //
195 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27),//
196 'TXT' => array( // Basic set for TEXT ---------------------------------------------------------------------------
197 'S1'=>0x00,'S2'=>0x01,'S3'=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, //
198 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x61=>0x0e,0x62=>0x0f,0x63=>0x10,0x64=>0x11,0x65=>0x12,0x66=>0x13, //
199 0x67=>0x14,0x68=>0x15,0x69=>0x16,0x6a=>0x17,0x6b=>0x18,0x6c=>0x19,0x6d=>0x1a,0x6e=>0x1b,0x6f=>0x1c,0x70=>0x1d, //
200 0x71=>0x1e,0x72=>0x1f,0x73=>0x20,0x74=>0x21,0x75=>0x22,0x76=>0x23,0x77=>0x24,0x78=>0x25,0x79=>0x26,0x7a=>0x27),//
201 'SH1' => array( // Shift 1 set ----------------------------------------------------------------------------------
202 0x00=>0x00,0x01=>0x01,0x02=>0x02,0x03=>0x03,0x04=>0x04,0x05=>0x05,0x06=>0x06,0x07=>0x07,0x08=>0x08,0x09=>0x09, //
203 0x0a=>0x0a,0x0b=>0x0b,0x0c=>0x0c,0x0d=>0x0d,0x0e=>0x0e,0x0f=>0x0f,0x10=>0x10,0x11=>0x11,0x12=>0x12,0x13=>0x13, //
204 0x14=>0x14,0x15=>0x15,0x16=>0x16,0x17=>0x17,0x18=>0x18,0x19=>0x19,0x1a=>0x1a,0x1b=>0x1b,0x1c=>0x1c,0x1d=>0x1d, //
205 0x1e=>0x1e,0x1f=>0x1f), //
206 'SH2' => array( // Shift 2 set ----------------------------------------------------------------------------------
207 0x21=>0x00,0x22=>0x01,0x23=>0x02,0x24=>0x03,0x25=>0x04,0x26=>0x05,0x27=>0x06,0x28=>0x07,0x29=>0x08,0x2a=>0x09, //
208 0x2b=>0x0a,0x2c=>0x0b,0x2d=>0x0c,0x2e=>0x0d,0x2f=>0x0e,0x3a=>0x0f,0x3b=>0x10,0x3c=>0x11,0x3d=>0x12,0x3e=>0x13, //
209 0x3f=>0x14,0x40=>0x15,0x5b=>0x16,0x5c=>0x17,0x5d=>0x18,0x5e=>0x19,0x5f=>0x1a,'F1'=>0x1b,'US'=>0x1e), //
210 'S3C' => array( // Shift 3 set for C40 --------------------------------------------------------------------------
211 0x60=>0x00,0x61=>0x01,0x62=>0x02,0x63=>0x03,0x64=>0x04,0x65=>0x05,0x66=>0x06,0x67=>0x07,0x68=>0x08,0x69=>0x09, //
212 0x6a=>0x0a,0x6b=>0x0b,0x6c=>0x0c,0x6d=>0x0d,0x6e=>0x0e,0x6f=>0x0f,0x70=>0x10,0x71=>0x11,0x72=>0x12,0x73=>0x13, //
213 0x74=>0x14,0x75=>0x15,0x76=>0x16,0x77=>0x17,0x78=>0x18,0x79=>0x19,0x7a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, //
214 0x7e=>0x1e,0x7f=>0x1f),
215 'S3T' => array( // Shift 3 set for TEXT -------------------------------------------------------------------------
216 0x60=>0x00,0x41=>0x01,0x42=>0x02,0x43=>0x03,0x44=>0x04,0x45=>0x05,0x46=>0x06,0x47=>0x07,0x48=>0x08,0x49=>0x09, //
217 0x4a=>0x0a,0x4b=>0x0b,0x4c=>0x0c,0x4d=>0x0d,0x4e=>0x0e,0x4f=>0x0f,0x50=>0x10,0x51=>0x11,0x52=>0x12,0x53=>0x13, //
218 0x54=>0x14,0x55=>0x15,0x56=>0x16,0x57=>0x17,0x58=>0x18,0x59=>0x19,0x5a=>0x1a,0x7b=>0x1b,0x7c=>0x1c,0x7d=>0x1d, //
219 0x7e=>0x1e,0x7f=>0x1f), //
220 'X12' => array( // Set for X12 ----------------------------------------------------------------------------------
221 0x0d=>0x00,0x2a=>0x01,0x3e=>0x02,0x20=>0x03,0x30=>0x04,0x31=>0x05,0x32=>0x06,0x33=>0x07,0x34=>0x08,0x35=>0x09, //
222 0x36=>0x0a,0x37=>0x0b,0x38=>0x0c,0x39=>0x0d,0x41=>0x0e,0x42=>0x0f,0x43=>0x10,0x44=>0x11,0x45=>0x12,0x46=>0x13, //
223 0x47=>0x14,0x48=>0x15,0x49=>0x16,0x4a=>0x17,0x4b=>0x18,0x4c=>0x19,0x4d=>0x1a,0x4e=>0x1b,0x4f=>0x1c,0x50=>0x1d, //
224 0x51=>0x1e,0x52=>0x1f,0x53=>0x20,0x54=>0x21,0x55=>0x22,0x56=>0x23,0x57=>0x24,0x58=>0x25,0x59=>0x26,0x5a=>0x27) //
225 );
226
227 // -----------------------------------------------------------------------------
228
229 /**
230 * This is the class constructor.
231 * Creates a datamatrix object
232 * @param $code (string) Code to represent using Datamatrix.
233 * @public
234 */
235 public function __construct($code) {
236 $barcode_array = array();
237 if ((is_null($code)) OR ($code == '\0') OR ($code == '')) {
238 return false;
239 }
240 // get data codewords
241 $cw = $this->getHighLevelEncoding($code);
242 // number of data codewords
243 $nd = count($cw);
244 // check size
245 if ($nd > 1558) {
246 return false;
247 }
248 // get minimum required matrix size.
249 foreach ($this->symbattr as $params) {
250 if ($params[11] >= $nd) {
251 break;
252 }
253 }
254 if ($params[11] < $nd) {
255 // too much data
256 return false;
257 } elseif ($params[11] > $nd) {
258 // add padding
259 if ((($params[11] - $nd) > 1) AND ($cw[($nd - 1)] != 254)) {
260 if ($this->last_enc == ENC_EDF) {
261 // switch to ASCII encoding
262 $cw[] = 124;
263 ++$nd;
264 } elseif (($this->last_enc != ENC_ASCII) AND ($this->last_enc != ENC_BASE256)) {
265 // switch to ASCII encoding
266 $cw[] = 254;
267 ++$nd;
268 }
269 }
270 if ($params[11] > $nd) {
271 // add first pad
272 $cw[] = 129;
273 ++$nd;
274 // add remaining pads
275 for ($i = $nd; $i < $params[11]; ++$i) {
276 $cw[] = $this->get253StateCodeword(129, $i);
277 }
278 }
279 }
280 // add error correction codewords
281 $cw = $this->getErrorCorrection($cw, $params[13], $params[14], $params[15]);
282 // initialize empty arrays
283 $grid = array_fill(0, ($params[2] * $params[3]), 0);
284 // get placement map
285 $places = $this->getPlacementMap($params[2], $params[3]);
286 // fill the grid with data
287 $grid = array();
288 $i = 0;
289 // region data row max index
290 $rdri = ($params[4] - 1);
291 // region data column max index
292 $rdci = ($params[5] - 1);
293 // for each vertical region
294 for ($vr = 0; $vr < $params[9]; ++$vr) {
295 // for each row on region
296 for ($r = 0; $r < $params[4]; ++$r) {
297 // get row
298 $row = (($vr * $params[4]) + $r);
299 // for each horizontal region
300 for ($hr = 0; $hr < $params[8]; ++$hr) {
301 // for each column on region
302 for ($c = 0; $c < $params[5]; ++$c) {
303 // get column
304 $col = (($hr * $params[5]) + $c);
305 // braw bits by case
306 if ($r == 0) {
307 // top finder pattern
308 if ($c % 2) {
309 $grid[$row][$col] = 0;
310 } else {
311 $grid[$row][$col] = 1;
312 }
313 } elseif ($r == $rdri) {
314 // bottom finder pattern
315 $grid[$row][$col] = 1;
316 } elseif ($c == 0) {
317 // left finder pattern
318 $grid[$row][$col] = 1;
319 } elseif ($c == $rdci) {
320 // right finder pattern
321 if ($r % 2) {
322 $grid[$row][$col] = 1;
323 } else {
324 $grid[$row][$col] = 0;
325 }
326 } else { // data bit
327 if ($places[$i] < 2) {
328 $grid[$row][$col] = $places[$i];
329 } else {
330 // codeword ID
331 $cw_id = (floor($places[$i] / 10) - 1);
332 // codeword BIT mask
333 $cw_bit = pow(2, (8 - ($places[$i] % 10)));
334 $grid[$row][$col] = (($cw[$cw_id] & $cw_bit) == 0) ? 0 : 1;
335 }
336 ++$i;
337 }
338 }
339 }
340 }
341 }
342 $this->barcode_array['num_rows'] = $params[0];
343 $this->barcode_array['num_cols'] = $params[1];
344 $this->barcode_array['bcode'] = $grid;
345 }
346
347 /**
348 * Returns a barcode array which is readable by TCPDF
349 * @return array barcode array readable by TCPDF;
350 * @public
351 */
352 public function getBarcodeArray() {
353 return $this->barcode_array;
354 }
355
356 /**
357 * Product of two numbers in a Power-of-Two Galois Field
358 * @param $a (int) first number to multiply.
359 * @param $b (int) second number to multiply.
360 * @param $log (array) Log table.
361 * @param $alog (array) Anti-Log table.
362 * @param $gf (array) Number of Factors of the Reed-Solomon polynomial.
363 * @return int product
364 * @protected
365 */
366 protected function getGFProduct($a, $b, $log, $alog, $gf) {
367 if (($a == 0) OR ($b == 0)) {
368 return 0;
369 }
370 return ($alog[($log[$a] + $log[$b]) % ($gf - 1)]);
371 }
372
373 /**
374 * Add error correction codewords to data codewords array (ANNEX E).
375 * @param $wd (array) Array of datacodewords.
376 * @param $nb (int) Number of blocks.
377 * @param $nd (int) Number of data codewords per block.
378 * @param $nc (int) Number of correction codewords per block.
379 * @param $gf (int) numner of fields on log/antilog table (power of 2).
380 * @param $pp (int) The value of its prime modulus polynomial (301 for ECC200).
381 * @return array data codewords + error codewords
382 * @protected
383 */
384 protected function getErrorCorrection($wd, $nb, $nd, $nc, $gf=256, $pp=301) {
385 // generate the log ($log) and antilog ($alog) tables
386 $log[0] = 0;
387 $alog[0] = 1;
388 for ($i = 1; $i < $gf; ++$i) {
389 $alog[$i] = ($alog[($i - 1)] * 2);
390 if ($alog[$i] >= $gf) {
391 $alog[$i] ^= $pp;
392 }
393 $log[$alog[$i]] = $i;
394 }
395 ksort($log);
396 // generate the polynomial coefficients (c)
397 $c = array_fill(0, ($nc + 1), 0);
398 $c[0] = 1;
399 for ($i = 1; $i <= $nc; ++$i) {
400 $c[$i] = $c[($i-1)];
401 for ($j = ($i - 1); $j >= 1; --$j) {
402 $c[$j] = $c[($j - 1)] ^ $this->getGFProduct($c[$j], $alog[$i], $log, $alog, $gf);
403 }
404 $c[0] = $this->getGFProduct($c[0], $alog[$i], $log, $alog, $gf);
405 }
406 ksort($c);
407 // total number of data codewords
408 $num_wd = ($nb * $nd);
409 // total number of error codewords
410 $num_we = ($nb * $nc);
411 // for each block
412 for ($b = 0; $b < $nb; ++$b) {
413 // create interleaved data block
414 $block = array();
415 for ($n = $b; $n < $num_wd; $n += $nb) {
416 $block[] = $wd[$n];
417 }
418 // initialize error codewords
419 $we = array_fill(0, ($nc + 1), 0);
420 // calculate error correction codewords for this block
421 for ($i = 0; $i < $nd; ++$i) {
422 $k = ($we[0] ^ $block[$i]);
423 for ($j = 0; $j < $nc; ++$j) {
424 $we[$j] = ($we[($j + 1)] ^ $this->getGFProduct($k, $c[($nc - $j - 1)], $log, $alog, $gf));
425 }
426 }
427 // add error codewords at the end of data codewords
428 $j = 0;
429 for ($i = $b; $i < $num_we; $i += $nb) {
430 $wd[($num_wd + $i)] = $we[$j];
431 ++$j;
432 }
433 }
434 // reorder codewords
435 ksort($wd);
436 return $wd;
437 }
438
439 /**
440 * Return the 253-state codeword
441 * @param $cwpad (int) Pad codeword.
442 * @param $cwpos (int) Number of data codewords from the beginning of encoded data.
443 * @return pad codeword
444 * @protected
445 */
446 protected function get253StateCodeword($cwpad, $cwpos) {
447 $pad = ($cwpad + (((149 * $cwpos) % 253) + 1));
448 if ($pad > 254) {
449 $pad -= 254;
450 }
451 return $pad;
452 }
453
454 /**
455 * Return the 255-state codeword
456 * @param $cwpad (int) Pad codeword.
457 * @param $cwpos (int) Number of data codewords from the beginning of encoded data.
458 * @return pad codeword
459 * @protected
460 */
461 protected function get255StateCodeword($cwpad, $cwpos) {
462 $pad = ($cwpad + (((149 * $cwpos) % 255) + 1));
463 if ($pad > 255) {
464 $pad -= 256;
465 }
466 return $pad;
467 }
468
469 /**
470 * Returns true if the char belongs to the selected mode
471 * @param $chr (int) Character (byte) to check.
472 * @param $mode (int) Current encoding mode.
473 * @return boolean true if the char is of the selected mode.
474 * @protected
475 */
476 protected function isCharMode($chr, $mode) {
477 $status = false;
478 switch ($mode) {
479 case ENC_ASCII: { // ASCII character 0 to 127
480 $status = (($chr >= 0) AND ($chr <= 127));
481 break;
482 }
483 case ENC_C40: { // Upper-case alphanumeric
484 $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 65) AND ($chr <= 90)));
485 break;
486 }
487 case ENC_TXT: { // Lower-case alphanumeric
488 $status = (($chr == 32) OR (($chr >= 48) AND ($chr <= 57)) OR (($chr >= 97) AND ($chr <= 122)));
489 break;
490 }
491 case ENC_X12: { // ANSI X12
492 $status = (($chr == 13) OR ($chr == 42) OR ($chr == 62));
493 break;
494 }
495 case ENC_EDF: { // ASCII character 32 to 94
496 $status = (($chr >= 32) AND ($chr <= 94));
497 break;
498 }
499 case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page)
500 $status = (($chr == 232) OR ($chr == 233) OR ($chr == 234) OR ($chr == 241));
501 break;
502 }
503 case ENC_ASCII_EXT: { // ASCII character 128 to 255
504 $status = (($chr >= 128) AND ($chr <= 255));
505 break;
506 }
507 case ENC_ASCII_NUM: { // ASCII digits
508 $status = (($chr >= 48) AND ($chr <= 57));
509 break;
510 }
511 }
512 return $status;
513 }
514
515 /**
516 * The look-ahead test scans the data to be encoded to find the best mode (Annex P - steps from J to S).
517 * @param $data (string) data to encode
518 * @param $pos (int) current position
519 * @param $mode (int) current encoding mode
520 * @return int encoding mode
521 * @protected
522 */
523 protected function lookAheadTest($data, $pos, $mode) {
524 $data_length = strlen($data);
525 if ($pos >= $data_length) {
526 return $mode;
527 }
528 $charscount = 0; // count processed chars
529 // STEP J
530 if ($mode == ENC_ASCII) {
531 $numch = array(0, 1, 1, 1, 1, 1.25);
532 } else {
533 $numch = array(1, 2, 2, 2, 2, 2.25);
534 $numch[$mode] = 0;
535 }
536 while (true) {
537 // STEP K
538 if (($pos + $charscount) == $data_length) {
539 if ($numch[ENC_ASCII] <= ceil(min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) {
540 return ENC_ASCII;
541 }
542 if ($numch[ENC_BASE256] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) {
543 return ENC_BASE256;
544 }
545 if ($numch[ENC_EDF] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256]))) {
546 return ENC_EDF;
547 }
548 if ($numch[ENC_TXT] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256]))) {
549 return ENC_TXT;
550 }
551 if ($numch[ENC_X12] < ceil(min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256]))) {
552 return ENC_X12;
553 }
554 return ENC_C40;
555 }
556 // get char
557 $chr = ord($data[$pos + $charscount]);
558 $charscount++;
559 // STEP L
560 if ($this->isCharMode($chr, ENC_ASCII_NUM)) {
561 $numch[ENC_ASCII] += (1 / 2);
562 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) {
563 $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]);
564 $numch[ENC_ASCII] += 2;
565 } else {
566 $numch[ENC_ASCII] = ceil($numch[ENC_ASCII]);
567 $numch[ENC_ASCII] += 1;
568 }
569 // STEP M
570 if ($this->isCharMode($chr, ENC_C40)) {
571 $numch[ENC_C40] += (2 / 3);
572 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) {
573 $numch[ENC_C40] += (8 / 3);
574 } else {
575 $numch[ENC_C40] += (4 / 3);
576 }
577 // STEP N
578 if ($this->isCharMode($chr, ENC_TXT)) {
579 $numch[ENC_TXT] += (2 / 3);
580 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) {
581 $numch[ENC_TXT] += (8 / 3);
582 } else {
583 $numch[ENC_TXT] += (4 / 3);
584 }
585 // STEP O
586 if ($this->isCharMode($chr, ENC_X12) OR $this->isCharMode($chr, ENC_C40)) {
587 $numch[ENC_X12] += (2 / 3);
588 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) {
589 $numch[ENC_X12] += (13 / 3);
590 } else {
591 $numch[ENC_X12] += (10 / 3);
592 }
593 // STEP P
594 if ($this->isCharMode($chr, ENC_EDF)) {
595 $numch[ENC_EDF] += (3 / 4);
596 } elseif ($this->isCharMode($chr, ENC_ASCII_EXT)) {
597 $numch[ENC_EDF] += (17 / 4);
598 } else {
599 $numch[ENC_EDF] += (13 / 4);
600 }
601 // STEP Q
602 if ($this->isCharMode($chr, ENC_BASE256)) {
603 $numch[ENC_BASE256] += 4;
604 } else {
605 $numch[ENC_BASE256] += 1;
606 }
607 // STEP R
608 if ($charscount >= 4) {
609 if (($numch[ENC_ASCII] + 1) <= min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) {
610 return ENC_ASCII;
611 }
612 if ((($numch[ENC_BASE256] + 1) <= $numch[ENC_ASCII])
613 OR (($numch[ENC_BASE256] + 1) < min($numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_EDF]))) {
614 return ENC_BASE256;
615 }
616 if (($numch[ENC_EDF] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_X12], $numch[ENC_BASE256])) {
617 return ENC_EDF;
618 }
619 if (($numch[ENC_TXT] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_X12], $numch[ENC_EDF], $numch[ENC_BASE256])) {
620 return ENC_TXT;
621 }
622 if (($numch[ENC_X12] + 1) < min($numch[ENC_ASCII], $numch[ENC_C40], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) {
623 return ENC_X12;
624 }
625 if (($numch[ENC_C40] + 1) < min($numch[ENC_ASCII], $numch[ENC_TXT], $numch[ENC_EDF], $numch[ENC_BASE256])) {
626 if ($numch[ENC_C40] < $numch[ENC_X12]) {
627 return ENC_C40;
628 }
629 if ($numch[ENC_C40] == $numch[ENC_X12]) {
630 $k = ($pos + $charscount + 1);
631 while ($k < $data_length) {
632 $tmpchr = ord($data{$k});
633 if ($this->isCharMode($tmpchr, ENC_X12)) {
634 return ENC_X12;
635 } elseif (!($this->isCharMode($tmpchr, ENC_X12) OR $this->isCharMode($tmpchr, ENC_C40))) {
636 break;
637 }
638 ++$k;
639 }
640 return ENC_C40;
641 }
642 }
643 }
644 } // end of while
645 }
646
647 /**
648 * Get the switching codeword to a new encoding mode (latch codeword)
649 * @param $mode (int) New encoding mode.
650 * @return (int) Switch codeword.
651 * @protected
652 */
653 protected function getSwitchEncodingCodeword($mode) {
654 switch ($mode) {
655 case ENC_ASCII: { // ASCII character 0 to 127
656 $cw = 254;
657 if ($this->last_enc == ENC_EDF) {
658 $cw = 124;
659 }
660 break;
661 }
662 case ENC_C40: { // Upper-case alphanumeric
663 $cw = 230;
664 break;
665 }
666 case ENC_TXT: { // Lower-case alphanumeric
667 $cw = 239;
668 break;
669 }
670 case ENC_X12: { // ANSI X12
671 $cw = 238;
672 break;
673 }
674 case ENC_EDF: { // ASCII character 32 to 94
675 $cw = 240;
676 break;
677 }
678 case ENC_BASE256: { // Function character (FNC1, Structured Append, Reader Program, or Code Page)
679 $cw = 231;
680 break;
681 }
682 }
683 return $cw;
684 }
685
686 /**
687 * Choose the minimum matrix size and return the max number of data codewords.
688 * @param $numcw (int) Number of current codewords.
689 * @return number of data codewords in matrix
690 * @protected
691 */
692 protected function getMaxDataCodewords($numcw) {
693 foreach ($this->symbattr as $key => $matrix) {
694 if ($matrix[11] >= $numcw) {
695 return $matrix[11];
696 }
697 }
698 return 0;
699 }
700
701 /**
702 * Get high level encoding using the minimum symbol data characters for ECC 200
703 * @param $data (string) data to encode
704 * @return array of codewords
705 * @protected
706 */
707 protected function getHighLevelEncoding($data) {
708 // STEP A. Start in ASCII encodation.
709 $enc = ENC_ASCII; // current encoding mode
710 $pos = 0; // current position
711 $cw = array(); // array of codewords to be returned
712 $cw_num = 0; // number of data codewords
713 $data_length = strlen($data); // number of chars
714 while ($pos < $data_length) {
715 // set last used encoding
716 $this->last_enc = $enc;
717 switch ($enc) {
718 case ENC_ASCII: { // STEP B. While in ASCII encodation
719 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))) {
720 // 1. If the next data sequence is at least 2 consecutive digits, encode the next two digits as a double digit in ASCII mode.
721 $cw[] = (intval(substr($data, $pos, 2)) + 130);
722 ++$cw_num;
723 $pos += 2;
724 } else {
725 // 2. If the look-ahead test (starting at step J) indicates another mode, switch to that mode.
726 $newenc = $this->lookAheadTest($data, $pos, $enc);
727 if ($newenc != $enc) {
728 // switch to new encoding
729 $enc = $newenc;
730 $cw[] = $this->getSwitchEncodingCodeword($enc);
731 ++$cw_num;
732 } else {
733 // get new byte
734 $chr = ord($data[$pos]);
735 ++$pos;
736 if ($this->isCharMode($chr, ENC_ASCII_EXT)) {
737 // 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.
738 $cw[] = 235;
739 $cw[] = ($chr - 127);
740 $cw_num += 2;
741 } else {
742 // 4. Otherwise process the next data character in ASCII encodation.
743 $cw[] = ($chr + 1);
744 ++$cw_num;
745 }
746 }
747 }
748 break;
749 }
750 case ENC_C40 : // Upper-case alphanumeric
751 case ENC_TXT : // Lower-case alphanumeric
752 case ENC_X12 : { // ANSI X12
753 $temp_cw = array();
754 $p = 0;
755 $epos = $pos;
756 // get charset ID
757 $set_id = $this->chset_id[$enc];
758 // get basic charset for current encoding
759 $charset = $this->chset[$set_id];
760 do {
761 // 2. process the next character in C40 encodation.
762 $chr = ord($data[$epos]);
763 ++$epos;
764 // check for extended character
765 if ($chr & 0x80) {
766 if ($enc == ENC_X12) {
767 return false;
768 }
769 $chr = ($chr & 0x7f);
770 $temp_cw[] = 1; // shift 2
771 $temp_cw[] = 30; // upper shift
772 $p += 2;
773 }
774 if (isset($charset[$chr])) {
775 $temp_cw[] = $charset[$chr];
776 ++$p;
777 } else {
778 if (isset($this->chset['SH1'][$chr])) {
779 $temp_cw[] = 0; // shift 1
780 $shiftset = $this->chset['SH1'];
781 } elseif (isset($chr, $this->chset['SH2'][$chr])) {
782 $temp_cw[] = 1; // shift 2
783 $shiftset = $this->chset['SH2'];
784 } elseif (($enc == ENC_C40) AND isset($this->chset['S3C'][$chr])) {
785 $temp_cw[] = 2; // shift 3
786 $shiftset = $this->chset['S3C'];
787 } elseif (($enc == ENC_TXT) AND isset($this->chset['S3T'][$chr])) {
788 $temp_cw[] = 2; // shift 3
789 $shiftset = $this->chset['S3T'];
790 } else {
791 return false;
792 }
793 $temp_cw[] = $shiftset[$chr];
794 $p += 2;
795 }
796 if ($p >= 3) {
797 $c1 = array_shift($temp_cw);
798 $c2 = array_shift($temp_cw);
799 $c3 = array_shift($temp_cw);
800 $p -= 3;
801 $tmp = ((1600 * $c1) + (40 * $c2) + $c3 + 1);
802 $cw[] = ($tmp >> 8);
803 $cw[] = ($tmp % 256);
804 $cw_num += 2;
805 $pos = $epos;
806 // 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.
807 $newenc = $this->lookAheadTest($data, $pos, $enc);
808 if ($newenc != $enc) {
809 // switch to new encoding
810 $enc = $newenc;
811 if ($enc != ENC_ASCII) {
812 // set unlatch character
813 $cw[] = $this->getSwitchEncodingCodeword(ENC_ASCII);
814 ++$cw_num;
815 }
816 $cw[] = $this->getSwitchEncodingCodeword($enc);
817 ++$cw_num;
818 $pos -= $p;
819 $p = 0;
820 break;
821 }
822 }
823 } while (($p > 0) AND ($epos < $data_length));
824 // process last data (if any)
825 if ($p > 0) {
826 // get remaining number of data symbols
827 $cwr = ($this->getMaxDataCodewords($cw_num) - $cw_num);
828 if (($cwr == 1) AND ($p == 1)) {
829 // d. If one symbol character remains and one C40 value (data character) remains to be encoded
830 $c1 = array_shift($temp_cw);
831 --$p;
832 $cw[] = ($chr + 1);
833 ++$cw_num;
834 $pos = $epos;
835 $enc = ENC_ASCII;
836 $this->last_enc = $enc;
837 } elseif (($cwr == 2) AND ($p == 1)) {
838 // c. If two symbol characters remain and only one C40 value (data character) remains to be encoded
839 $c1 = array_shift($temp_cw);
840 --$p;
841 $cw[] = 254;
842 $cw[] = ($chr + 1);
843 $cw_num += 2;
844 $pos = $epos;
845 $enc = ENC_ASCII;
846 $this->last_enc = $enc;
847 } elseif (($cwr == 2) AND ($p == 2)) {
848 // b. If two symbol characters remain and two C40 values remain to be encoded
849 $c1 = array_shift($temp_cw);
850 $c2 = array_shift($temp_cw);
851 $p -= 2;
852 $tmp = ((1600 * $c1) + (40 * $c2) + 1);
853 $cw[] = ($tmp >> 8);
854 $cw[] = ($tmp % 256);
855 $cw_num += 2;
856 $pos = $epos;
857 $enc = ENC_ASCII;
858 $this->last_enc = $enc;
859 } else {
860 // switch to ASCII encoding
861 if ($enc != ENC_ASCII) {
862 $enc = ENC_ASCII;
863 $this->last_enc = $enc;
864 $cw[] = $this->getSwitchEncodingCodeword($enc);
865 ++$cw_num;
866 $pos = ($epos - $p);
867 }
868 }
869 }
870 break;
871 }
872 case ENC_EDF: { // F. While in EDIFACT (EDF) encodation
873 // initialize temporary array with 0 length
874 $temp_cw = array();
875 $epos = $pos;
876 $field_length = 0;
877 $newenc = $enc;
878 do {
879 // 2. process the next character in EDIFACT encodation.
880 $chr = ord($data[$epos]);
881 if ($this->isCharMode($chr, ENC_EDF)) {
882 ++$epos;
883 $temp_cw[] = $chr;
884 ++$field_length;
885 }
886 if (($field_length == 4) OR ($epos == $data_length) OR !$this->isCharMode($chr, ENC_EDF)) {
887 if (($epos == $data_length) AND ($field_length < 3)) {
888 $enc = ENC_ASCII;
889 $cw[] = $this->getSwitchEncodingCodeword($enc);
890 ++$cw_num;
891 break;
892 }
893 if ($field_length < 4) {
894 // set unlatch character
895 $temp_cw[] = 0x1f;
896 ++$field_length;
897 // fill empty characters
898 for ($i = $field_length; $i < 4; ++$i) {
899 $temp_cw[] = 0;
900 }
901 $enc = ENC_ASCII;
902 $this->last_enc = $enc;
903 }
904 // encodes four data characters in three codewords
905 $tcw = (($temp_cw[0] & 0x3F) << 2) + (($temp_cw[1] & 0x30) >> 4);
906 if ($tcw > 0) {
907 $cw[] = $tcw;
908 $cw_num++;
909 }
910 $tcw= (($temp_cw[1] & 0x0F) << 4) + (($temp_cw[2] & 0x3C) >> 2);
911 if ($tcw > 0) {
912 $cw[] = $tcw;
913 $cw_num++;
914 }
915 $tcw = (($temp_cw[2] & 0x03) << 6) + ($temp_cw[3] & 0x3F);
916 if ($tcw > 0) {
917 $cw[] = $tcw;
918 $cw_num++;
919 }
920 $temp_cw = array();
921 $pos = $epos;
922 $field_length = 0;
923 if ($enc == ENC_ASCII) {
924 break; // exit from EDIFACT mode
925 }
926 }
927 } while ($epos < $data_length);
928 break;
929 }
930 case ENC_BASE256: { // G. While in Base 256 (B256) encodation
931 // initialize temporary array with 0 length
932 $temp_cw = array();
933 $field_length = 0;
934 while (($pos < $data_length) AND ($field_length <= 1555)) {
935 $newenc = $this->lookAheadTest($data, $pos, $enc);
936 if ($newenc != $enc) {
937 // 1. If the look-ahead test (starting at step J) indicates another mode, switch to that mode.
938 $enc = $newenc;
939 break; // exit from B256 mode
940 } else {
941 // 2. Otherwise, process the next character in Base 256 encodation.
942 $chr = ord($data[$pos]);
943 ++$pos;
944 $temp_cw[] = $chr;
945 ++$field_length;
946 }
947 }
948 // set field length
949 if ($field_length <= 249) {
950 $cw[] = $this->get255StateCodeword($field_length, ($cw_num + 1));
951 ++$cw_num;
952 } else {
953 $cw[] = $this->get255StateCodeword((floor($field_length / 250) + 249), ($cw_num + 1));
954 $cw[] = $this->get255StateCodeword(($field_length % 250), ($cw_num + 2));
955 $cw_num += 2;
956 }
957 if (!empty($temp_cw)) {
958 // add B256 field
959 foreach ($temp_cw as $p => $cht) {
960 $cw[] = $this->get255StateCodeword($cht, ($cw_num + $p + 1));
961 }
962 }
963 break;
964 }
965 } // end of switch enc
966 } // end of while
967 return $cw;
968 }
969
970 /**
971 * Places "chr+bit" with appropriate wrapping within array[].
972 * (Annex F - ECC 200 symbol character placement)
973 * @param $marr (array) Array of symbols.
974 * @param $nrow (int) Number of rows.
975 * @param $ncol (int) Number of columns.
976 * @param $row (int) Row number.
977 * @param $col (int) Column number.
978 * @param $chr (int) Char byte.
979 * @param $bit (int) Bit.
980 * @return array
981 * @protected
982 */
983 protected function placeModule($marr, $nrow, $ncol, $row, $col, $chr, $bit) {
984 if ($row < 0) {
985 $row += $nrow;
986 $col += (4 - (($nrow + 4) % 8));
987 }
988 if ($col < 0) {
989 $col += $ncol;
990 $row += (4 - (($ncol + 4) % 8));
991 }
992 $marr[(($row * $ncol) + $col)] = ((10 * $chr) + $bit);
993 return $marr;
994 }
995
996 /**
997 * Places the 8 bits of a utah-shaped symbol character.
998 * (Annex F - ECC 200 symbol character placement)
999 * @param $marr (array) Array of symbols.
1000 * @param $nrow (int) Number of rows.
1001 * @param $ncol (int) Number of columns.
1002 * @param $row (int) Row number.
1003 * @param $col (int) Column number.
1004 * @param $chr (int) Char byte.
1005 * @return array
1006 * @protected
1007 */
1008 protected function placeUtah($marr, $nrow, $ncol, $row, $col, $chr) {
1009 $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-2, $chr, 1);
1010 $marr = $this->placeModule($marr, $nrow, $ncol, $row-2, $col-1, $chr, 2);
1011 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-2, $chr, 3);
1012 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col-1, $chr, 4);
1013 $marr = $this->placeModule($marr, $nrow, $ncol, $row-1, $col, $chr, 5);
1014 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-2, $chr, 6);
1015 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col-1, $chr, 7);
1016 $marr = $this->placeModule($marr, $nrow, $ncol, $row, $col, $chr, 8);
1017 return $marr;
1018 }
1019
1020 /**
1021 * Places the 8 bits of the first special corner case.
1022 * (Annex F - ECC 200 symbol character placement)
1023 * @param $marr (array) Array of symbols.
1024 * @param $nrow (int) Number of rows.
1025 * @param $ncol (int) Number of columns.
1026 * @param $chr (int) Char byte.
1027 * @return array
1028 * @protected
1029 */
1030 protected function placeCornerA($marr, $nrow, $ncol, $chr) {
1031 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1);
1032 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 1, $chr, 2);
1033 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 2, $chr, 3);
1034 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4);
1035 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5);
1036 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6);
1037 $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7);
1038 $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8);
1039 return $marr;
1040 }
1041
1042 /**
1043 * Places the 8 bits of the second special corner case.
1044 * (Annex F - ECC 200 symbol character placement)
1045 * @param $marr (array) Array of symbols.
1046 * @param $nrow (int) Number of rows.
1047 * @param $ncol (int) Number of columns.
1048 * @param $chr (int) Char byte.
1049 * @return array
1050 * @protected
1051 */
1052 protected function placeCornerB($marr, $nrow, $ncol, $chr) {
1053 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1);
1054 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2);
1055 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3);
1056 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-4, $chr, 4);
1057 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 5);
1058 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 6);
1059 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 7);
1060 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8);
1061 return $marr;
1062 }
1063
1064 /**
1065 * Places the 8 bits of the third special corner case.
1066 * (Annex F - ECC 200 symbol character placement)
1067 * @param $marr (array) Array of symbols.
1068 * @param $nrow (int) Number of rows.
1069 * @param $ncol (int) Number of columns.
1070 * @param $chr (int) Char byte.
1071 * @return array
1072 * @protected
1073 */
1074 protected function placeCornerC($marr, $nrow, $ncol, $chr) {
1075 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-3, 0, $chr, 1);
1076 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-2, 0, $chr, 2);
1077 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 3);
1078 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4);
1079 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5);
1080 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 6);
1081 $marr = $this->placeModule($marr, $nrow, $ncol, 2, $ncol-1, $chr, 7);
1082 $marr = $this->placeModule($marr, $nrow, $ncol, 3, $ncol-1, $chr, 8);
1083 return $marr;
1084 }
1085
1086 /**
1087 * Places the 8 bits of the fourth special corner case.
1088 * (Annex F - ECC 200 symbol character placement)
1089 * @param $marr (array) Array of symbols.
1090 * @param $nrow (int) Number of rows.
1091 * @param $ncol (int) Number of columns.
1092 * @param $chr (int) Char byte.
1093 * @return array
1094 * @protected
1095 */
1096 protected function placeCornerD($marr, $nrow, $ncol, $chr) {
1097 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, 0, $chr, 1);
1098 $marr = $this->placeModule($marr, $nrow, $ncol, $nrow-1, $ncol-1, $chr, 2);
1099 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-3, $chr, 3);
1100 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-2, $chr, 4);
1101 $marr = $this->placeModule($marr, $nrow, $ncol, 0, $ncol-1, $chr, 5);
1102 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-3, $chr, 6);
1103 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-2, $chr, 7);
1104 $marr = $this->placeModule($marr, $nrow, $ncol, 1, $ncol-1, $chr, 8);
1105 return $marr;
1106 }
1107
1108 /**
1109 * Build a placement map.
1110 * (Annex F - ECC 200 symbol character placement)
1111 * @param $nrow (int) Number of rows.
1112 * @param $ncol (int) Number of columns.
1113 * @return array
1114 * @protected
1115 */
1116 protected function getPlacementMap($nrow, $ncol) {
1117 // initialize array with zeros
1118 $marr = array_fill(0, ($nrow * $ncol), 0);
1119 // set starting values
1120 $chr = 1;
1121 $row = 4;
1122 $col = 0;
1123 do {
1124 // repeatedly first check for one of the special corner cases, then
1125 if (($row == $nrow) AND ($col == 0)) {
1126 $marr = $this->placeCornerA($marr, $nrow, $ncol, $chr);
1127 ++$chr;
1128 }
1129 if (($row == ($nrow - 2)) AND ($col == 0) AND ($ncol % 4)) {
1130 $marr = $this->placeCornerB($marr, $nrow, $ncol, $chr);
1131 ++$chr;
1132 }
1133 if (($row == ($nrow - 2)) AND ($col == 0) AND (($ncol % 8) == 4)) {
1134 $marr = $this->placeCornerC($marr, $nrow, $ncol, $chr);
1135 ++$chr;
1136 }
1137 if (($row == ($nrow + 4)) AND ($col == 2) AND (!($ncol % 8))) {
1138 $marr = $this->placeCornerD($marr, $nrow, $ncol, $chr);
1139 ++$chr;
1140 }
1141 // sweep upward diagonally, inserting successive characters,
1142 do {
1143 if (($row < $nrow) AND ($col >= 0) AND (!$marr[(($row * $ncol) + $col)])) {
1144 $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr);
1145 ++$chr;
1146 }
1147 $row -= 2;
1148 $col += 2;
1149 } while (($row >= 0) AND ($col < $ncol));
1150 ++$row;
1151 $col += 3;
1152 // & then sweep downward diagonally, inserting successive characters,...
1153 do {
1154 if (($row >= 0) AND ($col < $ncol) AND (!$marr[(($row * $ncol) + $col)])) {
1155 $marr = $this->placeUtah($marr, $nrow, $ncol, $row, $col, $chr);
1156 ++$chr;
1157 }
1158 $row += 2;
1159 $col -= 2;
1160 } while (($row < $nrow) AND ($col >= 0));
1161 $row += 3;
1162 ++$col;
1163 // ... until the entire array is scanned
1164 } while (($row < $nrow) OR ($col < $ncol));
1165 // lastly, if the lower righthand corner is untouched, fill in fixed pattern
1166 if (!$marr[(($nrow * $ncol) - 1)]) {
1167 $marr[(($nrow * $ncol) - 1)] = 1;
1168 $marr[(($nrow * $ncol) - $ncol - 2)] = 1;
1169 }
1170 return $marr;
1171 }
1172
1173 } // end DataMatrix class
1174 //============================================================+
1175 // END OF FILE
1176 //============================================================+
1177