[cairo-commit] src/cairo-image-surface.c src/cairoint.h src/cairo-scaled-font.c
Behdad Esfahbod
behdad at kemper.freedesktop.org
Mon Jan 14 13:14:24 PST 2008
src/cairo-image-surface.c | 18 +++++++++++++++
src/cairo-scaled-font.c | 54 +++++++++++++++++++++++++---------------------
src/cairoint.h | 3 ++
3 files changed, 51 insertions(+), 24 deletions(-)
New commits:
commit 22d7f311f7733a57ece5d91708b2b5da9b71de86
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Mon Jan 14 16:14:02 2008 -0500
[scaled-font] Upgrade glyph mask as needed in case of mixed-format glyphs
In ecb895803b9d2a3fd142f4a2c694ca08c5581f0e Carl made fallback show_glyphs
always use a A8 mask in case of mixed-format glyphs. That's suboptimal if
there are ARGB32 glyphs. Using masks smartly we can implement the desired
behavior. Done now.
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index e3de7a4..cf19a8f 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -724,6 +724,24 @@ _cairo_content_from_format (cairo_format_t format)
return CAIRO_CONTENT_COLOR_ALPHA;
}
+cairo_private cairo_format_t
+_cairo_format_width (cairo_format_t format)
+{
+ switch (format) {
+ case CAIRO_FORMAT_ARGB32:
+ return 32;
+ case CAIRO_FORMAT_RGB24:
+ return 24;
+ case CAIRO_FORMAT_A8:
+ return 8;
+ case CAIRO_FORMAT_A1:
+ return 1;
+ default:
+ ASSERT_NOT_REACHED;
+ return 0;
+ }
+}
+
static cairo_surface_t *
_cairo_image_surface_create_similar (void *abstract_src,
cairo_content_t content,
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 03d8138..f8b124b 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1173,8 +1173,9 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
{
cairo_status_t status;
cairo_surface_t *mask = NULL;
- cairo_format_t mask_format;
+ cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */
cairo_surface_pattern_t mask_pattern;
+ cairo_solid_pattern_t white_pattern;
int i;
/* These operators aren't interpreted the same way by the backends;
@@ -1204,6 +1205,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
status = CAIRO_STATUS_SUCCESS;
+ _cairo_pattern_init_solid (&white_pattern, CAIRO_COLOR_WHITE, CAIRO_CONTENT_COLOR);
+
_cairo_cache_freeze (scaled_font->glyphs);
for (i = 0; i < num_glyphs; i++) {
@@ -1232,31 +1235,29 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
status = mask->status;
goto CLEANUP_MASK;
}
-
- status = _cairo_surface_fill_rectangle (mask,
- CAIRO_OPERATOR_CLEAR,
- CAIRO_COLOR_TRANSPARENT,
- 0, 0,
- width, height);
- if (status)
- goto CLEANUP_MASK;
- if (mask_format == CAIRO_FORMAT_ARGB32)
- pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)->
- pixman_image, TRUE);
}
- /* If we have glyphs of different formats, then the only thing
- * we can easily do is to migrate to an A8 mask. This is
- * sub-optimal if there are any component-alpha ARGB32 glyphs,
- * but pixman doesn't actually give us anyoperators that will
- * correctly ADD to a component-alpha mask. So here we are. */
+ /* If we have glyphs of different formats, we "upgrade" the mask
+ * to the wider of the formats. */
if (glyph_surface->format != mask_format &&
- mask_format != CAIRO_FORMAT_A8)
+ _cairo_format_width (mask_format) < _cairo_format_width (glyph_surface->format) )
{
cairo_surface_t *new_mask;
cairo_surface_pattern_t mask_pattern;
- mask_format = CAIRO_FORMAT_A8;
+ switch (glyph_surface->format) {
+ case CAIRO_FORMAT_ARGB32:
+ case CAIRO_FORMAT_A8:
+ case CAIRO_FORMAT_A1:
+ mask_format = glyph_surface->format;
+ break;
+ case CAIRO_FORMAT_RGB24:
+ default:
+ ASSERT_NOT_REACHED;
+ mask_format = CAIRO_FORMAT_ARGB32;
+ break;
+ }
+
new_mask = cairo_image_surface_create (mask_format,
width, height);
if (new_mask->status) {
@@ -1267,9 +1268,9 @@ _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_SOURCE,
+ status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+ &white_pattern.base,
&mask_pattern.base,
- NULL,
new_mask,
0, 0,
0, 0,
@@ -1295,21 +1296,24 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
_cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base);
status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
+ &white_pattern.base,
&glyph_pattern.base,
- NULL,
mask,
0, 0,
0, 0,
- x - dest_x,
- y - dest_y,
+ x - dest_x, y - dest_y,
glyph_surface->width,
glyph_surface->height);
_cairo_pattern_fini (&glyph_pattern.base);
+
if (status)
goto CLEANUP_MASK;
}
+ 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);
status = _cairo_surface_composite (op, pattern, &mask_pattern.base,
@@ -1324,6 +1328,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
CLEANUP_MASK:
_cairo_cache_thaw (scaled_font->glyphs);
+ _cairo_pattern_fini (&white_pattern.base);
+
if (mask != NULL)
cairo_surface_destroy (mask);
return _cairo_scaled_font_set_error (scaled_font, status);
diff --git a/src/cairoint.h b/src/cairoint.h
index efdf0f7..c284779 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1796,6 +1796,9 @@ _cairo_surface_has_device_transform (cairo_surface_t *surface);
== 0))
cairo_private cairo_format_t
+_cairo_format_width (cairo_format_t format);
+
+cairo_private cairo_format_t
_cairo_format_from_content (cairo_content_t content);
cairo_private cairo_content_t
More information about the cairo-commit
mailing list