summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2022-04-25 12:46:13 +0000
committerAdrian Johnson <ajohnson@redneon.com>2022-04-25 12:46:13 +0000
commiteee2b9ab9a653827d655ae35890aca25aa2ff6ee (patch)
treeeb76515c991892c65fc0c326b3e0d16620a67bca
parentcdcb67ef87790ab01c4f32a432f6bd47df0434e5 (diff)
parent4815949d2fd9053c5550de71c2f296005a4aa22d (diff)
Merge branch 'fix-color-glyph' into 'master'
Fix the scaled_glyph_init color glyph logic See merge request cairo/cairo!314
-rw-r--r--src/cairo-ft-font.c44
-rw-r--r--src/cairo-scaled-font-private.h7
-rwxr-xr-xsrc/cairo-scaled-font.c3
-rw-r--r--src/cairo-surface.c4
-rw-r--r--src/cairo-user-font.c365
-rw-r--r--src/win32/cairo-dwrite-font.cpp32
-rw-r--r--src/win32/cairo-win32-font.c6
-rw-r--r--test/reference/user-font.base.argb32.ref.pngbin5785 -> 0 bytes
-rw-r--r--test/reference/user-font.base.rgb24.ref.pngbin5785 -> 0 bytes
-rw-r--r--test/reference/user-font.image16.ref.pngbin5814 -> 0 bytes
-rw-r--r--test/reference/user-font.mask.argb32.ref.pngbin6478 -> 0 bytes
-rw-r--r--test/reference/user-font.mask.rgb24.ref.pngbin6478 -> 0 bytes
-rw-r--r--test/reference/user-font.pdf.ref.pngbin2626 -> 0 bytes
-rw-r--r--test/reference/user-font.ps.ref.pngbin4464 -> 0 bytes
-rw-r--r--test/reference/user-font.quartz.ref.pngbin5854 -> 9865 bytes
-rw-r--r--test/reference/user-font.recording.ref.pngbin0 -> 12398 bytes
-rw-r--r--test/reference/user-font.ref.pngbin5875 -> 9867 bytes
-rw-r--r--test/reference/user-font.svg.ref.pngbin5851 -> 0 bytes
-rw-r--r--test/reference/user-font.traps.argb32.ref.pngbin5785 -> 0 bytes
-rw-r--r--test/reference/user-font.traps.rgb24.ref.pngbin5785 -> 0 bytes
-rw-r--r--test/user-font.c71
21 files changed, 327 insertions, 205 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 60b98fb41..df1aa5b18 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2500,9 +2500,15 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
cairo_image_surface_t *surface;
cairo_bool_t uses_foreground_color = FALSE;
+ /* Only one info type at a time handled in this function */
+ assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE);
+
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
- if (!unscaled->have_color)
+ if (!unscaled->have_color) {
+ scaled_glyph->color_glyph = FALSE;
+ scaled_glyph->color_glyph_set = TRUE;
return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
#ifdef HAVE_FT_PALETTE_SET_FOREGROUND_COLOR
FT_LayerIterator iterator;
@@ -2539,7 +2545,7 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
#ifdef FT_LOAD_COLOR
load_flags |= FT_LOAD_COLOR;
#endif
- } else {
+ } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
#ifdef FT_LOAD_COLOR
load_flags &= ~FT_LOAD_COLOR;
#endif
@@ -2571,18 +2577,34 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
if (unlikely (status))
return status;
}
- if (pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 &&
- !pixman_image_get_component_alpha (surface->pixman_image)) {
- _cairo_scaled_glyph_set_color_surface (scaled_glyph,
- &scaled_font->base,
- surface,
- uses_foreground_color);
- } else {
+
+ if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+ /* We tried loading a color glyph and can now check if we got
+ * a color glyph and set scaled_glyph->color_glyph
+ * accordingly */
+ if (pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 &&
+ !pixman_image_get_component_alpha (surface->pixman_image))
+ {
+ _cairo_scaled_glyph_set_color_surface (scaled_glyph,
+ &scaled_font->base,
+ surface,
+ uses_foreground_color);
+
+ scaled_glyph->color_glyph = TRUE;
+ } else {
+ /* We didn't ask for a non-color surface, but store it
+ * anyway so we don't have to load it again. */
+ _cairo_scaled_glyph_set_surface (scaled_glyph,
+ &scaled_font->base,
+ surface);
+ scaled_glyph->color_glyph = FALSE;
+ status = CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+ scaled_glyph->color_glyph_set = TRUE;
+ } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
_cairo_scaled_glyph_set_surface (scaled_glyph,
&scaled_font->base,
surface);
- if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)
- scaled_glyph->not_color_glyph = TRUE;
}
return status;
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index 3b2fe586d..7a19f2539 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -151,11 +151,10 @@ struct _cairo_scaled_glyph {
/* TRUE if the color_surface required the foreground_color to render. */
unsigned uses_foreground_color : 1;
- /* TRUE if this is not a color glyph, FALSE if is a color glyph or unknown. */
- unsigned not_color_glyph : 1;
+ /* TRUE if color_glyph specifies if glyph is color or non color, FALSE if glyph color type unknown. */
+ unsigned color_glyph_set : 1;
- /* TRUE if recording_surface is a color glyph */
- unsigned recording_is_color : 1;
+ unsigned color_glyph : 1;
};
struct _cairo_scaled_glyph_private {
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 270f8ed34..203b6a10c 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -3057,7 +3057,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
need_info = info & ~scaled_glyph->has_info;
/* If this is not a color glyph, don't try loading the color surface again. */
- if ((need_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) && scaled_glyph->not_color_glyph)
+ if ((need_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) &&
+ scaled_glyph->color_glyph_set && !scaled_glyph->color_glyph)
return CAIRO_INT_STATUS_UNSUPPORTED;
/* If requesting a color surface for a glyph that has used the
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index ec10b2cfa..0bc0b8c7d 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2671,9 +2671,9 @@ composite_one_color_glyph (cairo_surface_t *surface,
cairo_matrix_scale (&matrix, x_scale, y_scale);
cairo_pattern_set_matrix (pattern, &matrix);
if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR || !has_color)
- status = _cairo_surface_mask (surface, op, pattern, pattern, clip);
+ status = _cairo_surface_mask (surface, op, pattern, pattern, clip);
else
- status = _cairo_surface_paint (surface, op, pattern, clip);
+ status = _cairo_surface_paint (surface, op, pattern, clip);
cairo_pattern_destroy (pattern);
}
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index b2a05d67d..fd989eaa0 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -142,192 +142,237 @@ _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t
}
static cairo_int_status_t
-_cairo_user_scaled_glyph_init (void *abstract_font,
- cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info,
- const cairo_color_t *foreground_color)
+_cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_font,
+ cairo_scaled_glyph_t *scaled_glyph)
{
+ cairo_user_font_face_t *face =
+ (cairo_user_font_face_t *) scaled_font->base.font_face;
+ cairo_text_extents_t extents = scaled_font->default_glyph_extents;
+ cairo_surface_t *recording_surface = NULL;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
- cairo_user_scaled_font_t *scaled_font = abstract_font;
- cairo_surface_t *recording_surface = scaled_glyph->recording_surface;
+ cairo_t *cr;
- if (!scaled_glyph->recording_surface) {
- cairo_user_font_face_t *face =
- (cairo_user_font_face_t *) scaled_font->base.font_face;
- cairo_text_extents_t extents = scaled_font->default_glyph_extents;
- cairo_t *cr;
+ if (!face->scaled_font_methods.render_color_glyph && !face->scaled_font_methods.render_glyph)
+ return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
- recording_surface = NULL;
- if (!face->scaled_font_methods.render_color_glyph && !face->scaled_font_methods.render_glyph)
- return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
+ /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
+ if (_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
+ recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE);
+ _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
+ &scaled_font->base,
+ recording_surface);
+ } else {
+ status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
+
+ if (face->scaled_font_methods.render_color_glyph) {
+ cairo_pattern_t *pattern;
+
+ recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE);
+
+ cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, TRUE);
+ pattern = cairo_pattern_create_rgb (0, 0, 0);
+ pattern->is_userfont_foreground = TRUE;
+ cairo_set_source (cr, pattern);
+ cairo_pattern_destroy (pattern);
+ status = face->scaled_font_methods.render_color_glyph ((cairo_scaled_font_t *)scaled_font,
+ _cairo_scaled_glyph_index(scaled_glyph),
+ cr, &extents);
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
+ status = cairo_status (cr);
+ scaled_glyph->color_glyph = TRUE;
+ scaled_glyph->color_glyph_set = TRUE;
+ }
+ cairo_destroy (cr);
+ }
- /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
- if (_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
+ if (status == (cairo_int_status_t)CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED &&
+ face->scaled_font_methods.render_glyph) {
+ if (recording_surface)
+ cairo_surface_destroy (recording_surface);
recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE);
- _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
- &scaled_font->base,
- recording_surface);
- } else {
- status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
-
- if (face->scaled_font_methods.render_color_glyph) {
- cairo_pattern_t *pattern;
-
- recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE);
-
- cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, TRUE);
- pattern = cairo_pattern_create_rgb (0, 0, 0);
- pattern->is_userfont_foreground = TRUE;
- cairo_set_source (cr, pattern);
- cairo_pattern_destroy (pattern);
- status = face->scaled_font_methods.render_color_glyph ((cairo_scaled_font_t *)scaled_font,
- _cairo_scaled_glyph_index(scaled_glyph),
- cr, &extents);
- if (status == CAIRO_INT_STATUS_SUCCESS) {
- status = cairo_status (cr);
- scaled_glyph->recording_is_color = TRUE;
- }
- cairo_destroy (cr);
+ recording_surface->device_transform.x0 = .25 * _cairo_scaled_glyph_xphase (scaled_glyph);
+ recording_surface->device_transform.y0 = .25 * _cairo_scaled_glyph_yphase (scaled_glyph);
+
+ cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, FALSE);
+
+ status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
+ _cairo_scaled_glyph_index(scaled_glyph),
+ cr, &extents);
+ if (status == CAIRO_INT_STATUS_SUCCESS) {
+ status = cairo_status (cr);
+ scaled_glyph->color_glyph = FALSE;
+ scaled_glyph->color_glyph_set = TRUE;
}
- if (status == (cairo_int_status_t)CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED &&
- face->scaled_font_methods.render_glyph) {
- if (recording_surface)
- cairo_surface_destroy (recording_surface);
- recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE);
- recording_surface->device_transform.x0 = .25 * _cairo_scaled_glyph_xphase (scaled_glyph);
- recording_surface->device_transform.y0 = .25 * _cairo_scaled_glyph_yphase (scaled_glyph);
+ cairo_destroy (cr);
+ }
- cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, FALSE);
+ if (status != CAIRO_INT_STATUS_SUCCESS) {
+ if (recording_surface)
+ cairo_surface_destroy (recording_surface);
+ return status;
+ }
- status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
- _cairo_scaled_glyph_index(scaled_glyph),
- cr, &extents);
- if (status == CAIRO_INT_STATUS_SUCCESS)
- status = cairo_status (cr);
+ _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
+ &scaled_font->base,
+ recording_surface);
+ }
- cairo_destroy (cr);
- }
+ /* set metrics */
- if (status != CAIRO_INT_STATUS_SUCCESS) {
- if (recording_surface)
- cairo_surface_destroy (recording_surface);
- return status;
- }
+ if (extents.width == 0.) {
+ cairo_box_t bbox;
+ double x1, y1, x2, y2;
+ double x_scale, y_scale;
- _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
- &scaled_font->base,
- recording_surface);
- }
+ /* Compute extents.x/y/width/height from recording_surface,
+ * in font space.
+ */
+ status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
+ &bbox,
+ &scaled_font->extent_scale);
+ if (unlikely (status))
+ return status;
- /* set metrics */
-
- if (extents.width == 0.) {
- cairo_box_t bbox;
- double x1, y1, x2, y2;
- double x_scale, y_scale;
-
- /* Compute extents.x/y/width/height from recording_surface,
- * in font space.
- */
- status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
- &bbox,
- &scaled_font->extent_scale);
- if (unlikely (status))
- return status;
-
- _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
-
- x_scale = scaled_font->extent_x_scale;
- y_scale = scaled_font->extent_y_scale;
- extents.x_bearing = x1 * x_scale;
- extents.y_bearing = y1 * y_scale;
- extents.width = (x2 - x1) * x_scale;
- extents.height = (y2 - y1) * y_scale;
- }
+ _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
+
+ x_scale = scaled_font->extent_x_scale;
+ y_scale = scaled_font->extent_y_scale;
+ extents.x_bearing = x1 * x_scale;
+ extents.y_bearing = y1 * y_scale;
+ extents.width = (x2 - x1) * x_scale;
+ extents.height = (y2 - y1) * y_scale;
+ }
+
+ if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
+ extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
+ extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
+ }
+
+ _cairo_scaled_glyph_set_metrics (scaled_glyph,
+ &scaled_font->base,
+ &extents);
+
+ return status;
+}
+
+static cairo_int_status_t
+_cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t *scaled_font,
+ cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color)
+{
+ cairo_surface_t *surface;
+ cairo_format_t format;
+ int width, height;
+ cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+
+ /* TODO
+ * extend the glyph cache to support argb glyphs.
+ * need to figure out the semantics and interaction with subpixel
+ * rendering first.
+ */
+
+ /* Only one info type at a time handled in this function */
+ assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE);
- if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
- extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
- extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
+ width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
+ _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
+ height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
+ _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
+
+ if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+ format = CAIRO_FORMAT_ARGB32;
+ } else {
+ switch (scaled_font->base.options.antialias) {
+ default:
+ case CAIRO_ANTIALIAS_DEFAULT:
+ case CAIRO_ANTIALIAS_FAST:
+ case CAIRO_ANTIALIAS_GOOD:
+ case CAIRO_ANTIALIAS_GRAY:
+ format = CAIRO_FORMAT_A8;
+ break;
+ case CAIRO_ANTIALIAS_NONE:
+ format = CAIRO_FORMAT_A1;
+ break;
+ case CAIRO_ANTIALIAS_BEST:
+ case CAIRO_ANTIALIAS_SUBPIXEL:
+ format = CAIRO_FORMAT_ARGB32;
+ break;
}
+ }
+ surface = cairo_image_surface_create (format, width, height);
- _cairo_scaled_glyph_set_metrics (scaled_glyph,
+ cairo_surface_set_device_offset (surface,
+ - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
+ - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
+
+ if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+ status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
+ surface,
+ foreground_color);
+ } else {
+ status = _cairo_recording_surface_replay (scaled_glyph->recording_surface, surface);
+ }
+
+ if (unlikely (status)) {
+ cairo_surface_destroy(surface);
+ return status;
+ }
+
+ if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+ _cairo_scaled_glyph_set_color_surface (scaled_glyph,
+ &scaled_font->base,
+ (cairo_image_surface_t *)surface,
+ TRUE);
+ surface = NULL;
+ } else {
+ _cairo_scaled_glyph_set_surface (scaled_glyph,
&scaled_font->base,
- &extents);
+ (cairo_image_surface_t *) surface);
+ surface = NULL;
}
- if (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) {
- cairo_surface_t *surface;
- cairo_format_t format;
- int width, height;
+ if (surface)
+ cairo_surface_destroy (surface);
- /* TODO
- * extend the glyph cache to support argb glyphs.
- * need to figure out the semantics and interaction with subpixel
- * rendering first.
- */
+ return status;
+}
- width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
- height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
-
- if (scaled_glyph->recording_is_color) {
- format = CAIRO_FORMAT_ARGB32;
- } else {
- switch (scaled_font->base.options.antialias) {
- default:
- case CAIRO_ANTIALIAS_DEFAULT:
- case CAIRO_ANTIALIAS_FAST:
- case CAIRO_ANTIALIAS_GOOD:
- case CAIRO_ANTIALIAS_GRAY:
- format = CAIRO_FORMAT_A8;
- break;
- case CAIRO_ANTIALIAS_NONE:
- format = CAIRO_FORMAT_A1;
- break;
- case CAIRO_ANTIALIAS_BEST:
- case CAIRO_ANTIALIAS_SUBPIXEL:
- format = CAIRO_FORMAT_ARGB32;
- break;
- }
- }
- surface = cairo_image_surface_create (format, width, height);
-
- cairo_surface_set_device_offset (surface,
- - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
- - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
-
- if (scaled_glyph->recording_is_color) {
- status = _cairo_recording_surface_replay_with_foreground_color (recording_surface,
- surface,
- foreground_color);
- } else {
- status = _cairo_recording_surface_replay (recording_surface, surface);
- }
+static cairo_int_status_t
+_cairo_user_scaled_glyph_init (void *abstract_font,
+ cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color)
+{
+ cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_user_scaled_font_t *scaled_font = abstract_font;
- if (unlikely (status)) {
- cairo_surface_destroy(surface);
+ if (!scaled_glyph->recording_surface) {
+ status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph);
+ if (status)
return status;
- }
+ }
- if (!scaled_glyph->recording_is_color && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE)) {
- _cairo_scaled_glyph_set_surface (scaled_glyph,
- &scaled_font->base,
- (cairo_image_surface_t *) surface);
- surface = NULL;
- }
+ if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+ if (!scaled_glyph->color_glyph )
+ return CAIRO_INT_STATUS_UNSUPPORTED;
- if (scaled_glyph->recording_is_color && (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) {
- _cairo_scaled_glyph_set_color_surface (scaled_glyph,
- &scaled_font->base,
- (cairo_image_surface_t *)surface,
- FALSE);
- surface = NULL;
- }
+ status = _cairo_user_scaled_glyph_init_surface (scaled_font,
+ scaled_glyph,
+ CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
+ foreground_color);
+ if (status)
+ return status;
+ }
- if (surface)
- cairo_surface_destroy (surface);
+ if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
+ status = _cairo_user_scaled_glyph_init_surface (scaled_font,
+ scaled_glyph,
+ CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL);
+ if (status)
+ return status;
}
if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
@@ -335,7 +380,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
if (!path)
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- status = _cairo_recording_surface_get_path (recording_surface, path);
+ status = _cairo_recording_surface_get_path (scaled_glyph->recording_surface, path);
if (unlikely (status)) {
_cairo_path_fixed_destroy (path);
return status;
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index ec44d3180..0a3b77362 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -864,8 +864,11 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
cairo_bool_t uses_foreground_color = FALSE;
cairo_dwrite_font_face_t *dwrite_font_face = (cairo_dwrite_font_face_t *)scaled_font->base.font_face;
- if (!dwrite_font_face->have_color)
+ if (!dwrite_font_face->have_color) {
+ scaled_glyph->color_glyph = FALSE;
+ scaled_glyph->color_glyph_set = TRUE;
return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
@@ -931,8 +934,12 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
0,
&run_enumerator);
- if (hr == DWRITE_E_NOCOLOR)
- return CAIRO_INT_STATUS_UNSUPPORTED; /* No color glyphs */
+ if (hr == DWRITE_E_NOCOLOR) {
+ /* No color glyphs */
+ scaled_glyph->color_glyph = FALSE;
+ scaled_glyph->color_glyph_set = TRUE;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
if (FAILED(hr))
return _cairo_dwrite_error (hr, "TranslateColorGlyphRun failed");
@@ -971,15 +978,11 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
return _cairo_dwrite_error (hr, "QueryInterface(&dc4) failed");
RefPtr<ID2D1SolidColorBrush> foreground_color_brush;
- if (foreground_color) {
- dc4->CreateSolidColorBrush(
- D2D1::ColorF(foreground_color->red,
- foreground_color->green,
- foreground_color->blue,
- foreground_color->alpha), &foreground_color_brush);
- } else {
- dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &foreground_color_brush);
- }
+ dc4->CreateSolidColorBrush(
+ D2D1::ColorF(foreground_color->red,
+ foreground_color->green,
+ foreground_color->blue,
+ foreground_color->alpha), &foreground_color_brush);
RefPtr<ID2D1SolidColorBrush> color_brush;
dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &color_brush);
@@ -1027,8 +1030,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
nullptr,
0,
DWRITE_MEASURING_MODE_NATURAL);
- if (foreground_color)
- uses_foreground_color = TRUE;
+ uses_foreground_color = TRUE;
break;
case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE:
case DWRITE_GLYPH_IMAGE_FORMATS_CFF:
@@ -1068,6 +1070,8 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
&scaled_font->base,
(cairo_image_surface_t *) image,
uses_foreground_color);
+ scaled_glyph->color_glyph = TRUE;
+ scaled_glyph->color_glyph_set = TRUE;
return CAIRO_INT_STATUS_SUCCESS;
}
diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c
index a3e1bd731..2003a2782 100644
--- a/src/win32/cairo-win32-font.c
+++ b/src/win32/cairo-win32-font.c
@@ -1115,6 +1115,12 @@ _cairo_win32_scaled_font_glyph_init (void *abstract_font,
return status;
}
+ if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+ scaled_glyph->color_glyph = FALSE;
+ scaled_glyph->color_glyph_set = TRUE;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
if (status)
diff --git a/test/reference/user-font.base.argb32.ref.png b/test/reference/user-font.base.argb32.ref.png
deleted file mode 100644
index 896dbab25..000000000
--- a/test/reference/user-font.base.argb32.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.base.rgb24.ref.png b/test/reference/user-font.base.rgb24.ref.png
deleted file mode 100644
index 896dbab25..000000000
--- a/test/reference/user-font.base.rgb24.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.image16.ref.png b/test/reference/user-font.image16.ref.png
deleted file mode 100644
index fcdfb5793..000000000
--- a/test/reference/user-font.image16.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.mask.argb32.ref.png b/test/reference/user-font.mask.argb32.ref.png
deleted file mode 100644
index b234a8801..000000000
--- a/test/reference/user-font.mask.argb32.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.mask.rgb24.ref.png b/test/reference/user-font.mask.rgb24.ref.png
deleted file mode 100644
index b234a8801..000000000
--- a/test/reference/user-font.mask.rgb24.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.pdf.ref.png b/test/reference/user-font.pdf.ref.png
deleted file mode 100644
index 5dc028eb3..000000000
--- a/test/reference/user-font.pdf.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.ps.ref.png b/test/reference/user-font.ps.ref.png
deleted file mode 100644
index 3a674c30a..000000000
--- a/test/reference/user-font.ps.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.quartz.ref.png b/test/reference/user-font.quartz.ref.png
index dfb2e0a15..f1a8d5752 100644
--- a/test/reference/user-font.quartz.ref.png
+++ b/test/reference/user-font.quartz.ref.png
Binary files differ
diff --git a/test/reference/user-font.recording.ref.png b/test/reference/user-font.recording.ref.png
new file mode 100644
index 000000000..aefe4c9fe
--- /dev/null
+++ b/test/reference/user-font.recording.ref.png
Binary files differ
diff --git a/test/reference/user-font.ref.png b/test/reference/user-font.ref.png
index 4cff7e996..87a3f68e3 100644
--- a/test/reference/user-font.ref.png
+++ b/test/reference/user-font.ref.png
Binary files differ
diff --git a/test/reference/user-font.svg.ref.png b/test/reference/user-font.svg.ref.png
deleted file mode 100644
index b89e92d20..000000000
--- a/test/reference/user-font.svg.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.traps.argb32.ref.png b/test/reference/user-font.traps.argb32.ref.png
deleted file mode 100644
index 896dbab25..000000000
--- a/test/reference/user-font.traps.argb32.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/reference/user-font.traps.rgb24.ref.png b/test/reference/user-font.traps.rgb24.ref.png
deleted file mode 100644
index 896dbab25..000000000
--- a/test/reference/user-font.traps.rgb24.ref.png
+++ /dev/null
Binary files differ
diff --git a/test/user-font.c b/test/user-font.c
index 435d5616f..d02a90f4d 100644
--- a/test/user-font.c
+++ b/test/user-font.c
@@ -36,11 +36,13 @@
#define TEXT_SIZE 64
#define WIDTH (TEXT_SIZE * 15 + 2*BORDER)
#ifndef ROTATED
- #define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
+ #define HEIGHT ((TEXT_SIZE + 2*BORDER)*3)
#else
#define HEIGHT WIDTH
#endif
-#define TEXT "geez... cairo user-font"
+
+#define TEXT1 "cairo user-font."
+#define TEXT2 " zg."
#define END_GLYPH 0
#define STROKE 126
@@ -136,8 +138,14 @@ test_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
return CAIRO_STATUS_SUCCESS;
}
+
+/* If color_render is TRUE, use the render_color_glyph callback
+ * instead of the render_glyph callbac. The output should be identical
+ * in this test since the render function does not alter the cairo_t
+ * source.
+ */
static cairo_status_t
-_user_font_face_create (cairo_font_face_t **out)
+_user_font_face_create (cairo_font_face_t **out, cairo_bool_t color_render)
{
/* Simple glyph definition: 1 - 15 means lineto (or moveto for first
* point) for one of the points on this grid:
@@ -174,8 +182,12 @@ _user_font_face_create (cairo_font_face_t **out)
cairo_status_t status;
user_font_face = cairo_user_font_face_create ();
- cairo_user_font_face_set_init_func (user_font_face, test_scaled_font_init);
- cairo_user_font_face_set_render_glyph_func (user_font_face, test_scaled_font_render_glyph);
+ cairo_user_font_face_set_init_func (user_font_face, test_scaled_font_init);
+ if (color_render)
+ cairo_user_font_face_set_render_color_glyph_func (user_font_face, test_scaled_font_render_glyph);
+ else
+ cairo_user_font_face_set_render_glyph_func (user_font_face, test_scaled_font_render_glyph);
+
cairo_user_font_face_set_unicode_to_glyph_func (user_font_face, test_scaled_font_unicode_to_glyph);
status = cairo_font_face_set_user_data (user_font_face,
@@ -194,11 +206,15 @@ static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
cairo_font_face_t *font_face;
- const char text[] = TEXT;
+ char full_text[100];
cairo_font_extents_t font_extents;
cairo_text_extents_t extents;
cairo_status_t status;
+ strcpy(full_text, TEXT1);
+ strcat(full_text, TEXT2);
+ strcat(full_text, TEXT2);
+
cairo_set_source_rgb (cr, 1, 1, 1);
cairo_paint (cr);
@@ -207,7 +223,7 @@ draw (cairo_t *cr, int width, int height)
cairo_rotate (cr, .6);
#endif
- status = _user_font_face_create (&font_face);
+ status = _user_font_face_create (&font_face, FALSE);
if (status) {
return cairo_test_status_from_status (cairo_test_get_context (cr),
status);
@@ -219,7 +235,7 @@ draw (cairo_t *cr, int width, int height)
cairo_set_font_size (cr, TEXT_SIZE);
cairo_font_extents (cr, &font_extents);
- cairo_text_extents (cr, text, &extents);
+ cairo_text_extents (cr, full_text, &extents);
/* logical boundaries in red */
cairo_move_to (cr, 0, BORDER);
@@ -244,16 +260,45 @@ draw (cairo_t *cr, int width, int height)
cairo_set_line_width (cr, 2);
cairo_stroke (cr);
- /* text in black */
+ /* First line. Text in black, except first "zg." in green */
cairo_set_source_rgb (cr, 0, 0, 0);
cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
- cairo_show_text (cr, text);
+ cairo_show_text (cr, TEXT1);
+ cairo_set_source_rgb (cr, 0, 1, 0);
+ cairo_show_text (cr, TEXT2);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_show_text (cr, TEXT2);
+
+ /* Now draw the second line using the render_color_glyph callback. The
+ * output should be the same because same render function is used
+ * and the render function does not set a color. This exercises
+ * the paint color glyph with foreground color code path and
+ * ensures cairo updates the glyph image when the foreground color
+ * changes.
+ */
+ status = _user_font_face_create (&font_face, TRUE);
+ if (status) {
+ return cairo_test_status_from_status (cairo_test_get_context (cr),
+ status);
+ }
+ cairo_set_font_face (cr, font_face);
+ cairo_font_face_destroy (font_face);
- /* filled version of text in blue */
- cairo_set_source_rgb (cr, 0, 0, 1);
+ cairo_set_font_size (cr, TEXT_SIZE);
+
+ /* text in black, except first "zg." in green */
cairo_move_to (cr, BORDER, BORDER + font_extents.height + 2*BORDER + font_extents.ascent);
- cairo_text_path (cr, text);
+ cairo_show_text (cr, TEXT1);
+ cairo_set_source_rgb (cr, 0, 1, 0);
+ cairo_show_text (cr, TEXT2);
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ cairo_show_text (cr, TEXT2);
+
+ /* Third line. Filled version of text in blue */
+ cairo_set_source_rgb (cr, 0, 0, 1);
+ cairo_move_to (cr, BORDER, BORDER + font_extents.height + 4*BORDER + 2*font_extents.ascent);
+ cairo_text_path (cr, full_text);
cairo_fill (cr);
return CAIRO_TEST_SUCCESS;