[cairo-commit] 4 commits - src/cairo-colr-glyph-render.c src/cairo-ft-font.c src/cairo-ft-private.h src/cairo-gstate.c src/cairo-pattern.c src/cairo-pattern-private.h src/cairo-recording-surface.c src/cairo-scaled-font.c src/cairo-scaled-font-private.h src/cairo-surface.c src/cairo-svg-glyph-render.c src/cairo-user-font.c test/cairo-svg-test-color.ttx test/cairo-svg-test-palette.ttx test/ft-svg-render-color.c test/ft-svg-render-palette.c test/meson.build test/reference test/svg

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Jan 28 04:54:28 UTC 2023


 dev/null                                     |binary
 src/cairo-colr-glyph-render.c                |   86 ++++++++++-----
 src/cairo-ft-font.c                          |  141 ++++++++++++++-----------
 src/cairo-ft-private.h                       |    9 +
 src/cairo-gstate.c                           |    2 
 src/cairo-pattern-private.h                  |    5 
 src/cairo-pattern.c                          |   20 ++-
 src/cairo-recording-surface.c                |    2 
 src/cairo-scaled-font-private.h              |    6 -
 src/cairo-scaled-font.c                      |   26 ++--
 src/cairo-surface.c                          |   14 +-
 src/cairo-svg-glyph-render.c                 |   77 +++++++-------
 src/cairo-user-font.c                        |   17 ---
 test/cairo-svg-test-color.ttx                |  148 +++++++++++++++++++++++++--
 test/ft-svg-render-color.c                   |   29 +++--
 test/meson.build                             |    4 
 test/reference/ft-svg-render-color.ref.png   |binary
 test/svg/color.2.foreground-solid.svg        |    4 
 test/svg/color.3.foreground-alpha.svg        |    4 
 test/svg/color.4.foreground-linear.svg       |   10 +
 test/svg/color.5.foreground-linear-alpha.svg |   10 +
 test/svg/color.6.foreground-radial.svg       |   10 +
 test/svg/color.7.foreground-radial-alpha.svg |   10 +
 23 files changed, 445 insertions(+), 189 deletions(-)

New commits:
commit b67afda591f90a40ba7eafcf42dbf36ed7a746e6
Merge: ffabca792 bdf97dd2a
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sat Jan 28 04:54:26 2023 +0000

    Merge branch 'fix-ft-foreground' into 'master'
    
    Fix foreground colors in FT/SVG/COLRv1
    
    See merge request cairo/cairo!430

commit bdf97dd2a16886f53f840f1d76922a28e4f36e63
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Jan 27 20:05:15 2023 +1030

    Rename is_userfont_foreground to is_foreground_marker
    
    as it is used by FT as well as user fonts.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 0860db593..0f4fd541a 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1145,7 +1145,7 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
     }
     _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
 
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID && !source->is_userfont_foreground &&
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID && !source->is_foreground_marker &&
 	mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
 	_cairo_operator_bounded_by_source (op))
     {
diff --git a/src/cairo-pattern-private.h b/src/cairo-pattern-private.h
index 6e658b54f..d061b39c4 100644
--- a/src/cairo-pattern-private.h
+++ b/src/cairo-pattern-private.h
@@ -72,7 +72,7 @@ struct _cairo_pattern {
     cairo_filter_t		filter;
     cairo_extend_t		extend;
     cairo_bool_t		has_component_alpha;
-    cairo_bool_t		is_userfont_foreground;
+    cairo_bool_t		is_foreground_marker;
 
     cairo_matrix_t		matrix;
     double			opacity;
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 37abc19cf..d16ed2836 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -76,7 +76,7 @@ static const cairo_solid_pattern_t _cairo_pattern_nil = {
       CAIRO_FILTER_DEFAULT,		/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT,	/* extend */
       FALSE,				/* has component alpha */
-      FALSE,				/* is_userfont_foreground */
+      FALSE,				/* is_foreground_marker */
       { 1., 0., 0., 1., 0., 0., },	/* matrix */
       1.0                               /* opacity */
     }
@@ -93,7 +93,7 @@ static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
       CAIRO_FILTER_DEFAULT,		/* filter */
       CAIRO_EXTEND_GRADIENT_DEFAULT,	/* extend */
       FALSE,				/* has component alpha */
-      FALSE,				/* is_userfont_foreground */
+      FALSE,				/* is_foreground_marker */
       { 1., 0., 0., 1., 0., 0., },	/* matrix */
       1.0                               /* opacity */
     }
@@ -110,7 +110,7 @@ const cairo_solid_pattern_t _cairo_pattern_black = {
       CAIRO_FILTER_NEAREST,		/* filter */
       CAIRO_EXTEND_REPEAT,		/* extend */
       FALSE,				/* has component alpha */
-      FALSE,				/* is_userfont_foreground */
+      FALSE,				/* is_foreground_marker */
       { 1., 0., 0., 1., 0., 0., },	/* matrix */
       1.0                               /* opacity */
     },
@@ -128,7 +128,7 @@ const cairo_solid_pattern_t _cairo_pattern_clear = {
       CAIRO_FILTER_NEAREST,		/* filter */
       CAIRO_EXTEND_REPEAT,		/* extend */
       FALSE,				/* has component alpha */
-      FALSE,				/* is_userfont_foreground */
+      FALSE,				/* is_foreground_marker */
       { 1., 0., 0., 1., 0., 0., },	/* matrix */
       1.0                               /* opacity */
     },
@@ -146,7 +146,7 @@ const cairo_solid_pattern_t _cairo_pattern_white = {
       CAIRO_FILTER_NEAREST,		/* filter */
       CAIRO_EXTEND_REPEAT,		/* extend */
       FALSE,				/* has component alpha */
-      FALSE,				/* is_userfont_foreground */
+      FALSE,				/* is_foreground_marker */
       { 1., 0., 0., 1., 0., 0., },	/* matrix */
       1.0                               /* opacity */
     },
@@ -238,7 +238,7 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
     pattern->opacity   = 1.0;
 
     pattern->has_component_alpha = FALSE;
-    pattern->is_userfont_foreground = FALSE;
+    pattern->is_foreground_marker = FALSE;
 
     cairo_matrix_init_identity (&pattern->matrix);
 
@@ -628,7 +628,7 @@ cairo_pattern_t *
 _cairo_pattern_create_foreground_marker (void)
 {
     cairo_pattern_t *pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
-    pattern->is_userfont_foreground = TRUE;
+    pattern->is_foreground_marker = TRUE;
     return pattern;
 }
 
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index a7de8df5b..e87320523 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -2706,7 +2706,7 @@ print_pattern (FILE                  *file,
     switch (pattern->type) {
 	case CAIRO_PATTERN_TYPE_SOLID: {
 	    cairo_solid_pattern_t *p = (cairo_solid_pattern_t *) pattern;
-	    if (pattern->is_userfont_foreground) {
+	    if (pattern->is_foreground_marker) {
 		fprintf (file, "solid foreground\n");
 	    } else {
 		fprintf (file, "solid rgba: %f %f %f %f\n",
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 503a9a1c1..e9e6233a6 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2204,7 +2204,7 @@ _cairo_surface_paint (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
-    if (source->is_userfont_foreground && surface->foreground_source) {
+    if (source->is_foreground_marker && surface->foreground_source) {
 	source = surface->foreground_source;
 	surface->foreground_used = TRUE;
     }
@@ -2259,7 +2259,7 @@ _cairo_surface_mask (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
-    if (source->is_userfont_foreground && surface->foreground_source) {
+    if (source->is_foreground_marker && surface->foreground_source) {
 	source = surface->foreground_source;
 	surface->foreground_used = TRUE;
     }
@@ -2320,12 +2320,12 @@ _cairo_surface_fill_stroke (cairo_surface_t	    *surface,
     if (unlikely (status))
 	return status;
 
-    if (fill_source->is_userfont_foreground && surface->foreground_source) {
+    if (fill_source->is_foreground_marker && surface->foreground_source) {
 	fill_source = surface->foreground_source;
 	surface->foreground_used = TRUE;
     }
 
-    if (stroke_source->is_userfont_foreground && surface->foreground_source) {
+    if (stroke_source->is_foreground_marker && surface->foreground_source) {
 	stroke_source = surface->foreground_source;
 	surface->foreground_used = TRUE;
     }
@@ -2404,7 +2404,7 @@ _cairo_surface_stroke (cairo_surface_t			*surface,
     if (unlikely (status))
 	return status;
 
-    if (source->is_userfont_foreground && surface->foreground_source) {
+    if (source->is_foreground_marker && surface->foreground_source) {
 	source = surface->foreground_source;
 	surface->foreground_used = TRUE;
     }
@@ -2454,7 +2454,7 @@ _cairo_surface_fill (cairo_surface_t		*surface,
     if (unlikely (status))
 	return status;
 
-    if (source->is_userfont_foreground && surface->foreground_source) {
+    if (source->is_foreground_marker && surface->foreground_source) {
 	source = surface->foreground_source;
 	surface->foreground_used = TRUE;
     }
@@ -2944,7 +2944,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
     if (unlikely (status))
 	return status;
 
-    if (source->is_userfont_foreground && surface->foreground_source)
+    if (source->is_foreground_marker && surface->foreground_source)
 	source = surface->foreground_source;
 
     if (_cairo_scaled_font_has_color_glyphs (scaled_font) &&
commit 9e59808ecb5f39e551e5e2ffbdab08c8ec66d21b
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Jan 27 19:18:10 2023 +1030

    svg: test foreground colors
    
    Convert the ft-svg-render-palette test to a color test that test
    both palettes and foreground colors.

diff --git a/test/cairo-svg-test-palette.ttx b/test/cairo-svg-test-color.ttx
similarity index 98%
rename from test/cairo-svg-test-palette.ttx
rename to test/cairo-svg-test-color.ttx
index 1b0630913..a915a704b 100644
--- a/test/cairo-svg-test-palette.ttx
+++ b/test/cairo-svg-test-color.ttx
@@ -18,12 +18,12 @@
     <!-- Most of this table will be recalculated by the compiler -->
     <tableVersion value="1.0"/>
     <fontRevision value="1.0"/>
-    <checkSumAdjustment value="0x1b8ac35c"/>
+    <checkSumAdjustment value="0x1d3a9a74"/>
     <magicNumber value="0x5f0f3cf5"/>
     <flags value="00000000 00000011"/>
     <unitsPerEm value="1000"/>
     <created value="Wed Jun 15 00:00:00 2022"/>
-    <modified value="Fri Jan 27 07:13:15 2023"/>
+    <modified value="Fri Jan 27 08:44:23 2023"/>
     <xMin value="0"/>
     <yMin value="0"/>
     <xMax value="1000"/>
@@ -248,13 +248,13 @@
 
   <name>
     <namerecord nameID="1" platformID="3" platEncID="1" langID="0x409">
-      Cairo Svg Test Palette
+      Cairo Svg Test Color
     </namerecord>
     <namerecord nameID="2" platformID="3" platEncID="1" langID="0x409">
       Regular
     </namerecord>
     <namerecord nameID="4" platformID="3" platEncID="1" langID="0x409">
-      Cairo Svg Test Palette Regular
+      Cairo Svg Test Color Regular
     </namerecord>
   </name>
 
diff --git a/test/ft-svg-render-palette.c b/test/ft-svg-render-color.c
similarity index 96%
rename from test/ft-svg-render-palette.c
rename to test/ft-svg-render-color.c
index eee5f27c8..c7572d5b0 100644
--- a/test/ft-svg-render-palette.c
+++ b/test/ft-svg-render-color.c
@@ -32,7 +32,7 @@
 #define WIDTH  (FONT_SIZE*8 + MARGIN*9)
 #define HEIGHT (FONT_SIZE*2 + MARGIN*3)
 
-#define FONT_FILE "cairo-svg-test-palette.ttf"
+#define FONT_FILE "cairo-svg-test-color.ttf"
 
 #define PALETTE_TEXT     "01"
 #define FOREGROUND_TEXT  "234567"
@@ -90,8 +90,8 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-CAIRO_TEST (ft_svg_render_palette,
-	    "Test cairo SVG font palettes",
+CAIRO_TEST (ft_svg_render_color,
+	    "Test cairo SVG font colors",
 	    "svgrender", /* keywords */
 	    NULL, /* requirements */
 	    WIDTH, HEIGHT,
diff --git a/test/meson.build b/test/meson.build
index 275dd07d7..e5b4f89d5 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -436,7 +436,7 @@ test_ft_svg_font_sources = [
 test_ft_svg_ttx_font_sources = [
   'ft-svg-cairo-logo.c',
   'ft-svg-render.c',
-  'ft-svg-render-palette.c'
+  'ft-svg-render-color.c'
 ]
 
 test_gl_sources = [
@@ -532,10 +532,10 @@ ps2png_sources = [
 
 test_ttx_fonts = [
   'cairo-logo-font.ttx',
+  'cairo-svg-test-color.ttx',
   'cairo-svg-test-doc.ttx',
   'cairo-svg-test-fill.ttx',
   'cairo-svg-test-gradient.ttx',
-  'cairo-svg-test-palette.ttx',
   'cairo-svg-test-path.ttx',
   'cairo-svg-test-shapes.ttx',
   'cairo-svg-test-stroke.ttx',
diff --git a/test/reference/ft-svg-render-color.ref.png b/test/reference/ft-svg-render-color.ref.png
new file mode 100644
index 000000000..d688c378c
Binary files /dev/null and b/test/reference/ft-svg-render-color.ref.png differ
diff --git a/test/reference/ft-svg-render-palette.ref.png b/test/reference/ft-svg-render-palette.ref.png
deleted file mode 100644
index 4a86f995b..000000000
Binary files a/test/reference/ft-svg-render-palette.ref.png and /dev/null differ
diff --git a/test/svg/palette.0.color0.svg b/test/svg/color.0.color0.svg
similarity index 100%
rename from test/svg/palette.0.color0.svg
rename to test/svg/color.0.color0.svg
diff --git a/test/svg/palette.1.color1.svg b/test/svg/color.1.color1.svg
similarity index 100%
rename from test/svg/palette.1.color1.svg
rename to test/svg/color.1.color1.svg
diff --git a/test/svg/color.2.foreground-solid.svg b/test/svg/color.2.foreground-solid.svg
new file mode 100644
index 000000000..cf77d65a6
--- /dev/null
+++ b/test/svg/color.2.foreground-solid.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <rect x="100" y="-750" width="800" height="500"
+        fill="currentColor" />
+</svg>
diff --git a/test/svg/color.3.foreground-alpha.svg b/test/svg/color.3.foreground-alpha.svg
new file mode 100644
index 000000000..fa67d4929
--- /dev/null
+++ b/test/svg/color.3.foreground-alpha.svg
@@ -0,0 +1,4 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <rect x="100" y="-750" width="800" height="500"
+        fill="currentColor" fill-opacity="0.5"  />
+</svg>
diff --git a/test/svg/color.4.foreground-linear.svg b/test/svg/color.4.foreground-linear.svg
new file mode 100644
index 000000000..d2f8816c6
--- /dev/null
+++ b/test/svg/color.4.foreground-linear.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <linearGradient id="grad" x1="33%" x21="66%">
+      <stop offset="0%" stop-color="currentColor" stop-opacity="1" />
+      <stop offset="100%" stop-color="red" stop-opacity="1" />
+    </linearGradient>
+  </defs>
+  <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
+
diff --git a/test/svg/color.5.foreground-linear-alpha.svg b/test/svg/color.5.foreground-linear-alpha.svg
new file mode 100644
index 000000000..a3c453ad3
--- /dev/null
+++ b/test/svg/color.5.foreground-linear-alpha.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <linearGradient id="grad" x1="33%" x21="66%">
+      <stop offset="0%" stop-color="currentColor" stop-opacity="0.3" />
+      <stop offset="100%" stop-color="red" stop-opacity="0.3" />
+    </linearGradient>
+  </defs>
+  <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
+
diff --git a/test/svg/color.6.foreground-radial.svg b/test/svg/color.6.foreground-radial.svg
new file mode 100644
index 000000000..97622c2b4
--- /dev/null
+++ b/test/svg/color.6.foreground-radial.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <radialGradient id="grad" cx="50%" cy="50%"
+                    fx="0.75" fy="0.35" r="0.5">
+      <stop offset="0%" stop-color="currentColor" stop-opacity="1" />
+      <stop offset="100%" stop-color="blue" stop-opacity="1" />
+    </radialGradient>
+  </defs>
+  <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
diff --git a/test/svg/color.7.foreground-radial-alpha.svg b/test/svg/color.7.foreground-radial-alpha.svg
new file mode 100644
index 000000000..76d6628e0
--- /dev/null
+++ b/test/svg/color.7.foreground-radial-alpha.svg
@@ -0,0 +1,10 @@
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <radialGradient id="grad" cx="50%" cy="50%"
+                    fx="0.75" fy="0.35" r="0.5">
+      <stop offset="0%" stop-color="currentColor" stop-opacity="0.5" />
+      <stop offset="100%" stop-color="blue" stop-opacity="0.5" />
+    </radialGradient>
+  </defs>
+  <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>
commit c8695f050340bff1dc2b3a64cf8386c5ad19c274
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Jan 27 19:08:16 2023 +1030

    Foreground color fixes for ft, svg, colrv1

diff --git a/src/cairo-colr-glyph-render.c b/src/cairo-colr-glyph-render.c
index 104942b78..28254fd51 100644
--- a/src/cairo-colr-glyph-render.c
+++ b/src/cairo-colr-glyph-render.c
@@ -36,6 +36,7 @@
 #include "cairo-array-private.h"
 #include "cairo-ft-private.h"
 #include "cairo-path-private.h"
+#include "cairo-pattern-private.h"
 
 #include <assert.h>
 #include <math.h>
@@ -55,9 +56,11 @@
 
 typedef struct _cairo_colr_glyph_render {
     FT_Face face;
-    cairo_pattern_t *foreground_color;
     FT_Color *palette;
     unsigned int num_palette_entries;
+    cairo_pattern_t *foreground_marker;
+    cairo_pattern_t *foreground_source;
+    cairo_bool_t foreground_source_used;
     int level;
 } cairo_colr_glyph_render_t;
 
@@ -225,29 +228,29 @@ draw_paint_colr_layers (cairo_colr_glyph_render_t *render,
 
 static void
 get_palette_color (cairo_colr_glyph_render_t *render,
-                   FT_ColorIndex             *ci,
-                   cairo_color_t             *color,
-                   cairo_bool_t              *is_foreground_color)
+		   FT_ColorIndex             *ci,
+		   cairo_color_t             *color,
+		   double                    *colr_alpha,
+		   cairo_bool_t              *is_foreground_color)
 {
     cairo_bool_t foreground = FALSE;
 
     if (ci->palette_index == 0xffff || ci->palette_index >= render->num_palette_entries) {
-        color->red = 0;
-        color->green = 0;
-        color->blue = 0;
+	color->red = 0;
+	color->green = 0;
+	color->blue = 0;
 	color->alpha = 1;
-        foreground = TRUE;
+	foreground = TRUE;
     } else {
-        FT_Color c = render->palette[ci->palette_index];
-        color->red = c.red / 255.0;
-        color->green = c.green / 255.0;
-        color->blue = c.blue / 255.0;
+	FT_Color c = render->palette[ci->palette_index];
+	color->red = c.red / 255.0;
+	color->green = c.green / 255.0;
+	color->blue = c.blue / 255.0;
 	color->alpha = c.alpha / 255.0;
     }
 
-    color->alpha *= double_from_2_14 (ci->alpha);
-    if (is_foreground_color)
-        *is_foreground_color = foreground;
+    *colr_alpha = double_from_2_14 (ci->alpha);
+    *is_foreground_color = foreground;
 }
 
 static cairo_status_t
@@ -256,21 +259,19 @@ draw_paint_solid (cairo_colr_glyph_render_t *render,
                   cairo_t                   *cr)
 {
     cairo_color_t color;
+    double colr_alpha;
     cairo_bool_t is_foreground_color;
 
 #if DEBUG_COLR
     printf ("%*sDraw PaintSolid\n", 2 * render->level, "");
 #endif
 
-    get_palette_color (render, &solid->color, &color, &is_foreground_color);
-    if (is_foreground_color)
-    {
-	cairo_set_source (cr, render->foreground_color);
-	cairo_paint_with_alpha (cr, color.alpha);
-    }
-    else
-    {
-	cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha);
+    get_palette_color (render, &solid->color, &color, &colr_alpha, &is_foreground_color);
+    if (is_foreground_color) {
+	cairo_set_source (cr, render->foreground_marker);
+	cairo_paint_with_alpha (cr, colr_alpha);
+    } else {
+	cairo_set_source_rgba (cr, color.red, color.green, color.blue, color.alpha * colr_alpha);
 	cairo_paint (cr);
     }
 
@@ -315,6 +316,8 @@ read_colorline (cairo_colr_glyph_render_t *render,
     cairo_colr_color_line_t *cl;
     FT_ColorStop stop;
     int i;
+    double colr_alpha;
+    cairo_bool_t is_foreground_color;
 
     cl = calloc (1, sizeof (cairo_colr_color_line_t));
     if (unlikely (cl == NULL))
@@ -330,7 +333,28 @@ read_colorline (cairo_colr_glyph_render_t *render,
     i = 0;
     while (FT_Get_Colorline_Stops (render->face, &stop, &colorline->color_stop_iterator)) {
 	cl->stops[i].position = double_from_16_16 (stop.stop_offset);
-	get_palette_color (render, &stop.color, &cl->stops[i].color, NULL);
+	get_palette_color (render, &stop.color, &cl->stops[i].color, &colr_alpha, &is_foreground_color);
+	if (is_foreground_color) {
+	    double red, green, blue, alpha;
+	    if (cairo_pattern_get_rgba (render->foreground_source,
+					&red, &green, &blue, &alpha) == CAIRO_STATUS_SUCCESS)
+	    {
+		cl->stops[i].color.red = red;
+		cl->stops[i].color.green = green;
+		cl->stops[i].color.blue = blue;
+		cl->stops[i].color.alpha = alpha * colr_alpha;
+		render->foreground_source_used = TRUE;
+	    }
+	    else
+	    {
+		cl->stops[i].color.red = 0;
+		cl->stops[i].color.green = 0;
+		cl->stops[i].color.blue = 0;
+		cl->stops[i].color.alpha = colr_alpha;
+	    }
+	} else {
+	    cl->stops[i].color.alpha *= colr_alpha;
+	}
 	i++;
     }
 
@@ -1190,7 +1214,9 @@ _cairo_render_colr_v1_glyph (FT_Face               face,
                              unsigned long         glyph,
                              FT_Color             *palette,
                              int                   num_palette_entries,
-                             cairo_t              *cr)
+                             cairo_t              *cr,
+                             cairo_pattern_t      *foreground_source,
+                             cairo_bool_t         *foreground_source_used)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_colr_glyph_render_t colr_render;
@@ -1202,7 +1228,9 @@ _cairo_render_colr_v1_glyph (FT_Face               face,
     colr_render.face = face;
     colr_render.palette = palette;
     colr_render.num_palette_entries = num_palette_entries;
-    colr_render.foreground_color = cairo_pattern_reference (cairo_get_source (cr));
+    colr_render.foreground_marker = _cairo_pattern_create_foreground_marker ();
+    colr_render.foreground_source = cairo_pattern_reference (foreground_source);;
+    colr_render.foreground_source_used = FALSE;
     colr_render.level = 0;
 
     status = draw_colr_glyph (&colr_render,
@@ -1210,7 +1238,9 @@ _cairo_render_colr_v1_glyph (FT_Face               face,
 			      FT_COLOR_INCLUDE_ROOT_TRANSFORM,
 			      cr);
   
-    cairo_pattern_destroy (colr_render.foreground_color);
+    cairo_pattern_destroy (colr_render.foreground_marker);
+    cairo_pattern_destroy (colr_render.foreground_source);
+    *foreground_source_used = colr_render.foreground_source_used;
 
     return status;
 }
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index e6a8d20e3..75d6f8c16 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2707,7 +2707,6 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t     *scaled_font,
     return status;
 }
 
-#ifdef HAVE_FT_PALETTE_SELECT
 static cairo_int_status_t
 _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled_font,
 						  cairo_scaled_glyph_t   *scaled_glyph,
@@ -2715,6 +2714,7 @@ _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled
 						  cairo_bool_t            vertical_layout,
 						  int                     load_flags)
 {
+#ifdef HAVE_FT_PALETTE_SELECT
     cairo_surface_t *recording_surface;
     cairo_t *cr;
     cairo_status_t status;
@@ -2755,8 +2755,7 @@ _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled
     {
 	cairo_pattern_t *pattern;
 	if (layer_color_index == 0xFFFF) {
-	    pattern = cairo_pattern_create_rgb (0, 0, 0);
-	    pattern->is_userfont_foreground = TRUE;
+	    pattern = _cairo_pattern_create_foreground_marker ();
 	} else {
 	    double r = 0, g = 0, b = 0, a = 1;
 	    if (layer_color_index <  num_palette_entries) {
@@ -2800,22 +2799,25 @@ _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled
 					       recording_surface,
 					       NULL);
     return status;
-}
+#else
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 #endif
+}
 
-#if HAVE_FT_COLR_V1
 static cairo_int_status_t
 _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled_font,
 						  cairo_scaled_glyph_t   *scaled_glyph,
 						  FT_Face                 face,
+						  const cairo_color_t    *foreground_color,
 						  cairo_text_extents_t   *extents)
 {
+#if HAVE_FT_COLR_V1
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_surface_t *recording_surface;
     cairo_t *cr;
-    cairo_pattern_t *pattern;
     FT_Color *palette;
     unsigned int num_palette_entries;
+    cairo_bool_t foreground_source_used = FALSE;
 
     recording_surface =
 	cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL);
@@ -2827,11 +2829,6 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
     cairo_set_font_size (cr, 1.0);
     cairo_set_font_options (cr, &scaled_font->base.options);
 
-    pattern = cairo_pattern_create_rgb (0, 0, 0);
-    pattern->is_userfont_foreground = TRUE;
-    cairo_set_source (cr, pattern);
-    cairo_pattern_destroy (pattern);
-
     extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin);
     extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin);
     extents->width = DOUBLE_FROM_26_6(face->bbox.xMax) - extents->x_bearing;
@@ -2840,14 +2837,15 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
     _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
 
     if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
+	cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
 	status = _cairo_render_colr_v1_glyph (face,
 					      _cairo_scaled_glyph_index (scaled_glyph),
                                               palette,
                                               num_palette_entries,
-					      cr);
-	if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
-	    status = CAIRO_INT_STATUS_UNSUPPORTED;
-
+					      cr,
+					      foreground_pattern,
+					      &foreground_source_used);
+	cairo_pattern_destroy (foreground_pattern);
 	if (status == CAIRO_STATUS_SUCCESS)
 	    status = cairo_status (cr);
     }
@@ -2864,7 +2862,7 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
     _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
 					       &scaled_font->base,
 					       recording_surface,
-					       NULL);
+					       foreground_source_used ? foreground_color : NULL);
 
     scaled_glyph->color_glyph = TRUE;
     scaled_glyph->color_glyph_set = TRUE;
@@ -2937,24 +2935,27 @@ _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled
     }
 
     return status;
-}
+#else
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 #endif
+}
 
-#if HAVE_FT_SVG_DOCUMENT
 static cairo_int_status_t
 _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_font,
 					      cairo_scaled_glyph_t   *scaled_glyph,
 					      FT_Face                 face,
+					      const cairo_color_t    *foreground_color,
 					      cairo_text_extents_t   *extents)
 {
+#if HAVE_FT_SVG_DOCUMENT
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_surface_t *recording_surface;
     cairo_t *cr;
-    cairo_pattern_t *pattern;
     FT_SVG_Document svg_doc = face->glyph->other;
     char *svg_document;
     FT_Color *palette;
     unsigned int num_palette_entries;
+    cairo_bool_t foreground_source_used = FALSE;
 
     /* Create NULL terminated SVG document */
     svg_document = _cairo_strndup ((const char*)svg_doc->svg_document, svg_doc->svg_document_length);
@@ -2974,11 +2975,6 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
     cairo_set_font_size (cr, 1.0);
     cairo_set_font_options (cr, &scaled_font->base.options);
 
-    pattern = cairo_pattern_create_rgb (0, 0, 0);
-    pattern->is_userfont_foreground = TRUE;
-    cairo_set_source (cr, pattern);
-    cairo_pattern_destroy (pattern);
-
     extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin);
     extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin);
     extents->width = DOUBLE_FROM_26_6(face->bbox.xMax) - extents->x_bearing;
@@ -2987,6 +2983,7 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
     _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
 
     if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
+	cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
 	status = _cairo_render_svg_glyph (svg_document,
 					  svg_doc->start_glyph_id,
 					  svg_doc->end_glyph_id,
@@ -2994,7 +2991,10 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
 					  svg_doc->units_per_EM,
 					  palette,
 					  num_palette_entries,
-					  cr);
+					  cr,
+					  foreground_pattern,
+					  &foreground_source_used);
+	cairo_pattern_destroy (foreground_pattern);
 	if (status == CAIRO_STATUS_SUCCESS)
 	    status = cairo_status (cr);
     }
@@ -3012,7 +3012,7 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
     _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
 					       &scaled_font->base,
 					       recording_surface,
-					       NULL);
+					       foreground_source_used ? foreground_color : NULL);
 
     scaled_glyph->color_glyph = TRUE;
     scaled_glyph->color_glyph_set = TRUE;
@@ -3085,8 +3085,10 @@ _cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_fon
     }
 
     return status;
-}
+#else
+    return CAIRO_INT_STATUS_UNSUPPORTED;
 #endif
+}
 
 static cairo_int_status_t
 _cairo_ft_scaled_glyph_init_surface_for_recording_surface (cairo_ft_scaled_font_t *scaled_font,
@@ -3278,11 +3280,12 @@ _cairo_ft_scaled_glyph_is_colr_v1 (cairo_ft_scaled_font_t *scaled_font,
 static const int ft_glyph_private_key;
 
 static cairo_int_status_t
-_cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t     *scaled_font,
-				     cairo_scaled_glyph_t	*scaled_glyph,
-				     FT_Face face,
-				     cairo_bool_t vertical_layout,
-				     int load_flags)
+_cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t  *scaled_font,
+				     cairo_scaled_glyph_t    *scaled_glyph,
+				     FT_Face                  face,
+				     cairo_bool_t             vertical_layout,
+				     int                      load_flags,
+				     const cairo_color_t     *foreground_color)
 {
     cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
     cairo_text_extents_t fs_metrics;
@@ -3348,25 +3351,23 @@ _cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t     *scaled_font,
 					&fs_metrics);
 
 
-/* SVG and COLR v1 glyphs require the bounding box to be obtained from
- * the ink extents of the rendering. We need to render glyph to a
- * recording surface to obtain these extents. But we also need the
- * advance from _cairo_ft_scaled_glyph_get_metrics() before calling
- * this function.
- */
+    /* SVG and COLRv1 glyphs require the bounding box to be obtained
+     * from the ink extents of the rendering. We need to render glyph
+     * to a recording surface to obtain these extents. But we also
+     * need the advance from _cairo_ft_scaled_glyph_get_metrics()
+     * before calling this function.
+     */
 
-#if HAVE_FT_SVG_DOCUMENT
     if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
 	status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
 										   scaled_glyph,
 										   face,
+										   foreground_color,
 										   &fs_metrics);
 	if (unlikely (status))
 	    return status;
     }
-#endif
 
-#if HAVE_FT_COLR_V1
     if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
 	if (!hint_metrics) {
 	    status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
@@ -3382,11 +3383,11 @@ _cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t     *scaled_font,
 	status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
 										       scaled_glyph,
 										       face,
+										       foreground_color,
 										       &fs_metrics);
 	if (unlikely (status))
 	    return status;
     }
-#endif
 
     _cairo_scaled_glyph_set_metrics (scaled_glyph,
 				     &scaled_font->base,
@@ -3409,6 +3410,11 @@ _cairo_ft_scaled_glyph_init (void			*abstract_font,
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_bool_t scaled_glyph_loaded = FALSE;
     cairo_ft_glyph_private_t *glyph_priv;
+    int color_flag = 0;
+
+#ifdef FT_LOAD_COLOR
+    color_flag = FT_LOAD_COLOR;
+#endif
 
     face = _cairo_ft_unscaled_font_lock_face (unscaled);
     if (!face)
@@ -3432,12 +3438,14 @@ _cairo_ft_scaled_glyph_init (void			*abstract_font,
 	vertical_layout = TRUE;
     }
 
+    /* Metrics will always be requested when a scaled glyph is created */
     if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
 	status = _cairo_ft_scaled_glyph_init_metrics (scaled_font,
 						      scaled_glyph,
 						      face,
 						      vertical_layout,
-						      load_flags);
+						      load_flags,
+						      foreground_color);
 	if (unlikely (status))
 	    goto FAIL;
     }
@@ -3447,26 +3455,39 @@ _cairo_ft_scaled_glyph_init (void			*abstract_font,
     assert (glyph_priv != NULL);
 
     if (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) {
-	switch (glyph_priv->format) {
-	    case CAIRO_FT_GLYPH_TYPE_BITMAP:
-	    case CAIRO_FT_GLYPH_TYPE_OUTLINE:
-		break;
-	    case CAIRO_FT_GLYPH_TYPE_SVG:
-	    case CAIRO_FT_GLYPH_TYPE_COLR_V1:
-		/* The SVG and COLR v1 recording surfaces are
-		 * initialized in _cairo_ft_scaled_glyph_init_metrics()
-		 */
-		status = CAIRO_STATUS_SUCCESS;
-		break;
-	    case CAIRO_FT_GLYPH_TYPE_COLR_V0:
-#ifdef HAVE_FT_PALETTE_SELECT
+	status = CAIRO_INT_STATUS_UNSUPPORTED;
+	if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG ||
+	    glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0 ||
+	    glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
+	{
+	    status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
+							scaled_glyph,
+							face,
+							load_flags | color_flag,
+							FALSE,
+							vertical_layout);
+	    if (unlikely (status))
+		goto FAIL;
+
+	    if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
+		status = _cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
+								       scaled_glyph,
+								       face,
+								       foreground_color,
+								       &scaled_glyph->fs_metrics);
+	    } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
+		status = _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
+									   scaled_glyph,
+									   face,
+									   foreground_color,
+									   &scaled_glyph->fs_metrics);
+	    } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0) {
 		status = _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (scaled_font,
 									   scaled_glyph,
 									   face,
 									   vertical_layout,
 									   load_flags);
-#endif
-		break;
+	    }
 	}
 	if (status)
 	    goto FAIL;
@@ -3477,8 +3498,8 @@ _cairo_ft_scaled_glyph_init (void			*abstract_font,
 	    glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
 	{
 	    status = _cairo_ft_scaled_glyph_init_surface_for_recording_surface (scaled_font,
-								    scaled_glyph,
-								    foreground_color);
+										scaled_glyph,
+										foreground_color);
 	} else {
 	    status = _cairo_ft_scaled_glyph_init_surface (scaled_font,
 							  scaled_glyph,
diff --git a/src/cairo-ft-private.h b/src/cairo-ft-private.h
index 312f65454..836f7e523 100644
--- a/src/cairo-ft-private.h
+++ b/src/cairo-ft-private.h
@@ -1,3 +1,4 @@
+/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 /* cairo - a vector graphics library with display and print output
  *
  * Copyright © 2005 Red Hat, Inc
@@ -74,7 +75,9 @@ _cairo_render_svg_glyph (const char           *svg_document,
                          double                units_per_em,
                          FT_Color             *palette,
                          int                   num_palette_entries,
-                         cairo_t              *cr);
+                         cairo_t              *cr,
+                         cairo_pattern_t      *foreground_source,
+                         cairo_bool_t         *foreground_source_used);
 #endif
 
 #if HAVE_FT_COLR_V1
@@ -83,7 +86,9 @@ _cairo_render_colr_v1_glyph (FT_Face                 face,
                              unsigned long           glyph,
                              FT_Color               *palette,
                              int                     num_palette_entries,
-                             cairo_t                *cr);
+                             cairo_t                *cr,
+                             cairo_pattern_t        *foreground_source,
+                             cairo_bool_t           *foreground_source_used);
 #endif
 
 CAIRO_END_DECLS
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index 0d52491c9..0860db593 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -1145,7 +1145,7 @@ _cairo_gstate_mask (cairo_gstate_t  *gstate,
     }
     _cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
 
-    if (source->type == CAIRO_PATTERN_TYPE_SOLID &&
+    if (source->type == CAIRO_PATTERN_TYPE_SOLID && !source->is_userfont_foreground &&
 	mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
 	_cairo_operator_bounded_by_source (op))
     {
diff --git a/src/cairo-pattern-private.h b/src/cairo-pattern-private.h
index 0a5e41e8b..6e658b54f 100644
--- a/src/cairo-pattern-private.h
+++ b/src/cairo-pattern-private.h
@@ -240,6 +240,9 @@ _cairo_pattern_fini (cairo_pattern_t *pattern);
 cairo_private cairo_pattern_t *
 _cairo_pattern_create_solid (const cairo_color_t	*color);
 
+cairo_private cairo_pattern_t *
+_cairo_pattern_create_foreground_marker (void);
+
 cairo_private void
 _cairo_pattern_transform (cairo_pattern_t      *pattern,
 			  const cairo_matrix_t *ctm_inverse);
diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 070309ac6..37abc19cf 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -624,6 +624,14 @@ _cairo_pattern_create_solid (const cairo_color_t *color)
     return &pattern->base;
 }
 
+cairo_pattern_t *
+_cairo_pattern_create_foreground_marker (void)
+{
+    cairo_pattern_t *pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
+    pattern->is_userfont_foreground = TRUE;
+    return pattern;
+}
+
 cairo_pattern_t *
 _cairo_pattern_create_in_error (cairo_status_t status)
 {
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index 8c10b60c7..64abbe0f5 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -150,11 +150,11 @@ struct _cairo_scaled_glyph {
 
     cairo_color_t           foreground_color;   /* only used for color glyphs */
 
-    /* TRUE if the recording_surface required the foreground_color to render. */
+    /* TRUE if the recording_surface used the foreground_source to render. */
     unsigned                recording_uses_foreground_color : 1;
 
-    /* TRUE if the color_surface required the foreground_color to render. */
-    unsigned                image_uses_foreground_color : 1;
+    /* TRUE if the recording surface uses the foreground marker. */
+    unsigned                recording_uses_foreground_marker : 1;
 
     /* TRUE if color_glyph specifies if glyph is color or non color, FALSE if glyph color type unknown. */
     unsigned                color_glyph_set : 1;
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index d7e3f1e4b..415b45f78 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2688,14 +2688,15 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
  * @scaled_glyph: a #cairo_scaled_glyph_t
  * @scaled_font: a #cairo_scaled_font_t
  * @surface: The image surface
- * @foreground_color: The foreground color that was used to render the
- * glyph, or NULL if foreground color not required.
+ * @foreground_marker_color: The foreground color that was used to
+ * substitute the foreground_marker, or NULL if foreground_marker not
+ * used when rendering the surface color.
  */
 void
 _cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t  *scaled_glyph,
 	                               cairo_scaled_font_t   *scaled_font,
 	                               cairo_image_surface_t *surface,
-				       const cairo_color_t   *foreground_color)
+				       const cairo_color_t   *foreground_marker_color)
 {
     if (scaled_glyph->color_surface != NULL)
 	cairo_surface_destroy (&scaled_glyph->color_surface->base);
@@ -2703,9 +2704,9 @@ _cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t  *scaled_glyph,
     /* sanity check the backend glyph contents */
     _cairo_debug_check_image_surface_is_defined (&surface->base);
     scaled_glyph->color_surface = surface;
-    scaled_glyph->image_uses_foreground_color = foreground_color != NULL;
-    if (foreground_color)
-	scaled_glyph->foreground_color = *foreground_color;
+    scaled_glyph->recording_uses_foreground_marker = foreground_marker_color != NULL;
+    if (foreground_marker_color)
+	scaled_glyph->foreground_color = *foreground_marker_color;
 
     if (surface != NULL)
 	scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
@@ -2935,19 +2936,20 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     /* If requesting a color surface or recording for a glyph that has
-     * used the foreground color to render the color_surface, and the
-     * foreground color has changed, request a new image and/or
-     * recording. */
-
-    if (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE &&
+     * used the foreground color to render the recording, and the
+     * foreground color has changed, request a new  recording. */
+    if ((info & (CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) &&
 	scaled_glyph->recording_uses_foreground_color &&
 	!_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
     {
 	need_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
     }
 
+    /* If requesting a color surface for a glyph that has
+     * used the foreground color to render the color_surface, and the
+     * foreground color has changed, request a new image. */
     if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE &&
-	scaled_glyph->image_uses_foreground_color &&
+	(scaled_glyph->recording_uses_foreground_marker || scaled_glyph->recording_uses_foreground_color) &&
 	!_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
     {
 	    need_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
diff --git a/src/cairo-svg-glyph-render.c b/src/cairo-svg-glyph-render.c
index 9b953687d..3c14f8c59 100644
--- a/src/cairo-svg-glyph-render.c
+++ b/src/cairo-svg-glyph-render.c
@@ -35,8 +35,9 @@
  */
 
 #include "cairoint.h"
-#include "cairo-ft-private.h"
 #include "cairo-array-private.h"
+#include "cairo-ft-private.h"
+#include "cairo-pattern-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 
 #include <stdarg.h>
@@ -239,7 +240,7 @@ typedef struct _cairo_svg_element {
 } cairo_svg_element_t;
 
 typedef struct _cairo_svg_color {
-    enum { RGB, CURRENT_COLOR } type;
+    enum { RGB, FOREGROUND } type;
     double red;
     double green;
     double blue;
@@ -291,7 +292,6 @@ typedef struct _cairo_svg_glyph_render {
     cairo_hash_table_t *ids;
     cairo_svg_graphics_state_t *graphics_state;
     cairo_t *cr;
-    cairo_pattern_t *foreground_color;
     double units_per_em;
     struct {
         cairo_svg_element_t *paint_server;
@@ -307,6 +307,10 @@ typedef struct _cairo_svg_glyph_render {
     double height;
     cairo_bool_t view_port_set;
 
+    cairo_pattern_t *foreground_marker;
+    cairo_pattern_t *foreground_source;
+    cairo_bool_t foreground_source_used;
+
     int debug; /* 0 = quiet, 1 = errors, 2 = warnings, 3 = info */
 } cairo_svg_glyph_render_t;
 
@@ -745,13 +749,13 @@ get_color (cairo_svg_glyph_render_t *svg_render,
 
     len = strlen(s);
 
-    if (string_equal (s, "inherit") ||
-        string_equal (s, "currentColor") ||
-        string_equal (s, "context-fill") ||
-        string_equal (s, "context-stroke"))
+    if (string_equal (s, "inherit")) {
+	return FALSE;
+    } else if (string_equal (s, "currentColor") ||
+	       string_equal (s, "context-fill") ||
+	       string_equal (s, "context-stroke"))
     {
-        color->type = CURRENT_COLOR;
-        color->red = color->green = color->blue = 0;
+	*color = svg_render->graphics_state->color;
         return TRUE;
     } else if (len > 0 && s[0] == '#') {
         if (len == 4) {
@@ -810,7 +814,7 @@ get_color (cairo_svg_glyph_render_t *svg_render,
 
             end = strpbrk(s, WHITE_SPACE_CHARS ")");
             if (!end || end == s)
-            return FALSE;
+		return FALSE;
 
             char *fallback = _cairo_strndup (s, end - s);
             cairo_bool_t success = get_color (svg_render, fallback, color);
@@ -1710,6 +1714,15 @@ render_element_stop (cairo_svg_glyph_render_t *svg_render,
                                            color.green,
                                            color.blue,
                                            opacity);
+    } else { /* color.type == FOREGROUND */
+        double red, green, blue, alpha;
+        if (cairo_pattern_get_rgba (svg_render->foreground_source, &red, &green, &blue, &alpha) == CAIRO_STATUS_SUCCESS) {
+	    svg_render->foreground_source_used = TRUE;
+	} else {
+            red = green = blue = 0;
+            alpha = 1;
+        }
+        cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, alpha);
     }
     return TRUE;
 }
@@ -1906,12 +1919,10 @@ draw_path (cairo_svg_glyph_render_t *svg_render)
                                        gs->fill.color.green,
                                        gs->fill.color.blue,
                                        gs->fill_opacity);
-            } else if (gs->fill.color.type == CURRENT_COLOR) {
-                cairo_set_source_rgba (svg_render->cr,
-                                       gs->color.red,
-                                       gs->color.green,
-                                       gs->color.blue,
-                                       gs->fill_opacity);
+            } else if (gs->fill.color.type == FOREGROUND) {
+		cairo_set_source (svg_render->cr, svg_render->foreground_marker);
+		if (gs->fill_opacity < 1.0)
+		    group = TRUE;
             }
         } else if (gs->fill.type == PAINT_SERVER) {
             pattern = create_pattern (svg_render, gs->fill.paint_server);
@@ -1942,12 +1953,10 @@ draw_path (cairo_svg_glyph_render_t *svg_render)
                                        gs->stroke.color.green,
                                        gs->stroke.color.blue,
                                        gs->stroke_opacity);
-            } else if (gs->stroke.color.type == CURRENT_COLOR) {
-                cairo_set_source_rgba (svg_render->cr,
-                                       gs->color.red,
-                                       gs->color.green,
-                                       gs->color.blue,
-                                       gs->stroke_opacity);
+            } else if (gs->fill.color.type == FOREGROUND) {
+		cairo_set_source (svg_render->cr, svg_render->foreground_marker);
+		if (gs->fill_opacity < 1.0)
+		    group = TRUE;
             }
         } else if (gs->stroke.type == PAINT_SERVER) {
             pattern = create_pattern (svg_render, gs->stroke.paint_server);
@@ -2579,20 +2588,11 @@ static void
 init_graphics_state (cairo_svg_glyph_render_t *svg_render)
 {
     cairo_svg_graphics_state_t *gs;
-    double alpha;
 
     gs = _cairo_malloc (sizeof (cairo_svg_graphics_state_t));
     get_paint (svg_render, "black", &gs->fill);
     get_paint (svg_render, "none", &gs->stroke);
-    gs->color.type = RGB;
-    if (cairo_pattern_get_rgba (svg_render->foreground_color,
-                                &gs->color.red,
-                                &gs->color.green,
-                                &gs->color.blue,
-                                &alpha) != CAIRO_STATUS_SUCCESS)
-    {
-        get_color (svg_render, "black", &gs->color);
-    }
+    gs->color.type = FOREGROUND;
     gs->fill_opacity = 1.0;
     gs->stroke_opacity = 1.0;
     gs->opacity = 1.0;
@@ -3096,7 +3096,9 @@ _cairo_render_svg_glyph (const char           *svg_document,
                          double                units_per_em,
                          FT_Color             *palette,
                          int                   num_palette_entries,
-                         cairo_t              *cr)
+                         cairo_t              *cr,
+                         cairo_pattern_t      *foreground_source,
+			 cairo_bool_t         *foreground_source_used)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
@@ -3122,7 +3124,6 @@ _cairo_render_svg_glyph (const char           *svg_document,
 
     svg_render->cr = cr;
     svg_render->units_per_em = units_per_em;
-    svg_render->foreground_color = cairo_pattern_reference (cairo_get_source (cr));
     svg_render->build_pattern.paint_server = NULL;
     svg_render->build_pattern.pattern = NULL;
     svg_render->build_pattern.type = BUILD_PATTERN_NONE;
@@ -3131,6 +3132,10 @@ _cairo_render_svg_glyph (const char           *svg_document,
     svg_render->num_palette_entries = num_palette_entries;
     svg_render->palette = palette;
 
+    svg_render->foreground_marker = _cairo_pattern_create_foreground_marker ();
+    svg_render->foreground_source = cairo_pattern_reference (foreground_source);;
+    svg_render->foreground_source_used = FALSE;
+
     init_graphics_state (svg_render);
 
     print_info (svg_render, "Glyph ID: %ld", glyph);
@@ -3175,7 +3180,9 @@ _cairo_render_svg_glyph (const char           *svg_document,
     while (svg_render->graphics_state)
         restore_graphics_state (svg_render);
 
-    cairo_pattern_destroy (svg_render->foreground_color);
+    cairo_pattern_destroy (svg_render->foreground_marker);
+    cairo_pattern_destroy (svg_render->foreground_source);
+    *foreground_source_used = svg_render->foreground_source_used;
 
     /* The hash entry for each element with an id is removed by
      * free_elements() */
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 913395fd9..e7a1d0211 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -381,20 +381,8 @@ _cairo_user_scaled_glyph_init (void			 *abstract_font,
 {
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_user_scaled_font_t *scaled_font = abstract_font;
-    cairo_bool_t need_recording = FALSE;
 
-    if (!scaled_glyph->recording_surface) {
-	need_recording = TRUE;
-    } else {
-	if ((info & (CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE|CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) &&
-	    scaled_glyph->recording_uses_foreground_color &&
-	    !_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
-	{
-	    need_recording = TRUE;
-	}
-    }
-
-    if (need_recording) {
+    if (!scaled_glyph->recording_surface || (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE)) {
 	status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph, foreground_color);
 	if (status)
 	    return status;
@@ -598,8 +586,7 @@ _cairo_user_font_face_scaled_font_create (void                        *abstract_
     }
 
     user_scaled_font->foreground_pattern = NULL;
-    user_scaled_font->foreground_marker = cairo_pattern_create_rgb (0, 0, 0);
-    user_scaled_font->foreground_marker->is_userfont_foreground = TRUE;
+    user_scaled_font->foreground_marker = _cairo_pattern_create_foreground_marker ();
 
     /* XXX metrics hinting? */
 
diff --git a/test/cairo-svg-test-palette.ttx b/test/cairo-svg-test-palette.ttx
index 0ee1a3977..1b0630913 100644
--- a/test/cairo-svg-test-palette.ttx
+++ b/test/cairo-svg-test-palette.ttx
@@ -6,18 +6,24 @@
     <GlyphID id="0" name=".notdef"/>
     <GlyphID id="1" name="zero"/>
     <GlyphID id="2" name="one"/>
+    <GlyphID id="3" name="two"/>
+    <GlyphID id="4" name="three"/>
+    <GlyphID id="5" name="four"/>
+    <GlyphID id="6" name="five"/>
+    <GlyphID id="7" name="six"/>
+    <GlyphID id="8" name="seven"/>
   </GlyphOrder>
 
   <head>
     <!-- Most of this table will be recalculated by the compiler -->
     <tableVersion value="1.0"/>
     <fontRevision value="1.0"/>
-    <checkSumAdjustment value="0xcb6df82"/>
+    <checkSumAdjustment value="0x1b8ac35c"/>
     <magicNumber value="0x5f0f3cf5"/>
     <flags value="00000000 00000011"/>
     <unitsPerEm value="1000"/>
     <created value="Wed Jun 15 00:00:00 2022"/>
-    <modified value="Sat Jan 21 05:46:29 2023"/>
+    <modified value="Fri Jan 27 07:13:15 2023"/>
     <xMin value="0"/>
     <yMin value="0"/>
     <xMax value="1000"/>
@@ -52,7 +58,7 @@
   <maxp>
     <!-- Most of this table will be recalculated by the compiler -->
     <tableVersion value="0x10000"/>
-    <numGlyphs value="3"/>
+    <numGlyphs value="9"/>
     <maxPoints value="4"/>
     <maxContours value="1"/>
     <maxCompositePoints value="0"/>
@@ -106,7 +112,7 @@
     <achVendID value="djr "/>
     <fsSelection value="00000000 01000000"/>
     <usFirstCharIndex value="48"/>
-    <usLastCharIndex value="49"/>
+    <usLastCharIndex value="55"/>
     <sTypoAscender value="1000"/>
     <sTypoDescender value="0"/>
     <sTypoLineGap value="200"/>
@@ -123,7 +129,13 @@
 
   <hmtx>
     <mtx name=".notdef" width="1100" lsb="0"/>
+    <mtx name="five" width="1100" lsb="0"/>
+    <mtx name="four" width="1100" lsb="0"/>
     <mtx name="one" width="1100" lsb="0"/>
+    <mtx name="seven" width="1100" lsb="0"/>
+    <mtx name="six" width="1100" lsb="0"/>
+    <mtx name="three" width="1100" lsb="0"/>
+    <mtx name="two" width="1100" lsb="0"/>
     <mtx name="zero" width="1100" lsb="0"/>
   </hmtx>
 
@@ -132,6 +144,12 @@
     <cmap_format_4 platformID="0" platEncID="3" language="0">
       <map code="0x30" name="zero"/><!-- DIGIT ZERO -->
       <map code="0x31" name="one"/><!-- DIGIT ONE -->
+      <map code="0x32" name="two"/><!-- DIGIT TWO -->
+      <map code="0x33" name="three"/><!-- DIGIT THREE -->
+      <map code="0x34" name="four"/><!-- DIGIT FOUR -->
+      <map code="0x35" name="five"/><!-- DIGIT FIVE -->
+      <map code="0x36" name="six"/><!-- DIGIT SIX -->
+      <map code="0x37" name="seven"/><!-- DIGIT SEVEN -->
     </cmap_format_4>
   </cmap>
 
@@ -146,6 +164,26 @@
 
     <TTGlyph name=".notdef"/><!-- contains no outline data -->
 
+    <TTGlyph name="five" xMin="0" yMin="0" xMax="1000" yMax="1000">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="0" y="1000" on="1"/>
+        <pt x="1000" y="1000" on="1"/>
+        <pt x="1000" y="0" on="1"/>
+      </contour>
+      <instructions/>
+    </TTGlyph>
+
+    <TTGlyph name="four" xMin="0" yMin="0" xMax="1000" yMax="1000">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="0" y="1000" on="1"/>
+        <pt x="1000" y="1000" on="1"/>
+        <pt x="1000" y="0" on="1"/>
+      </contour>
+      <instructions/>
+    </TTGlyph>
+
     <TTGlyph name="one" xMin="0" yMin="0" xMax="1000" yMax="1000">
       <contour>
         <pt x="0" y="0" on="1"/>
@@ -156,6 +194,46 @@
       <instructions/>
     </TTGlyph>
 
+    <TTGlyph name="seven" xMin="0" yMin="0" xMax="1000" yMax="1000">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="0" y="1000" on="1"/>
+        <pt x="1000" y="1000" on="1"/>
+        <pt x="1000" y="0" on="1"/>
+      </contour>
+      <instructions/>
+    </TTGlyph>
+
+    <TTGlyph name="six" xMin="0" yMin="0" xMax="1000" yMax="1000">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="0" y="1000" on="1"/>
+        <pt x="1000" y="1000" on="1"/>
+        <pt x="1000" y="0" on="1"/>
+      </contour>
+      <instructions/>
+    </TTGlyph>
+
+    <TTGlyph name="three" xMin="0" yMin="0" xMax="1000" yMax="1000">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="0" y="1000" on="1"/>
+        <pt x="1000" y="1000" on="1"/>
+        <pt x="1000" y="0" on="1"/>
+      </contour>
+      <instructions/>
+    </TTGlyph>
+
+    <TTGlyph name="two" xMin="0" yMin="0" xMax="1000" yMax="1000">
+      <contour>
+        <pt x="0" y="0" on="1"/>
+        <pt x="0" y="1000" on="1"/>
+        <pt x="1000" y="1000" on="1"/>
+        <pt x="1000" y="0" on="1"/>
+      </contour>
+      <instructions/>
+    </TTGlyph>
+
     <TTGlyph name="zero" xMin="0" yMin="0" xMax="1000" yMax="1000">
       <contour>
         <pt x="0" y="0" on="1"/>
@@ -219,6 +297,64 @@
       <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
   <rect x="100" y="-750" width="800" height="500"
         fill="var(--color1, blue)" />
+</svg>]]>
+    </svgDoc>
+    <svgDoc endGlyphID="3" startGlyphID="3">
+      <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <rect x="100" y="-750" width="800" height="500"
+        fill="currentColor" />
+</svg>]]>
+    </svgDoc>
+    <svgDoc endGlyphID="4" startGlyphID="4">
+      <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <rect x="100" y="-750" width="800" height="500"
+        fill="currentColor" fill-opacity="0.5"  />
+</svg>]]>
+    </svgDoc>
+    <svgDoc endGlyphID="5" startGlyphID="5">
+      <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <linearGradient id="grad" x1="33%" x21="66%">
+      <stop offset="0%" stop-color="currentColor" stop-opacity="1" />
+      <stop offset="100%" stop-color="red" stop-opacity="1" />
+    </linearGradient>
+  </defs>
+  <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+    </svgDoc>
+    <svgDoc endGlyphID="6" startGlyphID="6">
+      <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <linearGradient id="grad" x1="33%" x21="66%">
+      <stop offset="0%" stop-color="currentColor" stop-opacity="0.3" />
+      <stop offset="100%" stop-color="red" stop-opacity="0.3" />
+    </linearGradient>
+  </defs>
+  <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+    </svgDoc>
+    <svgDoc endGlyphID="7" startGlyphID="7">
+      <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <radialGradient id="grad" cx="50%" cy="50%"
+                    fx="0.75" fy="0.35" r="0.5">
+      <stop offset="0%" stop-color="currentColor" stop-opacity="1" />
+      <stop offset="100%" stop-color="blue" stop-opacity="1" />
+    </radialGradient>
+  </defs>
+  <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
+</svg>]]>
+    </svgDoc>
+    <svgDoc endGlyphID="8" startGlyphID="8">
+      <![CDATA[<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <radialGradient id="grad" cx="50%" cy="50%"
+                    fx="0.75" fy="0.35" r="0.5">
+      <stop offset="0%" stop-color="currentColor" stop-opacity="0.5" />
+      <stop offset="100%" stop-color="blue" stop-opacity="0.5" />
+    </radialGradient>
+  </defs>
+  <rect x="100" y="-900" width="800" height="800" fill="url(#grad)" />
 </svg>]]>
     </svgDoc>
   </SVG>
diff --git a/test/ft-svg-render-palette.c b/test/ft-svg-render-palette.c
index 3a01e4168..eee5f27c8 100644
--- a/test/ft-svg-render-palette.c
+++ b/test/ft-svg-render-palette.c
@@ -30,11 +30,12 @@
 #define FONT_SIZE 50
 #define MARGIN 5
 #define WIDTH  (FONT_SIZE*8 + MARGIN*9)
-#define HEIGHT (FONT_SIZE + MARGIN*2)
+#define HEIGHT (FONT_SIZE*2 + MARGIN*3)
 
 #define FONT_FILE "cairo-svg-test-palette.ttf"
 
-#define TEXT "01"
+#define PALETTE_TEXT     "01"
+#define FOREGROUND_TEXT  "234567"
 
 
 static cairo_test_status_t
@@ -52,32 +53,40 @@ draw (cairo_t *cr, int width, int height)
         return result;
 
     cairo_set_font_size (cr, FONT_SIZE);
+    
+    cairo_save (cr);
     cairo_move_to (cr, MARGIN, FONT_SIZE + MARGIN);
-
     font_options = cairo_font_options_create ();
 
     /* Default palette */
-    cairo_show_text (cr, TEXT);
+    cairo_show_text (cr, PALETTE_TEXT);
 
     /* Palette 1 */
     cairo_font_options_set_color_palette (font_options, 1);
     cairo_set_font_options (cr, font_options);
-    cairo_show_text (cr, TEXT);
+    cairo_show_text (cr, PALETTE_TEXT);
 
     /* Palette 0, override color 0 */
     cairo_font_options_set_color_palette (font_options, 0);
     cairo_font_options_set_custom_palette_color (font_options, 0, 1, 0, 1, 0.5);
     cairo_set_font_options (cr, font_options);
-    cairo_show_text (cr, TEXT);
+    cairo_show_text (cr, PALETTE_TEXT);
 
     /* Palette 1, override color 1 */
     cairo_font_options_set_color_palette (font_options, 1);
     cairo_font_options_set_custom_palette_color (font_options, 1, 0, 1, 1, 0.5);
     cairo_set_font_options (cr, font_options);
-    cairo_show_text (cr, TEXT);
+    cairo_show_text (cr, PALETTE_TEXT);
 
     cairo_font_options_destroy (font_options);
+    cairo_restore (cr);
+
+    cairo_move_to (cr, MARGIN, FONT_SIZE*2 + MARGIN*2);
+
+    cairo_set_source_rgb (cr, 0, 1, 0);
+    cairo_show_text (cr, FOREGROUND_TEXT);
 
+    
     return CAIRO_TEST_SUCCESS;
 }
 


More information about the cairo-commit mailing list