Commit ebfec3a
Generate outline for new masters from stroked paths
Changed files (7)
modifiedlibbirdfont/EditPointHandle.valamodifiedlibbirdfont/Glyph.valamodifiedlibbirdfont/GlyphCollection.valamodifiedlibbirdfont/OverViewItem.valamodifiedlibbirdfont/OverviewTools.valamodifiedlibbirdfont/Path.valamodifiedlibbirdfont/StrokeTool.vala
Diff
@@ -219,7 +219,7 @@ public class EditPointHandle : GLib.Object { process_connected_handle (); }- + public void move_to_coordinate_internal (double x, double y) { double a, b, c; @@ -308,6 +308,15 @@ public class EditPointHandle : GLib.Object { public bool is_line () { return PenTool.is_line (type); }++ public static double average_angle (double angle1, double angle2) {+ EditPointHandle handle = new EditPointHandle (new EditPoint (0, 0), 0, 1);+ double x = (cos (angle1) + cos (angle2)) / 2;+ double y = (sin (angle1) + sin (angle2)) / 2;+ handle.move_to_coordinate (x, y);+ return handle.angle;+ }+ } }@@ -2444,10 +2444,36 @@ public class Glyph : FontDisplay { GlyphCanvas.redraw (); } - public void self_interpolate (double weight) {+ public Glyph self_interpolate (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 ();+ + g.add_path (p.copy ());+ Path master = p.get_self_interpolated_master (counter);+ g.add_path (master);+ + 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 ()) {- p.self_interpolate (weight);+ bool counter = !p.is_clockwise ();+ Path path = p.self_interpolate_fast (weight, counter);+ g.add_path (path); }+ + return g; } } @@ -21,10 +21,8 @@ public class GlyphCollection : GLib.Object { unichar unicode_character; string name; bool unassigned;- public Gee.ArrayList<GlyphMaster> glyph_masters;- - // FIXME: move this somewhere- static int current_master = 0;+ public Gee.ArrayList<GlyphMaster> glyph_masters; + int current_master = 0; public GlyphCollection (unichar unicode_character, string name) { this.unicode_character = unicode_character;@@ -66,7 +64,7 @@ public class GlyphCollection : GLib.Object { add_master (m); return m; } else if (unlikely (i >= glyph_masters.size)) {- warning(@"No master at index $i.");+ warning(@"No master at index $i. ($(glyph_masters.size)) in $(name)"); i = glyph_masters.size - 1; } @@ -146,16 +144,28 @@ public class GlyphCollection : GLib.Object { } if (glyph_masters.size == 1) {- Glyph master1 = get_current ().copy ();- master1.self_interpolate (weight);- return master1;+ return get_current ().self_interpolate (weight); } else { warning("Not implemented."); } return get_current (); }- ++ public Glyph get_interpolated_fast (double weight) {+ if (weight == 0) { // FIXME: compare to master weight+ return get_current (); + }+ + if (glyph_masters.size == 1) {+ return get_current ().self_interpolate_fast (weight);+ } else {+ warning("Not implemented.");+ }+ + return get_current ();+ }+ public void insert_glyph (Glyph g, bool selected_glyph) { get_current_master ().insert_glyph (g, selected_glyph); }@@ -211,7 +211,7 @@ public class OverViewItem : GLib.Object { if (gl != null) { font = BirdFont.get_current_font ();- g = ((!) gl).get_interpolated (OverviewTools.current_master_size);+ g = ((!) gl).get_interpolated_fast (OverviewTools.current_master_size); c.save (); g.boundaries (out x1, out y1, out x2, out y2);@@ -199,7 +199,6 @@ public class OverviewTools : ToolCollection { master.add_glyph(g); glyph_collection.add_master (master); glyph_collection.set_selected_master (master);- print(@"$(glyph_collection.get_name ())\n"); i++; gc = font.get_glyph_collection_indice (i);@@ -2640,8 +2640,8 @@ public class Path : GLib.Object { EditPoint p = new EditPoint (Glyph.CANVAS_MAX, Glyph.CANVAS_MAX); foreach (EditPoint ep in points) {- d = distance (x, ep.x, y, ep.y);- + d = distance (x, ep.x, y, ep.y); + if (d < min) { min = d; p = ep;@@ -2651,69 +2651,78 @@ public class Path : GLib.Object { return p; } - public void self_interpolate (double weight) {+ public Path self_interpolate (double weight, bool counter) { Path master;+ Path p = new Path (); if (stroke > 0) {- stroke += 5 * weight * 2;+ p = copy ();+ p.stroke += 5 * weight * 2; - if (stroke < 0.002) {- stroke = 0.002;+ if (p.stroke < 0.002) {+ p.stroke = 0.002; } } else { remove_points_on_points ();- master = get_self_interpolated_master ();- interpolate_path (master, weight);+ master = get_self_interpolated_master (counter);+ p = interpolate_estimated_path (master, weight); recalculate_linear_handles ();- } - }- - Path get_self_interpolated_master () {- Path master = new Path ();- EditPoint ep1, ep2, none;- - none = new EditPoint ();- for (int i = 0; i < points.size; i++) {- ep1 = points.get (i).copy ();- ep2 = ep1.copy ();- - StrokeTool.move_segment (ep1, none, 5);- StrokeTool.move_segment (none, ep2, 5);- - ep1.x = (ep2.x + ep1.x) / 2;- ep1.y = (ep2.y + ep1.y) / 2;- - master.add_point (ep1.copy ()); } - return master; + return p;+ }+ + public Path self_interpolate_fast (double weight, bool counter) {+ return StrokeTool.change_weight_fast (this, 5 * weight, counter); } - void interpolate_path (Path master, double weight) {+ 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;- - if (unlikely (points.size != master.points.size)) {- warning ("Master and path must have the same number of points.");- return;- }- - for (int i = 0; i < points.size; i++) {- ep = points.get (i);- master_point = master.points.get (i);- + double x, y;++ master_point = new EditPoint ();++ for (int i = 0; i < p.points.size; i++) {+ ep = p.points.get (i);++ double right_angle = ep.get_right_handle ().angle;+ double left_angle = ep.get_left_handle ().angle;+ double angle = EditPointHandle.average_angle (right_angle, left_angle);+ angle += PI;+ angle %= 2 * PI;+ + x = ep.x + 5 * cos (angle);+ y = ep.y + 5 * sin (angle);+ + 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);+ ep.x += (master_point.x - ep.x) * weight; ep.y += (master_point.y - ep.y) * weight; +/* h = ep.get_right_handle ();- length = master_point.get_right_handle ().length;- h.length = length * weight + h.length * (1 - weight);+ h.length += 5 * weight; h = ep.get_left_handle ();- length = master_point.get_left_handle ().length;- h.length = length * weight + h.length * (1 - weight) ;+ h.length += 5 * weight;+ */ }+ + return p;+ }++ public Path get_self_interpolated_master (bool counter) {+ return StrokeTool.change_weight (this, counter); } } @@ -2799,8 +2799,7 @@ public class StrokeTool : GLib.Object { return sum > 0; } - public PathList create_stroke (Path original_path, double thickness) {- + public PathList create_stroke (Path original_path, double thickness) { PathList pl; EditPoint p1, p2, p3; EditPoint previous, previous_inside, start, start_inside;@@ -3115,6 +3114,56 @@ public class StrokeTool : GLib.Object { return paths; }+ + public static Path change_weight_fast (Path path, double weight, bool counter) {+ StrokeTool tool = new StrokeTool ();+ PathList pl;+ + pl = tool.get_stroke_fast (path, fabs(weight));+ + return_val_if_fail (pl.paths.size == 2, new Path ());+ + if (counter == !pl.paths.get (0).is_clockwise ()) {+ return pl.paths.get (0);+ }+ + return pl.paths.get (1);+ }+ + public static Path change_weight (Path path, bool counter) {+ StrokeTool tool = new StrokeTool ();+ Path o = path.copy ();+ Path interpolated = new Path();+ o.force_direction (Direction.CLOCKWISE);+ + PathList pl = tool.get_stroke (o, 5);+ Gee.ArrayList<PointSelection> deleted;+ + deleted = new Gee.ArrayList<PointSelection> (); ++ return_val_if_fail (pl.paths.size > 0, new Path ());+ + foreach (Path sp in pl.paths) {+ if (sp.points.size > interpolated.points.size+ && counter == !sp.is_clockwise ()) {+ interpolated = sp;+ }+ }+ + /*+ 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?+ } } }