From 71b06fd392680b6fcfece60d8a83ba6c56eada09 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Sat, 12 Mar 2016 23:49:09 -0800 Subject: [PATCH] [GX] Add VariationAlternates, to allow conditional lookups in GSUB/GPOS Not hooked up to runtime yet. --- src/hb-open-type-private.hh | 1 + src/hb-ot-layout-common-private.hh | 99 +++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 66f1c08df..865429da2 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -630,6 +630,7 @@ struct IntType inline operator Type(void) const { return v; } inline bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } inline bool operator != (const IntType &o) const { return !(*this == o); } + inline unsigned int get_size (void) const { return Size; } static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } inline int cmp (Type a) const { diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index 3154cfe7a..328472fb1 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -575,6 +575,7 @@ struct LookupFlag : USHORT IgnoreMarks = 0x0008u, IgnoreFlags = 0x000Eu, UseMarkFilteringSet = 0x0010u, + UseVariationAlternates= 0x0020u, Reserved = 0x00E0u, MarkAttachmentType = 0xFF00u }; @@ -587,6 +588,88 @@ struct LookupFlag : USHORT HB_MARK_AS_FLAG_T (OT::LookupFlag::Flags); namespace OT { +struct VariationGridAxis +{ + inline int locate (int *coords, unsigned int coord_len) const + { + int coord = axisIndex < coord_len ? coords[axisIndex] : 0; + + unsigned int count = axisCoords.len; + unsigned int i = 0; + while (i + 1 < count && coord < axisCoords[i + 1]) + i++; + + return axisCoords[i] <= coord ? i : -1; + } + + inline unsigned int get_len (void) const + { + return axisCoords.len - 1; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (c->check_struct (this) && axisCoords.sanitize (c)); + } + + Index axisIndex; + SortedArrayOf axisCoords; + public: + DEFINE_SIZE_ARRAY (4, axisCoords); +}; + +struct VariationGrid +{ + inline int locate (int *coords, unsigned int coord_len) const + { + int location = 0; + unsigned int count = axes.len; + for (unsigned int i = 0; i < count; i++) + { + const VariationGridAxis &axis = (this+axes[i]); + int axisLoc = axis.locate (coords, coord_len); + if (axisLoc == -1) + return -1; + location = location * (axis.get_len () - 1) + axisLoc; /* XXX Check for overflow?. */ + } + return location; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (axes.sanitize (c, this)); + } + + OffsetArrayOf + axes; + public: + DEFINE_SIZE_ARRAY (2, axes); +}; + +struct VariationAlternates +{ + inline unsigned int get_lookup_index (int *coords, unsigned int coord_len) const + { + int location = (this+grid).locate (coords, coord_len); + if (location == -1) + return 0xFFFE; /* TODO: give it a name. */ + return lookupIndex[location]; + } + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (grid.sanitize (c, this) && lookupIndex.sanitize (c)); + } + + OffsetTo grid; + IndexArray lookupIndex; + public: + DEFINE_SIZE_ARRAY (4, lookupIndex); +}; + struct Lookup { inline unsigned int get_subtable_count (void) const { return subTable.len; } @@ -655,10 +738,17 @@ struct Lookup TRACE_SANITIZE (this); /* Real sanitize of the subtables is done by GSUB/GPOS/... */ if (!(c->check_struct (this) && subTable.sanitize (c))) return_trace (false); + const void *cursor = &StructAfter (subTable); if (lookupFlag & LookupFlag::UseMarkFilteringSet) { - const USHORT &markFilteringSet = StructAfter (subTable); + const USHORT &markFilteringSet = CastR (cursor); if (!markFilteringSet.sanitize (c)) return_trace (false); + cursor = &StructAfter (markFilteringSet); + } + if (lookupFlag & LookupFlag::UseVariationAlternates) + { + const OffsetTo &varAlts = CastR > (cursor); + if (!varAlts.sanitize (c, this)) return_trace (false); } return_trace (true); } @@ -671,8 +761,13 @@ struct Lookup USHORT markFilteringSetX[VAR]; /* Index (base 0) into GDEF mark glyph sets * structure. This field is only present if bit * UseMarkFilteringSet of lookup flags is set. */ + OffsetTo + variationAlternatesZ[VAR]; + /* Index (base 0) into GDEF mark glyph sets + * structure. This field is only present if bit + * UseMarkFilteringSet of lookup flags is set. */ public: - DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX); + DEFINE_SIZE_MIN (6); }; typedef OffsetListOf LookupList;