Clone in a terminal:
Commit 59925fc
Johan Mattsson - 2013-09-10T09:58:37+00:00
59925fcd8f5ef157a21d418c28584876dc4ce1aejohan.mattsson.m@gmail.com

Merge branch 'master' of gitorious.org:birdfont/birdfont

Changed files (19)

Diff

diff --git a/birdfont/GtkWindow.vala b/birdfont/GtkWindow.valaindex 9117cd4..c98cfa7 100644--- a/birdfont/GtkWindow.vala+++ b/birdfont/GtkWindow.vala@@ -259,21 +259,6 @@ public class GtkWindow : Gtk.Window, NativeWindow { 				 				MainWindow.glyph_canvas.key_press (event.keyval); 				KeyBindings.add_modifier_from_keyval (event.keyval);-				-				if (KeyBindings.modifier == CTRL) {-					switch (event.keyval) {-						case 'a':-							Toolbox.select_tool_by_name ("move");-							MainWindow.get_current_glyph ().select_all_paths ();-							break;-						case 'c':-							ClipTool.copy ();-							break;-						case 'v':-							ClipTool.paste ();-							break;-					}-				} 			} 			 			return false;@@ -371,7 +356,7 @@ public class GtkWindow : Gtk.Window, NativeWindow { 	 	public void set_scrollbar_position (double position) { 		scrollbar_supress_signal = true;-		scrollbar.adjustment.value = (1 - scrollbar.adjustment.page_size) * position;+		scrollbar.adjustment.value = position * (1 - scrollbar.adjustment.page_size); 		scrollbar_supress_signal = false; 	} 	@@ -567,10 +552,10 @@ public class GtkWindow : Gtk.Window, NativeWindow { 		Gtk.MenuItem select_all_item = new Gtk.MenuItem.with_mnemonic (_("Select All Pa_ths")); 		edit_menu.append (select_all_item); 		select_all_item.activate.connect (() => {-			Toolbox.select_tool_by_name ("move");-			MainWindow.get_current_glyph ().select_all_paths ();+			MainWindow.select_all_paths (); 		});-+		select_all_item.add_accelerator ("activate", accel_group, 'A', Gdk.ModifierType.CONTROL_MASK, Gtk.AccelFlags.VISIBLE);+		 		Gtk.MenuItem search_item = new Gtk.MenuItem.with_mnemonic (_("_Search")); 		edit_menu.append (search_item); 		search_item.activate.connect (() => { OverView.search (); });	diff --git a/configure b/configureindex 7152cb2..d7f6722 100755--- a/configure+++ b/configure@@ -54,7 +54,7 @@ def configure (): 	libs = [ 			'cairo',  			'gdk-pixbuf-2.0', -			'gee-1.0',+			'gee-0.8', 			'gio-2.0',  			'glib-2.0',  			'gtk+-2.0',diff --git a/dodo.py b/dodo.pyindex d20e4ed..c48c4c2 100644--- a/dodo.py+++ b/dodo.py@@ -45,7 +45,7 @@ LIBS = [     'cairo',     'gdk-pixbuf-2.0',     'webkit-1.0',-    'gee-1.0'+    'gee-0.8'     ]  def task_build ():diff --git a/libbirdfont/BirdFont.vala b/libbirdfont/BirdFont.valaindex a341fb2..13a15c0 100644--- a/libbirdfont/BirdFont.vala+++ b/libbirdfont/BirdFont.vala@@ -43,6 +43,8 @@ public static int run_export (string[] arg) { 		return -1; 	} 	+	init_logfile ();+	 	for (int i = 1; i < arg.length; i++) {  		if (arg[i] == "-f" || arg[i] == "--fatal-warnings") {@@ -183,6 +185,9 @@ public class BirdFont { 	public static string exec_path = ""; 	public static string bundle_path = ""; +	public static bool logging = false;+	public static DataOutputStream? logstream = null;+ 	public static Font current_font; 	public static Glyph current_glyph; 	@@ -363,4 +368,58 @@ public class BirdFont { 	}	 } +void init_logfile () {+	DateTime t;+	File settings;+	string s;+	File log;+	+	try {+		t = new DateTime.now_local ();+		settings = BirdFont.get_settings_directory ();+		s = t.to_string ().replace (":", "_");+		log = settings.get_child (@"birdfont_$s.log");+		+		BirdFont.logstream = new DataOutputStream (log.create (FileCreateFlags.REPLACE_DESTINATION));+		((!)BirdFont.logstream).put_string ((!) log.get_path ());+		((!)BirdFont.logstream).put_string ("\n");+		+		warning ("Logging to " + (!) log.get_path ());+	} catch (GLib.Error e) {+		warning (e.message);+		warning ((!) log.get_path ());+	}++	LogLevelFlags levels = LogLevelFlags.LEVEL_ERROR | LogLevelFlags.LEVEL_CRITICAL | LogLevelFlags.LEVEL_WARNING | LogLevelFlags.LEVEL_DEBUG;+	Log.set_handler (null, levels, log_warning);		+		+	BirdFont.logging = true;+}++internal static void log_warning (string? log_domain, LogLevelFlags log_levels, string message) {+	if (log_domain != null) {+		printd ((!) log_domain);+	}+	+	printd ("\n");+	printd (message);+	printd ("\n");+	printd ("\n");+}++/** Write debug output to logfile. */+void printd (string s) {+	if (unlikely (BirdFont.logging)) {+		try {+			if (BirdFont.logstream != null) {+				((!)BirdFont.logstream).put_string (s);+			} else {+				warning ("No logstream.");+			}+		} catch (GLib.Error e) {+			warning (e.message);+		}+	}+}+ }diff --git a/libbirdfont/BirdFontFile.vala b/libbirdfont/BirdFontFile.valaindex 20c4f6a..e1a5339 100644--- a/libbirdfont/BirdFontFile.vala+++ b/libbirdfont/BirdFontFile.vala@@ -36,7 +36,9 @@ class BirdFontFile { 		Xml.Node* root; 		 		Parser.init ();-+		+		printd (@"Loading $path\n");+		 		font.font_file = path; // this will be updated if we are loading a backup file  		doc = Parser.parse_file (path);@@ -464,7 +466,10 @@ class BirdFontFile { 		Xml.Node* node = root; 		 		for (Xml.Node* iter = node->children; iter != null; iter = iter->next) {-+			+			printd (iter->name); // FIXME: delete+			printd ("\n");+	 			// this is a backup file set path to the original  			if (iter->name == "backup") { 				font.font_file = iter->children->content;@@ -498,6 +503,15 @@ class BirdFontFile {  			if (iter->name == "postscript_name" && iter->children != null) { 				font.postscript_name = iter->children->content;+				+				printd ("PostScript name:"); // FIXME: delete when debugging is done+				printd (iter->children->content);+				printd ("\n");+			}+			+			// FIXME: delete when debugging is done+			if (iter->name == "postscript_name" && iter->children == null) {+				printd ("Found PostScipt name but content for this node is null in libxml.\n"); 			} 			 			if (iter->name == "name" && iter->children != null) {@@ -702,6 +716,10 @@ class BirdFontFile { 				data = attr_content; 			} 		}++		if (!font.get_backgrounds_folder ().query_exists ()) {+			DirUtils.create ((!) font.get_backgrounds_folder ().get_path (), 0xFFFFFF);+		} 		 		img_dir = font.get_backgrounds_folder ().get_child ("parts"); diff --git a/libbirdfont/CharDatabase.vala b/libbirdfont/CharDatabase.valaindex d945d51..509df7e 100644--- a/libbirdfont/CharDatabase.vala+++ b/libbirdfont/CharDatabase.vala@@ -56,8 +56,7 @@ public class CharDatabase { 			result.add_single (s.get_char ());  		} 		-		var it = index.get (s).iterator ();-		for (var has_next = it.first (); has_next; has_next = it.next ()) {+		for (var it = index.get (s).iterator (); it.has_next (); it.next ()) { 			iv = it.get (); 			if (iv != null) { 				i = (string) iv;diff --git a/libbirdfont/Font.vala b/libbirdfont/Font.valaindex e4e78f7..7d2be8b 100644--- a/libbirdfont/Font.vala+++ b/libbirdfont/Font.vala@@ -333,6 +333,8 @@ public class Font : GLib.Object { 		} 		 		glyph_cache.insert (glyph_collection.get_unicode (), glyph_collection);+		+		printd (@"Adding $(glyph_collection.get_current ().get_name ())\n"); 	} 	 	public string get_name_for_character (unichar c) {diff --git a/libbirdfont/GlyphTable.vala b/libbirdfont/GlyphTable.valaindex 0f4ec1a..daa204a 100644--- a/libbirdfont/GlyphTable.vala+++ b/libbirdfont/GlyphTable.vala@@ -12,413 +12,67 @@     Lesser General Public License for more details. */ +using Gee;+ namespace BirdFont {  /** A sorted table of glyphs with search index. */ public class GlyphTable : GLib.Object {-	List<Item> data = new List<Item> (); 	-	List<RowItem> row1 = new List<RowItem> ();-	List<RowItem> row2 = new List<RowItem> ();-	List<RowItem> row3 = new List<RowItem> ();+	TreeMap<string, GlyphCollection> map; 	 	public GlyphTable () {+		map = new TreeMap<string, GlyphCollection> (); 	}  	public void remove_all () {-		while (data.length () > 0) {-			data.remove_link (data.first ());-		}-		build_index ();+		map.clear (); 	}  	public void @for_each (Func<GlyphCollection> func) {-		if (unlikely (is_null (data))) {+		if (unlikely (is_null (map))) { 			warning ("No data in table"); 			return; 		} 		-		data.foreach ((v) => {-			if (unlikely (is_null (v))) {-				warning ("No value found in GlyphTable.");-				return;-			}-						-			func (v.glyph_collection);-		});+		foreach (var entry in map.entries) {+			func (entry.value);+		} 	}  	public bool has_key (string n) {-		return find (n) != null;-	}--	unowned List<Item>? find (string n) {-		return find_index (n);-	}--	unowned List<Item>? find_next (string n) {-		return find_next_index (n);+		return map.has_key (n); 	} 		 	public void remove (string name) {-		unowned List<Item>? d = find (name);-		-		if (d == null) {-			warning (@"did not find $name");-			return;-		}-		-		data.remove_link ((!) d);-		build_index ();+		map.unset (name); 	}  	public uint length () {-		return data.length ();+		return map.size; 	}  	public new GlyphCollection? @get (string name) {-		unowned List<Item>? d = find_index (name);-		-		if (d == null) {-			return null;-		}-		-		return ((!) d).data.glyph_collection;+		return map.get (name); 	}  	public new GlyphCollection? nth (uint index) {-		unowned List<Item>? d = data.nth (index);-		-		if (d == null) {-			return null;-		}-		-		return ((!) d).data.glyph_collection;-	}--	public bool insert (string key, GlyphCollection g) {-		Item item;-		unowned List<Item>? next;--		if (find (key) != null) {-			warning (@"Table does already contains a glyph for key \"$key\".");-			stderr.printf ("char: %u\n", (uint) key.get_char (0));-			return false;-		}-				-		next = find_next (key);-		-		item = new Item (key, g);-		-		if (next == null) {-			data.append (item);-		} else {-			data.insert_before ((!) next, item); // _sorted-		}-		-		build_index ();-		-		if (find (key) == null) {-			warning (@"Can not find glyph \"$(key)\".");-			validate_index ();-			print_all ();-			return false;-		}-		-		return true;-	}--	public void print_all () {-		int indice = 0;-		-		print ("Data:\n");-		foreach (Item i in data) {-			print (@"key: $(i.name) indice: $(indice)\n");-			indice++;-		}-		-		print ("Index:\n");-		print ("\n");-		print ("row3\n");-		foreach (RowItem i in row3) {-			print (@"$(i.item.data.name)\n");-		}-		-		print ("\n");-		print ("row2\n");-		foreach (RowItem i in row2) {-			print (@"$(i.item.data.name)\n");-		}-		-		print ("\n");-		print ("row1\n");-		foreach (RowItem i in row1) {-			print (@"$(i.item.data.name)\n");-		}		-	}--	static int compare (string an, Item b) {-		string? bt = b.name;-		string bn = (!) bt;-		-		uint32 ac = 0;-		uint32 bc = 0;-				-		int i1 = 0;-		int i2 = 0;-		-		return_val_if_fail (bt != null, 0);-		-		int ca = an.char_count ();-		int cb = bn.char_count ();-		-		if (ca != cb) {-			return ca < cb ? 1 : -1;-		}-		-		while (true) {-			an.get_next_char (ref i1, out ac);-			bn.get_next_char (ref i2, out bc);-			-			if (ac == bc && ac != 0) {-				continue;-			}-			-			if (ac == bc) return 0;-			-			return (ac < bc) ? 1 : -1;-		}-	}-	-	public void build_index () {-		uint len;-		RowItem r;-		-		while (row1.length () > 0) {-			row1.remove_link (row1.first ());-		}--		while (row2.length () > 0) {-			row2.remove_link (row2.first ());-		}--		while (row3.length () > 0) {-			row3.remove_link (row3.first ());-		}+		uint i = 0; -		if (data.length () == 0) {-			return;-		}-				-		// row 1-		len = data.length () / 5;-		if (len == 0) len++;-		for (int i = 0; i < len; i++) {-			r = new RowItem ();-			r.item = data.nth (i * 5);-			r.level = 1;-			row1.append (r);-		}-		r = new RowItem ();-		r.item = data.last ();-		r.level = 1;-		r.last = true;-		row1.append (r);	-		-		// row 2-		len = row1.length () / 5;-		if (len == 0) len++;-		for (int i = 0; i < len; i++) {-			r = new RowItem ();-			r.next_row = row1.nth (i * 5);-			r.item = r.next_row.data.item; -			r.level = 2;-			row2.append (r);-		}-		r = new RowItem ();-		r.item = data.last ();-		r.level = 2;-		r.next_row = row1.last ();		-		r.last = true;-		row2.append (r);-		-		// row 3-		len = row2.length () / 5;-		if (len == 0) len++;-		for (int i = 0; i < len; i++) {-			r = new RowItem ();-			r.next_row = row2.nth (i * 5);-			r.item = r.next_row.data.item; -			r.level = 3;-			row3.append (r);-		}-		r = new RowItem ();-		r.item = data.last ();-		r.level = 3;-		r.next_row = row2.last ();-		r.last = true;	-		row3.append (r);-	}--	unowned List<Item>? find_next_index (string n) {-		unowned List<Item>? next = find_next_via_index (n);-		return next;-	}--	unowned List<Item>? find_index (string n) {-		unowned List<Item>? next = find_next_via_index (n);-		-		if (next == null) {-			return null;-		}-		-		if (compare (n, ((!)next).data) == 0) {-			return next;-		}-	-		if (((!)next) != data.first () && compare (n, ((!)next).prev.data) == 0) {-			return ((!)next).prev; // fetch previous since we are searching for the next one-		}-		-		return null; -	}-	-	unowned List<Item>? find_next_via_index (string n) {-		unowned List<Item> i = data.first ();-		unowned List<RowItem> r;-		int cmp;-		-		if (data.length () == 0) {-			return null;-		}--		r = row3.first ();-		int ti = 0;-		while (true) {-			cmp = compare (n, r.data.item.data);-			-			ti++;-			-			if (cmp == 1) {-				break;-			}-			-			if (cmp == 0) {-				return r.data.item;-			}-			-			if (r != row3.last ()) {-				r = r.next;-			} else {-				return null;+		foreach (var k in map.keys) {+			if (i == index) {+				return map.get (k); 			}-		} -		r = r.data.next_row;--		while (true) {-			cmp = compare (n, r.data.item.data);-			-			if (cmp == -1) {-				break;-			}--			if (cmp == 0) {-				return r.data.item;-			}-						-			if (r == row2.first ()) {;-				return r.data.item;-			} else r = r.prev;+			i++; 		}-		r = r.data.next_row;-		-		while (true) {-			cmp = compare (n, r.data.item.data);-			-			if (cmp == 1) {-				break;-			}-			-			if (cmp == 0) {-				return r.data.item;-			}-								-			if (r == row1.last ()) return null;-			else r = r.next;-		}-		i = r.data.item;-		-		-		while (true) {-			cmp = compare (n, i.data); -			if (cmp == -1) {-				// null?-				return i.next;-			}--			if (cmp == 0) {-				return i;-			}-						-			if (i == data.first ()) {-				return i;-			} else { -				i = i.prev;-			}-		}			+		return null; 	} -	public bool validate_index () {-		int cmp;-		Item prev;-		int index;-		-		if (data.length () == 0) {-			return true;-		}-		-		prev = data.first ().data;-		index = 0;-		foreach (Item i in data) {-			cmp = compare (prev.name, i);-		-			if (cmp == 1) {-				continue;-			}-						-			if (cmp == 0 && index != 0) {-				warning (@"Value is not unique: $(i.name).");-				return false;-			}--			if (cmp == -1) {-				warning (@"Value is not sorted: $cmp == cmp $(prev.name) $(i.name).");-				return false;-			}-			-			index++;-		}-	+	public bool insert (string key, GlyphCollection g) {+		map.set (key, g); 		return true; 	}--	class Item : GLib.Object {-		public string name;-		public GlyphCollection glyph_collection;-		-		public Item (string n, GlyphCollection gc) {-			glyph_collection = gc;-			name = n;-		}-	}--	class RowItem : GLib.Object {-		public unowned List<RowItem> next_row;-		public unowned List<Item> item;-		public int level = 0;-		public bool last = false;-	} }  }diff --git a/libbirdfont/KerningList.vala b/libbirdfont/KerningList.valaindex a864fa1..a8a05c9 100644--- a/libbirdfont/KerningList.vala+++ b/libbirdfont/KerningList.vala@@ -104,6 +104,10 @@ public class KerningList : FontDisplay { 			scroll = (int) (pairs - visible_rows); 		} 		+		if (visible_rows > pairs) {+			scroll = 0;+		} +		 		update_scrollbar (); 		redraw_area (0, 0, allocation.width, allocation.height); 	}diff --git a/libbirdfont/MainWindow.vala b/libbirdfont/MainWindow.valaindex 6c07c30..7538cab 100644--- a/libbirdfont/MainWindow.vala+++ b/libbirdfont/MainWindow.vala@@ -54,6 +54,16 @@ public class MainWindow { 		idle.attach (null);
 	}
 
+	public static void select_all_paths () {
+		Tool t = tools.get_current_tool ();
+		
+		if (! (t is MoveTool || t is ResizeTool)) {
+			Toolbox.select_tool_by_name ("move");
+		}
+		
+		get_current_glyph ().select_all_paths ();
+	}
+
 	public static DrawingTools get_drawing_tools () {
 		return tools.drawing_tools;
 	}
diff --git a/libbirdfont/MoveTool.vala b/libbirdfont/MoveTool.valaindex b9636e0..e4ef23a 100644--- a/libbirdfont/MoveTool.vala+++ b/libbirdfont/MoveTool.vala@@ -19,23 +19,19 @@ namespace BirdFont {  class MoveTool : Tool { -	bool move_path = false;-	bool moved = false;-	double last_x = 0;-	double last_y = 0;+	static bool move_path = false;+	static bool moved = false;+	static double last_x = 0;+	static double last_y = 0; 	-	double selection_x = 0;-	double selection_y = 0;	-	bool group_selection= false;+	static double selection_x = 0;+	static double selection_y = 0;	+	static bool group_selection= false; 	-	bool rotate_path = false;-	double last_rotate_y; 	static double selection_box_width = 0; 	static double selection_box_height = 0; 	static double selection_box_center_x = 0; 	static double selection_box_center_y = 0;-	double rotation = 0;-	double last_rotate = 0; 	 	public MoveTool (string n) { 		base (n, _("Move paths"), 'm', CTRL);@@ -44,137 +40,126 @@ class MoveTool : Tool { 		});  		deselect_action.connect((self) => {-			Glyph glyph = MainWindow.get_current_glyph ();-			glyph.clear_active_paths (); 		}); 				 		press_action.connect((self, b, x, y) => {-			Glyph glyph = MainWindow.get_current_glyph ();-						-			glyph.store_undo_state ();-			group_selection = false;-			-			foreach (Path p in glyph.active_paths) {-				if (is_over_rotate_handle (p, x, y)) {-					rotate_path = true;-					return;-				}-			}-			-			if (!glyph.is_over_selected_path (x, y)) {-				if (!glyph.select_path (x, y)) {-					glyph.clear_active_paths ();-				}-			}-			-			move_path = true;--			last_rotate = 0;-			rotation = 0;-			last_rotate_y = y;--			update_selection_boundries ();-						-			last_x = x;-			last_y = y;-			-			if (glyph.active_paths.length () == 0) {-				group_selection = true;-				selection_x = x;-				selection_y = y;	-			}-			-			update_boundries_for_selection ();+			press (b, x, y); 		});  		release_action.connect((self, b, x, y) => {-			Glyph glyph = MainWindow.get_current_glyph ();-			-			move_path = false;-			rotate_path = false;-			-			if (GridTool.is_visible () && moved) {-				foreach (Path p in glyph.active_paths) {-					tie_path_to_grid (p, x, y);-				}-			} else if (GridTool.has_ttf_grid ()) {-				foreach (Path p in glyph.active_paths) {-					tie_path_to_ttf_grid (p, x, y);-				}-			} -			-			if (group_selection) {-				select_group ();-			}-			-			group_selection = false;-			moved = false;+			release (b, x, y); 		}); 		 		move_action.connect ((self, x, y)	 => {-			Glyph glyph = MainWindow.get_current_glyph ();-			double dx = last_x - x;-			double dy = last_y - y; -			double p = PenTool.precision;-			-			if (move_path && (fabs(dx) > 0 || fabs (dy) > 0)) {-				moved = true;-				foreach (Path path in glyph.active_paths) {-					path.move (Glyph.ivz () * -dx * p, Glyph.ivz () * dy * p);-				}-			}-			-			if (rotate_path) {-				rotate (x, y);+			move (x, y);+		});+		+		key_press_action.connect ((self, keyval) => {+			key_press (keyval);+		});+		+		draw_action.connect ((self, cr, glyph) => {+			draw_actions (cr);+		});+	}++	public static void draw_actions (Context cr) {+		if (group_selection) {+			draw_selection_box (cr);+		}+	}+	+	public static void key_press (uint32 keyval) {+		Glyph g = MainWindow.get_current_glyph ();+		+		// delete selected paths+		if (keyval == Key.DEL || keyval == Key.BACK_SPACE) {+			foreach (Path p in g.active_paths) {+				g.path_list.remove (p);+				g.update_view (); 			} -			if (!rotate_path) {-				update_boundries_for_selection ();-				get_selection_box_boundries (out selection_box_center_x,-					out selection_box_center_y, out selection_box_width,-					out selection_box_height);	+			while (g.active_paths.length () > 0) {+				g.active_paths.remove_link (g.active_paths.first ());+			}+		}+		+		if (is_arrow_key (keyval)) {+			move_selected_paths (keyval);+		}+	}+	+	public static void move (int x, int y) {+		Glyph glyph = MainWindow.get_current_glyph ();+		double dx = last_x - x;+		double dy = last_y - y; +		double p = PenTool.precision;+		+		if (move_path && (fabs(dx) > 0 || fabs (dy) > 0)) {+			moved = true;+			foreach (Path path in glyph.active_paths) {+				path.move (Glyph.ivz () * -dx * p, Glyph.ivz () * dy * p); 			}+		} -			last_x = x;-			last_y = y;+		last_x = x;+		last_y = y; -			GlyphCanvas.redraw ();-		});+		GlyphCanvas.redraw ();+	}+	+	public static void release (int b, int x, int y) {+		Glyph glyph = MainWindow.get_current_glyph (); 		-		key_press_action.connect ((self, keyval) => {-			Glyph g = MainWindow.get_current_glyph ();-			-			// delete selected paths-			if (keyval == Key.DEL || keyval == Key.BACK_SPACE) {-				foreach (Path p in g.active_paths) {-					g.path_list.remove (p);-					g.update_view ();-				}--				while (g.active_paths.length () > 0) {-					g.active_paths.remove_link (g.active_paths.first ());-				}+		move_path = false;+		+		if (GridTool.is_visible () && moved) {+			foreach (Path p in glyph.active_paths) {+				tie_path_to_grid (p, x, y); 			}-			-			if (is_arrow_key (keyval)) {-				move_selected_paths (keyval);+		} else if (GridTool.has_ttf_grid ()) {+			foreach (Path p in glyph.active_paths) {+				tie_path_to_ttf_grid (p, x, y); 			}-		});+		}  		-		draw_action.connect ((self, cr, glyph) => {-			Glyph g = MainWindow.get_current_glyph ();-			-			if (g.active_paths.length () > 0) {-				draw_rotate_handle (cr);-			}-			-			if (group_selection) {-				draw_selection_box (cr);+		if (group_selection) {+			select_group ();+		}+		+		group_selection = false;+		moved = false;	+	}+		+	public static void press (int b, int x, int y) {+		Glyph glyph = MainWindow.get_current_glyph ();+					+		glyph.store_undo_state ();+		group_selection = false;+				+		if (!glyph.is_over_selected_path (x, y)) {+			if (!glyph.select_path (x, y)) {+				glyph.clear_active_paths (); 			}-		});+		}+		+		move_path = true;++		update_selection_boundries ();+					+		last_x = x;+		last_y = y;+		+		if (glyph.active_paths.length () == 0) {+			group_selection = true;+			selection_x = x;+			selection_y = y;	+		}+		+		update_boundries_for_selection ();	 	} 	-	void select_group () {+	static void select_group () { 		double x1 = Glyph.path_coordinate_x (Math.fmin (selection_x, last_x)); 		double y1 = Glyph.path_coordinate_y (Math.fmin (selection_y, last_y)); 		double x2 = Glyph.path_coordinate_x (Math.fmax (selection_x, last_x));@@ -185,18 +170,20 @@ class MoveTool : Tool { 		 		foreach (Path p in glyph.path_list) { 			if (p.xmin > x1 && p.xmax < x2 && p.ymin < y1 && p.ymax > y2) {-				glyph.active_paths.append (p);+				if (p.points.length () > 0) {+					glyph.active_paths.append (p);+				} 			} 		} 	} 	-	static void update_selection_boundries () {+	public static void update_selection_boundries () { 		get_selection_box_boundries (out selection_box_center_x, 			out selection_box_center_y, out selection_box_width, 			out selection_box_height);	 	} -	void draw_selection_box (Context cr) {+	static void draw_selection_box (Context cr) { 		double x = Math.fmin (selection_x, last_x); 		double y = Math.fmin (selection_y, last_y); @@ -212,33 +199,6 @@ class MoveTool : Tool { 		 		cr.restore (); 	}--	void draw_rotate_handle (Context cr) {-		double cx, cy, hx, hy;-		-		cx = Glyph.reverse_path_coordinate_x (selection_box_center_x);-		cy = Glyph.reverse_path_coordinate_y (selection_box_center_y);-		-		cr.save ();-		-		cr.set_source_rgba (0, 0, 0.3, 1);-		cr.rectangle (cx - 2.5, cy - 2.5, 5, 5);-		cr.fill ();--		hx = cos (rotation) * 75;-		hy = sin (rotation) * 75;--		cr.set_line_width (1);-		cr.move_to (cx, cy);-		cr.line_to (cx + hx, cy + hy);-		cr.stroke ();--		cr.set_source_rgba (0, 0, 0.3, 1);-		cr.rectangle (cx + hx - 2.5, cy + hy - 2.5, 5, 5);-		cr.fill ();-					-		cr.restore ();				-	} 	 	public static void get_selection_box_boundries (out double x, out double y, out double w, out double h) { 		double px, py, px2, py2;@@ -273,7 +233,7 @@ class MoveTool : Tool { 		y = py + (h / 2); 	} 	-	void move_selected_paths (uint key) {+	static void move_selected_paths (uint key) { 		Glyph glyph = MainWindow.get_current_glyph (); 		double x, y; 		@@ -304,11 +264,11 @@ class MoveTool : Tool { 		glyph.redraw_area (0, 0, glyph.allocation.width, glyph.allocation.height); 	} -	void tie_path_to_ttf_grid (Path p, double x, double y) {+	static void tie_path_to_ttf_grid (Path p, double x, double y) { 		tie_path_to_grid (p, x, y, true); 	}  -	void tie_path_to_grid (Path p, double x, double y, bool ttf_grid = false) {+	static void tie_path_to_grid (Path p, double x, double y, bool ttf_grid = false) { 		double sx, sy, qx, qy;	 		 		// tie to grid@@ -345,62 +305,6 @@ class MoveTool : Tool { 		} 	} 	-	/** Move rotate handle to pixel x,y. */-	void rotate (double x, double y) {-		double cx, cy, xc, yc, xc2, yc2, a, b, w, h;		-		Glyph glyph = MainWindow.get_current_glyph ();  -		double dx, dy;-		-		cx = Glyph.reverse_path_coordinate_x (selection_box_center_x);-		cy = Glyph.reverse_path_coordinate_y (selection_box_center_y);-		xc = selection_box_center_x;-		yc = selection_box_center_y;-		-		a = x - cx;-		b = y - cy;-		-		rotation = atan (b / a);-		-		if (a < 0) {-			rotation += PI;-		}-		-		foreach (Path p in glyph.active_paths) {-			p.rotate (rotation - last_rotate, selection_box_center_x, selection_box_center_y);-		}--		get_selection_box_boundries (out xc2, out yc2, out w, out h); --		dx = -(xc2 - xc);-		dy = -(yc2 - yc);-		-		foreach (Path p in glyph.active_paths) {-			p.move (dx, dy);-		}-		-		last_rotate = rotation;-		-		update_selection_boundries ();-	}--	bool is_over_rotate_handle (Path p, double x, double y) {-		double cx, cy, hx, hy;-		double size = 10;-		bool inx, iny;-		-		cx = Glyph.reverse_path_coordinate_x (selection_box_center_x);-		cy = Glyph.reverse_path_coordinate_y (selection_box_center_y);--		hx = cos (rotation) * 75;-		hy = sin (rotation) * 75;--		inx = x - size <= cx + hx - 2.5 <= x + size;-		iny = y - size <= cy + hy - 2.5 <= y + size;-		-		return inx && iny;-	}-- 	public static void flip_vertical () { 		flip (true); 	}diff --git a/libbirdfont/OpenFontFormat/GlyfTable.vala b/libbirdfont/OpenFontFormat/GlyfTable.valaindex a7e72c9..50f0bef 100644--- a/libbirdfont/OpenFontFormat/GlyfTable.vala+++ b/libbirdfont/OpenFontFormat/GlyfTable.vala@@ -116,6 +116,10 @@ class GlyfTable : Table { 		 		num_glyphs = glyphs.length (); 		+		if (glyphs.length () == 0) {+			warning ("No glyphs in glyf table.");+		}+		 		foreach (Glyph g in glyphs) { 			// set values for loca table 			assert (fd.length () % 4 == 0);@@ -155,6 +159,10 @@ class GlyfTable : Table { 		 		unassigned_glyphs = new List<Glyph> (); 		+		if (font.get_glyph_indice (0) == null) {+			warning ("No glyphs in font.");+		}+				 		// add glyphs, first all assigned then the unassigned ones 		for (indice = 0; (gl = font.get_glyph_indice (indice)) != null; indice++) {		 			g = (!) gl;@@ -176,6 +184,7 @@ class GlyfTable : Table { 			if (!g.is_unassigned ()) { 				glyphs.append (g); 			} else {+				printd ("Adding unassigned glyph."); 				unassigned_glyphs.append (g); 			} 		}diff --git a/libbirdfont/OpenFontFormat/OpenFontFormatWriter.vala b/libbirdfont/OpenFontFormat/OpenFontFormatWriter.valaindex 4e589b3..350a93e 100644--- a/libbirdfont/OpenFontFormat/OpenFontFormatWriter.vala+++ b/libbirdfont/OpenFontFormat/OpenFontFormatWriter.vala@@ -75,8 +75,4 @@ class OpenFontFormatWriter : Object  { 	} } -void printd (string s) {-	//print (s);-}- }diff --git a/libbirdfont/OverView.vala b/libbirdfont/OverView.valaindex a917269..2299d6d 100644--- a/libbirdfont/OverView.vala+++ b/libbirdfont/OverView.vala@@ -791,6 +791,7 @@ public class OverView : FontDisplay { 		double nrows = 0; 		double pos = 0; 		double size;+		double visible_rows; 		 		if (rows == 0) { 			MainWindow.set_scrollbar_size (0);@@ -809,9 +810,11 @@ public class OverView : FontDisplay { 				nrows = 1; 			} 			-			scroll_size = rows / (nrows - rows);+			// FIXME: this is not correct+			visible_rows = allocation.height / OverViewItem.height;+			scroll_size = visible_rows / nrows; 			MainWindow.set_scrollbar_size (scroll_size);-			pos = first_visible / (nrows * items_per_row - rows * items_per_row);+			pos = first_visible / (nrows * items_per_row - visible_rows * items_per_row); 			MainWindow.set_scrollbar_position (pos); 		} 	}diff --git a/libbirdfont/PenTool.vala b/libbirdfont/PenTool.valaindex c92dcbe..d71c2a4 100644--- a/libbirdfont/PenTool.vala+++ b/libbirdfont/PenTool.vala@@ -465,6 +465,8 @@ public class PenTool : Tool { 				}				 			} 		}+		+		update_selected_points (); 	}  	public static bool is_counter_path (Path path) {diff --git a/libbirdfont/ResizeTool.vala b/libbirdfont/ResizeTool.valaindex 002f577..0f49a5f 100644--- a/libbirdfont/ResizeTool.vala+++ b/libbirdfont/ResizeTool.vala@@ -29,9 +29,14 @@ class ResizeTool : Tool { 	static double selection_box_height = 0; 	static double selection_box_center_x = 0; 	static double selection_box_center_y = 0;-	++	static bool rotate_path = false;+	static double last_rotate_y;+	static double rotation = 0;+	static double last_rotate = 0;+		 	public ResizeTool (string n) {-		base (n, _("Resize paths"));+		base (n, _("Resize and rotate paths")); 		 		resize_handle = Icons.get_icon ("resize_handle.png"); 	@@ -39,8 +44,6 @@ class ResizeTool : Tool { 		});  		deselect_action.connect((self) => {-			Glyph glyph = MainWindow.get_current_glyph ();-			glyph.clear_active_paths (); 		}); 				 		press_action.connect((self, b, x, y) => {@@ -64,18 +67,26 @@ class ResizeTool : Tool { 					return;					 				} 			}-			-			if (!glyph.is_over_selected_path (x, y)) {-				if (!glyph.select_path (x, y)) {-					glyph.clear_active_paths ();++			foreach (Path p in glyph.active_paths) {+				if (is_over_rotate_handle (p, x, y)) {+					rotate_path = true;+					return; 				} 			}+			+			last_rotate = 0;+			rotation = 0;+			last_rotate_y = y; -			update_selection_boundries ();++			MoveTool.press (b, x, y); 		});  		release_action.connect((self, b, x, y) => { 			resize_path = false;+			rotate_path = false;+			MoveTool.release (b, x, y); 		}); 		 		move_action.connect ((self, x, y)	 => {@@ -83,7 +94,19 @@ class ResizeTool : Tool { 				resize (x, y); 			} +			if (rotate_path) {+				rotate (x, y);+			}++			if (!rotate_path) {+				MoveTool.update_boundries_for_selection ();+				MoveTool.get_selection_box_boundries (out selection_box_center_x,+					out selection_box_center_y, out selection_box_width,+					out selection_box_height);	+			}+		 			GlyphCanvas.redraw ();+			MoveTool.move (x, y); 		}); 		 		draw_action.connect ((self, cr, glyph) => {@@ -95,15 +118,94 @@ class ResizeTool : Tool { 				cr.paint (); 			} 			-+			if (g.active_paths.length () > 0) {+				draw_rotate_handle (cr);+			}+		+			MoveTool.draw_actions (cr); 		}); 	} -	static void update_selection_boundries () {-		MoveTool.update_boundries_for_selection ();-		MoveTool.get_selection_box_boundries (out selection_box_center_x,-			out selection_box_center_y, out selection_box_width,-			out selection_box_height);	+	/** Move rotate handle to pixel x,y. */+	static void rotate (double x, double y) {+		double cx, cy, xc, yc, xc2, yc2, a, b, w, h;		+		Glyph glyph = MainWindow.get_current_glyph ();  +		double dx, dy;+		+		cx = Glyph.reverse_path_coordinate_x (selection_box_center_x);+		cy = Glyph.reverse_path_coordinate_y (selection_box_center_y);+		xc = selection_box_center_x;+		yc = selection_box_center_y;+		+		a = x - cx;+		b = y - cy;+		+		rotation = atan (b / a);+		+		if (a < 0) {+			rotation += PI;+		}+		+		foreach (Path p in glyph.active_paths) {+			p.rotate (rotation - last_rotate, selection_box_center_x, selection_box_center_y);+		}++		MoveTool.get_selection_box_boundries (out xc2, out yc2, out w, out h); ++		dx = -(xc2 - xc);+		dy = -(yc2 - yc);+		+		foreach (Path p in glyph.active_paths) {+			p.move (dx, dy);+		}+		+		last_rotate = rotation;+		+		MoveTool.update_selection_boundries ();+	}++	static bool is_over_rotate_handle (Path p, double x, double y) {+		double cx, cy, hx, hy;+		double size = 10;+		bool inx, iny;+		+		cx = Glyph.reverse_path_coordinate_x (selection_box_center_x);+		cy = Glyph.reverse_path_coordinate_y (selection_box_center_y);++		hx = cos (rotation) * 75;+		hy = sin (rotation) * 75;++		inx = x - size <= cx + hx - 2.5 <= x + size;+		iny = y - size <= cy + hy - 2.5 <= y + size;+		+		return inx && iny;+	}+	+	static void draw_rotate_handle (Context cr) {+		double cx, cy, hx, hy;+		+		cx = Glyph.reverse_path_coordinate_x (selection_box_center_x);+		cy = Glyph.reverse_path_coordinate_y (selection_box_center_y);+		+		cr.save ();+		+		cr.set_source_rgba (0, 0, 0.3, 1);+		cr.rectangle (cx - 2.5, cy - 2.5, 5, 5);+		cr.fill ();++		hx = cos (rotation) * 75;+		hy = sin (rotation) * 75;++		cr.set_line_width (1);+		cr.move_to (cx, cy);+		cr.line_to (cx + hx, cy + hy);+		cr.stroke ();++		cr.set_source_rgba (0, 0, 0.3, 1);+		cr.rectangle (cx + hx - 2.5, cy + hy - 2.5, 5, 5);+		cr.fill ();+					+		cr.restore ();				 	}  	double get_resize_ratio (double x, double y) {diff --git a/libbirdfont/TabBar.vala b/libbirdfont/TabBar.valaindex afa0415..a41fd11 100644--- a/libbirdfont/TabBar.vala+++ b/libbirdfont/TabBar.vala@@ -186,13 +186,18 @@ public class TabBar : GLib.Object { 	public bool close_tab (int index, bool background_tab = false) {	 		unowned List<Tab?>? lt; 		Tab t;+		EmptyTab empty_tab_canvas;+		Tab empty_tab; 		-		if (tabs.length () <= 1) {+		if (!(0 <= index < tabs.length ())) { 			return false; 		} 		-		if (!(0 <= index < tabs.length ())) {-			return false;+		if (tabs.length () == 1) {+			empty_tab_canvas = new EmptyTab ("", "");+			MainWindow.get_glyph_canvas ().set_current_glyph (empty_tab_canvas);+			empty_tab = new Tab (empty_tab_canvas, 0, false);+			signal_tab_selected (empty_tab); 		} 		 		lt = tabs.nth(index);@@ -218,6 +223,7 @@ public class TabBar : GLib.Object { 		} 		 		select_tab (index);+		 		return false; 	} 	diff --git a/libbirdfont/TestCases.vala b/libbirdfont/TestCases.valaindex b30726b..4201942 100644--- a/libbirdfont/TestCases.vala+++ b/libbirdfont/TestCases.vala@@ -24,7 +24,6 @@ class TestCases { 		add (test_data_reader, "Font data reader"); 		add (test_argument, "Argument list"); 		add (test_glyph_ranges, "Glyph ranges");-		add (test_glyph_table, "Glyph table"); 		add (test_hex, "Unicode hex values"); 		add (test_reverse_path, "Reverse path"); 		add (test_reverse_random_triangles, "Reverse random paths");@@ -742,79 +741,6 @@ class TestCases { 		} 	} -	public static void test_glyph_table () {-		GlyphTable table = new GlyphTable ();-		List<GlyphCollection> gc = new List<GlyphCollection> ();-		List<unowned GlyphCollection> gc_copy;-		GlyphCollection g;-		-		return_if_fail (table.length () == 0);-		return_if_fail (table.get ("Some glyph") == null);-		-		// generate test data-		for (uint i = 0; i < 1000; i++) {-			gc.append (new GlyphCollection (new Glyph (@"TEST $i", i + 'a')));-		}--		g = gc.first ().data;-		if (!table.insert (g.get_unicode (), g)) {-			warning (@"Failed to insert $(g.get_name ())");-			return;-		}-		gc.append (g);-		-		// insert in random order-		gc_copy = gc.copy ();-		for (uint i = 0; gc_copy.length () > 0; i++) {-			int t = (int) ((gc_copy.length () - 1) * Random.next_double ());-			g = gc_copy.nth (t).data;-			-			if (!table.insert (g.get_name (), g)) {-				warning (@"Failed to insert $(g.get_name ())");-				return;-			}-			-			gc_copy.remove_all (g);-			-			if (!table.validate_index ()) {-				table.print_all ();-				warning ("index is invalid");-				return;-			}-		}-		-		if (table.length () != gc.length ()) {-			warning ("Table length does not match number of glyphs, $(table.length ()) != $(gc.length ())");-			return;-		}-		-		// validate table-		for (uint i = 0; i > 1000; i++) {-			g = (!) table.get (gc.nth (i).data.get_name ());-			return_if_fail (gc.nth (i).data == g);-		}-		-		// search -		for (int i = 0; i < 2000; i++) {-			int t = (int) (999 * Random.next_double ());-			if (table.get (@"TEST $t") == null) {-				table.print_all ();-				warning (@"Did't find TEST $t in glyph table.");-				return;-			}-		}-		-		// remove-		table.remove ("TEST 0");-		table.remove ("TEST 53");-		return_if_fail (table.get ("TEST 0") == null);-		return_if_fail (table.get ("TEST 53") == null);-		-		// search -		return_if_fail (table.get ("TEST 52") != null);-		return_if_fail (table.get ("TEST 54") != null);-	}- 	public static void test_hex () { 		test_hex_conv ('H', "U+48", 72); 		test_hex_conv ('1', "U+31", 49);diff --git a/libbirdfont/ZoomTool.vala b/libbirdfont/ZoomTool.valaindex d28b145..9aa6268 100644--- a/libbirdfont/ZoomTool.vala+++ b/libbirdfont/ZoomTool.vala@@ -23,7 +23,7 @@ class ZoomTool : Tool { 	List<Tab> views = new List<Tab> (); 	 	public ZoomTool (string n) {-		base (n, "Zoom");+		base (n, "Zoom", 'z');  		select_action.connect((self) => { 		});

Contact

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