summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2016-03-12 23:49:09 -0800
committerBehdad Esfahbod <behdad@behdad.org>2016-12-16 19:06:26 -0600
commit71b06fd392680b6fcfece60d8a83ba6c56eada09 (patch)
treea74b2f4dff8fb1f02ee949ab2eedea08b167ea6f /src
parent976eeb8e025e2b7601a91e661d6e9a88bf8afbd2 (diff)
[GX] Add VariationAlternates, to allow conditional lookups in GSUB/GPOS
Not hooked up to runtime yet.
Diffstat (limited to 'src')
-rw-r--r--src/hb-open-type-private.hh1
-rw-r--r--src/hb-ot-layout-common-private.hh99
2 files changed, 98 insertions, 2 deletions
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 66f1c08d..865429da 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<Type,Size> &o) const { return (Type) v == (Type) o.v; }
inline bool operator != (const IntType<Type,Size> &o) const { return !(*this == o); }
+ inline unsigned int get_size (void) const { return Size; }
static inline int cmp (const IntType<Type,Size> *a, const IntType<Type,Size> *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 3154cfe7..328472fb 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<F2DOT14> 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<VariationGridAxis>
+ 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<VariationGrid> 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<char> (subTable);
if (lookupFlag & LookupFlag::UseMarkFilteringSet)
{
- const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
+ const USHORT &markFilteringSet = CastR<USHORT> (cursor);
if (!markFilteringSet.sanitize (c)) return_trace (false);
+ cursor = &StructAfter<char> (markFilteringSet);
+ }
+ if (lookupFlag & LookupFlag::UseVariationAlternates)
+ {
+ const OffsetTo<VariationAlternates,ULONG> &varAlts = CastR<const OffsetTo<VariationAlternates,ULONG> > (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<VariationAlternates,ULONG>
+ 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<Lookup> LookupList;