Clone in a terminal:
Commit be6cf8c
Johan Mattsson - 2016-07-28T10:10:11+00:00
be6cf8c2e6f11439a462249cea8e01f4384082e2johan.mattsson.m@gmail.com

Path iterator

Changed files (3)

Diff

diff --git a/libsvgbird/Object.vala b/libsvgbird/Object.valaindex 210eafa..6d0986a 100644--- a/libsvgbird/Object.vala+++ b/libsvgbird/Object.vala@@ -128,6 +128,11 @@ public abstract class Object : GLib.Object { 		m.transform_point (ref x, ref y); 	} 	+	public void from_object_distance (ref double x, ref double y) {+		Matrix m = view_matrix;+		m.transform_distance (ref x, ref y);+	}+	 	public void to_object_distance (ref double x, ref double y) { 		Matrix m = view_matrix; 		m.invert ();@@ -406,7 +411,7 @@ public abstract class Object : GLib.Object { 	} 	 	public Matrix copy_matrix (Matrix m) {-		return new Matrix (m.xx, m.yx, m.xy, m.yy, m.x0, m.y0);+		return Matrix (m.xx, m.yx, m.xy, m.yy, m.x0, m.y0); 	} } diff --git a/libsvgbird/Points.vala b/libsvgbird/Points.valaindex 2656d66..b7e2a5c 100644--- a/libsvgbird/Points.vala+++ b/libsvgbird/Points.vala@@ -13,12 +13,14 @@ */  using Cairo;+using Math;  namespace SvgBird {  public class Points : GLib.Object { 	public Doubles point_data = new Doubles.for_capacity (100); 	public bool closed;+	public delegate bool LineIterator (double start_x, double start_y, double end_x, double end_y, double step, int point_index); 	 	public int size { 		get {@@ -64,6 +66,118 @@ public class Points : GLib.Object { 	public uchar get_point_type (int index) { 		return point_data.get_point_type (index); 	}++	public void all_points (LineIterator iter) {+		double previous_x;+		double previous_y;++		PointValue* points = point_data.data;+		int size = point_data.size;+		+		return_if_fail (size % 8 == 0);+	+		SvgPath.get_start (this, out previous_x, out previous_y);+	+		for (int i = 1; i < size; i += 8) {+			switch (points[i].type) {+			case POINT_ARC:		+				double rx = points[i + 1].value;+				double ry = points[i + 2].value;+				double rotation = points[i + 3].value;+				double large_arc = points[i + 4].value;+				double sweep = points[i + 5].value;+				double dest_x = points[i + 6].value;+				double dest_y = points[i + 7].value;++				double angle_start, angle_extent, cx, cy;+				+				get_arc_arguments (previous_x, previous_y, rx, ry,+							rotation, large_arc > 0, sweep > 0, dest_x, dest_y,+							out angle_start, out angle_extent,+							out cx, out cy);+							+				const int steps = 50;+				for (int step = 0; step < steps; step++) {+					double angle = angle_start + step * (angle_extent / steps);+					double next_x = cx + cos (angle);+					double next_y = cy + sin (angle);+					+					iter (previous_x, previous_y, next_x, next_y, step, i);+							+					previous_x = next_x;+					previous_y = next_y;+				}+				break;+			case POINT_CUBIC:+				all_lines (previous_x, previous_y,+					points[i + 1].value, points[i + 2].value,+					points[i + 3].value, points[i + 4].value,+					points[i + 5].value, points[i + 6].value,+					(x, y, t) => {+						iter (previous_x, previous_y, x, y, 1, i);+						+						previous_x = x;+						previous_y = y;+						return true;+					});++				previous_x = points[i + 5].value;+				previous_y = points[i + 6].value;+				break;+			case POINT_LINE:+				double x = points[i + 1].value;+				double y = points[i + 2].value;+				+				iter (previous_x, previous_y, x, y, 1, i);+				+				previous_x = x;+				previous_y = y;+				break;+			}+		}+	}+			+	private static bool all_lines (double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3,+			LineIterator iter, int index = 0, double steps = 400) {+		double px = x1;+		double py = y1;+		+		double t;+		+		double previous_x = px;+		double previous_y = py;+		+		for (int i = 0; i < steps; i++) {+			t = i / steps;+			+			px = bezier_path (t, x0, x1, x2, x3);+			py = bezier_path (t, y0, y1, y2, y3);+						+			if (!iter (previous_x, previous_y, px, py, t, index)) {+				return false;+			}+			+			previous_x = px;+			previous_y = py;+		}+		+		return true;+	}++	public static double bezier_path (double step, double p0, double p1, double p2, double p3) {+		double q0, q1, q2;+		double r0, r1;++		q0 = step * (p1 - p0) + p0;+		q1 = step * (p2 - p1) + p1;+		q2 = step * (p3 - p2) + p2;++		r0 = step * (q1 - q0) + q0;+		r1 = step * (q2 - q1) + q1;++		return step * (r1 - r0) + r0;+	}+ }  }diff --git a/libsvgbird/SvgPath.vala b/libsvgbird/SvgPath.valaindex 4ca4935..32536bf 100644--- a/libsvgbird/SvgPath.vala+++ b/libsvgbird/SvgPath.vala@@ -23,8 +23,6 @@ public class SvgPath : Object { 	double pen_position_x = 0; 	double pen_position_y = 0; 	-	public delegate bool LineIterator (double x, double y, double step);	-	 	public SvgPath () { 	} @@ -53,76 +51,13 @@ public class SvgPath : Object { 	} 	 	public static bool is_over_points (Points p, double point_x, double point_y) {-		double previous_x;-		double previous_y; 		bool inside = false;--		PointValue* points = p.point_data.data;-		int size = p.point_data.size;-		-		return_if_fail (size % 8 == 0);-	-		get_start (p, out previous_x, out previous_y); 	-		for (int i = 0; i < size; i += 8) {-			switch (points[i].type) {-			case POINT_ARC:		-				double rx = points[i + 1].value;-				double ry = points[i + 2].value;-				double rotation = points[i + 3].value;-				double large_arc = points[i + 4].value;-				double sweep = points[i + 5].value;-				double dest_x = points[i + 6].value;-				double dest_y = points[i + 7].value;+		p.all_points ((start_x, start_y, end_x, end_y) => {+			is_inside (ref inside, point_x, point_y, start_x, start_y, end_x, end_y);+			return true;+		}); -				double angle_start, angle_extent, cx, cy;-				-				get_arc_arguments (previous_x, previous_y, rx, ry,-							rotation, large_arc > 0, sweep > 0, dest_x, dest_y,-							out angle_start, out angle_extent,-							out cx, out cy);-				const int steps = 50;-				for (int step = 0; step < steps; step++) {-					double angle = angle_start + step * (angle_extent / steps);-					double next_x = cx + cos (angle);-					double next_y = cy + sin (angle);-					is_inside (ref inside, -							point_x, point_y,-							previous_x, previous_y, -							next_x, next_y);-							-					previous_x = next_x;-					previous_y = next_y;-				}-				break;-			case POINT_CUBIC:-				all_lines (previous_x, previous_y,-					points[i + 1].value, points[i + 2].value,-					points[i + 3].value, points[i + 4].value,-					points[i + 5].value, points[i + 6].value,-					(x, y, t) => {-						is_inside (ref inside, -							point_x, point_y,-							previous_x, previous_y, -							x, y);-						-						previous_x = x;-						previous_y = y;-						return true;-					});-					-				previous_x = points[i + 5].value;-				previous_y = points[i + 6].value;-				break;-			case POINT_LINE:-				is_inside (ref inside, point_x, point_y, previous_x, previous_y, -					points[i + 1].value, points[i + 2].value);-				previous_x = points[i + 1].value;-				previous_y = points[i + 2].value;-				break;-			}-		}-		 		return inside; 	} @@ -133,41 +68,6 @@ public class SvgPath : Object { 			inside = !inside; 		} 	}-			-	private static bool all_lines (double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3,-			LineIterator iter, double steps = 400) {-		double px = x1;-		double py = y1;-		-		double t;-		-		for (int i = 0; i < steps; i++) {-			t = i / steps;-			-			px = bezier_path (t, x0, x1, x2, x3);-			py = bezier_path (t, y0, y1, y2, y3);-						-			if (!iter (px, py, t)) {-				return false;-			}-		}-		-		return true;-	}--	public static double bezier_path (double step, double p0, double p1, double p2, double p3) {-		double q0, q1, q2;-		double r0, r1;--		q0 = step * (p1 - p0) + p0;-		q1 = step * (p2 - p1) + p1;-		q2 = step * (p3 - p2) + p2;--		r0 = step * (q1 - q0) + q0;-		r1 = step * (q2 - q1) + q1;--		return step * (r1 - r0) + r0;-	} 	 	public override void draw_outline (Context cr) { 		foreach (Points p in points) {

Contact

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