mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 09:58:12 +02:00
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:
parent
f0cd20e6ce
commit
df357f26ff
14 changed files with 235 additions and 135 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 |
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue