src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-kern-table.hh
changeset 54232 7c11a7cc7c1d
parent 50826 f5b95be8b6e2
equal deleted inserted replaced
54231:e4813eded7cb 54232:7c11a7cc7c1d
    25  */
    25  */
    26 
    26 
    27 #ifndef HB_OT_KERN_TABLE_HH
    27 #ifndef HB_OT_KERN_TABLE_HH
    28 #define HB_OT_KERN_TABLE_HH
    28 #define HB_OT_KERN_TABLE_HH
    29 
    29 
    30 #include "hb-open-type-private.hh"
    30 #include "hb-aat-layout-kerx-table.hh"
       
    31 
    31 
    32 
    32 /*
    33 /*
    33  * kern -- Kerning
    34  * kern -- Kerning
    34  * https://docs.microsoft.com/en-us/typography/opentype/spec/kern
    35  * https://docs.microsoft.com/en-us/typography/opentype/spec/kern
    35  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
    36  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
    38 
    39 
    39 
    40 
    40 namespace OT {
    41 namespace OT {
    41 
    42 
    42 
    43 
    43 struct hb_glyph_pair_t
    44 template <typename KernSubTableHeader>
    44 {
    45 struct KernSubTableFormat3
    45   hb_codepoint_t left;
    46 {
    46   hb_codepoint_t right;
    47   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
    47 };
    48   {
    48 
    49     hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
    49 struct KernPair
    50     hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (kernValue).as_array (glyphCount);
    50 {
    51     hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (leftClass).as_array (glyphCount);
    51   inline int get_kerning (void) const
    52     hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8> > (rightClass).as_array (leftClassCount * rightClassCount);
    52   { return value; }
    53 
    53 
    54     unsigned int leftC = leftClass[left];
    54   inline int cmp (const hb_glyph_pair_t &o) const
    55     unsigned int rightC = rightClass[right];
    55   {
    56     if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
    56     int ret = left.cmp (o.left);
    57       return 0;
    57     if (ret) return ret;
    58     unsigned int i = leftC * rightClassCount + rightC;
    58     return right.cmp (o.right);
    59     return kernValue[kernIndex[i]];
    59   }
    60   }
    60 
    61 
    61   inline bool sanitize (hb_sanitize_context_t *c) const
    62   bool apply (AAT::hb_aat_apply_context_t *c) const
       
    63   {
       
    64     TRACE_APPLY (this);
       
    65 
       
    66     if (!c->plan->requested_kerning)
       
    67       return false;
       
    68 
       
    69     if (header.coverage & header.Backwards)
       
    70       return false;
       
    71 
       
    72     hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
       
    73     machine.kern (c->font, c->buffer, c->plan->kern_mask);
       
    74 
       
    75     return_trace (true);
       
    76   }
       
    77 
       
    78   bool sanitize (hb_sanitize_context_t *c) const
       
    79   {
       
    80     TRACE_SANITIZE (this);
       
    81     return_trace (c->check_struct (this) &&
       
    82                   c->check_range (kernValueZ,
       
    83                                   kernValueCount * sizeof (FWORD) +
       
    84                                   glyphCount * 2 +
       
    85                                   leftClassCount * rightClassCount));
       
    86   }
       
    87 
       
    88   protected:
       
    89   KernSubTableHeader    header;
       
    90   HBUINT16              glyphCount;     /* The number of glyphs in this font. */
       
    91   HBUINT8               kernValueCount; /* The number of kerning values. */
       
    92   HBUINT8               leftClassCount; /* The number of left-hand classes. */
       
    93   HBUINT8               rightClassCount;/* The number of right-hand classes. */
       
    94   HBUINT8               flags;          /* Set to zero (reserved for future use). */
       
    95   UnsizedArrayOf<FWORD> kernValueZ;     /* The kerning values.
       
    96                                          * Length kernValueCount. */
       
    97 #if 0
       
    98   UnsizedArrayOf<HBUINT8>leftClass;     /* The left-hand classes.
       
    99                                          * Length glyphCount. */
       
   100   UnsizedArrayOf<HBUINT8>rightClass;    /* The right-hand classes.
       
   101                                          * Length glyphCount. */
       
   102   UnsizedArrayOf<HBUINT8>kernIndex;     /* The indices into the kernValue array.
       
   103                                          * Length leftClassCount * rightClassCount */
       
   104 #endif
       
   105   public:
       
   106   DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
       
   107 };
       
   108 
       
   109 template <typename KernSubTableHeader>
       
   110 struct KernSubTable
       
   111 {
       
   112   unsigned int get_size () const { return u.header.length; }
       
   113   unsigned int get_type () const { return u.header.format; }
       
   114 
       
   115   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
       
   116   {
       
   117     switch (get_type ()) {
       
   118     /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
       
   119     case 0: return u.format0.get_kerning (left, right);
       
   120     default:return 0;
       
   121     }
       
   122   }
       
   123 
       
   124   template <typename context_t>
       
   125   typename context_t::return_t dispatch (context_t *c) const
       
   126   {
       
   127     unsigned int subtable_type = get_type ();
       
   128     TRACE_DISPATCH (this, subtable_type);
       
   129     switch (subtable_type) {
       
   130     case 0:     return_trace (c->dispatch (u.format0));
       
   131     case 1:     return_trace (u.header.apple ? c->dispatch (u.format1) : c->default_return_value ());
       
   132     case 2:     return_trace (c->dispatch (u.format2));
       
   133     case 3:     return_trace (u.header.apple ? c->dispatch (u.format3) : c->default_return_value ());
       
   134     default:    return_trace (c->default_return_value ());
       
   135     }
       
   136   }
       
   137 
       
   138   bool sanitize (hb_sanitize_context_t *c) const
       
   139   {
       
   140     TRACE_SANITIZE (this);
       
   141     if (unlikely (!u.header.sanitize (c) ||
       
   142                   u.header.length < u.header.min_size ||
       
   143                   !c->check_range (this, u.header.length))) return_trace (false);
       
   144 
       
   145     return_trace (dispatch (c));
       
   146   }
       
   147 
       
   148   public:
       
   149   union {
       
   150   KernSubTableHeader                            header;
       
   151   AAT::KerxSubTableFormat0<KernSubTableHeader>  format0;
       
   152   AAT::KerxSubTableFormat1<KernSubTableHeader>  format1;
       
   153   AAT::KerxSubTableFormat2<KernSubTableHeader>  format2;
       
   154   KernSubTableFormat3<KernSubTableHeader>       format3;
       
   155   } u;
       
   156   public:
       
   157   DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
       
   158 };
       
   159 
       
   160 
       
   161 struct KernOTSubTableHeader
       
   162 {
       
   163   static constexpr bool apple = false;
       
   164   typedef AAT::ObsoleteTypes Types;
       
   165 
       
   166   unsigned int tuple_count () const { return 0; }
       
   167   bool is_horizontal () const { return (coverage & Horizontal); }
       
   168 
       
   169   enum Coverage
       
   170   {
       
   171     Horizontal  = 0x01u,
       
   172     Minimum     = 0x02u,
       
   173     CrossStream = 0x04u,
       
   174     Override    = 0x08u,
       
   175 
       
   176     /* Not supported: */
       
   177     Backwards   = 0x00u,
       
   178     Variation   = 0x00u,
       
   179   };
       
   180 
       
   181   bool sanitize (hb_sanitize_context_t *c) const
    62   {
   182   {
    63     TRACE_SANITIZE (this);
   183     TRACE_SANITIZE (this);
    64     return_trace (c->check_struct (this));
   184     return_trace (c->check_struct (this));
    65   }
   185   }
    66 
   186 
       
   187   public:
       
   188   HBUINT16      versionZ;       /* Unused. */
       
   189   HBUINT16      length;         /* Length of the subtable (including this header). */
       
   190   HBUINT8       format;         /* Subtable format. */
       
   191   HBUINT8       coverage;       /* Coverage bits. */
       
   192   public:
       
   193   DEFINE_SIZE_STATIC (6);
       
   194 };
       
   195 
       
   196 struct KernOT : AAT::KerxTable<KernOT>
       
   197 {
       
   198   friend struct AAT::KerxTable<KernOT>;
       
   199 
       
   200   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
       
   201   static constexpr unsigned minVersion = 0u;
       
   202 
       
   203   typedef KernOTSubTableHeader SubTableHeader;
       
   204   typedef SubTableHeader::Types Types;
       
   205   typedef KernSubTable<SubTableHeader> SubTable;
       
   206 
    67   protected:
   207   protected:
    68   GlyphID       left;
   208   HBUINT16      version;        /* Version--0x0000u */
    69   GlyphID       right;
   209   HBUINT16      tableCount;     /* Number of subtables in the kerning table. */
    70   FWORD         value;
   210   SubTable      firstSubTable;  /* Subtables. */
    71   public:
   211   public:
    72   DEFINE_SIZE_STATIC (6);
   212   DEFINE_SIZE_MIN (4);
    73 };
   213 };
    74 
   214 
    75 struct KernSubTableFormat0
   215 
    76 {
   216 struct KernAATSubTableHeader
    77   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
   217 {
    78   {
   218   static constexpr bool apple = true;
    79     hb_glyph_pair_t pair = {left, right};
   219   typedef AAT::ObsoleteTypes Types;
    80     int i = pairs.bsearch (pair);
   220 
    81     if (i == -1)
   221   unsigned int tuple_count () const { return 0; }
    82       return 0;
   222   bool is_horizontal () const       { return !(coverage & Vertical); }
    83     return pairs[i].get_kerning ();
   223 
    84   }
   224   enum Coverage
    85 
   225   {
    86   inline bool sanitize (hb_sanitize_context_t *c) const
   226     Vertical    = 0x80u,
    87   {
   227     CrossStream = 0x40u,
    88     TRACE_SANITIZE (this);
   228     Variation   = 0x20u,
    89     return_trace (pairs.sanitize (c));
   229 
    90   }
   230     /* Not supported: */
       
   231     Backwards   = 0x00u,
       
   232   };
       
   233 
       
   234   bool sanitize (hb_sanitize_context_t *c) const
       
   235   {
       
   236     TRACE_SANITIZE (this);
       
   237     return_trace (c->check_struct (this));
       
   238   }
       
   239 
       
   240   public:
       
   241   HBUINT32      length;         /* Length of the subtable (including this header). */
       
   242   HBUINT8       coverage;       /* Coverage bits. */
       
   243   HBUINT8       format;         /* Subtable format. */
       
   244   HBUINT16      tupleIndex;     /* The tuple index (used for variations fonts).
       
   245                                * This value specifies which tuple this subtable covers.
       
   246                                * Note: We don't implement. */
       
   247   public:
       
   248   DEFINE_SIZE_STATIC (8);
       
   249 };
       
   250 
       
   251 struct KernAAT : AAT::KerxTable<KernAAT>
       
   252 {
       
   253   friend struct AAT::KerxTable<KernAAT>;
       
   254 
       
   255   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
       
   256   static constexpr unsigned minVersion = 0x00010000u;
       
   257 
       
   258   typedef KernAATSubTableHeader SubTableHeader;
       
   259   typedef SubTableHeader::Types Types;
       
   260   typedef KernSubTable<SubTableHeader> SubTable;
    91 
   261 
    92   protected:
   262   protected:
    93   BinSearchArrayOf<KernPair> pairs;     /* Array of kerning pairs. */
   263   HBUINT32      version;        /* Version--0x00010000u */
    94   public:
   264   HBUINT32      tableCount;     /* Number of subtables in the kerning table. */
    95   DEFINE_SIZE_ARRAY (8, pairs);
   265   SubTable      firstSubTable;  /* Subtables. */
    96 };
       
    97 
       
    98 struct KernClassTable
       
    99 {
       
   100   inline unsigned int get_class (hb_codepoint_t g) const { return classes[g - firstGlyph]; }
       
   101 
       
   102   inline bool sanitize (hb_sanitize_context_t *c) const
       
   103   {
       
   104     TRACE_SANITIZE (this);
       
   105     return_trace (firstGlyph.sanitize (c) && classes.sanitize (c));
       
   106   }
       
   107 
       
   108   protected:
       
   109   HBUINT16              firstGlyph;     /* First glyph in class range. */
       
   110   ArrayOf<HBUINT16>     classes;        /* Glyph classes. */
       
   111   public:
       
   112   DEFINE_SIZE_ARRAY (4, classes);
       
   113 };
       
   114 
       
   115 struct KernSubTableFormat2
       
   116 {
       
   117   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
       
   118   {
       
   119     unsigned int l = (this+leftClassTable).get_class (left);
       
   120     unsigned int r = (this+rightClassTable).get_class (right);
       
   121     unsigned int offset = l * rowWidth + r * sizeof (FWORD);
       
   122     const FWORD *arr = &(this+array);
       
   123     if (unlikely ((const void *) arr < (const void *) this || (const void *) arr >= (const void *) end))
       
   124       return 0;
       
   125     const FWORD *v = &StructAtOffset<FWORD> (arr, offset);
       
   126     if (unlikely ((const void *) v < (const void *) arr || (const void *) (v + 1) > (const void *) end))
       
   127       return 0;
       
   128     return *v;
       
   129   }
       
   130 
       
   131   inline bool sanitize (hb_sanitize_context_t *c) const
       
   132   {
       
   133     TRACE_SANITIZE (this);
       
   134     return_trace (rowWidth.sanitize (c) &&
       
   135                   leftClassTable.sanitize (c, this) &&
       
   136                   rightClassTable.sanitize (c, this) &&
       
   137                   array.sanitize (c, this));
       
   138   }
       
   139 
       
   140   protected:
       
   141   HBUINT16      rowWidth;       /* The width, in bytes, of a row in the table. */
       
   142   OffsetTo<KernClassTable>
       
   143                 leftClassTable; /* Offset from beginning of this subtable to
       
   144                                  * left-hand class table. */
       
   145   OffsetTo<KernClassTable>
       
   146                 rightClassTable;/* Offset from beginning of this subtable to
       
   147                                  * right-hand class table. */
       
   148   OffsetTo<FWORD>
       
   149                 array;          /* Offset from beginning of this subtable to
       
   150                                  * the start of the kerning array. */
       
   151   public:
   266   public:
   152   DEFINE_SIZE_MIN (8);
   267   DEFINE_SIZE_MIN (8);
   153 };
   268 };
   154 
   269 
   155 struct KernSubTable
   270 struct kern
   156 {
   271 {
   157   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const
   272   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
   158   {
   273 
   159     switch (format) {
   274   bool has_data () const { return u.version32; }
   160     case 0: return u.format0.get_kerning (left, right);
   275   unsigned int get_type () const { return u.major; }
   161     case 2: return u.format2.get_kerning (left, right, end);
   276 
       
   277   bool has_state_machine () const
       
   278   {
       
   279     switch (get_type ()) {
       
   280     case 0: return u.ot.has_state_machine ();
       
   281     case 1: return u.aat.has_state_machine ();
       
   282     default:return false;
       
   283     }
       
   284   }
       
   285 
       
   286   bool has_cross_stream () const
       
   287   {
       
   288     switch (get_type ()) {
       
   289     case 0: return u.ot.has_cross_stream ();
       
   290     case 1: return u.aat.has_cross_stream ();
       
   291     default:return false;
       
   292     }
       
   293   }
       
   294 
       
   295   int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
       
   296   {
       
   297     switch (get_type ()) {
       
   298     case 0: return u.ot.get_h_kerning (left, right);
       
   299     case 1: return u.aat.get_h_kerning (left, right);
   162     default:return 0;
   300     default:return 0;
   163     }
   301     }
   164   }
   302   }
   165 
   303 
   166   inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
   304   bool apply (AAT::hb_aat_apply_context_t *c) const
   167   {
   305   { return dispatch (c); }
   168     TRACE_SANITIZE (this);
   306 
   169     switch (format) {
   307   template <typename context_t>
   170     case 0: return_trace (u.format0.sanitize (c));
   308   typename context_t::return_t dispatch (context_t *c) const
   171     case 2: return_trace (u.format2.sanitize (c));
   309   {
   172     default:return_trace (true);
   310     unsigned int subtable_type = get_type ();
   173     }
   311     TRACE_DISPATCH (this, subtable_type);
       
   312     switch (subtable_type) {
       
   313     case 0:     return_trace (c->dispatch (u.ot));
       
   314     case 1:     return_trace (c->dispatch (u.aat));
       
   315     default:    return_trace (c->default_return_value ());
       
   316     }
       
   317   }
       
   318 
       
   319   bool sanitize (hb_sanitize_context_t *c) const
       
   320   {
       
   321     TRACE_SANITIZE (this);
       
   322     if (!u.version32.sanitize (c)) return_trace (false);
       
   323     return_trace (dispatch (c));
   174   }
   324   }
   175 
   325 
   176   protected:
   326   protected:
   177   union {
   327   union {
   178   KernSubTableFormat0   format0;
   328   HBUINT32              version32;
   179   KernSubTableFormat2   format2;
       
   180   } u;
       
   181   public:
       
   182   DEFINE_SIZE_MIN (0);
       
   183 };
       
   184 
       
   185 
       
   186 template <typename T>
       
   187 struct KernSubTableWrapper
       
   188 {
       
   189   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
       
   190   inline const T* thiz (void) const { return static_cast<const T *> (this); }
       
   191 
       
   192   inline bool is_horizontal (void) const
       
   193   { return (thiz()->coverage & T::COVERAGE_CHECK_FLAGS) == T::COVERAGE_CHECK_HORIZONTAL; }
       
   194 
       
   195   inline bool is_override (void) const
       
   196   { return bool (thiz()->coverage & T::COVERAGE_OVERRIDE_FLAG); }
       
   197 
       
   198   inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
       
   199   { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); }
       
   200 
       
   201   inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const
       
   202   { return is_horizontal () ? get_kerning (left, right, end) : 0; }
       
   203 
       
   204   inline unsigned int get_size (void) const { return thiz()->length; }
       
   205 
       
   206   inline bool sanitize (hb_sanitize_context_t *c) const
       
   207   {
       
   208     TRACE_SANITIZE (this);
       
   209     return_trace (c->check_struct (thiz()) &&
       
   210                   thiz()->length >= T::min_size &&
       
   211                   c->check_array (thiz(), 1, thiz()->length) &&
       
   212                   thiz()->subtable.sanitize (c, thiz()->format));
       
   213   }
       
   214 };
       
   215 
       
   216 template <typename T>
       
   217 struct KernTable
       
   218 {
       
   219   /* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
       
   220   inline const T* thiz (void) const { return static_cast<const T *> (this); }
       
   221 
       
   222   inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
       
   223   {
       
   224     int v = 0;
       
   225     const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
       
   226     unsigned int count = thiz()->nTables;
       
   227     for (unsigned int i = 0; i < count; i++)
       
   228     {
       
   229       if (st->is_override ())
       
   230         v = 0;
       
   231       v += st->get_h_kerning (left, right, table_length + (const char *) this);
       
   232       st = &StructAfter<typename T::SubTableWrapper> (*st);
       
   233     }
       
   234     return v;
       
   235   }
       
   236 
       
   237   inline bool sanitize (hb_sanitize_context_t *c) const
       
   238   {
       
   239     TRACE_SANITIZE (this);
       
   240     if (unlikely (!c->check_struct (thiz()) ||
       
   241                   thiz()->version != T::VERSION))
       
   242       return_trace (false);
       
   243 
       
   244     const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (thiz()->data);
       
   245     unsigned int count = thiz()->nTables;
       
   246     for (unsigned int i = 0; i < count; i++)
       
   247     {
       
   248       if (unlikely (!st->sanitize (c)))
       
   249         return_trace (false);
       
   250       st = &StructAfter<typename T::SubTableWrapper> (*st);
       
   251     }
       
   252 
       
   253     return_trace (true);
       
   254   }
       
   255 };
       
   256 
       
   257 struct KernOT : KernTable<KernOT>
       
   258 {
       
   259   friend struct KernTable<KernOT>;
       
   260 
       
   261   static const uint16_t VERSION = 0x0000u;
       
   262 
       
   263   struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
       
   264   {
       
   265     friend struct KernSubTableWrapper<SubTableWrapper>;
       
   266 
       
   267     enum coverage_flags_t {
       
   268       COVERAGE_DIRECTION_FLAG   = 0x01u,
       
   269       COVERAGE_MINIMUM_FLAG     = 0x02u,
       
   270       COVERAGE_CROSSSTREAM_FLAG = 0x04u,
       
   271       COVERAGE_OVERRIDE_FLAG    = 0x08u,
       
   272 
       
   273       COVERAGE_VARIATION_FLAG   = 0x00u, /* Not supported. */
       
   274 
       
   275       COVERAGE_CHECK_FLAGS      = 0x07u,
       
   276       COVERAGE_CHECK_HORIZONTAL = 0x01u
       
   277     };
       
   278 
       
   279     protected:
       
   280     HBUINT16    versionZ;       /* Unused. */
       
   281     HBUINT16    length;         /* Length of the subtable (including this header). */
       
   282     HBUINT8     format;         /* Subtable format. */
       
   283     HBUINT8     coverage;       /* Coverage bits. */
       
   284     KernSubTable subtable;      /* Subtable data. */
       
   285     public:
       
   286     DEFINE_SIZE_MIN (6);
       
   287   };
       
   288 
       
   289   protected:
       
   290   HBUINT16      version;        /* Version--0x0000u */
       
   291   HBUINT16      nTables;        /* Number of subtables in the kerning table. */
       
   292   HBUINT8               data[VAR];
       
   293   public:
       
   294   DEFINE_SIZE_ARRAY (4, data);
       
   295 };
       
   296 
       
   297 struct KernAAT : KernTable<KernAAT>
       
   298 {
       
   299   friend struct KernTable<KernAAT>;
       
   300 
       
   301   static const uint32_t VERSION = 0x00010000u;
       
   302 
       
   303   struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
       
   304   {
       
   305     friend struct KernSubTableWrapper<SubTableWrapper>;
       
   306 
       
   307     enum coverage_flags_t {
       
   308       COVERAGE_DIRECTION_FLAG   = 0x80u,
       
   309       COVERAGE_CROSSSTREAM_FLAG = 0x40u,
       
   310       COVERAGE_VARIATION_FLAG   = 0x20u,
       
   311 
       
   312       COVERAGE_OVERRIDE_FLAG    = 0x00u, /* Not supported. */
       
   313 
       
   314       COVERAGE_CHECK_FLAGS      = 0xE0u,
       
   315       COVERAGE_CHECK_HORIZONTAL = 0x00u
       
   316     };
       
   317 
       
   318     protected:
       
   319     HBUINT32    length;         /* Length of the subtable (including this header). */
       
   320     HBUINT8     coverage;       /* Coverage bits. */
       
   321     HBUINT8     format;         /* Subtable format. */
       
   322     HBUINT16    tupleIndex;     /* The tuple index (used for variations fonts).
       
   323                                  * This value specifies which tuple this subtable covers. */
       
   324     KernSubTable subtable;      /* Subtable data. */
       
   325     public:
       
   326     DEFINE_SIZE_MIN (8);
       
   327   };
       
   328 
       
   329   protected:
       
   330   HBUINT32              version;        /* Version--0x00010000u */
       
   331   HBUINT32              nTables;        /* Number of subtables in the kerning table. */
       
   332   HBUINT8               data[VAR];
       
   333   public:
       
   334   DEFINE_SIZE_ARRAY (8, data);
       
   335 };
       
   336 
       
   337 struct kern
       
   338 {
       
   339   static const hb_tag_t tableTag = HB_OT_TAG_kern;
       
   340 
       
   341   inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const
       
   342   {
       
   343     switch (u.major) {
       
   344     case 0: return u.ot.get_h_kerning (left, right, table_length);
       
   345     case 1: return u.aat.get_h_kerning (left, right, table_length);
       
   346     default:return 0;
       
   347     }
       
   348   }
       
   349 
       
   350   inline bool sanitize (hb_sanitize_context_t *c) const
       
   351   {
       
   352     TRACE_SANITIZE (this);
       
   353     if (!u.major.sanitize (c)) return_trace (false);
       
   354     switch (u.major) {
       
   355     case 0: return_trace (u.ot.sanitize (c));
       
   356     case 1: return_trace (u.aat.sanitize (c));
       
   357     default:return_trace (true);
       
   358     }
       
   359   }
       
   360 
       
   361   struct accelerator_t
       
   362   {
       
   363     inline void init (hb_face_t *face)
       
   364     {
       
   365       blob = Sanitizer<kern>().sanitize (face->reference_table (HB_OT_TAG_kern));
       
   366       table = blob->as<kern> ();
       
   367       table_length = blob->length;
       
   368     }
       
   369     inline void fini (void)
       
   370     {
       
   371       hb_blob_destroy (blob);
       
   372     }
       
   373 
       
   374     inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
       
   375     { return table->get_h_kerning (left, right, table_length); }
       
   376 
       
   377     private:
       
   378     hb_blob_t *blob;
       
   379     const kern *table;
       
   380     unsigned int table_length;
       
   381   };
       
   382 
       
   383   protected:
       
   384   union {
       
   385   HBUINT16              major;
   329   HBUINT16              major;
   386   KernOT                ot;
   330   KernOT                ot;
   387   KernAAT               aat;
   331   KernAAT               aat;
   388   } u;
   332   } u;
   389   public:
   333   public:
   390   DEFINE_SIZE_UNION (2, major);
   334   DEFINE_SIZE_UNION (4, version32);
   391 };
   335 };
   392 
   336 
   393 } /* namespace OT */
   337 } /* namespace OT */
   394 
   338 
   395 
   339