Clone in a terminal:
Commit 5266176
Johan Mattsson - 2014-10-03T16:44:00+00:00
5266176197d77d85a4f80af0816ab0fe92e621d2johan.mattsson.m@gmail.com

Write and parse ligature subsitutions in GPOS table

Changed files (7)

Diff

diff --git a/libbirdfont/GlyphRange.vala b/libbirdfont/GlyphRange.valaindex 2ad900e..42bacad 100644--- a/libbirdfont/GlyphRange.vala+++ b/libbirdfont/GlyphRange.vala@@ -32,7 +32,6 @@ public class GlyphRange { 	 	public void add_unassigned (string glyph_name) { 		unassigned.add (glyph_name);-		len++; 	} 	 	public bool is_class () {diff --git a/libbirdfont/Ligatures.vala b/libbirdfont/Ligatures.valaindex 34f08dd..81e2713 100644--- a/libbirdfont/Ligatures.vala+++ b/libbirdfont/Ligatures.vala@@ -24,9 +24,12 @@ public class Ligatures : GLib.Object {  	public Ligatures () { 	}-+	+	// FIXME: keep ligatures sorted, long strings first 	public void get_ligatures (LigatureIterator iter) {-		iter ("f i", "fi");+		iter ("a f", "af");+		iter ("f f i", "ffi");+		iter ("f i", "fi");		 	}  	public void get_single_substitution_ligatures (SingleLigatureIterator iter) {diff --git a/libbirdfont/OpenFontFormat/FontData.vala b/libbirdfont/OpenFontFormat/FontData.valaindex 98aae72..bb93f5a 100644--- a/libbirdfont/OpenFontFormat/FontData.vala+++ b/libbirdfont/OpenFontFormat/FontData.vala@@ -21,8 +21,7 @@ public class FontData : Object {  	// Write pointer 	uint wp = 0;-	-	// length without padding+ 	uint32 len = 0; 	uint32 padding = 0; 	@@ -42,6 +41,10 @@ public class FontData : Object { 		} 	} 	+	public int get_read_pos () {+		return (int) rp;+	}+	 	public void write_at (uint pos, uint8 new_data) throws GLib.Error 		requires (pos <= capacity)  	{		diff --git a/libbirdfont/OpenFontFormat/Gsub.vala b/libbirdfont/OpenFontFormat/Gsub.valadeleted file mode 100644index c75ff1b..0000000--- a/libbirdfont/OpenFontFormat/Gsub.vala+++ /dev/null@@ -1,108 +0,0 @@-/*-    Copyright (C) 2012, 2013, 2014 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 -    published by the Free Software Foundation; either version 3 of the -    License, or (at your option) any later version.--    This library 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 -    Lesser General Public License for more details.-*/-using Math;--namespace BirdFont {--public class GsubTable : Table {-	-	GlyfTable glyf_table;-	-	public GsubTable (GlyfTable glyf_table) {-		this.glyf_table = glyf_table;-		id = "GSUB";-	}-	-	public override void parse (FontData dis) throws Error {-	}--	public void process () throws GLib.Error {-		FontData fd = new FontData ();--		fd.add_ulong (0x00010000); // table version-		fd.add_ushort (10); // offset to script list-		fd.add_ushort (30); // offset to feature list-		fd.add_ushort (44); // offset to lookup list-		-		// script list-		fd.add_ushort (1);   // number of items in script list-		fd.add_tag ("DFLT"); // default script-		fd.add_ushort (8); // offset to script table from script list-		-		// script table-		fd.add_ushort (4); // offset to default language system-		fd.add_ushort (0); // number of languages-		-		// LangSys table -		fd.add_ushort (0); // reserved-		fd.add_ushort (0); // required features (0xFFFF is none)-		fd.add_ushort (1); // number of features-		fd.add_ushort (0); // feature index-		-		// feature table-		fd.add_ushort (1); // number of features-		-		fd.add_tag ("clig"); // feature tag-		fd.add_ushort (8); // offset to feature-		-		fd.add_ushort (0); // feature prameters (null)-		fd.add_ushort (1); // number of lookups-		fd.add_ushort (0); // lookup indice-		-		// lookup table-		fd.add_ushort (1); // number of lookups-		fd.add_ushort (4); // offset to lookup 1--		fd.add_ushort (4); // lookup type // FIXME	-		fd.add_ushort (0); // lookup flags-		fd.add_ushort (1); // number of subtables-		fd.add_ushort (8); // array of offsets to subtable-		-		// ligature substitution subtable-		fd.add_ushort (1); // format identifier-		fd.add_ushort (8); // offset to coverage-		fd.add_ushort (1); // number of ligature set tables-		fd.add_ushort (18); // array of offsets to ligature sets-		-		// coverage-		fd.add_ushort (2); // format-		fd.add_ushort (1); // num ranges-		fd.add_ushort ((uint16) glyf_table.get_gid ("f")); // start gid-		fd.add_ushort ((uint16) glyf_table.get_gid ("f")); // end gid-		fd.add_ushort (0); // coverage start index-		-		// ligature-		fd.add_ushort (3); // number of ligatures in this set-		fd.add_ushort (8); // offset to ligature-		fd.add_ushort (14); // offset to ligature-		fd.add_ushort (20); // offset to ligature--		fd.add_ushort ((uint16) glyf_table.get_gid ("fi")); // DELETE);-		fd.add_ushort (2); // number of components-		fd.add_ushort ((uint16) glyf_table.get_gid ("i")); // gid to component --		fd.add_ushort ((uint16) glyf_table.get_gid ("fi")); // DELETE);-		fd.add_ushort (2); // number of components-		fd.add_ushort ((uint16) glyf_table.get_gid ("i")); // gid to component --		fd.add_ushort ((uint16) glyf_table.get_gid ("fi")); // DELETE);-		fd.add_ushort (2); // number of components-		fd.add_ushort ((uint16) glyf_table.get_gid ("i")); // gid to component -		-		fd.pad ();	-		this.font_data = fd;-	}-}--}diff --git a/libbirdfont/OpenFontFormat/GsubTable.vala b/libbirdfont/OpenFontFormat/GsubTable.valanew file mode 100644index 0000000..3a23bd9--- /dev/null+++ b/libbirdfont/OpenFontFormat/GsubTable.vala@@ -0,0 +1,197 @@+/*+    Copyright (C) 2012, 2013, 2014 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 +    published by the Free Software Foundation; either version 3 of the +    License, or (at your option) any later version.++    This library 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 +    Lesser General Public License for more details.+*/+using Math;++namespace BirdFont {++public class GsubTable : Table {+	+	GlyfTable glyf_table;+	+	public GsubTable (GlyfTable glyf_table) {+		this.glyf_table = glyf_table;+		id = "GSUB";+	}+	+	public override void parse (FontData dis) throws Error {+	}++	public void process () throws GLib.Error {+		FontData fd = new FontData ();+		Font font = BirdFont.get_current_font ();+		Ligatures ligatures = font.get_ligatures ();+		LigatureSet lig_set;+		LigatureSet last_set;+		FontData set_data;+		Gee.ArrayList<LigatureSet> liga_sets;+		uint16 ligature_pos;+		uint16 table_start;+		+		fd.add_ulong (0x00010000); // table version+		fd.add_ushort (10); // offset to script list+		fd.add_ushort (30); // offset to feature list+		fd.add_ushort (44); // offset to lookup list+		+		// script list+		fd.add_ushort (1);   // number of items in script list+		fd.add_tag ("DFLT"); // default script+		fd.add_ushort (8); // offset to script table from script list+		+		// script table+		fd.add_ushort (4); // offset to default language system+		fd.add_ushort (0); // number of languages+		+		// LangSys table +		fd.add_ushort (0); // reserved+		fd.add_ushort (0); // required features (0xFFFF is none)+		fd.add_ushort (1); // number of features+		fd.add_ushort (0); // feature index+		+		// feature table+		fd.add_ushort (1); // number of features+		+		fd.add_tag ("clig"); // feature tag+		fd.add_ushort (8); // offset to feature+		+		fd.add_ushort (0); // feature prameters (null)+		fd.add_ushort (1); // number of lookups+		fd.add_ushort (0); // lookup indice+		+		// lookup table+		fd.add_ushort (1); // number of lookups+		fd.add_ushort (4); // offset to lookup 1++		fd.add_ushort (4); // lookup type +		fd.add_ushort (0); // lookup flags+		fd.add_ushort (1); // number of subtables+		fd.add_ushort (8); // array of offsets to subtable++		// add existing ligatures+		liga_sets = new Gee.ArrayList<LigatureSet> ();+		lig_set = new LigatureSet (glyf_table);+		last_set = new LigatureSet (glyf_table);+		ligatures.get_ligatures ((s, l) => {+			string[] parts = s.split (" ");+			+			if (!font.has_glyph (l)) {+				warning (@"Ligature $l does not correspond to a glyph in this font.");+				return;+			}+			+			foreach (string p in parts) {+				if (!font.has_glyph (p)) {+					warning (@"Ligature substitution of $p is not possible, the character does have a glyph.");+					return;+				}+			}+			+			if (parts.length == 0) {+				warning ("No parts.");+				return;+			}+			+			if (last_set.starts_with (parts[0])) {+				last_set.add (new Ligature (l, s));+			} else {+				lig_set = new LigatureSet (glyf_table);+				lig_set.add (new Ligature (l, s));+				liga_sets.add (lig_set);+				last_set = lig_set;+			}+			+		});+				+		// ligature substitution subtable+		table_start = (uint16) fd.length_with_padding ();++		fd.add_ushort (1); // format identifier+		fd.add_ushort (6 + (uint16) 2 * liga_sets.size); // offset to coverage+		fd.add_ushort ((uint16) liga_sets.size); // number of ligature set tables++		// array of offsets to ligature sets+		uint16 size = 0;+		foreach (LigatureSet l in liga_sets) {+			ligature_pos = 10 + (uint16) liga_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) liga_sets.size);++		// coverage gid:+		foreach (LigatureSet l in liga_sets) {+			fd.add_ushort ((uint16) glyf_table.get_gid (l.get_coverage_char ()));+		}+		+		foreach (LigatureSet l in liga_sets) {+			set_data = l.get_set_data ();+			fd.append (set_data);+		}+		+		fd.pad ();+		+		this.font_data = fd;+	}++	void parse_ligatures (FontData fd, int table_start) {+		fd.seek (table_start);+		+		uint16 identifier = fd.read_ushort ();+		+		if (identifier != 1) {+			warning (@"Bad identifier expecting 1 found $identifier");+		}+		+		uint16 coverage_offset = fd.read_ushort ();+		uint16 num_sets = fd.read_ushort ();+		+		Gee.ArrayList<int> liga_set_offsets = new Gee.ArrayList<int> ();+		for (int i = 0; i < num_sets; i++) {+			uint16 liga_set_offset = fd.read_ushort ();+			liga_set_offsets.add (table_start + liga_set_offset);+		}+		+		foreach (int liga_set_pos in liga_set_offsets) {+			fd.seek (liga_set_pos);+			parse_ligature_set (fd);+		}		+	}+	+	/** Parse ligature set at the current position. */+	void parse_ligature_set (FontData fd) {+		int liga_start = fd.get_read_pos ();+		uint nliga = fd.read_ushort ();+		Gee.ArrayList<int> offsets = new Gee.ArrayList<int> ();+		+		for (uint i = 0; i < nliga; i++) {+			int off = fd.read_ushort ();+			offsets.add (off);+		}++		foreach (int off in offsets) {+			fd.seek (liga_start);+			fd.seek_relative (off);+			uint16 lig = fd.read_ushort ();+			uint16 nlig_comp = fd.read_ushort ();+			+			for (int i = 1; i < nlig_comp; i++) {+				uint16 lig_comp = fd.read_ushort ();+			} +		}+	}+}++}diff --git a/libbirdfont/OpenFontFormat/Ligature.vala b/libbirdfont/OpenFontFormat/Ligature.valanew file mode 100644index 0000000..8b0958d--- /dev/null+++ b/libbirdfont/OpenFontFormat/Ligature.vala@@ -0,0 +1,27 @@+/*+    Copyright (C) 2014 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 +    published by the Free Software Foundation; either version 3 of the +    License, or (at your option) any later version.++    This library 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 +    Lesser General Public License for more details.+*/++namespace BirdFont {++public class Ligature : GLib.Object {+	public string ligature = "";+	public string substitution = "";+	+	public Ligature (string ligature, string substitution) {+		this.ligature = ligature;+		this.substitution = substitution;+	}+}++}diff --git a/libbirdfont/OpenFontFormat/LigatureSet.vala b/libbirdfont/OpenFontFormat/LigatureSet.valanew file mode 100644index 0000000..1bc638c--- /dev/null+++ b/libbirdfont/OpenFontFormat/LigatureSet.vala@@ -0,0 +1,96 @@+/*+    Copyright (C) 2014 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 +    published by the Free Software Foundation; either version 3 of the +    License, or (at your option) any later version.++    This library 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 +    Lesser General Public License for more details.+*/++namespace BirdFont {++public class LigatureSet : GLib.Object {+	public Gee.ArrayList<Ligature> ligatures = new Gee.ArrayList<Ligature> ();+	GlyfTable glyf_table;+	+	public LigatureSet (GlyfTable gt) {+		glyf_table = gt;+	}+	+	public  void add (Ligature lig) {+		ligatures.add (lig);+	}+	+	public bool starts_with (string s) {+		if (ligatures.size == 0) {+			return false;+		}+		+		return ligatures.get (0).substitution.has_prefix (s);+	}+	+	public string get_coverage_char () {+		if (ligatures.size == 0) {+			warning ("No ligatures in set.");+			return "";+		}+		+		return (!) ligatures.get (0).substitution.get (0).to_string ();+	}+	+	public FontData get_set_data () {+		FontData fd, ligature_data;+		uint16 o, pos;+		+		fd = new FontData ();++		// number of ligatures in this set+		fd.add_ushort ((uint16) ligatures.size); +		+		ligature_data = new FontData ();+		foreach (Ligature l in ligatures) {+			// offset to ligatures+			o = 2 + 2 * ligatures.size;+			+			pos = (uint16) (o + ligature_data.length_with_padding ());+			+			fd.add_ushort (pos);+			add_ligature (ligature_data, l);+		}+		+		fd.append (ligature_data);+		+		return fd;+	}+	+	void add_ligature (FontData fd, Ligature ligature) throws GLib.Error {+		string[] parts = ligature.substitution.split (" ");+		bool first = true;+		int gid = glyf_table.get_gid (ligature.ligature);+		+		if (gid == -1) {+			warning (@"No glyph ID for ligature $(ligature.ligature).");+			gid = 0;+		}+		+		fd.add_ushort ((uint16) gid);+		+		// number of components including the coverage glyph+		fd.add_ushort ((uint16) parts.length); ++		foreach (string p in parts) {+			if (!first) {+				fd.add_ushort ((uint16) glyf_table.get_gid (p));+			}+			+			first = false;+		}+	}+}++}

Contact

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