added CFF2 get_extents
added source hb-ot-cff2-table.cc augmented VariationData to return scalars misc bug fixes, renaming, cleanup
This commit is contained in:
parent
55942ad5c1
commit
b51418f596
|
@ -30,6 +30,7 @@ HB_BASE_sources = \
|
|||
hb-ot-cff1-table.hh \
|
||||
hb-ot-cff1-table.cc \
|
||||
hb-ot-cff2-table.hh \
|
||||
hb-ot-cff2-table.cc \
|
||||
hb-ot-vorg-table.hh \
|
||||
hb-ot-hdmx-table.hh \
|
||||
hb-ot-head-table.hh \
|
||||
|
@ -227,6 +228,7 @@ HB_SUBSET_sources = \
|
|||
hb-subset-cff2.cc \
|
||||
hb-subset-cff-common.cc \
|
||||
hb-ot-cff1-table.cc \
|
||||
hb-ot-cff2-table.cc \
|
||||
hb-subset-input.cc \
|
||||
hb-subset-input.hh \
|
||||
hb-subset-plan.cc \
|
||||
|
|
|
@ -298,19 +298,13 @@ struct Number
|
|||
|
||||
inline const Number &operator += (const Number &n)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
default:
|
||||
case NumInt:
|
||||
u.int_val += n.to_int ();
|
||||
break;
|
||||
case NumFixed:
|
||||
u.fixed_val += n.to_fixed ();
|
||||
break;
|
||||
case NumReal:
|
||||
u.real_val += n.to_real ();
|
||||
break;
|
||||
}
|
||||
if (format == NumReal || n.format == NumReal)
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -453,8 +447,7 @@ struct Stack
|
|||
|
||||
inline void fini (void)
|
||||
{
|
||||
for (unsigned int i = 0; i < elements.len; i++)
|
||||
elements[i].fini ();
|
||||
elements.fini_deep ();
|
||||
}
|
||||
|
||||
inline const ELEM& operator [] (unsigned int i) const
|
||||
|
@ -477,12 +470,12 @@ struct Stack
|
|||
return Crap(ELEM);
|
||||
}
|
||||
|
||||
inline const ELEM& pop (void)
|
||||
inline ELEM& pop (void)
|
||||
{
|
||||
if (likely (count > 0))
|
||||
return elements[--count];
|
||||
else
|
||||
return Null(ELEM);
|
||||
return Crap(ELEM);
|
||||
}
|
||||
|
||||
inline void pop (unsigned int n)
|
||||
|
@ -678,6 +671,16 @@ struct InterpEnv
|
|||
return true;
|
||||
}
|
||||
|
||||
inline const ARG& eval_arg (unsigned int i)
|
||||
{
|
||||
return argStack[i];
|
||||
}
|
||||
|
||||
inline ARG& pop_arg (void)
|
||||
{
|
||||
return argStack.pop ();
|
||||
}
|
||||
|
||||
inline void pop_n_args (unsigned int n)
|
||||
{
|
||||
assert (n <= argStack.get_count ());
|
||||
|
|
|
@ -154,19 +154,19 @@ struct CSInterpEnv : InterpEnv<ARG>
|
|||
|
||||
inline unsigned int move_x_with_arg (unsigned int i)
|
||||
{
|
||||
pt.move_x (SUPER::argStack[i]);
|
||||
pt.move_x (SUPER::eval_arg (i));
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
inline unsigned int move_y_with_arg (unsigned int i)
|
||||
{
|
||||
pt.move_y (SUPER::argStack[i]);
|
||||
pt.move_y (SUPER::eval_arg (i));
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
inline unsigned int move_xy_with_arg (unsigned int i)
|
||||
{
|
||||
pt.move (SUPER::argStack[i], SUPER::argStack[i+1]);
|
||||
pt.move (SUPER::eval_arg (i), SUPER::eval_arg (i+1));
|
||||
return i + 2;
|
||||
}
|
||||
|
||||
|
@ -382,8 +382,8 @@ struct PathProcs
|
|||
static inline void rmoveto (ENV &env, PARAM& param)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
const Number &dy = env.argStack.pop ();
|
||||
const Number &dx = env.argStack.pop ();
|
||||
const Number &dy = env.pop_arg ();
|
||||
const Number &dx = env.pop_arg ();
|
||||
pt1.move (dx, dy);
|
||||
PATH::moveto (env, param, pt1);
|
||||
}
|
||||
|
@ -391,14 +391,14 @@ struct PathProcs
|
|||
static inline void hmoveto (ENV &env, PARAM& param)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move_x (env.argStack.pop ());
|
||||
pt1.move_x (env.pop_arg ());
|
||||
PATH::moveto (env, param, pt1);
|
||||
}
|
||||
|
||||
static inline void vmoveto (ENV &env, PARAM& param)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move_y (env.argStack.pop ());
|
||||
pt1.move_y (env.pop_arg ());
|
||||
PATH::moveto (env, param, pt1);
|
||||
}
|
||||
|
||||
|
@ -407,7 +407,7 @@ struct PathProcs
|
|||
for (unsigned int i = 0; i + 2 <= env.argStack.get_count (); i += 2)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move (env.argStack[i], env.argStack[i+1]);
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
}
|
||||
|
@ -419,15 +419,15 @@ struct PathProcs
|
|||
for (; i + 2 <= env.argStack.get_count (); i += 2)
|
||||
{
|
||||
pt1 = env.get_pt ();
|
||||
pt1.move_x (env.argStack[i]);
|
||||
pt1.move_x (env.eval_arg (i));
|
||||
PATH::line (env, param, pt1);
|
||||
pt1.move_y (env.argStack[i+1]);
|
||||
pt1.move_y (env.eval_arg (i+1));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
if (i < env.argStack.get_count ())
|
||||
{
|
||||
pt1 = env.get_pt ();
|
||||
pt1.move_x (env.argStack[i]);
|
||||
pt1.move_x (env.eval_arg (i));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
}
|
||||
|
@ -439,15 +439,15 @@ struct PathProcs
|
|||
for (; i + 2 <= env.argStack.get_count (); i += 2)
|
||||
{
|
||||
pt1 = env.get_pt ();
|
||||
pt1.move_y (env.argStack[i]);
|
||||
pt1.move_y (env.eval_arg (i));
|
||||
PATH::line (env, param, pt1);
|
||||
pt1.move_x (env.argStack[i+1]);
|
||||
pt1.move_x (env.eval_arg (i+1));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
if (i < env.argStack.get_count ())
|
||||
{
|
||||
pt1 = env.get_pt ();
|
||||
pt1.move_y (env.argStack[i]);
|
||||
pt1.move_y (env.eval_arg (i));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
}
|
||||
|
@ -457,11 +457,11 @@ struct PathProcs
|
|||
for (unsigned int i = 0; i + 6 <= env.argStack.get_count (); i += 6)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move (env.argStack[i], env.argStack[i+1]);
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
Point pt2 = pt1;
|
||||
pt2.move (env.argStack[i+2], env.argStack[i+3]);
|
||||
pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
|
||||
Point pt3 = pt2;
|
||||
pt3.move (env.argStack[i+4], env.argStack[i+5]);
|
||||
pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
}
|
||||
|
@ -472,17 +472,17 @@ struct PathProcs
|
|||
for (; i + 6 <= env.argStack.get_count (); i += 6)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move (env.argStack[i], env.argStack[i+1]);
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
Point pt2 = pt1;
|
||||
pt2.move (env.argStack[i+2], env.argStack[i+3]);
|
||||
pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
|
||||
Point pt3 = pt2;
|
||||
pt3.move (env.argStack[i+4], env.argStack[i+5]);
|
||||
pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
for (; i + 2 <= env.argStack.get_count (); i += 2)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move (env.argStack[i], env.argStack[i+1]);
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
}
|
||||
|
@ -494,17 +494,17 @@ struct PathProcs
|
|||
for (; i + 2 <= line_limit; i += 2)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move (env.argStack[i], env.argStack[i+1]);
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
PATH::line (env, param, pt1);
|
||||
}
|
||||
for (; i + 6 <= env.argStack.get_count (); i += 6)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move (env.argStack[i], env.argStack[i+1]);
|
||||
pt1.move (env.eval_arg (i), env.eval_arg (i+1));
|
||||
Point pt2 = pt1;
|
||||
pt2.move (env.argStack[i+2], env.argStack[i+3]);
|
||||
pt2.move (env.eval_arg (i+2), env.eval_arg (i+3));
|
||||
Point pt3 = pt2;
|
||||
pt3.move (env.argStack[i+4], env.argStack[i+5]);
|
||||
pt3.move (env.eval_arg (i+4), env.eval_arg (i+5));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
}
|
||||
|
@ -514,14 +514,14 @@ struct PathProcs
|
|||
unsigned int i = 0;
|
||||
Point pt1 = env.get_pt ();
|
||||
if ((env.argStack.get_count () & 1) != 0)
|
||||
pt1.move_x (env.argStack[i++]);
|
||||
pt1.move_x (env.eval_arg (i++));
|
||||
for (; i + 4 <= env.argStack.get_count (); i += 4)
|
||||
{
|
||||
pt1.move_y (env.argStack[i]);
|
||||
pt1.move_y (env.eval_arg (i));
|
||||
Point pt2 = pt1;
|
||||
pt2.move (env.argStack[i+1], env.argStack[i+2]);
|
||||
pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
|
||||
Point pt3 = pt2;
|
||||
pt3.move_y (env.argStack[i+3]);
|
||||
pt3.move_y (env.eval_arg (i+3));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
pt1 = env.get_pt ();
|
||||
}
|
||||
|
@ -532,14 +532,14 @@ struct PathProcs
|
|||
unsigned int i = 0;
|
||||
Point pt1 = env.get_pt ();
|
||||
if ((env.argStack.get_count () & 1) != 0)
|
||||
pt1.move_y (env.argStack[i++]);
|
||||
pt1.move_y (env.eval_arg (i++));
|
||||
for (; i + 4 <= env.argStack.get_count (); i += 4)
|
||||
{
|
||||
pt1.move_x (env.argStack[i]);
|
||||
pt1.move_x (env.eval_arg (i));
|
||||
Point pt2 = pt1;
|
||||
pt2.move (env.argStack[i+1], env.argStack[i+2]);
|
||||
pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
|
||||
Point pt3 = pt2;
|
||||
pt3.move_x (env.argStack[i+3]);
|
||||
pt3.move_x (env.eval_arg (i+3));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
pt1 = env.get_pt ();
|
||||
}
|
||||
|
@ -552,33 +552,33 @@ struct PathProcs
|
|||
if ((env.argStack.get_count () % 8) >= 4)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move_y (env.argStack[i]);
|
||||
pt1.move_y (env.eval_arg (i));
|
||||
Point pt2 = pt1;
|
||||
pt2.move (env.argStack[i+1], env.argStack[i+2]);
|
||||
pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
|
||||
Point pt3 = pt2;
|
||||
pt3.move_x (env.argStack[i+3]);
|
||||
pt3.move_x (env.eval_arg (i+3));
|
||||
i += 4;
|
||||
|
||||
for (; i + 8 <= env.argStack.get_count (); i += 8)
|
||||
{
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
pt1 = env.get_pt ();
|
||||
pt1.move_x (env.argStack[i]);
|
||||
pt1.move_x (env.eval_arg (i));
|
||||
pt2 = pt1;
|
||||
pt2.move (env.argStack[i+1], env.argStack[i+2]);
|
||||
pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
|
||||
pt3 = pt2;
|
||||
pt3.move_y (env.argStack[i+3]);
|
||||
pt3.move_y (env.eval_arg (i+3));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
|
||||
pt1 = pt3;
|
||||
pt1.move_y (env.argStack[i+4]);
|
||||
pt1.move_y (env.eval_arg (i+4));
|
||||
pt2 = pt1;
|
||||
pt2.move (env.argStack[i+5], env.argStack[i+6]);
|
||||
pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
|
||||
pt3 = pt2;
|
||||
pt3.move_x (env.argStack[i+7]);
|
||||
pt3.move_x (env.eval_arg (i+7));
|
||||
}
|
||||
if (i < env.argStack.get_count ())
|
||||
pt3.move_y (env.argStack[i]);
|
||||
pt3.move_y (env.eval_arg (i));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
else
|
||||
|
@ -586,21 +586,21 @@ struct PathProcs
|
|||
for (; i + 8 <= env.argStack.get_count (); i += 8)
|
||||
{
|
||||
pt1 = env.get_pt ();
|
||||
pt1.move_y (env.argStack[i]);
|
||||
pt1.move_y (env.eval_arg (i));
|
||||
pt2 = pt1;
|
||||
pt2.move (env.argStack[i+1], env.argStack[i+2]);
|
||||
pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
|
||||
pt3 = pt2;
|
||||
pt3.move_x (env.argStack[i+3]);
|
||||
pt3.move_x (env.eval_arg (i+3));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
|
||||
pt1 = pt3;
|
||||
pt1.move_x (env.argStack[i+4]);
|
||||
pt1.move_x (env.eval_arg (i+4));
|
||||
pt2 = pt1;
|
||||
pt2.move (env.argStack[i+5], env.argStack[i+6]);
|
||||
pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
|
||||
pt3 = pt2;
|
||||
pt3.move_y (env.argStack[i+7]);
|
||||
pt3.move_y (env.eval_arg (i+7));
|
||||
if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0))
|
||||
pt3.move_x (env.argStack[i+8]);
|
||||
pt3.move_x (env.eval_arg (i+8));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
}
|
||||
|
@ -613,33 +613,33 @@ struct PathProcs
|
|||
if ((env.argStack.get_count () % 8) >= 4)
|
||||
{
|
||||
Point pt1 = env.get_pt ();
|
||||
pt1.move_x (env.argStack[i]);
|
||||
pt1.move_x (env.eval_arg (i));
|
||||
Point pt2 = pt1;
|
||||
pt2.move (env.argStack[i+1], env.argStack[i+2]);
|
||||
pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
|
||||
Point pt3 = pt2;
|
||||
pt3.move_y (env.argStack[i+3]);
|
||||
pt3.move_y (env.eval_arg (i+3));
|
||||
i += 4;
|
||||
|
||||
for (; i + 8 <= env.argStack.get_count (); i += 8)
|
||||
{
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
pt1 = env.get_pt ();
|
||||
pt1.move_y (env.argStack[i]);
|
||||
pt1.move_y (env.eval_arg (i));
|
||||
pt2 = pt1;
|
||||
pt2.move (env.argStack[i+1], env.argStack[i+2]);
|
||||
pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
|
||||
pt3 = pt2;
|
||||
pt3.move_x (env.argStack[i+3]);
|
||||
pt3.move_x (env.eval_arg (i+3));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
|
||||
pt1 = pt3;
|
||||
pt1.move_x (env.argStack[i+4]);
|
||||
pt1.move_x (env.eval_arg (i+4));
|
||||
pt2 = pt1;
|
||||
pt2.move (env.argStack[i+5], env.argStack[i+6]);
|
||||
pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
|
||||
pt3 = pt2;
|
||||
pt3.move_y (env.argStack[i+7]);
|
||||
pt3.move_y (env.eval_arg (i+7));
|
||||
}
|
||||
if (i < env.argStack.get_count ())
|
||||
pt3.move_x (env.argStack[i]);
|
||||
pt3.move_x (env.eval_arg (i));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
else
|
||||
|
@ -647,21 +647,21 @@ struct PathProcs
|
|||
for (; i + 8 <= env.argStack.get_count (); i += 8)
|
||||
{
|
||||
pt1 = env.get_pt ();
|
||||
pt1.move_x (env.argStack[i]);
|
||||
pt1.move_x (env.eval_arg (i));
|
||||
pt2 = pt1;
|
||||
pt2.move (env.argStack[i+1], env.argStack[i+2]);
|
||||
pt2.move (env.eval_arg (i+1), env.eval_arg (i+2));
|
||||
pt3 = pt2;
|
||||
pt3.move_y (env.argStack[i+3]);
|
||||
pt3.move_y (env.eval_arg (i+3));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
|
||||
pt1 = pt3;
|
||||
pt1.move_y (env.argStack[i+4]);
|
||||
pt1.move_y (env.eval_arg (i+4));
|
||||
pt2 = pt1;
|
||||
pt2.move (env.argStack[i+5], env.argStack[i+6]);
|
||||
pt2.move (env.eval_arg (i+5), env.eval_arg (i+6));
|
||||
pt3 = pt2;
|
||||
pt3.move_x (env.argStack[i+7]);
|
||||
pt3.move_x (env.eval_arg (i+7));
|
||||
if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0))
|
||||
pt3.move_y (env.argStack[i+8]);
|
||||
pt3.move_y (env.eval_arg (i+8));
|
||||
PATH::curve (env, param, pt1, pt2, pt3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,11 +64,7 @@ struct DictValues
|
|||
|
||||
inline void fini (void)
|
||||
{
|
||||
for (unsigned int i = 0; i < values.len; i++)
|
||||
{
|
||||
values[i].fini ();
|
||||
}
|
||||
values.fini ();
|
||||
values.fini_deep ();
|
||||
}
|
||||
|
||||
inline void addOp (OpCode op, const SubByteStr& substr = SubByteStr ())
|
||||
|
|
|
@ -44,10 +44,7 @@ struct BlendArg : Number
|
|||
inline void fini (void)
|
||||
{
|
||||
Number::fini ();
|
||||
|
||||
for (unsigned int i = 0; i < deltas.len; i++)
|
||||
deltas[i].fini ();
|
||||
deltas.fini ();
|
||||
deltas.fini_deep ();
|
||||
}
|
||||
|
||||
inline void set_int (int v) { reset_blends (); Number::set_int (v); }
|
||||
|
@ -64,7 +61,7 @@ struct BlendArg : Number
|
|||
deltas[i] = blends_[i];
|
||||
}
|
||||
|
||||
inline bool blended (void) const { return deltas.len > 0; }
|
||||
inline bool blending (void) const { return deltas.len > 0; }
|
||||
inline void reset_blends (void)
|
||||
{
|
||||
numValues = valueIndex = 0;
|
||||
|
@ -81,11 +78,26 @@ typedef InterpEnv<BlendArg> BlendInterpEnv;
|
|||
struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
|
||||
{
|
||||
template <typename ACC>
|
||||
inline void init (const ByteStr &str, ACC &acc, unsigned int fd)
|
||||
inline void init (const ByteStr &str, ACC &acc, unsigned int fd,
|
||||
const int *coords_=nullptr, unsigned int coords_count_=0,
|
||||
const CFF2VariationStore *varStore_=nullptr)
|
||||
{
|
||||
SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
||||
set_region_count (acc.region_count);
|
||||
set_vsindex (acc.privateDicts[fd].vsindex);
|
||||
|
||||
coords = coords_;
|
||||
num_coords = coords_count_;
|
||||
varStore = varStore_;
|
||||
seen_blend = false;
|
||||
seen_vsindex = false;
|
||||
scalars.init ();
|
||||
do_blend = (coords != nullptr) && num_coords && (varStore != &Null(CFF2VariationStore));
|
||||
set_ivs (acc.privateDicts[fd].ivs);
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
scalars.fini ();
|
||||
SUPER::fini ();
|
||||
}
|
||||
|
||||
inline bool fetch_op (OpCode &op)
|
||||
|
@ -101,25 +113,80 @@ struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
|
|||
return true;
|
||||
}
|
||||
|
||||
inline const BlendArg& eval_arg (unsigned int i)
|
||||
{
|
||||
return blend_arg (argStack[i]);
|
||||
}
|
||||
|
||||
inline const BlendArg& pop_arg (void)
|
||||
{
|
||||
return blend_arg (argStack.pop ());
|
||||
}
|
||||
|
||||
inline void process_blend (void)
|
||||
{
|
||||
if (!seen_blend)
|
||||
{
|
||||
region_count = varStore->varStore.get_region_index_count (get_ivs ());
|
||||
if (do_blend)
|
||||
{
|
||||
scalars.resize (region_count);
|
||||
varStore->varStore.get_scalars (get_ivs (),
|
||||
(int *)coords, num_coords,
|
||||
&scalars[0], region_count);
|
||||
}
|
||||
seen_blend = true;
|
||||
}
|
||||
}
|
||||
|
||||
inline void process_vsindex (void)
|
||||
{
|
||||
unsigned int index;
|
||||
if (likely (argStack.check_pop_uint (index)))
|
||||
set_vsindex (argStack.check_pop_uint (index));
|
||||
if (do_blend)
|
||||
{
|
||||
unsigned int index;
|
||||
if (likely (!seen_vsindex && !seen_blend && argStack.check_pop_uint (index)))
|
||||
set_ivs (argStack.check_pop_uint (index));
|
||||
}
|
||||
seen_vsindex = true;
|
||||
}
|
||||
|
||||
inline unsigned int get_region_count (void) const { return region_count; }
|
||||
inline void set_region_count (unsigned int region_count_) { region_count = region_count_; }
|
||||
inline unsigned int get_vsindex (void) const { return vsindex; }
|
||||
inline void set_vsindex (unsigned int vsindex_) { vsindex = vsindex_; }
|
||||
inline unsigned int get_ivs (void) const { return ivs; }
|
||||
inline void set_ivs (unsigned int ivs_) { ivs = ivs_; }
|
||||
|
||||
protected:
|
||||
inline BlendArg& blend_arg (BlendArg &arg)
|
||||
{
|
||||
if (do_blend && arg.blending ())
|
||||
{
|
||||
if (likely (scalars.len == arg.deltas.len))
|
||||
{
|
||||
float v = arg.to_real ();
|
||||
for (unsigned int i = 0; i < scalars.len; i++)
|
||||
{
|
||||
v += scalars[i] * arg.deltas[i].to_real ();
|
||||
}
|
||||
arg.set_real (v);
|
||||
arg.deltas.resize (0);
|
||||
}
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
protected:
|
||||
const int *coords;
|
||||
unsigned int num_coords;
|
||||
const CFF2VariationStore *varStore;
|
||||
unsigned int region_count;
|
||||
unsigned int vsindex;
|
||||
unsigned int ivs;
|
||||
hb_vector_t<float> scalars;
|
||||
bool do_blend;
|
||||
bool seen_vsindex;
|
||||
bool seen_blend;
|
||||
|
||||
typedef CSInterpEnv<BlendArg, CFF2Subrs> SUPER;
|
||||
};
|
||||
|
||||
template <typename OPSET, typename PARAM, typename PATH=PathProcsNull<CFF2CSInterpEnv, PARAM> >
|
||||
struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
|
||||
{
|
||||
|
@ -129,7 +196,7 @@ struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
|
|||
case OpCode_callsubr:
|
||||
case OpCode_callgsubr:
|
||||
/* a subroutine number shoudln't be a blended value */
|
||||
if (unlikely (env.argStack.peek ().blended ()))
|
||||
if (unlikely (env.argStack.peek ().blending ()))
|
||||
return false;
|
||||
return SUPER::process_op (op, env, param);
|
||||
|
||||
|
@ -137,7 +204,7 @@ struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
|
|||
return OPSET::process_blend (env, param);
|
||||
|
||||
case OpCode_vsindexcs:
|
||||
if (unlikely (env.argStack.peek ().blended ()))
|
||||
if (unlikely (env.argStack.peek ().blending ()))
|
||||
return false;
|
||||
OPSET::process_vsindex (env, param);
|
||||
break;
|
||||
|
@ -152,6 +219,7 @@ struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
|
|||
{
|
||||
unsigned int n, k;
|
||||
|
||||
env.process_blend ();
|
||||
k = env.get_region_count ();
|
||||
if (unlikely (!env.argStack.check_pop_uint (n) ||
|
||||
(k+1) * n > env.argStack.get_count ()))
|
||||
|
|
|
@ -1093,9 +1093,7 @@ struct cff1
|
|||
sc.end_processing ();
|
||||
topDict.fini ();
|
||||
fontDicts.fini ();
|
||||
for (unsigned int i = 0; i < privateDicts.len; i++)
|
||||
privateDicts[i].fini ();
|
||||
privateDicts.fini ();
|
||||
privateDicts.fini_deep ();
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright © 2018 Adobe Systems Incorporated.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Adobe Author(s): Michiharu Ariza
|
||||
*/
|
||||
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
#include "hb-cff2-interp-cs.hh"
|
||||
|
||||
using namespace CFF;
|
||||
|
||||
struct ExtentsParam
|
||||
{
|
||||
inline void init (void)
|
||||
{
|
||||
path_open = false;
|
||||
min_x.set_int (0x7FFFFFFF);
|
||||
min_y.set_int (0x7FFFFFFF);
|
||||
max_x.set_int (-0x80000000);
|
||||
max_y.set_int (-0x80000000);
|
||||
}
|
||||
|
||||
inline void start_path (void) { path_open = true; }
|
||||
inline void end_path (void) { path_open = false; }
|
||||
inline bool is_path_open (void) const { return path_open; }
|
||||
|
||||
inline void update_bounds (const Point &pt)
|
||||
{
|
||||
if (pt.x < min_x) min_x = pt.x;
|
||||
if (pt.x > max_x) max_x = pt.x;
|
||||
if (pt.y < min_y) min_y = pt.y;
|
||||
if (pt.y > max_y) max_y = pt.y;
|
||||
}
|
||||
|
||||
bool path_open;
|
||||
Number min_x;
|
||||
Number min_y;
|
||||
Number max_x;
|
||||
Number max_y;
|
||||
};
|
||||
|
||||
struct CFF2PathProcs_Extents : PathProcs<CFF2PathProcs_Extents, CFF2CSInterpEnv, ExtentsParam>
|
||||
{
|
||||
static inline void moveto (CFF2CSInterpEnv &env, ExtentsParam& param, const Point &pt)
|
||||
{
|
||||
param.end_path ();
|
||||
env.moveto (pt);
|
||||
}
|
||||
|
||||
static inline void line (CFF2CSInterpEnv &env, ExtentsParam& param, const Point &pt1)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
param.start_path ();
|
||||
param.update_bounds (env.get_pt ());
|
||||
}
|
||||
env.moveto (pt1);
|
||||
param.update_bounds (env.get_pt ());
|
||||
}
|
||||
|
||||
static inline void curve (CFF2CSInterpEnv &env, ExtentsParam& param, const Point &pt1, const Point &pt2, const Point &pt3)
|
||||
{
|
||||
if (!param.is_path_open ())
|
||||
{
|
||||
param.start_path ();
|
||||
param.update_bounds (env.get_pt ());
|
||||
}
|
||||
/* include control points */
|
||||
param.update_bounds (pt1);
|
||||
param.update_bounds (pt2);
|
||||
env.moveto (pt3);
|
||||
param.update_bounds (env.get_pt ());
|
||||
}
|
||||
};
|
||||
|
||||
struct CFF2CSOpSet_Extents : CFF2CSOpSet<CFF2CSOpSet_Extents, ExtentsParam, CFF2PathProcs_Extents> {};
|
||||
|
||||
bool OT::cff2::accelerator_t::get_extents (hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
const int *coords,
|
||||
unsigned int num_coords) const
|
||||
{
|
||||
if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
|
||||
|
||||
unsigned int fd = fdSelect->get_fd (glyph);
|
||||
CFF2CSInterpreter<CFF2CSOpSet_Extents, ExtentsParam> interp;
|
||||
const ByteStr str = (*charStrings)[glyph];
|
||||
interp.env.init (str, *this, fd, coords, num_coords, varStore);
|
||||
ExtentsParam param;
|
||||
param.init ();
|
||||
if (unlikely (!interp.interpret (param))) return false;
|
||||
|
||||
if (param.min_x >= param.max_x)
|
||||
{
|
||||
extents->width = 0;
|
||||
extents->x_bearing = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
extents->x_bearing = (int32_t)param.min_x.floor ();
|
||||
extents->width = (int32_t)param.max_x.ceil () - extents->x_bearing;
|
||||
}
|
||||
if (param.min_y >= param.max_y)
|
||||
{
|
||||
extents->height = 0;
|
||||
extents->y_bearing = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
extents->y_bearing = (int32_t)param.max_y.ceil ();
|
||||
extents->height = (int32_t)param.min_y.floor () - extents->y_bearing;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -265,7 +265,7 @@ struct CFF2PrivateDictValues_Base : DictValues<VAL>
|
|||
DictValues<VAL>::init ();
|
||||
subrsOffset = 0;
|
||||
localSubrs = &Null(CFF2Subrs);
|
||||
vsindex = 0;
|
||||
ivs = 0;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
|
@ -286,15 +286,42 @@ struct CFF2PrivateDictValues_Base : DictValues<VAL>
|
|||
|
||||
unsigned int subrsOffset;
|
||||
const CFF2Subrs *localSubrs;
|
||||
unsigned int vsindex;
|
||||
unsigned int ivs;
|
||||
};
|
||||
|
||||
typedef CFF2PrivateDictValues_Base<OpStr> CFF2PrivateDictValues_Subset;
|
||||
typedef CFF2PrivateDictValues_Base<NumDictVal> CFF2PrivateDictValues;
|
||||
|
||||
struct CFF2PrivDictInterpEnv : NumInterpEnv
|
||||
{
|
||||
inline void init (const ByteStr &str)
|
||||
{
|
||||
NumInterpEnv::init (str);
|
||||
ivs = 0;
|
||||
seen_vsindex = false;
|
||||
}
|
||||
|
||||
inline void process_vsindex (void)
|
||||
{
|
||||
unsigned int index;
|
||||
if (likely (!seen_vsindex && argStack.check_pop_uint (index)))
|
||||
{
|
||||
set_ivs (argStack.check_pop_uint (index));
|
||||
}
|
||||
seen_vsindex = true;
|
||||
}
|
||||
|
||||
inline unsigned int get_ivs (void) const { return ivs; }
|
||||
inline void set_ivs (unsigned int ivs_) { ivs = ivs_; }
|
||||
|
||||
protected:
|
||||
unsigned int ivs;
|
||||
bool seen_vsindex;
|
||||
};
|
||||
|
||||
struct CFF2PrivateDictOpSet : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF2PrivateDictValues& dictval)
|
||||
static inline bool process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues& dictval)
|
||||
{
|
||||
NumDictVal val;
|
||||
val.init ();
|
||||
|
@ -327,8 +354,8 @@ struct CFF2PrivateDictOpSet : DictOpSet
|
|||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_vsindexdict:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.vsindex)))
|
||||
return false;
|
||||
env.process_vsindex ();
|
||||
dictval.ivs = env.get_ivs ();
|
||||
break;
|
||||
case OpCode_blenddict:
|
||||
break;
|
||||
|
@ -347,7 +374,7 @@ struct CFF2PrivateDictOpSet : DictOpSet
|
|||
|
||||
struct CFF2PrivateDictOpSet_Subset : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF2PrivateDictValues_Subset& dictval)
|
||||
static inline bool process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues_Subset& dictval)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_BlueValues:
|
||||
|
@ -455,11 +482,6 @@ struct cff2
|
|||
if (num_glyphs != sc.get_num_glyphs ())
|
||||
{ fini (); return; }
|
||||
|
||||
if (varStore != &Null(CFF2VariationStore))
|
||||
region_count = varStore->varStore.get_region_count ();
|
||||
else
|
||||
region_count = 0;
|
||||
|
||||
fdCount = fdArray->count;
|
||||
privateDicts.resize (fdCount);
|
||||
|
||||
|
@ -476,7 +498,7 @@ struct cff2
|
|||
|
||||
const ByteStr privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
|
||||
if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
|
||||
DictInterpreter<PRIVOPSET, PRIVDICTVAL> priv_interp;
|
||||
DictInterpreter<PRIVOPSET, PRIVDICTVAL, CFF2PrivDictInterpEnv> priv_interp;
|
||||
priv_interp.env.init(privDictStr);
|
||||
if (unlikely (!priv_interp.interpret (privateDicts[i]))) { fini (); return; }
|
||||
|
||||
|
@ -491,25 +513,13 @@ struct cff2
|
|||
{
|
||||
sc.end_processing ();
|
||||
fontDicts.fini ();
|
||||
for (unsigned int i = 0; i < privateDicts.len; i++)
|
||||
privateDicts[i].fini ();
|
||||
privateDicts.fini ();
|
||||
privateDicts.fini_deep ();
|
||||
hb_blob_destroy (blob);
|
||||
blob = nullptr;
|
||||
}
|
||||
|
||||
inline bool is_valid (void) const { return blob != nullptr; }
|
||||
|
||||
inline bool get_extents (hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{
|
||||
// XXX: TODO
|
||||
if (glyph >= num_glyphs)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
hb_blob_t *blob;
|
||||
hb_sanitize_context_t sc;
|
||||
|
@ -527,10 +537,16 @@ struct cff2
|
|||
hb_vector_t<PRIVDICTVAL> privateDicts;
|
||||
|
||||
unsigned int num_glyphs;
|
||||
unsigned int region_count;
|
||||
};
|
||||
|
||||
typedef accelerator_templ_t<CFF2PrivateDictOpSet, CFF2PrivateDictValues> accelerator_t;
|
||||
struct accelerator_t : accelerator_templ_t<CFF2PrivateDictOpSet, CFF2PrivateDictValues>
|
||||
{
|
||||
HB_INTERNAL bool get_extents (hb_codepoint_t glyph,
|
||||
hb_glyph_extents_t *extents,
|
||||
const int *coords,
|
||||
unsigned int num_coords) const;
|
||||
};
|
||||
|
||||
typedef accelerator_templ_t<CFF2PrivateDictOpSet_Subset, CFF2PrivateDictValues_Subset> accelerator_subset_t;
|
||||
|
||||
inline bool subset (hb_subset_plan_t *plan) const
|
||||
|
@ -560,6 +576,7 @@ struct cff2
|
|||
DEFINE_SIZE_STATIC (5);
|
||||
};
|
||||
|
||||
struct cff2_accelerator_t : cff2::accelerator_t {};
|
||||
} /* namespace OT */
|
||||
|
||||
#endif /* HB_OT_CFF2_TABLE_HH */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-ot-glyf-table.hh"
|
||||
#include "hb-ot-cff1-table.hh"
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
#include "hb-ot-kern-table.hh"
|
||||
#include "hb-ot-post-table.hh"
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
HB_OT_ACCELERATOR(OT, kern) \
|
||||
HB_OT_ACCELERATOR(OT, glyf) \
|
||||
HB_OT_ACCELERATOR(OT, cff1) \
|
||||
HB_OT_ACCELERATOR(OT, cff2) \
|
||||
HB_OT_ACCELERATOR(OT, CBDT) \
|
||||
/* */
|
||||
|
||||
|
|
|
@ -124,9 +124,13 @@ hb_ot_get_glyph_extents (hb_font_t *font,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data;
|
||||
unsigned int num_coords;
|
||||
const int *coords = hb_font_get_var_coords_normalized (font, &num_coords);
|
||||
bool ret = ot_face->glyf->get_extents (glyph, extents);
|
||||
if (!ret)
|
||||
ret = ot_face->cff1->get_extents (glyph, extents);
|
||||
if (!ret)
|
||||
ret = ot_face->cff2->get_extents (glyph, extents, coords, num_coords);
|
||||
if (!ret)
|
||||
ret = ot_face->CBDT->get_extents (glyph, extents);
|
||||
// TODO Hook up side-bearings variations.
|
||||
|
|
|
@ -1502,6 +1502,9 @@ struct VarRegionList
|
|||
|
||||
struct VarData
|
||||
{
|
||||
inline unsigned int get_region_index_count (void) const
|
||||
{ return regionIndices.len; }
|
||||
|
||||
inline unsigned int get_row_size (void) const
|
||||
{ return shortCount + regionIndices.len; }
|
||||
|
||||
|
@ -1540,6 +1543,18 @@ struct VarData
|
|||
return delta;
|
||||
}
|
||||
|
||||
inline void get_scalars (int *coords, unsigned int coord_count,
|
||||
const VarRegionList ®ions,
|
||||
float *scalars /*OUT */,
|
||||
unsigned int num_scalars) const
|
||||
{
|
||||
assert (num_scalars == regionIndices.len);
|
||||
for (unsigned int i = 0; i < num_scalars; i++)
|
||||
{
|
||||
scalars[i] = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -1589,8 +1604,17 @@ struct VariationStore
|
|||
dataSets.sanitize (c, this));
|
||||
}
|
||||
|
||||
inline unsigned int get_region_count (void) const
|
||||
{ return (this+regions).get_region_count (); }
|
||||
inline unsigned int get_region_index_count (unsigned int ivs) const
|
||||
{ return (this+dataSets[ivs]).get_region_index_count (); }
|
||||
|
||||
inline void get_scalars (unsigned int ivs,
|
||||
int *coords, unsigned int coord_count,
|
||||
float *scalars /*OUT*/,
|
||||
unsigned int num_scalars) const
|
||||
{
|
||||
(this+dataSets[ivs]).get_scalars (coords, coord_count, this+regions,
|
||||
&scalars[0], num_scalars);
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT16 format;
|
||||
|
|
|
@ -304,7 +304,7 @@ struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam>
|
|||
static inline void flush_args (CFF1CSInterpEnv &env, FlattenParam& param, unsigned int start_arg = 0)
|
||||
{
|
||||
for (unsigned int i = start_arg; i < env.argStack.get_count (); i++)
|
||||
param.flatStr.encode_num (env.argStack[i]);
|
||||
param.flatStr.encode_num (env.eval_arg (i));
|
||||
SUPER::flush_args (env, param, start_arg);
|
||||
}
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam>
|
|||
for (unsigned int i = start_arg; i < env.argStack.get_count ();)
|
||||
{
|
||||
const BlendArg &arg = env.argStack[i];
|
||||
if (arg.blended ())
|
||||
if (arg.blending ())
|
||||
{
|
||||
assert ((arg.numValues > 0) && (env.argStack.get_count () - start_arg >= arg.numValues));
|
||||
flatten_blends (arg, i, env, param);
|
||||
|
@ -135,7 +135,7 @@ struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam>
|
|||
for (unsigned int j = 0; j < arg.numValues; j++)
|
||||
{
|
||||
const BlendArg &arg1 = env.argStack[i + j];
|
||||
assert (arg1.blended () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) &&
|
||||
assert (arg1.blending () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) &&
|
||||
(arg1.deltas.len == env.get_region_count ()));
|
||||
param.flatStr.encode_num (arg1);
|
||||
}
|
||||
|
|
|
@ -54,12 +54,48 @@ test_extents_cff1 (void)
|
|||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
static void
|
||||
test_extents_cff2 (void)
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file ("fonts/AdobeVFPrototype.abc.otf");
|
||||
g_assert (blob);
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
g_assert (face);
|
||||
hb_font_t *font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
g_assert (font);
|
||||
hb_ot_font_set_funcs (font);
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_bool_t result = hb_font_get_glyph_extents (font, 1, &extents);
|
||||
g_assert (result);
|
||||
|
||||
g_assert_cmpint (extents.x_bearing, ==, 46);
|
||||
g_assert_cmpint (extents.y_bearing, ==, 487);
|
||||
g_assert_cmpint (extents.width, ==, 455);
|
||||
g_assert_cmpint (extents.height, ==, -500);
|
||||
|
||||
float coords[2] = { 600.0f, 50.0f };
|
||||
hb_font_set_var_coords_design (font, coords, 2);
|
||||
result = hb_font_get_glyph_extents (font, 1, &extents);
|
||||
g_assert (result);
|
||||
|
||||
g_assert_cmpint (extents.x_bearing, ==, 38);
|
||||
g_assert_cmpint (extents.y_bearing, ==, 493);
|
||||
g_assert_cmpint (extents.width, ==, 481);
|
||||
g_assert_cmpint (extents.height, ==, -508);
|
||||
|
||||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
hb_test_init (&argc, &argv);
|
||||
|
||||
hb_test_add (test_extents_cff1);
|
||||
hb_test_add (test_extents_cff2);
|
||||
|
||||
return hb_test_run ();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue