Clone in a terminal:
Commit 9132e8e
Johan Mattsson - 2015-03-23T20:36:39+00:00
9132e8e6206365c55a77daf9b56838fad435f7cfjohan.mattsson.m@gmail.com

Contextual ligatures

Changed files (4)

Diff

diff --git a/libbirdfont/OpenFontFormat/ContextualLigature.vala b/libbirdfont/OpenFontFormat/ContextualLigature.valaindex 7baaf21..37d2387 100644--- a/libbirdfont/OpenFontFormat/ContextualLigature.vala+++ b/libbirdfont/OpenFontFormat/ContextualLigature.vala@@ -40,7 +40,7 @@ public class ContextualLigature : GLib.Object { 		return ligature_list; 	} 	-	public FontData get_data (GlyfTable glyf_table) {+	public FontData get_data (GlyfTable glyf_table, uint16 ligature_lookup_index) { 		FontData fd = new FontData (); 		 		Gee.ArrayList<string> backtrack = GsubTable.get_names (backtrack);@@ -74,7 +74,7 @@ public class ContextualLigature : GLib.Object { 		fd.add_ushort (1); // substitute count 		// substitution lookup records 		fd.add_ushort (0); // glyph sequence index for the character that will be substituted -		fd.add_ushort (1); // go to the ligature substitution via lookup table+		fd.add_ushort (ligature_lookup_index); // go to the ligature substitution via lookup table  		// backtrack coverage table1 		if (fd.length_with_padding () != backtrack_offset) {diff --git a/libbirdfont/OpenFontFormat/ContextualLigatureSet.vala b/libbirdfont/OpenFontFormat/ContextualLigatureSet.valaindex b7d0470..044c8d5 100644--- a/libbirdfont/OpenFontFormat/ContextualLigatureSet.vala+++ b/libbirdfont/OpenFontFormat/ContextualLigatureSet.vala@@ -18,24 +18,32 @@ namespace BirdFont { public class ContextualLigatureSet : GLib.Object {  	public Gee.ArrayList<ContextualLigature> ligature_context;-	public LigatureSetList ligatures;+	public Gee.ArrayList<LigatureSetList> ligatures; 	 	public ContextualLigatureSet (GlyfTable glyf_table) { 		ligature_context = new Gee.ArrayList<ContextualLigature> ();	-		add_contextual_ligatures ();-		ligatures = new LigatureSetList.contextual (glyf_table, this);+		ligatures = new Gee.ArrayList<LigatureSetList> ();+		add_contextual_ligatures (glyf_table);+	}+	+	public int16 get_size () {+		if (ligatures.size != ligature_context.size) {+			warning ("Expecting one substitution table per contextual ligature");+		}+		+		return (int16) ligature_context.size; 	} 	 	public bool has_ligatures () { 		return ligature_context.size > 0; 	} 	-	void add_contextual_ligatures () {+	void add_contextual_ligatures (GlyfTable glyf_table) { 		Font font = BirdFont.get_current_font ();-		Ligatures ligatures = font.ligature_substitution; 		-		foreach (ContextualLigature c in ligatures.contextual_ligatures) {+		foreach (ContextualLigature c in font.ligature_substitution.contextual_ligatures) { 			ligature_context.add (c);+			ligatures.add (new LigatureSetList.contextual (glyf_table, c)); 		} 	} }diff --git a/libbirdfont/OpenFontFormat/GsubTable.vala b/libbirdfont/OpenFontFormat/GsubTable.valaindex 852364a..0297bd9 100644--- a/libbirdfont/OpenFontFormat/GsubTable.vala+++ b/libbirdfont/OpenFontFormat/GsubTable.vala@@ -1,5 +1,5 @@ /*-    Copyright (C) 2012, 2013, 2014 Johan Mattsson+    Copyright (C) 2012 2013 2014 2015 Johan Mattsson      This library is free software; you can redistribute it and/or modify      it under the terms of the GNU Lesser General Public License as @@ -28,20 +28,22 @@ public class GsubTable : OtfTable { 	}  	public void process () throws GLib.Error {-		FontData fd = new FontData ();+		FontData fd; 		FontData clig_subtable;-		FontData chained_context;-		FontData chained_ligatures; 		uint16 length; 		 		LigatureSetList clig; 		ContextualLigatureSet contextual;  		uint16 feature_lookups;+		uint16 lookups_end;+		+		Gee.ArrayList<FontData> chain_data; 		+		fd = new FontData (); 		clig = new LigatureSetList.clig (glyf_table); 		contextual = new ContextualLigatureSet (glyf_table);-				+		 		fd.add_ulong (0x00010000); // table version 		fd.add_ushort (10); // offset to script list 		fd.add_ushort (30); // offset to feature list@@ -78,33 +80,51 @@ public class GsubTable : OtfTable { 		fd.add_ushort (feature_lookups); // number of lookups 		 		if (contextual.has_ligatures ()) {-			fd.add_ushort (2); // lookup chained_context (etc.) The chained context tables are listed here but the actual ligature table is only referenced in the context table+			fd.add_ushort (1 + contextual.get_size ()); // lookup chained_context (etc.) The chained context tables are listed here but the actual ligature table is only referenced in the context table 			fd.add_ushort (0); // lookup clig_subtable 		} else { 			fd.add_ushort (0); // lookup clig_subtable 		} 		-		clig_subtable = get_ligature_subtable (clig);-		chained_ligatures = get_ligature_subtable (contextual.ligatures);-		chained_context = get_chaining_contextual_substition_subtable (contextual);+		clig_subtable = clig.get_data (glyf_table);+		chain_data = get_chaining_contextual_substition_subtable (contextual); 		 		// lookup table-		uint16 lookups = contextual.has_ligatures () ? 3 : 1;+		uint16 lookups;+		+		if (contextual.has_ligatures ()) {+			lookups = 2 + (uint16) contextual.get_size ();+		} else {+			lookups = 1;+		}+		 		fd.add_ushort (lookups); // number of lookups 		 		if (contextual.has_ligatures ()) {-			fd.add_ushort (8); // offset to lookup 1 -			fd.add_ushort (16); // offset to lookup 2-			fd.add_ushort (24); // offset to lookup 3+			uint16 offset_to_lookup;++			offset_to_lookup = 6 + 2 * contextual.get_size ();+			fd.add_ushort (offset_to_lookup); // offset to lookup 1, regular ligatures+			+			for (int i = 0; i < contextual.get_size (); i++) {+				offset_to_lookup += 8;+				// offset to ligature lookups used in chaining substitution+				fd.add_ushort (offset_to_lookup);+			}++			// offset to lookup for the chain table+			offset_to_lookup += 8;+			fd.add_ushort (offset_to_lookup);  		} else { 			fd.add_ushort (4); // offset to lookup 1  		} 		-		uint16 lookups_end;+		lookups_end = 8; // regular ligatures 		-		lookups_end = lookups * 8; 		if (contextual.has_ligatures ()) {-			lookups_end += 2 * ((uint16) contextual.ligature_context.size - 1);+			lookups_end += 8 * contextual.get_size (); // contextual ligatures+			lookups_end += 6; // chaining table+			lookups_end += 2 * (uint16) contextual.get_size (); // chaining subtables 		} 		 		length = 0;@@ -115,35 +135,46 @@ public class GsubTable : OtfTable { 		length += (uint16) clig_subtable.length_with_padding (); 		lookups_end -= 8; 		-		if (contextual.has_ligatures ()) {-			fd.add_ushort (4); // lookup type -			fd.add_ushort (0); // lookup flags-			fd.add_ushort (1); // number of subtables-			fd.add_ushort (lookups_end + length); // array of offsets to subtable-			length += (uint16) chained_ligatures.length_with_padding ();-			lookups_end -= 8;+		if (contextual.has_ligatures ()) {			+			+			for (int i = 0; i < contextual.ligatures.size; i++) {+				fd.add_ushort (4); // lookup type +				fd.add_ushort (0); // lookup flags+				fd.add_ushort (1); // number of subtables++				LigatureSetList ligature_set = contextual.ligatures.get (i);+				fd.add_ushort (lookups_end + length); // array of offsets to subtable+				length += (uint16) ligature_set.get_data (glyf_table).length_with_padding ();+				+				lookups_end -= 8;+			}  			fd.add_ushort (6); // lookup type  			fd.add_ushort (0); // lookup flags-			fd.add_ushort ((uint16) contextual.ligature_context.size); // number of subtables FIXME: 1?+			fd.add_ushort (contextual.get_size ()); // number of subtables 			-			foreach (ContextualLigature c in contextual.ligature_context) {+			foreach (FontData d in chain_data) { 				fd.add_ushort (lookups_end + length); // array of offsets to subtable-				length += (uint16) c.get_data (glyf_table).length_with_padding ();+				length += (uint16) d.length_with_padding (); 			} 			-			lookups_end -= 7 + 2 * contextual.ligature_context.size;+			lookups_end -= 6 + 2 * chain_data.size; 		} 		-		if (lookups_end == 0) {-			warning ("Wring offset to end of lookups.");+		if (lookups_end != 0) {+			warning (@"Wrong offset to end of lookups, $lookups_end bytes left."); 		} 		 		fd.append (clig_subtable); 		 		if (contextual.has_ligatures ()) {-			fd.append (chained_ligatures);-			fd.append (chained_context);+			foreach (LigatureSetList s in contextual.ligatures) {+				fd.append (s.get_data (glyf_table));+			}++			foreach (FontData d in chain_data) {+				fd.append (d);+			} 		} 		 		fd.pad ();@@ -151,57 +182,17 @@ public class GsubTable : OtfTable { 		this.font_data = fd; 	} -	FontData get_ligature_subtable (LigatureSetList liga_list) throws GLib.Error {-		FontData set_data;-		Gee.ArrayList<LigatureSet> ligature_sets;-		uint16 ligature_pos;-		uint16 table_start;-		FontData fd;-		-		ligature_sets = liga_list.ligature_sets;-		fd = new FontData ();--		// ligature substitution subtable-		table_start = (uint16) fd.length_with_padding ();--		fd.add_ushort (1); // format identifier-		fd.add_ushort (6 + (uint16) 2 * ligature_sets.size); // offset to coverage-		fd.add_ushort ((uint16) ligature_sets.size); // number of ligature set tables--		// array of offsets to ligature sets-		uint16 size = 0;-		foreach (LigatureSet l in ligature_sets) {-			ligature_pos = 10 + (uint16) ligature_sets.size * 4 + size;-			fd.add_ushort (ligature_pos);-			size += (uint16) l.get_set_data ().length_with_padding ();-		}--		// coverage-		fd.add_ushort (1); // format-		fd.add_ushort ((uint16) ligature_sets.size);--		// coverage gid:-		foreach (LigatureSet l in ligature_sets) {-			fd.add_ushort ((uint16) glyf_table.get_gid (l.get_coverage_char ()));-		}-		-		foreach (LigatureSet l in ligature_sets) {-			set_data = l.get_set_data ();-			fd.append (set_data);-		}-		-		return fd;-	}- 	// chaining contextual substitution format3-	FontData get_chaining_contextual_substition_subtable (ContextualLigatureSet contexts) throws GLib.Error {-		FontData fd_all = new FontData ();+	Gee.ArrayList<FontData> get_chaining_contextual_substition_subtable (ContextualLigatureSet contexts) throws GLib.Error {+		Gee.ArrayList<FontData> fd = new Gee.ArrayList<FontData> ();+		uint16 ligature_lookup_index = 1; 		 		foreach (ContextualLigature context in contexts.ligature_context) {-			fd_all.append (context.get_data (glyf_table)); // FIXME: remove..+			fd.add (context.get_data (glyf_table, ligature_lookup_index)); +			ligature_lookup_index++; 		} 		-		return fd_all;+		return fd; 	} 	 	void parse_ligatures (FontData fd, int table_start) {@@ -258,7 +249,7 @@ public class GsubTable : OtfTable { 	public static Gee.ArrayList<string> get_names (string glyphs) { 		Gee.ArrayList<string> names = new Gee.ArrayList<string> (); 		Font font = BirdFont.get_current_font ();-		string[] parts = glyphs.split (" ");+		string[] parts = glyphs.strip ().split (" "); 								 		foreach (string p in parts) {		 			if (p.has_prefix ("U+") || p.has_prefix ("u+")) {@@ -267,10 +258,12 @@ public class GsubTable : OtfTable { 			 			if (!font.has_glyph (p)) { 				warning (@"The character $p does have a glyph.");-				return new Gee.ArrayList<string> ();+				p = ".notdef"; 			} 			-			names.add (p);+			if (p != "") {+				names.add (p);+			} 		} 		 		return names;diff --git a/libbirdfont/OpenFontFormat/LigatureSetList.vala b/libbirdfont/OpenFontFormat/LigatureSetList.valaindex 285a4ce..9900232 100644--- a/libbirdfont/OpenFontFormat/LigatureSetList.vala+++ b/libbirdfont/OpenFontFormat/LigatureSetList.vala@@ -30,12 +30,12 @@ public class LigatureSetList : GLib.Object { 		add_clig_ligatures (glyf_table); 	} -	public LigatureSetList.contextual (GlyfTable glyf_table, ContextualLigatureSet ligatures) {+	public LigatureSetList.contextual (GlyfTable glyf_table, ContextualLigature ligature) { 		ligature_sets = new Gee.ArrayList<LigatureSet> ();	 		lig_set = new LigatureSet (glyf_table); 		last_set = new LigatureSet (glyf_table); -		add_contextual_ligatures (glyf_table, ligatures);+		add_contextual_ligatures (glyf_table, ligature); 	}  	void add_clig_ligatures (GlyfTable glyf_table) {@@ -47,11 +47,9 @@ public class LigatureSetList : GLib.Object { 		});	 	} -	void add_contextual_ligatures (GlyfTable glyf_table, ContextualLigatureSet ligatures) {-		foreach (ContextualLigature c in ligatures.ligature_context) {-			foreach (string l in c.ligatures.strip ().split (" ")) {-				add_ligatures (glyf_table, "r", l); // FIXME: parts = ""-			}+	void add_contextual_ligatures (GlyfTable glyf_table, ContextualLigature cl) {+		foreach (string l in cl.ligatures.strip ().split (" ")) {+			add_ligatures (glyf_table, cl.input, l); // FIXME: DELETE parts = "r" ?  		} 	} @@ -61,7 +59,7 @@ public class LigatureSetList : GLib.Object { 		requires (!is_null (lig_set) && !is_null (last_set)) { 			 		Font font = BirdFont.get_current_font ();-		string[] parts = characters.split (" ");+		string[] parts = characters.strip ().split (" "); 		string l = ligatures;  		if (l.has_prefix ("U+") || l.has_prefix ("u+")) {@@ -98,6 +96,46 @@ public class LigatureSetList : GLib.Object { 			last_set = lig_set; 		}		 	}++	public FontData get_data (GlyfTable glyf_table) throws GLib.Error {+		FontData set_data;+		uint16 ligature_pos;+		uint16 table_start;+		FontData fd;+		+		fd = new FontData ();++		// ligature substitution subtable+		table_start = (uint16) fd.length_with_padding ();++		fd.add_ushort (1); // format identifier+		fd.add_ushort (6 + (uint16) 2 * ligature_sets.size); // offset to coverage+		fd.add_ushort ((uint16) ligature_sets.size); // number of ligature set tables++		// array of offsets to ligature sets+		uint16 size = 0;+		foreach (LigatureSet l in ligature_sets) {+			ligature_pos = 10 + (uint16) ligature_sets.size * 4 + size;+			fd.add_ushort (ligature_pos);+			size += (uint16) l.get_set_data ().length_with_padding ();+		}++		// coverage+		fd.add_ushort (1); // format+		fd.add_ushort ((uint16) ligature_sets.size);++		// coverage gid:+		foreach (LigatureSet l in ligature_sets) {+			fd.add_ushort ((uint16) glyf_table.get_gid (l.get_coverage_char ()));+		}+		+		foreach (LigatureSet l in ligature_sets) {+			set_data = l.get_set_data ();+			fd.append (set_data);+		}+		+		return fd;+	} }  }

Contact

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