Added drop_hints to SubrFlattener
diff --git a/src/hb-cff-interp-cs-common.hh b/src/hb-cff-interp-cs-common.hh
index 9e22b1e..a07ca0d 100644
--- a/src/hb-cff-interp-cs-common.hh
+++ b/src/hb-cff-interp-cs-common.hh
@@ -282,6 +282,25 @@
     }
   }
 
+  /* hint operators (excluding hint/counter mask) */
+  static inline bool is_hint_op (OpCode op)
+  {
+    switch (op)
+    {
+      case OpCode_hstem:
+      case OpCode_vstem:
+      case OpCode_hstemhm:
+      case OpCode_vstemhm:
+      case OpCode_hflex:
+      case OpCode_flex:
+      case OpCode_hflex1:
+      case OpCode_flex1:
+        return true;
+      default:
+        return false;
+    }
+  }
+
   static inline bool is_subr_op (OpCode op)
   {
     switch (op)
@@ -301,7 +320,6 @@
 {
   inline bool interpret (PARAM& param)
   {
-    param.init ();
     Interpreter<ENV> &super = *this;
     super.env.set_endchar (false);
 
diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh
index f7294cc..56d7a57 100644
--- a/src/hb-subset-cff-common.hh
+++ b/src/hb-subset-cff-common.hh
@@ -252,13 +252,21 @@
   const bool  flatten_subrs;
 };
 
+struct FlattenParam
+{
+  ByteStrBuff &flatStr;
+  bool        drop_hints;
+};
 
 template <typename ACCESSOR, typename ENV, typename OPSET>
 struct SubrFlattener
 {
-  inline SubrFlattener (const ACCESSOR &acc_, const hb_vector_t<hb_codepoint_t> &glyphs_)
+  inline SubrFlattener (const ACCESSOR &acc_,
+                        const hb_vector_t<hb_codepoint_t> &glyphs_,
+                        bool drop_hints_)
     : acc (acc_),
-      glyphs (glyphs_)
+      glyphs (glyphs_),
+      drop_hints (drop_hints_)
   {}
 
   inline bool flatten (ByteStrBuffArray &flat_charstrings)
@@ -272,9 +280,10 @@
       hb_codepoint_t  glyph = glyphs[i];
       const ByteStr str = (*acc.charStrings)[glyph];
       unsigned int fd = acc.fdSelect->get_fd (glyph);
-      CSInterpreter<ENV, OPSET, ByteStrBuff> interp;
+      CSInterpreter<ENV, OPSET, FlattenParam> interp;
       interp.env.init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
-      if (unlikely (!interp.interpret (flat_charstrings[i])))
+      FlattenParam  param = { flat_charstrings[i], drop_hints };
+      if (unlikely (!interp.interpret (param)))
         return false;
     }
     return true;
@@ -282,6 +291,7 @@
   
   const ACCESSOR &acc;
   const hb_vector_t<hb_codepoint_t> &glyphs;
+  bool  drop_hints;
 };
 
 struct SubrRefMaps
diff --git a/src/hb-subset-cff1.cc b/src/hb-subset-cff1.cc
index 769eb5e..2685934 100644
--- a/src/hb-subset-cff1.cc
+++ b/src/hb-subset-cff1.cc
@@ -104,40 +104,50 @@
   }
 };
 
-struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, ByteStrBuff>
+struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam>
 {
-  static inline bool process_op (OpCode op, CFF1CSInterpEnv &env, ByteStrBuff& flatStr)
+  static inline bool process_op (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param)
   {
-    if (unlikely (!SUPER::process_op (op, env, flatStr)))
+    if (param.drop_hints && CSOPSET::is_hint_op (op))
+    {
+      env.clear_stack ();
+      return true;
+    }
+    if (unlikely (!SUPER::process_op (op, env, param)))
       return false;
     switch (op)
     {
       case OpCode_hintmask:
       case OpCode_cntrmask:
-        if (unlikely (!flatStr.encode_op (op)))
+        if (param.drop_hints)
+        {
+          env.clear_stack ();
+          return true;
+        }
+        if (unlikely (!param.flatStr.encode_op (op)))
           return false;
         for (int i = -env.hintmask_size; i < 0; i++)
-          if (unlikely (!flatStr.encode_byte (env.substr[i])))
+          if (unlikely (!param.flatStr.encode_byte (env.substr[i])))
             return false;
         break;
       default:
         if (!CSOPSET::is_subr_op (op) &&
             !CSOPSET::is_arg_op (op))
-          return flatStr.encode_op (op);
+          return param.flatStr.encode_op (op);
     }
     return true;
   }
 
-  static inline void flush_stack (CFF1CSInterpEnv &env, ByteStrBuff& flatStr)
+  static inline void flush_stack (CFF1CSInterpEnv &env, FlattenParam& param)
   {
     for (unsigned int i = 0; i < env.argStack.size; i++)
-      flatStr.encode_num (env.argStack.elements[i]);
-    SUPER::flush_stack (env, flatStr);
+      param.flatStr.encode_num (env.argStack.elements[i]);
+    SUPER::flush_stack (env, param);
   }
 
   private:
-  typedef CFF1CSOpSet<CFF1CSOpSet_Flatten, ByteStrBuff> SUPER;
-  typedef CSOpSet<CFF1CSOpSet_Flatten, CFF1CSInterpEnv, ByteStrBuff> CSOPSET;
+  typedef CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam> SUPER;
+  typedef CSOpSet<CFF1CSOpSet_Flatten, CFF1CSInterpEnv, FlattenParam> CSOPSET;
 };
 
 struct CFF1CSOpSet_SubsetSubrs : CFF1CSOpSet<CFF1CSOpSet_SubsetSubrs, SubrRefMapPair>
@@ -226,7 +236,8 @@
     if (flatten_subrs)
     {
       /* Flatten global & local subrs */
-      SubrFlattener<const OT::cff1::accelerator_subset_t, CFF1CSInterpEnv, CFF1CSOpSet_Flatten> flattener(acc, plan->glyphs);
+      SubrFlattener<const OT::cff1::accelerator_subset_t, CFF1CSInterpEnv, CFF1CSOpSet_Flatten>
+                    flattener(acc, plan->glyphs, plan->drop_hints);
       if (!flattener.flatten (flat_charstrings))
         return false;
       
diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc
index 59535e6..0edca28 100644
--- a/src/hb-subset-cff2.cc
+++ b/src/hb-subset-cff2.cc
@@ -75,20 +75,30 @@
   }
 };
 
-struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, ByteStrBuff>
+struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam>
 {
-  static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, ByteStrBuff& flatStr)
+  static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param)
   {
-    if (unlikely (!SUPER::process_op (op, env, flatStr)))
+    if (param.drop_hints && CSOPSET::is_hint_op (op))
+    {
+      env.clear_stack ();
+      return true;
+    }
+    if (unlikely (!SUPER::process_op (op, env, param)))
       return false;
     switch (op)
     {
       case OpCode_hintmask:
       case OpCode_cntrmask:
-        if (unlikely (!flatStr.encode_op (op)))
+        if (param.drop_hints)
+        {
+          env.clear_stack ();
+          return true;
+        }
+        if (unlikely (!param.flatStr.encode_op (op)))
           return false;
         for (int i = -env.hintmask_size; i < 0; i++)
-          if (unlikely (!flatStr.encode_byte (env.substr[i])))
+          if (unlikely (!param.flatStr.encode_byte (env.substr[i])))
             return false;
         break;
       case OpCode_return:
@@ -98,33 +108,33 @@
       default:
         if (!CSOPSET::is_subr_op (op) &&
             !CSOPSET::is_arg_op (op))
-          return flatStr.encode_op (op);
+          return param.flatStr.encode_op (op);
     }
     return true;
   }
 
-  static inline bool process_blend (CFF2CSInterpEnv &env, ByteStrBuff& flatStr)
+  static inline bool process_blend (CFF2CSInterpEnv &env, FlattenParam& param)
   {
-    flush_stack (env, flatStr);
+    flush_stack (env, param);
     return true;
   }
 
-  static inline bool process_vsindex (CFF2CSInterpEnv &env, ByteStrBuff& flatStr)
+  static inline bool process_vsindex (CFF2CSInterpEnv &env, FlattenParam& param)
   {
-    flush_stack (env, flatStr);
+    flush_stack (env, param);
     return true;
   }
 
-  static inline void flush_stack (CFF2CSInterpEnv &env, ByteStrBuff& flatStr)
+  static inline void flush_stack (CFF2CSInterpEnv &env, FlattenParam& param)
   {
     for (unsigned int i = 0; i < env.argStack.size; i++)
-      flatStr.encode_num (env.argStack.elements[i]);
-    SUPER::flush_stack (env, flatStr);
+      param.flatStr.encode_num (env.argStack.elements[i]);
+    SUPER::flush_stack (env, param);
   }
 
   private:
-  typedef CFF2CSOpSet<CFF2CSOpSet_Flatten, ByteStrBuff> SUPER;
-  typedef CSOpSet<CFF2CSOpSet_Flatten, CFF2CSInterpEnv, ByteStrBuff> CSOPSET;
+  typedef CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam> SUPER;
+  typedef CSOpSet<CFF2CSOpSet_Flatten, CFF2CSInterpEnv, FlattenParam> CSOPSET;
 };
 
 struct CFF2CSOpSet_SubsetSubrs : CFF2CSOpSet<CFF2CSOpSet_SubsetSubrs, SubrRefMapPair>
@@ -200,7 +210,8 @@
     if (flatten_subrs)
     {
       /* Flatten global & local subrs */
-      SubrFlattener<const OT::cff2::accelerator_subset_t, CFF2CSInterpEnv, CFF2CSOpSet_Flatten> flattener(acc, plan->glyphs);
+      SubrFlattener<const OT::cff2::accelerator_subset_t, CFF2CSInterpEnv, CFF2CSOpSet_Flatten>
+                    flattener(acc, plan->glyphs, plan->drop_hints);
       if (!flattener.flatten (flat_charstrings))
         return false;