[woff2] Avoid too many calls to `FT_REALLOC'.
We do this by using `totalSfntSize' as an initial reference, and extending the buffer when required. This reduces rendering time considerably. * include/freetype/internal/wofftypes.h (WOFF2_HeaderRec): Add `totalSfntSize', rename `total_sfnt_size' to `actual_sfnt_size'. * src/sfnt/sfwoff2.c (write_buf): Add parameter `dst_size' to keep track of and update total size of stream. (WRITE_SFNT_BUF, WRITE_SFNT_BUF_AT): Modify macros accordingly. (pad4, store_loca, reconstruct_glyf, reconstruct_hmtx, reconstruct_font): Update parameters to accept `sfnt_size'. (woff2_open_font): Add variable `sfnt_size'. Use WOFF2 header field `totalSfntSize' as initial reference (if value makes sense) and allocate `totalSfntSize' bytes for the sfnt stream. `write_buf' handles reallocation if and when required. Also resize the stream to `actual_sfnt_size' after reconstruction.
This commit is contained in:
parent
4d9b3d1d50
commit
1e02076815
25
ChangeLog
25
ChangeLog
|
@ -1,3 +1,28 @@
|
||||||
|
2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
|
||||||
|
|
||||||
|
[woff2] Avoid too many calls to `FT_REALLOC'.
|
||||||
|
|
||||||
|
We do this by using `totalSfntSize' as an initial reference, and
|
||||||
|
extending the buffer when required. This reduces rendering time
|
||||||
|
considerably.
|
||||||
|
|
||||||
|
* include/freetype/internal/wofftypes.h (WOFF2_HeaderRec): Add
|
||||||
|
`totalSfntSize', rename `total_sfnt_size' to `actual_sfnt_size'.
|
||||||
|
|
||||||
|
* src/sfnt/sfwoff2.c (write_buf): Add parameter `dst_size' to keep
|
||||||
|
track of and update total size of stream.
|
||||||
|
|
||||||
|
(WRITE_SFNT_BUF, WRITE_SFNT_BUF_AT): Modify macros accordingly.
|
||||||
|
|
||||||
|
(pad4, store_loca, reconstruct_glyf, reconstruct_hmtx,
|
||||||
|
reconstruct_font): Update parameters to accept `sfnt_size'.
|
||||||
|
|
||||||
|
(woff2_open_font): Add variable `sfnt_size'. Use WOFF2 header field
|
||||||
|
`totalSfntSize' as initial reference (if value makes sense) and
|
||||||
|
allocate `totalSfntSize' bytes for the sfnt stream. `write_buf'
|
||||||
|
handles reallocation if and when required. Also resize the stream
|
||||||
|
to `actual_sfnt_size' after reconstruction.
|
||||||
|
|
||||||
2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
|
2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
|
||||||
|
|
||||||
[woff2] Reconstruct `loca', `hmtx', and swap out stream.
|
[woff2] Reconstruct `loca', `hmtx', and swap out stream.
|
||||||
|
|
|
@ -165,6 +165,7 @@ FT_BEGIN_HEADER
|
||||||
FT_ULong flavor;
|
FT_ULong flavor;
|
||||||
FT_ULong length;
|
FT_ULong length;
|
||||||
FT_UShort num_tables;
|
FT_UShort num_tables;
|
||||||
|
FT_ULong totalSfntSize;
|
||||||
FT_ULong totalCompressedSize;
|
FT_ULong totalCompressedSize;
|
||||||
FT_ULong metaOffset;
|
FT_ULong metaOffset;
|
||||||
FT_ULong metaLength;
|
FT_ULong metaLength;
|
||||||
|
@ -176,7 +177,7 @@ FT_BEGIN_HEADER
|
||||||
FT_ULong compressed_offset;
|
FT_ULong compressed_offset;
|
||||||
FT_ULong header_version;
|
FT_ULong header_version;
|
||||||
FT_UShort num_fonts;
|
FT_UShort num_fonts;
|
||||||
FT_ULong total_sfnt_size;
|
FT_ULong actual_sfnt_size;
|
||||||
|
|
||||||
WOFF2_TtcFont ttc_fonts;
|
WOFF2_TtcFont ttc_fonts;
|
||||||
|
|
||||||
|
|
|
@ -73,10 +73,10 @@
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
#define WRITE_SFNT_BUF( buf, s ) \
|
#define WRITE_SFNT_BUF( buf, s ) \
|
||||||
write_buf( &sfnt, &dest_offset, buf, s, memory, TRUE )
|
write_buf( &sfnt, sfnt_size, &dest_offset, buf, s, memory )
|
||||||
|
|
||||||
#define WRITE_SFNT_BUF_AT( offset, buf, s ) \
|
#define WRITE_SFNT_BUF_AT( offset, buf, s ) \
|
||||||
write_buf( &sfnt, &offset, buf, s, memory, FALSE )
|
write_buf( &sfnt, sfnt_size, &offset, buf, s, memory )
|
||||||
|
|
||||||
#define N_CONTOUR_STREAM 0
|
#define N_CONTOUR_STREAM 0
|
||||||
#define N_POINTS_STREAM 1
|
#define N_POINTS_STREAM 1
|
||||||
|
@ -205,11 +205,11 @@
|
||||||
|
|
||||||
static FT_Error
|
static FT_Error
|
||||||
write_buf( FT_Byte** dst_bytes,
|
write_buf( FT_Byte** dst_bytes,
|
||||||
|
FT_ULong* dst_size,
|
||||||
FT_ULong* offset,
|
FT_ULong* offset,
|
||||||
FT_Byte* src,
|
FT_Byte* src,
|
||||||
FT_ULong size,
|
FT_ULong size,
|
||||||
FT_Memory memory,
|
FT_Memory memory )
|
||||||
FT_Bool extend_buf )
|
|
||||||
{
|
{
|
||||||
FT_Error error = FT_Err_Ok;
|
FT_Error error = FT_Err_Ok;
|
||||||
/* We are reallocating memory for `dst', so its pointer may change. */
|
/* We are reallocating memory for `dst', so its pointer may change. */
|
||||||
|
@ -219,15 +219,18 @@
|
||||||
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 );
|
||||||
|
|
||||||
/* DEBUG - Remove later */
|
|
||||||
/* FT_TRACE2(( "Reallocating %lu to %lu.\n", *offset, (*offset + size) )); */
|
|
||||||
/* Reallocate `dst'. */
|
/* Reallocate `dst'. */
|
||||||
if( extend_buf )
|
if( ( *offset + size ) > *dst_size )
|
||||||
{
|
{
|
||||||
|
/* DEBUG - Remove later */
|
||||||
|
FT_TRACE2(( "Reallocating %lu to %lu.\n",
|
||||||
|
*dst_size, (*offset + size) ));
|
||||||
if ( FT_REALLOC( dst,
|
if ( FT_REALLOC( dst,
|
||||||
(FT_ULong)( *offset ),
|
(FT_ULong)( *dst_size ),
|
||||||
(FT_ULong)( *offset + size ) ) )
|
(FT_ULong)( *offset + size ) ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
*dst_size = *offset + size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy data. */
|
/* Copy data. */
|
||||||
|
@ -244,6 +247,7 @@
|
||||||
|
|
||||||
static FT_Error
|
static FT_Error
|
||||||
pad4( FT_Byte** sfnt_bytes,
|
pad4( FT_Byte** sfnt_bytes,
|
||||||
|
FT_ULong* sfnt_size,
|
||||||
FT_ULong* out_offset,
|
FT_ULong* out_offset,
|
||||||
FT_Memory memory )
|
FT_Memory memory )
|
||||||
{
|
{
|
||||||
|
@ -722,6 +726,7 @@
|
||||||
FT_UShort index_format,
|
FT_UShort index_format,
|
||||||
FT_ULong* checksum,
|
FT_ULong* checksum,
|
||||||
FT_Byte** sfnt_bytes,
|
FT_Byte** sfnt_bytes,
|
||||||
|
FT_ULong* sfnt_size,
|
||||||
FT_ULong* out_offset,
|
FT_ULong* out_offset,
|
||||||
FT_Memory memory )
|
FT_Memory memory )
|
||||||
{
|
{
|
||||||
|
@ -783,6 +788,7 @@
|
||||||
WOFF2_Table loca_table,
|
WOFF2_Table loca_table,
|
||||||
FT_ULong* loca_checksum,
|
FT_ULong* loca_checksum,
|
||||||
FT_Byte** sfnt_bytes,
|
FT_Byte** sfnt_bytes,
|
||||||
|
FT_ULong* sfnt_size,
|
||||||
FT_ULong* out_offset,
|
FT_ULong* out_offset,
|
||||||
WOFF2_Info info,
|
WOFF2_Info info,
|
||||||
FT_Memory memory )
|
FT_Memory memory )
|
||||||
|
@ -1108,7 +1114,7 @@
|
||||||
if( WRITE_SFNT_BUF( glyph_buf, glyph_size ) )
|
if( WRITE_SFNT_BUF( glyph_buf, glyph_size ) )
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
if( pad4( &sfnt, &dest_offset, memory ) )
|
if( pad4( &sfnt, sfnt_size, &dest_offset, memory ) )
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
*glyf_checksum += compute_ULong_sum( glyph_buf, glyph_size );
|
*glyf_checksum += compute_ULong_sum( glyph_buf, glyph_size );
|
||||||
|
@ -1124,7 +1130,8 @@
|
||||||
loca_values[num_glyphs] = glyf_table->dst_length;
|
loca_values[num_glyphs] = glyf_table->dst_length;
|
||||||
|
|
||||||
if( store_loca( loca_values, num_glyphs + 1, index_format,
|
if( store_loca( loca_values, num_glyphs + 1, index_format,
|
||||||
loca_checksum, &sfnt, &dest_offset, memory ) )
|
loca_checksum, &sfnt, sfnt_size,
|
||||||
|
&dest_offset, memory ) )
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
loca_table->dst_length = dest_offset - loca_table->dst_offset;
|
loca_table->dst_length = dest_offset - loca_table->dst_offset;
|
||||||
|
@ -1172,6 +1179,7 @@
|
||||||
FT_Short* x_mins,
|
FT_Short* x_mins,
|
||||||
FT_ULong* checksum,
|
FT_ULong* checksum,
|
||||||
FT_Byte** sfnt_bytes,
|
FT_Byte** sfnt_bytes,
|
||||||
|
FT_ULong* sfnt_size,
|
||||||
FT_ULong* out_offset,
|
FT_ULong* out_offset,
|
||||||
FT_Memory memory )
|
FT_Memory memory )
|
||||||
{
|
{
|
||||||
|
@ -1306,6 +1314,7 @@
|
||||||
WOFF2_Header woff2,
|
WOFF2_Header woff2,
|
||||||
WOFF2_Info info,
|
WOFF2_Info info,
|
||||||
FT_Byte** sfnt_bytes,
|
FT_Byte** sfnt_bytes,
|
||||||
|
FT_ULong* sfnt_size,
|
||||||
FT_Memory memory )
|
FT_Memory memory )
|
||||||
{
|
{
|
||||||
FT_Error error = FT_Err_Ok;
|
FT_Error error = FT_Err_Ok;
|
||||||
|
@ -1427,8 +1436,8 @@
|
||||||
|
|
||||||
if( reconstruct_glyf( stream, &table, &checksum,
|
if( reconstruct_glyf( stream, &table, &checksum,
|
||||||
loca_table, &loca_checksum,
|
loca_table, &loca_checksum,
|
||||||
&sfnt, &dest_offset, info,
|
&sfnt, sfnt_size, &dest_offset,
|
||||||
memory ) )
|
info, memory ) )
|
||||||
return FT_THROW( Invalid_Table );
|
return FT_THROW( Invalid_Table );
|
||||||
FT_TRACE2(("glyf checksum is %08x\n", checksum));
|
FT_TRACE2(("glyf checksum is %08x\n", checksum));
|
||||||
}
|
}
|
||||||
|
@ -1441,7 +1450,7 @@
|
||||||
table.dst_offset = dest_offset;
|
table.dst_offset = dest_offset;
|
||||||
if( reconstruct_hmtx( stream, table.src_length, info->num_glyphs,
|
if( reconstruct_hmtx( stream, table.src_length, info->num_glyphs,
|
||||||
info->num_hmetrics, info->x_mins, &checksum,
|
info->num_hmetrics, info->x_mins, &checksum,
|
||||||
&sfnt, &dest_offset, memory ) )
|
&sfnt, sfnt_size, &dest_offset, memory ) )
|
||||||
return FT_THROW( Invalid_Table );
|
return FT_THROW( Invalid_Table );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1464,7 +1473,7 @@
|
||||||
/* Update checksum. */
|
/* Update checksum. */
|
||||||
font_checksum += compute_ULong_sum( table_entry, 16 );
|
font_checksum += compute_ULong_sum( table_entry, 16 );
|
||||||
|
|
||||||
if( pad4( &sfnt, &dest_offset, memory ) )
|
if( pad4( &sfnt, sfnt_size, &dest_offset, memory ) )
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
/* Sanity check. */
|
/* Sanity check. */
|
||||||
|
@ -1488,7 +1497,7 @@
|
||||||
|
|
||||||
FT_TRACE2(( "Final checksum = %u\n", font_checksum ));
|
FT_TRACE2(( "Final checksum = %u\n", font_checksum ));
|
||||||
|
|
||||||
woff2->total_sfnt_size = dest_offset;
|
woff2->actual_sfnt_size = dest_offset;
|
||||||
|
|
||||||
/* Set pointer of sfnt stream to its correct value. */
|
/* Set pointer of sfnt stream to its correct value. */
|
||||||
*sfnt_bytes = sfnt;
|
*sfnt_bytes = sfnt;
|
||||||
|
@ -1539,6 +1548,7 @@
|
||||||
FT_Byte* sfnt = NULL;
|
FT_Byte* sfnt = NULL;
|
||||||
FT_Stream sfnt_stream = NULL;
|
FT_Stream sfnt_stream = NULL;
|
||||||
FT_Byte* sfnt_header;
|
FT_Byte* sfnt_header;
|
||||||
|
FT_ULong sfnt_size;
|
||||||
|
|
||||||
FT_Byte* uncompressed_buf = NULL;
|
FT_Byte* uncompressed_buf = NULL;
|
||||||
|
|
||||||
|
@ -1552,7 +1562,8 @@
|
||||||
FT_FRAME_ULONG ( flavor ),
|
FT_FRAME_ULONG ( flavor ),
|
||||||
FT_FRAME_ULONG ( length ),
|
FT_FRAME_ULONG ( length ),
|
||||||
FT_FRAME_USHORT ( num_tables ),
|
FT_FRAME_USHORT ( num_tables ),
|
||||||
FT_FRAME_SKIP_BYTES( 2 + 4 ),
|
FT_FRAME_SKIP_BYTES( 2 ),
|
||||||
|
FT_FRAME_ULONG ( totalSfntSize ),
|
||||||
FT_FRAME_ULONG ( totalCompressedSize ),
|
FT_FRAME_ULONG ( totalCompressedSize ),
|
||||||
FT_FRAME_SKIP_BYTES( 2 * 2 ),
|
FT_FRAME_SKIP_BYTES( 2 * 2 ),
|
||||||
FT_FRAME_ULONG ( metaOffset ),
|
FT_FRAME_ULONG ( metaOffset ),
|
||||||
|
@ -1582,6 +1593,7 @@
|
||||||
FT_TRACE2(( "flavor -> 0x%X\n", woff2.flavor ));
|
FT_TRACE2(( "flavor -> 0x%X\n", woff2.flavor ));
|
||||||
FT_TRACE2(( "length -> %lu\n", woff2.length ));
|
FT_TRACE2(( "length -> %lu\n", woff2.length ));
|
||||||
FT_TRACE2(( "num_tables -> %hu\n", woff2.num_tables ));
|
FT_TRACE2(( "num_tables -> %hu\n", woff2.num_tables ));
|
||||||
|
FT_TRACE2(( "totalSfntSize -> %lu\n", woff2.totalSfntSize ));
|
||||||
FT_TRACE2(( "metaOffset -> %hu\n", woff2.metaOffset ));
|
FT_TRACE2(( "metaOffset -> %hu\n", woff2.metaOffset ));
|
||||||
FT_TRACE2(( "metaLength -> %hu\n", woff2.metaLength ));
|
FT_TRACE2(( "metaLength -> %hu\n", woff2.metaLength ));
|
||||||
FT_TRACE2(( "privOffset -> %hu\n", woff2.privOffset ));
|
FT_TRACE2(( "privOffset -> %hu\n", woff2.privOffset ));
|
||||||
|
@ -1816,12 +1828,7 @@
|
||||||
/* DEBUG - Remove later */
|
/* DEBUG - Remove later */
|
||||||
FT_TRACE2(( "Storing tables for TTC face index %d.\n", face_index ));
|
FT_TRACE2(( "Storing tables for TTC face index %d.\n", face_index ));
|
||||||
for ( nn = 0; nn < ttc_font->num_tables; nn++ )
|
for ( nn = 0; nn < ttc_font->num_tables; nn++ )
|
||||||
{
|
|
||||||
/* DEBUG - Remove later */
|
|
||||||
FT_TRACE2(( "i=%d, table_index=%d\n",
|
|
||||||
nn, ttc_font->table_indices[nn] ));
|
|
||||||
temp_indices[nn] = indices[ttc_font->table_indices[nn]];
|
temp_indices[nn] = indices[ttc_font->table_indices[nn]];
|
||||||
}
|
|
||||||
|
|
||||||
/* Resize array to required size. */
|
/* Resize array to required size. */
|
||||||
if( FT_RENEW_ARRAY( indices, woff2.num_tables,
|
if( FT_RENEW_ARRAY( indices, woff2.num_tables,
|
||||||
|
@ -1837,8 +1844,15 @@
|
||||||
woff2.num_tables = ttc_font->num_tables;
|
woff2.num_tables = ttc_font->num_tables;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We need to allocate this much at the minimum. */
|
||||||
|
sfnt_size = 12 + woff2.num_tables * 16UL;
|
||||||
|
/* This is what we normally expect. */
|
||||||
|
/* Initially trust `totalSfntSize' and change later as required. */
|
||||||
|
if ( woff2.totalSfntSize > sfnt_size )
|
||||||
|
sfnt_size = woff2.totalSfntSize;
|
||||||
|
|
||||||
/* Write sfnt header. */
|
/* Write sfnt header. */
|
||||||
if ( FT_ALLOC( sfnt, 12 + woff2.num_tables * 16UL ) ||
|
if ( FT_ALLOC( sfnt, sfnt_size ) ||
|
||||||
FT_NEW( sfnt_stream ) )
|
FT_NEW( sfnt_stream ) )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
|
@ -1910,11 +1924,24 @@
|
||||||
FT_FRAME_EXIT();
|
FT_FRAME_EXIT();
|
||||||
|
|
||||||
reconstruct_font( uncompressed_buf, woff2.uncompressed_size,
|
reconstruct_font( uncompressed_buf, woff2.uncompressed_size,
|
||||||
indices, &woff2, &info, &sfnt, memory );
|
indices, &woff2, &info, &sfnt, &sfnt_size,
|
||||||
|
memory );
|
||||||
|
|
||||||
|
/* Resize `sfnt' to actual size of sfnt stream. */
|
||||||
|
if ( woff2.actual_sfnt_size < sfnt_size )
|
||||||
|
{
|
||||||
|
/* DEBUG - Remove later */
|
||||||
|
FT_TRACE2(( "Trimming sfnt stream from %lu to %lu.\n",
|
||||||
|
sfnt_size, woff2.actual_sfnt_size ));
|
||||||
|
if ( FT_REALLOC( sfnt,
|
||||||
|
(FT_ULong)( sfnt_size ),
|
||||||
|
(FT_ULong)( woff2.actual_sfnt_size ) ) )
|
||||||
|
goto Exit;
|
||||||
|
}
|
||||||
|
|
||||||
/* reconstruct_font has done all the work. */
|
/* reconstruct_font has done all the work. */
|
||||||
/* Swap out stream and return. */
|
/* Swap out stream and return. */
|
||||||
FT_Stream_OpenMemory( sfnt_stream, sfnt, woff2.total_sfnt_size );
|
FT_Stream_OpenMemory( sfnt_stream, sfnt, woff2.actual_sfnt_size );
|
||||||
sfnt_stream->memory = stream->memory;
|
sfnt_stream->memory = stream->memory;
|
||||||
sfnt_stream->close = stream_close;
|
sfnt_stream->close = stream_close;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue