Clone in a terminal:
Commit 504952a
Johan Mattsson - 2015-11-18T10:48:37+00:00
504952afe669e84f42bd52d152172578450a5a13johan.mattsson.m@gmail.com

More multimaster code

Changed files (6)

Diff

diff --git a/libbirdfont/EditPointHandle.vala b/libbirdfont/EditPointHandle.valaindex 63bdc7c..ee5feb4 100644--- a/libbirdfont/EditPointHandle.vala+++ b/libbirdfont/EditPointHandle.vala@@ -314,6 +314,11 @@ public class EditPointHandle : GLib.Object { 		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; 	} diff --git a/libbirdfont/Glyph.vala b/libbirdfont/Glyph.valaindex d983f00..364f4f4 100644--- a/libbirdfont/Glyph.vala+++ b/libbirdfont/Glyph.vala@@ -2445,35 +2445,28 @@ public class Glyph : FontDisplay { 	} 	 	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));+			g2.add_path (p);+			g2.add_path (master); 		} 		-		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);-		}-		-		return g;+		return g2; 	} } diff --git a/libbirdfont/GlyphCollection.vala b/libbirdfont/GlyphCollection.valaindex 79d3afb..0a7907d 100644--- a/libbirdfont/GlyphCollection.vala+++ b/libbirdfont/GlyphCollection.vala@@ -158,7 +158,8 @@ public class GlyphCollection : GLib.Object { 		} 		 		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."); 		}diff --git a/libbirdfont/OverviewTools.vala b/libbirdfont/OverviewTools.valaindex 1050818..4e91137 100644--- a/libbirdfont/OverviewTools.vala+++ b/libbirdfont/OverviewTools.vala@@ -157,8 +157,8 @@ public class OverviewTools : ToolCollection  { 		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) => {diff --git a/libbirdfont/Path.vala b/libbirdfont/Path.valaindex 0bb47d4..4b7f5f2 100644--- a/libbirdfont/Path.vala+++ b/libbirdfont/Path.vala@@ -2634,23 +2634,6 @@ public class Path : GLib.Object { 		} 	} 	-	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) { 		Path master; 		Path p = new Path ();@@ -2671,26 +2654,22 @@ public class Path : GLib.Object { 		 		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,32 +2677,137 @@ public class Path : GLib.Object { 			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);+		}+	} }  }diff --git a/libbirdfont/StrokeTool.vala b/libbirdfont/StrokeTool.valaindex f0d135e..e612157 100644--- a/libbirdfont/StrokeTool.vala+++ b/libbirdfont/StrokeTool.vala@@ -3150,19 +3150,7 @@ public class StrokeTool : GLib.Object { 			} 		} 		-		/*-		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; 	}  } 

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112