shithub: freetype+ttf2subf

Download patch

ref: 106bacf5022e8c7c8bdcd8407efd64fb6db182b4
parent: 18f6ff11f91e377d6296bad2ece8bb2be7dbb0e2
author: Nikhil Ramakrishnan <[email protected]>
date: Thu Jul 4 21:09:52 EDT 2019

[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.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,18 @@
 2019-08-27  Nikhil Ramakrishnan  <[email protected]>
 
+	[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  <[email protected]>
+
 	[woff2] Handle TTCs and start reconstructing font.
 
 	We `handle' TTCs by modifying the `indices' array to point to only
--- 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 */