Added drop_hints to SubrFlattener

This commit is contained in:
Michiharu Ariza 2018-08-30 17:21:56 -07:00
parent 9fd08cc238
commit 8c5e03b541
4 changed files with 83 additions and 33 deletions

View File

@ -282,6 +282,25 @@ struct CSOpSet : OpSet
}
}
/* hint operators (excluding hint/counter mask) */
static inline bool is_hint_op (OpCode op)
{
switch (op)
{
case OpCode_hstem:
case OpCode_vstem:
case OpCode_hstemhm:
case OpCode_vstemhm:
case OpCode_hflex:
case OpCode_flex:
case OpCode_hflex1:
case OpCode_flex1:
return true;
default:
return false;
}
}
static inline bool is_subr_op (OpCode op)
{
switch (op)
@ -301,7 +320,6 @@ struct CSInterpreter : Interpreter<ENV>
{
inline bool interpret (PARAM& param)
{
param.init ();
Interpreter<ENV> &super = *this;
super.env.set_endchar (false);

View File

@ -252,13 +252,21 @@ struct CFFPrivateDict_OpSerializer : OpSerializer
const bool flatten_subrs;
};
struct FlattenParam
{
ByteStrBuff &flatStr;
bool drop_hints;
};
template <typename ACCESSOR, typename ENV, typename OPSET>
struct SubrFlattener
{
inline SubrFlattener (const ACCESSOR &acc_, const hb_vector_t<hb_codepoint_t> &glyphs_)
inline SubrFlattener (const ACCESSOR &acc_,
const hb_vector_t<hb_codepoint_t> &glyphs_,
bool drop_hints_)
: acc (acc_),
glyphs (glyphs_)
glyphs (glyphs_),
drop_hints (drop_hints_)
{}
inline bool flatten (ByteStrBuffArray &flat_charstrings)
@ -272,9 +280,10 @@ struct SubrFlattener
hb_codepoint_t glyph = glyphs[i];
const ByteStr str = (*acc.charStrings)[glyph];
unsigned int fd = acc.fdSelect->get_fd (glyph);
CSInterpreter<ENV, OPSET, ByteStrBuff> interp;
CSInterpreter<ENV, OPSET, FlattenParam> interp;
interp.env.init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
if (unlikely (!interp.interpret (flat_charstrings[i])))
FlattenParam param = { flat_charstrings[i], drop_hints };
if (unlikely (!interp.interpret (param)))
return false;
}
return true;
@ -282,6 +291,7 @@ struct SubrFlattener
const ACCESSOR &acc;
const hb_vector_t<hb_codepoint_t> &glyphs;
bool drop_hints;
};
struct SubrRefMaps

View File

@ -104,40 +104,50 @@ struct CFF1TopDict_OpSerializer : CFFTopDict_OpSerializer
}
};
struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, ByteStrBuff>
struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam>
{
static inline bool process_op (OpCode op, CFF1CSInterpEnv &env, ByteStrBuff& flatStr)
static inline bool process_op (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param)
{
if (unlikely (!SUPER::process_op (op, env, flatStr)))
if (param.drop_hints && CSOPSET::is_hint_op (op))
{
env.clear_stack ();
return true;
}
if (unlikely (!SUPER::process_op (op, env, param)))
return false;
switch (op)
{
case OpCode_hintmask:
case OpCode_cntrmask:
if (unlikely (!flatStr.encode_op (op)))
if (param.drop_hints)
{
env.clear_stack ();
return true;
}
if (unlikely (!param.flatStr.encode_op (op)))
return false;
for (int i = -env.hintmask_size; i < 0; i++)
if (unlikely (!flatStr.encode_byte (env.substr[i])))
if (unlikely (!param.flatStr.encode_byte (env.substr[i])))
return false;
break;
default:
if (!CSOPSET::is_subr_op (op) &&
!CSOPSET::is_arg_op (op))
return flatStr.encode_op (op);
return param.flatStr.encode_op (op);
}
return true;
}
static inline void flush_stack (CFF1CSInterpEnv &env, ByteStrBuff& flatStr)
static inline void flush_stack (CFF1CSInterpEnv &env, FlattenParam& param)
{
for (unsigned int i = 0; i < env.argStack.size; i++)
flatStr.encode_num (env.argStack.elements[i]);
SUPER::flush_stack (env, flatStr);
param.flatStr.encode_num (env.argStack.elements[i]);
SUPER::flush_stack (env, param);
}
private:
typedef CFF1CSOpSet<CFF1CSOpSet_Flatten, ByteStrBuff> SUPER;
typedef CSOpSet<CFF1CSOpSet_Flatten, CFF1CSInterpEnv, ByteStrBuff> CSOPSET;
typedef CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam> SUPER;
typedef CSOpSet<CFF1CSOpSet_Flatten, CFF1CSInterpEnv, FlattenParam> CSOPSET;
};
struct CFF1CSOpSet_SubsetSubrs : CFF1CSOpSet<CFF1CSOpSet_SubsetSubrs, SubrRefMapPair>
@ -226,7 +236,8 @@ struct cff_subset_plan {
if (flatten_subrs)
{
/* Flatten global & local subrs */
SubrFlattener<const OT::cff1::accelerator_subset_t, CFF1CSInterpEnv, CFF1CSOpSet_Flatten> flattener(acc, plan->glyphs);
SubrFlattener<const OT::cff1::accelerator_subset_t, CFF1CSInterpEnv, CFF1CSOpSet_Flatten>
flattener(acc, plan->glyphs, plan->drop_hints);
if (!flattener.flatten (flat_charstrings))
return false;

View File

@ -75,20 +75,30 @@ struct CFF2TopDict_OpSerializer : CFFTopDict_OpSerializer
}
};
struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, ByteStrBuff>
struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam>
{
static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, ByteStrBuff& flatStr)
static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param)
{
if (unlikely (!SUPER::process_op (op, env, flatStr)))
if (param.drop_hints && CSOPSET::is_hint_op (op))
{
env.clear_stack ();
return true;
}
if (unlikely (!SUPER::process_op (op, env, param)))
return false;
switch (op)
{
case OpCode_hintmask:
case OpCode_cntrmask:
if (unlikely (!flatStr.encode_op (op)))
if (param.drop_hints)
{
env.clear_stack ();
return true;
}
if (unlikely (!param.flatStr.encode_op (op)))
return false;
for (int i = -env.hintmask_size; i < 0; i++)
if (unlikely (!flatStr.encode_byte (env.substr[i])))
if (unlikely (!param.flatStr.encode_byte (env.substr[i])))
return false;
break;
case OpCode_return:
@ -98,33 +108,33 @@ struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, ByteStrBuff>
default:
if (!CSOPSET::is_subr_op (op) &&
!CSOPSET::is_arg_op (op))
return flatStr.encode_op (op);
return param.flatStr.encode_op (op);
}
return true;
}
static inline bool process_blend (CFF2CSInterpEnv &env, ByteStrBuff& flatStr)
static inline bool process_blend (CFF2CSInterpEnv &env, FlattenParam& param)
{
flush_stack (env, flatStr);
flush_stack (env, param);
return true;
}
static inline bool process_vsindex (CFF2CSInterpEnv &env, ByteStrBuff& flatStr)
static inline bool process_vsindex (CFF2CSInterpEnv &env, FlattenParam& param)
{
flush_stack (env, flatStr);
flush_stack (env, param);
return true;
}
static inline void flush_stack (CFF2CSInterpEnv &env, ByteStrBuff& flatStr)
static inline void flush_stack (CFF2CSInterpEnv &env, FlattenParam& param)
{
for (unsigned int i = 0; i < env.argStack.size; i++)
flatStr.encode_num (env.argStack.elements[i]);
SUPER::flush_stack (env, flatStr);
param.flatStr.encode_num (env.argStack.elements[i]);
SUPER::flush_stack (env, param);
}
private:
typedef CFF2CSOpSet<CFF2CSOpSet_Flatten, ByteStrBuff> SUPER;
typedef CSOpSet<CFF2CSOpSet_Flatten, CFF2CSInterpEnv, ByteStrBuff> CSOPSET;
typedef CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam> SUPER;
typedef CSOpSet<CFF2CSOpSet_Flatten, CFF2CSInterpEnv, FlattenParam> CSOPSET;
};
struct CFF2CSOpSet_SubsetSubrs : CFF2CSOpSet<CFF2CSOpSet_SubsetSubrs, SubrRefMapPair>
@ -200,7 +210,8 @@ struct cff2_subset_plan {
if (flatten_subrs)
{
/* Flatten global & local subrs */
SubrFlattener<const OT::cff2::accelerator_subset_t, CFF2CSInterpEnv, CFF2CSOpSet_Flatten> flattener(acc, plan->glyphs);
SubrFlattener<const OT::cff2::accelerator_subset_t, CFF2CSInterpEnv, CFF2CSOpSet_Flatten>
flattener(acc, plan->glyphs, plan->drop_hints);
if (!flattener.flatten (flat_charstrings))
return false;