summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2008-01-14 16:14:02 -0500
committerCarl Worth <cworth@cworth.org>2008-01-14 15:29:17 -0800
commit549234a27f6b25cd0577874aa2d047515041fae3 (patch)
tree375f0123b86bf0cc06aa7029ce9dd33f3f177a7e
parent35ed062a6269feeebae70c98000b60630a9ec3bd (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.c18
-rw-r--r--src/cairo-scaled-font.c55
-rw-r--r--src/cairoint.h3
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