The Birdfont Source Code


All Repositories / birdfont.git / commit – RSS feed

Stroke

These changes was commited to the Birdfont repository Fri, 08 May 2015 15:16:48 +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>
Fri, 08 May 2015 15:16:48 +0000 (17:16 +0200)
committer Johan Mattsson <johan.mattsson.m@gmail.com>
Fri, 08 May 2015 17:03:45 +0000 (19:03 +0200)
commit 51602ed89303cc17e28ddd5680c059b4ed92fa16
tree a9dfa0532a36b0d079ecc67b2be3d9cff1cbcb16
parent fc3845d5d87ba6b49e785ae7f51ede5ae969b3a1
Stroke

birdfont/GtkWindow.vala
libbirdfont/BezierTool.vala
libbirdfont/EditPoint.vala
libbirdfont/ResizeTool.vala
libbirdfont/StrokeTool.vala
--- a/birdfont/GtkWindow.vala +++ b/birdfont/GtkWindow.vala @@ -805,7 +805,9 @@ public class GlyphCanvasArea : DrawingArea { GlyphCanvas glyph_canvas; WidgetAllocation alloc = new WidgetAllocation (); - + uint32 last_release = 0; + uint32 last_press = 0; + public GlyphCanvasArea (GlyphCanvas gc) { int event_flags; @@ -852,17 +854,33 @@ button_press_event.connect ((t, e)=> { GtkWindow.reset_modifier (e.state); + if (e.time < last_press) { + warning ("Discarding event."); + return true; + } + + last_press = e.time; + if (e.type == EventType.BUTTON_PRESS) { TabContent.button_press (e.button, e.x, e.y); } else if (e.type == EventType.2BUTTON_PRESS) { TabContent.double_click (e.button, e.x, e.y); } - + return true; }); button_release_event.connect ((t, e)=> { - TabContent.button_release ((int) e.button, e.x, e.y); + if (e.time < last_release) { + warning ("Discarding event."); + return true; + } + + if (e.type == EventType.BUTTON_RELEASE) { + TabContent.button_release ((int) e.button, e.x, e.y); + last_release = e.time; + } + return true; });
--- a/libbirdfont/BezierTool.vala +++ b/libbirdfont/BezierTool.vala @@ -40,6 +40,7 @@ double last_release_time = 0; double last_press_time = 0; + bool button_down = false; public BezierTool (string name) { base (name, t_ ("Create Beziér curves")); @@ -87,11 +88,18 @@ double px, py; Path? p; Path path; - + + if (button_down) { + warning ("Discarding event."); + return; + } + + button_down = true; + return_if_fail (state != MOVE_HANDLES); return_if_fail (state != MOVE_LAST_HANDLE_RIGHT); return_if_fail (state != MOVE_LAST_HANDLE_LEFT); - + if (b == 2) { if (g.is_open ()) { stop_drawing (); @@ -186,6 +194,13 @@ public void release (int b, int x, int y) { double px, py; Glyph g; + + if (!button_down) { + warning ("Discarding event."); + return; + } + + button_down = false; return_if_fail (state != MOVE_POINT);
--- a/libbirdfont/EditPoint.vala +++ b/libbirdfont/EditPoint.vala @@ -54,6 +54,8 @@ public static uint OVERLAY = 1 << 11; public static uint CURVE = 1 << 12; public static uint CURVE_KEEP = 1 << 13; + public static uint SEGMENT_END = 1 << 14; + public static uint ALL = 0xFFFFFF; public uint flags = NONE;
--- a/libbirdfont/ResizeTool.vala +++ b/libbirdfont/ResizeTool.vala @@ -312,6 +312,7 @@ // resize paths foreach (Path selected_path in glyph.active_paths) { selected_path.resize (ratio); + selected_path.reset_stroke (); } // move paths relative to the updated xmin and xmax @@ -319,7 +320,7 @@ dx = resize_pos_x - selection_minx; dy = resize_pos_y - selection_miny; foreach (Path selected_path in glyph.active_paths) { - selected_path.move (dx, dy); + selected_path.move (dx, dy); } if (glyph.active_paths.size > 0) { @@ -409,6 +410,7 @@ foreach (Path p in glyph.active_paths) { p.move (dx, 0); + p.reset_stroke (); } last_skew = skew;
--- a/libbirdfont/StrokeTool.vala +++ b/libbirdfont/StrokeTool.vala @@ -88,16 +88,18 @@ } public static PathList get_stroke_fast (Path path, double thickness) { - /* PathList o; + PathList o; Path stroke; + o = get_stroke (path, thickness); + + /* // FIXME: stroke = path.copy (); stroke.remove_points_on_points (0.3); o = create_stroke (stroke, thickness, true); - - return o; */ - return get_stroke (path, thickness); + + return o; } public static PathList get_stroke (Path path, double thickness) { @@ -107,9 +109,22 @@ stroke = path.copy (); stroke.remove_points_on_points (0.3); o = create_stroke (stroke, thickness, false); + + if (stroke_selected) { // FIXME: DELETE + foreach (Path mm in o.paths) + ((!) BirdFont.get_current_font ().get_glyph ("o")).add_path (mm); + } + o = get_all_parts (o); - o = merge (o); + + if (stroke_selected) { // FIXME: DELETE + foreach (Path mm in o.paths) + ((!) BirdFont.get_current_font ().get_glyph ("p")).add_path (mm); + } + o = remove_intersection_paths (o); + o = merge (o); + m = new PathList (); foreach (Path p in o.paths) { m.add (simplify_stroke (p)); @@ -178,59 +193,55 @@ if (simplified.points.size > 0) { last = simplified.get_last_point (); + } + + if (added_segment.points.size > 0) { segment_last = added_segment.get_last_point (); - } + first = added_segment.get_first_point (); + segment_last.get_right_handle ().convert_to_line (); + + if (simplified.points.size > 1) { + simplified.delete_last_point (); + } + + last.get_right_handle ().x = first.get_right_handle ().x; + last.get_right_handle ().y = first.get_right_handle ().y; + + first.get_left_handle ().convert_to_curve (); + first.get_left_handle ().x = last.get_left_handle ().x; + first.get_left_handle ().y = last.get_left_handle ().y; + + last = added_segment.get_last_point (); + last.get_right_handle ().convert_to_line (); + last.recalculate_linear_handles (); + + simplified.append_path (added_segment); + + if (ep_start.get_right_handle ().is_line ()) { + first = added_segment.get_first_point (); + first.get_right_handle ().convert_to_line (); + first.recalculate_linear_handles (); + } - first = added_segment.get_first_point (); - - segment_last.get_right_handle ().convert_to_line (); - - if (simplified.points.size > 1) { - simplified.delete_last_point (); + } else { + warning ("No points in segment."); } - - last.get_right_handle ().x = first.get_right_handle ().x; - last.get_right_handle ().y = first.get_right_handle ().y; - - first.get_left_handle ().convert_to_curve (); - first.get_left_handle ().x = last.get_left_handle ().x; - first.get_left_handle ().y = last.get_left_handle ().y; - - simplified.append_path (added_segment); - - last = added_segment.get_last_point (); - last.get_right_handle ().convert_to_line (); - last.recalculate_linear_handles (); - - if (ep_start.get_right_handle ().is_line ()) { - first = added_segment.get_first_point (); - first.get_right_handle ().convert_to_line (); - first.recalculate_linear_handles (); - } - + i = stop; } else { simplified.add_point (ep.copy ()); } } - simplified.remove_points_on_points (); simplified.recalculate_linear_handles (); simplified.close (); - /* - if (p.get_first_point ().tie_handles) { - first = simplified.get_first_point (); - first.convert_to_curve (); - first.tie_handles = true; - first.process_tied_handle (); + simplified.remove_points_on_points (0.01); + + if (simplified.points.size > 0) { + simplified.get_last_point ().color = Color.pink (); + simplified.get_first_point ().color = Color.green (); } - */ - - //simplified.remove_points_on_points (); - - simplified.get_last_point ().color = Color.pink (); - simplified.get_first_point ().color = Color.green (); return simplified; } @@ -278,25 +289,28 @@ return simplified; } - static bool segment_is_line (Path p, int start, int stop) { - EditPoint p0, p1, p2; + static PathList remove_intersection_paths (PathList pl) { + PathList r = new PathList (); - if (stop - start < 2) { - warning ("Too small segment."); - return true; + foreach (Path p in pl.paths) { + if (p.points.size > 7) { + r.add (p); + } else { + has_new_corner (p); + } } - for (int i = start; i <= stop - 2; i++) { - p0 = p.points.get (i); - p1 = p.points.get (i + 1); - p2 = p.points.get (i + 2); - - if (!is_line (p0.x, p0.y, p1.x, p1.y, p2.x, p2.y)) { - return false; + return r; + } + + static bool has_new_corner (Path p) { + foreach (EditPoint ep in p.points) { + if ((ep.flags & EditPoint.NEW_CORNER) > 0) { + return true; } } - return true; + return false; } /** Create one stroke from the outline and counter stroke and close the @@ -380,6 +394,7 @@ EditPointHandle next_handle; EditPoint cutoff1, cutoff2; double adjusted_stroke = (stroke_width * 0.999999) / 2.0; + bool d1, d2; previous_handle = previous.get_left_handle (); next_handle = next.get_right_handle (); @@ -396,11 +411,27 @@ distance = Path.distance_to_point (corner, original); ratio = 1.5 * fabs (adjusted_stroke) / distance; + + double or = original.get_right_handle ().angle; + double ol = original.get_left_handle ().angle; + + if (previous.prev == null) { // FIXME: first point + warning ("Point before corner."); + d1 = false; + d2 = false; + } else { + d1 = corner.x - previous.x >= 0 == previous.x - previous.get_prev ().x >= 0; + d2 = corner.y - previous.y >= 0 == previous.y - previous.get_prev ().y >= 0; + } if (ratio > 1) { - stroked.add_point (corner); + if (!d1 && !d2) { + return; + } else { + stroked.add_point (corner); + } } else { - + cutoff1 = new EditPoint (); cutoff1.set_point_type (previous.type); cutoff1.convert_to_line (); @@ -409,11 +440,19 @@ cutoff2.set_point_type (previous.type); cutoff2.convert_to_line (); - cutoff1.x = previous.x + (corner.x - previous.x) * ratio; - cutoff1.y = previous.y + (corner.y - previous.y) * ratio; + if (fabs (or - ol) < 0.001) { + cutoff1.x = previous.x + 1.5 * fabs (adjusted_stroke) * -cos (or); + cutoff1.y = previous.y + 1.5 * fabs (adjusted_stroke) * -sin (or); - cutoff2.x = next.x + (corner.x - next.x) * ratio; - cutoff2.y = next.y + (corner.y - next.y) * ratio; + cutoff2.x = next.x + 1.5 * fabs (adjusted_stroke) * -cos (or); + cutoff2.y = next.y + 1.5 * fabs (adjusted_stroke) * -sin (or); + } else { + cutoff1.x = previous.x + (corner.x - previous.x) * ratio; + cutoff1.y = previous.y + (corner.y - previous.y) * ratio; + + cutoff2.x = next.x + (corner.x - next.x) * ratio; + cutoff2.y = next.y + (corner.y - next.y) * ratio; + } if (!cutoff1.is_valid () || cutoff2.is_valid ()) { cutoff1 = stroked.add_point (cutoff1); @@ -423,12 +462,8 @@ cutoff1.recalculate_linear_handles (); cutoff2.recalculate_linear_handles (); - return_if_fail (previous.prev != null); - - bool d1 = corner.x - previous.x > 0 == previous.x - previous.get_prev ().x > 0; - bool d2 = corner.y - previous.y > 0 == previous.y - previous.get_prev ().y > 0; - - if (!d1 && !d2) { // self intersection + // self intersection + if (!d1 && !d2) { cutoff1.deleted = true; cutoff2.deleted = true; @@ -436,7 +471,7 @@ stroked.add (cutoff1.x + (cutoff2.x - cutoff1.x) / 2, cutoff1.y + (cutoff2.y - cutoff1.y) / 2); return; - } + } if (distance > 4 * stroke_width) { previous.flags = EditPoint.NONE; @@ -557,10 +592,17 @@ if (add_intersection_points (path1, path2, 2)) { i = mark_intersection_as_deleted (path1); - return_if_fail (i == 2); + if (i != 2) { + warning (@"Expecting 2 points, $i points found."); + return false; + } i = mark_intersection_as_deleted (path2); - return_if_fail (i == 2); + if (i != 2) { + warning (@"Expecting 2 points, $i points found."); + return false; + } + pl1 = get_remaining_points (path1.copy ()); pl2 = get_remaining_points (path2.copy ()); @@ -787,7 +829,7 @@ ep1.type = prev.type; ep1.x = px; ep1.y = py; - ep1.color = c; + ep1.color = Color.yellow (); n.add (ep1); ep2.prev = ep1; @@ -805,7 +847,7 @@ ep3.type = prev.type; ep3.x = px; ep3.y = py; - ep3.color = c; + ep3.color = Color.yellow (); n.add (ep3); next.get_left_handle ().convert_to_line (); @@ -1189,6 +1231,7 @@ r = get_all_parts (r); } else { warning ("Not merged."); + error = true; } if (error) { @@ -1742,6 +1785,9 @@ bool intersection = false; int found = 0; + path1.close (); // FIXME: + path2.close (); + path1.all_segments ((ep1, ep2) => { double ix, iy; EditPoint p1, p2; @@ -1760,6 +1806,10 @@ return true; }); + + if (intersection && found != n) { + warning (@"Wrong number of points, $found != $n"); + } return intersection; } @@ -1912,9 +1962,9 @@ previous = start.copy (); previous_inside = start_inside.copy (); - previous.flags |= EditPoint.CURVE; - previous_inside.flags |= EditPoint.CURVE; - + previous.flags |= EditPoint.CURVE_KEEP; + previous_inside.flags |= EditPoint.CURVE_KEEP; + side1.add_point (previous); side2.add_point (previous_inside); } @@ -1937,7 +1987,19 @@ continue; } - step = 0; + get_segment (thickness, 0, 0.00001, p1, p2, out start); + get_segment (-thickness, 0, 0.00001, p1, p2, out start_inside); + + previous = start.copy (); + previous_inside = start_inside.copy (); + + previous.flags |= EditPoint.CURVE; + previous_inside.flags |= EditPoint.CURVE; + + side1.add_point (previous); + side2.add_point (previous_inside); + + step = step_size; keep = 0; step_size = 0.1; @@ -1965,7 +2027,7 @@ continue; } - if (flat && f_bigger && step_size < 0.25) { + if (flat && f_bigger && step_size < 0.1) { step_size *= step_increment; continue; } @@ -2023,7 +2085,7 @@ previous.flags |= EditPoint.CURVE; previous_inside.flags |= EditPoint.CURVE; - + side1.add_point (previous); side2.add_point (previous_inside); @@ -2081,9 +2143,6 @@ previous.flags |= EditPoint.CURVE; previous_inside.flags |= EditPoint.CURVE; - side1.add_point (s1); - side2.add_point (s2); - side1.add_point (previous); side2.add_point (previous_inside); } @@ -2111,7 +2170,6 @@ } static void convert_to_curve (Path path) { - if (path.is_open ()) { path.get_first_point ().flags &= EditPoint.ALL ^ EditPoint.CURVE; path.get_last_point ().flags &= EditPoint.ALL ^ EditPoint.CURVE;