summaryrefslogtreecommitdiff
path: root/src/cairo-xcb-surface-render.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cairo-xcb-surface-render.c')
-rw-r--r--[-rwxr-xr-x]src/cairo-xcb-surface-render.c148
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) {