mirror of
https://git.code.sf.net/p/zint/code
synced 2026-06-09 23:23:36 +00:00
Add convenience API funcs ZBarcode_UTF8_To_ECI() and
`ZBarcode_Dest_Len_ECI()`, primarily for ZXingC++ but also useful in general
This commit is contained in:
+39
-3
@@ -1,7 +1,7 @@
|
||||
/* eci.c - Extended Channel Interpretations */
|
||||
/*
|
||||
libzint - the open source barcode library
|
||||
Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
|
||||
Copyright (C) 2009-2025 Robin Stuart <rstuart114@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@@ -43,6 +43,30 @@
|
||||
|
||||
/* Single-byte stuff */
|
||||
|
||||
/* ECI 2 (bottom half ASCII, top half CP437), included for libzueci compatibility - assumes valid Unicode */
|
||||
static int u_cp437(const unsigned int u, unsigned char *dest) {
|
||||
int s, e;
|
||||
if (u < 0x80) {
|
||||
*dest = (unsigned char) u;
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = 0;
|
||||
e = ARRAY_SIZE(cp437_u) - 1;
|
||||
while (s <= e) {
|
||||
const int m = (s + e) >> 1;
|
||||
if (cp437_u[m] < u) {
|
||||
s = m + 1;
|
||||
} else if (cp437_u[m] > u) {
|
||||
e = m - 1;
|
||||
} else {
|
||||
*dest = cp437_sb[m];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Base ISO/IEC 8859 routine to convert Unicode codepoint `u` */
|
||||
static int u_iso8859(const unsigned int u, const unsigned short *tab_s, const unsigned short *tab_u,
|
||||
const unsigned char *tab_sb, int e, unsigned char *dest) {
|
||||
@@ -181,6 +205,15 @@ static int u_utf32le(const unsigned int u, unsigned char *dest) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
/* ECI 899 Binary, included for libzueci compatibility - assumes valid Unicode */
|
||||
static int u_binary(const unsigned int u, unsigned char *dest) {
|
||||
if (u <= 0xFF) {
|
||||
*dest = (unsigned char) u;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Multibyte stuff */
|
||||
|
||||
/* Acknowledgements to Bruno Haible <bruno@clisp.org> for a no. of techniques used here */
|
||||
@@ -701,7 +734,7 @@ typedef int (*eci_func_t)(const unsigned int u, unsigned char *dest);
|
||||
INTERNAL int utf8_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *p_length) {
|
||||
|
||||
static const eci_func_t eci_funcs[36] = {
|
||||
NULL, NULL, NULL, NULL, u_iso8859_2, /*0-4*/
|
||||
NULL, NULL, u_cp437, NULL, u_iso8859_2, /*0-4*/
|
||||
u_iso8859_3, u_iso8859_4, u_iso8859_5, u_iso8859_6, u_iso8859_7, /*5-9*/
|
||||
u_iso8859_8, u_iso8859_9, u_iso8859_10, u_iso8859_11, NULL, /*10-14*/
|
||||
u_iso8859_13, u_iso8859_14, u_iso8859_15, u_iso8859_16, NULL, /*15-19*/
|
||||
@@ -717,7 +750,8 @@ INTERNAL int utf8_to_eci(const int eci, const unsigned char source[], unsigned c
|
||||
int length = *p_length;
|
||||
|
||||
/* Special case ISO/IEC 8859-1 */
|
||||
if (eci == 0 || eci == 3) { /* Default ECI 0 to ISO/IEC 8859-1 */
|
||||
/* Default ECI 0 to ISO/IEC 8859-1 (and ECI 1 for libzueci compatibility) */
|
||||
if (eci == 0 || eci == 3 || eci == 1) {
|
||||
while (in_posn < length) {
|
||||
do {
|
||||
decode_utf8(&state, &codepoint, source[in_posn++]);
|
||||
@@ -737,6 +771,8 @@ INTERNAL int utf8_to_eci(const int eci, const unsigned char source[], unsigned c
|
||||
|
||||
if (eci == 170) { /* ASCII Invariant (archaic subset) */
|
||||
eci_func = u_ascii_inv;
|
||||
} else if (eci == 899) { /* Binary, for libzueci compatibility */
|
||||
eci_func = u_binary;
|
||||
} else {
|
||||
eci_func = eci_funcs[eci];
|
||||
if (eci_func == NULL) {
|
||||
|
||||
+43
-4
@@ -1,9 +1,10 @@
|
||||
/* eci_sb.h - Extended Channel Interpretations single-byte, generated by "backend/tools/gen_eci_sb_h.php"
|
||||
from "https://unicode.org/Public/MAPPINGS/ISO8859/8859-*.TXT"
|
||||
and "https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP125*.TXT" */
|
||||
/* eci_sb.h - Extended Channel Interpretations single-byte, generated by "backend/tools/gen_eci_sb_h.php" from
|
||||
"https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT" (for libzueci compatibility) and
|
||||
"https://unicode.org/Public/MAPPINGS/ISO8859/8859-*.TXT" and
|
||||
"https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP125*.TXT" */
|
||||
/*
|
||||
libzint - the open source barcode library
|
||||
Copyright (C) 2021-2022 Robin Stuart <rstuart114@gmail.com>
|
||||
Copyright (C) 2021-2025 Robin Stuart <rstuart114@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@@ -35,6 +36,44 @@
|
||||
#ifndef Z_ECI_SB_H
|
||||
#define Z_ECI_SB_H
|
||||
|
||||
/* Tables for ECI 2 CP437 (for libzueci compatibility) */
|
||||
static const unsigned short cp437_u[128] = { /* Unicode codepoints sorted */
|
||||
0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A5, 0x00AA, 0x00AB, 0x00AC,
|
||||
0x00B0, 0x00B1, 0x00B2, 0x00B5, 0x00B7, 0x00BA, 0x00BB, 0x00BC,
|
||||
0x00BD, 0x00BF, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C9, 0x00D1,
|
||||
0x00D6, 0x00DC, 0x00DF, 0x00E0, 0x00E1, 0x00E2, 0x00E4, 0x00E5,
|
||||
0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED,
|
||||
0x00EE, 0x00EF, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F6, 0x00F7,
|
||||
0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FF, 0x0192, 0x0393, 0x0398,
|
||||
0x03A3, 0x03A6, 0x03A9, 0x03B1, 0x03B4, 0x03B5, 0x03C0, 0x03C3,
|
||||
0x03C4, 0x03C6, 0x207F, 0x20A7, 0x2219, 0x221A, 0x221E, 0x2229,
|
||||
0x2248, 0x2261, 0x2264, 0x2265, 0x2310, 0x2320, 0x2321, 0x2500,
|
||||
0x2502, 0x250C, 0x2510, 0x2514, 0x2518, 0x251C, 0x2524, 0x252C,
|
||||
0x2534, 0x253C, 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555,
|
||||
0x2556, 0x2557, 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D,
|
||||
0x255E, 0x255F, 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565,
|
||||
0x2566, 0x2567, 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x2580,
|
||||
0x2584, 0x2588, 0x258C, 0x2590, 0x2591, 0x2592, 0x2593, 0x25A0,
|
||||
};
|
||||
static const unsigned char cp437_sb[128] = { /* Single-byte in Unicode order */
|
||||
0xFF, 0xAD, 0x9B, 0x9C, 0x9D, 0xA6, 0xAE, 0xAA,
|
||||
0xF8, 0xF1, 0xFD, 0xE6, 0xFA, 0xA7, 0xAF, 0xAC,
|
||||
0xAB, 0xA8, 0x8E, 0x8F, 0x92, 0x80, 0x90, 0xA5,
|
||||
0x99, 0x9A, 0xE1, 0x85, 0xA0, 0x83, 0x84, 0x86,
|
||||
0x91, 0x87, 0x8A, 0x82, 0x88, 0x89, 0x8D, 0xA1,
|
||||
0x8C, 0x8B, 0xA4, 0x95, 0xA2, 0x93, 0x94, 0xF6,
|
||||
0x97, 0xA3, 0x96, 0x81, 0x98, 0x9F, 0xE2, 0xE9,
|
||||
0xE4, 0xE8, 0xEA, 0xE0, 0xEB, 0xEE, 0xE3, 0xE5,
|
||||
0xE7, 0xED, 0xFC, 0x9E, 0xF9, 0xFB, 0xEC, 0xEF,
|
||||
0xF7, 0xF0, 0xF3, 0xF2, 0xA9, 0xF4, 0xF5, 0xC4,
|
||||
0xB3, 0xDA, 0xBF, 0xC0, 0xD9, 0xC3, 0xB4, 0xC2,
|
||||
0xC1, 0xC5, 0xCD, 0xBA, 0xD5, 0xD6, 0xC9, 0xB8,
|
||||
0xB7, 0xBB, 0xD4, 0xD3, 0xC8, 0xBE, 0xBD, 0xBC,
|
||||
0xC6, 0xC7, 0xCC, 0xB5, 0xB6, 0xB9, 0xD1, 0xD2,
|
||||
0xCB, 0xCF, 0xD0, 0xCA, 0xD8, 0xD7, 0xCE, 0xDF,
|
||||
0xDC, 0xDB, 0xDD, 0xDE, 0xB0, 0xB1, 0xB2, 0xFE,
|
||||
};
|
||||
|
||||
/* Forward reference to base ISO/IEC 8859 routine - see "eci.c" */
|
||||
static int u_iso8859(const unsigned int u, const unsigned short *tab_s, const unsigned short *tab_u,
|
||||
const unsigned char *tab_sb, int e, unsigned char *dest);
|
||||
|
||||
+62
-1
@@ -979,7 +979,7 @@ static int map_invalid_symbology(struct zint_symbol *symbol) {
|
||||
return warn_number;
|
||||
}
|
||||
|
||||
/* Encode a barcode. If `length` is 0, `source` must be NUL-terminated */
|
||||
/* Encode a barcode. If `length` is 0 or negative, `source` must be NUL-terminated */
|
||||
int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int length) {
|
||||
struct zint_seg segs[1];
|
||||
|
||||
@@ -2070,6 +2070,67 @@ float ZBarcode_XdimDp_From_Scale(int symbol_id, float scale, float xdim_mm_or_dp
|
||||
return xdim_mm_or_dpmm;
|
||||
}
|
||||
|
||||
/* Whether `eci` is valid character set ECI */
|
||||
static int is_valid_char_set_eci(const int eci) {
|
||||
/* Allowing ECI 1 and ECI 2 for libzueci compatibility (and ECI 0, which is mapped to ECI 2) */
|
||||
return (eci <= 35 && eci >= 0 && eci != 14 && eci != 19) || eci == 170 || eci == 899;
|
||||
}
|
||||
|
||||
/* Convert UTF-8 `source` of length `length` to `eci`-encoded `dest`, setting `p_dest_length` to length of `dest`
|
||||
on output. If `length` is 0 or negative, `source` must be NUL-terminated. Returns 0 on success, else
|
||||
ZINT_ERROR_INVALID_OPTION or ZINT_ERROR_INVALID_DATA. Compatible with libzueci `zueci_utf8_to_eci()` */
|
||||
int ZBarcode_UTF8_To_ECI(int eci, const unsigned char *source, int length, unsigned char dest[], int *p_dest_length) {
|
||||
int error_number;
|
||||
|
||||
/* Map ECI 0 to ECI 2 (CP437) for libzueci compatibility */
|
||||
if (eci == 0) {
|
||||
eci = 2;
|
||||
}
|
||||
if (!is_valid_char_set_eci(eci) || !source || !p_dest_length) {
|
||||
return ZINT_ERROR_INVALID_OPTION;
|
||||
}
|
||||
if (length <= 0) {
|
||||
length = (int) ustrlen(source); /* Note `zueci_utf8_to_eci()` doesn't do this */
|
||||
}
|
||||
if (!is_valid_utf8(source, length)) {
|
||||
return ZINT_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (eci == 26) { /* UTF-8 - no change */
|
||||
memcpy(dest, source, length);
|
||||
*p_dest_length = length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Only set `p_dest_length` on success, for libzueci compatibility */
|
||||
if ((error_number = utf8_to_eci(eci, source, dest, &length)) == 0) {
|
||||
*p_dest_length = length;
|
||||
}
|
||||
return error_number; /* 0 or ZINT_ERROR_INVALID_DATA */
|
||||
}
|
||||
|
||||
/* Calculate sufficient length needed to convert UTF-8 `source` of length `length` from UTF-8 to `eci`, and place
|
||||
in `p_dest_length`. If `length` is 0 or negative, `source` must be NUL-terminated. Returns 0 on success, else
|
||||
ZINT_ERROR_INVALID_OPTION or ZINT_ERROR_INVALID_DATA. Compatible with libzueci `zueci_dest_len_eci()` */
|
||||
int ZBarcode_Dest_Len_ECI(int eci, const unsigned char *source, int length, int *p_dest_length) {
|
||||
/* Map ECI 0 to ECI 2 (CP437) for libzueci compatibility */
|
||||
if (eci == 0) {
|
||||
eci = 2;
|
||||
}
|
||||
if (!is_valid_char_set_eci(eci) || !source || !p_dest_length) {
|
||||
return ZINT_ERROR_INVALID_OPTION;
|
||||
}
|
||||
if (length <= 0) {
|
||||
length = (int) ustrlen(source); /* Note `zueci_dest_len_eci()` doesn't do this */
|
||||
}
|
||||
if (!is_valid_utf8(source, length)) {
|
||||
return ZINT_ERROR_INVALID_DATA;
|
||||
}
|
||||
*p_dest_length = get_eci_length(eci, source, length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Whether Zint built without PNG support */
|
||||
int ZBarcode_NoPng(void) {
|
||||
#ifdef ZINT_NO_PNG
|
||||
|
||||
@@ -647,6 +647,19 @@ static const unsigned short int windows_1256[] = {
|
||||
0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2
|
||||
};
|
||||
|
||||
/* Taken from https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT */
|
||||
|
||||
static const unsigned short int cp437[] = {
|
||||
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
|
||||
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
|
||||
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
|
||||
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
|
||||
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
|
||||
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
|
||||
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
|
||||
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
|
||||
};
|
||||
|
||||
static void test_utf8_to_eci_sb(const testCtx *const p_ctx) {
|
||||
|
||||
struct item {
|
||||
@@ -674,6 +687,7 @@ static void test_utf8_to_eci_sb(const testCtx *const p_ctx) {
|
||||
/* 16*/ { 22, windows_1251 },
|
||||
/* 17*/ { 23, windows_1252 },
|
||||
/* 18*/ { 24, windows_1256 },
|
||||
/* 19*/ { 2, cp437 },
|
||||
};
|
||||
int data_size = ARRAY_SIZE(data);
|
||||
int i, length, ret;
|
||||
@@ -749,8 +763,8 @@ static void test_utf8_to_eci_ascii(const testCtx *const p_ctx) {
|
||||
/* 16*/ { 170, "~", -1, ZINT_ERROR_INVALID_DATA },
|
||||
/* 17*/ { 170, "\302\200", -1, ZINT_ERROR_INVALID_DATA },
|
||||
/* 18*/ { 170, "~", -1, ZINT_ERROR_INVALID_DATA },
|
||||
/* 19*/ { 1, "A", -1, ZINT_ERROR_INVALID_DATA },
|
||||
/* 20*/ { 2, "A", -1, ZINT_ERROR_INVALID_DATA },
|
||||
/* 19*/ { 1, "A", -1, 0 }, /* Now succeeds (maps to ISO/ECI 8859-1 for libzueci compatibility) */
|
||||
/* 20*/ { 2, "A", -1, 0 }, /* Now succeeds (maps to CP437 for libzueci compatibility) */
|
||||
/* 21*/ { 14, "A", -1, ZINT_ERROR_INVALID_DATA },
|
||||
/* 22*/ { 19, "A", -1, ZINT_ERROR_INVALID_DATA },
|
||||
/* 23*/ { 26, "A", -1, ZINT_ERROR_INVALID_DATA },
|
||||
|
||||
@@ -1,3 +1,34 @@
|
||||
/*
|
||||
libzint - the open source barcode library
|
||||
Copyright (C) 2021-2025 Robin Stuart <rstuart114@gmail.com>
|
||||
|
||||
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 */
|
||||
|
||||
/* Generated by gen_test_tab.php from KSX1001.TXT */
|
||||
static const unsigned int test_ksx1001_tab[] = {
|
||||
0x222E, 0x00A1,
|
||||
@@ -8292,3 +8323,5 @@ static const unsigned int test_ksx1001_tab_ind[] = {
|
||||
15712,
|
||||
16248,
|
||||
};
|
||||
|
||||
/* vim: set ts=4 sw=4 et : */
|
||||
|
||||
@@ -2177,6 +2177,116 @@ static void test_xdimdp_from_scale(const testCtx *const p_ctx) {
|
||||
testFinish();
|
||||
}
|
||||
|
||||
static void test_utf8_to_eci(const testCtx *const p_ctx) {
|
||||
|
||||
struct item {
|
||||
int eci;
|
||||
const char *data;
|
||||
int length;
|
||||
int ret_dest;
|
||||
int expected_dest_length;
|
||||
int ret;
|
||||
const char *expected;
|
||||
int expected_length;
|
||||
};
|
||||
/* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
|
||||
static const struct item data[] = {
|
||||
/* 0*/ { 3, "1234", -1, 0, 4, 0, "1234", -1 },
|
||||
/* 1*/ { 3, "1234", 0, 0, 4, 0, "1234", -1 }, /* Zero length allowed */
|
||||
/* 2*/ { 3, "1234", -2, 0, 4, 0, "1234", -1 }, /* Negative length allowed */
|
||||
/* 3*/ { 3, "", -1, 0, 0, 0, "", 0 }, /* Empty allowed */
|
||||
/* 4*/ { 3, NULL, -1, ZINT_ERROR_INVALID_OPTION, 0, -1, "", -1 },
|
||||
/* 5*/ { -1, "1234", -1, ZINT_ERROR_INVALID_OPTION, 0, -1, "", -1 },
|
||||
/* 6*/ { 0, "1234", -1, 0, 4, 0, "1234", -1 },
|
||||
/* 7*/ { 1, "1234", -1, 0, 4, 0, "1234", -1 },
|
||||
/* 8*/ { 2, "1234", -1, 0, 4, 0, "1234", -1 },
|
||||
/* 9*/ { 0, "1234é", -1, 0, 6, 0, "1234\202", 5 }, /* CP437 */
|
||||
/* 10*/ { 1, "1234é", -1, 0, 6, 0, "1234\351", 5 }, /* Same as ISO/IEC 8859-1 */
|
||||
/* 11*/ { 2, "1234é", -1, 0, 6, 0, "1234\202", 5 }, /* CP437 */
|
||||
/* 12*/ { 3, "1234é", -1, 0, 6, 0, "1234\351", 5 },
|
||||
/* 13*/ { 4, "1234˘", -1, 0, 6, 0, "1234\242", 5 }, /* ISO/IEC 8859-2 */
|
||||
/* 14*/ { 5, "1234Ħ", -1, 0, 6, 0, "1234\241", 5 }, /* ISO/IEC 8859-3 */
|
||||
/* 15*/ { 6, "1234ĸ", -1, 0, 6, 0, "1234\242", 5 }, /* ISO/IEC 8859-4 */
|
||||
/* 16*/ { 7, "1234Ё", -1, 0, 6, 0, "1234\241", 5 }, /* ISO/IEC 8859-5 */
|
||||
/* 17*/ { 8, "1234ء", -1, 0, 6, 0, "1234\301", 5 }, /* ISO/IEC 8859-6 */
|
||||
/* 18*/ { 9, "1234π", -1, 0, 6, 0, "1234\360", 5 }, /* ISO/IEC 8859-7 */
|
||||
/* 19*/ { 11, "1234ğ", -1, 0, 6, 0, "1234\360", 5 }, /* ISO/IEC 8859-9 */
|
||||
/* 20*/ { 12, "1234Ŋ", -1, 0, 6, 0, "1234\257", 5 }, /* ISO/IEC 8859-10 */
|
||||
/* 21*/ { 13, "1234๐", -1, 0, 7, 0, "1234\360", 5 }, /* ISO/IEC 8859-11 */
|
||||
/* 22*/ { 14, "1234", -1, ZINT_ERROR_INVALID_OPTION, 0, -1, "", -1 },
|
||||
/* 23*/ { 15, "1234š", -1, 0, 6, 0, "1234\360", 5 }, /* ISO/IEC 8859-13 */
|
||||
/* 24*/ { 16, "1234ŵ", -1, 0, 6, 0, "1234\360", 5 }, /* ISO/IEC 8859-14 */
|
||||
/* 25*/ { 17, "1234œ", -1, 0, 6, 0, "1234\275", 5 }, /* ISO/IEC 8859-15 */
|
||||
/* 26*/ { 18, "1234Ł", -1, 0, 6, 0, "1234\243", 5 }, /* ISO/IEC 8859-16 */
|
||||
/* 27*/ { 19, "1234", -1, ZINT_ERROR_INVALID_OPTION, 0, -1, "", -1 },
|
||||
/* 28*/ { 20, "1234点", -1, 0, 7, 0, "1234\223\137", 6 }, /* Shift JIS */
|
||||
/* 29*/ { 20, "1234¥", -1, 0, 6, 0, "1234\\", 5 }, /* Shift JIS - Yen sign -> backslash */
|
||||
/* 30*/ { 20, "1234~", -1, 0, 5, ZINT_ERROR_INVALID_DATA, "", -1 }, /* Shift JIS - no mapping for tilde */
|
||||
/* 31*/ { 20, "1234\\", -1, 0, 6, 0, "1234\201\137", -1 }, /* Shift JIS - backslash -> full-width reverse solidus */
|
||||
/* 32*/ { 21, "1234Ą", -1, 0, 6, 0, "1234\245", 5 }, /* Windows-1250 */
|
||||
/* 33*/ { 22, "1234ѓ", -1, 0, 6, 0, "1234\203", 5 }, /* Windows-1251 */
|
||||
/* 34*/ { 23, "1234ƒ", -1, 0, 6, 0, "1234\203", 5 }, /* Windows-1252 */
|
||||
/* 35*/ { 24, "1234پ", -1, 0, 6, 0, "1234\201", 5 }, /* Windows-1256 */
|
||||
/* 36*/ { 25, "1234é", -1, 0, 10, 0, "\0001\0002\0003\0004\000\351", 10 }, /* UTF-16BE */
|
||||
/* 37*/ { 26, "1234é", -1, 0, 6, 0, "1234é", 6 }, /* UTF-8 */
|
||||
/* 38*/ { 27, "1234é", -1, 0, 6, ZINT_ERROR_INVALID_DATA, "", -1 }, /* ASCII */
|
||||
/* 39*/ { 27, "1234", -1, 0, 4, 0, "1234", -1 }, /* ASCII */
|
||||
/* 40*/ { 28, "1234_", -1, 0, 7, 0, "1234\241\304", 6 }, /* Big5 */
|
||||
/* 41*/ { 29, "1234崂", -1, 0, 7, 0, "1234\341\300", 6 }, /* GB 2312 */
|
||||
/* 42*/ { 30, "1234가", -1, 0, 7, 0, "1234\260\241", 6 }, /* EUC-KR */
|
||||
/* 43*/ { 31, "1234郎", -1, 0, 7, 0, "1234\375\234", 6 }, /* GBK */
|
||||
/* 44*/ { 32, "1234崂", -1, 0, 14, 0, "1234\341\300", 6 }, /* GB 18030 */
|
||||
/* 45*/ { 33, "1234é", -1, 0, 10, 0, "1\0002\0003\0004\000\351\000", 10 }, /* UTF-16LE */
|
||||
/* 46*/ { 34, "1234é", -1, 0, 20, 0, "\000\000\0001\000\000\0002\000\000\0003\000\000\0004\000\000\000\351", 20 }, /* UTF-16BE */
|
||||
/* 47*/ { 35, "1234é", -1, 0, 20, 0, "1\000\000\0002\000\000\0003\000\000\0004\000\000\000\351\000\000\000", 20 }, /* UTF-16LE */
|
||||
/* 48*/ { 170, "1234", -1, 0, 4, 0, "1234", 4 }, /* ISO 646 Invariant */
|
||||
/* 49*/ { 170, "1234#", -1, 0, 5, ZINT_ERROR_INVALID_DATA, "", -1 }, /* ISO 646 Invariant */
|
||||
/* 50*/ { 899, "1234\000\127\302\200ÿ", 10, 0, 10, 0, "1234\000\127\200\377", 8 }, /* Binary */
|
||||
};
|
||||
const int data_size = ARRAY_SIZE(data);
|
||||
int i, length, ret;
|
||||
int expected_length;
|
||||
|
||||
testStart("test_utf8_to_eci");
|
||||
|
||||
for (i = 0; i < data_size; i++) {
|
||||
int ret_dest;
|
||||
unsigned char dest[1024];
|
||||
int dest_length;
|
||||
|
||||
if (testContinue(p_ctx, i)) continue;
|
||||
|
||||
length = data[i].length == -1 && data[i].data ? (int) strlen(data[i].data) : data[i].length;
|
||||
|
||||
ret_dest = ZBarcode_Dest_Len_ECI(data[i].eci, TCU(data[i].data), length, &dest_length);
|
||||
assert_equal(ret_dest, data[i].ret_dest, "i:%d ZBarcode_Dest_Len_ECI(%d, %s) ret_dest %d != %d\n",
|
||||
i, data[i].eci, data[i].data, ret_dest, data[i].ret_dest);
|
||||
|
||||
if (ret_dest < ZINT_ERROR) {
|
||||
assert_equal(dest_length, data[i].expected_dest_length,
|
||||
"i:%d ZBarcode_Dest_Len_ECI dest_length %d != expected_dest_length %d\n",
|
||||
i, dest_length, data[i].expected_dest_length);
|
||||
|
||||
expected_length = data[i].expected_length == -1 ? (int) strlen(data[i].expected) : data[i].expected_length;
|
||||
ret = ZBarcode_UTF8_To_ECI(data[i].eci, TCU(data[i].data), length, dest, &dest_length);
|
||||
assert_equal(ret, data[i].ret, "i:%d ZBarcode_UTF8_To_ECI(%d, %s) ret %d != %d\n",
|
||||
i, data[i].eci, data[i].data, ret, data[i].ret);
|
||||
if (ret < ZINT_ERROR) {
|
||||
assert_equal(dest_length, expected_length,
|
||||
"i:%d ZBarcode_UTF8_To_ECI dest_length %d != expected_length %d\n",
|
||||
i, dest_length, expected_length);
|
||||
#if 0
|
||||
printf("dest_length %d\n", dest_length); debug_print_escape(TCU(dest), dest_length, NULL); printf("\n");
|
||||
#endif
|
||||
assert_zero(memcmp(dest, data[i].expected, expected_length), "i:%d memcmp(\"%s\", \"%s\", %d) != 0\n",
|
||||
i, dest, data[i].expected, expected_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
testFinish();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
testFunction funcs[] = { /* name, func */
|
||||
@@ -2205,6 +2315,7 @@ int main(int argc, char *argv[]) {
|
||||
{ "test_reset", test_reset },
|
||||
{ "test_scale_from_xdimdp", test_scale_from_xdimdp },
|
||||
{ "test_xdimdp_from_scale", test_xdimdp_from_scale },
|
||||
{ "test_utf8_to_eci", test_utf8_to_eci },
|
||||
};
|
||||
|
||||
testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/* Generate ECI single-byte tables & routines from unicode.org mapping files */
|
||||
/*
|
||||
libzint - the open source barcode library
|
||||
Copyright (C) 2022-2023 Robin Stuart <rstuart114@gmail.com>
|
||||
Copyright (C) 2022-2025 Robin Stuart <rstuart114@gmail.com>
|
||||
*/
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
@@ -20,12 +20,13 @@ $out_dirname = isset($opts['o']) ? $opts['o'] : ($dirname . '/..'); // Where to
|
||||
$out = array();
|
||||
|
||||
$head = <<<'EOD'
|
||||
/* eci_sb.h - Extended Channel Interpretations single-byte, generated by "backend/tools/gen_eci_sb_h.php"
|
||||
from "https://unicode.org/Public/MAPPINGS/ISO8859/8859-*.TXT"
|
||||
and "https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP125*.TXT" */
|
||||
/* eci_sb.h - Extended Channel Interpretations single-byte, generated by "backend/tools/gen_eci_sb_h.php" from
|
||||
"https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT" (for libzueci compatibility) and
|
||||
"https://unicode.org/Public/MAPPINGS/ISO8859/8859-*.TXT" and
|
||||
"https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP125*.TXT" */
|
||||
/*
|
||||
libzint - the open source barcode library
|
||||
Copyright (C) 2021-2022 Robin Stuart <rstuart114@gmail.com>
|
||||
Copyright (C) 2021-2025 Robin Stuart <rstuart114@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@@ -60,6 +61,95 @@ EOD;
|
||||
|
||||
$out = explode("\n", $head);
|
||||
|
||||
// Read the CP437 file
|
||||
|
||||
$tot_cp437 = 0;
|
||||
|
||||
//$file = $data_dirname . '/' . 'CP437.TXT';
|
||||
$file = 'https://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/CP437.TXT';
|
||||
|
||||
if (($get = file_get_contents($file)) === false) {
|
||||
error_log($error = "$basename: ERROR: Could not read mapping file \"$file\"");
|
||||
exit($error . PHP_EOL);
|
||||
}
|
||||
|
||||
$lines = explode("\n", $get);
|
||||
|
||||
// Parse the file.
|
||||
|
||||
$sort = array();
|
||||
$sb = array();
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === '' || strncmp($line, '0x', 2) !== 0 || strpos($line, "*** NO MAPPING ***") !== false) {
|
||||
continue;
|
||||
}
|
||||
$matches = array();
|
||||
if (preg_match('/^0x([0-9a-f]{2})[ \t]+0x([0-9a-f]{4})[ \t].*$/', $line, $matches)) {
|
||||
$mb = hexdec($matches[1]);
|
||||
$unicode = hexdec($matches[2]);
|
||||
if ($unicode >= 0x80) {
|
||||
$sort[] = $unicode;
|
||||
$sb[] = $mb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array_multisort($sort, $sb);
|
||||
|
||||
// Output.
|
||||
|
||||
$out[] = '';
|
||||
$out[] = '/* Tables for ECI 2 CP437 (for libzueci compatibility) */';
|
||||
$cnt = count($sort);
|
||||
$out[] = 'static const unsigned short cp437_u[' . $cnt . '] = { /* Unicode codepoints sorted */';
|
||||
$line = ' ';
|
||||
for ($i = 0; $i < $cnt; $i++) {
|
||||
if ($i && $i % 8 === 0) {
|
||||
$out[] = $line;
|
||||
$line = ' ';
|
||||
}
|
||||
$line .= sprintf(' 0x%04X,', $sort[$i]);
|
||||
}
|
||||
if ($line !== ' ') {
|
||||
$out[] = $line;
|
||||
}
|
||||
$out[] = '};';
|
||||
$tot_cp437 += $cnt * 2;
|
||||
|
||||
$cnt = count($sb);
|
||||
$out[] = 'static const unsigned char cp437_sb[' . $cnt . '] = { /* Single-byte in Unicode order */';
|
||||
$line = ' ';
|
||||
for ($i = 0; $i < $cnt; $i++) {
|
||||
if ($i && $i % 8 === 0) {
|
||||
$out[] = $line;
|
||||
$line = ' ';
|
||||
}
|
||||
$line .= sprintf(' 0x%02X,', $sb[$i]);
|
||||
}
|
||||
if ($line !== ' ') {
|
||||
$out[] = $line;
|
||||
}
|
||||
$out[] = '};';
|
||||
$tot_cp437 += $cnt;
|
||||
|
||||
$u_sb = array_flip($sb);
|
||||
$b = 0x80;
|
||||
$cnt = 256 - $b;
|
||||
$max_idx = -1;
|
||||
for ($i = 0; $i < $cnt; $i++) {
|
||||
if (isset($u_sb[$i + $b])) {
|
||||
$max_idx = $i;
|
||||
}
|
||||
}
|
||||
$cnt = $max_idx + 1;
|
||||
$tot_cp437 += $cnt;
|
||||
|
||||
if (0) {
|
||||
$out[] = '';
|
||||
$out[] = '/* Total CP437 bytes: ' . $tot_cp437 . ' */';
|
||||
}
|
||||
|
||||
$u_iso8859 = <<<'EOD'
|
||||
|
||||
/* Forward reference to base ISO/IEC 8859 routine - see "eci.c" */
|
||||
|
||||
+14
-2
@@ -141,7 +141,7 @@ extern "C" {
|
||||
/* Segment for use with `ZBarcode_Encode_Segs()` below */
|
||||
struct zint_seg {
|
||||
unsigned char *source; /* Data to encode */
|
||||
int length; /* Length of `source`. If 0, `source` must be NUL-terminated */
|
||||
int length; /* Length of `source`. If 0 or negative, `source` must be NUL-terminated */
|
||||
int eci; /* Extended Channel Interpretation */
|
||||
};
|
||||
|
||||
@@ -405,7 +405,7 @@ extern "C" {
|
||||
ZINT_EXTERN void ZBarcode_Delete(struct zint_symbol *symbol);
|
||||
|
||||
|
||||
/* Encode a barcode. If `length` is 0, `source` must be NUL-terminated */
|
||||
/* Encode a barcode. If `length` is 0 or negative, `source` must be NUL-terminated */
|
||||
ZINT_EXTERN int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int length);
|
||||
|
||||
/* Encode a barcode with multiple ECI segments */
|
||||
@@ -488,6 +488,18 @@ extern "C" {
|
||||
const char *filetype);
|
||||
|
||||
|
||||
/* Convert UTF-8 `source` of length `length` to `eci`-encoded `dest`, setting `p_dest_length` to length of `dest`
|
||||
on output. If `length` is 0 or negative, `source` must be NUL-terminated. Returns 0 on success, else
|
||||
ZINT_ERROR_INVALID_OPTION or ZINT_ERROR_INVALID_DATA. Compatible with libzueci `zueci_utf8_to_eci()` */
|
||||
ZINT_EXTERN int ZBarcode_UTF8_To_ECI(int eci, const unsigned char *source, int length, unsigned char dest[],
|
||||
int *p_dest_length);
|
||||
|
||||
/* Calculate sufficient length needed to convert UTF-8 `source` of length `length` from UTF-8 to `eci`, and place
|
||||
in `p_dest_length`. If `length` is 0 or negative, `source` must be NUL-terminated. Returns 0 on success, else
|
||||
ZINT_ERROR_INVALID_OPTION or ZINT_ERROR_INVALID_DATA. Compatible with libzueci `zueci_dest_len_eci()` */
|
||||
ZINT_EXTERN int ZBarcode_Dest_Len_ECI(int eci, const unsigned char *source, int length, int *p_dest_length);
|
||||
|
||||
|
||||
/* Whether Zint built without PNG support */
|
||||
ZINT_EXTERN int ZBarcode_NoPng(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user