From ad28de1819c75a3c2e93fc06bb5704606cb186a3 Mon Sep 17 00:00:00 2001 From: Robin Stuart Date: Mon, 25 Nov 2019 19:08:25 +0000 Subject: [PATCH] Initial implementation of rMQR According to draft dated June 2018 --- backend/library.c | 53 +++-- backend/qr.c | 547 +++++++++++++++++++++++++++++++++++++++++----- backend/qr.h | 141 +++++++++++- backend/svg.c | 2 +- backend/zint.h | 243 ++++++++++---------- frontend/main.c | 8 +- 6 files changed, 783 insertions(+), 211 deletions(-) diff --git a/backend/library.c b/backend/library.c index 48a9c62d..99727b1b 100644 --- a/backend/library.c +++ b/backend/library.c @@ -181,6 +181,7 @@ extern int dmatrix(struct zint_symbol *symbol, const unsigned char source[], con extern int vin(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* VIN Code (Vehicle Identification Number) */ extern int mailmark(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Royal Mail 4-state Mailmark */ extern int ultracode(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Ultracode */ +extern int rmqr(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* rMQR */ extern int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */ extern int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to EPS/EMF/SVG */ @@ -385,7 +386,7 @@ static void check_row_heights(struct zint_symbol *symbol) { static int check_force_gs1(const int symbology) { /* Returns 1 if symbology MUST have GS1 data */ - + int result = is_composite(symbology); switch (symbology) { @@ -397,7 +398,7 @@ static int check_force_gs1(const int symbology) { result = 1; break; } - + return result; } @@ -414,6 +415,7 @@ static int gs1_compliant(const int symbology) { case BARCODE_CODE49: case BARCODE_QRCODE: case BARCODE_DOTCODE: + case BARCODE_RMQR: result = 1; break; } @@ -440,6 +442,7 @@ static int is_matrix(const int symbology) { case BARCODE_HANXIN: case BARCODE_DOTCODE: case BARCODE_UPNQR: + case BARCODE_RMQR: result = 1; break; } @@ -449,7 +452,7 @@ static int is_matrix(const int symbology) { static int is_linear(const int symbology) { /* Returns 1 if symbology is linear (1 dimensional) */ - + int result = 0; switch (symbology) { case BARCODE_CODE11: @@ -506,7 +509,7 @@ static int is_linear(const int symbology) { result = 1; break; } - + return result; } @@ -633,6 +636,7 @@ int ZBarcode_ValidID(int symbol_id) { case BARCODE_VIN: case BARCODE_MAILMARK: case BARCODE_ULTRA: + case BARCODE_RMQR: result = 1; break; } @@ -642,7 +646,7 @@ int ZBarcode_ValidID(int symbol_id) { static int extended_charset(struct zint_symbol *symbol, const unsigned char *source, const int length) { int error_number = 0; - + /* These are the "elite" standards which can support multiple character sets */ switch (symbol->symbology) { case BARCODE_QRCODE: error_number = qr_code(symbol, source, length); @@ -655,6 +659,8 @@ static int extended_charset(struct zint_symbol *symbol, const unsigned char *sou break; case BARCODE_UPNQR: error_number = upnqr(symbol, source, length); break; + case BARCODE_RMQR: error_number = rmqr(symbol, source, length); + break; } return error_number; @@ -669,7 +675,7 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour #else unsigned char* preprocessed = (unsigned char*) _alloca(in_length + 1); #endif - + if (symbol->symbology == BARCODE_CODE16K) { symbol->whitespace_width = 16; symbol->border_width = 2; @@ -685,7 +691,7 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour symbol->output_options += BARCODE_BOX; } } - + switch (symbol->input_mode & 0x07) { case DATA_MODE: case GS1_MODE: @@ -700,11 +706,11 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour } break; } - + if ((symbol->height == 0) && is_linear(symbol->symbology)) { symbol->height = 50; } - + switch (symbol->symbology) { case BARCODE_C25MATRIX: error_number = matrix_two_of_five(symbol, preprocessed, in_length); break; @@ -894,7 +900,7 @@ int escape_char_process(struct zint_symbol *symbol, unsigned char *input_string, in_posn = 0; out_posn = 0; - + do { if (input_string[in_posn] == '\\') { switch (input_string[in_posn + 1]) { @@ -968,11 +974,11 @@ int escape_char_process(struct zint_symbol *symbol, unsigned char *input_string, } out_posn++; } while (in_posn < *length); - + memcpy(input_string, escaped_string, out_posn); input_string[out_posn] = '\0'; *length = out_posn; - + error_number = 0; return error_number; @@ -1125,7 +1131,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int } } /* Everything from 128 up is Zint-specific */ - if (symbol->symbology >= 145) { + if (symbol->symbology > 145) { strcpy(symbol->errtxt, "216: Symbology out of range, using Code 128"); symbol->symbology = BARCODE_CODE128; error_number = ZINT_WARN_INVALID_OPTION; @@ -1193,7 +1199,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int if ((input_mode < 0) || (input_mode > 2)) { input_mode = DATA_MODE; } - + if ((symbol->eci != 0) && (symbol->eci != 26)) { input_mode = DATA_MODE; } @@ -1201,13 +1207,14 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int if (input_mode == UNICODE_MODE) { strip_bom(local_source, &in_length); } - + switch (symbol->symbology) { case BARCODE_QRCODE: case BARCODE_MICROQR: case BARCODE_GRIDMATRIX: case BARCODE_HANXIN: case BARCODE_UPNQR: + case BARCODE_RMQR: error_number = extended_charset(symbol, local_source, in_length); break; default: @@ -1247,7 +1254,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int error_number = reduced_charset(symbol, local_source, in_length); break; } - + if (error_number == 0) { error_number = ZINT_WARN_USES_ECI; strcpy(symbol->errtxt, "222: Encoded data includes ECI"); @@ -1341,7 +1348,7 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { error_number = dump_plot(symbol); } else if (!(strcmp(output, "EPS"))) { - error_number = plot_vector(symbol, rotate_angle, OUT_EPS_FILE); + error_number = plot_vector(symbol, rotate_angle, OUT_EPS_FILE); } else if (!(strcmp(output, "SVG"))) { error_number = plot_vector(symbol, rotate_angle, OUT_SVG_FILE); @@ -1434,7 +1441,7 @@ int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input, if (error_number == 0) { error_number = first_err; } - + return error_number; } @@ -1452,7 +1459,7 @@ int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, unsigned char if (error_number == 0) { error_number = first_err; } - + return error_number; } @@ -1523,13 +1530,13 @@ int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, i if (error_number >= 5) { return error_number; } - + first_err = error_number; error_number = ZBarcode_Print(symbol, rotate_angle); if (error_number == 0) { error_number = first_err; } - + return error_number; } @@ -1541,7 +1548,7 @@ int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename, if (error_number >= 5) { return error_number; } - + first_err = error_number; error_number = ZBarcode_Buffer(symbol, rotate_angle); if (error_number == 0) { @@ -1559,7 +1566,7 @@ int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol, char *fil if (error_number >= 5) { return error_number; } - + first_err = error_number; error_number = ZBarcode_Buffer_Vector(symbol, rotate_angle); if (error_number == 0) { diff --git a/backend/qr.c b/backend/qr.c index 6793d6fd..bc321f8f 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -1,8 +1,7 @@ -/* qr.c Handles QR Code */ +/* qr.c Handles QR Code, Micro QR Code, UPNQR and rMQR -/* libzint - the open source barcode library - Copyright (C) 2009 -2017 Robin Stuart + Copyright (C) 2009 - 2019 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -147,7 +146,7 @@ static int tribus(const int version,const int a,const int b,const int c) { } /* Convert input data to a binary stream and add padding */ -static void qr_binary(int datastream[], const int version, const int target_binlen, const char mode[], const int jisdata[], const size_t length, const int gs1, const int eci, const int est_binlen,const int debug) { +static void qr_binary(int datastream[], const int version, const int target_codewords, const char mode[], const int jisdata[], const size_t length, const int gs1, const int eci, const int est_binlen,const int debug) { int position = 0; int i; char padbits; @@ -163,10 +162,14 @@ static void qr_binary(int datastream[], const int version, const int target_binl strcpy(binary, ""); if (gs1) { - strcat(binary, "0101"); /* FNC1 */ + if (version < RMQR_VERSION) { + strcat(binary, "0101"); /* FNC1 */ + } else { + strcat(binary, "101"); + } } - if (eci != 0) { + if (eci != 0) { /* Not applicable to RMQR */ strcat(binary, "0111"); /* ECI (Table 4) */ if (eci <= 127) { bin_append(eci, 8, binary); /* 000000 to 000127 */ @@ -198,10 +201,18 @@ static void qr_binary(int datastream[], const int version, const int target_binl case 'K': /* Kanji mode */ /* Mode indicator */ - strcat(binary, "1000"); + if (version < RMQR_VERSION) { + strcat(binary, "1000"); + } else { + strcat(binary, "100"); + } /* Character count indicator */ - bin_append(short_data_block_length, tribus(version, 8, 10, 12), binary); + if (version < RMQR_VERSION) { + bin_append(short_data_block_length, tribus(version, 8, 10, 12), binary); + } else { + bin_append(short_data_block_length, rmqr_kanji_cci[version - RMQR_VERSION], binary); + } if (debug) { printf("Kanji block (length %d)\n\t", short_data_block_length); @@ -235,10 +246,18 @@ static void qr_binary(int datastream[], const int version, const int target_binl case 'B': /* Byte mode */ /* Mode indicator */ - strcat(binary, "0100"); + if (version < RMQR_VERSION) { + strcat(binary, "0100"); + } else { + strcat(binary, "011"); + } /* Character count indicator */ - bin_append(short_data_block_length, tribus(version, 8, 16, 16), binary); + if (version < RMQR_VERSION) { + bin_append(short_data_block_length, tribus(version, 8, 16, 16), binary); + } else { + bin_append(short_data_block_length, rmqr_byte_cci[version - RMQR_VERSION], binary); + } if (debug) { printf("Byte block (length %d)\n\t", short_data_block_length); @@ -267,7 +286,11 @@ static void qr_binary(int datastream[], const int version, const int target_binl case 'A': /* Alphanumeric mode */ /* Mode indicator */ - strcat(binary, "0010"); + if (version < RMQR_VERSION) { + strcat(binary, "0010"); + } else { + strcat(binary, "010"); + } percent_count = 0; for (i = 0; i < short_data_block_length; i++) { @@ -275,9 +298,13 @@ static void qr_binary(int datastream[], const int version, const int target_binl percent_count++; } } - + /* Character count indicator */ - bin_append(short_data_block_length + percent_count, tribus(version, 9, 11, 13), binary); + if (version < RMQR_VERSION) { + bin_append(short_data_block_length + percent_count, tribus(version, 9, 11, 13), binary); + } else { + bin_append(short_data_block_length + percent_count, rmqr_alphanum_cci[version - RMQR_VERSION], binary); + } if (debug) { printf("Alpha block (length %d)\n\t", short_data_block_length + percent_count); @@ -365,10 +392,18 @@ static void qr_binary(int datastream[], const int version, const int target_binl case 'N': /* Numeric mode */ /* Mode indicator */ - strcat(binary, "0001"); + if (version >= RMQR_VERSION) { + strcat(binary, "0001"); + } else { + strcat(binary, "001"); + } /* Character count indicator */ - bin_append(short_data_block_length, tribus(version, 10, 12, 14), binary); + if (version < RMQR_VERSION) { + bin_append(short_data_block_length, tribus(version, 10, 12, 14), binary); + } else { + bin_append(short_data_block_length, rmqr_numeric_cci[version - RMQR_VERSION], binary); + } if (debug) { printf("Number block (length %d)\n\t", short_data_block_length); @@ -416,7 +451,11 @@ static void qr_binary(int datastream[], const int version, const int target_binl } while (position < length); /* Terminator */ - strcat(binary, "0000"); + if (version < RMQR_VERSION) { + strcat(binary, "0000"); + } else { + strcat(binary, "000"); + } current_binlen = (int)strlen(binary); padbits = 8 - (current_binlen % 8); @@ -443,7 +482,7 @@ static void qr_binary(int datastream[], const int version, const int target_binl /* Add pad codewords */ toggle = 0; - for (i = current_bytes; i < target_binlen; i++) { + for (i = current_bytes; i < target_codewords; i++) { if (toggle == 0) { datastream[i] = 0xec; toggle = 1; @@ -455,7 +494,7 @@ static void qr_binary(int datastream[], const int version, const int target_binl if (debug) { printf("Resulting codewords:\n\t"); - for (i = 0; i < target_binlen; i++) { + for (i = 0; i < target_codewords; i++) { printf("0x%2X ", datastream[i]); } printf("\n"); @@ -463,14 +502,20 @@ static void qr_binary(int datastream[], const int version, const int target_binl } /* Split data into blocks, add error correction and then interleave the blocks and error correction data */ -static void add_ecc(int fullstream[],const int datastream[],const int version,const int data_cw,const int blocks) { - int ecc_cw = qr_total_codewords[version - 1] - data_cw; +static void add_ecc(int fullstream[],const int datastream[],const int version,const int data_cw,const int blocks,int debug) { + int ecc_cw; + + if (version < RMQR_VERSION) { + ecc_cw = qr_total_codewords[version - 1] - data_cw; + } else { + ecc_cw = rmqr_total_codewords[version - RMQR_VERSION] - data_cw; + } + int short_data_block_length = data_cw / blocks; int qty_long_blocks = data_cw % blocks; int qty_short_blocks = blocks - qty_long_blocks; int ecc_block_length = ecc_cw / blocks; - int i, j, length_this_block, posn, debug = 0; - + int i, j, length_this_block, posn; #ifndef _MSC_VER unsigned char data_block[short_data_block_length + 2]; @@ -670,35 +715,36 @@ static int cwbit(const int* fullstream,const int i) { return resultant; } -static void populate_grid(unsigned char* grid,const int size,const int* fullstream,const int cw) { +static void populate_grid(unsigned char* grid,const int h_size,const int v_size,const int* fullstream,const int cw) { int direction = 1; /* up */ int row = 0; /* right hand side */ int i, n, y; n = cw * 8; - y = size - 1; + y = v_size - 1; i = 0; do { - int x = (size - 2) - (row * 2); - if (x < 6) + int x = (h_size - 2) - (row * 2); + + if ((x < 6) && (v_size == h_size)) x--; /* skip over vertical timing pattern */ - if (!(grid[(y * size) + (x + 1)] & 0xf0)) { + if (!(grid[(y * h_size) + (x + 1)] & 0xf0)) { if (cwbit(fullstream, i)) { - grid[(y * size) + (x + 1)] = 0x01; + grid[(y * h_size) + (x + 1)] = 0x01; } else { - grid[(y * size) + (x + 1)] = 0x00; + grid[(y * h_size) + (x + 1)] = 0x00; } i++; } if (i < n) { - if (!(grid[(y * size) + x] & 0xf0)) { + if (!(grid[(y * h_size) + x] & 0xf0)) { if (cwbit(fullstream, i)) { - grid[(y * size) + x] = 0x01; + grid[(y * h_size) + x] = 0x01; } else { - grid[(y * size) + x] = 0x00; + grid[(y * h_size) + x] = 0x00; } i++; } @@ -715,10 +761,10 @@ static void populate_grid(unsigned char* grid,const int size,const int* fullstre y = 0; direction = 0; } - if (y == size) { + if (y == v_size) { /* reached the bottom */ row++; - y = size - 1; + y = v_size - 1; direction = 1; } } while (i < n); @@ -1335,11 +1381,15 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat currentMode = ' '; // Null if (gs1 == 1) { - count += 4; + if (version < RMQR_VERSION) { + count += 4; + } else { + count += 3; + } } if (eci != 0) { - count += 12; + count += 12; // RMQR does not support ECI } for (i = 0; i < inputLength; i++) { @@ -1347,11 +1397,19 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat count += 4; switch (inputMode[i]) { case 'K': - count += tribus(version, 8, 10, 12); + if (version < RMQR_VERSION) { + count += tribus(version, 8, 10, 12); + } else { + count += 3 + rmqr_kanji_cci[version - RMQR_VERSION]; + } count += (blockLength(i, inputMode, inputLength) * 13); break; case 'B': - count += tribus(version, 8, 16, 16); + if (version < RMQR_VERSION) { + count += tribus(version, 8, 16, 16); + } else { + count += 3 + rmqr_byte_cci[version - RMQR_VERSION]; + } for (j = i; j < (i + blockLength(i, inputMode, inputLength)); j++) { if (inputData[j] > 0xff) { count += 16; @@ -1361,7 +1419,11 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat } break; case 'A': - count += tribus(version, 9, 11, 13); + if (version < RMQR_VERSION) { + count += tribus(version, 9, 11, 13); + } else { + count += 3 + rmqr_alphanum_cci[version - RMQR_VERSION]; + } alphalength = blockLength(i, inputMode, inputLength); // In alphanumeric mode % becomes %% for (j = i; j < (i + alphalength); j++) { @@ -1381,7 +1443,11 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat } break; case 'N': - count += tribus(version, 10, 12, 14); + if (version < RMQR_VERSION) { + count += tribus(version, 10, 12, 14); + } else { + count += 3 + rmqr_numeric_cci[version - RMQR_VERSION]; + } switch (blockLength(i, inputMode, inputLength) % 3) { case 0: count += (blockLength(i, inputMode, inputLength) / 3) * 10; @@ -1406,7 +1472,7 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t length) { int i, j, est_binlen; - int ecc_level, autosize, version, max_cw, target_binlen, blocks, size; + int ecc_level, autosize, version, max_cw, target_codewords, blocks, size; int bitmask, gs1; int canShrink; @@ -1569,7 +1635,7 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len return ZINT_ERROR_TOO_LONG; } } - + /* Ensure maxium error correction capacity */ if (est_binlen <= qr_data_codewords_M[version - 1] * 8) { ecc_level = LEVEL_M; @@ -1581,30 +1647,30 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len ecc_level = LEVEL_H; } - target_binlen = qr_data_codewords_L[version - 1]; + target_codewords = qr_data_codewords_L[version - 1]; blocks = qr_blocks_L[version - 1]; switch (ecc_level) { - case LEVEL_M: target_binlen = qr_data_codewords_M[version - 1]; + case LEVEL_M: target_codewords = qr_data_codewords_M[version - 1]; blocks = qr_blocks_M[version - 1]; break; - case LEVEL_Q: target_binlen = qr_data_codewords_Q[version - 1]; + case LEVEL_Q: target_codewords = qr_data_codewords_Q[version - 1]; blocks = qr_blocks_Q[version - 1]; break; - case LEVEL_H: target_binlen = qr_data_codewords_H[version - 1]; + case LEVEL_H: target_codewords = qr_data_codewords_H[version - 1]; blocks = qr_blocks_H[version - 1]; break; } #ifndef _MSC_VER - int datastream[target_binlen + 1]; + int datastream[target_codewords + 1]; int fullstream[qr_total_codewords[version - 1] + 1]; #else - datastream = (int *) _alloca((target_binlen + 1) * sizeof (int)); + datastream = (int *) _alloca((target_codewords + 1) * sizeof (int)); fullstream = (int *) _alloca((qr_total_codewords[version - 1] + 1) * sizeof (int)); #endif - qr_binary(datastream, version, target_binlen, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug); - add_ecc(fullstream, datastream, version, target_binlen, blocks); + qr_binary(datastream, version, target_codewords, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug); + add_ecc(fullstream, datastream, version, target_codewords, blocks, symbol->debug); size = qr_sizes[version - 1]; #ifndef _MSC_VER @@ -1620,7 +1686,7 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len } setup_grid(grid, size, version); - populate_grid(grid, size, fullstream, qr_total_codewords[version - 1]); + populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); if (version >= 7) { add_version_info(grid, size, version); @@ -1647,8 +1713,6 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len return 0; } -/* NOTE: From this point forward concerns Micro QR Code only */ - static int micro_qr_intermediate(char binary[], const int jisdata[], const char mode[], const size_t length, int *kanji_used, int *alphanum_used, int *byte_used,const int debug) { /* Convert input data to an "intermediate stage" where data is binary encoded but control information is not */ @@ -2901,7 +2965,7 @@ int microqr(struct zint_symbol *symbol, const unsigned char source[], size_t len /* For UPNQR the symbol size and error correction capacity is fixed */ int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t length) { int i, j, est_binlen; - int ecc_level, version, target_binlen, blocks, size; + int ecc_level, version, target_codewords, blocks, size; int bitmask, error_number; #ifndef _MSC_VER @@ -2958,19 +3022,19 @@ int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t lengt version = 15; // 77 x 77 - target_binlen = qr_data_codewords_M[version - 1]; + target_codewords = qr_data_codewords_M[version - 1]; blocks = qr_blocks_M[version - 1]; #ifndef _MSC_VER - int datastream[target_binlen + 1]; + int datastream[target_codewords + 1]; int fullstream[qr_total_codewords[version - 1] + 1]; #else - datastream = (int *) _alloca((target_binlen + 1) * sizeof (int)); + datastream = (int *) _alloca((target_codewords + 1) * sizeof (int)); fullstream = (int *) _alloca((qr_total_codewords[version - 1] + 1) * sizeof (int)); #endif - qr_binary(datastream, version, target_binlen, mode, jisdata, length, 0, symbol->eci, est_binlen, symbol->debug); - add_ecc(fullstream, datastream, version, target_binlen, blocks); + qr_binary(datastream, version, target_codewords, mode, jisdata, length, 0, symbol->eci, est_binlen, symbol->debug); + add_ecc(fullstream, datastream, version, target_codewords, blocks, symbol->debug); size = qr_sizes[version - 1]; #ifndef _MSC_VER @@ -2986,7 +3050,7 @@ int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t lengt } setup_grid(grid, size, version); - populate_grid(grid, size, fullstream, qr_total_codewords[version - 1]); + populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); add_version_info(grid, size, version); @@ -3009,4 +3073,367 @@ int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t lengt return 0; } +static void setup_rmqr_grid(unsigned char* grid,const int h_size,const int v_size,const int version) { + int i, j; + char alignment[] = {0x1F, 0x11, 0x15, 0x11, 0x1F}; + int h_version, finder_position; + /* Add timing patterns - top and bottom */ + for (i = 0; i < h_size; i++) { + if (i % 2) { + grid[i] = 0x20; + grid[((v_size - 1) * h_size) + i] = 0x20; + } else { + grid[i] = 0x21; + grid[((v_size - 1) * h_size) + i] = 0x21; + } + } + + /* Add timing patterns - left and right */ + for (i = 0; i < v_size; i++) { + if (i % 2) { + grid[i * h_size] = 0x20; + grid[(i * h_size) + (h_size - 1)] = 0x20; + } else { + grid[i * h_size] = 0x21; + grid[(i * h_size) + (h_size - 1)] = 0x21; + } + } + + /* Add finder pattern */ + place_finder(grid, h_size, 0, 0); // This works because finder is always top left + + /* Add finder sub-pattern to bottom right */ + for (i = 0; i < 5; i++) { + for (j = 0; j < 5; j++) { + if (alignment[j] & 0x10 >> i) { + grid[((v_size - 5) * h_size) + (h_size * i) + (h_size - 5) + j] = 0x11; + } else { + grid[((v_size - 5) * h_size) + (h_size * i) + (h_size - 5) + j] = 0x10; + } + } + } + + /* Add corner finder pattern - bottom left */ + grid[(v_size - 2) * h_size] = 0x11; + grid[((v_size - 2) * h_size) + 1] = 0x10; + grid[((v_size - 1) * h_size) + 1] = 0x11; + + /* Add corner finder pattern - top right */ + grid[h_size - 2] = 0x11; + grid[(h_size * 2) - 2] = 0x10; + grid[(h_size * 2) - 1] = 0x11; + + /* Add seperator */ + for (i = 0; i < 7; i++) { + grid[(i * h_size) + 7] = 0x20; + } + if (v_size > 7) { + // Note for v_size = 9 this overrides the bottom right corner finder pattern + for(i = 0; i < 8; i++) { + grid[(7 * h_size) + i] = 0x20; + } + } + + /* Add alignment patterns */ + if (h_size > 27) { + for(i = 0; i < 5; i++) { + if (h_size == rmqr_width[i]) { + h_version = i; + } + } + + for(i = 0; i < 4; i++) { + finder_position = rmqr_table_d1[(h_version * 4) + i]; + + if (finder_position != 0) { + for (j = 0; j < v_size; j++) { + if (j % 2) { + grid[(j * h_size) + finder_position] = 0x10; + } else { + grid[(j * h_size) + finder_position] = 0x11; + } + } + + // Top square + grid[h_size + finder_position - 1] = 0x11; + grid[(h_size * 2) + finder_position - 1] = 0x11; + grid[h_size + finder_position + 1] = 0x11; + grid[(h_size * 2) + finder_position + 1] = 0x11; + + // Bottom square + grid[(h_size * (v_size - 3)) + finder_position - 1] = 0x11; + grid[(h_size * (v_size - 2)) + finder_position - 1] = 0x11; + grid[(h_size * (v_size - 3)) + finder_position + 1] = 0x11; + grid[(h_size * (v_size - 2)) + finder_position + 1] = 0x11; + } + } + } + + /* Reserve space for format information */ + for (i = 0; i < 5; i++) { + for (j = 0; j < 3; j++) { + grid[(h_size * (i + 1)) + j + 8] = 0x20; + grid[(h_size * (v_size - 6)) + (h_size * i) + j + (h_size - 8)] = 0x20; + } + } + grid[(h_size * 1) + 11] = 0x20; + grid[(h_size * 2) + 11] = 0x20; + grid[(h_size * 3) + 11] = 0x20; + grid[(h_size * (v_size - 6)) + (h_size - 5)] = 0x20; + grid[(h_size * (v_size - 6)) + (h_size - 4)] = 0x20; + grid[(h_size * (v_size - 6)) + (h_size - 3)] = 0x20; +} + +/* rMQR according to 2018 draft standard */ +int rmqr(struct zint_symbol *symbol, const unsigned char source[], size_t length) { + int i, j, est_binlen; + int ecc_level, autosize, version, max_cw, target_codewords, blocks, h_size, v_size; + int gs1; + int footprint, best_footprint, format_data; + unsigned int left_format_info, right_format_info; + +#ifndef _MSC_VER + int utfdata[length + 1]; + int jisdata[length + 1]; + char mode[length + 1]; +#else + int* datastream; + int* fullstream; + unsigned char* grid; + int* utfdata = (int *) _alloca((length + 1) * sizeof (int)); + int* jisdata = (int *) _alloca((length + 1) * sizeof (int)); + char* mode = (char *) _alloca(length + 1); +#endif + + gs1 = (symbol->input_mode == GS1_MODE); + + if ((symbol->input_mode == DATA_MODE) || (symbol->eci != 0)) { + for (i = 0; i < length; i++) { + jisdata[i] = (int) source[i]; + } + } else { + /* Convert Unicode input to Shift-JIS */ + int error_number = utf8toutf16(symbol, source, utfdata, &length); + if (error_number != 0) { + return error_number; + } + + for (i = 0; i < length; i++) { + if (utfdata[i] <= 0xff) { + jisdata[i] = utfdata[i]; + } else { + int glyph = 0; + j = 0; + do { + if (sjis_lookup[j * 2] == utfdata[i]) { + glyph = sjis_lookup[(j * 2) + 1]; + } + j++; + } while ((j < 6843) && (glyph == 0)); + if (glyph == 0) { + strcpy(symbol->errtxt, "575: Invalid character in input data"); + return ZINT_ERROR_INVALID_DATA; + } + jisdata[i] = glyph; + } + } + } + + define_mode(mode, jisdata, length, gs1); + est_binlen = getBinaryLength(RMQR_VERSION + 31, mode, jisdata, length, gs1, symbol->eci); + + ecc_level = LEVEL_M; + max_cw = 152; + if (symbol->option_1 == 1) { + strcpy(symbol->errtxt, "576: Error correction level L not available in rMQR"); + return ZINT_ERROR_INVALID_OPTION; + } + + if (symbol->option_1 == 3) { + strcpy(symbol->errtxt, "577: Error correction level Q not available in rMQR"); + return ZINT_ERROR_INVALID_OPTION; + } + + if (symbol->option_1 == 4) { + ecc_level = LEVEL_H; + max_cw = 76; + } + + if (est_binlen > (8 * max_cw)) { + strcpy(symbol->errtxt, "578: Input too long for selected error correction level"); + return ZINT_ERROR_TOO_LONG; + } + + if ((symbol->option_2 < 0) || (symbol->option_2 > 38)) { + strcpy(symbol->errtxt, "579: Invalid rMQR symbol size"); + return ZINT_ERROR_INVALID_OPTION; + } + + version = 31; // Set default to keep compiler happy + + if (symbol->option_2 == 0) { + // Automatic symbol size + autosize = 31; + best_footprint = rmqr_height[31] * rmqr_width[31]; + for (version = 30; version >= 0; version--) { + est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci); + footprint = rmqr_height[version] * rmqr_width[version]; + if (ecc_level == LEVEL_M) { + if (rmqr_data_codewords_M[version] >= (est_binlen / 8)) { + if (footprint < best_footprint) { + autosize = version; + best_footprint = footprint; + } + } + } else { + if (rmqr_data_codewords_H[version] >= (est_binlen / 8)) { + if (footprint < best_footprint) { + autosize = version; + best_footprint = footprint; + } + } + } + } + version = autosize; + est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci); + } + + if ((symbol->option_2 >= 1) && (symbol->option_2 <= 32)) { + // User specified symbol size + version = symbol->option_2 - 1; + } + + if (symbol->option_2 >= 33) { + // User has specified symbol height only + version = rmqr_fixed_height_upper_bound[symbol->option_2 - 32]; + for(i = version - 1; i > rmqr_fixed_height_upper_bound[symbol->option_2 - 33]; i--) { + est_binlen = getBinaryLength(RMQR_VERSION + i, mode, jisdata, length, gs1, symbol->eci); + if (ecc_level == LEVEL_M) { + if (rmqr_data_codewords_M[i] >= (est_binlen / 8)) { + version = i; + } + } else { + if (rmqr_data_codewords_H[i] >= (est_binlen / 8)) { + version = i; + } + } + } + est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, symbol->eci); + } + + if (symbol->option_1 == -1) { + // Detect if there is enough free space to increase ECC level + if (est_binlen < (rmqr_data_codewords_H[version] * 8)) { + ecc_level = LEVEL_H; + } + } + + if (ecc_level == LEVEL_M) { + target_codewords = rmqr_data_codewords_M[version]; + blocks = rmqr_blocks_M[version]; + } else { + target_codewords = rmqr_data_codewords_H[version]; + blocks = rmqr_blocks_H[version]; + } + + if (est_binlen > (target_codewords * 8)) { + // User has selected a symbol too small for the data + strcpy(symbol->errtxt, "580: Input too long for selected symbol size"); + return ZINT_ERROR_TOO_LONG; + } + + if (symbol->debug) { + printf("Minimum codewords = %d\n", est_binlen / 8); + printf("Selected version: %d = R%dx%d-", (version + 1), rmqr_height[version], rmqr_width[version]); + if (ecc_level == LEVEL_M) { + printf("M\n"); + } else { + printf("H\n"); + } + printf("Number of data codewords in symbol = %d\n", target_codewords); + printf("Number of ECC blocks = %d\n", blocks); + } + +#ifndef _MSC_VER + int datastream[target_codewords + 1]; + int fullstream[rmqr_total_codewords[version] + 1]; +#else + datastream = (int *) _alloca((target_codewords + 1) * sizeof (int)); + fullstream = (int *) _alloca((rmqr_total_codewords[version] + 1) * sizeof (int)); +#endif + + qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug); + add_ecc(fullstream, datastream, RMQR_VERSION + version, target_codewords, blocks, symbol->debug); + + h_size = rmqr_width[version]; + v_size = rmqr_height[version]; + +#ifndef _MSC_VER + unsigned char grid[h_size * v_size]; +#else + grid = (unsigned char *) _alloca((h_size * v_size) * sizeof (unsigned char)); +#endif + + for (i = 0; i < v_size; i++) { + for (j = 0; j < h_size; j++) { + grid[(i * h_size) + j] = 0; + } + } + + setup_rmqr_grid(grid, h_size, v_size, version); + populate_grid(grid, h_size, v_size, fullstream, rmqr_total_codewords[version]); + + /* apply bitmask */ + for (i = 0; i < v_size; i++) { + for (j = 0; j < h_size; j++) { + if ((grid[(i * h_size) + j] & 0xf0) == 0) { + // This is a data module + if (((i / 2) + (j / 3)) % 2 == 0) { // < This is the data mask from section 7.8.2 + // This module needs to be changed + if (grid[(i * h_size) + j] == 0x01) { + grid[(i * h_size) + j] = 0x00; + } else { + grid[(i * h_size) + j] = 0x01; + } + } + } + } + } + + /* add format information */ + format_data = version; + if (ecc_level == LEVEL_H) { + format_data += 32; + } + left_format_info = rmqr_format_info_left[format_data]; + right_format_info = rmqr_format_info_right[format_data]; + + for (i = 0; i < 5; i++) { + for (j = 0; j < 3; j++) { + grid[(h_size * (i + 1)) + j + 8] = (left_format_info >> ((j * 5) + i)) & 0x01; + grid[(h_size * (v_size - 6)) + (h_size * i) + j + (h_size - 8)] = (right_format_info >> ((j * 5) + i)) & 0x01; + } + } + grid[(h_size * 1) + 11] = (left_format_info >> 15) & 0x01; + grid[(h_size * 2) + 11] = (left_format_info >> 16) & 0x01; + grid[(h_size * 3) + 11] = (left_format_info >> 17) & 0x01; + grid[(h_size * (v_size - 6)) + (h_size - 5)] = (right_format_info >> 15) & 0x01; + grid[(h_size * (v_size - 6)) + (h_size - 4)] = (right_format_info >> 16) & 0x01; + grid[(h_size * (v_size - 6)) + (h_size - 3)] = (right_format_info >> 17) & 0x01; + + + symbol->width = h_size; + symbol->rows = v_size; + + for (i = 0; i < v_size; i++) { + for (j = 0; j < h_size; j++) { + if (grid[(i * h_size) + j] & 0x01) { + set_module(symbol, i, j); + } + } + symbol->row_height[i] = 1; + } + + return 0; +} \ No newline at end of file diff --git a/backend/qr.h b/backend/qr.h index c5a23c9e..5f48e53d 100644 --- a/backend/qr.h +++ b/backend/qr.h @@ -1,6 +1,5 @@ -/* qr.h Data for QR Code */ +/* qr.h Data for QR Code, Micro QR Code and rMQR -/* libzint - the open source barcode library Copyright (C) 2008-2017 Robin Stuart Copyright (C) 2006 Kentaro Fukuchi @@ -38,6 +37,8 @@ #define RHODIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" +#define RMQR_VERSION 100 + /* From ISO/IEC 18004:2006 Table 7 */ static const unsigned short int qr_data_codewords_L[] = { 19, 34, 55, 80, 108, 136, 156, 194, 232, 274, 324, 370, 428, 461, 523, 589, 647, @@ -69,6 +70,92 @@ static const unsigned short int qr_total_codewords[] = { 2185, 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706 }; +static const unsigned short int rmqr_height[] = { + 7, 7, 7, 7, 7, + 9, 9, 9, 9, 9, + 11, 11, 11, 11, 11, 11, + 13, 13, 13, 13, 13, 13, + 15, 15, 15, 15, 15, + 17, 17, 17, 17, 17 +}; + +static const unsigned short int rmqr_width[] = { + 43, 59, 77, 99, 139, + 43, 59, 77, 99, 139, + 27, 43, 59, 77, 99, 139, + 27, 43, 59, 77, 99, 139, + 43, 59, 77, 99, 139, + 43, 59, 77, 99, 139 +}; + +static const unsigned short int rmqr_data_codewords_M[] = { + 6, 12, 20, 28, 44, // R7x + 12, 21, 31, 42, 63, // R9x + 7, 19, 31, 43, 57, 84, // R11x + 12, 27, 38, 53, 73, 106, // R13x + 33, 48, 67, 88, 127, // R15x + 39, 56, 78, 100, 152 // R17x +}; + +static const unsigned short int rmqr_data_codewords_H[] = { + 3, 7, 10, 14, 24, // R7x + 7, 11, 17, 22, 33, // R9x + 5, 11, 15, 23, 29, 42, // R11x + 7, 13, 20, 29, 35, 54, // R13x + 15, 26, 31, 48, 69, // R15x + 21, 28, 38, 56, 76 // R17x +}; + +static const short int rmqr_fixed_height_upper_bound[] = { + -1, 4, 9, 15, 21, 26, 31 +}; + +static const unsigned short int rmqr_total_codewords[] = { + 13, 21, 32, 44, 68, // R7x + 21, 33, 49, 66, 99, // R9x + 15, 31, 47, 67, 89, 132, // R11x + 21, 41, 60, 85, 113, 166, // R13x + 51, 74, 103, 136, 199, // R15x + 61, 88, 122, 160, 232 // R17x +}; + + +static const unsigned short int rmqr_numeric_cci[] = { + 4, 5, 6, 7, 7, + 5, 6, 7, 7, 8, + 5, 6, 7, 7, 8, 8, + 5, 7, 7, 8, 8, 8, + 7, 7, 8, 8, 9, + 7, 8, 8, 8, 9 +}; + +static const unsigned short int rmqr_alphanum_cci[] = { + 4, 5, 5, 6, 6, + 5, 5, 6, 6, 7, + 4, 5, 6, 6, 7, 7, + 5, 6, 6, 7, 7, 8, + 6, 7, 7, 7, 8, + 6, 7, 7, 8, 8 +}; + +static const unsigned short int rmqr_byte_cci[] = { + 3, 4, 5, 5, 6, + 4, 5, 5, 6, 6, + 3, 5, 5, 6, 6, 7, + 4, 5, 6, 6, 7, 7, + 6, 6, 7, 7, 7, + 6, 6, 7, 7, 8 +}; + +static const unsigned short int rmqr_kanji_cci[] = { + 2, 3, 4, 5, 5, + 3, 4, 5, 5, 6, + 2, 4, 5, 5, 6, 6, + 3, 5, 5, 6, 6, 7, + 5, 5, 6, 6, 7, + 5, 6, 6, 6, 7 +}; + static const char qr_blocks_L[] = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25 @@ -89,6 +176,24 @@ static const char qr_blocks_H[] = { 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81 }; +static const char rmqr_blocks_M[] = { + 1, 1, 1, 1, 1, // R7x + 1, 1, 1, 1, 2, // R9x + 1, 1, 1, 1, 2, 2, // R11x + 1, 1, 1, 2, 2, 3, // R13x + 1, 1, 2, 2, 3, // R15x + 1, 2, 2, 3, 4 // R17x +}; + +static const char rmqr_blocks_H[] = { + 1, 1, 1, 1, 2, // R7x + 1, 1, 2, 2, 3, // R9x + 1, 1, 2, 2, 2, 3, // R11x + 1, 1, 2, 2, 3, 4, // R13x + 2, 2, 3, 4, 5, // R15x + 2, 2, 3, 4, 6 // R17x +}; + static const unsigned short int qr_sizes[] = { 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177 @@ -102,6 +207,7 @@ static const char qr_align_loopsize[] = { 0, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7 }; +// Table E1 - Row/column coordinates of center module of alignment patterns static const unsigned short int qr_table_e1[] = { 6, 18, 0, 0, 0, 0, 0, 6, 22, 0, 0, 0, 0, 0, @@ -144,6 +250,15 @@ static const unsigned short int qr_table_e1[] = { 6, 30, 58, 86, 114, 142, 170 }; +// Table D1 - Column coordinates of centre module of alignment patterns +static const unsigned short int rmqr_table_d1[] = { + 21, 0, 0, 0, + 19, 39, 0, 0, + 25, 51, 0, 0, + 23, 49, 75, 0, + 27, 55, 83, 111 +}; + static const unsigned int qr_annex_c[] = { /* Format information bit sequences */ 0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d, @@ -165,3 +280,25 @@ static const unsigned int qr_annex_c1[] = { 0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51, 0x34e3, 0x31d4, 0x3e8d, 0x3bba }; + +static const unsigned int rmqr_format_info_left[] = { + /* rMQR format information for finder pattern side */ + 0x1FAB2, 0x1E597, 0x1DBDD, 0x1C4F8, 0x1B86C, 0x1A749, 0x19903, 0x18626, 0x17F0E, 0x1602B, + 0x15E61, 0x14144, 0x13DD0, 0x122F5, 0x11CBF, 0x1039A, 0x0F1CA, 0x0EEEF, 0x0D0A5, 0x0CF80, + 0x0B314, 0x0AC31, 0x0927B, 0x08D5E, 0x07476, 0x06B53, 0x05519, 0x04A3C, 0x036A8, 0x0298D, + 0x017C7, 0x008E2, 0x3F367, 0x3EC42, 0x3D208, 0x3CD2D, 0x3B1B9, 0x3AE9C, 0x390D6, 0x38FF3, + 0x376DB, 0x369FE, 0x357B4, 0x34891, 0x33405, 0x32B20, 0x3156A, 0x30A4F, 0x2F81F, 0x2E73A, + 0x2D970, 0x2C655, 0x2BAC1, 0x2A5E4, 0x29BAE, 0x2848B, 0x27DA3, 0x26286, 0x25CCC, 0x243E9, + 0x23F7D, 0x22058, 0x21E12, 0x20137 +}; + +static const unsigned int rmqr_format_info_right[] = { + /* rMQR format information for subfinder pattern side */ + 0x20A7B, 0x2155E, 0x22B14, 0x23431, 0x248A5, 0x25780, 0x269CA, 0x276EF, 0x28FC7, 0x290E2, + 0x2AEA8, 0x2B18D, 0x2CD19, 0x2D23C, 0x2EC76, 0x2F353, 0x30103, 0x31E26, 0x3206C, 0x33F49, + 0x343DD, 0x35CF8, 0x362B2, 0x37D97, 0x384BF, 0x39B9A, 0x3A5D0, 0x3BAF5, 0x3C661, 0x3D944, + 0x3E70E, 0x3F82B, 0x003AE, 0x01C8B, 0x022C1, 0x03DE4, 0x04170, 0x05E55, 0x0601F, 0x07F3A, + 0x08612, 0x09937, 0x0A77D, 0x0B858, 0x0C4CC, 0x0DBE9, 0x0E5A3, 0x0FA86, 0x108D6, 0x117F3, + 0x129B9, 0x1369C, 0x14A08, 0x1552D, 0x16B67, 0x17442, 0x18D6A, 0x1924F, 0x1AC05, 0x1B320, + 0x1CFB4, 0x1D091, 0x1EEDB, 0x1F1FE +}; \ No newline at end of file diff --git a/backend/svg.c b/backend/svg.c index 6cde4635..cbba33e9 100644 --- a/backend/svg.c +++ b/backend/svg.c @@ -104,7 +104,7 @@ int svg_plot(struct zint_symbol *symbol) { int html_len = strlen((char *)symbol->text) + 1; - for (0; i < strlen((char *)symbol->text); i++) { + for (i = 0; i < strlen((char *)symbol->text); i++) { switch(symbol->text[i]) { case '>': case '<': diff --git a/backend/zint.h b/backend/zint.h index fc4e41a3..4cb052db 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -1,7 +1,7 @@ /* zint.h - definitions for libzint libzint - the open source barcode library - Copyright (C) 2009-2018 Robin Stuart + Copyright (C) 2009-2019 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -40,7 +40,7 @@ extern "C" { float x, y, length, width; struct zint_render_line *next; /* Pointer to next line */ }; - + struct zint_vector_rect { float x, y, height, width; int colour; @@ -54,7 +54,7 @@ extern "C" { unsigned char *text; struct zint_render_string *next; /* Pointer to next character */ }; - + struct zint_vector_string { float x, y, fsize; float width; /* Suggested string width, may be 0 if none recommended */ @@ -73,7 +73,7 @@ extern "C" { int colour; struct zint_vector_circle *next; /* Pointer to next circle */ }; - + struct zint_render_hexagon { float x, y, height; struct zint_render_hexagon *next; /* Pointer to next hexagon */ @@ -83,7 +83,7 @@ extern "C" { float x, y, diameter; struct zint_vector_hexagon *next; /* Pointer to next hexagon */ }; - + struct zint_render { float width, height; struct zint_render_line *lines; /* Pointer to first line */ @@ -91,7 +91,7 @@ extern "C" { struct zint_render_ring *rings; /* Pointer to first ring */ struct zint_render_hexagon *hexagons; /* Pointer to first hexagon */ }; - + struct zint_vector { float width, height; struct zint_vector_rect *rectangles; /* Pointer to first rectangle */ @@ -139,154 +139,155 @@ extern "C" { #define ZINT_VERSION_RELEASE 7 /* Tbarcode 7 codes */ -#define BARCODE_CODE11 1 -#define BARCODE_C25MATRIX 2 -#define BARCODE_C25INTER 3 -#define BARCODE_C25IATA 4 -#define BARCODE_C25LOGIC 6 -#define BARCODE_C25IND 7 -#define BARCODE_CODE39 8 -#define BARCODE_EXCODE39 9 -#define BARCODE_EANX 13 +#define BARCODE_CODE11 1 +#define BARCODE_C25MATRIX 2 +#define BARCODE_C25INTER 3 +#define BARCODE_C25IATA 4 +#define BARCODE_C25LOGIC 6 +#define BARCODE_C25IND 7 +#define BARCODE_CODE39 8 +#define BARCODE_EXCODE39 9 +#define BARCODE_EANX 13 #define BARCODE_EANX_CHK 14 -#define BARCODE_EAN128 16 -#define BARCODE_CODABAR 18 -#define BARCODE_CODE128 20 -#define BARCODE_DPLEIT 21 -#define BARCODE_DPIDENT 22 -#define BARCODE_CODE16K 23 -#define BARCODE_CODE49 24 -#define BARCODE_CODE93 25 -#define BARCODE_FLAT 28 -#define BARCODE_RSS14 29 -#define BARCODE_RSS_LTD 30 -#define BARCODE_RSS_EXP 31 -#define BARCODE_TELEPEN 32 -#define BARCODE_UPCA 34 +#define BARCODE_EAN128 16 +#define BARCODE_CODABAR 18 +#define BARCODE_CODE128 20 +#define BARCODE_DPLEIT 21 +#define BARCODE_DPIDENT 22 +#define BARCODE_CODE16K 23 +#define BARCODE_CODE49 24 +#define BARCODE_CODE93 25 +#define BARCODE_FLAT 28 +#define BARCODE_RSS14 29 +#define BARCODE_RSS_LTD 30 +#define BARCODE_RSS_EXP 31 +#define BARCODE_TELEPEN 32 +#define BARCODE_UPCA 34 #define BARCODE_UPCA_CHK 35 -#define BARCODE_UPCE 37 +#define BARCODE_UPCE 37 #define BARCODE_UPCE_CHK 38 -#define BARCODE_POSTNET 40 -#define BARCODE_MSI_PLESSEY 47 -#define BARCODE_FIM 49 -#define BARCODE_LOGMARS 50 -#define BARCODE_PHARMA 51 -#define BARCODE_PZN 52 -#define BARCODE_PHARMA_TWO 53 -#define BARCODE_PDF417 55 -#define BARCODE_PDF417TRUNC 56 -#define BARCODE_MAXICODE 57 -#define BARCODE_QRCODE 58 -#define BARCODE_CODE128B 60 -#define BARCODE_AUSPOST 63 -#define BARCODE_AUSREPLY 66 -#define BARCODE_AUSROUTE 67 -#define BARCODE_AUSREDIRECT 68 -#define BARCODE_ISBNX 69 -#define BARCODE_RM4SCC 70 -#define BARCODE_DATAMATRIX 71 -#define BARCODE_EAN14 72 +#define BARCODE_POSTNET 40 +#define BARCODE_MSI_PLESSEY 47 +#define BARCODE_FIM 49 +#define BARCODE_LOGMARS 50 +#define BARCODE_PHARMA 51 +#define BARCODE_PZN 52 +#define BARCODE_PHARMA_TWO 53 +#define BARCODE_PDF417 55 +#define BARCODE_PDF417TRUNC 56 +#define BARCODE_MAXICODE 57 +#define BARCODE_QRCODE 58 +#define BARCODE_CODE128B 60 +#define BARCODE_AUSPOST 63 +#define BARCODE_AUSREPLY 66 +#define BARCODE_AUSROUTE 67 +#define BARCODE_AUSREDIRECT 68 +#define BARCODE_ISBNX 69 +#define BARCODE_RM4SCC 70 +#define BARCODE_DATAMATRIX 71 +#define BARCODE_EAN14 72 #define BARCODE_VIN 73 -#define BARCODE_CODABLOCKF 74 -#define BARCODE_NVE18 75 -#define BARCODE_JAPANPOST 76 -#define BARCODE_KOREAPOST 77 -#define BARCODE_RSS14STACK 79 -#define BARCODE_RSS14STACK_OMNI 80 -#define BARCODE_RSS_EXPSTACK 81 -#define BARCODE_PLANET 82 -#define BARCODE_MICROPDF417 84 -#define BARCODE_ONECODE 85 -#define BARCODE_PLESSEY 86 +#define BARCODE_CODABLOCKF 74 +#define BARCODE_NVE18 75 +#define BARCODE_JAPANPOST 76 +#define BARCODE_KOREAPOST 77 +#define BARCODE_RSS14STACK 79 +#define BARCODE_RSS14STACK_OMNI 80 +#define BARCODE_RSS_EXPSTACK 81 +#define BARCODE_PLANET 82 +#define BARCODE_MICROPDF417 84 +#define BARCODE_ONECODE 85 +#define BARCODE_PLESSEY 86 /* Tbarcode 8 codes */ -#define BARCODE_TELEPEN_NUM 87 -#define BARCODE_ITF14 89 -#define BARCODE_KIX 90 -#define BARCODE_AZTEC 92 -#define BARCODE_DAFT 93 -#define BARCODE_MICROQR 97 +#define BARCODE_TELEPEN_NUM 87 +#define BARCODE_ITF14 89 +#define BARCODE_KIX 90 +#define BARCODE_AZTEC 92 +#define BARCODE_DAFT 93 +#define BARCODE_MICROQR 97 /* Tbarcode 9 codes */ -#define BARCODE_HIBC_128 98 -#define BARCODE_HIBC_39 99 -#define BARCODE_HIBC_DM 102 -#define BARCODE_HIBC_QR 104 -#define BARCODE_HIBC_PDF 106 -#define BARCODE_HIBC_MICPDF 108 -#define BARCODE_HIBC_BLOCKF 110 -#define BARCODE_HIBC_AZTEC 112 +#define BARCODE_HIBC_128 98 +#define BARCODE_HIBC_39 99 +#define BARCODE_HIBC_DM 102 +#define BARCODE_HIBC_QR 104 +#define BARCODE_HIBC_PDF 106 +#define BARCODE_HIBC_MICPDF 108 +#define BARCODE_HIBC_BLOCKF 110 +#define BARCODE_HIBC_AZTEC 112 /* Tbarcode 10 codes */ #define BARCODE_DOTCODE 115 #define BARCODE_HANXIN 116 - + /*Tbarcode 11 codes*/ #define BARCODE_MAILMARK 121 /* Zint specific */ -#define BARCODE_AZRUNE 128 -#define BARCODE_CODE32 129 -#define BARCODE_EANX_CC 130 -#define BARCODE_EAN128_CC 131 -#define BARCODE_RSS14_CC 132 -#define BARCODE_RSS_LTD_CC 133 -#define BARCODE_RSS_EXP_CC 134 -#define BARCODE_UPCA_CC 135 -#define BARCODE_UPCE_CC 136 -#define BARCODE_RSS14STACK_CC 137 -#define BARCODE_RSS14_OMNI_CC 138 -#define BARCODE_RSS_EXPSTACK_CC 139 -#define BARCODE_CHANNEL 140 -#define BARCODE_CODEONE 141 -#define BARCODE_GRIDMATRIX 142 +#define BARCODE_AZRUNE 128 +#define BARCODE_CODE32 129 +#define BARCODE_EANX_CC 130 +#define BARCODE_EAN128_CC 131 +#define BARCODE_RSS14_CC 132 +#define BARCODE_RSS_LTD_CC 133 +#define BARCODE_RSS_EXP_CC 134 +#define BARCODE_UPCA_CC 135 +#define BARCODE_UPCE_CC 136 +#define BARCODE_RSS14STACK_CC 137 +#define BARCODE_RSS14_OMNI_CC 138 +#define BARCODE_RSS_EXPSTACK_CC 139 +#define BARCODE_CHANNEL 140 +#define BARCODE_CODEONE 141 +#define BARCODE_GRIDMATRIX 142 #define BARCODE_UPNQR 143 -#define BARCODE_ULTRA 144 +#define BARCODE_ULTRA 144 +#define BARCODE_RMQR 145 // Output options -#define BARCODE_NO_ASCII 1 -#define BARCODE_BIND 2 -#define BARCODE_BOX 4 -#define BARCODE_STDOUT 8 -#define READER_INIT 16 -#define SMALL_TEXT 32 +#define BARCODE_NO_ASCII 1 +#define BARCODE_BIND 2 +#define BARCODE_BOX 4 +#define BARCODE_STDOUT 8 +#define READER_INIT 16 +#define SMALL_TEXT 32 #define BOLD_TEXT 64 #define CMYK_COLOUR 128 #define BARCODE_DOTTY_MODE 256 #define GS1_GS_SEPARATOR 512 // Input data types -#define DATA_MODE 0 -#define UNICODE_MODE 1 -#define GS1_MODE 2 -#define ESCAPE_MODE 8 +#define DATA_MODE 0 +#define UNICODE_MODE 1 +#define GS1_MODE 2 +#define ESCAPE_MODE 8 // Data Matrix specific options -#define DM_SQUARE 100 -#define DM_DMRE 101 +#define DM_SQUARE 100 +#define DM_DMRE 101 // Warning and error conditions -#define ZINT_WARN_INVALID_OPTION 2 +#define ZINT_WARN_INVALID_OPTION 2 #define ZINT_WARN_USES_ECI 3 -#define ZINT_ERROR_TOO_LONG 5 +#define ZINT_ERROR_TOO_LONG 5 #define ZINT_ERROR_INVALID_DATA 6 -#define ZINT_ERROR_INVALID_CHECK 7 -#define ZINT_ERROR_INVALID_OPTION 8 -#define ZINT_ERROR_ENCODING_PROBLEM 9 -#define ZINT_ERROR_FILE_ACCESS 10 -#define ZINT_ERROR_MEMORY 11 +#define ZINT_ERROR_INVALID_CHECK 7 +#define ZINT_ERROR_INVALID_OPTION 8 +#define ZINT_ERROR_ENCODING_PROBLEM 9 +#define ZINT_ERROR_FILE_ACCESS 10 +#define ZINT_ERROR_MEMORY 11 // Raster file types -#define OUT_BUFFER 0 -#define OUT_SVG_FILE 10 -#define OUT_EPS_FILE 20 -#define OUT_EMF_FILE 30 -#define OUT_PNG_FILE 100 -#define OUT_BMP_FILE 120 -#define OUT_GIF_FILE 140 -#define OUT_PCX_FILE 160 -#define OUT_JPG_FILE 180 -#define OUT_TIF_FILE 200 +#define OUT_BUFFER 0 +#define OUT_SVG_FILE 10 +#define OUT_EPS_FILE 20 +#define OUT_EMF_FILE 30 +#define OUT_PNG_FILE 100 +#define OUT_BMP_FILE 120 +#define OUT_GIF_FILE 140 +#define OUT_PCX_FILE 160 +#define OUT_JPG_FILE 180 +#define OUT_TIF_FILE 200 #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(_MSC_VER) #if defined (DLL_EXPORT) || defined(PIC) || defined(_USRDLL) diff --git a/frontend/main.c b/frontend/main.c index 33dcdad5..bbda6326 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -67,7 +67,7 @@ void types(void) { "40: Postnet 86: UK Plessey 141: Code One\n" "47: MSI Plessey 87: Telepen Numeric 142: Grid Matrix\n" "49: FIM 89: ITF-14 143: UPNQR\n" - "50: Logmars 90: KIX Code\n" + "50: Logmars 90: KIX Code 145: rMQR\n" ); } @@ -326,7 +326,7 @@ int batch_process(struct zint_symbol *symbol, char *filename, int mirror_mode, c output_file[o] = buffer[i]; } } - + // Skip escape characters if ((buffer[i] == 0x5c) && (symbol->input_mode & ESCAPE_MODE)) { i++; @@ -712,9 +712,9 @@ int main(int argc, char **argv) { fprintf(stderr, "%s\n", my_symbol->errtxt); fflush(stderr); } - if (error_number < 5) { + if (error_number < 5) { error_number = ZBarcode_Print(my_symbol, rotate_angle); - + if (error_number != 0) { fprintf(stderr, "%s\n", my_symbol->errtxt); fflush(stderr);