[sfnt] Read `CPAL' version 1 tables.

* include/freetype/internal.tttypes.h: Include FT_COLOR_H.
(TT_FaceRec): Add `palette' field.

* src/sfnt/ttcolr.c: Include FT_COLOR_H.
(Cpal): Remove all data covered by the new `palette' field in
`TT_FaceRec'.
(tt_face_load_colr): Updated.
Read `CPAL' version 1 data.
(tt_face_load_colr_layers, tt_face_find_color): Updated.

* src/sfnt/sfobjs.c (sfnt_done_face): Free glyph color palette data.
This commit is contained in:
Werner Lemberg 2018-06-09 23:56:21 +02:00
parent 8f1ed54877
commit c412de52fb
4 changed files with 131 additions and 33 deletions

View File

@ -1,3 +1,19 @@
2018-06-09 Werner Lemberg <wl@gnu.org>
[sfnt] Read `CPAL' version 1 tables.
* include/freetype/internal.tttypes.h: Include FT_COLOR_H.
(TT_FaceRec): Add `palette' field.
* src/sfnt/ttcolr.c: Include FT_COLOR_H.
(Cpal): Remove all data covered by the new `palette' field in
`TT_FaceRec'.
(tt_face_load_colr): Updated.
Read `CPAL' version 1 data.
(tt_face_load_colr_layers, tt_face_find_color): Updated.
* src/sfnt/sfobjs.c (sfnt_done_face): Free glyph color palette data.
2018-06-07 Alexei Podtelezhnikov <apodtele@gmail.com>
[base] API for Harmony LCD rendering.

View File

@ -24,6 +24,7 @@
#include <ft2build.h>
#include FT_TRUETYPE_TABLES_H
#include FT_INTERNAL_OBJECTS_H
#include FT_COLOR_H
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
#include FT_MULTIPLE_MASTERS_H
@ -1657,6 +1658,9 @@ FT_BEGIN_HEADER
/* postscript names table */
TT_Post_NamesRec postscript_names;
/* glyph colors */
FT_Palette palette; /* since 2.10 */
/************************************************************************
*
@ -1728,7 +1732,6 @@ FT_BEGIN_HEADER
FT_UInt sbit_num_strikes;
FT_UInt* sbit_strike_map;
void* colr_and_cpal;
FT_Byte* kern_table;
FT_ULong kern_table_size;
FT_UInt num_kern_tables;
@ -1756,6 +1759,9 @@ FT_BEGIN_HEADER
FT_ULong ebdt_size;
#endif
/* since 2.10 */
void* colr_and_cpal;
} TT_FaceRec;

View File

@ -1808,6 +1808,11 @@
FT_FREE( face->var_postscript_prefix );
#endif
/* freeing glyph color palette data */
FT_FREE( face->palette.palette_name_ids );
FT_FREE( face->palette.palette_types );
FT_FREE( face->palette.palette_entry_name_ids );
face->sfnt = NULL;
}

View File

@ -32,6 +32,7 @@
#include FT_INTERNAL_DEBUG_H
#include FT_INTERNAL_STREAM_H
#include FT_TRUETYPE_TAGS_H
#include FT_COLOR_H
#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
@ -68,22 +69,16 @@
} Colr;
/* all data from `CPAL' not covered in FT_Palette */
typedef struct Cpal_
{
FT_UShort version; /* Table version number (0 or 1 supported). */
FT_UShort num_palettes_entries; /* # of entries in each palette. */
FT_UShort num_palettes; /* # of palettes in the table. */
FT_UShort num_colors; /* Total number of color records, */
/* combined for all palettes. */
FT_Byte* colors; /* RGBA array of colors */
FT_Byte* color_indices; /* Index of each palette's first color record */
/* in the combined color record array. */
/* version 1 fields */
FT_ULong* palette_types;
FT_UShort* palette_labels;
FT_UShort* palette_entry_labels;
} Cpal;
@ -126,11 +121,13 @@
ColrCpal* cc = NULL;
FT_ULong base_glyph_begin, base_glyph_end, layer_begin, layer_end;
FT_ULong colors_begin, colors_end;
FT_ULong colors_offset;
FT_ULong table_size;
face->colr_and_cpal = NULL;
/*
* COLR
*/
error = face->goto_table( face, TTAG_COLR, stream, &table_size );
if ( error )
@ -173,6 +170,10 @@
if ( colr.base_glyphs < colr_table || colr.layers < colr_table )
goto InvalidTable;
/*
* CPAL
*/
error = face->goto_table( face, TTAG_CPAL, stream, &table_size );
if ( error )
goto NoColor;
@ -186,28 +187,99 @@
p = cpal_table;
FT_ZERO( &cpal );
cpal.version = FT_NEXT_USHORT( p );
cpal.num_palettes_entries = FT_NEXT_USHORT( p );
cpal.num_palettes = FT_NEXT_USHORT( p );
cpal.num_colors = FT_NEXT_USHORT( p );
cpal.version = FT_NEXT_USHORT( p );
if ( cpal.version > 1 )
goto InvalidTable;
colors_begin = FT_NEXT_ULONG( p );
face->palette.num_palette_entries = FT_NEXT_USHORT( p );
face->palette.num_palettes = FT_NEXT_USHORT( 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 )
goto InvalidTable;
cpal.color_indices = p;
cpal.colors = (FT_Byte*)cpal_table + colors_begin;
cpal.colors = (FT_Byte*)cpal_table + colors_offset;
if ( cpal.version != 0 && cpal.version != 1 )
goto InvalidTable;
if ( cpal.version == 1 )
{
FT_ULong type_offset, label_offset, entry_label_offset;
FT_UShort* array;
FT_UShort* limit;
FT_UShort* q;
colors_end = colors_begin + cpal.num_colors * COLOR_SIZE;
/* Ensure variable length tables lies within the COLR table. */
/* We wrap around FT_ULong at most once since count is FT_UShort. */
if ( colors_end < colors_begin || colors_end > table_size )
goto InvalidTable;
p += face->palette.num_palettes * 2;
if ( cpal.colors < cpal_table )
goto InvalidTable;
type_offset = FT_NEXT_ULONG( p );
label_offset = FT_NEXT_ULONG( p );
entry_label_offset = FT_NEXT_ULONG( p );
if ( type_offset )
{
if ( type_offset >= table_size )
goto InvalidTable;
if ( face->palette.num_palettes * 2 > table_size - type_offset )
goto InvalidTable;
if ( FT_QNEW_ARRAY( array, face->palette.num_palettes ) )
goto NoColor;
p = cpal_table + type_offset;
q = array;
limit = q + face->palette.num_palettes * sizeof ( FT_UShort );
while ( q < limit )
*q++ = FT_NEXT_USHORT( p );
face->palette.palette_types = array;
}
if ( label_offset )
{
if ( label_offset >= table_size )
goto InvalidTable;
if ( face->palette.num_palettes * 2 > table_size - label_offset )
goto InvalidTable;
if ( FT_QNEW_ARRAY( array, face->palette.num_palettes ) )
goto NoColor;
p = cpal_table + label_offset;
q = array;
limit = q + face->palette.num_palettes * sizeof ( FT_UShort );
while ( q < limit )
*q++ = FT_NEXT_USHORT( p );
face->palette.palette_name_ids = array;
}
if ( entry_label_offset )
{
if ( entry_label_offset >= table_size )
goto InvalidTable;
if ( face->palette.num_palette_entries * 2 >
table_size - entry_label_offset )
goto InvalidTable;
if ( FT_QNEW_ARRAY( array, face->palette.num_palette_entries ) )
goto NoColor;
p = cpal_table + entry_label_offset;
q = array;
limit = q + face->palette.num_palette_entries * sizeof ( FT_UShort );
while ( q < limit )
*q++ = FT_NEXT_USHORT( p );
face->palette.palette_entry_name_ids = array;
}
}
if ( FT_NEW( cc ) )
goto NoColor;
@ -225,10 +297,10 @@
error = FT_THROW( Invalid_File_Format );
NoColor:
if ( colr_table )
FT_FRAME_RELEASE( colr_table );
if ( cpal_table )
FT_FRAME_RELEASE( cpal_table );
FT_FRAME_RELEASE( colr_table );
FT_FRAME_RELEASE( cpal_table );
/* arrays in `face->palette' are freed in `sfnt_face_done' */
return error;
}
@ -300,7 +372,6 @@
ColrCpal* colr_and_cpal = (ColrCpal *)face->colr_and_cpal;
Colr* colr = &colr_and_cpal->colr;
Cpal* cpal = &colr_and_cpal->cpal;
BaseGlyphRecord glyph_record;
FT_Glyph_Layer layers;
@ -335,8 +406,8 @@
FT_UShort palette_index = FT_NEXT_USHORT( layer_record_ptr );
if ( palette_index != 0xFFFF &&
palette_index >= cpal->num_palettes_entries )
if ( palette_index != 0xFFFF &&
palette_index >= face->palette.num_palette_entries )
{
error = FT_THROW( Invalid_File_Format );
goto Error;
@ -375,7 +446,7 @@
FT_Int color_offset;
if ( color_index >= cpal->num_palettes_entries )
if ( color_index >= face->palette.num_palette_entries )
return 0;
p = cpal->color_indices + palette_index * (int)sizeof ( FT_UShort );