Commit 91b5a8a
Round line cap
Changed files (12)
modifiedlibbirdfont/BezierTool.valamodifiedlibbirdfont/Color.valamodifiedlibbirdfont/DrawingTools.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/MoveTool.valamodifiedlibbirdfont/Path.valamodifiedlibbirdfont/PenTool.valamodifiedlibbirdfont/ResizeTool.valamodifiedlibbirdfont/StrokeTool.valamodifiedlibbirdfont/SvgArc.valamodifiedlibbirdfont/SvgParser.valamodifiedlibbirdfont/TrackTool.vala
Diff
@@ -311,7 +311,7 @@ public class BezierTool : Tool { 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;@@ -47,9 +47,25 @@ public class Color { 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);+ } } }@@ -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 @@ public class DrawingTools : ToolCollection { 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) => {@@ -1238,7 +1238,7 @@ public class Glyph : FontDisplay { p.convert_path_ending_to_line (); } - p.get_stroke (); // cache stroke+ p.create_full_stroke (); // cache stroke } open = false;@@ -156,7 +156,7 @@ public class MoveTool : Tool { DrawingTools.resize_tool.signal_objects_rotated (); foreach (Path p in glyph.active_paths) {- p.get_stroke ();+ p.create_full_stroke (); } } else { objects_deselected ();@@ -48,6 +48,7 @@ public class Path { /** Stroke width */ public double stroke = 0;+ public LineCap line_cap = LineCap.BUTT; PathList? full_stroke = null; PathList? fast_stroke = null; @@ -756,6 +757,7 @@ public class Path { 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 class Path { } 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 () {@@ -188,7 +188,7 @@ public class PenTool : Tool { p.get_last_point ().set_reflective_handles (false); } - p.get_stroke (); // cache good stroke+ p.create_full_stroke (); // cache good stroke } }); @@ -108,7 +108,7 @@ public class ResizeTool : Tool { GlyphCanvas.redraw (); foreach (Path p in MainWindow.get_current_glyph ().active_paths) {- p.get_stroke ();+ p.create_full_stroke (); } }); @@ -17,6 +17,12 @@ using Math; namespace BirdFont { +public enum LineCap {+ BUTT,+ SQUARE,+ ROUND+}+ public class StrokeTool : Tool { public static double stroke_width = 0;@@ -283,26 +289,123 @@ public class StrokeTool : Tool { 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 start, end;+ EditPointHandle last_handle;+ EditPoint first, last; + + stroke1.remove_points_on_points ();+ stroke2.remove_points_on_points ();+ + 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 ();+ } - EditPoint n;- double stroke_width = path.stroke / 2;+ 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); - double y = sin (last_handle.angle - PI) * stroke_width;- double x = cos (last_handle.angle - PI) * stroke_width;+ a = (first.get_left_handle ().angle + PI) % (2 * PI);+ l = cap.points.get (1).get_right_handle ().length; - 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;+ 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 @@ public class StrokeTool : Tool { 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 @@ public class StrokeTool : Tool { last_counter.get_right_handle ().convert_to_line (); last_counter.recalculate_linear_handles (); }-+*/ return merged; } @@ -2094,17 +2195,17 @@ public class StrokeTool : Tool { 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); }@@ -159,6 +159,8 @@ static void add_arc_points (BezierPoints[] bezier_points, ref int bi, double x0, 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'; @@ -1195,16 +1195,8 @@ public class SvgParser { 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);-+ if (format == SvgFormat.ILLUSTRATOR) { path_list = create_paths_illustrator (bezier_points, bi); } else {@@ -1578,7 +1570,6 @@ public class SvgParser { } if (path.points.size > 0) {- warning ("Open path."); path_list.add (path); } @@ -122,7 +122,7 @@ public class TrackTool : Tool { drawing = true; foreach (Path path in glyph.active_paths) {- path.get_stroke (); // cache merged stroke parts+ path.create_full_stroke (); // cache merged stroke parts } } });