Removed parsed hint fields from CFF2PrivateDictValues
authorMichiharu Ariza <ariza@adobe.com>
Fri, 3 Aug 2018 21:35:09 +0000 (14:35 -0700)
committerMichiharu Ariza <ariza@adobe.com>
Fri, 3 Aug 2018 21:35:09 +0000 (14:35 -0700)
Instead moved & stored uniformly in values vector (renamed from opstrs)
This should be fine as we aren't likely going to use them as hints after all
Templatized DictValues whether to parse them out
For subsetter, they aren't parsed

src/hb-ot-cff-common-private.hh
src/hb-ot-cff2-table.hh
src/hb-subset-cff2.cc

index 9e89b4e..97565c7 100644 (file)
@@ -136,6 +136,23 @@ enum OpCode {
 inline OpCode Make_OpCode_ESC (unsigned char byte2)  { return (OpCode)(OpCode_ESC_Base + byte2); }
 inline unsigned int OpCode_Size (OpCode op) { return (op >= OpCode_ESC_Base)? 2: 1; }
 
+struct Number
+{
+  inline Number (void) { set_int (0); }
+
+  inline void set_int (int v)       { is_real = false; u.int_val = v; };
+  inline int to_int (void) const    { return is_real? (int)u.real_val: u.int_val; }
+  inline void set_real (float v)    { is_real = true; u.real_val = v; };
+  inline float to_real (void) const { return is_real? u.real_val: (float)u.int_val; }
+
+protected:
+  bool is_real;
+  union {
+    int     int_val;
+    float   real_val;
+  } u;
+};
+
 /* pair of table offset and length */
 struct offset_size_pair {
   unsigned int  offset;
@@ -363,36 +380,62 @@ struct IndexOf : Index
 /* an operator prefixed by its operands in a byte string */
 struct OpStr
 {
+  inline void init (void) {}
+
   OpCode  op;
   ByteStr str;
 };
 
-typedef hb_vector_t <OpStr> OpStrs;
+/* an opstr and the parsed out dict value(s) */
+struct DictVal : OpStr
+{
+  inline void init (void)
+  {
+    single_val.set_int (0);
+    multi_val.init ();
+  }
+
+  inline void fini (void)
+  {
+    multi_val.fini ();
+  }
+
+  Number              single_val;
+  hb_vector_t<Number> multi_val;
+};
 
-/* base param type for dict parsing */
+template <typename VAL>
 struct DictValues
 {
   inline void init (void)
   {
     opStart = 0;
-    opStrs.init ();
+    values.init ();
   }
 
   inline void fini (void)
   {
-    opStrs.fini ();
+    values.fini ();
   }
 
-  void pushOpStr (OpCode op, const ByteStr& str, unsigned int offset)
+  inline void pushVal (OpCode op, const ByteStr& str, unsigned int offset)
   {
-    OpStr *opstr = opStrs.push ();
-    opstr->op = op;
-    opstr->str = ByteStr (str, opStart, offset - opStart);
+    VAL *val = values.push ();
+    val->op = op;
+    val->str = ByteStr (str, opStart, offset - opStart);
     opStart = offset;
   }
 
-  unsigned int  opStart;
-  OpStrs        opStrs;
+  inline void pushVal (OpCode op, const ByteStr& str, unsigned int offset, const VAL &v)
+  {
+    VAL *val = values.push (v);
+    val->op = op;
+    val->str = ByteStr (str, opStart, offset - opStart);
+    opStart = offset;
+  }
+
+  unsigned int       opStart;
+  hb_vector_t<VAL>   values;
 };
 
 /* base of OP_SERIALIZER */
@@ -413,29 +456,29 @@ struct OpSerializer
 /* Top Dict, Font Dict, Private Dict */
 struct Dict : UnsizedByteStr
 {
-  template <typename OP_SERIALIZER, typename PARAM>
+  template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
   inline bool serialize (hb_serialize_context_t *c,
-                        const DictValues &values,
+                        const DICTVAL &dictval,
                         OP_SERIALIZER& opszr,
                         PARAM& param)
   {
     TRACE_SERIALIZE (this);
-    for (unsigned int i = 0; i < values.opStrs.len; i++)
+    for (unsigned int i = 0; i < dictval.values.len; i++)
     {
-      if (unlikely (!opszr.serialize (c, values.opStrs[i], param)))
+      if (unlikely (!opszr.serialize (c, dictval.values[i], param)))
         return_trace (false);
     }
     return_trace (true);
   }
 
   /* in parallel to above */
-  template <typename OP_SERIALIZER>
-  inline static unsigned int calculate_serialized_size (const DictValues &values,
+  template <typename DICTVAL, typename OP_SERIALIZER>
+  inline static unsigned int calculate_serialized_size (const DICTVAL &dictval,
                                                         OP_SERIALIZER& opszr)
   {
     unsigned int size = 0;
-    for (unsigned int i = 0; i < values.opStrs.len; i++)
-      size += opszr.calculate_serialized_size (values.opStrs[i]);
+    for (unsigned int i = 0; i < dictval.values.len; i++)
+      size += opszr.calculate_serialized_size (dictval.values[i]);
     return size;
   }
 
@@ -629,23 +672,6 @@ inline float parse_bcd (const ByteStr& str, unsigned int& offset, float& v)
   return true;
 }
 
-struct Number
-{
-  inline Number (void) { set_int (0); }
-
-  inline void set_int (int v)       { is_real = false; u.int_val = v; };
-  inline int to_int (void) const    { return is_real? (int)u.real_val: u.int_val; }
-  inline void set_real (float v)    { is_real = true; u.real_val = v; };
-  inline float to_real (void) const { return is_real? u.real_val: (float)u.int_val; }
-
-protected:
-  bool is_real;
-  union {
-    int     int_val;
-    float   real_val;
-  } u;
-};
-
 struct Stack
 {
   inline void init (void) { size = 0; }
@@ -697,11 +723,11 @@ struct Stack
       return false;
   }
 
-  inline bool check_pop_int (int& v)
+  inline bool check_pop_num (Number& n)
   {
     if (unlikely (!this->check_underflow (1)))
       return false;
-    v = this->pop ().to_int ();
+    n = this->pop ();
     return true;
   }
 
@@ -717,15 +743,7 @@ struct Stack
     return true;
   }
 
-  inline bool check_pop_real (float& v)
-  {
-    if (unlikely (!this->check_underflow (1)))
-      return false;
-    v = this->pop ().to_real ();
-    return true;
-  }
-
-  inline bool check_pop_delta (hb_vector_t<float>& vec, bool even=false)
+  inline bool check_pop_delta (hb_vector_t<Number>& vec, bool even=false)
   {
     if (even && unlikely ((this->size & 1) != 0))
       return false;
@@ -733,7 +751,8 @@ struct Stack
     float val = 0.0f;
     for (unsigned int i = 0; i < size; i++) {
       val += numbers[i].to_real ();
-      vec.push (val);
+      Number *n = vec.push ();
+      n->set_real (val);
     }
     return true;
   }
index 2212579..0f477e9 100644 (file)
@@ -64,7 +64,7 @@ struct CFF2VariationStore
   DEFINE_SIZE_MIN (2 + VariationStore::min_size);
 };
 
-struct CFF2TopDictValues : DictValues
+struct CFF2TopDictValues : DictValues<OpStr>
 {
   inline void init (void)
   {
@@ -85,11 +85,11 @@ struct CFF2TopDictValues : DictValues
   inline unsigned int calculate_serialized_size (void) const
   {
     unsigned int size = 0;
-    for (unsigned int i = 0; i < opStrs.len; i++)
+    for (unsigned int i = 0; i < values.len; i++)
     {
-      OpCode op = opStrs[i].op;
+      OpCode op = values[i].op;
       if (op == OpCode_FontMatrix)
-        size += opStrs[i].str.len;
+        size += values[i].str.len;
       else
         size += OpCode_Size (OpCode_longint) + 4 + OpCode_Size (op);
     }
@@ -105,49 +105,44 @@ struct CFF2TopDictValues : DictValues
 
 struct CFF2TopDictOpSet
 {
-  static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2TopDictValues& val)
+  static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2TopDictValues& dictval)
   {
     switch (op) {
       case OpCode_CharStrings:
-        if (unlikely (!check_pop_offset (stack, val.charStringsOffset)))
+        if (unlikely (!check_pop_offset (stack, dictval.charStringsOffset)))
           return false;
-        val.pushOpStr (op, str, offset + 1);
         break;
       case OpCode_vstore:
-        if (unlikely (!check_pop_offset (stack, val.vstoreOffset)))
+        if (unlikely (!check_pop_offset (stack, dictval.vstoreOffset)))
           return false;
-        val.pushOpStr (op, str, offset + 1);
         break;
       case OpCode_FDArray:
-        if (unlikely (!check_pop_offset (stack, val.FDArrayOffset)))
+        if (unlikely (!check_pop_offset (stack, dictval.FDArrayOffset)))
           return false;
-        val.pushOpStr (op, str, offset + 1);
         break;
       case OpCode_FDSelect:
-        if (unlikely (!check_pop_offset (stack, val.FDSelectOffset)))
+        if (unlikely (!check_pop_offset (stack, dictval.FDSelectOffset)))
           return false;
-        val.pushOpStr (op, str, offset + 1);
         break;
       case OpCode_FontMatrix:
         if (unlikely (!stack.check_underflow (6)))
           return false;
         for (int i = 0; i < 6; i++)
-          val.FontMatrix[i] = stack.pop ().to_real ();
-        val.pushOpStr (op, str, offset + 1);
+          dictval.FontMatrix[i] = stack.pop ().to_real ();
         break;
       case OpCode_longint:  /* 5-byte integer */
         if (unlikely (!str.check_limit (offset, 5) || !stack.check_overflow (1)))
           return false;
         stack.push_int ((int32_t)*(const HBUINT32*)&str[offset + 1]);
         offset += 4;
-        break;
+        return true;
       
       case OpCode_BCD:  /* real number */
         float v;
         if (unlikely (stack.check_overflow (1) || !parse_bcd (str, offset, v)))
           return false;
         stack.push_real (v);
-        break;
+        return true;
     
       default:
         /* XXX: invalid */
@@ -155,11 +150,12 @@ struct CFF2TopDictOpSet
         return false;
     }
 
+    dictval.pushVal (op, str, offset + 1);
     return true;
   }
 };
 
-struct CFF2FontDictValues : DictValues
+struct CFF2FontDictValues : DictValues<OpStr>
 {
   inline void init (void)
   {
@@ -179,28 +175,27 @@ struct CFF2FontDictValues : DictValues
 
 struct CFF2FontDictOpSet
 {
-  static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2FontDictValues& val)
+  static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2FontDictValues& dictval)
   {
     switch (op) {
       case OpCode_Private:
-        if (unlikely (!check_pop_offset (stack, val.privateDictOffset)))
+        if (unlikely (!check_pop_offset (stack, dictval.privateDictOffset)))
           return false;
-        if (unlikely (!stack.check_pop_uint (val.privateDictSize)))
+        if (unlikely (!stack.check_pop_uint (dictval.privateDictSize)))
           return false;
-        val.pushOpStr (op, str, offset + 1);
         break;
       case OpCode_longint:  /* 5-byte integer */
         if (unlikely (!str.check_limit (offset, 5) || !stack.check_overflow (1)))
           return false;
         stack.push_int ((int32_t)((str[offset + 1] << 24) | ((uint32_t)str[offset + 2] << 16) | ((uint32_t)str[offset + 3] << 8) | str[offset + 4]));
         offset += 4;
-        break;
+        return true;
       case OpCode_BCD:  /* real number */
         float v;
         if (unlikely (stack.check_overflow (1) || !parse_bcd (str, offset, v)))
           return false;
         stack.push_real (v);
-        break;
+        return true;
     
       default:
         /* XXX: invalid */
@@ -208,32 +203,34 @@ struct CFF2FontDictOpSet
         return false;
     }
 
+    dictval.pushVal (op, str, offset + 1);
     return true;
   }
 };
 
-struct CFF2PrivateDictValues_Base : DictValues
+template <typename VAL>
+struct CFF2PrivateDictValues_Base : DictValues<VAL>
 {
   inline void init (void)
   {
-    DictValues::init ();
+    DictValues<VAL>::init ();
     subrsOffset.set (0);
     localSubrs = &Null(Subrs);
   }
 
   inline void fini (void)
   {
-    DictValues::fini ();
+    DictValues<VAL>::fini ();
   }
 
   inline unsigned int calculate_serialized_size (void) const
   {
     unsigned int size = 0;
-    for (unsigned int i = 0; i < opStrs.len; i++)
-      if (opStrs[i].op == OpCode_Subrs)
+    for (unsigned int i = 0; i < DictValues<VAL>::values.len; i++)
+      if (DictValues<VAL>::values[i].op == OpCode_Subrs)
         size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
       else
-        size += opStrs[i].str.len;
+        size += DictValues<VAL>::values[i].str.len;
     return size;
   }
 
@@ -241,148 +238,71 @@ struct CFF2PrivateDictValues_Base : DictValues
   const Subrs       *localSubrs;
 };
 
-struct CFF2PrivateDictValues : CFF2PrivateDictValues_Base
-{
-  inline void init (void)
-  {
-    CFF2PrivateDictValues_Base::init ();
-
-    languageGroup = 0;
-    expansionFactor = 0.06f;
-    vsIndex = 0;
-    blueScale = 0.039625f;
-    blueShift = 7.0f;
-    blueFuzz = 1.0f;
-    stdHW = UNSET_REAL_VALUE;
-    stdVW = UNSET_REAL_VALUE;
-    subrsOffset.set (0);
-    blueValues.init ();
-    otherBlues.init ();
-    familyBlues.init ();
-    familyOtherBlues.init ();
-    stemSnapH.init ();
-    stemSnapV.init ();
-  }
-
-  inline void fini (void)
-  {
-    blueValues.fini ();
-    otherBlues.fini ();
-    familyBlues.fini ();
-    familyOtherBlues.fini ();
-    stemSnapH.fini ();
-    stemSnapV.fini ();
-
-    CFF2PrivateDictValues_Base::fini ();
-  }
-
-  int       languageGroup;
-  float     expansionFactor;
-  int       vsIndex;
-  float     blueScale;
-  float     blueShift;
-  float     blueFuzz;
-  float     stdHW;
-  float     stdVW;
-  hb_vector_t <float> blueValues;
-  hb_vector_t <float> otherBlues;
-  hb_vector_t <float> familyBlues;
-  hb_vector_t <float> familyOtherBlues;
-  hb_vector_t <float> stemSnapH;
-  hb_vector_t <float> stemSnapV;
-};
+typedef CFF2PrivateDictValues_Base<OpStr> CFF2PrivateDictValues_Subset;
+typedef CFF2PrivateDictValues_Base<DictVal> CFF2PrivateDictValues;
 
 struct CFF2PrivateDictOpSet
 {
-  static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues& val)
+  static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues& dictval)
   {
+    DictVal val;
+    val.init ();
+
     switch (op) {
       case OpCode_BlueValues:
-        if (unlikely (!stack.check_pop_delta (val.blueValues)))
-          return false;
-        break;
       case OpCode_OtherBlues:
-        if (unlikely (!stack.check_pop_delta (val.otherBlues)))
-          return false;
-        break;
       case OpCode_FamilyBlues:
-        if (unlikely (!stack.check_pop_delta (val.familyBlues)))
-          return false;
-        break;
       case OpCode_FamilyOtherBlues:
-        if (unlikely (!stack.check_pop_delta (val.familyOtherBlues)))
+      case OpCode_StemSnapH:
+      case OpCode_StemSnapV:
+        if (unlikely (!stack.check_pop_delta (val.multi_val)))
           return false;
         break;
       case OpCode_StdHW:
-        if (unlikely (!stack.check_pop_real (val.stdHW)))
-          return false;
-        break;
       case OpCode_StdVW:
-        if (unlikely (!stack.check_pop_real (val.stdVW)))
-          return false;
-        break;
       case OpCode_BlueScale:
-        if (unlikely (!stack.check_pop_real (val.blueScale)))
-          return false;
-        break;
       case OpCode_BlueShift:
-        if (unlikely (!stack.check_pop_real (val.blueShift)))
-          return false;
-        break;
       case OpCode_BlueFuzz:
-        if (unlikely (!stack.check_pop_real (val.blueFuzz)))
-          return false;
-        break;
-      case OpCode_StemSnapH:
-        if (unlikely (!stack.check_pop_delta (val.stemSnapH)))
-          return false;
-        break;
-      case OpCode_StemSnapV:
-        if (unlikely (!stack.check_pop_delta (val.stemSnapV)))
+      case OpCode_ExpansionFactor:
+        if (unlikely (!stack.check_pop_num (val.single_val)))
           return false;
         break;
       case OpCode_LanguageGroup:
-        if (unlikely (!stack.check_pop_int (val.languageGroup)))
-          return false;
-        break;
-      case OpCode_ExpansionFactor:
-        if (unlikely (!stack.check_pop_real (val.expansionFactor)))
+        if (unlikely (!stack.check_pop_num (val.single_val)))
           return false;
         break;
       case OpCode_Subrs:
-        if (unlikely (!check_pop_offset (stack, val.subrsOffset)))
+        if (unlikely (!check_pop_offset (stack, dictval.subrsOffset)))
           return false;
         break;
       case OpCode_blend:
         // XXX: TODO
-        break;
+        return true;
       case OpCode_longint:  /* 5-byte integer */
         if (unlikely (!str.check_limit (offset, 5) || !stack.check_overflow (1)))
           return false;
         stack.push_int ((int32_t)((str[offset + 1] << 24) | (str[offset + 2] << 16) || (str[offset + 3] << 8) || str[offset + 4]));
         offset += 4;
-        break;
+        return true;
       case OpCode_BCD:  /* real number */
         float v;
         if (unlikely (!stack.check_overflow (1) || !parse_bcd (str, offset, v)))
           return false;
         stack.push_real (v);
-        break;
+        return true;
 
       default:
         return false;
     }
 
-    if (op != OpCode_blend)
-      val.pushOpStr (op, str, offset + 1);
-
+    dictval.pushVal (op, str, offset + 1, val);
     return true;
   }
 };
 
 struct CFF2PrivateDictOpSet_Subset
 {
-  static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues_Base& val)
+  static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues_Subset& dictval)
   {
     switch (op) {
       case OpCode_BlueValues:
@@ -398,10 +318,13 @@ struct CFF2PrivateDictOpSet_Subset
       case OpCode_StemSnapV:
       case OpCode_LanguageGroup:
       case OpCode_ExpansionFactor:
-      case OpCode_blend:
         stack.clear ();
         break;
 
+      case OpCode_blend:
+        stack.clear ();
+        return true;
+
       case OpCode_BCD:
         {
           float v;
@@ -409,7 +332,7 @@ struct CFF2PrivateDictOpSet_Subset
         }
 
       case OpCode_Subrs:
-        if (unlikely (!check_pop_offset (stack, val.subrsOffset)))
+        if (unlikely (!check_pop_offset (stack, dictval.subrsOffset)))
           return false;
         break;
       case OpCode_longint:  /* 5-byte integer */
@@ -417,15 +340,13 @@ struct CFF2PrivateDictOpSet_Subset
           return false;
         stack.push_int ((int32_t)((str[offset + 1] << 24) | (str[offset + 2] << 16) || (str[offset + 3] << 8) || str[offset + 4]));
         offset += 4;
-        break;
+        return true;
 
       default:
         return false;
     }
 
-    if (op != OpCode_blend)
-      val.pushOpStr (op, str, offset + 1);
-
+    dictval.pushVal (op, str, offset + 1);
     return true;
   }
 };
@@ -580,7 +501,7 @@ struct cff2
   };
 
   typedef accelerator_templ_t<CFF2PrivateDictOpSet, CFF2PrivateDictValues> accelerator_t;
-  typedef accelerator_templ_t<CFF2PrivateDictOpSet_Subset, CFF2PrivateDictValues_Base> accelerator_subset_t;
+  typedef accelerator_templ_t<CFF2PrivateDictOpSet_Subset, CFF2PrivateDictValues_Subset> accelerator_subset_t;
 
   inline bool subset (hb_subset_plan_t *plan) const
   {
index 6bf397c..c2c012c 100644 (file)
@@ -167,7 +167,7 @@ struct subset_plan {
     /* top dict */
     {
       CFF2TopDict_OpSerializer topSzr;
-      offsets.topDictSize = TopDict::calculate_serialized_size<CFF2TopDict_OpSerializer> (acc.top, topSzr);
+      offsets.topDictSize = TopDict::calculate_serialized_size (acc.top, topSzr);
       final_size += offsets.topDictSize;
     }