15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2007,2008,2009  Red Hat, Inc.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright © 2010,2012  Google, Inc.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  This is part of HarfBuzz, a text shaping library.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Permission is hereby granted, without written agreement and without
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * license or royalty fees, to use, copy, modify, and distribute this
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * software and its documentation for any purpose, provided that the
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * above copyright notice and the following two paragraphs appear in
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * all copies of this software.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * DAMAGE.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Red Hat Author(s): Behdad Esfahbod
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Author(s): Behdad Esfahbod
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef HB_OT_LAYOUT_COMMON_PRIVATE_HH
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define HB_OT_LAYOUT_COMMON_PRIVATE_HH
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-ot-layout-private.hh"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-open-type-private.hh"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "hb-set-private.hh"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace OT {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NOT_COVERED		((unsigned int) -1)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MAX_NESTING_LEVEL	8
42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#define MAX_CONTEXT_LENGTH	64
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OpenType Layout Common Table Formats
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Record
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int cmp (hb_tag_t a) const {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return tag.cmp (a);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct sanitize_closure_t {
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_tag_t tag;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void *list_base;
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const sanitize_closure_t closure = {tag, base};
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tag		tag;		/* 4-byte Tag identifier */
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<Type>
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		offset;		/* Offset from beginning of object holding
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * the Record */
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (6);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RecordArrayOf : SortedArrayOf<Record<Type> > {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Tag& get_tag (unsigned int i) const
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* We cheat slightly and don't define separate Null objects
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * for Record types.  Instead, we return the correct Null(Tag)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * here. */
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= this->len)) return Null(Tag);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (*this)[i].tag;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_tags (unsigned int start_offset,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int *record_count /* IN/OUT */,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				hb_tag_t     *record_tags /* OUT */) const
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (record_count) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Record<Type> *arr = this->sub_array (start_offset, record_count);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int count = *record_count;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned int i = 0; i < count; i++)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	record_tags[i] = arr[i].tag;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this->len;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool find_index (hb_tag_t tag, unsigned int *index) const
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    /* If we want to allow non-sorted data, we can lsearch(). */
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int i = this->/*lsearch*/bsearch (tag);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != -1) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (index) *index = i;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index) *index = Index::NOT_FOUND_INDEX;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RecordListOf : RecordArrayOf<Type>
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return this+RecordArrayOf<Type>::operator [](i).offset; }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RangeRecord
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int cmp (hb_codepoint_t g) const {
1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return g < start ? -1 : g <= end ? 0 : +1 ;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects (const hb_set_t *glyphs) const {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return glyphs->intersects (start, end);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename set_t>
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_coverage (set_t *glyphs) const {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphs->add_range (start, end);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GlyphID	start;		/* First GlyphID in the range */
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GlyphID	end;		/* Last GlyphID in the range */
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	value;		/* Value */
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (6);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (RangeRecord, "\000\001");
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IndexArray : ArrayOf<Index>
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_indexes (unsigned int start_offset,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   unsigned int *_count /* IN/OUT */,
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   unsigned int *_indexes /* OUT */) const
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (_count) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const USHORT *arr = this->sub_array (start_offset, _count);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int count = *_count;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned int i = 0; i < count; i++)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	_indexes[i] = arr[i];
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this->len;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Script;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LangSys;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Feature;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LangSys
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_feature_count (void) const
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return featureIndex.len; }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_tag_t get_feature_index (unsigned int i) const
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return featureIndex[i]; }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_feature_indexes (unsigned int start_offset,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int *feature_count /* IN/OUT */,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int *feature_indexes /* OUT */) const
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xFFFFu; }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_required_feature_index (void) const
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (reqFeatureIndex == 0xFFFFu)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Index::NOT_FOUND_INDEX;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return reqFeatureIndex;;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c,
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			const Record<LangSys>::sanitize_closure_t * = NULL) {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Offset<>	lookupOrderZ;	/* = Null (reserved for an offset to a
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * reordering table) */
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	reqFeatureIndex;/* Index of a feature required for this
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * language system--if no required features
2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				 * = 0xFFFFu */
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IndexArray	featureIndex;	/* Array of indices into the FeatureList */
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (6, featureIndex);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Script
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lang_sys_count (void) const
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return langSys.len; }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Tag& get_lang_sys_tag (unsigned int i) const
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return langSys.get_tag (i); }
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 unsigned int *lang_sys_count /* IN/OUT */,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 hb_tag_t     *lang_sys_tags /* OUT */) const
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const LangSys& get_lang_sys (unsigned int i) const
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this+langSys[i].offset;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return langSys.find_index (tag, index); }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c,
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			const Record<Script>::sanitize_closure_t * = NULL) {
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<LangSys>
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		defaultLangSys;	/* Offset to DefaultLangSys table--from
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * beginning of Script table--may be Null */
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordArrayOf<LangSys>
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		langSys;	/* Array of LangSysRecords--listed
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * alphabetically by LangSysTag */
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, langSys);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef RecordListOf<Script> ScriptList;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FeatureParamsSize
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* This subtable has some "history", if you will.  Some earlier versions of
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Adobe tools calculated the offset of the FeatureParams sutable from the
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * beginning of the FeatureList table!  Now, that is dealt with in the
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Feature implementation.  But we still need to be able to tell junk from
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * real data.  Note: We don't check that the nameID actually exists.
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * coming out soon, and that the makeotf program will build a font with a
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * 'size' feature that is correct by the specification.
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * The specification for this feature tag is in the "OpenType Layout Tag
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Registry". You can see a copy of this at:
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * http://partners.adobe.com/public/developer/opentype/index_tag8.html#size
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Here is one set of rules to determine if the 'size' feature is built
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * correctly, or as by the older versions of MakeOTF. You may be able to do
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * better.
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Assume that the offset to the size feature is according to specification,
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * and make the following value checks. If it fails, assume the the size
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * offset from the beginning of the FeatureList table, rather than from the
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * beginning of the 'size' Feature table.
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * If "design size" == 0:
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     fails check
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Else if ("subfamily identifier" == 0 and
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "range start" == 0 and
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "range end" == 0 and
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "range start" == 0 and
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "menu name ID" == 0)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     passes check: this is the format used when there is a design size
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * specified, but there is no recommended size range.
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Else if ("design size" <  "range start" or
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "design size" >   "range end" or
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "range end" <= "range start" or
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "menu name ID"  < 256 or
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "menu name ID"  > 32767 or
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     menu name ID is not a name ID which is actually in the name table)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     fails test
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Else
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     passes test.
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!designSize)
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (false);
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (subfamilyID == 0 &&
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     subfamilyNameID == 0 &&
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     rangeStart == 0 &&
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     rangeEnd == 0)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (true);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (designSize < rangeStart ||
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     designSize > rangeEnd ||
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     subfamilyNameID < 256 ||
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     subfamilyNameID > 32767)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (false);
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (true);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	designSize;	/* Represents the design size in 720/inch
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * units (decipoints).  The design size entry
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * must be non-zero.  When there is a design
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * size but no recommended size range, the
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * rest of the array will consist of zeros. */
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	subfamilyID;	/* Has no independent meaning, but serves
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * as an identifier that associates fonts
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * in a subfamily. All fonts which share a
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * Preferred or Font Family name and which
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * differ only by size range shall have the
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * same subfamily value, and no fonts which
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * differ in weight or style shall have the
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * same subfamily value. If this value is
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * zero, the remaining fields in the array
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * will be ignored. */
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	subfamilyNameID;/* If the preceding value is non-zero, this
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * value must be set in the range 256 - 32767
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * (inclusive). It records the value of a
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * field in the name table, which must
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * contain English-language strings encoded
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * in Windows Unicode and Macintosh Roman,
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * and may contain additional strings
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * localized to other scripts and languages.
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * Each of these strings is the name an
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * application should use, in combination
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * with the family name, to represent the
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * subfamily in a menu.  Applications will
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * choose the appropriate version based on
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * their selection criteria. */
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	rangeStart;	/* Large end of the recommended usage range
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * (inclusive), stored in 720/inch units
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * (decipoints). */
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	rangeEnd;	/* Small end of the recommended usage range
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   (exclusive), stored in 720/inch units
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * (decipoints). */
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_STATIC (10);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FeatureParamsStylisticSet
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* Right now minorVersion is at zero.  Which means, any table supports
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * the uiNameID field. */
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  USHORT	version;	/* (set to 0): This corresponds to a “minor”
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * version number. Additional data may be
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * added to the end of this Feature Parameters
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * table in the future. */
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	uiNameID;	/* The 'name' table name ID that specifies a
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * string (or strings, for multiple languages)
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * for a user-interface label for this
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * feature.  The values of uiLabelNameId and
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * sampleTextNameId are expected to be in the
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * font-specific name ID range (256-32767),
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * though that is not a requirement in this
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * Feature Parameters specification. The
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * user-interface label for the feature can
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * be provided in multiple languages. An
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * English string should be included as a
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * fallback. The string should be kept to a
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * minimal length to fit comfortably with
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * different application interfaces. */
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_STATIC (4);
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
40423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)/* http://www.microsoft.com/typography/otspec/features_ae.htm#cv01-cv99 */
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FeatureParamsCharacterVariants
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) &&
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			 characters.sanitize (c));
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	format;			/* Format number is set to 0. */
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	featUILableNameID;	/* The ‘name’ table name ID that
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * specifies a string (or strings,
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * for multiple languages) for a
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * user-interface label for this
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * feature. (May be NULL.) */
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	featUITooltipTextNameID;/* The ‘name’ table name ID that
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * specifies a string (or strings,
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * for multiple languages) that an
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * application can use for tooltip
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * text for this feature. (May be
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * NULL.) */
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	sampleTextNameID;	/* The ‘name’ table name ID that
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * specifies sample text that
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * illustrates the effect of this
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * feature. (May be NULL.) */
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	numNamedParameters;	/* Number of named parameters. (May
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * be zero.) */
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	firstParamUILabelNameID;/* The first ‘name’ table name ID
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * used to specify strings for
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * user-interface labels for the
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * feature parameters. (Must be zero
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * if numParameters is zero.) */
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ArrayOf<UINT24>
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		characters;		/* Array of the Unicode Scalar Value
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * of the characters for which this
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * feature provides glyph variants.
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * (May be zero.) */
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_ARRAY (14, characters);
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FeatureParams
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) {
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (tag == HB_TAG ('s','i','z','e'))
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (u.size.sanitize (c));
4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (u.stylisticSet.sanitize (c));
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (u.characterVariants.sanitize (c));
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (true);
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (tag == HB_TAG ('s','i','z','e'))
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return u.size;
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Null(FeatureParamsSize);
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private:
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  union {
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FeatureParamsSize			size;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FeatureParamsStylisticSet		stylisticSet;
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FeatureParamsCharacterVariants	characterVariants;
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } u;
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_STATIC (17);
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Feature
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lookup_count (void) const
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return lookupIndex.len; }
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_tag_t get_lookup_index (unsigned int i) const
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return lookupIndex[i]; }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lookup_indexes (unsigned int start_index,
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  unsigned int *lookup_count /* IN/OUT */,
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  unsigned int *lookup_tags /* OUT */) const
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const FeatureParams &get_feature_params (void) const
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { return this+featureParams; }
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c,
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			const Record<Feature>::sanitize_closure_t *closure) {
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (false);
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* Some earlier versions of Adobe tools calculated the offset of the
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * FeatureParams subtable from the beginning of the FeatureList table!
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * If sanitizing "failed" for the FeatureParams subtable, try it with the
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * alternative location.  We would know sanitize "failed" if old value
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * of the offset was non-zero, but it's zeroed now.
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Only do this for the 'size' feature, since at the time of the faulty
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Adobe tools, only the 'size' feature had FeatureParams defined.
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    OffsetTo<FeatureParams> orig_offset = featureParams;
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (false);
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (likely (orig_offset.is_null ()))
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (true);
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (featureParams == 0 && closure &&
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	closure->tag == HB_TAG ('s','i','z','e') &&
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	closure->list_base && closure->list_base < this)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned int new_offset_int = (unsigned int) orig_offset -
5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				    (((char *) this) - ((char *) closure->list_base));
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      OffsetTo<FeatureParams> new_offset;
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      /* Check that it did not overflow. */
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_offset.set (new_offset_int);
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (new_offset == new_offset_int &&
5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	  c->try_set (&featureParams, new_offset) &&
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return TRACE_RETURN (false);
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (true);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OffsetTo<FeatureParams>
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 featureParams;	/* Offset to Feature Parameters table (if one
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * has been defined for the feature), relative
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * to the beginning of the Feature Table; = Null
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * if not required */
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IndexArray	 lookupIndex;	/* Array of LookupList indices */
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, lookupIndex);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef RecordListOf<Feature> FeatureList;
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LookupFlag : USHORT
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Flags {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RightToLeft		= 0x0001u,
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IgnoreBaseGlyphs	= 0x0002u,
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IgnoreLigatures	= 0x0004u,
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IgnoreMarks		= 0x0008u,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IgnoreFlags		= 0x000Eu,
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UseMarkFilteringSet	= 0x0010u,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Reserved		= 0x00E0u,
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MarkAttachmentType	= 0xFF00u
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (2);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Lookup
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_subtable_count (void) const { return subTable.len; }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_type (void) const { return lookupType; }
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * higher 16-bit is mark-filtering-set if the lookup uses one.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Not to be confused with glyph_props which is very similar. */
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline uint32_t get_props (void) const
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int flag = lookupFlag;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flag += (markFilteringSet << 16);
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return flag;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int lookup_type,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 uint32_t lookup_props,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int num_subtables)
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lookupType.set (lookup_type);
5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    lookupFlag.set (lookup_props & 0xFFFFu);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      markFilteringSet.set (lookup_props >> 16);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	lookupFlag;		/* Lookup qualifiers */
6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ArrayOf<Offset<> >
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		subTable;		/* Array of SubTables */
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * structure. This field is only present if bit
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * UseMarkFilteringSet of lookup flags is set. */
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef OffsetListOf<Lookup> LookupList;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Coverage Table
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CoverageFormat1
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct Coverage;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int i = glyphArray.bsearch (glyph_id);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return i;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<GlyphID> &glyphs,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int num_glyphs)
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphArray.len.set (num_glyphs);
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < num_glyphs; i++)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glyphArray[i] = glyphs[i];
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphs.advance (num_glyphs);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (glyphArray.sanitize (c));
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return glyphs->has (glyphArray[index]);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename set_t>
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_coverage (set_t *glyphs) const {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = glyphArray.len;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glyphs->add (glyphArray[i]);
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /* Older compilers need this to be public. */
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Iter {
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline bool more (void) { return i < c->glyphArray.len; }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void next (void) { i++; }
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_coverage (void) { return i; }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private:
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct CoverageFormat1 *c;
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int i;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private:
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	coverageFormat;	/* Format identifier--format = 1 */
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SortedArrayOf<GlyphID>
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		glyphArray;	/* Array of GlyphIDs--in numerical order */
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, glyphArray);
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CoverageFormat2
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct Coverage;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int i = rangeRecord.bsearch (glyph_id);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != -1) {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RangeRecord &range = rangeRecord[i];
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return (unsigned int) range.value + (glyph_id - range.start);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NOT_COVERED;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<GlyphID> &glyphs,
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int num_glyphs)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!num_glyphs)) return TRACE_RETURN (true);
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_ranges = 1;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 1; i < num_glyphs; i++)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glyphs[i - 1] + 1 != glyphs[i])
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_ranges++;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rangeRecord.len.set (num_ranges);
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (rangeRecord))) return TRACE_RETURN (false);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int range = 0;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rangeRecord[range].start = glyphs[0];
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rangeRecord[range].value.set (0);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 1; i < num_glyphs; i++)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glyphs[i - 1] + 1 != glyphs[i]) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	range++;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rangeRecord[range].start = glyphs[i];
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rangeRecord[range].value.set (i);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rangeRecord[range].end = glyphs[i];
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rangeRecord[range].end = glyphs[i];
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphs.advance (num_glyphs);
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rangeRecord.sanitize (c));
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int i;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = rangeRecord.len;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < count; i++) {
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RangeRecord &range = rangeRecord[i];
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (range.value <= index &&
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  index < (unsigned int) range.value + (range.end - range.start) &&
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  range.intersects (glyphs))
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (index < range.value)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename set_t>
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_coverage (set_t *glyphs) const {
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = rangeRecord.len;
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rangeRecord[i].add_coverage (glyphs);
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /* Older compilers need this to be public. */
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Iter {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void init (const CoverageFormat2 &c_) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c = &c_;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coverage = 0;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = 0;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline bool more (void) { return i < c->rangeRecord.len; }
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void next (void) {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coverage++;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j == c->rangeRecord[i].end) {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i++;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (more ())
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  j = c->rangeRecord[i].start;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      j++;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_glyph (void) { return j; }
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_coverage (void) { return coverage; }
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private:
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct CoverageFormat2 *c;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int i, j, coverage;
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private:
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	coverageFormat;	/* Format identifier--format = 2 */
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SortedArrayOf<RangeRecord>
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rangeRecord;	/* Array of glyph ranges--ordered by
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * Start GlyphID. rangeCount entries
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * long */
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, rangeRecord);
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Coverage
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.get_coverage(glyph_id);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return u.format2.get_coverage(glyph_id);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return NOT_COVERED;
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<GlyphID> &glyphs,
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int num_glyphs)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_ranges = 1;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 1; i < num_glyphs; i++)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glyphs[i - 1] + 1 != glyphs[i])
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_ranges++;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs));
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs));
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (false);
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.sanitize (c));
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return TRACE_RETURN (u.format2.sanitize (c));
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (true);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects (const hb_set_t *glyphs) const {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO speed this up */
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Coverage::Iter iter;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (iter.init (*this); iter.more (); iter.next ()) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glyphs->has (iter.get_glyph ()))
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.intersects_coverage (glyphs, index);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return u.format2.intersects_coverage (glyphs, index);
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return false;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename set_t>
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_coverage (set_t *glyphs) const {
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: u.format1.add_coverage (glyphs); break;
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: u.format2.add_coverage (glyphs); break;
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:                                 break;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Iter {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Iter (void) : format (0) {};
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void init (const Coverage &c_) {
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      format = c_.u.format;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
877f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case 1: u.format1.init (c_.u.format1); return;
878f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      case 2: u.format2.init (c_.u.format2); return;
879f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      default:                               return;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline bool more (void) {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: return u.format1.more ();
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: return u.format2.more ();
886f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      default:return false;
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void next (void) {
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: u.format1.next (); break;
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: u.format2.next (); break;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:                   break;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_glyph (void) {
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: return u.format1.get_glyph ();
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: return u.format2.get_glyph ();
900f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      default:return 0;
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_coverage (void) {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: return u.format1.get_coverage ();
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: return u.format2.get_coverage ();
907f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      default:return -1;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private:
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int format;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    union {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CoverageFormat1::Iter	format1;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CoverageFormat2::Iter	format2;
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } u;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT		format;		/* Format identifier */
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CoverageFormat1	format1;
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CoverageFormat2	format2;
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_UNION (2, format);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Class Definition Table
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ClassDefFormat1
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct ClassDef;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_class (hb_codepoint_t glyph_id) const
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely ((unsigned int) (glyph_id - startGlyph) < classValue.len))
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return classValue[glyph_id - startGlyph];
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename set_t>
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void add_class (set_t *glyphs, unsigned int klass) const {
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = classValue.len;
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (classValue[i] == klass)
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        glyphs->add (startGlyph + i);
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = classValue.len;
961f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (klass == 0)
962f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
963f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      /* Match if there's any glyph that is not listed! */
964f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      hb_codepoint_t g = -1;
965f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!hb_set_next (glyphs, &g))
966f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return false;
967f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (g < startGlyph)
968f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return true;
969f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      g = startGlyph + count - 1;
970f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (hb_set_next (glyphs, &g))
971f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return true;
972f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      /* Fall through. */
973f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (classValue[i] == klass && glyphs->has (startGlyph + i))
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	classFormat;		/* Format identifier--format = 1 */
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOf<USHORT>
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		classValue;		/* Array of Class Values--one per GlyphID */
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (6, classValue);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ClassDefFormat2
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct ClassDef;
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_class (hb_codepoint_t glyph_id) const
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int i = rangeRecord.bsearch (glyph_id);
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != -1)
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rangeRecord[i].value;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rangeRecord.sanitize (c));
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename set_t>
10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void add_class (set_t *glyphs, unsigned int klass) const {
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = rangeRecord.len;
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
10112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rangeRecord[i].value == klass)
10122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rangeRecord[i].add_coverage (glyphs);
10132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = rangeRecord.len;
1017f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (klass == 0)
1018f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    {
1019f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      /* Match if there's any glyph that is not listed! */
1020f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      hb_codepoint_t g = (hb_codepoint_t) -1;
1021f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      for (unsigned int i = 0; i < count; i++)
1022f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      {
1023f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (!hb_set_next (glyphs, &g))
1024f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  break;
1025f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (g < rangeRecord[i].start)
1026f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	  return true;
1027f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	g = rangeRecord[i].end;
1028f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1029f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (g != (hb_codepoint_t) -1 && hb_set_next (glyphs, &g))
1030f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return true;
1031f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      /* Fall through. */
1032f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	classFormat;	/* Format identifier--format = 2 */
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SortedArrayOf<RangeRecord>
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rangeRecord;	/* Array of glyph ranges--ordered by
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * Start GlyphID */
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, rangeRecord);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ClassDef
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_class (hb_codepoint_t glyph_id) const
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.get_class(glyph_id);
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return u.format2.get_class(glyph_id);
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return 0;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
10602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.sanitize (c));
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return TRACE_RETURN (u.format2.sanitize (c));
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (true);
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void add_class (hb_set_t *glyphs, unsigned int klass) const {
10702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (u.format) {
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 1: u.format1.add_class (glyphs, klass); return;
10722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 2: u.format2.add_class (glyphs, klass); return;
10732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:return;
10742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.intersects_class (glyphs, klass);
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return u.format2.intersects_class (glyphs, klass);
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return false;
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT		format;		/* Format identifier */
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClassDefFormat1	format1;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClassDefFormat2	format2;
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u;
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_UNION (2, format);
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Device Tables
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Device
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_position_t get_x_delta (hb_font_t *font) const
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return get_delta (font->x_ppem, font->x_scale); }
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_position_t get_y_delta (hb_font_t *font) const
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return get_delta (font->y_ppem, font->y_scale); }
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int get_delta (unsigned int ppem, int scale) const
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ppem) return 0;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int pixels = get_delta_pixels (ppem);
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pixels) return 0;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return (int) (pixels * (int64_t) scale / ppem);
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int get_delta_pixels (unsigned int ppem_size) const
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int f = deltaFormat;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (f < 1 || f > 3))
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ppem_size < startSize || ppem_size > endSize)
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int s = ppem_size - startSize;
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int byte = deltaValue[s >> (4 - f)];
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
11345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    unsigned int mask = (0xFFFFu >> (16 - (1 << f)));
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int delta = bits & mask;
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((unsigned int) delta >= ((mask + 1) >> 1))
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta -= mask + 1;
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return delta;
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_size (void) const
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int f = deltaFormat;
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
11522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	startSize;		/* Smallest size to correct--in ppem */
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	endSize;		/* Largest size to correct--in ppem */
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * 1	Signed 2-bit value, 8 values per uint16
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * 2	Signed 4-bit value, 4 values per uint16
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * 3	Signed 8-bit value, 2 values per uint16
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 */
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	deltaValue[VAR];	/* Array of compressed data */
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (6, deltaValue);
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} /* namespace OT */
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
1174