X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkborderimage.c;h=694db6fe0a86c079643af176c142f6321b52a1aa;hb=b9e189150bfd62c9e956e29324622058672600f0;hp=cf9da9cf0a804b4b32a63b9fa82344e81a9363b0;hpb=c0a6b1fb907f4947328af3ae307fd4ccfe874a1d;p=~andy%2Fgtk diff --git a/gtk/gtkborderimage.c b/gtk/gtkborderimage.c index cf9da9cf0..694db6fe0 100644 --- a/gtk/gtkborderimage.c +++ b/gtk/gtkborderimage.c @@ -16,9 +16,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ #include @@ -27,406 +25,217 @@ #include #include "gtkborderimageprivate.h" +#include "gtkcssbordervalueprivate.h" +#include "gtkcssimagevalueprivate.h" +#include "gtkcssnumbervalueprivate.h" +#include "gtkcssrepeatvalueprivate.h" +#include "gtkstylepropertiesprivate.h" +#include "gtkthemingengineprivate.h" + +/* this is in case round() is not provided by the compiler, + * such as in the case of C89 compilers, like MSVC + */ +#include "fallback-c89.c" -G_DEFINE_BOXED_TYPE (GtkBorderImage, _gtk_border_image, - _gtk_border_image_ref, _gtk_border_image_unref) - -enum { - BORDER_LEFT, - BORDER_MIDDLE, - BORDER_RIGHT, - BORDER_LAST, - BORDER_TOP = BORDER_LEFT, - BORDER_BOTTOM = BORDER_RIGHT -}; - -enum { - SIDE_TOP, - SIDE_RIGHT, - SIDE_BOTTOM, - SIDE_LEFT -}; - -struct _GtkBorderImage { - cairo_pattern_t *source; - GtkGradient *source_gradient; - - GtkBorder slice; - GtkCssBorderImageRepeat repeat; - - gint ref_count; -}; - -GtkBorderImage * -_gtk_border_image_new (cairo_pattern_t *pattern, - GtkBorder *slice, - GtkCssBorderImageRepeat *repeat) -{ - GtkBorderImage *image; - - image = g_slice_new0 (GtkBorderImage); - image->ref_count = 1; - - if (pattern != NULL) - image->source = cairo_pattern_reference (pattern); - - if (slice != NULL) - image->slice = *slice; - - if (repeat != NULL) - image->repeat = *repeat; - - return image; -} - -GtkBorderImage * -_gtk_border_image_new_for_gradient (GtkGradient *gradient, - GtkBorder *slice, - GtkCssBorderImageRepeat *repeat) -{ - GtkBorderImage *image; - - image = g_slice_new0 (GtkBorderImage); - image->ref_count = 1; - - if (gradient != NULL) - image->source_gradient = gtk_gradient_ref (gradient); - - if (slice != NULL) - image->slice = *slice; - - if (repeat != NULL) - image->repeat = *repeat; - - return image; -} - -GtkBorderImage * -_gtk_border_image_ref (GtkBorderImage *image) -{ - g_return_val_if_fail (image != NULL, NULL); - - image->ref_count++; - - return image; -} - -void -_gtk_border_image_unref (GtkBorderImage *image) -{ - g_return_if_fail (image != NULL); - - image->ref_count--; - - if (image->ref_count == 0) - { - if (image->source != NULL) - cairo_pattern_destroy (image->source); - - if (image->source_gradient != NULL) - gtk_gradient_unref (image->source_gradient); - - g_slice_free (GtkBorderImage, image); - } -} - -GParameter * -_gtk_border_image_unpack (const GValue *value, - guint *n_params) +gboolean +_gtk_border_image_init (GtkBorderImage *image, + GtkThemingEngine *engine) { - GParameter *parameter = g_new0 (GParameter, 3); - GtkBorderImage *image = g_value_get_boxed (value); - - parameter[0].name = "border-image-source"; - g_value_init (¶meter[0].value, CAIRO_GOBJECT_TYPE_PATTERN); - g_value_set_boxed (¶meter[0].value, image->source); + image->source = _gtk_css_image_value_get_image (_gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE)); + if (image->source == NULL) + return FALSE; - parameter[1].name = "border-image-slice"; - g_value_init (¶meter[1].value, GTK_TYPE_BORDER); - g_value_set_boxed (¶meter[1].value, &image->slice); + image->slice = _gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE); + image->width = _gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH); + image->repeat = _gtk_theming_engine_peek_property (engine, GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT); - parameter[2].name = "border-image-repeat"; - g_value_init (¶meter[2].value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT); - g_value_set_boxed (¶meter[2].value, &image->repeat); - - *n_params = 3; - return parameter; + return TRUE; } -void -_gtk_border_image_pack (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state) -{ - GtkBorderImage *image; - cairo_pattern_t *source; - GtkBorder *slice; - GtkCssBorderImageRepeat *repeat; - - gtk_style_properties_get (props, state, - "border-image-source", &source, - "border-image-slice", &slice, - "border-image-repeat", &repeat, - NULL); - - if (source == NULL) - { - g_value_take_boxed (value, NULL); - } - else - { - image = _gtk_border_image_new (source, slice, repeat); - g_value_take_boxed (value, image); - - cairo_pattern_destroy (source); - } - - if (slice != NULL) - gtk_border_free (slice); - - if (repeat != NULL) - g_free (repeat); -} +typedef struct _GtkBorderImageSliceSize GtkBorderImageSliceSize; +struct _GtkBorderImageSliceSize { + double offset; + double size; +}; static void -render_corner (cairo_t *cr, - gdouble corner_x, - gdouble corner_y, - gdouble corner_width, - gdouble corner_height, - cairo_surface_t *surface, - gdouble image_width, - gdouble image_height) +gtk_border_image_compute_border_size (GtkBorderImageSliceSize sizes[3], + double offset, + double area_size, + double start_border_width, + double end_border_width, + const GtkCssValue *start_border, + const GtkCssValue *end_border) { - if (corner_width == 0 || corner_height == 0) - return; - - cairo_save (cr); + double start, end; - cairo_translate (cr, corner_x, corner_y); - cairo_scale (cr, - 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 */ - cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST); - - cairo_paint (cr); - - cairo_restore (cr); -} + if (_gtk_css_number_value_get_unit (start_border) == GTK_CSS_NUMBER) + start = start_border_width * _gtk_css_number_value_get (start_border, 100); + else + start = _gtk_css_number_value_get (start_border, area_size); + if (_gtk_css_number_value_get_unit (end_border) == GTK_CSS_NUMBER) + end = end_border_width * _gtk_css_number_value_get (end_border, 100); + else + end = _gtk_css_number_value_get (end_border, area_size); -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; - gdouble avail_space, step; - cairo_surface_t *retval; - cairo_t *cr; - - n_repeats = (orientation == GTK_ORIENTATION_HORIZONTAL) ? - (gint) floor (width / tile_width) : - (gint) floor (height / tile_height); - - avail_space = (orientation == GTK_ORIENTATION_HORIZONTAL) ? - width - (n_repeats * tile_width) : - height - (n_repeats * tile_height); - step = avail_space / (n_repeats + 2); - - retval = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - width, height); - cr = cairo_create (retval); - idx = 0; - - while (idx < n_repeats) + /* XXX: reduce vertical and horizontal by the same factor */ + if (start + end > area_size) { - cairo_save (cr); - - if (orientation == GTK_ORIENTATION_HORIZONTAL) - cairo_set_source_surface (cr, tile, - ((idx + 1) * step) + (idx * tile_width), 0); - else - cairo_set_source_surface (cr, tile, - 0, ((idx + 1 ) * step) + (idx * tile_height)); - - cairo_paint (cr); - cairo_restore (cr); - - idx++; + start = start * area_size / (start + end); + end = end * area_size / (start + end); } - cairo_destroy (cr); - - return retval; + sizes[0].offset = offset; + sizes[0].size = start; + sizes[1].offset = offset + start; + sizes[1].size = area_size - start - end; + sizes[2].offset = offset + area_size - end; + sizes[2].size = end; } static void -render_border (cairo_t *cr, - gdouble total_width, - gdouble total_height, - cairo_surface_t *surface, - gdouble surface_width, - gdouble surface_height, - guint side, - GtkBorder *border_area, - GtkCssBorderImageRepeat *repeat) +gtk_border_image_render_slice (cairo_t *cr, + cairo_surface_t *slice, + double slice_width, + double slice_height, + double x, + double y, + double width, + double height, + GtkCssRepeatStyle hrepeat, + GtkCssRepeatStyle vrepeat) { - gdouble target_x, target_y; - gdouble target_width, target_height; - GdkRectangle image_area; + double hscale, vscale; + double xstep, ystep; + cairo_extend_t extend = CAIRO_EXTEND_PAD; + cairo_matrix_t matrix; cairo_pattern_t *pattern; - gboolean repeat_pattern; - if (surface == NULL) - return; + /* We can't draw center tiles yet */ + g_assert (hrepeat == GTK_CSS_REPEAT_STYLE_STRETCH || vrepeat == GTK_CSS_REPEAT_STYLE_STRETCH); - cairo_surface_reference (surface); - repeat_pattern = FALSE; + hscale = width / slice_width; + vscale = height / slice_height; + xstep = width; + ystep = height; - if (side == SIDE_TOP || side == SIDE_BOTTOM) + switch (hrepeat) { - target_height = (side == SIDE_TOP) ? (border_area->top) : (border_area->bottom); - target_width = surface_width * (target_height / surface_height); - } - else - { - target_width = (side == SIDE_LEFT) ? (border_area->left) : (border_area->right); - target_height = surface_height * (target_width / surface_width); + case GTK_CSS_REPEAT_STYLE_REPEAT: + extend = CAIRO_EXTEND_REPEAT; + hscale = vscale; + break; + case GTK_CSS_REPEAT_STYLE_SPACE: + { + double space, n; + + extend = CAIRO_EXTEND_NONE; + hscale = vscale; + + xstep = hscale * slice_width; + n = floor (width / xstep); + space = (width - n * xstep) / (n + 1); + xstep += space; + x += space; + width -= 2 * space; + } + break; + case GTK_CSS_REPEAT_STYLE_STRETCH: + break; + case GTK_CSS_REPEAT_STYLE_ROUND: + extend = CAIRO_EXTEND_REPEAT; + hscale = width / (slice_width * MAX (round (width / (slice_width * vscale)), 1)); + break; + default: + g_assert_not_reached (); + break; } - if (side == SIDE_TOP || side == SIDE_BOTTOM) + switch (vrepeat) { - image_area.x = border_area->left; - image_area.y = (side == SIDE_TOP) ? 0 : (total_height - border_area->bottom); - image_area.width = total_width - border_area->left - border_area->right; - image_area.height = (side == SIDE_TOP) ? border_area->top : border_area->bottom; - - target_x = border_area->left; - target_y = (side == SIDE_TOP) ? 0 : (total_height - border_area->bottom); - - if (repeat->vrepeat == GTK_CSS_REPEAT_STYLE_NONE) - { - target_width = image_area.width; - } - else if (repeat->vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT) - { - repeat_pattern = TRUE; - - target_x = border_area->left + (total_width - border_area->left - border_area->right) / 2; - target_y = ((side == SIDE_TOP) ? 0 : (total_height - border_area->bottom)) / 2; - } - else if (repeat->vrepeat == GTK_CSS_REPEAT_STYLE_ROUND) - { - gint n_repeats; - - repeat_pattern = TRUE; - - n_repeats = (gint) floor (image_area.width / surface_width); - target_width = image_area.width / n_repeats; - } - else if (repeat->vrepeat == GTK_CSS_REPEAT_STYLE_SPACE) - { - cairo_surface_t *spaced_surface; - - spaced_surface = create_spaced_surface (surface, - surface_width, surface_height, - image_area.width, surface_height, - GTK_ORIENTATION_HORIZONTAL); - cairo_surface_destroy (surface); - surface = spaced_surface; - - /* short-circuit hscaling */ - target_width = surface_width = cairo_image_surface_get_width (spaced_surface); - } + case GTK_CSS_REPEAT_STYLE_REPEAT: + extend = CAIRO_EXTEND_REPEAT; + vscale = hscale; + break; + case GTK_CSS_REPEAT_STYLE_SPACE: + { + double space, n; + + extend = CAIRO_EXTEND_NONE; + vscale = hscale; + + ystep = vscale * slice_height; + n = floor (height / ystep); + space = (height - n * ystep) / (n + 1); + ystep += space; + y += space; + height -= 2 * space; + } + break; + case GTK_CSS_REPEAT_STYLE_STRETCH: + break; + case GTK_CSS_REPEAT_STYLE_ROUND: + extend = CAIRO_EXTEND_REPEAT; + vscale = height / (slice_height * MAX (round (height / (slice_height * hscale)), 1)); + break; + default: + g_assert_not_reached (); + break; } - else - { - image_area.x = (side == SIDE_LEFT) ? 0 : (total_width - border_area->right); - image_area.y = border_area->top; - image_area.width = (side == SIDE_LEFT) ? border_area->left : border_area->right; - image_area.height = total_height - border_area->top - border_area->bottom; - target_x = (side == SIDE_LEFT) ? 0 : (total_width - border_area->right); - target_y = border_area->top; + pattern = cairo_pattern_create_for_surface (slice); - if (repeat->hrepeat == GTK_CSS_REPEAT_STYLE_NONE) - { - target_height = total_height - border_area->top - border_area->bottom; - } - else if (repeat->hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT) - { - repeat_pattern = TRUE; + cairo_matrix_init_translate (&matrix, + hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? slice_width / 2 : 0, + vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? slice_height / 2 : 0); + cairo_matrix_scale (&matrix, 1 / hscale, 1 / vscale); + cairo_matrix_translate (&matrix, + hrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? - width / 2 : 0, + vrepeat == GTK_CSS_REPEAT_STYLE_REPEAT ? - height / 2 : 0); - target_height = total_height - border_area->top - border_area->bottom; - target_x = (side == SIDE_LEFT) ? 0 : (total_width - border_area->right) / 2; - target_y = border_area->top + (total_height - border_area->top - border_area->bottom) / 2; - } - else if (repeat->hrepeat == GTK_CSS_REPEAT_STYLE_ROUND) - { - gint n_repeats; + cairo_pattern_set_matrix (pattern, &matrix); + cairo_pattern_set_extend (pattern, extend); - repeat_pattern = TRUE; + cairo_save (cr); + cairo_translate (cr, x, y); - n_repeats = (gint) floor (image_area.height / surface_height); - target_height = image_area.height / n_repeats; - } - else if (repeat->hrepeat == GTK_CSS_REPEAT_STYLE_SPACE) + for (y = 0; y < height; y += ystep) + { + for (x = 0; x < width; x += xstep) { - cairo_surface_t *spaced_surface; - - spaced_surface = create_spaced_surface (surface, - surface_width, surface_height, - surface_width, image_area.height, - GTK_ORIENTATION_VERTICAL); - cairo_surface_destroy (surface); - surface = spaced_surface; - - /* short-circuit vscaling */ - target_height = surface_height = cairo_image_surface_get_height (spaced_surface); + cairo_save (cr); + cairo_translate (cr, x, y); + cairo_set_source (cr, pattern); + cairo_rectangle (cr, 0, 0, xstep, ystep); + cairo_fill (cr); + cairo_restore (cr); } } - if (target_width == 0 || target_height == 0) - return; - - cairo_save (cr); - - pattern = cairo_pattern_create_for_surface (surface); - - gdk_cairo_rectangle (cr, &image_area); - cairo_clip (cr); - - cairo_translate (cr, - target_x, target_y); - - /* use the nearest filter for scaling, to avoid color blending */ - cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST); - - if (repeat_pattern) - cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); + cairo_restore (cr); - cairo_scale (cr, - target_width / surface_width, - target_height / surface_height); + cairo_pattern_destroy (pattern); +} - cairo_set_source (cr, pattern); - cairo_paint (cr); +static void +gtk_border_image_compute_slice_size (GtkBorderImageSliceSize sizes[3], + int surface_size, + int start_size, + int end_size) +{ + sizes[0].size = MIN (start_size, surface_size); + sizes[0].offset = 0; - cairo_restore (cr); + sizes[2].size = MIN (end_size, surface_size); + sizes[2].offset = surface_size - sizes[2].size; - cairo_pattern_destroy (pattern); - cairo_surface_destroy (surface); + sizes[1].size = MAX (0, surface_size - sizes[0].size - sizes[2].size); + sizes[1].offset = sizes[0].size; } void _gtk_border_image_render (GtkBorderImage *image, - GtkBorder *border_width, + const double border_width[4], cairo_t *cr, gdouble x, gdouble y, @@ -434,176 +243,80 @@ _gtk_border_image_render (GtkBorderImage *image, gdouble 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); - - if ((image->slice.left + image->slice.right) < surface_width) + GtkBorderImageSliceSize vertical_slice[3], horizontal_slice[3]; + GtkBorderImageSliceSize vertical_border[3], horizontal_border[3]; + double source_width, source_height; + int h, v; + + _gtk_css_image_get_concrete_size (image->source, + 0, 0, + width, height, + &source_width, &source_height); + + /* XXX: Optimize for (source_width == width && source_height == height) */ + + surface = _gtk_css_image_get_surface (image->source, + cairo_get_target (cr), + source_width, source_height); + + gtk_border_image_compute_slice_size (horizontal_slice, + source_width, + _gtk_css_number_value_get (_gtk_css_border_value_get_left (image->slice), source_width), + _gtk_css_number_value_get (_gtk_css_border_value_get_right (image->slice), source_width)); + gtk_border_image_compute_slice_size (vertical_slice, + source_height, + _gtk_css_number_value_get (_gtk_css_border_value_get_top (image->slice), source_height), + _gtk_css_number_value_get (_gtk_css_border_value_get_bottom (image->slice), source_height)); + gtk_border_image_compute_border_size (horizontal_border, + x, + width, + border_width[GTK_CSS_LEFT], + border_width[GTK_CSS_RIGHT], + _gtk_css_border_value_get_left (image->width), + _gtk_css_border_value_get_right (image->width)); + gtk_border_image_compute_border_size (vertical_border, + y, + height, + border_width[GTK_CSS_TOP], + border_width[GTK_CSS_BOTTOM], + _gtk_css_border_value_get_top (image->width), + _gtk_css_border_value_get_bottom(image->width)); + + for (v = 0; v < 3; v++) { - /* 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 (vertical_slice[v].size == 0 || + vertical_border[v].size == 0) + continue; - 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); + for (h = 0; h < 3; h++) + { + if (horizontal_slice[h].size == 0 || + horizontal_border[h].size == 0) + continue; + + if (h == 1 && v == 1) + continue; + + slice = cairo_surface_create_for_rectangle (surface, + horizontal_slice[h].offset, + vertical_slice[v].offset, + horizontal_slice[h].size, + vertical_slice[v].size); + + gtk_border_image_render_slice (cr, + slice, + horizontal_slice[h].size, + vertical_slice[v].size, + horizontal_border[h].offset, + vertical_border[v].offset, + horizontal_border[h].size, + vertical_border[v].size, + h == 1 ? _gtk_css_border_repeat_value_get_x (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH, + v == 1 ? _gtk_css_border_repeat_value_get_y (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH); + + 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, - slice, - slice_width, slice_height); - - cairo_surface_destroy (slice); - - /* Top/right corner */ - 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, - slice, - slice_width, slice_height); - - cairo_surface_destroy (slice); - - /* Bottom/left corner */ - 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, - slice, - slice_width, slice_height); - - cairo_surface_destroy (slice); - - /* Bottom/right corner */ - 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, - slice, - slice_width, slice_height); - - cairo_surface_destroy (slice); - - cairo_restore (cr); + cairo_surface_destroy (surface); }