From 54b332aaf95cf581fc3a967bdf3724a69eba75f8 Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Wed, 13 Jun 2018 08:46:27 +0200 Subject: [PATCH] [sfnt] Separate `CPAL' and `COLR' table handling. Later on we want to support the `SVG' table also, which needs `CPAL' (but not `COLR'). * include/freetype/internal/sfnt.h (SFNT_Interface): Add `load_cpal' and `free_cpal' fields. (FT_DEFINE_SFNT_INTERFACE): Updated. * include/freetype/internal/tttypes.h (TT_FaceRec): Replace `colr_and_cpal' fields with `cpal' and `colr'. * src/sfnt/sfdriver.c (sfnt_interface): Updated. * src/sfnt/sfobjs.c (sfnt_load_face, sfnt_done_face): Updated. * src/sfnt/ttcolr.c (Colr, Cpal): Add `table' field. (ColrCpal): Removed. (tt_face_load_colr): Split off CPAL handling into... (tt_face_load_cpal): ... this new function. (tt_face_free_colr): Split off CPAL handling into... (tt_face_free_cpal): ... this new function. (tt_face_load_colr_layers, tt_face_palette_set): Updated. * src/sfnt/ttcolr.h: Updated. * src/truetype/ttgload.c (TT_Load_Glyph): Updated. --- ChangeLog | 30 ++++ include/freetype/internal/sfnt.h | 6 + include/freetype/internal/tttypes.h | 14 +- src/sfnt/sfdriver.c | 4 + src/sfnt/sfobjs.c | 12 +- src/sfnt/ttcolr.c | 259 +++++++++++++++------------- src/sfnt/ttcolr.h | 7 + src/truetype/ttgload.c | 4 +- 8 files changed, 209 insertions(+), 127 deletions(-) diff --git a/ChangeLog b/ChangeLog index a873cfdc3..eb751ab83 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2018-06-13 Werner Lemberg + + [sfnt] Separate `CPAL' and `COLR' table handling. + + Later on we want to support the `SVG' table also, which needs `CPAL' + (but not `COLR'). + + * include/freetype/internal/sfnt.h (SFNT_Interface): Add `load_cpal' + and `free_cpal' fields. + (FT_DEFINE_SFNT_INTERFACE): Updated. + + * include/freetype/internal/tttypes.h (TT_FaceRec): Replace + `colr_and_cpal' fields with `cpal' and `colr'. + + * src/sfnt/sfdriver.c (sfnt_interface): Updated. + + * src/sfnt/sfobjs.c (sfnt_load_face, sfnt_done_face): Updated. + + * src/sfnt/ttcolr.c (Colr, Cpal): Add `table' field. + (ColrCpal): Removed. + (tt_face_load_colr): Split off CPAL handling into... + (tt_face_load_cpal): ... this new function. + (tt_face_free_colr): Split off CPAL handling into... + (tt_face_free_cpal): ... this new function. + (tt_face_load_colr_layers, tt_face_palette_set): Updated. + + * src/sfnt/ttcolr.h: Updated. + + * src/truetype/ttgload.c (TT_Load_Glyph): Updated. + 2018-06-12 Werner Lemberg [sfnt] Fix `sizeof' thinko. diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h index aac8e9b7f..731c7fe86 100644 --- a/include/freetype/internal/sfnt.h +++ b/include/freetype/internal/sfnt.h @@ -763,7 +763,9 @@ FT_BEGIN_HEADER TT_Set_SBit_Strike_Func set_sbit_strike; TT_Load_Strike_Metrics_Func load_strike_metrics; + TT_Load_Table_Func load_cpal; TT_Load_Table_Func load_colr; + TT_Free_Table_Func free_cpal; TT_Free_Table_Func free_colr; TT_Set_Palette_Func set_palette; TT_Load_Colr_Layer_Func load_colr_layer; @@ -811,7 +813,9 @@ FT_BEGIN_HEADER free_eblc_, \ set_sbit_strike_, \ load_strike_metrics_, \ + load_cpal_, \ load_colr_, \ + free_cpal_, \ free_colr_, \ set_palette_, \ load_colr_layer_, \ @@ -849,7 +853,9 @@ FT_BEGIN_HEADER free_eblc_, \ set_sbit_strike_, \ load_strike_metrics_, \ + load_cpal_, \ load_colr_, \ + free_cpal_, \ free_colr_, \ set_palette_, \ load_colr_layer_, \ diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h index 4d6314800..945b250c8 100644 --- a/include/freetype/internal/tttypes.h +++ b/include/freetype/internal/tttypes.h @@ -1546,10 +1546,13 @@ FT_BEGIN_HEADER * exposed by the API and the indices used in * the font's sbit table. * - * colr_and_cpal :: - * A pointer to data related to `COLR' and - * `CPAL' tables. NULL if tables are not - * available. + * cpal :: + * A pointer to data related to the `CPAL' table. NULL if the table + * is not available. + * + * colr :: + * A pointer to data related to the `COLR' table. NULL if the table + * is not available. * * kern_table :: * A pointer to the `kern' table. @@ -1780,7 +1783,8 @@ FT_BEGIN_HEADER #endif /* since 2.10 */ - void* colr_and_cpal; + void* cpal; + void* colr; } TT_FaceRec; diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c index dd3f80101..ff1305e5a 100644 --- a/src/sfnt/sfdriver.c +++ b/src/sfnt/sfdriver.c @@ -1257,8 +1257,12 @@ PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ), /* TT_Load_Strike_Metrics_Func load_strike_metrics */ + PUT_COLOR_LAYERS( tt_face_load_cpal ), + /* TT_Load_Table_Func load_cpal */ PUT_COLOR_LAYERS( tt_face_load_colr ), /* TT_Load_Table_Func load_colr */ + PUT_COLOR_LAYERS( tt_face_free_cpal ), + /* TT_Free_Table_Func free_cpal */ PUT_COLOR_LAYERS( tt_face_free_colr ), /* TT_Free_Table_Func free_colr */ PUT_COLOR_LAYERS( tt_face_palette_set ), diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c index 6a431ed2b..5dc41b4a3 100644 --- a/src/sfnt/sfobjs.c +++ b/src/sfnt/sfobjs.c @@ -1341,9 +1341,10 @@ if ( sfnt->load_eblc ) LOAD_( eblc ); - if ( sfnt->load_colr ) + /* colored glyph support */ + if ( sfnt->load_cpal ) { - /* Ignore error. Missing optional colr/cpal is okay. */ + LOAD_( cpal ); LOAD_( colr ); } @@ -1401,7 +1402,7 @@ */ if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX || - face->colr_and_cpal ) + face->colr ) flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ if ( has_outline == TRUE ) @@ -1746,8 +1747,11 @@ sfnt->free_eblc( face ); /* destroy color table data if it is loaded */ - if ( sfnt->free_colr ) + if ( sfnt->free_cpal ) + { + sfnt->free_cpal( face ); sfnt->free_colr( face ); + } } #ifdef TT_CONFIG_OPTION_BDF diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c index fee484089..a087ee2a9 100644 --- a/src/sfnt/ttcolr.c +++ b/src/sfnt/ttcolr.c @@ -57,18 +57,6 @@ } BaseGlyphRecord; - typedef struct Colr_ - { - FT_UShort version; - FT_UShort num_base_glyphs; - FT_UShort num_layers; - - FT_Byte* base_glyphs; - FT_Byte* layers; - - } Colr; - - /* all data from `CPAL' not covered in FT_Palette_Data */ typedef struct Cpal_ { @@ -79,20 +67,25 @@ FT_Byte* color_indices; /* Index of each palette's first color record */ /* in the combined color record array. */ + /* The memory which backs up the `CPAL' table. */ + void* table; + } Cpal; - typedef struct ColrCpal_ + typedef struct Colr_ { - /* Accessors into the colr/cpal tables. */ - Colr colr; - Cpal cpal; + FT_UShort version; + FT_UShort num_base_glyphs; + FT_UShort num_layers; - /* The memory which backs up colr/cpal tables. */ - void* colr_table; - void* cpal_table; + FT_Byte* base_glyphs; + FT_Byte* layers; - } ColrCpal; + /* The memory which backs up the `COLR' table. */ + void* table; + + } Colr; /************************************************************************** @@ -106,101 +99,55 @@ FT_LOCAL_DEF( FT_Error ) - tt_face_load_colr( TT_Face face, + tt_face_load_cpal( TT_Face face, FT_Stream stream ) { FT_Error error; FT_Memory memory = face->root.memory; - FT_Byte* colr_table = NULL; - FT_Byte* cpal_table = NULL; - FT_Byte* p = NULL; + FT_Byte* table = NULL; + FT_Byte* p = NULL; - Colr colr; - Cpal cpal; - ColrCpal* cc = NULL; + Cpal* cpal = NULL; - FT_ULong base_glyph_offset, layer_offset, colors_offset; + FT_ULong colors_offset; FT_ULong table_size; - /* - * COLR - */ - - error = face->goto_table( face, TTAG_COLR, stream, &table_size ); - if ( error ) - goto NoColor; - - if ( table_size < COLR_HEADER_SIZE ) - goto InvalidTable; - - if ( FT_FRAME_EXTRACT( table_size, colr_table ) ) - goto NoColor; - - p = colr_table; - - FT_ZERO( &colr ); - colr.version = FT_NEXT_USHORT( p ); - if ( colr.version != 0 ) - goto InvalidTable; - - colr.num_base_glyphs = FT_NEXT_USHORT( p ); - base_glyph_offset = FT_NEXT_ULONG( p ); - - if ( base_glyph_offset >= table_size ) - goto InvalidTable; - if ( colr.num_base_glyphs * BASE_GLYPH_SIZE > - table_size - base_glyph_offset ) - goto InvalidTable; - - layer_offset = FT_NEXT_ULONG( p ); - colr.num_layers = FT_NEXT_USHORT( p ); - - if ( layer_offset >= table_size ) - goto InvalidTable; - if ( colr.num_layers * LAYER_SIZE > table_size - layer_offset ) - goto InvalidTable; - - colr.base_glyphs = (FT_Byte*)( colr_table + base_glyph_offset ); - colr.layers = (FT_Byte*)( colr_table + layer_offset ); - - /* - * CPAL - */ - error = face->goto_table( face, TTAG_CPAL, stream, &table_size ); if ( error ) - goto NoColor; + goto NoCpal; if ( table_size < CPAL_V0_HEADER_BASE_SIZE ) goto InvalidTable; - if ( FT_FRAME_EXTRACT( table_size, cpal_table ) ) - goto NoColor; + if ( FT_FRAME_EXTRACT( table_size, table ) ) + goto NoCpal; - p = cpal_table; + p = table; - FT_ZERO( &cpal ); - cpal.version = FT_NEXT_USHORT( p ); - if ( cpal.version > 1 ) + if ( FT_NEW( cpal ) ) + goto NoCpal; + + cpal->version = FT_NEXT_USHORT( p ); + if ( cpal->version > 1 ) goto InvalidTable; face->palette_data.num_palette_entries = FT_NEXT_USHORT( p ); face->palette_data.num_palettes = FT_NEXT_USHORT( p ); - cpal.num_colors = FT_NEXT_USHORT( p ); - colors_offset = FT_NEXT_ULONG( p ); + cpal->num_colors = FT_NEXT_USHORT( p ); + colors_offset = FT_NEXT_ULONG( p ); if ( colors_offset >= table_size ) goto InvalidTable; - if ( cpal.num_colors * COLOR_SIZE > table_size - colors_offset ) + if ( cpal->num_colors * COLOR_SIZE > table_size - colors_offset ) goto InvalidTable; - cpal.color_indices = p; - cpal.colors = (FT_Byte*)( cpal_table + colors_offset ); + cpal->color_indices = p; + cpal->colors = (FT_Byte*)( table + colors_offset ); - if ( cpal.version == 1 ) + if ( cpal->version == 1 ) { FT_ULong type_offset, label_offset, entry_label_offset; FT_UShort* array = NULL; @@ -223,9 +170,9 @@ goto InvalidTable; if ( FT_QNEW_ARRAY( array, face->palette_data.num_palettes ) ) - goto NoColor; + goto NoCpal; - p = cpal_table + type_offset; + p = table + type_offset; q = array; limit = q + face->palette_data.num_palettes; @@ -244,9 +191,9 @@ goto InvalidTable; if ( FT_QNEW_ARRAY( array, face->palette_data.num_palettes ) ) - goto NoColor; + goto NoCpal; - p = cpal_table + label_offset; + p = table + label_offset; q = array; limit = q + face->palette_data.num_palettes; @@ -265,9 +212,9 @@ goto InvalidTable; if ( FT_QNEW_ARRAY( array, face->palette_data.num_palette_entries ) ) - goto NoColor; + goto NoCpal; - p = cpal_table + entry_label_offset; + p = table + entry_label_offset; q = array; limit = q + face->palette_data.num_palette_entries; @@ -278,20 +225,14 @@ } } - if ( FT_NEW( cc ) ) - goto NoColor; + cpal->table = table; - cc->colr = colr; - cc->cpal = cpal; - cc->colr_table = colr_table; - cc->cpal_table = cpal_table; - - face->colr_and_cpal = cc; + face->cpal = cpal; /* set up default palette */ if ( FT_NEW_ARRAY( face->palette, face->palette_data.num_palette_entries ) ) - goto NoColor; + goto NoCpal; tt_face_palette_set( face, 0 ); @@ -300,11 +241,9 @@ InvalidTable: error = FT_THROW( Invalid_Table ); - NoColor: - FT_FRAME_RELEASE( colr_table ); - FT_FRAME_RELEASE( cpal_table ); - - FT_FREE( cc ); + NoCpal: + FT_FRAME_RELEASE( table ); + FT_FREE( cpal ); /* arrays in `face->palette_data' and `face->palette' */ /* are freed in `sfnt_done_face' */ @@ -313,21 +252,111 @@ } + FT_LOCAL_DEF( FT_Error ) + tt_face_load_colr( TT_Face face, + FT_Stream stream ) + { + FT_Error error; + FT_Memory memory = face->root.memory; + + FT_Byte* table = NULL; + FT_Byte* p = NULL; + + Colr* colr = NULL; + + FT_ULong base_glyph_offset, layer_offset; + FT_ULong table_size; + + + /* `COLR' always needs `CPAL' */ + if ( !face->cpal ) + return FT_THROW( Invalid_File_Format ); + + error = face->goto_table( face, TTAG_COLR, stream, &table_size ); + if ( error ) + goto NoColr; + + if ( table_size < COLR_HEADER_SIZE ) + goto InvalidTable; + + if ( FT_FRAME_EXTRACT( table_size, table ) ) + goto NoColr; + + p = table; + + if ( FT_NEW( colr ) ) + goto NoColr; + + colr->version = FT_NEXT_USHORT( p ); + if ( colr->version != 0 ) + goto InvalidTable; + + colr->num_base_glyphs = FT_NEXT_USHORT( p ); + base_glyph_offset = FT_NEXT_ULONG( p ); + + if ( base_glyph_offset >= table_size ) + goto InvalidTable; + if ( colr->num_base_glyphs * BASE_GLYPH_SIZE > + table_size - base_glyph_offset ) + goto InvalidTable; + + layer_offset = FT_NEXT_ULONG( p ); + colr->num_layers = FT_NEXT_USHORT( p ); + + if ( layer_offset >= table_size ) + goto InvalidTable; + if ( colr->num_layers * LAYER_SIZE > table_size - layer_offset ) + goto InvalidTable; + + colr->base_glyphs = (FT_Byte*)( table + base_glyph_offset ); + colr->layers = (FT_Byte*)( table + layer_offset ); + colr->table = table; + + face->colr = colr; + + return FT_Err_Ok; + + InvalidTable: + error = FT_THROW( Invalid_Table ); + + NoColr: + FT_FRAME_RELEASE( table ); + FT_FREE( colr ); + + return error; + } + + + FT_LOCAL_DEF( void ) + tt_face_free_cpal( TT_Face face ) + { + FT_Stream stream = face->root.stream; + FT_Memory memory = face->root.memory; + + Cpal* cpal = (Cpal*)face->cpal; + + + if ( cpal ) + { + FT_FRAME_RELEASE( cpal->table ); + FT_FREE( cpal ); + } + } + + FT_LOCAL_DEF( void ) tt_face_free_colr( TT_Face face ) { FT_Stream stream = face->root.stream; FT_Memory memory = face->root.memory; - ColrCpal* colr_and_cpal = (ColrCpal*)face->colr_and_cpal; + Colr* colr = (Colr*)face->colr; - if ( colr_and_cpal ) + if ( colr ) { - FT_FRAME_RELEASE( colr_and_cpal->colr_table ); - FT_FRAME_RELEASE( colr_and_cpal->cpal_table ); - - FT_FREE( face->colr_and_cpal ); + FT_FRAME_RELEASE( colr->table ); + FT_FREE( colr ); } } @@ -377,8 +406,7 @@ FT_Error error; FT_Memory memory = face->root.memory; - ColrCpal* colr_and_cpal = (ColrCpal *)face->colr_and_cpal; - Colr* colr = &colr_and_cpal->colr; + Colr* colr = (Colr*)face->colr; BaseGlyphRecord glyph_record; FT_Glyph_Layer layers = NULL; @@ -441,8 +469,7 @@ tt_face_palette_set( TT_Face face, FT_UInt palette_index ) { - ColrCpal* colr_and_cpal = (ColrCpal *)face->colr_and_cpal; - Cpal* cpal = &colr_and_cpal->cpal; + Cpal* cpal = (Cpal*)face->cpal; FT_Byte* offset; FT_Byte* p; diff --git a/src/sfnt/ttcolr.h b/src/sfnt/ttcolr.h index bb9b40738..258f0f66e 100644 --- a/src/sfnt/ttcolr.h +++ b/src/sfnt/ttcolr.h @@ -29,10 +29,17 @@ FT_BEGIN_HEADER + FT_LOCAL( FT_Error ) + tt_face_load_cpal( TT_Face face, + FT_Stream stream ); + FT_LOCAL( FT_Error ) tt_face_load_colr( TT_Face face, FT_Stream stream ); + FT_LOCAL( void ) + tt_face_free_cpal( TT_Face face ); + FT_LOCAL( void ) tt_face_free_colr( TT_Face face ); diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c index 574cdf66d..c5e96e687 100644 --- a/src/truetype/ttgload.c +++ b/src/truetype/ttgload.c @@ -2906,8 +2906,8 @@ /* The outline based algorithm took care of metrics. */ /* Read additional color info if requested. */ - if ( ( load_flags & FT_LOAD_COLOR ) && - ( (TT_Face)glyph->face )->colr_and_cpal ) + if ( ( load_flags & FT_LOAD_COLOR ) && + ( (TT_Face)glyph->face )->colr ) { TT_Face face = (TT_Face)glyph->face; FT_Memory memory = face->root.memory;