Plot vector graphics using linked list structure

Simplifies the implementation of individual vector graphic file formats
This commit is contained in:
Robin Stuart 2018-06-10 09:16:18 +01:00
parent dddf2934fc
commit 30fcd7986c
7 changed files with 1255 additions and 2340 deletions

View File

@ -8,7 +8,7 @@ set(zint_COMMON_SRCS common.c library.c render.c large.c reedsol.c gs1.c eci.c)
set(zint_ONEDIM_SRCS 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)
set(zint_OUTPUT_SRCS render.c ps.c svg.c emf.c bmp.c pcx.c gif.c png.c tif.c raster.c)
set(zint_OUTPUT_SRCS vector.c render.c ps.c svg.c emf.c bmp.c pcx.c gif.c png.c tif.c raster.c)
set(zint_SRCS ${zint_OUTPUT_SRCS} ${zint_COMMON_SRCS} ${zint_ONEDIM_SRCS} ${zint_POSTAL_SRCS} ${zint_TWODIM_SRCS})
if(PNG_FOUND)

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/* library.c - external functions of libzint
libzint - the open source barcode library
Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
Copyright (C) 2009-2018 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -78,6 +78,7 @@ struct zint_symbol *ZBarcode_Create() {
}
extern void render_free(struct zint_symbol *symbol); /* Free render structures */
extern void vector_free(struct zint_symbol *symbol); /* Free vector structures */
void ZBarcode_Clear(struct zint_symbol *symbol) {
int i, j;
@ -100,6 +101,7 @@ void ZBarcode_Clear(struct zint_symbol *symbol) {
// If there is a rendered version, ensure its memory is released
render_free(symbol);
vector_free(symbol);
}
void ZBarcode_Delete(struct zint_symbol *symbol) {
@ -108,6 +110,7 @@ void ZBarcode_Delete(struct zint_symbol *symbol) {
// If there is a rendered version, ensure its memory is released
render_free(symbol);
vector_free(symbol);
free(symbol);
}
@ -179,8 +182,9 @@ extern int mailmark(struct zint_symbol *symbol, const unsigned char source[], co
extern int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */
extern int render_plot(struct zint_symbol *symbol, float width, float height); /* Plot to gLabels */
extern int ps_plot(struct zint_symbol *symbol); /* Plot to EPS */
extern int svg_plot(struct zint_symbol *symbol); /* Plot to SVG */
extern int vector_plot(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to new vector format */
//extern int ps_plot(struct zint_symbol *symbol); /* Plot to EPS */
//extern int svg_plot(struct zint_symbol *symbol); /* Plot to SVG */
extern int emf_plot(struct zint_symbol *symbol); /* Plot to Metafile */
void error_tag(char error_string[], int error_number) {
@ -1247,13 +1251,13 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
error_number = dump_plot(symbol);
} else
if (!(strcmp(output, "EPS"))) {
error_number = ps_plot(symbol);
error_number = vector_plot(symbol, rotate_angle, OUT_EPS_FILE);
} else
if (!(strcmp(output, "SVG"))) {
error_number = svg_plot(symbol);
error_number = vector_plot(symbol, rotate_angle, OUT_SVG_FILE);
} else
if (!(strcmp(output, "EMF"))) {
error_number = emf_plot(symbol);
error_number = vector_plot(symbol, rotate_angle, OUT_EMF_FILE);
} else {
strcpy(symbol->errtxt, "225: Unknown output format");
error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);

View File

@ -2,7 +2,7 @@
/*
libzint - the open source barcode library
Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
Copyright (C) 2009-2018 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -37,68 +37,21 @@
#include <math.h>
#include "common.h"
#define SSET "0123456789ABCDEF"
int ps_plot(struct zint_symbol *symbol) {
int i, block_width, latch, r;
float textpos, large_bar_height, preset_height, row_height;
FILE *feps;
int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
float red_ink, green_ink, blue_ink, red_paper, green_paper, blue_paper;
float cyan_ink, magenta_ink, yellow_ink, black_ink;
float cyan_paper, magenta_paper, yellow_paper, black_paper;
int error_number = 0;
int textoffset, xoffset, yoffset, textdone, main_width;
char textpart[10], addon[6];
int large_bar_count, comp_offset;
float addon_text_posn;
float scaler = symbol->scale;
float default_text_posn;
float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy;
float radius;
struct zint_vector_rect *rect;
struct zint_vector_hexagon *hex;
struct zint_vector_circle *circle;
struct zint_vector_string *string;
const char *locale = NULL;
float fontsize = symbol->fontsize * scaler;
#ifndef _MSC_VER
unsigned char local_text[ustrlen(symbol->text) + 1];
#else
unsigned char* local_text = (unsigned char*) malloc(ustrlen(symbol->text) + 1);
#endif
row_height = 0;
textdone = 0;
main_width = symbol->width;
strcpy(addon, "");
comp_offset = 0;
addon_text_posn = 0.0;
if (symbol->show_hrt != 0) {
/* Copy text from symbol */
ustrcpy(local_text, symbol->text);
} else {
/* No text needed */
switch (symbol->symbology) {
case BARCODE_EANX:
case BARCODE_EANX_CC:
case BARCODE_ISBNX:
case BARCODE_UPCA:
case BARCODE_UPCE:
case BARCODE_UPCA_CC:
case BARCODE_UPCE_CC:
/* For these symbols use dummy text to ensure formatting is done
* properly even if no text is required */
for (i = 0; i < ustrlen(symbol->text); i++) {
if (symbol->text[i] == '+') {
local_text[i] = '+';
} else {
local_text[i] = ' ';
}
local_text[ustrlen(symbol->text)] = '\0';
}
break;
default:
/* For everything else, just remove the text */
local_text[0] = '\0';
break;
}
}
if (symbol->output_options & BARCODE_STDOUT) {
feps = stdout;
@ -113,44 +66,6 @@ int ps_plot(struct zint_symbol *symbol) {
return ZINT_ERROR_FILE_ACCESS;
}
/* sort out colour options */
to_upper((unsigned char*) symbol->fgcolour);
to_upper((unsigned char*) symbol->bgcolour);
if (strlen(symbol->fgcolour) != 6) {
strcpy(symbol->errtxt, "646: Malformed foreground colour target");
fclose(feps);
#ifdef _MSC_VER
free(local_text);
#endif
return ZINT_ERROR_INVALID_OPTION;
}
if (strlen(symbol->bgcolour) != 6) {
strcpy(symbol->errtxt, "647: Malformed background colour target");
fclose(feps);
#ifdef _MSC_VER
free(local_text);
#endif
return ZINT_ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*) symbol->fgcolour, strlen(symbol->fgcolour));
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "648: Malformed foreground colour target");
fclose(feps);
#ifdef _MSC_VER
free(local_text);
#endif
return ZINT_ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*) symbol->bgcolour, strlen(symbol->bgcolour));
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "649: Malformed background colour target");
fclose(feps);
#ifdef _MSC_VER
free(local_text);
#endif
return ZINT_ERROR_INVALID_OPTION;
}
locale = setlocale(LC_ALL, "C");
fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
@ -213,102 +128,16 @@ int ps_plot(struct zint_symbol *symbol) {
yellow_paper = 0.0;
}
if (symbol->height == 0) {
symbol->height = 50;
}
large_bar_count = 0;
preset_height = 0.0;
for (i = 0; i < symbol->rows; i++) {
preset_height += symbol->row_height[i];
if (symbol->row_height[i] == 0) {
large_bar_count++;
}
}
large_bar_height = (symbol->height - preset_height) / large_bar_count;
if (large_bar_count == 0) {
symbol->height = preset_height;
}
while (!(module_is_set(symbol, symbol->rows - 1, comp_offset))) {
comp_offset++;
}
/* Certain symbols need whitespace otherwise characters get chopped off the sides */
if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC))
|| (symbol->symbology == BARCODE_ISBNX)) {
switch (ustrlen(local_text)) {
case 13: /* EAN 13 */
case 16:
case 19:
if (symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
}
main_width = 96 + comp_offset;
break;
default:
main_width = 68 + comp_offset;
}
}
if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
if (symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_width = 96 + comp_offset;
}
}
if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
if (symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_width = 51 + comp_offset;
}
}
latch = 0;
r = 0;
/* Isolate add-on text */
if (is_extendable(symbol->symbology)) {
for (i = 0; i < ustrlen(local_text); i++) {
if (latch == 1) {
addon[r] = local_text[i];
r++;
}
if (local_text[i] == '+') {
latch = 1;
}
}
}
addon[r] = '\0';
if (ustrlen(local_text) != 0) {
textoffset = 9;
} else {
textoffset = 0;
}
xoffset = symbol->border_width + symbol->whitespace_width;
yoffset = symbol->border_width;
/* Start writing the header */
fprintf(feps, "%%!PS-Adobe-3.0 EPSF-3.0\n");
fprintf(feps, "%%%%Creator: Zint %d.%d.%d\n", ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE);
if ((ustrlen(local_text) != 0) && (symbol->show_hrt != 0)) {
fprintf(feps, "%%%%Title: %s\n", local_text);
} else {
fprintf(feps, "%%%%Title: Zint Generated Symbol\n");
}
fprintf(feps, "%%%%Pages: 0\n");
if (symbol->symbology != BARCODE_MAXICODE) {
fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", (int) ceil((symbol->width + xoffset + xoffset) * scaler), (int) ceil((symbol->height + textoffset + yoffset + yoffset) * scaler));
} else {
fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", (int) ceil((74.0F + xoffset + xoffset) * scaler), (int) ceil((72.0F + yoffset + yoffset) * scaler));
}
fprintf(feps, "%%%%BoundingBox: 0 0 %d %d\n", (int) ceil(symbol->vector->width), (int) ceil(symbol->vector->height));
fprintf(feps, "%%%%EndComments\n");
/* Definitions */
fprintf(feps, "/TL { setlinewidth moveto lineto stroke } bind def\n");
fprintf(feps, "/TC { moveto 0 360 arc 360 0 arcn fill } bind def\n");
fprintf(feps, "/TD { newpath 0 360 arc fill } bind def\n");
fprintf(feps, "/TH { 0 setlinewidth moveto lineto lineto lineto lineto lineto closepath fill } bind def\n");
fprintf(feps, "/TB { 2 copy } bind def\n");
@ -319,124 +148,11 @@ int ps_plot(struct zint_symbol *symbol) {
/* Now the actual representation */
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_paper, green_paper, blue_paper);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_paper, magenta_paper, yellow_paper, black_paper);
}
fprintf(feps, "%.2f 0.00 TB 0.00 %.2f TR\n", (symbol->height + textoffset + yoffset + yoffset) * scaler, (symbol->width + xoffset + xoffset) * scaler);
if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
default_text_posn = 0.5 * scaler;
} else {
default_text_posn = (symbol->border_width + 0.5) * scaler;
}
if (symbol->symbology == BARCODE_MAXICODE) {
/* Maxicode uses hexagons */
float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, mx, my;
textoffset = 0.0;
if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, 0.0, (74.0 + xoffset + xoffset) * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + 72.0 + symbol->border_width) * scaler, 0.0, (74.0 + xoffset + xoffset) * scaler);
}
if ((symbol->output_options & BARCODE_BOX) != 0) {
/* side bars */
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (72.0 + (2 * symbol->border_width)) * scaler, textoffset * scaler, 0.0, symbol->border_width * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (72.0 + (2 * symbol->border_width)) * scaler, textoffset * scaler, (74.0 + xoffset + xoffset - symbol->border_width) * scaler, symbol->border_width * scaler);
}
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 10.85 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 8.97 * scaler, (44.73 + xoffset) * scaler, (35.60 + yoffset) * scaler);
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 7.10 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 5.22 * scaler, (40.98 + xoffset) * scaler, (35.60 + yoffset) * scaler);
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TC\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 3.31 * scaler, (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 1.43 * scaler, (37.19 + xoffset) * scaler, (35.60 + yoffset) * scaler);
for (r = 0; r < symbol->rows; r++) {
for (i = 0; i < symbol->width; i++) {
if (module_is_set(symbol, r, i)) {
/* Dump a hexagon */
my = ((symbol->rows - r - 1)) * 2.135 + 1.43;
ay = my + 1.0 + yoffset;
by = my + 0.5 + yoffset;
cy = my - 0.5 + yoffset;
dy = my - 1.0 + yoffset;
ey = my - 0.5 + yoffset;
fy = my + 0.5 + yoffset;
mx = 2.46 * i + 1.23 + ((r & 1) ? 1.23 : 0);
ax = mx + xoffset;
bx = mx + 0.86 + xoffset;
cx = mx + 0.86 + xoffset;
dx = mx + xoffset;
ex = mx - 0.86 + xoffset;
fx = mx - 0.86 + xoffset;
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TH\n", ax * scaler, ay * scaler, bx * scaler, by * scaler, cx * scaler, cy * scaler, dx * scaler, dy * scaler, ex * scaler, ey * scaler, fx * scaler, fy * scaler);
}
}
}
}
if (symbol->symbology != BARCODE_MAXICODE) {
/* everything else uses rectangles (or squares) */
/* Works from the bottom of the symbol up */
int addon_latch = 0;
for (r = 0; r < symbol->rows; r++) {
float row_posn;
int this_row = symbol->rows - r - 1; /* invert r otherwise plots upside down */
if (symbol->row_height[this_row] == 0) {
row_height = large_bar_height;
} else {
row_height = symbol->row_height[this_row];
}
row_posn = 0;
for (i = 0; i < r; i++) {
if (symbol->row_height[symbol->rows - i - 1] == 0) {
row_posn += large_bar_height;
} else {
row_posn += symbol->row_height[symbol->rows - i - 1];
}
}
row_posn += (textoffset + yoffset);
if ((symbol->output_options & BARCODE_DOTTY_MODE) != 0) {
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
/* Use dots instead of squares */
for (i = 0; i < symbol->width; i++) {
if (module_is_set(symbol, this_row, i)) {
fprintf(feps, "%.2f %.2f %.2f TD\n", ((i + xoffset) * scaler) + (scaler / 2.0), (row_posn * scaler) + (scaler / 2.0), (symbol->dot_size / 2.0) * scaler);
}
}
} else {
/* Normal mode, with rectangles */
fprintf(feps, "%.2f 0.00 TB 0.00 %.2f TR\n", symbol->vector->height, symbol->vector->width);
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
@ -445,518 +161,73 @@ int ps_plot(struct zint_symbol *symbol) {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f ", row_height * scaler, row_posn * scaler);
i = 0;
if (module_is_set(symbol, this_row, 0)) {
latch = 1;
} else {
latch = 0;
// Rectangles
rect = symbol->vector->rectangles;
while (rect) {
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", rect->height, (symbol->vector->height - rect->y) - rect->height, rect->x, rect->width);
rect = rect->next;
}
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
if ((addon_latch == 0) && (r == 0) && (i > main_width)) {
fprintf(feps, "TE\n");
// Hexagons
hex = symbol->vector->hexagons;
while (hex) {
radius = hex->diameter / 2.0;
ay = (symbol->vector->height - hex->y) + (1.0 * radius);
by = (symbol->vector->height - hex->y) + (0.5 * radius);
cy = (symbol->vector->height - hex->y) - (0.5 * radius);
dy = (symbol->vector->height - hex->y) - (1.0 * radius);
ey = (symbol->vector->height - hex->y) - (0.5 * radius);
fy = (symbol->vector->height - hex->y) + (0.5 * radius);
ax = hex->x;
bx = hex->x + (0.86 * radius);
cx = hex->x + (0.86 * radius);
dx = hex->x;
ex = hex->x - (0.86 * radius);
fx = hex->x - (0.86 * radius);
fprintf(feps, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f TH\n", ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy);
hex = hex->next;
}
// Circles
circle = symbol->vector->circles;
while (circle) {
if (circle->colour) {
// A 'white' circle
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_paper, green_paper, blue_paper);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_paper, magenta_paper, yellow_paper, black_paper);
}
fprintf(feps, "%.2f %.2f %.2f TD\n", circle->x, (symbol->vector->height - circle->y), circle->diameter / 2.0);
if (circle->next) {
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f ", (row_height - 5.0) * scaler, (row_posn - 5.0) * scaler);
addon_text_posn = row_posn + row_height - 8.0;
addon_latch = 1;
}
if (latch == 1) {
/* a bar */
fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset) * scaler, block_width * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
// A 'black' circle
fprintf(feps, "%.2f %.2f %.2f TD\n", circle->x, (symbol->vector->height - circle->y), circle->diameter / 2.0);
}
i += block_width;
} while (i < symbol->width);
}
}
}
/* That's done the actual data area, everything else is human-friendly */
xoffset += comp_offset;
if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) ||
(symbol->symbology == BARCODE_ISBNX)) {
/* guard bar extensions and text formatting for EAN8 and EAN13 */
switch (ustrlen(local_text)) {
case 8: /* EAN-8 */
case 11:
case 14:
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (32 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (34 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (64 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (66 + xoffset) * scaler, 1 * scaler);
for (i = 0; i < 4; i++) {
textpart[i] = local_text[i];
}
textpart[4] = '\0';
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = 17;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for (i = 0; i < 4; i++) {
textpart[i] = local_text[i + 4];
}
textpart[4] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = 50;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textdone = 1;
switch (strlen(addon)) {
case 2:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = xoffset + 86;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
case 5:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = xoffset + 100;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
circle = circle->next;
}
break;
case 13: /* EAN 13 */
case 16:
case 19:
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (92 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (94 + xoffset) * scaler, 1 * scaler);
textpart[0] = local_text[0];
textpart[1] = '\0';
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
// Text
string = symbol->vector->strings;
while (string) {
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = -7;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "%.2f scalefont setfont\n", string->fsize);
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", string->x, (symbol->vector->height - string->y));
fprintf(feps, " (%s) stringwidth\n", string->text);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, " (%s) show\n", string->text);
fprintf(feps, "setmatrix\n");
for (i = 0; i < 6; i++) {
textpart[i] = local_text[i + 1];
}
textpart[6] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = 24;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for (i = 0; i < 6; i++) {
textpart[i] = local_text[i + 7];
}
textpart[6] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = 71;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textdone = 1;
switch (strlen(addon)) {
case 2:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = xoffset + 114;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
case 5:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = xoffset + 128;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
}
break;
}
string = string->next;
}
if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
/* guard bar extensions and text formatting for UPCA */
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
latch = 1;
i = 0 + comp_offset;
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
if (latch == 1) {
/* a bar */
fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset - comp_offset) * scaler, block_width * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < 11 + comp_offset);
fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
latch = 1;
i = 85 + comp_offset;
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
if (latch == 1) {
/* a bar */
fprintf(feps, "TB %.2f %.2f TR\n", (i + xoffset - comp_offset) * scaler, block_width * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < 96 + comp_offset);
textpart[0] = local_text[0];
textpart[1] = '\0';
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", fontsize);
textpos = -5;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for (i = 0; i < 5; i++) {
textpart[i] = local_text[i + 1];
}
textpart[5] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = 27;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for (i = 0; i < 5; i++) {
textpart[i] = local_text[i + 6];
}
textpart[6] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = 68;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textpart[0] = local_text[11];
textpart[1] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", fontsize);
textpos = 100;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textdone = 1;
switch (strlen(addon)) {
case 2:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = xoffset + 116;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
case 5:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = xoffset + 130;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
}
}
if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
/* guard bar extensions and text formatting for UPCE */
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f ", 5.0 * scaler, (4.0 + yoffset) * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (0 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (2 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (46 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (48 + xoffset) * scaler, 1 * scaler);
fprintf(feps, "TB %.2f %.2f TR\n", (50 + xoffset) * scaler, 1 * scaler);
textpart[0] = local_text[0];
textpart[1] = '\0';
fprintf(feps, "TE\n");
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", fontsize);
textpos = -5;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
for (i = 0; i < 6; i++) {
textpart[i] = local_text[i + 1];
}
textpart[6] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = 24;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textpart[0] = local_text[7];
textpart[1] = '\0';
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", fontsize);
textpos = 55;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", textpart);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", textpart);
fprintf(feps, "setmatrix\n");
textdone = 1;
switch (strlen(addon)) {
case 2:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = xoffset + 70;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
case 5:
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", (11.0 / 8.0) * fontsize);
textpos = xoffset + 84;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", textpos * scaler, addon_text_posn * scaler);
fprintf(feps, " (%s) stringwidth\n", addon);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", addon);
fprintf(feps, "setmatrix\n");
break;
}
}
xoffset -= comp_offset;
switch (symbol->symbology) {
case BARCODE_MAXICODE:
/* Do nothing! (It's already been done) */
break;
default:
if (symbol->output_options & BARCODE_BIND) {
if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
/* row binding */
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
if (symbol->symbology != BARCODE_CODABLOCKF) {
for (r = 1; r < symbol->rows; r++) {
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", 2.0 * scaler, ((r * row_height) + textoffset + yoffset - 1) * scaler, xoffset * scaler, symbol->width * scaler);
}
} else {
for (r = 1; r < symbol->rows; r++) {
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", 2.0 * scaler, ((r * row_height) + textoffset + yoffset - 1) * scaler, (xoffset + 11) * scaler, (symbol->width - 25) * scaler);
}
}
}
}
if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
if (symbol->symbology != BARCODE_CODABLOCKF) {
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, 0.0, (symbol->width + xoffset + xoffset) * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + symbol->height + symbol->border_width) * scaler, 0.0, (symbol->width + xoffset + xoffset) * scaler);
} else {
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, textoffset * scaler, xoffset * scaler, symbol->width * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", symbol->border_width * scaler, (textoffset + symbol->height + symbol->border_width) * scaler, xoffset * scaler, symbol->width * scaler);
}
}
if (symbol->output_options & BARCODE_BOX) {
/* side bars */
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (symbol->height + (2 * symbol->border_width)) * scaler, textoffset * scaler, 0.0, symbol->border_width * scaler);
fprintf(feps, "%.2f %.2f TB %.2f %.2f TR\n", (symbol->height + (2 * symbol->border_width)) * scaler, textoffset * scaler, (symbol->width + xoffset + xoffset - symbol->border_width) * scaler, symbol->border_width * scaler);
}
break;
}
/* Put the human readable text at the bottom */
if ((textdone == 0) && (ustrlen(local_text))) {
fprintf(feps, "TE\n");
if ((symbol->output_options & CMYK_COLOUR) == 0) {
fprintf(feps, "%.2f %.2f %.2f setrgbcolor\n", red_ink, green_ink, blue_ink);
} else {
fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink);
}
fprintf(feps, "matrix currentmatrix\n");
fprintf(feps, "/Helvetica findfont\n");
fprintf(feps, "%.2f scalefont setfont\n", fontsize);
textpos = symbol->width / 2.0;
fprintf(feps, " 0 0 moveto %.2f %.2f translate 0.00 rotate 0 0 moveto\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(feps, " (%s) stringwidth\n", local_text);
fprintf(feps, "pop\n");
fprintf(feps, "-2 div 0 rmoveto\n");
fprintf(feps, " (%s) show\n", local_text);
fprintf(feps, "setmatrix\n");
}
fprintf(feps, "\nshowpage\n");
if (symbol->output_options & BARCODE_STDOUT) {
@ -968,11 +239,5 @@ int ps_plot(struct zint_symbol *symbol) {
if (locale)
setlocale(LC_ALL, locale);
#ifdef _MSC_VER
free(local_text);
#endif
return error_number;
}

View File

@ -2,7 +2,7 @@
/*
libzint - the open source barcode library
Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
Copyright (C) 2009-2018 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -41,64 +41,17 @@
#include "common.h"
#define SSET "0123456789ABCDEF"
int svg_plot(struct zint_symbol *symbol) {
int i, block_width, latch, r;
float textpos, large_bar_height, preset_height, row_height, row_posn = 0.0;
FILE *fsvg;
int error_number = 0;
int textoffset, xoffset, yoffset, textdone, main_width;
char textpart[10], addon[6];
int large_bar_count, comp_offset;
float addon_text_posn;
float scaler = symbol->scale;
float default_text_posn;
const char *locale = NULL;
float fontsize = symbol->fontsize * scaler;
#ifndef _MSC_VER
unsigned char local_text[ustrlen(symbol->text) + 1];
#else
unsigned char* local_text = (unsigned char*) _alloca(ustrlen(symbol->text) + 1);
#endif
float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy;
float radius;
row_height = 0;
textdone = 0;
main_width = symbol->width;
strcpy(addon, "");
comp_offset = 0;
addon_text_posn = 0.0;
if (symbol->show_hrt != 0) {
/* Copy text from symbol */
ustrcpy(local_text, symbol->text);
} else {
/* No text needed */
switch (symbol->symbology) {
case BARCODE_EANX:
case BARCODE_EANX_CC:
case BARCODE_ISBNX:
case BARCODE_UPCA:
case BARCODE_UPCE:
case BARCODE_UPCA_CC:
case BARCODE_UPCE_CC:
/* For these symbols use dummy text to ensure formatting is done
* properly even if no text is required */
for (i = 0; i < ustrlen(symbol->text); i++) {
if (symbol->text[i] == '+') {
local_text[i] = '+';
} else {
local_text[i] = ' ';
}
local_text[ustrlen(symbol->text)] = '\0';
}
break;
default:
/* For everything else, just remove the text */
local_text[0] = '\0';
break;
}
}
struct zint_vector_rect *rect;
struct zint_vector_hexagon *hex;
struct zint_vector_circle *circle;
struct zint_vector_string *string;
if (symbol->output_options & BARCODE_STDOUT) {
fsvg = stdout;
@ -110,560 +63,65 @@ int svg_plot(struct zint_symbol *symbol) {
return ZINT_ERROR_FILE_ACCESS;
}
/* sort out colour options */
to_upper((unsigned char*) symbol->fgcolour);
to_upper((unsigned char*) symbol->bgcolour);
if (strlen(symbol->fgcolour) != 6) {
strcpy(symbol->errtxt, "661: Malformed foreground colour target");
fclose(fsvg);
return ZINT_ERROR_INVALID_OPTION;
}
if (strlen(symbol->bgcolour) != 6) {
strcpy(symbol->errtxt, "662: Malformed background colour target");
fclose(fsvg);
return ZINT_ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*) symbol->fgcolour, strlen(symbol->fgcolour));
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "663: Malformed foreground colour target");
fclose(fsvg);
return ZINT_ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*) symbol->bgcolour, strlen(symbol->bgcolour));
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "664: Malformed background colour target");
fclose(fsvg);
return ZINT_ERROR_INVALID_OPTION;
}
locale = setlocale(LC_ALL, "C");
if (symbol->height == 0) {
symbol->height = 50;
}
large_bar_count = 0;
preset_height = 0.0;
for (i = 0; i < symbol->rows; i++) {
preset_height += symbol->row_height[i];
if (symbol->row_height[i] == 0) {
large_bar_count++;
}
}
large_bar_height = (symbol->height - preset_height) / large_bar_count;
if (large_bar_count == 0) {
symbol->height = preset_height;
}
while (!(module_is_set(symbol, symbol->rows - 1, comp_offset))) {
comp_offset++;
}
/* Certain symbols need whitespace otherwise characters get chopped off the sides */
if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC))
|| (symbol->symbology == BARCODE_ISBNX)) {
switch (ustrlen(local_text)) {
case 13: /* EAN 13 */
case 16:
case 19:
if (symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
}
main_width = 96 + comp_offset;
break;
default:
main_width = 68 + comp_offset;
}
}
if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
if (symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_width = 96 + comp_offset;
}
}
if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
if (symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_width = 51 + comp_offset;
}
}
latch = 0;
r = 0;
/* Isolate add-on text */
if (is_extendable(symbol->symbology)) {
for (i = 0; i < ustrlen(local_text); i++) {
if (latch == 1) {
addon[r] = local_text[i];
r++;
}
if (local_text[i] == '+') {
latch = 1;
}
}
}
addon[r] = '\0';
/* Don't include control characters in output text */
for(i = 0; i < ustrlen(local_text); i++) {
if (local_text[i] < ' ') {
local_text[i] = ' ';
}
}
if (ustrlen(local_text) != 0) {
textoffset = 9;
} else {
textoffset = 0;
}
xoffset = symbol->border_width + symbol->whitespace_width;
yoffset = symbol->border_width;
/* Start writing the header */
fprintf(fsvg, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
fprintf(fsvg, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n");
fprintf(fsvg, " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n");
if (symbol->symbology != BARCODE_MAXICODE) {
fprintf(fsvg, "<svg width=\"%d\" height=\"%d\" version=\"1.1\"\n", (int) ceil((symbol->width + xoffset + xoffset) * scaler), (int) ceil((symbol->height + textoffset + yoffset + yoffset) * scaler));
} else {
fprintf(fsvg, "<svg width=\"%d\" height=\"%d\" version=\"1.1\"\n", (int) ceil((74.0F + xoffset + xoffset) * scaler), (int) ceil((72.0F + yoffset + yoffset) * scaler));
}
fprintf(fsvg, "<svg width=\"%d\" height=\"%d\" version=\"1.1\"\n", (int) ceil(symbol->vector->width), (int) ceil(symbol->vector->height));
fprintf(fsvg, " xmlns=\"http://www.w3.org/2000/svg\">\n");
if ((ustrlen(local_text) != 0) && (symbol->show_hrt != 0)) {
fprintf(fsvg, " <desc>%s\n", local_text);
} else {
fprintf(fsvg, " <desc>Zint Generated Symbol\n");
}
fprintf(fsvg, " </desc>\n");
fprintf(fsvg, "\n <g id=\"barcode\" fill=\"#%s\">\n", symbol->fgcolour);
if (symbol->symbology != BARCODE_MAXICODE) {
fprintf(fsvg, " <rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" />\n", (int) ceil((symbol->width + xoffset + xoffset) * scaler), (int) ceil((symbol->height + textoffset + yoffset + yoffset) * scaler), symbol->bgcolour);
fprintf(fsvg, " <rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" />\n", (int) ceil(symbol->vector->width), (int) ceil(symbol->vector->height), symbol->bgcolour);
rect = symbol->vector->rectangles;
while (rect) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", rect->x, rect->y, rect->width, rect->height);
rect = rect->next;
}
hex = symbol->vector->hexagons;
while (hex) {
radius = hex->diameter / 2.0;
ay = hex->y + (1.0 * radius);
by = hex->y + (0.5 * radius);
cy = hex->y - (0.5 * radius);
dy = hex->y - (1.0 * radius);
ey = hex->y - (0.5 * radius);
fy = hex->y + (0.5 * radius);
ax = hex->x;
bx = hex->x + (0.86 * radius);
cx = hex->x + (0.86 * radius);
dx = hex->x;
ex = hex->x - (0.86 * radius);
fx = hex->x - (0.86 * radius);
fprintf(fsvg, " <path d=\"M %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f Z\" />\n", ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy);
hex = hex->next;
}
circle = symbol->vector->circles;
while (circle) {
if (circle->colour) {
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", circle->x, circle->y, circle->diameter / 2.0, symbol->bgcolour);
} else {
fprintf(fsvg, " <rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" />\n", (int) ceil((74.0F + xoffset + xoffset) * scaler), (int) ceil((72.0F + yoffset + yoffset) * scaler), symbol->bgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", circle->x, circle->y, circle->diameter / 2.0, symbol->fgcolour);
}
circle = circle->next;
}
if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
default_text_posn = (symbol->height + textoffset + symbol->border_width + symbol->border_width) * scaler;
} else {
default_text_posn = (symbol->height + textoffset + symbol->border_width) * scaler;
string = symbol->vector->strings;
while (string) {
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", string->x, string->y);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", string->fsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", string->text);
fprintf(fsvg, " </text>\n");
string = string->next;
}
if (symbol->symbology == BARCODE_MAXICODE) {
/* Maxicode uses hexagons */
float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, mx, my;
textoffset = 0.0;
if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, 0.0, (74.0 + xoffset + xoffset) * scaler, symbol->border_width * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, (72.0 + symbol->border_width) * scaler, (74.0 + xoffset + xoffset) * scaler, symbol->border_width * scaler);
}
if (symbol->output_options & BARCODE_BOX) {
/* side bars */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, 0.0, symbol->border_width * scaler, (72.0 + (2 * symbol->border_width)) * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (74.0 + xoffset + xoffset - symbol->border_width) * scaler, 0.0, symbol->border_width * scaler, (72.0 + (2 * symbol->border_width)) * scaler);
}
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 10.85 * scaler, symbol->fgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 8.97 * scaler, symbol->bgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 7.10 * scaler, symbol->fgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 5.22 * scaler, symbol->bgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 3.31 * scaler, symbol->fgcolour);
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 1.43 * scaler, symbol->bgcolour);
for (r = 0; r < symbol->rows; r++) {
for (i = 0; i < symbol->width; i++) {
if (module_is_set(symbol, r, i)) {
/* Dump a hexagon */
my = r * 2.135 + 1.43;
ay = my + 1.0 + yoffset;
by = my + 0.5 + yoffset;
cy = my - 0.5 + yoffset;
dy = my - 1.0 + yoffset;
ey = my - 0.5 + yoffset;
fy = my + 0.5 + yoffset;
if (r & 1) {
mx = (2.46 * i) + 1.23 + 1.23;
} else {
mx = (2.46 * i) + 1.23;
}
ax = mx + xoffset;
bx = mx + 0.86 + xoffset;
cx = mx + 0.86 + xoffset;
dx = mx + xoffset;
ex = mx - 0.86 + xoffset;
fx = mx - 0.86 + xoffset;
fprintf(fsvg, " <path d=\"M %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f L %.2f %.2f Z\" />\n", ax * scaler, ay * scaler, bx * scaler, by * scaler, cx * scaler, cy * scaler, dx * scaler, dy * scaler, ex * scaler, ey * scaler, fx * scaler, fy * scaler);
}
}
}
}
if (symbol->symbology != BARCODE_MAXICODE) {
/* everything else uses rectangles (or squares) */
/* Works from the bottom of the symbol up */
int addon_latch = 0;
for (r = 0; r < symbol->rows; r++) {
int this_row = r;
if (symbol->row_height[this_row] == 0) {
row_height = large_bar_height;
} else {
row_height = symbol->row_height[this_row];
}
row_posn = 0;
for (i = 0; i < r; i++) {
if (symbol->row_height[i] == 0) {
row_posn += large_bar_height;
} else {
row_posn += symbol->row_height[i];
}
}
row_posn += yoffset;
if (symbol->output_options & BARCODE_DOTTY_MODE) {
/* Use dot mode */
for (i = 0; i < symbol->width; i++) {
if (module_is_set(symbol, this_row, i)) {
fprintf(fsvg, " <circle cx=\"%.2f\" cy=\"%.2f\" r=\"%.2f\" fill=\"#%s\" />\n", ((i + xoffset) * scaler) + (scaler / 2.0), (row_posn * scaler) + (scaler / 2.0), (symbol->dot_size / 2.0) * scaler, symbol->fgcolour);
}
}
} else {
/* Normal mode, with rectangles */
i = 0;
if (module_is_set(symbol, this_row, 0)) {
latch = 1;
} else {
latch = 0;
}
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
if ((addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_width)) {
addon_text_posn = (row_posn + 8.0) * scaler;
addon_latch = 1;
}
if (latch == 1) {
/* a bar */
if (addon_latch == 0) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset) * scaler, row_posn * scaler, block_width * scaler, row_height * scaler);
} else {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset) * scaler, (row_posn + 10.0) * scaler, block_width * scaler, (row_height - 5.0) * scaler);
}
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < symbol->width);
}
}
}
/* That's done the actual data area, everything else is human-friendly */
xoffset += comp_offset;
row_posn = (row_posn + large_bar_height) * scaler;
if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) ||
(symbol->symbology == BARCODE_ISBNX)) {
/* guard bar extensions and text formatting for EAN8 and EAN13 */
switch (ustrlen(local_text)) {
case 8: /* EAN-8 */
case 11:
case 14:
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (32 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (34 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (64 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (66 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
for (i = 0; i < 4; i++) {
textpart[i] = local_text[i];
}
textpart[4] = '\0';
textpos = 17;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for (i = 0; i < 4; i++) {
textpart[i] = local_text[i + 4];
}
textpart[4] = '\0';
textpos = 50;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textdone = 1;
switch (strlen(addon)) {
case 2:
textpos = xoffset + 86;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
case 5:
textpos = xoffset + 100;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
}
break;
case 13: /* EAN 13 */
case 16:
case 19:
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (48 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (92 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (94 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
textpart[0] = local_text[0];
textpart[1] = '\0';
textpos = -7;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for (i = 0; i < 6; i++) {
textpart[i] = local_text[i + 1];
}
textpart[6] = '\0';
textpos = 24;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for (i = 0; i < 6; i++) {
textpart[i] = local_text[i + 7];
}
textpart[6] = '\0';
textpos = 71;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textdone = 1;
switch (strlen(addon)) {
case 2:
textpos = xoffset + 114;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
case 5:
textpos = xoffset + 128;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
}
break;
}
}
if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
/* guard bar extensions and text formatting for UPCA */
latch = 1;
i = 0 + comp_offset;
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
if (latch == 1) {
/* a bar */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset - comp_offset) * scaler, row_posn, block_width * scaler, 5.0 * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < 11 + comp_offset);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (48 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
latch = 1;
i = 85 + comp_offset;
do {
block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, symbol->rows - 1, i + block_width) == module_is_set(symbol, symbol->rows - 1, i));
if (latch == 1) {
/* a bar */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (i + xoffset - comp_offset) * scaler, row_posn, block_width * scaler, 5.0 * scaler);
latch = 0;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < 96 + comp_offset);
textpart[0] = local_text[0];
textpart[1] = '\0';
textpos = -5;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for (i = 0; i < 5; i++) {
textpart[i] = local_text[i + 1];
}
textpart[5] = '\0';
textpos = 27;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for (i = 0; i < 5; i++) {
textpart[i] = local_text[i + 6];
}
textpart[6] = '\0';
textpos = 68;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textpart[0] = local_text[11];
textpart[1] = '\0';
textpos = 100;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textdone = 1;
switch (strlen(addon)) {
case 2:
textpos = xoffset + 116;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
case 5:
textpos = xoffset + 130;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
}
}
if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
/* guard bar extensions and text formatting for UPCE */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (48 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (50 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler);
textpart[0] = local_text[0];
textpart[1] = '\0';
textpos = -5;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
for (i = 0; i < 6; i++) {
textpart[i] = local_text[i + 1];
}
textpart[6] = '\0';
textpos = 24;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (11.0 / 8.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textpart[0] = local_text[7];
textpart[1] = '\0';
textpos = 55;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", textpart);
fprintf(fsvg, " </text>\n");
textdone = 1;
switch (strlen(addon)) {
case 2:
textpos = xoffset + 70;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (8.0 / 11.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
case 5:
textpos = xoffset + 84;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", textpos * scaler, addon_text_posn * scaler);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", (8.0 / 11.0) * fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", addon);
fprintf(fsvg, " </text>\n");
break;
}
}
xoffset -= comp_offset;
switch (symbol->symbology) {
case BARCODE_MAXICODE:
/* Do nothing! (It's already been done) */
break;
default:
if (symbol->output_options & BARCODE_BIND) {
if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
/* row binding */
if (symbol->symbology != BARCODE_CODABLOCKF) {
for (r = 1; r < symbol->rows; r++) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", xoffset * scaler, ((r * row_height) + yoffset - 1) * scaler, symbol->width * scaler, 2.0 * scaler);
}
} else {
for (r = 1; r < symbol->rows; r++) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (xoffset + 11) * scaler, ((r * row_height) + yoffset - 1) * scaler, (symbol->width - 25) * scaler, 2.0 * scaler);
}
}
}
}
if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
if (symbol->symbology != BARCODE_CODABLOCKF) {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, 0.0, (symbol->width + xoffset + xoffset) * scaler, symbol->border_width * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, (symbol->height + symbol->border_width) * scaler, (symbol->width + xoffset + xoffset) * scaler, symbol->border_width * scaler);
} else {
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", xoffset * scaler, 0.0, symbol->width * scaler, symbol->border_width * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", xoffset * scaler, (symbol->height + symbol->border_width) * scaler, symbol->width * scaler, symbol->border_width * scaler);
}
}
if (symbol->output_options & BARCODE_BOX) {
/* side bars */
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", 0.0, 0.0, symbol->border_width * scaler, (symbol->height + (2 * symbol->border_width)) * scaler);
fprintf(fsvg, " <rect x=\"%.2f\" y=\"%.2f\" width=\"%.2f\" height=\"%.2f\" />\n", (symbol->width + xoffset + xoffset - symbol->border_width) * scaler, 0.0, symbol->border_width * scaler, (symbol->height + (2 * symbol->border_width)) * scaler);
}
break;
}
/* Put the human readable text at the bottom */
if ((textdone == 0) && ustrlen(local_text)) {
textpos = symbol->width / 2.0;
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"middle\"\n", (textpos + xoffset) * scaler, default_text_posn);
fprintf(fsvg, " font-family=\"Helvetica\" font-size=\"%.1f\" fill=\"#%s\" >\n", fontsize, symbol->fgcolour);
fprintf(fsvg, " %s\n", local_text);
fprintf(fsvg, " </text>\n");
}
fprintf(fsvg, " </g>\n");
fprintf(fsvg, "</svg>\n");
@ -678,4 +136,3 @@ int svg_plot(struct zint_symbol *symbol) {
return error_number;
}

861
backend/vector.c Normal file
View File

@ -0,0 +1,861 @@
/* vector.c - Creates vector image objects
libzint - the open source barcode library
Copyright (C) 2018 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.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include "common.h"
#define SSET "0123456789ABCDEF"
extern int ps_plot(struct zint_symbol *symbol);
extern int svg_plot(struct zint_symbol *symbol);
extern int emf_plot(struct zint_symbol *symbol);
struct zint_vector_rect *vector_plot_create_rect(float x, float y, float width, float height) {
struct zint_vector_rect *rect;
rect = (struct zint_vector_rect*) malloc(sizeof (struct zint_vector_rect));
if (!rect) return NULL;
rect->next = NULL;
rect->x = x;
rect->y = y;
rect->width = width;
rect->height = height;
rect->colour = -1; // Default colour
return rect;
}
int vector_plot_add_rect(struct zint_symbol *symbol, struct zint_vector_rect *rect, struct zint_vector_rect **last_rect) {
if (!rect) return ZINT_ERROR_MEMORY;
if (*last_rect)
(*last_rect)->next = rect;
else
symbol->vector->rectangles = rect; // first rectangle
*last_rect = rect;
return 1;
}
struct zint_vector_hexagon *vector_plot_create_hexagon(float x, float y, float diameter) {
struct zint_vector_hexagon *hexagon;
hexagon = (struct zint_vector_hexagon*) malloc(sizeof (struct zint_vector_hexagon));
if (!hexagon) return NULL;
hexagon->next = NULL;
hexagon->x = x;
hexagon->y = y;
hexagon->diameter = (diameter * 5.0) / 4.0; // Ugly kludge for legacy support
return hexagon;
}
int vector_plot_add_hexagon(struct zint_symbol *symbol, struct zint_vector_hexagon *hexagon, struct zint_vector_hexagon **last_hexagon) {
if (!hexagon) return ZINT_ERROR_MEMORY;
if (*last_hexagon)
(*last_hexagon)->next = hexagon;
else
symbol->vector->hexagons = hexagon; // first hexagon
*last_hexagon = hexagon;
return 1;
}
struct zint_vector_circle *vector_plot_create_circle(float x, float y, float diameter, int colour) {
struct zint_vector_circle *circle;
circle = (struct zint_vector_circle *) malloc(sizeof (struct zint_vector_circle));
if (!circle) return NULL;
circle->next = NULL;
circle->x = x;
circle->y = y;
circle->diameter = diameter;
circle->colour = colour;
return circle;
}
int vector_plot_add_circle(struct zint_symbol *symbol, struct zint_vector_circle *circle, struct zint_vector_circle **last_circle) {
if (!circle) return ZINT_ERROR_MEMORY;
if (*last_circle)
(*last_circle)->next = circle;
else
symbol->vector->circles = circle; // first circle
*last_circle = circle;
return 1;
}
int vector_plot_add_string(struct zint_symbol *symbol,
unsigned char *text, float x, float y, float fsize, float width,
struct zint_vector_string **last_string) {
struct zint_vector_string *string;
string = (struct zint_vector_string*) malloc(sizeof (struct zint_vector_string));
string->next = NULL;
string->x = x;
string->y = y;
string->width = width;
string->fsize = fsize;
string->length = ustrlen(text);
string->text = (unsigned char*) malloc(sizeof (unsigned char) * (ustrlen(text) + 1));
ustrcpy(string->text, text);
if (*last_string)
(*last_string)->next = string;
else
symbol->vector->strings = string; // First text portion
*last_string = string;
return 1;
}
void vector_free(struct zint_symbol *symbol) {
if (symbol->vector != NULL) {
struct zint_vector_rect *rect;
struct zint_vector_hexagon *hex;
struct zint_vector_circle *circle;
struct zint_vector_string *string;
// Free Rectangles
rect = symbol->vector->rectangles;
while (rect) {
struct zint_vector_rect *r = rect;
rect = rect->next;
free(r);
}
// Free Hexagons
hex = symbol->vector->hexagons;
while (hex) {
struct zint_vector_hexagon *h = hex;
hex = hex->next;
free(h);
}
// Free Circles
circle = symbol->vector->circles;
while (circle) {
struct zint_vector_circle *c = circle;
circle = circle->next;
free(c);
}
// Free Strings
string = symbol->vector->strings;
while (string) {
struct zint_vector_string *s = string;
string = string->next;
free(s->text);
free(s);
}
// Free vector
free(symbol->vector);
symbol->vector = NULL;
}
}
void vector_scale(struct zint_symbol *symbol) {
struct zint_vector_rect *rect;
struct zint_vector_hexagon *hex;
struct zint_vector_circle *circle;
struct zint_vector_string *string;
float scale = symbol->scale * 2.0;
symbol->vector->width *= scale;
symbol->vector->height *= scale;
rect = symbol->vector->rectangles;
while (rect) {
rect->x *= scale;
rect->y *= scale;
rect->height *= scale;
rect->width *= scale;
rect = rect->next;
}
hex = symbol->vector->hexagons;
while (hex) {
hex->x *= scale;
hex->y *= scale;
hex->diameter *= scale;
hex = hex->next;
}
circle = symbol->vector->circles;
while (circle) {
circle->x *= scale;
circle->y *= scale;
circle->diameter *= scale;
circle = circle->next;
}
string = symbol->vector->strings;
while (string) {
string->x *= scale;
string->y *= scale;
string->width *= scale;
string->fsize *= scale;
string = string->next;
}
return;
}
void delete_last_rect(struct zint_vector_rect *rect) {
struct zint_vector_rect *local;
local = rect;
if (local->next == NULL) {
free(local);
return;
}
while (local->next->next != NULL) {
local = local->next;
}
free(local->next);
local->next = NULL;
}
void bump_up_rect(struct zint_vector_rect *rect) {
struct zint_vector_rect *local;
local = rect;
while (local->next) {
local->x = local->next->x;
local->y = local->next->y;
local->height = local->next->height;
local->width = local->next->width;
local = local->next;
}
}
void vector_reduce_rectangles(struct zint_symbol *symbol) {
// Looks for vertically aligned rectangles and merges them together
struct zint_vector_rect *rect, *target = NULL;
rect = symbol->vector->rectangles;
while (rect) {
target = rect->next;
while (target) {
if ((rect->x == target->x) && (rect->width == target->width) && ((rect->y + rect->height) == target->y)) {
rect->height += target->height;
bump_up_rect(target);
delete_last_rect(symbol->vector->rectangles);
} else {
target = target->next;
}
}
rect = rect->next;
}
return;
}
int vector_plot(struct zint_symbol *symbol, int rotate_angle, int file_type) {
int error_number;
struct zint_vector *vector;
struct zint_vector_rect *rectangle, *rect, *last_rectangle = NULL;
struct zint_vector_hexagon *last_hexagon = NULL;
struct zint_vector_string *last_string = NULL;
struct zint_vector_circle *last_circle = NULL;
int i, r, latch;
float textpos, large_bar_height, preset_height, row_height, row_posn = 0.0;
int text_offset, text_height, xoffset, yoffset, textdone, main_symbol_width_x;
char addon[6];
int large_bar_count, symbol_lead_in;
float addon_text_posn;
float default_text_posn;
int hide_text = 0;
int upceanflag = 0;
int rect_count, last_row_start;
int this_row;
// Sanity check colours
to_upper((unsigned char*) symbol->fgcolour);
to_upper((unsigned char*) symbol->bgcolour);
if (strlen(symbol->fgcolour) != 6) {
strcpy(symbol->errtxt, "661: Malformed foreground colour target");
return ZINT_ERROR_INVALID_OPTION;
}
if (strlen(symbol->bgcolour) != 6) {
strcpy(symbol->errtxt, "662: Malformed background colour target");
return ZINT_ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*) symbol->fgcolour, strlen(symbol->fgcolour));
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "663: Malformed foreground colour target");
return ZINT_ERROR_INVALID_OPTION;
}
error_number = is_sane(SSET, (unsigned char*) symbol->bgcolour, strlen(symbol->bgcolour));
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "664: Malformed background colour target");
return ZINT_ERROR_INVALID_OPTION;
}
// Free any previous rendering structures
vector_free(symbol);
// Allocate memory
vector = symbol->vector = (struct zint_vector *) malloc(sizeof (struct zint_vector));
if (!vector) return ZINT_ERROR_MEMORY;
vector->rectangles = NULL;
vector->hexagons = NULL;
vector->circles = NULL;
vector->strings = NULL;
row_height = 0;
textdone = 0;
textpos = 0.0;
main_symbol_width_x = symbol->width;
strcpy(addon, "");
symbol_lead_in = 0;
addon_text_posn = 0.0;
rect_count = 0;
last_row_start = 0;
/*
* Determine if there will be any addon texts and text height
*/
latch = 0;
r = 0;
/* Isolate add-on text */
if (is_extendable(symbol->symbology)) {
for (i = 0; i < (int) ustrlen(symbol->text); i++) {
if (latch == 1) {
addon[r] = symbol->text[i];
r++;
}
if (symbol->text[i] == '+') {
latch = 1;
}
}
}
addon[r] = '\0';
/*
* Calculate the width of the barcode, especially if there are any extra
* borders or white space to add.
*/
while (!(module_is_set(symbol, symbol->rows - 1, symbol_lead_in))) {
symbol_lead_in++;
}
/* Certain symbols need whitespace otherwise characters get chopped off the sides */
if ((((symbol->symbology == BARCODE_EANX || symbol->symbology == BARCODE_EANX_CHK) && (symbol->rows == 1)) ||
(symbol->symbology == BARCODE_EANX_CC)) || (symbol->symbology == BARCODE_ISBNX)) {
switch (ustrlen(symbol->text)) {
case 13: /* EAN 13 */
case 16:
case 19:
if (symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
}
main_symbol_width_x = 96 + symbol_lead_in;
upceanflag = 13;
break;
case 2:
main_symbol_width_x = 22 + symbol_lead_in;
upceanflag = 2;
break;
case 5:
main_symbol_width_x = 49 + symbol_lead_in;
upceanflag = 5;
break;
default:
main_symbol_width_x = 68 + symbol_lead_in;
upceanflag = 8;
}
} else if (((symbol->symbology == BARCODE_UPCA || symbol->symbology == BARCODE_UPCA_CHK) && (symbol->rows == 1))
|| (symbol->symbology == BARCODE_UPCA_CC)) {
upceanflag = 12;
if (symbol->whitespace_width < 10) {
symbol->whitespace_width = 10;
main_symbol_width_x = 96 + symbol_lead_in;
}
} else if (((symbol->symbology == BARCODE_UPCE || symbol->symbology == BARCODE_UPCE_CHK) && (symbol->rows == 1))
|| (symbol->symbology == BARCODE_UPCE_CC)) {
upceanflag = 6;
if (symbol->whitespace_width == 0) {
symbol->whitespace_width = 10;
main_symbol_width_x = 51 + symbol_lead_in;
}
}
if ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0)) {
hide_text = 1;
text_height = 0.0;
text_offset = upceanflag ? 9.0 : 0.0;
} else {
text_height = upceanflag ? 11.0 : 9.0;
text_offset = 9.0;
}
if (symbol->output_options & SMALL_TEXT)
text_height *= 0.8;
xoffset = symbol->border_width + symbol->whitespace_width;
yoffset = symbol->border_width;
// Determine if height should be overridden
large_bar_count = 0;
preset_height = 0.0;
for (i = 0; i < symbol->rows; i++) {
preset_height += symbol->row_height[i];
if (symbol->row_height[i] == 0) {
large_bar_count++;
}
}
vector->width = ceil(symbol->width + xoffset + xoffset);
vector->height = ceil(symbol->height + text_offset + yoffset + yoffset);
large_bar_height = (symbol->height - preset_height) / large_bar_count;
if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
default_text_posn = symbol->height + text_offset + symbol->border_width + symbol->border_width;
} else {
default_text_posn = symbol->height + text_offset + symbol->border_width;
}
int addon_latch = 0;
// Plot rectangles - most symbols created here
if ((symbol->symbology != BARCODE_MAXICODE) && ((symbol->output_options & BARCODE_DOTTY_MODE) == 0)) {
for (r = 0; r < symbol->rows; r++) {
this_row = r;
last_row_start = rect_count;
if (symbol->row_height[this_row] == 0) {
row_height = large_bar_height;
} else {
row_height = symbol->row_height[this_row];
}
row_posn = 0;
for (i = 0; i < r; i++) {
if (symbol->row_height[i] == 0) {
row_posn += large_bar_height;
} else {
row_posn += symbol->row_height[i];
}
}
row_posn += yoffset;
i = 0;
if (module_is_set(symbol, this_row, 0)) {
latch = 1;
} else {
latch = 0;
}
do {
int block_width = 0;
do {
block_width++;
} while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
if ((addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_symbol_width_x)) {
addon_text_posn = row_posn + 8.0;
addon_latch = 1;
}
if (latch == 1) {
/* a bar */
if (addon_latch == 0) {
rectangle = vector_plot_create_rect(i + xoffset, row_posn, block_width, row_height);
} else {
rectangle = vector_plot_create_rect(i + xoffset, row_posn + 10.0, block_width, row_height - 5.0);
}
latch = 0;
vector_plot_add_rect(symbol, rectangle, &last_rectangle);
rect_count++;
} else {
/* a space */
latch = 1;
}
i += block_width;
} while (i < symbol->width);
}
}
// Plot Maxicode symbols
if (symbol->symbology == BARCODE_MAXICODE) {
vector->width = 37.0 + xoffset;
vector->height = 36.0 + yoffset;
// Bullseye
struct zint_vector_circle *circle = vector_plot_create_circle(17.88 + (xoffset / 2.0), 17.8 + (yoffset / 2.0), 10.85, 0);
vector_plot_add_circle(symbol, circle, &last_circle);
circle = vector_plot_create_circle(17.88 + (xoffset / 2.0), 17.8 + (yoffset / 2.0), 8.97, 1);
vector_plot_add_circle(symbol, circle, &last_circle);
circle = vector_plot_create_circle(17.88 + (xoffset / 2.0), 17.8 + (yoffset / 2.0), 7.10, 0);
vector_plot_add_circle(symbol, circle, &last_circle);
circle = vector_plot_create_circle(17.88 + (xoffset / 2.0), 17.8 + (yoffset / 2.0), 5.22, 1);
vector_plot_add_circle(symbol, circle, &last_circle);
circle = vector_plot_create_circle(17.88 + (xoffset / 2.0), 17.8 + (yoffset / 2.0), 3.31, 0);
vector_plot_add_circle(symbol, circle, &last_circle);
circle = vector_plot_create_circle(17.88 + (xoffset / 2.0), 17.8 + (yoffset / 2.0), 1.43, 1);
vector_plot_add_circle(symbol, circle, &last_circle);
/* Hexagons */
for (r = 0; r < symbol->rows; r++) {
for (i = 0; i < symbol->width; i++) {
if (module_is_set(symbol, r, i)) {
//struct zint_vector_hexagon *hexagon = vector_plot_create_hexagon(((i * 0.88) + ((r & 1) ? 1.76 : 1.32)), ((r * 0.76) + 0.76), symbol->dot_size);
struct zint_vector_hexagon *hexagon = vector_plot_create_hexagon(((i * 1.23) + 0.615 + ((r & 1) ? 0.615 : 0.0)), ((r * 1.067) + 0.715), symbol->dot_size);
vector_plot_add_hexagon(symbol, hexagon, &last_hexagon);
}
}
}
}
// Dotty mode
if ((symbol->symbology != BARCODE_MAXICODE) && (symbol->output_options & BARCODE_DOTTY_MODE)) {
for (r = 0; r < symbol->rows; r++) {
for (i = 0; i < symbol->width; i++) {
if (module_is_set(symbol, r, i)) {
struct zint_vector_circle *circle = vector_plot_create_circle(i + 0.5 + (xoffset / 2.0), r + 0.5 + (yoffset / 2.0), 1.0, 0);
vector_plot_add_circle(symbol, circle, &last_circle);
}
}
}
}
/* Guard bar extension */
if (upceanflag == 6) {
i = 0;
for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) {
switch (i - last_row_start) {
case 0:
case 1:
case 14:
case 15:
case 16:
rect->height += 5.0;
break;
}
i++;
}
}
if (upceanflag == 8) {
i = 0;
for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) {
switch (i - last_row_start) {
case 0:
case 1:
case 10:
case 11:
case 20:
case 21:
rect->height += 5.0;
break;
}
i++;
}
}
if (upceanflag == 12) {
i = 0;
for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) {
switch (i - last_row_start) {
case 0:
case 1:
case 2:
case 3:
case 14:
case 15:
case 26:
case 27:
case 28:
case 29:
rect->height += 5.0;
break;
}
i++;
}
}
if (upceanflag == 13) {
i = 0;
for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) {
switch (i - last_row_start) {
case 0:
case 1:
case 14:
case 15:
case 28:
case 29:
rect->height += 5.0;
break;
}
i++;
}
}
/* Add the text */
xoffset += symbol_lead_in;
row_posn = row_posn + large_bar_height;
if (!hide_text) {
char textpart[10];
float textwidth;
if (upceanflag == 8) {
for (i = 0; i < 4; i++) {
textpart[i] = symbol->text[i];
}
textpart[4] = '\0';
textpos = 17;
textwidth = 4.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn, text_height, textwidth, &last_string);
for (i = 0; i < 4; i++) {
textpart[i] = symbol->text[i + 4];
}
textpart[4] = '\0';
textpos = 50;
vector_plot_add_string(symbol, (unsigned char *) textpart, (textpos + xoffset), default_text_posn, text_height, textwidth, &last_string);
textdone = 1;
switch (strlen(addon)) {
case 2:
textpos = xoffset + 86;
textwidth = 2.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) addon, textpos, addon_text_posn, text_height, textwidth, &last_string);
break;
case 5:
textpos = xoffset + 100;
textwidth = 5.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) addon, textpos, addon_text_posn, text_height, textwidth, &last_string);
break;
}
}
if (upceanflag == 13) {
textpart[0] = symbol->text[0];
textpart[1] = '\0';
textpos = -5; // 7
textwidth = 8.5;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn, text_height, textwidth, &last_string);
for (i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[6] = '\0';
textpos = 25;
textwidth = 6.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn, text_height, textwidth, &last_string);
for (i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 7];
}
textpart[6] = '\0';
textpos = 72;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn, text_height, textwidth, &last_string);
textdone = 1;
switch (strlen(addon)) {
case 2:
textpos = xoffset + 114;
textwidth = 2.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) addon, textpos, addon_text_posn, text_height, textwidth, &last_string);
break;
case 5:
textpos = xoffset + 128;
textwidth = 5.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) addon, textpos, addon_text_posn, text_height, textwidth, &last_string);
break;
}
}
if (upceanflag == 12) {
textpart[0] = symbol->text[0];
textpart[1] = '\0';
textpos = -5;
textwidth = 6.2;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn - 2.0, text_height * (8.0 / 11.0), textwidth, &last_string);
for (i = 0; i < 5; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[5] = '\0';
textpos = 27;
textwidth = 5.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn, text_height, textwidth, &last_string);
for (i = 0; i < 5; i++) {
textpart[i] = symbol->text[i + 6];
}
textpos = 68;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn, text_height, textwidth, &last_string);
textpart[0] = symbol->text[11];
textpart[1] = '\0';
textpos = 100;
textwidth = 6.2;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn - 2.0, text_height * (8.0 / 11.0), textwidth, &last_string);
textdone = 1;
switch (strlen(addon)) {
case 2:
textpos = xoffset + 116;
textwidth = 2.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) addon, textpos, addon_text_posn, text_height, textwidth, &last_string);
break;
case 5:
textpos = xoffset + 130;
textwidth = 5.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) addon, textpos, addon_text_posn, text_height, textwidth, &last_string);
break;
}
}
if (upceanflag == 6) {
textpart[0] = symbol->text[0];
textpart[1] = '\0';
textpos = -5;
textwidth = 6.2;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn - 2.0, text_height * (8.0 / 11.0), textwidth, &last_string);
for (i = 0; i < 6; i++) {
textpart[i] = symbol->text[i + 1];
}
textpart[6] = '\0';
textpos = 24;
textwidth = 6.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn, text_height, textwidth, &last_string);
textpart[0] = symbol->text[7];
textpart[1] = '\0';
textpos = 55;
textwidth = 6.2;
vector_plot_add_string(symbol, (unsigned char *) textpart, textpos + xoffset, default_text_posn - 2.0, text_height * (8.0 / 11.0), textwidth, &last_string);
textdone = 1;
switch (strlen(addon)) {
case 2:
textpos = xoffset + 70;
textwidth = 2.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) addon, textpos, addon_text_posn, text_height, textwidth, &last_string);
break;
case 5:
textpos = xoffset + 84;
textwidth = 5.0 * 8.5;
vector_plot_add_string(symbol, (unsigned char *) addon, textpos, addon_text_posn, text_height, textwidth, &last_string);
break;
}
}
/* Put normal human readable text at the bottom (and centered) */
if (textdone == 0) {
// caculate start xoffset to center text
vector_plot_add_string(symbol, symbol->text, (symbol->width / 2.0) + xoffset, default_text_posn, text_height, symbol->width, &last_string);
}
}
//Remove control characters from readable text
// This only applies to Code 128
struct zint_vector_string *string = symbol->vector->strings;
if (string) {
for (i = 0; i < string->length; i++) {
if (string->text[i] < ' ') {
string->text[i] = ' ';
}
}
}
// Binding and boxes
if ((symbol->output_options & BARCODE_BIND) != 0) {
if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) {
/* row binding */
for (r = 1; r < symbol->rows; r++) {
if (symbol->symbology != BARCODE_CODABLOCKF) {
rectangle = vector_plot_create_rect(xoffset, (r * row_height) + yoffset - 1, symbol->width, 2.0);
vector_plot_add_rect(symbol, rectangle, &last_rectangle);
} else {
rectangle = vector_plot_create_rect(xoffset + 11.0, (r * row_height) + yoffset - 1, symbol->width - 25.0, 2.0);
vector_plot_add_rect(symbol, rectangle, &last_rectangle);
}
}
}
}
if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) {
rectangle = vector_plot_create_rect(0.0, 0.0, symbol->width + xoffset + xoffset, symbol->border_width);
if (symbol->symbology == BARCODE_CODABLOCKF) {
rectangle->x = xoffset;
rectangle->width -= (2.0 * xoffset);
}
vector_plot_add_rect(symbol, rectangle, &last_rectangle);
rectangle = vector_plot_create_rect(0.0, symbol->height + symbol->border_width, symbol->width + xoffset + xoffset, symbol->border_width);
if (symbol->symbology == BARCODE_CODABLOCKF) {
rectangle->x = xoffset;
rectangle->width -= (2.0 * xoffset);
}
vector_plot_add_rect(symbol, rectangle, &last_rectangle);
}
if (symbol->output_options & BARCODE_BOX) {
/* side bars */
rectangle = vector_plot_create_rect(0.0, 0.0, symbol->border_width, (symbol->height + (2 * symbol->border_width)));
vector_plot_add_rect(symbol, rectangle, &last_rectangle);
rectangle = vector_plot_create_rect(symbol->width + xoffset + xoffset - symbol->border_width, 0.0, symbol->border_width, (symbol->height + (2 * symbol->border_width)));
vector_plot_add_rect(symbol, rectangle, &last_rectangle);
}
vector_reduce_rectangles(symbol);
vector_scale(symbol);
switch (file_type) {
case OUT_EPS_FILE:
error_number = ps_plot(symbol);
break;
case OUT_SVG_FILE:
error_number = svg_plot(symbol);
break;
case OUT_EMF_FILE:
error_number = emf_plot(symbol);
break;
}
vector_free(symbol);
return error_number;
}

View File

@ -1,7 +1,7 @@
/* zint.h - definitions for libzint
libzint - the open source barcode library
Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
Copyright (C) 2009-2018 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -41,6 +41,12 @@ extern "C" {
struct zint_render_line *next; /* Pointer to next line */
};
struct zint_vector_rect {
float x, y, height, width;
int colour;
struct zint_vector_rect *next;
};
struct zint_render_string {
float x, y, fsize;
float width; /* Suggested string width, may be 0 if none recommended */
@ -49,16 +55,35 @@ extern "C" {
struct zint_render_string *next; /* Pointer to next character */
};
struct zint_vector_string {
float x, y, fsize;
float width; /* Suggested string width, may be 0 if none recommended */
int length;
unsigned char *text;
struct zint_vector_string *next; /* Pointer to next character */
};
struct zint_render_ring {
float x, y, radius, line_width;
struct zint_render_ring *next; /* Pointer to next ring */
};
struct zint_vector_circle {
float x, y, diameter;
int colour;
struct zint_vector_circle *next; /* Pointer to next circle */
};
struct zint_render_hexagon {
float x, y, height;
struct zint_render_hexagon *next; /* Pointer to next hexagon */
};
struct zint_vector_hexagon {
float x, y, diameter;
struct zint_vector_hexagon *next; /* Pointer to next hexagon */
};
struct zint_render {
float width, height;
struct zint_render_line *lines; /* Pointer to first line */
@ -67,6 +92,14 @@ extern "C" {
struct zint_render_hexagon *hexagons; /* Pointer to first hexagon */
};
struct zint_vector {
float width, height;
struct zint_vector_rect *rectangles; /* Pointer to first rectangle */
struct zint_vector_hexagon *hexagons; /* Pointer to first hexagon */
struct zint_vector_string *strings; /* Points to first string */
struct zint_vector_circle *circles; /* Points to first circle */
};
struct zint_symbol {
int symbology;
int height;
@ -96,6 +129,7 @@ extern "C" {
int bitmap_height;
unsigned int bitmap_byte_length;
float dot_size;
struct zint_vector *vector;
struct zint_render *rendered;
int debug;
};
@ -242,6 +276,9 @@ extern "C" {
// Raster file types
#define OUT_BUFFER 0
#define OUT_SVG_FILE 10
#define OUT_EPS_FILE 20
#define OUT_EMF_FILE 30
#define OUT_PNG_FILE 100
#define OUT_BMP_FILE 120
#define OUT_GIF_FILE 140