summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>2019-07-05 01:09:52 +0530
committerNikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>2019-07-05 01:09:52 +0530
commitc325089c2fd005e2c324aa4f3ddb942258aed5f1 (patch)
tree6ac017e0393053fab8518bf41c91dd9f0c3abd3d
parent0d0bd49be5d0b77ccdc873201c98d490b53c2dbe (diff)
downloadfreetype2-c325089c2fd005e2c324aa4f3ddb942258aed5f1.tar.gz
[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 params and iterate over tables.
-rw-r--r--src/sfnt/sfwoff2.c149
1 files changed, 141 insertions, 8 deletions
diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c
index 38025c60d..a44cd6f80 100644
--- a/src/sfnt/sfwoff2.c
+++ b/src/sfnt/sfwoff2.c
@@ -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 );
- /* TODO reconstruct the font tables! */
+ /* 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 */