diff options
Diffstat (limited to 'src/cairo-xcb-surface-render.c')
-rw-r--r--[-rwxr-xr-x] | src/cairo-xcb-surface-render.c | 148 |
1 files changed, 81 insertions, 67 deletions
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index c6393a809..eec45c7f3 100755..100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -39,6 +39,7 @@ #include "cairo-clip-inline.h" #include "cairo-clip-private.h" #include "cairo-composite-rectangles-private.h" +#include "cairo-image-surface-inline.h" #include "cairo-image-surface-private.h" #include "cairo-list-inline.h" #include "cairo-region-private.h" @@ -396,11 +397,6 @@ _pattern_is_supported (uint32_t flags, if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) return TRUE; - if (! _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL)) { - if ((flags & CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM) == 0) - return FALSE; - } - switch (pattern->extend) { default: ASSERT_NOT_REACHED; @@ -414,19 +410,22 @@ _pattern_is_supported (uint32_t flags, } if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_filter_t filter; - - filter = pattern->filter; - if (_cairo_matrix_has_unity_scale (&pattern->matrix) && - _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL)) - { - filter = CAIRO_FILTER_NEAREST; - } - - if (! (filter == CAIRO_FILTER_NEAREST || filter == CAIRO_FILTER_FAST)) { - if ((flags & CAIRO_XCB_RENDER_HAS_FILTERS) == 0) - return FALSE; + switch (pattern->filter) { + case CAIRO_FILTER_FAST: + case CAIRO_FILTER_NEAREST: + return (flags & CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM) || + _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL); + case CAIRO_FILTER_GOOD: + return flags & CAIRO_XCB_RENDER_HAS_FILTER_GOOD; + case CAIRO_FILTER_BEST: + return flags & CAIRO_XCB_RENDER_HAS_FILTER_BEST; + case CAIRO_FILTER_BILINEAR: + case CAIRO_FILTER_GAUSSIAN: + default: + return flags & CAIRO_XCB_RENDER_HAS_FILTERS; } + } else if (pattern->type == CAIRO_PATTERN_TYPE_MESH) { + return FALSE; } else { /* gradient */ if ((flags & CAIRO_XCB_RENDER_HAS_GRADIENTS) == 0) return FALSE; @@ -438,9 +437,8 @@ _pattern_is_supported (uint32_t flags, { return FALSE; } + return TRUE; } - - return pattern->type != CAIRO_PATTERN_TYPE_MESH; } static void @@ -519,7 +517,7 @@ _cairo_xcb_picture_set_filter (cairo_xcb_picture_t *picture, render_filter = "best"; len = strlen ("best"); } - else { + else { render_filter = "convolution"; len = strlen ("convolution"); } @@ -1045,9 +1043,7 @@ _cairo_xcb_surface_setup_surface_picture(cairo_xcb_picture_t *picture, filter = pattern->base.filter; if (filter != CAIRO_FILTER_NEAREST && - _cairo_matrix_has_unity_scale (&pattern->base.matrix) && - _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.x0)) && - _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.y0))) + _cairo_matrix_is_pixel_exact (&pattern->base.matrix)) { filter = CAIRO_FILTER_NEAREST; } @@ -1113,10 +1109,11 @@ record_to_picture (cairo_surface_t *target, return _cairo_xcb_transparent_picture ((cairo_xcb_surface_t *) target); /* Now draw the recording surface to an xcb surface */ - tmp = _cairo_surface_create_similar_scratch (target, - source->content, - limit.width, - limit.height); + tmp = _cairo_surface_create_scratch (target, + source->content, + limit.width, + limit.height, + CAIRO_COLOR_TRANSPARENT); if (tmp->status != CAIRO_STATUS_SUCCESS) { return (cairo_xcb_picture_t *) tmp; } @@ -1176,13 +1173,13 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target, /* restore transform */ if (filtered_picture != picture) { - _cairo_xcb_picture_set_matrix (filtered_picture, + _cairo_xcb_picture_set_matrix (filtered_picture, &pattern->base.matrix, pattern->base.filter, extents->x + extents->width/2., extents->y + extents->height/2.); - _cairo_xcb_picture_set_matrix (picture, + _cairo_xcb_picture_set_matrix (picture, &pattern->base.matrix, pattern->base.filter, extents->x + extents->width/2., @@ -1199,7 +1196,7 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target, if (source->type == CAIRO_SURFACE_TYPE_XCB) { - if (source->backend->type == CAIRO_SURFACE_TYPE_XCB) { + if (_cairo_surface_is_xcb(source)) { cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) source; if (xcb->screen == target->screen && xcb->fallback == NULL) { picture = _copy_to_picture ((cairo_xcb_surface_t *) source); @@ -1360,13 +1357,13 @@ _cairo_xcb_surface_picture (cairo_xcb_surface_t *target, /* restore transform */ if (filtered_picture != picture) { - _cairo_xcb_picture_set_matrix (filtered_picture, + _cairo_xcb_picture_set_matrix (filtered_picture, &pattern->base.matrix, pattern->base.filter, extents->x + extents->width/2., extents->y + extents->height/2.); - _cairo_xcb_picture_set_matrix (picture, + _cairo_xcb_picture_set_matrix (picture, &pattern->base.matrix, pattern->base.filter, extents->x + extents->width/2., @@ -1425,7 +1422,7 @@ _render_fill_boxes (void *abstract_dst, cairo_boxes_t *boxes) { cairo_xcb_surface_t *dst = abstract_dst; - xcb_rectangle_t stack_xrects[CAIRO_STACK_ARRAY_LENGTH (sizeof (xcb_rectangle_t))]; + xcb_rectangle_t stack_xrects[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)]; xcb_rectangle_t *xrects = stack_xrects; xcb_render_color_t render_color; int render_op = _render_operator (op); @@ -1581,7 +1578,7 @@ _render_composite_boxes (cairo_xcb_surface_t *dst, src->x + extents->x, src->y + extents->y, 0, 0, extents->x, extents->y, - extents->width, extents->height); + extents->width, extents->height); } @@ -1770,11 +1767,11 @@ get_clip_surface (const cairo_clip_t *clip, cairo_surface_t *surface; cairo_status_t status; - surface = _cairo_surface_create_similar_solid (&target->base, - CAIRO_CONTENT_ALPHA, - clip->extents.width, - clip->extents.height, - CAIRO_COLOR_WHITE); + surface = _cairo_surface_create_scratch (&target->base, + CAIRO_CONTENT_ALPHA, + clip->extents.width, + clip->extents.height, + CAIRO_COLOR_WHITE); if (unlikely (surface->status)) return (cairo_xcb_surface_t *) surface; @@ -2033,7 +2030,7 @@ _clip_and_composite_combine (cairo_clip_t *clip, { cairo_xcb_surface_t *tmp; cairo_xcb_surface_t *clip_surface; - int clip_x, clip_y; + int clip_x = 0, clip_y = 0; xcb_render_picture_t clip_picture; cairo_status_t status; @@ -2336,7 +2333,7 @@ _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst, cairo_clip_t *clip) { cairo_xcb_surface_t *mask; - int mask_x, mask_y; + int mask_x = 0, mask_y = 0; mask = get_clip_surface (clip, dst, &mask_x, &mask_y); if (unlikely (mask->base.status)) @@ -2739,7 +2736,7 @@ _composite_boxes (cairo_xcb_surface_t *dst, if (need_clip_mask) { cairo_xcb_surface_t *clip_surface; - int clip_x, clip_y; + int clip_x = 0, clip_y = 0; clip_surface = get_clip_surface (extents->clip, dst, &clip_x, &clip_y); @@ -2877,7 +2874,7 @@ _upload_image_inplace (cairo_xcb_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; pattern = (const cairo_surface_pattern_t *) source; - if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE) + if (! _cairo_surface_is_image (pattern->surface)) return CAIRO_INT_STATUS_UNSUPPORTED; /* Have we already upload this image to a pixmap? */ @@ -2992,27 +2989,29 @@ _boxes_for_traps (cairo_boxes_t *boxes, cairo_traps_t *traps, cairo_antialias_t antialias) { - int i; + int i, j; _cairo_boxes_init (boxes); - boxes->num_boxes = traps->num_traps; boxes->chunks.base = (cairo_box_t *) traps->traps; - boxes->chunks.count = traps->num_traps; boxes->chunks.size = traps->num_traps; if (antialias != CAIRO_ANTIALIAS_NONE) { - for (i = 0; i < traps->num_traps; i++) { + for (i = j = 0; i < traps->num_traps; i++) { /* Note the traps and boxes alias so we need to take the local copies first. */ cairo_fixed_t x1 = traps->traps[i].left.p1.x; cairo_fixed_t x2 = traps->traps[i].right.p1.x; cairo_fixed_t y1 = traps->traps[i].top; cairo_fixed_t y2 = traps->traps[i].bottom; - boxes->chunks.base[i].p1.x = x1; - boxes->chunks.base[i].p1.y = y1; - boxes->chunks.base[i].p2.x = x2; - boxes->chunks.base[i].p2.y = y2; + if (x1 == x2 || y1 == y2) + continue; + + boxes->chunks.base[j].p1.x = x1; + boxes->chunks.base[j].p1.y = y1; + boxes->chunks.base[j].p2.x = x2; + boxes->chunks.base[j].p2.y = y2; + j++; if (boxes->is_pixel_aligned) { boxes->is_pixel_aligned = @@ -3023,7 +3022,7 @@ _boxes_for_traps (cairo_boxes_t *boxes, } else { boxes->is_pixel_aligned = TRUE; - for (i = 0; i < traps->num_traps; i++) { + for (i = j = 0; i < traps->num_traps; i++) { /* Note the traps and boxes alias so we need to take the local copies first. */ cairo_fixed_t x1 = traps->traps[i].left.p1.x; cairo_fixed_t x2 = traps->traps[i].right.p1.x; @@ -3031,12 +3030,18 @@ _boxes_for_traps (cairo_boxes_t *boxes, cairo_fixed_t y2 = traps->traps[i].bottom; /* round down here to match Pixman's behavior when using traps. */ - boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1); - boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1); - boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2); - boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2); + boxes->chunks.base[j].p1.x = _cairo_fixed_round_down (x1); + boxes->chunks.base[j].p1.y = _cairo_fixed_round_down (y1); + boxes->chunks.base[j].p2.x = _cairo_fixed_round_down (x2); + boxes->chunks.base[j].p2.y = _cairo_fixed_round_down (y2); + + j += (boxes->chunks.base[j].p1.x != boxes->chunks.base[j].p2.x && + boxes->chunks.base[j].p1.y != boxes->chunks.base[j].p2.y); } } + + boxes->num_boxes = j; + boxes->chunks.count = j; } static cairo_status_t @@ -3209,6 +3214,9 @@ _clip_and_composite_boxes (cairo_xcb_surface_t *dst, clip = _cairo_clip_copy (extents->clip); clip = _cairo_clip_intersect_boxes (clip, boxes); + if (_cairo_clip_is_all_clipped (clip)) + return CAIRO_INT_STATUS_NOTHING_TO_DO; + status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias); _cairo_clip_path_destroy (clip->path); @@ -4561,6 +4569,9 @@ _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection, const uint8_t *d; uint8_t *new, *n; + if (c == 0) + break; + new = malloc (c); if (unlikely (new == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -4589,6 +4600,9 @@ _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection, const uint32_t *d; uint32_t *new, *n; + if (c == 0) + break; + new = malloc (4 * c); if (unlikely (new == NULL)) { status = _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -4979,36 +4993,36 @@ _create_convolution_coef (double *convolution_matrix, return NULL; if (is_x_pass) { - length = col; + length = col; values = _cairo_malloc_ab (length + 2, sizeof (xcb_render_fixed_t)); if (values == NULL) return NULL; - v = col; - values[0] = _cairo_fixed_16_16_from_double (v); - values[1] = _cairo_fixed_16_16_from_double (1.0); + v = col; + values[0] = _cairo_fixed_16_16_from_double (v); + values[1] = _cairo_fixed_16_16_from_double (1.0); coef = _cairo_malloc_ab (length, sizeof (double)); if (coef == NULL) { free (values); return NULL; } memset (coef, 0, sizeof (double) * length); - compute_x_coef_to_double (convolution_matrix, row, col, coef); + compute_x_coef_to_double (convolution_matrix, row, col, coef); } else { - length = row; + length = row; values = _cairo_malloc_ab (length + 2, sizeof (xcb_render_fixed_t)); if (values == NULL) return NULL; - values[0] = _cairo_fixed_16_16_from_double (1.0); - v = row; - values[1] = _cairo_fixed_16_16_from_double (v); + values[0] = _cairo_fixed_16_16_from_double (1.0); + v = row; + values[1] = _cairo_fixed_16_16_from_double (v); coef = _cairo_malloc_ab (length, sizeof (double)); if (coef == NULL) { free (values); return NULL; } memset (coef, 0, sizeof (double) * length); - compute_y_coef_to_double (convolution_matrix, row, col, coef); + compute_y_coef_to_double (convolution_matrix, row, col, coef); } for (i = 0; i < length; i++) @@ -5102,7 +5116,7 @@ _cairo_xcb_gaussian_filter (cairo_xcb_surface_t *source, pixmap, xrender_format, 0, 0); - _cairo_xcb_connection_free_pixmap (source->connection, pixmap); + _cairo_xcb_connection_free_pixmap (source->connection, pixmap); } if (width != src_width || height != src_height) { |