Commit 7e1cce58b58a6c368ca390fa35cfc99aafa9e54d

Werner Lemberg 2017-01-06T20:31:22

[truetype] Add HVAR access without advance width map. * src/truetype/ttgxvar.c (ft_var_load_hvar): Handle case where `offsetToAdvanceWidthMapping' is zero. (tt_hadvance_adjust): Implement direct deltaSet access by glyph index.

diff --git a/ChangeLog b/ChangeLog
index a3e33e0..ccdd2e5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
 2017-01-06  Werner Lemberg  <wl@gnu.org>
 
+	[truetype] Add HVAR access without advance width map.
+
+	* src/truetype/ttgxvar.c (ft_var_load_hvar): Handle case where
+	`offsetToAdvanceWidthMapping' is zero.
+	(tt_hadvance_adjust): Implement direct deltaSet access by glyph
+	index.
+
+2017-01-06  Werner Lemberg  <wl@gnu.org>
+
 	[pcf] Revise driver.
 
 	This commit improves tracing and handling of malformed fonts.  In
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index c7f389a..9891037 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -436,6 +436,7 @@
     FT_ULong   table_len;
     FT_ULong   table_offset;
     FT_ULong   store_offset;
+    FT_ULong   widthMap_offset;
 
     FT_ULong*  dataOffsetArray = NULL;
 
@@ -464,9 +465,8 @@
       goto Exit;
     }
 
-    /* skip map offset */
-    if ( FT_READ_ULONG( store_offset ) ||
-         FT_STREAM_SKIP( 4 )           )
+    if ( FT_READ_ULONG( store_offset )    ||
+         FT_READ_ULONG( widthMap_offset ) )
       goto Exit;
 
     /* parse item variation store */
@@ -619,7 +619,7 @@
 
         /* Parse delta set.                                                */
         /*                                                                 */
-        /* On input, deltas are ( shortDeltaCount + regionIdxCount ) bytes */
+        /* On input, deltas are (shortDeltaCount + regionIdxCount) bytes   */
         /* each; on output, deltas are expanded to `regionIdxCount' shorts */
         /* each.                                                           */
         if ( FT_NEW_ARRAY( hvarData->deltaSet,
@@ -660,6 +660,7 @@
     /* end parse item variation store */
 
     /* parse width map */
+    if ( widthMap_offset )
     {
       GX_WidthMap  widthMap;
 
@@ -789,7 +790,6 @@
 
     GX_HVarData  varData;
 
-    FT_UInt    innerIndex, outerIndex;
     FT_UInt    master, j;
     FT_Fixed   netAdjustment = 0;     /* accumulated adjustment */
     FT_Fixed   scaledDelta;
@@ -815,18 +815,40 @@
     /* advance width adjustments are always present in an `HVAR' table, */
     /* so need to test for this capability                              */
 
-    if ( gindex >= face->blend->hvar_table->widthMap.mapCount )
+    if ( face->blend->hvar_table->widthMap.innerIndex )
     {
-      FT_TRACE2(( "gindex %d out of range\n", gindex ));
-      error = FT_THROW( Invalid_Argument );
-      goto Exit;
+      FT_UInt  innerIndex, outerIndex;
+
+
+      if ( gindex >= face->blend->hvar_table->widthMap.mapCount )
+      {
+        FT_TRACE2(( "gindex %d out of range\n", gindex ));
+        error = FT_THROW( Invalid_Argument );
+        goto Exit;
+      }
+
+      /* trust that HVAR parser has checked indices */
+      outerIndex = face->blend->hvar_table->widthMap.outerIndex[gindex];
+      innerIndex = face->blend->hvar_table->widthMap.innerIndex[gindex];
+      varData    = &face->blend->hvar_table->itemStore.varData[outerIndex];
+      deltaSet   = &varData->deltaSet[varData->regionIdxCount * innerIndex];
     }
+    else
+    {
+      /* no widthMap data; use glyph index as inner index instead */
+      /* (and value 0 for outer index)                            */
+
+      varData = &face->blend->hvar_table->itemStore.varData[0];
+
+      if ( gindex >= varData->itemCount )
+      {
+        FT_TRACE2(( "gindex %d out of range\n", gindex ));
+        error = FT_THROW( Invalid_Argument );
+        goto Exit;
+      }
 
-    /* trust that HVAR parser has checked indices */
-    outerIndex = face->blend->hvar_table->widthMap.outerIndex[gindex];
-    innerIndex = face->blend->hvar_table->widthMap.innerIndex[gindex];
-    varData    = &face->blend->hvar_table->itemStore.varData[outerIndex];
-    deltaSet   = &varData->deltaSet[varData->regionIdxCount * innerIndex];
+      deltaSet = &varData->deltaSet[varData->regionIdxCount * gindex];
+    }
 
     /* See pseudo code from `Font Variations Overview' */
     /* in the OpenType specification.                  */
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 46a77bd..26ba0d7 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -125,8 +125,8 @@ FT_BEGIN_HEADER
     GX_HVStoreRec   itemStore;        /* Item Variation Store */
     GX_WidthMapRec  widthMap;         /* Advance Width Mapping */
 #if 0
-    GX_LSBMap       LsbMap;           /* not implemented */
-    GX_RSBMap       RsbMap;           /* not implemented */
+    GX_LSBMap       lsbMap;           /* not implemented */
+    GX_RSBMap       rsbMap;           /* not implemented */
 #endif
 
   } GX_HVarTableRec, *GX_HVarTable;