[ease] [general] Added thumbnail-specific Cairo rendering.



commit 60c2cdd4ba3ee7bbb82a11e1660c6095a5815b23
Author: Nate Stedman <natesm gmail com>
Date:   Mon Aug 23 08:41:52 2010 -0400

    [general] Added thumbnail-specific Cairo rendering.
    
    Cairo rendering specific to thumbnails, which allows
    subclasses of Element to optimize and cache data.
    
    Cairo redraw can happen quite frequently when dragging
    elements around, and reloading large image files
    constantly to Cairo render is a Bad Thing. ImageElement
    implements the new thumbnail methods, caching a small
    version of the image.

 ease-core/ease-element.vala       |   24 ++++++++++++++++++++++++
 ease-core/ease-image-element.vala |   37 ++++++++++++++++++++++++++++++++++++-
 ease-core/ease-slide.vala         |   22 ++++++++++++++++++++++
 ease/ease-editor-window.vala      |    7 +++++++
 ease/ease-slide-button-panel.vala |    2 +-
 5 files changed, 90 insertions(+), 2 deletions(-)
---
diff --git a/ease-core/ease-element.vala b/ease-core/ease-element.vala
index f22a633..05ca7f3 100644
--- a/ease-core/ease-element.vala
+++ b/ease-core/ease-element.vala
@@ -176,6 +176,30 @@ public abstract class Ease.Element : GLib.Object, UndoSource
 	public abstract void cairo_render(Cairo.Context context) throws Error;
 	
 	/**
+	 * Renders this Element to a thumbnail-sized CairoContext. The ability to
+	 * override this method in subclasses allows for optimizations to be
+	 * performed, preventing slowdown.
+	 *
+	 * Especially when dragging Elements around, thumbnails are rapidly redrawn.
+	 * If an Element subclass uses any potentially large media files, it is a
+	 * good idea to override this method, cache a low resolution version of the
+	 * file, and draw with that.
+	 *
+	 * If not overriden, this method will simply call { link cairo_render}.
+	 *
+	 * @param context The context to render to.
+	 */
+	public virtual void cairo_render_small(Cairo.Context context) throws Error
+	{
+		cairo_render(context);
+	}
+	
+	/**
+	 * Instructs subclasses to free any cached data for Cairo rendering.
+	 */
+	public virtual void cairo_free_cache() {}
+	
+	/**
 	 * Returns a ClutterActor for use in presentations and the editor.
 	 *
 	 * @param c The context of the actor.
diff --git a/ease-core/ease-image-element.vala b/ease-core/ease-image-element.vala
index 3bad007..b661bc8 100644
--- a/ease-core/ease-image-element.vala
+++ b/ease-core/ease-image-element.vala
@@ -22,6 +22,21 @@
 public class Ease.ImageElement : MediaElement
 {
 	private const string UI_FILE_PATH = "inspector-element-image.ui";
+	private const int CACHE_SIZE = 100;
+	
+	private Gdk.Pixbuf small_cache
+	{
+		get
+		{
+			if (small_cache_l != null) return small_cache_l;
+			var filename = Path.build_path("/", parent.parent.path, filename);
+			return small_cache_l = new Gdk.Pixbuf.from_file_at_size(filename,
+			                                                        CACHE_SIZE,
+			                                                        CACHE_SIZE);
+		}
+		set { small_cache_l = value; }
+	}
+	private Gdk.Pixbuf small_cache_l;
 	
 	/**
 	 * Create a new element.
@@ -31,6 +46,12 @@ public class Ease.ImageElement : MediaElement
 		signals();
 	}
 	
+	public override void signals()
+	{
+		base.signals();
+		notify["filename"].connect(() => small_cache_l = null);
+	}
+	
 	internal ImageElement.from_json(Json.Object obj)
 	{
 		base.from_json(obj);
@@ -41,6 +62,11 @@ public class Ease.ImageElement : MediaElement
 		return new ImageActor(this, c);
 	}
 	
+	public override void cairo_free_cache()
+	{
+		small_cache = null;
+	}
+	
 	public override Gtk.Widget inspector_widget()
 	{
 		var builder = new Gtk.Builder();
@@ -120,8 +146,17 @@ public class Ease.ImageElement : MediaElement
 		                                               false);
 		
 		Gdk.cairo_set_source_pixbuf(context, pixbuf, 0, 0);
-		
 		context.rectangle(0, 0, width, height);
 		context.fill();
 	}
+	
+	public override void cairo_render_small(Cairo.Context context) throws Error
+	{
+		var scaled = small_cache.scale_simple((int)width, (int)height,
+		                                      Gdk.InterpType.NEAREST);
+		Gdk.cairo_set_source_pixbuf(context, scaled, 0, 0);
+		context.rectangle(0, 0, width, height);
+		context.scale(40, 40);
+		context.fill();
+	}
 }
diff --git a/ease-core/ease-slide.vala b/ease-core/ease-slide.vala
index d637641..bba1a07 100644
--- a/ease-core/ease-slide.vala
+++ b/ease-core/ease-slide.vala
@@ -544,6 +544,28 @@ public class Ease.Slide : GLib.Object, UndoSource
 		cairo_render_sized(context, parent.width, parent.height);
 	}
 	
+	/**
+	 * Draws the Slide to a thumbnail-sized Cairo.Context. Will call
+	 * { link Element.cairo_render_small} instead of
+	 * { link Element.cairo_render}.
+	 *
+	 * @param context The Cairo.Context to draw to.
+	 */
+	public void cairo_render_small(Cairo.Context context)
+	{
+		context.save();
+		cairo_render_background(context, parent.width, parent.height);
+		context.restore();
+		
+		foreach (var e in elements)
+		{
+			context.save();
+			context.translate(e.x, e.y);
+			e.cairo_render_small(context);
+			context.restore();
+		}
+	}
+	
 	/** 
 	 * Draws the { link Slide} to a Cairo.Context at a specified size.
 	 *
diff --git a/ease/ease-editor-window.vala b/ease/ease-editor-window.vala
index cebf268..97e52b4 100644
--- a/ease/ease-editor-window.vala
+++ b/ease/ease-editor-window.vala
@@ -281,6 +281,13 @@ internal class Ease.EditorWindow : Gtk.Window
 	 */
 	internal void set_slide(int index)
 	{
+		// clear any cairo rendering caches that the current slide has
+		foreach (var element in slide)
+		{
+			element.cairo_free_cache();
+		}
+		
+		// get the new slide
 		slide = document.get_slide(index);
 		
 		// update ui elements for this new slide
diff --git a/ease/ease-slide-button-panel.vala b/ease/ease-slide-button-panel.vala
index f58bd45..1024293 100644
--- a/ease/ease-slide-button-panel.vala
+++ b/ease/ease-slide-button-panel.vala
@@ -188,7 +188,7 @@ internal class Ease.SlideButtonPanel : Gtk.ScrolledWindow
 		
 		try
 		{
-			slide.cairo_render(context);
+			slide.cairo_render_small(context);
 		}
 		catch (GLib.Error e)
 		{



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]