[cairo-commit] 2 commits - src/cairo-ft-font.c src/cairo-scaled-font.c src/cairo-scaled-font-private.h src/cairo-surface.c src/cairo-user-font.c src/win32 test/reference test/user-font.c

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Apr 25 12:46:15 UTC 2022


 dev/null                                   |binary
 src/cairo-ft-font.c                        |   44 ++-
 src/cairo-scaled-font-private.h            |    7 
 src/cairo-scaled-font.c                    |    3 
 src/cairo-surface.c                        |    4 
 src/cairo-user-font.c                      |  365 ++++++++++++++++-------------
 src/win32/cairo-dwrite-font.cpp            |   32 +-
 src/win32/cairo-win32-font.c               |    6 
 test/reference/user-font.quartz.ref.png    |binary
 test/reference/user-font.recording.ref.png |binary
 test/reference/user-font.ref.png           |binary
 test/user-font.c                           |   71 ++++-
 12 files changed, 327 insertions(+), 205 deletions(-)

New commits:
commit eee2b9ab9a653827d655ae35890aca25aa2ff6ee
Merge: cdcb67ef8 4815949d2
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Apr 25 12:46:13 2022 +0000

    Merge branch 'fix-color-glyph' into 'master'
    
    Fix the scaled_glyph_init color glyph logic
    
    See merge request cairo/cairo!314

commit 4815949d2fd9053c5550de71c2f296005a4aa22d
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Apr 22 21:18:09 2022 +0930

    Fix the scaled_glyph_init color glyph logic
    
    and split _cairo_user_scaled_glyph_init() into multiple functions.
    
    Update user-font test to test changing foreground text color.

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
Binary files a/test/reference/user-font.base.argb32.ref.png and /dev/null 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
Binary files a/test/reference/user-font.base.rgb24.ref.png and /dev/null 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
Binary files a/test/reference/user-font.image16.ref.png and /dev/null 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
Binary files a/test/reference/user-font.mask.argb32.ref.png and /dev/null 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
Binary files a/test/reference/user-font.mask.rgb24.ref.png and /dev/null 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
Binary files a/test/reference/user-font.pdf.ref.png and /dev/null 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
Binary files a/test/reference/user-font.ps.ref.png and /dev/null differ
diff --git a/test/reference/user-font.quartz.ref.png b/test/reference/user-font.quartz.ref.png
index dfb2e0a15..f1a8d5752 100644
Binary files a/test/reference/user-font.quartz.ref.png and b/test/reference/user-font.quartz.ref.png 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
Binary files /dev/null and b/test/reference/user-font.recording.ref.png differ
diff --git a/test/reference/user-font.ref.png b/test/reference/user-font.ref.png
index 4cff7e996..87a3f68e3 100644
Binary files a/test/reference/user-font.ref.png and b/test/reference/user-font.ref.png 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
Binary files a/test/reference/user-font.svg.ref.png and /dev/null 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
Binary files a/test/reference/user-font.traps.argb32.ref.png and /dev/null 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
Binary files a/test/reference/user-font.traps.rgb24.ref.png and /dev/null 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;


More information about the cairo-commit mailing list