tor-browser

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

hb-ot-cff-common.hh (11038B)


      1 /*
      2 * Copyright © 2018 Adobe 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 * Adobe Author(s): Michiharu Ariza
     25 */
     26 #ifndef HB_OT_CFF_COMMON_HH
     27 #define HB_OT_CFF_COMMON_HH
     28 
     29 #include "hb-open-type.hh"
     30 #include "hb-bimap.hh"
     31 #include "hb-ot-layout-common.hh"
     32 #include "hb-cff-interp-dict-common.hh"
     33 #include "hb-subset-plan.hh"
     34 
     35 namespace CFF {
     36 
     37 using namespace OT;
     38 
     39 #define CFF_UNDEF_CODE  0xFFFFFFFF
     40 
     41 using objidx_t = hb_serialize_context_t::objidx_t;
     42 using whence_t = hb_serialize_context_t::whence_t;
     43 
     44 /* CFF offsets can technically be negative */
     45 template<typename Type, typename ...Ts>
     46 static inline const Type& StructAtOffsetOrNull (const void *P, int offset, hb_sanitize_context_t &sc, Ts&&... ds)
     47 {
     48  if (!offset) return Null (Type);
     49 
     50  const char *p = (const char *) P + offset;
     51  if (!sc.check_point (p)) return Null (Type);
     52 
     53  const Type &obj = *reinterpret_cast<const Type *> (p);
     54  if (!obj.sanitize (&sc, std::forward<Ts> (ds)...)) return Null (Type);
     55 
     56  return obj;
     57 }
     58 
     59 
     60 struct code_pair_t
     61 {
     62  unsigned code;
     63  hb_codepoint_t glyph;
     64 };
     65 
     66 
     67 using str_buff_t = hb_vector_t<unsigned char>;
     68 using str_buff_vec_t = hb_vector_t<str_buff_t>;
     69 using glyph_to_sid_map_t = hb_vector_t<code_pair_t>;
     70 
     71 /* Top Dict, Font Dict, Private Dict */
     72 struct Dict : UnsizedByteStr
     73 {
     74  template <typename DICTVAL, typename OP_SERIALIZER, typename ...Ts>
     75  bool serialize (hb_serialize_context_t *c,
     76 	  const DICTVAL &dictval,
     77 	  OP_SERIALIZER& opszr,
     78 	  Ts&&... ds)
     79  {
     80    TRACE_SERIALIZE (this);
     81    for (unsigned int i = 0; i < dictval.get_count (); i++)
     82      if (unlikely (!opszr.serialize (c, dictval[i], ds...)))
     83 return_trace (false);
     84 
     85    return_trace (true);
     86  }
     87 
     88  template <typename T, typename V>
     89  static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp)
     90  {
     91    if (unlikely ((!serialize_int<T, V> (c, intOp, value))))
     92      return false;
     93 
     94    TRACE_SERIALIZE (this);
     95    /* serialize the opcode */
     96    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op), false);
     97    if (unlikely (!p)) return_trace (false);
     98    if (Is_OpCode_ESC (op))
     99    {
    100      *p = OpCode_escape;
    101      op = Unmake_OpCode_ESC (op);
    102      p++;
    103    }
    104    *p = op;
    105    return_trace (true);
    106  }
    107 
    108  template <typename V>
    109  static bool serialize_int4_op (hb_serialize_context_t *c, op_code_t op, V value)
    110  { return serialize_int_op<HBINT32> (c, op, value, OpCode_longintdict); }
    111 
    112  template <typename V>
    113  static bool serialize_int2_op (hb_serialize_context_t *c, op_code_t op, V value)
    114  { return serialize_int_op<HBINT16> (c, op, value, OpCode_shortint); }
    115 
    116  template <typename T, int int_op>
    117  static bool serialize_link_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence)
    118  {
    119    T &ofs = *(T *) (c->head + OpCode_Size (int_op));
    120    if (unlikely (!serialize_int_op<T> (c, op, 0, int_op))) return false;
    121    c->add_link (ofs, link, whence);
    122    return true;
    123  }
    124 
    125  static bool serialize_link4_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head)
    126  { return serialize_link_op<HBINT32, OpCode_longintdict> (c, op, link, whence); }
    127 
    128  static bool serialize_link2_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head)
    129  { return serialize_link_op<HBINT16, OpCode_shortint> (c, op, link, whence); }
    130 };
    131 
    132 struct TopDict : Dict {};
    133 struct FontDict : Dict {};
    134 struct PrivateDict : Dict {};
    135 
    136 struct table_info_t
    137 {
    138  void init () { offset = size = 0; link = 0; }
    139 
    140  unsigned int    offset;
    141  unsigned int    size;
    142  objidx_t	  link;
    143 };
    144 
    145 template <typename COUNT>
    146 struct FDArray : CFFIndex<COUNT>
    147 {
    148  template <typename DICTVAL, typename INFO, typename Iterator, typename OP_SERIALIZER>
    149  bool serialize (hb_serialize_context_t *c,
    150 	  Iterator it,
    151 	  OP_SERIALIZER& opszr)
    152  {
    153    TRACE_SERIALIZE (this);
    154 
    155    /* serialize INDEX data */
    156    hb_vector_t<unsigned> sizes;
    157    if (it.is_random_access_iterator)
    158      sizes.alloc (hb_len (it));
    159 
    160    c->push ();
    161    char *data_base = c->head;
    162    + it
    163    | hb_map ([&] (const hb_pair_t<const DICTVAL&, const INFO&> &_)
    164    {
    165      FontDict *dict = c->start_embed<FontDict> ();
    166 	dict->serialize (c, _.first, opszr, _.second);
    167 	return c->head - (const char*)dict;
    168       })
    169    | hb_sink (sizes)
    170    ;
    171    unsigned data_size = c->head - data_base;
    172    c->pop_pack (false);
    173 
    174    if (unlikely (sizes.in_error ())) return_trace (false);
    175 
    176    /* It just happens that the above is packed right after the header below.
    177     * Such a hack. */
    178 
    179    /* serialize INDEX header */
    180    return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes), data_size));
    181  }
    182 };
    183 
    184 /* FDSelect */
    185 struct FDSelect0 {
    186  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
    187  {
    188    TRACE_SANITIZE (this);
    189    if (unlikely (!(c->check_struct (this))))
    190      return_trace (false);
    191    hb_barrier ();
    192    if (unlikely (!c->check_array (fds, c->get_num_glyphs ())))
    193      return_trace (false);
    194 
    195    return_trace (true);
    196  }
    197 
    198  unsigned get_fd (hb_codepoint_t glyph) const
    199  { return fds[glyph]; }
    200 
    201  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
    202  { return {fds[glyph], glyph + 1}; }
    203 
    204  unsigned int get_size (unsigned int num_glyphs) const
    205  { return HBUINT8::static_size * num_glyphs; }
    206 
    207  HBUINT8     fds[HB_VAR_ARRAY];
    208 
    209  DEFINE_SIZE_MIN (0);
    210 };
    211 
    212 template <typename GID_TYPE, typename FD_TYPE>
    213 struct FDSelect3_4_Range
    214 {
    215  bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
    216  {
    217    TRACE_SANITIZE (this);
    218    return_trace (c->check_struct (this) &&
    219 	  hb_barrier () &&
    220 	  first < c->get_num_glyphs () && (fd < fdcount));
    221  }
    222 
    223  GID_TYPE    first;
    224  FD_TYPE     fd;
    225  public:
    226  DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
    227 };
    228 
    229 template <typename GID_TYPE, typename FD_TYPE>
    230 struct FDSelect3_4
    231 {
    232  unsigned int get_size () const
    233  { return GID_TYPE::static_size * 2 + ranges.get_size (); }
    234 
    235  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
    236  {
    237    TRACE_SANITIZE (this);
    238    if (unlikely (!(c->check_struct (this) &&
    239 	    ranges.sanitize (c, nullptr, fdcount) &&
    240 	    hb_barrier () &&
    241 	    (nRanges () != 0) &&
    242 	    ranges[0].first == 0)))
    243      return_trace (false);
    244 
    245    for (unsigned int i = 1; i < nRanges (); i++)
    246      if (unlikely (ranges[i - 1].first >= ranges[i].first))
    247 return_trace (false);
    248 
    249    if (unlikely (!(sentinel().sanitize (c) &&
    250 	   hb_barrier () &&
    251 	   (sentinel() == c->get_num_glyphs ()))))
    252      return_trace (false);
    253 
    254    return_trace (true);
    255  }
    256 
    257  static int _cmp_range (const void *_key, const void *_item)
    258  {
    259    hb_codepoint_t glyph = * (hb_codepoint_t *) _key;
    260    FDSelect3_4_Range<GID_TYPE, FD_TYPE> *range = (FDSelect3_4_Range<GID_TYPE, FD_TYPE> *) _item;
    261 
    262    if (glyph < range[0].first) return -1;
    263    if (glyph < range[1].first) return 0;
    264    return +1;
    265  }
    266 
    267  unsigned get_fd (hb_codepoint_t glyph) const
    268  {
    269    auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
    270    return range ? range->fd : ranges[nRanges () - 1].fd;
    271  }
    272 
    273  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
    274  {
    275    auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
    276    unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd;
    277    hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first;
    278    return {fd, end};
    279  }
    280 
    281  GID_TYPE        &nRanges ()       { return ranges.len; }
    282  GID_TYPE         nRanges () const { return ranges.len; }
    283  GID_TYPE       &sentinel ()       { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
    284  const GID_TYPE &sentinel () const { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
    285 
    286  ArrayOf<FDSelect3_4_Range<GID_TYPE, FD_TYPE>, GID_TYPE> ranges;
    287  /* GID_TYPE sentinel */
    288 
    289  DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges);
    290 };
    291 
    292 typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
    293 typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
    294 
    295 struct FDSelect
    296 {
    297  bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
    298  {
    299    TRACE_SERIALIZE (this);
    300    unsigned int size = src.get_size (num_glyphs);
    301    FDSelect *dest = c->allocate_size<FDSelect> (size, false);
    302    if (unlikely (!dest)) return_trace (false);
    303    hb_memcpy (dest, &src, size);
    304    return_trace (true);
    305  }
    306 
    307  unsigned int get_size (unsigned int num_glyphs) const
    308  {
    309    switch (format)
    310    {
    311    case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs);
    312    case 3: hb_barrier (); return format.static_size + u.format3.get_size ();
    313    default:return 0;
    314    }
    315  }
    316 
    317  unsigned get_fd (hb_codepoint_t glyph) const
    318  {
    319    if (this == &Null (FDSelect)) return 0;
    320 
    321    switch (format)
    322    {
    323    case 0: hb_barrier (); return u.format0.get_fd (glyph);
    324    case 3: hb_barrier (); return u.format3.get_fd (glyph);
    325    default:return 0;
    326    }
    327  }
    328  /* Returns pair of fd and one after last glyph in range. */
    329  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
    330  {
    331    if (this == &Null (FDSelect)) return {0, 1};
    332 
    333    switch (format)
    334    {
    335    case 0: hb_barrier (); return u.format0.get_fd_range (glyph);
    336    case 3: hb_barrier (); return u.format3.get_fd_range (glyph);
    337    default:return {0, 1};
    338    }
    339  }
    340 
    341  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
    342  {
    343    TRACE_SANITIZE (this);
    344    if (unlikely (!c->check_struct (this)))
    345      return_trace (false);
    346    hb_barrier ();
    347 
    348    switch (format)
    349    {
    350    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount));
    351    case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount));
    352    default:return_trace (false);
    353    }
    354  }
    355 
    356  HBUINT8	format;
    357  union {
    358  FDSelect0	format0;
    359  FDSelect3	format3;
    360  } u;
    361  public:
    362  DEFINE_SIZE_MIN (1);
    363 };
    364 
    365 template <typename COUNT>
    366 struct Subrs : CFFIndex<COUNT>
    367 {
    368  typedef COUNT count_type;
    369  typedef CFFIndex<COUNT> SUPER;
    370 };
    371 
    372 } /* namespace CFF */
    373 
    374 #endif /* HB_OT_CFF_COMMON_HH */