]> git.sur5r.net Git - glabels/commitdiff
Added libzint as a barcode backend.
authorSam Lown <me@samlown.com>
Mon, 17 May 2010 08:55:06 +0000 (10:55 +0200)
committerJim Evins <evins@snaught.com>
Mon, 17 May 2010 23:22:59 +0000 (19:22 -0400)
Added libzint as a barcode backend.  Currently only implements the
GS1-128 barcode.

configure.ac
src/Makefile.am
src/bc-zint.c [new file with mode: 0644]
src/bc-zint.h [new file with mode: 0644]
src/bc.c

index 61d6f9ba62eb25560ef137cc964dabce409b0eed..8193c77f06b07b2357219ac78fd81d620bdf9c2a 100644 (file)
@@ -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}
 
 
 "
index d18b29e937aa8496e569ce49dcde912cbf826ea8..a002c69c8d394e0aa5292a5ccbe6ce6654e2792e 100644 (file)
@@ -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 (file)
index 0000000..e938c71
--- /dev/null
@@ -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 (file)
index 0000000..c0a797d
--- /dev/null
@@ -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
+ */
index 5a1d6bc29ad779fb4ab6c043ee87071a74a5b4fd..3c3d1dc1cf25cde3743783a0495ef57849c8ae18 100644 (file)
--- 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,