Commit d641444
GUI for selecting OTF feature tags
Changed files (10)
addedlibbirdfont/AlternateSets.valamodifiedlibbirdfont/BirdFontFile.valamodifiedlibbirdfont/ExportTool.valamodifiedlibbirdfont/Font.valamodifiedlibbirdfont/OpenFontFormat/Alternate.valamodifiedlibbirdfont/OpenFontFormat/AlternateFeature.valamodifiedlibbirdfont/OpenFontFormat/GsubTable.valaaddedlibbirdfont/OtfFeatureTable.valamodifiedlibbirdfont/OverviewTools.valaaddedlibbirdfont/String.vala
Diff
new file mode 100644@@ -0,0 +1,56 @@+/*+ 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.+*/++namespace BirdFont {++public class AlternateSets : GLib.Object {+ + public Gee.ArrayList<Alternate> alternates;+ + public AlternateSets () {+ alternates = new Gee.ArrayList<Alternate> ();+ }+ + public Gee.ArrayList<string> get_all_tags () {+ Gee.ArrayList<string> tags;+ tags = new Gee.ArrayList<string> ();+ + foreach (Alternate a in alternates) {+ if (tags.index_of (a.tag) == -1) {+ tags.add (a.tag);+ }+ }+ + return tags;+ }++ public Gee.ArrayList<Alternate> get_alt (string tag) { + Gee.ArrayList<Alternate> alt;+ alt = new Gee.ArrayList<Alternate> ();+ + foreach (Alternate a in alternates) {+ if (a.tag == tag) {+ alt.add (a);+ }+ }+ + return alt;+ }+ + public void add (Alternate alternate) {+ alternates.add (alternate);+ }+}++}@@ -191,13 +191,15 @@ class BirdFontFile : GLib.Object { } public void write_alternates (DataOutputStream os) throws GLib.Error {- foreach (Alternate alternate in font.alternates) {+ foreach (Alternate alternate in font.alternates.alternates) { string character = @"$(Font.to_hex (alternate.character))";+ string tag = alternate.tag; foreach (string alt in alternate.alternates) { os.put_string (@"<alternate "); os.put_string (@"character=\"$character\" ");- os.put_string (@"alternate=\"$alt\" />\n");+ os.put_string (@"alternate=\"$alt\" ");+ os.put_string (@"tag=\"$(tag)\" />\n"); } } }@@ -832,6 +834,7 @@ class BirdFontFile : GLib.Object { public void parse_alternate (Tag tag) { unichar character = '\0'; string alt = "";+ string alt_tag = ""; foreach (Attribute attribute in tag.get_attributes ()) { if (attribute.get_name () == "character") {@@ -841,9 +844,13 @@ class BirdFontFile : GLib.Object { if (attribute.get_name () == "alternate") { alt = unserialize (attribute.get_content ()); }++ if (attribute.get_name () == "tag") {+ alt_tag = attribute.get_content ();+ } } - font.add_alternate (character, alt);+ font.add_alternate (character, alt, alt_tag); } public void parse_format (Tag tag) {@@ -371,15 +371,13 @@ os.put_string ( </div> <div>- <h3 class="big">Optional Features</h3>+ <h3 class="big"></h3> <p class="big">- <span class="swashes">Like swashes</span>- <span class="alternates">alternates &</span>- <span class="smallcaps">small caps</span> can be been added+ OTF features, <span class="swashes">like swashes </span>+ <span class="alternates">alternates & </span>+ <span class="smallcaps">small caps</span>, can be been added to the font. </p>- -</p> </div> <div>@@ -36,7 +36,7 @@ public class Font : GLib.Object { public GlyphTable ligature; /** List of alternate glyphs. */- public Gee.ArrayList<Alternate> alternates;+ public AlternateSets alternates; public Gee.ArrayList<BackgroundImage> background_images; public string background_scale = "1";@@ -179,15 +179,17 @@ public class Font : GLib.Object { settings = new FontSettings (); kerning_strings = new KerningStrings (); - alternates = new Gee.ArrayList<Alternate> ();+ alternates = new AlternateSets (); } ~Font () { font_deleted (); } - public Alternate? get_alternate (unichar character) {- foreach (Alternate a in alternates) {+ public Alternate? get_alternate (unichar character, string tag) {+ Gee.ArrayList<Alternate> alt = alternates.get_alt (tag);+ + foreach (Alternate a in alt) { if (a.character == character) { return a; }@@ -197,12 +199,13 @@ public class Font : GLib.Object { } public void add_new_alternate (GlyphCollection glyph,- GlyphCollection alternate) {+ GlyphCollection alternate, string tag) {+ Alternate a;- Alternate? alt = get_alternate (glyph.get_unicode_character ());+ Alternate? alt = get_alternate (glyph.get_unicode_character (), tag); if (alt == null) {- a = new Alternate (glyph.get_unicode_character ());+ a = new Alternate (glyph.get_unicode_character (), tag); alternates.add (a); } else { a = (!) alt;@@ -213,12 +216,14 @@ public class Font : GLib.Object { glyph_cache.insert (alternate.get_name (), alternate); } - public void add_alternate (unichar character, string alternate) {+ public void add_alternate (unichar character, string alternate, + string tag) {+ Alternate a;- Alternate? alt = get_alternate (character);+ Alternate? alt = get_alternate (character, tag); if (alt == null) {- a = new Alternate (character);+ a = new Alternate (character, tag); alternates.add (a); } else { a = (!) alt;@@ -586,7 +591,7 @@ public class Font : GLib.Object { glyph_name.remove (glyph.get_name ()); ligature.remove (glyph.get_current ().get_name ()); - foreach (Alternate a in alternates) {+ foreach (Alternate a in alternates.alternates) { a.remove (glyph); } @@ -18,10 +18,12 @@ public class Alternate : GLib.Object { public unichar character; public Gee.ArrayList<string> alternates;+ public string tag; - public Alternate (unichar character) {+ public Alternate (unichar character, string tag) { this.character = character; this.alternates = new Gee.ArrayList<string> ();+ this.tag = tag; } public void add (string glyph_name) {@@ -16,49 +16,56 @@ namespace BirdFont { public class AlternateFeature : GLib.Object { GlyfTable glyf_table;+ Gee.ArrayList<Alternate> alternates;+ string tag; - public AlternateFeature (GlyfTable glyf_table) { + public AlternateFeature (GlyfTable glyf_table, string tag) {+ Font font = OpenFontFormatWriter.get_current_font ();+ + this.tag = tag; this.glyf_table = glyf_table;+ alternates = font.alternates.get_alt (tag);++ alternates.sort ((a, b) => {+ Alternate alt1 = (Alternate) a;+ Alternate alt2 = (Alternate) b;+ return strcmp ((!) alt1.character.to_string (), (!) alt2.character.to_string ());+ }); } public bool has_alternates () {- Font font = OpenFontFormatWriter.get_current_font ();- return font.alternates.size > 0;+ return alternates.size > 0; } public Lookups get_lookups () throws GLib.Error { Lookups lookups = new Lookups ();- Lookup lookup = new Lookup (3, 0, Lookups.ALTERNATES);+ Lookup lookup = new Lookup (3, 0, tag); FontData fd = new FontData ();- Font font = OpenFontFormatWriter.get_current_font ();- - font.alternates.sort ((a, b) => {- Alternate alt1 = (Alternate) a;- Alternate alt2 = (Alternate) b;- return strcmp ((!) alt1.character.to_string (), (!) alt2.character.to_string ());- });- + fd.add_ushort (1); // format identifier // offset to coverage int coverage_offset = 6;- coverage_offset += 2 * font.alternates.size;+ coverage_offset += 2 * alternates.size; coverage_offset += 2 + 2 * get_number_of_alternates (); fd.add_ushort ((uint16) coverage_offset); // number of alternate sets- fd.add_ushort ((uint16) font.alternates.size); + fd.add_ushort ((uint16) alternates.size); - int offset = 6 + 2 * font.alternates.size;- for (int i = 0; i < font.alternates.size; i++) {+ print (@"alternates.size: $(alternates.size)\n");+ + int offset = 6 + 2 * alternates.size;+ for (int i = 0; i < alternates.size; i++) { // offset to each alternate set fd.add_ushort ((uint16) offset); offset += 2;- offset += 2 * font.alternates.get (i).alternates.size;+ offset += 2 * alternates.get (i).alternates.size; } // alternates- foreach (Alternate alternate in font.alternates) {+ foreach (Alternate alternate in alternates) {+ print (@"alternate.alternates.size: $(alternate.alternates.size)\n"); fd.add_ushort ((uint16) alternate.alternates.size); foreach (string alt in alternate.alternates) {@@ -68,8 +75,8 @@ public class AlternateFeature : GLib.Object { // coverage fd.add_ushort (1); // format- fd.add_ushort ((uint16) font.alternates.size); // coverage array length- foreach (Alternate alternate in font.alternates) {+ fd.add_ushort ((uint16) alternates.size); // coverage array length+ foreach (Alternate alternate in alternates) { string glyph_name = (!) alternate.character.to_string (); fd.add_ushort ((uint16) glyf_table.get_gid (glyph_name)); }@@ -82,9 +89,8 @@ public class AlternateFeature : GLib.Object { int get_number_of_alternates () { int n = 0;- Font font = OpenFontFormatWriter.get_current_font (); - foreach (Alternate alternate in font.alternates) {+ foreach (Alternate alternate in alternates) { n += alternate.alternates.size; } @@ -32,17 +32,17 @@ public class GsubTable : OtfTable { fd = new FontData (); CligFeature clig_feature = new CligFeature (glyf_table);- AlternateFeature alternate_feature = new AlternateFeature (glyf_table);+ AlternateFeature salt = new AlternateFeature (glyf_table, "salt"); Lookups lookups = new Lookups (); FeatureList features = new FeatureList (); - if (alternate_feature.has_alternates ()) { - Lookups aalt_lookup = alternate_feature.get_lookups ();- Feature aalt_feature_lookup = new Feature ("salt", lookups);- aalt_feature_lookup.add_feature_lookup (Lookups.ALTERNATES);- features.add (aalt_feature_lookup); - lookups.append (aalt_lookup);+ if (salt.has_alternates ()) { + Lookups salt_lookup = salt.get_lookups ();+ Feature salt_feature_lookup = new Feature ("salt", lookups);+ salt_feature_lookup.add_feature_lookup ("salt");+ features.add (salt_feature_lookup); + lookups.append (salt_lookup); } bool has_clig = clig_feature.contextual.has_ligatures ()new file mode 100644@@ -0,0 +1,129 @@+/*+ 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 Cairo;++namespace BirdFont {++/** A table for managing feature tags in Open Type tables. */+public class OtfFeatureTable : Table {+ Gee.ArrayList<Row> rows = new Gee.ArrayList<Row> ();+ + static const int NONE = 0;+ static const int OTF_FEATURE = 1;+ + GlyphCollection glyph_collection;+ string alternate_name = "";+ TextListener listener;+ + public OtfFeatureTable (GlyphCollection gc) {+ glyph_collection = gc;+ }++ public override Gee.ArrayList<Row> get_rows () {+ return rows;+ }++ public override void selected_row (Row row, int column, bool delete_button) {+ if (row.get_index () == OTF_FEATURE) {+ String s = (String) row.get_row_data ();+ add_new_alternate (s.data);+ }+ }++ public override void update_rows () {+ Row row;++ rows.clear ();++ row = new Row.headline (t_("OTF Features"));+ rows.add (row);+ + row = new Row.columns_1 (t_("Glyph") + ": " + glyph_collection.get_name (), NONE, false);+ rows.add (row);+ + // FIXME: reuse parts of this for fractions etc.+ + row = new Row.headline (t_("Tag"));+ rows.add (row);+ + row = new Row.columns_1 (t_("Stylistic Alternate") + " (salt)", OTF_FEATURE, false);+ row.set_row_data (new String ("salt"));+ rows.add (row);++ row = new Row.columns_1 (t_("Small Caps") + " (smcp)", OTF_FEATURE, false);+ row.set_row_data (new String ("smcp"));+ rows.add (row);++ row = new Row.columns_1 (t_("Capitals to Small Caps") + " (c2sc)", OTF_FEATURE, false);+ row.set_row_data (new String ("c2sc"));+ rows.add (row);++ row = new Row.columns_1 (t_("Swashes") + " (swsh)", OTF_FEATURE, false);+ row.set_row_data (new String ("swsh"));+ rows.add (row);+ + GlyphCanvas.redraw ();+ }++ public override string get_label () {+ return t_("OTF Feature Tags");+ }++ public override string get_name () {+ return "OTF Feature Tags";+ }++ public override void draw (WidgetAllocation allocation, Context cr) {+ base.draw (allocation, cr);+ } ++ public void add_new_alternate (string tag) {+ GlyphCollection gc = glyph_collection;+ + listener = new TextListener (t_("Glyph name"), "", t_("Add"));+ + listener.signal_text_input.connect ((text) => {+ alternate_name = text;+ });+ + listener.signal_submit.connect (() => {+ GlyphCollection alt;+ Font font;+ OverView overview = MainWindow.get_overview ();+ + font = BirdFont.get_current_font ();+ + if (alternate_name == "" || gc.is_unassigned ()) {+ MainWindow.tabs.close_display (this);+ return;+ }+ + if (font.glyph_name.has_key (alternate_name)) {+ MainWindow.show_message (t_("All glyphs must have unique names."));+ } else {+ alt = new GlyphCollection.with_glyph ('\0', alternate_name);+ alt.set_unassigned (true);+ font.add_new_alternate (gc, alt, tag);+ MainWindow.tabs.close_display (this);+ MainWindow.get_overview ().update_item_list ();+ overview.open_glyph_signal (alt);+ }+ });+ + TabContent.show_text_input (listener);+ }+}++}@@ -32,8 +32,6 @@ public class OverviewTools : ToolCollection { public static SpinButton skew; public static SpinButton resize; - private string alternate_name = "";- public OverviewTools () { Expander font_name = new Expander (); Expander character_sets = new Expander (t_("Character Sets"));@@ -142,47 +140,18 @@ public class OverviewTools : ToolCollection { } public void add_new_alternate (Tool tool) {- TextListener listener; OverView o = MainWindow.get_overview (); OverViewItem oi = o.selected_item; GlyphCollection gc; - if (oi.glyphs == null) {+ tool.set_selected (false);+ + if (oi.glyphs == null || ((!) oi.glyphs).is_unassigned ()) { return; } - gc = (!) oi.glyphs;- - listener = new TextListener (t_("Alternate"), "", t_("Add"));- - listener.signal_text_input.connect ((text) => {- alternate_name = text;- });- - listener.signal_submit.connect (() => {- GlyphCollection alt;- Font font;- OverView overview = MainWindow.get_overview ();- - font = BirdFont.get_current_font ();- - if (alternate_name == "" || gc.is_unassigned ()) {- return;- }- - if (font.glyph_name.has_key (alternate_name)) {- MainWindow.show_message (t_("All glyphs must have unique names."));- } else {- alt = new GlyphCollection.with_glyph ('\0', alternate_name);- alt.set_unassigned (true);- font.add_new_alternate (gc, alt);- MainWindow.get_overview ().update_item_list ();- overview.open_glyph_signal (alt);- }- });- - tool.set_selected (false);- TabContent.show_text_input (listener);+ gc = (!) oi.glyphs; + MainWindow.tabs.add_tab (new OtfFeatureTable (gc)); } public void process_transform () {new file mode 100644@@ -0,0 +1,26 @@+/*+ 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.+*/++namespace BirdFont {++/** Boxed string class. */+public class String : GLib.Object {+ public string data;+ + public String (string data) {+ this.data = data;+ }+}++}