Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend/gridmtx.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 /* gridmtx.c - Grid Matrix */ | |
| 2 /* | |
| 3 libzint - the open source barcode library | |
| 4 Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com> | |
| 5 | |
| 6 Redistribution and use in source and binary forms, with or without | |
| 7 modification, are permitted provided that the following conditions | |
| 8 are met: | |
| 9 | |
| 10 1. Redistributions of source code must retain the above copyright | |
| 11 notice, this list of conditions and the following disclaimer. | |
| 12 2. Redistributions in binary form must reproduce the above copyright | |
| 13 notice, this list of conditions and the following disclaimer in the | |
| 14 documentation and/or other materials provided with the distribution. | |
| 15 3. Neither the name of the project nor the names of its contributors | |
| 16 may be used to endorse or promote products derived from this software | |
| 17 without specific prior written permission. | |
| 18 | |
| 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
| 20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| 22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE | |
| 23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| 24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| 25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| 26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| 27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| 28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| 29 SUCH DAMAGE. | |
| 30 */ | |
| 31 /* SPDX-License-Identifier: BSD-3-Clause */ | |
| 32 | |
| 33 /* This file implements Grid Matrix as specified in | |
| 34 AIM Global Document Number AIMD014 Rev. 1.63 Revised 9 Dec 2008 */ | |
| 35 | |
| 36 #include <stdio.h> | |
| 37 #include "common.h" | |
| 38 #include "reedsol.h" | |
| 39 #include "gridmtx.h" | |
| 40 #include "eci.h" | |
| 41 | |
| 42 static const char EUROPIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz "; | |
| 43 static const char EUROPIUM_UPR[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "; | |
| 44 static const char EUROPIUM_LWR[] = "abcdefghijklmnopqrstuvwxyz "; | |
| 45 | |
| 46 /* gm_define_mode() stuff */ | |
| 47 | |
| 48 /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */ | |
| 49 #define GM_MULT 6 | |
| 50 | |
| 51 /* Non-digit numeral set, excluding EOL (carriage return/linefeed) */ | |
| 52 static const char gm_numeral_nondigits[] = " +-.,"; | |
| 53 | |
| 54 /* Whether in numeral or not. If in numeral, *p_numeral_end is set to position after numeral, | |
| 55 * and *p_numeral_cost is set to per-numeral cost */ | |
| 56 static int gm_in_numeral(const unsigned int ddata[], const int length, const int in_posn, | |
| 57 unsigned int *p_numeral_end, unsigned int *p_numeral_cost) { | |
| 58 int i, digit_cnt, nondigit, nondigit_posn; | |
| 59 | |
| 60 if (in_posn < (int) *p_numeral_end) { | |
| 61 return 1; | |
| 62 } | |
| 63 | |
| 64 /* Attempt to calculate the average 'cost' of using numeric mode in number of bits (times GM_MULT) */ | |
| 65 /* Also ensures that numeric mode is not selected when it cannot be used: for example in | |
| 66 a string which has "2.2.0" (cannot have more than one non-numeric character for each | |
| 67 block of three numeric characters) */ | |
| 68 for (i = in_posn, digit_cnt = 0, nondigit = 0, nondigit_posn = 0; i < length && i < in_posn + 4 && digit_cnt < 3; | |
| 69 i++) { | |
| 70 if (z_isdigit(ddata[i])) { | |
| 71 digit_cnt++; | |
| 72 } else if (posn(gm_numeral_nondigits, (const char) ddata[i]) != -1) { | |
| 73 if (nondigit) { | |
| 74 break; | |
| 75 } | |
| 76 nondigit = 1; | |
| 77 nondigit_posn = i; | |
| 78 } else if (i < length - 1 && ddata[i] == 13 && ddata[i + 1] == 10) { | |
| 79 if (nondigit) { | |
| 80 break; | |
| 81 } | |
| 82 i++; | |
| 83 nondigit = 2; | |
| 84 nondigit_posn = i; | |
| 85 } else { | |
| 86 break; | |
| 87 } | |
| 88 } | |
| 89 if (digit_cnt == 0) { /* Must have at least one digit */ | |
| 90 *p_numeral_end = 0; | |
| 91 return 0; | |
| 92 } | |
| 93 if (nondigit && nondigit_posn == i - 1) { /* Non-digit can't be at end */ | |
| 94 nondigit = 0; | |
| 95 } | |
| 96 *p_numeral_end = in_posn + digit_cnt + nondigit; | |
| 97 /* Calculate per-numeral cost where 120 == (10 + 10) * GM_MULT, 60 == 10 * GM_MULT */ | |
| 98 if (digit_cnt == 3) { | |
| 99 *p_numeral_cost = nondigit == 2 ? 24 /* (120 / 5) */ : nondigit == 1 ? 30 /* (120 / 4) */ : 20 /* (60 / 3) */; | |
| 100 } else if (digit_cnt == 2) { | |
| 101 *p_numeral_cost = nondigit == 2 ? 30 /* (120 / 4) */ : nondigit == 1 ? 40 /* (120 / 3) */ : 30 /* (60 / 2) */; | |
| 102 } else { | |
| 103 *p_numeral_cost = nondigit == 2 ? 40 /* (120 / 3) */ : nondigit == 1 ? 60 /* (120 / 2) */ : 60 /* (60 / 1) */; | |
| 104 } | |
| 105 return 1; | |
| 106 } | |
| 107 | |
| 108 /* Encoding modes */ | |
| 109 #define GM_CHINESE 'H' | |
| 110 #define GM_NUMBER 'N' | |
| 111 #define GM_LOWER 'L' | |
| 112 #define GM_UPPER 'U' | |
| 113 #define GM_MIXED 'M' | |
| 114 #define GM_BYTE 'B' | |
| 115 /* Note Control is a submode of Lower, Upper and Mixed modes */ | |
| 116 | |
| 117 /* Indexes into mode_types array */ | |
| 118 #define GM_H 0 /* Chinese (Hanzi) */ | |
| 119 #define GM_N 1 /* Numeral */ | |
| 120 #define GM_L 2 /* Lower case */ | |
| 121 #define GM_U 3 /* Upper case */ | |
| 122 #define GM_M 4 /* Mixed */ | |
| 123 #define GM_B 5 /* Byte */ | |
| 124 | |
| 125 #define GM_NUM_MODES 6 | |
| 126 | |
| 127 /* Calculate optimized encoding modes. Adapted from Project Nayuki */ | |
| 128 /* Copyright (c) Project Nayuki. (MIT License) See qr.c for detailed notice */ | |
| 129 static void gm_define_mode(char *mode, const unsigned int ddata[], const int length, const int debug_print) { | |
| 130 /* Must be in same order as GM_H etc */ | |
| 131 static const char mode_types[] = { GM_CHINESE, GM_NUMBER, GM_LOWER, GM_UPPER, GM_MIXED, GM_BYTE, '\0' }; | |
| 132 | |
| 133 /* Initial mode costs */ | |
| 134 static const unsigned int head_costs[GM_NUM_MODES] = { | |
| 135 /* H N (+pad prefix) L U M B (+byte count) */ | |
| 136 4 * GM_MULT, (4 + 2) * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, (4 + 9) * GM_MULT | |
| 137 }; | |
| 138 | |
| 139 /* Cost of switching modes from k to j - see AIMD014 Rev. 1.63 Table 9 – Type conversion codes */ | |
| 140 static const unsigned char switch_costs[GM_NUM_MODES][GM_NUM_MODES] = { | |
| 141 /* H N L U M B */ | |
| 142 /*H*/ { 0, (13 + 2) * GM_MULT, 13 * GM_MULT, 13 * GM_MULT, 13 * GM_MULT, (13 + 9) * GM_MULT }, | |
| 143 /*N*/ { 10 * GM_MULT, 0, 10 * GM_MULT, 10 * GM_MULT, 10 * GM_MULT, (10 + 9) * GM_MULT }, | |
| 144 /*L*/ { 5 * GM_MULT, (5 + 2) * GM_MULT, 0, 5 * GM_MULT, 7 * GM_MULT, (7 + 9) * GM_MULT }, | |
| 145 /*U*/ { 5 * GM_MULT, (5 + 2) * GM_MULT, 5 * GM_MULT, 0, 7 * GM_MULT, (7 + 9) * GM_MULT }, | |
| 146 /*M*/ { 10 * GM_MULT, (10 + 2) * GM_MULT, 10 * GM_MULT, 10 * GM_MULT, 0, (10 + 9) * GM_MULT }, | |
| 147 /*B*/ { 4 * GM_MULT, (4 + 2) * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 0 }, | |
| 148 }; | |
| 149 | |
| 150 /* Final end-of-data cost - see AIMD014 Rev. 1.63 Table 9 – Type conversion codes */ | |
| 151 static const unsigned char eod_costs[GM_NUM_MODES] = { | |
| 152 /* H N L U M B */ | |
| 153 13 * GM_MULT, 10 * GM_MULT, 5 * GM_MULT, 5 * GM_MULT, 10 * GM_MULT, 4 * GM_MULT | |
| 154 }; | |
| 155 | |
| 156 unsigned int numeral_end = 0, numeral_cost = 0, byte_count = 0; /* State */ | |
| 157 int double_byte, space, numeric, lower, upper, control, double_digit, eol; | |
| 158 | |
| 159 int i, j, k; | |
| 160 unsigned int min_cost; | |
| 161 char cur_mode; | |
| 162 unsigned int prev_costs[GM_NUM_MODES]; | |
| 163 unsigned int cur_costs[GM_NUM_MODES]; | |
| 164 char (*char_modes)[GM_NUM_MODES] = (char (*)[GM_NUM_MODES]) z_alloca(GM_NUM_MODES * length); | |
| 165 | |
| 166 /* char_modes[i][j] represents the mode to encode the code point at index i such that the final segment | |
| 167 ends in mode_types[j] and the total number of bits is minimized over all possible choices */ | |
| 168 memset(char_modes, 0, length * GM_NUM_MODES); | |
| 169 | |
| 170 /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT) | |
| 171 * bits needed to encode the entire string prefix of length i, and end in mode_types[j] */ | |
| 172 memcpy(prev_costs, head_costs, GM_NUM_MODES * sizeof(unsigned int)); | |
| 173 | |
| 174 /* Calculate costs using dynamic programming */ | |
| 175 for (i = 0; i < length; i++) { | |
| 176 memset(cur_costs, 0, GM_NUM_MODES * sizeof(unsigned int)); | |
| 177 | |
| 178 space = numeric = lower = upper = control = double_digit = eol = 0; | |
| 179 | |
| 180 double_byte = ddata[i] > 0xFF; | |
| 181 if (!double_byte) { | |
| 182 space = ddata[i] == ' '; | |
| 183 if (!space) { | |
| 184 numeric = z_isdigit(ddata[i]); | |
| 185 if (!numeric) { | |
| 186 lower = z_islower(ddata[i]); | |
| 187 if (!lower) { | |
| 188 upper = z_isupper(ddata[i]); | |
| 189 if (!upper) { | |
| 190 control = ddata[i] < 0x7F; /* Exclude DEL */ | |
| 191 if (control && i + 1 < length) { | |
| 192 eol = ddata[i] == 13 && ddata[i + 1] == 10; | |
| 193 } | |
| 194 } | |
| 195 } | |
| 196 } else if (i + 1 < length) { | |
| 197 double_digit = z_isdigit(ddata[i + 1]); | |
| 198 } | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 /* Hanzi mode can encode anything */ | |
| 203 cur_costs[GM_H] = prev_costs[GM_H] + (double_digit || eol ? 39 : 78); /* (6.5 : 13) * GM_MULT */ | |
| 204 char_modes[i][GM_H] = GM_CHINESE; | |
| 205 | |
| 206 /* Byte mode can encode anything */ | |
| 207 if (byte_count == 512 || (double_byte && byte_count == 511)) { | |
| 208 cur_costs[GM_B] = head_costs[GM_B]; | |
| 209 if (double_byte && byte_count == 511) { | |
| 210 cur_costs[GM_B] += 48; /* 8 * GM_MULT */ | |
| 211 double_byte = 0; /* Splitting double-byte so mark as single */ | |
| 212 } | |
| 213 byte_count = 0; | |
| 214 } | |
| 215 cur_costs[GM_B] += prev_costs[GM_B] + (double_byte ? 96 : 48); /* (16 : 8) * GM_MULT */ | |
| 216 char_modes[i][GM_B] = GM_BYTE; | |
| 217 byte_count += double_byte ? 2 : 1; | |
| 218 | |
| 219 if (gm_in_numeral(ddata, length, i, &numeral_end, &numeral_cost)) { | |
| 220 cur_costs[GM_N] = prev_costs[GM_N] + numeral_cost; | |
| 221 char_modes[i][GM_N] = GM_NUMBER; | |
| 222 } | |
| 223 | |
| 224 if (control) { | |
| 225 cur_costs[GM_L] = prev_costs[GM_L] + 78; /* (7 + 6) * GM_MULT */ | |
| 226 char_modes[i][GM_L] = GM_LOWER; | |
| 227 cur_costs[GM_U] = prev_costs[GM_U] + 78; /* (7 + 6) * GM_MULT */ | |
| 228 char_modes[i][GM_U] = GM_UPPER; | |
| 229 cur_costs[GM_M] = prev_costs[GM_M] + 96; /* (10 + 6) * GM_MULT */ | |
| 230 char_modes[i][GM_M] = GM_MIXED; | |
| 231 } else { | |
| 232 if (lower || space) { | |
| 233 cur_costs[GM_L] = prev_costs[GM_L] + 30; /* 5 * GM_MULT */ | |
| 234 char_modes[i][GM_L] = GM_LOWER; | |
| 235 } | |
| 236 if (upper || space) { | |
| 237 cur_costs[GM_U] = prev_costs[GM_U] + 30; /* 5 * GM_MULT */ | |
| 238 char_modes[i][GM_U] = GM_UPPER; | |
| 239 } | |
| 240 if (numeric || lower || upper || space) { | |
| 241 cur_costs[GM_M] = prev_costs[GM_M] + 36; /* 6 * GM_MULT */ | |
| 242 char_modes[i][GM_M] = GM_MIXED; | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 if (i == length - 1) { /* Add end of data costs if last character */ | |
| 247 for (j = 0; j < GM_NUM_MODES; j++) { | |
| 248 if (char_modes[i][j]) { | |
| 249 cur_costs[j] += eod_costs[j]; | |
| 250 } | |
| 251 } | |
| 252 } | |
| 253 | |
| 254 /* Start new segment at the end to switch modes */ | |
| 255 for (j = 0; j < GM_NUM_MODES; j++) { /* To mode */ | |
| 256 for (k = 0; k < GM_NUM_MODES; k++) { /* From mode */ | |
| 257 if (j != k && char_modes[i][k]) { | |
| 258 const unsigned int new_cost = cur_costs[k] + switch_costs[k][j]; | |
| 259 if (!char_modes[i][j] || new_cost < cur_costs[j]) { | |
| 260 cur_costs[j] = new_cost; | |
| 261 char_modes[i][j] = mode_types[k]; | |
| 262 } | |
| 263 } | |
| 264 } | |
| 265 } | |
| 266 | |
| 267 memcpy(prev_costs, cur_costs, GM_NUM_MODES * sizeof(unsigned int)); | |
| 268 } | |
| 269 | |
| 270 /* Find optimal ending mode */ | |
| 271 min_cost = prev_costs[0]; | |
| 272 cur_mode = mode_types[0]; | |
| 273 for (i = 1; i < GM_NUM_MODES; i++) { | |
| 274 if (prev_costs[i] < min_cost) { | |
| 275 min_cost = prev_costs[i]; | |
| 276 cur_mode = mode_types[i]; | |
| 277 } | |
| 278 } | |
| 279 | |
| 280 /* Get optimal mode for each code point by tracing backwards */ | |
| 281 for (i = length - 1; i >= 0; i--) { | |
| 282 j = posn(mode_types, cur_mode); | |
| 283 cur_mode = char_modes[i][j]; | |
| 284 mode[i] = cur_mode; | |
| 285 } | |
| 286 | |
| 287 if (debug_print) { | |
| 288 printf(" Mode: %.*s\n", length, mode); | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 /* Add the length indicator for byte encoded blocks */ | |
| 293 static void gm_add_byte_count(char binary[], const int byte_count_posn, const int byte_count) { | |
| 294 /* AIMD014 6.3.7: "Let L be the number of bytes of input data to be encoded in the 8-bit binary data set. | |
| 295 * First output (L-1) as a 9-bit binary prefix to record the number of bytes..." */ | |
| 296 bin_append_posn(byte_count - 1, 9, binary, byte_count_posn); | |
| 297 } | |
| 298 | |
| 299 /* Add a control character to the data stream */ | |
| 300 static int gm_add_shift_char(char binary[], int bp, int shifty, const int debug_print) { | |
| 301 int i; | |
| 302 int glyph = 0; | |
| 303 | |
| 304 if (shifty < 32) { | |
| 305 glyph = shifty; | |
| 306 } else { | |
| 307 for (i = 32; i < 64; i++) { | |
| 308 if (gm_shift_set[i] == shifty) { | |
| 309 glyph = i; | |
| 310 break; | |
| 311 } | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 if (debug_print) { | |
| 316 printf("SHIFT [%d] ", glyph); | |
| 317 } | |
| 318 | |
| 319 bp = bin_append_posn(glyph, 6, binary, bp); | |
| 320 | |
| 321 return bp; | |
| 322 } | |
| 323 | |
| 324 static int gm_encode(unsigned int ddata[], const int length, char binary[], const int eci, int *p_bp, | |
| 325 const int debug_print) { | |
| 326 /* Create a binary stream representation of the input data. | |
| 327 7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters, | |
| 328 Mixed numerals and latters, Control characters and 8-bit binary data */ | |
| 329 int sp = 0; | |
| 330 int current_mode = 0; | |
| 331 int last_mode; | |
| 332 unsigned int glyph = 0; | |
| 333 int c1, c2, done; | |
| 334 int p = 0, ppos; | |
| 335 int numbuf[3], punt = 0; | |
| 336 int number_pad_posn = 0; | |
| 337 int byte_count_posn = 0; | |
| 338 int byte_count = 0; | |
| 339 int shift; | |
| 340 int bp = *p_bp; | |
| 341 char *mode = (char *) z_alloca(length); | |
| 342 | |
| 343 if (eci != 0) { | |
| 344 /* ECI assignment according to Table 8 */ | |
| 345 bp = bin_append_posn(12, 4, binary, bp); /* ECI */ | |
| 346 if (eci <= 1023) { | |
| 347 bp = bin_append_posn(eci, 11, binary, bp); | |
| 348 } else if (eci <= 32767) { | |
| 349 bp = bin_append_posn(2, 2, binary, bp); | |
| 350 bp = bin_append_posn(eci, 15, binary, bp); | |
| 351 } else { | |
| 352 bp = bin_append_posn(3, 2, binary, bp); | |
| 353 bp = bin_append_posn(eci, 20, binary, bp); | |
| 354 } | |
| 355 } | |
| 356 | |
| 357 gm_define_mode(mode, ddata, length, debug_print); | |
| 358 | |
| 359 do { | |
| 360 const int next_mode = mode[sp]; | |
| 361 | |
| 362 if (next_mode != current_mode) { | |
| 363 switch (current_mode) { | |
| 364 case 0: | |
| 365 switch (next_mode) { | |
| 366 case GM_CHINESE: bp = bin_append_posn(1, 4, binary, bp); | |
| 367 break; | |
| 368 case GM_NUMBER: bp = bin_append_posn(2, 4, binary, bp); | |
| 369 break; | |
| 370 case GM_LOWER: bp = bin_append_posn(3, 4, binary, bp); | |
| 371 break; | |
| 372 case GM_UPPER: bp = bin_append_posn(4, 4, binary, bp); | |
| 373 break; | |
| 374 case GM_MIXED: bp = bin_append_posn(5, 4, binary, bp); | |
| 375 break; | |
| 376 case GM_BYTE: bp = bin_append_posn(6, 4, binary, bp); | |
| 377 break; | |
| 378 } | |
| 379 break; | |
| 380 case GM_CHINESE: | |
| 381 switch (next_mode) { | |
| 382 case GM_NUMBER: bp = bin_append_posn(8161, 13, binary, bp); | |
| 383 break; | |
| 384 case GM_LOWER: bp = bin_append_posn(8162, 13, binary, bp); | |
| 385 break; | |
| 386 case GM_UPPER: bp = bin_append_posn(8163, 13, binary, bp); | |
| 387 break; | |
| 388 case GM_MIXED: bp = bin_append_posn(8164, 13, binary, bp); | |
| 389 break; | |
| 390 case GM_BYTE: bp = bin_append_posn(8165, 13, binary, bp); | |
| 391 break; | |
| 392 } | |
| 393 break; | |
| 394 case GM_NUMBER: | |
| 395 /* add numeric block padding value */ | |
| 396 switch (p) { | |
| 397 case 1: binary[number_pad_posn] = '1'; | |
| 398 binary[number_pad_posn + 1] = '0'; | |
| 399 break; /* 2 pad digits */ | |
| 400 case 2: binary[number_pad_posn] = '0'; | |
| 401 binary[number_pad_posn + 1] = '1'; | |
| 402 break; /* 1 pad digits */ | |
| 403 case 3: binary[number_pad_posn] = '0'; | |
| 404 binary[number_pad_posn + 1] = '0'; | |
| 405 break; /* 0 pad digits */ | |
| 406 } | |
| 407 switch (next_mode) { | |
| 408 case GM_CHINESE: bp = bin_append_posn(1019, 10, binary, bp); | |
| 409 break; | |
| 410 case GM_LOWER: bp = bin_append_posn(1020, 10, binary, bp); | |
| 411 break; | |
| 412 case GM_UPPER: bp = bin_append_posn(1021, 10, binary, bp); | |
| 413 break; | |
| 414 case GM_MIXED: bp = bin_append_posn(1022, 10, binary, bp); | |
| 415 break; | |
| 416 case GM_BYTE: bp = bin_append_posn(1023, 10, binary, bp); | |
| 417 break; | |
| 418 } | |
| 419 break; | |
| 420 case GM_LOWER: | |
| 421 case GM_UPPER: | |
| 422 switch (next_mode) { | |
| 423 case GM_CHINESE: bp = bin_append_posn(28, 5, binary, bp); | |
| 424 break; | |
| 425 case GM_NUMBER: bp = bin_append_posn(29, 5, binary, bp); | |
| 426 break; | |
| 427 case GM_LOWER: | |
| 428 case GM_UPPER: bp = bin_append_posn(30, 5, binary, bp); | |
| 429 break; | |
| 430 case GM_MIXED: bp = bin_append_posn(124, 7, binary, bp); | |
| 431 break; | |
| 432 case GM_BYTE: bp = bin_append_posn(126, 7, binary, bp); | |
| 433 break; | |
| 434 } | |
| 435 break; | |
| 436 case GM_MIXED: | |
| 437 switch (next_mode) { | |
| 438 case GM_CHINESE: bp = bin_append_posn(1009, 10, binary, bp); | |
| 439 break; | |
| 440 case GM_NUMBER: bp = bin_append_posn(1010, 10, binary, bp); | |
| 441 break; | |
| 442 case GM_LOWER: bp = bin_append_posn(1011, 10, binary, bp); | |
| 443 break; | |
| 444 case GM_UPPER: bp = bin_append_posn(1012, 10, binary, bp); | |
| 445 break; | |
| 446 case GM_BYTE: bp = bin_append_posn(1015, 10, binary, bp); | |
| 447 break; | |
| 448 } | |
| 449 break; | |
| 450 case GM_BYTE: | |
| 451 /* add byte block length indicator */ | |
| 452 gm_add_byte_count(binary, byte_count_posn, byte_count); | |
| 453 byte_count = 0; | |
| 454 switch (next_mode) { | |
| 455 case GM_CHINESE: bp = bin_append_posn(1, 4, binary, bp); | |
| 456 break; | |
| 457 case GM_NUMBER: bp = bin_append_posn(2, 4, binary, bp); | |
| 458 break; | |
| 459 case GM_LOWER: bp = bin_append_posn(3, 4, binary, bp); | |
| 460 break; | |
| 461 case GM_UPPER: bp = bin_append_posn(4, 4, binary, bp); | |
| 462 break; | |
| 463 case GM_MIXED: bp = bin_append_posn(5, 4, binary, bp); | |
| 464 break; | |
| 465 } | |
| 466 break; | |
| 467 } | |
| 468 if (debug_print) { | |
| 469 switch (next_mode) { | |
| 470 case GM_CHINESE: fputs("CHIN ", stdout); | |
| 471 break; | |
| 472 case GM_NUMBER: fputs("NUMB ", stdout); | |
| 473 break; | |
| 474 case GM_LOWER: fputs("LOWR ", stdout); | |
| 475 break; | |
| 476 case GM_UPPER: fputs("UPPR ", stdout); | |
| 477 break; | |
| 478 case GM_MIXED: fputs("MIXD ", stdout); | |
| 479 break; | |
| 480 case GM_BYTE: fputs("BYTE ", stdout); | |
| 481 break; | |
| 482 } | |
| 483 } | |
| 484 } | |
| 485 last_mode = current_mode; | |
| 486 current_mode = next_mode; | |
| 487 | |
| 488 switch (current_mode) { | |
| 489 case GM_CHINESE: | |
| 490 done = 0; | |
| 491 if (ddata[sp] > 0xff) { | |
| 492 /* GB2312 character */ | |
| 493 c1 = (ddata[sp] & 0xff00) >> 8; | |
| 494 c2 = ddata[sp] & 0xff; | |
| 495 | |
| 496 if ((c1 >= 0xa1) && (c1 <= 0xa9)) { | |
| 497 glyph = (0x60 * (c1 - 0xa1)) + (c2 - 0xa0); | |
| 498 } else if ((c1 >= 0xb0) && (c1 <= 0xf7)) { | |
| 499 glyph = (0x60 * (c1 - 0xb0 + 9)) + (c2 - 0xa0); | |
| 500 } | |
| 501 done = 1; /* GB 2312 always within above ranges */ | |
| 502 /* Note not using the unallocated glyphs 7776 to 8191 mentioned in AIMD014 section 6.3.1.2 */ | |
| 503 } | |
| 504 if (!(done)) { | |
| 505 if (sp != (length - 1)) { | |
| 506 if ((ddata[sp] == 13) && (ddata[sp + 1] == 10)) { | |
| 507 /* End of Line */ | |
| 508 glyph = 7776; | |
| 509 sp++; | |
| 510 done = 1; | |
| 511 } | |
| 512 } | |
| 513 } | |
| 514 if (!(done)) { | |
| 515 if (sp != (length - 1)) { | |
| 516 if (z_isdigit(ddata[sp]) && z_isdigit(ddata[sp + 1])) { | |
| 517 /* Two digits */ | |
| 518 glyph = 8033 + (10 * (ddata[sp] - '0')) + (ddata[sp + 1] - '0'); | |
| 519 sp++; | |
| 520 done = 1; | |
| 521 } | |
| 522 } | |
| 523 } | |
| 524 if (!(done)) { | |
| 525 /* Byte value */ | |
| 526 glyph = 7777 + ddata[sp]; | |
| 527 } | |
| 528 | |
| 529 if (debug_print) { | |
| 530 printf("[%d] ", (int) glyph); | |
| 531 } | |
| 532 | |
| 533 bp = bin_append_posn(glyph, 13, binary, bp); | |
| 534 sp++; | |
| 535 break; | |
| 536 | |
| 537 case GM_NUMBER: | |
| 538 if (last_mode != current_mode) { | |
| 539 /* Reserve a space for numeric digit padding value (2 bits) */ | |
| 540 number_pad_posn = bp; | |
| 541 bp = bin_append_posn(0, 2, binary, bp); | |
| 542 } | |
| 543 p = 0; | |
| 544 ppos = -1; | |
| 545 | |
| 546 /* Numeric compression can also include certain combinations of | |
| 547 non-numeric character */ | |
| 548 | |
| 549 numbuf[0] = '0'; | |
| 550 numbuf[1] = '0'; | |
| 551 numbuf[2] = '0'; | |
| 552 do { | |
| 553 if (z_isdigit(ddata[sp])) { | |
| 554 numbuf[p] = ddata[sp]; | |
| 555 p++; | |
| 556 } else if (posn(gm_numeral_nondigits, (const char) ddata[sp]) != -1) { | |
| 557 if (ppos != -1) { | |
| 558 break; | |
| 559 } | |
| 560 punt = ddata[sp]; | |
| 561 ppos = p; | |
| 562 } else if (sp < (length - 1) && (ddata[sp] == 13) && (ddata[sp + 1] == 10)) { | |
| 563 /* <end of line> */ | |
| 564 if (ppos != -1) { | |
| 565 break; | |
| 566 } | |
| 567 punt = ddata[sp]; | |
| 568 sp++; | |
| 569 ppos = p; | |
| 570 } else { | |
| 571 break; | |
| 572 } | |
| 573 sp++; | |
| 574 } while ((p < 3) && (sp < length) && mode[sp] == GM_NUMBER); | |
| 575 | |
| 576 if (ppos != -1) { | |
| 577 switch (punt) { | |
| 578 case ' ': glyph = 0; | |
| 579 break; | |
| 580 case '+': glyph = 3; | |
| 581 break; | |
| 582 case '-': glyph = 6; | |
| 583 break; | |
| 584 case '.': glyph = 9; | |
| 585 break; | |
| 586 case ',': glyph = 12; | |
| 587 break; | |
| 588 case 13: glyph = 15; | |
| 589 break; | |
| 590 } | |
| 591 glyph += ppos; | |
| 592 glyph += 1000; | |
| 593 | |
| 594 if (debug_print) { | |
| 595 printf("[%d] ", (int) glyph); | |
| 596 } | |
| 597 | |
| 598 bp = bin_append_posn(glyph, 10, binary, bp); | |
| 599 } | |
| 600 | |
| 601 glyph = (100 * (numbuf[0] - '0')) + (10 * (numbuf[1] - '0')) + (numbuf[2] - '0'); | |
| 602 if (debug_print) { | |
| 603 printf("[%d] ", (int) glyph); | |
| 604 } | |
| 605 | |
| 606 bp = bin_append_posn(glyph, 10, binary, bp); | |
| 607 break; | |
| 608 | |
| 609 case GM_BYTE: | |
| 610 if (last_mode != current_mode) { | |
| 611 /* Reserve space for byte block length indicator (9 bits) */ | |
| 612 byte_count_posn = bp; | |
| 613 bp = bin_append_posn(0, 9, binary, bp); | |
| 614 } | |
| 615 glyph = ddata[sp]; | |
| 616 if (byte_count == 512 || (glyph > 0xFF && byte_count == 511)) { | |
| 617 /* Maximum byte block size is 512 bytes. If longer is needed then start a new block */ | |
| 618 if (glyph > 0xFF && byte_count == 511) { /* Split double-byte */ | |
| 619 bp = bin_append_posn(glyph >> 8, 8, binary, bp); | |
| 620 glyph &= 0xFF; | |
| 621 byte_count++; | |
| 622 } | |
| 623 gm_add_byte_count(binary, byte_count_posn, byte_count); | |
| 624 bp = bin_append_posn(7, 4, binary, bp); | |
| 625 byte_count_posn = bp; | |
| 626 bp = bin_append_posn(0, 9, binary, bp); | |
| 627 byte_count = 0; | |
| 628 } | |
| 629 | |
| 630 if (debug_print) { | |
| 631 printf("[%d] ", (int) glyph); | |
| 632 } | |
| 633 bp = bin_append_posn(glyph, glyph > 0xFF ? 16 : 8, binary, bp); | |
| 634 sp++; | |
| 635 byte_count++; | |
| 636 if (glyph > 0xFF) { | |
| 637 byte_count++; | |
| 638 } | |
| 639 break; | |
| 640 | |
| 641 case GM_MIXED: | |
| 642 shift = 1; | |
| 643 if (z_isdigit(ddata[sp])) { | |
| 644 shift = 0; | |
| 645 } else if (z_isupper(ddata[sp])) { | |
| 646 shift = 0; | |
| 647 } else if (z_islower(ddata[sp])) { | |
| 648 shift = 0; | |
| 649 } else if (ddata[sp] == ' ') { | |
| 650 shift = 0; | |
| 651 } | |
| 652 | |
| 653 if (shift == 0) { | |
| 654 /* Mixed Mode character */ | |
| 655 glyph = posn(EUROPIUM, (const char) ddata[sp]); | |
| 656 if (debug_print) { | |
| 657 printf("[%d] ", (int) glyph); | |
| 658 } | |
| 659 | |
| 660 bp = bin_append_posn(glyph, 6, binary, bp); | |
| 661 } else { | |
| 662 /* Shift Mode character */ | |
| 663 bp = bin_append_posn(1014, 10, binary, bp); /* shift indicator */ | |
| 664 bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print); | |
| 665 } | |
| 666 | |
| 667 sp++; | |
| 668 break; | |
| 669 | |
| 670 case GM_UPPER: | |
| 671 shift = 1; | |
| 672 if (z_isupper(ddata[sp])) { | |
| 673 shift = 0; | |
| 674 } else if (ddata[sp] == ' ') { | |
| 675 shift = 0; | |
| 676 } | |
| 677 | |
| 678 if (shift == 0) { | |
| 679 /* Upper Case character */ | |
| 680 glyph = posn(EUROPIUM_UPR, (const char) ddata[sp]); | |
| 681 if (debug_print) { | |
| 682 printf("[%d] ", (int) glyph); | |
| 683 } | |
| 684 | |
| 685 bp = bin_append_posn(glyph, 5, binary, bp); | |
| 686 } else { | |
| 687 /* Shift Mode character */ | |
| 688 bp = bin_append_posn(125, 7, binary, bp); /* shift indicator */ | |
| 689 bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print); | |
| 690 } | |
| 691 | |
| 692 sp++; | |
| 693 break; | |
| 694 | |
| 695 case GM_LOWER: | |
| 696 shift = 1; | |
| 697 if (z_islower(ddata[sp])) { | |
| 698 shift = 0; | |
| 699 } else if (ddata[sp] == ' ') { | |
| 700 shift = 0; | |
| 701 } | |
| 702 | |
| 703 if (shift == 0) { | |
| 704 /* Lower Case character */ | |
| 705 glyph = posn(EUROPIUM_LWR, (const char) ddata[sp]); | |
| 706 if (debug_print) { | |
| 707 printf("[%d] ", (int) glyph); | |
| 708 } | |
| 709 | |
| 710 bp = bin_append_posn(glyph, 5, binary, bp); | |
| 711 } else { | |
| 712 /* Shift Mode character */ | |
| 713 bp = bin_append_posn(125, 7, binary, bp); /* shift indicator */ | |
| 714 bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print); | |
| 715 } | |
| 716 | |
| 717 sp++; | |
| 718 break; | |
| 719 } | |
| 720 if (bp > 9191) { | |
| 721 return ZINT_ERROR_TOO_LONG; | |
| 722 } | |
| 723 | |
| 724 } while (sp < length); | |
| 725 | |
| 726 if (current_mode == GM_NUMBER) { | |
| 727 /* add numeric block padding value */ | |
| 728 switch (p) { | |
| 729 case 1: binary[number_pad_posn] = '1'; | |
| 730 binary[number_pad_posn + 1] = '0'; | |
| 731 break; /* 2 pad digits */ | |
| 732 case 2: binary[number_pad_posn] = '0'; | |
| 733 binary[number_pad_posn + 1] = '1'; | |
| 734 break; /* 1 pad digit */ | |
| 735 case 3: binary[number_pad_posn] = '0'; | |
| 736 binary[number_pad_posn + 1] = '0'; | |
| 737 break; /* 0 pad digits */ | |
| 738 } | |
| 739 } | |
| 740 | |
| 741 if (current_mode == GM_BYTE) { | |
| 742 /* Add byte block length indicator */ | |
| 743 gm_add_byte_count(binary, byte_count_posn, byte_count); | |
| 744 } | |
| 745 | |
| 746 /* Add "end of data" character */ | |
| 747 switch (current_mode) { | |
| 748 case GM_CHINESE: bp = bin_append_posn(8160, 13, binary, bp); | |
| 749 break; | |
| 750 case GM_NUMBER: bp = bin_append_posn(1018, 10, binary, bp); | |
| 751 break; | |
| 752 case GM_LOWER: | |
| 753 case GM_UPPER: bp = bin_append_posn(27, 5, binary, bp); | |
| 754 break; | |
| 755 case GM_MIXED: bp = bin_append_posn(1008, 10, binary, bp); | |
| 756 break; | |
| 757 case GM_BYTE: bp = bin_append_posn(0, 4, binary, bp); | |
| 758 break; | |
| 759 } | |
| 760 | |
| 761 if (bp > 9191) { | |
| 762 return ZINT_ERROR_TOO_LONG; | |
| 763 } | |
| 764 | |
| 765 *p_bp = bp; | |
| 766 | |
| 767 if (debug_print) { | |
| 768 printf("\nBinary (%d): %.*s\n", bp, bp, binary); | |
| 769 } | |
| 770 | |
| 771 return 0; | |
| 772 } | |
| 773 | |
| 774 static int gm_encode_segs(unsigned int ddata[], const struct zint_seg segs[], const int seg_count, char binary[], | |
| 775 const int reader, const struct zint_structapp *p_structapp, int *p_bin_len, const int debug_print) { | |
| 776 int i; | |
| 777 unsigned int *dd = ddata; | |
| 778 int bp = 0; | |
| 779 int p; | |
| 780 | |
| 781 if (reader && (!p_structapp || p_structapp->index == 1)) { /* Appears only in 1st symbol if Structured Append */ | |
| 782 bp = bin_append_posn(10, 4, binary, bp); /* FNC3 - Reader Initialisation */ | |
| 783 } | |
| 784 | |
| 785 if (p_structapp) { | |
| 786 bp = bin_append_posn(9, 4, binary, bp); /* FNC2 - Structured Append */ | |
| 787 bp = bin_append_posn(to_int((const unsigned char *) p_structapp->id, (int) strlen(p_structapp->id)), 8, | |
| 788 binary, bp); /* File signature */ | |
| 789 bp = bin_append_posn(p_structapp->count - 1, 4, binary, bp); | |
| 790 bp = bin_append_posn(p_structapp->index - 1, 4, binary, bp); | |
| 791 } | |
| 792 | |
| 793 for (i = 0; i < seg_count; i++) { | |
| 794 int error_number = gm_encode(dd, segs[i].length, binary, segs[i].eci, &bp, debug_print); | |
| 795 if (error_number != 0) { | |
| 796 return error_number; | |
| 797 } | |
| 798 dd += segs[i].length; | |
| 799 } | |
| 800 | |
| 801 /* Add padding bits if required */ | |
| 802 p = 7 - (bp % 7); | |
| 803 if (p % 7) { | |
| 804 bp = bin_append_posn(0, p, binary, bp); | |
| 805 } | |
| 806 /* Note bit-padding can't tip `bp` over max 9191 (1313 * 7) */ | |
| 807 | |
| 808 if (debug_print) { | |
| 809 printf("\nBinary (%d): %.*s\n", bp, bp, binary); | |
| 810 } | |
| 811 | |
| 812 *p_bin_len = bp; | |
| 813 | |
| 814 return 0; | |
| 815 } | |
| 816 | |
| 817 static void gm_add_ecc(const char binary[], const int data_posn, const int layers, const int ecc_level, | |
| 818 unsigned char word[]) { | |
| 819 int data_cw, i, j, wp, p; | |
| 820 int n1, b1, n2, b2, e1, b3, e2; | |
| 821 int block_size, ecc_size; | |
| 822 unsigned char data[1320], block[130]; | |
| 823 unsigned char data_block[115], ecc_block[70]; | |
| 824 rs_t rs; | |
| 825 | |
| 826 data_cw = gm_data_codewords[((layers - 1) * 5) + (ecc_level - 1)]; | |
| 827 | |
| 828 for (i = 0; i < 1320; i++) { | |
| 829 data[i] = 0; | |
| 830 } | |
| 831 | |
| 832 /* Convert from binary stream to 7-bit codewords */ | |
| 833 for (i = 0; i < data_posn; i++) { | |
| 834 for (p = 0; p < 7; p++) { | |
| 835 if (binary[i * 7 + p] == '1') { | |
| 836 data[i] += (0x40 >> p); | |
| 837 } | |
| 838 } | |
| 839 } | |
| 840 | |
| 841 /* Add padding codewords */ | |
| 842 data[data_posn] = 0x00; | |
| 843 for (i = (data_posn + 1); i < data_cw; i++) { | |
| 844 if (i & 1) { | |
| 845 data[i] = 0x7e; | |
| 846 } else { | |
| 847 data[i] = 0x00; | |
| 848 } | |
| 849 } | |
| 850 | |
| 851 /* Get block sizes */ | |
| 852 n1 = gm_n1[(layers - 1)]; | |
| 853 b1 = gm_b1[(layers - 1)]; | |
| 854 n2 = n1 - 1; | |
| 855 b2 = gm_b2[(layers - 1)]; | |
| 856 e1 = gm_ebeb[((layers - 1) * 20) + ((ecc_level - 1) * 4)]; | |
| 857 b3 = gm_ebeb[((layers - 1) * 20) + ((ecc_level - 1) * 4) + 1]; | |
| 858 e2 = gm_ebeb[((layers - 1) * 20) + ((ecc_level - 1) * 4) + 2]; | |
| 859 | |
| 860 rs_init_gf(&rs, 0x89); | |
| 861 | |
| 862 /* Split the data into blocks */ | |
| 863 wp = 0; | |
| 864 for (i = 0; i < (b1 + b2); i++) { | |
| 865 int data_size; | |
| 866 if (i < b1) { | |
| 867 block_size = n1; | |
| 868 } else { | |
| 869 block_size = n2; | |
| 870 } | |
| 871 if (i < b3) { | |
| 872 ecc_size = e1; | |
| 873 } else { | |
| 874 ecc_size = e2; | |
| 875 } | |
| 876 data_size = block_size - ecc_size; | |
| 877 | |
| 878 /* printf("block %d/%d: data %d / ecc %d\n", i + 1, (b1 + b2), data_size, ecc_size);*/ | |
| 879 | |
| 880 for (j = 0; j < data_size; j++) { | |
| 881 data_block[j] = data[wp]; | |
| 882 wp++; | |
| 883 } | |
| 884 | |
| 885 /* Calculate ECC data for this block */ | |
| 886 rs_init_code(&rs, ecc_size, 1); | |
| 887 rs_encode(&rs, data_size, data_block, ecc_block); | |
| 888 | |
| 889 /* Add error correction data */ | |
| 890 for (j = 0; j < data_size; j++) { | |
| 891 block[j] = data_block[j]; | |
| 892 } | |
| 893 for (j = 0; j < ecc_size; j++) { | |
| 894 block[j + data_size] = ecc_block[j]; | |
| 895 } | |
| 896 | |
| 897 for (j = 0; j < n2; j++) { | |
| 898 word[((b1 + b2) * j) + i] = block[j]; | |
| 899 } | |
| 900 if (block_size == n1) { | |
| 901 word[((b1 + b2) * (n1 - 1)) + i] = block[(n1 - 1)]; | |
| 902 } | |
| 903 } | |
| 904 } | |
| 905 | |
| 906 static void gm_place_macromodule(char grid[], int x, int y, int word1, int word2, int size) { | |
| 907 int i, j; | |
| 908 | |
| 909 i = (x * 6) + 1; | |
| 910 j = (y * 6) + 1; | |
| 911 | |
| 912 if (word2 & 0x40) { | |
| 913 grid[(j * size) + i + 2] = '1'; | |
| 914 } | |
| 915 if (word2 & 0x20) { | |
| 916 grid[(j * size) + i + 3] = '1'; | |
| 917 } | |
| 918 if (word2 & 0x10) { | |
| 919 grid[((j + 1) * size) + i] = '1'; | |
| 920 } | |
| 921 if (word2 & 0x08) { | |
| 922 grid[((j + 1) * size) + i + 1] = '1'; | |
| 923 } | |
| 924 if (word2 & 0x04) { | |
| 925 grid[((j + 1) * size) + i + 2] = '1'; | |
| 926 } | |
| 927 if (word2 & 0x02) { | |
| 928 grid[((j + 1) * size) + i + 3] = '1'; | |
| 929 } | |
| 930 if (word2 & 0x01) { | |
| 931 grid[((j + 2) * size) + i] = '1'; | |
| 932 } | |
| 933 if (word1 & 0x40) { | |
| 934 grid[((j + 2) * size) + i + 1] = '1'; | |
| 935 } | |
| 936 if (word1 & 0x20) { | |
| 937 grid[((j + 2) * size) + i + 2] = '1'; | |
| 938 } | |
| 939 if (word1 & 0x10) { | |
| 940 grid[((j + 2) * size) + i + 3] = '1'; | |
| 941 } | |
| 942 if (word1 & 0x08) { | |
| 943 grid[((j + 3) * size) + i] = '1'; | |
| 944 } | |
| 945 if (word1 & 0x04) { | |
| 946 grid[((j + 3) * size) + i + 1] = '1'; | |
| 947 } | |
| 948 if (word1 & 0x02) { | |
| 949 grid[((j + 3) * size) + i + 2] = '1'; | |
| 950 } | |
| 951 if (word1 & 0x01) { | |
| 952 grid[((j + 3) * size) + i + 3] = '1'; | |
| 953 } | |
| 954 } | |
| 955 | |
| 956 static void gm_place_data_in_grid(unsigned char word[], char grid[], int modules, int size) { | |
| 957 int x, y, macromodule, offset; | |
| 958 | |
| 959 offset = 13 - ((modules - 1) / 2); | |
| 960 for (y = 0; y < modules; y++) { | |
| 961 for (x = 0; x < modules; x++) { | |
| 962 macromodule = gm_macro_matrix[((y + offset) * 27) + (x + offset)]; | |
| 963 gm_place_macromodule(grid, x, y, word[macromodule * 2], word[(macromodule * 2) + 1], size); | |
| 964 } | |
| 965 } | |
| 966 } | |
| 967 | |
| 968 /* Place the layer ID into each macromodule */ | |
| 969 static void gm_place_layer_id(char *grid, int size, int layers, int modules, int ecc_level) { | |
| 970 int i, j, layer, start, stop; | |
| 971 int *layerid = (int *) z_alloca(sizeof(int) * (layers + 1)); | |
| 972 int *id = (int *) z_alloca(sizeof(int) * (modules * modules)); | |
| 973 | |
| 974 /* Calculate Layer IDs */ | |
| 975 for (i = 0; i <= layers; i++) { | |
| 976 if (ecc_level == 1) { | |
| 977 layerid[i] = 3 - (i % 4); | |
| 978 } else { | |
| 979 layerid[i] = (i + 5 - ecc_level) % 4; | |
| 980 } | |
| 981 } | |
| 982 | |
| 983 for (i = 0; i < modules; i++) { | |
| 984 for (j = 0; j < modules; j++) { | |
| 985 id[(i * modules) + j] = 0; | |
| 986 } | |
| 987 } | |
| 988 | |
| 989 /* Calculate which value goes in each macromodule */ | |
| 990 start = modules / 2; | |
| 991 stop = modules / 2; | |
| 992 for (layer = 0; layer <= layers; layer++) { | |
| 993 for (i = start; i <= stop; i++) { | |
| 994 id[(start * modules) + i] = layerid[layer]; | |
| 995 id[(i * modules) + start] = layerid[layer]; | |
| 996 id[((modules - start - 1) * modules) + i] = layerid[layer]; | |
| 997 id[(i * modules) + (modules - start - 1)] = layerid[layer]; | |
| 998 } | |
| 999 start--; | |
| 1000 stop++; | |
| 1001 } | |
| 1002 | |
| 1003 /* Place the data in the grid */ | |
| 1004 for (i = 0; i < modules; i++) { | |
| 1005 for (j = 0; j < modules; j++) { | |
| 1006 if (id[(i * modules) + j] & 0x02) { | |
| 1007 grid[(((i * 6) + 1) * size) + (j * 6) + 1] = '1'; | |
| 1008 } | |
| 1009 if (id[(i * modules) + j] & 0x01) { | |
| 1010 grid[(((i * 6) + 1) * size) + (j * 6) + 2] = '1'; | |
| 1011 } | |
| 1012 } | |
| 1013 } | |
| 1014 } | |
| 1015 | |
| 1016 INTERNAL int gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { | |
| 1017 int warn_number = 0; | |
| 1018 int size, modules, error_number; | |
| 1019 int auto_layers, min_layers, layers, auto_ecc_level, min_ecc_level, ecc_level; | |
| 1020 int x, y, i; | |
| 1021 int full_multibyte; | |
| 1022 char binary[9300]; | |
| 1023 int data_cw, input_latch = 0; | |
| 1024 unsigned char word[1460] = {0}; | |
| 1025 int data_max, reader = 0; | |
| 1026 const struct zint_structapp *p_structapp = NULL; | |
| 1027 int size_squared; | |
| 1028 int bin_len; | |
| 1029 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 1030 const int eci_length_segs = get_eci_length_segs(segs, seg_count); | |
| 1031 struct zint_seg *local_segs = (struct zint_seg *) z_alloca(sizeof(struct zint_seg) * seg_count); | |
| 1032 unsigned int *ddata = (unsigned int *) z_alloca(sizeof(unsigned int) * eci_length_segs); | |
| 1033 char *grid; | |
| 1034 | |
| 1035 segs_cpy(symbol, segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs & protect lengths) */ | |
| 1036 | |
| 1037 /* If ZINT_FULL_MULTIBYTE set use Hanzi mode in DATA_MODE or for non-GB 2312 in UNICODE_MODE */ | |
| 1038 full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; | |
| 1039 | |
| 1040 if ((symbol->input_mode & 0x07) == DATA_MODE) { | |
| 1041 gb2312_cpy_segs(local_segs, seg_count, ddata, full_multibyte); | |
| 1042 } else { | |
| 1043 unsigned int *dd = ddata; | |
| 1044 for (i = 0; i < seg_count; i++) { | |
| 1045 int done = 0; | |
| 1046 if (local_segs[i].eci != 0 && local_segs[i].eci != 29) { /* Unless default or ECI 29 (GB 2312) */ | |
| 1047 /* Try other conversions */ | |
| 1048 error_number = gb2312_utf8_to_eci(local_segs[i].eci, local_segs[i].source, &local_segs[i].length, | |
| 1049 dd, full_multibyte); | |
| 1050 if (error_number == 0) { | |
| 1051 done = 1; | |
| 1052 } else { | |
| 1053 return errtxtf(error_number, symbol, 535, "Invalid character in input for ECI '%d'", | |
| 1054 local_segs[i].eci); | |
| 1055 } | |
| 1056 } | |
| 1057 if (!done) { | |
| 1058 /* Try GB 2312 (EUC-CN) */ | |
| 1059 error_number = gb2312_utf8(symbol, local_segs[i].source, &local_segs[i].length, dd); | |
| 1060 if (error_number != 0) { | |
| 1061 return error_number; | |
| 1062 } | |
| 1063 } | |
| 1064 dd += local_segs[i].length; | |
| 1065 } | |
| 1066 } | |
| 1067 | |
| 1068 if (symbol->output_options & READER_INIT) reader = 1; | |
| 1069 | |
| 1070 if (symbol->structapp.count) { | |
| 1071 if (symbol->structapp.count < 2 || symbol->structapp.count > 16) { | |
| 1072 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 536, | |
| 1073 "Structured Append count '%d' out of range (2 to 16)", symbol->structapp.count); | |
| 1074 } | |
| 1075 if (symbol->structapp.index < 1 || symbol->structapp.index > symbol->structapp.count) { | |
| 1076 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 537, | |
| 1077 "Structured Append index '%1$d' out of range (1 to count %2$d)", | |
| 1078 symbol->structapp.index, symbol->structapp.count); | |
| 1079 } | |
| 1080 if (symbol->structapp.id[0]) { | |
| 1081 int id, id_len; | |
| 1082 | |
| 1083 for (id_len = 1; id_len < 4 && symbol->structapp.id[id_len]; id_len++); | |
| 1084 | |
| 1085 if (id_len > 3) { /* 255 (8 bits) */ | |
| 1086 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 538, | |
| 1087 "Structured Append ID length %d too long (3 digit maximum)", id_len); | |
| 1088 } | |
| 1089 | |
| 1090 id = to_int((const unsigned char *) symbol->structapp.id, id_len); | |
| 1091 if (id == -1) { | |
| 1092 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 539, "Invalid Structured Append ID (digits only)"); | |
| 1093 } | |
| 1094 if (id > 255) { | |
| 1095 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 530, | |
| 1096 "Structured Append ID value '%d' out of range (0 to 255)", id); | |
| 1097 } | |
| 1098 } | |
| 1099 p_structapp = &symbol->structapp; | |
| 1100 } | |
| 1101 | |
| 1102 if (symbol->eci > 811799) { | |
| 1103 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 533, "ECI code '%d' out of range (0 to 811799)", | |
| 1104 symbol->eci); | |
| 1105 } | |
| 1106 | |
| 1107 error_number = gm_encode_segs(ddata, local_segs, seg_count, binary, reader, p_structapp, &bin_len, debug_print); | |
| 1108 if (error_number != 0) { | |
| 1109 return errtxt(error_number, symbol, 531, "Input too long, requires too many codewords (maximum 1313)"); | |
| 1110 } | |
| 1111 | |
| 1112 /* Determine the size of the symbol */ | |
| 1113 data_cw = bin_len / 7; /* Binary length always a multiple of 7 */ | |
| 1114 | |
| 1115 auto_layers = 13; | |
| 1116 for (i = 12; i > 0; i--) { | |
| 1117 if (gm_recommend_cw[(i - 1)] >= data_cw) { | |
| 1118 auto_layers = i; | |
| 1119 } | |
| 1120 } | |
| 1121 min_layers = 13; | |
| 1122 for (i = 12; i > 0; i--) { | |
| 1123 if (gm_max_cw[(i - 1)] >= data_cw) { | |
| 1124 min_layers = i; | |
| 1125 } | |
| 1126 } | |
| 1127 layers = auto_layers; | |
| 1128 | |
| 1129 if ((symbol->option_2 >= 1) && (symbol->option_2 <= 13)) { | |
| 1130 input_latch = 1; | |
| 1131 if (symbol->option_2 >= min_layers) { | |
| 1132 layers = symbol->option_2; | |
| 1133 } else { | |
| 1134 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 534, | |
| 1135 "Input too long for Version %1$d, requires %2$d codewords (maximum %3$d)", | |
| 1136 symbol->option_2, data_cw, gm_max_cw[symbol->option_2 - 1]); | |
| 1137 } | |
| 1138 } | |
| 1139 | |
| 1140 auto_ecc_level = 3; | |
| 1141 if (layers == 1) { | |
| 1142 auto_ecc_level = 5; | |
| 1143 } else if ((layers == 2) || (layers == 3)) { | |
| 1144 auto_ecc_level = 4; | |
| 1145 } | |
| 1146 ecc_level = auto_ecc_level; | |
| 1147 | |
| 1148 min_ecc_level = 1; | |
| 1149 if (layers == 1) { | |
| 1150 min_ecc_level = 4; | |
| 1151 } else if (layers == 2) { | |
| 1152 min_ecc_level = 2; | |
| 1153 } | |
| 1154 | |
| 1155 if ((symbol->option_1 >= 1) && (symbol->option_1 <= 5)) { | |
| 1156 if (symbol->option_1 >= min_ecc_level) { | |
| 1157 ecc_level = symbol->option_1; | |
| 1158 } else { | |
| 1159 ecc_level = min_ecc_level; | |
| 1160 } | |
| 1161 } | |
| 1162 if (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)]) { | |
| 1163 /* If layers user-specified (option_2), try reducing ECC level first */ | |
| 1164 if (input_latch && ecc_level > min_ecc_level) { | |
| 1165 do { | |
| 1166 ecc_level--; | |
| 1167 } while ((data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)]) | |
| 1168 && (ecc_level > min_ecc_level)); | |
| 1169 } | |
| 1170 while (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)] && (layers < 13)) { | |
| 1171 layers++; | |
| 1172 } | |
| 1173 /* ECC min level 1 for layers > 2 */ | |
| 1174 while (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)] && ecc_level > 1) { | |
| 1175 ecc_level--; | |
| 1176 } | |
| 1177 } | |
| 1178 | |
| 1179 data_max = 1313; | |
| 1180 switch (ecc_level) { | |
| 1181 case 2: data_max = 1167; | |
| 1182 break; | |
| 1183 case 3: data_max = 1021; | |
| 1184 break; | |
| 1185 case 4: data_max = 875; | |
| 1186 break; | |
| 1187 case 5: data_max = 729; | |
| 1188 break; | |
| 1189 } | |
| 1190 | |
| 1191 if (data_cw > data_max) { | |
| 1192 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 532, | |
| 1193 "Input too long for ECC level %1$d, requires %2$d codewords (maximum %3$d)", | |
| 1194 ecc_level, data_cw, data_max); | |
| 1195 } | |
| 1196 if (debug_print) { | |
| 1197 printf("Layers: %d, ECC level: %d, Data Codewords: %d\n", layers, ecc_level, data_cw); | |
| 1198 } | |
| 1199 | |
| 1200 gm_add_ecc(binary, data_cw, layers, ecc_level, word); | |
| 1201 #ifdef ZINT_TEST | |
| 1202 if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, word, data_cw); | |
| 1203 #endif | |
| 1204 size = 6 + (layers * 12); | |
| 1205 modules = 1 + (layers * 2); | |
| 1206 size_squared = size * size; | |
| 1207 | |
| 1208 grid = (char *) z_alloca(size_squared); | |
| 1209 memset(grid, '0', size_squared); | |
| 1210 | |
| 1211 gm_place_data_in_grid(word, grid, modules, size); | |
| 1212 gm_place_layer_id(grid, size, layers, modules, ecc_level); | |
| 1213 | |
| 1214 /* Add macromodule frames */ | |
| 1215 for (x = 0; x < modules; x++) { | |
| 1216 int dark = 1 - (x & 1); | |
| 1217 for (y = 0; y < modules; y++) { | |
| 1218 if (dark == 1) { | |
| 1219 for (i = 0; i < 5; i++) { | |
| 1220 grid[((y * 6) * size) + (x * 6) + i] = '1'; | |
| 1221 grid[(((y * 6) + 5) * size) + (x * 6) + i] = '1'; | |
| 1222 grid[(((y * 6) + i) * size) + (x * 6)] = '1'; | |
| 1223 grid[(((y * 6) + i) * size) + (x * 6) + 5] = '1'; | |
| 1224 } | |
| 1225 grid[(((y * 6) + 5) * size) + (x * 6) + 5] = '1'; | |
| 1226 dark = 0; | |
| 1227 } else { | |
| 1228 dark = 1; | |
| 1229 } | |
| 1230 } | |
| 1231 } | |
| 1232 | |
| 1233 /* Copy values to symbol */ | |
| 1234 symbol->width = size; | |
| 1235 symbol->rows = size; | |
| 1236 | |
| 1237 for (x = 0; x < size; x++) { | |
| 1238 for (y = 0; y < size; y++) { | |
| 1239 if (grid[(y * size) + x] == '1') { | |
| 1240 set_module(symbol, y, x); | |
| 1241 } | |
| 1242 } | |
| 1243 symbol->row_height[x] = 1; | |
| 1244 } | |
| 1245 symbol->height = size; | |
| 1246 | |
| 1247 return warn_number; | |
| 1248 } | |
| 1249 | |
| 1250 /* vim: set ts=4 sw=4 et : */ |
