[aat] Skip terminator in VarSizedBinSearchArray<>

Fixes shaping with Apple Chancery on 10.13 again.  In that font,
there was a terminator segment, that was tripping off sanitize().
This commit is contained in:
Behdad Esfahbod 2018-11-24 23:12:28 -05:00
parent 4202a3cde3
commit 3d30972699
2 changed files with 26 additions and 1 deletions

View File

@ -76,6 +76,8 @@ struct LookupFormat0
template <typename T>
struct LookupSegmentSingle
{
enum { TerminationWordCount = 2 };
inline int cmp (hb_codepoint_t g) const {
return g < first ? -1 : g <= last ? 0 : +1 ;
}
@ -134,6 +136,8 @@ struct LookupFormat2
template <typename T>
struct LookupSegmentArray
{
enum { TerminationWordCount = 2 };
inline const T* get_value (hb_codepoint_t glyph_id, const void *base) const
{
return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
@ -204,6 +208,8 @@ struct LookupFormat4
template <typename T>
struct LookupSingle
{
enum { TerminationWordCount = 1 };
inline int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
inline bool sanitize (hb_sanitize_context_t *c) const

View File

@ -874,6 +874,22 @@ struct VarSizedBinSearchArrayOf
HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
inline bool last_is_terminator (void) const
{
if (unlikely (!header.nUnits)) return false;
/* Gah.
*
* "The number of termination values that need to be included is table-specific.
* The value that indicates binary search termination is 0xFFFF." */
const HBUINT16 *words = &StructAtOffset<HBUINT16> (&bytesZ, (header.nUnits - 1) * header.unitSize);
unsigned int count = Type::TerminationWordCount;
for (unsigned int i = 0; i < count; i++)
if (words[i] != 0xFFFFu)
return false;
return true;
}
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= get_length ())) return Null (Type);
@ -884,7 +900,10 @@ struct VarSizedBinSearchArrayOf
if (unlikely (i >= get_length ())) return Crap (Type);
return StructAtOffset<Type> (&bytesZ, i * header.unitSize);
}
inline unsigned int get_length (void) const { return header.nUnits; }
inline unsigned int get_length (void) const
{
return header.nUnits - last_is_terminator ();
}
inline unsigned int get_size (void) const
{ return header.static_size + header.nUnits * header.unitSize; }