summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2021-08-27 23:12:24 +0930
committerAdrian Johnson <ajohnson@redneon.com>2021-08-28 18:07:01 +0930
commitfea24631076f74a3202ba0233be85588ae28db36 (patch)
tree1df67721f194ad6f161d5d63ddd146d05a0d0b68
parent5e76dd7a5c0585515eeef5099f12b273c94d3b0f (diff)
downloadcairo-fea24631076f74a3202ba0233be85588ae28db36.tar.gz
Support color fonts that use the foreground color
COLR fonts can have a layer with the same color as the current text color. This change passes the current color (if solid) through to the font backend where it can be used to render color fonts. scaled_glyph_lookup checks if the foreground color has changed (for glyph that require it) and requests a new color surface if required. This also fixes a bug where scaled_glyph_lookup would always request a color surface for glyphs for glyphs in color fonts that do not have color.
-rw-r--r--configure.ac2
-rw-r--r--meson.build1
-rw-r--r--src/cairo-ft-font.c40
-rw-r--r--src/cairo-gl-glyphs.c2
-rw-r--r--src/cairo-image-compositor.c5
-rw-r--r--src/cairo-quartz-font.c3
-rw-r--r--src/cairo-scaled-font-private.h9
-rw-r--r--src/cairo-scaled-font-subsets.c2
-rwxr-xr-xsrc/cairo-scaled-font.c41
-rw-r--r--src/cairo-script-surface.c5
-rw-r--r--src/cairo-surface.c13
-rw-r--r--src/cairo-svg-surface.c2
-rw-r--r--src/cairo-type1-fallback.c3
-rw-r--r--src/cairo-type3-glyph-surface.c4
-rw-r--r--src/cairo-user-font.c6
-rw-r--r--src/cairo-xcb-surface-render.c3
-rw-r--r--src/cairo-xlib-render-compositor.c2
-rw-r--r--src/cairoint.h20
-rw-r--r--src/drm/cairo-drm-i915-glyphs.c2
-rw-r--r--src/drm/cairo-drm-i965-glyphs.c2
-rw-r--r--src/drm/cairo-drm-intel.c3
-rw-r--r--src/test-base-compositor-surface.c1
-rw-r--r--src/win32/cairo-win32-font.c4
-rw-r--r--src/win32/cairo-win32-printing-surface.c2
24 files changed, 160 insertions, 17 deletions
diff --git a/configure.ac b/configure.ac
index 0ca0c8e2b..8ff3f35d6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -561,7 +561,7 @@ if test "x$use_ft" = "xyes"; then
LIBS="$LIBS $ft_LIBS"
CFLAGS="$CFLAGS $ft_CFLAGS"
- AC_CHECK_FUNCS(FT_Get_X11_Font_Format FT_GlyphSlot_Embolden FT_GlyphSlot_Oblique FT_Load_Sfnt_Table FT_Library_SetLcdFilter FT_Get_Var_Design_Coordinates FT_Done_MM_Var)
+ AC_CHECK_FUNCS(FT_Get_X11_Font_Format FT_GlyphSlot_Embolden FT_GlyphSlot_Oblique FT_Load_Sfnt_Table FT_Library_SetLcdFilter FT_Get_Var_Design_Coordinates FT_Done_MM_Var FT_Palette_Set_Foreground_Color)
AC_MSG_CHECKING(for FT_HAS_COLOR)
AC_LINK_IFELSE([AC_LANG_PROGRAM([
diff --git a/meson.build b/meson.build
index 7a0506712..6236d743b 100644
--- a/meson.build
+++ b/meson.build
@@ -330,6 +330,7 @@ if freetype_dep.found()
'FT_Library_SetLcdFilter',
'FT_Get_Var_Design_Coordinates',
'FT_Done_MM_Var',
+ 'FT_Palette_Set_Foreground_Color',
]
if freetype_dep.type_name() == 'internal'
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index adfb445df..66300dd03 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2479,6 +2479,7 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_glyph_info_t info,
FT_Face face,
+ const cairo_color_t *foreground_color,
cairo_bool_t vertical_layout,
int load_flags)
{
@@ -2486,11 +2487,40 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
FT_GlyphSlot glyph;
cairo_status_t status;
cairo_image_surface_t *surface;
+ cairo_bool_t uses_foreground_color = FALSE;
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
if (!unscaled->have_color)
return CAIRO_INT_STATUS_UNSUPPORTED;
+#ifdef HAVE_FT_PALETTE_SET_FOREGROUND_COLOR
+ FT_LayerIterator iterator;
+ FT_UInt layer_glyph_index;
+ FT_UInt layer_color_index;
+ FT_Color color;
+
+ /* Check if there is a layer that uses the foreground color */
+ iterator.p = NULL;
+ while (FT_Get_Color_Glyph_Layer(face,
+ _cairo_scaled_glyph_index(scaled_glyph),
+ &layer_glyph_index,
+ &layer_color_index,
+ &iterator)) {
+ if (layer_color_index == 0xFFFF) {
+ uses_foreground_color = TRUE;
+ break;
+ }
+ }
+
+ if (uses_foreground_color) {
+ color.red = (FT_Byte)(foreground_color->red * 0xFF);
+ color.green = (FT_Byte)(foreground_color->green * 0xFF);
+ color.blue = (FT_Byte)(foreground_color->blue * 0xFF);
+ color.alpha = (FT_Byte)(foreground_color->alpha * 0xFF);
+ FT_Palette_Set_Foreground_Color (face, color);
+ }
+#endif
+
load_flags &= ~FT_LOAD_MONOCHROME;
/* clear load target mode */
load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags)));
@@ -2534,11 +2564,14 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
!pixman_image_get_component_alpha (surface->pixman_image)) {
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
&scaled_font->base,
- surface);
+ surface,
+ uses_foreground_color);
} else {
_cairo_scaled_glyph_set_surface (scaled_glyph,
&scaled_font->base,
surface);
+ if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)
+ scaled_glyph->not_color_glyph = TRUE;
}
return status;
@@ -2547,7 +2580,8 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
static cairo_int_status_t
_cairo_ft_scaled_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info)
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color)
{
cairo_text_extents_t fs_metrics;
cairo_ft_scaled_font_t *scaled_font = abstract_font;
@@ -2698,6 +2732,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
scaled_glyph,
CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
face,
+ foreground_color,
vertical_layout,
load_flags);
if (unlikely (status))
@@ -2709,6 +2744,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
scaled_glyph,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
face,
+ NULL, /* foreground color */
vertical_layout,
load_flags);
if (unlikely (status))
diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c
index 5923af441..0384dbf24 100644
--- a/src/cairo-gl-glyphs.c
+++ b/src/cairo-gl-glyphs.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Chris Wilson
@@ -269,6 +270,7 @@ render_glyphs (cairo_gl_surface_t *dst,
status = _cairo_scaled_glyph_lookup (info->font,
info->glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
goto FINISH;
diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
index 0ded5388e..0a293f05d 100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -909,6 +909,7 @@ composite_glyphs (void *_dst,
CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
status = _cairo_scaled_glyph_lookup (info->font, index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
@@ -997,6 +998,7 @@ composite_one_glyph (void *_dst,
status = _cairo_scaled_glyph_lookup (info->font,
info->glyphs[0].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
@@ -1059,6 +1061,7 @@ composite_glyphs_via_mask (void *_dst,
status = _cairo_scaled_glyph_lookup (info->font,
info->glyphs[0].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status)) {
pixman_image_unref (white);
@@ -1105,6 +1108,7 @@ composite_glyphs_via_mask (void *_dst,
{
status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status)) {
@@ -1231,6 +1235,7 @@ composite_glyphs (void *_dst,
{
status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 8cb71434f..77a9d6a55 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -743,7 +743,8 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
static cairo_int_status_t
_cairo_quartz_scaled_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info)
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color)
{
cairo_quartz_scaled_font_t *font = (cairo_quartz_scaled_font_t *) abstract_font;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index 4bacb1a01..42e9b0913 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -147,7 +147,14 @@ struct _cairo_scaled_glyph {
void *dev_private;
cairo_list_t dev_privates;
- cairo_bool_t has_color;
+ cairo_color_t foreground_color; /* only used for color glyphs */
+ /* TRUE if the color_surface used the foreground_color to render. */
+ unsigned uses_foreground_color : 1;
+
+ /* TRUE if this is not a color glyph, FALSE if is a color glyph or unknown. */
+ unsigned not_color_glyph : 1;
+
+ unsigned has_color : 1;
};
struct _cairo_scaled_glyph_private {
diff --git a/src/cairo-scaled-font-subsets.c b/src/cairo-scaled-font-subsets.c
index 0ae41aebe..94a7aae26 100644
--- a/src/cairo-scaled-font-subsets.c
+++ b/src/cairo-scaled-font-subsets.c
@@ -513,6 +513,7 @@ _cairo_sub_font_add_glyph (cairo_sub_font_t *sub_font,
status = _cairo_scaled_glyph_lookup (sub_font->scaled_font,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
if (unlikely (status)) {
@@ -890,6 +891,7 @@ _cairo_scaled_font_subsets_map_glyph (cairo_scaled_font_subsets_t *subsets,
status = _cairo_scaled_glyph_lookup (scaled_font,
scaled_font_glyph_index,
CAIRO_SCALED_GLYPH_INFO_PATH,
+ NULL, /* foreground color */
&scaled_glyph);
_cairo_scaled_font_thaw_cache (scaled_font);
}
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 65c1d2595..ef0db0506 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1611,6 +1611,7 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status)) {
status = _cairo_scaled_font_set_error (scaled_font, status);
@@ -1732,6 +1733,7 @@ cairo_scaled_font_text_to_glyphs_internal_cached (cairo_scaled_font_t *scaled_
status = _cairo_scaled_glyph_lookup (scaled_font,
g,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
return status;
@@ -1792,6 +1794,7 @@ cairo_scaled_font_text_to_glyphs_internal_uncached (cairo_scaled_font_t *scaled
status = _cairo_scaled_glyph_lookup (scaled_font,
g,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
return status;
@@ -2176,6 +2179,7 @@ _cairo_scaled_font_single_glyph_device_extents (cairo_scaled_font_t *scaled_fon
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph->index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (likely (status == CAIRO_STATUS_SUCCESS)) {
cairo_bool_t round_xy = _cairo_font_options_get_round_glyph_positions (&scaled_font->options) == CAIRO_ROUND_GLYPH_POS_ON;
@@ -2246,6 +2250,7 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
break;
@@ -2402,6 +2407,7 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
@@ -2656,6 +2662,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
+ NULL, /* foreground color */
&scaled_glyph);
if (status == CAIRO_INT_STATUS_SUCCESS) {
status = _cairo_path_fixed_append (path,
@@ -2670,6 +2677,7 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
goto BAIL;
@@ -2830,7 +2838,8 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
void
_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font,
- cairo_image_surface_t *surface)
+ cairo_image_surface_t *surface,
+ cairo_bool_t uses_foreground_color)
{
if (scaled_glyph->color_surface != NULL)
cairo_surface_destroy (&scaled_glyph->color_surface->base);
@@ -2838,6 +2847,7 @@ _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->uses_foreground_color = uses_foreground_color;
if (surface != NULL)
scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
@@ -2956,6 +2966,8 @@ _cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font,
* @index: the glyph to create
* @info: a #cairo_scaled_glyph_info_t marking which portions of
* the glyph should be filled in.
+ * @foreground_color - foreground color to use when rendering color fonts. Use NULL
+ * if not requesting CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE or foreground color is unknown.
* @scaled_glyph_ret: a #cairo_scaled_glyph_t where the glyph
* is returned.
*
@@ -2976,11 +2988,14 @@ _cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font,
* %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
* %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
* %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
+ * %CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE - surface holding recording of glyph
+ * %CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE - surface holding color glyph image
**/
cairo_int_status_t
_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
unsigned long index,
cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color,
cairo_scaled_glyph_t **scaled_glyph_ret)
{
cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
@@ -2998,6 +3013,9 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
if (CAIRO_INJECT_FAULT ())
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ if (foreground_color == NULL)
+ foreground_color = CAIRO_COLOR_BLACK;
+
/*
* Check cache for glyph
*/
@@ -3016,7 +3034,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
status =
scaled_font->backend->scaled_glyph_init (scaled_font,
scaled_glyph,
- info | CAIRO_SCALED_GLYPH_INFO_METRICS);
+ info | CAIRO_SCALED_GLYPH_INFO_METRICS,
+ foreground_color);
if (unlikely (status)) {
_cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph);
goto err;
@@ -3035,10 +3054,26 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
* already has the requested data and amend it if not
*/
need_info = info & ~scaled_glyph->has_info;
+
+ /* If this is not a color glyph, don't try loading the color surface again. */
+ if ((need_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) && scaled_glyph->not_color_glyph)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ /* 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->uses_foreground_color &&
+ !_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
+ {
+ need_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
+ }
+
if (need_info) {
status = scaled_font->backend->scaled_glyph_init (scaled_font,
scaled_glyph,
- need_info);
+ need_info,
+ foreground_color);
if (unlikely (status))
goto err;
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index 9d6b954c1..ca9bafbb7 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -3194,6 +3194,7 @@ _emit_scaled_glyphs (cairo_script_surface_t *surface,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
break;
@@ -3204,6 +3205,7 @@ _emit_scaled_glyphs (cairo_script_surface_t *surface,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (_cairo_status_is_error (status))
break;
@@ -3229,6 +3231,7 @@ _emit_scaled_glyphs (cairo_script_surface_t *surface,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (_cairo_status_is_error (status))
break;
@@ -3411,6 +3414,7 @@ _cairo_script_surface_show_text_glyphs (void *abstract_surface,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status)) {
_cairo_scaled_font_thaw_cache (scaled_font);
@@ -3434,6 +3438,7 @@ _cairo_script_surface_show_text_glyphs (void *abstract_surface,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[n].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status)) {
_cairo_scaled_font_thaw_cache (scaled_font);
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 380759db9..eea7d6030 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2602,6 +2602,7 @@ slim_hidden_def (cairo_surface_has_show_text_glyphs);
static inline cairo_int_status_t
ensure_scaled_glyph (cairo_scaled_font_t *scaled_font,
+ cairo_color_t *foreground_color,
cairo_scaled_glyph_t **glyph_cache,
cairo_glyph_t *glyph,
cairo_scaled_glyph_t **scaled_glyph)
@@ -2615,12 +2616,14 @@ ensure_scaled_glyph (cairo_scaled_font_t *scaled_font,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph->index,
CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
+ foreground_color,
scaled_glyph);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
/* If the color surface not available, ensure scaled_glyph is not NULL. */
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph->index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
scaled_glyph);
}
if (unlikely (status))
@@ -2693,6 +2696,10 @@ composite_color_glyphs (cairo_surface_t *surface,
int byte_pos = 0;
int gp;
cairo_scaled_glyph_t *glyph_cache[GLYPH_CACHE_SIZE];
+ cairo_color_t *foreground_color = NULL;
+
+ if (source->type == CAIRO_PATTERN_TYPE_SOLID)
+ foreground_color = &((cairo_solid_pattern_t *) source)->color;
memset (glyph_cache, 0, sizeof (glyph_cache));
@@ -2714,7 +2721,7 @@ composite_color_glyphs (cairo_surface_t *surface,
else
gp = glyph_pos + j;
- status = ensure_scaled_glyph (scaled_font, glyph_cache,
+ status = ensure_scaled_glyph (scaled_font, foreground_color, glyph_cache,
&glyphs[gp], &scaled_glyph);
if (unlikely (status))
goto UNLOCK;
@@ -2745,7 +2752,7 @@ composite_color_glyphs (cairo_surface_t *surface,
else
gp = glyph_pos + j;
- status = ensure_scaled_glyph (scaled_font, glyph_cache,
+ status = ensure_scaled_glyph (scaled_font, foreground_color, glyph_cache,
&glyphs[gp], &scaled_glyph);
if (unlikely (status))
goto UNLOCK;
@@ -2774,7 +2781,7 @@ composite_color_glyphs (cairo_surface_t *surface,
} else {
for (glyph_pos = 0; glyph_pos < *num_glyphs; glyph_pos++) {
- status = ensure_scaled_glyph (scaled_font, glyph_cache,
+ status = ensure_scaled_glyph (scaled_font, foreground_color, glyph_cache,
&glyphs[glyph_pos], &scaled_glyph);
if (unlikely (status))
goto UNLOCK;
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 80f3a0eb0..c6d9382b3 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1326,6 +1326,7 @@ _cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_PATH,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status)) {
return status;
@@ -1357,6 +1358,7 @@ _cairo_svg_document_emit_bitmap_glyph_data (cairo_svg_document_t *document,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS | CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status)) {
return status;
diff --git a/src/cairo-type1-fallback.c b/src/cairo-type1-fallback.c
index 0b8e66cd0..3a44c4666 100644
--- a/src/cairo-type1-fallback.c
+++ b/src/cairo-type1-fallback.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2006 Red Hat, Inc
@@ -354,6 +355,7 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS|
CAIRO_SCALED_GLYPH_INFO_PATH,
+ NULL, /* foreground color */
&scaled_glyph);
/* It is ok for the .notdef glyph to not have a path available. We
@@ -363,6 +365,7 @@ cairo_type1_font_create_charstring (cairo_type1_font_t *font,
status = _cairo_scaled_glyph_lookup (font->type1_scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
}
if (unlikely (status))
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index 6b2102319..05ef417dc 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -373,6 +373,7 @@ _cairo_type3_glyph_surface_emit_fallback_image (cairo_type3_glyph_surface_t *sur
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
return status;
@@ -428,6 +429,7 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (_cairo_int_status_is_error (status))
@@ -480,11 +482,13 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
status = _cairo_scaled_glyph_lookup (surface->scaled_font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (status == CAIRO_INT_STATUS_SUCCESS)
status = CAIRO_INT_STATUS_IMAGE_FALLBACK;
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 04c9ee699..47b9f0422 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -144,7 +144,8 @@ _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t
static cairo_int_status_t
_cairo_user_scaled_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info)
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color)
{
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_user_scaled_font_t *scaled_font = abstract_font;
@@ -300,7 +301,8 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
if (scaled_glyph->has_color && (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) {
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
&scaled_font->base,
- (cairo_image_surface_t *)surface);
+ (cairo_image_surface_t *)surface,
+ FALSE);
}
}
diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c
index a1eaad9a5..5993aa378 100644
--- a/src/cairo-xcb-surface-render.c
+++ b/src/cairo-xcb-surface-render.c
@@ -3994,6 +3994,7 @@ _can_composite_glyphs (cairo_xcb_surface_t *dst,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs->index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&glyph);
if (unlikely (status))
break;
@@ -4399,6 +4400,7 @@ _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
scaled_glyph_out);
if (unlikely (status))
return status;
@@ -4692,6 +4694,7 @@ _composite_glyphs (void *closure,
status = _cairo_scaled_glyph_lookup (info->font,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&glyph);
if (unlikely (status)) {
cairo_surface_destroy (&src->base);
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index bf8d20546..c872f5680 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -1204,6 +1204,7 @@ _cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display,
glyph_index,
CAIRO_SCALED_GLYPH_INFO_METRICS |
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
pscaled_glyph);
if (unlikely (status))
return status;
@@ -1619,6 +1620,7 @@ composite_glyphs (void *surface,
status = _cairo_scaled_glyph_lookup (info->font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&glyph);
if (unlikely (status))
return status;
diff --git a/src/cairoint.h b/src/cairoint.h
index 1e0cb4bf1..c5872b8cc 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -519,10 +519,24 @@ struct _cairo_scaled_font_backend {
void
(*fini) (void *scaled_font);
+/**
+ * Get the requested glyph info.
+ * @scaled_font: a #cairo_scaled_font_t
+ * @scaled_glyph: a #cairo_scaled_glyph_t the glyph
+ * @info: a #cairo_scaled_glyph_info_t which information to retreive
+ * %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
+ * %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
+ * %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
+ * %CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE - surface holding recording of glyph
+ * %CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE - surface holding color glyph image
+ * @foreground_color - foreground color to use when rendering color fonts. Use NULL
+ * if not requesting CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE or foreground color is unknown.
+ */
cairo_warn cairo_int_status_t
(*scaled_glyph_init) (void *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info);
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color);
/* A backend only needs to implement this or ucs4_to_index(), not
* both. This allows the backend to do something more sophisticated
@@ -1284,12 +1298,14 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
cairo_private void
_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font,
- cairo_image_surface_t *surface);
+ cairo_image_surface_t *surface,
+ cairo_bool_t uses_foreground_color);
cairo_private cairo_int_status_t
_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
unsigned long index,
cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color,
cairo_scaled_glyph_t **scaled_glyph_ret);
cairo_private double
diff --git a/src/drm/cairo-drm-i915-glyphs.c b/src/drm/cairo-drm-i915-glyphs.c
index 3b0efc248..6fdcc0d2b 100644
--- a/src/drm/cairo-drm-i915-glyphs.c
+++ b/src/drm/cairo-drm-i915-glyphs.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Intel Corporation
@@ -447,6 +448,7 @@ i915_surface_glyphs (void *abstract_surface,
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
goto FINISH;
diff --git a/src/drm/cairo-drm-i965-glyphs.c b/src/drm/cairo-drm-i965-glyphs.c
index 1ef0a6f59..22ace66e3 100644
--- a/src/drm/cairo-drm-i965-glyphs.c
+++ b/src/drm/cairo-drm-i965-glyphs.c
@@ -1,3 +1,4 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2009 Intel Corporation
@@ -366,6 +367,7 @@ i965_surface_glyphs (void *abstract_surface,
status = _cairo_scaled_glyph_lookup (scaled_font,
g[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
goto FINISH;
diff --git a/src/drm/cairo-drm-intel.c b/src/drm/cairo-drm-intel.c
index e45f999ec..ce6c38040 100644
--- a/src/drm/cairo-drm-intel.c
+++ b/src/drm/cairo-drm-intel.c
@@ -994,7 +994,8 @@ intel_get_glyph (intel_device_t *device,
status =
scaled_font->backend->scaled_glyph_init (scaled_font,
scaled_glyph,
- CAIRO_SCALED_GLYPH_INFO_SURFACE);
+ CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL);
if (unlikely (status))
return status;
diff --git a/src/test-base-compositor-surface.c b/src/test-base-compositor-surface.c
index ff84b10af..00e3d0c56 100644
--- a/src/test-base-compositor-surface.c
+++ b/src/test-base-compositor-surface.c
@@ -734,6 +734,7 @@ composite_glyphs (cairo_image_surface_t *dst,
status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ NULL, /* foreground color */
&scaled_glyph);
if (unlikely (status))
diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c
index 792e329d4..eb4ba7a22 100644
--- a/src/win32/cairo-win32-font.c
+++ b/src/win32/cairo-win32-font.c
@@ -715,6 +715,7 @@ _cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled
status = _cairo_scaled_glyph_lookup (&scaled_font->base,
glyph_indices[i],
CAIRO_SCALED_GLYPH_INFO_METRICS,
+ NULL, /* foreground color */
&scaled_glyph);
if (status) {
free (*glyphs);
@@ -1319,7 +1320,8 @@ _draw_glyphs_on_surface (cairo_win32_surface_t *surface,
static cairo_int_status_t
_cairo_win32_scaled_font_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info)
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;
cairo_status_t status;
diff --git a/src/win32/cairo-win32-printing-surface.c b/src/win32/cairo-win32-printing-surface.c
index 36d17e960..19b7f9e93 100644
--- a/src/win32/cairo-win32-printing-surface.c
+++ b/src/win32/cairo-win32-printing-surface.c
@@ -1865,6 +1865,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
+ NULL, /* foreground color */
&scaled_glyph);
if (status)
break;
@@ -1919,6 +1920,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
+ NULL, /* foreground color */
&scaled_glyph);
if (status)
break;