Clone in a terminal:
Commit 815d47d
Johan Mattsson - 2015-12-09T21:22:35+00:00
815d47d945dd46ef3eba96ce0db7882715563ea5johan.mattsson.m@gmail.com

Speed optimization for rotated background images

Changed files (4)

Diff

diff --git a/libbirdfont/BackgroundImage.vala b/libbirdfont/BackgroundImage.valaindex 2cc5d04..2f01aaf 100644--- a/libbirdfont/BackgroundImage.vala+++ b/libbirdfont/BackgroundImage.vala@@ -29,19 +29,7 @@ public class BackgroundImage { 	public double img_scale_x = 1; 	public double img_scale_y = 1; 	-	public double img_rotation {-		get {-			return img_rotation_angle;-		}-		-		set {-			scaled = null;-			scaled_contrast = null;-			img_rotation_angle = value;-		}-	}-	-	private double img_rotation_angle = 0;+	public double img_rotation = 0; 	 	private int size = -1; @@ -60,7 +48,7 @@ public class BackgroundImage { 	public signal void updated ();  	private ScaledBackgrounds? scaled = null;-	private ScaledBackgrounds? scaled_contrast = null;+	private ImageSurface? contrast_image = null;  	public double img_offset_x { 		get { return img_x + Glyph.xc (); }@@ -366,11 +354,47 @@ public class BackgroundImage { 		 		path = (!) png_image.get_path (); 	}++	private ScaledBackgrounds get_image () {+		return get_scaled_backgrounds ();+	} 	+	public void preview_img_rotation_from_coordinate (double x, double y) {+		double rotation;+		ScaledBackgrounds backgounds;+		+		if (get_img_rotation_from_coordinate (x, y, out rotation)) {+			img_rotation = rotation;+			backgounds = get_image ();+			double view_zoom = MainWindow.get_current_glyph ().view_zoom;+			ImageSurface rotated;+			+			img_rotation = rotation;+			+			if (!high_contrast) {+				rotated = rotate ((ImageSurface) get_padded_image ());+				scaled = new ScaledBackgrounds.single_size (rotated, 1);+			} else {+				contrast_image = null;+			}+		}+	}+ 	public void set_img_rotation_from_coordinate (double x, double y) {+		double rotation;+		if (get_img_rotation_from_coordinate (x, y, out rotation)) {+			img_rotation = rotation;+			scaled = null;+			contrast_image = null;+		}+	}+	+	public bool get_img_rotation_from_coordinate (double x, double y, out double rotation) { 		double bcx, bcy; 		double a, b, c, length; +		rotation = 0;+		 		bcx = img_middle_x; 		bcy = img_middle_y; @@ -379,7 +403,7 @@ public class BackgroundImage { 		c = a * a + b * b; 		 		if (c == 0) {-			return;+			return false; 		} 		 		length = sqrt (fabs (c));	@@ -388,9 +412,8 @@ public class BackgroundImage { 			length = -length; 		} 	-		img_rotation =  (y > bcy) ? acos (a / length) + PI : -acos (a / length) + PI;-		-		background_image = null;+		rotation = (y > bcy) ? acos (a / length) + PI : -acos (a / length) + PI;+		return true; 	} 	 	public void set_img_scale (double xs, double ys) {@@ -418,10 +441,6 @@ public class BackgroundImage { 		double image_scale_x, image_scale_y;  		ScaledBackgrounds backgrounds = get_scaled_backgrounds ();--		if (high_contrast) {-			backgrounds = get_contrast_image ();-		} 		 		if (unlikely (get_img ().status () != Cairo.Status.SUCCESS)) { 			warning (@"Background image is invalid. (\"$path\")\n");@@ -432,45 +451,73 @@ public class BackgroundImage { 		image_scale_x = img_scale_x; 		image_scale_y = img_scale_y; -		ScaledBackground scaled;-		ScaledBackgroundPart part;+		ImageSurface scaled_image;+		Context scaled_context; -		scaled = backgrounds.get_image (view_zoom * img_scale_x); // FIXME: y+		if (!high_contrast) {+			ScaledBackground scaled;+			ScaledBackgroundPart part; -		double part_offset_x = img_offset_x - view_offset_x;-		part_offset_x *= view_zoom;-		part_offset_x = -part_offset_x;+			scaled = backgrounds.get_image (view_zoom * img_scale_x); // FIXME: y -		double part_offset_y = img_offset_y - view_offset_y;-		part_offset_y *= view_zoom;-		part_offset_y = -part_offset_y;-		-		part = scaled.get_part (part_offset_x, part_offset_y, -			allocation.width, allocation.height); +			double part_offset_x = img_offset_x - view_offset_x;+			part_offset_x *= view_zoom;+			part_offset_x = -part_offset_x; -		scale_x = view_zoom * image_scale_x;-		scale_y = view_zoom * image_scale_y;-		-		scale_x /= part.get_scale ();-		scale_y /= part.get_scale ();-		-		ImageSurface scaled_image;-		Context scaled_context;-		-		scaled_image = new ImageSurface (Format.ARGB32, allocation.width, allocation.height);-		scaled_context = new Context (scaled_image);+			double part_offset_y = img_offset_y - view_offset_y;+			part_offset_y *= view_zoom;+			part_offset_y = -part_offset_y;+			+			part = scaled.get_part (part_offset_x, part_offset_y, +				(int) (allocation.width * view_zoom), (int) (allocation.height * view_zoom));  -		scaled_context.scale (scale_x, scale_y);-		-		double scaled_x = part.offset_x;-		double scaled_y = part.offset_y;-		-		scaled_x += view_zoom * (img_offset_x / scale_x - view_offset_x / scale_x);-		scaled_y += view_zoom * (img_offset_y / scale_y - view_offset_y / scale_y);-		-		scaled_context.set_source_surface (part.get_image (), scaled_x, scaled_y);-		scaled_context.paint ();+			scale_x = view_zoom * image_scale_x;+			scale_y = view_zoom * image_scale_y;+			+			scale_x /= part.get_scale ();+			scale_y /= part.get_scale ();+						+			scaled_image = new ImageSurface (Format.ARGB32, allocation.width, allocation.height);+			+			scaled_context = new Context (scaled_image); +			scaled_context.scale (scale_x, scale_y);+			+			double scaled_x = part.offset_x;+			double scaled_y = part.offset_y;+			+			scaled_x += view_zoom * (img_offset_x / scale_x - view_offset_x / scale_x);+			scaled_y += view_zoom * (img_offset_y / scale_y - view_offset_y / scale_y);+			+			scaled_context.set_source_surface (part.get_image (), scaled_x, scaled_y);+			scaled_context.paint ();+		} else {		+			ImageSurface contrast = get_contrast_image ();+			+			image_scale_x = img_scale_x * ((double) size_margin / contrast.get_width ());+			image_scale_y = img_scale_y * ((double) size_margin / contrast.get_height ());			+			+			scaled_image = new ImageSurface (Format.ARGB32, allocation.width, allocation.height);+			Context contrast_context = new Context (scaled_image);+			contrast_context.save ();++			contrast_context.set_source_rgba (1, 1, 1, 1);+			contrast_context.rectangle (0, 0, allocation.width, allocation.height);+			contrast_context.fill ();++			// scale both canvas and image at the same time+			scale_x = view_zoom * image_scale_x;+			scale_y = view_zoom * image_scale_y;+			+			contrast_context.scale (scale_x, scale_y);+			contrast_context.translate (-view_offset_x / image_scale_x, -view_offset_y / image_scale_y);+			+			contrast_context.set_source_surface (contrast, img_offset_x / image_scale_x, img_offset_y / image_scale_y);++			contrast_context.paint ();+			contrast_context.restore ();+		}+		 		// add it 		cr.save ();		 		cr.set_source_surface (scaled_image, 0, 0);@@ -521,7 +568,11 @@ public class BackgroundImage { 		return sg; 	} 	-	private ImageSurface rotate (ImageSurface padded_image) {				+	private ImageSurface rotate (ImageSurface padded_image) {+		return rotate_image (padded_image, img_rotation);+	}+	+	public static ImageSurface rotate_image (ImageSurface padded_image, double angle) { 		ImageSurface s; 		Context c; 		@@ -533,12 +584,8 @@ public class BackgroundImage { 	 		c.save (); -		Theme.color (c, "Background 1");-		c.rectangle (0, 0, w, h);-		c.fill ();-			 		c.translate (w * 0.5, h * 0.5);-		c.rotate (img_rotation);+		c.rotate (angle); 		c.translate (-w * 0.5, -h * 0.5); 		 		c.set_source_surface (padded_image, 0, 0);@@ -709,21 +756,20 @@ public class BackgroundImage {  	public void update_background () { 		background_image = null;-		scaled_contrast = null;+		contrast_image = null; 		 		GlyphCanvas.redraw (); 		updated (); 	} -	ScaledBackgrounds get_contrast_image () {-		if (scaled_contrast == null) {-			ImageSurface image = get_contrast_image_surface ();-			scaled_contrast = new ScaledBackgrounds (image);+	ImageSurface get_contrast_image () {+		if (contrast_image == null) {+			contrast_image  = get_contrast_image_surface (); 		} 		-		return (!) scaled_contrast;+		return (!) contrast_image; 	}-	+ 	ImageSurface get_contrast_image_surface () { 		ImageSurface s; 		Context c;@@ -748,6 +794,7 @@ public class BackgroundImage {  		s = new ImageSurface (Format.RGB24, scaled_width, scaled_width); 		sg = (ImageSurface) get_padded_image ();	+		sg = rotate (sg); 		c = new Context (s); 	 		c.save ();@@ -833,7 +880,7 @@ public class BackgroundImage { 			return pl; 		} -		img = get_contrast_image ().get_image (1).get_image ();+		img = get_contrast_image ();  		w = img.get_width(); 		h = img.get_height();@@ -1214,7 +1261,7 @@ public class BackgroundImage { 		ImageSurface img; 		double simplification = DrawingTools.auto_trace_simplify.get_value (); -		img = get_contrast_image ().get_image (1).get_image ();+		img = get_contrast_image ();  		image_scale_x = ((double) size_margin / img.get_width ()); 		image_scale_y = ((double) size_margin / img.get_height ());diff --git a/libbirdfont/BackgroundTool.vala b/libbirdfont/BackgroundTool.valaindex 2252699..b7376c9 100644--- a/libbirdfont/BackgroundTool.vala+++ b/libbirdfont/BackgroundTool.vala@@ -21,6 +21,9 @@ public class BackgroundTool : Tool { 	double begin_x = 0; 	double begin_y = 0; +	int last_x;+	int last_y;+	 	public double img_offset_x = 0; 	public double img_offset_y = 0; @@ -78,20 +81,33 @@ public class BackgroundTool : Tool { 			img_height = background.get_img ().get_height () * background.img_scale_y; 			 			move_bg = true;+			+			last_x = x;+			last_y = y; 		});  		release_action.connect((self, b, x, y) => { 			Glyph g = MainWindow.get_current_glyph (); 			BackgroundImage? bg = g.get_background_image ();+			double coordinate_x, coordinate_y; 			 			if (bg == null) { 				return; 			} 			-			img_offset_x = ((!)bg).img_offset_x;-			img_offset_y = ((!)bg).img_offset_y;+			BackgroundImage background = (!) bg;++			coordinate_x = Glyph.path_coordinate_x (x);+			coordinate_y = Glyph.path_coordinate_y (y);+		+			if (background.selected_handle == 2) {+				background.set_img_rotation_from_coordinate (coordinate_x, coordinate_y);+			}+						+			img_offset_x = background.img_offset_x;+			img_offset_y = background.img_offset_y; 			-			((!)bg).handler_release (x, y);+			background.handler_release (x, y); 			 			move_bg = false; 		});@@ -135,7 +151,7 @@ public class BackgroundTool : Tool { 		}); 	} 		-	void move (double x, double y) {+	void move (int x, int y) { 		Glyph g = MainWindow.get_current_glyph (); 		BackgroundImage? background_image = g.get_background_image (); 		BackgroundImage bg = (!) background_image;@@ -156,11 +172,11 @@ public class BackgroundTool : Tool { 	 		dx *= PenTool.precision; 		dy *= PenTool.precision;-		+ 		if (bg.selected_handle == 2) { 			coordinate_x = Glyph.path_coordinate_x (x); 			coordinate_y = Glyph.path_coordinate_y (y);-			bg.set_img_rotation_from_coordinate (coordinate_x, coordinate_y);+			bg.preview_img_rotation_from_coordinate (coordinate_x, coordinate_y); 		} 		 		if (bg.selected_handle == 1) {@@ -181,6 +197,9 @@ public class BackgroundTool : Tool { 		}  		GlyphCanvas.redraw ();+		+		last_x = x;+		last_y = y; 	}  	public static void load_background_image () {diff --git a/libbirdfont/ScaledBackgrounds.vala b/libbirdfont/ScaledBackgrounds.valaindex f5d33a9..5dee3f9 100644--- a/libbirdfont/ScaledBackgrounds.vala+++ b/libbirdfont/ScaledBackgrounds.vala@@ -35,6 +35,14 @@ public class ScaledBackgrounds : GLib.Object { 		} 	} +	public ScaledBackgrounds.single_size (ImageSurface original, double scale_factor) {+		this.original = original;+		scaled = new ArrayList<ScaledBackground> ();++		ScaledBackground image = scale (scale_factor);+		scaled.add (image);+	}+	 	public ScaledBackground get_image (double scale) { 		foreach (ScaledBackground image in scaled) { 			if (image.get_scale () < scale) {diff --git a/libbirdfont/ScaledImage.vala b/libbirdfont/ScaledImage.valaindex b1609d8..f8e1b09 100644--- a/libbirdfont/ScaledImage.vala+++ b/libbirdfont/ScaledImage.vala@@ -20,6 +20,7 @@ namespace BirdFont {  public class ScaledBackground : GLib.Object { 	ImageSurface image;+	ImageSurface rotated; 	ArrayList<ImageSurface> parts; 	int size; 	int part_width;@@ -28,24 +29,39 @@ public class ScaledBackground : GLib.Object { 	 	public ScaledBackground (ImageSurface image, double scale) { 		this.image = image;+		rotated = image; 		this.scale = scale;+		parts = new ArrayList<ImageSurface> ();		 		-		parts = new ArrayList<ImageSurface> ();+		create_parts ();+	}+	+	void create_parts () {+		parts.clear ();+		size = image.get_width () / 100; 		-		size = 10;+		if (size < 10) {+			size = 10;+		}+ 		part_width = image.get_width () / size; 		part_height = image.get_height () / size;-+				 		for (int y = 0; y < size; y++) { 			for (int x = 0; x < size; x++) { 				ImageSurface next_part;-				next_part = new ImageSurface (Format.RGB24, part_width, part_height);+				next_part = new ImageSurface (Format.ARGB32, part_width, part_height); 				Context context = new Context (next_part);-				context.set_source_surface (image, -x * part_width, -y * part_width);+				context.set_source_surface (rotated, -x * part_width, -y * part_width); 				context.paint (); 				parts.add (next_part); 			}-		}+		}	+	}+	+	public void rotate (double angle) {+		rotated = BackgroundImage.rotate_image (image, angle);+		create_parts (); 	} 	 	public double get_scale () {@@ -88,7 +104,9 @@ public class ScaledBackground : GLib.Object {  		int assembled_width = (int) ((size + 2) * image_width); 		int assembled_height = (int) ((size + 2) * image_height);-		image = new ImageSurface (Format.RGB24, assembled_width, assembled_height);+		+		image = new ImageSurface (Format.ARGB32, assembled_width, assembled_height);+ 		Context context = new Context (image);  		int start_offset_x = start_x * part_width;

Contact

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