diff --git a/backend/raster.c b/backend/raster.c index 3af6ba2d..c15c26d8 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -83,7 +83,7 @@ static int buffer_plot(struct zint_symbol *symbol, char *pixelbuf) { bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]); bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]); bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]); - + for (row = 0; row < symbol->bitmap_height; row++) { for (column = 0; column < symbol->bitmap_width; column++) { i = ((row * symbol->bitmap_width) + column) * 3; @@ -643,6 +643,45 @@ static int plot_raster_dotty(struct zint_symbol *symbol, int rotate_angle, int d return error_number; } +/* Convert UTF-8 to Latin1 Codepage for the interpretation line */ +static void to_latin1(const unsigned char source[], unsigned char preprocessed[]) { + int j, i, input_length; + + input_length = ustrlen(source); + + j = 0; + i = 0; + while (i < input_length) { + switch (source[i]) { + case 0xC2: + /* UTF-8 C2xxh */ + /* Character range: C280h (latin: 80h) to C2BFh (latin: BFh) */ + i++; + preprocessed[j] = source[i]; + j++; + break; + case 0xC3: + /* UTF-8 C3xx */ + /* Character range: C380h (latin: C0h) to C3BFh (latin: FFh) */ + i++; + preprocessed[j] = source[i] + 64; + j++; + break; + default: + /* Process ASCII (< 80h), all other unicode points are ignored */ + if (source[i] < 128) { + preprocessed[j] = source[i]; + j++; + } + break; + } + i++; + } + preprocessed[j] = '\0'; + + return; +} + static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int data_type) { int error_number; double large_bar_height; @@ -915,9 +954,15 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } if (!textdone) { +#ifndef _MSC_VER + unsigned char local_text[ustrlen(symbol->text) + 1]; +#else + unsigned char* local_text = (unsigned char*) _alloca(ustrlen(symbol->text) + 1); +#endif + to_latin1(symbol->text, local_text); /* Put the human readable text at the bottom */ textpos = 2 * (main_width / 2 + xoffset); - draw_string(pixelbuf, symbol->text, textpos, default_text_posn, textflags, image_width, image_height); + draw_string(pixelbuf, local_text, textpos, default_text_posn, textflags, image_width, image_height); } } diff --git a/backend/tests/test_raster.c b/backend/tests/test_raster.c index bdfac75d..2efb8d33 100644 --- a/backend/tests/test_raster.c +++ b/backend/tests/test_raster.c @@ -684,6 +684,71 @@ static void test_draw_string_wrap(int index, int debug) { testFinish(); } +static void test_code128_utf8(int index, int debug) { + + testStart(""); + + int ret; + struct item { + unsigned char *data; + + int expected_height; + int expected_rows; + int expected_width; + int expected_bitmap_width; + int expected_bitmap_height; + int expected_text_row; + int expected_text_col; + int expected_text_len; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "é", 50, 1, 57, 114, 118, 109, 53, 6 }, + }; + int data_size = ARRAY_SIZE(data); + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, BARCODE_CODE128, UNICODE_MODE, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, data[i].data, length); + assert_zero(ret, "i:%d ZBarcode_Encode(%d) ret %d != 0 %s\n", i, BARCODE_CODE128, ret, symbol->errtxt); + + ret = ZBarcode_Buffer(symbol, 0); + assert_zero(ret, "i:%d ZBarcode_Buffer(%d) ret %d != 0\n", i, BARCODE_CODE128, ret); + assert_nonnull(symbol->bitmap, "i:%d (%d) symbol->bitmap NULL\n", i, BARCODE_CODE128); + + assert_equal(symbol->height, data[i].expected_height, "i:%d (%d) symbol->height %d != %d\n", i, BARCODE_CODE128, symbol->height, data[i].expected_height); + assert_equal(symbol->rows, data[i].expected_rows, "i:%d (%d) symbol->rows %d != %d\n", i, BARCODE_CODE128, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d (%d) symbol->width %d != %d\n", i, BARCODE_CODE128, symbol->width, data[i].expected_width); + assert_equal(symbol->bitmap_width, data[i].expected_bitmap_width, "i:%d (%d) symbol->bitmap_width %d != %d\n", i, BARCODE_CODE128, symbol->bitmap_width, data[i].expected_bitmap_width); + assert_equal(symbol->bitmap_height, data[i].expected_bitmap_height, "i:%d (%d) symbol->bitmap_height %d != %d\n", i, BARCODE_CODE128, symbol->bitmap_height, data[i].expected_bitmap_height); + + if (index != -1) testUtilBitmapPrint(symbol); + + ret = ZBarcode_Print(symbol, 0); + assert_zero(ret, "i:%d ZBarcode_Print(%d) ret %d != 0\n", i, BARCODE_CODE128, ret); + + int text_bits_set = 0; + int row = data[i].expected_text_row; + for (int column = data[i].expected_text_col; column < data[i].expected_text_col + data[i].expected_text_len; column++) { + if (is_row_column_black(symbol, row, column)) { + text_bits_set++; + } + } + assert_equal(text_bits_set, data[i].expected_text_len, "i:%d (%d) text_bits_set %d != expected_text_len %d\n", i, BARCODE_CODE128, text_bits_set, data[i].expected_text_len); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -693,6 +758,7 @@ int main(int argc, char *argv[]) { { "test_row_separator", test_row_separator, 1, 0, 1 }, { "test_output_options", test_output_options, 1, 0, 1 }, { "test_draw_string_wrap", test_draw_string_wrap, 1, 0, 1 }, + { "test_code128_utf8", test_code128_utf8, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs));