Clone in a terminal:
Commit a76d9a8
Johan Mattsson - 2013-02-12T21:26:39+00:00
a76d9a8e1fd33f29ad36b3d3bf0976499b41d283johan.mattsson.m@gmail.com

parse ligatures from svg font

Changed files (7)

Diff

diff --git a/libbirdfont/Context.vala b/libbirdfont/Context.valadeleted file mode 100644index 562f4ea..0000000--- a/libbirdfont/Context.vala+++ /dev/null@@ -1,335 +0,0 @@-/*-    Copyright (C) 2012 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 {--/** Kerning context. */-public class ContextDisplay : FontDisplay {--	List <Word> row;-	int active_handle = -1;-	int selected_handle = -1;-	-	double begin_handle_x = 0;-	double begin_handle_y = 0;-	-	double last_handle_x = 0;-	-	public ContextDisplay () {-		Word w = new Word ();-		row = new List <Word> ();-		row.append (w);-	}--	public override string get_name () {-		return "Kerning";-	}-	-	public override void draw (Allocation allocation, Context cr) {-		Glyph? g;-		Glyph glyph;-		double x, y, w, kern, alpha;-		double x2;-		int i, wi;-		string prev;-		-		i = 0;-		-		// bg color-		cr.save ();-		cr.set_source_rgba (1, 1, 1, 1);-		cr.rectangle (0, 0, allocation.width, allocation.height);-		cr.fill ();-		cr.restore ();-	-		alpha = 1;-		y = 100;-		x = 20;-		w = 0;-		prev = "";-		-		foreach (Word word in row) {-			wi = 0;-			-			foreach (string s in word.glyph) {				-				g = (!) BirdFont.get_current_font ().get_glyph_by_name (s);	-				-				if (s == "") {-					continue;-				}-				-				kern = (prev != "") ? get_kerning (prev, s) : 0;-				-				// draw glyph				-				if (g == null) {-					w = 50;-					alpha = 1;-				} else {-					alpha = 0;-					glyph = (!) g;-					Svg.draw_svg_path (cr, glyph.get_svg_data (), x + kern, y);-					w = glyph.get_width ();-				}--				// handle-				if (active_handle == i) {-					//x2 = x + kern;-					x2 = x + kern / 2.0;-					-					cr.save ();-					cr.set_source_rgba (153/255.0, 153/255.0, 173/255.0, 1);-					cr.move_to (x2 - 5, y + 20);-					cr.line_to (x2 + 0, y + 20 - 5);-					cr.line_to (x2 + 5, y + 20);-					cr.fill ();-					-					cr.set_font_size (10);-					cr.show_text (s);-					cr.restore ();-				}	-				-				x += w + kern;-	-				// caption-				if (g == null || ((!)g).is_empty ()) {-					cr.save ();-					cr.set_source_rgba (153/255.0, 153/255.0, 153/255.0, alpha);-					cr.move_to (x - w / 2.0 - 5, y + 20);-					cr.set_font_size (10);-					cr.show_text (s);-					cr.restore ();-				}-							-				prev = s;-				-				wi++;-				i++;-			}-			-			if (y > allocation.height && i > 10) {-				row.remove (word);-			}-						-			y += MainWindow.get_current_glyph ().get_height () + 20;-			x = 20;			-		}-	}-	-	private void set_kerning (int handle, double val) {-		string a, b;-		Font font;-		int wi = 0;-		double kern;-		-		font = BirdFont.get_current_font ();--		font.touch ();--		a = "";-		b = "";--		foreach (Word word in row) {-			foreach (string s in word.glyph) {-				-				if (s == "") {-					continue;-				}-				-				b = s;-				-				if (handle == wi) {-					kern = font.get_kerning_by_name (a, b) + val;-					font.set_kerning_by_name (a, b, kern);-				}-				-				wi++;-				-				a = b;-			}-		}-		-		-	}-	-	private double get_kerning (string a, string b) {-		Font font = BirdFont.get_current_font ();-		return font.get_kerning_by_name (a, b);-	}-	-	public override void selected_canvas () {-		Glyph g;-		Word w;-		unowned List<Word>? r;-		unowned List<string>? rw;-		StringBuilder s = new StringBuilder ();-		bool append_char = false;-		-		KeyBindings.singleton.set_require_modifier (true);-		-		g = MainWindow.get_current_glyph ();-		s.append_unichar (g.get_unichar ());--		r = row;-		return_if_fail (r != null);--		if (row.length () == 0) {-			append_char = true;-		}-		-		if (row.length () > 0) {-			rw = row.first ().data.glyph;-			return_if_fail (rw != null);-			append_char = (row.first ().data.glyph.data.index_of (s.str) == -1);-		}-		-		if (append_char) {-			w = new Word ();-			row.append (w);-			w.glyph.prepend (s.str);-		}					-	}-	-	public override void key_press (uint keyval) {-		unichar c = (unichar) keyval;-		Font f = BirdFont.get_current_font ();-		string name;-		-		if (KeyBindings.modifier == NONE || KeyBindings.modifier == SHIFT) {-					-			if (keyval == Key.BACK_SPACE && row.length () > 0) {	-				row.first ().data.glyph.remove_link (row.first ().data.glyph.last ());-			}-			-			if (row.length () == 0 || c == Key.ENTER) {-				row.prepend (new Word ());-			}-			-			if (!is_modifier_key (c) && c.validate ()) {-				name = f.get_name_for_character (c);-				row.first ().data.glyph.append (name);-			}-		}-		-		MainWindow.get_glyph_canvas ().redraw ();-	}-	-	public override void motion_notify (double ex, double ey) {-		double k, y;-		-		if (selected_handle == -1) {-			set_active_handle (ex, ey);-		} else {-			y = 1;-			-			if (Math.fabs (ey - begin_handle_y) > 20) {-				y = ((Math.fabs (ey - begin_handle_y) / 100) + 1);-			}-			-			k = (ex - last_handle_x) / y; // y-axis is variable precision-			set_kerning (selected_handle, k);-			MainWindow.get_glyph_canvas ().redraw ();-		}-		-		last_handle_x = ex;-	}-	-	public void set_active_handle (double ex, double ey) {-		double y = 100;-		double x = 20;-		double w = 0;-		double d, kern;-		double min = double.MAX;-		int i = 0;-		int row_index = 0;-		int col_index = 0;-		Glyph? g;-		Glyph glyph = new Glyph.no_lines ("");-		-		string prev = "";-		string gl_name = "";-		-		foreach (Word word in row) {-			col_index = 0;-			foreach (string s in word.glyph) {-				-				// draw glyph-				g = (!) BirdFont.get_current_font ().get_glyph_by_name (s);	-				kern = (prev != "") ? get_kerning (prev, s) : 0;-				-				if (g == null) {-					w = 50;	-				} else {-					glyph = (!) g;-					w = glyph.get_width ();-					-				}-				-				d = Math.pow (x + kern - ex, 2) + Math.pow (y - ey, 2);-				-				if (d < min) {-					min = d;-					gl_name = glyph.get_name ();-					-					if (active_handle != i - row_index) {-						active_handle = i - row_index;-						MainWindow.get_glyph_canvas ().redraw ();-					}--					if (col_index == word.glyph.length () || col_index == 0) {-						active_handle = -1;-					}-				}-				-				prev = s;-				x += w + kern;-				i++;-				col_index++;-			}-			-			row_index++;-			y += MainWindow.get_current_glyph ().get_height () + 20;-			x = 20;-		}-	}-	-	public override void button_release (int button, double ex, double ey) {-		set_active_handle (ex, ey);-		selected_handle = -1;-	}-	-	public override void button_press (uint button, double ex, double ey) {-		set_active_handle (ex, ey);-		selected_handle = active_handle;-		begin_handle_x = ex;-		begin_handle_y = ey;-		last_handle_x = ex;-	}--}--class Word {-	public List <string> glyph;-	-	public Word () {-		glyph = new List <string> ();-		glyph.append ("");-	}-}--}diff --git a/libbirdfont/Font.vala b/libbirdfont/Font.valaindex c52c06d..204b80e 100644--- a/libbirdfont/Font.vala+++ b/libbirdfont/Font.vala@@ -28,13 +28,13 @@ public enum FontFormat { public class Font : GLib.Object { 	 	/** Table with glyphs sorted by their unicode value. */-	GlyphTable glyph_cache = new GlyphTable ();+	GlyphTable glyph_unicode = new GlyphTable (); 	 	/** Table with glyphs sorted by their name. */ 	GlyphTable glyph_name = new GlyphTable (); -	/** Last unassigned index */-	int next_unindexed = 0;+	/** Ligatures */+	GlyphTable ligature = new GlyphTable (); 	 	public List <string> background_images = new List <string> (); 	public string background_scale = "1";@@ -174,7 +174,7 @@ public class Font : GLib.Object {  	public void print_all () { 		stdout.printf ("Unicode:\n");		-		glyph_cache.for_each((g) => {+		glyph_unicode.for_each((g) => { 			stdout.printf (@"$(g.get_unicode ())\n"); 		}); 		@@ -196,7 +196,7 @@ public class Font : GLib.Object { 		} 				 		ret = new Glyph ("nonmarkingreturn", '\r');-		ret.set_unassigned (false);+ 		ret.left_limit = 0; 		ret.right_limit = 0; 		ret.remove_empty_paths ();@@ -214,7 +214,7 @@ public class Font : GLib.Object { 		} 		 		n = new Glyph ("null", '\0');-		n.set_unassigned (false);+		 		n.left_limit = 0; 		n.right_limit = 0; 		n.remove_empty_paths ();@@ -236,7 +236,7 @@ public class Font : GLib.Object { 		} 				 		n = new Glyph ("space", ' ');-		n.set_unassigned (false);+ 		n.left_limit = 0; 		n.right_limit = 27; 		n.remove_empty_paths ();@@ -260,7 +260,6 @@ public class Font : GLib.Object { 		p = new Path (); 		i = new Path (); 		-		g.set_unassigned (true); 		g.left_limit = -33; 		g.right_limit = 33; 		@@ -306,10 +305,10 @@ public class Font : GLib.Object { 		} 		 		if (glyph_collection.get_unicode () != "") {-			glyph_name.insert (glyph_collection.get_name (), glyph_collection);			+			glyph_unicode.insert (glyph_collection.get_unicode (), glyph_collection); 		} 		-		glyph_cache.insert (glyph_collection.get_unicode (), glyph_collection);+		glyph_name.insert (glyph_collection.get_name (), glyph_collection);			 	} 	 	public string get_name_for_character (unichar c) {@@ -342,9 +341,9 @@ public class Font : GLib.Object { 	} 	 	public void delete_glyph (GlyphCollection glyph) {-		glyph_cache.remove (glyph.get_unicode ());+		glyph_unicode.remove (glyph.get_unicode ()); 		glyph_name.remove (glyph.get_name ());-		// FIXME: DELETE: glyph_cache.remove (glyph);+		// FIXME: DELETE: glyph_unicode.remove (glyph); 	} 	 	/** Obtain all versions and alterntes for this glyph. */@@ -368,7 +367,7 @@ public class Font : GLib.Object { 	/** Get glyph collection by unichar code. */ 	public GlyphCollection? get_cached_glyph_collection (string unichar_code) { 		GlyphCollection? gc = null;-		gc = glyph_cache.get (unichar_code);+		gc = glyph_unicode.get (unichar_code); 		return gc; 	} @@ -393,7 +392,7 @@ public class Font : GLib.Object { 		 	public Glyph? get_glyph (string name) { 		GlyphCollection? gc = null;-		gc = glyph_cache.get (name);+		gc = glyph_unicode.get (name); 		 		if (gc == null) { 			return null;@@ -422,6 +421,19 @@ public class Font : GLib.Object { 		background_images.append (file); 	} +	public string get_name_from_unicode (string unicode) {+		string v = "";+		Glyph? g = get_glyph (unicode);+		+		if (g != null) {+			v = ((!)g).get_name ();+		} else {+			warning (@"no name for \"$unicode\"");+		}+		+		return v;+	}+ 	/** Obtain kerning for pair with name a and b. 	 * @param a name of left glyph kerning pair 	 * @param b name of right glyph kerning pair@@ -619,7 +631,7 @@ public class Font : GLib.Object { 				os.put_string ("\n"); 			} 			-			glyph_cache.for_each ((gc) => {+			glyph_unicode.for_each ((gc) => { 				bool selected; 				 				if (is_null (gc)) {@@ -637,7 +649,7 @@ public class Font : GLib.Object { 				} 			}); 		-			glyph_cache.for_each ((gc) => {+			glyph_unicode.for_each ((gc) => { 				Glyph glyph; 				 				try {@@ -665,7 +677,7 @@ public class Font : GLib.Object { 				} 			}); -			glyph_cache.for_each ((gc) => {+			glyph_unicode.for_each ((gc) => { 				GlyphBackgroundImage bg; 				 				try {@@ -811,7 +823,7 @@ public class Font : GLib.Object { 				grid_width.remove_link (grid_width.first ()); 			} -			glyph_cache.remove_all ();+			glyph_unicode.remove_all (); 			glyph_name.remove_all (); 			 			if (path.has_suffix (".svg")) {@@ -904,27 +916,17 @@ public class Font : GLib.Object { 		 		if (gcl != null) { 			warning (@"glyph \"$(g.get_name ())\" does already exist");+			return; 		}-		-		if (g.is_unassigned ()) {-			gc = new GlyphCollection (g); 			-			if (g.name == "") {-				warning ("refusing to insert glyph without name");-				g.name = @"($(++next_unindexed))";-				return;+		gc = new GlyphCollection (g);+		add_glyph_collection (gc);++		if (g.is_ligature ()) {+			foreach (string s in g.substitution) {+				ligature.insert (s, gc); 			}-			-			add_glyph_collection ((!) gc);-		} else if (gcl == null) {-			gc = new GlyphCollection (g);-			add_glyph_collection ((!) gc);-		} else {-			stderr.printf (@"Glyph collection does already have an entry for $(g.get_name ()) char $((uint64) g.unichar_code).\n"); 		}-				-		// take xheight from appropriate lower case letter-		// xheight_position = estimate_xheight (); 	}  	public bool parse_otf_file (string path) throws GLib.Error {@@ -945,7 +947,7 @@ public class Font : GLib.Object { 		font_file = path; 		 		// empty cache and fill it with new glyphs from disk-		glyph_cache.remove_all ();+		glyph_unicode.remove_all (); 		glyph_name.remove_all ();  		while (background_images.length () > 0) {diff --git a/libbirdfont/Glyph.vala b/libbirdfont/Glyph.valaindex 8b689dc..27ef658 100644--- a/libbirdfont/Glyph.vala+++ b/libbirdfont/Glyph.vala@@ -75,7 +75,6 @@ public class Glyph : FontDisplay { 	bool xheight_lines_visible = false; 	bool margin_boundries_visible = false; 	-	bool unassigned = false; 	public unichar unichar_code = 0; 	 	List<Glyph> undo_list = new List<Glyph> ();@@ -85,6 +84,9 @@ public class Glyph : FontDisplay { 	string glyph_sequence = ""; 	bool open = true; 	+	bool ligature = false;+	public List<string> substitution = new List<string> ();+	 	public Glyph (string name, unichar unichar_code = 0) { 		this.name = name; 		this.unichar_code = unichar_code;@@ -103,6 +105,15 @@ public class Glyph : FontDisplay {  		path_list.append (new Path ()); 	}+	+	public void add_ligature_substitution (string glyph_sequence) {+		ligature = true;+		substitution.append (glyph_sequence);+	}+	+	public bool is_ligature () {+		return ligature;+	}  	public void select_all_paths () { 		clear_active_paths ();@@ -167,14 +178,6 @@ public class Glyph : FontDisplay { 		 		return 0; 	}-		-	public void set_unassigned (bool u) {-		unassigned = u;-	}-	-	public bool is_unassigned () {-		return unassigned;-	}  	public void boundries (out double x1, out double y1, out double x2, out double y2) { 		if (path_list.length () == 0) {@@ -1445,6 +1448,11 @@ public class Glyph : FontDisplay { 			g.background_image = ((!) background_image).copy (); 		} 		+		g.ligature = ligature;+		foreach (string s in substitution) {+			g.substitution.append (s);+		}+				 		return g; 	} diff --git a/libbirdfont/KerningDisplay.vala b/libbirdfont/KerningDisplay.valanew file mode 100644index 0000000..bfa4f78--- /dev/null+++ b/libbirdfont/KerningDisplay.vala@@ -0,0 +1,335 @@+/*+    Copyright (C) 2012 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 {++/** Kerning context. */+public class KerningDisplay : FontDisplay {++	List <Word> row;+	int active_handle = -1;+	int selected_handle = -1;+	+	double begin_handle_x = 0;+	double begin_handle_y = 0;+	+	double last_handle_x = 0;+	+	public KerningDisplay () {+		Word w = new Word ();+		row = new List <Word> ();+		row.append (w);+	}++	public override string get_name () {+		return "Kerning";+	}+	+	public override void draw (Allocation allocation, Context cr) {+		Glyph? g;+		Glyph glyph;+		double x, y, w, kern, alpha;+		double x2;+		int i, wi;+		string prev;+		+		i = 0;+		+		// bg color+		cr.save ();+		cr.set_source_rgba (1, 1, 1, 1);+		cr.rectangle (0, 0, allocation.width, allocation.height);+		cr.fill ();+		cr.restore ();+	+		alpha = 1;+		y = 100;+		x = 20;+		w = 0;+		prev = "";+		+		foreach (Word word in row) {+			wi = 0;+			+			foreach (string s in word.glyph) {				+				g = (!) BirdFont.get_current_font ().get_glyph_by_name (s);	+				+				if (s == "") {+					continue;+				}+				+				kern = (prev != "") ? get_kerning (prev, s) : 0;+				+				// draw glyph				+				if (g == null) {+					w = 50;+					alpha = 1;+				} else {+					alpha = 0;+					glyph = (!) g;+					Svg.draw_svg_path (cr, glyph.get_svg_data (), x + kern, y);+					w = glyph.get_width ();+				}++				// handle+				if (active_handle == i) {+					//x2 = x + kern;+					x2 = x + kern / 2.0;+					+					cr.save ();+					cr.set_source_rgba (153/255.0, 153/255.0, 173/255.0, 1);+					cr.move_to (x2 - 5, y + 20);+					cr.line_to (x2 + 0, y + 20 - 5);+					cr.line_to (x2 + 5, y + 20);+					cr.fill ();+					+					cr.set_font_size (10);+					cr.show_text (s);+					cr.restore ();+				}	+				+				x += w + kern;+	+				// caption+				if (g == null || ((!)g).is_empty ()) {+					cr.save ();+					cr.set_source_rgba (153/255.0, 153/255.0, 153/255.0, alpha);+					cr.move_to (x - w / 2.0 - 5, y + 20);+					cr.set_font_size (10);+					cr.show_text (s);+					cr.restore ();+				}+							+				prev = s;+				+				wi++;+				i++;+			}+			+			if (y > allocation.height && i > 10) {+				row.remove (word);+			}+						+			y += MainWindow.get_current_glyph ().get_height () + 20;+			x = 20;			+		}+	}+	+	private void set_kerning (int handle, double val) {+		string a, b;+		Font font;+		int wi = 0;+		double kern;+		+		font = BirdFont.get_current_font ();++		font.touch ();++		a = "";+		b = "";++		foreach (Word word in row) {+			foreach (string s in word.glyph) {+				+				if (s == "") {+					continue;+				}+				+				b = s;+				+				if (handle == wi) {+					kern = font.get_kerning_by_name (a, b) + val;+					font.set_kerning_by_name (a, b, kern);+				}+				+				wi++;+				+				a = b;+			}+		}+		+		+	}+	+	private double get_kerning (string a, string b) {+		Font font = BirdFont.get_current_font ();+		return font.get_kerning_by_name (a, b);+	}+	+	public override void selected_canvas () {+		Glyph g;+		Word w;+		unowned List<Word>? r;+		unowned List<string>? rw;+		StringBuilder s = new StringBuilder ();+		bool append_char = false;+		+		KeyBindings.singleton.set_require_modifier (true);+		+		g = MainWindow.get_current_glyph ();+		s.append_unichar (g.get_unichar ());++		r = row;+		return_if_fail (r != null);++		if (row.length () == 0) {+			append_char = true;+		}+		+		if (row.length () > 0) {+			rw = row.first ().data.glyph;+			return_if_fail (rw != null);+			append_char = (row.first ().data.glyph.data.index_of (s.str) == -1);+		}+		+		if (append_char) {+			w = new Word ();+			row.append (w);+			w.glyph.prepend (s.str);+		}					+	}+	+	public override void key_press (uint keyval) {+		unichar c = (unichar) keyval;+		Font f = BirdFont.get_current_font ();+		string name;+		+		if (KeyBindings.modifier == NONE || KeyBindings.modifier == SHIFT) {+					+			if (keyval == Key.BACK_SPACE && row.length () > 0) {	+				row.first ().data.glyph.remove_link (row.first ().data.glyph.last ());+			}+			+			if (row.length () == 0 || c == Key.ENTER) {+				row.prepend (new Word ());+			}+			+			if (!is_modifier_key (c) && c.validate ()) {+				name = f.get_name_for_character (c);+				row.first ().data.glyph.append (name);+			}+		}+		+		MainWindow.get_glyph_canvas ().redraw ();+	}+	+	public override void motion_notify (double ex, double ey) {+		double k, y;+		+		if (selected_handle == -1) {+			set_active_handle (ex, ey);+		} else {+			y = 1;+			+			if (Math.fabs (ey - begin_handle_y) > 20) {+				y = ((Math.fabs (ey - begin_handle_y) / 100) + 1);+			}+			+			k = (ex - last_handle_x) / y; // y-axis is variable precision+			set_kerning (selected_handle, k);+			MainWindow.get_glyph_canvas ().redraw ();+		}+		+		last_handle_x = ex;+	}+	+	public void set_active_handle (double ex, double ey) {+		double y = 100;+		double x = 20;+		double w = 0;+		double d, kern;+		double min = double.MAX;+		int i = 0;+		int row_index = 0;+		int col_index = 0;+		Glyph? g;+		Glyph glyph = new Glyph.no_lines ("");+		+		string prev = "";+		string gl_name = "";+		+		foreach (Word word in row) {+			col_index = 0;+			foreach (string s in word.glyph) {+				+				// draw glyph+				g = (!) BirdFont.get_current_font ().get_glyph_by_name (s);	+				kern = (prev != "") ? get_kerning (prev, s) : 0;+				+				if (g == null) {+					w = 50;	+				} else {+					glyph = (!) g;+					w = glyph.get_width ();+					+				}+				+				d = Math.pow (x + kern - ex, 2) + Math.pow (y - ey, 2);+				+				if (d < min) {+					min = d;+					gl_name = glyph.get_name ();+					+					if (active_handle != i - row_index) {+						active_handle = i - row_index;+						MainWindow.get_glyph_canvas ().redraw ();+					}++					if (col_index == word.glyph.length () || col_index == 0) {+						active_handle = -1;+					}+				}+				+				prev = s;+				x += w + kern;+				i++;+				col_index++;+			}+			+			row_index++;+			y += MainWindow.get_current_glyph ().get_height () + 20;+			x = 20;+		}+	}+	+	public override void button_release (int button, double ex, double ey) {+		set_active_handle (ex, ey);+		selected_handle = -1;+	}+	+	public override void button_press (uint button, double ex, double ey) {+		set_active_handle (ex, ey);+		selected_handle = active_handle;+		begin_handle_x = ex;+		begin_handle_y = ey;+		last_handle_x = ex;+	}++}++class Word {+	public List <string> glyph;+	+	public Word () {+		glyph = new List <string> ();+		glyph.append ("");+	}+}++}diff --git a/libbirdfont/MenuTab.vala b/libbirdfont/MenuTab.valaindex 952a34a..4ca50d1 100644--- a/libbirdfont/MenuTab.vala+++ b/libbirdfont/MenuTab.vala@@ -408,7 +408,7 @@ c.append (""" 	} 	 	public static void show_kerning_context () {-		MainWindow.get_tab_bar ().add_unique_tab (new ContextDisplay (), 85, false);+		MainWindow.get_tab_bar ().add_unique_tab (new KerningDisplay (), 85, false); 	} 	 	public static void preview () {diff --git a/libbirdfont/OpenFontFormatWriter.vala b/libbirdfont/OpenFontFormatWriter.valaindex c24ebc7..7d5448a 100644--- a/libbirdfont/OpenFontFormatWriter.vala+++ b/libbirdfont/OpenFontFormatWriter.vala@@ -759,11 +759,6 @@ class GlyfTable : Table { 		
 		while (gl != glyphs.first ()) {
 			g = (!) gl.data;
-			
-			if (!g.is_unassigned ()) {
-				break;
-			}
-			
 			gl = gl.prev;
 		}
 		
@@ -845,10 +840,6 @@ class GlyfTable : Table { 		
 		glyph.name = name;
 
-		if (character == 0) {
-			glyph.set_unassigned (true);
-		}
-		
 		if (character == 0 && name != "") {
 			stderr.printf (@"Got null character\n");
 			stderr.printf (@"gid: $index\n");
@@ -1560,11 +1551,7 @@ class GlyfTable : Table { 			
 			g.remove_empty_paths ();
 
-			if (!g.is_unassigned ()) {
-				glyphs.append (g);
-			} else {
-				unassigned_glyphs.append (g);
-			}
+			glyphs.append (g);
 		}
 		
 		foreach (Glyph ug in unassigned_glyphs) {
@@ -1809,9 +1796,7 @@ class CmapSubtableWindowsUnicode : CmapSubtable { 		uint32 first_assigned = 1;
 		
 		foreach (Glyph g in glyf_table.glyphs) {
-			if (!g.is_unassigned ()) {
-				glyph_range.add_single (g.unichar_code);
-			}
+			glyph_range.add_single (g.unichar_code);
 		}
 		
 		// glyph_range.print_all ();
diff --git a/libbirdfont/SvgFont.vala b/libbirdfont/SvgFont.valaindex bb3cc11..b627e4f 100644--- a/libbirdfont/SvgFont.vala+++ b/libbirdfont/SvgFont.vala@@ -78,6 +78,7 @@ class SvgFont : GLib.Object { 		StringBuilder sl, sr; 		string attr_name = ""; 		string attr_content;+		string ln, rn; 		 		for (Xml.Attr* prop = node->properties; prop != null; prop = prop->next) { 			attr_name = prop->name;@@ -107,22 +108,52 @@ class SvgFont : GLib.Object { 			} 		} 		+		// , is used as separator+		if (left == ",") {+			left = "&#x2c;";+		}++		if (right == ",") {+			right = "&#x2c;";+		} 		-		// TODO: ranges and sequences for u1 & u2 + g1 & g2+		// TODO: ranges for u1 & u2 + g1 & g2+		+		// u1 + u2 or g2 		foreach (string lk in left.split (",")) {+			l = get_unichar (lk);+			sl = new StringBuilder ();+			sl.append_unichar (l);+			ln = font.get_name_from_unicode (sl.str);+					 			foreach (string rk in right.split (",")) {-				l = get_unichar (lk); 				r = get_unichar (rk);-				-				sl = new StringBuilder ();-				sl.append_unichar (l);-				 				sr = new StringBuilder (); 				sr.append_unichar (r);-				-				font.set_kerning (sl.str, sr.str, -kerning);				+				rn = font.get_name_from_unicode (sr.str);+				font.set_kerning_by_name (ln, rn, -kerning);+			}++			foreach (string rk in right_name.split (",")) {+				font.set_kerning_by_name (ln, rk, -kerning);+			}+		}++		// g1 + u2 or g2+		foreach (string lk in left_name.split (",")) {+			foreach (string rk in right.split (",")) {+				r = get_unichar (rk);+				sr = new StringBuilder ();+				sr.append_unichar (r);+				rn = font.get_name_from_unicode (sr.str);+				font.set_kerning_by_name (lk, rn, -kerning);+			}++			foreach (string rk in right_name.split (",")) {+				font.set_kerning_by_name (lk, rk, -kerning); 			} 		}+ 	}  	void parse_font_limits (Xml.Node* node) {@@ -176,14 +207,18 @@ class SvgFont : GLib.Object { 	/** Obtain unichar value from either a character, a hex representation of 	 *  a character or series of characters (f, &#x6d; or ffi). 	 */-	static unichar get_unichar (string val) {+	unichar get_unichar (string val) { 		string v = val; 		unichar unicode_value;-		+ 		if (val == "&") { 			return '&'; 		}-		++		if (val == ",") {+			return ',';+		}+ 		// TODO: parse ligatures 		if (v.has_prefix ("&")) { 			// parse hex value@@ -192,19 +227,27 @@ class SvgFont : GLib.Object { 			v = v.replace (";", ""); 			unicode_value = Font.to_unichar (v); 		} else {-			// obtain unicode value 			-			if (v.char_count () > 1) {-				warning ("font contains ligatures");+			// don't assign ligatures to any code point+			if (is_ligature (val)) { 				return '\0'; 			} 			+			// obtain unicode value 			unicode_value = v.get_char (0); 		} 		 		return unicode_value;	 	} 	+	bool is_ligature (string v) {+		if (v.has_prefix ("&")) {+			return false;+		}+		+		return v.char_count () > 1; +	}+	 	void parse_glyph (Xml.Node* node) { 		string attr_name = ""; 		string attr_content;@@ -213,6 +256,7 @@ class SvgFont : GLib.Object { 		string svg = ""; 		Glyph glyph; 		double advance = font_advance;+		string ligature = "";  		for (Xml.Attr* prop = node->properties; prop != null; prop = prop->next) { 			attr_name = prop->name;@@ -224,6 +268,10 @@ class SvgFont : GLib.Object { 				if (glyph_name == "") { 					glyph_name = attr_content; 				}+				+				if (is_ligature (attr_content)) {+					ligature = attr_content;+				} 			} 			 			// svg data@@ -240,15 +288,15 @@ class SvgFont : GLib.Object { 			} 		} 		-		// FIXME: this code will ignore characters that are mapped several glyphs-		if (unicode_value != '\0') {-			glyph = new Glyph (glyph_name, unicode_value);-			ImportSvg.parse_svg_data (svg, glyph, true, units);			-			glyph.right_limit = glyph.left_limit + advance * units;-			font.add_glyph_callback (glyph);-		} else {-			warning ("ignoring glyph");+		glyph = new Glyph (glyph_name, unicode_value);+		ImportSvg.parse_svg_data (svg, glyph, true, units);			+		glyph.right_limit = glyph.left_limit + advance * units;+		+		if (ligature != "") {+			glyph.add_ligature_substitution (ligature); 		}+		+		font.add_glyph_callback (glyph); 	} } 

Contact

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