Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/zint/backend/code1.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 /* code1.c - USS Code One */ | |
| 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 #include <assert.h> | |
| 34 #include <math.h> | |
| 35 #include <stdio.h> | |
| 36 #include "common.h" | |
| 37 #include "code1.h" | |
| 38 #include "reedsol.h" | |
| 39 #include "large.h" | |
| 40 | |
| 41 #define C1_MAX_CWS 1480 /* Max data codewords for Version H */ | |
| 42 #define C1_MAX_CWS_S "1480" /* String version of above */ | |
| 43 #define C1_MAX_ECCS 560 /* Max ECC codewords for Version H */ | |
| 44 | |
| 45 #define C1_ASCII 1 | |
| 46 #define C1_C40 2 | |
| 47 #define C1_DECIMAL 3 | |
| 48 #define C1_TEXT 4 | |
| 49 #define C1_EDI 5 | |
| 50 #define C1_BYTE 6 | |
| 51 | |
| 52 /* Add solid bar */ | |
| 53 static void c1_horiz(struct zint_symbol *symbol, const int row_no, const int full) { | |
| 54 int i; | |
| 55 | |
| 56 if (full) { | |
| 57 for (i = 0; i < symbol->width; i++) { | |
| 58 set_module(symbol, row_no, i); | |
| 59 } | |
| 60 } else { | |
| 61 for (i = 1; i < symbol->width - 1; i++) { | |
| 62 set_module(symbol, row_no, i); | |
| 63 } | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 /* Central recognition pattern for Versions A-H */ | |
| 68 static void c1_central_finder(struct zint_symbol *symbol, const int start_row, const int row_count, | |
| 69 const int full_rows) { | |
| 70 int i; | |
| 71 | |
| 72 for (i = 0; i < row_count; i++) { | |
| 73 if (i < full_rows) { | |
| 74 c1_horiz(symbol, start_row + (i * 2), 1); | |
| 75 } else { | |
| 76 c1_horiz(symbol, start_row + (i * 2), 0); | |
| 77 if (i != row_count - 1) { | |
| 78 set_module(symbol, start_row + (i * 2) + 1, 1); | |
| 79 set_module(symbol, start_row + (i * 2) + 1, symbol->width - 2); | |
| 80 } | |
| 81 } | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 /* Add solid column */ | |
| 86 static void c1_vert(struct zint_symbol *symbol, const int column, const int height, const int top) { | |
| 87 int i; | |
| 88 | |
| 89 if (top) { | |
| 90 for (i = 0; i < height; i++) { | |
| 91 set_module(symbol, i, column); | |
| 92 } | |
| 93 } else { | |
| 94 for (i = 0; i < height; i++) { | |
| 95 set_module(symbol, symbol->rows - i - 1, column); | |
| 96 } | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 /* Add bump to the right of the vertical recognition pattern column (Versions A-H) */ | |
| 101 static void c1_spigot(struct zint_symbol *symbol, const int row_no) { | |
| 102 int i; | |
| 103 | |
| 104 for (i = symbol->width - 1; i > 0; i--) { | |
| 105 if (module_is_set(symbol, row_no, i - 1)) { | |
| 106 set_module(symbol, row_no, i); | |
| 107 } | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 /* Is basic (non-shifted) C40? */ | |
| 112 static int c1_isc40(const unsigned char input) { | |
| 113 if (z_isdigit(input) || z_isupper(input) || input == ' ') { | |
| 114 return 1; | |
| 115 } | |
| 116 return 0; | |
| 117 } | |
| 118 | |
| 119 /* Is basic (non-shifted) TEXT? */ | |
| 120 static int c1_istext(const unsigned char input) { | |
| 121 if (z_isdigit(input) || z_islower(input) || input == ' ') { | |
| 122 return 1; | |
| 123 } | |
| 124 return 0; | |
| 125 } | |
| 126 | |
| 127 /* Is basic (non-shifted) C40/TEXT? */ | |
| 128 static int c1_isc40text(const int current_mode, const unsigned char input) { | |
| 129 return current_mode == C1_C40 ? c1_isc40(input) : c1_istext(input); | |
| 130 } | |
| 131 | |
| 132 /* EDI characters are uppercase alphanumerics plus space plus EDI terminator (CR) plus 2 EDI separator chars */ | |
| 133 static int c1_isedi(const unsigned char input) { | |
| 134 | |
| 135 if (c1_isc40(input)) { | |
| 136 return 1; | |
| 137 } | |
| 138 if (input == 13 || input == '*' || input == '>') { | |
| 139 return 1; | |
| 140 } | |
| 141 | |
| 142 return 0; | |
| 143 } | |
| 144 | |
| 145 /* Whether Step Q4bi applies, i.e. if one of the 3 EDI terminator/separator chars appears before a non-EDI char */ | |
| 146 static int c1_is_step_Q4bi_applicable(const unsigned char source[], const int length, const int position) { | |
| 147 int i; | |
| 148 | |
| 149 for (i = position; i < length && c1_isedi(source[i]); i++) { | |
| 150 if (source[i] == 13 || source[i] == '*' || source[i] == '>') { | |
| 151 return 1; | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 return 0; | |
| 156 } | |
| 157 | |
| 158 /* Character counts are multiplied by this, so as to be whole integer divisible by 2 and 3 */ | |
| 159 #define C1_MULT 6 | |
| 160 | |
| 161 #define C1_MULT_1_DIV_2 3 | |
| 162 #define C1_MULT_2_DIV_3 4 | |
| 163 #define C1_MULT_1 6 | |
| 164 #define C1_MULT_4_DIV_3 8 | |
| 165 #define C1_MULT_2 12 | |
| 166 #define C1_MULT_8_DIV_3 16 | |
| 167 #define C1_MULT_3 18 | |
| 168 #define C1_MULT_10_DIV_3 20 | |
| 169 #define C1_MULT_13_DIV_3 26 | |
| 170 | |
| 171 #define C1_MULT_MINUS_1 5 | |
| 172 #define C1_MULT_CEIL(n) ((((n) + C1_MULT_MINUS_1) / C1_MULT) * C1_MULT) | |
| 173 | |
| 174 /* AIM USS Code One Annex D Steps J-R */ | |
| 175 static int c1_look_ahead_test(const unsigned char source[], const int length, const int position, | |
| 176 const int current_mode, const int gs1) { | |
| 177 int ascii_count, c40_count, text_count, edi_count, byte_count; | |
| 178 int ascii_rnded, c40_rnded, text_rnded, edi_rnded, byte_rnded; | |
| 179 int cnt_1; | |
| 180 int sp; | |
| 181 | |
| 182 /* Step J1 */ | |
| 183 if (current_mode == C1_ASCII) { | |
| 184 ascii_count = 0; | |
| 185 c40_count = C1_MULT_1; | |
| 186 text_count = C1_MULT_1; | |
| 187 edi_count = C1_MULT_1; | |
| 188 byte_count = C1_MULT_2; | |
| 189 } else { | |
| 190 ascii_count = C1_MULT_1; | |
| 191 c40_count = C1_MULT_2; | |
| 192 text_count = C1_MULT_2; | |
| 193 edi_count = C1_MULT_2; | |
| 194 byte_count = C1_MULT_3; | |
| 195 } | |
| 196 | |
| 197 switch (current_mode) { | |
| 198 case C1_C40: c40_count = 0; /* Step J2 */ | |
| 199 break; | |
| 200 case C1_TEXT: text_count = 0; /* Step J3 */ | |
| 201 break; | |
| 202 case C1_EDI: edi_count = 0; /* Missing in spec */ | |
| 203 break; | |
| 204 case C1_BYTE: byte_count = 0; /* Step J4 */ | |
| 205 break; | |
| 206 } | |
| 207 | |
| 208 for (sp = position; sp < length; sp++) { | |
| 209 const unsigned char c = source[sp]; | |
| 210 const int is_extended = c & 0x80; | |
| 211 | |
| 212 /* Step L */ | |
| 213 if (z_isdigit(c)) { | |
| 214 ascii_count += C1_MULT_1_DIV_2; /* Step L1 */ | |
| 215 } else { | |
| 216 if (is_extended) { | |
| 217 ascii_count = ceilf(ascii_count) + C1_MULT_2; /* Step L2 */ | |
| 218 } else { | |
| 219 ascii_count = ceilf(ascii_count) + C1_MULT_1; /* Step L3 */ | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 /* Step M */ | |
| 224 if (c1_isc40(c)) { | |
| 225 c40_count += C1_MULT_2_DIV_3; /* Step M1 */ | |
| 226 } else if (is_extended) { | |
| 227 c40_count += C1_MULT_8_DIV_3; /* Step M2 */ | |
| 228 } else { | |
| 229 c40_count += C1_MULT_4_DIV_3; /* Step M3 */ | |
| 230 } | |
| 231 | |
| 232 /* Step N */ | |
| 233 if (c1_istext(c)) { | |
| 234 text_count += C1_MULT_2_DIV_3; /* Step N1 */ | |
| 235 } else if (is_extended) { | |
| 236 text_count += C1_MULT_8_DIV_3; /* Step N2 */ | |
| 237 } else { | |
| 238 text_count += C1_MULT_4_DIV_3; /* Step N3 */ | |
| 239 } | |
| 240 | |
| 241 /* Step O */ | |
| 242 if (c1_isedi(c)) { | |
| 243 edi_count += C1_MULT_2_DIV_3; /* Step O1 */ | |
| 244 } else if (is_extended) { | |
| 245 edi_count += C1_MULT_13_DIV_3; /* Step O2 */ | |
| 246 } else { | |
| 247 edi_count += C1_MULT_10_DIV_3; /* Step O3 */ | |
| 248 } | |
| 249 | |
| 250 /* Step P */ | |
| 251 if (gs1 && c == '\x1D') { | |
| 252 byte_count += C1_MULT_3; /* Step P1 */ | |
| 253 } else { | |
| 254 byte_count += C1_MULT_1; /* Step P2 */ | |
| 255 } | |
| 256 | |
| 257 /* If at least 4 characters processed */ | |
| 258 /* NOTE: different than spec, where it's at least 3, but that ends up suppressing C40/TEXT/EDI. | |
| 259 BWIPP also uses 4 (cf very similar Data Matrix ISO/IEC 16022:2006 Annex P algorithm) */ | |
| 260 if (sp >= position + 3) { | |
| 261 /* Step Q */ | |
| 262 ascii_rnded = C1_MULT_CEIL(ascii_count); | |
| 263 c40_rnded = C1_MULT_CEIL(c40_count); | |
| 264 text_rnded = C1_MULT_CEIL(text_count); | |
| 265 edi_rnded = C1_MULT_CEIL(edi_count); | |
| 266 byte_rnded = C1_MULT_CEIL(byte_count); | |
| 267 | |
| 268 cnt_1 = byte_count + C1_MULT_1; | |
| 269 if (cnt_1 <= ascii_rnded && cnt_1 <= c40_rnded && cnt_1 <= text_rnded && cnt_1 <= edi_rnded) { | |
| 270 return C1_BYTE; /* Step Q1 */ | |
| 271 } | |
| 272 cnt_1 = ascii_count + C1_MULT_1; | |
| 273 if (cnt_1 <= c40_rnded && cnt_1 <= text_rnded && cnt_1 <= edi_rnded && cnt_1 <= byte_rnded) { | |
| 274 return C1_ASCII; /* Step Q2 */ | |
| 275 } | |
| 276 cnt_1 = text_rnded + C1_MULT_1; | |
| 277 if (cnt_1 <= ascii_rnded && cnt_1 <= c40_rnded && cnt_1 <= edi_rnded && cnt_1 <= byte_rnded) { | |
| 278 return C1_TEXT; /* Step Q3 */ | |
| 279 } | |
| 280 cnt_1 = c40_rnded + C1_MULT_1; | |
| 281 if (cnt_1 <= ascii_rnded && cnt_1 <= text_rnded) { | |
| 282 /* Step Q4 */ | |
| 283 if (c40_rnded < edi_rnded) { | |
| 284 return C1_C40; /* Step Q4a */ | |
| 285 } | |
| 286 if (c40_rnded == edi_rnded) { | |
| 287 /* Step Q4b */ | |
| 288 if (c1_is_step_Q4bi_applicable(source, length, sp + 1)) { | |
| 289 return C1_EDI; /* Step Q4bi */ | |
| 290 } | |
| 291 return C1_C40; /* Step Q4bii */ | |
| 292 } | |
| 293 } | |
| 294 cnt_1 = edi_rnded + C1_MULT_1; | |
| 295 if (cnt_1 <= ascii_rnded && cnt_1 <= c40_rnded && cnt_1 <= text_rnded && cnt_1 <= byte_rnded) { | |
| 296 return C1_EDI; /* Step Q5 */ | |
| 297 } | |
| 298 } | |
| 299 } | |
| 300 | |
| 301 /* Step K */ | |
| 302 ascii_rnded = C1_MULT_CEIL(ascii_count); | |
| 303 c40_rnded = C1_MULT_CEIL(c40_count); | |
| 304 text_rnded = C1_MULT_CEIL(text_count); | |
| 305 edi_rnded = C1_MULT_CEIL(edi_count); | |
| 306 byte_rnded = C1_MULT_CEIL(byte_count); | |
| 307 | |
| 308 if (byte_count <= ascii_rnded && byte_count <= c40_rnded && byte_count <= text_rnded && byte_count <= edi_rnded) { | |
| 309 return C1_BYTE; /* Step K1 */ | |
| 310 } | |
| 311 if (ascii_count <= c40_rnded && ascii_count <= text_rnded && ascii_count <= edi_rnded | |
| 312 && ascii_count <= byte_rnded) { | |
| 313 return C1_ASCII; /* Step K2 */ | |
| 314 } | |
| 315 if (c40_rnded <= text_rnded && c40_rnded <= edi_rnded) { | |
| 316 return C1_C40; /* Step K3 */ | |
| 317 } | |
| 318 if (text_rnded <= edi_rnded) { | |
| 319 return C1_TEXT; /* Step K4 */ | |
| 320 } | |
| 321 | |
| 322 return C1_EDI; /* Step K5 */ | |
| 323 } | |
| 324 | |
| 325 /* Whether can fit last character or characters in a single ASCII codeword */ | |
| 326 static int c1_is_last_single_ascii(const unsigned char source[], const int length, const int sp) { | |
| 327 if (length - sp == 1 && source[sp] <= 127) { | |
| 328 return 1; | |
| 329 } | |
| 330 if (length - sp == 2 && is_twodigits(source, length, sp)) { | |
| 331 return 1; | |
| 332 } | |
| 333 return 0; | |
| 334 } | |
| 335 | |
| 336 /* Initialize number of digits array (taken from BWIPP) */ | |
| 337 static void c1_set_num_digits(const unsigned char source[], const int length, int num_digits[]) { | |
| 338 int i; | |
| 339 for (i = length - 1; i >= 0; i--) { | |
| 340 if (z_isdigit(source[i])) { | |
| 341 num_digits[i] = num_digits[i + 1] + 1; | |
| 342 } | |
| 343 } | |
| 344 } | |
| 345 | |
| 346 /* Copy C40/TEXT/EDI triplets from buffer to `target`. Returns elements left in buffer (< 3) */ | |
| 347 static int c1_cte_buffer_transfer(int cte_buffer[6], int cte_p, unsigned target[], int *p_tp) { | |
| 348 int cte_i, cte_e; | |
| 349 int tp = *p_tp; | |
| 350 | |
| 351 cte_e = (cte_p / 3) * 3; | |
| 352 | |
| 353 for (cte_i = 0; cte_i < cte_e; cte_i += 3) { | |
| 354 int iv = (1600 * cte_buffer[cte_i]) + (40 * cte_buffer[cte_i + 1]) + (cte_buffer[cte_i + 2]) + 1; | |
| 355 target[tp++] = iv >> 8; | |
| 356 target[tp++] = iv & 0xFF; | |
| 357 } | |
| 358 | |
| 359 cte_p -= cte_e; | |
| 360 | |
| 361 if (cte_p) { | |
| 362 memmove(cte_buffer, cte_buffer + cte_e, sizeof(int) * cte_p); | |
| 363 } | |
| 364 | |
| 365 *p_tp = tp; | |
| 366 | |
| 367 return cte_p; | |
| 368 } | |
| 369 | |
| 370 /* Copy DECIMAL bytes to `target`. Returns bits left in buffer (< 8) */ | |
| 371 static int c1_decimal_binary_transfer(char decimal_binary[24], int db_p, unsigned int target[], int *p_tp) { | |
| 372 int b_i, b_e, p; | |
| 373 int tp = *p_tp; | |
| 374 | |
| 375 /* Transfer full bytes to target */ | |
| 376 b_e = db_p & 0xF8; | |
| 377 | |
| 378 for (b_i = 0; b_i < b_e; b_i += 8) { | |
| 379 int value = 0; | |
| 380 for (p = 0; p < 8; p++) { | |
| 381 value <<= 1; | |
| 382 value += decimal_binary[b_i + p] == '1'; | |
| 383 } | |
| 384 target[tp++] = value; | |
| 385 } | |
| 386 | |
| 387 db_p &= 0x07; /* Bits remaining */ | |
| 388 | |
| 389 if (db_p) { | |
| 390 memmove(decimal_binary, decimal_binary + b_e, db_p); | |
| 391 } | |
| 392 | |
| 393 *p_tp = tp; | |
| 394 | |
| 395 return db_p; | |
| 396 } | |
| 397 | |
| 398 /* Unlatch to ASCII from DECIMAL mode using 6 ones flag. DECIMAL binary buffer will be empty */ | |
| 399 static int c1_decimal_unlatch(char decimal_binary[24], int db_p, unsigned int target[], int *p_tp, | |
| 400 const int decimal_count, const unsigned char source[], int *p_sp) { | |
| 401 int sp = *p_sp; | |
| 402 int bits_left; | |
| 403 | |
| 404 db_p = bin_append_posn(63, 6, decimal_binary, db_p); /* Unlatch */ | |
| 405 if (db_p >= 8) { | |
| 406 db_p = c1_decimal_binary_transfer(decimal_binary, db_p, target, p_tp); | |
| 407 } | |
| 408 bits_left = (8 - db_p) & 0x07; | |
| 409 if (decimal_count >= 1 && bits_left >= 4) { | |
| 410 db_p = bin_append_posn(ctoi(source[sp]) + 1, 4, decimal_binary, db_p); | |
| 411 sp++; | |
| 412 if (bits_left == 6) { | |
| 413 db_p = bin_append_posn(1, 2, decimal_binary, db_p); | |
| 414 } | |
| 415 (void) c1_decimal_binary_transfer(decimal_binary, db_p, target, p_tp); | |
| 416 | |
| 417 } else if (bits_left) { | |
| 418 if (bits_left >= 4) { | |
| 419 db_p = bin_append_posn(15, 4, decimal_binary, db_p); | |
| 420 } | |
| 421 if (bits_left == 2 || bits_left == 6) { | |
| 422 db_p = bin_append_posn(1, 2, decimal_binary, db_p); | |
| 423 } | |
| 424 (void) c1_decimal_binary_transfer(decimal_binary, db_p, target, p_tp); | |
| 425 } | |
| 426 | |
| 427 *p_sp = sp; | |
| 428 | |
| 429 return 0; | |
| 430 } | |
| 431 | |
| 432 /* Number of codewords remaining in a particular version (may be negative) */ | |
| 433 static int c1_codewords_remaining(struct zint_symbol *symbol, const int tp) { | |
| 434 int i; | |
| 435 | |
| 436 if (symbol->option_2 == 10) { /* Version T */ | |
| 437 if (tp > 24) { | |
| 438 return 38 - tp; | |
| 439 } | |
| 440 if (tp > 10) { | |
| 441 return 24 - tp; | |
| 442 } | |
| 443 return 10 - tp; | |
| 444 } | |
| 445 /* Versions A to H */ | |
| 446 for (i = 6; i >= 0; i--) { | |
| 447 if (tp > c1_data_length[i]) { | |
| 448 return c1_data_length[i + 1] - tp; | |
| 449 } | |
| 450 } | |
| 451 return c1_data_length[0] - tp; | |
| 452 } | |
| 453 | |
| 454 /* Number of C40/TEXT elements needed to encode `input` */ | |
| 455 static int c1_c40text_cnt(const int current_mode, const int gs1, unsigned char input) { | |
| 456 int cnt; | |
| 457 | |
| 458 if (gs1 && input == '\x1D') { | |
| 459 return 2; | |
| 460 } | |
| 461 cnt = 1; | |
| 462 if (input & 0x80) { | |
| 463 cnt += 2; | |
| 464 input -= 128; | |
| 465 } | |
| 466 if ((current_mode == C1_C40 && c1_c40_shift[input]) || (current_mode == C1_TEXT && c1_text_shift[input])) { | |
| 467 cnt += 1; | |
| 468 } | |
| 469 | |
| 470 return cnt; | |
| 471 } | |
| 472 | |
| 473 /* Copy `source` to `eci_buf` with "\NNNNNN" ECI indicator at start and backslashes escaped */ | |
| 474 static void c1_eci_escape(const int eci, unsigned char source[], const int length, unsigned char eci_buf[], | |
| 475 const int eci_length) { | |
| 476 int i, j; | |
| 477 | |
| 478 j = sprintf((char *) eci_buf, "\\%06d", eci); | |
| 479 | |
| 480 for (i = 0; i < length && j < eci_length; i++) { | |
| 481 if (source[i] == '\\') { | |
| 482 eci_buf[j++] = '\\'; | |
| 483 } | |
| 484 eci_buf[j++] = source[i]; | |
| 485 } | |
| 486 eci_buf[j] = '\0'; | |
| 487 } | |
| 488 | |
| 489 /* Convert to codewords */ | |
| 490 static int c1_encode(struct zint_symbol *symbol, unsigned char source[], int length, const int eci, | |
| 491 const int seg_count, const int gs1, unsigned int target[], int *p_tp, int *p_last_mode) { | |
| 492 int current_mode, next_mode, last_mode; | |
| 493 int sp = 0; | |
| 494 int tp = *p_tp; | |
| 495 int i; | |
| 496 int cte_buffer[6], cte_p = 0; /* C1_C40/TEXT/EDI buffer and index */ | |
| 497 char decimal_binary[24]; /* C1_DECIMAL buffer */ | |
| 498 int db_p = 0; | |
| 499 int byte_start = 0; | |
| 500 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 501 const int eci_length = length + 7 + chr_cnt(source, length, '\\'); | |
| 502 unsigned char *eci_buf = (unsigned char *) z_alloca(eci_length + 1); | |
| 503 int *num_digits = (int *) z_alloca(sizeof(int) * (eci_length + 1)); | |
| 504 | |
| 505 memset(num_digits, 0, sizeof(int) * (eci_length + 1)); | |
| 506 | |
| 507 /* Step A */ | |
| 508 current_mode = C1_ASCII; | |
| 509 next_mode = C1_ASCII; | |
| 510 | |
| 511 if (gs1 && tp == 0) { | |
| 512 c1_set_num_digits(source, length, num_digits); | |
| 513 if (length >= 15 && num_digits[0] >= 15) { | |
| 514 target[tp++] = 236; /* FNC1 and change to Decimal */ | |
| 515 next_mode = C1_DECIMAL; | |
| 516 if (debug_print) fputs("FNC1Dec ", stdout); | |
| 517 } else if (length >= 7 && num_digits[0] == length) { | |
| 518 target[tp++] = 236; /* FNC1 and change to Decimal */ | |
| 519 next_mode = C1_DECIMAL; | |
| 520 if (debug_print) fputs("FNC1Dec ", stdout); | |
| 521 } else { | |
| 522 target[tp++] = 232; /* FNC1 */ | |
| 523 if (debug_print) fputs("FNC1 ", stdout); | |
| 524 } | |
| 525 /* Note ignoring Structured Append and ECI if GS1 mode (up to caller to warn/error) */ | |
| 526 } else { | |
| 527 if (symbol->structapp.count && tp == 0) { | |
| 528 if (symbol->structapp.count < 16) { /* Group mode */ | |
| 529 if ((eci || seg_count > 1) && symbol->structapp.index == 1) { | |
| 530 /* Initial pad indicator for 1st symbol only */ | |
| 531 target[tp++] = 129; /* Pad */ | |
| 532 target[tp++] = 233; /* FNC2 */ | |
| 533 target[tp++] = (symbol->structapp.index - 1) * 15 + (symbol->structapp.count - 1); | |
| 534 target[tp++] = '\\' + 1; /* Escape char */ | |
| 535 if (debug_print) fputs("SAGrp ", stdout); | |
| 536 } else { | |
| 537 target[tp++] = (symbol->structapp.index - 1) * 15 + (symbol->structapp.count - 1); | |
| 538 target[tp++] = 233; /* FNC2 */ | |
| 539 if (debug_print) fputs("FNC2 ", stdout); | |
| 540 } | |
| 541 } else { /* Extended Group mode */ | |
| 542 if ((eci || seg_count > 1) && symbol->structapp.index == 1) { | |
| 543 /* Initial pad indicator for 1st symbol only */ | |
| 544 target[tp++] = 129; /* Pad */ | |
| 545 target[tp++] = '\\' + 1; /* Escape char */ | |
| 546 target[tp++] = 233; /* FNC2 */ | |
| 547 target[tp++] = symbol->structapp.index; | |
| 548 target[tp++] = symbol->structapp.count; | |
| 549 if (debug_print) fputs("SAExGrp ", stdout); | |
| 550 } else { | |
| 551 target[tp++] = symbol->structapp.index; | |
| 552 target[tp++] = symbol->structapp.count; | |
| 553 target[tp++] = 233; /* FNC2 */ | |
| 554 if (debug_print) fputs("FNC2 ", stdout); | |
| 555 } | |
| 556 } | |
| 557 if (eci) { | |
| 558 c1_eci_escape(eci, source, length, eci_buf, eci_length); | |
| 559 source = eci_buf; | |
| 560 length = eci_length; | |
| 561 } | |
| 562 } else if (eci || seg_count > 1) { | |
| 563 if (tp == 0) { | |
| 564 target[tp++] = 129; /* Pad */ | |
| 565 target[tp++] = '\\' + 1; /* Escape char */ | |
| 566 if (debug_print) fputs("PADEsc ", stdout); | |
| 567 } | |
| 568 if (eci) { | |
| 569 c1_eci_escape(eci, source, length, eci_buf, eci_length); | |
| 570 source = eci_buf; | |
| 571 length = eci_length; | |
| 572 } | |
| 573 } | |
| 574 c1_set_num_digits(source, length, num_digits); | |
| 575 } | |
| 576 | |
| 577 do { | |
| 578 last_mode = current_mode; | |
| 579 if (current_mode != next_mode) { | |
| 580 /* Change mode */ | |
| 581 switch (next_mode) { | |
| 582 case C1_C40: target[tp++] = 230; | |
| 583 if (debug_print) fputs("->C40 ", stdout); | |
| 584 break; | |
| 585 case C1_TEXT: target[tp++] = 239; | |
| 586 if (debug_print) fputs("->Text ", stdout); | |
| 587 break; | |
| 588 case C1_EDI: target[tp++] = 238; | |
| 589 if (debug_print) fputs("->EDI ", stdout); | |
| 590 break; | |
| 591 case C1_BYTE: target[tp++] = 231; | |
| 592 if (debug_print) fputs("->Byte ", stdout); | |
| 593 byte_start = tp; | |
| 594 target[tp++] = 0; /* Byte count holder (may be expanded to 2 codewords) */ | |
| 595 break; | |
| 596 } | |
| 597 current_mode = next_mode; | |
| 598 } | |
| 599 | |
| 600 if (current_mode == C1_ASCII) { | |
| 601 /* Step B - ASCII encodation */ | |
| 602 next_mode = C1_ASCII; | |
| 603 | |
| 604 if ((length - sp) >= 21 && num_digits[sp] >= 21) { | |
| 605 /* Step B1 */ | |
| 606 next_mode = C1_DECIMAL; | |
| 607 db_p = bin_append_posn(15, 4, decimal_binary, db_p); | |
| 608 } else if ((length - sp) >= 13 && num_digits[sp] == (length - sp)) { | |
| 609 /* Step B2 */ | |
| 610 next_mode = C1_DECIMAL; | |
| 611 db_p = bin_append_posn(15, 4, decimal_binary, db_p); | |
| 612 } | |
| 613 | |
| 614 if (next_mode == C1_ASCII) { | |
| 615 if (is_twodigits(source, length, sp)) { | |
| 616 /* Step B3 */ | |
| 617 target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; | |
| 618 if (debug_print) printf("ASCDD(%.2s) ", source + sp); | |
| 619 sp += 2; | |
| 620 } else { | |
| 621 if (gs1 && source[sp] == '\x1D') { | |
| 622 if (length - (sp + 1) >= 15 && num_digits[sp + 1] >= 15) { | |
| 623 /* Step B4 */ | |
| 624 target[tp++] = 236; /* FNC1 and change to Decimal */ | |
| 625 if (debug_print) fputs("FNC1 ", stdout); | |
| 626 sp++; | |
| 627 next_mode = C1_DECIMAL; | |
| 628 } else if (length - (sp + 1) >= 7 && num_digits[sp + 1] == length - (sp + 1)) { | |
| 629 /* Step B5 */ | |
| 630 target[tp++] = 236; /* FNC1 and change to Decimal */ | |
| 631 if (debug_print) fputs("FNC1 ", stdout); | |
| 632 sp++; | |
| 633 next_mode = C1_DECIMAL; | |
| 634 } | |
| 635 } | |
| 636 | |
| 637 if (next_mode == C1_ASCII) { | |
| 638 | |
| 639 /* Step B6 */ | |
| 640 next_mode = c1_look_ahead_test(source, length, sp, current_mode, gs1); | |
| 641 if (next_mode == last_mode) { /* Avoid looping on latch (ticket #300 (#8) Andre Maute) */ | |
| 642 next_mode = C1_ASCII; | |
| 643 } | |
| 644 | |
| 645 if (next_mode == C1_ASCII) { | |
| 646 if (debug_print) printf("ASC(%d) ", source[sp]); | |
| 647 | |
| 648 if (source[sp] & 0x80) { | |
| 649 /* Step B7 */ | |
| 650 target[tp++] = 235; /* FNC4 (Upper Shift) */ | |
| 651 target[tp++] = (source[sp] - 128) + 1; | |
| 652 if (debug_print) printf("UpSh(%d) ", source[sp]); | |
| 653 } else if (gs1 && source[sp] == '\x1D') { | |
| 654 /* Step B8 */ | |
| 655 target[tp++] = 232; /* FNC1 */ | |
| 656 if (debug_print) fputs("FNC1 ", stdout); | |
| 657 } else { | |
| 658 /* Step B8 */ | |
| 659 target[tp++] = source[sp] + 1; | |
| 660 if (debug_print) printf("ASC(%d) ", source[sp]); | |
| 661 } | |
| 662 sp++; | |
| 663 } | |
| 664 } | |
| 665 } | |
| 666 } | |
| 667 | |
| 668 } else if (current_mode == C1_C40 || current_mode == C1_TEXT) { | |
| 669 /* Step C/D - C40/TEXT encodation */ | |
| 670 | |
| 671 next_mode = current_mode; | |
| 672 if (cte_p == 0) { | |
| 673 /* Step C/D1 */ | |
| 674 if ((length - sp) >= 12 && num_digits[sp] >= 12) { | |
| 675 /* Step C/D1a */ | |
| 676 next_mode = C1_ASCII; | |
| 677 } else if ((length - sp) >= 8 && num_digits[sp] == (length - sp)) { | |
| 678 /* Step C/D1b */ | |
| 679 next_mode = C1_ASCII; | |
| 680 } else { | |
| 681 next_mode = c1_look_ahead_test(source, length, sp, current_mode, gs1); | |
| 682 } | |
| 683 } | |
| 684 | |
| 685 if (next_mode != current_mode) { | |
| 686 /* Step C/D1c */ | |
| 687 target[tp++] = 255; /* Unlatch */ | |
| 688 if (debug_print) fputs("Unlatch ", stdout); | |
| 689 } else { | |
| 690 /* Step C/D2 */ | |
| 691 const char *ct_shift, *ct_value; | |
| 692 | |
| 693 if (current_mode == C1_C40) { | |
| 694 ct_shift = c1_c40_shift; | |
| 695 ct_value = c1_c40_value; | |
| 696 } else { | |
| 697 ct_shift = c1_text_shift; | |
| 698 ct_value = c1_text_value; | |
| 699 } | |
| 700 if (debug_print) fputs(current_mode == C1_C40 ? "C40 " : "TEXT ", stdout); | |
| 701 | |
| 702 if (source[sp] & 0x80) { | |
| 703 cte_buffer[cte_p++] = 1; /* Shift 2 */ | |
| 704 cte_buffer[cte_p++] = 30; /* FNC4 (Upper Shift) */ | |
| 705 if (ct_shift[source[sp] - 128]) { | |
| 706 cte_buffer[cte_p++] = ct_shift[source[sp] - 128] - 1; | |
| 707 } | |
| 708 cte_buffer[cte_p++] = ct_value[source[sp] - 128]; | |
| 709 } else if (gs1 && source[sp] == '\x1D') { | |
| 710 cte_buffer[cte_p++] = 1; /* Shift 2 */ | |
| 711 cte_buffer[cte_p++] = 27; /* FNC1 */ | |
| 712 } else { | |
| 713 if (ct_shift[source[sp]]) { | |
| 714 cte_buffer[cte_p++] = ct_shift[source[sp]] - 1; | |
| 715 } | |
| 716 cte_buffer[cte_p++] = ct_value[source[sp]]; | |
| 717 } | |
| 718 | |
| 719 if (cte_p >= 3) { | |
| 720 cte_p = c1_cte_buffer_transfer(cte_buffer, cte_p, target, &tp); | |
| 721 } | |
| 722 sp++; | |
| 723 } | |
| 724 | |
| 725 } else if (current_mode == C1_EDI) { | |
| 726 /* Step E - EDI Encodation */ | |
| 727 | |
| 728 next_mode = C1_EDI; | |
| 729 if (cte_p == 0) { | |
| 730 /* Step E1 */ | |
| 731 if ((length - sp) >= 12 && num_digits[sp] >= 12) { | |
| 732 /* Step E1a */ | |
| 733 next_mode = C1_ASCII; | |
| 734 } else if ((length - sp) >= 8 && num_digits[sp] == (length - sp)) { | |
| 735 /* Step E1b */ | |
| 736 next_mode = C1_ASCII; | |
| 737 } else if ((length - sp) < 3 || !c1_isedi(source[sp]) || !c1_isedi(source[sp + 1]) | |
| 738 || !c1_isedi(source[sp + 2])) { | |
| 739 /* Step E1c */ | |
| 740 /* This ensures ASCII switch if don't have EDI triplet, so cte_p will be zero on loop exit */ | |
| 741 next_mode = C1_ASCII; | |
| 742 } | |
| 743 } | |
| 744 | |
| 745 if (next_mode != C1_EDI) { | |
| 746 if (c1_is_last_single_ascii(source, length, sp) && c1_codewords_remaining(symbol, tp) == 1) { | |
| 747 /* No unlatch needed if data fits as ASCII in last data codeword */ | |
| 748 } else { | |
| 749 target[tp++] = 255; /* Unlatch */ | |
| 750 if (debug_print) fputs("Unlatch ", stdout); | |
| 751 } | |
| 752 } else { | |
| 753 /* Step E2 */ | |
| 754 static const char edi_nonalphanum_chars[] = "\015*> "; | |
| 755 | |
| 756 if (debug_print) fputs("EDI ", stdout); | |
| 757 | |
| 758 if (z_isdigit(source[sp])) { | |
| 759 cte_buffer[cte_p++] = source[sp] - '0' + 4; | |
| 760 } else if (z_isupper(source[sp])) { | |
| 761 cte_buffer[cte_p++] = source[sp] - 'A' + 14; | |
| 762 } else { | |
| 763 cte_buffer[cte_p++] = posn(edi_nonalphanum_chars, source[sp]); | |
| 764 } | |
| 765 | |
| 766 if (cte_p >= 3) { | |
| 767 cte_p = c1_cte_buffer_transfer(cte_buffer, cte_p, target, &tp); | |
| 768 } | |
| 769 sp++; | |
| 770 } | |
| 771 | |
| 772 } else if (current_mode == C1_DECIMAL) { | |
| 773 /* Step F - Decimal encodation */ | |
| 774 | |
| 775 if (debug_print) fputs("DEC ", stdout); | |
| 776 | |
| 777 next_mode = C1_DECIMAL; | |
| 778 | |
| 779 if (length - sp < 3) { | |
| 780 /* Step F1 */ | |
| 781 const int bits_left = 8 - db_p; | |
| 782 const int can_ascii = bits_left == 8 && c1_is_last_single_ascii(source, length, sp); | |
| 783 if (c1_codewords_remaining(symbol, tp) == 1 | |
| 784 && (can_ascii || (num_digits[sp] == 1 && bits_left >= 4))) { | |
| 785 if (can_ascii) { | |
| 786 /* Encode last character or last 2 digits as ASCII */ | |
| 787 if (is_twodigits(source, length, sp)) { | |
| 788 target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; | |
| 789 if (debug_print) printf("ASCDD(%.2s) ", source + sp); | |
| 790 sp += 2; | |
| 791 } else { | |
| 792 target[tp++] = source[sp] + 1; | |
| 793 if (debug_print) printf("ASC(%d) ", source[sp]); | |
| 794 sp++; | |
| 795 } | |
| 796 } else { | |
| 797 /* Encode last digit in 4 bits */ | |
| 798 db_p = bin_append_posn(ctoi(source[sp]) + 1, 4, decimal_binary, db_p); | |
| 799 sp++; | |
| 800 if (bits_left == 6) { | |
| 801 db_p = bin_append_posn(1, 2, decimal_binary, db_p); | |
| 802 } | |
| 803 db_p = c1_decimal_binary_transfer(decimal_binary, db_p, target, &tp); | |
| 804 } | |
| 805 } else { | |
| 806 db_p = c1_decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp); | |
| 807 current_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */ | |
| 808 } | |
| 809 next_mode = C1_ASCII; | |
| 810 | |
| 811 } else { | |
| 812 if (num_digits[sp] < 3) { | |
| 813 /* Step F2 */ | |
| 814 db_p = c1_decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp); | |
| 815 current_mode = next_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */ | |
| 816 } else { | |
| 817 /* Step F3 */ | |
| 818 /* There are three digits - convert the value to binary */ | |
| 819 int value = (100 * ctoi(source[sp])) + (10 * ctoi(source[sp + 1])) + ctoi(source[sp + 2]) + 1; | |
| 820 db_p = bin_append_posn(value, 10, decimal_binary, db_p); | |
| 821 if (db_p >= 8) { | |
| 822 db_p = c1_decimal_binary_transfer(decimal_binary, db_p, target, &tp); | |
| 823 } | |
| 824 sp += 3; | |
| 825 } | |
| 826 } | |
| 827 | |
| 828 } else if (current_mode == C1_BYTE) { | |
| 829 next_mode = C1_BYTE; | |
| 830 | |
| 831 if (gs1 && source[sp] == '\x1D') { | |
| 832 next_mode = C1_ASCII; | |
| 833 } else { | |
| 834 if (source[sp] <= 127) { | |
| 835 next_mode = c1_look_ahead_test(source, length, sp, current_mode, gs1); | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 if (next_mode != C1_BYTE) { | |
| 840 /* Update byte field length */ | |
| 841 int byte_count = tp - (byte_start + 1); | |
| 842 if (byte_count <= 249) { | |
| 843 target[byte_start] = byte_count; | |
| 844 } else { | |
| 845 /* Insert extra codeword */ | |
| 846 memmove(target + byte_start + 2, target + byte_start + 1, sizeof(unsigned int) * byte_count); | |
| 847 target[byte_start] = 249 + (byte_count / 250); | |
| 848 target[byte_start + 1] = (byte_count % 250); | |
| 849 tp++; | |
| 850 } | |
| 851 } else { | |
| 852 if (debug_print) printf("BYTE(%d) ", source[sp]); | |
| 853 | |
| 854 target[tp++] = source[sp]; | |
| 855 sp++; | |
| 856 } | |
| 857 } | |
| 858 | |
| 859 if (tp > C1_MAX_CWS) { | |
| 860 if (debug_print) fputc('\n', stdout); | |
| 861 /* Data is too large for symbol */ | |
| 862 return 0; | |
| 863 } | |
| 864 } while (sp < length); | |
| 865 | |
| 866 if (debug_print) { | |
| 867 printf("\nEnd Current Mode: %d, tp %d, cte_p %d, db_p %d\n", current_mode, tp, cte_p, db_p); | |
| 868 } | |
| 869 | |
| 870 /* Empty buffers (note cte_buffer will be empty if current_mode C1_EDI) */ | |
| 871 if (current_mode == C1_C40 || current_mode == C1_TEXT) { | |
| 872 if (cte_p >= 1) { | |
| 873 const int cws_remaining = c1_codewords_remaining(symbol, tp); | |
| 874 | |
| 875 /* Note doing strict interpretation of spec here (same as BWIPP), as now also done in Data Matrix case */ | |
| 876 if (cws_remaining == 1 && cte_p == 1 && c1_isc40text(current_mode, source[sp - 1])) { | |
| 877 /* 2.2.2.2 "...except when a single symbol character is left at the end before the first | |
| 878 error correction character. This single character is encoded in the ASCII code set." */ | |
| 879 target[tp++] = source[sp - 1] + 1; /* As ASCII */ | |
| 880 cte_p = 0; | |
| 881 } else if (cws_remaining == 2 && cte_p == 2) { | |
| 882 /* 2.2.2.2 "Two characters may be encoded in C40 mode in the last two data symbol characters of the | |
| 883 symbol as two C40 values followed by one of the C40 shift characters." */ | |
| 884 cte_buffer[cte_p++] = 0; /* Shift 0 */ | |
| 885 cte_p = c1_cte_buffer_transfer(cte_buffer, cte_p, target, &tp); | |
| 886 } | |
| 887 if (cte_p >= 1) { | |
| 888 int cnt, total_cnt = 0; | |
| 889 /* Backtrack to last complete triplet (same technique as BWIPP) */ | |
| 890 while (sp > 0 && cte_p % 3) { | |
| 891 sp--; | |
| 892 cnt = c1_c40text_cnt(current_mode, gs1, source[sp]); | |
| 893 total_cnt += cnt; | |
| 894 cte_p -= cnt; | |
| 895 } | |
| 896 tp -= (total_cnt / 3) * 2; | |
| 897 | |
| 898 target[tp++] = 255; /* Unlatch */ | |
| 899 for (; sp < length; sp++) { | |
| 900 if (is_twodigits(source, length, sp)) { | |
| 901 target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; | |
| 902 sp++; | |
| 903 } else if (source[sp] & 0x80) { | |
| 904 target[tp++] = 235; /* FNC4 (Upper Shift) */ | |
| 905 target[tp++] = (source[sp] - 128) + 1; | |
| 906 } else if (gs1 && source[sp] == '\x1D') { | |
| 907 target[tp++] = 232; /* FNC1 */ | |
| 908 } else { | |
| 909 target[tp++] = source[sp] + 1; | |
| 910 } | |
| 911 } | |
| 912 current_mode = C1_ASCII; | |
| 913 } | |
| 914 } | |
| 915 | |
| 916 } else if (current_mode == C1_DECIMAL) { | |
| 917 int bits_left; | |
| 918 | |
| 919 /* Finish Decimal mode and go back to ASCII unless only one codeword remaining */ | |
| 920 if (c1_codewords_remaining(symbol, tp) > 1) { | |
| 921 db_p = bin_append_posn(63, 6, decimal_binary, db_p); /* Unlatch */ | |
| 922 } | |
| 923 | |
| 924 if (db_p >= 8) { | |
| 925 db_p = c1_decimal_binary_transfer(decimal_binary, db_p, target, &tp); | |
| 926 } | |
| 927 | |
| 928 bits_left = (8 - db_p) & 0x07; | |
| 929 | |
| 930 if (bits_left) { | |
| 931 | |
| 932 if ((bits_left == 4) || (bits_left == 6)) { | |
| 933 db_p = bin_append_posn(15, 4, decimal_binary, db_p); | |
| 934 } | |
| 935 | |
| 936 if (bits_left == 2 || bits_left == 6) { | |
| 937 db_p = bin_append_posn(1, 2, decimal_binary, db_p); | |
| 938 } | |
| 939 | |
| 940 (void) c1_decimal_binary_transfer(decimal_binary, db_p, target, &tp); | |
| 941 } | |
| 942 current_mode = C1_ASCII; | |
| 943 | |
| 944 } else if (current_mode == C1_BYTE) { | |
| 945 /* Update byte field length unless no codewords remaining */ | |
| 946 if (c1_codewords_remaining(symbol, tp) > 0) { | |
| 947 int byte_count = tp - (byte_start + 1); | |
| 948 if (byte_count <= 249) { | |
| 949 target[byte_start] = byte_count; | |
| 950 } else { | |
| 951 /* Insert extra byte field byte */ | |
| 952 memmove(target + byte_start + 2, target + byte_start + 1, sizeof(unsigned int) * byte_count); | |
| 953 target[byte_start] = 249 + (byte_count / 250); | |
| 954 target[byte_start + 1] = (byte_count % 250); | |
| 955 tp++; | |
| 956 } | |
| 957 } | |
| 958 } | |
| 959 | |
| 960 /* Re-check length of data */ | |
| 961 if (tp > C1_MAX_CWS) { | |
| 962 /* Data is too large for symbol */ | |
| 963 return 0; | |
| 964 } | |
| 965 | |
| 966 *p_last_mode = current_mode; | |
| 967 | |
| 968 if (debug_print) { | |
| 969 printf("Target (%d):", tp); | |
| 970 for (i = 0; i < tp; i++) { | |
| 971 printf(" [%d]", (int) target[i]); | |
| 972 } | |
| 973 printf("\nLast Mode: %d\n", *p_last_mode); | |
| 974 } | |
| 975 | |
| 976 return tp; | |
| 977 } | |
| 978 | |
| 979 /* Call `c1_encode()` for each segment */ | |
| 980 static int c1_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count, const int gs1, | |
| 981 unsigned int target[], int *p_last_mode) { | |
| 982 int i; | |
| 983 int tp = 0; | |
| 984 | |
| 985 for (i = 0; i < seg_count; i++) { | |
| 986 tp = c1_encode(symbol, segs[i].source, segs[i].length, segs[i].eci, seg_count, gs1, target, &tp, p_last_mode); | |
| 987 } | |
| 988 | |
| 989 return tp; | |
| 990 } | |
| 991 | |
| 992 /* Set symbol from datagrid */ | |
| 993 static void c1_block_copy(struct zint_symbol *symbol, char datagrid[136][120], const int start_row, | |
| 994 const int start_col, const int height, const int width, const int row_offset, const int col_offset) { | |
| 995 int i, j; | |
| 996 | |
| 997 for (i = start_row; i < (start_row + height); i++) { | |
| 998 for (j = start_col; j < (start_col + width); j++) { | |
| 999 if (datagrid[i][j]) { | |
| 1000 set_module(symbol, i + row_offset, j + col_offset); | |
| 1001 } | |
| 1002 } | |
| 1003 } | |
| 1004 } | |
| 1005 | |
| 1006 /* Get total length allowing for ECIs and escaping backslashes */ | |
| 1007 static int c1_total_length_segs(struct zint_seg segs[], const int seg_count) { | |
| 1008 int total_len = 0; | |
| 1009 int i; | |
| 1010 | |
| 1011 if (segs[0].eci || seg_count > 1) { | |
| 1012 for (i = 0; i < seg_count; i++) { | |
| 1013 total_len += segs[i].length + 7 + chr_cnt(segs[i].source, segs[i].length, '\\'); | |
| 1014 } | |
| 1015 } else { | |
| 1016 total_len = segs[0].length; | |
| 1017 } | |
| 1018 | |
| 1019 return total_len; | |
| 1020 } | |
| 1021 | |
| 1022 INTERNAL int codeone(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { | |
| 1023 int size = 1, i, j; | |
| 1024 char datagrid[136][120]; | |
| 1025 int row, col; | |
| 1026 int sub_version = 0; | |
| 1027 rs_t rs; | |
| 1028 const int gs1 = (symbol->input_mode & 0x07) == GS1_MODE; | |
| 1029 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; | |
| 1030 | |
| 1031 if ((symbol->option_2 < 0) || (symbol->option_2 > 10)) { | |
| 1032 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 513, "Version '%d' out of range (1 to 10)", | |
| 1033 symbol->option_2); | |
| 1034 } | |
| 1035 | |
| 1036 if (symbol->structapp.count) { | |
| 1037 if (symbol->option_2 == 9) { /* Version S */ | |
| 1038 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 714, "Structured Append not available for Version S"); | |
| 1039 } | |
| 1040 if (gs1) { | |
| 1041 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 710, | |
| 1042 "Cannot have Structured Append and GS1 mode at the same time"); | |
| 1043 } | |
| 1044 if (symbol->structapp.count < 2 || symbol->structapp.count > 128) { | |
| 1045 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 711, | |
| 1046 "Structured Append count '%d' out of range (2 to 128)", symbol->structapp.count); | |
| 1047 } | |
| 1048 if (symbol->structapp.index < 1 || symbol->structapp.index > symbol->structapp.count) { | |
| 1049 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 712, | |
| 1050 "Structured Append index '%1$d' out of range (1 to count %2$d)", | |
| 1051 symbol->structapp.index, symbol->structapp.count); | |
| 1052 } | |
| 1053 if (symbol->structapp.id[0]) { | |
| 1054 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 713, "Structured Append ID not available for Code One"); | |
| 1055 } | |
| 1056 } | |
| 1057 | |
| 1058 if (symbol->option_2 == 9) { | |
| 1059 /* Version S */ | |
| 1060 int codewords; | |
| 1061 large_uint elreg; | |
| 1062 unsigned int target[30], ecc[15]; | |
| 1063 int block_width; | |
| 1064 | |
| 1065 if (seg_count > 1) { | |
| 1066 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 715, "Multiple segments not supported for Version S"); | |
| 1067 } | |
| 1068 if (segs[0].length > 18) { | |
| 1069 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 514, "Input length %d too long for Version S (maximum 18)", | |
| 1070 segs[0].length); | |
| 1071 } | |
| 1072 if ((i = not_sane(NEON_F, segs[0].source, segs[0].length))) { | |
| 1073 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 515, | |
| 1074 "Invalid character at position %d in input (Version S encodes digits only)", i); | |
| 1075 } | |
| 1076 | |
| 1077 size = 9; | |
| 1078 if (segs[0].length <= 6) { | |
| 1079 /* Version S-10 */ | |
| 1080 sub_version = 1; | |
| 1081 codewords = 4; | |
| 1082 block_width = 2; | |
| 1083 } else if (segs[0].length <= 12) { | |
| 1084 /* Version S-20 */ | |
| 1085 sub_version = 2; | |
| 1086 codewords = 8; | |
| 1087 block_width = 4; | |
| 1088 } else { | |
| 1089 /* Version S-30 */ | |
| 1090 sub_version = 3; | |
| 1091 codewords = 12; | |
| 1092 block_width = 6; | |
| 1093 } | |
| 1094 | |
| 1095 if (debug_print) { | |
| 1096 printf("Subversion: %d\n", sub_version); | |
| 1097 } | |
| 1098 | |
| 1099 /* Convert value plus one to binary */ | |
| 1100 large_load_str_u64(&elreg, segs[0].source, segs[0].length); | |
| 1101 large_add_u64(&elreg, 1); | |
| 1102 large_uint_array(&elreg, target, codewords, 5 /*bits*/); | |
| 1103 | |
| 1104 rs_init_gf(&rs, 0x25); | |
| 1105 rs_init_code(&rs, codewords, 0); | |
| 1106 rs_encode_uint(&rs, codewords, target, ecc); | |
| 1107 | |
| 1108 for (i = 0; i < codewords; i++) { | |
| 1109 target[i + codewords] = ecc[i]; | |
| 1110 } | |
| 1111 | |
| 1112 if (debug_print) { | |
| 1113 printf("Codewords (%d): ", codewords); | |
| 1114 for (i = 0; i < codewords * 2; i++) printf(" %d", (int) target[i]); | |
| 1115 fputc('\n', stdout); | |
| 1116 } | |
| 1117 | |
| 1118 i = 0; | |
| 1119 for (row = 0; row < 2; row++) { | |
| 1120 for (col = 0; col < block_width; col++) { | |
| 1121 datagrid[row * 2][col * 5] = target[i] & 0x10; | |
| 1122 datagrid[row * 2][(col * 5) + 1] = target[i] & 0x08; | |
| 1123 datagrid[row * 2][(col * 5) + 2] = target[i] & 0x04; | |
| 1124 datagrid[(row * 2) + 1][col * 5] = target[i] & 0x02; | |
| 1125 datagrid[(row * 2) + 1][(col * 5) + 1] = target[i] & 0x01; | |
| 1126 datagrid[row * 2][(col * 5) + 3] = target[i + 1] & 0x10; | |
| 1127 datagrid[row * 2][(col * 5) + 4] = target[i + 1] & 0x08; | |
| 1128 datagrid[(row * 2) + 1][(col * 5) + 2] = target[i + 1] & 0x04; | |
| 1129 datagrid[(row * 2) + 1][(col * 5) + 3] = target[i + 1] & 0x02; | |
| 1130 datagrid[(row * 2) + 1][(col * 5) + 4] = target[i + 1] & 0x01; | |
| 1131 i += 2; | |
| 1132 } | |
| 1133 } | |
| 1134 | |
| 1135 symbol->rows = 8; | |
| 1136 symbol->width = 10 * sub_version + 1; | |
| 1137 | |
| 1138 } else if (symbol->option_2 == 10) { | |
| 1139 /* Version T */ | |
| 1140 unsigned int target[C1_MAX_CWS + C1_MAX_ECCS]; /* Use same buffer size as A to H to avail of loop checks */ | |
| 1141 unsigned int ecc[22]; | |
| 1142 int data_length; | |
| 1143 int data_cw, ecc_cw, block_width; | |
| 1144 int last_mode = 0; /* Suppress gcc 14 "-Wmaybe-uninitialized" false positive */ | |
| 1145 | |
| 1146 if ((i = c1_total_length_segs(segs, seg_count)) > 90) { | |
| 1147 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 519, "Input length %d too long for Version T (maximum 90)", | |
| 1148 i); | |
| 1149 } | |
| 1150 | |
| 1151 data_length = c1_encode_segs(symbol, segs, seg_count, gs1, target, &last_mode); | |
| 1152 | |
| 1153 assert(data_length); /* Can't exceed C1_MAX_CWS as input <= 90 */ | |
| 1154 if (data_length > 38) { | |
| 1155 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 516, | |
| 1156 "Input too long for Version T, requires %d codewords (maximum 38)", data_length); | |
| 1157 } | |
| 1158 | |
| 1159 size = 10; | |
| 1160 if (data_length <= 10) { | |
| 1161 sub_version = 1; | |
| 1162 data_cw = 10; | |
| 1163 ecc_cw = 10; | |
| 1164 block_width = 4; | |
| 1165 } else if (data_length <= 24) { | |
| 1166 sub_version = 2; | |
| 1167 data_cw = 24; | |
| 1168 ecc_cw = 16; | |
| 1169 block_width = 8; | |
| 1170 } else { | |
| 1171 sub_version = 3; | |
| 1172 data_cw = 38; | |
| 1173 ecc_cw = 22; | |
| 1174 block_width = 12; | |
| 1175 } | |
| 1176 | |
| 1177 if (debug_print) { | |
| 1178 printf("Padding: %d, Subversion: %d\n", data_cw - data_length, sub_version); | |
| 1179 } | |
| 1180 | |
| 1181 /* If require padding */ | |
| 1182 if (data_cw > data_length) { | |
| 1183 /* If did not finish in ASCII or BYTE mode, switch to ASCII */ | |
| 1184 if (last_mode != C1_ASCII && last_mode != C1_BYTE) { | |
| 1185 target[data_length++] = 255; /* Unlatch */ | |
| 1186 } | |
| 1187 for (i = data_length; i < data_cw; i++) { | |
| 1188 target[i] = 129; /* Pad */ | |
| 1189 } | |
| 1190 } | |
| 1191 | |
| 1192 /* Calculate error correction data */ | |
| 1193 rs_init_gf(&rs, 0x12d); | |
| 1194 rs_init_code(&rs, ecc_cw, 0); | |
| 1195 rs_encode_uint(&rs, data_cw, target, ecc); | |
| 1196 | |
| 1197 for (i = 0; i < ecc_cw; i++) { | |
| 1198 target[data_cw + i] = ecc[i]; | |
| 1199 } | |
| 1200 | |
| 1201 if (debug_print) { | |
| 1202 printf("Codewords (%d):", data_cw + ecc_cw); | |
| 1203 for (i = 0; i < data_cw + ecc_cw; i++) printf(" %d", (int) target[i]); | |
| 1204 fputc('\n', stdout); | |
| 1205 } | |
| 1206 | |
| 1207 i = 0; | |
| 1208 for (row = 0; row < 5; row++) { | |
| 1209 for (col = 0; col < block_width; col++) { | |
| 1210 datagrid[row * 2][col * 4] = target[i] & 0x80; | |
| 1211 datagrid[row * 2][(col * 4) + 1] = target[i] & 0x40; | |
| 1212 datagrid[row * 2][(col * 4) + 2] = target[i] & 0x20; | |
| 1213 datagrid[row * 2][(col * 4) + 3] = target[i] & 0x10; | |
| 1214 datagrid[(row * 2) + 1][col * 4] = target[i] & 0x08; | |
| 1215 datagrid[(row * 2) + 1][(col * 4) + 1] = target[i] & 0x04; | |
| 1216 datagrid[(row * 2) + 1][(col * 4) + 2] = target[i] & 0x02; | |
| 1217 datagrid[(row * 2) + 1][(col * 4) + 3] = target[i] & 0x01; | |
| 1218 i++; | |
| 1219 } | |
| 1220 } | |
| 1221 | |
| 1222 symbol->rows = 16; | |
| 1223 symbol->width = (sub_version * 16) + 1; | |
| 1224 | |
| 1225 } else { | |
| 1226 /* Versions A to H */ | |
| 1227 unsigned int target[C1_MAX_CWS + C1_MAX_ECCS]; | |
| 1228 unsigned int sub_data[185], sub_ecc[70]; | |
| 1229 int data_length; | |
| 1230 int data_cw; | |
| 1231 int blocks, data_blocks, ecc_blocks, ecc_length; | |
| 1232 int last_mode; | |
| 1233 | |
| 1234 data_length = c1_encode_segs(symbol, segs, seg_count, gs1, target, &last_mode); | |
| 1235 | |
| 1236 if (data_length == 0) { | |
| 1237 return errtxt(ZINT_ERROR_TOO_LONG, symbol, 517, | |
| 1238 "Input too long, requires too many codewords (maximum " C1_MAX_CWS_S ")"); | |
| 1239 } | |
| 1240 | |
| 1241 for (i = 7; i >= 0; i--) { | |
| 1242 if (c1_data_length[i] >= data_length) { | |
| 1243 size = i + 1; | |
| 1244 } | |
| 1245 } | |
| 1246 | |
| 1247 if (symbol->option_2 > size) { | |
| 1248 size = symbol->option_2; | |
| 1249 } | |
| 1250 | |
| 1251 if ((symbol->option_2 != 0) && (symbol->option_2 < size)) { | |
| 1252 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 518, | |
| 1253 "Input too long for Version %1$c, requires %2$d codewords (maximum %3$d)", | |
| 1254 'A' + symbol->option_2 - 1, data_length, c1_data_length[symbol->option_2 - 1]); | |
| 1255 } | |
| 1256 data_cw = c1_data_length[size - 1]; | |
| 1257 | |
| 1258 /* If require padding */ | |
| 1259 if (data_cw > data_length) { | |
| 1260 /* If did not finish in ASCII or BYTE mode, switch to ASCII */ | |
| 1261 if (last_mode != C1_ASCII && last_mode != C1_BYTE) { | |
| 1262 target[data_length++] = 255; /* Unlatch */ | |
| 1263 } | |
| 1264 if (debug_print) { | |
| 1265 printf("Padding: %d\n", data_cw - data_length); | |
| 1266 } | |
| 1267 for (i = data_length; i < data_cw; i++) { | |
| 1268 target[i] = 129; /* Pad */ | |
| 1269 } | |
| 1270 } else if (debug_print) { | |
| 1271 fputs("No padding\n", stdout); | |
| 1272 } | |
| 1273 | |
| 1274 /* Calculate error correction data */ | |
| 1275 blocks = c1_blocks[size - 1]; | |
| 1276 data_blocks = c1_data_blocks[size - 1]; | |
| 1277 ecc_blocks = c1_ecc_blocks[size - 1]; | |
| 1278 ecc_length = c1_ecc_length[size - 1]; | |
| 1279 | |
| 1280 rs_init_gf(&rs, 0x12d); | |
| 1281 rs_init_code(&rs, ecc_blocks, 0); | |
| 1282 for (i = 0; i < blocks; i++) { | |
| 1283 for (j = 0; j < data_blocks; j++) { | |
| 1284 sub_data[j] = target[j * blocks + i]; | |
| 1285 } | |
| 1286 rs_encode_uint(&rs, data_blocks, sub_data, sub_ecc); | |
| 1287 for (j = 0; j < ecc_blocks; j++) { | |
| 1288 target[data_cw + j * blocks + i] = sub_ecc[j]; | |
| 1289 } | |
| 1290 } | |
| 1291 | |
| 1292 if (debug_print) { | |
| 1293 printf("Codewords (%d):", data_cw + ecc_length); | |
| 1294 for (i = 0; i < data_cw + ecc_length; i++) printf(" %d", (int) target[i]); | |
| 1295 fputc('\n', stdout); | |
| 1296 } | |
| 1297 | |
| 1298 i = 0; | |
| 1299 for (row = 0; row < c1_grid_height[size - 1]; row++) { | |
| 1300 for (col = 0; col < c1_grid_width[size - 1]; col++) { | |
| 1301 datagrid[row * 2][col * 4] = target[i] & 0x80; | |
| 1302 datagrid[row * 2][(col * 4) + 1] = target[i] & 0x40; | |
| 1303 datagrid[row * 2][(col * 4) + 2] = target[i] & 0x20; | |
| 1304 datagrid[row * 2][(col * 4) + 3] = target[i] & 0x10; | |
| 1305 datagrid[(row * 2) + 1][col * 4] = target[i] & 0x08; | |
| 1306 datagrid[(row * 2) + 1][(col * 4) + 1] = target[i] & 0x04; | |
| 1307 datagrid[(row * 2) + 1][(col * 4) + 2] = target[i] & 0x02; | |
| 1308 datagrid[(row * 2) + 1][(col * 4) + 3] = target[i] & 0x01; | |
| 1309 i++; | |
| 1310 } | |
| 1311 } | |
| 1312 | |
| 1313 symbol->rows = c1_height[size - 1]; | |
| 1314 symbol->width = c1_width[size - 1]; | |
| 1315 } | |
| 1316 | |
| 1317 if (debug_print) { | |
| 1318 printf("Version: %d\n", size); | |
| 1319 } | |
| 1320 | |
| 1321 switch (size) { | |
| 1322 case 1: /* Version A */ | |
| 1323 c1_central_finder(symbol, 6, 3, 1); | |
| 1324 c1_vert(symbol, 4, 6, 1); | |
| 1325 c1_vert(symbol, 12, 5, 0); | |
| 1326 set_module(symbol, 5, 12); | |
| 1327 c1_spigot(symbol, 0); | |
| 1328 c1_spigot(symbol, 15); | |
| 1329 c1_block_copy(symbol, datagrid, 0, 0, 5, 4, 0, 0); | |
| 1330 c1_block_copy(symbol, datagrid, 0, 4, 5, 12, 0, 2); | |
| 1331 c1_block_copy(symbol, datagrid, 5, 0, 5, 12, 6, 0); | |
| 1332 c1_block_copy(symbol, datagrid, 5, 12, 5, 4, 6, 2); | |
| 1333 break; | |
| 1334 case 2: /* Version B */ | |
| 1335 c1_central_finder(symbol, 8, 4, 1); | |
| 1336 c1_vert(symbol, 4, 8, 1); | |
| 1337 c1_vert(symbol, 16, 7, 0); | |
| 1338 set_module(symbol, 7, 16); | |
| 1339 c1_spigot(symbol, 0); | |
| 1340 c1_spigot(symbol, 21); | |
| 1341 c1_block_copy(symbol, datagrid, 0, 0, 7, 4, 0, 0); | |
| 1342 c1_block_copy(symbol, datagrid, 0, 4, 7, 16, 0, 2); | |
| 1343 c1_block_copy(symbol, datagrid, 7, 0, 7, 16, 8, 0); | |
| 1344 c1_block_copy(symbol, datagrid, 7, 16, 7, 4, 8, 2); | |
| 1345 break; | |
| 1346 case 3: /* Version C */ | |
| 1347 c1_central_finder(symbol, 11, 4, 2); | |
| 1348 c1_vert(symbol, 4, 11, 1); | |
| 1349 c1_vert(symbol, 26, 13, 1); | |
| 1350 c1_vert(symbol, 4, 10, 0); | |
| 1351 c1_vert(symbol, 26, 10, 0); | |
| 1352 c1_spigot(symbol, 0); | |
| 1353 c1_spigot(symbol, 27); | |
| 1354 c1_block_copy(symbol, datagrid, 0, 0, 10, 4, 0, 0); | |
| 1355 c1_block_copy(symbol, datagrid, 0, 4, 10, 20, 0, 2); | |
| 1356 c1_block_copy(symbol, datagrid, 0, 24, 10, 4, 0, 4); | |
| 1357 c1_block_copy(symbol, datagrid, 10, 0, 10, 4, 8, 0); | |
| 1358 c1_block_copy(symbol, datagrid, 10, 4, 10, 20, 8, 2); | |
| 1359 c1_block_copy(symbol, datagrid, 10, 24, 10, 4, 8, 4); | |
| 1360 break; | |
| 1361 case 4: /* Version D */ | |
| 1362 c1_central_finder(symbol, 16, 5, 1); | |
| 1363 c1_vert(symbol, 4, 16, 1); | |
| 1364 c1_vert(symbol, 20, 16, 1); | |
| 1365 c1_vert(symbol, 36, 16, 1); | |
| 1366 c1_vert(symbol, 4, 15, 0); | |
| 1367 c1_vert(symbol, 20, 15, 0); | |
| 1368 c1_vert(symbol, 36, 15, 0); | |
| 1369 c1_spigot(symbol, 0); | |
| 1370 c1_spigot(symbol, 12); | |
| 1371 c1_spigot(symbol, 27); | |
| 1372 c1_spigot(symbol, 39); | |
| 1373 c1_block_copy(symbol, datagrid, 0, 0, 15, 4, 0, 0); | |
| 1374 c1_block_copy(symbol, datagrid, 0, 4, 15, 14, 0, 2); | |
| 1375 c1_block_copy(symbol, datagrid, 0, 18, 15, 14, 0, 4); | |
| 1376 c1_block_copy(symbol, datagrid, 0, 32, 15, 4, 0, 6); | |
| 1377 c1_block_copy(symbol, datagrid, 15, 0, 15, 4, 10, 0); | |
| 1378 c1_block_copy(symbol, datagrid, 15, 4, 15, 14, 10, 2); | |
| 1379 c1_block_copy(symbol, datagrid, 15, 18, 15, 14, 10, 4); | |
| 1380 c1_block_copy(symbol, datagrid, 15, 32, 15, 4, 10, 6); | |
| 1381 break; | |
| 1382 case 5: /* Version E */ | |
| 1383 c1_central_finder(symbol, 22, 5, 2); | |
| 1384 c1_vert(symbol, 4, 22, 1); | |
| 1385 c1_vert(symbol, 26, 24, 1); | |
| 1386 c1_vert(symbol, 48, 22, 1); | |
| 1387 c1_vert(symbol, 4, 21, 0); | |
| 1388 c1_vert(symbol, 26, 21, 0); | |
| 1389 c1_vert(symbol, 48, 21, 0); | |
| 1390 c1_spigot(symbol, 0); | |
| 1391 c1_spigot(symbol, 12); | |
| 1392 c1_spigot(symbol, 39); | |
| 1393 c1_spigot(symbol, 51); | |
| 1394 c1_block_copy(symbol, datagrid, 0, 0, 21, 4, 0, 0); | |
| 1395 c1_block_copy(symbol, datagrid, 0, 4, 21, 20, 0, 2); | |
| 1396 c1_block_copy(symbol, datagrid, 0, 24, 21, 20, 0, 4); | |
| 1397 c1_block_copy(symbol, datagrid, 0, 44, 21, 4, 0, 6); | |
| 1398 c1_block_copy(symbol, datagrid, 21, 0, 21, 4, 10, 0); | |
| 1399 c1_block_copy(symbol, datagrid, 21, 4, 21, 20, 10, 2); | |
| 1400 c1_block_copy(symbol, datagrid, 21, 24, 21, 20, 10, 4); | |
| 1401 c1_block_copy(symbol, datagrid, 21, 44, 21, 4, 10, 6); | |
| 1402 break; | |
| 1403 case 6: /* Version F */ | |
| 1404 c1_central_finder(symbol, 31, 5, 3); | |
| 1405 c1_vert(symbol, 4, 31, 1); | |
| 1406 c1_vert(symbol, 26, 35, 1); | |
| 1407 c1_vert(symbol, 48, 31, 1); | |
| 1408 c1_vert(symbol, 70, 35, 1); | |
| 1409 c1_vert(symbol, 4, 30, 0); | |
| 1410 c1_vert(symbol, 26, 30, 0); | |
| 1411 c1_vert(symbol, 48, 30, 0); | |
| 1412 c1_vert(symbol, 70, 30, 0); | |
| 1413 c1_spigot(symbol, 0); | |
| 1414 c1_spigot(symbol, 12); | |
| 1415 c1_spigot(symbol, 24); | |
| 1416 c1_spigot(symbol, 45); | |
| 1417 c1_spigot(symbol, 57); | |
| 1418 c1_spigot(symbol, 69); | |
| 1419 c1_block_copy(symbol, datagrid, 0, 0, 30, 4, 0, 0); | |
| 1420 c1_block_copy(symbol, datagrid, 0, 4, 30, 20, 0, 2); | |
| 1421 c1_block_copy(symbol, datagrid, 0, 24, 30, 20, 0, 4); | |
| 1422 c1_block_copy(symbol, datagrid, 0, 44, 30, 20, 0, 6); | |
| 1423 c1_block_copy(symbol, datagrid, 0, 64, 30, 4, 0, 8); | |
| 1424 c1_block_copy(symbol, datagrid, 30, 0, 30, 4, 10, 0); | |
| 1425 c1_block_copy(symbol, datagrid, 30, 4, 30, 20, 10, 2); | |
| 1426 c1_block_copy(symbol, datagrid, 30, 24, 30, 20, 10, 4); | |
| 1427 c1_block_copy(symbol, datagrid, 30, 44, 30, 20, 10, 6); | |
| 1428 c1_block_copy(symbol, datagrid, 30, 64, 30, 4, 10, 8); | |
| 1429 break; | |
| 1430 case 7: /* Version G */ | |
| 1431 c1_central_finder(symbol, 47, 6, 2); | |
| 1432 c1_vert(symbol, 6, 47, 1); | |
| 1433 c1_vert(symbol, 27, 49, 1); | |
| 1434 c1_vert(symbol, 48, 47, 1); | |
| 1435 c1_vert(symbol, 69, 49, 1); | |
| 1436 c1_vert(symbol, 90, 47, 1); | |
| 1437 c1_vert(symbol, 6, 46, 0); | |
| 1438 c1_vert(symbol, 27, 46, 0); | |
| 1439 c1_vert(symbol, 48, 46, 0); | |
| 1440 c1_vert(symbol, 69, 46, 0); | |
| 1441 c1_vert(symbol, 90, 46, 0); | |
| 1442 c1_spigot(symbol, 0); | |
| 1443 c1_spigot(symbol, 12); | |
| 1444 c1_spigot(symbol, 24); | |
| 1445 c1_spigot(symbol, 36); | |
| 1446 c1_spigot(symbol, 67); | |
| 1447 c1_spigot(symbol, 79); | |
| 1448 c1_spigot(symbol, 91); | |
| 1449 c1_spigot(symbol, 103); | |
| 1450 c1_block_copy(symbol, datagrid, 0, 0, 46, 6, 0, 0); | |
| 1451 c1_block_copy(symbol, datagrid, 0, 6, 46, 19, 0, 2); | |
| 1452 c1_block_copy(symbol, datagrid, 0, 25, 46, 19, 0, 4); | |
| 1453 c1_block_copy(symbol, datagrid, 0, 44, 46, 19, 0, 6); | |
| 1454 c1_block_copy(symbol, datagrid, 0, 63, 46, 19, 0, 8); | |
| 1455 c1_block_copy(symbol, datagrid, 0, 82, 46, 6, 0, 10); | |
| 1456 c1_block_copy(symbol, datagrid, 46, 0, 46, 6, 12, 0); | |
| 1457 c1_block_copy(symbol, datagrid, 46, 6, 46, 19, 12, 2); | |
| 1458 c1_block_copy(symbol, datagrid, 46, 25, 46, 19, 12, 4); | |
| 1459 c1_block_copy(symbol, datagrid, 46, 44, 46, 19, 12, 6); | |
| 1460 c1_block_copy(symbol, datagrid, 46, 63, 46, 19, 12, 8); | |
| 1461 c1_block_copy(symbol, datagrid, 46, 82, 46, 6, 12, 10); | |
| 1462 break; | |
| 1463 case 8: /* Version H */ | |
| 1464 c1_central_finder(symbol, 69, 6, 3); | |
| 1465 c1_vert(symbol, 6, 69, 1); | |
| 1466 c1_vert(symbol, 26, 73, 1); | |
| 1467 c1_vert(symbol, 46, 69, 1); | |
| 1468 c1_vert(symbol, 66, 73, 1); | |
| 1469 c1_vert(symbol, 86, 69, 1); | |
| 1470 c1_vert(symbol, 106, 73, 1); | |
| 1471 c1_vert(symbol, 126, 69, 1); | |
| 1472 c1_vert(symbol, 6, 68, 0); | |
| 1473 c1_vert(symbol, 26, 68, 0); | |
| 1474 c1_vert(symbol, 46, 68, 0); | |
| 1475 c1_vert(symbol, 66, 68, 0); | |
| 1476 c1_vert(symbol, 86, 68, 0); | |
| 1477 c1_vert(symbol, 106, 68, 0); | |
| 1478 c1_vert(symbol, 126, 68, 0); | |
| 1479 c1_spigot(symbol, 0); | |
| 1480 c1_spigot(symbol, 12); | |
| 1481 c1_spigot(symbol, 24); | |
| 1482 c1_spigot(symbol, 36); | |
| 1483 c1_spigot(symbol, 48); | |
| 1484 c1_spigot(symbol, 60); | |
| 1485 c1_spigot(symbol, 87); | |
| 1486 c1_spigot(symbol, 99); | |
| 1487 c1_spigot(symbol, 111); | |
| 1488 c1_spigot(symbol, 123); | |
| 1489 c1_spigot(symbol, 135); | |
| 1490 c1_spigot(symbol, 147); | |
| 1491 c1_block_copy(symbol, datagrid, 0, 0, 68, 6, 0, 0); | |
| 1492 c1_block_copy(symbol, datagrid, 0, 6, 68, 18, 0, 2); | |
| 1493 c1_block_copy(symbol, datagrid, 0, 24, 68, 18, 0, 4); | |
| 1494 c1_block_copy(symbol, datagrid, 0, 42, 68, 18, 0, 6); | |
| 1495 c1_block_copy(symbol, datagrid, 0, 60, 68, 18, 0, 8); | |
| 1496 c1_block_copy(symbol, datagrid, 0, 78, 68, 18, 0, 10); | |
| 1497 c1_block_copy(symbol, datagrid, 0, 96, 68, 18, 0, 12); | |
| 1498 c1_block_copy(symbol, datagrid, 0, 114, 68, 6, 0, 14); | |
| 1499 c1_block_copy(symbol, datagrid, 68, 0, 68, 6, 12, 0); | |
| 1500 c1_block_copy(symbol, datagrid, 68, 6, 68, 18, 12, 2); | |
| 1501 c1_block_copy(symbol, datagrid, 68, 24, 68, 18, 12, 4); | |
| 1502 c1_block_copy(symbol, datagrid, 68, 42, 68, 18, 12, 6); | |
| 1503 c1_block_copy(symbol, datagrid, 68, 60, 68, 18, 12, 8); | |
| 1504 c1_block_copy(symbol, datagrid, 68, 78, 68, 18, 12, 10); | |
| 1505 c1_block_copy(symbol, datagrid, 68, 96, 68, 18, 12, 12); | |
| 1506 c1_block_copy(symbol, datagrid, 68, 114, 68, 6, 12, 14); | |
| 1507 break; | |
| 1508 case 9: /* Version S */ | |
| 1509 c1_horiz(symbol, 5, 1); | |
| 1510 c1_horiz(symbol, 7, 1); | |
| 1511 set_module(symbol, 6, 0); | |
| 1512 set_module(symbol, 6, symbol->width - 1); | |
| 1513 unset_module(symbol, 7, 1); | |
| 1514 unset_module(symbol, 7, symbol->width - 2); | |
| 1515 switch (sub_version) { | |
| 1516 case 1: /* Version S-10 */ | |
| 1517 set_module(symbol, 0, 5); | |
| 1518 c1_block_copy(symbol, datagrid, 0, 0, 4, 5, 0, 0); | |
| 1519 c1_block_copy(symbol, datagrid, 0, 5, 4, 5, 0, 1); | |
| 1520 break; | |
| 1521 case 2: /* Version S-20 */ | |
| 1522 set_module(symbol, 0, 10); | |
| 1523 set_module(symbol, 4, 10); | |
| 1524 c1_block_copy(symbol, datagrid, 0, 0, 4, 10, 0, 0); | |
| 1525 c1_block_copy(symbol, datagrid, 0, 10, 4, 10, 0, 1); | |
| 1526 break; | |
| 1527 case 3: /* Version S-30 */ | |
| 1528 set_module(symbol, 0, 15); | |
| 1529 set_module(symbol, 4, 15); | |
| 1530 set_module(symbol, 6, 15); | |
| 1531 c1_block_copy(symbol, datagrid, 0, 0, 4, 15, 0, 0); | |
| 1532 c1_block_copy(symbol, datagrid, 0, 15, 4, 15, 0, 1); | |
| 1533 break; | |
| 1534 } | |
| 1535 break; | |
| 1536 case 10: /* Version T */ | |
| 1537 c1_horiz(symbol, 11, 1); | |
| 1538 c1_horiz(symbol, 13, 1); | |
| 1539 c1_horiz(symbol, 15, 1); | |
| 1540 set_module(symbol, 12, 0); | |
| 1541 set_module(symbol, 12, symbol->width - 1); | |
| 1542 set_module(symbol, 14, 0); | |
| 1543 set_module(symbol, 14, symbol->width - 1); | |
| 1544 unset_module(symbol, 13, 1); | |
| 1545 unset_module(symbol, 13, symbol->width - 2); | |
| 1546 unset_module(symbol, 15, 1); | |
| 1547 unset_module(symbol, 15, symbol->width - 2); | |
| 1548 switch (sub_version) { | |
| 1549 case 1: /* Version T-16 */ | |
| 1550 set_module(symbol, 0, 8); | |
| 1551 set_module(symbol, 10, 8); | |
| 1552 c1_block_copy(symbol, datagrid, 0, 0, 10, 8, 0, 0); | |
| 1553 c1_block_copy(symbol, datagrid, 0, 8, 10, 8, 0, 1); | |
| 1554 break; | |
| 1555 case 2: /* Version T-32 */ | |
| 1556 set_module(symbol, 0, 16); | |
| 1557 set_module(symbol, 10, 16); | |
| 1558 set_module(symbol, 12, 16); | |
| 1559 c1_block_copy(symbol, datagrid, 0, 0, 10, 16, 0, 0); | |
| 1560 c1_block_copy(symbol, datagrid, 0, 16, 10, 16, 0, 1); | |
| 1561 break; | |
| 1562 case 3: /* Verion T-48 */ | |
| 1563 set_module(symbol, 0, 24); | |
| 1564 set_module(symbol, 10, 24); | |
| 1565 set_module(symbol, 12, 24); | |
| 1566 set_module(symbol, 14, 24); | |
| 1567 c1_block_copy(symbol, datagrid, 0, 0, 10, 24, 0, 0); | |
| 1568 c1_block_copy(symbol, datagrid, 0, 24, 10, 24, 0, 1); | |
| 1569 break; | |
| 1570 } | |
| 1571 break; | |
| 1572 } | |
| 1573 | |
| 1574 for (i = 0; i < symbol->rows; i++) { | |
| 1575 symbol->row_height[i] = 1; | |
| 1576 } | |
| 1577 symbol->height = symbol->rows; | |
| 1578 | |
| 1579 if (symbol->option_2 == 9) { /* Version S */ | |
| 1580 if (symbol->eci || gs1) { | |
| 1581 return errtxtf(ZINT_WARN_INVALID_OPTION, symbol, 511, "%s ignored for Version S", | |
| 1582 symbol->eci && gs1 ? "ECI and GS1 mode" : symbol->eci ? "ECI" : "GS1 mode"); | |
| 1583 } | |
| 1584 } else if (symbol->eci && gs1) { | |
| 1585 return errtxt(ZINT_WARN_INVALID_OPTION, symbol, 512, "ECI ignored for GS1 mode"); | |
| 1586 } | |
| 1587 | |
| 1588 return 0; | |
| 1589 } | |
| 1590 | |
| 1591 /* vim: set ts=4 sw=4 et : */ |
