Clone in a terminal:
Commit 32cdb16
Johan Mattsson - 2013-08-27T18:14:16+00:00
32cdb167b4098bb2f12ad8283acddf727e928a45johan.mattsson.m@gmail.com

search for characters in unicode character database

Changed files (7)

Diff

diff --git a/birdfont/GtkWindow.vala b/birdfont/GtkWindow.valaindex ef63fe2..1683506 100644--- a/birdfont/GtkWindow.vala+++ b/birdfont/GtkWindow.vala@@ -538,6 +538,11 @@ public class GtkWindow : Gtk.Window, NativeWindow { 		}); 		select_all_item.add_accelerator ("activate", accel_group, 'A', Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE); +		Gtk.MenuItem search_item = new Gtk.MenuItem.with_mnemonic (_("Search"));+		edit_menu.append (search_item);+		search_item.activate.connect (() => { OverView.search (); });	+		search_item.add_accelerator ("activate", accel_group, 'F', Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE);+	 		Gtk.MenuItem export_svg_item = new Gtk.MenuItem.with_mnemonic (_("_Export Glyph as SVG")); 		edit_menu.append (export_svg_item); 		export_svg_item.activate.connect (() => { ExportTool.export_current_glyph (); });	diff --git a/libbirdfont/CharDatabase.vala b/libbirdfont/CharDatabase.valaindex fd0a216..79d93b2 100644--- a/libbirdfont/CharDatabase.vala+++ b/libbirdfont/CharDatabase.vala@@ -12,89 +12,166 @@     Lesser General Public License for more details. */ +using Gee;+ namespace BirdFont { -class CharDatabase {+public class CharDatabase {+	+	static HashMap<string, string> entries;+	static HashMultiMap<string, string> index; +	static GlyphRange full_unicode_range;+	static bool database_is_loaded = false;+	 	public CharDatabase () {+		entries = new HashMap<string, string> ();+		index = new HashMultiMap<string, string> ();+	+		full_unicode_range = new GlyphRange ();++		IdleSource idle = new IdleSource ();+		idle.set_callback (() => {+			show_loading_message ();+			parse_all_entries ();+			database_is_loaded = true;+			return false;+		});+		idle.attach (null); 	} -	public static bool has_ascender (unichar c) {-		if (!c.islower()) return true;+	public static GlyphRange search (string s) {+		GlyphRange result = new GlyphRange ();+		GlyphRange ucd_result = new GlyphRange ();+		unichar c;+		string i;+		string? iv; 		-		switch (c) {-			case 'b': return true;-			case 'd': return true;-			case 'f': return true;-			case 'h': return true;-			case 'i': return true;-			case 'j': return true;-			case 'k': return true;-			case 'l': return true;	+		if (!database_is_loaded) {+			show_loading_message (); 		} 		-		if ('à' <= c <= 'å') return true;-		if ('è' <= c <= 'ö') return true;-		if ('ù' <= c <= 'ă') return true;-		if ('ć' <= c <= 'ė') return true;--		return false;+		return_if_fail (result.get_length () == 0);+		+		if (s.has_prefix ("U+") || s.has_prefix ("u+")) {+			c = Font.to_unichar (s.down ());+			+			if (c != '\0') {+				result.add_single (c);+			}+		}+		+		if (s.char_count () == 1) {+			result.add_single (s.get_char ()); +		}+		+		var it = index.get (s).iterator ();+		for (var has_next = it.first (); has_next; has_next = it.next ()) {+			iv = it.get ();+			if (iv != null) {+				i = (string) iv;+				c = Font.to_unichar ("U+" + i.down ());+				ucd_result.add_single (c);+			}+		}+    +		if (ucd_result.get_length () > 0) {+			ucd_result.sort ();+			result.parse_ranges (ucd_result.get_all_ranges ());+		}+		+		return result; 	} -	public static bool has_descender (unichar c) {-		switch (c) {-			case 'g': return true;-			case 'j': return true;-			case 'p': return true;-			case 'q': return true;-			case 'y': return true;+	private void add_entry (string data) {+		string[] e;+		string[] r;+		string[] d;+		string index_values;+		unichar ch;+		+		string unicode_hex;+		+		if (data.has_prefix ("@")) { // ignore comments+			return; 		} 		-		return false;		+		index_values = data.down ();+		index_values = index_values.replace ("\tx", "");+		index_values = index_values.replace ("\t*", "");+		index_values = index_values.replace ("\t=", "");+		index_values = index_values.replace ("\t#", "");+		index_values = index_values.replace (" - ", " ");+		index_values = index_values.replace ("(", "");+		index_values = index_values.replace (")", "");+		index_values = index_values.replace ("<font>", "");+		index_values = index_values.replace (" a ", " ");+		index_values = index_values.replace (" is ", " ");+		index_values = index_values.replace (" the ", " ");+		+		e = index_values.split ("\t");++		return_if_fail (e.length > 0);+		+		unicode_hex = e[0].up ();+		+		ch = Font.to_unichar ("U+" + unicode_hex.down ());+		full_unicode_range.add_single (ch);+		Tool.yield ();++		entries.set (unicode_hex, data);+				+		foreach (string s in e) {+			r = s.split ("\n");+			foreach (string t in r) {  +				d = t.split (" ");+				foreach (string token in d) {+					if (token != "") {+						index.set (token, unicode_hex);+						Tool.yield ();+					}+				}+			}+		}+		+		Tool.yield (); 	}-	-	public static string get_unicode_database_entry (unichar c) {++	private void parse_all_entries () { 		FileInputStream fin; 		DataInputStream din; 		string? line; 		string data;-		string hex_char; 		string description = ""; 		File file;-				+ 		file = get_unicode_database ();-		hex_char = Font.to_hex (c).replace ("U+", "");-		-		if (hex_char.char_count () == 2) {-			hex_char = "00" + hex_char;-		}-		-		if (hex_char.char_count () == 6 && hex_char.has_prefix ("0")) {-			hex_char = hex_char.substring (1);-		}-		-		hex_char += "\t";-		hex_char = hex_char.up (); 		 		try { 			fin = file.read (); 			din = new DataInputStream (fin); 			-			while ((line = din.read_line (null)) != null) {+			line = din.read_line (null);+			while (true) { 				data = (!) line;-				if (data.has_prefix (hex_char)) {-					description = data;-					-					while ((line = din.read_line (null)) != null) {-						data = (!) line;-						if (data.has_prefix ("\t")) {-							description += "\n";-							description += data;-						} else {-							break;+				description = data;+				+				while ((line = din.read_line (null)) != null) {+					data = (!) line;+					if (data.has_prefix ("\t")) {+						description += "\n";+						description += data;+					} else {+						if (description.index_of ("<not a character>") == -1) {+							add_entry (description); 						}+						break; 					} 					+					Tool.yield ();+				}+				+				if (line == null) { 					break; 				} 			}@@ -107,102 +184,82 @@ class CharDatabase { 			din.close (); 		} catch (GLib.Error e) { 			warning (e.message);-			stderr.printf ("when reading %s", (!) get_unicode_database ().get_path ());+			warning ("In %s", (!) get_unicode_database ().get_path ()); 		}+	}++	public static bool has_ascender (unichar c) {+		if (!c.islower()) return true; 		-		if (description == "") {-			description = Font.to_hex (c).replace ("U+", "") + "\tUNICODE CHARACTER";+		switch (c) {+			case 'b': return true;+			case 'd': return true;+			case 'f': return true;+			case 'h': return true;+			case 'k': return true;+			case 'l': return true;	+		}++		return false;+	}++	public static bool has_descender (unichar c) {+		switch (c) {+			case 'g': return true;+			case 'j': return true;+			case 'p': return true;+			case 'q': return true;+			case 'y': return true; 		} 		-		return description;		+		return false;		 	} 	-	public static void get_full_unicode (GlyphRange glyph_range) {-		File file;-		FileInputStream fin;-		DataInputStream din;-		DataOutputStream os;-		string? line;-		string data;-		string[] range;+	/** Convert from the U+xx form to the unicode database hex value. */ +	static string to_database_hex (unichar c) {+		string hex_char = Font.to_hex (c).replace ("U+", "");++		if (hex_char.char_count () == 2) {+			hex_char = "00" + hex_char;+		} 		-		try {		-			file = BirdFont.get_settings_directory ().get_child ("full_unicode_range");-			-			if (file.query_exists ()) {-				// read cached glyph ranges-				fin = file.read ();-				din = new DataInputStream (fin);-				while ((line = din.read_line (null)) != null) {-					data = (!) line;-					-					if (data == "") {-						break;-					}-					-					range = data.split (" - ");-					return_if_fail (range.length == 2);-					-					glyph_range.add_range (Font.to_unichar ("U+" + range[0]), Font.to_unichar ("U+" + range[1]));-				}-				fin.close ();-				din.close ();					-			} else {-				parse_full_unicode_database (glyph_range);-				-				// write cache-				os = new DataOutputStream(file.create (FileCreateFlags.REPLACE_DESTINATION));-				os.put_string (glyph_range.get_all_ranges ());-				os.close ();-			}-		} catch (GLib.Error e) {-			warning (e.message);+		if (hex_char.char_count () == 6 && hex_char.has_prefix ("0")) {+			hex_char = hex_char.substring (1); 		}+		+		hex_char = hex_char.up ();		+		return hex_char; 	} 	-	/** Obtain full unicode range from unicode database. */-	public static void parse_full_unicode_database (GlyphRange glyph_range) {-		FileInputStream fin;-		DataInputStream din;-		string? line;-		string data;-		string hex_char;-		File file;-		unichar ch;+	public static string get_unicode_database_entry (unichar c) {+		string description;+		string? d; 		-		file = get_unicode_database ();+		d = entries.get (to_database_hex (c)); 		-		if (!file.query_exists ()) {-			warning ("Can not find unicode database.");-			return;+		if (d == null) {+			description = Font.to_hex (c).replace ("U+", "") + "\tUNICODE CHARACTER";+		} else {+			description = (!) d; 		}-+		+		return description;		+	}+	+	static void show_loading_message () {+		MainWindow.set_status (_("Loading the unicode database") + " ...");+	}+	+	public static void get_full_unicode (GlyphRange glyph_range) {+		if (!database_is_loaded) {+			show_loading_message ();+		}+		 		try {-			fin = file.read ();-			din = new DataInputStream (fin);-			-			while ((line = din.read_line (null)) != null) {-				data = (!) line;-				-				if (data.has_prefix ("\t") || data.has_prefix (";") || data.has_prefix ("@")) {-					continue;-				}-				-				if (data.index_of ("<not a character>") != -1) {-					continue;-				}-				-				hex_char = "U+" + data.substring (0, data.index_of ("\t")).down ();-				-				ch = Font.to_unichar (hex_char);-				glyph_range.add_single (ch);-			}-			-			fin.close ();-			din.close ();-		} catch (GLib.Error e) {+			glyph_range.parse_ranges (full_unicode_range.get_all_ranges ());+		} catch (MarkupError e) { 			warning (e.message);-		}	+		} 	} 	 	static File get_unicode_database () {diff --git a/libbirdfont/DefaultCharactersSet.vala b/libbirdfont/DefaultCharactersSet.valaindex 1a3fa71..615d2e3 100644--- a/libbirdfont/DefaultCharactersSet.vala+++ b/libbirdfont/DefaultCharactersSet.vala@@ -261,6 +261,7 @@ public class DefaultCharacterSet { 		CharDatabase.get_full_unicode (gr); 		 		if (gr.get_length () == 0) {+			warning ("No items obtained from UCD."); 			gr.add_range ('\0', (unichar) 0xFFF8); 		} 	}diff --git a/libbirdfont/Font.vala b/libbirdfont/Font.valaindex a243a16..21e6b06 100644--- a/libbirdfont/Font.vala+++ b/libbirdfont/Font.vala@@ -718,7 +718,7 @@ public class Font : GLib.Object { 		unichar rc = 0; 		bool r; 		-		if (unlikely (!unicode.has_prefix ("U+"))) {+		if (unlikely (!unicode.has_prefix ("U+") && !unicode.has_prefix ("u+"))) { 			warning (@"All unicode values must begin with U+ ($unicode)"); 			return '\0'; 		}diff --git a/libbirdfont/GlyphRange.vala b/libbirdfont/GlyphRange.valaindex 47f7a79..bd7e9a3 100644--- a/libbirdfont/GlyphRange.vala+++ b/libbirdfont/GlyphRange.vala@@ -136,6 +136,8 @@ public class GlyphRange { 				add_single (' '); 			} else if (w == "divis") { 				add_single ('-');+			} else if (w == "null") {+				add_single ('\0'); 			} else if (w.index_of ("-") > -1) { 				parse_range (w); 			} else {@@ -179,7 +181,11 @@ public class GlyphRange { 		if (c == '-') { 			return "divis"; 		}-		++		if (c == '\0') {+			return "null";+		}+				 		s.append_unichar (c);	 		return s.str;	 	}@@ -192,17 +198,30 @@ public class GlyphRange { 		if (c == "divis") { 			return "-"; 		}++		if (c == "null") {+			return "\0";+		} 		 		return c; 	} 	 	private void parse_range (string s) throws MarkupError { 		string[] r = s.split ("-");+		bool null_range = false; 		-		if (r.length != 2-			|| unserialize (r[0]).char_count () != 1 -			|| unserialize (r[1]).char_count () != 1) {-			throw new MarkupError.PARSE (@"$s is not a valid range, it should be on the form A-Z.");+		if (r.length == 2 && r[0] == "null" && r[1] == "null") {+			null_range = true;+		} else if (r.length == 2 && r[0] == "null" &&  unserialize (r[1]).char_count () == 1) {+			null_range = true;+		} +		+		if (!null_range) {+			if (r.length != 2+				|| unserialize (r[0]).char_count () != 1 +				|| unserialize (r[1]).char_count () != 1) {+				throw new MarkupError.PARSE (@"$s is not a valid range, it should be on the form A-Z.");+			} 		} 		 		append_range (unserialize (r[0]).get_char (), unserialize (r[1]).get_char ());diff --git a/libbirdfont/MainWindow.vala b/libbirdfont/MainWindow.valaindex 76955cb..5feb478 100644--- a/libbirdfont/MainWindow.vala+++ b/libbirdfont/MainWindow.vala@@ -28,8 +28,8 @@ public class MainWindow { 	public static OverView over_view;	
 	public static TabBar tabs;
 	public static NativeWindow native_window;
-	
 	public static KerningDisplay kerning_display;
+	public static CharDatabase character_database;
 
 	public MainWindow () {
 		singleton = this;
@@ -42,6 +42,7 @@ public class MainWindow { 		tool_tip = new TooltipArea ();
 		over_view = new OverView();
 		kerning_display = new KerningDisplay ();
+		character_database = new CharDatabase ();
 	}
 
 	public static DrawingTools get_drawing_tools () {
@@ -60,10 +61,6 @@ public class MainWindow { 		return glyph_canvas;
 	}
 	
-	public static OverView get_over_view () {
-		return over_view;
-	}
-	
 	public static Glyph get_current_glyph () {
 		if (unlikely (is_null (BirdFont.current_glyph))) {
 			warning ("No default glyph have been set yet.\n");
diff --git a/libbirdfont/OverView.vala b/libbirdfont/OverView.valaindex e3579b4..ff2c192 100644--- a/libbirdfont/OverView.vala+++ b/libbirdfont/OverView.vala@@ -32,9 +32,9 @@ public class OverView : FontDisplay { 	public signal void open_glyph_signal (GlyphCollection c); 	 	GlyphRange glyph_range;+	string search_query = ""; 	 	List<OverViewItem> visible_items = new List<OverViewItem> ();- 	List<GlyphCollection> deleted_glyphs = new List<GlyphCollection> (); 		 	bool all_available = true;@@ -51,7 +51,7 @@ public class OverView : FontDisplay { 			gr = new GlyphRange (); 			set_glyph_range (gr); 		}-		+ 		reset_zoom ();  		this.open_glyph_signal.connect ((glyph_collection) => {@@ -104,6 +104,26 @@ public class OverView : FontDisplay { 		update_scrollbar (); 	} 	+	public static void search () {+		OverView ow = MainWindow.get_overview ();+		TextListener listener = new TextListener (_("Search"), ow.search_query, _("Filter"));+		+		listener.signal_text_input.connect ((text) => {+			OverView o = MainWindow.get_overview ();+			o.search_query = text;+		});+		+		listener.signal_submit.connect (() => {+			OverView o = MainWindow.get_overview ();+			GlyphRange r = CharDatabase.search (o.search_query);+			o.set_glyph_range (r);+			MainWindow.native_window.hide_text_input ();+			MainWindow.get_tab_bar ().select_tab_name ("Overview");+		});+		+		MainWindow.native_window.set_text_listener (listener);+	}+	 	public Glyph? get_current_glyph ()  	requires (selected > 0 && selected < visible_items.length ()) { 		OverViewItem oi = visible_items.nth (selected).data;

Contact

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