Merge branch 'fix-user-fonts-foreground' into 'master'
Add new cairo_user_scaled_font_get_foreground_source() function See merge request cairo/cairo!422
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_COLOR_SURFACE;
|
||||
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;
|
||||
}
|
||||
|
||||
if (need_info) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
37
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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 8.9 KiB |
BIN
test/reference/user-font-color.svg.xfail.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
test/reference/user-font-color.xcb.ref.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
BIN
test/reference/user-font-color.xlib.ref.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 10 KiB |
|
|
@ -32,16 +32,27 @@
|
|||
|
||||
#include "cairo-test.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define BORDER 10
|
||||
#define TEXT_SIZE 64
|
||||
#define WIDTH (TEXT_SIZE * 12 + 2*BORDER)
|
||||
#define HEIGHT (TEXT_SIZE + 2*BORDER)
|
||||
#define WIDTH (TEXT_SIZE * 11 + 2*BORDER)
|
||||
#define HEIGHT (4*TEXT_SIZE + 5*BORDER)
|
||||
|
||||
#define TEXT "abcdefghijkl"
|
||||
#define TEXT "abcdefghij"
|
||||
|
||||
/* These characters will be drawn twice with a different foreground color */
|
||||
#define FG_TEXT "acfh"
|
||||
|
||||
/* Uppercase draws the same text but forces the use of the non-color
|
||||
* render callback */
|
||||
#define TEXT_NO_COLOR "ABCDEFGHIJ"
|
||||
#define FG_TEXT_NO_COLOR "ACFH"
|
||||
|
||||
#define TEXT_PATH "aabccdeffghhij"
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -55,40 +66,60 @@ test_scaled_font_init (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
static void
|
||||
render_glyph_solid (cairo_t *cr, double width, double height, cairo_bool_t color)
|
||||
render_glyph_solid (cairo_t *cr,
|
||||
double width,
|
||||
double height,
|
||||
cairo_bool_t color,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_pattern_t *pattern = cairo_pattern_reference(cairo_get_source (cr));
|
||||
|
||||
if (color)
|
||||
cairo_set_source_rgba (cr, 0, 1, 1, 0.5);
|
||||
cairo_set_source_rgba (cr, 0.7, 0.2, 0.1, 0.9);
|
||||
cairo_rectangle (cr, 0, 0, width/2, height/2);
|
||||
cairo_fill (cr);
|
||||
|
||||
/* Draw the middle rectangle using the foreground color */
|
||||
if (color)
|
||||
cairo_set_source (cr, pattern);
|
||||
if (color) {
|
||||
if (scaled_font)
|
||||
cairo_set_source (cr, cairo_user_scaled_font_get_foreground_marker (scaled_font));
|
||||
else
|
||||
cairo_set_source_rgba (cr, 0.2, 0.5, 0.3, 0.9);
|
||||
}
|
||||
cairo_rectangle (cr, width/4, height/4, width/2, height/2);
|
||||
cairo_fill (cr);
|
||||
|
||||
if (color)
|
||||
cairo_set_source_rgba (cr, 1, 1, 0, 0.5);
|
||||
cairo_set_source_rgba (cr, 0.2, 0.3, 0.5, 0.9);
|
||||
cairo_rectangle (cr, width/2, height/2, width/2, height/2);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_pattern_destroy (pattern);
|
||||
}
|
||||
|
||||
static void
|
||||
render_glyph_linear (cairo_t *cr, double width, double height, cairo_bool_t color)
|
||||
render_glyph_linear (cairo_t *cr,
|
||||
double width,
|
||||
double height,
|
||||
cairo_bool_t color,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_pattern_t *pat;
|
||||
cairo_pattern_t *fg;
|
||||
|
||||
pat = cairo_pattern_create_linear (0.0, 0.0, width, height);
|
||||
cairo_pattern_add_color_stop_rgba (pat, 0, 1, 0, 0, 1);
|
||||
cairo_pattern_add_color_stop_rgba (pat, 0.5, 0, 1, 0, color ? 0.5 : 1);
|
||||
cairo_pattern_add_color_stop_rgba (pat, 1, 0, 0, 1, 1);
|
||||
cairo_set_source (cr, pat);
|
||||
if (scaled_font) {
|
||||
double r, g, b, a;
|
||||
|
||||
fg = cairo_user_scaled_font_get_foreground_source (scaled_font);
|
||||
if (cairo_pattern_get_rgba (fg, &r, &g, &b, &a) != CAIRO_STATUS_SUCCESS) {
|
||||
r = g = b = 0;
|
||||
a = 1;
|
||||
}
|
||||
cairo_pattern_add_color_stop_rgba (pat, 0, r, g, b, a);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1, 0, 0, 1);
|
||||
} else {
|
||||
cairo_pattern_add_color_stop_rgb (pat, 0, 1, 0.4, 0.2);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 0.5, 0.2, 1, 0.4);
|
||||
cairo_pattern_add_color_stop_rgb (pat, 1, 0.2, 0.3, 1);
|
||||
}
|
||||
|
||||
cairo_set_source (cr, pat);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
|
@ -102,23 +133,23 @@ render_glyph_text (cairo_t *cr, double width, double height, cairo_bool_t color)
|
|||
cairo_set_font_size(cr, 0.5);
|
||||
|
||||
if (color)
|
||||
cairo_set_source_rgb (cr, 0.5, 0.5, 0);
|
||||
cairo_set_source_rgb (cr, 0.5, 0.7, 0);
|
||||
cairo_move_to (cr, width*0.1, height/2);
|
||||
cairo_show_text (cr, "a");
|
||||
|
||||
if (color)
|
||||
cairo_set_source_rgb (cr, 0, 0.5, 0.5);
|
||||
cairo_set_source_rgb (cr, 0, 0.5, 0.7);
|
||||
cairo_move_to (cr, width*0.4, height*0.9);
|
||||
cairo_show_text (cr, "z");
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
test_scaled_font_render_color_glyph (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph,
|
||||
cairo_t *cr,
|
||||
cairo_text_extents_t *metrics)
|
||||
test_scaled_font_render_glyph_common (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph,
|
||||
cairo_t *cr,
|
||||
cairo_text_extents_t *metrics,
|
||||
cairo_bool_t color)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
double width = 0.5;
|
||||
double height = 0.8;
|
||||
|
||||
|
|
@ -126,101 +157,80 @@ test_scaled_font_render_color_glyph (cairo_scaled_font_t *scaled_font,
|
|||
cairo_translate (cr, 0.125, -0.6);
|
||||
switch (glyph) {
|
||||
case 'a':
|
||||
render_glyph_solid (cr, width, height, TRUE);
|
||||
render_glyph_solid (cr, width, height, color, scaled_font);
|
||||
break;
|
||||
case 'b':
|
||||
render_glyph_linear (cr, width, height, TRUE);
|
||||
render_glyph_solid (cr, width, height, color, NULL);
|
||||
break;
|
||||
case 'c':
|
||||
render_glyph_text (cr, width, height, TRUE);
|
||||
render_glyph_linear (cr, width, height, color, scaled_font);
|
||||
break;
|
||||
|
||||
/* Ensure that the following glyphs are rendered with
|
||||
* test_scaled_font_render_glyph() even if we draw
|
||||
* something before returning.
|
||||
*/
|
||||
case 'd':
|
||||
render_glyph_solid (cr, width, height, TRUE);
|
||||
status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
render_glyph_linear (cr, width, height, color, NULL);
|
||||
break;
|
||||
case 'e':
|
||||
render_glyph_linear (cr, width, height, TRUE);
|
||||
status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
render_glyph_text (cr, width, height, color);
|
||||
break;
|
||||
case 'f':
|
||||
render_glyph_solid (cr, width, height, TRUE);
|
||||
status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
cairo_push_group (cr);
|
||||
render_glyph_solid (cr, width, height, color, scaled_font);
|
||||
cairo_pop_group_to_source (cr);
|
||||
cairo_paint (cr);
|
||||
break;
|
||||
case 'g':
|
||||
cairo_push_group (cr);
|
||||
render_glyph_solid (cr, width, height, TRUE);
|
||||
render_glyph_solid (cr, width, height, color, NULL);
|
||||
cairo_pop_group_to_source (cr);
|
||||
cairo_paint (cr);
|
||||
break;
|
||||
case 'h':
|
||||
cairo_push_group (cr);
|
||||
render_glyph_linear (cr, width, height, TRUE);
|
||||
render_glyph_linear (cr, width, height, color, scaled_font);
|
||||
cairo_pop_group_to_source (cr);
|
||||
cairo_paint (cr);
|
||||
break;
|
||||
case 'i':
|
||||
cairo_push_group (cr);
|
||||
render_glyph_text (cr, width, height, TRUE);
|
||||
render_glyph_linear (cr, width, height, color, NULL);
|
||||
cairo_pop_group_to_source (cr);
|
||||
cairo_paint (cr);
|
||||
break;
|
||||
default:
|
||||
status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
test_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph,
|
||||
cairo_t *cr,
|
||||
cairo_text_extents_t *metrics)
|
||||
{
|
||||
double width = 0.5;
|
||||
double height = 0.8;
|
||||
metrics->x_advance = 0.75;
|
||||
cairo_translate (cr, 0.125, -0.6);
|
||||
switch (glyph) {
|
||||
case 'd':
|
||||
render_glyph_solid (cr, width, height, FALSE);
|
||||
break;
|
||||
case 'e':
|
||||
render_glyph_linear (cr, width, height, FALSE);
|
||||
break;
|
||||
case 'f':
|
||||
render_glyph_text (cr, width, height, FALSE);
|
||||
break;
|
||||
case 'j':
|
||||
cairo_push_group (cr);
|
||||
render_glyph_solid (cr, width, height, FALSE);
|
||||
render_glyph_text (cr, width, height, color);
|
||||
cairo_pop_group_to_source (cr);
|
||||
cairo_paint (cr);
|
||||
break;
|
||||
case 'k':
|
||||
cairo_push_group (cr);
|
||||
render_glyph_linear (cr, width, height, FALSE);
|
||||
cairo_pop_group_to_source (cr);
|
||||
cairo_paint (cr);
|
||||
break;
|
||||
case 'l':
|
||||
cairo_push_group (cr);
|
||||
render_glyph_text (cr, width, height, FALSE);
|
||||
cairo_pop_group_to_source (cr);
|
||||
cairo_paint (cr);
|
||||
break;
|
||||
default:
|
||||
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
test_scaled_font_render_color_glyph_callback (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph,
|
||||
cairo_t *cr,
|
||||
cairo_text_extents_t *metrics)
|
||||
{
|
||||
if (isupper(glyph))
|
||||
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
|
||||
return test_scaled_font_render_glyph_common (scaled_font, glyph, cr, metrics, TRUE);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
test_scaled_font_render_glyph_callback (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph,
|
||||
cairo_t *cr,
|
||||
cairo_text_extents_t *metrics)
|
||||
{
|
||||
int c = glyph;
|
||||
if (isupper(c))
|
||||
c = tolower(c);
|
||||
|
||||
return test_scaled_font_render_glyph_common (scaled_font, c, cr, metrics, FALSE);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_user_font_face_create (cairo_font_face_t **out)
|
||||
{
|
||||
|
|
@ -229,13 +239,35 @@ _user_font_face_create (cairo_font_face_t **out)
|
|||
|
||||
user_font_face = cairo_user_font_face_create ();
|
||||
cairo_user_font_face_set_init_func (user_font_face, test_scaled_font_init);
|
||||
cairo_user_font_face_set_render_color_glyph_func (user_font_face, test_scaled_font_render_color_glyph);
|
||||
cairo_user_font_face_set_render_glyph_func (user_font_face, test_scaled_font_render_glyph);
|
||||
cairo_user_font_face_set_render_color_glyph_func (user_font_face,
|
||||
test_scaled_font_render_color_glyph_callback);
|
||||
cairo_user_font_face_set_render_glyph_func (user_font_face,
|
||||
test_scaled_font_render_glyph_callback);
|
||||
|
||||
*out = user_font_face;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Any text characters that are in fg_text will be drawn with a different color */
|
||||
static void
|
||||
draw_line (cairo_t *cr, const char *text, const char *fg_text)
|
||||
{
|
||||
char buf[10];
|
||||
|
||||
for (unsigned i = 0; i < strlen(text); i++) {
|
||||
buf[0] = text[i];
|
||||
buf[1] = 0;
|
||||
|
||||
if (strchr (fg_text, text[i])) {
|
||||
cairo_set_source_rgb (cr, 1, 0, 0);
|
||||
cairo_show_text (cr, buf);
|
||||
}
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 1, 0);
|
||||
cairo_show_text (cr, buf);
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
|
|
@ -244,6 +276,7 @@ draw (cairo_t *cr, int width, int height)
|
|||
cairo_font_extents_t font_extents;
|
||||
cairo_text_extents_t extents;
|
||||
cairo_status_t status;
|
||||
cairo_font_options_t *font_options;
|
||||
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
|
@ -285,10 +318,31 @@ draw (cairo_t *cr, int width, int height)
|
|||
cairo_set_line_width (cr, 2);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* text in color */
|
||||
cairo_set_source_rgb (cr, 0, 0.3, 0);
|
||||
/* Line 1: text in color */
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
|
||||
cairo_show_text (cr, text);
|
||||
draw_line (cr, TEXT, FG_TEXT);
|
||||
|
||||
/* Line 2: text in non-color (color render callback returns
|
||||
* CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED.
|
||||
*/
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.height + 1*BORDER + font_extents.ascent);
|
||||
draw_line (cr, TEXT_NO_COLOR, FG_TEXT_NO_COLOR);
|
||||
|
||||
/* Line 3: Filled version of color text in blue */
|
||||
cairo_move_to (cr, BORDER, BORDER + 2*font_extents.height + 2*BORDER + font_extents.ascent);
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
cairo_text_path (cr, TEXT_PATH);
|
||||
cairo_fill (cr);
|
||||
|
||||
/* Line 4: color glyphs with CAIRO_COLOR_MODE_NO_COLOR font option. */
|
||||
font_options = cairo_font_options_create ();
|
||||
cairo_get_font_options (cr, font_options);
|
||||
cairo_font_options_set_color_mode (font_options, CAIRO_COLOR_MODE_NO_COLOR);
|
||||
cairo_set_font_options (cr, font_options);
|
||||
cairo_font_options_destroy (font_options);
|
||||
|
||||
cairo_move_to (cr, BORDER, BORDER + 3*font_extents.height + 3*BORDER + font_extents.ascent);
|
||||
draw_line (cr, TEXT, FG_TEXT);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,9 @@
|
|||
#else
|
||||
#define HEIGHT WIDTH
|
||||
#endif
|
||||
#define TEXT "geez... cairo user-font"
|
||||
|
||||
#define TEXT1 "cairo user-font."
|
||||
#define TEXT2 " zg"
|
||||
|
||||
static cairo_user_data_key_t fallback_font_key;
|
||||
|
||||
|
|
@ -148,11 +150,16 @@ _user_font_face_create (cairo_font_face_t **out)
|
|||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
const char text[] = TEXT;
|
||||
cairo_font_extents_t font_extents;
|
||||
cairo_text_extents_t extents;
|
||||
cairo_font_face_t *font_face;
|
||||
cairo_status_t status;
|
||||
char full_text[100];
|
||||
|
||||
strcpy(full_text, TEXT1);
|
||||
strcat(full_text, TEXT2);
|
||||
strcat(full_text, TEXT2);
|
||||
strcat(full_text, TEXT2);
|
||||
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
|
@ -174,7 +181,7 @@ draw (cairo_t *cr, int width, int height)
|
|||
cairo_set_font_size (cr, TEXT_SIZE);
|
||||
|
||||
cairo_font_extents (cr, &font_extents);
|
||||
cairo_text_extents (cr, text, &extents);
|
||||
cairo_text_extents (cr, full_text, &extents);
|
||||
|
||||
/* logical boundaries in red */
|
||||
cairo_move_to (cr, 0, BORDER);
|
||||
|
|
@ -199,16 +206,26 @@ draw (cairo_t *cr, int width, int height)
|
|||
cairo_set_line_width (cr, 2);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* text in gray */
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
|
||||
cairo_show_text (cr, text);
|
||||
|
||||
/* TEXT1 in black */
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_show_text (cr, TEXT1);
|
||||
|
||||
/* Draw TEXT2 three times with three different foreground colors.
|
||||
* This checks that cairo uses the foreground color and does not cache
|
||||
* glyph images when the foreground color changes.
|
||||
*/
|
||||
cairo_show_text (cr, TEXT2);
|
||||
cairo_set_source_rgb (cr, 0, 0.5, 0);
|
||||
cairo_show_text (cr, TEXT2);
|
||||
cairo_set_source_rgb (cr, 0.2, 0.5, 0.5);
|
||||
cairo_show_text (cr, TEXT2);
|
||||
|
||||
/* filled version of text in light blue */
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.height + BORDER + font_extents.ascent);
|
||||
cairo_text_path (cr, text);
|
||||
cairo_text_path (cr, full_text);
|
||||
cairo_fill (cr);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#define BORDER 10
|
||||
#define TEXT_SIZE 64
|
||||
#define WIDTH (TEXT_SIZE * 15 + 2*BORDER)
|
||||
#define WIDTH (TEXT_SIZE * 16 + 2*BORDER)
|
||||
#ifndef ROTATED
|
||||
#define HEIGHT ((TEXT_SIZE + 2*BORDER)*3)
|
||||
#else
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
#endif
|
||||
|
||||
#define TEXT1 "cairo user-font."
|
||||
#define TEXT2 " zg."
|
||||
#define TEXT2 " zg"
|
||||
|
||||
#define END_GLYPH 0
|
||||
#define STROKE 126
|
||||
|
|
@ -202,6 +202,24 @@ _user_font_face_create (cairo_font_face_t **out, cairo_bool_t color_render)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_line (cairo_t *cr)
|
||||
{
|
||||
/* TEXT1 in black */
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_show_text (cr, TEXT1);
|
||||
|
||||
/* Draw TEXT2 three times with three different foreground colors.
|
||||
* This checks that cairo uses the foreground color and does not cache
|
||||
* glyph images when the foreground color changes.
|
||||
*/
|
||||
cairo_show_text (cr, TEXT2);
|
||||
cairo_set_source_rgb (cr, 0, 0.5, 0);
|
||||
cairo_show_text (cr, TEXT2);
|
||||
cairo_set_source_rgb (cr, 0.2, 0.5, 0.5);
|
||||
cairo_show_text (cr, TEXT2);
|
||||
}
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
|
|
@ -214,6 +232,7 @@ draw (cairo_t *cr, int width, int height)
|
|||
strcpy(full_text, TEXT1);
|
||||
strcat(full_text, TEXT2);
|
||||
strcat(full_text, TEXT2);
|
||||
strcat(full_text, TEXT2);
|
||||
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
|
@ -260,21 +279,14 @@ draw (cairo_t *cr, int width, int height)
|
|||
cairo_set_line_width (cr, 2);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* First line. Text in black, except first "zg." in green */
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
/* First line. TEXT1 in black. TEXT2 in different colors. */
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
|
||||
cairo_show_text (cr, TEXT1);
|
||||
cairo_set_source_rgb (cr, 0, 1, 0);
|
||||
cairo_show_text (cr, TEXT2);
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_show_text (cr, TEXT2);
|
||||
draw_line (cr);
|
||||
|
||||
/* Now draw the second line using the render_color_glyph callback. The
|
||||
* output should be the same because same render function is used
|
||||
* and the render function does not set a color. This exercises
|
||||
* the paint color glyph with foreground color code path and
|
||||
* ensures cairo updates the glyph image when the foreground color
|
||||
* changes.
|
||||
/* Now draw the second line using the render_color_glyph
|
||||
* callback. The text should be all black because the default
|
||||
* color of render function is used instead of the foreground
|
||||
* color.
|
||||
*/
|
||||
status = _user_font_face_create (&font_face, TRUE);
|
||||
if (status) {
|
||||
|
|
@ -287,13 +299,8 @@ draw (cairo_t *cr, int width, int height)
|
|||
|
||||
cairo_set_font_size (cr, TEXT_SIZE);
|
||||
|
||||
/* text in black, except first "zg." in green */
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.height + 2*BORDER + font_extents.ascent);
|
||||
cairo_show_text (cr, TEXT1);
|
||||
cairo_set_source_rgb (cr, 0, 1, 0);
|
||||
cairo_show_text (cr, TEXT2);
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_show_text (cr, TEXT2);
|
||||
draw_line (cr);
|
||||
|
||||
/* Third line. Filled version of text in blue */
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
|
|
|
|||