Commit 3c76541
convert a set of control points to symmetric points and convert segments to lines
Changed files (6)
addedicons/create_line.pngaddedicons/symmetric.pngmodifiedlibbirdfont/EditPoint.valamodifiedlibbirdfont/EditPointHandle.valamodifiedlibbirdfont/PenTool.valamodifiedlibbirdfont/Toolbox.vala
Diff
new file mode 100644Binary files /dev/null and b/icons/create_line.png differnew file mode 100644Binary files /dev/null and b/icons/symmetric.png differ@@ -46,6 +46,7 @@ public class EditPoint { public EditPointHandle left_handle; public bool tie_handles = false;+ public bool reflective_handles = false; public EditPoint (double nx = 0, double ny = 0, PointType nt = PointType.NONE) { x = nx;@@ -78,6 +79,11 @@ public class EditPoint { && get_left_handle ().y () == e.get_left_handle ().y (); } + /** Make handles symetrical. */+ public void set_reflective_handles (bool symmetrical) {+ reflective_handles = symmetrical;+ }+ /** Flip handles if next point on path is in the other direction. * Used to recalculate handles after new point is inserted on a path. */@@ -212,6 +218,12 @@ public class EditPoint { public void set_tie_handle (bool t) { tie_handles = t; }+ + public void process_symmetrical_handles () {+ process_tied_handle ();+ right_handle.process_symmetrical_handle ();+ left_handle.process_symmetrical_handle ();+ } /** This can only be performed if the path has been closed. */ public void process_tied_handle () @@ -345,10 +357,14 @@ public class EditPoint { // move connected quadratic handle if (left_handle.type == PointType.QUADRATIC || right_handle.type == PointType.QUADRATIC) { if (next != null) {+ ((!)next).data.set_tie_handle (false);+ ((!)next).data.set_reflective_handles (false); ((!)next).data.left_handle.move_to_coordinate_internal (right_handle.x (), right_handle.y ()); } if (prev != null && !((!)prev).data.is_selected ()) {+ ((!)prev).data.set_tie_handle (false);+ ((!)prev).data.set_reflective_handles (false); ((!)prev).data.right_handle.move_to_coordinate (left_handle.x (), left_handle.y ()); } }@@ -116,9 +116,16 @@ public class EditPointHandle { public void move_to_coordinate (double x, double y) { move_to_coordinate_internal (x, y);+ if (parent.tie_handles) { tie_handle (); }+ + if (parent.reflective_handles) {+ tie_handle ();+ process_symmetrical_handle ();+ }+ process_connected_handle (); } @@ -168,6 +175,18 @@ public class EditPointHandle { } } + public void process_symmetrical_handle () {+ if (is_left_handle ()) {+ parent.get_right_handle ().length = length;+ parent.get_right_handle ().process_connected_handle ();+ } else {+ parent.get_left_handle ().length = length;+ parent.get_left_handle ().process_connected_handle ();+ }+ + process_connected_handle ();+ }+ public void tie_handle () { if (is_left_handle ()) { parent.get_right_handle ().angle = angle - PI;@@ -78,14 +78,17 @@ public class PenTool : Tool { press_action.connect ((self, b, x, y) => { first_move_action = true; + last_point_x = x;+ last_point_y = y;++ press (b, x, y, false);+ if (GridTool.is_visible ()) { tie_pixels (ref x, ref y); } last_point_x = x; last_point_y = y;-- press (b, x, y, false); }); double_click_action.connect ((self, b, x, y) => {@@ -165,9 +168,11 @@ public class PenTool : Tool { double px = 0; double py = 0; - control_point_event (x, y);- curve_active_corner_event (x, y);- set_default_handle_positions ();+ // DELETE if (!move_selected_handle) {+ control_point_event (x, y);+ curve_active_corner_event (x, y);+ set_default_handle_positions (); // FIXME+ //} // show new point on path if (glyph.new_point_on_path != null) {@@ -187,7 +192,7 @@ public class PenTool : Tool { if (selected_handle.type == PointType.LINE_DOUBLE_CURVE) { selected_handle.set_point_type (PointType.DOUBLE_CURVE); }- + if (GridTool.is_visible ()) { coordinate_x = Glyph.path_coordinate_x (x); coordinate_y = Glyph.path_coordinate_y (y);@@ -329,6 +334,7 @@ public class PenTool : Tool { if (active_edit_point == null) { if (KeyBindings.modifier != SHIFT) { remove_all_selected_points ();+ return; } } @@ -834,7 +840,7 @@ public class PenTool : Tool { double d_point = g.view_zoom * get_distance_to_closest_edit_point (event_x, event_y); double dl, dr;- + foreach (EditPoint selected_corner in selected_points) { dl = g.view_zoom * selected_corner.get_left_handle ().get_point ().get_distance (x, y); dr = g.view_zoom * selected_corner.get_right_handle ().get_point ().get_distance (x, y);@@ -1097,6 +1103,89 @@ public class PenTool : Tool { g.redraw_area (0, 0, g.allocation.width, g.allocation.height); } + public static void convert_point_to_line (EditPoint ep, bool both) {+ ep.set_tie_handle (false);+ ep.set_reflective_handles (false);+ + if (ep.type == PointType.CUBIC || ep.type == PointType.LINE_CUBIC) {+ ep.type = PointType.LINE_CUBIC;+ + if (both) {+ ep.get_left_handle ().type = PointType.LINE_CUBIC;+ ep.get_right_handle ().type = PointType.LINE_CUBIC;+ }+ + if (ep.next != null && ep.get_next ().data.is_selected ()) {+ ep.get_right_handle ().type = PointType.LINE_CUBIC;+ }++ if (ep.prev != null && ep.get_prev ().data.is_selected ()) {+ ep.get_left_handle ().type = PointType.LINE_CUBIC;+ }+ + }++ if (ep.type == PointType.DOUBLE_CURVE| ep.type == PointType.LINE_DOUBLE_CURVE) {+ ep.type = PointType.LINE_DOUBLE_CURVE;+ if (both) {+ ep.get_left_handle ().type = PointType.LINE_DOUBLE_CURVE;+ ep.get_right_handle ().type = PointType.LINE_DOUBLE_CURVE;+ }++ if (ep.next != null && ep.get_next ().data.is_selected ()) {+ ep.get_right_handle ().type = PointType.LINE_DOUBLE_CURVE;+ }++ if (ep.prev != null && ep.get_prev ().data.is_selected ()) {+ ep.get_left_handle ().type = PointType.LINE_DOUBLE_CURVE;+ }+ }++ if (ep.type == PointType.QUADRATIC || ep.type == PointType.LINE_QUADRATIC) {+ ep.type = PointType.LINE_QUADRATIC;+ + if (both) {+ ep.get_left_handle ().type = PointType.LINE_QUADRATIC;+ ep.get_right_handle ().type = PointType.LINE_QUADRATIC;+ + if (ep.next != null) {+ ep.get_next ().data.get_left_handle ().type = PointType.LINE_QUADRATIC; + }+ + if (ep.prev != null) {+ ep.get_prev ().data.get_right_handle ().type = PointType.LINE_QUADRATIC; + }+ }+ + if (ep.next != null && ep.get_next ().data.is_selected ()) {+ ep.get_right_handle ().type = PointType.LINE_QUADRATIC;+ ep.get_next ().data.get_left_handle ().type = PointType.LINE_QUADRATIC;+ }++ if (ep.prev != null && ep.get_prev ().data.is_selected ()) {+ ep.get_left_handle ().type = PointType.LINE_QUADRATIC;+ ep.get_prev ().data.get_right_handle ().type = PointType.LINE_QUADRATIC;+ } + + }+ + ep.recalculate_linear_handles ();+ }+ + public static void convert_segment_to_line () {+ if (selected_points.length () == 0) {+ return;+ }+ + if (selected_points.length () == 1) {+ convert_point_to_line (selected_points.first ().data, true);+ } else {+ foreach (EditPoint p in selected_points) {+ convert_point_to_line (p, false);+ }+ }+ }+ /** Draw a test glyph. */ public override bool test () { test_select_action ();@@ -59,6 +59,7 @@ public class Toolbox : GLib.Object { Expander path_tool_modifiers = new Expander (); Expander draw_tool_modifiers = new Expander ();+ Expander edit_point_modifiers = new Expander (); Expander characterset_tools = new Expander (); Expander test_tools = new Expander (); Expander guideline_tools = new Expander ();@@ -116,39 +117,50 @@ public class Toolbox : GLib.Object { if (tie) { ep.process_tied_handle ();+ ep.set_reflective_handles (false); }- + ep.set_tie_handle (tie);- MainWindow.get_current_glyph ().update_view (); } - // don't select the tie tool. give focus to the point type selection:- var idle = new IdleSource();- idle.set_callback (() => {- if (point_type == PointType.QUADRATIC) {- select_tool (quadratic_points);- }-- if (point_type == PointType.CUBIC) {- select_tool (cubic_points);- }-- if (point_type == PointType.DOUBLE_CURVE) {- select_tool (double_points);+ MainWindow.get_current_glyph ().update_view ();+ });+ edit_point_modifiers.add_tool (tie_handles);+ + // symmetrical handles+ Tool reflect_handle = new Tool ("symmetric", _("Symmetrical handles"), 'r');+ reflect_handle.select_action.connect ((self) => {+ bool symmetrical;+ EditPoint ep;+ if (PenTool.selected_points.length () > 0) {+ ep = PenTool.selected_points.first ().data;+ symmetrical = ep.reflective_handles;+ foreach (EditPoint p in PenTool.selected_points) {+ p.set_reflective_handles (!symmetrical);+ p.process_symmetrical_handles ();+ + if (symmetrical) {+ ep.set_tie_handle (false);+ } }- return false;- });- - idle.attach (null); + MainWindow.get_current_glyph ().update_view ();+ } });- draw_tool_modifiers.add_tool (tie_handles);- + edit_point_modifiers.add_tool (reflect_handle);++ Tool create_line = new Tool ("create_line", _("Convert segment to line."), 'r');+ create_line.select_action.connect ((self) => {+ PenTool.convert_segment_to_line ();+ MainWindow.get_current_glyph ().update_view ();+ });+ edit_point_modifiers.add_tool (create_line);+ // path tools Tool union_paths_tool = new MergeTool ("union_paths"); path_tool_modifiers.add_tool (union_paths_tool); - Tool reverse_path_tool = new Tool ("reverse_path", _("Create counter from outline"), 'r');+ Tool reverse_path_tool = new Tool ("reverse_path", _("Create counter from outline")); reverse_path_tool.select_action.connect ((self) => { Glyph g = MainWindow.get_current_glyph (); @@ -549,6 +561,7 @@ public class Toolbox : GLib.Object { draw_tools.set_open (true); draw_tool_modifiers.set_open (true);+ edit_point_modifiers.set_open (true); path_tool_modifiers.set_open (true); view_tools.set_open (true); grid.set_open (true);@@ -560,6 +573,7 @@ public class Toolbox : GLib.Object { add_expander (draw_tools); add_expander (draw_tool_modifiers);+ add_expander (edit_point_modifiers); add_expander (path_tool_modifiers); add_expander (characterset_tools);@@ -579,6 +593,9 @@ public class Toolbox : GLib.Object { draw_tool_modifiers.set_persistent (true); draw_tool_modifiers.set_unique (true); + edit_point_modifiers.set_persistent (false);+ edit_point_modifiers.set_unique (false);+ path_tool_modifiers.set_persistent (false); path_tool_modifiers.set_unique (false);