diff options
-rw-r--r-- | doc/public/cairo-sections.txt | 2 | ||||
-rw-r--r-- | src/cairo-ft-font.c | 13 | ||||
-rw-r--r-- | src/cairo-quartz-font.c | 2 | ||||
-rw-r--r-- | src/cairo-scaled-font-private.h | 6 | ||||
-rwxr-xr-x | src/cairo-scaled-font.c | 62 | ||||
-rw-r--r-- | src/cairo-user-font.c | 206 | ||||
-rw-r--r-- | src/cairo.h | 37 | ||||
-rw-r--r-- | src/cairoint.h | 5 | ||||
-rw-r--r-- | src/win32/cairo-dwrite-font.cpp | 2 |
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; |