ref: c412de52fb909dcdf6e60c574d1f991a4f43cb3b
parent: 8f1ed54877ffab4fc2cf2be329446c748a885842
author: Werner Lemberg <[email protected]>
date: Sat Jun 9 19:56:21 EDT 2018
[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.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2018-06-09 Werner Lemberg <[email protected]>
+
+ [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 <[email protected]>
[base] API for Harmony LCD rendering.
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -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,7 +1658,10 @@
/* postscript names table */
TT_Post_NamesRec postscript_names;
+ /* glyph colors */
+ FT_Palette palette; /* since 2.10 */
+
/************************************************************************
*
* TrueType-specific fields (ignored by the CFF driver)
@@ -1728,7 +1732,6 @@
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;
@@ -1755,6 +1758,9 @@
FT_ULong ebdt_start; /* either `CBDT', `EBDT', or `bdat' */
FT_ULong ebdt_size;
#endif
+
+ /* since 2.10 */
+ void* colr_and_cpal;
} TT_FaceRec;
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -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;
}
--- a/src/sfnt/ttcolr.c
+++ b/src/sfnt/ttcolr.c
@@ -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,11 +69,10 @@
} 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 */
@@ -79,11 +79,6 @@
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,29 +187,100 @@
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.color_indices = p;
- cpal.colors = (FT_Byte*)cpal_table + colors_begin;
+ cpal.num_colors = FT_NEXT_USHORT( p );
+ colors_offset = FT_NEXT_ULONG( p );
- if ( cpal.version != 0 && cpal.version != 1 )
+ if ( colors_offset >= table_size )
goto InvalidTable;
+ if ( cpal.num_colors * COLOR_SIZE > table_size - colors_offset )
+ goto InvalidTable;
- colors_end = colors_begin + cpal.num_colors * COLOR_SIZE;
+ cpal.color_indices = p;
+ cpal.colors = (FT_Byte*)cpal_table + colors_offset;
- /* 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;
+ if ( cpal.version == 1 )
+ {
+ FT_ULong type_offset, label_offset, entry_label_offset;
+ FT_UShort* array;
+ FT_UShort* limit;
+ FT_UShort* q;
- if ( cpal.colors < cpal_table )
- goto InvalidTable;
+ p += face->palette.num_palettes * 2;
+
+ 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,11 +297,11 @@
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 );