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.
This commit is contained in:
Adrian Johnson 2022-04-22 21:18:09 +09:30
parent cdcb67ef87
commit 4815949d2f
21 changed files with 340 additions and 218 deletions

View file

@ -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;

View file

@ -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 {

View file

@ -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

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -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;