diff --git a/src/Makefile.sources b/src/Makefile.sources index fde872093..c9883f833 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -243,6 +243,8 @@ HB_ICU_headers = hb-icu.h # Sources for libharfbuzz-subset HB_SUBSET_sources = \ + hb-number.cc \ + hb-number.hh \ hb-ot-cff1-table.cc \ hb-ot-cff2-table.cc \ hb-static.cc \ diff --git a/src/hb-cff-interp-dict-common.hh b/src/hb-cff-interp-dict-common.hh index 1d5df2582..1f03d8239 100644 --- a/src/hb-cff-interp-dict-common.hh +++ b/src/hb-cff-interp-dict-common.hh @@ -94,130 +94,52 @@ struct dict_opset_t : opset_t } } + /* Turns CFF's BCD format into strtod understandable string */ static double parse_bcd (byte_str_ref_t& str_ref) { - bool neg = false; - double int_part = 0; - uint64_t frac_part = 0; - uint32_t frac_count = 0; - bool exp_neg = false; - uint32_t exp_part = 0; - bool exp_overflow = false; - enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART; - enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END }; - const uint64_t MAX_FRACT = 0xFFFFFFFFFFFFFull; /* 1^52-1 */ - const uint32_t MAX_EXP = 0x7FFu; /* 1^11-1 */ + if (unlikely (str_ref.in_error ())) return .0; - double value = 0.0; + enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END }; + + char buf[32]; unsigned char byte = 0; - for (uint32_t i = 0;; i++) + for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count) { - char d; - if ((i & 1) == 0) + unsigned nibble; + if (!(i & 1)) { - if (!str_ref.avail ()) - { - str_ref.set_error (); - return 0.0; - } + if (unlikely (!str_ref.avail ())) break; + byte = str_ref[0]; str_ref.inc (); - d = byte >> 4; + nibble = byte >> 4; } else - d = byte & 0x0F; + nibble = byte & 0x0F; - switch (d) + if (unlikely (nibble == RESERVED)) break; + else if (nibble == END) { - case RESERVED: - str_ref.set_error (); - return value; - - case END: - value = (double) (neg ? -int_part : int_part); - if (frac_count > 0) - { - double frac = frac_part / pow (10.0, (double) frac_count); - if (neg) frac = -frac; - value += frac; - } - if (unlikely (exp_overflow)) - { - if (value == 0.0) - return value; - if (exp_neg) - return neg ? -DBL_MIN : DBL_MIN; - else - return neg ? -DBL_MAX : DBL_MAX; - } - if (exp_part != 0) - { - if (exp_neg) - value /= pow (10.0, (double) exp_part); - else - value *= pow (10.0, (double) exp_part); - } - return value; - - case NEG: - if (i != 0) - { - str_ref.set_error (); - return 0.0; - } - neg = true; + const char *p = buf; + double pv; + if (unlikely (!hb_parse_double (&p, p + count, &pv, true/* whole buffer */))) break; - - case DECIMAL: - if (part != INT_PART) - { - str_ref.set_error (); - return value; - } - part = FRAC_PART; - break; - - case EXP_NEG: - exp_neg = true; - HB_FALLTHROUGH; - - case EXP_POS: - if (part == EXP_PART) - { - str_ref.set_error (); - return value; - } - part = EXP_PART; - break; - - default: - switch (part) { - default: - case INT_PART: - int_part = (int_part * 10) + d; - break; - - case FRAC_PART: - if (likely (frac_part <= MAX_FRACT / 10)) - { - frac_part = (frac_part * 10) + (unsigned)d; - frac_count++; - } - break; - - case EXP_PART: - if (likely (exp_part * 10 + d <= MAX_EXP)) - { - exp_part = (exp_part * 10) + d; - } - else - exp_overflow = true; - break; - } + return pv; + } + else + { + buf[count] = "0123456789.EE?-?"[nibble]; + if (nibble == EXP_NEG) + { + ++count; + if (unlikely (count == ARRAY_LENGTH (buf))) break; + buf[count] = '-'; + } } } - return value; + str_ref.set_error (); + return .0; } static bool is_hint_op (op_code_t op)