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
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * OpenType Layout Common Table Formats
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Script, ScriptList, LangSys, Feature, FeatureList, Lookup, LookupList
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Record
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int cmp (hb_tag_t a) const {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return tag.cmp (a);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct sanitize_closure_t {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    hb_tag_t tag;
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void *list_base;
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, void *base) {
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const sanitize_closure_t closure = {tag, base};
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure));
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Tag		tag;		/* 4-byte Tag identifier */
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<Type>
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		offset;		/* Offset from beginning of object holding
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * the Record */
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (6);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RecordArrayOf : SortedArrayOf<Record<Type> > {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Tag& get_tag (unsigned int i) const
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* We cheat slightly and don't define separate Null objects
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * for Record types.  Instead, we return the correct Null(Tag)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     * here. */
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (i >= this->len)) return Null(Tag);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (*this)[i].tag;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_tags (unsigned int start_offset,
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				unsigned int *record_count /* IN/OUT */,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				hb_tag_t     *record_tags /* OUT */) const
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (record_count) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const Record<Type> *arr = this->sub_array (start_offset, record_count);
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int count = *record_count;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned int i = 0; i < count; i++)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	record_tags[i] = arr[i].tag;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this->len;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool find_index (hb_tag_t tag, unsigned int *index) const
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i = this->search (tag);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != -1) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (index) *index = i;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index) *index = Index::NOT_FOUND_INDEX;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename Type>
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RecordListOf : RecordArrayOf<Type>
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Type& operator [] (unsigned int i) const
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return this+RecordArrayOf<Type>::operator [](i).offset; }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (RecordArrayOf<Type>::sanitize (c, this));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct RangeRecord
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int cmp (hb_codepoint_t g) const {
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return g < start ? -1 : g <= end ? 0 : +1 ;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects (const hb_set_t *glyphs) const {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return glyphs->intersects (start, end);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename set_t>
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_coverage (set_t *glyphs) const {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphs->add_range (start, end);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GlyphID	start;		/* First GlyphID in the range */
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GlyphID	end;		/* Last GlyphID in the range */
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	value;		/* Value */
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (6);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (RangeRecord, "\000\001");
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IndexArray : ArrayOf<Index>
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_indexes (unsigned int start_offset,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   unsigned int *_count /* IN/OUT */,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				   unsigned int *_indexes /* OUT */) const
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (_count) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const USHORT *arr = this->sub_array (start_offset, _count);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unsigned int count = *_count;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned int i = 0; i < count; i++)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	_indexes[i] = arr[i];
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this->len;
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Script;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LangSys;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Feature;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LangSys
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_feature_count (void) const
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return featureIndex.len; }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_tag_t get_feature_index (unsigned int i) const
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return featureIndex[i]; }
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_feature_indexes (unsigned int start_offset,
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int *feature_count /* IN/OUT */,
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					   unsigned int *feature_indexes /* OUT */) const
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return featureIndex.get_indexes (start_offset, feature_count, feature_indexes); }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool has_required_feature (void) const { return reqFeatureIndex != 0xffff; }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_required_feature_index (void) const
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reqFeatureIndex == 0xffff)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return Index::NOT_FOUND_INDEX;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   return reqFeatureIndex;;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c,
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			const Record<LangSys>::sanitize_closure_t * = NULL) {
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Offset	lookupOrder;	/* = Null (reserved for an offset to a
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * reordering table) */
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	reqFeatureIndex;/* Index of a feature required for this
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * language system--if no required features
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * = 0xFFFF */
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IndexArray	featureIndex;	/* Array of indices into the FeatureList */
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (6, featureIndex);
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_NULL_DATA (LangSys, "\0\0\xFF\xFF");
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Script
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lang_sys_count (void) const
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return langSys.len; }
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const Tag& get_lang_sys_tag (unsigned int i) const
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return langSys.get_tag (i); }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lang_sys_tags (unsigned int start_offset,
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 unsigned int *lang_sys_count /* IN/OUT */,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 hb_tag_t     *lang_sys_tags /* OUT */) const
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return langSys.get_tags (start_offset, lang_sys_count, lang_sys_tags); }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const LangSys& get_lang_sys (unsigned int i) const
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == Index::NOT_FOUND_INDEX) return get_default_lang_sys ();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return this+langSys[i].offset;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool find_lang_sys_index (hb_tag_t tag, unsigned int *index) const
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return langSys.find_index (tag, index); }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool has_default_lang_sys (void) const { return defaultLangSys != 0; }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c,
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			const Record<Script>::sanitize_closure_t * = NULL) {
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (defaultLangSys.sanitize (c, this) && langSys.sanitize (c, this));
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OffsetTo<LangSys>
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		defaultLangSys;	/* Offset to DefaultLangSys table--from
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * beginning of Script table--may be Null */
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordArrayOf<LangSys>
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		langSys;	/* Array of LangSysRecords--listed
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * alphabetically by LangSysTag */
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, langSys);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef RecordListOf<Script> ScriptList;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* http://www.microsoft.com/typography/otspec/features_pt.htm#size */
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FeatureParamsSize
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false);
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* This subtable has some "history", if you will.  Some earlier versions of
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Adobe tools calculated the offset of the FeatureParams sutable from the
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * beginning of the FeatureList table!  Now, that is dealt with in the
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Feature implementation.  But we still need to be able to tell junk from
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * real data.  Note: We don't check that the nameID actually exists.
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Read Roberts wrote on 9/15/06 on opentype-list@indx.co.uk :
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Yes, it is correct that a new version of the AFDKO (version 2.0) will be
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * coming out soon, and that the makeotf program will build a font with a
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * 'size' feature that is correct by the specification.
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * The specification for this feature tag is in the "OpenType Layout Tag
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Registry". You can see a copy of this at:
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * http://partners.adobe.com/public/developer/opentype/index_tag8.html#size
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Here is one set of rules to determine if the 'size' feature is built
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * correctly, or as by the older versions of MakeOTF. You may be able to do
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * better.
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Assume that the offset to the size feature is according to specification,
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * and make the following value checks. If it fails, assume the the size
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * feature is calculated as versions of MakeOTF before the AFDKO 2.0 built it.
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * If this fails, reject the 'size' feature. The older makeOTF's calculated the
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * offset from the beginning of the FeatureList table, rather than from the
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * beginning of the 'size' Feature table.
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * If "design size" == 0:
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     fails check
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Else if ("subfamily identifier" == 0 and
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "range start" == 0 and
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "range end" == 0 and
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "range start" == 0 and
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "menu name ID" == 0)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     passes check: this is the format used when there is a design size
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * specified, but there is no recommended size range.
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Else if ("design size" <  "range start" or
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "design size" >   "range end" or
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "range end" <= "range start" or
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "menu name ID"  < 256 or
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     "menu name ID"  > 32767 or
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     menu name ID is not a name ID which is actually in the name table)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     fails test
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Else
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *     passes test.
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!designSize)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (false);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (subfamilyID == 0 &&
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     subfamilyNameID == 0 &&
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     rangeStart == 0 &&
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     rangeEnd == 0)
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (true);
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (designSize < rangeStart ||
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     designSize > rangeEnd ||
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     subfamilyNameID < 256 ||
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	     subfamilyNameID > 32767)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (false);
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (true);
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	designSize;	/* Represents the design size in 720/inch
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * units (decipoints).  The design size entry
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * must be non-zero.  When there is a design
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * size but no recommended size range, the
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * rest of the array will consist of zeros. */
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	subfamilyID;	/* Has no independent meaning, but serves
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * as an identifier that associates fonts
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * in a subfamily. All fonts which share a
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * Preferred or Font Family name and which
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * differ only by size range shall have the
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * same subfamily value, and no fonts which
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * differ in weight or style shall have the
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * same subfamily value. If this value is
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * zero, the remaining fields in the array
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * will be ignored. */
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	subfamilyNameID;/* If the preceding value is non-zero, this
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * value must be set in the range 256 - 32767
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * (inclusive). It records the value of a
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * field in the name table, which must
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * contain English-language strings encoded
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * in Windows Unicode and Macintosh Roman,
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * and may contain additional strings
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * localized to other scripts and languages.
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * Each of these strings is the name an
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * application should use, in combination
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * with the family name, to represent the
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * subfamily in a menu.  Applications will
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * choose the appropriate version based on
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * their selection criteria. */
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	rangeStart;	/* Large end of the recommended usage range
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * (inclusive), stored in 720/inch units
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * (decipoints). */
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	rangeEnd;	/* Small end of the recommended usage range
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				   (exclusive), stored in 720/inch units
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * (decipoints). */
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_STATIC (10);
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/* http://www.microsoft.com/typography/otspec/features_pt.htm#ssxx */
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FeatureParamsStylisticSet
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* Right now minorVersion is at zero.  Which means, any table supports
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * the uiNameID field. */
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (c->check_struct (this));
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	minorVersion;	/* (set to 0): This corresponds to a “minor”
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * version number. Additional data may be
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * added to the end of this Feature Parameters
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * table in the future. */
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	uiNameID;	/* The 'name' table name ID that specifies a
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * string (or strings, for multiple languages)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * for a user-interface label for this
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * feature.  The values of uiLabelNameId and
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * sampleTextNameId are expected to be in the
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * font-specific name ID range (256-32767),
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * though that is not a requirement in this
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * Feature Parameters specification. The
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * user-interface label for the feature can
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * be provided in multiple languages. An
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * English string should be included as a
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * fallback. The string should be kept to a
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * minimal length to fit comfortably with
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				 * different application interfaces. */
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_STATIC (4);
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FeatureParamsCharacterVariants
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) &&
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			 characters.sanitize (c));
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	format;			/* Format number is set to 0. */
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	featUILableNameID;	/* The ‘name’ table name ID that
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * specifies a string (or strings,
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * for multiple languages) for a
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * user-interface label for this
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * feature. (May be NULL.) */
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	featUITooltipTextNameID;/* The ‘name’ table name ID that
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * specifies a string (or strings,
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * for multiple languages) that an
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * application can use for tooltip
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * text for this feature. (May be
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * NULL.) */
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	sampleTextNameID;	/* The ‘name’ table name ID that
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * specifies sample text that
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * illustrates the effect of this
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * feature. (May be NULL.) */
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	numNamedParameters;	/* Number of named parameters. (May
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * be zero.) */
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  USHORT	firstParamUILabelNameID;/* The first ‘name’ table name ID
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * used to specify strings for
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * user-interface labels for the
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * feature parameters. (Must be zero
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * if numParameters is zero.) */
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ArrayOf<UINT24>
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		characters;		/* Array of the Unicode Scalar Value
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * of the characters for which this
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * feature provides glyph variants.
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)					 * (May be zero.) */
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_ARRAY (14, characters);
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct FeatureParams
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles){
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c, hb_tag_t tag) {
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (tag == HB_TAG ('s','i','z','e'))
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (u.size.sanitize (c));
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((tag & 0xFFFF0000) == HB_TAG ('s','s','\0','\0')) /* ssXX */
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (u.stylisticSet.sanitize (c));
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((tag & 0xFFFF0000) == HB_TAG ('c','v','\0','\0')) /* cvXX */
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (u.characterVariants.sanitize (c));
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (true);
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const FeatureParamsSize& get_size_params (hb_tag_t tag) const
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (tag == HB_TAG ('s','i','z','e'))
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return u.size;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return Null(FeatureParamsSize);
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private:
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  union {
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FeatureParamsSize			size;
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FeatureParamsStylisticSet		stylisticSet;
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  FeatureParamsCharacterVariants	characterVariants;
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } u;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DEFINE_SIZE_STATIC (17);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Feature
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lookup_count (void) const
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return lookupIndex.len; }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_tag_t get_lookup_index (unsigned int i) const
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return lookupIndex[i]; }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_lookup_indexes (unsigned int start_index,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  unsigned int *lookup_count /* IN/OUT */,
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					  unsigned int *lookup_tags /* OUT */) const
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return lookupIndex.get_indexes (start_index, lookup_count, lookup_tags); }
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline const FeatureParams &get_feature_params (void) const
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  { return this+featureParams; }
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c,
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)			const Record<Feature>::sanitize_closure_t *closure) {
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (!(c->check_struct (this) && lookupIndex.sanitize (c))))
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (false);
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    /* Some earlier versions of Adobe tools calculated the offset of the
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * FeatureParams subtable from the beginning of the FeatureList table!
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * If sanitizing "failed" for the FeatureParams subtable, try it with the
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * alternative location.  We would know sanitize "failed" if old value
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * of the offset was non-zero, but it's zeroed now.
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     *
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Only do this for the 'size' feature, since at the time of the faulty
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     * Adobe tools, only the 'size' feature had FeatureParams defined.
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     */
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Offset orig_offset = featureParams;
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (unlikely (!featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE)))
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (false);
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (likely (!orig_offset))
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return TRACE_RETURN (true);
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (featureParams == 0 && closure &&
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	closure->tag == HB_TAG ('s','i','z','e') &&
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	closure->list_base && closure->list_base < this)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    {
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned int new_offset_int = (unsigned int) orig_offset -
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)				    ((char *) this - (char *) closure->list_base);
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Offset new_offset;
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      /* Check that it did not overflow. */
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_offset.set (new_offset_int);
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (new_offset == new_offset_int &&
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	  featureParams.try_set (c, new_offset) &&
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	  !featureParams.sanitize (c, this, closure ? closure->tag : HB_TAG_NONE))
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)	return TRACE_RETURN (false);
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return TRACE_RETURN (true);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OffsetTo<FeatureParams>
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)		 featureParams;	/* Offset to Feature Parameters table (if one
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * has been defined for the feature), relative
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * to the beginning of the Feature Table; = Null
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * if not required */
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IndexArray	 lookupIndex;	/* Array of LookupList indices */
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, lookupIndex);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef RecordListOf<Feature> FeatureList;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct LookupFlag : USHORT
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum Flags {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RightToLeft		= 0x0001u,
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IgnoreBaseGlyphs	= 0x0002u,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IgnoreLigatures	= 0x0004u,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IgnoreMarks		= 0x0008u,
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IgnoreFlags		= 0x000Eu,
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UseMarkFilteringSet	= 0x0010u,
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Reserved		= 0x00E0u,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MarkAttachmentType	= 0xFF00u
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_STATIC (2);
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Lookup
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_subtable_count (void) const { return subTable.len; }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_type (void) const { return lookupType; }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* lookup_props is a 32-bit integer where the lower 16-bit is LookupFlag and
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * higher 16-bit is mark-filtering-set if the lookup uses one.
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   * Not to be confused with glyph_props which is very similar. */
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline uint32_t get_props (void) const
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int flag = lookupFlag;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (flag & LookupFlag::UseMarkFilteringSet))
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flag += (markFilteringSet << 16);
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return flag;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int lookup_type,
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 uint32_t lookup_props,
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int num_subtables)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lookupType.set (lookup_type);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lookupFlag.set (lookup_props & 0xFFFF);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!subTable.serialize (c, num_subtables))) return TRACE_RETURN (false);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      markFilteringSet.set (lookup_props >> 16);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* Real sanitize of the subtables is done by GSUB/GPOS/... */
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(c->check_struct (this) && subTable.sanitize (c))) return TRACE_RETURN (false);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (lookupFlag & LookupFlag::UseMarkFilteringSet)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      USHORT &markFilteringSet = StructAfter<USHORT> (subTable);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!markFilteringSet.sanitize (c)) return TRACE_RETURN (false);
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	lookupType;		/* Different enumerations for GSUB and GPOS */
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	lookupFlag;		/* Lookup qualifiers */
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOf<Offset>
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		subTable;		/* Array of SubTables */
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	markFilteringSetX[VAR];	/* Index (base 0) into GDEF mark glyph sets
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * structure. This field is only present if bit
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * UseMarkFilteringSet of lookup flags is set. */
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY2 (6, subTable, markFilteringSetX);
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef OffsetListOf<Lookup> LookupList;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Coverage Table
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CoverageFormat1
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct Coverage;
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i = glyphArray.search (glyph_id);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_STATIC (((unsigned int) -1) == NOT_COVERED);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return i;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<GlyphID> &glyphs,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int num_glyphs)
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphArray.len.set (num_glyphs);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (glyphArray))) return TRACE_RETURN (false);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < num_glyphs; i++)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glyphArray[i] = glyphs[i];
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphs.advance (num_glyphs);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (glyphArray.sanitize (c));
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return glyphs->has (glyphArray[index]);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename set_t>
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_coverage (set_t *glyphs) const {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = glyphArray.len;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      glyphs->add (glyphArray[i]);
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /* Older compilers need this to be public. */
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Iter {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline bool more (void) { return i < c->glyphArray.len; }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void next (void) { i++; }
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_coverage (void) { return i; }
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private:
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct CoverageFormat1 *c;
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int i;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private:
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	coverageFormat;	/* Format identifier--format = 1 */
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SortedArrayOf<GlyphID>
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		glyphArray;	/* Array of GlyphIDs--in numerical order */
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, glyphArray);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct CoverageFormat2
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct Coverage;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i = rangeRecord.search (glyph_id);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != -1) {
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RangeRecord &range = rangeRecord[i];
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return (unsigned int) range.value + (glyph_id - range.start);
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NOT_COVERED;
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<GlyphID> &glyphs,
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int num_glyphs)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!num_glyphs)) return TRACE_RETURN (true);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_ranges = 1;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 1; i < num_glyphs; i++)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glyphs[i - 1] + 1 != glyphs[i])
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_ranges++;
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rangeRecord.len.set (num_ranges);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend (rangeRecord))) return TRACE_RETURN (false);
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int range = 0;
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rangeRecord[range].start = glyphs[0];
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rangeRecord[range].value.set (0);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 1; i < num_glyphs; i++)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glyphs[i - 1] + 1 != glyphs[i]) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	range++;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rangeRecord[range].start = glyphs[i];
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	rangeRecord[range].value.set (i);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rangeRecord[range].end = glyphs[i];
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rangeRecord[range].end = glyphs[i];
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    glyphs.advance (num_glyphs);
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (true);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rangeRecord.sanitize (c));
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int i;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = rangeRecord.len;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < count; i++) {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RangeRecord &range = rangeRecord[i];
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (range.value <= index &&
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  index < (unsigned int) range.value + (range.end - range.start) &&
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  range.intersects (glyphs))
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      else if (index < range.value)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename set_t>
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_coverage (set_t *glyphs) const {
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = rangeRecord.len;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rangeRecord[i].add_coverage (glyphs);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  public:
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  /* Older compilers need this to be public. */
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Iter {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void init (const CoverageFormat2 &c_) {
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      c = &c_;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coverage = 0;
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = 0;
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline bool more (void) { return i < c->rangeRecord.len; }
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void next (void) {
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      coverage++;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (j == c->rangeRecord[i].end) {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        i++;
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	if (more ())
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	  j = c->rangeRecord[i].start;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)	return;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      j++;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_glyph (void) { return j; }
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_coverage (void) { return coverage; }
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private:
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct CoverageFormat2 *c;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int i, j, coverage;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  private:
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	coverageFormat;	/* Format identifier--format = 2 */
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SortedArrayOf<RangeRecord>
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rangeRecord;	/* Array of glyph ranges--ordered by
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * Start GlyphID. rangeCount entries
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * long */
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, rangeRecord);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Coverage
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_coverage (hb_codepoint_t glyph_id) const
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.get_coverage(glyph_id);
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return u.format2.get_coverage(glyph_id);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return NOT_COVERED;
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool serialize (hb_serialize_context_t *c,
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 Supplier<GlyphID> &glyphs,
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)			 unsigned int num_glyphs)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SERIALIZE (this);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (!c->extend_min (*this))) return TRACE_RETURN (false);
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int num_ranges = 1;
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 1; i < num_glyphs; i++)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glyphs[i - 1] + 1 != glyphs[i])
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        num_ranges++;
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    u.format.set (num_glyphs * 2 < num_ranges * 3 ? 1 : 2);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.serialize (c, glyphs, num_glyphs));
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return TRACE_RETURN (u.format2.serialize (c, glyphs, num_glyphs));
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (false);
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.sanitize (c));
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return TRACE_RETURN (u.format2.sanitize (c));
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (true);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects (const hb_set_t *glyphs) const {
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /* TODO speed this up */
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Coverage::Iter iter;
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (iter.init (*this); iter.more (); iter.next ()) {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (glyphs->has (iter.get_glyph ()))
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.intersects_coverage (glyphs, index);
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return u.format2.intersects_coverage (glyphs, index);
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return false;
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <typename set_t>
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline void add_coverage (set_t *glyphs) const {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: u.format1.add_coverage (glyphs); break;
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: u.format2.add_coverage (glyphs); break;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:                                 break;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Iter {
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Iter (void) : format (0) {};
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void init (const Coverage &c_) {
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      format = c_.u.format;
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: return u.format1.init (c_.u.format1);
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: return u.format2.init (c_.u.format2);
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:return;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline bool more (void) {
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: return u.format1.more ();
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: return u.format2.more ();
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:return true;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline void next (void) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: u.format1.next (); break;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: u.format2.next (); break;
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:                   break;
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_glyph (void) {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: return u.format1.get_glyph ();
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: return u.format2.get_glyph ();
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:return true;
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    inline uint16_t get_coverage (void) {
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (format) {
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 1: return u.format1.get_coverage ();
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case 2: return u.format2.get_coverage ();
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:return true;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    private:
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int format;
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    union {
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CoverageFormat1::Iter	format1;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CoverageFormat2::Iter	format2;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } u;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT		format;		/* Format identifier */
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CoverageFormat1	format1;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CoverageFormat2	format2;
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u;
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_UNION (2, format);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Class Definition Table
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ClassDefFormat1
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct ClassDef;
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_class (hb_codepoint_t glyph_id) const
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely ((unsigned int) (glyph_id - startGlyph) < classValue.len))
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return classValue[glyph_id - startGlyph];
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && classValue.sanitize (c));
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename set_t>
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void add_class (set_t *glyphs, unsigned int klass) const {
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = classValue.len;
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (classValue[i] == klass)
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        glyphs->add (startGlyph + i);
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = classValue.len;
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (classValue[i] == klass && glyphs->has (startGlyph + i))
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	classFormat;		/* Format identifier--format = 1 */
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GlyphID	startGlyph;		/* First GlyphID of the classValueArray */
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ArrayOf<USHORT>
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		classValue;		/* Array of Class Values--one per GlyphID */
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (6, classValue);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ClassDefFormat2
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend struct ClassDef;
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  private:
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_class (hb_codepoint_t glyph_id) const
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int i = rangeRecord.search (glyph_id);
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != -1)
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rangeRecord[i].value;
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (rangeRecord.sanitize (c));
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  template <typename set_t>
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void add_class (set_t *glyphs, unsigned int klass) const {
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned int count = rangeRecord.len;
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (rangeRecord[i].value == klass)
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        rangeRecord[i].add_coverage (glyphs);
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int count = rangeRecord.len;
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned int i = 0; i < count; i++)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rangeRecord[i].value == klass && rangeRecord[i].intersects (glyphs))
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	classFormat;	/* Format identifier--format = 2 */
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SortedArrayOf<RangeRecord>
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)		rangeRecord;	/* Array of glyph ranges--ordered by
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)				 * Start GlyphID */
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (4, rangeRecord);
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ClassDef
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_class (hb_codepoint_t glyph_id) const
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.get_class(glyph_id);
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return u.format2.get_class(glyph_id);
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return 0;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!u.format.sanitize (c)) return TRACE_RETURN (false);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return TRACE_RETURN (u.format1.sanitize (c));
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return TRACE_RETURN (u.format2.sanitize (c));
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return TRACE_RETURN (true);
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  inline void add_class (hb_set_t *glyphs, unsigned int klass) const {
10382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (u.format) {
10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 1: u.format1.add_class (glyphs, klass); return;
10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case 2: u.format2.add_class (glyphs, klass); return;
10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    default:return;
10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
10442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (u.format) {
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1: return u.format1.intersects_class (glyphs, klass);
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2: return u.format2.intersects_class (glyphs, klass);
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:return false;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  union {
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT		format;		/* Format identifier */
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClassDefFormat1	format1;
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClassDefFormat2	format2;
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } u;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_UNION (2, format);
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Device Tables
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Device
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_position_t get_x_delta (hb_font_t *font) const
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return get_delta (font->x_ppem, font->x_scale); }
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline hb_position_t get_y_delta (hb_font_t *font) const
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { return get_delta (font->y_ppem, font->y_scale); }
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int get_delta (unsigned int ppem, int scale) const
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ppem) return 0;
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int pixels = get_delta_pixels (ppem);
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!pixels) return 0;
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return pixels * (int64_t) scale / ppem;
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline int get_delta_pixels (unsigned int ppem_size) const
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int f = deltaFormat;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (f < 1 || f > 3))
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ppem_size < startSize || ppem_size > endSize)
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int s = ppem_size - startSize;
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int byte = deltaValue[s >> (4 - f)];
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int bits = (byte >> (16 - (((s & ((1 << (4 - f)) - 1)) + 1) << f)));
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int mask = (0xFFFF >> (16 - (1 << f)));
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int delta = bits & mask;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((unsigned int) delta >= ((mask + 1) >> 1))
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delta -= mask + 1;
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return delta;
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline unsigned int get_size (void) const
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int f = deltaFormat;
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (unlikely (f < 1 || f > 3 || startSize > endSize)) return 3 * USHORT::static_size;
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return USHORT::static_size * (4 + ((endSize - startSize) >> (4 - f)));
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline bool sanitize (hb_sanitize_context_t *c) {
11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_SANITIZE (this);
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TRACE_RETURN (c->check_struct (this) && c->check_range (this, this->get_size ()));
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  protected:
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	startSize;		/* Smallest size to correct--in ppem */
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	endSize;		/* Largest size to correct--in ppem */
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	deltaFormat;		/* Format of DeltaValue array data: 1, 2, or 3
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * 1	Signed 2-bit value, 8 values per uint16
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * 2	Signed 4-bit value, 4 values per uint16
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 * 3	Signed 8-bit value, 2 values per uint16
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)					 */
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  USHORT	deltaValue[VAR];	/* Array of compressed data */
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  public:
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEFINE_SIZE_ARRAY (6, deltaValue);
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} /* namespace OT */
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* HB_OT_LAYOUT_COMMON_PRIVATE_HH */
1142