[eog] Fully rely on cairo to render the image in EogScrollView
- From: Claudio Saavedra <csaavedra src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [eog] Fully rely on cairo to render the image in EogScrollView
- Date: Wed, 8 Sep 2010 16:43:10 +0000 (UTC)
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]