diff --git a/ChangeLog b/ChangeLog index 6883f6e6..86625c18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -13,6 +13,10 @@ Version 2.11.1.9 (dev) not released yet compliant - Legacy and never-used output option BARCODE_NO_ASCII removed (value now used by new output option BARCODE_BIND_TOP) +- Symbology BARCODE_CODE128B (Suppress subset C) renamed to BARCODE_CODE128AB + to more accurately reflect its behaviour (old name still recognised) +- CLI now expects floating point arguments to be in simple decimal point + notation (i.e. not scientific notation) with a maximum of 7 significant digits Changes ------- @@ -36,6 +40,35 @@ Changes (will add back in future if go fully CMake) - NO_PNG -> ZINT_NO_PNG and new API function `Zint_NoPng()` to determine if no PNG support in libzint; replace use in GUI with backend_qt method `noPng()` +- API: add new zint_symbol `dpmm` field for output resolution (BMP/EMF/PCX/PNG/ + TIF only, i.e. excluding EPS, GIF & SVG) +- Add support for specifying scale by X-dimension and resolution with new option + `--scalexdimdp` for CLI/Tcl & new API function `ZBarcode_Scale_From_XdimDp()` + (plus `ZBarcode_XdimDp_From_Scale()` and `ZBarcode_Default_Xdim()`) and new + GUI popup; manual: document +- BMP/EMF/PCX/PNG/TIF: use new `dpmm` resolution field (for EMF following + Inkscape) +- backend_qt: add `dpmm()`, `vectorWidth()`, `vectorHeight()`, `noPng()`, + `getVersion()`, `takesGS1AIData()`, & `XdimDp` stuff incl. new `QZintXdimDp` + struct for passing around scale vars & use in `getAsCLI()`; add comments +- Raise `scale` limit to 200 (from 100) to allow for large dpmm +- output: create directories & subdirectories as necessary for output path using + new function `out_fopen()` and use in BMP/EMF/EPS/GIF/PCX/PNG/SVG/TIF +- DPLEIT/DPIDENT: format HRT according to (incomplete) documentation, and set + default height to 72X (from 50X) +- CODE128B renamed to CODE128AB as can use subsets A and/or B +- MAILMARK: better error message if input < 14 characters +- GUI: add "Default" button for DAFT tracker ratio & enable/disable various + default buttons; use new `takesGS1AIData()` to enable/disable GS1-specific + checkboxes +- CLI: use new `validate_float()` to parse float options (7 significant digits + allowed only, no scientific notation) +- DATAMATRIX/GRIDMATRIX/PDF417/QR/ULTRA: micro-optimize structapp ID parse +- library/CLI: fiddle with static asserts (make CHAR_BIT sensitive, supposedly) +- win32/README: update building libpng (assembly removed) +- README.linux: document incompatibility of Qt6 >= 6.3 +- manual: expand Barcode Studio waffle +- test suite: change range separator to hyphen and allow multiple excludes Bugs ---- @@ -65,6 +98,10 @@ Bugs Text segments to avoid affecting 1st char of 2nd segment - GUI: only skip encoded/errored signal processing if active modal ExportDialog (wasn't clearing/setting error text bar correctly) +- CODABAR: fix minimum height calc +- EMF: fix indexing of handles (zero-based not 1-based) +- GUI: fix symbology zap (previous technique of clearing and re-loading settings + without doing a sync no longer works); fix UPCEAN guard descent enable Version 2.11.1 (2022-08-22) @@ -909,3 +946,5 @@ Version 0.1 (as Zebar) 2006-11-13 Draws UPC-A. UPC-E, EAN-8, EAN-13, Interlaced 2 of 5, Codabar, Code 39, Extended Code 39 and Code 93 barcodes and Add-on codes EAN-2 and EAN-5 without parity. + +# vim: syntax=off : diff --git a/README.linux b/README.linux index a9c050b3..4a60932c 100644 --- a/README.linux +++ b/README.linux @@ -73,8 +73,8 @@ e.g. CMAKE_MODULE_PATH=/usr/lib/x86_64-linux-gnu/cmake/Qt5 2.2. Using the Qt Maintenance Tool ---------------------------------- -Alternatively, for a more consistent, dependable, flexible experience, sign up and download the -Qt Maintenance Tool from +Alternatively, for a more consistent experience, sign up and download the Qt Maintenance Tool +from https://www.qt.io/download-qt-installer @@ -82,8 +82,8 @@ On Ubuntu/Debian you may need to install xinerama to run the tool: sudo apt install libxcb-xinerama0 -Launch the tool and install the "Desktop gcc 64-bit" component for either Qt 5.15.2 or Qt 6 -(>= 6.1, and not 6.3.0). +Launch the tool and install the "Desktop gcc 64-bit" component for either Qt 5.15.2 (preferred) +or Qt 6 (>= 6.1, 6.2.4 preferably, and not >= 6.3 which are incompatible). Once Qt is installed you may need to tell CMake where it is: diff --git a/backend/2of5.c b/backend/2of5.c index 58044610..d1d347c2 100644 --- a/backend/2of5.c +++ b/backend/2of5.c @@ -207,7 +207,7 @@ static int c25_inter_common(struct zint_symbol *symbol, unsigned char source[], /* ISO/IEC 16390:2007 Section 4.4 min height 5mm or 15% of symbol width whichever greater where (P = character pairs, N = wide/narrow ratio = 3) width = (P(4N + 6) + N + 6)X = (length / 2) * 18 + 9 */ - /* Taking X = 0.330mm from Annex D.3.1 (application specification) */ + /* Taking min X = 0.330mm from Annex D.3.1 (application specification) */ const float min_height_min = stripf(5.0f / 0.33f); float min_height = stripf((18.0f * (length / 2) + 9.0f) * 0.15f); if (min_height < min_height_min) { @@ -281,8 +281,11 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt } /* Deutsche Post Leitcode */ +/* Documentation (of a very incomplete and non-technical type): +https://www.deutschepost.de/content/dam/dpag/images/D_d/dialogpost-schwer/dp-dialogpost-schwer-broschuere-072021.pdf +*/ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) { - int i, error_number; + int i, j, error_number; unsigned int count; int factor; unsigned char localstr[16] = {0}; @@ -311,16 +314,27 @@ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int leng localstr[13] = c25_check_digit(count); localstr[14] = '\0'; error_number = c25_inter_common(symbol, localstr, 14, 1 /*dont_set_height*/); - ustrcpy(symbol->text, localstr); + + /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do examples at + https://www.philaseiten.de/cgi-bin/index.pl?ST=8615&CP=0&F=1#M147 */ + for (i = 0, j = 0; i <= 14; i++) { + symbol->text[j++] = localstr[i]; + if (i == 4 || i == 7 || i == 10) { + symbol->text[j++] = '.'; + } + } /* TODO: Find documentation on BARCODE_DPLEIT dimensions/height */ + /* Based on eyeballing DIALOGPOST SCHWER, using 72X as default */ + (void) set_height(symbol, 0.0f, 72.0f, 0.0f, 1 /*no_errtxt*/); return error_number; } /* Deutsche Post Identcode */ +/* See dpleit() for (sort of) documentation reference */ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length) { - int i, error_number, zeroes; + int i, j, error_number, zeroes; unsigned int count; int factor; unsigned char localstr[16] = {0}; @@ -348,9 +362,20 @@ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int len localstr[11] = c25_check_digit(count); localstr[12] = '\0'; error_number = c25_inter_common(symbol, localstr, 12, 1 /*dont_set_height*/); - ustrcpy(symbol->text, localstr); + + /* HRT formatting as per DIALOGPOST SCHWER brochure but TEC-IT differs as do other examples (see above) */ + for (i = 0, j = 0; i <= 12; i++) { + symbol->text[j++] = localstr[i]; + if (i == 1 || i == 4 || i == 7) { + symbol->text[j++] = '.'; + } else if (i == 3 || i == 10) { + symbol->text[j++] = ' '; + } + } /* TODO: Find documentation on BARCODE_DPIDENT dimensions/height */ + /* Based on eyeballing DIALOGPOST SCHWER, using 72X as default */ + (void) set_height(symbol, 0.0f, 72.0f, 0.0f, 1 /*no_errtxt*/); return error_number; } diff --git a/backend/bmp.c b/backend/bmp.c index 4fa6bc54..32c94f54 100644 --- a/backend/bmp.c +++ b/backend/bmp.c @@ -31,12 +31,14 @@ /* SPDX-License-Identifier: BSD-3-Clause */ #include +#include #include #ifdef _MSC_VER #include #include #endif #include "common.h" +#include "output.h" #include "bmp.h" /* Bitmap header structure */ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) { @@ -44,6 +46,7 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) int row_size; int bits_per_pixel; int colour_count; + int resolution; unsigned int data_offset, data_size, file_size; unsigned char *bitmap_file_start, *bmp_posn; unsigned char *bitmap; @@ -157,8 +160,9 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) info_header.bits_per_pixel = bits_per_pixel; info_header.compression_method = 0; /* BI_RGB */ info_header.image_size = 0; - info_header.horiz_res = 0; - info_header.vert_res = 0; + resolution = symbol->dpmm ? (int) roundf(stripf(symbol->dpmm * 1000.0f)) : 0; /* pixels per metre */ + info_header.horiz_res = resolution; + info_header.vert_res = resolution; info_header.colours = colour_count; info_header.important_colours = colour_count; @@ -194,7 +198,7 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) #endif bmp_file = stdout; } else { - if (!(bmp_file = fopen(symbol->outfile, "wb"))) { + if (!(bmp_file = out_fopen(symbol->outfile, "wb"))) { free(bitmap_file_start); sprintf(symbol->errtxt, "601: Could not open output file (%d: %.30s)", errno, strerror(errno)); return ZINT_ERROR_FILE_ACCESS; diff --git a/backend/codablock.c b/backend/codablock.c index fcfb5319..69ebda7c 100644 --- a/backend/codablock.c +++ b/backend/codablock.c @@ -563,8 +563,8 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int } symbol->text[0] = '\0'; /* Disable HRT for compatibility with CODABLOCKF */ if (symbol->output_options & COMPLIANT_HEIGHT) { - /* AIM ISS-X-24 Section 4.5.1 minimum row height 8 (for compatibility with CODABLOCKF, not specced for - CODE128) */ + /* AIM ISS-X-24 Section 4.6.1 minimum row height 8X (for compatibility with CODABLOCKF, not specced + for CODE128) */ error_number = set_height(symbol, 8.0f, 10.0f, 0.0f, 0 /*no_errtxt*/); } else { (void) set_height(symbol, 0.0f, 5.0f, 0.0f, 1 /*no_errtxt*/); diff --git a/backend/code128.c b/backend/code128.c index d9720976..7088c375 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -448,7 +448,7 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len indexchaine = 0; mode = c128_parunmodd(source[indexchaine]); - if ((symbol->symbology == BARCODE_CODE128B) && (mode == C128_ABORC)) { + if ((symbol->symbology == BARCODE_CODE128AB) && (mode == C128_ABORC)) { mode = C128_AORB; } @@ -461,7 +461,7 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len break; } mode = c128_parunmodd(source[indexchaine]); - if ((symbol->symbology == BARCODE_CODE128B) && (mode == C128_ABORC)) { + if ((symbol->symbology == BARCODE_CODE128AB) && (mode == C128_ABORC)) { mode = C128_AORB; } } @@ -1169,7 +1169,8 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) } else if (!is_sane(NEON_F, local_source + length - 6, 3)) { /* 3-digit Service Code */ strcpy(symbol->errtxt, "832: Service Code (characters 6-4 from end) should be numeric"); } else { /* Last 10 characters of Tracking No. */ - strcpy(symbol->errtxt, "833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric"); + strcpy(symbol->errtxt, + "833: Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric"); } error_number = ZINT_WARN_NONCOMPLIANT; } diff --git a/backend/common.c b/backend/common.c index bc146193..d1e4b3a1 100644 --- a/backend/common.c +++ b/backend/common.c @@ -262,7 +262,7 @@ INTERNAL int is_stackable(const int symbology) { } switch (symbology) { - case BARCODE_CODE128B: + case BARCODE_CODE128AB: case BARCODE_ISBNX: case BARCODE_EAN14: case BARCODE_NVE18: diff --git a/backend/dmatrix.c b/backend/dmatrix.c index 72e735d2..3aa7dfbc 100644 --- a/backend/dmatrix.c +++ b/backend/dmatrix.c @@ -1686,7 +1686,7 @@ static int dm_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], co if (symbol->structapp.id[0]) { int id, id_len, id1_err, id2_err; - for (id_len = 0; id_len < 32 && symbol->structapp.id[id_len]; id_len++); + for (id_len = 1; id_len < 7 && symbol->structapp.id[id_len]; id_len++); if (id_len > 6) { /* ID1 * 1000 + ID2 */ strcpy(symbol->errtxt, "722: Structured Append ID too long (6 digit maximum)"); diff --git a/backend/emf.c b/backend/emf.c index 1185e7f1..af9883bf 100644 --- a/backend/emf.c +++ b/backend/emf.c @@ -42,6 +42,7 @@ #include #endif #include "common.h" +#include "output.h" #include "emf.h" /* Multiply truncating to 3 decimal places (avoids rounding differences on various platforms) */ @@ -180,6 +181,16 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { int rectangle_bycolour[9] = {0}; int width, height; + int bounds_pxx, bounds_pxy; /* Pixels */ + int frame_cmmx, frame_cmmy; /* Hundredths of a mm, i.e. "centi-millimeters" */ + int device_pxx, device_pxy; /* Pixels */ + int mmx, mmy; /* Millimeters */ + int micronx, microny; /* Micrometers */ + const float dpmm = symbol->dpmm ? stripf(symbol->dpmm) + : ZBarcode_XdimDp_From_Scale(symbol->symbology, symbol->scale, + ZBarcode_Default_Xdim(symbol->symbology), "EMF"); + const int sideways = rotate_angle == 90 || rotate_angle == 270; + int draw_background = 1; int bold; const int output_to_stdout = symbol->output_options & BARCODE_STDOUT; @@ -230,6 +241,8 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { emr_ellipse_t *circle; emr_polygon_t *hexagon; + const int ih_ultra_offset = symbol->symbology == BARCODE_ULTRA ? 8 : 0; + if (symbol->vector == NULL) { strcpy(symbol->errtxt, "643: Vector header NULL"); return ZINT_ERROR_INVALID_DATA; @@ -281,39 +294,54 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { width = (int) ceilf(symbol->vector->width); height = (int) ceilf(symbol->vector->height); + bounds_pxx = width - 1; /* Following Inkscape, bounds "inclusive-inclusive", so size 1 less */ + bounds_pxy = height - 1; + device_pxx = width; /* device */ + device_pxy = height; + + if (dpmm) { + frame_cmmx = (int) roundf(stripf(width * 100.0f / dpmm)) - 1; /* frame also "inclusive-inclusive" */ + frame_cmmy = (int) roundf(stripf(height * 100.0f / dpmm)) - 1; + mmx = (int) roundf(stripf(width / dpmm)); /* millimeters */ + mmy = (int) roundf(stripf(height / dpmm)); + micronx = (int) roundf(stripf(width * 1000.0f / dpmm)); /* micrometers */ + microny = (int) roundf(stripf(height * 1000.0f / dpmm)); + } else { /* Should only happen if `symbol->scale` zero. */ + frame_cmmx = (int) roundf(stripf(width * 100.0f)) - 1; + frame_cmmy = (int) roundf(stripf(height * 100.0f)) - 1; + mmx = (int) roundf(stripf(width)); + mmy = (int) roundf(stripf(height)); + micronx = (int) roundf(stripf(width * 1000.0f)); + microny = (int) roundf(stripf(height * 1000.0f)); + } + /* Header */ emr_header.type = 0x00000001; /* EMR_HEADER */ emr_header.size = 108; /* Including extensions */ - emr_header.emf_header.bounds.left = 0; - emr_header.emf_header.bounds.right = rotate_angle == 90 || rotate_angle == 270 ? height : width; - emr_header.emf_header.bounds.bottom = rotate_angle == 90 || rotate_angle == 270 ? width : height; - emr_header.emf_header.bounds.top = 0; - emr_header.emf_header.frame.left = 0; - emr_header.emf_header.frame.right = emr_header.emf_header.bounds.right * 30; - emr_header.emf_header.frame.top = 0; - emr_header.emf_header.frame.bottom = emr_header.emf_header.bounds.bottom * 30; + emr_header.emf_header.bounds.left = emr_header.emf_header.bounds.top = 0; + emr_header.emf_header.bounds.right = sideways ? bounds_pxy : bounds_pxx; + emr_header.emf_header.bounds.bottom = sideways ? bounds_pxx : bounds_pxy; + emr_header.emf_header.frame.left = emr_header.emf_header.frame.top = 0; + emr_header.emf_header.frame.right = sideways ? frame_cmmy : frame_cmmx; + emr_header.emf_header.frame.bottom = sideways ? frame_cmmx : frame_cmmy; emr_header.emf_header.record_signature = 0x464d4520; /* ENHMETA_SIGNATURE */ emr_header.emf_header.version = 0x00010000; - if (symbol->symbology == BARCODE_ULTRA) { - emr_header.emf_header.handles = 12; /* Number of graphics objects */ - } else { - emr_header.emf_header.handles = fsize2 != 0.0f ? 5 : 4; - } + emr_header.emf_header.handles = (fsize2 != 0.0f ? 5 : 4) + ih_ultra_offset; /* Number of graphics objects */ emr_header.emf_header.reserved = 0x0000; emr_header.emf_header.n_description = 0; emr_header.emf_header.off_description = 0; emr_header.emf_header.n_pal_entries = 0; - emr_header.emf_header.device.cx = 1000; - emr_header.emf_header.device.cy = 1000; - emr_header.emf_header.millimeters.cx = 300; - emr_header.emf_header.millimeters.cy = 300; + emr_header.emf_header.device.cx = sideways ? device_pxy : device_pxx; + emr_header.emf_header.device.cy = sideways ? device_pxx : device_pxy; + emr_header.emf_header.millimeters.cx = sideways ? mmy : mmx; + emr_header.emf_header.millimeters.cy = sideways ? mmx : mmy; /* HeaderExtension1 */ emr_header.emf_header.cb_pixel_format = 0x0000; /* None set */ emr_header.emf_header.off_pixel_format = 0x0000; /* None set */ emr_header.emf_header.b_open_gl = 0x0000; /* OpenGL not present */ /* HeaderExtension2 */ - emr_header.emf_header.micrometers.cx = 0; - emr_header.emf_header.micrometers.cy = 0; + emr_header.emf_header.micrometers.cx = sideways ? microny : micronx; + emr_header.emf_header.micrometers.cy = sideways ? micronx : microny; bytecount = 108; recordcount = 1; @@ -339,7 +367,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { /* Create Brushes */ emr_createbrushindirect_bg.type = 0x00000027; /* EMR_CREATEBRUSHINDIRECT */ emr_createbrushindirect_bg.size = 24; - emr_createbrushindirect_bg.ih_brush = 1; + emr_createbrushindirect_bg.ih_brush = 0; emr_createbrushindirect_bg.log_brush.brush_style = 0x0000; /* BS_SOLID */ emr_createbrushindirect_bg.log_brush.color.red = bgred; emr_createbrushindirect_bg.log_brush.color.green = bggrn; @@ -353,7 +381,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { for (i = 0; i < 9; i++) { emr_createbrushindirect_colour[i].type = 0x00000027; /* EMR_CREATEBRUSHINDIRECT */ emr_createbrushindirect_colour[i].size = 24; - emr_createbrushindirect_colour[i].ih_brush = 2 + i; + emr_createbrushindirect_colour[i].ih_brush = 1 + i; emr_createbrushindirect_colour[i].log_brush.brush_style = 0x0000; /* BS_SOLID */ if (i == 0) { emr_createbrushindirect_colour[i].log_brush.color.red = fgred; @@ -372,7 +400,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { } else { emr_createbrushindirect_fg.type = 0x00000027; /* EMR_CREATEBRUSHINDIRECT */ emr_createbrushindirect_fg.size = 24; - emr_createbrushindirect_fg.ih_brush = 2; + emr_createbrushindirect_fg.ih_brush = 1; emr_createbrushindirect_fg.log_brush.brush_style = 0x0000; /* BS_SOLID */ emr_createbrushindirect_fg.log_brush.color.red = fgred; emr_createbrushindirect_fg.log_brush.color.green = fggrn; @@ -385,7 +413,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { emr_selectobject_bgbrush.type = 0x00000025; /* EMR_SELECTOBJECT */ emr_selectobject_bgbrush.size = 12; - emr_selectobject_bgbrush.ih_object = 1; + emr_selectobject_bgbrush.ih_object = emr_createbrushindirect_bg.ih_brush; bytecount += 12; recordcount++; @@ -393,14 +421,14 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { for (i = 0; i < 9; i++) { emr_selectobject_colour[i].type = 0x00000025; /* EMR_SELECTOBJECT */ emr_selectobject_colour[i].size = 12; - emr_selectobject_colour[i].ih_object = 2 + i; + emr_selectobject_colour[i].ih_object = emr_createbrushindirect_colour[i].ih_brush; } bytecount += colours_used * 12; recordcount += colours_used; } else { emr_selectobject_fgbrush.type = 0x00000025; /* EMR_SELECTOBJECT */ emr_selectobject_fgbrush.size = 12; - emr_selectobject_fgbrush.ih_object = 2; + emr_selectobject_fgbrush.ih_object = emr_createbrushindirect_fg.ih_brush; bytecount += 12; recordcount++; } @@ -408,7 +436,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { /* Create Pens */ emr_createpen.type = 0x00000026; /* EMR_CREATEPEN */ emr_createpen.size = 28; - emr_createpen.ih_pen = 11; + emr_createpen.ih_pen = 2 + ih_ultra_offset; emr_createpen.log_pen.pen_style = 0x00000005; /* PS_NULL */ emr_createpen.log_pen.width.x = 1; emr_createpen.log_pen.width.y = 0; /* ignored */ @@ -421,7 +449,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { emr_selectobject_pen.type = 0x00000025; /* EMR_SELECTOBJECT */ emr_selectobject_pen.size = 12; - emr_selectobject_pen.ih_object = 11; + emr_selectobject_pen.ih_object = emr_createpen.ih_pen; bytecount += 12; recordcount++; @@ -431,8 +459,8 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { background.size = 24; background.box.top = 0; background.box.left = 0; - background.box.right = emr_header.emf_header.bounds.right; - background.box.bottom = emr_header.emf_header.bounds.bottom; + background.box.right = width; + background.box.bottom = height; bytecount += 24; recordcount++; } @@ -537,7 +565,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { memset(&emr_extcreatefontindirectw, 0, sizeof(emr_extcreatefontindirectw)); emr_extcreatefontindirectw.type = 0x00000052; /* EMR_EXTCREATEFONTINDIRECTW */ emr_extcreatefontindirectw.size = 104; - emr_extcreatefontindirectw.ih_fonts = 12; + emr_extcreatefontindirectw.ih_fonts = 3 + ih_ultra_offset; emr_extcreatefontindirectw.elw.height = (int32_t) fsize; emr_extcreatefontindirectw.elw.width = 0; /* automatic */ emr_extcreatefontindirectw.elw.weight = bold ? 700 : 400; @@ -551,20 +579,20 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { emr_selectobject_font.type = 0x00000025; /* EMR_SELECTOBJECT */ emr_selectobject_font.size = 12; - emr_selectobject_font.ih_object = 12; + emr_selectobject_font.ih_object = emr_extcreatefontindirectw.ih_fonts; bytecount += 12; recordcount++; if (fsize2) { memcpy(&emr_extcreatefontindirectw2, &emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw)); - emr_extcreatefontindirectw2.ih_fonts = 13; + emr_extcreatefontindirectw2.ih_fonts = 4 + ih_ultra_offset; emr_extcreatefontindirectw2.elw.height = (int32_t) fsize2; bytecount += 104; recordcount++; emr_selectobject_font2.type = 0x00000025; /* EMR_SELECTOBJECT */ emr_selectobject_font2.size = 12; - emr_selectobject_font2.ih_object = 13; + emr_selectobject_font2.ih_object = emr_extcreatefontindirectw2.ih_fonts; bytecount += 12; recordcount++; } @@ -684,7 +712,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { #endif emf_file = stdout; } else { - if (!(emf_file = fopen(symbol->outfile, "wb"))) { + if (!(emf_file = out_fopen(symbol->outfile, "wb"))) { sprintf(symbol->errtxt, "640: Could not open output file (%d: %.30s)", errno, strerror(errno)); return ZINT_ERROR_FILE_ACCESS; } diff --git a/backend/gif.c b/backend/gif.c index c20096fe..337a60e4 100644 --- a/backend/gif.c +++ b/backend/gif.c @@ -37,6 +37,7 @@ #include #endif #include "common.h" +#include "output.h" /* Limit initial LZW buffer size to this in expectation that compressed data will fit for typical scalings */ #define GIF_LZW_PAGE_SIZE 0x100000 /* Megabyte */ @@ -474,7 +475,7 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) #endif gif_file = stdout; } else { - if (!(gif_file = fopen(symbol->outfile, "wb"))) { + if (!(gif_file = out_fopen(symbol->outfile, "wb"))) { sprintf(symbol->errtxt, "611: Could not open output file (%d: %.30s)", errno, strerror(errno)); return ZINT_ERROR_FILE_ACCESS; } diff --git a/backend/gridmtx.c b/backend/gridmtx.c index d5779021..932fe51d 100644 --- a/backend/gridmtx.c +++ b/backend/gridmtx.c @@ -1079,7 +1079,7 @@ INTERNAL int gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], cons if (symbol->structapp.id[0]) { int id, id_len; - for (id_len = 0; id_len < 32 && symbol->structapp.id[id_len]; id_len++); + for (id_len = 1; id_len < 4 && symbol->structapp.id[id_len]; id_len++); if (id_len > 3) { /* 255 (8 bits) */ strcpy(symbol->errtxt, "538: Structured Append ID too long (3 digit maximum)"); diff --git a/backend/library.c b/backend/library.c index 06e56bf2..2e801ad8 100644 --- a/backend/library.c +++ b/backend/library.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include "common.h" #include "eci.h" @@ -41,12 +42,12 @@ /* It's assumed that int is at least 32 bits, the following will compile-time fail if not * https://stackoverflow.com/a/1980056 */ -typedef char static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ? -1 : 1]; +typedef char static_assert_int_at_least_32bits[sizeof(int) * CHAR_BIT < 32 ? -1 : 1]; -typedef char static_assert_uint16_is_16bits[sizeof(uint16_t) != 2 ? -1 : 1]; -typedef char static_assert_int32_is_32bits[sizeof(int32_t) != 4 ? -1 : 1]; -typedef char static_assert_uint32_is_32bits[sizeof(uint32_t) != 4 ? -1 : 1]; -typedef char static_assert_uint64_at_least_64bits[sizeof(uint64_t) < 8 ? -1 : 1]; +typedef char static_assert_uint16_is_16bits[sizeof(uint16_t) * CHAR_BIT != 16 ? -1 : 1]; +typedef char static_assert_int32_is_32bits[sizeof(int32_t) * CHAR_BIT != 32 ? -1 : 1]; +typedef char static_assert_uint32_is_32bits[sizeof(uint32_t) * CHAR_BIT != 32 ? -1 : 1]; +typedef char static_assert_uint64_at_least_64bits[sizeof(uint64_t) * CHAR_BIT < 64 ? -1 : 1]; /* Create and initialize a symbol structure */ struct zint_symbol *ZBarcode_Create(void) { @@ -203,8 +204,10 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) INTERNAL int bc412(struct zint_symbol *symbol, unsigned char source[], int length); /* BC412 */ /* Output handlers */ -INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */ -INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to EPS/EMF/SVG */ +/* Plot to BMP/GIF/PCX/PNG/TIF */ +INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); +/* Plot to EMF/EPS/SVG */ +INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Prefix error message with Error/Warning */ static int error_tag(struct zint_symbol *symbol, int error_number, const char *error_string) { @@ -1047,8 +1050,8 @@ int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[ } /* Check other symbol fields */ - if ((symbol->scale < 0.01f) || (symbol->scale > 100.0f)) { - return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "227: Scale out of range (0.01 to 100)"); + if ((symbol->scale < 0.01f) || (symbol->scale > 200.0f)) { + return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "227: Scale out of range (0.01 to 200)"); } if ((symbol->dot_size < 0.01f) || (symbol->dot_size > 20.0f)) { return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "221: Dot size out of range (0.01 to 20)"); @@ -1207,6 +1210,33 @@ static int check_output_args(struct zint_symbol *symbol, int rotate_angle) { return 0; } +struct zint_filetypes { const char extension[4]; int is_raster; int filetype; }; +static const struct zint_filetypes filetypes[] = { + { "BMP", 1, OUT_BMP_FILE }, { "EMF", 0, OUT_EMF_FILE }, { "EPS", 0, OUT_EPS_FILE }, + { "GIF", 1, OUT_GIF_FILE }, { "PCX", 1, OUT_PCX_FILE }, { "PNG", 1, OUT_PNG_FILE }, + { "SVG", 0, OUT_SVG_FILE }, { "TIF", 1, OUT_TIF_FILE }, { "TXT", 0, 0 } +}; + +/* Return index of `extension` in `filetypes`, or -1 if not found */ +static int filetype_idx(const char *extension) { + char uc_extension[4] = {0}; + int i; + + if (strlen(extension) != 3) { + return -1; + } + memcpy(uc_extension, extension, 3); + to_upper((unsigned char *) uc_extension, 3); + + for (i = 0; i < ARRAY_SIZE(filetypes); i++) { + if (strcmp(uc_extension, filetypes[i].extension) == 0) { + break; + } + } + + return i == ARRAY_SIZE(filetypes) ? -1 : i; +} + /* Output a previously encoded symbol to file `symbol->outfile` */ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { int error_number; @@ -1218,40 +1248,17 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { len = (int) strlen(symbol->outfile); if (len > 3) { - char output[4]; - output[0] = symbol->outfile[len - 3]; - output[1] = symbol->outfile[len - 2]; - output[2] = symbol->outfile[len - 1]; - output[3] = '\0'; - to_upper((unsigned char *) output, 3); - - if (!(strcmp(output, "PNG"))) { - error_number = plot_raster(symbol, rotate_angle, OUT_PNG_FILE); - - } else if (!(strcmp(output, "BMP"))) { - error_number = plot_raster(symbol, rotate_angle, OUT_BMP_FILE); - - } else if (!(strcmp(output, "PCX"))) { - error_number = plot_raster(symbol, rotate_angle, OUT_PCX_FILE); - - } else if (!(strcmp(output, "GIF"))) { - error_number = plot_raster(symbol, rotate_angle, OUT_GIF_FILE); - - } else if (!(strcmp(output, "TIF"))) { - error_number = plot_raster(symbol, rotate_angle, OUT_TIF_FILE); - - } else if (!(strcmp(output, "TXT"))) { - error_number = dump_plot(symbol); - - } else if (!(strcmp(output, "EPS"))) { - 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); - - } else if (!(strcmp(output, "EMF"))) { - error_number = plot_vector(symbol, rotate_angle, OUT_EMF_FILE); - + int i = filetype_idx(symbol->outfile + len - 3); + if (i >= 0) { + if (filetypes[i].filetype) { + if (filetypes[i].is_raster) { + error_number = plot_raster(symbol, rotate_angle, filetypes[i].filetype); + } else { + error_number = plot_vector(symbol, rotate_angle, filetypes[i].filetype); + } + } else { + error_number = dump_plot(symbol); + } } else { return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "225: Unknown output format"); } @@ -1597,7 +1604,7 @@ int ZBarcode_BarcodeName(int symbol_id, char name[32]) { { "BARCODE_MAXICODE", BARCODE_MAXICODE, 57 }, { "BARCODE_QRCODE", BARCODE_QRCODE, 58 }, { "", -1, 59 }, - { "BARCODE_CODE128B", BARCODE_CODE128B, 60 }, + { "BARCODE_CODE128AB", BARCODE_CODE128AB, 60 }, { "", -1, 61 }, { "", -1, 62 }, { "BARCODE_AUSPOST", BARCODE_AUSPOST, 63 }, @@ -1761,7 +1768,7 @@ unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) { /* Note does not include HIBC versions */ switch (symbol_id) { case BARCODE_CODE128: /* Note does not include GS1_128 or NVE18 */ - case BARCODE_CODE128B: + case BARCODE_CODE128AB: case BARCODE_CODE16K: case BARCODE_CODABLOCKF: case BARCODE_PDF417: @@ -1831,7 +1838,7 @@ unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) { case BARCODE_C25LOGIC: case BARCODE_C25IND: case BARCODE_CODE128: /* Left to application */ - case BARCODE_CODE128B: + case BARCODE_CODE128AB: case BARCODE_DPLEIT: /* TODO: Find doc */ case BARCODE_DPIDENT: /* TODO: Find doc */ case BARCODE_FLAT: /* TODO: Find doc */ @@ -1856,6 +1863,243 @@ unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) { return result; } +/* Return default X-dimension in mm for symbology `symbol_id`. Returns 0 on error (invalid `symbol_id`) */ +float ZBarcode_Default_Xdim(int symbol_id) { + float x_dim_mm; + + if (!ZBarcode_ValidID(symbol_id)) { + return 0.0f; + } + switch (symbol_id) { + /* Postal 2/4-track */ + case BARCODE_AUSPOST: + case BARCODE_AUSREPLY: + case BARCODE_AUSROUTE: + case BARCODE_AUSREDIRECT: + /* Australia Post Customer Barcoding Technical Specifications, average of 0.4 to 0.6 mm */ + x_dim_mm = 0.5f; + break; + case BARCODE_CEPNET: + case BARCODE_POSTNET: + case BARCODE_PLANET: + case BARCODE_USPS_IMAIL: + /* USPS-B-3200 Section 2.3.1, height 0.145" (average of 0.125, 0.165) / 6.235 (Zint height), same as + USPS DMM 300 Section 708.4.2.5 using bar pitch (1" / 43) ~ 0.023" */ + x_dim_mm = 0.591f; + break; + case BARCODE_RM4SCC: + case BARCODE_KIX: + case BARCODE_MAILMARK: + /* Royal Mail Mailmark Barcode Definition Document, height 5.1mm / 8 (Zint height) == 0.6375 */ + x_dim_mm = 0.638f; /* Seems better fit to round up to 3 d.p. */ + break; + case BARCODE_JAPANPOST: + x_dim_mm = 0.6f; /* Japan Post Zip/Barcode Manual */ + break; + + /* GS1 (excluding GS1-128, ITF-14, GS1 QRCODE & GS1 DATAMATRIX - see default) */ + case BARCODE_EANX: + case BARCODE_EANX_CHK: + case BARCODE_EANX_CC: + case BARCODE_ISBNX: + case BARCODE_UPCA: + case BARCODE_UPCA_CHK: + case BARCODE_UPCA_CC: + case BARCODE_UPCE: + case BARCODE_UPCE_CHK: + case BARCODE_UPCE_CC: + case BARCODE_DBAR_OMN: + case BARCODE_DBAR_OMN_CC: + case BARCODE_DBAR_LTD: + case BARCODE_DBAR_LTD_CC: + case BARCODE_DBAR_EXP: + case BARCODE_DBAR_EXP_CC: + case BARCODE_DBAR_STK: + case BARCODE_DBAR_STK_CC: + case BARCODE_DBAR_OMNSTK: + case BARCODE_DBAR_OMNSTK_CC: + case BARCODE_DBAR_EXPSTK: + case BARCODE_DBAR_EXPSTK_CC: + x_dim_mm = 0.33f; /* GS1 General Standards 22.0 Section 5.12.3 Table 1 except DBAR_LTD Table 4 */ + break; + + /* Specific */ + case BARCODE_BC412: + x_dim_mm = 0.12f; /* SEMI T1-95 Table 1 */ + break; + case BARCODE_CODABAR: + x_dim_mm = 0.38f; /* EN 798:1996 Appendix D.1 (d), average of 0.33 to 0.43 mm */ + break; + case BARCODE_CODE32: + x_dim_mm = 0.25f; /* Allegato A Caratteristiche tecniche del bollino farmaceutico, 0.25mm */ + break; + case BARCODE_DPD: + x_dim_mm = 0.375f; /* DPD Parcel Label Specification Version 2.4.1 (19.01.2021) Section 4.6.1.2 */ + break; + case BARCODE_FIM: + /* USPS DMM 300 Section 708.9.3, 0.03125" */ + x_dim_mm = 0.79375f; + break; + case BARCODE_LOGMARS: + x_dim_mm = 0.34925f; /* MIL-STD-1189 Rev. B Section 5.2, average of 0.0075" and 0.02" */ + break; + case BARCODE_MAXICODE: + /* ISO/IEC 16023:2000 Table 7, based on L = 25.5mm */ + x_dim_mm = 0.88f; + break; + case BARCODE_PHARMA: + x_dim_mm = 0.5f; /* Laetus Pharmacode Guide Section 1.2, standard 0.5mm */ + break; + case BARCODE_PHARMA_TWO: + x_dim_mm = 1.0f; /* Laetus Pharmacode Guide Section 1.4, standard 1mm */ + break; + case BARCODE_PZN: + x_dim_mm = 0.25f; /* Technical Information regarding PZN, "normal" X 0.25mm */ + break; + case BARCODE_TELEPEN: + case BARCODE_TELEPEN_NUM: + /* Telepen Barcode Symbology information and History, average of between 0.010" and 0.0125" */ + x_dim_mm = 0.28575f; + break; + + /* Stacked (excluding GS1 DataBar) */ + case BARCODE_CODE16K: /* Application-defined */ + case BARCODE_CODE49: /* ANSI/AIM BC6-2000 Appendix D.2.4, C grade if > 0.25mm */ + case BARCODE_CODABLOCKF: /* Application-defined */ + case BARCODE_HIBC_BLOCKF: + case BARCODE_PDF417: /* Maybe 0.27mm following ISO/IEC 15438:2015 Annex S.2.2 example? */ + case BARCODE_PDF417COMP: + case BARCODE_HIBC_PDF: + case BARCODE_MICROPDF417: + case BARCODE_HIBC_MICPDF: + /* Fairly arbitrarily using ISO/IEC 15416:2016 Section 5.3.1 Table 1, aperature diameters 0.125 & 0.250 + (also fits in 0.25 <= X < 0.5 range for aperature 0.2 from ISO/IEC 15415:2011 Annex D Table D.1) */ + x_dim_mm = 0.33f; + break; + + /* Application defined (and hence pretty arbitrary) */ + default: + if (is_fixed_ratio(symbol_id)) { + /* GS1 General Standards 22.0 Section 5.12.3 Table 1 (general retail) */ + x_dim_mm = 0.625f; + } else { + /* GS1 General Standards 22.0 Section 5.12.3.4 GS1-128 Tables 2, 4, 5, 6, 8 */ + x_dim_mm = 0.495f; + } + break; + } + + return x_dim_mm; +} + +/* Return the scale to use for `symbol_id` for non-zero X-dimension `x_dim_mm` at `dpmm` dots per mm for + `filetype`. If `dpmm` zero defaults to 12. If `filetype` NULL/empty, defaults to "GIF". Returns 0 on error */ +float ZBarcode_Scale_From_XdimDp(int symbol_id, float x_dim_mm, float dpmm, const char *filetype) { + int i; + float scale; + + if (!ZBarcode_ValidID(symbol_id)) { + return 0.0f; + } + if (x_dim_mm <= 0.0f || x_dim_mm > 10.0f) { /* 10mm == 0.39" */ + return 0.0f; + } + if (dpmm == 0.0f) { + dpmm = 12.0f; /* ~300 dpi */ + } else if (dpmm < 0.0f || dpmm > 1000.0f) { /* 1000 dpmm == 25400 dpi */ + return 0.0f; + } + if (filetype && *filetype) { + if ((i = filetype_idx(filetype)) < 0 || filetypes[i].filetype == 0) { /* Not found or TXT */ + return 0.0f; + } + } else { + i = filetype_idx("GIF"); /* Default to raster */ + } + + scale = stripf(stripf(x_dim_mm) * stripf(dpmm)); + + if (symbol_id == BARCODE_MAXICODE) { + if (filetypes[i].is_raster) { + scale /= 10.0f; + } else if (filetypes[i].filetype == OUT_EMF_FILE) { + scale /= 40.0f; + } else { + scale /= 2.0f; + } + } else { + if (filetypes[i].is_raster) { + scale = roundf(scale) / 2.0f; /* Half-integer increments */ + } else { + scale /= 2.0f; + } + } + scale = stripf(scale); + + if (scale > 200.0f) { + scale = 200.0f; + } else { + if (filetypes[i].is_raster) { + if (symbol_id == BARCODE_MAXICODE) { + if (scale < 0.2f) { + scale = 0.2f; + } + } else if (scale < 0.5f) { + scale = 0.5f; /* Note if dotty mode needs further bounding to 1.0 */ + } + } else { + if (scale < 0.1f) { + scale = 0.1f; + } + } + } + + return scale; +} + +/* Reverse of `ZBarcode_Scale_From_XdimDp()` above to estimate the X-dimension or dpmm given non-zero `scale` and + non-zero `x_dim_mm_or_dpmm`. Return value bound to dpmm max not X-dimension max. Returns 0 on error */ +float ZBarcode_XdimDp_From_Scale(int symbol_id, float scale, float xdim_mm_or_dpmm, const char *filetype) { + int i; + + if (!ZBarcode_ValidID(symbol_id)) { + return 0.0f; + } + if (scale <= 0.0f || scale > 200.0f) { + return 0.0f; + } + if (xdim_mm_or_dpmm <= 0.0f || xdim_mm_or_dpmm > 1000.0f) { /* 1000 dpmm == 25400 dpi */ + return 0.0f; + } + if (filetype && *filetype) { + if ((i = filetype_idx(filetype)) < 0 || filetypes[i].filetype == 0) { /* Not found or TXT */ + return 0.0f; + } + } else { + i = filetype_idx("GIF"); /* Default to raster */ + } + + if (symbol_id == BARCODE_MAXICODE) { + if (filetypes[i].is_raster) { + scale *= 10.0f; + } else if (filetypes[i].filetype == OUT_EMF_FILE) { + scale *= 40.0f; + } else { + scale *= 2.0f; + } + } else { + scale *= 2.0f; + } + + xdim_mm_or_dpmm = stripf(stripf(scale) / stripf(xdim_mm_or_dpmm)); + + if (xdim_mm_or_dpmm > 1000.0f) { /* Note if X-dimension sought needs to be further bound to <= 10 on return */ + xdim_mm_or_dpmm = 1000.0f; + } + + return xdim_mm_or_dpmm; +} + /* Whether Zint built without PNG support */ int ZBarcode_NoPng(void) { #ifdef ZINT_NO_PNG diff --git a/backend/mailmark.c b/backend/mailmark.c index 03fb8a56..98f9bd1f 100644 --- a/backend/mailmark.c +++ b/backend/mailmark.c @@ -154,13 +154,15 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le ustrcpy(local_source, source); if (length < 22) { + if (length < 14) { + strcpy(symbol->errtxt, "588: Input too short (14 character minimum)"); + return ZINT_ERROR_TOO_LONG; + } for (i = length; i <= 22; i++) { strcat(local_source, " "); } length = 22; - } - - if ((length > 22) && (length < 26)) { + } else if ((length > 22) && (length < 26)) { for (i = length; i <= 26; i++) { strcat(local_source, " "); } diff --git a/backend/medical.c b/backend/medical.c index b35db0d7..8d26dd00 100644 --- a/backend/medical.c +++ b/backend/medical.c @@ -188,7 +188,8 @@ INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int if (symbol->output_options & COMPLIANT_HEIGHT) { /* Laetus Pharmacode Guide 1.4 - Two-track height min 8mm / 2mm (X max) = 4, standard 8mm / 1mm = 8, max 12mm / 0.8mm (X min) = 15 */ + Two-track height min 8mm / 2mm (X max) = 4X (2X per row), standard 8mm / 1mm = 8X, + max 12mm / 0.8mm (X min) = 15X */ error_number = set_height(symbol, 2.0f, 8.0f, 15.0f, 0 /*no_errtxt*/); } else { (void) set_height(symbol, 0.0f, 10.0f, 0.0f, 1 /*no_errtxt*/); @@ -270,11 +271,11 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len expand(symbol, dest, d - dest); if (symbol->output_options & COMPLIANT_HEIGHT) { - /* BS EN 798:1995 4.4.1 (d) max of 5mm / 0.191mm (X) ~ 26.178 or 15% of width where (taking N = narrow/wide - ratio as 2 and I = X) width = ((2 * N + 5) * C + (N – 1) * (D + 2)) * X + I * (C – 1) + 2Q + /* BS EN 798:1995 4.4.1 (d) max of 5mm / 0.43mm (X max) ~ 11.628 or 15% of width where (taking N = + narrow/wide ratio as 2 and I = X) width = ((2 * N + 5) * C + (N – 1) * (D + 2)) * X + I * (C – 1) + 2Q = ((4 + 5) * C + (D + 2) + C - 1 + 2 * 10) * X = (10 * C + D + 21) * X Length (C) includes start/stop chars */ - const float min_height_min = stripf(5.0f / 0.191f); + const float min_height_min = stripf(5.0f / 0.43f); float min_height = stripf((10.0f * ((add_checksum ? length + 1 : length) + 2.0f) + d_chars + 21.0f) * 0.15f); if (min_height < min_height_min) { min_height = min_height_min; diff --git a/backend/output.c b/backend/output.c index 0506878a..a9601389 100644 --- a/backend/output.c +++ b/backend/output.c @@ -31,8 +31,14 @@ /* SPDX-License-Identifier: BSD-3-Clause */ #include +#include #include -#include +#ifdef _WIN32 +#include +#include +#else +#include /* mkdir(2) */ +#endif #include "common.h" #include "output.h" #include "font.h" @@ -241,7 +247,7 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text done = 1; break; case BARCODE_CODE128: - case BARCODE_CODE128B: + case BARCODE_CODE128AB: case BARCODE_HIBC_128: case BARCODE_NVE18: /* ISO/IEC 15417:2007 4.4.2 */ @@ -250,7 +256,7 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text break; case BARCODE_DPLEIT: case BARCODE_DPIDENT: - /* Using CODE39 values TODO: Find doc */ + /* Using C25INTER values TODO: Find doc */ *left = *right = 10.0f; done = 1; break; @@ -486,7 +492,7 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text #ifdef ZINT_TEST /* Wrapper for direct testing */ INTERNAL int out_quiet_zones_test(const struct zint_symbol *symbol, const int hide_text, float *left, float *right, float *top, float *bottom) { - return out_quiet_zones(symbol, hide_text, left, right, top, bottom); + return out_quiet_zones(symbol, hide_text, left, right, top, bottom); } #endif @@ -742,4 +748,90 @@ INTERNAL void out_upcean_split_text(int upceanflag, unsigned char text[], } } +/* Make a directory; already existing dir okay */ +/* Adapted from https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950 and + https://nachtimwald.com/2019/07/10/recursive-create-directory-in-c-revisited/ */ +static int out_maybe_mkdir(const char* path) +{ +#ifdef _WIN32 + DWORD dwAttrib; + + /* Try to make the directory */ + if (CreateDirectory(path, NULL) != 0) { /* Non-zero on success */ + return 0; + } + /* If it fails for any reason but already exists, fail */ + if (GetLastError() != ERROR_ALREADY_EXISTS) { + return -1; + } + /* Check if the existing path is a directory */ + if ((dwAttrib = GetFileAttributes(path)) == (DWORD) -1 || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { + return -1; + } +#else + struct stat st; + + /* Try to make the directory */ + if (mkdir(path, 0777) == 0) { + return 0; + } + /* If it fails for any reason but already exists, fail */ + if (errno != EEXIST) { + return -1; + } + /* Check if the existing path is a directory */ + if (stat(path, &st) != 0 || !S_ISDIR(st.st_mode)) { + return -1; + } +#endif + + return 0; +} + +/* Create output file, creating sub-directories if necessary. Returns `fopen()` FILE pointer */ +INTERNAL FILE *out_fopen(const char filename[256], const char *mode) { + FILE *outfile; + + if (!(outfile = fopen(filename, mode))) { + char dirname[256]; + char *d; +#ifdef _WIN32 + char *dirend = strrchr(filename, '\\'); + if (!dirend) { + dirend = strrchr(filename, '/'); + } +#else + char *dirend = strrchr(filename, '/'); +#endif + if (!dirend) { + return outfile; + } + + /* Adapted from https://gist.github.com/JonathonReinhart/8c0d90191c38af2dcadb102c4e202950 */ + /* Remove filename, leaving directories */ + memcpy(dirname, filename, dirend - filename); + dirname[dirend - filename] = '/'; + dirname[dirend - filename + 1] = '\0'; +#if _WIN32 + for (d = dirname; *d; d++) { /* Convert to Unix separators */ + if (*d == '\\') { + *d = '/'; + } + } +#endif + for (d = dirname + 1; *d; d++) { /* Ignore slash at start if any */ + if (*d == '/' && *(d - 1) != '/') { /* Ignore double-slashes */ + *d = '\0'; /* Temporarily truncate */ + if (out_maybe_mkdir(dirname) != 0) { + return NULL; + } + *d = '/'; /* Restore */ + } + } + outfile = fopen(filename, mode); + } + + return outfile; +} + /* vim: set ts=4 sw=4 et : */ diff --git a/backend/output.h b/backend/output.h index ca356ccf..1cf405c5 100644 --- a/backend/output.h +++ b/backend/output.h @@ -37,6 +37,8 @@ extern "C" { #endif /* __cplusplus */ +#include /* For FILE */ + INTERNAL int out_check_colour_options(struct zint_symbol *symbol); INTERNAL void out_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text, float *xoffset, float *yoffset, float *roffset, float *boffset, const float scaler, @@ -47,6 +49,7 @@ INTERNAL float out_large_bar_height(struct zint_symbol *symbol, int si, int *row INTERNAL void out_upcean_split_text(int upceanflag, unsigned char text[], unsigned char textpart1[5], unsigned char textpart2[7], unsigned char textpart3[7], unsigned char textpart4[2]); +INTERNAL FILE *out_fopen(const char filename[256], const char *mode); #ifdef __cplusplus } diff --git a/backend/pcx.c b/backend/pcx.c index 3d282b1a..e7b2c1e9 100644 --- a/backend/pcx.c +++ b/backend/pcx.c @@ -31,12 +31,14 @@ /* SPDX-License-Identifier: BSD-3-Clause */ #include +#include #include #ifdef _MSC_VER #include #include #endif #include "common.h" +#include "output.h" #include "pcx.h" /* PCX header structure */ /* ZSoft PCX File Format Technical Reference Manual http://bespin.org/~qz/pc-gpe/pcx.txt */ @@ -68,8 +70,8 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) header.window_ymin = 0; header.window_xmax = symbol->bitmap_width - 1; header.window_ymax = symbol->bitmap_height - 1; - header.horiz_dpi = 300; - header.vert_dpi = 300; + header.horiz_dpi = symbol->dpmm ? (uint16_t) roundf(stripf(symbol->dpmm * 25.4f)) : 300; + header.vert_dpi = header.horiz_dpi; for (i = 0; i < 48; i++) { header.colourmap[i] = 0x00; @@ -98,7 +100,7 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) #endif pcx_file = stdout; } else { - if (!(pcx_file = fopen(symbol->outfile, "wb"))) { + if (!(pcx_file = out_fopen(symbol->outfile, "wb"))) { sprintf(symbol->errtxt, "621: Could not open output file (%d: %.30s)", errno, strerror(errno)); return ZINT_ERROR_FILE_ACCESS; } diff --git a/backend/pdf417.c b/backend/pdf417.c index 13e52cde..15f05f84 100644 --- a/backend/pdf417.c +++ b/backend/pdf417.c @@ -1132,7 +1132,7 @@ static int pdf_initial_segs(struct zint_symbol *symbol, struct zint_seg segs[], if (symbol->structapp.id[0]) { int id_len; - for (id_len = 0; id_len < 32 && symbol->structapp.id[id_len]; id_len++); + for (id_len = 1; id_len < 31 && symbol->structapp.id[id_len]; id_len++); if (id_len > 30) { /* 10 triplets */ strcpy(symbol->errtxt, "742: Structured Append ID too long (30 digit maximum)"); diff --git a/backend/png.c b/backend/png.c index 799bb967..89d7687b 100644 --- a/backend/png.c +++ b/backend/png.c @@ -33,6 +33,7 @@ #ifndef ZINT_NO_PNG #include +#include #include #ifdef _MSC_VER #include @@ -42,6 +43,7 @@ #include #include #include "common.h" +#include "output.h" /* Note if change this need to change "backend/tests/test_png.c" definition also */ struct wpng_error_type { @@ -232,7 +234,7 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) #endif outfile = stdout; } else { - if (!(outfile = fopen(symbol->outfile, "wb"))) { + if (!(outfile = out_fopen(symbol->outfile, "wb"))) { sprintf(symbol->errtxt, "632: Could not open output file (%d: %.30s)", errno, strerror(errno)); return ZINT_ERROR_FILE_ACCESS; } @@ -279,6 +281,11 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) png_set_compression_strategy(png_ptr, compression_strategy); } + if (symbol->dpmm) { + int resolution = (int) roundf(stripf(symbol->dpmm * 1000.0f)); /* pixels per metre */ + png_set_pHYs(png_ptr, info_ptr, resolution, resolution, PNG_RESOLUTION_METER); + } + /* set Header block */ png_set_IHDR(png_ptr, info_ptr, symbol->bitmap_width, symbol->bitmap_height, bit_depth, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, diff --git a/backend/ps.c b/backend/ps.c index 2cf83e2f..de956259 100644 --- a/backend/ps.c +++ b/backend/ps.c @@ -35,6 +35,7 @@ #include #include #include "common.h" +#include "output.h" static void colour_to_pscolor(int option, int colour, char *output) { *output = '\0'; @@ -174,7 +175,7 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) { if (output_to_stdout) { feps = stdout; } else { - if (!(feps = fopen(symbol->outfile, "w"))) { + if (!(feps = out_fopen(symbol->outfile, "w"))) { sprintf(symbol->errtxt, "645: Could not open output file (%d: %.30s)", errno, strerror(errno)); return ZINT_ERROR_FILE_ACCESS; } diff --git a/backend/qr.c b/backend/qr.c index bf9e569c..e4525cbd 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -1620,9 +1620,9 @@ INTERNAL int qrcode(struct zint_symbol *symbol, struct zint_seg segs[], const in if (symbol->structapp.id[0]) { int id, id_len; - for (id_len = 0; id_len < 32 && symbol->structapp.id[id_len]; id_len++); + for (id_len = 1; id_len < 4 && symbol->structapp.id[id_len]; id_len++); - if (id_len > 3) { /* 255 */ + if (id_len > 3) { /* Max value 255 */ strcpy(symbol->errtxt, "752: Structured Append ID too long (3 digit maximum)"); return ZINT_ERROR_INVALID_OPTION; } diff --git a/backend/raster.c b/backend/raster.c index ac893a21..d56ecee7 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -688,7 +688,8 @@ static void draw_bind_box(const struct zint_symbol *symbol, unsigned char *pixel const int width_si = symbol->width * si; draw_bar(pixelbuf, xoffset_si, width_si, ybind_top, bwidth_si, image_width, image_height, DEFAULT_INK); if (!(symbol->output_options & BARCODE_BIND_TOP)) { /* Trumps BARCODE_BOX & BARCODE_BIND */ - draw_bar(pixelbuf, xoffset_si, width_si, ybind_bot, bwidth_si, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, xoffset_si, width_si, ybind_bot, bwidth_si, image_width, image_height, + DEFAULT_INK); } } if (symbol->output_options & BARCODE_BOX) { diff --git a/backend/svg.c b/backend/svg.c index 76c94d13..41171814 100644 --- a/backend/svg.c +++ b/backend/svg.c @@ -36,6 +36,7 @@ #include #include "common.h" +#include "output.h" static void pick_colour(int colour, char colour_code[]) { switch (colour) { @@ -183,7 +184,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) { if (symbol->output_options & BARCODE_STDOUT) { fsvg = stdout; } else { - if (!(fsvg = fopen(symbol->outfile, "w"))) { + if (!(fsvg = out_fopen(symbol->outfile, "w"))) { sprintf(symbol->errtxt, "680: Could not open output file (%d: %.30s)", errno, strerror(errno)); return ZINT_ERROR_FILE_ACCESS; } diff --git a/backend/tests/README b/backend/tests/README index 126a33bf..51f62812 100644 --- a/backend/tests/README +++ b/backend/tests/README @@ -62,21 +62,25 @@ To run a single dataset item in a single test function, use '-i ': backend/tests/test_dotcode -f input -i 2 -To run a range of dataset items in a single test function, use '-i ,': +To run a range of dataset items in a single test function, use '-i -': - backend/tests/test_dotcode -f input -i 2,5 + backend/tests/test_dotcode -f input -i 2-5 To exclude a single dataset item in a single test function, use '-x ': backend/tests/test_dotcode -f input -x 4 -This can also take a range, '-x ,': +This can also take a range, '-x -': backend/tests/test_dotcode -f input -x 4,6 +Exclude can be used multiple times (unlike '-i'): + + backend/tests/test_dotcode -f input -x 4 -x 6-8 + The include and exclude options can be used together: - backend/tests/test_dotcode -f input -i 2,7 -x 4 + backend/tests/test_dotcode -f input -i 2-7 -x 4 -x 6 To show debug info (if any), use '-d ': diff --git a/backend/tests/data/emf/code128_egrave_bold.emf b/backend/tests/data/emf/code128_egrave_bold.emf index d27b9309..b6eb3759 100644 Binary files a/backend/tests/data/emf/code128_egrave_bold.emf and b/backend/tests/data/emf/code128_egrave_bold.emf differ diff --git a/backend/tests/data/emf/code128_egrave_bold_100dpi.emf b/backend/tests/data/emf/code128_egrave_bold_100dpi.emf new file mode 100644 index 00000000..c52622db Binary files /dev/null and b/backend/tests/data/emf/code128_egrave_bold_100dpi.emf differ diff --git a/backend/tests/data/emf/code128_egrave_bold_1200dpi.emf b/backend/tests/data/emf/code128_egrave_bold_1200dpi.emf new file mode 100644 index 00000000..ce9a2e4c Binary files /dev/null and b/backend/tests/data/emf/code128_egrave_bold_1200dpi.emf differ diff --git a/backend/tests/data/emf/code128_egrave_bold_150dpi.emf b/backend/tests/data/emf/code128_egrave_bold_150dpi.emf new file mode 100644 index 00000000..a48f29bb Binary files /dev/null and b/backend/tests/data/emf/code128_egrave_bold_150dpi.emf differ diff --git a/backend/tests/data/emf/code128_egrave_bold_300dpi.emf b/backend/tests/data/emf/code128_egrave_bold_300dpi.emf new file mode 100644 index 00000000..52e1579e Binary files /dev/null and b/backend/tests/data/emf/code128_egrave_bold_300dpi.emf differ diff --git a/backend/tests/data/emf/code128_egrave_bold_400dpi.emf b/backend/tests/data/emf/code128_egrave_bold_400dpi.emf new file mode 100644 index 00000000..cf242c45 Binary files /dev/null and b/backend/tests/data/emf/code128_egrave_bold_400dpi.emf differ diff --git a/backend/tests/data/emf/code39_rotate_180.emf b/backend/tests/data/emf/code39_rotate_180.emf index ed0b8bae..8cf1dbb6 100644 Binary files a/backend/tests/data/emf/code39_rotate_180.emf and b/backend/tests/data/emf/code39_rotate_180.emf differ diff --git a/backend/tests/data/emf/code39_rotate_270.emf b/backend/tests/data/emf/code39_rotate_270.emf index 7e416a7e..1600f02f 100644 Binary files a/backend/tests/data/emf/code39_rotate_270.emf and b/backend/tests/data/emf/code39_rotate_270.emf differ diff --git a/backend/tests/data/emf/code39_rotate_90.emf b/backend/tests/data/emf/code39_rotate_90.emf index 6e3bcf03..c4edf199 100644 Binary files a/backend/tests/data/emf/code39_rotate_90.emf and b/backend/tests/data/emf/code39_rotate_90.emf differ diff --git a/backend/tests/data/emf/code39_rotate_90_300dpi.emf b/backend/tests/data/emf/code39_rotate_90_300dpi.emf new file mode 100644 index 00000000..2aaf8139 Binary files /dev/null and b/backend/tests/data/emf/code39_rotate_90_300dpi.emf differ diff --git a/backend/tests/data/emf/ean13_5addon_#185.emf b/backend/tests/data/emf/ean13_5addon_#185.emf index 27ad3a1c..74433a19 100644 Binary files a/backend/tests/data/emf/ean13_5addon_#185.emf and b/backend/tests/data/emf/ean13_5addon_#185.emf differ diff --git a/backend/tests/data/emf/ean13_5addon_ggs_5.2.2.5.2-2.emf b/backend/tests/data/emf/ean13_5addon_ggs_5.2.2.5.2-2.emf index ca4d94ae..dd1d681c 100644 Binary files a/backend/tests/data/emf/ean13_5addon_ggs_5.2.2.5.2-2.emf and b/backend/tests/data/emf/ean13_5addon_ggs_5.2.2.5.2-2.emf differ diff --git a/backend/tests/data/emf/itf14_bold.emf b/backend/tests/data/emf/itf14_bold.emf index 5bf28f86..a505b69e 100644 Binary files a/backend/tests/data/emf/itf14_bold.emf and b/backend/tests/data/emf/itf14_bold.emf differ diff --git a/backend/tests/data/emf/itf14_bold_600dpi.emf b/backend/tests/data/emf/itf14_bold_600dpi.emf new file mode 100644 index 00000000..fa9ce7ab Binary files /dev/null and b/backend/tests/data/emf/itf14_bold_600dpi.emf differ diff --git a/backend/tests/data/emf/maxicode_#185.emf b/backend/tests/data/emf/maxicode_#185.emf index 000f1254..cdf3165a 100644 Binary files a/backend/tests/data/emf/maxicode_#185.emf and b/backend/tests/data/emf/maxicode_#185.emf differ diff --git a/backend/tests/data/emf/maxicode_#185_150dpi.emf b/backend/tests/data/emf/maxicode_#185_150dpi.emf new file mode 100644 index 00000000..10b6d0c6 Binary files /dev/null and b/backend/tests/data/emf/maxicode_#185_150dpi.emf differ diff --git a/backend/tests/data/emf/maxicode_#185_600dpi.emf b/backend/tests/data/emf/maxicode_#185_600dpi.emf new file mode 100644 index 00000000..a5b330ff Binary files /dev/null and b/backend/tests/data/emf/maxicode_#185_600dpi.emf differ diff --git a/backend/tests/data/emf/maxicode_rotate_90_nobg.emf b/backend/tests/data/emf/maxicode_rotate_90_nobg.emf index b2ba16e9..24281c11 100644 Binary files a/backend/tests/data/emf/maxicode_rotate_90_nobg.emf and b/backend/tests/data/emf/maxicode_rotate_90_nobg.emf differ diff --git a/backend/tests/data/emf/maxicode_rotate_90_nobg_300dpi.emf b/backend/tests/data/emf/maxicode_rotate_90_nobg_300dpi.emf new file mode 100644 index 00000000..0638fa06 Binary files /dev/null and b/backend/tests/data/emf/maxicode_rotate_90_nobg_300dpi.emf differ diff --git a/backend/tests/data/emf/telenum_fg_bg.emf b/backend/tests/data/emf/telenum_fg_bg.emf index 10d2991b..d3b113cc 100644 Binary files a/backend/tests/data/emf/telenum_fg_bg.emf and b/backend/tests/data/emf/telenum_fg_bg.emf differ diff --git a/backend/tests/data/emf/telenum_fg_bg_150dpi.emf b/backend/tests/data/emf/telenum_fg_bg_150dpi.emf new file mode 100644 index 00000000..0ba548b8 Binary files /dev/null and b/backend/tests/data/emf/telenum_fg_bg_150dpi.emf differ diff --git a/backend/tests/data/emf/ultracode_fg_bg.emf b/backend/tests/data/emf/ultracode_fg_bg.emf index 8cf5d473..319e714c 100644 Binary files a/backend/tests/data/emf/ultracode_fg_bg.emf and b/backend/tests/data/emf/ultracode_fg_bg.emf differ diff --git a/backend/tests/data/emf/ultracode_fg_bg_box2.emf b/backend/tests/data/emf/ultracode_fg_bg_box2.emf index 807a675e..15aeb089 100644 Binary files a/backend/tests/data/emf/ultracode_fg_bg_box2.emf and b/backend/tests/data/emf/ultracode_fg_bg_box2.emf differ diff --git a/backend/tests/data/emf/ultracode_fg_bg_box2_600dpi.emf b/backend/tests/data/emf/ultracode_fg_bg_box2_600dpi.emf new file mode 100644 index 00000000..281097c9 Binary files /dev/null and b/backend/tests/data/emf/ultracode_fg_bg_box2_600dpi.emf differ diff --git a/backend/tests/data/emf/upca_2addon_ggs_5.2.6.6-5.emf b/backend/tests/data/emf/upca_2addon_ggs_5.2.6.6-5.emf index 9ba4b41b..d80b7940 100644 Binary files a/backend/tests/data/emf/upca_2addon_ggs_5.2.6.6-5.emf and b/backend/tests/data/emf/upca_2addon_ggs_5.2.6.6-5.emf differ diff --git a/backend/tests/data/emf/upce_2addon.emf b/backend/tests/data/emf/upce_2addon.emf index 23a1fd89..05069912 100644 Binary files a/backend/tests/data/emf/upce_2addon.emf and b/backend/tests/data/emf/upce_2addon.emf differ diff --git a/backend/tests/data/emf/upce_2addon_150dpi.emf b/backend/tests/data/emf/upce_2addon_150dpi.emf new file mode 100644 index 00000000..06382bc4 Binary files /dev/null and b/backend/tests/data/emf/upce_2addon_150dpi.emf differ diff --git a/backend/tests/data/emf/upce_2addon_small_bold.emf b/backend/tests/data/emf/upce_2addon_small_bold.emf index c1100b74..b25e5ef6 100644 Binary files a/backend/tests/data/emf/upce_2addon_small_bold.emf and b/backend/tests/data/emf/upce_2addon_small_bold.emf differ diff --git a/backend/tests/data/print/emf/code128_aim.emf b/backend/tests/data/print/emf/code128_aim.emf index 48060f3e..512d6db2 100644 Binary files a/backend/tests/data/print/emf/code128_aim.emf and b/backend/tests/data/print/emf/code128_aim.emf differ diff --git a/backend/tests/data/print/emf/dotcode_aim_fig7.emf b/backend/tests/data/print/emf/dotcode_aim_fig7.emf index 73c1d70e..a1fd307a 100644 Binary files a/backend/tests/data/print/emf/dotcode_aim_fig7.emf and b/backend/tests/data/print/emf/dotcode_aim_fig7.emf differ diff --git a/backend/tests/data/print/emf/maxicode_fig_2.emf b/backend/tests/data/print/emf/maxicode_fig_2.emf index 56405975..b9de887e 100644 Binary files a/backend/tests/data/print/emf/maxicode_fig_2.emf and b/backend/tests/data/print/emf/maxicode_fig_2.emf differ diff --git a/backend/tests/data/print/emf/qr_v1_m.emf b/backend/tests/data/print/emf/qr_v1_m.emf index 1fb8e5ec..daa46897 100644 Binary files a/backend/tests/data/print/emf/qr_v1_m.emf and b/backend/tests/data/print/emf/qr_v1_m.emf differ diff --git a/backend/tests/data/print/emf/ultracode_a.emf b/backend/tests/data/print/emf/ultracode_a.emf index 7d7c28c4..0493de8c 100644 Binary files a/backend/tests/data/print/emf/ultracode_a.emf and b/backend/tests/data/print/emf/ultracode_a.emf differ diff --git a/backend/tests/test_2of5.c b/backend/tests/test_2of5.c index ceb6bee5..c27eb99b 100644 --- a/backend/tests/test_2of5.c +++ b/backend/tests/test_2of5.c @@ -135,10 +135,10 @@ static void test_hrt(const testCtx *const p_ctx) { /* 15*/ { BARCODE_C25IND, -1, "123456789", "123456789" }, /* 16*/ { BARCODE_C25IND, 1, "123456789", "1234567895" }, /* 17*/ { BARCODE_C25IND, 2, "123456789", "123456789" }, - /* 18*/ { BARCODE_DPLEIT, -1, "123456789", "00001234567890" }, /* Leading zeroes added to make 13 + appended checksum */ - /* 19*/ { BARCODE_DPLEIT, -1, "1234567890123", "12345678901236" }, - /* 20*/ { BARCODE_DPIDENT, -1, "123456789", "001234567890" }, /* Leading zeroes added to make 11 + appended checksum */ - /* 21*/ { BARCODE_DPIDENT, -1, "12345678901", "123456789016" }, + /* 18*/ { BARCODE_DPLEIT, -1, "123456789", "00001.234.567.890" }, /* Leading zeroes added to make 13 + appended checksum */ + /* 19*/ { BARCODE_DPLEIT, -1, "1234567890123", "12345.678.901.236" }, + /* 20*/ { BARCODE_DPIDENT, -1, "123456789", "00.12 3.456.789 0" }, /* Leading zeroes added to make 11 + appended checksum */ + /* 21*/ { BARCODE_DPIDENT, -1, "12345678901", "12.34 5.678.901 6" }, /* 22*/ { BARCODE_ITF14, -1, "123456789", "00001234567895" }, /* Leading zeroes added to make 13 + appended checksum */ /* 23*/ { BARCODE_ITF14, -1, "1234567890123", "12345678901231" }, }; @@ -282,25 +282,31 @@ static void test_encode(const testCtx *const p_ctx) { /* 15*/ { BARCODE_DPLEIT, -1, "0000087654321", 0, 1, 135, "Deutsche Post Leitcode; verified manually against tec-it", "101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101" }, - /* 16*/ { BARCODE_DPLEIT, -1, "5082300702800", 0, 1, 135, "Deutsche Post Leitcode https://de.wikipedia.org/wiki/Leitcode example", + /* 16*/ { BARCODE_DPLEIT, -1, "2045703000360", 0, 1, 135, "Deutsche Post DIALOGPOST SCHWER brochure 3.1 example", + "101010111010001000111010001011100010111010101000111000111011101110100010001010101110001110001011101110001000101010001011100011101011101" + }, + /* 17*/ { BARCODE_DPLEIT, -1, "5082300702800", 0, 1, 135, "Deutsche Post Leitcode https://de.wikipedia.org/wiki/Leitcode example", "101011101011100010001011101000101110100011101110100010001010101110111000100010100011101110100011101010001110001010001011100011101011101" }, - /* 17*/ { BARCODE_DPIDENT, -1, "00087654321", 0, 1, 117, "Deutsche Post Identcode; verified manually against tec-it", + /* 18*/ { BARCODE_DPIDENT, -1, "00087654321", 0, 1, 117, "Deutsche Post Identcode; verified manually against tec-it (HRT differently formatted)", "101010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101" }, - /* 18*/ { BARCODE_DPIDENT, -1, "39601313414", 0, 1, 117, "Deutsche Post Identcode https://de.wikipedia.org/wiki/Leitcode example", + /* 19*/ { BARCODE_DPIDENT, -1, "80420000001", 0, 1, 117, "Deutsche Post DIALOGPOST SCHWER brochure 3.1 example", + "101011101010001110001010100011101011100010101110001110001010101110001110001010101110001110001011101010001000111011101" + }, + /* 20*/ { BARCODE_DPIDENT, -1, "39601313414", 0, 1, 117, "Deutsche Post Identcode https://de.wikipedia.org/wiki/Leitcode example", "101011101110001010001010111011100010001011100010001010111011100010001010111010001011101011100010101110001000111011101" }, - /* 19*/ { BARCODE_ITF14, -1, "0000087654321", 0, 1, 135, "ITF-14; verified manually against tec-it", + /* 21*/ { BARCODE_ITF14, -1, "0000087654321", 0, 1, 135, "ITF-14; verified manually against tec-it", "101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101" }, - /* 20*/ { BARCODE_ITF14, -1, "0950110153000", 0, 1, 135, "GS1 General Specifications Figure 5.1-2", + /* 22*/ { BARCODE_ITF14, -1, "0950110153000", 0, 1, 135, "GS1 General Specifications Figure 5.1-2", "101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001010001000111011101011101" }, - /* 21*/ { BARCODE_ITF14, -1, "1540014128876", 0, 1, 135, "GS1 General Specifications Figure 5.3.2.4-1", + /* 23*/ { BARCODE_ITF14, -1, "1540014128876", 0, 1, 135, "GS1 General Specifications Figure 5.3.2.4-1", "101011100010100010111010101110001000111010001011101110100010001011101011100010001110101000111011101010111000100010001110001110101011101" }, - /* 22*/ { BARCODE_ITF14, -1, "0950110153001", 0, 1, 135, "GS1 General Specifications Figure 5.3.6-1", + /* 24*/ { BARCODE_ITF14, -1, "0950110153001", 0, 1, 135, "GS1 General Specifications Figure 5.3.6-1", "101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001011101010001000111011101" }, }; diff --git a/backend/tests/test_bmp.c b/backend/tests/test_bmp.c index 50dd85b7..6cd6fd43 100644 --- a/backend/tests/test_bmp.c +++ b/backend/tests/test_bmp.c @@ -65,7 +65,7 @@ static void test_pixel_plot(const testCtx *const p_ctx) { char data_buf[8 * 2 + 1]; - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_pixel_plot"); @@ -104,7 +104,7 @@ static void test_pixel_plot(const testCtx *const p_ctx) { if (ret < ZINT_ERROR) { if (have_identify) { - ret = testUtilVerifyIdentify(symbol->outfile, debug); + ret = testUtilVerifyIdentify(have_identify, symbol->outfile, debug); assert_zero(ret, "i:%d identify %s ret %d != 0\n", i, symbol->outfile, ret); } if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) { @@ -156,7 +156,7 @@ static void test_print(const testCtx *const p_ctx) { char escaped[1024]; int escaped_size = 1024; - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_print"); @@ -211,7 +211,7 @@ static void test_print(const testCtx *const p_ctx) { ret = testUtilRename(symbol->outfile, expected_file); assert_zero(ret, "i:%d testUtilRename(%s, %s) ret %d != 0 (%d: %s)\n", i, symbol->outfile, expected_file, ret, errno, strerror(errno)); if (have_identify) { - ret = testUtilVerifyIdentify(expected_file, debug); + ret = testUtilVerifyIdentify(have_identify, expected_file, debug); assert_zero(ret, "i:%d %s identify %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), expected_file, ret); } } else { @@ -242,10 +242,13 @@ static void test_outfile(const testCtx *const p_ctx) { symbol.bitmap = data; symbol.bitmap_width = symbol.bitmap_height = 1; - strcpy(symbol.outfile, "nosuch_dir/out.bmp"); + strcpy(symbol.outfile, "test_bmp_out.bmp"); + (void) testUtilRmROFile(symbol.outfile); /* In case lying around from previous fail */ + assert_nonzero(testUtilCreateROFile(symbol.outfile), "bmp_pixel_plot testUtilCreateROFile(%s) fail (%d: %s)\n", symbol.outfile, errno, strerror(errno)); ret = bmp_pixel_plot(&symbol, data); assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "bmp_pixel_plot ret %d != ZINT_ERROR_FILE_ACCESS (%d) (%s)\n", ret, ZINT_ERROR_FILE_ACCESS, symbol.errtxt); + assert_zero(testUtilRmROFile(symbol.outfile), "bmp_pixel_plot testUtilRmROFile(%s) != 0 (%d: %s)\n", symbol.outfile, errno, strerror(errno)); symbol.output_options |= BARCODE_STDOUT; diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c index b3675a69..b1809fca 100644 --- a/backend/tests/test_code128.c +++ b/backend/tests/test_code128.c @@ -55,10 +55,10 @@ static void test_large(const testCtx *const p_ctx) { /* 4*/ { BARCODE_CODE128, "\351A", 41, ZINT_ERROR_TOO_LONG, -1 }, /* 41 chars (+ 20 shifts) */ /* 5*/ { BARCODE_CODE128, "0", 120, 0, 695 }, /* 6*/ { BARCODE_CODE128, "0", 121, ZINT_ERROR_TOO_LONG, -1 }, - /* 7*/ { BARCODE_CODE128B, "A", 60, 0, 695 }, - /* 8*/ { BARCODE_CODE128B, "A", 61, ZINT_ERROR_TOO_LONG, -1 }, - /* 9*/ { BARCODE_CODE128B, "0", 60, 0, 695 }, - /* 10*/ { BARCODE_CODE128B, "0", 61, ZINT_ERROR_TOO_LONG, -1 }, + /* 7*/ { BARCODE_CODE128AB, "A", 60, 0, 695 }, + /* 8*/ { BARCODE_CODE128AB, "A", 61, ZINT_ERROR_TOO_LONG, -1 }, + /* 9*/ { BARCODE_CODE128AB, "0", 60, 0, 695 }, + /* 10*/ { BARCODE_CODE128AB, "0", 61, ZINT_ERROR_TOO_LONG, -1 }, /* 11*/ { BARCODE_GS1_128, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]1234567890", -1, 0, 706 }, /* 116 nos + 3 FNC1s */ /* 12*/ { BARCODE_GS1_128, "[90]123456789012345678901234567890[91]1234567890123456789012345678901234567890123456789012345678901234567890[92]1234[93]1234", -1, ZINT_ERROR_TOO_LONG, -1 }, /* 116 nos + 4 FNC1s */ /* 13*/ { BARCODE_GS1_128, "A", 161, ZINT_ERROR_TOO_LONG, -1 }, @@ -198,13 +198,13 @@ static void test_hrt(const testCtx *const p_ctx) { struct item data[] = { /* 0*/ { BARCODE_CODE128, UNICODE_MODE, -1, "1234567890", -1, "1234567890" }, /* 1*/ { BARCODE_CODE128, UNICODE_MODE, -1, "\000ABC\000DEF\000", 9, " ABC DEF " }, - /* 2*/ { BARCODE_CODE128B, UNICODE_MODE, -1, "12345\00067890", 11, "12345 67890" }, + /* 2*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, "12345\00067890", 11, "12345 67890" }, /* 3*/ { BARCODE_CODE128, UNICODE_MODE, -1, "12345\01167890\037\177", -1, "12345 67890 " }, /* 4*/ { BARCODE_CODE128, UNICODE_MODE, -1, "abcdé", -1, "abcdé" }, /* 5*/ { BARCODE_CODE128, DATA_MODE, -1, "abcd\351", -1, "abcdé" }, /* 6*/ { BARCODE_CODE128, DATA_MODE, -1, "ab\240cd\351", -1, "ab\302\240cdé" }, /* NBSP */ - /* 7*/ { BARCODE_CODE128B, UNICODE_MODE, -1, "abcdé", -1, "abcdé" }, - /* 8*/ { BARCODE_CODE128B, DATA_MODE, -1, "abcd\351", -1, "abcdé" }, + /* 7*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, "abcdé", -1, "abcdé" }, + /* 8*/ { BARCODE_CODE128AB, DATA_MODE, -1, "abcd\351", -1, "abcdé" }, /* 9*/ { BARCODE_HIBC_128, UNICODE_MODE, -1, "1234567890", -1, "*+12345678900*" }, /* 10*/ { BARCODE_HIBC_128, UNICODE_MODE, -1, "a99912345", -1, "*+A999123457*" }, /* Converts to upper */ /* 11*/ { BARCODE_DPD, UNICODE_MODE, -1, "000393206219912345678101040", -1, "0003 932 0621 9912 3456 78 101 040 9" }, /* DPDAPPD 4.0.2 - Illustration 7 */ @@ -281,7 +281,7 @@ static void test_reader_init(const testCtx *const p_ctx) { struct item data[] = { /* 0*/ { BARCODE_CODE128, UNICODE_MODE, READER_INIT, "A", 0, 1, 57, "(5) 104 96 33 60 106", "StartA FNC3 A" }, /* 1*/ { BARCODE_CODE128, UNICODE_MODE, READER_INIT, "12", 0, 1, 68, "(6) 104 96 99 12 22 106", "StartB FNC3 CodeC 12" }, - /* 2*/ { BARCODE_CODE128B, UNICODE_MODE, READER_INIT, "\0371234", 0, 1, 101, "(9) 103 96 95 17 18 19 20 6 106", "StartA FNC3 US 1 2 3 4" }, + /* 2*/ { BARCODE_CODE128AB, UNICODE_MODE, READER_INIT, "\0371234", 0, 1, 101, "(9) 103 96 95 17 18 19 20 6 106", "StartA FNC3 US 1 2 3 4" }, /* 3*/ { BARCODE_GS1_128, GS1_MODE, READER_INIT, "[90]12", 0, 1, 68, "(6) 105 102 90 12 11 106", "StartC FNC1 90 12 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, /* 4*/ { BARCODE_EAN14, GS1_MODE, READER_INIT, "12", 0, 1, 134, "(12) 105 102 1 0 0 0 0 0 1 23 12 106", "StartC FNC1 01 00 (5) 01 23 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, /* 5*/ { BARCODE_NVE18, GS1_MODE, READER_INIT, "12", 0, 1, 156, "(14) 105 102 0 0 0 0 0 0 0 0 1 23 58 106", "StartC FNC1 00 (8) 01 23 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, @@ -766,13 +766,13 @@ static void test_encode(const testCtx *const p_ctx) { /* 0*/ { BARCODE_CODE128, UNICODE_MODE, -1, "AIM", 0, 1, 68, 1, "ISO/IEC 15417:2007 Figure 1", "11010010000101000110001100010001010111011000101110110001100011101011" }, - /* 1*/ { BARCODE_CODE128B, UNICODE_MODE, -1, "AIM", 0, 1, 68, 1, "128B same", + /* 1*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, "AIM", 0, 1, 68, 1, "128B same", "11010010000101000110001100010001010111011000101110110001100011101011" }, /* 2*/ { BARCODE_CODE128, UNICODE_MODE, -1, "1234567890", 0, 1, 90, 1, "", "110100111001011001110010001011000111000101101100001010011011110110100111100101100011101011" }, - /* 3*/ { BARCODE_CODE128B, UNICODE_MODE, -1, "1234567890", 0, 1, 145, 1, "", + /* 3*/ { BARCODE_CODE128AB, UNICODE_MODE, -1, "1234567890", 0, 1, 145, 1, "", "1101001000010011100110110011100101100101110011001001110110111001001100111010011101101110111010011001110010110010011101100101000110001100011101011" }, /* 4*/ { BARCODE_CODE128, DATA_MODE, -1, "\101\102\103\104\105\106\200\200\200\200\200", 0, 1, 178, 1, "", diff --git a/backend/tests/test_eci.c b/backend/tests/test_eci.c index f7b6ae17..213bafbd 100644 --- a/backend/tests/test_eci.c +++ b/backend/tests/test_eci.c @@ -266,9 +266,9 @@ static void test_reduced_charset_input(const testCtx *const p_ctx) { /*121*/ { BARCODE_MAXICODE, UNICODE_MODE, 29, "齄齄", 0, 29, "U+9F44 in GB2312 but not in Big5" }, /*122*/ { BARCODE_MAXICODE, UNICODE_MODE, 30, "가", 0, 30, "U+AC00 in EUC-KR" }, /*123*/ { BARCODE_MAXICODE, UNICODE_MODE, 30, "가가", 0, 30, "U+AC00 in EUC-KR" }, - /*124*/ { BARCODE_CODE128B, UNICODE_MODE, 0, "é", 0, 0, "" }, - /*125*/ { BARCODE_CODE128B, UNICODE_MODE, 3, "é", ZINT_ERROR_INVALID_OPTION, -1, "Does not support ECI" }, - /*126*/ { BARCODE_CODE128B, UNICODE_MODE, 0, "β", ZINT_ERROR_INVALID_DATA, -1, "β not in ISO 8859-1" }, + /*124*/ { BARCODE_CODE128AB, UNICODE_MODE, 0, "é", 0, 0, "" }, + /*125*/ { BARCODE_CODE128AB, UNICODE_MODE, 3, "é", ZINT_ERROR_INVALID_OPTION, -1, "Does not support ECI" }, + /*126*/ { BARCODE_CODE128AB, UNICODE_MODE, 0, "β", ZINT_ERROR_INVALID_DATA, -1, "β not in ISO 8859-1" }, /*127*/ { BARCODE_DATAMATRIX, UNICODE_MODE, 0, "é", 0, 0, "" }, /*128*/ { BARCODE_DATAMATRIX, UNICODE_MODE, 3, "é", 0, 3, "Supports ECI" }, /*129*/ { BARCODE_DATAMATRIX, UNICODE_MODE, 0, "β", ZINT_WARN_USES_ECI, 9, "" }, diff --git a/backend/tests/test_emf.c b/backend/tests/test_emf.c index abc5e2e8..be931d74 100644 --- a/backend/tests/test_emf.c +++ b/backend/tests/test_emf.c @@ -44,6 +44,7 @@ static void test_print(const testCtx *const p_ctx) { int whitespace_height; int option_1; int option_2; + float dpmm; char *fgcolour; char *bgcolour; int rotate_angle; @@ -52,21 +53,34 @@ static void test_print(const testCtx *const p_ctx) { char *comment; }; struct item data[] = { - /* 0*/ { BARCODE_CODE128, UNICODE_MODE, -1, BOLD_TEXT, -1, -1, -1, -1, "", "", 0, "Égjpqy", "code128_egrave_bold.emf", "" }, - /* 1*/ { BARCODE_TELEPEN, -1, -1, -1, -1, -1, -1, -1, "147AD0", "FC9630", 0, "123", "telenum_fg_bg.emf", "" }, - /* 2*/ { BARCODE_ULTRA, -1, -1, -1, 5, -1, -1, -1, "147AD0", "FC9630", 0, "123", "ultracode_fg_bg.emf", "" }, - /* 3*/ { BARCODE_ULTRA, -1, 2, BARCODE_BOX, 2, 2, -1, -1, "FF0000", "0000FF", 0, "123", "ultracode_fg_bg_box2.emf", "" }, - /* 4*/ { BARCODE_EANX, -1, -1, -1, -1, -1, -1, -1, "", "", 0, "9780877799306+54321", "ean13_5addon_ggs_5.2.2.5.2-2.emf", "" }, - /* 5*/ { BARCODE_EANX, -1, -1, -1, -1, -1, -1, -1, "", "", 0, "210987654321+54321", "ean13_5addon_#185.emf", "#185 Byte count, font data, HeaderExtension1/2" }, - /* 6*/ { BARCODE_UPCA, -1, -1, -1, -1, -1, -1, -1, "", "", 0, "012345678905+24", "upca_2addon_ggs_5.2.6.6-5.emf", "" }, - /* 7*/ { BARCODE_UPCE, -1, -1, -1, -1, -1, -1, -1, "", "", 0, "0123456+12", "upce_2addon.emf", "" }, - /* 8*/ { BARCODE_UPCE, -1, -1, SMALL_TEXT | BOLD_TEXT, -1, -1, -1, -1, "", "", 0, "0123456+12", "upce_2addon_small_bold.emf", "" }, - /* 9*/ { BARCODE_ITF14, -1, -1, BOLD_TEXT, -1, -1, -1, -1, "", "", 0, "123", "itf14_bold.emf", "" }, - /* 10*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, -1, -1, "", "", 90, "123", "code39_rotate_90.emf", "" }, - /* 11*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, -1, -1, "", "", 180, "123", "code39_rotate_180.emf", "" }, - /* 12*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, -1, -1, "", "", 270, "123", "code39_rotate_270.emf", "" }, - /* 13*/ { BARCODE_MAXICODE, -1, -1, -1, -1, -1, -1, -1, "E0E0E0", "700070", 0, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", "maxicode_#185.emf", "#185 Maxicode scaling" }, - /* 14*/ { BARCODE_MAXICODE, -1, -1, -1, -1, -1, -1, -1, "", "FFFFFF00", 90, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", "maxicode_rotate_90_nobg.emf", "" }, + /* 0*/ { BARCODE_CODE128, UNICODE_MODE, -1, BOLD_TEXT, -1, -1, -1, -1, 0, "", "", 0, "Égjpqy", "code128_egrave_bold.emf", "" }, + /* 1*/ { BARCODE_CODE128, UNICODE_MODE, -1, BOLD_TEXT, -1, -1, -1, -1, 100.0f / 25.4f, "", "", 0, "Égjpqy", "code128_egrave_bold_100dpi.emf", "" }, + /* 2*/ { BARCODE_CODE128, UNICODE_MODE, -1, BOLD_TEXT, -1, -1, -1, -1, 150.0f / 25.4f, "", "", 0, "Égjpqy", "code128_egrave_bold_150dpi.emf", "" }, + /* 3*/ { BARCODE_CODE128, UNICODE_MODE, -1, BOLD_TEXT, -1, -1, -1, -1, 300.0f / 25.4f, "", "", 0, "Égjpqy", "code128_egrave_bold_300dpi.emf", "" }, + /* 4*/ { BARCODE_CODE128, UNICODE_MODE, -1, BOLD_TEXT, -1, -1, -1, -1, 400.0f / 25.4f, "", "", 0, "Égjpqy", "code128_egrave_bold_400dpi.emf", "" }, + /* 5*/ { BARCODE_CODE128, UNICODE_MODE, -1, BOLD_TEXT, -1, -1, -1, -1, 1200.0f / 25.4f, "", "", 0, "Égjpqy", "code128_egrave_bold_1200dpi.emf", "" }, + /* 6*/ { BARCODE_TELEPEN, -1, -1, -1, -1, -1, -1, -1, 0, "147AD0", "FC9630", 0, "123", "telenum_fg_bg.emf", "" }, + /* 7*/ { BARCODE_TELEPEN, -1, -1, -1, -1, -1, -1, -1, 150.0f / 25.4f, "147AD0", "FC9630", 0, "123", "telenum_fg_bg_150dpi.emf", "" }, + /* 8*/ { BARCODE_ULTRA, -1, -1, -1, 5, -1, -1, -1, 0, "147AD0", "FC9630", 0, "123", "ultracode_fg_bg.emf", "" }, + /* 9*/ { BARCODE_ULTRA, -1, 2, BARCODE_BOX, 2, 2, -1, -1, 0, "FF0000", "0000FF", 0, "123", "ultracode_fg_bg_box2.emf", "" }, + /* 10*/ { BARCODE_ULTRA, -1, 2, BARCODE_BOX, 2, 2, -1, -1, 600.0f / 25.4f, "FF0000", "0000FF", 0, "123", "ultracode_fg_bg_box2_600dpi.emf", "" }, + /* 11*/ { BARCODE_EANX, -1, -1, -1, -1, -1, -1, -1, 0, "", "", 0, "9780877799306+54321", "ean13_5addon_ggs_5.2.2.5.2-2.emf", "" }, + /* 12*/ { BARCODE_EANX, -1, -1, -1, -1, -1, -1, -1, 0, "", "", 0, "210987654321+54321", "ean13_5addon_#185.emf", "#185 Byte count, font data, HeaderExtension1/2" }, + /* 13*/ { BARCODE_UPCA, -1, -1, -1, -1, -1, -1, -1, 0, "", "", 0, "012345678905+24", "upca_2addon_ggs_5.2.6.6-5.emf", "" }, + /* 14*/ { BARCODE_UPCE, -1, -1, -1, -1, -1, -1, -1, 0, "", "", 0, "0123456+12", "upce_2addon.emf", "" }, + /* 15*/ { BARCODE_UPCE, -1, -1, -1, -1, -1, -1, -1, 150.f / 25.4f, "", "", 0, "0123456+12", "upce_2addon_150dpi.emf", "" }, + /* 16*/ { BARCODE_UPCE, -1, -1, SMALL_TEXT | BOLD_TEXT, -1, -1, -1, -1, 0, "", "", 0, "0123456+12", "upce_2addon_small_bold.emf", "" }, + /* 17*/ { BARCODE_ITF14, -1, -1, BOLD_TEXT, -1, -1, -1, -1, 0, "", "", 0, "123", "itf14_bold.emf", "" }, + /* 18*/ { BARCODE_ITF14, -1, -1, BOLD_TEXT, -1, -1, -1, -1, 600.f / 25.4f, "", "", 0, "123", "itf14_bold_600dpi.emf", "" }, + /* 19*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, -1, -1, 0, "", "", 90, "123", "code39_rotate_90.emf", "" }, + /* 20*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, -1, -1, 300.f / 25.4f, "", "", 90, "123", "code39_rotate_90_300dpi.emf", "" }, + /* 21*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, -1, -1, 0, "", "", 180, "123", "code39_rotate_180.emf", "" }, + /* 22*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, -1, -1, 0, "", "", 270, "123", "code39_rotate_270.emf", "" }, + /* 23*/ { BARCODE_MAXICODE, -1, -1, -1, -1, -1, -1, -1, 0, "E0E0E0", "700070", 0, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", "maxicode_#185.emf", "#185 Maxicode scaling" }, + /* 24*/ { BARCODE_MAXICODE, -1, -1, -1, -1, -1, -1, -1, 150.f / 25.4f, "E0E0E0", "700070", 0, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", "maxicode_#185_150dpi.emf", "#185 Maxicode scaling" }, + /* 25*/ { BARCODE_MAXICODE, -1, -1, -1, -1, -1, -1, -1, 600.f / 25.4f, "E0E0E0", "700070", 0, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", "maxicode_#185_600dpi.emf", "#185 Maxicode scaling" }, + /* 26*/ { BARCODE_MAXICODE, -1, -1, -1, -1, -1, -1, -1, 0, "", "FFFFFF00", 90, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", "maxicode_rotate_90_nobg.emf", "" }, + /* 27*/ { BARCODE_MAXICODE, -1, -1, -1, -1, -1, -1, -1, 300.0f, "", "FFFFFF00", 90, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", "maxicode_rotate_90_nobg_300dpi.emf", "" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -111,6 +125,10 @@ static void test_print(const testCtx *const p_ctx) { if (data[i].whitespace_height != -1) { symbol->whitespace_height = data[i].whitespace_height; } + if (data[i].dpmm) { + symbol->dpmm = data[i].dpmm; + symbol->scale = ZBarcode_Scale_From_XdimDp(symbol->symbology, ZBarcode_Default_Xdim(symbol->symbology), symbol->dpmm, "EMF"); + } if (*data[i].fgcolour) { strcpy(symbol->fgcolour, data[i].fgcolour); } @@ -128,10 +146,10 @@ static void test_print(const testCtx *const p_ctx) { assert_nonzero(testUtilDataPath(expected_file, sizeof(expected_file), data_dir, data[i].expected_file), "i:%d testUtilDataPath == 0\n", i); if (p_ctx->generate) { - printf(" /*%3d*/ { %s, %s, %d, %s, %d, %d, %d, %d, \"%s\", \"%s\", %d, \"%s\", \"%s\", \"%s\" },\n", + printf(" /*%3d*/ { %s, %s, %d, %s, %d, %d, %d, %d, %g, \"%s\", \"%s\", %d, \"%s\", \"%s\", \"%s\" },\n", i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].border_width, testUtilOutputOptionsName(data[i].output_options), data[i].whitespace_width, data[i].whitespace_height, - data[i].option_1, data[i].option_2, data[i].fgcolour, data[i].bgcolour, data[i].rotate_angle, + data[i].option_1, data[i].option_2, data[i].dpmm, data[i].fgcolour, data[i].bgcolour, data[i].rotate_angle, testUtilEscape(data[i].data, length, escaped, escaped_size), data[i].expected_file, data[i].comment); ret = testUtilRename(symbol->outfile, expected_file); assert_zero(ret, "i:%d testUtilRename(%s, %s) ret %d != 0\n", i, symbol->outfile, expected_file, ret); @@ -170,10 +188,13 @@ static void test_outfile(const testCtx *const p_ctx) { symbol.symbology = BARCODE_CODE128; symbol.vector = &vector; - strcpy(symbol.outfile, "nosuch_dir/out.emf"); + strcpy(symbol.outfile, "test_emf_out.emf"); + (void) testUtilRmROFile(symbol.outfile); /* In case lying around from previous fail */ + assert_nonzero(testUtilCreateROFile(symbol.outfile), "emf_plot testUtilCreateROFile(%s) fail (%d: %s)\n", symbol.outfile, errno, strerror(errno)); ret = emf_plot(&symbol, 0); assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "emf_plot ret %d != ZINT_ERROR_FILE_ACCESS (%d) (%s)\n", ret, ZINT_ERROR_FILE_ACCESS, symbol.errtxt); + assert_zero(testUtilRmROFile(symbol.outfile), "emf_plot testUtilRmROFile(%s) != 0 (%d: %s)\n", symbol.outfile, errno, strerror(errno)); symbol.output_options |= BARCODE_STDOUT; diff --git a/backend/tests/test_gif.c b/backend/tests/test_gif.c index 9acfe03f..e990f9f1 100644 --- a/backend/tests/test_gif.c +++ b/backend/tests/test_gif.c @@ -65,7 +65,7 @@ static void test_pixel_plot(const testCtx *const p_ctx) { char data_buf[19 * 32 + 1]; /* 19 * 32 == 608 */ - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_pixel_plot"); @@ -100,7 +100,7 @@ static void test_pixel_plot(const testCtx *const p_ctx) { if (ret < ZINT_ERROR) { if (have_identify) { - ret = testUtilVerifyIdentify(symbol->outfile, debug); + ret = testUtilVerifyIdentify(have_identify, symbol->outfile, debug); assert_zero(ret, "i:%d identify %s ret %d != 0\n", i, symbol->outfile, ret); } if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) { @@ -184,7 +184,7 @@ static void test_print(const testCtx *const p_ctx) { char escaped[1024]; int escaped_size = 1024; - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_print"); @@ -251,7 +251,7 @@ static void test_print(const testCtx *const p_ctx) { ret = testUtilRename(symbol->outfile, expected_file); assert_zero(ret, "i:%d testUtilRename(%s, %s) ret %d != 0\n", i, symbol->outfile, expected_file, ret); if (have_identify) { - ret = testUtilVerifyIdentify(expected_file, debug); + ret = testUtilVerifyIdentify(have_identify, expected_file, debug); assert_zero(ret, "i:%d %s identify %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), expected_file, ret); } } else { @@ -282,10 +282,13 @@ static void test_outfile(const testCtx *const p_ctx) { symbol.bitmap = data; symbol.bitmap_width = symbol.bitmap_height = 1; - strcpy(symbol.outfile, "nosuch_dir/out.gif"); + strcpy(symbol.outfile, "test_gif_out.gif"); + (void) testUtilRmROFile(symbol.outfile); /* In case lying around from previous fail */ + assert_nonzero(testUtilCreateROFile(symbol.outfile), "gif_pixel_plot testUtilCreateROFile(%s) fail (%d: %s)\n", symbol.outfile, errno, strerror(errno)); ret = gif_pixel_plot(&symbol, data); assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "gif_pixel_plot ret %d != ZINT_ERROR_FILE_ACCESS (%d) (%s)\n", ret, ZINT_ERROR_FILE_ACCESS, symbol.errtxt); + assert_zero(testUtilRmROFile(symbol.outfile), "gif_pixel_plot testUtilRmROFile(%s) != 0 (%d: %s)\n", symbol.outfile, errno, strerror(errno)); symbol.output_options |= BARCODE_STDOUT; diff --git a/backend/tests/test_library.c b/backend/tests/test_library.c index f8af4869..a0eb9bb6 100644 --- a/backend/tests/test_library.c +++ b/backend/tests/test_library.c @@ -29,10 +29,12 @@ */ /* SPDX-License-Identifier: BSD-3-Clause */ -#include "testcommon.h" -#include -#include #include +#include +#include +#include +#include "testcommon.h" +#include "../common.h" static void test_checks(const testCtx *const p_ctx) { int debug = p_ctx->debug; @@ -63,8 +65,8 @@ static void test_checks(const testCtx *const p_ctx) { /* 1*/ { BARCODE_CODE128, -1, "1234", -1, -1, 0, 0, 0, 0, 0, -1, -1, -1, -1, 0, "", -1 }, /* 2*/ { BARCODE_QRCODE, -1, "1234", -1, -1, 3, 0, 0, 0, 0, -1, -1, -1, -1, 0, "", -1 }, /* 3*/ { BARCODE_QRCODE, -1, "1234", -1, -1, 999999 + 1, 0, 0, 0, 0, -1, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 218: Invalid ECI code 1000000", -1 }, - /* 4*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, 0.009, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 227: Scale out of range (0.01 to 100)", -1 }, - /* 5*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, 100.01, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 227: Scale out of range (0.01 to 100)", -1 }, + /* 4*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, 0.009, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 227: Scale out of range (0.01 to 200)", -1 }, + /* 5*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, 200.01, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 227: Scale out of range (0.01 to 200)", -1 }, /* 6*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, -1, 20.1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Dot size out of range (0.01 to 20)", -1 }, /* 7*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, 0.01, 0.009, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Dot size out of range (0.01 to 20)", -1 }, /* 8*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, -0.1, 0, 0, 0, -1, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 765: Height out of range (0 to 2000)", -1 }, @@ -1381,6 +1383,204 @@ static void test_clear(const testCtx *const p_ctx) { testFinish(); } +static void test_scale_from_xdimdp(const testCtx *const p_ctx) { + + struct item { + int symbology; + float x_dim; + float dpmm; + int dpi; + char *filetype; + float expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + struct item data[] = { + /* 0*/ { BARCODE_EANX, 0.33f, 2, 50, "gif", 0.5f }, + /* 1*/ { BARCODE_EANX, 0.33f, 2, 50, "emf", 0.33000001f }, + /* 2*/ { BARCODE_EANX, 0.33f, 2, 50, "svg", 0.33000001f }, + /* 3*/ { BARCODE_EANX, 0.33f, 3, 76, "gif", 0.5f }, + /* 4*/ { BARCODE_EANX, 0.33f, 3, 76, "svg", 0.495f }, + /* 5*/ { BARCODE_EANX, 0.33f, 4, 100, "gif", 0.5f }, + /* 6*/ { BARCODE_EANX, 0.33f, 4, 100, "svg", 0.66000003f }, + /* 7*/ { BARCODE_EANX, 0.33f, 6, 150, "gif", 1 }, + /* 8*/ { BARCODE_EANX, 0.33f, 6, 150, "svg", 0.99f }, + /* 9*/ { BARCODE_EANX, 0.33f, 8, 200, "gif", 1.5f }, + /* 10*/ { BARCODE_EANX, 0.33f, 8, 200, "svg", 1.32f }, + /* 11*/ { BARCODE_EANX, 0.33f, 12, 300, "gif", 2 }, + /* 12*/ { BARCODE_EANX, 0.33f, 12, 300, "svg", 1.98f }, + /* 13*/ { BARCODE_EANX, 0.33f, 16, 400, "gif", 2.5f }, /* NOTE: scale previously documented as 3.0f */ + /* 14*/ { BARCODE_EANX, 0.33f, 16, 400, "svg", 2.64f }, + /* 15*/ { BARCODE_EANX, 0.33f, 24, 600, "gif", 4 }, + /* 16*/ { BARCODE_EANX, 0.33f, 24, 600, "svg", 3.96f }, + /* 17*/ { BARCODE_EANX, 0.33f, 47, 1200, "gif", 8 }, + /* 18*/ { BARCODE_EANX, 0.33f, 47, 1200, "emf", 7.755f }, + /* 19*/ { BARCODE_EANX, 0.33f, 47, 1200, "svg", 7.755f }, + /* 20*/ { BARCODE_EANX, 0.33f, 94, 2400, "gif", 15.5f }, /* NOTE dpmm previously documented as 95 */ + /* 21*/ { BARCODE_EANX, 0.33f, 94, 2400, "svg", 15.51f }, + /* 22*/ { BARCODE_EANX, 0.33f, 189, 4800, "gif", 31 }, + /* 23*/ { BARCODE_EANX, 0.33f, 189, 4800, "svg", 31.185001f }, + /* 24*/ { BARCODE_EANX, 0.33f, 378, 9600, "gif", 62.5f }, + /* 25*/ { BARCODE_EANX, 0.33f, 378, 9600, "svg", 62.370003f }, + /* 26*/ { BARCODE_MAXICODE, 0.88f, 4, 100, "gif", 0.352f }, + /* 27*/ { BARCODE_MAXICODE, 0.88f, 4, 100, "emf", 0.1f }, /* NOTE scale rounded up to min 0.1 so doesn't round trip */ + /* 28*/ { BARCODE_MAXICODE, 0.88f, 4, 100, "svg", 1.76f }, + /* 29*/ { BARCODE_MAXICODE, 0.88f, 6, 150, "gif", 0.528f }, /* NOTE scale previously documented as 0.5f */ + /* 30*/ { BARCODE_MAXICODE, 0.88f, 6, 150, "emf", 0.132f }, + /* 31*/ { BARCODE_MAXICODE, 0.88f, 6, 150, "svg", 2.6399999 }, + /* 32*/ { BARCODE_MAXICODE, 0.88f, 8, 200, "gif", 0.704f }, /* NOTE scale previously documented as 0.7f */ + /* 33*/ { BARCODE_MAXICODE, 0.88f, 8, 200, "emf", 0.176f }, + /* 34*/ { BARCODE_MAXICODE, 0.88f, 8, 200, "svg", 3.52f }, + /* 35*/ { BARCODE_MAXICODE, 0.88f, 12, 300, "gif", 1.056f }, /* NOTE scale previously documented as 1.0f */ + /* 36*/ { BARCODE_MAXICODE, 0.88f, 12, 300, "emf", 0.264f }, + /* 37*/ { BARCODE_MAXICODE, 0.88f, 12, 300, "svg", 5.2799997f }, + /* 38*/ { BARCODE_MAXICODE, 0.88f, 16, 400, "gif", 1.408f }, /* NOTE scale previously documented as 1.4f */ + /* 39*/ { BARCODE_MAXICODE, 0.88f, 16, 400, "emf", 0.352f }, + /* 40*/ { BARCODE_MAXICODE, 0.88f, 16, 400, "gif", 1.408f }, + /* 41*/ { BARCODE_MAXICODE, 0.88f, 24, 600, "gif", 2.112f }, /* NOTE scale previously documented as 2.1f */ + /* 42*/ { BARCODE_MAXICODE, 0.88f, 24, 600, "emf", 0.528f }, + /* 43*/ { BARCODE_MAXICODE, 0.88f, 24, 600, "svg", 10.559999f }, + /* 44*/ { BARCODE_MAXICODE, 0.88f, 47, 1200, "gif", 4.136f }, /* NOTE scale previously documented as 4.1f */ + /* 45*/ { BARCODE_MAXICODE, 0.88f, 47, 1200, "emf", 1.034f }, + /* 46*/ { BARCODE_MAXICODE, 0.88f, 47, 1200, "svg", 20.68f }, + /* 47*/ { BARCODE_MAXICODE, 0.88f, 94, 2400, "gif", 8.272f }, /* NOTE dpmm previously documented as 95, scale as 8.2f */ + /* 48*/ { BARCODE_MAXICODE, 0.88f, 94, 2400, "emf", 2.0680001f }, + /* 49*/ { BARCODE_MAXICODE, 0.88f, 94, 2400, "svg", 41.360001f }, + /* 50*/ { BARCODE_MAXICODE, 0.88f, 189, 4800, "gif", 16.632f }, /* NOTE scale previously documented as 16.4f */ + /* 51*/ { BARCODE_MAXICODE, 0.88f, 189, 4800, "emf", 4.158f }, + /* 52*/ { BARCODE_MAXICODE, 0.88f, 189, 4800, "svg", 83.159996f }, + /* 53*/ { BARCODE_MAXICODE, 0.88f, 378, 9600, "gif", 33.264f }, + /* 54*/ { BARCODE_MAXICODE, 0.88f, 378, 9600, "emf", 8.316f }, + /* 55*/ { BARCODE_MAXICODE, 0.88f, 378, 9600, "svg", 166.31999f }, + /* 56*/ { BARCODE_PDF417, 0.27f, 2, 50, "gif", 0.5f }, + /* 57*/ { BARCODE_PDF417, 0.27f, 2, 50, "svg", 0.27000001f }, + /* 58*/ { BARCODE_PDF417, 0.27f, 6, 150, "gif", 1 }, + /* 59*/ { BARCODE_PDF417, 0.27f, 6, 150, "svg", 0.81000006f }, + /* 60*/ { BARCODE_PDF417, 0.27f, 12, 300, "gif", 1.5 }, + /* 61*/ { BARCODE_PDF417, 0.27f, 12, 300, "svg", 1.6200001f }, + /* 62*/ { BARCODE_PDF417, 0.27f, 24, 600, "gif", 3 }, + /* 63*/ { BARCODE_PDF417, 0.27f, 24, 600, "emf", 3.2400002f }, + /* 64*/ { BARCODE_PDF417, 0.27f, 24, 600, "svg", 3.2400002f }, + /* 65*/ { BARCODE_PHARMA_TWO, 1, 2, 50, "gif", 1 }, + /* 66*/ { BARCODE_PHARMA_TWO, 1, 2, 50, "svg", 1 }, + /* 67*/ { BARCODE_PHARMA_TWO, 1, 6, 150, "gif", 3 }, + /* 68*/ { BARCODE_PHARMA_TWO, 1, 6, 150, "svg", 3 }, + /* 69*/ { BARCODE_PHARMA_TWO, 1, 8, 200, "gif", 4 }, + /* 70*/ { BARCODE_PHARMA_TWO, 1, 8, 200, "svg", 4 }, + /* 71*/ { BARCODE_PHARMA_TWO, 1, 189, 4800, "gif", 94.5f }, + /* 72*/ { BARCODE_PHARMA_TWO, 1, 189, 4800, "svg", 94.5f }, + /* 73*/ { BARCODE_PHARMA_TWO, 1, 378, 9600, "gif", 189 }, + /* 74*/ { BARCODE_PHARMA_TWO, 1, 378, 9600, "svg", 189 }, + /* 75*/ { BARCODE_PHARMA_TWO, 1, 401, 10200, "gif", 200 }, /* NOTE scale capped to 200 so doesn't round trip */ + /* 76*/ { BARCODE_PHARMA_TWO, 1, 401, 10200, "svg", 200 }, + /* 77*/ { BARCODE_CODE128, 0.5, 12, 300, "gif", 3 }, + /* 78*/ { BARCODE_CODE128, 0, 12, -1, "gif", 0 }, /* x_dim zero */ + /* 79*/ { BARCODE_CODE128, 200.1f, 12, -1, "gif", 0 }, /* x_dim > 200 */ + /* 80*/ { BARCODE_CODE128, 0.5f, -0.1f, -1, "gif", 0 }, /* dpmm neg */ + /* 81*/ { BARCODE_CODE128, 0.5f, 1000.1, -1, "gif", 0 }, /* dpmm > 1000 */ + /* 82*/ { BARCODE_CODE128, 0.5f, 300, -1, "abcd", 0 }, /* filetype unknown */ + /* 83*/ { BARCODE_QRCODE, 10, 31, 800, "gif", 155 }, + }; + int data_size = ARRAY_SIZE(data); + int i; + float ret; + float x_dim_from_scale; + float dpmm_from_dpi; + + testStart("test_scale_from_xdimdp"); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + ret = ZBarcode_Scale_From_XdimDp(data[i].symbology, data[i].x_dim, data[i].dpmm, data[i].filetype); + assert_equal(ret, data[i].expected, "i:%d ZBarcode_Scale_From_XdimDp(%s, %g, %g, %s) %.8g != %.8g\n", + i, testUtilBarcodeName(data[i].symbology), data[i].dpmm, data[i].x_dim, data[i].filetype, ret, data[i].expected); + + if (ret) { + dpmm_from_dpi = roundf(data[i].dpi / 25.4f); + ret = ZBarcode_Scale_From_XdimDp(data[i].symbology, data[i].x_dim, dpmm_from_dpi, data[i].filetype); + assert_equal(ret, data[i].expected, "i:%d ZBarcode_Scale_From_XdimDp(%s, %g (dpi %d), %g, %s) %.8g != %.8g\n", + i, testUtilBarcodeName(data[i].symbology), dpmm_from_dpi, data[i].dpi, data[i].x_dim, data[i].filetype, ret, data[i].expected); + + if (data[i].expected > 0.1f && data[i].expected < 200.0f /* Can't round trip scales <= 0.1 or >= 200.0f */ + && (data[i].symbology == BARCODE_MAXICODE || strcmp(data[i].filetype, "gif") != 0)) { /* Non-MAXICODE raster rounds to half-increments */ + x_dim_from_scale = ZBarcode_XdimDp_From_Scale(data[i].symbology, ret, data[i].dpmm, data[i].filetype); + x_dim_from_scale = roundf(x_dim_from_scale * 100.0f) / 100.0f; + assert_equal(x_dim_from_scale, data[i].x_dim, "i:%d ZBarcode_XdimDp_From_Scale(%s, %g, %g, %s) %.8g != x_dim %.8g\n", + i, testUtilBarcodeName(data[i].symbology), ret, data[i].x_dim, data[i].filetype, x_dim_from_scale, data[i].x_dim); + } + } + } + + testFinish(); +} + +static void test_xdimdp_from_scale(const testCtx *const p_ctx) { + + struct item { + int symbology; + float scale; + float dpmm; /* Note testing "normal" case that want X-dim, not dpmm */ + int dpi; + char *filetype; + float expected; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + struct item data[] = { + /* 0*/ { BARCODE_EANX, 1, 6, 150, "gif", 0.33333334f }, + /* 1*/ { BARCODE_EANX, 1.32f, 8, 200, "gif", 0.33000001f }, + /* 2*/ { BARCODE_EANX, 1.5f, 8, 200, "gif", 0.375f }, + /* 3*/ { BARCODE_EANX, 1.98f, 12, 300, "gif", 0.33f }, + /* 4*/ { BARCODE_EANX, 2, 12, 300, "gif", 0.33333334f }, + /* 5*/ { BARCODE_EANX, 2, 12, 300, "svg", 0.33333334f }, + /* 6*/ { BARCODE_EANX, 2.64f, 16, 400, "gif", 0.33f }, + /* 7*/ { BARCODE_EANX, 2.5f, 16, 400, "gif", 0.3125f }, + /* 8*/ { BARCODE_EANX, 3.96f, 24, 600, "gif", 0.33f }, + /* 9*/ { BARCODE_EANX, 3.96f, 24, 600, "svg", 0.33f }, + /* 10*/ { BARCODE_EANX, 4, 24, 600, "gif", 0.33333334f }, + /* 11*/ { BARCODE_EANX, 7.755f, 47, 1200, "gif", 0.33f }, + /* 12*/ { BARCODE_EANX, 8, 47, 1200, "gif", 0.34042552f }, + /* 13*/ { BARCODE_EANX, 15.51f, 94, 2400, "gif", 0.33f }, + /* 14*/ { BARCODE_EANX, 15.5f, 94, 2400, "gif", 0.32978722f }, + /* 15*/ { BARCODE_EANX, 31.185001f, 189, 4800, "gif", 0.33f }, + /* 16*/ { BARCODE_EANX, 31, 189, 4800, "gif", 0.32804233f }, + /* 17*/ { BARCODE_MAXICODE, 1, 12, 300, "gif", 0.83333331f }, + /* 18*/ { BARCODE_MAXICODE, 0.264f, 12, 300, "emf", 0.87999994f }, + /* 19*/ { BARCODE_MAXICODE, 5.2799997f, 12, 300, "svg", 0.87999994f }, + /* 20*/ { BARCODE_MAXICODE, 2, 24, 600, "gif", 0.83333331f }, + /* 21*/ { BARCODE_MAXICODE, 0.528f, 24, 600, "emf", 0.87999994f }, + /* 22*/ { BARCODE_MAXICODE, 10.559999f, 24, 600, "svg", 0.87999994f }, + /* 23*/ { BARCODE_CODE128, 0, 12, -1, "gif", 0 }, /* scale zero */ + /* 24*/ { BARCODE_CODE128, 200.01f, 12, -1, "gif", 0 }, /* scale > 200 */ + /* 25*/ { BARCODE_CODE128, 0.5f, 0, -1, "gif", 0 }, /* xdim_mm_or_dpmm zero */ + /* 26*/ { BARCODE_CODE128, 0.5f, 1000.1f, -1, "gif", 0 }, /* xdim_mm_or_dpmm > 1000 */ + }; + int data_size = ARRAY_SIZE(data); + int i; + float ret; + float dpmm_from_dpi; + + testStart("test_xdimdp_from_scale"); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + ret = ZBarcode_XdimDp_From_Scale(data[i].symbology, data[i].scale, data[i].dpmm, data[i].filetype); + assert_equal(ret, data[i].expected, "i:%d ZBarcode_XdimDp_From_Scale(%s, %g, %g, %s) %.8g != %.8g\n", + i, testUtilBarcodeName(data[i].symbology), data[i].dpmm, data[i].scale, data[i].filetype, ret, data[i].expected); + + if (ret) { + dpmm_from_dpi = roundf(data[i].dpi / 25.4f); + ret = ZBarcode_XdimDp_From_Scale(data[i].symbology, data[i].scale, dpmm_from_dpi, data[i].filetype); + assert_equal(ret, data[i].expected, "i:%d ZBarcode_XdimDp_From_Scale(%s, %g (dpi %d), %g, %s) %.8g != %.8g\n", + i, testUtilBarcodeName(data[i].symbology), dpmm_from_dpi, data[i].dpi, data[i].scale, data[i].filetype, ret, data[i].expected); + } + } + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func */ @@ -1404,6 +1604,8 @@ int main(int argc, char *argv[]) { { "test_strip_bom", test_strip_bom }, { "test_zero_outfile", test_zero_outfile }, { "test_clear", test_clear }, + { "test_scale_from_xdimdp", test_scale_from_xdimdp }, + { "test_xdimdp_from_scale", test_xdimdp_from_scale }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_mailmark.c b/backend/tests/test_mailmark.c index 74f9d4a8..f0cefecf 100644 --- a/backend/tests/test_mailmark.c +++ b/backend/tests/test_mailmark.c @@ -44,59 +44,61 @@ static void test_input(const testCtx *const p_ctx) { struct item data[] = { /* 0*/ { "41038422416563762XY11 ", 0, 3, 155 }, /* 1*/ { "41038422416563762XY11 ", ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 2*/ { "41038422416563762xy11 ", 0, 3, 155 }, /* Case insensitive */ - /* 3*/ { "41038422416563762xy11 .", ZINT_ERROR_INVALID_DATA, -1, -1 }, - /* 4*/ { "0100000000000AA000AA0A", 0, 3, 131, }, /* Length 22, Mailmark C (2 digit chain id) */ - /* 5*/ { "5100000000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 1st char format 0-4 only */ - /* 6*/ { "0000000000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 2nd char version id 1-4 only */ - /* 7*/ { "01F0000000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 3rd char class 0-9A-E only */ - /* 8*/ { "0100A00000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 4-5th chars chain id 2 digits */ - /* 9*/ { "010000000000AAA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 6-13th chars item id 8 digits */ - /* 10*/ { "0100000000000 A000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* Remaining chars post code */ - /* 11*/ { "0100000000000C1I2JQ3N ", 0, 3, 131, }, /* F N F N L L N L S */ - /* 12*/ { "010000000000091I2JQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad 1st F */ - /* 13*/ { "0100000000000CAI2JQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad 1st N */ - /* 14*/ { "0100000000000C1I2IQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad 1st L */ - /* 15*/ { "0100000000000C1I2IQ3NA", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad S */ - /* 16*/ { "0100000000000KM12JQ3N ", 0, 3, 131, }, /* F F N N L L N L S */ - /* 17*/ { "0100000000000K 12JQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad 2nd F (non-numeric otherwise matches last pattern) */ - /* 18*/ { "0100000000000KM1AJQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad 2nd N */ - /* 19*/ { "0100000000000KM12JO3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad 2nd L */ - /* 20*/ { "0100000000000KM12JQ3NA", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad S */ - /* 21*/ { "0100000000000OV123JQ4U", 0, 3, 131, }, /* F F N N N L L N L */ - /* 22*/ { "01000000000009V123JQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N N L L N L bad 1st F */ - /* 23*/ { "0100000000000OV12AJQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N N L L N L bad 3rd N */ - /* 24*/ { "0100000000000OV123JQ4V", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N N L L N L bad 3rd L */ - /* 25*/ { "0100000000000CI1K3JQ4U", 0, 3, 131, }, /* F F N F N L L N L */ - /* 26*/ { "0100000000000CI1 3JQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N F N L L N L bad 3rd F (non-numeric otherwise matches pattern above) */ - /* 27*/ { "0100000000000CIAK3JQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N F N L L N L bad 1st N */ - /* 28*/ { "0100000000000CI1K3CQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N F N L L N L bad 1st L */ - /* 29*/ { "0100000000000C12JQ3U ", 0, 3, 131, }, /* F N N L L N L S S */ - /* 30*/ { "0100000000000912JQ3U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad F */ - /* 31*/ { "0100000000000C1AJQ3U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad 2nd N */ - /* 32*/ { "0100000000000C12JO3U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad 2nd L */ - /* 33*/ { "0100000000000C12JQ3UA ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad 1st S */ - /* 34*/ { "0100000000000C123JQ4U ", 0, 3, 131, }, /* F N N N L L N L S */ - /* 35*/ { "01000000000009123JQ4U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad F */ - /* 36*/ { "0100000000000C12AJQ4U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad 3rd N */ - /* 37*/ { "0100000000000C123JQ4V ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad 3rd L */ - /* 38*/ { "0100000000000C123JQ4U1", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad S */ - /* 39*/ { "01000000000000000AA000AA0A", 0, 3, 155, }, /* Length 26, Mailmark L (6 digit chain id) */ - /* 40*/ { "010A0000000000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 4-9th chars chain id 6 digits */ - /* 41*/ { "010A0000000000000 A000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* Post code */ - /* 42*/ { "01000000000000000C1I2JQ3N ", 0, 3, 155, }, /* F N F N L L N L S */ - /* 43*/ { "01000000000000000C1 2JQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad 2nd F */ - /* 44*/ { "01000000000000000KM12JQ3N ", 0, 3, 155, }, /* F F N N L L N L S */ - /* 45*/ { "01000000000000000KM12JQAN ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad 3rd N */ - /* 46*/ { "01000000000000000OV123JQ4U", 0, 3, 155, }, /* F F N N N L L N L */ - /* 47*/ { "01000000000000000OV123IQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N N L L N L bad 1st L */ - /* 48*/ { "01000000000000000CI1K3JQ4U", 0, 3, 155, }, /* F F N F N L L N L */ - /* 49*/ { "010000000000000009I1K3JQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N F N L L N L bad 1st F */ - /* 50*/ { "01000000000000000C12JQ3U ", 0, 3, 155, }, /* F N N L L N L S S */ - /* 51*/ { "01000000000000000C12JQ3U A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad 2nd S */ - /* 52*/ { "01000000000000000C123JQ4U ", 0, 3, 155, }, /* F N N N L L N L S */ - /* 53*/ { "01000000000000000C 23JQ4U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad 1st N (non-alpha otherwise matches 2nd pattern) */ - /* 54*/ { "41038422416563762XY1", ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 2*/ { "4103842241656", ZINT_ERROR_TOO_LONG, -1, -1 }, /* Too short (< 14) */ + /* 3*/ { "41038422416563", ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 4*/ { "41038422416563762xy11 ", 0, 3, 155 }, /* Case insensitive */ + /* 5*/ { "41038422416563762xy11 .", ZINT_ERROR_INVALID_DATA, -1, -1 }, + /* 6*/ { "0100000000000AA000AA0A", 0, 3, 131, }, /* Length 22, Mailmark C (2 digit chain id) */ + /* 7*/ { "5100000000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 1st char format 0-4 only */ + /* 8*/ { "0000000000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 2nd char version id 1-4 only */ + /* 9*/ { "01F0000000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 3rd char class 0-9A-E only */ + /* 10*/ { "0100A00000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 4-5th chars chain id 2 digits */ + /* 11*/ { "010000000000AAA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 6-13th chars item id 8 digits */ + /* 12*/ { "0100000000000 A000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* Remaining chars post code */ + /* 13*/ { "0100000000000C1I2JQ3N ", 0, 3, 131, }, /* F N F N L L N L S */ + /* 14*/ { "010000000000091I2JQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad 1st F */ + /* 15*/ { "0100000000000CAI2JQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad 1st N */ + /* 16*/ { "0100000000000C1I2IQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad 1st L */ + /* 17*/ { "0100000000000C1I2IQ3NA", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad S */ + /* 18*/ { "0100000000000KM12JQ3N ", 0, 3, 131, }, /* F F N N L L N L S */ + /* 19*/ { "0100000000000K 12JQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad 2nd F (non-numeric otherwise matches last pattern) */ + /* 20*/ { "0100000000000KM1AJQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad 2nd N */ + /* 21*/ { "0100000000000KM12JO3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad 2nd L */ + /* 22*/ { "0100000000000KM12JQ3NA", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad S */ + /* 23*/ { "0100000000000OV123JQ4U", 0, 3, 131, }, /* F F N N N L L N L */ + /* 24*/ { "01000000000009V123JQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N N L L N L bad 1st F */ + /* 25*/ { "0100000000000OV12AJQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N N L L N L bad 3rd N */ + /* 26*/ { "0100000000000OV123JQ4V", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N N L L N L bad 3rd L */ + /* 27*/ { "0100000000000CI1K3JQ4U", 0, 3, 131, }, /* F F N F N L L N L */ + /* 28*/ { "0100000000000CI1 3JQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N F N L L N L bad 3rd F (non-numeric otherwise matches pattern above) */ + /* 29*/ { "0100000000000CIAK3JQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N F N L L N L bad 1st N */ + /* 30*/ { "0100000000000CI1K3CQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N F N L L N L bad 1st L */ + /* 31*/ { "0100000000000C12JQ3U ", 0, 3, 131, }, /* F N N L L N L S S */ + /* 32*/ { "0100000000000912JQ3U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad F */ + /* 33*/ { "0100000000000C1AJQ3U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad 2nd N */ + /* 34*/ { "0100000000000C12JO3U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad 2nd L */ + /* 35*/ { "0100000000000C12JQ3UA ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad 1st S */ + /* 36*/ { "0100000000000C123JQ4U ", 0, 3, 131, }, /* F N N N L L N L S */ + /* 37*/ { "01000000000009123JQ4U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad F */ + /* 38*/ { "0100000000000C12AJQ4U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad 3rd N */ + /* 39*/ { "0100000000000C123JQ4V ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad 3rd L */ + /* 40*/ { "0100000000000C123JQ4U1", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad S */ + /* 41*/ { "01000000000000000AA000AA0A", 0, 3, 155, }, /* Length 26, Mailmark L (6 digit chain id) */ + /* 42*/ { "010A0000000000000AA000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 4-9th chars chain id 6 digits */ + /* 43*/ { "010A0000000000000 A000AA0A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* Post code */ + /* 44*/ { "01000000000000000C1I2JQ3N ", 0, 3, 155, }, /* F N F N L L N L S */ + /* 45*/ { "01000000000000000C1 2JQ3N ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N F N L L N L S bad 2nd F */ + /* 46*/ { "01000000000000000KM12JQ3N ", 0, 3, 155, }, /* F F N N L L N L S */ + /* 47*/ { "01000000000000000KM12JQAN ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N L L N L S bad 3rd N */ + /* 48*/ { "01000000000000000OV123JQ4U", 0, 3, 155, }, /* F F N N N L L N L */ + /* 49*/ { "01000000000000000OV123IQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N N N L L N L bad 1st L */ + /* 50*/ { "01000000000000000CI1K3JQ4U", 0, 3, 155, }, /* F F N F N L L N L */ + /* 51*/ { "010000000000000009I1K3JQ4U", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F F N F N L L N L bad 1st F */ + /* 52*/ { "01000000000000000C12JQ3U ", 0, 3, 155, }, /* F N N L L N L S S */ + /* 53*/ { "01000000000000000C12JQ3U A", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N L L N L S S bad 2nd S */ + /* 54*/ { "01000000000000000C123JQ4U ", 0, 3, 155, }, /* F N N N L L N L S */ + /* 55*/ { "01000000000000000C 23JQ4U ", ZINT_ERROR_INVALID_DATA, -1, -1 }, /* F N N N L L N L S bad 1st N (non-alpha otherwise matches 2nd pattern) */ + /* 56*/ { "41038422416563762XY1", ZINT_ERROR_INVALID_DATA, -1, -1 }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; diff --git a/backend/tests/test_output.c b/backend/tests/test_output.c index a552f194..d22e05ed 100644 --- a/backend/tests/test_output.c +++ b/backend/tests/test_output.c @@ -30,6 +30,11 @@ /* SPDX-License-Identifier: BSD-3-Clause */ #include "testcommon.h" +#include "../output.h" +#ifdef _WIN32 +#include +#include +#endif INTERNAL int out_quiet_zones_test(const struct zint_symbol *symbol, const int hide_text, float *left, float *right, float *top, float *bottom); @@ -57,10 +62,107 @@ static void test_quiet_zones(const testCtx *const p_ctx) { testFinish(); } +#ifdef _WIN32 +#define TEST_OUT_SEP '\\' +#define TEST_OUT_SEP_STR "\\" +#else +#define TEST_OUT_SEP '/' +#define TEST_OUT_SEP_STR "/" +#endif + +static void test_fopen(const testCtx *const p_ctx) { + struct item { + char dir[32]; + char subdir[32]; + char *filename; + int succeed; + }; + /* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */ + struct item data[] = { + /* 0*/ { "", "", "out.png", 1 }, + /* 1*/ { "out_test", "", "out.png", 1 }, + /* 2*/ { "out_test_with_subdir", "out_test_subdir", "out.png", 1 }, + /* 3*/ { "out_test_with_subdir", "out_test_subdir", "out.bmp", 1 }, + /* 4*/ { "out_test_with_subdir", "out_test_subdir", "out.emf", 1 }, + /* 5*/ { "out_test_with_subdir", "out_test_subdir", "out.eps", 1 }, + /* 6*/ { "out_test_with_subdir", "out_test_subdir", "out.gif", 1 }, + /* 7*/ { "out_test_with_subdir", "out_test_subdir", "out.pcx", 1 }, + /* 8*/ { "out_test_with_subdir", "out_test_subdir", "out.svg", 1 }, + /* 9*/ { "out_test_with_subdir", "out_test_subdir", "out.tif", 1 }, + /* 10*/ { "out_test/", "", "out.png", 1 }, + /* 11*/ { "out_test//", "", "out.png", 1 }, + /* 12*/ { "out_test/", "/out_test_subdir/", "out.png", 1 }, + /* 13*/ { "out_test\\", "\\out_test_subdir\\", "out.png", 1 }, + }; + int data_size = ARRAY_SIZE(data); + int i, len; + + FILE *ret; + char cwdbuf[1024]; + char outfile[1024 + 256]; + char dirname[1024 + 256]; + char subdirname[1024 + 256]; + int dir_exists, subdir_exists; + + testStart("test_fopen"); + + assert_nonnull(getcwd(cwdbuf, sizeof(cwdbuf)), "getcwd NULL (%d, %s)\n", errno, strerror(errno)); + + for (i = 0; i < data_size; i++) { + + if (testContinue(p_ctx, i)) continue; + + strcpy(outfile, cwdbuf); + len = strlen(outfile); + if (len && outfile[len - 1] != TEST_OUT_SEP) { outfile[len++] = TEST_OUT_SEP; outfile[len] = '\0'; } + dir_exists = subdir_exists = 0; + + if (data[i].dir[0]) { + strcat(outfile, data[i].dir); + strcat(outfile, TEST_OUT_SEP_STR); + strcpy(dirname, outfile); + dir_exists = testUtilDirExists(dirname); + if (data[i].subdir[0]) { + strcat(outfile, data[i].subdir); + strcat(outfile, TEST_OUT_SEP_STR); + strcpy(subdirname, outfile); + subdir_exists = testUtilDirExists(subdirname); + } + } + strcat(outfile, data[i].filename); + + ret = out_fopen(outfile, "w"); + if (data[i].succeed) { + assert_nonnull(ret, "i:%d out_fopen(%s) == NULL (%d: %s)\n", i, outfile, errno, strerror(errno)); + assert_zero(fclose(ret), "i:%d fclose(%s) != 0 (%d: %s)\n", i, outfile, errno, strerror(errno)); + assert_nonzero(testUtilExists(outfile), "i:%d testUtilExists(%s) != 0 (%d: %s)\n", i, outfile, errno, strerror(errno)); + if (data[i].dir[0]) { + assert_nonzero(testUtilDirExists(dirname), "i:%d testUtilDirExists(%s) != 0 (%d: %s)\n", i, dirname, errno, strerror(errno)); + } + assert_zero(remove(outfile), "i:%d remove(%s) != 0 (%d: %s)\n", i, outfile, errno, strerror(errno)); + if (data[i].dir[0]) { + if (data[i].subdir[0] && !subdir_exists) { + assert_zero(testUtilRmDir(subdirname), "i:%d rmdir(%s) != 0 (%d: %s)\n", i, subdirname, errno, strerror(errno)); + } + if (!dir_exists && strcmp(dirname, "/") != 0 && strcmp(dirname, "\\") != 0) { + assert_zero(testUtilRmDir(dirname), "i:%d rmdir(%s) != 0 (%d: %s)\n", i, dirname, errno, strerror(errno)); + } + } + } else { + assert_null(ret, "i:%d out_fopen(%s) == NULL (%d: %s)\n", i, outfile, errno, strerror(errno)); + /* TODO: may have left junk around */ + } + } + + testFinish(); +} + + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func */ { "test_quiet_zones", test_quiet_zones }, + { "test_fopen", test_fopen }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_pcx.c b/backend/tests/test_pcx.c index 86545945..60032db8 100644 --- a/backend/tests/test_pcx.c +++ b/backend/tests/test_pcx.c @@ -65,7 +65,7 @@ static void test_print(const testCtx *const p_ctx) { char escaped[1024]; int escaped_size = 1024; - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_pcx"); @@ -124,7 +124,7 @@ static void test_print(const testCtx *const p_ctx) { ret = testUtilRename(symbol->outfile, expected_file); assert_zero(ret, "i:%d testUtilRename(%s, %s) ret %d != 0 (%d: %s)\n", i, symbol->outfile, expected_file, ret, errno, strerror(errno)); if (have_identify) { - ret = testUtilVerifyIdentify(expected_file, debug); + ret = testUtilVerifyIdentify(have_identify, expected_file, debug); assert_zero(ret, "i:%d %s identify %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), expected_file, ret); } } else { @@ -157,10 +157,13 @@ static void test_outfile(const testCtx *const p_ctx) { symbol.bitmap = data; symbol.bitmap_width = symbol.bitmap_height = 1; - strcpy(symbol.outfile, "nosuch_dir/out.pcx"); + strcpy(symbol.outfile, "test_pcx_out.pcx"); + (void) testUtilRmROFile(symbol.outfile); /* In case lying around from previous fail */ + assert_nonzero(testUtilCreateROFile(symbol.outfile), "pcx_pixel_plot testUtilCreateROFile(%s) fail (%d: %s)\n", symbol.outfile, errno, strerror(errno)); ret = pcx_pixel_plot(&symbol, data); assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "pcx_pixel_plot ret %d != ZINT_ERROR_FILE_ACCESS (%d) (%s)\n", ret, ZINT_ERROR_FILE_ACCESS, symbol.errtxt); + assert_zero(testUtilRmROFile(symbol.outfile), "pcx_pixel_plot testUtilRmROFile(%s) != 0 (%d: %s)\n", symbol.outfile, errno, strerror(errno)); symbol.output_options |= BARCODE_STDOUT; diff --git a/backend/tests/test_png.c b/backend/tests/test_png.c index 064ed5ef..390d8bb3 100644 --- a/backend/tests/test_png.c +++ b/backend/tests/test_png.c @@ -63,7 +63,7 @@ static void test_pixel_plot(const testCtx *const p_ctx) { char data_buf[8 * 2 + 1]; - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_pixel_plot"); @@ -98,7 +98,7 @@ static void test_pixel_plot(const testCtx *const p_ctx) { if (ret < ZINT_ERROR) { if (have_identify) { - ret = testUtilVerifyIdentify(symbol->outfile, debug); + ret = testUtilVerifyIdentify(have_identify, symbol->outfile, debug); assert_zero(ret, "i:%d identify %s ret %d != 0\n", i, symbol->outfile, ret); } if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) { @@ -214,7 +214,7 @@ static void test_print(const testCtx *const p_ctx) { int escaped_size = 1024; char *text; - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_print"); @@ -288,7 +288,7 @@ static void test_print(const testCtx *const p_ctx) { ret = testUtilRename(symbol->outfile, expected_file); assert_zero(ret, "i:%d testUtilRename(%s, %s) ret %d != 0\n", i, symbol->outfile, expected_file, ret); if (have_identify) { - ret = testUtilVerifyIdentify(expected_file, debug); + ret = testUtilVerifyIdentify(have_identify, expected_file, debug); assert_zero(ret, "i:%d %s identify %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), expected_file, ret); } } else { @@ -321,10 +321,13 @@ static void test_outfile(const testCtx *const p_ctx) { symbol.bitmap = data; symbol.bitmap_width = symbol.bitmap_height = 1; - strcpy(symbol.outfile, "nosuch_dir/out.png"); + strcpy(symbol.outfile, "test_png_out.png"); + (void) testUtilRmROFile(symbol.outfile); /* In case lying around from previous fail */ + assert_nonzero(testUtilCreateROFile(symbol.outfile), "png_pixel_plot testUtilCreateROFile(%s) fail (%d: %s)\n", symbol.outfile, errno, strerror(errno)); ret = png_pixel_plot(&symbol, data); assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "png_pixel_plot ret %d != ZINT_ERROR_FILE_ACCESS (%d) (%s)\n", ret, ZINT_ERROR_FILE_ACCESS, symbol.errtxt); + assert_zero(testUtilRmROFile(symbol.outfile), "png_pixel_plot testUtilRmROFile(%s) != 0 (%d: %s)\n", symbol.outfile, errno, strerror(errno)); symbol.output_options |= BARCODE_STDOUT; diff --git a/backend/tests/test_print.c b/backend/tests/test_print.c index 4a4cb839..0c33371b 100644 --- a/backend/tests/test_print.c +++ b/backend/tests/test_print.c @@ -67,7 +67,7 @@ static void test_print(const testCtx *const p_ctx) { char escaped[1024]; int escaped_size = 1024; - int have_identify = 0; + const char *have_identify = NULL; int have_libreoffice = 0; int have_ghostscript = 0; int have_vnu = 0; @@ -177,7 +177,7 @@ static void test_print(const testCtx *const p_ctx) { assert_zero(ret, "i:%d %s tiffinfo %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), expected_file, ret); } else if (strcmp(exts[j], "txt") != 0) { /* I.e. rasters */ if (have_identify) { - ret = testUtilVerifyIdentify(expected_file, debug); + ret = testUtilVerifyIdentify(have_identify, expected_file, debug); assert_zero(ret, "i:%d %s identify %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), expected_file, ret); } } diff --git a/backend/tests/test_ps.c b/backend/tests/test_ps.c index e6be8073..a9154bc1 100644 --- a/backend/tests/test_ps.c +++ b/backend/tests/test_ps.c @@ -224,10 +224,13 @@ static void test_outfile(const testCtx *const p_ctx) { symbol.symbology = BARCODE_CODE128; symbol.vector = &vector; - strcpy(symbol.outfile, "nosuch_dir/out.eps"); + strcpy(symbol.outfile, "test_ps_out.eps"); + (void) testUtilRmROFile(symbol.outfile); /* In case lying around from previous fail */ + assert_nonzero(testUtilCreateROFile(symbol.outfile), "ps_plot testUtilCreateROFile(%s) fail (%d: %s)\n", symbol.outfile, errno, strerror(errno)); ret = ps_plot(&symbol, 0); assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "ps_plot ret %d != ZINT_ERROR_FILE_ACCESS (%d) (%s)\n", ret, ZINT_ERROR_FILE_ACCESS, symbol.errtxt); + assert_zero(testUtilRmROFile(symbol.outfile), "ps_plot testUtilRmROFile(%s) != 0 (%d: %s)\n", symbol.outfile, errno, strerror(errno)); symbol.output_options |= BARCODE_STDOUT; diff --git a/backend/tests/test_qr.c b/backend/tests/test_qr.c index 7384ac29..8006ac1b 100644 --- a/backend/tests/test_qr.c +++ b/backend/tests/test_qr.c @@ -91,10 +91,12 @@ static void test_qr_options(const testCtx *const p_ctx) { /* 38*/ { -1, -1, 4, 1, { 3, 16, "123" }, "12345678901", 0, 0, 21, -1, "" }, /* 39*/ { -1, -1, 4, 1, { 3, 17, "123" }, "12345678901", ZINT_ERROR_INVALID_OPTION, -1, 0, -1, "Error 750: Structured Append count out of range (2-16)" }, /* 40*/ { -1, -1, 4, 1, { 3, 2, "123" }, "12345678901", ZINT_ERROR_INVALID_OPTION, -1, 0, -1, "Error 751: Structured Append index out of range (1-2)" }, - /* 41*/ { -1, -1, 4, 1, { 1, 2, "256" }, "12345678901", ZINT_ERROR_INVALID_OPTION, -1, 0, -1, "Error 754: Structured Append ID '256' out of range (0-255)" }, - /* 42*/ { GS1_MODE, 3, -1, -1, { 0, 0, "" }, "[20]12", ZINT_WARN_NONCOMPLIANT, 0, 21, -1, "Warning 755: Using ECI in GS1 mode not supported by GS1 standards" }, - /* 43*/ { GS1_MODE, -1, -1, -1, { 1, 2, "" }, "[20]12", ZINT_WARN_NONCOMPLIANT, 0, 21, -1, "Warning 756: Using Structured Append in GS1 mode not supported by GS1 standards" }, - /* 44*/ { GS1_MODE, 3, -1, -1, { 1, 2, "" }, "[20]12", ZINT_WARN_NONCOMPLIANT, 0, 21, -1, "Warning 755: Using ECI in GS1 mode not supported by GS1 standards" }, /* ECI trumps Structured Append */ + /* 41*/ { -1, -1, 4, 1, { 1, 2, "1234" }, "12345678901", ZINT_ERROR_INVALID_OPTION, -1, 0, -1, "Error 752: Structured Append ID too long (3 digit maximum)" }, + /* 42*/ { -1, -1, 4, 1, { 1, 2, "12A" }, "12345678901", ZINT_ERROR_INVALID_OPTION, -1, 0, -1, "Error 753: Invalid Structured Append ID (digits only)" }, + /* 43*/ { -1, -1, 4, 1, { 1, 2, "256" }, "12345678901", ZINT_ERROR_INVALID_OPTION, -1, 0, -1, "Error 754: Structured Append ID '256' out of range (0-255)" }, + /* 44*/ { GS1_MODE, 3, -1, -1, { 0, 0, "" }, "[20]12", ZINT_WARN_NONCOMPLIANT, 0, 21, -1, "Warning 755: Using ECI in GS1 mode not supported by GS1 standards" }, + /* 45*/ { GS1_MODE, -1, -1, -1, { 1, 2, "" }, "[20]12", ZINT_WARN_NONCOMPLIANT, 0, 21, -1, "Warning 756: Using Structured Append in GS1 mode not supported by GS1 standards" }, + /* 46*/ { GS1_MODE, 3, -1, -1, { 1, 2, "" }, "[20]12", ZINT_WARN_NONCOMPLIANT, 0, 21, -1, "Warning 755: Using ECI in GS1 mode not supported by GS1 standards" }, /* ECI trumps Structured Append */ }; int data_size = ARRAY_SIZE(data); int i, length, ret; diff --git a/backend/tests/test_raster.c b/backend/tests/test_raster.c index 1886e747..35f38f77 100644 --- a/backend/tests/test_raster.c +++ b/backend/tests/test_raster.c @@ -176,10 +176,10 @@ static void test_buffer(const testCtx *const p_ctx) { /* 51*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, "A00000000B", "", 50, 1, 102, 204, 116 }, /* 52*/ { BARCODE_CODE128, -1, "1234567890", "", 50, 1, 90, 180, 116 }, /* 53*/ { BARCODE_CODE128, COMPLIANT_HEIGHT, "1234567890", "", 50, 1, 90, 180, 116 }, - /* 54*/ { BARCODE_DPLEIT, -1, "1234567890123", "", 50, 1, 135, 270, 116 }, - /* 55*/ { BARCODE_DPLEIT, COMPLIANT_HEIGHT, "1234567890123", "", 50, 1, 135, 270, 116 }, - /* 56*/ { BARCODE_DPIDENT, -1, "12345678901", "", 50, 1, 117, 234, 116 }, - /* 57*/ { BARCODE_DPIDENT, COMPLIANT_HEIGHT, "12345678901", "", 50, 1, 117, 234, 116 }, + /* 54*/ { BARCODE_DPLEIT, -1, "1234567890123", "", 72, 1, 135, 270, 160 }, + /* 55*/ { BARCODE_DPLEIT, COMPLIANT_HEIGHT, "1234567890123", "", 72, 1, 135, 270, 160 }, + /* 56*/ { BARCODE_DPIDENT, -1, "12345678901", "", 72, 1, 117, 234, 160 }, + /* 57*/ { BARCODE_DPIDENT, COMPLIANT_HEIGHT, "12345678901", "", 72, 1, 117, 234, 160 }, /* 58*/ { BARCODE_CODE16K, -1, "1234567890", "", 20, 2, 70, 162, 44 }, /* 59*/ { BARCODE_CODE16K, COMPLIANT_HEIGHT, "1234567890", "", 21, 2, 70, 162, 46 }, /* 60*/ { BARCODE_CODE49, -1, "1234567890", "", 20, 2, 70, 162, 44 }, @@ -244,8 +244,8 @@ static void test_buffer(const testCtx *const p_ctx) { /*119*/ { BARCODE_MAXICODE, COMPLIANT_HEIGHT, "1234567890", "", 165, 33, 30, 299, 298 }, /*120*/ { BARCODE_QRCODE, -1, "1234567890AB", "", 21, 21, 21, 42, 42 }, /*121*/ { BARCODE_QRCODE, COMPLIANT_HEIGHT, "1234567890AB", "", 21, 21, 21, 42, 42 }, - /*122*/ { BARCODE_CODE128B, -1, "1234567890", "", 50, 1, 145, 290, 116 }, - /*123*/ { BARCODE_CODE128B, COMPLIANT_HEIGHT, "1234567890", "", 50, 1, 145, 290, 116 }, + /*122*/ { BARCODE_CODE128AB, -1, "1234567890", "", 50, 1, 145, 290, 116 }, + /*123*/ { BARCODE_CODE128AB, COMPLIANT_HEIGHT, "1234567890", "", 50, 1, 145, 290, 116 }, /*124*/ { BARCODE_AUSPOST, -1, "12345678901234567890123", "", 8, 3, 133, 266, 16 }, /*125*/ { BARCODE_AUSPOST, COMPLIANT_HEIGHT, "12345678901234567890123", "", 9.5, 3, 133, 266, 19 }, /*126*/ { BARCODE_AUSREPLY, -1, "12345678", "", 8, 3, 73, 146, 16 }, @@ -1477,10 +1477,10 @@ static void test_quiet_zones(const testCtx *const p_ctx) { /* 44*/ { BARCODE_CODABAR, BARCODE_QUIET_ZONES, -1, -1, "A0B", 0, 50, 1, 32, 104, 116, 0 /*set*/, 0, 100, 0, 20 }, /* 45*/ { BARCODE_CODE128, -1, -1, -1, "1234", 0, 50, 1, 57, 114, 116, 1 /*set*/, 0, 100, 0, 4 }, /* 46*/ { BARCODE_CODE128, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 57, 154, 116, 0 /*set*/, 0, 100, 0, 20 }, - /* 47*/ { BARCODE_DPLEIT, -1, -1, -1, "1234", 0, 50, 1, 135, 270, 116, 1 /*set*/, 0, 100, 0, 2 }, - /* 48*/ { BARCODE_DPLEIT, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 135, 310, 116, 0 /*set*/, 0, 100, 0, 20 }, - /* 49*/ { BARCODE_DPIDENT, -1, -1, -1, "1234", 0, 50, 1, 117, 234, 116, 1 /*set*/, 0, 100, 0, 2 }, - /* 50*/ { BARCODE_DPIDENT, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 117, 274, 116, 0 /*set*/, 0, 100, 0, 20 }, + /* 47*/ { BARCODE_DPLEIT, -1, -1, -1, "1234", 0, 72, 1, 135, 270, 160, 1 /*set*/, 0, 100, 0, 2 }, + /* 48*/ { BARCODE_DPLEIT, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 72, 1, 135, 310, 160, 0 /*set*/, 0, 100, 0, 20 }, + /* 49*/ { BARCODE_DPIDENT, -1, -1, -1, "1234", 0, 72, 1, 117, 234, 160, 1 /*set*/, 0, 100, 0, 2 }, + /* 50*/ { BARCODE_DPIDENT, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 72, 1, 117, 274, 160, 0 /*set*/, 0, 100, 0, 20 }, /* 51*/ { BARCODE_CODE16K, -1, -1, -1, "1234", 0, 20, 2, 70, 162, 44, 0 /*set*/, 2, 20, 0, 20 }, /* 52*/ { BARCODE_CODE16K, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 20, 2, 70, 162, 44, 0 /*set*/, 2, 20, 0, 20 }, /* 53*/ { BARCODE_CODE16K, BARCODE_NO_QUIET_ZONES, -1, -1, "1234", 0, 20, 2, 70, 140, 44, 1 /*set*/, 2, 20, 0, 6 }, @@ -1564,8 +1564,8 @@ static void test_quiet_zones(const testCtx *const p_ctx) { /*131*/ { BARCODE_MAXICODE, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 165, 33, 30, 319, 318, 0 /*set*/, 0, 9, 0, 319 }, /*132*/ { BARCODE_QRCODE, -1, -1, -1, "1234", 0, 21, 21, 21, 42, 42, 1 /*set*/, 0, 2, 0, 14 }, /*133*/ { BARCODE_QRCODE, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 21, 21, 21, 58, 58, 0 /*set*/, 0, 8, 0, 58 }, - /*134*/ { BARCODE_CODE128B, -1, -1, -1, "1234", 0, 50, 1, 79, 158, 116, 1 /*set*/, 0, 100, 0, 4 }, - /*135*/ { BARCODE_CODE128B, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 79, 198, 116, 0 /*set*/, 0, 100, 0, 20 }, + /*134*/ { BARCODE_CODE128AB, -1, -1, -1, "1234", 0, 50, 1, 79, 158, 116, 1 /*set*/, 0, 100, 0, 4 }, + /*135*/ { BARCODE_CODE128AB, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 79, 198, 116, 0 /*set*/, 0, 100, 0, 20 }, /*136*/ { BARCODE_AUSPOST, -1, -1, -1, "12345678", 0, 8, 3, 73, 146, 16, 1 /*set*/, 0, 10, 0, 2 }, /*137*/ { BARCODE_AUSPOST, BARCODE_QUIET_ZONES, -1, -1, "12345678", 0, 8, 3, 73, 186, 28, 0 /*set*/, 0, 28, 0, 20 }, /*138*/ { BARCODE_AUSREPLY, -1, -1, -1, "1234", 0, 8, 3, 73, 146, 16, 1 /*set*/, 0, 10, 0, 2 }, @@ -2045,8 +2045,8 @@ static void test_height(const testCtx *const p_ctx) { /* 50*/ { BARCODE_CODABAR, -1, 1, "A0B", "", 0, 1, 1, 32, 64, 2, "" }, /* 51*/ { BARCODE_CODABAR, -1, 4, "A0B", "", 0, 4, 1, 32, 64, 8, "" }, /* 52*/ { BARCODE_CODABAR, -1, 26, "A0B", "", 0, 26, 1, 32, 64, 52, "" }, - /* 53*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, 26, "A0B", "", ZINT_WARN_NONCOMPLIANT, 26, 1, 32, 64, 52, "" }, - /* 54*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, 27, "A0B", "", 0, 27, 1, 32, 64, 54, "" }, + /* 53*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, 11, "A0B", "", ZINT_WARN_NONCOMPLIANT, 11, 1, 32, 64, 22, "" }, + /* 54*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, 12, "A0B", "", 0, 12, 1, 32, 64, 24, "" }, /* 55*/ { BARCODE_CODE128, -1, 1, "1234567890", "", 0, 1, 1, 90, 180, 2, "" }, /* 56*/ { BARCODE_CODE128, COMPLIANT_HEIGHT, 1, "1234567890", "", 0, 1, 1, 90, 180, 2, "" }, /* 57*/ { BARCODE_CODE128, -1, 4, "1234567890", "", 0, 4, 1, 90, 180, 8, "" }, @@ -2188,9 +2188,9 @@ static void test_height(const testCtx *const p_ctx) { /*193*/ { BARCODE_PDF417COMP, -1, 24, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ", "", ZINT_WARN_NONCOMPLIANT, 22.5, 9, 86, 172, 45, "" }, /*194*/ { BARCODE_MAXICODE, -1, 1, "1234567890", "", 0, 16.5, 33, 30, 299, 298, "Fixed size, symbol->height ignored" }, /*195*/ { BARCODE_QRCODE, -1, 1, "ABCD", "", 0, 21, 21, 21, 42, 42, "Fixed width-to-height ratio, symbol->height ignored" }, - /*196*/ { BARCODE_CODE128B, -1, 1, "1234567890", "", 0, 1, 1, 145, 290, 2, "" }, - /*197*/ { BARCODE_CODE128B, COMPLIANT_HEIGHT, 1, "1234567890", "", 0, 1, 1, 145, 290, 2, "" }, - /*198*/ { BARCODE_CODE128B, -1, 4, "1234567890", "", 0, 4, 1, 145, 290, 8, "" }, + /*196*/ { BARCODE_CODE128AB, -1, 1, "1234567890", "", 0, 1, 1, 145, 290, 2, "" }, + /*197*/ { BARCODE_CODE128AB, COMPLIANT_HEIGHT, 1, "1234567890", "", 0, 1, 1, 145, 290, 2, "" }, + /*198*/ { BARCODE_CODE128AB, -1, 4, "1234567890", "", 0, 4, 1, 145, 290, 8, "" }, /*199*/ { BARCODE_AUSPOST, -1, -1, "12345678901234567890123", "", 0, 8, 3, 133, 266, 16, "" }, /*200*/ { BARCODE_AUSPOST, -1, 1, "12345678901234567890123", "", 0, 2.5, 3, 133, 266, 5, "" }, /*201*/ { BARCODE_AUSPOST, COMPLIANT_HEIGHT, 1, "12345678901234567890123", "", ZINT_WARN_NONCOMPLIANT, 1.5, 3, 133, 266, 3, "" }, diff --git a/backend/tests/test_svg.c b/backend/tests/test_svg.c index 5bbccb6c..9ba33b43 100644 --- a/backend/tests/test_svg.c +++ b/backend/tests/test_svg.c @@ -232,10 +232,13 @@ static void test_outfile(const testCtx *const p_ctx) { symbol.symbology = BARCODE_CODE128; symbol.vector = &vector; - strcpy(symbol.outfile, "nosuch_dir/out.svg"); + strcpy(symbol.outfile, "test_svg_out.svg"); + (void) testUtilRmROFile(symbol.outfile); /* In case lying around from previous fail */ + assert_nonzero(testUtilCreateROFile(symbol.outfile), "svg_plot testUtilCreateROFile(%s) fail (%d: %s)\n", symbol.outfile, errno, strerror(errno)); ret = svg_plot(&symbol, 0); assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "svg_plot ret %d != ZINT_ERROR_FILE_ACCESS (%d) (%s)\n", ret, ZINT_ERROR_FILE_ACCESS, symbol.errtxt); + assert_zero(testUtilRmROFile(symbol.outfile), "svg_plot testUtilRmROFile(%s) != 0 (%d: %s)\n", symbol.outfile, errno, strerror(errno)); symbol.output_options |= BARCODE_STDOUT; diff --git a/backend/tests/test_tif.c b/backend/tests/test_tif.c index 8cf713ef..68da2d56 100644 --- a/backend/tests/test_tif.c +++ b/backend/tests/test_tif.c @@ -96,7 +96,7 @@ static void test_pixel_plot(const testCtx *const p_ctx) { char data_buf[ZINT_MAX_DATA_LEN * 2 + 1]; int have_tiffinfo = testUtilHaveTiffInfo(); - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_pixel_plot"); @@ -136,7 +136,7 @@ static void test_pixel_plot(const testCtx *const p_ctx) { ret = testUtilVerifyTiffInfo(symbol->outfile, debug); assert_zero(ret, "i:%d tiffinfo %s ret %d != 0\n", i, symbol->outfile, ret); } else if (have_identify && !data[i].no_identify) { - ret = testUtilVerifyIdentify(symbol->outfile, debug); + ret = testUtilVerifyIdentify(have_identify, symbol->outfile, debug); assert_zero(ret, "i:%d identify %s ret %d != 0\n", i, symbol->outfile, ret); } @@ -214,7 +214,7 @@ static void test_print(const testCtx *const p_ctx) { char *text; int have_tiffinfo = testUtilHaveTiffInfo(); - int have_identify = testUtilHaveIdentify(); + const char *const have_identify = testUtilHaveIdentify(); testStart("test_print"); @@ -289,7 +289,7 @@ static void test_print(const testCtx *const p_ctx) { ret = testUtilVerifyTiffInfo(expected_file, debug); assert_zero(ret, "i:%d %s tiffinfo %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), expected_file, ret); } else if (have_identify) { - ret = testUtilVerifyIdentify(expected_file, debug); + ret = testUtilVerifyIdentify(have_identify, expected_file, debug); assert_zero(ret, "i:%d %s identify %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), expected_file, ret); } } else { @@ -320,10 +320,13 @@ static void test_outfile(const testCtx *const p_ctx) { symbol.bitmap = data; symbol.bitmap_width = symbol.bitmap_height = 1; - strcpy(symbol.outfile, "nosuch_dir/out.tif"); + strcpy(symbol.outfile, "test_tif_out.tif"); + (void) testUtilRmROFile(symbol.outfile); /* In case lying around from previous fail */ + assert_nonzero(testUtilCreateROFile(symbol.outfile), "tif_pixel_plot testUtilCreateROFile(%s) fail (%d: %s)\n", symbol.outfile, errno, strerror(errno)); ret = tif_pixel_plot(&symbol, data); assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "tif_pixel_plot ret %d != ZINT_ERROR_FILE_ACCESS (%d) (%s)\n", ret, ZINT_ERROR_FILE_ACCESS, symbol.errtxt); + assert_zero(testUtilRmROFile(symbol.outfile), "tif_pixel_plot testUtilRmROFile(%s) != 0 (%d: %s)\n", symbol.outfile, errno, strerror(errno)); symbol.output_options |= BARCODE_STDOUT; diff --git a/backend/tests/test_vector.c b/backend/tests/test_vector.c index 45af562a..c4159b65 100644 --- a/backend/tests/test_vector.c +++ b/backend/tests/test_vector.c @@ -188,8 +188,8 @@ static void test_buffer_vector(const testCtx *const p_ctx) { /* 24*/ { BARCODE_GS1_128, "[01]12345678901231", "", 50, 1, 134, 268, 118.900002 }, /* 25*/ { BARCODE_CODABAR, "A00000000B", "", 50, 1, 102, 204, 118.900002 }, /* 26*/ { BARCODE_CODE128, "1234567890", "", 50, 1, 90, 180, 118.900002 }, - /* 27*/ { BARCODE_DPLEIT, "1234567890123", "", 50, 1, 135, 270, 118.900002 }, - /* 28*/ { BARCODE_DPIDENT, "12345678901", "", 50, 1, 117, 234, 118.900002 }, + /* 27*/ { BARCODE_DPLEIT, "1234567890123", "", 72, 1, 135, 270, 162.89999 }, + /* 28*/ { BARCODE_DPIDENT, "12345678901", "", 72, 1, 117, 234, 162.89999 }, /* 29*/ { BARCODE_CODE16K, "1234567890", "", 20, 2, 70, 162, 44 }, /* 30*/ { BARCODE_CODE49, "1234567890", "", 20, 2, 70, 162, 44 }, /* 31*/ { BARCODE_CODE93, "1234567890", "", 50, 1, 127, 254, 118.900002 }, @@ -222,7 +222,7 @@ static void test_buffer_vector(const testCtx *const p_ctx) { /* 58*/ { BARCODE_PDF417COMP, "1234567890", "", 21, 7, 69, 138, 42 }, /* 59*/ { BARCODE_MAXICODE, "1234567890", "", 165, 33, 30, 60, 57.7333984 }, /* 60*/ { BARCODE_QRCODE, "1234567890AB", "", 21, 21, 21, 42, 42 }, - /* 61*/ { BARCODE_CODE128B, "1234567890", "", 50, 1, 145, 290, 118.900002 }, + /* 61*/ { BARCODE_CODE128AB, "1234567890", "", 50, 1, 145, 290, 118.900002 }, /* 62*/ { BARCODE_AUSPOST, "12345678901234567890123", "", 8, 3, 133, 266, 16 }, /* 63*/ { BARCODE_AUSREPLY, "12345678", "", 8, 3, 73, 146, 16 }, /* 64*/ { BARCODE_AUSROUTE, "12345678", "", 8, 3, 73, 146, 16 }, @@ -1175,10 +1175,10 @@ static void test_quiet_zones(const testCtx *const p_ctx) { /* 44*/ { BARCODE_CODABAR, BARCODE_QUIET_ZONES, -1, -1, "A0B", 0, 50, 1, 32, 104, 118.9, 20, 0, 2, 100 }, /* 45*/ { BARCODE_CODE128, -1, -1, -1, "1234", 0, 50, 1, 57, 114, 118.9, 0, 0, 4, 100 }, /* 46*/ { BARCODE_CODE128, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 57, 154, 118.9, 20, 0, 4, 100 }, - /* 47*/ { BARCODE_DPLEIT, -1, -1, -1, "1234", 0, 50, 1, 135, 270, 118.9, 0, 0, 2, 100 }, - /* 48*/ { BARCODE_DPLEIT, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 135, 310, 118.9, 20, 0, 2, 100 }, - /* 49*/ { BARCODE_DPIDENT, -1, -1, -1, "1234", 0, 50, 1, 117, 234, 118.9, 0, 0, 2, 100 }, - /* 50*/ { BARCODE_DPIDENT, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 117, 274, 118.9, 20, 0, 2, 100 }, + /* 47*/ { BARCODE_DPLEIT, -1, -1, -1, "1234", 0, 72, 1, 135, 270, 162.89999, 0, 0, 2, 144 }, + /* 48*/ { BARCODE_DPLEIT, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 72, 1, 135, 310, 162.89999, 20, 0, 2, 144 }, + /* 49*/ { BARCODE_DPIDENT, -1, -1, -1, "1234", 0, 72, 1, 117, 234, 162.89999, 0, 0, 2, 144 }, + /* 50*/ { BARCODE_DPIDENT, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 72, 1, 117, 274, 162.89999, 20, 0, 2, 144 }, /* 51*/ { BARCODE_CODE16K, -1, -1, -1, "1234", 0, 20, 2, 70, 162, 44, 20, 2, 6, 19 }, /* 52*/ { BARCODE_CODE16K, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 20, 2, 70, 162, 44, 20, 2, 6, 19 }, /* 53*/ { BARCODE_CODE16K, BARCODE_NO_QUIET_ZONES, -1, -1, "1234", 0, 20, 2, 70, 140, 44, 0, 2, 6, 19 }, @@ -1261,8 +1261,8 @@ static void test_quiet_zones(const testCtx *const p_ctx) { /*130*/ { BARCODE_MAXICODE, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 165, 33, 30, 64, 61.733398, 31, 30.866699, 16.430941, 0 }, /*131*/ { BARCODE_QRCODE, -1, -1, -1, "1234", 0, 21, 21, 21, 42, 42, 0, 0, 14, 2 }, /*132*/ { BARCODE_QRCODE, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 21, 21, 21, 58, 58, 8, 8, 14, 2 }, - /*133*/ { BARCODE_CODE128B, -1, -1, -1, "1234", 0, 50, 1, 79, 158, 118.9, 0, 0, 4, 100 }, - /*134*/ { BARCODE_CODE128B, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 79, 198, 118.9, 20, 0, 4, 100 }, + /*133*/ { BARCODE_CODE128AB, -1, -1, -1, "1234", 0, 50, 1, 79, 158, 118.9, 0, 0, 4, 100 }, + /*134*/ { BARCODE_CODE128AB, BARCODE_QUIET_ZONES, -1, -1, "1234", 0, 50, 1, 79, 198, 118.9, 20, 0, 4, 100 }, /*135*/ { BARCODE_AUSPOST, -1, -1, -1, "12345678", 0, 8, 3, 73, 146, 16, 0, 0, 2, 10 }, /*136*/ { BARCODE_AUSPOST, BARCODE_QUIET_ZONES, -1, -1, "12345678", 0, 8, 3, 73, 186, 29.333332, 20, 6.6666665, 2, 10 }, /*137*/ { BARCODE_AUSREPLY, -1, -1, -1, "1234", 0, 8, 3, 73, 146, 16, 0, 0, 2, 10 }, @@ -1550,8 +1550,8 @@ static void test_height(const testCtx *const p_ctx) { /* 50*/ { BARCODE_CODABAR, -1, 1, "A0B", "", 0, 1, 1, 32, 64, 2, "" }, /* 51*/ { BARCODE_CODABAR, -1, 4, "A0B", "", 0, 4, 1, 32, 64, 8, "" }, /* 52*/ { BARCODE_CODABAR, -1, 26, "A0B", "", 0, 26, 1, 32, 64, 52, "" }, - /* 53*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, 26, "A0B", "", ZINT_WARN_NONCOMPLIANT, 26, 1, 32, 64, 52, "" }, - /* 54*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, 27, "A0B", "", 0, 27, 1, 32, 64, 54, "" }, + /* 53*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, 11, "A0B", "", ZINT_WARN_NONCOMPLIANT, 11, 1, 32, 64, 22, "" }, + /* 54*/ { BARCODE_CODABAR, COMPLIANT_HEIGHT, 12, "A0B", "", 0, 12, 1, 32, 64, 24, "" }, /* 55*/ { BARCODE_CODE128, -1, 1, "1234567890", "", 0, 1, 1, 90, 180, 2, "" }, /* 56*/ { BARCODE_CODE128, COMPLIANT_HEIGHT, 1, "1234567890", "", 0, 1, 1, 90, 180, 2, "" }, /* 57*/ { BARCODE_CODE128, -1, 4, "1234567890", "", 0, 4, 1, 90, 180, 8, "" }, @@ -1693,9 +1693,9 @@ static void test_height(const testCtx *const p_ctx) { /*193*/ { BARCODE_PDF417COMP, -1, 24, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ", "", ZINT_WARN_NONCOMPLIANT, 24, 9, 86, 172, 48, "" }, /*194*/ { BARCODE_MAXICODE, -1, 1, "1234567890", "", 0, 16.5, 33, 30, 60, 57.733398, "Fixed size, symbol->height ignored" }, /*195*/ { BARCODE_QRCODE, -1, 1, "ABCD", "", 0, 21, 21, 21, 42, 42, "Fixed width-to-height ratio, symbol->height ignored" }, - /*196*/ { BARCODE_CODE128B, -1, 1, "1234567890", "", 0, 1, 1, 145, 290, 2, "" }, - /*197*/ { BARCODE_CODE128B, COMPLIANT_HEIGHT, 1, "1234567890", "", 0, 1, 1, 145, 290, 2, "" }, - /*198*/ { BARCODE_CODE128B, -1, 4, "1234567890", "", 0, 4, 1, 145, 290, 8, "" }, + /*196*/ { BARCODE_CODE128AB, -1, 1, "1234567890", "", 0, 1, 1, 145, 290, 2, "" }, + /*197*/ { BARCODE_CODE128AB, COMPLIANT_HEIGHT, 1, "1234567890", "", 0, 1, 1, 145, 290, 2, "" }, + /*198*/ { BARCODE_CODE128AB, -1, 4, "1234567890", "", 0, 4, 1, 145, 290, 8, "" }, /*199*/ { BARCODE_AUSPOST, -1, -1, "12345678901234567890123", "", 0, 8, 3, 133, 266, 16, "" }, /*200*/ { BARCODE_AUSPOST, -1, 1, "12345678901234567890123", "", 0, 2, 3, 133, 266, 4, "" }, /*201*/ { BARCODE_AUSPOST, COMPLIANT_HEIGHT, 1, "12345678901234567890123", "", ZINT_WARN_NONCOMPLIANT, 1.9230771, 3, 133, 266, 3.8461542, "" }, diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index cc8cb7a1..cb4d6e58 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -202,7 +202,7 @@ static int validate_int_range(const char src[], int *p_val, int *p_val_end) { for (i = 0; i < length; i++) { if (src[i] < '0' || src[i] > '9') { - if (src[i] != ',') { + if (src[i] != '-') { return 0; } val_end = 0; @@ -236,9 +236,13 @@ void testRun(int argc, char *argv[], testFunction funcs[], int funcs_size) { char *optarg; char *func = NULL; char func_buf[256 + 5]; + int exclude_idx = 0; testCtx ctx; - ctx.index = ctx.index_end = ctx.exclude = ctx.exclude_end = -1; + ctx.index = ctx.index_end = -1; + for (i = 0; i < ZINT_TEST_CTX_EXC_MAX; i++) { + ctx.exclude[i] = ctx.exclude_end[i] = -1; + } ctx.generate = ctx.debug = 0; if (argc) { @@ -303,9 +307,13 @@ void testRun(int argc, char *argv[], testFunction funcs[], int funcs_size) { fprintf(stderr, "testRun: -x exclude value missing, ignored\n"); } else { optarg = argv[++i]; - if (!validate_int_range(optarg, &ctx.exclude, &ctx.exclude_end)) { + if (exclude_idx + 1 == ZINT_TEST_CTX_EXC_MAX) { + fprintf(stderr, "testRun: too many -x exclude values, ignored\n"); + } else if (!validate_int_range(optarg, &ctx.exclude[exclude_idx], &ctx.exclude_end[exclude_idx])) { fprintf(stderr, "testRun: -x exclude value invalid, ignored\n"); - ctx.exclude = ctx.exclude_end = -1; + ctx.exclude[exclude_idx] = ctx.exclude_end[exclude_idx] = -1; + } else { + exclude_idx++; } } } else { @@ -329,6 +337,7 @@ void testRun(int argc, char *argv[], testFunction funcs[], int funcs_size) { /* Call in a dataset loop to determine if a datum should be tested according to -i & -x args */ int testContinue(const testCtx *const p_ctx, const int i) { + int j; if (p_ctx->index != -1) { if (p_ctx->index_end != -1) { if (i < p_ctx->index || (p_ctx->index_end && i > p_ctx->index_end)) { @@ -338,12 +347,12 @@ int testContinue(const testCtx *const p_ctx, const int i) { return 1; } } - if (p_ctx->exclude != -1) { - if (p_ctx->exclude_end != -1) { - if (i >= p_ctx->exclude && (p_ctx->exclude_end == 0 || i <= p_ctx->exclude_end)) { + for (j = 0; j < ZINT_TEST_CTX_EXC_MAX && p_ctx->exclude[j] != -1; j++) { + if (p_ctx->exclude_end[j] != -1) { + if (i >= p_ctx->exclude[j] && (p_ctx->exclude_end[j] == 0 || i <= p_ctx->exclude_end[j])) { return 1; } - } else if (i == p_ctx->exclude) { + } else if (i == p_ctx->exclude[j]) { return 1; } } @@ -1351,7 +1360,7 @@ int testUtilRmDir(const char *dirname) { #endif } -/* Rename a file (Windows compatibility). */ +/* Rename a file (Windows compatibility) */ int testUtilRename(const char *oldpath, const char *newpath) { #ifdef _MSVC int ret = remove(newpath); @@ -1360,6 +1369,37 @@ int testUtilRename(const char *oldpath, const char *newpath) { return rename(oldpath, newpath); } +/* Create read-only file */ +int testUtilCreateROFile(const char *filename) { + FILE *fp = fopen(filename, "w+"); + if (fp == NULL) { + return 0; + } + if (fclose(fp) != 0) { + return 0; + } +#ifdef _WIN32 + if (SetFileAttributesA(filename, GetFileAttributesA(filename) | FILE_ATTRIBUTE_READONLY) == 0) { + return 0; + } +#else + if (chmod(filename, S_IRUSR | S_IRGRP | S_IROTH) != 0) { + return 0; + } +#endif + return 1; +} + +/* Remove read-only file (Windows compatibility) */ +int testUtilRmROFile(const char *filename) { +#ifdef _WIN32 + if (SetFileAttributesA(filename, GetFileAttributesA(filename) & ~FILE_ATTRIBUTE_READONLY) == 0) { + return -1; + } +#endif + return remove(filename); +} + /* Compare 2 PNG files */ int testUtilCmpPngs(const char *png1, const char *png2) { int ret = -1; @@ -1730,12 +1770,19 @@ int testUtilCmpEpss(const char *eps1, const char *eps2) { #endif /* Whether ImageMagick's identify utility available on system */ -int testUtilHaveIdentify(void) { - return system("magick -version " DEV_NULL) == 0; +const char *testUtilHaveIdentify(void) { + static const char *progs[2] = { "magick identify", "identify" }; + if (system("magick -version " DEV_NULL_STDERR) == 0) { + return progs[0]; + } + if (system("identify -version " DEV_NULL_STDERR) == 0) { + return progs[1]; + } + return NULL; } /* Check raster files */ -int testUtilVerifyIdentify(const char *filename, int debug) { +int testUtilVerifyIdentify(const char *const prog, const char *filename, int debug) { char cmd[512 + 128]; if (strlen(filename) > 512) { @@ -1745,12 +1792,12 @@ int testUtilVerifyIdentify(const char *filename, int debug) { if (debug & ZINT_DEBUG_TEST_PRINT) { /* Verbose very noisy though so for quick check just return default output */ if (debug & ZINT_DEBUG_TEST_LESS_NOISY) { - sprintf(cmd, "magick identify %s", filename); + sprintf(cmd, "%s %s", prog, filename); } else { - sprintf(cmd, "magick identify -verbose %s", filename); + sprintf(cmd, "%s -verbose %s", prog, filename); } } else { - sprintf(cmd, "magick identify -verbose %s " DEV_NULL, filename); + sprintf(cmd, "%s -verbose %s " DEV_NULL, prog, filename); } return system(cmd); @@ -1981,7 +2028,7 @@ static const char *testUtilBwippName(int index, const struct zint_symbol *symbol { "maxicode", BARCODE_MAXICODE, 57, 1, 1, 0, 0, 0, }, { "qrcode", BARCODE_QRCODE, 58, 1, 1, 1, 0, 0, }, { "", -1, 59, 0, 0, 0, 0, 0, }, - { "", BARCODE_CODE128B, 60, 0, 0, 0, 0, 0, }, + { "", BARCODE_CODE128AB, 60, 0, 0, 0, 0, 0, }, { "", -1, 61, 0, 0, 0, 0, 0, }, { "", -1, 62, 0, 0, 0, 0, 0, }, { "auspost", BARCODE_AUSPOST, 63, 0, 0, 0, 0, 0, }, @@ -3324,7 +3371,7 @@ static const char *testUtilZXingCPPName(int index, const struct zint_symbol *sym { "MaxiCode", BARCODE_MAXICODE, 57, }, { "QRCode", BARCODE_QRCODE, 58, }, { "", -1, 59, }, - { "Code128", BARCODE_CODE128B, 60, }, + { "Code128", BARCODE_CODE128AB, 60, }, { "", -1, 61, }, { "", -1, 62, }, { "", BARCODE_AUSPOST, 63, }, diff --git a/backend/tests/testcommon.h b/backend/tests/testcommon.h index 3c4ae3c6..6e7f6327 100644 --- a/backend/tests/testcommon.h +++ b/backend/tests/testcommon.h @@ -86,11 +86,12 @@ void testFinish(void); void testSkip(const char *msg); void testReport(void); +#define ZINT_TEST_CTX_EXC_MAX 32 typedef struct s_testCtx { int index; int index_end; - int exclude; - int exclude_end; + int exclude[ZINT_TEST_CTX_EXC_MAX]; + int exclude_end[ZINT_TEST_CTX_EXC_MAX]; int generate; int debug; } testCtx; @@ -163,6 +164,8 @@ int testUtilDirExists(const char *dirname); int testUtilMkDir(const char *dirname); int testUtilRmDir(const char *dirname); int testUtilRename(const char *oldpath, const char *newpath); +int testUtilCreateROFile(const char *filename); +int testUtilRmROFile(const char *filename); int testUtilCmpPngs(const char *file1, const char *file2); int testUtilCmpTxts(const char *txt1, const char *txt2); @@ -170,8 +173,8 @@ int testUtilCmpBins(const char *bin1, const char *bin2); int testUtilCmpSvgs(const char *svg1, const char *svg2); int testUtilCmpEpss(const char *eps1, const char *eps2); -int testUtilHaveIdentify(void); -int testUtilVerifyIdentify(const char *filename, int debug); +const char *testUtilHaveIdentify(void); +int testUtilVerifyIdentify(const char *const prog, const char *filename, int debug); int testUtilHaveLibreOffice(void); int testUtilVerifyLibreOffice(const char *filename, int debug); int testUtilHaveGhostscript(void); diff --git a/backend/tif.c b/backend/tif.c index 7a93e5d9..c64287b5 100644 --- a/backend/tif.c +++ b/backend/tif.c @@ -38,6 +38,7 @@ #include #endif #include "common.h" +#include "output.h" #include "tif.h" #include "tif_lzw.h" @@ -331,7 +332,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) #endif tif_file = stdout; } else { - if (!(tif_file = fopen(symbol->outfile, "wb+"))) { /* '+' as use fseek/ftell() */ + if (!(tif_file = out_fopen(symbol->outfile, "wb+"))) { /* '+' as use fseek/ftell() */ sprintf(symbol->errtxt, "672: Could not open output file (%d: %.30s)", errno, strerror(errno)); return ZINT_ERROR_FILE_ACCESS; } @@ -523,7 +524,11 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) tags[entries].tag = 0x0128; /* ResolutionUnit */ tags[entries].type = 3; /* SHORT */ tags[entries].count = 1; - tags[entries++].offset = 2; /* Inches */ + if (symbol->dpmm) { + tags[entries++].offset = 3; /* Centimetres */ + } else { + tags[entries++].offset = 2; /* Inches */ + } if (color_map_size) { tags[entries].tag = 0x0140; /* ColorMap */ @@ -571,17 +576,17 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) total_bytes_put += strip_count * 8; } - /* X Resolution */ - temp32 = 72; + /* XResolution */ + temp32 = symbol->dpmm ? symbol->dpmm : 72; fwrite(&temp32, 4, 1, tif_file); - temp32 = 1; + temp32 = symbol->dpmm ? 10 /*cm*/ : 1; fwrite(&temp32, 4, 1, tif_file); total_bytes_put += 8; - /* Y Resolution */ - temp32 = 72; + /* YResolution */ + temp32 = symbol->dpmm ? symbol->dpmm : 72; fwrite(&temp32, 4, 1, tif_file); - temp32 = 1; + temp32 = symbol->dpmm ? 10 /*cm*/ : 1; fwrite(&temp32, 4, 1, tif_file); total_bytes_put += 8; diff --git a/backend/ultra.c b/backend/ultra.c index f6d53330..75d74987 100644 --- a/backend/ultra.c +++ b/backend/ultra.c @@ -957,7 +957,7 @@ INTERNAL int ultra(struct zint_symbol *symbol, struct zint_seg segs[], const int if (symbol->structapp.id[0]) { int id, id_len; - for (id_len = 0; id_len < 32 && symbol->structapp.id[id_len]; id_len++); + for (id_len = 1; id_len < 6 && symbol->structapp.id[id_len]; id_len++); if (id_len > 5) { /* 282 * 283 + 282 = 80088 */ strcpy(symbol->errtxt, "593: Structured Append ID too long (5 digit maximum)"); diff --git a/backend/zint.h b/backend/zint.h index 9818d4bb..3777ed34 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -111,6 +111,7 @@ extern "C" { int fontsize; /* Unused */ int input_mode; /* Encoding of input data (see DATA_MODE etc below). Default DATA_MODE */ int eci; /* Extended Channel Interpretation. Default 0 (none) */ + float dpmm; /* Resolution of output in dots per mm (BMP/EMF/PCX/PNG/TIF only). Default 0 (none) */ float dot_size; /* Size of dots used in BARCODE_DOTTY_MODE. Default 0.8 */ float guard_descent; /* Height in X-dimensions that EAN/UPC guard bars descend. Default 5 */ struct zint_structapp structapp; /* Structured Append info. Default structapp.count 0 (none) */ @@ -184,7 +185,8 @@ extern "C" { #define BARCODE_PDF417TRUNC 56 /* Legacy */ #define BARCODE_MAXICODE 57 /* MaxiCode */ #define BARCODE_QRCODE 58 /* QR Code */ -#define BARCODE_CODE128B 60 /* Code 128 (Subset B) */ +#define BARCODE_CODE128AB 60 /* Code 128 (Suppress subset C) */ +#define BARCODE_CODE128B 60 /* Legacy */ #define BARCODE_AUSPOST 63 /* Australia Post Standard Customer */ #define BARCODE_AUSREPLY 66 /* Australia Post Reply Paid */ #define BARCODE_AUSROUTE 67 /* Australia Post Routing */ @@ -322,7 +324,7 @@ extern "C" { #define ZINT_ERROR_USES_ECI 13 /* Error counterpart of warning if WARN_FAIL_ALL set (see below) */ #define ZINT_ERROR_NONCOMPLIANT 14 /* Error counterpart of warning if WARN_FAIL_ALL set */ -/* Warning warn (`symbol->warn_level`) */ +/* Warning level (`symbol->warn_level`) */ #define WARN_DEFAULT 0 /* Default behaviour */ #define WARN_FAIL_ALL 2 /* Treat warning as error */ @@ -443,6 +445,19 @@ extern "C" { ZINT_EXTERN unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag); + /* Return default X-dimension in mm for symbology `symbol_id`. Returns 0 on error (invalid `symbol_id`) */ + ZINT_EXTERN float ZBarcode_Default_Xdim(int symbol_id); + + /* Return the scale to use for `symbol_id` for non-zero X-dimension `x_dim_mm` at `dpmm` dots per mm for + `filetype`. If `dpmm` zero defaults to 12. If `filetype` NULL/empty, defaults to "GIF". Returns 0 on error */ + ZINT_EXTERN float ZBarcode_Scale_From_XdimDp(int symbol_id, float x_dim_mm, float dpmm, const char *filetype); + + /* Reverse of `ZBarcode_Scale_From_XdimDp()` above to estimate the X-dimension or dpmm given non-zero `scale` and + non-zero `x_dim_mm_or_dpmm`. Return value bound to dpmm max not X-dimension max. Returns 0 on error */ + ZINT_EXTERN float ZBarcode_XdimDp_From_Scale(int symbol_id, float scale, float x_dim_mm_or_dpmm, + const char *filetype); + + /* Whether Zint built without PNG support */ ZINT_EXTERN int ZBarcode_NoPng(void); diff --git a/backend_qt/qzint.cpp b/backend_qt/qzint.cpp index a870c09b..2e33319d 100644 --- a/backend_qt/qzint.cpp +++ b/backend_qt/qzint.cpp @@ -105,6 +105,7 @@ namespace Zint { : m_zintSymbol(nullptr), m_symbol(BARCODE_CODE128), m_input_mode(UNICODE_MODE), m_height(0.0f), m_option_1(-1), m_option_2(0), m_option_3(0), + m_dpmm(0.0f), m_scale(1.0f), m_dotty(false), m_dot_size(4.0f / 5.0f), m_guardDescent(5.0f), @@ -122,6 +123,7 @@ namespace Zint { m_reader_init(false), m_warn_level(WARN_DEFAULT), m_debug(false), m_encodedWidth(0), m_encodedRows(0), + m_vectorWidth(0.0f), m_vectorHeight(0.0f), m_error(0), target_size_horiz(0), target_size_vert(0) // Legacy { @@ -133,7 +135,7 @@ namespace Zint { ZBarcode_Delete(m_zintSymbol); } - void QZint::resetSymbol() { + bool QZint::resetSymbol() { m_error = 0; m_lastError.clear(); @@ -142,7 +144,7 @@ namespace Zint { } else if (!(m_zintSymbol = ZBarcode_Create())) { m_error = ZINT_ERROR_MEMORY; m_lastError = QSL("Insufficient memory for Zint structure"); - return; + return false; } m_zintSymbol->symbology = m_symbol; @@ -194,27 +196,32 @@ namespace Zint { m_zintSymbol->input_mode |= GS1NOCHECK_MODE; } m_zintSymbol->eci = m_eci; + m_zintSymbol->dpmm = m_dpmm; m_zintSymbol->dot_size = m_dot_size; m_zintSymbol->guard_descent = m_guardDescent; m_zintSymbol->structapp = m_structapp; m_zintSymbol->warn_level = m_warn_level; m_zintSymbol->debug = m_debug ? ZINT_DEBUG_PRINT : 0; + + return true; } void QZint::encode() { - resetSymbol(); - if (m_segs.empty()) { - QByteArray bstr = m_text.toUtf8(); - /* Note do our own rotation */ - m_error = ZBarcode_Encode_and_Buffer_Vector(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), 0); - } else { - struct zint_seg segs[maxSegs]; - std::vector bstrs; - int seg_count = convertSegs(segs, bstrs); - /* Note do our own rotation */ - m_error = ZBarcode_Encode_Segs_and_Buffer_Vector(m_zintSymbol, segs, seg_count, 0); + if (resetSymbol()) { + if (m_segs.empty()) { + QByteArray bstr = m_text.toUtf8(); + /* Note do our own rotation */ + m_error = ZBarcode_Encode_and_Buffer_Vector(m_zintSymbol, (unsigned char *) bstr.data(), + bstr.length(), 0); + } else { + struct zint_seg segs[maxSegs]; + std::vector bstrs; + int seg_count = convertSegs(segs, bstrs); + /* Note do our own rotation */ + m_error = ZBarcode_Encode_Segs_and_Buffer_Vector(m_zintSymbol, segs, seg_count, 0); + } + m_lastError = m_zintSymbol->errtxt; } - m_lastError = m_zintSymbol->errtxt; if (m_error < ZINT_ERROR) { m_borderType = m_zintSymbol->output_options & (BARCODE_BIND | BARCODE_BOX | BARCODE_BIND_TOP); @@ -224,14 +231,17 @@ namespace Zint { m_vwhitespace = m_zintSymbol->whitespace_height; m_encodedWidth = m_zintSymbol->width; m_encodedRows = m_zintSymbol->rows; + m_vectorWidth = m_zintSymbol->vector->width; + m_vectorHeight = m_zintSymbol->vector->height; emit encoded(); } else { - m_encodedWidth = 0; - m_encodedRows = 0; + m_encodedWidth = m_encodedRows = 0; + m_vectorWidth = m_vectorHeight = 0.0f; emit errored(); } } + /* Symbology to use (see BARCODE_XXX) */ int QZint::symbol() const { return m_symbol; } @@ -240,6 +250,7 @@ namespace Zint { m_symbol = symbol; } + /* Input data encoding. Default UNICODE_MODE */ int QZint::inputMode() const { return m_input_mode; } @@ -248,19 +259,23 @@ namespace Zint { m_input_mode = input_mode; } + /* Input data (segment 0 text) */ QString QZint::text() const { return m_text; } + /* Set input data. Note: clears segs */ void QZint::setText(const QString& text) { m_text = text; m_segs.clear(); } + /* Input segments. */ std::vector QZint::segs() const { return m_segs; } + /* Set segments. Note: clears text and sets eci */ void QZint::setSegs(const std::vector& segs) { m_segs = segs; m_text.clear(); @@ -269,6 +284,7 @@ namespace Zint { } } + /* Primary message (Maxicode, Composite) */ QString QZint::primaryMessage() const { return m_primaryMessage; } @@ -277,6 +293,7 @@ namespace Zint { m_primaryMessage = primaryMessage; } + /* Symbol height in X-dimensions */ float QZint::height() const { return m_height; } @@ -285,6 +302,7 @@ namespace Zint { m_height = height; } + /* Symbol-specific options (see "../docs/manual.txt") */ int QZint::option1() const { return m_option_1; } @@ -293,6 +311,7 @@ namespace Zint { m_option_1 = option_1; } + /* Symbol-specific options */ int QZint::option2() const { return m_option_2; } @@ -309,6 +328,7 @@ namespace Zint { m_option_3 = option; } + /* Scale factor when printing barcode, i.e. adjusts X-dimension */ float QZint::scale() const { return m_scale; } @@ -317,6 +337,16 @@ namespace Zint { m_scale = scale; } + /* Resolution of output in dots per mm (BMP/EMF/PCX/PNG/TIF only) */ + float QZint::dpmm() const { + return m_dpmm; + } + + void QZint::setDPMM(float dpmm) { + m_dpmm = dpmm; + } + + /* Dotty mode */ bool QZint::dotty() const { return m_dotty; } @@ -325,6 +355,7 @@ namespace Zint { m_dotty = dotty; } + /* Size of dots used in BARCODE_DOTTY_MODE */ float QZint::dotSize() const { return m_dot_size; } @@ -333,6 +364,7 @@ namespace Zint { m_dot_size = dotSize; } + /* Height in X-dimensions that EAN/UPC guard bars descend */ float QZint::guardDescent() const { return m_guardDescent; } @@ -341,6 +373,7 @@ namespace Zint { m_guardDescent = guardDescent; } + /* Structured Append info */ int QZint::structAppCount() const { return m_structapp.count; } @@ -378,6 +411,7 @@ namespace Zint { memset(&m_structapp, 0, sizeof(m_structapp)); } + /* Foreground colour */ QColor QZint::fgColor() const { return m_fgColor; } @@ -386,6 +420,7 @@ namespace Zint { m_fgColor = fgColor; } + /* Background colour */ QColor QZint::bgColor() const { return m_bgColor; } @@ -394,6 +429,7 @@ namespace Zint { m_bgColor = bgColor; } + /* Use CMYK colour space (Encapsulated PostScript and TIF) */ bool QZint::cmyk() const { return m_cmyk; } @@ -402,6 +438,7 @@ namespace Zint { m_cmyk = cmyk; } + /* Type of border above/below/around barcode */ int QZint::borderType() const { return m_borderType; } @@ -418,6 +455,7 @@ namespace Zint { } } + /* Size of border in X-dimensions */ int QZint::borderWidth() const { return m_borderWidth; } @@ -428,6 +466,7 @@ namespace Zint { m_borderWidth = borderWidth; } + /* Width in X-dimensions of whitespace to left & right of barcode */ int QZint::whitespace() const { return m_whitespace; } @@ -436,6 +475,7 @@ namespace Zint { m_whitespace = whitespace; } + /* Height in X-dimensions of whitespace above & below the barcode */ int QZint::vWhitespace() const { return m_vwhitespace; } @@ -444,6 +484,7 @@ namespace Zint { m_vwhitespace = vWhitespace; } + /* Type of font to use i.e. normal, small, bold or (vector only) small bold */ int QZint::fontSetting() const { return m_fontSetting; } @@ -468,6 +509,7 @@ namespace Zint { } } + /* Show (true) or hide (false) Human Readable Text */ bool QZint::showText() const { return m_show_hrt; } @@ -476,6 +518,7 @@ namespace Zint { m_show_hrt = showText; } + /* Set to true to use GS (Group Separator) instead of FNC1 as GS1 separator (Data Matrix) */ bool QZint::gsSep() const { return m_gssep; } @@ -484,6 +527,8 @@ namespace Zint { m_gssep = gsSep; } + /* Add compliant quiet zones (additional to any specified whitespace) + Note: CODE16K, CODE49, CODABLOCKF, ITF14, EAN/UPC have default quiet zones */ bool QZint::quietZones() const { return m_quiet_zones; } @@ -492,6 +537,7 @@ namespace Zint { m_quiet_zones = quietZones; } + /* Disable quiet zones, notably those with defaults as listed above */ bool QZint::noQuietZones() const { return m_no_quiet_zones; } @@ -500,6 +546,7 @@ namespace Zint { m_no_quiet_zones = noQuietZones; } + /* Warn if height not compliant and use standard height (if any) as default */ bool QZint::compliantHeight() const { return m_compliant_height; } @@ -508,6 +555,7 @@ namespace Zint { m_compliant_height = compliantHeight; } + /* Rotate barcode by angle (degrees 0, 90, 180 and 270) */ int QZint::rotateAngle() const { return m_rotate_angle; } @@ -536,6 +584,7 @@ namespace Zint { } } + /* Extended Channel Interpretation (segment 0 eci) */ int QZint::eci() const { return m_eci; } @@ -552,6 +601,7 @@ namespace Zint { } } + /* Process parentheses as GS1 AI delimiters (instead of square brackets) */ bool QZint::gs1Parens() const { return m_gs1parens; } @@ -560,6 +610,7 @@ namespace Zint { m_gs1parens = gs1Parens; } + /* Do not check validity of GS1 data (except that printable ASCII only) */ bool QZint::gs1NoCheck() const { return m_gs1nocheck; } @@ -568,6 +619,7 @@ namespace Zint { m_gs1nocheck = gs1NoCheck; } + /* Reader Initialisation (Programming) */ bool QZint::readerInit() const { return m_reader_init; } @@ -576,6 +628,7 @@ namespace Zint { m_reader_init = readerInit; } + /* Affects error/warning value returned by Zint API (see `getError()` below) */ int QZint::warnLevel() const { return m_warn_level; } @@ -584,6 +637,7 @@ namespace Zint { m_warn_level = warnLevel; } + /* Debugging flags */ bool QZint::debug() const { return m_debug; } @@ -592,6 +646,7 @@ namespace Zint { m_debug = debug; } + /* Symbol output info set by Zint on successful `render()` */ int QZint::encodedWidth() const { // Read-only, encoded width (no. of modules encoded) return m_encodedWidth; } @@ -600,7 +655,15 @@ namespace Zint { return m_encodedRows; } - /* Legacy */ + float QZint::vectorWidth() const { // Read-only, scaled width + return m_vectorWidth; + } + + float QZint::vectorHeight() const { // Read-only, scaled height + return m_vectorHeight; + } + + /* Legacy property getters/setters */ void QZint::setWidth(int width) { setOption1(width); } int QZint::width() const { return m_option_1; } void QZint::setSecurityLevel(int securityLevel) { setOption2(securityLevel); } @@ -614,6 +677,7 @@ namespace Zint { } QString QZint::error_message() const { return m_lastError; } /* Same as lastError() */ + /* Test capabilities - `ZBarcode_Cap()` */ bool QZint::hasHRT(int symbology) const { return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_HRT); } @@ -670,50 +734,63 @@ namespace Zint { return ZBarcode_Cap(symbology ? symbology : m_symbol, ZINT_CAP_COMPLIANT_HEIGHT); } + /* Whether takes GS1 AI-delimited data */ + bool QZint::takesGS1AIData(int symbology) const { + if (symbology == 0) { + symbology = m_symbol; + } + switch (symbology) { + case BARCODE_GS1_128: + case BARCODE_DBAR_EXP: + case BARCODE_DBAR_EXPSTK: + return true; + break; + default: + return symbology >= BARCODE_EANX_CC && symbology <= BARCODE_DBAR_EXPSTK_CC; + break; + } + } + + /* Error or warning returned by Zint on `render()` or `save_to_file()` */ int QZint::getError() const { return m_error; } + /* Error message returned by Zint on `render()` or `save_to_file()` */ const QString& QZint::lastError() const { return m_lastError; } + /* Whether `lastError()` set */ bool QZint::hasErrors() const { return m_lastError.length(); } - bool QZint::noPng() const { - return ZBarcode_NoPng() == 1; - } - - int QZint::getVersion() const { - return ZBarcode_Version(); - } - bool QZint::save_to_file(const QString& filename) { - resetSymbol(); - strcpy(m_zintSymbol->outfile, filename.toLatin1().left(255)); - if (m_segs.empty()) { - QByteArray bstr = m_text.toUtf8(); - m_error = ZBarcode_Encode_and_Print(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), - m_rotate_angle); - } else { - struct zint_seg segs[maxSegs]; - std::vector bstrs; - int seg_count = convertSegs(segs, bstrs); - m_error = ZBarcode_Encode_Segs_and_Print(m_zintSymbol, segs, seg_count, m_rotate_angle); + if (resetSymbol()) { + strcpy(m_zintSymbol->outfile, filename.toLatin1().left(255)); + if (m_segs.empty()) { + QByteArray bstr = m_text.toUtf8(); + m_error = ZBarcode_Encode_and_Print(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), + m_rotate_angle); + } else { + struct zint_seg segs[maxSegs]; + std::vector bstrs; + int seg_count = convertSegs(segs, bstrs); + m_error = ZBarcode_Encode_Segs_and_Print(m_zintSymbol, segs, seg_count, m_rotate_angle); + } } if (m_error >= ZINT_ERROR) { m_lastError = m_zintSymbol->errtxt; - m_encodedWidth = 0; - m_encodedRows = 0; + m_encodedWidth = m_encodedRows = 0; + m_vectorWidth = m_vectorHeight = 0.0f; emit errored(); return false; - } else { - return true; } + return true; } + /* Convert `zint_vector_rect->colour` to Qt color */ Qt::GlobalColor QZint::colourToQtColor(int colour) { switch (colour) { case 1: // Cyan @@ -756,7 +833,8 @@ namespace Zint { return i; } - /* Note: legacy argument `mode` is not used */ + /* Encode and display barcode in `paintRect` using `painter`. + Note: legacy argument `mode` is not used */ void QZint::render(QPainter& painter, const QRectF& paintRect, AspectRatioMode /*mode*/) { struct zint_vector_rect *rect; struct zint_vector_hexagon *hex; @@ -923,12 +1001,76 @@ namespace Zint { painter.restore(); } + /* Returns the default X-dimension (`ZBarcode_Default_Xdim()`). + If `symbology` non-zero then used instead of `symbol()` */ + float QZint::defaultXdim(int symbology) const { + return ZBarcode_Default_Xdim(symbology ? symbology : m_symbol); + } + + /* Returns the scale to use for X-dimension `x_dim_mm` at `dpmm` for `filetype`. + If `symbology` non-zero then used instead of `symbol()` */ + float QZint::getScaleFromXdimDp(float x_dim_mm, float dpmm, const QString& fileType, int symbology) const { + return ZBarcode_Scale_From_XdimDp(symbology ? symbology : m_symbol, x_dim_mm, dpmm, fileType.toLatin1()); + } + + /* Reverse of `getScaleFromXdimDp()` above, returning the X-dimension or dot density given the scale `scale`. + If `symbology` non-zero then used instead of `symbol()` */ + float QZint::getXdimDpFromScale(float scale, float x_dim_mm_or_dpmm, const QString& fileType, + int symbology) const { + return ZBarcode_XdimDp_From_Scale(symbology ? symbology : m_symbol, scale, x_dim_mm_or_dpmm, + fileType.toLatin1()); + } + + /* Set `width_x_dim` and `height_x_dim` with estimated size of barcode based on X-dimension `x_dim`. To be called + after a successful `render()`. Returns false if `scale()` zero or render is in error, otherwise true */ + bool QZint::getWidthHeightXdim(float x_dim, float &width_x_dim, float &height_x_dim) const { + + if (m_scale == 0.0f || m_vectorWidth == 0.0f || m_vectorHeight == 0.0f) { + width_x_dim = height_x_dim = 0.0f; + return false; + } + + const float scale = m_scale * 2.0f; + const float width = m_vectorWidth / scale; + const float height = m_vectorHeight / scale; + + if (rotateAngle() == 90 || rotateAngle() == 270) { // Sideways - swop + width_x_dim = (height * x_dim); + height_x_dim = (width * x_dim); + } else { + width_x_dim = (width * x_dim); + height_x_dim = (height * x_dim); + } + + return true; + } + + /* Return the BARCODE_XXX name of `symbology` */ + QString QZint::barcodeName(const int symbology) { + char buf[32]; + if (ZBarcode_BarcodeName(symbology, buf) == 0) { + return QString(buf); + } + return QSL(""); + } + + /* Whether Zint library "libzint" built with PNG support or not */ + bool QZint::noPng() { + return ZBarcode_NoPng() == 1; + } + + /* Version of Zint library "libzint" linked to */ + int QZint::getVersion() { + return ZBarcode_Version(); + } + /* Translate settings into Command Line equivalent. Set `win` to use Windows escaping of data. If `autoHeight` set then `--height=` option will not be emitted. If HEIGHTPERROW_MODE set and non-zero `heightPerRow` given then use that for height instead of internal height */ QString QZint::getAsCLI(const bool win, const bool longOptOnly, const bool barcodeNames, const bool noEXE, - const bool autoHeight, const float heightPerRow, const QString& outfile) const { + const bool autoHeight, const float heightPerRow, const QString& outfile, + const QZintXdimDpVars *xdimdpVars) const { QString cmd(win && !noEXE ? QSL("zint.exe") : QSL("zint")); char name_buf[32]; @@ -1071,7 +1213,9 @@ namespace Zint { arg_int(cmd, "--rows=", option3()); } - if (scale() != 1.0f) { + if (dpmm()) { + arg_scalexdimdp(cmd, "--scalexdimdp", scale(), dpmm(), symbol(), xdimdpVars); + } else if (scale() != 1.0f) { arg_float(cmd, "--scale=", scale()); } @@ -1202,6 +1346,41 @@ namespace Zint { } } } + + void QZint::arg_scalexdimdp(QString& cmd, const char *const opt, const float scale, const float dpmm, + const int symbol, const QZintXdimDpVars *xdimdpVars) { + if (dpmm) { + float resolution = dpmm; + float x_dim; + const char *x_dim_units_str = ""; + const char *resolution_units_str = ""; + if (xdimdpVars && xdimdpVars->set) { + x_dim = xdimdpVars->x_dim; + resolution = xdimdpVars->resolution; + if (xdimdpVars->x_dim_units || xdimdpVars->resolution_units) { + x_dim_units_str = xdimdpVars->x_dim_units ? "in" : "mm"; + resolution_units_str = xdimdpVars->resolution_units ? "dpi" : "dpmm"; + } + } else { + x_dim = ZBarcode_XdimDp_From_Scale(symbol, scale, resolution, nullptr); + } + cmd += QString::asprintf(" %s=%g%s,%g%s", + opt, x_dim, x_dim_units_str, resolution, resolution_units_str); + } + } + + /* Helper to return "GIF"/"SVG"(/"EMF") if `msg` false, "raster"/"vector"(/"EMF") otherwise + (EMF only if `symbol` is MaxiCode) */ + const char *QZintXdimDpVars::getFileType(int symbol, const struct QZintXdimDpVars *vars, bool msg) { + static const char *filetypes[3] = { "GIF", "SVG", "EMF" }; + static const char *msg_types[3] = { "raster", "vector", "EMF" }; + + if (!vars) return ""; + + const int idx = std::max(std::min(symbol == BARCODE_MAXICODE ? vars->filetype_maxicode + : vars->filetype, 2), 0); + return msg ? msg_types[idx] : filetypes[idx]; + } } /* namespace Zint */ /* vim: set ts=4 sw=4 et : */ diff --git a/backend_qt/qzint.h b/backend_qt/qzint.h index efe1fc78..75077beb 100644 --- a/backend_qt/qzint.h +++ b/backend_qt/qzint.h @@ -16,9 +16,15 @@ ***************************************************************************/ /* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * For version, see "../backend/zintconfig.h" + * For documentation, see "../docs/manual.txt" + */ + #ifndef QZINT_H #define QZINT_H +#include #include #include #include "zint.h" @@ -29,148 +35,200 @@ namespace Zint /* QString version of `struct zint_seg` */ class QZintSeg { public: - QString m_text; - int m_eci; + QString m_text; // `seg->source` and `seg->length` + int m_eci; // `seg->eci` QZintSeg(); QZintSeg(const QString& text, const int ECIIndex = 0); // `ECIIndex` is comboBox index (not ECI value) }; +struct QZintXdimDpVars; // Forward reference to Printing Scale settings, see end + /* Interface */ class QZint : public QObject { Q_OBJECT public: - enum AspectRatioMode{ IgnoreAspectRatio = 0, KeepAspectRatio = 1, CenterBarCode = 2 }; /* Legacy - not used */ + /* Legacy - not used */ + enum AspectRatioMode{ IgnoreAspectRatio = 0, KeepAspectRatio = 1, CenterBarCode = 2 }; public: QZint(); ~QZint(); - int symbol() const; /* Symbology */ + /* Symbology to use (see BARCODE_XXX) */ + int symbol() const; // `symbol->symbology` void setSymbol(int symbol); - int inputMode() const; + /* Input data encoding. Default UNICODE_MODE */ + int inputMode() const; // `symbol->input_mode` void setInputMode(int input_mode); + /* Note text/eci and segs are mutally exclusive */ + + /* Input data (segment 0 text) */ QString text() const; - void setText(const QString& text); // Clears segs + /* Set input data. Note: clears segs */ + void setText(const QString& text); + /* Input segments. */ std::vector segs() const; - void setSegs(const std::vector& segs); // Clears text and sets eci + /* Set segments. Note: clears text and sets eci */ + void setSegs(const std::vector& segs); - QString primaryMessage() const; + /* Primary message (Maxicode, Composite) */ + QString primaryMessage() const; // `symbol->primary` void setPrimaryMessage(const QString& primaryMessage); - float height() const; + /* Symbol height in X-dimensions */ + float height() const; // `symbol->height` void setHeight(float height); - int option1() const; + /* Symbol-specific options (see "../docs/manual.txt") */ + int option1() const; // `symbol->option_1` void setOption1(int option_1); - int option2() const; + /* Symbol-specific options */ + int option2() const; // `symbol->option_2` void setOption2(int option); - int option3() const; + /* Symbol-specific options */ + int option3() const; // `symbol->option_3` void setOption3(int option); - float scale() const; + /* Scale factor when printing barcode, i.e. adjusts X-dimension */ + float scale() const; // `symbol->scale` void setScale(float scale); - bool dotty() const; + /* Resolution of output in dots per mm (BMP/EMF/PCX/PNG/TIF only) */ + float dpmm() const; // `symbol->dpmm` + void setDPMM(float dpmm); + + /* Dotty mode */ + bool dotty() const; // `symbol->input_mode | BARCODE_DOTTY_MODE` void setDotty(bool botty); - float dotSize() const; + /* Size of dots used in BARCODE_DOTTY_MODE */ + float dotSize() const; // `symbol->dot_size` void setDotSize(float dot_size); - float guardDescent() const; + /* Height in X-dimensions that EAN/UPC guard bars descend */ + float guardDescent() const; // `symbol->guard_descent` void setGuardDescent(float guardDescent); - int structAppCount() const; - int structAppIndex() const; - QString structAppID() const; + /* Structured Append info */ + int structAppCount() const; // `symbol->structapp.count` + int structAppIndex() const; // `symbol->structapp.index` + QString structAppID() const; // `symbol->structapp.id` void setStructApp(const int count, const int index, const QString& id); void clearStructApp(); - QColor fgColor() const; + /* Foreground colour */ + QColor fgColor() const; // `symbol->fgcolour` void setFgColor(const QColor& fgColor); - QColor bgColor() const; + /* Background colour */ + QColor bgColor() const; // `symbol->bgcolour` void setBgColor(const QColor& bgColor); - bool cmyk() const; + /* Use CMYK colour space (Encapsulated PostScript and TIF) */ + bool cmyk() const; // `symbol->output_options | CMYK_COLOUR` void setCMYK(bool cmyk); - int borderType() const; + /* Type of border above/below/around barcode */ + int borderType() const; // `symbol->output_options | BARCODE_BIND | BARCODE_BOX | BARCODE_BIND_TOP` void setBorderType(int borderTypeIndex); - int borderWidth() const; + /* Size of border in X-dimensions */ + int borderWidth() const; // `symbol->border_width` void setBorderWidth(int borderWidth); - int whitespace() const; + /* Width in X-dimensions of whitespace to left & right of barcode */ + int whitespace() const; // `symbol->whitespace_width` void setWhitespace(int whitespace); - int vWhitespace() const; + /* Height in X-dimensions of whitespace above & below the barcode */ + int vWhitespace() const; // `symbol->whitespace_height` void setVWhitespace(int vWhitespace); - int fontSetting() const; + /* Type of font to use i.e. normal, small, bold or (vector only) small bold */ + int fontSetting() const; // `symbol->output_options | SMALL_TEXT | BOLD_TEXT` void setFontSetting(int fontSettingIndex); // Sets from comboBox index void setFontSettingValue(int fontSetting); // Sets literal value - bool showText() const; + /* Show (true) or hide (false) Human Readable Text */ + bool showText() const; // `symbol->show_hrt` void setShowText(bool showText); - bool gsSep() const; + /* Set to true to use GS (Group Separator) instead of FNC1 as GS1 separator (Data Matrix) */ + bool gsSep() const; // `symbol->output_options | GS1_GS_SEPARATOR` void setGSSep(bool gsSep); - bool quietZones() const; + /* Add compliant quiet zones (additional to any specified whitespace) + Note: CODE16K, CODE49, CODABLOCKF, ITF14, EAN/UPC have default quiet zones */ + bool quietZones() const; // `symbol->output_options | BARCODE_QUIET_ZONES` void setQuietZones(bool quietZones); - bool noQuietZones() const; + /* Disable quiet zones, notably those with defaults as listed above */ + bool noQuietZones() const; // `symbol->output_options | BARCODE_NO_QUIET_ZONES` void setNoQuietZones(bool noQuietZones); - bool compliantHeight() const; + /* Warn if height not compliant and use standard height (if any) as default */ + bool compliantHeight() const; // `symbol->output_options | COMPLIANT_HEIGHT` void setCompliantHeight(bool compliantHeight); + /* Rotate barcode by angle (degrees 0, 90, 180 and 270) */ int rotateAngle() const; void setRotateAngle(int rotateIndex); // Sets from comboBox index void setRotateAngleValue(int rotateAngle); // Sets literal value - int eci() const; + /* Extended Channel Interpretation (segment 0 eci) */ + int eci() const; // `symbol->eci` void setECI(int ECIIndex); // Sets from comboBox index void setECIValue(int eci); // Sets literal value - bool gs1Parens() const; + /* Process parentheses as GS1 AI delimiters (instead of square brackets) */ + bool gs1Parens() const; // `symbol->input_mode | GS1PARENS_MODE` void setGS1Parens(bool gs1Parens); - bool gs1NoCheck() const; + /* Do not check validity of GS1 data (except that printable ASCII only) */ + bool gs1NoCheck() const; // `symbol->input_mode | GS1NOCHECK_MODE` void setGS1NoCheck(bool gs1NoCheck); - bool readerInit() const; + /* Reader Initialisation (Programming) */ + bool readerInit() const; // `symbol->output_options | READER_INIT` void setReaderInit(bool readerInit); - int warnLevel() const; + /* Affects error/warning value returned by Zint API (see `getError()` below) */ + int warnLevel() const; // `symbol->warn_level` void setWarnLevel(int warnLevel); - bool debug() const; + /* Debugging flags */ + bool debug() const; // `symbol->debug` void setDebug(bool debug); + + /* Symbol output info set by Zint on successful `render()` */ int encodedWidth() const; // Read-only, encoded width (no. of modules encoded) int encodedRows() const; // Read-only, no. of rows encoded + float vectorWidth() const; // Read-only, scaled width + float vectorHeight() const; // Read-only, scaled height + /* Legacy property getters/setters */ - void setWidth(int width); /* option_1 */ + void setWidth(int width); /* `symbol->option_1` */ int width() const; - void setSecurityLevel(int securityLevel); /* option_2 */ + void setSecurityLevel(int securityLevel); /* `symbol->option_2` */ int securityLevel() const; void setPdf417CodeWords(int pdf417CodeWords); /* No-op */ int pdf417CodeWords() const; - void setHideText(bool hide); /* setShowText(!hide) */ - void setTargetSize(int width, int height); - QString error_message() const; /* Same as lastError() */ + void setHideText(bool hide); /* `setShowText(!hide)` */ + void setTargetSize(int width, int height); /* No-op */ + QString error_message() const; /* Same as `lastError()` */ - /* Test capabilities - ZBarcode_Cap() */ + + /* Test capabilities - `ZBarcode_Cap()` */ bool hasHRT(int symbology = 0) const; bool isStackable(int symbology = 0) const; bool isExtendable(int symbology = 0) const; @@ -186,20 +244,56 @@ public: bool supportsStructApp(int symbology = 0) const; bool hasCompliantHeight(int symbology = 0) const; + /* Whether takes GS1 AI-delimited data */ + bool takesGS1AIData(int symbology = 0) const; + + + /* Error or warning returned by Zint on `render()` or `save_to_file()` */ int getError() const; - const QString& lastError() const; - bool hasErrors() const; + /* Error message returned by Zint on `render()` or `save_to_file()` */ + const QString& lastError() const; // `symbol->errtxt` - bool save_to_file(const QString& filename); + /* Whether `lastError()` set */ + bool hasErrors() const; // `symbol->errtxt` - /* Note: legacy argument `mode` is not used */ + + /* Encode and print barcode to file `filename`. Only sets `getError()` on error, not on warning */ + bool save_to_file(const QString& filename); // `ZBarcode_Print()` + + /* Encode and display barcode in `paintRect` using `painter`. + Note: legacy argument `mode` is not used */ void render(QPainter& painter, const QRectF& paintRect, AspectRatioMode mode = IgnoreAspectRatio); - /* Whether Zint library "libzint" built with PNG support or not (`ZBarcode_NoPng()`) */ - bool noPng() const; - int getVersion() const; + /* Returns the default X-dimension (`ZBarcode_Default_Xdim()`). + If `symbology` non-zero then used instead of `symbol()` */ + float defaultXdim(int symbology = 0) const; + + /* Returns the scale to use for X-dimension `x_dim_mm` at `dpmm` for `filetype`. + If `symbology` non-zero then used instead of `symbol()` */ + float getScaleFromXdimDp(float x_dim_mm, float dpmm, const QString& fileType, int symbology = 0) const; + // `ZBarcode_Scale_Xdim()` + + /* Reverse of `getScaleFromXdimDp()` above, returning the X-dimension or dot density given the scale `scale`. + If `symbology` non-zero then used instead of `symbol()` */ + float getXdimDpFromScale(float scale, float x_dim_mm_or_dpmm, const QString& fileType, int symbology = 0) const; + // `ZBarcode_XdimDp_From_Scale()` + + /* Set `width_x_dim` and `height_x_dim` with estimated size of barcode based on X-dimension `x_dim`. To be called + after a successful `render()`. Returns false if `scale()` zero or render is in error, otherwise true */ + bool getWidthHeightXdim(float x_dim, float &width_x_dim, float &height_x_dim) const; + + + /* Return the BARCODE_XXX name of `symbology` */ + static QString barcodeName(const int symbology); // `ZBarcode_BarcodeName()` + + /* Whether Zint library "libzint" built with PNG support or not */ + static bool noPng(); // `ZBarcode_NoPng()` + + /* Version of Zint library "libzint" linked to */ + static int getVersion(); // `ZBarcode_Version()` + /* Translate settings into Command Line equivalent. Set `win` to use Windows escaping of data. If `autoHeight` set then `--height=` option will not be emitted. @@ -207,18 +301,20 @@ public: height */ QString getAsCLI(const bool win, const bool longOptOnly = false, const bool barcodeNames = false, const bool noEXE = false, const bool autoHeight = false, const float heightPerRow = 0.0f, - const QString& outfile = "") const; + const QString& outfile = "", const QZintXdimDpVars *xdimdpVars = nullptr) const; signals: - void encoded(); - void errored(); + void encoded(); // Emitted on successful `render()` + void errored(); // Emitted if an error (not warning) occurred on `render()` private: - void resetSymbol(); - void encode(); + bool resetSymbol(); // Reset the symbol structure for encoding using member fields + void encode(); // `ZBarcode_Encode_and_Buffer_Vector()` or `ZBarcode_Encode_Segs_and_Buffer_Vector()` + /* Helper to convert `m_segs` to `struct zint_seg[]` */ int convertSegs(struct zint_seg segs[], std::vector& bstrs); + /* Convert `zint_vector_rect->colour` to Qt color */ static Qt::GlobalColor colourToQtColor(int colour); /* `getAsCLI()` helpers */ @@ -232,6 +328,8 @@ private: static void arg_float(QString& cmd, const char *const opt, const float val, const bool allowZero = false); static void arg_structapp(QString& cmd, const char *const opt, const int count, const int index, const QString& id, const bool win); + static void arg_scalexdimdp(QString& cmd, const char *const opt, const float scale, const float dpmm, + const int symbol, const QZintXdimDpVars *xdimdpVars); private: zint_symbol *m_zintSymbol; @@ -244,6 +342,7 @@ private: int m_option_1; int m_option_2; int m_option_3; + float m_dpmm; float m_scale; bool m_dotty; float m_dot_size; @@ -271,6 +370,8 @@ private: bool m_debug; int m_encodedWidth; int m_encodedRows; + float m_vectorWidth; + float m_vectorHeight; QString m_lastError; int m_error; @@ -278,6 +379,21 @@ private: int target_size_vert; /* Legacy */ }; +/* Printing Scale settings */ +struct QZintXdimDpVars { + double x_dim = 0.0; // X-dimension in `x_dim_units` + int x_dim_units = 0; // 0 for mm, 1 for inches + int resolution = 0; // Dot density in `resolution_units` + int resolution_units = 0; // 0 for dpmm, 1 for dpi + int filetype = 0; // For non-MaxiCode, 0 for GIF (raster), 1 for SVG (vector) + int filetype_maxicode = 0; // For MaxiCode only, 0 for GIF (raster), 1 for SVG (vector), 2 for EMF + int set = 0; // 1 if explicitly set, 0 if just defaults (in which case the struct isn't applicable to `dpmm()`) + + /* Helper to return "GIF"/"SVG"(/"EMF") if `msg` false, "raster"/"vector"(/"EMF") otherwise + (EMF only if `symbol` is MaxiCode) */ + static const char *getFileType(int symbol, const struct QZintXdimDpVars *vars, bool msg = false); +}; + } /* namespace Zint */ /* vim: set ts=4 sw=4 et : */ diff --git a/backend_qt/tests/test_qzint.cpp b/backend_qt/tests/test_qzint.cpp index e4d9734a..3c64e771 100644 --- a/backend_qt/tests/test_qzint.cpp +++ b/backend_qt/tests/test_qzint.cpp @@ -115,6 +115,10 @@ private slots: bc.setScale(scale); QCOMPARE(bc.scale(), scale); + float dpmm = 11.811f; + bc.setDPMM(dpmm); + QCOMPARE(bc.dpmm(), dpmm); + bool dotty = true; bc.setDotty(dotty); QCOMPARE(bc.dotty(), dotty); @@ -260,6 +264,12 @@ private slots: QCOMPARE(bc.encodedWidth(), 0); // Read-only QCOMPARE(bc.encodedRows(), 0); // Read-only + + QCOMPARE(bc.vectorWidth(), 0.0f); // Read-only + QCOMPARE(bc.vectorHeight(), 0.0f); // Read-only + + QCOMPARE(bc.takesGS1AIData(BARCODE_CODE128), false); + QCOMPARE(bc.takesGS1AIData(BARCODE_GS1_128), true); } void setGetECIValueTest_data() @@ -370,10 +380,12 @@ private slots: QTest::addColumn("error_message"); QTest::addColumn("encodedWidth"); QTest::addColumn("encodedRows"); + QTest::addColumn("vectorWidth"); + QTest::addColumn("vectorHeight"); - QTest::newRow("BARCODE_QRCODE") << BARCODE_QRCODE << "1234" << 0 << "" << 21 << 21; + QTest::newRow("BARCODE_QRCODE") << BARCODE_QRCODE << "1234" << 0 << "" << 21 << 21 << 42.0f << 42.0f; if (!m_skipIfFontUsed) { - QTest::newRow("BARCODE_QRCODE no text") << BARCODE_QRCODE << "" << ZINT_ERROR_INVALID_DATA << "Error 778: No input data (segment 0 empty)" << 0 << 0; + QTest::newRow("BARCODE_QRCODE no text") << BARCODE_QRCODE << "" << ZINT_ERROR_INVALID_DATA << "Error 778: No input data (segment 0 empty)" << 0 << 0 << 0.0f << 0.0f; } } @@ -398,6 +410,8 @@ private slots: QFETCH(QString, error_message); QFETCH(int, encodedWidth); QFETCH(int, encodedRows); + QFETCH(float, vectorWidth); + QFETCH(float, vectorHeight); bc.setSymbol(symbology); bc.setText(text); @@ -416,6 +430,8 @@ private slots: QCOMPARE(bc.hasErrors(), getError != 0); QCOMPARE(bc.encodedWidth(), encodedWidth); QCOMPARE(bc.encodedRows(), encodedRows); + QCOMPARE(bc.vectorWidth(), vectorWidth); + QCOMPARE(bc.vectorHeight(), vectorHeight); if (getError) { QCOMPARE(spyEncoded.count(), 0); @@ -476,6 +492,7 @@ private slots: QTest::addColumn("option2"); QTest::addColumn("option3"); QTest::addColumn("scale"); + QTest::addColumn("dpmm"); QTest::addColumn("dotty"); QTest::addColumn("dotSize"); QTest::addColumn("guardDescent"); @@ -503,341 +520,403 @@ private slots: QTest::addColumn("warnLevel"); QTest::addColumn("debug"); + QTest::addColumn("xdimdp_xdim"); + QTest::addColumn("xdimdp_xdim_units"); + QTest::addColumn("xdimdp_resolution"); + QTest::addColumn("xdimdp_resolution_units"); + QTest::addColumn("xdimdp_filetype"); + QTest::addColumn("xdimdp_filetype_maxicode"); + QTest::addColumn("expected_cmd"); QTest::addColumn("expected_win"); QTest::addColumn("expected_longOptOnly"); QTest::addColumn("expected_barcodeNames"); QTest::addColumn("expected_noexe"); + QTest::addColumn("expected_xdimdp"); QTest::newRow("BARCODE_AUSPOST") << true << 0.0f << "" << BARCODE_AUSPOST << DATA_MODE // symbology-inputMode << "12345678" << "" // text-primary - << 30.0f << -1 << 0 << 0 << 1.0f << false << 0.8f // height-dotSize + << 30.0f << -1 << 0 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 63 --binary --compliantheight -d '12345678'" << "zint.exe -b 63 --binary --compliantheight -d \"12345678\"" << "zint --barcode=63 --binary --compliantheight --data='12345678'" << "zint -b AUSPOST --binary --compliantheight -d '12345678'" - << "zint -b 63 --binary --compliantheight -d \"12345678\""; + << "zint -b 63 --binary --compliantheight -d \"12345678\"" + << ""; QTest::newRow("BARCODE_AZTEC") << false << 0.0f << "" << BARCODE_AZTEC << UNICODE_MODE // symbology-inputMode << "12345678Ж0%var%" << "" // text-primary - << 0.0f << 1 << 0 << 0 << 4.0f << true << 0.9f // height-dotSize + << 0.0f << 1 << 0 << 0 << 4.0f << 0.0f << true << 0.9f // height-dotSize << 5.0f << 2 << 1 << "as\"dfa'sdf" << QColor(Qt::blue) << QColor(Qt::white) // guardDescent-bgColor << true << 0 << 0 << 2 << 3 << 0 // cmyk-fontSetting << true << false << false << false << false << 0 // showText-rotateAngle << 7 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 92 --cmyk --eci=7 -d '12345678Ж0%var%' --dotsize=0.9 --dotty --fg=0000FF --scale=4" " --secure=1 --structapp='1,2,as\"dfa'\\''sdf' --vwhitesp=3 -w 2" << "zint.exe -b 92 --cmyk --eci=7 -d \"12345678Ж0%var%\" --dotsize=0.9 --dotty --fg=0000FF --scale=4" " --secure=1 --structapp=\"1,2,as\\\"dfa'sdf\" --vwhitesp=3 -w 2" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_C25INTER") << true << 0.0f << "" << BARCODE_C25INTER << UNICODE_MODE // symbology-inputMode << "12345" << "" // text-primary - << 0.0f << -1 << 2 << 0 << 1.0f << false << 0.8f // height-dotSize + << 0.0f << -1 << 2 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << SMALL_TEXT // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 3 --compliantheight -d '12345' --small --vers=2" << "zint.exe -b 3 --compliantheight -d \"12345\" --small --vers=2" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_CHANNEL") << false << 0.0f << "" << BARCODE_CHANNEL << UNICODE_MODE // symbology-inputMode << "453678" << "" // text-primary - << 19.7f << -1 << 7 << 0 << 1.0f << false << 0.8f // height-dotSize + << 19.7f << -1 << 7 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(255, 255, 255, 0) // guardDescent-bgColor << false << 1 << 2 << 0 << 0 << BOLD_TEXT // cmyk-fontSetting << true << false << true << false << false << 90 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << true // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 140 --bind --bold --border=2 -d '453678' --height=19.7 --nobackground --quietzones" " --rotate=90 --verbose --vers=7" << "zint.exe -b 140 --bind --bold --border=2 -d \"453678\" --height=19.7 --nobackground --quietzones" " --rotate=90 --verbose --vers=7" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_GS1_128_CC") << false << 0.0f << "" << BARCODE_GS1_128_CC << UNICODE_MODE // symbology-inputMode << "[01]12345678901231[15]121212" << "[11]901222[99]ABCDE" // text-primary - << 71.142f << 3 << 0 << 0 << 3.5f << false << 0.8f // height-dotSize + << 71.142f << 3 << 0 << 0 << 3.5f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << false << false << true << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 131 --compliantheight -d '[11]901222[99]ABCDE' --height=71.142 --mode=3 --notext" " --primary='[01]12345678901231[15]121212' --quietzones --scale=3.5" << "zint.exe -b 131 --compliantheight -d \"[11]901222[99]ABCDE\" --height=71.142 --mode=3 --notext" " --primary=\"[01]12345678901231[15]121212\" --quietzones --scale=3.5" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_CODE16K") << false << 11.7f << "" << BARCODE_CODE16K << (UNICODE_MODE | HEIGHTPERROW_MODE) // symbology-inputMode << "12345678901234567890123456789012" << "" // text-primary - << 0.0f << 4 << 0 << 2 << 1.0f << false << 0.8f // height-dotSize + << 0.0f << 4 << 0 << 2 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 1 << 1 << 0 << 0 << SMALL_TEXT // cmyk-fontSetting << true << false << false << true << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 23 --compliantheight -d '12345678901234567890123456789012'" " --height=11.7 --heightperrow --noquietzones --rows=4 --separator=2 --small" << "zint.exe -b 23 --compliantheight -d \"12345678901234567890123456789012\"" " --height=11.7 --heightperrow --noquietzones --rows=4 --separator=2 --small" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_CODE49") << true << 0.0f << "" << BARCODE_CODE49 << UNICODE_MODE // symbology-inputMode << "12345678901234567890" << "" // text-primary - << 30.0f << -1 << 0 << 0 << 1.0f << false << 0.8f // height-dotSize + << 30.0f << -1 << 0 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 24 --compliantheight -d '12345678901234567890'" << "zint.exe -b 24 --compliantheight -d \"12345678901234567890\"" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_CODABLOCKF") << true << 0.0f << "" << BARCODE_CODABLOCKF << (DATA_MODE | ESCAPE_MODE) // symbology-inputMode << "T\\n\\xA0t\\\"" << "" // text-primary - << 0.0f << 2 << 5 << 3 << 3.0f << false << 0.8f // height-dotSize + << 0.0f << 2 << 5 << 3 << 3.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 2 << 4 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << true << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 74 --binary --border=4 --box --cols=5 --compliantheight -d 'T\\n\\xA0t\\\"' --esc --init" " --rows=2 --scale=3 --separator=3" << "zint.exe -b 74 --binary --border=4 --box --cols=5 --compliantheight -d \"T\\n\\xA0t\\\\\"\" --esc --init" " --rows=2 --scale=3 --separator=3" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_DAFT") << false << 0.0f << "" << BARCODE_DAFT << UNICODE_MODE // symbology-inputMode << "daft" << "" // text-primary - << 9.2f << -1 << 251 << 0 << 1.0f << false << 0.7f // height-dotSize + << 9.2f << -1 << 251 << 0 << 1.0f << 0.0f << false << 0.7f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(0x30, 0x31, 0x32, 0x33) << QColor(0xBF, 0xBE, 0xBD, 0xBC) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 93 --bg=BFBEBDBC -d 'daft' --fg=30313233 --height=9.2 --vers=251" << "zint.exe -b 93 --bg=BFBEBDBC -d \"daft\" --fg=30313233 --height=9.2 --vers=251" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_DATAMATRIX") << true << 0.0f << "" << BARCODE_DATAMATRIX << GS1_MODE // symbology-inputMode << "[20]12" << "" // text-primary - << 0.0f << -1 << 0 << DM_SQUARE << 1.0f << false << 0.7f // height-dotSize + << 0.0f << -1 << 0 << DM_SQUARE << 1.0f << 0.0f << false << 0.7f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << true << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 71 -d '[20]12' --gs1 --gssep --square" << "zint.exe -b 71 -d \"[20]12\" --gs1 --gssep --square" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_DATAMATRIX") << false << 0.0f << "" << BARCODE_DATAMATRIX << (DATA_MODE | ESCAPE_MODE | FAST_MODE) // symbology-inputMode << "ABCDEFGH\\x01I" << "" // text-primary - << 0.0f << -1 << 0 << 0 << 1.0f << false << 0.7f // height-dotSize + << 0.0f << -1 << 0 << 0 << 1.0f << 0.0f << false << 0.7f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 71 --binary -d 'ABCDEFGH\\x01I' --esc --fast" << "zint.exe -b 71 --binary -d \"ABCDEFGH\\x01I\" --esc --fast" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_DBAR_EXPSTK_CC") << false << 40.8f << "" << BARCODE_DBAR_EXPSTK_CC << (DATA_MODE | HEIGHTPERROW_MODE) // symbology-inputMode << "[91]ABCDEFGHIJKL" << "[11]901222[99]ABCDE" // text-primary - << 0.0f << -1 << 0 << 2 << 1.0f << true << 0.9f // height-dotSize + << 0.0f << -1 << 0 << 2 << 1.0f << 0.0f << true << 0.9f // height-dotSize << 3.0f << 2 << 1 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 139 --binary --compliantheight -d '[11]901222[99]ABCDE' --height=40.8 --heightperrow" " --primary='[91]ABCDEFGHIJKL' --rows=2" << "zint.exe -b 139 --binary --compliantheight -d \"[11]901222[99]ABCDE\" --height=40.8 --heightperrow" " --primary=\"[91]ABCDEFGHIJKL\" --rows=2" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_DOTCODE") << false << 1.0f << "" << BARCODE_DOTCODE << GS1_MODE // symbology-inputMode << "[20]01" << "" // text-primary - << 30.0f << -1 << 8 << ((0 + 1) << 8) << 1.0f << false << 0.7f // height-dotSize + << 30.0f << -1 << 8 << ((0 + 1) << 8) << 1.0f << 0.0f << false << 0.7f // height-dotSize << 0.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 115 --cols=8 -d '[20]01' --dotsize=0.7 --gs1 --mask=0" << "zint.exe -b 115 --cols=8 -d \"[20]01\" --dotsize=0.7 --gs1 --mask=0" - << "" << "" << ""; + << "" << "" << "" << ""; + + QTest::newRow("BARCODE_DOTCODE") << false << 1.0f << "" + << BARCODE_DOTCODE << GS1_MODE // symbology-inputMode + << "[20]01" << "" // text-primary + << 30.0f << -1 << 8 << ((0 + 1) << 8) << 1.0f << 0.0f << false << 0.7f // height-dotSize + << 0.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor + << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting + << true << false << false << false << true << 0 // showText-rotateAngle + << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp + << "zint -b 115 --cols=8 -d '[20]01' --dotsize=0.7 --gs1 --mask=0" + << "zint.exe -b 115 --cols=8 -d \"[20]01\" --dotsize=0.7 --gs1 --mask=0" + << "" << "" << "" << ""; + + QTest::newRow("BARCODE_DPD") << true << 0.0f << "" + << BARCODE_DPD << UNICODE_MODE // symbology-inputMode + << "1234567890123456789012345678" << "" // text-primary + << 0.0f << -1 << 0 << 0 << 4.5f << 24.0f << true << 0.8f // height-dotSize + << 0.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor + << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting + << true << false << false << false << true << 0 // showText-rotateAngle + << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.375 << 0 << 600 << 1 << 0 << 0 // xdimdp + << "zint -b 96 --compliantheight -d '1234567890123456789012345678' --scalexdimdp=0.375,24" + << "zint.exe -b 96 --compliantheight -d \"1234567890123456789012345678\" --scalexdimdp=0.375,24" + << "" << "" << "" + << "zint -b 96 --compliantheight -d '1234567890123456789012345678' --scalexdimdp=0.375mm,600dpi"; QTest::newRow("BARCODE_EANX") << true << 0.0f << "" << BARCODE_EANX << UNICODE_MODE // symbology-inputMode << "123456789012+12" << "" // text-primary - << 0.0f << -1 << 8 << 0 << 1.0f << true << 0.8f // height-dotSize + << 0.0f << -1 << 8 << 0 << 1.0f << 0.0f << true << 0.8f // height-dotSize << 0.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 13 --addongap=8 --compliantheight -d '123456789012+12' --guarddescent=0" << "zint.exe -b 13 --addongap=8 --compliantheight -d \"123456789012+12\" --guarddescent=0" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_GRIDMATRIX") << false << 0.0f << "" << BARCODE_GRIDMATRIX << UNICODE_MODE // symbology-inputMode << "Your Data Here!" << "" // text-primary - << 0.0f << 1 << 5 << 0 << 0.5f << false << 0.8f // height-dotSize + << 0.0f << 1 << 5 << 0 << 0.5f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << true << false << true << 270 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 142 -d 'Your Data Here!' --quietzones --rotate=270 --scale=0.5 --secure=1 --vers=5" << "zint.exe -b 142 -d \"Your Data Here!\" --quietzones --rotate=270 --scale=0.5 --secure=1 --vers=5" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_HANXIN") << false << 0.0f << "" << BARCODE_HANXIN << (UNICODE_MODE | ESCAPE_MODE) // symbology-inputMode << "éβÿ啊\\e\"'" << "" // text-primary - << 30.0f << 2 << 5 << ((0 + 1) << 8) << 1.0f << false << 0.8f // height-dotSize + << 30.0f << 2 << 5 << ((0 + 1) << 8) << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 29 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 116 --eci=29 -d 'éβÿ啊\\e\"'\\''' --esc --mask=0 --secure=2 --vers=5" << "zint.exe -b 116 --eci=29 -d \"éβÿ啊\\e\\\"'\" --esc --mask=0 --secure=2 --vers=5" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_HIBC_DM") << false << 10.0f << "" << BARCODE_HIBC_DM << UNICODE_MODE // symbology-inputMode << "1234" << "" // text-primary - << 0.0f << -1 << 8 << DM_DMRE << 1.0f << false << 0.7f // height-dotSize + << 0.0f << -1 << 8 << DM_DMRE << 1.0f << 0.0f << false << 0.7f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << true << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 102 -d '1234' --dmre --vers=8" << "zint.exe -b 102 -d \"1234\" --dmre --vers=8" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_HIBC_PDF") << false << 0.0f << "" << BARCODE_HIBC_PDF << (DATA_MODE | HEIGHTPERROW_MODE) // symbology-inputMode << "TEXT" << "" // text-primary - << 3.5f << 3 << 4 << 10 << 10.0f << false << 0.8f // height-dotSize + << 3.5f << 3 << 4 << 10 << 10.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 2 << 1 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << true << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 106 --binary --cols=4 -d 'TEXT' --height=3.5 --heightperrow --quietzones" " --rows=10 --scale=10 --secure=3 --structapp=1,2" << "zint.exe -b 106 --binary --cols=4 -d \"TEXT\" --height=3.5 --heightperrow --quietzones" " --rows=10 --scale=10 --secure=3 --structapp=1,2" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_ITF14") << true << 0.0f << "" << BARCODE_ITF14 << UNICODE_MODE // symbology-inputMode << "9212320967145" << "" // text-primary - << 30.0f << -1 << 0 << 0 << 1.0f << false << 0.8f // height-dotSize + << 30.0f << -1 << 0 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 89 --compliantheight -d '9212320967145'" << "zint.exe -b 89 --compliantheight -d \"9212320967145\"" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_ITF14") << true << 0.0f << "" << BARCODE_ITF14 << UNICODE_MODE // symbology-inputMode << "9212320967145" << "" // text-primary - << 30.0f << -1 << 0 << 0 << 1.0f << false << 0.8f // height-dotSize + << 30.0f << -1 << 0 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 1 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 89 --border=1 --compliantheight -d '9212320967145'" << "zint.exe -b 89 --border=1 --compliantheight -d \"9212320967145\"" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_MAXICODE") << true << 0.0f << "" << BARCODE_MAXICODE << (UNICODE_MODE | ESCAPE_MODE) // symbology-inputMode << "152382802840001" << "1Z00004951\\GUPSN\\G06X610\\G159\\G1234567\\G1/1\\G\\GY\\G1 MAIN ST\\GTOWN\\GNY\\R\\E" // text-primary - << 0.0f << -1 << (96 + 1) << 0 << 2.5f << false << 0.8f // height-dotSize + << 0.0f << -1 << (96 + 1) << 0 << 2.5f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << true << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 57 -d '1Z00004951\\GUPSN\\G06X610\\G159\\G1234567\\G1/1\\G\\GY\\G1 MAIN ST\\GTOWN\\GNY\\R\\E'" " --esc --primary='152382802840001' --quietzones --scale=2.5 --scmvv=96" << "zint.exe -b 57 -d \"1Z00004951\\GUPSN\\G06X610\\G159\\G1234567\\G1/1\\G\\GY\\G1 MAIN ST\\GTOWN\\GNY\\R\\E\"" " --esc --primary=\"152382802840001\" --quietzones --scale=2.5 --scmvv=96" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_MICROQR") << false << 0.0f << "" << BARCODE_MICROQR << UNICODE_MODE // symbology-inputMode << "1234" << "" // text-primary - << 30.0f << 2 << 3 << (ZINT_FULL_MULTIBYTE | (3 + 1) << 8) << 1.0f << false << 0.8f // height-dotSize + << 30.0f << 2 << 3 << (ZINT_FULL_MULTIBYTE | (3 + 1) << 8) << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 97 -d '1234' --fullmultibyte --mask=3 --secure=2 --vers=3" << "zint.exe -b 97 -d \"1234\" --fullmultibyte --mask=3 --secure=2 --vers=3" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_QRCODE") << true << 0.0f << "" << BARCODE_QRCODE << GS1_MODE // symbology-inputMode << "(01)12" << "" // text-primary - << 0.0f << 1 << 5 << (ZINT_FULL_MULTIBYTE | (0 + 1) << 8) << 1.0f << false << 0.8f // height-dotSize + << 0.0f << 1 << 5 << (ZINT_FULL_MULTIBYTE | (0 + 1) << 8) << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << true << false << true << 0 // showText-rotateAngle << 0 << true << true << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 58 -d '(01)12' --fullmultibyte --gs1 --gs1parens --gs1nocheck --mask=0 --quietzones" " --secure=1 --vers=5" << "zint.exe -b 58 -d \"(01)12\" --fullmultibyte --gs1 --gs1parens --gs1nocheck --mask=0 --quietzones" " --secure=1 --vers=5" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_RMQR") << true << 0.0f << "" << BARCODE_RMQR << UNICODE_MODE // symbology-inputMode << "テ" << "" // text-primary - << 30.0f << -1 << 8 << 0 << 1.0f << false << 0.8f // height-dotSize + << 30.0f << -1 << 8 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 180 // showText-rotateAngle << 20 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 145 --eci=20 -d 'テ' --rotate=180 --vers=8" << "zint.exe -b 145 --eci=20 -d \"テ\" --rotate=180 --vers=8" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_ULTRA") << false << 0.0f << "" << BARCODE_ULTRA << (GS1_MODE | GS1PARENS_MODE | GS1NOCHECK_MODE) // symbology-inputMode << "(01)1" << "" // text-primary - << 0.0f << 6 << 2 << 0 << 1.0f << true << 0.8f // height-dotSize + << 0.0f << 6 << 2 << 0 << 1.0f << 0.0f << true << 0.8f // height-dotSize << 5.0f << 2 << 1 << "4" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 144 -d '(01)1' --gs1 --gs1parens --gs1nocheck --secure=6 --structapp='1,2,4' --vers=2" << "zint.exe -b 144 -d \"(01)1\" --gs1 --gs1parens --gs1nocheck --secure=6 --structapp=\"1,2,4\" --vers=2" - << "" << "" << ""; + << "" << "" << "" << ""; QTest::newRow("BARCODE_UPCE_CC") << true << 0.0f << "out.svg" << BARCODE_UPCE_CC << UNICODE_MODE // symbology-inputMode << "12345670+1234" << "[11]901222[99]ABCDE" // text-primary - << 0.0f << -1 << 0 << 0 << 1.0f << false << 0.8f // height-dotSize + << 0.0f << -1 << 0 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 6.5f << 0 << 0 << "" << QColor(0xEF, 0x29, 0x29) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << (BOLD_TEXT | SMALL_TEXT) // cmyk-fontSetting << true << false << false << true << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_FAIL_ALL << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 136 --bold --compliantheight -d '[11]901222[99]ABCDE' --fg=EF2929 --guarddescent=6.5" " --noquietzones -o 'out.svg' --primary='12345670+1234' --small --werror" << "zint.exe -b 136 --bold --compliantheight -d \"[11]901222[99]ABCDE\" --fg=EF2929 --guarddescent=6.5" @@ -847,19 +926,21 @@ private slots: << "zint -b UPCE_CC --bold --compliantheight -d '[11]901222[99]ABCDE' --fg=EF2929 --guarddescent=6.5" " --noquietzones -o 'out.svg' --primary='12345670+1234' --small --werror" << "zint -b 136 --bold --compliantheight -d \"[11]901222[99]ABCDE\" --fg=EF2929 --guarddescent=6.5" - " --noquietzones -o \"out.svg\" --primary=\"12345670+1234\" --small --werror"; + " --noquietzones -o \"out.svg\" --primary=\"12345670+1234\" --small --werror" + << ""; QTest::newRow("BARCODE_VIN") << false << 2.0f << "" << BARCODE_VIN << UNICODE_MODE // symbology-inputMode << "12345678701234567" << "" // text-primary - << 20.0f << -1 << 1 << 0 << 1.0f << false << 0.8f // height-dotSize + << 20.0f << -1 << 1 << 0 << 1.0f << 0.0f << false << 0.8f // height-dotSize << 5.0f << 0 << 0 << "" << QColor(Qt::black) << QColor(Qt::white) // guardDescent-bgColor << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 0 << false << false << false << WARN_DEFAULT << false // eci-debug + << 0.0 << 0 << 0 << 0 << 0 << 0 // xdimdp << "zint -b 73 -d '12345678701234567' --height=20 --vers=1" << "zint.exe -b 73 -d \"12345678701234567\" --height=20 --vers=1" - << "" << "" << ""; + << "" << "" << "" << ""; } void getAsCLITest() @@ -881,6 +962,7 @@ private slots: QFETCH(int, option2); QFETCH(int, option3); QFETCH(float, scale); + QFETCH(float, dpmm); QFETCH(bool, dotty); QFETCH(float, dotSize); QFETCH(float, guardDescent); @@ -908,11 +990,19 @@ private slots: QFETCH(int, warnLevel); QFETCH(bool, debug); + QFETCH(double, xdimdp_xdim); + QFETCH(int, xdimdp_xdim_units); + QFETCH(int, xdimdp_resolution); + QFETCH(int, xdimdp_resolution_units); + QFETCH(int, xdimdp_filetype); + QFETCH(int, xdimdp_filetype_maxicode); + QFETCH(QString, expected_cmd); QFETCH(QString, expected_win); QFETCH(QString, expected_longOptOnly); QFETCH(QString, expected_barcodeNames); QFETCH(QString, expected_noexe); + QFETCH(QString, expected_xdimdp); bc.setSymbol(symbology); bc.setInputMode(inputMode); @@ -927,6 +1017,7 @@ private slots: bc.setOption2(option2); bc.setOption3(option3); bc.setScale(scale); + bc.setDPMM(dpmm); bc.setDotty(dotty); bc.setDotSize(dotSize); bc.setGuardDescent(guardDescent); @@ -977,6 +1068,16 @@ private slots: autoHeight, heightPerRow, outfile); QCOMPARE(cmd, expected_noexe); } + + if (xdimdp_xdim) { + struct Zint::QZintXdimDpVars vars = { + xdimdp_xdim, xdimdp_xdim_units, xdimdp_resolution, xdimdp_resolution_units, xdimdp_filetype, + xdimdp_filetype_maxicode, 1 /*set*/ + }; + cmd = bc.getAsCLI(false /*win*/, false /*longOptOnly*/, false /*barcodeNames*/, false /*noEXE*/, + autoHeight, heightPerRow, outfile, &vars); + QCOMPARE(cmd, expected_xdimdp); + } } void getAsCLISegsTest() @@ -1017,7 +1118,7 @@ private slots: QCOMPARE(cmd, expected_win); } - void qZintAndLibZintEqual_data() + void qZintAndLibZintEqualTest_data() { QTest::addColumn("symbology"); QTest::addColumn("rotateAngles"); @@ -1030,7 +1131,7 @@ private slots: QTest::newRow("symbology=BARCODE_QRCODE rotateAngles=270 text=Hello%20World") << BARCODE_QRCODE << 270 << "Hello%20World"; } - void qZintAndLibZintEqual() + void qZintAndLibZintEqualTest() { QFETCH(int, symbology); QFETCH(int, rotateAngles); @@ -1064,6 +1165,25 @@ private slots: QFile::remove(fileNameForLibZint); QFile::remove(fileNameForQZint); } + + void barcodeNameTest_data() + { + QTest::addColumn("symbology"); + QTest::addColumn("expected_name"); + + QTest::newRow("BARCODE_MAXICODE") << BARCODE_MAXICODE << "BARCODE_MAXICODE"; + QTest::newRow("BARCODE_CODE128AB") << BARCODE_CODE128AB << "BARCODE_CODE128AB"; + QTest::newRow("BARCODE_CODE128B") << BARCODE_CODE128B << "BARCODE_CODE128AB"; + } + + void barcodeNameTest() + { + QFETCH(int, symbology); + QFETCH(QString, expected_name); + + QString name = Zint::QZint::barcodeName(symbology); + QCOMPARE(name, expected_name); + } }; QTEST_MAIN(TestQZint) diff --git a/backend_tcl/configure.in b/backend_tcl/configure.in index 89df5653..43763cfd 100644 --- a/backend_tcl/configure.in +++ b/backend_tcl/configure.in @@ -14,7 +14,7 @@ # so you can encode the package version directly into the source files. #----------------------------------------------------------------------- -AC_INIT([zint], [2.11.1]) +AC_INIT([zint],[2.11.1]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. @@ -224,4 +224,5 @@ case ${TK_DEFS} in ;; esac -AC_OUTPUT([Makefile]) +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/backend_tcl/demo/demo.tcl b/backend_tcl/demo/demo.tcl index b61ce7c1..96c1a4cb 100644 --- a/backend_tcl/demo/demo.tcl +++ b/backend_tcl/demo/demo.tcl @@ -31,29 +31,29 @@ proc Generate {} { if {[catch {zint encode [.e get] ::zintimg -barcode [.c get] {*}[.o get]} e]} { tk_messageBox -message $e -title "Zint error" } else { - set w [image width ::zintimg] - set h [image height ::zintimg] - set lw [winfo width .l] - set lh [winfo height .l] - set sx [expr {int(1.0 * $lw / $w)}] - set sy [expr {int(1.0 * $lh / $h)}] - if {$sy < $sx} { - set sx $sy - } - if {$sx <= 0} { - set sx [expr {1.1 * $lw / $w}] - set sy [expr {1.1 * $lh / $h}] - if {$sy < $sx} { - set sx $sy - } - } - ::zintimg blank - ::zintimg configure -width 1 -height 1 - ::zintimg blank - ::zintimg configure -width 0 -height 0 - catch { - zint encode [.e get] ::zintimg -barcode [.c get] -scale $sx {*}[.o get] - } + set w [image width ::zintimg] + set h [image height ::zintimg] + set lw [winfo width .l] + set lh [winfo height .l] + set sx [expr {int(1.0 * $lw / $w)}] + set sy [expr {int(1.0 * $lh / $h)}] + if {$sy < $sx} { + set sx $sy + } + if {$sx <= 0} { + set sx [expr {1.1 * $lw / $w}] + set sy [expr {1.1 * $lh / $h}] + if {$sy < $sx} { + set sx $sy + } + } + ::zintimg blank + ::zintimg configure -width 1 -height 1 + ::zintimg blank + ::zintimg configure -width 0 -height 0 + catch { + zint encode [.e get] ::zintimg -barcode [.c get] -scale $sx {*}[.o get] + } } } pack [label .l -image ::zintimg -bg white] -side top -fill both -expand 1 \ diff --git a/backend_tcl/zint.c b/backend_tcl/zint.c index a2538504..c3ed919c 100644 --- a/backend_tcl/zint.c +++ b/backend_tcl/zint.c @@ -28,6 +28,7 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* SPDX-License-Identifier: BSD-3-Clause */ /* History @@ -151,6 +152,11 @@ - Added BC412 2022-08-20 GL - Added CEPNet +2022-11-10 GL +- Added -bindtop option +2022-12-02 GL +- Added -scalexdimdp option +- Renamed CODE128B to CODE128AB */ #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) @@ -258,7 +264,7 @@ static const char *s_code_list[] = { "PDF417Compact", "MaxiCode", "QR", - "Code128B", + "Code128AB", "AusPost", "AusReply", "AusRoute", @@ -358,7 +364,7 @@ static const int s_code_number[] = { BARCODE_PDF417COMP, BARCODE_MAXICODE, BARCODE_QRCODE, - BARCODE_CODE128B, + BARCODE_CODE128AB, BARCODE_AUSPOST, BARCODE_AUSREPLY, BARCODE_AUSROUTE, @@ -522,6 +528,7 @@ static const char help_message[] = "zint tcl(stub,obj) dll\n" " -rotate angle: Image rotation by 0,90 or 270 degrees\n" " -rows integer: Codablock F, PDF417: number of rows\n" " -scale double: Scale the image to this factor\n" + " -scalexdimdp {xdim ?resolution?}: Scale with X-dimension mm, resolution dpmm\n" " -scmvv integer: Prefix SCM with [)>\\R01\\Gvv (vv is integer) (MaxiCode)\n" " -secure integer: EC Level (Aztec, GridMatrix, HanXin, PDF417, QR, UltraCode)\n" " -segN {eci data}: Set the ECI & data content for segment N where N is 1 to 9\n" @@ -734,6 +741,8 @@ static int Encode(Tcl_Interp *interp, int objc, Tcl_Obj *pSegDataObjs[10] = {0}; Tcl_DString segInputs[10]; struct zint_seg segs[10]; + double xdim = 0.0; + double resolution = 0.0; /*------------------------------------------------------------------------*/ /* >> Check if at least data and object is given and a pair number of */ /* >> options */ @@ -765,7 +774,7 @@ static int Encode(Tcl_Interp *interp, int objc, "-gs1nocheck", "-gs1parens", "-gssep", "-guarddescent", "-height", "-heightperrow", "-init", "-mask", "-mode", "-nobackground", "-noquietzones", "-notext", "-primary", "-quietzones", - "-reverse", "-rotate", "-rows", "-scale", "-scmvv", "-secure", + "-reverse", "-rotate", "-rows", "-scale", "-scalexdimdp", "-scmvv", "-secure", "-seg1", "-seg2", "-seg3", "-seg4", "-seg5", "-seg6", "-seg7", "-seg8", "-seg9", "-separator", "-smalltext", "-square", "-structapp", "-to", "-vers", "-vwhitesp", "-werror", "-whitesp", @@ -777,7 +786,7 @@ static int Encode(Tcl_Interp *interp, int objc, iGS1NoCheck, iGS1Parens, iGSSep, iGuardDescent, iHeight, iHeightPerRow, iInit, iMask, iMode, iNoBackground, iNoQuietZones, iNoText, iPrimary, iQuietZones, - iReverse, iRotate, iRows, iScale, iSCMvv, iSecure, + iReverse, iRotate, iRows, iScale, iScaleXdimDp, iSCMvv, iSecure, iSeg1, iSeg2, iSeg3, iSeg4, iSeg5, iSeg6, iSeg7, iSeg8, iSeg9, iSeparator, iSmallText, iSquare, iStructApp, iTo, iVers, iVWhiteSp, iWError, iWhiteSp @@ -1100,6 +1109,42 @@ static int Encode(Tcl_Interp *interp, int objc, my_symbol->scale = (float)doubleValue; } break; + case iScaleXdimDp: + /* >> Decode the -scalexdimdp parameter as list of xdim ?resolution? */ + { + Tcl_Obj *poParam; + xdim = resolution = 0.0; + if (TCL_OK != Tcl_ListObjLength(interp, + objv[optionPos+1], &lStr)) + { + fError = 1; + } else if ( ! ( lStr == 1 || lStr == 2 ) ) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj( + "option -scalexdimdp not a list of 1 or 2", -1)); + fError = 1; + } else { + if (TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1], + 0, &poParam) + || TCL_OK != Tcl_GetDoubleFromObj(interp, poParam, &xdim) + || xdim < 0.0) + { + fError = 1; + } + if (!fError && lStr == 2 && ( + TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1], + 1, &poParam) + || TCL_OK != Tcl_GetDoubleFromObj(interp, poParam, &resolution) + || resolution < 0.0)) + { + fError = 1; + } + if (!fError && resolution == 0.0) { + resolution = 12.0; /* Default 12 dpmm (~300 dpi) */ + } + } + } + break; case iBorder: if (intValue < 0 || intValue > 1000) { Tcl_SetObjResult(interp, @@ -1375,6 +1420,16 @@ static int Encode(Tcl_Interp *interp, int objc, my_symbol->option_1 = rows; } } + if (resolution) { + float scale; + if (xdim == 0.0) { + xdim = ZBarcode_Default_Xdim(my_symbol->symbology); + } + scale = ZBarcode_Scale_From_XdimDp(my_symbol->symbology, (float)xdim, (float)resolution, NULL /*filetype*/); + if (scale > 0.0f) { + my_symbol->scale = scale; + } + } /*------------------------------------------------------------------------*/ /* >>> Prepare input dstring and encode it to ECI encoding*/ Tcl_DStringInit(& dsInput); diff --git a/docs/Makefile b/docs/Makefile index 2e29d327..b122be0f 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -19,19 +19,23 @@ IMAGES = \ images/zint.png \ images/zint-qt.png \ images/gui_main.png \ + images/gui_delete.png \ + images/gui_zap.png \ images/gui_menus.png \ images/gui_composite.png \ images/gui_segs.png \ images/gui_aztec.png \ images/gui_appearance.png \ + images/gui_scaling.png \ + images/gui_set_printing_scale.png \ + images/gui_black_eye.png \ + images/gui_white_eye.png \ + images/gui_swap.png \ images/gui_colour.png \ images/gui_data_dialog.png \ images/gui_sequence.png \ images/gui_export.png \ images/gui_cli_equivalent.png \ - images/gui_black_eye.png \ - images/gui_white_eye.png \ - images/gui_swap.png \ images/pdf417_heightperrow.svg \ images/code128_box.svg \ images/qrcode_box.svg \ @@ -77,7 +81,7 @@ IMAGES = \ images/codabar.svg \ images/pharma.svg \ images/code128.svg \ - images/code128b.svg \ + images/code128ab.svg \ images/gs1_128.svg \ images/ean14.svg \ images/nve18.svg \ diff --git a/docs/images/code128b.svg b/docs/images/code128ab.svg similarity index 100% rename from docs/images/code128b.svg rename to docs/images/code128ab.svg diff --git a/docs/images/dpident.svg b/docs/images/dpident.svg index 6f75fd66..4dd360ce 100644 --- a/docs/images/dpident.svg +++ b/docs/images/dpident.svg @@ -1,50 +1,50 @@ - Zint Generated Symbol - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 912320967127 + 91.23 2.096.712 7 diff --git a/docs/images/dpleit.svg b/docs/images/dpleit.svg index dae8802c..6f74ba3f 100644 --- a/docs/images/dpleit.svg +++ b/docs/images/dpleit.svg @@ -1,55 +1,55 @@ - Zint Generated Symbol - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - 92123209671456 + 92123.209.671.456 diff --git a/docs/images/gui_appearance.png b/docs/images/gui_appearance.png index eac79608..3bf525cf 100644 Binary files a/docs/images/gui_appearance.png and b/docs/images/gui_appearance.png differ diff --git a/docs/images/gui_black_eye.png b/docs/images/gui_black_eye.png index 7bbe7fa8..bd100d80 100644 Binary files a/docs/images/gui_black_eye.png and b/docs/images/gui_black_eye.png differ diff --git a/docs/images/gui_delete.png b/docs/images/gui_delete.png new file mode 100644 index 00000000..4c44d8b6 Binary files /dev/null and b/docs/images/gui_delete.png differ diff --git a/docs/images/gui_scaling.png b/docs/images/gui_scaling.png new file mode 100644 index 00000000..f008bcf2 Binary files /dev/null and b/docs/images/gui_scaling.png differ diff --git a/docs/images/gui_set_printing_scale.png b/docs/images/gui_set_printing_scale.png new file mode 100644 index 00000000..857dfdbd Binary files /dev/null and b/docs/images/gui_set_printing_scale.png differ diff --git a/docs/images/gui_swap.png b/docs/images/gui_swap.png index 38236ffc..064a693c 100644 Binary files a/docs/images/gui_swap.png and b/docs/images/gui_swap.png differ diff --git a/docs/images/gui_white_eye.png b/docs/images/gui_white_eye.png index 2ef3f877..2a7a197b 100644 Binary files a/docs/images/gui_white_eye.png and b/docs/images/gui_white_eye.png differ diff --git a/docs/images/gui_zap.png b/docs/images/gui_zap.png new file mode 100644 index 00000000..ee8920ad Binary files /dev/null and b/docs/images/gui_zap.png differ diff --git a/docs/manual.pmd b/docs/manual.pmd index 940fedd8..7ef9370f 100644 --- a/docs/manual.pmd +++ b/docs/manual.pmd @@ -1,6 +1,6 @@ % Zint Barcode Generator and Zint Barcode Studio User Manual % Version 2.11.1.9 -% November 2022 +% December 2022 # 1. Introduction @@ -250,6 +250,17 @@ only show barcodes in the drop-down whose names contain the word `"mail"`. Each word entered will match. So typing `"mail post"` will show barcodes whose names contain `"mail"` or `"post"` (or both). +The ellipsis button `"..."` to the right of the data text box invokes the Data +Dialog - see [3.6 Data Dialog] for details. The delete button +![delete](images/gui_delete.png) next to it will clear the data text box and +the ECI (Extended Channel Interpretations) drop-down if set. + +To set the barcode as a Programming Initialisation symbol click the +`"Reader Init"` checkbox. The `"1234.."` button to its right invokes the +Sequence Dialog - see [3.7 Sequence Dialog]. The zap button +![zap](images/gui_zap.png) will clear all data and reset all settings for the +barcode to defaults. + The `"BMP"` and `"SVG"` buttons at the bottom will copy the image to the clipboard in BMP format and SVG format respectively. Further copy-to-clipboard formats are available by clicking the `"Menu"` button, along with @@ -295,23 +306,40 @@ part of a Structured Append sequence of symbols. ![Zint Barcode Studio showing Appearance tab options](images/gui_appearance.png) The Appearance tab can be used to adjust the dimensions and other properties of -the symbol. The `"Height"` value affects the height of symbologies which do not -have a fixed width-to-height ratio, i.e. those other than matrix symbologies. -Boundary bars (`"Border Type"`) can be added and adjusted (`"Border Width"`) and -the size of the saved image (`"Printing Scale"`) can be specified. +the symbol. -## 3.6 Colour Dialog +The `"Height"` value affects the height of symbologies which do not have a fixed +width-to-height ratio, i.e. those other than matrix symbologies. For such +symbologies the `"Automatic Height"` checkbox will be enabled - uncheck this to +manually adjust the height. The `"Compliant Height"` checkbox applies to +symbologies that define a standard height - see [4.4 Adjusting Height]. + +Boundary bars can be added with the `"Border Type"` drop-down and their size +adjusted with `"Border Width"`, and whitespace can be adjusted both horizontally +(first spinbox) and vertically (second spinbox), and also through the +`"Quiet Zones"` checkbox if standard quiet zones are defined for the symbology. + +The size of the saved image can be specified with `"Printing Scale"`, and also +by clicking the ![scaling](images/gui_scaling.png) icon to invoke the "Set +Printing Scale" dialog - see [4.9 Adjusting Image Size] for further details. + +![Adjusting the Print Size](images/gui_set_printing_scale.png) + +The foreground and background colours can be set either using the text boxes +which accept RRGGBBAA hexadecimal values or by clicking the foreground eye +![eye](images/gui_black_eye.png) and background eye +![eye](images/gui_white_eye.png) buttons which invoke a colour picker. ![The colour picker tool](images/gui_colour.png) -A colour dialog is used to adjust the colour of the foreground and background of -the generated image. In the Appearance tab click on the foreground eye -![eye](images/gui_black_eye.png) or background eye -![eye](images/gui_white_eye.png) button respectively. The colours can be reset -to black-on-white using the `"Reset"` button, and exchanged one for the other -using the swap ![swap](images/gui_swap.png) button next to it. +(Note that to change the colours visually, the luminence slider, the long narrow +column on the right, must be adjusted.) -## 3.7 Data Dialog +The colours can be reset to black-on-white using the `"Reset"` button, and +exchanged one for the other using the swap ![swap](images/gui_swap.png) button +next to it. + +## 3.6 Data Dialog ![Entering longer text input](images/gui_data_dialog.png) @@ -329,7 +357,7 @@ box any separate lines in the data will be escaped as `'\n'` and the carriage returns (`CR`) or `CR+LF` pairs, and behaves the same on both Windows and Unix. (For details on escape sequences, see [4.1 Inputting Data].) -## 3.8 Sequence Dialog +## 3.7 Sequence Dialog ![Creating a sequence of barcode symbols](images/gui_sequence.png) @@ -351,7 +379,7 @@ meanings as given below: Table: {#tbl:sequence_format_characters tag=": Sequence Format Characters"} -## 3.9 Export Dialog +## 3.8 Export Dialog ![Setting filenames for an exported sequence of barcode symbols](images/gui_export.png) @@ -361,7 +389,7 @@ Dialog sets the parameters for exporting a sequence of barcode images. Here you can set the filename and the output image format. Note that the symbology, colour and other formatting information are taken from the main window. -## 3.10 CLI Equivalent Dialog +## 3.9 CLI Equivalent Dialog ![CLI Equivalent Dialog](images/gui_cli_equivalent.png) @@ -510,6 +538,13 @@ for the other supported file types: zint -o there.eps -d "This Text" ``` +The filename can contain directories and sub-directories also, which will be +created if they don't already exist: + +```bash +zint -o "dir/subdir/filename.eps" -d "This Text" +``` + ## 4.3 Selecting Barcode Type Selecting which type of barcode you wish to produce (i.e. which symbology to @@ -613,7 +648,7 @@ Value 58 `BARCODE_QRCODE` QR Code - 60 `BARCODE_CODE128B` Code 128 (Subset B) + 60 `BARCODE_CODE128AB` Code 128 (Suppress subset C) 63 `BARCODE_AUSPOST` Australia Post Standard Customer @@ -929,11 +964,11 @@ The scale of the image can be altered using the `--scale` option followed by a multiple of the default X-dimension. The scale is multiplied by 2 (with the exception of MaxiCode) before being applied. The default scale is 1. -For MaxiCode, the scale is multiplied by 10 for raster output, by 20 for EMF +For MaxiCode, the scale is multiplied by 10 for raster output, by 40 for EMF vector output, and by 2 otherwise (non-EMF vector output). For raster output, the default X-dimension is 2 pixels (except for MaxiCode, see -[4.9.2 MaxiCode Raster Scaling] below). For example for PNG images a scale of 5 +[4.9.3 MaxiCode Raster Scaling] below). For example for PNG images a scale of 5 will increase the X-dimension to 10 pixels. Scales for raster output should be given in increments of 0.5, i.e. 0.5, 1, 1.5, 2, 2.5, 3, 3.5, etc., to avoid the X-dimension varying across the symbol due to interpolation. 0.5 increments are @@ -946,63 +981,73 @@ Dots]). The minimum scale for vector output is 0.1, giving a minimum X-dimension of 0.2. -The maximum scale for both raster and vector is 100. +The maximum scale for both raster and vector is 200. -### 4.9.1 Scaling Example +### 4.9.1 Scaling by X-dimension and Resolution + +An alternative way to specify the scale which takes these details into account +is to use the `--scalexdimdp` option, which has the format + +``` +--scalexdimdp=X[,R] +``` + +where `X` is the X-dimension (in mm by default) and `R` is the resolution (in +dpmm, dots per mm, by default). `R` is optional, and defaults to 12 dpmm, and +`X` may be zero, in which case it uses a symbology-specific default. The units +may be given in inches for `X` by appending `"in"`, and in dpi (dots per inch) +for `R` by appending `"dpi"`. For example + +```bash +zint -d "1234" --scalexdimdp=0.013in,300dpi +``` + +Explicit metric units may also be given by appending `"mm"` and `"dpmm"` as +appropriate, and may be mixed with U.S. units: + +```bash +zint -d "1234" --scalexdimdp=0.33mm,300dpi +``` + +### 4.9.2 Scaling Example The GS1 General Specifications Section 5.2.6.6 'Symbol dimensions at nominal size' gives an example of an EAN-13 barcode using the X-dimension of 0.33mm. To -print that example as a PNG at 12 dots per mm (dpmm), the equivalent of 300 dots -per inch (`dpi = dpmm * 25.4`), specify a scale of 2, since `0.33 * 12 = 3.96` -pixels, or 4 pixels rounding to the nearest pixel: +print that example as a PNG at 12 dpmm, the approximate equivalent of 300 dpi +(`dpi = dpmm * 25.4`), specify a scale of 2, since `0.33 * 12 = 3.96` pixels, or +4 pixels rounding to the nearest pixel: ```bash zint -b EANX -d "501234567890" --compliantheight --scale=2 ``` -This will result in output of 38.27mm x 26.08mm (WxH) at 300 dpi. The following -table shows the scale to use (in 0.5 increments) depending on the dpmm desired, -for a target X-dimension of 0.33mm: +This will result in output of 37.29mm x 25.56mm (WxH) at 12 dpmm. The same +result can be achieved using the `--scalexdimdp` option with -dpmm dpi scale ----- ---- ----- - 6 150 1 - 8 200 1.5 - 12 300 2 - 16 400 3 - 24 600 4 - 47 1200 8 - 95 2400 15.5 -189 4800 31 +```bash +zint -b EANX -d "501234567890" --compliantheight --scalexdimdp=0 +``` -Table: {#tbl:scaling_xdim_0_33mm tag=": Scaling for X-dimension 0.33mm"} +as 0.33mm is the default X-dimension for EAN, and 12 dpmm the default +resolution. -### 4.9.2 MaxiCode Raster Scaling +### 4.9.3 MaxiCode Raster Scaling For MaxiCode symbols, which use hexagons, the scale for raster output is -multiplied by 10 before being applied. The minimum scale is 0.2, so the minimum -X-dimension is 2 pixels. +multiplied by 10 before being applied. The 0.5 increment recommended for normal +raster output does not apply. + +The minimum scale is 0.2, so the minimum X-dimension is 2 pixels. However scales +below 0.5 are not recommended and may produce symbols that are not within the +following size ranges. MaxiCode symbols have fixed size ranges of 24.82mm to 27.93mm in width, and -23.71mm to 26.69mm in height, excluding quiet zones. The following table shows -the scale to use depending on the dpmm desired, with dpi equivalents: +23.71mm to 26.69mm in height, excluding quiet zones. The default X-dimension is +0.88mm. For example, to output at the default X-dimension at 600 dpi specify: -dpmm dpi scale ----- ---- ----- - 6 150 0.5 - 8 200 0.7 - 12 300 1 - 16 400 1.4 - 24 600 2.1 - 47 1200 4.1 - 95 2400 8.2 -189 4800 16.4 - -Table: {#tbl:maxicode_raster_scaling tag=": MaxiCode Raster Scaling"} - -Note that the 0.5 increment recommended for normal raster output does not apply. -Scales below 0.5 are not recommended and may produce symbols that are not within -the minimum/maximum size ranges. +```bash +zint -b MAXICODE -d "MaxiCode (19 chars)" --scalexdimdp=0,600dpi +``` ## 4.10 Input Modes @@ -1270,6 +1315,16 @@ Input Filenames Generated Table: {#tbl:batch_filename_examples tag=": Batch Filename Examples"} +The special characters can span directories also, which is useful when creating +a large number of barcodes: + +Input Filenames Generated +-------------------- ------------------------------------------------------ +`-o dir~/file~~~.svg` `dir0/file001.svg`, `dir0/file002.svg`, ... + , `dir0/file999.svg`, `dir1/file000.svg`, ... + +Table: {#tbl:batch_dir_examples tag=": Batch Directory Examples"} + ## 4.12 Direct Output The finished image files can be output directly to stdout for use as part of a @@ -1731,7 +1786,11 @@ Variable Name Type Meaning Default Value `eci` integer Extended Channel 0 (none) Interpretation code. -`dot_size` float Diameter of dots used in 4.0 / 5.0 +`dpmm` float Resolution of output in dots 0 (none) + per mm (BMP/EMF/PCX/PNG/TIF + only). + +`dot_size` float Diameter of dots used in 0.8 dotty mode. `guard_descent` float Height of guard bar 5.0 @@ -2142,7 +2201,53 @@ int main(int argc, char **argv) A maximum of 256 segments may be specified. Use of multiple segments with GS1 data is not currently supported. -## 5.12 Verifying Symbology Availability +## 5.12 Scaling Helpers + +To help with scaling the output, the following three function are available: + +```c +float ZBarcode_Default_Xdim(int symbol_id); + +float ZBarcode_Scale_From_XdimDp(int symbol_id, float x_dim_mm, float dpmm, + const char *filetype) { + +float ZBarcode_XdimDP_From_Scale(int symbol_id, float scale, + float x_dim_mm_or_dpmm, const char *filetype); +``` + +The first `ZBarcode_Default_Xdim()` returns the default X-dimension suggested by +Zint for symbology `symbol_id`. + +The second `ZBarcode_Scale_From_XdimDp()` returns the scale to use to output to +a file of type `filetype` with X-dimension `x_dim_mm` at `dpmm` dots per mm. The +given X-dimension must be non-zero and less than or equal to 10mm, however +`dpmm` may be zero and defaults to 12 dpmm, and `filetype` may be NULL or empty +in which case a GIF filetype is assumed. For raster output (BMP/GIF/PCX/PNG/TIF) +the scale is rounded to half-integer increments. + +For example: + +```c +my_symbol->symbology = BARCODE_RM4SCC; /* Royal Mail 4-State Customer Code */ +my_symbol->dpmm = 600.0f / 25.4f; /* 600 dpi */ +my_symbol->scale = ZBarcode_Scale_From_XdimDp( + my_symbol->symbology, + ZBarcode_Default_Xdim(my_symbol->symbology), + my_symbol->dpmm, "PNG"); /* 7.5 */ +``` + +The third function `ZBarcode_XdimDP_From_Scale()` is the "reverse" of +`ZBarcode_Scale_From_XdimDp()`, returning the X-dimension (in mm) or the dot +density (in dpmm) given a scale `scale`. Both `scale` and `x_dim_mm_or_dpmm` +must be non-zero. The returned value is bound to the maximum value of dpmm +(1000), so must be further bound to 10 on return if the X-dimension is sought. + +Note that the X-dimension to use is application dependent, and varies not only +due to the symbology, resolution and filetype but also due to the type of +scanner used, the intended scanning distance, and what media ("substrates") the +barcode appears on. + +## 5.13 Verifying Symbology Availability An additional function available in the API is: @@ -2180,7 +2285,7 @@ if (ZBarcode_BarcodeName(BARCODE_PDF417, name) == 0) { will print `BARCODE_PDF417`. -## 5.13 Checking Symbology Capabilities +## 5.14 Checking Symbology Capabilities It can be useful for frontend programs to know the capabilities of a symbology. This can be determined using another additional function: @@ -2246,7 +2351,7 @@ if (cap & ZINT_CAP_ECI) { } ``` -## 5.14 Zint Version +## 5.15 Zint Version Whether the Zint library linked to was built with PNG support may be determined with: @@ -2362,16 +2467,16 @@ bind or bindtop) and leaving the border width 0. ![`zint -b DPLEIT -d "9212320967145"`](images/dpleit.svg) Leitcode is based on Interleaved Code 2 of 5 and is used by Deutsche Post for -mailing purposes. Leitcode requires a 13-digit numerical input and includes a -check digit. +routing purposes. Leitcode requires a 13-digit numerical input to which Zint +adds a check digit. #### 6.1.2.8 Deutsche Post Identcode ![`zint -b DPIDENT -d "91232096712"`](images/dpident.svg) Identcode is based on Interleaved Code 2 of 5 and is used by Deutsche Post for -mailing purposes. Identcode requires an 11-digit numerical input and includes a -check digit. +identification purposes. Identcode requires an 11-digit numerical input to which +Zint adds a check digit. \clearpage @@ -2389,7 +2494,7 @@ to draw a UPC-A symbol with the data 72527270270 with an EAN-5 add-on showing the data 12345 use the command: ```bash -zint -b UPCA -d 72527270270+12345 +zint -b UPCA -d "72527270270+12345" ``` or using the API encode a data string with the + character included: @@ -2423,7 +2528,7 @@ encoding by entering a 7-digit article number starting with the digit 1. For example: ```bash -zint -b UPCE -d 1123456 +zint -b UPCE -d "1123456" ``` or @@ -2456,7 +2561,7 @@ data. In addition EAN-2 and EAN-5 add-on symbols can be added to EAN-8 and EAN-13 symbols using the + character as with UPC symbols. For example: ```bash -zint -b EANX -d 54321 +zint -b EANX -d "54321" ``` ![`zint -b EANX --compliantheight -d "54321"`](images/eanx5.svg) @@ -2464,7 +2569,7 @@ zint -b EANX -d 54321 will encode a stand-alone EAN-5, whereas ```bash -zint -b EANX -d 7432365+54321 +zint -b EANX -d "7432365+54321" ``` will encode an EAN-8 symbol with an EAN-5 add-on. As before these results can @@ -2599,7 +2704,7 @@ PZN encodes a 7-digit number to which Zint will add a modulo-11 check digit. --vers=1`](images/logmars.svg) LOGMARS (Logistics Applications of Automated Marking and Reading Symbols) is a -variation of the Code 39 symbology used by the US Department of Defense. +variation of the Code 39 symbology used by the U.S. Department of Defense. LOGMARS encodes the same character set as Standard Code 39. It does not require a check digit but a modulo-43 check digit can be added by setting `--vers=1` (API `option_2 = 1`). @@ -2669,13 +2774,16 @@ the encoding of ISO/IEC 8859-1 (non-English) characters in Code 128 symbols. The ISO/IEC 8859-1 character set is shown in Appendix [A.2 Latin Alphabet No. 1 (ISO/IEC 8859-1)]. -#### 6.1.10.2 Code 128 Subset B +#### 6.1.10.2 Code 128 Suppress Subset C (Subsets A and B only) -![`zint -b CODE128B -d "130170X178"`](images/code128b.svg) +![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg) It is sometimes advantageous to stop Code 128 from using subset mode C which -compresses numerical data. The `BARCODE_CODE128B` variant (symbology 60) -suppresses mode C in favour of mode B. +compresses numerical data. The `BARCODE_CODE128AB`[^10] variant (symbology 60) +suppresses mode C in favour of modes A and B. + +[^10]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is +still recognised. #### 6.1.10.3 GS1-128 @@ -3318,10 +3426,10 @@ these will be appended by Zint if not included in the input data. ![`zint -b USPS_IMAIL --compliantheight -d "01234567094987654321-01234"`](images/usps_imail.svg) -Also known as the OneCode barcode and used in the US by the United States Postal -Service (USPS), the Intelligent Mail system replaced the POSTNET and PLANET -symbologies in 2009. Intelligent Mail is a fixed length (65-bar) symbol which -combines routing and customer information in a single symbol. Input data +Also known as the OneCode barcode and used in the U.S. by the United States +Postal Service (USPS), the Intelligent Mail system replaced the POSTNET and +PLANET symbologies in 2009. Intelligent Mail is a fixed length (65-bar) symbol +which combines routing and customer information in a single symbol. Input data consists of a 20-digit tracking code, followed by a dash (`-`), followed by a delivery point zip-code which can be 0, 5, 9 or 11 digits in length. For example all of the following inputs are valid data entries: @@ -3375,7 +3483,7 @@ zint -b RM4SCC --compliantheight -d "W1J0TR01" --square`](images/hibc_dm.svg) Also known as Semacode this symbology was developed in 1989 by Acuity CiMatrix -in partnership with the US DoD and NASA. The symbol can encode a large amount +in partnership with the U.S. DoD and NASA. The symbol can encode a large amount of data in a small area. Data Matrix encodes characters in the Latin-1 set by default but also supports encoding in other character sets using the ECI mechanism. It can also encode GS1 data. The size of the generated symbol can @@ -3727,7 +3835,7 @@ using the `--structapp` option (see [4.16 Structured Append]) (API `structapp`). It does not support specifying an ID. MaxiCode uses a different scaling than other symbols for raster output, see -[4.9.2 MaxiCode Raster Scaling], and also for EMF vector output, when the scale +[4.9.3 MaxiCode Raster Scaling], and also for EMF vector output, when the scale is multiplied by 20 instead of 2. ### 6.6.7 Aztec Code (ISO 24778) diff --git a/docs/manual.txt b/docs/manual.txt index 7cdcae7a..855b87b4 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -1,6 +1,6 @@ Zint Barcode Generator and Zint Barcode Studio User Manual Version 2.11.1.9 -November 2022 +December 2022 ******************************************************************************* * For reference the following is a text-only version of the Zint manual, * @@ -22,11 +22,10 @@ November 2022 - 3.3 Additional ECI/Data Segments Groupbox - 3.4 Symbology-specific Tab - 3.5 Appearance Tab - - 3.6 Colour Dialog - - 3.7 Data Dialog - - 3.8 Sequence Dialog - - 3.9 Export Dialog - - 3.10 CLI Equivalent Dialog + - 3.6 Data Dialog + - 3.7 Sequence Dialog + - 3.8 Export Dialog + - 3.9 CLI Equivalent Dialog - 4. Using the Command Line - 4.1 Inputting Data - 4.2 Directing Output @@ -37,8 +36,9 @@ November 2022 - 4.7 Using Colour - 4.8 Rotating the Symbol - 4.9 Adjusting Image Size - - 4.9.1 Scaling Example - - 4.9.2 MaxiCode Raster Scaling + - 4.9.1 Scaling by X-dimension and Resolution + - 4.9.2 Scaling Example + - 4.9.3 MaxiCode Raster Scaling - 4.10 Input Modes - 4.10.1 Unicode, Data, and GS1 Modes - 4.10.2 Input Modes and ECI @@ -65,9 +65,10 @@ November 2022 - 5.9 Adjusting Other Output Options - 5.10 Setting the Input Mode - 5.11 Multiple Segments - - 5.12 Verifying Symbology Availability - - 5.13 Checking Symbology Capabilities - - 5.14 Zint Version + - 5.12 Scaling Helpers + - 5.13 Verifying Symbology Availability + - 5.14 Checking Symbology Capabilities + - 5.15 Zint Version - 6. Types of Symbology - 6.1 One-Dimensional Symbols - 6.1.1 Code 11 @@ -105,7 +106,7 @@ November 2022 - 6.1.9 Pharmacode - 6.1.10 Code 128 - 6.1.10.1 Standard Code 128 (ISO 15417) - - 6.1.10.2 Code 128 Subset B + - 6.1.10.2 Code 128 Suppress Subset C (Subsets A and B only) - 6.1.10.3 GS1-128 - 6.1.10.4 EAN-14 - 6.1.10.5 NVE-18 (SSCC-18) @@ -415,6 +416,16 @@ only show barcodes in the drop-down whose names contain the word "mail". Each word entered will match. So typing "mail post" will show barcodes whose names contain "mail" or "post" (or both). +The ellipsis button "..." to the right of the data text box invokes the Data +Dialog - see 3.6 Data Dialog for details. The delete button [delete] next to it +will clear the data text box and the ECI (Extended Channel Interpretations) +drop-down if set. + +To set the barcode as a Programming Initialisation symbol click the +"Reader Init" checkbox. The "1234.." button to its right invokes the Sequence +Dialog - see 3.7 Sequence Dialog. The zap button [zap] will clear all data and +reset all settings for the barcode to defaults. + The "BMP" and "SVG" buttons at the bottom will copy the image to the clipboard in BMP format and SVG format respectively. Further copy-to-clipboard formats are available by clicking the "Menu" button, along with "CLI Equivalent", "Save As", @@ -458,22 +469,38 @@ part of a Structured Append sequence of symbols. [Zint Barcode Studio showing Appearance tab options] The Appearance tab can be used to adjust the dimensions and other properties of -the symbol. The "Height" value affects the height of symbologies which do not -have a fixed width-to-height ratio, i.e. those other than matrix symbologies. -Boundary bars ("Border Type") can be added and adjusted ("Border Width") and the -size of the saved image ("Printing Scale") can be specified. +the symbol. -3.6 Colour Dialog +The "Height" value affects the height of symbologies which do not have a fixed +width-to-height ratio, i.e. those other than matrix symbologies. For such +symbologies the "Automatic Height" checkbox will be enabled - uncheck this to +manually adjust the height. The "Compliant Height" checkbox applies to +symbologies that define a standard height - see 4.4 Adjusting Height. + +Boundary bars can be added with the "Border Type" drop-down and their size +adjusted with "Border Width", and whitespace can be adjusted both horizontally +(first spinbox) and vertically (second spinbox), and also through the +"Quiet Zones" checkbox if standard quiet zones are defined for the symbology. + +The size of the saved image can be specified with "Printing Scale", and also by +clicking the [scaling] icon to invoke the “Set Printing Scale” dialog - see 4.9 +Adjusting Image Size for further details. + +[Adjusting the Print Size] + +The foreground and background colours can be set either using the text boxes +which accept RRGGBBAA hexadecimal values or by clicking the foreground eye [eye] +and background eye [eye] buttons which invoke a colour picker. [The colour picker tool] -A colour dialog is used to adjust the colour of the foreground and background of -the generated image. In the Appearance tab click on the foreground eye [eye] or -background eye [eye] button respectively. The colours can be reset to -black-on-white using the "Reset" button, and exchanged one for the other using -the swap [swap] button next to it. +(Note that to change the colours visually, the luminence slider, the long narrow +column on the right, must be adjusted.) -3.7 Data Dialog +The colours can be reset to black-on-white using the "Reset" button, and +exchanged one for the other using the swap [swap] button next to it. + +3.6 Data Dialog [Entering longer text input] @@ -491,7 +518,7 @@ checkbox will be set. This only affects line feeds, not carriage returns (CR) or CR+LF pairs, and behaves the same on both Windows and Unix. (For details on escape sequences, see 4.1 Inputting Data.) -3.8 Sequence Dialog +3.7 Sequence Dialog [Creating a sequence of barcode symbols] @@ -513,7 +540,7 @@ meanings as given below: : Table : Sequence Format Characters: -3.9 Export Dialog +3.8 Export Dialog [Setting filenames for an exported sequence of barcode symbols] @@ -522,7 +549,7 @@ sets the parameters for exporting a sequence of barcode images. Here you can set the filename and the output image format. Note that the symbology, colour and other formatting information are taken from the main window. -3.10 CLI Equivalent Dialog +3.9 CLI Equivalent Dialog [CLI Equivalent Dialog] @@ -652,6 +679,11 @@ the other supported file types: zint -o there.eps -d "This Text" +The filename can contain directories and sub-directories also, which will be +created if they don’t already exist: + + zint -o "dir/subdir/filename.eps" -d "This Text" + 4.3 Selecting Barcode Type Selecting which type of barcode you wish to produce (i.e. which symbology to @@ -751,7 +783,7 @@ underscores are optional. 58 BARCODE_QRCODE QR Code - 60 BARCODE_CODE128B Code 128 (Subset B) + 60 BARCODE_CODE128AB Code 128 (Suppress subset C) 63 BARCODE_AUSPOST Australia Post Standard Customer @@ -1032,11 +1064,11 @@ The scale of the image can be altered using the --scale option followed by a multiple of the default X-dimension. The scale is multiplied by 2 (with the exception of MaxiCode) before being applied. The default scale is 1. -For MaxiCode, the scale is multiplied by 10 for raster output, by 20 for EMF +For MaxiCode, the scale is multiplied by 10 for raster output, by 40 for EMF vector output, and by 2 otherwise (non-EMF vector output). For raster output, the default X-dimension is 2 pixels (except for MaxiCode, see -4.9.2 MaxiCode Raster Scaling below). For example for PNG images a scale of 5 +4.9.3 MaxiCode Raster Scaling below). For example for PNG images a scale of 5 will increase the X-dimension to 10 pixels. Scales for raster output should be given in increments of 0.5, i.e. 0.5, 1, 1.5, 2, 2.5, 3, 3.5, etc., to avoid the X-dimension varying across the symbol due to interpolation. 0.5 increments are @@ -1048,61 +1080,61 @@ minimum scale for raster output in dotty mode is 1 (see 4.14 Working with Dots). The minimum scale for vector output is 0.1, giving a minimum X-dimension of 0.2. -The maximum scale for both raster and vector is 100. +The maximum scale for both raster and vector is 200. -4.9.1 Scaling Example +4.9.1 Scaling by X-dimension and Resolution + +An alternative way to specify the scale which takes these details into account +is to use the --scalexdimdp option, which has the format + + --scalexdimdp=X[,R] + +where X is the X-dimension (in mm by default) and R is the resolution (in dpmm, +dots per mm, by default). R is optional, and defaults to 12 dpmm, and X may be +zero, in which case it uses a symbology-specific default. The units may be given +in inches for X by appending "in", and in dpi (dots per inch) for R by appending +"dpi". For example + + zint -d "1234" --scalexdimdp=0.013in,300dpi + +Explicit metric units may also be given by appending "mm" and "dpmm" as +appropriate, and may be mixed with U.S. units: + + zint -d "1234" --scalexdimdp=0.33mm,300dpi + +4.9.2 Scaling Example The GS1 General Specifications Section 5.2.6.6 ‘Symbol dimensions at nominal size’ gives an example of an EAN-13 barcode using the X-dimension of 0.33mm. To -print that example as a PNG at 12 dots per mm (dpmm), the equivalent of 300 dots -per inch (dpi = dpmm * 25.4), specify a scale of 2, since 0.33 * 12 = 3.96 -pixels, or 4 pixels rounding to the nearest pixel: +print that example as a PNG at 12 dpmm, the approximate equivalent of 300 dpi +(dpi = dpmm * 25.4), specify a scale of 2, since 0.33 * 12 = 3.96 pixels, or 4 +pixels rounding to the nearest pixel: zint -b EANX -d "501234567890" --compliantheight --scale=2 -This will result in output of 38.27mm x 26.08mm (WxH) at 300 dpi. The following -table shows the scale to use (in 0.5 increments) depending on the dpmm desired, -for a target X-dimension of 0.33mm: +This will result in output of 37.29mm x 25.56mm (WxH) at 12 dpmm. The same +result can be achieved using the --scalexdimdp option with - dpmm dpi scale - ------ ------ ------- - 6 150 1 - 8 200 1.5 - 12 300 2 - 16 400 3 - 24 600 4 - 47 1200 8 - 95 2400 15.5 - 189 4800 31 + zint -b EANX -d "501234567890" --compliantheight --scalexdimdp=0 - : Table : Scaling for X-dimension 0.33mm: +as 0.33mm is the default X-dimension for EAN, and 12 dpmm the default +resolution. -4.9.2 MaxiCode Raster Scaling +4.9.3 MaxiCode Raster Scaling For MaxiCode symbols, which use hexagons, the scale for raster output is -multiplied by 10 before being applied. The minimum scale is 0.2, so the minimum -X-dimension is 2 pixels. +multiplied by 10 before being applied. The 0.5 increment recommended for normal +raster output does not apply. + +The minimum scale is 0.2, so the minimum X-dimension is 2 pixels. However scales +below 0.5 are not recommended and may produce symbols that are not within the +following size ranges. MaxiCode symbols have fixed size ranges of 24.82mm to 27.93mm in width, and -23.71mm to 26.69mm in height, excluding quiet zones. The following table shows -the scale to use depending on the dpmm desired, with dpi equivalents: +23.71mm to 26.69mm in height, excluding quiet zones. The default X-dimension is +0.88mm. For example, to output at the default X-dimension at 600 dpi specify: - dpmm dpi scale - ------ ------ ------- - 6 150 0.5 - 8 200 0.7 - 12 300 1 - 16 400 1.4 - 24 600 2.1 - 47 1200 4.1 - 95 2400 8.2 - 189 4800 16.4 - - : Table : MaxiCode Raster Scaling: - -Note that the 0.5 increment recommended for normal raster output does not apply. -Scales below 0.5 are not recommended and may produce symbols that are not within -the minimum/maximum size ranges. + zint -b MAXICODE -d "MaxiCode (19 chars)" --scalexdimdp=0,600dpi 4.10 Input Modes @@ -1348,6 +1380,16 @@ The following table shows some examples to clarify this method: : Table : Batch Filename Examples: +The special characters can span directories also, which is useful when creating +a large number of barcodes: + + Input Filenames Generated + --------------------- ----------------------------------------- + -o dir~/file~~~.svg dir0/file001.svg, dir0/file002.svg, … + , dir0/file999.svg, dir1/file000.svg, … + + : Table : Batch Directory Examples: + 4.12 Direct Output The finished image files can be output directly to stdout for use as part of a @@ -1776,7 +1818,11 @@ encoding stages. The zint_symbol structure consists of the following variables: eci integer Extended Channel 0 (none) Interpretation code. - dot_size float Diameter of dots used in 4.0 / 5.0 + dpmm float Resolution of output in dots 0 (none) + per mm (BMP/EMF/PCX/PNG/TIF + only). + + dot_size float Diameter of dots used in 0.8 dotty mode. guard_descent float Height of guard bar descent 5.0 @@ -2147,7 +2193,49 @@ example: A maximum of 256 segments may be specified. Use of multiple segments with GS1 data is not currently supported. -5.12 Verifying Symbology Availability +5.12 Scaling Helpers + +To help with scaling the output, the following three function are available: + + float ZBarcode_Default_Xdim(int symbol_id); + + float ZBarcode_Scale_From_XdimDp(int symbol_id, float x_dim_mm, float dpmm, + const char *filetype) { + + float ZBarcode_XdimDP_From_Scale(int symbol_id, float scale, + float x_dim_mm_or_dpmm, const char *filetype); + +The first ZBarcode_Default_Xdim() returns the default X-dimension suggested by +Zint for symbology symbol_id. + +The second ZBarcode_Scale_From_XdimDp() returns the scale to use to output to a +file of type filetype with X-dimension x_dim_mm at dpmm dots per mm. The given +X-dimension must be non-zero and less than or equal to 10mm, however dpmm may be +zero and defaults to 12 dpmm, and filetype may be NULL or empty in which case a +GIF filetype is assumed. For raster output (BMP/GIF/PCX/PNG/TIF) the scale is +rounded to half-integer increments. + +For example: + + my_symbol->symbology = BARCODE_RM4SCC; /* Royal Mail 4-State Customer Code */ + my_symbol->dpmm = 600.0f / 25.4f; /* 600 dpi */ + my_symbol->scale = ZBarcode_Scale_From_XdimDp( + my_symbol->symbology, + ZBarcode_Default_Xdim(my_symbol->symbology), + my_symbol->dpmm, "PNG"); /* 7.5 */ + +The third function ZBarcode_XdimDP_From_Scale() is the “reverse” of +ZBarcode_Scale_From_XdimDp(), returning the X-dimension (in mm) or the dot +density (in dpmm) given a scale scale. Both scale and x_dim_mm_or_dpmm must be +non-zero. The returned value is bound to the maximum value of dpmm (1000), so +must be further bound to 10 on return if the X-dimension is sought. + +Note that the X-dimension to use is application dependent, and varies not only +due to the symbology, resolution and filetype but also due to the type of +scanner used, the intended scanning distance, and what media (“substrates”) the +barcode appears on. + +5.13 Verifying Symbology Availability An additional function available in the API is: @@ -2177,7 +2265,7 @@ success. For instance: will print BARCODE_PDF417. -5.13 Checking Symbology Capabilities +5.14 Checking Symbology Capabilities It can be useful for frontend programs to know the capabilities of a symbology. This can be determined using another additional function: @@ -2239,7 +2327,7 @@ For example: printf("PDF417 does not support ECI\n"); } -5.14 Zint Version +5.15 Zint Version Whether the Zint library linked to was built with PNG support may be determined with: @@ -2349,16 +2437,16 @@ bind or bindtop) and leaving the border width 0. [zint -b DPLEIT -d "9212320967145"] Leitcode is based on Interleaved Code 2 of 5 and is used by Deutsche Post for -mailing purposes. Leitcode requires a 13-digit numerical input and includes a -check digit. +routing purposes. Leitcode requires a 13-digit numerical input to which Zint +adds a check digit. 6.1.2.8 Deutsche Post Identcode [zint -b DPIDENT -d "91232096712"] Identcode is based on Interleaved Code 2 of 5 and is used by Deutsche Post for -mailing purposes. Identcode requires an 11-digit numerical input and includes a -check digit. +identification purposes. Identcode requires an 11-digit numerical input to which +Zint adds a check digit. 6.1.3 UPC (Universal Product Code) (ISO 15420) @@ -2372,7 +2460,7 @@ EAN-2 and EAN-5 add-on symbols can be added using the + character. For example, to draw a UPC-A symbol with the data 72527270270 with an EAN-5 add-on showing the data 12345 use the command: - zint -b UPCA -d 72527270270+12345 + zint -b UPCA -d "72527270270+12345" or using the API encode a data string with the + character included: @@ -2401,7 +2489,7 @@ calculated by Zint. EAN-2 and EAN-5 add-on symbols can be added using the + character as with UPC-A. In addition Zint also supports Number System 1 encoding by entering a 7-digit article number starting with the digit 1. For example: - zint -b UPCE -d 1123456 + zint -b UPCE -d "1123456" or @@ -2430,13 +2518,13 @@ Zint will decide which symbology to use depending on the length of the input data. In addition EAN-2 and EAN-5 add-on symbols can be added to EAN-8 and EAN-13 symbols using the + character as with UPC symbols. For example: - zint -b EANX -d 54321 + zint -b EANX -d "54321" [zint -b EANX --compliantheight -d "54321"] will encode a stand-alone EAN-5, whereas - zint -b EANX -d 7432365+54321 + zint -b EANX -d "7432365+54321" will encode an EAN-8 symbol with an EAN-5 add-on. As before these results can be achieved using the API: @@ -2567,9 +2655,9 @@ PZN encodes a 7-digit number to which Zint will add a modulo-11 check digit. [zint -b LOGMARS --compliantheight -d "12345/ABCDE" --vers=1] LOGMARS (Logistics Applications of Automated Marking and Reading Symbols) is a -variation of the Code 39 symbology used by the US Department of Defense. LOGMARS -encodes the same character set as Standard Code 39. It does not require a check -digit but a modulo-43 check digit can be added by setting --vers=1 (API +variation of the Code 39 symbology used by the U.S. Department of Defense. +LOGMARS encodes the same character set as Standard Code 39. It does not require +a check digit but a modulo-43 check digit can be added by setting --vers=1 (API option_2 = 1). 6.1.7.6 Code 32 @@ -2636,13 +2724,13 @@ encoding of ISO/IEC 8859-1 (non-English) characters in Code 128 symbols. The ISO/IEC 8859-1 character set is shown in Appendix A.2 Latin Alphabet No. 1 (ISO/IEC 8859-1). -6.1.10.2 Code 128 Subset B +6.1.10.2 Code 128 Suppress Subset C (Subsets A and B only) -[zint -b CODE128B -d "130170X178"] +[zint -b CODE128AB -d "130170X178"] It is sometimes advantageous to stop Code 128 from using subset mode C which -compresses numerical data. The BARCODE_CODE128B variant (symbology 60) -suppresses mode C in favour of mode B. +compresses numerical data. The BARCODE_CODE128AB[10] variant (symbology 60) +suppresses mode C in favour of modes A and B. 6.1.10.3 GS1-128 @@ -3242,10 +3330,10 @@ these will be appended by Zint if not included in the input data. [zint -b USPS_IMAIL --compliantheight -d "01234567094987654321-01234"] -Also known as the OneCode barcode and used in the US by the United States Postal -Service (USPS), the Intelligent Mail system replaced the POSTNET and PLANET -symbologies in 2009. Intelligent Mail is a fixed length (65-bar) symbol which -combines routing and customer information in a single symbol. Input data +Also known as the OneCode barcode and used in the U.S. by the United States +Postal Service (USPS), the Intelligent Mail system replaced the POSTNET and +PLANET symbologies in 2009. Intelligent Mail is a fixed length (65-bar) symbol +which combines routing and customer information in a single symbol. Input data consists of a 20-digit tracking code, followed by a dash (-), followed by a delivery point zip-code which can be 0, 5, 9 or 11 digits in length. For example all of the following inputs are valid data entries: @@ -3290,8 +3378,8 @@ as [zint -b HIBC_DM -d "/ACMRN123456/V200912190833" --fast --square] Also known as Semacode this symbology was developed in 1989 by Acuity CiMatrix -in partnership with the US DoD and NASA. The symbol can encode a large amount of -data in a small area. Data Matrix encodes characters in the Latin-1 set by +in partnership with the U.S. DoD and NASA. The symbol can encode a large amount +of data in a small area. Data Matrix encodes characters in the Latin-1 set by default but also supports encoding in other character sets using the ECI mechanism. It can also encode GS1 data. The size of the generated symbol can be adjusted using the --vers option (API option_2) as shown in the table below. A @@ -3627,7 +3715,7 @@ using the --structapp option (see 4.16 Structured Append) (API structapp). It does not support specifying an ID. MaxiCode uses a different scaling than other symbols for raster output, see -4.9.2 MaxiCode Raster Scaling, and also for EMF vector output, when the scale is +4.9.3 MaxiCode Raster Scaling, and also for EMF vector output, when the scale is multiplied by 20 instead of 2. 6.6.7 Aztec Code (ISO 24778) @@ -4165,7 +4253,7 @@ defined. Annex B. Man Page ZINT(1) -% ZINT(1) Version 2.11.1.9 % % November 2022 +% ZINT(1) Version 2.11.1.9 % % December 2022 NAME @@ -4478,12 +4566,25 @@ OPTIONS multiplied by 2 (except for MaxiCode) before being applied. The default scale is 1. - For MaxiCode, the scale is multiplied by 10 for raster output, by 20 for EMF + For MaxiCode, the scale is multiplied by 10 for raster output, by 40 for EMF output, and by 2 otherwise. Increments of 0.5 (half-integers) are recommended for non-MaxiCode raster output (BMP, GIF, PCX, PNG and TIF). + See also --scalexdimdp below. + +--scalexdimdp=X[,R] + + Scale the image according to X-dimension X and resolution R, where X is in + mm and R is in dpmm (dots per mm). X and R may be floating-point. R is + optional and defaults to 12 dpmm (approximately 300 dpi). + + The scaling takes into account the output filetype, and deals with all the + details mentioned above. Units may be specified for X by appending “in” + (inch) or “mm”, and for R by appending “dpi” (dots per inch) or “dpmm” - + e.g. --scalexdimdp=0.013in,300dpi. + --scmvv=INTEGER For MaxiCode, prefix the Structured Carrier Message (SCM) with @@ -4728,3 +4829,6 @@ Special considerations apply to ITF-14 - see 6.1.2.6 ITF-14. [9] Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and UPC-E have compliant quiet zones added by default. + +[10] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still +recognised. diff --git a/docs/zint.1 b/docs/zint.1 index c6d18412..fa112e46 100644 --- a/docs/zint.1 +++ b/docs/zint.1 @@ -14,7 +14,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "ZINT" "1" "November 2022" "Version 2.11.1.9" "" +.TH "ZINT" "1" "December 2022" "Version 2.11.1.9" "" .hy .SH NAME .PP @@ -348,11 +348,29 @@ for MaxiCode) before being applied. The default scale is 1. .RS .PP -For MaxiCode, the scale is multiplied by 10 for raster output, by 20 for +For MaxiCode, the scale is multiplied by 10 for raster output, by 40 for EMF output, and by 2 otherwise. .PP Increments of 0.5 (half-integers) are recommended for non-MaxiCode raster output (BMP, GIF, PCX, PNG and TIF). +.PP +See also \f[V]--scalexdimdp\f[R] below. +.RE +.TP +\f[V]--scalexdimdp=X[,R]\f[R] +Scale the image according to X-dimension \f[I]X\f[R] and resolution +\f[I]R\f[R], where \f[I]X\f[R] is in mm and \f[I]R\f[R] is in dpmm (dots +per mm). +\f[I]X\f[R] and \f[I]R\f[R] may be floating-point. +\f[I]R\f[R] is optional and defaults to 12 dpmm (approximately 300 dpi). +.RS +.PP +The scaling takes into account the output filetype, and deals with all +the details mentioned above. +Units may be specified for \f[I]X\f[R] by appending \[lq]in\[rq] (inch) +or \[lq]mm\[rq], and for \f[I]R\f[R] by appending \[lq]dpi\[rq] (dots +per inch) or \[lq]dpmm\[rq] - +e.g.\ \f[V]--scalexdimdp=0.013in,300dpi\f[R]. .RE .TP \f[V]--scmvv=INTEGER\f[R] @@ -400,9 +418,9 @@ For Data Matrix symbols, exclude rectangular sizes when considering automatic sizes. .TP \f[V]--structapp=I,C[,ID]\f[R] -Set Structured Append info, where \f[V]I\f[R] is the 1-based index, -\f[V]C\f[R] is the total number of symbols in the sequence, and -\f[V]ID\f[R], which is optional, is the identifier that all symbols in +Set Structured Append info, where \f[I]I\f[R] is the 1-based index, +\f[I]C\f[R] is the total number of symbols in the sequence, and +\f[I]ID\f[R], which is optional, is the identifier that all symbols in the sequence share. Structured Append is supported by Aztec Code, Code One, Data Matrix, DotCode, Grid Matrix, MaxiCode, MicroPDF417, PDF417, QR Code and diff --git a/docs/zint.1.pmd b/docs/zint.1.pmd index 02e83b76..ed3dfad9 100644 --- a/docs/zint.1.pmd +++ b/docs/zint.1.pmd @@ -1,6 +1,6 @@ % ZINT(1) Version 2.11.1.9 % -% November 2022 +% December 2022 # NAME @@ -280,10 +280,21 @@ Paintbrush (`PCX`), Portable Network Format (`PNG`), Scalable Vector Graphic (`S : Adjust the size of the X-dimension. *NUMBER* may be floating-point, and is multiplied by 2 (except for MaxiCode) before being applied. The default scale is 1. - For MaxiCode, the scale is multiplied by 10 for raster output, by 20 for EMF output, and by 2 otherwise. + For MaxiCode, the scale is multiplied by 10 for raster output, by 40 for EMF output, and by 2 otherwise. Increments of 0.5 (half-integers) are recommended for non-MaxiCode raster output (BMP, GIF, PCX, PNG and TIF). + See also `--scalexdimdp` below. + +`--scalexdimdp=X[,R]` + +: Scale the image according to X-dimension *X* and resolution *R*, where *X* is in mm and *R* is in dpmm (dots per + mm). *X* and *R* may be floating-point. *R* is optional and defaults to 12 dpmm (approximately 300 dpi). + + The scaling takes into account the output filetype, and deals with all the details mentioned above. Units may be + specified for *X* by appending "in" (inch) or "mm", and for *R* by appending "dpi" (dots per inch) or "dpmm" - + e.g. `--scalexdimdp=0.013in,300dpi`. + `--scmvv=INTEGER` : For MaxiCode, prefix the Structured Carrier Message (SCM) with `"[)>\R01\Gvv"`, where `vv` is a 2-digit *INTEGER*. @@ -322,8 +333,8 @@ Paintbrush (`PCX`), Portable Network Format (`PNG`), Scalable Vector Graphic (`S `--structapp=I,C[,ID]` -: Set Structured Append info, where `I` is the 1-based index, `C` is the total number of symbols in the sequence, - and `ID`, which is optional, is the identifier that all symbols in the sequence share. Structured Append is +: Set Structured Append info, where *I* is the 1-based index, *C* is the total number of symbols in the sequence, + and *ID*, which is optional, is the identifier that all symbols in the sequence share. Structured Append is supported by Aztec Code, Code One, Data Matrix, DotCode, Grid Matrix, MaxiCode, MicroPDF417, PDF417, QR Code and Ultracode. diff --git a/docs/zint_images.sh b/docs/zint_images.sh index 1f564a19..69a3063c 100755 --- a/docs/zint_images.sh +++ b/docs/zint_images.sh @@ -66,7 +66,7 @@ zint -b VIN -d "2FTPX28L0XCA15511" --vers=1 --scale=$SCALE_LINEAR -o images/vin. zint -b CODABAR --compliantheight -d "A37859B" --scale=$SCALE_LINEAR -o images/codabar.svg zint -b PHARMA --compliantheight -d "130170" --scale=$SCALE_LINEAR -o images/pharma.svg zint -b CODE128 --bind -d "130170X178" --scale=$SCALE_LINEAR -o images/code128.svg -zint -b CODE128B -d "130170X178" --scale=$SCALE_LINEAR -o images/code128b.svg +zint -b CODE128AB -d "130170X178" --scale=$SCALE_LINEAR -o images/code128ab.svg zint -b GS1_128 --compliantheight -d "[01]98898765432106[3202]012345[15]991231" --scale=$SCALE_LINEAR -o images/gs1_128.svg zint -b EAN14 --compliantheight -d "9889876543210" --scale=$SCALE_LINEAR -o images/ean14.svg zint -b NVE18 --compliantheight -d "37612345000001003" --scale=$SCALE_LINEAR -o images/nve18.svg diff --git a/frontend/main.c b/frontend/main.c index 3e86f7e8..d6a0f9e8 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -37,7 +37,7 @@ /* It's assumed that int is at least 32 bits, the following will compile-time fail if not * https://stackoverflow.com/a/1980056 */ -typedef int static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ? -1 : 1]; +typedef char static_assert_int_at_least_32bits[sizeof(int) * CHAR_BIT < 32 ? -1 : 1]; #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) ((int) (sizeof(x) / sizeof((x)[0]))) @@ -60,57 +60,57 @@ typedef int static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ? /* Print list of supported symbologies */ static void types(void) { - printf( " # Name Description # Name Description\n" - " 1 CODE11 Code 11 74 CODABLOCKF Codablock-F\n" - " 2 C25STANDARD Standard 2 of 5 75 NVE18 NVE-18\n" - " 3 C25INTER Interleaved 2 of 5 76 JAPANPOST Japanese Post\n" - " 4 C25IATA IATA 2 of 5 77 KOREAPOST Korea Post\n" - " 6 C25LOGIC Data Logic 2 of 5 79 DBAR_STK GS1 DataBar Stacked\n" - " 7 C25IND Industrial 2 of 5 80 DBAR_OMNSTK GS1 DataBar Stack Omni\n" - " 8 CODE39 Code 39 81 DBAR_EXPSTK GS1 DataBar Exp Stack\n" - " 9 EXCODE39 Extended Code 39 82 PLANET USPS PLANET\n" - "13 EANX EAN-2 to EAN-13 84 MICROPDF417 MicroPDF417\n" - "14 EANX_CHK EAN + Check Digit 85 USPS_IMAIL USPS Intelligent Mail\n" - "16 GS1_128 GS1-128 86 PLESSEY UK Plessey\n" - "18 CODABAR Codabar 87 TELEPEN_NUM Telepen Numeric\n" - "20 CODE128 Code 128 89 ITF14 ITF-14\n" - "21 DPLEIT Deutsche Post Leitcode 90 KIX Dutch Post KIX Code\n" - "22 DPIDENT Deutsche Post Identcode 92 AZTEC Aztec Code\n" - "23 CODE16K Code 16K 93 DAFT DAFT Code\n" - "24 CODE49 Code 49 96 DPD DPD Parcel Code 128\n" - "25 CODE93 Code 93 97 MICROQR Micro QR Code\n" - "28 FLAT Flattermarken 98 HIBC_128 HIBC Code 128\n" - "29 DBAR_OMN GS1 DataBar Omni 99 HIBC_39 HIBC Code 39\n" - "30 DBAR_LTD GS1 DataBar Limited 102 HIBC_DM HIBC Data Matrix\n" - "31 DBAR_EXP GS1 DataBar Expanded 104 HIBC_QR HIBC QR Code\n" - "32 TELEPEN Telepen Alpha 106 HIBC_PDF HIBC PDF417\n" - "34 UPCA UPC-A 108 HIBC_MICPDF HIBC MicroPDF417\n" - "35 UPCA_CHK UPC-A + Check Digit 110 HIBC_BLOCKF HIBC Codablock-F\n" - "37 UPCE UPC-E 112 HIBC_AZTEC HIBC Aztec Code\n" - "38 UPCE_CHK UPC-E + Check Digit 115 DOTCODE DotCode\n" - "40 POSTNET USPS POSTNET 116 HANXIN Han Xin Code\n" - "47 MSI_PLESSEY MSI Plessey 121 MAILMARK Royal Mail Mailmark\n" - "49 FIM Facing Ident Mark 128 AZRUNE Aztec Runes\n" - "50 LOGMARS LOGMARS Code 39 129 CODE32 Code 32\n" - "51 PHARMA Pharmacode One-Track 130 EANX_CC Composite EAN\n" - "52 PZN Pharmazentralnummer 131 GS1_128_CC Composite GS1-128\n" - "53 PHARMA_TWO Pharmacode Two-Track 132 DBAR_OMN_CC Comp DataBar Omni\n" - "54 CEPNET Brazilian CEPNet 133 DBAR_LTD_CC Comp DataBar Limited\n" - "55 PDF417 PDF417 134 DBAR_EXP_CC Comp DataBar Expanded\n" - "56 PDF417COMP Compact PDF417 135 UPCA_CC Composite UPC-A\n" - "57 MAXICODE MaxiCode 136 UPCE_CC Composite UPC-E\n" - "58 QRCODE QR Code 137 DBAR_STK_CC Comp DataBar Stacked\n" - "60 CODE128B Code 128 (Subset B) 138 DBAR_OMNSTK_CC Comp DataBar Stack Omn\n" - "63 AUSPOST AP Standard Customer 139 DBAR_EXPSTK_CC Comp DataBar Exp Stack\n" - "66 AUSREPLY AP Reply Paid 140 CHANNEL Channel Code\n" - "67 AUSROUTE AP Routing 141 CODEONE Code One\n" - "68 AUSREDIRECT AP Redirection 142 GRIDMATRIX Grid Matrix\n" - "69 ISBNX ISBN 143 UPNQR UPN QR Code\n" - "70 RM4SCC Royal Mail 4SCC 144 ULTRA Ultracode\n" - "71 DATAMATRIX Data Matrix 145 RMQR Rectangular Micro QR\n" - "72 EAN14 EAN-14 146 BC412 BC412\n" - "73 VIN Vehicle Information No.\n" - ); + /* Breaking up strings so don't get too long (i.e. 500 or so) */ + fputs(" # Name Description # Name Description\n" + " 1 CODE11 Code 11 74 CODABLOCKF Codablock-F\n" + " 2 C25STANDARD Standard 2 of 5 75 NVE18 NVE-18\n" + " 3 C25INTER Interleaved 2 of 5 76 JAPANPOST Japanese Post\n" + " 4 C25IATA IATA 2 of 5 77 KOREAPOST Korea Post\n", stdout); + fputs(" 6 C25LOGIC Data Logic 2 of 5 79 DBAR_STK GS1 DataBar Stacked\n" + " 7 C25IND Industrial 2 of 5 80 DBAR_OMNSTK GS1 DataBar Stack Omni\n" + " 8 CODE39 Code 39 81 DBAR_EXPSTK GS1 DataBar Exp Stack\n" + " 9 EXCODE39 Extended Code 39 82 PLANET USPS PLANET\n" + "13 EANX EAN-2 to EAN-13 84 MICROPDF417 MicroPDF417\n", stdout); + fputs("14 EANX_CHK EAN + Check Digit 85 USPS_IMAIL USPS Intelligent Mail\n" + "16 GS1_128 GS1-128 86 PLESSEY UK Plessey\n" + "18 CODABAR Codabar 87 TELEPEN_NUM Telepen Numeric\n" + "20 CODE128 Code 128 89 ITF14 ITF-14\n" + "21 DPLEIT Deutsche Post Leitcode 90 KIX Dutch Post KIX Code\n", stdout); + fputs("22 DPIDENT Deutsche Post Identcode 92 AZTEC Aztec Code\n" + "23 CODE16K Code 16K 93 DAFT DAFT Code\n" + "24 CODE49 Code 49 96 DPD DPD Parcel Code 128\n" + "25 CODE93 Code 93 97 MICROQR Micro QR Code\n" + "28 FLAT Flattermarken 98 HIBC_128 HIBC Code 128\n", stdout); + fputs("29 DBAR_OMN GS1 DataBar Omni 99 HIBC_39 HIBC Code 39\n" + "30 DBAR_LTD GS1 DataBar Limited 102 HIBC_DM HIBC Data Matrix\n" + "31 DBAR_EXP GS1 DataBar Expanded 104 HIBC_QR HIBC QR Code\n" + "32 TELEPEN Telepen Alpha 106 HIBC_PDF HIBC PDF417\n" + "34 UPCA UPC-A 108 HIBC_MICPDF HIBC MicroPDF417\n", stdout); + fputs("35 UPCA_CHK UPC-A + Check Digit 110 HIBC_BLOCKF HIBC Codablock-F\n" + "37 UPCE UPC-E 112 HIBC_AZTEC HIBC Aztec Code\n" + "38 UPCE_CHK UPC-E + Check Digit 115 DOTCODE DotCode\n" + "40 POSTNET USPS POSTNET 116 HANXIN Han Xin Code\n" + "47 MSI_PLESSEY MSI Plessey 121 MAILMARK Royal Mail Mailmark\n", stdout); + fputs("49 FIM Facing Ident Mark 128 AZRUNE Aztec Runes\n" + "50 LOGMARS LOGMARS Code 39 129 CODE32 Code 32\n" + "51 PHARMA Pharmacode One-Track 130 EANX_CC Composite EAN\n" + "52 PZN Pharmazentralnummer 131 GS1_128_CC Composite GS1-128\n" + "53 PHARMA_TWO Pharmacode Two-Track 132 DBAR_OMN_CC Comp DataBar Omni\n", stdout); + fputs("54 CEPNET Brazilian CEPNet 133 DBAR_LTD_CC Comp DataBar Limited\n" + "55 PDF417 PDF417 134 DBAR_EXP_CC Comp DataBar Expanded\n" + "56 PDF417COMP Compact PDF417 135 UPCA_CC Composite UPC-A\n" + "57 MAXICODE MaxiCode 136 UPCE_CC Composite UPC-E\n" + "58 QRCODE QR Code 137 DBAR_STK_CC Comp DataBar Stacked\n", stdout); + fputs("60 CODE128AB Code 128 (Suppress C) 138 DBAR_OMNSTK_CC Comp DataBar Stack Omn\n" + "63 AUSPOST AP Standard Customer 139 DBAR_EXPSTK_CC Comp DataBar Exp Stack\n" + "66 AUSREPLY AP Reply Paid 140 CHANNEL Channel Code\n" + "67 AUSROUTE AP Routing 141 CODEONE Code One\n" + "68 AUSREDIRECT AP Redirection 142 GRIDMATRIX Grid Matrix\n", stdout); + fputs("69 ISBNX ISBN 143 UPNQR UPN QR Code\n" + "70 RM4SCC Royal Mail 4SCC 144 ULTRA Ultracode\n" + "71 DATAMATRIX Data Matrix 145 RMQR Rectangular Micro QR\n" + "72 EAN14 EAN-14 146 BC412 BC412\n" + "73 VIN Vehicle Information No.\n", stdout); } /* Output version information */ @@ -141,116 +141,114 @@ static void usage(int no_png) { version(no_png); - printf( "Encode input data in a barcode and save as BMP/EMF/EPS/GIF/PCX%s/SVG/TIF/TXT\n\n" - " -b, --barcode=TYPE Number or name of barcode type. Default is 20 (CODE128)\n" - " --addongap=NUMBER Set add-on gap in multiples of X-dimension for EAN/UPC\n" - " --batch Treat each line of input file as a separate data set\n" - " --bg=COLOUR Specify a background colour (in hex RGB/RGBA)\n" - " --binary Treat input as raw binary data\n" - " --bind Add boundary bars\n" - " --bindtop Add top boundary bar only\n" - " --bold Use bold text\n" - " --border=NUMBER Set width of border in multiples of X-dimension\n" - " --box Add a box around the symbol\n" - " --cmyk Use CMYK colour space in EPS/TIF symbols\n" - " --cols=NUMBER Set the number of data columns in symbol\n" - " --compliantheight Warn if height not compliant, and use standard default\n" - " -d, --data=DATA Set the symbol data content (segment 0)\n" - " --direct Send output to stdout\n" - " --dmre Allow Data Matrix Rectangular Extended\n" - " --dotsize=NUMBER Set radius of dots in dotty mode\n" - " --dotty Use dots instead of squares for matrix symbols\n" - " --dump Dump hexadecimal representation to stdout\n" - " -e, --ecinos Display ECI (Extended Channel Interpretation) table\n" - " --eci=NUMBER Set the ECI code for the data (segment 0)\n" - " --esc Process escape characters in input data\n" - " --fast Use faster encodation (Data Matrix)\n" - " --fg=COLOUR Specify a foreground colour (in hex RGB/RGBA)\n" - " --filetype=TYPE Set output file type BMP/EMF/EPS/GIF/PCX%s/SVG/TIF/TXT\n" - " --fullmultibyte Use multibyte for binary/Latin (QR/Han Xin/Grid Matrix)\n" - " --gs1 Treat input as GS1 compatible data\n" - " --gs1nocheck Do not check validity of GS1 data\n" - " --gs1parens Process parentheses \"()\" as GS1 AI delimiters, not \"[]\"\n" - " --gssep Use separator GS for GS1 (Data Matrix)\n" - " --guarddescent=NUMBER Set height of guard bar descent in X-dims (EAN/UPC)\n" - " -h, --help Display help message\n" - " --height=NUMBER Set height of symbol in multiples of X-dimension\n" - " --heightperrow Treat height as per-row\n" - " -i, --input=FILE Read input data from FILE\n" - " --init Create Reader Initialisation (Programming) symbol\n" - " --mask=NUMBER Set masking pattern to use (QR/Han Xin/DotCode)\n" - " --mirror Use batch data to determine filename\n" - " --mode=NUMBER Set encoding mode (MaxiCode/Composite)\n" - " --nobackground Remove background (EMF/EPS/GIF%s/SVG/TIF only)\n" - " --noquietzones Disable default quiet zones\n" - " --notext Remove human readable text\n" - " -o, --output=FILE Send output to FILE. Default is out.%s\n" - " --primary=STRING Set primary message (MaxiCode/Composite)\n" - " --quietzones Add compliant quiet zones\n" - " -r, --reverse Reverse colours (white on black)\n" - " --rotate=NUMBER Rotate symbol by NUMBER degrees\n" - " --rows=NUMBER Set number of rows (Codablock-F/PDF417)\n" - " --scale=NUMBER Adjust size of X-dimension\n" - " --scmvv=NUMBER Prefix SCM with \"[)>\\R01\\Gvv\" (vv is NUMBER) (MaxiCode)\n" - " --secure=NUMBER Set error correction level (ECC)\n" - " --segN=ECI,DATA Set the ECI & data content for segment N, where N 1 to 9\n" - " --separator=NUMBER Set height of row separator bars (stacked symbologies)\n" - " --small Use small text\n" - " --square Force Data Matrix symbols to be square\n" - " --structapp=I,C[,ID] Set Structured Append info (I index, C count)\n" - " -t, --types Display table of barcode types\n" - " --vers=NUMBER Set symbol version (size, check digits, other options)\n" - " -v, --version Display Zint version\n" - " --vwhitesp=NUMBER Set height of vertical whitespace in multiples of X-dim\n" - " -w, --whitesp=NUMBER Set width of horizontal whitespace in multiples of X-dim\n" - " --werror Convert all warnings into errors\n", - no_png_type, no_png_type, no_png_type, no_png_ext - ); + printf("Encode input data in a barcode and save as BMP/EMF/EPS/GIF/PCX%s/SVG/TIF/TXT\n\n", no_png_type); + fputs( " -b, --barcode=TYPE Number or name of barcode type. Default is 20 (CODE128)\n" + " --addongap=NUMBER Set add-on gap in multiples of X-dimension for EAN/UPC\n" + " --batch Treat each line of input file as a separate data set\n" + " --bg=COLOUR Specify a background colour (in hex RGB/RGBA)\n" + " --binary Treat input as raw binary data\n", stdout); + fputs( " --bind Add boundary bars\n" + " --bindtop Add top boundary bar only\n" + " --bold Use bold text\n" + " --border=NUMBER Set width of border in multiples of X-dimension\n" + " --box Add a box around the symbol\n", stdout); + fputs( " --cmyk Use CMYK colour space in EPS/TIF symbols\n" + " --cols=NUMBER Set the number of data columns in symbol\n" + " --compliantheight Warn if height not compliant, and use standard default\n" + " -d, --data=DATA Set the symbol data content (segment 0)\n" + " --direct Send output to stdout\n", stdout); + fputs( " --dmre Allow Data Matrix Rectangular Extended\n" + " --dotsize=NUMBER Set radius of dots in dotty mode\n" + " --dotty Use dots instead of squares for matrix symbols\n" + " --dump Dump hexadecimal representation to stdout\n" + " -e, --ecinos Display ECI (Extended Channel Interpretation) table\n", stdout); + fputs( " --eci=NUMBER Set the ECI code for the data (segment 0)\n" + " --esc Process escape characters in input data\n" + " --fast Use faster encodation (Data Matrix)\n" + " --fg=COLOUR Specify a foreground colour (in hex RGB/RGBA)\n", stdout); + printf(" --filetype=TYPE Set output file type BMP/EMF/EPS/GIF/PCX%s/SVG/TIF/TXT\n", no_png_type); + fputs( " --fullmultibyte Use multibyte for binary/Latin (QR/Han Xin/Grid Matrix)\n" + " --gs1 Treat input as GS1 compatible data\n" + " --gs1nocheck Do not check validity of GS1 data\n" + " --gs1parens Process parentheses \"()\" as GS1 AI delimiters, not \"[]\"\n" + " --gssep Use separator GS for GS1 (Data Matrix)\n", stdout); + fputs( " --guarddescent=NUMBER Set height of guard bar descent in X-dims (EAN/UPC)\n" + " -h, --help Display help message\n" + " --height=NUMBER Set height of symbol in multiples of X-dimension\n" + " --heightperrow Treat height as per-row\n" + " -i, --input=FILE Read input data from FILE\n", stdout); + fputs( " --init Create Reader Initialisation (Programming) symbol\n" + " --mask=NUMBER Set masking pattern to use (QR/Han Xin/DotCode)\n" + " --mirror Use batch data to determine filename\n" + " --mode=NUMBER Set encoding mode (MaxiCode/Composite)\n", stdout); + printf(" --nobackground Remove background (EMF/EPS/GIF%s/SVG/TIF only)\n", no_png_type); + fputs( " --noquietzones Disable default quiet zones\n" + " --notext Remove human readable text\n", stdout); + printf(" -o, --output=FILE Send output to FILE. Default is out.%s\n", no_png_ext); + fputs( " --primary=STRING Set primary message (MaxiCode/Composite)\n" + " --quietzones Add compliant quiet zones\n" + " -r, --reverse Reverse colours (white on black)\n" + " --rotate=NUMBER Rotate symbol by NUMBER degrees\n" + " --rows=NUMBER Set number of rows (Codablock-F/PDF417)\n", stdout); + fputs( " --scale=NUMBER Adjust size of X-dimension\n" + " --scalexdimdp=X[,R] Adjust size to X-dimension X at resolution R\n" + " --scmvv=NUMBER Prefix SCM with \"[)>\\R01\\Gvv\" (vv is NUMBER) (MaxiCode)\n" + " --secure=NUMBER Set error correction level (ECC)\n" + " --segN=ECI,DATA Set the ECI & data content for segment N, where N 1 to 9\n", stdout); + fputs( " --separator=NUMBER Set height of row separator bars (stacked symbologies)\n" + " --small Use small text\n" + " --square Force Data Matrix symbols to be square\n" + " --structapp=I,C[,ID] Set Structured Append info (I index, C count)\n" + " -t, --types Display table of barcode types\n", stdout); + fputs( " --vers=NUMBER Set symbol version (size, check digits, other options)\n" + " -v, --version Display Zint version\n" + " --vwhitesp=NUMBER Set height of vertical whitespace in multiples of X-dim\n" + " -w, --whitesp=NUMBER Set width of horizontal whitespace in multiples of X-dim\n" + " --werror Convert all warnings into errors\n", stdout); } /* Display supported ECI codes */ static void show_eci(void) { - printf( " 3: ISO/IEC 8859-1 - Latin alphabet No. 1 (default)\n" - " 4: ISO/IEC 8859-2 - Latin alphabet No. 2\n" - " 5: ISO/IEC 8859-3 - Latin alphabet No. 3\n" - " 6: ISO/IEC 8859-4 - Latin alphabet No. 4\n" - " 7: ISO/IEC 8859-5 - Latin/Cyrillic alphabet\n" - " 8: ISO/IEC 8859-6 - Latin/Arabic alphabet\n" - " 9: ISO/IEC 8859-7 - Latin/Greek alphabet\n" - " 10: ISO/IEC 8859-8 - Latin/Hebrew alphabet\n" - " 11: ISO/IEC 8859-9 - Latin alphabet No. 5 (Turkish)\n" - " 12: ISO/IEC 8859-10 - Latin alphabet No. 6 (Nordic)\n" - " 13: ISO/IEC 8859-11 - Latin/Thai alphabet\n" - " 15: ISO/IEC 8859-13 - Latin alphabet No. 7 (Baltic)\n" - " 16: ISO/IEC 8859-14 - Latin alphabet No. 8 (Celtic)\n" - " 17: ISO/IEC 8859-15 - Latin alphabet No. 9\n" - " 18: ISO/IEC 8859-16 - Latin alphabet No. 10\n" - " 20: Shift JIS (JIS X 0208 and JIS X 0201)\n" - " 21: Windows 1250 - Latin 2 (Central Europe)\n" - " 22: Windows 1251 - Cyrillic\n" - " 23: Windows 1252 - Latin 1\n" - " 24: Windows 1256 - Arabic\n" - " 25: UTF-16BE (High order byte first)\n" - " 26: UTF-8\n" - " 27: ASCII (ISO/IEC 646 IRV)\n" - " 28: Big5 (Taiwan) Chinese Character Set\n" - " 29: GB 2312 (PRC) Chinese Character Set\n" - " 30: Korean Character Set EUC-KR (KS X 1001:2002)\n" - " 31: GBK Chinese Character Set\n" - " 32: GB 18030 Chinese Character Set\n" - " 33: UTF-16LE (Low order byte first)\n" - " 34: UTF-32BE (High order bytes first)\n" - " 35: UTF-32LE (Low order bytes first)\n" - "170: ISO/IEC 646 Invariant (ASCII subset)\n" - "899: 8-bit binary data\n" - ); + fputs(" 3: ISO/IEC 8859-1 - Latin alphabet No. 1 (default)\n" + " 4: ISO/IEC 8859-2 - Latin alphabet No. 2\n" + " 5: ISO/IEC 8859-3 - Latin alphabet No. 3\n" + " 6: ISO/IEC 8859-4 - Latin alphabet No. 4\n" + " 7: ISO/IEC 8859-5 - Latin/Cyrillic alphabet\n", stdout); + fputs(" 8: ISO/IEC 8859-6 - Latin/Arabic alphabet\n" + " 9: ISO/IEC 8859-7 - Latin/Greek alphabet\n" + " 10: ISO/IEC 8859-8 - Latin/Hebrew alphabet\n" + " 11: ISO/IEC 8859-9 - Latin alphabet No. 5 (Turkish)\n" + " 12: ISO/IEC 8859-10 - Latin alphabet No. 6 (Nordic)\n", stdout); + fputs(" 13: ISO/IEC 8859-11 - Latin/Thai alphabet\n" + " 15: ISO/IEC 8859-13 - Latin alphabet No. 7 (Baltic)\n" + " 16: ISO/IEC 8859-14 - Latin alphabet No. 8 (Celtic)\n" + " 17: ISO/IEC 8859-15 - Latin alphabet No. 9\n" + " 18: ISO/IEC 8859-16 - Latin alphabet No. 10\n", stdout); + fputs(" 20: Shift JIS (JIS X 0208 and JIS X 0201)\n" + " 21: Windows 1250 - Latin 2 (Central Europe)\n" + " 22: Windows 1251 - Cyrillic\n" + " 23: Windows 1252 - Latin 1\n" + " 24: Windows 1256 - Arabic\n", stdout); + fputs(" 25: UTF-16BE (High order byte first)\n" + " 26: UTF-8\n" + " 27: ASCII (ISO/IEC 646 IRV)\n" + " 28: Big5 (Taiwan) Chinese Character Set\n" + " 29: GB 2312 (PRC) Chinese Character Set\n", stdout); + fputs(" 30: Korean Character Set EUC-KR (KS X 1001:2002)\n" + " 31: GBK Chinese Character Set\n" + " 32: GB 18030 Chinese Character Set\n" + " 33: UTF-16LE (Low order byte first)\n" + " 34: UTF-32BE (High order bytes first)\n", stdout); + fputs(" 35: UTF-32LE (Low order bytes first)\n" + "170: ISO/IEC 646 Invariant (ASCII subset)\n" + "899: 8-bit binary data\n", stdout); } /* Verifies that a string (length <= 9) only uses digits. On success returns value in arg */ -static int validate_int(const char source[], int *p_val) { +static int validate_int(const char source[], int len, int *p_val) { int val = 0; int i; - const int length = (int) strlen(source); + const int length = len == -1 ? (int) strlen(source) : len; if (length > 9) { /* Prevent overflow */ return 0; @@ -267,13 +265,67 @@ static int validate_int(const char source[], int *p_val) { return 1; } +/* Verifies that a string is a simplified form of floating point, max 7 significant decimal digits with + optional decimal point. On success returns val in arg. On failure sets `errbuf` */ +static int validate_float(const char source[], float *p_val, char errbuf[64]) { + static const float fract_muls[7] = { 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f }; + int val = 0; + const char *dot = strchr(source, '.'); + int int_len = dot ? (int) (dot - source) : (int) strlen(source); + if (int_len > 9) { + strcpy(errbuf, "integer part must be 7 digits maximum"); /* Say 7 not 9 to "manage expections" */ + return 0; + } + if (int_len) { + int tmp_val; + if (!validate_int(source, int_len, &val)) { + strcpy(errbuf, "integer part must be digits only"); + return 0; + } + for (int_len = 0, tmp_val = val; tmp_val; tmp_val /= 10, int_len++); /* log10(val) */ + if (int_len > 7) { + strcpy(errbuf, "integer part must be 7 digits maximum"); + return 0; + } + } + if (dot && *++dot) { + int val2, fract_len; + const char *e; + for (e = dot + strlen(dot) - 1; e > dot && *e == '0'; e--); /* Ignore trailing zeroes */ + fract_len = (int) (e + 1 - dot); + if (fract_len) { + if (fract_len > 7) { + strcpy(errbuf, "fractional part must be 7 digits maximum"); + return 0; + } + if (!validate_int(dot, fract_len, &val2)) { + strcpy(errbuf, "fractional part must be digits only"); + return 0; + } + if (val2 && int_len + fract_len > 7) { + if (val) { + strcpy(errbuf, "7 significant digits maximum"); + } else { + strcpy(errbuf, "fractional part must be 7 digits maximum"); + } + return 0; + } + *p_val = val + val2 * fract_muls[fract_len - 1]; + } else { + *p_val = (float) val; + } + } else { + *p_val = (float) val; + } + return 1; +} + /* Converts an integer value to its hexadecimal character */ static char itoc(const int source) { if ((source >= 0) && (source <= 9)) { return ('0' + source); - } else { - return ('A' + (source - 10)); } + return ('A' - 10 + source); } /* Converts upper case characters to lower case in a string source[] */ @@ -327,7 +379,8 @@ static int get_barcode_name(const char *barcode_name) { { BARCODE_CODABLOCKF, "codablockf" }, { BARCODE_CODE11, "code11" }, { BARCODE_CODE128, "code128" }, - { BARCODE_CODE128B, "code128b" }, + { BARCODE_CODE128AB, "code128ab" }, + { BARCODE_CODE128AB, "code128b" }, /* Synonym */ { BARCODE_CODE16K, "code16k" }, { BARCODE_C25LOGIC, "code2of5datalogic" }, /* Synonym */ { BARCODE_C25IATA, "code2of5iata" }, /* Synonym */ @@ -616,6 +669,87 @@ static int is_raster(const char *filetype, const int no_png) { return 0; } +/* Helper for `validate_scalexdimdp()` to search for units, returning -2 on error, -1 if not found, else index */ +static int validate_units(char *buf, const char *units[], int units_size) { + int i; + char *unit; + + to_lower(buf); + for (i = 0; i < units_size; i++) { + if ((unit = strstr(buf, units[i])) != NULL) { + if (strlen(units[i]) != strlen(unit)) { + return -2; + } + *unit = '\0'; + break; + } + } + if (i == units_size) { + i = -1; + } + return i; +} + +/* Parse and validate argument "xdim[,resolution]" to "--scalexdimdp" */ +static int validate_scalexdimdp(const char *optarg, float *p_x_dim_mm, float *p_dpmm) { + static const char *x_units[] = { "mm", "in" }; + static const char *r_units[] = { "dpmm", "dpi" }; + char x_buf[7 + 1 + 4 + 1] = {0}; /* Allow for 7 digits + dot + 4-char unit + NUL */ + char r_buf[7 + 1 + 4 + 1] = {0}; /* As above */ + int units_i; /* For `validate_units()` */ + char errbuf[64]; /* For `validate_float()` */ + const char *comma = strchr(optarg, ','); + if (comma) { + if (comma == optarg || comma - optarg >= ARRAY_SIZE(x_buf)) { + fprintf(stderr, "Error 174: scalexdimdp X-dim too %s\n", comma == optarg ? "short" : "long"); + return 0; + } + strncpy(x_buf, optarg, comma - optarg); + comma++; + if (!*comma || strlen(comma) >= ARRAY_SIZE(r_buf)) { + fprintf(stderr, "Error 175: scalexdimdp resolution too %s\n", !*comma ? "short" : "long"); + return 0; + } + strcpy(r_buf, comma); + } else { + if (!*optarg || strlen(optarg) >= ARRAY_SIZE(x_buf)) { + fprintf(stderr, "Error 176: scalexdimdp X-dim too %s\n", !*optarg ? "short" : "long"); + return 0; + } + strcpy(x_buf, optarg); + } + if ((units_i = validate_units(x_buf, x_units, ARRAY_SIZE(x_units))) == -2) { + fprintf(stderr, "Error 177: scalexdimdp X-dim units must occur at end\n"); + return 0; + } + if (!validate_float(x_buf, p_x_dim_mm, errbuf)) { + fprintf(stderr, "Error 178: scalexdimdp X-dim invalid floating point (%s)\n", errbuf); + return 0; + } + if (units_i > 0) { /* Ignore mm */ + *p_x_dim_mm /= 25.4f /*in*/; + } + *p_dpmm = 0.0f; + if (comma) { + if ((units_i = validate_units(r_buf, r_units, ARRAY_SIZE(r_units))) == -2) { + fprintf(stderr, "Error 179: scalexdimdp resolution units must occur at end\n"); + return 0; + } + if (!validate_float(r_buf, p_dpmm, errbuf)) { + fprintf(stderr, "Error 180: scalexdimdp resolution invalid floating point (%s)\n", errbuf); + return 0; + } + if (units_i > 0) { /* Ignore dpmm */ + *p_dpmm /= 25.4f /*dpi*/; + } + } + if (*p_dpmm == 0.0f) { + *p_dpmm = 12.0f; /* 300 dpi */ + } + + return 1; +} + /* Parse and validate Structured Append argument "index,count[,ID]" to "--structapp" */ int validate_structapp(const char *optarg, struct zint_structapp *structapp) { char index[10] = {0}, count[10] = {0}; @@ -651,11 +785,11 @@ int validate_structapp(const char *optarg, struct zint_structapp *structapp) { } strcpy(count, comma); } - if (!validate_int(index, &structapp->index)) { + if (!validate_int(index, -1 /*len*/, &structapp->index)) { fprintf(stderr, "Error 160: Invalid Structured Append index (digits only)\n"); return 0; } - if (!validate_int(count, &structapp->count)) { + if (!validate_int(count, -1 /*len*/, &structapp->count)) { fprintf(stderr, "Error 161: Invalid Structured Append count (digits only)\n"); return 0; } @@ -680,7 +814,7 @@ static int validate_seg(const char *optarg, const int N, struct zint_seg segs[10 return 0; } strncpy(eci, optarg, comma - optarg); - if (!validate_int(eci, &segs[N].eci)) { + if (!validate_int(eci, -1 /*len*/, &segs[N].eci)) { fprintf(stderr, "Error 167: Invalid segment ECI (digits only)\n"); return 0; } @@ -991,7 +1125,9 @@ int main(int argc, char **argv) { char *outfile_extension; int data_arg_num = 0; int seg_count = 0; + float x_dim_mm = 0.0f, dpmm = 0.0f; float float_opt; + char errbuf[64]; /* For `validate_float()` */ arg_opt *arg_opts = (arg_opt *) z_alloca(sizeof(arg_opt) * argc); int no_getopt_error = 1; @@ -1022,7 +1158,7 @@ int main(int argc, char **argv) { OPT_GS1, OPT_GS1NOCHECK, OPT_GS1PARENS, OPT_GSSEP, OPT_GUARDDESCENT, OPT_HEIGHT, OPT_HEIGHTPERROW, OPT_INIT, OPT_MIRROR, OPT_MASK, OPT_MODE, OPT_NOBACKGROUND, OPT_NOQUIETZONES, OPT_NOTEXT, OPT_PRIMARY, OPT_QUIETZONES, - OPT_ROTATE, OPT_ROWS, OPT_SCALE, OPT_SCMVV, OPT_SECURE, + OPT_ROTATE, OPT_ROWS, OPT_SCALE, OPT_SCALEXDIM, OPT_SCMVV, OPT_SECURE, OPT_SEG1, OPT_SEG2, OPT_SEG3, OPT_SEG4, OPT_SEG5, OPT_SEG6, OPT_SEG7, OPT_SEG8, OPT_SEG9, OPT_SEPARATOR, OPT_SMALL, OPT_SQUARE, OPT_STRUCTAPP, OPT_VERBOSE, OPT_VERS, OPT_VWHITESP, OPT_WERROR @@ -1079,6 +1215,7 @@ int main(int argc, char **argv) { {"rotate", 1, NULL, OPT_ROTATE}, {"rows", 1, NULL, OPT_ROWS}, {"scale", 1, NULL, OPT_SCALE}, + {"scalexdimdp", 1, NULL, OPT_SCALEXDIM}, {"scmvv", 1, NULL, OPT_SCMVV}, {"secure", 1, NULL, OPT_SECURE}, {"seg1", 1, NULL, OPT_SEG1}, @@ -1108,7 +1245,7 @@ int main(int argc, char **argv) { switch (c) { case OPT_ADDONGAP: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 139: Invalid add-on gap value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1146,7 +1283,7 @@ int main(int argc, char **argv) { my_symbol->output_options |= BOLD_TEXT; break; case OPT_BORDER: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 107: Invalid border width value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1165,7 +1302,7 @@ int main(int argc, char **argv) { my_symbol->output_options |= CMYK_COLOUR; break; case OPT_COLS: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 131: Invalid columns value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1190,13 +1327,16 @@ int main(int argc, char **argv) { } break; case OPT_DOTSIZE: - my_symbol->dot_size = (float) (atof(optarg)); - if (my_symbol->dot_size < 0.01f) { - /* Zero and negative values are not permitted */ + if (!validate_float(optarg, &float_opt, errbuf)) { + fprintf(stderr, "Error 181: Invalid dot radius floating point (%s)\n", errbuf); + return do_exit(ZINT_ERROR_INVALID_OPTION); + } + if (float_opt >= 0.01f) { + my_symbol->dot_size = float_opt; + } else { fprintf(stderr, "Warning 106: Invalid dot radius value (less than 0.01), ignoring\n"); fflush(stderr); warn_number = ZINT_WARN_INVALID_OPTION; - my_symbol->dot_size = 4.0f / 5.0f; } break; case OPT_DOTTY: @@ -1207,7 +1347,7 @@ int main(int argc, char **argv) { strcpy(my_symbol->outfile, "dummy.txt"); break; case OPT_ECI: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 138: Invalid ECI value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1230,7 +1370,9 @@ int main(int argc, char **argv) { break; case OPT_FILETYPE: /* Select the type of output file */ - if (!supported_filetype(optarg, no_png, &png_refused)) { + if (supported_filetype(optarg, no_png, &png_refused)) { + strncpy(filetype, optarg, (size_t) 3); + } else { if (png_refused) { fprintf(stderr, "Warning 152: PNG format disabled at compile time, ignoring\n"); } else { @@ -1238,12 +1380,10 @@ int main(int argc, char **argv) { } fflush(stderr); warn_number = ZINT_WARN_INVALID_OPTION; - } else { - strncpy(filetype, optarg, (size_t) 3); } break; case OPT_FONTSIZE: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 130: Invalid font size value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1271,7 +1411,10 @@ int main(int argc, char **argv) { my_symbol->output_options |= GS1_GS_SEPARATOR; break; case OPT_GUARDDESCENT: - float_opt = (float) atof(optarg); + if (!validate_float(optarg, &float_opt, errbuf)) { + fprintf(stderr, "Error 182: Invalid guard bar descent floating point (%s)\n", errbuf); + return do_exit(ZINT_ERROR_INVALID_OPTION); + } if (float_opt >= 0.0f && float_opt <= 50.0f) { my_symbol->guard_descent = float_opt; } else { @@ -1282,7 +1425,10 @@ int main(int argc, char **argv) { } break; case OPT_HEIGHT: - float_opt = (float) atof(optarg); + if (!validate_float(optarg, &float_opt, errbuf)) { + fprintf(stderr, "Error 183: Invalid symbol height floating point (%s)\n", errbuf); + return do_exit(ZINT_ERROR_INVALID_OPTION); + } if (float_opt >= 0.5f && float_opt <= 2000.0f) { my_symbol->height = float_opt; } else { @@ -1303,7 +1449,7 @@ int main(int argc, char **argv) { mirror_mode = 1; break; case OPT_MASK: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 148: Invalid mask value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1317,7 +1463,7 @@ int main(int argc, char **argv) { } break; case OPT_MODE: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 136: Invalid mode value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1352,7 +1498,7 @@ int main(int argc, char **argv) { break; case OPT_ROTATE: /* Only certain inputs allowed */ - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 117: Invalid rotation value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1374,7 +1520,7 @@ int main(int argc, char **argv) { } break; case OPT_ROWS: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 132: Invalid rows value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1387,17 +1533,37 @@ int main(int argc, char **argv) { } break; case OPT_SCALE: - my_symbol->scale = (float) (atof(optarg)); - if (my_symbol->scale < 0.01f) { - /* Zero and negative values are not permitted */ + if (!validate_float(optarg, &float_opt, errbuf)) { + fprintf(stderr, "Error 184: Invalid scale floating point (%s)\n", errbuf); + return do_exit(ZINT_ERROR_INVALID_OPTION); + } + if (float_opt >= 0.01f) { + my_symbol->scale = float_opt; + } else { fprintf(stderr, "Warning 105: Invalid scale value (less than 0.01), ignoring\n"); fflush(stderr); warn_number = ZINT_WARN_INVALID_OPTION; - my_symbol->scale = 1.0f; + } + break; + case OPT_SCALEXDIM: + if (!validate_scalexdimdp(optarg, &x_dim_mm, &dpmm)) { + return do_exit(ZINT_ERROR_INVALID_OPTION); + } + if (x_dim_mm > 10.0f || dpmm > 1000.0f) { + if (x_dim_mm > 10.0f) { + fprintf(stderr, + "Warning 185: scalexdimdp X-dim (%g) out of range (> 10), ignoring\n", x_dim_mm); + } else { + fprintf(stderr, + "Warning 186: scalexdimdp resolution (%g) out of range (> 1000), ignoring\n", dpmm); + } + fflush(stderr); + warn_number = ZINT_WARN_INVALID_OPTION; + x_dim_mm = dpmm = 0.0f; } break; case OPT_SCMVV: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 149: Invalid Structured Carrier Message version value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1412,7 +1578,7 @@ int main(int argc, char **argv) { } break; case OPT_SECURE: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 134: Invalid ECC value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1452,7 +1618,7 @@ int main(int argc, char **argv) { } break; case OPT_SEPARATOR: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 128: Invalid separator value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1481,7 +1647,7 @@ int main(int argc, char **argv) { my_symbol->debug = 1; break; case OPT_VERS: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 133: Invalid version value (digits only)\n"); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1494,7 +1660,7 @@ int main(int argc, char **argv) { } break; case OPT_VWHITESP: - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 153: Invalid vertical whitespace value '%s' (digits only)\n", optarg); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1528,7 +1694,7 @@ int main(int argc, char **argv) { break; case 'b': - if (!validate_int(optarg, &val) && !(val = get_barcode_name(optarg))) { + if (!validate_int(optarg, -1 /*len*/, &val) && !(val = get_barcode_name(optarg))) { fprintf(stderr, "Error 119: Invalid barcode type '%s'\n", optarg); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1536,7 +1702,7 @@ int main(int argc, char **argv) { break; case 'w': - if (!validate_int(optarg, &val)) { + if (!validate_int(optarg, -1 /*len*/, &val)) { fprintf(stderr, "Error 120: Invalid horizontal whitespace value '%s' (digits only)\n", optarg); return do_exit(ZINT_ERROR_INVALID_OPTION); } @@ -1570,7 +1736,7 @@ int main(int argc, char **argv) { input_cnt++; } else { fprintf(stderr, "Warning 143: Can only define one input file in batch mode, ignoring '%s'\n", - optarg); + optarg); fflush(stderr); warn_number = ZINT_WARN_INVALID_OPTION; } @@ -1601,6 +1767,15 @@ int main(int argc, char **argv) { break; } } + if (optind != argc) { + if (optind + 1 == argc) { + fprintf(stderr, "Warning 191: extra argument '%s' ignored\n", argv[optind]); + } else { + fprintf(stderr, "Warning 192: extra arguments beginning with '%s' ignored\n", argv[optind]); + } + fflush(stderr); + warn_number = ZINT_WARN_INVALID_OPTION; + } if (data_arg_num) { const int symbology = my_symbol->symbology; @@ -1648,11 +1823,26 @@ int main(int argc, char **argv) { strcpy(filetype, no_png ? "gif" : "png"); } } + if (dpmm) { /* Allow `x_dim_mm` to be zero */ + if (x_dim_mm == 0.0f) { + x_dim_mm = ZBarcode_Default_Xdim(symbology); + } + float_opt = ZBarcode_Scale_From_XdimDp(symbology, x_dim_mm, dpmm, filetype); + if (float_opt > 0.0f) { + my_symbol->scale = float_opt; + my_symbol->dpmm = dpmm; + } else { + fprintf(stderr, "Warning 187: Invalid scalexdimdp X-dim (%g), resolution (%g) combo, ignoring\n", + x_dim_mm, dpmm); + fflush(stderr); + warn_number = ZINT_WARN_INVALID_OPTION; + } + } if (((symbology != BARCODE_MAXICODE && my_symbol->scale < 0.5f) || my_symbol->scale < 0.2f) && is_raster(filetype, no_png)) { const int min = symbology != BARCODE_MAXICODE ? 5 : 2; fprintf(stderr, "Warning 145: Scaling less than 0.%d will be set to 0.%d for '%s' output\n", min, min, - filetype); + filetype); fflush(stderr); warn_number = ZINT_WARN_INVALID_OPTION; } @@ -1681,11 +1871,26 @@ int main(int argc, char **argv) { if (filetype[0] != '\0') { set_extension(my_symbol->outfile, filetype); } + if (dpmm) { /* Allow `x_dim_mm` to be zero */ + if (x_dim_mm == 0.0f) { + x_dim_mm = ZBarcode_Default_Xdim(symbology); + } + float_opt = ZBarcode_Scale_From_XdimDp(symbology, x_dim_mm, dpmm, get_extension(my_symbol->outfile)); + if (float_opt > 0.0f) { + my_symbol->scale = float_opt; + my_symbol->dpmm = dpmm; + } else { + fprintf(stderr, "Warning 190: Invalid scalexdimdp X-dim (%g), resolution (%g) combo, ignoring\n", + x_dim_mm, dpmm); + fflush(stderr); + warn_number = ZINT_WARN_INVALID_OPTION; + } + } if (((symbology != BARCODE_MAXICODE && my_symbol->scale < 0.5f) || my_symbol->scale < 0.2f) && is_raster(get_extension(my_symbol->outfile), no_png)) { const int min = symbology != BARCODE_MAXICODE ? 5 : 2; fprintf(stderr, "Warning 146: Scaling less than 0.%d will be set to 0.%d for '%s' output\n", min, min, - get_extension(my_symbol->outfile)); + get_extension(my_symbol->outfile)); fflush(stderr); warn_number = ZINT_WARN_INVALID_OPTION; } diff --git a/frontend/tests/test_args.c b/frontend/tests/test_args.c index 684a609e..00f10b54 100644 --- a/frontend/tests/test_args.c +++ b/frontend/tests/test_args.c @@ -162,7 +162,7 @@ static void arg_bool(char *cmd, const char *opt, int val) { static void arg_double(char *cmd, const char *opt, double val) { if (val != -1) { - sprintf(cmd + (int) strlen(cmd), "%s%s%g", strlen(cmd) ? " " : "", opt, val); + sprintf(cmd + (int) strlen(cmd), "%s%s%.8f", strlen(cmd) ? " " : "", opt, val); } } @@ -560,6 +560,7 @@ static void test_input(const testCtx *const p_ctx) { arg_input(cmd, input_filename, data[i].input); arg_data(cmd, "-o ", data[i].outfile); + if (!data[i].expected) printf("++++ Following Error 778 expected, ignore\n"); assert_nonnull(exec(cmd, buf, sizeof(buf) - 1, debug, i, NULL), "i:%d exec(%s) NULL\n", i, cmd); outfile = data[i].expected; @@ -731,6 +732,7 @@ static void test_batch_large(const testCtx *const p_ctx) { strcat(data_buf, "\n"); have_input = arg_input(cmd, input_filename, data_buf); + if (!data[i].expected) printf("++++ Following Error 541 expected, ignore\n"); assert_nonnull(exec(cmd, buf, sizeof(buf) - 1, debug, i, NULL), "i:%d exec(%s) NULL\n", i, cmd); if (data[i].expected) { assert_zero(remove(data[i].expected), "i:%d remove(%s) != 0 (%d: %s)\n", i, data[i].expected, errno, strerror(errno)); @@ -779,38 +781,39 @@ static void test_checks(const testCtx *const p_ctx) { /* 2*/ { 13, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 140: Add-on gap out of range (7 to 12), ignoring" }, /* 3*/ { -1, -2, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 107: Invalid border width value (digits only)" }, /* 4*/ { -1, 1001, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 108: Border width out of range (0 to 1000), ignoring" }, - /* 5*/ { -1, -1, -1, 0.009, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 106: Invalid dot radius value (less than 0.01), ignoring" }, - /* 6*/ { -1, -1, -2, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 131: Invalid columns value (digits only)" }, - /* 7*/ { -1, -1, 201, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 111: Number of columns out of range (1 to 200), ignoring" }, - /* 8*/ { -1, -1, -1, -1, -2, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 138: Invalid ECI value (digits only)" }, - /* 9*/ { -1, -1, -1, -1, 1000000, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 118: ECI code out of range (0 to 999999), ignoring" }, - /* 10*/ { -1, -1, -1, -1, -1, "jpg", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 142: File type 'jpg' not supported, ignoring" }, - /* 11*/ { -1, -1, -1, -1, -1, NULL, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 110: Symbol height '-2' out of range (0.5 to 2000), ignoring" }, - /* 12*/ { -1, -1, -1, -1, -1, NULL, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 110: Symbol height '0' out of range (0.5 to 2000), ignoring" }, - /* 13*/ { -1, -1, -1, -1, -1, NULL, 2001, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 110: Symbol height '2001' out of range (0.5 to 2000), ignoring" }, - /* 14*/ { -1, -1, -1, -1, -1, NULL, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 135: Guard bar descent '-2' out of range (0 to 50), ignoring" }, - /* 15*/ { -1, -1, -1, -1, -1, NULL, -1, 50.1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 135: Guard bar descent '50.1' out of range (0 to 50), ignoring" }, - /* 16*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 148: Invalid mask value (digits only)" }, - /* 17*/ { -1, -1, -1, -1, -1, NULL, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 147: Mask value out of range (0 to 7), ignoring" }, - /* 18*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 116: Mode value out of range (0 to 6), ignoring" }, - /* 19*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, "Error 117: Invalid rotation value (digits only)" }, - /* 20*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 137: Invalid rotation parameter (0, 90, 180 or 270 only), ignoring" }, - /* 21*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, "Error 132: Invalid rows value (digits only)" }, - /* 22*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, 91, -1, -1, -1, -1, -1, -1, -1, "Warning 112: Number of rows out of range (1 to 90), ignoring" }, - /* 23*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, "Warning 105: Invalid scale value (less than 0.01), ignoring" }, - /* 24*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, 0.49, -1, -1, -1, -1, -1, -1, "Warning 146: Scaling less than 0.5 will be set to 0.5 for 'gif' output" }, - /* 25*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, "Error 149: Invalid Structured Carrier Message version value (digits only)" }, - /* 26*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, 100, -1, -1, -1, -1, -1, "Warning 150: Structured Carrier Message version out of range (0 to 99), ignoring" }, - /* 27*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, "Error 134: Invalid ECC value (digits only)" }, - /* 28*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, "Warning 114: ECC level out of range (0 to 8), ignoring" }, - /* 29*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, "Error 128: Invalid separator value (digits only)" }, - /* 30*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, "Warning 127: Separator value out of range (0 to 4), ignoring" }, - /* 31*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, "Error 133: Invalid version value (digits only)" }, - /* 32*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1000, -1, -1, "Warning 113: Version value out of range (1 to 999), ignoring" }, - /* 33*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, "Error 153: Invalid vertical whitespace value '-2' (digits only)" }, - /* 34*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1001, -1, "Warning 154: Vertical whitespace value out of range (0 to 1000), ignoring" }, - /* 35*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, "Error 120: Invalid horizontal whitespace value '-2' (digits only)" }, - /* 36*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1001, "Warning 121: Horizontal whitespace value out of range (0 to 1000), ignoring" }, + /* 5*/ { -1, -1, -1, 12345678, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 181: Invalid dot radius floating point (integer part must be 7 digits maximum)" }, + /* 6*/ { -1, -1, -1, 0.009, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 106: Invalid dot radius value (less than 0.01), ignoring" }, + /* 7*/ { -1, -1, -2, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 131: Invalid columns value (digits only)" }, + /* 8*/ { -1, -1, 201, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 111: Number of columns out of range (1 to 200), ignoring" }, + /* 9*/ { -1, -1, -1, -1, -2, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 138: Invalid ECI value (digits only)" }, + /* 10*/ { -1, -1, -1, -1, 1000000, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 118: ECI code out of range (0 to 999999), ignoring" }, + /* 11*/ { -1, -1, -1, -1, -1, "jpg", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 142: File type 'jpg' not supported, ignoring" }, + /* 12*/ { -1, -1, -1, -1, -1, NULL, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 183: Invalid symbol height floating point (integer part must be digits only)" }, + /* 13*/ { -1, -1, -1, -1, -1, NULL, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 110: Symbol height '0' out of range (0.5 to 2000), ignoring" }, + /* 14*/ { -1, -1, -1, -1, -1, NULL, 2001, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 110: Symbol height '2001' out of range (0.5 to 2000), ignoring" }, + /* 15*/ { -1, -1, -1, -1, -1, NULL, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 182: Invalid guard bar descent floating point (integer part must be digits only)" }, + /* 16*/ { -1, -1, -1, -1, -1, NULL, -1, 50.1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 135: Guard bar descent '50.1' out of range (0 to 50), ignoring" }, + /* 17*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 148: Invalid mask value (digits only)" }, + /* 18*/ { -1, -1, -1, -1, -1, NULL, -1, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 147: Mask value out of range (0 to 7), ignoring" }, + /* 19*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 116: Mode value out of range (0 to 6), ignoring" }, + /* 20*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, "Error 117: Invalid rotation value (digits only)" }, + /* 21*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 137: Invalid rotation parameter (0, 90, 180 or 270 only), ignoring" }, + /* 22*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, "Error 132: Invalid rows value (digits only)" }, + /* 23*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, 91, -1, -1, -1, -1, -1, -1, -1, "Warning 112: Number of rows out of range (1 to 90), ignoring" }, + /* 24*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, "Error 184: Invalid scale floating point (integer part must be digits only)" }, + /* 25*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, 0.49, -1, -1, -1, -1, -1, -1, "Warning 146: Scaling less than 0.5 will be set to 0.5 for 'gif' output" }, + /* 26*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, "Error 149: Invalid Structured Carrier Message version value (digits only)" }, + /* 27*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, 100, -1, -1, -1, -1, -1, "Warning 150: Structured Carrier Message version out of range (0 to 99), ignoring" }, + /* 28*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, "Error 134: Invalid ECC value (digits only)" }, + /* 29*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, "Warning 114: ECC level out of range (0 to 8), ignoring" }, + /* 30*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, "Error 128: Invalid separator value (digits only)" }, + /* 31*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, "Warning 127: Separator value out of range (0 to 4), ignoring" }, + /* 32*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, "Error 133: Invalid version value (digits only)" }, + /* 33*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1000, -1, -1, "Warning 113: Version value out of range (1 to 999), ignoring" }, + /* 34*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, "Error 153: Invalid vertical whitespace value '-2' (digits only)" }, + /* 35*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1001, -1, "Warning 154: Vertical whitespace value out of range (0 to 1000), ignoring" }, + /* 36*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, "Error 120: Invalid horizontal whitespace value '-2' (digits only)" }, + /* 37*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1001, "Warning 121: Horizontal whitespace value out of range (0 to 1000), ignoring" }, }; int data_size = ARRAY_SIZE(data); int i; @@ -853,7 +856,7 @@ static void test_checks(const testCtx *const p_ctx) { strcat(cmd, " 2>&1"); assert_nonnull(exec(cmd, buf, sizeof(buf) - 1, debug, i, NULL), "i:%d exec(%s) NULL\n", i, cmd); - assert_zero(strcmp(buf, data[i].expected), "i:%d buf (%s) != expected (%s)\n", i, buf, data[i].expected); + assert_zero(strcmp(buf, data[i].expected), "i:%d buf (%s) != expected (%s) (%s)\n", i, buf, data[i].expected, cmd); if (strncmp(data[i].expected, "Warning", 7) == 0) { assert_zero(remove(outfilename), "i:%d remove(%s) != 0 (%d: %s)\n", i, outfilename, errno, strerror(errno)); @@ -966,115 +969,116 @@ static void test_barcode_symbology(const testCtx *const p_ctx) { /* 88*/ { "MaxiCode", "1", NULL, 0, "BARCODE_MAXICODE (57)," }, /* 89*/ { "QR CODE", "1", NULL, 0, "BARCODE_QRCODE (58)," }, /* 90*/ { "qr", "1", NULL, 0, "BARCODE_QRCODE (58)," }, /* Synonym */ - /* 91*/ { "Code 128 B", "1", NULL, 0, "BARCODE_CODE128B (60)," }, - /* 92*/ { "AUS POST", "12345678901234567890123", NULL, 0, "BARCODE_AUSPOST (63)," }, - /* 93*/ { "AusReply", "12345678", NULL, 0, "BARCODE_AUSREPLY (66)," }, - /* 94*/ { "AUSROUTE", "12345678", NULL, 0, "BARCODE_AUSROUTE (67)," }, - /* 95*/ { "AUS REDIRECT", "12345678", NULL, 0, "BARCODE_AUSREDIRECT (68)," }, - /* 96*/ { "isbnx", "123456789", NULL, 0, "BARCODE_ISBNX (69)," }, - /* 97*/ { "rm4scc", "1", NULL, 0, "BARCODE_RM4SCC (70)," }, - /* 98*/ { "DataMatrix", "1", NULL, 0, "BARCODE_DATAMATRIX (71)," }, - /* 99*/ { "EAN14", "1", NULL, 0, "BARCODE_EAN14 (72)," }, - /*100*/ { "vin", "12345678701234567", NULL, 0, "BARCODE_VIN (73)" }, - /*101*/ { "CodaBlock-F", "1", NULL, 0, "BARCODE_CODABLOCKF (74)," }, - /*102*/ { "NVE18", "1", NULL, 0, "BARCODE_NVE18 (75)," }, - /*103*/ { "Japan Post", "1", NULL, 0, "BARCODE_JAPANPOST (76)," }, - /*104*/ { "Korea Post", "1", NULL, 0, "BARCODE_KOREAPOST (77)," }, - /*105*/ { "DBar Stk", "1", NULL, 0, "BARCODE_DBAR_STK (79)," }, - /*106*/ { "rss14stack", "1", NULL, 0, "BARCODE_DBAR_STK (79)," }, - /*107*/ { "DataBar Stk", "1", NULL, 0, "BARCODE_DBAR_STK (79)," }, - /*108*/ { "DataBar Stacked", "1", NULL, 0, "BARCODE_DBAR_STK (79)," }, - /*109*/ { "DBar Omn Stk", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, - /*110*/ { "RSS14STACK OMNI", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, - /*111*/ { "DataBar Omn Stk", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, - /*112*/ { "DataBar Stacked Omn", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, - /*113*/ { "DataBar Stacked Omni", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, - /*114*/ { "DBar Exp Stk", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, - /*115*/ { "rss_expstack", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, - /*116*/ { "DataBar Exp Stk", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, - /*117*/ { "DataBar Expanded Stk", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, - /*118*/ { "DataBar Expanded Stacked", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, - /*119*/ { "planet", "12345678901", NULL, 0, "BARCODE_PLANET (82)," }, - /*120*/ { "MicroPDF417", "1", NULL, 0, "BARCODE_MICROPDF417 (84)," }, - /*121*/ { "USPS IMail", "12345678901234567890", NULL, 0, "BARCODE_USPS_IMAIL (85)," }, - /*122*/ { "OneCode", "12345678901234567890", NULL, 0, "BARCODE_USPS_IMAIL (85)," }, - /*123*/ { "plessey", "1", NULL, 0, "BARCODE_PLESSEY (86)," }, - /*124*/ { "telepen num", "1", NULL, 0, "BARCODE_TELEPEN_NUM (87)," }, - /*125*/ { "ITF14", "1", NULL, 0, "BARCODE_ITF14 (89)," }, - /*126*/ { "KIX", "1", NULL, 0, "BARCODE_KIX (90)," }, - /*127*/ { "Aztec", "1", NULL, 0, "BARCODE_AZTEC (92)," }, - /*128*/ { "Aztec Code", "1", NULL, 0, "BARCODE_AZTEC (92)," }, /* Synonym */ - /*129*/ { "daft", "D", NULL, 0, "BARCODE_DAFT (93)," }, - /*130*/ { "DPD", "0123456789012345678901234567", NULL, 0, "BARCODE_DPD (96)," }, - /*131*/ { "Micro QR", "1", NULL, 0, "BARCODE_MICROQR (97)," }, - /*132*/ { "Micro QR Code", "1", NULL, 0, "BARCODE_MICROQR (97)," }, - /*133*/ { "hibc128", "1", NULL, 0, "BARCODE_HIBC_128 (98)," }, - /*134*/ { "hibccode128", "1", NULL, 0, "BARCODE_HIBC_128 (98)," }, /* Synonym */ - /*135*/ { "hibc39", "1", NULL, 0, "BARCODE_HIBC_39 (99)," }, - /*136*/ { "hibccode39", "1", NULL, 0, "BARCODE_HIBC_39 (99)," }, /* Synonym */ - /*137*/ { "hibcdatamatrix", "1", NULL, 0, "BARCODE_HIBC_DM (102)," }, /* Synonym */ - /*138*/ { "hibcdm", "1", NULL, 0, "BARCODE_HIBC_DM (102)," }, - /*139*/ { "HIBC qr", "1", NULL, 0, "BARCODE_HIBC_QR (104)," }, - /*140*/ { "HIBC QR Code", "1", NULL, 0, "BARCODE_HIBC_QR (104)," }, /* Synonym */ - /*141*/ { "HIBCPDF", "1", NULL, 0, "BARCODE_HIBC_PDF (106)," }, - /*142*/ { "HIBCPDF417", "1", NULL, 0, "BARCODE_HIBC_PDF (106)," }, /* Synonym */ - /*143*/ { "HIBCMICPDF", "1", NULL, 0, "BARCODE_HIBC_MICPDF (108)," }, - /*144*/ { "HIBC Micro PDF", "1", NULL, 0, "BARCODE_HIBC_MICPDF (108)," }, /* Synonym */ - /*145*/ { "HIBC Micro PDF417", "1", NULL, 0, "BARCODE_HIBC_MICPDF (108)," }, /* Synonym */ - /*146*/ { "HIBC BlockF", "1", NULL, 0, "BARCODE_HIBC_BLOCKF (110)," }, - /*147*/ { "HIBC CodaBlock-F", "1", NULL, 0, "BARCODE_HIBC_BLOCKF (110)," }, /* Synonym */ - /*148*/ { "HIBC Aztec", "1", NULL, 0, "BARCODE_HIBC_AZTEC (112)," }, - /*149*/ { "DotCode", "1", NULL, 0, "BARCODE_DOTCODE (115)," }, - /*150*/ { "Han Xin", "1", NULL, 0, "BARCODE_HANXIN (116)," }, - /*151*/ { "Mailmark", "01000000000000000AA00AA0A", NULL, 0, "BARCODE_MAILMARK (121)," }, - /*152*/ { "azrune", "1", NULL, 0, "BARCODE_AZRUNE (128)," }, - /*153*/ { "aztecrune", "1", NULL, 0, "BARCODE_AZRUNE (128)," }, /* Synonym */ - /*154*/ { "aztecrunes", "1", NULL, 0, "BARCODE_AZRUNE (128)," }, /* Synonym */ - /*155*/ { "code32", "1", NULL, 0, "BARCODE_CODE32 (129)," }, - /*156*/ { "eanx cc", "[20]01", "1234567890128", 0, "BARCODE_EANX_CC (130)," }, - /*157*/ { "eancc", "[20]01", "1234567890128", 0, "BARCODE_EANX_CC (130)," }, - /*158*/ { "GS1 128 CC", "[01]12345678901231", "[20]01", 0, "BARCODE_GS1_128_CC (131)," }, - /*159*/ { "EAN128 CC", "[01]12345678901231", "[20]01", 0, "BARCODE_GS1_128_CC (131)," }, - /*160*/ { "dbaromncc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMN_CC (132)," }, - /*161*/ { "rss14 cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMN_CC (132)," }, - /*162*/ { "databaromncc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMN_CC (132)," }, - /*163*/ { "databaromnicc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMN_CC (132)," }, - /*164*/ { "dbarltdcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_LTD_CC (133)," }, - /*165*/ { "rss ltd cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_LTD_CC (133)," }, - /*166*/ { "databarltdcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_LTD_CC (133)," }, - /*167*/ { "databarlimitedcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_LTD_CC (133)," }, - /*168*/ { "dbarexpcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXP_CC (134)," }, - /*169*/ { "rss exp cc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXP_CC (134)," }, - /*170*/ { "databarexpcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXP_CC (134)," }, - /*171*/ { "databar expanded cc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXP_CC (134)," }, - /*172*/ { "upcacc", "[20]01", "12345678901", 0, "BARCODE_UPCA_CC (135)," }, - /*173*/ { "upcecc", "[20]01", "1234567", 0, "BARCODE_UPCE_CC (136)," }, - /*174*/ { "dbar stk cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_STK_CC (137)," }, - /*175*/ { "rss14stackcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_STK_CC (137)," }, - /*176*/ { "databar stk cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_STK_CC (137)," }, - /*177*/ { "databar stacked cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_STK_CC (137)," }, - /*178*/ { "dbaromnstkcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, - /*179*/ { "BARCODE_RSS14_OMNI_CC", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, - /*180*/ { "databaromnstkcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, - /*181*/ { "databar stacked omncc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, - /*182*/ { "databar stacked omni cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, - /*183*/ { "dbarexpstkcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, - /*184*/ { "RSS EXPSTACK CC", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, - /*185*/ { "databarexpstkcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, - /*186*/ { "databar expanded stkcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, - /*187*/ { "databar expanded stacked cc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, - /*188*/ { "Channel", "1", NULL, 0, "BARCODE_CHANNEL (140)," }, - /*189*/ { "Channel Code", "1", NULL, 0, "BARCODE_CHANNEL (140)," }, - /*190*/ { "CodeOne", "1", NULL, 0, "BARCODE_CODEONE (141)," }, - /*191*/ { "Grid Matrix", "1", NULL, 0, "BARCODE_GRIDMATRIX (142)," }, - /*192*/ { "UPN QR", "1", NULL, 0, "BARCODE_UPNQR (143)," }, - /*193*/ { "UPN QR Code", "1", NULL, 0, "BARCODE_UPNQR (143)," }, /* Synonym */ - /*194*/ { "ultra", "1", NULL, 0, "BARCODE_ULTRA (144)," }, - /*195*/ { "ultracode", "1", NULL, 0, "BARCODE_ULTRA (144)," }, /* Synonym */ - /*196*/ { "rMQR", "1", NULL, 0, "BARCODE_RMQR (145)," }, - /*197*/ { "bc412", "1234567", NULL, 0, "BARCODE_BC412 (146)," }, - /*198*/ { "x", "1", NULL, 1, "Error 119: Invalid barcode type 'x'" }, - /*199*/ { "\177", "1", NULL, 1, "Error 119: Invalid barcode type '\177'" }, + /* 91*/ { "Code 128 B", "1", NULL, 0, "BARCODE_CODE128AB (60)," }, + /* 92*/ { "Code 128 aB", "1", NULL, 0, "BARCODE_CODE128AB (60)," }, + /* 93*/ { "AUS POST", "12345678901234567890123", NULL, 0, "BARCODE_AUSPOST (63)," }, + /* 94*/ { "AusReply", "12345678", NULL, 0, "BARCODE_AUSREPLY (66)," }, + /* 95*/ { "AUSROUTE", "12345678", NULL, 0, "BARCODE_AUSROUTE (67)," }, + /* 96*/ { "AUS REDIRECT", "12345678", NULL, 0, "BARCODE_AUSREDIRECT (68)," }, + /* 97*/ { "isbnx", "123456789", NULL, 0, "BARCODE_ISBNX (69)," }, + /* 98*/ { "rm4scc", "1", NULL, 0, "BARCODE_RM4SCC (70)," }, + /* 99*/ { "DataMatrix", "1", NULL, 0, "BARCODE_DATAMATRIX (71)," }, + /*100*/ { "EAN14", "1", NULL, 0, "BARCODE_EAN14 (72)," }, + /*101*/ { "vin", "12345678701234567", NULL, 0, "BARCODE_VIN (73)" }, + /*102*/ { "CodaBlock-F", "1", NULL, 0, "BARCODE_CODABLOCKF (74)," }, + /*103*/ { "NVE18", "1", NULL, 0, "BARCODE_NVE18 (75)," }, + /*104*/ { "Japan Post", "1", NULL, 0, "BARCODE_JAPANPOST (76)," }, + /*105*/ { "Korea Post", "1", NULL, 0, "BARCODE_KOREAPOST (77)," }, + /*106*/ { "DBar Stk", "1", NULL, 0, "BARCODE_DBAR_STK (79)," }, + /*107*/ { "rss14stack", "1", NULL, 0, "BARCODE_DBAR_STK (79)," }, + /*108*/ { "DataBar Stk", "1", NULL, 0, "BARCODE_DBAR_STK (79)," }, + /*109*/ { "DataBar Stacked", "1", NULL, 0, "BARCODE_DBAR_STK (79)," }, + /*110*/ { "DBar Omn Stk", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, + /*111*/ { "RSS14STACK OMNI", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, + /*112*/ { "DataBar Omn Stk", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, + /*113*/ { "DataBar Stacked Omn", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, + /*114*/ { "DataBar Stacked Omni", "1", NULL, 0, "BARCODE_DBAR_OMNSTK (80)," }, + /*115*/ { "DBar Exp Stk", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, + /*116*/ { "rss_expstack", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, + /*117*/ { "DataBar Exp Stk", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, + /*118*/ { "DataBar Expanded Stk", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, + /*119*/ { "DataBar Expanded Stacked", "[20]01", NULL, 0, "BARCODE_DBAR_EXPSTK (81)," }, + /*120*/ { "planet", "12345678901", NULL, 0, "BARCODE_PLANET (82)," }, + /*121*/ { "MicroPDF417", "1", NULL, 0, "BARCODE_MICROPDF417 (84)," }, + /*122*/ { "USPS IMail", "12345678901234567890", NULL, 0, "BARCODE_USPS_IMAIL (85)," }, + /*123*/ { "OneCode", "12345678901234567890", NULL, 0, "BARCODE_USPS_IMAIL (85)," }, + /*124*/ { "plessey", "1", NULL, 0, "BARCODE_PLESSEY (86)," }, + /*125*/ { "telepen num", "1", NULL, 0, "BARCODE_TELEPEN_NUM (87)," }, + /*126*/ { "ITF14", "1", NULL, 0, "BARCODE_ITF14 (89)," }, + /*127*/ { "KIX", "1", NULL, 0, "BARCODE_KIX (90)," }, + /*128*/ { "Aztec", "1", NULL, 0, "BARCODE_AZTEC (92)," }, + /*129*/ { "Aztec Code", "1", NULL, 0, "BARCODE_AZTEC (92)," }, /* Synonym */ + /*130*/ { "daft", "D", NULL, 0, "BARCODE_DAFT (93)," }, + /*131*/ { "DPD", "0123456789012345678901234567", NULL, 0, "BARCODE_DPD (96)," }, + /*132*/ { "Micro QR", "1", NULL, 0, "BARCODE_MICROQR (97)," }, + /*133*/ { "Micro QR Code", "1", NULL, 0, "BARCODE_MICROQR (97)," }, + /*134*/ { "hibc128", "1", NULL, 0, "BARCODE_HIBC_128 (98)," }, + /*135*/ { "hibccode128", "1", NULL, 0, "BARCODE_HIBC_128 (98)," }, /* Synonym */ + /*136*/ { "hibc39", "1", NULL, 0, "BARCODE_HIBC_39 (99)," }, + /*137*/ { "hibccode39", "1", NULL, 0, "BARCODE_HIBC_39 (99)," }, /* Synonym */ + /*138*/ { "hibcdatamatrix", "1", NULL, 0, "BARCODE_HIBC_DM (102)," }, /* Synonym */ + /*139*/ { "hibcdm", "1", NULL, 0, "BARCODE_HIBC_DM (102)," }, + /*140*/ { "HIBC qr", "1", NULL, 0, "BARCODE_HIBC_QR (104)," }, + /*141*/ { "HIBC QR Code", "1", NULL, 0, "BARCODE_HIBC_QR (104)," }, /* Synonym */ + /*142*/ { "HIBCPDF", "1", NULL, 0, "BARCODE_HIBC_PDF (106)," }, + /*143*/ { "HIBCPDF417", "1", NULL, 0, "BARCODE_HIBC_PDF (106)," }, /* Synonym */ + /*144*/ { "HIBCMICPDF", "1", NULL, 0, "BARCODE_HIBC_MICPDF (108)," }, + /*145*/ { "HIBC Micro PDF", "1", NULL, 0, "BARCODE_HIBC_MICPDF (108)," }, /* Synonym */ + /*146*/ { "HIBC Micro PDF417", "1", NULL, 0, "BARCODE_HIBC_MICPDF (108)," }, /* Synonym */ + /*147*/ { "HIBC BlockF", "1", NULL, 0, "BARCODE_HIBC_BLOCKF (110)," }, + /*148*/ { "HIBC CodaBlock-F", "1", NULL, 0, "BARCODE_HIBC_BLOCKF (110)," }, /* Synonym */ + /*149*/ { "HIBC Aztec", "1", NULL, 0, "BARCODE_HIBC_AZTEC (112)," }, + /*150*/ { "DotCode", "1", NULL, 0, "BARCODE_DOTCODE (115)," }, + /*151*/ { "Han Xin", "1", NULL, 0, "BARCODE_HANXIN (116)," }, + /*152*/ { "Mailmark", "01000000000000000AA00AA0A", NULL, 0, "BARCODE_MAILMARK (121)," }, + /*153*/ { "azrune", "1", NULL, 0, "BARCODE_AZRUNE (128)," }, + /*154*/ { "aztecrune", "1", NULL, 0, "BARCODE_AZRUNE (128)," }, /* Synonym */ + /*155*/ { "aztecrunes", "1", NULL, 0, "BARCODE_AZRUNE (128)," }, /* Synonym */ + /*156*/ { "code32", "1", NULL, 0, "BARCODE_CODE32 (129)," }, + /*157*/ { "eanx cc", "[20]01", "1234567890128", 0, "BARCODE_EANX_CC (130)," }, + /*158*/ { "eancc", "[20]01", "1234567890128", 0, "BARCODE_EANX_CC (130)," }, + /*159*/ { "GS1 128 CC", "[01]12345678901231", "[20]01", 0, "BARCODE_GS1_128_CC (131)," }, + /*160*/ { "EAN128 CC", "[01]12345678901231", "[20]01", 0, "BARCODE_GS1_128_CC (131)," }, + /*161*/ { "dbaromncc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMN_CC (132)," }, + /*162*/ { "rss14 cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMN_CC (132)," }, + /*163*/ { "databaromncc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMN_CC (132)," }, + /*164*/ { "databaromnicc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMN_CC (132)," }, + /*165*/ { "dbarltdcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_LTD_CC (133)," }, + /*166*/ { "rss ltd cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_LTD_CC (133)," }, + /*167*/ { "databarltdcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_LTD_CC (133)," }, + /*168*/ { "databarlimitedcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_LTD_CC (133)," }, + /*169*/ { "dbarexpcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXP_CC (134)," }, + /*170*/ { "rss exp cc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXP_CC (134)," }, + /*171*/ { "databarexpcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXP_CC (134)," }, + /*172*/ { "databar expanded cc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXP_CC (134)," }, + /*173*/ { "upcacc", "[20]01", "12345678901", 0, "BARCODE_UPCA_CC (135)," }, + /*174*/ { "upcecc", "[20]01", "1234567", 0, "BARCODE_UPCE_CC (136)," }, + /*175*/ { "dbar stk cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_STK_CC (137)," }, + /*176*/ { "rss14stackcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_STK_CC (137)," }, + /*177*/ { "databar stk cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_STK_CC (137)," }, + /*178*/ { "databar stacked cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_STK_CC (137)," }, + /*179*/ { "dbaromnstkcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, + /*180*/ { "BARCODE_RSS14_OMNI_CC", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, + /*181*/ { "databaromnstkcc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, + /*182*/ { "databar stacked omncc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, + /*183*/ { "databar stacked omni cc", "[20]01", "1234567890123", 0, "BARCODE_DBAR_OMNSTK_CC (138)," }, + /*184*/ { "dbarexpstkcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, + /*185*/ { "RSS EXPSTACK CC", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, + /*186*/ { "databarexpstkcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, + /*187*/ { "databar expanded stkcc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, + /*188*/ { "databar expanded stacked cc", "[20]01", "[01]12345678901231", 0, "BARCODE_DBAR_EXPSTK_CC (139)," }, + /*189*/ { "Channel", "1", NULL, 0, "BARCODE_CHANNEL (140)," }, + /*190*/ { "Channel Code", "1", NULL, 0, "BARCODE_CHANNEL (140)," }, + /*191*/ { "CodeOne", "1", NULL, 0, "BARCODE_CODEONE (141)," }, + /*192*/ { "Grid Matrix", "1", NULL, 0, "BARCODE_GRIDMATRIX (142)," }, + /*193*/ { "UPN QR", "1", NULL, 0, "BARCODE_UPNQR (143)," }, + /*194*/ { "UPN QR Code", "1", NULL, 0, "BARCODE_UPNQR (143)," }, /* Synonym */ + /*195*/ { "ultra", "1", NULL, 0, "BARCODE_ULTRA (144)," }, + /*196*/ { "ultracode", "1", NULL, 0, "BARCODE_ULTRA (144)," }, /* Synonym */ + /*197*/ { "rMQR", "1", NULL, 0, "BARCODE_RMQR (145)," }, + /*198*/ { "bc412", "1234567", NULL, 0, "BARCODE_BC412 (146)," }, + /*199*/ { "x", "1", NULL, 1, "Error 119: Invalid barcode type 'x'" }, + /*200*/ { "\177", "1", NULL, 1, "Error 119: Invalid barcode type '\177'" }, }; int data_size = ARRAY_SIZE(data); int i; @@ -1170,6 +1174,18 @@ static void test_other_opts(const testCtx *const p_ctx) { /* 44*/ { -1, NULL, -1, " -h", NULL, "Encode input data in a barcode ", 1 }, /* 45*/ { -1, NULL, -1, " -e", NULL, "3: ISO/IEC 8859-1 ", 1 }, /* 46*/ { -1, NULL, -1, " -t", NULL, "1 CODE11 ", 1 }, + /* 47*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "12345678", "Error 178: scalexdimdp X-dim invalid floating point (integer part must be 7 digits maximum)", 0 }, + /* 48*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "1234567890123", "Error 176: scalexdimdp X-dim too long", 0 }, + /* 49*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "123456.12", "Error 178: scalexdimdp X-dim invalid floating point (7 significant digits maximum)", 0 }, + /* 50*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", ",12.34", "Error 174: scalexdimdp X-dim too short", 0 }, + /* 51*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "12.34,", "Error 175: scalexdimdp resolution too short", 0 }, + /* 52*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "12mm1", "Error 177: scalexdimdp X-dim units must occur at end", 0 }, + /* 53*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "1inc", "Error 177: scalexdimdp X-dim units must occur at end", 0 }, + /* 54*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "1234x", "Error 178: scalexdimdp X-dim invalid floating point (integer part must be digits only)", 0 }, + /* 55*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "12.34in,123x", "Error 180: scalexdimdp resolution invalid floating point (integer part must be digits only)", 0 }, + /* 56*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "12,123.45678", "Error 180: scalexdimdp resolution invalid floating point (7 significant digits maximum)", 0 }, + /* 57*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "10.1,1000", "Warning 185: scalexdimdp X-dim (10.1) out of range (> 10), ignoring", 0 }, + /* 58*/ { BARCODE_EANX, "501234567890", -1, " --scalexdimdp=", "10,1000.1", "Warning 186: scalexdimdp resolution (1000.1) out of range (> 1000), ignoring", 0 }, }; int data_size = ARRAY_SIZE(data); int i; diff --git a/frontend_qt/CMakeLists.txt b/frontend_qt/CMakeLists.txt index f456b2d6..5a63fd27 100644 --- a/frontend_qt/CMakeLists.txt +++ b/frontend_qt/CMakeLists.txt @@ -8,14 +8,14 @@ project(zint-qt) set(CMAKE_AUTORCC ON) set(${PROJECT_NAME}_SRCS barcodeitem.cpp main.cpp mainwindow.cpp - cliwindow.cpp datawindow.cpp sequencewindow.cpp exportwindow.cpp) + cliwindow.cpp datawindow.cpp scalewindow.cpp sequencewindow.cpp exportwindow.cpp) if(USE_QT6) - qt6_wrap_cpp(zint-qt_SRCS mainwindow.h cliwindow.h datawindow.h sequencewindow.h exportwindow.h) - qt6_wrap_ui(zint-qt_SRCS mainWindow.ui extCLI.ui extData.ui extSequence.ui extExport.ui) + qt6_wrap_cpp(zint-qt_SRCS mainwindow.h cliwindow.h datawindow.h scalewindow.h sequencewindow.h exportwindow.h) + qt6_wrap_ui(zint-qt_SRCS mainWindow.ui extCLI.ui extData.ui extScale.ui extSequence.ui extExport.ui) else() - qt5_wrap_cpp(zint-qt_SRCS mainwindow.h cliwindow.h datawindow.h sequencewindow.h exportwindow.h) - qt5_wrap_ui(zint-qt_SRCS mainWindow.ui extCLI.ui extData.ui extSequence.ui extExport.ui) + qt5_wrap_cpp(zint-qt_SRCS mainwindow.h cliwindow.h datawindow.h scalewindow.h sequencewindow.h exportwindow.h) + qt5_wrap_ui(zint-qt_SRCS mainWindow.ui extCLI.ui extData.ui extScale.ui extSequence.ui extExport.ui) endif() # grpAztec.ui grpC39.ui grpCodablockF.ui grpDotCode.ui grpMaxicode.ui grpQR.ui grpUPNQR.ui diff --git a/frontend_qt/cliwindow.cpp b/frontend_qt/cliwindow.cpp index 538521f7..714048fa 100644 --- a/frontend_qt/cliwindow.cpp +++ b/frontend_qt/cliwindow.cpp @@ -16,6 +16,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +/* SPDX-License-Identifier: GPL-3.0-or-later */ //#include #include @@ -23,15 +24,15 @@ #include #include "cliwindow.h" -#include "barcodeitem.h" // Shorthand #define QSL QStringLiteral static const int tempMessageTimeout = 2000; -CLIWindow::CLIWindow(BarcodeItem *bc, const bool autoHeight, const double heightPerRow) - : m_bc(bc), m_autoHeight(autoHeight), m_heightPerRow(heightPerRow) +CLIWindow::CLIWindow(BarcodeItem *bc, const bool autoHeight, const double heightPerRow, + const struct Zint::QZintXdimDpVars* xdimdpVars) + : m_bc(bc), m_autoHeight(autoHeight), m_heightPerRow(heightPerRow), m_xdimdpVars(xdimdpVars) { setupUi(this); QSettings settings; @@ -106,7 +107,8 @@ void CLIWindow::generate_cli() chkCLINoEXE->setEnabled(false); } QString cmd = m_bc->bc.getAsCLI(radCLIWin->isChecked(), chkCLILongOpts->isChecked(), - chkCLIBarcodeName->isChecked(), noEXE, m_autoHeight, m_heightPerRow); + chkCLIBarcodeName->isChecked(), noEXE, m_autoHeight, m_heightPerRow, QSL("") /*outfile*/, + m_xdimdpVars); txtCLICmd->setPlainText(cmd); statusBarCLI->clearMessage(); diff --git a/frontend_qt/cliwindow.h b/frontend_qt/cliwindow.h index da688a97..5968cb18 100644 --- a/frontend_qt/cliwindow.h +++ b/frontend_qt/cliwindow.h @@ -1,6 +1,6 @@ /* Zint Barcode Generator - the open source barcode generator - Copyright (C) 2021 Robin Stuart + Copyright (C) 2021-2022 Robin Stuart This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,21 +16,21 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -/* vim: set ts=4 sw=4 et : */ +/* SPDX-License-Identifier: GPL-3.0-or-later */ #ifndef CLIWINDOW_H #define CLIWINDOW_H #include "ui_extCLI.h" - -class BarcodeItem; +#include "barcodeitem.h" class CLIWindow : public QDialog, private Ui::CLIDialog { Q_OBJECT public: - CLIWindow(BarcodeItem *bc, const bool autoHeight, const double heightPerRow); + CLIWindow(BarcodeItem *bc, const bool autoHeight, const double heightPerRow, + const struct Zint::QZintXdimDpVars* xdimdpVars); virtual ~CLIWindow(); private slots: @@ -41,6 +41,8 @@ protected: BarcodeItem *m_bc; bool m_autoHeight; double m_heightPerRow; + const Zint::QZintXdimDpVars *m_xdimdpVars; }; +/* vim: set ts=4 sw=4 et : */ #endif diff --git a/frontend_qt/extData.ui b/frontend_qt/extData.ui index aabbf351..3ad52597 100644 --- a/frontend_qt/extData.ui +++ b/frontend_qt/extData.ui @@ -51,6 +51,9 @@ + + false + &From File... @@ -75,6 +78,9 @@ Note that Line Feeds (0x0A) are not included,<br/> but any present will be + + false + C&lear @@ -98,6 +104,9 @@ Note that Line Feeds (0x0A) are not included,<br/> but any present will be + + false + &OK @@ -109,6 +118,9 @@ Line Feeds (0xA0) will be escaped as "\n" + + false + &Cancel diff --git a/frontend_qt/extExport.ui b/frontend_qt/extExport.ui index 31b2bbf9..b6842011 100644 --- a/frontend_qt/extExport.ui +++ b/frontend_qt/extExport.ui @@ -135,9 +135,9 @@ - + - File &Format: + File &Type: The type of file which you want to create diff --git a/frontend_qt/extScale.ui b/frontend_qt/extScale.ui new file mode 100644 index 00000000..2f54d50b --- /dev/null +++ b/frontend_qt/extScale.ui @@ -0,0 +1,350 @@ + + + ScaleDialog + + + + 0 + 0 + 250 + 200 + + + + Set Printing Scale + + + + :res/zint-qt.ico:res/zint-qt.ico + + + + + + + + + 120 + 16777215 + + + + X-dimension in selected units + + + &X-dimension: + + + spnXdim + + + + + + + X-dimension in selected units + + + + + + 5 + + + 0.001000000000000 + + + 100.000000000000000 + + + 0.010000000000000 + + + 1.000000000000000 + + + + + + + X-dimension units (millimetres or inches) + + + + 80 + 16777215 + + + + + mm + + + + + in + + + + + + + + false + + + + 80 + 16777215 + + + + Reset X-dimension to default (symbology specific) + + + De&fault + + + + 40 + 20 + + + + + + + + + 120 + 16777215 + + + + Resolution (dot density) in selected units + + + &Resolution: + + + spnResolution + + + + + + + Resolution (dot density) in selected units + + + + + + 9999 + + + 1 + + + 12 + + + + + + + Resolution units (dots per mm or dots per inch) + + + + 80 + 16777215 + + + + + dpmm + + + + + dpi + + + + + + + + false + + + + 80 + 16777215 + + + + Reset resolution to default (12 dpmm or 300 dpi) + + + Defau&lt + + + + + + + + 120 + 16777215 + + + + The type of file which will be outputted to + + + File &Type: + + + cmbFileType + + + + + + + The type of file which will be outputted to + + + + Raster (BMP/GIF/PCX/PNG/TIF) + + + + + Vector (excluding EMF) + + + + + Extended Metafile (EMF) + + + + + + + + + 120 + 16777215 + + + + Calculated scale + + + Printing Scale: + + + + + + + Calculated scale + + + + + + + + + + + 120 + 16777215 + + + + Image size (width x height) of barcode + + + Print Size: + + + + + + + Image size (width x height) of barcode + + + + + + + + + + + + Qt::Vertical + + + + 40 + 10 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + Close the window and update the Printing Scale + + + &Ok + + + + + + + false + + + Close window without updating the Printing Scale + + + &Close + + + + + + + + + + diff --git a/frontend_qt/frontend_qt.pro b/frontend_qt/frontend_qt.pro index 94c583bd..438eccfd 100644 --- a/frontend_qt/frontend_qt.pro +++ b/frontend_qt/frontend_qt.pro @@ -18,11 +18,13 @@ HEADERS += barcodeitem.h \ datawindow.h \ exportwindow.h \ mainwindow.h \ + scalewindow.h \ sequencewindow.h FORMS += extCLI.ui \ extData.ui \ extExport.ui \ + extScale.ui \ extSequence.ui \ grpAztec.ui \ grpC11.ui \ @@ -64,6 +66,7 @@ SOURCES += barcodeitem.cpp \ exportwindow.cpp \ main.cpp \ mainwindow.cpp \ + scalewindow.cpp \ sequencewindow.cpp TRANSLATIONS = frontend_de.ts diff --git a/frontend_qt/frontend_qt_zintdll.pro b/frontend_qt/frontend_qt_zintdll.pro index 9a6c5a07..05c3732c 100644 --- a/frontend_qt/frontend_qt_zintdll.pro +++ b/frontend_qt/frontend_qt_zintdll.pro @@ -10,12 +10,14 @@ HEADERS += barcodeitem.h \ datawindow.h \ exportwindow.h \ mainwindow.h \ + scalewindow.h \ sequencewindow.h FORMS += extCLI.ui \ extData.ui \ extExport.ui \ extSequence.ui \ + extScale.ui \ grpAztec.ui \ grpC11.ui \ grpC128.ui \ @@ -56,6 +58,7 @@ SOURCES += barcodeitem.cpp \ exportwindow.cpp \ main.cpp \ mainwindow.cpp \ + scalewindow.cpp \ sequencewindow.cpp RESOURCES += resources.qrc diff --git a/frontend_qt/frontend_vc8.pro b/frontend_qt/frontend_vc8.pro index 4317d197..b09a801f 100644 --- a/frontend_qt/frontend_vc8.pro +++ b/frontend_qt/frontend_vc8.pro @@ -7,6 +7,7 @@ CONFIG += warn_on \ FORMS = mainWindow.ui \ extCLI.ui \ + extScale.ui \ extSequence.ui \ extExport.ui \ extData.ui @@ -16,6 +17,7 @@ HEADERS = mainwindow.h \ cliwindow.h \ datawindow.h \ exportwindow.h \ + scalewindow.h \ sequencewindow.h \ qzint.h @@ -25,7 +27,8 @@ SOURCES = main.cpp \ cliwindow.cpp \ datawindow.cpp \ exportwindow.cpp \ - sequencewindow.cpp + scalewindow.cpp \ + sequencewindow.cpp \ qzint.cpp RESOURCES = resources.qrc diff --git a/frontend_qt/grpDAFT.ui b/frontend_qt/grpDAFT.ui index 00b343ad..20d3ab3b 100644 --- a/frontend_qt/grpDAFT.ui +++ b/frontend_qt/grpDAFT.ui @@ -66,6 +66,22 @@ + + + + + 80 + 16777215 + + + + Reset tracker ratio to default 25% + + + De&fault + + + diff --git a/frontend_qt/grpUPCA.ui b/frontend_qt/grpUPCA.ui index 767962d6..4fde6117 100644 --- a/frontend_qt/grpUPCA.ui +++ b/frontend_qt/grpUPCA.ui @@ -25,7 +25,7 @@ - A&dd-on Gap: + Add-o&n Gap: Horizontal space in X-dimensions between @@ -129,13 +129,13 @@ descend below the main bars (default 5X) - + Reset guard bars descent height to default 5X - &Reset + De&fault diff --git a/frontend_qt/grpUPCEAN.ui b/frontend_qt/grpUPCEAN.ui index bec68d3d..57011e09 100644 --- a/frontend_qt/grpUPCEAN.ui +++ b/frontend_qt/grpUPCEAN.ui @@ -25,7 +25,7 @@ - A&dd-on Gap: + Add-o&n Gap: Horizontal space in X-dimensions between @@ -139,13 +139,13 @@ descend below the main bars (default 5X) - + Reset guard bars descent height to default 5X - &Reset + De&fault diff --git a/frontend_qt/mainWindow.ui b/frontend_qt/mainWindow.ui index e9843a78..073a925e 100644 --- a/frontend_qt/mainWindow.ui +++ b/frontend_qt/mainWindow.ui @@ -1603,7 +1603,7 @@ as delimiters for GS1 Application Identifiers - + @@ -1656,7 +1656,7 @@ and use standard height (if any) for default - + false @@ -1707,7 +1707,7 @@ and use standard height (if any) for default - + Width of boundary bars or border in X-dimensions @@ -1742,7 +1742,7 @@ and use standard height (if any) for default - + Add border or box @@ -1788,7 +1788,7 @@ and use standard height (if any) for default - + @@ -1863,7 +1863,46 @@ in X-dimensions + + + + + 22 + 16777215 + + + + Set Printing Scale by X-dimension and resolution + + + + + + + + + Image size (width x height) of barcode at given dot density + + + Print Size: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + Image size (width x height) of barcode at given dot density + + + + + + + Set font characteristics @@ -1880,7 +1919,7 @@ in X-dimensions - + Set font characteristics @@ -1908,7 +1947,7 @@ in X-dimensions - + Show Human Readable Text in image @@ -1922,7 +1961,7 @@ in X-dimensions - + true @@ -1941,7 +1980,7 @@ in X-dimensions - + @@ -1959,7 +1998,7 @@ or "RRGGBBAA" (alpha) - + @@ -1975,7 +2014,7 @@ or "RRGGBBAA" (alpha) - + true @@ -1994,7 +2033,7 @@ or "RRGGBBAA" (alpha) - + @@ -2012,7 +2051,7 @@ or "RRGGBBAA" (alpha) - + @@ -2028,7 +2067,7 @@ or "RRGGBBAA" (alpha) - + true @@ -2047,7 +2086,7 @@ or "RRGGBBAA" (alpha) - + @@ -2063,7 +2102,7 @@ or "RRGGBBAA" (alpha) - + @@ -2080,7 +2119,7 @@ or "RRGGBBAA" (alpha) - + Use CMYK colour space in EPS/TIF output @@ -2093,7 +2132,7 @@ or "RRGGBBAA" (alpha) - + Add compliant quiet zones (if any) to whitespace @@ -2107,7 +2146,7 @@ or "RRGGBBAA" (alpha) - + Rotate symbol by degrees @@ -2123,7 +2162,7 @@ or "RRGGBBAA" (alpha) - + Rotate symbol by degrees @@ -2150,7 +2189,7 @@ or "RRGGBBAA" (alpha) - + Use dots instead of squares for matrix symbols @@ -2164,7 +2203,7 @@ or "RRGGBBAA" (alpha) - + false @@ -2184,7 +2223,7 @@ or "RRGGBBAA" (alpha) - + false @@ -2215,6 +2254,19 @@ or "RRGGBBAA" (alpha) + + + + Qt::Vertical + + + + 40 + 10 + + + + diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index b5ab1750..8e15ad5a 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -36,6 +36,7 @@ #include "mainwindow.h" #include "cliwindow.h" #include "datawindow.h" +#include "scalewindow.h" #include "sequencewindow.h" // Shorthand @@ -190,7 +191,8 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) : QWidget(parent, fl), m_optionWidget(nullptr), m_symbology(0), m_menu(nullptr), m_lblHeightPerRow(nullptr), m_spnHeightPerRow(nullptr), - m_btnHeightPerRowDisable(nullptr), m_btnHeightPerRowDefault(nullptr) + m_btnHeightPerRowDisable(nullptr), m_btnHeightPerRowDefault(nullptr), + m_scaleWindow(nullptr) { // Undocumented command line debug flag m_bc.bc.setDebug(QCoreApplication::arguments().contains(QSL("--verbose"))); @@ -224,6 +226,8 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) mac_hack_vLayouts(this); mac_hack_statusBars(this, "statusBar"); vLayoutTabData->setContentsMargins(QMargins(20, 0, 20, 0)); + tabMain->setMinimumSize(QSize(0, 380)); + tabMain->setMaximumSize(QSize(16777215, 380)); #endif #ifdef _WIN32 tabMain->setMinimumSize(QSize(0, 316)); @@ -235,6 +239,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) m_fgcolor_geometry = settings.value(QSL("studio/fgcolor_geometry")).toByteArray(); m_bgcolor_geometry = settings.value(QSL("studio/bgcolor_geometry")).toByteArray(); + btnScale->setIcon(QIcon(QSL(":res/scaling.svg"))); fgcolor->setIcon(QIcon(QSL(":res/black-eye.svg"))); bgcolor->setIcon(QIcon(QSL(":res/white-eye.svg"))); btnReverse->setIcon(QIcon(QSL(":res/shuffle.svg"))); @@ -307,7 +312,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) connect(spnVWhitespace, SIGNAL(valueChanged( int )), SLOT(update_preview())); connect(btnMenu, SIGNAL(clicked( bool )), SLOT(menu())); connect(btnSave, SIGNAL(clicked( bool )), SLOT(save())); - connect(spnScale, SIGNAL(valueChanged( double )), SLOT(change_print_scale())); + connect(spnScale, SIGNAL(valueChanged( double )), SLOT(update_preview())); connect(btnExit, SIGNAL(clicked( bool )), SLOT(quit_now())); connect(btnReset, SIGNAL(clicked( bool )), SLOT(reset_colours())); connect(btnReverse, SIGNAL(clicked( bool )), SLOT(reverse_colours())); @@ -324,6 +329,7 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) connect(chkAutoHeight, SIGNAL(toggled( bool )), SLOT(autoheight_ui_set())); connect(chkAutoHeight, SIGNAL(toggled( bool )), SLOT(update_preview())); connect(chkCompliantHeight, SIGNAL(toggled( bool )), SLOT(update_preview())); + connect(btnScale, SIGNAL(clicked( bool )), SLOT(open_scale_dialog())); connect(chkHRTShow, SIGNAL(toggled( bool )), SLOT(HRTShow_ui_set())); connect(chkHRTShow, SIGNAL(toggled( bool )), SLOT(update_preview())); connect(chkCMYK, SIGNAL(toggled( bool )), SLOT(change_cmyk())); @@ -426,6 +432,11 @@ MainWindow::~MainWindow() settings.setValue(QSL("studio/appearance/rotate"), cmbRotate->currentIndex()); settings.setValue(QSL("studio/appearance/chk_dotty"), chkDotty->isChecked() ? 1 : 0); settings.setValue(QSL("studio/appearance/dot_size"), spnDotSize->value()); + // These are "system-wide" + settings.setValue(QSL("studio/xdimdpvars/resolution"), m_xdimdpVars.resolution); + settings.setValue(QSL("studio/xdimdpvars/resolution_units"), m_xdimdpVars.resolution_units); + settings.setValue(QSL("studio/xdimdpvars/filetype"), m_xdimdpVars.filetype); + settings.setValue(QSL("studio/xdimdpvars/filetype_maxicode"), m_xdimdpVars.filetype_maxicode); save_sub_settings(settings, m_bc.bc.symbol()); } @@ -472,13 +483,20 @@ void MainWindow::load_settings(QSettings &settings) cmbRotate->setCurrentIndex(settings.value(QSL("studio/appearance/rotate"), 0).toInt()); chkDotty->setChecked(settings.value(QSL("studio/appearance/chk_dotty"), 0).toInt() ? true : false); spnDotSize->setValue(settings.value(QSL("studio/appearance/dot_size"), 4.0 / 5.0).toFloat()); + // These are "system-wide" + m_xdimdpVars.resolution_units = settings.value(QSL("studio/xdimdpvars/resolution_units"), 0).toInt(); + const int defaultResolution = m_xdimdpVars.resolution_units == 1 ? 300 : 12; // 300dpi or 12dpmm + m_xdimdpVars.resolution = settings.value(QSL("studio/xdimdpvars/resolution"), defaultResolution).toInt(); + m_xdimdpVars.filetype = std::max(std::min(settings.value(QSL("studio/xdimdpvars/filetype"), 0).toInt(), 1), 0); + m_xdimdpVars.filetype_maxicode + = std::max(std::min(settings.value(QSL("studio/xdimdpvars/filetype_maxicode"), 0).toInt(), 2), 0); } QString MainWindow::get_zint_version(void) { QString zint_version; - int lib_version = ZBarcode_Version(); + int lib_version = Zint::QZint::getVersion(); int version_major = lib_version / 10000; int version_minor = (lib_version % 10000) / 100; int version_release = lib_version % 100; @@ -721,7 +739,8 @@ void MainWindow::about() "\"Telepen\" is a Registered Trademark of SB Electronics.
" "\"Mailmark\" is a Registered Trademark of Royal Mail.

" "

With thanks to Harald Oehlmann, Norbert Szabó, Robert Elliott, Milton Neal, " - "Git Lost, Alonso Schaich, Andre Maute and many others at SourceForge.

" + "Git Lost, Alonso Schaich, Andre Maute and many others at " + "SourceForge.

" "

" #ifndef Q_OS_MACOS "" @@ -859,7 +878,6 @@ void MainWindow::open_data_dialog_seg(const int seg_no) } disconnect(&dlg, SIGNAL(dataChanged(const QString&, bool, int)), this, SLOT(on_dataChanged(const QString&, bool, int))); - update_preview(); } void MainWindow::open_data_dialog() @@ -898,14 +916,22 @@ void MainWindow::zap() #if QT_VERSION < 0x60000 settings.setIniCodec("UTF-8"); #endif - settings.clear(); int symbology = bstyle_items[bstyle->currentIndex()].symbology; + QString name = get_setting_name(symbology); + settings.remove(QSL("studio/bc/%1").arg(name)); + settings.remove(QSL("studio/data")); + settings.remove(QSL("studio/eci")); load_settings(settings); + setColorTxtBtn(m_fgcolor, txt_fgcolor, fgcolor); setColorTxtBtn(m_bgcolor, txt_bgcolor, bgcolor); + m_xdimdpVars.x_dim = 0.0f; + m_xdimdpVars.x_dim_units = 0; + m_xdimdpVars.set = 0; + load_sub_settings(settings, symbology); txtData->setFocus(Qt::OtherFocusReason); @@ -921,10 +947,17 @@ void MainWindow::on_dataChanged(const QString& text, bool escaped, int seg_no) update_preview(); } +void MainWindow::on_scaleChanged(double scale) +{ + spnScale->setValue(scale); + size_msg_ui_set(); +} + void MainWindow::open_cli_dialog() { CLIWindow dlg(&m_bc, chkAutoHeight->isEnabled() && chkAutoHeight->isChecked(), - m_spnHeightPerRow && m_spnHeightPerRow->isEnabled() ? m_spnHeightPerRow->value() : 0.0); + m_spnHeightPerRow && m_spnHeightPerRow->isEnabled() ? m_spnHeightPerRow->value() : 0.0, + &m_xdimdpVars); #ifdef Q_OS_MACOS mac_hack_statusBars(&dlg); @@ -933,6 +966,25 @@ void MainWindow::open_cli_dialog() (void) dlg.exec(); } +void MainWindow::open_scale_dialog() +{ + double originalScale = spnScale->value(); + QString originalSizeMsg = lblSizeMsg->text(); + ScaleWindow dlg(&m_bc, &m_xdimdpVars); + m_scaleWindow = &dlg; + connect(&dlg, SIGNAL(scaleChanged(double)), this, SLOT(on_scaleChanged(double))); + (void) dlg.exec(); + disconnect(&dlg, SIGNAL(scaleChanged(double)), this, SLOT(on_scaleChanged(double))); + if (dlg.Valid) { + m_xdimdpVars = dlg.m_vars; + update_preview(); + } else { // Restore + spnScale->setValue(originalScale); + lblSizeMsg->setText(originalSizeMsg); + } + m_scaleWindow = nullptr; +} + void MainWindow::on_fgcolor_clicked() { color_clicked(m_fgcolor, txt_fgcolor, fgcolor, tr("Set foreground colour"), m_fgcolor_geometry, @@ -1037,6 +1089,9 @@ void MainWindow::autoheight_ui_set() m_btnHeightPerRowDisable->setEnabled(enabled && m_spnHeightPerRow->value()); } if (m_btnHeightPerRowDefault) { + if (enabled && m_spnHeightPerRow->value() == get_height_per_row_default()) { + enabled = false; + } m_btnHeightPerRowDefault->setEnabled(enabled); } } @@ -1163,8 +1218,9 @@ void MainWindow::on_encoded() if (!chkAutoHeight->isEnabled() || chkAutoHeight->isChecked() || !heightb->isEnabled()) { /* setValue() rounds up/down to precision (decimals 3), we want round up only */ float height = (float) (ceil(m_bc.bc.height() * 1000.0f) / 1000.0f); - heightb->setValue(height); + heightb->setValue(height); // This can cause a double-encode unfortunately } + size_msg_ui_set(); if (m_optionWidget) { automatic_info_set(); @@ -1180,6 +1236,7 @@ void MainWindow::on_errored() } enableActions(); errtxtBar_set(); + size_msg_ui_set(); if (m_optionWidget) { automatic_info_set(); } @@ -1238,10 +1295,37 @@ void MainWindow::filter_symbologies() } } -void MainWindow::change_print_scale() +void MainWindow::size_msg_ui_set() { - /* This value is only used when printing (saving) to file */ - m_bc.bc.setScale((float) spnScale->value()); + if (m_bc.bc.getError() < ZINT_ERROR) { + float scale = (float) spnScale->value(); + struct Zint::QZintXdimDpVars *vars = m_scaleWindow ? &m_scaleWindow->m_vars : &m_xdimdpVars; + if (vars->x_dim == 0.0) { + vars->x_dim_units = 0; + vars->x_dim = m_bc.bc.getXdimDpFromScale(scale, get_dpmm(vars), getFileType(vars)); + } else { + // Scale trumps stored X-dimension + double x_dim_mm = vars->x_dim_units == 1 ? vars->x_dim * 25.4 : vars->x_dim; + if (m_bc.bc.getScaleFromXdimDp((float) x_dim_mm, get_dpmm(vars), getFileType(vars)) != scale) { + x_dim_mm = std::min(m_bc.bc.getXdimDpFromScale(scale, get_dpmm(vars), getFileType(vars)), 10.0f); + vars->x_dim = vars->x_dim_units == 1 ? x_dim_mm / 25.4 : x_dim_mm; + } + } + float width_x_dim, height_x_dim; + if (m_bc.bc.getWidthHeightXdim((float) vars->x_dim, width_x_dim, height_x_dim)) { + const char *fmt = vars->x_dim_units == 1 ? "%.3f x %.3f in @ %d %s (%s)" : "%.2f x %.2f mm @ %d %s (%s)"; + const char *resolution_units_str = vars->resolution_units == 1 ? "dpi" : "dpmm"; + lblSizeMsg->setText(QString::asprintf(fmt, width_x_dim, height_x_dim, vars->resolution, + resolution_units_str, getFileType(vars, true /*msg*/))); + } else { + lblSizeMsg->clear(); + } + } else { + lblSizeMsg->clear(); + } + if (m_scaleWindow) { + m_scaleWindow->size_msg_ui_set(); + } } void MainWindow::change_cmyk() @@ -1323,53 +1407,59 @@ void MainWindow::height_per_row_disable() } } +double MainWindow::get_height_per_row_default() +{ + const QString &name = m_btnHeightPerRowDefault->objectName(); + double val = 0.0; + if (name == QSL("btnPDFHeightPerRowDefault")) { + val = 3.0; + } else if (name == QSL("btnMPDFHeightPerRowDefault")) { + val = 2.0; + } else if (name == QSL("btnC16kHeightPerRowDefault")) { + if (chkCompliantHeight->isEnabled() && chkCompliantHeight->isChecked()) { + const int rows = m_bc.bc.encodedRows(); + val = 10.0 + (double)((rows - 1) * (get_cmb_index(QSL("cmbC16kRowSepHeight")) + 1)) / rows; + } else { + val = 10.0; + } + } else if (name == QSL("btnCbfHeightPerRowDefault")) { + // Depends on no. of data cols + const int cols = (m_bc.bc.encodedWidth() - 57) / 11; // 57 = 4 * 11 (start/subset/checks) + 13 (stop char) + val = 0.55 * cols + 3; + if (val < 10.0) { + val = 10.0; + } + } else if (name == QSL("btnC49HeightPerRowDefault")) { + if (chkCompliantHeight->isEnabled() && chkCompliantHeight->isChecked()) { + const int rows = m_bc.bc.encodedRows(); + val = 10.0 + (double)((rows - 1) * (get_cmb_index(QSL("cmbC49RowSepHeight")) + 1)) / rows; + } else { + val = 10.0; + } + } else if (name == QSL("btnDBESHeightPerRowDefault")) { + val = 34.0; + } + return val; +} + void MainWindow::height_per_row_default() { if (m_spnHeightPerRow && m_btnHeightPerRowDefault) { - const QString &name = m_btnHeightPerRowDefault->objectName(); - double val = 0.0; - if (name == QSL("btnPDFHeightPerRowDefault")) { - val = 3.0; - } else if (name == QSL("btnMPDFHeightPerRowDefault")) { - val = 2.0; - } else if (name == QSL("btnC16kHeightPerRowDefault")) { - if (chkCompliantHeight->isEnabled() && chkCompliantHeight->isChecked()) { - const int rows = m_bc.bc.encodedRows(); - val = 10.0 + (double)((rows - 1) * (get_cmb_index(QSL("cmbC16kRowSepHeight")) + 1)) / rows; - } else { - val = 10.0; - } - } else if (name == QSL("btnCbfHeightPerRowDefault")) { - // Depends on no. of data cols - const int cols = (m_bc.bc.encodedWidth() - 57) / 11; // 57 = 4 * 11 (start/subset/checks) + 13 (stop char) - val = 0.55 * cols + 3; - if (val < 10.0) { - val = 10.0; - } - } else if (name == QSL("btnC49HeightPerRowDefault")) { - if (chkCompliantHeight->isEnabled() && chkCompliantHeight->isChecked()) { - const int rows = m_bc.bc.encodedRows(); - val = 10.0 + (double)((rows - 1) * (get_cmb_index(QSL("cmbC49RowSepHeight")) + 1)) / rows; - } else { - val = 10.0; - } - } else if (name == QSL("btnDBESHeightPerRowDefault")) { - val = 34.0; - } + double val = get_height_per_row_default(); if (val) { m_spnHeightPerRow->setValue(val); } } } -void MainWindow::guard_reset_upcean() +void MainWindow::guard_default_upcean() { - guard_reset(QSL("spnUPCEANGuardDescent")); + guard_default(QSL("spnUPCEANGuardDescent")); } -void MainWindow::guard_reset_upca() +void MainWindow::guard_default_upca() { - guard_reset(QSL("spnUPCAGuardDescent")); + guard_default(QSL("spnUPCAGuardDescent")); } void MainWindow::view_context_menu(const QPoint &pos) @@ -1446,6 +1536,10 @@ void MainWindow::change_options() setColorTxtBtn(m_fgcolor, txt_fgcolor, fgcolor); setColorTxtBtn(m_bgcolor, txt_bgcolor, bgcolor); + m_xdimdpVars.x_dim = 0.0f; + m_xdimdpVars.x_dim_units = 0; + m_xdimdpVars.set = 0; + if (symbology == BARCODE_CODE128) { QFile file(QSL(":/grpC128.ui")); if (!file.open(QIODevice::ReadOnly)) @@ -1695,9 +1789,12 @@ void MainWindow::change_options() m_optionWidget = uiload.load(&file); file.close(); load_sub_settings(settings, symbology); - tabMain->insertTab(1, m_optionWidget, tr("DAFT")); + tabMain->insertTab(1, m_optionWidget, tr("D&AFT")); set_smaller_font(QSL("noteTrackerRatios")); + connect(get_widget(QSL("spnDAFTTrackerRatio")), SIGNAL(valueChanged( double )), SLOT(daft_ui_set())); connect(get_widget(QSL("spnDAFTTrackerRatio")), SIGNAL(valueChanged( double )), SLOT(update_preview())); + connect(get_widget(QSL("btnDAFTTrackerDefault")), SIGNAL(clicked( bool )), SLOT(daft_tracker_default())); + daft_ui_set(); } } else if (symbology == BARCODE_DPD) { @@ -1975,7 +2072,7 @@ void MainWindow::change_options() } connect(get_widget(QSL("cmbUPCAAddonGap")), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(get_widget(QSL("spnUPCAGuardDescent")), SIGNAL(valueChanged( double )), SLOT(update_preview())); - connect(get_widget(QSL("btnUPCAGuardReset")), SIGNAL(clicked( bool )), SLOT(guard_reset_upca())); + connect(get_widget(QSL("btnUPCAGuardDefault")), SIGNAL(clicked( bool )), SLOT(guard_default_upca())); connect(get_widget(QSL("chkUPCANoQuietZones")), SIGNAL(toggled( bool )), SLOT(update_preview())); } else if (symbology == BARCODE_EANX || symbology == BARCODE_EANX_CHK || symbology == BARCODE_EANX_CC @@ -2000,7 +2097,7 @@ void MainWindow::change_options() } connect(get_widget(QSL("cmbUPCEANAddonGap")), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(get_widget(QSL("spnUPCEANGuardDescent")), SIGNAL(valueChanged( double )), SLOT(update_preview())); - connect(get_widget(QSL("btnUPCEANGuardReset")), SIGNAL(clicked( bool )), SLOT(guard_reset_upcean())); + connect(get_widget(QSL("btnUPCEANGuardDefault")), SIGNAL(clicked( bool )), SLOT(guard_default_upcean())); connect(get_widget(QSL("chkUPCEANNoQuietZones")), SIGNAL(toggled( bool )), SLOT(update_preview())); } else if (symbology == BARCODE_VIN) { @@ -2232,7 +2329,7 @@ void MainWindow::combobox_item_enabled(QComboBox *comboBox, int index, bool enab } } -void MainWindow::upcean_addon_gap(const QString &comboBoxName, const QString &labelName, int base) +bool MainWindow::upcean_addon_gap(const QString &comboBoxName, const QString &labelName, int base) { QComboBox *comboBox = m_optionWidget->findChild(comboBoxName); QLabel *label = m_optionWidget->findChild(labelName); @@ -2251,26 +2348,38 @@ void MainWindow::upcean_addon_gap(const QString &comboBoxName, const QString &la m_bc.bc.setOption2(item_val + base); } } + return enabled; } -void MainWindow::upcean_guard_descent(const QString &spnBoxName, const QString &labelName) +void MainWindow::upcean_guard_descent(const QString &spnBoxName, const QString &labelName, + const QString &btnDefaultName, bool enabled) { QDoubleSpinBox *spnBox = m_optionWidget->findChild(spnBoxName); QLabel *label = m_optionWidget->findChild(labelName); + QPushButton *btnDefault = m_optionWidget->findChild(btnDefaultName); - bool enabled = txtData->text().length() > 5; if (spnBox) { spnBox->setEnabled(enabled); } if (label) { label->setEnabled(enabled); } + if (btnDefault) { + btnDefault->setEnabled(enabled); + } if (enabled && spnBox) { m_bc.bc.setGuardDescent(spnBox->value()); + if (btnDefault && spnBox->value() == 5.0) { + QWidget *focus = QApplication::focusWidget(); + btnDefault->setEnabled(false); + if (focus == btnDefault) { + spnBox->setFocus(); + } + } } } -void MainWindow::guard_reset(const QString &spnBoxName) +void MainWindow::guard_default(const QString &spnBoxName) { QDoubleSpinBox *spnBox = m_optionWidget->findChild(spnBoxName); if (spnBox && spnBox->value() != 5.0) { @@ -2279,6 +2388,32 @@ void MainWindow::guard_reset(const QString &spnBoxName) } } +void MainWindow::daft_ui_set() +{ + QDoubleSpinBox *spnBox = m_optionWidget->findChild(QSL("spnDAFTTrackerRatio")); + QPushButton *btnDefault = m_optionWidget->findChild(QSL("btnDAFTTrackerDefault")); + if (spnBox && spnBox->value() == 25.0) { + if (btnDefault) { + QWidget *focus = QApplication::focusWidget(); + btnDefault->setEnabled(false); + if (focus == btnDefault) { + spnBox->setFocus(); + } + } + } else if (btnDefault && !btnDefault->isEnabled()) { + btnDefault->setEnabled(true); + } +} + +void MainWindow::daft_tracker_default() +{ + QDoubleSpinBox *spnBox = m_optionWidget->findChild(QSL("spnDAFTTrackerRatio")); + if (spnBox && spnBox->value() != 25.0) { + spnBox->setValue(25.0); + update_preview(); + } +} + void MainWindow::set_gs1_mode(bool gs1_mode) { if (gs1_mode) { @@ -2344,6 +2479,7 @@ void MainWindow::update_preview() m_bc.bc.setOption1(-1); m_bc.bc.setOption2(0); m_bc.bc.setOption3(0); + m_bc.bc.setDPMM(m_xdimdpVars.set ? get_dpmm(&m_xdimdpVars) : 0.0f); chkData->setEnabled(true); if (chkData->isChecked()) { m_bc.bc.setInputMode(DATA_MODE); @@ -2363,7 +2499,7 @@ void MainWindow::update_preview() case BARCODE_CODE128: if (get_rad_val(QSL("radC128CSup"))) - m_bc.bc.setSymbol(BARCODE_CODE128B); + m_bc.bc.setSymbol(BARCODE_CODE128AB); else if (get_rad_val(QSL("radC128EAN"))) m_bc.bc.setSymbol(chkComposite->isChecked() ? BARCODE_GS1_128_CC : BARCODE_GS1_128); else if (get_rad_val(QSL("radC128HIBC"))) @@ -2374,8 +2510,12 @@ void MainWindow::update_preview() case BARCODE_EANX: m_bc.bc.setSymbol(chkComposite->isChecked() ? BARCODE_EANX_CC : BARCODE_EANX); - upcean_addon_gap(QSL("cmbUPCEANAddonGap"), QSL("lblUPCEANAddonGap"), 7 /*base*/); - upcean_guard_descent(QSL("spnUPCEANGuardDescent"), QSL("lblUPCEANGuardDescent")); + { + bool have_addon = upcean_addon_gap(QSL("cmbUPCEANAddonGap"), QSL("lblUPCEANAddonGap"), 7 /*base*/); + bool enable_guard = have_addon || txtData->text().length() > 5; + upcean_guard_descent(QSL("spnUPCEANGuardDescent"), QSL("lblUPCEANGuardDescent"), + QSL("btnUPCEANGuardDefault"), enable_guard); + } if (get_chk_val(QSL("chkUPCEANNoQuietZones"))) { m_bc.bc.setNoQuietZones(true); } @@ -2384,7 +2524,8 @@ void MainWindow::update_preview() case BARCODE_ISBNX: m_bc.bc.setSymbol(symbology); upcean_addon_gap(QSL("cmbUPCEANAddonGap"), QSL("lblUPCEANAddonGap"), 7 /*base*/); - upcean_guard_descent(QSL("spnUPCEANGuardDescent"), QSL("lblUPCEANGuardDescent")); + upcean_guard_descent(QSL("spnUPCEANGuardDescent"), QSL("lblUPCEANGuardDescent"), + QSL("btnUPCEANGuardDefault")); if (get_chk_val(QSL("chkUPCEANNoQuietZones"))) { m_bc.bc.setNoQuietZones(true); } @@ -2393,7 +2534,7 @@ void MainWindow::update_preview() case BARCODE_UPCA: m_bc.bc.setSymbol(chkComposite->isChecked() ? BARCODE_UPCA_CC : BARCODE_UPCA); upcean_addon_gap(QSL("cmbUPCAAddonGap"), QSL("lblUPCAAddonGap"), 9 /*base*/); - upcean_guard_descent(QSL("spnUPCAGuardDescent"), QSL("lblUPCAGuardDescent")); + upcean_guard_descent(QSL("spnUPCAGuardDescent"), QSL("lblUPCAGuardDescent"), QSL("btnUPCAGuardDefault")); if (get_chk_val(QSL("chkUPCANoQuietZones"))) { m_bc.bc.setNoQuietZones(true); } @@ -2402,7 +2543,8 @@ void MainWindow::update_preview() case BARCODE_UPCE: m_bc.bc.setSymbol(chkComposite->isChecked() ? BARCODE_UPCE_CC : BARCODE_UPCE); upcean_addon_gap(QSL("cmbUPCEANAddonGap"), QSL("lblUPCEANAddonGap"), 7 /*base*/); - upcean_guard_descent(QSL("spnUPCEANGuardDescent"), QSL("lblUPCEANGuardDescent")); + upcean_guard_descent(QSL("spnUPCEANGuardDescent"), QSL("lblUPCEANGuardDescent"), + QSL("btnUPCEANGuardDefault")); if (get_chk_val(QSL("chkUPCEANNoQuietZones"))) { m_bc.bc.setNoQuietZones(true); } @@ -2888,8 +3030,8 @@ void MainWindow::update_preview() lblECI->setEnabled(cmbECI->isEnabled()); } btnClearData->setEnabled(!txtData->text().isEmpty()); - chkGS1Parens->setEnabled(m_bc.bc.supportsGS1()); - chkGS1NoCheck->setEnabled(m_bc.bc.supportsGS1()); + chkGS1Parens->setEnabled(m_bc.bc.takesGS1AIData(m_symbology) || (m_bc.bc.inputMode() & 0x07) == GS1_MODE); + chkGS1NoCheck->setEnabled(chkGS1Parens->isEnabled()); chkRInit->setEnabled(m_bc.bc.supportsReaderInit() && (m_bc.bc.inputMode() & 0x07) != GS1_MODE); chkCompliantHeight->setEnabled(m_bc.bc.hasCompliantHeight()); @@ -2926,7 +3068,7 @@ void MainWindow::update_preview() } m_bc.bc.setFgColor(m_fgcolor); m_bc.bc.setBgColor(m_bgcolor); - change_print_scale(); + m_bc.bc.setScale((float) spnScale->value()); change_cmyk(); m_bc.setSize(width - 10, height - 10); m_bc.update(); @@ -2942,7 +3084,7 @@ void MainWindow::createActions() QIcon copyIcon(QIcon::fromTheme(QSL("edit-copy"), QIcon(QSL(":res/copy.svg")))); QIcon cliIcon(QSL(":res/zint_black.ico")); QIcon saveIcon(QIcon::fromTheme(QSL("document-save"), QIcon(QSL(":res/download.svg")))); - QIcon zapIcon(QIcon(QSL(":res/zap.svg"))); + QIcon zapIcon(QSL(":res/zap.svg")); QIcon aboutIcon(QSL(":res/zint-qt.ico")); QIcon helpIcon(QIcon::fromTheme(QSL("help-contents"), QIcon(QSL(":res/help-circle.svg")))); QIcon quitIcon(QIcon::fromTheme(QSL("window-close"), QIcon(QSL(":res/x.svg")))); @@ -3135,7 +3277,7 @@ void MainWindow::errtxtBar_clear() if (!errtxtBarContainer->isHidden()) { errtxtBarContainer->hide(); errtxtBarContainer->update(); - update_preview(); + update_preview(); // This causes a double-encode unfortunately } } @@ -3154,7 +3296,7 @@ void MainWindow::errtxtBar_set() if (errtxtBarContainer->isHidden()) { errtxtBarContainer->show(); errtxtBarContainer->update(); - update_preview(); + update_preview(); // This causes a double-encode unfortunately } } } @@ -3442,9 +3584,8 @@ QWidget *MainWindow::get_widget(const QString &name) /* Return settings subsection name for a symbol */ QString MainWindow::get_setting_name(int symbology) { - char name_buf[32]; switch (symbology) { - case BARCODE_CODE128B: + case BARCODE_CODE128AB: case BARCODE_GS1_128: case BARCODE_GS1_128_CC: case BARCODE_HIBC_128: @@ -3472,6 +3613,21 @@ QString MainWindow::get_setting_name(int symbology) case BARCODE_HIBC_QR: symbology = BARCODE_QRCODE; break; + case BARCODE_DBAR_OMN_CC: + symbology = BARCODE_DBAR_OMN; + break; + case BARCODE_DBAR_OMNSTK_CC: + symbology = BARCODE_DBAR_OMNSTK; + break; + case BARCODE_DBAR_LTD_CC: + symbology = BARCODE_DBAR_LTD; + break; + case BARCODE_DBAR_STK_CC: + symbology = BARCODE_DBAR_STK; + break; + case BARCODE_DBAR_EXP_CC: + symbology = BARCODE_DBAR_EXP; + break; case BARCODE_DBAR_EXPSTK_CC: symbology = BARCODE_DBAR_EXPSTK; break; @@ -3488,11 +3644,7 @@ QString MainWindow::get_setting_name(int symbology) symbology = BARCODE_UPCE; break; } - if (ZBarcode_BarcodeName(symbology, name_buf) != 0) { - return QSL(""); - } - QString name(name_buf + 8); // Strip "BARCODE_" prefix - return name.toLower(); + return Zint::QZint::barcodeName(symbology).mid(8).toLower(); // Strip "BARCODE_" prefix } /* Helper to return index of selected radio button in group, checking for NULL */ @@ -3624,7 +3776,7 @@ void MainWindow::set_spn_from_setting(QSettings &settings, const QString &settin void MainWindow::save_sub_settings(QSettings &settings, int symbology) { QString name = get_setting_name(symbology); - if (!name.isEmpty()) { + if (!name.isEmpty()) { // Should never be empty settings.setValue(QSL("studio/bc/%1/data").arg(name), txtData->text()); if (!grpSegs->isHidden()) { settings.setValue(QSL("studio/bc/%1/data_seg1").arg(name), txtDataSeg1->text()); @@ -3683,11 +3835,14 @@ void MainWindow::save_sub_settings(QSettings &settings, int symbology) settings.setValue(QSL("studio/bc/%1/paper/green").arg(name), m_bgcolor.green()); settings.setValue(QSL("studio/bc/%1/paper/blue").arg(name), m_bgcolor.blue()); settings.setValue(QSL("studio/bc/%1/paper/alpha").arg(name), m_bgcolor.alpha()); + settings.setValue(QSL("studio/bc/%1/xdimdpvars/x_dim").arg(name), m_xdimdpVars.x_dim); + settings.setValue(QSL("studio/bc/%1/xdimdpvars/x_dim_units").arg(name), m_xdimdpVars.x_dim_units); + settings.setValue(QSL("studio/bc/%1/xdimdpvars/set").arg(name), m_xdimdpVars.set); } switch (symbology) { case BARCODE_CODE128: - case BARCODE_CODE128B: + case BARCODE_CODE128AB: case BARCODE_GS1_128: case BARCODE_GS1_128_CC: case BARCODE_HIBC_128: @@ -3999,7 +4154,7 @@ void MainWindow::save_sub_settings(QSettings &settings, int symbology) void MainWindow::load_sub_settings(QSettings &settings, int symbology) { QString name = get_setting_name(symbology); - if (!name.isEmpty()) { + if (!name.isEmpty()) { // Should never be empty const QString &tdata = settings.value(QSL("studio/bc/%1/data").arg(name), QSL("")).toString(); if (!tdata.isEmpty()) { txtData->setText(tdata); @@ -4071,11 +4226,19 @@ void MainWindow::load_sub_settings(QSettings &settings, int symbology) settings.value(QSL("studio/bc/%1/paper/green").arg(name), 0xff).toInt(), settings.value(QSL("studio/bc/%1/paper/blue").arg(name), 0xff).toInt(), settings.value(QSL("studio/bc/%1/paper/alpha").arg(name), 0xff).toInt()); + + m_xdimdpVars.x_dim = settings.value(QSL("studio/bc/%1/xdimdpvars/x_dim").arg(name), 0.0).toFloat(); + m_xdimdpVars.x_dim_units = settings.value(QSL("studio/bc/%1/xdimdpvars/x_dim_units").arg(name), 0).toInt(); + m_xdimdpVars.set = settings.value(QSL("studio/bc/%1/xdimdpvars/set").arg(name), 0).toInt(); + } else { + m_xdimdpVars.x_dim = 0.0; + m_xdimdpVars.x_dim_units = 0; + m_xdimdpVars.set = 0; } switch (symbology) { case BARCODE_CODE128: - case BARCODE_CODE128B: + case BARCODE_CODE128AB: case BARCODE_GS1_128: case BARCODE_GS1_128_CC: case BARCODE_HIBC_128: @@ -4384,4 +4547,14 @@ void MainWindow::load_sub_settings(QSettings &settings, int symbology) } } +float MainWindow::get_dpmm(const struct Zint::QZintXdimDpVars* vars) const +{ + return (float) (vars->resolution_units == 1 ? vars->resolution / 25.4 : vars->resolution); +} + +const char *MainWindow::getFileType(const struct Zint::QZintXdimDpVars* vars, bool msg) const +{ + return Zint::QZintXdimDpVars::getFileType(m_bc.bc.symbol(), vars, msg); +} + /* vim: set ts=4 sw=4 et : */ diff --git a/frontend_qt/mainwindow.h b/frontend_qt/mainwindow.h index 84b99ad9..84f04389 100644 --- a/frontend_qt/mainwindow.h +++ b/frontend_qt/mainwindow.h @@ -24,14 +24,16 @@ #include #include -#include "ui_mainWindow.h" -#include "barcodeitem.h" - class QLabel; class QShortcut; class QDoubleSpinBox; class QPushButton; +#include "ui_mainWindow.h" +#include "barcodeitem.h" + +class ScaleWindow; + class MainWindow : public QWidget, private Ui::mainWindow { Q_OBJECT @@ -64,7 +66,6 @@ public slots: void composite_ean_check(); void maxi_scm_ui_set(); void msi_plessey_ui_set(); - void change_print_scale(); void change_cmyk(); void autoheight_ui_set(); void HRTShow_ui_set(); @@ -74,6 +75,7 @@ public slots: void on_encoded(); void on_errored(); void on_dataChanged(const QString& text, bool escaped, int seg_no); + void on_scaleChanged(double scale); void filter_symbologies(); bool save(); @@ -97,6 +99,7 @@ public slots: void clear_composite(); void zap(); void open_cli_dialog(); + void open_scale_dialog(); void copy_to_clipboard_bmp(); void copy_to_clipboard_emf(); @@ -112,8 +115,11 @@ public slots: void height_per_row_disable(); void height_per_row_default(); - void guard_reset_upcean(); - void guard_reset_upca(); + void guard_default_upcean(); + void guard_default_upca(); + + void daft_ui_set(); + void daft_tracker_default(); void view_context_menu(const QPoint &pos); void errtxtBar_context_menu(const QPoint &pos); @@ -134,9 +140,11 @@ protected: virtual bool eventFilter(QObject *watched, QEvent *event) override; void combobox_item_enabled(QComboBox *comboBox, int index, bool enabled); - void upcean_addon_gap(const QString &comboBoxName, const QString &labelName, int base); - void upcean_guard_descent(const QString &spnBoxName, const QString &labelName); - void guard_reset(const QString &spnBoxName); + bool upcean_addon_gap(const QString &comboBoxName, const QString &labelName, int base); + void upcean_guard_descent(const QString &spnBoxName, const QString &labelName, const QString &btnDefaultName, + bool enabled = true); + void guard_default(const QString &spnBoxName); + double get_height_per_row_default(); void set_gs1_mode(bool gs1_mode); void set_smaller_font(const QString &labelName); @@ -187,6 +195,11 @@ protected: void save_sub_settings(QSettings &settings, int symbology); void load_sub_settings(QSettings &settings, int symbology); + void size_msg_ui_set(); + + float get_dpmm(const struct Zint::QZintXdimDpVars *vars) const; + const char *getFileType(const struct Zint::QZintXdimDpVars *vars, bool msg = false) const; + private: QColor m_fgcolor, m_bgcolor; QByteArray m_fgcolor_geometry, m_bgcolor_geometry; @@ -223,6 +236,8 @@ private: QDoubleSpinBox *m_spnHeightPerRow; QPushButton *m_btnHeightPerRowDisable; QPushButton *m_btnHeightPerRowDefault; + struct Zint::QZintXdimDpVars m_xdimdpVars; + ScaleWindow *m_scaleWindow; }; /* vim: set ts=4 sw=4 et : */ diff --git a/frontend_qt/res/LICENSE_lucide b/frontend_qt/res/LICENSE_lucide new file mode 100644 index 00000000..325e8ff0 --- /dev/null +++ b/frontend_qt/res/LICENSE_lucide @@ -0,0 +1,15 @@ +ISC License + +Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2022. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/frontend_qt/res/scaling.svg b/frontend_qt/res/scaling.svg new file mode 100644 index 00000000..e9b7d889 --- /dev/null +++ b/frontend_qt/res/scaling.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/frontend_qt/resources.qrc b/frontend_qt/resources.qrc index 86c6cf5a..0dd1b020 100644 --- a/frontend_qt/resources.qrc +++ b/frontend_qt/resources.qrc @@ -41,6 +41,7 @@ res/download.svg res/help-circle.svg res/menu.svg + res/scaling.svg res/shuffle.svg res/white-eye.svg res/x.svg diff --git a/frontend_qt/scalewindow.cpp b/frontend_qt/scalewindow.cpp new file mode 100644 index 00000000..178cd2e2 --- /dev/null +++ b/frontend_qt/scalewindow.cpp @@ -0,0 +1,248 @@ +/* + Zint Barcode Generator - the open source barcode generator + Copyright (C) 2022 Robin Stuart + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* SPDX-License-Identifier: GPL-3.0-or-later */ + +//#include +#include +#include + +#include +#include "scalewindow.h" + +// Shorthand +#define QSL QStringLiteral + +/* "Standard" dpmm/dpi equivalents */ +static int resolution_standard(int inch, int val) +{ + /* Note toss-up between rounding 2400 dpi to 94 or 95 (~94.48818897637795275591) */ + static int standards[9][2] = { + { 4, 100 }, { 6, 150 }, { 8, 200 }, { 12, 300 }, { 16, 400 }, + { 24, 600 }, { 47, 1200 }, { 94, 2400 }, { 189, 4800 }, + }; + for (int i = 0; i < 8; i++) { + if (standards[i][inch] == val) { + return standards[i][inch ? 0 : 1]; + } + } + return 0; +} + +ScaleWindow::ScaleWindow(BarcodeItem *bc, Zint::QZintXdimDpVars *vars) + : m_bc(bc), Valid(false), m_vars(*vars) +{ + setupUi(this); + + if (m_bc->bc.noPng()) { + cmbFileType->setItemText(0, QSL("Raster (BMP/GIF/PCX/TIF)")); + } + if (m_bc->bc.symbol() != BARCODE_MAXICODE) { + cmbFileType->setItemText(1, QSL("Vector (EMF/EPS/SVG)")); + cmbFileType->removeItem(2); // EMF + } + + QSettings settings; +#if QT_VERSION < 0x60000 + settings.setIniCodec("UTF-8"); +#endif + + QByteArray geometry = settings.value(QSL("studio/scale/window_geometry")).toByteArray(); + restoreGeometry(geometry); + + spnXdim->setValue(m_vars.x_dim); + cmbXdimUnits->setCurrentIndex(m_vars.x_dim_units); + spnResolution->setValue(m_vars.resolution); + cmbResolutionUnits->setCurrentIndex(m_vars.resolution_units); + + if (m_bc->bc.symbol() == BARCODE_MAXICODE) { + cmbFileType->setCurrentIndex(std::min(m_vars.filetype_maxicode, cmbFileType->count() - 1)); + } else { + cmbFileType->setCurrentIndex(std::min(m_vars.filetype, cmbFileType->count() - 1)); + } + + if (cmbXdimUnits->currentIndex() == 1) { // Inches + spnXdim->setSingleStep(0.001); + } else { + spnXdim->setSingleStep(0.01); + } + if (cmbResolutionUnits->currentIndex() == 1) { // Inches + spnResolution->setSingleStep(50); + } else { + spnResolution->setSingleStep(1); + } + + size_msg_ui_set(); + + QIcon closeIcon(QIcon::fromTheme(QSL("window-close"), QIcon(QSL(":res/x.svg")))); + QIcon okIcon(QIcon(QSL(":res/check.svg"))); + btnCancel->setIcon(closeIcon); + btnOK->setIcon(okIcon); + + connect(btnCancel, SIGNAL(clicked( bool )), SLOT(close())); + connect(btnOK, SIGNAL(clicked( bool )), SLOT(okay())); + connect(spnXdim, SIGNAL(valueChanged( double )), SLOT(update_scale())); + connect(cmbXdimUnits, SIGNAL(currentIndexChanged( int )), SLOT(x_dim_units_change())); + connect(btnXdimDefault, SIGNAL(clicked( bool )), SLOT(x_dim_default())); + connect(spnResolution, SIGNAL(valueChanged( int )), SLOT(update_scale())); + connect(cmbResolutionUnits, SIGNAL(currentIndexChanged( int )), SLOT(resolution_units_change())); + connect(btnResolutionDefault, SIGNAL(clicked( bool )), SLOT(resolution_default())); + connect(cmbFileType, SIGNAL(currentIndexChanged( int )), SLOT(update_scale())); +} + +ScaleWindow::~ScaleWindow() +{ + QSettings settings; +#if QT_VERSION < 0x60000 + settings.setIniCodec("UTF-8"); +#endif + settings.setValue(QSL("studio/scale/window_geometry"), saveGeometry()); +} + +void ScaleWindow::size_msg_ui_set() +{ + msgPrintingScale->setText(QString::asprintf("%.2f", m_bc->bc.scale())); + float width_x_dim, height_x_dim; + if (m_bc->bc.getWidthHeightXdim((float) m_vars.x_dim, width_x_dim, height_x_dim)) { + const char *fmt = cmbXdimUnits->currentIndex() == 1 ? "%.3f x %.3f in" : "%.2f x %.2f mm"; + msgWidthHeight->setText(QString::asprintf(fmt, width_x_dim, height_x_dim)); + } else { + msgWidthHeight->clear(); + } + + bool defaultDisable; + QWidget *focus = QApplication::focusWidget(); + + // This doesn't work well due to rounding errors TODO: fix + defaultDisable = m_bc->bc.defaultXdim() == (float) get_x_dim_mm(); + btnXdimDefault->setEnabled(!defaultDisable); + if (focus == btnXdimDefault && defaultDisable) { + spnXdim->setFocus(); + } + + defaultDisable = (cmbResolutionUnits->currentIndex() == 0 && spnResolution->value() == 12) + || (cmbResolutionUnits->currentIndex() == 1 && spnResolution->value() == 300); + btnResolutionDefault->setEnabled(!defaultDisable); + if (focus == btnResolutionDefault && defaultDisable) { + spnResolution->setFocus(); + } +} + +void ScaleWindow::okay() +{ + if (update_vars()) { + Valid = true; + m_vars.set = 1; + } + close(); +} + +void ScaleWindow::update_scale() +{ + float scale = update_vars(); + if (scale) { + // Need up-to-date `vectorWidth()` and `vectorHeight()` to estimate size including borders, whitespace & text, + // so tell main window to encode and it will update UI here via `size_msg_ui_set()` + emit scaleChanged(scale); + } +} + +void ScaleWindow::x_dim_units_change() +{ + if (cmbXdimUnits->currentIndex() == 1) { // Inches + spnXdim->setValue(spnXdim->value() / 25.4); + spnXdim->setSingleStep(0.001); + } else { + spnXdim->setValue(spnXdim->value() * 25.4); + spnXdim->setSingleStep(0.01); + } + update_scale(); +} + +void ScaleWindow::x_dim_default() +{ + if (cmbXdimUnits->currentIndex() == 1) { // Inches + spnXdim->setValue(m_bc->bc.defaultXdim() / 25.4); + } else { + spnXdim->setValue(m_bc->bc.defaultXdim()); + } + update_scale(); +} + +void ScaleWindow::resolution_units_change() +{ + int value; + if (cmbResolutionUnits->currentIndex() == 1) { // Inches + if ((value = resolution_standard(0, spnResolution->value()))) { + spnResolution->setValue(value); + } else { + spnResolution->setValue((int) roundf(spnResolution->value() * 25.4f)); + } + spnResolution->setSingleStep(50); + } else { + if ((value = resolution_standard(1, spnResolution->value()))) { + spnResolution->setValue(value); + } else { + spnResolution->setValue((int) roundf(spnResolution->value() / 25.4f)); + } + spnResolution->setSingleStep(1); + } + update_scale(); +} + +void ScaleWindow::resolution_default() +{ + spnResolution->setValue(cmbResolutionUnits->currentIndex() == 1 ? 300 : 12); + update_scale(); +} + +float ScaleWindow::get_x_dim_mm() const +{ + return (float) (cmbXdimUnits->currentIndex() == 1 ? spnXdim->value() * 25.4 : spnXdim->value()); + +} + +float ScaleWindow::get_dpmm() const +{ + return (float) (cmbResolutionUnits->currentIndex() == 1 ? spnResolution->value() / 25.4 : spnResolution->value()); +} + +const char *ScaleWindow::getFileType() const +{ + static const char *filetypes[3] = { "GIF", "SVG", "EMF" }; + return filetypes[std::max(std::min(cmbFileType->currentIndex(), 2), 0)]; +} + +double ScaleWindow::update_vars() +{ + double scale = (double) m_bc->bc.getScaleFromXdimDp(get_x_dim_mm(), get_dpmm(), getFileType()); + if (scale != 0.0) { + m_vars.x_dim = spnXdim->value(); + m_vars.x_dim_units = cmbXdimUnits->currentIndex(); + m_vars.resolution = spnResolution->value(); + m_vars.resolution_units = cmbResolutionUnits->currentIndex(); + if (m_bc->bc.symbol() == BARCODE_MAXICODE) { + m_vars.filetype_maxicode = cmbFileType->currentIndex(); + } else { + m_vars.filetype = cmbFileType->currentIndex(); + } + } + return scale; +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/frontend_qt/scalewindow.h b/frontend_qt/scalewindow.h new file mode 100644 index 00000000..01833288 --- /dev/null +++ b/frontend_qt/scalewindow.h @@ -0,0 +1,63 @@ +/* + Zint Barcode Generator - the open source barcode generator + Copyright (C) 2022 Robin Stuart + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +/* SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef SCALEWINDOW_H +#define SCALEWINDOW_H + +#include "ui_extScale.h" +#include "barcodeitem.h" + +class ScaleWindow : public QDialog, private Ui::ScaleDialog +{ + Q_OBJECT + +private: + BarcodeItem *m_bc; + +public: + ScaleWindow(BarcodeItem *bc, struct Zint::QZintXdimDpVars *vars); + ~ScaleWindow(); + + bool Valid; + + struct Zint::QZintXdimDpVars m_vars; + +signals: + void scaleChanged(double scale); + +public slots: + void size_msg_ui_set(); +private slots: + void okay(); + void update_scale(); + void x_dim_units_change(); + void x_dim_default(); + void resolution_units_change(); + void resolution_default(); + +private: + float get_x_dim_mm() const; + float get_dpmm() const; + const char *getFileType() const; + double update_vars(); +}; + +/* vim: set ts=4 sw=4 et : */ +#endif diff --git a/win32/README b/win32/README index ddb1743c..55109ef5 100644 --- a/win32/README +++ b/win32/README @@ -31,7 +31,7 @@ First build zlib: cd zlib nmake -f win32\Makefile.msc clean - nmake -f win32\Makefile.msc LOC="-DASMV -DASMINF=" OBJA="inffas32.obj match686.obj" + nmake -f win32\Makefile.msc cd .. diff --git a/win32/zint_cmdline_vc6/readme.txt b/win32/zint_cmdline_vc6/readme.txt index b30ac566..f9d77890 100644 --- a/win32/zint_cmdline_vc6/readme.txt +++ b/win32/zint_cmdline_vc6/readme.txt @@ -13,13 +13,13 @@ $ZR is the zint root folder (this file is in $ZR\win32\zint_cmdline_vc6) (if not available in the Start Menu, open a Command Prompt and run "C:\Program Files (x86)\Microsoft Visual Studio\VC98\Bin\VCVARS32.BAT") -a) zlib (current version: 1.2.11) +a) zlib (current version: 1.2.13) * put zlib to $ZR\..\zlib cd $ZR\..\zlib nmake -f win32\Makefile.msc -> generates zlib.lib, zlib1.dll -b) lpng (current version: 1.6.37) +b) lpng (current version: 1.6.39) * put libpng to $ZR\..\lpng cd $ZR\..\lpng nmake -f scripts\makefile.vcwin32