The Birdfont Source Code


All Repositories / birdfont.git / commitdiff – RSS feed

Generate stylistic alternates and fix PostScript names

These changes was commited to the Birdfont repository Sun, 27 Sep 2015 13:41:14 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
[Sun, 27 Sep 2015 13:41:14 +0000]

Updated Files

libbirdfont/Font.vala
libbirdfont/GlyphCollection.vala
libbirdfont/OpenFontFormat/Alternate.vala
libbirdfont/OpenFontFormat/AlternateFeature.vala
libbirdfont/OpenFontFormat/CligFeature.vala
libbirdfont/OpenFontFormat/Feature.vala
libbirdfont/OpenFontFormat/FeatureList.vala
libbirdfont/OpenFontFormat/GlyfTable.vala
libbirdfont/OpenFontFormat/GsubTable.vala
libbirdfont/OpenFontFormat/HheaTable.vala
libbirdfont/OpenFontFormat/LigatureCollection.vala
libbirdfont/OpenFontFormat/Lookup.vala
libbirdfont/OpenFontFormat/Lookups.vala
libbirdfont/OpenFontFormat/NameTable.vala
libbirdfont/OpenFontFormat/PostTable.vala
libbirdfont/OverView.vala
libbirdfont/OverviewTools.vala
libbirdfont/StrokeTool.vala
resources/icons.bf
--- a/libbirdfont/Font.vala +++ b/libbirdfont/Font.vala @@ -34,6 +34,9 @@ /** Table with ligatures. */ public GlyphTable ligature; + + /** List of alternate glyphs. */ + public Gee.ArrayList<Alternate> alternates; public Gee.ArrayList<BackgroundImage> background_images; public string background_scale = "1"; @@ -63,7 +66,7 @@ bool modified = false; - // name table descriptions + // name table strings public string postscript_name; public string name; public string subfamily; @@ -175,10 +178,39 @@ settings = new FontSettings (); kerning_strings = new KerningStrings (); + + alternates = new Gee.ArrayList<Alternate> (); } ~Font () { font_deleted (); + } + + public Alternate? get_alternate (GlyphCollection gc) { + foreach (Alternate a in alternates) { + if (a.glyph == gc) { + return a; + } + } + + return null; + } + + public void add_new_alternate (GlyphCollection glyph, + GlyphCollection alternate) { + + Alternate a; + Alternate? alt = get_alternate (alternate); + + if (alt == null) { + a = new Alternate (glyph); + alternates.add (a); + } else { + a = (!) alt; + } + + a.add (alternate); + glyph_name.insert (alternate.get_name (), alternate); } public bool has_compatible_format () { @@ -539,6 +571,10 @@ glyph_cache.remove (glyph.get_name ()); glyph_name.remove (glyph.get_name ()); ligature.remove (glyph.get_current ().get_name ()); + + foreach (Alternate a in alternates) { + a.remove (glyph); + } foreach (Glyph g in glyph.glyphs) { deleted_glyphs.add (g);
--- a/libbirdfont/GlyphCollection.vala +++ b/libbirdfont/GlyphCollection.vala @@ -37,6 +37,7 @@ g = new Glyph (name, unicode_character); glyphs.add (g); + set_selected (g); } public void remove (int index) {
--- /dev/null +++ b/libbirdfont/OpenFontFormat/Alternate.vala @@ -1,1 +1,48 @@ + /* + 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 Alternate : GLib.Object { + + public GlyphCollection glyph; + public Gee.ArrayList<GlyphCollection> alternates; + + public Alternate (GlyphCollection glyph) { + this.glyph = glyph; + this.alternates = new Gee.ArrayList<GlyphCollection> (); + } + + public void add (GlyphCollection g) { + alternates.add (g); + } + + public void remove (GlyphCollection g) { + int i = 0; + foreach (GlyphCollection a in alternates) { + if (a.get_name () == g.get_name ()) { + break; + } + i++; + } + + if (i < alternates.size) { + alternates.remove_at (i); + } + } + + } + + }
--- a/libbirdfont/OpenFontFormat/AlternateFeature.vala +++ b/libbirdfont/OpenFontFormat/AlternateFeature.vala @@ -11,20 +11,86 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ - using Math; namespace BirdFont { public class AlternateFeature : GLib.Object { - FontData font_data = new FontData (); + GlyfTable glyf_table; + + public AlternateFeature (GlyfTable glyf_table) { + this.glyf_table = glyf_table; + } + + public bool has_alternates () { + Font font = OpenFontFormatWriter.get_current_font (); + return font.alternates.size > 0; + } + + public Lookups get_lookups () throws GLib.Error { + Lookups lookups = new Lookups (); + Lookup lookup = new Lookup (3, 0, Lookups.ALTERNATES); + 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.glyph.get_name (), alt2.glyph.get_name ()); + }); + + fd.add_ushort (1); // format identifier + + // offset to coverage + int coverage_offset = 6; + coverage_offset += 2 * font.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); + + int offset = 6 + 2 * font.alternates.size; + for (int i = 0; i < font.alternates.size; i++) { + // offset to each alternate set + fd.add_ushort ((uint16) offset); + offset += 2; + offset += 2 * font.alternates.size; + } + + // alternates + fd.add_ushort ((uint16) font.alternates.size); + foreach (Alternate alternate in font.alternates) { + foreach (GlyphCollection g in alternate.alternates) { + string name = g.get_name (); + fd.add_ushort ((uint16) glyf_table.get_gid (name)); + } + } - public AlternateFeature () { + // coverage + fd.add_ushort (1); // format + fd.add_ushort ((uint16) font.alternates.size); // coverage array length + foreach (Alternate alternate in font.alternates) { + string glyph_name = alternate.glyph.get_name (); + fd.add_ushort ((uint16) glyf_table.get_gid (glyph_name)); + } + + lookup.add_subtable (fd); + lookups.add_lookup (lookup); + + return lookups; } - public FontData get_font_data () { - return font_data; + int get_number_of_alternates () { + int n = 0; + Font font = OpenFontFormatWriter.get_current_font (); + + foreach (Alternate alternate in font.alternates) { + n += alternate.alternates.size; + } + + return n; } } }
--- a/libbirdfont/OpenFontFormat/CligFeature.vala +++ b/libbirdfont/OpenFontFormat/CligFeature.vala @@ -24,6 +24,10 @@ public CligFeature (GlyfTable glyf_table) throws GLib.Error { this.glyf_table = glyf_table; generate_feature (); + } + + public bool has_regular_ligatures () { + return clig.ligature_sets.size > 0; } public Lookups get_lookups () {
--- /dev/null +++ b/libbirdfont/OpenFontFormat/Feature.vala @@ -1,1 +1,40 @@ + /* + 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 Feature : GLib.Object { + + public string tag; + public Lookups lookups; + public Gee.ArrayList<int> public_lookups = new Gee.ArrayList<int> (); + + public int lookup_offset = 0; // FIXME:DELETE + + public Feature (string tag, Lookups lookups) { + this.tag = tag; + this.lookups = lookups; + } + + public void add_feature_lookup (int lookup_token) { + public_lookups.add (lookup_token); + } + + public int get_public_lookups () { + return public_lookups.size; + } + } + + }
--- /dev/null +++ b/libbirdfont/OpenFontFormat/FeatureList.vala @@ -1,1 +1,59 @@ + /* + 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 FeatureList : GLib.Object { + + public Gee.ArrayList<Feature> features = new Gee.ArrayList<Feature> (); + + public FeatureList () { + } + + public void add (Feature f) { + features.add (f); + } + + public FontData generate_feature_tags () throws GLib.Error { + FontData fd = new FontData (); + + 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 + + offset += 4 + 2 * feature.get_public_lookups (); + } + + foreach (Feature feature in features) { + // feature prameters (null) + fd.add_ushort (0); + + // number of lookups + fd.add_ushort ((uint16) feature.public_lookups.size); + + foreach (int p in feature.public_lookups) { + // reference to a lookup table (lookup index) + fd.add_ushort (feature.lookups.find (p)); + } + } + + return fd; + } + } + + }
--- a/libbirdfont/OpenFontFormat/GlyfTable.vala +++ b/libbirdfont/OpenFontFormat/GlyfTable.vala @@ -144,7 +144,7 @@ Gee.ArrayList<GlyphCollection> unassigned_glyphs; bool unassigned; - // add notdef character and other special chars first + // add notdef character and other special characters first glyphs.add (font.get_not_def_character ()); glyphs.add (font.get_null_character ()); glyphs.add (font.get_nonmarking_return ()); @@ -159,12 +159,10 @@ // add glyphs for (indice = 0; (gcn = font.get_glyph_collection_indice (indice)) != null; indice++) { gc = (!) gcn; - g = gc.get_current ().copy (); + gc = gc.copy_deep (); + g = gc.get_current (); g.remove_empty_paths (); unassigned = gc.is_unassigned (); - - gc = new GlyphCollection (gc.get_unicode_character (), gc.get_name ()); - gc.add_glyph (g); if (unassigned) { unassigned_glyphs.add (gc);
--- a/libbirdfont/OpenFontFormat/GsubTable.vala +++ b/libbirdfont/OpenFontFormat/GsubTable.vala @@ -32,12 +32,46 @@ fd = new FontData (); CligFeature clig_feature = new CligFeature (glyf_table); - AlternateFeature alternate_feature = new AlternateFeature (); + AlternateFeature alternate_feature = new AlternateFeature (glyf_table); + + 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 ("aalt", lookups); + aalt_feature_lookup.add_feature_lookup (Lookups.ALTERNATES); + features.add (aalt_feature_lookup); + lookups.append (aalt_lookup); + } + + bool has_clig = clig_feature.contextual.has_ligatures () + || clig_feature.has_regular_ligatures (); + + if (has_clig) { + Lookups clig_lookups = clig_feature.get_lookups (); + Feature clig_feature_lookup = new Feature ("clig", lookups); + + if (clig_feature.contextual.has_ligatures ()) { + clig_feature_lookup.add_feature_lookup (Lookups.CHAINED_CONTEXT); + } + + if (clig_feature.has_regular_ligatures ()) { + clig_feature_lookup.add_feature_lookup (Lookups.LIGATURES); + } + + features.add (clig_feature_lookup); + lookups.append (clig_lookups); + } + + FontData feature_tags = features.generate_feature_tags (); + + uint lookup_list_offset = 30 + 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 (clig_feature.contextual.has_ligatures () ? 46 : 44); // offset to lookup list + fd.add_ushort ((uint16) lookup_list_offset); // offset to lookup list // script list fd.add_ushort (1); // number of items in script list @@ -53,40 +87,18 @@ 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 - // FIXME: Should it be liga and clig? - Lookups lookups = new Lookups (); - lookups.append (clig_feature.get_lookups ()); - - // FIXME: refactor clig_feature - uint16 feature_lookups = 1; - - if (clig_feature.contextual.has_ligatures ()) { - feature_lookups++; - } - - fd.add_ushort (0); // feature prameters (null) - fd.add_ushort (feature_lookups); // number of lookups - - if (clig_feature.contextual.has_ligatures ()) { - // The chained context tables are listed here but the actual - // ligature table is only referenced in the context table - fd.add_ushort (lookups.find (Lookups.CHAINED_CONTEXT)); - fd.add_ushort (lookups.find (Lookups.LIGATURES)); - } else { - fd.add_ushort (lookups.find (Lookups.LIGATURES)); // lookup clig_subtable + // feature lookups with references to the lookup list + fd.append (feature_tags); + + if (lookup_list_offset != fd.length_with_padding ()) { + warning (@"Bad offset to lookup list: $(lookup_list_offset) != $(fd.length_with_padding ())"); } - + // lookup list - fd.append (lookups.genrate_lookup_list ()); - - // subtables + fd.append (lookups.generate_lookup_list ()); + + // subtable data foreach (Lookup lookup in lookups.tables) { foreach (FontData subtable in lookup.subtables) { fd.append (subtable); @@ -100,5 +112,4 @@ } } -
--- a/libbirdfont/OpenFontFormat/HheaTable.vala +++ b/libbirdfont/OpenFontFormat/HheaTable.vala @@ -86,7 +86,7 @@ int16 ascender, descender; FontData fd = new FontData (); Fixed version = 1 << 16; - Font font = BirdFont.get_current_font (); + Font font = OpenFontFormatWriter.get_current_font (); fd.add_fixed (version); // table version
--- a/libbirdfont/OpenFontFormat/LigatureCollection.vala +++ b/libbirdfont/OpenFontFormat/LigatureCollection.vala @@ -11,7 +11,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. */ - using Math; namespace BirdFont {
--- a/libbirdfont/OpenFontFormat/Lookup.vala +++ b/libbirdfont/OpenFontFormat/Lookup.vala @@ -33,6 +33,10 @@ } public uint get_lookup_entry_size () throws GLib.Error { + if (subtables.size == 0) { + warning ("No subtables."); + } + return 6 + 2 * subtables.size; }
--- a/libbirdfont/OpenFontFormat/Lookups.vala +++ b/libbirdfont/OpenFontFormat/Lookups.vala @@ -23,8 +23,9 @@ public static const int NONE = 0; public static const int CHAINED_CONTEXT = 1; - public static const int LIGATURES = 1; - + public static const int LIGATURES = 2; + public static const int ALTERNATES = 2; + public Lookups () { } @@ -57,7 +58,7 @@ } } - public FontData genrate_lookup_list () throws GLib.Error { + public FontData generate_lookup_list () throws GLib.Error { FontData fd = new FontData (); uint lookup_offset; uint tables_size;
--- a/libbirdfont/OpenFontFormat/NameTable.vala +++ b/libbirdfont/OpenFontFormat/NameTable.vala @@ -149,7 +149,9 @@ return name_validation (s, true); } - public string name_validation (string s, bool allow_space) { + public static string name_validation (string s, bool allow_space, + int max_length = 27) { + string n; int ccount; unichar c; @@ -158,7 +160,7 @@ n = s; ccount = n.char_count (); // truncate strings longer than 28 characters - for (int i = 0; i < ccount && i < 27; i++) { + for (int i = 0; i < ccount && i < max_length; i++) { c = n.get_char (n.index_of_nth_char (i)); if (allow_space && c == ' ') { @@ -173,7 +175,7 @@ return name.str; } - bool is_valid_ps_name_char (unichar c) { + static bool is_valid_ps_name_char (unichar c) { switch (c) { case '[': return false;
--- a/libbirdfont/OpenFontFormat/PostTable.vala +++ b/libbirdfont/OpenFontFormat/PostTable.vala @@ -20,124 +20,10 @@ Gee.ArrayList<uint16> index = new Gee.ArrayList<uint16> (); Gee.ArrayList<string> names = new Gee.ArrayList<string> (); - - Gee.ArrayList<string> available_names = new Gee.ArrayList<string> (); public PostTable (GlyfTable g) { id = "post"; glyf_table = g; - } - - public int get_gid (string name) { // FIXME: do fast lookup - int i = 0; - int j = 0; - foreach (string n in names) { - if (n == name) { - j = 0; - foreach (uint16 k in index) { - if (k == i) { - return j; - } - j++; - } - - return i; - } - i++; - } - return -1; - } - - public string get_name (int gid) { - int k; - - if (!(0 <= gid < index.size)) { - warning ("gid is out of range."); - return ""; - } - - k = index.get (gid); - - if (gid != 0 && k == 0) { - warning (@"Glyph $gid is assigned to name .notdef, only gid 0 can be .notdef character."); - return ""; - } - - if (!(0 <= k < names.size)) { - warning ("k is out of range."); - return ""; - } - - return names.get (k); - } - - public override void parse (FontData dis) throws Error { - dis.seek (offset); - - Fixed format = dis.read_fixed (); - Fixed italic = dis.read_fixed (); - - int16 underlie_pos = dis.read_short (); - int16 underlie_thickness = dis.read_short (); - uint32 is_fixed_pitch = dis.read_ulong (); - - uint32 mem_min42 = dis.read_ulong (); - uint32 mem_max42 = dis.read_ulong (); - uint32 mem_min1 = dis.read_ulong (); - uint32 mem_max1 = dis.read_ulong (); - - uint16 nnames = dis.read_ushort (); - - if (format != 0x00020000) { - warning ("Only post tables of version 2 will be parsed found version $(format.get_string ())"); - return; - } - - printd (@"format: $(format.get_string ())\n"); - printd (@"italic: $(italic.get_string ())\n"); - printd (@"underlie_pos: $(underlie_pos)\n"); - printd (@"underlie_thickness: $(underlie_thickness)\n"); - printd (@"is_fixed_pitch: $(is_fixed_pitch)\n"); - printd (@"mem_min42: $(mem_min42)\n"); - printd (@"mem_max42: $(mem_max42)\n"); - printd (@"mem_min1: $(mem_min1)\n"); - printd (@"mem_max1: $(mem_max1)\n"); - printd (@"\n"); - - printd (@"Num names: $(nnames)\n"); - - uint16 k; - int non_standard_names = 0; - for (uint16 i = 0; i < nnames; i++) { - k = dis.read_ushort (); - index.add (k); - - if (k >= 258) { - non_standard_names++; - } - } - - add_standard_names (); - - // read non standard names - for (int i = 0; i < non_standard_names; i++) { - uint8 len = dis.read_byte (); - StringBuilder name = new StringBuilder (); - - for (int j = 0; j < len; j++) { - name.append_c (dis.read_char ()); - } - - names.add (name.str); - } - - populate_available (); - } - - void populate_available () { - for (int i = 0; i < index.size; i++) { - available_names.add (get_name (i)); - } } // the Macintosh standard order @@ -1188,7 +1074,8 @@ int name_index; GlyphCollection gc; Glyph g; - + string ps_name; + fd.add_fixed (0x00020000); // Version fd.add_fixed (0x00000000); // italicAngle @@ -1213,20 +1100,24 @@ assert (names.size == 0); add_standard_names (); + + print ("Adding post names\n"); for (int i = 1; i < glyf_table.glyphs.size; i++) { gc = glyf_table.glyphs.get (i); g = gc.get_current (); name_index = get_standard_index (g.unichar_code); - if (name_index != 0) { + if (name_index != 0 && !gc.is_unassigned ()) { fd.add_ushort ((uint16) name_index); // use standard name } else { - printd (@"Adding non standard postscript name $(g.get_name ())\n"); + printd (@"Adding non standard postscript name $(gc.get_name ())\n"); name_index = (int) names.size; // use font specific name fd.add_ushort ((uint16) name_index); - names.add (g.get_name ()); + + ps_name = create_ps_name (g.get_name ()); + names.add (ps_name); } this.index.add ((uint16) name_index); @@ -1237,6 +1128,7 @@ if (n.length > 0xFF) { warning (@"too long name for glyph $n"); + continue; } fd.add ((uint8) n.length); @@ -1248,7 +1140,34 @@ this.font_data = fd; } + string create_ps_name (string name) { + string valid_name = NameTable.name_validation (name, false, 0xFF); + + if (valid_name.char_count () == 1) { + warning (@"Too short name: $valid_name generated from $name"); + valid_name = add_suffix (valid_name); + } + + if (names.index_of (valid_name) > -1) { + valid_name = add_suffix (valid_name); + } + + return valid_name; + } + + string add_suffix (string valid_name) { + int i = 2; + string s; + + s = valid_name + @"_$i"; + while (names.index_of (s) > -1) { + i++; + s = valid_name + @"_$i"; + } + + return s; + } } }
--- a/libbirdfont/OverView.vala +++ b/libbirdfont/OverView.vala @@ -20,7 +20,7 @@ public class OverView : FontDisplay { public WidgetAllocation allocation = new WidgetAllocation (); - OverViewItem selected_item = new OverViewItem (null, '\0', 0, 0); + public OverViewItem selected_item = new OverViewItem (null, '\0', 0, 0); public Gee.ArrayList<GlyphCollection> copied_glyphs = new Gee.ArrayList<GlyphCollection> (); public Gee.ArrayList<GlyphCollection> selected_items = new Gee.ArrayList<GlyphCollection> (); @@ -1347,7 +1347,7 @@ if (((!)character_info).is_ligature ()) { name = ((!)character_info).get_name (); - draw_info_line (t_("Ligature") + ": " + name, cr, x, y, 0); + draw_info_line (name, cr, x, y, 0); } else { i = 0; foreach (string line in lines) {
--- a/libbirdfont/OverviewTools.vala +++ b/libbirdfont/OverviewTools.vala @@ -31,12 +31,15 @@ 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")); Expander zoom_expander = new Expander (t_("Zoom")); Expander transform_expander = new Expander (t_("Transform")); + Expander glyph_expander = new Expander (t_("Glyph")); expanders = new Gee.ArrayList<Expander> (); custom_character_sets = new Gee.ArrayList<LabelTool> (); @@ -126,11 +129,60 @@ transform.selected = false; transform.set_persistent (false); transform_expander.add_tool (transform); + + Tool alternate = new Tool ("alternate", t_("Create alternate")); + alternate.select_action.connect (add_new_alternate); + glyph_expander.add_tool (alternate); expanders.add (font_name); expanders.add (zoom_expander); expanders.add (character_sets); expanders.add (transform_expander); + expanders.add (glyph_expander); + } + + 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) { + 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 == "") { + 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); } public void process_transform () {
--- a/libbirdfont/StrokeTool.vala +++ b/libbirdfont/StrokeTool.vala @@ -124,6 +124,7 @@ foreach (Path p in g.active_paths) { p.close (); + p.remove_points_on_points (); o.add (p); }
--- a/resources/icons.bf +++ b/resources/icons.bf @@ -2,5 +2,5 @@ <font> - <format>2.0</format> + <format>2.1</format> <postscript_name>BirdfontIcons</postscript_name> <name>Birdfont Icons</name> @@ -13,8 +13,15 @@ <description>An icon font for the font editor Birdfont.</description> <copyright>Copyright 2015 GNU Lesser General Public License</copyright> + <license></license> + <license_url></license_url> <weight>400</weight> <units_per_em>1024</units_per_em> + <trademark></trademark> + <manufacturer></manufacturer> + <designer></designer> + <vendor_url></vendor_url> + <designer_url></designer_url> <horizontal> <top_limit>84.0000000000</top_limit> @@ -289,6 +296,21 @@ <layer name= "Layer" visible="true"> <path data="S -16.0000000000,30.5449735450 L 20.0000000000,30.5449735450 L 20.0000000000,26.5449735450 L -16.0000000000,26.5449735450 L -16.0000000000,30.5449735450" /> <path data="S 0.0000000000,46.5449735450 L 4.0000000000,46.5449735450 L 4.0000000000,10.5449735450 L 0.0000000000,10.5449735450 L 0.0000000000,46.5449735450" /> + </layer> + </glyph> + </collection> + <collection name="alternate"> + <selected id="0"/> + <glyph id="0" left="-28" right="28"> + <layer name= "Layer" visible="true"> + <path data="B 3.6759014745,40.7567512767 C 3.6759014745,40.7567512767 3.6759014745,40.7567512767 3.6759014745,40.7567512767 C 3.6759014745,40.7567512767 3.2688257643,40.8457013235 3.0652879094,40.8901763469 C 2.8617500543,40.9346513703 2.6582121992,40.9791263937 2.4546743442,41.0236014172 C 1.5642251139,41.2181733328 0.6737758836,41.4127452485 -0.2166733467,41.6073171642 C -0.0994455563,42.1438046394 0.0177822341,42.6802921146 0.1350100246,43.2167795898 C 1.0254592549,43.0222076741 1.9159084853,42.8276357584 2.8063577155,42.6330638427 C 3.4169712807,42.4996387725 4.0275848458,42.3662137022 4.6381984109,42.2327886320 C 5.4654639795,42.0520229679 6.2927295481,41.8712573040 7.1199951168,41.6904916405 C 7.1582621678,41.4790581417 7.1965292188,41.2676246430 7.2347962697,41.0561911442 C 4.6535421192,39.3891160541 2.0722879687,37.7220409638 -0.5089661818,36.0549658736 C -2.0599617587,35.0532721462 -3.6109573357,34.0515784188 -5.1619529127,33.0498846913 C -6.3196453115,32.3022015700 -7.4773377103,31.5545184487 -8.6350301092,30.8068353274 C -8.9329576056,31.2681382352 -9.2308851020,31.7294411430 -9.5288125985,32.1907440508 C -8.3711201996,32.9384271721 -7.2134278008,33.6861102935 -6.0557354020,34.4337934149 C -4.5047398250,35.4354871422 -2.9537442480,36.4371808696 -1.4027486711,37.4388745971 C -0.3687516197,38.1066704153 0.6652454316,38.7744662336 1.6992424829,39.4422620519 C 3.3981499084,40.5394830478 2.7542954653,40.0795161653 3.6759014745,40.7567512767" /> + <path data="B 3.2646352148,35.0697188780 C 3.4529797567,35.5741584754 3.6413242987,36.0785980728 3.8296688407,36.5830376702 C 4.0819997291,37.2588506799 4.3343306176,37.9346636897 4.5866615060,38.6104766994 C 4.9546321149,39.5960053688 5.3226027239,40.5815340382 5.6905733328,41.5670627076 C 6.2050291379,41.3749783758 6.7194849431,41.1828940441 7.2339407481,40.9908097123 C 6.8659701392,40.0052810430 6.4979995302,39.0197523735 6.1300289212,38.0342237042 C 5.8776980328,37.3584106944 5.6253671444,36.6825976847 5.3730362559,36.0067846750 C 5.1846917140,35.5023450776 4.9963471720,34.9979054802 4.8080026300,34.4934658828 M 3.2646352148,35.0697188780" /> + <path data="B 2.2039994470,16.7446012982 C 1.1700023957,17.4123971165 0.1360053444,18.0801929348 -0.8979917070,18.7479887530 C -2.4489872839,19.7496824805 -3.9999828608,20.7513762078 -5.5509784378,21.7530699352 C -6.7086708366,22.5007530566 -7.8663632355,23.2484361780 -9.0240556343,23.9961192993 C -8.7261281379,24.4574222071 -8.4282006415,24.9187251149 -8.1302731450,25.3800280227 C -6.9725807462,24.6323449014 -5.8148883474,23.8846617800 -4.6571959485,23.1369786587 C -3.1062003716,22.1352849313 -1.5552047946,21.1335912039 -0.0042092177,20.1318974764 C 2.5770449328,18.4648223862 5.1582990833,16.7977472960 7.7395532338,15.1306722059 C 7.7012861829,14.9192387071 7.6630191319,14.7078052084 7.6247520809,14.4963717096 C 6.7974865122,14.3156060461 5.9702209436,14.1348403822 5.1429553751,13.9540747181 C 4.5323418099,13.8206496478 3.9217282448,13.6872245776 3.3111146797,13.5537995074 C 2.4206654494,13.3592275916 1.5302162190,13.1646556760 0.6397669887,12.9700837603 C 0.5225391983,13.5065712355 0.4053114078,14.0430587107 0.2880836174,14.5795461859 C 1.1785328477,14.7741181016 2.0689820780,14.9686900172 2.9594313083,15.1632619329 C 3.1629691634,15.2077369563 3.3665070184,15.2522119798 3.5700448735,15.2966870031 C 3.7735827285,15.3411620266 4.1806584386,15.4301120734 4.1806584386,15.4301120734 C 4.1806584386,15.4301120734 4.1806584386,15.4301120734 4.1806584386,15.4301120734 C 3.2590524294,16.1073471848 3.9029068725,15.6473803023 2.2039994470,16.7446012982" /> + <path data="B 5.3127595942,21.6933974673 C 5.5011041361,21.1889578699 5.6894486781,20.6845182725 5.8777932201,20.1800786751 C 6.1301241085,19.5042656654 6.3824549969,18.8284526557 6.6347858854,18.1526396459 C 7.0027564944,17.1671109765 7.3707271033,16.1815823071 7.7386977122,15.1960536378 C 7.2242419072,15.0039693059 6.7097861021,14.8118849742 6.1953302969,14.6198006425 C 5.8273596881,15.6053293119 5.4593890791,16.5908579813 5.0914184701,17.5763866507 C 4.8390875817,18.2521996604 4.5867566933,18.9280126702 4.3344258048,19.6038256798 C 4.1460812628,20.1082652772 3.9577367209,20.6127048746 3.7693921789,21.1171444720 M 5.3127595942,21.6933974673" /> + <path data="S 27.5084977672,39.1601233077 L 9.3282139024,39.1601233077 L 18.4183558348,54.3103598617 L 27.5084977672,39.1601233077" /> + <path data="S 12.6997545643,14.7606495448 L 26.0573543453,14.7606495448 L 26.0573543453,1.4030497638 L 12.6997545643,1.4030497638 L 12.6997545643,14.7606495448" /> + <path data="B -14.3764353493,31.3046892257 C -14.1272616411,31.0346434605 -14.3764353493,31.3046892257 -14.3764353493,31.3046892257 C -14.1272616411,31.0346434605 -14.0672089911,30.9837086223 -13.8623329216,30.7178020715 C -13.6065849730,30.3858694303 -13.3977455777,30.0306253113 -13.2027179830,29.6608065126 C -13.0834737539,29.4072882220 -13.0542515682,29.3558890569 -12.9517101422,29.0949722124 C -12.8473697454,28.8294778835 -12.7666783102,28.5595814714 -12.6911935158,28.2848694529 C -12.6139755421,27.9494662774 -12.5427105763,27.6104930915 -12.5213814882,27.2659421275 C -12.5110855591,27.0996212675 -12.5075550732,26.9329505830 -12.5006429073,26.7664547674 C -12.4741698843,26.1287895730 -12.6196005716,25.4801529704 -12.7976349746,24.8731900560 C -12.8925515717,24.5941502305 -12.9922946818,24.3201193128 -13.1161646890,24.0522817354 C -13.2260276858,23.8147307772 -13.2586845368,23.7634915666 -13.3835241233,23.5338107416 C -13.5142093436,23.3170031222 -13.5495490952,23.2498149588 -13.6951323087,23.0425093010 C -13.9014177387,22.7487657045 -14.1322563101,22.4723797944 -14.3861690503,22.2184713483 C -14.3861690503,22.2184713483 -14.3861690503,22.2184713483 -14.3861690503,22.2184713483 C -14.6586427044,21.9668135753 -14.7094597969,21.9065576513 -14.9770103728,21.7004148908 C -15.3089430141,21.4446669422 -15.6641871329,21.2358275469 -16.0340059317,21.0407999522 C -16.2875242223,20.9215557231 -16.3389233873,20.8923335374 -16.5998402319,20.7897921114 C -16.8653345608,20.6854517145 -17.1352309730,20.6047602794 -17.4099429913,20.5292754850 C -17.6420181068,20.4758461454 -17.6937924431,20.4601222088 -17.9284189764,20.4212356465 C -18.2661838671,20.3652551259 -18.6078402959,20.3387210585 -18.9503607179,20.3387251387 C -19.2383021519,20.3488920775 -19.5195034719,20.3606717249 -19.8046594476,20.4020676429 C -20.1511584759,20.4523686941 -20.4861238421,20.5373084875 -20.8216223882,20.6357169438 C -21.1006622137,20.7306335409 -21.3746931316,20.8303766510 -21.6425307088,20.9542466582 C -21.8800816670,21.0641096550 -21.9313208776,21.0967665060 -22.1610017027,21.2216060925 C -22.8657201499,21.6463895285 -23.4900758435,22.1605383637 -23.9943975534,22.8150923420 C -24.2501455021,23.1470249833 -24.4589848974,23.5022691021 -24.6540124921,23.8720879009 C -24.7732567212,24.1256061915 -24.8024789068,24.1770053565 -24.9050203329,24.4379222011 C -25.0093607298,24.7034165300 -25.0900521649,24.9733129422 -25.1655369593,25.2480249606 C -25.2427549329,25.5834281361 -25.3140198987,25.9224013221 -25.3353489869,26.2669522861 C -25.3456449160,26.4332731461 -25.3491754019,26.5999438306 -25.3560875677,26.7664396462 C -25.3825605908,27.4041048406 -25.2371299035,28.0527414431 -25.0590955006,28.6597043575 C -24.9641789034,28.9387441830 -24.8644357933,29.2127751008 -24.7405657860,29.4806126780 C -24.6307027893,29.7181636362 -24.5980459383,29.7694028468 -24.4732063518,29.9990836719 C -24.0484229157,30.7038021191 -23.5342740805,31.3281578127 -22.8797201023,31.8324795226 C -22.5477874611,32.0882274713 -22.1925433421,32.2970668666 -21.8227245434,32.4920944612 C -21.5692062528,32.6113386904 -21.5178070877,32.6405608760 -21.2568902432,32.7431023021 C -20.9913959142,32.8474426990 -20.7214995021,32.9281341340 -20.4467874838,33.0036189285 C -19.9444942582,33.1192590532 -19.4456317544,33.1941456522 -18.9281289485,33.1941695482 C -19.0615567624,33.1941616876 -18.7817245277,33.1941803462 -18.5290552687,33.1808466582 C -18.4492515689,33.1766353124 -18.3696554484,33.1688284483 -18.2901765298,33.1604937357 C -17.8615408487,33.1155440146 -17.4478902965,33.0182547753 -17.0351080868,32.8971774698 C -16.7560682612,32.8022608725 -16.4820373435,32.7025177625 -16.2141997662,32.5786477552 C -15.9766488081,32.4687847585 -15.9254095974,32.4361279075 -15.6957287724,32.3112883210 C -15.4789211530,32.1806031007 -15.4117329896,32.1452633491 -15.2044273318,31.9996801355 C -14.9090523118,31.7922490161 -14.6317498598,31.5600107261 -14.3764353493,31.3046892257" /> + <path data="B -18.9259276385,24.0104388377 C -18.8046174118,24.0135980089 -18.9259276385,24.0104388377 -18.9259276385,24.0104388377 C -18.8046174118,24.0135980089 -18.7895247346,24.0113370207 -18.6803238825,24.0224357941 C -18.5727282364,24.0333714204 -18.4676550533,24.0533874806 -18.3619012191,24.0754366886 C -18.2374201695,24.1070775771 -18.1152043773,24.1413046993 -17.9946933055,24.1862415298 C -17.8710993530,24.2323279219 -17.8450635053,24.2462044492 -17.7257894863,24.2995346995 C -17.5673564620,24.3789047134 -17.4140554414,24.4631561222 -17.2705058271,24.5677067054 C -17.1433733797,24.6603002773 -17.1298221759,24.6809132511 -16.9916660133,24.8055623986 C -16.8993966054,24.8978293907 -16.8140898319,24.9942820306 -16.7366029173,25.0994342600 C -16.6725650915,25.1863356443 -16.6568424804,25.2149165372 -16.5988440467,25.3067183927 C -16.5401191335,25.4099037221 -16.5247307878,25.4329811180 -16.4725372872,25.5409881308 C -16.4117993993,25.6666765357 -16.3622217592,25.7955026614 -16.3149699723,25.9266786714 C -16.2508930951,26.1311950863 -16.1938361129,26.3419004728 -16.1807670823,26.5570108897 C -16.1646931863,26.8215800497 -16.1832607650,27.0734623105 -16.2373547194,27.3329112251 C -16.2689956079,27.4573922748 -16.3032227301,27.5796080669 -16.3481595606,27.7001191387 C -16.3942459527,27.8237130913 -16.4081224800,27.8497489390 -16.4614527303,27.9690229580 C -16.5408227442,28.1274559822 -16.6250741530,28.2807570028 -16.7296247362,28.4243066171 C -16.8206048871,28.5492238119 -16.8410048697,28.5630887605 -16.9621223719,28.6977882466 C -16.9621223719,28.6977882466 -16.9621223719,28.6977882466 -16.9621223719,28.6977882466 C -17.0561984914,28.7918667568 -17.1541146194,28.8791858454 -17.2613522908,28.9582095270 C -17.3482536751,29.0222473528 -17.3768345680,29.0379699639 -17.4686364235,29.0959683975 C -17.5718217529,29.1546933109 -17.5948991488,29.1700816565 -17.7029061616,29.2222751571 C -17.8285945666,29.2830130450 -17.9574206922,29.3325906850 -18.0885967022,29.3798424720 C -18.2642832198,29.4348866767 -18.4402738831,29.4809525247 -18.6233123712,29.5039237226 C -18.7457715276,29.5192922582 -18.7648818498,29.5160165691 -18.9149831952,29.5224553501 C -18.9149831952,29.5224553501 -18.9149831952,29.5224553501 -18.9149831952,29.5224553501 C -19.0364241594,29.5224569827 -19.1567059786,29.5155674129 -19.2768909645,29.4981929740 C -19.3751994278,29.4839810957 -19.3974435550,29.4777622140 -19.4948292559,29.4574577249 C -19.6193103056,29.4258168363 -19.7415260977,29.3915897142 -19.8620371695,29.3466528836 C -19.9856311220,29.3005664916 -20.0116669698,29.2866899642 -20.1309409888,29.2333597139 C -20.2893740130,29.1539897001 -20.4426750336,29.0697382912 -20.5862246479,28.9651877080 C -20.7152618546,28.8712068550 -20.7286255721,28.8503308051 -20.8697642344,28.7226323597 C -20.8697642344,28.7226323597 -20.8697642344,28.7226323597 -20.8697642344,28.7226323597 C -20.9604360648,28.6319629710 -21.0439963691,28.5367726193 -21.1201275578,28.4334601534 C -21.1841653836,28.3465587692 -21.1998879947,28.3179778764 -21.2578864283,28.2261760208 C -21.3166113416,28.1229906914 -21.3319996874,28.0999132956 -21.3841931879,27.9919062827 C -21.4449310758,27.8662178777 -21.4945087158,27.7373917520 -21.5417605028,27.6062157420 C -21.6058373799,27.4016993272 -21.6628943621,27.1909939407 -21.6759633928,26.9758835238 C -21.6920372888,26.7113143638 -21.6734697101,26.4594321030 -21.6193757557,26.1999831883 C -21.5877348671,26.0755021387 -21.5535077450,25.9532863465 -21.5085709144,25.8327752747 C -21.4624845224,25.7091813222 -21.4486079950,25.6831454745 -21.3952777447,25.5638714555 C -21.2974394117,25.3685732284 -21.1912709053,25.1727778876 -21.0482280606,25.0059528978 C -20.9940830337,24.9428057785 -20.9364735939,24.8827136604 -20.8805963606,24.8210940417 C -20.8805963606,24.8210940417 -20.8805963606,24.8210940417 -20.8805963606,24.8210940417 C -20.7912819596,24.7317780594 -20.6971317251,24.6496672998 -20.5953781843,24.5746848865 C -20.5084768000,24.5106470607 -20.4798959072,24.4949244496 -20.3880940516,24.4369260159 C -20.2849087222,24.3782011027 -20.2618313263,24.3628127570 -20.1538243135,24.3106192564 C -20.0281359085,24.2498813685 -19.8993097828,24.2003037284 -19.7681337728,24.1530519415 C -19.6626218253,24.1199940762 -19.6417579038,24.1116518118 -19.5366087518,24.0855193231 C -19.3366033702,24.0358124232 -19.1321438606,24.0104426854 -18.9259276385,24.0104388377" /> </layer> </glyph> </collection> @@ -1605,6 +1627,7 @@ <ligature sequence="i n f o _ i c o n" replacement="info_icon"/> <ligature sequence="s a v e _ f o n t" replacement="save_font"/> <ligature sequence="l o c k _ g r i d" replacement="lock_grid"/> + <ligature sequence="a l t e r n a t e" replacement="alternate"/> <ligature sequence="n e w _ f o n t" replacement="new_font"/> <ligature sequence="p r o g r e s s" replacement="progress"/> <ligature sequence="z o o m _ 1 _ 1" replacement="zoom_1_1"/>