diff options
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh')
-rw-r--r-- | src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh | 482 |
1 files changed, 225 insertions, 257 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh index e07faca63f..39444d803f 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-kern-table.hh @@ -27,365 +27,333 @@ #ifndef HB_OT_KERN_TABLE_HH #define HB_OT_KERN_TABLE_HH -#include "hb-open-type-private.hh" - -namespace OT { +#include "hb-aat-layout-kerx-table.hh" /* * kern -- Kerning + * https://docs.microsoft.com/en-us/typography/opentype/spec/kern + * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html */ - #define HB_OT_TAG_kern HB_TAG('k','e','r','n') -struct hb_glyph_pair_t -{ - hb_codepoint_t left; - hb_codepoint_t right; -}; - -struct KernPair -{ - inline int get_kerning (void) const - { return value; } - - inline int cmp (const hb_glyph_pair_t &o) const - { - int ret = left.cmp (o.left); - if (ret) return ret; - return right.cmp (o.right); - } - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (c->check_struct (this)); - } +namespace OT { - protected: - GlyphID left; - GlyphID right; - FWORD value; - public: - DEFINE_SIZE_STATIC (6); -}; -struct KernSubTableFormat0 +template <typename KernSubTableHeader> +struct KernSubTableFormat3 { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const { - hb_glyph_pair_t pair = {left, right}; - int i = pairs.bsearch (pair); - if (i == -1) + hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount); + hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount); + hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount); + hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount); + + unsigned int leftC = leftClass[left]; + unsigned int rightC = rightClass[right]; + if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount)) return 0; - return pairs[i].get_kerning (); + unsigned int i = leftC * rightClassCount + rightC; + return kernValue[kernIndex[i]]; } - inline bool sanitize (hb_sanitize_context_t *c) const + bool apply (AAT::hb_aat_apply_context_t *c) const { - TRACE_SANITIZE (this); - return_trace (pairs.sanitize (c)); - } + TRACE_APPLY (this); - protected: - BinSearchArrayOf<KernPair> pairs; /* Array of kerning pairs. */ - public: - DEFINE_SIZE_ARRAY (8, pairs); -}; + if (!c->plan->requested_kerning) + return false; -struct KernClassTable -{ - inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; } - - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - return_trace (firstGlyph.sanitize (c) && classes.sanitize (c)); - } + if (header.coverage & header.Backwards) + return false; - protected: - UINT16 firstGlyph; /* First glyph in class range. */ - ArrayOf<UINT16> classes; /* Glyph classes. */ - public: - DEFINE_SIZE_ARRAY (4, classes); -}; + hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream); + machine.kern (c->font, c->buffer, c->plan->kern_mask); -struct KernSubTableFormat2 -{ - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { - unsigned int l = (this+leftClassTable).get_class (left); - unsigned int r = (this+leftClassTable).get_class (left); - unsigned int offset = l * rowWidth + r * sizeof (FWORD); - const FWORD *arr = &(this+array); - if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end)) - return 0; - const FWORD *v = &StructAtOffset<FWORD> (arr, offset); - if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end)) - return 0; - return *v; + return_trace (true); } - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (rowWidth.sanitize (c) && - leftClassTable.sanitize (c, this) && - rightClassTable.sanitize (c, this) && - array.sanitize (c, this)); + return_trace (c->check_struct (this) && + hb_barrier () && + c->check_range (kernValueZ, + kernValueCount * sizeof (FWORD) + + glyphCount * 2 + + leftClassCount * rightClassCount)); } protected: - UINT16 rowWidth; /* The width, in bytes, of a row in the table. */ - OffsetTo<KernClassTable> - leftClassTable; /* Offset from beginning of this subtable to - * left-hand class table. */ - OffsetTo<KernClassTable> - rightClassTable;/* Offset from beginning of this subtable to - * right-hand class table. */ - OffsetTo<FWORD> - array; /* Offset from beginning of this subtable to - * the start of the kerning array. */ + KernSubTableHeader + header; + HBUINT16 glyphCount; /* The number of glyphs in this font. */ + HBUINT8 kernValueCount; /* The number of kerning values. */ + HBUINT8 leftClassCount; /* The number of left-hand classes. */ + HBUINT8 rightClassCount;/* The number of right-hand classes. */ + HBUINT8 flags; /* Set to zero (reserved for future use). */ + UnsizedArrayOf<FWORD> + kernValueZ; /* The kerning values. + * Length kernValueCount. */ +#if 0 + UnsizedArrayOf<HBUINT8> + leftClass; /* The left-hand classes. + * Length glyphCount. */ + UnsizedArrayOf<HBUINT8> + rightClass; /* The right-hand classes. + * Length glyphCount. */ + UnsizedArrayOf<HBUINT8>kernIndex; + /* The indices into the kernValue array. + * Length leftClassCount * rightClassCount */ +#endif public: - DEFINE_SIZE_MIN (8); + DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ); }; +template <typename KernSubTableHeader> struct KernSubTable { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const + unsigned int get_size () const { return u.header.length; } + unsigned int get_type () const { return u.header.format; } + + int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const { - switch (format) { + switch (get_type ()) { + /* This method hooks up to hb_font_t's get_h_kerning. Only support Format0. */ case 0: return u.format0.get_kerning (left, right); - case 2: return u.format2.get_kerning (left, right, end); default:return 0; } } - inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const { - TRACE_SANITIZE (this); - switch (format) { - case 0: return_trace (u.format0.sanitize (c)); - case 2: return_trace (u.format2.sanitize (c)); - default:return_trace (true); + unsigned int subtable_type = get_type (); + TRACE_DISPATCH (this, subtable_type); + switch (subtable_type) { + case 0: return_trace (c->dispatch (u.format0)); +#ifndef HB_NO_AAT_SHAPE + case 1: return_trace (u.header.apple ? c->dispatch (u.format1, std::forward<Ts> (ds)...) : c->default_return_value ()); +#endif + case 2: return_trace (c->dispatch (u.format2)); +#ifndef HB_NO_AAT_SHAPE + case 3: return_trace (u.header.apple ? c->dispatch (u.format3, std::forward<Ts> (ds)...) : c->default_return_value ()); +#endif + default: return_trace (c->default_return_value ()); } } - protected: + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (!(u.header.sanitize (c) && + hb_barrier () && + u.header.length >= u.header.min_size && + c->check_range (this, u.header.length)))) return_trace (false); + + return_trace (dispatch (c)); + } + + public: union { - KernSubTableFormat0 format0; - KernSubTableFormat2 format2; + KernSubTableHeader header; + AAT::KerxSubTableFormat0<KernSubTableHeader> format0; + AAT::KerxSubTableFormat1<KernSubTableHeader> format1; + AAT::KerxSubTableFormat2<KernSubTableHeader> format2; + KernSubTableFormat3<KernSubTableHeader> format3; } u; public: - DEFINE_SIZE_MIN (0); + DEFINE_SIZE_MIN (KernSubTableHeader::static_size); }; -template <typename T> -struct KernSubTableWrapper +struct KernOTSubTableHeader { - /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ - inline const T* thiz (void) const { return static_cast<const T *> (this); } + static constexpr bool apple = false; + typedef AAT::ObsoleteTypes Types; - inline bool is_horizontal (void) const - { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; } + unsigned tuple_count () const { return 0; } + bool is_horizontal () const { return (coverage & Horizontal); } - inline bool is_override (void) const - { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); } - - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); } - - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { return is_horizontal () ? get_kerning (left, right, end) : 0; } - - inline unsigned int get_size (void) const { return thiz()->length; } + enum Coverage + { + Horizontal = 0x01u, + Minimum = 0x02u, + CrossStream = 0x04u, + Override = 0x08u, + + /* Not supported: */ + Backwards = 0x00u, + Variation = 0x00u, + }; - inline bool sanitize (hb_sanitize_context_t *c) const + bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (c->check_struct (thiz()) && - thiz()->length >= thiz()->min_size && - c->check_array (thiz(), 1, thiz()->length) && - thiz()->subtable.sanitize (c, thiz()->format)); + return_trace (c->check_struct (this)); } + + public: + HBUINT16 versionZ; /* Unused. */ + HBUINT16 length; /* Length of the subtable (including this header). */ + HBUINT8 format; /* Subtable format. */ + HBUINT8 coverage; /* Coverage bits. */ + public: + DEFINE_SIZE_STATIC (6); }; -template <typename T> -struct KernTable +struct KernOT : AAT::KerxTable<KernOT> { - /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */ - inline const T* thiz (void) const { return static_cast<const T *> (this); } + friend struct AAT::KerxTable<KernOT>; - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const - { - int v = 0; - const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data); - unsigned int count = thiz()->nTables; - for (unsigned int i = 0; i < count; i++) - { - if (st->is_override ()) - v = 0; - v += st->get_h_kerning (left, right, table_length + (const char *) this); - st = &StructAfter<typename T::SubTableWrapper> (*st); - } - return v; - } + static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; + static constexpr unsigned minVersion = 0u; - inline bool sanitize (hb_sanitize_context_t *c) const - { - TRACE_SANITIZE (this); - if (unlikely (!c->check_struct (thiz()) || - thiz()->version != T::VERSION)) - return_trace (false); - - const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data); - unsigned int count = thiz()->nTables; - for (unsigned int i = 0; i < count; i++) - { - if (unlikely (!st->sanitize (c))) - return_trace (false); - st = &StructAfter<typename T::SubTableWrapper> (*st); - } + typedef KernOTSubTableHeader SubTableHeader; + typedef SubTableHeader::Types Types; + typedef KernSubTable<SubTableHeader> SubTable; - return_trace (true); - } + protected: + HBUINT16 version; /* Version--0x0000u */ + HBUINT16 tableCount; /* Number of subtables in the kerning table. */ + SubTable firstSubTable; /* Subtables. */ + public: + DEFINE_SIZE_MIN (4); }; -struct KernOT : KernTable<KernOT> + +struct KernAATSubTableHeader { - friend struct KernTable<KernOT>; + static constexpr bool apple = true; + typedef AAT::ObsoleteTypes Types; - static const uint16_t VERSION = 0x0000u; + unsigned tuple_count () const { return 0; } + bool is_horizontal () const { return !(coverage & Vertical); } - struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper> + enum Coverage { - friend struct KernSubTableWrapper<SubTableWrapper>; - - enum coverage_flags_t { - COVERAGE_DIRECTION_FLAG = 0x01u, - COVERAGE_MINIMUM_FLAG = 0x02u, - COVERAGE_CROSSSTREAM_FLAG = 0x04u, - COVERAGE_OVERRIDE_FLAG = 0x08u, - - COVERAGE_VARIATION_FLAG = 0x00u, /* Not supported. */ - - COVERAGE_CHECK_FLAGS = 0x07u, - COVERAGE_CHECK_HORIZONTAL = 0x01u - }; - - protected: - UINT16 versionZ; /* Unused. */ - UINT16 length; /* Length of the subtable (including this header). */ - UINT8 format; /* Subtable format. */ - UINT8 coverage; /* Coverage bits. */ - KernSubTable subtable; /* Subtable data. */ - public: - DEFINE_SIZE_MIN (6); + Vertical = 0x80u, + CrossStream = 0x40u, + Variation = 0x20u, + + /* Not supported: */ + Backwards = 0x00u, }; - protected: - UINT16 version; /* Version--0x0000u */ - UINT16 nTables; /* Number of subtables in the kerning table. */ - UINT8 data[VAR]; + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this)); + } + + public: + HBUINT32 length; /* Length of the subtable (including this header). */ + HBUINT8 coverage; /* Coverage bits. */ + HBUINT8 format; /* Subtable format. */ + HBUINT16 tupleIndex; /* The tuple index (used for variations fonts). + * This value specifies which tuple this subtable covers. + * Note: We don't implement. */ public: - DEFINE_SIZE_ARRAY (4, data); + DEFINE_SIZE_STATIC (8); }; -struct KernAAT : KernTable<KernAAT> +struct KernAAT : AAT::KerxTable<KernAAT> { - friend struct KernTable<KernAAT>; + friend struct AAT::KerxTable<KernAAT>; - static const uint32_t VERSION = 0x00010000u; + static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; + static constexpr unsigned minVersion = 0x00010000u; - struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper> - { - friend struct KernSubTableWrapper<SubTableWrapper>; - - enum coverage_flags_t { - COVERAGE_DIRECTION_FLAG = 0x80u, - COVERAGE_CROSSSTREAM_FLAG = 0x40u, - COVERAGE_VARIATION_FLAG = 0x20u, - - COVERAGE_OVERRIDE_FLAG = 0x00u, /* Not supported. */ - - COVERAGE_CHECK_FLAGS = 0xE0u, - COVERAGE_CHECK_HORIZONTAL = 0x00u - }; - - protected: - UINT32 length; /* Length of the subtable (including this header). */ - UINT8 coverage; /* Coverage bits. */ - UINT8 format; /* Subtable format. */ - UINT16 tupleIndex; /* The tuple index (used for variations fonts). - * This value specifies which tuple this subtable covers. */ - KernSubTable subtable; /* Subtable data. */ - public: - DEFINE_SIZE_MIN (8); - }; + typedef KernAATSubTableHeader SubTableHeader; + typedef SubTableHeader::Types Types; + typedef KernSubTable<SubTableHeader> SubTable; protected: - UINT32 version; /* Version--0x00010000u */ - UINT32 nTables; /* Number of subtables in the kerning table. */ - UINT8 data[VAR]; + HBUINT32 version; /* Version--0x00010000u */ + HBUINT32 tableCount; /* Number of subtables in the kerning table. */ + SubTable firstSubTable; /* Subtables. */ public: - DEFINE_SIZE_ARRAY (8, data); + DEFINE_SIZE_MIN (8); }; struct kern { - static const hb_tag_t tableTag = HB_OT_TAG_kern; + static constexpr hb_tag_t tableTag = HB_OT_TAG_kern; - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const + bool has_data () const { return u.version32; } + unsigned get_type () const { return u.major; } + + bool has_state_machine () const { - switch (u.major) { - case 0: return u.ot.get_h_kerning (left, right, table_length); - case 1: return u.aat.get_h_kerning (left, right, table_length); - default:return 0; + switch (get_type ()) { + case 0: return u.ot.has_state_machine (); +#ifndef HB_NO_AAT_SHAPE + case 1: return u.aat.has_state_machine (); +#endif + default:return false; } } - inline bool sanitize (hb_sanitize_context_t *c) const + bool has_cross_stream () const { - TRACE_SANITIZE (this); - if (!u.major.sanitize (c)) return_trace (false); - switch (u.major) { - case 0: return_trace (u.ot.sanitize (c)); - case 1: return_trace (u.aat.sanitize (c)); - default:return_trace (true); + switch (get_type ()) { + case 0: return u.ot.has_cross_stream (); +#ifndef HB_NO_AAT_SHAPE + case 1: return u.aat.has_cross_stream (); +#endif + default:return false; } } - struct accelerator_t + int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const { - inline void init (hb_face_t *face) - { - blob = Sanitizer<kern>::sanitize (face->reference_table (HB_OT_TAG_kern)); - table = Sanitizer<kern>::lock_instance (blob); - table_length = hb_blob_get_length (blob); - } - inline void fini (void) - { - hb_blob_destroy (blob); + switch (get_type ()) { + case 0: return u.ot.get_h_kerning (left, right); +#ifndef HB_NO_AAT_SHAPE + case 1: return u.aat.get_h_kerning (left, right); +#endif + default:return 0; } + } - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const - { return table->get_h_kerning (left, right, table_length); } + bool apply (AAT::hb_aat_apply_context_t *c) const + { return dispatch (c); } - private: - hb_blob_t *blob; - const kern *table; - unsigned int table_length; - }; + template <typename context_t, typename ...Ts> + typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const + { + unsigned int subtable_type = get_type (); + TRACE_DISPATCH (this, subtable_type); + switch (subtable_type) { + case 0: return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...)); +#ifndef HB_NO_AAT_SHAPE + case 1: return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...)); +#endif + default: return_trace (c->default_return_value ()); + } + } + + bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (!u.version32.sanitize (c)) return_trace (false); + hb_barrier (); + return_trace (dispatch (c)); + } protected: union { - UINT16 major; + HBUINT32 version32; + HBUINT16 major; KernOT ot; +#ifndef HB_NO_AAT_SHAPE KernAAT aat; +#endif } u; public: - DEFINE_SIZE_UNION (2, major); + DEFINE_SIZE_UNION (4, version32); }; } /* namespace OT */ |