subset CFF1 String Index
Repurposed FDMap as Remap then subclassed for remapping SIDs misc code cleanup
This commit is contained in:
parent
1e88b1755c
commit
1666b89e30
|
@ -562,8 +562,6 @@ struct ArgStack : Stack<ARG, 513>
|
|||
/* an operator prefixed by its operands in a byte string */
|
||||
struct OpStr
|
||||
{
|
||||
inline void init (void) {}
|
||||
|
||||
OpCode op;
|
||||
ByteStr str;
|
||||
};
|
||||
|
|
|
@ -97,21 +97,22 @@ struct DictValues
|
|||
hb_vector_t<VAL> values;
|
||||
};
|
||||
|
||||
struct TopDictValues : DictValues<OpStr>
|
||||
template <typename OPSTR=OpStr>
|
||||
struct TopDictValues : DictValues<OPSTR>
|
||||
{
|
||||
inline void init (void)
|
||||
{
|
||||
DictValues<OpStr>::init ();
|
||||
DictValues<OPSTR>::init ();
|
||||
charStringsOffset = 0;
|
||||
FDArrayOffset = 0;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
DictValues<OpStr>::fini ();
|
||||
DictValues<OPSTR>::fini ();
|
||||
}
|
||||
|
||||
inline unsigned int calculate_serialized_op_size (const OpStr& opstr) const
|
||||
inline unsigned int calculate_serialized_op_size (const OPSTR& opstr) const
|
||||
{
|
||||
switch (opstr.op)
|
||||
{
|
||||
|
@ -174,9 +175,10 @@ struct DictOpSet : OpSet<Number>
|
|||
}
|
||||
};
|
||||
|
||||
template <typename VAL=OpStr>
|
||||
struct TopDictOpSet : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, InterpEnv<Number>& env, TopDictValues& dictval)
|
||||
static inline bool process_op (OpCode op, InterpEnv<Number>& env, TopDictValues<VAL> & dictval)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_CharStrings:
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace CFF {
|
|||
|
||||
using namespace OT;
|
||||
|
||||
#define CFF_UNDEF_CODE 0xFFFFFFFF
|
||||
|
||||
/* utility macro */
|
||||
template<typename Type>
|
||||
static inline const Type& StructAtOffsetOrNull(const void *P, unsigned int offset)
|
||||
|
@ -291,10 +293,8 @@ struct Dict : UnsizedByteStr
|
|||
}
|
||||
|
||||
template <typename INTTYPE, int minVal, int maxVal>
|
||||
inline static bool serialize_offset_op (hb_serialize_context_t *c, OpCode op, int value, OpCode intOp)
|
||||
inline static bool serialize_int_op (hb_serialize_context_t *c, OpCode op, int value, OpCode intOp)
|
||||
{
|
||||
if (value == 0)
|
||||
return true;
|
||||
// XXX: not sure why but LLVM fails to compile the following 'unlikely' macro invocation
|
||||
if (/*unlikely*/ (!serialize_int<INTTYPE, minVal, maxVal> (c, intOp, value)))
|
||||
return false;
|
||||
|
@ -313,11 +313,23 @@ struct Dict : UnsizedByteStr
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
inline static bool serialize_uint4_op (hb_serialize_context_t *c, OpCode op, int value)
|
||||
{ return serialize_int_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
|
||||
|
||||
inline static bool serialize_uint2_op (hb_serialize_context_t *c, OpCode op, int value)
|
||||
{ return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
|
||||
|
||||
inline static bool serialize_offset4_op (hb_serialize_context_t *c, OpCode op, int value)
|
||||
{ return serialize_offset_op<HBUINT32, 0, 0x7FFFFFFF> (c, op, value, OpCode_longintdict); }
|
||||
{
|
||||
if (value == 0) return true;
|
||||
return serialize_uint4_op (c, op, value);
|
||||
}
|
||||
|
||||
inline static bool serialize_offset2_op (hb_serialize_context_t *c, OpCode op, int value)
|
||||
{ return serialize_offset_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
|
||||
{
|
||||
if (value == 0) return true;
|
||||
return serialize_uint2_op (c, op, value);
|
||||
}
|
||||
};
|
||||
|
||||
struct TopDict : Dict {};
|
||||
|
@ -333,9 +345,9 @@ struct TableInfo
|
|||
unsigned int offSize;
|
||||
};
|
||||
|
||||
/* font dict index remap table from fullset FDArray to subset FDArray.
|
||||
* set to HB_SET_VALUE_INVALID if excluded from subset */
|
||||
struct FDMap : hb_vector_t<hb_codepoint_t>
|
||||
/* used to remap font index or SID from fullset to subset.
|
||||
* set to CFF_UNDEF_CODE if excluded from subset */
|
||||
struct Remap : hb_vector_t<hb_codepoint_t>
|
||||
{
|
||||
inline void init (void)
|
||||
{ hb_vector_t<hb_codepoint_t>::init (); }
|
||||
|
@ -343,16 +355,26 @@ struct FDMap : hb_vector_t<hb_codepoint_t>
|
|||
inline void fini (void)
|
||||
{ hb_vector_t<hb_codepoint_t>::fini (); }
|
||||
|
||||
inline bool reset (unsigned int count)
|
||||
{
|
||||
if (unlikely (!hb_vector_t<hb_codepoint_t>::resize (count)))
|
||||
return false;
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
(*this)[i] = CFF_UNDEF_CODE;
|
||||
count = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool fullset (void) const
|
||||
{
|
||||
for (unsigned int i = 0; i < len; i++)
|
||||
if (hb_vector_t<hb_codepoint_t>::operator[] (i) == HB_SET_VALUE_INVALID)
|
||||
if (hb_vector_t<hb_codepoint_t>::operator[] (i) == CFF_UNDEF_CODE)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool excludes (hb_codepoint_t fd) const
|
||||
{ return (fd < len) && ((*this)[fd] == HB_SET_VALUE_INVALID); }
|
||||
inline bool excludes (hb_codepoint_t id) const
|
||||
{ return (id < len) && ((*this)[id] == CFF_UNDEF_CODE); }
|
||||
|
||||
inline hb_codepoint_t operator[] (hb_codepoint_t i) const
|
||||
{
|
||||
|
@ -367,17 +389,65 @@ struct FDMap : hb_vector_t<hb_codepoint_t>
|
|||
assert (i < len);
|
||||
return hb_vector_t<hb_codepoint_t>::operator[] (i);
|
||||
}
|
||||
|
||||
inline unsigned int add (unsigned int i)
|
||||
{
|
||||
if ((*this)[i] == CFF_UNDEF_CODE)
|
||||
(*this)[i] = count++;
|
||||
return (*this)[i];
|
||||
}
|
||||
|
||||
inline hb_codepoint_t get_count (void) const
|
||||
{ return count; }
|
||||
|
||||
protected:
|
||||
hb_codepoint_t count;
|
||||
};
|
||||
|
||||
template <typename COUNT>
|
||||
struct FDArray : CFFIndexOf<COUNT, FontDict>
|
||||
{
|
||||
/* used by CFF1 */
|
||||
template <typename DICTVAL, typename OP_SERIALIZER>
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
unsigned int offSize_,
|
||||
const hb_vector_t<DICTVAL> &fontDicts,
|
||||
OP_SERIALIZER& opszr)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
this->count.set (fontDicts.len);
|
||||
this->offSize.set (offSize_);
|
||||
if (!unlikely (c->allocate_size<HBUINT8> (offSize_ * (fontDicts.len + 1))))
|
||||
return_trace (false);
|
||||
|
||||
/* serialize font dict offsets */
|
||||
unsigned int offset = 1;
|
||||
unsigned int fid = 0;
|
||||
for (; fid < fontDicts.len; fid++)
|
||||
{
|
||||
CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
|
||||
offset += FontDict::calculate_serialized_size (fontDicts[fid], opszr);
|
||||
}
|
||||
CFFIndexOf<COUNT, FontDict>::set_offset_at (fid, offset);
|
||||
|
||||
/* serialize font dicts */
|
||||
for (unsigned int i = 0; i < fontDicts.len; i++)
|
||||
{
|
||||
FontDict *dict = c->start_embed<FontDict> ();
|
||||
if (unlikely (!dict->serialize (c, fontDicts[i], opszr, fontDicts[i])))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
/* used by CFF2 */
|
||||
template <typename DICTVAL, typename OP_SERIALIZER>
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
unsigned int offSize_,
|
||||
const hb_vector_t<DICTVAL> &fontDicts,
|
||||
unsigned int fdCount,
|
||||
const FDMap &fdmap,
|
||||
const Remap &fdmap,
|
||||
OP_SERIALIZER& opszr,
|
||||
const hb_vector_t<TableInfo> &privateInfos)
|
||||
{
|
||||
|
@ -415,7 +485,7 @@ struct FDArray : CFFIndexOf<COUNT, FontDict>
|
|||
inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
|
||||
const hb_vector_t<DICTVAL> &fontDicts,
|
||||
unsigned int fdCount,
|
||||
const FDMap &fdmap,
|
||||
const Remap &fdmap,
|
||||
OP_SERIALIZER& opszr)
|
||||
{
|
||||
unsigned int dictsSize = 0;
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace CFF {
|
|||
*/
|
||||
#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
|
||||
|
||||
#define CFF_UNDEF_CODE 0xFFFFFFFF
|
||||
#define CFF_UNDEF_SID CFF_UNDEF_CODE
|
||||
|
||||
enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
|
||||
enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
|
||||
|
@ -529,13 +529,132 @@ struct Charset {
|
|||
DEFINE_SIZE_MIN (1);
|
||||
};
|
||||
|
||||
struct CFF1TopDictValues : TopDictValues
|
||||
struct CFF1StringIndex : CFF1Index
|
||||
{
|
||||
inline bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings, unsigned int offSize_, const Remap &sidmap)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
|
||||
{
|
||||
if (!unlikely (c->extend_min (*this)))
|
||||
return_trace (false);
|
||||
count.set (0);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
hb_vector_t<ByteStr> bytesArray;
|
||||
bytesArray.init ();
|
||||
if (!bytesArray.resize (sidmap.get_count ()))
|
||||
return_trace (false);
|
||||
for (unsigned int i = 0; i < strings.count; i++)
|
||||
{
|
||||
hb_codepoint_t j = sidmap[i];
|
||||
if (j != CFF_UNDEF_CODE)
|
||||
bytesArray[j] = strings[i];
|
||||
}
|
||||
|
||||
bool result = CFF1Index::serialize (c, offSize_, bytesArray);
|
||||
bytesArray.fini ();
|
||||
return_trace (result);
|
||||
}
|
||||
|
||||
/* in parallel to above */
|
||||
inline unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const Remap &sidmap) const
|
||||
{
|
||||
offSize = 0;
|
||||
if ((count == 0) || (sidmap.get_count () == 0))
|
||||
return count.static_size;
|
||||
|
||||
unsigned int dataSize = 0;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (sidmap[i] != CFF_UNDEF_CODE)
|
||||
dataSize += length_at (i);
|
||||
|
||||
offSize = calcOffSize(dataSize);
|
||||
return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize);
|
||||
}
|
||||
};
|
||||
|
||||
struct CFF1TopDictInterpEnv : NumInterpEnv
|
||||
{
|
||||
inline CFF1TopDictInterpEnv (void)
|
||||
: NumInterpEnv(), prev_offset(0), last_offset(0) {}
|
||||
|
||||
unsigned int prev_offset;
|
||||
unsigned int last_offset;
|
||||
};
|
||||
|
||||
enum NameDictValIndex
|
||||
{
|
||||
version,
|
||||
notice,
|
||||
copyright,
|
||||
fullName,
|
||||
familyName,
|
||||
weight,
|
||||
postscript,
|
||||
fontName,
|
||||
baseFontName,
|
||||
registry,
|
||||
ordering,
|
||||
|
||||
NameDictValCount
|
||||
};
|
||||
|
||||
struct NameDictValues
|
||||
{
|
||||
inline void init (void)
|
||||
{
|
||||
for (unsigned int i = 0; i < NameDictValCount; i++)
|
||||
values[i] = CFF_UNDEF_SID;
|
||||
}
|
||||
|
||||
inline unsigned int& operator[] (unsigned int i)
|
||||
{ assert (i < NameDictValCount); return values[i]; }
|
||||
|
||||
inline unsigned int operator[] (unsigned int i) const
|
||||
{ assert (i < NameDictValCount); return values[i]; }
|
||||
|
||||
static inline enum NameDictValIndex name_op_to_index (OpCode op)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_version:
|
||||
return NameDictValIndex::version;
|
||||
case OpCode_Notice:
|
||||
return NameDictValIndex::notice;
|
||||
case OpCode_Copyright:
|
||||
return NameDictValIndex::copyright;
|
||||
case OpCode_FullName:
|
||||
return NameDictValIndex::fullName;
|
||||
case OpCode_FamilyName:
|
||||
return NameDictValIndex::familyName;
|
||||
case OpCode_Weight:
|
||||
return NameDictValIndex::weight;
|
||||
case OpCode_PostScript:
|
||||
return NameDictValIndex::postscript;
|
||||
case OpCode_FontName:
|
||||
return NameDictValIndex::fontName;
|
||||
default:
|
||||
assert (0);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int values[NameDictValCount];
|
||||
};
|
||||
|
||||
struct CFF1TopDictVal : OpStr
|
||||
{
|
||||
unsigned int last_arg_offset;
|
||||
};
|
||||
|
||||
struct CFF1TopDictValues : TopDictValues<CFF1TopDictVal>
|
||||
{
|
||||
inline void init (void)
|
||||
{
|
||||
TopDictValues::init ();
|
||||
|
||||
ros[0] = ros[1] = ros[2] = 0;
|
||||
nameSIDs.init ();
|
||||
ros_supplement = 0;
|
||||
cidCount = 8720;
|
||||
EncodingOffset = 0;
|
||||
CharsetOffset = 0;
|
||||
|
@ -549,73 +668,26 @@ struct CFF1TopDictValues : TopDictValues
|
|||
}
|
||||
|
||||
inline bool is_CID (void) const
|
||||
{ return ros[0] != 0; }
|
||||
{ return nameSIDs[NameDictValIndex::registry] != CFF_UNDEF_SID; }
|
||||
|
||||
inline unsigned int calculate_serialized_size (void) const
|
||||
{
|
||||
unsigned int size = 0;
|
||||
for (unsigned int i = 0; i < getNumValues (); i++)
|
||||
{
|
||||
OpCode op = getValue (i).op;
|
||||
switch (op)
|
||||
{
|
||||
case OpCode_FDSelect:
|
||||
size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
|
||||
break;
|
||||
default:
|
||||
size += TopDictValues::calculate_serialized_op_size (getValue (i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
NameDictValues nameSIDs;
|
||||
unsigned int ros_supplement_offset;
|
||||
unsigned int ros_supplement;
|
||||
unsigned int cidCount;
|
||||
|
||||
unsigned int ros[3]; /* registry, ordering, supplement */
|
||||
unsigned int cidCount;
|
||||
|
||||
unsigned int EncodingOffset;
|
||||
unsigned int CharsetOffset;
|
||||
unsigned int FDSelectOffset;
|
||||
TableInfo privateDictInfo;
|
||||
unsigned int EncodingOffset;
|
||||
unsigned int CharsetOffset;
|
||||
unsigned int FDSelectOffset;
|
||||
TableInfo privateDictInfo;
|
||||
};
|
||||
|
||||
/* a copy of a parsed out CFF1TopDictValues augmented with additional operators */
|
||||
struct CFF1TopDictValuesMod : CFF1TopDictValues
|
||||
struct CFF1TopDictOpSet : TopDictOpSet<CFF1TopDictVal>
|
||||
{
|
||||
inline void init (const CFF1TopDictValues *base_= &Null(CFF1TopDictValues))
|
||||
static inline bool process_op (OpCode op, CFF1TopDictInterpEnv& env, CFF1TopDictValues& dictval)
|
||||
{
|
||||
SUPER::init ();
|
||||
base = base_;
|
||||
}
|
||||
CFF1TopDictVal val;
|
||||
val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
SUPER::fini ();
|
||||
}
|
||||
|
||||
inline unsigned getNumValues (void) const
|
||||
{
|
||||
return base->getNumValues () + SUPER::getNumValues ();
|
||||
}
|
||||
inline const OpStr &getValue (unsigned int i) const
|
||||
{
|
||||
if (i < base->getNumValues ())
|
||||
return (*base)[i];
|
||||
else
|
||||
return SUPER::values[i - base->getNumValues ()];
|
||||
}
|
||||
inline const OpStr &operator [] (unsigned int i) const { return getValue (i); }
|
||||
|
||||
protected:
|
||||
typedef CFF1TopDictValues SUPER;
|
||||
const CFF1TopDictValues *base;
|
||||
};
|
||||
|
||||
struct CFF1TopDictOpSet : TopDictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1TopDictValues& dictval)
|
||||
{
|
||||
|
||||
switch (op) {
|
||||
case OpCode_version:
|
||||
case OpCode_Notice:
|
||||
|
@ -623,6 +695,12 @@ struct CFF1TopDictOpSet : TopDictOpSet
|
|||
case OpCode_FullName:
|
||||
case OpCode_FamilyName:
|
||||
case OpCode_Weight:
|
||||
case OpCode_PostScript:
|
||||
case OpCode_BaseFontName:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValues::name_op_to_index (op)])))
|
||||
return false;
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_isFixedPitch:
|
||||
case OpCode_ItalicAngle:
|
||||
case OpCode_UnderlinePosition:
|
||||
|
@ -632,8 +710,6 @@ struct CFF1TopDictOpSet : TopDictOpSet
|
|||
case OpCode_UniqueID:
|
||||
case OpCode_StrokeWidth:
|
||||
case OpCode_SyntheticBase:
|
||||
case OpCode_PostScript:
|
||||
case OpCode_BaseFontName:
|
||||
case OpCode_CIDFontVersion:
|
||||
case OpCode_CIDFontRevision:
|
||||
case OpCode_CIDFontType:
|
||||
|
@ -651,9 +727,9 @@ struct CFF1TopDictOpSet : TopDictOpSet
|
|||
break;
|
||||
|
||||
case OpCode_ROS:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.ros[2]) ||
|
||||
!env.argStack.check_pop_uint (dictval.ros[1]) ||
|
||||
!env.argStack.check_pop_uint (dictval.ros[0])))
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.ros_supplement) ||
|
||||
!env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValIndex::ordering]) ||
|
||||
!env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValIndex::registry])))
|
||||
return false;
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
@ -685,6 +761,7 @@ struct CFF1TopDictOpSet : TopDictOpSet
|
|||
break;
|
||||
|
||||
default:
|
||||
env.last_offset = env.substr.offset;
|
||||
if (unlikely (!TopDictOpSet::process_op (op, env, dictval)))
|
||||
return false;
|
||||
/* Record this operand below if stack is empty, otherwise done */
|
||||
|
@ -692,7 +769,7 @@ struct CFF1TopDictOpSet : TopDictOpSet
|
|||
break;
|
||||
}
|
||||
|
||||
dictval.addOp (op, env.substr);
|
||||
dictval.addOp (op, env.substr, val);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -703,6 +780,7 @@ struct CFF1FontDictValues : DictValues<OpStr>
|
|||
{
|
||||
DictValues<OpStr>::init ();
|
||||
privateDictInfo.init ();
|
||||
fontName = CFF_UNDEF_SID;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
|
@ -710,7 +788,8 @@ struct CFF1FontDictValues : DictValues<OpStr>
|
|||
DictValues<OpStr>::fini ();
|
||||
}
|
||||
|
||||
TableInfo privateDictInfo;
|
||||
TableInfo privateDictInfo;
|
||||
unsigned int fontName;
|
||||
};
|
||||
|
||||
struct CFF1FontDictOpSet : DictOpSet
|
||||
|
@ -719,6 +798,10 @@ struct CFF1FontDictOpSet : DictOpSet
|
|||
{
|
||||
switch (op) {
|
||||
case OpCode_FontName:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.fontName)))
|
||||
return false;
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_FontMatrix:
|
||||
case OpCode_PaintType:
|
||||
env.clear_args ();
|
||||
|
@ -869,13 +952,12 @@ struct CFF1PrivateDictOpSet_Subset : DictOpSet
|
|||
}
|
||||
};
|
||||
|
||||
typedef DictInterpreter<CFF1TopDictOpSet, CFF1TopDictValues> CFF1TopDict_Interpreter;
|
||||
typedef DictInterpreter<CFF1TopDictOpSet, CFF1TopDictValues, CFF1TopDictInterpEnv> CFF1TopDict_Interpreter;
|
||||
typedef DictInterpreter<CFF1FontDictOpSet, CFF1FontDictValues> CFF1FontDict_Interpreter;
|
||||
typedef DictInterpreter<CFF1PrivateDictOpSet, CFF1PrivateDictValues> CFF1PrivateDict_Interpreter;
|
||||
|
||||
typedef CFF1Index CFF1NameIndex;
|
||||
typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
|
||||
typedef CFF1Index CFF1StringIndex;
|
||||
|
||||
}; /* namespace CFF */
|
||||
|
||||
|
@ -899,9 +981,7 @@ struct cff1
|
|||
{
|
||||
inline void init (hb_face_t *face)
|
||||
{
|
||||
topDicts.init ();
|
||||
topDicts.resize (1);
|
||||
topDicts[0].init ();
|
||||
topDict.init ();
|
||||
fontDicts.init ();
|
||||
privateDicts.init ();
|
||||
|
||||
|
@ -929,19 +1009,19 @@ struct cff1
|
|||
if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
|
||||
CFF1TopDict_Interpreter top_interp;
|
||||
top_interp.env.init (topDictStr);
|
||||
if (unlikely (!top_interp.interpret (topDicts[0]))) { fini (); return; }
|
||||
if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
|
||||
}
|
||||
|
||||
encoding = &Null(Encoding);
|
||||
charset = &StructAtOffsetOrNull<Charset> (cff, topDicts[0].CharsetOffset);
|
||||
charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
|
||||
if (unlikely (is_CID () && (charset == &Null(Charset))))
|
||||
{ fini (); return; }
|
||||
|
||||
fdCount = 1;
|
||||
if (is_CID ())
|
||||
{
|
||||
fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDicts[0].FDArrayOffset);
|
||||
fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDicts[0].FDSelectOffset);
|
||||
fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
|
||||
fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
|
||||
if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
|
||||
(fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
|
||||
{ fini (); return; }
|
||||
|
@ -954,7 +1034,7 @@ struct cff1
|
|||
fdSelect = &Null(CFF1FDSelect);
|
||||
if (!is_predef_encoding ())
|
||||
{
|
||||
encoding = &StructAtOffsetOrNull<Encoding> (cff, topDicts[0].EncodingOffset);
|
||||
encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
|
||||
if ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))
|
||||
{ fini (); return; }
|
||||
}
|
||||
|
@ -968,7 +1048,7 @@ struct cff1
|
|||
if ((globalSubrs != &Null (CFF1Subrs)) && !stringIndex->sanitize (&sc))
|
||||
{ fini (); return; }
|
||||
|
||||
charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDicts[0].charStringsOffset);
|
||||
charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
|
||||
|
||||
if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
|
||||
{ fini (); return; }
|
||||
|
@ -1008,7 +1088,7 @@ struct cff1
|
|||
}
|
||||
else /* non-CID */
|
||||
{
|
||||
CFF1TopDictValues *font = &topDicts[0];
|
||||
CFF1TopDictValues *font = &topDict;
|
||||
PRIVDICTVAL *priv = &privateDicts[0];
|
||||
|
||||
const ByteStr privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
|
||||
|
@ -1027,8 +1107,7 @@ struct cff1
|
|||
inline void fini (void)
|
||||
{
|
||||
sc.end_processing ();
|
||||
topDicts[0].fini ();
|
||||
topDicts.fini ();
|
||||
topDict.fini ();
|
||||
fontDicts.fini ();
|
||||
privateDicts.fini ();
|
||||
hb_blob_destroy (blob);
|
||||
|
@ -1036,10 +1115,10 @@ struct cff1
|
|||
}
|
||||
|
||||
inline bool is_valid (void) const { return blob != nullptr; }
|
||||
inline bool is_CID (void) const { return topDicts[0].is_CID (); }
|
||||
inline bool is_CID (void) const { return topDict.is_CID (); }
|
||||
|
||||
inline bool is_predef_encoding (void) const { return topDicts[0].EncodingOffset <= ExpertEncoding; }
|
||||
inline bool is_predef_charset (void) const { return topDicts[0].CharsetOffset <= ExpertSubsetCharset; }
|
||||
inline bool is_predef_encoding (void) const { return topDict.EncodingOffset <= ExpertEncoding; }
|
||||
inline bool is_predef_charset (void) const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
|
||||
|
||||
inline hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
|
||||
{
|
||||
|
@ -1050,7 +1129,7 @@ struct cff1
|
|||
hb_codepoint_t sid = glyph_to_sid (glyph);
|
||||
if (sid == 0) return 0;
|
||||
hb_codepoint_t code = 0;
|
||||
switch (topDicts[0].EncodingOffset)
|
||||
switch (topDict.EncodingOffset)
|
||||
{
|
||||
case StandardEncoding:
|
||||
code = lookup_standard_encoding (sid);
|
||||
|
@ -1072,7 +1151,7 @@ struct cff1
|
|||
else
|
||||
{
|
||||
hb_codepoint_t sid = 0;
|
||||
switch (topDicts[0].CharsetOffset)
|
||||
switch (topDict.CharsetOffset)
|
||||
{
|
||||
case ISOAdobeCharset:
|
||||
if (glyph <= 228 /*zcaron*/) sid = glyph;
|
||||
|
@ -1116,7 +1195,7 @@ struct cff1
|
|||
const CFF1FDSelect *fdSelect;
|
||||
unsigned int fdCount;
|
||||
|
||||
hb_vector_t<CFF1TopDictValues> topDicts;
|
||||
CFF1TopDictValues topDict;
|
||||
hb_vector_t<CFF1FontDictValues> fontDicts;
|
||||
hb_vector_t<PRIVDICTVAL> privateDicts;
|
||||
|
||||
|
|
|
@ -135,18 +135,18 @@ struct CFF2VariationStore
|
|||
DEFINE_SIZE_MIN (2 + VariationStore::min_size);
|
||||
};
|
||||
|
||||
struct CFF2TopDictValues : TopDictValues
|
||||
struct CFF2TopDictValues : TopDictValues<>
|
||||
{
|
||||
inline void init (void)
|
||||
{
|
||||
TopDictValues::init ();
|
||||
TopDictValues<>::init ();
|
||||
vstoreOffset = 0;
|
||||
FDSelectOffset = 0;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
TopDictValues::fini ();
|
||||
TopDictValues<>::fini ();
|
||||
}
|
||||
|
||||
inline unsigned int calculate_serialized_size (void) const
|
||||
|
@ -162,7 +162,7 @@ struct CFF2TopDictValues : TopDictValues
|
|||
size += OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
|
||||
break;
|
||||
default:
|
||||
size += TopDictValues::calculate_serialized_op_size (getValue (i));
|
||||
size += TopDictValues<>::calculate_serialized_op_size (getValue (i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +173,7 @@ struct CFF2TopDictValues : TopDictValues
|
|||
unsigned int FDSelectOffset;
|
||||
};
|
||||
|
||||
struct CFF2TopDictOpSet : TopDictOpSet
|
||||
struct CFF2TopDictOpSet : TopDictOpSet<>
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF2TopDictValues& dictval)
|
||||
{
|
||||
|
@ -209,7 +209,7 @@ struct CFF2TopDictOpSet : TopDictOpSet
|
|||
return true;
|
||||
}
|
||||
|
||||
typedef TopDictOpSet SUPER;
|
||||
typedef TopDictOpSet<> SUPER;
|
||||
};
|
||||
|
||||
struct CFF2FontDictValues : DictValues<OpStr>
|
||||
|
|
|
@ -46,7 +46,7 @@ hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
|
|||
unsigned int &subst_fdselect_size /* OUT */,
|
||||
unsigned int &subst_fdselect_format /* OUT */,
|
||||
hb_vector_t<hb_codepoint_t> &subst_first_glyphs /* OUT */,
|
||||
FDMap &fdmap /* OUT */)
|
||||
Remap &fdmap /* OUT */)
|
||||
{
|
||||
subset_fd_count = 0;
|
||||
subst_fdselect_size = 0;
|
||||
|
@ -62,7 +62,7 @@ hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
|
|||
hb_set_t *set = hb_set_create ();
|
||||
if (set == &Null (hb_set_t))
|
||||
return false;
|
||||
hb_codepoint_t prev_fd = HB_SET_VALUE_INVALID;
|
||||
hb_codepoint_t prev_fd = CFF_UNDEF_CODE;
|
||||
for (hb_codepoint_t i = 0; i < subset_num_glyphs; i++)
|
||||
{
|
||||
hb_codepoint_t fd = src.get_fd (glyphs[i]);
|
||||
|
@ -85,14 +85,16 @@ hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
|
|||
}
|
||||
|
||||
/* create a fdmap */
|
||||
fdmap.resize (fdCount);
|
||||
for (unsigned int i = 0; i < fdmap.len; i++)
|
||||
fdmap[i] = HB_SET_VALUE_INVALID;
|
||||
hb_codepoint_t fd = HB_SET_VALUE_INVALID;
|
||||
unsigned int fdindex = 0;
|
||||
if (!fdmap.reset (fdCount))
|
||||
{
|
||||
hb_set_destroy (set);
|
||||
return false;
|
||||
}
|
||||
|
||||
hb_codepoint_t fd = CFF_UNDEF_CODE;
|
||||
while (set->next (&fd))
|
||||
fdmap[fd] = fdindex++;
|
||||
assert (fdindex == subset_fd_count);
|
||||
fdmap.add (fd);
|
||||
assert (fdmap.get_count () == subset_fd_count);
|
||||
hb_set_destroy (set);
|
||||
}
|
||||
|
||||
|
@ -131,7 +133,7 @@ serialize_fdselect_3_4 (hb_serialize_context_t *c,
|
|||
const FDSelect &src,
|
||||
unsigned int size,
|
||||
const hb_vector_t<hb_codepoint_t> &first_glyphs,
|
||||
const FDMap &fdmap)
|
||||
const Remap &fdmap)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
|
||||
|
@ -159,7 +161,7 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c,
|
|||
unsigned int fdselect_format,
|
||||
unsigned int size,
|
||||
const hb_vector_t<hb_codepoint_t> &first_glyphs,
|
||||
const FDMap &fdmap)
|
||||
const Remap &fdmap)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
FDSelect *p = c->allocate_min<FDSelect> ();
|
||||
|
|
|
@ -129,10 +129,11 @@ struct CFFSubTableOffsets {
|
|||
hb_vector_t<TableInfo> localSubrsInfos;
|
||||
};
|
||||
|
||||
template <typename OPSTR=OpStr>
|
||||
struct CFFTopDict_OpSerializer : OpSerializer
|
||||
{
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
const OpStr &opstr,
|
||||
const OPSTR &opstr,
|
||||
const CFFSubTableOffsets &offsets) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
@ -154,7 +155,7 @@ struct CFFTopDict_OpSerializer : OpSerializer
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
inline unsigned int calculate_serialized_size (const OpStr &opstr) const
|
||||
inline unsigned int calculate_serialized_size (const OPSTR &opstr) const
|
||||
{
|
||||
switch (opstr.op)
|
||||
{
|
||||
|
@ -162,7 +163,7 @@ struct CFFTopDict_OpSerializer : OpSerializer
|
|||
case OpCode_FDArray:
|
||||
case OpCode_FDSelect:
|
||||
return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
|
||||
|
||||
|
||||
default:
|
||||
return opstr.str.len;
|
||||
}
|
||||
|
@ -179,12 +180,9 @@ struct CFFFontDict_OpSerializer : OpSerializer
|
|||
|
||||
if (opstr.op == OpCode_Private)
|
||||
{
|
||||
/* serialize the private dict size as a 2-byte integer */
|
||||
if (unlikely (!UnsizedByteStr::serialize_int2 (c, privateDictInfo.size)))
|
||||
return_trace (false);
|
||||
|
||||
/* serialize the private dict offset as a 4-byte integer */
|
||||
if (unlikely (!UnsizedByteStr::serialize_int4 (c, privateDictInfo.offset)))
|
||||
/* serialize the private dict size & offset as 2-byte & 4-byte integers */
|
||||
if (unlikely (!UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) ||
|
||||
!UnsizedByteStr::serialize_int4 (c, privateDictInfo.offset)))
|
||||
return_trace (false);
|
||||
|
||||
/* serialize the opcode */
|
||||
|
@ -386,7 +384,7 @@ hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
|
|||
unsigned int &subst_fdselect_size /* OUT */,
|
||||
unsigned int &subst_fdselect_format /* OUT */,
|
||||
hb_vector_t<hb_codepoint_t> &subst_first_glyphs /* OUT */,
|
||||
CFF::FDMap &fdmap /* OUT */);
|
||||
CFF::Remap &fdmap /* OUT */);
|
||||
|
||||
HB_INTERNAL bool
|
||||
hb_serialize_cff_fdselect (hb_serialize_context_t *c,
|
||||
|
@ -396,6 +394,6 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c,
|
|||
unsigned int fdselect_format,
|
||||
unsigned int size,
|
||||
const hb_vector_t<hb_codepoint_t> &first_glyphs,
|
||||
const CFF::FDMap &fdmap);
|
||||
const CFF::Remap &fdmap);
|
||||
|
||||
#endif /* HB_SUBSET_CFF_COMMON_HH */
|
||||
|
|
|
@ -34,46 +34,122 @@
|
|||
|
||||
using namespace CFF;
|
||||
|
||||
struct RemapSID : Remap
|
||||
{
|
||||
inline unsigned int add (unsigned int sid)
|
||||
{
|
||||
if ((sid != CFF_UNDEF_SID) && !is_std_std (sid))
|
||||
return offset_sid (Remap::add (unoffset_sid (sid)));
|
||||
else
|
||||
return sid;
|
||||
}
|
||||
|
||||
inline unsigned int operator[] (unsigned int sid) const
|
||||
{
|
||||
if (is_std_std (sid))
|
||||
return sid;
|
||||
else
|
||||
return offset_sid (Remap::operator [] (unoffset_sid (sid)));
|
||||
}
|
||||
|
||||
static const unsigned int num_std_strings = 391;
|
||||
|
||||
static inline bool is_std_std (unsigned int sid) { return sid < num_std_strings; }
|
||||
static inline unsigned int offset_sid (unsigned int sid) { return sid + num_std_strings; }
|
||||
static inline unsigned int unoffset_sid (unsigned int sid) { return sid - num_std_strings; }
|
||||
};
|
||||
|
||||
struct CFF1SubTableOffsets : CFFSubTableOffsets
|
||||
{
|
||||
inline CFF1SubTableOffsets (void)
|
||||
: CFFSubTableOffsets (),
|
||||
nameIndexOffset (0),
|
||||
stringIndexOffset (0),
|
||||
encodingOffset (0),
|
||||
charsetOffset (0)
|
||||
encodingOffset (0)
|
||||
{
|
||||
stringIndexInfo.init ();
|
||||
charsetInfo.init ();
|
||||
privateDictInfo.init ();
|
||||
}
|
||||
|
||||
unsigned int nameIndexOffset;
|
||||
unsigned int stringIndexOffset;
|
||||
TableInfo stringIndexInfo;
|
||||
unsigned int encodingOffset;
|
||||
unsigned int charsetOffset;
|
||||
TableInfo charsetInfo;
|
||||
TableInfo privateDictInfo;
|
||||
};
|
||||
|
||||
struct CFF1TopDict_OpSerializer : CFFTopDict_OpSerializer
|
||||
/* a copy of a parsed out CFF1TopDictValues augmented with additional operators */
|
||||
struct CFF1TopDictValuesMod : CFF1TopDictValues
|
||||
{
|
||||
inline void init (const CFF1TopDictValues *base_= &Null(CFF1TopDictValues))
|
||||
{
|
||||
SUPER::init ();
|
||||
base = base_;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
{
|
||||
SUPER::fini ();
|
||||
}
|
||||
|
||||
inline unsigned getNumValues (void) const
|
||||
{
|
||||
return base->getNumValues () + SUPER::getNumValues ();
|
||||
}
|
||||
inline const CFF1TopDictVal &getValue (unsigned int i) const
|
||||
{
|
||||
if (i < base->getNumValues ())
|
||||
return (*base)[i];
|
||||
else
|
||||
return SUPER::values[i - base->getNumValues ()];
|
||||
}
|
||||
inline const CFF1TopDictVal &operator [] (unsigned int i) const { return getValue (i); }
|
||||
|
||||
inline void reassignSIDs (const RemapSID& sidmap)
|
||||
{
|
||||
for (unsigned int i = 0; i < NameDictValCount; i++)
|
||||
nameSIDs[i] = sidmap[base->nameSIDs[i]];
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef CFF1TopDictValues SUPER;
|
||||
const CFF1TopDictValues *base;
|
||||
};
|
||||
|
||||
struct TopDictModifiers
|
||||
{
|
||||
inline TopDictModifiers (const CFF1SubTableOffsets &offsets_,
|
||||
const unsigned int (&nameSIDs_)[NameDictValCount])
|
||||
: offsets (offsets_),
|
||||
nameSIDs (nameSIDs_)
|
||||
{}
|
||||
|
||||
const CFF1SubTableOffsets &offsets;
|
||||
const unsigned int (&nameSIDs)[NameDictValCount];
|
||||
};
|
||||
|
||||
struct CFF1TopDict_OpSerializer : CFFTopDict_OpSerializer<CFF1TopDictVal>
|
||||
{
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
const OpStr &opstr,
|
||||
const CFF1SubTableOffsets &offsets) const
|
||||
const CFF1TopDictVal &opstr,
|
||||
const TopDictModifiers &mod) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
switch (opstr.op)
|
||||
OpCode op = opstr.op;
|
||||
switch (op)
|
||||
{
|
||||
case OpCode_charset:
|
||||
return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.charsetOffset));
|
||||
return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.charsetInfo.offset));
|
||||
|
||||
case OpCode_Encoding:
|
||||
return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.encodingOffset));
|
||||
return_trace (FontDict::serialize_offset4_op(c, op, mod.offsets.encodingOffset));
|
||||
|
||||
case OpCode_Private:
|
||||
{
|
||||
if (unlikely (!UnsizedByteStr::serialize_int2 (c, offsets.privateDictInfo.size)))
|
||||
if (unlikely (!UnsizedByteStr::serialize_int2 (c, mod.offsets.privateDictInfo.size)))
|
||||
return_trace (false);
|
||||
if (unlikely (!UnsizedByteStr::serialize_int4 (c, offsets.privateDictInfo.offset)))
|
||||
if (unlikely (!UnsizedByteStr::serialize_int4 (c, mod.offsets.privateDictInfo.offset)))
|
||||
return_trace (false);
|
||||
HBUINT8 *p = c->allocate_size<HBUINT8> (1);
|
||||
if (unlikely (p == nullptr)) return_trace (false);
|
||||
|
@ -81,29 +157,117 @@ struct CFF1TopDict_OpSerializer : CFFTopDict_OpSerializer
|
|||
}
|
||||
break;
|
||||
|
||||
case OpCode_version:
|
||||
case OpCode_Notice:
|
||||
case OpCode_Copyright:
|
||||
case OpCode_FullName:
|
||||
case OpCode_FamilyName:
|
||||
case OpCode_Weight:
|
||||
case OpCode_PostScript:
|
||||
case OpCode_BaseFontName:
|
||||
case OpCode_FontName:
|
||||
return_trace (FontDict::serialize_offset2_op(c, op, mod.nameSIDs[NameDictValues::name_op_to_index (op)]));
|
||||
|
||||
case OpCode_ROS:
|
||||
{
|
||||
/* for registry & ordering, reassigned SIDs are serialized
|
||||
* for supplement, the original byte string is copied along with the op code */
|
||||
OpStr supp_op;
|
||||
supp_op.op = op;
|
||||
supp_op.str.str = opstr.str.str + opstr.last_arg_offset;
|
||||
assert (opstr.str.len >= opstr.last_arg_offset + 3);
|
||||
supp_op.str.len = opstr.str.len - opstr.last_arg_offset;
|
||||
return_trace (UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[NameDictValIndex::registry]) &&
|
||||
UnsizedByteStr::serialize_int2 (c, mod.nameSIDs[NameDictValIndex::ordering]) &&
|
||||
copy_opstr (c, supp_op));
|
||||
}
|
||||
default:
|
||||
return_trace (CFFTopDict_OpSerializer::serialize (c, opstr, offsets));
|
||||
return_trace (CFFTopDict_OpSerializer<CFF1TopDictVal>::serialize (c, opstr, mod.offsets));
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline unsigned int calculate_serialized_size (const OpStr &opstr) const
|
||||
inline unsigned int calculate_serialized_size (const CFF1TopDictVal &opstr) const
|
||||
{
|
||||
switch (opstr.op)
|
||||
OpCode op = opstr.op;
|
||||
switch (op)
|
||||
{
|
||||
case OpCode_charset:
|
||||
case OpCode_Encoding:
|
||||
return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
|
||||
return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (op);
|
||||
|
||||
case OpCode_Private:
|
||||
return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Private);
|
||||
|
||||
case OpCode_version:
|
||||
case OpCode_Notice:
|
||||
case OpCode_Copyright:
|
||||
case OpCode_FullName:
|
||||
case OpCode_FamilyName:
|
||||
case OpCode_Weight:
|
||||
case OpCode_PostScript:
|
||||
case OpCode_BaseFontName:
|
||||
case OpCode_FontName:
|
||||
return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (op);
|
||||
|
||||
case OpCode_ROS:
|
||||
return ((OpCode_Size (OpCode_shortint) + 2) * 2) + (opstr.str.len - opstr.last_arg_offset)/* supplement + op */;
|
||||
|
||||
default:
|
||||
return CFFTopDict_OpSerializer::calculate_serialized_size (opstr);
|
||||
return CFFTopDict_OpSerializer<CFF1TopDictVal>::calculate_serialized_size (opstr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct FontDictValuesMod
|
||||
{
|
||||
inline void init (const CFF1FontDictValues *base_,
|
||||
unsigned int fontName_,
|
||||
const TableInfo &privateDictInfo_)
|
||||
{
|
||||
base = base_;
|
||||
fontName = fontName_;
|
||||
privateDictInfo = privateDictInfo_;
|
||||
}
|
||||
|
||||
inline unsigned getNumValues (void) const
|
||||
{
|
||||
return base->getNumValues ();
|
||||
}
|
||||
|
||||
inline const OpStr &operator [] (unsigned int i) const { return (*base)[i]; }
|
||||
|
||||
const CFF1FontDictValues *base;
|
||||
TableInfo privateDictInfo;
|
||||
unsigned int fontName;
|
||||
};
|
||||
|
||||
struct CFF1FontDict_OpSerializer : CFFFontDict_OpSerializer
|
||||
{
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
const OpStr &opstr,
|
||||
const FontDictValuesMod &mod) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
||||
if (opstr.op == OpCode_FontName)
|
||||
return_trace (FontDict::serialize_uint2_op (c, opstr.op, mod.fontName));
|
||||
else
|
||||
return_trace (SUPER::serialize (c, opstr, mod.privateDictInfo));
|
||||
}
|
||||
|
||||
inline unsigned int calculate_serialized_size (const OpStr &opstr) const
|
||||
{
|
||||
if (opstr.op == OpCode_FontName)
|
||||
return OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_FontName);
|
||||
else
|
||||
return SUPER::calculate_serialized_size (opstr);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef CFFFontDict_OpSerializer SUPER;
|
||||
};
|
||||
|
||||
struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam>
|
||||
{
|
||||
static inline void flush_args_and_op (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param)
|
||||
|
@ -199,11 +363,14 @@ struct cff_subset_plan {
|
|||
fdmap.init ();
|
||||
subset_charstrings.init ();
|
||||
flat_charstrings.init ();
|
||||
privateDictInfos.init ();
|
||||
fontdicts_mod.init ();
|
||||
subrRefMaps.init ();
|
||||
subset_enc_code_ranges.init ();
|
||||
subset_enc_supp_codes.init ();
|
||||
subset_charset_ranges.init ();
|
||||
sidmap.init ();
|
||||
for (unsigned int i = 0; i < NameDictValCount; i++)
|
||||
topDictModSIDs[i] = CFF_UNDEF_SID;
|
||||
}
|
||||
|
||||
inline ~cff_subset_plan (void)
|
||||
|
@ -214,11 +381,13 @@ struct cff_subset_plan {
|
|||
fdmap.fini ();
|
||||
subset_charstrings.fini ();
|
||||
flat_charstrings.fini ();
|
||||
privateDictInfos.fini ();
|
||||
fontdicts_mod.fini ();
|
||||
subrRefMaps.fini ();
|
||||
subset_enc_code_ranges.fini ();
|
||||
subset_enc_supp_codes.init ();
|
||||
subset_charset_ranges.fini ();
|
||||
sidmap.fini ();
|
||||
fontdicts_mod.fini ();
|
||||
}
|
||||
|
||||
inline unsigned int plan_subset_encoding (const OT::cff1::accelerator_subset_t &acc, hb_subset_plan_t *plan)
|
||||
|
@ -303,6 +472,9 @@ struct cff_subset_plan {
|
|||
hb_codepoint_t orig_glyph = plan->glyphs[glyph];
|
||||
sid = acc.glyph_to_sid (orig_glyph);
|
||||
|
||||
if (!acc.is_CID ())
|
||||
sid = sidmap.add (sid);
|
||||
|
||||
if (sid != last_sid + 1)
|
||||
{
|
||||
if (subset_charset_ranges.len > 0)
|
||||
|
@ -342,6 +514,29 @@ struct cff_subset_plan {
|
|||
subset_charset_format? subset_charset_ranges.len: plan->glyphs.len);
|
||||
}
|
||||
|
||||
inline bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc)
|
||||
{
|
||||
if (unlikely (!sidmap.reset (acc.stringIndex->count)))
|
||||
return false;
|
||||
|
||||
for (unsigned int i = 0; i < NameDictValCount; i++)
|
||||
{
|
||||
unsigned int sid = acc.topDict.nameSIDs[i];
|
||||
if (sid != CFF_UNDEF_SID)
|
||||
{
|
||||
(void)sidmap.add (sid);
|
||||
topDictModSIDs[i] = sidmap[sid];
|
||||
}
|
||||
}
|
||||
|
||||
if (acc.fdArray != &Null(CFF1FDArray))
|
||||
for (unsigned int fd = 0; fd < orig_fdcount; fd++)
|
||||
if (!fdmap.excludes (fd))
|
||||
(void)sidmap.add (acc.fontDicts[fd].fontName);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool create (const OT::cff1::accelerator_subset_t &acc,
|
||||
hb_subset_plan_t *plan)
|
||||
{
|
||||
|
@ -376,9 +571,9 @@ struct cff_subset_plan {
|
|||
/* top dict INDEX */
|
||||
{
|
||||
/* Add encoding/charset to a (copy of) top dict as necessary */
|
||||
topdict_mod.init (&acc.topDicts[0]);
|
||||
bool need_to_add_enc = (subset_encoding && !acc.topDicts[0].hasOp (OpCode_Encoding));
|
||||
bool need_to_add_set = (subset_charset && !acc.topDicts[0].hasOp (OpCode_charset));
|
||||
topdict_mod.init (&acc.topDict);
|
||||
bool need_to_add_enc = (subset_encoding && !acc.topDict.hasOp (OpCode_Encoding));
|
||||
bool need_to_add_set = (subset_charset && !acc.topDict.hasOp (OpCode_charset));
|
||||
if (need_to_add_enc || need_to_add_set)
|
||||
{
|
||||
if (need_to_add_enc)
|
||||
|
@ -395,9 +590,36 @@ struct cff_subset_plan {
|
|||
&topdict_mod, 1, topdict_sizes, topSzr);
|
||||
}
|
||||
|
||||
/* Determine re-mapping of font index as fdmap among other info */
|
||||
if (acc.fdSelect != &Null(CFF1FDSelect)
|
||||
&& unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
|
||||
orig_fdcount,
|
||||
*acc.fdSelect,
|
||||
subset_fdcount,
|
||||
offsets.FDSelectInfo.size,
|
||||
subset_fdselect_format,
|
||||
subset_fdselect_first_glyphs,
|
||||
fdmap)))
|
||||
return false;
|
||||
|
||||
/* remove unused SIDs & reassign SIDs */
|
||||
{
|
||||
/* SIDs for name strings in dicts are added before glyph names so they fit in 16-bit int range */
|
||||
if (unlikely (!collect_sids_in_dicts (acc)))
|
||||
return false;
|
||||
assert (sidmap.get_count () <= 0x8000);
|
||||
if (subset_charset)
|
||||
offsets.charsetInfo.size = plan_subset_charset (acc, plan);
|
||||
|
||||
topdict_mod.reassignSIDs (sidmap);
|
||||
}
|
||||
|
||||
/* String INDEX */
|
||||
offsets.stringIndexOffset = final_size;
|
||||
final_size += acc.stringIndex->get_size ();
|
||||
{
|
||||
offsets.stringIndexInfo.offset = final_size;
|
||||
offsets.stringIndexInfo.size = acc.stringIndex->calculate_serialized_size (offsets.stringIndexInfo.offSize, sidmap);
|
||||
final_size += offsets.stringIndexInfo.size;
|
||||
}
|
||||
|
||||
if (flatten_subrs)
|
||||
{
|
||||
|
@ -433,24 +655,13 @@ struct cff_subset_plan {
|
|||
final_size += plan_subset_encoding (acc, plan);
|
||||
|
||||
/* Charset */
|
||||
offsets.charsetOffset = final_size;
|
||||
if (subset_charset)
|
||||
final_size += plan_subset_charset (acc, plan);
|
||||
offsets.charsetInfo.offset = final_size;
|
||||
final_size += offsets.charsetInfo.size;
|
||||
|
||||
/* FDSelect */
|
||||
if (acc.fdSelect != &Null(CFF1FDSelect))
|
||||
{
|
||||
offsets.FDSelectInfo.offset = final_size;
|
||||
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs,
|
||||
orig_fdcount,
|
||||
*acc.fdSelect,
|
||||
subset_fdcount,
|
||||
offsets.FDSelectInfo.size,
|
||||
subset_fdselect_format,
|
||||
subset_fdselect_first_glyphs,
|
||||
fdmap)))
|
||||
return false;
|
||||
|
||||
if (!is_fds_subsetted ())
|
||||
offsets.FDSelectInfo.size = acc.fdSelect->calculate_serialized_size (acc.num_glyphs);
|
||||
final_size += offsets.FDSelectInfo.size;
|
||||
|
@ -459,8 +670,14 @@ struct cff_subset_plan {
|
|||
/* FDArray (FDIndex) */
|
||||
if (acc.fdArray != &Null(CFF1FDArray)) {
|
||||
offsets.FDArrayInfo.offset = final_size;
|
||||
CFFFontDict_OpSerializer fontSzr;
|
||||
final_size += CFF1FDArray::calculate_serialized_size(offsets.FDArrayInfo.offSize/*OUT*/, acc.fontDicts, subset_fdcount, fdmap, fontSzr);
|
||||
CFF1FontDict_OpSerializer fontSzr;
|
||||
unsigned int dictsSize = 0;
|
||||
for (unsigned int i = 0; i < acc.fontDicts.len; i++)
|
||||
if (!fdmap.excludes (i))
|
||||
dictsSize += FontDict::calculate_serialized_size (acc.fontDicts[i], fontSzr);
|
||||
|
||||
offsets.FDArrayInfo.offSize = calcOffSize (dictsSize + 1);
|
||||
final_size += CFF1Index::calculate_serialized_size (offsets.FDArrayInfo.offSize, subset_fdcount, dictsSize);
|
||||
}
|
||||
|
||||
/* CharStrings */
|
||||
|
@ -493,11 +710,12 @@ struct cff_subset_plan {
|
|||
{
|
||||
if (!fdmap.excludes (i))
|
||||
{
|
||||
unsigned int priv_size;
|
||||
CFFPrivateDict_OpSerializer privSzr (plan->drop_hints, flatten_subrs);
|
||||
priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr);
|
||||
unsigned int priv_size = PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr);
|
||||
TableInfo privInfo = { final_size, priv_size, 0 };
|
||||
privateDictInfos.push (privInfo);
|
||||
FontDictValuesMod fontdict_mod;
|
||||
fontdict_mod.init ( &acc.fontDicts[i], sidmap[acc.fontDicts[i].fontName], privInfo );
|
||||
fontdicts_mod.push (fontdict_mod);
|
||||
final_size += privInfo.size;
|
||||
if (!flatten_subrs)
|
||||
final_size += offsets.localSubrsInfos[i].size;
|
||||
|
@ -505,10 +723,10 @@ struct cff_subset_plan {
|
|||
}
|
||||
|
||||
if (!acc.is_CID ())
|
||||
offsets.privateDictInfo = privateDictInfos[0];
|
||||
offsets.privateDictInfo = fontdicts_mod[0].privateDictInfo;
|
||||
|
||||
return ((subset_charstrings.len == plan->glyphs.len) &&
|
||||
(privateDictInfos.len == subset_fdcount));
|
||||
(fontdicts_mod.len == subset_fdcount));
|
||||
}
|
||||
|
||||
inline unsigned int get_final_size (void) const { return final_size; }
|
||||
|
@ -526,12 +744,12 @@ struct cff_subset_plan {
|
|||
hb_vector_t<hb_codepoint_t> subset_fdselect_first_glyphs;
|
||||
|
||||
/* font dict index remap table from fullset FDArray to subset FDArray.
|
||||
* set to HB_SET_VALUE_INVALID if excluded from subset */
|
||||
FDMap fdmap;
|
||||
* set to CFF_UNDEF_CODE if excluded from subset */
|
||||
Remap fdmap;
|
||||
|
||||
hb_vector_t<ByteStr> subset_charstrings;
|
||||
ByteStrBuffArray flat_charstrings;
|
||||
hb_vector_t<TableInfo> privateDictInfos;
|
||||
hb_vector_t<FontDictValuesMod> fontdicts_mod;
|
||||
|
||||
SubrRefMaps subrRefMaps;
|
||||
|
||||
|
@ -548,6 +766,9 @@ struct cff_subset_plan {
|
|||
uint8_t subset_charset_format;
|
||||
hb_vector_t<code_pair> subset_charset_ranges;
|
||||
bool subset_charset;
|
||||
|
||||
RemapSID sidmap;
|
||||
unsigned int topDictModSIDs[NameDictValCount];
|
||||
};
|
||||
|
||||
static inline bool _write_cff1 (const cff_subset_plan &plan,
|
||||
|
@ -589,9 +810,10 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
|||
CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict> > ();
|
||||
if (dest == nullptr) return false;
|
||||
CFF1TopDict_OpSerializer topSzr;
|
||||
TopDictModifiers modifier (plan.offsets, plan.topDictModSIDs);
|
||||
if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize,
|
||||
&plan.topdict_mod, 1,
|
||||
plan.topdict_sizes, topSzr, plan.offsets)))
|
||||
plan.topdict_sizes, topSzr, modifier)))
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF top dict");
|
||||
return false;
|
||||
|
@ -600,10 +822,10 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
|||
|
||||
/* String INDEX */
|
||||
{
|
||||
assert (plan.offsets.stringIndexOffset == c.head - c.start);
|
||||
assert (plan.offsets.stringIndexInfo.offset == c.head - c.start);
|
||||
CFF1StringIndex *dest = c.start_embed<CFF1StringIndex> ();
|
||||
if (unlikely (dest == nullptr)) return false;
|
||||
if (unlikely (!dest->serialize (&c, *acc.stringIndex)))
|
||||
if (unlikely (!dest->serialize (&c, *acc.stringIndex, plan.offsets.stringIndexInfo.offSize, plan.sidmap)))
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF string INDEX");
|
||||
return false;
|
||||
|
@ -643,7 +865,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
|||
/* Charset */
|
||||
if (plan.subset_charset)
|
||||
{
|
||||
assert (plan.offsets.charsetOffset == c.head - c.start);
|
||||
assert (plan.offsets.charsetInfo.offset == c.head - c.start);
|
||||
Charset *dest = c.start_embed<Charset> ();
|
||||
if (unlikely (dest == nullptr)) return false;
|
||||
if (unlikely (!dest->serialize (&c,
|
||||
|
@ -689,10 +911,10 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
|||
assert (plan.offsets.FDArrayInfo.offset == c.head - c.start);
|
||||
CFF1FDArray *fda = c.start_embed<CFF1FDArray> ();
|
||||
if (unlikely (fda == nullptr)) return false;
|
||||
CFFFontDict_OpSerializer fontSzr;
|
||||
CFF1FontDict_OpSerializer fontSzr;
|
||||
if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize,
|
||||
acc.fontDicts, plan.subset_fdcount, plan.fdmap,
|
||||
fontSzr, plan.privateDictInfos)))
|
||||
plan.fontdicts_mod,
|
||||
fontSzr)))
|
||||
{
|
||||
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF FDArray");
|
||||
return false;
|
||||
|
@ -719,7 +941,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
|
|||
{
|
||||
PrivateDict *pd = c.start_embed<PrivateDict> ();
|
||||
if (unlikely (pd == nullptr)) return false;
|
||||
unsigned int priv_size = plan.flatten_subrs? 0: plan.privateDictInfos[plan.fdmap[i]].size;
|
||||
unsigned int priv_size = plan.flatten_subrs? 0: plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
|
||||
bool result;
|
||||
CFFPrivateDict_OpSerializer privSzr (plan.drop_hints, plan.flatten_subrs);
|
||||
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
|
||||
|
|
|
@ -44,7 +44,7 @@ struct CFF2SubTableOffsets : CFFSubTableOffsets
|
|||
unsigned int varStoreOffset;
|
||||
};
|
||||
|
||||
struct CFF2TopDict_OpSerializer : CFFTopDict_OpSerializer
|
||||
struct CFF2TopDict_OpSerializer : CFFTopDict_OpSerializer<>
|
||||
{
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
const OpStr &opstr,
|
||||
|
@ -58,7 +58,7 @@ struct CFF2TopDict_OpSerializer : CFFTopDict_OpSerializer
|
|||
return_trace (FontDict::serialize_offset4_op(c, opstr.op, offsets.varStoreOffset));
|
||||
|
||||
default:
|
||||
return_trace (CFFTopDict_OpSerializer::serialize (c, opstr, offsets));
|
||||
return_trace (CFFTopDict_OpSerializer<>::serialize (c, opstr, offsets));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ struct CFF2TopDict_OpSerializer : CFFTopDict_OpSerializer
|
|||
return OpCode_Size (OpCode_longintdict) + 4 + OpCode_Size (opstr.op);
|
||||
|
||||
default:
|
||||
return CFFTopDict_OpSerializer::calculate_serialized_size (opstr);
|
||||
return CFFTopDict_OpSerializer<>::calculate_serialized_size (opstr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -355,7 +355,7 @@ struct cff2_subset_plan {
|
|||
unsigned int subset_fdselect_format;
|
||||
hb_vector_t<hb_codepoint_t> subset_fdselect_first_glyphs;
|
||||
|
||||
FDMap fdmap;
|
||||
Remap fdmap;
|
||||
|
||||
hb_vector_t<ByteStr> subset_charstrings;
|
||||
ByteStrBuffArray flat_charstrings;
|
||||
|
|
Loading…
Reference in New Issue