The Birdfont Source Code


All Repositories / birdfont.git / commitdiff – RSS feed

New Beziér tool

These changes was commited to the Birdfont repository Tue, 14 Oct 2014 18:01:44 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
[Tue, 14 Oct 2014 18:01:44 +0000]

Updated Files

libbirdfont/DrawingTools.vala
libbirdfont/ForesightTool.vala
libbirdfont/Path.vala
libbirdfont/PenTool.vala
libbirdfont/PointTool.vala
--- a/libbirdfont/DrawingTools.vala +++ b/libbirdfont/DrawingTools.vala @@ -35,6 +35,7 @@ public static MoveTool move_tool; public static PenTool pen_tool; + ForesightTool foresight_tool; PointTool point_tool; ZoomTool zoom_tool; public static ResizeTool resize_tool; @@ -103,6 +104,12 @@ grid_expander = grid; // Draw tools + foresight_tool = new ForesightTool ("foresight"); + foresight_tool.select_action.connect ((self) => { + update_drawing_and_background_tools (self); + }); + draw_tools.add_tool (foresight_tool); + pen_tool = new PenTool ("pen_tool"); pen_tool.select_action.connect ((self) => { update_drawing_and_background_tools (self); @@ -1325,6 +1332,7 @@ move_background.set_selected (false); cut_background.set_selected (false); + foresight_tool.set_selected (false); pen_tool.set_selected (false); point_tool.set_selected (false); zoom_tool.set_selected (false); @@ -1346,7 +1354,8 @@ if (resize_tool.is_selected () || move_tool.is_selected ()) { show_object_tool_modifiers (); - } else if (pen_tool.is_selected () + } else if (foresight_tool.is_selected () + || pen_tool.is_selected () || point_tool.is_selected () || track_tool.is_selected ()) { show_point_tool_modifiers ();
--- /dev/null +++ b/libbirdfont/ForesightTool.vala @@ -1,1 +1,184 @@ + /* + Copyright (C) 2014 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 { + + /** Move control points. */ + 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; + + uint state = NONE; + + public ForesightTool (string name) { + base (name, t_ ("Create Beziér curves"), '.', CTRL); + + select_action.connect ((self) => { + }); + + deselect_action.connect ((self) => { + }); + + press_action.connect ((self, b, x, y) => { + PenTool p = (PenTool) PointTool.pen (); + PointSelection ps; + EditPoint first_point; + + if (state == NONE) { + add_new_point (x, y); + move_action (this, x + 10, y + 10); + state = MOVE_HANDLES; + PenTool.active_path.hide_end_handle = false; + } + + if (state == MOVE_POINT) { + state = MOVE_HANDLES; + PenTool.active_path.hide_end_handle = false; + + if (p.has_join_icon ()) { + return_if_fail (PenTool.active_path.points.size != 0); + ps = new PointSelection (PenTool.active_path.points.get (PenTool.active_path.points.size - 1), PenTool.active_path); + ps.point.set_tie_handle (false); + ps.point.convert_to_curve (); + + ps = new PointSelection (PenTool.active_path.points.get (0), PenTool.active_path); + ps.point.set_tie_handle (false); + ps.point.convert_to_curve (); + + first_point = PenTool.active_path.points.get (0); + + p.release_action (p, 3, x, y); + p.press_action (p, 3, x, y); + + if (ps.path.has_point (first_point)) { + ps.path.reverse (); + } + + 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; + } + } + }); + + double_click_action.connect ((self, b, x, y) => { + Tool p = PointTool.pen (); + + if (!BirdFont.android) { + p.double_click_action (p, b, x, y); + } + }); + + release_action.connect ((self, b, x, y) => { + Tool p = PointTool.pen (); + PointSelection last; + + if (state == MOVE_HANDLES) { + state = MOVE_POINT; + add_new_point (x, y); + PenTool.active_path.hide_end_handle = true; + } + + if (state == MOVE_LAST_HANDLE) { + state = NONE; + return_if_fail (PenTool.selected_points.size != 0); + last = PenTool.selected_points.get (PenTool.selected_points.size - 1); + p.release_action (p, 3, x, y); + PenTool.selected_points.add (last); + PenTool.active_path.highlight_last_segment = false; + + last.path.direction_is_set = false; + PenTool.force_direction (); + } + }); + + move_action.connect ((self, x, y) => { + Tool p = PointTool.pen (); + PointSelection last; + + if (state == MOVE_HANDLES || state == MOVE_LAST_HANDLE) { + return_if_fail (PenTool.selected_points.size != 0); + last = PenTool.selected_points.get (PenTool.selected_points.size - 1); + + PenTool.move_selected_handle = true; + PenTool.selected_handle = (state == MOVE_LAST_HANDLE) + ? last.point.get_left_handle () : last.point.get_right_handle (); + last.point.set_reflective_handles (true); + last.point.convert_to_curve (); + p.move_action (p, x, y); + last.point.set_reflective_handles (false); + PenTool.move_selected_handle = false; + last.path.highlight_last_segment = true; + + last.point.set_tie_handle (true); + } else { + p.move_action (p, x, y); + } + + }); + + key_press_action.connect ((self, keyval) => { + Tool p = PointTool.pen (); + p.key_press_action (p, keyval); + }); + + key_release_action.connect ((self, keyval) => { + Tool p = PointTool.pen (); + p.key_release_action (p, keyval); + }); + + draw_action.connect ((tool, cairo_context, glyph) => { + Tool p = PointTool.pen (); + p.draw_action (p, cairo_context, glyph); + }); + } + + void add_new_point (int x, int y) { + PointSelection last; + + Tool p = PointTool.pen (); + + PenTool.selected_points.clear (); + PenTool.selected_handle = new EditPointHandle.empty (); + + p.release_action (p, 3, x, y); + p.press_action (p, 1, x, y); + + return_if_fail (PenTool.selected_points.size != 0); + last = PenTool.selected_points.get (PenTool.selected_points.size - 1); + + p.release_action (p, 1, x, y); + p.press_action (p, 3, x, y); + + PenTool.selected_points.clear (); + PenTool.selected_points.add (last); + PenTool.selected_point = last.point; + PenTool.active_edit_point = null; + + PenTool.move_selected_handle = false; + } + } + + }
--- a/libbirdfont/Path.vala +++ b/libbirdfont/Path.vala @@ -43,7 +43,7 @@ bool edit = true; bool open = true; - bool direction_is_set = false; + public bool direction_is_set = false; bool no_derived_direction = false; bool clockwise_direction = true; @@ -90,6 +90,9 @@ public double rotation = 0; public double skew = 0; + + public bool hide_end_handle = true; + public bool highlight_last_segment = false; public Path () { string width; @@ -207,6 +210,7 @@ unowned EditPoint? n = null; unowned EditPoint en; unowned EditPoint em; + int i; if (points.size < 2) { return; @@ -215,23 +219,52 @@ cr.new_path (); // draw lines + i = 0; foreach (EditPoint e in points) { if (n != null) { en = (!) n; - draw_next (en, e, cr); + if (!highlight_last_segment || i != points.size - 1) { + draw_next (en, e, cr); + } } n = e; + i++; } // close path if (!is_open () && n != null) { - en = (!) n; - em = points.get (0).get_link_item (); - draw_next (en, em, cr); + if (highlight_last_segment) { + cr.stroke (); + en = points.get (points.size - 1).get_link_item (); + em = points.get (0).get_link_item (); + draw_next (en, em, cr); + cr.stroke (); + } else { + en = (!) n; + em = points.get (0).get_link_item (); + draw_next (en, em, cr); + cr.stroke (); + } + } else { + cr.stroke (); } - cr.stroke (); + // draw highlighted segment + if (highlight_last_segment && points.size >= 2) { + line_color_r = 0.5; + line_color_g = 0.5; + line_color_b = 0.8; + line_color_a = 1; + + draw_next (points.get (points.size - 2), points.get (points.size - 1), cr); + cr.stroke (); + + line_color_r = 0; + line_color_g = 0; + line_color_b = 0; + line_color_a = 1; + } } public void draw_edit_points (Context cr) { @@ -262,7 +295,7 @@ Glyph g; double center_x, center_y; double ex, ey; - + if (points.size == 0){ return; } @@ -286,7 +319,7 @@ n = e; } - + // close path if (!is_open () && points.size >= 2 && n != null) { en = (!) n; @@ -452,7 +485,7 @@ img_left = (!) edit_point_handle_image; } - if (!(is_open () && e == points.get (points.size - 1))) { + if (!hide_end_handle || !(is_open () && e == points.get (points.size - 1))) { draw_line (handle_right, e, cr, 0.15); draw_image (cr, img_right, e.get_right_handle ().x, e.get_right_handle ().y); } @@ -515,13 +548,15 @@ */ public bool force_direction (Direction direction) { bool c = (direction == Direction.CLOCKWISE); + bool d = is_clockwise (); direction_is_set = true; - if (c != is_clockwise ()) { + if (c != d) { this.reverse (); } - if (unlikely (is_clockwise () != c)) { + d = is_clockwise (); + if (unlikely (d != c)) { warning ("Failed to set direction for path in force_direction."); return true; } @@ -669,6 +704,9 @@ new_path.fill = fill; new_path.direction_is_set = direction_is_set; new_path.create_list (); + + new_path.hide_end_handle = hide_end_handle; + new_path.highlight_last_segment = highlight_last_segment; return new_path; }
--- a/libbirdfont/PenTool.vala +++ b/libbirdfont/PenTool.vala @@ -236,7 +236,7 @@ path_stroke_width = width; } - private bool has_join_icon () { + public bool has_join_icon () { double mx, my; get_tie_position (out mx, out my); return (mx > -10 * MainWindow.units && my > -10 * MainWindow.units); @@ -735,7 +735,7 @@ /** Set fill property to transparend for counter paths. */ public static void force_direction () { Glyph g = MainWindow.get_current_glyph (); - + // don't retain direction clockwise.clear (); counter_clockwise.clear ();
--- a/libbirdfont/PointTool.vala +++ b/libbirdfont/PointTool.vala @@ -80,10 +80,10 @@ }); } - private static Tool pen () { + public static Tool pen () { return MainWindow.get_toolbox ().get_tool ("pen_tool"); } } }