Clone in a terminal:
Commit de058b1
Johan Mattsson - 2013-08-30T10:58:30+00:00
de058b1ed2f4cb994e9cd2c379bf08739e4db27ajohan.mattsson.m@gmail.com

resize tool

Changed files (4)

Diff

diff --git a/icons/resize.png b/icons/resize.pngnew file mode 100644index 0000000..a483bb6Binary files /dev/null and b/icons/resize.png differdiff --git a/libbirdfont/DrawingTools.vala b/libbirdfont/DrawingTools.valaindex b2dccba..c6ff3ad 100644--- a/libbirdfont/DrawingTools.vala+++ b/libbirdfont/DrawingTools.vala@@ -70,7 +70,10 @@ public class DrawingTools : ToolCollection  {  		Tool move_tool = new MoveTool ("move"); 		draw_tools.add_tool (move_tool);-+		+		Tool resize_tool = new ResizeTool ("resize");+		draw_tools.add_tool (resize_tool);+		 		// quadratic Bézier points 		Tool quadratic_points = new Tool ("quadratic_points", _("Create quadratic Bézier curves")); 		quadratic_points.select_action.connect ((self) => {diff --git a/libbirdfont/MoveTool.vala b/libbirdfont/MoveTool.valaindex 96f1ab7..c92c8c9 100644--- a/libbirdfont/MoveTool.vala+++ b/libbirdfont/MoveTool.vala@@ -1,5 +1,5 @@ /*-    Copyright (C) 2012 Johan Mattsson+    Copyright (C) 2012 2013 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 @@ -23,11 +23,7 @@ class MoveTool : Tool { 	bool moved = false; 	double last_x = 0; 	double last_y = 0;--	bool resize_path = false;-	Path? resized_path = null;-	double last_resize_y;-+	 	bool rotate_path = false; 	double last_rotate_y; 	static double selection_box_width = 0;@@ -37,13 +33,9 @@ class MoveTool : Tool { 	double rotation = 0; 	double last_rotate = 0; 	-	ImageSurface? resize_handle;-	 	public MoveTool (string n) { 		base (n, _("Move paths"), 'm', CTRL);-		-		resize_handle = Icons.get_icon ("resize_handle.png");-	+ 		select_action.connect((self) => { 		}); @@ -58,28 +50,12 @@ class MoveTool : Tool { 			glyph.store_undo_state (); 			 			foreach (Path p in glyph.active_paths) {-				if (is_over_resize_handle (p, x, y)) {-					resize_path = true;-					resized_path = p;-					last_resize_y = y;-					return;-				}-				 				if (is_over_rotate_handle (p, x, y)) { 					rotate_path = true; 					return; 				} 			} 			-			if (resized_path != null) {-				if (is_over_resize_handle ((!) resized_path, x, y)) {-					resize_path = true;-					last_resize_y = y;-					rotation = 0;-					return;					-				}-			}-			 			if (!glyph.is_over_selected_path (x, y)) { 				if (!glyph.select_path (x, y)) { 					glyph.clear_active_paths ();@@ -102,7 +78,6 @@ class MoveTool : Tool { 			Glyph glyph = MainWindow.get_current_glyph (); 			 			move_path = false;-			resize_path = false; 			rotate_path = false; 			 			if (GridTool.is_visible () && moved) {@@ -127,10 +102,6 @@ class MoveTool : Tool { 				} 			} 			-			if (resize_path && can_resize (x, y)) {-				resize (x, y);-			}- 			if (rotate_path) { 				rotate (x, y); 			}@@ -169,12 +140,6 @@ class MoveTool : Tool { 		 		draw_action.connect ((self, cr, glyph) => { 			Glyph g = MainWindow.get_current_glyph ();-			ImageSurface resize_img = (!) resize_handle;-			-			foreach (Path p in g.active_paths) {-				cr.set_source_surface (resize_img, Glyph.reverse_path_coordinate_x (p.xmax) - 10, Glyph.reverse_path_coordinate_y (p.ymax) - 10);-				cr.paint ();-			} 			 			if (g.active_paths.length () > 0) { 				draw_rotate_handle (cr);@@ -279,98 +244,6 @@ class MoveTool : Tool { 		glyph.redraw_area (0, 0, glyph.allocation.width, glyph.allocation.height); 	} -	double get_resize_ratio (double x, double y) {-		double ratio;-		double h;-		Path rp;-		-		return_val_if_fail (!is_null (resized_path), 0);-		rp = (!) resized_path;-		h = rp.xmax - rp.xmin;--		ratio = 1;-		ratio -= 0.7 * PenTool.precision * (Glyph.path_coordinate_y (last_resize_y) - Glyph.path_coordinate_y (y)) / h;		--		return ratio;-	}--	/** Move resize handle to pixel x,y. */-	void resize (double x, double y) {-		Path rp;-		double ratio;-		double resize_pos_x = 0;-		double resize_pos_y = 0;-		Glyph glyph = MainWindow.get_current_glyph ();-		double selection_minx, selection_miny, dx, dy;-		-		ratio = get_resize_ratio (x, y);--		return_if_fail (!is_null (resized_path));-		rp = (!) resized_path;-		get_selection_min (out resize_pos_x, out resize_pos_y);-		-		foreach (Path selected_path in glyph.active_paths) {-			selected_path.resize (ratio);-		}-		-		// resize paths-		foreach (Path selected_path in glyph.active_paths) {-			selected_path.resize (ratio);-		}-		-		// move paths relative to the updated xmin and xmax-		get_selection_min (out selection_minx, out selection_miny);-		dx = resize_pos_x - selection_minx;-		dy = resize_pos_y - selection_miny;-		foreach (Path selected_path in glyph.active_paths) {-			selected_path.move (dx, dy);-		}-		-		last_resize_y = y;-	}--	void get_selection_min (out double x, out double y) {-		Glyph glyph = MainWindow.get_current_glyph ();-		x = double.MAX;-		y = double.MAX;-		foreach (Path p in glyph.active_paths) {-			if (p.xmin < x) {-				x = p.xmin;-			}-			-			if (p.ymin < y) {-				y = p.ymin;-			}-		}-	}--	bool can_resize (double x, double y) {-		Glyph glyph = MainWindow.get_current_glyph ();-		double h, w;-		double ratio = get_resize_ratio (x, y);-		-		foreach (Path selected_path in glyph.active_paths) {-			h = selected_path.ymax - selected_path.ymin;-			w = selected_path.xmax - selected_path.xmin;-			-			if (selected_path.points.length () == 0) {-				continue;-			}-			-			if (h * ratio < 1 || w * ratio < 1) {-				return false;-			}-		}-		-		return true;-	}--	bool is_over_resize_handle (Path p, double x, double y) {-		double handle_x = Math.fabs (Glyph.reverse_path_coordinate_x (p.xmax)); -		double handle_y = Math.fabs (Glyph.reverse_path_coordinate_y (p.ymax));-		return fabs (handle_x - x + 10) < 20 && fabs (handle_y - y + 10) < 20;-	}- 	void tie_path_to_grid (Path p, double x, double y) { 		double sx, sy, qx, qy;	 		diff --git a/libbirdfont/ResizeTool.vala b/libbirdfont/ResizeTool.valanew file mode 100644index 0000000..2b1f516--- /dev/null+++ b/libbirdfont/ResizeTool.vala@@ -0,0 +1,267 @@+/*+    Copyright (C) 2013 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.+*/++using Math;+using Cairo;++namespace BirdFont {++class ResizeTool : Tool {+	+	bool resize_path = false;+	Path? resized_path = null;+	double last_resize_y;++	ImageSurface? resize_handle;++	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;+	+	public ResizeTool (string n) {+		base (n, _("Resize paths"));+		+		resize_handle = Icons.get_icon ("resize_handle.png");+	+		select_action.connect((self) => {+		});++		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 ();+			+			foreach (Path p in glyph.active_paths) {+				if (is_over_resize_handle (p, x, y)) {+					resize_path = true;+					resized_path = p;+					last_resize_y = y;+					return;+				}+			}+			+			if (resized_path != null) {+				if (is_over_resize_handle ((!) resized_path, x, y)) {+					resize_path = true;+					last_resize_y = y;+					return;					+				}+			}+			+			if (!glyph.is_over_selected_path (x, y)) {+				if (!glyph.select_path (x, y)) {+					glyph.clear_active_paths ();+				}+			}++			update_selection_boundries ();+		});++		release_action.connect((self, b, x, y) => {+			resize_path = false;+		});+		+		move_action.connect ((self, x, y)	 => {+			Glyph glyph = MainWindow.get_current_glyph ();+			+			if (resize_path && can_resize (x, y)) {+				resize (x, y);+			}++			MainWindow.get_glyph_canvas ().redraw ();+		});+		+		draw_action.connect ((self, cr, glyph) => {+			Glyph g = MainWindow.get_current_glyph ();+			ImageSurface resize_img = (!) resize_handle;+			+			foreach (Path p in g.active_paths) {+				cr.set_source_surface (resize_img, Glyph.reverse_path_coordinate_x (p.xmax) - 10, Glyph.reverse_path_coordinate_y (p.ymax) - 10);+				cr.paint ();+			}+			++		});+	}++	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);	+	}++	static void get_selection_box_boundries (out double x, out double y, out double w, out double h) {+		double px, py, px2, py2;+		Glyph glyph = MainWindow.get_current_glyph ();+		+		px = 10000;+		py = 10000;+		px2 = -10000;+		py2 = -10000;+		+		foreach (Path p in glyph.active_paths) {+			if (px > p.xmin) {+				px = p.xmin;+			} ++			if (py > p.ymin) {+				py = p.ymin;+			}++			if (px2 < p.xmax) {+				px2 = p.xmax;+			}+			+			if (py2 < p.ymax) {+				py2 = p.ymax;+			}+		}+		+		w = px2 - px;+		h = py2 - py;+		x = px + (w / 2);+		y = py + (h / 2);+	}+	+	void move_selected_paths (uint key) {+		Glyph glyph = MainWindow.get_current_glyph ();+		double x, y;+		+		x = 0;+		y = 0;+		+		switch (key) {+			case Key.UP:+				y = 1;+				break;+			case Key.DOWN:+				y = -1;+				break;+			case Key.LEFT:+				x = -1;+				break;+			case Key.RIGHT:+				x = 1;+				break;+			default:+				break;+		}+		+		foreach (Path path in glyph.active_paths) {+			path.move (x * Glyph.ivz (), y * Glyph.ivz ());+		}+		+		glyph.redraw_area (0, 0, glyph.allocation.width, glyph.allocation.height);+	}++	double get_resize_ratio (double x, double y) {+		double ratio;+		double h;+		Path rp;+		+		return_val_if_fail (!is_null (resized_path), 0);+		rp = (!) resized_path;+		h = rp.xmax - rp.xmin;++		ratio = 1;+		ratio -= 0.7 * PenTool.precision * (Glyph.path_coordinate_y (last_resize_y) - Glyph.path_coordinate_y (y)) / h;		++		return ratio;+	}++	/** Move resize handle to pixel x,y. */+	void resize (double x, double y) {+		Path rp;+		double ratio;+		double resize_pos_x = 0;+		double resize_pos_y = 0;+		Glyph glyph = MainWindow.get_current_glyph ();+		double selection_minx, selection_miny, dx, dy;+		+		ratio = get_resize_ratio (x, y);++		return_if_fail (!is_null (resized_path));+		rp = (!) resized_path;+		get_selection_min (out resize_pos_x, out resize_pos_y);+		+		foreach (Path selected_path in glyph.active_paths) {+			selected_path.resize (ratio);+		}+		+		// resize paths+		foreach (Path selected_path in glyph.active_paths) {+			selected_path.resize (ratio);+		}+		+		// move paths relative to the updated xmin and xmax+		get_selection_min (out selection_minx, out selection_miny);+		dx = resize_pos_x - selection_minx;+		dy = resize_pos_y - selection_miny;+		foreach (Path selected_path in glyph.active_paths) {+			selected_path.move (dx, dy);+		}+		+		last_resize_y = y;+	}++	void get_selection_min (out double x, out double y) {+		Glyph glyph = MainWindow.get_current_glyph ();+		x = double.MAX;+		y = double.MAX;+		foreach (Path p in glyph.active_paths) {+			if (p.xmin < x) {+				x = p.xmin;+			}+			+			if (p.ymin < y) {+				y = p.ymin;+			}+		}+	}++	bool can_resize (double x, double y) {+		Glyph glyph = MainWindow.get_current_glyph ();+		double h, w;+		double ratio = get_resize_ratio (x, y);+		+		foreach (Path selected_path in glyph.active_paths) {+			h = selected_path.ymax - selected_path.ymin;+			w = selected_path.xmax - selected_path.xmin;+			+			if (selected_path.points.length () == 0) {+				continue;+			}+			+			if (h * ratio < 1 || w * ratio < 1) {+				return false;+			}+		}+		+		return true;+	}++	bool is_over_resize_handle (Path p, double x, double y) {+		double handle_x = Math.fabs (Glyph.reverse_path_coordinate_x (p.xmax)); +		double handle_y = Math.fabs (Glyph.reverse_path_coordinate_y (p.ymax));+		return fabs (handle_x - x + 10) < 20 && fabs (handle_y - y + 10) < 20;+	}+}++}

Contact

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