Clone in a terminal:
Commit 17f5c30
Johan Mattsson - 2014-03-23T02:00:58+00:00
17f5c30a3f7d3b93d58a0790f723fc98ea84f5dejohan.mattsson.m@gmail.com

Render filled paths without parsing SVG This commit makes the stroke code five times faster.

Changed files (7)

Diff

diff --git a/birdfont/GtkWindow.vala b/birdfont/GtkWindow.valaindex bfe0523..1bb16ea 100644--- a/birdfont/GtkWindow.vala+++ b/birdfont/GtkWindow.vala@@ -352,7 +352,7 @@ public class GtkWindow : Gtk.Window, NativeWindow {  		public ColorWindow (ColorTool color_tool) {			 			color_selection.color_changed.connect (() => {-				Color c;+				Gdk.Color c; 				color_selection.get_current_color (out c); 				color_tool.color_r = (double) c.red / uint16.MAX; 				color_tool.color_g = (double) c.green / uint16.MAX;diff --git a/libbirdfont/Color.vala b/libbirdfont/Color.valanew file mode 100644index 0000000..b4e93e7--- /dev/null+++ b/libbirdfont/Color.vala@@ -0,0 +1,35 @@+/*+    Copyright (C) 2014 Johan Mattsson++    This library is free software; you can redistribute it and/or modify +    it under the terms of the GNU Lesser General Public License as +    published by the Free Software Foundation; either version 3 of the +    License, or (at your option) any later version.++    This library is distributed in the hope that it will be useful, but +    WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +    Lesser General Public License for more details.+*/++namespace BirdFont {++public class Color {+	public double r;+	public double g;+	public double b;+	public double a;+	+	public Color (double r, double g, double b, double a) {+		this.r = r;+		this.g = g;+		this.b = b;+		this.a = a;+	}+	+	public static Color black () {+		return new Color (0, 0, 0, 1);+	}+}++}diff --git a/libbirdfont/Glyph.vala b/libbirdfont/Glyph.valaindex 004dd16..c971650 100644--- a/libbirdfont/Glyph.vala+++ b/libbirdfont/Glyph.vala@@ -1336,64 +1336,78 @@ public class Glyph : FontDisplay { 	} 	 	public void draw_path (Context cr) {-		double left, baseline;-		Font font = BirdFont.get_current_font ();-		-		baseline = font.base_line;-		left = get_line ("left").pos;-		-		if (!is_open ()) {-			cr.save ();-			cr.set_source_rgba (0, 0, 0, 1);-			-			Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () - baseline);-			-			cr.restore ();-		}- 		if (is_open () && Path.fill_open_path) {+			cr.save ();+			cr.new_path (); 			foreach (unowned Path p in path_list) {-				cr.save ();-				cr.set_source_rgba (Path.fill_color_r, Path.fill_color_g, Path.fill_color_b, Path.fill_color_a);-				Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () - baseline);-				cr.restore ();+				if (p.stroke > 0) {+					draw_path_list (StrokeTool.get_stroke (p, p.stroke), cr, get_path_fill_color ());+				}++				p.draw_path (cr, get_path_fill_color ()); 			}+			cr.fill ();+			cr.restore (); 		} 						 		if (is_open ()) {+			cr.save (); 			foreach (unowned Path p in path_list) {-				p.draw_outline (cr, allocation, view_zoom);-				p.draw_edit_points (cr, allocation, view_zoom);	- 				if (p.stroke > 0) {			 					draw_outline_for_paths (StrokeTool.get_stroke (p, p.stroke), cr); 				}++				p.draw_outline (cr);+				p.draw_edit_points (cr);	 			}+			cr.restore (); 		}  		if (!is_open ()) {+			// This was good for testing but it is way too slow:+			// Svg.draw_svg_path (cr, get_svg_data (), Glyph.xc () + left, Glyph.yc () - baseline);+			+			cr.save ();+			cr.new_path ();+			foreach (unowned Path p in path_list) {+				if (p.stroke == 0) {+					p.draw_path (cr, Color.black ());+				} else {+					draw_path_list (StrokeTool.get_stroke (p, p.stroke), cr, Color.black ());+				}+			}+			cr.fill ();+			cr.restore ();+			 			foreach (unowned Path p in active_paths) {+				cr.save (); 				if (p.stroke == 0) {-					p.fill_path (cr, allocation, view_zoom);+					p.draw_path (cr); 				} else {-					fill_paths (StrokeTool.get_stroke (p, p.stroke), cr);+					draw_path_list (StrokeTool.get_stroke (p, p.stroke), cr); 				}+				cr.fill ();+				cr.restore (); 			} 		} 	} 	+	private Color get_path_fill_color () {+		return new Color (Path.fill_color_r, Path.fill_color_g, Path.fill_color_b, Path.fill_color_a);+	}+	 	private void draw_outline_for_paths (PathList pl, Context cr) {-		foreach (Path p in pl.paths) {-			p.draw_outline (cr, allocation, view_zoom);+		foreach (Path p in pl.paths) {			+			p.draw_outline (cr); 		} 	}  	-	private void fill_paths (PathList pl, Context cr) {+	private void draw_path_list (PathList pl, Context cr, Color? c = null) { 		foreach (Path p in pl.paths) {-			p.fill_path (cr, allocation, view_zoom);+			p.draw_path (cr, c); 		}-	} -	+	}+		 	private void draw_zoom_area(Context cr) { 		cr.save (); 		cr.set_line_width (2.0);@@ -1443,7 +1457,7 @@ public class Glyph : FontDisplay {  		if (unlikely (Preferences.draw_boundaries)) { 			foreach (unowned Path p in path_list) {-				p.draw_boundaries (cr, allocation, view_zoom);+				p.draw_boundaries (cr); 			} 		} 		diff --git a/libbirdfont/GlyphRange.vala b/libbirdfont/GlyphRange.valaindex 2f7f717..dcf46f7 100644--- a/libbirdfont/GlyphRange.vala+++ b/libbirdfont/GlyphRange.vala@@ -183,8 +183,29 @@ public class GlyphRange { 	} 	 	public static string serialize (string s) {+		+		if (s == "space") {+			return s;+		}++		if (s == "divis") {+			return s;+		}++		if (s == "null") {+			return s;+		}++		if (s == "quote") {+			return s;+		}++		if (s == "ampersand") {+			return s;+		}+		 		if (s.char_count () > 1) {-			warning ("Expecting a single glyph");+			warning (@"Expecting a single glyph ($s)"); 			return s; 		} 		diff --git a/libbirdfont/Path.vala b/libbirdfont/Path.valaindex 6bf5bc2..a3a9668 100644--- a/libbirdfont/Path.vala+++ b/libbirdfont/Path.vala@@ -169,7 +169,7 @@ public class Path { 		stroke = width;	 	} -	public void draw_boundaries  (Context cr, WidgetAllocation allocation, double view_zoom) {+	public void draw_boundaries  (Context cr) { 		double x = Glyph.reverse_path_coordinate_x (xmin);  		double y = Glyph.reverse_path_coordinate_y (ymin); 		double x2 = Glyph.reverse_path_coordinate_x (xmax);@@ -185,7 +185,7 @@ public class Path { 		cr.restore (); 	} -	public void draw_outline (Context cr, WidgetAllocation allocation, double view_zoom) {+	public void draw_outline (Context cr) { 		unowned List<EditPoint> ep = points; 		 		unowned EditPoint? n = null;@@ -218,7 +218,7 @@ public class Path { 		cr.stroke (); 	} 	-	public void draw_edit_points (Context cr, WidgetAllocation allocation, double view_zoom) {+	public void draw_edit_points (Context cr) { 		unowned List<EditPoint> ep = points; 		 		if (is_editable ()) {@@ -236,14 +236,17 @@ public class Path { 		} 	} -	public void fill_path (Context cr, WidgetAllocation allocation, double view_zoom) {+	/** Add all control points for a path to the cairo context.+	 * Call Context.new_path (); before this method and Context.fill ()+	 * to show the path.+	 */+	public void draw_path (Context cr, Color? color = null) { 		unowned List<EditPoint> ep = points;-		 		unowned EditPoint? n = null; 		unowned EditPoint en; 		unowned EditPoint em;-		cr.new_path ();-					+		Color c;+		 		// draw lines 		foreach (EditPoint e in ep) { 			if (n != null) {@@ -263,14 +266,17 @@ public class Path {  		// fill path 		cr.close_path ();-			-		if (is_clockwise ()) {-			cr.set_source_rgba (80/255.0, 95/255.0, 137/255.0, 0.5);+		+		if (color != null) {+			c = (!) color;+			cr.set_source_rgba (c.r, c.g, c.b, c.a); 		} else {-			cr.set_source_rgba (144/255.0, 145/255.0, 236/255.0, 0.5);+			if (is_clockwise ()) {+				cr.set_source_rgba (80/255.0, 95/255.0, 137/255.0, 0.5);+			} else {+				cr.set_source_rgba (144/255.0, 145/255.0, 236/255.0, 0.5);+			} 		}-		-		cr.fill (); 	}  	private void draw_next (EditPoint e, EditPoint en, Context cr) {@@ -752,7 +758,7 @@ public class Path { 			Glyph.path_coordinate_x (y2)); 	} 	-	private static double get_length_from (EditPoint a, EditPoint b) {+	public static double get_length_from (EditPoint a, EditPoint b) { 		double x, y; 		 		x = Math.fabs (a.x - a.get_right_handle ().x ());diff --git a/libbirdfont/StrokeTool.vala b/libbirdfont/StrokeTool.valaindex c0b4099..f785db7 100644--- a/libbirdfont/StrokeTool.vala+++ b/libbirdfont/StrokeTool.vala@@ -58,8 +58,10 @@ public class StrokeTool : Tool { 			outline.close (); 			paths.add (outline); 		} else if (!p.is_open () && !p.is_filled ()) {+			 			outline = create_stroke (p, thickness); 			counter = create_stroke (p, -1 * thickness);+			 			paths.add (outline); 			paths.add (counter); 			@@ -91,7 +93,7 @@ public class StrokeTool : Tool { 			warning ("Can not create stroke."); 			paths.add (p); 		}-		+ 		return paths; 	} 	@@ -170,11 +172,11 @@ public class StrokeTool : Tool { 		Path new_path; 		Path stroked; 		-		new_path = tangents (p);+		new_path = add_tangent_points (p); 		 		if (new_path.points.length () >= 2) { 			stroked = change_stroke_width (new_path, thickness);-+			 			if (!p.is_open ()) { 				stroked.reverse (); 				stroked.close ();@@ -188,14 +190,6 @@ public class StrokeTool : Tool { 		return stroked; 	} -	static Path tangents (Path p) {-		Path pn = p;-		for (int i = 0; i < 3; i++) {-			pn = add_tangent_points (pn);-		}-		return pn;-	}- 	static Path add_tangent_points (Path p) { 		Path path = p.copy (); 		int steps = 2;@@ -206,14 +200,14 @@ public class StrokeTool : Tool { 		 		path.all_segments ((start, stop) => { 			EditPoint? prev = null;+			double length = Path.get_length_from (start, stop); 			-			if (start.type == PointType.DOUBLE_CURVE) {-				steps = 1;-			} else {-				steps = 2;-			}-			-			Path.all_of (start, stop, (x, y, step) => {+			steps = (start.type == PointType.DOUBLE_CURVE) ?+				(int) (length / 10) : +				(int) (length / 5);++			if (steps > 1) {+				Path.all_of (start, stop, (x, y, step) => { 					EditPoint ep = new EditPoint ();  					if (0 < step < 1) {@@ -251,10 +245,12 @@ public class StrokeTool : Tool { 					} 					 					return true;-				}, steps);-				-				return true;-			});+				}, steps);				+			}+			+			return true;+		});+	  		while (new_points.length () > 0) { 			nep = new_points.first ().data;diff --git a/libbirdfont/Test.vala b/libbirdfont/Test.valaindex 2e27748..7fcfdab 100644--- a/libbirdfont/Test.vala+++ b/libbirdfont/Test.vala@@ -42,6 +42,11 @@ class Test : Object { 	public bool is_benchmark () { 		return benchmark; 	}+	+	public static void print_time (string mess, double start_time) {+		double stop_time = GLib.get_real_time ();+		print (@"$mess $((stop_time - start_time) / 1000000.0)\n");+	} }  }

Contact

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