diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2022-04-22 21:18:09 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2022-04-25 17:08:07 +0930 |
commit | 4815949d2fd9053c5550de71c2f296005a4aa22d (patch) | |
tree | eb76515c991892c65fc0c326b3e0d16620a67bca | |
parent | cdcb67ef87790ab01c4f32a432f6bd47df0434e5 (diff) |
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.
21 files changed, 327 insertions, 205 deletions
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 60b98fb41..df1aa5b18 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -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; diff --git a/src/cairo-scaled-font-private.h b/src/cairo-scaled-font-private.h index 3b2fe586d..7a19f2539 100644 --- a/src/cairo-scaled-font-private.h +++ b/src/cairo-scaled-font-private.h @@ -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 { diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 270f8ed34..203b6a10c 100755 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -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 diff --git a/src/cairo-surface.c b/src/cairo-surface.c index ec10b2cfa..0bc0b8c7d 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -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); } diff --git a/src/cairo-user-font.c b/src/cairo-user-font.c index b2a05d67d..fd989eaa0 100644 --- a/src/cairo-user-font.c +++ b/src/cairo-user-font.c @@ -142,192 +142,237 @@ _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t } static cairo_int_status_t -_cairo_user_scaled_glyph_init (void *abstract_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info, - const cairo_color_t *foreground_color) +_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_user_scaled_font_t *scaled_font = abstract_font; - cairo_surface_t *recording_surface = scaled_glyph->recording_surface; + cairo_t *cr; - 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; + if (!face->scaled_font_methods.render_color_glyph && !face->scaled_font_methods.render_glyph) + return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED; - 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->color_glyph = TRUE; + scaled_glyph->color_glyph_set = TRUE; + } + cairo_destroy (cr); + } - /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */ - if (_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) { + 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); - _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); + 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; } - 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); + cairo_destroy (cr); + } - cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, FALSE); + if (status != CAIRO_INT_STATUS_SUCCESS) { + if (recording_surface) + cairo_surface_destroy (recording_surface); + return status; + } - 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_scaled_glyph_set_recording_surface (scaled_glyph, + &scaled_font->base, + recording_surface); + } - cairo_destroy (cr); - } + /* set metrics */ - if (status != CAIRO_INT_STATUS_SUCCESS) { - if (recording_surface) - cairo_surface_destroy (recording_surface); - return status; - } + if (extents.width == 0.) { + cairo_box_t bbox; + double x1, y1, x2, y2; + double x_scale, y_scale; - _cairo_scaled_glyph_set_recording_surface (scaled_glyph, - &scaled_font->base, - recording_surface); - } + /* 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; - /* 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; - } + _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); - 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; + 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_scaled_glyph_set_metrics (scaled_glyph, + 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, - &extents); + (cairo_image_surface_t *) surface); + surface = NULL; } - 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 (surface) + cairo_surface_destroy (surface); - /* TODO - * extend the glyph cache to support argb glyphs. - * need to figure out the semantics and interaction with subpixel - * rendering first. - */ + return status; +} - 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); - } +static cairo_int_status_t +_cairo_user_scaled_glyph_init (void *abstract_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info, + const cairo_color_t *foreground_color) +{ + cairo_int_status_t status = CAIRO_STATUS_SUCCESS; + cairo_user_scaled_font_t *scaled_font = abstract_font; - if (unlikely (status)) { - cairo_surface_destroy(surface); + if (!scaled_glyph->recording_surface) { + status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph); + 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 (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) { + if (!scaled_glyph->color_glyph ) + return CAIRO_INT_STATUS_UNSUPPORTED; - 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; - } + status = _cairo_user_scaled_glyph_init_surface (scaled_font, + scaled_glyph, + CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE, + foreground_color); + if (status) + return status; + } - 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; diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp index ec44d3180..0a3b77362 100644 --- a/src/win32/cairo-dwrite-font.cpp +++ b/src/win32/cairo-dwrite-font.cpp @@ -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; } diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c index a3e1bd731..2003a2782 100644 --- a/src/win32/cairo-win32-font.c +++ b/src/win32/cairo-win32-font.c @@ -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) diff --git a/test/reference/user-font.base.argb32.ref.png b/test/reference/user-font.base.argb32.ref.png Binary files differdeleted file mode 100644 index 896dbab25..000000000 --- a/test/reference/user-font.base.argb32.ref.png +++ /dev/null diff --git a/test/reference/user-font.base.rgb24.ref.png b/test/reference/user-font.base.rgb24.ref.png Binary files differdeleted file mode 100644 index 896dbab25..000000000 --- a/test/reference/user-font.base.rgb24.ref.png +++ /dev/null diff --git a/test/reference/user-font.image16.ref.png b/test/reference/user-font.image16.ref.png Binary files differdeleted file mode 100644 index fcdfb5793..000000000 --- a/test/reference/user-font.image16.ref.png +++ /dev/null diff --git a/test/reference/user-font.mask.argb32.ref.png b/test/reference/user-font.mask.argb32.ref.png Binary files differdeleted file mode 100644 index b234a8801..000000000 --- a/test/reference/user-font.mask.argb32.ref.png +++ /dev/null diff --git a/test/reference/user-font.mask.rgb24.ref.png b/test/reference/user-font.mask.rgb24.ref.png Binary files differdeleted file mode 100644 index b234a8801..000000000 --- a/test/reference/user-font.mask.rgb24.ref.png +++ /dev/null diff --git a/test/reference/user-font.pdf.ref.png b/test/reference/user-font.pdf.ref.png Binary files differdeleted file mode 100644 index 5dc028eb3..000000000 --- a/test/reference/user-font.pdf.ref.png +++ /dev/null diff --git a/test/reference/user-font.ps.ref.png b/test/reference/user-font.ps.ref.png Binary files differdeleted file mode 100644 index 3a674c30a..000000000 --- a/test/reference/user-font.ps.ref.png +++ /dev/null diff --git a/test/reference/user-font.quartz.ref.png b/test/reference/user-font.quartz.ref.png Binary files differindex dfb2e0a15..f1a8d5752 100644 --- a/test/reference/user-font.quartz.ref.png +++ b/test/reference/user-font.quartz.ref.png diff --git a/test/reference/user-font.recording.ref.png b/test/reference/user-font.recording.ref.png Binary files differnew file mode 100644 index 000000000..aefe4c9fe --- /dev/null +++ b/test/reference/user-font.recording.ref.png diff --git a/test/reference/user-font.ref.png b/test/reference/user-font.ref.png Binary files differindex 4cff7e996..87a3f68e3 100644 --- a/test/reference/user-font.ref.png +++ b/test/reference/user-font.ref.png diff --git a/test/reference/user-font.svg.ref.png b/test/reference/user-font.svg.ref.png Binary files differdeleted file mode 100644 index b89e92d20..000000000 --- a/test/reference/user-font.svg.ref.png +++ /dev/null diff --git a/test/reference/user-font.traps.argb32.ref.png b/test/reference/user-font.traps.argb32.ref.png Binary files differdeleted file mode 100644 index 896dbab25..000000000 --- a/test/reference/user-font.traps.argb32.ref.png +++ /dev/null diff --git a/test/reference/user-font.traps.rgb24.ref.png b/test/reference/user-font.traps.rgb24.ref.png Binary files differdeleted file mode 100644 index 896dbab25..000000000 --- a/test/reference/user-font.traps.rgb24.ref.png +++ /dev/null diff --git a/test/user-font.c b/test/user-font.c index 435d5616f..d02a90f4d 100644 --- a/test/user-font.c +++ b/test/user-font.c @@ -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); + } + cairo_set_font_face (cr, font_face); + cairo_font_face_destroy (font_face); - /* filled version of text in blue */ - cairo_set_source_rgb (cr, 0, 0, 1); + 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; |