Clone in a terminal:
Commit 9ae0f4c
Johan Mattsson - 2015-12-08T18:59:19+00:00
9ae0f4c71ab0aaface5a7c208b8f2604c471a66bjohan.mattsson.m@gmail.com

Speed optimizations for background images This code splits big images in smaller parts and renders only the relevant sections.

Changed files (4)

Diff

diff --git a/libbirdfont/BackgroundImage.vala b/libbirdfont/BackgroundImage.valaindex 5c48946..536aec4 100644--- a/libbirdfont/BackgroundImage.vala+++ b/libbirdfont/BackgroundImage.vala@@ -47,6 +47,8 @@ public class BackgroundImage { 	 	public signal void updated (); +	private ScaledBackgrounds? scaled = null;+ 	public double img_offset_x { 		get { return img_x + Glyph.xc (); } 		set { img_x = value - Glyph.xc (); }@@ -114,6 +116,14 @@ public class BackgroundImage { 		return bg;		 	} +	public ScaledBackgrounds get_scaled_backgrounds () {+		if (scaled == null) {+			scaled = new ScaledBackgrounds ((ImageSurface) get_rotated_image ());+		}+		+		return (!) scaled;+ 	}+ 	public void add_selection (BackgroundSelection bs) { 		selections.add (bs); 	}@@ -160,7 +170,7 @@ public class BackgroundImage { 		 		if (background_image == null) { 			background_image = new ImageSurface.from_png (path);-			original_image = new ImageSurface.from_png (path);+			original_image = new ImageSurface.from_png (path);			 		} 		 		return (!) original_image;@@ -387,7 +397,9 @@ public class BackgroundImage { 		img_offset_y = g.get_line ("top").pos;		 	} -	public void draw (Context cr, WidgetAllocation allocation, double view_offset_x, double view_offset_y, double view_zoom) {+	public void draw (Context cr, WidgetAllocation allocation,+			double view_offset_x, double view_offset_y, double view_zoom) {+				 		double scale_x, scale_y; 		double image_scale_x, image_scale_y; 		ImageSurface s;@@ -417,29 +429,50 @@ public class BackgroundImage { 			image_scale_y = img_scale_y * ((double) rotated_image.get_height () / s.get_height ());			 		} 		-		st = new Surface.similar (s, s.get_content (), allocation.width, allocation.height);-		ct = new Context (st);-		ct.save ();+		// FIXME: rotated and contrast+		ScaledBackgrounds backgrounds = get_scaled_backgrounds ();+		ScaledBackground scaled = backgrounds.get_image (view_zoom * img_scale_x); // FIXME: y -		ct.set_source_rgba (1, 1, 1, 1);-		ct.rectangle (0, 0, allocation.width, allocation.height);-		ct.fill ();+		ScaledBackgroundPart part;+		double part_scale_x = view_zoom * image_scale_x;+		double part_scale_y = view_zoom * image_scale_y;+		+		double part_offset_x = img_offset_x - view_offset_x;+		part_offset_x *= view_zoom;+		part_offset_x = -part_offset_x;++		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);  -		// scale both canvas and image at the same time 		scale_x = view_zoom * image_scale_x; 		scale_y = view_zoom * image_scale_y; 		-		ct.scale (scale_x, scale_y);-		ct.translate (-view_offset_x / image_scale_x, -view_offset_y / image_scale_y);+		scale_x /= part.get_scale ();+		scale_y /= part.get_scale (); 		-		ct.set_source_surface (s, img_offset_x / image_scale_x, img_offset_y / image_scale_y);+		ImageSurface scaled_image;+		Context scaled_context;+		scaled_image = new ImageSurface (Format.ARGB32, allocation.width, allocation.height);+		scaled_context = new Context (scaled_image); -		ct.paint ();-		ct.restore ();+		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 ();+ 		// add it 		cr.save ();-		cr.set_source_surface (st, 0, 0);+		cr.set_source_surface (scaled_image, 0, 0); 		cr.paint (); 		cr.restore (); 	}diff --git a/libbirdfont/ScaledBackgroundPart.vala b/libbirdfont/ScaledBackgroundPart.valanew file mode 100644index 0000000..6396d5b--- /dev/null+++ b/libbirdfont/ScaledBackgroundPart.vala@@ -0,0 +1,43 @@+/*+	Copyright (C) 2015 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.+*/++using Cairo;+using Math;+using Gee;++namespace BirdFont {++public class ScaledBackgroundPart : GLib.Object {+	public double scale;+	public int offset_x;+	public int offset_y;+	public ImageSurface image;+	+	public ScaledBackgroundPart (ImageSurface image, double scale, int offset_x, int offset_y) {+		this.image = image;+		this.scale = scale;+		this.offset_x = offset_x;+		this.offset_y = offset_y;+	}++	public double get_scale () {+		return scale;+	}+	+	public ImageSurface get_image () {+		return image;+	}+}++}diff --git a/libbirdfont/ScaledBackgrounds.vala b/libbirdfont/ScaledBackgrounds.valanew file mode 100644index 0000000..f5d33a9--- /dev/null+++ b/libbirdfont/ScaledBackgrounds.vala@@ -0,0 +1,64 @@+/*+	Copyright (C) 2015 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.+*/++using Cairo;+using Math;+using Gee;++namespace BirdFont {++public class ScaledBackgrounds : GLib.Object {+	ImageSurface original;+	ArrayList<ScaledBackground> scaled;+	+	public ScaledBackgrounds (ImageSurface original) {+		this.original = original;+		scaled = new ArrayList<ScaledBackground> ();++		ScaledBackground image = scale (0.01);+		scaled.add (image);+					+		for (double scale_factor = 0.1; scale_factor <= 1; scale_factor += 0.1) {+			image = scale (scale_factor);+			scaled.add (image);+		}+	}++	public ScaledBackground get_image (double scale) {+		foreach (ScaledBackground image in scaled) {+			if (image.get_scale () < scale) {+				continue;+			}+			+			return image;+		}++		return scaled.get (scaled.size - 1);+	}++	private ScaledBackground scale (double scale_factor) {+		ImageSurface scaled_image;+		int width = (int) (scale_factor * original.get_width ());+		int height = (int) (scale_factor * original.get_height ());+		scaled_image = new ImageSurface (Format.ARGB32, width, height);+		Context context = new Context (scaled_image);+		context.scale (scale_factor, scale_factor);+		context.set_source_surface (original, 0, 0);+		context.paint ();+		+		return new ScaledBackground (scaled_image, scale_factor);+	}+}++}diff --git a/libbirdfont/ScaledImage.vala b/libbirdfont/ScaledImage.valanew file mode 100644index 0000000..9f2bd6d--- /dev/null+++ b/libbirdfont/ScaledImage.vala@@ -0,0 +1,128 @@+/*+	Copyright (C) 2015 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.+*/++using Cairo;+using Math;+using Gee;++namespace BirdFont {++public class ScaledBackground : GLib.Object {+	ImageSurface image;+	double scale;+	ArrayList<ImageSurface> parts;+	int size;+	int part_width;+	int part_height;+	+	public ScaledBackground (ImageSurface image, double scale) {+		this.image = image;+		this.scale = scale;+		parts = new ArrayList<ImageSurface> ();+		+		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);+				Context context = new Context (next_part);+				context.set_source_surface (image, -x * part_width, -y * part_width);+				context.paint ();+				parts.add (next_part);+			}+		}+	}+	+	public double get_scale () {+		return scale;+	}+	+	public ImageSurface get_image () {+		return image;+	}+	+	ImageSurface? get_part_at (int x, int y) {+		int index = y * size + x;++		if (x >= size || x < 0) {+			return null;+		}++		if (y >= size || y < 0) {+			return null;+		}+						+		if (unlikely (!(0 <= index < parts.size))) {+			warning (@"No part at index: $x, $y");+			return null;+		}+		+		return parts.get (index);+	}+	+	public ScaledBackgroundPart get_part (double offset_x, double offset_y, +			int width, int height) {+				+		double image_width = part_width * size;+		double image_height = part_height * size;+		+		int start_x = (int) ((offset_x / image_width) * size) - 1;+		int start_y = (int) ((offset_y / image_height) * size) - 1;+		int stop_x = (int) (((offset_x + width) / image_width) * size) + 2;+		int stop_y = (int) (((offset_y + height) / image_height) * size) + 2;++		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);+		Context context = new Context (image);++		int start_offset_x = start_x * part_width;+		int start_offset_y = start_y * part_height;+		+		if (start_offset_x > 0) {+			start_x = -1;+			start_offset_x = start_x * part_width;+		}++		if (start_offset_y > 0) {+			start_y = -1;+			start_offset_y = start_y * part_height;+		}+				+		for (int y = start_y; y < stop_y; y++) {+			for (int x = start_x; x < stop_x; x++) {+				ImageSurface? part = get_part_at (x, y);+				+				if (part != null) {+					context.save ();+					+					context.set_source_surface ((!) part,+						(x - start_x) * part_width,+						(y - start_y) * part_height);+						+					context.paint ();+					context.restore ();+				}+			}+		}+		+		return new ScaledBackgroundPart (image, scale,+				start_offset_x, start_offset_y);+	}+}++}

Contact

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