[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.
This commit is contained in:
Werner Lemberg 2018-06-13 08:46:27 +02:00
parent c07ca2a1b3
commit 54b332aaf9
8 changed files with 209 additions and 127 deletions

View File

@ -1,3 +1,33 @@
2018-06-13 Werner Lemberg <wl@gnu.org>
[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 <wl@gnu.org>
[sfnt] Fix `sizeof' thinko.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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