[glabels/vala] Added EAN-13 support. Assorted cleanup.



commit dc8a124b9408a5cfae02a525781d351a6f13da93
Author: Jim Evins <evins snaught com>
Date:   Sat Sep 15 18:02:15 2012 -0400

    Added EAN-13 support.  Assorted cleanup.

 glabels/barcode_backends.vala             |    3 +
 libglbarcode/barcode.vala                 |   67 ++++++-
 libglbarcode/barcode_code39.vala          |   28 ++-
 libglbarcode/barcode_code39_extended.vala |    9 +
 libglbarcode/barcode_onecode.vala         |   33 +++-
 libglbarcode/barcode_postnet.vala         |   50 +++++-
 libglbarcode/barcode_upc.vala             |  273 +++++++++++++++++++++--------
 libglbarcode/factory.vala                 |    1 +
 8 files changed, 361 insertions(+), 103 deletions(-)
---
diff --git a/glabels/barcode_backends.vala b/glabels/barcode_backends.vala
index 72a4cb7..d57c22f 100644
--- a/glabels/barcode_backends.vala
+++ b/glabels/barcode_backends.vala
@@ -67,6 +67,9 @@ namespace glabels
 			register( "UPC-A", _("UPC - A"),
 			          true, false, true, false, "12345678901", false, 11 );
 
+			register( "EAN-13", _("EAN - 13"),
+			          true, false, true, false, "123456789012", false, 12 );
+
 #if HAVE_LIBBARCODE
 
 			register( "gnu-barcode:EAN", _("GNU-Barcode : EAN (any)"),
diff --git a/libglbarcode/barcode.vala b/libglbarcode/barcode.vala
index 9693296..7fa9d47 100644
--- a/libglbarcode/barcode.vala
+++ b/libglbarcode/barcode.vala
@@ -24,41 +24,72 @@ using GLib;
 namespace glbarcode
 {
 
+	/**
+	 * Base class for all barcode types
+	 */
 	public abstract class Barcode : Object
 	{
 
+		/*
+		 * Construction parameters
+		 */
 		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; }
 
+		/*
+		 * Status parameters
+		 */
 		public bool    is_empty      { get; private set; }
 		public bool    is_data_valid { get; private set; }
 
+		/*
+		 * List of vectorized drawing primitives
+		 */
 		private List<Shape>   shapes;
 
 
+		/**
+		 * Validate data method.
+		 */
 		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 )
+		/**
+		 * Pre-process data method.
+		 */
+		protected virtual string preprocess( string data )
 		{
 			return data;
 		}
 
 
-		protected virtual string preprocess( string data )
+		/**
+		 * Encode data method.
+		 */
+		protected abstract string encode( string canon_data );
+
+
+		/**
+		 * Vectorize encoded data method.
+		 */
+		protected abstract void   vectorize( string coded_data, string cooked_data, string display_text );
+
+
+		/**
+		 * Prepare data for display as text part of barcode.
+		 */
+		protected virtual string prepare_text( string data )
 		{
 			return data;
 		}
 
 
+		/**
+		 * Construction.
+		 */
 		construct
 		{
 			if ( (data == null) || (data == "") )
@@ -74,11 +105,12 @@ namespace glbarcode
 				{
 					is_data_valid = true;
 
-					string display_text = to_text( data );
 					string cooked_data  = preprocess( data );
-					string coded_data   = encode( cooked_data, checksum_flag );
+					string coded_data   = encode( cooked_data );
+
+					string display_text = prepare_text( data );
 
-					vectorize( coded_data, text_flag, checksum_flag, w, h, cooked_data, display_text );
+					vectorize( coded_data, cooked_data, display_text );
 				}
 				else
 				{
@@ -88,6 +120,9 @@ namespace glbarcode
 		}
 
 
+		/**
+		 * Add box.  Used by vectorize method.
+		 */
 		protected void add_box( double x, double y, double w, double h )
 		{
 			ShapeBox box = new ShapeBox( x, y, w, h );
@@ -95,6 +130,9 @@ namespace glbarcode
 		}
 
 
+		/**
+		 * Add string.  Used by vectorize method.
+		 */
 		protected void add_string(  double x, double y, double fsize, string s )
 		{
 			ShapeText text = new ShapeText( x, y, fsize, s );
@@ -102,6 +140,9 @@ namespace glbarcode
 		}
 
 
+		/**
+		 * Add ring.  Used by vectorize method.
+		 */
 		protected void add_ring(    double x, double y, double r, double line_width )
 		{
 			ShapeRing ring = new ShapeRing( x, y, r, line_width );
@@ -109,6 +150,9 @@ namespace glbarcode
 		}
 
 
+		/**
+		 * Add hexagon.  Used by vectorize method.
+		 */
 		protected void add_hexagon( double x, double y, double h )
 		{
 			ShapeHexagon hexagon = new ShapeHexagon( x, y, h );
@@ -116,6 +160,9 @@ namespace glbarcode
 		}
 
 
+		/**
+		 * Render barcode using supplied renderer.
+		 */
 		public void render( Renderer renderer )
 		{
 			renderer.render( w, h, shapes );
diff --git a/libglbarcode/barcode_code39.vala b/libglbarcode/barcode_code39.vala
index ec6fc98..441a2cc 100644
--- a/libglbarcode/barcode_code39.vala
+++ b/libglbarcode/barcode_code39.vala
@@ -25,9 +25,15 @@ using glbarcode.Constants;
 namespace glbarcode
 {
 
+	/**
+	 * Code39 Barcode
+	 */
 	public class BarcodeCode39 : Barcode
 	{
 
+		/*
+		 * Constants
+		 */
 		private const double MIN_X       = ( 0.01 *  PTS_PER_INCH );
 		private const double N           = 2.5;
 		private const double MIN_I       = MIN_X;
@@ -92,6 +98,9 @@ namespace glbarcode
 		private const string frame_symbol = "NwNnWnWnN";
 
 
+		/**
+		 * Code39 data validation method
+		 */
 		protected override bool validate( string data )
 		{
 			for ( int i = 0; i < data.length; i++ )
@@ -108,7 +117,10 @@ namespace glbarcode
 		}
 
 
-		protected override string encode( string canon_data, bool checksum_flag )
+		/**
+		 * Code39 data encoding method
+		 */
+		protected override string encode( string canon_data )
 		{
 			StringBuilder code = new StringBuilder();
 
@@ -140,10 +152,10 @@ namespace glbarcode
 		}
 
 
-		protected override void vectorize( string coded_data,
-		                                   bool text_flag, bool checksum_flag,
-		                                   double w, double h,
-		                                   string data, string text )
+		/**
+		 * Code39 vectorize method
+		 */
+		protected override void vectorize( string coded_data, string data, string text )
 		{
 			/* determine width and establish horizontal scale */
 			double min_l;
@@ -229,11 +241,11 @@ namespace glbarcode
 				add_string( x_quiet + width/2, height + (h_text_area-text_size)/2, text_size, starred_text );
 			}
 
-			this.w = width + 2*x_quiet;
-			this.h = text_flag ? height + h_text_area : height;
+			/* Overwrite requested size with actual size. */
+			w = width + 2*x_quiet;
+			h = text_flag ? height + h_text_area : height;
 		}
 
-
 	}
 
 }
diff --git a/libglbarcode/barcode_code39_extended.vala b/libglbarcode/barcode_code39_extended.vala
index aef2754..0fc05ba 100644
--- a/libglbarcode/barcode_code39_extended.vala
+++ b/libglbarcode/barcode_code39_extended.vala
@@ -24,6 +24,9 @@ using GLib;
 namespace glbarcode
 {
 
+	/**
+	 * Extended Code39 Barcode
+	 */
 	public class BarcodeCode39Extended : BarcodeCode39
 	{
 
@@ -64,6 +67,9 @@ namespace glbarcode
 		};
 
 
+		/**
+		 * Extended Code39 data validation method.
+		 */
 		protected override bool validate( string data )
 		{
 			for ( int i=0; i < data.length; i++ )
@@ -78,6 +84,9 @@ namespace glbarcode
 		}
 
 
+		/**
+		 * Extended Code39 preprocess data method.
+		 */
 		protected override string preprocess( string data )
 		{
 			StringBuilder extended_data = new StringBuilder("");
diff --git a/libglbarcode/barcode_onecode.vala b/libglbarcode/barcode_onecode.vala
index c541bb2..49bac94 100644
--- a/libglbarcode/barcode_onecode.vala
+++ b/libglbarcode/barcode_onecode.vala
@@ -25,9 +25,15 @@ using glbarcode.Constants;
 namespace glbarcode
 {
 
+	/**
+	 * ONE CODE (USPS Intelligent Mail) Barcode
+	 */
 	public class BarcodeOneCode : Barcode
 	{
 
+		/*
+		 * Constants
+		 */
 		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 );
@@ -42,6 +48,9 @@ namespace glbarcode
 		private const double ONECODE_VERT_MARGIN      = ( 0.028  * PTS_PER_INCH );
 
 
+		/**
+		 * 104-bit Integer Representation
+		 */
 		private struct Int104
 		{
 			public uint8[] byte;
@@ -91,6 +100,9 @@ namespace glbarcode
 		}
 
 
+		/*
+		 * Encoding tables
+		 */
 		private enum Char
 		{
 			A = 0,
@@ -328,6 +340,9 @@ namespace glbarcode
 		};
 
 
+		/**
+		 * ONE CODE data validation method.
+		 */
 		protected override bool validate( string data )
 		{
 			if ( (data.length != 20) &&
@@ -355,7 +370,10 @@ namespace glbarcode
 		}
 
 
-		protected override string encode( string data, bool checksum_flag )
+		/**
+		 * ONE CODE data encoding method.
+		 */
+		protected override string encode( string data )
 		{
 			Int104 value = Int104();
 
@@ -465,10 +483,10 @@ namespace glbarcode
 		}
 
 
-		protected override void vectorize( string coded_data,
-		                                   bool text_flag, bool checksum_flag,
-		                                   double w, double h,
-		                                   string data, string text )
+		/**
+		 * ONE CODE vectorization method.
+		 */
+		protected override void vectorize( string coded_data, string data, string text )
 		{
 			double x = ONECODE_HORIZ_MARGIN;
 			for ( int i = 0; i < coded_data.length; i++ )
@@ -504,8 +522,9 @@ namespace glbarcode
 				x += ONECODE_BAR_PITCH;
 			}
 
-			this.w = x + ONECODE_HORIZ_MARGIN;
-			this.h = ONECODE_FULL_HEIGHT + 2 * ONECODE_VERT_MARGIN;
+			/* Overwrite requested size with actual size. */
+			w = x + ONECODE_HORIZ_MARGIN;
+			h = ONECODE_FULL_HEIGHT + 2 * ONECODE_VERT_MARGIN;
 		}
 
 
diff --git a/libglbarcode/barcode_postnet.vala b/libglbarcode/barcode_postnet.vala
index 9ce5bb8..f09f2f5 100644
--- a/libglbarcode/barcode_postnet.vala
+++ b/libglbarcode/barcode_postnet.vala
@@ -25,6 +25,9 @@ using glbarcode.Constants;
 namespace glbarcode
 {
 
+	/**
+	 * 5 Digit POSTNET Barcode (ZIP only)
+	 */
 	public class BarcodePostnet5 : BarcodePostnet
 	{
 		protected override bool validate_digits( int n_digits )
@@ -34,6 +37,9 @@ namespace glbarcode
 	}
 
 
+	/**
+	 * 9 Digit POSTNET Barcode (ZIP+4)
+	 */
 	public class BarcodePostnet9 : BarcodePostnet
 	{
 		protected override bool validate_digits( int n_digits )
@@ -43,6 +49,9 @@ namespace glbarcode
 	}
 
 
+	/**
+	 * 11 Digit POSTNET Barcode (ZIP + 4 + Delivery Point)
+	 */
 	public class BarcodePostnet11 : BarcodePostnet
 	{
 		protected override bool validate_digits( int n_digits )
@@ -52,6 +61,9 @@ namespace glbarcode
 	}
 
 
+	/**
+	 * 8 Digit CEPNET Barcode (Brazillian, based on POSTNET)
+	 */
 	public class BarcodeCepnet : BarcodePostnet
 	{
 		protected override bool validate_digits( int n_digits )
@@ -61,9 +73,15 @@ namespace glbarcode
 	}
 
 
+	/**
+	 * POSTNET Barcode (Any USPS Length)
+	 */
 	public class BarcodePostnet : Barcode
 	{
 
+		/*
+		 * Constants
+		 */
 		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 );
@@ -71,6 +89,10 @@ namespace glbarcode
 		private const double POSTNET_HORIZ_MARGIN   = ( 0.125   * PTS_PER_INCH );
 		private const double POSTNET_VERT_MARGIN    = ( 0.04    * PTS_PER_INCH );
 
+
+		/*
+		 * Encoding symbology
+		 */
 		private const string[] symbols = {
 			/* 0 */ "11000",
 			/* 1 */ "00011",
@@ -86,14 +108,20 @@ namespace glbarcode
 
 		private const string frame_symbol = "1";
 
-
+		
+		/**
+		 * POSTNET general validate length method
+		 */
 		protected virtual bool validate_digits( int n_digits )
 		{
-			/* Accept any valid POSTNET length for general Postnet type. */
+			/* Accept any valid POSTNET length. */
 			return (n_digits == 5) || (n_digits == 9) || (n_digits ==11);
 		}
 
 
+		/**
+		 * POSTNET data validation method
+		 */
 		protected override bool validate( string data )
 		{
 
@@ -115,7 +143,10 @@ namespace glbarcode
 		}
 
 
-		protected override string encode( string data, bool checksum_flag )
+		/**
+		 * POSTNET data encoding method
+		 */
+		protected override string encode( string data )
 		{
 			StringBuilder code = new StringBuilder();
 
@@ -145,10 +176,10 @@ namespace glbarcode
 		}
 
 
-		protected override void vectorize( string coded_data,
-		                                   bool text_flag, bool checksum_flag,
-		                                   double w, double h,
-		                                   string data, string text )
+		/**
+		 * POSTNET vectorization method
+		 */
+		protected override void vectorize( string coded_data, string data, string text )
 		{
 			double x = POSTNET_HORIZ_MARGIN;
 			for ( int i=0; i < coded_data.length; i++ )
@@ -176,8 +207,9 @@ namespace glbarcode
 				x += POSTNET_BAR_PITCH;
 			}
 
-			this.w = x + POSTNET_HORIZ_MARGIN;
-			this.h = POSTNET_FULLBAR_HEIGHT + 2 * POSTNET_VERT_MARGIN;
+			/* Overwrite requested size with actual size. */
+			w = x + POSTNET_HORIZ_MARGIN;
+			h = POSTNET_FULLBAR_HEIGHT + 2 * POSTNET_VERT_MARGIN;
 		}
 
 
diff --git a/libglbarcode/barcode_upc.vala b/libglbarcode/barcode_upc.vala
index 8594164..ec9692f 100644
--- a/libglbarcode/barcode_upc.vala
+++ b/libglbarcode/barcode_upc.vala
@@ -25,29 +25,97 @@ using glbarcode.Constants;
 namespace glbarcode
 {
 
-	public class BarcodeUPCA : Barcode
+	/**
+	 * UPC-A Barcode
+	 */
+	public class BarcodeUPCA : BarcodeBaseUPC
 	{
+		static construct
+		{
+			end_bars_thresh  = 7;
+			end_bars_modules = 11;
+		}
+
+		protected override bool validate_digits( int n_digits )
+		{
+			return (n_digits == 11);
+		}
+
+		protected override void vectorize_text( string text,
+		                                        double size1, double size2,
+		                                        double x1_left, double x1_right, double y1,
+		                                        double x2_left, double x2_right, double y2 )
+		{
+			add_string( x2_left,  y2, size2, text[0:1] );
+			add_string( x1_left,  y1, size1, text[1:6] );
+			add_string( x1_right, y1, size1, text[6:11] );
+			add_string( x2_right, y2, size2, text[11:12] );
+		}
+	}
+
+
+	/**
+	 * EAN-13 Barcode
+	 */
+	public class BarcodeEAN13 : BarcodeBaseUPC
+	{
+		static construct
+		{
+			end_bars_thresh  = 3;
+			end_bars_modules = 3;
+		}
 
+		protected override bool validate_digits( int n_digits )
+		{
+			return (n_digits == 12);
+		}
+
+		protected override void vectorize_text( string text,
+		                                        double size1, double size2,
+		                                        double x1_left, double x1_right, double y1,
+		                                        double x2_left, double x2_right, double y2 )
+		{
+			add_string( x2_left,  y2, size2, text[0:1] );
+			add_string( x1_left,  y1, size1, text[1:7] );
+			add_string( x1_right, y1, size1, text[7:13] );
+		}
+	}
+
+
+	/**
+	 * Base class for UPC-A and EAN-13
+	 */
+	public abstract class BarcodeBaseUPC : Barcode
+	{
+
+		/*
+		 * Constants
+		 */
 		private const int    QUIET_MODULES   = 9;
 
 		private const double BASE_MODULE_SIZE      = ( 0.01 *  PTS_PER_INCH );
-		private const double BASE_FONT_SIZE        = 7.2;
+		private const double BASE_FONT_SIZE        = 7;
 		private const double BASE_TEXT_AREA_HEIGHT = 11;
 
 
-		private const string[] symbols = {
-			/* left:  sBsB */
-			/* right: BsBs */
-			/* 0 */  "3211",
-			/* 1 */  "2221",
-			/* 2 */  "2122",
-			/* 3 */  "1411",
-			/* 4 */  "1132",
-			/* 5 */  "1231",
-			/* 6 */  "1114",
-			/* 7 */  "1312",
-			/* 8 */  "1213",
-			/* 9 */  "3112"
+		/*
+		 * Symbology
+		 */
+		private string[,] symbols = {
+			/*          Odd     Even  */
+			/*    Left: sBsB    sBsB  */
+			/*   Right: BsBs    ----  */
+			/*                        */
+			/* 0 */  { "3211", "1123" },
+			/* 1 */  { "2221", "1222" },
+			/* 2 */  { "2122", "2212" },
+			/* 3 */  { "1411", "1141" },
+			/* 4 */  { "1132", "2311" },
+			/* 5 */  { "1231", "1321" },
+			/* 6 */  { "1114", "4111" },
+			/* 7 */  { "1312", "2131" },
+			/* 8 */  { "1213", "3121" },
+			/* 9 */  { "3112", "2113" }
 		};
 
 		private const string s_symbol = "111";   /* BsB */
@@ -55,9 +123,46 @@ namespace glbarcode
 		private const string m_symbol = "11111"; /* sBsBs */
 
 
-		private string check_digit;
+		/*
+		 * Parity selection
+		 */
+		private enum Parity { ODD=0, EVEN=1 }
+
+		private Parity[,] parity = {
+			/*                Position 1,  Position 2,  Position 3,  Position 4,  Position 5,  Position 6
+			/* 0 (UPC-A) */ { Parity.ODD,  Parity.ODD,  Parity.ODD,  Parity.ODD,  Parity.ODD,  Parity.ODD  },
+			/* 1         */ { Parity.ODD,  Parity.ODD,  Parity.EVEN, Parity.ODD,  Parity.EVEN, Parity.EVEN },
+			/* 2         */ { Parity.ODD,  Parity.ODD,  Parity.EVEN, Parity.EVEN, Parity.ODD,  Parity.EVEN },
+			/* 3         */ { Parity.ODD,  Parity.ODD,  Parity.EVEN, Parity.EVEN, Parity.EVEN, Parity.ODD  },
+			/* 4         */ { Parity.ODD,  Parity.EVEN, Parity.ODD,  Parity.ODD,  Parity.EVEN, Parity.EVEN },
+			/* 5         */ { Parity.ODD,  Parity.EVEN, Parity.EVEN, Parity.ODD,  Parity.ODD,  Parity.EVEN },
+			/* 6         */ { Parity.ODD,  Parity.EVEN, Parity.EVEN, Parity.EVEN, Parity.ODD,  Parity.ODD  },
+			/* 7         */ { Parity.ODD,  Parity.EVEN, Parity.ODD,  Parity.EVEN, Parity.ODD,  Parity.EVEN },
+			/* 8         */ { Parity.ODD,  Parity.EVEN, Parity.ODD,  Parity.EVEN, Parity.EVEN, Parity.ODD  },
+			/* 9         */ { Parity.ODD,  Parity.EVEN, Parity.EVEN, Parity.ODD,  Parity.EVEN, Parity.ODD  }
+		};
+
+
+		private int first_digit_val;
+		private int check_digit_val;
 
+		/*
+		 * Adaptation parameters and methods that are unique to each concrete class.
+		 */
+		protected static int end_bars_thresh;  /* Number of end bars and spaces that are long. */
+		protected static int end_bars_modules; /* Number of modules consumed by long end bars. */
 
+		protected abstract bool validate_digits( int n_digits );
+
+		protected abstract void vectorize_text( string text,
+		                                        double size1, double size2,
+		                                        double x1_left, double x1_right, double y1,
+		                                        double x2_left, double x2_right, double y2 );
+
+
+		/*
+		 * Validate data
+		 */
 		protected override bool validate( string data )
 		{
 			int n_digits = 0;
@@ -70,20 +175,19 @@ namespace glbarcode
 				}
 				else if ( data[i] != ' ')
 				{
-					/* Only allow digits and spaces. */
+					/* Only allow digits and spaces -- ignoring spaces. */
 					return false;
 				}
 			}
 
-			if ( n_digits != 11 )
-			{
-				return false;
-			}
-
-			return true;
+			/* validate n_digits (call implementation from concrete class) */
+			return validate_digits( n_digits );
 		}
 
 
+		/*
+		 * Pre-process data before encoding
+		 */
 		protected override string preprocess( string data )
 		{
 			StringBuilder stripped_data = new StringBuilder();
@@ -96,14 +200,29 @@ namespace glbarcode
 				}
 			}
 
-			return stripped_data.str;
+			if ( stripped_data.len == 11 )
+			{
+				/* UPC-A */
+				first_digit_val = 0;
+				return stripped_data.str;
+			}
+			else
+			{
+				/* EAN-13 */
+				first_digit_val = stripped_data.str[0].digit_value();
+				return stripped_data.str[1:stripped_data.len];
+			}
+
 		}
 
 
-		protected override string encode( string canon_data, bool checksum_flag )
+		/*
+		 * Encode data
+		 */
+		protected override string encode( string canon_data )
 		{
 			int sum_odd  = 0;
-			int sum_even = 0;
+			int sum_even = first_digit_val;
 
 			StringBuilder code = new StringBuilder();
 
@@ -111,10 +230,10 @@ namespace glbarcode
 			code.append( s_symbol );
 
 			/* Left 6 digits */
-			for ( int i=0; i < 6; i++ )
+			for ( int i = 0; i < 6; i++ )
 			{
 				int c_value = canon_data[i].digit_value();
-				code.append( symbols[c_value] );
+				code.append( symbols[c_value,parity[first_digit_val,i]] );
 
 				if ( (i & 1) == 0 )
 				{
@@ -130,10 +249,10 @@ namespace glbarcode
 			code.append( m_symbol );
 
 			/* Right 5 digits */
-			for ( int i=6; i < 11; i++ )
+			for ( int i = 6; i < 11; i++ )
 			{
 				int c_value = canon_data[i].digit_value();
-				code.append( symbols[c_value] );
+				code.append( symbols[c_value,Parity.ODD] );
 
 				if ( (i & 1) == 0 )
 				{
@@ -146,29 +265,39 @@ namespace glbarcode
 			}
 
 			/* Check digit */
-			int check = (3*sum_odd + sum_even) % 10;
-			if ( check != 0 )
+			check_digit_val = (3*sum_odd + sum_even) % 10;
+			if ( check_digit_val != 0 )
 			{
-				check = 10 - check;
+				check_digit_val = 10 - check_digit_val;
 			}
-			code.append( symbols[check] );
-			check_digit = check.to_string(); /* Save for display. */
-
+			code.append( symbols[check_digit_val,Parity.ODD] );
 
 			/* Right frame symbol */
 			code.append( e_symbol );
 
+			/* Append a final zero length space to make the length of the encoded string even. */
+			code.append( "0" );
+
 			return code.str;
 		}
 
 
-		protected override void vectorize( string coded_data,
-		                                   bool text_flag, bool checksum_flag,
-		                                   double w, double h,
-		                                   string data, string text )
+		/*
+		 * Process data for display as text
+		 */
+		protected override string prepare_text( string data )
+		{
+			return data.concat( check_digit_val.to_string(), null );
+		}
+
+
+		/*
+		 * Vectorize
+		 */
+		protected override void vectorize( string coded_data, string data, string text )
 		{
 			/* determine width and establish horizontal scale */
-			int n_modules = 7*(data.length+1) + 11;
+			int n_modules     = 7*(data.length+1) + 11;
 
 			double scale;
 			if ( w == 0 )
@@ -184,30 +313,37 @@ namespace glbarcode
 					scale = 1.0;
 				}
 			}
-			double width = (n_modules + 2*QUIET_MODULES) * scale * BASE_MODULE_SIZE;
+			double width       = scale * BASE_MODULE_SIZE * (n_modules + 2*QUIET_MODULES);
+			double x_quiet     = scale * BASE_MODULE_SIZE * QUIET_MODULES;
 
-			/* determine text parameters */
+			/* determine bar height */
 			double h_text_area = scale * BASE_TEXT_AREA_HEIGHT;
-			double text_size1  = scale * BASE_FONT_SIZE;
-			double text_size2  = 0.75*text_size1;
-			double text_c1 = (QUIET_MODULES + 5 + n_modules/4) * scale * BASE_MODULE_SIZE;
-			double text_c2 = (QUIET_MODULES - 4 + 3*n_modules/4) * scale * BASE_MODULE_SIZE;
+			double h_bar1      = double.max( (h - h_text_area), width/2 );
+			double h_bar2      = h_bar1 + h_text_area/2;
 
-			/* determine bar height */
-			double h_bar1 = double.max( (h - h_text_area), width/2 );
-			double h_bar2 = h_bar1 + h_text_area/2;
+			/* determine text parameters */
+			double text_size1    = scale * BASE_FONT_SIZE;
+			double text_size2    = 0.75*text_size1;
+
+			double text_x1_left  = scale * BASE_MODULE_SIZE * (QUIET_MODULES + end_bars_modules/2 + n_modules/4);
+			double text_x1_right = scale * BASE_MODULE_SIZE * (QUIET_MODULES - end_bars_modules/2 + 3*n_modules/4);
+			double text_x2_left  = scale * BASE_MODULE_SIZE * QUIET_MODULES/2;
+			double text_x2_right = scale * BASE_MODULE_SIZE * (n_modules + 3*QUIET_MODULES/2);
+
+			double text_y1       = h_bar2 - text_size1/2;
+			double text_y2       = h_bar2 - text_size2/2;
 
-			/* determine horizontal quiet zone */
-			double x_quiet = QUIET_MODULES * scale * BASE_MODULE_SIZE;
 
 			/* now traverse the code string and draw each bar */
+			int n_bars_spaces = coded_data.length - 1; /* coded data has dummy "0" on end. */
+
 			double x1 = x_quiet;
-			for ( int i=0; i < coded_data.length; i+=2 )
+			for ( int i = 0; i < n_bars_spaces; i += 2 )
 			{
 				double h_bar;
 
-				if ( ( (i > 7) && (i < (coded_data.length/2-1)) ) ||
-				     ( (i > (coded_data.length/2+1)) && (i < (coded_data.length-7)) ) )
+				if ( ( (i > end_bars_thresh)     && (i < (n_bars_spaces/2-1))             ) ||
+				     ( (i > (n_bars_spaces/2+1)) && (i < (n_bars_spaces-end_bars_thresh)) ) )
 				{
 					h_bar = h_bar1;
 				}
@@ -217,25 +353,24 @@ namespace glbarcode
 				}
 
 				/* Bar */
-				int bar_w = coded_data[i].digit_value();
-
-				add_box( x1, 0.0, (bar_w*scale*BASE_MODULE_SIZE - INK_BLEED), h_bar );
-				x1 += bar_w * scale * BASE_MODULE_SIZE;
+				int w_bar = coded_data[i].digit_value();
+				add_box( x1, 0.0, (w_bar*scale*BASE_MODULE_SIZE - INK_BLEED), h_bar );
+				x1 += w_bar * scale * BASE_MODULE_SIZE;
 
 				/* Space */
-				int space_w = coded_data[i+1].digit_value();
-
-				x1 += space_w * scale * BASE_MODULE_SIZE;
+				int w_space = coded_data[i+1].digit_value();
+				x1 += w_space * scale * BASE_MODULE_SIZE;
 			}
 
-			/* draw text */
-			add_string( x_quiet/2,       h_bar2 - text_size2/2, text_size2, text[0:1] );
-			add_string( text_c1,         h_bar2 - text_size1/2, text_size1, text[1:6] );
-			add_string( text_c2,         h_bar2 - text_size1/2, text_size1, text[6:11] );
-			add_string( width-x_quiet/2, h_bar2 - text_size2/2, text_size2, check_digit );
+			/* draw text (call implementation from concrete class) */
+			vectorize_text( text,
+			                text_size1, text_size2,
+			                text_x1_left, text_x1_right, text_y1,
+			                text_x2_left, text_x2_right, text_y2 );
 
-			this.w = width;
-			this.h = h_bar1 + h_text_area;
+			/* Overwrite requested size with actual size. */
+			w = width;
+			h = h_bar1 + h_text_area;
 		}
 
 
diff --git a/libglbarcode/factory.vala b/libglbarcode/factory.vala
index 09950bc..9c7307b 100644
--- a/libglbarcode/factory.vala
+++ b/libglbarcode/factory.vala
@@ -65,6 +65,7 @@ namespace glbarcode
 			register_type( "POSTNET-11",      typeof(BarcodePostnet11) );
 			register_type( "CEPNET",          typeof(BarcodeCepnet) );
 			register_type( "UPC-A",           typeof(BarcodeUPCA) );
+			register_type( "EAN-13",          typeof(BarcodeEAN13) );
 
 			initialized = true;
 		}



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