From 3d3097269995aa227b4b198d4da2baf942b65c66 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 24 Nov 2018 23:12:28 -0500 Subject: [PATCH] [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(). --- src/hb-aat-layout-common.hh | 6 ++++++ src/hb-open-type.hh | 21 ++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 2c09a796c..3ee96bc91 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -76,6 +76,8 @@ struct LookupFormat0 template 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 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 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 8970ec784..9b412dbce 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -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 (&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 (&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; }