Commit de058b1
resize tool
Changed files (4)
addedicons/resize.pngmodifiedlibbirdfont/DrawingTools.valamodifiedlibbirdfont/MoveTool.valaaddedlibbirdfont/ResizeTool.vala
Diff
new file mode 100644Binary files /dev/null and b/icons/resize.png differ@@ -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) => {@@ -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; new file mode 100644@@ -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;+ }+}++}