mirror of
https://github.com/zint/zint
synced 2024-11-16 20:57:25 +13:00
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:
parent
070162214b
commit
98f86727cc
3
.clang-tidy
Normal file
3
.clang-tidy
Normal file
@ -0,0 +1,3 @@
|
||||
---
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-security.insecureAPI.strcpy'
|
||||
HeaderFilterRegex: '.*'
|
@ -3,12 +3,16 @@ Version 2.13.0.9 (dev) not released yet
|
||||
|
||||
**Incompatible changes**
|
||||
------------------------
|
||||
None so far
|
||||
- New `memfile` & `memfile_size` fields in `symbol` for use with new output
|
||||
option `BARCODE_MEMORY_FILE`
|
||||
|
||||
Changes
|
||||
-------
|
||||
- BMP: lessen heap memory usage by only `malloc()`ing a row
|
||||
- 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
|
||||
----
|
||||
|
21
README.clang-tidy
Normal file
21
README.clang-tidy
Normal 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
|
@ -8,7 +8,7 @@ if(ZINT_USE_PNG)
|
||||
find_package(PNG)
|
||||
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_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)
|
||||
|
@ -24,7 +24,7 @@ APP:=zint
|
||||
DLL:=$(APP).dll
|
||||
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
|
||||
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
|
||||
|
@ -33,11 +33,8 @@
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include "common.h"
|
||||
#include "filemem.h"
|
||||
#include "output.h"
|
||||
#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 resolution;
|
||||
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_info_header_t info_header;
|
||||
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];
|
||||
int ultra_fg_index = 9;
|
||||
unsigned char map[128];
|
||||
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT; /* Suppress gcc -fanalyzer warning */
|
||||
unsigned char *rowbuf;
|
||||
|
||||
(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;
|
||||
|
||||
/* Open output file in binary mode */
|
||||
if (output_to_stdout) {
|
||||
#ifdef _MSC_VER
|
||||
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
|
||||
sprintf(symbol->errtxt, "600: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_open(fmp, symbol, "wb")) {
|
||||
sprintf(symbol->errtxt, "601: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
free(rowbuf);
|
||||
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);
|
||||
fwrite(&info_header, sizeof(bitmap_info_header_t), 1, bmp_file);
|
||||
fm_write(&file_header, sizeof(bitmap_file_header_t), 1, fmp);
|
||||
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) {
|
||||
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) {
|
||||
fwrite(&fg, sizeof(color_ref_t), 1, bmp_file);
|
||||
fm_write(&fg, sizeof(color_ref_t), 1, fmp);
|
||||
}
|
||||
} else {
|
||||
fwrite(&fg, sizeof(color_ref_t), 1, bmp_file);
|
||||
fm_write(&fg, sizeof(color_ref_t), 1, fmp);
|
||||
}
|
||||
|
||||
/* 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++) {
|
||||
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 */
|
||||
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++) {
|
||||
rowbuf[column >> 3] |= map[pb[column]] >> (column & 7);
|
||||
}
|
||||
fwrite(rowbuf, 1, row_size, bmp_file);
|
||||
fm_write(rowbuf, 1, row_size, fmp);
|
||||
}
|
||||
}
|
||||
free(rowbuf);
|
||||
|
||||
if (ferror(bmp_file)) {
|
||||
sprintf(symbol->errtxt, "603: Incomplete write to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(bmp_file);
|
||||
}
|
||||
if (fm_error(fmp)) {
|
||||
sprintf(symbol->errtxt, "603: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
if (fflush(bmp_file) != 0) {
|
||||
sprintf(symbol->errtxt, "604: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_close(fmp, symbol)) {
|
||||
sprintf(symbol->errtxt, "605: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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;
|
||||
}
|
||||
|
@ -606,6 +606,11 @@ INTERNAL char *debug_print_escape(const unsigned char *source, const int first_l
|
||||
}
|
||||
|
||||
#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) */
|
||||
INTERNAL void debug_test_codeword_dump(struct zint_symbol *symbol, const unsigned char *codewords, const int length) {
|
||||
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 */
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif /*ZINT_TEST*/
|
||||
|
||||
/* vim: set ts=4 sw=4 et : */
|
||||
|
@ -41,21 +41,37 @@ extern "C" {
|
||||
#define ARRAY_SIZE(x) ((int) (sizeof(x) / sizeof((x)[0])))
|
||||
#endif
|
||||
|
||||
/* Determine if C89 (excluding MSVC, which doesn't define __STDC_VERSION__) */
|
||||
#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199000L)
|
||||
#define ZINT_IS_C89
|
||||
/* Determine if C89 or C99 (excluding MSVC, which doesn't define __STDC_VERSION__) */
|
||||
#ifndef _MSC_VER
|
||||
# if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199000L
|
||||
# define ZINT_IS_C89
|
||||
# elif __STDC_VERSION__ <= 199901L /* Actually includes pseudo-standards "C94/C95" as well */
|
||||
# define ZINT_IS_C99
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <malloc.h>
|
||||
# define z_alloca(nmemb) _alloca(nmemb)
|
||||
#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>
|
||||
# endif
|
||||
# define z_alloca(nmemb) alloca(nmemb)
|
||||
#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
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
|
102
backend/emf.c
102
backend/emf.c
@ -37,11 +37,8 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include "common.h"
|
||||
#include "filemem.h"
|
||||
#include "output.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) {
|
||||
int i;
|
||||
FILE *emf_file;
|
||||
struct filemem fm;
|
||||
struct filemem *const fmp = &fm;
|
||||
unsigned char fgred, fggrn, fgblu, bgred, bggrn, bgblu, bgalpha;
|
||||
int error_number = 0;
|
||||
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 bold;
|
||||
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_circle *circ;
|
||||
@ -703,66 +700,56 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
|
||||
emr_header.emf_header.records = recordcount;
|
||||
|
||||
/* Send EMF data to file */
|
||||
if (output_to_stdout) {
|
||||
#ifdef _MSC_VER
|
||||
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
|
||||
sprintf(symbol->errtxt, "642: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_open(fmp, symbol, "wb")) {
|
||||
sprintf(symbol->errtxt, "640: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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) {
|
||||
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) {
|
||||
for (i = 0; i < 9; 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 {
|
||||
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) {
|
||||
fwrite(&emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw_t), 1, emf_file);
|
||||
fm_write(&emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw_t), 1, fmp);
|
||||
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);
|
||||
fwrite(&emr_selectobject_pen, sizeof(emr_selectobject_t), 1, emf_file);
|
||||
fm_write(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, fmp);
|
||||
fm_write(&emr_selectobject_pen, sizeof(emr_selectobject_t), 1, fmp);
|
||||
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) {
|
||||
for (i = 0; i < 9; 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;
|
||||
this_rectangle = 0;
|
||||
while (rect) {
|
||||
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++;
|
||||
rect = rect->next;
|
||||
@ -770,42 +757,42 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file);
|
||||
fm_write(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, fmp);
|
||||
|
||||
/* Rectangles */
|
||||
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 */
|
||||
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 */
|
||||
if (symbol->symbology == BARCODE_MAXICODE) {
|
||||
/* Bullseye needed */
|
||||
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 % 2) {
|
||||
fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file);
|
||||
fm_write(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, fmp);
|
||||
} else {
|
||||
fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file);
|
||||
fm_write(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, fmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
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 */
|
||||
if (string_count > 0) {
|
||||
fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file);
|
||||
fwrite(&emr_settextcolor, sizeof(emr_settextcolor_t), 1, emf_file);
|
||||
fm_write(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, fmp);
|
||||
fm_write(&emr_settextcolor, sizeof(emr_settextcolor_t), 1, fmp);
|
||||
}
|
||||
|
||||
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++) {
|
||||
if (text_fsizes[i] != current_fsize) {
|
||||
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) {
|
||||
current_halign = text_haligns[i];
|
||||
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) {
|
||||
fwrite(&emr_settextalign_left, sizeof(emr_settextalign_t), 1, emf_file);
|
||||
fm_write(&emr_settextalign_left, sizeof(emr_settextalign_t), 1, fmp);
|
||||
} 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);
|
||||
fwrite(this_string[i], emf_bump_up(text[i].w_emr_text.chars), 1, emf_file);
|
||||
fm_write(&text[i], sizeof(emr_exttextoutw_t), 1, fmp);
|
||||
fm_write(this_string[i], emf_bump_up(text[i].w_emr_text.chars), 1, fmp);
|
||||
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)) {
|
||||
sprintf(symbol->errtxt, "644: Incomplete write to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(emf_file);
|
||||
}
|
||||
if (fm_error(fmp)) {
|
||||
sprintf(symbol->errtxt, "644: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
if (fflush(emf_file) != 0) {
|
||||
sprintf(symbol->errtxt, "940: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_close(fmp, symbol)) {
|
||||
sprintf(symbol->errtxt, "941: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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;
|
||||
}
|
||||
|
||||
|
464
backend/filemem.c
Normal file
464
backend/filemem.c
Normal 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
95
backend/filemem.h
Normal 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 */
|
@ -32,18 +32,15 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include "common.h"
|
||||
#include "filemem.h"
|
||||
#include "output.h"
|
||||
|
||||
/* Limit initial LZW buffer size to this in expectation that compressed data will fit for typical scalings */
|
||||
#define GIF_LZW_PAGE_SIZE 0x100000 /* Megabyte */
|
||||
|
||||
typedef struct s_statestruct {
|
||||
FILE *file;
|
||||
struct filemem *fmp;
|
||||
unsigned char *pOut;
|
||||
const unsigned char *pIn;
|
||||
const unsigned char *pInEnd;
|
||||
@ -65,7 +62,7 @@ static void BufferNextByte(statestruct *pState) {
|
||||
(pState->OutPosCur)++;
|
||||
if (pState->fOutPaged && pState->OutPosCur + 2 >= pState->OutLength) {
|
||||
/* 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);
|
||||
pState->OutByteCountPos -= 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
|
||||
*/
|
||||
INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) {
|
||||
struct filemem fm;
|
||||
unsigned char outbuf[10];
|
||||
unsigned short usTemp;
|
||||
unsigned char paletteRGB[10][3];
|
||||
@ -250,7 +248,6 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
statestruct State;
|
||||
int transparent_index;
|
||||
int bgindex = -1, fgindex = -1;
|
||||
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT;
|
||||
|
||||
static const unsigned char RGBUnused[3] = {0,0,0};
|
||||
unsigned char RGBfg[3];
|
||||
@ -277,23 +274,15 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
|
||||
State.fmp = &fm;
|
||||
|
||||
/* Open output file in binary mode */
|
||||
if (output_to_stdout) {
|
||||
#ifdef _MSC_VER
|
||||
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
|
||||
sprintf(symbol->errtxt, "610: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_open(State.fmp, symbol, "wb")) {
|
||||
sprintf(symbol->errtxt, "611: Could not open output file (%d: %.30s)", State.fmp->err,
|
||||
strerror(State.fmp->err));
|
||||
free(State.pOut);
|
||||
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.
|
||||
@ -310,7 +299,6 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
* 'K': black
|
||||
* '0' and '1' may be identical to one of the other values
|
||||
*/
|
||||
paletteCount = 0;
|
||||
memset(State.map, 0, sizeof(State.map));
|
||||
if (symbol->symbology == BARCODE_ULTRA) {
|
||||
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)
|
||||
outbuf[4] = '9';
|
||||
|
||||
fwrite(outbuf, 1, 6, State.file);
|
||||
fm_write(outbuf, 1, 6, State.fmp);
|
||||
/* Screen Descriptor (7) */
|
||||
/* Screen 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;
|
||||
/* Byte 7 must be 0x00 */
|
||||
outbuf[6] = 0x00;
|
||||
fwrite(outbuf, 1, 7, State.file);
|
||||
fm_write(outbuf, 1, 7, State.fmp);
|
||||
/* 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 */
|
||||
for (i = paletteCount; i < paletteSize; i++) {
|
||||
fwrite(RGBUnused, 1, 3, State.file);
|
||||
fm_write(RGBUnused, 1, 3, State.fmp);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
/* Block Terminator */
|
||||
outbuf[7] = 0;
|
||||
fwrite(outbuf, 1, 8, State.file);
|
||||
fm_write(outbuf, 1, 8, State.fmp);
|
||||
}
|
||||
/* Image Descriptor */
|
||||
/* 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.
|
||||
*/
|
||||
outbuf[9] = 0x00;
|
||||
fwrite(outbuf, 1, 10, State.file);
|
||||
fm_write(outbuf, 1, 10, State.fmp);
|
||||
|
||||
/* call lzw encoding */
|
||||
if (!gif_lzw(&State, paletteBitSize)) {
|
||||
free(State.pOut);
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(State.file);
|
||||
}
|
||||
(void) fm_close(State.fmp, symbol);
|
||||
strcpy(symbol->errtxt, "613: Insufficient memory for LZW buffer");
|
||||
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);
|
||||
|
||||
/* GIF terminator */
|
||||
fputc('\x3b', State.file);
|
||||
fm_putc('\x3b', State.fmp);
|
||||
|
||||
if (ferror(State.file)) {
|
||||
sprintf(symbol->errtxt, "615: Incomplete write to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(State.file);
|
||||
}
|
||||
if (fm_error(State.fmp)) {
|
||||
sprintf(symbol->errtxt, "615: Incomplete write to output (%d: %.30s)", State.fmp->err,
|
||||
strerror(State.fmp->err));
|
||||
(void) fm_close(State.fmp, symbol);
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
if (fflush(State.file) != 0) {
|
||||
sprintf(symbol->errtxt, "616: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_close(State.fmp, symbol)) {
|
||||
sprintf(symbol->errtxt, "617: Failure on closing output file (%d: %.30s)", State.fmp->err,
|
||||
strerror(State.fmp->err));
|
||||
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;
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ static void set_symbol_defaults(struct zint_symbol *symbol) {
|
||||
symbol->bitmap = NULL;
|
||||
symbol->alphamap = NULL;
|
||||
symbol->vector = NULL;
|
||||
symbol->memfile = NULL;
|
||||
}
|
||||
|
||||
/* Create and initialize a symbol structure */
|
||||
@ -115,6 +116,11 @@ void ZBarcode_Clear(struct zint_symbol *symbol) {
|
||||
}
|
||||
symbol->bitmap_width = 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 */
|
||||
vector_free(symbol);
|
||||
@ -130,6 +136,9 @@ void ZBarcode_Reset(struct zint_symbol *symbol) {
|
||||
if (symbol->alphamap != NULL) {
|
||||
free(symbol->alphamap);
|
||||
}
|
||||
if (symbol->memfile != NULL) {
|
||||
free(symbol->memfile);
|
||||
}
|
||||
vector_free(symbol);
|
||||
|
||||
memset(symbol, 0, sizeof(*symbol));
|
||||
@ -144,6 +153,8 @@ void ZBarcode_Delete(struct zint_symbol *symbol) {
|
||||
free(symbol->bitmap);
|
||||
if (symbol->alphamap != NULL)
|
||||
free(symbol->alphamap);
|
||||
if (symbol->memfile != NULL)
|
||||
free(symbol->memfile);
|
||||
|
||||
/* If there is a rendered version, ensure its memory is released */
|
||||
vector_free(symbol);
|
||||
@ -1556,7 +1567,7 @@ int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename) {
|
||||
|
||||
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) {
|
||||
(void) fclose(file);
|
||||
return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "235: Input file empty or unseekable");
|
||||
|
@ -997,34 +997,4 @@ INTERNAL FILE *out_fopen(const char filename[256], const char *mode) {
|
||||
return outfile;
|
||||
}
|
||||
|
||||
/* Output float without trailing zeroes to `fp` with decimal pts `dp` (precision) */
|
||||
INTERNAL void out_putsf(const char *const prefix, const int dp, const float arg, FILE *fp) {
|
||||
int i, end;
|
||||
char buf[256]; /* Assuming `dp` reasonable */
|
||||
const int len = sprintf(buf, "%.*f", dp, arg);
|
||||
|
||||
if (*prefix) {
|
||||
fputs(prefix, fp);
|
||||
}
|
||||
|
||||
/* Adapted from https://stackoverflow.com/a/36202854/664741 */
|
||||
for (i = len - 1, end = len; i >= 0; i--) {
|
||||
if (buf[i] == '0') {
|
||||
if (end == i + 1) {
|
||||
end = i;
|
||||
}
|
||||
} else if (!z_isdigit(buf[i]) && buf[i] != '-') { /* If not digit or minus then decimal point */
|
||||
if (end == i + 1) {
|
||||
end = i;
|
||||
} else {
|
||||
buf[i] = '.'; /* Overwrite any locale-specific setting for decimal point */
|
||||
}
|
||||
buf[end] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fputs(buf, fp);
|
||||
}
|
||||
|
||||
/* vim: set ts=4 sw=4 et : */
|
||||
|
@ -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);
|
||||
#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
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
@ -33,11 +33,8 @@
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include "common.h"
|
||||
#include "filemem.h"
|
||||
#include "output.h"
|
||||
#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;
|
||||
int row, column, i, colour;
|
||||
int run_count;
|
||||
FILE *pcx_file;
|
||||
struct filemem fm;
|
||||
struct filemem *const fmp = &fm;
|
||||
pcx_header_t header;
|
||||
unsigned char previous;
|
||||
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 */
|
||||
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 */
|
||||
if (output_to_stdout) {
|
||||
#ifdef _MSC_VER
|
||||
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
|
||||
sprintf(symbol->errtxt, "620: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_open(fmp, symbol, "wb")) {
|
||||
sprintf(symbol->errtxt, "621: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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 (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 {
|
||||
if (run_count > 1 || (previous & 0xc0) == 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];
|
||||
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) {
|
||||
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)) {
|
||||
sprintf(symbol->errtxt, "622: Incomplete write to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(pcx_file);
|
||||
}
|
||||
if (fm_error(fmp)) {
|
||||
sprintf(symbol->errtxt, "622: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
if (fflush(pcx_file) != 0) {
|
||||
sprintf(symbol->errtxt, "623: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_close(fmp, symbol)) {
|
||||
sprintf(symbol->errtxt, "624: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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;
|
||||
}
|
||||
|
@ -35,16 +35,15 @@
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include <png.h>
|
||||
#include <zlib.h>
|
||||
#include <setjmp.h>
|
||||
#include "common.h"
|
||||
#include "filemem.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 */
|
||||
struct wpng_error_type {
|
||||
struct zint_symbol *symbol;
|
||||
@ -72,8 +71,20 @@ INTERNAL void wpng_error_handler_test(png_structp png_ptr, png_const_charp msg)
|
||||
}
|
||||
#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 */
|
||||
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;
|
||||
|
||||
/* 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) {
|
||||
struct wpng_error_type wpng_error;
|
||||
FILE *outfile;
|
||||
struct filemem fm;
|
||||
struct filemem *const fmp = &fm;
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
int i;
|
||||
@ -105,11 +117,10 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
|
||||
png_color palette[32];
|
||||
int num_palette;
|
||||
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 compression_strategy;
|
||||
const unsigned char *pb;
|
||||
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT;
|
||||
unsigned char *outdata = (unsigned char *) z_alloca(symbol->bitmap_width);
|
||||
|
||||
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->bgcolour, &bg.red, &bg.green, &bg.blue, &bg_alpha);
|
||||
|
||||
num_trans = 0;
|
||||
if (symbol->symbology == BARCODE_ULTRA) {
|
||||
static const unsigned char ultra_chars[8] = { 'W', 'C', 'B', 'M', 'R', 'Y', 'G', 'K' };
|
||||
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 */
|
||||
if (output_to_stdout) {
|
||||
#ifdef _MSC_VER
|
||||
if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
|
||||
sprintf(symbol->errtxt, "631: Could not set stdout to binary (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_open(fmp, symbol, "wb")) {
|
||||
sprintf(symbol->errtxt, "632: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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 */
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, &wpng_error, wpng_error_handler, NULL);
|
||||
if (!png_ptr) {
|
||||
strcpy(symbol->errtxt, "633: Insufficient memory for PNG write structure buffer");
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(outfile);
|
||||
}
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
|
||||
@ -228,29 +228,25 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
|
||||
if (!info_ptr) {
|
||||
png_destroy_write_struct(&png_ptr, NULL);
|
||||
strcpy(symbol->errtxt, "634: Insufficient memory for PNG info structure buffer");
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(outfile);
|
||||
}
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
|
||||
/* catch jumping here */
|
||||
if (setjmp(wpng_error.jmpbuf)) {
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(outfile);
|
||||
}
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
|
||||
/* open output file with libpng */
|
||||
png_init_io(png_ptr, outfile);
|
||||
/* Set our output functions */
|
||||
png_set_write_fn(png_ptr, fmp, wpng_write, wpng_flush);
|
||||
|
||||
/* set compression */
|
||||
png_set_compression_level(png_ptr, 9);
|
||||
|
||||
/* 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) {
|
||||
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 */
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
if (ferror(outfile)) {
|
||||
sprintf(symbol->errtxt, "638: Incomplete write to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(outfile);
|
||||
}
|
||||
if (fm_error(fmp)) {
|
||||
sprintf(symbol->errtxt, "638: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
if (fflush(outfile) != 0) {
|
||||
sprintf(symbol->errtxt, "639: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_close(fmp, symbol)) {
|
||||
sprintf(symbol->errtxt, "960: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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;
|
||||
}
|
||||
/* 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 */
|
||||
|
224
backend/ps.c
224
backend/ps.c
@ -35,10 +35,11 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "common.h"
|
||||
#include "filemem.h"
|
||||
#include "output.h"
|
||||
|
||||
/* 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*/;
|
||||
if (is_rgb) {
|
||||
/* 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) */
|
||||
"1 1 1", /* 7: White (8) */
|
||||
};
|
||||
fputs(ps_rgbs[idx], feps);
|
||||
fputs(" setrgbcolor\n", feps);
|
||||
fm_puts(ps_rgbs[idx], fmp);
|
||||
fm_puts(" setrgbcolor\n", fmp);
|
||||
} else {
|
||||
static const char ps_cmyks[8][8] = {
|
||||
"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 0", /* 7: White (8) */
|
||||
};
|
||||
fputs(ps_cmyks[idx], feps);
|
||||
fputs(" setcmykcolor\n", feps);
|
||||
fm_puts(ps_cmyks[idx], fmp);
|
||||
fm_puts(" setcmykcolor\n", fmp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -107,51 +108,52 @@ INTERNAL void ps_convert_test(const unsigned char *string, unsigned char *ps_str
|
||||
#endif
|
||||
|
||||
/* Helper to output RGB colour */
|
||||
static void ps_put_rgbcolor(const float red, const float green, const float blue, FILE *feps) {
|
||||
out_putsf("", 2, red, feps);
|
||||
out_putsf(" ", 2, green, feps);
|
||||
out_putsf(" ", 2, blue, feps);
|
||||
fputs(" setrgbcolor\n", feps);
|
||||
static void ps_put_rgbcolor(const float red, const float green, const float blue,
|
||||
struct filemem *const fmp) {
|
||||
fm_putsf("", 2, red, fmp);
|
||||
fm_putsf(" ", 2, green, fmp);
|
||||
fm_putsf(" ", 2, blue, fmp);
|
||||
fm_puts(" setrgbcolor\n", fmp);
|
||||
}
|
||||
|
||||
/* Helper to output CMYK colour */
|
||||
static void ps_put_cmykcolor(const float cyan, const float magenta, const float yellow, const float black,
|
||||
FILE *feps) {
|
||||
out_putsf("", 2, cyan, feps);
|
||||
out_putsf(" ", 2, magenta, feps);
|
||||
out_putsf(" ", 2, yellow, feps);
|
||||
out_putsf(" ", 2, black, feps);
|
||||
fputs(" setcmykcolor\n", feps);
|
||||
struct filemem *const fmp) {
|
||||
fm_putsf("", 2, cyan, fmp);
|
||||
fm_putsf(" ", 2, magenta, fmp);
|
||||
fm_putsf(" ", 2, yellow, fmp);
|
||||
fm_putsf(" ", 2, black, fmp);
|
||||
fm_puts(" setcmykcolor\n", fmp);
|
||||
}
|
||||
|
||||
/* Helper to output rectangle */
|
||||
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) {
|
||||
out_putsf("", 2, rect->height, feps);
|
||||
out_putsf(" ", 2, (symbol->vector->height - rect->y) - rect->height, feps);
|
||||
fm_putsf("", 2, rect->height, fmp);
|
||||
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);
|
||||
out_putsf(" ", 2, rect->width, feps);
|
||||
fputs(" R\n", feps);
|
||||
fm_putsf(type == 0 ? " " : type == 1 ? " I " : type == 2 ? "I " : "", 2, rect->x, fmp);
|
||||
fm_putsf(" ", 2, rect->width, fmp);
|
||||
fm_puts(" R\n", fmp);
|
||||
}
|
||||
|
||||
/* Helper to output circle/disc */
|
||||
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) {
|
||||
out_putsf("", 2, circle->x, feps);
|
||||
out_putsf(" ", 2, symbol->vector->height - circle->y, feps);
|
||||
out_putsf(" ", 4, radius, feps);
|
||||
out_putsf(" ", 4, circle->width, feps);
|
||||
fputs(" C\n", feps);
|
||||
fm_putsf("", 2, circle->x, fmp);
|
||||
fm_putsf(" ", 2, symbol->vector->height - circle->y, fmp);
|
||||
fm_putsf(" ", 4, radius, fmp);
|
||||
fm_putsf(" ", 4, circle->width, fmp);
|
||||
fm_puts(" C\n", fmp);
|
||||
} else {
|
||||
if (type == 0 || type == 1) {
|
||||
out_putsf("", 2, symbol->vector->height - circle->y, feps);
|
||||
out_putsf(" ", 4, radius, feps);
|
||||
fm_putsf("", 2, symbol->vector->height - circle->y, fmp);
|
||||
fm_putsf(" ", 4, radius, fmp);
|
||||
}
|
||||
out_putsf(type == 0 ? " " : type == 1 ? " I " : type == 2 ? "I " : "", 2, circle->x, feps);
|
||||
fputs(" D\n", feps);
|
||||
fm_putsf(type == 0 ? " " : type == 1 ? " I " : type == 2 ? "I " : "", 2, circle->x, fmp);
|
||||
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) {
|
||||
FILE *feps;
|
||||
struct filemem fm;
|
||||
struct filemem *const fmp = &fm;
|
||||
unsigned char fgred, fggrn, fgblu, bgred, bggrn, bgblu, bgalpha;
|
||||
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` */
|
||||
@ -190,22 +193,16 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
|
||||
int iso_latin1 = 0;
|
||||
int have_circles_with_width = 0, have_circles_without_width = 0;
|
||||
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;
|
||||
|
||||
if (symbol->vector == NULL) {
|
||||
strcpy(symbol->errtxt, "646: Vector header NULL");
|
||||
return ZINT_ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
feps = stdout;
|
||||
} else {
|
||||
if (!(feps = out_fopen(symbol->outfile, "w"))) {
|
||||
sprintf(symbol->errtxt, "645: Could not open output file (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_open(fmp, symbol, "w")) {
|
||||
sprintf(symbol->errtxt, "645: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
return ZINT_ERROR_FILE_ACCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_rgb) {
|
||||
(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 */
|
||||
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) {
|
||||
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);
|
||||
} 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"
|
||||
"%%Pages: 0\n", feps);
|
||||
fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n",
|
||||
fm_puts("%%Title: Zint Generated Symbol\n"
|
||||
"%%Pages: 0\n", fmp);
|
||||
fm_printf(fmp, "%%%%BoundingBox: 0 0 %d %d\n",
|
||||
(int) ceilf(symbol->vector->width), (int) ceilf(symbol->vector->height));
|
||||
fputs("%%EndComments\n", feps);
|
||||
fm_puts("%%EndComments\n", fmp);
|
||||
|
||||
/* Definitions */
|
||||
if (have_circles_without_width) {
|
||||
/* 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) {
|
||||
/* 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 }"
|
||||
" bind def\n", feps);
|
||||
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", fmp);
|
||||
}
|
||||
if (symbol->vector->hexagons) {
|
||||
/* Hexagon: radius half_radius half_sqrt3_radius x y */
|
||||
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 }"
|
||||
" bind def\n", feps);
|
||||
" bind def\n", fmp);
|
||||
} 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 }"
|
||||
" bind def\n", feps);
|
||||
" bind def\n", fmp);
|
||||
}
|
||||
/* 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 */
|
||||
}
|
||||
if (symbol->vector->rectangles || draw_background) {
|
||||
/* 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 }"
|
||||
" bind def\n", feps);
|
||||
fm_puts("/R { newpath 4 1 roll exch moveto 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill }"
|
||||
" bind def\n", fmp);
|
||||
}
|
||||
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 */
|
||||
fputs("/I { 2 copy } bind def\n", feps);
|
||||
fm_puts("/I { 2 copy } bind def\n", fmp);
|
||||
}
|
||||
|
||||
/* Now the actual representation */
|
||||
@ -319,21 +316,21 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
|
||||
/* Background */
|
||||
if (draw_background) {
|
||||
if (is_rgb) {
|
||||
ps_put_rgbcolor(red_paper, green_paper, blue_paper, feps);
|
||||
ps_put_rgbcolor(red_paper, green_paper, blue_paper, fmp);
|
||||
} 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);
|
||||
out_putsf(" 0 0 ", 2, symbol->vector->width, feps); /* y x w */
|
||||
fputs(" R\n", feps);
|
||||
fm_putsf("", 2, symbol->vector->height, fmp);
|
||||
fm_putsf(" 0 0 ", 2, symbol->vector->width, fmp); /* y x w */
|
||||
fm_puts(" R\n", fmp);
|
||||
}
|
||||
|
||||
if (symbol->symbology != BARCODE_ULTRA) {
|
||||
if (is_rgb) {
|
||||
ps_put_rgbcolor(red_ink, green_ink, blue_ink, feps);
|
||||
ps_put_rgbcolor(red_ink, green_ink, blue_ink, fmp);
|
||||
} 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) {
|
||||
/* Set foreground colour */
|
||||
if (is_rgb) {
|
||||
ps_put_rgbcolor(red_ink, green_ink, blue_ink, feps);
|
||||
ps_put_rgbcolor(red_ink, green_ink, blue_ink, fmp);
|
||||
} 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;
|
||||
}
|
||||
} else {
|
||||
/* 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) {
|
||||
ps_put_rect(symbol, rect, type_latch ? 2 : 1, feps);
|
||||
ps_put_rect(symbol, rect, type_latch ? 2 : 1, fmp);
|
||||
type_latch = 1;
|
||||
} else {
|
||||
ps_put_rect(symbol, rect, type_latch ? 3 : 0, feps);
|
||||
ps_put_rect(symbol, rect, type_latch ? 3 : 0, fmp);
|
||||
type_latch = 0;
|
||||
}
|
||||
}
|
||||
@ -385,10 +382,10 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
|
||||
type_latch = 0;
|
||||
for (rect = symbol->vector->rectangles; rect; rect = rect->next) {
|
||||
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;
|
||||
} else {
|
||||
ps_put_rect(symbol, rect, type_latch ? 3 : 0, feps);
|
||||
ps_put_rect(symbol, rect, type_latch ? 3 : 0, fmp);
|
||||
type_latch = 0;
|
||||
}
|
||||
}
|
||||
@ -400,18 +397,18 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
|
||||
float hy = symbol->vector->height - hex->y;
|
||||
if (previous_diameter != hex->diameter) {
|
||||
previous_diameter = hex->diameter;
|
||||
out_putsf("", 4, 0.5f * previous_diameter /*radius*/, feps);
|
||||
out_putsf(" ", 4, 0.43301270189221932338f * previous_diameter /*half_sqrt3_radius*/, feps);
|
||||
out_putsf(" ", 4, 0.25f * previous_diameter /*half_radius*/, feps);
|
||||
fputc('\n', feps);
|
||||
fm_putsf("", 4, 0.5f * previous_diameter /*radius*/, fmp);
|
||||
fm_putsf(" ", 4, 0.43301270189221932338f * previous_diameter /*half_sqrt3_radius*/, fmp);
|
||||
fm_putsf(" ", 4, 0.25f * previous_diameter /*half_radius*/, fmp);
|
||||
fm_putc('\n', fmp);
|
||||
}
|
||||
if (hex->next) {
|
||||
out_putsf("J ", 2, hex->x, feps);
|
||||
fm_putsf("J ", 2, hex->x, fmp);
|
||||
} else {
|
||||
out_putsf("", 2, hex->x, feps);
|
||||
fm_putsf("", 2, hex->x, fmp);
|
||||
}
|
||||
out_putsf(" ", 2, hy, feps);
|
||||
fputs(" H\n", feps);
|
||||
fm_putsf(" ", 2, hy, fmp);
|
||||
fm_puts(" H\n", fmp);
|
||||
}
|
||||
|
||||
/* Circles */
|
||||
@ -425,25 +422,25 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
|
||||
if (circle->colour) { /* Legacy - no longer used */
|
||||
/* A 'white' circle */
|
||||
if (is_rgb) {
|
||||
ps_put_rgbcolor(red_paper, green_paper, blue_paper, feps);
|
||||
ps_put_rgbcolor(red_paper, green_paper, blue_paper, fmp);
|
||||
} 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 (is_rgb) {
|
||||
ps_put_rgbcolor(red_ink, green_ink, blue_ink, feps);
|
||||
ps_put_rgbcolor(red_ink, green_ink, blue_ink, fmp);
|
||||
} 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 {
|
||||
/* A 'black' circle */
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -465,71 +462,62 @@ INTERNAL int ps_plot(struct zint_symbol *symbol) {
|
||||
}
|
||||
if (iso_latin1) {
|
||||
/* Change encoding to ISO 8859-1, see Postscript Language Reference Manual 2nd Edition Example 5.6 */
|
||||
fprintf(feps, "/%s findfont\n", font);
|
||||
fputs("dup length dict begin\n"
|
||||
fm_printf(fmp, "/%s findfont\n", font);
|
||||
fm_puts("dup length dict begin\n"
|
||||
"{1 index /FID ne {def} {pop pop} ifelse} forall\n"
|
||||
"/Encoding ISOLatin1Encoding def\n"
|
||||
"currentdict\n"
|
||||
"end\n"
|
||||
"/Helvetica-ISOLatin1 exch definefont pop\n", feps);
|
||||
"/Helvetica-ISOLatin1 exch definefont pop\n", fmp);
|
||||
font = "Helvetica-ISOLatin1";
|
||||
}
|
||||
do {
|
||||
ps_convert(string->text, ps_string);
|
||||
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 */
|
||||
out_putsf( " ", 2, upcean ? string->fsize * 1.07f : string->fsize, feps);
|
||||
fputs(" scalefont setfont\n", feps);
|
||||
fm_putsf( " ", 2, upcean ? string->fsize * 1.07f : string->fsize, fmp);
|
||||
fm_puts(" scalefont setfont\n", fmp);
|
||||
previous_fsize = string->fsize;
|
||||
}
|
||||
/* Unhack the guard whitespace `gws_left_fudge`/`gws_right_fudge` hack */
|
||||
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 */
|
||||
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] == '>') {
|
||||
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 {
|
||||
out_putsf(" ", 2, string->x, feps);
|
||||
fm_putsf(" ", 2, string->x, fmp);
|
||||
}
|
||||
out_putsf(" ", 2, symbol->vector->height - string->y, feps);
|
||||
fputs(" moveto\n", feps);
|
||||
fm_putsf(" ", 2, symbol->vector->height - string->y, fmp);
|
||||
fm_puts(" moveto\n", fmp);
|
||||
if (string->rotation != 0) {
|
||||
fputs(" gsave\n", feps);
|
||||
fprintf(feps, " %d rotate\n", 360 - string->rotation);
|
||||
fm_puts(" gsave\n", fmp);
|
||||
fm_printf(fmp, " %d rotate\n", 360 - string->rotation);
|
||||
}
|
||||
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");
|
||||
}
|
||||
fprintf(feps, " (%s) show\n", ps_string);
|
||||
fm_printf(fmp, " (%s) show\n", ps_string);
|
||||
if (string->rotation != 0) {
|
||||
fputs(" grestore\n", feps);
|
||||
fm_puts(" grestore\n", fmp);
|
||||
}
|
||||
string = string->next;
|
||||
} while (string);
|
||||
}
|
||||
|
||||
if (ferror(feps)) {
|
||||
sprintf(symbol->errtxt, "647: Incomplete write to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(feps);
|
||||
}
|
||||
if (fm_error(fmp)) {
|
||||
sprintf(symbol->errtxt, "647: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
if (fflush(feps) != 0) {
|
||||
sprintf(symbol->errtxt, "648: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_close(fmp, symbol)) {
|
||||
sprintf(symbol->errtxt, "649: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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;
|
||||
}
|
||||
|
@ -827,7 +827,8 @@ static void qr_add_ecc(unsigned char fullstream[], const unsigned char datastrea
|
||||
}
|
||||
|
||||
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);
|
||||
@ -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++) {
|
||||
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) {
|
||||
|
@ -244,12 +244,14 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, const int image
|
||||
#ifndef ZINT_NO_PNG
|
||||
error_number = png_pixel_plot(symbol, rotated_pixbuf);
|
||||
#else
|
||||
if (rotate_angle) {
|
||||
free(rotated_pixbuf);
|
||||
}
|
||||
return ZINT_ERROR_INVALID_OPTION;
|
||||
error_number = ZINT_ERROR_INVALID_OPTION;
|
||||
#endif
|
||||
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:
|
||||
error_number = pcx_pixel_plot(symbol, rotated_pixbuf);
|
||||
break;
|
||||
@ -262,6 +264,9 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, const int image
|
||||
default:
|
||||
error_number = bmp_pixel_plot(symbol, rotated_pixbuf);
|
||||
break;
|
||||
#if defined(__GNUC__) && !defined(__clang__) && defined(NDEBUG) && defined(ZINT_NO_PNG)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rotate_angle) {
|
||||
@ -1417,6 +1422,10 @@ INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_
|
||||
if (error != 0) {
|
||||
return error;
|
||||
}
|
||||
if (symbol->rows <= 0) {
|
||||
strcpy(symbol->errtxt, "664: No rows");
|
||||
return ZINT_ERROR_INVALID_OPTION;
|
||||
}
|
||||
|
||||
if (symbol->symbology == BARCODE_MAXICODE) {
|
||||
error = plot_raster_maxicode(symbol, rotate_angle, file_type);
|
||||
|
211
backend/svg.c
211
backend/svg.c
@ -35,6 +35,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "filemem.h"
|
||||
#include "output.h"
|
||||
#include "fonts/normal_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 */
|
||||
static void svg_put_fattrib(const char *prefix, const int dp, const float val, FILE *fsvg) {
|
||||
out_putsf(prefix, dp, val, fsvg);
|
||||
fputc('"', fsvg);
|
||||
static void svg_put_fattrib(const char *prefix, const int dp, const float val, struct filemem *fmp) {
|
||||
fm_putsf(prefix, dp, val, fmp);
|
||||
fm_putc('"', fmp);
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
svg_put_fattrib(" opacity=\"", 3, val, fsvg);
|
||||
svg_put_fattrib(" opacity=\"", 3, val, fmp);
|
||||
}
|
||||
if (close) {
|
||||
fputc('/', fsvg);
|
||||
fm_putc('/', fmp);
|
||||
}
|
||||
fputs(">\n", fsvg);
|
||||
fm_puts(">\n", fmp);
|
||||
}
|
||||
|
||||
INTERNAL int svg_plot(struct zint_symbol *symbol) {
|
||||
static const char normal_font_family[] = "Arimo";
|
||||
static const char upcean_font_family[] = "OCRB";
|
||||
FILE *fsvg;
|
||||
struct filemem fm;
|
||||
struct filemem *const fmp = &fm;
|
||||
int error_number = 0;
|
||||
float previous_diameter;
|
||||
float radius, half_radius, half_sqrt3_radius;
|
||||
@ -135,7 +137,6 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
|
||||
int len, html_len;
|
||||
|
||||
const int upcean = is_upcean(symbol->symbology);
|
||||
const int output_to_stdout = symbol->output_options & BARCODE_STDOUT;
|
||||
char *html_string;
|
||||
|
||||
(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");
|
||||
return ZINT_ERROR_INVALID_DATA;
|
||||
}
|
||||
if (output_to_stdout) {
|
||||
fsvg = stdout;
|
||||
} else {
|
||||
if (!(fsvg = out_fopen(symbol->outfile, "w"))) {
|
||||
sprintf(symbol->errtxt, "680: Could not open output file (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_open(fmp, symbol, "w")) {
|
||||
sprintf(symbol->errtxt, "680: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
return ZINT_ERROR_FILE_ACCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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",
|
||||
fsvg);
|
||||
fprintf(fsvg, "<svg width=\"%d\" height=\"%d\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n",
|
||||
fmp);
|
||||
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));
|
||||
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) {
|
||||
fprintf(fsvg, " <style>@font-face {font-family:\"%s\"; src:url(data:font/woff2;base64,%s);}</style>\n",
|
||||
upcean ? "OCRB" : "Arimo", upcean ? upcean_woff2 : normal_woff2);
|
||||
/* Split into `puts()` rather than one very large `printf()` */
|
||||
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) {
|
||||
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);
|
||||
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) {
|
||||
int current_colour = 0;
|
||||
rect = symbol->vector->rectangles;
|
||||
fputs(" <path d=\"", fsvg);
|
||||
fm_puts(" <path d=\"", fmp);
|
||||
while (rect) {
|
||||
if (current_colour && rect->colour != current_colour) {
|
||||
fputc('"', fsvg);
|
||||
fm_putc('"', fmp);
|
||||
if (current_colour != -1) {
|
||||
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);
|
||||
fputs(" <path d=\"", fsvg);
|
||||
svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fmp);
|
||||
fm_puts(" <path d=\"", fmp);
|
||||
}
|
||||
current_colour = rect->colour;
|
||||
out_putsf("M", 2, rect->x, fsvg);
|
||||
out_putsf(" ", 2, rect->y, fsvg);
|
||||
out_putsf("h", 2, rect->width, fsvg);
|
||||
out_putsf("v", 2, rect->height, fsvg);
|
||||
out_putsf("h-", 2, rect->width, fsvg);
|
||||
fputs("Z", fsvg);
|
||||
fm_putsf("M", 2, rect->x, fmp);
|
||||
fm_putsf(" ", 2, rect->y, fmp);
|
||||
fm_putsf("h", 2, rect->width, fmp);
|
||||
fm_putsf("v", 2, rect->height, fmp);
|
||||
fm_putsf("h-", 2, rect->width, fmp);
|
||||
fm_puts("Z", fmp);
|
||||
rect = rect->next;
|
||||
}
|
||||
fputc('"', fsvg);
|
||||
fm_putc('"', fmp);
|
||||
if (current_colour != -1) {
|
||||
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) {
|
||||
previous_diameter = radius = half_radius = half_sqrt3_radius = 0.0f;
|
||||
hex = symbol->vector->hexagons;
|
||||
fputs(" <path d=\"", fsvg);
|
||||
fm_puts(" <path d=\"", fmp);
|
||||
while (hex) {
|
||||
if (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;
|
||||
}
|
||||
if ((hex->rotation == 0) || (hex->rotation == 180)) {
|
||||
out_putsf("M", 2, hex->x, fsvg);
|
||||
out_putsf(" ", 2, hex->y + radius, fsvg);
|
||||
out_putsf("L", 2, hex->x + half_sqrt3_radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y + half_radius, fsvg);
|
||||
out_putsf("L", 2, hex->x + half_sqrt3_radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y - half_radius, fsvg);
|
||||
out_putsf("L", 2, hex->x, fsvg);
|
||||
out_putsf(" ", 2, hex->y - radius, fsvg);
|
||||
out_putsf("L", 2, hex->x - half_sqrt3_radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y - half_radius, fsvg);
|
||||
out_putsf("L", 2, hex->x - half_sqrt3_radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y + half_radius, fsvg);
|
||||
fm_putsf("M", 2, hex->x, fmp);
|
||||
fm_putsf(" ", 2, hex->y + radius, fmp);
|
||||
fm_putsf("L", 2, hex->x + half_sqrt3_radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y + half_radius, fmp);
|
||||
fm_putsf("L", 2, hex->x + half_sqrt3_radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y - half_radius, fmp);
|
||||
fm_putsf("L", 2, hex->x, fmp);
|
||||
fm_putsf(" ", 2, hex->y - radius, fmp);
|
||||
fm_putsf("L", 2, hex->x - half_sqrt3_radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y - half_radius, fmp);
|
||||
fm_putsf("L", 2, hex->x - half_sqrt3_radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y + half_radius, fmp);
|
||||
} else {
|
||||
out_putsf("M", 2, hex->x - radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y, fsvg);
|
||||
out_putsf("L", 2, hex->x - half_radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y + half_sqrt3_radius, fsvg);
|
||||
out_putsf("L", 2, hex->x + half_radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y + half_sqrt3_radius, fsvg);
|
||||
out_putsf("L", 2, hex->x + radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y, fsvg);
|
||||
out_putsf("L", 2, hex->x + half_radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y - half_sqrt3_radius, fsvg);
|
||||
out_putsf("L", 2, hex->x - half_radius, fsvg);
|
||||
out_putsf(" ", 2, hex->y - half_sqrt3_radius, fsvg);
|
||||
fm_putsf("M", 2, hex->x - radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y, fmp);
|
||||
fm_putsf("L", 2, hex->x - half_radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y + half_sqrt3_radius, fmp);
|
||||
fm_putsf("L", 2, hex->x + half_radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y + half_sqrt3_radius, fmp);
|
||||
fm_putsf("L", 2, hex->x + radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y, fmp);
|
||||
fm_putsf("L", 2, hex->x + half_radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y - half_sqrt3_radius, fmp);
|
||||
fm_putsf("L", 2, hex->x - half_radius, fmp);
|
||||
fm_putsf(" ", 2, hex->y - half_sqrt3_radius, fmp);
|
||||
}
|
||||
fputc('Z', fsvg);
|
||||
fm_putc('Z', fmp);
|
||||
hex = hex->next;
|
||||
}
|
||||
fputc('"', fsvg);
|
||||
svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fsvg);
|
||||
fm_putc('"', fmp);
|
||||
svg_put_opacity_close(fg_alpha, fg_alpha_opacity, 1 /*close*/, fmp);
|
||||
}
|
||||
|
||||
previous_diameter = radius = 0.0f;
|
||||
@ -286,28 +286,28 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
|
||||
previous_diameter = circle->diameter;
|
||||
radius = 0.5f * previous_diameter;
|
||||
}
|
||||
fputs(" <circle", fsvg);
|
||||
svg_put_fattrib(" cx=\"", 2, circle->x, fsvg);
|
||||
svg_put_fattrib(" cy=\"", 2, circle->y, fsvg);
|
||||
svg_put_fattrib(" r=\"", circle->width ? 3 : 2, radius, fsvg);
|
||||
fm_puts(" <circle", fmp);
|
||||
svg_put_fattrib(" cx=\"", 2, circle->x, fmp);
|
||||
svg_put_fattrib(" cy=\"", 2, circle->y, fmp);
|
||||
svg_put_fattrib(" r=\"", circle->width ? 3 : 2, radius, fmp);
|
||||
|
||||
if (circle->colour) { /* Legacy - no longer used */
|
||||
if (circle->width) {
|
||||
fprintf(fsvg, " stroke=\"#%s\"", bgcolour_string);
|
||||
svg_put_fattrib(" stroke-width=\"", 3, circle->width, fsvg);
|
||||
fputs(" fill=\"none\"", fsvg);
|
||||
fm_printf(fmp, " stroke=\"#%s\"", bgcolour_string);
|
||||
svg_put_fattrib(" stroke-width=\"", 3, circle->width, fmp);
|
||||
fm_puts(" fill=\"none\"", fmp);
|
||||
} 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! */
|
||||
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 {
|
||||
if (circle->width) {
|
||||
fprintf(fsvg, " stroke=\"#%s\"", fgcolour_string);
|
||||
svg_put_fattrib(" stroke-width=\"", 3, circle->width, fsvg);
|
||||
fputs(" fill=\"none\"", fsvg);
|
||||
fm_printf(fmp, " stroke=\"#%s\"", fgcolour_string);
|
||||
svg_put_fattrib(" stroke-width=\"", 3, circle->width, fmp);
|
||||
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;
|
||||
}
|
||||
@ -316,54 +316,45 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
|
||||
string = symbol->vector->strings;
|
||||
while (string) {
|
||||
const char *const halign = string->halign == 2 ? "end" : string->halign == 1 ? "start" : "middle";
|
||||
fputs(" <text", fsvg);
|
||||
svg_put_fattrib(" x=\"", 2, string->x, fsvg);
|
||||
svg_put_fattrib(" y=\"", 2, string->y, fsvg);
|
||||
fprintf(fsvg, " text-anchor=\"%s\"", halign);
|
||||
fm_puts(" <text", fmp);
|
||||
svg_put_fattrib(" x=\"", 2, string->x, fmp);
|
||||
svg_put_fattrib(" y=\"", 2, string->y, fmp);
|
||||
fm_printf(fmp, " text-anchor=\"%s\"", halign);
|
||||
if (upcean) {
|
||||
fprintf(fsvg, " font-family=\"%s, monospace\"", upcean_font_family);
|
||||
fm_printf(fmp, " font-family=\"%s, monospace\"", upcean_font_family);
|
||||
} 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) {
|
||||
fputs(" font-weight=\"bold\"", fsvg);
|
||||
fm_puts(" font-weight=\"bold\"", fmp);
|
||||
}
|
||||
if (string->rotation != 0) {
|
||||
fprintf(fsvg, " transform=\"rotate(%d", string->rotation);
|
||||
out_putsf(",", 2, string->x, fsvg);
|
||||
out_putsf(",", 2, string->y, fsvg);
|
||||
fputs(")\"", fsvg);
|
||||
fm_printf(fmp, " transform=\"rotate(%d", string->rotation);
|
||||
fm_putsf(",", 2, string->x, fmp);
|
||||
fm_putsf(",", 2, string->y, fmp);
|
||||
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);
|
||||
fprintf(fsvg, " %s\n", html_string);
|
||||
fputs(" </text>\n", fsvg);
|
||||
fm_printf(fmp, " %s\n", html_string);
|
||||
fm_puts(" </text>\n", fmp);
|
||||
string = string->next;
|
||||
}
|
||||
|
||||
fputs(" </g>\n"
|
||||
"</svg>\n", fsvg);
|
||||
fm_puts(" </g>\n"
|
||||
"</svg>\n", fmp);
|
||||
|
||||
if (ferror(fsvg)) {
|
||||
sprintf(symbol->errtxt, "682: Incomplete write to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(fsvg);
|
||||
}
|
||||
if (fm_error(fmp)) {
|
||||
sprintf(symbol->errtxt, "682: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
if (fflush(fsvg) != 0) {
|
||||
sprintf(symbol->errtxt, "683: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!fm_close(fmp, symbol)) {
|
||||
sprintf(symbol->errtxt, "684: Failure on closing output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
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;
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ zint_add_test(dmatrix test_dmatrix)
|
||||
zint_add_test(dotcode test_dotcode)
|
||||
zint_add_test(eci test_eci)
|
||||
zint_add_test(emf test_emf)
|
||||
zint_add_test(filemem test_filemem)
|
||||
zint_add_test(gb18030 test_gb18030)
|
||||
zint_add_test(gb2312 test_gb2312)
|
||||
zint_add_test(gif test_gif)
|
||||
|
@ -155,6 +155,8 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
char expected_file[4096];
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
unsigned char filebuf[32768];
|
||||
int filebuf_size;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -590,7 +590,7 @@ static void test_fuzz(const testCtx *const p_ctx) {
|
||||
};
|
||||
struct item data[] = {
|
||||
/* 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"
|
||||
"\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"
|
||||
|
@ -104,6 +104,8 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
char expected_file[1024];
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
unsigned char filebuf[32768];
|
||||
int filebuf_size;
|
||||
|
||||
int have_libreoffice = 0;
|
||||
if (p_ctx->generate) {
|
||||
@ -182,7 +184,23 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
|
||||
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);
|
||||
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);
|
||||
|
477
backend/tests/test_filemem.c
Normal file
477
backend/tests/test_filemem.c
Normal 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 : */
|
||||
|
@ -191,6 +191,8 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
char expected_file[4096];
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
unsigned char filebuf[32768];
|
||||
int filebuf_size;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
|
||||
#include "testcommon.h"
|
||||
#include "../output.h"
|
||||
#include <locale.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
@ -411,82 +410,6 @@ static void test_fopen(const testCtx *const p_ctx) {
|
||||
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[]) {
|
||||
|
||||
testFunction funcs[] = { /* name, func */
|
||||
@ -496,7 +419,6 @@ int main(int argc, char *argv[]) {
|
||||
{ "test_quiet_zones", test_quiet_zones },
|
||||
{ "test_set_whitespace_offsets", test_set_whitespace_offsets },
|
||||
{ "test_fopen", test_fopen },
|
||||
{ "test_out_putsf", test_out_putsf },
|
||||
};
|
||||
|
||||
testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
|
||||
|
@ -65,6 +65,8 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
char expected_file[4096];
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
unsigned char filebuf[36864];
|
||||
int filebuf_size;
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
/* 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, 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 */
|
||||
/* 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 */
|
||||
@ -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 */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
/* 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 */
|
||||
|
@ -239,6 +239,8 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
char expected_file[1024];
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
unsigned char filebuf[32768];
|
||||
int filebuf_size;
|
||||
char *text;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
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, 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);
|
||||
}
|
||||
|
||||
|
@ -117,8 +117,9 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
int i, length, ret;
|
||||
struct zint_symbol *symbol = NULL;
|
||||
|
||||
const char *data_dir = "/backend/tests/data/eps";
|
||||
const char *eps = "out.eps";
|
||||
const char data_dir[] = "/backend/tests/data/eps";
|
||||
const char eps[] = "out.eps";
|
||||
const char memfile[] = "mem.eps";
|
||||
char expected_file[1024];
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
@ -193,7 +194,25 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
|
||||
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);
|
||||
|
||||
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(memfile), "i:%d testUtilRemove(%s) != 0\n", i, memfile);
|
||||
}
|
||||
}
|
||||
|
||||
ZBarcode_Delete(symbol);
|
||||
|
@ -144,8 +144,9 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
int i, length, ret;
|
||||
struct zint_symbol *symbol = NULL;
|
||||
|
||||
const char *data_dir = "/backend/tests/data/svg";
|
||||
const char *svg = "out.svg";
|
||||
const char data_dir[] = "/backend/tests/data/svg";
|
||||
const char svg[] = "out.svg";
|
||||
const char memfile[] = "mem.eps";
|
||||
char expected_file[1024];
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
@ -240,7 +241,25 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
|
||||
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);
|
||||
|
||||
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(memfile), "i:%d testUtilRemove(%s) != 0\n", i, memfile);
|
||||
}
|
||||
}
|
||||
|
||||
ZBarcode_Delete(symbol);
|
||||
|
@ -214,6 +214,8 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
char expected_file[1024];
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
unsigned char filebuf[32768];
|
||||
int filebuf_size;
|
||||
char *text;
|
||||
|
||||
int have_tiffinfo = testUtilHaveTiffInfo();
|
||||
@ -301,9 +303,25 @@ static void test_print(const testCtx *const p_ctx) {
|
||||
|
||||
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);
|
||||
|
||||
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, 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);
|
||||
}
|
||||
|
||||
|
@ -1516,6 +1516,67 @@ int testUtilRmROFile(const char *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 */
|
||||
int testUtilCmpPngs(const char *png1, const char *png2) {
|
||||
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 maxi_len = 0;
|
||||
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);
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
maxi_len = (int) strlen(maxi);
|
||||
}
|
||||
#if 1
|
||||
|
@ -57,7 +57,7 @@ extern "C" {
|
||||
#define testutil_pclose(stream) _pclose(stream)
|
||||
#else
|
||||
#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 int pclose(FILE *stream);
|
||||
# endif
|
||||
@ -174,6 +174,8 @@ int testUtilRmDir(const char *dirname);
|
||||
int testUtilRename(const char *oldpath, const char *newpath);
|
||||
int testUtilCreateROFile(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 testUtilCmpTxts(const char *txt1, const char *txt2);
|
||||
|
Binary file not shown.
105
backend/tif.c
105
backend/tif.c
@ -34,11 +34,8 @@
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include "common.h"
|
||||
#include "filemem.h"
|
||||
#include "output.h"
|
||||
#include "tif.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;
|
||||
unsigned int bytes_put;
|
||||
long total_bytes_put;
|
||||
FILE *tif_file;
|
||||
struct filemem fm;
|
||||
struct filemem *const fmp = &fm;
|
||||
const unsigned char *pb;
|
||||
int compression = TIF_NO_COMPRESSION;
|
||||
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 */
|
||||
if (output_to_stdout) {
|
||||
#ifdef _MSC_VER
|
||||
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));
|
||||
if (!fm_open(fmp, symbol, "wb")) {
|
||||
sprintf(symbol->errtxt, "672: Could not open output file (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
return ZINT_ERROR_FILE_ACCESS;
|
||||
}
|
||||
if (!output_to_stdout) {
|
||||
compression = TIF_LZW;
|
||||
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.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);
|
||||
|
||||
/* 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)) {
|
||||
/* End of strip */
|
||||
if (compression == TIF_LZW) {
|
||||
file_pos = ftell(tif_file);
|
||||
if (!tif_lzw_encode(&lzw_state, tif_file, strip_buf, bytes_put)) { /* Only fails if can't malloc */
|
||||
file_pos = fm_tell(fmp);
|
||||
if (!tif_lzw_encode(&lzw_state, fmp, strip_buf, bytes_put)) { /* Only fails if can't malloc */
|
||||
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");
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
bytes_put = ftell(tif_file) - file_pos;
|
||||
bytes_put = fm_tell(fmp) - file_pos;
|
||||
if (bytes_put != strip_bytes[strip]) {
|
||||
const int diff = bytes_put - strip_bytes[strip];
|
||||
strip_bytes[strip] = bytes_put;
|
||||
@ -403,7 +393,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fwrite(strip_buf, 1, bytes_put, tif_file);
|
||||
fm_write(strip_buf, 1, bytes_put, fmp);
|
||||
}
|
||||
strip++;
|
||||
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) {
|
||||
putc(0, tif_file); /* IFD must be on word boundary */
|
||||
fm_putc(0, fmp); /* IFD must be on word boundary */
|
||||
total_bytes_put++;
|
||||
}
|
||||
|
||||
if (compression == TIF_LZW) {
|
||||
tif_lzw_cleanup(&lzw_state);
|
||||
|
||||
file_pos = ftell(tif_file);
|
||||
fseek(tif_file, 4, SEEK_SET);
|
||||
file_pos = fm_tell(fmp);
|
||||
fm_seek(fmp, 4, SEEK_SET);
|
||||
free_memory = file_pos;
|
||||
temp32 = (uint32_t) free_memory;
|
||||
/* Shouldn't happen as `free_memory` checked above to be <= 0xffff0000 & should only decrease */
|
||||
if (free_memory != temp32 || (long) free_memory != file_pos) {
|
||||
strcpy(symbol->errtxt, "982: Output file size too big");
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(tif_file);
|
||||
}
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
fseek(tif_file, file_pos, SEEK_SET);
|
||||
fm_write(&temp32, 4, 1, fmp);
|
||||
fm_seek(fmp, file_pos, SEEK_SET);
|
||||
}
|
||||
|
||||
/* 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];
|
||||
} else {
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
tags[entries++].offset = (uint32_t) free_memory;
|
||||
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].count = 1;
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
tags[entries++].offset = (uint32_t) free_memory;
|
||||
free_memory += 8;
|
||||
|
||||
tags[entries].tag = 0x011b; /* YResolution */
|
||||
tags[entries].type = 5; /* RATIONAL */
|
||||
tags[entries].count = 1;
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
tags[entries++].offset = (uint32_t) free_memory;
|
||||
free_memory += 8;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
fwrite(&entries, sizeof(entries), 1, tif_file);
|
||||
fwrite(&tags, sizeof(tiff_tag_t), entries, tif_file);
|
||||
fwrite(&offset, sizeof(offset), 1, tif_file);
|
||||
fm_write(&entries, sizeof(entries), 1, fmp);
|
||||
fm_write(&tags, sizeof(tiff_tag_t), entries, fmp);
|
||||
fm_write(&offset, sizeof(offset), 1, fmp);
|
||||
total_bytes_put += ifd_size;
|
||||
|
||||
if (samples_per_pixel > 2) {
|
||||
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;
|
||||
}
|
||||
@ -567,66 +555,59 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
|
||||
if (strip_count != 1) {
|
||||
/* Strip offsets */
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
/* XResolution */
|
||||
temp32 = symbol->dpmm ? symbol->dpmm : 72;
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
fm_write(&temp32, 4, 1, fmp);
|
||||
temp32 = symbol->dpmm ? 10 /*cm*/ : 1;
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
fm_write(&temp32, 4, 1, fmp);
|
||||
total_bytes_put += 8;
|
||||
|
||||
/* YResolution */
|
||||
temp32 = symbol->dpmm ? symbol->dpmm : 72;
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
fm_write(&temp32, 4, 1, fmp);
|
||||
temp32 = symbol->dpmm ? 10 /*cm*/ : 1;
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
fm_write(&temp32, 4, 1, fmp);
|
||||
total_bytes_put += 8;
|
||||
|
||||
if (color_map_size) {
|
||||
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++) {
|
||||
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++) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (ferror(tif_file)) {
|
||||
sprintf(symbol->errtxt, "679: Incomplete write to output (%d: %.30s)", errno, strerror(errno));
|
||||
if (!output_to_stdout) {
|
||||
(void) fclose(tif_file);
|
||||
}
|
||||
if (fm_error(fmp)) {
|
||||
sprintf(symbol->errtxt, "679: Incomplete write to output (%d: %.30s)", fmp->err, strerror(fmp->err));
|
||||
(void) fm_close(fmp, symbol);
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
|
||||
if (output_to_stdout) {
|
||||
if (fflush(tif_file) != 0) {
|
||||
sprintf(symbol->errtxt, "980: Incomplete flush to output (%d: %.30s)", errno, strerror(errno));
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
} else {
|
||||
if (ftell(tif_file) != total_bytes_put) {
|
||||
(void) fclose(tif_file);
|
||||
if (!output_to_stdout) {
|
||||
if (fm_tell(fmp) != total_bytes_put) {
|
||||
(void) fm_close(fmp, symbol);
|
||||
strcpy(symbol->errtxt, "674: Failed to write all output");
|
||||
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;
|
||||
|
@ -161,13 +161,13 @@ static void tif_lzw_cl_hash(tif_lzw_state *sp) {
|
||||
}
|
||||
|
||||
/* Explicit 0xff masking to make icc -check=conversions happy */
|
||||
#define PutNextCode(op_file, c) { \
|
||||
#define PutNextCode(op_fmp, c) { \
|
||||
nextdata = (nextdata << nbits) | c; \
|
||||
nextbits += nbits; \
|
||||
putc((nextdata >> (nextbits - 8)) & 0xff, op_file); \
|
||||
fm_putc((nextdata >> (nextbits - 8)) & 0xff, op_fmp); \
|
||||
nextbits -= 8; \
|
||||
if (nextbits >= 8) { \
|
||||
putc((nextdata >> (nextbits - 8)) & 0xff, op_file); \
|
||||
fm_putc((nextdata >> (nextbits - 8)) & 0xff, op_fmp); \
|
||||
nextbits -= 8; \
|
||||
} \
|
||||
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
|
||||
* 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 tif_lzw_hash *hp;
|
||||
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;
|
||||
|
||||
if (cc > 0) {
|
||||
PutNextCode(op_file, CODE_CLEAR);
|
||||
PutNextCode(op_fmp, CODE_CLEAR);
|
||||
ent = *bp++; cc--; incount++;
|
||||
}
|
||||
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.
|
||||
*/
|
||||
PutNextCode(op_file, ent);
|
||||
PutNextCode(op_fmp, ent);
|
||||
ent = (tif_lzw_hcode) c;
|
||||
hp->code = (tif_lzw_hcode) (free_ent++);
|
||||
hp->hash = fcode;
|
||||
@ -286,7 +286,7 @@ static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char
|
||||
incount = 0;
|
||||
outcount = 0;
|
||||
free_ent = CODE_FIRST;
|
||||
PutNextCode(op_file, CODE_CLEAR);
|
||||
PutNextCode(op_fmp, CODE_CLEAR);
|
||||
nbits = BITS_MIN;
|
||||
maxcode = MAXCODE(BITS_MIN);
|
||||
} else {
|
||||
@ -314,7 +314,7 @@ static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char
|
||||
incount = 0;
|
||||
outcount = 0;
|
||||
free_ent = CODE_FIRST;
|
||||
PutNextCode(op_file, CODE_CLEAR);
|
||||
PutNextCode(op_fmp, CODE_CLEAR);
|
||||
nbits = BITS_MIN;
|
||||
maxcode = MAXCODE(BITS_MIN);
|
||||
} 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) {
|
||||
|
||||
PutNextCode(op_file, ent);
|
||||
PutNextCode(op_fmp, ent);
|
||||
free_ent++;
|
||||
|
||||
if (free_ent == CODE_MAX - 1) {
|
||||
/* table is full, emit clear code and reset */
|
||||
outcount = 0;
|
||||
PutNextCode(op_file, CODE_CLEAR);
|
||||
PutNextCode(op_fmp, CODE_CLEAR);
|
||||
nbits = BITS_MIN;
|
||||
} 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 */
|
||||
if (nextbits > 0) {
|
||||
putc((nextdata << (8 - nextbits)) & 0xff, op_file);
|
||||
fm_putc((nextdata << (8 - nextbits)) & 0xff, op_fmp);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -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) */
|
||||
|
||||
/* For UPC/EAN only */
|
||||
float addon_row_yposn;
|
||||
float addon_row_height;
|
||||
float addon_row_yposn = 0.0f; /* Suppress gcc -Wmaybe-uninitialized false positive */
|
||||
float addon_row_height = 0.0f; /* Ditto */
|
||||
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_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) {
|
||||
return error_number;
|
||||
}
|
||||
if (symbol->rows <= 0) {
|
||||
strcpy(symbol->errtxt, "697: No rows");
|
||||
return ZINT_ERROR_INVALID_OPTION;
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
vector = symbol->vector = (struct zint_vector *) malloc(sizeof(struct zint_vector));
|
||||
|
@ -131,6 +131,8 @@ extern "C" {
|
||||
int bitmap_height; /* Height of bitmap image (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) */
|
||||
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 */
|
||||
@ -273,25 +275,26 @@ extern "C" {
|
||||
#define BARCODE_LAST 146 /* Max barcode number marker, not barcode */
|
||||
|
||||
/* 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 */
|
||||
#define BARCODE_BIND 0x0002 /* Boundary bars above & below the symbol and between stacked symbols */
|
||||
#define BARCODE_BOX 0x0004 /* Box around symbol */
|
||||
#define BARCODE_STDOUT 0x0008 /* Output to stdout */
|
||||
#define READER_INIT 0x0010 /* Reader Initialisation (Programming) */
|
||||
#define SMALL_TEXT 0x0020 /* Use smaller font */
|
||||
#define BOLD_TEXT 0x0040 /* Use bold font */
|
||||
#define CMYK_COLOUR 0x0080 /* CMYK colour space (Encapsulated PostScript and TIF) */
|
||||
#define BARCODE_DOTTY_MODE 0x0100 /* 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 OUT_BUFFER_INTERMEDIATE 0x0400 /* 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_BIND 0x00002 /* Boundary bars above & below the symbol and between stacked symbols */
|
||||
#define BARCODE_BOX 0x00004 /* Box around symbol */
|
||||
#define BARCODE_STDOUT 0x00008 /* Output to stdout */
|
||||
#define READER_INIT 0x00010 /* Reader Initialisation (Programming) */
|
||||
#define SMALL_TEXT 0x00020 /* Use smaller font */
|
||||
#define BOLD_TEXT 0x00040 /* Use bold font */
|
||||
#define CMYK_COLOUR 0x00080 /* CMYK colour space (Encapsulated PostScript and TIF) */
|
||||
#define BARCODE_DOTTY_MODE 0x00100 /* Plot a matrix symbol using dots rather than squares */
|
||||
#define GS1_GS_SEPARATOR 0x00200 /* Use GS instead of FNC1 as GS1 separator (Data Matrix) */
|
||||
#define OUT_BUFFER_INTERMEDIATE 0x00400 /* Return ASCII values in bitmap buffer (OUT_BUFFER only) */
|
||||
#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
|
||||
*/
|
||||
#define BARCODE_NO_QUIET_ZONES 0x1000 /* 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 EANUPC_GUARD_WHITESPACE 0x4000 /* 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 BARCODE_NO_QUIET_ZONES 0x01000 /* Disable quiet zones, notably those with defaults as listed above */
|
||||
#define COMPLIANT_HEIGHT 0x02000 /* Warn if height not compliant, or use standard height (if any) as default */
|
||||
#define EANUPC_GUARD_WHITESPACE 0x04000 /* Add quiet zone indicators ("<"/">") to HRT whitespace (EAN/UPC) */
|
||||
#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`) */
|
||||
#define DATA_MODE 0 /* Binary */
|
||||
|
@ -42,6 +42,7 @@ HEADERS += ../backend/aztec.h \
|
||||
../backend/gb18030.h \
|
||||
../backend/gb2312.h \
|
||||
../backend/gbk.h \
|
||||
../backend/filemem.h \
|
||||
../backend/general_field.h \
|
||||
../backend/gridmtx.h \
|
||||
../backend/gs1.h \
|
||||
@ -86,6 +87,7 @@ SOURCES += ../backend/2of5.c \
|
||||
../backend/dotcode.c \
|
||||
../backend/eci.c \
|
||||
../backend/emf.c \
|
||||
../backend/filemem.c \
|
||||
../backend/general_field.c \
|
||||
../backend/gif.c \
|
||||
../backend/gridmtx.c \
|
||||
|
@ -33,6 +33,7 @@ HEADERS += ../backend/aztec.h \
|
||||
../backend/gb18030.h \
|
||||
../backend/gb2312.h \
|
||||
../backend/gbk.h \
|
||||
../backend/filemem.h \
|
||||
../backend/general_field.h \
|
||||
../backend/gridmtx.h \
|
||||
../backend/gs1.h \
|
||||
@ -70,6 +71,7 @@ SOURCES += ../backend/2of5.c \
|
||||
../backend/eci.c \
|
||||
../backend/emf.c \
|
||||
../backend/gridmtx.c \
|
||||
../backend/filemem.c \
|
||||
../backend/general_field.c \
|
||||
../backend/gif.c \
|
||||
../backend/gs1.c \
|
||||
|
1
backend_tcl/configure
vendored
1
backend_tcl/configure
vendored
@ -5361,6 +5361,7 @@ printf "%s\n" "$ac_cv_c_bigendian" >&6; }
|
||||
../backend/dotcode.c
|
||||
../backend/eci.c
|
||||
../backend/emf.c
|
||||
../backend/filemem.c
|
||||
../backend/general_field.c
|
||||
../backend/gif.c
|
||||
../backend/gridmtx.c
|
||||
|
@ -90,6 +90,7 @@ TEA_ADD_SOURCES([
|
||||
../backend/dotcode.c
|
||||
../backend/eci.c
|
||||
../backend/emf.c
|
||||
../backend/filemem.c
|
||||
../backend/general_field.c
|
||||
../backend/gif.c
|
||||
../backend/gridmtx.c
|
||||
|
@ -161,6 +161,10 @@ SOURCE=..\backend\emf.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\backend\filemem.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\backend\general_field.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
639
docs/manual.html
639
docs/manual.html
File diff suppressed because it is too large
Load Diff
121
docs/manual.pmd
121
docs/manual.pmd
@ -1028,7 +1028,7 @@ zint --fg=00ff0055 -d "This Text"
|
||||
|
||||
![`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
|
||||
(SVG) output formats, as for vector output the background will "shine through" a
|
||||
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
|
||||
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.
|
||||
|
||||
## 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
|
||||
symbols and we don't mind that they only save to `"out.png"`. As with the CLI
|
||||
program, of course, these options can be altered. The way this is done is by
|
||||
altering the contents of the `zint_symbol` structure between the creation and
|
||||
encoding stages. The `zint_symbol` structure consists of the following members:
|
||||
symbols and we don't mind that they only save to `"out.png"` (or to memory, as
|
||||
above). As with the CLI program, of course, these options can be altered. The
|
||||
way this is done is by altering the contents of the `zint_symbol` structure
|
||||
between the creation and encoding stages. The `zint_symbol` structure consists
|
||||
of the following members:
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
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].
|
||||
|
||||
`height` float Symbol height in Symbol dependent
|
||||
X-dimensions, excluding
|
||||
fixed width-to-height
|
||||
symbols.[^7]
|
||||
symbols.[^8]
|
||||
|
||||
`scale` float Scale factor for 1.0
|
||||
adjusting size of image
|
||||
@ -1909,7 +1944,7 @@ Member Name Type Meaning Default Value
|
||||
X-dimensions.
|
||||
|
||||
`output_options` integer Set various output 0 (none)
|
||||
parameters - see [5.9
|
||||
parameters - see [5.10
|
||||
Adjusting Output
|
||||
Options].
|
||||
|
||||
@ -1943,7 +1978,7 @@ Member Name Type Meaning Default Value
|
||||
`.eps`, `.pcx`, `.svg`,
|
||||
`.tif` or `.txt` followed
|
||||
by a terminating
|
||||
`NUL`.[^8]
|
||||
`NUL`.[^9]
|
||||
|
||||
`primary` character Primary message data for `""` (empty)
|
||||
string more complex symbols,
|
||||
@ -1959,7 +1994,7 @@ Member Name Type Meaning Default Value
|
||||
Readable Text (HRT).
|
||||
|
||||
`input_mode` integer Set encoding of input `DATA_MODE`
|
||||
data - see [5.10 Setting
|
||||
data - see [5.11 Setting
|
||||
the Input Mode].
|
||||
|
||||
`eci` integer Extended Channel 0 (none)
|
||||
@ -1989,7 +2024,7 @@ Member Name Type Meaning Default Value
|
||||
|
||||
`warn_level` integer Affects error/warning `WARN_DEFAULT`
|
||||
value returned by Zint
|
||||
API - see [5.7 Handling
|
||||
API - see [5.8 Handling
|
||||
Errors].
|
||||
|
||||
`text` unsigned Human Readable Text, `""` (empty)
|
||||
@ -2017,7 +2052,7 @@ Member Name Type Meaning Default Value
|
||||
string event that an error
|
||||
occurred, with a
|
||||
terminating `NUL` - see
|
||||
[5.7 Handling Errors].
|
||||
[5.8 Handling Errors].
|
||||
|
||||
`bitmap` pointer to Pointer to stored bitmap (output only)
|
||||
unsigned image - see [5.4
|
||||
@ -2044,17 +2079,28 @@ Member Name Type Meaning Default Value
|
||||
structure vector elements - see
|
||||
[5.5 Buffering Symbols
|
||||
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="$ $"}
|
||||
|
||||
[^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,
|
||||
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
|
||||
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
|
||||
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].
|
||||
|
||||
## 5.7 Handling Errors
|
||||
## 5.8 Handling Errors
|
||||
|
||||
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
|
||||
@ -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`.
|
||||
|
||||
## 5.8 Specifying a Symbology
|
||||
## 5.9 Specifying a Symbology
|
||||
|
||||
Symbologies can be specified by number or by name as shown in the Table
|
||||
{@tbl:barcode_types}. For example
|
||||
@ -2211,7 +2257,7 @@ means the same as
|
||||
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
|
||||
file. To select more than one option from the table below simply `OR` them
|
||||
@ -2226,10 +2272,10 @@ Value Effect
|
||||
------------------------- ---------------------------------------------------
|
||||
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
|
||||
between rows if stacking multiple symbols.[^10]
|
||||
between rows if stacking multiple symbols.[^11]
|
||||
|
||||
`BARCODE_BOX` Add a box surrounding the symbol and whitespace.
|
||||
|
||||
@ -2256,7 +2302,7 @@ Value Effect
|
||||
Symbols in Memory (raster)].
|
||||
|
||||
`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.
|
||||
|
||||
@ -2268,20 +2314,23 @@ Value Effect
|
||||
|
||||
`EMBED_VECTOR_FONT` Embed font in vector output - currently available
|
||||
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="$ $"}
|
||||
|
||||
[^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].
|
||||
|
||||
[^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].
|
||||
|
||||
[^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.
|
||||
|
||||
## 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`
|
||||
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
|
||||
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:
|
||||
|
||||
@ -2426,7 +2475,7 @@ int main(int argc, char **argv)
|
||||
A maximum of 256 segments may be specified. Use of multiple segments with GS1
|
||||
data is not currently supported.
|
||||
|
||||
## 5.12 Scaling Helpers
|
||||
## 5.13 Scaling Helpers
|
||||
|
||||
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
|
||||
barcode appears on.
|
||||
|
||||
## 5.13 Verifying Symbology Availability
|
||||
## 5.14 Verifying Symbology Availability
|
||||
|
||||
An additional function available in the API is:
|
||||
|
||||
@ -2511,7 +2560,7 @@ if (ZBarcode_BarcodeName(BARCODE_PDF417, name) == 0) {
|
||||
|
||||
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.
|
||||
This can be determined using another additional function:
|
||||
@ -2530,7 +2579,7 @@ Value Meaning
|
||||
|
||||
`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
|
||||
[6.3 GS1 Composite Symbols (ISO 24723)] below)
|
||||
@ -2561,7 +2610,7 @@ Value Meaning
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
with:
|
||||
@ -3091,13 +3140,13 @@ all-numeric characters.
|
||||
![`zint -b CODE128AB -d "130170X178"`](images/code128ab.svg){.lin}
|
||||
|
||||
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.
|
||||
|
||||
Note that the special escapes to manually switch Code Sets mentioned above are
|
||||
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.
|
||||
|
||||
#### 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`.
|
||||
|
||||
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`
|
||||
rectangular area specifying where to paint into:
|
||||
|
||||
|
139
docs/manual.txt
139
docs/manual.txt
@ -62,16 +62,17 @@ December 2023
|
||||
- 5.3 Encoding and Printing Functions in Depth
|
||||
- 5.4 Buffering Symbols in Memory (raster)
|
||||
- 5.5 Buffering Symbols in Memory (vector)
|
||||
- 5.6 Setting Options
|
||||
- 5.7 Handling Errors
|
||||
- 5.8 Specifying a Symbology
|
||||
- 5.9 Adjusting Output Options
|
||||
- 5.10 Setting the Input Mode
|
||||
- 5.11 Multiple Segments
|
||||
- 5.12 Scaling Helpers
|
||||
- 5.13 Verifying Symbology Availability
|
||||
- 5.14 Checking Symbology Capabilities
|
||||
- 5.15 Zint Version
|
||||
- 5.6 Buffering Symbols in Memory (memfile)
|
||||
- 5.7 Setting Options
|
||||
- 5.8 Handling Errors
|
||||
- 5.9 Specifying a Symbology
|
||||
- 5.10 Adjusting Output Options
|
||||
- 5.11 Setting the Input Mode
|
||||
- 5.12 Multiple Segments
|
||||
- 5.13 Scaling Helpers
|
||||
- 5.14 Verifying Symbology Availability
|
||||
- 5.15 Checking Symbology Capabilities
|
||||
- 5.16 Zint Version
|
||||
- 6. Types of Symbology
|
||||
- 6.1 One-Dimensional Symbols
|
||||
- 6.1.1 Code 11
|
||||
@ -1130,7 +1131,7 @@ format. For example:
|
||||
|
||||
[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
|
||||
(SVG) output formats, as for vector output the background will “shine through” a
|
||||
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
|
||||
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.
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
symbols and we don’t mind that they only save to "out.png". As with the CLI
|
||||
program, of course, these options can be altered. The way this is done is by
|
||||
altering the contents of the zint_symbol structure between the creation and
|
||||
encoding stages. The zint_symbol structure consists of the following members:
|
||||
symbols and we don’t mind that they only save to "out.png" (or to memory, as
|
||||
above). As with the CLI program, of course, these options can be altered. The
|
||||
way this is done is by altering the contents of the zint_symbol structure
|
||||
between the creation and encoding stages. The zint_symbol structure consists of
|
||||
the following members:
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
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.
|
||||
|
||||
height float Symbol height in Symbol dependent
|
||||
X-dimensions, excluding
|
||||
fixed width-to-height
|
||||
symbols.[7]
|
||||
symbols.[8]
|
||||
|
||||
scale float Scale factor for adjusting 1.0
|
||||
size of image (sets
|
||||
@ -1932,7 +1962,7 @@ encoding stages. The zint_symbol structure consists of the following members:
|
||||
X-dimensions.
|
||||
|
||||
output_options integer Set various output 0 (none)
|
||||
parameters - see 5.9
|
||||
parameters - see 5.10
|
||||
Adjusting Output Options.
|
||||
|
||||
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,
|
||||
.emf, .eps, .pcx, .svg,
|
||||
.tif or .txt followed by a
|
||||
terminating NUL.[8]
|
||||
terminating NUL.[9]
|
||||
|
||||
primary character Primary message data for "" (empty)
|
||||
string more complex symbols, with
|
||||
@ -1979,7 +2009,7 @@ encoding stages. The zint_symbol structure consists of the following members:
|
||||
Readable Text (HRT).
|
||||
|
||||
input_mode integer Set encoding of input DATA_MODE
|
||||
data - see 5.10 Setting
|
||||
data - see 5.11 Setting
|
||||
the Input Mode.
|
||||
|
||||
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
|
||||
value returned by Zint
|
||||
API - see 5.7 Handling
|
||||
API - see 5.8 Handling
|
||||
Errors.
|
||||
|
||||
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)
|
||||
string that an error occurred,
|
||||
with a terminating NUL -
|
||||
see 5.7 Handling Errors.
|
||||
see 5.8 Handling Errors.
|
||||
|
||||
bitmap pointer to Pointer to stored bitmap (output only)
|
||||
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
|
||||
Buffering Symbols in
|
||||
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
|
||||
@ -2091,7 +2131,7 @@ ignored:
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
5.8 Specifying a Symbology
|
||||
5.9 Specifying a Symbology
|
||||
|
||||
Symbologies can be specified by number or by name as shown in the Table
|
||||
: Barcode Types (Symbologies). For example
|
||||
@ -2209,7 +2249,7 @@ means the same as
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
between rows if stacking multiple symbols.[10]
|
||||
between rows if stacking multiple symbols.[11]
|
||||
|
||||
BARCODE_BOX Add a box surrounding the symbol and whitespace.
|
||||
|
||||
@ -2252,7 +2292,7 @@ together when adjusting this value:
|
||||
Symbols in Memory (raster).
|
||||
|
||||
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.
|
||||
|
||||
@ -2264,11 +2304,14 @@ together when adjusting this value:
|
||||
|
||||
EMBED_VECTOR_FONT Embed font in vector output - currently available
|
||||
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
|
||||
|
||||
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
|
||||
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 Zint’s automatic mask
|
||||
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:
|
||||
|
||||
@ -2399,7 +2442,7 @@ example:
|
||||
A maximum of 256 segments may be specified. Use of multiple segments with GS1
|
||||
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:
|
||||
|
||||
@ -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
|
||||
barcode appears on.
|
||||
|
||||
5.13 Verifying Symbology Availability
|
||||
5.14 Verifying Symbology Availability
|
||||
|
||||
An additional function available in the API is:
|
||||
|
||||
@ -2472,7 +2515,7 @@ success. For instance:
|
||||
|
||||
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.
|
||||
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_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
|
||||
6.3 GS1 Composite Symbols (ISO 24723) below)
|
||||
@ -2535,7 +2578,7 @@ For example:
|
||||
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
|
||||
with:
|
||||
@ -2995,7 +3038,7 @@ all-numeric characters.
|
||||
[zint -b CODE128AB -d "130170X178"]
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
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: #,
|
||||
$, @, [, \, ], ^, `, {, |, }, ~.
|
||||
|
||||
[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
|
||||
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
|
||||
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.
|
||||
|
||||
[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.
|
||||
|
||||
[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.
|
||||
|
||||
[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.
|
||||
|
@ -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])))
|
||||
#endif
|
||||
|
||||
/* Determine if C89 (excluding MSVC, which doesn't define __STDC_VERSION__) */
|
||||
#if !defined(_MSC_VER) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199000L)
|
||||
#define ZINT_IS_C89
|
||||
/* Determine if C89 or C99 (excluding MSVC, which doesn't define __STDC_VERSION__) */
|
||||
#ifndef _MSC_VER
|
||||
# if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199000L
|
||||
# define ZINT_IS_C89
|
||||
# elif __STDC_VERSION__ <= 199901L /* Actually includes pseudo-standards "C94/C95" as well */
|
||||
# define ZINT_IS_C99
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include <malloc.h>
|
||||
# define z_alloca(nmemb) _alloca(nmemb)
|
||||
#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>
|
||||
# endif
|
||||
# define z_alloca(nmemb) alloca(nmemb)
|
||||
|
@ -326,11 +326,11 @@ version_replace(2, $data_dirname . 'win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp'
|
||||
|
||||
// win32/vs2008/libzint.vcproj
|
||||
|
||||
version_replace(3, $data_dirname . 'win32/vs2008/libzint.vcproj', '/ZINT_VERSION="/', '/"[0-9.]+/', '"' . $v_str);
|
||||
version_replace(2, $data_dirname . 'win32/vs2008/libzint.vcproj', '/ZINT_VERSION="/', '/"[0-9.]+/', '"' . $v_str);
|
||||
|
||||
// win32/vs2008/zint.vcproj
|
||||
|
||||
version_replace(3, $data_dirname . 'win32/vs2008/zint.vcproj', '/ZINT_VERSION="/', '/"[0-9.]+/', '"' . $v_str);
|
||||
version_replace(2, $data_dirname . 'win32/vs2008/zint.vcproj', '/ZINT_VERSION="/', '/"[0-9.]+/', '"' . $v_str);
|
||||
|
||||
// win32/vs2015/libzint.vcxproj
|
||||
|
||||
|
@ -139,6 +139,7 @@
|
||||
<ClCompile Include="..\backend\dotcode.c" />
|
||||
<ClCompile Include="..\backend\eci.c" />
|
||||
<ClCompile Include="..\backend\emf.c" />
|
||||
<ClCompile Include="..\backend\filemem.c" />
|
||||
<ClCompile Include="..\backend\general_field.c" />
|
||||
<ClCompile Include="..\backend\gif.c" />
|
||||
<ClCompile Include="..\backend\gridmtx.c" />
|
||||
@ -187,6 +188,7 @@
|
||||
<ClInclude Include="..\backend\gb18030.h" />
|
||||
<ClInclude Include="..\backend\gb2312.h" />
|
||||
<ClInclude Include="..\backend\gbk.h" />
|
||||
<ClInclude Include="..\backend\filemem.h" />
|
||||
<ClInclude Include="..\backend\general_field.h" />
|
||||
<ClInclude Include="..\backend\gridmtx.h" />
|
||||
<ClInclude Include="..\backend\gs1.h" />
|
||||
|
@ -184,76 +184,6 @@
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</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="\"2.13.0.9\"""
|
||||
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>
|
||||
<References>
|
||||
</References>
|
||||
@ -318,14 +248,6 @@
|
||||
<File
|
||||
RelativePath="..\..\backend\dllversion.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release_LIB|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\backend\dmatrix.c"
|
||||
@ -343,6 +265,10 @@
|
||||
RelativePath="..\..\backend\emf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\backend\filemem.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\backend\general_field.c"
|
||||
>
|
||||
@ -533,6 +459,10 @@
|
||||
RelativePath="..\..\backend\gbk.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\backend\filemem.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\backend\general_field.h"
|
||||
>
|
||||
@ -642,14 +572,6 @@
|
||||
<File
|
||||
RelativePath="..\..\backend\libzint.rc"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release_LIB|Win32"
|
||||
ExcludedFromBuild="true"
|
||||
>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
|
29
win32/vs2008/zint.sln
Normal file
29
win32/vs2008/zint.sln
Normal 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
|
@ -41,7 +41,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\backend"
|
||||
AdditionalIncludeDirectories="..\..\backend"
|
||||
PreprocessorDefinitions="WIN32;_WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ZINT_VERSION="\"2.13.0.9\"";ZINT_DLL"
|
||||
MinimalRebuild="true"
|
||||
ExceptionHandling="0"
|
||||
@ -114,7 +114,7 @@
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories="..\backend"
|
||||
AdditionalIncludeDirectories="..\..\backend"
|
||||
PreprocessorDefinitions="WIN32;_WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;ZINT_VERSION="\"2.13.0.9\"";ZINT_DLL"
|
||||
StringPooling="true"
|
||||
ExceptionHandling="0"
|
||||
@ -136,80 +136,7 @@
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalLibraryDirectories="d:\opt\lib"
|
||||
/>
|
||||
<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="\"2.13.0.9\"""
|
||||
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"
|
||||
AdditionalLibraryDirectories=""
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
@ -243,15 +170,15 @@
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\getopt\getopt.c"
|
||||
RelativePath="..\..\getopt\getopt.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\getopt\getopt1.c"
|
||||
RelativePath="..\..\getopt\getopt1.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\frontend\main.c"
|
||||
RelativePath="..\..\frontend\main.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
@ -261,11 +188,11 @@
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\getopt\getopt.h"
|
||||
RelativePath="..\..\getopt\getopt.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\frontend\resource.h"
|
||||
RelativePath="..\..\frontend\resource.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
@ -275,7 +202,7 @@
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\frontend\zint.rc"
|
||||
RelativePath="..\..\frontend\zint.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
|
@ -316,6 +316,7 @@
|
||||
<ClCompile Include="..\..\backend\dotcode.c" />
|
||||
<ClCompile Include="..\..\backend\eci.c" />
|
||||
<ClCompile Include="..\..\backend\emf.c" />
|
||||
<ClCompile Include="..\..\backend\filemem.c" />
|
||||
<ClCompile Include="..\..\backend\general_field.c" />
|
||||
<ClCompile Include="..\..\backend\gif.c" />
|
||||
<ClCompile Include="..\..\backend\gridmtx.c" />
|
||||
@ -364,6 +365,7 @@
|
||||
<ClInclude Include="..\..\backend\gb18030.h" />
|
||||
<ClInclude Include="..\..\backend\gb2312.h" />
|
||||
<ClInclude Include="..\..\backend\gbk.h" />
|
||||
<ClInclude Include="..\..\backend\filemem.h" />
|
||||
<ClInclude Include="..\..\backend\general_field.h" />
|
||||
<ClInclude Include="..\..\backend\gridmtx.h" />
|
||||
<ClInclude Include="..\..\backend\gs1.h" />
|
||||
|
@ -139,6 +139,7 @@
|
||||
<ClCompile Include="..\..\backend\dotcode.c" />
|
||||
<ClCompile Include="..\..\backend\eci.c" />
|
||||
<ClCompile Include="..\..\backend\emf.c" />
|
||||
<ClCompile Include="..\..\backend\filemem.c" />
|
||||
<ClCompile Include="..\..\backend\general_field.c" />
|
||||
<ClCompile Include="..\..\backend\gif.c" />
|
||||
<ClCompile Include="..\..\backend\gridmtx.c" />
|
||||
@ -187,6 +188,7 @@
|
||||
<ClInclude Include="..\..\backend\gb18030.h" />
|
||||
<ClInclude Include="..\..\backend\gb2312.h" />
|
||||
<ClInclude Include="..\..\backend\gbk.h" />
|
||||
<ClInclude Include="..\..\backend\filemem.h" />
|
||||
<ClInclude Include="..\..\backend\general_field.h" />
|
||||
<ClInclude Include="..\..\backend\gridmtx.h" />
|
||||
<ClInclude Include="..\..\backend\gs1.h" />
|
||||
|
@ -139,6 +139,7 @@
|
||||
<ClCompile Include="..\..\backend\dotcode.c" />
|
||||
<ClCompile Include="..\..\backend\eci.c" />
|
||||
<ClCompile Include="..\..\backend\emf.c" />
|
||||
<ClCompile Include="..\..\backend\filemem.c" />
|
||||
<ClCompile Include="..\..\backend\general_field.c" />
|
||||
<ClCompile Include="..\..\backend\gif.c" />
|
||||
<ClCompile Include="..\..\backend\gridmtx.c" />
|
||||
@ -187,6 +188,7 @@
|
||||
<ClInclude Include="..\..\backend\gb18030.h" />
|
||||
<ClInclude Include="..\..\backend\gb2312.h" />
|
||||
<ClInclude Include="..\..\backend\gbk.h" />
|
||||
<ClInclude Include="..\..\backend\filemem.h" />
|
||||
<ClInclude Include="..\..\backend\general_field.h" />
|
||||
<ClInclude Include="..\..\backend\gridmtx.h" />
|
||||
<ClInclude Include="..\..\backend\gs1.h" />
|
||||
|
@ -156,6 +156,10 @@ SOURCE=..\..\backend\emf.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\backend\filemem.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\..\backend\general_field.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
Loading…
Reference in New Issue
Block a user