summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/public/cairo-sections.txt2
-rw-r--r--src/cairo-ft-font.c13
-rw-r--r--src/cairo-quartz-font.c2
-rw-r--r--src/cairo-scaled-font-private.h6
-rwxr-xr-xsrc/cairo-scaled-font.c62
-rw-r--r--src/cairo-user-font.c206
-rw-r--r--src/cairo.h37
-rw-r--r--src/cairoint.h5
-rw-r--r--src/win32/cairo-dwrite-font.cpp2
9 files changed, 270 insertions, 65 deletions
diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index 2aeecdca1..4b07fa3c7 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -57,6 +57,8 @@ cairo_user_font_face_set_unicode_to_glyph_func
cairo_user_font_face_get_unicode_to_glyph_func
cairo_user_font_face_set_text_to_glyphs_func
cairo_user_font_face_get_text_to_glyphs_func
+cairo_user_scaled_font_get_foreground_marker
+cairo_user_scaled_font_get_foreground_source
</SECTION>
<SECTION>
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 254dcf25e..e6a8d20e3 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2685,7 +2685,7 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
&scaled_font->base,
surface,
- uses_foreground_color);
+ uses_foreground_color ? foreground_color : NULL);
scaled_glyph->color_glyph = TRUE;
} else {
@@ -2797,7 +2797,8 @@ _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
&scaled_font->base,
- recording_surface);
+ recording_surface,
+ NULL);
return status;
}
#endif
@@ -2862,7 +2863,8 @@ _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);
+ recording_surface,
+ NULL);
scaled_glyph->color_glyph = TRUE;
scaled_glyph->color_glyph_set = TRUE;
@@ -3009,7 +3011,8 @@ _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);
+ recording_surface,
+ NULL);
scaled_glyph->color_glyph = TRUE;
scaled_glyph->color_glyph_set = TRUE;
@@ -3118,7 +3121,7 @@ _cairo_ft_scaled_glyph_init_surface_for_recording_surface (cairo_ft_scaled_font_
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
&scaled_font->base,
(cairo_image_surface_t *)surface,
- foreground_used);
+ foreground_used ? foreground_color : NULL);
surface = NULL;
if (surface)
diff --git a/src/cairo-quartz-font.c b/src/cairo-quartz-font.c
index 641a2dfc7..1e7531356 100644
--- a/src/cairo-quartz-font.c
+++ b/src/cairo-quartz-font.c
@@ -656,7 +656,7 @@ _cairo_quartz_init_glyph_surface (cairo_quartz_scaled_font_t *font,
cairo_surface_mark_dirty (&surface->base);
if (is_color)
- _cairo_scaled_glyph_set_color_surface (scaled_glyph, &font->base, surface, fg_color != NULL);
+ _cairo_scaled_glyph_set_color_surface (scaled_glyph, &font->base, surface, fg_color);
else
_cairo_scaled_glyph_set_surface (scaled_glyph, &font->base, surface);
diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h
index bcc13bdc8..8c10b60c7 100644
--- a/src/cairo-scaled-font-private.h
+++ b/src/cairo-scaled-font-private.h
@@ -149,8 +149,12 @@ struct _cairo_scaled_glyph {
cairo_list_t dev_privates;
cairo_color_t foreground_color; /* only used for color glyphs */
+
+ /* TRUE if the recording_surface required the foreground_color to render. */
+ unsigned recording_uses_foreground_color : 1;
+
/* TRUE if the color_surface required the foreground_color to render. */
- unsigned uses_foreground_color : 1;
+ unsigned image_uses_foreground_color : 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 cc52ed577..d7e3f1e4b 100755
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -2653,10 +2653,19 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_PATH;
}
+/**
+ * _cairo_scaled_glyph_set_recording_surface:
+ * @scaled_glyph: a #cairo_scaled_glyph_t
+ * @scaled_font: a #cairo_scaled_font_t
+ * @recording_surface: The recording surface
+ * @foreground_color: The foreground color that was used to record the
+ * glyph, or NULL if foreground color not required.
+ */
void
_cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_font_t *scaled_font,
- cairo_surface_t *recording_surface)
+ cairo_scaled_font_t *scaled_font,
+ cairo_surface_t *recording_surface,
+ const cairo_color_t * foreground_color)
{
if (scaled_glyph->recording_surface != NULL) {
cairo_surface_finish (scaled_glyph->recording_surface);
@@ -2664,6 +2673,9 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
}
scaled_glyph->recording_surface = recording_surface;
+ scaled_glyph->recording_uses_foreground_color = foreground_color != NULL;
+ if (foreground_color)
+ scaled_glyph->foreground_color = *foreground_color;
if (recording_surface != NULL)
scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
@@ -2671,11 +2683,19 @@ _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
}
+/**
+ * _cairo_scaled_glyph_set_color_surface:
+ * @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.
+ */
void
-_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_font_t *scaled_font,
+_cairo_scaled_glyph_set_color_surface (cairo_scaled_glyph_t *scaled_glyph,
+ cairo_scaled_font_t *scaled_font,
cairo_image_surface_t *surface,
- cairo_bool_t uses_foreground_color)
+ const cairo_color_t *foreground_color)
{
if (scaled_glyph->color_surface != NULL)
cairo_surface_destroy (&scaled_glyph->color_surface->base);
@@ -2683,7 +2703,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->uses_foreground_color = uses_foreground_color;
+ scaled_glyph->image_uses_foreground_color = foreground_color != NULL;
+ if (foreground_color)
+ scaled_glyph->foreground_color = *foreground_color;
if (surface != NULL)
scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
@@ -2814,8 +2836,11 @@ _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.
+ * @foreground_color - foreground color to use when rendering color
+ * fonts. Use NULL if not requesting
+ * CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE or
+ * CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, or foreground color is
+ * unknown.
* @scaled_glyph_ret: a #cairo_scaled_glyph_t where the glyph
* is returned.
*
@@ -2909,14 +2934,23 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
scaled_glyph->color_glyph_set && !scaled_glyph->color_glyph)
return CAIRO_INT_STATUS_UNSUPPORTED;
- /* If requesting a color surface for a glyph that has used the
- * 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 &&
+ /* 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 &&
+ scaled_glyph->recording_uses_foreground_color &&
+ !_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
+ {
+ need_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
+ }
+
+ if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE &&
+ scaled_glyph->image_uses_foreground_color &&
!_cairo_color_equal (foreground_color, &scaled_glyph->foreground_color))
{
- need_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
+ need_info |= CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE;
}
if (need_info) {
diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c
index 80cd4c303..913395fd9 100644
--- a/src/cairo-user-font.c
+++ b/src/cairo-user-font.c
@@ -95,13 +95,19 @@ typedef struct _cairo_user_scaled_font {
double snap_x_scale;
double snap_y_scale;
+ cairo_pattern_t *foreground_marker;
+ cairo_pattern_t *foreground_pattern;
+ cairo_bool_t foreground_marker_used;
+ cairo_bool_t foreground_colors_used;
+
} cairo_user_scaled_font_t;
/* #cairo_user_scaled_font_t */
static cairo_surface_t *
-_cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t *scaled_font,
- cairo_bool_t color)
+_cairo_user_scaled_font_create_recording_surface (cairo_user_scaled_font_t *scaled_font,
+ cairo_bool_t color,
+ const cairo_color_t *foreground_color)
{
cairo_content_t content;
@@ -113,10 +119,20 @@ _cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t
CAIRO_CONTENT_ALPHA;
}
+ if (scaled_font->foreground_pattern)
+ cairo_pattern_destroy (scaled_font->foreground_pattern);
+
+ scaled_font->foreground_marker_used = FALSE;
+ scaled_font->foreground_colors_used = FALSE;
+ if (foreground_color) {
+ scaled_font->foreground_pattern = _cairo_pattern_create_solid (foreground_color);
+ } else {
+ scaled_font->foreground_pattern = cairo_pattern_create_rgb (0, 0, 0);
+ }
+
return cairo_recording_surface_create (content, NULL);
}
-
static cairo_t *
_cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font,
cairo_surface_t *recording_surface,
@@ -143,7 +159,8 @@ _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t
static cairo_int_status_t
_cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_font,
- cairo_scaled_glyph_t *scaled_glyph)
+ cairo_scaled_glyph_t *scaled_glyph,
+ const cairo_color_t *foreground_color)
{
cairo_user_font_face_t *face =
(cairo_user_font_face_t *) scaled_font->base.font_face;
@@ -151,29 +168,25 @@ _cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_fon
cairo_surface_t *recording_surface = NULL;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
cairo_t *cr;
+ cairo_bool_t foreground_used = FALSE;
if (!face->scaled_font_methods.render_color_glyph && !face->scaled_font_methods.render_glyph)
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
/* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
if (_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
- recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE);
+ recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE, foreground_color);
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
&scaled_font->base,
- recording_surface);
+ recording_surface,
+ NULL);
} else {
status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
if (face->scaled_font_methods.render_color_glyph) {
- cairo_pattern_t *pattern;
-
- recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE);
+ recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE, foreground_color);
cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, TRUE);
- pattern = cairo_pattern_create_rgb (0, 0, 0);
- pattern->is_userfont_foreground = TRUE;
- cairo_set_source (cr, pattern);
- cairo_pattern_destroy (pattern);
status = face->scaled_font_methods.render_color_glyph ((cairo_scaled_font_t *)scaled_font,
_cairo_scaled_glyph_index(scaled_glyph),
cr, &extents);
@@ -182,14 +195,16 @@ _cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_fon
scaled_glyph->color_glyph = TRUE;
scaled_glyph->color_glyph_set = TRUE;
}
+
cairo_destroy (cr);
+ foreground_used = scaled_font->foreground_marker_used || scaled_font->foreground_colors_used;
}
if (status == (cairo_int_status_t)CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED &&
face->scaled_font_methods.render_glyph) {
if (recording_surface)
cairo_surface_destroy (recording_surface);
- recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE);
+ recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE, foreground_color);
recording_surface->device_transform.x0 = .25 * _cairo_scaled_glyph_xphase (scaled_glyph);
recording_surface->device_transform.y0 = .25 * _cairo_scaled_glyph_yphase (scaled_glyph);
@@ -205,6 +220,7 @@ _cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_fon
}
cairo_destroy (cr);
+ foreground_used = FALSE;
}
if (status != CAIRO_INT_STATUS_SUCCESS) {
@@ -215,7 +231,8 @@ _cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_fon
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
&scaled_font->base,
- recording_surface);
+ recording_surface,
+ foreground_used ? foreground_color : NULL);
}
/* set metrics */
@@ -265,8 +282,8 @@ _cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t *scaled_font,
cairo_surface_t *surface;
cairo_format_t format;
int width, height;
- cairo_bool_t foreground_used;
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
+ cairo_bool_t foreground_used;
/* TODO
* extend the glyph cache to support argb glyphs.
@@ -313,20 +330,23 @@ _cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t *scaled_font,
surface,
foreground_color,
&foreground_used);
+
} else {
status = _cairo_recording_surface_replay (scaled_glyph->recording_surface, surface);
+ foreground_used = FALSE;
}
-
if (unlikely (status)) {
cairo_surface_destroy(surface);
return status;
}
+ foreground_used = foreground_used || scaled_glyph->recording_uses_foreground_color;
+
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
&scaled_font->base,
(cairo_image_surface_t *)surface,
- foreground_used);
+ foreground_used ? foreground_color : NULL);
surface = NULL;
} else {
_cairo_scaled_glyph_set_surface (scaled_glyph,
@@ -341,6 +361,18 @@ _cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t *scaled_font,
return status;
}
+static void
+_cairo_user_scaled_glyph_fini (void *abstract_font)
+{
+ cairo_user_scaled_font_t *scaled_font = abstract_font;
+
+ if (scaled_font->foreground_pattern)
+ cairo_pattern_destroy (scaled_font->foreground_pattern);
+
+ if (scaled_font->foreground_marker)
+ cairo_pattern_destroy (scaled_font->foreground_marker);
+}
+
static cairo_int_status_t
_cairo_user_scaled_glyph_init (void *abstract_font,
cairo_scaled_glyph_t *scaled_glyph,
@@ -349,9 +381,21 @@ _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) {
- status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph);
+ 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) {
+ status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph, foreground_color);
if (status)
return status;
}
@@ -511,7 +555,7 @@ _cairo_user_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
CAIRO_FONT_TYPE_USER,
- NULL, /* scaled_font_fini */
+ _cairo_user_scaled_glyph_fini,
_cairo_user_scaled_glyph_init,
_cairo_user_text_to_glyphs,
_cairo_user_ucs4_to_index,
@@ -553,6 +597,10 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
return status;
}
+ 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;
+
/* XXX metrics hinting? */
/* compute a normalized version of font scale matrix to compute
@@ -601,7 +649,7 @@ _cairo_user_font_face_scaled_font_create (void *abstract_
cairo_surface_t *recording_surface;
cairo_t *cr;
- recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font, FALSE);
+ recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font, FALSE, NULL);
cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface, FALSE);
cairo_surface_destroy (recording_surface);
@@ -1056,3 +1104,119 @@ cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
user_font_face = (cairo_user_font_face_t *) font_face;
return user_font_face->scaled_font_methods.unicode_to_glyph;
}
+
+/**
+ * cairo_user_scaled_font_get_foreground_marker:
+ * @scaled_font: A user scaled font
+ *
+ * Gets the foreground pattern of the glyph currently being
+ * rendered. A #cairo_user_scaled_font_render_glyph_func_t function
+ * that has been set with
+ * cairo_user_font_face_set_render_color_glyph_func() may call this
+ * function to retrieve the current foreground pattern for the glyph
+ * being rendered. The function should not be called outside of a
+ * cairo_user_font_face_set_render_color_glyph_func() callback.
+ *
+ * The foreground marker pattern contains an internal marker to
+ * indicate that it is to be substituted with the current source when
+ * rendered to a surface. Querying the foreground marker will reveal a
+ * solid black color, however this is not representative of the color
+ * that will actually be used. Similarly, setting a solid black color
+ * will render black, not the foreground pattern when the glyph is
+ * painted to a surface. Using the foreground marker as the source
+ * instead of cairo_user_scaled_font_get_foreground_source() in a
+ * color render callback has the following benefits:
+ *
+ * 1. Cairo only needs to call the render callback once as it can
+ * cache the recording. Cairo will substitute the actual foreground
+ * color when rendering the recording.
+ *
+ * 2. On backends that have the concept of a foreground color in fonts such as
+ * PDF, PostScript, and SVG, cairo can generate more optimal
+ * output. The glyph can be included in an embedded font.
+ *
+ * The one drawback of the using foreground marker is the render
+ * callback can not access the color components of the pattern as the
+ * actual foreground pattern is not available at the time the render
+ * callback is invoked. If the render callback needs to query the
+ * foreground pattern, use
+ * cairo_user_scaled_font_get_foreground_source().
+ *
+ * If the render callback simply wants to call cairo_set_source() with
+ * the foreground pattern,
+ * cairo_user_scaled_font_get_foreground_marker() is the preferred
+ * function to use as it results in better performance than
+ * cairo_user_scaled_font_get_foreground_source().
+ *
+ * Return value: the current foreground source marker pattern. This
+ * object is owned by cairo. This object must not be modified or used
+ * outside of a color render callback. To keep a reference to it,
+ * you must call cairo_pattern_reference().
+ *
+ * Since: 1.18
+ **/
+cairo_pattern_t *
+cairo_user_scaled_font_get_foreground_marker (cairo_scaled_font_t *scaled_font)
+{
+ cairo_user_scaled_font_t *user_scaled_font;
+
+ if (scaled_font->backend != &_cairo_user_scaled_font_backend)
+ return _cairo_pattern_create_in_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+
+ user_scaled_font = (cairo_user_scaled_font_t *)scaled_font;
+ return user_scaled_font->foreground_marker;
+}
+
+/**
+ * cairo_user_scaled_font_get_foreground_source:
+ * @scaled_font: A user scaled font
+ *
+ * Gets the foreground pattern of the glyph currently being
+ * rendered. A #cairo_user_scaled_font_render_glyph_func_t function
+ * that has been set with
+ * cairo_user_font_face_set_render_color_glyph_func() may call this
+ * function to retrieve the current foreground pattern for the glyph
+ * being rendered. The function should not be called outside of a
+ * cairo_user_font_face_set_render_color_glyph_func() callback.
+ *
+ * This function returns the current source at the time the glyph is
+ * rendered. Compared with
+ * cairo_user_scaled_font_get_foreground_marker(), this function
+ * returns the actual source pattern that will be used to render the
+ * glyph. The render callback is free to query the pattern and
+ * extract color components or other pattern data. For example if the
+ * render callback wants to create a gradient stop based on colors in
+ * the foreground source pattern, it will need to use this function in
+ * order to be able to query the colors in the foreground pattern.
+ *
+ * While this function does not have the restrictions on using the
+ * pattern that cairo_user_scaled_font_get_foreground_marker() has, it
+ * does incur a performance penalty. If a render callback calls this
+ * function:
+ *
+ * 1. Cairo will call the render callback whenever the current pattern
+ * of the context in which the glyph is rendered changes.
+ *
+ * 2. On backends that support font embedding (PDF, PostScript, and
+ * SVG), cairo can not embed this glyph in a font. Instead the glyph
+ * will be emitted as an image or sequence of drawing operations each
+ * time it is used.
+ *
+ * Return value: the current foreground source pattern. This object is
+ * owned by cairo. To keep a reference to it, you must call
+ * cairo_pattern_reference().
+ *
+ * Since: 1.18
+ **/
+cairo_pattern_t *
+cairo_user_scaled_font_get_foreground_source (cairo_scaled_font_t *scaled_font)
+{
+ cairo_user_scaled_font_t *user_scaled_font;
+
+ if (scaled_font->backend != &_cairo_user_scaled_font_backend)
+ return _cairo_pattern_create_in_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
+
+ user_scaled_font = (cairo_user_scaled_font_t *)scaled_font;
+ user_scaled_font->foreground_colors_used = TRUE;
+ return user_scaled_font->foreground_pattern;
+}
diff --git a/src/cairo.h b/src/cairo.h
index c74d7c2c5..a9b423b28 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1815,25 +1815,14 @@ typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_
* cairo_user_font_face_set_render_glyph_func(), the result is
* undefined if any source other than the default source on @cr is
* used. That means, glyph bitmaps should be rendered using
- * cairo_mask() instead of cairo_paint(). When this callback is set with
- * cairo_user_font_face_set_render_color_glyph_func(), setting the
- * source is a valid operation.
+ * cairo_mask() instead of cairo_paint().
*
* When this callback is set with
* cairo_user_font_face_set_render_color_glyph_func(), the default
- * source is the current source color of the context that is rendering
- * the user font. That is, the same color a non-color user font will
- * be rendered in. In most cases the callback will want to set a
- * specific color. If the callback wishes to use the current context
- * color after using another source, it should retain a reference to
- * the source or use cairo_save()/cairo_restore() prior to changing
- * the source. Note that the default source contains an internal
- * marker to indicate that it is to be substituted with the current
- * context source color when rendered to a surface. Querying the
- * default source pattern will reveal a solid black color, however
- * this is not representative of the color that will actually be
- * used. Similarly, setting a solid black color will render black, not
- * the current context source when the glyph is painted to a surface.
+ * source is black. Setting the source is a valid
+ * operation. cairo_user_scaled_font_get_foreground_marker() or
+ * cairo_user_scaled_font_get_foreground_source() may be called to
+ * obtain the current source at the time the glyph is rendered.
*
* Other non-default settings on @cr include a font size of 1.0 (given that
* it is set up to be in font space), and font options corresponding to
@@ -1856,10 +1845,13 @@ typedef cairo_status_t (*cairo_user_scaled_font_init_func_t) (cairo_scaled_font_
* Where both color and non-color callbacks has been set using
* cairo_user_font_face_set_render_color_glyph_func(), and
* cairo_user_font_face_set_render_glyph_func(), the color glyph
- * callback may return %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED if the
- * glyph is not a color glyph. This is the only case in which the
- * %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED may be returned from a
- * render callback.
+ * callback will be called first. If the color glyph callback returns
+ * %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, any drawing operations are
+ * discarded and the non-color callback will be called. This is the
+ * only case in which the %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED may
+ * be returned from a render callback. This fallback sequence allows a
+ * user font face to contain a combination of both color and non-color
+ * glyphs.
*
* Returns: %CAIRO_STATUS_SUCCESS upon success,
* %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED if fallback options should be tried,
@@ -2027,6 +2019,11 @@ cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face);
cairo_public cairo_user_scaled_font_unicode_to_glyph_func_t
cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face);
+cairo_public cairo_pattern_t *
+cairo_user_scaled_font_get_foreground_marker (cairo_scaled_font_t *scaled_font);
+
+cairo_public cairo_pattern_t *
+cairo_user_scaled_font_get_foreground_source (cairo_scaled_font_t *scaled_font);
/* Query functions */
diff --git a/src/cairoint.h b/src/cairoint.h
index 65bc16f53..af2501057 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1292,13 +1292,14 @@ _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
cairo_private void
_cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
cairo_scaled_font_t *scaled_font,
- cairo_surface_t *recording_surface);
+ cairo_surface_t *recording_surface,
+ const cairo_color_t *foreground_color);
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_bool_t uses_foreground_color);
+ const cairo_color_t *foreground_color);
cairo_private cairo_int_status_t
_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index 764835bc8..f0657d636 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -1065,7 +1065,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
&scaled_font->base,
(cairo_image_surface_t *) image,
- uses_foreground_color);
+ uses_foreground_color ? foreground_color : NULL);
scaled_glyph->color_glyph = TRUE;
scaled_glyph->color_glyph_set = TRUE;