diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2008-01-14 16:14:02 -0500 |
---|---|---|
committer | Carl Worth <cworth@cworth.org> | 2008-01-14 15:29:17 -0800 |
commit | 549234a27f6b25cd0577874aa2d047515041fae3 (patch) | |
tree | 375f0123b86bf0cc06aa7029ce9dd33f3f177a7e | |
parent | 35ed062a6269feeebae70c98000b60630a9ec3bd (diff) |
[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.
Cherry picked from commit 22d7f311f7733a57ece5d91708b2b5da9b71de86
-rw-r--r-- | src/cairo-image-surface.c | 18 | ||||
-rw-r--r-- | src/cairo-scaled-font.c | 55 | ||||
-rw-r--r-- | src/cairoint.h | 3 |
3 files changed, 52 insertions, 24 deletions
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c index 27287fad2..12e0b75cf 100644 --- a/src/cairo-image-surface.c +++ b/src/cairo-image-surface.c @@ -572,6 +572,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 256899ba3..4e474babf 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -1037,8 +1037,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; @@ -1068,6 +1069,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++) { @@ -1096,31 +1099,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) { @@ -1131,9 +1132,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, @@ -1161,17 +1162,17 @@ _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; } @@ -1179,6 +1180,10 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, if (mask != NULL) { cairo_surface_pattern_t mask_pattern; + 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, @@ -1194,6 +1199,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 status; diff --git a/src/cairoint.h b/src/cairoint.h index 21d43d925..6efd90eda 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -2022,6 +2022,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 |