Initial implementation of rMQR

According to draft dated June 2018
This commit is contained in:
Robin Stuart 2019-11-25 19:08:25 +00:00
parent 385a0a246f
commit ad28de1819
6 changed files with 783 additions and 211 deletions

View File

@ -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 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 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 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_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 */ extern int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to EPS/EMF/SVG */
@ -414,6 +415,7 @@ static int gs1_compliant(const int symbology) {
case BARCODE_CODE49: case BARCODE_CODE49:
case BARCODE_QRCODE: case BARCODE_QRCODE:
case BARCODE_DOTCODE: case BARCODE_DOTCODE:
case BARCODE_RMQR:
result = 1; result = 1;
break; break;
} }
@ -440,6 +442,7 @@ static int is_matrix(const int symbology) {
case BARCODE_HANXIN: case BARCODE_HANXIN:
case BARCODE_DOTCODE: case BARCODE_DOTCODE:
case BARCODE_UPNQR: case BARCODE_UPNQR:
case BARCODE_RMQR:
result = 1; result = 1;
break; break;
} }
@ -633,6 +636,7 @@ int ZBarcode_ValidID(int symbol_id) {
case BARCODE_VIN: case BARCODE_VIN:
case BARCODE_MAILMARK: case BARCODE_MAILMARK:
case BARCODE_ULTRA: case BARCODE_ULTRA:
case BARCODE_RMQR:
result = 1; result = 1;
break; break;
} }
@ -655,6 +659,8 @@ static int extended_charset(struct zint_symbol *symbol, const unsigned char *sou
break; break;
case BARCODE_UPNQR: error_number = upnqr(symbol, source, length); case BARCODE_UPNQR: error_number = upnqr(symbol, source, length);
break; break;
case BARCODE_RMQR: error_number = rmqr(symbol, source, length);
break;
} }
return error_number; 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 */ /* 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"); strcpy(symbol->errtxt, "216: Symbology out of range, using Code 128");
symbol->symbology = BARCODE_CODE128; symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION; error_number = ZINT_WARN_INVALID_OPTION;
@ -1208,6 +1214,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
case BARCODE_GRIDMATRIX: case BARCODE_GRIDMATRIX:
case BARCODE_HANXIN: case BARCODE_HANXIN:
case BARCODE_UPNQR: case BARCODE_UPNQR:
case BARCODE_RMQR:
error_number = extended_charset(symbol, local_source, in_length); error_number = extended_charset(symbol, local_source, in_length);
break; break;
default: default:

View File

@ -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 libzint - the open source barcode library
Copyright (C) 2009 -2017 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009 - 2019 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions 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 */ /* 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 position = 0;
int i; int i;
char padbits; char padbits;
@ -163,10 +162,14 @@ static void qr_binary(int datastream[], const int version, const int target_binl
strcpy(binary, ""); strcpy(binary, "");
if (gs1) { if (gs1) {
if (version < RMQR_VERSION) {
strcat(binary, "0101"); /* FNC1 */ strcat(binary, "0101"); /* FNC1 */
} else {
strcat(binary, "101");
}
} }
if (eci != 0) { if (eci != 0) { /* Not applicable to RMQR */
strcat(binary, "0111"); /* ECI (Table 4) */ strcat(binary, "0111"); /* ECI (Table 4) */
if (eci <= 127) { if (eci <= 127) {
bin_append(eci, 8, binary); /* 000000 to 000127 */ 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': case 'K':
/* Kanji mode */ /* Kanji mode */
/* Mode indicator */ /* Mode indicator */
if (version < RMQR_VERSION) {
strcat(binary, "1000"); strcat(binary, "1000");
} else {
strcat(binary, "100");
}
/* Character count indicator */ /* Character count indicator */
if (version < RMQR_VERSION) {
bin_append(short_data_block_length, tribus(version, 8, 10, 12), binary); 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) { if (debug) {
printf("Kanji block (length %d)\n\t", short_data_block_length); 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': case 'B':
/* Byte mode */ /* Byte mode */
/* Mode indicator */ /* Mode indicator */
if (version < RMQR_VERSION) {
strcat(binary, "0100"); strcat(binary, "0100");
} else {
strcat(binary, "011");
}
/* Character count indicator */ /* Character count indicator */
if (version < RMQR_VERSION) {
bin_append(short_data_block_length, tribus(version, 8, 16, 16), binary); 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) { if (debug) {
printf("Byte block (length %d)\n\t", short_data_block_length); 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': case 'A':
/* Alphanumeric mode */ /* Alphanumeric mode */
/* Mode indicator */ /* Mode indicator */
if (version < RMQR_VERSION) {
strcat(binary, "0010"); strcat(binary, "0010");
} else {
strcat(binary, "010");
}
percent_count = 0; percent_count = 0;
for (i = 0; i < short_data_block_length; i++) { for (i = 0; i < short_data_block_length; i++) {
@ -277,7 +300,11 @@ static void qr_binary(int datastream[], const int version, const int target_binl
} }
/* Character count indicator */ /* Character count indicator */
if (version < RMQR_VERSION) {
bin_append(short_data_block_length + percent_count, tribus(version, 9, 11, 13), binary); 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) { if (debug) {
printf("Alpha block (length %d)\n\t", short_data_block_length + percent_count); 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': case 'N':
/* Numeric mode */ /* Numeric mode */
/* Mode indicator */ /* Mode indicator */
if (version >= RMQR_VERSION) {
strcat(binary, "0001"); strcat(binary, "0001");
} else {
strcat(binary, "001");
}
/* Character count indicator */ /* Character count indicator */
if (version < RMQR_VERSION) {
bin_append(short_data_block_length, tribus(version, 10, 12, 14), binary); 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) { if (debug) {
printf("Number block (length %d)\n\t", short_data_block_length); 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); } while (position < length);
/* Terminator */ /* Terminator */
if (version < RMQR_VERSION) {
strcat(binary, "0000"); strcat(binary, "0000");
} else {
strcat(binary, "000");
}
current_binlen = (int)strlen(binary); current_binlen = (int)strlen(binary);
padbits = 8 - (current_binlen % 8); 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 */ /* Add pad codewords */
toggle = 0; toggle = 0;
for (i = current_bytes; i < target_binlen; i++) { for (i = current_bytes; i < target_codewords; i++) {
if (toggle == 0) { if (toggle == 0) {
datastream[i] = 0xec; datastream[i] = 0xec;
toggle = 1; toggle = 1;
@ -455,7 +494,7 @@ static void qr_binary(int datastream[], const int version, const int target_binl
if (debug) { if (debug) {
printf("Resulting codewords:\n\t"); 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("0x%2X ", datastream[i]);
} }
printf("\n"); 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 */ /* 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) { static void add_ecc(int fullstream[],const int datastream[],const int version,const int data_cw,const int blocks,int debug) {
int ecc_cw = qr_total_codewords[version - 1] - data_cw; 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 short_data_block_length = data_cw / blocks;
int qty_long_blocks = data_cw % blocks; int qty_long_blocks = data_cw % blocks;
int qty_short_blocks = blocks - qty_long_blocks; int qty_short_blocks = blocks - qty_long_blocks;
int ecc_block_length = ecc_cw / 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 #ifndef _MSC_VER
unsigned char data_block[short_data_block_length + 2]; unsigned char data_block[short_data_block_length + 2];
@ -670,35 +715,36 @@ static int cwbit(const int* fullstream,const int i) {
return resultant; 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 direction = 1; /* up */
int row = 0; /* right hand side */ int row = 0; /* right hand side */
int i, n, y; int i, n, y;
n = cw * 8; n = cw * 8;
y = size - 1; y = v_size - 1;
i = 0; i = 0;
do { do {
int x = (size - 2) - (row * 2); int x = (h_size - 2) - (row * 2);
if (x < 6)
if ((x < 6) && (v_size == h_size))
x--; /* skip over vertical timing pattern */ 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)) { if (cwbit(fullstream, i)) {
grid[(y * size) + (x + 1)] = 0x01; grid[(y * h_size) + (x + 1)] = 0x01;
} else { } else {
grid[(y * size) + (x + 1)] = 0x00; grid[(y * h_size) + (x + 1)] = 0x00;
} }
i++; i++;
} }
if (i < n) { if (i < n) {
if (!(grid[(y * size) + x] & 0xf0)) { if (!(grid[(y * h_size) + x] & 0xf0)) {
if (cwbit(fullstream, i)) { if (cwbit(fullstream, i)) {
grid[(y * size) + x] = 0x01; grid[(y * h_size) + x] = 0x01;
} else { } else {
grid[(y * size) + x] = 0x00; grid[(y * h_size) + x] = 0x00;
} }
i++; i++;
} }
@ -715,10 +761,10 @@ static void populate_grid(unsigned char* grid,const int size,const int* fullstre
y = 0; y = 0;
direction = 0; direction = 0;
} }
if (y == size) { if (y == v_size) {
/* reached the bottom */ /* reached the bottom */
row++; row++;
y = size - 1; y = v_size - 1;
direction = 1; direction = 1;
} }
} while (i < n); } while (i < n);
@ -1335,11 +1381,15 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
currentMode = ' '; // Null currentMode = ' '; // Null
if (gs1 == 1) { if (gs1 == 1) {
if (version < RMQR_VERSION) {
count += 4; count += 4;
} else {
count += 3;
}
} }
if (eci != 0) { if (eci != 0) {
count += 12; count += 12; // RMQR does not support ECI
} }
for (i = 0; i < inputLength; i++) { for (i = 0; i < inputLength; i++) {
@ -1347,11 +1397,19 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
count += 4; count += 4;
switch (inputMode[i]) { switch (inputMode[i]) {
case 'K': case 'K':
if (version < RMQR_VERSION) {
count += tribus(version, 8, 10, 12); count += tribus(version, 8, 10, 12);
} else {
count += 3 + rmqr_kanji_cci[version - RMQR_VERSION];
}
count += (blockLength(i, inputMode, inputLength) * 13); count += (blockLength(i, inputMode, inputLength) * 13);
break; break;
case 'B': case 'B':
if (version < RMQR_VERSION) {
count += tribus(version, 8, 16, 16); 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++) { for (j = i; j < (i + blockLength(i, inputMode, inputLength)); j++) {
if (inputData[j] > 0xff) { if (inputData[j] > 0xff) {
count += 16; count += 16;
@ -1361,7 +1419,11 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
} }
break; break;
case 'A': case 'A':
if (version < RMQR_VERSION) {
count += tribus(version, 9, 11, 13); count += tribus(version, 9, 11, 13);
} else {
count += 3 + rmqr_alphanum_cci[version - RMQR_VERSION];
}
alphalength = blockLength(i, inputMode, inputLength); alphalength = blockLength(i, inputMode, inputLength);
// In alphanumeric mode % becomes %% // In alphanumeric mode % becomes %%
for (j = i; j < (i + alphalength); j++) { for (j = i; j < (i + alphalength); j++) {
@ -1381,7 +1443,11 @@ static int getBinaryLength(const int version,char inputMode[],const int inputDat
} }
break; break;
case 'N': case 'N':
if (version < RMQR_VERSION) {
count += tribus(version, 10, 12, 14); count += tribus(version, 10, 12, 14);
} else {
count += 3 + rmqr_numeric_cci[version - RMQR_VERSION];
}
switch (blockLength(i, inputMode, inputLength) % 3) { switch (blockLength(i, inputMode, inputLength) % 3) {
case 0: case 0:
count += (blockLength(i, inputMode, inputLength) / 3) * 10; 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 qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t length) {
int i, j, est_binlen; 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 bitmask, gs1;
int canShrink; int canShrink;
@ -1581,30 +1647,30 @@ int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t len
ecc_level = LEVEL_H; 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]; blocks = qr_blocks_L[version - 1];
switch (ecc_level) { 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]; blocks = qr_blocks_M[version - 1];
break; 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]; blocks = qr_blocks_Q[version - 1];
break; 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]; blocks = qr_blocks_H[version - 1];
break; break;
} }
#ifndef _MSC_VER #ifndef _MSC_VER
int datastream[target_binlen + 1]; int datastream[target_codewords + 1];
int fullstream[qr_total_codewords[version - 1] + 1]; int fullstream[qr_total_codewords[version - 1] + 1];
#else #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)); fullstream = (int *) _alloca((qr_total_codewords[version - 1] + 1) * sizeof (int));
#endif #endif
qr_binary(datastream, version, target_binlen, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug); qr_binary(datastream, version, target_codewords, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug);
add_ecc(fullstream, datastream, version, target_binlen, blocks); add_ecc(fullstream, datastream, version, target_codewords, blocks, symbol->debug);
size = qr_sizes[version - 1]; size = qr_sizes[version - 1];
#ifndef _MSC_VER #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); 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) { if (version >= 7) {
add_version_info(grid, size, version); 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; 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) { 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 /* Convert input data to an "intermediate stage" where data is binary encoded but
control information is not */ 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 */ /* 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 upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t length) {
int i, j, est_binlen; 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; int bitmask, error_number;
#ifndef _MSC_VER #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 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]; blocks = qr_blocks_M[version - 1];
#ifndef _MSC_VER #ifndef _MSC_VER
int datastream[target_binlen + 1]; int datastream[target_codewords + 1];
int fullstream[qr_total_codewords[version - 1] + 1]; int fullstream[qr_total_codewords[version - 1] + 1];
#else #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)); fullstream = (int *) _alloca((qr_total_codewords[version - 1] + 1) * sizeof (int));
#endif #endif
qr_binary(datastream, version, target_binlen, mode, jisdata, length, 0, symbol->eci, est_binlen, symbol->debug); qr_binary(datastream, version, target_codewords, mode, jisdata, length, 0, symbol->eci, est_binlen, symbol->debug);
add_ecc(fullstream, datastream, version, target_binlen, blocks); add_ecc(fullstream, datastream, version, target_codewords, blocks, symbol->debug);
size = qr_sizes[version - 1]; size = qr_sizes[version - 1];
#ifndef _MSC_VER #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); 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); 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; 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;
}

View File

@ -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 libzint - the open source barcode library
Copyright (C) 2008-2017 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2008-2017 Robin Stuart <rstuart114@gmail.com>
Copyright (C) 2006 Kentaro Fukuchi <fukuchi@megaui.net> Copyright (C) 2006 Kentaro Fukuchi <fukuchi@megaui.net>
@ -38,6 +37,8 @@
#define RHODIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" #define RHODIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"
#define RMQR_VERSION 100
/* From ISO/IEC 18004:2006 Table 7 */ /* From ISO/IEC 18004:2006 Table 7 */
static const unsigned short int qr_data_codewords_L[] = { 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, 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 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[] = { 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, 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 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 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[] = { 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, 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 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 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[] = { static const unsigned short int qr_table_e1[] = {
6, 18, 0, 0, 0, 0, 0, 6, 18, 0, 0, 0, 0, 0,
6, 22, 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 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[] = { static const unsigned int qr_annex_c[] = {
/* Format information bit sequences */ /* Format information bit sequences */
0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0, 0x77c4, 0x72f3, 0x7daa, 0x789d, 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, 0x7c16, 0x7921, 0x06de, 0x03e9, 0x0cb0, 0x0987, 0x1735, 0x1202, 0x1d5b, 0x186c, 0x2508, 0x203f, 0x2f66, 0x2a51, 0x34e3,
0x31d4, 0x3e8d, 0x3bba 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
};

View File

@ -104,7 +104,7 @@ int svg_plot(struct zint_symbol *symbol) {
int html_len = strlen((char *)symbol->text) + 1; 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]) { switch(symbol->text[i]) {
case '>': case '>':
case '<': case '<':

View File

@ -1,7 +1,7 @@
/* zint.h - definitions for libzint /* zint.h - definitions for libzint
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2018 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2019 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -242,6 +242,7 @@ extern "C" {
#define BARCODE_GRIDMATRIX 142 #define BARCODE_GRIDMATRIX 142
#define BARCODE_UPNQR 143 #define BARCODE_UPNQR 143
#define BARCODE_ULTRA 144 #define BARCODE_ULTRA 144
#define BARCODE_RMQR 145
// Output options // Output options
#define BARCODE_NO_ASCII 1 #define BARCODE_NO_ASCII 1

View File

@ -67,7 +67,7 @@ void types(void) {
"40: Postnet 86: UK Plessey 141: Code One\n" "40: Postnet 86: UK Plessey 141: Code One\n"
"47: MSI Plessey 87: Telepen Numeric 142: Grid Matrix\n" "47: MSI Plessey 87: Telepen Numeric 142: Grid Matrix\n"
"49: FIM 89: ITF-14 143: UPNQR\n" "49: FIM 89: ITF-14 143: UPNQR\n"
"50: Logmars 90: KIX Code\n" "50: Logmars 90: KIX Code 145: rMQR\n"
); );
} }