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.
This commit is contained in:
Chris Wilson 2009-10-16 16:48:54 +01:00
parent f0cd20e6ce
commit df357f26ff
14 changed files with 235 additions and 135 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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 |

View file

@ -930,6 +930,39 @@ _cairo_image_surface_set_filter (cairo_image_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_image_surface_set_extend (cairo_image_surface_t *surface,
cairo_extend_t extend)
{
pixman_repeat_t pixman_repeat;
switch (extend) {
case CAIRO_EXTEND_NONE:
pixman_repeat = PIXMAN_REPEAT_NONE;
break;
case CAIRO_EXTEND_REPEAT:
pixman_repeat = PIXMAN_REPEAT_NORMAL;
break;
case CAIRO_EXTEND_REFLECT:
pixman_repeat = PIXMAN_REPEAT_REFLECT;
break;
case CAIRO_EXTEND_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,
@ -942,25 +975,19 @@ _cairo_image_surface_set_attributes (cairo_image_surface_t *surface,
if (unlikely (status))
return status;
switch (attributes->extend) {
case CAIRO_EXTEND_NONE:
pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NONE);
break;
case CAIRO_EXTEND_REPEAT:
pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NORMAL);
break;
case CAIRO_EXTEND_REFLECT:
pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_REFLECT);
break;
case CAIRO_EXTEND_PAD:
pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_PAD);
break;
}
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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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,

View file

@ -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);

View file

@ -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 */

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;