This patch solves the issue of PCB eating my system's ram when zooming
in.. turns out it was only happening when I had a background image
(mechanical CAD drawing) loaded.

The attached patch stops PCB trying to keep a scaled copy of the entire
background image, but instead only causes it to cache the right size to
fit on the screen.

This does now stop caching of the whole image at a particular zoom-level
(which would speed up panning), but I didn't notice any real hit in
performance. If there were, a more complex caching scheme could be
developed, where we store an image a bit larger than the piece we're
viewing, so small pans can be fast.

Comments?

-- 
Peter Clifton

Electrical Engineering Division,
Engineering Department,
University of Cambridge,
9, JJ Thomson Avenue,
Cambridge
CB3 0FA

Tel: +44 (0)7729 980173 - (No signal in the lab!)
? hid/gtk/.gui-output-events.c.swp
? hid/gtk/.gui-top-window.c.swp
? hid/gtk/.gui.h.swp
Index: hid/gtk/gtkhid-main.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/gtk/gtkhid-main.c,v
retrieving revision 1.56
diff -U3 -p -r1.56 gtkhid-main.c
--- hid/gtk/gtkhid-main.c	13 Apr 2008 15:29:20 -0000	1.56
+++ hid/gtk/gtkhid-main.c	30 Apr 2008 00:44:40 -0000
@@ -474,40 +474,68 @@ ghid_invalidate_lr (int left, int right,
 static void
 ghid_draw_bg_image(void)
 {
-	static GdkPixbuf	*pixbuf;
-	GdkInterpType	interp_type;
-	gint	x, y, w, h, w_src, h_src;
-	static gint	w_scaled, h_scaled;
-
-	if (!ghidgui->bg_pixbuf)
-		return;
-
-	w = PCB->MaxWidth / gport->zoom;
-	h = PCB->MaxHeight / gport->zoom;
-	x = gport->view_x0 / gport->zoom;
-	y = gport->view_y0 / gport->zoom;
-
-	if (w_scaled != w || h_scaled != h)
-		{
-		if (pixbuf)
-			g_object_unref(G_OBJECT(pixbuf));
-
-		w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf);
-		h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf);
-		if (w > w_src && h > h_src)
-			interp_type = GDK_INTERP_NEAREST;
-		else
-			interp_type = GDK_INTERP_BILINEAR;
-
-		pixbuf = gdk_pixbuf_scale_simple(ghidgui->bg_pixbuf, w, h, interp_type);
-		w_scaled = w;
-		h_scaled = h;
-		}
-	if (pixbuf)
-		gdk_pixbuf_render_to_drawable(pixbuf, gport->drawable, gport->bg_gc,
-            x, y, 0, 0,
-            w - x, h - y, GDK_RGB_DITHER_NORMAL, 0, 0);
-	}
+  static GdkPixbuf *pixbuf = NULL;
+  static gint vw_scaled, vh_scaled, x_cached, y_cached;
+  GdkInterpType interp_type;
+  gint x, y, vw, vh, w, h, w_src, h_src;
+  int bits_per_sample;
+  gboolean has_alpha;
+
+  if (!ghidgui->bg_pixbuf)
+    return;
+
+  w = PCB->MaxWidth / gport->zoom;
+  h = PCB->MaxHeight / gport->zoom;
+  x = gport->view_x0 / gport->zoom;
+  y = gport->view_y0 / gport->zoom;
+  vw = gport->view_width / gport->zoom;
+  vh = gport->view_height / gport->zoom;
+
+  if (pixbuf == NULL || vw_scaled != vw || vh_scaled != vh)
+    {
+      if (pixbuf != NULL)
+        g_object_unref(G_OBJECT(pixbuf));
+
+      bits_per_sample = gdk_pixbuf_get_bits_per_sample(ghidgui->bg_pixbuf);
+      has_alpha = gdk_pixbuf_get_has_alpha (ghidgui->bg_pixbuf);
+      pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+                              has_alpha,
+                              bits_per_sample,
+                              vw, vh);
+    }
+
+  if (pixbuf == NULL)
+    return;
+
+  if (vw_scaled != vw || vh_scaled != vh ||
+       x_cached != x  ||  y_cached != y)
+    {
+      w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf);
+      h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf);
+
+      if (w > w_src && h > h_src)
+        interp_type = GDK_INTERP_NEAREST;
+      else
+        interp_type = GDK_INTERP_BILINEAR;
+
+      gdk_pixbuf_scale(ghidgui->bg_pixbuf, pixbuf,
+                       0, 0, vw, vh,
+                       (double) -x,
+                       (double) -y,
+                       (double) w / w_src,
+                       (double) h / h_src,
+                       interp_type);
+
+      x_cached = x;
+      y_cached = y;
+      vw_scaled = vw;
+      vh_scaled = vh;
+    }
+
+  if (pixbuf != NULL)
+    gdk_draw_pixbuf(gport->drawable, gport->bg_gc, pixbuf,
+                    0, 0, 0, 0, vw, vh, GDK_RGB_DITHER_NORMAL, 0, 0);
+}
 
 void
 ghid_invalidate_all ()

_______________________________________________
geda-dev mailing list
[email protected]
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev

Reply via email to