[cff] Use switch on multi-format structs (#1762)

This commit is contained in:
Ebrahim Byagowi 2019-06-09 11:49:25 +04:30 committed by GitHub
parent eff579f743
commit 9b853f755d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 235 additions and 207 deletions

View File

@ -76,8 +76,8 @@ struct biased_subrs_t
void fini () {} void fini () {}
unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; } unsigned int get_count () const { return (subrs == nullptr) ? 0 : subrs->count; }
unsigned int get_bias () const { return bias; } unsigned int get_bias () const { return bias; }
byte_str_t operator [] (unsigned int index) const byte_str_t operator [] (unsigned int index) const
{ {

View File

@ -134,10 +134,10 @@ struct dict_opset_t : opset_t<number_t>
return value; return value;
case END: case END:
value = (double)(neg? -int_part: int_part); value = (double) (neg ? -int_part : int_part);
if (frac_count > 0) if (frac_count > 0)
{ {
double frac = (frac_part / pow (10.0, (double)frac_count)); double frac = (frac_part / pow (10.0, (double) frac_count));
if (neg) frac = -frac; if (neg) frac = -frac;
value += frac; value += frac;
} }
@ -146,16 +146,16 @@ struct dict_opset_t : opset_t<number_t>
if (value == 0.0) if (value == 0.0)
return value; return value;
if (exp_neg) if (exp_neg)
return neg? -DBL_MIN: DBL_MIN; return neg ? -DBL_MIN : DBL_MIN;
else else
return neg? -DBL_MAX: DBL_MAX; return neg ? -DBL_MAX : DBL_MAX;
} }
if (exp_part != 0) if (exp_part != 0)
{ {
if (exp_neg) if (exp_neg)
value /= pow (10.0, (double)exp_part); value /= pow (10.0, (double) exp_part);
else else
value *= pow (10.0, (double)exp_part); value *= pow (10.0, (double) exp_part);
} }
return value; return value;

View File

@ -82,22 +82,14 @@ struct str_buff_vec_t : hb_vector_t<str_buff_t>
template <typename COUNT> template <typename COUNT>
struct CFFIndex struct CFFIndex
{ {
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
(c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
c->check_array (offsets, offSize, count + 1) &&
c->check_array ((const HBUINT8*)data_base (), 1, max_offset () - 1))));
}
static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count) static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count)
{ return offSize * (count + 1); } { return offSize * (count + 1); }
unsigned int offset_array_size () const unsigned int offset_array_size () const
{ return calculate_offset_array_size (offSize, count); } { return calculate_offset_array_size (offSize, count); }
static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count, unsigned int dataSize) static unsigned int calculate_serialized_size (unsigned int offSize_, unsigned int count,
unsigned int dataSize)
{ {
if (count == 0) if (count == 0)
return COUNT::static_size; return COUNT::static_size;
@ -199,11 +191,11 @@ struct CFFIndex
unsigned int length_at (unsigned int index) const unsigned int length_at (unsigned int index) const
{ {
if (likely ((offset_at (index + 1) >= offset_at (index)) && if (likely ((offset_at (index + 1) >= offset_at (index)) &&
(offset_at (index + 1) <= offset_at (count)))) (offset_at (index + 1) <= offset_at (count))))
return offset_at (index + 1) - offset_at (index); return offset_at (index + 1) - offset_at (index);
else else
return 0; return 0;
} }
const unsigned char *data_base () const const unsigned char *data_base () const
@ -216,12 +208,12 @@ struct CFFIndex
if (likely (index < count)) if (likely (index < count))
return byte_str_t (data_base () + offset_at (index) - 1, length_at (index)); return byte_str_t (data_base () + offset_at (index) - 1, length_at (index));
else else
return Null(byte_str_t); return Null (byte_str_t);
} }
unsigned int get_size () const unsigned int get_size () const
{ {
if (this != &Null(CFFIndex)) if (this != &Null (CFFIndex))
{ {
if (count > 0) if (count > 0)
return min_size + offset_array_size () + (offset_at (count) - 1); return min_size + offset_array_size () + (offset_at (count) - 1);
@ -232,6 +224,15 @@ struct CFFIndex
return 0; return 0;
} }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */
(c->check_struct (this) && offSize >= 1 && offSize <= 4 &&
c->check_array (offsets, offSize, count + 1) &&
c->check_array ((const HBUINT8*) data_base (), 1, max_offset () - 1))));
}
protected: protected:
unsigned int max_offset () const unsigned int max_offset () const
{ {
@ -245,10 +246,10 @@ struct CFFIndex
} }
public: public:
COUNT count; /* Number of object data. Note there are (count+1) offsets */ COUNT count; /* Number of object data. Note there are (count+1) offsets */
HBUINT8 offSize; /* The byte size of each offset in the offsets array. */ HBUINT8 offSize; /* The byte size of each offset in the offsets array. */
HBUINT8 offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */ HBUINT8 offsets[VAR]; /* The array of (count + 1) offsets into objects array (1-base). */
/* HBUINT8 data[VAR]; Object data */ /* HBUINT8 data[VAR]; Object data */
public: public:
DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets); DEFINE_SIZE_ARRAY (COUNT::static_size + HBUINT8::static_size, offsets);
}; };
@ -293,7 +294,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
/* serialize data */ /* serialize data */
for (unsigned int i = 0; i < dataArrayLen; i++) for (unsigned int i = 0; i < dataArrayLen; i++)
{ {
TYPE *dest = c->start_embed<TYPE> (); TYPE *dest = c->start_embed<TYPE> ();
if (unlikely (dest == nullptr || if (unlikely (dest == nullptr ||
!dest->serialize (c, dataArray[i], param1, param2))) !dest->serialize (c, dataArray[i], param1, param2)))
return_trace (false); return_trace (false);
@ -310,7 +311,7 @@ struct CFFIndexOf : CFFIndex<COUNT>
const PARAM &param) const PARAM &param)
{ {
/* determine offset size */ /* determine offset size */
unsigned int totalDataSize = 0; unsigned int totalDataSize = 0;
for (unsigned int i = 0; i < dataArrayLen; i++) for (unsigned int i = 0; i < dataArrayLen; i++)
{ {
unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param); unsigned int dataSize = TYPE::calculate_serialized_size (dataArray[i], param);
@ -334,10 +335,9 @@ struct Dict : UnsizedByteStr
{ {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
for (unsigned int i = 0; i < dictval.get_count (); i++) for (unsigned int i = 0; i < dictval.get_count (); i++)
{
if (unlikely (!opszr.serialize (c, dictval[i], param))) if (unlikely (!opszr.serialize (c, dictval[i], param)))
return_trace (false); return_trace (false);
}
return_trace (true); return_trace (true);
} }
@ -391,14 +391,10 @@ struct Dict : UnsizedByteStr
{ return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); } { return serialize_int_op<HBUINT16, 0, 0x7FFF> (c, op, value, OpCode_shortint); }
static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value) static bool serialize_offset4_op (hb_serialize_context_t *c, op_code_t op, int value)
{ { return serialize_uint4_op (c, op, value); }
return serialize_uint4_op (c, op, value);
}
static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value) static bool serialize_offset2_op (hb_serialize_context_t *c, op_code_t op, int value)
{ { return serialize_uint2_op (c, op, value); }
return serialize_uint2_op (c, op, value);
}
}; };
struct TopDict : Dict {}; struct TopDict : Dict {};
@ -483,7 +479,7 @@ struct FDArray : CFFIndexOf<COUNT, FontDict>
return_trace (false); return_trace (false);
/* serialize font dict offsets */ /* serialize font dict offsets */
unsigned int offset = 1; unsigned int offset = 1;
unsigned int fid = 0; unsigned int fid = 0;
for (; fid < fontDicts.length; fid++) for (; fid < fontDicts.length; fid++)
{ {
@ -575,9 +571,7 @@ struct FDSelect0 {
} }
hb_codepoint_t get_fd (hb_codepoint_t glyph) const hb_codepoint_t get_fd (hb_codepoint_t glyph) const
{ { return (hb_codepoint_t) fds[glyph]; }
return (hb_codepoint_t)fds[glyph];
}
unsigned int get_size (unsigned int num_glyphs) const unsigned int get_size (unsigned int num_glyphs) const
{ return HBUINT8::static_size * num_glyphs; } { return HBUINT8::static_size * num_glyphs; }
@ -588,7 +582,8 @@ struct FDSelect0 {
}; };
template <typename GID_TYPE, typename FD_TYPE> template <typename GID_TYPE, typename FD_TYPE>
struct FDSelect3_4_Range { struct FDSelect3_4_Range
{
bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
@ -597,12 +592,13 @@ struct FDSelect3_4_Range {
GID_TYPE first; GID_TYPE first;
FD_TYPE fd; FD_TYPE fd;
public:
DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size); DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
}; };
template <typename GID_TYPE, typename FD_TYPE> template <typename GID_TYPE, typename FD_TYPE>
struct FDSelect3_4 { struct FDSelect3_4
{
unsigned int get_size () const unsigned int get_size () const
{ return GID_TYPE::static_size * 2 + ranges.get_size (); } { return GID_TYPE::static_size * 2 + ranges.get_size (); }
@ -614,10 +610,8 @@ struct FDSelect3_4 {
return_trace (false); return_trace (false);
for (unsigned int i = 1; i < nRanges (); i++) for (unsigned int i = 1; i < nRanges (); i++)
{
if (unlikely (ranges[i - 1].first >= ranges[i].first)) if (unlikely (ranges[i - 1].first >= ranges[i].first))
return_trace (false); return_trace (false);
}
if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ()))) if (unlikely (!sentinel().sanitize (c) || (sentinel() != c->get_num_glyphs ())))
return_trace (false); return_trace (false);
@ -649,17 +643,8 @@ struct FDSelect3_4 {
typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3; typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range; typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
struct FDSelect { struct FDSelect
bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const {
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) && (format == 0 || format == 3) &&
((format == 0)?
u.format0.sanitize (c, fdcount):
u.format3.sanitize (c, fdcount))));
}
bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs) bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
{ {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
@ -675,30 +660,46 @@ struct FDSelect {
unsigned int get_size (unsigned int num_glyphs) const unsigned int get_size (unsigned int num_glyphs) const
{ {
unsigned int size = format.static_size; switch (format)
if (format == 0) {
size += u.format0.get_size (num_glyphs); case 0: return format.static_size + u.format0.get_size (num_glyphs);
else case 3: return format.static_size + u.format3.get_size ();
size += u.format3.get_size (); default:return 0;
return size; }
} }
hb_codepoint_t get_fd (hb_codepoint_t glyph) const hb_codepoint_t get_fd (hb_codepoint_t glyph) const
{ {
if (this == &Null(FDSelect)) if (this == &Null (FDSelect))
return 0; return 0;
if (format == 0) switch (format)
return u.format0.get_fd (glyph); {
else case 0: return u.format0.get_fd (glyph);
return u.format3.get_fd (glyph); case 3: return u.format3.get_fd (glyph);
default:return 0;
}
} }
HBUINT8 format; bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
union { {
FDSelect0 format0; TRACE_SANITIZE (this);
FDSelect3 format3; if (unlikely (!c->check_struct (this)))
} u; return_trace (false);
switch (format)
{
case 0: return_trace (u.format0.sanitize (c, fdcount));
case 3: return_trace (u.format3.sanitize (c, fdcount));
default:return_trace (false);
}
}
HBUINT8 format;
union {
FDSelect0 format0;
FDSelect3 format3;
} u;
public:
DEFINE_SIZE_MIN (1); DEFINE_SIZE_MIN (1);
}; };

View File

@ -161,21 +161,8 @@ struct CFF1SuppEncData {
DEFINE_SIZE_ARRAY_SIZED (1, supps); DEFINE_SIZE_ARRAY_SIZED (1, supps);
}; };
struct Encoding { struct Encoding
bool sanitize (hb_sanitize_context_t *c) const {
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this)))
return_trace (false);
unsigned int fmt = format & 0x7F;
if (unlikely (fmt > 1))
return_trace (false);
if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
return_trace (false);
return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
}
/* serialize a fullset Encoding */ /* serialize a fullset Encoding */
bool serialize (hb_serialize_context_t *c, const Encoding &src) bool serialize (hb_serialize_context_t *c, const Encoding &src)
{ {
@ -197,11 +184,12 @@ struct Encoding {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
Encoding *dest = c->extend_min (*this); Encoding *dest = c->extend_min (*this);
if (unlikely (dest == nullptr)) return_trace (false); if (unlikely (dest == nullptr)) return_trace (false);
dest->format = format | ((supp_codes.length > 0)? 0x80: 0); dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
if (format == 0) switch (format) {
case 0:
{ {
Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count); Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
if (unlikely (fmt0 == nullptr)) return_trace (false); if (unlikely (fmt0 == nullptr)) return_trace (false);
fmt0->nCodes () = enc_count; fmt0->nCodes () = enc_count;
unsigned int glyph = 0; unsigned int glyph = 0;
for (unsigned int i = 0; i < code_ranges.length; i++) for (unsigned int i = 0; i < code_ranges.length; i++)
@ -213,7 +201,9 @@ struct Encoding {
return_trace (false); return_trace (false);
} }
} }
else break;
case 1:
{ {
Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length); Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
if (unlikely (fmt1 == nullptr)) return_trace (false); if (unlikely (fmt1 == nullptr)) return_trace (false);
@ -226,7 +216,11 @@ struct Encoding {
fmt1->ranges[i].nLeft = code_ranges[i].glyph; fmt1->ranges[i].nLeft = code_ranges[i].glyph;
} }
} }
if (supp_codes.length > 0) break;
}
if (supp_codes.length)
{ {
CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length); CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
if (unlikely (suppData == nullptr)) return_trace (false); if (unlikely (suppData == nullptr)) return_trace (false);
@ -237,6 +231,7 @@ struct Encoding {
suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */ suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
} }
} }
return_trace (true); return_trace (true);
} }
@ -245,11 +240,13 @@ struct Encoding {
unsigned int enc_count, unsigned int enc_count,
unsigned int supp_count) unsigned int supp_count)
{ {
unsigned int size = min_size; unsigned int size = min_size;
if (format == 0) switch (format)
size += Encoding0::min_size + HBUINT8::static_size * enc_count; {
else case 0: size += Encoding0::min_size + HBUINT8::static_size * enc_count; break;
size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; case 1: size += Encoding1::min_size + Encoding1_Range::static_size * enc_count; break;
default:return 0;
}
if (supp_count > 0) if (supp_count > 0)
size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count; size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
return size; return size;
@ -258,10 +255,11 @@ struct Encoding {
unsigned int get_size () const unsigned int get_size () const
{ {
unsigned int size = min_size; unsigned int size = min_size;
if (table_format () == 0) switch (table_format ())
size += u.format0.get_size (); {
else case 0: size += u.format0.get_size (); break;
size += u.format1.get_size (); case 1: size += u.format1.get_size (); break;
}
if (has_supplement ()) if (has_supplement ())
size += suppEncData ().get_size (); size += suppEncData ().get_size ();
return size; return size;
@ -269,14 +267,16 @@ struct Encoding {
hb_codepoint_t get_code (hb_codepoint_t glyph) const hb_codepoint_t get_code (hb_codepoint_t glyph) const
{ {
if (table_format () == 0) switch (table_format ())
return u.format0.get_code (glyph); {
else case 0: return u.format0.get_code (glyph);
return u.format1.get_code (glyph); case 1: return u.format1.get_code (glyph);
default:return 0;
}
} }
uint8_t table_format () const { return (format & 0x7F); } uint8_t table_format () const { return format & 0x7F; }
bool has_supplement () const { return (format & 0x80) != 0; } bool has_supplement () const { return format & 0x80; }
void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
{ {
@ -285,21 +285,37 @@ struct Encoding {
suppEncData().get_codes (sid, codes); suppEncData().get_codes (sid, codes);
} }
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this)))
return_trace (false);
switch (table_format ())
{
case 0: if (unlikely (!u.format0.sanitize (c))) { return_trace (false); } break;
case 1: if (unlikely (!u.format1.sanitize (c))) { return_trace (false); } break;
default:return_trace (false);
}
return_trace (likely (!has_supplement () || suppEncData ().sanitize (c)));
}
protected: protected:
const CFF1SuppEncData &suppEncData () const const CFF1SuppEncData &suppEncData () const
{ {
if ((format & 0x7F) == 0) switch (table_format ())
return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]); {
else case 0: return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes ()-1]);
return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]); case 1: return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges ()-1]);
default:return Null (CFF1SuppEncData);
}
} }
public: public:
HBUINT8 format; HBUINT8 format;
union { union {
Encoding0 format0; Encoding0 format0;
Encoding1 format1; Encoding1 format1;
} u; } u;
/* CFF1SuppEncData suppEncData; */ /* CFF1SuppEncData suppEncData; */
@ -433,23 +449,8 @@ typedef Charset1_2<HBUINT16> Charset2;
typedef Charset_Range<HBUINT8> Charset1_Range; typedef Charset_Range<HBUINT8> Charset1_Range;
typedef Charset_Range<HBUINT16> Charset2_Range; typedef Charset_Range<HBUINT16> Charset2_Range;
struct Charset { struct Charset
bool sanitize (hb_sanitize_context_t *c) const {
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this)))
return_trace (false);
if (format == 0)
return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
else if (format == 1)
return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
else if (likely (format == 2))
return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
else
return_trace (false);
}
/* serialize a fullset Charset */ /* serialize a fullset Charset */
bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs) bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
{ {
@ -471,10 +472,12 @@ struct Charset {
Charset *dest = c->extend_min (*this); Charset *dest = c->extend_min (*this);
if (unlikely (dest == nullptr)) return_trace (false); if (unlikely (dest == nullptr)) return_trace (false);
dest->format = format; dest->format = format;
if (format == 0) switch (format)
{
case 0:
{ {
Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1)); Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
if (unlikely (fmt0 == nullptr)) return_trace (false); if (unlikely (fmt0 == nullptr)) return_trace (false);
unsigned int glyph = 0; unsigned int glyph = 0;
for (unsigned int i = 0; i < sid_ranges.length; i++) for (unsigned int i = 0; i < sid_ranges.length; i++)
{ {
@ -483,7 +486,9 @@ struct Charset {
fmt0->sids[glyph++] = sid++; fmt0->sids[glyph++] = sid++;
} }
} }
else if (format == 1) break;
case 1:
{ {
Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length); Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
if (unlikely (fmt1 == nullptr)) return_trace (false); if (unlikely (fmt1 == nullptr)) return_trace (false);
@ -495,7 +500,9 @@ struct Charset {
fmt1->ranges[i].nLeft = sid_ranges[i].glyph; fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
} }
} }
else /* format 2 */ break;
case 2:
{ {
Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length); Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
if (unlikely (fmt2 == nullptr)) return_trace (false); if (unlikely (fmt2 == nullptr)) return_trace (false);
@ -506,56 +513,72 @@ struct Charset {
fmt2->ranges[i].first = sid_ranges[i].code; fmt2->ranges[i].first = sid_ranges[i].code;
fmt2->ranges[i].nLeft = sid_ranges[i].glyph; fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
} }
}
break;
} }
return_trace (true); return_trace (true);
} }
/* parallel to above: calculate the size of a subset Charset */ /* parallel to above: calculate the size of a subset Charset */
static unsigned int calculate_serialized_size ( static unsigned int calculate_serialized_size (uint8_t format,
uint8_t format, unsigned int count)
unsigned int count)
{ {
unsigned int size = min_size; switch (format)
if (format == 0) {
size += Charset0::min_size + HBUINT16::static_size * (count - 1); case 0: return min_size + Charset0::min_size + HBUINT16::static_size * (count - 1);
else if (format == 1) case 1: return min_size + Charset1::min_size + Charset1_Range::static_size * count;
size += Charset1::min_size + Charset1_Range::static_size * count; case 2: return min_size + Charset2::min_size + Charset2_Range::static_size * count;
else default:return 0;
size += Charset2::min_size + Charset2_Range::static_size * count; }
return size;
} }
unsigned int get_size (unsigned int num_glyphs) const unsigned int get_size (unsigned int num_glyphs) const
{ {
unsigned int size = min_size; switch (format)
if (format == 0) {
size += u.format0.get_size (num_glyphs); case 0: return min_size + u.format0.get_size (num_glyphs);
else if (format == 1) case 1: return min_size + u.format1.get_size (num_glyphs);
size += u.format1.get_size (num_glyphs); case 2: return min_size + u.format2.get_size (num_glyphs);
else default:return 0;
size += u.format2.get_size (num_glyphs); }
return size;
} }
hb_codepoint_t get_sid (hb_codepoint_t glyph) const hb_codepoint_t get_sid (hb_codepoint_t glyph) const
{ {
if (format == 0) switch (format)
return u.format0.get_sid (glyph); {
else if (format == 1) case 0: return u.format0.get_sid (glyph);
return u.format1.get_sid (glyph); case 1: return u.format1.get_sid (glyph);
else case 2: return u.format2.get_sid (glyph);
return u.format2.get_sid (glyph); default:return 0;
}
} }
hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
{ {
if (format == 0) switch (format)
return u.format0.get_glyph (sid, num_glyphs); {
else if (format == 1) case 0: return u.format0.get_glyph (sid, num_glyphs);
return u.format1.get_glyph (sid, num_glyphs); case 1: return u.format1.get_glyph (sid, num_glyphs);
else case 2: return u.format2.get_glyph (sid, num_glyphs);
return u.format2.get_glyph (sid, num_glyphs); default:return 0;
}
}
bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
if (unlikely (!c->check_struct (this)))
return_trace (false);
switch (format)
{
case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
default:return_trace (false);
}
} }
HBUINT8 format; HBUINT8 format;

View File

@ -51,18 +51,6 @@ typedef FDSelect3_4_Range<HBUINT32, HBUINT16> FDSelect4_Range;
struct CFF2FDSelect struct CFF2FDSelect
{ {
bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
{
TRACE_SANITIZE (this);
return_trace (likely (c->check_struct (this) && (format == 0 || format == 3 || format == 4) &&
((format == 0)?
u.format0.sanitize (c, fdcount):
((format == 3)?
u.format3.sanitize (c, fdcount):
u.format4.sanitize (c, fdcount)))));
}
bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs) bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
{ {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
@ -78,35 +66,51 @@ struct CFF2FDSelect
unsigned int get_size (unsigned int num_glyphs) const unsigned int get_size (unsigned int num_glyphs) const
{ {
unsigned int size = format.static_size; switch (format)
if (format == 0) {
size += u.format0.get_size (num_glyphs); case 0: return format.static_size + u.format0.get_size (num_glyphs);
else if (format == 3) case 3: return format.static_size + u.format3.get_size ();
size += u.format3.get_size (); case 4: return format.static_size + u.format4.get_size ();
else default:return 0;
size += u.format4.get_size (); }
return size;
} }
hb_codepoint_t get_fd (hb_codepoint_t glyph) const hb_codepoint_t get_fd (hb_codepoint_t glyph) const
{ {
if (this == &Null(CFF2FDSelect)) if (this == &Null (CFF2FDSelect))
return 0; return 0;
if (format == 0)
return u.format0.get_fd (glyph); switch (format)
else if (format == 3) {
return u.format3.get_fd (glyph); case 0: return u.format0.get_fd (glyph);
else case 3: return u.format3.get_fd (glyph);
return u.format4.get_fd (glyph); case 4: return u.format4.get_fd (glyph);
default:return 0;
}
} }
HBUINT8 format; bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
union { {
FDSelect0 format0; TRACE_SANITIZE (this);
FDSelect3 format3; if (unlikely (!c->check_struct (this)))
FDSelect4 format4; return_trace (false);
} u;
switch (format)
{
case 0: return_trace (u.format0.sanitize (c, fdcount));
case 3: return_trace (u.format3.sanitize (c, fdcount));
case 4: return_trace (u.format4.sanitize (c, fdcount));
default:return_trace (false);
}
}
HBUINT8 format;
union {
FDSelect0 format0;
FDSelect3 format3;
FDSelect4 format4;
} u;
public:
DEFINE_SIZE_MIN (2); DEFINE_SIZE_MIN (2);
}; };

View File

@ -1040,7 +1040,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
bool result; bool result;
cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0; unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset); result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
if (unlikely (!result)) if (unlikely (!result))
{ {

View File

@ -547,7 +547,7 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
bool result; bool result;
cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0)? priv_size: 0; unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset); result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset);
if (unlikely (!result)) if (unlikely (!result))
{ {