Clone in a terminal:
Commit ef90c26
Johan Mattsson - 2012-07-30T20:18:55+00:00
ef90c2637666e7301cd8eea69905011ce60c47a1johan.mattsson.m@gmail.com

test case improvments

Changed files (10)

Diff

diff --git a/src/Argument.vala b/src/Argument.valanew file mode 100644index 0000000..fcf0f21--- /dev/null+++ b/src/Argument.vala@@ -0,0 +1,217 @@+/*+    Copyright (C) 2012 Johan Mattsson++    This program is free software: you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation, either version 3 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License+    along with this program.  If not, see <http://www.gnu.org/licenses/>.+*/++namespace Supplement {+	+class Argument : GLib.Object {+	+	List<string> args;+	+	public Argument (string line) {+		args = new List<string> ();+		set_argument (line);+	}+	+	public Argument.command_line (string[] arg) {	+		args = new List<string> ();++		foreach (string a in arg) {+			args.append (a);+		}+	}+	+	/** returns 0 if valid or index the bad parameter. */ +	public int validate () {+		string prev = "";+		int i = 0;+		foreach (string a in args) {+			+			// program name+			if (i == 0) {+				prev = a;+				i++;+				continue;+			}++			// a single character, like -t+			if (!a.has_prefix ("--") && a.has_prefix ("-")) {+				a = expand_param (a);+			}+			+			print (@"\"$a\"\n");+			+			// valid parameter+			if (a == "--autosave" || a == "--exit" || a == "--slow" || a == "--help" || a == "--test") {+				prev = a;+				i++;+				continue;+			} else if (a.has_prefix ("--")) {+				return i;+			}+			+			// not argument to test+			if (prev != "--test") {+				return i;+			}+			+			prev = a;+			i++;+		}+		+		return 0;+	}+	+	public void print_all () {+		print (@"$(args.length ()) arguments:\n");+		+		foreach (string p in args) {+			print (@"$p\n");+		}+	}+	+	public bool has_argument (string param) {+		return (get_argument (param) != null);+	}+	+	/** Get commandline argument. */+	public string? get_argument (string param) {+		int i = 0;+		string? n;+		string p;++		if (param.substring (0, 1) != "-") {+			warning (@"parameters must begin with \"-\" got $param");+			return null;+		}++		foreach (string s in args) {++			// this is content not a parameter +			if (s.substring (0, 1) != "-") continue;++			// we might need to expand -t to test fo instance+			if (s.substring (0, 2) != "--") {+				p = expand_param (s);+			} else {				+				p = s;+			}+			+			if (param == p) {+				if (i + 2 >= args.length ()) {+					return "";+				}+				+				n = args.nth (i + 2).data;+				if (n == null) {+					return "";+				}+				+				if (args.nth (i + 2).data.substring (0, 1) == "-") {+					return "";+				}+				+				return args.nth (i + 2).data;+			}+			+			i++;+		}+		+		return null;+	}++	private void print_padded (string cmd, string desc) {+		int l = 25 - cmd.char_count ();++		stdout.printf (cmd);+		+		for (int i = 0; i < l; i++) {+				stdout.printf (" ");+		}+		+		stdout.printf (desc);+		stdout.printf ("\n");+	}++	/** Return full command line parameter for an abbrevation.+	 * -t becomes --test.+	 */+	private string expand_param (string? param) {+		if (param == null) return "";+		var p = (!) param;+		+		if (p.length == 0) return "";+		if (p.get_char (0) != '-') return "";+		if (p.char_count () != 2) return "";+		+		switch (p.get_char (1)) {+			case 'a': +				return "--autosave";+			case 'e': +				return "--exit";+			case 's': +				return "--slow";+			case 'h': +				return "--help";+			case 't': +				return "--test";+		}+		+		return "";+	}++	private void set_argument (string arg) {+		int i = 0;+		int a;+		string n;+		+		if (arg.char_count () <= 1) {+			return;+		}+		+		do {+			a = arg.index_of (" ", i + 1);+			n = arg.substring (i, a - i);+			+			if (n.index_of ("\"") == 0) {+				a = arg.index_of ("\"", i + 1);+				n = arg.substring (i, a - i + 1);+			}+					+			args.append (n);+			+			i += n.char_count () + 1;+		} while (i < arg.char_count ());+	}++	public void print_help () +		requires (args.length () > 0)+	{+		stdout.printf ("Usage: ");+		stdout.printf (args.nth (0).data);+		stdout.printf (" [OPTION ...]\n");++		print_padded ("-e, --exit", "exit if a testcase failes");+		print_padded ("-h, --help", "show this message");+		print_padded ("-s, --slow", "sleep between each command in test suite");+		print_padded ("-t, --test [TEST]", "run test case");+		+		stdout.printf ("\n");+	}++}+	+}diff --git a/src/Font.vala b/src/Font.valaindex 916e18a..5dfac9a 100644--- a/src/Font.vala+++ b/src/Font.vala@@ -280,40 +280,71 @@ class Font : GLib.Object { 		return get_glyph (n) != null; 	} -	public void create_not_def () {+	public Glyph get_nonmarking_return () {+		Glyph ret;+		+		if (has_glyph ("nonmarkingreturn")) {+			return (!) get_glyph ("nonmarkingreturn");+		}+				+		ret = new Glyph ("nonmarkingreturn");+		ret.set_unassigned (true);+		ret.left_limit = 0;+		ret.right_limit = 0;+		+		return ret;+	}+		+	public Glyph get_null_character () {+		Glyph n;+		+		if (has_glyph ("null")) {+			return (!) get_glyph ("null");+		}+		+		n = new Glyph ("null");+		n.set_unassigned (true);+		n.left_limit = 0;+		n.right_limit = 0;+		+		return n;+	}+	+	public Glyph get_not_def_character () { 		Glyph g;+ 		Path p; 		Path i; 		-		return_if_fail (!has_glyph ("notdef."));+		if (has_glyph ("notdef")) {+			return (!) get_glyph ("notdef");+		} 		-		g = new Glyph ("notdef.", 0);+		g = new Glyph ("notdef", 0); 		p = new Path (); 		i = new Path (); 		 		g.set_unassigned (true);-		g.left_limit = -120;-		g.right_limit = 120;+		g.left_limit = -33;+		g.right_limit = 33; 		-		p.add (-100, 100);-		p.add (100, 100);-		p.add (100, -100);-		p.add (-100, -100);+		p.add (-30, 30);+		p.add (30, 30);+		p.add (30, -30);+		p.add (-30, -30); 		p.close (); 		-		i.add (-80, 80);-		i.add (80, 80);-		i.add (80, -80);-		i.add (-80, -80);+		i.add (-25, 25);+		i.add (25, 25);+		i.add (25, -25);+		i.add (-25, -25); 		i.reverse (); 		i.close ();  		g.add_path (i); 		g.add_path (p);-		-		add_glyph (g);-		-		assert (has_glyph ("notdef."));++		return g; 	} 		 	public void add_glyph (Glyph glyph) {@@ -327,6 +358,11 @@ class Font : GLib.Object { 	public void add_glyph_collection (GlyphCollection glyph_collection) { 		GlyphCollection? gc = get_glyph_collection (glyph_collection.get_name ()); 		+		if (glyph_collection.get_name () == "") {+			warning ("Refusing to insert glyph with name \"\", null character should be named null.");+			return;+		}+		 		if (gc != null) { 			warning ("glyph has been inserted"); 		}@@ -651,7 +687,7 @@ class Font : GLib.Object { 		gcl = get_glyph_collection (g.get_name ()); 		 		if (gcl != null) {-			warning (@"glyph \"$(g.get_name ())\"does already exist");+			warning (@"glyph \"$(g.get_name ())\" does already exist"); 		} 		 		if (g.is_unassigned ()) {@@ -661,15 +697,15 @@ class Font : GLib.Object { 				g.name = @"($(++next_unindexed))"; 			} 			-			unassigned_glyphs.insert ((!) gc);+			add_glyph_collection ((!) gc); 		} else if (gcl == null) { 			gc = new GlyphCollection (g);-			glyph_cache.insert ((!) gc);+			add_glyph_collection ((!) gc); 		} else { 			stderr.printf (@"Glyph collection does already have an entry for $(g.get_name ()) char $((uint64) g.unichar_code).\n"); 			gc = new GlyphCollection (g); 			g.name = @"($(++next_unindexed))";-			unassigned_glyphs.insert ((!) gc);+			add_glyph_collection ((!) gc); 		} 		 		// take xheight from appropriate lower case letter@@ -951,7 +987,7 @@ class Font : GLib.Object { 				 		if (gc == null) { 			gc = new GlyphCollection (g);-			glyph_cache.insert ((!) gc);+			add_glyph_collection ((!) gc); 		} else { 			((!)gc).insert_glyph (g, selected); 		}diff --git a/src/GlyphRange.vala b/src/GlyphRange.valaindex de827b8..f1be1bc 100644--- a/src/GlyphRange.vala+++ b/src/GlyphRange.vala@@ -95,7 +95,7 @@ class GlyphRange { 		add_range (c, c); 	} 	-	public unichar get_length () {+	public uint32 get_length () { 		unichar l = len; 		l += unassigned.length (); 		return l;@@ -196,8 +196,7 @@ class GlyphRange { 		}  		r = ranges.first ().data;--		ti = (index < r.length ()) ? index - 1: index;+		ti = index;  		foreach (UniRange u in ranges) { 			ti -= u.length ();@@ -215,7 +214,7 @@ class GlyphRange { 		return sb.str; 	} 	-	public unichar length () {+	public uint32 length () { 		return len; 	} diff --git a/src/GlyphTable.vala b/src/GlyphTable.valaindex 4b26ab7..c924b34 100644--- a/src/GlyphTable.vala+++ b/src/GlyphTable.vala@@ -91,6 +91,7 @@ class GlyphTable : GLib.Object { 		 		if (g.get_name () == "") { 			warning (@"No proper name for glyph collection. g.get_name (): \"$(g.get_name ())\"");+			return false; 		}  		if (find (g.get_name ()) != null) {diff --git a/src/OpenFontFormatWriter.vala b/src/OpenFontFormatWriter.valaindex 4f8361a..cf3cf25 100644--- a/src/OpenFontFormatWriter.vala+++ b/src/OpenFontFormatWriter.vala@@ -45,13 +45,7 @@ class OpenFontFormatWriter : Object  { 		Glyph? g;
 		unowned List<Table> tables;
 		unichar indice = 0;
-		
-		if (!font.has_glyph ("notdef.")) {
-			font.create_not_def ();
-		}
-		
-		assert (font.has_glyph ("notdef."));
-		
+
 		directory_table.process ();	
 		tables = directory_table.get_tables ();
 
@@ -436,16 +430,6 @@ class LocaTable : Table { 		if (glyph_offsets != null) delete glyph_offsets;
 	}
 	
-	public uint32 get_last_glyph_length () {
-		return_if_fail (glyph_offsets != null);
-		
-		if (size == 0) {
-			warning ("No glyphs in loca table");
-		}
-		
-		return glyph_offsets[size + 1];
-	}
-	
 	public uint32 get_offset (uint32 i) {
 		return_if_fail (glyph_offsets != null);
 		
@@ -472,10 +456,6 @@ class LocaTable : Table { 			warning (@"No offset for glyph $i. Requires (0 <= $i < $(size + 1)");
 		}
 		
-		if (i == size -1) {
-			return get_last_glyph_length () == 0;
-		}
-		
 		return glyph_offsets[i] == glyph_offsets[i + 1];
 	}
 	
@@ -526,8 +506,6 @@ class LocaTable : Table { 		for (int i = 0; i < size; i++) {
 			print (@"get_offset ($i): $(get_offset (i))\n");
 		}
-		
-		print (@"get_last_glyph_length (): $(get_last_glyph_length ())\n");
 	}
 	
 	public void process (GlyfTable glyf_table, HeadTable head_table) {
@@ -569,8 +547,9 @@ class LocaTable : Table { 			warn_if_reached ();
 		}
 		
-		if (!(glyf_table.location_offsets.length () == font.length ())) {
-			warning (@"(glyf_table.location_offsets.length () == font.length ()) ($(glyf_table.location_offsets.length ()) == $(font.length ()))");
+		// err maybe not +1
+		if (!(glyf_table.location_offsets.length () == glyf_table.glyphs.length () + 1)) {
+			warning (@"(glyf_table.location_offsets.length () == glyf_table.glyphs.length () + 1) ($(glyf_table.location_offsets.length ()) == $(glyf_table.glyphs.length () + 1))");
 		}
 		
 		font_data = fd;		
@@ -594,12 +573,18 @@ class GlyfTable : Table { 	public int16 ymax = 0;
 	
 	public LocaTable loca_table;
-	public List<uint32> location_offsets;
+	
+	public List<uint32> location_offsets; 
+
+	// list of glyphs sorted in the order we expect to find them in a
+	// ttf font. notdef is the firs glyph followed by null and nonmarkingreturn.	
+	public List<Glyph> glyphs;
 	
 	public GlyfTable (LocaTable l) {
 		id = "glyf";
 		loca_table = l;
 		location_offsets = new List<uint32> ();
+		glyphs = new List<Glyph> ();
 	}	
 	
 	/** Add this glyph from thread safe callback to the running gui. */
@@ -625,17 +610,17 @@ class GlyfTable : Table { 
 		print (@"loca.size: $(loca.size)\n");
 		
-		// notdef. character:
+		// notdef character:
 		character = cmap.get_char (0);
 
 		if (character != 0) {
-			warning ("notdef. has a another value in cmap table");
+			warning ("notdef has a another value in cmap table");
 		}
 		
 		glyph = parse_next_glyf (dis, 0, 0, out xmin, out xmax, units_per_em);
 		glyph.left_limit = 0;
 		glyph.right_limit = glyph.left_limit + hmtx_table.get_advance (0);
-		glyph.name = "notdef.";
+		glyph.name = "notdef";
 		glyph.set_unassigned (true);		
 		add_glyph (glyph);				
 		
@@ -657,10 +642,12 @@ class GlyfTable : Table { 					
 					glyph = parse_next_glyf (dis, character, glyph_offset, out xmin, out xmax, units_per_em);
 					
-					//glyph.left_limit = xmin - hmtx_table.get_lsb (i);
+					glyph.left_limit = xmin - hmtx_table.get_lsb (i);
 					glyph.left_limit = 0;
 					glyph.right_limit = glyph.left_limit + hmtx_table.get_advance (i);
 					
+					print (@"$(glyph.right_limit) = $(glyph.left_limit) + $(hmtx_table.get_advance (i))\n");
+					
 					if (xmin > glyph.right_limit || xmax < glyph.left_limit) {
 						warning (@"Glyph $(name.str) is outside of it's box.");
 						glyph.left_limit = xmin;
@@ -1081,14 +1068,12 @@ class GlyfTable : Table { 
 		Font font = Supplement.get_current_font ();
 		
-		// glyph need padding too, but to two byte boundries 
-		if (fd.length () % 2 != 0) {
-			fd.add (0);
+		g.remove_empty_paths ();
+		if (g.path_list.length () == 0) {
+			// ensure that location_offsets == location_offset + 1
+			return;
 		}
 		
-		// set values for loca table
-		location_offsets.append (fd.length ());
-		
 		g.remove_empty_paths ();
 		
 		ncontours = (int16) g.path_list.length ();
@@ -1167,35 +1152,51 @@ class GlyfTable : Table { 				prev = e.y + font.base_line;
 			}
 		}
+		
+		// glyph need padding too, but to two byte boundries 
+		if (fd.length () % 2 != 0) {
+			fd.add (0);
+		}
 	}
 
-	public void process () {
-		FontData fd = new FontData ();
-		uint32 indice;
+	// necessary in order to have glyphs sorted according to ttf specification
+	public void create_glyph_table () {
 		Glyph? gl;
 		Glyph g;
 		Font font = Supplement.get_current_font ();
-		
-		assert (font.has_glyph ("notdef."));
-		
-		// add notdef. character at index zero
-		gl = font.get_glyph ("notdef.");
-		process_glyph ((!)gl, fd);
-	
-		
-		// add glyphs
+		uint32 indice;
+
+		// add notdef. character at index zero + other special chars first
+		glyphs.append (font.get_not_def_character ());
+		// glyphs.append (font.get_null_character ());
+		// glyphs.append (font.get_nonmarking_return ());
+			
+		// add glyphs, first all assigned then the unassigned ones
 		for (indice = 0; (gl = font.get_glyph_indice (indice)) != null; indice++) {		
 			g = (!) gl;
 			
-			if (g.name == "notdef.") {
+			if (g.name == "notdef" || g.name == "null"  || g.name == "nonmarkingreturn") {
 				continue;
 			}
 			
+			glyphs.append (g);
+		}	
+		
+	}
+
+	public void process () {
+		FontData fd = new FontData ();
+		
+		create_glyph_table ();
+		
+		foreach (Glyph g in glyphs) {
+			// set values for loca table
+			location_offsets.append (fd.length ());
+			
 			process_glyph (g, fd);
 		}
 
-		// last entry in loca table
-		location_offsets.append (fd.length ());
+		location_offsets.append (fd.length ()); // last entry in loca table is special
 		
 		fd.pad ();
 						
@@ -1409,14 +1410,12 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		// print (@"New range $(s.str) - $(e.str) delta: $delta_offset, range: $range_offset\n");
 	}
 	
-	public void process (FontData fd) {
+	public void process (FontData fd, GlyfTable glyf_table) {
 		GlyphRange glyph_range = new GlyphRange ();
-		Font font = Supplement.get_current_font ();
 		unowned List<UniRange> ranges;
 			
 		unichar i = 0;
 		Glyph? gl;
-		Glyph g;
 		
 		uint16 seg_count_2;
 		uint16 seg_count;
@@ -1427,10 +1426,18 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		uint16 gid_length = 0;
 		
 		uint32 indice;
-		
-		for (i = 0; (gl = font.get_glyph_indice (i)) != null; i++) {
-			g = (!) gl;
-			
+		uint32 first_assigned = 0;
+
+		foreach (Glyph g in glyf_table.glyphs) {
+			if (!g.is_unassigned ()) {
+				first_assigned++;
+			} else {
+				break;
+			}
+		}
+		print (@"first_assigned $first_assigned\n");
+		first_assigned = 1;
+		foreach (Glyph g in glyf_table.glyphs) {
 			if (!g.is_unassigned ()) {
 				glyph_range.add_single (g.unichar_code);
 			}
@@ -1460,7 +1467,7 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		fd.add_ushort (range_shift);
 		
 		// end codes
-		indice = 0;
+		indice = first_assigned;
 		foreach (UniRange u in ranges) {
 			if (u.stop >= 0xFFFF) {
 				warning ("Not implemented yet.");
@@ -1474,7 +1481,7 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		fd.add_ushort (0); // Reserved
 		
 		// start codes
-		indice = 1; // one since first glyph is notdef.
+		indice = first_assigned; // since first glyph are notdef, null and nonmarkingreturn
 		foreach (UniRange u in ranges) {
 			if (u.start >= 0xFFFF) {
 				warning ("Not implemented yet.");
@@ -1486,7 +1493,7 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		fd.add_ushort (0xFFFF); // Last segment
 
 		// delta
-		indice = 1;
+		indice = first_assigned;
 		foreach (UniRange u in ranges) {
 			
 			if ((u.start - indice) > 0xFFFF && u.start > indice) {
@@ -1654,7 +1661,7 @@ class CmapTable : Table { 		print (@"subtable_offset: $(subtable_offset)\n");
 		
 		fd.add_ulong (subtable_offset);
-		cmap.process (fd);
+		cmap.process (fd, glyf_table);
 
 		// padding
 		fd.pad ();
@@ -1846,10 +1853,12 @@ class HheaTable : Table { 		
 	GlyfTable glyf_table;
 	HeadTable head_table;
+	HmtxTable hmtx_table;
 	
-	public HheaTable (GlyfTable g, HeadTable h) {
+	public HheaTable (GlyfTable g, HeadTable h, HmtxTable hm) {
 		glyf_table = g;
 		head_table = h;
+		hmtx_table = hm;
 		id = "hhea";
 	}
 	
@@ -1902,14 +1911,14 @@ class HheaTable : Table { 		fd.add_16 ((int16) (-1 * (font.top_position - font.base_line))); // Ascender
 		fd.add_16 ((int16) (-1 * font.bottom_position)); // Descender
 		fd.add_16 (0); // LineGap
+				
+		fd.add_u16 (hmtx_table.max_advance); // maximum advance width value in 'hmtx' table.
 		
-		fd.add_u16 (0); // advanceWidthMax Maximum advance width value in 'hmtx' table.
-		
-		fd.add_16 (0); // minLeftSideBearing
-		fd.add_16 (0); // minRightSideBearing
-		fd.add_16 (0); // xMaxExtent Max(lsb + (xMax - xMin))
+		fd.add_16 (hmtx_table.min_lsb); // min left side bearing
+		fd.add_16 (hmtx_table.min_rsb); // min right side bearing
+		fd.add_16 (hmtx_table.max_extent); // x max extent Max(lsb + (xMax - xMin))
 		
-		fd.add_16 (0); // caretSlopeRise
+		fd.add_16 (1); // caretSlopeRise
 		fd.add_16 (0); // caretSlopeRun
 		fd.add_16 (0); // caretOffset
 		
@@ -1937,11 +1946,18 @@ class HmtxTable : Table { 	uint16* advance_width = null;
 	uint16* left_side_bearing = null;
 	uint16* left_side_bearing_monospaced = null;
-		
+	
+	public int16 max_advance = 0;
+	public int16 max_extent = 0;
+	public int16 min_lsb = 0; 
+	public int16 min_rsb = 0;
+			
 	HeadTable head_table;
+	GlyfTable glyf_table;
 	
-	public HmtxTable (HeadTable h) {
+	public HmtxTable (HeadTable h, GlyfTable gt) {
 		head_table = h;
+		glyf_table = gt;
 		id = "hmtx";
 	}
 	
@@ -1951,16 +1967,16 @@ class HmtxTable : Table { 	}
 
 	public double get_advance (uint32 i) {
-		return_if_fail (i < nmetrics);
-		return_if_fail (advance_width != null);
+		return_val_if_fail (i < nmetrics, 0.0);
+		return_val_if_fail (advance_width != null, 0.0);
 		
 		return advance_width[i] * 1000 / head_table.get_units_per_em ();
 	}
 		
 	/** Get left side bearing relative to xmin. */
 	public double get_lsb (uint32 i) {
-		return_if_fail (i < nmetrics);
-		return_if_fail (left_side_bearing != null);
+		return_val_if_fail (i < nmetrics, 0.0);
+		return_val_if_fail (left_side_bearing != null, 0.0);
 		
 		return left_side_bearing[i] * 1000 / head_table.get_units_per_em ();
 	}
@@ -1989,6 +2005,8 @@ class HmtxTable : Table { 		for (int i = 0; i < nmetrics; i++) {
 			advance_width[i] = dis.read_ushort ();
 			left_side_bearing[i] = dis.read_short ();
+			
+			print (@"advance_width[i] $(advance_width[i])    $(left_side_bearing[i]) \n");
 		}
 		
 		for (int i = 0; i < nmonospaced; i++) {
@@ -1999,18 +2017,53 @@ class HmtxTable : Table { 	public void process () {
 		FontData fd = new FontData ();
 		Font font = Supplement.get_current_font ();
-		Glyph g;
+
+		int16 advance;
+		int16 extent;
+		int16 rsb;
+		int16 lsb;
+		
+		double xmin;
+		double ymin;
+		double xmax;
+		double ymax;
 		
 		// advance and lsb
-		for (uint i = 0; i < font.length (); i++) {
-			g = (!) font.get_glyph_indice (i);
-			fd.add_u16 ((uint16) (g.right_limit - g.left_limit));
-			fd.add_16 (0);
+		foreach (Glyph g in glyf_table.glyphs) {
+			g.boundries (out xmin, out ymin, out xmax, out ymax);
+
+			lsb = (int16) (xmin - g.left_limit);
+			advance = (int16) (g.right_limit - g.left_limit);
+			extent = (int16) (lsb + (xmax - xmin));
+			rsb = (int16) (advance - extent);
+
+			print (@"$(g.name) advance: $advance  = $((int16) (g.right_limit))  -  $((int16) (g.left_limit))\n");
+						
+			fd.add_u16 (advance);
+			fd.add_16 (lsb);
+	
+			if (advance > max_advance) {
+				max_advance = advance;
+			}
+			
+			if (extent > max_extent) {
+				max_extent = extent;
+			}
+			
+			if (rsb < min_rsb) {
+				min_rsb = rsb;
+			}
+
+			if (lsb < min_lsb) {
+				min_lsb = lsb;
+			}
 		}
 		
 		// monospaced lsb ...
 		
 		font_data = fd;
+		
+		warn_if_fail (max_advance != 0);
 	}
 }
 
@@ -2046,18 +2099,17 @@ class MaxpTable : Table { 	
 	public void process () {
 		FontData fd = new FontData();
-		Font font = Supplement.get_current_font ();
 		uint16 max_points, max_contours;
 				
 		// Version 0.5 for fonts with cff data and 1.0 for ttf
 		fd.add_u16 (0);
 		fd.add_u16 (5);
 		
-		if (font.length () == 0) {
+		if (glyf_table.glyphs.length () == 0) {
 			warning ("Zero glyphs in maxp table.");
 		}
 		
-		fd.add_u16 ((uint16) font.length ()); // numGlyphs in the font
+		fd.add_u16 ((uint16) glyf_table.glyphs.length ()); // numGlyphs in the font
 
 		fd.pad ();
 		
@@ -2271,8 +2323,8 @@ class DirectoryTable : Table { 		glyf_table = new GlyfTable (loca_table);
 		cmap_table = new CmapTable (glyf_table);
 		head_table = new HeadTable (glyf_table);
-		hhea_table = new HheaTable (glyf_table, head_table);
-		hmtx_table = new HmtxTable (head_table);
+		hmtx_table = new HmtxTable (head_table, glyf_table);
+		hhea_table = new HheaTable (glyf_table, head_table, hmtx_table);
 		maxp_table = new MaxpTable (glyf_table);
 		name_table = new NameTable ();
 		os_2_table = new Os2Table (); 
@@ -2283,11 +2335,11 @@ class DirectoryTable : Table { 
 	public void process () {
 		// generate font data
-		head_table.process ();
 		glyf_table.process ();
+		head_table.process ();
 		cmap_table.process (glyf_table);
-		hhea_table.process ();
 		hmtx_table.process ();
+		hhea_table.process ();
 		maxp_table.process ();
 		name_table.process ();
 		os_2_table.process ();
@@ -2307,8 +2359,8 @@ class DirectoryTable : Table { 			tables.append (glyf_table);
 			tables.append (loca_table);
 			tables.append (cmap_table);  // The other required tables
-			tables.append (hhea_table);
 			tables.append (hmtx_table);
+			tables.append (hhea_table);
 			tables.append (maxp_table);
 			//tables.append (os_2_table);
 			//tables.append (name_table);
@@ -2486,18 +2538,21 @@ class DirectoryTable : Table { 		table_offset = 0;
 		
 		table_offset += offset_table.get_font_data ().length_with_padding ();
-		table_offset += this.get_font_data ().length_with_padding ();
+		
+		if (this.font_data != null) {
+			table_offset += this.get_font_data ().length_with_padding ();
+		}
 
 		head_table.set_check_sum_adjustment (0); // Set this to zero, calculate the sum and update the value
 
 		foreach (Table t in tables) {
-			
-			print (@"c $(t.id)  offset: $(table_offset)  len with pad  $( t.get_font_data ().length_with_padding ())\n");
-			
+						
 			if (t is DirectoryTable || t is OffsetTable) {
 				continue;
 			}
 			
+			print (@"c $(t.id)  offset: $(table_offset)  len with pad  $(t.get_font_data ().length_with_padding ())\n");
+
 			table_length = t.get_font_data ().length (); // without padding
 			
 			fd.add_tag (t.get_id ()); // name of table
diff --git a/src/OverView.vala b/src/OverView.valaindex 94b90ec..0657bae 100644--- a/src/OverView.vala+++ b/src/OverView.vala@@ -27,9 +27,9 @@ class OverView : FontDisplay { 	 	int rows = 0; 	int items_per_row = 0;-	unichar first_character = 1;-	unichar first_visible = 1;-	unichar selected = 1;+	unichar first_character = 0;+	unichar first_visible = 0;+	unichar selected = 0; 	 	double view_offset_y = 0; 	double view_offset_x = 0;@@ -226,10 +226,10 @@ class OverView : FontDisplay { 		return visible_characters; 	} 	-	public void draw_caption (int row, double width, Context cr, double y, unichar index_begin) {+	public void draw_caption (int row, double width, Context cr, double y, uint64 index_begin) { 		string character_string; 		double left_margin, x, caption_y; // for glyph caption-		unichar index = index_begin;+		uint64 index = index_begin; 		int i = row * items_per_row; 		cr.save (); 		cr.set_line_width (1);@@ -252,11 +252,16 @@ class OverView : FontDisplay { 			warning ("Max zoom level reached"); 					 		while (x < width) {-			if (index > glyph_range.get_length ()) {+			if (! (0 <= index < glyph_range.get_length ())) { 				break; 			} 			-			character_string = glyph_range.get_char (index);+			character_string = glyph_range.get_char ((uint32) index);+			+			if (character_string == "") {+				warning ("Got null character as name for glyph.");+				break;+			} 			 			cr.save (); 			draw_thumbnail (cr, character_string, x, y);@@ -353,7 +358,7 @@ class OverView : FontDisplay { 	public override void draw (Allocation allocation, Context cr) { 		double width; 		double y;-		unichar t;+		uint64 t; 		int i;  		while (visible_characters.length () > 9) {diff --git a/src/Supplement.vala b/src/Supplement.valaindex a7ae1a2..e717173 100644--- a/src/Supplement.vala+++ b/src/Supplement.vala@@ -23,7 +23,7 @@ class Supplement { 
 	static Font current_font;
 
-	static string[]? args = null;
+	public static Argument args;
 	
 	public static Font get_current_font () {
 		return current_font;
@@ -54,142 +54,30 @@ class Supplement { 			
 		return backup;
 	}
-	
+
 	public static bool has_argument (string param) {
-		return (get_argument (param) != null);
+		return args.has_argument (param);
 	}
 	
-	/** Get commandline argument. */
-	public static string? get_argument (string param) 
-		requires (args != null)
-	{
-		var a = (!) args;
-		int i = 0;
-		string? n;
-				
-		foreach (string s in a) {
-			string p;
-
-			if (s.substring (0, 1) != "-") continue;
-
-			if (s.substring (0, 2) != "--") {
-				p = expand_param (s);
-			} else {				
-				p = s;
-			}
-			
-			if (param == p) {
-				if (i + 2 >= a.length) {
-					return "";
-				}
-				
-				n = a[i + 2];
-				if (n == null || ((!)n).length == 0) {
-					return "";
-				}
-				
-				if (a[i + 2].substring (0, 1) == "-") {
-					return "";
-				}
-				
-				return a[i + 2];
-			}
-			
-			i++;
-		}
-		
-		return null;
-	}
-
-	private static void print_padded (string cmd, string desc) {
-		int l = 25 - cmd.char_count ();
-
-		stdout.printf (cmd);
-		
-		for (int i = 0; i < l; i++) {
-				stdout.printf (" ");
-		}
-		
-		stdout.printf (desc);
-		stdout.printf ("\n");
-	}
-
-	/** Return full command line parameter for an abbrevation.
-	 * -t becomes --test.
-	 */
-	private static string expand_param (string? param) {
-		if (param == null) return "";
-		var p = (!) param;
-		
-		if (p.length == 0) return "";
-		if (p.get_char (0) != '-') return "";
-		if (p.char_count () != 2) return "";
-		
-		switch (p.get_char (1)) {
-			case 'a': 
-				return "--autosave";
-			case 'e': 
-				return "--exit";
-			case 's': 
-				return "--slow";
-			case 'h': 
-				return "--help";
-			case 't': 
-				return "--test";
-		}
-		
-		return "";
+	public static string? get_argument (string param) {
+		return args.get_argument (param);
 	}
-
-	// FIXME: It seems broken:
-	public static string[] split_compound_parameters (string[] a) {
-		int ti = 0;
-		string[] na = new string [a.length];
-		
-		foreach (string s in a) {
-			if (s.substring (0, 2) != "--" && s.length > 2) {
-				unichar c;
-				int t = 1;
-				
-				while (s.get_next_char (ref t, out c)) {
-					if (c != ' ' && c != '-') {
-						StringBuilder b = new StringBuilder ();
-						b.append_unichar (c);
-						na += @"-$(b.str)";
-					}
-				}
-			}
 			
-			na[ti] = a[ti];
-			ti++;
-		}
+	public static void main(string[] arg) {
+		int err_arg;
 		
-		return na;
-	}
-
-	public static void print_help (string[] args) 
-		requires (args.length > 0)
-	{
-		
-		stdout.printf ("Usage: ");
-		stdout.printf (args[0]);
-		stdout.printf (" [OPTION ...]\n");
-
-		print_padded ("-e, --exit", "exit if a testcase failes");
-		print_padded ("-h, --help", "show this message");
-		print_padded ("-s, --slow", "sleep between each command in test suite");
-		print_padded ("-t, --test[=TEST]", "run test case");
+		args = new Argument.command_line (arg);
 		
-		stdout.printf ("\n");
-	}
+		if (args.has_argument ("--help")) {
+			args.print_help ();
+			Process.exit (0);
+		}
 
-	public static void main(string[] args) {		
-		Supplement.args = split_compound_parameters (args);
-		Supplement.args = args;
-		
-		if (has_argument ("--help")) {
-			print_help (args);
-			Process.exit(0);
+		err_arg = args.validate ();
+		if (err_arg != 0) {
+			stdout.printf (@"Unknown parameter $(arg [err_arg])\n\n");
+			args.print_help ();
+			Process.exit (0);
 		}
 
 		Preferences preferences = new Preferences ();
@@ -197,7 +85,7 @@ class Supplement {        
 		current_font = new Font ();
 		
-		Gtk.init (ref args);
+		Gtk.init (ref arg);
 		var window = new MainWindow ("Supplement");
 		window.show_all ();
 
@@ -205,7 +93,7 @@ class Supplement { 		idle.set_callback(() => {
 			preferences.load ();
 			return false;
-    });
+		});
 		
 		idle.attach (null);
 		
diff --git a/src/TestCases.vala b/src/TestCases.valanew file mode 100644index 0000000..b498e46--- /dev/null+++ b/src/TestCases.vala@@ -0,0 +1,224 @@+/*+    Copyright (C) 2012 Johan Mattsson++    This program is free software: you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation, either version 3 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License+    along with this program.  If not, see <http://www.gnu.org/licenses/>.+*/++namespace Supplement {++/** All the things we want to test listed is here. */+class TestCases {+	+	public List<Test> test_cases;++	public TestCases () {+		add (test_argument, "Argument list");+		add (test_glyph_ranges, "Glyph ranges");+		add (test_glyph_table, "Glyph table");+		add (test_active_edit_point, "Active edit point");+		add (test_hex, "Unicode hex values");+		add (test_reverse_path, "Reverse path");+		add (test_reverse_random_paths, "Reverse random paths");+		add (test_coordinates, "Coordinates");+		add (test_drawing, "Pen tool");+		add (test_delete_points, "Delete edit points");+		add (test_view_result, "View result in web browser");+		add (test_save_backup, "Save backup");+	}++	public static void test_argument () {+		Argument arg = new Argument ("supplement -t \"Argument list\" --unknown -unknown --help -s");+		+		return_if_fail (arg.has_argument ("--test"));+		return_if_fail ((!) arg.get_argument ("--test") == "\"Argument list\"" );+		return_if_fail (arg.has_argument ("--unknown"));+		return_if_fail (arg.has_argument ("--help"));+		return_if_fail (arg.has_argument ("--slow"));+		return_if_fail (arg.validate () != 0);++		arg = new Argument ("supplement --test \"Argument list\"");+		return_if_fail ((!) arg.get_argument ("--test") == "\"Argument list\"" );+		return_if_fail (!arg.has_argument ("--help"));+		return_if_fail (!arg.has_argument ("--slow"));+		return_if_fail (arg.validate () == 0);+		+	}++	public static void test_glyph_ranges () {+		GlyphRange gr = new GlyphRange ();+		+		gr.add_range ('b', 'c');+		gr.add_single ('d');+		gr.add_range ('e', 'h');+		gr.add_range ('k', 'm');+		gr.add_range ('o', 'u');+		gr.add_range ('a', 'd');+		gr.add_range ('f', 'z');+		gr.add_range ('b', 'd');+			+		return_if_fail (gr.length () == 'z' - 'a' + 1);+		return_if_fail (gr.get_ranges ().length () == 1);+		return_if_fail (gr.get_ranges ().first ().data.length () == 'z' - 'a' + 1);+		+		for (unichar i = 'a'; i <= 'z'; i++) {+			uint index = i - 'a';+			string c = gr.get_char (index);+			StringBuilder s = new StringBuilder ();+			s.append_unichar (i);+			+			if (c != s.str) {+				warning (@"wrong glyph in glyph range got \"$c\" expected \"$(s.str)\" for index $(index).");+			}+		}+		+		gr = new GlyphRange ();+		gr.add_single ('a');+		gr.add_range ('c', 'e');+		gr.add_single ('◊');+		return_if_fail (gr.get_char (0) == "a");+		return_if_fail (gr.get_char (1) == "c");+		return_if_fail (gr.get_char (2) == "d");+		return_if_fail (gr.get_char (3) == "e");+		return_if_fail (gr.get_char (4) == "◊");+	}++	public static void test_glyph_table () {+		GlyphTable table = new GlyphTable ();+		List<GlyphCollection> gc = new List<GlyphCollection> ();+		List<unowned GlyphCollection> gc_copy;+		GlyphCollection g;+		+		return_if_fail (table.length () == 0);+		return_if_fail (table.get ("Some glyph") == null);+		+		// generate test data+		for (uint i = 0; i < 1000; i++) {+			gc.append (new GlyphCollection (new Glyph (@"TEST $i", i + 'a')));+		}++		// insert in random order+		gc_copy = gc.copy ();+		for (uint i = 0; gc_copy.length () > 0; i++) {+			int t = (int) ((gc_copy.length () - 1) * Random.next_double ());+			g = gc_copy.nth (t).data;+			+			if (!table.insert (g)) {+				warning (@"Failed to insert $(g.get_name ())");+				return;+			}+			+			gc_copy.remove_all (g);+			+			if (!table.validate_index ()) {+				table.print_all ();+				warning ("index is invalid");+				return;+			}+		}+		+		return_if_fail (table.length () == gc.length ());+		+		// validate table+		for (uint i = 0; i > 1000; i++) {+			g = (!) table.get (gc.nth (i).data.get_name ());+			return_if_fail (gc.nth (i).data == g);+		}+		+		// search +		for (int i = 0; i < 2000; i++) {+			int t = (int) (999 * Random.next_double ());+			if (table.get (@"TEST $t") == null) {+				table.print_all ();+				warning (@"Did't find TEST $t in glyph table.");+				return;+			}+		}++		// remove+		table.remove ("TEST 0");+		table.remove ("TEST 53");+		return_if_fail (table.get ("TEST 0") == null);+		return_if_fail (table.get ("TEST 53") == null);+		+		// search +		return_if_fail (table.get ("TEST 52") != null);+		return_if_fail (table.get ("TEST 54") != null);+	}++	public static void test_delete_points () {+		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");+		tool.test_delete_points ();+	}++	public static void test_active_edit_point () {+		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");+		tool.test_active_edit_point ();+	}+	+	public static void test_save_backup () {+		// TODO draw various things and assert that they are restored correctly+		Supplement.get_current_font ().save_backup ();+		Supplement.get_current_font ().restore_backup ();+	}++	public static void test_hex () {+		test_hex_conv ('H', "U+48", 72);+		test_hex_conv ('1', "U+31", 49);+		test_hex_conv ('å', "U+e5", 229);+		test_hex_conv ('◊', "U+25ca", 9674);+	}++	private static void test_hex_conv (unichar h, string sr, int r) {+		string s = Font.to_hex (h);+		unichar t = Font.to_unichar (sr);+		+		if (s != sr) warning (@"($s != \"$sr\")");+		if ((int)t != r || t != h) warning (@"$((int)t) != $r || $t != '$h'");+	}++	public static void test_coordinates () {+		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");+		tool.test_coordinates ();		+	}++	public static void test_view_result () {+		ExportTool tool = (ExportTool) MainWindow.get_toolbox ().get_tool ("export");+		tool.test_view_result ();+	}++	public static void test_reverse_random_paths () {+		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");+		tool.test_reverse_random_triangles ();		+	}++	public static void test_reverse_path () {+		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");+		tool.test_reverse_path ();+	}++	public static void test_drawing () {+		Tool tool = MainWindow.get_toolbox ().get_tool ("pen_tool");+		tool.test ();+	}+		+	private void add (Callback callback, string name) {+		test_cases.append (new Test (callback, name));+	}+	+	public unowned List<Test> get_test_functions () {+		return test_cases;+	}+}	+	+}diff --git a/src/TestSupplement.vala b/src/TestSupplement.valaindex 1518e29..d31ff7d 100644--- a/src/TestSupplement.vala+++ b/src/TestSupplement.vala@@ -27,170 +27,6 @@ class Test : Object { 	}
 }
 
-/** All the things we might want to test is here. */
-class TestCases {
-	
-	public List<Test> test_cases;
-
-	public TestCases () {
-		add (test_glyph_ranges, "Glyph ranges");
-		add (test_glyph_table, "Glyph table");
-		add (test_active_edit_point, "Active edit point");
-		add (test_hex, "Unicode hex values");
-		add (test_reverse_path, "Reverse path");
-		add (test_reverse_random_paths, "Reverse random paths");
-		add (test_coordinates, "Coordinates");
-		add (test_drawing, "Pen tool");
-		add (test_delete_points, "Delete edit points");
-		add (test_view_result, "View result in web browser");
-		add (test_save_backup, "Save backup");
-	}
-
-	public static void test_glyph_ranges () {
-		GlyphRange gr = new GlyphRange ();
-		
-		gr.add_range ('b', 'c');
-		gr.add_single ('d');
-		gr.add_range ('e', 'h');
-		gr.add_range ('k', 'm');
-		gr.add_range ('o', 'u');
-		gr.add_range ('a', 'd');
-		gr.add_range ('f', 'z');
-		gr.add_range ('b', 'd');
-			
-		return_if_fail (gr.length () == 'z' - 'a' + 1);
-		return_if_fail (gr.get_ranges ().length () == 1);
-		return_if_fail (gr.get_ranges ().first ().data.length () == 'z' - 'a' + 1);
-	}
-
-	public static void test_glyph_table () {
-		GlyphTable table = new GlyphTable ();
-		List<GlyphCollection> gc = new List<GlyphCollection> ();
-		List<unowned GlyphCollection> gc_copy;
-		GlyphCollection g;
-		
-		return_if_fail (table.length () == 0);
-		return_if_fail (table.get ("Some glyph") == null);
-		
-		// generate test data
-		for (uint i = 0; i < 1000; i++) {
-			gc.append (new GlyphCollection (new Glyph (@"TEST $i", i + 'a')));
-		}
-
-		// insert in random order
-		gc_copy = gc.copy ();
-		for (uint i = 0; gc_copy.length () > 0; i++) {
-			int t = (int) ((gc_copy.length () - 1) * Random.next_double ());
-			g = gc_copy.nth (t).data;
-			
-			if (!table.insert (g)) {
-				warning (@"Failed to insert $(g.get_name ())");
-				return;
-			}
-			
-			gc_copy.remove_all (g);
-			
-			if (!table.validate_index ()) {
-				table.print_all ();
-				warning ("index is invalid");
-				return;
-			}
-		}
-		
-		return_if_fail (table.length () == gc.length ());
-		
-		// validate table
-		for (uint i = 0; i > 1000; i++) {
-			g = (!) table.get (gc.nth (i).data.get_name ());
-			return_if_fail (gc.nth (i).data == g);
-		}
-		
-		// search 
-		for (int i = 0; i < 2000; i++) {
-			int t = (int) (999 * Random.next_double ());
-			if (table.get (@"TEST $t") == null) {
-				table.print_all ();
-				warning (@"Did't find TEST $t in glyph table.");
-				return;
-			}
-		}
-
-		// remove
-		table.remove ("TEST 0");
-		table.remove ("TEST 53");
-		return_if_fail (table.get ("TEST 0") == null);
-		return_if_fail (table.get ("TEST 53") == null);
-		
-		// search 
-		return_if_fail (table.get ("TEST 52") != null);
-		return_if_fail (table.get ("TEST 54") != null);
-	}
-
-	public static void test_delete_points () {
-		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");
-		tool.test_delete_points ();
-	}
-
-	public static void test_active_edit_point () {
-		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");
-		tool.test_active_edit_point ();
-	}
-	
-	public static void test_save_backup () {
-		// TODO draw various things and assert that they are restored correctly
-		Supplement.get_current_font ().save_backup ();
-		Supplement.get_current_font ().restore_backup ();
-	}
-
-	public static void test_hex () {
-		test_hex_conv ('H', "U+48", 72);
-		test_hex_conv ('1', "U+31", 49);
-		test_hex_conv ('å', "U+e5", 229);
-		test_hex_conv ('◊', "U+25ca", 9674);
-	}
-
-	private static void test_hex_conv (unichar h, string sr, int r) {
-		string s = Font.to_hex (h);
-		unichar t = Font.to_unichar (sr);
-		
-		if (s != sr) warning (@"($s != \"$sr\")");
-		if ((int)t != r || t != h) warning (@"$((int)t) != $r || $t != '$h'");
-	}
-
-	public static void test_coordinates () {
-		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");
-		tool.test_coordinates ();		
-	}
-
-	public static void test_view_result () {
-		ExportTool tool = (ExportTool) MainWindow.get_toolbox ().get_tool ("export");
-		tool.test_view_result ();
-	}
-
-	public static void test_reverse_random_paths () {
-		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");
-		tool.test_reverse_random_triangles ();		
-	}
-
-	public static void test_reverse_path () {
-		PenTool tool = (PenTool) MainWindow.get_toolbox ().get_tool ("pen_tool");
-		tool.test_reverse_path ();
-	}
-
-	public static void test_drawing () {
-		Tool tool = MainWindow.get_toolbox ().get_tool ("pen_tool");
-		tool.test ();
-	}
-		
-	private void add (Callback callback, string name) {
-		test_cases.append (new Test (callback, name));
-	}
-	
-	public unowned List<Test> get_test_functions () {
-		return test_cases;
-	}
-}
-
 /** Class for executing tests cases. */
 class TestSupplement : GLib.Object {
 
@@ -208,18 +44,23 @@ class TestSupplement : GLib.Object { 
 	unowned List<Test> passed;
 	unowned List<Test> failed;
+	unowned List<Test> skipped;
 
 	static TestSupplement? singleton = null;
 
 	bool has_failed = false;
-	
+	bool has_skipped = false;
+		
 	static bool slow_test = false;
 	
+	string test_cases_to_run; // name of specific test case or all to run all test cases
+	
 	public TestSupplement () {
 		assert (singleton == null);
 		tests = new TestCases ();
 		test_cases = tests.get_test_functions ();
 		current_case = test_cases.first ();
+		test_cases_to_run = "All";
 		
 		from_command_line ();
 	}
@@ -245,7 +86,7 @@ class TestSupplement : GLib.Object { 			if (t.name == s) return true;
 		}	
 		
-		if (s == "") {
+		if (s == "" || s == "All") {
 			print ("No speceific tescase given run all test cases.\n");
 			return true;
 		}
@@ -258,17 +99,18 @@ class TestSupplement : GLib.Object { 		string? stn = Supplement.get_argument ("--test");
 	
 		if (stn != null) {
-			string st = (!)stn;
+			string st = (!) stn;
 			
 			if (!has_test_case (st)) {
-				stderr.printf (@"Test case $st does not exist.\n");
-				stderr.printf ("\nAvaliable cases:\n");
+				stderr.printf (@"Test case \"$st\" does not exist.\n");
+				stderr.printf ("\nAvaliable test cases:\n");
+				
 				foreach (var t in test_cases) {
 					stderr.printf (t.name);
 					stderr.printf ("\n");
 				}
 				
-				assert (false);
+				Process.exit(1);
 			}
 
 			if (st == "All" || st == "") {
@@ -277,6 +119,7 @@ class TestSupplement : GLib.Object { 				stderr.printf  (@"Run only test case \"$st\" \n");
 			}
 			
+			test_cases_to_run = st;
 		}
 	}
 
@@ -326,6 +169,16 @@ class TestSupplement : GLib.Object { 		stdout.printf ("\n");
 		stdout.printf ("Testcase results:\n");
 
+		foreach (var t in skipped) {
+			stdout.printf ("%s", t.name);
+			pad (40 - t.name.char_count());
+			stdout.printf ("Skipped\n");
+		}
+		
+		if (skipped.length () > 0) {
+			stdout.printf ("\n");
+		}
+		
 		foreach (var t in passed) {
 			stdout.printf ("%s", t.name);
 			pad (40 - t.name.char_count());
@@ -355,31 +208,42 @@ class TestSupplement : GLib.Object { 			}
 
 			Test test = (!)((!) current_case).data;
-
+					
 			has_failed = false;
-			
-			test.callback ();
+			has_skipped = false;
 
+			if (test_cases_to_run != "All" && test_cases_to_run != test.name) {
+				has_skipped = true;
+			} else {
+				test.callback ();
+			}
+			
 			if (has_failed) {
-				failed.append ((!)test);
+				failed.append ((!) test);
 				
 				if (Supplement.has_argument ("--exit")) {
 					print_result ();
-					
-					bool test_case_will_not_fail = false;
-					assert (test_case_will_not_fail);
+					Process.exit (1);
 				}
 	
+			} else if (has_skipped) {
+				skipped.append ((!) test);
 			} else {
-				passed.append ((!)test);
+				passed.append ((!) test);
 			}
 
 			if (unlikely (current_case == test_cases.last ())) {
-				stderr.printf ("Finished running test suite.\n");			
+				stdout.printf ("Finished running test suite.\n");			
+				
 				AtomicInt.set (ref state, DONE);
 				Log.set_handler (null, LogLevelFlags.LEVEL_MASK, Log.default_handler);
 
 				print_result ();
+				
+				if (Supplement.has_argument ("--exit")) {
+					print_result ();
+					Process.exit ((failed.length () == 0) ? 0 : 1);
+				}
 				return false;
 			}
 			
diff --git a/src/wscript b/src/wscriptindex 65bb8ba..9b127b2 100644--- a/src/wscript+++ b/src/wscript@@ -1,4 +1,5 @@ SUPPLEMENT_MAIN = [
+	'Argument.vala',
 	'Font.vala',
 	'BackgroundTool.vala',
 	'BackgroundSelection.vala',
@@ -43,6 +44,7 @@ SUPPLEMENT_MAIN = [ 	'SvgFontFormatWriter.vala',
 	'Preferences.vala',
 	'TabBar.vala',
+	'TestCases.vala', 
 	'TestSupplement.vala', 
 	'Tool.vala',
 	'Toolbox.vala',

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112