Commit d7653df
Generate stylistic alternates and fix PostScript names
Changed files (19)
modifiedlibbirdfont/Font.valamodifiedlibbirdfont/GlyphCollection.valaaddedlibbirdfont/OpenFontFormat/Alternate.valamodifiedlibbirdfont/OpenFontFormat/AlternateFeature.valamodifiedlibbirdfont/OpenFontFormat/CligFeature.valaaddedlibbirdfont/OpenFontFormat/Feature.valaaddedlibbirdfont/OpenFontFormat/FeatureList.valamodifiedlibbirdfont/OpenFontFormat/GlyfTable.valamodifiedlibbirdfont/OpenFontFormat/GsubTable.valamodifiedlibbirdfont/OpenFontFormat/HheaTable.valamodifiedlibbirdfont/OpenFontFormat/LigatureCollection.valamodifiedlibbirdfont/OpenFontFormat/Lookup.valamodifiedlibbirdfont/OpenFontFormat/Lookups.valamodifiedlibbirdfont/OpenFontFormat/NameTable.valamodifiedlibbirdfont/OpenFontFormat/PostTable.valamodifiedlibbirdfont/OverView.valamodifiedlibbirdfont/OverviewTools.valamodifiedlibbirdfont/StrokeTool.valamodifiedresources/icons.bf
Diff
@@ -35,6 +35,9 @@ public class Font : GLib.Object { /** 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 @@ public class Font : GLib.Object { bool modified = false; - // name table descriptions+ // name table strings public string postscript_name; public string name; public string subfamily;@@ -175,12 +178,41 @@ public class Font : GLib.Object { 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 () { return !newer_format () && !older_format (); }@@ -540,6 +572,10 @@ public class Font : GLib.Object { 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); }@@ -37,6 +37,7 @@ public class GlyphCollection : GLib.Object { g = new Glyph (name, unicode_character); glyphs.add (g);+ set_selected (g); } public void remove (int index) {new file mode 100644@@ -0,0 +1,47 @@+/*+ 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);+ }+ }+ +}++}@@ -11,18 +11,84 @@ 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; } } @@ -26,6 +26,10 @@ public class CligFeature : GLib.Object { generate_feature (); } + public bool has_regular_ligatures () {+ return clig.ligature_sets.size > 0;+ }+ public Lookups get_lookups () { return lookups; }new file mode 100644@@ -0,0 +1,39 @@+/*+ 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;+ }+}++}new file mode 100644@@ -0,0 +1,58 @@+/*+ 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;+ }+}++}@@ -144,7 +144,7 @@ public class GlyfTable : OtfTable { 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 @@ public class GlyfTable : OtfTable { // 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);@@ -32,12 +32,46 @@ public class GsubTable : OtfTable { 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 @@ public class GsubTable : OtfTable { 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,4 +112,3 @@ public class GsubTable : OtfTable { } }-@@ -86,7 +86,7 @@ public class HheaTable : OtfTable { 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 @@ -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 { @@ -33,6 +33,10 @@ public class Lookup : GLib.Object { } public uint get_lookup_entry_size () throws GLib.Error {+ if (subtables.size == 0) {+ warning ("No subtables.");+ }+ return 6 + 2 * subtables.size; } @@ -23,8 +23,9 @@ public class Lookups : GLib.Object { 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 class Lookups : GLib.Object { } } - 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;@@ -149,7 +149,9 @@ public class NameTable : OtfTable { 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 @@ public class NameTable : OtfTable { 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 @@ public class NameTable : OtfTable { 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;@@ -20,125 +20,11 @@ public class PostTable : OtfTable { 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 private void add_standard_names () {@@ -1188,7 +1074,8 @@ public class PostTable : OtfTable { int name_index; GlyphCollection gc; Glyph g;- + string ps_name;+ fd.add_fixed (0x00020000); // Version fd.add_fixed (0x00000000); // italicAngle @@ -1214,19 +1101,23 @@ public class PostTable : OtfTable { 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 @@ public class PostTable : OtfTable { if (n.length > 0xFF) { warning (@"too long name for glyph $n");+ continue; } fd.add ((uint8) n.length);@@ -1248,6 +1140,33 @@ public class PostTable : OtfTable { 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;+ } } }@@ -20,7 +20,7 @@ namespace BirdFont { 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 @@ public class OverView : FontDisplay { 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) {@@ -32,11 +32,14 @@ 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")); 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> ();@@ -127,10 +130,59 @@ public class OverviewTools : ToolCollection { 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 () {@@ -124,6 +124,7 @@ public class StrokeTool : Tool { foreach (Path p in g.active_paths) { p.close ();+ p.remove_points_on_points (); o.add (p); } @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <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>@@ -292,6 +299,21 @@ GNU Lesser General Public License</copyright> </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> <collection name="apply_stroke"> <selected id="1"/> <glyph id="1" left="-26.53515625" right="29.796903565002076">@@ -1605,6 +1627,7 @@ GNU Lesser General Public License</copyright> <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"/>