summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-10-16 16:48:54 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-10-21 11:37:16 +0100
commitdf357f26ff72571acb840715efa4930054d4fdbe (patch)
tree66e9174c24c52564a5d691a21653c8b31a3b7156
parentf0cd20e6cec445eb627c2708c2230c8bad1b64ce (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.c5
-rw-r--r--src/cairo-gl-glyphs.c23
-rw-r--r--src/cairo-gl-surface.c18
-rw-r--r--src/cairo-gstate.c17
-rw-r--r--src/cairo-image-surface.c55
-rw-r--r--src/cairo-pattern.c22
-rw-r--r--src/cairo-pdf-surface.c10
-rw-r--r--src/cairo-scaled-font.c14
-rw-r--r--src/cairo-svg-surface.c10
-rw-r--r--src/cairo-types-private.h71
-rw-r--r--src/cairo-win32-font.c10
-rw-r--r--src/cairo-xlib-surface-private.h1
-rw-r--r--src/cairo-xlib-surface.c43
-rw-r--r--src/cairoint.h69
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;