The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Round line cap

These changes was commited to the Birdfont repository Mon, 11 May 2015 21:16:49 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
author Johan Mattsson <johan.mattsson.m@gmail.com>
Mon, 11 May 2015 21:16:49 +0000 (23:16 +0200)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Mon, 11 May 2015 21:16:49 +0000 (23:16 +0200)
commit 91b5a8a76dc451f80f44ed9e1020571c881361ed
tree 11a5988dffe66eb2f85010ff268f155f75d4fdbd
parent fb52d7788451a6d80d1eefe1c2b301356e1187d9
Round line cap

13 files changed:
libbirdfont/BezierTool.vala
libbirdfont/Color.vala
libbirdfont/DrawingTools.vala
libbirdfont/Glyph.vala
libbirdfont/MoveTool.vala
libbirdfont/Path.vala
libbirdfont/PenTool.vala
libbirdfont/ResizeTool.vala
libbirdfont/StrokeTool.vala
libbirdfont/SvgArc.vala
libbirdfont/SvgParser.vala
libbirdfont/TrackTool.vala
--- a/libbirdfont/BezierTool.vala +++ b/libbirdfont/BezierTool.vala @@ -311,7 +311,7 @@ if (state == MOVE_POINT && current_path.points.size > 0) { current_path.delete_last_point (); current_path.reset_stroke (); - current_path.get_stroke (); // cache better stroke + current_path.create_full_stroke (); // cache better stroke } state = NONE;
--- a/libbirdfont/Color.vala +++ b/libbirdfont/Color.vala @@ -47,10 +47,26 @@ return new Color (222.0 / 255, 203.0 / 255, 43 / 255.0, 1); } + public static Color brown () { + return new Color (160.0 / 255, 90.0 / 255, 44.0 / 255, 1); + } + public static Color pink () { return new Color (247.0 / 255, 27.0 / 255, 113 / 255.0, 1); + } + + public static Color white () { + return new Color (1, 1, 1, 1); + } + + public static Color grey () { + return new Color (0.5, 0.5, 0.5, 1); + } + + public static Color magenta () { + return new Color (103.0 / 255, 33.0 / 255, 120.0 / 255, 1); } } }
--- a/libbirdfont/DrawingTools.vala +++ b/libbirdfont/DrawingTools.vala @@ -1,5 +1,5 @@ /* - Copyright (C) 2012, 2013, 2014 Johan Mattsson + Copyright (C) 2012 2013 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 @@ -850,7 +850,41 @@ outline.set_selected (false); }); stroke_expander.add_tool (outline); - + + // set line cap + Tool line_cap_round = new Tool ("line_cap_round", t_("Round line cap")); + line_cap_round.select_action.connect ((self) => { + Glyph g; + + g = MainWindow.get_current_glyph (); + g.store_undo_state (); + + foreach (Path p in g.active_paths) { + p.line_cap = LineCap.ROUND; + p.reset_stroke (); + } + + GlyphCanvas.redraw (); + }); + stroke_expander.add_tool (line_cap_round); + + Tool line_cap_square = new Tool ("line_cap_square", t_("Square line cap")); + line_cap_square.select_action.connect ((self) => { + Glyph g; + + g = MainWindow.get_current_glyph (); + g.store_undo_state (); + + foreach (Path p in g.active_paths) { + p.line_cap = LineCap.SQUARE; + p.reset_stroke (); + } + + GlyphCanvas.redraw (); + }); + stroke_expander.add_tool (line_cap_square); + + // tests if (BirdFont.has_argument ("--test")) { Tool test_case = new Tool ("test_case"); test_case.select_action.connect((self) => {
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -1238,7 +1238,7 @@ p.convert_path_ending_to_line (); } - p.get_stroke (); // cache stroke + p.create_full_stroke (); // cache stroke } open = false;
--- a/libbirdfont/MoveTool.vala +++ b/libbirdfont/MoveTool.vala @@ -156,7 +156,7 @@ DrawingTools.resize_tool.signal_objects_rotated (); foreach (Path p in glyph.active_paths) { - p.get_stroke (); + p.create_full_stroke (); } } else { objects_deselected ();
--- a/libbirdfont/Path.vala +++ b/libbirdfont/Path.vala @@ -48,6 +48,7 @@ /** Stroke width */ public double stroke = 0; + public LineCap line_cap = LineCap.BUTT; PathList? full_stroke = null; PathList? fast_stroke = null; @@ -756,6 +757,7 @@ new_path.edit = edit; new_path.open = open; new_path.stroke = stroke; + new_path.line_cap = line_cap; new_path.skew = skew; new_path.fill = fill; new_path.direction_is_set = direction_is_set; @@ -2320,7 +2322,9 @@ } public void create_full_stroke () { - full_stroke = StrokeTool.get_stroke (this, stroke); + if (stroke > 0) { + full_stroke = StrokeTool.get_stroke (this, stroke); + } } public PathList get_stroke () {
--- a/libbirdfont/PenTool.vala +++ b/libbirdfont/PenTool.vala @@ -188,7 +188,7 @@ p.get_last_point ().set_reflective_handles (false); } - p.get_stroke (); // cache good stroke + p.create_full_stroke (); // cache good stroke } });
--- a/libbirdfont/ResizeTool.vala +++ b/libbirdfont/ResizeTool.vala @@ -108,7 +108,7 @@ GlyphCanvas.redraw (); foreach (Path p in MainWindow.get_current_glyph ().active_paths) { - p.get_stroke (); + p.create_full_stroke (); } });
--- a/libbirdfont/StrokeTool.vala +++ b/libbirdfont/StrokeTool.vala @@ -16,6 +16,12 @@ using Math; namespace BirdFont { + + public enum LineCap { + BUTT, + SQUARE, + ROUND + } public class StrokeTool : Tool { @@ -283,26 +289,123 @@ return false; } - static void add_line_cap (Path path, Path stroke, - EditPointHandle last_handle, - EditPoint start, EditPoint end) { + static void add_line_cap (Path path, Path stroke1, Path stroke2, bool last_cap) { + if (path.line_cap == LineCap.SQUARE) { + add_square_cap (path, stroke1, stroke2, last_cap); + } else if (path.line_cap == LineCap.ROUND) { + add_round_cap (path, stroke1, stroke2, last_cap); + } + } + + static void add_round_cap (Path path, Path stroke1, Path stroke2, bool last_cap) { + double px, py; + double step, start_angle, stop_angle; + double radius; + EditPoint n, nstart, nend; + Path cap = new Path (); - EditPoint n; - double stroke_width = path.stroke / 2; + EditPoint start, end; + EditPointHandle last_handle; + EditPoint first, last; - double y = sin (last_handle.angle - PI) * stroke_width; - double x = cos (last_handle.angle - PI) * stroke_width; + stroke1.remove_points_on_points (); + stroke2.remove_points_on_points (); - n = stroke.add (start.x + x, start.y + y); - n.type = start.type; - n.get_right_handle ().type = start.type; - n.get_left_handle ().type = start.type; + last_handle = path.get_first_point ().get_right_handle (); + start = stroke1.get_last_point (); + end = stroke2.get_first_point (); + + start_angle = last_handle.angle + PI / 2; + stop_angle = start_angle + PI; + + nstart = cap.add (start.x, start.y); + radius = Path.distance_to_point (start, end) / 2; + step = PI / 5; + + for (int j = 0; j < 5; j++) { + double angle = start_angle + step * j; + px = radius * cos (angle) + last_handle.parent.x; + py = radius * sin (angle) + last_handle.parent.y; + n = cap.add (px, py); + + n.type = PointType.LINE_CUBIC; + n.get_right_handle ().type = PointType.LINE_CUBIC; + n.get_left_handle ().type = PointType.LINE_CUBIC; + } + + nend = cap.add (end.x, end.y); + + for (int i = 0; i < cap.points.size; i++) { + cap.points.get (i).recalculate_linear_handles (); + } + + int size = cap.points.size; + + for (int i = 1; i < size; i++) { + n = cap.points.get (i); + n.convert_to_curve (); + n.set_tie_handle (true); + n.process_tied_handle (); + } + + int f = stroke1.points.size - 1; + + for (int i = 2; i < cap.points.size - 1; i++) { + n = cap.points.get (i).copy (); + stroke1.add_point (n); + } + + return_if_fail (0 < f < stroke1.points.size); + + first = stroke1.points.get (f); + stroke1.add_point (stroke2.get_first_point ()); + + last = stroke1.get_last_point (); + + double a; + double l; + + return_if_fail (cap.points.size > 1); + + a = (first.get_left_handle ().angle + PI) % (2 * PI); + l = cap.points.get (1).get_right_handle ().length; + + first.get_right_handle ().convert_to_curve (); + first.get_right_handle ().angle = a; + first.get_right_handle ().length = l; + + a = (first.get_left_handle ().angle + PI) % (2 * PI); + + last.get_left_handle ().convert_to_curve (); + last.get_left_handle ().angle = a; + last.get_left_handle ().length = l; + } + + static void add_square_cap (Path path, Path stroke1, Path stroke2, bool last_cap) { + EditPointHandle last_handle; + EditPoint start; + EditPoint end; + EditPoint n; + double x, y; + double stroke_width = path.stroke / 2; + + last_handle = path.get_first_point ().get_right_handle (); + start = stroke1.get_last_point (); + end = stroke2.get_first_point (); + + y = sin (last_handle.angle - PI) * stroke_width; + x = cos (last_handle.angle - PI) * stroke_width; + + n = stroke1.add (start.x + x, start.y + y); + n.type = PointType.CUBIC; + n.get_right_handle ().type = PointType.CUBIC; + n.get_left_handle ().type = PointType.CUBIC; n.convert_to_line (); - n = stroke.add (end.x + x, end.y + y); - n.type = start.type; - n.get_right_handle ().type = start.type; - n.get_left_handle ().type = start.type; + n = stroke1.add (end.x + x, end.y + y); + n.type = PointType.CUBIC; + n.get_right_handle ().type = PointType.CUBIC; + n.get_left_handle ().type = PointType.CUBIC; n.convert_to_line (); } @@ -317,28 +420,26 @@ Path merged; EditPoint last_counter, first; - + merged = stroke.copy (); - counter.reverse (); - - counter.reverse (); merged.reverse (); last_counter = new EditPoint (); first = new EditPoint (); - add_line_cap (path, merged, path.get_first_point ().get_right_handle (), - merged.get_last_point (), counter.get_first_point ()); + add_line_cap (path, merged, counter, true); + path.reverse (); + + add_line_cap (path, counter, merged, true); + path.reverse (); merged.append_path (counter); - - add_line_cap (path, merged, path.get_last_point ().get_left_handle (), - merged.get_last_point (), merged.get_first_point ()); merged.close (); merged.create_list (); merged.recalculate_linear_handles (); - + /* + // BUTT CAP if (path.is_open ()) { first = merged.get_first_point (); last_counter = merged.get_last_point (); @@ -349,7 +450,7 @@ last_counter.get_right_handle ().convert_to_line (); last_counter.recalculate_linear_handles (); } - + */ return merged; } @@ -2094,17 +2195,17 @@ previous_inside.flags |= EditPoint.CURVE; side1.add_point (previous); - side2.add_point (previous_inside); + side2.add_point (previous_inside); } } if (!fast) { side1.remove_points_on_points (); side2.remove_points_on_points (); - + convert_to_curve (side1); convert_to_curve (side2); - + side2.reverse (); pl = merge_stroke_parts (path, side1, side2); }
--- a/libbirdfont/SvgArc.vala +++ b/libbirdfont/SvgArc.vala @@ -158,6 +158,8 @@ for (double a = 0; a < fabs (angleExtent); a += step) { theta = PI - angleStart - angleExtent + s * a; + + return_if_fail (0 <= bi < bezier_points.length); bezier_points[bi].type = 'S'; bezier_points[bi].svg_type = 'a';
--- a/libbirdfont/SvgParser.vala +++ b/libbirdfont/SvgParser.vala @@ -1195,16 +1195,8 @@ return path_list; } - /* //FIXME: DELETE - if (bezier_points[bi - 1].type != 'z') { - bezier_points[bi].type = 'z'; - bezier_points[bi].svg_type = 'z'; - bi++; - } - */ + move_and_resize (bezier_points, bi, svg_glyph, units, glyph); - move_and_resize (bezier_points, bi, svg_glyph, units, glyph); - if (format == SvgFormat.ILLUSTRATOR) { path_list = create_paths_illustrator (bezier_points, bi); } else { @@ -1578,7 +1570,6 @@ } if (path.points.size > 0) { - warning ("Open path."); path_list.add (path); }
--- a/libbirdfont/TrackTool.vala +++ b/libbirdfont/TrackTool.vala @@ -122,7 +122,7 @@ drawing = true; foreach (Path path in glyph.active_paths) { - path.get_stroke (); // cache merged stroke parts + path.create_full_stroke (); // cache merged stroke parts } } });