Clone in a terminal:
Commit 53e0e06
Johan Mattsson - 2013-09-10T05:57:35+00:00
53e0e06b4bda5dff325439466ad5442539de94acjohan.mattsson.m@gmail.com

replace glyph table with tree map from gee

Changed files (5)

Diff

diff --git a/dodo.py b/dodo.pyindex d20e4ed..c48c4c2 100644--- a/dodo.py+++ b/dodo.py@@ -45,7 +45,7 @@ LIBS = [     'cairo',     'gdk-pixbuf-2.0',     'webkit-1.0',-    'gee-1.0'+    'gee-0.8'     ]  def task_build ():diff --git a/libbirdfont/CharDatabase.vala b/libbirdfont/CharDatabase.valaindex d945d51..509df7e 100644--- a/libbirdfont/CharDatabase.vala+++ b/libbirdfont/CharDatabase.vala@@ -56,8 +56,7 @@ public class CharDatabase { 			result.add_single (s.get_char ());  		} 		-		var it = index.get (s).iterator ();-		for (var has_next = it.first (); has_next; has_next = it.next ()) {+		for (var it = index.get (s).iterator (); it.has_next (); it.next ()) { 			iv = it.get (); 			if (iv != null) { 				i = (string) iv;diff --git a/libbirdfont/GlyphTable.vala b/libbirdfont/GlyphTable.valaindex 0f4ec1a..8002549 100644--- a/libbirdfont/GlyphTable.vala+++ b/libbirdfont/GlyphTable.vala@@ -12,413 +12,70 @@     Lesser General Public License for more details. */ +using Gee;+ namespace BirdFont {  /** A sorted table of glyphs with search index. */ public class GlyphTable : GLib.Object {-	List<Item> data = new List<Item> (); 	-	List<RowItem> row1 = new List<RowItem> ();-	List<RowItem> row2 = new List<RowItem> ();-	List<RowItem> row3 = new List<RowItem> ();+	TreeMap<string, GlyphCollection> map; 	 	public GlyphTable () {+		map = new TreeMap<string, GlyphCollection> (); 	}  	public void remove_all () {-		while (data.length () > 0) {-			data.remove_link (data.first ());-		}-		build_index ();+		map.clear (); 	}  	public void @for_each (Func<GlyphCollection> func) {-		if (unlikely (is_null (data))) {+		if (unlikely (is_null (map))) { 			warning ("No data in table"); 			return; 		} 		-		data.foreach ((v) => {-			if (unlikely (is_null (v))) {-				warning ("No value found in GlyphTable.");-				return;-			}-						-			func (v.glyph_collection);-		});+		foreach (var entry in map.entries) {+			func (entry.value);+		} 	}  	public bool has_key (string n) {-		return find (n) != null;-	}--	unowned List<Item>? find (string n) {-		return find_index (n);-	}--	unowned List<Item>? find_next (string n) {-		return find_next_index (n);+		return map.has_key (n); 	} 		 	public void remove (string name) {-		unowned List<Item>? d = find (name);-		-		if (d == null) {-			warning (@"did not find $name");-			return;-		}-		-		data.remove_link ((!) d);-		build_index ();+		map.unset (name); 	}  	public uint length () {-		return data.length ();+		return map.size; 	}  	public new GlyphCollection? @get (string name) {-		unowned List<Item>? d = find_index (name);-		-		if (d == null) {-			return null;-		}-		-		return ((!) d).data.glyph_collection;+		return map.get (name); 	}  	public new GlyphCollection? nth (uint index) {-		unowned List<Item>? d = data.nth (index);+		Iterator<string>? iterator = map.ascending_keys.iterator_at (map.ascending_keys.first ());+		Iterator<string> iter; 		-		if (d == null) {+		if (iterator == null) { 			return null; 		} 		-		return ((!) d).data.glyph_collection;-	}--	public bool insert (string key, GlyphCollection g) {-		Item item;-		unowned List<Item>? next;--		if (find (key) != null) {-			warning (@"Table does already contains a glyph for key \"$key\".");-			stderr.printf ("char: %u\n", (uint) key.get_char (0));-			return false;+		iter = (!) iterator;+		for (uint i = 0; i != index; i++) {+			iter.next (); 		}-				-		next = find_next (key);-		-		item = new Item (key, g);-		-		if (next == null) {-			data.append (item);-		} else {-			data.insert_before ((!) next, item); // _sorted-		}-		-		build_index ();-		-		if (find (key) == null) {-			warning (@"Can not find glyph \"$(key)\".");-			validate_index ();-			print_all ();-			return false;-		}-		-		return true;-	} -	public void print_all () {-		int indice = 0;-		-		print ("Data:\n");-		foreach (Item i in data) {-			print (@"key: $(i.name) indice: $(indice)\n");-			indice++;-		}-		-		print ("Index:\n");-		print ("\n");-		print ("row3\n");-		foreach (RowItem i in row3) {-			print (@"$(i.item.data.name)\n");-		}-		-		print ("\n");-		print ("row2\n");-		foreach (RowItem i in row2) {-			print (@"$(i.item.data.name)\n");-		}-		-		print ("\n");-		print ("row1\n");-		foreach (RowItem i in row1) {-			print (@"$(i.item.data.name)\n");-		}		+		return map.get (iter.get ()); 	} -	static int compare (string an, Item b) {-		string? bt = b.name;-		string bn = (!) bt;-		-		uint32 ac = 0;-		uint32 bc = 0;-				-		int i1 = 0;-		int i2 = 0;-		-		return_val_if_fail (bt != null, 0);-		-		int ca = an.char_count ();-		int cb = bn.char_count ();-		-		if (ca != cb) {-			return ca < cb ? 1 : -1;-		}-		-		while (true) {-			an.get_next_char (ref i1, out ac);-			bn.get_next_char (ref i2, out bc);-			-			if (ac == bc && ac != 0) {-				continue;-			}-			-			if (ac == bc) return 0;-			-			return (ac < bc) ? 1 : -1;-		}-	}-	-	public void build_index () {-		uint len;-		RowItem r;-		-		while (row1.length () > 0) {-			row1.remove_link (row1.first ());-		}--		while (row2.length () > 0) {-			row2.remove_link (row2.first ());-		}--		while (row3.length () > 0) {-			row3.remove_link (row3.first ());-		}--		if (data.length () == 0) {-			return;-		}-				-		// row 1-		len = data.length () / 5;-		if (len == 0) len++;-		for (int i = 0; i < len; i++) {-			r = new RowItem ();-			r.item = data.nth (i * 5);-			r.level = 1;-			row1.append (r);-		}-		r = new RowItem ();-		r.item = data.last ();-		r.level = 1;-		r.last = true;-		row1.append (r);	-		-		// row 2-		len = row1.length () / 5;-		if (len == 0) len++;-		for (int i = 0; i < len; i++) {-			r = new RowItem ();-			r.next_row = row1.nth (i * 5);-			r.item = r.next_row.data.item; -			r.level = 2;-			row2.append (r);-		}-		r = new RowItem ();-		r.item = data.last ();-		r.level = 2;-		r.next_row = row1.last ();		-		r.last = true;-		row2.append (r);-		-		// row 3-		len = row2.length () / 5;-		if (len == 0) len++;-		for (int i = 0; i < len; i++) {-			r = new RowItem ();-			r.next_row = row2.nth (i * 5);-			r.item = r.next_row.data.item; -			r.level = 3;-			row3.append (r);-		}-		r = new RowItem ();-		r.item = data.last ();-		r.level = 3;-		r.next_row = row2.last ();-		r.last = true;	-		row3.append (r);-	}--	unowned List<Item>? find_next_index (string n) {-		unowned List<Item>? next = find_next_via_index (n);-		return next;-	}--	unowned List<Item>? find_index (string n) {-		unowned List<Item>? next = find_next_via_index (n);-		-		if (next == null) {-			return null;-		}-		-		if (compare (n, ((!)next).data) == 0) {-			return next;-		}-	-		if (((!)next) != data.first () && compare (n, ((!)next).prev.data) == 0) {-			return ((!)next).prev; // fetch previous since we are searching for the next one-		}-		-		return null; -	}-	-	unowned List<Item>? find_next_via_index (string n) {-		unowned List<Item> i = data.first ();-		unowned List<RowItem> r;-		int cmp;-		-		if (data.length () == 0) {-			return null;-		}--		r = row3.first ();-		int ti = 0;-		while (true) {-			cmp = compare (n, r.data.item.data);-			-			ti++;-			-			if (cmp == 1) {-				break;-			}-			-			if (cmp == 0) {-				return r.data.item;-			}-			-			if (r != row3.last ()) {-				r = r.next;-			} else {-				return null;-			}-		} -		r = r.data.next_row;--		while (true) {-			cmp = compare (n, r.data.item.data);-			-			if (cmp == -1) {-				break;-			}--			if (cmp == 0) {-				return r.data.item;-			}-						-			if (r == row2.first ()) {;-				return r.data.item;-			} else r = r.prev;-		}-		r = r.data.next_row;-		-		while (true) {-			cmp = compare (n, r.data.item.data);-			-			if (cmp == 1) {-				break;-			}-			-			if (cmp == 0) {-				return r.data.item;-			}-								-			if (r == row1.last ()) return null;-			else r = r.next;-		}-		i = r.data.item;-		-		-		while (true) {-			cmp = compare (n, i.data);--			if (cmp == -1) {-				// null?-				return i.next;-			}--			if (cmp == 0) {-				return i;-			}-						-			if (i == data.first ()) {-				return i;-			} else { -				i = i.prev;-			}-		}			-	}--	public bool validate_index () {-		int cmp;-		Item prev;-		int index;-		-		if (data.length () == 0) {-			return true;-		}-		-		prev = data.first ().data;-		index = 0;-		foreach (Item i in data) {-			cmp = compare (prev.name, i);-		-			if (cmp == 1) {-				continue;-			}-						-			if (cmp == 0 && index != 0) {-				warning (@"Value is not unique: $(i.name).");-				return false;-			}--			if (cmp == -1) {-				warning (@"Value is not sorted: $cmp == cmp $(prev.name) $(i.name).");-				return false;-			}-			-			index++;-		}-	+	public bool insert (string key, GlyphCollection g) {+		map.set (key, g); 		return true; 	}--	class Item : GLib.Object {-		public string name;-		public GlyphCollection glyph_collection;-		-		public Item (string n, GlyphCollection gc) {-			glyph_collection = gc;-			name = n;-		}-	}--	class RowItem : GLib.Object {-		public unowned List<RowItem> next_row;-		public unowned List<Item> item;-		public int level = 0;-		public bool last = false;-	} }  }diff --git a/libbirdfont/OpenFontFormat/GlyfTable.vala b/libbirdfont/OpenFontFormat/GlyfTable.valaindex a7e72c9..50f0bef 100644--- a/libbirdfont/OpenFontFormat/GlyfTable.vala+++ b/libbirdfont/OpenFontFormat/GlyfTable.vala@@ -116,6 +116,10 @@ class GlyfTable : Table { 		 		num_glyphs = glyphs.length (); 		+		if (glyphs.length () == 0) {+			warning ("No glyphs in glyf table.");+		}+		 		foreach (Glyph g in glyphs) { 			// set values for loca table 			assert (fd.length () % 4 == 0);@@ -155,6 +159,10 @@ class GlyfTable : Table { 		 		unassigned_glyphs = new List<Glyph> (); 		+		if (font.get_glyph_indice (0) == null) {+			warning ("No glyphs in font.");+		}+				 		// add glyphs, first all assigned then the unassigned ones 		for (indice = 0; (gl = font.get_glyph_indice (indice)) != null; indice++) {		 			g = (!) gl;@@ -176,6 +184,7 @@ class GlyfTable : Table { 			if (!g.is_unassigned ()) { 				glyphs.append (g); 			} else {+				printd ("Adding unassigned glyph."); 				unassigned_glyphs.append (g); 			} 		}diff --git a/libbirdfont/TestCases.vala b/libbirdfont/TestCases.valaindex b30726b..4201942 100644--- a/libbirdfont/TestCases.vala+++ b/libbirdfont/TestCases.vala@@ -24,7 +24,6 @@ class TestCases { 		add (test_data_reader, "Font data reader"); 		add (test_argument, "Argument list"); 		add (test_glyph_ranges, "Glyph ranges");-		add (test_glyph_table, "Glyph table"); 		add (test_hex, "Unicode hex values"); 		add (test_reverse_path, "Reverse path"); 		add (test_reverse_random_triangles, "Reverse random paths");@@ -742,79 +741,6 @@ class TestCases { 		} 	} -	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')));-		}--		g = gc.first ().data;-		if (!table.insert (g.get_unicode (), g)) {-			warning (@"Failed to insert $(g.get_name ())");-			return;-		}-		gc.append (g);-		-		// 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.get_name (), 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;-			}-		}-		-		if (table.length () != gc.length ()) {-			warning ("Table length does not match number of glyphs, $(table.length ()) != $(gc.length ())");-			return;-		}-		-		// 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_hex () { 		test_hex_conv ('H', "U+48", 72); 		test_hex_conv ('1', "U+31", 49);

Contact

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