[gnome-system-tools/rendering-cleanup: 9/20] e-map: Make cache a server-side surface
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-system-tools/rendering-cleanup: 9/20] e-map: Make cache a server-side surface
- Date: Tue, 5 Oct 2010 16:40:57 +0000 (UTC)
commit ce7c968fe97fe78ef1a1b7cca7a8c0a50e9888a7
Author: Benjamin Otte <otte redhat com>
Date: Mon Oct 4 19:04:11 2010 +0200
e-map: Make cache a server-side surface
Doing performance optimizations on the client is not a good idea...
src/time/e-map/e-map.c | 180 ++++++++++++++++++++++--------------------------
1 files changed, 82 insertions(+), 98 deletions(-)
---
diff --git a/src/time/e-map/e-map.c b/src/time/e-map/e-map.c
index 4597b7a..d88c970 100644
--- a/src/time/e-map/e-map.c
+++ b/src/time/e-map/e-map.c
@@ -56,7 +56,8 @@ EMapZoomState;
struct _EMapPrivate {
/* Pointer to map image */
- GdkPixbuf *map_pixbuf, *map_render_pixbuf;
+ GdkPixbuf *map_pixbuf;
+ cairo_surface_t *map_render_surface;
/* Settings */
gboolean frozen, smooth_zoom;
@@ -94,7 +95,7 @@ static gint e_map_expose (GtkWidget *widget, GdkEventExpose *event);
static gint e_map_key_press (GtkWidget *widget, GdkEventKey *event);
static void e_map_set_scroll_adjustments (GtkWidget *widget, GtkAdjustment *hadj, GtkAdjustment *vadj);
-static void update_render_pixbuf (EMap *map, GdkInterpType interp, gboolean render_overlays);
+static void update_render_surface (EMap *map, gboolean render_overlays);
static void set_scroll_area (EMap *view, int width, int height);
static void center_at (EMap *map, gint x, gint y);
static void smooth_center_at (EMap *map, gint x, gint y);
@@ -259,11 +260,8 @@ e_map_finalize (GObject *object)
priv->map_pixbuf = NULL;
}
- if (priv->map_render_pixbuf)
- {
- g_object_unref (priv->map_render_pixbuf);
- priv->map_render_pixbuf = NULL;
- }
+ /* gone in unrealize */
+ g_assert (priv->map_render_surface == NULL);
g_free (priv);
view->priv = NULL;
@@ -326,7 +324,7 @@ e_map_realize (GtkWidget *widget)
gtk_widget_set_style (widget, style);
gdk_window_set_back_pixmap (window, NULL, FALSE);
- update_render_pixbuf (E_MAP (widget), GDK_INTERP_BILINEAR, TRUE);
+ update_render_surface (E_MAP (widget), TRUE);
}
/* Unrealize handler for the map view */
@@ -334,8 +332,11 @@ e_map_realize (GtkWidget *widget)
static void
e_map_unrealize (GtkWidget *widget)
{
- g_return_if_fail (widget != NULL);
- g_return_if_fail (E_IS_MAP (widget));
+ EMap *view = E_MAP (widget);
+ EMapPrivate *priv = view->priv;
+
+ cairo_surface_destroy (priv->map_render_surface);
+ priv->map_render_surface = NULL;
if (GTK_WIDGET_CLASS (parent_class)->unrealize)
(*GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
@@ -391,7 +392,7 @@ e_map_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
gtk_widget_queue_draw (widget);
}
- update_render_pixbuf (view, GDK_INTERP_BILINEAR, TRUE);
+ update_render_surface (view, TRUE);
}
/* Button press handler for the map view */
@@ -448,16 +449,15 @@ e_map_expose (GtkWidget *widget, GdkEventExpose *event)
view = E_MAP (widget);
priv = view->priv;
- if (!priv->map_render_pixbuf) return FALSE;
cr = gdk_cairo_create (event->window);
gdk_cairo_region (cr, event->region);
cairo_clip (cr);
- gdk_cairo_set_source_pixbuf (cr,
- priv->map_render_pixbuf,
- - priv->xofs,
- - priv->yofs);
+ cairo_set_source_surface (cr,
+ priv->map_render_surface,
+ - priv->xofs,
+ - priv->yofs);
cairo_paint (cr);
cairo_destroy (cr);
@@ -641,8 +641,8 @@ e_map_window_to_world (EMap *map, gdouble win_x, gdouble win_y, gdouble *world_l
priv = map->priv;
g_return_if_fail (gtk_widget_get_realized (GTK_WIDGET (map)));
- width = gdk_pixbuf_get_width (priv->map_render_pixbuf);
- height = gdk_pixbuf_get_height (priv->map_render_pixbuf);
+ width = E_MAP_GET_WIDTH (map);
+ height = E_MAP_GET_HEIGHT (map);
*world_longitude = (win_x + priv->xofs - (gdouble) width / 2.0) /
((gdouble) width / 2.0) * 180.0;
@@ -659,12 +659,12 @@ e_map_world_to_window (EMap *map, gdouble world_longitude, gdouble world_latitud
g_return_if_fail (map);
priv = map->priv;
- g_return_if_fail (priv->map_render_pixbuf);
+ g_return_if_fail (priv->map_render_surface);
g_return_if_fail (world_longitude >= -180.0 && world_longitude <= 180.0);
g_return_if_fail (world_latitude >= -90.0 && world_latitude <= 90.0);
- width = gdk_pixbuf_get_width (priv->map_render_pixbuf);
- height = gdk_pixbuf_get_height (priv->map_render_pixbuf);
+ width = E_MAP_GET_WIDTH (map);
+ height = E_MAP_GET_HEIGHT (map);
*win_x = (width / 2.0 + (width / 2.0) * world_longitude / 180.0) - priv->xofs;
*win_y = (height / 2.0 - (height / 2.0) * world_latitude / 90.0) - priv->yofs;
@@ -788,7 +788,7 @@ e_map_remove_point (EMap *map, EMapPoint *point)
/* FIXME: Re-scaling the whole pixbuf is more than a little
* overkill when just one point is removed */
- update_render_pixbuf (map, GDK_INTERP_BILINEAR, TRUE);
+ update_render_surface (map, TRUE);
repaint_point (map, point);
}
@@ -848,7 +848,7 @@ e_map_point_is_in_view (EMap *map, EMapPoint *point)
gdouble x, y;
priv = map->priv;
- if (!priv->map_render_pixbuf) return FALSE;
+ if (!priv->map_render_surface) return FALSE;
e_map_world_to_window (map, point->longitude, point->latitude, &x, &y);
gtk_widget_get_allocation (GTK_WIDGET (map), &allocation);
@@ -897,7 +897,7 @@ e_map_get_closest_point (EMap *map, gdouble longitude, gdouble latitude, gboolea
static void
update_and_paint (EMap *map)
{
- update_render_pixbuf (map, GDK_INTERP_BILINEAR, TRUE);
+ update_render_surface (map, TRUE);
gtk_widget_queue_draw (GTK_WIDGET (map));
}
@@ -915,15 +915,14 @@ load_map_background (EMap *view, gchar *name)
if (priv->map_pixbuf) g_object_unref (priv->map_pixbuf);
priv->map_pixbuf = pb0;
- update_render_pixbuf (view, GDK_INTERP_BILINEAR, TRUE);
+ update_render_surface (view, TRUE);
return TRUE;
}
static void
-update_render_pixbuf (EMap *map,
- GdkInterpType interp,
- gboolean render_overlays)
+update_render_surface (EMap *map,
+ gboolean render_overlays)
{
EMapPrivate *priv;
EMapPoint *point;
@@ -959,20 +958,25 @@ update_render_pixbuf (EMap *map,
/* Reallocate the pixbuf */
- if (priv->map_render_pixbuf) g_object_unref (priv->map_render_pixbuf);
- priv->map_render_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, /* No alpha */
- 8, width, height);
+ if (priv->map_render_surface) cairo_surface_destroy (priv->map_render_surface);
+ priv->map_render_surface = gdk_window_create_similar_surface (gtk_widget_get_window (GTK_WIDGET (map)),
+ CAIRO_CONTENT_COLOR,
+ width, height);
/* Scale the original map into the rendering pixbuf */
-
if (width > 1 && height > 1)
{
- gdk_pixbuf_scale (priv->map_pixbuf, priv->map_render_pixbuf, 0, 0, /* Dest (x, y) */
- width, height, 0, 0, /* Offset (x, y) */
- zoom, zoom, /* Scale (x, y) */
- interp);
+ cairo_t *cr = cairo_create (priv->map_render_surface);
+ cairo_scale (cr, (double) width / orig_width, (double) height / orig_height);
+ gdk_cairo_set_source_pixbuf (cr, priv->map_pixbuf, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
}
+ /* Compute image offsets with respect to window */
+
+ set_scroll_area (map, width, height);
+
if (render_overlays)
{
/* Add points */
@@ -983,73 +987,53 @@ update_render_pixbuf (EMap *map,
update_render_point (map, point);
}
}
-
- /* Compute image offsets with respect to window */
-
- set_scroll_area (map, width, height);
-}
-
-/* Queues a repaint of the specified area in window coordinates */
-
-static void
-put_pixel_with_clipping (GdkPixbuf *pixbuf, gint x, gint y, guint rgba)
-{
- gint width, height;
- gint rowstride, n_channels;
- guchar *pixels, *pixel;
-
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- n_channels = gdk_pixbuf_get_n_channels (pixbuf);
- pixels = gdk_pixbuf_get_pixels (pixbuf);
-
- if (x < 0 || x >= width || y < 0 || y >= height)
- return;
-
- pixel = pixels + (y * rowstride) + (x * n_channels);
-
- *pixel = (rgba >> 24);
- *(pixel + 1) = (rgba >> 16) & 0x000000ff;
- *(pixel + 2) = (rgba >> 8) & 0x000000ff;
-
- if (n_channels > 3)
- {
- *(pixel + 3) = rgba & 0x000000ff;
- }
}
-/* Redraw point in client pixbuf */
+/* Redraw point in client surface */
static void
update_render_point (EMap *map, EMapPoint *point)
{
EMapPrivate *priv;
- GdkPixbuf *pb;
+ cairo_t *cr;
gdouble px, py;
+ static guchar mask1[] = { 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+ 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ static guchar mask2[] = { 0x00, 0xff, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0x00,
+ 0x00, 0xff, 0x00, 0x00 };
+ cairo_surface_t *mask;
priv = map->priv;
- pb = priv->map_render_pixbuf;
- if (!pb) return;
+
+ if (priv->map_render_surface == NULL)
+ return;
+
+ cr = cairo_create (priv->map_render_surface);
+ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
e_map_world_to_window (map, point->longitude, point->latitude, &px, &py);
- px += priv->xofs;
- py += priv->yofs;
-
- put_pixel_with_clipping (pb, px, py, point->rgba);
- put_pixel_with_clipping (pb, px - 1, py, point->rgba);
- put_pixel_with_clipping (pb, px + 1, py, point->rgba);
- put_pixel_with_clipping (pb, px, py - 1, point->rgba);
- put_pixel_with_clipping (pb, px, py + 1, point->rgba);
-
- put_pixel_with_clipping (pb, px - 2, py, 0x000000ff);
- put_pixel_with_clipping (pb, px + 2, py, 0x000000ff);
- put_pixel_with_clipping (pb, px, py - 2, 0x000000ff);
- put_pixel_with_clipping (pb, px, py + 2, 0x000000ff);
- put_pixel_with_clipping (pb, px - 1, py - 1, 0x000000ff);
- put_pixel_with_clipping (pb, px - 1, py + 1, 0x000000ff);
- put_pixel_with_clipping (pb, px + 1, py - 1, 0x000000ff);
- put_pixel_with_clipping (pb, px + 1, py + 1, 0x000000ff);
+ px = floor (px + priv->xofs);
+ py = floor (py + priv->yofs);
+
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ mask = cairo_image_surface_create_for_data (mask1, CAIRO_FORMAT_A8, 5, 5, 8);
+ cairo_mask_surface (cr, mask, px - 2, py - 2);
+ cairo_surface_destroy (mask);
+
+ cairo_set_source_rgba (cr,
+ ((point->rgba >> 24) & 0xff) / 255.0,
+ ((point->rgba >> 16) & 0xff) / 255.0,
+ ((point->rgba >> 8) & 0xff) / 255.0,
+ ( point->rgba & 0xff) / 255.0);
+ mask = cairo_image_surface_create_for_data (mask2, CAIRO_FORMAT_A8, 3, 3, 4);
+ cairo_mask_surface (cr, mask, px - 1, py - 1);
+ cairo_surface_destroy (mask);
+
+ cairo_destroy (cr);
}
/* Repaint point on X server */
@@ -1377,8 +1361,8 @@ zoom_in_smooth (EMap *map)
priv = map->priv;
window = gtk_widget_get_window (GTK_WIDGET (map));
- width = gdk_pixbuf_get_width (priv->map_render_pixbuf);
- height = gdk_pixbuf_get_height (priv->map_render_pixbuf);
+ width = E_MAP_GET_WIDTH (map);
+ height = E_MAP_GET_HEIGHT (map);
/* Center the target point as much as possible */
@@ -1388,7 +1372,7 @@ zoom_in_smooth (EMap *map)
/* Render and paint a temporary map without overlays, so they don't get in
* the way (look ugly) while zooming */
- update_render_pixbuf (map, GDK_INTERP_BILINEAR, FALSE);
+ update_render_surface (map, FALSE);
gtk_widget_draw (GTK_WIDGET (map), NULL);
/* Find out where in the area we're going to zoom to */
@@ -1399,7 +1383,7 @@ zoom_in_smooth (EMap *map)
* blowup sequence ends */
priv->zoom_state = E_MAP_ZOOMED_IN;
- update_render_pixbuf (map, GDK_INTERP_BILINEAR, TRUE);
+ update_render_surface (map, TRUE);
/* Do the blowup */
@@ -1429,7 +1413,7 @@ zoom_in (EMap *map)
priv->zoom_state = E_MAP_ZOOMED_IN;
- update_render_pixbuf (map, GDK_INTERP_BILINEAR, TRUE);
+ update_render_surface (map, TRUE);
e_map_world_to_window (
map, priv->zoom_target_long,
@@ -1462,14 +1446,14 @@ zoom_out (EMap *map)
area.width = allocation.width;
area.height = allocation.height;
- /* Must be done before update_render_pixbuf() */
+ /* Must be done before update_render_surface() */
e_map_window_to_world (
map, area.width / 2, area.height / 2,
&longitude, &latitude);
priv->zoom_state = E_MAP_ZOOMED_OUT;
- update_render_pixbuf (map, GDK_INTERP_BILINEAR, TRUE);
+ update_render_surface (map, TRUE);
e_map_world_to_window (map, longitude, latitude, &x, &y);
center_at (map, x + priv->xofs, y + priv->yofs);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]