[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().
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh
index 2c09a79..3ee96bc 100644
--- a/src/hb-aat-layout-common.hh
+++ b/src/hb-aat-layout-common.hh
@@ -76,6 +76,8 @@
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 @@
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 @@
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
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index 8970ec7..9b412db 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -874,6 +874,22 @@
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 @@
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; }