[cairo-commit] 7 commits - src/cairo.c src/cairo-color.c src/cairo-gl-glyphs.c src/cairo-gl-private.h src/cairo-gl-surface.c src/cairo-gstate.c src/cairo-image-surface.c test/Makefile.sources test/zero-mask.c test/zero-mask.ref.png test/zero-mask.rgb24.ref.png
Benjamin Otte
company at kemper.freedesktop.org
Thu May 13 03:14:23 PDT 2010
src/cairo-color.c | 10 +-
src/cairo-gl-glyphs.c | 36 +------
src/cairo-gl-private.h | 1
src/cairo-gl-surface.c | 4
src/cairo-gstate.c | 15 +++
src/cairo-image-surface.c | 2
src/cairo.c | 3
test/Makefile.sources | 3
test/zero-mask.c | 199 +++++++++++++++++++++++++++++++++++++++++++
test/zero-mask.ref.png |binary
test/zero-mask.rgb24.ref.png |binary
11 files changed, 239 insertions(+), 34 deletions(-)
New commits:
commit c69143e3f9c95ab3937a7efb8e4de170c4edb648
Author: Benjamin Otte <otte at redhat.com>
Date: Wed May 12 21:14:36 2010 +0200
gl: Don't keep a temporary surface in the device
We get circular references that way.
If it turns out later such a cache is critical, we'll need to invent a
way to avoid circling references. For now, just pretend it's not
important.
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index f283f56..217f4fb 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -672,32 +672,13 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
return status;
/* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */
- mask = NULL;
- if (ctx->glyphs_temporary_mask) {
- if (glyph_extents->width <= ctx->glyphs_temporary_mask->width &&
- glyph_extents->height <= ctx->glyphs_temporary_mask->height)
- {
- status = _cairo_gl_surface_clear (ctx->glyphs_temporary_mask);
- if (unlikely (status)) {
- _cairo_gl_context_release (ctx);
- return status;
- }
-
- mask = &ctx->glyphs_temporary_mask->base;
- } else {
- cairo_surface_destroy (&ctx->glyphs_temporary_mask->base);
- ctx->glyphs_temporary_mask = NULL;
- }
- }
- if (mask == NULL) {
- mask = cairo_gl_surface_create (dst->base.device,
- CAIRO_CONTENT_COLOR_ALPHA,
- glyph_extents->width,
- glyph_extents->height);
- if (unlikely (mask->status)) {
- _cairo_gl_context_release (ctx);
- return mask->status;
- }
+ mask = cairo_gl_surface_create (dst->base.device,
+ CAIRO_CONTENT_COLOR_ALPHA,
+ glyph_extents->width,
+ glyph_extents->height);
+ if (unlikely (mask->status)) {
+ _cairo_gl_context_release (ctx);
+ return mask->status;
}
for (i = 0; i < num_glyphs; i++) {
@@ -730,8 +711,7 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
*remaining_glyphs = num_glyphs;
}
- if (ctx->glyphs_temporary_mask == NULL)
- ctx->glyphs_temporary_mask = (cairo_gl_surface_t *) mask;
+ cairo_surface_destroy (mask);
_cairo_gl_context_release (ctx);
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 15e5466..83836e7 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -135,7 +135,6 @@ typedef struct _cairo_gl_context {
[CAIRO_GL_SHADER_IN_COUNT];
cairo_gl_surface_t *current_target;
- cairo_gl_surface_t *glyphs_temporary_mask;
cairo_gl_glyph_cache_t glyph_cache[2];
cairo_list_t fonts;
commit ec1ca17b71b41159ea8754d42954863b62623536
Author: Benjamin Otte <otte at redhat.com>
Date: Thu May 13 12:07:53 2010 +0200
gl: Don't create 0x0 surfaces
We get a very annoyed libGL if we try to create 0x0 textures, so we
return an image surface instead.
Tested by the zero-mask test.
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 27fc02c..eb2e91b 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -535,6 +535,10 @@ _cairo_gl_surface_create_similar (void *abstract_surface,
cairo_gl_context_t *ctx;
cairo_status_t status;
+ if (width < 1 || height < 1)
+ return cairo_image_surface_create (_cairo_format_from_content (content),
+ width, height);
+
status = _cairo_gl_context_acquire (surface->device, &ctx);
if (unlikely (status))
return _cairo_surface_create_in_error (status);
commit 108e3f5031fc16843197382af78af299b19ef290
Author: Benjamin Otte <otte at redhat.com>
Date: Thu May 13 12:01:39 2010 +0200
Use a solid color for 0xN and Nx0 surfaces
This gets around the need to check for 0-sized surfaces in the backends.
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 0012558..459df3b 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -860,7 +860,22 @@ _cairo_gstate_copy_pattern (cairo_pattern_t *pattern,
*/
switch (original->type) {
case CAIRO_PATTERN_TYPE_SOLID:
+ break;
+
case CAIRO_PATTERN_TYPE_SURFACE:
+ {
+ cairo_surface_pattern_t *surface = (cairo_surface_pattern_t *) original;
+ cairo_rectangle_int_t extents;
+
+ if (_cairo_surface_get_extents (surface->surface, &extents) &&
+ (extents.width == 0 || extents.height == 0)) {
+ _cairo_pattern_init_solid ((cairo_solid_pattern_t *) pattern,
+ CAIRO_COLOR_TRANSPARENT,
+ surface->surface->content);
+
+ return;
+ }
+ }
break;
case CAIRO_PATTERN_TYPE_LINEAR:
commit 18c963824ebbb0e7054e682ecb5664a282a58552
Author: Benjamin Otte <otte at redhat.com>
Date: Thu May 13 11:56:22 2010 +0200
Make _cairo_color_equal() work for unmultiplied colors, too
Color stop colors are unmultiplied, and we use it there.
diff --git a/src/cairo-color.c b/src/cairo-color.c
index ddba5ca..9483c8b 100644
--- a/src/cairo-color.c
+++ b/src/cairo-color.c
@@ -162,6 +162,7 @@ _cairo_color_get_rgba_premultiplied (cairo_color_t *color,
*alpha = color->alpha;
}
+/* NB: This function works both for unmultiplied and premultiplied colors */
cairo_bool_t
_cairo_color_equal (const cairo_color_t *color_a,
const cairo_color_t *color_b)
@@ -169,10 +170,15 @@ _cairo_color_equal (const cairo_color_t *color_a,
if (color_a == color_b)
return TRUE;
+ if (color_a->alpha_short != color_b->alpha_short)
+ return FALSE;
+
+ if (color_a->alpha_short == 0)
+ return TRUE;
+
return color_a->red_short == color_b->red_short &&
color_a->green_short == color_b->green_short &&
- color_a->blue_short == color_b->blue_short &&
- color_a->alpha_short == color_b->alpha_short;
+ color_a->blue_short == color_b->blue_short;
}
cairo_bool_t
commit 7bd8d0db1f4ac448c93d6d342726f64a0d6300e3
Author: Benjamin Otte <otte at redhat.com>
Date: Thu May 13 11:23:33 2010 +0200
image: Fix wholly unbounded fixup
Tested by zero-mask test.
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index b98d108..4e2388c 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -1662,7 +1662,7 @@ _cairo_image_surface_fixup_unbounded (cairo_image_surface_t *dst,
width, height);
} else {
pixman_color_t color = { 0, };
- pixman_box32_t box = { x, y, width, height };
+ pixman_box32_t box = { x, y, x + width, y + height };
if (! pixman_image_fill_boxes (PIXMAN_OP_CLEAR,
dst->pixman_image,
commit 8aa50b5a7873b8317d0593105497607dbb2fae1d
Author: Benjamin Otte <otte at redhat.com>
Date: Thu May 13 10:27:37 2010 +0200
cairo_paint_with_alpha(cr, 0.0) is only a noop when bounded by mask
diff --git a/src/cairo.c b/src/cairo.c
index 0070f98..7ddfd84 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -2139,7 +2139,8 @@ cairo_paint_with_alpha (cairo_t *cr,
return;
}
- if (CAIRO_ALPHA_IS_ZERO (alpha)) {
+ if (CAIRO_ALPHA_IS_ZERO (alpha) &&
+ _cairo_operator_bounded_by_mask (cr->gstate->op)) {
return;
}
commit ee32dfb3de035e73cb8c2073c0826daf244e3845
Author: Benjamin Otte <otte at redhat.com>
Date: Thu May 13 10:04:49 2010 +0200
test: Add a test for various zero mask operations
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 1464516..cf03fcc 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -269,7 +269,8 @@ test_sources = \
user-font-rescale.c \
xcomposite-projection.c \
xlib-expose-event.c \
- zero-alpha.c
+ zero-alpha.c \
+ zero-mask.c
pthread_test_sources = \
pthread-same-source.c \
diff --git a/test/zero-mask.c b/test/zero-mask.c
new file mode 100644
index 0000000..b1458b3
--- /dev/null
+++ b/test/zero-mask.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright © 2010 Red Hat, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Benjamin Otte <otte at gnome.org>
+ */
+
+#include "cairo-test.h"
+
+#define RECT 10
+#define SPACE 5
+
+static void
+paint_with_alpha (cairo_t *cr)
+{
+ cairo_paint_with_alpha (cr, 0.0);
+}
+
+static void
+mask_with_solid (cairo_t *cr)
+{
+ cairo_pattern_t *pattern = cairo_pattern_create_rgba (1, 0, 0, 0);
+
+ cairo_mask (cr, pattern);
+
+ cairo_pattern_destroy (pattern);
+}
+
+static void
+mask_with_empty_gradient (cairo_t *cr)
+{
+ cairo_pattern_t *pattern = cairo_pattern_create_linear (1, 2, 3, 4);
+
+ cairo_mask (cr, pattern);
+
+ cairo_pattern_destroy (pattern);
+}
+
+static void
+mask_with_gradient (cairo_t *cr)
+{
+ cairo_pattern_t *pattern = cairo_pattern_create_radial (1, 2, 3, 4, 5, 6);
+
+ cairo_pattern_add_color_stop_rgba (pattern, 0, 1, 0, 0, 0);
+ cairo_pattern_add_color_stop_rgba (pattern, 0, 0, 0, 1, 0);
+
+ cairo_mask (cr, pattern);
+
+ cairo_pattern_destroy (pattern);
+}
+
+static void
+mask_with_surface (cairo_t *cr)
+{
+ cairo_surface_t *surface = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ RECT,
+ RECT);
+
+ cairo_mask_surface (cr, surface, 0, 0);
+
+ cairo_surface_destroy (surface);
+}
+
+static void
+mask_with_alpha_surface (cairo_t *cr)
+{
+ cairo_surface_t *surface = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_ALPHA,
+ RECT / 2,
+ RECT / 2);
+ cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT);
+
+ cairo_mask (cr, pattern);
+
+ cairo_pattern_destroy (pattern);
+ cairo_surface_destroy (surface);
+}
+
+static void
+mask_with_nonclear_surface (cairo_t *cr)
+{
+ static unsigned char data[8 * 4] = { 0, };
+ cairo_surface_t *surface = cairo_image_surface_create_for_data (data,
+ CAIRO_FORMAT_A1,
+ 16, 8, 4);
+
+ cairo_mask_surface (cr, surface, 0, 0);
+
+ cairo_surface_destroy (surface);
+}
+
+static void
+mask_with_0x0_surface (cairo_t *cr)
+{
+ cairo_surface_t *surface = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ 0, 0);
+
+ cairo_mask_surface (cr, surface, 0, 0);
+
+ cairo_surface_destroy (surface);
+}
+
+static void
+mask_with_extend_none (cairo_t *cr)
+{
+ cairo_surface_t *surface = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ RECT,
+ RECT);
+
+ cairo_mask_surface (cr, surface, 2 * RECT, 2 * RECT);
+
+ cairo_surface_destroy (surface);
+}
+
+#define ARRAY_LENGTH(array) (sizeof (array) / sizeof ((array)[0]))
+
+typedef void (* mask_func_t) (cairo_t *);
+
+mask_func_t mask_funcs[] = {
+ paint_with_alpha,
+ mask_with_solid,
+ mask_with_empty_gradient,
+ mask_with_gradient,
+ mask_with_surface,
+ mask_with_alpha_surface,
+ mask_with_nonclear_surface,
+ mask_with_0x0_surface,
+ mask_with_extend_none
+};
+
+cairo_operator_t operators[] = {
+ CAIRO_OPERATOR_CLEAR,
+ CAIRO_OPERATOR_SOURCE,
+ CAIRO_OPERATOR_OVER,
+ CAIRO_OPERATOR_IN,
+ CAIRO_OPERATOR_DEST_ATOP,
+ CAIRO_OPERATOR_SATURATE,
+ CAIRO_OPERATOR_MULTIPLY
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ unsigned int i, op;
+
+ /* 565-compatible gray background */
+ cairo_set_source_rgb (cr, 0.51613, 0.55555, 0.51613);
+ cairo_paint (cr);
+
+ cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); /* green */
+ /* mask with zero-alpha in several ways */
+
+ cairo_translate (cr, SPACE, SPACE);
+
+ for (op = 0; op < ARRAY_LENGTH (operators); op++) {
+ cairo_set_operator (cr, operators[op]);
+
+ for (i = 0; i < ARRAY_LENGTH (mask_funcs); i++) {
+ cairo_save (cr);
+ cairo_translate (cr, i * (RECT + SPACE), op * (RECT + SPACE));
+ cairo_rectangle (cr, 0, 0, RECT, RECT);
+ cairo_clip (cr);
+ mask_funcs[i] (cr);
+ cairo_restore (cr);
+ }
+ }
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (zero_mask,
+ "Testing that masking with zero alpha works",
+ "alpha, mask", /* keywords */
+ NULL, /* requirements */
+ SPACE + (RECT + SPACE) * ARRAY_LENGTH (mask_funcs),
+ SPACE + (RECT + SPACE) * ARRAY_LENGTH (operators),
+ NULL, draw)
diff --git a/test/zero-mask.ref.png b/test/zero-mask.ref.png
new file mode 100644
index 0000000..ffae8d9
Binary files /dev/null and b/test/zero-mask.ref.png differ
diff --git a/test/zero-mask.rgb24.ref.png b/test/zero-mask.rgb24.ref.png
new file mode 100644
index 0000000..263c3d1
Binary files /dev/null and b/test/zero-mask.rgb24.ref.png differ
More information about the cairo-commit
mailing list