[glabels/vala] Initial porting of libglbarcode to VALA



commit bf38cf92814da85b95b76e7ab27ca617f3e170f0
Author: Jim Evins <evins snaught com>
Date:   Sat Sep 1 18:28:52 2012 -0400

    Initial porting of libglbarcode to VALA

 .gitignore                                 |    8 +
 Makefile.am                                |    1 +
 configure.ac                               |   13 +
 libglbarcode/Makefile.am                   |   89 ++--
 libglbarcode/barcode.vala                  |  125 +++++
 libglbarcode/barcode_code39.vala           |  237 +++++++++
 libglbarcode/barcode_code39_extended.vala  |   96 ++++
 libglbarcode/barcode_onecode.vala          |  575 +++++++++++++++++++++
 libglbarcode/barcode_postnet.vala          |  186 +++++++
 libglbarcode/cairo_renderer.vala           |  127 +++++
 libglbarcode/constants.vala                |   36 ++
 libglbarcode/demo/Makefile.am              |   37 ++
 libglbarcode/demo/glbarcode.vala           |  128 +++++
 libglbarcode/factory.vala                  |  151 ++++++
 libglbarcode/lgl-barcode-code39.c          |  456 -----------------
 libglbarcode/lgl-barcode-code39.h          |   49 --
 libglbarcode/lgl-barcode-create.c          |  119 -----
 libglbarcode/lgl-barcode-create.h          |   52 --
 libglbarcode/lgl-barcode-onecode.c         |  747 ----------------------------
 libglbarcode/lgl-barcode-onecode.h         |   49 --
 libglbarcode/lgl-barcode-postnet.c         |  277 ----------
 libglbarcode/lgl-barcode-postnet.h         |   49 --
 libglbarcode/lgl-barcode-render-to-cairo.c |  346 -------------
 libglbarcode/lgl-barcode-render-to-cairo.h |   48 --
 libglbarcode/lgl-barcode-type.h            |   61 ---
 libglbarcode/lgl-barcode.c                 |  362 --------------
 libglbarcode/lgl-barcode.h                 |  415 ---------------
 libglbarcode/libglbarcode-3.0.pc.in        |   13 -
 libglbarcode/libglbarcode.h                |   47 --
 libglbarcode/renderer.vala                 |   71 +++
 libglbarcode/shape.vala                    |  182 +++++++
 31 files changed, 2014 insertions(+), 3138 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 683c249..82a5daf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -49,8 +49,16 @@ glabels-*.tar.gz
 /libglabels/*.stamp
 /libglabels/libglabels*.pc
 
+/libglbarcode/*.c
+/libglbarcode/*.h
+/libglbarcode/*.vapi
+/libglbarcode/*.stamp
 /libglbarcode/libglbarcode*.pc
 
+/libglbarcode/demo/*.c
+/libglbarcode/demo/*.h
+/libglbarcode/demo/glbarcode
+
 /glabels/*.c
 /glabels/*.stamp
 /glabels/test
diff --git a/Makefile.am b/Makefile.am
index b23c823..755bf12 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4,6 +4,7 @@ NULL =
 
 SUBDIRS = \
 	libglabels \
+	libglbarcode \
 	glabels \
 	po \
 	templates \
diff --git a/configure.ac b/configure.ac
index 12ac679..467ca8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -76,6 +76,7 @@ GEE_REQUIRED=0.6.2.1
 CAIRO_REQUIRED=1.10.2
 GDK_PIXBUF_REQUIRED=2.24.0
 LIBRSVG_REQUIRED=2.36.0
+PANGOCAIRO_REQUIRED=1.30.0
 
 PKG_CHECK_MODULES(GLABELS, [\
 			   glib-2.0 >= $GLIB_REQUIRED \
@@ -101,10 +102,22 @@ PKG_CHECK_MODULES(LIBGLABELS, [\
 AC_SUBST(LIBGLABELS_CFLAGS)
 AC_SUBST(LIBGLABELS_LIBS)
 
+PKG_CHECK_MODULES(LIBGLBARCODE, [\
+                                glib-2.0 >= $GLIB_REQUIRED \
+                                gobject-2.0 >= $GLIB_REQUIRED \
+                                cairo >= $CAIRO_REQUIRED \
+                                pangocairo >= $PANGOCAIRO_REQUIRED \
+])
+
+AC_SUBST(LIBGLBARCODE_CFLAGS)
+AC_SUBST(LIBGLBARCODE_LIBS)
+
 
 AC_CONFIG_FILES([Makefile
 	vapi/Makefile
 	libglabels/Makefile
+	libglbarcode/Makefile
+	libglbarcode/demo/Makefile
 	glabels/Makefile
 	glabels/cursors/Makefile
 	po/Makefile.in
diff --git a/libglbarcode/Makefile.am b/libglbarcode/Makefile.am
index 7a884df..a666c60 100644
--- a/libglbarcode/Makefile.am
+++ b/libglbarcode/Makefile.am
@@ -1,51 +1,44 @@
-configdir = $(datadir)/$(LIBGLBARCODE_BRANCH)
+NULL = 
+
+lib_LTLIBRARIES = libglbarcode-4.0.la
+
+libglbarcode_4_0_la_SOURCES = \
+	factory.vala \
+	barcode.vala \
+	barcode_code39.vala \
+	barcode_code39_extended.vala \
+	barcode_onecode.vala \
+	barcode_postnet.vala \
+	shape.vala \
+	renderer.vala \
+	cairo_renderer.vala \
+	constants.vala \
+	$(NULL)
 
 INCLUDES = \
-	$(LIBGLBARCODE_CFLAGS)				\
-	-DLIBGLBARCODE_CONFIG_DIR=\""$(configdir)"\" \
-	$(DISABLE_DEPRECATED_CFLAGS)
-
-libglbarcode_3_0_la_LDFLAGS=\
-        -version-info $(LIBGLBARCODE_API_VERSION) \
-        $(LIBGLBARCODE_LIBS) \
-        -no-undefined 
-
-lib_LTLIBRARIES = libglbarcode-3.0.la
-
-libglbarcode_3_0_la_SOURCES =		\
-	lgl-barcode.c			\
-	lgl-barcode.h			\
-	lgl-barcode-create.c		\
-	lgl-barcode-create.h		\
-	lgl-barcode-render-to-cairo.c	\
-	lgl-barcode-render-to-cairo.h	\
-	lgl-barcode-type.h		\
-	lgl-barcode-onecode.c		\
-	lgl-barcode-onecode.h		\
-	lgl-barcode-postnet.c		\
-	lgl-barcode-postnet.h		\
-	lgl-barcode-code39.c		\
-	lgl-barcode-code39.h
-
-libglbarcode_3_0includedir=$(includedir)/$(LIBGLBARCODE_BRANCH)
-
-libglbarcode_3_0include_HEADERS = 	\
-	libglbarcode.h
-
-libglbarcode_3_0subincludedir=$(includedir)/$(LIBGLBARCODE_BRANCH)/libglbarcode
-
-libglbarcode_3_0subinclude_HEADERS = 	\
-	lgl-barcode.h			\
-	lgl-barcode-create.h		\
-	lgl-barcode-render-to-cairo.h	\
-	lgl-barcode-type.h		\
-	lgl-barcode-onecode.h		\
-	lgl-barcode-postnet.h		\
-	lgl-barcode-code39.h
-
-EXTRA_DIST =			\
-	$(LIBGLBARCODE_BRANCH).pc.in
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = $(LIBGLBARCODE_BRANCH).pc
+	-include config.h \
+	$(LIBGLBARCODE_CFLAGS) \
+	-DLOCALEDIR=\""$(localedir)"\" \
+	-DDATADIR=\""$(datadir)"\" \
+	-DLIBGLBARCODE_BRANCH=\""$(LIBGLBARCODE_BRANCH)"\" \
+	$(NULL)
+
+VALAFLAGS = \
+	--vapidir=$(srcdir)/../vapi \
+	--pkg config \
+	--pkg posix \
+	--pkg gobject-2.0 \
+	--pkg cairo \
+	--pkg pangocairo \
+	--header=libglbarcode-4.h \
+	--vapi=libglbarcode-4.vapi \
+	$(NULL)
+
+EXTRA_DIST = \
+	libglbarcode-4.h \
+	libglbarcode-4.vapi \
+	$(NULL)
+
+DISTCLEANFILES = \
+	$(NULL)
 
diff --git a/libglbarcode/barcode.vala b/libglbarcode/barcode.vala
new file mode 100644
index 0000000..683d9ad
--- /dev/null
+++ b/libglbarcode/barcode.vala
@@ -0,0 +1,125 @@
+/*  barcode.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+
+namespace glbarcode
+{
+
+	public abstract class Barcode : Object
+	{
+
+		public string? data          { get; construct; }
+		public bool    text_flag     { get; construct; }
+		public bool    checksum_flag { get; construct; }
+		public double  w             { get; construct set; }
+		public double  h             { get; construct set; }
+
+		public bool    is_empty      { get; private set; }
+		public bool    is_data_valid { get; private set; }
+
+		private List<Shape>   shapes;
+
+
+		protected abstract bool   validate( string data );
+		protected abstract string encode( string canon_data, bool checksum_flag );
+		protected abstract void   vectorize( string coded_data,
+		                                     bool text_flag, bool checksum_flag,
+		                                     double w, double h,
+		                                     string data, string text );
+
+
+		protected virtual string to_text( string data )
+		{
+			return data;
+		}
+
+
+		protected virtual string preprocess( string data )
+		{
+			return data;
+		}
+
+
+		construct
+		{
+			if ( (data == null) || (data == "") )
+			{
+				is_empty = true;
+			}
+			else
+			{
+				is_empty = false;
+
+				if ( validate( data ) )
+				{
+					is_data_valid = true;
+
+					string display_text = to_text( data );
+					string cooked_data  = preprocess( data );
+					string coded_data   = encode( cooked_data, checksum_flag );
+
+					vectorize( coded_data, text_flag, checksum_flag, w, h, cooked_data, display_text );
+				}
+				else
+				{
+					is_data_valid = false;
+				}
+			}
+		}
+
+
+		protected void add_box( double x, double y, double w, double h )
+		{
+			ShapeBox box = new ShapeBox( x, y, w, h );
+			shapes.prepend( box );
+		}
+
+
+		protected void add_string(  double x, double y, double fsize, string s )
+		{
+			ShapeText text = new ShapeText( x, y, fsize, s );
+			shapes.prepend( text );
+		}
+
+
+		protected void add_ring(    double x, double y, double r, double line_width )
+		{
+			ShapeRing ring = new ShapeRing( x, y, r, line_width );
+			shapes.prepend( ring );
+		}
+
+
+		protected void add_hexagon( double x, double y, double h )
+		{
+			ShapeHexagon hexagon = new ShapeHexagon( x, y, h );
+			shapes.prepend( hexagon );
+		}
+
+
+		public void render( Renderer renderer )
+		{
+			renderer.render( w, h, shapes );
+		}
+
+	}
+
+}
diff --git a/libglbarcode/barcode_code39.vala b/libglbarcode/barcode_code39.vala
new file mode 100644
index 0000000..03d87ef
--- /dev/null
+++ b/libglbarcode/barcode_code39.vala
@@ -0,0 +1,237 @@
+/*  barcode_code39.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+using glbarcode.Constants;
+
+namespace glbarcode
+{
+
+	public class BarcodeCode39 : Barcode
+	{
+
+		private const double MIN_X       = ( 0.01 *  PTS_PER_INCH );
+		private const double N           = 2.5;
+		private const double MIN_I       = MIN_X;
+		private const double MIN_HEIGHT  = ( 0.25 *  PTS_PER_INCH );
+		private const double MIN_QUIET   = ( 0.10 *  PTS_PER_INCH );
+
+		private const double INK_BLEED   = ( 0.00325 * PTS_PER_INCH );
+
+		private const double TEXT_AREA_HEIGHT = 14.0;
+		private const double TEXT_SIZE        = 10.0;
+
+
+		/* Code 39 alphabet. Position indicates value. */
+		private const string alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%";
+
+		/* Code 39 symbols. Position must match position in alphabet. */
+		private const string[] symbols = {
+			/*        BsBsBsBsB */
+			/* 0 */  "NnNwWnWnN",
+			/* 1 */  "WnNwNnNnW",
+			/* 2 */  "NnWwNnNnW",
+			/* 3 */  "WnWwNnNnN",
+			/* 4 */  "NnNwWnNnW",
+			/* 5 */  "WnNwWnNnN",
+			/* 6 */  "NnWwWnNnN",
+			/* 7 */  "NnNwNnWnW",
+			/* 8 */  "WnNwNnWnN",
+			/* 9 */  "NnWwNnWnN",
+			/* A */  "WnNnNwNnW",
+			/* B */  "NnWnNwNnW",
+			/* C */  "WnWnNwNnN",
+			/* D */  "NnNnWwNnW",
+			/* E */  "WnNnWwNnN",
+			/* F */  "NnWnWwNnN",
+			/* G */  "NnNnNwWnW",
+			/* H */  "WnNnNwWnN",
+			/* I */  "NnWnNwWnN",
+			/* J */  "NnNnWwWnN",
+			/* K */  "WnNnNnNwW",
+			/* L */  "NnWnNnNwW",
+			/* M */  "WnWnNnNwN",
+			/* N */  "NnNnWnNwW",
+			/* O */  "WnNnWnNwN",
+			/* P */  "NnWnWnNwN",
+			/* Q */  "NnNnNnWwW",
+			/* R */  "WnNnNnWwN",
+			/* S */  "NnWnNnWwN",
+			/* T */  "NnNnWnWwN",
+			/* U */  "WwNnNnNnW",
+			/* V */  "NwWnNnNnW",
+			/* W */  "WwWnNnNnN",
+			/* X */  "NwNnWnNnW",
+			/* Y */  "WwNnWnNnN",
+			/* Z */  "NwWnWnNnN",
+			/* - */  "NwNnNnWnW",
+			/* . */  "WwNnNnWnN",
+			/*   */  "NwWnNnWnN",
+			/* $ */  "NwNwNwNnN",
+			/* / */  "NwNwNnNwN",
+			/* + */  "NwNnNwNwN",
+			/* % */  "NnNwNwNwN"
+		};
+
+		private const string frame_symbol = "NwNnWnWnN";
+
+
+		protected override bool validate( string data )
+		{
+			for ( int i = 0; i < data.length; i++ )
+			{
+				char c = data[i].toupper();
+
+				if ( !alphabet.contains( c.to_string() ) )
+				{
+					return false;
+				}
+			}
+
+			return true;
+		}
+
+
+		protected override string encode( string canon_data, bool checksum_flag )
+		{
+			StringBuilder code = new StringBuilder();
+
+			/* Left frame symbol */
+			code.append( frame_symbol );
+			code.append( "i" );
+
+			int sum = 0;
+			for ( int i=0; i < canon_data.length; i++ )
+			{
+				int c_value = alphabet.index_of_char( canon_data[i].toupper() );
+
+				code.append( symbols[c_value] );
+				code.append( "i" );
+
+				sum += c_value;
+			}
+
+			if ( checksum_flag )
+			{
+				code.append( symbols[sum % 43] );
+				code.append( "i" );
+			}
+
+			/* Right frame bar */
+			code.append( frame_symbol );
+
+			return code.str;
+		}
+
+
+		protected override void vectorize( string coded_data,
+		                                   bool text_flag, bool checksum_flag,
+		                                   double w, double h,
+		                                   string data, string text )
+		{
+			/* determine width and establish horizontal scale */
+			double min_l;
+			if (!checksum_flag)
+			{
+				min_l = (data.length + 2)*(3*N + 6)*MIN_X + (data.length + 1)*MIN_I;
+			}
+			else
+			{
+				min_l = (data.length + 3)*(3*N + 6)*MIN_X + (data.length + 2)*MIN_I;
+			}
+        
+			double scale;
+			if ( w == 0 )
+			{
+				scale = 1.0;
+			}
+			else
+			{
+				scale = w / (min_l + 2*MIN_QUIET);
+
+				if ( scale < 1.0 )
+				{
+					scale = 1.0;
+				}
+			}
+			double width = min_l * scale;
+
+			/* determine height of barcode */
+			double height = text_flag ? h - TEXT_AREA_HEIGHT : h;
+			height = double.max( height, double.max( 0.15*width, MIN_HEIGHT ) );
+
+			/* determine horizontal quiet zone */
+			double x_quiet = double.max( (10 * scale * MIN_X), MIN_QUIET );
+
+			/* Now traverse the code string and each bar */
+			double x1 = x_quiet;
+			for ( int i=0; i < coded_data.length; i++ )
+			{
+				
+				switch ( coded_data[i] )
+				{
+
+				case 'i':
+					/* Inter-character gap */
+					x1 += scale * MIN_I;
+					break;
+
+				case 'N':
+					/* Narrow bar */
+					add_box( x1, 0.0, (scale*MIN_X - INK_BLEED), height );
+					x1 += scale*MIN_X;
+					break;
+
+				case 'W':
+					/* Wide bar */
+					add_box( x1, 0.0, (scale*N*MIN_X - INK_BLEED), height );
+					x1 += scale * N * MIN_X;
+					break;
+
+				case 'n':
+					/* Narrow space */
+					x1 += scale * MIN_X;
+					break;
+
+				case 'w':
+					/* Wide space */
+					x1 += scale * N * MIN_X;
+					break;
+
+				default:
+					assert_not_reached();
+				}
+			}
+
+			if ( text_flag )
+			{
+				string starred_text = "*%s*".printf( text );
+				add_string( x_quiet + width/2, height + (TEXT_AREA_HEIGHT-TEXT_SIZE)/2, TEXT_SIZE, starred_text );
+			}
+
+			this.w = width + 2*x_quiet;
+			this.h = text_flag ? height + TEXT_AREA_HEIGHT : height;
+		}
+
+
+	}
+
+}
diff --git a/libglbarcode/barcode_code39_extended.vala b/libglbarcode/barcode_code39_extended.vala
new file mode 100644
index 0000000..aef2754
--- /dev/null
+++ b/libglbarcode/barcode_code39_extended.vala
@@ -0,0 +1,96 @@
+/*  barcode_code39_extended.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+
+namespace glbarcode
+{
+
+	public class BarcodeCode39Extended : BarcodeCode39
+	{
+
+		private const string[] ascii_map =
+		{
+			/* NUL */ "%U",   /* SOH */ "$A",   /* STX */ "$B",   /* ETX */ "$C",
+			/* EOT */ "$D",   /* ENQ */ "$E",   /* ACK */ "$F",   /* BEL */ "$G",
+			/* BS  */ "$H",   /* HT  */ "$I",   /* LF  */ "$J",   /* VT  */ "$K",
+			/* FF  */ "$L",   /* CR  */ "$M",   /* SO  */ "$N",   /* SI  */ "$O",
+			/* DLE */ "$P",   /* DC1 */ "$Q",   /* DC2 */ "$R",   /* DC3 */ "$S",
+			/* DC4 */ "$T",   /* NAK */ "$U",   /* SYN */ "$V",   /* ETB */ "$W",
+			/* CAN */ "$X",   /* EM  */ "$Y",   /* SUB */ "$Z",   /* ESC */ "%A",
+			/* FS  */ "%B",   /* GS  */ "%C",   /* RS  */ "%D",   /* US  */ "%E",
+			/* " " */ " ",    /* !   */ "/A",   /* "   */ "/B",   /* #   */ "/C",
+			/* $   */ "/D",   /* %   */ "/E",   /* &   */ "/F",   /* '   */ "/G",
+			/* (   */ "/H",   /* )   */ "/I",   /* *   */ "/J",   /* +   */ "/K",
+			/* ,   */ "/L",   /* -   */ "-",    /* .   */ ".",    /* /   */ "/O",
+			/* 0   */ "0",    /* 1   */ "1",    /* 2   */ "2",    /* 3   */ "3",
+			/* 4   */ "4",    /* 5   */ "5",    /* 6   */ "6",    /* 7   */ "7",
+			/* 8   */ "8",    /* 9   */ "9",    /* :   */ "/Z",   /* ;   */ "%F",
+			/* <   */ "%G",   /* =   */ "%H",   /* >   */ "%I",   /* ?   */ "%J",
+			/* @   */ "%V",   /* A   */ "A",    /* B   */ "B",    /* C   */ "C",
+			/* D   */ "D",    /* E   */ "E",    /* F   */ "F",    /* G   */ "G",
+			/* H   */ "H",    /* I   */ "I",    /* J   */ "J",    /* K   */ "K",
+			/* L   */ "L",    /* M   */ "M",    /* N   */ "N",    /* O   */ "O",
+			/* P   */ "P",    /* Q   */ "Q",    /* R   */ "R",    /* S   */ "S",
+			/* T   */ "T",    /* U   */ "U",    /* V   */ "V",    /* W   */ "W",
+			/* X   */ "X",    /* Y   */ "Y",    /* Z   */ "Z",    /* [   */ "%K",
+			/* \   */ "%L",   /* ]   */ "%M",   /* ^   */ "%N",   /* _   */ "%O",
+			/* `   */ "%W",   /* a   */ "+A",   /* b   */ "+B",   /* c   */ "+C",
+			/* d   */ "+D",   /* e   */ "+E",   /* f   */ "+F",   /* g   */ "+G",
+			/* h   */ "+H",   /* i   */ "+I",   /* j   */ "+J",   /* k   */ "+K",
+			/* l   */ "+L",   /* m   */ "+M",   /* n   */ "+N",   /* o   */ "+O",
+			/* p   */ "+P",   /* q   */ "+Q",   /* r   */ "+R",   /* s   */ "+S",
+			/* t   */ "+T",   /* u   */ "+U",   /* v   */ "+V",   /* w   */ "+W",
+			/* x   */ "+X",   /* y   */ "+Y",   /* z   */ "+Z",   /* {   */ "%P",
+			/* |   */ "%Q",   /* }   */ "%R",   /* ~   */ "%S",   /* DEL */ "%T" 
+		};
+
+
+		protected override bool validate( string data )
+		{
+			for ( int i=0; i < data.length; i++ )
+			{
+				if ( (data[i] < 0) || (data[i] > 0x7F) )
+				{
+					return false;
+				}
+			}
+
+			return true;
+		}
+
+
+		protected override string preprocess( string data )
+		{
+			StringBuilder extended_data = new StringBuilder("");
+
+			for ( int i=0; i < data.length; i++ )
+			{
+				extended_data.append( ascii_map[ data[i] ] );
+			}
+				
+			return extended_data.str;
+		}
+
+
+	}
+
+}
diff --git a/libglbarcode/barcode_onecode.vala b/libglbarcode/barcode_onecode.vala
new file mode 100644
index 0000000..c541bb2
--- /dev/null
+++ b/libglbarcode/barcode_onecode.vala
@@ -0,0 +1,575 @@
+/*  barcode_onecode.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+using glbarcode.Constants;
+
+namespace glbarcode
+{
+
+	public class BarcodeOneCode : Barcode
+	{
+
+		private const double ONECODE_BAR_WIDTH        = ( 0.02   * PTS_PER_INCH );
+		private const double ONECODE_FULL_HEIGHT      = ( 0.145  * PTS_PER_INCH );
+		private const double ONECODE_ASCENDER_HEIGHT  = ( 0.0965 * PTS_PER_INCH );
+		private const double ONECODE_DESCENDER_HEIGHT = ( 0.0965 * PTS_PER_INCH );
+		private const double ONECODE_TRACKER_HEIGHT   = ( 0.048  * PTS_PER_INCH );
+		private const double ONECODE_FULL_OFFSET      = 0;
+		private const double ONECODE_ASCENDER_OFFSET  = 0;
+		private const double ONECODE_DESCENDER_OFFSET = ( 0.0485 * PTS_PER_INCH );
+		private const double ONECODE_TRACKER_OFFSET   = ( 0.0485 * PTS_PER_INCH );
+		private const double ONECODE_BAR_PITCH        = ( 0.0458 * PTS_PER_INCH );
+		private const double ONECODE_HORIZ_MARGIN     = ( 0.125  * PTS_PER_INCH );
+		private const double ONECODE_VERT_MARGIN      = ( 0.028  * PTS_PER_INCH );
+
+
+		private struct Int104
+		{
+			public uint8[] byte;
+
+			public Int104()
+			{
+				byte = new uint8[13];
+			}
+
+			public void mult_uint( uint y )
+			{
+				uint64 carry = 0;
+				for ( int i = 12; i >= 0; i-- )
+				{
+					uint64 temp = byte[i]*y + carry;
+
+					byte[i] = (uint8)(temp & 0xFF);
+					carry   = temp >> 8;
+				}
+			}
+
+			public void add_uint64( uint64 y )
+			{
+				uint64 carry = 0;
+				for ( int i = 12; i >= 0; i-- )
+				{
+					uint64 temp = byte[i] + (y&0xFF) + carry;
+
+					byte[i] = (uint8)(temp & 0xFF);
+					carry   = temp >> 8;
+					y       = y >> 8;
+				}
+			}
+
+			public uint div_uint( uint y )
+			{
+				uint carry = 0;
+				for ( int i = 0; i < 13; i++ )
+				{
+					uint temp = byte[i] + (carry << 8);
+
+					byte[i] = (uint8)(temp / y);
+					carry   = temp % y;
+				}
+				return carry;
+			}
+		}
+
+
+		private enum Char
+		{
+			A = 0,
+			B = 1,
+			C = 2,
+			D = 3,
+			E = 4,
+			F = 5,
+			G = 6,
+			H = 7,
+			I = 8,
+			J = 9
+		}
+
+		private struct Bar { Char i; int mask; }
+
+		private struct BarMapEntry
+		{
+			Bar descender;
+			Bar ascender;
+		}
+
+		private const BarMapEntry[] bar_map = {
+			/*  1 */ { { Char.H, 1<<2  }, { Char.E, 1<<3  } },
+			/*  2 */ { { Char.B, 1<<10 }, { Char.A, 1<<0  } },
+			/*  3 */ { { Char.J, 1<<12 }, { Char.C, 1<<8  } },
+			/*  4 */ { { Char.F, 1<<5  }, { Char.G, 1<<11 } },
+			/*  5 */ { { Char.I, 1<<9  }, { Char.D, 1<<1  } },
+			/*  6 */ { { Char.A, 1<<1  }, { Char.F, 1<<12 } },
+			/*  7 */ { { Char.C, 1<<5  }, { Char.B, 1<<8  } },
+			/*  8 */ { { Char.E, 1<<4  }, { Char.J, 1<<11 } },
+			/*  9 */ { { Char.G, 1<<3  }, { Char.I, 1<<10 } },
+			/* 10 */ { { Char.D, 1<<9  }, { Char.H, 1<<6  } },
+			/* 11 */ { { Char.F, 1<<11 }, { Char.B, 1<<4  } },
+			/* 12 */ { { Char.I, 1<<5  }, { Char.C, 1<<12 } },
+			/* 13 */ { { Char.J, 1<<10 }, { Char.A, 1<<2  } },
+			/* 14 */ { { Char.H, 1<<1  }, { Char.G, 1<<7  } },
+			/* 15 */ { { Char.D, 1<<6  }, { Char.E, 1<<9  } },
+			/* 16 */ { { Char.A, 1<<3  }, { Char.I, 1<<6  } },
+			/* 17 */ { { Char.G, 1<<4  }, { Char.C, 1<<7  } },
+			/* 18 */ { { Char.B, 1<<1  }, { Char.J, 1<<9  } },
+			/* 19 */ { { Char.H, 1<<10 }, { Char.F, 1<<2  } },
+			/* 20 */ { { Char.E, 1<<0  }, { Char.D, 1<<8  } },
+			/* 21 */ { { Char.G, 1<<2  }, { Char.A, 1<<4  } },
+			/* 22 */ { { Char.I, 1<<11 }, { Char.B, 1<<0  } },
+			/* 23 */ { { Char.J, 1<<8  }, { Char.D, 1<<12 } },
+			/* 24 */ { { Char.C, 1<<6  }, { Char.H, 1<<7  } },
+			/* 25 */ { { Char.F, 1<<1  }, { Char.E, 1<<10 } },
+			/* 26 */ { { Char.B, 1<<12 }, { Char.G, 1<<9  } },
+			/* 27 */ { { Char.H, 1<<3  }, { Char.I, 1<<0  } },
+			/* 28 */ { { Char.F, 1<<8  }, { Char.J, 1<<7  } },
+			/* 29 */ { { Char.E, 1<<6  }, { Char.C, 1<<10 } },
+			/* 30 */ { { Char.D, 1<<4  }, { Char.A, 1<<5  } },
+			/* 31 */ { { Char.I, 1<<4  }, { Char.F, 1<<7  } },
+			/* 32 */ { { Char.H, 1<<11 }, { Char.B, 1<<9  } },
+			/* 33 */ { { Char.G, 1<<0  }, { Char.J, 1<<6  } },
+			/* 34 */ { { Char.A, 1<<6  }, { Char.E, 1<<8  } },
+			/* 35 */ { { Char.C, 1<<1  }, { Char.D, 1<<2  } },
+			/* 36 */ { { Char.F, 1<<9  }, { Char.I, 1<<12 } },
+			/* 37 */ { { Char.E, 1<<11 }, { Char.G, 1<<1  } },
+			/* 38 */ { { Char.J, 1<<5  }, { Char.H, 1<<4  } },
+			/* 39 */ { { Char.D, 1<<3  }, { Char.B, 1<<2  } },
+			/* 40 */ { { Char.A, 1<<7  }, { Char.C, 1<<0  } },
+			/* 41 */ { { Char.B, 1<<3  }, { Char.E, 1<<1  } },
+			/* 42 */ { { Char.G, 1<<10 }, { Char.D, 1<<5  } },
+			/* 43 */ { { Char.I, 1<<7  }, { Char.J, 1<<4  } },
+			/* 44 */ { { Char.C, 1<<11 }, { Char.F, 1<<6  } },
+			/* 45 */ { { Char.A, 1<<8  }, { Char.H, 1<<12 } },
+			/* 46 */ { { Char.E, 1<<2  }, { Char.I, 1<<1  } },
+			/* 47 */ { { Char.F, 1<<10 }, { Char.D, 1<<0  } },
+			/* 48 */ { { Char.J, 1<<3  }, { Char.A, 1<<9  } },
+			/* 49 */ { { Char.G, 1<<5  }, { Char.C, 1<<4  } },
+			/* 50 */ { { Char.H, 1<<8  }, { Char.B, 1<<7  } },
+			/* 51 */ { { Char.F, 1<<0  }, { Char.E, 1<<5  } },
+			/* 52 */ { { Char.C, 1<<3  }, { Char.A, 1<<10 } },
+			/* 53 */ { { Char.G, 1<<12 }, { Char.J, 1<<2  } },
+			/* 54 */ { { Char.D, 1<<11 }, { Char.B, 1<<6  } },
+			/* 55 */ { { Char.I, 1<<8  }, { Char.H, 1<<9  } },
+			/* 56 */ { { Char.F, 1<<4  }, { Char.A, 1<<11 } },
+			/* 57 */ { { Char.B, 1<<5  }, { Char.C, 1<<2  } },
+			/* 58 */ { { Char.J, 1<<1  }, { Char.E, 1<<12 } },
+			/* 59 */ { { Char.I, 1<<3  }, { Char.G, 1<<6  } },
+			/* 60 */ { { Char.H, 1<<0  }, { Char.D, 1<<7  } },
+			/* 61 */ { { Char.E, 1<<7  }, { Char.H, 1<<5  } },
+			/* 62 */ { { Char.A, 1<<12 }, { Char.B, 1<<11 } },
+			/* 63 */ { { Char.C, 1<<9  }, { Char.J, 1<<0  } },
+			/* 64 */ { { Char.G, 1<<8  }, { Char.F, 1<<3  } },
+			/* 65 */ { { Char.D, 1<<10 }, { Char.I, 1<<2  } }
+		};
+
+
+		private const string[] tdaf_table = { "T", "D", "A", "F" };
+
+
+		private const uint character_table[] = {
+			/* Table I 5 of 13. */
+			  31, 7936,   47, 7808,   55, 7552,   59, 7040,   61, 6016,
+			  62, 3968,   79, 7744,   87, 7488,   91, 6976,   93, 5952,
+			  94, 3904,  103, 7360,  107, 6848,  109, 5824,  110, 3776,
+			 115, 6592,  117, 5568,  118, 3520,  121, 5056,  122, 3008,
+			 124, 1984,  143, 7712,  151, 7456,  155, 6944,  157, 5920,
+			 158, 3872,  167, 7328,  171, 6816,  173, 5792,  174, 3744,
+			 179, 6560,  181, 5536,  182, 3488,  185, 5024,  186, 2976,
+			 188, 1952,  199, 7264,  203, 6752,  205, 5728,  206, 3680,
+			 211, 6496,  213, 5472,  214, 3424,  217, 4960,  218, 2912,
+			 220, 1888,  227, 6368,  229, 5344,  230, 3296,  233, 4832,
+			 234, 2784,  236, 1760,  241, 4576,  242, 2528,  244, 1504,
+			 248,  992,  271, 7696,  279, 7440,  283, 6928,  285, 5904,
+			 286, 3856,  295, 7312,  299, 6800,  301, 5776,  302, 3728,
+			 307, 6544,  309, 5520,  310, 3472,  313, 5008,  314, 2960,
+			 316, 1936,  327, 7248,  331, 6736,  333, 5712,  334, 3664,
+			 339, 6480,  341, 5456,  342, 3408,  345, 4944,  346, 2896,
+			 348, 1872,  355, 6352,  357, 5328,  358, 3280,  361, 4816,
+			 362, 2768,  364, 1744,  369, 4560,  370, 2512,  372, 1488,
+			 376,  976,  391, 7216,  395, 6704,  397, 5680,  398, 3632,
+			 403, 6448,  405, 5424,  406, 3376,  409, 4912,  410, 2864,
+			 412, 1840,  419, 6320,  421, 5296,  422, 3248,  425, 4784,
+			 426, 2736,  428, 1712,  433, 4528,  434, 2480,  436, 1456,
+			 440,  944,  451, 6256,  453, 5232,  454, 3184,  457, 4720,
+			 458, 2672,  460, 1648,  465, 4464,  466, 2416,  468, 1392,
+			 472,  880,  481, 4336,  482, 2288,  484, 1264,  488,  752,
+			 527, 7688,  535, 7432,  539, 6920,  541, 5896,  542, 3848,
+			 551, 7304,  555, 6792,  557, 5768,  558, 3720,  563, 6536,
+			 565, 5512,  566, 3464,  569, 5000,  570, 2952,  572, 1928,
+			 583, 7240,  587, 6728,  589, 5704,  590, 3656,  595, 6472,
+			 597, 5448,  598, 3400,  601, 4936,  602, 2888,  604, 1864,
+			 611, 6344,  613, 5320,  614, 3272,  617, 4808,  618, 2760,
+			 620, 1736,  625, 4552,  626, 2504,  628, 1480,  632,  968,
+			 647, 7208,  651, 6696,  653, 5672,  654, 3624,  659, 6440,
+			 661, 5416,  662, 3368,  665, 4904,  666, 2856,  668, 1832,
+			 675, 6312,  677, 5288,  678, 3240,  681, 4776,  682, 2728,
+			 684, 1704,  689, 4520,  690, 2472,  692, 1448,  696,  936,
+			 707, 6248,  709, 5224,  710, 3176,  713, 4712,  714, 2664,
+			 716, 1640,  721, 4456,  722, 2408,  724, 1384,  728,  872,
+			 737, 4328,  738, 2280,  740, 1256,  775, 7192,  779, 6680,
+			 781, 5656,  782, 3608,  787, 6424,  789, 5400,  790, 3352,
+			 793, 4888,  794, 2840,  796, 1816,  803, 6296,  805, 5272,
+			 806, 3224,  809, 4760,  810, 2712,  812, 1688,  817, 4504,
+			 818, 2456,  820, 1432,  824,  920,  835, 6232,  837, 5208,
+			 838, 3160,  841, 4696,  842, 2648,  844, 1624,  849, 4440,
+			 850, 2392,  852, 1368,  865, 4312,  866, 2264,  868, 1240,
+			 899, 6200,  901, 5176,  902, 3128,  905, 4664,  906, 2616,
+			 908, 1592,  913, 4408,  914, 2360,  916, 1336,  929, 4280,
+			 930, 2232,  932, 1208,  961, 4216,  962, 2168,  964, 1144,
+			1039, 7684, 1047, 7428, 1051, 6916, 1053, 5892, 1054, 3844,
+			1063, 7300, 1067, 6788, 1069, 5764, 1070, 3716, 1075, 6532,
+			1077, 5508, 1078, 3460, 1081, 4996, 1082, 2948, 1084, 1924,
+			1095, 7236, 1099, 6724, 1101, 5700, 1102, 3652, 1107, 6468,
+			1109, 5444, 1110, 3396, 1113, 4932, 1114, 2884, 1116, 1860,
+			1123, 6340, 1125, 5316, 1126, 3268, 1129, 4804, 1130, 2756,
+			1132, 1732, 1137, 4548, 1138, 2500, 1140, 1476, 1159, 7204,
+			1163, 6692, 1165, 5668, 1166, 3620, 1171, 6436, 1173, 5412,
+			1174, 3364, 1177, 4900, 1178, 2852, 1180, 1828, 1187, 6308,
+			1189, 5284, 1190, 3236, 1193, 4772, 1194, 2724, 1196, 1700,
+			1201, 4516, 1202, 2468, 1204, 1444, 1219, 6244, 1221, 5220,
+			1222, 3172, 1225, 4708, 1226, 2660, 1228, 1636, 1233, 4452,
+			1234, 2404, 1236, 1380, 1249, 4324, 1250, 2276, 1287, 7188,
+			1291, 6676, 1293, 5652, 1294, 3604, 1299, 6420, 1301, 5396,
+			1302, 3348, 1305, 4884, 1306, 2836, 1308, 1812, 1315, 6292,
+			1317, 5268, 1318, 3220, 1321, 4756, 1322, 2708, 1324, 1684,
+			1329, 4500, 1330, 2452, 1332, 1428, 1347, 6228, 1349, 5204,
+			1350, 3156, 1353, 4692, 1354, 2644, 1356, 1620, 1361, 4436,
+			1362, 2388, 1377, 4308, 1378, 2260, 1411, 6196, 1413, 5172,
+			1414, 3124, 1417, 4660, 1418, 2612, 1420, 1588, 1425, 4404,
+			1426, 2356, 1441, 4276, 1442, 2228, 1473, 4212, 1474, 2164,
+			1543, 7180, 1547, 6668, 1549, 5644, 1550, 3596, 1555, 6412,
+			1557, 5388, 1558, 3340, 1561, 4876, 1562, 2828, 1564, 1804,
+			1571, 6284, 1573, 5260, 1574, 3212, 1577, 4748, 1578, 2700,
+			1580, 1676, 1585, 4492, 1586, 2444, 1603, 6220, 1605, 5196,
+			1606, 3148, 1609, 4684, 1610, 2636, 1617, 4428, 1618, 2380,
+			1633, 4300, 1634, 2252, 1667, 6188, 1669, 5164, 1670, 3116,
+			1673, 4652, 1674, 2604, 1681, 4396, 1682, 2348, 1697, 4268,
+			1698, 2220, 1729, 4204, 1730, 2156, 1795, 6172, 1797, 5148,
+			1798, 3100, 1801, 4636, 1802, 2588, 1809, 4380, 1810, 2332,
+			1825, 4252, 1826, 2204, 1857, 4188, 1858, 2140, 1921, 4156,
+			1922, 2108, 2063, 7682, 2071, 7426, 2075, 6914, 2077, 5890,
+			2078, 3842, 2087, 7298, 2091, 6786, 2093, 5762, 2094, 3714,
+			2099, 6530, 2101, 5506, 2102, 3458, 2105, 4994, 2106, 2946,
+			2119, 7234, 2123, 6722, 2125, 5698, 2126, 3650, 2131, 6466,
+			2133, 5442, 2134, 3394, 2137, 4930, 2138, 2882, 2147, 6338,
+			2149, 5314, 2150, 3266, 2153, 4802, 2154, 2754, 2161, 4546,
+			2162, 2498, 2183, 7202, 2187, 6690, 2189, 5666, 2190, 3618,
+			2195, 6434, 2197, 5410, 2198, 3362, 2201, 4898, 2202, 2850,
+			2211, 6306, 2213, 5282, 2214, 3234, 2217, 4770, 2218, 2722,
+			2225, 4514, 2226, 2466, 2243, 6242, 2245, 5218, 2246, 3170,
+			2249, 4706, 2250, 2658, 2257, 4450, 2258, 2402, 2273, 4322,
+			2311, 7186, 2315, 6674, 2317, 5650, 2318, 3602, 2323, 6418,
+			2325, 5394, 2326, 3346, 2329, 4882, 2330, 2834, 2339, 6290,
+			2341, 5266, 2342, 3218, 2345, 4754, 2346, 2706, 2353, 4498,
+			2354, 2450, 2371, 6226, 2373, 5202, 2374, 3154, 2377, 4690,
+			2378, 2642, 2385, 4434, 2401, 4306, 2435, 6194, 2437, 5170,
+			2438, 3122, 2441, 4658, 2442, 2610, 2449, 4402, 2465, 4274,
+			2497, 4210, 2567, 7178, 2571, 6666, 2573, 5642, 2574, 3594,
+			2579, 6410, 2581, 5386, 2582, 3338, 2585, 4874, 2586, 2826,
+			2595, 6282, 2597, 5258, 2598, 3210, 2601, 4746, 2602, 2698,
+			2609, 4490, 2627, 6218, 2629, 5194, 2630, 3146, 2633, 4682,
+			2641, 4426, 2657, 4298, 2691, 6186, 2693, 5162, 2694, 3114,
+			2697, 4650, 2705, 4394, 2721, 4266, 2753, 4202, 2819, 6170,
+			2821, 5146, 2822, 3098, 2825, 4634, 2833, 4378, 2849, 4250,
+			2881, 4186, 2945, 4154, 3079, 7174, 3083, 6662, 3085, 5638,
+			3086, 3590, 3091, 6406, 3093, 5382, 3094, 3334, 3097, 4870,
+			3107, 6278, 3109, 5254, 3110, 3206, 3113, 4742, 3121, 4486,
+			3139, 6214, 3141, 5190, 3145, 4678, 3153, 4422, 3169, 4294,
+			3203, 6182, 3205, 5158, 3209, 4646, 3217, 4390, 3233, 4262,
+			3265, 4198, 3331, 6166, 3333, 5142, 3337, 4630, 3345, 4374,
+			3361, 4246, 3393, 4182, 3457, 4150, 3587, 6158, 3589, 5134,
+			3593, 4622, 3601, 4366, 3617, 4238, 3649, 4174, 3713, 4142,
+			3841, 4126, 4111, 7681, 4119, 7425, 4123, 6913, 4125, 5889,
+			4135, 7297, 4139, 6785, 4141, 5761, 4147, 6529, 4149, 5505,
+			4153, 4993, 4167, 7233, 4171, 6721, 4173, 5697, 4179, 6465,
+			4181, 5441, 4185, 4929, 4195, 6337, 4197, 5313, 4201, 4801,
+			4209, 4545, 4231, 7201, 4235, 6689, 4237, 5665, 4243, 6433,
+			4245, 5409, 4249, 4897, 4259, 6305, 4261, 5281, 4265, 4769,
+			4273, 4513, 4291, 6241, 4293, 5217, 4297, 4705, 4305, 4449,
+			4359, 7185, 4363, 6673, 4365, 5649, 4371, 6417, 4373, 5393,
+			4377, 4881, 4387, 6289, 4389, 5265, 4393, 4753, 4401, 4497,
+			4419, 6225, 4421, 5201, 4425, 4689, 4483, 6193, 4485, 5169,
+			4489, 4657, 4615, 7177, 4619, 6665, 4621, 5641, 4627, 6409,
+			4629, 5385, 4633, 4873, 4643, 6281, 4645, 5257, 4649, 4745,
+			4675, 6217, 4677, 5193, 4739, 6185, 4741, 5161, 4867, 6169,
+			4869, 5145, 5127, 7173, 5131, 6661, 5133, 5637, 5139, 6405,
+			5141, 5381, 5155, 6277, 5157, 5253, 5187, 6213, 5251, 6181,
+			5379, 6165, 5635, 6157, 6151, 7171, 6155, 6659, 6163, 6403,
+			6179, 6275, 6211, 5189, 4681, 4433, 4321, 3142, 2634, 2386,
+			2274, 1612, 1364, 1252,  856,  744,  496,
+			/* Table II 2 of 13. */
+			   3, 6144,    5, 5120,    6, 3072,    9, 4608,   10, 2560,
+			  12, 1536,   17, 4352,   18, 2304,   20, 1280,   24,  768,
+			  33, 4224,   34, 2176,   36, 1152,   40,  640,   48,  384,
+			  65, 4160,   66, 2112,   68, 1088,   72,  576,   80,  320,
+			  96,  192,  129, 4128,  130, 2080,  132, 1056,  136,  544,
+			 144,  288,  257, 4112,  258, 2064,  260, 1040,  264,  528,
+			 513, 4104,  514, 2056,  516, 1032, 1025, 4100, 1026, 2052,
+			2049, 4098, 4097, 2050, 1028,  520,  272,  160
+		};
+
+
+		protected override bool validate( string data )
+		{
+			if ( (data.length != 20) &&
+			     (data.length != 25) &&
+			     (data.length != 29) &&
+			     (data.length != 31) )
+			{
+				return false;
+			}
+
+			for ( int i = 0; i < data.length; i++ )
+			{
+				if ( !data[i].isdigit() )
+				{
+					return false;
+				}
+			}
+
+			if (data[1] > '4')
+			{
+				return false; /* Invalid Barcode Identifier. */
+			}
+
+			return true;
+		}
+
+
+		protected override string encode( string data, bool checksum_flag )
+		{
+			Int104 value = Int104();
+
+			/*-----------------------------------------------------------*/
+			/* Step 1 -- Conversion of Data Fields into Binary Data      */
+			/*-----------------------------------------------------------*/
+
+			/* Step 1.a -- Routing Code */
+			int j;
+			for ( j = 20; data[j] != 0; j++ )
+			{
+				value.mult_uint( 10 );
+				value.add_uint64( data[j] - '0' );
+			}
+			switch ( j-20 )
+			{
+			case 0:
+				break;
+			case 5:
+				value.add_uint64( 1 );
+				break;
+			case 9:
+				value.add_uint64( 1 );
+				value.add_uint64( 100000 );
+				break;
+			case 11:
+				value.add_uint64( 1 );
+				value.add_uint64( 100000 );
+				value.add_uint64( 1000000000 );
+				break;
+			default:
+				assert_not_reached();
+			}
+
+			/* Step 1.b -- Tracking Code */
+			value.mult_uint( 10 );
+			value.add_uint64( data[0] - '0' );
+			value.mult_uint( 5 );
+			value.add_uint64( data[1] - '0' );
+
+			for ( int i = 2; i < 20; i++ )
+			{
+				value.mult_uint( 10 );
+				value.add_uint64( data[i] - '0' );
+			}
+
+
+			/*-----------------------------------------------------------*/
+			/* Step 2 -- Generation of 11-Bit CRC on Binary Data         */
+			/*-----------------------------------------------------------*/
+
+			uint crc11 = USPS_MSB_Math_CRC11GenerateFrameCheckSequence( value.byte );
+
+
+			/*-----------------------------------------------------------*/
+			/* Step 3 -- Conversion of Binary Data to Codewords          */
+			/*-----------------------------------------------------------*/
+			uint[] codeword = new uint[10];
+
+			codeword[9] = value.div_uint( 636 );
+			for ( int i = 8; i >= 1; i-- )
+			{
+				codeword[i] = value.div_uint( 1365 );
+			}
+			codeword[0] = value.div_uint( 659 );
+
+
+			/*-----------------------------------------------------------*/
+			/* Step 4 -- Inserting Additional Information into Codewords */
+			/*-----------------------------------------------------------*/
+
+			codeword[9] *= 2;
+			codeword[0] += ((crc11 & 0x400) != 0) ? 659 : 0;
+
+
+			/*-----------------------------------------------------------*/
+			/* Step 5 -- Conversion from Codewords to Characters         */
+			/*-----------------------------------------------------------*/
+			uint[] character = new uint[10];
+
+			for ( int i = 0; i < 10; i++ )
+			{
+				character[i] = character_table[ codeword[i] ];
+
+				if ( (crc11 & (1<<i)) != 0 )
+				{
+					character[i] = ~character[i] & 0x1FFF;
+				}
+			}
+
+
+			/*-----------------------------------------------------------*/
+			/* Step 6 -- Conversion from Characters to IMail Barcode     */
+			/*-----------------------------------------------------------*/
+			StringBuilder code = new StringBuilder();
+
+			for ( int i = 0; i < 65; i++ )
+			{
+				int d = (character[ bar_map[i].descender.i ] & bar_map[i].descender.mask) != 0 ? 1 : 0;
+				int a = (character[ bar_map[i].ascender.i ]  & bar_map[i].ascender.mask)  != 0 ? 1 : 0;
+
+				code.append( tdaf_table[ (a<<1) + d ] );
+			}
+
+
+			return code.str;
+		}
+
+
+		protected override void vectorize( string coded_data,
+		                                   bool text_flag, bool checksum_flag,
+		                                   double w, double h,
+		                                   string data, string text )
+		{
+			double x = ONECODE_HORIZ_MARGIN;
+			for ( int i = 0; i < coded_data.length; i++ )
+			{
+				double y = ONECODE_VERT_MARGIN;
+				double length;
+
+				switch ( coded_data[i] )
+				{
+				case 'T':
+					y      += ONECODE_TRACKER_OFFSET;
+					length  = ONECODE_TRACKER_HEIGHT;
+					break;
+				case 'D':
+					y      += ONECODE_DESCENDER_OFFSET;
+					length  = ONECODE_DESCENDER_HEIGHT;
+					break;
+				case 'A':
+					y      += ONECODE_ASCENDER_OFFSET;
+					length  = ONECODE_ASCENDER_HEIGHT;
+					break;
+				case 'F':
+					y      += ONECODE_FULL_OFFSET;
+					length  = ONECODE_FULL_HEIGHT;
+					break;
+				default:
+					assert_not_reached();
+				}
+				double width = ONECODE_BAR_WIDTH;
+
+				add_box( x, y, width, length );
+
+				x += ONECODE_BAR_PITCH;
+			}
+
+			this.w = x + ONECODE_HORIZ_MARGIN;
+			this.h = ONECODE_FULL_HEIGHT + 2 * ONECODE_VERT_MARGIN;
+		}
+
+
+		/***************************************************************************
+		 ** USPS_MSB_Math_CRC11GenerateFrameCheckSequence
+		 **
+		 ** Inputs:
+		 **   ByteAttayPtr is the address of a 13 byte array holding 102 bytes which
+		 **   are right justified - ie: the leftmost 2 bits of the first byte do not
+		 **   hold data and must be set to zero.
+		 **
+		 ** Outputs:
+		 **   return unsigned short - 11 bit Frame Check Sequence (right justified)
+		 **
+		 ** From Appendix C of USPS publication USPS-B-3200E, 07/08/05.
+		 ***************************************************************************/
+		private uint USPS_MSB_Math_CRC11GenerateFrameCheckSequence( uint8* ByteArrayPtr )
+		{
+			uint  GeneratorPolynomial = 0x0F35;
+			uint  FrameCheckSequence  = 0x07FF;
+			uint  Data;
+			int   ByteIndex, Bit;
+
+			/* Do most significant byte skipping the 2 most significant bits */
+			Data = *ByteArrayPtr << 5;
+			ByteArrayPtr++;
+			for ( Bit = 2; Bit < 8; Bit++ )
+			{
+				if ( ((FrameCheckSequence ^ Data) & 0x400) != 0 )
+				{
+					FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
+				}
+				else
+				{
+					FrameCheckSequence = (FrameCheckSequence << 1);
+				}
+				FrameCheckSequence &= 0x7FF;
+				Data <<= 1;
+			}
+
+			/* Do rest of the bytes */
+			for ( ByteIndex = 1; ByteIndex < 13; ByteIndex++ )
+			{
+				Data = *ByteArrayPtr << 3;
+				ByteArrayPtr++;
+				for ( Bit = 0; Bit < 8; Bit++ )
+				{
+					if ( ((FrameCheckSequence ^ Data) & 0x0400) != 0 )
+					{
+						FrameCheckSequence = (FrameCheckSequence << 1) ^ GeneratorPolynomial;
+					}
+					else
+					{
+						FrameCheckSequence = (FrameCheckSequence << 1);
+					}
+					FrameCheckSequence &= 0x7FF;
+					Data <<= 1;
+				}
+			}
+
+			return FrameCheckSequence;
+		}
+
+
+	}
+
+}
diff --git a/libglbarcode/barcode_postnet.vala b/libglbarcode/barcode_postnet.vala
new file mode 100644
index 0000000..6891fae
--- /dev/null
+++ b/libglbarcode/barcode_postnet.vala
@@ -0,0 +1,186 @@
+/*  barcode_postnet.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+using glbarcode.Constants;
+
+namespace glbarcode
+{
+
+	public class BarcodePostnet5 : BarcodePostnet
+	{
+		protected override bool validate_digits( int n_digits )
+		{
+			return (n_digits == 5);
+		}
+	}
+
+
+	public class BarcodePostnet9 : BarcodePostnet
+	{
+		protected override bool validate_digits( int n_digits )
+		{
+			return (n_digits == 9);
+		}
+	}
+
+
+	public class BarcodePostnet11 : BarcodePostnet
+	{
+		protected override bool validate_digits( int n_digits )
+		{
+			return (n_digits == 11);
+		}
+	}
+
+
+	public class BarcodeCepnet : BarcodePostnet
+	{
+		protected override bool validate_digits( int n_digits )
+		{
+			return (n_digits == 8);
+		}
+	}
+
+
+	public class BarcodePostnet : Barcode
+	{
+
+		private const double POSTNET_BAR_WIDTH      = ( 0.02    * PTS_PER_INCH );
+		private const double POSTNET_FULLBAR_HEIGHT = ( 0.125   * PTS_PER_INCH );
+		private const double POSTNET_HALFBAR_HEIGHT = ( 0.05    * PTS_PER_INCH );
+		private const double POSTNET_BAR_PITCH      = ( 0.04545 * PTS_PER_INCH );
+		private const double POSTNET_HORIZ_MARGIN   = ( 0.125   * PTS_PER_INCH );
+		private const double POSTNET_VERT_MARGIN    = ( 0.04    * PTS_PER_INCH );
+
+		private const string[] symbols = {
+			/* 0 */ "11000",
+			/* 1 */ "00011",
+			/* 2 */ "00101",
+			/* 3 */ "00110",
+			/* 4 */ "01001",
+			/* 5 */ "01010",
+			/* 6 */ "01100",
+			/* 7 */ "10001",
+			/* 8 */ "10010",
+			/* 9 */ "10100"
+		};
+
+		private const string frame_symbol = "1";
+
+
+		protected virtual bool validate_digits( int n_digits )
+		{
+			/* Accept any valid POSTNET length for general Postnet type. */
+			return (n_digits == 5) || (n_digits == 9) || (n_digits ==11);
+		}
+
+
+		protected override bool validate( string data )
+		{
+
+			int n_digits = 0;
+			for ( int i = 0; i < data.length; i++ )
+			{
+				if ( data[i].isdigit() )
+                {
+                        n_digits++;
+                }
+                else if ( (data[i] != '-') && (data[i] != ' ') )
+                {
+                        /* Only allow digits, dashes, and spaces. */
+                        return false;
+                }
+			}
+
+			return validate_digits( n_digits );
+		}
+
+
+		protected override string encode( string data, bool checksum_flag )
+		{
+			StringBuilder code = new StringBuilder();
+
+			/* Left frame bar */
+			code.append( frame_symbol );
+
+			/* process each digit, adding approptiate symbol */
+			int sum = 0;
+			for ( int i = 0; i < data.length; i++ )
+			{
+				if ( data[i].isdigit() )
+				{
+					/* Only translate the digits (0-9) */
+					int d = data[i] - '0';
+					code.append( symbols[d] );
+					sum += d;
+                }
+			}
+
+			/* Create mandatory correction character */
+			code.append( symbols[ (10 - (sum % 10)) % 10 ] );
+
+			/* Right frame bar */
+			code.append( frame_symbol );
+
+			return code.str;
+		}
+
+
+		protected override void vectorize( string coded_data,
+		                                   bool text_flag, bool checksum_flag,
+		                                   double w, double h,
+		                                   string data, string text )
+		{
+			double x = POSTNET_HORIZ_MARGIN;
+			for ( int i=0; i < coded_data.length; i++ )
+			{
+				double length, width;
+
+				double y = POSTNET_VERT_MARGIN;
+
+				switch ( coded_data[i] )
+				{
+				case '0':
+					y += POSTNET_FULLBAR_HEIGHT - POSTNET_HALFBAR_HEIGHT;
+					length = POSTNET_HALFBAR_HEIGHT;
+					break;
+				case '1':
+					length = POSTNET_FULLBAR_HEIGHT;
+					break;
+				default:
+					assert_not_reached();
+				}
+				width = POSTNET_BAR_WIDTH;
+
+				add_box( x, y, width, length );
+
+				x += POSTNET_BAR_PITCH;
+			}
+
+			this.w = x + POSTNET_HORIZ_MARGIN;
+			this.h = POSTNET_FULLBAR_HEIGHT + 2 * POSTNET_VERT_MARGIN;
+		}
+
+
+	}
+
+}
diff --git a/libglbarcode/cairo_renderer.vala b/libglbarcode/cairo_renderer.vala
new file mode 100644
index 0000000..b234b53
--- /dev/null
+++ b/libglbarcode/cairo_renderer.vala
@@ -0,0 +1,127 @@
+/*  cairo_renderer.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+
+namespace glbarcode
+{
+
+	public class CairoRenderer : Renderer
+	{
+
+		private const double FONT_SCALE  = 72.0/96;
+		private const string FONT_FAMILY = "Sans";
+
+
+		private Cairo.Context cr;
+		private bool          fill;
+
+
+		public CairoRenderer( Cairo.Context cr, bool fill = true )
+		{
+			this.cr   = cr;
+			this.fill = fill;
+		}
+
+
+		public override void draw_begin( double w, double h )
+		{
+		}
+
+
+		public override void draw_end()
+		{
+		}
+
+
+		public override void draw_box( ShapeBox box )
+		{
+			cr.rectangle( box.x, box.y, box.w, box.h );
+			if ( fill )
+			{
+				cr.fill();
+			}
+		}
+
+
+		public override void draw_text( ShapeText text )
+		{
+			Pango.FontDescription desc = new Pango.FontDescription();
+			desc.set_family( FONT_FAMILY );
+			desc.set_size( (int)(text.fsize * Pango.SCALE * FONT_SCALE + 0.5) );
+
+			Pango.Layout layout = Pango.cairo_create_layout( cr );
+			layout.set_font_description( desc );
+
+			layout.set_text( text.s, -1);
+
+			int iw, ih;
+			layout.get_size( out iw, out ih );
+			double layout_width = (double)iw / (double)Pango.SCALE;
+
+			double x_offset = layout_width / 2.0;
+			double y_offset = 0.2 * text.fsize;
+
+			cr.move_to( (text.x - x_offset), (text.y - y_offset) );
+			if ( fill )
+			{
+				Pango.cairo_show_layout( cr, layout );
+			}
+			else
+			{
+				Pango.cairo_layout_path( cr, layout );
+			}
+		}
+
+
+		public override void draw_ring( ShapeRing ring )
+		{
+			cr.new_sub_path();
+			cr.arc( ring.x, ring.y, ring.r + ring.line_width/2, 0.0, 2*Math.PI );
+			cr.close_path();
+			cr.new_sub_path();
+			cr.arc( ring.x, ring.y, ring.r - ring.line_width/2, 0.0, -2*Math.PI );
+			cr.close_path();
+			if ( fill )
+			{
+				cr.fill();
+			}
+		}
+
+
+		public override void draw_hexagon( ShapeHexagon hexagon )
+		{
+			cr.move_to( hexagon.x,                   hexagon.y );
+			cr.line_to( hexagon.x + 0.433*hexagon.h, hexagon.y + 0.25*hexagon.h );
+			cr.line_to( hexagon.x + 0.433*hexagon.h, hexagon.y + 0.75*hexagon.h );
+			cr.line_to( hexagon.x,                   hexagon.y +      hexagon.h );
+			cr.line_to( hexagon.x - 0.433*hexagon.h, hexagon.y + 0.75*hexagon.h );
+			cr.line_to( hexagon.x - 0.433*hexagon.h, hexagon.y + 0.25*hexagon.h );
+			cr.close_path();
+			if ( fill )
+			{
+				cr.fill();
+			}
+		}
+
+	}
+
+}
diff --git a/libglbarcode/constants.vala b/libglbarcode/constants.vala
new file mode 100644
index 0000000..0b94759
--- /dev/null
+++ b/libglbarcode/constants.vala
@@ -0,0 +1,36 @@
+/*  constants.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+
+namespace glbarcode
+{
+
+	namespace Constants
+	{
+
+		public const double PTS_PER_INCH = 72.0;
+		public const double PTS_PER_MM   =  2.83464566929;
+		public const double PTS_PER_CM   = 10*PTS_PER_MM;
+
+	}
+
+}
diff --git a/libglbarcode/demo/Makefile.am b/libglbarcode/demo/Makefile.am
new file mode 100644
index 0000000..10c96e3
--- /dev/null
+++ b/libglbarcode/demo/Makefile.am
@@ -0,0 +1,37 @@
+NULL = 
+
+bin_PROGRAMS = glbarcode
+
+glbarcode_SOURCES = \
+	glbarcode.vala \
+	$(NULL)
+
+glbarcode_LDADD = \
+	-L.. -lglbarcode-4.0 \
+	$(LIBGLBARCODE_LIBS) \
+	$(NULL)
+
+INCLUDES = \
+	$(LIBGLBARCODE_CFLAGS) \
+	-DLOCALEDIR=\""$(localedir)"\" \
+	-DDATADIR=\""$(datadir)"\" \
+	-DLIBGLBARCODE_BRANCH=\""$(LIBGLBARCODE_BRANCH)"\" \
+	-I.. \
+	$(NULL)
+
+VALAFLAGS = \
+	--pkg posix \
+	--pkg gobject-2.0 \
+	--pkg cairo \
+	--pkg pangocairo \
+	--vapidir .. \
+	../libglbarcode-4.vapi \
+	$(NULL)
+
+EXTRA_DIST = \
+	$(NULL)
+
+DISTCLEANFILES = \
+	$(NULL)
+
+
diff --git a/libglbarcode/demo/glbarcode.vala b/libglbarcode/demo/glbarcode.vala
new file mode 100644
index 0000000..0928bf7
--- /dev/null
+++ b/libglbarcode/demo/glbarcode.vala
@@ -0,0 +1,128 @@
+/*  glbarcode.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+using GLib;
+
+namespace glbarcode
+{
+
+	class Demo
+	{
+
+		private static string type;
+		private static bool   text;
+		private static bool   checksum;
+		private static double w;
+		private static double h;
+		private static string data;
+		private static double ppi;
+
+		private const OptionEntry[] option_entries = {
+			{ "type",      't', 0, OptionArg.STRING, ref type,
+			  "barcode type",
+			  "TYPE"
+			},
+			{ "text", 'x', 0, OptionArg.NONE, ref text,
+			  "Show literal text (if supported)",
+			  null
+			},
+			{ "checksum", 'c', 0, OptionArg.NONE, ref checksum,
+			  "Include checksum (if optional)",
+			  null
+			},
+			{ "width", 'w', 0, OptionArg.DOUBLE, ref w,
+			  "Suggested width (points)",
+			  "WIDTH"
+			},
+			{ "height", 'h', 0, OptionArg.DOUBLE, ref h,
+			  "Suggested height (points)",
+			  "HEIGHT"
+			},
+			{ "data", 'd', 0, OptionArg.STRING, ref data,
+			  "Barcode data",
+			  "DATA"
+			},
+			{ "resolution", 'r', 0, OptionArg.STRING, ref ppi,
+			  "Resolution (Pixels per Inch)",
+			  "PPI"
+			},
+			{ null }
+		};
+
+
+		internal static int main( string[] args )
+		{
+			/* Set defaults. */
+			type      = "Code39";
+			text      = false;
+			checksum  = false;
+			w         = 144;
+			h         = 72;
+			data      = "";
+			ppi       = 72;
+
+			/* Parse command line arguments. */
+			var option_context = new OptionContext( "" );
+			option_context.set_summary( "Command line demo program for libglbarcode." );
+			option_context.add_main_entries( option_entries, null );
+
+			try {
+				option_context.parse( ref args );
+			}
+			catch ( OptionError e )
+			{
+				message( "%s\nRun '%s --help' to see a full list of available command line options.\n",
+				         e.message, args[0] );
+				return -1;
+			}
+
+			/* Initialize barcode factory. */
+			glbarcode.Factory.init();
+
+			/* Create barcode object. */
+			glbarcode.Barcode barcode = glbarcode.Factory.create_barcode( type, text, checksum, w, h, data );
+
+			/* Create and initialize cairo surface and context to render to. */
+			double scale = ppi / glbarcode.Constants.PTS_PER_INCH;
+			var surface = new Cairo.ImageSurface( Cairo.Format.ARGB32,
+			                                      (int)(scale*barcode.w),
+			                                      (int)(scale*barcode.h) );
+			var cr = new Cairo.Context( surface );
+			cr.scale( scale, scale );
+			cr.rectangle( 0, 0, barcode.w, barcode.h );
+			cr.set_source_rgba( 1, 1, 1, 1 );
+			cr.fill();
+
+			/* Render barcode to cairo surface. */
+			cr.set_source_rgba( 0, 0, 0, 1 );
+			barcode.render( new glbarcode.CairoRenderer( cr ) );
+
+			/* Write surface to output file. */
+			message( "Creating output.png\n" );
+			surface.write_to_png( "output.png" );
+
+			return 0;
+		}
+
+	}
+
+}
+
+
diff --git a/libglbarcode/factory.vala b/libglbarcode/factory.vala
new file mode 100644
index 0000000..1a6e0e5
--- /dev/null
+++ b/libglbarcode/factory.vala
@@ -0,0 +1,151 @@
+/*  factory.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+
+namespace glbarcode
+{
+
+	private uint str_case_hash( string s )
+	{
+		uint h = 5381;
+
+		for ( int i = 0; i < s.length; i++ )
+		{
+			h = (h << 5) + h + s[i].tolower();
+		}
+		return h;
+	}
+
+
+	private bool str_case_equal( string a, string b )
+	{
+		return a.ascii_casecmp( b ) == 0;
+	}
+
+
+	/**
+	 * Barcode factory.
+	 */
+	public class Factory
+	{
+		private static bool initialized = false;
+		private static HashTable<string,Type> mappings;
+
+
+		static construct
+		{
+			mappings = new HashTable<string, Type>( str_case_hash, str_case_equal );
+
+			/* Register built-in types. */
+			register_type( "Code39",          typeof(BarcodeCode39) );
+			register_type( "Code39Ext",       typeof(BarcodeCode39Extended) );
+			register_type( "ONECODE",         typeof(BarcodeOneCode) );
+			register_type( "POSTNET",         typeof(BarcodePostnet) );
+			register_type( "POSTNET-5",       typeof(BarcodePostnet5) );
+			register_type( "POSTNET-9",       typeof(BarcodePostnet9) );
+			register_type( "POSTNET-11",      typeof(BarcodePostnet11) );
+			register_type( "CEPNET",          typeof(BarcodeCepnet) );
+
+			initialized = true;
+		}
+
+
+		/**
+		 * Initialize barcode factory.
+		 *
+		 * Initializes the singleton barcode factory.
+		 */
+		public static void init()
+		{
+			if ( !initialized )
+			{
+				new Factory();
+			}
+			else
+			{
+				message( "glbarcode.Factory already initialized.\n" );
+			}
+		}
+
+
+		/**
+		 * Register barcode type with factory.
+		 *
+		 * @param name barcode type, e.g. "Code39"
+		 * @param type barcode object class type, e.g. typeof(BarcodeCode39).  Must be a subtype of Barcode.
+		 */
+		public static void register_type( string name,
+		                                  Type   type )
+		{
+			if ( type.is_a( typeof(Barcode) ) )
+			{
+				mappings.insert( name, type );
+			}
+			else
+			{
+				message( "glBarcode.Factory.register_type: invalid barcode type: %s\n", type.name() );
+			}
+		}
+
+
+		/**
+		 * Create a new barcode object.
+		 *
+		 * @param name barcode type, e.g. "Code39"
+		 * @param text_flag show literal text under barcode
+		 * @param checksum_flag include a checksum
+		 * @param w suggested width of barcode
+		 * @param h suggested height of barcode
+		 * @param data data to encode in barcode
+		 */
+		public static Barcode? create_barcode( string  name,
+		                                       bool    text_flag,
+		                                       bool    checksum_flag,
+		                                       double  w,
+		                                       double  h,
+		                                       string? data )
+		{
+			Barcode? barcode = null;
+
+			Type type = mappings.lookup( name );
+
+			if ( mappings.contains( name ) )
+			{
+				barcode = Object.new( type,
+				                      text_flag     : text_flag,
+				                      checksum_flag : checksum_flag,
+				                      w             : w,
+				                      h             : h,
+				                      data          : data ) as Barcode;
+			}
+			else
+			{
+				message( "Unknown barcode type: \"%s\"\n", name );
+			}
+
+			return barcode;
+		}
+
+
+	}
+
+}
diff --git a/libglbarcode/renderer.vala b/libglbarcode/renderer.vala
new file mode 100644
index 0000000..2d7a3dd
--- /dev/null
+++ b/libglbarcode/renderer.vala
@@ -0,0 +1,71 @@
+/*  renderer.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+
+namespace glbarcode
+{
+
+	public abstract class Renderer
+	{
+		public void render( double w, double h, List<Shape> shapes )
+		{
+			draw_begin( w, h );
+
+			foreach (Shape shape in shapes)
+			{
+				if ( shape is ShapeBox )
+				{
+					draw_box( shape as ShapeBox );
+				}
+				else if ( shape is ShapeText )
+				{
+					draw_text( shape as ShapeText );
+				}
+				else if ( shape is ShapeRing )
+				{
+					draw_ring( shape as ShapeRing );
+				}
+				else if ( shape is ShapeHexagon )
+				{
+					draw_hexagon( shape as ShapeHexagon );
+				}
+				else
+				{
+					assert_not_reached();
+				}
+			}
+
+			draw_end();
+		}
+
+
+		protected abstract void draw_begin( double w, double h );
+		protected abstract void draw_end();
+
+		protected abstract void draw_box(     ShapeBox     box );
+		protected abstract void draw_text(    ShapeText    text );
+		protected abstract void draw_ring(    ShapeRing    ring );
+		protected abstract void draw_hexagon( ShapeHexagon hexagon );
+
+	}
+
+}
diff --git a/libglbarcode/shape.vala b/libglbarcode/shape.vala
new file mode 100644
index 0000000..fbd31c1
--- /dev/null
+++ b/libglbarcode/shape.vala
@@ -0,0 +1,182 @@
+/*  shape.vala
+ *
+ *  Copyright (C) 2012  Jim Evins <evins snaught com>
+ *
+ *  This file is part of libglbarcode.
+ *
+ *  libglabels is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU Lesser General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  libglabels 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 Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public License
+ *  along with libglabels.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+using GLib;
+
+namespace glbarcode
+{
+
+	public abstract class Shape
+	{
+		public double x;
+		public double y;
+	}
+
+	/**
+	 * A solid box drawing primitive.
+	 *
+	 *<programlisting>
+	 *
+	 * @ =  origin (x,y) from top left corner of barcode
+	 *
+	 *              @---------+
+	 *              |         |
+	 *              |         |
+	 *              |         |
+	 *              |         | h
+	 *              |         |
+	 *              |         |
+	 *              |         |
+	 *              +---------+
+	 *                   w
+	 *
+	 *</programlisting>
+	 *
+	 * All units are in points ( 1 point = 1/72 inch ).
+	 */
+	public class ShapeBox : Shape
+	{
+		public double              w;
+		public double              h;
+
+		public ShapeBox( double x, double y, double w, double h )
+		{
+			this.x = x;
+			this.y = y;
+			this.w = w;
+			this.h = h;
+		}
+	}
+
+
+	/**
+	 * A character string drawing primitive.
+	 *
+	 *<programlisting>
+	 *
+	 * @ =  origin (x,y) from top left corner of barcode
+	 *
+	 *              ____        _  ------------------
+	 *             /    \      | |                  ^
+	 *            /  /\  \     | |                  |
+	 *           /  /__\  \    | |___     ____      |
+	 *          /  ______  \   | ._  \   /  __|     | ~fsize
+	 *         /  /      \  \  | |_)  | |  (__      |
+	 *        /__/        \__\ |_.___/   \____|     |
+	 *                                              v
+	 *                           @ ------------------
+	 *                           x = horizontal center
+	 *
+	 *</programlisting>
+	 *
+	 * All units are in points ( 1 point = 1/72 inch ).
+	 */
+	public class ShapeText : Shape
+	{
+		public double              fsize;
+		public string              s;
+
+		public ShapeText( double x, double y, double fsize, string s )
+		{
+			this.x     = x;
+			this.y     = y;
+			this.fsize = fsize;
+			this.s     = s;
+		}
+	}
+
+
+	/**
+	 * A ring (an open circle) drawing primitive.
+	 *
+	 *<programlisting>
+	 *
+	 * @ = origin (x,y) is centre of circle
+	 *
+	 *                v  line_width
+	 *           _.-""""-._
+	 *         .'   ____   `.
+	 *        /   .'  ^ `.   \
+	 *       |   /        \   |
+	 *       |   |    @---|---|------
+	 *       |   \        /   |     |
+	 *        \   `.____.'   /      | r
+	 *         `._    ...._.'.......v
+	 *            `-....-'
+	 *
+	 *</programlisting>
+	 *
+	 * All units are in points ( 1 point = 1/72 inch ).
+	 */
+	public class ShapeRing : Shape
+	{
+		public double              r;
+		public double              line_width;
+
+		public ShapeRing( double x, double y, double r, double line_width )
+		{
+			this.x          = x;
+			this.y          = y;
+			this.r          = r;
+			this.line_width = line_width;
+		}
+	}
+
+
+	/**
+	 * A solid regular hexagon (oriented with vertexes at top and bottom) drawing primitive.
+	 *
+	 *<programlisting>
+	 *
+	 * @ = origin (x,y) is top of hexagon
+	 *
+	 *                  @ ------------------
+	 *              _-"   "-_              ^
+	 *          _-"           "-_          |
+	 *       +"                   "+       |
+	 *       |                     |       |
+	 *       |                     |       |
+	 *       |                     |       | h
+	 *       |                     |       |
+	 *       |                     |       |
+	 *       +_                   _+       |
+	 *         "-_             _-"         |
+	 *            "-_       _-"            |
+	 *               "-_ _-"               v
+	 *                  " ------------------
+	 *
+	 *</programlisting>
+	 *
+	 * All units are in points ( 1 point = 1/72 inch ).
+	 */
+	public class ShapeHexagon : Shape
+	{
+		public double              h;
+
+		public ShapeHexagon( double x, double y, double h )
+		{
+			this.x = x;
+			this.y = y;
+			this.h = h;
+		}
+	}
+
+}



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