diff --git a/src/cairo-font-options.c b/src/cairo-font-options.c index 73a1c6b75..30d695894 100644 --- a/src/cairo-font-options.c +++ b/src/cairo-font-options.c @@ -57,6 +57,7 @@ static const cairo_font_options_t _cairo_font_options_nil = { CAIRO_HINT_METRICS_DEFAULT, CAIRO_ROUND_GLYPH_POS_DEFAULT, NULL, /* variations */ + CAIRO_COLOR_MODE_DEFAULT, CAIRO_COLOR_PALETTE_DEFAULT }; @@ -76,6 +77,7 @@ _cairo_font_options_init_default (cairo_font_options_t *options) options->hint_metrics = CAIRO_HINT_METRICS_DEFAULT; options->round_glyph_positions = CAIRO_ROUND_GLYPH_POS_DEFAULT; options->variations = NULL; + options->color_mode = CAIRO_COLOR_MODE_DEFAULT; options->palette_index = CAIRO_COLOR_PALETTE_DEFAULT; } @@ -90,6 +92,7 @@ _cairo_font_options_init_copy (cairo_font_options_t *options, options->hint_metrics = other->hint_metrics; options->round_glyph_positions = other->round_glyph_positions; options->variations = other->variations ? strdup (other->variations) : NULL; + options->color_mode = other->color_mode; options->palette_index = other->palette_index; } @@ -259,6 +262,8 @@ cairo_font_options_merge (cairo_font_options_t *options, } } + if (other->color_mode != CAIRO_COLOR_MODE_DEFAULT) + options->color_mode = other->color_mode; if (other->palette_index != CAIRO_COLOR_PALETTE_DEFAULT) options->palette_index = other->palette_index; } @@ -298,6 +303,7 @@ cairo_font_options_equal (const cairo_font_options_t *options, ((options->variations == NULL && other->variations == NULL) || (options->variations != NULL && other->variations != NULL && strcmp (options->variations, other->variations) == 0)) && + options->color_mode == other->color_mode && options->palette_index == other->palette_index); } slim_hidden_def (cairo_font_options_equal); @@ -333,7 +339,8 @@ cairo_font_options_hash (const cairo_font_options_t *options) (options->subpixel_order << 4) | (options->lcd_filter << 8) | (options->hint_style << 12) | - (options->hint_metrics << 16)) ^ hash; + (options->hint_metrics << 16) | + (options->color_mode << 20)) ^ hash; } slim_hidden_def (cairo_font_options_hash); @@ -631,6 +638,47 @@ cairo_font_options_get_variations (cairo_font_options_t *options) return options->variations; } +/** + * cairo_font_options_set_color_mode: + * @options: a #cairo_font_options_t + * @font_color: the new color mode + * + * Sets the color mode for the font options object. This controls + * whether color fonts are to be rendered in color or as outlines. + * See the documentation for #cairo_color_mode_t for full details. + * + * Since: 1.18 + **/ +cairo_public void +cairo_font_options_set_color_mode (cairo_font_options_t *options, + cairo_color_mode_t color_mode) +{ + if (cairo_font_options_status (options)) + return; + + options->color_mode = color_mode; +} + +/** + * cairo_font_options_get_color_mode: + * @options: a #cairo_font_options_t + * + * Gets the color mode for the font options object. + * See the documentation for #cairo_color_mode_t for full details. + * + * Return value: the color mode for the font options object + * + * Since: 1.18 + **/ +cairo_public cairo_color_mode_t +cairo_font_options_get_color_mode (const cairo_font_options_t *options) +{ + if (cairo_font_options_status ((cairo_font_options_t *) options)) + return CAIRO_COLOR_MODE_DEFAULT; + + return options->color_mode; +} + /** * cairo_font_options_set_color_palette: * @options: a #cairo_font_options_t diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 41a9a8321..cdb02ff65 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -2664,10 +2664,20 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF; + /* The font metrics for color glyphs should be the same as the + * outline glyphs. But just in case there aren't, request the + * color or outline metrics based on the font option and if + * the font has color. + */ + int color_flag = 0; +#ifdef FT_LOAD_COLOR + if (unscaled->have_color && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) + color_flag = FT_LOAD_COLOR; +#endif status = _cairo_ft_scaled_glyph_load_glyph (scaled_font, scaled_glyph, face, - load_flags, + load_flags | color_flag, !hint_metrics, vertical_layout); if (unlikely (status)) diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 0bc0b8c7d..105f4bff1 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -2901,7 +2901,9 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface, if (unlikely (status)) return status; - if (_cairo_scaled_font_has_color_glyphs (scaled_font)) { + if (_cairo_scaled_font_has_color_glyphs (scaled_font) && + scaled_font->options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) + { utf8_copy = malloc (sizeof (char) * utf8_len); memcpy (utf8_copy, utf8, sizeof (char) * utf8_len); utf8 = utf8_copy; diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index dfb72b2ad..b39a94a37 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -2118,24 +2118,28 @@ _cairo_svg_surface_emit_surface (cairo_svg_document_t *document, assert (is_bounded); _cairo_svg_stream_printf (&document->xml_node_defs, - "xml_node_defs, - uri, uri_len); - } else { - status = _cairo_surface_base64_encode (surface, - &document->xml_node_defs); - if (unlikely (status)) - return status; + if (extents.width != 0 && extents.height != 0) { + _cairo_svg_stream_printf (&document->xml_node_defs, " xlink:href=\""); + cairo_surface_get_mime_data (surface, CAIRO_MIME_TYPE_URI, + &uri, &uri_len); + if (uri != NULL) { + _cairo_svg_surface_emit_attr_value (&document->xml_node_defs, + uri, uri_len); + } else { + status = _cairo_surface_base64_encode (surface, + &document->xml_node_defs); + if (unlikely (status)) + return status; + } + _cairo_svg_stream_printf (&document->xml_node_defs, "\""); } - _cairo_svg_stream_printf (&document->xml_node_defs, "\"/>\n"); + _cairo_svg_stream_printf (&document->xml_node_defs, "/>\n"); return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-types-private.h b/src/cairo-types-private.h index f01afcf2d..a9980f3b9 100644 --- a/src/cairo-types-private.h +++ b/src/cairo-types-private.h @@ -195,6 +195,7 @@ struct _cairo_font_options { cairo_hint_metrics_t hint_metrics; cairo_round_glyph_positions_t round_glyph_positions; char *variations; + cairo_color_mode_t color_mode; unsigned int palette_index; }; diff --git a/src/cairo.h b/src/cairo.h index aec16eaed..82e2c69d8 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -1369,6 +1369,29 @@ typedef enum _cairo_hint_metrics { CAIRO_HINT_METRICS_ON } cairo_hint_metrics_t; +/** + * cairo_color_mode_t: + * @CAIRO_COLOR_MODE_DEFAULT: Use the default color mode for + * font backend and target device, since 1.18. + * @CAIRO_COLOR_MODE_NO_COLOR: Disable rendering color glyphs. Glyphs are + * always rendered as outline glyphs, since 1.18. + * @CAIRO_COLOR_MODE_COLOR: Enable rendering color glyphs. If the font + * contains a color presentation for a glyph, and when supported by + * the font backend, the glyph will be rendered in color, since 1.18. + * + * Specifies if color fonts are to be rendered using the the color + * glyphs or outline glyphs. Glyphs that do not have a color + * presentation, and non-color fonts are not affected by this font + * option. + * + * Since: 1.18 + **/ +typedef enum _cairo_color_mode { + CAIRO_COLOR_MODE_DEFAULT, + CAIRO_COLOR_MODE_NO_COLOR, + CAIRO_COLOR_MODE_COLOR +} cairo_color_mode_t; + /** * cairo_font_options_t: * @@ -1448,6 +1471,13 @@ cairo_font_options_set_variations (cairo_font_options_t *options, #define CAIRO_COLOR_PALETTE_DEFAULT 0 +cairo_public void +cairo_font_options_set_color_mode (cairo_font_options_t *options, + cairo_color_mode_t color_mode); + +cairo_public cairo_color_mode_t +cairo_font_options_get_color_mode (const cairo_font_options_t *options); + cairo_public unsigned int cairo_font_options_get_color_palette (const cairo_font_options_t *options); diff --git a/test/ft-color-font.c b/test/ft-color-font.c index 58a1dc3ca..d10555dcf 100644 --- a/test/ft-color-font.c +++ b/test/ft-color-font.c @@ -27,9 +27,9 @@ #include "cairo-test.h" #include -#define WIDTH 50 -#define HEIGHT WIDTH - +#define SIZE 40 +#define HEIGHT SIZE +#define WIDTH (SIZE * 1.5) #define FONT "Noto Color Emoji" static const char smiley_face_utf8[] = { 0xf0, 0x9f, 0x99, 0x82, 0x00 }; /* U+1F642 */ @@ -87,13 +87,23 @@ static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_test_status_t result; + cairo_font_options_t *font_options; result = set_color_emoji_font (cr); if (result != CAIRO_TEST_SUCCESS) return result; - cairo_set_font_size (cr, HEIGHT/2); - cairo_move_to (cr, width/4, 3*height/4); + cairo_set_font_size (cr, SIZE/2); + cairo_move_to (cr, SIZE/8, 0.7 * SIZE); + + cairo_show_text(cr, smiley_face_utf8); + + /* Show that the color mode font option can disable color rendering */ + 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_show_text(cr, smiley_face_utf8); diff --git a/test/reference/ft-color-font.image16.ref.png b/test/reference/ft-color-font.image16.ref.png index 579cd69c9..8c7463420 100644 Binary files a/test/reference/ft-color-font.image16.ref.png and b/test/reference/ft-color-font.image16.ref.png differ diff --git a/test/reference/ft-color-font.pdf.ref.png b/test/reference/ft-color-font.pdf.ref.png new file mode 100644 index 000000000..3ea9e7850 Binary files /dev/null and b/test/reference/ft-color-font.pdf.ref.png differ diff --git a/test/reference/ft-color-font.recording.ref.png b/test/reference/ft-color-font.recording.ref.png index 902a00c17..5035dde11 100644 Binary files a/test/reference/ft-color-font.recording.ref.png and b/test/reference/ft-color-font.recording.ref.png differ diff --git a/test/reference/ft-color-font.ref.png b/test/reference/ft-color-font.ref.png index 020a1a501..104f24923 100644 Binary files a/test/reference/ft-color-font.ref.png and b/test/reference/ft-color-font.ref.png differ diff --git a/test/reference/ft-color-font.script.xfail.png b/test/reference/ft-color-font.script.xfail.png index f8b166180..238827723 100644 Binary files a/test/reference/ft-color-font.script.xfail.png and b/test/reference/ft-color-font.script.xfail.png differ