From 31b14fd4dce4b017090f5ba7c15a178fa0ce6d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20R=C3=B6ttsches?= Date: Wed, 29 Jun 2022 16:01:13 +0300 Subject: [PATCH] [sfnt] Load variation store for 'COLR' v1. * src/sfnt/ttcolr.c: Include `ttobjs.h` temporarily. (VARIABLE_COLRV1_ENABLED): New temporary macro to detect whether variable COLRv1 is enabled. (Colr): New fields `var_store` and `delta_set_idx_map`. (tt_face_load_colr, tt_face_free_colr) [VARIABLE_COLRV1_ENABLED]: Load and free variation store data using the functions from the Multiple Masters service. --- src/sfnt/ttcolr.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c index e02dd060e..c7232e1fc 100644 --- a/src/sfnt/ttcolr.c +++ b/src/sfnt/ttcolr.c @@ -30,10 +30,15 @@ #include #include #include +#include #include #include #include + /* the next code line is a temporary hack, to be removed together with */ + /* `VARIABLE_COLRV1_ENABLED` and related code */ +#include "../truetype/ttobjs.h" + #ifdef TT_CONFIG_OPTION_COLOR_LAYERS @@ -50,6 +55,10 @@ #define COLR_HEADER_SIZE 14U +#define VARIABLE_COLRV1_ENABLED \ + ( ((TT_Driver)FT_FACE_DRIVER( face ))->enable_variable_colrv1 ) + + typedef enum FT_PaintFormat_Internal_ { FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER = 18, @@ -104,6 +113,10 @@ */ FT_Byte* paints_start_v1; + /* Item Variation Store for variable 'COLR' v1. */ + GX_ItemVarStoreRec var_store; + GX_DeltaSetIdxMapRec delta_set_idx_map; + /* The memory that backs up the `COLR' table. */ void* table; FT_ULong table_size; @@ -138,7 +151,9 @@ FT_ULong base_glyph_offset, layer_offset; FT_ULong base_glyphs_offset_v1, num_base_glyphs_v1; FT_ULong layer_offset_v1, num_layers_v1, clip_list_offset; + FT_ULong var_idx_map_offset, var_store_offset; FT_ULong table_size; + FT_ULong colr_offset_in_stream; /* `COLR' always needs `CPAL' */ @@ -149,6 +164,8 @@ if ( error ) goto NoColr; + colr_offset_in_stream = FT_STREAM_POS(); + if ( table_size < COLR_HEADER_SIZE ) goto InvalidTable; @@ -239,6 +256,64 @@ colr->clip_list = (FT_Byte*)( table + clip_list_offset ); else colr->clip_list = 0; + + colr->var_store.dataCount = 0; + colr->var_store.varData = NULL; + colr->var_store.axisCount = 0; + colr->var_store.regionCount = 0; + colr->var_store.varRegionList = 0; + + colr->delta_set_idx_map.mapCount = 0; + colr->delta_set_idx_map.outerIndex = NULL; + colr->delta_set_idx_map.innerIndex = NULL; + +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR && + VARIABLE_COLRV1_ENABLED ) + { + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + var_idx_map_offset = FT_NEXT_ULONG( p ); + + if ( var_idx_map_offset >= table_size ) + goto InvalidTable; + + var_store_offset = FT_NEXT_ULONG( p ); + if ( var_store_offset >= table_size ) + goto InvalidTable; + + if ( var_store_offset ) + { + /* If variation info has not been initialized yet, try doing so, */ + /* otherwise loading the variation store will fail as it */ + /* requires access to `blend` for checking the number of axes. */ + if ( !face->blend ) + if ( mm->get_mm_var( FT_FACE( face ), NULL ) ) + goto InvalidTable; + + /* Try loading `VarIdxMap` and `VarStore`. */ + error = mm->load_item_var_store( + FT_FACE( face ), + colr_offset_in_stream + var_store_offset, + &colr->var_store ); + if ( error != FT_Err_Ok ) + goto InvalidTable; + } + + if ( colr->var_store.axisCount && var_idx_map_offset ) + { + error = mm->load_delta_set_idx_map( + FT_FACE( face ), + colr_offset_in_stream + var_idx_map_offset, + &colr->delta_set_idx_map, + &colr->var_store, + table_size ); + if ( error != FT_Err_Ok ) + goto InvalidTable; + } + } +#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ } colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset ); @@ -251,6 +326,19 @@ return FT_Err_Ok; InvalidTable: +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( VARIABLE_COLRV1_ENABLED ) + { + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + mm->done_delta_set_idx_map( FT_FACE( face ), + &colr->delta_set_idx_map ); + mm->done_item_var_store( FT_FACE( face ), + &colr->var_store ); + } +#endif + error = FT_THROW( Invalid_Table ); NoColr: @@ -272,6 +360,18 @@ if ( colr ) { +#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT + if ( VARIABLE_COLRV1_ENABLED ) + { + FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; + + + mm->done_delta_set_idx_map( FT_FACE( face ), + &colr->delta_set_idx_map ); + mm->done_item_var_store( FT_FACE( face ), + &colr->var_store ); + } +#endif FT_FRAME_RELEASE( colr->table ); FT_FREE( colr ); }