mirror of
https://git.code.sf.net/p/zint/code
synced 2026-06-15 10:03:36 +00: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:
@@ -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
|
||||
|
||||
+21
-44
@@ -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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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,29 +154,20 @@ 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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 : */
|
||||
|
||||
+20
-4
@@ -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;
|
||||
|
||||
+42
-64
@@ -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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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,43 +800,34 @@ 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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
return error_number;
|
||||
}
|
||||
|
||||
@@ -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 : */
|
||||
@@ -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 */
|
||||
+28
-49
@@ -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,22 +274,14 @@ 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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -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,41 +446,32 @@ 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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+12
-1
@@ -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 */
|
||||
|
||||
+17
-39
@@ -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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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,30 +144,21 @@ 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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+40
-48
@@ -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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
+108
-120
@@ -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,21 +193,15 @@ 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));
|
||||
return ZINT_ERROR_FILE_ACCESS;
|
||||
}
|
||||
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) {
|
||||
@@ -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,70 +462,61 @@ 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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
return error_number;
|
||||
|
||||
+4
-2
@@ -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) {
|
||||
|
||||
+13
-4
@@ -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);
|
||||
|
||||
+103
-112
@@ -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));
|
||||
return ZINT_ERROR_FILE_ACCESS;
|
||||
}
|
||||
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,53 +316,44 @@ 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));
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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,7 +222,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);
|
||||
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, 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);
|
||||
|
||||
@@ -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,7 +270,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);
|
||||
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, 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,7 +136,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);
|
||||
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, 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,7 +332,23 @@ 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);
|
||||
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, 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);
|
||||
|
||||
+22
-3
@@ -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);
|
||||
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_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);
|
||||
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_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,7 +303,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);
|
||||
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, 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.
+46
-65
@@ -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));
|
||||
return ZINT_ERROR_FILE_ACCESS;
|
||||
}
|
||||
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;
|
||||
|
||||
+12
-12
@@ -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;
|
||||
|
||||
+6
-2
@@ -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));
|
||||
|
||||
+19
-16
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user