Clone in a terminal:
Commit 77aaf39
Johan Mattsson - 2013-03-16T08:47:16+00:00
77aaf39a685217eac00f47a8e8ad813ef4d06764johan.mattsson.m@gmail.com

Get descriptions from the Unicode Character Database

Changed files (6)

Diff

diff --git a/icons/next_tab.png b/icons/next_tab.pngindex a2f760c..864b736 100644Binary files a/icons/next_tab.png and b/icons/next_tab.png differdiff --git a/libbirdfont/CharDatabase.vala b/libbirdfont/CharDatabase.valaindex f2ce631..5f1183c 100644--- a/libbirdfont/CharDatabase.vala+++ b/libbirdfont/CharDatabase.vala@@ -58,6 +58,169 @@ class CharDatabase { 		return false;		 	} 	+	public static string get_unicode_database_entry (unichar c) {+		FileInputStream fin;+		DataInputStream din;+		string? line;+		string data;+		string hex_char;+		string description = "";+		File file;+				+		file = (!) File.new_for_path ("/usr/share/unicode/NamesList.txt"); // FIXME+		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) {+				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;+						}+					}+					+					break;+				}+			}+			+			if (description == "") {+				warning ("no description found");+			}+			+			fin.close ();+			din.close ();+		} catch (GLib.Error e) {+			warning (e.message);+		}+		+		return description;		+	}+	+	public static void get_full_unicode (GlyphRange glyph_range) {+		File file;+		FileInputStream fin;+		DataInputStream din;+		DataOutputStream os;+		string? line;+		string data;+		string[] range;+		+		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);+		}+	}+	+	/** 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;+		+		file = get_unicode_database ();+		+		if (!file.query_exists ()) {+			warning ("Can not find unicode database.");+			return;+		}++		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) {+			warning (e.message);+		}	+	}+	+	static File get_unicode_database () {+		File f;++		f = (!) File.new_for_path (PREFIX + "/share/unicode/NamesList.txt");+		if (f.query_exists ()) {+			return f;+		}+		+		f = (!) File.new_for_path (".\\NamesList.txt");+		if (f.query_exists ()) {+			return f;+		}+			+		f = (!) File.new_for_path ("/usr/share/unicode/NamesList.txt");+		return f;+	} }  }diff --git a/libbirdfont/CharacterInfo.vala b/libbirdfont/CharacterInfo.valanew file mode 100644index 0000000..bff5234--- /dev/null+++ b/libbirdfont/CharacterInfo.vala@@ -0,0 +1,66 @@+/*+    Copyright (C) 2013 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/>.+*/++using Cairo;++namespace BirdFont {++/** Display functions for a unicode character database entry. */+public class CharacterInfo : GLib.Object {++	static ImageSurface? info_icon = null;+	double x = 0;+	double y = 0;+	unichar unicode;+	+	public CharacterInfo (unichar c) {+		unicode = c;+		+		if (info_icon == null) {+			info_icon = Icons.get_icon ("info_icon.png");+		}+	}+	+	public string get_entry () {+		return CharDatabase.get_unicode_database_entry (unicode);+	}+	+	public void set_position (double x, double y) {+		this.x = x;+		this.y = y;+	}+	+	public bool is_over_icon (double px, double py) {+		return (x <= px <= x + 12) && (y <= py <= y + 12);+	}+	+	public void draw_icon (Context cr) {	+		ImageSurface i = (!) info_icon;+		+		// info icon			+		if (likely (info_icon != null && i.status () == Cairo.Status.SUCCESS)) {+			cr.save ();+			cr.set_source_surface (i, x, y);+			cr.paint ();+			cr.restore ();+		} else {+			warning ("Failed to load icon.");+		}		+	}+}++}diff --git a/libbirdfont/GlyphCollection.vala b/libbirdfont/GlyphCollection.valaindex 7e4995e..a78e37b 100644--- a/libbirdfont/GlyphCollection.vala+++ b/libbirdfont/GlyphCollection.vala@@ -22,11 +22,11 @@ namespace BirdFont {  public class GlyphCollection : GLib.Object { 	VersionList versions;-	+ 	public GlyphCollection (Glyph? current = null) { 		versions = new VersionList (current); 	}-	+ 	public VersionList get_version_list () { 		return versions; 	}diff --git a/libbirdfont/GlyphRange.vala b/libbirdfont/GlyphRange.valaindex 9ddb740..2ea7e6c 100644--- a/libbirdfont/GlyphRange.vala+++ b/libbirdfont/GlyphRange.vala@@ -175,16 +175,18 @@ public class GlyphRange { 	} 	 	public void use_full_unicode_range () {-		add_range ('\0', (unichar) 0xFFF8);+		CharDatabase.get_full_unicode (this);+		+		if (len == 0) {+			add_range ('\0', (unichar) 0xFFF8);+		} 	} 	 	// Todo: complete localized alphabetical sort åäö is the right order for example. 	public void sort () { 		ranges.sort ((a, b) => { 			bool r = a.start > b.start;-			 			return_val_if_fail (a.start != b.start, 0);-			 			return (r) ? 1 : -1; 		}); 	}@@ -240,9 +242,9 @@ public class GlyphRange { 	 	private void append_range (unichar start, unichar stop) { 		UniRange r;-		 		StringBuilder s = new StringBuilder (); 		StringBuilder e = new StringBuilder ();+		 		s.append_unichar (start); 		e.append_unichar (stop); 		@@ -345,17 +347,19 @@ public class GlyphRange { 	}  	public void print_all () {-		StringBuilder s;-		 		stdout.printf ("Ranges:\n");+		stdout.printf (get_all_ranges ());+	}+	+	public string get_all_ranges () {+		StringBuilder s = new StringBuilder (); 		foreach (UniRange u in ranges) {-			s = new StringBuilder ();-			s.append_unichar (u.start);+			s.append (Font.to_hex_code (u.start)); 			s.append (" - ");-			s.append_unichar (u.stop);+			s.append (Font.to_hex_code (u.stop)); 			s.append ("\n");-			stdout.printf (s.str); 		}+		return s.str; 	} } diff --git a/libbirdfont/OverView.vala b/libbirdfont/OverView.valaindex 969b25a..650f321 100644--- a/libbirdfont/OverView.vala+++ b/libbirdfont/OverView.vala@@ -48,12 +48,16 @@ public class OverView : FontDisplay { 	int zoom_list_index = 0;  	List<GlyphCollection> deleted_glyphs = new List<GlyphCollection> ();+	List<CharacterInfo> unicode_database_info = new List<CharacterInfo> (); 	 	bool all_available = true; 	+	/** Show unicode database info. */+	CharacterInfo? character_info = null;+	 	public OverView (GlyphRange? range = null) { 		GlyphRange gr;-		+ 		if (range == null) { 			gr = new GlyphRange (); 			set_glyph_range (gr);@@ -92,6 +96,8 @@ public class OverView : FontDisplay { 				g.close_path (); 				g.default_zoom (); 				z.store_current_view ();+				+				print (@"CHARDB: $(CharDatabase.get_unicode_database_entry (new_char))\n"); 			} 		}); 		@@ -330,11 +336,12 @@ public class OverView : FontDisplay { 			cr.set_line_join (LineJoin.ROUND); 			cr.set_line_width(12); 			-			cr.rectangle (x, y + nail_height - 20, nail_width - 30, 10);			+			cr.rectangle (x, y + nail_height - 20, nail_width - 20, 10);			 			cr.stroke (); 			cr.restore (); 			 			draw_menu (cr, character_string, x, y);+			draw_character_info_icon (cr, character_string, x, y); 			 			caption_y = y + 10 + nail_height - 20; 			@@ -348,9 +355,27 @@ public class OverView : FontDisplay { 		 		cr.stroke(); 	}+	+	private void draw_character_info_icon (Context cr, string character_string, double x, double y) {+		double px = x + nail_width - 40;+		double py = y + nail_height - 21;+		CharacterInfo info;+		unichar c = character_string.get_char ();+		+		if (character_string.char_count () > 1) {+			warning ("Ligature - not a character");+			c = '\0';+		} 		+		info = new CharacterInfo (c);+		unicode_database_info.append (info);+		info.set_position (px, py);+		info.draw_icon (cr);+	}+	 	private void draw_menu (Context cr, string name, double x, double y) {-		GlyphCollection? gl = BirdFont.get_current_font ().get_glyph_collection (name);+		Font font = BirdFont.get_current_font ();+		GlyphCollection? gl = font.get_glyph_collection (name); 		GlyphCollection g; 		DropMenu menu; 		@@ -361,7 +386,7 @@ public class OverView : FontDisplay { 		g = (!) gl; 		 		menu = g.get_version_list ();-		menu.set_position (x + nail_width - 40, y + nail_height - 21);+		menu.set_position (x + nail_width - 55, y + nail_height - 21); 		menu.draw_icon (cr); 		menu.draw_menu (cr); 		@@ -421,7 +446,11 @@ public class OverView : FontDisplay { 		int i; 		int n_items; 		Font font = BirdFont.get_current_font ();-					+		+		while (unicode_database_info.length () > 0) {+			unicode_database_info.remove_link (unicode_database_info.first ());+		}+		 		while (visible_characters.length () > 9) { 			visible_characters.remove_link (visible_characters.first ()); 		}@@ -438,8 +467,8 @@ public class OverView : FontDisplay { 			draw_empty_canvas (allocation, cr); 		} 		-		n_items = ((allocation.width - 40) / nail_width);-		rows = (allocation.height / nail_height);+		n_items = allocation.width / nail_width;+		rows = allocation.height / nail_height;  		if (items_per_row != n_items) { 	 			if (items_per_row == 0) {@@ -454,10 +483,10 @@ public class OverView : FontDisplay { 			} 		} -		width = nail_width * items_per_row;+		width = (nail_width - 5) * items_per_row; 		view_offset_x = (allocation.width - width) / 2.0; 		-		cr.translate(view_offset_x, view_offset_y);+		cr.translate (view_offset_x, view_offset_y); 	 		y = 0; 		t = first_visible;@@ -470,8 +499,104 @@ public class OverView : FontDisplay { 			i++; 		} 		+		cr.restore (); // restore translation+		+		if (character_info != null) {+			draw_character_info (allocation, cr, (!) character_info);+		} 	} +	void draw_character_info (Allocation allocation, Context cr, CharacterInfo info) {+		double x, y, w, h;+		int i;+		string unicode_value, unicode_description;+		string[] column;+		string entry = info.get_entry ();+		int len = 0;+		int length = 0;+		bool see_also = false;+		+		foreach (string line in entry.split ("\n")) {+			len = line.char_count ();+			if (len > length) {+				length = len;+			}+		}+		+		x = allocation.width * 0.1 - view_offset_x;+		y = allocation.height * 0.1 - view_offset_y;+		w = allocation.width * 0.9 - x - view_offset_x; +		h = allocation.height * 0.9 - y - view_offset_y;+		+		if (w < 8 * length) {+			w = 8 * length;+			if (w > allocation.width - view_offset_x) {+				x = -view_offset_x;+			} else {+				x = (allocation.width - view_offset_x- w) / 2.0;+			}+		}+		+		// background	+		cr.save ();+		cr.set_source_rgba (1, 1, 1, 0.7);+		cr.rectangle (x, y, w, h);+		cr.fill ();+		cr.restore ();++		cr.save ();+		cr.set_source_rgba (0, 0, 0, 0.7);+		cr.set_line_width (2);+		cr.rectangle (x, y, w, h);+		cr.stroke ();+		cr.restore ();++		// database entry+		i = 0;+		foreach (string line in entry.split ("\n")) {+			if (i == 0) {+				column = line.split ("\t");+				return_if_fail (column.length == 2);+				unicode_value = "U+" + column[0];+				unicode_description = column[1];++				draw_line (unicode_description, cr, x, y, i);+				i++;++				draw_line (unicode_value, cr, x, y, i);+				i++;			+			} else {+				+				if (line.has_prefix ("\t*")) {+					draw_line (line.replace ("\t*", "•"), cr, x, y, i);+					i++;					+				} else if (line.has_prefix ("\tx (")) {+					if (!see_also) {+						i++;+						draw_line (_("See also:"), cr, x, y, i);+						i++;+						see_also = true;+					}+					+					draw_line (line.replace ("\tx (", "•").replace (")", ""), cr, x, y, i);+					i++;+				} else {++					i++;+				}+			}+		}+	}+	+	void draw_line (string line, Context cr, double x, double y, int row) {+		cr.save ();+		cr.set_font_size (12);+		cr.set_source_rgba (0, 0, 0, 1);+		cr.move_to (x + 10, y + 28 + row * 18 * 1.2);+		cr.show_text (line);+		cr.restore ();		+	}+	 	void draw_empty_canvas (Allocation allocation, Context cr) { 		cr.save (); 		cr.set_source_rgba (156/255.0, 156/255.0, 156/255.0, 1);@@ -594,7 +719,10 @@ public class OverView : FontDisplay { 	private int selected_offset_y (unichar item) { 		int64 di; 		int64 a, b;-		if (unlikely (items_per_row == 0)) return 0;+		+		if (unlikely (items_per_row == 0)) {+			return 0;+		} 		 		a = (int64) item; 		b = (int64) first_visible;@@ -848,7 +976,8 @@ public class OverView : FontDisplay { 	private void selection_click (uint button, double ex, double ey) { 		double x = view_offset_x; 		double y = view_offset_y;-+		double px, py;+		 		// click in margin 		int n_items = (allocation.width - 40 / nail_width); 		double m = (allocation.width - 40 - (n_items * nail_width)) / 2.0;@@ -867,21 +996,30 @@ public class OverView : FontDisplay { 			len = glyph_range.length (); 		} 		+		px = ex - view_offset_x;+		py = ey - view_offset_y; 		foreach (GlyphCollection g in get_visible_glyphs ()) { 			bool a;--			a = g.get_version_list ().menu_item_action (ex - view_offset_x, ey - view_offset_y); // select one item on the menu+			+			a = g.get_version_list ().menu_item_action (px, py); // select one item on the menu 			 			if (a) { 				return; 			} 						-			a = g.get_version_list ().menu_icon_action (ex - view_offset_x, ey - view_offset_y); // open menu+			a = g.get_version_list ().menu_icon_action (px, py); // open menu 			 			if (a) { 				menu_action = true; 			} 		}++		character_info = null;+		foreach (CharacterInfo info in unicode_database_info) {+			if (info.is_over_icon (px, py)) {+				character_info = info;+			}+		} 		 		if (ex < m) { 			ex = m + 1;

Contact

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