freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2] master 07ee1d2 2/5: [truetype] Parse `MVAR' table.


From: Werner LEMBERG
Subject: [freetype2] master 07ee1d2 2/5: [truetype] Parse `MVAR' table.
Date: Wed, 11 Jan 2017 13:28:10 +0000 (UTC)

branch: master
commit 07ee1d250c5ae008e3467dea39dfc0b7f99af0b3
Author: Werner Lemberg <address@hidden>
Commit: Werner Lemberg <address@hidden>

    [truetype] Parse `MVAR' table.
    
    * src/truetype/ttgxvar.h (MVAR_TAG_XXX): New macros for MVAR tags.
    (GX_Value, GX_MVarTable): New structures.
    (GX_Blend): Add it.
    
    * src/truetype/ttgxvar.c (GX_VALUE_SIZE, GX_VALUE_CASE,
    GX_GASP_CASE): New macros.
    (ft_var_get_value_pointer): New auxiliary function to get a pointer
    to a value from various SFNT tables already stored in `TT_Face'.
    (ft_var_load_mvar): New function.
    (TT_Get_MM_Var): Call it.
    (tt_done_blend): Updated.
---
 ChangeLog              |   16 ++++
 src/truetype/ttgxvar.c |  215 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/truetype/ttgxvar.h |   73 ++++++++++++++++
 3 files changed, 302 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5ba2319..f3bb28b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,21 @@
 2017-01-11  Werner Lemberg  <address@hidden>
 
+       [truetype] Parse `MVAR' table.
+
+       * src/truetype/ttgxvar.h (MVAR_TAG_XXX): New macros for MVAR tags.
+       (GX_Value, GX_MVarTable): New structures.
+       (GX_Blend): Add it.
+
+       * src/truetype/ttgxvar.c (GX_VALUE_SIZE, GX_VALUE_CASE,
+       GX_GASP_CASE): New macros.
+       (ft_var_get_value_pointer): New auxiliary function to get a pointer
+       to a value from various SFNT tables already stored in `TT_Face'.
+       (ft_var_load_mvar): New function.
+       (TT_Get_MM_Var): Call it.
+       (tt_done_blend): Updated.
+
+2017-01-11  Werner Lemberg  <address@hidden>
+
        [truetype] More preparations for MVAR support.
 
        * src/truetype/ttobjs.c (tt_size_reset): Add argument to make
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index b012871..c89a1c9 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -744,6 +744,7 @@
     if ( FT_READ_USHORT( majorVersion ) ||
          FT_STREAM_SKIP( 2 )            )
       goto Exit;
+
     if ( majorVersion != 1 )
     {
       FT_TRACE2(( "bad table version %d\n", majorVersion ));
@@ -964,7 +965,6 @@
                                    outerIndex,
                                    innerIndex );
 
-    /* apply the accumulated adjustment to derive the interpolated value */
     FT_TRACE5(( "horizontal width %d adjusted by %d units (HVAR)\n",
                 *avalue,
                 delta ));
@@ -976,6 +976,205 @@
   }
 
 
+#define GX_VALUE_SIZE  8
+
+  /* all values are FT_Short or FT_UShort entities; */
+  /* we treat them consistently as FT_Short         */
+#define GX_VALUE_CASE( tag, dflt )      \
+          case MVAR_TAG_ ## tag :       \
+            p = (FT_Short*)&face->dflt; \
+            break
+
+#define GX_GASP_CASE( idx )                                       \
+          case MVAR_TAG_GASP_ ## idx :                            \
+            if ( idx < face->gasp.numRanges - 1 )                 \
+              p = (FT_Short*)&face->gasp.gaspRanges[idx].maxPPEM; \
+            else                                                  \
+              p = NULL;                                           \
+            break
+
+
+  static FT_Short*
+  ft_var_get_value_pointer( TT_Face   face,
+                            FT_ULong  mvar_tag )
+  {
+    FT_Short*  p;
+
+
+    switch ( mvar_tag )
+    {
+      GX_GASP_CASE( 0 );
+      GX_GASP_CASE( 1 );
+      GX_GASP_CASE( 2 );
+      GX_GASP_CASE( 3 );
+      GX_GASP_CASE( 4 );
+      GX_GASP_CASE( 5 );
+      GX_GASP_CASE( 6 );
+      GX_GASP_CASE( 7 );
+      GX_GASP_CASE( 8 );
+      GX_GASP_CASE( 9 );
+
+      GX_VALUE_CASE( CPHT, os2.sCapHeight );
+      GX_VALUE_CASE( HASC, os2.sTypoAscender );
+      GX_VALUE_CASE( HCLA, os2.usWinAscent );
+      GX_VALUE_CASE( HCLD, os2.usWinDescent );
+      GX_VALUE_CASE( HCOF, horizontal.caret_Offset );
+      GX_VALUE_CASE( HCRN, horizontal.caret_Slope_Run );
+      GX_VALUE_CASE( HCRS, horizontal.caret_Slope_Rise );
+      GX_VALUE_CASE( HDSC, os2.sTypoDescender );
+      GX_VALUE_CASE( HLGP, os2.sTypoLineGap );
+      GX_VALUE_CASE( SBXO, os2.ySubscriptXOffset);
+      GX_VALUE_CASE( SBXS, os2.ySubscriptXSize );
+      GX_VALUE_CASE( SBYO, os2.ySubscriptYOffset );
+      GX_VALUE_CASE( SBYS, os2.ySubscriptYSize );
+      GX_VALUE_CASE( SPXO, os2.ySuperscriptXOffset );
+      GX_VALUE_CASE( SPXS, os2.ySuperscriptXSize );
+      GX_VALUE_CASE( SPYO, os2.ySuperscriptYOffset );
+      GX_VALUE_CASE( SPYS, os2.ySuperscriptYSize );
+      GX_VALUE_CASE( STRO, os2.yStrikeoutPosition );
+      GX_VALUE_CASE( STRS, os2.yStrikeoutSize );
+      GX_VALUE_CASE( UNDO, postscript.underlinePosition );
+      GX_VALUE_CASE( UNDS, postscript.underlineThickness );
+      GX_VALUE_CASE( VASC, vertical.Ascender );
+      GX_VALUE_CASE( VCOF, vertical.caret_Offset );
+      GX_VALUE_CASE( VCRN, vertical.caret_Slope_Run );
+      GX_VALUE_CASE( VCRS, vertical.caret_Slope_Rise );
+      GX_VALUE_CASE( VDSC, vertical.Descender );
+      GX_VALUE_CASE( VLGP, vertical.Line_Gap );
+      GX_VALUE_CASE( XHGT, os2.sxHeight );
+
+    default:
+      /* ignore unknown tag */
+      p = NULL;
+    }
+
+    return p;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    ft_var_load_mvar                                                   */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Parse the `MVAR' table.                                            */
+  /*                                                                       */
+  /*    Some memory may remain allocated on error; it is always freed in   */
+  /*    `tt_done_blend', however.                                          */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    face :: The font face.                                             */
+  /*                                                                       */
+  static void
+  ft_var_load_mvar( TT_Face  face )
+  {
+    FT_Stream  stream = FT_FACE_STREAM( face );
+    FT_Memory  memory = stream->memory;
+
+    GX_Blend         blend = face->blend;
+    GX_ItemVarStore  itemStore;
+    GX_Value         value, limit;
+
+    FT_Error   error;
+    FT_UShort  majorVersion;
+    FT_ULong   table_len;
+    FT_ULong   table_offset;
+    FT_UShort  store_offset;
+    FT_ULong   records_offset;
+
+
+    FT_TRACE2(( "MVAR " ));
+
+    error = face->goto_table( face, TTAG_MVAR, stream, &table_len );
+    if ( error )
+    {
+      FT_TRACE2(( "is missing\n" ));
+      return;
+    }
+
+    table_offset = FT_STREAM_POS();
+
+    /* skip minor version */
+    if ( FT_READ_USHORT( majorVersion ) ||
+         FT_STREAM_SKIP( 2 )            )
+      return;
+
+    if ( majorVersion != 1 )
+    {
+      FT_TRACE2(( "bad table version %d\n", majorVersion ));
+      return;
+    }
+
+    if ( FT_NEW( blend->mvar_table ) )
+      return;
+
+    /* skip value record size */
+    if ( FT_READ_USHORT( blend->mvar_table->axisCount )  ||
+         FT_STREAM_SKIP( 2 )                             ||
+         FT_READ_USHORT( blend->mvar_table->valueCount ) ||
+         FT_READ_USHORT( store_offset )                  )
+      return;
+
+    records_offset = FT_STREAM_POS();
+
+    error = ft_var_load_item_variation_store(
+              face,
+              table_offset + store_offset,
+              &blend->mvar_table->itemStore );
+    if ( error )
+      return;
+
+    if ( FT_NEW_ARRAY( blend->mvar_table->values,
+                       blend->mvar_table->valueCount ) )
+      return;
+
+    if ( FT_STREAM_SEEK( records_offset )                                ||
+         FT_FRAME_ENTER( blend->mvar_table->valueCount * GX_VALUE_SIZE ) )
+      return;
+
+    value     = blend->mvar_table->values;
+    limit     = value + blend->mvar_table->valueCount;
+    itemStore = &blend->mvar_table->itemStore;
+
+    for ( ; value < limit; value++ )
+    {
+      value->tag        = FT_GET_ULONG();
+      value->outerIndex = FT_GET_USHORT();
+      value->innerIndex = FT_GET_USHORT();
+
+      if ( value->outerIndex >= itemStore->dataCount                  ||
+           value->innerIndex >= itemStore->varData[value->outerIndex]
+                                                  .itemCount          )
+      {
+        error = FT_THROW( Invalid_Table );
+        break;
+      }
+    }
+
+    FT_FRAME_EXIT();
+
+    if ( error )
+      return;
+
+    FT_TRACE2(( "loaded\n" ));
+
+    value = blend->mvar_table->values;
+    limit = value + blend->mvar_table->valueCount;
+
+    /* save original values of the data MVAR is going to modify */
+    for ( ; value < limit; value++ )
+    {
+      FT_Short*  p = ft_var_get_value_pointer( face, value->tag );
+
+
+      value->unmodified = *p;
+    }
+
+    face->variation_support |= TT_FACE_FLAG_VAR_MVAR;
+  }
+
+
   typedef struct  GX_GVar_Head_
   {
     FT_Long    version;
@@ -1332,7 +1531,8 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Check that the font's `fvar' table is valid, parse it, and return  */
-  /*    those data.                                                        */
+  /*    those data.  It also loads (and parses) the `MVAR' table, if       */
+  /*    possible.                                                          */
   /*                                                                       */
   /* <InOut>                                                               */
   /*    face   :: The font face.                                           */
@@ -1551,6 +1751,8 @@
 
         FT_FRAME_EXIT();
       }
+
+      ft_var_load_mvar( face );
     }
 
     /* fill the output array if requested */
@@ -3074,6 +3276,15 @@
         FT_FREE( blend->hvar_table );
       }
 
+      if ( blend->mvar_table )
+      {
+        ft_var_done_item_variation_store( face,
+                                          &blend->mvar_table->itemStore );
+
+        FT_FREE( blend->mvar_table->values );
+        FT_FREE( blend->mvar_table );
+      }
+
       FT_FREE( blend->tuplecoords );
       FT_FREE( blend->glyphoffsets );
       FT_FREE( blend );
diff --git a/src/truetype/ttgxvar.h b/src/truetype/ttgxvar.h
index 8c0d131..a04b410 100644
--- a/src/truetype/ttgxvar.h
+++ b/src/truetype/ttgxvar.h
@@ -132,6 +132,77 @@ FT_BEGIN_HEADER
   } GX_HVarTableRec, *GX_HVarTable;
 
 
+#define MVAR_TAG_GASP_0  FT_MAKE_TAG( 'g', 's', 'p', '0' )
+#define MVAR_TAG_GASP_1  FT_MAKE_TAG( 'g', 's', 'p', '1' )
+#define MVAR_TAG_GASP_2  FT_MAKE_TAG( 'g', 's', 'p', '2' )
+#define MVAR_TAG_GASP_3  FT_MAKE_TAG( 'g', 's', 'p', '3' )
+#define MVAR_TAG_GASP_4  FT_MAKE_TAG( 'g', 's', 'p', '4' )
+#define MVAR_TAG_GASP_5  FT_MAKE_TAG( 'g', 's', 'p', '5' )
+#define MVAR_TAG_GASP_6  FT_MAKE_TAG( 'g', 's', 'p', '6' )
+#define MVAR_TAG_GASP_7  FT_MAKE_TAG( 'g', 's', 'p', '7' )
+#define MVAR_TAG_GASP_8  FT_MAKE_TAG( 'g', 's', 'p', '8' )
+#define MVAR_TAG_GASP_9  FT_MAKE_TAG( 'g', 's', 'p', '9' )
+
+#define MVAR_TAG_CPHT  FT_MAKE_TAG( 'c', 'p', 'h', 't' )
+#define MVAR_TAG_HASC  FT_MAKE_TAG( 'h', 'a', 's', 'c' )
+#define MVAR_TAG_HCLA  FT_MAKE_TAG( 'h', 'c', 'l', 'a' )
+#define MVAR_TAG_HCLD  FT_MAKE_TAG( 'h', 'c', 'l', 'd' )
+#define MVAR_TAG_HCOF  FT_MAKE_TAG( 'h', 'c', 'o', 'f' )
+#define MVAR_TAG_HCRN  FT_MAKE_TAG( 'h', 'c', 'r', 'n' )
+#define MVAR_TAG_HCRS  FT_MAKE_TAG( 'h', 'c', 'r', 's' )
+#define MVAR_TAG_HDSC  FT_MAKE_TAG( 'h', 'd', 's', 'c' )
+#define MVAR_TAG_HLGP  FT_MAKE_TAG( 'h', 'l', 'g', 'p' )
+#define MVAR_TAG_SBXO  FT_MAKE_TAG( 's', 'b', 'x', 'o' )
+#define MVAR_TAG_SBXS  FT_MAKE_TAG( 's', 'b', 'x', 's' )
+#define MVAR_TAG_SBYO  FT_MAKE_TAG( 's', 'b', 'y', 'o' )
+#define MVAR_TAG_SBYS  FT_MAKE_TAG( 's', 'b', 'y', 's' )
+#define MVAR_TAG_SPXO  FT_MAKE_TAG( 's', 'p', 'x', 'o' )
+#define MVAR_TAG_SPXS  FT_MAKE_TAG( 's', 'p', 'x', 's' )
+#define MVAR_TAG_SPYO  FT_MAKE_TAG( 's', 'p', 'y', 'o' )
+#define MVAR_TAG_SPYS  FT_MAKE_TAG( 's', 'p', 'y', 's' )
+#define MVAR_TAG_STRO  FT_MAKE_TAG( 's', 't', 'r', 'o' )
+#define MVAR_TAG_STRS  FT_MAKE_TAG( 's', 't', 'r', 's' )
+#define MVAR_TAG_UNDO  FT_MAKE_TAG( 'u', 'n', 'd', 'o' )
+#define MVAR_TAG_UNDS  FT_MAKE_TAG( 'u', 'n', 'd', 's' )
+#define MVAR_TAG_VASC  FT_MAKE_TAG( 'v', 'a', 's', 'c' )
+#define MVAR_TAG_VCOF  FT_MAKE_TAG( 'v', 'c', 'o', 'f' )
+#define MVAR_TAG_VCRN  FT_MAKE_TAG( 'v', 'c', 'r', 'n' )
+#define MVAR_TAG_VCRS  FT_MAKE_TAG( 'v', 'c', 'r', 's' )
+#define MVAR_TAG_VDSC  FT_MAKE_TAG( 'v', 'd', 's', 'c' )
+#define MVAR_TAG_VLGP  FT_MAKE_TAG( 'v', 'l', 'g', 'p' )
+#define MVAR_TAG_XHGT  FT_MAKE_TAG( 'x', 'h', 'g', 't' )
+
+
+  typedef struct  GX_ValueRec_
+  {
+    FT_ULong   tag;
+    FT_UShort  outerIndex;
+    FT_UShort  innerIndex;
+
+    FT_Short  unmodified;  /* values are either FT_Short or FT_UShort */
+
+  } GX_ValueRec, *GX_Value;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Struct>                                                              */
+  /*    GX_MVarTableRec                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Data from the `MVAR' table.                                        */
+  /*                                                                       */
+  typedef struct  GX_MVarTableRec_
+  {
+    FT_UShort  axisCount;
+    FT_UShort  valueCount;
+
+    GX_ItemVarStoreRec  itemStore;        /* Item Variation Store  */
+    GX_Value            values;           /* Value Records         */
+
+  } GX_MVarTableRec, *GX_MVarTable;
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Struct>                                                              */
@@ -165,6 +236,8 @@ FT_BEGIN_HEADER
     FT_Error        hvar_error;
     GX_HVarTable    hvar_table;
 
+    GX_MVarTable    mvar_table;
+
     FT_UInt         tuplecount;      /* shared tuples in `gvar'           */
     FT_Fixed*       tuplecoords;     /* tuplecoords[tuplecount][num_axis] */
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]