[woff2] Create stream for uncompressed buffer.

Uncompressed buffer is now an `FT_Stream'.

Perform basic checks and start iterating over tables.

* src/sfnt/sfwoff2.c (stream_close, find_table, read_num_hmetrics):
New functions.
(reconstruct_font): Modify parameters and iterate over tables.
(woff2_open_font): Updated.
This commit is contained in:
Nikhil Ramakrishnan 2019-07-05 01:09:52 +05:30 committed by Werner Lemberg
parent 18f6ff11f9
commit 106bacf502
2 changed files with 154 additions and 8 deletions

View File

@ -1,3 +1,16 @@
2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
[woff2] Create stream for uncompressed buffer.
Uncompressed buffer is now an `FT_Stream'.
Perform basic checks and start iterating over tables.
* src/sfnt/sfwoff2.c (stream_close, find_table, read_num_hmetrics):
New functions.
(reconstruct_font): Modify parameters and iterate over tables.
(woff2_open_font): Updated.
2019-08-27 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
[woff2] Handle TTCs and start reconstructing font.

View File

@ -65,6 +65,20 @@
} while ( 0 )
static void
stream_close( FT_Stream stream )
{
FT_Memory memory = stream->memory;
FT_FREE( stream->base );
stream->size = 0;
stream->base = NULL;
stream->close = NULL;
}
FT_CALLBACK_DEF( int )
compare_tags( const void* a,
const void* b )
@ -235,23 +249,140 @@
}
static WOFF2_Table
find_table( WOFF2_Table* tables,
FT_UShort num_tables,
FT_ULong tag )
{
FT_Int i;
for ( i = 0; i < num_tables; i++ )
{
if( tables[i]->Tag == tag )
return tables[i];
}
return NULL;
}
/* Read `numberOfHMetrics' from `hhea' table. */
static FT_Error
read_num_hmetrics( FT_Stream stream,
FT_ULong table_len,
FT_UShort* num_hmetrics )
{
FT_Error error = FT_Err_Ok;
FT_UShort num_metrics;
if( FT_STREAM_SKIP( 34 ) )
return FT_THROW( Invalid_Table );
if( FT_READ_USHORT( num_metrics ) )
return FT_THROW( Invalid_Table );
*num_hmetrics = num_metrics;
FT_TRACE2(( "num_hmetrics = %d\n", *num_hmetrics ));
return error;
}
static FT_Error
reconstruct_font( FT_Byte* transformed_buf,
FT_ULong transformed_buf_size,
WOFF2_Table* indices,
WOFF2_Header woff2,
FT_Int face_index,
FT_Byte* sfnt )
FT_Byte* sfnt,
FT_Memory memory )
{
/* We're writing only one face per call, so offset is fixed. */
FT_ULong dst_offset = 12;
FT_Byte* table_entry = NULL;
FT_Error error = FT_Err_Ok;
FT_Stream stream = NULL;
/* We're writing only one face per call, so initial offset is fixed. */
FT_ULong dst_offset = 12;
FT_UShort num_tables = woff2->num_tables;
FT_ULong checksum = 0;
FT_ULong loca_checksum = 0;
FT_Int nn = 0;
FT_UShort num_hmetrics;
/* Few table checks before reconstruction. */
/* `glyf' must be present with `loca'. */
const WOFF2_Table glyf_table = find_table( indices, num_tables,
TTAG_glyf );
const WOFF2_Table loca_table = find_table( indices, num_tables,
TTAG_loca );
if( ( !glyf_table && loca_table ) ||
( !loca_table && glyf_table ) )
{
FT_ERROR(( "Cannot have only one of glyf/loca.\n" ));
return FT_THROW( Invalid_Table );
}
/* Both `glyf' and `loca' must have same transformation. */
if( glyf_table != NULL )
{
if( ( glyf_table->flags & WOFF2_FLAGS_TRANSFORM ) !=
( loca_table->flags & WOFF2_FLAGS_TRANSFORM ) )
{
FT_ERROR(( "Transformation mismatch in glyf and loca." ));
return FT_THROW( Invalid_Table );
}
}
FT_UNUSED( dst_offset );
FT_UNUSED( table_entry );
FT_UNUSED( loca_checksum );
FT_UNUSED( checksum );
/* Create a stream for the uncompressed buffer. */
if ( FT_NEW( stream ) )
return FT_THROW( Invalid_Table );
FT_Stream_OpenMemory( stream, transformed_buf, transformed_buf_size );
stream->close = stream_close;
FT_ASSERT( FT_STREAM_POS() == 0 );
/* Reconstruct/copy tables to output stream. */
for ( nn = 0; nn < num_tables; nn++ )
{
WOFF2_TableRec table = *( indices[nn] );
/* DEBUG - Remove later */
FT_TRACE2(( "Seeking to %d with table size %d.\n", table.src_offset, table.src_length ));
FT_TRACE2(( "Table tag: %c%c%c%c.\n",
(FT_Char)( table.Tag >> 24 ),
(FT_Char)( table.Tag >> 16 ),
(FT_Char)( table.Tag >> 8 ),
(FT_Char)( table.Tag ) ));
if ( FT_STREAM_SEEK( table.src_offset ) )
return FT_THROW( Invalid_Table );
if( table.src_offset + table.src_length > transformed_buf_size )
return FT_THROW( Invalid_Table );
/* Get stream size for fields of `hmtx' table. */
if( table.Tag == TTAG_hhea )
{
if( read_num_hmetrics( stream, table.src_length, &num_hmetrics ) )
return FT_THROW( Invalid_Table );
}
if( ( table.flags & WOFF2_FLAGS_TRANSFORM ) != WOFF2_FLAGS_TRANSFORM )
{
/* Check if `head' is atleast 12 bytes. */
if( table.Tag == TTAG_head )
{
if( table.src_length < 12 )
return FT_THROW( Invalid_Table );
}
}
}
/* TODO reconstruct the font tables! */
return FT_Err_Ok;
}
@ -564,6 +695,8 @@
ttc_font->num_tables ) )
goto Exit;
/* DEBUG - Remove later */
FT_TRACE2(( "Storing tables for TTC face index %d.\n", face_index ));
for ( nn = 0; nn < ttc_font->num_tables; nn++ )
{
/* DEBUG - Remove later */
@ -660,7 +793,7 @@
/* TODO Write table entries. */
reconstruct_font( uncompressed_buf, woff2.uncompressed_size,
indices, &woff2, face_index, sfnt );
indices, &woff2, sfnt, memory );
error = FT_THROW( Unimplemented_Feature );
/* DEBUG - Remove later */