Commit 53e0e06
replace glyph table with tree map from gee
Changed files (5)
modifieddodo.pymodifiedlibbirdfont/CharDatabase.valamodifiedlibbirdfont/GlyphTable.valamodifiedlibbirdfont/OpenFontFormat/GlyfTable.valamodifiedlibbirdfont/TestCases.vala
Diff
@@ -45,7 +45,7 @@ LIBS = [ 'cairo', 'gdk-pixbuf-2.0', 'webkit-1.0',- 'gee-1.0'+ 'gee-0.8' ] def task_build ():@@ -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;@@ -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;- } } }@@ -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); } }@@ -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);