[gtk+/border-image: 6/7] border-image: don't cache the cairo_surface_t in GtkBorderImage
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/border-image: 6/7] border-image: don't cache the cairo_surface_t in GtkBorderImage
- Date: Sun, 5 Jun 2011 21:03:52 +0000 (UTC)
commit 957a4f92efaf370925afae9cdd00c0e6e5022512
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Wed Jun 1 10:23:36 2011 -0400
border-image: don't cache the cairo_surface_t in GtkBorderImage
It's not useful to cache these surfaces here, as the GtkBorderImage will
be always generated on the fly, being a shorthand property.
This also allows to get rid of the intermediate image surfaces for
rendering the slices; we now use cairo_surface_create_for_rectangle()
to proxy the slices from the source surface to the rendered area, which
should also yield better performance.
gtk/gtkborderimage.c | 397 +++++++++++++++++++++++---------------------------
1 files changed, 185 insertions(+), 212 deletions(-)
---
diff --git a/gtk/gtkborderimage.c b/gtk/gtkborderimage.c
index 939d45f..075889b 100644
--- a/gtk/gtkborderimage.c
+++ b/gtk/gtkborderimage.c
@@ -76,148 +76,8 @@ struct _GtkBorderImage {
gint ref_count;
gboolean resolved;
-
- cairo_surface_t *surfaces[BORDER_LAST][BORDER_LAST];
};
-static void
-_gtk_border_image_ensure_slices (GtkBorderImage *image,
- gdouble width,
- gdouble height)
-{
- cairo_surface_t *surface;
- cairo_t *cr;
-
- if (image->surfaces[0][0] != NULL)
- return;
-
- if (cairo_pattern_get_type (image->source) != CAIRO_PATTERN_TYPE_SURFACE)
- {
- cairo_matrix_t matrix;
-
- cairo_matrix_init_scale (&matrix, 1 / width, 1 / height);
- cairo_pattern_set_matrix (image->source, &matrix);
-
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
- cr = cairo_create (surface);
- cairo_set_source (cr, image->source);
- cairo_paint (cr);
-
- cairo_destroy (cr);
- }
- else
- {
- cairo_pattern_get_surface (image->source, &surface);
- cairo_surface_reference (surface);
-
- width = cairo_image_surface_get_width (surface);
- height = cairo_image_surface_get_height (surface);
- }
-
- /* Top /left corner */
- image->surfaces[BORDER_LEFT][BORDER_TOP] =
- cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR_ALPHA,
- image->slice.left, image->slice.top);
- cr = cairo_create (image->surfaces[BORDER_LEFT][BORDER_TOP]);
- cairo_set_source_surface (cr, surface, 0, 0);
- cairo_paint (cr);
-
- cairo_destroy (cr);
-
- /* Top/right corner */
- image->surfaces[BORDER_RIGHT][BORDER_TOP] =
- cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR_ALPHA,
- image->slice.right, image->slice.top);
- cr = cairo_create (image->surfaces[BORDER_RIGHT][BORDER_TOP]);
- cairo_set_source_surface (cr, surface,
- - width + image->slice.right,
- 0);
- cairo_paint (cr);
- cairo_destroy (cr);
-
- /* Bottom/left corner */
- image->surfaces[BORDER_LEFT][BORDER_BOTTOM] =
- cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR_ALPHA,
- image->slice.left, image->slice.bottom);
- cr = cairo_create (image->surfaces[BORDER_LEFT][BORDER_BOTTOM]);
- cairo_set_source_surface (cr, surface,
- 0,
- - height + image->slice.bottom);
- cairo_paint (cr);
- cairo_destroy (cr);
-
- /* Bottom/right corner */
- image->surfaces[BORDER_RIGHT][BORDER_BOTTOM] =
- cairo_surface_create_similar (surface, CAIRO_CONTENT_COLOR_ALPHA,
- image->slice.right, image->slice.bottom);
- cr = cairo_create (image->surfaces[BORDER_RIGHT][BORDER_BOTTOM]);
- cairo_set_source_surface (cr, surface,
- - width + image->slice.right,
- - height + image->slice.bottom);
- cairo_paint (cr);
- cairo_destroy (cr);
-
- if ((image->slice.left + image->slice.right) < width)
- {
- /* Top side */
- image->surfaces[BORDER_MIDDLE][BORDER_TOP] =
- cairo_surface_create_similar (surface,
- CAIRO_CONTENT_COLOR_ALPHA,
- width - image->slice.left - image->slice.right,
- image->slice.top);
- cr = cairo_create (image->surfaces[BORDER_MIDDLE][BORDER_TOP]);
- cairo_set_source_surface (cr, surface,
- - image->slice.left,
- 0);
- cairo_paint (cr);
- cairo_destroy (cr);
-
- /* Bottom side */
- image->surfaces[BORDER_MIDDLE][BORDER_BOTTOM] =
- cairo_surface_create_similar (surface,
- CAIRO_CONTENT_COLOR_ALPHA,
- width - image->slice.left - image->slice.right,
- image->slice.bottom);
- cr = cairo_create (image->surfaces[BORDER_MIDDLE][BORDER_BOTTOM]);
- cairo_set_source_surface (cr, surface,
- - image->slice.left,
- - height + image->slice.bottom);
- cairo_paint (cr);
- cairo_destroy (cr);
- }
-
- if ((image->slice.top + image->slice.bottom) < height)
- {
- /* Left side */
- image->surfaces[BORDER_LEFT][BORDER_MIDDLE] =
- cairo_surface_create_similar (surface,
- CAIRO_CONTENT_COLOR_ALPHA,
- image->slice.left,
- height - image->slice.top - image->slice.bottom);
- cr = cairo_create (image->surfaces[BORDER_LEFT][BORDER_MIDDLE]);
- cairo_set_source_surface (cr, surface,
- 0,
- - image->slice.top);
- cairo_paint (cr);
- cairo_destroy (cr);
-
- /* Right side */
- image->surfaces[BORDER_RIGHT][BORDER_MIDDLE] =
- cairo_surface_create_similar (surface,
- CAIRO_CONTENT_COLOR_ALPHA,
- image->slice.right,
- height - image->slice.top - image->slice.bottom);
- cr = cairo_create (image->surfaces[BORDER_RIGHT][BORDER_MIDDLE]);
- cairo_set_source_surface (cr, surface,
- - width + image->slice.right,
- - image->slice.top);
- cairo_paint (cr);
- cairo_destroy (cr);
- }
-
- cairo_surface_destroy (surface);
-}
-
GtkBorderImage *
_gtk_border_image_new (cairo_pattern_t *pattern,
GtkBorder *slice,
@@ -382,26 +242,23 @@ _gtk_border_image_pack (GValue *value,
static void
render_corner (cairo_t *cr,
+ gdouble corner_x,
+ gdouble corner_y,
+ gdouble corner_width,
+ gdouble corner_height,
cairo_surface_t *surface,
- gdouble x,
- gdouble y,
- gdouble width,
- gdouble height)
+ gdouble image_width,
+ gdouble image_height)
{
- gint image_width, image_height;
-
- if (width == 0 || height == 0)
+ if (corner_width == 0 || corner_height == 0)
return;
cairo_save (cr);
- image_width = cairo_image_surface_get_width (surface);
- image_height = cairo_image_surface_get_height (surface);
-
- cairo_translate (cr, x, y);
+ cairo_translate (cr, corner_x, corner_y);
cairo_scale (cr,
- width / image_width,
- height / image_height);
+ corner_width / image_width,
+ corner_height / image_height);
cairo_set_source_surface (cr, surface, 0, 0);
/* use the nearest filter for scaling, to avoid color blending */
@@ -414,19 +271,17 @@ render_corner (cairo_t *cr,
static cairo_surface_t *
create_spaced_surface (cairo_surface_t *tile,
+ gdouble tile_width,
+ gdouble tile_height,
gdouble width,
gdouble height,
GtkOrientation orientation)
{
gint n_repeats, idx;
- gint tile_width, tile_height;
gdouble avail_space, step;
cairo_surface_t *retval;
cairo_t *cr;
- tile_width = cairo_image_surface_get_width (tile);
- tile_height = cairo_image_surface_get_height (tile);
-
n_repeats = (orientation == GTK_ORIENTATION_HORIZONTAL) ?
(gint) floor (width / tile_width) :
(gint) floor (height / tile_height);
@@ -465,16 +320,17 @@ create_spaced_surface (cairo_surface_t *tile,
static void
render_border (cairo_t *cr,
- cairo_surface_t *surface,
gdouble total_width,
gdouble total_height,
+ cairo_surface_t *surface,
+ gdouble surface_width,
+ gdouble surface_height,
guint side,
GtkBorder *border_area,
GtkBorderImageRepeat *repeat)
{
gdouble target_x, target_y;
gdouble target_width, target_height;
- gint original_width, original_height;
GdkRectangle image_area;
cairo_pattern_t *pattern;
gboolean repeat_pattern;
@@ -485,18 +341,15 @@ render_border (cairo_t *cr,
cairo_surface_reference (surface);
repeat_pattern = FALSE;
- original_width = cairo_image_surface_get_width (surface);
- original_height = cairo_image_surface_get_height (surface);
-
if (side == SIDE_TOP || side == SIDE_BOTTOM)
{
target_height = (side == SIDE_TOP) ? (border_area->top) : (border_area->bottom);
- target_width = original_width * (target_height / original_height);
+ target_width = surface_width * (target_height / surface_height);
}
else
{
target_width = (side == SIDE_LEFT) ? (border_area->left) : (border_area->right);
- target_height = original_height * (target_width / original_width);
+ target_height = surface_height * (target_width / surface_width);
}
if (side == SIDE_TOP || side == SIDE_BOTTOM)
@@ -526,7 +379,7 @@ render_border (cairo_t *cr,
repeat_pattern = TRUE;
- n_repeats = (gint) floor (image_area.width / original_width);
+ n_repeats = (gint) floor (image_area.width / surface_width);
target_width = image_area.width / n_repeats;
}
else if (repeat->vrepeat == GTK_REPEAT_STYLE_SPACE)
@@ -534,13 +387,14 @@ render_border (cairo_t *cr,
cairo_surface_t *spaced_surface;
spaced_surface = create_spaced_surface (surface,
- image_area.width, original_height,
+ surface_width, surface_height,
+ image_area.width, surface_height,
GTK_ORIENTATION_HORIZONTAL);
cairo_surface_destroy (surface);
surface = spaced_surface;
/* short-circuit hscaling */
- target_width = original_width = cairo_image_surface_get_width (surface);
+ target_width = surface_width = cairo_image_surface_get_width (spaced_surface);
}
}
else
@@ -571,7 +425,7 @@ render_border (cairo_t *cr,
repeat_pattern = TRUE;
- n_repeats = (gint) floor (image_area.height / original_height);
+ n_repeats = (gint) floor (image_area.height / surface_height);
target_height = image_area.height / n_repeats;
}
else if (repeat->hrepeat == GTK_REPEAT_STYLE_SPACE)
@@ -579,13 +433,14 @@ render_border (cairo_t *cr,
cairo_surface_t *spaced_surface;
spaced_surface = create_spaced_surface (surface,
- original_width, image_area.height,
+ surface_width, surface_height,
+ surface_width, image_area.height,
GTK_ORIENTATION_VERTICAL);
cairo_surface_destroy (surface);
surface = spaced_surface;
/* short-circuit vscaling */
- target_height = original_height = cairo_image_surface_get_height (surface);
+ target_height = surface_height = cairo_image_surface_get_height (spaced_surface);
}
}
@@ -609,8 +464,8 @@ render_border (cairo_t *cr,
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
cairo_scale (cr,
- target_width / original_width,
- target_height / original_height);
+ target_width / surface_width,
+ target_height / surface_height);
cairo_set_source (cr, pattern);
cairo_paint (cr);
@@ -618,6 +473,7 @@ render_border (cairo_t *cr,
cairo_restore (cr);
cairo_pattern_destroy (pattern);
+ cairo_surface_destroy (surface);
}
void
@@ -629,60 +485,177 @@ _gtk_border_image_render (GtkBorderImage *image,
gdouble width,
gdouble height)
{
- cairo_surface_t *surface;
-
- _gtk_border_image_ensure_slices (image, width, height);
+ cairo_surface_t *surface, *slice;
+ gdouble slice_width, slice_height, surface_width, surface_height;
+
+ if (cairo_pattern_get_type (image->source) != CAIRO_PATTERN_TYPE_SURFACE)
+ {
+ cairo_matrix_t matrix;
+ cairo_t *surface_cr;
+
+ surface_width = width;
+ surface_height = height;
+
+ cairo_matrix_init_scale (&matrix, 1 / width, 1 / height);
+ cairo_pattern_set_matrix (image->source, &matrix);
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ surface_cr = cairo_create (surface);
+ cairo_set_source (surface_cr, image->source);
+ cairo_paint (surface_cr);
+
+ cairo_destroy (surface_cr);
+ }
+ else
+ {
+ cairo_pattern_get_surface (image->source, &surface);
+ cairo_surface_reference (surface);
+
+ surface_width = cairo_image_surface_get_width (surface);
+ surface_height = cairo_image_surface_get_height (surface);
+ }
cairo_save (cr);
cairo_translate (cr, x, y);
- /* Top side */
- surface = image->surfaces[BORDER_MIDDLE][BORDER_TOP];
- render_border (cr, surface,
- width, height, SIDE_TOP,
- border_width, &image->repeat);
-
- /* Bottom side */
- surface = image->surfaces[BORDER_MIDDLE][BORDER_BOTTOM];
- render_border (cr, surface,
- width, height, SIDE_BOTTOM,
- border_width, &image->repeat);
-
- /* Left side */
- surface = image->surfaces[BORDER_LEFT][BORDER_MIDDLE];
- render_border (cr, surface,
- width, height, SIDE_LEFT,
- border_width, &image->repeat);
-
- /* Right side */
- surface = image->surfaces[BORDER_RIGHT][BORDER_MIDDLE];
- render_border (cr, surface,
- width, height, SIDE_RIGHT,
- border_width, &image->repeat);
-
- /* Top/Left corner */
- surface = image->surfaces[BORDER_LEFT][BORDER_TOP];
- render_corner (cr, surface,
+ if ((image->slice.left + image->slice.right) < surface_width)
+ {
+ /* Top side */
+ slice_width = surface_width - image->slice.left - image->slice.right;
+ slice_height = image->slice.top;
+ slice = cairo_surface_create_for_rectangle
+ (surface,
+ image->slice.left, 0,
+ slice_width, slice_height);
+
+ render_border (cr,
+ width, height,
+ slice,
+ slice_width, slice_height,
+ SIDE_TOP,
+ border_width,
+ &image->repeat);
+
+ cairo_surface_destroy (slice);
+
+ /* Bottom side */
+ slice_height = image->slice.bottom;
+ slice = cairo_surface_create_for_rectangle
+ (surface,
+ image->slice.left, surface_height - image->slice.bottom,
+ slice_width, slice_height);
+
+ render_border (cr,
+ width, height,
+ slice,
+ slice_width, slice_height,
+ SIDE_BOTTOM,
+ border_width,
+ &image->repeat);
+
+ cairo_surface_destroy (slice);
+ }
+
+ if ((image->slice.top + image->slice.bottom) < surface_height)
+ {
+ /* Left side */
+ slice_width = image->slice.left;
+ slice_height = surface_height - image->slice.top - image->slice.bottom;
+ slice = cairo_surface_create_for_rectangle
+ (surface,
+ 0, image->slice.top,
+ slice_width, slice_height);
+
+ render_border (cr,
+ width, height,
+ slice,
+ slice_width, slice_height,
+ SIDE_LEFT,
+ border_width,
+ &image->repeat);
+
+ cairo_surface_destroy (slice);
+
+ /* Right side */
+ slice_width = image->slice.right;
+ slice = cairo_surface_create_for_rectangle
+ (surface,
+ surface_width - image->slice.right, image->slice.top,
+ slice_width, slice_height);
+
+ render_border (cr,
+ width, height,
+ slice,
+ slice_width, slice_height,
+ SIDE_RIGHT,
+ border_width,
+ &image->repeat);
+
+ cairo_surface_destroy (slice);
+ }
+
+ /* Top/left corner */
+ slice_width = image->slice.left;
+ slice_height = image->slice.top;
+ slice = cairo_surface_create_for_rectangle
+ (surface,
+ 0, 0,
+ slice_width, slice_height);
+
+ render_corner (cr,
0, 0,
- border_width->left, border_width->top);
+ border_width->left, border_width->top,
+ slice,
+ slice_width, slice_height);
+
+ cairo_surface_destroy (slice);
/* Top/right corner */
- surface = image->surfaces[BORDER_RIGHT][BORDER_TOP];
- render_corner (cr, surface,
+ slice_width = image->slice.right;
+ slice = cairo_surface_create_for_rectangle
+ (surface,
+ surface_width - image->slice.right, 0,
+ slice_width, slice_height);
+
+ render_corner (cr,
width - border_width->right, 0,
- border_width->right, border_width->top);
+ border_width->right, border_width->top,
+ slice,
+ slice_width, slice_height);
+
+ cairo_surface_destroy (slice);
/* Bottom/left corner */
- surface = image->surfaces[BORDER_LEFT][BORDER_BOTTOM];
- render_corner (cr, surface,
+ slice_width = image->slice.left;
+ slice_height = image->slice.bottom;
+ slice = cairo_surface_create_for_rectangle
+ (surface,
+ 0, surface_height - image->slice.bottom,
+ slice_width, slice_height);
+
+ render_corner (cr,
0, height - border_width->bottom,
- border_width->left, border_width->bottom);
+ border_width->left, border_width->bottom,
+ slice,
+ slice_width, slice_height);
+
+ cairo_surface_destroy (slice);
/* Bottom/right corner */
- surface = image->surfaces[BORDER_RIGHT][BORDER_BOTTOM];
- render_corner (cr, surface,
+ slice_width = image->slice.right;
+ slice = cairo_surface_create_for_rectangle
+ (surface,
+ surface_width - image->slice.right,
+ surface_height - image->slice.bottom,
+ slice_width, slice_height);
+
+ render_corner (cr,
width - border_width->right, height - border_width->bottom,
- border_width->right, border_width->bottom);
+ border_width->right, border_width->bottom,
+ slice,
+ slice_width, slice_height);
+
+ cairo_surface_destroy (slice);
cairo_restore (cr);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]