Clone in a terminal:
Commit 8fe65b2
Johan Mattsson - 2014-07-10T15:01:24+00:00
8fe65b220263d0c2dd05fa7d0779a250738ad0f7johan.mattsson.m@gmail.com

Use quatratic control points for estimating SVG arc instruction before converting TTF

Changed files (5)

Diff

diff --git a/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala b/libbirdfont/OpenFontFormat/OpenFontFormatReader.valaindex ca3b854..8f4c640 100644--- a/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala+++ b/libbirdfont/OpenFontFormat/OpenFontFormatReader.vala@@ -147,7 +147,7 @@ public class OpenFontFormatReader : Object { 		return directory_table.head_table.get_adjusted_checksum (); 	} 	-	public static string parse_kerning (string file_name) {+	public static string? parse_kerning (string file_name) { 		KernTable kern_table; 		CmapTable cmap_table; 		HeadTable head_table;@@ -156,6 +156,7 @@ public class OpenFontFormatReader : Object { 		unichar left, right; 		double kerning, units_per_em; 		uint npairs = 0;+		string result = ""; 		 		try { 			reader.parse_index (file_name);@@ -194,7 +195,13 @@ public class OpenFontFormatReader : Object { 			warning (@"Failed to parse font. $(e.message)"); 		} 				-		return bf_kerning.str;+		result = bf_kerning.str;+		+		if (result == "") {+			return null;+		}+		+		return result.dup ();				 	} } }diff --git a/libbirdfont/OpenFontFormat/load_font.c b/libbirdfont/OpenFontFormat/load_font.cindex db91a11..3364f41 100644--- a/libbirdfont/OpenFontFormat/load_font.c+++ b/libbirdfont/OpenFontFormat/load_font.c@@ -757,6 +757,7 @@ GString* get_bf_font (FT_Face face, char* file, int* err) { 		g_string_append_printf (bf, "</collection>\n"); 	} + 	// glyph outlines 	for (i = 0; i < face->num_glyphs; i++) { 		error = FT_Load_Glyph (face, i, FT_LOAD_DEFAULT | FT_LOAD_NO_SCALE);@@ -792,9 +793,9 @@ GString* get_bf_font (FT_Face face, char* file, int* err) { 		g_string_append (bf, glyph->str); 		g_string_free (glyph, 0); 	}-	+ 	kerning = (gchar*) bird_font_open_font_format_reader_parse_kerning (file); -	+ 	if (kerning != NULL) { 		g_string_append (bf, kerning); 		g_free (kerning);	diff --git a/libbirdfont/Path.vala b/libbirdfont/Path.valaindex 023bc90..e2befee 100644--- a/libbirdfont/Path.vala+++ b/libbirdfont/Path.vala@@ -1063,10 +1063,11 @@ public class Path { 		foreach (EditPoint next in points) { 			left = first.get_right_handle ().type; 			right = next.get_left_handle ().type;+						 			if (right == PointType.DOUBLE_CURVE || left == PointType.DOUBLE_CURVE) { 				first.get_right_handle ().type = PointType.QUADRATIC; -				// half the way between handles+				// half way between handles 				x = first.get_right_handle ().x () + (next.get_left_handle ().x () - first.get_right_handle ().x ()) / 2; 				y = first.get_right_handle ().y () + (next.get_left_handle ().y () - first.get_right_handle ().y ()) / 2; 				@@ -1090,6 +1091,10 @@ public class Path { 		} 		 		for (int i = 0; i < middle_points.size; i++) {+			+			hidden = middle_points.get (i);+			print (@"middle $(hidden.x)  $(hidden.y)\n");+			 			add_point_after (middle_points.get (i), first_points.get (i)); 		} 	}@@ -1108,7 +1113,7 @@ public class Path { 			warning ("Less than 2 points in path."); 			return quadratic_path; 		}-		+	 		i = points.get (0); 		next = i.get_next (); @@ -1155,7 +1160,9 @@ public class Path { 		} else { 			quadratic_path.reopen (); 		}-								+		+		quadratic_path.remove_points_on_points ();+						 		return quadratic_path; 	} 	@@ -1184,7 +1191,9 @@ public class Path { 						 			e = new EditPoint (x, y, PointType.QUADRATIC); 			added_points++;-+			+			e = quadratic_path.add_point (e);+/* 			prev = e;  			e = quadratic_path.add_point (e);@@ -1193,9 +1202,14 @@ public class Path { 			prev.recalculate_linear_handles (); 			 			new_quadratic_points.add (prev);+*/ 			return true; 		}, steps); 		+		foreach (EditPoint e in quadratic_path.points) {+			e.recalculate_linear_handles ();+		}+		 		quadratic_path.close (); 	} @@ -2148,6 +2162,52 @@ public class Path { 		} 		return i; 	}+	+	public void remove_points_on_points () +	requires (points.size > 0) {+		Gee.ArrayList<EditPoint> remove = new Gee.ArrayList<EditPoint> ();+		EditPoint n;+		EditPointHandle hr, h;+		+		create_list ();+		+		foreach (EditPoint ep in points) {+			if (ep.next != null) {+				n = ep.get_next ();+			} else {+				warning ("NEXT IS NULL");+				n = points.get (0);+			}+				+			if (fabs (n.x - ep.x) < 0.00001 && fabs (n.y - ep.y) < 0.00001) {+				remove.add (ep);+			}+		}++		foreach (EditPoint r in remove) {+			if (r.next != null) {+				n = r.get_next ();+			} else {+				n = points.get (0);+			}+			+			points.remove (r);+			h = n.get_left_handle ();+			hr = r.get_left_handle ();+			h.length = hr.length;+			h.angle = hr.angle;+			h.type = hr.type;+			+			if (h.length < 0.00001) {+				h.length = 0.00001;+				h.angle = n.get_right_handle ().angle - PI;+			}+			+			create_list ();+		}+		+		recalculate_linear_handles ();+	} }  }diff --git a/libbirdfont/SvgArc.vala b/libbirdfont/SvgArc.valaindex b9ec170..c56667d 100644--- a/libbirdfont/SvgArc.vala+++ b/libbirdfont/SvgArc.vala@@ -79,9 +79,11 @@ static void add_arc_points (BezierPoints[] bezier_points, ref int bi, double x0, 	Pry = ry * ry; 	Px1 = x1 * x1; 	Py1 = y1 * y1;+ 	 	// Check that radii are large enough 	radiiCheck = Px1 / Prx + Py1 / Pry;+	 	if (radiiCheck > 1) { 		rx = sqrt (radiiCheck) * rx; 		ry = sqrt (radiiCheck) * ry;@@ -93,7 +95,7 @@ static void add_arc_points (BezierPoints[] bezier_points, ref int bi, double x0, 	// Step 2 : Compute (cx1, cy1) 	// 	sign = (largeArcFlag == sweepFlag) ? -1 : 1;-	sq = ((Prx*Pry)-(Prx*Py1)-(Pry*Px1)) / ((Prx*Py1)+(Pry*Px1));+	sq = ((Prx * Pry) - (Prx * Py1) - (Pry * Px1)) / ((Prx * Py1) + (Pry * Px1)); 	sq = (sq < 0) ? 0 : sq; 	coef = (sign * Math.sqrt(sq)); 	cx1 = coef * ((rx * y1) / ry);@@ -142,7 +144,7 @@ static void add_arc_points (BezierPoints[] bezier_points, ref int bi, double x0, 	 	// Approximate the path with Beziér points 	s = (angleExtent > 0) ? 1 : -1;-	step = fabs (angleExtent) / (3 * fabs (angleExtent));+	step = fabs (angleExtent) / (2 * fabs (angleExtent));  	theta = PI - angleStart - angleExtent; 	@@ -163,11 +165,11 @@ static void add_arc_points (BezierPoints[] bezier_points, ref int bi, double x0, 		bezier_points[bi].x0 = cx + rx * cos (theta); 		bezier_points[bi].y0 = cy + ry * sin (theta); -		bezier_points[bi].x1 = cx + rx * cos (theta + 1 * step / 3);-		bezier_points[bi].y1 = cy + ry * sin (theta + 1 * step / 3);+		bezier_points[bi].x1 = cx + rx * cos (theta + 1 * step / 4);+		bezier_points[bi].y1 = cy + ry * sin (theta + 1 * step / 4); 		-		bezier_points[bi].x2 = cx + rx * cos (theta + 2 * step / 3);-		bezier_points[bi].y2 = cy + ry * sin (theta + 2 * step / 3);+		bezier_points[bi].x2 = cx + rx * cos (theta + 2 * step / 4);+		bezier_points[bi].y2 = cy + ry * sin (theta + 2 * step / 4); 						 		bi++; 	}diff --git a/libbirdfont/SvgParser.vala b/libbirdfont/SvgParser.valaindex e83ff00..f7f9554 100644--- a/libbirdfont/SvgParser.vala+++ b/libbirdfont/SvgParser.vala@@ -904,7 +904,6 @@ public class SvgParser { 		PathList path_list = new PathList (); 		EditPoint ep = new EditPoint (); 		Gee.ArrayList<EditPoint> smooth_points = new Gee.ArrayList<EditPoint> ();-		EditPoint next, prev; 				 		path = new Path (); 		@@ -1021,28 +1020,31 @@ public class SvgParser { 		}  		foreach (EditPoint e in smooth_points) {-			e.set_tie_handle (true);-			e.process_tied_handle ();-			-			e.set_point_type (PointType.CUBIC);-			e.get_right_handle ().set_point_type (PointType.CUBIC);-			e.get_left_handle ().set_point_type (PointType.CUBIC);-			-			if (e.next != null) {-				next = e.get_next ();-				next.get_left_handle ().angle = next.get_right_handle ().angle - PI;-			}+			e.set_point_type (PointType.LINE_DOUBLE_CURVE);+			e.get_right_handle ().set_point_type (PointType.LINE_DOUBLE_CURVE);+			e.get_left_handle ().set_point_type (PointType.LINE_DOUBLE_CURVE);+		} -			if (e.prev != null) {-				prev = e.get_prev ();-				prev.get_right_handle ().angle = prev.get_left_handle ().angle - PI;+		foreach (EditPoint e in smooth_points) {+			e.recalculate_linear_handles ();+		}+		++		for (int i = 0; i < 3; i++) {+			foreach (EditPoint e in smooth_points) {+				e.set_tie_handle (true);+				e.process_tied_handle (); 			} 		} 		 		if (path.points.size > 0) { 			path_list.add (path); 		}-		++		foreach (Path p in path_list.paths) {+			p.remove_points_on_points ();+		}+				 		return path_list; 	} @@ -1053,7 +1055,6 @@ public class SvgParser { 		bool first_point = true; 		double first_left_x, first_left_y; 		Gee.ArrayList<EditPoint> smooth_points = new Gee.ArrayList<EditPoint> ();-		EditPoint next, prev; 				 		path = new Path (); 				@@ -1140,21 +1141,20 @@ public class SvgParser { 		} 		 		foreach (EditPoint e in smooth_points) {-			e.set_tie_handle (true);-			e.process_tied_handle ();+			e.set_point_type (PointType.LINE_DOUBLE_CURVE);+			e.get_right_handle ().set_point_type (PointType.LINE_DOUBLE_CURVE);+			e.get_left_handle ().set_point_type (PointType.LINE_DOUBLE_CURVE);+		} -			e.set_point_type (PointType.CUBIC);-			e.get_right_handle ().set_point_type (PointType.CUBIC);-			e.get_left_handle ().set_point_type (PointType.CUBIC);+		foreach (EditPoint e in smooth_points) {+			e.recalculate_linear_handles ();+		}+		 -			if (e.next != null) {-				next = e.get_next ();-				next.get_left_handle ().angle = next.get_right_handle ().angle - PI;-			}-			-			if (e.prev != null) {-				prev = e.get_prev ();-				prev.get_right_handle ().angle = prev.get_left_handle ().angle - PI;+		for (int i = 0; i < 3; i++) {+			foreach (EditPoint e in smooth_points) {+				e.set_tie_handle (true);+				e.process_tied_handle (); 			} 		} 				@@ -1163,6 +1163,10 @@ public class SvgParser { 			path_list.add (path); 		} 		+		foreach (Path p in path_list.paths) {+			p.remove_points_on_points ();+		}+		 		return path_list; 	} 	

Contact

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