Clone in a terminal:
Commit dd80093
Johan Mattsson - 2014-09-30T10:44:34+00:00
dd8009322109f8c8b1b91219f2032441e47f124fjohan.mattsson.m@gmail.com

Add ligatures

Changed files (11)

Diff

diff --git a/birdfont/GtkWindow.vala b/birdfont/GtkWindow.valaindex ec2d02d..e2544bf 100644--- a/birdfont/GtkWindow.vala+++ b/birdfont/GtkWindow.vala@@ -731,6 +731,12 @@ public class GtkWindow : Gtk.Window, NativeWindow { 		show_ligatures.activate.connect (() => {  			 MenuTab.show_ligature_tab (); 		});++		Gtk.MenuItem add_ligature = new Gtk.MenuItem.with_mnemonic (t_("_Add Ligature"));+		ligature_menu.append (add_ligature);+		add_ligature.activate.connect (() => { +			 MenuTab.add_ligature ();+		});		 		 		// Add menus 		Gtk.MenuItem file_launcher = new Gtk.MenuItem.with_mnemonic (t_("_File"));diff --git a/libbirdfont/BirdFontFile.vala b/libbirdfont/BirdFontFile.valaindex 25f1865..a382a91 100644--- a/libbirdfont/BirdFontFile.vala+++ b/libbirdfont/BirdFontFile.vala@@ -33,27 +33,35 @@ class BirdFontFile : GLib.Object { 	public bool load (string path) { 		string xml_data; 		XmlParser parser;-		bool ok;+		bool ok = false; 	-		FileUtils.get_contents(path, out xml_data);-		-		font.background_images.clear ();-		font.font_file = path;-		-		parser = new XmlParser (xml_data);-		ok = load_xml (parser);-				+		try {+			FileUtils.get_contents(path, out xml_data);+			+			font.background_images.clear ();+			font.font_file = path;+			+			parser = new XmlParser (xml_data);+			ok = load_xml (parser);+		} catch (GLib.FileError e) {+			warning (e.message);+		}+			 		return ok; 	}  	public bool load_part (string bfp_file) { 		string xml_data; 		XmlParser parser;-		bool ok;+		bool ok = false; 	-		FileUtils.get_contents(bfp_file, out xml_data);-		parser = new XmlParser (xml_data);-		ok = load_xml (parser);+		try {+			FileUtils.get_contents(bfp_file, out xml_data);+			parser = new XmlParser (xml_data);+			ok = load_xml (parser);+		} catch (GLib.FileError e) {+			warning (e.message);+		} 		 		return ok; 	}@@ -195,6 +203,7 @@ class BirdFontFile : GLib.Object { 		os.put_string ("""<?xml version="1.0" encoding="utf-8" standalone="yes"?>"""); 		os.put_string ("\n"); 		os.put_string ("<font>\n");+		os.put_string ("<format>1.0</format>\n"); 	} 	 	public void write_closing_root_tag (DataOutputStream os) throws GLib.Error {@@ -302,7 +311,15 @@ class BirdFontFile : GLib.Object { 	}  	public void write_glyph_collection_start (GlyphCollection gc, DataOutputStream os)  throws GLib.Error {-		os.put_string (@"<collection unicode=\"$(Font.to_hex (gc.get_current ().unichar_code))\">\n");		+		os.put_string ("<collection ");+		+		if (gc.get_current ().is_unassigned ()) {+			os.put_string (@"name=\"$(gc.get_current ().get_name ())\"");+		} else {+			os.put_string (@"unicode=\"$(Font.to_hex (gc.get_current ().unichar_code))\"");+		}+		+		os.put_string (">\n"); 	}  	public void write_glyph_collection_end (DataOutputStream os)  throws GLib.Error {@@ -902,10 +919,12 @@ class BirdFontFile : GLib.Object { 		int selected_id = -1; 		Attribute attribute; 		Tag t;+		bool unassigned = false; 		 		tag.reparse (); 		while (tag.has_more_attributes ()) { 			attribute = tag.get_next_attribute ();+			 			if (attribute.get_name () == "unicode") { 				unicode = Font.to_unichar (attribute.get_content ()); 				b = new StringBuilder ();@@ -915,6 +934,14 @@ class BirdFontFile : GLib.Object { 				if (name == "") { 					name = ".null"; 				}+				+				unassigned = false;+			}++			if (attribute.get_name () == "name") {+				unicode = '\0';+				name = attribute.get_content ();+				unassigned = true; 			} 		} @@ -937,7 +964,7 @@ class BirdFontFile : GLib.Object { 			t = tag.get_next_tag (); 			 			if (t.get_name () == "glyph") {-				parse_glyph (t, gc, name, unicode, selected_id);+				parse_glyph (t, gc, name, unicode, selected_id, unassigned); 			} 		} 		@@ -969,7 +996,8 @@ class BirdFontFile : GLib.Object { 		return id; 	} -	private void parse_glyph (Tag tag, GlyphCollection gc, string name, unichar unicode, int selected_id) {	+	private void parse_glyph (Tag tag, GlyphCollection gc, string name, +			unichar unicode, int selected_id, bool unassigned) {	 		Glyph glyph = new Glyph (name, unicode); 		Path path; 		bool selected = false;@@ -1015,7 +1043,8 @@ class BirdFontFile : GLib.Object { 			} 		} -		glyph.version_id = (has_id) ? id : (int) gc.length () + 1;		+		glyph.version_id = (has_id) ? id : (int) gc.length () + 1;+		glyph.set_unassigned (unassigned); 		gc.insert_glyph (glyph, selected || selected_id == id); 	} diff --git a/libbirdfont/ClipTool.vala b/libbirdfont/ClipTool.valaindex 4b6554a..75974b4 100644--- a/libbirdfont/ClipTool.vala+++ b/libbirdfont/ClipTool.vala@@ -157,14 +157,29 @@ public class ClipTool : Tool { 		 		if (overview) { 			o = MainWindow.get_overview ();+			unichar last_assigned = '\0'; 			foreach (GlyphCollection gc in o.selected_items) { 				s.append ("\n"); 				s.append ("<!-- BirdFontClipboard\n"); -				s.append ("BF glyph: ");-				s.append (@"$(Font.to_hex (gc.get_unicode_character ()))");+				if (!gc.is_unassigned ()) {+					last_assigned = gc.get_unicode_character ();+					+					s.append ("BF glyph: ");+					s.append (@"$(Font.to_hex (gc.get_unicode_character ()))");+					s.append ("\n");+				} else {+					last_assigned++;+					+					s.append ("BF glyph: ");+					s.append (@"$(Font.to_hex (last_assigned))");+					s.append ("\n");+				}++				s.append ("BF unassigned: ");+				s.append (@"$(gc.is_unassigned ())"); 				s.append ("\n");-				+							 				s.append ("BF left: "); 				s.append (@"$(gc.get_current ().left_limit)"); 				s.append ("\n");@@ -191,6 +206,10 @@ public class ClipTool : Tool { 			s.append (@"$(Font.to_hex (glyph.unichar_code))"); 			s.append ("\n"); 			+			s.append ("BF unassigned: ");+			s.append (@"$(glyph.is_unassigned ())");+			s.append ("\n");+						 			s.append ("BF left: "); 			s.append (@"$(glyph.left_limit)"); 			s.append ("\n");@@ -272,8 +291,6 @@ public class ClipTool : Tool { 		Gee.ArrayList<Glyph> glyphs = new Gee.ArrayList<Glyph> (); 		Glyph glyph = new Glyph ("null", '\0'); 		string[] items = data.split ("\nBF ");-		string d;-		int i; 		unichar c; 		Glyph destination; 		GlyphCollection gc;@@ -287,7 +304,13 @@ public class ClipTool : Tool { 				glyph = new Glyph ((!) c.to_string (), c); 				glyphs.add (glyph); 			}-			++			if (p.has_prefix ("unassigned:")) {+				p = p.replace ("unassigned: ", "");+				p = p.replace ("\n", "");+				glyph.set_unassigned (bool.parse (p)); // FIXME: move to gc+			}+						 			if (p.has_prefix ("path:")) { 				p = p.replace ("path: ", ""); 				p = p.replace ("\n", "");diff --git a/libbirdfont/Font.vala b/libbirdfont/Font.valaindex c53eebb..13d4278 100644--- a/libbirdfont/Font.vala+++ b/libbirdfont/Font.vala@@ -376,7 +376,8 @@ public class Font : GLib.Object { 			return; 		} 		-		if (glyph_collection.get_unicode () != "") {+		// FIXME: move unassinged+		if (glyph_collection.get_unicode () != "" || glyph_collection.get_current ().is_unassigned ()) { 			glyph_name.insert (glyph_collection.get_name (), glyph_collection);			 		} 		diff --git a/libbirdfont/GlyphCollection.vala b/libbirdfont/GlyphCollection.valaindex 75110c0..587c15c 100644--- a/libbirdfont/GlyphCollection.vala+++ b/libbirdfont/GlyphCollection.vala@@ -21,6 +21,7 @@ public class GlyphCollection : GLib.Object { 	VersionList versions; 	unichar unicode_character; 	string name;+	bool unassigned = false;  	public GlyphCollection (unichar unicode_character, string name) { 		this.unicode_character = unicode_character;@@ -28,6 +29,14 @@ public class GlyphCollection : GLib.Object { 		versions = new VersionList (null, this); 	} +	public void set_unassigned (bool a) {+		unassigned = a;+	}++	public bool is_unassigned () {+		return unassigned;+	}+	 	public void add_glyph (Glyph g) { 		get_version_list ().add_glyph (g); 	}diff --git a/libbirdfont/MenuTab.vala b/libbirdfont/MenuTab.valaindex 8099d58..29f5339 100644--- a/libbirdfont/MenuTab.vala+++ b/libbirdfont/MenuTab.vala@@ -448,6 +448,50 @@ public class MenuTab : FontDisplay { 		SpacingClassTab t = MainWindow.get_spacing_class_tab (); 		MainWindow.get_tab_bar ().add_unique_tab (t); 	}++	public static void add_ligature () {+		TextListener listener;+		string ligature_name = "";+		+		if (suppress_event) {+			warn_if_test ("Event suppressed");+			return;+		}+		+		listener = new TextListener (t_("Name"), "", t_("Add ligature"));+		+		listener.signal_text_input.connect ((text) => {+			ligature_name = text;+		});+		+		listener.signal_submit.connect (() => {+			Font font = BirdFont.get_current_font ();+			GlyphCollection? fg;+			Glyph glyph;+			GlyphCollection glyph_collection;+			OverView o = MainWindow.get_overview ();++			fg = font.get_glyph_collection_by_name (ligature_name);++			if (fg == null) {+				glyph_collection = new GlyphCollection ('\0', ligature_name);+				+				glyph = new Glyph (ligature_name, '\0');+				glyph.set_unassigned (true);+				glyph_collection.insert_glyph (glyph, true);++				font.add_glyph_collection (glyph_collection);+			}+			+			o.display_all_available_glyphs ();+			o.scroll_to_glyph (ligature_name);+			+			MainWindow.native_window.hide_text_input ();+			Toolbox.select_tool_by_name ("available_characters");+		});+		+		MainWindow.native_window.set_text_listener (listener);+	} }  }diff --git a/libbirdfont/OpenFontFormat/Gsub.vala b/libbirdfont/OpenFontFormat/Gsub.valaindex 0bd7d22..2491051 100644--- a/libbirdfont/OpenFontFormat/Gsub.vala+++ b/libbirdfont/OpenFontFormat/Gsub.vala@@ -63,7 +63,7 @@ public class GsubTable : Table { 		fd.add_ushort (1); // number of lookups 		fd.add_ushort (4); // offset to lookup 1 		-		// ligature substitution+		// ligature substitution subtable 		fd.add_ushort (1); // lookup type, format identifier 		fd.add_ushort (20); // offset to coverage 		fd.add_ushort (1); // number of ligature set tablesdiff --git a/libbirdfont/OverView.vala b/libbirdfont/OverView.valaindex 988e279..8b98de6 100644--- a/libbirdfont/OverView.vala+++ b/libbirdfont/OverView.vala@@ -107,19 +107,24 @@ public class OverView : FontDisplay { 		update_scrollbar (); 	} 	-	public GlyphCollection add_empty_character_to_font (unichar character) {-		return add_character_to_font (character, true);+	public GlyphCollection add_empty_character_to_font (unichar character, bool unassigned, string name) {+		return add_character_to_font (character, true, unassigned); 	} 	-	public GlyphCollection add_character_to_font (unichar character, bool empty = false) {+	public GlyphCollection add_character_to_font (unichar character, bool empty = false,+			bool unassigned = false, string glyph_name = "") { 		StringBuilder name = new StringBuilder (); 		Font font = BirdFont.get_current_font (); 		GlyphCollection? fg; 		Glyph glyph; 		GlyphCollection glyph_collection; -		name.append_unichar (character);-+		if (glyph_name == "") {+			name.append_unichar (character);+		} else {+			name.append (glyph_name);+		}+		 		if (all_available) { 			fg = font.get_glyph_collection_by_name (name.str); 		} else {@@ -132,13 +137,15 @@ public class OverView : FontDisplay { 			glyph_collection = new GlyphCollection (character, name.str); 			 			if (!empty) {-				glyph = new Glyph (name.str, character);+				glyph = new Glyph (name.str, (!unassigned) ? character : '\0'); 				glyph_collection.insert_glyph (glyph, true); 			} 			 			font.add_glyph_collection (glyph_collection); 		} 		+		glyph_collection.set_unassigned (unassigned);+		 		return glyph_collection; 	} 	@@ -768,11 +775,11 @@ public class OverView : FontDisplay { 		redo_items.clear (); 	} 	-	bool select_visible_character (unichar c) {+	bool select_visible_glyph (string name) { 		int i = 0; 		 		foreach (OverViewItem o in visible_items) {-			if (o.character == c) {+			if (o.get_name () == name) { 				selected = i; 				selected_item = get_selected_item (); 				return true;@@ -788,11 +795,27 @@ public class OverView : FontDisplay { 		 		return false; 	}-			+	+	bool select_visible_character (unichar c) {+		StringBuilder s = new StringBuilder ();+		s.append_unichar (c);+		return select_visible_glyph (s.str);+	}+	 	public void scroll_to_char (unichar c) {+		StringBuilder s = new StringBuilder ();++		if (is_modifier_key (c)) {+			return;+		}+		+		s.append_unichar (c);+		scroll_to_glyph (s.str);+	}+		+	public void scroll_to_glyph (string name) { 		GlyphRange gr = glyph_range; 		int i, r, index;-		StringBuilder s = new StringBuilder (); 		string ch; 		Font font = BirdFont.get_current_font (); 		GlyphCollection? glyphs = null;@@ -804,16 +827,11 @@ public class OverView : FontDisplay { 			warning ("No items."); 			return; 		}-		-		if (is_modifier_key (c)) {-			return;-		}-		-		s.append_unichar (c);-		ch = s.str;++		ch = name;  		// selected char is visible-		if (select_visible_character (c)) {+		if (select_visible_glyph (ch)) { 			return; 		} 		@@ -842,6 +860,12 @@ public class OverView : FontDisplay { 				} 			} 		} else {+			+			if (ch.char_count () > 1) {+				warning ("Can't scroll to ligature in this view");+				return;+			}+			 			for (r = 0; r < gr.length (); r += items_per_row) { 				for (i = 0; i < items_per_row; i++) { 					if (gr.get_char (r + i) == ch) {@@ -858,7 +882,7 @@ public class OverView : FontDisplay { 		if (index > -1) { 			first_visible = r; 			update_item_list ();-			select_visible_character (c);+			select_visible_glyph (ch); 		} 	} 	@@ -1125,24 +1149,27 @@ public class OverView : FontDisplay { 			return (int) ((GlyphCollection) a).get_unicode_character ()  				- (int) ((GlyphCollection) b).get_unicode_character (); 		});-		-		// FIXME: copy and paste to unicode character + 1 -		+ 		index = (uint32) first_visible + selected; 		for (i = 0; i < copied_glyphs.size; i++) { 			if (all_available) { 				if (f.length () == 0) {-					c = add_empty_character_to_font (-						glyps.get (i).get_unicode_character ());					+					c = add_empty_character_to_font (glyps.get (i).get_unicode_character (),+						glyps.get (i).is_unassigned (), glyps.get (i).get_name ()); 				} else if (index >= f.length ()) { 					c = add_empty_character_to_font (-						((!)f.get_glyph_collection_indice (f.length () - 1)).get_unicode_character () + i);+						((!)f.get_glyph_collection_indice (f.length () - 1))+							.get_unicode_character () + i,+						glyps.get (i).is_unassigned (),+						glyps.get (i).get_name ()); 				} else { 					c = f.get_glyph_collection_indice ((uint32) index); 				} 				 				if (c == null) {-					c = add_empty_character_to_font (copied_glyphs.get (i).get_unicode_character ());+					c = add_empty_character_to_font (copied_glyphs.get (i).get_unicode_character (),+						glyps.get (i).is_unassigned (),+						glyps.get (i).get_name ()); 				} 				 				return_if_fail (c != null);@@ -1159,7 +1186,9 @@ public class OverView : FontDisplay { 				c = f.get_glyph_collection_by_name (character_string); 				 				if (c == null) {-					gc = add_empty_character_to_font (character_string.get_char ());+					gc = add_empty_character_to_font (character_string.get_char (), +						glyps.get (i).is_unassigned (),+						glyps.get (i).get_name ()); 				} else { 					gc = (!) c; 				}diff --git a/libbirdfont/OverViewItem.vala b/libbirdfont/OverViewItem.valaindex 2a52e35..5a5b2f3 100644--- a/libbirdfont/OverViewItem.vala+++ b/libbirdfont/OverViewItem.vala@@ -18,7 +18,7 @@ using Math; namespace BirdFont { 	 public class OverViewItem : GLib.Object {-	public unichar character = 'A';+	public unichar character = '\0'; 	public GlyphCollection? glyphs; 	public double x; 	public double y;@@ -41,6 +41,19 @@ public class OverViewItem : GLib.Object { 		this.info = new CharacterInfo (character); 	} 	+	public string get_name () {+		StringBuilder s;+		+		if (glyphs != null) {+			return ((!) glyphs).get_name ();+		}+		+		s = new StringBuilder ();+		s.append_unichar (character);+		+		return s.str;+	}+	 	public void set_selected (bool s) { 		selected = s; 	}diff --git a/libbirdfont/PenTool.vala b/libbirdfont/PenTool.valaindex 3abbbf7..91c7262 100644--- a/libbirdfont/PenTool.vala+++ b/libbirdfont/PenTool.vala@@ -530,9 +530,6 @@ public class PenTool : Tool { 		Glyph glyph = MainWindow.get_current_glyph (); 		double coordinate_x, coordinate_y; 		double delta_coordinate_x, delta_coordinate_y;-		int px = 0;-		int py = 0;-		EditPoint p; 		double angle = 0; 		 		control_point_event (x, y);@@ -656,16 +653,7 @@ public class PenTool : Tool { 			} 		} 	}-	-	private static void tie_pixels (ref int x, ref int y) {-		double coordinate_x, coordinate_y;-		coordinate_x = Glyph.path_coordinate_x (x);-		coordinate_y = Glyph.path_coordinate_y (y);-		GridTool.tie_coordinate (ref coordinate_x, ref coordinate_y);-		x = Glyph.reverse_path_coordinate_x (coordinate_x);-		y = Glyph.reverse_path_coordinate_y (coordinate_y);-	}-	+ 	public void press (int button, int x, int y, bool double_click) { 		Glyph? g = MainWindow.get_current_glyph (); 		Glyph glyph = (!) g;@@ -904,8 +892,7 @@ public class PenTool : Tool { 		Path path; 		bool direction_changed = false; 		Path union, second_path;-		EditPoint last_point, first_point;-		EditPointHandle last_rh, fist_lh;+		EditPoint first_point; 		int px, py; 		 		if (glyph.path_list.size == 0) {diff --git a/libbirdfont/SvgParser.vala b/libbirdfont/SvgParser.valaindex 05bca81..004ad71 100644--- a/libbirdfont/SvgParser.vala+++ b/libbirdfont/SvgParser.vala@@ -55,7 +55,6 @@ public class SvgParser { 		Glyph glyph;  		string[] lines = xml_data.split ("\n"); 		bool has_format = false;-		StringBuilder sb = new StringBuilder (); 		SvgParser parser = new SvgParser (); 		XmlParser xmlparser; 		Tag root;@@ -363,7 +362,6 @@ public class SvgParser { 	private void parse_path (Tag tag, PathList pl) { 		Glyph glyph = MainWindow.get_current_glyph (); 		PathList path_list = new PathList ();-		Tag t; 		Attribute attr; 		 		tag.reparse ();	

Contact

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