From 3c8dec60e5c9534ccfef25d1a916cf33eba911d4 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Fri, 6 Jan 2023 22:21:16 +1030 Subject: [PATCH] Integrate COLR v1 renderer with cairo-ft-font.c --- meson.build | 1 + src/cairo-colr-glyph-render.c | 53 +++++++++++------------------------ src/cairo-ft-font.c | 48 +++++++++++++++++++++++++------ src/cairo-ft-private.h | 12 ++++++++ src/cairo-pattern.c | 4 ++- src/cairo.c | 2 ++ src/cairoint.h | 5 ++++ src/meson.build | 1 + 8 files changed, 80 insertions(+), 46 deletions(-) diff --git a/meson.build b/meson.build index 02f74856c..75bbf37b1 100644 --- a/meson.build +++ b/meson.build @@ -320,6 +320,7 @@ if freetype_dep.found() }] ft_check_funcs = [ + 'FT_Get_Color_Glyph_Paint', 'FT_Get_X11_Font_Format', 'FT_GlyphSlot_Embolden', 'FT_GlyphSlot_Oblique', diff --git a/src/cairo-colr-glyph-render.c b/src/cairo-colr-glyph-render.c index 68dd100c4..83e8a6229 100644 --- a/src/cairo-colr-glyph-render.c +++ b/src/cairo-colr-glyph-render.c @@ -29,23 +29,24 @@ * Matthias Clasen */ -#include -#include -#include -#include - -#include -#include -#include -#include -#include - #include "cairoint.h" +#include "cairo-array-private.h" #include "cairo-ft-private.h" -#include "cairo-array-private.h" +#include +#include +#include +#include + +#if HAVE_FT_GET_COLOR_GLYPH_PAINT + +#include +#include FT_CONFIG_OPTIONS_H +#include FT_COLOR_H +#include FT_GLYPH_H +#include FT_OUTLINE_H +#include FT_SIZES_H -#ifdef TT_SUPPORT_COLRV1 /* {{{ Utilities */ @@ -829,27 +830,6 @@ _cairo_colr_glyph_bounds (FT_Face face, return CAIRO_STATUS_CLIP_NOT_REPRESENTABLE; } -/* Return what COLR table version this glyph is using, 0 or 1. - * Return -1 if the glyph is not in the COLR table. - */ -int -_cairo_colr_glyph_version (FT_Face face, - unsigned long glyph) -{ - FT_OpaquePaint paint = { NULL, 0 }; - FT_UInt glyph_index, color_index; - FT_LayerIterator iter; - - if (FT_Get_Color_Glyph_Paint (face, glyph, FT_COLOR_INCLUDE_ROOT_TRANSFORM, &paint)) - return 1; - - iter.p = NULL; - if (FT_Get_Color_Glyph_Layer (face, glyph, &glyph_index, &color_index, &iter)) - return 0; - - return -1; -} - static int colorline_uses_foreground (FT_Face face, FT_ColorLine *colorline) @@ -1575,7 +1555,7 @@ add_sweep_gradient_patches (ColorLine *cl, a0, c0, 2 * M_PI, &color, pattern); - goto done; + return; } else { @@ -1586,7 +1566,6 @@ add_sweep_gradient_patches (ColorLine *cl, } } } -done: } } @@ -2106,6 +2085,6 @@ cleanup: /* }}} */ -#endif +#endif /* HAVE_FT_GET_COLOR_GLYPH_PAINT */ /* vim:set foldmethod=marker expandtab: */ diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 823898c23..2578692fd 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -2498,6 +2498,7 @@ typedef enum { CAIRO_FT_GLYPH_TYPE_OUTLINE, CAIRO_FT_GLYPH_TYPE_SVG, CAIRO_FT_GLYPH_TYPE_COLR_V0, + CAIRO_FT_GLYPH_TYPE_COLR_V1, } cairo_ft_glyph_format_t; typedef struct { @@ -2600,6 +2601,7 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font, cairo_status_t status; cairo_image_surface_t *surface; cairo_bool_t uses_foreground_color = FALSE; + cairo_ft_glyph_private_t *glyph_priv = scaled_glyph->dev_private; /* 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); @@ -2643,7 +2645,17 @@ _cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font, glyph = face->glyph; - if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) { + if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) { + uses_foreground_color = _cairo_colr_glyph_uses_foreground (face, + _cairo_scaled_glyph_index(scaled_glyph)); + status = _cairo_render_colr_glyph (face, + glyph->glyph_index, + scaled_font->base.options.palette_index, + foreground_color, + &surface); + } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0 || + glyph_priv->format == CAIRO_FT_GLYPH_TYPE_OUTLINE) { + status = _render_glyph_outline (face, &scaled_font->ft_options.base, &surface); } else { @@ -3084,9 +3096,8 @@ _cairo_ft_scaled_glyph_get_metrics (cairo_ft_scaled_font_t *scaled_font, static cairo_bool_t _cairo_ft_scaled_glyph_is_colr_v0 (cairo_ft_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_t *scaled_glyph, FT_Face face) - { #ifdef HAVE_FT_PALETTE_SELECT FT_LayerIterator iterator; @@ -3095,15 +3106,33 @@ _cairo_ft_scaled_glyph_is_colr_v0 (cairo_ft_scaled_font_t *scaled_font, iterator.p = NULL; if (FT_Get_Color_Glyph_Layer(face, - _cairo_scaled_glyph_index (scaled_glyph), - &layer_glyph_index, - &layer_color_index, - &iterator)) + _cairo_scaled_glyph_index (scaled_glyph), + &layer_glyph_index, + &layer_color_index, + &iterator) == 1) { return TRUE; } #endif + return FALSE; +} +static cairo_bool_t +_cairo_ft_scaled_glyph_is_colr_v1 (cairo_ft_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + FT_Face face) +{ +#if HAVE_FT_GET_COLOR_GLYPH_PAINT + FT_OpaquePaint paint = { NULL, 0 }; + + if (FT_Get_Color_Glyph_Paint (face, + _cairo_scaled_glyph_index (scaled_glyph), + FT_COLOR_INCLUDE_ROOT_TRANSFORM, + &paint) == 1) + { + return TRUE; + } +#endif return FALSE; } @@ -3160,7 +3189,9 @@ _cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t *scaled_font, if (is_svg_format) { glyph_priv->format = CAIRO_FT_GLYPH_TYPE_SVG; } else if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) { - if (_cairo_ft_scaled_glyph_is_colr_v0 (scaled_font, scaled_glyph, face)) + if (_cairo_ft_scaled_glyph_is_colr_v1 (scaled_font, scaled_glyph, face)) + glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V1; + else if (_cairo_ft_scaled_glyph_is_colr_v0 (scaled_font, scaled_glyph, face)) glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V0; else glyph_priv->format = CAIRO_FT_GLYPH_TYPE_OUTLINE; @@ -3252,6 +3283,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font, switch (glyph_priv->format) { case CAIRO_FT_GLYPH_TYPE_BITMAP: case CAIRO_FT_GLYPH_TYPE_OUTLINE: + case CAIRO_FT_GLYPH_TYPE_COLR_V1: status = CAIRO_INT_STATUS_UNSUPPORTED; break; case CAIRO_FT_GLYPH_TYPE_SVG: diff --git a/src/cairo-ft-private.h b/src/cairo-ft-private.h index 75d65b4db..8ce0e95cd 100644 --- a/src/cairo-ft-private.h +++ b/src/cairo-ft-private.h @@ -70,6 +70,18 @@ _cairo_render_svg_glyph (const char *svg_document, cairo_t *cr); #endif +cairo_private cairo_status_t +_cairo_render_colr_glyph (FT_Face face, + unsigned long glyph, + FT_UShort palette_index, + const cairo_color_t *foreground_color, + cairo_image_surface_t **surface); + +cairo_private int +_cairo_colr_glyph_uses_foreground (FT_Face face, + unsigned long glyph); + + CAIRO_END_DECLS #endif /* CAIRO_HAS_FT_FONT */ diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index 2cbd52b2c..64db0a336 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -1048,6 +1048,7 @@ cairo_pattern_create_mesh (void) return &pattern->base; } +slim_hidden_def (cairo_pattern_create_mesh); /** * cairo_pattern_reference: @@ -1283,7 +1284,7 @@ cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern) for (i = 0; i < 4; i++) mesh->has_color[i] = FALSE; } - +slim_hidden_def (cairo_mesh_pattern_begin_patch); static void _calc_control_point (cairo_mesh_patch_t *patch, int control_point) @@ -1400,6 +1401,7 @@ cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern) mesh->current_patch = NULL; } +slim_hidden_def (cairo_mesh_pattern_end_patch); /** * cairo_mesh_pattern_curve_to: diff --git a/src/cairo.c b/src/cairo.c index 7bfc6a143..35696ab89 100644 --- a/src/cairo.c +++ b/src/cairo.c @@ -1595,6 +1595,7 @@ cairo_identity_matrix (cairo_t *cr) if (unlikely (status)) _cairo_set_error (cr, status); } +slim_hidden_def (cairo_identity_matrix); /** * cairo_user_to_device: @@ -2874,6 +2875,7 @@ cairo_clip_extents (cairo_t *cr, if (unlikely (status)) _cairo_set_error (cr, status); } +slim_hidden_def (cairo_clip_extents); /** * cairo_in_clip: diff --git a/src/cairoint.h b/src/cairoint.h index 976162e6f..032d42145 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1950,6 +1950,7 @@ slim_hidden_proto (cairo_append_path); slim_hidden_proto (cairo_arc); slim_hidden_proto (cairo_arc_negative); slim_hidden_proto (cairo_clip); +slim_hidden_proto (cairo_clip_extents); slim_hidden_proto (cairo_clip_preserve); slim_hidden_proto (cairo_close_path); slim_hidden_proto (cairo_copy_path); @@ -1983,6 +1984,7 @@ slim_hidden_proto (cairo_get_tolerance); slim_hidden_proto (cairo_glyph_allocate); slim_hidden_proto (cairo_glyph_free); slim_hidden_proto (cairo_has_current_point); +slim_hidden_proto (cairo_identity_matrix); slim_hidden_proto (cairo_image_surface_create); slim_hidden_proto (cairo_image_surface_create_for_data); slim_hidden_proto (cairo_image_surface_get_data); @@ -2004,7 +2006,9 @@ slim_hidden_proto (cairo_matrix_scale); slim_hidden_proto (cairo_matrix_transform_distance); slim_hidden_proto (cairo_matrix_transform_point); slim_hidden_proto (cairo_matrix_translate); +slim_hidden_proto (cairo_mesh_pattern_begin_patch); slim_hidden_proto (cairo_mesh_pattern_curve_to); +slim_hidden_proto (cairo_mesh_pattern_end_patch); slim_hidden_proto (cairo_mesh_pattern_get_control_point); slim_hidden_proto (cairo_mesh_pattern_get_corner_color_rgba); slim_hidden_proto (cairo_mesh_pattern_get_patch_count); @@ -2020,6 +2024,7 @@ slim_hidden_proto_no_warn (cairo_path_destroy); slim_hidden_proto (cairo_pattern_add_color_stop_rgba); slim_hidden_proto (cairo_pattern_create_for_surface); slim_hidden_proto (cairo_pattern_create_linear); +slim_hidden_proto (cairo_pattern_create_mesh); slim_hidden_proto (cairo_pattern_create_radial); slim_hidden_proto (cairo_pattern_create_rgb); slim_hidden_proto (cairo_pattern_create_rgba); diff --git a/src/meson.build b/src/meson.build index abb04e1ff..30de39f35 100644 --- a/src/meson.build +++ b/src/meson.build @@ -130,6 +130,7 @@ cairo_feature_sources = { ], 'cairo-ft': [ 'cairo-ft-font.c', + 'cairo-colr-glyph-render.c', 'cairo-svg-glyph-render.c' ],