The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Generate swsh, salt, smcp and c2sc tables.

These changes was commited to the Birdfont repository Sun, 27 Sep 2015 22:59:38 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
author Johan Mattsson <johan.mattsson.m@gmail.com>
Sun, 27 Sep 2015 22:59:38 +0000 (00:59 +0200)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Sun, 27 Sep 2015 22:59:38 +0000 (00:59 +0200)
commit bd66d9b55d01a161bb623c7739de886981507245
tree 8d5f9dc76708af6a42125223b56d8e06ac6ce237
parent d64144422991645142a57f94381bfb9f72eaaadd
Generate swsh, salt, smcp and c2sc tables.
This commit adds support for swashes, stylistic alternatives, small caps and
conversion from uppercase to small caps

13 files changed:
libbirdfont/AlternateSets.vala
libbirdfont/ExportTool.vala
libbirdfont/OpenFontFormat/Alternate.vala
libbirdfont/OpenFontFormat/AlternateFeature.vala
libbirdfont/OpenFontFormat/CligFeature.vala
libbirdfont/OpenFontFormat/Feature.vala
libbirdfont/OpenFontFormat/FeatureList.vala
libbirdfont/OpenFontFormat/GsubTable.vala
libbirdfont/OpenFontFormat/Lookup.vala
libbirdfont/OpenFontFormat/Lookups.vala
libbirdfont/OverView.vala
libbirdfont/OverviewTools.vala
--- a/libbirdfont/AlternateSets.vala +++ b/libbirdfont/AlternateSets.vala @@ -40,7 +40,7 @@ alt = new Gee.ArrayList<Alternate> (); foreach (Alternate a in alternates) { - if (a.tag == tag) { + if (a.tag == tag && a.alternates.size > 0) { alt.add (a); } } @@ -50,8 +50,16 @@ public void add (Alternate alternate) { alternates.add (alternate); + } + + public AlternateSets copy () { + AlternateSets n = new AlternateSets (); + foreach (Alternate a in alternates) { + n.alternates.add (a.copy ()); + } + return n; } } }
--- a/libbirdfont/ExportTool.vala +++ b/libbirdfont/ExportTool.vala @@ -351,6 +351,14 @@ -ms-font-feature-settings: "smcp"; -webkit-font-feature-settings: "smcp"; font-feature-settings: "smcp"; + } + + span.capstosmallcaps { + font-variant-caps: all-small-caps; + -moz-font-feature-settings: "c2sc", "smcp"; + -ms-font-feature-settings: "c2sc", "smcp"; + -webkit-font-feature-settings: "c2sc", "smcp"; + font-feature-settings: "c2sc", "smcp"; } </style> """); @@ -373,10 +381,11 @@ <div> <h3 class="big"></h3> <p class="big"> - OTF features, <span class="swashes">like swashes </span> + <span class="capstosmallcaps">OTF</span> 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. + to the font.</span> </p> </div>
--- a/libbirdfont/OpenFontFormat/Alternate.vala +++ b/libbirdfont/OpenFontFormat/Alternate.vala @@ -44,7 +44,16 @@ } } + public Alternate copy () { + Alternate n = new Alternate (character, tag); + + foreach (string s in alternates) { + n.add (s); + } + + return n; + } } }
--- a/libbirdfont/OpenFontFormat/AlternateFeature.vala +++ b/libbirdfont/OpenFontFormat/AlternateFeature.vala @@ -47,13 +47,16 @@ // offset to coverage int coverage_offset = 6; coverage_offset += 2 * alternates.size; - coverage_offset += 2 + 2 * get_number_of_alternates (); + + foreach (Alternate a in alternates) { + coverage_offset += 2; + coverage_offset += 2 * a.alternates.size; + } + fd.add_ushort ((uint16) coverage_offset); // number of alternate sets fd.add_ushort ((uint16) alternates.size); - - print (@"alternates.size: $(alternates.size)\n"); int offset = 6 + 2 * alternates.size; for (int i = 0; i < alternates.size; i++) { @@ -65,13 +68,22 @@ // alternates foreach (Alternate alternate in alternates) { - print (@"alternate.alternates.size: $(alternate.alternates.size)\n"); fd.add_ushort ((uint16) alternate.alternates.size); + + alternate.alternates.sort ((a, b) => { + string alt1 = (string) a; + string alt2 = (string) b; + return strcmp (alt1, alt2); + }); foreach (string alt in alternate.alternates) { fd.add_ushort ((uint16) glyf_table.get_gid (alt)); } } + + if (fd.length_with_padding () != coverage_offset) { + warning (@"Bad coverage offset. $(fd.length_with_padding ()) != $coverage_offset"); + } // coverage fd.add_ushort (1); // format @@ -85,18 +97,8 @@ lookups.add_lookup (lookup); return lookups; - } - - int get_number_of_alternates () { - int n = 0; - - foreach (Alternate alternate in alternates) { - n += alternate.alternates.size; - } - - return n; } } }
--- a/libbirdfont/OpenFontFormat/CligFeature.vala +++ b/libbirdfont/OpenFontFormat/CligFeature.vala @@ -59,14 +59,14 @@ lookups.add_lookup(lookup); } - lookup = new Lookup (6, 0, Lookups.CHAINED_CONTEXT); + lookup = new Lookup (6, 0, "chained"); foreach (FontData d in chain_data) { lookup.add_subtable (d); } lookups.add_lookup(lookup); } - lookup = new Lookup (4, 0, Lookups.LIGATURES); + lookup = new Lookup (4, 0, "ligatures"); lookup.add_subtable (clig_subtable); lookups.add_lookup(lookup); }
--- a/libbirdfont/OpenFontFormat/Feature.vala +++ b/libbirdfont/OpenFontFormat/Feature.vala @@ -18,16 +18,14 @@ public string tag; public Lookups lookups; - public Gee.ArrayList<int> public_lookups = new Gee.ArrayList<int> (); - - public int lookup_offset = 0; // FIXME:DELETE + public Gee.ArrayList<string> public_lookups = new Gee.ArrayList<string> (); public Feature (string tag, Lookups lookups) { this.tag = tag; this.lookups = lookups; } - public void add_feature_lookup (int lookup_token) { + public void add_feature_lookup (string lookup_token) { public_lookups.add (lookup_token); }
--- a/libbirdfont/OpenFontFormat/FeatureList.vala +++ b/libbirdfont/OpenFontFormat/FeatureList.vala @@ -27,15 +27,28 @@ public FontData generate_feature_tags () throws GLib.Error { FontData fd = new FontData (); + + features.sort ((fa, fb) => { + Feature a = (Feature) fa; + Feature b = (Feature) fb; + return strcmp (a.tag, b.tag); + }); fd.add_ushort ((uint16) features.size); // number of features uint offset = 2 + 6 * features.size; foreach (Feature feature in features) { - fd.add_tag (feature.tag); // feature tag: aalt, clig etc. - fd.add_ushort ((uint16) offset); // offset to feature + // feature tag: aalt, clig etc. + fd.add_tag (feature.tag); + + // offset to feature from beginning of this table + fd.add_ushort ((uint16) offset); offset += 4 + 2 * feature.get_public_lookups (); + + if (feature.get_public_lookups () == 0) { + warning (@"No lookups for $(feature.tag)"); + } } foreach (Feature feature in features) { @@ -45,7 +58,7 @@ // number of lookups fd.add_ushort ((uint16) feature.public_lookups.size); - foreach (int p in feature.public_lookups) { + foreach (string p in feature.public_lookups) { // reference to a lookup table (lookup index) fd.add_ushort (feature.lookups.find (p)); }
--- a/libbirdfont/OpenFontFormat/GsubTable.vala +++ b/libbirdfont/OpenFontFormat/GsubTable.vala @@ -32,19 +32,10 @@ fd = new FontData (); CligFeature clig_feature = new CligFeature (glyf_table); - AlternateFeature salt = new AlternateFeature (glyf_table, "salt"); Lookups lookups = new Lookups (); FeatureList features = new FeatureList (); - 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 () || clig_feature.has_regular_ligatures (); @@ -53,24 +44,30 @@ Feature clig_feature_lookup = new Feature ("clig", lookups); if (clig_feature.contextual.has_ligatures ()) { - clig_feature_lookup.add_feature_lookup (Lookups.CHAINED_CONTEXT); + clig_feature_lookup.add_feature_lookup ("chained"); } if (clig_feature.has_regular_ligatures ()) { - clig_feature_lookup.add_feature_lookup (Lookups.LIGATURES); + clig_feature_lookup.add_feature_lookup ("ligatures"); } features.add (clig_feature_lookup); lookups.append (clig_lookups); } - + + add_alternate_table (features, lookups, "swsh"); + add_alternate_table (features, lookups, "salt"); + add_alternate_table (features, lookups, "c2sc"); + add_alternate_table (features, lookups, "smcp"); + FontData feature_tags = features.generate_feature_tags (); - uint lookup_list_offset = 30 + feature_tags.length_with_padding (); + uint feature_list_offset = 28 + 2 * features.features.size; + uint lookup_list_offset = feature_list_offset + feature_tags.length_with_padding (); 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 ((uint16) feature_list_offset); // offset to feature list fd.add_ushort ((uint16) lookup_list_offset); // offset to lookup list // script list @@ -86,7 +83,11 @@ fd.add_ushort (0); // reserved fd.add_ushort (0xFFFF); // required features (0xFFFF is none) fd.add_ushort ((uint16) features.features.size); // number of features - fd.add_ushort (0); // feature index + + // FIXME: double check this + for (int i = 0; i < features.features.size; i++) { + fd.add_ushort ((uint16) i); // feature index + } // feature lookups with references to the lookup list fd.append (feature_tags); @@ -109,7 +110,21 @@ this.font_data = fd; } + + /** Add alterate substitutions to lookups and features. */ + public void add_alternate_table (FeatureList features, Lookups lookups, string tag) + throws GLib.Error { + AlternateFeature alt = new AlternateFeature (glyf_table, tag); + if (alt.has_alternates ()) { + Lookups alt_lookup = alt.get_lookups (); + Feature alt_feature_lookup = new Feature (tag, lookups); + alt_feature_lookup.add_feature_lookup (tag); + features.add (alt_feature_lookup); + lookups.append (alt_lookup); + } + } + } }
--- a/libbirdfont/OpenFontFormat/Lookup.vala +++ b/libbirdfont/OpenFontFormat/Lookup.vala @@ -19,9 +19,15 @@ public uint16 type; public uint16 flags; public Gee.ArrayList<FontData> subtables; - public int token; + public string token; - public Lookup (uint16 type, uint16 flags, int token = Lookups.NONE) { + // the token is used for obtaining index in lookup list, an empty + // string ensures that the subtable can't be directly used by + // a table, chaining context use that feature. + // + // Lookups.find is used to obtain index in the lookup list for + // a token. + public Lookup (uint16 type, uint16 flags, string token = "") { this.type = type; this.flags = flags; subtables = new Gee.ArrayList<FontData> ();
--- a/libbirdfont/OpenFontFormat/Lookups.vala +++ b/libbirdfont/OpenFontFormat/Lookups.vala @@ -20,11 +20,6 @@ public class Lookups : GLib.Object { public Gee.ArrayList<Lookup> tables = new Gee.ArrayList<Lookup> (); - - public static const int NONE = 0; - public static const int CHAINED_CONTEXT = 1; - public static const int LIGATURES = 2; - public static const int ALTERNATES = 2; public Lookups () { } @@ -38,7 +33,7 @@ } /** Find the lookup index for a particular lookup. */ - public uint16 find (int token) { + public uint16 find (string token) { uint16 index = 0; foreach (Lookup lookup in tables) { if (lookup.token == token) {
--- a/libbirdfont/OverView.vala +++ b/libbirdfont/OverView.vala @@ -918,6 +918,8 @@ public void delete_selected_glyph () { Font font = BirdFont.get_current_font (); OverViewUndoItem undo_item = new OverViewUndoItem (); + + undo_item.alternate_sets = font.alternates.copy (); foreach (GlyphCollection g in selected_items) { undo_item.glyphs.add (g.copy ()); @@ -952,6 +954,9 @@ } } + Font f = BirdFont.get_current_font (); + f.alternates = previous_collection.alternate_sets.copy (); + undo_items.remove_at (undo_items.size - 1); GlyphCanvas.redraw (); } @@ -973,6 +978,8 @@ font.add_glyph_collection (g); } + font.alternates = previous_collection.alternate_sets.copy (); + redo_items.remove_at (redo_items.size - 1); GlyphCanvas.redraw (); } @@ -981,6 +988,8 @@ GlyphCollection? gc; OverViewUndoItem ui = new OverViewUndoItem (); Font font = BirdFont.get_current_font (); + + ui.alternate_sets = font.alternates.copy (); foreach (GlyphCollection g in previous_collection.glyphs) { gc = font.get_glyph_collection (g.get_name ()); @@ -997,6 +1006,8 @@ public void store_undo_state (GlyphCollection gc) { OverViewUndoItem i = new OverViewUndoItem (); + Font f = BirdFont.get_current_font (); + i.alternate_sets = f.alternates.copy (); i.glyphs.add (gc); store_undo_items (i); } @@ -1414,7 +1425,7 @@ } public void paste () { - GlyphCollection gc = new GlyphCollection ('\0', ""); + GlyphCollection gc; GlyphCollection? c; Glyph glyph; uint32 index; @@ -1422,9 +1433,13 @@ int skip = 0; int s; string character_string; - Gee.ArrayList<GlyphCollection> glyps = new Gee.ArrayList<GlyphCollection> (); - Font f = BirdFont.get_current_font (); + Gee.ArrayList<GlyphCollection> glyps; + Font f; OverViewUndoItem undo_item; + + f = BirdFont.get_current_font (); + gc = new GlyphCollection ('\0', ""); + glyps = new Gee.ArrayList<GlyphCollection> (); copied_glyphs.sort ((a, b) => { return (int) ((GlyphCollection) a).get_unicode_character () @@ -1480,6 +1495,7 @@ } undo_item = new OverViewUndoItem (); + undo_item.alternate_sets = f.alternates.copy (); foreach (GlyphCollection g in glyps) { undo_item.glyphs.add (g.copy ()); } @@ -1515,9 +1531,10 @@ } public class OverViewUndoItem { + public AlternateSets alternate_sets = new AlternateSets (); public Gee.ArrayList<GlyphCollection> glyphs = new Gee.ArrayList<GlyphCollection> (); } } }
--- a/libbirdfont/OverviewTools.vala +++ b/libbirdfont/OverviewTools.vala @@ -161,6 +161,9 @@ o = get_overview (); ui = new OverView.OverViewUndoItem (); + + Font f = BirdFont.get_current_font (); + ui.alternate_sets = f.alternates.copy (); foreach (GlyphCollection gc in o.selected_items) { if (gc.length () > 0) {