ref: 2a23dc7fb30a46f86f625d4b7ec210bf8fe310e7
parent: 5367e0ca016bc79096cb3b57217fc1326dc3b997
author: Nikhil Ramakrishnan <[email protected]>
date: Tue Aug 13 22:36:27 EDT 2019
[woff2] Support `hmtx' reconstruction when `glyf' is untransformed. `reconstruct_hmtx' requires `info->x_mins' and `info->num_glyphs' to reconstruct the hmtx table. In case glyf is not transformed, we call `get_x_mins' which does the necessary work. * src/sfnt/sfwoff2.c (get_x_mins): New function. (reconstruct_font): Call get_x_mins.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
2019-08-27 Nikhil Ramakrishnan <[email protected]>
+ [woff2] Support `hmtx' reconstruction when `glyf' is untransformed.
+
+ `reconstruct_hmtx' requires `info->x_mins' and `info->num_glyphs' to
+ reconstruct the hmtx table. In case glyf is not transformed, we
+ call `get_x_mins' which does the necessary work.
+
+ * src/sfnt/sfwoff2.c (get_x_mins): New function.
+ (reconstruct_font): Call get_x_mins.
+
+2019-08-27 Nikhil Ramakrishnan <[email protected]>
+
[sfnt] Support `face->num_faces' for WOFF2 fonts.
Set correct value of `face->num_faces' for WOFF2 fonts. This is
--- a/src/sfnt/sfwoff2.c
+++ b/src/sfnt/sfwoff2.c
@@ -1170,8 +1170,93 @@
}
- /* XXX What if hmtx is transformed but glyf is not? */
+ /* Get `x_mins' for untransformed glyf table. */
static FT_Error
+ get_x_mins( FT_Stream stream,
+ WOFF2_Table* tables,
+ FT_UShort num_tables,
+ WOFF2_Info info,
+ FT_Memory memory )
+ {
+ FT_UShort num_glyphs;
+ FT_UShort index_format;
+ FT_ULong glyf_offset;
+ FT_UShort glyf_offset_short;
+ FT_ULong loca_offset;
+ FT_Int i;
+ FT_Error error = FT_Err_Ok;
+ FT_ULong offset_size;
+
+ const WOFF2_Table glyf_table = find_table( tables, num_tables,
+ TTAG_glyf );
+ const WOFF2_Table loca_table = find_table( tables, num_tables,
+ TTAG_loca );
+ const WOFF2_Table maxp_table = find_table( tables, num_tables,
+ TTAG_maxp );
+ const WOFF2_Table head_table = find_table( tables, num_tables,
+ TTAG_head );
+
+ /* Read `numGlyphs' from maxp table. */
+ if ( FT_STREAM_SEEK( maxp_table->src_offset ) && FT_STREAM_SKIP( 8 ) )
+ return error;
+
+ if( FT_READ_USHORT( num_glyphs ) )
+ return error;
+
+ info->num_glyphs = num_glyphs;
+
+ FT_TRACE2(( "num_glyphs = %d", num_glyphs ));
+
+ /* Read `indexToLocFormat' from head table. */
+ if( FT_STREAM_SEEK( head_table->src_offset ) && FT_STREAM_SKIP( 50 ) )
+ return error;
+
+ if( FT_READ_USHORT( index_format ) )
+ return error;
+
+ offset_size = index_format ? 4 : 2;
+
+ /* Create x_mins array. */
+ if( FT_NEW_ARRAY( info->x_mins, num_glyphs ) )
+ return error;
+
+ loca_offset = loca_table->src_offset;
+
+ for( i = 0; i < num_glyphs; ++i )
+ {
+ if( FT_STREAM_SEEK( loca_offset ) )
+ return error;
+
+ loca_offset += offset_size;
+
+ if( index_format )
+ {
+ if( FT_READ_ULONG( glyf_offset ) )
+ return error;
+ }
+ else
+ {
+ if( FT_READ_USHORT( glyf_offset_short ) )
+ return error;
+
+ glyf_offset = (FT_ULong)( glyf_offset_short );
+ glyf_offset = glyf_offset << 1;
+ }
+
+ glyf_offset += glyf_table->src_offset;
+
+ if( FT_STREAM_SEEK( glyf_offset ) && FT_STREAM_SKIP( 2 ) )
+ return error;
+
+ if( FT_READ_USHORT( info->x_mins[i] ) )
+ return error;
+ }
+
+ return error;
+ }
+
+
+ static FT_Error
reconstruct_hmtx( FT_Stream stream,
FT_ULong transformed_size,
FT_UShort num_glyphs,
@@ -1450,11 +1535,11 @@
}
else if( table.Tag == TTAG_hmtx )
{
+ /* If glyf is not transformed and hmtx is, handle separately. */
if( !is_glyf_xform )
{
- FT_ERROR(( "hmtx is transformed but glyf is not.\n" ));
- error = FT_THROW( Unimplemented_Feature );
- goto Fail;
+ if( get_x_mins(stream, indices, num_tables, info, memory) )
+ return FT_THROW( Invalid_Table );
}
table.dst_offset = dest_offset;
if( reconstruct_hmtx( stream, table.src_length, info->num_glyphs,