Drop hints from CFF2 charstrings
Templatized ArgStack so it may store the default value along with blend deltas as BlendArg while parsing blend operator arguments in CFF2 charstring Added get_region_count() method to VarRegionList & VariationStore
This commit is contained in:
parent
fcf177885b
commit
f2d299b0b7
|
@ -210,7 +210,10 @@ inline unsigned int OpCode_Size (OpCode op) { return Is_OpCode_ESC (op)? 2: 1; }
|
||||||
|
|
||||||
struct Number
|
struct Number
|
||||||
{
|
{
|
||||||
inline Number (void) { set_int (0); }
|
inline void init (void)
|
||||||
|
{ set_int (0); }
|
||||||
|
inline void fini (void)
|
||||||
|
{}
|
||||||
|
|
||||||
inline void set_int (int v) { format = NumInt; u.int_val = v; };
|
inline void set_int (int v) { format = NumInt; u.int_val = v; };
|
||||||
inline int to_int (void) const { return is_int ()? u.int_val: (int)to_real (); }
|
inline int to_int (void) const { return is_int ()? u.int_val: (int)to_real (); }
|
||||||
|
@ -336,7 +339,15 @@ struct ByteStr
|
||||||
struct SubByteStr
|
struct SubByteStr
|
||||||
{
|
{
|
||||||
inline SubByteStr (void)
|
inline SubByteStr (void)
|
||||||
: str (), offset (0) {}
|
{ init (); }
|
||||||
|
|
||||||
|
inline void init (void)
|
||||||
|
{
|
||||||
|
str = ByteStr (0);
|
||||||
|
offset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fini (void) {}
|
||||||
|
|
||||||
inline SubByteStr (const ByteStr &str_, unsigned int offset_ = 0)
|
inline SubByteStr (const ByteStr &str_, unsigned int offset_ = 0)
|
||||||
: str (str_), offset (offset_) {}
|
: str (str_), offset (offset_) {}
|
||||||
|
@ -379,15 +390,35 @@ inline float parse_bcd (SubByteStr& substr, float& v)
|
||||||
template <typename ELEM, int LIMIT>
|
template <typename ELEM, int LIMIT>
|
||||||
struct Stack
|
struct Stack
|
||||||
{
|
{
|
||||||
inline void init (void) { count = 0; }
|
inline void init (void)
|
||||||
inline void fini (void) { }
|
{
|
||||||
|
count = 0;
|
||||||
|
elements.init ();
|
||||||
|
elements.resize (kSizeLimit);
|
||||||
|
for (unsigned int i = 0; i < elements.len; i++)
|
||||||
|
elements[i].init ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fini (void)
|
||||||
|
{
|
||||||
|
for (unsigned int i = 0; i < elements.len; i++)
|
||||||
|
elements[i].fini ();
|
||||||
|
}
|
||||||
|
|
||||||
inline void push (const ELEM &v)
|
inline void push (const ELEM &v)
|
||||||
{
|
{
|
||||||
if (likely (count < kSizeLimit))
|
if (likely (count < elements.len))
|
||||||
elements[count++] = v;
|
elements[count++] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline ELEM &push (void)
|
||||||
|
{
|
||||||
|
if (likely (count < elements.len))
|
||||||
|
return elements[count++];
|
||||||
|
else
|
||||||
|
return Crap(ELEM);
|
||||||
|
}
|
||||||
|
|
||||||
inline const ELEM& pop (void)
|
inline const ELEM& pop (void)
|
||||||
{
|
{
|
||||||
if (likely (count > 0))
|
if (likely (count > 0))
|
||||||
|
@ -396,9 +427,17 @@ struct Stack
|
||||||
return Null(ELEM);
|
return Null(ELEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const ELEM& peek (void)
|
||||||
|
{
|
||||||
|
if (likely (count > 0))
|
||||||
|
return elements[count];
|
||||||
|
else
|
||||||
|
return Null(ELEM);
|
||||||
|
}
|
||||||
|
|
||||||
inline void unpop (void)
|
inline void unpop (void)
|
||||||
{
|
{
|
||||||
if (likely (count < kSizeLimit))
|
if (likely (count < elements.len))
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,7 +452,7 @@ struct Stack
|
||||||
static const unsigned int kSizeLimit = LIMIT;
|
static const unsigned int kSizeLimit = LIMIT;
|
||||||
|
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
ELEM elements[kSizeLimit];
|
hb_vector_t<ELEM, kSizeLimit> elements;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* argument stack */
|
/* argument stack */
|
||||||
|
@ -422,16 +461,20 @@ struct ArgStack : Stack<ARG, 513>
|
||||||
{
|
{
|
||||||
inline void push_int (int v)
|
inline void push_int (int v)
|
||||||
{
|
{
|
||||||
ARG n;
|
ARG &n = S::push ();
|
||||||
n.set_int (v);
|
n.set_int (v);
|
||||||
S::push (n);
|
}
|
||||||
|
|
||||||
|
inline void push_fixed (int32_t v)
|
||||||
|
{
|
||||||
|
ARG &n = S::push ();
|
||||||
|
n.set_fixed (v);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void push_real (float v)
|
inline void push_real (float v)
|
||||||
{
|
{
|
||||||
ARG n;
|
ARG &n = S::push ();
|
||||||
n.set_real (v);
|
n.set_real (v);
|
||||||
S::push (n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool check_pop_num (ARG& n)
|
inline bool check_pop_num (ARG& n)
|
||||||
|
@ -495,7 +538,7 @@ struct ArgStack : Stack<ARG, 513>
|
||||||
{
|
{
|
||||||
if (unlikely (!substr.avail (4) || !S::check_overflow (1)))
|
if (unlikely (!substr.avail (4) || !S::check_overflow (1)))
|
||||||
return false;
|
return false;
|
||||||
push_real ((int32_t)*(const HBUINT32*)&substr[0] / 65536.0);
|
push_fixed ((int32_t)*(const HBUINT32*)&substr[0]);
|
||||||
substr.inc (4);
|
substr.inc (4);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,10 @@ using namespace OT;
|
||||||
|
|
||||||
struct CFF1CSInterpEnv : CSInterpEnv<Number, CFF1Subrs>
|
struct CFF1CSInterpEnv : CSInterpEnv<Number, CFF1Subrs>
|
||||||
{
|
{
|
||||||
inline void init (const ByteStr &str, const CFF1Subrs &globalSubrs, const CFF1Subrs &localSubrs)
|
template <typename ACC>
|
||||||
|
inline void init (const ByteStr &str, ACC &acc, unsigned int fd)
|
||||||
{
|
{
|
||||||
SUPER::init (str, globalSubrs, localSubrs);
|
SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
||||||
processed_width = false;
|
processed_width = false;
|
||||||
has_width = false;
|
has_width = false;
|
||||||
for (unsigned int i = 0; i < kTransientArraySize; i++)
|
for (unsigned int i = 0; i < kTransientArraySize; i++)
|
||||||
|
|
|
@ -33,12 +33,60 @@ namespace CFF {
|
||||||
|
|
||||||
using namespace OT;
|
using namespace OT;
|
||||||
|
|
||||||
|
struct BlendArg : Number
|
||||||
|
{
|
||||||
|
inline void init (void)
|
||||||
|
{
|
||||||
|
Number::init ();
|
||||||
|
deltas.init ();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void fini (void)
|
||||||
|
{
|
||||||
|
Number::fini ();
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < deltas.len; i++)
|
||||||
|
deltas[i].fini ();
|
||||||
|
deltas.fini ();
|
||||||
|
}
|
||||||
|
|
||||||
|
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_real (float v) { reset_blends (); Number::set_real (v); }
|
||||||
|
|
||||||
|
inline void set_blends (unsigned int numValues_, unsigned int valueIndex_,
|
||||||
|
unsigned int numBlends, const BlendArg *blends_)
|
||||||
|
{
|
||||||
|
numValues = numValues_;
|
||||||
|
valueIndex = valueIndex_;
|
||||||
|
deltas.resize (numBlends);
|
||||||
|
for (unsigned int i = 0; i < numBlends; i++)
|
||||||
|
deltas[i] = blends_[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool blended (void) const { return deltas.len > 0; }
|
||||||
|
inline void reset_blends (void)
|
||||||
|
{
|
||||||
|
numValues = valueIndex = 0;
|
||||||
|
deltas.resize (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int numValues;
|
||||||
|
unsigned int valueIndex;
|
||||||
|
hb_vector_t<Number> deltas;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef InterpEnv<BlendArg> BlendInterpEnv;
|
||||||
|
typedef DictVal<BlendArg> BlendDictVal;
|
||||||
|
|
||||||
struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
|
struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
|
||||||
{
|
{
|
||||||
inline void init (const ByteStr &str, const CFF2Subrs &globalSubrs_, const CFF2Subrs &localSubrs_)
|
template <typename ACC>
|
||||||
|
inline void init (const ByteStr &str, ACC &acc, unsigned int fd)
|
||||||
{
|
{
|
||||||
SUPER::init (str, globalSubrs_, localSubrs_);
|
SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
||||||
ivs = 0;
|
set_region_count (acc.region_count);
|
||||||
|
set_vsindex (acc.privateDicts[fd].vsindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool fetch_op (OpCode &op)
|
inline bool fetch_op (OpCode &op)
|
||||||
|
@ -58,14 +106,17 @@ struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
|
||||||
{
|
{
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
if (likely (argStack.check_pop_uint (index)))
|
if (likely (argStack.check_pop_uint (index)))
|
||||||
set_ivs (argStack.check_pop_uint (index));
|
set_vsindex (argStack.check_pop_uint (index));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned int get_ivs (void) const { return ivs; }
|
inline unsigned int get_region_count (void) const { return region_count; }
|
||||||
inline void set_ivs (unsigned int ivs_) { ivs = ivs_; }
|
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_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned int ivs;
|
unsigned int region_count;
|
||||||
|
unsigned int vsindex;
|
||||||
|
|
||||||
typedef CSInterpEnv<BlendArg, CFF2Subrs> SUPER;
|
typedef CSInterpEnv<BlendArg, CFF2Subrs> SUPER;
|
||||||
};
|
};
|
||||||
|
@ -76,26 +127,42 @@ struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM>
|
||||||
static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, PARAM& param)
|
static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, PARAM& param)
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
|
case OpCode_callsubr:
|
||||||
|
case OpCode_callgsubr:
|
||||||
|
/* a subroutine number shoudln't be a blended value */
|
||||||
|
return (!env.argStack.peek ().blended () &&
|
||||||
|
SUPER::process_op (op, env, param));
|
||||||
|
|
||||||
case OpCode_blendcs:
|
case OpCode_blendcs:
|
||||||
return OPSET::process_blend (env, param);
|
return OPSET::process_blend (env, param);
|
||||||
|
|
||||||
case OpCode_vsindexcs:
|
case OpCode_vsindexcs:
|
||||||
|
if (unlikely (env.argStack.peek ().blended ()))
|
||||||
|
return false;
|
||||||
OPSET::process_vsindex (env, param);
|
OPSET::process_vsindex (env, param);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (unlikely (!SUPER::process_op (op, env, param)))
|
return SUPER::process_op (op, env, param);
|
||||||
return false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool process_blend (CFF2CSInterpEnv &env, PARAM& param)
|
static inline bool process_blend (CFF2CSInterpEnv &env, PARAM& param)
|
||||||
{
|
{
|
||||||
// XXX: TODO leave default values?
|
unsigned int n, k;
|
||||||
OPSET::flush_args (env, param);
|
|
||||||
|
k = env.get_region_count ();
|
||||||
|
if (unlikely (!env.argStack.check_pop_uint (n) ||
|
||||||
|
(k+1) * n > env.argStack.get_count ()))
|
||||||
|
return false;
|
||||||
|
/* copy the blend values into blend array of the default values */
|
||||||
|
unsigned int start = env.argStack.get_count () - ((k+1) * n);
|
||||||
|
for (unsigned int i = 0; i < n; i++)
|
||||||
|
env.argStack.elements[start + i].set_blends (n, i, k, &env.argStack.elements[start + n + (i * k)]);
|
||||||
|
|
||||||
|
/* pop off blend values leaving default values now adorned with blend values */
|
||||||
|
env.argStack.count -= k * n;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,13 +48,6 @@ typedef Subrs<HBUINT32> CFF2Subrs;
|
||||||
typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
|
typedef FDSelect3_4<HBUINT32, HBUINT16> FDSelect4;
|
||||||
typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
|
typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
|
||||||
|
|
||||||
struct BlendArg : Number
|
|
||||||
{
|
|
||||||
// XXX: TODO
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef InterpEnv<BlendArg> BlendInterpEnv;
|
|
||||||
|
|
||||||
struct CFF2FDSelect
|
struct CFF2FDSelect
|
||||||
{
|
{
|
||||||
inline bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
|
inline bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
|
||||||
|
@ -271,6 +264,7 @@ struct CFF2PrivateDictValues_Base : DictValues<VAL>
|
||||||
DictValues<VAL>::init ();
|
DictValues<VAL>::init ();
|
||||||
subrsOffset = 0;
|
subrsOffset = 0;
|
||||||
localSubrs = &Null(CFF2Subrs);
|
localSubrs = &Null(CFF2Subrs);
|
||||||
|
vsindex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void fini (void)
|
inline void fini (void)
|
||||||
|
@ -291,9 +285,9 @@ struct CFF2PrivateDictValues_Base : DictValues<VAL>
|
||||||
|
|
||||||
unsigned int subrsOffset;
|
unsigned int subrsOffset;
|
||||||
const CFF2Subrs *localSubrs;
|
const CFF2Subrs *localSubrs;
|
||||||
|
unsigned int vsindex;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DictVal<BlendArg> BlendDictVal;
|
|
||||||
typedef CFF2PrivateDictValues_Base<OpStr> CFF2PrivateDictValues_Subset;
|
typedef CFF2PrivateDictValues_Base<OpStr> CFF2PrivateDictValues_Subset;
|
||||||
typedef CFF2PrivateDictValues_Base<NumDictVal> CFF2PrivateDictValues;
|
typedef CFF2PrivateDictValues_Base<NumDictVal> CFF2PrivateDictValues;
|
||||||
|
|
||||||
|
@ -332,9 +326,11 @@ struct CFF2PrivateDictOpSet : DictOpSet<>
|
||||||
env.clear_args ();
|
env.clear_args ();
|
||||||
break;
|
break;
|
||||||
case OpCode_vsindexdict:
|
case OpCode_vsindexdict:
|
||||||
|
if (unlikely (!env.argStack.check_pop_uint (dictval.vsindex)))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
case OpCode_blenddict:
|
case OpCode_blenddict:
|
||||||
// XXX: TODO
|
break;
|
||||||
return true;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (unlikely (!DictOpSet::process_op (op, env)))
|
if (unlikely (!DictOpSet::process_op (op, env)))
|
||||||
|
@ -458,6 +454,11 @@ struct cff2
|
||||||
if (num_glyphs != sc.get_num_glyphs ())
|
if (num_glyphs != sc.get_num_glyphs ())
|
||||||
{ fini (); return; }
|
{ fini (); return; }
|
||||||
|
|
||||||
|
if (varStore != &Null(CFF2VariationStore))
|
||||||
|
region_count = varStore->varStore.get_region_count ();
|
||||||
|
else
|
||||||
|
region_count = 0;
|
||||||
|
|
||||||
fdCount = fdArray->count;
|
fdCount = fdArray->count;
|
||||||
privateDicts.resize (fdCount);
|
privateDicts.resize (fdCount);
|
||||||
|
|
||||||
|
@ -523,6 +524,7 @@ struct cff2
|
||||||
hb_vector_t<PRIVDICTVAL> privateDicts;
|
hb_vector_t<PRIVDICTVAL> privateDicts;
|
||||||
|
|
||||||
unsigned int num_glyphs;
|
unsigned int num_glyphs;
|
||||||
|
unsigned int region_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef accelerator_templ_t<CFF2PrivateDictOpSet, CFF2PrivateDictValues> accelerator_t;
|
typedef accelerator_templ_t<CFF2PrivateDictOpSet, CFF2PrivateDictValues> accelerator_t;
|
||||||
|
|
|
@ -1346,6 +1346,9 @@ struct VarRegionList
|
||||||
axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
|
axesZ.sanitize (c, (unsigned int) axisCount * (unsigned int) regionCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned int get_region_count (void) const
|
||||||
|
{ return regionCount; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HBUINT16 axisCount;
|
HBUINT16 axisCount;
|
||||||
HBUINT16 regionCount;
|
HBUINT16 regionCount;
|
||||||
|
@ -1444,6 +1447,9 @@ struct VariationStore
|
||||||
dataSets.sanitize (c, this));
|
dataSets.sanitize (c, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned int get_region_count (void) const
|
||||||
|
{ return (this+regions).get_region_count (); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HBUINT16 format;
|
HBUINT16 format;
|
||||||
LOffsetTo<VarRegionList> regions;
|
LOffsetTo<VarRegionList> regions;
|
||||||
|
|
|
@ -42,30 +42,34 @@ struct ByteStrBuff : hb_vector_t<char, 1>
|
||||||
return (push ((const char)b) != &Crap(char));
|
return (push ((const char)b) != &Crap(char));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool encode_int (int v)
|
||||||
|
{
|
||||||
|
if ((-1131 <= v) && (v <= 1131))
|
||||||
|
{
|
||||||
|
if ((-107 <= v) && (v <= 107))
|
||||||
|
return encode_byte (v + 139);
|
||||||
|
else if (v > 0)
|
||||||
|
{
|
||||||
|
v -= 108;
|
||||||
|
return encode_byte ((v >> 8) + OpCode_TwoBytePosInt0) && encode_byte (v & 0xFF);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v = -v - 108;
|
||||||
|
return encode_byte ((v >> 8) + OpCode_TwoByteNegInt0) && encode_byte (v & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert ((v & ~0xFFFF) == 0);
|
||||||
|
return encode_byte (OpCode_shortint) &&
|
||||||
|
encode_byte ((v >> 8) & 0xFF) &&
|
||||||
|
encode_byte (v & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
inline bool encode_num (const Number& n)
|
inline bool encode_num (const Number& n)
|
||||||
{
|
{
|
||||||
if (n.in_int_range ())
|
if (n.in_int_range ())
|
||||||
{
|
{
|
||||||
int v = n.to_int ();
|
return encode_int (n.to_int ());
|
||||||
if ((-1131 <= v) && (v <= 1131))
|
|
||||||
{
|
|
||||||
if ((-107 <= v) && (v <= 107))
|
|
||||||
return encode_byte (v + 139);
|
|
||||||
else if (v > 0)
|
|
||||||
{
|
|
||||||
v -= 108;
|
|
||||||
return encode_byte ((v >> 8) + OpCode_TwoBytePosInt0) && encode_byte (v & 0xFF);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
v = -v - 108;
|
|
||||||
return encode_byte ((v >> 8) + OpCode_TwoByteNegInt0) && encode_byte (v & 0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert ((v & ~0xFFFF) == 0);
|
|
||||||
return encode_byte (OpCode_shortint) &&
|
|
||||||
encode_byte ((v >> 8) & 0xFF) &&
|
|
||||||
encode_byte (v & 0xFF);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -258,10 +262,10 @@ struct FlattenParam
|
||||||
bool drop_hints;
|
bool drop_hints;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ACCESSOR, typename ENV, typename OPSET>
|
template <typename ACC, typename ENV, typename OPSET>
|
||||||
struct SubrFlattener
|
struct SubrFlattener
|
||||||
{
|
{
|
||||||
inline SubrFlattener (const ACCESSOR &acc_,
|
inline SubrFlattener (const ACC &acc_,
|
||||||
const hb_vector_t<hb_codepoint_t> &glyphs_,
|
const hb_vector_t<hb_codepoint_t> &glyphs_,
|
||||||
bool drop_hints_)
|
bool drop_hints_)
|
||||||
: acc (acc_),
|
: acc (acc_),
|
||||||
|
@ -281,7 +285,7 @@ struct SubrFlattener
|
||||||
const ByteStr str = (*acc.charStrings)[glyph];
|
const ByteStr str = (*acc.charStrings)[glyph];
|
||||||
unsigned int fd = acc.fdSelect->get_fd (glyph);
|
unsigned int fd = acc.fdSelect->get_fd (glyph);
|
||||||
CSInterpreter<ENV, OPSET, FlattenParam> interp;
|
CSInterpreter<ENV, OPSET, FlattenParam> interp;
|
||||||
interp.env.init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
interp.env.init (str, acc, fd);
|
||||||
FlattenParam param = { flat_charstrings[i], drop_hints };
|
FlattenParam param = { flat_charstrings[i], drop_hints };
|
||||||
if (unlikely (!interp.interpret (param)))
|
if (unlikely (!interp.interpret (param)))
|
||||||
return false;
|
return false;
|
||||||
|
@ -289,7 +293,7 @@ struct SubrFlattener
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ACCESSOR &acc;
|
const ACC &acc;
|
||||||
const hb_vector_t<hb_codepoint_t> &glyphs;
|
const hb_vector_t<hb_codepoint_t> &glyphs;
|
||||||
bool drop_hints;
|
bool drop_hints;
|
||||||
};
|
};
|
||||||
|
@ -342,10 +346,10 @@ struct SubrRefMapPair
|
||||||
hb_set_t *local_map;
|
hb_set_t *local_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ACCESSOR, typename ENV, typename OPSET>
|
template <typename ACC, typename ENV, typename OPSET>
|
||||||
struct SubrSubsetter
|
struct SubrSubsetter
|
||||||
{
|
{
|
||||||
inline SubrSubsetter (const ACCESSOR &acc_, const hb_vector_t<hb_codepoint_t> &glyphs_)
|
inline SubrSubsetter (const ACC &acc_, const hb_vector_t<hb_codepoint_t> &glyphs_)
|
||||||
: acc (acc_),
|
: acc (acc_),
|
||||||
glyphs (glyphs_)
|
glyphs (glyphs_)
|
||||||
{}
|
{}
|
||||||
|
@ -361,14 +365,14 @@ struct SubrSubsetter
|
||||||
unsigned int fd = acc.fdSelect->get_fd (glyph);
|
unsigned int fd = acc.fdSelect->get_fd (glyph);
|
||||||
SubrRefMapPair pair = { refmaps.global_map, refmaps.local_maps[fd] };
|
SubrRefMapPair pair = { refmaps.global_map, refmaps.local_maps[fd] };
|
||||||
CSInterpreter<ENV, OPSET, SubrRefMapPair> interp;
|
CSInterpreter<ENV, OPSET, SubrRefMapPair> interp;
|
||||||
interp.env.init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
interp.env.init (str, acc, fd);
|
||||||
if (unlikely (!interp.interpret (pair)))
|
if (unlikely (!interp.interpret (pair)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ACCESSOR &acc;
|
const ACC &acc;
|
||||||
const hb_vector_t<hb_codepoint_t> &glyphs;
|
const hb_vector_t<hb_codepoint_t> &glyphs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -148,8 +148,9 @@ struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam>
|
||||||
static inline void flush_hintmask (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param)
|
static inline void flush_hintmask (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param)
|
||||||
{
|
{
|
||||||
SUPER::flush_hintmask (op, env, param);
|
SUPER::flush_hintmask (op, env, param);
|
||||||
for (unsigned int i = 0; i < env.hintmask_size; i++)
|
if (!param.drop_hints)
|
||||||
param.flatStr.encode_byte (env.substr[i]);
|
for (unsigned int i = 0; i < env.hintmask_size; i++)
|
||||||
|
param.flatStr.encode_byte (env.substr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -77,12 +77,6 @@ struct CFF2TopDict_OpSerializer : CFFTopDict_OpSerializer
|
||||||
|
|
||||||
struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam>
|
struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam>
|
||||||
{
|
{
|
||||||
static inline bool process_blend (CFF2CSInterpEnv &env, FlattenParam& param)
|
|
||||||
{
|
|
||||||
flush_args (env, param);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void flush_args_and_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param)
|
static inline void flush_args_and_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param)
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
|
@ -117,14 +111,56 @@ struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam>
|
||||||
|
|
||||||
static inline void flush_n_args (unsigned int n, CFF2CSInterpEnv &env, FlattenParam& param)
|
static inline void flush_n_args (unsigned int n, CFF2CSInterpEnv &env, FlattenParam& param)
|
||||||
{
|
{
|
||||||
for (unsigned int i = env.argStack.count - n; i < env.argStack.count; i++)
|
for (unsigned int i = env.argStack.count - n; i < env.argStack.count;)
|
||||||
param.flatStr.encode_num (env.argStack.elements[i]);
|
{
|
||||||
|
const BlendArg &arg = env.argStack.elements[i];
|
||||||
|
if (arg.blended ())
|
||||||
|
{
|
||||||
|
assert ((arg.numValues > 0) && (n >= arg.numValues));
|
||||||
|
flatten_blends (arg, i, env, param);
|
||||||
|
i += arg.numValues;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
param.flatStr.encode_num (arg);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
SUPER::flush_n_args (n, env, param);
|
SUPER::flush_n_args (n, env, param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void flatten_blends (const BlendArg &arg, unsigned int i, CFF2CSInterpEnv &env, FlattenParam& param)
|
||||||
|
{
|
||||||
|
/* flatten the default values */
|
||||||
|
for (unsigned int j = 0; j < arg.numValues; j++)
|
||||||
|
{
|
||||||
|
const BlendArg &arg1 = env.argStack.elements[i + j];
|
||||||
|
assert (arg1.blended () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) &&
|
||||||
|
(arg1.deltas.len == env.get_region_count ()));
|
||||||
|
param.flatStr.encode_num (arg1);
|
||||||
|
}
|
||||||
|
/* flatten deltas for each value */
|
||||||
|
for (unsigned int j = 0; j < arg.numValues; j++)
|
||||||
|
{
|
||||||
|
const BlendArg &arg1 = env.argStack.elements[i + j];
|
||||||
|
for (unsigned int k = 0; k < arg1.deltas.len; k++)
|
||||||
|
param.flatStr.encode_num (arg1.deltas[k]);
|
||||||
|
}
|
||||||
|
/* flatten the number of values followed by blend operator */
|
||||||
|
param.flatStr.encode_int (arg.numValues);
|
||||||
|
param.flatStr.encode_op (OpCode_blendcs);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void flush_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param)
|
static inline void flush_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param)
|
||||||
{
|
{
|
||||||
param.flatStr.encode_op (op);
|
switch (op)
|
||||||
|
{
|
||||||
|
case OpCode_return:
|
||||||
|
case OpCode_endchar:
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
param.flatStr.encode_op (op);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue