[cairo] [PATCH] [API] Support component-alpha.
Chris Wilson
chris at chris-wilson.co.uk
Wed Oct 14 16:47:09 PDT 2009
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.
So we need component-alpha support on patterns internally, so present
the same power to the users as well. For indeed, they may well be
dreaming of demonstrating sub-pixel geometry masks...
[This patch is hastily written and requires testing.]
---
src/cairo-ft-font.c | 5 ---
src/cairo-gl-surface.c | 45 ++++++++++++++++++++---------
src/cairo-gstate.c | 7 +---
src/cairo-image-surface.c | 58 ++++++++++++++++++++++++++++----------
src/cairo-pattern.c | 56 ++++++++++++++++++++++++++++++++++--
src/cairo-scaled-font.c | 11 ++++---
src/cairo-types-private.h | 1 +
src/cairo-win32-font.c | 10 ++----
src/cairo-xlib-surface-private.h | 1 +
src/cairo-xlib-surface.c | 43 +++++++++++++++++++++++-----
src/cairo.h | 22 ++++++++++++++
src/cairoint.h | 1 +
12 files changed, 198 insertions(+), 62 deletions(-)
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 1c5edc1..02ab6cc 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -803,7 +803,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;
@@ -971,7 +970,6 @@ _get_bitmap_surface (FT_Bitmap *bitmap,
data = data_rgba;
stride = stride_rgba;
format = CAIRO_FORMAT_ARGB32;
- subpixel = TRUE;
break;
}
}
@@ -994,9 +992,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-surface.c b/src/cairo-gl-surface.c
index 8ebfbc0..39c8fcc 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1342,20 +1342,37 @@ _cairo_gl_surface_composite (cairo_operator_t op,
_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);
-
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_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);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ if (mask_attributes.component_alpha == CAIRO_SINGLE_ALPHA) {
+ /* 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);
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_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);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ } else {
+ /* IN: dst.argb = src.argb * mask.argb */
+ 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);
+
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_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_COLOR);
+ glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
+ }
break;
}
}
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 6f58bcf..98e2205 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -999,12 +999,9 @@ _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)
+ mask_pattern.type == CAIRO_PATTERN_TYPE_SOLID &&
+ mask_pattern.base.component_alpha == CAIRO_SINGLE_ALPHA)
{
cairo_color_t combined;
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 49ce7a5..06d9f3e 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -927,33 +927,61 @@ _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;
}
- status = _cairo_image_surface_set_filter (surface, attributes->filter);
+ 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_component_alpha_t ca)
+{
+ pixman_image_set_component_alpha (surface->pixman_image,
+ ca != CAIRO_SINGLE_ALPHA);
+ 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->extend);
+ 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->component_alpha);
if (unlikely (status))
return status;
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 1888d83..7a8e8b0 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -130,6 +130,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
pattern->filter = CAIRO_FILTER_DEFAULT;
+ pattern->component_alpha = CAIRO_SINGLE_ALPHA;
+
cairo_matrix_init_identity (&pattern->matrix);
}
@@ -1523,6 +1525,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->component_alpha = pattern->base.component_alpha;
*out = &image->base;
@@ -1619,6 +1622,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->component_alpha = pattern->base.component_alpha;
return status;
}
@@ -1763,6 +1767,7 @@ NOCACHE:
cairo_matrix_init_identity (&attribs->matrix);
attribs->extend = CAIRO_EXTEND_REPEAT;
attribs->filter = CAIRO_FILTER_NEAREST;
+ attribs->component_alpha = pattern->base.component_alpha;
status = CAIRO_STATUS_SUCCESS;
@@ -1849,6 +1854,9 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
{
const cairo_pattern_union_t *pattern;
+ if (abstract_pattern->component_alpha)
+ return FALSE;
+
pattern = (cairo_pattern_union_t *) abstract_pattern;
switch (pattern->base.type) {
case CAIRO_PATTERN_TYPE_SOLID:
@@ -1958,6 +1966,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->component_alpha = pattern->base.component_alpha;
attr->x_offset = attr->y_offset = tx = ty = 0;
if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
@@ -2378,11 +2387,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->component_alpha == CAIRO_SINGLE_ALPHA &&
+ mask->type == CAIRO_PATTERN_TYPE_SOLID)
{
cairo_color_t combined;
cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
@@ -2648,6 +2656,8 @@ _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->component_alpha, sizeof (pattern->component_alpha));
}
switch (pattern->type) {
@@ -2799,6 +2809,9 @@ _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
if (a->type != b->type)
return FALSE;
+ if (a->component_alpha != b->component_alpha)
+ return FALSE;
+
if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
return FALSE;
@@ -3079,6 +3092,41 @@ cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
return CAIRO_STATUS_SUCCESS;
}
+/**
+ * cairo_pattern_set_component_alpha:
+ * @pattern: a #cairo_pattern_t
+ * @value: Enable use of per-component alpha mask?
+ *
+ * When used as a mask a pattern with content CAIRO_CONTENT_COLOR,
+ * i.e. a pattern with red, green, blue components as well as an
+ * alpha component (which may be implicitly 1) the value used for the
+ * mask may either be per-component or the single alpha value.
+ *
+ * The default is to use the single alpha channel for masking. Using
+ * per-component alpha may be used in conjunction with sub-pixel
+ * antialiasing to improve clarity on pixellated displays, e.g. LCDs.
+ *
+ * Since: 1.10
+ **/
+void
+cairo_pattern_set_component_alpha (cairo_pattern_t *pattern,
+ cairo_component_alpha_t ca)
+{
+ if (unlikely (pattern->status))
+ return;
+
+ pattern->component_alpha = ca;
+}
+
+cairo_component_alpha_t
+cairo_pattern_get_component_alpha (cairo_pattern_t *pattern)
+{
+ if (unlikely (pattern->status))
+ return CAIRO_SINGLE_ALPHA;
+
+ return pattern->component_alpha;
+}
+
void
_cairo_pattern_reset_static_data (void)
{
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 48451a6..357ce46 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2170,6 +2170,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
}
_cairo_pattern_init_for_surface (&mask_pattern, mask);
+ if (mask_format == CAIRO_FORMAT_ARGB32)
+ mask_pattern.base.component_alpha = CAIRO_COMPONENT_ALPHA;
status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
&white_pattern.base,
@@ -2204,6 +2206,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.component_alpha = CAIRO_COMPONENT_ALPHA;
status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
&white_pattern.base,
@@ -2223,12 +2227,9 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
}
}
- /* XXX ComponentAlpha needs to be a cairo pattern property! */
- 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.component_alpha = CAIRO_COMPONENT_ALPHA;
status = _cairo_surface_composite (op, pattern, &mask_pattern.base,
surface,
diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h
index 068c261..0e216f3 100644
--- a/src/cairo-types-private.h
+++ b/src/cairo-types-private.h
@@ -350,6 +350,7 @@ struct _cairo_pattern {
cairo_matrix_t matrix;
cairo_filter_t filter;
cairo_extend_t extend;
+ cairo_component_alpha_t component_alpha;
};
struct _cairo_solid_pattern {
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 71bad77..8e9e44d 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1438,10 +1438,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);
@@ -1455,6 +1451,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.component_alpha = CAIRO_COMPONENT_ALPHA;
status = _cairo_surface_composite (op, pattern,
&mask.base,
@@ -1467,8 +1467,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 92107e7..b40ee59 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_component_alpha_t component_alpha;
XTransform xtransform;
uint32_t a_mask;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index f3ebc9d..91e4113 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1549,11 +1549,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)
@@ -1583,12 +1583,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_component_alpha_t ca,
+ unsigned long *mask,
+ XRenderPictureAttributes *pa)
+{
+ if (surface->component_alpha == ca)
+ return CAIRO_STATUS_SUCCESS;
+ *mask |= CPComponentAlpha;
+ pa->component_alpha = !! ca;
+
+ surface->component_alpha = ca;
return CAIRO_STATUS_SUCCESS;
}
@@ -1599,6 +1613,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);
@@ -1607,7 +1623,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->component_alpha,
+ &mask, &pa);
if (unlikely (status))
return status;
@@ -1615,6 +1638,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;
}
@@ -2969,6 +2995,7 @@ found:
surface->depth = depth;
surface->filter = CAIRO_FILTER_NEAREST;
surface->extend = CAIRO_EXTEND_NONE;
+ surface->component_alpha = CAIRO_SINGLE_ALPHA;
surface->xtransform = identity;
surface->clip_region = NULL;
diff --git a/src/cairo.h b/src/cairo.h
index c239dea..a91c824 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -2374,6 +2374,28 @@ cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter);
cairo_public cairo_filter_t
cairo_pattern_get_filter (cairo_pattern_t *pattern);
+/**
+ * cairo_component_alpha_t:
+ * @CAIRO_SINGLE_ALPHA: Use the alpha component when masking
+ * @CAIRO_COMPONENT_ALPHA: Use the component value when masking
+ *
+ * #cairo_component_alpha_t is used to indicate which channel to use
+ * when masking with the pattern. See cairo_pattern_set_component_alpha()
+ * for how this affects masking with a particular pattern.
+ */
+typedef enum cairo_component_alpha {
+ CAIRO_SINGLE_ALPHA = 0,
+ CAIRO_COMPONENT_ALPHA,
+} cairo_component_alpha_t;
+
+cairo_public void
+cairo_pattern_set_component_alpha (cairo_pattern_t *pattern,
+ cairo_component_alpha_t ca);
+
+cairo_public cairo_component_alpha_t
+cairo_pattern_get_component_alpha (cairo_pattern_t *pattern);
+
+
cairo_public cairo_status_t
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
double *red, double *green,
diff --git a/src/cairoint.h b/src/cairoint.h
index 8706488..464cf33 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -874,6 +874,7 @@ typedef struct _cairo_surface_attributes {
cairo_matrix_t matrix;
cairo_extend_t extend;
cairo_filter_t filter;
+ cairo_component_alpha_t component_alpha;
int x_offset;
int y_offset;
void *extra;
--
1.6.4.3
More information about the cairo
mailing list