make parse_bcd locale free

This commit is contained in:
Michiharu Ariza 2018-09-11 13:24:27 -07:00
parent bb38d0f663
commit 0bd5912a08
1 changed files with 68 additions and 24 deletions

View File

@ -26,8 +26,8 @@
#ifndef HB_CFF_INTERP_DICT_COMMON_HH #ifndef HB_CFF_INTERP_DICT_COMMON_HH
#define HB_CFF_INTERP_DICT_COMMON_HH #define HB_CFF_INTERP_DICT_COMMON_HH
#include "hb-common.h"
#include "hb-cff-interp-common.hh" #include "hb-cff-interp-common.hh"
#include <math.h>
namespace CFF { namespace CFF {
@ -154,43 +154,87 @@ struct DictOpSet : OpSet<Number>
static inline bool parse_bcd (SubByteStr& substr, float& v) static inline bool parse_bcd (SubByteStr& substr, float& v)
{ {
v = 0.0f; v = 0.0f;
hb_vector_t<char, 64> str;
str.init (); bool neg = false;
str.push ('x'); /* hack: disguise a varation option string */ double int_part = 0;
str.push ('='); long frac_part = 0;
unsigned int frac_count = 0;
bool exp_neg = false;
unsigned int exp_part = 0;
enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART;
enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
double value = 0.0;
unsigned char byte = 0; unsigned char byte = 0;
for (unsigned int i = 0; substr.avail (); i++) for (unsigned int i = 0;; i++)
{ {
char c; char d;
if ((i & 1) == 0) if ((i & 1) == 0)
{ {
if (!substr.avail ()) return false;
byte = substr[0]; byte = substr[0];
substr.inc (); substr.inc ();
c = (byte & 0xF0) >> 4; d = byte >> 4;
} }
else else
c = byte & 0x0F; d = byte & 0x0F;
if (c == 0x0F) switch (d)
{ {
hb_variation_t var; case RESERVED:
if (unlikely (!hb_variation_from_string (&str[0], str.len, &var)))
{
str.fini ();
return false; return false;
}
v = var.value;
str.fini ();
return true;
}
else if (c == 0x0D) return false;
str.push ("0123456789.EE - "[c]); case END:
if (c == 0x0C) value = (double)int_part;
str.push ('-'); if (frac_count > 0)
value += (frac_part / pow (10.0, (double)frac_count));
if (exp_part != 0)
{
if (exp_neg)
value /= pow (10.0, (double)exp_part);
else
value *= pow (10.0, (double)exp_part);
}
v = (float)value;
return true;
case NEG:
if (i != 0) return false;
neg = true;
break;
case DECIMAL:
if (part != INT_PART) return false;
part = FRAC_PART;
break;
case EXP_NEG:
exp_neg = true;
/* NO BREAK */
case EXP_POS:
if (part == EXP_PART) return false;
part = EXP_PART;
break;
default:
switch (part) {
default:
case INT_PART:
int_part = (int_part * 10) + d;
break;
case FRAC_PART:
frac_part = (frac_part * 10) + d;
frac_count++;
break;
case EXP_PART:
exp_part = (exp_part * 10) + d;
break;
}
}
} }
str.fini ();
return false; return false;
} }