Fix the scaled_glyph_init color glyph logic
and split _cairo_user_scaled_glyph_init() into multiple functions. Update user-font test to test changing foreground text color.
|
|
@ -2500,9 +2500,15 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
|
|||
cairo_image_surface_t *surface;
|
||||
cairo_bool_t uses_foreground_color = FALSE;
|
||||
|
||||
/* Only one info type at a time handled in this function */
|
||||
assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE);
|
||||
|
||||
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
|
||||
if (!unscaled->have_color)
|
||||
if (!unscaled->have_color) {
|
||||
scaled_glyph->color_glyph = FALSE;
|
||||
scaled_glyph->color_glyph_set = TRUE;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FT_PALETTE_SET_FOREGROUND_COLOR
|
||||
FT_LayerIterator iterator;
|
||||
|
|
@ -2539,7 +2545,7 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
|
|||
#ifdef FT_LOAD_COLOR
|
||||
load_flags |= FT_LOAD_COLOR;
|
||||
#endif
|
||||
} else {
|
||||
} else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
|
||||
#ifdef FT_LOAD_COLOR
|
||||
load_flags &= ~FT_LOAD_COLOR;
|
||||
#endif
|
||||
|
|
@ -2571,18 +2577,34 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
if (pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 &&
|
||||
!pixman_image_get_component_alpha (surface->pixman_image)) {
|
||||
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
surface,
|
||||
uses_foreground_color);
|
||||
} else {
|
||||
|
||||
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
|
||||
/* We tried loading a color glyph and can now check if we got
|
||||
* a color glyph and set scaled_glyph->color_glyph
|
||||
* accordingly */
|
||||
if (pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 &&
|
||||
!pixman_image_get_component_alpha (surface->pixman_image))
|
||||
{
|
||||
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
surface,
|
||||
uses_foreground_color);
|
||||
|
||||
scaled_glyph->color_glyph = TRUE;
|
||||
} else {
|
||||
/* We didn't ask for a non-color surface, but store it
|
||||
* anyway so we don't have to load it again. */
|
||||
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
surface);
|
||||
scaled_glyph->color_glyph = FALSE;
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
scaled_glyph->color_glyph_set = TRUE;
|
||||
} else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
|
||||
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
surface);
|
||||
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)
|
||||
scaled_glyph->not_color_glyph = TRUE;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -151,11 +151,10 @@ struct _cairo_scaled_glyph {
|
|||
/* TRUE if the color_surface required the foreground_color to render. */
|
||||
unsigned uses_foreground_color : 1;
|
||||
|
||||
/* TRUE if this is not a color glyph, FALSE if is a color glyph or unknown. */
|
||||
unsigned not_color_glyph : 1;
|
||||
/* TRUE if color_glyph specifies if glyph is color or non color, FALSE if glyph color type unknown. */
|
||||
unsigned color_glyph_set : 1;
|
||||
|
||||
/* TRUE if recording_surface is a color glyph */
|
||||
unsigned recording_is_color : 1;
|
||||
unsigned color_glyph : 1;
|
||||
};
|
||||
|
||||
struct _cairo_scaled_glyph_private {
|
||||
|
|
|
|||
|
|
@ -3057,7 +3057,8 @@ _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
|
|||
need_info = info & ~scaled_glyph->has_info;
|
||||
|
||||
/* If this is not a color glyph, don't try loading the color surface again. */
|
||||
if ((need_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) && scaled_glyph->not_color_glyph)
|
||||
if ((need_info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) &&
|
||||
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
|
||||
|
|
|
|||
|
|
@ -2671,9 +2671,9 @@ composite_one_color_glyph (cairo_surface_t *surface,
|
|||
cairo_matrix_scale (&matrix, x_scale, y_scale);
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR || !has_color)
|
||||
status = _cairo_surface_mask (surface, op, pattern, pattern, clip);
|
||||
status = _cairo_surface_mask (surface, op, pattern, pattern, clip);
|
||||
else
|
||||
status = _cairo_surface_paint (surface, op, pattern, clip);
|
||||
status = _cairo_surface_paint (surface, op, pattern, clip);
|
||||
cairo_pattern_destroy (pattern);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,6 +141,204 @@ _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t
|
|||
return cr;
|
||||
}
|
||||
|
||||
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_user_font_face_t *face =
|
||||
(cairo_user_font_face_t *) scaled_font->base.font_face;
|
||||
cairo_text_extents_t extents = scaled_font->default_glyph_extents;
|
||||
cairo_surface_t *recording_surface = NULL;
|
||||
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_t *cr;
|
||||
|
||||
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);
|
||||
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
recording_surface);
|
||||
} 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);
|
||||
|
||||
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);
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS) {
|
||||
status = cairo_status (cr);
|
||||
scaled_glyph->color_glyph = TRUE;
|
||||
scaled_glyph->color_glyph_set = TRUE;
|
||||
}
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
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->device_transform.x0 = .25 * _cairo_scaled_glyph_xphase (scaled_glyph);
|
||||
recording_surface->device_transform.y0 = .25 * _cairo_scaled_glyph_yphase (scaled_glyph);
|
||||
|
||||
cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, FALSE);
|
||||
|
||||
status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
|
||||
_cairo_scaled_glyph_index(scaled_glyph),
|
||||
cr, &extents);
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS) {
|
||||
status = cairo_status (cr);
|
||||
scaled_glyph->color_glyph = FALSE;
|
||||
scaled_glyph->color_glyph_set = TRUE;
|
||||
}
|
||||
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
if (status != CAIRO_INT_STATUS_SUCCESS) {
|
||||
if (recording_surface)
|
||||
cairo_surface_destroy (recording_surface);
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
recording_surface);
|
||||
}
|
||||
|
||||
/* set metrics */
|
||||
|
||||
if (extents.width == 0.) {
|
||||
cairo_box_t bbox;
|
||||
double x1, y1, x2, y2;
|
||||
double x_scale, y_scale;
|
||||
|
||||
/* Compute extents.x/y/width/height from recording_surface,
|
||||
* in font space.
|
||||
*/
|
||||
status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
|
||||
&bbox,
|
||||
&scaled_font->extent_scale);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
|
||||
|
||||
x_scale = scaled_font->extent_x_scale;
|
||||
y_scale = scaled_font->extent_y_scale;
|
||||
extents.x_bearing = x1 * x_scale;
|
||||
extents.y_bearing = y1 * y_scale;
|
||||
extents.width = (x2 - x1) * x_scale;
|
||||
extents.height = (y2 - y1) * y_scale;
|
||||
}
|
||||
|
||||
if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
|
||||
extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
|
||||
extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
|
||||
}
|
||||
|
||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
&extents);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t *scaled_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_glyph_info_t info,
|
||||
const cairo_color_t *foreground_color)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_format_t format;
|
||||
int width, height;
|
||||
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* TODO
|
||||
* extend the glyph cache to support argb glyphs.
|
||||
* need to figure out the semantics and interaction with subpixel
|
||||
* rendering first.
|
||||
*/
|
||||
|
||||
/* Only one info type at a time handled in this function */
|
||||
assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE);
|
||||
|
||||
width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
|
||||
_cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
|
||||
height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
|
||||
_cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
|
||||
|
||||
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
} else {
|
||||
switch (scaled_font->base.options.antialias) {
|
||||
default:
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
case CAIRO_ANTIALIAS_FAST:
|
||||
case CAIRO_ANTIALIAS_GOOD:
|
||||
case CAIRO_ANTIALIAS_GRAY:
|
||||
format = CAIRO_FORMAT_A8;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
format = CAIRO_FORMAT_A1;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_BEST:
|
||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
surface = cairo_image_surface_create (format, width, height);
|
||||
|
||||
cairo_surface_set_device_offset (surface,
|
||||
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
|
||||
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
|
||||
|
||||
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
|
||||
status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
|
||||
surface,
|
||||
foreground_color);
|
||||
} else {
|
||||
status = _cairo_recording_surface_replay (scaled_glyph->recording_surface, surface);
|
||||
}
|
||||
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy(surface);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
|
||||
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
(cairo_image_surface_t *)surface,
|
||||
TRUE);
|
||||
surface = NULL;
|
||||
} else {
|
||||
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
(cairo_image_surface_t *) surface);
|
||||
surface = NULL;
|
||||
}
|
||||
|
||||
if (surface)
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_user_scaled_glyph_init (void *abstract_font,
|
||||
cairo_scaled_glyph_t *scaled_glyph,
|
||||
|
|
@ -149,185 +347,32 @@ _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_surface_t *recording_surface = scaled_glyph->recording_surface;
|
||||
|
||||
if (!scaled_glyph->recording_surface) {
|
||||
cairo_user_font_face_t *face =
|
||||
(cairo_user_font_face_t *) scaled_font->base.font_face;
|
||||
cairo_text_extents_t extents = scaled_font->default_glyph_extents;
|
||||
cairo_t *cr;
|
||||
|
||||
recording_surface = NULL;
|
||||
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);
|
||||
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
recording_surface);
|
||||
} 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);
|
||||
|
||||
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);
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS) {
|
||||
status = cairo_status (cr);
|
||||
scaled_glyph->recording_is_color = TRUE;
|
||||
}
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
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->device_transform.x0 = .25 * _cairo_scaled_glyph_xphase (scaled_glyph);
|
||||
recording_surface->device_transform.y0 = .25 * _cairo_scaled_glyph_yphase (scaled_glyph);
|
||||
|
||||
cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, FALSE);
|
||||
|
||||
status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
|
||||
_cairo_scaled_glyph_index(scaled_glyph),
|
||||
cr, &extents);
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS)
|
||||
status = cairo_status (cr);
|
||||
|
||||
cairo_destroy (cr);
|
||||
}
|
||||
|
||||
if (status != CAIRO_INT_STATUS_SUCCESS) {
|
||||
if (recording_surface)
|
||||
cairo_surface_destroy (recording_surface);
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
recording_surface);
|
||||
}
|
||||
|
||||
/* set metrics */
|
||||
|
||||
if (extents.width == 0.) {
|
||||
cairo_box_t bbox;
|
||||
double x1, y1, x2, y2;
|
||||
double x_scale, y_scale;
|
||||
|
||||
/* Compute extents.x/y/width/height from recording_surface,
|
||||
* in font space.
|
||||
*/
|
||||
status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
|
||||
&bbox,
|
||||
&scaled_font->extent_scale);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
|
||||
|
||||
x_scale = scaled_font->extent_x_scale;
|
||||
y_scale = scaled_font->extent_y_scale;
|
||||
extents.x_bearing = x1 * x_scale;
|
||||
extents.y_bearing = y1 * y_scale;
|
||||
extents.width = (x2 - x1) * x_scale;
|
||||
extents.height = (y2 - y1) * y_scale;
|
||||
}
|
||||
|
||||
if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
|
||||
extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
|
||||
extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
|
||||
}
|
||||
|
||||
_cairo_scaled_glyph_set_metrics (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
&extents);
|
||||
status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE | CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) {
|
||||
cairo_surface_t *surface;
|
||||
cairo_format_t format;
|
||||
int width, height;
|
||||
if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
|
||||
if (!scaled_glyph->color_glyph )
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* TODO
|
||||
* extend the glyph cache to support argb glyphs.
|
||||
* need to figure out the semantics and interaction with subpixel
|
||||
* rendering first.
|
||||
*/
|
||||
|
||||
width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
|
||||
_cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
|
||||
height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
|
||||
_cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
|
||||
|
||||
if (scaled_glyph->recording_is_color) {
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
} else {
|
||||
switch (scaled_font->base.options.antialias) {
|
||||
default:
|
||||
case CAIRO_ANTIALIAS_DEFAULT:
|
||||
case CAIRO_ANTIALIAS_FAST:
|
||||
case CAIRO_ANTIALIAS_GOOD:
|
||||
case CAIRO_ANTIALIAS_GRAY:
|
||||
format = CAIRO_FORMAT_A8;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_NONE:
|
||||
format = CAIRO_FORMAT_A1;
|
||||
break;
|
||||
case CAIRO_ANTIALIAS_BEST:
|
||||
case CAIRO_ANTIALIAS_SUBPIXEL:
|
||||
format = CAIRO_FORMAT_ARGB32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
surface = cairo_image_surface_create (format, width, height);
|
||||
|
||||
cairo_surface_set_device_offset (surface,
|
||||
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
|
||||
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
|
||||
|
||||
if (scaled_glyph->recording_is_color) {
|
||||
status = _cairo_recording_surface_replay_with_foreground_color (recording_surface,
|
||||
surface,
|
||||
foreground_color);
|
||||
} else {
|
||||
status = _cairo_recording_surface_replay (recording_surface, surface);
|
||||
}
|
||||
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy(surface);
|
||||
status = _cairo_user_scaled_glyph_init_surface (scaled_font,
|
||||
scaled_glyph,
|
||||
CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
|
||||
foreground_color);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scaled_glyph->recording_is_color && (info & CAIRO_SCALED_GLYPH_INFO_SURFACE)) {
|
||||
_cairo_scaled_glyph_set_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
(cairo_image_surface_t *) surface);
|
||||
surface = NULL;
|
||||
}
|
||||
|
||||
if (scaled_glyph->recording_is_color && (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) {
|
||||
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
|
||||
&scaled_font->base,
|
||||
(cairo_image_surface_t *)surface,
|
||||
FALSE);
|
||||
surface = NULL;
|
||||
}
|
||||
|
||||
if (surface)
|
||||
cairo_surface_destroy (surface);
|
||||
if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
|
||||
status = _cairo_user_scaled_glyph_init_surface (scaled_font,
|
||||
scaled_glyph,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
NULL);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
|
||||
|
|
@ -335,7 +380,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
|
|||
if (!path)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = _cairo_recording_surface_get_path (recording_surface, path);
|
||||
status = _cairo_recording_surface_get_path (scaled_glyph->recording_surface, path);
|
||||
if (unlikely (status)) {
|
||||
_cairo_path_fixed_destroy (path);
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -864,8 +864,11 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
|
|||
cairo_bool_t uses_foreground_color = FALSE;
|
||||
|
||||
cairo_dwrite_font_face_t *dwrite_font_face = (cairo_dwrite_font_face_t *)scaled_font->base.font_face;
|
||||
if (!dwrite_font_face->have_color)
|
||||
if (!dwrite_font_face->have_color) {
|
||||
scaled_glyph->color_glyph = FALSE;
|
||||
scaled_glyph->color_glyph_set = TRUE;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
|
||||
y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
|
||||
|
|
@ -931,8 +934,12 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
|
|||
0,
|
||||
&run_enumerator);
|
||||
|
||||
if (hr == DWRITE_E_NOCOLOR)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED; /* No color glyphs */
|
||||
if (hr == DWRITE_E_NOCOLOR) {
|
||||
/* No color glyphs */
|
||||
scaled_glyph->color_glyph = FALSE;
|
||||
scaled_glyph->color_glyph_set = TRUE;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
return _cairo_dwrite_error (hr, "TranslateColorGlyphRun failed");
|
||||
|
|
@ -971,15 +978,11 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
|
|||
return _cairo_dwrite_error (hr, "QueryInterface(&dc4) failed");
|
||||
|
||||
RefPtr<ID2D1SolidColorBrush> foreground_color_brush;
|
||||
if (foreground_color) {
|
||||
dc4->CreateSolidColorBrush(
|
||||
D2D1::ColorF(foreground_color->red,
|
||||
foreground_color->green,
|
||||
foreground_color->blue,
|
||||
foreground_color->alpha), &foreground_color_brush);
|
||||
} else {
|
||||
dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &foreground_color_brush);
|
||||
}
|
||||
dc4->CreateSolidColorBrush(
|
||||
D2D1::ColorF(foreground_color->red,
|
||||
foreground_color->green,
|
||||
foreground_color->blue,
|
||||
foreground_color->alpha), &foreground_color_brush);
|
||||
|
||||
RefPtr<ID2D1SolidColorBrush> color_brush;
|
||||
dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &color_brush);
|
||||
|
|
@ -1027,8 +1030,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
|
|||
nullptr,
|
||||
0,
|
||||
DWRITE_MEASURING_MODE_NATURAL);
|
||||
if (foreground_color)
|
||||
uses_foreground_color = TRUE;
|
||||
uses_foreground_color = TRUE;
|
||||
break;
|
||||
case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE:
|
||||
case DWRITE_GLYPH_IMAGE_FORMATS_CFF:
|
||||
|
|
@ -1068,6 +1070,8 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
|
|||
&scaled_font->base,
|
||||
(cairo_image_surface_t *) image,
|
||||
uses_foreground_color);
|
||||
scaled_glyph->color_glyph = TRUE;
|
||||
scaled_glyph->color_glyph_set = TRUE;
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1115,6 +1115,12 @@ _cairo_win32_scaled_font_glyph_init (void *abstract_font,
|
|||
return status;
|
||||
}
|
||||
|
||||
if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
|
||||
scaled_glyph->color_glyph = FALSE;
|
||||
scaled_glyph->color_glyph_set = TRUE;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
|
||||
status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
|
||||
if (status)
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 9.6 KiB |
BIN
test/reference/user-font.recording.ref.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 5.7 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
|
@ -36,11 +36,13 @@
|
|||
#define TEXT_SIZE 64
|
||||
#define WIDTH (TEXT_SIZE * 15 + 2*BORDER)
|
||||
#ifndef ROTATED
|
||||
#define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
|
||||
#define HEIGHT ((TEXT_SIZE + 2*BORDER)*3)
|
||||
#else
|
||||
#define HEIGHT WIDTH
|
||||
#endif
|
||||
#define TEXT "geez... cairo user-font"
|
||||
|
||||
#define TEXT1 "cairo user-font."
|
||||
#define TEXT2 " zg."
|
||||
|
||||
#define END_GLYPH 0
|
||||
#define STROKE 126
|
||||
|
|
@ -136,8 +138,14 @@ test_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* If color_render is TRUE, use the render_color_glyph callback
|
||||
* instead of the render_glyph callbac. The output should be identical
|
||||
* in this test since the render function does not alter the cairo_t
|
||||
* source.
|
||||
*/
|
||||
static cairo_status_t
|
||||
_user_font_face_create (cairo_font_face_t **out)
|
||||
_user_font_face_create (cairo_font_face_t **out, cairo_bool_t color_render)
|
||||
{
|
||||
/* Simple glyph definition: 1 - 15 means lineto (or moveto for first
|
||||
* point) for one of the points on this grid:
|
||||
|
|
@ -174,8 +182,12 @@ _user_font_face_create (cairo_font_face_t **out)
|
|||
cairo_status_t status;
|
||||
|
||||
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_glyph_func (user_font_face, test_scaled_font_render_glyph);
|
||||
cairo_user_font_face_set_init_func (user_font_face, test_scaled_font_init);
|
||||
if (color_render)
|
||||
cairo_user_font_face_set_render_color_glyph_func (user_font_face, test_scaled_font_render_glyph);
|
||||
else
|
||||
cairo_user_font_face_set_render_glyph_func (user_font_face, test_scaled_font_render_glyph);
|
||||
|
||||
cairo_user_font_face_set_unicode_to_glyph_func (user_font_face, test_scaled_font_unicode_to_glyph);
|
||||
|
||||
status = cairo_font_face_set_user_data (user_font_face,
|
||||
|
|
@ -194,11 +206,15 @@ static cairo_test_status_t
|
|||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_font_face_t *font_face;
|
||||
const char text[] = TEXT;
|
||||
char full_text[100];
|
||||
cairo_font_extents_t font_extents;
|
||||
cairo_text_extents_t extents;
|
||||
cairo_status_t status;
|
||||
|
||||
strcpy(full_text, TEXT1);
|
||||
strcat(full_text, TEXT2);
|
||||
strcat(full_text, TEXT2);
|
||||
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
|
|
@ -207,7 +223,7 @@ draw (cairo_t *cr, int width, int height)
|
|||
cairo_rotate (cr, .6);
|
||||
#endif
|
||||
|
||||
status = _user_font_face_create (&font_face);
|
||||
status = _user_font_face_create (&font_face, FALSE);
|
||||
if (status) {
|
||||
return cairo_test_status_from_status (cairo_test_get_context (cr),
|
||||
status);
|
||||
|
|
@ -219,7 +235,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);
|
||||
|
|
@ -244,16 +260,45 @@ draw (cairo_t *cr, int width, int height)
|
|||
cairo_set_line_width (cr, 2);
|
||||
cairo_stroke (cr);
|
||||
|
||||
/* text in black */
|
||||
/* First line. Text in black, except first "zg." in green */
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.ascent);
|
||||
cairo_show_text (cr, text);
|
||||
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);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
status = _user_font_face_create (&font_face, TRUE);
|
||||
if (status) {
|
||||
return cairo_test_status_from_status (cairo_test_get_context (cr),
|
||||
status);
|
||||
}
|
||||
|
||||
/* filled version of text in blue */
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
cairo_set_font_face (cr, font_face);
|
||||
cairo_font_face_destroy (font_face);
|
||||
|
||||
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_text_path (cr, text);
|
||||
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);
|
||||
|
||||
/* Third line. Filled version of text in blue */
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
cairo_move_to (cr, BORDER, BORDER + font_extents.height + 4*BORDER + 2*font_extents.ascent);
|
||||
cairo_text_path (cr, full_text);
|
||||
cairo_fill (cr);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
|
|
|
|||