From 30fcd7986cc80a65d9ec422b86c447d4823b84ec Mon Sep 17 00:00:00 2001 From: Robin Stuart Date: Sun, 10 Jun 2018 09:16:18 +0100 Subject: [PATCH] Plot vector graphics using linked list structure Simplifies the implementation of individual vector graphic file formats --- backend/CMakeLists.txt | 2 +- backend/emf.c | 1163 ++++++++-------------------------------- backend/library.c | 16 +- backend/ps.c | 871 +++--------------------------- backend/svg.c | 643 ++-------------------- backend/vector.c | 861 +++++++++++++++++++++++++++++ backend/zint.h | 39 +- 7 files changed, 1255 insertions(+), 2340 deletions(-) create mode 100644 backend/vector.c diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index ac93865a..b71da66d 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -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) diff --git a/backend/emf.c b/backend/emf.c index 5a17643d..16016a52 100644 --- a/backend/emf.c +++ b/backend/emf.c @@ -1,7 +1,7 @@ /* emf.c - Support for Microsoft Enhanced Metafile Format libzint - the open source barcode library - Copyright (C) 2016-2017 Robin Stuart + Copyright (C) 2016-2018 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -41,27 +41,14 @@ #include "common.h" #include "emf.h" -#define SSET "0123456789ABCDEF" - int count_rectangles(struct zint_symbol *symbol) { int rectangles = 0; + struct zint_vector_rect *rect; - if ((symbol->symbology != BARCODE_MAXICODE) && - ((symbol->output_options & BARCODE_DOTTY_MODE) == 0)) { - int this_row; - for(this_row = 0; this_row < symbol->rows; this_row++) { - int i, latch = 0; - for(i = 0; i < symbol->width; i++) { - if ((module_is_set(symbol, this_row, i)) && (latch == 0)) { - latch = 1; - rectangles++; - } - - if ((!(module_is_set(symbol, this_row, i))) && (latch == 1)) { - latch = 0; - } - } - } + rect = symbol->vector->rectangles; + while (rect) { + rectangles++; + rect = rect->next; } return rectangles; @@ -69,18 +56,12 @@ int count_rectangles(struct zint_symbol *symbol) { int count_circles(struct zint_symbol *symbol) { int circles = 0; + struct zint_vector_circle *circ; - if ((symbol->symbology != BARCODE_MAXICODE) && - ((symbol->output_options & BARCODE_DOTTY_MODE) != 0)) { - int this_row; - for(this_row = 0; this_row < symbol->rows; this_row++) { - int i; - for(i = 0; i < symbol->width; i++) { - if (module_is_set(symbol, this_row, i)) { - circles++; - } - } - } + circ = symbol->vector->circles; + while (circ) { + circles++; + circ = circ->next; } return circles; @@ -88,22 +69,30 @@ int count_circles(struct zint_symbol *symbol) { int count_hexagons(struct zint_symbol *symbol) { int hexagons = 0; + struct zint_vector_hexagon *hex; - if (symbol->symbology == BARCODE_MAXICODE) { - int this_row; - for(this_row = 0; this_row < symbol->rows; this_row++) { - int i; - for(i = 0; i < symbol->width; i++) { - if (module_is_set(symbol, this_row, i)) { - hexagons++; - } - } - } + hex = symbol->vector->hexagons; + while (hex) { + hexagons++; + hex = hex->next; } return hexagons; } +int count_strings(struct zint_symbol *symbol) { + int strings = 0; + struct zint_vector_string *str; + + str = symbol->vector->strings; + while (str) { + strings++; + str = str->next; + } + + return strings; +} + void utfle_copy(unsigned char *output, unsigned char *input, int length) { int i; int o; @@ -112,7 +101,7 @@ void utfle_copy(unsigned char *output, unsigned char *input, int length) { i = 0; o = 0; do { - if(input[i] <= 0x7f) { + if (input[i] <= 0x7f) { /* 1 byte mode (7-bit ASCII) */ output[o] = input[i]; output[o + 1] = 0x00; @@ -137,25 +126,25 @@ int bump_up(int input) { } int emf_plot(struct zint_symbol *symbol) { - int i, block_width, latch, this_row; - float large_bar_height, preset_height, row_height; + int i; FILE *emf_file; int fgred, fggrn, fgblu, bgred, bggrn, bgblu; int error_number = 0; - int textoffset, xoffset, yoffset, textdone; - int large_bar_count, comp_offset; - float scaler = symbol->scale * 10; int rectangle_count, this_rectangle; int circle_count, this_circle; int hexagon_count, this_hexagon; + int string_count, this_text; int bytecount, recordcount; - int upcean = 0; - unsigned char regw[7]; - unsigned char regx[7]; - unsigned char regy[7]; - unsigned char regz[7]; - unsigned char output_buffer[12]; - uint32_t dx; + float radius; + unsigned char *this_string[6]; + uint32_t spacing; + + float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy; + + struct zint_vector_rect *rect; + struct zint_vector_circle *circ; + struct zint_vector_hexagon *hex; + struct zint_vector_string *str; emr_header_t emr_header; emr_eof_t emr_eof; @@ -166,88 +155,10 @@ int emf_plot(struct zint_symbol *symbol) { emr_createpen_t emr_createpen; emr_selectobject_t emr_selectobject_pen; emr_rectangle_t background; - emr_ellipse_t bullseye[6]; emr_extcreatefontindirectw_t emr_extcreatefontindirectw; emr_selectobject_t emr_selectobject_font; - emr_exttextoutw_t emr_exttextoutw[6]; - emr_extcreatefontindirectw_t emr_extcreatefontindirectw_big; - emr_selectobject_t emr_selectobject_font_big; - - box_t box; - -#ifndef _MSC_VER - unsigned char local_text[bump_up(ustrlen(symbol->text) + 1)]; - unsigned char string_buffer[2 * bump_up(ustrlen(symbol->text) + 1)]; -#else - unsigned char* local_text; - unsigned char* string_buffer; - emr_rectangle_t *rectangle, *row_binding; - emr_ellipse_t* circle; - emr_polygon_t* hexagon; - local_text = (unsigned char*) _alloca(bump_up(ustrlen(symbol->text) + 1) * sizeof (unsigned char)); - string_buffer = (unsigned char*) _alloca(2 * bump_up(ustrlen(symbol->text) + 1) * sizeof (unsigned char)); -#endif - - row_height = 0; - textdone = 0; - comp_offset = 0; - this_rectangle = 0; - this_circle = 0; - this_hexagon = 0; - dx = 0; - latch = 0; - - for(i = 0; i < 6; i++) { - regw[i] = '\0'; - regx[i] = '\0'; - regy[i] = '\0'; - regz[i] = '\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; - } - } - - /* sort out colour options */ - to_upper((unsigned char*) symbol->fgcolour); - to_upper((unsigned char*) symbol->bgcolour); - - if (strlen(symbol->fgcolour) != 6) { - strcpy(symbol->errtxt, "641: Malformed foreground colour target"); - return ZINT_ERROR_INVALID_OPTION; - } - - if (strlen(symbol->bgcolour) != 6) { - strcpy(symbol->errtxt, "642: Malformed background colour target"); - return ZINT_ERROR_INVALID_OPTION; - } + //emr_extcreatefontindirectw_t emr_extcreatefontindirectw_big; + //emr_selectobject_t emr_selectobject_font_big; fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]); fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]); @@ -256,100 +167,37 @@ int emf_plot(struct zint_symbol *symbol) { bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]); bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]); - 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; - } - break; - } - upcean = 1; - } - - if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) { - if (symbol->whitespace_width == 0) { - symbol->whitespace_width = 10; - } - upcean = 1; - } - - if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) { - if (symbol->whitespace_width == 0) { - symbol->whitespace_width = 10; - } - upcean = 1; - } - - if (ustrlen(local_text) != 0) { - textoffset = 9; - } else { - textoffset = 0; - } - xoffset = symbol->border_width + symbol->whitespace_width; - yoffset = symbol->border_width; - rectangle_count = count_rectangles(symbol); circle_count = count_circles(symbol); hexagon_count = count_hexagons(symbol); + string_count = count_strings(symbol); #ifndef _MSC_VER emr_rectangle_t rectangle[rectangle_count]; - emr_rectangle_t row_binding[symbol->rows - 1]; emr_ellipse_t circle[circle_count]; emr_polygon_t hexagon[hexagon_count]; + emr_exttextoutw_t text[string_count]; #else - rectangle = (emr_rectangle_t*) _alloca(rectangle_count*sizeof(emr_rectangle_t)); - row_binding = (emr_rectangle_t*) _alloca((symbol->rows - 1)*sizeof(emr_rectangle_t)); - circle = (emr_ellipse_t*) _alloca(circle_count*sizeof(emr_ellipse_t)); - hexagon = (emr_polygon_t*) _alloca(hexagon_count*sizeof(emr_polygon_t)); + emr_rectangle_t *rectangle = (emr_rectangle_t*) _alloca(rectangle_count * sizeof (emr_rectangle_t)); + emr_ellipse_t *circle = (emr_ellipse_t*) _alloca(circle_count * sizeof (emr_ellipse_t)); + emr_polygon_t *hexagon = (emr_polygon_t*) _alloca(hexagon_count * sizeof (emr_polygon_t)); + emr_exttextoutw_t *text = (emr_exttextoutw_t*) _alloca(string_count * sizeof (emr_exttextoutw_t)); #endif - + /* Header */ emr_header.type = 0x00000001; // EMR_HEADER emr_header.size = 88; // Assuming no additional data in header emr_header.emf_header.bounds.left = 0; - if (symbol->symbology != BARCODE_MAXICODE) { - emr_header.emf_header.bounds.right = ceil((symbol->width + xoffset + xoffset) * scaler); - emr_header.emf_header.bounds.bottom = ceil((symbol->height + textoffset + yoffset + yoffset) * scaler); - } else { - emr_header.emf_header.bounds.right = ceil((74.0F + xoffset + xoffset) * scaler); - emr_header.emf_header.bounds.bottom = ceil((72.0F + yoffset + yoffset) * scaler); - } + emr_header.emf_header.bounds.right = ceil(symbol->vector->width); + emr_header.emf_header.bounds.bottom = ceil(symbol->vector->height); emr_header.emf_header.bounds.top = 0; emr_header.emf_header.frame.left = 0; emr_header.emf_header.frame.right = emr_header.emf_header.bounds.right * 30; emr_header.emf_header.frame.top = 0; emr_header.emf_header.frame.bottom = emr_header.emf_header.bounds.bottom * 30; emr_header.emf_header.record_signature = 0x464d4520; // ENHMETA_SIGNATURE - emr_header.emf_header.version = 0x00010000;; - emr_header.emf_header.handles = 6; // Number of graphics objects + emr_header.emf_header.version = 0x00010000; + emr_header.emf_header.handles = 4; // Number of graphics objects emr_header.emf_header.reserved = 0x0000; emr_header.emf_header.n_description = 0; emr_header.emf_header.off_description = 0; @@ -370,7 +218,7 @@ int emf_plot(struct zint_symbol *symbol) { emr_createbrushindirect_fg.log_brush.color.green = fggrn; emr_createbrushindirect_fg.log_brush.color.blue = fgblu; emr_createbrushindirect_fg.log_brush.color.reserved = 0; - emr_createbrushindirect_fg.log_brush.brush_hatch = 0; // ignored + emr_createbrushindirect_fg.log_brush.brush_hatch = 0x0006; // HS_SOLIDCLR bytecount += 24; recordcount++; @@ -382,7 +230,7 @@ int emf_plot(struct zint_symbol *symbol) { emr_createbrushindirect_bg.log_brush.color.green = bggrn; emr_createbrushindirect_bg.log_brush.color.blue = bgblu; emr_createbrushindirect_bg.log_brush.color.reserved = 0; - emr_createbrushindirect_bg.log_brush.brush_hatch = 0; // ignored + emr_createbrushindirect_bg.log_brush.brush_hatch = 0x0006; // HS_SOLIDCLR bytecount += 24; recordcount++; @@ -418,12 +266,100 @@ int emf_plot(struct zint_symbol *symbol) { bytecount += 12; recordcount++; + /* Make background from a rectangle */ + background.type = 0x0000002b; // EMR_RECTANGLE; + background.size = 24; + background.box.top = 0; + background.box.left = 0; + background.box.right = emr_header.emf_header.bounds.right; + background.box.bottom = emr_header.emf_header.bounds.bottom; + bytecount += 24; + recordcount++; + + //Rectangles + rect = symbol->vector->rectangles; + this_rectangle = 0; + while (rect) { + rectangle[this_rectangle].type = 0x0000002b; // EMR_RECTANGLE; + rectangle[this_rectangle].size = 24; + rectangle[this_rectangle].box.top = rect->y; + rectangle[this_rectangle].box.bottom = rect->y + rect->height; + rectangle[this_rectangle].box.left = rect->x; + rectangle[this_rectangle].box.right = rect->x + rect->width; + this_rectangle++; + bytecount += 24; + recordcount++; + rect = rect->next; + } + + //Circles + circ = symbol->vector->circles; + this_circle = 0; + while (circ) { + radius = circ->diameter / 2.0; + circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE + circle[this_circle].size = 24; + circle[this_circle].box.top = circ->y - radius; + circle[this_circle].box.bottom = circ->y + radius; + circle[this_circle].box.left = circ->x - radius; + circle[this_circle].box.right = circ->x + radius; + this_circle++; + bytecount += 24; + recordcount++; + circ = circ->next; + } + + //Hexagons + hex = symbol->vector->hexagons; + this_hexagon = 0; + while (hex) { + hexagon[this_hexagon].type = 0x00000003; // EMR_POLYGON + hexagon[this_hexagon].size = 76; + hexagon[this_hexagon].count = 6; + + 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); + + hexagon[this_hexagon].a_points_a.x = ax; + hexagon[this_hexagon].a_points_a.y = ay; + hexagon[this_hexagon].a_points_b.x = bx; + hexagon[this_hexagon].a_points_b.y = by; + hexagon[this_hexagon].a_points_c.x = cx; + hexagon[this_hexagon].a_points_c.y = cy; + hexagon[this_hexagon].a_points_d.x = dx; + hexagon[this_hexagon].a_points_d.y = dy; + hexagon[this_hexagon].a_points_e.x = ex; + hexagon[this_hexagon].a_points_e.y = ey; + hexagon[this_hexagon].a_points_f.x = fx; + hexagon[this_hexagon].a_points_f.y = fy; + + hexagon[this_hexagon].bounds.top = hexagon[this_hexagon].a_points_d.y; + hexagon[this_hexagon].bounds.bottom = hexagon[this_hexagon].a_points_a.y; + hexagon[this_hexagon].bounds.left = hexagon[this_hexagon].a_points_e.x; + hexagon[this_hexagon].bounds.right = hexagon[this_hexagon].a_points_c.x; + this_hexagon++; + bytecount += 76; + recordcount++; + hex = hex->next; + } + /* Create font records */ - if ((symbol->show_hrt != 0) && (ustrlen(local_text) != 0)) { + if (symbol->vector->strings) { emr_extcreatefontindirectw.type = 0x00000052; // EMR_EXTCREATEFONTINDIRECTW emr_extcreatefontindirectw.size = 104; emr_extcreatefontindirectw.ih_fonts = 4; - emr_extcreatefontindirectw.elw.height = (8 * scaler); + emr_extcreatefontindirectw.elw.height = 16 * symbol->scale; emr_extcreatefontindirectw.elw.width = 0; // automatic emr_extcreatefontindirectw.elw.escapement = 0; emr_extcreatefontindirectw.elw.orientation = 0; @@ -436,566 +372,53 @@ int emf_plot(struct zint_symbol *symbol) { emr_extcreatefontindirectw.elw.clip_precision = 0x00; // CLIP_DEFAULT_PRECIS emr_extcreatefontindirectw.elw.quality = 0x00; emr_extcreatefontindirectw.elw.pitch_and_family = 0x00; - for(i = 0; i < 64; i++) { + for (i = 0; i < 64; i++) { emr_extcreatefontindirectw.elw.facename[i] = '\0'; } utfle_copy(emr_extcreatefontindirectw.elw.facename, (unsigned char*) "sans-serif", 10); + bytecount += 104; + recordcount++; emr_selectobject_font.type = 0x00000025; // EMR_SELECTOBJECT emr_selectobject_font.size = 12; emr_selectobject_font.ih_object = 4; - - if (!((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX))) { - bytecount += 104; - recordcount++; - bytecount += 12; - recordcount++; - } - - if (upcean) { - emr_extcreatefontindirectw_big.type = 0x00000052; // EMR_EXTCREATEFONTINDIRECTW - emr_extcreatefontindirectw_big.size = 104; - if (!((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX))) { - emr_extcreatefontindirectw_big.ih_fonts = 4; - } else { - emr_extcreatefontindirectw_big.ih_fonts = 5; - } - emr_extcreatefontindirectw_big.elw.height = (11 * scaler); - emr_extcreatefontindirectw_big.elw.width = 0; // automatic - emr_extcreatefontindirectw_big.elw.escapement = 0; - emr_extcreatefontindirectw_big.elw.orientation = 0; - emr_extcreatefontindirectw_big.elw.weight = 400; - emr_extcreatefontindirectw_big.elw.italic = 0x00; - emr_extcreatefontindirectw_big.elw.underline = 0x00; - emr_extcreatefontindirectw_big.elw.strike_out = 0x00; - emr_extcreatefontindirectw_big.elw.char_set = 0x01; - emr_extcreatefontindirectw_big.elw.out_precision = 0x00; // OUT_DEFAULT_PRECIS - emr_extcreatefontindirectw_big.elw.clip_precision = 0x00; // CLIP_DEFAULT_PRECIS - emr_extcreatefontindirectw_big.elw.quality = 0x00; - emr_extcreatefontindirectw_big.elw.pitch_and_family = 0x00; - for(i = 0; i < 64; i++) { - emr_extcreatefontindirectw_big.elw.facename[i] = '\0'; - } - utfle_copy(emr_extcreatefontindirectw_big.elw.facename, (unsigned char*) "sans-serif", 10); - bytecount += 104; - recordcount++; - - emr_selectobject_font_big.type = 0x00000025; // EMR_SELECTOBJECT - emr_selectobject_font_big.size = 12; - emr_selectobject_font_big.ih_object = 5; - bytecount += 12; - recordcount++; - } + bytecount += 12; + recordcount++; } - /* Text */ - if ((symbol->show_hrt != 0) && (ustrlen(local_text) != 0)) { - - if ((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX)) { - latch = ustrlen(local_text); - for(i = 0; i < ustrlen(local_text); i++) { - if (local_text[i] == '+') { - latch = i; - } - } - if (latch > 8) { - // EAN-13 - for(i = 1; i <= 6; i++) { - regw[i - 1] = local_text[i]; - regx[i - 1] = local_text[i + 6]; - } - if (ustrlen(local_text) > latch) { - // With add-on - for (i = (latch + 1); i <= ustrlen(local_text); i++) { - regz[i - (latch + 1)] = local_text[i]; - } - } - local_text[1] = '\0'; - } else if (latch > 5) { - // EAN-8 - for(i = 0; i <= 3; i++) { - regw[i] = local_text[i + 4]; - } - if (ustrlen(local_text) > latch) { - // With add-on - for (i = (latch + 1); i <= ustrlen(local_text); i++) { - regz[i - (latch + 1)] = local_text[i]; - } - } - local_text[4] = '\0'; - } - + //Text + str = symbol->vector->strings; + this_text = 0; + while (str) { + this_string[this_text] = malloc(bump_up(str->length + 1) * 2); + text[this_text].type = 0x00000054; // EMR_EXTTEXTOUTW + text[this_text].size = 76 + (6 * bump_up(str->length + 1)); + text[this_text].bounds.top = 0; // ignored + text[this_text].bounds.left = 0; // ignored + text[this_text].bounds.right = 0xffffffff; // ignored + text[this_text].bounds.bottom = 0xffffffff; // ignored + text[this_text].i_graphics_mode = 0x00000001; // GM_COMPATIBLE + text[this_text].ex_scale = 1.0; + text[this_text].ey_scale = 1.0; + text[this_text].w_emr_text.reference.x = str->x - (4 * str->length * symbol->scale); // text left + text[this_text].w_emr_text.reference.y = str->y - (16 * symbol->scale); // text top + text[this_text].w_emr_text.chars = str->length; + text[this_text].w_emr_text.off_string = 76; + text[this_text].w_emr_text.options = 0; + text[this_text].w_emr_text.rectangle.top = 0; + text[this_text].w_emr_text.rectangle.left = 0; + text[this_text].w_emr_text.rectangle.right = 0xffffffff; + text[this_text].w_emr_text.rectangle.bottom = 0xffffffff; + text[this_text].w_emr_text.off_dx = 76 + (2 * bump_up(str->length + 1)); + for (i = 0; i < bump_up(str->length + 1) * 2; i++) { + this_string[this_text][i] = '\0'; } - - if ((symbol->symbology == BARCODE_UPCA) || (symbol->symbology == BARCODE_UPCA_CC)) { - latch = ustrlen(local_text); - for(i = 0; i < ustrlen(local_text); i++) { - if (local_text[i] == '+') { - latch = i; - } - } - if (ustrlen(local_text) > latch) { - // With add-on - for (i = (latch + 1); i <= ustrlen(local_text); i++) { - regz[i - (latch + 1)] = local_text[i]; - } - } - for(i = 1; i <= 5; i++) { - regw[i - 1] = local_text[i]; - regx[i - 1] = local_text[i + 6]; - } - regy[0] = local_text[11]; - local_text[1] = '\0'; - } - - if ((symbol->symbology == BARCODE_UPCE) || (symbol->symbology == BARCODE_UPCE_CC)) { - latch = ustrlen(local_text); - for(i = 0; i < ustrlen(local_text); i++) { - if (local_text[i] == '+') { - latch = i; - } - } - if (ustrlen(local_text) > latch) { - // With add-on - for (i = (latch + 1); i <= ustrlen(local_text); i++) { - regz[i - (latch + 1)] = local_text[i]; - } - } - for(i = 1; i <= 6; i++) { - regw[i - 1] = local_text[i]; - } - regx[0] = local_text[7]; - local_text[1] = '\0'; - } - - for(i = 0; i <= 5; i++) { - emr_exttextoutw[i].type = 0x00000054; // EMR_EXTTEXTOUTW - emr_exttextoutw[i].bounds.top = 0; // ignored - emr_exttextoutw[i].bounds.left = 0; // ignoredemr_header.emf_header.bytes += - emr_exttextoutw[i].bounds.right = 0xffffffff; // ignored - emr_exttextoutw[i].bounds.bottom = 0xffffffff; // ignored - emr_exttextoutw[i].i_graphics_mode = 0x00000001; // GM_COMPATIBLE - emr_exttextoutw[i].ex_scale = 1.0; - emr_exttextoutw[i].ey_scale = 1.0; - emr_exttextoutw[i].w_emr_text.off_string = 76; - emr_exttextoutw[i].w_emr_text.options = 0; - emr_exttextoutw[i].w_emr_text.rectangle.top = 0; - emr_exttextoutw[i].w_emr_text.rectangle.left = 0; - emr_exttextoutw[i].w_emr_text.rectangle.right = 0xffffffff; - emr_exttextoutw[i].w_emr_text.rectangle.bottom = 0xffffffff; - if (i > 0) { - emr_exttextoutw[i].size = 76 + (6 * 6); - emr_exttextoutw[i].w_emr_text.off_dx = 76 + (2 * 6); - } - } - - emr_exttextoutw[0].w_emr_text.chars = ustrlen(local_text); - emr_exttextoutw[0].size = 76 + (6 * bump_up(ustrlen(local_text) + 1)); - emr_exttextoutw[0].w_emr_text.reference.x = (emr_header.emf_header.bounds.right - (ustrlen(local_text) * 5.3 * scaler)) / 2; // text left - emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler); // text top - emr_exttextoutw[0].w_emr_text.off_dx = 76 + (2 * bump_up(ustrlen(local_text) + 1)); - for (i = 0; i < bump_up(ustrlen(local_text) + 1) * 2; i++) { - string_buffer[i] = '\0'; - } - utfle_copy(string_buffer, local_text, ustrlen(local_text)); - bytecount += 76 + (6 * bump_up(ustrlen(local_text) + 1)); + utfle_copy(this_string[this_text], str->text, str->length); + bytecount += 76 + (6 * bump_up(str->length + 1)); recordcount++; - emr_exttextoutw[1].w_emr_text.chars = ustrlen(regw); - emr_exttextoutw[2].w_emr_text.chars = ustrlen(regx); - emr_exttextoutw[3].w_emr_text.chars = ustrlen(regy); - emr_exttextoutw[4].w_emr_text.chars = ustrlen(regz); - - if ((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX)) { - if (latch > 8) { - /* EAN-13 */ - emr_exttextoutw[0].w_emr_text.reference.x = (xoffset - 9) * scaler; - emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - emr_exttextoutw[1].w_emr_text.reference.x = (8 + xoffset) * scaler; - emr_exttextoutw[1].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - emr_exttextoutw[2].w_emr_text.reference.x = (55 + xoffset) * scaler; - emr_exttextoutw[2].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - if (ustrlen(regz) > 2) { - emr_exttextoutw[4].w_emr_text.reference.x = (115 + xoffset) * scaler; - bytecount += 112; - recordcount++; - } else if (ustrlen(regz) != 0) { - emr_exttextoutw[4].w_emr_text.reference.x = (109 + xoffset) * scaler; - bytecount += 112; - recordcount++; - } - emr_exttextoutw[4].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - ((large_bar_height + 9) * scaler); - bytecount += 2 * 112; - recordcount += 2; - } else if (latch > 5) { - /* EAN-8 */ - emr_exttextoutw[0].w_emr_text.reference.x = (7 + xoffset) * scaler; - emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - emr_exttextoutw[1].w_emr_text.reference.x = (40 + xoffset) * scaler; - emr_exttextoutw[1].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - if (ustrlen(regz) > 2) { - emr_exttextoutw[4].w_emr_text.reference.x = (87 + xoffset) * scaler; - bytecount += 112; - recordcount++; - } else if (ustrlen(regz) != 0) { - emr_exttextoutw[4].w_emr_text.reference.x = (81 + xoffset) * scaler; - bytecount += 112; - recordcount++; - } - emr_exttextoutw[4].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - ((large_bar_height + 9) * scaler); - bytecount += 112; - recordcount++; - } - } - - if ((symbol->symbology == BARCODE_UPCA) || (symbol->symbology == BARCODE_UPCA_CC)) { - emr_exttextoutw[0].w_emr_text.reference.x = (xoffset - 7) * scaler; - emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - emr_exttextoutw[1].w_emr_text.reference.x = (14 + xoffset) * scaler; - emr_exttextoutw[1].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - emr_exttextoutw[2].w_emr_text.reference.x = (55 + xoffset) * scaler; - emr_exttextoutw[2].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - emr_exttextoutw[3].w_emr_text.reference.x = (98 + xoffset) * scaler; - emr_exttextoutw[3].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - if (ustrlen(regz) > 2) { - emr_exttextoutw[4].w_emr_text.reference.x = (117 + xoffset) * scaler; - bytecount += 112; - recordcount++; - } else if (ustrlen(regz) != 0) { - emr_exttextoutw[4].w_emr_text.reference.x = (111 + xoffset) * scaler; - bytecount += 112; - recordcount++; - } - emr_exttextoutw[4].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - ((large_bar_height + 9) * scaler); - bytecount += (3 * 112) + 12; - recordcount += 4; - } - - if ((symbol->symbology == BARCODE_UPCE) || (symbol->symbology == BARCODE_UPCE_CC)) { - emr_exttextoutw[0].w_emr_text.reference.x = (xoffset - 7) * scaler; - emr_exttextoutw[0].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - emr_exttextoutw[1].w_emr_text.reference.x = (8 + xoffset) * scaler; - emr_exttextoutw[1].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - emr_exttextoutw[2].w_emr_text.reference.x = (53 + xoffset) * scaler; - emr_exttextoutw[2].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - (9 * scaler);; - if (ustrlen(regz) > 2) { - emr_exttextoutw[4].w_emr_text.reference.x = (71 + xoffset) * scaler; - bytecount += 112; - recordcount++; - } else if (ustrlen(regz) != 0) { - emr_exttextoutw[4].w_emr_text.reference.x = (65 + xoffset) * scaler; - bytecount += 112; - recordcount++; - } - emr_exttextoutw[4].w_emr_text.reference.y = emr_header.emf_header.bounds.bottom - ((large_bar_height + 9) * scaler); - bytecount += (2 * 112) + 12; - recordcount += 3; - } - } - - /* Make background from a rectangle */ - background.type = 0x0000002b; // EMR_RECTANGLE; - background.size = 24; - background.box.top = 0; - background.box.left = 0; - background.box.right = emr_header.emf_header.bounds.right; - background.box.bottom = emr_header.emf_header.bounds.bottom; - bytecount += 24; - recordcount++; - - /* Make bind and box rectangles if needed */ - if ((symbol->output_options & BARCODE_BIND) || (symbol->output_options & BARCODE_BOX)) { - box.top.type = 0x0000002b; // EMR_RECTANGLE; - box.top.size = 24; - box.top.box.top = 0; - box.top.box.bottom = symbol->border_width * scaler; - box.top.box.left = symbol->border_width * scaler; - box.top.box.right = emr_header.emf_header.bounds.right - (symbol->border_width * scaler); - bytecount += 24; - recordcount++; - - box.bottom.type = 0x0000002b; // EMR_RECTANGLE; - box.bottom.size = 24; - box.bottom.box.top = emr_header.emf_header.bounds.bottom - ((symbol->border_width + textoffset) * scaler); - box.bottom.box.bottom = emr_header.emf_header.bounds.bottom - (textoffset * scaler); - box.bottom.box.left = symbol->border_width * scaler; - box.bottom.box.right = emr_header.emf_header.bounds.right - (symbol->border_width * scaler); - bytecount += 24; - recordcount++; - - if (symbol->output_options & BARCODE_BOX) { - box.left.type = 0x0000002b; // EMR_RECTANGLE; - box.left.size = 24; - box.left.box.top = 0; - box.left.box.bottom = emr_header.emf_header.bounds.bottom - (textoffset * scaler); - box.left.box.left = 0; - box.left.box.right = symbol->border_width * scaler; - bytecount += 24; - recordcount++; - - box.right.type = 0x0000002b; // EMR_RECTANGLE; - box.right.size = 24; - box.right.box.top = 0; - box.right.box.bottom = emr_header.emf_header.bounds.bottom - (textoffset * scaler); - box.right.box.left = emr_header.emf_header.bounds.right - (symbol->border_width * scaler); - box.right.box.right = emr_header.emf_header.bounds.right; - bytecount += 24; - recordcount++; - } - } - - /* Make image rectangles, circles, hexagons */ - for (this_row = 0; this_row < symbol->rows; this_row++) { - float row_posn; - - 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 < this_row; i++) { - if (symbol->row_height[i] == 0) { - row_posn += large_bar_height; - } else { - row_posn += symbol->row_height[i]; - } - } - row_posn += yoffset; - - if (symbol->symbology != BARCODE_MAXICODE) { - if ((symbol->output_options & BARCODE_DOTTY_MODE) != 0) { - // Use dots (circles) - for(i = 0; i < symbol->width; i++) { - if(module_is_set(symbol, this_row, i)) { - circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE - circle[this_circle].size = 24; - circle[this_circle].box.top = this_row * scaler; - circle[this_circle].box.bottom = (this_row + 1) * scaler; - circle[this_circle].box.left = (i + xoffset) * scaler; - circle[this_circle].box.right = (i + xoffset + 1) * scaler; - this_circle++; - bytecount += 24; - recordcount++; - } - } - } 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 (latch == 1) { - /* a bar */ - rectangle[this_rectangle].type = 0x0000002b; // EMR_RECTANGLE; - rectangle[this_rectangle].size = 24; - rectangle[this_rectangle].box.top = row_posn * scaler; - rectangle[this_rectangle].box.bottom = (row_posn + row_height) * scaler; - rectangle[this_rectangle].box.left = (i + xoffset) * scaler; - rectangle[this_rectangle].box.right = (i + xoffset + block_width) * scaler; - bytecount += 24; - recordcount++; - - if (this_row == symbol->rows - 1) { - /* Last row, extend bars if needed */ - if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) || - (symbol->symbology == BARCODE_ISBNX)) { - /* guard bar extensions for EAN8 and EAN13 */ - if (ustrlen(regx) != 0) { - /* EAN-13 */ - switch (i) { - case 0: - case 2: - case 46: - case 48: - case 92: - case 94: - rectangle[this_rectangle].box.bottom += (5 * scaler); - break; - } - if (i > 94) { - /* Add-on */ - rectangle[this_rectangle].box.top += (10 * scaler); - rectangle[this_rectangle].box.bottom += (5 * scaler); - } - } else if (ustrlen(regw) != 0) { - /* EAN-8 */ - switch (i) { - case 0: - case 2: - case 32: - case 34: - case 64: - case 66: - rectangle[this_rectangle].box.bottom += (5 * scaler); - break; - } - if (i > 66) { - /* Add-on */ - rectangle[this_rectangle].box.top += (10 * scaler); - rectangle[this_rectangle].box.bottom += (5 * scaler); - } - } - } - if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) { - /* guard bar extensions for UPCA */ - if (((i >= 0) && (i <= 11)) || ((i >= 85) && (i <= 96))) { - rectangle[this_rectangle].box.bottom += (5 * scaler); - } - if ((i == 46) || (i == 48)) { - rectangle[this_rectangle].box.bottom += (5 * scaler); - } - if (i > 96) { - /* Add-on */ - rectangle[this_rectangle].box.top += (10 * scaler); - rectangle[this_rectangle].box.bottom += (5 * scaler); - } - } - - if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) { - /* guard bar extensions for UPCE */ - switch (i) { - case 0: - case 2: - case 46: - case 48: - case 50: - rectangle[this_rectangle].box.bottom += (5 * scaler); - break; - } - if (i > 50) { - /* Add-on */ - rectangle[this_rectangle].box.top += (10 * scaler); - rectangle[this_rectangle].box.bottom += (5 * scaler); - } - } - } - - this_rectangle++; - latch = 0; - } else { - /* a space */ - latch = 1; - } - - - i += block_width; - } while (i < symbol->width); - } - } else { - float ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy, mx, my; - /* Maxicode, use hexagons */ - - /* Calculate bullseye */ - for(i = 0; i < 6; i++) { - bullseye[i].type = 0x0000002a; // EMR_ELLIPSE - bullseye[i].size = 24; - } - bullseye[0].box.top = (35.60 - 10.85) * scaler; - bullseye[0].box.bottom = (35.60 + 10.85) * scaler; - bullseye[0].box.left = (35.76 - 10.85) * scaler; - bullseye[0].box.right = (35.76 + 10.85) * scaler; - bullseye[1].box.top = (35.60 - 8.97) * scaler; - bullseye[1].box.bottom = (35.60 + 8.97) * scaler; - bullseye[1].box.left = (35.76 - 8.97) * scaler; - bullseye[1].box.right = (35.76 + 8.97) * scaler; - bullseye[2].box.top = (35.60 - 7.10) * scaler; - bullseye[2].box.bottom = (35.60 + 7.10) * scaler; - bullseye[2].box.left = (35.76 - 7.10) * scaler; - bullseye[2].box.right = (35.76 + 7.10) * scaler; - bullseye[3].box.top = (35.60 - 5.22) * scaler; - bullseye[3].box.bottom = (35.60 + 5.22) * scaler; - bullseye[3].box.left = (35.76 - 5.22) * scaler; - bullseye[3].box.right = (35.76 + 5.22) * scaler; - bullseye[4].box.top = (35.60 - 3.31) * scaler; - bullseye[4].box.bottom = (35.60 + 3.31) * scaler; - bullseye[4].box.left = (35.76 - 3.31) * scaler; - bullseye[4].box.right = (35.76 + 3.31) * scaler; - bullseye[5].box.top = (35.60 - 1.43) * scaler; - bullseye[5].box.bottom = (35.60 + 1.43) * scaler; - bullseye[5].box.left = (35.76 - 1.43) * scaler; - bullseye[5].box.right = (35.76 + 1.43) * scaler; - - /* Plot hexagons */ - for(i = 0; i < symbol->width; i++) { - if(module_is_set(symbol, this_row, i)) { - hexagon[this_hexagon].type = 0x00000003; // EMR_POLYGON - hexagon[this_hexagon].size = 76; - hexagon[this_hexagon].count = 6; - - my = this_row * 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 (this_row & 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; - - hexagon[this_hexagon].a_points_a.x = ax * scaler; - hexagon[this_hexagon].a_points_a.y = ay * scaler; - hexagon[this_hexagon].a_points_b.x = bx * scaler; - hexagon[this_hexagon].a_points_b.y = by * scaler; - hexagon[this_hexagon].a_points_c.x = cx * scaler; - hexagon[this_hexagon].a_points_c.y = cy * scaler; - hexagon[this_hexagon].a_points_d.x = dx * scaler; - hexagon[this_hexagon].a_points_d.y = dy * scaler; - hexagon[this_hexagon].a_points_e.x = ex * scaler; - hexagon[this_hexagon].a_points_e.y = ey * scaler; - hexagon[this_hexagon].a_points_f.x = fx * scaler; - hexagon[this_hexagon].a_points_f.y = fy * scaler; - - hexagon[this_hexagon].bounds.top = hexagon[this_hexagon].a_points_d.y; - hexagon[this_hexagon].bounds.bottom = hexagon[this_hexagon].a_points_a.y; - hexagon[this_hexagon].bounds.left = hexagon[this_hexagon].a_points_e.x; - hexagon[this_hexagon].bounds.right = hexagon[this_hexagon].a_points_c.x; - this_hexagon++; - bytecount += 76; - recordcount++; - } - } - } - } - - if (symbol->output_options & BARCODE_BIND) { - if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) { - /* row binding */ - for (i = 1; i < symbol->rows; i++) { - row_binding[i - 1].type = 0x0000002b; // EMR_RECTANGLE; - row_binding[i - 1].size = 24; - row_binding[i - 1].box.top = ((i * row_height) + yoffset - 1) * scaler; - row_binding[i - 1].box.bottom = row_binding[i - 1].box.top + (2 * scaler); - - if (symbol->symbology != BARCODE_CODABLOCKF) { - row_binding[i - 1].box.left = xoffset * scaler; - row_binding[i - 1].box.right = emr_header.emf_header.bounds.right - (xoffset * scaler); - } else { - row_binding[i - 1].box.left = (xoffset + 11) * scaler; - row_binding[i - 1].box.right = emr_header.emf_header.bounds.right - ((xoffset + 14) * scaler); - } - bytecount += 24; - recordcount++; - } - } + this_text++; + str = str->next; } /* Create EOF record */ @@ -1007,6 +430,11 @@ int emf_plot(struct zint_symbol *symbol) { bytecount += 18; recordcount++; + if (symbol->symbology == BARCODE_MAXICODE) { + bytecount += 5 * sizeof (emr_selectobject_t); + recordcount += 5; + } + /* Put final counts in header */ emr_header.emf_header.bytes = bytecount; emr_header.emf_header.records = recordcount; @@ -1022,198 +450,63 @@ int emf_plot(struct zint_symbol *symbol) { return ZINT_ERROR_FILE_ACCESS; } - fwrite(&emr_header, sizeof(emr_header_t), 1, emf_file); + fwrite(&emr_header, sizeof (emr_header_t), 1, emf_file); - fwrite(&emr_createbrushindirect_fg, sizeof(emr_createbrushindirect_t), 1, emf_file); - fwrite(&emr_createbrushindirect_bg, sizeof(emr_createbrushindirect_t), 1, emf_file); - fwrite(&emr_createpen, sizeof(emr_createpen_t), 1, emf_file); + fwrite(&emr_createbrushindirect_fg, sizeof (emr_createbrushindirect_t), 1, emf_file); + fwrite(&emr_createbrushindirect_bg, sizeof (emr_createbrushindirect_t), 1, emf_file); + fwrite(&emr_createpen, sizeof (emr_createpen_t), 1, emf_file); - if ((symbol->show_hrt != 0) && (ustrlen(local_text) != 0)) { - fwrite(&emr_extcreatefontindirectw, sizeof(emr_extcreatefontindirectw_t), 1, emf_file); + if (symbol->vector->strings) { + fwrite(&emr_extcreatefontindirectw, sizeof (emr_extcreatefontindirectw_t), 1, emf_file); } - fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&emr_selectobject_pen, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&background, sizeof(emr_rectangle_t), 1, emf_file); + fwrite(&emr_selectobject_bgbrush, sizeof (emr_selectobject_t), 1, emf_file); + fwrite(&emr_selectobject_pen, sizeof (emr_selectobject_t), 1, emf_file); + fwrite(&background, sizeof (emr_rectangle_t), 1, emf_file); - fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file); + fwrite(&emr_selectobject_fgbrush, sizeof (emr_selectobject_t), 1, emf_file); + // Rectangles for (i = 0; i < rectangle_count; i++) { - fwrite(&rectangle[i], sizeof(emr_rectangle_t), 1, emf_file); - } - for (i = 0; i < circle_count; i++) { - fwrite(&circle[i], sizeof(emr_ellipse_t), 1, emf_file); + fwrite(&rectangle[i], sizeof (emr_rectangle_t), 1, emf_file); } + + // Hexagons for (i = 0; i < hexagon_count; i++) { - fwrite(&hexagon[i], sizeof(emr_polygon_t), 1, emf_file); + fwrite(&hexagon[i], sizeof (emr_polygon_t), 1, emf_file); } - if ((symbol->output_options & BARCODE_BIND) || (symbol->output_options & BARCODE_BOX)) { - fwrite(&box.top, sizeof(emr_rectangle_t), 1, emf_file); - fwrite(&box.bottom, sizeof(emr_rectangle_t), 1, emf_file); - if (symbol->output_options & BARCODE_BOX) { - fwrite(&box.left, sizeof(emr_rectangle_t), 1, emf_file); - fwrite(&box.right, sizeof(emr_rectangle_t), 1, emf_file); + // Circles + if (symbol->symbology == BARCODE_MAXICODE) { + // Bullseye needed + for (i = 0; i < circle_count; i++) { + fwrite(&circle[i], sizeof (emr_ellipse_t), 1, emf_file); + if (i < circle_count - 1) { + if (i % 2) { + fwrite(&emr_selectobject_fgbrush, sizeof (emr_selectobject_t), 1, emf_file); + } else { + fwrite(&emr_selectobject_bgbrush, sizeof (emr_selectobject_t), 1, emf_file); + } + } + } + } else { + for (i = 0; i < circle_count; i++) { + fwrite(&circle[i], sizeof (emr_ellipse_t), 1, emf_file); } } - if (symbol->output_options & BARCODE_BIND) { - if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) { - for(i = 0; i < symbol->rows - 1; i++) { - fwrite(&row_binding[i], sizeof(emr_rectangle_t), 1, emf_file); - } + // Text + for (i = 0; i < string_count; i++) { + spacing = 8 * symbol->scale; + fwrite(&emr_selectobject_font, sizeof (emr_selectobject_t), 1, emf_file); + fwrite(&text[i], sizeof (emr_exttextoutw_t), 1, emf_file); + fwrite(this_string[i], bump_up(text[i].w_emr_text.chars + 1) * 2, 1, emf_file); + for (int j = 0; j < bump_up(text[i].w_emr_text.chars + 1); j++) { + fwrite(&spacing, 4, 1, emf_file); } } - if(symbol->symbology == BARCODE_MAXICODE) { - fwrite(&bullseye[0], sizeof(emr_ellipse_t), 1, emf_file); - fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&bullseye[1], sizeof(emr_ellipse_t), 1, emf_file); - fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&bullseye[2], sizeof(emr_ellipse_t), 1, emf_file); - fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&bullseye[3], sizeof(emr_ellipse_t), 1, emf_file); - fwrite(&emr_selectobject_fgbrush, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&bullseye[4], sizeof(emr_ellipse_t), 1, emf_file); - fwrite(&emr_selectobject_bgbrush, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&bullseye[5], sizeof(emr_ellipse_t), 1, emf_file); - } - - if ((symbol->show_hrt != 0) && (ustrlen(local_text) != 0)) { - if ((symbol->symbology == BARCODE_EANX) || (symbol->symbology == BARCODE_EANX_CC) || (symbol->symbology == BARCODE_ISBNX)) { - if (ustrlen(regx) != 0) { - /* EAN-13 */ - fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file); - fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file); - for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) { - fwrite(&dx, 4, 1, emf_file); - } - fwrite(&emr_exttextoutw[1], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regw, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - fwrite(&emr_exttextoutw[2], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regx, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - if (ustrlen(regz) != 0) { - fwrite(&emr_exttextoutw[4], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regz, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - } - textdone = 1; - } else if (ustrlen(regw) != 0) { - /* EAN-8 */ - fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file); - fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file); - for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) { - fwrite(&dx, 4, 1, emf_file); - } - fwrite(&emr_exttextoutw[1], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regw, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - if (ustrlen(regz) != 0) { - fwrite(&emr_exttextoutw[4], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regz, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - } - textdone = 1; - } - } - if ((symbol->symbology == BARCODE_UPCA) || (symbol->symbology == BARCODE_UPCA_CC)) { - fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file); - fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file); - for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) { - fwrite(&dx, 4, 1, emf_file); - } - fwrite(&emr_exttextoutw[3], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regy, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - fwrite(&emr_selectobject_font_big, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&emr_exttextoutw[1], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regw, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - fwrite(&emr_exttextoutw[2], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regx, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - if (ustrlen(regz) != 0) { - fwrite(&emr_exttextoutw[4], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regz, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - } - textdone = 1; - } - - if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) { - fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file); - fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file); - for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) { - fwrite(&dx, 4, 1, emf_file); - } - fwrite(&emr_exttextoutw[2], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regx, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - fwrite(&emr_selectobject_font_big, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&emr_exttextoutw[1], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regw, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - if (ustrlen(regz) != 0) { - fwrite(&emr_exttextoutw[4], sizeof(emr_exttextoutw_t), 1, emf_file); - utfle_copy(output_buffer, regz, 6); - fwrite(&output_buffer, 12, 1, emf_file); - for (i = 0; i < 6; i++) { - fwrite(&dx, 4, 1, emf_file); - } - } - textdone = 1; - } - - if (textdone == 0) { - fwrite(&emr_selectobject_font, sizeof(emr_selectobject_t), 1, emf_file); - fwrite(&emr_exttextoutw[0], sizeof(emr_exttextoutw_t), 1, emf_file); - fwrite(&string_buffer, 2 * bump_up(ustrlen(local_text) + 1), 1, emf_file); - for (i = 0; i < bump_up(ustrlen(local_text) + 1); i++) { - fwrite(&dx, 4, 1, emf_file); - } - } - } - - fwrite(&emr_eof, sizeof(emr_eof_t), 1, emf_file); + fwrite(&emr_eof, sizeof (emr_eof_t), 1, emf_file); if (symbol->output_options & BARCODE_STDOUT) { fflush(emf_file); @@ -1222,5 +515,3 @@ int emf_plot(struct zint_symbol *symbol) { } return error_number; } - - diff --git a/backend/library.c b/backend/library.c index e182992c..d7f28eaa 100644 --- a/backend/library.c +++ b/backend/library.c @@ -1,7 +1,7 @@ /* library.c - external functions of libzint libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009-2018 Robin Stuart 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); diff --git a/backend/ps.c b/backend/ps.c index cdf59cec..f2185f4a 100644 --- a/backend/ps.c +++ b/backend/ps.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009-2018 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -37,68 +37,21 @@ #include #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, "%%%%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,644 +148,86 @@ 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); + fprintf(feps, "%.2f 0.00 TB 0.00 %.2f TR\n", symbol->vector->height, symbol->vector->width); - 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, "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 ", row_height * scaler, row_posn * scaler); - 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 == 0) && (i > main_width)) { - 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 ", (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; - } - 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; - } - - 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); - } - 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, "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"); - 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; - - } - } - - 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, "TE\n"); + if ((symbol->output_options & CMYK_COLOUR) == 0) { 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; - } - + } else { + fprintf(feps, "%.2f %.2f %.2f %.2f setcmykcolor\n", cyan_ink, magenta_ink, yellow_ink, black_ink); } - - 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); - } - } - } + + // 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; + } + + // 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); } - if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) { - fprintf(feps, "TE\n"); + 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); } - 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); + // A 'black' circle + fprintf(feps, "%.2f %.2f %.2f TD\n", circle->x, (symbol->vector->height - circle->y), circle->diameter / 2.0); } + circle = circle->next; + } + + // Text + string = symbol->vector->strings; + while (string) { 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, "%.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", local_text); + fprintf(feps, " (%s) show\n", string->text); fprintf(feps, "setmatrix\n"); + string = string->next; } + 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; } - - diff --git a/backend/svg.c b/backend/svg.c index 15df31ae..5c40d6fb 100644 --- a/backend/svg.c +++ b/backend/svg.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009-2018 Robin Stuart 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 - - 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; - } - } + 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; 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, "\n"); fprintf(fsvg, "\n"); - if (symbol->symbology != BARCODE_MAXICODE) { - fprintf(fsvg, "width + xoffset + xoffset) * scaler), (int) ceil((symbol->height + textoffset + yoffset + yoffset) * scaler)); - } else { - fprintf(fsvg, "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, " %s\n", local_text); - } else { - fprintf(fsvg, " Zint Generated Symbol\n"); - } + fprintf(fsvg, " Zint Generated Symbol\n"); fprintf(fsvg, " \n"); fprintf(fsvg, "\n \n", symbol->fgcolour); - if (symbol->symbology != BARCODE_MAXICODE) { - fprintf(fsvg, " \n", (int) ceil((symbol->width + xoffset + xoffset) * scaler), (int) ceil((symbol->height + textoffset + yoffset + yoffset) * scaler), symbol->bgcolour); - } else { - fprintf(fsvg, " \n", (int) ceil((74.0F + xoffset + xoffset) * scaler), (int) ceil((72.0F + yoffset + yoffset) * scaler), symbol->bgcolour); + fprintf(fsvg, " \n", (int) ceil(symbol->vector->width), (int) ceil(symbol->vector->height), symbol->bgcolour); + + + rect = symbol->vector->rectangles; + while (rect) { + fprintf(fsvg, " \n", rect->x, rect->y, rect->width, rect->height); + rect = rect->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; + + 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, " \n", ax, ay, bx, by, cx, cy, dx, dy, ex, ey, fx, fy); + hex = hex->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, " \n", 0.0, 0.0, (74.0 + xoffset + xoffset) * scaler, symbol->border_width * scaler); - fprintf(fsvg, " \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, " \n", 0.0, 0.0, symbol->border_width * scaler, (72.0 + (2 * symbol->border_width)) * scaler); - fprintf(fsvg, " \n", (74.0 + xoffset + xoffset - symbol->border_width) * scaler, 0.0, symbol->border_width * scaler, (72.0 + (2 * symbol->border_width)) * scaler); - } - fprintf(fsvg, " \n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 10.85 * scaler, symbol->fgcolour); - fprintf(fsvg, " \n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 8.97 * scaler, symbol->bgcolour); - fprintf(fsvg, " \n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 7.10 * scaler, symbol->fgcolour); - fprintf(fsvg, " \n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 5.22 * scaler, symbol->bgcolour); - fprintf(fsvg, " \n", (35.76 + xoffset) * scaler, (35.60 + yoffset) * scaler, 3.31 * scaler, symbol->fgcolour); - fprintf(fsvg, " \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, " \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); - } - } + + circle = symbol->vector->circles; + while (circle) { + if (circle->colour) { + fprintf(fsvg, " \n", circle->x, circle->y, circle->diameter / 2.0, symbol->bgcolour); + } else { + fprintf(fsvg, " \n", circle->x, circle->y, circle->diameter / 2.0, symbol->fgcolour); } + circle = circle->next; } - - 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, " \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, " \n", (i + xoffset) * scaler, row_posn * scaler, block_width * scaler, row_height * scaler); - } else { - fprintf(fsvg, " \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, " \n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (32 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (34 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (64 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \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, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - for (i = 0; i < 4; i++) { - textpart[i] = local_text[i + 4]; - } - textpart[4] = '\0'; - textpos = 50; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - textdone = 1; - switch (strlen(addon)) { - case 2: - textpos = xoffset + 86; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", addon); - fprintf(fsvg, " \n"); - break; - case 5: - textpos = xoffset + 100; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", addon); - fprintf(fsvg, " \n"); - break; - } - - break; - case 13: /* EAN 13 */ - case 16: - case 19: - fprintf(fsvg, " \n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (48 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (92 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (94 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - textpart[0] = local_text[0]; - textpart[1] = '\0'; - textpos = -7; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - for (i = 0; i < 6; i++) { - textpart[i] = local_text[i + 1]; - } - textpart[6] = '\0'; - textpos = 24; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - for (i = 0; i < 6; i++) { - textpart[i] = local_text[i + 7]; - } - textpart[6] = '\0'; - textpos = 71; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - textdone = 1; - switch (strlen(addon)) { - case 2: - textpos = xoffset + 114; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", addon); - fprintf(fsvg, " \n"); - break; - case 5: - textpos = xoffset + 128; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", addon); - fprintf(fsvg, " \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, " \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, " \n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \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, " \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, " \n", fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); + + string = symbol->vector->strings; + while (string) { + fprintf(fsvg, " 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, " \n"); - for (i = 0; i < 5; i++) { - textpart[i] = local_text[i + 1]; - } - textpart[5] = '\0'; - textpos = 27; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - for (i = 0; i < 5; i++) { - textpart[i] = local_text[i + 6]; - } - textpart[6] = '\0'; - textpos = 68; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - textpart[0] = local_text[11]; - textpart[1] = '\0'; - textpos = 100; - fprintf(fsvg, " \n", fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - textdone = 1; - switch (strlen(addon)) { - case 2: - textpos = xoffset + 116; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", addon); - fprintf(fsvg, " \n"); - break; - case 5: - textpos = xoffset + 130; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", addon); - fprintf(fsvg, " \n"); - break; - } - + string = string->next; } - if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) { - /* guard bar extensions and text formatting for UPCE */ - fprintf(fsvg, " \n", (0 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (2 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (46 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (48 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - fprintf(fsvg, " \n", (50 + xoffset) * scaler, row_posn, scaler, 5.0 * scaler); - textpart[0] = local_text[0]; - textpart[1] = '\0'; - textpos = -5; - fprintf(fsvg, " \n", fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - for (i = 0; i < 6; i++) { - textpart[i] = local_text[i + 1]; - } - textpart[6] = '\0'; - textpos = 24; - fprintf(fsvg, " \n", (11.0 / 8.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - textpart[0] = local_text[7]; - textpart[1] = '\0'; - textpos = 55; - fprintf(fsvg, " \n", fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", textpart); - fprintf(fsvg, " \n"); - textdone = 1; - switch (strlen(addon)) { - case 2: - textpos = xoffset + 70; - fprintf(fsvg, " \n", (8.0 / 11.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", addon); - fprintf(fsvg, " \n"); - break; - case 5: - textpos = xoffset + 84; - fprintf(fsvg, " \n", (8.0 / 11.0) * fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", addon); - fprintf(fsvg, " \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, " \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, " \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, " \n", 0.0, 0.0, (symbol->width + xoffset + xoffset) * scaler, symbol->border_width * scaler); - fprintf(fsvg, " \n", 0.0, (symbol->height + symbol->border_width) * scaler, (symbol->width + xoffset + xoffset) * scaler, symbol->border_width * scaler); - } else { - fprintf(fsvg, " \n", xoffset * scaler, 0.0, symbol->width * scaler, symbol->border_width * scaler); - fprintf(fsvg, " \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, " \n", 0.0, 0.0, symbol->border_width * scaler, (symbol->height + (2 * symbol->border_width)) * scaler); - fprintf(fsvg, " \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, " \n", fontsize, symbol->fgcolour); - fprintf(fsvg, " %s\n", local_text); - fprintf(fsvg, " \n"); - } fprintf(fsvg, " \n"); fprintf(fsvg, "\n"); @@ -678,4 +136,3 @@ int svg_plot(struct zint_symbol *symbol) { return error_number; } - diff --git a/backend/vector.c b/backend/vector.c new file mode 100644 index 00000000..f6f9fd65 --- /dev/null +++ b/backend/vector.c @@ -0,0 +1,861 @@ +/* vector.c - Creates vector image objects + + libzint - the open source barcode library + Copyright (C) 2018 Robin Stuart + + 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 +#include +#include +#include + +#ifdef _MSC_VER +#include +#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; + +} diff --git a/backend/zint.h b/backend/zint.h index 1b78b241..a4030e07 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -1,7 +1,7 @@ /* zint.h - definitions for libzint libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009-2018 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -40,6 +40,12 @@ extern "C" { float x, y, length, width; 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; @@ -48,17 +54,36 @@ extern "C" { unsigned char *text; 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 */ @@ -66,6 +91,14 @@ extern "C" { struct zint_render_ring *rings; /* Pointer to first ring */ 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; @@ -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