1 /*
   2  * Copyright © 2017  Google, Inc.
   3  *
   4  *  This is part of HarfBuzz, a text shaping library.
   5  *
   6  * Permission is hereby granted, without written agreement and without
   7  * license or royalty fees, to use, copy, modify, and distribute this
   8  * software and its documentation for any purpose, provided that the
   9  * above copyright notice and the following two paragraphs appear in
  10  * all copies of this software.
  11  *
  12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
  13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
  14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
  15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
  16  * DAMAGE.
  17  *
  18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
  19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
  21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  23  *
  24  * Google Author(s): Behdad Esfahbod
  25  */
  26 
  27 #ifndef HB_OT_KERN_TABLE_HH
  28 #define HB_OT_KERN_TABLE_HH
  29 
  30 #include "hb-aat-layout-kerx-table.hh"
  31 
  32 
  33 /*
  34  * kern -- Kerning
  35  * https://docs.microsoft.com/en-us/typography/opentype/spec/kern
  36  * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
  37  */
  38 #define HB_OT_TAG_kern HB_TAG('k','e','r','n')
  39 
  40 
  41 namespace OT {
  42 
  43 
  44 template <typename KernSubTableHeader>
  45 struct KernSubTableFormat3
  46 {
  47   int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
  48   {
  49     hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
  50     hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (kernValue).as_array (glyphCount);
  51     hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8> > (leftClass).as_array (glyphCount);
  52     hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8> > (rightClass).as_array (leftClassCount * rightClassCount);
  53 
  54     unsigned int leftC = leftClass[left];
  55     unsigned int rightC = rightClass[right];
  56     if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
  57       return 0;
  58     unsigned int i = leftC * rightClassCount + rightC;
  59     return kernValue[kernIndex[i]];
  60   }
  61 
  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
 182   {
 183     TRACE_SANITIZE (this);
 184     return_trace (c->check_struct (this));
 185   }
 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 
 207   protected:
 208   HBUINT16      version;        /* Version--0x0000u */
 209   HBUINT16      tableCount;     /* Number of subtables in the kerning table. */
 210   SubTable      firstSubTable;  /* Subtables. */
 211   public:
 212   DEFINE_SIZE_MIN (4);
 213 };
 214 
 215 
 216 struct KernAATSubTableHeader
 217 {
 218   static constexpr bool apple = true;
 219   typedef AAT::ObsoleteTypes Types;
 220 
 221   unsigned int tuple_count () const { return 0; }
 222   bool is_horizontal () const       { return !(coverage & Vertical); }
 223 
 224   enum Coverage
 225   {
 226     Vertical    = 0x80u,
 227     CrossStream = 0x40u,
 228     Variation   = 0x20u,
 229 
 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;
 261 
 262   protected:
 263   HBUINT32      version;        /* Version--0x00010000u */
 264   HBUINT32      tableCount;     /* Number of subtables in the kerning table. */
 265   SubTable      firstSubTable;  /* Subtables. */
 266   public:
 267   DEFINE_SIZE_MIN (8);
 268 };
 269 
 270 struct kern
 271 {
 272   static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
 273 
 274   bool has_data () const { return u.version32; }
 275   unsigned int get_type () const { return u.major; }
 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);
 300     default:return 0;
 301     }
 302   }
 303 
 304   bool apply (AAT::hb_aat_apply_context_t *c) const
 305   { return dispatch (c); }
 306 
 307   template <typename context_t>
 308   typename context_t::return_t dispatch (context_t *c) const
 309   {
 310     unsigned int subtable_type = get_type ();
 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));
 324   }
 325 
 326   protected:
 327   union {
 328   HBUINT32              version32;
 329   HBUINT16              major;
 330   KernOT                ot;
 331   KernAAT               aat;
 332   } u;
 333   public:
 334   DEFINE_SIZE_UNION (4, version32);
 335 };
 336 
 337 } /* namespace OT */
 338 
 339 
 340 #endif /* HB_OT_KERN_TABLE_HH */