Implement parse_bcd
authorMichiharu Ariza <ariza@adobe.com>
Tue, 11 Sep 2018 17:43:15 +0000 (10:43 -0700)
committerMichiharu Ariza <ariza@adobe.com>
Tue, 11 Sep 2018 17:43:15 +0000 (10:43 -0700)
src/hb-cff-interp-common.hh
src/hb-cff-interp-dict-common.hh

index 5b3477e..ea70209 100644 (file)
@@ -371,21 +371,6 @@ struct SubByteStr
   unsigned int  offset; /* beginning of the sub-string within str */
 };
 
-inline float parse_bcd (SubByteStr& substr, float& v)
-{
-  // XXX: TODO
-  v = 0;
-  for (;;) {
-    if (!substr.avail ())
-      return false;
-    unsigned char byte = substr[0];
-    substr.inc ();
-    if (((byte & 0xF0) == 0xF0) || ((byte & 0x0F) == 0x0F))
-      break;
-  }
-  return true;
-}
-
 /* stack */
 template <typename ELEM, int LIMIT>
 struct Stack
index f33ec9a..aaa8622 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef HB_CFF_INTERP_DICT_COMMON_HH
 #define HB_CFF_INTERP_DICT_COMMON_HH
 
+#include "hb-common.h"
 #include "hb-cff-interp-common.hh"
 
 namespace CFF {
@@ -150,6 +151,49 @@ struct DictOpSet : OpSet<Number>
     return true;
   }
 
+  static inline bool parse_bcd (SubByteStr& substr, float& v)
+  {
+    v = 0.0f;
+    hb_vector_t<char, 64> str;
+
+    str.init ();
+    str.push ('x'); /* hack: disguise a varation option string */
+    str.push ('=');
+    unsigned char byte = 0;
+    for (unsigned int i = 0; substr.avail (); i++)
+    {
+      char c;
+      if ((i & 1) == 0)
+      {
+        byte = substr[0];
+        substr.inc ();
+        c = (byte & 0xF0) >> 4;
+      }
+      else
+        c = byte & 0x0F;
+
+      if (c == 0x0F)
+      {
+        hb_variation_t  var;
+        if (unlikely (!hb_variation_from_string (&str[0], str.len, &var)))
+        {
+          str.fini ();
+          return false;
+        }
+        v = var.value;
+        str.fini ();
+        return true;
+      }
+      else if (c == 0x0D) return false;
+      
+      str.push ("0123456789.EE - "[c]);
+      if (c == 0x0C)
+        str.push ('-');
+    }
+    str.fini ();
+    return false;
+  }
+
   static inline bool is_hint_op (OpCode op)
   {
     switch (op)