[woff2] More formatting and documentation.

* include/freetype/internal/wofftypes.h, src/sfnt/sfwoff2.c: Implement
formatting changes suggested as

  https://lists.nongnu.org/archive/html/freetype-devel/2019-08/msg00052.html
This commit is contained in:
Nikhil Ramakrishnan 2019-08-21 20:21:02 +05:30
parent 25774f3da5
commit 933c185b7e
2 changed files with 103 additions and 68 deletions

View File

@ -120,12 +120,6 @@ FT_BEGIN_HEADER
* Number of tables in TTC, indicating number of elements in * Number of tables in TTC, indicating number of elements in
* `table_indices`. * `table_indices`.
* *
* dst_offset ::
* Uncompressed table offset.
*
* header_checksum ::
* Checksum for font header.
*
* table_indices :: * table_indices ::
* Array of table indices for each TTC font. * Array of table indices for each TTC font.
*/ */
@ -133,8 +127,6 @@ FT_BEGIN_HEADER
{ {
FT_ULong flavor; FT_ULong flavor;
FT_UShort num_tables; FT_UShort num_tables;
FT_ULong dst_offset;
FT_ULong header_checksum;
FT_UShort* table_indices; FT_UShort* table_indices;
} WOFF2_TtcFontRec, *WOFF2_TtcFont; } WOFF2_TtcFontRec, *WOFF2_TtcFont;
@ -157,7 +149,7 @@ FT_BEGIN_HEADER
* We don't care about the fields `reserved`, `majorVersion` and * We don't care about the fields `reserved`, `majorVersion` and
* `minorVersion`, so they are not included. The `totalSfntSize` field * `minorVersion`, so they are not included. The `totalSfntSize` field
* does not necessarily represent the actual size of the uncompressed * does not necessarily represent the actual size of the uncompressed
* SFNT font stream, so that is not included either. * SFNT font stream, so that is used as a reference value instead.
*/ */
typedef struct WOFF2_HeaderRec_ typedef struct WOFF2_HeaderRec_
{ {
@ -173,13 +165,13 @@ FT_BEGIN_HEADER
FT_ULong privOffset; FT_ULong privOffset;
FT_ULong privLength; FT_ULong privLength;
FT_ULong uncompressed_size; FT_ULong uncompressed_size; /* uncompressed brotli stream size */
FT_ULong compressed_offset; FT_ULong compressed_offset; /* compressed stream offset */
FT_ULong header_version; FT_ULong header_version; /* version of original TTC Header */
FT_UShort num_fonts; FT_UShort num_fonts; /* number of fonts in TTC */
FT_ULong actual_sfnt_size; FT_ULong actual_sfnt_size; /* actual size of sfnt stream */
WOFF2_TtcFont ttc_fonts; WOFF2_TtcFont ttc_fonts; /* metadata for fonts in a TTC */
} WOFF2_HeaderRec, *WOFF2_Header; } WOFF2_HeaderRec, *WOFF2_Header;
@ -194,14 +186,17 @@ FT_BEGIN_HEADER
* sfnt tables. * sfnt tables.
* *
* @fields: * @fields:
* header_checksum ::
* Checksum of SFNT offset table.
*
* num_glyphs :: * num_glyphs ::
* Number of glyphs in the font. * Number of glyphs in the font.
* *
* num_hmetrics :: * num_hmetrics ::
* `numberOfHMetrics' field in the `hhea' table. * `numberOfHMetrics` field in the 'hhea' table.
* *
* x_mins :: * x_mins ::
* `xMin' values of glyph bounding box. * `xMin` values of glyph bounding box.
*/ */
typedef struct WOFF2_InfoRec_ typedef struct WOFF2_InfoRec_
{ {
@ -236,7 +231,6 @@ FT_BEGIN_HEADER
FT_ULong flags; /* calculated flags */ FT_ULong flags; /* calculated flags */
FT_ULong src_offset; /* compressed table offset */ FT_ULong src_offset; /* compressed table offset */
FT_ULong src_length; /* compressed table length */ FT_ULong src_length; /* compressed table length */
FT_ULong dst_offset; /* uncompressed table offset */ FT_ULong dst_offset; /* uncompressed table offset */
} WOFF2_TableRec, *WOFF2_Table; } WOFF2_TableRec, *WOFF2_Table;
@ -249,7 +243,7 @@ FT_BEGIN_HEADER
* *
* @description: * @description:
* This structure stores information about a substream in the transformed * This structure stores information about a substream in the transformed
* `glyf' table in a WOFF2 stream. * 'glyf' table in a WOFF2 stream.
* *
* @fields: * @fields:
* start :: * start ::
@ -266,6 +260,7 @@ FT_BEGIN_HEADER
FT_ULong start; FT_ULong start;
FT_ULong offset; FT_ULong offset;
FT_ULong size; FT_ULong size;
} WOFF2_SubstreamRec, *WOFF2_Substream; } WOFF2_SubstreamRec, *WOFF2_Substream;
@ -276,7 +271,7 @@ FT_BEGIN_HEADER
* *
* @description: * @description:
* This structure stores information about a point in the transformed * This structure stores information about a point in the transformed
* `glyf' table in a WOFF2 stream. * 'glyf' table in a WOFF2 stream.
* *
* @fields: * @fields:
* x :: * x ::
@ -286,13 +281,14 @@ FT_BEGIN_HEADER
* y-coordinate. * y-coordinate.
* *
* on_curve :: * on_curve ::
* on-curve. * Whether point is on-curve.
*/ */
typedef struct WOFF2_PointRec_ typedef struct WOFF2_PointRec_
{ {
FT_Int x; FT_Int x;
FT_Int y; FT_Int y;
FT_Bool on_curve; FT_Bool on_curve;
} WOFF2_PointRec, *WOFF2_Point; } WOFF2_PointRec, *WOFF2_Point;

View File

@ -135,6 +135,7 @@
FT_Byte result_byte = 0; FT_Byte result_byte = 0;
FT_UShort result_short = 0; FT_UShort result_short = 0;
if ( FT_READ_BYTE( code ) ) if ( FT_READ_BYTE( code ) )
return error; return error;
if ( code == wordCode ) if ( code == wordCode )
@ -176,7 +177,9 @@
FT_Byte code; FT_Byte code;
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
for ( i = 0; i < 5; ++i ) {
for ( i = 0; i < 5; ++i )
{
code = 0; code = 0;
if ( FT_READ_BYTE( code ) ) if ( FT_READ_BYTE( code ) )
return error; return error;
@ -215,7 +218,8 @@
/* We are reallocating memory for `dst', so its pointer may change. */ /* We are reallocating memory for `dst', so its pointer may change. */
FT_Byte* dst = *dst_bytes; FT_Byte* dst = *dst_bytes;
/* Check if we are within limits. */
/* Check whether we are within limits. */
if ( ( *offset + size ) > WOFF2_DEFAULT_MAX_SIZE ) if ( ( *offset + size ) > WOFF2_DEFAULT_MAX_SIZE )
return FT_THROW( Array_Too_Large ); return FT_THROW( Array_Too_Large );
@ -256,6 +260,7 @@
FT_Byte zeroes[] = { 0, 0, 0 }; FT_Byte zeroes[] = { 0, 0, 0 };
FT_ULong pad_bytes; FT_ULong pad_bytes;
if ( dest_offset + 3 < dest_offset ) if ( dest_offset + 3 < dest_offset )
return FT_THROW( Invalid_Table ); return FT_THROW( Invalid_Table );
@ -281,6 +286,7 @@
FT_ULong i; FT_ULong i;
FT_ULong v; FT_ULong v;
for ( i = 0; i < aligned_size; i += 4 ) for ( i = 0; i < aligned_size; i += 4 )
{ {
checksum += ( buf[i] << 24 ) | ( buf[i+1] << 16 ) | checksum += ( buf[i] << 24 ) | ( buf[i+1] << 16 ) |
@ -310,15 +316,16 @@
FT_ULong uncompressed_size = dst_size; FT_ULong uncompressed_size = dst_size;
BrotliDecoderResult result; BrotliDecoderResult result;
result = BrotliDecoderDecompress( result = BrotliDecoderDecompress(
src_size, src, &uncompressed_size, dst); src_size, src, &uncompressed_size, dst);
if ( result != BROTLI_DECODER_RESULT_SUCCESS || if ( result != BROTLI_DECODER_RESULT_SUCCESS ||
uncompressed_size != dst_size ) uncompressed_size != dst_size )
{ {
FT_ERROR(( "woff2_decompress: Stream length mismatch.\n" )); FT_ERROR(( "woff2_decompress: Stream length mismatch.\n" ));
return FT_THROW( Invalid_Table ); return FT_THROW( Invalid_Table );
} }
FT_TRACE2(( "woff2_decompress: Brotli stream decompressed.\n" )); FT_TRACE2(( "woff2_decompress: Brotli stream decompressed.\n" ));
return FT_Err_Ok; return FT_Err_Ok;
@ -339,6 +346,7 @@
{ {
FT_Int i; FT_Int i;
for ( i = 0; i < num_tables; i++ ) for ( i = 0; i < num_tables; i++ )
{ {
if ( tables[i]->Tag == tag ) if ( tables[i]->Tag == tag )
@ -357,6 +365,7 @@
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_UShort num_metrics; FT_UShort num_metrics;
if ( FT_STREAM_SKIP( 34 ) ) if ( FT_STREAM_SKIP( 34 ) )
return FT_THROW( Invalid_Table ); return FT_THROW( Invalid_Table );
@ -411,6 +420,7 @@
FT_Int i; FT_Int i;
if ( n_points > in_size ) if ( n_points > in_size )
return FT_THROW( Invalid_Table ); return FT_THROW( Invalid_Table );
@ -418,6 +428,8 @@
{ {
FT_Byte flag = flags_in[i]; FT_Byte flag = flags_in[i];
FT_Bool on_curve = !( flag >> 7 ); FT_Bool on_curve = !( flag >> 7 );
flag &= 0x7f; flag &= 0x7f;
if ( flag < 84 ) if ( flag < 84 )
data_bytes = 1; data_bytes = 1;
@ -506,20 +518,20 @@
FT_ULong dst_size, FT_ULong dst_size,
FT_ULong* glyph_size ) FT_ULong* glyph_size )
{ {
FT_UInt flag_offset = 10 + ( 2 * n_contours ) + 2 + instruction_len; FT_UInt flag_offset = 10 + ( 2 * n_contours ) + 2 + instruction_len;
FT_Int last_flag = -1; FT_Int last_flag = -1;
FT_Int repeat_count = 0; FT_Int repeat_count = 0;
FT_Int last_x = 0; FT_Int last_x = 0;
FT_Int last_y = 0; FT_Int last_y = 0;
FT_UInt x_bytes = 0; FT_UInt x_bytes = 0;
FT_UInt y_bytes = 0; FT_UInt y_bytes = 0;
FT_UInt xy_bytes; FT_UInt xy_bytes;
FT_UInt i; FT_UInt i;
FT_UInt x_offset; FT_UInt x_offset;
FT_UInt y_offset; FT_UInt y_offset;
FT_Byte* pointer; FT_Byte* pointer;
for ( i = 0; i < n_points; ++i ) for ( i = 0; i < n_points; ++i )
{ {
const WOFF2_PointRec point = points[i]; const WOFF2_PointRec point = points[i];
@ -528,6 +540,7 @@
FT_Int dx = point.x - last_x; FT_Int dx = point.x - last_x;
FT_Int dy = point.y - last_y; FT_Int dy = point.y - last_y;
if ( dx == 0 ) if ( dx == 0 )
flag |= GLYF_THIS_X_IS_SAME; flag |= GLYF_THIS_X_IS_SAME;
else if ( dx > -256 && dx < 256 ) else if ( dx > -256 && dx < 256 )
@ -641,6 +654,7 @@
FT_ULong offset; FT_ULong offset;
FT_Byte* pointer; FT_Byte* pointer;
if ( n_points > 0 ) if ( n_points > 0 )
{ {
x_min = points[0].x; x_min = points[0].x;
@ -682,6 +696,7 @@
FT_Bool we_have_inst = FALSE; FT_Bool we_have_inst = FALSE;
FT_UShort flags = FLAG_MORE_COMPONENTS; FT_UShort flags = FLAG_MORE_COMPONENTS;
if ( FT_STREAM_SEEK( start_offset ) ) if ( FT_STREAM_SEEK( start_offset ) )
goto Exit; goto Exit;
while ( flags & FLAG_MORE_COMPONENTS ) while ( flags & FLAG_MORE_COMPONENTS )
@ -712,8 +727,8 @@
*size = FT_STREAM_POS() - start_offset; *size = FT_STREAM_POS() - start_offset;
*have_instructions = we_have_inst; *have_instructions = we_have_inst;
Exit: Exit:
return error; return error;
} }
@ -739,6 +754,7 @@
const FT_ULong offset_size = index_format ? 4 : 2; const FT_ULong offset_size = index_format ? 4 : 2;
if ( ( loca_values_size << 2 ) >> 2 != loca_values_size ) if ( ( loca_values_size << 2 ) >> 2 != loca_values_size )
goto Fail; goto Fail;
@ -750,6 +766,8 @@
for ( i = 0; i < loca_values_size; i++ ) for ( i = 0; i < loca_values_size; i++ )
{ {
FT_ULong value = loca_values[i]; FT_ULong value = loca_values[i];
if ( index_format ) if ( index_format )
WRITE_ULONG( dst, value ); WRITE_ULONG( dst, value );
else else
@ -768,13 +786,13 @@
FT_FREE( loca_buf ); FT_FREE( loca_buf );
return error; return error;
Fail: Fail:
if ( !error ) if ( !error )
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
FT_FREE( loca_buf ); FT_FREE( loca_buf );
return error; return error;
} }
@ -818,6 +836,7 @@
FT_Byte* glyph_buf = NULL; FT_Byte* glyph_buf = NULL;
WOFF2_Point points = NULL; WOFF2_Point points = NULL;
if ( FT_NEW_ARRAY( substreams, num_substreams ) ) if ( FT_NEW_ARRAY( substreams, num_substreams ) )
goto Fail; goto Fail;
@ -849,6 +868,8 @@
for ( i = 0; i < num_substreams; ++i ) for ( i = 0; i < num_substreams; ++i )
{ {
FT_ULong substream_size; FT_ULong substream_size;
if ( FT_READ_ULONG( substream_size ) ) if ( FT_READ_ULONG( substream_size ) )
goto Fail; goto Fail;
if ( substream_size > glyf_table->TransformLength - offset ) if ( substream_size > glyf_table->TransformLength - offset )
@ -889,6 +910,7 @@
FT_ULong bbox_offset; FT_ULong bbox_offset;
FT_UShort x_min; FT_UShort x_min;
/* Set `have_bbox'. */ /* Set `have_bbox'. */
bbox_offset = bbox_bitmap_offset + ( i >> 3 ); bbox_offset = bbox_bitmap_offset + ( i >> 3 );
if ( FT_STREAM_SEEK( bbox_offset ) || if ( FT_STREAM_SEEK( bbox_offset ) ||
@ -912,6 +934,7 @@
FT_ULong size_needed; FT_ULong size_needed;
FT_Byte* pointer = NULL; FT_Byte* pointer = NULL;
/* Composite glyphs must have explicit bbox. */ /* Composite glyphs must have explicit bbox. */
if ( !have_bbox ) if ( !have_bbox )
goto Fail; goto Fail;
@ -990,6 +1013,7 @@
FT_Byte* pointer = NULL; FT_Byte* pointer = NULL;
if ( FT_NEW_ARRAY( n_points_arr, n_contours ) ) if ( FT_NEW_ARRAY( n_points_arr, n_contours ) )
goto Fail; goto Fail;
@ -1149,17 +1173,17 @@
return error; return error;
Fail: Fail:
if ( !error ) if ( !error )
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
FT_FREE( substreams ); FT_FREE( substreams );
FT_FREE( loca_values ); FT_FREE( loca_values );
FT_FREE( n_points_arr ); FT_FREE( n_points_arr );
FT_FREE( glyph_buf ); FT_FREE( glyph_buf );
FT_FREE( points ); FT_FREE( points );
return error; return error;
} }
@ -1189,6 +1213,7 @@
const WOFF2_Table head_table = find_table( tables, num_tables, const WOFF2_Table head_table = find_table( tables, num_tables,
TTAG_head ); TTAG_head );
/* Read `numGlyphs' from maxp table. */ /* Read `numGlyphs' from maxp table. */
if ( FT_STREAM_SEEK( maxp_table->src_offset ) && FT_STREAM_SKIP( 8 ) ) if ( FT_STREAM_SEEK( maxp_table->src_offset ) && FT_STREAM_SKIP( 8 ) )
return error; return error;
@ -1273,6 +1298,7 @@
FT_Byte* hmtx_table = NULL; FT_Byte* hmtx_table = NULL;
FT_Byte* dst = NULL; FT_Byte* dst = NULL;
if ( FT_READ_BYTE( hmtx_flags ) ) if ( FT_READ_BYTE( hmtx_flags ) )
goto Fail; goto Fail;
@ -1292,7 +1318,7 @@
( num_hmetrics < 1 ) ) ( num_hmetrics < 1 ) )
goto Fail; goto Fail;
/* Must have atleast one entry. */ /* Must have at least one entry. */
if ( num_hmetrics < 1 ) if ( num_hmetrics < 1 )
goto Fail; goto Fail;
@ -1305,6 +1331,7 @@
{ {
FT_UShort advance_width; FT_UShort advance_width;
if ( FT_READ_USHORT( advance_width ) ) if ( FT_READ_USHORT( advance_width ) )
goto Fail; goto Fail;
@ -1316,6 +1343,7 @@
{ {
FT_Short lsb; FT_Short lsb;
if ( has_proportional_lsbs ) if ( has_proportional_lsbs )
{ {
if ( FT_READ_SHORT( lsb ) ) if ( FT_READ_SHORT( lsb ) )
@ -1332,6 +1360,7 @@
{ {
FT_Short lsb; FT_Short lsb;
if ( has_monospace_lsbs ) if ( has_monospace_lsbs )
{ {
if ( FT_READ_SHORT( lsb ) ) if ( FT_READ_SHORT( lsb ) )
@ -1374,10 +1403,11 @@
return error; return error;
Fail: Fail:
if ( !error ) if ( !error )
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
return error;
return error;
} }
@ -1419,6 +1449,7 @@
const WOFF2_Table loca_table = find_table( indices, num_tables, const WOFF2_Table loca_table = find_table( indices, num_tables,
TTAG_loca ); TTAG_loca );
if ( ( !glyf_table && loca_table ) || if ( ( !glyf_table && loca_table ) ||
( !loca_table && glyf_table ) ) ( !loca_table && glyf_table ) )
{ {
@ -1455,6 +1486,7 @@
{ {
WOFF2_TableRec table = *( indices[nn] ); WOFF2_TableRec table = *( indices[nn] );
FT_TRACE3(( "Seeking to %d with table size %d.\n", FT_TRACE3(( "Seeking to %d with table size %d.\n",
table.src_offset, table.src_length )); table.src_offset, table.src_length ));
FT_TRACE3(( "Table tag: %c%c%c%c.\n", FT_TRACE3(( "Table tag: %c%c%c%c.\n",
@ -1481,7 +1513,7 @@
checksum = 0; checksum = 0;
if ( ( table.flags & WOFF2_FLAGS_TRANSFORM ) != WOFF2_FLAGS_TRANSFORM ) if ( ( table.flags & WOFF2_FLAGS_TRANSFORM ) != WOFF2_FLAGS_TRANSFORM )
{ {
/* Check if `head' is atleast 12 bytes. */ /* Check whether `head' is at least 12 bytes. */
if ( table.Tag == TTAG_head ) if ( table.Tag == TTAG_head )
{ {
if ( table.src_length < 12 ) if ( table.src_length < 12 )
@ -1591,15 +1623,15 @@
return error; return error;
Fail: Fail:
if ( !error ) if ( !error )
error = FT_THROW( Invalid_Table ); error = FT_THROW( Invalid_Table );
FT_FREE( table_entry ); FT_FREE( table_entry );
FT_Stream_Close( stream ); FT_Stream_Close( stream );
FT_FREE( stream ); FT_FREE( stream );
return error; return error;
} }
@ -1662,6 +1694,7 @@
FT_FRAME_END FT_FRAME_END
}; };
FT_ASSERT( stream == face->root.stream ); FT_ASSERT( stream == face->root.stream );
FT_ASSERT( FT_STREAM_POS() == 0 ); FT_ASSERT( FT_STREAM_POS() == 0 );
@ -1716,6 +1749,8 @@
for ( nn = 0; nn < woff2.num_tables; nn++ ) for ( nn = 0; nn < woff2.num_tables; nn++ )
{ {
WOFF2_Table table = tables + nn; WOFF2_Table table = tables + nn;
if ( FT_READ_BYTE( table->FlagByte ) ) if ( FT_READ_BYTE( table->FlagByte ) )
goto Exit; goto Exit;
@ -1824,6 +1859,7 @@
{ {
WOFF2_TtcFont ttc_font = woff2.ttc_fonts + nn; WOFF2_TtcFont ttc_font = woff2.ttc_fonts + nn;
if ( READ_255USHORT( ttc_font->num_tables ) ) if ( READ_255USHORT( ttc_font->num_tables ) )
goto Exit; goto Exit;
if ( FT_READ_ULONG( ttc_font->flavor ) ) if ( FT_READ_ULONG( ttc_font->flavor ) )
@ -1845,6 +1881,7 @@
FT_UShort table_index; FT_UShort table_index;
WOFF2_Table table; WOFF2_Table table;
if ( READ_255USHORT( table_index ) ) if ( READ_255USHORT( table_index ) )
goto Exit; goto Exit;
@ -1934,6 +1971,7 @@
{ {
WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index; WOFF2_TtcFont ttc_font = woff2.ttc_fonts + face_index;
/* Create a temporary array. */ /* Create a temporary array. */
if ( FT_NEW_ARRAY( temp_indices, if ( FT_NEW_ARRAY( temp_indices,
ttc_font->num_tables ) ) ttc_font->num_tables ) )
@ -1975,6 +2013,7 @@
{ {
FT_UInt searchRange, entrySelector, rangeShift, x; FT_UInt searchRange, entrySelector, rangeShift, x;
x = woff2.num_tables; x = woff2.num_tables;
entrySelector = 0; entrySelector = 0;
while ( x ) while ( x )