Add BARCODE_MEMORY_FILE to symbol->output_options to allow

outputting to in-memory buffer `symbol->memfile` instead of to
  file `symbol->outfile`, ticket #301
Add "README.clang-tidy" and ".clang-tidy" options file
Suppress some warnings
This commit is contained in:
gitlost 2023-12-27 19:20:19 +00:00
parent 070162214b
commit 98f86727cc
59 changed files with 2407 additions and 1262 deletions

3
.clang-tidy Normal file
View File

@ -0,0 +1,3 @@
---
Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-security.insecureAPI.strcpy'
HeaderFilterRegex: '.*'

View File

@ -3,12 +3,16 @@ Version 2.13.0.9 (dev) not released yet
**Incompatible changes** **Incompatible changes**
------------------------ ------------------------
None so far - New `memfile` & `memfile_size` fields in `symbol` for use with new output
option `BARCODE_MEMORY_FILE`
Changes Changes
------- -------
- BMP: lessen heap memory usage by only `malloc()`ing a row - BMP: lessen heap memory usage by only `malloc()`ing a row
- GIF: lessen heap memory usage by paging; use standard colour char map - GIF: lessen heap memory usage by paging; use standard colour char map
- Add `BARCODE_MEMORY_FILE` to `symbol->output_options` to allow outputting to
in-memory buffer `symbol->memfile` instead of to file `symbol->outfile`,
ticket #301
Bugs Bugs
---- ----

21
README.clang-tidy Normal file
View File

@ -0,0 +1,21 @@
Current as of latest clang-tidy-18 from Ubuntu 22.04 apt package (2023-12-26)
Requires cmake in "build" sub-directory with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON (for "build/compile_commands.json")
and -DCMAKE_BUILD_TYPE=Debug (so `assert()`s defined), and then make (for Qt generated includes).
In project root directory (warning, slow):
clang-tidy-18 backend/*.c frontend/*.c backend_qt/*.cpp frontend_qt/*.cpp -p build/compile_commands.json
For "backend_tcl", which has no "compile_commands.json", specify the tcl include directory, e.g.
clang-tidy-18 backend_tcl/*.c -- -I/usr/include/tcl8.6
Options are in ".clang-tidy" (in the project root directory). The excluded checks are
`clang-analyzer-security.insecureAPI.strcpy` (for `strcpy()`, `strcat()` etc), and
`clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling` (for `sprintf()`).
The test suite (cmake given -DZINT_TEST=ON) can also be analysed with an additional check disabled:
clang-tidy-18 backend/tests/*.c frontend/tests/*.c backend_qt/tests/*.cpp \
-checks='-clang-analyzer-optin.performance.Padding' -p build/compile_commands.json

View File

@ -8,7 +8,7 @@ if(ZINT_USE_PNG)
find_package(PNG) find_package(PNG)
endif() endif()
set(zint_COMMON_SRCS common.c library.c large.c reedsol.c gs1.c eci.c general_field.c) set(zint_COMMON_SRCS common.c library.c large.c reedsol.c gs1.c eci.c filemem.c general_field.c)
set(zint_ONEDIM_SRCS bc412.c code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c) set(zint_ONEDIM_SRCS bc412.c code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c)
set(zint_POSTAL_SRCS postal.c auspost.c imail.c mailmark.c) set(zint_POSTAL_SRCS postal.c auspost.c imail.c mailmark.c)
set(zint_TWODIM_SRCS code16k.c codablock.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c ultra.c) set(zint_TWODIM_SRCS code16k.c codablock.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c ultra.c)

View File

@ -24,7 +24,7 @@ APP:=zint
DLL:=$(APP).dll DLL:=$(APP).dll
STATLIB:=lib$(APP).a STATLIB:=lib$(APP).a
COMMON_OBJ:= common.o library.o large.o reedsol.o gs1.o eci.o general_field.o sjis.o gb2312.o gb18030.o COMMON_OBJ:= common.o library.o large.o reedsol.o gs1.o eci.o filemem.o general_field.o sjis.o gb2312.o gb18030.o
ONEDIM_OBJ:= code.o code128.o 2of5.o upcean.o telepen.o medical.o plessey.o rss.o ONEDIM_OBJ:= code.o code128.o 2of5.o upcean.o telepen.o medical.o plessey.o rss.o
POSTAL_OBJ:= postal.o auspost.o imail.o mailmark.o POSTAL_OBJ:= postal.o auspost.o imail.o mailmark.o
TWODIM_OBJ:= code16k.o codablock.o dmatrix.o pdf417.o qr.o maxicode.o composite.o aztec.o code49.o code1.o gridmtx.o hanxin.o dotcode.o ultra.o TWODIM_OBJ:= code16k.o codablock.o dmatrix.o pdf417.o qr.o maxicode.o composite.o aztec.o code49.o code1.o gridmtx.o hanxin.o dotcode.o ultra.o

View File

@ -33,11 +33,8 @@
#include <errno.h> #include <errno.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#endif
#include "common.h" #include "common.h"
#include "filemem.h"
#include "output.h" #include "output.h"
#include "bmp.h" /* Bitmap header structure */ #include "bmp.h" /* Bitmap header structure */
@ -47,7 +44,8 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
int colour_count; int colour_count;
int resolution; int resolution;
size_t row_size, data_offset, file_size; size_t row_size, data_offset, file_size;
FILE *bmp_file; struct filemem fm;
struct filemem *const fmp = &fm;
bitmap_file_header_t file_header; bitmap_file_header_t file_header;
bitmap_info_header_t info_header; bitmap_info_header_t info_header;
color_ref_t bg; color_ref_t bg;
@ -55,7 +53,6 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
color_ref_t palette[8]; color_ref_t palette[8];
int ultra_fg_index = 9; int ultra_fg_index = 9;
unsigned char map[128]; unsigned char map[128];
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT; /* Suppress gcc -fanalyzer warning */
unsigned char *rowbuf; unsigned char *rowbuf;
(void) out_colour_get_rgb(symbol->fgcolour, &fg.red, &fg.green, &fg.blue, NULL /*alpha*/); (void) out_colour_get_rgb(symbol->fgcolour, &fg.red, &fg.green, &fg.blue, NULL /*alpha*/);
@ -119,36 +116,25 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
info_header.important_colours = colour_count; info_header.important_colours = colour_count;
/* Open output file in binary mode */ /* Open output file in binary mode */
if (output_to_stdout) { if (!fm_open(fmp, symbol, "wb")) {
#ifdef _MSC_VER sprintf(symbol->errtxt, "601: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
sprintf(symbol->errtxt, "600: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
free(rowbuf); free(rowbuf);
return ZINT_ERROR_FILE_ACCESS; return ZINT_ERROR_FILE_ACCESS;
} }
#endif
bmp_file = stdout;
} else {
if (!(bmp_file = out_fopen(symbol->outfile, "wb"))) {
sprintf(symbol->errtxt, "601: Could not open output file (%d: %.30s)", errno, strerror(errno));
free(rowbuf);
return ZINT_ERROR_FILE_ACCESS;
}
}
fwrite(&file_header, sizeof(bitmap_file_header_t), 1, bmp_file); fm_write(&file_header, sizeof(bitmap_file_header_t), 1, fmp);
fwrite(&info_header, sizeof(bitmap_info_header_t), 1, bmp_file); fm_write(&info_header, sizeof(bitmap_info_header_t), 1, fmp);
fwrite(&bg, sizeof(color_ref_t), 1, bmp_file); fm_write(&bg, sizeof(color_ref_t), 1, fmp);
if (bits_per_pixel == 4) { if (bits_per_pixel == 4) {
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
fwrite(&palette[i], sizeof(color_ref_t), 1, bmp_file); fm_write(&palette[i], sizeof(color_ref_t), 1, fmp);
} }
if (ultra_fg_index == 9) { if (ultra_fg_index == 9) {
fwrite(&fg, sizeof(color_ref_t), 1, bmp_file); fm_write(&fg, sizeof(color_ref_t), 1, fmp);
} }
} else { } else {
fwrite(&fg, sizeof(color_ref_t), 1, bmp_file); fm_write(&fg, sizeof(color_ref_t), 1, fmp);
} }
/* Pixel Plotting */ /* Pixel Plotting */
@ -159,7 +145,7 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
for (column = 0; column < symbol->bitmap_width; column++) { for (column = 0; column < symbol->bitmap_width; column++) {
rowbuf[column >> 1] |= map[pb[column]] << (!(column & 1) << 2); rowbuf[column >> 1] |= map[pb[column]] << (!(column & 1) << 2);
} }
fwrite(rowbuf, 1, row_size, bmp_file); fm_write(rowbuf, 1, row_size, fmp);
} }
} else { /* bits_per_pixel == 1 */ } else { /* bits_per_pixel == 1 */
for (row = 0; row < symbol->bitmap_height; row++) { for (row = 0; row < symbol->bitmap_height; row++) {
@ -168,30 +154,21 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
for (column = 0; column < symbol->bitmap_width; column++) { for (column = 0; column < symbol->bitmap_width; column++) {
rowbuf[column >> 3] |= map[pb[column]] >> (column & 7); rowbuf[column >> 3] |= map[pb[column]] >> (column & 7);
} }
fwrite(rowbuf, 1, row_size, bmp_file); fm_write(rowbuf, 1, row_size, fmp);
} }
} }
free(rowbuf); free(rowbuf);
if (ferror(bmp_file)) { if (fm_error(fmp)) {
sprintf(symbol->errtxt, "603: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "603: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(bmp_file);
}
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (output_to_stdout) { if (!fm_close(fmp, symbol)) {
if (fflush(bmp_file) != 0) { sprintf(symbol->errtxt, "605: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
sprintf(symbol->errtxt, "604: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
} else {
if (fclose(bmp_file) != 0) {
sprintf(symbol->errtxt, "605: Failure on closing output file (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE;
}
}
return 0; return 0;
} }

View File

@ -606,6 +606,11 @@ INTERNAL char *debug_print_escape(const unsigned char *source, const int first_l
} }
#ifdef ZINT_TEST #ifdef ZINT_TEST
/* Suppress gcc warning null destination pointer [-Wformat-overflow=] false-positive */
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-overflow="
#endif
/* Dumps hex-formatted codewords in symbol->errtxt (for use in testing) */ /* Dumps hex-formatted codewords in symbol->errtxt (for use in testing) */
INTERNAL void debug_test_codeword_dump(struct zint_symbol *symbol, const unsigned char *codewords, const int length) { INTERNAL void debug_test_codeword_dump(struct zint_symbol *symbol, const unsigned char *codewords, const int length) {
int i, max = length, cnt_len = 0; int i, max = length, cnt_len = 0;
@ -655,6 +660,9 @@ INTERNAL void debug_test_codeword_dump_int(struct zint_symbol *symbol, const int
} }
symbol->errtxt[strlen(symbol->errtxt) - 1] = '\0'; /* Zap last space */ symbol->errtxt[strlen(symbol->errtxt) - 1] = '\0'; /* Zap last space */
} }
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif #endif
#endif /*ZINT_TEST*/
/* vim: set ts=4 sw=4 et : */ /* vim: set ts=4 sw=4 et : */

View File

@ -41,21 +41,37 @@ extern "C" {
#define ARRAY_SIZE(x) ((int) (sizeof(x) / sizeof((x)[0]))) #define ARRAY_SIZE(x) ((int) (sizeof(x) / sizeof((x)[0])))
#endif #endif
/* Determine if C89 (excluding MSVC, which doesn't define __STDC_VERSION__) */ /* Determine if C89 or C99 (excluding MSVC, which doesn't define __STDC_VERSION__) */
#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199000L) #ifndef _MSC_VER
# if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199000L
# define ZINT_IS_C89 # define ZINT_IS_C89
# elif __STDC_VERSION__ <= 199901L /* Actually includes pseudo-standards "C94/C95" as well */
# define ZINT_IS_C99
# endif
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
# include <malloc.h> # include <malloc.h>
# define z_alloca(nmemb) _alloca(nmemb) # define z_alloca(nmemb) _alloca(nmemb)
#else #else
# if defined(ZINT_IS_C89) || defined(__NuttX__) /* C89 or NuttX RTOS */ # if defined(ZINT_IS_C89) || defined(ZINT_IS_C99) || defined(__NuttX__) /* C89 or C99 or NuttX RTOS */
# include <alloca.h> # include <alloca.h>
# endif # endif
# define z_alloca(nmemb) alloca(nmemb) # define z_alloca(nmemb) alloca(nmemb)
#endif #endif
#ifdef _MSC_VER
# if _MSC_VER >= 1400 /* MSVC 2005 (C++ 8.0) */
# define restrict __restrict
# else
# define restrict
# endif
#else
# ifdef ZINT_IS_C89
# define restrict
# endif
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
typedef unsigned __int8 uint8_t; typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t; typedef unsigned __int16 uint16_t;

View File

@ -37,11 +37,8 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#endif
#include "common.h" #include "common.h"
#include "filemem.h"
#include "output.h" #include "output.h"
#include "emf.h" #include "emf.h"
@ -164,7 +161,8 @@ static int emf_utfle_length(const unsigned char *input, const int length) {
INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) { INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
int i; int i;
FILE *emf_file; struct filemem fm;
struct filemem *const fmp = &fm;
unsigned char fgred, fggrn, fgblu, bgred, bggrn, bgblu, bgalpha; unsigned char fgred, fggrn, fgblu, bgred, bggrn, bgblu, bgalpha;
int error_number = 0; int error_number = 0;
int rectangle_count, this_rectangle; int rectangle_count, this_rectangle;
@ -191,7 +189,6 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
int draw_background = 1; int draw_background = 1;
int bold; int bold;
const int upcean = is_upcean(symbol->symbology); const int upcean = is_upcean(symbol->symbology);
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT;
struct zint_vector_rect *rect; struct zint_vector_rect *rect;
struct zint_vector_circle *circ; struct zint_vector_circle *circ;
@ -703,66 +700,56 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
emr_header.emf_header.records = recordcount; emr_header.emf_header.records = recordcount;
/* Send EMF data to file */ /* Send EMF data to file */
if (output_to_stdout) { if (!fm_open(fmp, symbol, "wb")) {
#ifdef _MSC_VER sprintf(symbol->errtxt, "640: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
sprintf(symbol->errtxt, "642: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_ACCESS; return ZINT_ERROR_FILE_ACCESS;
} }
#endif
emf_file = stdout;
} else {
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;
}
}
fwrite(&emr_header, sizeof(emr_header_t), 1, emf_file); fm_write(&emr_header, sizeof(emr_header_t), 1, fmp);
fwrite(&emr_mapmode, sizeof(emr_mapmode_t), 1, emf_file); fm_write(&emr_mapmode, sizeof(emr_mapmode_t), 1, fmp);
if (rotate_angle) { if (rotate_angle) {
fwrite(&emr_setworldtransform, sizeof(emr_setworldtransform_t), 1, emf_file); fm_write(&emr_setworldtransform, sizeof(emr_setworldtransform_t), 1, fmp);
} }
fwrite(&emr_createbrushindirect_bg, sizeof(emr_createbrushindirect_t), 1, emf_file); fm_write(&emr_createbrushindirect_bg, sizeof(emr_createbrushindirect_t), 1, fmp);
if (symbol->symbology == BARCODE_ULTRA) { if (symbol->symbology == BARCODE_ULTRA) {
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
if (rectangle_bycolour[i]) { if (rectangle_bycolour[i]) {
fwrite(&emr_createbrushindirect_colour[i], sizeof(emr_createbrushindirect_t), 1, emf_file); fm_write(&emr_createbrushindirect_colour[i], sizeof(emr_createbrushindirect_t), 1, fmp);
} }
} }
} else { } else {
fwrite(&emr_createbrushindirect_fg, sizeof(emr_createbrushindirect_t), 1, emf_file); fm_write(&emr_createbrushindirect_fg, sizeof(emr_createbrushindirect_t), 1, fmp);
} }
fwrite(&emr_createpen, sizeof(emr_createpen_t), 1, emf_file); fm_write(&emr_createpen, sizeof(emr_createpen_t), 1, fmp);
if (symbol->vector->strings) { if (symbol->vector->strings) {
fwrite(&emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw_t), 1, emf_file); fm_write(&emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw_t), 1, fmp);
if (fsize2) { if (fsize2) {
fwrite(&emr_extcreatefontindirectw2, sizeof(emr_extcreatefontindirectw_t), 1, emf_file); fm_write(&emr_extcreatefontindirectw2, sizeof(emr_extcreatefontindirectw_t), 1, fmp);
} }
} }
fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file); fm_write(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, fmp);
fwrite(&emr_selectobject_pen, sizeof(emr_selectobject_t), 1, emf_file); fm_write(&emr_selectobject_pen, sizeof(emr_selectobject_t), 1, fmp);
if (draw_background) { if (draw_background) {
fwrite(&background, sizeof(emr_rectangle_t), 1, emf_file); fm_write(&background, sizeof(emr_rectangle_t), 1, fmp);
} }
if (symbol->symbology == BARCODE_ULTRA) { if (symbol->symbology == BARCODE_ULTRA) {
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
if (rectangle_bycolour[i]) { if (rectangle_bycolour[i]) {
fwrite(&emr_selectobject_colour[i], sizeof(emr_selectobject_t), 1, emf_file); fm_write(&emr_selectobject_colour[i], sizeof(emr_selectobject_t), 1, fmp);
rect = symbol->vector->rectangles; rect = symbol->vector->rectangles;
this_rectangle = 0; this_rectangle = 0;
while (rect) { while (rect) {
if ((i == 0 && rect->colour == -1) || rect->colour == i) { if ((i == 0 && rect->colour == -1) || rect->colour == i) {
fwrite(&rectangle[this_rectangle], sizeof(emr_rectangle_t), 1, emf_file); fm_write(&rectangle[this_rectangle], sizeof(emr_rectangle_t), 1, fmp);
} }
this_rectangle++; this_rectangle++;
rect = rect->next; rect = rect->next;
@ -770,42 +757,42 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
} }
} }
} else { } else {
fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file); fm_write(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, fmp);
/* Rectangles */ /* Rectangles */
for (i = 0; i < rectangle_count; i++) { for (i = 0; i < rectangle_count; i++) {
fwrite(&rectangle[i], sizeof(emr_rectangle_t), 1, emf_file); fm_write(&rectangle[i], sizeof(emr_rectangle_t), 1, fmp);
} }
} }
/* Hexagons */ /* Hexagons */
for (i = 0; i < hexagon_count; i++) { for (i = 0; i < hexagon_count; i++) {
fwrite(&hexagon[i], sizeof(emr_polygon_t), 1, emf_file); fm_write(&hexagon[i], sizeof(emr_polygon_t), 1, fmp);
} }
/* Circles */ /* Circles */
if (symbol->symbology == BARCODE_MAXICODE) { if (symbol->symbology == BARCODE_MAXICODE) {
/* Bullseye needed */ /* Bullseye needed */
for (i = 0; i < circle_count; i++) { for (i = 0; i < circle_count; i++) {
fwrite(&circle[i], sizeof(emr_ellipse_t), 1, emf_file); fm_write(&circle[i], sizeof(emr_ellipse_t), 1, fmp);
if (i < circle_count - 1) { if (i < circle_count - 1) {
if (i % 2) { if (i % 2) {
fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file); fm_write(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, fmp);
} else { } else {
fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file); fm_write(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, fmp);
} }
} }
} }
} else { } else {
for (i = 0; i < circle_count; i++) { for (i = 0; i < circle_count; i++) {
fwrite(&circle[i], sizeof(emr_ellipse_t), 1, emf_file); fm_write(&circle[i], sizeof(emr_ellipse_t), 1, fmp);
} }
} }
/* Text */ /* Text */
if (string_count > 0) { if (string_count > 0) {
fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file); fm_write(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, fmp);
fwrite(&emr_settextcolor, sizeof(emr_settextcolor_t), 1, emf_file); fm_write(&emr_settextcolor, sizeof(emr_settextcolor_t), 1, fmp);
} }
current_fsize = fsize; current_fsize = fsize;
@ -813,44 +800,35 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
for (i = 0; i < string_count; i++) { for (i = 0; i < string_count; i++) {
if (text_fsizes[i] != current_fsize) { if (text_fsizes[i] != current_fsize) {
current_fsize = text_fsizes[i]; current_fsize = text_fsizes[i];
fwrite(&emr_selectobject_font2, sizeof(emr_selectobject_t), 1, emf_file); fm_write(&emr_selectobject_font2, sizeof(emr_selectobject_t), 1, fmp);
} }
if (text_haligns[i] != current_halign) { if (text_haligns[i] != current_halign) {
current_halign = text_haligns[i]; current_halign = text_haligns[i];
if (current_halign == 0) { if (current_halign == 0) {
fwrite(&emr_settextalign_centre, sizeof(emr_settextalign_t), 1, emf_file); fm_write(&emr_settextalign_centre, sizeof(emr_settextalign_t), 1, fmp);
} else if (current_halign == 1) { } else if (current_halign == 1) {
fwrite(&emr_settextalign_left, sizeof(emr_settextalign_t), 1, emf_file); fm_write(&emr_settextalign_left, sizeof(emr_settextalign_t), 1, fmp);
} else { } else {
fwrite(&emr_settextalign_right, sizeof(emr_settextalign_t), 1, emf_file); fm_write(&emr_settextalign_right, sizeof(emr_settextalign_t), 1, fmp);
} }
} }
fwrite(&text[i], sizeof(emr_exttextoutw_t), 1, emf_file); fm_write(&text[i], sizeof(emr_exttextoutw_t), 1, fmp);
fwrite(this_string[i], emf_bump_up(text[i].w_emr_text.chars), 1, emf_file); fm_write(this_string[i], emf_bump_up(text[i].w_emr_text.chars), 1, fmp);
free(this_string[i]); free(this_string[i]);
} }
fwrite(&emr_eof, sizeof(emr_eof_t), 1, emf_file); fm_write(&emr_eof, sizeof(emr_eof_t), 1, fmp);
if (ferror(emf_file)) { if (fm_error(fmp)) {
sprintf(symbol->errtxt, "644: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "644: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(emf_file);
}
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (output_to_stdout) { if (!fm_close(fmp, symbol)) {
if (fflush(emf_file) != 0) { sprintf(symbol->errtxt, "941: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
sprintf(symbol->errtxt, "940: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
} else {
if (fclose(emf_file) != 0) {
sprintf(symbol->errtxt, "941: Failure on closing output file (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE;
}
}
return error_number; return error_number;
} }

464
backend/filemem.c Normal file
View File

@ -0,0 +1,464 @@
/* filemem.c - write to file/memory abstraction */
/*
libzint - the open source barcode library
Copyright (C) 2023 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* SPDX-License-Identifier: BSD-3-Clause */
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#endif
#include "filemem.h"
#include "output.h"
#define FM_PAGE_SIZE 0x8000 /* 32k */
#ifndef EOVERFLOW
#define EOVERFLOW EINVAL
#endif
#if defined(_MSC_VER) && _MSC_VER < 1800 /* `va_copy()` not before MSVC 2013 (C++ 12.0) */
# define va_copy(dest, src) (dest = src)
#else
# if defined(ZINT_IS_C89) && !defined(va_copy)
# ifdef __GNUC__
# define va_copy __va_copy /* Available with clang as well */
# else
# define va_copy(dest, src) (dest = src) /* Will fail if array (need `*dest = *src`) or something else */
# endif
# endif
#endif
/* Helper to set `err` only if not already set, returning 0 always for convenience */
static int fm_seterr(struct filemem *restrict const fmp, const int err) {
if (fmp->err == 0) {
fmp->err = err;
}
return 0;
}
/* Helper to set position, syncing end marker */
static void fm_setpos(struct filemem *restrict const fmp, const size_t pos) {
assert(pos <= fmp->memsize);
fmp->mempos = pos;
if (fmp->mempos > fmp->memend) {
fmp->memend = fmp->mempos;
}
}
/* Helper to clear memory buffer and associates */
static void fm_clear_mem(struct filemem *restrict const fmp) {
if (fmp->mem) {
free(fmp->mem);
fmp->mem = NULL;
}
fmp->memsize = fmp->mempos = fmp->memend = 0;
#ifdef FM_NO_VSNPRINTF
if (fmp->fp_null) {
(void) fclose(fmp->fp_null);
fmp->fp_null = NULL;
}
#endif
}
/* `fopen()` if file, setup memory buffer if BARCODE_MEMORY_FILE, returning 1 on success, 0 on failure */
INTERNAL int fm_open(struct filemem *restrict const fmp, struct zint_symbol *symbol, const char *mode) {
assert(fmp && symbol && mode);
fmp->fp = NULL;
fmp->mem = NULL;
fmp->memsize = fmp->mempos = fmp->memend = 0;
fmp->flags = symbol->output_options & (BARCODE_STDOUT | BARCODE_MEMORY_FILE);
fmp->err = 0;
#ifdef FM_NO_VSNPRINTF
fmp->fp_null = NULL;
#endif
if (fmp->flags & BARCODE_MEMORY_FILE) {
if (!(fmp->mem = (unsigned char *) malloc(FM_PAGE_SIZE))) {
return fm_seterr(fmp, ENOMEM);
}
fmp->memsize = FM_PAGE_SIZE;
if (symbol->memfile) {
free(symbol->memfile);
symbol->memfile = NULL;
}
symbol->memfile_size = 0;
return 1;
}
if (fmp->flags & BARCODE_STDOUT) {
#ifdef _MSC_VER
if (strchr(mode, 'b') != NULL && _setmode(_fileno(stdout), _O_BINARY) == -1) {
return fm_seterr(fmp, errno);
}
#endif
fmp->fp = stdout;
return 1;
}
if (!(fmp->fp = out_fopen(symbol->outfile, mode))) {
return fm_seterr(fmp, errno);
}
return 1;
}
/* Expand memory buffer, returning 1 on success, 0 on failure */
static int fm_mem_expand(struct filemem *restrict const fmp, const size_t size) {
unsigned char *new_mem;
size_t new_size;
assert(fmp);
if (!fmp->mem) {
return fm_seterr(fmp, EINVAL);
}
if (size == 0) {
return 1;
}
if (fmp->mempos + size < fmp->memsize) { /* Fits? */
if (fmp->mempos + size <= fmp->mempos) { /* Check for overflow */
fm_clear_mem(fmp);
return fm_seterr(fmp, EOVERFLOW);
}
return 1;
}
new_size = fmp->memsize + (size < FM_PAGE_SIZE ? FM_PAGE_SIZE : size);
if (new_size <= fmp->memsize) { /* Check for overflow */
fm_clear_mem(fmp);
return fm_seterr(fmp, EOVERFLOW);
}
/* Protect against very large files & (Linux) OOM killer - cf `raster_malloc()` in "raster.c" */
if (new_size > 0x40000000 /*1GB*/ || !(new_mem = (unsigned char *) realloc(fmp->mem, new_size))) {
fm_clear_mem(fmp);
return fm_seterr(fmp, new_size > 0x40000000 ? EINVAL : ENOMEM);
}
fmp->mem = new_mem;
fmp->memsize = new_size;
return 1;
}
/* `fwrite()` to file or memory, returning 1 on success, 0 on failure */
INTERNAL int fm_write(const void *restrict ptr, const size_t size, const size_t nitems,
struct filemem *restrict const fmp) {
assert(fmp && ptr);
if (fmp->err) {
return 0;
}
if (size == 0 || nitems == 0) {
return 1;
}
if (fmp->flags & BARCODE_MEMORY_FILE) {
const size_t tot_size = size * nitems;
if (tot_size / size != nitems) {
return fm_seterr(fmp, EOVERFLOW);
}
if (!fm_mem_expand(fmp, tot_size)) {
return 0;
}
memcpy(fmp->mem + fmp->mempos, ptr, tot_size);
fm_setpos(fmp, fmp->mempos + tot_size);
return 1;
}
if (fwrite(ptr, size, nitems, fmp->fp) == 0) {
return fm_seterr(fmp, errno);
}
return 1;
}
/* `fputc()` to file or memory, returning 1 on success, 0 on failure */
INTERNAL int fm_putc(const int ch, struct filemem *restrict const fmp) {
assert(fmp);
if (fmp->err) {
return 0;
}
if (fmp->flags & BARCODE_MEMORY_FILE) {
if (!fm_mem_expand(fmp, 1)) {
return 0;
}
fmp->mem[fmp->mempos] = (unsigned char) ch;
fm_setpos(fmp, fmp->mempos + 1);
return 1;
}
if (fputc(ch, fmp->fp) == EOF) {
return fm_seterr(fmp, errno);
}
return 1;
}
/* `fputs()` to file or memory, returning 1 on success, 0 on failure */
INTERNAL int fm_puts(const char *str, struct filemem *restrict const fmp) {
assert(fmp);
if (fmp->err) {
return 0;
}
if (fmp->flags & BARCODE_MEMORY_FILE) {
const size_t len = strlen(str);
if (!fm_mem_expand(fmp, len)) {
return 0;
}
memcpy(fmp->mem + fmp->mempos, str, len);
fm_setpos(fmp, fmp->mempos + len);
return 1;
}
if (fputs(str, fmp->fp) == EOF) {
return fm_seterr(fmp, errno);
}
return 1;
}
#ifdef FM_NO_VSNPRINTF
# ifdef _WIN32
# define DEV_NULL "NUL"
# else
# define DEV_NULL "/dev/null"
# endif
#endif
/* Helper to `printf()` into mem buffer */
static int fm_vprintf(struct filemem *restrict const fmp, const char *fmt, va_list ap) {
va_list cpy;
int size, check;
/* Adapted from https://stackoverflow.com/a/52558247/664741 */
#ifdef FM_NO_VSNPRINTF
if (!fmp->fp_null && !(fmp->fp_null = fopen(DEV_NULL, "wb"))) {
return fm_seterr(fmp, errno);
}
#endif
va_copy(cpy, ap);
/* The clang-tidy warning is a bug https://github.com/llvm/llvm-project/issues/40656 */
#ifdef FM_NO_VSNPRINTF
size = vfprintf(fmp->fp_null, fmt, cpy); /* NOLINT(clang-analyzer-valist.Uninitialized) */
#else
size = vsnprintf(NULL, 0, fmt, cpy); /* NOLINT(clang-analyzer-valist.Uninitialized) */
#endif
va_end(cpy);
if (size < 0) {
return fm_seterr(fmp, errno);
}
if (!fm_mem_expand(fmp, size + 1)) {
return 0;
}
#ifdef FM_NO_VSNPRINTF
/* NOLINTNEXTLINE(clang-analyzer-valist.Uninitialized) - see above */
check = vsprintf((char *) fmp->mem + fmp->mempos, fmt, ap);
#else
/* NOLINTNEXTLINE(clang-analyzer-valist.Uninitialized) - see above */
check = vsnprintf((char *) fmp->mem + fmp->mempos, size + 1, fmt, ap);
#endif
(void)check;
assert(check == size);
fm_setpos(fmp, fmp->mempos + size);
return 1;
}
/* `fprintf()` to memory or file, returning 1 on success, 0 on failure */
INTERNAL int fm_printf(struct filemem *restrict const fmp, const char *fmt, ...) {
va_list ap;
int ret;
assert(fmp && fmt);
if (fmp->err) {
return 0;
}
if (fmp->flags & BARCODE_MEMORY_FILE) {
va_start(ap, fmt);
ret = fm_vprintf(fmp, fmt, ap);
va_end(ap);
return ret;
}
va_start(ap, fmt);
ret = vfprintf(fmp->fp, fmt, ap) >= 0; /* NOLINT(clang-analyzer-valist.Uninitialized) - see above */
if (!ret) {
(void) fm_seterr(fmp, errno);
}
va_end(ap);
return ret != 0;
}
/* Output float without trailing zeroes to `fmp` with decimal pts `dp` (precision), returning 1 on success, 0 on
failure */
INTERNAL int fm_putsf(const char *prefix, const int dp, const float arg, struct filemem *restrict const fmp) {
int i, end;
char buf[256]; /* Assuming `dp` reasonable */
const int len = sprintf(buf, "%.*f", dp, arg);
assert(fmp);
if (fmp->err) {
return 0;
}
if (prefix && *prefix) {
if (!fm_puts(prefix, fmp)) {
return 0;
}
}
/* 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;
}
}
return fm_puts(buf, fmp);
}
/* `fclose()` if file, set `symbol->memfile` & `symbol->memfile_size` if memory, returning 1 on success, 0 on
failure */
INTERNAL int fm_close(struct filemem *restrict const fmp, struct zint_symbol *symbol) {
assert(fmp && symbol);
if (fmp->flags & BARCODE_MEMORY_FILE) {
if (fmp->err || !fmp->mem) {
fm_clear_mem(fmp);
return fm_seterr(fmp, EINVAL);
}
symbol->memfile_size = (int) fmp->mempos;
if ((size_t) symbol->memfile_size != fmp->mempos) {
fm_clear_mem(fmp);
symbol->memfile_size = 0;
return fm_seterr(fmp, EINVAL);
}
symbol->memfile = fmp->mem;
fmp->mem = NULL; /* Now belongs to `symbol` */
fm_clear_mem(fmp);
return 1;
}
if (fmp->err || !fmp->fp) {
if (!(fmp->flags & BARCODE_STDOUT) && fmp->fp) {
(void) fclose(fmp->fp);
}
return fm_seterr(fmp, EINVAL);
}
if (fmp->flags & BARCODE_STDOUT) {
if (fflush(fmp->fp) != 0) {
fmp->fp = NULL;
return fm_seterr(fmp, errno);
}
} else {
if (fclose(fmp->fp) != 0) {
fmp->fp = NULL;
return fm_seterr(fmp, errno);
}
}
fmp->fp = NULL;
return 1;
}
/* `fseek()` to file/memory offset, returning 1 if successful, 0 on failure */
INTERNAL int fm_seek(struct filemem *restrict const fmp, const long offset, const int whence) {
assert(fmp);
if (fmp->err) {
return 0;
}
if (fmp->flags & BARCODE_MEMORY_FILE) {
const size_t start = whence == SEEK_SET ? 0 : whence == SEEK_CUR ? fmp->mempos : fmp->memend;
const size_t new_pos = start + offset;
if ((offset > 0 && new_pos <= start) || (offset < 0 && new_pos >= start)) { /* Check for over/underflow */
return fm_seterr(fmp, EINVAL);
}
if (!fm_mem_expand(fmp, new_pos)) {
return 0;
}
fm_setpos(fmp, new_pos);
return 1;
}
if (fseek(fmp->fp, offset, whence) != 0) {
return fm_seterr(fmp, errno);
}
return 1;
}
/* `ftell()` returns current file/memory offset if successful, -1 on failure */
INTERNAL long fm_tell(struct filemem *restrict const fmp) {
long ret;
assert(fmp);
if (fmp->err) {
return -1;
}
if (fmp->flags & BARCODE_MEMORY_FILE) {
if (!fmp->mem) {
(void) fm_seterr(fmp, ENOMEM);
return -1;
}
return (long) fmp->mempos;
}
ret = ftell(fmp->fp);
/* On many Linux distros `ftell()` returns LONG_MAX not -1 on error */
if (ret < 0 || ret == LONG_MAX) {
(void) fm_seterr(fmp, errno);
return -1;
}
return ret;
}
/* Return `err`, which uses `errno` values */
INTERNAL int fm_error(struct filemem *restrict const fmp) {
assert(fmp);
return fmp->err;
}
/* `fflush()` if file, no-op (apart from error checking) if memory, returning 1 on success, 0 on failure
NOTE: don't use, included only for libpng compatibility */
INTERNAL int fm_flush(struct filemem *restrict const fmp) {
assert(fmp);
if (fmp->err) {
return 0;
}
if (fmp->flags & BARCODE_MEMORY_FILE) {
if (!fmp->mem) {
return fm_seterr(fmp, EINVAL);
}
return 1;
}
if (fflush(fmp->fp) == EOF) {
return fm_seterr(fmp, errno);
}
return 1;
}
/* vim: set ts=4 sw=4 et : */

95
backend/filemem.h Normal file
View File

@ -0,0 +1,95 @@
/* filemem.h - write to file/memory abstraction */
/*
libzint - the open source barcode library
Copyright (C) 2023 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* SPDX-License-Identifier: BSD-3-Clause */
#ifndef Z_FILEMEM_H
#define Z_FILEMEM_H
#include <stdio.h>
#include "common.h"
/* Whether `vsnprintf()` available */
#if (defined(_MSC_VER) && _MSC_VER < 1900) || defined(ZINT_IS_C89) /* Pre-MSVC 2015 (C++ 14.0) or C89 */
#define FM_NO_VSNPRINTF
#endif
struct filemem {
FILE *fp;
unsigned char *mem;
size_t memsize; /* Size of `mem` buffer (capacity) */
size_t mempos; /* Current position */
size_t memend; /* For use by `fm_seek()`, points to highest `mempos` reached */
int flags; /* BARCODE_MEMORY_FILE or BARCODE_STDOUT */
int err; /* `errno` values, reset only on `fm_open()` */
#ifdef FM_NO_VSNPRINTF
FILE *fp_null; /* Only used for BARCODE_MEMORY_FILE */
#endif
};
/* `fopen()` if file, setup memory buffer if BARCODE_MEMORY_FILE, returning 1 on success, 0 on failure */
INTERNAL int fm_open(struct filemem *restrict const fmp, struct zint_symbol *symbol, const char *mode);
/* `fwrite()` to file or memory, returning 1 on success, 0 on failure */
INTERNAL int fm_write(const void *restrict ptr, const size_t size, const size_t nitems,
struct filemem *restrict const fmp);
/* `fputc()` to file or memory, returning 1 on success, 0 on failure */
INTERNAL int fm_putc(const int ch, struct filemem *restrict const fmp);
/* `fputs()` to file or memory, returning 1 on success, 0 on failure */
INTERNAL int fm_puts(const char *str, struct filemem *restrict const fmp);
/* `fprintf()` to memory or file, returning 1 on success, 0 on failure */
INTERNAL int fm_printf(struct filemem *restrict const fmp, const char *format, ...);
/* Output float without trailing zeroes to `fmp` with decimal pts `dp` (precision), returning 1 on success, 0 on
failure */
INTERNAL int fm_putsf(const char *prefix, const int dp, const float arg, struct filemem *restrict const fmp);
/* `fclose()` if file, set `symbol->memfile` & `symbol->memfile_size` if memory, returning 1 on success, 0 on
failure */
INTERNAL int fm_close(struct filemem *restrict const fmp, struct zint_symbol *symbol);
/* `fseek()` to file/memory offset, returning 1 on success, 0 on failure */
INTERNAL int fm_seek(struct filemem *restrict const fmp, const long offset, const int whence);
/* `ftell()` returns current file/memory offset if successful, -1 on failure */
INTERNAL long fm_tell(struct filemem *restrict const fmp);
/* Return `err`, which uses `errno` values */
INTERNAL int fm_error(struct filemem *restrict const fmp);
/* `fflush()` if file, no-op if memory, returning 1 on success, 0 on failure
NOTE: don't use, included only for libpng compatibility */
INTERNAL int fm_flush(struct filemem *restrict const fmp);
/* vim: set ts=4 sw=4 et : */
#endif /* Z_FILEMEM_H */

View File

@ -32,18 +32,15 @@
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#endif
#include "common.h" #include "common.h"
#include "filemem.h"
#include "output.h" #include "output.h"
/* Limit initial LZW buffer size to this in expectation that compressed data will fit for typical scalings */ /* Limit initial LZW buffer size to this in expectation that compressed data will fit for typical scalings */
#define GIF_LZW_PAGE_SIZE 0x100000 /* Megabyte */ #define GIF_LZW_PAGE_SIZE 0x100000 /* Megabyte */
typedef struct s_statestruct { typedef struct s_statestruct {
FILE *file; struct filemem *fmp;
unsigned char *pOut; unsigned char *pOut;
const unsigned char *pIn; const unsigned char *pIn;
const unsigned char *pInEnd; const unsigned char *pInEnd;
@ -65,7 +62,7 @@ static void BufferNextByte(statestruct *pState) {
(pState->OutPosCur)++; (pState->OutPosCur)++;
if (pState->fOutPaged && pState->OutPosCur + 2 >= pState->OutLength) { if (pState->fOutPaged && pState->OutPosCur + 2 >= pState->OutLength) {
/* Keep last 256 bytes so `OutByteCountPos` within range */ /* Keep last 256 bytes so `OutByteCountPos` within range */
fwrite(pState->pOut, 1, pState->OutPosCur - 256, pState->file); fm_write(pState->pOut, 1, pState->OutPosCur - 256, pState->fmp);
memmove(pState->pOut, pState->pOut + pState->OutPosCur - 256, 256); memmove(pState->pOut, pState->pOut + pState->OutPosCur - 256, 256);
pState->OutByteCountPos -= pState->OutPosCur - 256; pState->OutByteCountPos -= pState->OutPosCur - 256;
pState->OutPosCur = 256; pState->OutPosCur = 256;
@ -241,6 +238,7 @@ static int gif_lzw(statestruct *pState, int paletteBitSize) {
* Called function to save in gif format * Called function to save in gif format
*/ */
INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) { INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) {
struct filemem fm;
unsigned char outbuf[10]; unsigned char outbuf[10];
unsigned short usTemp; unsigned short usTemp;
unsigned char paletteRGB[10][3]; unsigned char paletteRGB[10][3];
@ -250,7 +248,6 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
statestruct State; statestruct State;
int transparent_index; int transparent_index;
int bgindex = -1, fgindex = -1; int bgindex = -1, fgindex = -1;
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT;
static const unsigned char RGBUnused[3] = {0,0,0}; static const unsigned char RGBUnused[3] = {0,0,0};
unsigned char RGBfg[3]; unsigned char RGBfg[3];
@ -277,23 +274,15 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
State.fmp = &fm;
/* Open output file in binary mode */ /* Open output file in binary mode */
if (output_to_stdout) { if (!fm_open(State.fmp, symbol, "wb")) {
#ifdef _MSC_VER sprintf(symbol->errtxt, "611: Could not open output file (%d: %.30s)", State.fmp->err,
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) { strerror(State.fmp->err));
sprintf(symbol->errtxt, "610: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
free(State.pOut); free(State.pOut);
return ZINT_ERROR_FILE_ACCESS; return ZINT_ERROR_FILE_ACCESS;
} }
#endif
State.file = stdout;
} else {
if (!(State.file = out_fopen(symbol->outfile, "wb"))) {
sprintf(symbol->errtxt, "611: Could not open output file (%d: %.30s)", errno, strerror(errno));
free(State.pOut);
return ZINT_ERROR_FILE_ACCESS;
}
}
/* /*
* Build a table of the used palette items. * Build a table of the used palette items.
@ -310,7 +299,6 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
* 'K': black * 'K': black
* '0' and '1' may be identical to one of the other values * '0' and '1' may be identical to one of the other values
*/ */
paletteCount = 0;
memset(State.map, 0, sizeof(State.map)); memset(State.map, 0, sizeof(State.map));
if (symbol->symbology == BARCODE_ULTRA) { if (symbol->symbology == BARCODE_ULTRA) {
static const unsigned char ultra_chars[8] = { 'W', 'C', 'B', 'M', 'R', 'Y', 'G', 'K' }; static const unsigned char ultra_chars[8] = { 'W', 'C', 'B', 'M', 'R', 'Y', 'G', 'K' };
@ -375,7 +363,7 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
if (transparent_index != -1) if (transparent_index != -1)
outbuf[4] = '9'; outbuf[4] = '9';
fwrite(outbuf, 1, 6, State.file); fm_write(outbuf, 1, 6, State.fmp);
/* Screen Descriptor (7) */ /* Screen Descriptor (7) */
/* Screen Width */ /* Screen Width */
usTemp = (unsigned short) symbol->bitmap_width; usTemp = (unsigned short) symbol->bitmap_width;
@ -402,12 +390,12 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
outbuf[5] = bgindex == -1 ? 0 : bgindex; outbuf[5] = bgindex == -1 ? 0 : bgindex;
/* Byte 7 must be 0x00 */ /* Byte 7 must be 0x00 */
outbuf[6] = 0x00; outbuf[6] = 0x00;
fwrite(outbuf, 1, 7, State.file); fm_write(outbuf, 1, 7, State.fmp);
/* Global Color Table (paletteSize*3) */ /* Global Color Table (paletteSize*3) */
fwrite(paletteRGB, 1, 3*paletteCount, State.file); fm_write(paletteRGB, 1, 3*paletteCount, State.fmp);
/* add unused palette items to fill palette size */ /* add unused palette items to fill palette size */
for (i = paletteCount; i < paletteSize; i++) { for (i = paletteCount; i < paletteSize; i++) {
fwrite(RGBUnused, 1, 3, State.file); fm_write(RGBUnused, 1, 3, State.fmp);
} }
/* Graphic control extension (8) */ /* Graphic control extension (8) */
@ -435,7 +423,7 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
outbuf[6] = (unsigned char) transparent_index; outbuf[6] = (unsigned char) transparent_index;
/* Block Terminator */ /* Block Terminator */
outbuf[7] = 0; outbuf[7] = 0;
fwrite(outbuf, 1, 8, State.file); fm_write(outbuf, 1, 8, State.fmp);
} }
/* Image Descriptor */ /* Image Descriptor */
/* Image separator character = ',' */ /* Image separator character = ',' */
@ -458,42 +446,33 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
* There is no local color table if its most significant bit is reset. * There is no local color table if its most significant bit is reset.
*/ */
outbuf[9] = 0x00; outbuf[9] = 0x00;
fwrite(outbuf, 1, 10, State.file); fm_write(outbuf, 1, 10, State.fmp);
/* call lzw encoding */ /* call lzw encoding */
if (!gif_lzw(&State, paletteBitSize)) { if (!gif_lzw(&State, paletteBitSize)) {
free(State.pOut); free(State.pOut);
if (!output_to_stdout) { (void) fm_close(State.fmp, symbol);
(void) fclose(State.file);
}
strcpy(symbol->errtxt, "613: Insufficient memory for LZW buffer"); strcpy(symbol->errtxt, "613: Insufficient memory for LZW buffer");
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
fwrite((const char *) State.pOut, 1, State.OutPosCur, State.file); fm_write((const char *) State.pOut, 1, State.OutPosCur, State.fmp);
free(State.pOut); free(State.pOut);
/* GIF terminator */ /* GIF terminator */
fputc('\x3b', State.file); fm_putc('\x3b', State.fmp);
if (ferror(State.file)) { if (fm_error(State.fmp)) {
sprintf(symbol->errtxt, "615: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "615: Incomplete write to output (%d: %.30s)", State.fmp->err,
if (!output_to_stdout) { strerror(State.fmp->err));
(void) fclose(State.file); (void) fm_close(State.fmp, symbol);
}
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (output_to_stdout) { if (!fm_close(State.fmp, symbol)) {
if (fflush(State.file) != 0) { sprintf(symbol->errtxt, "617: Failure on closing output file (%d: %.30s)", State.fmp->err,
sprintf(symbol->errtxt, "616: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); strerror(State.fmp->err));
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
} else {
if (fclose(State.file) != 0) {
sprintf(symbol->errtxt, "617: Failure on closing output file (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE;
}
}
return 0; return 0;
} }

View File

@ -75,6 +75,7 @@ static void set_symbol_defaults(struct zint_symbol *symbol) {
symbol->bitmap = NULL; symbol->bitmap = NULL;
symbol->alphamap = NULL; symbol->alphamap = NULL;
symbol->vector = NULL; symbol->vector = NULL;
symbol->memfile = NULL;
} }
/* Create and initialize a symbol structure */ /* Create and initialize a symbol structure */
@ -115,6 +116,11 @@ void ZBarcode_Clear(struct zint_symbol *symbol) {
} }
symbol->bitmap_width = 0; symbol->bitmap_width = 0;
symbol->bitmap_height = 0; symbol->bitmap_height = 0;
if (symbol->memfile != NULL) {
free(symbol->memfile);
symbol->memfile = NULL;
}
symbol->memfile_size = 0;
/* If there is a rendered version, ensure its memory is released */ /* If there is a rendered version, ensure its memory is released */
vector_free(symbol); vector_free(symbol);
@ -130,6 +136,9 @@ void ZBarcode_Reset(struct zint_symbol *symbol) {
if (symbol->alphamap != NULL) { if (symbol->alphamap != NULL) {
free(symbol->alphamap); free(symbol->alphamap);
} }
if (symbol->memfile != NULL) {
free(symbol->memfile);
}
vector_free(symbol); vector_free(symbol);
memset(symbol, 0, sizeof(*symbol)); memset(symbol, 0, sizeof(*symbol));
@ -144,6 +153,8 @@ void ZBarcode_Delete(struct zint_symbol *symbol) {
free(symbol->bitmap); free(symbol->bitmap);
if (symbol->alphamap != NULL) if (symbol->alphamap != NULL)
free(symbol->alphamap); free(symbol->alphamap);
if (symbol->memfile != NULL)
free(symbol->memfile);
/* If there is a rendered version, ensure its memory is released */ /* If there is a rendered version, ensure its memory is released */
vector_free(symbol); vector_free(symbol);
@ -1556,7 +1567,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename) {
fileLen = ftell(file); fileLen = ftell(file);
/* On many Linux distros ftell() returns LONG_MAX not -1 on error */ /* On many Linux distros `ftell()` returns LONG_MAX not -1 on error */
if (fileLen <= 0 || fileLen == LONG_MAX) { if (fileLen <= 0 || fileLen == LONG_MAX) {
(void) fclose(file); (void) fclose(file);
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "235: Input file empty or unseekable"); return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "235: Input file empty or unseekable");

View File

@ -997,34 +997,4 @@ INTERNAL FILE *out_fopen(const char filename[256], const char *mode) {
return outfile; 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 : */ /* vim: set ts=4 sw=4 et : */

View File

@ -77,9 +77,6 @@ INTERNAL FILE *out_fopen(const char filename[256], const char *mode);
INTERNAL FILE *out_win_fopen(const char *filename, const char *mode); INTERNAL FILE *out_win_fopen(const char *filename, const char *mode);
#endif #endif
/* 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);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@ -33,11 +33,8 @@
#include <errno.h> #include <errno.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#endif
#include "common.h" #include "common.h"
#include "filemem.h"
#include "output.h" #include "output.h"
#include "pcx.h" /* PCX header structure */ #include "pcx.h" /* PCX header structure */
@ -46,11 +43,11 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
unsigned char fgred, fggrn, fgblu, fgalpha, bgred, bggrn, bgblu, bgalpha; unsigned char fgred, fggrn, fgblu, fgalpha, bgred, bggrn, bgblu, bgalpha;
int row, column, i, colour; int row, column, i, colour;
int run_count; int run_count;
FILE *pcx_file; struct filemem fm;
struct filemem *const fmp = &fm;
pcx_header_t header; pcx_header_t header;
unsigned char previous; unsigned char previous;
const unsigned char *pb; const unsigned char *pb;
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT; /* Suppress gcc -fanalyzer warning */
const int bytes_per_line = symbol->bitmap_width + (symbol->bitmap_width & 1); /* Must be even */ const int bytes_per_line = symbol->bitmap_width + (symbol->bitmap_width & 1); /* Must be even */
unsigned char *rle_row = (unsigned char *) z_alloca(bytes_per_line); unsigned char *rle_row = (unsigned char *) z_alloca(bytes_per_line);
@ -88,22 +85,12 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} }
/* Open output file in binary mode */ /* Open output file in binary mode */
if (output_to_stdout) { if (!fm_open(fmp, symbol, "wb")) {
#ifdef _MSC_VER sprintf(symbol->errtxt, "621: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
sprintf(symbol->errtxt, "620: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_ACCESS; return ZINT_ERROR_FILE_ACCESS;
} }
#endif
pcx_file = stdout;
} else {
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;
}
}
fwrite(&header, sizeof(pcx_header_t), 1, pcx_file); fm_write(&header, sizeof(pcx_header_t), 1, fmp);
for (row = 0, pb = pixelbuf; row < symbol->bitmap_height; row++, pb += symbol->bitmap_width) { for (row = 0, pb = pixelbuf; row < symbol->bitmap_height; row++, pb += symbol->bitmap_width) {
for (colour = 0; colour < header.number_of_planes; colour++) { for (colour = 0; colour < header.number_of_planes; colour++) {
@ -147,9 +134,9 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} else { } else {
if (run_count > 1 || (previous & 0xc0) == 0xc0) { if (run_count > 1 || (previous & 0xc0) == 0xc0) {
run_count += 0xc0; run_count += 0xc0;
fputc(run_count, pcx_file); fm_putc(run_count, fmp);
} }
fputc(previous, pcx_file); fm_putc(previous, fmp);
previous = rle_row[column]; previous = rle_row[column];
run_count = 1; run_count = 1;
} }
@ -157,31 +144,22 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
if (run_count > 1 || (previous & 0xc0) == 0xc0) { if (run_count > 1 || (previous & 0xc0) == 0xc0) {
run_count += 0xc0; run_count += 0xc0;
fputc(run_count, pcx_file); fm_putc(run_count, fmp);
} }
fputc(previous, pcx_file); fm_putc(previous, fmp);
} }
} }
if (ferror(pcx_file)) { if (fm_error(fmp)) {
sprintf(symbol->errtxt, "622: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "622: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(pcx_file);
}
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (output_to_stdout) { if (!fm_close(fmp, symbol)) {
if (fflush(pcx_file) != 0) { sprintf(symbol->errtxt, "624: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
sprintf(symbol->errtxt, "623: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
} else {
if (fclose(pcx_file) != 0) {
sprintf(symbol->errtxt, "624: Failure on closing output file (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE;
}
}
return 0; return 0;
} }

View File

@ -35,16 +35,15 @@
#include <errno.h> #include <errno.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#ifdef _MSC_VER
#include <fcntl.h>
#include <io.h>
#endif
#include <png.h> #include <png.h>
#include <zlib.h> #include <zlib.h>
#include <setjmp.h> #include <setjmp.h>
#include "common.h" #include "common.h"
#include "filemem.h"
#include "output.h" #include "output.h"
/* Note using "wpng_" prefix not "png_" (except for `png_pixel_plot()`) to avoid clashing with libpng */
/* Note if change this need to change "backend/tests/test_png.c" definition also */ /* Note if change this need to change "backend/tests/test_png.c" definition also */
struct wpng_error_type { struct wpng_error_type {
struct zint_symbol *symbol; struct zint_symbol *symbol;
@ -72,8 +71,20 @@ INTERNAL void wpng_error_handler_test(png_structp png_ptr, png_const_charp msg)
} }
#endif #endif
/* libpng write callback */
static void wpng_write(png_structp png_ptr, png_bytep ptr, size_t size) {
struct filemem *fmp = (struct filemem *) png_get_io_ptr(png_ptr);
(void) fm_write(ptr, 1, size, fmp);
}
/* libpng flush callback */
static void wpng_flush(png_structp png_ptr) {
struct filemem *fmp = (struct filemem *) png_get_io_ptr(png_ptr);
(void) fm_flush(fmp);
}
/* Guestimate best compression strategy */ /* Guestimate best compression strategy */
static int guess_compression_strategy(struct zint_symbol *symbol, const unsigned char *pixelbuf) { static int wpng_guess_compression_strategy(struct zint_symbol *symbol, const unsigned char *pixelbuf) {
(void)pixelbuf; (void)pixelbuf;
/* TODO: Do properly */ /* TODO: Do properly */
@ -94,7 +105,8 @@ static int guess_compression_strategy(struct zint_symbol *symbol, const unsigned
INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf) { INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf) {
struct wpng_error_type wpng_error; struct wpng_error_type wpng_error;
FILE *outfile; struct filemem fm;
struct filemem *const fmp = &fm;
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
int i; int i;
@ -105,11 +117,10 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
png_color palette[32]; png_color palette[32];
int num_palette; int num_palette;
unsigned char trans_alpha[32]; unsigned char trans_alpha[32];
int num_trans = 0; int num_trans; /* Note initialize below to avoid gcc -Wclobbered warning due to `longjmp()` */
int bit_depth; int bit_depth;
int compression_strategy; int compression_strategy;
const unsigned char *pb; const unsigned char *pb;
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT;
unsigned char *outdata = (unsigned char *) z_alloca(symbol->bitmap_width); unsigned char *outdata = (unsigned char *) z_alloca(symbol->bitmap_width);
wpng_error.symbol = symbol; wpng_error.symbol = symbol;
@ -117,6 +128,7 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
(void) out_colour_get_rgb(symbol->fgcolour, &fg.red, &fg.green, &fg.blue, &fg_alpha); (void) out_colour_get_rgb(symbol->fgcolour, &fg.red, &fg.green, &fg.blue, &fg_alpha);
(void) out_colour_get_rgb(symbol->bgcolour, &bg.red, &bg.green, &bg.blue, &bg_alpha); (void) out_colour_get_rgb(symbol->bgcolour, &bg.red, &bg.green, &bg.blue, &bg_alpha);
num_trans = 0;
if (symbol->symbology == BARCODE_ULTRA) { if (symbol->symbology == BARCODE_ULTRA) {
static const unsigned char ultra_chars[8] = { 'W', 'C', 'B', 'M', 'R', 'Y', 'G', 'K' }; static const unsigned char ultra_chars[8] = { 'W', 'C', 'B', 'M', 'R', 'Y', 'G', 'K' };
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
@ -199,28 +211,16 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} }
/* Open output file in binary mode */ /* Open output file in binary mode */
if (output_to_stdout) { if (!fm_open(fmp, symbol, "wb")) {
#ifdef _MSC_VER sprintf(symbol->errtxt, "632: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
sprintf(symbol->errtxt, "631: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_ACCESS; return ZINT_ERROR_FILE_ACCESS;
} }
#endif
outfile = stdout;
} else {
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;
}
}
/* Set up error handling routine as proc() above */ /* Set up error handling routine as proc() above */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &wpng_error, wpng_error_handler, NULL); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &wpng_error, wpng_error_handler, NULL);
if (!png_ptr) { if (!png_ptr) {
strcpy(symbol->errtxt, "633: Insufficient memory for PNG write structure buffer"); strcpy(symbol->errtxt, "633: Insufficient memory for PNG write structure buffer");
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(outfile);
}
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
@ -228,29 +228,25 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
if (!info_ptr) { if (!info_ptr) {
png_destroy_write_struct(&png_ptr, NULL); png_destroy_write_struct(&png_ptr, NULL);
strcpy(symbol->errtxt, "634: Insufficient memory for PNG info structure buffer"); strcpy(symbol->errtxt, "634: Insufficient memory for PNG info structure buffer");
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(outfile);
}
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
/* catch jumping here */ /* catch jumping here */
if (setjmp(wpng_error.jmpbuf)) { if (setjmp(wpng_error.jmpbuf)) {
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(outfile);
}
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
/* open output file with libpng */ /* Set our output functions */
png_init_io(png_ptr, outfile); png_set_write_fn(png_ptr, fmp, wpng_write, wpng_flush);
/* set compression */ /* set compression */
png_set_compression_level(png_ptr, 9); png_set_compression_level(png_ptr, 9);
/* Compression strategy can make a difference */ /* Compression strategy can make a difference */
compression_strategy = guess_compression_strategy(symbol, pixelbuf); compression_strategy = wpng_guess_compression_strategy(symbol, pixelbuf);
if (compression_strategy != Z_DEFAULT_STRATEGY) { if (compression_strategy != Z_DEFAULT_STRATEGY) {
png_set_compression_strategy(png_ptr, compression_strategy); png_set_compression_strategy(png_ptr, compression_strategy);
} }
@ -317,27 +313,23 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
/* make sure we have disengaged */ /* make sure we have disengaged */
png_destroy_write_struct(&png_ptr, &info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr);
if (ferror(outfile)) { if (fm_error(fmp)) {
sprintf(symbol->errtxt, "638: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "638: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(outfile);
}
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (output_to_stdout) { if (!fm_close(fmp, symbol)) {
if (fflush(outfile) != 0) { sprintf(symbol->errtxt, "960: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
sprintf(symbol->errtxt, "639: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
} else {
if (fclose(outfile) != 0) {
sprintf(symbol->errtxt, "960: Failure on closing output file (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE;
}
}
return 0; return 0;
} }
/* vim: set ts=4 sw=4 et : */ /* vim: set ts=4 sw=4 et : */
#else
#if defined(__clang__)
/* Suppresses clang-tidy-18 "clang-diagnostic-empty-translation-unit" */
typedef int wpng_make_clang_tidy_compilers_happy;
#endif
#endif /* ZINT_NO_PNG */ #endif /* ZINT_NO_PNG */

View File

@ -35,10 +35,11 @@
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include "common.h" #include "common.h"
#include "filemem.h"
#include "output.h" #include "output.h"
/* Output Ultracode rectangle colour as PostScript setrgbcolor/setcmykcolor */ /* Output Ultracode rectangle colour as PostScript setrgbcolor/setcmykcolor */
static void ps_put_colour(const int is_rgb, const int colour, FILE *feps) { static void ps_put_colour(const int is_rgb, const int colour, struct filemem *const fmp) {
const int idx = colour >= 1 && colour <= 8 ? colour - 1 : 6 /*black*/; const int idx = colour >= 1 && colour <= 8 ? colour - 1 : 6 /*black*/;
if (is_rgb) { if (is_rgb) {
/* Use RGB colour space */ /* Use RGB colour space */
@ -52,8 +53,8 @@ static void ps_put_colour(const int is_rgb, const int colour, FILE *feps) {
"0 0 0", /* 6: Black (7) */ "0 0 0", /* 6: Black (7) */
"1 1 1", /* 7: White (8) */ "1 1 1", /* 7: White (8) */
}; };
fputs(ps_rgbs[idx], feps); fm_puts(ps_rgbs[idx], fmp);
fputs(" setrgbcolor\n", feps); fm_puts(" setrgbcolor\n", fmp);
} else { } else {
static const char ps_cmyks[8][8] = { static const char ps_cmyks[8][8] = {
"1 0 0 0", /* 0: Cyan (1) */ "1 0 0 0", /* 0: Cyan (1) */
@ -65,8 +66,8 @@ static void ps_put_colour(const int is_rgb, const int colour, FILE *feps) {
"0 0 0 1", /* 6: Black (7) */ "0 0 0 1", /* 6: Black (7) */
"0 0 0 0", /* 7: White (8) */ "0 0 0 0", /* 7: White (8) */
}; };
fputs(ps_cmyks[idx], feps); fm_puts(ps_cmyks[idx], fmp);
fputs(" setcmykcolor\n", feps); fm_puts(" setcmykcolor\n", fmp);
} }
} }
@ -107,51 +108,52 @@ INTERNAL void ps_convert_test(const unsigned char *string, unsigned char *ps_str
#endif #endif
/* Helper to output RGB colour */ /* Helper to output RGB colour */
static void ps_put_rgbcolor(const float red, const float green, const float blue, FILE *feps) { static void ps_put_rgbcolor(const float red, const float green, const float blue,
out_putsf("", 2, red, feps); struct filemem *const fmp) {
out_putsf(" ", 2, green, feps); fm_putsf("", 2, red, fmp);
out_putsf(" ", 2, blue, feps); fm_putsf(" ", 2, green, fmp);
fputs(" setrgbcolor\n", feps); fm_putsf(" ", 2, blue, fmp);
fm_puts(" setrgbcolor\n", fmp);
} }
/* Helper to output CMYK colour */ /* Helper to output CMYK colour */
static void ps_put_cmykcolor(const float cyan, const float magenta, const float yellow, const float black, static void ps_put_cmykcolor(const float cyan, const float magenta, const float yellow, const float black,
FILE *feps) { struct filemem *const fmp) {
out_putsf("", 2, cyan, feps); fm_putsf("", 2, cyan, fmp);
out_putsf(" ", 2, magenta, feps); fm_putsf(" ", 2, magenta, fmp);
out_putsf(" ", 2, yellow, feps); fm_putsf(" ", 2, yellow, fmp);
out_putsf(" ", 2, black, feps); fm_putsf(" ", 2, black, fmp);
fputs(" setcmykcolor\n", feps); fm_puts(" setcmykcolor\n", fmp);
} }
/* Helper to output rectangle */ /* Helper to output rectangle */
static void ps_put_rect(const struct zint_symbol *symbol, const struct zint_vector_rect *rect, const int type, static void ps_put_rect(const struct zint_symbol *symbol, const struct zint_vector_rect *rect, const int type,
FILE *feps) { struct filemem *const fmp) {
if (type == 0 || type == 1) { if (type == 0 || type == 1) {
out_putsf("", 2, rect->height, feps); fm_putsf("", 2, rect->height, fmp);
out_putsf(" ", 2, (symbol->vector->height - rect->y) - rect->height, feps); fm_putsf(" ", 2, (symbol->vector->height - rect->y) - rect->height, fmp);
} }
out_putsf(type == 0 ? " " : type == 1 ? " I " : type == 2 ? "I " : "", 2, rect->x, feps); fm_putsf(type == 0 ? " " : type == 1 ? " I " : type == 2 ? "I " : "", 2, rect->x, fmp);
out_putsf(" ", 2, rect->width, feps); fm_putsf(" ", 2, rect->width, fmp);
fputs(" R\n", feps); fm_puts(" R\n", fmp);
} }
/* Helper to output circle/disc */ /* Helper to output circle/disc */
static void ps_put_circle(const struct zint_symbol *symbol, const struct zint_vector_circle *circle, static void ps_put_circle(const struct zint_symbol *symbol, const struct zint_vector_circle *circle,
const float radius, const int type, FILE *feps) { const float radius, const int type, struct filemem *const fmp) {
if (circle->width) { if (circle->width) {
out_putsf("", 2, circle->x, feps); fm_putsf("", 2, circle->x, fmp);
out_putsf(" ", 2, symbol->vector->height - circle->y, feps); fm_putsf(" ", 2, symbol->vector->height - circle->y, fmp);
out_putsf(" ", 4, radius, feps); fm_putsf(" ", 4, radius, fmp);
out_putsf(" ", 4, circle->width, feps); fm_putsf(" ", 4, circle->width, fmp);
fputs(" C\n", feps); fm_puts(" C\n", fmp);
} else { } else {
if (type == 0 || type == 1) { if (type == 0 || type == 1) {
out_putsf("", 2, symbol->vector->height - circle->y, feps); fm_putsf("", 2, symbol->vector->height - circle->y, fmp);
out_putsf(" ", 4, radius, feps); fm_putsf(" ", 4, radius, fmp);
} }
out_putsf(type == 0 ? " " : type == 1 ? " I " : type == 2 ? "I " : "", 2, circle->x, feps); fm_putsf(type == 0 ? " " : type == 1 ? " I " : type == 2 ? "I " : "", 2, circle->x, fmp);
fputs(" D\n", feps); fm_puts(" D\n", fmp);
} }
} }
@ -168,7 +170,8 @@ static int ps_count_rectangles(const struct zint_symbol *symbol) {
} }
INTERNAL int ps_plot(struct zint_symbol *symbol) { INTERNAL int ps_plot(struct zint_symbol *symbol) {
FILE *feps; struct filemem fm;
struct filemem *const fmp = &fm;
unsigned char fgred, fggrn, fgblu, bgred, bggrn, bgblu, bgalpha; unsigned char fgred, fggrn, fgblu, bgred, bggrn, bgblu, bgalpha;
int fgcyan, fgmagenta, fgyellow, fgblack, bgcyan, bgmagenta, bgyellow, bgblack; int fgcyan, fgmagenta, fgyellow, fgblack, bgcyan, bgmagenta, bgyellow, bgblack;
float red_ink = 0.0f, green_ink = 0.0f, blue_ink = 0.0f; /* Suppress `-Wmaybe-uninitialized` */ float red_ink = 0.0f, green_ink = 0.0f, blue_ink = 0.0f; /* Suppress `-Wmaybe-uninitialized` */
@ -190,22 +193,16 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
int iso_latin1 = 0; int iso_latin1 = 0;
int have_circles_with_width = 0, have_circles_without_width = 0; int have_circles_with_width = 0, have_circles_without_width = 0;
const int upcean = is_upcean(symbol->symbology); const int upcean = is_upcean(symbol->symbology);
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT;
const int is_rgb = (symbol->output_options & CMYK_COLOUR) == 0; const int is_rgb = (symbol->output_options & CMYK_COLOUR) == 0;
if (symbol->vector == NULL) { if (symbol->vector == NULL) {
strcpy(symbol->errtxt, "646: Vector header NULL"); strcpy(symbol->errtxt, "646: Vector header NULL");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
if (!fm_open(fmp, symbol, "w")) {
if (output_to_stdout) { sprintf(symbol->errtxt, "645: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
feps = stdout;
} else {
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; return ZINT_ERROR_FILE_ACCESS;
} }
}
if (is_rgb) { if (is_rgb) {
(void) out_colour_get_rgb(symbol->fgcolour, &fgred, &fggrn, &fgblu, NULL /*alpha*/); (void) out_colour_get_rgb(symbol->fgcolour, &fgred, &fggrn, &fgblu, NULL /*alpha*/);
@ -266,52 +263,52 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
} }
/* Start writing the header */ /* Start writing the header */
fputs("%!PS-Adobe-3.0 EPSF-3.0\n", feps); fm_puts("%!PS-Adobe-3.0 EPSF-3.0\n", fmp);
if (ZINT_VERSION_BUILD) { if (ZINT_VERSION_BUILD) {
fprintf(feps, "%%%%Creator: Zint %d.%d.%d.%d\n", fm_printf(fmp, "%%%%Creator: Zint %d.%d.%d.%d\n",
ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE, ZINT_VERSION_BUILD); ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE, ZINT_VERSION_BUILD);
} else { } else {
fprintf(feps, "%%%%Creator: Zint %d.%d.%d\n", ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE); fm_printf(fmp, "%%%%Creator: Zint %d.%d.%d\n", ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE);
} }
fputs("%%Title: Zint Generated Symbol\n" fm_puts("%%Title: Zint Generated Symbol\n"
"%%Pages: 0\n", feps); "%%Pages: 0\n", fmp);
fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", fm_printf(fmp, "%%%%BoundingBox: 0 0 %d %d\n",
(int) ceilf(symbol->vector->width), (int) ceilf(symbol->vector->height)); (int) ceilf(symbol->vector->width), (int) ceilf(symbol->vector->height));
fputs("%%EndComments\n", feps); fm_puts("%%EndComments\n", fmp);
/* Definitions */ /* Definitions */
if (have_circles_without_width) { if (have_circles_without_width) {
/* Disc: y radius x D */ /* Disc: y radius x D */
fputs("/D { newpath 3 1 roll 0 360 arc fill } bind def\n", feps); fm_puts("/D { newpath 3 1 roll 0 360 arc fill } bind def\n", fmp);
} }
if (have_circles_with_width) { if (have_circles_with_width) {
/* Circle (ring): x y radius width C (adapted from BWIPP renmaxicode.ps) */ /* Circle (ring): x y radius width C (adapted from BWIPP renmaxicode.ps) */
fputs("/C { newpath 4 1 roll 3 copy 0 360 arc closepath 4 -1 roll add 360 0 arcn closepath fill }" fm_puts("/C { newpath 4 1 roll 3 copy 0 360 arc closepath 4 -1 roll add 360 0 arcn closepath fill }"
" bind def\n", feps); " bind def\n", fmp);
} }
if (symbol->vector->hexagons) { if (symbol->vector->hexagons) {
/* Hexagon: radius half_radius half_sqrt3_radius x y */ /* Hexagon: radius half_radius half_sqrt3_radius x y */
if (symbol->vector->hexagons->rotation == 0 || symbol->vector->hexagons->rotation == 180) { if (symbol->vector->hexagons->rotation == 0 || symbol->vector->hexagons->rotation == 180) {
fputs("/H { newpath moveto 2 copy exch neg exch rmoveto 2 index neg 0 exch rlineto 2 copy neg rlineto" fm_puts("/H { newpath moveto 2 copy exch neg exch rmoveto 2 index neg 0 exch rlineto 2 copy neg rlineto"
" 2 copy rlineto 3 -1 roll 0 exch rlineto exch neg exch rlineto closepath fill }" " 2 copy rlineto 3 -1 roll 0 exch rlineto exch neg exch rlineto closepath fill }"
" bind def\n", feps); " bind def\n", fmp);
} else { } else {
fputs("/H { newpath moveto 2 copy neg exch neg rmoveto 2 index 0 rlineto 2 copy exch rlineto" fm_puts("/H { newpath moveto 2 copy neg exch neg rmoveto 2 index 0 rlineto 2 copy exch rlineto"
" 2 copy neg exch rlineto 3 -1 roll neg 0 rlineto neg exch neg rlineto closepath fill }" " 2 copy neg exch rlineto 3 -1 roll neg 0 rlineto neg exch neg rlineto closepath fill }"
" bind def\n", feps); " bind def\n", fmp);
} }
/* Copy r hr hsr for repeat use without having to specify them subsequently */ /* Copy r hr hsr for repeat use without having to specify them subsequently */
fputs("/J { 3 copy } bind def\n", feps); fm_puts("/J { 3 copy } bind def\n", fmp);
/* TODO: Save repeating x also */ /* TODO: Save repeating x also */
} }
if (symbol->vector->rectangles || draw_background) { if (symbol->vector->rectangles || draw_background) {
/* Rectangle: h y x w */ /* Rectangle: h y x w */
fputs("/R { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill }" fm_puts("/R { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill }"
" bind def\n", feps); " bind def\n", fmp);
} }
if (symbol->vector->rectangles || have_circles_without_width) { if (symbol->vector->rectangles || have_circles_without_width) {
/* Copy h y (rect) or y r (disc) for repeat use without having to specify them subsequently */ /* Copy h y (rect) or y r (disc) for repeat use without having to specify them subsequently */
fputs("/I { 2 copy } bind def\n", feps); fm_puts("/I { 2 copy } bind def\n", fmp);
} }
/* Now the actual representation */ /* Now the actual representation */
@ -319,21 +316,21 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
/* Background */ /* Background */
if (draw_background) { if (draw_background) {
if (is_rgb) { if (is_rgb) {
ps_put_rgbcolor(red_paper, green_paper, blue_paper, feps); ps_put_rgbcolor(red_paper, green_paper, blue_paper, fmp);
} else { } else {
ps_put_cmykcolor(cyan_paper, magenta_paper, yellow_paper, black_paper, feps); ps_put_cmykcolor(cyan_paper, magenta_paper, yellow_paper, black_paper, fmp);
} }
out_putsf("", 2, symbol->vector->height, feps); fm_putsf("", 2, symbol->vector->height, fmp);
out_putsf(" 0 0 ", 2, symbol->vector->width, feps); /* y x w */ fm_putsf(" 0 0 ", 2, symbol->vector->width, fmp); /* y x w */
fputs(" R\n", feps); fm_puts(" R\n", fmp);
} }
if (symbol->symbology != BARCODE_ULTRA) { if (symbol->symbology != BARCODE_ULTRA) {
if (is_rgb) { if (is_rgb) {
ps_put_rgbcolor(red_ink, green_ink, blue_ink, feps); ps_put_rgbcolor(red_ink, green_ink, blue_ink, fmp);
} else { } else {
ps_put_cmykcolor(cyan_ink, magenta_ink, yellow_ink, black_ink, feps); ps_put_cmykcolor(cyan_ink, magenta_ink, yellow_ink, black_ink, fmp);
} }
} }
@ -362,22 +359,22 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
if (colour_rect_flag == 0) { if (colour_rect_flag == 0) {
/* Set foreground colour */ /* Set foreground colour */
if (is_rgb) { if (is_rgb) {
ps_put_rgbcolor(red_ink, green_ink, blue_ink, feps); ps_put_rgbcolor(red_ink, green_ink, blue_ink, fmp);
} else { } else {
ps_put_cmykcolor(cyan_ink, magenta_ink, yellow_ink, black_ink, feps); ps_put_cmykcolor(cyan_ink, magenta_ink, yellow_ink, black_ink, fmp);
} }
colour_rect_flag = 1; colour_rect_flag = 1;
} }
} else { } else {
/* Set new colour */ /* Set new colour */
ps_put_colour(is_rgb, rect->colour, feps); ps_put_colour(is_rgb, rect->colour, fmp);
} }
} }
if (i + 1 < u_i && rect->height == ultra_rects[i + 1]->height && rect->y == ultra_rects[i + 1]->y) { if (i + 1 < u_i && rect->height == ultra_rects[i + 1]->height && rect->y == ultra_rects[i + 1]->y) {
ps_put_rect(symbol, rect, type_latch ? 2 : 1, feps); ps_put_rect(symbol, rect, type_latch ? 2 : 1, fmp);
type_latch = 1; type_latch = 1;
} else { } else {
ps_put_rect(symbol, rect, type_latch ? 3 : 0, feps); ps_put_rect(symbol, rect, type_latch ? 3 : 0, fmp);
type_latch = 0; type_latch = 0;
} }
} }
@ -385,10 +382,10 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
type_latch = 0; type_latch = 0;
for (rect = symbol->vector->rectangles; rect; rect = rect->next) { for (rect = symbol->vector->rectangles; rect; rect = rect->next) {
if (rect->next && rect->height == rect->next->height && rect->y == rect->next->y) { if (rect->next && rect->height == rect->next->height && rect->y == rect->next->y) {
ps_put_rect(symbol, rect, type_latch ? 2 : 1, feps); ps_put_rect(symbol, rect, type_latch ? 2 : 1, fmp);
type_latch = 1; type_latch = 1;
} else { } else {
ps_put_rect(symbol, rect, type_latch ? 3 : 0, feps); ps_put_rect(symbol, rect, type_latch ? 3 : 0, fmp);
type_latch = 0; type_latch = 0;
} }
} }
@ -400,18 +397,18 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
float hy = symbol->vector->height - hex->y; float hy = symbol->vector->height - hex->y;
if (previous_diameter != hex->diameter) { if (previous_diameter != hex->diameter) {
previous_diameter = hex->diameter; previous_diameter = hex->diameter;
out_putsf("", 4, 0.5f * previous_diameter /*radius*/, feps); fm_putsf("", 4, 0.5f * previous_diameter /*radius*/, fmp);
out_putsf(" ", 4, 0.43301270189221932338f * previous_diameter /*half_sqrt3_radius*/, feps); fm_putsf(" ", 4, 0.43301270189221932338f * previous_diameter /*half_sqrt3_radius*/, fmp);
out_putsf(" ", 4, 0.25f * previous_diameter /*half_radius*/, feps); fm_putsf(" ", 4, 0.25f * previous_diameter /*half_radius*/, fmp);
fputc('\n', feps); fm_putc('\n', fmp);
} }
if (hex->next) { if (hex->next) {
out_putsf("J ", 2, hex->x, feps); fm_putsf("J ", 2, hex->x, fmp);
} else { } else {
out_putsf("", 2, hex->x, feps); fm_putsf("", 2, hex->x, fmp);
} }
out_putsf(" ", 2, hy, feps); fm_putsf(" ", 2, hy, fmp);
fputs(" H\n", feps); fm_puts(" H\n", fmp);
} }
/* Circles */ /* Circles */
@ -425,25 +422,25 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
if (circle->colour) { /* Legacy - no longer used */ if (circle->colour) { /* Legacy - no longer used */
/* A 'white' circle */ /* A 'white' circle */
if (is_rgb) { if (is_rgb) {
ps_put_rgbcolor(red_paper, green_paper, blue_paper, feps); ps_put_rgbcolor(red_paper, green_paper, blue_paper, fmp);
} else { } else {
ps_put_cmykcolor(cyan_paper, magenta_paper, yellow_paper, black_paper, feps); ps_put_cmykcolor(cyan_paper, magenta_paper, yellow_paper, black_paper, fmp);
} }
ps_put_circle(symbol, circle, radius, 0 /*type*/, feps); ps_put_circle(symbol, circle, radius, 0 /*type*/, fmp);
if (circle->next) { if (circle->next) {
if (is_rgb) { if (is_rgb) {
ps_put_rgbcolor(red_ink, green_ink, blue_ink, feps); ps_put_rgbcolor(red_ink, green_ink, blue_ink, fmp);
} else { } else {
ps_put_cmykcolor(cyan_ink, magenta_ink, yellow_ink, black_ink, feps); ps_put_cmykcolor(cyan_ink, magenta_ink, yellow_ink, black_ink, fmp);
} }
} }
} else { } else {
/* A 'black' circle */ /* A 'black' circle */
if (circle->next && circle->y == circle->next->y && circle->diameter == circle->next->diameter) { if (circle->next && circle->y == circle->next->y && circle->diameter == circle->next->diameter) {
ps_put_circle(symbol, circle, radius, type_latch ? 2 : 1, feps); ps_put_circle(symbol, circle, radius, type_latch ? 2 : 1, fmp);
type_latch = 1; type_latch = 1;
} else { } else {
ps_put_circle(symbol, circle, radius, type_latch ? 3 : 0, feps); ps_put_circle(symbol, circle, radius, type_latch ? 3 : 0, fmp);
type_latch = 0; type_latch = 0;
} }
} }
@ -465,71 +462,62 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
} }
if (iso_latin1) { if (iso_latin1) {
/* Change encoding to ISO 8859-1, see Postscript Language Reference Manual 2nd Edition Example 5.6 */ /* Change encoding to ISO 8859-1, see Postscript Language Reference Manual 2nd Edition Example 5.6 */
fprintf(feps, "/%s findfont\n", font); fm_printf(fmp, "/%s findfont\n", font);
fputs("dup length dict begin\n" fm_puts("dup length dict begin\n"
"{1 index /FID ne {def} {pop pop} ifelse} forall\n" "{1 index /FID ne {def} {pop pop} ifelse} forall\n"
"/Encoding ISOLatin1Encoding def\n" "/Encoding ISOLatin1Encoding def\n"
"currentdict\n" "currentdict\n"
"end\n" "end\n"
"/Helvetica-ISOLatin1 exch definefont pop\n", feps); "/Helvetica-ISOLatin1 exch definefont pop\n", fmp);
font = "Helvetica-ISOLatin1"; font = "Helvetica-ISOLatin1";
} }
do { do {
ps_convert(string->text, ps_string); ps_convert(string->text, ps_string);
if (string->fsize != previous_fsize) { if (string->fsize != previous_fsize) {
fprintf(feps, "/%s findfont", font); fm_printf(fmp, "/%s findfont", font);
/* Compensate for Helvetica being smaller than Zint's OCR-B */ /* Compensate for Helvetica being smaller than Zint's OCR-B */
out_putsf( " ", 2, upcean ? string->fsize * 1.07f : string->fsize, feps); fm_putsf( " ", 2, upcean ? string->fsize * 1.07f : string->fsize, fmp);
fputs(" scalefont setfont\n", feps); fm_puts(" scalefont setfont\n", fmp);
previous_fsize = string->fsize; previous_fsize = string->fsize;
} }
/* Unhack the guard whitespace `gws_left_fudge`/`gws_right_fudge` hack */ /* Unhack the guard whitespace `gws_left_fudge`/`gws_right_fudge` hack */
if (upcean && string->halign == 1 && string->text[0] == '<') { if (upcean && string->halign == 1 && string->text[0] == '<') {
const float gws_left_fudge = symbol->scale < 0.1f ? 0.1f : symbol->scale; /* 0.5 * 2 * scale */ const float gws_left_fudge = symbol->scale < 0.1f ? 0.1f : symbol->scale; /* 0.5 * 2 * scale */
out_putsf(" ", 2, string->x + gws_left_fudge, feps); fm_putsf(" ", 2, string->x + gws_left_fudge, fmp);
} else if (upcean && string->halign == 2 && string->text[0] == '>') { } else if (upcean && string->halign == 2 && string->text[0] == '>') {
const float gws_right_fudge = symbol->scale < 0.1f ? 0.1f : symbol->scale; /* 0.5 * 2 * scale */ const float gws_right_fudge = symbol->scale < 0.1f ? 0.1f : symbol->scale; /* 0.5 * 2 * scale */
out_putsf(" ", 2, string->x - gws_right_fudge, feps); fm_putsf(" ", 2, string->x - gws_right_fudge, fmp);
} else { } else {
out_putsf(" ", 2, string->x, feps); fm_putsf(" ", 2, string->x, fmp);
} }
out_putsf(" ", 2, symbol->vector->height - string->y, feps); fm_putsf(" ", 2, symbol->vector->height - string->y, fmp);
fputs(" moveto\n", feps); fm_puts(" moveto\n", fmp);
if (string->rotation != 0) { if (string->rotation != 0) {
fputs(" gsave\n", feps); fm_puts(" gsave\n", fmp);
fprintf(feps, " %d rotate\n", 360 - string->rotation); fm_printf(fmp, " %d rotate\n", 360 - string->rotation);
} }
if (string->halign == 0 || string->halign == 2) { /* Need width for middle or right align */ if (string->halign == 0 || string->halign == 2) { /* Need width for middle or right align */
fprintf(feps, " (%s) stringwidth pop" /* Returns "width height" - discard "height" */ fm_printf(fmp, " (%s) stringwidth pop" /* Returns "width height" - discard "height" */
" %s 0 rmoveto\n", ps_string, string->halign == 2 ? "neg" : "-2 div"); " %s 0 rmoveto\n", ps_string, string->halign == 2 ? "neg" : "-2 div");
} }
fprintf(feps, " (%s) show\n", ps_string); fm_printf(fmp, " (%s) show\n", ps_string);
if (string->rotation != 0) { if (string->rotation != 0) {
fputs(" grestore\n", feps); fm_puts(" grestore\n", fmp);
} }
string = string->next; string = string->next;
} while (string); } while (string);
} }
if (ferror(feps)) { if (fm_error(fmp)) {
sprintf(symbol->errtxt, "647: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "647: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(feps);
}
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (output_to_stdout) { if (!fm_close(fmp, symbol)) {
if (fflush(feps) != 0) { sprintf(symbol->errtxt, "649: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
sprintf(symbol->errtxt, "648: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
} else {
if (fclose(feps) != 0) {
sprintf(symbol->errtxt, "649: Failure on closing output file (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE;
}
}
return error_number; return error_number;
} }

View File

@ -827,7 +827,8 @@ static void qr_add_ecc(unsigned char fullstream[], const unsigned char datastrea
} }
for (j = 0; j < length_this_block; j++) { for (j = 0; j < length_this_block; j++) {
data_block[j] = datastream[in_posn + j]; /* NOLINT false-positive popped up with clang-tidy 14.0.1 */ /* This false-positive popped up with clang-tidy 14.0.1 */
data_block[j] = datastream[in_posn + j]; /* NOLINT(clang-analyzer-core.uninitialized.Assign) */
} }
rs_encode(&rs, length_this_block, data_block, ecc_block); rs_encode(&rs, length_this_block, data_block, ecc_block);
@ -848,7 +849,8 @@ static void qr_add_ecc(unsigned char fullstream[], const unsigned char datastrea
} }
for (j = 0; j < short_data_block_length; j++) { for (j = 0; j < short_data_block_length; j++) {
interleaved_data[(j * blocks) + i] = data_block[j]; /* NOLINT and another with clang-tidy 14.0.6 */ /* And another with clang-tidy 14.0.6 */
interleaved_data[(j * blocks) + i] = data_block[j]; /* NOLINT(clang-analyzer-core.uninitialized.Assign) */
} }
if (i >= qty_short_blocks) { if (i >= qty_short_blocks) {

View File

@ -244,12 +244,14 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, const int image
#ifndef ZINT_NO_PNG #ifndef ZINT_NO_PNG
error_number = png_pixel_plot(symbol, rotated_pixbuf); error_number = png_pixel_plot(symbol, rotated_pixbuf);
#else #else
if (rotate_angle) { error_number = ZINT_ERROR_INVALID_OPTION;
free(rotated_pixbuf);
}
return ZINT_ERROR_INVALID_OPTION;
#endif #endif
break; break;
#if defined(__GNUC__) && !defined(__clang__) && defined(NDEBUG) && defined(ZINT_NO_PNG)
/* Suppress gcc warning <unknown> may be used uninitialized - only when Release and ZINT_NO_PNG */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
case OUT_PCX_FILE: case OUT_PCX_FILE:
error_number = pcx_pixel_plot(symbol, rotated_pixbuf); error_number = pcx_pixel_plot(symbol, rotated_pixbuf);
break; break;
@ -262,6 +264,9 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, const int image
default: default:
error_number = bmp_pixel_plot(symbol, rotated_pixbuf); error_number = bmp_pixel_plot(symbol, rotated_pixbuf);
break; break;
#if defined(__GNUC__) && !defined(__clang__) && defined(NDEBUG) && defined(ZINT_NO_PNG)
#pragma GCC diagnostic pop
#endif
} }
if (rotate_angle) { if (rotate_angle) {
@ -1417,6 +1422,10 @@ INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_
if (error != 0) { if (error != 0) {
return error; return error;
} }
if (symbol->rows <= 0) {
strcpy(symbol->errtxt, "664: No rows");
return ZINT_ERROR_INVALID_OPTION;
}
if (symbol->symbology == BARCODE_MAXICODE) { if (symbol->symbology == BARCODE_MAXICODE) {
error = plot_raster_maxicode(symbol, rotate_angle, file_type); error = plot_raster_maxicode(symbol, rotate_angle, file_type);

View File

@ -35,6 +35,7 @@
#include <stdio.h> #include <stdio.h>
#include "common.h" #include "common.h"
#include "filemem.h"
#include "output.h" #include "output.h"
#include "fonts/normal_woff2.h" #include "fonts/normal_woff2.h"
#include "fonts/upcean_woff2.h" #include "fonts/upcean_woff2.h"
@ -95,26 +96,27 @@ static void svg_make_html_friendly(const unsigned char *string, char *html_versi
} }
/* Helper to output floating point attribute */ /* Helper to output floating point attribute */
static void svg_put_fattrib(const char *prefix, const int dp, const float val, FILE *fsvg) { static void svg_put_fattrib(const char *prefix, const int dp, const float val, struct filemem *fmp) {
out_putsf(prefix, dp, val, fsvg); fm_putsf(prefix, dp, val, fmp);
fputc('"', fsvg); fm_putc('"', fmp);
} }
/* Helper to output opacity attribute attribute and close tag (maybe) */ /* Helper to output opacity attribute attribute and close tag (maybe) */
static void svg_put_opacity_close(const unsigned char alpha, const float val, const int close, FILE *fsvg) { static void svg_put_opacity_close(const unsigned char alpha, const float val, const int close, struct filemem *fmp) {
if (alpha != 0xff) { if (alpha != 0xff) {
svg_put_fattrib(" opacity=\"", 3, val, fsvg); svg_put_fattrib(" opacity=\"", 3, val, fmp);
} }
if (close) { if (close) {
fputc('/', fsvg); fm_putc('/', fmp);
} }
fputs(">\n", fsvg); fm_puts(">\n", fmp);
} }
INTERNAL int svg_plot(struct zint_symbol *symbol) { INTERNAL int svg_plot(struct zint_symbol *symbol) {
static const char normal_font_family[] = "Arimo"; static const char normal_font_family[] = "Arimo";
static const char upcean_font_family[] = "OCRB"; static const char upcean_font_family[] = "OCRB";
FILE *fsvg; struct filemem fm;
struct filemem *const fmp = &fm;
int error_number = 0; int error_number = 0;
float previous_diameter; float previous_diameter;
float radius, half_radius, half_sqrt3_radius; float radius, half_radius, half_sqrt3_radius;
@ -135,7 +137,6 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
int len, html_len; int len, html_len;
const int upcean = is_upcean(symbol->symbology); const int upcean = is_upcean(symbol->symbology);
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT;
char *html_string; char *html_string;
(void) out_colour_get_rgb(symbol->fgcolour, &fgred, &fggreen, &fgblue, &fg_alpha); (void) out_colour_get_rgb(symbol->fgcolour, &fgred, &fggreen, &fgblue, &fg_alpha);
@ -175,69 +176,68 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
strcpy(symbol->errtxt, "681: Vector header NULL"); strcpy(symbol->errtxt, "681: Vector header NULL");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
if (output_to_stdout) { if (!fm_open(fmp, symbol, "w")) {
fsvg = stdout; sprintf(symbol->errtxt, "680: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
} else {
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; return ZINT_ERROR_FILE_ACCESS;
} }
}
/* Start writing the header */ /* Start writing the header */
fputs("<?xml version=\"1.0\" standalone=\"no\"?>\n" fm_puts("<?xml version=\"1.0\" standalone=\"no\"?>\n"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
fsvg); fmp);
fprintf(fsvg, "<svg width=\"%d\" height=\"%d\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n", fm_printf(fmp, "<svg width=\"%d\" height=\"%d\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n",
(int) ceilf(symbol->vector->width), (int) ceilf(symbol->vector->height)); (int) ceilf(symbol->vector->width), (int) ceilf(symbol->vector->height));
fputs(" <desc>Zint Generated Symbol</desc>\n", fsvg); fm_puts(" <desc>Zint Generated Symbol</desc>\n", fmp);
if ((symbol->output_options & EMBED_VECTOR_FONT) && symbol->vector->strings) { if ((symbol->output_options & EMBED_VECTOR_FONT) && symbol->vector->strings) {
fprintf(fsvg, " <style>@font-face {font-family:\"%s\"; src:url(data:font/woff2;base64,%s);}</style>\n", /* Split into `puts()` rather than one very large `printf()` */
upcean ? "OCRB" : "Arimo", upcean ? upcean_woff2 : normal_woff2); fm_printf(fmp, " <style>@font-face {font-family:\"%s\"; src:url(data:font/woff2;base64,",
upcean ? "OCRB" : "Arimo");
fm_puts(upcean ? upcean_woff2 : normal_woff2, fmp);
fm_puts(");}</style>\n", fmp);
} }
fprintf(fsvg, " <g id=\"barcode\" fill=\"#%s\">\n", fgcolour_string); fm_printf(fmp, " <g id=\"barcode\" fill=\"#%s\">\n", fgcolour_string);
if (bg_alpha != 0) { if (bg_alpha != 0) {
fprintf(fsvg, " <rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\"", fm_printf(fmp, " <rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\"",
(int) ceilf(symbol->vector->width), (int) ceilf(symbol->vector->height), bgcolour_string); (int) ceilf(symbol->vector->width), (int) ceilf(symbol->vector->height), bgcolour_string);
svg_put_opacity_close(bg_alpha, bg_alpha_opacity, 1 /*close*/, fsvg); svg_put_opacity_close(bg_alpha, bg_alpha_opacity, 1 /*close*/, fmp);
} }
if (symbol->vector->rectangles) { if (symbol->vector->rectangles) {
int current_colour = 0; int current_colour = 0;
rect = symbol->vector->rectangles; rect = symbol->vector->rectangles;
fputs(" <path d=\"", fsvg); fm_puts(" <path d=\"", fmp);
while (rect) { while (rect) {
if (current_colour && rect->colour != current_colour) { if (current_colour && rect->colour != current_colour) {
fputc('"', fsvg); fm_putc('"', fmp);
if (current_colour != -1) { if (current_colour != -1) {
svg_pick_colour(current_colour, colour_code); svg_pick_colour(current_colour, colour_code);
fprintf(fsvg, " fill=\"#%s\"", colour_code); fm_printf(fmp, " fill=\"#%s\"", colour_code);
} }
svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fsvg); svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fmp);
fputs(" <path d=\"", fsvg); fm_puts(" <path d=\"", fmp);
} }
current_colour = rect->colour; current_colour = rect->colour;
out_putsf("M", 2, rect->x, fsvg); fm_putsf("M", 2, rect->x, fmp);
out_putsf(" ", 2, rect->y, fsvg); fm_putsf(" ", 2, rect->y, fmp);
out_putsf("h", 2, rect->width, fsvg); fm_putsf("h", 2, rect->width, fmp);
out_putsf("v", 2, rect->height, fsvg); fm_putsf("v", 2, rect->height, fmp);
out_putsf("h-", 2, rect->width, fsvg); fm_putsf("h-", 2, rect->width, fmp);
fputs("Z", fsvg); fm_puts("Z", fmp);
rect = rect->next; rect = rect->next;
} }
fputc('"', fsvg); fm_putc('"', fmp);
if (current_colour != -1) { if (current_colour != -1) {
svg_pick_colour(current_colour, colour_code); svg_pick_colour(current_colour, colour_code);
fprintf(fsvg, " fill=\"#%s\"", colour_code); fm_printf(fmp, " fill=\"#%s\"", colour_code);
} }
svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fsvg); svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fmp);
} }
if (symbol->vector->hexagons) { if (symbol->vector->hexagons) {
previous_diameter = radius = half_radius = half_sqrt3_radius = 0.0f; previous_diameter = radius = half_radius = half_sqrt3_radius = 0.0f;
hex = symbol->vector->hexagons; hex = symbol->vector->hexagons;
fputs(" <path d=\"", fsvg); fm_puts(" <path d=\"", fmp);
while (hex) { while (hex) {
if (previous_diameter != hex->diameter) { if (previous_diameter != hex->diameter) {
previous_diameter = hex->diameter; previous_diameter = hex->diameter;
@ -246,37 +246,37 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
half_sqrt3_radius = 0.43301270189221932338f * previous_diameter; half_sqrt3_radius = 0.43301270189221932338f * previous_diameter;
} }
if ((hex->rotation == 0) || (hex->rotation == 180)) { if ((hex->rotation == 0) || (hex->rotation == 180)) {
out_putsf("M", 2, hex->x, fsvg); fm_putsf("M", 2, hex->x, fmp);
out_putsf(" ", 2, hex->y + radius, fsvg); fm_putsf(" ", 2, hex->y + radius, fmp);
out_putsf("L", 2, hex->x + half_sqrt3_radius, fsvg); fm_putsf("L", 2, hex->x + half_sqrt3_radius, fmp);
out_putsf(" ", 2, hex->y + half_radius, fsvg); fm_putsf(" ", 2, hex->y + half_radius, fmp);
out_putsf("L", 2, hex->x + half_sqrt3_radius, fsvg); fm_putsf("L", 2, hex->x + half_sqrt3_radius, fmp);
out_putsf(" ", 2, hex->y - half_radius, fsvg); fm_putsf(" ", 2, hex->y - half_radius, fmp);
out_putsf("L", 2, hex->x, fsvg); fm_putsf("L", 2, hex->x, fmp);
out_putsf(" ", 2, hex->y - radius, fsvg); fm_putsf(" ", 2, hex->y - radius, fmp);
out_putsf("L", 2, hex->x - half_sqrt3_radius, fsvg); fm_putsf("L", 2, hex->x - half_sqrt3_radius, fmp);
out_putsf(" ", 2, hex->y - half_radius, fsvg); fm_putsf(" ", 2, hex->y - half_radius, fmp);
out_putsf("L", 2, hex->x - half_sqrt3_radius, fsvg); fm_putsf("L", 2, hex->x - half_sqrt3_radius, fmp);
out_putsf(" ", 2, hex->y + half_radius, fsvg); fm_putsf(" ", 2, hex->y + half_radius, fmp);
} else { } else {
out_putsf("M", 2, hex->x - radius, fsvg); fm_putsf("M", 2, hex->x - radius, fmp);
out_putsf(" ", 2, hex->y, fsvg); fm_putsf(" ", 2, hex->y, fmp);
out_putsf("L", 2, hex->x - half_radius, fsvg); fm_putsf("L", 2, hex->x - half_radius, fmp);
out_putsf(" ", 2, hex->y + half_sqrt3_radius, fsvg); fm_putsf(" ", 2, hex->y + half_sqrt3_radius, fmp);
out_putsf("L", 2, hex->x + half_radius, fsvg); fm_putsf("L", 2, hex->x + half_radius, fmp);
out_putsf(" ", 2, hex->y + half_sqrt3_radius, fsvg); fm_putsf(" ", 2, hex->y + half_sqrt3_radius, fmp);
out_putsf("L", 2, hex->x + radius, fsvg); fm_putsf("L", 2, hex->x + radius, fmp);
out_putsf(" ", 2, hex->y, fsvg); fm_putsf(" ", 2, hex->y, fmp);
out_putsf("L", 2, hex->x + half_radius, fsvg); fm_putsf("L", 2, hex->x + half_radius, fmp);
out_putsf(" ", 2, hex->y - half_sqrt3_radius, fsvg); fm_putsf(" ", 2, hex->y - half_sqrt3_radius, fmp);
out_putsf("L", 2, hex->x - half_radius, fsvg); fm_putsf("L", 2, hex->x - half_radius, fmp);
out_putsf(" ", 2, hex->y - half_sqrt3_radius, fsvg); fm_putsf(" ", 2, hex->y - half_sqrt3_radius, fmp);
} }
fputc('Z', fsvg); fm_putc('Z', fmp);
hex = hex->next; hex = hex->next;
} }
fputc('"', fsvg); fm_putc('"', fmp);
svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fsvg); svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fmp);
} }
previous_diameter = radius = 0.0f; previous_diameter = radius = 0.0f;
@ -286,28 +286,28 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
previous_diameter = circle->diameter; previous_diameter = circle->diameter;
radius = 0.5f * previous_diameter; radius = 0.5f * previous_diameter;
} }
fputs(" <circle", fsvg); fm_puts(" <circle", fmp);
svg_put_fattrib(" cx=\"", 2, circle->x, fsvg); svg_put_fattrib(" cx=\"", 2, circle->x, fmp);
svg_put_fattrib(" cy=\"", 2, circle->y, fsvg); svg_put_fattrib(" cy=\"", 2, circle->y, fmp);
svg_put_fattrib(" r=\"", circle->width ? 3 : 2, radius, fsvg); svg_put_fattrib(" r=\"", circle->width ? 3 : 2, radius, fmp);
if (circle->colour) { /* Legacy - no longer used */ if (circle->colour) { /* Legacy - no longer used */
if (circle->width) { if (circle->width) {
fprintf(fsvg, " stroke=\"#%s\"", bgcolour_string); fm_printf(fmp, " stroke=\"#%s\"", bgcolour_string);
svg_put_fattrib(" stroke-width=\"", 3, circle->width, fsvg); svg_put_fattrib(" stroke-width=\"", 3, circle->width, fmp);
fputs(" fill=\"none\"", fsvg); fm_puts(" fill=\"none\"", fmp);
} else { } else {
fprintf(fsvg, " fill=\"#%s\"", bgcolour_string); fm_printf(fmp, " fill=\"#%s\"", bgcolour_string);
} }
/* This doesn't work how the user is likely to expect - more work needed! */ /* This doesn't work how the user is likely to expect - more work needed! */
svg_put_opacity_close(bg_alpha, bg_alpha_opacity, 1 /*close*/, fsvg); svg_put_opacity_close(bg_alpha, bg_alpha_opacity, 1 /*close*/, fmp);
} else { } else {
if (circle->width) { if (circle->width) {
fprintf(fsvg, " stroke=\"#%s\"", fgcolour_string); fm_printf(fmp, " stroke=\"#%s\"", fgcolour_string);
svg_put_fattrib(" stroke-width=\"", 3, circle->width, fsvg); svg_put_fattrib(" stroke-width=\"", 3, circle->width, fmp);
fputs(" fill=\"none\"", fsvg); fm_puts(" fill=\"none\"", fmp);
} }
svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fsvg); svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fmp);
} }
circle = circle->next; circle = circle->next;
} }
@ -316,54 +316,45 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
string = symbol->vector->strings; string = symbol->vector->strings;
while (string) { while (string) {
const char *const halign = string->halign == 2 ? "end" : string->halign == 1 ? "start" : "middle"; const char *const halign = string->halign == 2 ? "end" : string->halign == 1 ? "start" : "middle";
fputs(" <text", fsvg); fm_puts(" <text", fmp);
svg_put_fattrib(" x=\"", 2, string->x, fsvg); svg_put_fattrib(" x=\"", 2, string->x, fmp);
svg_put_fattrib(" y=\"", 2, string->y, fsvg); svg_put_fattrib(" y=\"", 2, string->y, fmp);
fprintf(fsvg, " text-anchor=\"%s\"", halign); fm_printf(fmp, " text-anchor=\"%s\"", halign);
if (upcean) { if (upcean) {
fprintf(fsvg, " font-family=\"%s, monospace\"", upcean_font_family); fm_printf(fmp, " font-family=\"%s, monospace\"", upcean_font_family);
} else { } else {
fprintf(fsvg, " font-family=\"%s, Arial, sans-serif\"", normal_font_family); fm_printf(fmp, " font-family=\"%s, Arial, sans-serif\"", normal_font_family);
} }
svg_put_fattrib(" font-size=\"", 1, string->fsize, fsvg); svg_put_fattrib(" font-size=\"", 1, string->fsize, fmp);
if (bold) { if (bold) {
fputs(" font-weight=\"bold\"", fsvg); fm_puts(" font-weight=\"bold\"", fmp);
} }
if (string->rotation != 0) { if (string->rotation != 0) {
fprintf(fsvg, " transform=\"rotate(%d", string->rotation); fm_printf(fmp, " transform=\"rotate(%d", string->rotation);
out_putsf(",", 2, string->x, fsvg); fm_putsf(",", 2, string->x, fmp);
out_putsf(",", 2, string->y, fsvg); fm_putsf(",", 2, string->y, fmp);
fputs(")\"", fsvg); fm_puts(")\"", fmp);
} }
svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 0 /*close*/, fsvg); svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 0 /*close*/, fmp);
svg_make_html_friendly(string->text, html_string); svg_make_html_friendly(string->text, html_string);
fprintf(fsvg, " %s\n", html_string); fm_printf(fmp, " %s\n", html_string);
fputs(" </text>\n", fsvg); fm_puts(" </text>\n", fmp);
string = string->next; string = string->next;
} }
fputs(" </g>\n" fm_puts(" </g>\n"
"</svg>\n", fsvg); "</svg>\n", fmp);
if (ferror(fsvg)) { if (fm_error(fmp)) {
sprintf(symbol->errtxt, "682: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "682: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(fsvg);
}
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (output_to_stdout) { if (!fm_close(fmp, symbol)) {
if (fflush(fsvg) != 0) { sprintf(symbol->errtxt, "684: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
sprintf(symbol->errtxt, "683: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
} else {
if (fclose(fsvg) != 0) {
sprintf(symbol->errtxt, "684: Failure on closing output file (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE;
}
}
return error_number; return error_number;
} }

View File

@ -58,6 +58,7 @@ zint_add_test(dmatrix test_dmatrix)
zint_add_test(dotcode test_dotcode) zint_add_test(dotcode test_dotcode)
zint_add_test(eci test_eci) zint_add_test(eci test_eci)
zint_add_test(emf test_emf) zint_add_test(emf test_emf)
zint_add_test(filemem test_filemem)
zint_add_test(gb18030 test_gb18030) zint_add_test(gb18030 test_gb18030)
zint_add_test(gb2312 test_gb2312) zint_add_test(gb2312 test_gb2312)
zint_add_test(gif test_gif) zint_add_test(gif test_gif)

View File

@ -155,6 +155,8 @@ static void test_print(const testCtx *const p_ctx) {
char expected_file[4096]; char expected_file[4096];
char escaped[1024]; char escaped[1024];
int escaped_size = 1024; int escaped_size = 1024;
unsigned char filebuf[32768];
int filebuf_size;
const char *const have_identify = testUtilHaveIdentify(); const char *const have_identify = testUtilHaveIdentify();
@ -220,9 +222,25 @@ static void test_print(const testCtx *const p_ctx) {
ret = testUtilCmpBins(symbol->outfile, expected_file); ret = testUtilCmpBins(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
ret = testUtilReadFile(symbol->outfile, filebuf, sizeof(filebuf), &filebuf_size); /* For BARCODE_MEMORY_FILE */
assert_zero(ret, "i:%d %s testUtilReadFile(%s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile); assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
} }
symbol->output_options |= BARCODE_MEMORY_FILE;
ret = ZBarcode_Print(symbol, 0);
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0 (%s)\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "i:%d %s memfile NULL\n", i, testUtilBarcodeName(data[i].symbology));
assert_equal(symbol->memfile_size, filebuf_size, "i:%d %s memfile_size %d != %d\n",
i, testUtilBarcodeName(data[i].symbology), symbol->memfile_size, filebuf_size);
assert_zero(memcmp(symbol->memfile, filebuf, symbol->memfile_size), "i:%d %s memcmp(memfile, filebuf) != 0\n",
i, testUtilBarcodeName(data[i].symbology));
}
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
} }

View File

@ -590,7 +590,7 @@ static void test_fuzz(const testCtx *const p_ctx) {
}; };
struct item data[] = { struct item data[] = {
/* 0*/ { -1, -1, "\034\034I", 3, 0, 1, "" }, /* 0*/ { -1, -1, "\034\034I", 3, 0, 1, "" },
/* 1*/ { 6, -2147483648, /* 1*/ { 6, -2147483647 - 1 /*Suppress MSVC warning C4146*/,
"\134\000\377\153\143\163\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061" "\134\000\377\153\143\163\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061\061"
"\071\065\062\000\000\000\000\061\061\061\061\061\061\366\366\366\366\366\366\366\366\366\366\007\366\366\366\366\366\366\366\061\061\061\061\061\061\061\061\061" "\071\065\062\000\000\000\000\061\061\061\061\061\061\366\366\366\366\366\366\366\366\366\366\007\366\366\366\366\366\366\366\061\061\061\061\061\061\061\061\061"
"\061\061\061\061\061\061\061\323\323\323\323\000\200\135\000\362\000\000\000\000\000\050\000\000\000\000\162\162\162\162\034\153\143\163\061\061\061\061\061\061" "\061\061\061\061\061\061\061\323\323\323\323\000\200\135\000\362\000\000\000\000\000\050\000\000\000\000\162\162\162\162\034\153\143\163\061\061\061\061\061\061"

View File

@ -104,6 +104,8 @@ static void test_print(const testCtx *const p_ctx) {
char expected_file[1024]; char expected_file[1024];
char escaped[1024]; char escaped[1024];
int escaped_size = 1024; int escaped_size = 1024;
unsigned char filebuf[32768];
int filebuf_size;
int have_libreoffice = 0; int have_libreoffice = 0;
if (p_ctx->generate) { if (p_ctx->generate) {
@ -182,7 +184,23 @@ static void test_print(const testCtx *const p_ctx) {
ret = testUtilCmpBins(symbol->outfile, expected_file); ret = testUtilCmpBins(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
if (p_ctx->index == -1) assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
ret = testUtilReadFile(symbol->outfile, filebuf, sizeof(filebuf), &filebuf_size); /* For BARCODE_MEMORY_FILE */
assert_zero(ret, "i:%d %s testUtilReadFile(%s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
}
symbol->output_options |= BARCODE_MEMORY_FILE;
ret = ZBarcode_Print(symbol, data[i].rotate_angle);
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0 (%s)\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "i:%d %s memfile NULL\n", i, testUtilBarcodeName(data[i].symbology));
assert_equal(symbol->memfile_size, filebuf_size, "i:%d %s memfile_size %d != %d\n",
i, testUtilBarcodeName(data[i].symbology), symbol->memfile_size, filebuf_size);
assert_zero(memcmp(symbol->memfile, filebuf, symbol->memfile_size), "i:%d %s memcmp(memfile, filebuf) != 0\n",
i, testUtilBarcodeName(data[i].symbology));
} }
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);

View File

@ -0,0 +1,477 @@
/*
libzint - the open source barcode library
Copyright (C) 2023 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* SPDX-License-Identifier: BSD-3-Clause */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <locale.h>
#include <math.h>
#include <sys/stat.h>
#include "testcommon.h"
#include "../common.h"
#include "../filemem.h"
static void test_svg(const testCtx *const p_ctx) {
int debug = p_ctx->debug;
struct item {
int symbology;
int output_options;
char *outfile;
char *data;
int length;
int ret;
char *expected;
};
/* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
struct item data[] = {
/* 0*/ { BARCODE_CODE128, BARCODE_MEMORY_FILE, "out.svg", "ABCDEF", -1, 0,
"<?xml version=\"1.0\" standalone=\"no\"?>\n"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
"<svg width=\"202\" height=\"117\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n"
" <desc>Zint Generated Symbol</desc>\n"
" <g id=\"barcode\" fill=\"#000000\">\n"
" <rect x=\"0\" y=\"0\" width=\"202\" height=\"117\" fill=\"#FFFFFF\"/>\n"
" <path d=\"M0 0h4v100h-4ZM6 0h2v100h-2ZM12 0h2v100h-2ZM22 0h2v100h-2ZM26 0h2v100h-2ZM34 0h4v100h-4ZM44 0h2v100h-2ZM52 0h2v100h-2ZM56 0h4v100h-4ZM66 0h2v100h-2ZM74 0h2v100h-2ZM82 0h4v100h-4ZM88 0h2v100h-2ZM92 0h4v100h-4ZM102 0h2v100h-2ZM110 0h2v100h-2ZM118 0h4v100h-4ZM124 0h2v100h-2ZM132 0h2v100h-2ZM140 0h4v100h-4ZM150 0h2v100h-2ZM154 0h2v100h-2ZM158 0h4v100h-4ZM168 0h6v100h-6ZM176 0h4v100h-4ZM186 0h6v100h-6ZM194 0h2v100h-2ZM198 0h4v100h-4Z\"/>\n"
" <text x=\"101\" y=\"113.34\" text-anchor=\"middle\" font-family=\"Arimo, Arial, sans-serif\" font-size=\"14\">\n"
" ABCDEF\n"
" </text>\n"
" </g>\n"
"</svg>\n"
},
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol = NULL;
testStartSymbol("test_svg", &symbol);
for (i = 0; i < data_size; i++) {
if (testContinue(p_ctx, i)) continue;
symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, data[i].output_options, data[i].data, data[i].length, debug);
strcpy(symbol->outfile, data[i].outfile);
ret = ZBarcode_Encode_and_Print(symbol, TU(data[i].data), length, 0);
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_and_Print(%d) ret %d != %d (%s)\n",
i, data[i].symbology, ret, data[i].ret, symbol->errtxt);
if (ret < ZINT_ERROR) {
const int expected_size = (int) strlen(data[i].expected);
assert_nonnull(symbol->memfile, "i:%d memfile NULL (%s)\n", i, symbol->errtxt);
assert_equal(symbol->memfile_size, expected_size, "i:%d memfile_size %d != %d (%s)\n",
i, symbol->memfile_size, expected_size, symbol->errtxt);
ret = memcmp(symbol->memfile, data[i].expected, symbol->memfile_size);
assert_zero(ret, "i:%d memcmp() %d != 0\n", i, ret);
} else {
assert_null(symbol->memfile, "i:%d memfile != NULL (%s)\n", i, symbol->errtxt);
assert_zero(symbol->memfile_size, "i:%d memfile_size != 0 (%s)\n", i, symbol->errtxt);
}
ZBarcode_Delete(symbol);
}
testFinish();
}
#ifndef _WIN32
extern FILE *fmemopen(void *buf, size_t size, const char *mode);
#endif
static void test_putsf(const testCtx *const p_ctx) {
int debug = p_ctx->debug;
struct item {
const char *prefix;
int dp;
float arg;
const char *locale;
const char *expected;
};
/* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
struct item data[] = {
/* 0*/ { "", 2, 1234.123, "", "1234.12" },
/* 1*/ { "", 3, 1234.123, "", "1234.123" },
/* 2*/ { "prefix ", 4, 1234.123, "", "prefix 1234.123" },
/* 3*/ { "", 2, -1234.126, "", "-1234.13" },
/* 4*/ { "", 2, 1234.1, "", "1234.1" },
/* 5*/ { "", 3, 1234.1, "", "1234.1" },
/* 6*/ { "", 4, 1234.1, "", "1234.1" },
/* 7*/ { "", 2, 1234.0, "", "1234" },
/* 8*/ { "", 2, -1234.0, "", "-1234" },
/* 9*/ { "", 3, 1234.1234, "de_DE.UTF-8", "1234.123" },
/* 10*/ { "", 4, -1234.1234, "de_DE.UTF-8", "-1234.1234" },
/* 11*/ { "prefix ", 4, -1234.1234, "de_DE.UTF-8", "prefix -1234.1234" },
};
int data_size = ARRAY_SIZE(data);
int i, j;
struct zint_symbol symbol_data = {0};
struct zint_symbol *const symbol = &symbol_data;
struct filemem fm;
struct filemem *const fmp = &fm;
#ifndef _WIN32
FILE *fp;
char buf[512] = {0}; /* Suppress clang-16/17 run-time exception MemorySanitizer: use-of-uninitialized-value */
#endif
testStart("test_putsf");
for (j = 0; j < 2; j++) { /* 1st `memfile`, then file */
#ifdef _WIN32
if (j == 1) break; /* Skip file test on Windows */
#endif
for (i = 0; i < data_size; i++) {
const char *locale = NULL;
int expected_size;
if (testContinue(p_ctx, i)) continue;
ZBarcode_Reset(symbol);
if (j == 1) {
#ifndef _WIN32
buf[0] = '\0';
fp = fmemopen(buf, sizeof(buf), "w");
assert_nonnull(fp, "%d: fmemopen fail (%d, %s)\n", i, errno, strerror(errno));
#endif
} else {
symbol->output_options |= BARCODE_MEMORY_FILE;
}
assert_nonzero(fm_open(fmp, symbol, "w"), "i:%d: fm_open fail (%d, %s)\n", i, fmp->err, strerror(fmp->err));
if (j == 1) {
#ifndef _WIN32
/* Hack in `fmemopen()` fp */
assert_zero(fclose(fmp->fp), "i:%d fclose(fmp->fp) fail (%d, %s)\n", i, errno, strerror(errno));
fmp->fp = fp;
#endif
}
if (data[i].locale && data[i].locale[0]) {
locale = setlocale(LC_ALL, data[i].locale);
if (!locale) { /* May not be available - warn unless quiet mode */
if (!(debug & ZINT_DEBUG_TEST_LESS_NOISY)) {
printf("i:%d: Warning: locale \"%s\" not available\n", i, data[i].locale);
}
}
}
fm_putsf(data[i].prefix, data[i].dp, data[i].arg, fmp);
assert_nonzero(fm_close(fmp, symbol), "i:%d: fm_close fail (%d, %s)\n", i, fmp->err, strerror(fmp->err));
if (locale) {
assert_nonnull(setlocale(LC_ALL, locale), "i:%d: setlocale(%s) restore fail (%d, %s)\n",
i, locale, errno, strerror(errno));
}
if (j == 1) {
#ifndef _WIN32
assert_zero(strcmp(buf, data[i].expected), "%d: strcmp(%s, %s) != 0\n", i, buf, data[i].expected);
#endif
} else {
expected_size = (int) strlen(data[i].expected);
assert_equal(symbol->memfile_size, expected_size, "i:%d: memfile_size %d != expected_size %d\n",
i, symbol->memfile_size, expected_size);
assert_nonnull(symbol->memfile, "i:%d memfile NULL\n", i);
assert_zero(memcmp(symbol->memfile, data[i].expected, expected_size), "i:%d: memcmp(%.*s, %.*s) != 0\n",
i, symbol->memfile_size, symbol->memfile, expected_size, data[i].expected);
}
ZBarcode_Clear(symbol);
}
}
testFinish();
}
static void test_printf(const testCtx *const p_ctx) {
int debug = p_ctx->debug;
int ret;
int j;
struct zint_symbol symbol_data = {0};
struct zint_symbol *const symbol = &symbol_data;
struct filemem fm;
struct filemem *const fmp = &fm;
const char outfile[] = "test_printf.tst";
unsigned char filebuf[32768];
int filebuf_size;
const char fmt1[] = "\n%s%04d\n\032\nwow\n\r\n%.2s\n"; /* '\032' SUB (^Z) */
const char expected1[] = "\ngosh0123\n\032\nwow\n\r\nge\n";
#ifdef _WIN32
/* On Windows, non-binary (i.e. text) files, LF -> LF+CR (note, actual files only, not memfiles) */
const char expected1_text_file[] = "\r\ngosh0123\r\n\032\r\nwow\r\n\r\r\nge\r\n";
#endif
const char *expected;
int expected_size;
(void)debug;
testStart("test_printf");
for (j = 0; j < 2; j++) { /* 1st memfile, then file */
ZBarcode_Reset(symbol);
/* Binary */
expected = expected1;
if (j == 1) {
strcpy(symbol->outfile, outfile);
} else {
symbol->output_options |= BARCODE_MEMORY_FILE;
}
ret = fm_open(fmp, symbol, "wb");
assert_equal(ret, 1, "fm_open ret %d != 1\n", ret);
ret = fm_printf(fmp, fmt1, "gosh", 123, "gee");
assert_equal(ret, 1, "fm_printf ret %d != 1\n", ret);
ret = fm_close(fmp, symbol);
assert_equal(ret, 1, "fm_close ret %d != 1\n", ret);
expected_size = (int) strlen(expected);
if (j == 1) {
ret = testUtilReadFile(symbol->outfile, filebuf, sizeof(filebuf), &filebuf_size);
assert_zero(ret, "testUtilReadFile(%s) %d != 0\n", symbol->outfile, ret);
assert_equal((int) filebuf_size, expected_size, "filebuf_size %d != %d\n", filebuf_size, expected_size);
assert_zero(memcmp(filebuf, expected, filebuf_size), "memcmp(%.*s, %s) != 0\n",
filebuf_size, filebuf, expected);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "testUtilRemove(%s) != 0\n", symbol->outfile);
}
} else {
assert_nonnull(symbol->memfile, "memfile NULL (%d: %s)\n", fmp->err, strerror(fmp->err));
assert_equal(symbol->memfile_size, expected_size, "mempos %d != %d\n",
symbol->memfile_size, expected_size);
assert_zero(memcmp(symbol->memfile, expected, symbol->memfile_size), "memcmp(%.*s, %s) != 0\n",
symbol->memfile_size, symbol->memfile, expected);
}
/* Non-binary */
expected = expected1;
if (j == 1) {
strcpy(symbol->outfile, outfile);
#ifdef _WIN32
expected = expected1_text_file;
#endif
} else {
symbol->output_options |= BARCODE_MEMORY_FILE;
}
ret = fm_open(fmp, symbol, "w");
assert_equal(ret, 1, "fm_open ret %d != 1\n", ret);
ret = fm_printf(fmp, fmt1, "gosh", 123, "gee");
assert_equal(ret, 1, "fm_printf ret %d != 1\n", ret);
ret = fm_close(fmp, symbol);
assert_equal(ret, 1, "fm_close ret %d != 1\n", ret);
expected_size = (int) strlen(expected);
if (j == 1) {
ret = testUtilReadFile(symbol->outfile, filebuf, sizeof(filebuf), &filebuf_size);
assert_zero(ret, "testUtilReadFile(%s) %d != 0\n", symbol->outfile, ret);
assert_equal((int) filebuf_size, expected_size, "filebuf_size %d != %d\n", filebuf_size, expected_size);
assert_zero(memcmp(filebuf, expected, filebuf_size), "memcmp(%.*s, %s) != 0\n",
filebuf_size, filebuf, expected);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "testUtilRemove(%s) != 0\n", symbol->outfile);
}
} else {
assert_nonnull(symbol->memfile, "mem NULL (%d: %s)\n", fmp->err, strerror(fmp->err));
assert_equal(symbol->memfile_size, expected_size, "mempos %d != %d\n",
symbol->memfile_size, expected_size);
assert_zero(memcmp(symbol->memfile, expected, symbol->memfile_size), "memcmp(%.*s, %s) != 0\n",
symbol->memfile_size, symbol->memfile, expected);
}
ZBarcode_Clear(symbol);
}
testFinish();
}
static void test_seek(const testCtx *const p_ctx) {
int debug = p_ctx->debug;
int ret;
int j;
struct zint_symbol symbol_data = {0};
struct zint_symbol *const symbol = &symbol_data;
struct filemem fm;
struct filemem *const fmp = &fm;
const char outfile[] = "test_seek.tst";
(void)debug;
testStart("test_seek");
for (j = 0; j < 2; j++) { /* 1st memfile, then file */
ZBarcode_Reset(symbol);
if (j == 1) {
strcpy(symbol->outfile, outfile);
} else {
symbol->output_options |= BARCODE_MEMORY_FILE;
}
ret = fm_open(fmp, symbol, "wb");
assert_equal(ret, 1, "j:%d fm_open ret %d != 1\n", j, ret);
ret = fm_puts("1234567890", fmp);
assert_equal(ret, 1, "j:%d fm_puts ret %d != 1\n", j, ret);
if (j != 1) {
assert_nonnull(fmp->mem, "mem NULL (%d: %s)\n", fmp->err, strerror(fmp->err));
assert_equal(fmp->mempos, 10, "mempos %d != 10\n", (int) fmp->mempos);
assert_zero(memcmp(fmp->mem, "1234567890", fmp->mempos), "memcmp fail\n");
}
ret = fm_seek(fmp, -10, SEEK_CUR);
assert_equal(ret, 1, "j:%d fm_seek ret %d != 1 (%d: %s)\n", j, ret, fmp->err, strerror(fmp->err));
ret = fm_error(fmp);
assert_zero(ret, "j:%d fm_error ret %d != 0\n", j, ret);
ret = (int) fm_tell(fmp);
assert_zero(ret, "j:%d fm_tell ret %d != 0\n", j, ret);
ret = fm_seek(fmp, 0, SEEK_END);
assert_equal(ret, 1, "j:%d fm_seek ret %d != 1\n", j, ret);
ret = fm_error(fmp);
assert_zero(ret, "j:%d fm_error ret %d != 0\n", j, ret);
ret = (int) fm_tell(fmp);
assert_equal(ret, 10, "j:%d fm_tell ret %d != 10\n", j, ret);
ret = fm_seek(fmp, -1, SEEK_SET);
assert_zero(ret, "j:%d fm_seek ret %d != 1\n", j, ret);
assert_equal(fmp->err, EINVAL, "j:%d fmp->err %d (%s) != EINVAL\n", j, fmp->err, strerror(fmp->err));
ret = fm_close(fmp, symbol);
assert_zero(ret, "j:%d fm_close ret %d != 0\n", j, ret);
assert_equal(fmp->err, EINVAL, "j:%d fmp->err %d (%s) != EINVAL\n", j, fmp->err, strerror(fmp->err));
if (j == 1) {
assert_zero(testUtilRemove(symbol->outfile), "testUtilRemove(%s) != 0\n", symbol->outfile);
}
ret = fm_open(fmp, symbol, "wb");
assert_equal(ret, 1, "j:%d fm_open ret %d != 1\n", j, ret);
ret = fm_seek(fmp, LONG_MAX, SEEK_CUR);
if (j == 1) { /* May work on some file systems */
if (ret == 0) {
assert_equal(fmp->err, EINVAL, "j:%d fmp->err %d (%s) != EINVAL\n", j, fmp->err, strerror(fmp->err));
}
} else {
assert_zero(ret, "j:%d fm_seek ret %d != 0\n", j, ret);
assert_equal(fmp->err, EINVAL, "j:%d fmp->err %d (%s) != EINVAL\n", j, fmp->err, strerror(fmp->err));
}
ret = fm_close(fmp, symbol);
if (j == 1) { /* See above */
if (ret == 0) {
assert_equal(fmp->err, EINVAL, "j:%d fmp->err %d (%s) != EINVAL\n", j, fmp->err, strerror(fmp->err));
}
} else {
assert_zero(ret, "j:%d fm_close ret %d != 0\n", j, ret);
assert_equal(fmp->err, EINVAL, "j:%d fmp->err %d (%s) != EINVAL\n", j, fmp->err, strerror(fmp->err));
}
if (j == 1) {
assert_zero(testUtilRemove(symbol->outfile), "testUtilRemove(%s) != 0\n", symbol->outfile);
}
ZBarcode_Clear(symbol);
}
testFinish();
}
static void test_large(const testCtx *const p_ctx) {
int debug = p_ctx->debug;
int ret;
struct zint_symbol *symbol = NULL;
char data[] = "1";
int expected_size = 354879;
(void)debug;
testStart("test_large");
symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
symbol->symbology = BARCODE_HANXIN;
symbol->output_options |= BARCODE_MEMORY_FILE;
strcpy(symbol->outfile, "out.gif"); /* Use GIF in case ZINT_NO_PNG */
symbol->option_2 = 84;
symbol->scale = 10.0f; /* Could go up to 86.5 (pixel buffer 0x3FB913B1, file size 8868579) but very very slow */
ret = ZBarcode_Encode_and_Print(symbol, TU(data), -1, 0);
assert_zero(ret, "ZBarcode_Encode_and_Print ret %d != 0 (%s)\n", ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "memfile NULL (%s)\n", symbol->errtxt);
assert_equal(symbol->memfile_size, expected_size, "memfile_size %d != expected %d\n",
symbol->memfile_size, expected_size);
symbol->scale = 87.0f; /* Too large (pixel buffer > 1GB) */
ret = ZBarcode_Print(symbol, 0);
assert_equal(ret, ZINT_ERROR_MEMORY, "ZBarcode_Print ret %d != ZINT_ERROR_MEMORY (%s)\n", ret, symbol->errtxt);
ZBarcode_Delete(symbol);
testFinish();
}
int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func */
{ "test_svg", test_svg },
{ "test_putsf", test_putsf },
{ "test_printf", test_printf },
{ "test_seek", test_seek },
{ "test_large", test_large },
};
testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
testReport();
return 0;
}
/* vim: set ts=4 sw=4 et : */

View File

@ -191,6 +191,8 @@ static void test_print(const testCtx *const p_ctx) {
char expected_file[4096]; char expected_file[4096];
char escaped[1024]; char escaped[1024];
int escaped_size = 1024; int escaped_size = 1024;
unsigned char filebuf[32768];
int filebuf_size;
const char *const have_identify = testUtilHaveIdentify(); const char *const have_identify = testUtilHaveIdentify();
@ -268,9 +270,25 @@ static void test_print(const testCtx *const p_ctx) {
ret = testUtilCmpBins(symbol->outfile, expected_file); ret = testUtilCmpBins(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
ret = testUtilReadFile(symbol->outfile, filebuf, sizeof(filebuf), &filebuf_size); /* For BARCODE_MEMORY_FILE */
assert_zero(ret, "i:%d %s testUtilReadFile(%s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile); assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
} }
symbol->output_options |= BARCODE_MEMORY_FILE;
ret = ZBarcode_Print(symbol, 0);
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0 (%s)\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "i:%d %s memfile NULL\n", i, testUtilBarcodeName(data[i].symbology));
assert_equal(symbol->memfile_size, filebuf_size, "i:%d %s memfile_size %d != %d\n",
i, testUtilBarcodeName(data[i].symbology), symbol->memfile_size, filebuf_size);
assert_zero(memcmp(symbol->memfile, filebuf, symbol->memfile_size), "i:%d %s memcmp(memfile, filebuf) != 0\n",
i, testUtilBarcodeName(data[i].symbology));
}
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
} }

View File

@ -31,7 +31,6 @@
#include "testcommon.h" #include "testcommon.h"
#include "../output.h" #include "../output.h"
#include <locale.h>
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
#include <direct.h> #include <direct.h>
@ -411,82 +410,6 @@ static void test_fopen(const testCtx *const p_ctx) {
testFinish(); testFinish();
} }
#ifndef _WIN32
extern FILE *fmemopen(void *buf, size_t size, const char *mode);
#endif
static void test_out_putsf(const testCtx *const p_ctx) {
int debug = p_ctx->debug;
struct item {
const char *prefix;
int dp;
float arg;
const char *locale;
const char *expected;
};
/* s/\/\*[ 0-9]*\*\//\=printf("\/\*%3d*\/", line(".") - line("'<")): */
struct item data[] = {
/* 0*/ { "", 2, 1234.123, "", "1234.12" },
/* 1*/ { "", 3, 1234.123, "", "1234.123" },
/* 2*/ { "prefix ", 4, 1234.123, "", "prefix 1234.123" },
/* 3*/ { "", 2, -1234.126, "", "-1234.13" },
/* 4*/ { "", 2, 1234.1, "", "1234.1" },
/* 5*/ { "", 3, 1234.1, "", "1234.1" },
/* 6*/ { "", 4, 1234.1, "", "1234.1" },
/* 7*/ { "", 2, 1234.0, "", "1234" },
/* 8*/ { "", 2, -1234.0, "", "-1234" },
/* 9*/ { "", 3, 1234.1234, "de_DE.UTF-8", "1234.123" },
/* 10*/ { "", 4, -1234.1234, "de_DE.UTF-8", "-1234.1234" },
/* 11*/ { "prefix ", 4, -1234.1234, "de_DE.UTF-8", "prefix -1234.1234" },
};
int data_size = ARRAY_SIZE(data);
int i;
FILE *fp;
char buf[512] = {0}; /* Suppress clang-16/17 run-time exception MemorySanitizer: use-of-uninitialized-value */
testStart("test_out_putsf");
#ifdef _WIN32
(void)i; (void)fp; (void)buf;
testSkip("Test not implemented on Windows");
#else
for (i = 0; i < data_size; i++) {
const char *locale = NULL;
if (testContinue(p_ctx, i)) continue;
buf[0] = '\0';
fp = fmemopen(buf, sizeof(buf), "w");
assert_nonnull(fp, "%d: fmemopen fail (%d, %s)\n", i, errno, strerror(errno));
if (data[i].locale && data[i].locale[0]) {
locale = setlocale(LC_ALL, data[i].locale);
if (!locale) { /* May not be available - warn unless quiet mode */
if (!(debug & ZINT_DEBUG_TEST_LESS_NOISY)) {
printf("%d: Warning: locale \"%s\" not available\n", i, data[i].locale);
}
}
}
out_putsf(data[i].prefix, data[i].dp, data[i].arg, fp);
assert_zero(fclose(fp), "%d: fclose fail (%d, %s)\n", i, errno, strerror(errno));
if (locale) {
assert_nonnull(setlocale(LC_ALL, locale), "%d: setlocale(%s) restore fail (%d, %s)\n",
i, locale, errno, strerror(errno));
}
assert_zero(strcmp(buf, data[i].expected), "%d: strcmp(%s, %s) != 0\n", i, buf, data[i].expected);
}
testFinish();
#endif /* _WIN32 */
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func */ testFunction funcs[] = { /* name, func */
@ -496,7 +419,6 @@ int main(int argc, char *argv[]) {
{ "test_quiet_zones", test_quiet_zones }, { "test_quiet_zones", test_quiet_zones },
{ "test_set_whitespace_offsets", test_set_whitespace_offsets }, { "test_set_whitespace_offsets", test_set_whitespace_offsets },
{ "test_fopen", test_fopen }, { "test_fopen", test_fopen },
{ "test_out_putsf", test_out_putsf },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -65,6 +65,8 @@ static void test_print(const testCtx *const p_ctx) {
char expected_file[4096]; char expected_file[4096];
char escaped[1024]; char escaped[1024];
int escaped_size = 1024; int escaped_size = 1024;
unsigned char filebuf[36864];
int filebuf_size;
const char *const have_identify = testUtilHaveIdentify(); const char *const have_identify = testUtilHaveIdentify();
@ -134,9 +136,25 @@ static void test_print(const testCtx *const p_ctx) {
ret = testUtilCmpBins(symbol->outfile, expected_file); ret = testUtilCmpBins(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
ret = testUtilReadFile(symbol->outfile, filebuf, sizeof(filebuf), &filebuf_size); /* For BARCODE_MEMORY_FILE */
assert_zero(ret, "i:%d %s testUtilReadFile(%s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile); assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
} }
symbol->output_options |= BARCODE_MEMORY_FILE;
ret = ZBarcode_Print(symbol, 0);
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0 (%s)\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "i:%d %s memfile NULL\n", i, testUtilBarcodeName(data[i].symbology));
assert_equal(symbol->memfile_size, filebuf_size, "i:%d %s memfile_size %d != %d\n",
i, testUtilBarcodeName(data[i].symbology), symbol->memfile_size, filebuf_size);
assert_zero(memcmp(symbol->memfile, filebuf, symbol->memfile_size), "i:%d %s memcmp(memfile, filebuf) != 0\n",
i, testUtilBarcodeName(data[i].symbology));
}
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
} }

View File

@ -144,8 +144,8 @@ static void test_options(const testCtx *const p_ctx) {
/* 9*/ { BARCODE_PDF417, -1, 10, -1, 0, { 0, 0, "" }, "12345", 0, 0, 3, 239, "", -1 }, /* ECC auto-set to 2, cols 10 */ /* 9*/ { BARCODE_PDF417, -1, 10, -1, 0, { 0, 0, "" }, "12345", 0, 0, 3, 239, "", -1 }, /* ECC auto-set to 2, cols 10 */
/* 10*/ { BARCODE_PDF417, 9, -1, -1, 0, { 0, 0, "" }, "12345", ZINT_WARN_INVALID_OPTION, 0, 6, 103, "Warning 460: Security value out of range", -1 }, /* Invalid ECC, auto-set */ /* 10*/ { BARCODE_PDF417, 9, -1, -1, 0, { 0, 0, "" }, "12345", ZINT_WARN_INVALID_OPTION, 0, 6, 103, "Warning 460: Security value out of range", -1 }, /* Invalid ECC, auto-set */
/* 11*/ { BARCODE_PDF417, -1, 31, -1, 0, { 0, 0, "" }, "12345", ZINT_WARN_INVALID_OPTION, 0, 6, 103, "Warning 461: Number of columns out of range (1 to 30)", 0 }, /* Invalid cols, auto-set */ /* 11*/ { BARCODE_PDF417, -1, 31, -1, 0, { 0, 0, "" }, "12345", ZINT_WARN_INVALID_OPTION, 0, 6, 103, "Warning 461: Number of columns out of range (1 to 30)", 0 }, /* Invalid cols, auto-set */
/* 12*/ { BARCODE_PDF417, -1, -1, 2, 0, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, 0, 0, 0, "Error 466: Number of rows out of range (3 to 90)", -1 }, /* Invalid rows, error */ /* 12*/ { BARCODE_PDF417, -1, -1, 2, 0, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, ZINT_ERROR_INVALID_OPTION, 0, 0, "Error 466: Number of rows out of range (3 to 90)", -1 }, /* Invalid rows, error */
/* 13*/ { BARCODE_PDF417, -1, -1, 91, 0, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, 0, 0, 0, "Error 466: Number of rows out of range (3 to 90)", -1 }, /* Invalid rows, error */ /* 13*/ { BARCODE_PDF417, -1, -1, 91, 0, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, ZINT_ERROR_INVALID_OPTION, 0, 0, "Error 466: Number of rows out of range (3 to 90)", -1 }, /* Invalid rows, error */
/* 14*/ { BARCODE_PDF417, 9, -1, -1, WARN_FAIL_ALL, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 460: Security value out of range", -1 }, /* Invalid ECC */ /* 14*/ { BARCODE_PDF417, 9, -1, -1, WARN_FAIL_ALL, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 460: Security value out of range", -1 }, /* Invalid ECC */
/* 15*/ { BARCODE_PDF417, -1, 31, -1, WARN_FAIL_ALL, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 461: Number of columns out of range (1 to 30)", -1 }, /* Invalid cols */ /* 15*/ { BARCODE_PDF417, -1, 31, -1, WARN_FAIL_ALL, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 461: Number of columns out of range (1 to 30)", -1 }, /* Invalid cols */
/* 16*/ { BARCODE_PDF417, -1, 30, 31, 0, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 475: Columns x rows out of range (1 to 928)", -1 }, /* Rows * cols (930) > 928 */ /* 16*/ { BARCODE_PDF417, -1, 30, 31, 0, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 475: Columns x rows out of range (1 to 928)", -1 }, /* Rows * cols (930) > 928 */
@ -160,11 +160,11 @@ static void test_options(const testCtx *const p_ctx) {
/* 25*/ { BARCODE_MICROPDF417, -1, 5, -1, WARN_FAIL_ALL, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 468: Specified width out of range", -1 }, /* Invalid cols */ /* 25*/ { BARCODE_MICROPDF417, -1, 5, -1, WARN_FAIL_ALL, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 468: Specified width out of range", -1 }, /* Invalid cols */
/* 26*/ { BARCODE_MICROPDF417, -1, 5, 3, 0, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 476: Cannot specify rows for MicroPDF417", -1 }, /* Rows option not available */ /* 26*/ { BARCODE_MICROPDF417, -1, 5, 3, 0, { 0, 0, "" }, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0, "Error 476: Cannot specify rows for MicroPDF417", -1 }, /* Rows option not available */
/* 27*/ { BARCODE_MICROPDF417, -1, 1, -1, 0, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM", ZINT_WARN_INVALID_OPTION, 0, 17, 55, "Warning 469: Specified symbol size too small for data", -1 }, /* Cols 1 too small, auto-upped to 2 with warning */ /* 27*/ { BARCODE_MICROPDF417, -1, 1, -1, 0, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM", ZINT_WARN_INVALID_OPTION, 0, 17, 55, "Warning 469: Specified symbol size too small for data", -1 }, /* Cols 1 too small, auto-upped to 2 with warning */
/* 28*/ { BARCODE_MICROPDF417, -1, 1, -1, WARN_FAIL_ALL, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM", ZINT_ERROR_INVALID_OPTION, 0, 0, 0, "Error 469: Specified symbol size too small for data", -1 }, /* Cols 1 too small */ /* 28*/ { BARCODE_MICROPDF417, -1, 1, -1, WARN_FAIL_ALL, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLM", ZINT_ERROR_INVALID_OPTION, ZINT_ERROR_INVALID_OPTION, 0, 0, "Error 469: Specified symbol size too small for data", -1 }, /* Cols 1 too small */
/* 29*/ { BARCODE_MICROPDF417, -1, 2, -1, 0, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWX", ZINT_WARN_INVALID_OPTION, 0, 15, 99, "Warning 470: Specified symbol size too small for data", -1 }, /* Cols 2 too small, auto-upped to 4 with warning */ /* 29*/ { BARCODE_MICROPDF417, -1, 2, -1, 0, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWX", ZINT_WARN_INVALID_OPTION, 0, 15, 99, "Warning 470: Specified symbol size too small for data", -1 }, /* Cols 2 too small, auto-upped to 4 with warning */
/* 30*/ { BARCODE_MICROPDF417, -1, 2, -1, WARN_FAIL_ALL, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWX", ZINT_ERROR_INVALID_OPTION, 0, 0, 0, "Error 470: Specified symbol size too small for data", -1 }, /* Cols 2 too small */ /* 30*/ { BARCODE_MICROPDF417, -1, 2, -1, WARN_FAIL_ALL, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWX", ZINT_ERROR_INVALID_OPTION, ZINT_ERROR_INVALID_OPTION, 0, 0, "Error 470: Specified symbol size too small for data", -1 }, /* Cols 2 too small */
/* 31*/ { BARCODE_MICROPDF417, -1, 3, -1, 0, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKL", ZINT_WARN_INVALID_OPTION, 0, 32, 99, "Warning 471: Specified symbol size too small for data", -1 }, /* Cols 3 too small, auto-upped to 4 with warning */ /* 31*/ { BARCODE_MICROPDF417, -1, 3, -1, 0, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKL", ZINT_WARN_INVALID_OPTION, 0, 32, 99, "Warning 471: Specified symbol size too small for data", -1 }, /* Cols 3 too small, auto-upped to 4 with warning */
/* 32*/ { BARCODE_MICROPDF417, -1, 3, -1, WARN_FAIL_ALL, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKL", ZINT_ERROR_INVALID_OPTION, 0, 0, 0, "Error 471: Specified symbol size too small for data", -1 }, /* Cols 3 too small */ /* 32*/ { BARCODE_MICROPDF417, -1, 3, -1, WARN_FAIL_ALL, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKLMOPQRSTUVWXYZABCDEFGHIJKL", ZINT_ERROR_INVALID_OPTION, ZINT_ERROR_INVALID_OPTION, 0, 0, "Error 471: Specified symbol size too small for data", -1 }, /* Cols 3 too small */
/* 33*/ { BARCODE_PDF417, -1, 1, -1, 0, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH", ZINT_WARN_INVALID_OPTION, 0, 89, 103, "Warning 748: Columns increased from 1 to 2", -1 }, /* Cols 1 auto-upped to 2 just fits, now with warning */ /* 33*/ { BARCODE_PDF417, -1, 1, -1, 0, { 0, 0, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH", ZINT_WARN_INVALID_OPTION, 0, 89, 103, "Warning 748: Columns increased from 1 to 2", -1 }, /* Cols 1 auto-upped to 2 just fits, now with warning */
/* 34*/ { BARCODE_PDF417, -1, 1, -1, 0, { 1, 2, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH", ZINT_WARN_INVALID_OPTION, 0, 67, 120, "Warning 748: Columns increased from 1 to 3", -1 }, /* Cols 1 too small with Structured Append, used to fail, now auto-upped to 3 with warning */ /* 34*/ { BARCODE_PDF417, -1, 1, -1, 0, { 1, 2, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH", ZINT_WARN_INVALID_OPTION, 0, 67, 120, "Warning 748: Columns increased from 1 to 3", -1 }, /* Cols 1 too small with Structured Append, used to fail, now auto-upped to 3 with warning */
/* 35*/ { BARCODE_PDF417, -1, 1, -1, 0, { 1, 2, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST", ZINT_WARN_INVALID_OPTION, 0, 89, 103, "Warning 748: Columns increased from 1 to 2", -1 }, /* Cols 1 with Structured Append auto-upped to 2 just fits, now with warning */ /* 35*/ { BARCODE_PDF417, -1, 1, -1, 0, { 1, 2, "" }, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRST", ZINT_WARN_INVALID_OPTION, 0, 89, 103, "Warning 748: Columns increased from 1 to 2", -1 }, /* Cols 1 with Structured Append auto-upped to 2 just fits, now with warning */

View File

@ -239,6 +239,8 @@ static void test_print(const testCtx *const p_ctx) {
char expected_file[1024]; char expected_file[1024];
char escaped[1024]; char escaped[1024];
int escaped_size = 1024; int escaped_size = 1024;
unsigned char filebuf[32768];
int filebuf_size;
char *text; char *text;
const char *const have_identify = testUtilHaveIdentify(); const char *const have_identify = testUtilHaveIdentify();
@ -330,9 +332,25 @@ static void test_print(const testCtx *const p_ctx) {
assert_zero(ret, "i:%d %s testUtilCmpPngs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpPngs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
ret = testUtilCmpBins(symbol->outfile, expected_file); ret = testUtilCmpBins(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
ret = testUtilReadFile(symbol->outfile, filebuf, sizeof(filebuf), &filebuf_size); /* For BARCODE_MEMORY_FILE */
assert_zero(ret, "i:%d %s testUtilReadFile(%s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile); assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
} }
symbol->output_options |= BARCODE_MEMORY_FILE;
ret = ZBarcode_Print(symbol, 0);
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0 (%s)\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "i:%d %s memfile NULL\n", i, testUtilBarcodeName(data[i].symbology));
assert_equal(symbol->memfile_size, filebuf_size, "i:%d %s memfile_size %d != %d\n",
i, testUtilBarcodeName(data[i].symbology), symbol->memfile_size, filebuf_size);
assert_zero(memcmp(symbol->memfile, filebuf, symbol->memfile_size), "i:%d %s memcmp(memfile, filebuf) != 0\n",
i, testUtilBarcodeName(data[i].symbology));
}
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
} }

View File

@ -117,8 +117,9 @@ static void test_print(const testCtx *const p_ctx) {
int i, length, ret; int i, length, ret;
struct zint_symbol *symbol = NULL; struct zint_symbol *symbol = NULL;
const char *data_dir = "/backend/tests/data/eps"; const char data_dir[] = "/backend/tests/data/eps";
const char *eps = "out.eps"; const char eps[] = "out.eps";
const char memfile[] = "mem.eps";
char expected_file[1024]; char expected_file[1024];
char escaped[1024]; char escaped[1024];
int escaped_size = 1024; int escaped_size = 1024;
@ -193,7 +194,25 @@ static void test_print(const testCtx *const p_ctx) {
ret = testUtilCmpEpss(symbol->outfile, expected_file); ret = testUtilCmpEpss(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpEpss(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpEpss(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
symbol->output_options |= BARCODE_MEMORY_FILE;
ret = ZBarcode_Print(symbol, data[i].rotate_angle);
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0 (%s)\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "i:%d %s memfile NULL\n", i, testUtilBarcodeName(data[i].symbology));
assert_nonzero(symbol->memfile_size, "i:%d %s memfile_size 0\n", i, testUtilBarcodeName(data[i].symbology));
ret = testUtilWriteFile(memfile, symbol->memfile, symbol->memfile_size, "wb");
assert_zero(ret, "%d: testUtilWriteFile(%s) fail ret %d != 0\n", i, memfile, ret);
ret = testUtilCmpEpss(symbol->outfile, memfile);
assert_zero(ret, "i:%d %s testUtilCmpEpss(%s, %s) %d != 0\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, memfile, ret);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile); assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
assert_zero(testUtilRemove(memfile), "i:%d testUtilRemove(%s) != 0\n", i, memfile);
}
} }
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);

View File

@ -144,8 +144,9 @@ static void test_print(const testCtx *const p_ctx) {
int i, length, ret; int i, length, ret;
struct zint_symbol *symbol = NULL; struct zint_symbol *symbol = NULL;
const char *data_dir = "/backend/tests/data/svg"; const char data_dir[] = "/backend/tests/data/svg";
const char *svg = "out.svg"; const char svg[] = "out.svg";
const char memfile[] = "mem.eps";
char expected_file[1024]; char expected_file[1024];
char escaped[1024]; char escaped[1024];
int escaped_size = 1024; int escaped_size = 1024;
@ -240,7 +241,25 @@ static void test_print(const testCtx *const p_ctx) {
ret = testUtilCmpSvgs(symbol->outfile, expected_file); ret = testUtilCmpSvgs(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpSvgs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpSvgs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
symbol->output_options |= BARCODE_MEMORY_FILE;
ret = ZBarcode_Print(symbol, data[i].rotate_angle);
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0 (%s)\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "i:%d %s memfile NULL\n", i, testUtilBarcodeName(data[i].symbology));
assert_nonzero(symbol->memfile_size, "i:%d %s memfile_size 0\n", i, testUtilBarcodeName(data[i].symbology));
ret = testUtilWriteFile(memfile, symbol->memfile, symbol->memfile_size, "wb");
assert_zero(ret, "%d: testUtilWriteFile(%s) fail ret %d != 0\n", i, memfile, ret);
ret = testUtilCmpSvgs(symbol->outfile, memfile);
assert_zero(ret, "i:%d %s testUtilCmpSvgs(%s, %s) %d != 0\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, memfile, ret);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile); assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
assert_zero(testUtilRemove(memfile), "i:%d testUtilRemove(%s) != 0\n", i, memfile);
}
} }
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);

View File

@ -214,6 +214,8 @@ static void test_print(const testCtx *const p_ctx) {
char expected_file[1024]; char expected_file[1024];
char escaped[1024]; char escaped[1024];
int escaped_size = 1024; int escaped_size = 1024;
unsigned char filebuf[32768];
int filebuf_size;
char *text; char *text;
int have_tiffinfo = testUtilHaveTiffInfo(); int have_tiffinfo = testUtilHaveTiffInfo();
@ -301,9 +303,25 @@ static void test_print(const testCtx *const p_ctx) {
ret = testUtilCmpBins(symbol->outfile, expected_file); ret = testUtilCmpBins(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
ret = testUtilReadFile(symbol->outfile, filebuf, sizeof(filebuf), &filebuf_size); /* For BARCODE_MEMORY_FILE */
assert_zero(ret, "i:%d %s testUtilReadFile(%s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret);
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) {
assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile); assert_zero(testUtilRemove(symbol->outfile), "i:%d testUtilRemove(%s) != 0\n", i, symbol->outfile);
} }
symbol->output_options |= BARCODE_MEMORY_FILE;
ret = ZBarcode_Print(symbol, 0);
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0 (%s)\n",
i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret, symbol->errtxt);
assert_nonnull(symbol->memfile, "i:%d %s memfile NULL\n", i, testUtilBarcodeName(data[i].symbology));
assert_equal(symbol->memfile_size, filebuf_size, "i:%d %s memfile_size %d != %d\n",
i, testUtilBarcodeName(data[i].symbology), symbol->memfile_size, filebuf_size);
assert_zero(memcmp(symbol->memfile, filebuf, symbol->memfile_size), "i:%d %s memcmp(memfile, filebuf) != 0\n",
i, testUtilBarcodeName(data[i].symbology));
}
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
} }

View File

@ -1516,6 +1516,67 @@ int testUtilRmROFile(const char *filename) {
return testUtilRemove(filename); return testUtilRemove(filename);
} }
/* Read file into buffer */
int testUtilReadFile(const char *filename, unsigned char *buffer, int buffer_size, int *p_size) {
long fileLen;
size_t n;
size_t nRead = 0;
FILE *fp = testUtilOpen(filename, "rb");
if (!fp) {
return 1;
}
if (fseek(fp, 0, SEEK_END) != 0) {
(void) fclose(fp);
return 2;
}
fileLen = ftell(fp);
if (fileLen <= 0 || fileLen == LONG_MAX) {
(void) fclose(fp);
return 3;
}
if (fseek(fp, 0, SEEK_SET) != 0) {
(void) fclose(fp);
return 4;
}
if (fileLen > (long) buffer_size) {
(void) fclose(fp);
return 5;
}
do {
n = fread(buffer + nRead, 1, fileLen - nRead, fp);
if (ferror(fp)) {
(void) fclose(fp);
return 6;
}
nRead += n;
} while (!feof(fp) && (0 < n) && ((long) nRead < fileLen));
if (fclose(fp) != 0) {
return 7;
}
*p_size = (int) nRead;
return 0;
}
/* Write file from buffer */
int testUtilWriteFile(const char *filename, const unsigned char *buffer, const int buffer_size, const char *mode) {
FILE *fp = testUtilOpen(filename, mode);
if (!fp) {
return 1;
}
if (fwrite(buffer, 1, buffer_size, fp) == 0) {
(void) fclose(fp);
return 2;
}
if (fclose(fp) != 0) {
return 3;
}
return 0;
}
/* Compare 2 PNG files */ /* Compare 2 PNG files */
int testUtilCmpPngs(const char *png1, const char *png2) { int testUtilCmpPngs(const char *png1, const char *png2) {
int ret = -1; int ret = -1;
@ -3945,7 +4006,15 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in
int primary_len = (int) strlen(primary); int primary_len = (int) strlen(primary);
int maxi_len = 0; int maxi_len = 0;
if (symbol->option_2 >= 1 && symbol->option_2 <= 100) { if (symbol->option_2 >= 1 && symbol->option_2 <= 100) {
/* Suppress gcc warning null destination pointer [-Wformat-overflow=] false-positive */
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-overflow="
#endif
sprintf(maxi, "[)>\03601\035%02d", symbol->option_2 - 1); sprintf(maxi, "[)>\03601\035%02d", symbol->option_2 - 1);
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
maxi_len = (int) strlen(maxi); maxi_len = (int) strlen(maxi);
} }
#if 1 #if 1

View File

@ -57,7 +57,7 @@ extern "C" {
#define testutil_pclose(stream) _pclose(stream) #define testutil_pclose(stream) _pclose(stream)
#else #else
#include <unistd.h> #include <unistd.h>
# if defined(ZINT_IS_C89) # if defined(ZINT_IS_C89) || defined(ZINT_IS_C99)
extern FILE *popen(const char *command, const char *type); extern FILE *popen(const char *command, const char *type);
extern int pclose(FILE *stream); extern int pclose(FILE *stream);
# endif # endif
@ -174,6 +174,8 @@ int testUtilRmDir(const char *dirname);
int testUtilRename(const char *oldpath, const char *newpath); int testUtilRename(const char *oldpath, const char *newpath);
int testUtilCreateROFile(const char *filename); int testUtilCreateROFile(const char *filename);
int testUtilRmROFile(const char *filename); int testUtilRmROFile(const char *filename);
int testUtilReadFile(const char *filename, unsigned char *buffer, int buffer_size, int *p_size);
int testUtilWriteFile(const char *filename, const unsigned char *buffer, const int buffer_size, const char *mode);
int testUtilCmpPngs(const char *file1, const char *file2); int testUtilCmpPngs(const char *file1, const char *file2);
int testUtilCmpTxts(const char *txt1, const char *txt2); int testUtilCmpTxts(const char *txt1, const char *txt2);

View File

@ -34,11 +34,8 @@
#include <errno.h> #include <errno.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#endif
#include "common.h" #include "common.h"
#include "filemem.h"
#include "output.h" #include "output.h"
#include "tif.h" #include "tif.h"
#include "tif_lzw.h" #include "tif_lzw.h"
@ -97,7 +94,8 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
int strip_row; int strip_row;
unsigned int bytes_put; unsigned int bytes_put;
long total_bytes_put; long total_bytes_put;
FILE *tif_file; struct filemem fm;
struct filemem *const fmp = &fm;
const unsigned char *pb; const unsigned char *pb;
int compression = TIF_NO_COMPRESSION; int compression = TIF_NO_COMPRESSION;
tif_lzw_state lzw_state; tif_lzw_state lzw_state;
@ -315,19 +313,11 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} }
/* Open output file in binary mode */ /* Open output file in binary mode */
if (output_to_stdout) { if (!fm_open(fmp, symbol, "wb")) {
#ifdef _MSC_VER sprintf(symbol->errtxt, "672: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
sprintf(symbol->errtxt, "671: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_ACCESS;
}
#endif
tif_file = stdout;
} else {
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; return ZINT_ERROR_FILE_ACCESS;
} }
if (!output_to_stdout) {
compression = TIF_LZW; compression = TIF_LZW;
tif_lzw_init(&lzw_state); tif_lzw_init(&lzw_state);
} }
@ -341,7 +331,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
header.identity = 42; header.identity = 42;
header.offset = (uint32_t) free_memory; header.offset = (uint32_t) free_memory;
fwrite(&header, sizeof(tiff_header_t), 1, tif_file); fm_write(&header, sizeof(tiff_header_t), 1, fmp);
total_bytes_put = sizeof(tiff_header_t); total_bytes_put = sizeof(tiff_header_t);
/* Pixel data */ /* Pixel data */
@ -387,14 +377,14 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
if (strip_row == rows_per_strip || (strip == strip_count - 1 && strip_row == rows_last_strip)) { if (strip_row == rows_per_strip || (strip == strip_count - 1 && strip_row == rows_last_strip)) {
/* End of strip */ /* End of strip */
if (compression == TIF_LZW) { if (compression == TIF_LZW) {
file_pos = ftell(tif_file); file_pos = fm_tell(fmp);
if (!tif_lzw_encode(&lzw_state, tif_file, strip_buf, bytes_put)) { /* Only fails if can't malloc */ if (!tif_lzw_encode(&lzw_state, fmp, strip_buf, bytes_put)) { /* Only fails if can't malloc */
tif_lzw_cleanup(&lzw_state); tif_lzw_cleanup(&lzw_state);
(void) fclose(tif_file); /* Only use LZW if not STDOUT, so ok to close */ (void) fm_close(fmp, symbol);
strcpy(symbol->errtxt, "673: Failed to malloc LZW hash table"); strcpy(symbol->errtxt, "673: Failed to malloc LZW hash table");
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
bytes_put = ftell(tif_file) - file_pos; bytes_put = fm_tell(fmp) - file_pos;
if (bytes_put != strip_bytes[strip]) { if (bytes_put != strip_bytes[strip]) {
const int diff = bytes_put - strip_bytes[strip]; const int diff = bytes_put - strip_bytes[strip];
strip_bytes[strip] = bytes_put; strip_bytes[strip] = bytes_put;
@ -403,7 +393,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} }
} }
} else { } else {
fwrite(strip_buf, 1, bytes_put, tif_file); fm_write(strip_buf, 1, bytes_put, fmp);
} }
strip++; strip++;
total_bytes_put += bytes_put; total_bytes_put += bytes_put;
@ -415,27 +405,25 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} }
if (total_bytes_put & 1) { if (total_bytes_put & 1) {
putc(0, tif_file); /* IFD must be on word boundary */ fm_putc(0, fmp); /* IFD must be on word boundary */
total_bytes_put++; total_bytes_put++;
} }
if (compression == TIF_LZW) { if (compression == TIF_LZW) {
tif_lzw_cleanup(&lzw_state); tif_lzw_cleanup(&lzw_state);
file_pos = ftell(tif_file); file_pos = fm_tell(fmp);
fseek(tif_file, 4, SEEK_SET); fm_seek(fmp, 4, SEEK_SET);
free_memory = file_pos; free_memory = file_pos;
temp32 = (uint32_t) free_memory; temp32 = (uint32_t) free_memory;
/* Shouldn't happen as `free_memory` checked above to be <= 0xffff0000 & should only decrease */ /* Shouldn't happen as `free_memory` checked above to be <= 0xffff0000 & should only decrease */
if (free_memory != temp32 || (long) free_memory != file_pos) { if (free_memory != temp32 || (long) free_memory != file_pos) {
strcpy(symbol->errtxt, "982: Output file size too big"); strcpy(symbol->errtxt, "982: Output file size too big");
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(tif_file);
}
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
fwrite(&temp32, 4, 1, tif_file); fm_write(&temp32, 4, 1, fmp);
fseek(tif_file, file_pos, SEEK_SET); fm_seek(fmp, file_pos, SEEK_SET);
} }
/* Image File Directory */ /* Image File Directory */
@ -504,7 +492,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
tags[entries++].offset = strip_bytes[0]; tags[entries++].offset = strip_bytes[0];
} else { } else {
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = free_memory; tags[entries++].offset = (uint32_t) free_memory;
free_memory += strip_count * 4; free_memory += strip_count * 4;
} }
@ -512,14 +500,14 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
tags[entries].type = 5; /* RATIONAL */ tags[entries].type = 5; /* RATIONAL */
tags[entries].count = 1; tags[entries].count = 1;
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = free_memory; tags[entries++].offset = (uint32_t) free_memory;
free_memory += 8; free_memory += 8;
tags[entries].tag = 0x011b; /* YResolution */ tags[entries].tag = 0x011b; /* YResolution */
tags[entries].type = 5; /* RATIONAL */ tags[entries].type = 5; /* RATIONAL */
tags[entries].count = 1; tags[entries].count = 1;
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = free_memory; tags[entries++].offset = (uint32_t) free_memory;
free_memory += 8; free_memory += 8;
tags[entries].tag = 0x0128; /* ResolutionUnit */ tags[entries].tag = 0x0128; /* ResolutionUnit */
@ -552,14 +540,14 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
tags[update_offsets[i]].offset += ifd_size; tags[update_offsets[i]].offset += ifd_size;
} }
fwrite(&entries, sizeof(entries), 1, tif_file); fm_write(&entries, sizeof(entries), 1, fmp);
fwrite(&tags, sizeof(tiff_tag_t), entries, tif_file); fm_write(&tags, sizeof(tiff_tag_t), entries, fmp);
fwrite(&offset, sizeof(offset), 1, tif_file); fm_write(&offset, sizeof(offset), 1, fmp);
total_bytes_put += ifd_size; total_bytes_put += ifd_size;
if (samples_per_pixel > 2) { if (samples_per_pixel > 2) {
for (i = 0; i < samples_per_pixel; i++) { for (i = 0; i < samples_per_pixel; i++) {
fwrite(&bits_per_sample, sizeof(bits_per_sample), 1, tif_file); fm_write(&bits_per_sample, sizeof(bits_per_sample), 1, fmp);
} }
total_bytes_put += sizeof(bits_per_sample) * samples_per_pixel; total_bytes_put += sizeof(bits_per_sample) * samples_per_pixel;
} }
@ -567,66 +555,59 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
if (strip_count != 1) { if (strip_count != 1) {
/* Strip offsets */ /* Strip offsets */
for (i = 0; i < strip_count; i++) { for (i = 0; i < strip_count; i++) {
fwrite(&strip_offset[i], 4, 1, tif_file); fm_write(&strip_offset[i], 4, 1, fmp);
} }
/* Strip byte lengths */ /* Strip byte lengths */
for (i = 0; i < strip_count; i++) { for (i = 0; i < strip_count; i++) {
fwrite(&strip_bytes[i], 4, 1, tif_file); fm_write(&strip_bytes[i], 4, 1, fmp);
} }
total_bytes_put += strip_count * 8; total_bytes_put += strip_count * 8;
} }
/* XResolution */ /* XResolution */
temp32 = symbol->dpmm ? symbol->dpmm : 72; temp32 = symbol->dpmm ? symbol->dpmm : 72;
fwrite(&temp32, 4, 1, tif_file); fm_write(&temp32, 4, 1, fmp);
temp32 = symbol->dpmm ? 10 /*cm*/ : 1; temp32 = symbol->dpmm ? 10 /*cm*/ : 1;
fwrite(&temp32, 4, 1, tif_file); fm_write(&temp32, 4, 1, fmp);
total_bytes_put += 8; total_bytes_put += 8;
/* YResolution */ /* YResolution */
temp32 = symbol->dpmm ? symbol->dpmm : 72; temp32 = symbol->dpmm ? symbol->dpmm : 72;
fwrite(&temp32, 4, 1, tif_file); fm_write(&temp32, 4, 1, fmp);
temp32 = symbol->dpmm ? 10 /*cm*/ : 1; temp32 = symbol->dpmm ? 10 /*cm*/ : 1;
fwrite(&temp32, 4, 1, tif_file); fm_write(&temp32, 4, 1, fmp);
total_bytes_put += 8; total_bytes_put += 8;
if (color_map_size) { if (color_map_size) {
for (i = 0; i < color_map_size; i++) { for (i = 0; i < color_map_size; i++) {
fwrite(&color_map[i].red, 2, 1, tif_file); fm_write(&color_map[i].red, 2, 1, fmp);
} }
for (i = 0; i < color_map_size; i++) { for (i = 0; i < color_map_size; i++) {
fwrite(&color_map[i].green, 2, 1, tif_file); fm_write(&color_map[i].green, 2, 1, fmp);
} }
for (i = 0; i < color_map_size; i++) { for (i = 0; i < color_map_size; i++) {
fwrite(&color_map[i].blue, 2, 1, tif_file); fm_write(&color_map[i].blue, 2, 1, fmp);
} }
total_bytes_put += 6 * color_map_size; total_bytes_put += 6 * color_map_size;
} }
if (ferror(tif_file)) { if (fm_error(fmp)) {
sprintf(symbol->errtxt, "679: Incomplete write to output (%d: %.30s)", errno, strerror(errno)); sprintf(symbol->errtxt, "679: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
if (!output_to_stdout) { (void) fm_close(fmp, symbol);
(void) fclose(tif_file);
}
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (output_to_stdout) { if (!output_to_stdout) {
if (fflush(tif_file) != 0) { if (fm_tell(fmp) != total_bytes_put) {
sprintf(symbol->errtxt, "980: Incomplete flush to output (%d: %.30s)", errno, strerror(errno)); (void) fm_close(fmp, symbol);
return ZINT_ERROR_FILE_WRITE;
}
} else {
if (ftell(tif_file) != total_bytes_put) {
(void) fclose(tif_file);
strcpy(symbol->errtxt, "674: Failed to write all output"); strcpy(symbol->errtxt, "674: Failed to write all output");
return ZINT_ERROR_FILE_WRITE; return ZINT_ERROR_FILE_WRITE;
} }
if (fclose(tif_file) != 0) {
sprintf(symbol->errtxt, "981: Failure on closing output file (%d: %.30s)", errno, strerror(errno));
return ZINT_ERROR_FILE_WRITE;
} }
if (!fm_close(fmp, symbol)) {
sprintf(symbol->errtxt, "981: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
return ZINT_ERROR_FILE_WRITE;
} }
return 0; return 0;

View File

@ -161,13 +161,13 @@ static void tif_lzw_cl_hash(tif_lzw_state *sp) {
} }
/* Explicit 0xff masking to make icc -check=conversions happy */ /* Explicit 0xff masking to make icc -check=conversions happy */
#define PutNextCode(op_file, c) { \ #define PutNextCode(op_fmp, c) { \
nextdata = (nextdata << nbits) | c; \ nextdata = (nextdata << nbits) | c; \
nextbits += nbits; \ nextbits += nbits; \
putc((nextdata >> (nextbits - 8)) & 0xff, op_file); \ fm_putc((nextdata >> (nextbits - 8)) & 0xff, op_fmp); \
nextbits -= 8; \ nextbits -= 8; \
if (nextbits >= 8) { \ if (nextbits >= 8) { \
putc((nextdata >> (nextbits - 8)) & 0xff, op_file); \ fm_putc((nextdata >> (nextbits - 8)) & 0xff, op_fmp); \
nextbits -= 8; \ nextbits -= 8; \
} \ } \
outcount += nbits; \ outcount += nbits; \
@ -187,7 +187,7 @@ static void tif_lzw_cl_hash(tif_lzw_state *sp) {
* are re-sized at this point, and a CODE_CLEAR is generated * are re-sized at this point, and a CODE_CLEAR is generated
* for the decoder. * for the decoder.
*/ */
static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char *bp, int cc) { static int tif_lzw_encode(tif_lzw_state *sp, struct filemem *op_fmp, const unsigned char *bp, int cc) {
register long fcode; register long fcode;
register tif_lzw_hash *hp; register tif_lzw_hash *hp;
register int h, c; register int h, c;
@ -229,7 +229,7 @@ static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char
ent = (tif_lzw_hcode) -1; ent = (tif_lzw_hcode) -1;
if (cc > 0) { if (cc > 0) {
PutNextCode(op_file, CODE_CLEAR); PutNextCode(op_fmp, CODE_CLEAR);
ent = *bp++; cc--; incount++; ent = *bp++; cc--; incount++;
} }
while (cc > 0) { while (cc > 0) {
@ -275,7 +275,7 @@ static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char
/* /*
* New entry, emit code and add to table. * New entry, emit code and add to table.
*/ */
PutNextCode(op_file, ent); PutNextCode(op_fmp, ent);
ent = (tif_lzw_hcode) c; ent = (tif_lzw_hcode) c;
hp->code = (tif_lzw_hcode) (free_ent++); hp->code = (tif_lzw_hcode) (free_ent++);
hp->hash = fcode; hp->hash = fcode;
@ -286,7 +286,7 @@ static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char
incount = 0; incount = 0;
outcount = 0; outcount = 0;
free_ent = CODE_FIRST; free_ent = CODE_FIRST;
PutNextCode(op_file, CODE_CLEAR); PutNextCode(op_fmp, CODE_CLEAR);
nbits = BITS_MIN; nbits = BITS_MIN;
maxcode = MAXCODE(BITS_MIN); maxcode = MAXCODE(BITS_MIN);
} else { } else {
@ -314,7 +314,7 @@ static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char
incount = 0; incount = 0;
outcount = 0; outcount = 0;
free_ent = CODE_FIRST; free_ent = CODE_FIRST;
PutNextCode(op_file, CODE_CLEAR); PutNextCode(op_fmp, CODE_CLEAR);
nbits = BITS_MIN; nbits = BITS_MIN;
maxcode = MAXCODE(BITS_MIN); maxcode = MAXCODE(BITS_MIN);
} else { } else {
@ -332,13 +332,13 @@ static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char
*/ */
if (ent != (tif_lzw_hcode) -1) { if (ent != (tif_lzw_hcode) -1) {
PutNextCode(op_file, ent); PutNextCode(op_fmp, ent);
free_ent++; free_ent++;
if (free_ent == CODE_MAX - 1) { if (free_ent == CODE_MAX - 1) {
/* table is full, emit clear code and reset */ /* table is full, emit clear code and reset */
outcount = 0; outcount = 0;
PutNextCode(op_file, CODE_CLEAR); PutNextCode(op_fmp, CODE_CLEAR);
nbits = BITS_MIN; nbits = BITS_MIN;
} else { } else {
/* /*
@ -351,10 +351,10 @@ static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char
} }
} }
} }
PutNextCode(op_file, CODE_EOI); PutNextCode(op_fmp, CODE_EOI);
/* Explicit 0xff masking to make icc -check=conversions happy */ /* Explicit 0xff masking to make icc -check=conversions happy */
if (nextbits > 0) { if (nextbits > 0) {
putc((nextdata << (8 - nextbits)) & 0xff, op_file); fm_putc((nextdata << (8 - nextbits)) & 0xff, op_fmp);
} }
return 1; return 1;

View File

@ -409,8 +409,8 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
const float descent_small = 0.948426545f; /* Arimo value for SMALL_TEXT (font height 5) */ const float descent_small = 0.948426545f; /* Arimo value for SMALL_TEXT (font height 5) */
/* For UPC/EAN only */ /* For UPC/EAN only */
float addon_row_yposn; float addon_row_yposn = 0.0f; /* Suppress gcc -Wmaybe-uninitialized false positive */
float addon_row_height; float addon_row_height = 0.0f; /* Ditto */
int upcae_outside_font_height = 0; /* UPC-A/E outside digits font size */ int upcae_outside_font_height = 0; /* UPC-A/E outside digits font size */
const float gws_left_fudge = 0.5f; /* These make the guard whitespaces appear closer to the edge for SVG/qzint */ const float gws_left_fudge = 0.5f; /* These make the guard whitespaces appear closer to the edge for SVG/qzint */
const float gws_right_fudge = 0.5f; /* (undone by EMF/EPS) */ const float gws_right_fudge = 0.5f; /* (undone by EMF/EPS) */
@ -443,6 +443,10 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
if (error_number != 0) { if (error_number != 0) {
return error_number; return error_number;
} }
if (symbol->rows <= 0) {
strcpy(symbol->errtxt, "697: No rows");
return ZINT_ERROR_INVALID_OPTION;
}
/* Allocate memory */ /* Allocate memory */
vector = symbol->vector = (struct zint_vector *) malloc(sizeof(struct zint_vector)); vector = symbol->vector = (struct zint_vector *) malloc(sizeof(struct zint_vector));

View File

@ -131,6 +131,8 @@ extern "C" {
int bitmap_height; /* Height of bitmap image (raster output only) */ int bitmap_height; /* Height of bitmap image (raster output only) */
unsigned char *alphamap; /* Array of alpha values used (raster output only) */ unsigned char *alphamap; /* Array of alpha values used (raster output only) */
struct zint_vector *vector; /* Pointer to vector header (vector output only) */ struct zint_vector *vector; /* Pointer to vector header (vector output only) */
unsigned char *memfile; /* Pointer to in-memory file buffer if BARCODE_MEMORY_FILE (output only) */
int memfile_size; /* Length of in-memory file buffer (output only) */
}; };
/* Segment for use with `ZBarcode_Encode_Segs()` below */ /* Segment for use with `ZBarcode_Encode_Segs()` below */
@ -273,25 +275,26 @@ extern "C" {
#define BARCODE_LAST 146 /* Max barcode number marker, not barcode */ #define BARCODE_LAST 146 /* Max barcode number marker, not barcode */
/* Output options (`symbol->output_options`) */ /* Output options (`symbol->output_options`) */
#define BARCODE_BIND_TOP 0x0001 /* Boundary bar above the symbol only (not below), does not affect stacking */ #define BARCODE_BIND_TOP 0x00001 /* Boundary bar above the symbol only (not below), does not affect stacking */
/* Note: value was once used by the legacy (never-used) BARCODE_NO_ASCII */ /* Note: value was once used by the legacy (never-used) BARCODE_NO_ASCII */
#define BARCODE_BIND 0x0002 /* Boundary bars above & below the symbol and between stacked symbols */ #define BARCODE_BIND 0x00002 /* Boundary bars above & below the symbol and between stacked symbols */
#define BARCODE_BOX 0x0004 /* Box around symbol */ #define BARCODE_BOX 0x00004 /* Box around symbol */
#define BARCODE_STDOUT 0x0008 /* Output to stdout */ #define BARCODE_STDOUT 0x00008 /* Output to stdout */
#define READER_INIT 0x0010 /* Reader Initialisation (Programming) */ #define READER_INIT 0x00010 /* Reader Initialisation (Programming) */
#define SMALL_TEXT 0x0020 /* Use smaller font */ #define SMALL_TEXT 0x00020 /* Use smaller font */
#define BOLD_TEXT 0x0040 /* Use bold font */ #define BOLD_TEXT 0x00040 /* Use bold font */
#define CMYK_COLOUR 0x0080 /* CMYK colour space (Encapsulated PostScript and TIF) */ #define CMYK_COLOUR 0x00080 /* CMYK colour space (Encapsulated PostScript and TIF) */
#define BARCODE_DOTTY_MODE 0x0100 /* Plot a matrix symbol using dots rather than squares */ #define BARCODE_DOTTY_MODE 0x00100 /* Plot a matrix symbol using dots rather than squares */
#define GS1_GS_SEPARATOR 0x0200 /* Use GS instead of FNC1 as GS1 separator (Data Matrix) */ #define GS1_GS_SEPARATOR 0x00200 /* Use GS instead of FNC1 as GS1 separator (Data Matrix) */
#define OUT_BUFFER_INTERMEDIATE 0x0400 /* Return ASCII values in bitmap buffer (OUT_BUFFER only) */ #define OUT_BUFFER_INTERMEDIATE 0x00400 /* Return ASCII values in bitmap buffer (OUT_BUFFER only) */
#define BARCODE_QUIET_ZONES 0x0800 /* Add compliant quiet zones (additional to any specified whitespace) */ #define BARCODE_QUIET_ZONES 0x00800 /* Add compliant quiet zones (additional to any specified whitespace) */
/* Note: CODE16K, CODE49, CODABLOCKF, ITF14, EAN/UPC have default quiet zones /* Note: CODE16K, CODE49, CODABLOCKF, ITF14, EAN/UPC have default quiet zones
*/ */
#define BARCODE_NO_QUIET_ZONES 0x1000 /* Disable quiet zones, notably those with defaults as listed above */ #define BARCODE_NO_QUIET_ZONES 0x01000 /* Disable quiet zones, notably those with defaults as listed above */
#define COMPLIANT_HEIGHT 0x2000 /* Warn if height not compliant, or use standard height (if any) as default */ #define COMPLIANT_HEIGHT 0x02000 /* Warn if height not compliant, or use standard height (if any) as default */
#define EANUPC_GUARD_WHITESPACE 0x4000 /* Add quiet zone indicators ("<"/">") to HRT whitespace (EAN/UPC) */ #define EANUPC_GUARD_WHITESPACE 0x04000 /* Add quiet zone indicators ("<"/">") to HRT whitespace (EAN/UPC) */
#define EMBED_VECTOR_FONT 0x8000 /* Embed font in vector output - currently only for SVG output */ #define EMBED_VECTOR_FONT 0x08000 /* Embed font in vector output - currently only for SVG output */
#define BARCODE_MEMORY_FILE 0x10000 /* Write output to in-memory buffer `memfile` instead of to `outfile` */
/* Input data types (`symbol->input_mode`) */ /* Input data types (`symbol->input_mode`) */
#define DATA_MODE 0 /* Binary */ #define DATA_MODE 0 /* Binary */

View File

@ -42,6 +42,7 @@ HEADERS += ../backend/aztec.h \
../backend/gb18030.h \ ../backend/gb18030.h \
../backend/gb2312.h \ ../backend/gb2312.h \
../backend/gbk.h \ ../backend/gbk.h \
../backend/filemem.h \
../backend/general_field.h \ ../backend/general_field.h \
../backend/gridmtx.h \ ../backend/gridmtx.h \
../backend/gs1.h \ ../backend/gs1.h \
@ -86,6 +87,7 @@ SOURCES += ../backend/2of5.c \
../backend/dotcode.c \ ../backend/dotcode.c \
../backend/eci.c \ ../backend/eci.c \
../backend/emf.c \ ../backend/emf.c \
../backend/filemem.c \
../backend/general_field.c \ ../backend/general_field.c \
../backend/gif.c \ ../backend/gif.c \
../backend/gridmtx.c \ ../backend/gridmtx.c \

View File

@ -33,6 +33,7 @@ HEADERS += ../backend/aztec.h \
../backend/gb18030.h \ ../backend/gb18030.h \
../backend/gb2312.h \ ../backend/gb2312.h \
../backend/gbk.h \ ../backend/gbk.h \
../backend/filemem.h \
../backend/general_field.h \ ../backend/general_field.h \
../backend/gridmtx.h \ ../backend/gridmtx.h \
../backend/gs1.h \ ../backend/gs1.h \
@ -70,6 +71,7 @@ SOURCES += ../backend/2of5.c \
../backend/eci.c \ ../backend/eci.c \
../backend/emf.c \ ../backend/emf.c \
../backend/gridmtx.c \ ../backend/gridmtx.c \
../backend/filemem.c \
../backend/general_field.c \ ../backend/general_field.c \
../backend/gif.c \ ../backend/gif.c \
../backend/gs1.c \ ../backend/gs1.c \

View File

@ -5361,6 +5361,7 @@ printf "%s\n" "$ac_cv_c_bigendian" >&6; }
../backend/dotcode.c ../backend/dotcode.c
../backend/eci.c ../backend/eci.c
../backend/emf.c ../backend/emf.c
../backend/filemem.c
../backend/general_field.c ../backend/general_field.c
../backend/gif.c ../backend/gif.c
../backend/gridmtx.c ../backend/gridmtx.c

View File

@ -90,6 +90,7 @@ TEA_ADD_SOURCES([
../backend/dotcode.c ../backend/dotcode.c
../backend/eci.c ../backend/eci.c
../backend/emf.c ../backend/emf.c
../backend/filemem.c
../backend/general_field.c ../backend/general_field.c
../backend/gif.c ../backend/gif.c
../backend/gridmtx.c ../backend/gridmtx.c

View File

@ -161,6 +161,10 @@ SOURCE=..\backend\emf.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\backend\filemem.c
# End Source File
# Begin Source File
SOURCE=..\backend\general_field.c SOURCE=..\backend\general_field.c
# End Source File # End Source File
# Begin Source File # Begin Source File

File diff suppressed because it is too large Load Diff

View File

@ -1028,7 +1028,7 @@ zint --fg=00ff0055 -d "This Text"
![`zint -d "This Text" --fg=00FF0055`](images/code128_green_alpha.svg){.lin} ![`zint -d "This Text" --fg=00FF0055`](images/code128_green_alpha.svg){.lin}
will produce a semi-transparent green foreground with standard (white) will produce a semi-transparent green foreground with a standard (white)
background. Note that transparency is treated differently by raster and vector background. Note that transparency is treated differently by raster and vector
(SVG) output formats, as for vector output the background will "shine through" a (SVG) output formats, as for vector output the background will "shine through" a
transparent foreground. For instance transparent foreground. For instance
@ -1707,7 +1707,7 @@ int main(int argc, char **argv)
``` ```
Note that when using the API, the input data is assumed to be 8-bit binary Note that when using the API, the input data is assumed to be 8-bit binary
unless the `input_mode` member of the `zint_symbol` structure is set - see [5.10 unless the `input_mode` member of the `zint_symbol` structure is set - see [5.11
Setting the Input Mode] for details. Setting the Input Mode] for details.
## 5.3 Encoding and Printing Functions in Depth ## 5.3 Encoding and Printing Functions in Depth
@ -1876,24 +1876,59 @@ for (circle = my_symbol->vector->circles; circle; circle = circle->next) {
} }
``` ```
## 5.6 Setting Options ## 5.6 Buffering Symbols in Memory (memfile)
Symbols can also be stored as "in-memory" file buffers by giving the
`BARCODE_MEMORY_FILE` option to the `output_options` member, which saves the
print output to member `memfile` instead of to the output file `outfile`. The
length of the buffer is given in `memfile_size`. For instance:
```c
#include <zint.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
struct zint_symbol *my_symbol;
my_symbol = ZBarcode_Create();
my_symbol->output_options |= BARCODE_MEMORY_FILE;
/* Only the extension is used, to determine output format */
strcpy(my_symbol->outfile, "mem.svg");
ZBarcode_Encode_and_Print(my_symbol, argv[1], 0, 0);
/* `my_symbol->memfile` now contains the SVG output */
fwrite(my_symbol->memfile, 1, my_symbol->memfile_size, stdout);
ZBarcode_Delete(my_symbol);
return 0;
}
```
will print the SVG output to `stdout` (the file "mem.svg" is not created). This
is particularly useful for the textual formats EPS and SVG,[^7] allowing the
output to be manipulated and processed by the client.
[^7]: BARCODE_MEMORY_FILE textual formats EPS and SVG will have Unix newlines
(LF) on both Windows and Unix, i.e. not CR+LF on Windows.
## 5.7 Setting Options
So far our application is not very useful unless we plan to only make Code 128 So far our application is not very useful unless we plan to only make Code 128
symbols and we don't mind that they only save to `"out.png"`. As with the CLI symbols and we don't mind that they only save to `"out.png"` (or to memory, as
program, of course, these options can be altered. The way this is done is by above). As with the CLI program, of course, these options can be altered. The
altering the contents of the `zint_symbol` structure between the creation and way this is done is by altering the contents of the `zint_symbol` structure
encoding stages. The `zint_symbol` structure consists of the following members: between the creation and encoding stages. The `zint_symbol` structure consists
of the following members:
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
Member Name Type Meaning Default Value Member Name Type Meaning Default Value
------------------- ---------- ------------------------- ----------------- ------------------- ---------- ------------------------- -----------------
`symbology` integer Symbol to use - see [5.8 `BARCODE_CODE128` `symbology` integer Symbol to use - see [5.9 `BARCODE_CODE128`
Specifying a Symbology]. Specifying a Symbology].
`height` float Symbol height in Symbol dependent `height` float Symbol height in Symbol dependent
X-dimensions, excluding X-dimensions, excluding
fixed width-to-height fixed width-to-height
symbols.[^7] symbols.[^8]
`scale` float Scale factor for 1.0 `scale` float Scale factor for 1.0
adjusting size of image adjusting size of image
@ -1909,7 +1944,7 @@ Member Name Type Meaning Default Value
X-dimensions. X-dimensions.
`output_options` integer Set various output 0 (none) `output_options` integer Set various output 0 (none)
parameters - see [5.9 parameters - see [5.10
Adjusting Output Adjusting Output
Options]. Options].
@ -1943,7 +1978,7 @@ Member Name Type Meaning Default Value
`.eps`, `.pcx`, `.svg`, `.eps`, `.pcx`, `.svg`,
`.tif` or `.txt` followed `.tif` or `.txt` followed
by a terminating by a terminating
`NUL`.[^8] `NUL`.[^9]
`primary` character Primary message data for `""` (empty) `primary` character Primary message data for `""` (empty)
string more complex symbols, string more complex symbols,
@ -1959,7 +1994,7 @@ Member Name Type Meaning Default Value
Readable Text (HRT). Readable Text (HRT).
`input_mode` integer Set encoding of input `DATA_MODE` `input_mode` integer Set encoding of input `DATA_MODE`
data - see [5.10 Setting data - see [5.11 Setting
the Input Mode]. the Input Mode].
`eci` integer Extended Channel 0 (none) `eci` integer Extended Channel 0 (none)
@ -1989,7 +2024,7 @@ Member Name Type Meaning Default Value
`warn_level` integer Affects error/warning `WARN_DEFAULT` `warn_level` integer Affects error/warning `WARN_DEFAULT`
value returned by Zint value returned by Zint
API - see [5.7 Handling API - see [5.8 Handling
Errors]. Errors].
`text` unsigned Human Readable Text, `""` (empty) `text` unsigned Human Readable Text, `""` (empty)
@ -2017,7 +2052,7 @@ Member Name Type Meaning Default Value
string event that an error string event that an error
occurred, with a occurred, with a
terminating `NUL` - see terminating `NUL` - see
[5.7 Handling Errors]. [5.8 Handling Errors].
`bitmap` pointer to Pointer to stored bitmap (output only) `bitmap` pointer to Pointer to stored bitmap (output only)
unsigned image - see [5.4 unsigned image - see [5.4
@ -2044,17 +2079,28 @@ Member Name Type Meaning Default Value
structure vector elements - see structure vector elements - see
[5.5 Buffering Symbols [5.5 Buffering Symbols
in Memory (vector)]. in Memory (vector)].
`memfile` pointer to Pointer to in-memory (output only)
unsigned file buffer if
character `BARCODE_MEMORY_FILE`
array set in `output_options`
- see [5.6 Buffering
Symbols in Memory
(memfile)].
`memfile_size` integer Length of in-memory file (output only)
buffer.
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
Table: API Structure `zint_symbol` {#tbl:api_structure_zint_symbol tag="$ $"} Table: API Structure `zint_symbol` {#tbl:api_structure_zint_symbol tag="$ $"}
[^7]: The `height` value is ignored for Aztec (including HIBC and Aztec Rune), [^8]: The `height` value is ignored for Aztec (including HIBC and Aztec Rune),
Code One, Data Matrix (including HIBC), DotCode, Grid Matrix, Han Xin, MaxiCode, Code One, Data Matrix (including HIBC), DotCode, Grid Matrix, Han Xin, MaxiCode,
QR Code (including HIBC, Micro QR, rMQR and UPNQR), and Ultracode - all of which QR Code (including HIBC, Micro QR, rMQR and UPNQR), and Ultracode - all of which
have a fixed width-to-height ratio (or, in the case of Code One, a fixed have a fixed width-to-height ratio (or, in the case of Code One, a fixed
height). height).
[^8]: For Windows, `outfile` is assumed to be UTF-8 encoded. [^9]: For Windows, `outfile` is assumed to be UTF-8 encoded.
To alter these values use the syntax shown in the example below. This code has To alter these values use the syntax shown in the example below. This code has
the same result as the previous example except the output is now taller and the same result as the previous example except the output is now taller and
@ -2085,7 +2131,7 @@ ignored:
This is what the CLI option `--nobackground` does - see [4.7 Using Colour]. This is what the CLI option `--nobackground` does - see [4.7 Using Colour].
## 5.7 Handling Errors ## 5.8 Handling Errors
If errors occur during encoding a non-zero integer value is passed back to the If errors occur during encoding a non-zero integer value is passed back to the
calling application. In addition the `errtxt` member is set to a message calling application. In addition the `errtxt` member is set to a message
@ -2196,7 +2242,7 @@ Error 881: Malformed foreground RGB colour 'nonsense' (hexadecimal only)
To treat all warnings as errors, set `symbol->warn_level` to `WARN_FAIL_ALL`. To treat all warnings as errors, set `symbol->warn_level` to `WARN_FAIL_ALL`.
## 5.8 Specifying a Symbology ## 5.9 Specifying a Symbology
Symbologies can be specified by number or by name as shown in the Table Symbologies can be specified by number or by name as shown in the Table
{@tbl:barcode_types}. For example {@tbl:barcode_types}. For example
@ -2211,7 +2257,7 @@ means the same as
symbol->symbology = 50; symbol->symbology = 50;
``` ```
## 5.9 Adjusting Output Options ## 5.10 Adjusting Output Options
The `output_options` member can be used to adjust various aspects of the output The `output_options` member can be used to adjust various aspects of the output
file. To select more than one option from the table below simply `OR` them file. To select more than one option from the table below simply `OR` them
@ -2226,10 +2272,10 @@ Value Effect
------------------------- --------------------------------------------------- ------------------------- ---------------------------------------------------
0 No options selected. 0 No options selected.
`BARCODE_BIND_TOP` Boundary bar above the symbol only.[^9] `BARCODE_BIND_TOP` Boundary bar above the symbol only.[^10]
`BARCODE_BIND` Boundary bars above and below the symbol and `BARCODE_BIND` Boundary bars above and below the symbol and
between rows if stacking multiple symbols.[^10] between rows if stacking multiple symbols.[^11]
`BARCODE_BOX` Add a box surrounding the symbol and whitespace. `BARCODE_BOX` Add a box surrounding the symbol and whitespace.
@ -2256,7 +2302,7 @@ Value Effect
Symbols in Memory (raster)]. Symbols in Memory (raster)].
`BARCODE_QUIET_ZONES` Add compliant quiet zones (additional to any `BARCODE_QUIET_ZONES` Add compliant quiet zones (additional to any
specified whitespace).[^11] specified whitespace).[^12]
`BARCODE_NO_QUIET_ZONES` Disable quiet zones, notably those with defaults. `BARCODE_NO_QUIET_ZONES` Disable quiet zones, notably those with defaults.
@ -2268,20 +2314,23 @@ Value Effect
`EMBED_VECTOR_FONT` Embed font in vector output - currently available `EMBED_VECTOR_FONT` Embed font in vector output - currently available
for SVG output only. for SVG output only.
`BARCODE_MEMORY_FILE` Write output to in-memory buffer `symbol->memfile`
instead of to `outfile` file.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Table: API `output_options` Values {#tbl:api_output_options tag="$ $"} Table: API `output_options` Values {#tbl:api_output_options tag="$ $"}
[^9]: The `BARCODE_BIND_TOP` flag is set by default for DPD - see [6.1.10.7 DPD [^10]: The `BARCODE_BIND_TOP` flag is set by default for DPD - see [6.1.10.7 DPD
Code]. Code].
[^10]: The `BARCODE_BIND` flag is always set for Codablock-F, Code 16K and Code [^11]: The `BARCODE_BIND` flag is always set for Codablock-F, Code 16K and Code
49. Special considerations apply to ITF-14 - see [6.1.2.6 ITF-14]. 49. Special considerations apply to ITF-14 - see [6.1.2.6 ITF-14].
[^11]: Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and [^12]: 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. UPC-E have compliant quiet zones added by default.
## 5.10 Setting the Input Mode ## 5.11 Setting the Input Mode
The way in which the input data is encoded can be set using the `input_mode` The way in which the input data is encoded can be set using the `input_mode`
member. Valid values are shown in the table below. member. Valid values are shown in the table below.
@ -2366,7 +2415,7 @@ be set to the overall height on output).
MicroPDF417 and PDF417. For QR Code and UPNQR, it affects Zint's automatic mask MicroPDF417 and PDF417. For QR Code and UPNQR, it affects Zint's automatic mask
selection - see [6.6.3 QR Code (ISO 18004)] for details. selection - see [6.6.3 QR Code (ISO 18004)] for details.
## 5.11 Multiple Segments ## 5.12 Multiple Segments
For input data requiring multiple ECIs, the following functions may be used: For input data requiring multiple ECIs, the following functions may be used:
@ -2426,7 +2475,7 @@ int main(int argc, char **argv)
A maximum of 256 segments may be specified. Use of multiple segments with GS1 A maximum of 256 segments may be specified. Use of multiple segments with GS1
data is not currently supported. data is not currently supported.
## 5.12 Scaling Helpers ## 5.13 Scaling Helpers
To help with scaling the output, the following three function are available: To help with scaling the output, the following three function are available:
@ -2473,7 +2522,7 @@ 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 scanner used, the intended scanning distance, and what media ("substrates") the
barcode appears on. barcode appears on.
## 5.13 Verifying Symbology Availability ## 5.14 Verifying Symbology Availability
An additional function available in the API is: An additional function available in the API is:
@ -2511,7 +2560,7 @@ if (ZBarcode_BarcodeName(BARCODE_PDF417, name) == 0) {
will print `BARCODE_PDF417`. will print `BARCODE_PDF417`.
## 5.14 Checking Symbology Capabilities ## 5.15 Checking Symbology Capabilities
It can be useful for frontend programs to know the capabilities of a symbology. It can be useful for frontend programs to know the capabilities of a symbology.
This can be determined using another additional function: This can be determined using another additional function:
@ -2530,7 +2579,7 @@ Value Meaning
`ZINT_CAP_STACKABLE` Is the symbology stackable? `ZINT_CAP_STACKABLE` Is the symbology stackable?
`ZINT_CAP_EANUPC`[^12] Is the symbology EAN/UPC? `ZINT_CAP_EANUPC`[^13] Is the symbology EAN/UPC?
`ZINT_CAP_COMPOSITE` Does the symbology support composite data? (see `ZINT_CAP_COMPOSITE` Does the symbology support composite data? (see
[6.3 GS1 Composite Symbols (ISO 24723)] below) [6.3 GS1 Composite Symbols (ISO 24723)] below)
@ -2561,7 +2610,7 @@ Value Meaning
Table: {#tbl:api_cap tag=": API Capability Flags"} Table: {#tbl:api_cap tag=": API Capability Flags"}
[^12]: `ZINT_CAP_EANUPC` was previously named `ZINT_CAP_EXTENDABLE`, which is [^13]: `ZINT_CAP_EANUPC` was previously named `ZINT_CAP_EXTENDABLE`, which is
still recognised. still recognised.
For example: For example:
@ -2581,7 +2630,7 @@ if (cap & ZINT_CAP_ECI) {
} }
``` ```
## 5.15 Zint Version ## 5.16 Zint Version
Whether the Zint library linked to was built with PNG support may be determined Whether the Zint library linked to was built with PNG support may be determined
with: with:
@ -3091,13 +3140,13 @@ all-numeric characters.
![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg){.lin} ![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg){.lin}
It is sometimes advantageous to stop Code 128 from using Code Set C which It is sometimes advantageous to stop Code 128 from using Code Set C which
compresses numerical data. The `BARCODE_CODE128AB`[^13] variant (symbology 60) compresses numerical data. The `BARCODE_CODE128AB`[^14] variant (symbology 60)
suppresses Code Set C in favour of Code Sets A and B. suppresses Code Set C in favour of Code Sets A and B.
Note that the special escapes to manually switch Code Sets mentioned above are Note that the special escapes to manually switch Code Sets mentioned above are
not available for this variant (nor for any other). not available for this variant (nor for any other).
[^13]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is [^14]: `BARCODE_CODE128AB` previously used the name `BARCODE_CODE128B`, which is
still recognised. still recognised.
#### 6.1.10.3 GS1-128 #### 6.1.10.3 GS1-128
@ -4866,7 +4915,7 @@ Used internally by Zint Barcode Studio to display the preview, the Qt Backend
Buffering Symbols in Memory (vector)]) provided by the Zint library `libzint`. Buffering Symbols in Memory (vector)]) provided by the Zint library `libzint`.
The main class is `Zint::QZint`, which has getter/setter properties that The main class is `Zint::QZint`, which has getter/setter properties that
correspond to the `zint_symbol` structure (see [5.6 Setting Options]), and a correspond to the `zint_symbol` structure (see [5.7 Setting Options]), and a
main method `render()` which takes a Qt `QPainter` to paint with, and a `QRectF` main method `render()` which takes a Qt `QPainter` to paint with, and a `QRectF`
rectangular area specifying where to paint into: rectangular area specifying where to paint into:

View File

@ -62,16 +62,17 @@ December 2023
- 5.3 Encoding and Printing Functions in Depth - 5.3 Encoding and Printing Functions in Depth
- 5.4 Buffering Symbols in Memory (raster) - 5.4 Buffering Symbols in Memory (raster)
- 5.5 Buffering Symbols in Memory (vector) - 5.5 Buffering Symbols in Memory (vector)
- 5.6 Setting Options - 5.6 Buffering Symbols in Memory (memfile)
- 5.7 Handling Errors - 5.7 Setting Options
- 5.8 Specifying a Symbology - 5.8 Handling Errors
- 5.9 Adjusting Output Options - 5.9 Specifying a Symbology
- 5.10 Setting the Input Mode - 5.10 Adjusting Output Options
- 5.11 Multiple Segments - 5.11 Setting the Input Mode
- 5.12 Scaling Helpers - 5.12 Multiple Segments
- 5.13 Verifying Symbology Availability - 5.13 Scaling Helpers
- 5.14 Checking Symbology Capabilities - 5.14 Verifying Symbology Availability
- 5.15 Zint Version - 5.15 Checking Symbology Capabilities
- 5.16 Zint Version
- 6. Types of Symbology - 6. Types of Symbology
- 6.1 One-Dimensional Symbols - 6.1 One-Dimensional Symbols
- 6.1.1 Code 11 - 6.1.1 Code 11
@ -1130,7 +1131,7 @@ format. For example:
[zint -d "This Text" --fg=00FF0055] [zint -d "This Text" --fg=00FF0055]
will produce a semi-transparent green foreground with standard (white) will produce a semi-transparent green foreground with a standard (white)
background. Note that transparency is treated differently by raster and vector background. Note that transparency is treated differently by raster and vector
(SVG) output formats, as for vector output the background will “shine through” a (SVG) output formats, as for vector output the background will “shine through” a
transparent foreground. For instance transparent foreground. For instance
@ -1742,7 +1743,7 @@ function as shown in the next example:
} }
Note that when using the API, the input data is assumed to be 8-bit binary Note that when using the API, the input data is assumed to be 8-bit binary
unless the input_mode member of the zint_symbol structure is set - see 5.10 unless the input_mode member of the zint_symbol structure is set - see 5.11
Setting the Input Mode for details. Setting the Input Mode for details.
5.3 Encoding and Printing Functions in Depth 5.3 Encoding and Printing Functions in Depth
@ -1899,24 +1900,53 @@ draw_string(), and draw_circle() routines available:
draw_circle(circle->x, circle->y, circle->diameter, circle->width); draw_circle(circle->x, circle->y, circle->diameter, circle->width);
} }
5.6 Setting Options 5.6 Buffering Symbols in Memory (memfile)
Symbols can also be stored as “in-memory” file buffers by giving the
BARCODE_MEMORY_FILE option to the output_options member, which saves the print
output to member memfile instead of to the output file outfile. The length of
the buffer is given in memfile_size. For instance:
#include <zint.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
struct zint_symbol *my_symbol;
my_symbol = ZBarcode_Create();
my_symbol->output_options |= BARCODE_MEMORY_FILE;
/* Only the extension is used, to determine output format */
strcpy(my_symbol->outfile, "mem.svg");
ZBarcode_Encode_and_Print(my_symbol, argv[1], 0, 0);
/* `my_symbol->memfile` now contains the SVG output */
fwrite(my_symbol->memfile, 1, my_symbol->memfile_size, stdout);
ZBarcode_Delete(my_symbol);
return 0;
}
will print the SVG output to stdout (the file “mem.svg” is not created). This is
particularly useful for the textual formats EPS and SVG,[7] allowing the output
to be manipulated and processed by the client.
5.7 Setting Options
So far our application is not very useful unless we plan to only make Code 128 So far our application is not very useful unless we plan to only make Code 128
symbols and we dont mind that they only save to "out.png". As with the CLI symbols and we dont mind that they only save to "out.png" (or to memory, as
program, of course, these options can be altered. The way this is done is by above). As with the CLI program, of course, these options can be altered. The
altering the contents of the zint_symbol structure between the creation and way this is done is by altering the contents of the zint_symbol structure
encoding stages. The zint_symbol structure consists of the following members: between the creation and encoding stages. The zint_symbol structure consists of
the following members:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Member Name Type Meaning Default Value Member Name Type Meaning Default Value
-------------------- ------------ -------------------------- ----------------- -------------------- ------------ -------------------------- -----------------
symbology integer Symbol to use - see 5.8 BARCODE_CODE128 symbology integer Symbol to use - see 5.9 BARCODE_CODE128
Specifying a Symbology. Specifying a Symbology.
height float Symbol height in Symbol dependent height float Symbol height in Symbol dependent
X-dimensions, excluding X-dimensions, excluding
fixed width-to-height fixed width-to-height
symbols.[7] symbols.[8]
scale float Scale factor for adjusting 1.0 scale float Scale factor for adjusting 1.0
size of image (sets size of image (sets
@ -1932,7 +1962,7 @@ encoding stages. The zint_symbol structure consists of the following members:
X-dimensions. X-dimensions.
output_options integer Set various output 0 (none) output_options integer Set various output 0 (none)
parameters - see 5.9 parameters - see 5.10
Adjusting Output Options. Adjusting Output Options.
fgcolour character Foreground (ink) colour as "000000" fgcolour character Foreground (ink) colour as "000000"
@ -1963,7 +1993,7 @@ encoding stages. The zint_symbol structure consists of the following members:
end in .png, .gif, .bmp, end in .png, .gif, .bmp,
.emf, .eps, .pcx, .svg, .emf, .eps, .pcx, .svg,
.tif or .txt followed by a .tif or .txt followed by a
terminating NUL.[8] terminating NUL.[9]
primary character Primary message data for "" (empty) primary character Primary message data for "" (empty)
string more complex symbols, with string more complex symbols, with
@ -1979,7 +2009,7 @@ encoding stages. The zint_symbol structure consists of the following members:
Readable Text (HRT). Readable Text (HRT).
input_mode integer Set encoding of input DATA_MODE input_mode integer Set encoding of input DATA_MODE
data - see 5.10 Setting data - see 5.11 Setting
the Input Mode. the Input Mode.
eci integer Extended Channel 0 (none) eci integer Extended Channel 0 (none)
@ -2009,7 +2039,7 @@ encoding stages. The zint_symbol structure consists of the following members:
warn_level integer Affects error/warning WARN_DEFAULT warn_level integer Affects error/warning WARN_DEFAULT
value returned by Zint value returned by Zint
API - see 5.7 Handling API - see 5.8 Handling
Errors. Errors.
text unsigned Human Readable Text, which "" (empty) text unsigned Human Readable Text, which "" (empty)
@ -2036,7 +2066,7 @@ encoding stages. The zint_symbol structure consists of the following members:
errtxt character Error message in the event (output only) errtxt character Error message in the event (output only)
string that an error occurred, string that an error occurred,
with a terminating NUL - with a terminating NUL -
see 5.7 Handling Errors. see 5.8 Handling Errors.
bitmap pointer to Pointer to stored bitmap (output only) bitmap pointer to Pointer to stored bitmap (output only)
unsigned image - see 5.4 Buffering unsigned image - see 5.4 Buffering
@ -2062,6 +2092,16 @@ encoding stages. The zint_symbol structure consists of the following members:
structure vector elements - see 5.5 structure vector elements - see 5.5
Buffering Symbols in Buffering Symbols in
Memory (vector). Memory (vector).
memfile pointer to Pointer to in-memory file (output only)
unsigned buffer if
character BARCODE_MEMORY_FILE set in
array output_options - see 5.6
Buffering Symbols in
Memory (memfile).
memfile_size integer Length of in-memory file (output only)
buffer.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
: Table  : API Structure zint_symbol : Table  : API Structure zint_symbol
@ -2091,7 +2131,7 @@ ignored:
This is what the CLI option --nobackground does - see 4.7 Using Colour. This is what the CLI option --nobackground does - see 4.7 Using Colour.
5.7 Handling Errors 5.8 Handling Errors
If errors occur during encoding a non-zero integer value is passed back to the If errors occur during encoding a non-zero integer value is passed back to the
calling application. In addition the errtxt member is set to a message detailing calling application. In addition the errtxt member is set to a message detailing
@ -2198,7 +2238,7 @@ This code will exit with the appropriate message:
To treat all warnings as errors, set symbol->warn_level to WARN_FAIL_ALL. To treat all warnings as errors, set symbol->warn_level to WARN_FAIL_ALL.
5.8 Specifying a Symbology 5.9 Specifying a Symbology
Symbologies can be specified by number or by name as shown in the Table Symbologies can be specified by number or by name as shown in the Table
: Barcode Types (Symbologies). For example : Barcode Types (Symbologies). For example
@ -2209,7 +2249,7 @@ means the same as
symbol->symbology = 50; symbol->symbology = 50;
5.9 Adjusting Output Options 5.10 Adjusting Output Options
The output_options member can be used to adjust various aspects of the output The output_options member can be used to adjust various aspects of the output
file. To select more than one option from the table below simply OR them file. To select more than one option from the table below simply OR them
@ -2222,10 +2262,10 @@ together when adjusting this value:
-------------------------- --------------------------------------------------- -------------------------- ---------------------------------------------------
0 No options selected. 0 No options selected.
BARCODE_BIND_TOP Boundary bar above the symbol only.[9] BARCODE_BIND_TOP Boundary bar above the symbol only.[10]
BARCODE_BIND Boundary bars above and below the symbol and BARCODE_BIND Boundary bars above and below the symbol and
between rows if stacking multiple symbols.[10] between rows if stacking multiple symbols.[11]
BARCODE_BOX Add a box surrounding the symbol and whitespace. BARCODE_BOX Add a box surrounding the symbol and whitespace.
@ -2252,7 +2292,7 @@ together when adjusting this value:
Symbols in Memory (raster). Symbols in Memory (raster).
BARCODE_QUIET_ZONES Add compliant quiet zones (additional to any BARCODE_QUIET_ZONES Add compliant quiet zones (additional to any
specified whitespace).[11] specified whitespace).[12]
BARCODE_NO_QUIET_ZONES Disable quiet zones, notably those with defaults. BARCODE_NO_QUIET_ZONES Disable quiet zones, notably those with defaults.
@ -2264,11 +2304,14 @@ together when adjusting this value:
EMBED_VECTOR_FONT Embed font in vector output - currently available EMBED_VECTOR_FONT Embed font in vector output - currently available
for SVG output only. for SVG output only.
BARCODE_MEMORY_FILE Write output to in-memory buffer symbol->memfile
instead of to outfile file.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
: Table  : API output_options Values : Table  : API output_options Values
5.10 Setting the Input Mode 5.11 Setting the Input Mode
The way in which the input data is encoded can be set using the input_mode The way in which the input data is encoded can be set using the input_mode
member. Valid values are shown in the table below. member. Valid values are shown in the table below.
@ -2345,7 +2388,7 @@ FAST_MODE causes a less optimal encodation scheme to be used for Data Matrix,
MicroPDF417 and PDF417. For QR Code and UPNQR, it affects Zints automatic mask MicroPDF417 and PDF417. For QR Code and UPNQR, it affects Zints automatic mask
selection - see 6.6.3 QR Code (ISO 18004) for details. selection - see 6.6.3 QR Code (ISO 18004) for details.
5.11 Multiple Segments 5.12 Multiple Segments
For input data requiring multiple ECIs, the following functions may be used: For input data requiring multiple ECIs, the following functions may be used:
@ -2399,7 +2442,7 @@ example:
A maximum of 256 segments may be specified. Use of multiple segments with GS1 A maximum of 256 segments may be specified. Use of multiple segments with GS1
data is not currently supported. data is not currently supported.
5.12 Scaling Helpers 5.13 Scaling Helpers
To help with scaling the output, the following three function are available: To help with scaling the output, the following three function are available:
@ -2442,7 +2485,7 @@ 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 scanner used, the intended scanning distance, and what media (“substrates”) the
barcode appears on. barcode appears on.
5.13 Verifying Symbology Availability 5.14 Verifying Symbology Availability
An additional function available in the API is: An additional function available in the API is:
@ -2472,7 +2515,7 @@ success. For instance:
will print BARCODE_PDF417. will print BARCODE_PDF417.
5.14 Checking Symbology Capabilities 5.15 Checking Symbology Capabilities
It can be useful for frontend programs to know the capabilities of a symbology. It can be useful for frontend programs to know the capabilities of a symbology.
This can be determined using another additional function: This can be determined using another additional function:
@ -2489,7 +2532,7 @@ see which are set.
ZINT_CAP_STACKABLE Is the symbology stackable? ZINT_CAP_STACKABLE Is the symbology stackable?
ZINT_CAP_EANUPC[12] Is the symbology EAN/UPC? ZINT_CAP_EANUPC[13] Is the symbology EAN/UPC?
ZINT_CAP_COMPOSITE Does the symbology support composite data? (see ZINT_CAP_COMPOSITE Does the symbology support composite data? (see
6.3 GS1 Composite Symbols (ISO 24723) below) 6.3 GS1 Composite Symbols (ISO 24723) below)
@ -2535,7 +2578,7 @@ For example:
printf("PDF417 does not support ECI\n"); printf("PDF417 does not support ECI\n");
} }
5.15 Zint Version 5.16 Zint Version
Whether the Zint library linked to was built with PNG support may be determined Whether the Zint library linked to was built with PNG support may be determined
with: with:
@ -2995,7 +3038,7 @@ all-numeric characters.
[zint -b CODE128AB -d "130170X178"] [zint -b CODE128AB -d "130170X178"]
It is sometimes advantageous to stop Code 128 from using Code Set C which It is sometimes advantageous to stop Code 128 from using Code Set C which
compresses numerical data. The BARCODE_CODE128AB[13] variant (symbology 60) compresses numerical data. The BARCODE_CODE128AB[14] variant (symbology 60)
suppresses Code Set C in favour of Code Sets A and B. suppresses Code Set C in favour of Code Sets A and B.
Note that the special escapes to manually switch Code Sets mentioned above are Note that the special escapes to manually switch Code Sets mentioned above are
@ -4689,7 +4732,7 @@ QZint renders a barcode by drawing the vector representation (see 5.5 Buffering
Symbols in Memory (vector)) provided by the Zint library libzint. Symbols in Memory (vector)) provided by the Zint library libzint.
The main class is Zint::QZint, which has getter/setter properties that The main class is Zint::QZint, which has getter/setter properties that
correspond to the zint_symbol structure (see 5.6 Setting Options), and a main correspond to the zint_symbol structure (see 5.7 Setting Options), and a main
method render() which takes a Qt QPainter to paint with, and a QRectF method render() which takes a Qt QPainter to paint with, and a QRectF
rectangular area specifying where to paint into: rectangular area specifying where to paint into:
@ -5492,24 +5535,28 @@ the yen sign (¥), and tilde (~) to overline (U+203E).
[6] ISO/IEC 646 Invariant is a subset of ASCII with 12 characters undefined: #, [6] ISO/IEC 646 Invariant is a subset of ASCII with 12 characters undefined: #,
$, @, [, \, ], ^, `, {, |, }, ~. $, @, [, \, ], ^, `, {, |, }, ~.
[7] The height value is ignored for Aztec (including HIBC and Aztec Rune), Code [7] BARCODE_MEMORY_FILE textual formats EPS and SVG will have Unix newlines (LF)
on both Windows and Unix, i.e. not CR+LF on Windows.
[8] The height value is ignored for Aztec (including HIBC and Aztec Rune), Code
One, Data Matrix (including HIBC), DotCode, Grid Matrix, Han Xin, MaxiCode, QR One, Data Matrix (including HIBC), DotCode, Grid Matrix, Han Xin, MaxiCode, QR
Code (including HIBC, Micro QR, rMQR and UPNQR), and Ultracode - all of which Code (including HIBC, Micro QR, rMQR and UPNQR), and Ultracode - all of which
have a fixed width-to-height ratio (or, in the case of Code One, a fixed have a fixed width-to-height ratio (or, in the case of Code One, a fixed
height). height).
[8] For Windows, outfile is assumed to be UTF-8 encoded. [9] For Windows, outfile is assumed to be UTF-8 encoded.
[9] The BARCODE_BIND_TOP flag is set by default for DPD - see 6.1.10.7 DPD Code. [10] The BARCODE_BIND_TOP flag is set by default for DPD - see 6.1.10.7 DPD
Code.
[10] The BARCODE_BIND flag is always set for Codablock-F, Code 16K and Code 49. [11] The BARCODE_BIND flag is always set for Codablock-F, Code 16K and Code 49.
Special considerations apply to ITF-14 - see 6.1.2.6 ITF-14. Special considerations apply to ITF-14 - see 6.1.2.6 ITF-14.
[11] Codablock-F, Code 16K, Code 49, EAN-2 to EAN-13, ISBN, ITF-14, UPC-A and [12] 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. UPC-E have compliant quiet zones added by default.
[12] ZINT_CAP_EANUPC was previously named ZINT_CAP_EXTENDABLE, which is still [13] ZINT_CAP_EANUPC was previously named ZINT_CAP_EXTENDABLE, which is still
recognised. recognised.
[13] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still [14] BARCODE_CODE128AB previously used the name BARCODE_CODE128B, which is still
recognised. recognised.

View File

@ -44,16 +44,20 @@ typedef char static_assert_int_at_least_32bits[sizeof(int) * CHAR_BIT < 32 ? -1
#define ARRAY_SIZE(x) ((int) (sizeof(x) / sizeof((x)[0]))) #define ARRAY_SIZE(x) ((int) (sizeof(x) / sizeof((x)[0])))
#endif #endif
/* Determine if C89 (excluding MSVC, which doesn't define __STDC_VERSION__) */ /* Determine if C89 or C99 (excluding MSVC, which doesn't define __STDC_VERSION__) */
#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199000L) #ifndef _MSC_VER
# if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199000L
# define ZINT_IS_C89 # define ZINT_IS_C89
# elif __STDC_VERSION__ <= 199901L /* Actually includes pseudo-standards "C94/C95" as well */
# define ZINT_IS_C99
# endif
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
# include <malloc.h> # include <malloc.h>
# define z_alloca(nmemb) _alloca(nmemb) # define z_alloca(nmemb) _alloca(nmemb)
#else #else
# if defined(ZINT_IS_C89) || defined(__NuttX__) /* C89 or NuttX RTOS */ # if defined(ZINT_IS_C89) || defined(ZINT_IS_C99) || defined(__NuttX__) /* C89 or C99 or NuttX RTOS */
# include <alloca.h> # include <alloca.h>
# endif # endif
# define z_alloca(nmemb) alloca(nmemb) # define z_alloca(nmemb) alloca(nmemb)

View File

@ -326,11 +326,11 @@ version_replace(2, $data_dirname . 'win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp'
// win32/vs2008/libzint.vcproj // win32/vs2008/libzint.vcproj
version_replace(3, $data_dirname . 'win32/vs2008/libzint.vcproj', '/ZINT_VERSION=&quot;/', '/&quot;[0-9.]+/', '&quot;' . $v_str); version_replace(2, $data_dirname . 'win32/vs2008/libzint.vcproj', '/ZINT_VERSION=&quot;/', '/&quot;[0-9.]+/', '&quot;' . $v_str);
// win32/vs2008/zint.vcproj // win32/vs2008/zint.vcproj
version_replace(3, $data_dirname . 'win32/vs2008/zint.vcproj', '/ZINT_VERSION=&quot;/', '/&quot;[0-9.]+/', '&quot;' . $v_str); version_replace(2, $data_dirname . 'win32/vs2008/zint.vcproj', '/ZINT_VERSION=&quot;/', '/&quot;[0-9.]+/', '&quot;' . $v_str);
// win32/vs2015/libzint.vcxproj // win32/vs2015/libzint.vcxproj

View File

@ -139,6 +139,7 @@
<ClCompile Include="..\backend\dotcode.c" /> <ClCompile Include="..\backend\dotcode.c" />
<ClCompile Include="..\backend\eci.c" /> <ClCompile Include="..\backend\eci.c" />
<ClCompile Include="..\backend\emf.c" /> <ClCompile Include="..\backend\emf.c" />
<ClCompile Include="..\backend\filemem.c" />
<ClCompile Include="..\backend\general_field.c" /> <ClCompile Include="..\backend\general_field.c" />
<ClCompile Include="..\backend\gif.c" /> <ClCompile Include="..\backend\gif.c" />
<ClCompile Include="..\backend\gridmtx.c" /> <ClCompile Include="..\backend\gridmtx.c" />
@ -187,6 +188,7 @@
<ClInclude Include="..\backend\gb18030.h" /> <ClInclude Include="..\backend\gb18030.h" />
<ClInclude Include="..\backend\gb2312.h" /> <ClInclude Include="..\backend\gb2312.h" />
<ClInclude Include="..\backend\gbk.h" /> <ClInclude Include="..\backend\gbk.h" />
<ClInclude Include="..\backend\filemem.h" />
<ClInclude Include="..\backend\general_field.h" /> <ClInclude Include="..\backend\general_field.h" />
<ClInclude Include="..\backend\gridmtx.h" /> <ClInclude Include="..\backend\gridmtx.h" />
<ClInclude Include="..\backend\gs1.h" /> <ClInclude Include="..\backend\gs1.h" />

View File

@ -184,76 +184,6 @@
Name="VCPostBuildEventTool" Name="VCPostBuildEventTool"
/> />
</Configuration> </Configuration>
<Configuration
Name="Release_LIB|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="2"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
EnableIntrinsicFunctions="false"
AdditionalIncludeDirectories="d:\opt\include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ZINT_VERSION=&quot;\&quot;2.13.0.9\&quot;&quot;"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="false"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="0"
CompileAs="0"
DisableSpecificWarnings="4018;4244;4305"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
PreprocessorDefinitions="NDEBUG"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="$(OutDir)\libzintMD.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations> </Configurations>
<References> <References>
</References> </References>
@ -318,14 +248,6 @@
<File <File
RelativePath="..\..\backend\dllversion.c" RelativePath="..\..\backend\dllversion.c"
> >
<FileConfiguration
Name="Release_LIB|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File> </File>
<File <File
RelativePath="..\..\backend\dmatrix.c" RelativePath="..\..\backend\dmatrix.c"
@ -343,6 +265,10 @@
RelativePath="..\..\backend\emf.c" RelativePath="..\..\backend\emf.c"
> >
</File> </File>
<File
RelativePath="..\..\backend\filemem.c"
>
</File>
<File <File
RelativePath="..\..\backend\general_field.c" RelativePath="..\..\backend\general_field.c"
> >
@ -533,6 +459,10 @@
RelativePath="..\..\backend\gbk.h" RelativePath="..\..\backend\gbk.h"
> >
</File> </File>
<File
RelativePath="..\..\backend\filemem.h"
>
</File>
<File <File
RelativePath="..\..\backend\general_field.h" RelativePath="..\..\backend\general_field.h"
> >
@ -642,14 +572,6 @@
<File <File
RelativePath="..\..\backend\libzint.rc" RelativePath="..\..\backend\libzint.rc"
> >
<FileConfiguration
Name="Release_LIB|Win32"
ExcludedFromBuild="true"
>
<Tool
Name="VCResourceCompilerTool"
/>
</FileConfiguration>
</File> </File>
</Filter> </Filter>
</Files> </Files>

29
win32/vs2008/zint.sln Normal file
View File

@ -0,0 +1,29 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zint", "zint.vcproj", "{3169C7FA-E52C-4BFC-B7BB-E55EBA133770}"
ProjectSection(ProjectDependencies) = postProject
{5C08DC40-8F7D-475E-AA3C-814DED735A4B} = {5C08DC40-8F7D-475E-AA3C-814DED735A4B}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzint", "libzint.vcproj", "{5C08DC40-8F7D-475E-AA3C-814DED735A4B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{3169C7FA-E52C-4BFC-B7BB-E55EBA133770}.Debug|Win32.ActiveCfg = Debug|Win32
{3169C7FA-E52C-4BFC-B7BB-E55EBA133770}.Debug|Win32.Build.0 = Debug|Win32
{3169C7FA-E52C-4BFC-B7BB-E55EBA133770}.Release|Win32.ActiveCfg = Release|Win32
{3169C7FA-E52C-4BFC-B7BB-E55EBA133770}.Release|Win32.Build.0 = Release|Win32
{5C08DC40-8F7D-475E-AA3C-814DED735A4B}.Debug|Win32.ActiveCfg = Debug|Win32
{5C08DC40-8F7D-475E-AA3C-814DED735A4B}.Debug|Win32.Build.0 = Debug|Win32
{5C08DC40-8F7D-475E-AA3C-814DED735A4B}.Release|Win32.ActiveCfg = Release|Win32
{5C08DC40-8F7D-475E-AA3C-814DED735A4B}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -41,7 +41,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="0" Optimization="0"
AdditionalIncludeDirectories="..\backend" AdditionalIncludeDirectories="..\..\backend"
PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ZINT_VERSION=&quot;\&quot;2.13.0.9\&quot;&quot;;ZINT_DLL" PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ZINT_VERSION=&quot;\&quot;2.13.0.9\&quot;&quot;;ZINT_DLL"
MinimalRebuild="true" MinimalRebuild="true"
ExceptionHandling="0" ExceptionHandling="0"
@ -114,7 +114,7 @@
<Tool <Tool
Name="VCCLCompilerTool" Name="VCCLCompilerTool"
Optimization="2" Optimization="2"
AdditionalIncludeDirectories="..\backend" AdditionalIncludeDirectories="..\..\backend"
PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ZINT_VERSION=&quot;\&quot;2.13.0.9\&quot;&quot;;ZINT_DLL" PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ZINT_VERSION=&quot;\&quot;2.13.0.9\&quot;&quot;;ZINT_DLL"
StringPooling="true" StringPooling="true"
ExceptionHandling="0" ExceptionHandling="0"
@ -136,80 +136,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalLibraryDirectories="d:\opt\lib" AdditionalLibraryDirectories=""
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release_LIB|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
WholeProgramOptimization="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories="..\backend"
PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ZINT_VERSION=&quot;\&quot;2.13.0.9\&quot;&quot;"
StringPooling="true"
ExceptionHandling="0"
RuntimeLibrary="2"
EnableFunctionLevelLinking="false"
RuntimeTypeInfo="false"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="0"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="libpngMD.lib zlibMD.lib"
AdditionalLibraryDirectories="d:\opt\lib"
/> />
<Tool <Tool
Name="VCALinkTool" Name="VCALinkTool"
@ -243,15 +170,15 @@
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
> >
<File <File
RelativePath="..\getopt\getopt.c" RelativePath="..\..\getopt\getopt.c"
> >
</File> </File>
<File <File
RelativePath="..\getopt\getopt1.c" RelativePath="..\..\getopt\getopt1.c"
> >
</File> </File>
<File <File
RelativePath="..\frontend\main.c" RelativePath="..\..\frontend\main.c"
> >
</File> </File>
</Filter> </Filter>
@ -261,11 +188,11 @@
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
> >
<File <File
RelativePath=".\getopt\getopt.h" RelativePath="..\..\getopt\getopt.h"
> >
</File> </File>
<File <File
RelativePath="..\frontend\resource.h" RelativePath="..\..\frontend\resource.h"
> >
</File> </File>
</Filter> </Filter>
@ -275,7 +202,7 @@
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
> >
<File <File
RelativePath="..\frontend\zint.rc" RelativePath="..\..\frontend\zint.rc"
> >
</File> </File>
</Filter> </Filter>

View File

@ -316,6 +316,7 @@
<ClCompile Include="..\..\backend\dotcode.c" /> <ClCompile Include="..\..\backend\dotcode.c" />
<ClCompile Include="..\..\backend\eci.c" /> <ClCompile Include="..\..\backend\eci.c" />
<ClCompile Include="..\..\backend\emf.c" /> <ClCompile Include="..\..\backend\emf.c" />
<ClCompile Include="..\..\backend\filemem.c" />
<ClCompile Include="..\..\backend\general_field.c" /> <ClCompile Include="..\..\backend\general_field.c" />
<ClCompile Include="..\..\backend\gif.c" /> <ClCompile Include="..\..\backend\gif.c" />
<ClCompile Include="..\..\backend\gridmtx.c" /> <ClCompile Include="..\..\backend\gridmtx.c" />
@ -364,6 +365,7 @@
<ClInclude Include="..\..\backend\gb18030.h" /> <ClInclude Include="..\..\backend\gb18030.h" />
<ClInclude Include="..\..\backend\gb2312.h" /> <ClInclude Include="..\..\backend\gb2312.h" />
<ClInclude Include="..\..\backend\gbk.h" /> <ClInclude Include="..\..\backend\gbk.h" />
<ClInclude Include="..\..\backend\filemem.h" />
<ClInclude Include="..\..\backend\general_field.h" /> <ClInclude Include="..\..\backend\general_field.h" />
<ClInclude Include="..\..\backend\gridmtx.h" /> <ClInclude Include="..\..\backend\gridmtx.h" />
<ClInclude Include="..\..\backend\gs1.h" /> <ClInclude Include="..\..\backend\gs1.h" />

View File

@ -139,6 +139,7 @@
<ClCompile Include="..\..\backend\dotcode.c" /> <ClCompile Include="..\..\backend\dotcode.c" />
<ClCompile Include="..\..\backend\eci.c" /> <ClCompile Include="..\..\backend\eci.c" />
<ClCompile Include="..\..\backend\emf.c" /> <ClCompile Include="..\..\backend\emf.c" />
<ClCompile Include="..\..\backend\filemem.c" />
<ClCompile Include="..\..\backend\general_field.c" /> <ClCompile Include="..\..\backend\general_field.c" />
<ClCompile Include="..\..\backend\gif.c" /> <ClCompile Include="..\..\backend\gif.c" />
<ClCompile Include="..\..\backend\gridmtx.c" /> <ClCompile Include="..\..\backend\gridmtx.c" />
@ -187,6 +188,7 @@
<ClInclude Include="..\..\backend\gb18030.h" /> <ClInclude Include="..\..\backend\gb18030.h" />
<ClInclude Include="..\..\backend\gb2312.h" /> <ClInclude Include="..\..\backend\gb2312.h" />
<ClInclude Include="..\..\backend\gbk.h" /> <ClInclude Include="..\..\backend\gbk.h" />
<ClInclude Include="..\..\backend\filemem.h" />
<ClInclude Include="..\..\backend\general_field.h" /> <ClInclude Include="..\..\backend\general_field.h" />
<ClInclude Include="..\..\backend\gridmtx.h" /> <ClInclude Include="..\..\backend\gridmtx.h" />
<ClInclude Include="..\..\backend\gs1.h" /> <ClInclude Include="..\..\backend\gs1.h" />

View File

@ -139,6 +139,7 @@
<ClCompile Include="..\..\backend\dotcode.c" /> <ClCompile Include="..\..\backend\dotcode.c" />
<ClCompile Include="..\..\backend\eci.c" /> <ClCompile Include="..\..\backend\eci.c" />
<ClCompile Include="..\..\backend\emf.c" /> <ClCompile Include="..\..\backend\emf.c" />
<ClCompile Include="..\..\backend\filemem.c" />
<ClCompile Include="..\..\backend\general_field.c" /> <ClCompile Include="..\..\backend\general_field.c" />
<ClCompile Include="..\..\backend\gif.c" /> <ClCompile Include="..\..\backend\gif.c" />
<ClCompile Include="..\..\backend\gridmtx.c" /> <ClCompile Include="..\..\backend\gridmtx.c" />
@ -187,6 +188,7 @@
<ClInclude Include="..\..\backend\gb18030.h" /> <ClInclude Include="..\..\backend\gb18030.h" />
<ClInclude Include="..\..\backend\gb2312.h" /> <ClInclude Include="..\..\backend\gb2312.h" />
<ClInclude Include="..\..\backend\gbk.h" /> <ClInclude Include="..\..\backend\gbk.h" />
<ClInclude Include="..\..\backend\filemem.h" />
<ClInclude Include="..\..\backend\general_field.h" /> <ClInclude Include="..\..\backend\general_field.h" />
<ClInclude Include="..\..\backend\gridmtx.h" /> <ClInclude Include="..\..\backend\gridmtx.h" />
<ClInclude Include="..\..\backend\gs1.h" /> <ClInclude Include="..\..\backend\gs1.h" />

View File

@ -156,6 +156,10 @@ SOURCE=..\..\backend\emf.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\backend\filemem.c
# End Source File
# Begin Source File
SOURCE=..\..\backend\general_field.c SOURCE=..\..\backend\general_field.c
# End Source File # End Source File
# Begin Source File # Begin Source File