[cairo-commit] 3 commits - .gitlab-ci/ignore-quartz-argb32.txt .gitlab-ci/ignore-quartz-rgb24.txt .gitlab-ci/ignore-svg11-argb32.txt .gitlab-ci/ignore-svg11-rgb24.txt src/cairo-ft-font.c src/cairo-image-source.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-recording-surface.c src/cairo-recording-surface-private.h src/cairo-surface.c src/cairo-surface-private.h src/cairo-surface-wrapper.c src/cairo-surface-wrapper-private.h src/cairo-type3-glyph-surface.c src/cairo-user-font.c test/reference test/user-font-color.c

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jan 3 07:45:37 UTC 2023


 .gitlab-ci/ignore-quartz-argb32.txt               |    2 
 .gitlab-ci/ignore-quartz-rgb24.txt                |    2 
 .gitlab-ci/ignore-svg11-argb32.txt                |    1 
 .gitlab-ci/ignore-svg11-rgb24.txt                 |    1 
 dev/null                                          |binary
 src/cairo-ft-font.c                               |    6 +-
 src/cairo-image-source.c                          |    4 +
 src/cairo-pdf-surface.c                           |   47 --------------------
 src/cairo-ps-surface.c                            |   34 --------------
 src/cairo-recording-surface-private.h             |    7 +--
 src/cairo-recording-surface.c                     |   29 ++++++++++--
 src/cairo-surface-private.h                       |    3 +
 src/cairo-surface-wrapper-private.h               |    5 --
 src/cairo-surface-wrapper.c                       |   33 --------------
 src/cairo-surface.c                               |   43 ++++++++++++++++++
 src/cairo-type3-glyph-surface.c                   |   31 +------------
 src/cairo-user-font.c                             |    6 +-
 test/reference/user-font-color.image16.ref.png    |binary
 test/reference/user-font-color.pdf.ref.png        |binary
 test/reference/user-font-color.quartz.ref.png     |binary
 test/reference/user-font-color.recording.ref.png  |binary
 test/reference/user-font-color.ref.png            |binary
 test/reference/user-font-color.script.xfail.png   |binary
 test/reference/user-font-proxy.pdf.argb32.ref.png |binary
 test/reference/user-font-proxy.pdf.rgb24.ref.png  |binary
 test/reference/user-font-proxy.quartz.ref.png     |binary
 test/user-font-color.c                            |   50 +++++++++++++++++++++-
 27 files changed, 142 insertions(+), 162 deletions(-)

New commits:
commit ca0f8ffd84004a0576791531730b649b562ef05a
Merge: 1af1e1125 f0ce8658f
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Jan 3 07:45:35 2023 +0000

    Merge branch 'foreground-color-in-group' into 'master'
    
    User-fonts fails when foreground color used inside a group
    
    See merge request cairo/cairo!380

commit f0ce8658f9ca905b87463f283155ed5c3ad67c10
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Dec 31 20:53:37 2022 +1030

    Fix user-font with foreground in group failures on image, PDF, and PS

diff --git a/.gitlab-ci/ignore-quartz-argb32.txt b/.gitlab-ci/ignore-quartz-argb32.txt
index e00077831..3102cb865 100644
--- a/.gitlab-ci/ignore-quartz-argb32.txt
+++ b/.gitlab-ci/ignore-quartz-argb32.txt
@@ -50,4 +50,6 @@ text-antialias-subpixel-rgb
 text-antialias-subpixel-vbgr
 text-antialias-subpixel-vrgb
 text-unhinted-metrics
+user-font-color
 user-font-proxy
+user-font-rescale
diff --git a/.gitlab-ci/ignore-quartz-rgb24.txt b/.gitlab-ci/ignore-quartz-rgb24.txt
index 0941d59cd..a386d7e30 100644
--- a/.gitlab-ci/ignore-quartz-rgb24.txt
+++ b/.gitlab-ci/ignore-quartz-rgb24.txt
@@ -81,4 +81,6 @@ text-antialias-subpixel-vbgr
 text-antialias-subpixel-vrgb
 text-unhinted-metrics
 thin-lines
+user-font-color
 user-font-proxy
+user-font-rescale
diff --git a/.gitlab-ci/ignore-svg11-argb32.txt b/.gitlab-ci/ignore-svg11-argb32.txt
index c0f6bb287..a37cf287d 100644
--- a/.gitlab-ci/ignore-svg11-argb32.txt
+++ b/.gitlab-ci/ignore-svg11-argb32.txt
@@ -50,3 +50,4 @@ text-rotate
 text-unhinted-metrics
 tighten-bounds
 unbounded-operator
+user-font-color
diff --git a/.gitlab-ci/ignore-svg11-rgb24.txt b/.gitlab-ci/ignore-svg11-rgb24.txt
index d598bfa9f..952ab2786 100644
--- a/.gitlab-ci/ignore-svg11-rgb24.txt
+++ b/.gitlab-ci/ignore-svg11-rgb24.txt
@@ -107,3 +107,4 @@ tighten-bounds
 unbounded-operator
 xcb-surface-source
 xlib-surface-source
+user-font-color
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 100f839d7..68e11a178 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2944,6 +2944,7 @@ _cairo_ft_scaled_glyph_init_surface_svg_glyph (cairo_ft_scaled_font_t *scaled_fo
     cairo_surface_t *surface;
     int width, height;
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+    cairo_bool_t foreground_used;
 
     width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
 	_cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
@@ -2958,7 +2959,8 @@ _cairo_ft_scaled_glyph_init_surface_svg_glyph (cairo_ft_scaled_font_t *scaled_fo
 
     status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
 								    surface,
-								    foreground_color);
+								    foreground_color,
+								    &foreground_used);
     if (unlikely (status)) {
 	cairo_surface_destroy(surface);
 	return status;
@@ -2967,7 +2969,7 @@ _cairo_ft_scaled_glyph_init_surface_svg_glyph (cairo_ft_scaled_font_t *scaled_fo
     _cairo_scaled_glyph_set_color_surface (scaled_glyph,
 					   &scaled_font->base,
 					   (cairo_image_surface_t *)surface,
-					   TRUE);
+					   foreground_used);
     surface = NULL;
 
     if (surface)
diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c
index c56845ab2..b8c1c88f5 100644
--- a/src/cairo-image-source.c
+++ b/src/cairo-image-source.c
@@ -1207,6 +1207,8 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
 	    clone = _cairo_image_surface_create_with_content (source->content,
 							      limit.width,
 							      limit.height);
+	if (dst->base.foreground_source)
+	    clone->foreground_source = cairo_pattern_reference (dst->base.foreground_source);
     }
 
     m = NULL;
@@ -1224,6 +1226,8 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
     /* Handle recursion by returning future reads from the current image */
     proxy = attach_proxy (source, clone);
     status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL);
+    if (clone->foreground_used)
+	dst->base.foreground_used = clone->foreground_used;
     detach_proxy (source, proxy);
     if (unlikely (status)) {
 	cairo_surface_destroy (clone);
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 86ee48cdc..7ec47a956 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -6453,47 +6453,6 @@ _cairo_pdf_emit_imagemask (cairo_image_surface_t *image,
     return _cairo_output_stream_get_status (stream);
 }
 
-static cairo_int_status_t
-_cairo_pdf_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
-					     void		        *closure)
-{
-    cairo_pdf_surface_t *surface = closure;
-    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-    cairo_int_status_t status2;
-    unsigned int i;
-    cairo_surface_t *type3_surface;
-    cairo_output_stream_t *null_stream;
-
-    null_stream = _cairo_null_stream_create ();
-    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
-						       null_stream,
-						       _cairo_pdf_emit_imagemask,
-						       surface->font_subsets,
-						       FALSE);
-    if (unlikely (type3_surface->status)) {
-	status2 = _cairo_output_stream_destroy (null_stream);
-	return type3_surface->status;
-    }
-
-    _cairo_type3_glyph_surface_set_font_subsets_callback (type3_surface,
-							  _cairo_pdf_surface_add_font,
-							  surface);
-
-    for (i = 0; i < font_subset->num_glyphs; i++) {
-	status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
-							   font_subset->glyphs[i]);
-	if (unlikely (status))
-	    break;
-    }
-
-    cairo_surface_destroy (type3_surface);
-    status2 = _cairo_output_stream_destroy (null_stream);
-    if (status == CAIRO_INT_STATUS_SUCCESS)
-	status = status2;
-
-    return status;
-}
-
 static cairo_int_status_t
 _cairo_pdf_surface_emit_type3_font_subset (cairo_pdf_surface_t		*surface,
 					   cairo_scaled_font_subset_t	*font_subset)
@@ -6731,12 +6690,6 @@ _cairo_pdf_surface_emit_font_subsets (cairo_pdf_surface_t *surface)
 {
     cairo_int_status_t status;
 
-    status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
-						      _cairo_pdf_surface_analyze_user_font_subset,
-						      surface);
-    if (unlikely (status))
-	goto BAIL;
-
     status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
                                                           _cairo_pdf_surface_emit_unscaled_font_subset,
                                                           surface);
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 343a5ea05..ad7c8fb1d 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -734,34 +734,6 @@ _cairo_ps_emit_imagemask (cairo_image_surface_t *image,
     return _cairo_output_stream_get_status (stream);
 }
 
-static cairo_int_status_t
-_cairo_ps_surface_analyze_user_font_subset (cairo_scaled_font_subset_t *font_subset,
-					    void		       *closure)
-{
-    cairo_ps_surface_t *surface = closure;
-    cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    unsigned int i;
-    cairo_surface_t *type3_surface;
-
-    type3_surface = _cairo_type3_glyph_surface_create (font_subset->scaled_font,
-						       NULL,
-						       _cairo_ps_emit_imagemask,
-						       surface->font_subsets,
-						       TRUE);
-
-    for (i = 0; i < font_subset->num_glyphs; i++) {
-	status = _cairo_type3_glyph_surface_analyze_glyph (type3_surface,
-							   font_subset->glyphs[i]);
-	if (unlikely (status))
-	    break;
-
-    }
-    cairo_surface_finish (type3_surface);
-    cairo_surface_destroy (type3_surface);
-
-    return status;
-}
-
 static cairo_status_t
 _cairo_ps_surface_emit_type3_font_subset (cairo_ps_surface_t		*surface,
 					  cairo_scaled_font_subset_t	*font_subset)
@@ -928,12 +900,6 @@ _cairo_ps_surface_emit_font_subsets (cairo_ps_surface_t *surface)
 				 "%% _cairo_ps_surface_emit_font_subsets\n");
 #endif
 
-    status = _cairo_scaled_font_subsets_foreach_user (surface->font_subsets,
-						      _cairo_ps_surface_analyze_user_font_subset,
-						      surface);
-    if (unlikely (status))
-	return status;
-
     status = _cairo_scaled_font_subsets_foreach_unscaled (surface->font_subsets,
                                                           _cairo_ps_surface_emit_unscaled_font_subset,
                                                           surface);
diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h
index 63b7a1de6..3d325383b 100644
--- a/src/cairo-recording-surface-private.h
+++ b/src/cairo-recording-surface-private.h
@@ -173,9 +173,10 @@ _cairo_recording_surface_replay (cairo_surface_t *surface,
 				 cairo_surface_t *target);
 
 cairo_private cairo_status_t
-_cairo_recording_surface_replay_with_foreground_color (cairo_surface_t *surface,
-                                                       cairo_surface_t *target,
-                                                       const cairo_color_t *color);
+_cairo_recording_surface_replay_with_foreground_color (cairo_surface_t     *surface,
+                                                       cairo_surface_t     *target,
+                                                       const cairo_color_t *foreground_color,
+                                                       cairo_bool_t        *foreground_used);
 
 cairo_private cairo_status_t
 _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface,
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index d6b6ab337..1df0998e0 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -105,6 +105,7 @@ typedef struct _cairo_recording_surface_replay_params {
     cairo_recording_replay_type_t type;
     cairo_recording_region_type_t region;
     const cairo_color_t *foreground_color;
+    cairo_bool_t foreground_used;
 } cairo_recording_surface_replay_params_t;
 
 static const cairo_surface_backend_t cairo_recording_surface_backend;
@@ -1829,7 +1830,11 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t	*surface,
     }
     _cairo_surface_wrapper_set_inverse_transform (&wrapper, params->surface_transform);
     _cairo_surface_wrapper_set_clip (&wrapper, params->target_clip);
-    _cairo_surface_wrapper_set_foreground_color (&wrapper, params->foreground_color);
+
+    if (params->foreground_color) {
+	params->target->foreground_source = _cairo_pattern_create_solid (params->foreground_color);
+	params->target->foreground_used = FALSE;
+    }
 
     /* Compute the extents of the target clip in recorded device space */
     if (! _cairo_surface_wrapper_get_target_extents (&wrapper, params->surface_is_unbounded, &extents))
@@ -2019,6 +2024,12 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t	*surface,
     }
 
 done:
+    if (params->foreground_color) {
+	cairo_pattern_destroy (params->target->foreground_source);
+	params->target->foreground_source = NULL;
+	params->foreground_used = params->target->foreground_used;
+    }
+
     _cairo_surface_wrapper_fini (&wrapper);
     return _cairo_surface_set_error (&surface->base, status);
 }
@@ -2151,11 +2162,13 @@ _cairo_recording_surface_replay (cairo_surface_t *surface,
 }
 
 cairo_status_t
-_cairo_recording_surface_replay_with_foreground_color (cairo_surface_t *surface,
-                                                       cairo_surface_t *target,
-                                                       const cairo_color_t *color)
+_cairo_recording_surface_replay_with_foreground_color (cairo_surface_t     *surface,
+                                                       cairo_surface_t     *target,
+						       const cairo_color_t *foreground_color,
+						       cairo_bool_t        *foreground_used)
 {
     cairo_recording_surface_replay_params_t params;
+    cairo_status_t status;
 
     params.surface_extents = NULL;
     params.surface_transform = NULL;
@@ -2164,9 +2177,13 @@ _cairo_recording_surface_replay_with_foreground_color (cairo_surface_t *surface,
     params.surface_is_unbounded = FALSE;
     params.type = CAIRO_RECORDING_REPLAY;
     params.region = CAIRO_RECORDING_REGION_ALL;
-    params.foreground_color = color;
+    params.foreground_color = foreground_color;
+    params.foreground_used = FALSE;
 
-    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, &params);
+    status = _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, &params);
+    *foreground_used = params.foreground_used;
+
+    return status;
 }
 
 cairo_status_t
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index e4ad5f3b1..35b559f9c 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -104,6 +104,9 @@ struct _cairo_surface {
      * cairo_surface_create_similar().
      */
     cairo_font_options_t font_options;
+
+    cairo_pattern_t *foreground_source;
+    cairo_bool_t foreground_used;
 };
 
 cairo_private cairo_surface_t *
diff --git a/src/cairo-surface-wrapper-private.h b/src/cairo-surface-wrapper-private.h
index 7c3bc56ba..380ba099d 100644
--- a/src/cairo-surface-wrapper-private.h
+++ b/src/cairo-surface-wrapper-private.h
@@ -53,7 +53,6 @@ struct _cairo_surface_wrapper {
     cairo_bool_t has_extents;
     cairo_rectangle_int_t extents;
     const cairo_clip_t *clip;
-    cairo_pattern_t *foreground_source;
 
     cairo_bool_t needs_transform;
 };
@@ -74,10 +73,6 @@ cairo_private void
 _cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper,
 				 const cairo_clip_t *clip);
 
-cairo_private void
-_cairo_surface_wrapper_set_foreground_color (cairo_surface_wrapper_t *wrapper,
-                                             const cairo_color_t *color);
-
 cairo_private void
 _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper);
 
diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c
index 8ba82bd40..7fb417a20 100644
--- a/src/cairo-surface-wrapper.c
+++ b/src/cairo-surface-wrapper.c
@@ -144,9 +144,6 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
     if (_cairo_clip_is_all_clipped (dev_clip))
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
-    if (source->is_userfont_foreground && wrapper->foreground_source)
-        source = wrapper->foreground_source;
-
     if (wrapper->needs_transform) {
 	cairo_matrix_t m;
 
@@ -185,9 +182,6 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
     if (_cairo_clip_is_all_clipped (dev_clip))
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
-    if (source->is_userfont_foreground && wrapper->foreground_source)
-        source = wrapper->foreground_source;
-
     if (wrapper->needs_transform) {
 	cairo_matrix_t m;
 
@@ -235,9 +229,6 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
     if (_cairo_clip_is_all_clipped (dev_clip))
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
-    if (source->is_userfont_foreground && wrapper->foreground_source)
-        source = wrapper->foreground_source;
-
     if (wrapper->needs_transform) {
 	cairo_matrix_t m;
 
@@ -306,12 +297,6 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
     if (_cairo_clip_is_all_clipped (dev_clip))
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
-    if (fill_source->is_userfont_foreground && wrapper->foreground_source)
-        fill_source = wrapper->foreground_source;
-
-    if (stroke_source->is_userfont_foreground && wrapper->foreground_source)
-        stroke_source = wrapper->foreground_source;
-
     if (wrapper->needs_transform) {
 	cairo_matrix_t m;
 
@@ -377,9 +362,6 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t	*wrapper,
     if (_cairo_clip_is_all_clipped (dev_clip))
 	return CAIRO_INT_STATUS_NOTHING_TO_DO;
 
-    if (source->is_userfont_foreground && wrapper->foreground_source)
-        source = wrapper->foreground_source;
-
     if (wrapper->needs_transform) {
 	cairo_matrix_t m;
 
@@ -443,9 +425,6 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
     cairo_surface_get_font_options (wrapper->target, &options);
     cairo_font_options_merge (&options, &scaled_font->options);
 
-    if (source->is_userfont_foreground && wrapper->foreground_source)
-        source = wrapper->foreground_source;
-
     if (wrapper->needs_transform) {
 	cairo_matrix_t m;
 	int i;
@@ -612,14 +591,6 @@ _cairo_surface_wrapper_set_clip (cairo_surface_wrapper_t *wrapper,
     wrapper->clip = clip;
 }
 
-void
-_cairo_surface_wrapper_set_foreground_color (cairo_surface_wrapper_t *wrapper,
-                                             const cairo_color_t *color)
-{
-    if (color)
-        wrapper->foreground_source = _cairo_pattern_create_solid (color);
-}
-
 void
 _cairo_surface_wrapper_get_font_options (cairo_surface_wrapper_t    *wrapper,
 					 cairo_font_options_t	    *options)
@@ -651,7 +622,6 @@ _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
     wrapper->has_extents = FALSE;
     wrapper->extents.x = wrapper->extents.y = 0;
     wrapper->clip = NULL;
-    wrapper->foreground_source = NULL;
 
     wrapper->needs_transform = FALSE;
     if (target) {
@@ -663,9 +633,6 @@ _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
 void
 _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper)
 {
-    if (wrapper->foreground_source)
-        cairo_pattern_destroy (wrapper->foreground_source);
-
     cairo_surface_destroy (wrapper->target);
 }
 
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 105f4bff1..399958d02 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -134,7 +134,9 @@ const cairo_surface_t name = {					\
       CAIRO_HINT_STYLE_DEFAULT,		/* hint_style */	\
       CAIRO_HINT_METRICS_DEFAULT,	/* hint_metrics */	\
       CAIRO_ROUND_GLYPH_POS_DEFAULT	/* round_glyph_positions */	\
-    }					/* font_options */	\
+    },					/* font_options */		\
+    NULL,                               /* foreground_source */		\
+    FALSE,                              /* foreground_used */   \
 }
 
 /* XXX error object! */
@@ -439,6 +441,9 @@ _cairo_surface_init (cairo_surface_t			*surface,
     surface->snapshot_of = NULL;
 
     surface->has_font_options = FALSE;
+
+    surface->foreground_source = NULL;
+    surface->foreground_used = FALSE;
 }
 
 static void
@@ -976,6 +981,9 @@ cairo_surface_destroy (cairo_surface_t *surface)
     _cairo_user_data_array_fini (&surface->user_data);
     _cairo_user_data_array_fini (&surface->mime_data);
 
+    if (surface->foreground_source)
+	cairo_pattern_destroy (surface->foreground_source);
+
     if (surface->owns_device)
         cairo_device_destroy (surface->device);
 
@@ -2196,6 +2204,11 @@ _cairo_surface_paint (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
+    if (source->is_userfont_foreground && surface->foreground_source) {
+	source = surface->foreground_source;
+	surface->foreground_used = TRUE;
+    }
+
     status = surface->backend->paint (surface, op, source, clip);
     is_clear = op == CAIRO_OPERATOR_CLEAR && clip == NULL;
     if (status != CAIRO_INT_STATUS_NOTHING_TO_DO || is_clear) {
@@ -2246,6 +2259,11 @@ _cairo_surface_mask (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
+    if (source->is_userfont_foreground && surface->foreground_source) {
+	source = surface->foreground_source;
+	surface->foreground_used = TRUE;
+    }
+
     status = surface->backend->mask (surface, op, source, mask, clip);
     if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
 	surface->is_clear = FALSE;
@@ -2302,6 +2320,16 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
     if (unlikely (status))
 	return status;
 
+    if (fill_source->is_userfont_foreground && surface->foreground_source) {
+	fill_source = surface->foreground_source;
+	surface->foreground_used = TRUE;
+    }
+
+    if (stroke_source->is_userfont_foreground && surface->foreground_source) {
+	stroke_source = surface->foreground_source;
+	surface->foreground_used = TRUE;
+    }
+
     if (surface->backend->fill_stroke) {
 	cairo_matrix_t dev_ctm = *stroke_ctm;
 	cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
@@ -2376,6 +2404,11 @@ _cairo_surface_stroke (cairo_surface_t			*surface,
     if (unlikely (status))
 	return status;
 
+    if (source->is_userfont_foreground && surface->foreground_source) {
+	source = surface->foreground_source;
+	surface->foreground_used = TRUE;
+    }
+
     status = surface->backend->stroke (surface, op, source,
 				       path, stroke_style,
 				       ctm, ctm_inverse,
@@ -2421,6 +2454,11 @@ _cairo_surface_fill (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
+    if (source->is_userfont_foreground && surface->foreground_source) {
+	source = surface->foreground_source;
+	surface->foreground_used = TRUE;
+    }
+
     status = surface->backend->fill (surface, op, source,
 				     path, fill_rule,
 				     tolerance, antialias,
@@ -2901,6 +2939,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
     if (unlikely (status))
 	return status;
 
+    if (source->is_userfont_foreground && surface->foreground_source)
+	source = surface->foreground_source;
+
     if (_cairo_scaled_font_has_color_glyphs (scaled_font) &&
 	scaled_font->options.color_mode != CAIRO_COLOR_MODE_NO_COLOR)
     {
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 19b2b84fb..c0971e102 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -207,6 +207,9 @@ _cairo_type3_glyph_surface_paint (void			*abstract_surface,
 	return status;
 
     pattern = (const cairo_surface_pattern_t *) source;
+    if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
+	return CAIRO_INT_STATUS_IMAGE_FALLBACK;
+
     status = _cairo_surface_acquire_source_image (pattern->surface,
 						  &image, &image_extra);
     if (unlikely (status))
@@ -291,33 +294,7 @@ _cairo_type3_glyph_surface_show_glyphs (void		     *abstract_surface,
 					cairo_scaled_font_t  *scaled_font,
 					const cairo_clip_t     *clip)
 {
-    cairo_type3_glyph_surface_t *surface = abstract_surface;
-    cairo_int_status_t status;
-    cairo_scaled_font_t *font;
-    cairo_matrix_t new_ctm;
-
-    status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
-    if (unlikely (status))
-	return status;
-
-    cairo_matrix_multiply (&new_ctm, &surface->cairo_to_pdf, &scaled_font->ctm);
-    font = cairo_scaled_font_create (scaled_font->font_face,
-				     &scaled_font->font_matrix,
-				     &new_ctm,
-				     &scaled_font->options);
-    if (unlikely (font->status))
-	return font->status;
-
-    status = _cairo_pdf_operators_show_text_glyphs (&surface->pdf_operators,
-						    NULL, 0,
-						    glyphs, num_glyphs,
-						    NULL, 0,
-						    FALSE,
-						    font);
-
-    cairo_scaled_font_destroy (font);
-
-    return status;
+    return CAIRO_INT_STATUS_IMAGE_FALLBACK;
 }
 
 static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 03002d603..80cd4c303 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -265,6 +265,7 @@ _cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t  *scaled_font,
     cairo_surface_t *surface;
     cairo_format_t format;
     int width, height;
+    cairo_bool_t foreground_used;
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
 
     /* TODO
@@ -310,7 +311,8 @@ _cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t  *scaled_font,
     if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
 	status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
 									surface,
-									foreground_color);
+									foreground_color,
+									&foreground_used);
     } else {
 	status = _cairo_recording_surface_replay (scaled_glyph->recording_surface, surface);
     }
@@ -324,7 +326,7 @@ _cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t  *scaled_font,
 	_cairo_scaled_glyph_set_color_surface (scaled_glyph,
 					       &scaled_font->base,
 					       (cairo_image_surface_t *)surface,
-					       TRUE);
+					       foreground_used);
 	surface = NULL;
     } else {
 	_cairo_scaled_glyph_set_surface (scaled_glyph,
diff --git a/test/reference/user-font-color.image16.ref.png b/test/reference/user-font-color.image16.ref.png
index 404fbf948..6e3fe434c 100644
Binary files a/test/reference/user-font-color.image16.ref.png and b/test/reference/user-font-color.image16.ref.png differ
diff --git a/test/reference/user-font-color.pdf.ref.png b/test/reference/user-font-color.pdf.ref.png
index 674d1a4d6..9cb145202 100644
Binary files a/test/reference/user-font-color.pdf.ref.png and b/test/reference/user-font-color.pdf.ref.png differ
diff --git a/test/reference/user-font-color.quartz.ref.png b/test/reference/user-font-color.quartz.ref.png
index fc976e8ea..712e9a3d9 100644
Binary files a/test/reference/user-font-color.quartz.ref.png and b/test/reference/user-font-color.quartz.ref.png differ
diff --git a/test/reference/user-font-color.recording.ref.png b/test/reference/user-font-color.recording.ref.png
index 0b4cb06f5..68c058adc 100644
Binary files a/test/reference/user-font-color.recording.ref.png and b/test/reference/user-font-color.recording.ref.png differ
diff --git a/test/reference/user-font-color.ref.png b/test/reference/user-font-color.ref.png
index c4294c5f7..9c33df7cd 100644
Binary files a/test/reference/user-font-color.ref.png and b/test/reference/user-font-color.ref.png differ
diff --git a/test/reference/user-font-color.script.xfail.png b/test/reference/user-font-color.script.xfail.png
index e268cdc03..61ceab505 100644
Binary files a/test/reference/user-font-color.script.xfail.png and b/test/reference/user-font-color.script.xfail.png differ
diff --git a/test/reference/user-font-color.svg.ref.png b/test/reference/user-font-color.svg.ref.png
deleted file mode 100644
index 4ce8882f8..000000000
Binary files a/test/reference/user-font-color.svg.ref.png and /dev/null differ
diff --git a/test/reference/user-font-color.svg.rgb24.xfail.png b/test/reference/user-font-color.svg.rgb24.xfail.png
deleted file mode 100644
index 37b8aaa1e..000000000
Binary files a/test/reference/user-font-color.svg.rgb24.xfail.png and /dev/null differ
diff --git a/test/reference/user-font-proxy.pdf.argb32.ref.png b/test/reference/user-font-proxy.pdf.argb32.ref.png
index 9d61720e7..749c61bcd 100644
Binary files a/test/reference/user-font-proxy.pdf.argb32.ref.png and b/test/reference/user-font-proxy.pdf.argb32.ref.png differ
diff --git a/test/reference/user-font-proxy.pdf.rgb24.ref.png b/test/reference/user-font-proxy.pdf.rgb24.ref.png
index cffa9edb7..749c61bcd 100644
Binary files a/test/reference/user-font-proxy.pdf.rgb24.ref.png and b/test/reference/user-font-proxy.pdf.rgb24.ref.png differ
diff --git a/test/reference/user-font-proxy.quartz.ref.png b/test/reference/user-font-proxy.quartz.ref.png
index f7b1163be..710f58a92 100644
Binary files a/test/reference/user-font-proxy.quartz.ref.png and b/test/reference/user-font-proxy.quartz.ref.png differ
commit 513c49e623887ed4c9e6a86e81d35cccde6d1662
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Dec 31 20:26:40 2022 +1030

    user-font-color test: draw glyphs again inside a group
    
    This demonstrates a bug in user-fonts with foreground color inside a
    group.

diff --git a/test/user-font-color.c b/test/user-font-color.c
index 781d6945d..c35e693be 100644
--- a/test/user-font-color.c
+++ b/test/user-font-color.c
@@ -38,10 +38,10 @@
 
 #define BORDER 10
 #define TEXT_SIZE 64
-#define WIDTH  (TEXT_SIZE * 6 + 2*BORDER)
+#define WIDTH  (TEXT_SIZE * 12 + 2*BORDER)
 #define HEIGHT (TEXT_SIZE + 2*BORDER)
 
-#define TEXT   "abcdef"
+#define TEXT   "abcdefghijkl"
 
 
 static cairo_status_t
@@ -64,6 +64,7 @@ render_glyph_solid (cairo_t *cr, double width, double height, cairo_bool_t color
     cairo_rectangle (cr, 0, 0, width/2, height/2);
     cairo_fill (cr);
 
+    /* Draw the middle rectangle using the foreground color */
     if (color)
         cairo_set_source (cr, pattern);
     cairo_rectangle (cr, width/4, height/4, width/2, height/2);
@@ -133,6 +134,11 @@ test_scaled_font_render_color_glyph (cairo_scaled_font_t  *scaled_font,
         case 'c':
             render_glyph_text (cr, width, height, TRUE);
             break;
+
+            /* Ensure that the following glyphs are rendered with
+             * test_scaled_font_render_glyph() even if we draw
+             * something before returning.
+             */
         case 'd':
             render_glyph_solid (cr, width, height, TRUE);
             status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
@@ -145,6 +151,26 @@ test_scaled_font_render_color_glyph (cairo_scaled_font_t  *scaled_font,
             render_glyph_solid (cr, width, height, TRUE);
             status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
             break;
+        case 'g':
+            cairo_push_group (cr);
+            render_glyph_solid (cr, width, height, TRUE);
+            cairo_pop_group_to_source (cr);
+            cairo_paint (cr);
+            break;
+        case 'h':
+            cairo_push_group (cr);
+            render_glyph_linear (cr, width, height, TRUE);
+            cairo_pop_group_to_source (cr);
+            cairo_paint (cr);
+            break;
+        case 'i':
+            cairo_push_group (cr);
+            render_glyph_text (cr, width, height, TRUE);
+            cairo_pop_group_to_source (cr);
+            cairo_paint (cr);
+            break;
+        default:
+            status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
     }
 
     return status;
@@ -170,6 +196,26 @@ test_scaled_font_render_glyph (cairo_scaled_font_t  *scaled_font,
         case 'f':
             render_glyph_text (cr, width, height, FALSE);
             break;
+        case 'j':
+            cairo_push_group (cr);
+            render_glyph_solid (cr, width, height, FALSE);
+            cairo_pop_group_to_source (cr);
+            cairo_paint (cr);
+            break;
+        case 'k':
+            cairo_push_group (cr);
+            render_glyph_linear (cr, width, height, FALSE);
+            cairo_pop_group_to_source (cr);
+            cairo_paint (cr);
+            break;
+        case 'l':
+            cairo_push_group (cr);
+            render_glyph_text (cr, width, height, FALSE);
+            cairo_pop_group_to_source (cr);
+            cairo_paint (cr);
+            break;
+        default:
+            return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
     }
 
     return CAIRO_STATUS_SUCCESS;


More information about the cairo-commit mailing list