diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..2c91bd37 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build/ +*.swp +*.swo diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 57a819ed..6159679c 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -4,7 +4,7 @@ project(zint) find_package(PNG) -set(zint_COMMON_SRCS common.c library.c ps.c large.c reedsol.c gs1.c svg.c png.c) +set(zint_COMMON_SRCS common.c library.c render.c ps.c large.c reedsol.c gs1.c svg.c png.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) set(zint_TWODIM_SRCS code16k.c dmatrix.c dm200.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c) diff --git a/backend/Makefile b/backend/Makefile index a27179c5..4534b46d 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -18,8 +18,8 @@ includedir := $(prefix)/include libdir := $(prefix)/lib DESTDIR := -COMMON:= common.c png.c library.c ps.c large.c reedsol.c gs1.c svg.c -COMMON_OBJ:= common.o png.o library.o ps.o large.o reedsol.o gs1.o svg.o +COMMON:= common.c render.c png.c library.c ps.c large.c reedsol.c gs1.c svg.c +COMMON_OBJ:= common.o render.o png.o library.o ps.o large.o reedsol.o gs1.o svg.o ONEDIM:= code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c ONEDIM_OBJ:= code.o code128.o 2of5.o upcean.o telepen.o medical.o plessey.o rss.o POSTAL:= postal.c auspost.c imail.c @@ -28,7 +28,7 @@ TWODIM:= code16k.c dmatrix.c dm200.c pdf417.c qr.c maxicode.c composite.c aztec. TWODIM_OBJ:= code16k.o dmatrix.o dm200.o pdf417.o qr.o maxicode.o composite.o aztec.o code49.o code1.o gridmtx.o LIBS:= `libpng12-config --I_opts --L_opts --ldflags` -lz -lm -libzint: code.c code128.c 2of5.c upcean.c medical.c telepen.c plessey.c postal.c auspost.c imail.c code16k.c dmatrix.c dm200.c reedsol.c pdf417.c maxicode.c rss.c common.c png.c library.c ps.c qr.c large.c composite.c aztec.c gs1.c svg.c code49.c code1.c gridmtx.c +libzint: code.c code128.c 2of5.c upcean.c medical.c telepen.c plessey.c postal.c auspost.c imail.c code16k.c dmatrix.c dm200.c reedsol.c pdf417.c maxicode.c rss.c common.c render.c png.c library.c ps.c qr.c large.c composite.c aztec.c gs1.c svg.c code49.c code1.c gridmtx.c $(CC) -Wall -fPIC $(CFLAGS) $(ZINT_VERSION) -c $(ONEDIM) $(CC) -Wall -fPIC $(CFLAGS) $(ZINT_VERSION) -c $(POSTAL) $(CC) -Wall -fPIC $(CFLAGS) $(ZINT_VERSION) -c $(TWODIM) diff --git a/backend/Makefile.mingw b/backend/Makefile.mingw index 5cb0e83b..9e0977fc 100644 --- a/backend/Makefile.mingw +++ b/backend/Makefile.mingw @@ -24,7 +24,7 @@ APP:=zint DLL:=$(APP).dll STATLIB:=lib$(APP).a -COMMON_OBJ:= common.o png.o library.o ps.o large.o reedsol.o gs1.o svg.o +COMMON_OBJ:= common.o render.o png.o library.o ps.o large.o reedsol.o gs1.o svg.o ONEDIM_OBJ:= code.o code128.o 2of5.o upcean.o telepen.o medical.o plessey.o rss.o POSTAL_OBJ:= postal.o auspost.o imail.o TWODIM_OBJ:= code16k.o dmatrix.o dm200.o pdf417.o qr.o maxicode.o composite.o aztec.o code49.o code1.o gridmtx.o diff --git a/backend/library.c b/backend/library.c index c2dc570d..a8fff727 100644 --- a/backend/library.c +++ b/backend/library.c @@ -92,6 +92,30 @@ void ZBarcode_Delete(struct zint_symbol *symbol) { if (symbol->bitmap != NULL) free(symbol->bitmap); + + // If there is a rendered version, ensure it's memory is released + if (symbol->rendered != NULL) { + struct zint_render_line *line, *l; + struct zint_render_char *bchar, *bc; + + // Free lines + line = symbol->rendered->lines; + while(line) { + l = line; + line = line->next; + free(l); + } + // Free Chars + bchar = symbol->rendered->chars; + while (bchar) { + bc = bchar; + bchar = bchar->next; + free(bc); + } + + // Free Render + free(symbol->rendered); + } free(symbol); } @@ -154,6 +178,8 @@ extern int grid_matrix(struct zint_symbol *symbol, unsigned char source[], int l extern int png_handle(struct zint_symbol *symbol, int rotate_angle); #endif +extern int render_plot(struct zint_symbol *symbol, unsigned int hide_text); + extern int bmp_handle(struct zint_symbol *symbol, int rotate_angle); extern int ps_plot(struct zint_symbol *symbol); extern int svg_plot(struct zint_symbol *symbol); @@ -835,3 +861,15 @@ int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename, return ZBarcode_Buffer(symbol, rotate_angle); } + +/* + * Rendering support, initially added by Sam Lown. + * + * Converts encoded data into an intermediate format to be interpreted + * in other applications using this library. + */ +int ZBarcode_Render(struct zint_symbol *symbol, unsigned int hide_text) +{ + // Send the request to the render_plot method + return render_plot(symbol, hide_text); +} diff --git a/backend/render.c b/backend/render.c new file mode 100644 index 00000000..ba126c9f --- /dev/null +++ b/backend/render.c @@ -0,0 +1,212 @@ +/* + * render.c - Generic Rendered Format + * + * Initiall written by Sam Lown for use in gLabels. Converts encoded + * data into a generic internal structure of lines and characters + * usable in external applications. + */ + +/* + libzint - the open source barcode library + Copyright (C) 2009 Robin Stuart + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include +#include "common.h" + +int render_plot(struct zint_symbol *symbol, unsigned int hide_text) +{ + struct zint_render *render; + struct zint_render_line *line, *last_line = NULL; + struct zint_render_char *bchar, *last_bchar = NULL; + + int i, r, block_width, latch, this_row; + float textpos, large_bar_height, preset_height, row_height, row_posn = 0.0; + // int error_number = 0; + int textoffset, textheight, xoffset, yoffset, textdone, main_width; + char addon[6]; //, textpart[10]; + int large_bar_count, comp_offset; + float addon_text_posn; + float default_text_posn; + float scaler = symbol->scale; + unsigned char *p; + + // Allocate memory for the rendered version + render = symbol->rendered = malloc(sizeof(struct zint_render)); + render->lines = NULL; + render->chars = NULL; + + row_height = 0; + textdone = 0; + textpos = 0.0; + main_width = symbol->width; + strcpy(addon, ""); + comp_offset = 0; + addon_text_posn = 0.0; + + if (symbol->height < 15) { + symbol->height = 15; + } + // symbol->height = 50; + + if(!hide_text && strlen((char *) symbol->text)) { + textheight = 9.0; + textoffset = 2.0; + } else { + textheight = textoffset = 0.0; + } + // Update height for texts + symbol->height -= textheight + textoffset; + + 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++; + } + + xoffset = symbol->border_width + symbol->whitespace_width; + yoffset = symbol->border_width; + + render->width = (symbol->width + xoffset + xoffset) * scaler; + render->height = (symbol->height + textheight + textoffset + yoffset + yoffset) * scaler; + + default_text_posn = (symbol->height + textoffset + symbol->border_width) * 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++) { + 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; + + 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 */ + line = malloc(sizeof(struct zint_render_line)); + line->next = NULL; + + line->width = block_width * scaler; + line->x = (i + xoffset) * scaler; + + if(addon_latch == 0) { + line->y = row_posn * scaler; + line->length = row_height * scaler; + } else { + line->y = (row_posn + 10.0) * scaler; + line->length = (row_height - 5.0) * scaler; + } + latch = 0; + + if (last_line) + last_line->next = line; + else + render->lines = line; // first line + last_line = line; + } else { + /* a space */ + latch = 1; + } + i += block_width; + + } while (i < symbol->width); + } + } + /* That's done the actual data area, everything else is human-friendly */ + + + /* Add the text */ + xoffset -= comp_offset; + + if (!hide_text) { + // caculate start xoffset to center text + xoffset = symbol->width / 2.0; + xoffset -= (strlen((char *) symbol->text) / 2) * 5.0; + + for (p = symbol->text; *p != 0; p++) { + if (p != symbol->text && *p == '(') xoffset += 3.0; + + bchar = malloc(sizeof(struct zint_render_char)); + bchar->next = NULL; + bchar->x = (textpos + xoffset) * scaler; + bchar->y = default_text_posn; + bchar->fsize = 8.0 * scaler; + bchar->c = (char) *p; + + if (last_bchar) + last_bchar->next = bchar; + else + render->chars = bchar; // First character + last_bchar = bchar; + + // Poor mans kerning for next character + if (*p == '(') { + xoffset += 3.0; + } else if (*p == ')') { + xoffset += 3.0; + } else { + xoffset += 5.0; + } + } + } + + return 1; +} diff --git a/backend/zint.h b/backend/zint.h index 71c3fafe..eed05c96 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -25,6 +25,23 @@ extern "C" { #endif /* __cplusplus */ +struct zint_render_line { + float x, y, length, width; + struct zint_render_line *next; /* Pointer to next line */ +}; + +struct zint_render_char { + float x, y, fsize; + char c; + struct zint_render_char *next; /* Pointer to next character */ +}; + +struct zint_render { + float width, height; + struct zint_render_line *lines; /* Pointer to first line */ + struct zint_render_char *chars; /* Pointer to first character */ +}; + struct zint_symbol { int symbology; int height; @@ -50,8 +67,10 @@ struct zint_symbol { char *bitmap; int bitmap_width; int bitmap_height; + struct zint_render *rendered; }; + /* Tbarcode 7 codes */ #define BARCODE_CODE11 1 #define BARCODE_C25MATRIX 2 @@ -189,6 +208,8 @@ ZINT_EXTERN int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle); ZINT_EXTERN int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle); ZINT_EXTERN int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, int rotate_angle); +ZINT_EXTERN int ZBarcode_Render(struct zint_symbol *symbol, unsigned int hide_text); + ZINT_EXTERN int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle); ZINT_EXTERN int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle); ZINT_EXTERN int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename, int rotate_angle);