[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