diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index 6f955a2b7..8a5f7c5b3 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -34,9 +34,49 @@ #define READ_255USHORT( var ) Read255UShort( stream, &var ) + #define READ_BASE128( var ) ReadBase128( stream, &var ) + #define ROUND4( var ) ( var + 3 ) & ~3 +#define WRITE_USHORT( p, v ) \ + do \ + { \ + *(p)++ = (FT_Byte)( (v) >> 8 ); \ + *(p)++ = (FT_Byte)( (v) >> 0 ); \ + \ + } while ( 0 ) + +#define WRITE_ULONG( p, v ) \ + do \ + { \ + *(p)++ = (FT_Byte)( (v) >> 24 ); \ + *(p)++ = (FT_Byte)( (v) >> 16 ); \ + *(p)++ = (FT_Byte)( (v) >> 8 ); \ + *(p)++ = (FT_Byte)( (v) >> 0 ); \ + \ + } while ( 0 ) + + + FT_CALLBACK_DEF( int ) + compare_tags( const void* a, + const void* b ) + { + WOFF2_Table table1 = *(WOFF2_Table*)a; + WOFF2_Table table2 = *(WOFF2_Table*)b; + + FT_ULong tag1 = table1->Tag; + FT_ULong tag2 = table2->Tag; + + + if ( tag1 > tag2 ) + return 1; + else if ( tag1 < tag2 ) + return -1; + else + return 0; + } + static FT_Error Read255UShort( FT_Stream stream, @@ -183,6 +223,10 @@ FT_UInt64 first_table_offset; FT_UInt64 file_offset; + FT_Byte* sfnt = NULL; + FT_Stream sfnt_stream = NULL; + FT_Byte* sfnt_header; + static const FT_Frame_Field woff2_header_fields[] = { #undef FT_STRUCTURE @@ -211,6 +255,9 @@ FT_ASSERT( stream == face->root.stream ); FT_ASSERT( FT_STREAM_POS() == 0 ); + /* DEBUG - Remove later. */ + FT_TRACE2(( "Face index = %ld\n", face->root.face_index )); + /* Read WOFF2 Header. */ if ( FT_STREAM_READ_FIELDS( woff2_header_fields, &woff2 ) ) return error; @@ -408,7 +455,7 @@ return FT_THROW( Invalid_Table ); /* DEBUG - Remove later */ else - FT_TRACE2(( "Glyf and loca are valid.\n" )); + FT_TRACE2(( "glyf and loca are valid.\n" )); } } /* Collection directory reading complete. */ @@ -444,11 +491,82 @@ if( file_offset != ( ROUND4( woff2.length ) ) ) return FT_THROW( Invalid_Table ); + /* Redirect a TTC to exit for now. */ + if( woff2.header_version ) + { + FT_TRACE2(( "Reading TTC fonts not supported yet.\n" )); + error = FT_THROW( Unimplemented_Feature ); + goto Exit; + } + + /* Write sfnt header. */ + if ( FT_ALLOC( sfnt, 12 + woff2.num_tables * 16UL ) || + FT_NEW( sfnt_stream ) ) + goto Exit; + + sfnt_header = sfnt; + + { + FT_UInt searchRange, entrySelector, rangeShift, x; + /* DEBUG - Remove later */ + FT_TRACE2(( "Writing SFNT offset table.\n" )); + + x = woff2.num_tables; + entrySelector = 0; + while ( x ) + { + x >>= 1; + entrySelector += 1; + } + entrySelector--; + + searchRange = ( 1 << entrySelector ) * 16; + rangeShift = ( woff2.num_tables * 16 ) - searchRange; + + WRITE_ULONG ( sfnt_header, woff2.flavor ); + WRITE_USHORT( sfnt_header, woff2.num_tables ); + WRITE_USHORT( sfnt_header, searchRange ); + WRITE_USHORT( sfnt_header, entrySelector ); + WRITE_USHORT( sfnt_header, rangeShift ); + + } + + /* Sort tables by tag. */ + ft_qsort( indices, + woff2.num_tables, + sizeof ( WOFF2_Table ), + compare_tags ); + + /* DEBUG - Remove later */ + FT_TRACE2(( "Sorted table indices: \n" )); + for( nn = 0; nn < woff2.num_tables; ++nn ) + { + WOFF2_Table table = indices[nn]; + /* DEBUG - Remove later */ + FT_TRACE2(( " Index %d", nn )); + FT_TRACE2(( " %c%c%c%c\n", + (FT_Char)( table->Tag >> 24 ), + (FT_Char)( table->Tag >> 16 ), + (FT_Char)( table->Tag >> 8 ), + (FT_Char)( table->Tag ))); + } + error = FT_THROW( Unimplemented_Feature ); + /* DEBUG - Remove later */ FT_TRACE2(( "Reached end without errors.\n" )); goto Exit; Exit: + FT_FREE( tables ); + FT_FREE( indices ); + + if( error ) + { + FT_FREE( sfnt ); + FT_Stream_Close( sfnt_stream ); + FT_FREE( sfnt_stream ); + } + return error; } @@ -456,6 +574,8 @@ #undef READ_255USHORT #undef READ_BASE128 #undef ROUND4 +#undef WRITE_USHORT +#undef WRITE_ULONG /* END */