zint/backend/maxicode.c

761 lines
30 KiB
C
Raw Normal View History

/* maxicode.c - Handles MaxiCode */
2008-07-14 09:15:55 +12:00
/*
libzint - the open source barcode library
Copyright (C) 2010-2024 Robin Stuart <rstuart114@gmail.com>
2008-07-14 09:15:55 +12:00
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* SPDX-License-Identifier: BSD-3-Clause */
2008-07-14 09:15:55 +12:00
/* Includes corrections thanks to Monica Swanson @ Source Technologies */
#include <assert.h>
#include <stdio.h>
2008-07-14 09:15:55 +12:00
#include "common.h"
#include "maxicode.h"
#include "reedsol.h"
/* Handles error correction of primary message */
static void maxi_do_primary_check(unsigned char maxi_codeword[144]) {
unsigned char results[15];
int j;
int datalen = 10;
int ecclen = 10;
rs_t rs;
rs_init_gf(&rs, 0x43);
rs_init_code(&rs, ecclen, 1);
rs_encode(&rs, datalen, maxi_codeword, results);
2008-07-14 09:15:55 +12:00
for (j = 0; j < ecclen; j += 1)
maxi_codeword[ datalen + j] = results[ecclen - 1 - j];
2008-07-14 09:15:55 +12:00
}
/* Handles error correction of odd characters in secondary */
static void maxi_do_secondary_chk_odd(unsigned char maxi_codeword[144], const int ecclen) {
unsigned char data[100];
unsigned char results[30];
int j;
int datalen = 68;
rs_t rs;
rs_init_gf(&rs, 0x43);
rs_init_code(&rs, ecclen, 1);
2008-07-14 09:15:55 +12:00
if (ecclen == 20)
datalen = 84;
2008-07-14 09:15:55 +12:00
for (j = 1; j < datalen; j += 2)
data[(j - 1) / 2] = maxi_codeword[j + 20];
2008-07-14 09:15:55 +12:00
rs_encode(&rs, datalen / 2, data, results);
2008-07-14 09:15:55 +12:00
for (j = 0; j < (ecclen); j += 1)
maxi_codeword[ datalen + (2 * j) + 1 + 20 ] = results[ecclen - 1 - j];
2008-07-14 09:15:55 +12:00
}
/* Handles error correction of even characters in secondary */
static void maxi_do_secondary_chk_even(unsigned char maxi_codeword[144], const int ecclen) {
unsigned char data[100];
unsigned char results[30];
int j;
int datalen = 68;
rs_t rs;
2008-07-14 09:15:55 +12:00
if (ecclen == 20)
datalen = 84;
2008-07-14 09:15:55 +12:00
rs_init_gf(&rs, 0x43);
rs_init_code(&rs, ecclen, 1);
for (j = 0; j < datalen + 1; j += 2)
data[j / 2] = maxi_codeword[j + 20];
2008-07-14 09:15:55 +12:00
rs_encode(&rs, datalen / 2, data, results);
2008-07-14 09:15:55 +12:00
for (j = 0; j < (ecclen); j += 1)
maxi_codeword[ datalen + (2 * j) + 20] = results[ecclen - 1 - j];
2008-07-14 09:15:55 +12:00
}
/* Moves everything up so that a shift or latch can be inserted */
static void maxi_bump(unsigned char set[], unsigned char character[], const int bump_posn, int *p_length) {
if (bump_posn < 143) {
memmove(set + bump_posn + 1, set + bump_posn, 143 - bump_posn);
memmove(character + bump_posn + 1, character + bump_posn, 143 - bump_posn);
}
(*p_length)++; /* Increment length regardless to make sure too long always triggered */
2008-07-14 09:15:55 +12:00
}
/* If the value is present in array, return the value, else return badvalue */
static int maxi_value_in_array(const unsigned char val, const unsigned char arr[], const int badvalue,
const int arrLength) {
int i;
for (i = 0; i < arrLength; i++) {
if (arr[i] == val) return val;
}
return badvalue;
}
/* Choose the best set from previous and next set in the range of the setval array, if no value can be found we
* return setval[0] */
static int maxi_bestSurroundingSet(const int index, const int length, const unsigned char set[], const int sp,
const unsigned char setval[], const int setLength) {
int badValue = -1;
int option1 = maxi_value_in_array(set[sp + index - 1], setval, badValue, setLength);
if (index + 1 < length) {
/* we have two options to check (previous & next) */
int option2 = maxi_value_in_array(set[sp + index + 1], setval, badValue, setLength);
if (option2 != badValue && option1 > option2) {
return option2;
}
}
if (option1 != badValue) {
return option1;
}
return setval[0];
}
/* Format text according to Appendix A */
static int maxi_text_process(unsigned char set[144], unsigned char character[144], const unsigned char in_source[],
int length, const int eci, const int scm_vv, int *p_sp, int current_set, const int debug_print) {
int sp = *p_sp;
int i, count;
#ifndef NDEBUG
int ns_count1 = 0, ns_count2 = 0;
#endif
static const unsigned char set15[2] = { 1, 5 };
static const unsigned char set12[2] = { 1, 2 };
static const unsigned char set12345[5] = { 1, 2, 3, 4, 5 };
const unsigned char *source = in_source;
unsigned char *source_buf = (unsigned char *) z_alloca(length + 9); /* For prefixing 9-character SCM sequence */
if (sp + length > 144) {
return 0;
}
/* Insert ECI at the beginning of message if needed */
/* Encode ECI assignment numbers according to table 3 */
if (eci != 0) {
if (sp + 1 + length > 144) return 0;
character[sp++] = 27; /* ECI */
if (eci <= 31) {
if (sp + 1 + length > 144) return 0;
character[sp++] = eci;
} else if (eci <= 1023) {
if (sp + 2 + length > 144) return 0;
character[sp++] = 0x20 | ((eci >> 6) & 0x0F);
character[sp++] = eci & 0x3F;
} else if (eci <= 32767) {
if (sp + 3 + length > 144) return 0;
character[sp++] = 0x30 | ((eci >> 12) & 0x07);
character[sp++] = (eci >> 6) & 0x3F;
character[sp++] = eci & 0x3F;
} else {
if (sp + 4 + length > 144) return 0;
character[sp++] = 0x38 | ((eci >> 18) & 0x03);
character[sp++] = (eci >> 12) & 0x3F;
character[sp++] = (eci >> 6) & 0x3F;
character[sp++] = eci & 0x3F;
}
}
if (scm_vv != -1) { /* Add SCM prefix */
if (sp + length > 135) {
return 0;
}
sprintf((char *) source_buf, "[)>\03601\035%02d", scm_vv); /* [)>\R01\Gvv */
memcpy(source_buf + 9, in_source, length);
source = source_buf;
length += 9;
}
for (i = 0; i < length; i++) {
/* Look up characters in table from Appendix A - this gives
value and code set for most characters */
set[sp + i] = maxiCodeSet[source[i]];
character[sp + i] = maxiSymbolChar[source[i]];
}
/* If a character can be represented in more than one code set,
pick which version to use */
if (set[sp + 0] == 0) {
if (character[sp + 0] == 13) {
character[sp + 0] = 0;
}
set[sp + 0] = 1;
}
for (i = 1; i < length; i++) {
if (set[sp + i] == 0) {
/* Special character */
if (character[sp + i] == 13) {
/* Carriage Return */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set15, 2);
if (set[sp + i] == 5) {
character[sp + i] = 13;
} else {
character[sp + i] = 0;
}
} else if (character[sp + i] == 28) {
/* FS */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12345, 5);
if (set[sp + i] == 5) {
character[sp + i] = 32;
}
} else if (character[sp + i] == 29) {
/* GS */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12345, 5);
if (set[sp + i] == 5) {
character[sp + i] = 33;
}
} else if (character[sp + i] == 30) {
/* RS */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12345, 5);
if (set[sp + i] == 5) {
character[sp + i] = 34;
}
} else if (character[sp + i] == 32) {
/* Space */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12345, 5);
if (set[sp + i] == 1) {
character[sp + i] = 32;
} else if (set[sp + i] == 2) {
character[sp + i] = 47;
} else {
character[sp + i] = 59;
}
} else if (character[sp + i] == 44) {
/* Comma */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12, 2);
if (set[sp + i] == 2) {
character[sp + i] = 48;
}
} else if (character[sp + i] == 46) {
/* Full Stop */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12, 2);
if (set[sp + i] == 2) {
character[sp + i] = 49;
}
} else if (character[sp + i] == 47) {
/* Slash */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12, 2);
if (set[sp + i] == 2) {
character[sp + i] = 50;
}
} else if (character[sp + i] == 58) {
/* Colon */
set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12, 2);
if (set[sp + i] == 2) {
character[sp + i] = 51;
}
}
}
}
/* Find candidates for number compression */
/* Note the prohibition on number compression in the primary message in ISO/IEC 16023:2000 B.1 (1)
applies to modes 2 & 3 only */
count = 0;
for (i = 0; sp + i < 144 && sp + i < length; i++) {
if ((set[sp + i] == 1) && ((character[sp + i] >= 48) && (character[sp + i] <= 57))) {
/* Character is a number */
count++;
if (count == 9) {
/* Nine digits in a row can be compressed */
memset(set + sp + i - 8, 6, 9); /* Set set of nine digits to 6 */
count = 0;
#ifndef NDEBUG
ns_count1++;
#endif
}
} else {
count = 0;
}
}
/* Add shift and latch characters */
for (i = 0; sp + i < 144 && set[sp + i] != 255; i++) {
if ((set[sp + i] != current_set) && (set[sp + i] != 6)) {
switch (set[sp + i]) {
case 1:
if (current_set == 2) { /* Set B */
if (sp + i + 1 < 144 && set[sp + i + 1] == 1) {
if (sp + i + 2 < 144 && set[sp + i + 2] == 1) {
if (sp + i + 3 < 144 && set[sp + i + 3] == 1) {
/* Latch A */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 63; /* Set B Latch A */
current_set = 1;
i += 3; /* Next 3 Set A so skip over */
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
if (debug_print) fputs("LCHA ", stdout);
} else {
/* 3 Shift A */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 57; /* Set B triple shift A */
i += 2; /* Next 2 Set A so skip over */
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
if (debug_print) fputs("3SHA ", stdout);
}
} else {
/* 2 Shift A */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 56; /* Set B double shift A */
i++; /* Next Set A so skip over */
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
if (debug_print) fputs("2SHA ", stdout);
}
} else {
/* Shift A */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 59; /* Set A Shift B */
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
if (debug_print) fputs("SHA ", stdout);
}
} else { /* All sets other than B only have latch */
/* Latch A */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 58; /* Sets C,D,E Latch A */
current_set = 1;
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
if (debug_print) fputs("LCHA ", stdout);
}
break;
case 2: /* Set B */
/* If not Set A or next Set B */
if (current_set != 1 || (sp + i + 1 < 144 && set[sp + i + 1] == 2)) {
/* Latch B */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 63; /* Sets A,C,D,E Latch B */
current_set = 2;
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
if (debug_print) fputs("LCHB ", stdout);
} else { /* Only available from Set A */
/* Shift B */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 59; /* Set B Shift A */
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
if (debug_print) fputs("SHB ", stdout);
}
break;
case 3: /* Set C */
case 4: /* Set D */
case 5: /* Set E */
/* If first and next 3 same set, or not first and previous and next 2 same set */
if ((sp + i == 0 && sp + i + 3 < 144 && set[sp + i + 1] == set[sp + i]
&& set[sp + i + 2] == set[sp + i] && set[sp + i + 3] == set[sp + i])
|| (sp + i > 0 && set[sp + i - 1] == set[sp + i] && sp + i + 2 < 144
&& set[sp + i + 1] == set[sp + i] && set[sp + i + 2] == set[sp + i])) {
/* Lock in C/D/E */
if (sp + i == 0) {
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 60 + set[sp + i] - 3;
i++; /* Extra bump */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 60 + set[sp + i] - 3;
i += 3; /* Next 3 same set so skip over */
} else {
/* Add single Shift to previous Shift */
maxi_bump(set, character, sp + i - 1, &length);
character[sp + i - 1] = 60 + set[sp + i] - 3;
i += 2; /* Next 2 same set so skip over */
}
current_set = set[sp + i];
if (debug_print) printf("LCK%c ", 'C' + set[sp + i] - 3);
} else {
/* Shift C/D/E */
maxi_bump(set, character, sp + i, &length);
character[sp + i] = 60 + set[sp + i] - 3;
if (debug_print) printf("SH%c ", 'C' + set[sp + i] - 3);
}
break;
}
i++; /* Allow for bump */
}
}
/* Number compression has not been forgotten! - It's handled below */
for (i = 0; sp + i < 144 && sp + i <= length - 9; i++) {
if (set[sp + i] == 6) {
/* Number compression */
int value = to_int(character + sp + i, 9);
character[sp + i] = 31; /* NS */
character[sp + i + 1] = (value & 0x3f000000) >> 24;
character[sp + i + 2] = (value & 0xfc0000) >> 18;
character[sp + i + 3] = (value & 0x3f000) >> 12;
character[sp + i + 4] = (value & 0xfc0) >> 6;
character[sp + i + 5] = (value & 0x3f);
memmove(set + sp + i + 6, set + sp + i + 9, 144 - (sp + i + 9));
memmove(character + sp + i + 6, character + sp + i + 9, 144 - (sp + i + 9));
i += 5;
length -= 3;
#ifndef NDEBUG
ns_count2++;
#endif
}
}
assert(ns_count1 == ns_count2);
*p_sp = sp + length;
return current_set;
}
/* Call `maxi_text_process()` for each segment, dealing with Structured Append beforehand and populating
`maxi_codeword` afterwards */
static int maxi_text_process_segs(unsigned char maxi_codeword[144], const int mode, const struct zint_seg segs[],
const int seg_count, const int structapp_cw, int scm_vv, const int debug_print) {
unsigned char set[144], character[144] = {0};
int i;
int sp = 0;
int current_set = 1; /* Initial Code Set A */
int padding_set = 0, padding_char = 0; /* Suppress clang-tidy-20 warnings */
const int max_length = mode == 5 ? 77 : mode <= 3 ? 84 : 93;
memset(set, 255, 144);
/* Insert Structured Append at beginning if needed */
if (structapp_cw) {
character[sp++] = 33; /* PAD */
character[sp++] = structapp_cw;
}
for (i = 0; i < seg_count; i++) {
current_set = maxi_text_process(set, character, segs[i].source, segs[i].length, segs[i].eci, scm_vv, &sp,
current_set, debug_print);
if (current_set == 0) {
return ZINT_ERROR_TOO_LONG;
}
scm_vv = -1;
}
/* If end in Code Set C or D, switch to A for padding */
if (sp < max_length && (current_set == 3 || current_set == 4)) {
set[sp] = 1;
character[sp] = 58; /* Sets C,D Latch A */
sp++;
current_set = 1;
if (debug_print) fputs("LCHA ", stdout);
}
if (debug_print) {
if (sp < max_length) {
printf("\nPads (%d)\n", max_length - sp);
} else {
fputs("\nNo Pads\n", stdout);
}
}
if (sp < max_length) {
padding_set = current_set == 5 ? 5 : current_set == 2 ? 2 : 1;
padding_char = current_set == 5 ? 28 : 33;
for (; sp < max_length; sp++) {
/* Add the padding */
set[sp] = padding_set;
character[sp] = padding_char;
}
}
if (debug_print) printf("Length: %d\n", sp);
if (sp > max_length) {
return ZINT_ERROR_TOO_LONG;
}
/* Copy the encoded text into the codeword array */
if ((mode == 2) || (mode == 3)) {
for (i = 0; i < 84; i++) { /* secondary only */
maxi_codeword[i + 20] = character[i];
}
} else if ((mode == 4) || (mode == 6)) {
for (i = 0; i < 9; i++) { /* primary */
maxi_codeword[i + 1] = character[i];
}
for (i = 0; i < 84; i++) { /* secondary */
maxi_codeword[i + 20] = character[i + 9];
}
} else { /* Mode 5 */
for (i = 0; i < 9; i++) { /* primary */
maxi_codeword[i + 1] = character[i];
}
for (i = 0; i < 68; i++) { /* secondary */
maxi_codeword[i + 20] = character[i + 9];
}
}
return 0;
2008-07-14 09:15:55 +12:00
}
/* Format structured primary for Mode 2 */
static void maxi_do_primary_2(unsigned char maxi_codeword[144], const unsigned char postcode[],
const int postcode_length, const int country, const int service) {
int postcode_num;
postcode_num = to_int(postcode, postcode_length);
maxi_codeword[0] = ((postcode_num & 0x03) << 4) | 2;
maxi_codeword[1] = ((postcode_num & 0xfc) >> 2);
maxi_codeword[2] = ((postcode_num & 0x3f00) >> 8);
maxi_codeword[3] = ((postcode_num & 0xfc000) >> 14);
maxi_codeword[4] = ((postcode_num & 0x3f00000) >> 20);
maxi_codeword[5] = ((postcode_num & 0x3c000000) >> 26) | ((postcode_length & 0x3) << 4);
maxi_codeword[6] = ((postcode_length & 0x3c) >> 2) | ((country & 0x3) << 4);
maxi_codeword[7] = (country & 0xfc) >> 2;
maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
maxi_codeword[9] = ((service & 0x3f0) >> 4);
2008-07-14 09:15:55 +12:00
}
/* Format structured primary for Mode 3 */
static void maxi_do_primary_3(unsigned char maxi_codeword[144], unsigned char postcode[], const int country,
const int service) {
int i;
/* Convert to Code Set A */
for (i = 0; i < 6; i++) {
postcode[i] = maxiSymbolChar[postcode[i]];
}
maxi_codeword[0] = ((postcode[5] & 0x03) << 4) | 3;
maxi_codeword[1] = ((postcode[4] & 0x03) << 4) | ((postcode[5] & 0x3c) >> 2);
maxi_codeword[2] = ((postcode[3] & 0x03) << 4) | ((postcode[4] & 0x3c) >> 2);
maxi_codeword[3] = ((postcode[2] & 0x03) << 4) | ((postcode[3] & 0x3c) >> 2);
maxi_codeword[4] = ((postcode[1] & 0x03) << 4) | ((postcode[2] & 0x3c) >> 2);
maxi_codeword[5] = ((postcode[0] & 0x03) << 4) | ((postcode[1] & 0x3c) >> 2);
maxi_codeword[6] = ((postcode[0] & 0x3c) >> 2) | ((country & 0x3) << 4);
maxi_codeword[7] = (country & 0xfc) >> 2;
maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
maxi_codeword[9] = ((service & 0x3f0) >> 4);
2008-07-14 09:15:55 +12:00
}
INTERNAL int maxicode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
int i, j, block, shift, mode, lp = 0;
int error_number, eclen;
unsigned char maxi_codeword[144] = {0};
int scm_vv = -1;
int structapp_cw = 0;
const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
mode = symbol->option_1;
if (mode <= 0) { /* If mode is unspecified (-1) or to be auto-determined (0) between 2 and 3 */
lp = (int) strlen(symbol->primary);
if (lp == 0) {
if (mode == 0) { /* Require primary message to auto-determine between 2 and 3 */
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 554, "Primary Message empty");
}
mode = 4;
} else {
mode = 2;
for (i = 0; i < lp - 6; i++) {
if (!z_isdigit(symbol->primary[i]) && (symbol->primary[i] != ' ')) {
mode = 3;
break;
}
}
}
}
if ((mode < 2) || (mode > 6)) { /* Only codes 2 to 6 supported */
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 550, "Mode '%d' out of range (2 to 6)", mode);
}
if ((mode == 2) || (mode == 3)) { /* Modes 2 and 3 need data in symbol->primary */
unsigned char postcode[10];
2017-10-24 08:34:31 +13:00
int countrycode;
int service;
int postcode_len;
if (lp == 0) { /* Mode set manually means lp doesn't get set */
lp = (int) strlen(symbol->primary);
}
if (lp < 7 || lp > 15) { /* 1 to 9 character postcode + 3 digit country code + 3 digit service class */
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
if (lp == 0) {
return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 548, "Primary Message empty");
}
return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 551, "Primary Message length %d wrong (7 to 15 only)",
lp);
}
postcode_len = lp - 6;
countrycode = to_int((const unsigned char *) (symbol->primary + postcode_len), 3);
service = to_int((const unsigned char *) (symbol->primary + postcode_len + 3), 3);
if (countrycode == -1 || service == -1) { /* check that country code and service are numeric */
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 552,
"Non-numeric country code or service class in Primary Message");
}
memcpy(postcode, symbol->primary, postcode_len);
postcode[postcode_len] = '\0';
if (mode == 2) {
for (i = 0; i < postcode_len; i++) {
if (postcode[i] == ' ') {
postcode[i] = '\0';
postcode_len = i;
break;
} else if (!z_isdigit(postcode[i])) {
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 555, "Non-numeric postcode in Primary Message");
}
}
if (countrycode == 840 && postcode_len == 5) {
/* Annex B, section B.1, paragraph 4.a, "In the case of country code 840, if the "+4" is unknown,
then fill with zeroes" (adapted from OkaiBarcode, stricter interpretation, props Daniel Gredler) */
memcpy(postcode + 5, "0000", 5); /* Include NUL char */
postcode_len = 9;
}
maxi_do_primary_2(maxi_codeword, postcode, postcode_len, countrycode, service);
} else {
/* Just truncate and space-pad */
postcode[6] = '\0';
for (i = postcode_len; i < 6; i++) {
postcode[i] = ' ';
}
/* Upper-case and check for Code Set A characters only */
Performance improvements for linear encoding and raster output - use fixed-length string tables (mostly) instead of (char *) pointer ones (saves ~40K) - re-use C128Table for CODABLOCKF and CODE16K (required removal of Stop character and extra CODE16K-only entry) - use pointer to destination and copy (memcpy/strcpy(), bin_append_posn()) instead of concatenating (strcat()) (mostly) - replace last remaining bin_append()s with bin_append_posn(); bin_append() removed - add length arg to toupper() and expand() (avoids strlen()) - change is_sane() to use table-based flags (avoids an iteration) - rename lookup() to is_sane_lookup() and change to check and return posns and use in pointer to destination loops (avoids strcat()s) - remove special case PHARMA in expand() (dealt with in pharma()) - make #define SILVER/CALCIUM/TECHNETIUM/KRSET etc static strings - replace strchr() -> posn() - CODE128: populate destination once in checksum loop; re-use and export some more routines (c128_set_a/b/c(), c128_put_in_set()) for sharing; prefix defines (SHIFTA -> C128_SHIFTA etc) and existing exported routines - use factor XOR toggle trick in checksum calcs (avoids branch) - raster.c: fill out single 1-pixel row and copy using new draw_bar_line(), copy_bar_line() routines; similarly in buffer_plot compare previous line & copy if same (same technique as used to improve non-half-integer scaling, significant performance increase, (c) codemonkey82); also done for PNG (BMP/GIF/PCX/TIFF not done) - raster/vector/output.c: shorten "output_" prefix -> "out_"; sync vector to other raster changes to try to keep source files similar - 2of5.c: prefix "c25_" JAPANPOST: return error if input data truncated (backward incompatible) DAFT: max chars 50 -> 100 common.c: istwodigit() -> is_twodigit() common.c/emf.c/output.c: use some further stripf()s (MSVC6 float variations) library.c: new check_output_args() helper zint.h: add BARCODE_LAST marker and use in library.c QRCODE: remove a NOLINT (requires clang-tidy-13), one remaining CMake: separate no-optimize from ZINT_DEBUG into new ZINT_NOOPT option
2021-10-21 11:05:30 +13:00
to_upper(postcode, postcode_len);
for (i = 0; i < 6; i++) {
/* Don't allow Code Set A control characters CR, RS, GS and RS */
if (postcode[i] < ' ' || maxiCodeSet[postcode[i]] > 1) {
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 556,
"Invalid character in postcode in Primary Message");
}
}
maxi_do_primary_3(maxi_codeword, postcode, countrycode, service);
}
if (symbol->option_2) { /* Check for option_2 = vv + 1, where vv is version of SCM prefix "[)>\R01\Gvv" */
if (symbol->option_2 < 0 || symbol->option_2 > 100) {
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 557,
"SCM prefix version '%d' out of range (1 to 100)", symbol->option_2);
}
scm_vv = symbol->option_2 - 1;
}
if (debug_print) {
printf("Postcode: %s, Country Code: %d, Service Class: %d\n", postcode, countrycode, service);
}
} else {
maxi_codeword[0] = mode;
}
if (debug_print) {
printf("Mode: %d\n", mode);
}
if (symbol->structapp.count) {
if (symbol->structapp.count < 2 || symbol->structapp.count > 8) {
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 558,
"Structured Append count '%d' out of range (2 to 8)", symbol->structapp.count);
}
if (symbol->structapp.index < 1 || symbol->structapp.index > symbol->structapp.count) {
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 559,
"Structured Append index '%1$d' out of range (1 to count %2$d)",
symbol->structapp.index, symbol->structapp.count);
}
if (symbol->structapp.id[0]) {
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 549, "Structured Append ID not available for MaxiCode");
}
structapp_cw = (symbol->structapp.count - 1) | ((symbol->structapp.index - 1) << 3);
}
error_number = maxi_text_process_segs(maxi_codeword, mode, segs, seg_count, structapp_cw, scm_vv, debug_print);
if (error_number == ZINT_ERROR_TOO_LONG) {
CODE128: reduce extended latch cut-off from 5 to 4 for better encodation in certain cases (and no pessimizations found so far), props lyngklip (BWIPP); fix extended char latching when exactly 3 extended chars at end; count code set C (not digits) in loop deciding when to shift/latch to extended for better estimate AZTEC: return warning if ECC < 5% (due to bit-stuffing when version given); return error if > 22 layers (Zint 26) for Reader Initialisation symbol requested for better error message AZTEC/HANXIN/QRCODE: consolidate different ECC data size tables into one indexed by ECC DBAR_EXP: check for reduced length <= 77 up front for better error message HANXIN: use `malloc()` rather than `z_alloca()` for large binary array QRCODE: `ecc_level` now 0-based (not 1-based) MICROQR: consolidate different version end routines into one `microqr_end()` and use new `microqr_data` table to simplify code MICROPDF417: use table for max codewords per column library: centralize all error messages using new `errtxt()`, `errtxtf()`, `errtxt_adj()` funcs that protect `symbol->errtxt` from overflow, & try to make error messages more consistent thru-out, adding more feedback info to many, & use positional args "%n$" in prep for l10n (maybe); `is_sane/is_sane_lookup()` -> `not_sane/not_sane_lookup()`, returning 1-based position (zero on failure) instead of bool; `long` ints -> plain `int` (except those dealing with `ftell()`, `fread()` etc) as depend on int being 32-bits already GUI: in "grpDATF.ui" use "PlainText" rather than "RichText" for tracker ratio examples as height of text messing up sometimes manual: clarify Codablock-F length maximum & add examples docs: README: pandoc 3.5, Ubuntu 24.04 CMake: use "-Wpedantic" for Clang only as GNU complains about `errtxtf()` positional args "%n$"
2024-10-28 10:33:33 +13:00
return errtxt(error_number, symbol, 553, "Input too long, requires too many codewords (maximum 144)");
}
/* All the data is sorted - now do error correction */
maxi_do_primary_check(maxi_codeword); /* always EEC */
if (mode == 5)
eclen = 56; /* 68 data codewords , 56 error corrections */
else
eclen = 40; /* 84 data codewords, 40 error corrections */
maxi_do_secondary_chk_even(maxi_codeword, eclen / 2); /* do error correction of even */
maxi_do_secondary_chk_odd(maxi_codeword, eclen / 2); /* do error correction of odd */
if (debug_print) {
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
fputs("Codewords:", stdout);
for (i = 0; i < 144; i++) printf(" %d", maxi_codeword[i]);
EAN/UPC: add quiet zone indicators option (API `output_options` `EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
2023-06-12 12:25:55 +12:00
fputc('\n', stdout);
}
#ifdef ZINT_TEST
if (symbol->debug & ZINT_DEBUG_TEST) {
debug_test_codeword_dump(symbol, maxi_codeword, 144);
}
#endif
/* Copy data into symbol grid */
for (i = 0; i < 33; i++) {
for (j = 0; j < 30; j++) {
block = (MaxiGrid[(i * 30) + j] + 5) / 6;
if (block != 0) {
shift = 5 - ((MaxiGrid[(i * 30) + j] + 5) % 6);
if ((maxi_codeword[block - 1] >> shift) & 0x1) {
set_module(symbol, i, j);
}
}
}
}
/* Add orientation markings */
set_module(symbol, 0, 28); /* Top right filler */
set_module(symbol, 0, 29);
set_module(symbol, 9, 10); /* Top left marker */
set_module(symbol, 9, 11);
set_module(symbol, 10, 11);
set_module(symbol, 15, 7); /* Left hand marker */
set_module(symbol, 16, 8);
set_module(symbol, 16, 20); /* Right hand marker */
set_module(symbol, 17, 20);
set_module(symbol, 22, 10); /* Bottom left marker */
set_module(symbol, 23, 10);
set_module(symbol, 22, 17); /* Bottom right marker */
set_module(symbol, 23, 17);
symbol->width = 30;
symbol->rows = 33;
/* Note MaxiCode fixed size so symbol height ignored but set anyway */
(void) set_height(symbol, 5.0f, 0.0f, 0.0f, 1 /*no_errtxt*/);
return error_number;
2008-07-14 09:15:55 +12:00
}
/* vim: set ts=4 sw=4 et : */