From f9d05eb32695dfcbc5c7ae747c0c794e64cc55b8 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Thu, 14 Jun 2018 21:02:49 +0200 Subject: [PATCH] Provide iterative API to access `COLR' data. This solution doesn't store any data in an `FT_GlyphSlot' object. * include/freetype/freetype.h (FT_LayerIterator): New structure. (FT_Get_Color_Glyph_Layer): New function. * include/freetype/internal/sfnt.h (TT_Get_Colr_Layer_Func): New function type. (SFNT_Interface, FT_DEFINE_SFNT_INTERFACE): Add it. * src/base/ftobjs.c (FT_Get_Color_Glyph_Layer): Implement it. * src/sfnt/ttcolr.c (tt_face_get_colr_layer): New function. * src/sfnt/ttcolr.h: Updated. * src/sfnt/sfdriver.c (sfnt_interface): Updated. --- ChangeLog | 20 +++++++ include/freetype/freetype.h | 97 +++++++++++++++++++++++++++++++- include/freetype/internal/sfnt.h | 43 ++++++++++++++ src/base/ftobjs.c | 31 ++++++++++ src/sfnt/sfdriver.c | 2 + src/sfnt/ttcolr.c | 48 ++++++++++++++++ src/sfnt/ttcolr.h | 6 ++ 7 files changed, 246 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b1bec04ee..5df7fa590 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2018-06-14 Werner Lemberg + + Provide iterative API to access `COLR' data. + + This solution doesn't store any data in an `FT_GlyphSlot' object. + + * include/freetype/freetype.h (FT_LayerIterator): New structure. + (FT_Get_Color_Glyph_Layer): New function. + + * include/freetype/internal/sfnt.h (TT_Get_Colr_Layer_Func): New + function type. + (SFNT_Interface, FT_DEFINE_SFNT_INTERFACE): Add it. + + * src/base/ftobjs.c (FT_Get_Color_Glyph_Layer): Implement it. + + * src/sfnt/ttcolr.c (tt_face_get_colr_layer): New function. + * src/sfnt/ttcolr.h: Updated. + + * src/sfnt/sfdriver.c (sfnt_interface): Updated. + 2018-06-14 Werner Lemberg Add glyph index and glyph load flags to glyph slot. diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h index 35e6ed652..02abd8a59 100644 --- a/include/freetype/freetype.h +++ b/include/freetype/freetype.h @@ -3101,7 +3101,7 @@ FT_BEGIN_HEADER * blending of the color glyph layers associated with the glyph index, * using the same bitmap format as embedded color bitmap images. This * is mainly for convenience; for full control of color layers use - * @FT_Get_GlyphLayers and FreeType's color functions like + * @FT_Get_Color_Glyph_Layer and FreeType's color functions like * @FT_Palette_Select instead of setting FT_LOAD_COLOR for rendering * so that the client application can handle blending by itself. * @@ -4264,6 +4264,101 @@ FT_BEGIN_HEADER FT_Glyph_Layer *alayers ); + /********************************************************************** + * + * @struct: + * FT_LayerIterator + * + * @description: + * This iterator object is needed for @FT_Get_Color_Glyph_Layer. + * + * @fields: + * num_layers :: + * The number of glyph layers for the requested glyph index. Will be + * set by @FT_Get_Color_Glyph_Layer. + * + * layer :: + * The current layer. Will be set by @FT_Get_Color_Glyph_Layer. + * + * p :: + * An opaque pointer into `COLR' table data. The caller must set this + * to NULL before the first call of @FT_Get_Color_Glyph_Layer. + */ + typedef struct FT_LayerIterator_ + { + FT_UInt num_layers; + FT_UInt layer; + FT_Byte* p; + + } FT_LayerIterator; + + + /************************************************************************* + * + * @func: + * FT_Get_Color_Glyph_Layer + * + * @description: + * This is an interface to the `COLR' table in OpenType fonts to + * iteratively retrieve the colored glyph layers associated with the + * current glyph slot. + * + * https://docs.microsoft.com/en-us/typography/opentype/spec/colr + * + * The glyph layer data for a given glyph index, if present, provides an + * alternative, multi-colour glyph representation: Instead of rendering + * the outline or bitmap with the given glyph index, glyphs with the + * indices and colors returned by this function are rendered layer by + * layer. + * + * The returned elements are ordered in the z~direction from bottom to + * top; the `n'th element should be rendered with the associated palette + * color and blended on top of the already rendered layers (elements 0, + * 1, ..., n-1). + * + * @input: + * face :: + * A handle to the parent face object. + * + * base_glyph :: + * The glyph index the colored glyph layers are associated with. + * + * @inout: + * iterator :: + * An @FT_LayerIterator object. For the first call you should set + * `iterator->p' to NULL. For all following calls, simply use the + * same object again. + * + * @output: + * acolor_index :: + * The color index into the font face's color palette of the current + * layer. The value 0xFFFF is special; it doesn't reference a palette + * entry but indicates that the text foreground color should be used + * instead (to be set up by the application outside of FreeType). + * + * The color palette can be retrieved with @FT_Palette_Select. + * + * @return: + * The glyph index of the current layer. If there are no more layers + * (or if there are no layers at all), value~0 gets returned. In case + * of an error, value~0 is returned also. + * + * @note: + * This function is necessary if you want to handle glyph layers by + * yourself. In particular, functions that operate with @FT_GlyphRec + * objects (like @FT_Get_Glyph or @FT_Glyph_To_Bitmap) don't have access + * to this information. + * + * @FT_Render_Glyph, however, handles colored glyph layers + * automatically if the @FT_LOAD_COLOR flag is passed to it. + */ + FT_EXPORT( FT_UInt ) + FT_Get_Color_Glyph_Layer( FT_Face face, + FT_UInt base_glyph, + FT_UInt *acolor_index, + FT_LayerIterator* iterator ); + + /************************************************************************** * * @Enum: diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h index 731c7fe86..2093c28e7 100644 --- a/include/freetype/internal/sfnt.h +++ b/include/freetype/internal/sfnt.h @@ -526,6 +526,46 @@ FT_BEGIN_HEADER FT_UShort* num_layers ); + /************************************************************************** + * + * @FuncType: + * TT_Get_Colr_Layer_Func + * + * @Description: + * Iteratively get the color layer data of a given glyph index. + * + * @Input: + * face :: + * The target face object. + * + * base_glyph :: + * The glyph index the colored glyph layers are associated with. + * + * @inout: + * iterator :: + * An @FT_LayerIterator object. For the first call you should set + * `iterator->p' to NULL. For all following calls, simply use the + * same object again. + * + * @output: + * acolor_index :: + * The color index into the font face's color palette of the current + * layer. The value 0xFFFF is special; it doesn't reference a palette + * entry but indicates that the text foreground color should be used + * instead (to be set up by the application outside of FreeType). + * + * @return: + * The glyph index of the current layer. If there are no more layers + * (or if there are no layers at all), value~0 gets returned. In case + * of an error, value~0 is returned also. + */ + typedef FT_UInt + (*TT_Get_Colr_Layer_Func)( TT_Face face, + FT_UInt base_glyph, + FT_UInt *acolor_index, + FT_LayerIterator* iterator ); + + /************************************************************************** * * @FuncType: @@ -769,6 +809,7 @@ FT_BEGIN_HEADER TT_Free_Table_Func free_colr; TT_Set_Palette_Func set_palette; TT_Load_Colr_Layer_Func load_colr_layer; + TT_Get_Colr_Layer_Func get_colr_layer; TT_Blend_Colr_Func colr_blend; TT_Get_Metrics_Func get_metrics; @@ -819,6 +860,7 @@ FT_BEGIN_HEADER free_colr_, \ set_palette_, \ load_colr_layer_, \ + get_colr_layer_, \ colr_blend_, \ get_metrics_, \ get_name_, \ @@ -859,6 +901,7 @@ FT_BEGIN_HEADER free_colr_, \ set_palette_, \ load_colr_layer_, \ + get_colr_layer_, \ colr_blend_, \ get_metrics_, \ get_name_, \ diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index bd3c039b0..29a1c114c 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -5490,4 +5490,35 @@ } + /* documentation is in freetype.h */ + + FT_EXPORT_DEF( FT_UInt ) + FT_Get_Color_Glyph_Layer( FT_Face face, + FT_UInt base_glyph, + FT_UInt *acolor_index, + FT_LayerIterator* iterator ) + { + TT_Face ttface; + SFNT_Service sfnt; + + + if ( !face || + !acolor_index || + !iterator || + base_glyph >= (FT_UInt)face->num_glyphs ) + return 0; + + if ( !FT_IS_SFNT( face ) ) + return 0; + + ttface = (TT_Face)face; + sfnt = (SFNT_Service)ttface->sfnt; + + return sfnt->get_colr_layer( ttface, + base_glyph, + acolor_index, + iterator ); + } + + /* END */ diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index 0c3ddc89f..e1f481802 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -1270,6 +1270,8 @@ /* TT_Set_Palette_Func set_palette */ PUT_COLOR_LAYERS( tt_face_load_colr_layers ), /* TT_Load_Colr_Layer_Func load_colr_layer */ + PUT_COLOR_LAYERS( tt_face_get_colr_layer ), + /* TT_Get_Colr_Layer_Func get_colr_layer */ PUT_COLOR_LAYERS( tt_face_colr_blend_layer ), /* TT_Blend_Colr_Func colr_blend */ diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c index 66592b626..323f0ca51 100644 --- a/src/sfnt/ttcolr.c +++ b/src/sfnt/ttcolr.c @@ -275,6 +275,54 @@ } + FT_LOCAL_DEF( FT_UInt ) + tt_face_get_colr_layer( TT_Face face, + FT_UInt base_glyph, + FT_UInt *acolor_index, + FT_LayerIterator* iterator ) + { + Colr* colr = (Colr*)face->colr; + BaseGlyphRecord glyph_record; + FT_UInt glyph_index; + + + if ( !iterator->p ) + { + /* first call to function */ + iterator->layer = 0; + + if ( !find_base_glyph_record( colr->base_glyphs, + colr->num_base_glyphs, + base_glyph, + &glyph_record ) ) + return 0; + + iterator->p = colr->layers + + LAYER_SIZE * glyph_record.first_layer_index; + + if ( glyph_record.num_layers ) + iterator->num_layers = glyph_record.num_layers; + else + return 0; + } + + if ( iterator->layer >= iterator->num_layers ) + return 0; + + glyph_index = FT_NEXT_USHORT( iterator->p ); + *acolor_index = FT_NEXT_USHORT( iterator->p ); + + if ( glyph_index >= FT_FACE( face )->num_glyphs || + ( *acolor_index != 0xFFFF && + *acolor_index >= face->palette_data.num_palette_entries ) ) + return 0; + + iterator->layer++; + + return glyph_index; + } + + FT_LOCAL_DEF( FT_Error ) tt_face_colr_blend_layer( TT_Face face, FT_UInt color_index, diff --git a/src/sfnt/ttcolr.h b/src/sfnt/ttcolr.h index a5487556c..480fd6770 100644 --- a/src/sfnt/ttcolr.h +++ b/src/sfnt/ttcolr.h @@ -42,6 +42,12 @@ FT_BEGIN_HEADER FT_Glyph_Layer *ret_layers, FT_UShort* ret_num_layers ); + FT_LOCAL( FT_UInt ) + tt_face_get_colr_layer( TT_Face face, + FT_UInt base_glyph, + FT_UInt *acolor_index, + FT_LayerIterator* iterator ); + FT_LOCAL( FT_Error ) tt_face_colr_blend_layer( TT_Face face, FT_UInt color_index,