Commit 7bcd266
Merge branch 'master' of github.com:johanmattssonm/birdfont
Changed files (31)
modifiedlibbirdfont/AlternateSets.valamodifiedlibbirdfont/BirdFont.valaaddedlibbirdfont/ExportUtils.valamodifiedlibbirdfont/GlyphCanvas.valaaddedlibbirdfont/ImportUtils.valamodifiedlibbirdfont/KerningDisplay.valamodifiedlibbirdfont/KerningTools.valamodifiedlibbirdfont/LoadCallback.valamodifiedlibbirdfont/MenuTab.valamodifiedlibbirdfont/OpenFontFormat/Alternate.valamodifiedlibbirdfont/OpenFontFormat/CffTable.valamodifiedlibbirdfont/OtfFeatureTable.valamodifiedlibbirdfont/OtfLabel.valamodifiedlibbirdfont/OverView.valamodifiedlibbirdfont/OverViewItem.valamodifiedlibbirdfont/OverviewTools.valamodifiedlibbirdfont/Path.valamodifiedlibbirdfont/PenTool.valamodifiedlibbirdfont/RecentFiles.valamodifiedlibbirdfont/SaveCallback.valamodifiedlibbirdfont/SpacingTab.valaaddedlibbirdfont/StrokeTask.valamodifiedlibbirdfont/StrokeTool.valamodifiedlibbirdfont/TabBar.valamodifiedlibbirdfont/TabContent.valamodifiedlibbirdfont/Task.valamodifiedlibbirdfont/Toolbox.valamodifiedlibbirdfont/VersionList.valamodifiedlibbirdfont/ZoomBar.valamodifiedlibbirdgems/GGVecLib.cmodifiedscripts/version.py
Diff
@@ -32,6 +32,10 @@ public class AlternateSets : GLib.Object { } } + tags.sort ((a, b) => {+ return strcmp ((string) a, (string) b);+ });+ return tags; } @@ -48,6 +52,18 @@ public class AlternateSets : GLib.Object { return alt; } + public void remove_empty_sets () {+ int i = 0;+ foreach (Alternate a in alternates) {+ if (a.is_empty ()) {+ alternates.remove_at (i);+ remove_empty_sets ();+ return;+ }+ i++;+ }+ }+ public void add (Alternate alternate) { alternates.add (alternate); }@@ -61,4 +77,18 @@ public class AlternateSets : GLib.Object { } } +public class AlternateItem : GLib.Object {+ public Alternate alternate_list;+ public string alternate;+ + public AlternateItem (Alternate alternate_list, string alternate) {+ this.alternate_list = alternate_list;+ this.alternate = alternate;+ }+ + public void delete_item_from_list () {+ alternate_list.remove_alternate (alternate);+ }+}+ }@@ -19,295 +19,15 @@ namespace BirdFont { public static string? settings_directory = null; -static void print_import_help (string[] arg) {- stdout.printf (t_("Usage:"));- stdout.printf (arg[0]);- stdout.printf (" " + t_("BF-FILE") + " " + t_("SVG-FILES ...") +"\n");- stdout.printf ("\n");-}--public static int run_import (string[] arg) {- string bf_file = "";- Gee.ArrayList<string> svg_files = new Gee.ArrayList<string> ();- File bf;- File svg;- Font font;- bool imported;- - Theme.set_default_colors ();- Preferences.load ();- BirdFont.args = new Argument ("");- BirdFont.current_font = new Font ();- BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ('\0', "");- MainWindow.init ();-- if (arg.length < 3) {- print_import_help (arg);- return -1;- }- - bf_file = build_absoulute_path (arg[1]);- - for (int i = 2; i < arg.length; i++) {- svg_files.add (arg[i]);- }- - bf = File.new_for_path (bf_file);- foreach (string f in svg_files) {- svg = File.new_for_path (f);- - if (!svg.query_exists ()) {- stdout.printf (@"$f " + t_("does not exist.") + "\n");- return -1;- }- }- - font = BirdFont.get_current_font ();-- if (!bf.query_exists ()) {- stdout.printf (@"$bf_file " + t_("does not exist.") + " ");- stdout.printf (t_("A new font will be created.") + "\n");- font.set_file (bf_file);- } else {- font.set_file (bf_file);- if (!font.load ()) {- warning (@"Failed to load font $bf_file.\n");- - if (!bf_file.has_suffix (".bf")) {- warning (@"Is it a .bf file?\n");- }- - return -1;- }- }-- font.save_backup ();-- foreach (string f in svg_files) {- svg = File.new_for_path (f);- imported = import_svg_file (font, svg);- - if (!imported) {- stdout.printf (t_("Failed to import") + " " + f + "\n");- stdout.printf (t_("Aborting") + "\n");- return -1;- }- }- - font.save_bf ();- - return 0;-}- internal static string build_absoulute_path (string file_name) { File f = File.new_for_path (file_name); return (!) f.get_path (); } -static bool import_svg_file (Font font, File svg_file) {- string file_name = (!) svg_file.get_basename ();- string glyph_name;- StringBuilder n;- Glyph glyph;- GlyphCollection? gc = null;- GlyphCollection glyph_collection;- unichar character;- GlyphCanvas canvas;- - glyph_name = file_name.replace (".svg", "");- glyph_name = glyph_name.replace (".SVG", "");- - if (glyph_name.char_count () > 1) {- if (glyph_name.has_prefix ("U+")) {- n = new StringBuilder ();- n.append_unichar (Font.to_unichar (glyph_name));- glyph_name = n.str;- gc = font.get_glyph_collection (glyph_name);- } else {- gc = font.get_glyph_collection_by_name (glyph_name);- - if (gc == null) {- stdout.printf (file_name + " " + t_("is not the name of a glyph or a Unicode value.") + "\n");- stdout.printf (t_("Unicode values must start with U+.") + "\n");- return false;- }- } - } else {- gc = font.get_glyph_collection (glyph_name);- }-- if (gc != null) {- glyph_collection = (!) gc;- character = glyph_collection.get_unicode_character ();- glyph = new Glyph (glyph_collection.get_name (), character);- glyph.version_id = glyph_collection.get_last_id () + 1;- glyph_collection.insert_glyph (glyph, true);- } else {- return_val_if_fail (glyph_name.char_count () == 1, false);- character = glyph_name.get_char (0);- glyph_collection = new GlyphCollection (character, glyph_name);- glyph = new Glyph (glyph_name, character);- glyph_collection.insert_glyph (glyph, true);- font.add_glyph_collection (glyph_collection);- }-- canvas = MainWindow.get_glyph_canvas ();- canvas.set_current_glyph_collection (glyph_collection);-- stdout.printf (t_("Adding"));- stdout.printf (" ");- stdout.printf ((!) svg_file.get_basename ());- stdout.printf (" ");- stdout.printf (t_("to"));- stdout.printf (" ");- stdout.printf (t_("Glyph"));- stdout.printf (": ");- stdout.printf (glyph.get_name ());- stdout.printf (" ");- stdout.printf (t_("Version"));- stdout.printf (": ");- stdout.printf (@"$(glyph.version_id)");- stdout.printf ("\n");- - SvgParser.import_svg ((!) svg_file.get_path ());- - return true;-}--static void print_export_help (string[] arg) {- stdout.printf (t_("Usage:"));- stdout.printf (arg[0]);- stdout.printf (" [" + t_("OPTION") + "...] " + t_("FILE") +"\n");- stdout.printf ("-h, --help " + t_("print this message") + "\n");- stdout.printf ("-o, --output [DIRECTORY] " + t_("write files to this directory") + "\n");- stdout.printf ("-s, --svg " + t_("write svg file") + "\n");- stdout.printf ("-t, --ttf " + t_("write ttf and eot file") + "\n");- stdout.printf ("\n");-}- public static string get_version () { return VERSION; } -public static int run_export (string[] arg) {- string output_directory = ".";- string file_name = "";- bool specific_formats = false; - bool write_ttf = false;- bool write_svg = false; - File directory;- Font font;- MainWindow main_window;-- stdout.printf ("birdfont-export version %s\n", VERSION);-- if (arg.length < 2) {- print_export_help (arg);- return -1;- }-- Theme.set_default_colors ();- BirdFont.current_font = BirdFont.new_font ();- BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ( '\0', "null");- main_window = new MainWindow ();- - // FIXME: create a option for this and add structure the log messages- - if (BirdFont.logging) {- init_logfile ();- }- - for (int i = 1; i < arg.length; i++) {-- if (arg[i] == "-f" || arg[i] == "--fatal-warnings") {- BirdFont.fatal_wanings = true;- return 0;- }-- if (arg[i] == "-h" || arg[i] == "--help") {- print_export_help (arg);- return 0;- }- - if ((arg[i] == "-o" || arg[i] == "--output") && i + 1 < arg.length) {- output_directory = arg[i + 1];- i++;- continue;- }-- if (arg[i] == "-s" || arg[i] == "--svg") {- write_svg = true;- specific_formats = true;- continue;- }- - if (arg[i] == "-t" || arg[i] == "--ttf") {- write_ttf = true;- specific_formats = true;- continue;- }- - if (arg[i].has_prefix ("-")) {- print_export_help (arg);- return 1;- }- - if (!arg[i].has_prefix ("-")) {- file_name = arg[i];- - if (i != arg.length - 1) {- print_export_help (arg);- return 1;- }- - break;- }- }-- if (BirdFont.fatal_wanings) {- LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;- Log.set_handler (null, levels, BirdFont.fatal_warning); - }- - Preferences.load ();- - BirdFont.args = new Argument ("");- BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ('\0', "");- - file_name = build_absoulute_path (file_name);- - font = BirdFont.get_current_font ();- font.set_file (file_name);- if (!font.load ()) {- warning (@"Failed to load font $file_name.\n");- - if (!file_name.has_suffix (".bf")) {- warning (@"Is it a .bf file?\n");- }- - return 1;- }-- directory = File.new_for_path (output_directory);- - if (!directory.query_exists ()) {- stderr.printf (t_("Can't find output directory") + @"$((!)directory.get_path ())\n");- return 1;- }-- if (!specific_formats || write_svg) {- print (@"Writing $(ExportSettings.get_file_name (font)).svg to $output_directory\n");- ExportTool.export_svg_font_path (File.new_for_path (output_directory));- }-- if (!specific_formats || write_ttf) {- print (@"Writing $(ExportSettings.get_file_name (font)).ttf to $output_directory\n");- ExportTool.export_ttf_font_path (File.new_for_path (output_directory));- }- - return 0;-}- public static void set_logging (bool log) { BirdFont.logging = log; }@@ -365,7 +85,7 @@ public class BirdFont { public static string exec_path = ""; public static string? bundle_path = null; - public static bool logging = false;+ internal static bool logging = false; public static DataOutputStream? logstream = null; public static Font current_font;@@ -540,6 +260,16 @@ public class BirdFont { } } + public static bool has_logging () {+ bool log;+ + lock (BirdFont.logging) {+ log = BirdFont.logging;+ }+ + return log;+ }+ public static Argument get_arguments () { return args; }@@ -683,7 +413,23 @@ public class BirdFont { internal static string? get_argument (string param) { return args.get_argument (param);- } + }+ + public static void debug_message (string s) {+ if (unlikely (has_logging ())) {+ try {+ if (BirdFont.logstream != null) {+ ((!)BirdFont.logstream).put_string (s);+ } else {+ warning ("No logstream.");+ }+ + stderr.printf (s);+ } catch (GLib.Error e) {+ warning (e.message);+ }+ }+ } } void init_logfile () {@@ -732,27 +478,7 @@ public static void printd (string s) { #if ANDROID __android_log_print (ANDROID_LOG_WARN, "BirdFont", s); #else- IdleSource idle = new IdleSource ();-- idle.set_callback (() => {- if (unlikely (BirdFont.logging)) {- try {- if (BirdFont.logstream != null) {- ((!)BirdFont.logstream).put_string (s);- } else {- warning ("No logstream.");- }- - stderr.printf (s);- } catch (GLib.Error e) {- warning (e.message);- }- }- - return false;- });- - idle.attach (null);+ BirdFont.debug_message (s); #endif } new file mode 100644@@ -0,0 +1,147 @@+/*+ Copyright (C) 2012 2014 Johan Mattsson++ This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details.+*/+namespace BirdFont {++static void print_export_help (string[] arg) {+ stdout.printf (t_("Usage:"));+ stdout.printf (arg[0]);+ stdout.printf (" [" + t_("OPTION") + "...] " + t_("FILE") +"\n");+ stdout.printf ("-h, --help " + t_("print this message") + "\n");+ stdout.printf ("-o, --output [DIRECTORY] " + t_("write files to this directory") + "\n");+ stdout.printf ("-s, --svg " + t_("write svg file") + "\n");+ stdout.printf ("-t, --ttf " + t_("write ttf and eot file") + "\n");+ stdout.printf ("\n");+}+++public static int run_export (string[] arg) {+ string output_directory = ".";+ string file_name = "";+ bool specific_formats = false; + bool write_ttf = false;+ bool write_svg = false; + File directory;+ Font font;+ MainWindow main_window;++ stdout.printf ("birdfont-export version %s\n", VERSION);++ if (arg.length < 2) {+ print_export_help (arg);+ return -1;+ }++ Theme.set_default_colors ();+ BirdFont.current_font = BirdFont.new_font ();+ BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ( '\0', "null");+ main_window = new MainWindow ();+ + // FIXME: create a option for this and add structure the log messages+ + if (BirdFont.has_logging ()) {+ init_logfile ();+ }+ + for (int i = 1; i < arg.length; i++) {++ if (arg[i] == "-f" || arg[i] == "--fatal-warnings") {+ BirdFont.fatal_wanings = true;+ return 0;+ }++ if (arg[i] == "-h" || arg[i] == "--help") {+ print_export_help (arg);+ return 0;+ }+ + if ((arg[i] == "-o" || arg[i] == "--output") && i + 1 < arg.length) {+ output_directory = arg[i + 1];+ i++;+ continue;+ }++ if (arg[i] == "-s" || arg[i] == "--svg") {+ write_svg = true;+ specific_formats = true;+ continue;+ }+ + if (arg[i] == "-t" || arg[i] == "--ttf") {+ write_ttf = true;+ specific_formats = true;+ continue;+ }+ + if (arg[i].has_prefix ("-")) {+ print_export_help (arg);+ return 1;+ }+ + if (!arg[i].has_prefix ("-")) {+ file_name = arg[i];+ + if (i != arg.length - 1) {+ print_export_help (arg);+ return 1;+ }+ + break;+ }+ }++ if (BirdFont.fatal_wanings) {+ LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING;+ Log.set_handler (null, levels, BirdFont.fatal_warning); + }+ + Preferences.load ();+ + BirdFont.args = new Argument ("");+ BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ('\0', "");+ + file_name = build_absoulute_path (file_name);+ + font = BirdFont.get_current_font ();+ font.set_file (file_name);+ if (!font.load ()) {+ warning (@"Failed to load font $file_name.\n");+ + if (!file_name.has_suffix (".bf")) {+ warning (@"Is it a .bf file?\n");+ }+ + return 1;+ }++ directory = File.new_for_path (output_directory);+ + if (!directory.query_exists ()) {+ stderr.printf (t_("Can't find output directory") + @"$((!)directory.get_path ())\n");+ return 1;+ }++ if (!specific_formats || write_svg) {+ print (@"Writing $(ExportSettings.get_file_name (font)).svg to $output_directory\n");+ ExportTool.export_svg_font_path (File.new_for_path (output_directory));+ }++ if (!specific_formats || write_ttf) {+ print (@"Writing $(ExportSettings.get_file_name (font)).ttf to $output_directory\n");+ ExportTool.export_ttf_font_path (File.new_for_path (output_directory));+ }+ + return 0;+}++}@@ -81,7 +81,7 @@ public class GlyphCanvas : GLib.Object { } public void redraw_area (int x, int y, int w, int h) { - if (MenuTab.suppress_event) { + if (MenuTab.has_suppress_event ()) { warning ("Do not call redraw from background thread."); } else { signal_redraw_area (x, y, w, h); new file mode 100644@@ -0,0 +1,166 @@+/*+ Copyright (C) 2012 2014 Johan Mattsson++ This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version.++ This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details.+*/+namespace BirdFont {++static void print_import_help (string[] arg) {+ stdout.printf (t_("Usage:"));+ stdout.printf (arg[0]);+ stdout.printf (" " + t_("BF-FILE") + " " + t_("SVG-FILES ...") +"\n");+ stdout.printf ("\n");+}++public static int run_import (string[] arg) {+ string bf_file = "";+ Gee.ArrayList<string> svg_files = new Gee.ArrayList<string> ();+ File bf;+ File svg;+ Font font;+ bool imported;+ + Theme.set_default_colors ();+ Preferences.load ();+ BirdFont.args = new Argument ("");+ BirdFont.current_font = new Font ();+ BirdFont.current_glyph_collection = new GlyphCollection.with_glyph ('\0', "");+ MainWindow.init ();++ if (arg.length < 3) {+ print_import_help (arg);+ return -1;+ }+ + bf_file = build_absoulute_path (arg[1]);+ + for (int i = 2; i < arg.length; i++) {+ svg_files.add (arg[i]);+ }+ + bf = File.new_for_path (bf_file);+ foreach (string f in svg_files) {+ svg = File.new_for_path (f);+ + if (!svg.query_exists ()) {+ stdout.printf (@"$f " + t_("does not exist.") + "\n");+ return -1;+ }+ }+ + font = BirdFont.get_current_font ();++ if (!bf.query_exists ()) {+ stdout.printf (@"$bf_file " + t_("does not exist.") + " ");+ stdout.printf (t_("A new font will be created.") + "\n");+ font.set_file (bf_file);+ } else {+ font.set_file (bf_file);+ if (!font.load ()) {+ warning (@"Failed to load font $bf_file.\n");+ + if (!bf_file.has_suffix (".bf")) {+ warning (@"Is it a .bf file?\n");+ }+ + return -1;+ }+ }++ font.save_backup ();++ foreach (string f in svg_files) {+ svg = File.new_for_path (f);+ imported = import_svg_file (font, svg);+ + if (!imported) {+ stdout.printf (t_("Failed to import") + " " + f + "\n");+ stdout.printf (t_("Aborting") + "\n");+ return -1;+ }+ }+ + font.save_bf ();+ + return 0;+}++static bool import_svg_file (Font font, File svg_file) {+ string file_name = (!) svg_file.get_basename ();+ string glyph_name;+ StringBuilder n;+ Glyph glyph;+ GlyphCollection? gc = null;+ GlyphCollection glyph_collection;+ unichar character;+ GlyphCanvas canvas;+ + glyph_name = file_name.replace (".svg", "");+ glyph_name = glyph_name.replace (".SVG", "");+ + if (glyph_name.char_count () > 1) {+ if (glyph_name.has_prefix ("U+")) {+ n = new StringBuilder ();+ n.append_unichar (Font.to_unichar (glyph_name));+ glyph_name = n.str;+ gc = font.get_glyph_collection (glyph_name);+ } else {+ gc = font.get_glyph_collection_by_name (glyph_name);+ + if (gc == null) {+ stdout.printf (file_name + " " + t_("is not the name of a glyph or a Unicode value.") + "\n");+ stdout.printf (t_("Unicode values must start with U+.") + "\n");+ return false;+ }+ } + } else {+ gc = font.get_glyph_collection (glyph_name);+ }++ if (gc != null) {+ glyph_collection = (!) gc;+ character = glyph_collection.get_unicode_character ();+ glyph = new Glyph (glyph_collection.get_name (), character);+ glyph.version_id = glyph_collection.get_last_id () + 1;+ glyph_collection.insert_glyph (glyph, true);+ } else {+ return_val_if_fail (glyph_name.char_count () == 1, false);+ character = glyph_name.get_char (0);+ glyph_collection = new GlyphCollection (character, glyph_name);+ glyph = new Glyph (glyph_name, character);+ glyph_collection.insert_glyph (glyph, true);+ font.add_glyph_collection (glyph_collection);+ }++ canvas = MainWindow.get_glyph_canvas ();+ canvas.set_current_glyph_collection (glyph_collection);++ stdout.printf (t_("Adding"));+ stdout.printf (" ");+ stdout.printf ((!) svg_file.get_basename ());+ stdout.printf (" ");+ stdout.printf (t_("to"));+ stdout.printf (" ");+ stdout.printf (t_("Glyph"));+ stdout.printf (": ");+ stdout.printf (glyph.get_name ());+ stdout.printf (" ");+ stdout.printf (t_("Version"));+ stdout.printf (": ");+ stdout.printf (@"$(glyph.version_id)");+ stdout.printf ("\n");+ + SvgParser.import_svg ((!) svg_file.get_path ());+ + return true;+}++}@@ -392,7 +392,7 @@ public class KerningDisplay : FontDisplay { public void set_absolute_kerning (int handle, double val) { double kern; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -612,7 +612,7 @@ public class KerningDisplay : FontDisplay { public override void key_press (uint keyval) { unichar c; - if (MenuTab.suppress_event) { // don't update kerning while saving font+ if (MenuTab.has_suppress_event ()) { // don't update kerning while saving font return; } @@ -680,7 +680,7 @@ public class KerningDisplay : FontDisplay { listener.signal_text_input.connect ((text) => { submitted_value = text; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -719,7 +719,7 @@ public class KerningDisplay : FontDisplay { Glyph? g; string name; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -752,7 +752,7 @@ public class KerningDisplay : FontDisplay { public override void motion_notify (double ex, double ey) { double k, y; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -866,7 +866,7 @@ public class KerningDisplay : FontDisplay { TextListener listener; string kerning = @"$(get_kerning_for_handle (selected_handle))"; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -880,7 +880,7 @@ public class KerningDisplay : FontDisplay { string submitted_value; double parsed_value; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -916,7 +916,7 @@ public class KerningDisplay : FontDisplay { public void add_text (string t) { int c; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -932,7 +932,7 @@ public class KerningDisplay : FontDisplay { UndoItem ui; UndoItem redo_state; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -951,7 +951,7 @@ public class KerningDisplay : FontDisplay { public override void redo () { UndoItem ui; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -33,7 +33,6 @@ public class KerningTools : ToolCollection { static OtfTags active_otf_features; public KerningTools () {- active_otf_features = new OtfTags (); selected (); } @@ -52,6 +51,8 @@ public class KerningTools : ToolCollection { public static void init () { Font font = BirdFont.get_current_font (); + active_otf_features = new OtfTags ();+ Expander kerning_tools = new Expander (t_("Kerning Tools")); classes = new Expander (); expanders = new Gee.ArrayList<Expander> ();@@ -181,6 +182,8 @@ public class KerningTools : ToolCollection { public static void add_otf_label (string tag) { OtfLabel otf_label = new OtfLabel (tag);+ FontSettings fs = BirdFont.get_current_font ().settings;+ otf_features.add_tool (otf_label); otf_label.otf_feature_activity.connect ((enable, tag) => { OtfTags tags = active_otf_features.copy ();@@ -190,17 +193,22 @@ public class KerningTools : ToolCollection { // create a new feature set in order to keep the features // for other parts of the text in kerning tab active_otf_features = tags;-+ if (enable) { tags.add (tag);+ fs.set_setting (@"kerning_$(tag)", "true"); } else { tags.remove (tag);+ fs.set_setting (@"kerning_$(tag)", "false"); } kd.get_last_segment ().set_otf_tags (tags); GlyphCanvas.redraw (); });+ + bool enable = fs.get_setting (@"kerning_$(tag)") == "true";+ otf_label.set_selected_tag (enable); } public static void add_unique_class (KerningRange kerning_class) {@@ -39,7 +39,7 @@ public class LoadCallback : GLib.Object { } public void load () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -73,7 +73,7 @@ public class LoadCallback : GLib.Object { private void load_new_font () { FileChooser fc = new FileChooser (); - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -23,7 +23,7 @@ public class MenuTab : FontDisplay { * * This variable is used only in the gui thread. */- public static bool suppress_event;+ private static bool suppress_event; /** True if the background thread is running. */ public static bool background_thread;@@ -48,6 +48,16 @@ public class MenuTab : FontDisplay { background_thread = false; } + public static bool has_suppress_event () {+ bool suppress;+ + lock (suppress_event) {+ suppress = suppress_event;+ }+ + return suppress;+ }+ public static void set_save_callback (SaveCallback c) { if (!save_callback.is_done) { warning ("Prevoius save command has not finished");@@ -567,7 +577,7 @@ public class MenuTab : FontDisplay { } public static void save_as () {- if (MenuTab.suppress_event || !save_callback.is_done) {+ if (MenuTab.has_suppress_event () || !save_callback.is_done) { warn_if_test ("Event suppressed"); return; }@@ -577,7 +587,7 @@ public class MenuTab : FontDisplay { } public static void save () {- if (MenuTab.suppress_event && !save_callback.is_done) {+ if (MenuTab.has_suppress_event () && !save_callback.is_done) { warn_if_test ("Event suppressed"); return; }@@ -587,7 +597,7 @@ public class MenuTab : FontDisplay { } public static void load () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -26,14 +26,18 @@ public class Alternate : GLib.Object { this.tag = tag; } + public bool is_empty () {+ return alternates.size == 0;+ }+ public void add (string alternate_name) { alternates.add (alternate_name); } - public void remove (GlyphCollection g) {+ public void remove_alternate (string alt) { int i = 0; foreach (string a in alternates) {- if (a == g.get_name ()) {+ if (a == alt) { break; } i++;@@ -41,7 +45,11 @@ public class Alternate : GLib.Object { if (i < alternates.size) { alternates.remove_at (i);- }+ } + }+ + public void remove (GlyphCollection g) {+ remove_alternate (g.get_name ()); } public Alternate copy () {@@ -113,11 +113,9 @@ public class CffTable : OtfTable { len = offsets.get (i + 1) - off; //dis.seek (offset + off + header_size); data = dis.read_string (len);- print (@"Found name $data\n"); } // dict index- print (@"dict index\n"); dict_index = read_index (); // dict data@@ -24,14 +24,19 @@ public class OtfFeatureTable : Table { static const int OTF_FEATURE = 1; static const int SOURCE_GLYPH = 2; // the glyph to replace static const int REPLACEMENT_GLYPH = 3;+ static const int ALTERNATE_ENTRY = 4; GlyphCollection glyph_collection; GlyphCollection? replacement_glyph = null; string alternate_name = ""; TextListener listener; + Gee.ArrayList<AlternateItem> undo_items;+ // FIXME: implement redo+ public OtfFeatureTable (GlyphCollection gc) { glyph_collection = gc;+ undo_items = new Gee.ArrayList<AlternateItem> (); } public override Gee.ArrayList<Row> get_rows () {@@ -40,6 +45,9 @@ public class OtfFeatureTable : Table { public override void selected_row (Row row, int column, bool delete_button) { int row_index = row.get_index ();+ Object o;+ String s;+ AlternateItem a; if (row_index == SOURCE_GLYPH) { GlyphSelection gs = new GlyphSelection ();@@ -60,14 +68,35 @@ public class OtfFeatureTable : Table { GlyphCanvas.set_display (gs); } else if (row_index == OTF_FEATURE) {- String s = (String) row.get_row_data ();+ return_if_fail (row.has_row_data ());+ o = (!) row.get_row_data ();+ return_if_fail (o is String);+ s = (String) o; add_new_alternate (s.data);+ } else if (row_index == ALTERNATE_ENTRY) {+ if (delete_button) {+ return_if_fail (row.has_row_data ());+ o = (!) row.get_row_data ();+ return_if_fail (o is AlternateItem);+ a = (AlternateItem) o;+ + a.delete_item_from_list (); + Font f = BirdFont.get_current_font ();+ f.alternates.remove_empty_sets ();+ + undo_items.add (a);+ + update_rows ();+ GlyphCanvas.redraw ();+ } } } public override void update_rows () { Row row;-+ Font font;+ + font = BirdFont.get_current_font (); rows.clear (); row = new Row.headline (t_("Glyph Substitutions"));@@ -106,10 +135,34 @@ public class OtfFeatureTable : Table { row = new Row.columns_1 (OtfLabel.get_string ("swsh"), OTF_FEATURE, false); row.set_row_data (new String ("swsh")); rows.add (row);- + + Gee.ArrayList<string> tags = font.alternates.get_all_tags ();+ foreach (string tag in tags) {+ row = new Row.headline (OtfLabel.get_string (tag));+ rows.add (row);+ add_alternate_items (tag);+ }+ GlyphCanvas.redraw (); } + void add_alternate_items (string tag) {+ Font font = BirdFont.get_current_font ();+ foreach (Alternate alt in font.alternates.get_alt (tag)) {+ add_alternate_rows (alt);+ } + }++ void add_alternate_rows (Alternate alt) {+ Row row;+ + foreach (string a in alt.alternates) {+ row = new Row.columns_2 (alt.glyph_name, a, ALTERNATE_ENTRY, true);+ row.set_row_data (new AlternateItem (alt, a));+ rows.add (row);+ } + }+ public override string get_label () { return t_("Glyph Substitutions"); }@@ -162,8 +215,26 @@ public class OtfFeatureTable : Table { MainWindow.tabs.close_display (this); } else { TabContent.show_text_input (listener);- }+ } + }+ + public override void undo () {+ AlternateItem item;+ Font font;+ + font = BirdFont.get_current_font (); + if (undo_items.size > 0) {+ item = undo_items.get (undo_items.size - 1);+ undo_items.remove_at (undo_items.size - 1);+ + font.add_alternate (item.alternate_list.glyph_name,+ item.alternate,+ item.alternate_list.tag);+ + update_rows ();+ GlyphCanvas.redraw ();+ } } } @@ -32,11 +32,15 @@ public class OtfLabel : LabelTool { select_action.connect ((self) => { active_substitution = !active_substitution;- self.set_selected (active_substitution);- otf_feature_activity (active_substitution, tag);+ set_selected_tag (active_substitution); }); } + public void set_selected_tag (bool enabled) {+ set_selected (enabled);+ otf_feature_activity (enabled, tag);+ }+ /** @return translated string representation of a OTF feature tag. */ public static string get_string (string tag) { if (tag == "salt") {@@ -549,8 +549,8 @@ public class OverView : FontDisplay { public override void draw (WidgetAllocation allocation, Context cr) { - if (this.allocation.width == allocation.width- || this.allocation.height == allocation.height+ if (this.allocation.width != allocation.width+ || this.allocation.height != allocation.height || this.allocation.width == 0) { this.allocation = allocation; update_item_list ();@@ -816,6 +816,8 @@ public class OverView : FontDisplay { return; case Key.UP:+ get_selected_item ().selected = false;+ key_up (); selected_item = get_selected_item (); @@ -828,6 +830,8 @@ public class OverView : FontDisplay { return; case Key.RIGHT:+ get_selected_item ().selected = false;+ key_right (); selected_item = get_selected_item (); @@ -840,6 +844,8 @@ public class OverView : FontDisplay { return; case Key.LEFT:+ get_selected_item ().selected = false;+ key_left (); selected_item = get_selected_item (); @@ -852,6 +858,8 @@ public class OverView : FontDisplay { return; case Key.DOWN:+ get_selected_item ().selected = false;+ key_down (); selected_item = get_selected_item (); @@ -864,6 +872,8 @@ public class OverView : FontDisplay { return; case Key.PG_UP:+ get_selected_item ().selected = false;+ for (int i = 0; i < rows; i++) { key_up (); }@@ -878,6 +888,8 @@ public class OverView : FontDisplay { return; case Key.PG_DOWN:+ get_selected_item ().selected = false;+ for (int i = 0; i < rows; i++) { key_down (); }@@ -114,6 +114,7 @@ public class OverViewItem : GLib.Object { g = (!) glyphs; version_menu.set_position (x + width - 21, y + height - 18); a = version_menu.menu_item_action (px, py); // select one item on the menu+ if (a) { return s; }@@ -158,6 +159,7 @@ public class OverViewItem : GLib.Object { draw_thumbnail (cr, glyphs, x, y + height); draw_caption (cr);+ draw_menu (cr); } public void adjust_scale () {@@ -273,7 +275,6 @@ public class OverViewItem : GLib.Object { label.draw_at_baseline (cr, x + 0.08 * width, y + height - 6); } - draw_menu (cr); cr.restore (); } @@ -128,11 +128,9 @@ public class OverviewTools : ToolCollection { transform.set_persistent (false); transform_expander.add_tool (transform); - if (BirdFont.has_argument ("--test")) {- Tool alternate = new Tool ("alternate", t_("Create alternate"));- alternate.select_action.connect (add_new_alternate);- glyph_expander.add_tool (alternate);- }+ 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);@@ -53,8 +53,9 @@ public class Path : GLib.Object { /** Stroke width */ public double stroke = 0; public LineCap line_cap = LineCap.BUTT;- PathList? full_stroke = null;+ public PathList? full_stroke = null; PathList? fast_stroke = null;+ StrokeTask? stroke_creator; /** Fill property for closed paths with stroke. */ public bool fill = false;@@ -2413,13 +2414,20 @@ public class Path : GLib.Object { } public void create_full_stroke () {-#if ANDROID == false- if (stroke > 0) {- full_stroke = StrokeTool.get_stroke (this, stroke);+ if (stroke <= 0) {+ return; }-#endif+ + StrokeTask task = new StrokeTask (this);+ MainWindow.native_window.run_non_blocking_background_thread (task);+ + if (stroke_creator != null) {+ ((!) stroke_creator).cancel ();+ }+ + stroke_creator = task; }- + public PathList get_stroke () { if (full_stroke == null) { full_stroke = StrokeTool.get_stroke (this, stroke);@@ -424,8 +424,13 @@ public class PenTool : Tool { foreach (PointSelection p in selected_points) { remove_point_simplify (p);+ p.path.reset_stroke (); }- ++ foreach (PointSelection p in selected_points) {+ p.path.create_full_stroke ();+ }+ g.update_view (); selected_points.clear ();@@ -201,7 +201,7 @@ public class RecentFiles : Table { Font font; SaveDialogListener dialog = new SaveDialogListener (); - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -211,7 +211,7 @@ public class RecentFiles : Table { MenuTab.load_callback.file_loaded.connect (() => { Font f; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warning ("Load font event suppressed."); return; }@@ -234,7 +234,7 @@ public class RecentFiles : Table { dialog.signal_discard.connect (() => { Font f; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -250,7 +250,7 @@ public class RecentFiles : Table { }); dialog.signal_save.connect (() => {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed."); return; }@@ -26,7 +26,7 @@ public class SaveCallback : GLib.Object { } public void save_as () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -71,7 +71,7 @@ public class SaveCallback : GLib.Object { Font f; string fn; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -234,7 +234,7 @@ public class SpacingTab : KerningDisplay { listener.signal_text_input.connect ((text) => { submitted_value = text; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -278,7 +278,7 @@ public class SpacingTab : KerningDisplay { listener.signal_text_input.connect ((text) => { submitted_value = text; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } new file mode 100644@@ -0,0 +1,57 @@+/*+ 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 {+ +class StrokeTask : Task {+ bool cancelled = false;+ Path original; // path in gui thread+ Path background_path; // path in background thread+ + public StrokeTask (Path path) {+ base (null);+ original = path;+ background_path = path.copy ();+ }+ + public void cancel () {+ lock (cancelled) { + cancelled = true;+ }+ }+ + public override void run () {+ PathList stroke;+ double w;+ + w = background_path.stroke;+ stroke = StrokeTool.get_stroke (background_path, w);++ IdleSource idle = new IdleSource (); + idle.set_callback (() => {+ + lock (cancelled) { + if (!cancelled) {+ original.full_stroke = stroke;+ GlyphCanvas.redraw ();+ }+ }+ + return false;+ });+ idle.attach (null); + }+}++}@@ -218,18 +218,17 @@ public class StrokeTool : Tool { static void remove_single_point_intersections (Path p) { PointSelection ps; - p.remove_points_on_points (0.1);+ p.remove_points_on_points (); for (int i = 0; i < p.points.size; i++) { EditPoint ep = p.points.get (i);+ EditPoint next = p.points.get ((i + 1) % p.points.size); if (fabs (ep.get_right_handle ().angle - ep.get_left_handle ().angle) % (2 * PI) < 0.01) { ps = new PointSelection (ep, p); PenTool.remove_point_simplify (ps);- i--;- } else if (ep.next != null && Path.distance_to_point (ep, ep.get_next ()) < 0.01) {+ } else if (Path.distance_to_point (ep, next) < 0.01) { ps = new PointSelection (ep, p); PenTool.remove_point_simplify (ps);- i--; } } }@@ -946,6 +945,13 @@ public class StrokeTool : Tool { PenTool.convert_point_type (e, PointType.CUBIC); } + foreach (EditPoint e in p.points) {+ if ((e.flags & EditPoint.CURVE) == 0) {+ p.set_new_start (e);+ break;+ }+ }+ for (int i = 0; i < p.points.size; i++) { ep = p.points.get (i); @@ -1027,22 +1033,10 @@ public class StrokeTool : Tool { simplified.add_point (ep.copy ()); } }-+ simplified.recalculate_linear_handles (); simplified.close (); remove_single_point_intersections (simplified);- - first = simplified.get_first_point ();- first.left_handle.angle = last_handle.angle;- first.left_handle.length = last_handle.length;-- double left = first.get_left_handle ().angle;- double right = first.get_right_handle ().angle;- - if (fabs (right - left) % (2 * PI) < 0.01) {- first.get_left_handle ().convert_to_line ();- first.recalculate_linear_handles ();- } simplified.remove_points_on_points (); @@ -1331,6 +1325,9 @@ public class StrokeTool : Tool { previous_handle = previous.get_left_handle (); next_handle = next.get_right_handle (); + previous_handle.convert_to_line ();+ next_handle.convert_to_line ();+ previous_handle.angle += PI; next_handle.angle += PI; @@ -85,7 +85,7 @@ public class TabBar : GLib.Object { public void motion (double x, double y) { MainWindow.set_cursor (NativeWindow.VISIBLE); - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -170,7 +170,7 @@ public class TabBar : GLib.Object { public bool select_char (string s) { int i = 0; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return false; }@@ -187,7 +187,7 @@ public class TabBar : GLib.Object { } public bool select_tab_name (string s) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return false; }@@ -196,7 +196,7 @@ public class TabBar : GLib.Object { } public void select_overview () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -208,7 +208,7 @@ public class TabBar : GLib.Object { Tab t; bool open; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -228,7 +228,7 @@ public class TabBar : GLib.Object { public void close_display (FontDisplay f) { int i = -1; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -248,7 +248,7 @@ public class TabBar : GLib.Object { } public void close_all_tabs () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -266,7 +266,7 @@ public class TabBar : GLib.Object { Tab empty_tab; GlyphCollection gc; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return false; }@@ -331,7 +331,7 @@ public class TabBar : GLib.Object { public bool selected_open_tab (Tab t) { int i = 0; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return false; }@@ -369,7 +369,7 @@ public class TabBar : GLib.Object { public bool selected_open_tab_by_name (string t) { int i = 0; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return false; }@@ -407,7 +407,7 @@ public class TabBar : GLib.Object { public void select_tab (int index, bool signal_selected = true) { Tab t; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -567,7 +567,7 @@ public class TabBar : GLib.Object { int s = (tabs.size == 0) ? 0 : selected + 1; Tab t; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -596,7 +596,7 @@ public class TabBar : GLib.Object { public bool add_unique_tab (FontDisplay display_item, bool signal_selected = true) { bool i; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return false; }@@ -31,14 +31,14 @@ public class TabContent : GLib.Object { static double last_press_time = 0; public static void zoom_in () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { } GlyphCanvas.current_display.zoom_in (); } public static void zoom_out () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -46,7 +46,7 @@ public class TabContent : GLib.Object { } public static void move_view (double x, double y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -54,7 +54,7 @@ public class TabContent : GLib.Object { } public static bool has_scrollbar () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return false; } @@ -62,7 +62,7 @@ public class TabContent : GLib.Object { } public static void scroll_to (double percent) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -73,7 +73,7 @@ public class TabContent : GLib.Object { AbstractMenu menu; Dialog dialog; - if (unlikely (MenuTab.suppress_event)) {+ if (unlikely (MenuTab.has_suppress_event ())) { cr.save (); Theme.color (cr, "Background 1"); cr.rectangle (0, 0, allocation.width, allocation.height);@@ -118,7 +118,7 @@ public class TabContent : GLib.Object { Context cr; WidgetAllocation alloc; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warning ("Background surface already created."); return; }@@ -131,7 +131,7 @@ public class TabContent : GLib.Object { } public static void key_press (uint keyval) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -146,7 +146,7 @@ public class TabContent : GLib.Object { } public static void key_release (uint keyval) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -160,7 +160,7 @@ public class TabContent : GLib.Object { public static void motion_notify (double x, double y) { Toolbox toolbox; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -176,7 +176,7 @@ public class TabContent : GLib.Object { } public static void button_release (int button, double x, double y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -194,7 +194,7 @@ public class TabContent : GLib.Object { } public static void button_press (uint button, double x, double y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -217,7 +217,7 @@ public class TabContent : GLib.Object { } public static void double_click (uint button, double ex, double ey) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -229,7 +229,7 @@ public class TabContent : GLib.Object { public static void scroll_wheel_pixel_delta (double x, double y, double pixeldelta_x, double pixeldelta_y) { - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -239,7 +239,7 @@ public class TabContent : GLib.Object { } public static void scroll_wheel_up (double x, double y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -249,7 +249,7 @@ public class TabContent : GLib.Object { } public static void scroll_wheel_down (double x, double y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -259,7 +259,7 @@ public class TabContent : GLib.Object { } public static void tap_down (int finger, int x, int y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -269,7 +269,7 @@ public class TabContent : GLib.Object { } public static void tap_up (int finger, int x, int y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -279,7 +279,7 @@ public class TabContent : GLib.Object { } public static void tap_move (int finger, int x, int y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -289,7 +289,7 @@ public class TabContent : GLib.Object { } public static void undo () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -297,7 +297,7 @@ public class TabContent : GLib.Object { } public static void redo () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { return; } @@ -19,11 +19,18 @@ public class Task : GLib.Object { public delegate void Runnable (); Runnable task; - public Task (owned Runnable r) {- task = (owned) r;+ public Task (owned Runnable? r) {+ if (r != null) {+ task = (!) ((owned) r);+ } } - public void run () {+ public virtual void run () {+ if (task == null) {+ warning ("No task set.");+ return;+ }+ task (); } @@ -144,7 +144,7 @@ public class Toolbox : GLib.Object { } public void press (uint button, double x, double y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -171,7 +171,7 @@ public class Toolbox : GLib.Object { y -= current_set.scroll; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -198,7 +198,7 @@ public class Toolbox : GLib.Object { } public void double_click (uint button, double x, double y) {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -219,7 +219,7 @@ public class Toolbox : GLib.Object { y -= current_set.scroll; - if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Event suppressed"); return; }@@ -331,7 +331,7 @@ public class Toolbox : GLib.Object { } public static void redraw_tool_box () {- if (MenuTab.suppress_event) {+ if (MenuTab.has_suppress_event ()) { warn_if_test ("Don't redraw toolbox when background thread is running."); return; }@@ -36,7 +36,7 @@ public class VersionList : GLib.Object { double width = 0; double menu_x = -1; - public bool menu_visible = false;+ public bool menu_visible { get; set; } Gee.ArrayList <MenuAction> actions = new Gee.ArrayList <MenuAction> (); const int item_height = 25; MenuDirection direction = MenuDirection.DROP_DOWN;@@ -47,6 +47,7 @@ public class VersionList : GLib.Object { public signal void add_glyph_item (Glyph item); public VersionList (GlyphCollection gc) {+ menu_visible = false; MenuAction ma = add_item (t_("New version")); ma.has_delete_button = false; ma.action.connect ((self) => {@@ -432,8 +433,8 @@ public class VersionList : GLib.Object { } } - if (x - width + 19 < 0) {- menu_x = 30;+ if (x - width < 5) {+ menu_x = 5; } else { menu_x = x - width; }@@ -79,7 +79,7 @@ public class ZoomBar : Tool { set_zoom (zoom_level); - if (!MenuTab.suppress_event) {+ if (!MenuTab.has_suppress_event ()) { new_zoom (zoom_level); } @@ -379,7 +379,7 @@ int i, j, k; /* binary greatest common divisor by Silver and Terzian. See Knuth */ /* both inputs must be >= 0 */-gcd(u, v)+int gcd(u, v) int u, v; { int t, f;@@ -13,7 +13,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. """ -VERSION = '2.12.0'+VERSION = '2.13.0-beta3' SO_VERSION_MAJOR = '36' SO_VERSION_MINOR = '0' SO_VERSION = SO_VERSION_MAJOR + '.' + SO_VERSION_MINOR