[glabels] Added libzint as a barcode backend.



commit 0f73f8658931299b97a4e9126622014e7d86e9ed
Author: Sam Lown <me samlown com>
Date:   Mon May 17 10:55:06 2010 +0200

    Added libzint as a barcode backend.
    
    Added libzint as a barcode backend.  Currently only implements the
    GS1-128 barcode.

 configure.ac    |   24 +++++
 src/Makefile.am |    7 ++
 src/bc-zint.c   |  300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/bc-zint.h   |   49 +++++++++
 src/bc.c        |    8 ++
 5 files changed, 388 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 61d6f9b..8193c77 100644
--- a/configure.ac
+++ b/configure.ac
@@ -80,6 +80,7 @@ LIBEBOOK_REQUIRED=2.28.0
 LIBBARCODE_REQUIRED=0.98
 LIBQRENCODE_REQUIRED=3.1.0
 LIBIEC16022_REQUIRED=0.2.4
+LIBZINT_REQUIRED=2.3.1
 
 dnl Make above strings available for packaging files (e.g. rpm spec files)
 AC_SUBST(GLIB_REQUIRED)
@@ -90,6 +91,7 @@ AC_SUBST(LIBEBOOK_REQUIRED)
 AC_SUBST(LIBBARCODE_REQUIRED)
 AC_SUBST(LIBQRENCODE_REQUIRED)
 AC_SUBST(LIBIEC16022_REQUIRED)
+AC_SUBST(LIBZINT_REQUIRED)
 
 
 dnl ---------------------------------------------------------------------------
@@ -158,6 +160,27 @@ else
 	help_libbarcode="(See http://www.gnu.org/software/barcode/barcode.html)"
 fi
 
+dnl ---------------------------------------------------------------------------
+dnl - Check for optional Zint backend
+dnl ---------------------------------------------------------------------------
+AC_ARG_WITH(libzint,
+	    [AS_HELP_STRING([--without-libzint],[build without Zint Barcode support])])
+have_libzint=no
+if test "x$with_libzint" != xno; then
+   AC_CHECK_LIB(zint, ZBarcode_Create,
+		[have_libzint=yes], [have_libzint=no])
+fi
+
+if test "x$have_libzint" = "xyes"; then
+	AC_DEFINE(HAVE_LIBZINT,1,[Define to 1 for Zint Barcode support])
+	LIBZINT_CFLAGS=""
+	LIBZINT_LIBS="-lzint"
+	AC_SUBST(LIBZINT_CFLAGS)
+	AC_SUBST(LIBZINT_LIBS)
+else
+	help_libzint="(See http://www.zint.org.uk)"
+fi
+
 
 dnl ---------------------------------------------------------------------------
 dnl - Check for optional QRencode Barcode backend
@@ -288,6 +311,7 @@ Optional barcode backends:
         GNU Barcode ............. ${have_libbarcode} ${help_libbarcode}
         QR Code ................. ${have_libqrencode} ${help_libqrencode}
         IEC 16022 ............... ${have_libiec16022} ${help_libiec16022}
+        Zint .................... ${have_libzint} ${help_libzint}
 
 
 "
diff --git a/src/Makefile.am b/src/Makefile.am
index d18b29e..a002c69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,6 +8,7 @@ INCLUDES = \
 	$(GLABELS_CFLAGS) 					\
 	$(LIBEBOOK_CFLAGS)					\
 	$(LIBBARCODE_CFLAGS)					\
+	$(LIBZINT_CFLAGS)						\
 	$(LIBQRENCODE_CFLAGS)					\
 	$(LIBIEC16022_CFLAGS)					\
 	$(DISABLE_DEPRECATED_CFLAGS)				\
@@ -24,6 +25,7 @@ glabels_3_LDADD = 				\
 	../libglabels/$(LIBGLABELS_BRANCH).la	\
 	$(LIBEBOOK_LIBS)		 	\
 	$(LIBBARCODE_LIBS)		 	\
+	$(LIBZINT_LIBS)				\
 	$(LIBQRENCODE_LIBS)			\
 	$(LIBIEC16022_LIBS)
 
@@ -34,6 +36,7 @@ glabels_3_batch_LDADD = 				\
 	../libglabels/$(LIBGLABELS_BRANCH).la	\
 	$(LIBEBOOK_LIBS)		 	\
 	$(LIBBARCODE_LIBS)		 	\
+	$(LIBZINT_LIBS)				\
 	$(LIBQRENCODE_LIBS)			\
 	$(LIBIEC16022_LIBS)
 
@@ -118,6 +121,8 @@ glabels_3_SOURCES = 			\
 	bc.h				\
 	bc-gnubarcode.c			\
 	bc-gnubarcode.h			\
+	bc-zint.c		\
+	bc-zint.h 	\
 	bc-postnet.c			\
 	bc-postnet.h			\
 	bc-iec16022.c			\
@@ -239,6 +244,8 @@ glabels_3_batch_SOURCES = 		\
 	bc.h				\
 	bc-gnubarcode.c			\
 	bc-gnubarcode.h			\
+	bc-zint.c		\
+	bc-zint.h		\
 	bc-postnet.c			\
 	bc-postnet.h			\
 	bc-iec16022.c			\
diff --git a/src/bc-zint.c b/src/bc-zint.c
new file mode 100644
index 0000000..e938c71
--- /dev/null
+++ b/src/bc-zint.c
@@ -0,0 +1,300 @@
+/*
+ *  bc-zint.c
+ *  Copyright (C) 2001-2009  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels 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.
+ *
+ *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#ifdef HAVE_LIBZINT
+
+#include "bc-zint.h"
+
+#include <glib.h>
+#include <ctype.h>
+#include <string.h>
+#include <zint.h> /* Zint */
+
+#include "debug.h"
+
+
+/*========================================================*/
+/* Private macros and constants.                          */
+/*========================================================*/
+#define SHRINK_AMOUNT 0.15	/* shrink bars to account for ink spreading */
+#define FONT_SCALE    0.95	/* Shrink fonts just a hair */
+
+
+/*===========================================*/
+/* Local function prototypes                 */
+/*===========================================*/
+static glBarcode *render_zint     (struct zint_symbol *symbol, gboolean text_flag);
+gint module_is_set(struct zint_symbol *symbol, gint y_coord, gint x_coord);
+
+
+
+/*****************************************************************************/
+/* Generate intermediate representation of barcode.                          */
+/*****************************************************************************/
+glBarcode *
+gl_barcode_zint_new (const gchar    *id,
+			   gboolean        text_flag,
+			   gboolean        checksum_flag,
+			   gdouble         w,
+			   gdouble         h,
+			   const gchar    *digits)
+{
+	glBarcode           *gbc;
+	struct zint_symbol  *symbol;
+	gint                 type;
+	gint		     result;
+
+	symbol = ZBarcode_Create();
+
+	/* Assign type flag.  Pre-filter by length for subtypes. */
+	if (g_ascii_strcasecmp (id, "GS1-128") == 0) {
+		symbol->symbology = BARCODE_EAN128;
+	} else {
+		g_message( "Illegal barcode id %s", id );
+		ZBarcode_Delete (symbol);
+		return NULL;
+	}
+
+	/* Checksum not supported yet!! 
+	if (!checksum_flag) {
+		flags |= BARCODE_NO_CHECKSUM;
+	}
+	*/
+
+	// g_message ("Zint Requested Dimensions: %f x %f", w, h);
+
+	result = ZBarcode_Encode(symbol, (unsigned char *)digits, 0);
+	if (result) {
+		ZBarcode_Delete (symbol);
+		g_message ("Zint Error: %s", symbol->errtxt);
+		return NULL;
+	}
+
+	/* Scale calculated after height, always maintain aspect ratio */
+	// symbol->height = (h > 0.0 ? (gint)h : 50);
+	symbol->scale = (w / symbol->width);
+	symbol->height = h / symbol->scale; // height always in standard size
+
+
+	/* Convert Sums provided by zint encode */
+	gbc = render_zint(symbol, text_flag);
+
+	// g_message ("Zint Barcode Dimensions: %f x %f", gbc->width, gbc->height);
+
+	ZBarcode_Delete(symbol);
+
+	return gbc;
+}
+
+
+/*--------------------------------------------------------------------------
+ * PRIVATE. Render to glBarcode the provided Zint symbol.
+ *
+ * Based on the SVG output from Zint library, handles lots of otherwise
+ * internal  Zint code to convert directly to glBarcode representation.
+ *
+ *--------------------------------------------------------------------------*/
+static glBarcode *render_zint(struct zint_symbol *symbol, gboolean text_flag) {
+
+	glBarcode     *gbc;
+	glBarcodeLine *line;
+	glBarcodeChar *bchar;
+	
+	gint i, r, block_width, latch, this_row;
+	gfloat textpos, large_bar_height, preset_height, row_height, row_posn = 0.0;
+	gint error_number = 0;
+	gint textoffset, textheight, xoffset, yoffset, textdone, main_width;
+	gchar textpart[10], addon[6];
+	gint large_bar_count, comp_offset;
+	gfloat addon_text_posn;
+	gfloat default_text_posn;
+	gfloat scaler = symbol->scale;
+	gchar *p;
+
+	gbc = g_new0(glBarcode, 1);
+
+	row_height = 0;
+	textdone = 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(text_flag && strlen(symbol->text) != 0) {
+		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;
+
+	gbc->width = (gdouble) (symbol->width + xoffset + xoffset) * scaler;
+	gbc->height = (gdouble) (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 = g_new0 (glBarcodeLine, 1);
+
+					line->width = block_width * scaler;
+					/* glBarcodeLine centers based on width, counter-act!!! */
+					line->x = ((i + xoffset) + (block_width / 2.0)) * 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;
+					// g_message ("Zint Adding Line at: %f x %f dim: %f x %f", line->x, line->y, line->width, line->length);
+					gbc->lines = g_list_append (gbc->lines, 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 (text_flag) {
+		// caculate start xoffset to center text
+		xoffset = symbol->width / 2.0;
+		xoffset -= (strlen(symbol->text) / 2) * 5.0;
+
+		for (p = symbol->text; *p != 0; p++) {
+			if (p != symbol->text && *p == '(') xoffset += 3.0;
+			bchar = g_new0 (glBarcodeChar, 1);
+			bchar->x = (textpos + xoffset) * scaler;
+			bchar->y = default_text_posn;
+			bchar->fsize = 8.0 * scaler;
+			bchar->c = (gchar) *p;
+			gbc->chars = g_list_append (gbc->chars, bchar);
+			// Poor mans kerning
+			if (*p == '(') {
+				xoffset += 3.0;
+			} else if (*p == ')') {
+				xoffset += 3.0;
+			} else {
+				xoffset += 5.0;
+			}
+		}
+	}
+
+	return gbc;
+}
+
+/*
+ * Stolen from Zint common.c
+ */
+gint module_is_set(struct zint_symbol *symbol, gint y_coord, gint x_coord)
+{
+	return (symbol->encoded_data[y_coord][x_coord / 7] & (1 << (x_coord % 7))) ? 1 : 0;
+}
+
+#endif /* HAVE_LIBZINT */
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/bc-zint.h b/src/bc-zint.h
new file mode 100644
index 0000000..c0a797d
--- /dev/null
+++ b/src/bc-zint.h
@@ -0,0 +1,49 @@
+/*
+ *  bc-zint.h
+ *  Copyright (C) 2010  Sam Lown <me samlown com>.
+ *  Copyright (C) 2001-2009  Jim Evins <evins snaught com>.
+ *
+ *  This file is part of gLabels.
+ *
+ *  gLabels 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.
+ *
+ *  gLabels 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 gLabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __BC_ZINT_H__
+#define __BC_ZINT_H__
+
+#include "bc.h"
+
+G_BEGIN_DECLS
+
+glBarcode *gl_barcode_zint_new (const gchar    *id,
+				      gboolean        text_flag,
+				      gboolean        checksum_flag,
+				      gdouble         w,
+				      gdouble         h,
+				      const gchar    *digits);
+
+G_END_DECLS
+
+#endif /* __BC_ZINT_H__ */
+
+
+
+/*
+ * Local Variables:       -- emacs
+ * mode: C                -- emacs
+ * c-basic-offset: 8      -- emacs
+ * tab-width: 8           -- emacs
+ * indent-tabs-mode: nil  -- emacs
+ * End:                   -- emacs
+ */
diff --git a/src/bc.c b/src/bc.c
index 5a1d6bc..3c3d1dc 100644
--- a/src/bc.c
+++ b/src/bc.c
@@ -27,6 +27,7 @@
 
 #include "bc-postnet.h"
 #include "bc-gnubarcode.h"
+#include "bc-zint.h"
 #include "bc-iec16022.h"
 #include "bc-iec18004.h"
 
@@ -156,6 +157,13 @@ static const Backend backends[] = {
 
 #endif /* HAVE_LIBBARCODE */
 
+#ifdef HAVE_LIBZINT
+
+	{ "GS1-128", N_("GS1-128"), gl_barcode_zint_new,
+	  TRUE, TRUE, FALSE, FALSE, "[00]001234560000000018", TRUE, 16},
+
+#endif /* HAVE_LIBZINT */
+
 #ifdef HAVE_LIBIEC16022
 
 	{ "IEC16022", N_("IEC16022 (DataMatrix)"), gl_barcode_iec16022_new,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]