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.
This commit is contained in:
Werner Lemberg 2018-06-14 21:02:49 +02:00
parent 33ac83e376
commit f9d05eb326
7 changed files with 246 additions and 1 deletions

View File

@ -1,3 +1,23 @@
2018-06-14 Werner Lemberg <wl@gnu.org>
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 <wl@gnu.org>
Add glyph index and glyph load flags to glyph slot.

View File

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

View File

@ -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_, \

View File

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

View File

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

View File

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

View File

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