Merge pull request #1441 from harfbuzz/cff-doublenum

use double as CFF Number implementation
This commit is contained in:
Behdad Esfahbod 2018-12-04 04:14:13 -05:00 committed by GitHub
commit c968869f21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 23 additions and 81 deletions

View File

@ -218,80 +218,41 @@ inline unsigned int OpCode_Size (OpCode op) { return Is_OpCode_ESC (op) ? 2: 1;
struct Number struct Number
{ {
inline void init (void) inline void init (void)
{ set_int (0); } { set_real (0.0); }
inline void fini (void) inline void fini (void)
{} {}
inline void set_int (int v) { format = NumInt; u.int_val = v; } inline void set_int (int v) { value = (double)v; }
inline int to_int (void) const { return is_int ()? u.int_val: (int)to_real (); } inline int to_int (void) const { return (int)value; }
inline void set_fixed (int32_t v) { format = NumFixed; u.fixed_val = v; } inline void set_fixed (int32_t v) { value = v / 65536.0; }
inline int32_t to_fixed (void) const inline int32_t to_fixed (void) const
{ {
if (is_fixed ()) return (int32_t)(value * 65536.0);
return u.fixed_val;
else if (is_real ())
return (int32_t)(u.real_val * 65536.0f);
else
return (int32_t)(u.int_val << 16);
} }
inline void set_real (float v) { format = NumReal; u.real_val = v; } inline void set_real (double v) { value = v; }
inline float to_real (void) const inline double to_real (void) const
{ {
if (is_real ()) return value;
return u.real_val;
if (is_fixed ())
return u.fixed_val / 65536.0f;
else
return (float)u.int_val;
} }
inline int ceil (void) const inline int ceil (void) const
{ {
switch (format) return (int)::ceil (value);
{
default:
case NumInt:
return u.int_val;
case NumFixed:
return (u.fixed_val + 0xFFFF) >> 16;
case NumReal:
return (int)ceilf (u.real_val);
}
} }
inline int floor (void) const inline int floor (void) const
{ {
switch (format) return (int)::floor (value);
{
default:
case NumInt:
return u.int_val;
case NumFixed:
return u.fixed_val >> 16;
case NumReal:
return (int)floorf (u.real_val);
}
} }
inline bool in_int_range (void) const inline bool in_int_range (void) const
{ {
if (is_int ()) return ((double)(int16_t)to_int () == value);
return true;
if (is_fixed () && ((u.fixed_val & 0xFFFF) == 0))
return true;
else
return ((float)(int16_t)to_int () == u.real_val);
} }
inline bool operator > (const Number &n) const inline bool operator > (const Number &n) const
{ {
switch (format) return value > n.to_real ();
{
default:
case NumInt: return u.int_val > n.to_int ();
case NumFixed: return u.fixed_val > n.to_fixed ();
case NumReal: return u.real_val > n.to_real ();
}
} }
inline bool operator < (const Number &n) const inline bool operator < (const Number &n) const
@ -305,32 +266,13 @@ struct Number
inline const Number &operator += (const Number &n) inline const Number &operator += (const Number &n)
{ {
if (format == NumReal || n.format == NumReal)
set_real (to_real () + n.to_real ()); set_real (to_real () + n.to_real ());
else if (format == NumFixed || n.format == NumFixed)
set_fixed (to_fixed () + n.to_fixed ());
else
set_int (to_int () + n.to_int ());
return *this; return *this;
} }
protected: protected:
enum NumFormat { double value;
NumInt,
NumFixed,
NumReal
};
NumFormat format;
union {
int int_val;
int32_t fixed_val;
float real_val;
} u;
inline bool is_int (void) const { return format == NumInt; }
inline bool is_fixed (void) const { return format == NumFixed; }
inline bool is_real (void) const { return format == NumReal; }
}; };
/* byte string */ /* byte string */
@ -578,7 +520,7 @@ struct ArgStack : Stack<ARG, 513>
n.set_fixed (v); n.set_fixed (v);
} }
inline void push_real (float v) inline void push_real (double v)
{ {
ARG &n = S::push (); ARG &n = S::push ();
n.set_real (v); n.set_real (v);

View File

@ -103,9 +103,9 @@ struct DictOpSet : OpSet<Number>
} }
} }
static inline float parse_bcd (SubByteStr& substr) static inline double parse_bcd (SubByteStr& substr)
{ {
float v = 0.0f; double v = 0.0;
bool neg = false; bool neg = false;
double int_part = 0; double int_part = 0;
@ -126,7 +126,7 @@ struct DictOpSet : OpSet<Number>
if (!substr.avail ()) if (!substr.avail ())
{ {
substr.set_error (); substr.set_error ();
return 0.0f; return 0.0;
} }
byte = substr[0]; byte = substr[0];
substr.inc (); substr.inc ();
@ -152,13 +152,13 @@ struct DictOpSet : OpSet<Number>
else else
value *= pow (10.0, (double)exp_part); value *= pow (10.0, (double)exp_part);
} }
return (float)value; return value;
case NEG: case NEG:
if (i != 0) if (i != 0)
{ {
substr.set_error (); substr.set_error ();
return 0.0f; return 0.0;
} }
neg = true; neg = true;
break; break;

View File

@ -49,7 +49,7 @@ struct BlendArg : Number
inline void set_int (int v) { reset_blends (); Number::set_int (v); } inline void set_int (int v) { reset_blends (); Number::set_int (v); }
inline void set_fixed (int32_t v) { reset_blends (); Number::set_fixed (v); } inline void set_fixed (int32_t v) { reset_blends (); Number::set_fixed (v); }
inline void set_real (float v) { reset_blends (); Number::set_real (v); } inline void set_real (double v) { reset_blends (); Number::set_real (v); }
inline void set_blends (unsigned int numValues_, unsigned int valueIndex_, inline void set_blends (unsigned int numValues_, unsigned int valueIndex_,
unsigned int numBlends, const BlendArg *blends_) unsigned int numBlends, const BlendArg *blends_)
@ -169,10 +169,10 @@ struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
{ {
if (likely (scalars.len == arg.deltas.len)) if (likely (scalars.len == arg.deltas.len))
{ {
float v = arg.to_real (); double v = arg.to_real ();
for (unsigned int i = 0; i < scalars.len; i++) for (unsigned int i = 0; i < scalars.len; i++)
{ {
v += scalars[i] * arg.deltas[i].to_real (); v += (double)scalars[i] * arg.deltas[i].to_real ();
} }
arg.set_real (v); arg.set_real (v);
arg.deltas.resize (0); arg.deltas.resize (0);