diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2009-10-16 16:48:54 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2009-10-21 11:37:16 +0100 |
commit | df357f26ff72571acb840715efa4930054d4fdbe (patch) | |
tree | 66e9174c24c52564a5d691a21653c8b31a3b7156 | |
parent | f0cd20e6cec445eb627c2708c2230c8bad1b64ce (diff) |
Support component-alpha.
Within our code base we carried a few hacks to utilize the component
alpha capabilities of pixman, whilst not supporting the concept for our
own masks. Thus we were setting it upon the pixman_image_t that we
passed around through code that was blissfully unaware and indeed the
component-alpha property was forgotten (e.g. upgrading glyph masks).
The real issue is that without explicit support that a pattern carries
subpixel masking information, that information is lost when using that
pattern with composite. Again we can look at the example of compositing
a sub-pixel glyph mask onto a remote xlib surface for further failure.
-rw-r--r-- | src/cairo-ft-font.c | 5 | ||||
-rw-r--r-- | src/cairo-gl-glyphs.c | 23 | ||||
-rw-r--r-- | src/cairo-gl-surface.c | 18 | ||||
-rw-r--r-- | src/cairo-gstate.c | 17 | ||||
-rw-r--r-- | src/cairo-image-surface.c | 55 | ||||
-rw-r--r-- | src/cairo-pattern.c | 22 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 10 | ||||
-rw-r--r-- | src/cairo-scaled-font.c | 14 | ||||
-rw-r--r-- | src/cairo-svg-surface.c | 10 | ||||
-rw-r--r-- | src/cairo-types-private.h | 71 | ||||
-rw-r--r-- | src/cairo-win32-font.c | 10 | ||||
-rw-r--r-- | src/cairo-xlib-surface-private.h | 1 | ||||
-rw-r--r-- | src/cairo-xlib-surface.c | 43 | ||||
-rw-r--r-- | src/cairoint.h | 69 |
14 files changed, 234 insertions, 134 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 036bfa06..05f65628 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -802,7 +802,6 @@ _get_bitmap_surface (FT_Bitmap *bitmap, int width, height, stride; unsigned char *data; int format = CAIRO_FORMAT_A8; - cairo_bool_t subpixel = FALSE; width = bitmap->width; height = bitmap->rows; @@ -970,7 +969,6 @@ _get_bitmap_surface (FT_Bitmap *bitmap, data = data_rgba; stride = stride_rgba; format = CAIRO_FORMAT_ARGB32; - subpixel = TRUE; break; } } @@ -993,9 +991,6 @@ _get_bitmap_surface (FT_Bitmap *bitmap, return (*surface)->base.status; } - if (subpixel) - pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); - _cairo_image_surface_assume_ownership_of_data ((*surface)); _cairo_debug_check_image_surface_is_defined (&(*surface)->base); diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c index ff599d88..4370fdba 100644 --- a/src/cairo-gl-glyphs.c +++ b/src/cairo-gl-glyphs.c @@ -341,6 +341,7 @@ _render_glyphs (cairo_gl_surface_t *dst, int num_glyphs, const cairo_rectangle_int_t *glyph_extents, cairo_scaled_font_t *scaled_font, + cairo_bool_t *has_component_alpha, cairo_region_t *clip_region, int *remaining_glyphs) { @@ -353,6 +354,8 @@ _render_glyphs (cairo_gl_surface_t *dst, int i = 0; GLuint vbo = 0; + *has_component_alpha = FALSE; + status = _cairo_gl_operand_init (&composite_setup.src, source, dst, glyph_extents->x, glyph_extents->y, dst_x, dst_y, @@ -376,6 +379,7 @@ _render_glyphs (cairo_gl_surface_t *dst, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + /* XXX component alpha */ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE1); glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE1); glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA); @@ -466,6 +470,10 @@ _render_glyphs (cairo_gl_surface_t *dst, glBindTexture (GL_TEXTURE_2D, cache->tex); last_format = scaled_glyph->surface->format; + if (last_format == CAIRO_FORMAT_ARGB32) + *has_component_alpha = TRUE; + + /* XXX component alpha */ } if (scaled_glyph->surface_private == NULL) { @@ -545,10 +553,11 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst, cairo_surface_t *mask; cairo_status_t status; cairo_solid_pattern_t solid; + cairo_bool_t has_component_alpha; int i; mask = cairo_gl_surface_create (dst->ctx, - CAIRO_CONTENT_ALPHA, + CAIRO_CONTENT_COLOR_ALPHA, glyph_extents->width, glyph_extents->height); if (unlikely (mask->status)) @@ -559,15 +568,17 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst, glyphs[i].y -= glyph_extents->y; } - _cairo_pattern_init_solid (&solid, CAIRO_COLOR_WHITE, CAIRO_CONTENT_ALPHA); + _cairo_pattern_init_solid (&solid, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR_ALPHA); status = _render_glyphs ((cairo_gl_surface_t *) mask, 0, 0, - CAIRO_OPERATOR_ADD, &solid.base, + CAIRO_OPERATOR_SOURCE, &solid.base, glyphs, num_glyphs, glyph_extents, - scaled_font, NULL, remaining_glyphs); + scaled_font, &has_component_alpha, + NULL, remaining_glyphs); if (likely (status == CAIRO_STATUS_SUCCESS)) { cairo_surface_pattern_t mask_pattern; _cairo_pattern_init_for_surface (&mask_pattern, mask); + mask_pattern.base.has_component_alpha = has_component_alpha; cairo_matrix_init_translate (&mask_pattern.base.matrix, -glyph_extents->x, -glyph_extents->y); status = _cairo_surface_mask (&dst->base, op, @@ -601,6 +612,7 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst, cairo_region_t *clip_region = NULL; cairo_solid_pattern_t solid_pattern; cairo_bool_t overlap, use_mask = FALSE; + cairo_bool_t has_component_alpha; cairo_status_t status; if (! GLEW_ARB_vertex_buffer_object) @@ -712,7 +724,8 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst, return _render_glyphs (dst, extents.x, extents.y, op, source, glyphs, num_glyphs, &extents, - scaled_font, clip_region, remaining_glyphs); + scaled_font, &has_component_alpha, + clip_region, remaining_glyphs); EMPTY: *remaining_glyphs = 0; diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c index 29bf950d..07b6d4d3 100644 --- a/src/cairo-gl-surface.c +++ b/src/cairo-gl-surface.c @@ -1004,6 +1004,7 @@ _cairo_gl_pattern_surface_texture_setup (cairo_gl_composite_operand_t *operand, operand->operand.texture.tex = gl_surface->tex; operand->operand.texture.surface = NULL; attributes->matrix = src->base.matrix; + attributes->has_component_alpha = src->base.has_component_alpha; attributes->extend = src->base.extend; attributes->filter = src->base.filter; /* Demote the filter if we're doing a 1:1 mapping of pixels. */ @@ -1257,7 +1258,7 @@ _cairo_gl_set_src_operand (cairo_gl_context_t *ctx, switch (setup->src.type) { case OPERAND_CONSTANT: _cairo_gl_set_tex_combine_constant_color (ctx, 0, - setup->src.operand.constant.color); + setup->src.operand.constant.color); break; case OPERAND_TEXTURE: _cairo_gl_set_texture_surface (0, setup->src.operand.texture.tex, @@ -1317,6 +1318,13 @@ _cairo_gl_surface_composite (cairo_operator_t op, if (! _cairo_gl_operator_is_supported (op)) return CAIRO_INT_STATUS_UNSUPPORTED; + /* XXX: There is no sane way of expressing ComponentAlpha using + * fixed-function combiners and every possible operator. Look at the + * EXA drivers for the more appropriate fallback conditions. + */ + if (mask && mask->has_component_alpha) + return CAIRO_INT_STATUS_UNSUPPORTED; + memset (&setup, 0, sizeof (setup)); status = _cairo_gl_operand_init (&setup.src, src, dst, @@ -1327,9 +1335,6 @@ _cairo_gl_surface_composite (cairo_operator_t op, return status; src_attributes = &setup.src.operand.texture.attributes; - if (mask != NULL && _cairo_pattern_is_opaque (mask)) - mask = NULL; - if (mask != NULL) { status = _cairo_gl_operand_init (&setup.mask, mask, dst, mask_x, mask_y, @@ -1352,13 +1357,13 @@ _cairo_gl_surface_composite (cairo_operator_t op, switch (setup.mask.type) { case OPERAND_CONSTANT: _cairo_gl_set_tex_combine_constant_color (ctx, 1, - setup.mask.operand.constant.color); + setup.mask.operand.constant.color); break; + case OPERAND_TEXTURE: _cairo_gl_set_texture_surface (1, setup.mask.operand.texture.tex, mask_attributes); - /* IN: dst.argb = src.argb * mask.aaaa */ glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); @@ -1368,6 +1373,7 @@ _cairo_gl_surface_composite (cairo_operator_t op, glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); + /* IN: dst.argb = src.argb * mask.aaaa */ glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB, GL_TEXTURE1); glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE1); glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_ALPHA); diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c index 7ee88d6d..86e20bc9 100644 --- a/src/cairo-gstate.c +++ b/src/cairo-gstate.c @@ -1002,17 +1002,22 @@ _cairo_gstate_mask (cairo_gstate_t *gstate, _cairo_gstate_copy_transformed_source (gstate, &source_pattern.base); _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask); - /* XXX: This optimization assumes that there is no color - * information in mask, so this will need to change if we - * support RENDER-style 4-channel masks. - */ if (source_pattern.type == CAIRO_PATTERN_TYPE_SOLID && mask_pattern.type == CAIRO_PATTERN_TYPE_SOLID) { cairo_color_t combined; - combined = source_pattern.solid.color; - _cairo_color_multiply_alpha (&combined, mask_pattern.solid.color.alpha); + if (mask_pattern.base.has_component_alpha) { +#define M(R, A, B, c) R.c = A.c * B.c + M(combined, source_pattern.solid.color, mask_pattern.solid.color, red); + M(combined, source_pattern.solid.color, mask_pattern.solid.color, green); + M(combined, source_pattern.solid.color, mask_pattern.solid.color, blue); + M(combined, source_pattern.solid.color, mask_pattern.solid.color, alpha); +#undef M + } else { + combined = source_pattern.solid.color; + _cairo_color_multiply_alpha (&combined, mask_pattern.solid.color.alpha); + } _cairo_pattern_init_solid (&source_pattern.solid, &combined, source_pattern.solid.content | diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index d4b607e1..b0a26bf9 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -931,36 +931,63 @@ _cairo_image_surface_set_filter (cairo_image_surface_t *surface, } static cairo_status_t -_cairo_image_surface_set_attributes (cairo_image_surface_t *surface, - cairo_surface_attributes_t *attributes, - double xc, double yc) +_cairo_image_surface_set_extend (cairo_image_surface_t *surface, + cairo_extend_t extend) { - cairo_int_status_t status; - - status = _cairo_image_surface_set_matrix (surface, &attributes->matrix, - xc, yc); - if (unlikely (status)) - return status; + pixman_repeat_t pixman_repeat; - switch (attributes->extend) { + switch (extend) { case CAIRO_EXTEND_NONE: - pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NONE); + pixman_repeat = PIXMAN_REPEAT_NONE; break; case CAIRO_EXTEND_REPEAT: - pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NORMAL); + pixman_repeat = PIXMAN_REPEAT_NORMAL; break; case CAIRO_EXTEND_REFLECT: - pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_REFLECT); + pixman_repeat = PIXMAN_REPEAT_REFLECT; break; case CAIRO_EXTEND_PAD: - pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_PAD); + pixman_repeat = PIXMAN_REPEAT_PAD; break; } + pixman_image_set_repeat (surface->pixman_image, pixman_repeat); + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_image_surface_set_component_alpha (cairo_image_surface_t *surface, + cairo_bool_t ca) +{ + pixman_image_set_component_alpha (surface->pixman_image, ca); + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_image_surface_set_attributes (cairo_image_surface_t *surface, + cairo_surface_attributes_t *attributes, + double xc, double yc) +{ + cairo_int_status_t status; + + status = _cairo_image_surface_set_matrix (surface, &attributes->matrix, + xc, yc); + if (unlikely (status)) + return status; + status = _cairo_image_surface_set_filter (surface, attributes->filter); if (unlikely (status)) return status; + status = _cairo_image_surface_set_extend (surface, attributes->extend); + if (unlikely (status)) + return status; + + status = _cairo_image_surface_set_component_alpha (surface, + attributes->has_component_alpha); + if (unlikely (status)) + return status; + return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index d72867a0..a566183c 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -129,6 +129,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) pattern->filter = CAIRO_FILTER_DEFAULT; + pattern->has_component_alpha = FALSE; + cairo_matrix_init_identity (&pattern->matrix); } @@ -1522,6 +1524,7 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat attr->matrix = matrix; attr->extend = pattern->base.extend; attr->filter = CAIRO_FILTER_NEAREST; + attr->has_component_alpha = pattern->base.has_component_alpha; *out = &image->base; @@ -1615,6 +1618,7 @@ _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pat cairo_matrix_init_identity (&attr->matrix); attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE; attr->filter = CAIRO_FILTER_NEAREST; + attr->has_component_alpha = pattern->base.has_component_alpha; return status; } @@ -1759,6 +1763,7 @@ NOCACHE: cairo_matrix_init_identity (&attribs->matrix); attribs->extend = CAIRO_EXTEND_REPEAT; attribs->filter = CAIRO_FILTER_NEAREST; + attribs->has_component_alpha = pattern->base.has_component_alpha; status = CAIRO_STATUS_SUCCESS; @@ -1845,6 +1850,9 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern) { const cairo_pattern_union_t *pattern; + if (abstract_pattern->has_component_alpha) + return FALSE; + pattern = (cairo_pattern_union_t *) abstract_pattern; switch (pattern->base.type) { case CAIRO_PATTERN_TYPE_SOLID: @@ -1953,6 +1961,7 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat attr->matrix = pattern->base.matrix; attr->extend = pattern->base.extend; attr->filter = _cairo_pattern_analyze_filter (&pattern->base, &pad); + attr->has_component_alpha = pattern->base.has_component_alpha; attr->x_offset = attr->y_offset = tx = ty = 0; if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) { @@ -2370,11 +2379,10 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src, /* If src and mask are both solid, then the mask alpha can be * combined into src and mask can be ignored. */ - /* XXX: This optimization assumes that there is no color - * information in mask, so this will need to change when we - * support RENDER-style 4-channel masks. */ if (src->type == CAIRO_PATTERN_TYPE_SOLID && - mask && mask->type == CAIRO_PATTERN_TYPE_SOLID) + mask && + ! mask->has_component_alpha && + mask->type == CAIRO_PATTERN_TYPE_SOLID) { cairo_color_t combined; cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src; @@ -2651,6 +2659,9 @@ _cairo_pattern_hash (const cairo_pattern_t *pattern) &pattern->filter, sizeof (pattern->filter)); hash = _cairo_hash_bytes (hash, &pattern->extend, sizeof (pattern->extend)); + hash = _cairo_hash_bytes (hash, + &pattern->has_component_alpha, + sizeof (pattern->has_component_alpha)); } switch (pattern->type) { @@ -2808,6 +2819,9 @@ _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b) if (a->type != b->type) return FALSE; + if (a->has_component_alpha != b->has_component_alpha) + return FALSE; + if (a->type != CAIRO_PATTERN_TYPE_SOLID) { if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t))) return FALSE; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 896980a8..60ebfe5e 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -5433,9 +5433,13 @@ _cairo_pdf_surface_mask (void *abstract_surface, if (_cairo_status_is_error (source_status)) return source_status; - mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask); - if (_cairo_status_is_error (mask_status)) - return mask_status; + if (mask->has_component_alpha) { + mask_status = CAIRO_INT_STATUS_UNSUPPORTED; + } else { + mask_status = _cairo_pdf_surface_analyze_operation (surface, op, mask); + if (_cairo_status_is_error (mask_status)) + return mask_status; + } return _cairo_analysis_surface_merge_status (source_status, mask_status); diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 199ad39e..179844fc 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -2169,8 +2169,10 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, } _cairo_pattern_init_for_surface (&mask_pattern, mask); - - status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, + /* Note that we only upgrade masks, i.e. A1 -> A8 -> ARGB32, so there is + * never any component alpha here. + */ + status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE, &white_pattern.base, &mask_pattern.base, new_mask, @@ -2203,6 +2205,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, _cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base); + if (mask_format == CAIRO_FORMAT_ARGB32) + glyph_pattern.base.has_component_alpha = TRUE; status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, &white_pattern.base, @@ -2222,11 +2226,9 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, } } - if (mask_format == CAIRO_FORMAT_ARGB32) { - pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)-> - pixman_image, TRUE); - } _cairo_pattern_init_for_surface (&mask_pattern, mask); + if (mask_format == CAIRO_FORMAT_ARGB32) + mask_pattern.base.has_component_alpha = TRUE; status = _cairo_surface_composite (op, pattern, &mask_pattern.base, surface, diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 26ae3d9d..6277af18 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -2262,9 +2262,13 @@ _cairo_svg_surface_mask (void *abstract_surface, if (_cairo_status_is_error (source_status)) return source_status; - mask_status = _cairo_svg_surface_analyze_operation (surface, op, mask); - if (_cairo_status_is_error (mask_status)) - return mask_status; + if (mask->has_component_alpha) { + mask_status = CAIRO_INT_STATUS_UNSUPPORTED; + } else { + mask_status = _cairo_svg_surface_analyze_operation (surface, op, mask); + if (_cairo_status_is_error (mask_status)) + return mask_status; + } return _cairo_analysis_surface_merge_status (source_status, mask_status); diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h index 82754cff..16b27c25 100644 --- a/src/cairo-types-private.h +++ b/src/cairo-types-private.h @@ -340,4 +340,75 @@ struct _cairo_mime_data { void *closure; }; +struct _cairo_pattern { + cairo_pattern_type_t type; + cairo_reference_count_t ref_count; + cairo_status_t status; + cairo_user_data_array_t user_data; + + cairo_matrix_t matrix; + cairo_filter_t filter; + cairo_extend_t extend; + + cairo_bool_t has_component_alpha; +}; + +struct _cairo_solid_pattern { + cairo_pattern_t base; + cairo_color_t color; + cairo_content_t content; +}; + +typedef struct _cairo_surface_pattern { + cairo_pattern_t base; + + cairo_surface_t *surface; +} cairo_surface_pattern_t; + +typedef struct _cairo_gradient_stop { + double offset; + cairo_color_t color; +} cairo_gradient_stop_t; + +typedef struct _cairo_gradient_pattern { + cairo_pattern_t base; + + unsigned int n_stops; + unsigned int stops_size; + cairo_gradient_stop_t *stops; + cairo_gradient_stop_t stops_embedded[2]; +} cairo_gradient_pattern_t; + +typedef struct _cairo_linear_pattern { + cairo_gradient_pattern_t base; + + cairo_point_t p1; + cairo_point_t p2; +} cairo_linear_pattern_t; + +typedef struct _cairo_radial_pattern { + cairo_gradient_pattern_t base; + + cairo_point_t c1; + cairo_fixed_t r1; + cairo_point_t c2; + cairo_fixed_t r2; +} cairo_radial_pattern_t; + +typedef union { + cairo_gradient_pattern_t base; + + cairo_linear_pattern_t linear; + cairo_radial_pattern_t radial; +} cairo_gradient_pattern_union_t; + +typedef union { + cairo_pattern_type_t type; + cairo_pattern_t base; + + cairo_solid_pattern_t solid; + cairo_surface_pattern_t surface; + cairo_gradient_pattern_union_t gradient; +} cairo_pattern_union_t; + #endif /* CAIRO_TYPES_PRIVATE_H */ diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index 216c7513..7a86cc8c 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1437,10 +1437,6 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font, _invert_argb32_mask (tmp_surface); mask_surface = &tmp_surface->base; - - /* XXX: Hacky, should expose this in cairo_image_surface */ - pixman_image_set_component_alpha (((cairo_image_surface_t *)tmp_surface->image)->pixman_image, TRUE); - } else { mask_surface = _compute_a8_mask (tmp_surface); cairo_surface_destroy (&tmp_surface->base); @@ -1454,6 +1450,10 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font, * destination */ _cairo_pattern_init_for_surface (&mask, mask_surface); + cairo_surface_destroy (mask_surface); + + if (scaled_font->quality == CLEARTYPE_QUALITY) + mask.base.has_component_alpha = TRUE; status = _cairo_surface_composite (op, pattern, &mask.base, @@ -1466,8 +1466,6 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font, _cairo_pattern_fini (&mask.base); - cairo_surface_destroy (mask_surface); - return status; } } diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h index 92107e7f..b30848d5 100644 --- a/src/cairo-xlib-surface-private.h +++ b/src/cairo-xlib-surface-private.h @@ -95,6 +95,7 @@ struct _cairo_xlib_surface { XRenderPictFormat *xrender_format; cairo_filter_t filter; cairo_extend_t extend; + cairo_bool_t has_component_alpha; XTransform xtransform; uint32_t a_mask; diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 994a4f9d..8965373e 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -1539,11 +1539,11 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, } static cairo_status_t -_cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, - cairo_extend_t extend) +_cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, + cairo_extend_t extend, + unsigned long *mask, + XRenderPictureAttributes *pa) { - XRenderPictureAttributes pa; - unsigned long mask; int repeat; if (surface->extend == extend) @@ -1573,12 +1573,26 @@ _cairo_xlib_surface_set_repeat (cairo_xlib_surface_t *surface, return CAIRO_INT_STATUS_UNSUPPORTED; } - mask = CPRepeat; - pa.repeat = repeat; + *mask |= CPRepeat; + pa->repeat = repeat; - XRenderChangePicture (surface->dpy, surface->src_picture, mask, &pa); surface->extend = extend; + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_xlib_surface_set_component_alpha (cairo_xlib_surface_t *surface, + cairo_bool_t ca, + unsigned long *mask, + XRenderPictureAttributes *pa) +{ + if (surface->has_component_alpha == ca) + return CAIRO_STATUS_SUCCESS; + *mask |= CPComponentAlpha; + pa->component_alpha = ca; + + surface->has_component_alpha = ca; return CAIRO_STATUS_SUCCESS; } @@ -1589,6 +1603,8 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, double yc) { cairo_int_status_t status; + XRenderPictureAttributes pa; + unsigned long mask = 0; _cairo_xlib_surface_ensure_src_picture (surface); @@ -1597,7 +1613,14 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, if (unlikely (status)) return status; - status = _cairo_xlib_surface_set_repeat (surface, attributes->extend); + status = _cairo_xlib_surface_set_repeat (surface, attributes->extend, + &mask, &pa); + if (unlikely (status)) + return status; + + status = _cairo_xlib_surface_set_component_alpha (surface, + attributes->has_component_alpha, + &mask, &pa); if (unlikely (status)) return status; @@ -1605,6 +1628,9 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, if (unlikely (status)) return status; + if (mask) + XRenderChangePicture (surface->dpy, surface->src_picture, mask, &pa); + return CAIRO_STATUS_SUCCESS; } @@ -2946,6 +2972,7 @@ found: surface->depth = depth; surface->filter = CAIRO_FILTER_NEAREST; surface->extend = CAIRO_EXTEND_NONE; + surface->has_component_alpha = FALSE; surface->xtransform = identity; surface->clip_region = NULL; diff --git a/src/cairoint.h b/src/cairoint.h index fc1046e3..c309f3db 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -871,81 +871,14 @@ extern const cairo_private cairo_surface_backend_t _cairo_image_surface_backend; #define CAIRO_EXTEND_GRADIENT_DEFAULT CAIRO_EXTEND_PAD #define CAIRO_FILTER_DEFAULT CAIRO_FILTER_GOOD -struct _cairo_pattern { - cairo_pattern_type_t type; - cairo_reference_count_t ref_count; - cairo_status_t status; - cairo_user_data_array_t user_data; - - cairo_matrix_t matrix; - cairo_filter_t filter; - cairo_extend_t extend; -}; - -struct _cairo_solid_pattern { - cairo_pattern_t base; - cairo_color_t color; - cairo_content_t content; -}; - extern const cairo_private cairo_solid_pattern_t _cairo_pattern_black; -typedef struct _cairo_surface_pattern { - cairo_pattern_t base; - - cairo_surface_t *surface; -} cairo_surface_pattern_t; - -typedef struct _cairo_gradient_stop { - double offset; - cairo_color_t color; -} cairo_gradient_stop_t; - -typedef struct _cairo_gradient_pattern { - cairo_pattern_t base; - - unsigned int n_stops; - unsigned int stops_size; - cairo_gradient_stop_t *stops; - cairo_gradient_stop_t stops_embedded[2]; -} cairo_gradient_pattern_t; - -typedef struct _cairo_linear_pattern { - cairo_gradient_pattern_t base; - - cairo_point_t p1; - cairo_point_t p2; -} cairo_linear_pattern_t; - -typedef struct _cairo_radial_pattern { - cairo_gradient_pattern_t base; - - cairo_point_t c1; - cairo_fixed_t r1; - cairo_point_t c2; - cairo_fixed_t r2; -} cairo_radial_pattern_t; - -typedef union { - cairo_gradient_pattern_t base; - - cairo_linear_pattern_t linear; - cairo_radial_pattern_t radial; -} cairo_gradient_pattern_union_t; - -typedef union { - cairo_pattern_type_t type; - cairo_pattern_t base; - - cairo_solid_pattern_t solid; - cairo_surface_pattern_t surface; - cairo_gradient_pattern_union_t gradient; -} cairo_pattern_union_t; typedef struct _cairo_surface_attributes { cairo_matrix_t matrix; cairo_extend_t extend; cairo_filter_t filter; + cairo_bool_t has_component_alpha; int x_offset; int y_offset; void *extra; |