[eog] Fully rely on cairo to render the image in EogScrollView



commit 919929eea1d63380f773f9c0a339a32149e592ba
Author: Claudio Saavedra <csaavedra igalia com>
Date:   Mon Aug 16 23:14:39 2010 +0300

    Fully rely on cairo to render the image in EogScrollView
    
    This is an initial patch to showcase how EogScrollView performs when
    we discard all the internal optimizations and rely on cairo to render
    the image. In general, performance is quite good, with a few caveats:
    
    - Rendering svg is broken (librsvg is not building because of the
      changes in API in GTK+ 3)
    - There is flickering in the rendering of the background for images
      with an alpha channel
    - Images bigger than 4096Ã?4096 seems to be quite slow (at least with
      an nvidia card)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=626795

 src/eog-scroll-view.c |  106 +++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 94 insertions(+), 12 deletions(-)
---
diff --git a/src/eog-scroll-view.c b/src/eog-scroll-view.c
index 784d70d..f6bfdd8 100644
--- a/src/eog-scroll-view.c
+++ b/src/eog-scroll-view.c
@@ -631,6 +631,44 @@ get_transparency_params (EogScrollView *view, int *size, guint32 *color1, guint3
 	*size = CHECK_MEDIUM;
 }
 
+
+static cairo_surface_t *
+create_background_surface (EogScrollView *view)
+{
+	int check_size;
+	guint32 check_1 = 0;
+	guint32 check_2 = 0;
+	cairo_surface_t *surface;
+
+	get_transparency_params (view, &check_size, &check_1, &check_2);
+	surface = gdk_window_create_similar_surface (gtk_widget_get_window (view->priv->display),
+						     CAIRO_CONTENT_COLOR,
+						     check_size * 2, check_size * 2);
+	cairo_t* cr = cairo_create (surface);
+	cairo_set_source_rgba (cr,
+			       ((check_1 & 0xff0000) >> 16) / 255.,
+			       ((check_1 & 0x00ff00) >> 8)  / 255.,
+			       (check_1 & 0x0000ff)         / 255.,
+			       1.);
+	cairo_rectangle (cr, 0, 0, check_size, check_size);
+	cairo_rectangle (cr, check_size, check_size, check_size, check_size);
+	cairo_fill (cr);
+
+	cairo_set_source_rgba (cr,
+			       ((check_2 & 0xff0000) >> 16) / 255.,
+			       ((check_2 & 0x00ff00) >> 8)  / 255.,
+			       (check_2 & 0x0000ff)         / 255.,
+			       1.);
+	cairo_rectangle (cr, 0, check_size, check_size, check_size);
+	cairo_rectangle (cr, check_size, 0, check_size, check_size);
+	cairo_fill (cr);
+
+	cairo_destroy (cr);
+
+	return surface;
+}
+
+#if 0
 #ifdef HAVE_RSVG
 static cairo_surface_t *
 create_background_surface (EogScrollView *view)
@@ -1068,6 +1106,7 @@ request_paint_area (EogScrollView *view, GdkRectangle *area)
 
 	priv->uta = uta_add_rect (priv->uta, r.x0, r.y0, r.x1, r.y1);
 }
+#endif
 
 
 /* =======================================
@@ -1129,10 +1168,12 @@ scroll_to (EogScrollView *view, int x, int y, gboolean change_adjustments)
 	twidth = (allocation.width + EOG_UTILE_SIZE - 1) >> EOG_UTILE_SHIFT;
 	theight = (allocation.height + EOG_UTILE_SIZE - 1) >> EOG_UTILE_SHIFT;
 
+#if 0
 	if (priv->uta)
 		g_assert (priv->idle_id != 0);
 	else
 		priv->idle_id = g_idle_add (paint_iteration_idle, view);
+#endif
 
 	priv->uta = uta_ensure_size (priv->uta, 0, 0, twidth, theight);
 
@@ -1735,18 +1776,16 @@ eog_scroll_view_focus_out_event (GtkWidget     *widget,
 	return FALSE;
 }
 
-/* Expose event handler for the drawing area.  First we process the whole dirty
- * region by drawing a non-interpolated version, which is "instantaneous", and
- * we do this synchronously.  Then, if we are set to use interpolation, we queue
- * an idle handler to handle interpolated drawing there.
- */
 static gboolean
 display_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data)
 {
 	EogScrollView *view;
-	GdkRectangle rect;
-	gint n_rects;
-	int i;
+	EogScrollViewPrivate *priv;
+	cairo_t *cr;
+	GtkAllocation allocation;
+	int scaled_width, scaled_height;
+	int xofs, yofs;
+	EogIRect r, d;
 
 	g_return_val_if_fail (GTK_IS_DRAWING_AREA (widget), FALSE);
 	g_return_val_if_fail (event != NULL, FALSE);
@@ -1754,13 +1793,56 @@ display_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data)
 
 	view = EOG_SCROLL_VIEW (data);
 
-	n_rects = cairo_region_num_rectangles (event->region);
+	priv = view->priv;
+
+	if (priv->pixbuf == NULL)
+		return TRUE;
+
+	compute_scaled_size (view, priv->zoom, &scaled_width, &scaled_height);
+
+	gtk_widget_get_allocation (GTK_WIDGET (priv->display), &allocation);
+
+	/* Compute image offsets with respect to the window */
+
+	if (scaled_width <= allocation.width)
+		xofs = (allocation.width - scaled_width) / 2;
+	else
+		xofs = -priv->xofs;
+
+	if (scaled_height <= allocation.height)
+		yofs = (allocation.height - scaled_height) / 2;
+	else
+		yofs = -priv->yofs;
+
+	eog_debug_message (DEBUG_WINDOW, "zoom %.2f, xofs: %i, yofs: %i scaled w: %i h: %i\n",
+			   priv->zoom, xofs, yofs, scaled_width, scaled_height);
+
+	cr = gdk_cairo_create (GDK_DRAWABLE (gtk_widget_get_window (GTK_WIDGET (view->priv->display))));
+	gdk_cairo_region (cr, event->region);
+	cairo_clip (cr);
+
+	/* Paint the background */
+	cairo_set_source (cr, gdk_window_get_background_pattern (gtk_widget_get_window (priv->display)));
+	cairo_rectangle (cr, 0, 0, allocation.width, allocation.height);
+	cairo_rectangle (cr, MAX (0, xofs), MAX (0, yofs),
+			 scaled_width, scaled_height);
+	cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+	cairo_fill (cr);
 
-	for (i = 0; i < n_rects; i++) {
-		cairo_region_get_rectangle (event->region, i, &rect);
-		request_paint_area (view, &rect);
+	if (gdk_pixbuf_get_has_alpha (priv->pixbuf)) {
+		if (priv->background_surface == NULL) {
+			priv->background_surface = create_background_surface (view);
+		}
+		cairo_set_source_surface (cr, priv->background_surface, xofs, yofs);
+		cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+		cairo_rectangle (cr, xofs, yofs, scaled_width, scaled_height);
+		cairo_fill (cr);
 	}
 
+	cairo_scale (cr, priv->zoom, priv->zoom);
+	cairo_set_source_surface (cr, priv->surface, xofs/priv->zoom, yofs/priv->zoom);
+	cairo_paint (cr);
+	cairo_destroy (cr);
 	return TRUE;
 }
 



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