tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

hb-ot-kern-table.hh (12371B)


      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-common.hh"
     31 #include "hb-aat-layout-kerx-table.hh"
     32 
     33 
     34 /*
     35 * kern -- Kerning
     36 * https://docs.microsoft.com/en-us/typography/opentype/spec/kern
     37 * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6kern.html
     38 */
     39 #define HB_OT_TAG_kern HB_TAG('k','e','r','n')
     40 
     41 
     42 namespace OT {
     43 
     44 
     45 template <typename KernSubTableHeader>
     46 struct KernSubTableFormat3
     47 {
     48  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
     49  {
     50    hb_array_t<const FWORD> kernValue = kernValueZ.as_array (kernValueCount);
     51    hb_array_t<const HBUINT8> leftClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (kernValue).as_array (glyphCount);
     52    hb_array_t<const HBUINT8> rightClass = StructAfter<const UnsizedArrayOf<HBUINT8>> (leftClass).as_array (glyphCount);
     53    hb_array_t<const HBUINT8> kernIndex = StructAfter<const UnsizedArrayOf<HBUINT8>> (rightClass).as_array (leftClassCount * rightClassCount);
     54 
     55    unsigned int leftC = leftClass[left];
     56    unsigned int rightC = rightClass[right];
     57    if (unlikely (leftC >= leftClassCount || rightC >= rightClassCount))
     58      return 0;
     59    unsigned int i = leftC * rightClassCount + rightC;
     60    return kernValue[kernIndex[i]];
     61  }
     62 
     63  bool apply (AAT::hb_aat_apply_context_t *c) const
     64  {
     65    TRACE_APPLY (this);
     66 
     67    if (!c->plan->requested_kerning)
     68      return false;
     69 
     70    if (header.coverage & header.Backwards)
     71      return false;
     72 
     73    hb_kern_machine_t<KernSubTableFormat3> machine (*this, header.coverage & header.CrossStream);
     74    machine.kern (c->font, c->buffer, c->plan->kern_mask);
     75 
     76    return_trace (true);
     77  }
     78 
     79  bool sanitize (hb_sanitize_context_t *c) const
     80  {
     81    TRACE_SANITIZE (this);
     82    return_trace (c->check_struct (this) &&
     83 	  hb_barrier () &&
     84 	  c->check_range (kernValueZ,
     85 			  kernValueCount * sizeof (FWORD) +
     86 			  glyphCount * 2 +
     87 			  leftClassCount * rightClassCount));
     88  }
     89 
     90  template <typename set_t>
     91  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
     92  {
     93    if (likely (glyphCount))
     94    {
     95      left_set.add_range (0, num_glyphs - 1);
     96      right_set.add_range (0, num_glyphs - 1);
     97    }
     98  }
     99 
    100  protected:
    101  KernSubTableHeader
    102 	header;
    103  HBUINT16	glyphCount;	/* The number of glyphs in this font. */
    104  HBUINT8	kernValueCount;	/* The number of kerning values. */
    105  HBUINT8	leftClassCount;	/* The number of left-hand classes. */
    106  HBUINT8	rightClassCount;/* The number of right-hand classes. */
    107  HBUINT8	flags;		/* Set to zero (reserved for future use). */
    108  UnsizedArrayOf<FWORD>
    109 	kernValueZ;	/* The kerning values.
    110 			 * Length kernValueCount. */
    111 #if 0
    112  UnsizedArrayOf<HBUINT8>
    113 	leftClass;	/* The left-hand classes.
    114 			 * Length glyphCount. */
    115  UnsizedArrayOf<HBUINT8>
    116 	rightClass;	/* The right-hand classes.
    117 			 * Length glyphCount. */
    118  UnsizedArrayOf<HBUINT8>kernIndex;
    119 			/* The indices into the kernValue array.
    120 			 * Length leftClassCount * rightClassCount */
    121 #endif
    122  public:
    123  DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
    124 };
    125 
    126 template <typename KernSubTableHeader>
    127 struct KernSubTable
    128 {
    129  unsigned int get_size () const { return u.header.length; }
    130  unsigned int get_type () const { return u.header.format; }
    131 
    132  int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
    133  {
    134    switch (get_type ()) {
    135    /* This method hooks up to hb_font_t's get_h_kerning.  Only support Format0. */
    136    case 0: hb_barrier (); return u.format0.get_kerning (left, right);
    137    default:return 0;
    138    }
    139  }
    140 
    141  template <typename context_t, typename ...Ts>
    142  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
    143  {
    144    unsigned int subtable_type = get_type ();
    145    TRACE_DISPATCH (this, subtable_type);
    146    switch (subtable_type) {
    147    case 0:	return_trace (c->dispatch (u.format0));
    148 #ifndef HB_NO_AAT_SHAPE
    149    case 1:	return_trace (c->dispatch (u.format1, std::forward<Ts> (ds)...));
    150 #endif
    151    case 2:	return_trace (c->dispatch (u.format2));
    152 #ifndef HB_NO_AAT_SHAPE
    153    case 3:	return_trace (c->dispatch (u.format3, std::forward<Ts> (ds)...));
    154 #endif
    155    default:	return_trace (c->default_return_value ());
    156    }
    157  }
    158 
    159  template <typename set_t>
    160  void collect_glyphs (set_t &left_set, set_t &right_set, unsigned num_glyphs) const
    161  {
    162    unsigned int subtable_type = get_type ();
    163    switch (subtable_type) {
    164    case 0:	u.format0.collect_glyphs (left_set, right_set, num_glyphs); return;
    165    case 1:	u.format1.collect_glyphs (left_set, right_set, num_glyphs); return;
    166    case 2:	u.format2.collect_glyphs (left_set, right_set, num_glyphs); return;
    167    case 3:	u.format3.collect_glyphs (left_set, right_set, num_glyphs); return;
    168    default:	return;
    169    }
    170  }
    171 
    172  bool sanitize (hb_sanitize_context_t *c) const
    173  {
    174    TRACE_SANITIZE (this);
    175    if (unlikely (!(u.header.sanitize (c) &&
    176 	    hb_barrier () &&
    177 	    u.header.length >= u.header.min_size &&
    178 	    c->check_range (this, u.header.length)))) return_trace (false);
    179 
    180    return_trace (dispatch (c));
    181  }
    182 
    183  public:
    184  union {
    185  KernSubTableHeader				header;
    186  AAT::KerxSubTableFormat0<KernSubTableHeader>	format0;
    187  AAT::KerxSubTableFormat1<KernSubTableHeader>	format1;
    188  AAT::KerxSubTableFormat2<KernSubTableHeader>	format2;
    189  KernSubTableFormat3<KernSubTableHeader>	format3;
    190  } u;
    191  public:
    192  DEFINE_SIZE_MIN (KernSubTableHeader::static_size);
    193 };
    194 
    195 
    196 struct KernOTSubTableHeader
    197 {
    198  static constexpr bool apple = false;
    199  typedef AAT::ObsoleteTypes Types;
    200 
    201  unsigned   tuple_count () const { return 0; }
    202  bool     is_horizontal () const { return (coverage & Horizontal); }
    203 
    204  enum Coverage
    205  {
    206    Horizontal	= 0x01u,
    207    Minimum	= 0x02u,
    208    CrossStream	= 0x04u,
    209    Override	= 0x08u,
    210 
    211    /* Not supported: */
    212    Backwards	= 0x00u,
    213    Variation	= 0x00u,
    214  };
    215 
    216  bool sanitize (hb_sanitize_context_t *c) const
    217  {
    218    TRACE_SANITIZE (this);
    219    return_trace (c->check_struct (this));
    220  }
    221 
    222  public:
    223  HBUINT16	versionZ;	/* Unused. */
    224  HBUINT16	length;		/* Length of the subtable (including this header). */
    225  HBUINT8	format;		/* Subtable format. */
    226  HBUINT8	coverage;	/* Coverage bits. */
    227  public:
    228  DEFINE_SIZE_STATIC (6);
    229 };
    230 
    231 struct KernOT : AAT::KerxTable<KernOT>
    232 {
    233  friend struct AAT::KerxTable<KernOT>;
    234 
    235  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
    236  static constexpr unsigned minVersion = 0u;
    237 
    238  typedef KernOTSubTableHeader SubTableHeader;
    239  typedef SubTableHeader::Types Types;
    240  typedef KernSubTable<SubTableHeader> SubTable;
    241 
    242  protected:
    243  HBUINT16	version;	/* Version--0x0000u */
    244  HBUINT16	tableCount;	/* Number of subtables in the kerning table. */
    245  SubTable	firstSubTable;	/* Subtables. */
    246  public:
    247  DEFINE_SIZE_MIN (4);
    248 };
    249 
    250 
    251 struct KernAATSubTableHeader
    252 {
    253  static constexpr bool apple = true;
    254  typedef AAT::ObsoleteTypes Types;
    255 
    256  unsigned   tuple_count () const { return 0; }
    257  bool     is_horizontal () const { return !(coverage & Vertical); }
    258 
    259  enum Coverage
    260  {
    261    Vertical	= 0x80u,
    262    CrossStream	= 0x40u,
    263    Variation	= 0x20u,
    264 
    265    /* Not supported: */
    266    Backwards	= 0x00u,
    267  };
    268 
    269  bool sanitize (hb_sanitize_context_t *c) const
    270  {
    271    TRACE_SANITIZE (this);
    272    return_trace (c->check_struct (this));
    273  }
    274 
    275  public:
    276  HBUINT32	length;		/* Length of the subtable (including this header). */
    277  HBUINT8	coverage;	/* Coverage bits. */
    278  HBUINT8	format;		/* Subtable format. */
    279  HBUINT16	tupleIndex;	/* The tuple index (used for variations fonts).
    280 			 * This value specifies which tuple this subtable covers.
    281 			 * Note: We don't implement. */
    282  public:
    283  DEFINE_SIZE_STATIC (8);
    284 };
    285 
    286 struct KernAAT : AAT::KerxTable<KernAAT>
    287 {
    288  friend struct AAT::KerxTable<KernAAT>;
    289 
    290  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
    291  static constexpr unsigned minVersion = 0x00010000u;
    292 
    293  typedef KernAATSubTableHeader SubTableHeader;
    294  typedef SubTableHeader::Types Types;
    295  typedef KernSubTable<SubTableHeader> SubTable;
    296 
    297  protected:
    298  HBUINT32	version;	/* Version--0x00010000u */
    299  HBUINT32	tableCount;	/* Number of subtables in the kerning table. */
    300  SubTable	firstSubTable;	/* Subtables. */
    301  public:
    302  DEFINE_SIZE_MIN (8);
    303 };
    304 
    305 struct kern
    306 {
    307  static constexpr hb_tag_t tableTag = HB_OT_TAG_kern;
    308 
    309  bool     has_data () const { return u.version32.v; }
    310  unsigned get_type () const { return u.major.v; }
    311 
    312  bool has_state_machine () const
    313  {
    314    switch (get_type ()) {
    315    case 0: hb_barrier (); return u.ot.has_state_machine ();
    316 #ifndef HB_NO_AAT_SHAPE
    317    case 1: hb_barrier (); return u.aat.has_state_machine ();
    318 #endif
    319    default:return false;
    320    }
    321  }
    322 
    323  bool has_cross_stream () const
    324  {
    325    switch (get_type ()) {
    326    case 0: hb_barrier (); return u.ot.has_cross_stream ();
    327 #ifndef HB_NO_AAT_SHAPE
    328    case 1: hb_barrier (); return u.aat.has_cross_stream ();
    329 #endif
    330    default:return false;
    331    }
    332  }
    333 
    334  int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
    335  {
    336    switch (get_type ()) {
    337    case 0: hb_barrier (); return u.ot.get_h_kerning (left, right);
    338 #ifndef HB_NO_AAT_SHAPE
    339    case 1: hb_barrier (); return u.aat.get_h_kerning (left, right);
    340 #endif
    341    default:return 0;
    342    }
    343  }
    344 
    345  bool apply (AAT::hb_aat_apply_context_t *c,
    346       const AAT::kern_accelerator_data_t &accel_data) const
    347  { return dispatch (c, accel_data); }
    348 
    349  template <typename context_t, typename ...Ts>
    350  typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
    351  {
    352    unsigned int subtable_type = get_type ();
    353    TRACE_DISPATCH (this, subtable_type);
    354    switch (subtable_type) {
    355    case 0:	return_trace (c->dispatch (u.ot, std::forward<Ts> (ds)...));
    356 #ifndef HB_NO_AAT_SHAPE
    357    case 1:	return_trace (c->dispatch (u.aat, std::forward<Ts> (ds)...));
    358 #endif
    359    default:	return_trace (c->default_return_value ());
    360    }
    361  }
    362 
    363  bool sanitize (hb_sanitize_context_t *c) const
    364  {
    365    TRACE_SANITIZE (this);
    366    if (!u.version32.v.sanitize (c)) return_trace (false);
    367    hb_barrier ();
    368    return_trace (dispatch (c));
    369  }
    370 
    371  AAT::kern_accelerator_data_t create_accelerator_data (unsigned num_glyphs) const
    372  {
    373    switch (get_type ()) {
    374    case 0: hb_barrier (); return u.ot.create_accelerator_data (num_glyphs);
    375 #ifndef HB_NO_AAT_SHAPE
    376    case 1: hb_barrier (); return u.aat.create_accelerator_data (num_glyphs);
    377 #endif
    378    default:return AAT::kern_accelerator_data_t ();
    379    }
    380  }
    381 
    382  struct accelerator_t
    383  {
    384    accelerator_t (hb_face_t *face)
    385    {
    386      hb_sanitize_context_t sc;
    387      this->table = sc.reference_table<kern> (face);
    388      this->accel_data = this->table->create_accelerator_data (face->get_num_glyphs ());
    389    }
    390    ~accelerator_t ()
    391    {
    392      this->table.destroy ();
    393    }
    394 
    395    hb_blob_t *get_blob () const { return table.get_blob (); }
    396 
    397    bool apply (AAT::hb_aat_apply_context_t *c) const
    398    {
    399      return table->apply (c, accel_data);
    400    }
    401 
    402    hb_blob_ptr_t<kern> table;
    403    AAT::kern_accelerator_data_t accel_data;
    404    AAT::hb_aat_scratch_t scratch;
    405  };
    406 
    407  protected:
    408  union {
    409  struct { HBUINT32 v; }	version32;
    410  struct { HBUINT16 v; }	major;
    411  KernOT		ot;
    412 #ifndef HB_NO_AAT_SHAPE
    413  KernAAT		aat;
    414 #endif
    415  } u;
    416  public:
    417  DEFINE_SIZE_UNION (4, version32.v);
    418 };
    419 
    420 struct kern_accelerator_t : kern::accelerator_t {
    421  kern_accelerator_t (hb_face_t *face) : kern::accelerator_t (face) {}
    422 };
    423 
    424 } /* namespace OT */
    425 
    426 
    427 #endif /* HB_OT_KERN_TABLE_HH */