The Birdfont Source Code


All Repositories / birdfont.git / commitdiff – RSS feed

More multimaster code

These changes was commited to the Birdfont repository Wed, 18 Nov 2015 10:48:37 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
[Wed, 18 Nov 2015 10:48:37 +0000]

Updated Files

libbirdfont/EditPointHandle.vala
libbirdfont/Glyph.vala
libbirdfont/GlyphCollection.vala
libbirdfont/OverviewTools.vala
libbirdfont/Path.vala
libbirdfont/StrokeTool.vala
--- a/libbirdfont/EditPointHandle.vala +++ b/libbirdfont/EditPointHandle.vala @@ -314,6 +314,11 @@ double x = (cos (angle1) + cos (angle2)) / 2; double y = (sin (angle1) + sin (angle2)) / 2; handle.move_to_coordinate (x, y); + + if (fabs (x) < 0.001 && fabs (y) < 0.001) { + return (angle1 + PI / 2) % 2 * PI; + } + return handle.angle; }
--- a/libbirdfont/Glyph.vala +++ b/libbirdfont/Glyph.vala @@ -2445,37 +2445,30 @@ } public Glyph self_interpolate (double weight) { - Glyph g = copy (); - g.fix_curve_orientation (); - g.layers = new Layer (); // remove all paths + Glyph g1 = copy (); + Glyph g2 = copy (); - foreach (Path p in get_visible_paths ()) { + g1.fix_curve_orientation (); + g2.layers = new Layer (); // remove all paths + + foreach (Path p in g1.get_visible_paths ()) { bool counter = !p.is_clockwise (); + //g2.add_path (p.self_interpolate (weight, counter)); + + g2.add_path (p.copy ()); - g.add_path (p.copy ()); + p.remove_points_on_points (); Path master = p.get_self_interpolated_master (counter); - g.add_path (master); + p = p.interpolate_estimated_path (master, weight); + p.recalculate_linear_handles (); - g.add_path (p.interpolate_estimated_path (master, weight)); - } - - return g; - } - - public Glyph self_interpolate_fast (double weight) { - Glyph g = copy (); - g.fix_curve_orientation (); - g.layers = new Layer (); // remove all paths - - foreach (Path p in get_visible_paths ()) { - bool counter = !p.is_clockwise (); - Path path = p.self_interpolate_fast (weight, counter); - g.add_path (path); + g2.add_path (p); + g2.add_path (master); } - return g; + return g2; } } }
--- a/libbirdfont/GlyphCollection.vala +++ b/libbirdfont/GlyphCollection.vala @@ -158,7 +158,8 @@ } if (glyph_masters.size == 1) { - return get_current ().self_interpolate_fast (weight); + //return get_current ().self_interpolate_fast (weight); + return get_current (); } else { warning("Not implemented."); }
--- a/libbirdfont/OverviewTools.vala +++ b/libbirdfont/OverviewTools.vala @@ -157,8 +157,8 @@ master_size.set_big_number (false); master_size.set_int_value ("0.000"); master_size.set_int_step (1); - master_size.set_min (-2); - master_size.set_max (2); + master_size.set_min (-1); + master_size.set_max (1); master_size.show_icon (true); master_size.set_persistent (false); master_size.new_value_action.connect ((self) => {
--- a/libbirdfont/Path.vala +++ b/libbirdfont/Path.vala @@ -2632,23 +2632,6 @@ h.move_to_coordinate (nx, ny); } - } - - public EditPoint get_closest_point (double x, double y) { - double min = Glyph.CANVAS_MAX; - double d; - EditPoint p = new EditPoint (Glyph.CANVAS_MAX, Glyph.CANVAS_MAX); - - foreach (EditPoint ep in points) { - d = distance (x, ep.x, y, ep.y); - - if (d < min) { - min = d; - p = ep; - } - } - - return p; } public Path self_interpolate (double weight, bool counter) { @@ -2670,27 +2653,23 @@ } return p; - } - - public Path self_interpolate_fast (double weight, bool counter) { - return StrokeTool.change_weight_fast (this, 5 * weight, counter); - } - - static double abs_max (double a, double b) { - return fabs (a) > fabs (b) ? a : b; } public Path interpolate_estimated_path (Path master, double weight) { Path p = copy (); EditPoint ep, master_point; - EditPointHandle h; - double length; double x, y; + + if (p.points.size <= 1 || master.points.size <= 1) { + return p; + } master_point = new EditPoint (); for (int i = 0; i < p.points.size; i++) { ep = p.points.get (i); + + bool debug = (-19 < ep.x < -21) && (39 < ep.y < 41); double right_angle = ep.get_right_handle ().angle; double left_angle = ep.get_left_handle ().angle; @@ -2698,33 +2677,138 @@ angle += PI; angle %= 2 * PI; - x = ep.x + 5 * cos (angle); - y = ep.y + 5 * sin (angle); + double close_x, close_y; + double min_distance = Glyph.CANVAS_MAX; + double distance; + double distance_to_edge = (5 / 2.0) * weight; - master_point = new EditPoint (); - master.get_closest_point_on_path (master_point, x, y); - master_point.color = Color.red (); - master.insert_new_point_on_path (master_point); + close_x = Glyph.CANVAS_MAX; + close_y = Glyph.CANVAS_MAX; - ep.x += (master_point.x - ep.x) * weight; - ep.y += (master_point.y - ep.y) * weight; + while (Path.distance (close_x, master_point.x, close_y, master_point.y) > 0.1) { + x = ep.x + distance_to_edge * cos (angle); + y = ep.y + distance_to_edge * sin (angle); + + if (debug) { + print(@"Search $x $y\n"); + } + + master_point = new EditPoint (); + master.get_closest_point_on_path (master_point, x, y); + master_point.color = Color.red (); + master.insert_new_point_on_path (master_point); + master_point.get_right_handle ().angle = angle; + + distance_to_edge += 0.1; + + distance = Path.distance (x, master_point.x, y, master_point.y); + if (distance < min_distance) { + min_distance = distance; + close_x = x; + close_y = y; + } + + if (distance_to_edge > 5) { + break; + } + } - /* - h = ep.get_right_handle (); - h.length += 5 * weight; + x = close_x; + y = close_x; - h = ep.get_left_handle (); - h.length += 5 * weight; - */ + ep.x += (master_point.x - ep.x) * weight; + ep.y += (master_point.y - ep.y) * weight; } + + p.adjust_interpolated_handles (master, fabs ((5 / 2.0) * weight)); return p; } public Path get_self_interpolated_master (bool counter) { return StrokeTool.change_weight (this, counter); + } + + void adjust_interpolated_handles (Path master, double edge) { + EditPoint ep, next; + + for (int i = 0; i < points.size; i++) { + ep = points.get (i); + next = points.get (i % points.size); + adjust_interpolated_handle (master, ep, next, edge); + } + } + + void adjust_interpolated_handle (Path master, + EditPoint ep, EditPoint next, + double edge) { + + double x, y; + double next_length_adjustment = 0; + double prev_length_adjustment_reverse = 0; + + double min_distortion = double.MAX; + + EditPoint master_point = new EditPoint (); + + get_point_for_step (ep, next, 0.55, out x, out y); + master.get_closest_point_on_path (master_point, x, y); + + double tolerance = 0.01; + double start_length = ep.get_right_handle ().length; + double stop_length = next.get_left_handle ().length; + + EditPoint ep1, ep2; + + ep1 = ep.copy (); + ep2 = next.copy (); + + double total_distance = Path.distance (ep1.x, ep2.x, ep1.y, ep2.y); + + for (double m = 50.0; m >= tolerance / 2.0; m /= 10.0) { + double step = m / 10.0; + min_distortion = double.MAX; + + double first = (m == 50.0) ? 0 : -m; + + for (double a = first; a < m; a += step) { + for (double b = first; b < m; b += step) { + + if (start_length + a + stop_length + b > total_distance) { + break; + } + + ep1.get_right_handle ().length = start_length + a; + ep2.get_left_handle ().length = stop_length + b; + + get_point_for_step (ep1, ep2, 0.55, out x, out y); + double error = distance (master_point.x, x, master_point.y, y); + error = fabs(error - edge); + + if (error < min_distortion + && start_length + a > 0 + && stop_length + b > 0) { + min_distortion = error; + prev_length_adjustment_reverse = a; + next_length_adjustment = b; + } + } + } + + start_length += prev_length_adjustment_reverse; + stop_length += next_length_adjustment; + } + + ep.get_right_handle ().length = start_length; + + if (ep.get_right_handle ().type != PointType.QUADRATIC) { + next.get_left_handle ().length = stop_length; + } else { + next.get_left_handle ().move_to_coordinate ( + ep.get_right_handle ().x, ep.get_right_handle ().y); + } } } }
--- a/libbirdfont/StrokeTool.vala +++ b/libbirdfont/StrokeTool.vala @@ -3150,21 +3150,9 @@ } } - /* - foreach (EditPoint ep in interpolated.points) { - if ((ep.flags & EditPoint.SEGMENT_END) != 0) { - deleted.add (new PointSelection (ep, interpolated)); - } - } - - foreach (PointSelection ps in deleted) { - PenTool.remove_point_simplify_path (ps); - } - */ - - return interpolated; // FIXME: split paths in interpolation? + return interpolated; } } }