Commit 4a3e1ac
Enable contextual ligatures
Changed files (6)
modifiedlibbirdfont/LigatureList.valaaddedlibbirdfont/OpenFontFormat/ContextualLigatureCollection.valadeletedlibbirdfont/OpenFontFormat/ContextualLigatureSet.valamodifiedlibbirdfont/OpenFontFormat/GsubTable.valaaddedlibbirdfont/OpenFontFormat/LigatureCollection.valadeletedlibbirdfont/OpenFontFormat/LigatureSetList.vala
Diff
@@ -99,13 +99,9 @@ public class LigatureList : Table { Row row; rows.clear ();- if (BirdFont.has_argument ("--test")) {- row = new Row.columns_2 (t_("New Ligature"), t_("New Contextual Substitution"), NEW_LIGATURE, false);- rows.add (row);- } else {- row = new Row.columns_1 (t_("New Ligature"), NEW_LIGATURE, false);- rows.add (row);- }++ row = new Row.columns_2 (t_("New Ligature"), t_("New Contextual Substitution"), NEW_LIGATURE, false);+ rows.add (row); i = 0; ligatures.get_ligatures ((subst, liga) => {new file mode 100644@@ -0,0 +1,51 @@+/*+ Copyright (C) 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 + 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 ContextualLigatureCollection : GLib.Object {++ public Gee.ArrayList<ContextualLigature> ligature_context;+ public Gee.ArrayList<LigatureCollection> ligatures;+ + public ContextualLigatureCollection (GlyfTable glyf_table) {+ ligature_context = new Gee.ArrayList<ContextualLigature> (); + ligatures = new Gee.ArrayList<LigatureCollection> ();+ 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 (GlyfTable glyf_table) {+ Font font = BirdFont.get_current_font ();+ + foreach (ContextualLigature c in font.ligature_substitution.contextual_ligatures) {+ ligature_context.add (c);+ ligatures.add (new LigatureCollection.contextual (glyf_table, c));+ }+ }+}++}deleted file mode 100644@@ -1,51 +0,0 @@-/*- Copyright (C) 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 - 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 ContextualLigatureSet : GLib.Object {-- public Gee.ArrayList<ContextualLigature> ligature_context;- public Gee.ArrayList<LigatureSetList> ligatures;- - public ContextualLigatureSet (GlyfTable glyf_table) {- ligature_context = new Gee.ArrayList<ContextualLigature> (); - 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 (GlyfTable glyf_table) {- Font font = BirdFont.get_current_font ();- - foreach (ContextualLigature c in font.ligature_substitution.contextual_ligatures) {- ligature_context.add (c);- ligatures.add (new LigatureSetList.contextual (glyf_table, c));- }- }-}--}@@ -32,8 +32,8 @@ public class GsubTable : OtfTable { FontData clig_subtable; uint16 length; - LigatureSetList clig;- ContextualLigatureSet contextual;+ LigatureCollection clig;+ ContextualLigatureCollection contextual; uint16 feature_lookups; uint16 lookups_end;@@ -41,8 +41,8 @@ public class GsubTable : OtfTable { Gee.ArrayList<FontData> chain_data; fd = new FontData ();- clig = new LigatureSetList.clig (glyf_table);- contextual = new ContextualLigatureSet (glyf_table);+ clig = new LigatureCollection.clig (glyf_table);+ contextual = new ContextualLigatureCollection (glyf_table); fd.add_ulong (0x00010000); // table version fd.add_ushort (10); // offset to script list@@ -71,8 +71,8 @@ public class GsubTable : OtfTable { fd.add_ushort (8); // offset to feature // FIXME: Should it be liga and clig? - clig = new LigatureSetList.clig (glyf_table);- contextual = new ContextualLigatureSet (glyf_table);+ clig = new LigatureCollection.clig (glyf_table);+ contextual = new ContextualLigatureCollection (glyf_table); feature_lookups = contextual.has_ligatures () ? 2 : 1; @@ -142,7 +142,7 @@ public class GsubTable : OtfTable { fd.add_ushort (0); // lookup flags fd.add_ushort (1); // number of subtables - LigatureSetList ligature_set = contextual.ligatures.get (i);+ LigatureCollection 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 (); @@ -168,7 +168,7 @@ public class GsubTable : OtfTable { fd.append (clig_subtable); if (contextual.has_ligatures ()) {- foreach (LigatureSetList s in contextual.ligatures) {+ foreach (LigatureCollection s in contextual.ligatures) { fd.append (s.get_data (glyf_table)); } @@ -183,7 +183,7 @@ public class GsubTable : OtfTable { } // chaining contextual substitution format3- Gee.ArrayList<FontData> get_chaining_contextual_substition_subtable (ContextualLigatureSet contexts) throws GLib.Error {+ Gee.ArrayList<FontData> get_chaining_contextual_substition_subtable (ContextualLigatureCollection contexts) throws GLib.Error { Gee.ArrayList<FontData> fd = new Gee.ArrayList<FontData> (); uint16 ligature_lookup_index = 1; new file mode 100644@@ -0,0 +1,141 @@+/*+ 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.+*/+using Math;++namespace BirdFont {++public class LigatureCollection : GLib.Object {++ public Gee.ArrayList<LigatureSet> ligature_sets;++ LigatureSet lig_set;+ LigatureSet last_set;++ public LigatureCollection.clig (GlyfTable glyf_table) {+ ligature_sets = new Gee.ArrayList<LigatureSet> (); + lig_set = new LigatureSet (glyf_table);+ last_set = new LigatureSet (glyf_table);+ + add_clig_ligatures (glyf_table);+ }++ public LigatureCollection.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, ligature);+ }++ void add_clig_ligatures (GlyfTable glyf_table) {+ Font font = BirdFont.get_current_font ();+ Ligatures ligatures = font.get_ligatures (); + + ligatures.get_ligatures ((parts, ligature) => {+ add_ligatures (glyf_table, parts, ligature);+ }); + }++ 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" ? + }+ }++ // multiple ligatures in non-contextual substitution+ // FIXME: what if parts equals "" ? Which set does ligatures becomes a part of?+ public void add_ligatures (GlyfTable glyf_table, string characters, string ligatures) + requires (!is_null (lig_set) && !is_null (last_set)) {+ + Font font = BirdFont.get_current_font ();+ string[] parts = characters.strip ().split (" ");+ string l = ligatures;++ if (l.has_prefix ("U+") || l.has_prefix ("u+")) {+ l = (!) Font.to_unichar (l).to_string ();+ }+ + if (!font.has_glyph (l)) {+ warning (@"Ligature $l does not correspond to a glyph in this font.");+ return;+ }+ + foreach (string p in parts) { + if (p.has_prefix ("U+") || p.has_prefix ("u+")) {+ p = (!) Font.to_unichar (p).to_string ();+ }+ + 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, characters));+ } else {+ lig_set = new LigatureSet (glyf_table);+ lig_set.add (new Ligature (l, characters));+ ligature_sets.add (lig_set);+ 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;+ }+}++}deleted file mode 100644@@ -1,141 +0,0 @@-/*- 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.-*/-using Math;--namespace BirdFont {--public class LigatureSetList : GLib.Object {-- public Gee.ArrayList<LigatureSet> ligature_sets;-- LigatureSet lig_set;- LigatureSet last_set;-- public LigatureSetList.clig (GlyfTable glyf_table) {- ligature_sets = new Gee.ArrayList<LigatureSet> (); - lig_set = new LigatureSet (glyf_table);- last_set = new LigatureSet (glyf_table);- - add_clig_ligatures (glyf_table);- }-- 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, ligature);- }-- void add_clig_ligatures (GlyfTable glyf_table) {- Font font = BirdFont.get_current_font ();- Ligatures ligatures = font.get_ligatures (); - - ligatures.get_ligatures ((parts, ligature) => {- add_ligatures (glyf_table, parts, ligature);- }); - }-- 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" ? - }- }-- // multiple ligatures in non-contextual substitution- // FIXME: what if parts equals "" ? Which set does ligatures becomes a part of?- public void add_ligatures (GlyfTable glyf_table, string characters, string ligatures) - requires (!is_null (lig_set) && !is_null (last_set)) {- - Font font = BirdFont.get_current_font ();- string[] parts = characters.strip ().split (" ");- string l = ligatures;-- if (l.has_prefix ("U+") || l.has_prefix ("u+")) {- l = (!) Font.to_unichar (l).to_string ();- }- - if (!font.has_glyph (l)) {- warning (@"Ligature $l does not correspond to a glyph in this font.");- return;- }- - foreach (string p in parts) { - if (p.has_prefix ("U+") || p.has_prefix ("u+")) {- p = (!) Font.to_unichar (p).to_string ();- }- - 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, characters));- } else {- lig_set = new LigatureSet (glyf_table);- lig_set.add (new Ligature (l, characters));- ligature_sets.add (lig_set);- 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;- }-}--}