Integrate COLR v1 renderer with cairo-ft-font.c

This commit is contained in:
Adrian Johnson 2023-01-06 22:21:16 +10:30
parent e892d0e92f
commit 3c8dec60e5
8 changed files with 80 additions and 46 deletions

View file

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

View file

@ -29,23 +29,24 @@
* Matthias Clasen <mclasen@redhat.com>
*/
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <freetype/config/ftoption.h>
#include <freetype/ftcolor.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/ftsizes.h>
#include "cairoint.h"
#include "cairo-array-private.h"
#include "cairo-ft-private.h"
#include "cairo-array-private.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#if HAVE_FT_GET_COLOR_GLYPH_PAINT
#include <ft2build.h>
#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: */

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -130,6 +130,7 @@ cairo_feature_sources = {
],
'cairo-ft': [
'cairo-ft-font.c',
'cairo-colr-glyph-render.c',
'cairo-svg-glyph-render.c'
],