mirror of
https://git.code.sf.net/p/zint/code
synced 2025-05-09 13:41:59 -04:00
EAN/UPC: add quiet zone indicators option (API output_options
`EANUPC_GUARD_WHITESPACE`, CLI `--guardwhitespace`) (ticket #287) EAN-2/EAN-5: HRT now at top instead of at bottom for standalones, following BWIPP CLI: batch mode: don't close input if stdin EAN/UPC: fix excess 1X to right of add-ons Composites: fix excess whitespace; fix quiet zone calcs to allow for linear shifting CLI: use own (Wine) version of `CommandLineToArgvW()` to avoid loading "shell32.dll" Move "font.h" -> "raster_font.h" EPS/SVG: use new `out_putsf()` func to output floats, avoiding trailing zeroes & locale dependency EPS: simplify "TR" formula SVG: change font from "Helvetica, sans serif" to "OCR-B, monospace"; use single "<path>" instead of multiple "<rect>"s to draw boxes (reduces file size) Add `EMBED_VECTOR_FONT` to `output_options` (CLI `--embedfont`) to enable embedding of font in vector output - currently only for SVG output of EAN/UPC GUI: use "OCR-B" font for EAN/UPC and "Arimo" for all others (was "Helvetica" for both); paint background of screen preview light grey so as contrasts with whitespace and quiet zones EMF: prefix funcs with `emf_`; simplify string `halign` handling large: rename `large_int` -> `large_uint` CODE128/common: move `c128_hrt_cpy_iso8859_1()` to `hrt_cpy_iso8859_1()` and add `ZINT_WARN_HRT_TRUNCATED` warning (for future use) Various symbologies: replace `printf()` with `fputs()` (symbol->debug) QRCODE: better assert(), removing a NOLINT (2 left) CLI: add some more barcode synonyms for DBAR common: various fiddlings CMake: don't include png.c unless ZINT_USE_PNG (avoids clang warning)
This commit is contained in:
parent
6d015d6a8f
commit
607e4ed33a
395 changed files with 11528 additions and 23016 deletions
159
backend/output.c
159
backend/output.c
|
@ -190,7 +190,7 @@ INTERNAL int out_colour_get_cmyk(const char *colour, int *cyan, int *magenta, in
|
|||
}
|
||||
|
||||
/* Return minimum quiet zones for each symbology */
|
||||
static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text,
|
||||
static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text, const int comp_xoffset,
|
||||
float *left, float *right, float *top, float *bottom) {
|
||||
int done = 0;
|
||||
|
||||
|
@ -235,33 +235,39 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text
|
|||
case BARCODE_ISBNX:
|
||||
/* GS1 General Specifications 21.0.1 Section 5.2.3.4 */
|
||||
switch (ustrlen(symbol->text)) {
|
||||
case 13: /* EAN-13 */
|
||||
case 13: /* EAN-13/ISBN */
|
||||
if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) {
|
||||
*left = 11.0f;
|
||||
*right = 7.0f;
|
||||
*left = comp_xoffset >= 10 ? 1.0f : 11.0f - comp_xoffset; /* Need at least 1X for CC-A/B */
|
||||
*right = 7.0f - (comp_xoffset != 0);
|
||||
} else if (!hide_text) {
|
||||
*left = 11.0f; /* Need for outside left digit */
|
||||
*left = comp_xoffset >= 10 ? 1.0f : 11.0f - comp_xoffset; /* Need for outside left digit */
|
||||
}
|
||||
break;
|
||||
case 16: /* EAN-13/ISBN + 2 digit addon */
|
||||
case 19: /* EAN-13/ISBN + 5 digit addon */
|
||||
case 16: /* EAN-13/ISBN + 2 digit add-on */
|
||||
case 19: /* EAN-13/ISBN + 5 digit add-on */
|
||||
if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) {
|
||||
*left = 11.0f;
|
||||
*left = comp_xoffset >= 10 ? 1.0f : 11.0f - comp_xoffset; /* Need at least 1X for CC-A/B */
|
||||
*right = 5.0f;
|
||||
} else if (!hide_text) {
|
||||
*left = 11.0f; /* Need for outside left digit */
|
||||
*left = comp_xoffset >= 10 ? 1.0f : 11.0f - comp_xoffset; /* Need for outside left digit */
|
||||
}
|
||||
break;
|
||||
case 5: /* EAN-5 addon */
|
||||
case 2: /* EAN-2 addon */
|
||||
case 5: /* EAN-5 add-on */
|
||||
case 2: /* EAN-2 add-on */
|
||||
if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) {
|
||||
*left = 7.0f;
|
||||
*right = 5.0f;
|
||||
}
|
||||
break;
|
||||
default: /* EAN-8 (+/- 2/5 digit addon) */
|
||||
case 8: /* EAN-8 */
|
||||
if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) {
|
||||
*left = *right = 7.0f;
|
||||
*left = comp_xoffset >= 6 ? 1.0f : 7.0f - comp_xoffset; /* Need at least 1X for CC-A/B */
|
||||
*right = 7.0f - (comp_xoffset != 0);
|
||||
}
|
||||
break;
|
||||
default: /* EAN-8 + 2/5 digit add-on */
|
||||
if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) {
|
||||
*left = comp_xoffset >= 6 ? 1.0f : 7.0f - comp_xoffset; /* Need at least 1X for CC-A/B */
|
||||
*right = 5.0f;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -272,16 +278,16 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text
|
|||
case BARCODE_UPCA_CC:
|
||||
/* GS1 General Specifications 21.0.1 Section 5.2.3.4 */
|
||||
if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) {
|
||||
*left = 9.0f;
|
||||
if (ustrlen(symbol->text) > 12) { /* UPC-A + addon */
|
||||
*left = comp_xoffset >= 8 ? 1.0f : 9.0f - comp_xoffset; /* Need at least 1X for CC-A/B */
|
||||
if (ustrlen(symbol->text) > 12) { /* UPC-A + add-on */
|
||||
*right = 5.0f;
|
||||
} else {
|
||||
*right = 9.0f;
|
||||
*right = 9.0f - (comp_xoffset != 0);
|
||||
}
|
||||
} else if (!hide_text) {
|
||||
*left = 9.0f; /* Need for outside left digit */
|
||||
if (ustrlen(symbol->text) <= 12) { /* No addon */
|
||||
*right = 9.0f; /* Need for outside right digit */
|
||||
*left = comp_xoffset >= 8 ? 1.0f : 9.0f - comp_xoffset; /* Need for outside left digit */
|
||||
if (ustrlen(symbol->text) <= 12) { /* No add-on */
|
||||
*right = 9.0f - (comp_xoffset != 0); /* Need for outside right digit */
|
||||
}
|
||||
}
|
||||
done = 1;
|
||||
|
@ -291,16 +297,16 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text
|
|||
case BARCODE_UPCE_CC:
|
||||
/* GS1 General Specifications 21.0.1 Section 5.2.3.4 */
|
||||
if (!(symbol->output_options & BARCODE_NO_QUIET_ZONES)) {
|
||||
*left = 9.0f;
|
||||
if (ustrlen(symbol->text) > 8) { /* UPC-E + addon */
|
||||
*left = comp_xoffset >= 8 ? 1.0f : 9.0f - comp_xoffset;
|
||||
if (ustrlen(symbol->text) > 8) { /* UPC-E + add-on */
|
||||
*right = 5.0f;
|
||||
} else {
|
||||
*right = 7.0f;
|
||||
*right = 7.0f - (comp_xoffset != 0);
|
||||
}
|
||||
} else if (!hide_text) {
|
||||
*left = 9.0f; /* Need for outside left digit */
|
||||
if (ustrlen(symbol->text) <= 8) { /* No addon */
|
||||
*right = 7.0f; /* Need for outside right digit */
|
||||
*left = comp_xoffset >= 8 ? 1.0f : 9.0f - comp_xoffset; /* Need for outside left digit */
|
||||
if (ustrlen(symbol->text) <= 8) { /* No add-on */
|
||||
*right = 7.0f - (comp_xoffset != 0); /* Need for outside right digit */
|
||||
}
|
||||
}
|
||||
done = 1;
|
||||
|
@ -349,12 +355,28 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text
|
|||
done = 1;
|
||||
break;
|
||||
case BARCODE_GS1_128: /* GS1-128 */
|
||||
case BARCODE_GS1_128_CC:
|
||||
case BARCODE_EAN14:
|
||||
/* GS1 General Specifications 21.0.1 Section 5.4.4.2 */
|
||||
*left = *right = 10.0f;
|
||||
done = 1;
|
||||
break;
|
||||
case BARCODE_GS1_128_CC:
|
||||
/* GS1 General Specifications 21.0.1 Sections 5.11.2.1 (CC-A), 5.11.2.2 (CC-B) & 5.11.2.3 (CC-C) */
|
||||
{
|
||||
int comp_roffset = 0; /* Right offset of linear */
|
||||
int min_qz; /* Minimum quiet zone - 1X for CC-A/B, 2X for CC-C */
|
||||
int x;
|
||||
for (x = symbol->width - 1; x >= 0 && !module_is_set(symbol, symbol->rows - 1, x); x--) {
|
||||
comp_roffset++;
|
||||
}
|
||||
/* Determine if CC-C by counting initial start pattern */
|
||||
for (x = 0; x < 8 && module_is_set(symbol, 0, x); x++);
|
||||
min_qz = x == 8 ? 2 : 1;
|
||||
*left = comp_xoffset >= 10 - min_qz ? min_qz : 10.0f - comp_xoffset;
|
||||
*right = comp_roffset >= 10 - min_qz ? min_qz : 10.0f - comp_roffset;
|
||||
}
|
||||
done = 1;
|
||||
break;
|
||||
case BARCODE_CODABAR:
|
||||
/* BS EN 798:1995 Section 4.4.1 (d) */
|
||||
*left = *right = 10.0f;
|
||||
|
@ -394,14 +416,26 @@ static int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text
|
|||
/* GS1 General Specifications 21.0.1 Section 5.5.1.1 - Quiet Zones: None required */
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
/* GS1 General Specifications 21.0.1 Sections 5.11.2.1 (CC-A) & 5.11.2.2 (CC-B) require 1X either side
|
||||
but this may be supplied by the positioning of the linear component */
|
||||
case BARCODE_DBAR_OMN_CC:
|
||||
case BARCODE_DBAR_LTD_CC:
|
||||
case BARCODE_DBAR_EXP_CC:
|
||||
/* Always have at least 1X to right of CC-A/B */
|
||||
if (comp_xoffset > 1) { /* Exclude DBAR_LTD_CC with CC-A which always has 1X to left */
|
||||
*left = 1.0f;
|
||||
}
|
||||
done = 1;
|
||||
break;
|
||||
case BARCODE_DBAR_STK_CC:
|
||||
case BARCODE_DBAR_OMNSTK_CC:
|
||||
/* Always have at least 1X to left of CC-A/B */
|
||||
*right = 1.0f;
|
||||
done = 1;
|
||||
break;
|
||||
case BARCODE_DBAR_EXP_CC:
|
||||
case BARCODE_DBAR_EXPSTK_CC:
|
||||
/* GS1 General Specifications 21.0.1 Sections 5.11.2.1 (CC-A) & 5.11.2.2 (CC-B) */
|
||||
*left = *right = 1.0f;
|
||||
/* Always have at least 1X to left and right of CC-A/B */
|
||||
done = 1;
|
||||
break;
|
||||
|
||||
|
@ -614,19 +648,19 @@ 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,
|
||||
INTERNAL int out_quiet_zones_test(const struct zint_symbol *symbol, const int hide_text, const int comp_xoffset,
|
||||
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, comp_xoffset, left, right, top, bottom);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set left (x), top (y), right and bottom offsets for whitespace */
|
||||
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,
|
||||
int *xoffset_si, int *yoffset_si, int *roffset_si, int *boffset_si) {
|
||||
const int comp_xoffset, float *xoffset, float *yoffset, float *roffset, float *boffset,
|
||||
const float scaler, int *xoffset_si, int *yoffset_si, int *roffset_si, int *boffset_si) {
|
||||
float qz_left, qz_right, qz_top, qz_bottom;
|
||||
|
||||
out_quiet_zones(symbol, hide_text, &qz_left, &qz_right, &qz_top, &qz_bottom);
|
||||
out_quiet_zones(symbol, hide_text, comp_xoffset, &qz_left, &qz_right, &qz_top, &qz_bottom);
|
||||
|
||||
*xoffset = symbol->whitespace_width + qz_left;
|
||||
*roffset = symbol->whitespace_width + qz_right;
|
||||
|
@ -658,22 +692,22 @@ INTERNAL void out_set_whitespace_offsets(const struct zint_symbol *symbol, const
|
|||
}
|
||||
}
|
||||
|
||||
/* Set composite offset and main width excluding addon (for start of addon calc) and addon text, returning
|
||||
/* Set composite offset and main width excluding add-on (for start of add-on calc) and add-on text, returning
|
||||
UPC/EAN type */
|
||||
INTERNAL int out_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset,
|
||||
INTERNAL int out_process_upcean(const struct zint_symbol *symbol, const int comp_xoffset, int *p_main_width,
|
||||
unsigned char addon[6], int *p_addon_gap) {
|
||||
int main_width; /* Width of main linear symbol, excluding addon */
|
||||
int comp_xoffset; /* Whitespace offset (if any) of main linear symbol due to having composite */
|
||||
int main_width; /* Width of main linear symbol, excluding add-on */
|
||||
int upceanflag; /* UPC/EAN type flag */
|
||||
int i, j, latch;
|
||||
int text_length = (int) ustrlen(symbol->text);
|
||||
const int text_length = (int) ustrlen(symbol->text);
|
||||
|
||||
latch = 0;
|
||||
j = 0;
|
||||
/* Isolate add-on text */
|
||||
for (i = 6; i < text_length && j < 5; i++) {
|
||||
if (latch == 1) {
|
||||
addon[j] = symbol->show_hrt ? symbol->text[i] : ' '; /* Use dummy space-filled addon if no hrt */
|
||||
/* Use dummy space-filled add-on if no hrt */
|
||||
addon[j] = symbol->show_hrt ? symbol->text[i] : ' ';
|
||||
j++;
|
||||
} else if (symbol->text[i] == '+') {
|
||||
latch = 1;
|
||||
|
@ -689,14 +723,6 @@ INTERNAL int out_process_upcean(const struct zint_symbol *symbol, int *p_main_wi
|
|||
}
|
||||
}
|
||||
|
||||
/* Calculate composite offset */
|
||||
comp_xoffset = 0;
|
||||
if (is_composite(symbol->symbology)) {
|
||||
while (!(module_is_set(symbol, symbol->rows - 1, comp_xoffset))) {
|
||||
comp_xoffset++;
|
||||
}
|
||||
}
|
||||
|
||||
upceanflag = 0;
|
||||
main_width = symbol->width;
|
||||
if ((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CHK)
|
||||
|
@ -709,11 +735,11 @@ INTERNAL int out_process_upcean(const struct zint_symbol *symbol, int *p_main_wi
|
|||
upceanflag = 13;
|
||||
break;
|
||||
case 2:
|
||||
/* EAN-2 can't have addon or be composite */
|
||||
/* EAN-2 can't have add-on or be composite */
|
||||
upceanflag = 2;
|
||||
break;
|
||||
case 5:
|
||||
/* EAN-5 can't have addon or be composite */
|
||||
/* EAN-5 can't have add-on or be composite */
|
||||
upceanflag = 5;
|
||||
break;
|
||||
default:
|
||||
|
@ -731,7 +757,6 @@ INTERNAL int out_process_upcean(const struct zint_symbol *symbol, int *p_main_wi
|
|||
upceanflag = 6;
|
||||
}
|
||||
|
||||
*p_comp_xoffset = comp_xoffset;
|
||||
*p_main_width = main_width;
|
||||
|
||||
return upceanflag;
|
||||
|
@ -989,4 +1014,34 @@ INTERNAL FILE *out_fopen(const char filename[256], const char *mode) {
|
|||
return outfile;
|
||||
}
|
||||
|
||||
/* Output float without trailing zeroes to `fp` with decimal pts `dp` (precision) */
|
||||
INTERNAL void out_putsf(const char *const prefix, const int dp, const float arg, FILE *fp) {
|
||||
int i, end;
|
||||
char buf[256]; /* Assuming `dp` reasonable */
|
||||
const int len = sprintf(buf, "%.*f", dp, arg);
|
||||
|
||||
if (*prefix) {
|
||||
fputs(prefix, fp);
|
||||
}
|
||||
|
||||
/* Adapted from https://stackoverflow.com/a/36202854/664741 */
|
||||
for (i = len - 1, end = len; i >= 0; i--) {
|
||||
if (buf[i] == '0') {
|
||||
if (end == i + 1) {
|
||||
end = i;
|
||||
}
|
||||
} else if (!z_isdigit(buf[i]) && buf[i] != '-') { /* If not digit or minus then decimal point */
|
||||
if (end == i + 1) {
|
||||
end = i;
|
||||
} else {
|
||||
buf[i] = '.'; /* Overwrite any locale-specific setting for decimal point */
|
||||
}
|
||||
buf[end] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fputs(buf, fp);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et : */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue