Commit ef2b95c
New bezier drawing tool
Changed files (7)
addedlibbirdfont/BezierTool.valamodifiedlibbirdfont/DrawingTools.valadeletedlibbirdfont/ForesightTool.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/MainWindow.valamodifiedlibbirdfont/PenTool.valamodifiedresources/icons.bf
Diff
new file mode 100644@@ -0,0 +1,228 @@+/*+ 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.+*/++using Math;+using Cairo;++namespace BirdFont {++/** Create Beziér curves. */+public class BezierTool : Tool {+ + public const uint NONE = 0;+ public const uint MOVE_POINT = 1;+ public const uint MOVE_HANDLES = 2;+ public const uint MOVE_LAST_HANDLE = 3;+ public const uint MOVE_FIRST_HANDLE = 4;+ + uint state = NONE;+ bool move_right_handle = true;+ int previous_point = 0;+ + Path current_path = new Path ();+ EditPoint current_point = new EditPoint ();++ int last_x = 0;+ int last_y = 0;++ double last_release_time = 0;+ + public BezierTool (string name) {+ base (name, t_ ("Create Beziér curves"));++ select_action.connect ((self) => {+ state = NONE;+ MainWindow.set_cursor (NativeWindow.VISIBLE);+ });++ deselect_action.connect ((self) => {+ state = NONE;+ MainWindow.set_cursor (NativeWindow.VISIBLE);+ });+ + press_action.connect ((self, b, x, y) => {+ press (b, x, y);+ });++ double_click_action.connect ((self, b, x, y) => {+ });++ release_action.connect ((self, b, x, y) => {+ release (b, x, y);+ });++ move_action.connect ((self, x, y) => {+ move (x, y);+ });+ + key_press_action.connect ((self, keyval) => {+ });+ + key_release_action.connect ((self, keyval) => {+ });+ + draw_action.connect ((tool, cairo_context, glyph) => {+ if (PenTool.can_join (current_point)) {+ PenTool.draw_join_icon (cairo_context, last_x, last_y);+ }+ });+ }+ + public void press (int b, int x, int y) {+ Glyph g = MainWindow.get_current_glyph ();+ double px, py;+ Path? p;+ Path path;++ if (b == 2) {+ if (g.is_open ()) {+ g.close_path ();+ } else {+ g.open_path ();+ }+ + MainWindow.set_cursor (NativeWindow.VISIBLE);+ state = NONE;++ return;+ }+ + PenTool.update_orientation ();+ + MainWindow.set_cursor (NativeWindow.HIDDEN);+ g.open_path ();+ + px = Glyph.path_coordinate_x (x);+ py = Glyph.path_coordinate_y (y); ++ if (state == NONE) {+ g.open_path ();+ current_path = new Path ();+ current_path.reopen ();+ current_path.hide_end_handle = true;+ current_point = current_path.add (px, py);+ current_point.get_left_handle ().convert_to_line ();+ current_point.recalculate_linear_handles ();+ g.add_path (current_path);+ GlyphCanvas.redraw ();+ state = MOVE_POINT;+ } else if (state == MOVE_POINT) {+ if (PenTool.can_join (current_point)) {+ p = PenTool.join_paths (current_point);+ + return_if_fail (p != null);+ path = (!) p;+ + if (current_path.points.size == 1) {+ return_if_fail (path.is_open ());+ current_path = path;+ current_point = path.get_last_point ();+ state = MOVE_POINT;+ } else {+ g.open_path ();+ current_path = path;+ current_point = path.get_first_point ();+ state = MOVE_LAST_HANDLE; + }+ } else {+ state = MOVE_HANDLES;+ }+ }+ }++ public void release (int b, int x, int y) {+ double px, py;+ Glyph g;+ + // ignore double clicks+ if ((GLib.get_real_time () - last_release_time) / 1000000.0 < 0.2) {+ last_release_time = GLib.get_real_time ();+ return;+ }+ last_release_time = GLib.get_real_time ();+ + px = Glyph.path_coordinate_x (x);+ py = Glyph.path_coordinate_y (y);+ + if (state == MOVE_HANDLES) {+ current_point = current_path.add (px, py);+ current_path.hide_end_handle = true;+ current_point.get_left_handle ().convert_to_line ();+ current_point.recalculate_linear_handles ();+ GlyphCanvas.redraw ();+ state = MOVE_POINT;+ } else if (state == MOVE_LAST_HANDLE) {+ current_path.update_region_boundaries ();+ g = MainWindow.get_current_glyph ();+ g.close_path ();+ MainWindow.set_cursor (NativeWindow.VISIBLE);+ + if (Path.is_counter (g.get_paths (), current_path)) {+ current_path.force_direction (Direction.COUNTER_CLOCKWISE);+ } else {+ current_path.force_direction (Direction.CLOCKWISE);+ }+ + state = NONE;+ }+ }+ + public void move (int x, int y) {+ double px, py;+ + last_x = x;+ last_y = y;+ + px = Glyph.path_coordinate_x (x);+ py = Glyph.path_coordinate_y (y); + + if (state == MOVE_POINT) {+ current_point.x = px;+ current_point.y = py;+ current_path.hide_end_handle = true;+ current_point.recalculate_linear_handles ();+ GlyphCanvas.redraw ();+ } else if (state == MOVE_HANDLES || state == MOVE_LAST_HANDLE) {+ current_path.hide_end_handle = false;+ current_point.set_reflective_handles (true);+ current_point.convert_to_curve ();+ current_point.get_right_handle ().move_to_coordinate (px, py);+ GlyphCanvas.redraw ();+ }+ + if (current_path.points.size > 0) {+ current_path.get_first_point ().set_reflective_handles (false);+ current_path.get_last_point ().set_reflective_handles (false);+ }+ }+ + public void switch_to_line_mode () {+ int s = current_path.points.size;+ if (s > 2) {+ current_path.points.get (s - 2).get_right_handle ().convert_to_line ();+ current_point.get_left_handle ().convert_to_line ();+ }+ }+ + public void stop_drawing () {+ if (state == MOVE_POINT && current_path.points.size > 0) {+ current_path.delete_last_point ();+ }+ + state = NONE;+ }+ +}++}@@ -40,7 +40,7 @@ public class DrawingTools : ToolCollection { public static MoveTool move_tool; public static PenTool pen_tool; - public static ForesightTool foresight_tool;+ public static BezierTool bezier_tool; PointTool point_tool; public static ZoomTool zoom_tool; public static ResizeTool resize_tool;@@ -121,15 +121,15 @@ public class DrawingTools : ToolCollection { font_name.add_tool (new FontName ()); // Draw tools- foresight_tool = new ForesightTool ("foresight");- foresight_tool.select_action.connect ((self) => {+ bezier_tool = new BezierTool ("bezier_tool");+ bezier_tool.select_action.connect ((self) => { update_drawing_and_background_tools (self); });- draw_tools.add_tool (foresight_tool);+ draw_tools.add_tool (bezier_tool); Tool bezier_line = new Tool ("bezier_line", t_("Convert the last segment to a straight line")); bezier_line.select_action.connect ((self) => {- foresight_tool.switch_to_line_mode ();+ bezier_tool.switch_to_line_mode (); }); bezier_line.is_tool_modifier = true; draw_tools.add_tool (bezier_line);@@ -589,8 +589,8 @@ public class DrawingTools : ToolCollection { current = MainWindow.get_toolbox ().get_current_tool (); - if (current is ForesightTool) {- ((ForesightTool) current).stop_drawing ();+ if (current is BezierTool) {+ ((BezierTool) current).stop_drawing (); } PenTool.reset_stroke ();@@ -821,7 +821,7 @@ public class DrawingTools : ToolCollection { || pen_tool.is_selected () || track_tool.is_selected () || point_tool.is_selected ()- || foresight_tool.is_selected ();+ || bezier_tool.is_selected (); StrokeTool.stroke_width = object_stroke.get_value (); @@ -1097,9 +1097,9 @@ public class DrawingTools : ToolCollection { Toolbox tb = MainWindow.get_toolbox (); tb.reset_active_tool ();- update_drawing_and_background_tools (foresight_tool);- tb.select_tool (foresight_tool);- tb.set_current_tool (foresight_tool);+ update_drawing_and_background_tools (bezier_tool);+ tb.select_tool (bezier_tool);+ tb.set_current_tool (bezier_tool); set_point_type_from_preferences (); @@ -1269,7 +1269,7 @@ public class DrawingTools : ToolCollection { move_background.set_selected (false); cut_background.set_selected (false); - foresight_tool.set_selected (false);+ bezier_tool.set_selected (false); pen_tool.set_selected (false); point_tool.set_selected (false); zoom_tool.set_selected (false);@@ -1296,7 +1296,7 @@ public class DrawingTools : ToolCollection { if (resize_tool.is_selected () || move_tool.is_selected ()) { show_object_tool_modifiers ();- } else if (foresight_tool.is_selected ()+ } else if (bezier_tool.is_selected () || pen_tool.is_selected () || point_tool.is_selected () || track_tool.is_selected ()) {deleted file mode 100644@@ -1,515 +0,0 @@-/*- Copyright (C) 2014 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.-*/--using Math;-using Cairo;--namespace BirdFont {--/** Create Beziér curves and preview the path. */-public class ForesightTool : Tool {- - public const uint NONE = 0;- public const uint MOVE_POINT = 1;- public const uint MOVE_HANDLES = 2;- public const uint MOVE_LAST_HANDLE = 3;- public const uint MOVE_FIRST_HANDLE = 4;- - uint state = NONE;- bool move_right_handle = true;- int previous_point = 0;- - Path current_path = new Path ();-- int last_move_x = 0;- int last_move_y = 0;-- public bool skip_deselect = false;-- static int press_counter = 0;- double last_release_time = 0;- - public ForesightTool (string name) {- base (name, t_ ("Create Beziér curves"));-- select_action.connect ((self) => {- PenTool p = (PenTool) PointTool.pen ();- - if (state != NONE) {- p.release_action (p, 1, last_move_x, last_move_y);- }- - MainWindow.get_current_glyph ().clear_active_paths ();- MainWindow.set_cursor (NativeWindow.VISIBLE);- state = NONE;- });-- deselect_action.connect ((self) => {- PenTool p = (PenTool) PointTool.pen ();- - if (state != NONE) {- p.release_action (p, 1, last_move_x, last_move_y);- }- - MainWindow.set_cursor (NativeWindow.VISIBLE);- state = NONE;- });- - press_action.connect ((self, b, x, y) => {- // ignore double clicks- if ((GLib.get_real_time () - last_release_time) / 1000000.0 < 0.2) {- print ("Double click.");- last_release_time = GLib.get_real_time ();- MainWindow.set_cursor (NativeWindow.VISIBLE);- return;- }- last_release_time = GLib.get_real_time ();-- press (b, x, y);- });-- double_click_action.connect ((self, b, x, y) => {- EditPoint last;- get_active_path ().delete_last_point ();- - last = get_active_path ().get_last_point ();- - PenTool.selected_points.clear ();- PenTool.selected_points.add (new PointSelection (last, get_active_path ())); - PenTool.selected_point = last; - PenTool.active_edit_point = null;- });-- release_action.connect ((self, b, x, y) => {- PenTool p = (PenTool) PointTool.pen ();- PointSelection last;- - last_move_x = x;- last_move_y = y;- - if (b == 2) {- return;- }- - if (state == MOVE_HANDLES || state == MOVE_FIRST_HANDLE) {- if (state != MOVE_FIRST_HANDLE) {- last = add_new_point (x, y); - }- - state = MOVE_POINT;- move_action (this, x, y);- } else if (state == MOVE_LAST_HANDLE) {- previous_point = 0;- - if (unlikely (PenTool.selected_points.size == 0)) {- warning ("No point in move last handle.");- return;- }- - last = PenTool.selected_points.get (PenTool.selected_points.size - 1);- - p.release_action (p, 2, x, y);- - PenTool.selected_points.add (last);- PenTool.active_path.highlight_last_segment = false;- - last.path.direction_is_set = false;- PenTool.force_direction ();- - state = NONE;- MainWindow.set_cursor (NativeWindow.VISIBLE);- } else if (state == MOVE_POINT) {- } else if (state == NONE) {- } else {- warning (@"Unknown state $state.");- }- - current_path.hide_end_handle = true;- });-- move_action.connect ((self, x, y) => {- Tool p = PointTool.pen ();- PointSelection last;- bool lh;- EditPointHandle h;- Path a;- - last_move_x = x;- last_move_y = y;- - a = get_active_path ();- if (a.is_open () && a.points.size > 1) {- a.get_first_point ().set_reflective_handles (false);- a.get_first_point ().set_tie_handle (false);- }- - if (MainWindow.dialog.visible && state != NONE) {- state = NONE;- p.release_action (p, 1, last_move_x, last_move_y);- }- - if (state == NONE) {- MainWindow.set_cursor (NativeWindow.VISIBLE);- }- - PenTool.active_path = current_path;- PenTool.active_path.hide_end_handle = (state == MOVE_POINT);- - if (state == MOVE_HANDLES || state == MOVE_LAST_HANDLE) { - if (previous_point > 0) {- return_if_fail (PenTool.active_path.points.size >= previous_point + 1);- return_if_fail (PenTool.active_path.points.size > 0);- last = new PointSelection (PenTool.active_path.points.get (PenTool.active_path.points.size - (previous_point + 1)), PenTool.active_path); - } else {- if (unlikely (PenTool.selected_points.size == 0)) {- warning ("No point to move in state %u", state);- return;- }- last = PenTool.selected_points.get (PenTool.selected_points.size - 1);- - if (last.point.get_right_handle ().is_line () || last.point.get_left_handle ().is_line ()) {- last.point.convert_to_curve ();- last.point.get_right_handle ().length = 0.1;- last.point.get_left_handle ().length = 0.1;- }- }- - PenTool.move_selected_handle = true;- PenTool.move_selected = false;- - lh = (state == MOVE_LAST_HANDLE);- - if (!move_right_handle) {- lh = !lh;- }- - if (previous_point > 0) {- lh = false;- }- - h = (lh) ? last.point.get_left_handle () : last.point.get_right_handle ();- PenTool.selected_handle = h;- PenTool.active_handle = h;- - if (previous_point == 0 - && !last.point.reflective_point- && !last.point.tie_handles) {- - last.point.convert_to_curve ();- last.point.set_reflective_handles (true);- last.point.get_right_handle ().length = 0.1;- last.point.get_left_handle ().length = 0.1;- }- - if (previous_point == 0) {- last.point.set_reflective_handles (true);- }- - if (previous_point > 0) {- PenTool.retain_angle = last.point.tie_handles;- }- - if (h.is_line ()) {- last.point.convert_to_curve ();- last.point.get_right_handle ().length = 0.1;- last.point.get_left_handle ().length = 0.1;- }- - p.move_action (p, x, y);- last.point.set_reflective_handles (false);- - PenTool.selected_handle = h;- PenTool.active_handle = h;- - PenTool.move_selected_handle = false;- last.path.highlight_last_segment = true;- - if (previous_point == 0) {- last.point.set_tie_handle (true);- p.move_action (p, x, y);- }- - PenTool.retain_angle = false;- - MainWindow.set_cursor (NativeWindow.HIDDEN);- } else {- if (DrawingTools.get_selected_point_type () != PointType.QUADRATIC) {- p.move_action (p, x, y);- } else {- PenTool.move_point_independent_of_handle = true;- p.move_action (p, x, y);- PenTool.move_point_independent_of_handle = false;- }- }- - if (PenTool.active_path.points.size < 3) {- PenTool.active_edit_point = null;- }- });- - key_press_action.connect ((self, keyval) => {- PenTool p = (PenTool) PointTool.pen ();- p.key_press_action (p, keyval);- });- - key_release_action.connect ((self, keyval) => {- Tool p = PointTool.pen ();- p.key_release_action (p, keyval);- MainWindow.set_cursor (NativeWindow.VISIBLE);- });- - draw_action.connect ((tool, cairo_context, glyph) => {- Tool p = PointTool.pen ();- p.draw_action (p, cairo_context, glyph);- });- }- - public void press (int b, int x, int y) {- PenTool p = (PenTool) PointTool.pen ();- PointSelection ps;- EditPoint first_point;- bool clockwise;- Path? path = null;- bool one_point = false;- Glyph g;- - MainWindow.set_cursor (NativeWindow.HIDDEN);-- BirdFont.get_current_font ().touch ();- g = MainWindow.get_current_glyph ();- g.store_undo_state ();-- if (b == 2) {- last_move_x = x;- last_move_y = y;- - stop_drawing ();- - move_action (this, x, y);- return;- } - - if (state == NONE) {- state = MOVE_POINT;- - PenTool.active_path = get_active_path ();- - add_new_point (x, y);- - PenTool.last_point_x = Glyph.path_coordinate_x (x);- PenTool.last_point_y = Glyph.path_coordinate_y (y);- - move_action (this, x, y);- state = MOVE_FIRST_HANDLE;- - press_action(this, b, x, y);- release_action(this, b, x, y);- }- - if (previous_point > 0) {- previous_point = 0;- state = MOVE_POINT;- }- - if (previous_point == 0) {- if (state == MOVE_POINT) { - state = MOVE_HANDLES;- - path = PenTool.find_path_to_join ();- - if (path != null) {- one_point = (((!) path).points.size == 1);- }- - if (p.has_join_icon ()) {- // FIXME: last activa path in list- ps = new PointSelection (PenTool.active_path.points.get (PenTool.active_path.points.size - 1), PenTool.active_path);- ps.point.set_tie_handle (false);- - ps = new PointSelection (PenTool.active_path.points.get (0), PenTool.active_path);- ps.point.set_tie_handle (false);- - first_point = PenTool.active_path.points.get (0);- clockwise = PenTool.active_path.is_clockwise ();-- PenTool.move_selected = false;- p.release_action (p, 2, x, y);- - PenTool.move_selected = false;- p.press_action (p, 2, x, y);- - if (ps.path.has_point (first_point)) {- ps.path.reverse ();- }- - if (clockwise && PenTool.active_path.is_clockwise ()) {- ps = new PointSelection (PenTool.active_path.points.get (0), PenTool.active_path);- } else {- ps = new PointSelection (PenTool.active_path.points.get (PenTool.active_path.points.size - 1), PenTool.active_path);- }- - PenTool.selected_points.clear ();- PenTool.selected_points.add (ps);- PenTool.selected_point = ps.point; - - state = MOVE_LAST_HANDLE;- - if (one_point) {- p.press_action (p, 2, x, y);- state = NONE;- }- }- } - }-- last_move_x = x;- last_move_y = y;- }- - public void stop_drawing () {- PenTool p = (PenTool) PointTool.pen ();- Path a;- - p.release_action (p, 1, last_move_x, last_move_y);-- if (state != NONE) {- a = get_active_path ();- if (a.is_open () && a.points.size > 0) {- a.delete_last_point ();-- a.get_first_point ().set_reflective_handles (false);- a.get_first_point ().set_tie_handle (false);-- a.get_last_point ().set_reflective_handles (false);- a.get_last_point ().set_tie_handle (false);- }- }-- p.press_action (p, 2, last_move_x, last_move_y);- p.release_action (p, 2, last_move_x, last_move_y);- current_path.hide_end_handle = true;- - previous_point = 0;- state = NONE;- - MainWindow.get_current_glyph ().clear_active_paths ();- PenTool.active_path = new Path ();- }- - public Path get_active_path () {- Glyph g = MainWindow.get_current_glyph ();- if (g.active_paths.size == 0) {- return new Path ();- }- return g.active_paths.get (g.active_paths.size -1);- }- - public void switch_to_line_mode () {- EditPoint ep;- EditPoint last;- - if (PenTool.active_path.points.size > 2) {- ep = PenTool.active_path.points.get (PenTool.active_path.points.size - 2);- ep.get_right_handle ().convert_to_line ();- ep.set_tie_handle (false);- - last = PenTool.active_path.points.get (PenTool.active_path.points.size - 1);- last.convert_to_line ();- - move_action (this, last_move_x, last_move_y);- }- }- - PointSelection add_new_point (int x, int y) {- PointSelection last;- double handle_x, handle_y;- - PenTool p = (PenTool) PointTool.pen ();- - if (PenTool.active_path.points.size == 0) {- last = p.new_point_action (x, y);- } else { - if (PenTool.selected_points.size == 0) {- last = p.new_point_action (x, y);- }- - if (PenTool.selected_points.size == 0) {- warning ("No selected points.");- return new PointSelection.empty ();- }- - last = PenTool.selected_points.get (PenTool.selected_points.size - 1);- - PenTool.selected_points.clear ();- PenTool.selected_handle = new EditPointHandle.empty ();- - if (DrawingTools.get_selected_point_type () != PointType.QUADRATIC) {- last = p.new_point_action (x, y);- } else {- last.point.get_right_handle ().length *= 0.999999;- handle_x = last.point.get_right_handle ().x;- handle_y = last.point.get_right_handle ().y;- - last = p.new_point_action (x, y);- - last.point.get_left_handle ().x = handle_x;- last.point.get_left_handle ().y = handle_y;- }- - PenTool.move_selected = true;- p.move_action (p, x, y);- }- - PenTool.selected_points.clear ();- PenTool.selected_points.add (last); - PenTool.selected_point = last.point; - PenTool.active_edit_point = null;- PenTool.show_selection_box = false;- - PenTool.move_selected_handle = false;- PenTool.move_selected = true;-- PenTool.active_path.hide_end_handle = (state == MOVE_POINT);- - current_path = last.path;- - return last;- }- - // FIXME: solve the straight line issue in undo- public override void before_undo () {- EditPoint last;- - if (PenTool.active_path.points.size > 1) {- last = PenTool.active_path.points.get (PenTool.active_path.points.size - 2);- last.convert_to_curve ();- }- }- - public override void after_undo () {- PenTool.selected_points.clear ();- PenTool.active_edit_point = null;- state = NONE;-- EditPoint last;- - if (PenTool.active_path.points.size > 0) {- last = PenTool.active_path.points.get (PenTool.active_path.points.size - 1);- last.convert_to_curve ();- }- }--}--}@@ -1559,7 +1559,7 @@ public class Glyph : FontDisplay { if (!(MainWindow.get_toolbox ().get_current_tool () is PenTool) && !(MainWindow.get_toolbox ().get_current_tool () is PointTool) && !(MainWindow.get_toolbox ().get_current_tool () is TrackTool)- && !(MainWindow.get_toolbox ().get_current_tool () is ForesightTool)) {+ && !(MainWindow.get_toolbox ().get_current_tool () is BezierTool)) { cr.save (); cr.new_path (); foreach (Path p in active_paths) {@@ -2278,6 +2278,16 @@ public class Glyph : FontDisplay { TabContent.show_text_input (listener); }+ + public PathList get_paths () {+ PathList pl = new PathList ();+ + foreach (Path p in path_list) {+ pl.add (p);+ }+ + return pl;+ } } }@@ -52,7 +52,7 @@ public class MainWindow : GLib.Object { dialog = new Dialog (); spacing_tab = new SpacingTab (); - tools.select_tool (DrawingTools.foresight_tool); + tools.select_tool (DrawingTools.bezier_tool); } public static SpacingTab get_spacing_tab () { @@ -161,8 +161,8 @@ public class PenTool : Tool { x = Glyph.path_coordinate_x (ix); y = Glyph.path_coordinate_y (iy); - if (has_join_icon ()) {- join_paths (x, y);+ if (has_join_icon () && active_edit_point != null) {+ join_paths ((!) active_edit_point); } active_handle = new EditPointHandle.empty ();@@ -176,20 +176,7 @@ public class PenTool : Tool { edit_active_corner = false; show_selection_box = false; - // update path direction if it has changed- foreach (Path p in clockwise) {- if (!p.is_open () && !p.is_clockwise ()) {- p.reverse ();- update_selection ();- }- }-- foreach (Path p in counter_clockwise) {- if (!p.is_open () && p.is_clockwise ()) {- p.reverse ();- update_selection ();- }- }+ set_orientation (); MainWindow.set_cursor (NativeWindow.VISIBLE); @@ -252,10 +239,10 @@ public class PenTool : Tool { key_release_action.connect ((self, keyval) => { double x, y; if (is_arrow_key (keyval)) {- if (KeyBindings.modifier != CTRL) {+ if (KeyBindings.modifier != CTRL && active_edit_point != null) { x = Glyph.reverse_path_coordinate_x (selected_point.x); y = Glyph.reverse_path_coordinate_y (selected_point.y);- join_paths (x, y);+ join_paths ((!) active_edit_point); reset_stroke (); } } @@ -280,9 +267,34 @@ public class PenTool : Tool { } } + public static void set_orientation () {+ // update path direction if it has changed+ foreach (Path p in clockwise) {+ if (!p.is_open () && !p.is_clockwise ()) {+ p.reverse ();+ update_selection ();+ }+ }++ foreach (Path p in counter_clockwise) {+ if (!p.is_open () && p.is_clockwise ()) {+ p.reverse ();+ update_selection ();+ }+ } + }+ public bool has_join_icon () {+ if (active_edit_point != null) {+ return can_join ((!) active_edit_point);+ }+ + return false;+ }++ public static bool can_join (EditPoint ep) { double mx, my;- get_tie_position (out mx, out my);+ get_tie_position (ep, out mx, out my); return (mx > -10 * MainWindow.units && my > -10 * MainWindow.units); } @@ -1055,7 +1067,7 @@ public class PenTool : Tool { } } - public static Path? find_path_to_join () {+ public static Path? find_path_to_join (EditPoint end_point) { Path? m = null; Glyph glyph = MainWindow.get_current_glyph (); EditPoint ep_last, ep_first;@@ -1068,12 +1080,12 @@ public class PenTool : Tool { ep_last = path.points.get (path.points.size - 1); ep_first = path.points.get (0); - if (active_edit_point == ep_last) {+ if (end_point == ep_last) { m = path; break; } - if (active_edit_point == ep_first) {+ if (end_point == ep_first) { m = path; break; }@@ -1162,7 +1174,8 @@ public class PenTool : Tool { } } - private static void join_paths (double x, double y) {+ /** @return the new path or null if no path could be merged with the end point. */+ public static Path? join_paths (EditPoint end_point) { Glyph glyph = MainWindow.get_current_glyph (); Path? p; Path path;@@ -1171,25 +1184,26 @@ public class PenTool : Tool { int px, py; if (glyph.path_list.size == 0) {- return;+ warning ("No paths.");+ return null; } - p = find_path_to_join ();+ p = find_path_to_join (end_point); if (p == null) { warning ("No path to join.");- return;+ return null; } path = (!) p; if (!path.is_open ()) { warning ("Path is closed.");- return;+ return null; } return_if_fail (path.points.size > 0); - px = Glyph.reverse_path_coordinate_x (((!) active_edit_point).x);- py = Glyph.reverse_path_coordinate_y (((!) active_edit_point).y);+ px = Glyph.reverse_path_coordinate_x (end_point.x);+ py = Glyph.reverse_path_coordinate_y (end_point.y); if (path.points.size == 1) { glyph.delete_path (path);@@ -1202,10 +1216,7 @@ public class PenTool : Tool { active_path = merge; merge.reopen (); glyph.open_path ();- - print ("CONTINUE FIRST\n");- - return;+ return merge; } if (is_close_to_point (merge.points.get (0), px, py)) {@@ -1215,15 +1226,12 @@ public class PenTool : Tool { merge.reopen (); glyph.open_path (); merge.reverse ();- - print ("CONTINUE\n");- - return;+ return merge; } } } - return;+ return null; } if (active_edit_point == path.points.get (0)) {@@ -1237,11 +1245,11 @@ public class PenTool : Tool { if (path.points.get (0) == active_edit_point) { warning ("Wrong direction.");- return;+ return null; } // join path with it self- if (is_endpoint ((!) active_edit_point)+ if (is_endpoint (end_point) && is_close_to_point (path.points.get (0), px, py)) { close_path (path);@@ -1258,7 +1266,7 @@ public class PenTool : Tool { remove_all_selected_points (); - return;+ return path; } foreach (Path merge in glyph.path_list) {@@ -1306,7 +1314,7 @@ public class PenTool : Tool { union.update_region_boundaries (); - return;+ return union; } } }@@ -1315,6 +1323,8 @@ public class PenTool : Tool { path.reverse (); update_selection (); }+ + return null; } /** Merge paths if ends are close. */@@ -1390,29 +1400,27 @@ public class PenTool : Tool { void draw_merge_icon (Context cr) { double x, y;- get_tie_position (out x, out y);- draw_join_icon (cr, x, y);+ if (active_edit_point != null) {+ get_tie_position ((!) active_edit_point, out x, out y);+ draw_join_icon (cr, x, y);+ } } /** Obtain the position where to ends meet. */- void get_tie_position (out double x, out double y) {+ static void get_tie_position (EditPoint current_point, out double x, out double y) { Glyph glyph; EditPoint active; double px, py; x = -100; y = -100;- - if (active_edit_point == null) {- return;- } - if (!is_endpoint ((!) active_edit_point)) {+ if (!is_endpoint (current_point)) { return; } glyph = MainWindow.get_current_glyph ();- active = (!) active_edit_point;+ active = current_point; return_if_fail (!is_null (glyph)); @@ -199,6 +199,17 @@ GNU Lesser General Public License</copyright> <path stroke="0" skew="0" data="B 28.7823504083,25.8680965676 M 26.2950154895,23.2677009707 M 9.6750958051,39.5484386207 M 12.1624307239,42.1488342176 M 28.7823504083,25.8680965676" /> </glyph> </collection>+<collection name="bezier_tool">+ <selected id="2"/>+ <glyph id="1" left="-28" right="28">+ </glyph>+ <glyph id="2" left="-28" right="44.054140127388528">+ <path stroke="0" skew="0" data="B 2.5292812784,44.7926187215 M 3.8367822764,44.0794363589 C 3.8367822764,44.0794363589 5.6698701483,42.9721208955 7.9970127245,41.8210255443 C 10.3241553008,40.6699301929 13.1430703979,39.5057503226 14.8911088956,39.0871598212 C 19.3725947163,38.0139630021 26.1831629693,36.8287490065 26.1831629693,36.8287490065 M 27.3718002401,36.5910215523 M 27.3718002401,35.4023842815 M 27.2527463310,22.0896468474 M 27.1336924219,21.2576007579 M 26.4205100595,20.9011997585 C 14.7034373343,14.4397295176 4.6763976082,5.9023851103 -3.6520128941,-5.3676839283 M -4.1274678025,-5.9620025637 M -4.8406501651,-5.9620025637 M -12.2102012447,-5.6056015645 M -13.8742934239,-5.4865476553 M -13.5178924246,-3.8224554761 C -11.9078879957,3.0714124768 -9.7659065790,13.9251351612 -4.7219766199,31.0046165611 M -4.7219766199,31.2423440153 M -4.6029227109,31.3613979244 M 1.9345822790,43.4854980875 M 2.5289009145,44.7929990855 M 2.5292812784,44.7926187215" />+ <path stroke="0" skew="0" data="B -6.0814353303,7.6780380292 C -3.5720984332,13.3816711826 -0.0943930151,18.9058105991 -0.0943930151,18.9058105991 C -0.1213608175,21.2315838652 1.2735097744,23.8255517361 3.7141149100,24.8070428125 C 3.9112575332,22.5672698301 3.4487349984,20.0078770403 1.1973228799,18.3312708879 C 1.2685270069,18.4826557306 -1.6727511654,13.8106836556 -4.5064243827,7.6525916825 C -6.0859768756,4.2199593898 -7.8261540635,-0.4207775145 -8.7011999798,-2.8886939252 M -5.4349688005,-3.1090829315 C 2.8294264529,7.8699316302 12.8614869829,16.3623550577 24.2809629719,22.8032095738 M 24.5186904260,34.2141273744 C 23.3475879321,34.4153018553 18.4726536657,35.2347198626 14.2964098964,36.2348107351 C 12.0221759422,36.7794158052 9.0907872321,38.1373150235 6.6891313626,39.3252676394 C 5.0266747482,40.1476144488 4.4331929135,40.4779605192 3.7175381854,40.8704960915 C 3.7176015794,40.8705594855 3.7176649733,40.8706228794 3.7177283673,40.8706862734 C 1.8159087339,37.3443957031 -0.0859108995,33.8181051328 -1.9877305330,30.2918145624 C -2.0242454699,30.1693373781 -2.0725516886,30.1761839288 -2.1067844420,30.0540871083 M -2.1067844420,29.9350331993 C -6.7668891626,14.0819211717 -8.7232149468,4.0716935311 -10.3083816112,-2.8713554774 C -9.4782492743,-0.6638813021 -7.6385524745,4.1387053056 -6.0814353303,7.6780380292" />+ <path stroke="0" skew="0" data="B 27.6008011519,43.5614898312 C 27.5611165156,43.5771398250 27.6856077556,43.5107018807 27.7280110575,43.4853079055 M 27.3716100582,35.1648470092 M 24.5188806080,35.2839009183 M 24.8752816073,42.4157245437 C 21.8079888660,42.7833462789 18.5182973370,42.7399847911 15.2473197131,43.8420892688 C 12.5363138619,44.7555332387 9.9518170529,46.4453760558 7.8777686335,47.8834559898 M 4.3118568209,42.0591333624 M 1.9345822790,43.6043618145 C 3.3609470041,45.8627726292 4.7873117292,48.1211834440 6.2136764543,50.3795942587 C 6.4910251508,50.8550491670 6.7683738473,51.3305040754 7.0457225439,51.8059589838 C 7.0457859379,51.8058955898 7.0458493318,51.8058321958 7.0459127258,51.8057688018 M 9.4229970857,57.7491453382 C 9.6211032975,58.1453577619 9.8192095093,58.5415701855 10.0173157211,58.9377826091 C 10.4135281448,58.7792976396 10.8097405684,58.6208126702 11.2059529921,58.4623277007 C 17.3076243160,56.3227806132 23.4092956399,54.1832335256 29.5109669638,52.0436864380 C 29.9864218721,51.8852014685 30.4618767805,51.7267164990 30.9373316888,51.5682315295 C 30.7392254770,51.1323978636 30.5411192652,50.6965641976 30.3430130534,50.2607305316 C 29.4317244791,48.0023197169 28.5148717858,45.7945700646 27.6008011519,43.5614898312" />+ <path stroke="0" skew="0" data="B 25.0586929962,45.1476024612 C 25.7093155024,46.7741587267 26.4420259467,48.3186270539 27.1336924219,49.9041393503 M 11.4436804462,55.3718707964 C 10.6555237791,53.6766937351 9.8673671120,51.9815166738 9.0792104449,50.2863396124 C 9.2940350824,50.2199310451 9.4702169488,50.0445714056 9.6005524501,49.9639820033 C 11.4474465869,48.7280947041 14.0174099645,47.3106270615 16.1984197118,46.5757648098 C 18.7674832545,45.7101735478 21.9871036230,45.4530142351 25.0586929962,45.1476024612" />+ </glyph>+</collection> <collection unicode="U+63"> <selected id="1"/> <glyph id="1" left="-28" right="28">@@ -350,15 +361,6 @@ GNU Lesser General Public License</copyright> <path stroke="0" skew="0" data="B -23.5540421546,0.0711646889 M 30.3522079454,20.7274646889 M -23.5540421546,20.7274646889 M -23.5540421546,0.0711646889" /> </glyph> </collection>-<collection name="foresight">- <selected id="1"/>- <glyph id="1" left="-28" right="44.054140127388528">- <path stroke="0" skew="0" data="B 2.5292812784,44.7926187215 M 3.8367822764,44.0794363589 C 3.8367822764,44.0794363589 5.6698701483,42.9721208955 7.9970127245,41.8210255443 C 10.3241553008,40.6699301929 13.1430703979,39.5057503226 14.8911088956,39.0871598212 C 19.3725947163,38.0139630021 26.1831629693,36.8287490065 26.1831629693,36.8287490065 M 27.3718002401,36.5910215523 M 27.3718002401,35.4023842815 M 27.2527463310,22.0896468474 M 27.1336924219,21.2576007579 M 26.4205100595,20.9011997585 C 14.7034373343,14.4397295176 4.6763976082,5.9023851103 -3.6520128941,-5.3676839283 M -4.1274678025,-5.9620025637 M -4.8406501651,-5.9620025637 M -12.2102012447,-5.6056015645 M -13.8742934239,-5.4865476553 M -13.5178924246,-3.8224554761 C -11.9078879957,3.0714124768 -9.7659065790,13.9251351612 -4.7219766199,31.0046165611 M -4.7219766199,31.2423440153 M -4.6029227109,31.3613979244 M 1.9345822790,43.4854980875 M 2.5289009145,44.7929990855 M 2.5292812784,44.7926187215" />- <path stroke="0" skew="0" data="B -6.0814353303,7.6780380292 C -3.5720984332,13.3816711826 -0.0943930151,18.9058105991 -0.0943930151,18.9058105991 C -0.1213608175,21.2315838652 1.2735097744,23.8255517361 3.7141149100,24.8070428125 C 3.9112575332,22.5672698301 3.4487349984,20.0078770403 1.1973228799,18.3312708879 C 1.2685270069,18.4826557306 -1.6727511654,13.8106836556 -4.5064243827,7.6525916825 C -6.0859768756,4.2199593898 -7.8261540635,-0.4207775145 -8.7011999798,-2.8886939252 M -5.4349688005,-3.1090829315 C 2.8294264529,7.8699316302 12.8614869829,16.3623550577 24.2809629719,22.8032095738 M 24.5186904260,34.2141273744 C 23.3475879321,34.4153018553 18.4726536657,35.2347198626 14.2964098964,36.2348107351 C 12.0221759422,36.7794158052 9.0907872321,38.1373150235 6.6891313626,39.3252676394 C 5.0266747482,40.1476144488 4.4331929135,40.4779605192 3.7175381854,40.8704960915 C 3.7176015794,40.8705594855 3.7176649733,40.8706228794 3.7177283673,40.8706862734 C 1.8159087339,37.3443957031 -0.0859108995,33.8181051328 -1.9877305330,30.2918145624 C -2.0242454699,30.1693373781 -2.0725516886,30.1761839288 -2.1067844420,30.0540871083 M -2.1067844420,29.9350331993 C -6.7668891626,14.0819211717 -8.7232149468,4.0716935311 -10.3083816112,-2.8713554774 C -9.4782492743,-0.6638813021 -7.6385524745,4.1387053056 -6.0814353303,7.6780380292" />- <path stroke="0" skew="0" data="B 27.6008011519,43.5614898312 C 27.5611165156,43.5771398250 27.6856077556,43.5107018807 27.7280110575,43.4853079055 M 27.3716100582,35.1648470092 M 24.5188806080,35.2839009183 M 24.8752816073,42.4157245437 C 21.8079888660,42.7833462789 18.5182973370,42.7399847911 15.2473197131,43.8420892688 C 12.5363138619,44.7555332387 9.9518170529,46.4453760558 7.8777686335,47.8834559898 M 4.3118568209,42.0591333624 M 1.9345822790,43.6043618145 C 3.3609470041,45.8627726292 4.7873117292,48.1211834440 6.2136764543,50.3795942587 C 6.4910251508,50.8550491670 6.7683738473,51.3305040754 7.0457225439,51.8059589838 C 7.0457859379,51.8058955898 7.0458493318,51.8058321958 7.0459127258,51.8057688018 M 9.4229970857,57.7491453382 C 9.6211032975,58.1453577619 9.8192095093,58.5415701855 10.0173157211,58.9377826091 C 10.4135281448,58.7792976396 10.8097405684,58.6208126702 11.2059529921,58.4623277007 C 17.3076243160,56.3227806132 23.4092956399,54.1832335256 29.5109669638,52.0436864380 C 29.9864218721,51.8852014685 30.4618767805,51.7267164990 30.9373316888,51.5682315295 C 30.7392254770,51.1323978636 30.5411192652,50.6965641976 30.3430130534,50.2607305316 C 29.4317244791,48.0023197169 28.5148717858,45.7945700646 27.6008011519,43.5614898312" />- <path stroke="0" skew="0" data="B 25.0586929962,45.1476024612 C 25.7093155024,46.7741587267 26.4420259467,48.3186270539 27.1336924219,49.9041393503 M 11.4436804462,55.3718707964 C 10.6555237791,53.6766937351 9.8673671120,51.9815166738 9.0792104449,50.2863396124 C 9.2940350824,50.2199310451 9.4702169488,50.0445714056 9.6005524501,49.9639820033 C 11.4474465869,48.7280947041 14.0174099645,47.3106270615 16.1984197118,46.5757648098 C 18.7674832545,45.7101735478 21.9871036230,45.4530142351 25.0586929962,45.1476024612" />- </glyph>-</collection> <collection name="full_glyph"> <selected id="1"/> <glyph id="1" left="-28" right="28">@@ -1103,6 +1105,7 @@ GNU Lesser General Public License</copyright> <ligature sequence="r e v e r s e _ p a t h" replacement="reverse_path"/> <ligature sequence="e x p o r t _ f o n t s" replacement="export_fonts"/> <ligature sequence="a p p l y _ s t r o k e" replacement="apply_stroke"/>+<ligature sequence="b e z i e r _ t o o l" replacement="bezier_tool"/> <ligature sequence="r i g h t _ a r r o w" replacement="right_arrow"/> <ligature sequence="b e z i e r _ l i n e" replacement="bezier_line"/> <ligature sequence="c r e a t e _ l i n e" replacement="create_line"/>