Clone in a terminal:
Commit 7bcd266
Johan Mattsson - 2015-10-07T20:19:21+00:00
7bcd2669c5ce0c8032551a5c4dc8c3ebdaa7aad5johan.mattsson.m@gmail.com

Merge branch 'master' of github.com:johanmattssonm/birdfont

Changed files (31)

Diff

diff --git a/libbirdfont/AlternateSets.vala b/libbirdfont/AlternateSets.valaindex b95e968..b33d7d4 100644--- a/libbirdfont/AlternateSets.vala+++ b/libbirdfont/AlternateSets.vala@@ -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);+	}+}+ }diff --git a/libbirdfont/BirdFont.vala b/libbirdfont/BirdFont.valaindex 3323e11..932a5ce 100644--- a/libbirdfont/BirdFont.vala+++ b/libbirdfont/BirdFont.vala@@ -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 } diff --git a/libbirdfont/ExportUtils.vala b/libbirdfont/ExportUtils.valanew file mode 100644index 0000000..c4307d7--- /dev/null+++ b/libbirdfont/ExportUtils.vala@@ -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;+}++}diff --git a/libbirdfont/GlyphCanvas.vala b/libbirdfont/GlyphCanvas.valaindex b2f62a7..5bbd063 100644--- a/libbirdfont/GlyphCanvas.vala+++ b/libbirdfont/GlyphCanvas.vala@@ -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);
diff --git a/libbirdfont/ImportUtils.vala b/libbirdfont/ImportUtils.valanew file mode 100644index 0000000..0c45601--- /dev/null+++ b/libbirdfont/ImportUtils.vala@@ -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;+}++}diff --git a/libbirdfont/KerningDisplay.vala b/libbirdfont/KerningDisplay.valaindex d4c5c0c..217d38c 100644--- a/libbirdfont/KerningDisplay.vala+++ b/libbirdfont/KerningDisplay.vala@@ -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; 		} 		diff --git a/libbirdfont/KerningTools.vala b/libbirdfont/KerningTools.valaindex 409ae02..687bd39 100644--- a/libbirdfont/KerningTools.vala+++ b/libbirdfont/KerningTools.vala@@ -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) {diff --git a/libbirdfont/LoadCallback.vala b/libbirdfont/LoadCallback.valaindex 3afb93f..890303d 100644--- a/libbirdfont/LoadCallback.vala+++ b/libbirdfont/LoadCallback.vala@@ -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; 		}diff --git a/libbirdfont/MenuTab.vala b/libbirdfont/MenuTab.valaindex 0951704..e7e7106 100644--- a/libbirdfont/MenuTab.vala+++ b/libbirdfont/MenuTab.vala@@ -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; 		}diff --git a/libbirdfont/OpenFontFormat/Alternate.vala b/libbirdfont/OpenFontFormat/Alternate.valaindex 9dbdd0c..2d899ff 100644--- a/libbirdfont/OpenFontFormat/Alternate.vala+++ b/libbirdfont/OpenFontFormat/Alternate.vala@@ -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 () {diff --git a/libbirdfont/OpenFontFormat/CffTable.vala b/libbirdfont/OpenFontFormat/CffTable.valaindex d64dcdd..c7f7325 100644--- a/libbirdfont/OpenFontFormat/CffTable.vala+++ b/libbirdfont/OpenFontFormat/CffTable.vala@@ -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 datadiff --git a/libbirdfont/OtfFeatureTable.vala b/libbirdfont/OtfFeatureTable.valaindex c947c56..a3459a7 100644--- a/libbirdfont/OtfFeatureTable.vala+++ b/libbirdfont/OtfFeatureTable.vala@@ -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 ();+		} 	} } diff --git a/libbirdfont/OtfLabel.vala b/libbirdfont/OtfLabel.valaindex b51a672..5833a12 100644--- a/libbirdfont/OtfLabel.vala+++ b/libbirdfont/OtfLabel.vala@@ -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") {diff --git a/libbirdfont/OverView.vala b/libbirdfont/OverView.valaindex 12ebb25..2f8cf96 100644--- a/libbirdfont/OverView.vala+++ b/libbirdfont/OverView.vala@@ -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 (); 				}diff --git a/libbirdfont/OverViewItem.vala b/libbirdfont/OverViewItem.valaindex bf7083b..c70da1b 100644--- a/libbirdfont/OverViewItem.vala+++ b/libbirdfont/OverViewItem.vala@@ -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 (); 	} 	diff --git a/libbirdfont/OverviewTools.vala b/libbirdfont/OverviewTools.valaindex e0c10ca..ab5ef0e 100644--- a/libbirdfont/OverviewTools.vala+++ b/libbirdfont/OverviewTools.vala@@ -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);diff --git a/libbirdfont/Path.vala b/libbirdfont/Path.valaindex f861ef4..e1d9075 100644--- a/libbirdfont/Path.vala+++ b/libbirdfont/Path.vala@@ -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);diff --git a/libbirdfont/PenTool.vala b/libbirdfont/PenTool.valaindex 8075151..809ec85 100644--- a/libbirdfont/PenTool.vala+++ b/libbirdfont/PenTool.vala@@ -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 ();diff --git a/libbirdfont/RecentFiles.vala b/libbirdfont/RecentFiles.valaindex e5e8fbb..45eefe2 100644--- a/libbirdfont/RecentFiles.vala+++ b/libbirdfont/RecentFiles.vala@@ -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; 			}diff --git a/libbirdfont/SaveCallback.vala b/libbirdfont/SaveCallback.valaindex a402a5d..56d96f2 100644--- a/libbirdfont/SaveCallback.vala+++ b/libbirdfont/SaveCallback.vala@@ -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; 		}diff --git a/libbirdfont/SpacingTab.vala b/libbirdfont/SpacingTab.valaindex 0fc1b98..8c2d2a9 100644--- a/libbirdfont/SpacingTab.vala+++ b/libbirdfont/SpacingTab.vala@@ -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; 			} 			diff --git a/libbirdfont/StrokeTask.vala b/libbirdfont/StrokeTask.valanew file mode 100644index 0000000..1bda518--- /dev/null+++ b/libbirdfont/StrokeTask.vala@@ -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);		+	}+}++}diff --git a/libbirdfont/StrokeTool.vala b/libbirdfont/StrokeTool.valaindex 9185aa3..c5c2089 100644--- a/libbirdfont/StrokeTool.vala+++ b/libbirdfont/StrokeTool.vala@@ -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; 		diff --git a/libbirdfont/TabBar.vala b/libbirdfont/TabBar.valaindex 9a7be7e..3ade386 100644--- a/libbirdfont/TabBar.vala+++ b/libbirdfont/TabBar.vala@@ -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; 		}diff --git a/libbirdfont/TabContent.vala b/libbirdfont/TabContent.valaindex f7415d2..fcc67fe 100644--- a/libbirdfont/TabContent.vala+++ b/libbirdfont/TabContent.vala@@ -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; 		} 		diff --git a/libbirdfont/Task.vala b/libbirdfont/Task.valaindex 3077edb..ce7088f 100644--- a/libbirdfont/Task.vala+++ b/libbirdfont/Task.vala@@ -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 (); 	} diff --git a/libbirdfont/Toolbox.vala b/libbirdfont/Toolbox.valaindex ebc8d5f..899da2f 100644--- a/libbirdfont/Toolbox.vala+++ b/libbirdfont/Toolbox.vala@@ -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; 		}diff --git a/libbirdfont/VersionList.vala b/libbirdfont/VersionList.valaindex 4a47259..2d5c73d 100644--- a/libbirdfont/VersionList.vala+++ b/libbirdfont/VersionList.vala@@ -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; 		}diff --git a/libbirdfont/ZoomBar.vala b/libbirdfont/ZoomBar.valaindex 16933d0..6387b62 100644--- a/libbirdfont/ZoomBar.vala+++ b/libbirdfont/ZoomBar.vala@@ -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); 		} 		diff --git a/libbirdgems/GGVecLib.c b/libbirdgems/GGVecLib.cindex 4f1e7cd..55393a8 100644--- a/libbirdgems/GGVecLib.c+++ b/libbirdgems/GGVecLib.c@@ -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;diff --git a/scripts/version.py b/scripts/version.pyindex f356583..e8c8555 100644--- a/scripts/version.py+++ b/scripts/version.py@@ -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

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112