- BMP/EMF/PCX/TIF: fix endianness on big-endian machines (note TIF

now always written as little-endian - simplifies testing)
- READMEs: add date updated
This commit is contained in:
gitlost 2024-01-17 01:45:45 +00:00
parent cf04ac15b0
commit bead450f38
16 changed files with 317 additions and 265 deletions

View file

@ -21,6 +21,8 @@ Bugs
also lessens to some degree chances of being victim of OOM killer on Linux) also lessens to some degree chances of being victim of OOM killer on Linux)
- GUI: printing scale dialog: set maxima on X-dim and resolution to keep scale - GUI: printing scale dialog: set maxima on X-dim and resolution to keep scale
<= 200 <= 200
- BMP/EMF/PCX/TIF: fix endianness on big-endian machines (note TIF now always
written as little-endian - simplifies testing)
Version 2.13.0 (2023-12-18) Version 2.13.0 (2023-12-18)

View file

@ -1,3 +1,4 @@
% README.bsd 2024-01-17
% Tested on FreeBSD 14.0-RELEASE (with X11 + GNOME installed), OpenBSD 7.4 (with X11) and NetBSD 9.3 (with X11) % Tested on FreeBSD 14.0-RELEASE (with X11 + GNOME installed), OpenBSD 7.4 (with X11) and NetBSD 9.3 (with X11)
1. Prerequisites for building zint 1. Prerequisites for building zint

View file

@ -1,4 +1,5 @@
Current as of latest clang-tidy-18 from Ubuntu 22.04 apt package (2023-12-26) % README.clang-tidy 2024-01-17
% Current as of latest clang-tidy-18 from Ubuntu 22.04 apt package
Requires cmake in "build" sub-directory with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON (for "build/compile_commands.json") Requires cmake in "build" sub-directory with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON (for "build/compile_commands.json")
and -DCMAKE_BUILD_TYPE=Debug (so `assert()`s defined), and then make (for Qt generated includes). and -DCMAKE_BUILD_TYPE=Debug (so `assert()`s defined), and then make (for Qt generated includes).

View file

@ -1,3 +1,4 @@
% README.linux 2024-01-17
% Tested on Ubuntu 20.04.4 LTS, Ubuntu 22.04 LTS and Fedora Linux 39 (Workstation Edition) % Tested on Ubuntu 20.04.4 LTS, Ubuntu 22.04 LTS and Fedora Linux 39 (Workstation Edition)
1. Prerequisites for building zint 1. Prerequisites for building zint

View file

@ -1,3 +1,4 @@
% README.macos 2014-01-17
% Tested on macOS 12.4 Monterey VirtualBox (thanks to https://github.com/myspaghetti/macos-virtualbox) % Tested on macOS 12.4 Monterey VirtualBox (thanks to https://github.com/myspaghetti/macos-virtualbox)
1. Prerequisites for building zint and zint-qt 1. Prerequisites for building zint and zint-qt

View file

@ -1 +1,2 @@
% README.windows 2014-01-17
See "README" in the "win32" sub-directory. See "README" in the "win32" sub-directory.

View file

@ -1,7 +1,7 @@
/* bmp.c - Handles output to Windows Bitmap file */ /* bmp.c - Handles output to Windows Bitmap file */
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -97,23 +97,23 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
file_header.header_field = 0x4d42; /* "BM" */ out_le_u16(file_header.header_field, 0x4d42); /* "BM" */
file_header.file_size = (uint32_t) file_size; out_le_u32(file_header.file_size, file_size);
file_header.reserved = 0; out_le_u32(file_header.reserved, 0);
file_header.data_offset = (uint32_t) data_offset; out_le_u32(file_header.data_offset, data_offset);
info_header.header_size = sizeof(bitmap_info_header_t); out_le_u32(info_header.header_size, sizeof(bitmap_info_header_t));
info_header.width = symbol->bitmap_width; out_le_i32(info_header.width, symbol->bitmap_width);
info_header.height = symbol->bitmap_height; out_le_i32(info_header.height, symbol->bitmap_height);
info_header.colour_planes = 1; out_le_u16(info_header.colour_planes, 1);
info_header.bits_per_pixel = bits_per_pixel; out_le_u16(info_header.bits_per_pixel, bits_per_pixel);
info_header.compression_method = 0; /* BI_RGB */ out_le_u32(info_header.compression_method, 0); /* BI_RGB */
info_header.image_size = 0; out_le_u32(info_header.image_size, 0);
resolution = symbol->dpmm ? (int) roundf(stripf(symbol->dpmm * 1000.0f)) : 0; /* pixels per metre */ resolution = symbol->dpmm ? (int) roundf(stripf(symbol->dpmm * 1000.0f)) : 0; /* pixels per metre */
info_header.horiz_res = resolution; out_le_i32(info_header.horiz_res, resolution);
info_header.vert_res = resolution; out_le_i32(info_header.vert_res, resolution);
info_header.colours = colour_count; out_le_u32(info_header.colours, colour_count);
info_header.important_colours = colour_count; out_le_u32(info_header.important_colours, colour_count);
/* Open output file in binary mode */ /* Open output file in binary mode */
if (!fm_open(fmp, symbol, "wb")) { if (!fm_open(fmp, symbol, "wb")) {

View file

@ -200,6 +200,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
emr_exttextoutw_t text[6]; emr_exttextoutw_t text[6];
float text_fsizes[6]; float text_fsizes[6];
int text_haligns[6]; int text_haligns[6];
int text_bumped_lens[6];
emr_header_t emr_header; emr_header_t emr_header;
emr_eof_t emr_eof; emr_eof_t emr_eof;
@ -303,74 +304,76 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
} }
/* Header */ /* Header */
emr_header.type = 0x00000001; /* EMR_HEADER */ out_le_u32(emr_header.type, 0x00000001); /* EMR_HEADER */
emr_header.size = 108; /* Including extensions */ out_le_u32(emr_header.size, 108); /* Including extensions */
emr_header.emf_header.bounds.left = emr_header.emf_header.bounds.top = 0; out_le_i32(emr_header.emf_header.bounds.left, 0);
emr_header.emf_header.bounds.right = sideways ? bounds_pxy : bounds_pxx; out_le_i32(emr_header.emf_header.bounds.top, 0);
emr_header.emf_header.bounds.bottom = sideways ? bounds_pxx : bounds_pxy; out_le_i32(emr_header.emf_header.bounds.right, sideways ? bounds_pxy : bounds_pxx);
emr_header.emf_header.frame.left = emr_header.emf_header.frame.top = 0; out_le_i32(emr_header.emf_header.bounds.bottom, sideways ? bounds_pxx : bounds_pxy);
emr_header.emf_header.frame.right = sideways ? frame_cmmy : frame_cmmx; out_le_i32(emr_header.emf_header.frame.left, 0);
emr_header.emf_header.frame.bottom = sideways ? frame_cmmx : frame_cmmy; out_le_i32(emr_header.emf_header.frame.top, 0);
emr_header.emf_header.record_signature = 0x464d4520; /* ENHMETA_SIGNATURE */ out_le_i32(emr_header.emf_header.frame.right, sideways ? frame_cmmy : frame_cmmx);
emr_header.emf_header.version = 0x00010000; out_le_i32(emr_header.emf_header.frame.bottom, sideways ? frame_cmmx : frame_cmmy);
emr_header.emf_header.handles = (fsize2 != 0.0f ? 5 : 4) + ih_ultra_offset; /* Number of graphics objects */ out_le_u32(emr_header.emf_header.record_signature, 0x464d4520); /* ENHMETA_SIGNATURE */
emr_header.emf_header.reserved = 0x0000; out_le_u32(emr_header.emf_header.version, 0x00010000);
emr_header.emf_header.n_description = 0; out_le_u16(emr_header.emf_header.handles, (fsize2 != 0.0f ? 5 : 4) + ih_ultra_offset); /* No. of graphics objs */
emr_header.emf_header.off_description = 0; out_le_u16(emr_header.emf_header.reserved, 0x0000);
emr_header.emf_header.n_pal_entries = 0; out_le_u32(emr_header.emf_header.n_description, 0);
emr_header.emf_header.device.cx = sideways ? device_pxy : device_pxx; out_le_u32(emr_header.emf_header.off_description, 0);
emr_header.emf_header.device.cy = sideways ? device_pxx : device_pxy; out_le_u32(emr_header.emf_header.n_pal_entries, 0);
emr_header.emf_header.millimeters.cx = sideways ? mmy : mmx; out_le_u32(emr_header.emf_header.device.cx, sideways ? device_pxy : device_pxx);
emr_header.emf_header.millimeters.cy = sideways ? mmx : mmy; out_le_u32(emr_header.emf_header.device.cy, sideways ? device_pxx : device_pxy);
out_le_u32(emr_header.emf_header.millimeters.cx, sideways ? mmy : mmx);
out_le_u32(emr_header.emf_header.millimeters.cy, sideways ? mmx : mmy);
/* HeaderExtension1 */ /* HeaderExtension1 */
emr_header.emf_header.cb_pixel_format = 0x0000; /* None set */ out_le_u32(emr_header.emf_header.cb_pixel_format, 0x0000); /* None set */
emr_header.emf_header.off_pixel_format = 0x0000; /* None set */ out_le_u32(emr_header.emf_header.off_pixel_format, 0x0000); /* None set */
emr_header.emf_header.b_open_gl = 0x0000; /* OpenGL not present */ out_le_u32(emr_header.emf_header.b_open_gl, 0x0000); /* OpenGL not present */
/* HeaderExtension2 */ /* HeaderExtension2 */
emr_header.emf_header.micrometers.cx = sideways ? microny : micronx; out_le_u32(emr_header.emf_header.micrometers.cx, sideways ? microny : micronx);
emr_header.emf_header.micrometers.cy = sideways ? micronx : microny; out_le_u32(emr_header.emf_header.micrometers.cy, sideways ? micronx : microny);
bytecount = 108; bytecount = 108;
recordcount = 1; recordcount = 1;
emr_mapmode.type = 0x00000011; /* EMR_SETMAPMODE */ out_le_u32(emr_mapmode.type, 0x00000011); /* EMR_SETMAPMODE */
emr_mapmode.size = 12; out_le_u32(emr_mapmode.size, 12);
emr_mapmode.mapmode = 0x01; /* MM_TEXT */ out_le_u32(emr_mapmode.mapmode, 0x01); /* MM_TEXT */
bytecount += 12; bytecount += 12;
recordcount++; recordcount++;
if (rotate_angle) { if (rotate_angle) {
emr_setworldtransform.type = 0x00000023; /* EMR_SETWORLDTRANSFORM */ out_le_u32(emr_setworldtransform.type, 0x00000023); /* EMR_SETWORLDTRANSFORM */
emr_setworldtransform.size = 32; out_le_u32(emr_setworldtransform.size, 32);
emr_setworldtransform.m11 = rotate_angle == 90 ? 0.0f : rotate_angle == 180 ? -1.0f : 0.0f; out_le_float(emr_setworldtransform.m11, rotate_angle == 90 ? 0.0f : rotate_angle == 180 ? -1.0f : 0.0f);
emr_setworldtransform.m12 = rotate_angle == 90 ? 1.0f : rotate_angle == 180 ? 0.0f : -1.0f; out_le_float(emr_setworldtransform.m12, rotate_angle == 90 ? 1.0f : rotate_angle == 180 ? 0.0f : -1.0f);
emr_setworldtransform.m21 = rotate_angle == 90 ? -1.0f : rotate_angle == 180 ? 0.0f : 1.0f; out_le_float(emr_setworldtransform.m21, rotate_angle == 90 ? -1.0f : rotate_angle == 180 ? 0.0f : 1.0f);
emr_setworldtransform.m22 = rotate_angle == 90 ? 0.0f : rotate_angle == 180 ? -1.0f : 0.0f; out_le_float(emr_setworldtransform.m22, rotate_angle == 90 ? 0.0f : rotate_angle == 180 ? -1.0f : 0.0f);
emr_setworldtransform.dx = rotate_angle == 90 ? height : rotate_angle == 180 ? width : 0.0f; out_le_float(emr_setworldtransform.dx, rotate_angle == 90 ? height : rotate_angle == 180 ? width : 0.0f);
emr_setworldtransform.dy = rotate_angle == 90 ? 0.0f : rotate_angle == 180 ? height : width; out_le_float(emr_setworldtransform.dy, rotate_angle == 90 ? 0.0f : rotate_angle == 180 ? height : width);
bytecount += 32; bytecount += 32;
recordcount++; recordcount++;
} }
/* Create Brushes */ /* Create Brushes */
emr_createbrushindirect_bg.type = 0x00000027; /* EMR_CREATEBRUSHINDIRECT */ out_le_u32(emr_createbrushindirect_bg.type, 0x00000027); /* EMR_CREATEBRUSHINDIRECT */
emr_createbrushindirect_bg.size = 24; out_le_u32(emr_createbrushindirect_bg.size, 24);
emr_createbrushindirect_bg.ih_brush = 0; out_le_u32(emr_createbrushindirect_bg.ih_brush, 0);
emr_createbrushindirect_bg.log_brush.brush_style = 0x0000; /* BS_SOLID */ out_le_u32(emr_createbrushindirect_bg.log_brush.brush_style, 0x0000); /* BS_SOLID */
emr_createbrushindirect_bg.log_brush.color.red = bgred; emr_createbrushindirect_bg.log_brush.color.red = bgred;
emr_createbrushindirect_bg.log_brush.color.green = bggrn; emr_createbrushindirect_bg.log_brush.color.green = bggrn;
emr_createbrushindirect_bg.log_brush.color.blue = bgblu; emr_createbrushindirect_bg.log_brush.color.blue = bgblu;
emr_createbrushindirect_bg.log_brush.color.reserved = 0; emr_createbrushindirect_bg.log_brush.color.reserved = 0;
emr_createbrushindirect_bg.log_brush.brush_hatch = 0x0006; /* HS_SOLIDCLR */ out_le_u32(emr_createbrushindirect_bg.log_brush.brush_hatch, 0x0006); /* HS_SOLIDCLR */
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
if (symbol->symbology == BARCODE_ULTRA) { if (symbol->symbology == BARCODE_ULTRA) {
static const char ultra_chars[] = "0CBMRYGKW"; static const char ultra_chars[] = "0CBMRYGKW";
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
emr_createbrushindirect_colour[i].type = 0x00000027; /* EMR_CREATEBRUSHINDIRECT */ out_le_u32(emr_createbrushindirect_colour[i].type, 0x00000027); /* EMR_CREATEBRUSHINDIRECT */
emr_createbrushindirect_colour[i].size = 24; out_le_u32(emr_createbrushindirect_colour[i].size, 24);
emr_createbrushindirect_colour[i].ih_brush = 1 + i; out_le_u32(emr_createbrushindirect_colour[i].ih_brush, 1 + i);
emr_createbrushindirect_colour[i].log_brush.brush_style = 0x0000; /* BS_SOLID */ out_le_u32(emr_createbrushindirect_colour[i].log_brush.brush_style, 0x0000); /* BS_SOLID */
if (i == 0) { if (i == 0) {
emr_createbrushindirect_colour[i].log_brush.color.red = fgred; emr_createbrushindirect_colour[i].log_brush.color.red = fgred;
emr_createbrushindirect_colour[i].log_brush.color.green = fggrn; emr_createbrushindirect_colour[i].log_brush.color.green = fggrn;
@ -382,53 +385,53 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
&emr_createbrushindirect_colour[i].log_brush.color.blue); &emr_createbrushindirect_colour[i].log_brush.color.blue);
} }
emr_createbrushindirect_colour[i].log_brush.color.reserved = 0; emr_createbrushindirect_colour[i].log_brush.color.reserved = 0;
emr_createbrushindirect_colour[i].log_brush.brush_hatch = 0x0006; /* HS_SOLIDCLR */ out_le_u32(emr_createbrushindirect_colour[i].log_brush.brush_hatch, 0x0006); /* HS_SOLIDCLR */
} }
bytecount += colours_used * 24; bytecount += colours_used * 24;
recordcount += colours_used; recordcount += colours_used;
} else { } else {
emr_createbrushindirect_fg.type = 0x00000027; /* EMR_CREATEBRUSHINDIRECT */ out_le_u32(emr_createbrushindirect_fg.type, 0x00000027); /* EMR_CREATEBRUSHINDIRECT */
emr_createbrushindirect_fg.size = 24; out_le_u32(emr_createbrushindirect_fg.size, 24);
emr_createbrushindirect_fg.ih_brush = 1; out_le_u32(emr_createbrushindirect_fg.ih_brush, 1);
emr_createbrushindirect_fg.log_brush.brush_style = 0x0000; /* BS_SOLID */ out_le_u32(emr_createbrushindirect_fg.log_brush.brush_style, 0x0000); /* BS_SOLID */
emr_createbrushindirect_fg.log_brush.color.red = fgred; emr_createbrushindirect_fg.log_brush.color.red = fgred;
emr_createbrushindirect_fg.log_brush.color.green = fggrn; emr_createbrushindirect_fg.log_brush.color.green = fggrn;
emr_createbrushindirect_fg.log_brush.color.blue = fgblu; emr_createbrushindirect_fg.log_brush.color.blue = fgblu;
emr_createbrushindirect_fg.log_brush.color.reserved = 0; emr_createbrushindirect_fg.log_brush.color.reserved = 0;
emr_createbrushindirect_fg.log_brush.brush_hatch = 0x0006; /* HS_SOLIDCLR */ out_le_u32(emr_createbrushindirect_fg.log_brush.brush_hatch, 0x0006); /* HS_SOLIDCLR */
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
} }
emr_selectobject_bgbrush.type = 0x00000025; /* EMR_SELECTOBJECT */ out_le_u32(emr_selectobject_bgbrush.type, 0x00000025); /* EMR_SELECTOBJECT */
emr_selectobject_bgbrush.size = 12; out_le_u32(emr_selectobject_bgbrush.size, 12);
emr_selectobject_bgbrush.ih_object = emr_createbrushindirect_bg.ih_brush; emr_selectobject_bgbrush.ih_object = emr_createbrushindirect_bg.ih_brush;
bytecount += 12; bytecount += 12;
recordcount++; recordcount++;
if (symbol->symbology == BARCODE_ULTRA) { if (symbol->symbology == BARCODE_ULTRA) {
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
emr_selectobject_colour[i].type = 0x00000025; /* EMR_SELECTOBJECT */ out_le_u32(emr_selectobject_colour[i].type, 0x00000025); /* EMR_SELECTOBJECT */
emr_selectobject_colour[i].size = 12; out_le_u32(emr_selectobject_colour[i].size, 12);
emr_selectobject_colour[i].ih_object = emr_createbrushindirect_colour[i].ih_brush; emr_selectobject_colour[i].ih_object = emr_createbrushindirect_colour[i].ih_brush;
} }
bytecount += colours_used * 12; bytecount += colours_used * 12;
recordcount += colours_used; recordcount += colours_used;
} else { } else {
emr_selectobject_fgbrush.type = 0x00000025; /* EMR_SELECTOBJECT */ out_le_u32(emr_selectobject_fgbrush.type, 0x00000025); /* EMR_SELECTOBJECT */
emr_selectobject_fgbrush.size = 12; out_le_u32(emr_selectobject_fgbrush.size, 12);
emr_selectobject_fgbrush.ih_object = emr_createbrushindirect_fg.ih_brush; emr_selectobject_fgbrush.ih_object = emr_createbrushindirect_fg.ih_brush;
bytecount += 12; bytecount += 12;
recordcount++; recordcount++;
} }
/* Create Pens */ /* Create Pens */
emr_createpen.type = 0x00000026; /* EMR_CREATEPEN */ out_le_u32(emr_createpen.type, 0x00000026); /* EMR_CREATEPEN */
emr_createpen.size = 28; out_le_u32(emr_createpen.size, 28);
emr_createpen.ih_pen = 2 + ih_ultra_offset; out_le_u32(emr_createpen.ih_pen, 2 + ih_ultra_offset);
emr_createpen.log_pen.pen_style = 0x00000005; /* PS_NULL */ out_le_u32(emr_createpen.log_pen.pen_style, 0x00000005); /* PS_NULL */
emr_createpen.log_pen.width.x = 1; out_le_i32(emr_createpen.log_pen.width.x, 1);
emr_createpen.log_pen.width.y = 0; /* ignored */ out_le_i32(emr_createpen.log_pen.width.y, 0); /* ignored */
emr_createpen.log_pen.color_ref.red = 0; emr_createpen.log_pen.color_ref.red = 0;
emr_createpen.log_pen.color_ref.green = 0; emr_createpen.log_pen.color_ref.green = 0;
emr_createpen.log_pen.color_ref.blue = 0; emr_createpen.log_pen.color_ref.blue = 0;
@ -436,20 +439,20 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
bytecount += 28; bytecount += 28;
recordcount++; recordcount++;
emr_selectobject_pen.type = 0x00000025; /* EMR_SELECTOBJECT */ out_le_u32(emr_selectobject_pen.type, 0x00000025); /* EMR_SELECTOBJECT */
emr_selectobject_pen.size = 12; out_le_u32(emr_selectobject_pen.size, 12);
emr_selectobject_pen.ih_object = emr_createpen.ih_pen; emr_selectobject_pen.ih_object = emr_createpen.ih_pen;
bytecount += 12; bytecount += 12;
recordcount++; recordcount++;
if (draw_background) { if (draw_background) {
/* Make background from a rectangle */ /* Make background from a rectangle */
background.type = 0x0000002b; /* EMR_RECTANGLE */ out_le_u32(background.type, 0x0000002b); /* EMR_RECTANGLE */
background.size = 24; out_le_u32(background.size, 24);
background.box.top = 0; out_le_i32(background.box.top, 0);
background.box.left = 0; out_le_i32(background.box.left, 0);
background.box.right = width; out_le_i32(background.box.right, width);
background.box.bottom = height; out_le_i32(background.box.bottom, height);
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
} }
@ -458,12 +461,12 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
rect = symbol->vector->rectangles; rect = symbol->vector->rectangles;
this_rectangle = 0; this_rectangle = 0;
while (rect) { while (rect) {
rectangle[this_rectangle].type = 0x0000002b; /* EMR_RECTANGLE */ out_le_u32(rectangle[this_rectangle].type, 0x0000002b); /* EMR_RECTANGLE */
rectangle[this_rectangle].size = 24; out_le_u32(rectangle[this_rectangle].size, 24);
rectangle[this_rectangle].box.top = (int32_t) rect->y; out_le_i32(rectangle[this_rectangle].box.top, rect->y);
rectangle[this_rectangle].box.bottom = (int32_t) stripf(rect->y + rect->height); out_le_i32(rectangle[this_rectangle].box.bottom, stripf(rect->y + rect->height));
rectangle[this_rectangle].box.left = (int32_t) rect->x; out_le_i32(rectangle[this_rectangle].box.left, rect->x);
rectangle[this_rectangle].box.right = (int32_t) stripf(rect->x + rect->width); out_le_i32(rectangle[this_rectangle].box.right, stripf(rect->x + rect->width));
this_rectangle++; this_rectangle++;
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
@ -481,24 +484,24 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
previous_diameter = circ->diameter + circ->width; previous_diameter = circ->diameter + circ->width;
radius = emf_mul3dpf(0.5f, previous_diameter); radius = emf_mul3dpf(0.5f, previous_diameter);
} }
circle[this_circle].type = 0x0000002a; /* EMR_ELLIPSE */ out_le_u32(circle[this_circle].type, 0x0000002a); /* EMR_ELLIPSE */
circle[this_circle].size = 24; out_le_u32(circle[this_circle].size, 24);
circle[this_circle].box.top = (int32_t) stripf(circ->y - radius); out_le_i32(circle[this_circle].box.top, stripf(circ->y - radius));
circle[this_circle].box.bottom = (int32_t) stripf(circ->y + radius); out_le_i32(circle[this_circle].box.bottom, stripf(circ->y + radius));
circle[this_circle].box.left = (int32_t) stripf(circ->x - radius); out_le_i32(circle[this_circle].box.left, stripf(circ->x - radius));
circle[this_circle].box.right = (int32_t) stripf(circ->x + radius); out_le_i32(circle[this_circle].box.right, stripf(circ->x + radius));
this_circle++; this_circle++;
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
if (symbol->symbology == BARCODE_MAXICODE) { /* Drawing MaxiCode bullseye using overlayed discs */ if (symbol->symbology == BARCODE_MAXICODE) { /* Drawing MaxiCode bullseye using overlayed discs */
float inner_radius = radius - circ->width; float inner_radius = radius - circ->width;
circle[this_circle].type = 0x0000002a; /* EMR_ELLIPSE */ out_le_u32(circle[this_circle].type, 0x0000002a); /* EMR_ELLIPSE */
circle[this_circle].size = 24; out_le_u32(circle[this_circle].size, 24);
circle[this_circle].box.top = (int32_t) stripf(circ->y - inner_radius); out_le_i32(circle[this_circle].box.top, stripf(circ->y - inner_radius));
circle[this_circle].box.bottom = (int32_t) stripf(circ->y + inner_radius); out_le_i32(circle[this_circle].box.bottom, stripf(circ->y + inner_radius));
circle[this_circle].box.left = (int32_t) stripf(circ->x - inner_radius); out_le_i32(circle[this_circle].box.left, stripf(circ->x - inner_radius));
circle[this_circle].box.right = (int32_t) stripf(circ->x + inner_radius); out_le_i32(circle[this_circle].box.right, stripf(circ->x + inner_radius));
this_circle++; this_circle++;
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
@ -512,9 +515,9 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
hex = symbol->vector->hexagons; hex = symbol->vector->hexagons;
this_hexagon = 0; this_hexagon = 0;
while (hex) { while (hex) {
hexagon[this_hexagon].type = 0x00000003; /* EMR_POLYGON */ out_le_u32(hexagon[this_hexagon].type, 0x00000003); /* EMR_POLYGON */
hexagon[this_hexagon].size = 76; out_le_u32(hexagon[this_hexagon].size, 76);
hexagon[this_hexagon].count = 6; out_le_u32(hexagon[this_hexagon].count, 6);
if (previous_diameter != hex->diameter) { if (previous_diameter != hex->diameter) {
previous_diameter = hex->diameter; previous_diameter = hex->diameter;
@ -524,18 +527,18 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
} }
/* Note rotation done via world transform */ /* Note rotation done via world transform */
hexagon[this_hexagon].a_points_a.x = (int32_t) hex->x; out_le_i32(hexagon[this_hexagon].a_points_a.x, hex->x);
hexagon[this_hexagon].a_points_a.y = (int32_t) stripf(hex->y + radius); out_le_i32(hexagon[this_hexagon].a_points_a.y, stripf(hex->y + radius));
hexagon[this_hexagon].a_points_b.x = (int32_t) stripf(hex->x + half_sqrt3_radius); out_le_i32(hexagon[this_hexagon].a_points_b.x, stripf(hex->x + half_sqrt3_radius));
hexagon[this_hexagon].a_points_b.y = (int32_t) stripf(hex->y + half_radius); out_le_i32(hexagon[this_hexagon].a_points_b.y, stripf(hex->y + half_radius));
hexagon[this_hexagon].a_points_c.x = (int32_t) stripf(hex->x + half_sqrt3_radius); out_le_i32(hexagon[this_hexagon].a_points_c.x, stripf(hex->x + half_sqrt3_radius));
hexagon[this_hexagon].a_points_c.y = (int32_t) stripf(hex->y - half_radius); out_le_i32(hexagon[this_hexagon].a_points_c.y, stripf(hex->y - half_radius));
hexagon[this_hexagon].a_points_d.x = (int32_t) hex->x; out_le_i32(hexagon[this_hexagon].a_points_d.x, hex->x);
hexagon[this_hexagon].a_points_d.y = (int32_t) stripf(hex->y - radius); out_le_i32(hexagon[this_hexagon].a_points_d.y, stripf(hex->y - radius));
hexagon[this_hexagon].a_points_e.x = (int32_t) stripf(hex->x - half_sqrt3_radius); out_le_i32(hexagon[this_hexagon].a_points_e.x, stripf(hex->x - half_sqrt3_radius));
hexagon[this_hexagon].a_points_e.y = (int32_t) stripf(hex->y - half_radius); out_le_i32(hexagon[this_hexagon].a_points_e.y, stripf(hex->y - half_radius));
hexagon[this_hexagon].a_points_f.x = (int32_t) stripf(hex->x - half_sqrt3_radius); out_le_i32(hexagon[this_hexagon].a_points_f.x, stripf(hex->x - half_sqrt3_radius));
hexagon[this_hexagon].a_points_f.y = (int32_t) stripf(hex->y + half_radius); out_le_i32(hexagon[this_hexagon].a_points_f.y, stripf(hex->y + half_radius));
hexagon[this_hexagon].bounds.top = hexagon[this_hexagon].a_points_d.y; hexagon[this_hexagon].bounds.top = hexagon[this_hexagon].a_points_d.y;
hexagon[this_hexagon].bounds.bottom = hexagon[this_hexagon].a_points_a.y; hexagon[this_hexagon].bounds.bottom = hexagon[this_hexagon].a_points_a.y;
@ -551,12 +554,12 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
if (symbol->vector->strings) { if (symbol->vector->strings) {
bold = (symbol->output_options & BOLD_TEXT) && !is_upcean(symbol->symbology); bold = (symbol->output_options & BOLD_TEXT) && !is_upcean(symbol->symbology);
memset(&emr_extcreatefontindirectw, 0, sizeof(emr_extcreatefontindirectw)); memset(&emr_extcreatefontindirectw, 0, sizeof(emr_extcreatefontindirectw));
emr_extcreatefontindirectw.type = 0x00000052; /* EMR_EXTCREATEFONTINDIRECTW */ out_le_u32(emr_extcreatefontindirectw.type, 0x00000052); /* EMR_EXTCREATEFONTINDIRECTW */
emr_extcreatefontindirectw.size = 104; out_le_u32(emr_extcreatefontindirectw.size, 104);
emr_extcreatefontindirectw.ih_fonts = 3 + ih_ultra_offset; out_le_u32(emr_extcreatefontindirectw.ih_fonts, 3 + ih_ultra_offset);
emr_extcreatefontindirectw.elw.height = (int32_t) fsize; out_le_i32(emr_extcreatefontindirectw.elw.height, fsize);
emr_extcreatefontindirectw.elw.width = 0; /* automatic */ out_le_i32(emr_extcreatefontindirectw.elw.width, 0); /* automatic */
emr_extcreatefontindirectw.elw.weight = bold ? 700 : 400; out_le_i32(emr_extcreatefontindirectw.elw.weight, bold ? 700 : 400);
emr_extcreatefontindirectw.elw.char_set = 0x00; /* ANSI_CHARSET */ emr_extcreatefontindirectw.elw.char_set = 0x00; /* ANSI_CHARSET */
emr_extcreatefontindirectw.elw.out_precision = 0x00; /* OUT_DEFAULT_PRECIS */ emr_extcreatefontindirectw.elw.out_precision = 0x00; /* OUT_DEFAULT_PRECIS */
emr_extcreatefontindirectw.elw.clip_precision = 0x00; /* CLIP_DEFAULT_PRECIS */ emr_extcreatefontindirectw.elw.clip_precision = 0x00; /* CLIP_DEFAULT_PRECIS */
@ -565,21 +568,21 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
bytecount += 104; bytecount += 104;
recordcount++; recordcount++;
emr_selectobject_font.type = 0x00000025; /* EMR_SELECTOBJECT */ out_le_u32(emr_selectobject_font.type, 0x00000025); /* EMR_SELECTOBJECT */
emr_selectobject_font.size = 12; out_le_u32(emr_selectobject_font.size, 12);
emr_selectobject_font.ih_object = emr_extcreatefontindirectw.ih_fonts; emr_selectobject_font.ih_object = emr_extcreatefontindirectw.ih_fonts;
bytecount += 12; bytecount += 12;
recordcount++; recordcount++;
if (fsize2) { if (fsize2) {
memcpy(&emr_extcreatefontindirectw2, &emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw)); memcpy(&emr_extcreatefontindirectw2, &emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw));
emr_extcreatefontindirectw2.ih_fonts = 4 + ih_ultra_offset; out_le_u32(emr_extcreatefontindirectw2.ih_fonts, 4 + ih_ultra_offset);
emr_extcreatefontindirectw2.elw.height = (int32_t) fsize2; out_le_i32(emr_extcreatefontindirectw2.elw.height, fsize2);
bytecount += 104; bytecount += 104;
recordcount++; recordcount++;
emr_selectobject_font2.type = 0x00000025; /* EMR_SELECTOBJECT */ out_le_u32(emr_selectobject_font2.type, 0x00000025); /* EMR_SELECTOBJECT */
emr_selectobject_font2.size = 12; out_le_u32(emr_selectobject_font2.size, 12);
emr_selectobject_font2.ih_object = emr_extcreatefontindirectw2.ih_fonts; emr_selectobject_font2.ih_object = emr_extcreatefontindirectw2.ih_fonts;
bytecount += 12; bytecount += 12;
recordcount++; recordcount++;
@ -587,22 +590,22 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
/* Note select aligns counted below in strings loop */ /* Note select aligns counted below in strings loop */
emr_settextalign_centre.type = 0x00000016; /* EMR_SETTEXTALIGN */ out_le_u32(emr_settextalign_centre.type, 0x00000016); /* EMR_SETTEXTALIGN */
emr_settextalign_centre.size = 12; out_le_u32(emr_settextalign_centre.size, 12);
emr_settextalign_centre.text_alignment_mode = 0x0006 | 0x0018; /* TA_CENTER | TA_BASELINE */ out_le_u32(emr_settextalign_centre.text_alignment_mode, 0x0006 | 0x0018); /* TA_CENTER | TA_BASELINE */
if (halign_left) { if (halign_left) {
emr_settextalign_left.type = 0x00000016; /* EMR_SETTEXTALIGN */ out_le_u32(emr_settextalign_left.type, 0x00000016); /* EMR_SETTEXTALIGN */
emr_settextalign_left.size = 12; out_le_u32(emr_settextalign_left.size, 12);
emr_settextalign_left.text_alignment_mode = 0x0000 | 0x0018; /* TA_LEFT | TA_BASELINE */ out_le_u32(emr_settextalign_left.text_alignment_mode, 0x0000 | 0x0018); /* TA_LEFT | TA_BASELINE */
} }
if (halign_right) { if (halign_right) {
emr_settextalign_right.type = 0x00000016; /* EMR_SETTEXTALIGN */ out_le_u32(emr_settextalign_right.type, 0x00000016); /* EMR_SETTEXTALIGN */
emr_settextalign_right.size = 12; out_le_u32(emr_settextalign_right.size, 12);
emr_settextalign_right.text_alignment_mode = 0x0002 | 0x0018; /* TA_RIGHT | TA_BASELINE */ out_le_u32(emr_settextalign_right.text_alignment_mode, 0x0002 | 0x0018); /* TA_RIGHT | TA_BASELINE */
} }
emr_settextcolor.type = 0x0000018; /* EMR_SETTEXTCOLOR */ out_le_u32(emr_settextcolor.type, 0x0000018); /* EMR_SETTEXTCOLOR */
emr_settextcolor.size = 12; out_le_u32(emr_settextcolor.size, 12);
emr_settextcolor.color.red = fgred; emr_settextcolor.color.red = fgred;
emr_settextcolor.color.green = fggrn; emr_settextcolor.color.green = fggrn;
emr_settextcolor.color.blue = fgblu; emr_settextcolor.color.blue = fgblu;
@ -619,7 +622,6 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
current_halign = -1; current_halign = -1;
while (string) { while (string) {
int utfle_len; int utfle_len;
int bumped_len;
if (string->fsize != current_fsize) { if (string->fsize != current_fsize) {
string = string->next; string = string->next;
continue; continue;
@ -633,45 +635,45 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
} }
assert(string->length > 0); assert(string->length > 0);
utfle_len = emf_utfle_length(string->text, string->length); utfle_len = emf_utfle_length(string->text, string->length);
bumped_len = emf_bump_up(utfle_len); text_bumped_lens[this_text] = emf_bump_up(utfle_len);
if (!(this_string[this_text] = (unsigned char *) malloc(bumped_len))) { if (!(this_string[this_text] = (unsigned char *) malloc(text_bumped_lens[this_text]))) {
for (i = 0; i < this_text; i++) { for (i = 0; i < this_text; i++) {
free(this_string[i]); free(this_string[i]);
} }
strcpy(symbol->errtxt, "641: Insufficient memory for EMF string buffer"); strcpy(symbol->errtxt, "641: Insufficient memory for EMF string buffer");
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
memset(this_string[this_text], 0, bumped_len); memset(this_string[this_text], 0, text_bumped_lens[this_text]);
text[this_text].type = 0x00000054; /* EMR_EXTTEXTOUTW */ out_le_u32(text[this_text].type, 0x00000054); /* EMR_EXTTEXTOUTW */
text[this_text].size = 76 + bumped_len; out_le_u32(text[this_text].size, 76 + text_bumped_lens[this_text]);
text[this_text].bounds.top = 0; /* ignored */ out_le_i32(text[this_text].bounds.top, 0); /* ignored */
text[this_text].bounds.left = 0; /* ignored */ out_le_i32(text[this_text].bounds.left, 0); /* ignored */
text[this_text].bounds.right = 0xffffffff; /* ignored */ out_le_i32(text[this_text].bounds.right, 0xffffffff); /* ignored */
text[this_text].bounds.bottom = 0xffffffff; /* ignored */ out_le_i32(text[this_text].bounds.bottom, 0xffffffff); /* ignored */
text[this_text].i_graphics_mode = 0x00000002; /* GM_ADVANCED */ out_le_u32(text[this_text].i_graphics_mode, 0x00000002); /* GM_ADVANCED */
text[this_text].ex_scale = 1.0f; out_le_float(text[this_text].ex_scale, 1.0f);
text[this_text].ey_scale = 1.0f; out_le_float(text[this_text].ey_scale, 1.0f);
/* Unhack the guard whitespace `gws_left_fudge`/`gws_right_fudge` hack */ /* Unhack the guard whitespace `gws_left_fudge`/`gws_right_fudge` hack */
if (upcean && string->halign == 1 && string->text[0] == '<') { if (upcean && string->halign == 1 && string->text[0] == '<') {
const float gws_left_fudge = symbol->scale < 0.1f ? 0.1f : symbol->scale; /* 0.5 * 2 * scale */ const float gws_left_fudge = symbol->scale < 0.1f ? 0.1f : symbol->scale; /* 0.5 * 2 * scale */
text[this_text].w_emr_text.reference.x = (int32_t) (string->x + gws_left_fudge); out_le_i32(text[this_text].w_emr_text.reference.x, string->x + gws_left_fudge);
} else if (upcean && string->halign == 2 && string->text[0] == '>') { } else if (upcean && string->halign == 2 && string->text[0] == '>') {
const float gws_right_fudge = symbol->scale < 0.1f ? 0.1f : symbol->scale; /* 0.5 * 2 * scale */ const float gws_right_fudge = symbol->scale < 0.1f ? 0.1f : symbol->scale; /* 0.5 * 2 * scale */
text[this_text].w_emr_text.reference.x = (int32_t) (string->x - gws_right_fudge); out_le_i32(text[this_text].w_emr_text.reference.x, string->x - gws_right_fudge);
} else { } else {
text[this_text].w_emr_text.reference.x = (int32_t) string->x; out_le_i32(text[this_text].w_emr_text.reference.x, string->x);
} }
text[this_text].w_emr_text.reference.y = (int32_t) string->y; out_le_i32(text[this_text].w_emr_text.reference.y, string->y);
text[this_text].w_emr_text.chars = utfle_len; out_le_u32(text[this_text].w_emr_text.chars, utfle_len);
text[this_text].w_emr_text.off_string = 76; out_le_u32(text[this_text].w_emr_text.off_string, 76);
text[this_text].w_emr_text.options = 0; out_le_u32(text[this_text].w_emr_text.options, 0);
text[this_text].w_emr_text.rectangle.top = 0; out_le_i32(text[this_text].w_emr_text.rectangle.top, 0);
text[this_text].w_emr_text.rectangle.left = 0; out_le_i32(text[this_text].w_emr_text.rectangle.left, 0);
text[this_text].w_emr_text.rectangle.right = 0xffffffff; out_le_i32(text[this_text].w_emr_text.rectangle.right, 0xffffffff);
text[this_text].w_emr_text.rectangle.bottom = 0xffffffff; out_le_i32(text[this_text].w_emr_text.rectangle.bottom, 0xffffffff);
text[this_text].w_emr_text.off_dx = 0; out_le_u32(text[this_text].w_emr_text.off_dx, 0);
emf_utfle_copy(this_string[this_text], string->text, string->length); emf_utfle_copy(this_string[this_text], string->text, string->length);
bytecount += 76 + bumped_len; bytecount += 76 + text_bumped_lens[this_text];
recordcount++; recordcount++;
this_text++; this_text++;
@ -682,10 +684,10 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
assert(this_text == string_count); assert(this_text == string_count);
/* Create EOF record */ /* Create EOF record */
emr_eof.type = 0x0000000e; /* EMR_EOF */ out_le_u32(emr_eof.type, 0x0000000e); /* EMR_EOF */
emr_eof.size = 20; /* Assuming no palette entries */ out_le_u32(emr_eof.size, 20); /* Assuming no palette entries */
emr_eof.n_pal_entries = 0; out_le_u32(emr_eof.n_pal_entries, 0);
emr_eof.off_pal_entries = 0; out_le_u32(emr_eof.off_pal_entries, 0);
emr_eof.size_last = emr_eof.size; emr_eof.size_last = emr_eof.size;
bytecount += 20; bytecount += 20;
recordcount++; recordcount++;
@ -696,8 +698,8 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
} }
/* Put final counts in header */ /* Put final counts in header */
emr_header.emf_header.bytes = bytecount; out_le_u32(emr_header.emf_header.bytes, bytecount);
emr_header.emf_header.records = recordcount; out_le_u32(emr_header.emf_header.records, recordcount);
/* Send EMF data to file */ /* Send EMF data to file */
if (!fm_open(fmp, symbol, "wb")) { if (!fm_open(fmp, symbol, "wb")) {
@ -813,7 +815,7 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
} }
} }
fm_write(&text[i], sizeof(emr_exttextoutw_t), 1, fmp); 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); fm_write(this_string[i], text_bumped_lens[i], 1, fmp);
free(this_string[i]); free(this_string[i]);
} }

View file

@ -1,7 +1,7 @@
/* output.h - Common routines for raster/vector */ /* output.h - Common routines for raster/vector */
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2020-2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2020-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -77,6 +77,42 @@ INTERNAL FILE *out_fopen(const char filename[256], const char *mode);
INTERNAL FILE *out_win_fopen(const char *filename, const char *mode); INTERNAL FILE *out_win_fopen(const char *filename, const char *mode);
#endif #endif
/* Little-endian output */
#define out_le_u16(b, n) do { \
unsigned char *bp = (unsigned char *) &(b); \
uint16_t u16 = (uint16_t) (n); \
bp[0] = (unsigned char) (u16 & 0xFF); \
bp[1] = (unsigned char) ((u16 >> 8) & 0xFF); \
} while (0)
#define out_le_u32(b, n) do { \
unsigned char *bp = (unsigned char *) &(b); \
uint32_t u32 = (uint32_t) (n); \
bp[0] = (unsigned char) (u32 & 0xFF); \
bp[1] = (unsigned char) ((u32 >> 8) & 0xFF); \
bp[2] = (unsigned char) ((u32 >> 16) & 0xFF); \
bp[3] = (unsigned char) ((u32 >> 24) & 0xFF); \
} while (0)
#define out_le_i32(b, n) do { \
unsigned char *bp = (unsigned char *) &(b); \
int32_t i32 = (int32_t) (n); \
bp[0] = (unsigned char) (i32 & 0xFF); \
bp[1] = (unsigned char) ((i32 >> 8) & 0xFF); \
bp[2] = (unsigned char) ((i32 >> 16) & 0xFF); \
bp[3] = (unsigned char) ((i32 >> 24) & 0xFF); \
} while (0)
#define out_le_float(b, n) do { \
unsigned char *bp = (unsigned char *) &(b); \
float f = n; \
uint32_t *p_u32 = (uint32_t *) &(f); \
bp[0] = (unsigned char) (*p_u32 & 0xFF); \
bp[1] = (unsigned char) ((*p_u32 >> 8) & 0xFF); \
bp[2] = (unsigned char) ((*p_u32 >> 16) & 0xFF); \
bp[3] = (unsigned char) ((*p_u32 >> 24) & 0xFF); \
} while (0)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View file

@ -1,7 +1,7 @@
/* pcx.c - Handles output to ZSoft PCX file */ /* pcx.c - Handles output to ZSoft PCX file */
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -60,11 +60,11 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
header.version = 5; /* Version 3.0 */ header.version = 5; /* Version 3.0 */
header.encoding = 1; /* Run length encoding */ header.encoding = 1; /* Run length encoding */
header.bits_per_pixel = 8; /* TODO: 1-bit monochrome black/white */ header.bits_per_pixel = 8; /* TODO: 1-bit monochrome black/white */
header.window_xmin = 0; out_le_u16(header.window_xmin, 0);
header.window_ymin = 0; out_le_u16(header.window_ymin, 0);
header.window_xmax = symbol->bitmap_width - 1; out_le_u16(header.window_xmax, symbol->bitmap_width - 1);
header.window_ymax = symbol->bitmap_height - 1; out_le_u16(header.window_ymax, symbol->bitmap_height - 1);
header.horiz_dpi = symbol->dpmm ? (uint16_t) roundf(stripf(symbol->dpmm * 25.4f)) : 300; out_le_u16(header.horiz_dpi, symbol->dpmm ? roundf(stripf(symbol->dpmm * 25.4f)) : 300);
header.vert_dpi = header.horiz_dpi; header.vert_dpi = header.horiz_dpi;
for (i = 0; i < 48; i++) { for (i = 0; i < 48; i++) {
@ -74,11 +74,11 @@ INTERNAL int pcx_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
header.reserved = 0; header.reserved = 0;
header.number_of_planes = 3 + (fgalpha != 0xFF || bgalpha != 0xFF); /* TODO: 1-bit monochrome black/white */ header.number_of_planes = 3 + (fgalpha != 0xFF || bgalpha != 0xFF); /* TODO: 1-bit monochrome black/white */
header.bytes_per_line = bytes_per_line; out_le_u16(header.bytes_per_line, bytes_per_line);
header.palette_info = 1; /* Colour */ out_le_u16(header.palette_info, 1); /* Colour */
header.horiz_screen_size = 0; out_le_u16(header.horiz_screen_size, 0);
header.vert_screen_size = 0; out_le_u16(header.vert_screen_size, 0);
for (i = 0; i < 54; i++) { for (i = 0; i < 54; i++) {
header.filler[i] = 0x00; header.filler[i] = 0x00;

View file

@ -1,3 +1,5 @@
% backend/tests/README 2024-01-17
Zint backend test suite Zint backend test suite
----------------------- -----------------------

View file

@ -1,6 +1,6 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2021-2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2021-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -123,8 +123,8 @@ static void test_colour_get_rgb(const testCtx *const p_ctx) {
unsigned char red = 0, green = 0, blue = 0, alpha = 0, rgb_alpha = 0; unsigned char red = 0, green = 0, blue = 0, alpha = 0, rgb_alpha = 0;
int cyan, magenta, yellow, black; int cyan, magenta, yellow, black;
int have_alpha; int have_alpha;
char rgb[16]; char rgb[64];
char cmyk[16]; char cmyk[64];
if (testContinue(p_ctx, i)) continue; if (testContinue(p_ctx, i)) continue;

View file

@ -1,7 +1,7 @@
/* tif.c - Aldus Tagged Image File Format support */ /* tif.c - Aldus Tagged Image File Format support */
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2016-2023 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2016-2024 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -69,10 +69,6 @@ static void to_cmyk(const char *colour, unsigned char *cmyk) {
cmyk[4] = alpha; cmyk[4] = alpha;
} }
static int is_big_endian(void) {
return (*((const uint16_t *)"\x11\x22") == 0x1122);
}
/* TIFF Revision 6.0 https://www.adobe.io/content/dam/udp/en/open/standards/tiff/TIFF6.pdf */ /* TIFF Revision 6.0 https://www.adobe.io/content/dam/udp/en/open/standards/tiff/TIFF6.pdf */
INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf) { INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf) {
unsigned char fg[4], bg[4]; unsigned char fg[4], bg[4];
@ -113,6 +109,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
int offsets = 0; int offsets = 0;
int ifd_size; int ifd_size;
uint32_t temp32; uint32_t temp32;
uint16_t temp16;
(void) out_colour_get_rgb(symbol->fgcolour, &fg[0], &fg[1], &fg[2], &fg[3]); (void) out_colour_get_rgb(symbol->fgcolour, &fg[0], &fg[1], &fg[2], &fg[3]);
(void) out_colour_get_rgb(symbol->bgcolour, &bg[0], &bg[1], &bg[2], &bg[3]); (void) out_colour_get_rgb(symbol->bgcolour, &bg[0], &bg[1], &bg[2], &bg[3]);
@ -323,13 +320,9 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} }
/* Header */ /* Header */
if (is_big_endian()) { out_le_u16(header.byte_order, 0x4949); /* "II" little-endian */
header.byte_order = 0x4D4D; /* "MM" big-endian */ out_le_u16(header.identity, 42);
} else { out_le_u32(header.offset, free_memory);
header.byte_order = 0x4949; /* "II" little-endian */
}
header.identity = 42;
header.offset = (uint32_t) free_memory;
fm_write(&header, sizeof(tiff_header_t), 1, fmp); fm_write(&header, sizeof(tiff_header_t), 1, fmp);
total_bytes_put = sizeof(tiff_header_t); total_bytes_put = sizeof(tiff_header_t);
@ -422,29 +415,30 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
(void) fm_close(fmp, symbol); (void) fm_close(fmp, symbol);
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
} }
out_le_u32(temp32, temp32);
fm_write(&temp32, 4, 1, fmp); fm_write(&temp32, 4, 1, fmp);
fm_seek(fmp, file_pos, SEEK_SET); fm_seek(fmp, file_pos, SEEK_SET);
} }
/* Image File Directory */ /* Image File Directory */
tags[entries].tag = 0x0100; /* ImageWidth */ out_le_u16(tags[entries].tag, 0x0100); /* ImageWidth */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
tags[entries++].offset = symbol->bitmap_width; out_le_u32(tags[entries++].offset, symbol->bitmap_width);
tags[entries].tag = 0x0101; /* ImageLength - number of rows */ out_le_u16(tags[entries].tag, 0x0101); /* ImageLength - number of rows */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
tags[entries++].offset = symbol->bitmap_height; out_le_u32(tags[entries++].offset, symbol->bitmap_height);
if (samples_per_pixel != 1 || bits_per_sample != 1) { if (samples_per_pixel != 1 || bits_per_sample != 1) {
tags[entries].tag = 0x0102; /* BitsPerSample */ out_le_u16(tags[entries].tag, 0x0102); /* BitsPerSample */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = samples_per_pixel; out_le_u32(tags[entries].count, samples_per_pixel);
if (samples_per_pixel == 1) { if (samples_per_pixel == 1) {
tags[entries++].offset = bits_per_sample; out_le_u32(tags[entries++].offset, bits_per_sample);
} else if (samples_per_pixel == 2) { /* 2 SHORTS fit into LONG offset so packed into offset */ } else if (samples_per_pixel == 2) { /* 2 SHORTS fit into LONG offset so packed into offset */
tags[entries++].offset = (bits_per_sample << 16) | bits_per_sample; out_le_u32(tags[entries++].offset, (bits_per_sample << 16) | bits_per_sample);
} else { } else {
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = (uint32_t) free_memory; tags[entries++].offset = (uint32_t) free_memory;
@ -452,21 +446,21 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} }
} }
tags[entries].tag = 0x0103; /* Compression */ out_le_u16(tags[entries].tag, 0x0103); /* Compression */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
tags[entries++].offset = compression; out_le_u32(tags[entries++].offset, compression);
tags[entries].tag = 0x0106; /* PhotometricInterpretation */ out_le_u16(tags[entries].tag, 0x0106); /* PhotometricInterpretation */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
tags[entries++].offset = pmi; out_le_u32(tags[entries++].offset, pmi);
tags[entries].tag = 0x0111; /* StripOffsets */ out_le_u16(tags[entries].tag, 0x0111); /* StripOffsets */
tags[entries].type = 4; /* LONG */ out_le_u16(tags[entries].type, 4); /* LONG */
tags[entries].count = strip_count; out_le_u32(tags[entries].count, strip_count);
if (strip_count == 1) { if (strip_count == 1) {
tags[entries++].offset = strip_offset[0]; out_le_u32(tags[entries++].offset, strip_offset[0]);
} else { } else {
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = (uint32_t) free_memory; tags[entries++].offset = (uint32_t) free_memory;
@ -474,78 +468,81 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
} }
if (samples_per_pixel > 1) { if (samples_per_pixel > 1) {
tags[entries].tag = 0x0115; /* SamplesPerPixel */ out_le_u16(tags[entries].tag, 0x0115); /* SamplesPerPixel */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
tags[entries++].offset = samples_per_pixel; out_le_u32(tags[entries++].offset, samples_per_pixel);
} }
tags[entries].tag = 0x0116; /* RowsPerStrip */ out_le_u16(tags[entries].tag, 0x0116); /* RowsPerStrip */
tags[entries].type = 4; /* LONG */ out_le_u16(tags[entries].type, 4); /* LONG */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
tags[entries++].offset = rows_per_strip; out_le_u32(tags[entries++].offset, rows_per_strip);
tags[entries].tag = 0x0117; /* StripByteCounts */ out_le_u16(tags[entries].tag, 0x0117); /* StripByteCounts */
tags[entries].type = 4; /* LONG */ out_le_u16(tags[entries].type, 4); /* LONG */
tags[entries].count = strip_count; out_le_u32(tags[entries].count, strip_count);
if (strip_count == 1) { if (strip_count == 1) {
tags[entries++].offset = strip_bytes[0]; out_le_u32(tags[entries++].offset, strip_bytes[0]);
} else { } else {
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = (uint32_t) free_memory; tags[entries++].offset = (uint32_t) free_memory;
free_memory += strip_count * 4; free_memory += strip_count * 4;
} }
tags[entries].tag = 0x011a; /* XResolution */ out_le_u16(tags[entries].tag, 0x011a); /* XResolution */
tags[entries].type = 5; /* RATIONAL */ out_le_u16(tags[entries].type, 5); /* RATIONAL */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = (uint32_t) free_memory; tags[entries++].offset = (uint32_t) free_memory;
free_memory += 8; free_memory += 8;
tags[entries].tag = 0x011b; /* YResolution */ out_le_u16(tags[entries].tag, 0x011b); /* YResolution */
tags[entries].type = 5; /* RATIONAL */ out_le_u16(tags[entries].type, 5); /* RATIONAL */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = (uint32_t) free_memory; tags[entries++].offset = (uint32_t) free_memory;
free_memory += 8; free_memory += 8;
tags[entries].tag = 0x0128; /* ResolutionUnit */ out_le_u16(tags[entries].tag, 0x0128); /* ResolutionUnit */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
if (symbol->dpmm) { if (symbol->dpmm) {
tags[entries++].offset = 3; /* Centimetres */ out_le_u32(tags[entries++].offset, 3); /* Centimetres */
} else { } else {
tags[entries++].offset = 2; /* Inches */ out_le_u32(tags[entries++].offset, 2); /* Inches */
} }
if (color_map_size) { if (color_map_size) {
tags[entries].tag = 0x0140; /* ColorMap */ out_le_u16(tags[entries].tag, 0x0140); /* ColorMap */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = color_map_size * 3; out_le_u32(tags[entries].count, color_map_size * 3);
update_offsets[offsets++] = entries; update_offsets[offsets++] = entries;
tags[entries++].offset = (uint32_t) free_memory; tags[entries++].offset = (uint32_t) free_memory;
/* free_memory += color_map_size * 3 * 2; Unnecessary as long as last use */ /* free_memory += color_map_size * 3 * 2; Unnecessary as long as last use */
} }
if (extra_samples) { if (extra_samples) {
tags[entries].tag = 0x0152; /* ExtraSamples */ out_le_u16(tags[entries].tag, 0x0152); /* ExtraSamples */
tags[entries].type = 3; /* SHORT */ out_le_u16(tags[entries].type, 3); /* SHORT */
tags[entries].count = 1; out_le_u32(tags[entries].count, 1);
tags[entries++].offset = extra_samples; out_le_u32(tags[entries++].offset, extra_samples);
} }
ifd_size = sizeof(entries) + sizeof(tiff_tag_t) * entries + sizeof(offset); ifd_size = sizeof(entries) + sizeof(tiff_tag_t) * entries + sizeof(offset);
for (i = 0; i < offsets; i++) { for (i = 0; i < offsets; i++) {
tags[update_offsets[i]].offset += ifd_size; out_le_u32(tags[update_offsets[i]].offset, tags[update_offsets[i]].offset + ifd_size);
} }
fm_write(&entries, sizeof(entries), 1, fmp); out_le_u16(temp16, entries);
fm_write(&temp16, sizeof(entries), 1, fmp);
fm_write(&tags, sizeof(tiff_tag_t), entries, fmp); fm_write(&tags, sizeof(tiff_tag_t), entries, fmp);
out_le_u32(offset, offset);
fm_write(&offset, sizeof(offset), 1, fmp); fm_write(&offset, sizeof(offset), 1, fmp);
total_bytes_put += ifd_size; total_bytes_put += ifd_size;
if (samples_per_pixel > 2) { if (samples_per_pixel > 2) {
out_le_u16(bits_per_sample, bits_per_sample);
for (i = 0; i < samples_per_pixel; i++) { for (i = 0; i < samples_per_pixel; i++) {
fm_write(&bits_per_sample, sizeof(bits_per_sample), 1, fmp); fm_write(&bits_per_sample, sizeof(bits_per_sample), 1, fmp);
} }
@ -555,27 +552,29 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
if (strip_count != 1) { if (strip_count != 1) {
/* Strip offsets */ /* Strip offsets */
for (i = 0; i < strip_count; i++) { for (i = 0; i < strip_count; i++) {
fm_write(&strip_offset[i], 4, 1, fmp); out_le_u32(temp32, strip_offset[i]);
fm_write(&temp32, 4, 1, fmp);
} }
/* Strip byte lengths */ /* Strip byte lengths */
for (i = 0; i < strip_count; i++) { for (i = 0; i < strip_count; i++) {
fm_write(&strip_bytes[i], 4, 1, fmp); out_le_u32(temp32, strip_bytes[i]);
fm_write(&temp32, 4, 1, fmp);
} }
total_bytes_put += strip_count * 8; total_bytes_put += strip_count * 8;
} }
/* XResolution */ /* XResolution */
temp32 = symbol->dpmm ? symbol->dpmm : 72; out_le_u32(temp32, symbol->dpmm ? symbol->dpmm : 72);
fm_write(&temp32, 4, 1, fmp); fm_write(&temp32, 4, 1, fmp);
temp32 = symbol->dpmm ? 10 /*cm*/ : 1; out_le_u32(temp32, symbol->dpmm ? 10 /*cm*/ : 1);
fm_write(&temp32, 4, 1, fmp); fm_write(&temp32, 4, 1, fmp);
total_bytes_put += 8; total_bytes_put += 8;
/* YResolution */ /* YResolution */
temp32 = symbol->dpmm ? symbol->dpmm : 72; out_le_u32(temp32, symbol->dpmm ? symbol->dpmm : 72);
fm_write(&temp32, 4, 1, fmp); fm_write(&temp32, 4, 1, fmp);
temp32 = symbol->dpmm ? 10 /*cm*/ : 1; out_le_u32(temp32, symbol->dpmm ? 10 /*cm*/ : 1);
fm_write(&temp32, 4, 1, fmp); fm_write(&temp32, 4, 1, fmp);
total_bytes_put += 8; total_bytes_put += 8;

View file

@ -1,3 +1,5 @@
% docs/README 2014-01-17
For generation of "docs/manual.pdf" and "docs/manual.txt" from "manual.pmd" using a recent version of pandoc For generation of "docs/manual.pdf" and "docs/manual.txt" from "manual.pmd" using a recent version of pandoc
On Ubuntu/Debian (tested on Ubuntu 22.04) On Ubuntu/Debian (tested on Ubuntu 22.04)

View file

@ -1,3 +1,5 @@
% frontend/tests/README 2024-01-12
Zint frontend test suite Zint frontend test suite
------------------------ ------------------------

View file

@ -1,3 +1,5 @@
% win32/README 2024-01-17
Visual Studio 2022 Visual Studio 2022
------------------ ------------------