tor-browser

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

hb-cff-interp-dict-common.hh (4900B)


      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_CFF_INTERP_DICT_COMMON_HH
     27 #define HB_CFF_INTERP_DICT_COMMON_HH
     28 
     29 #include "hb-cff-interp-common.hh"
     30 
     31 namespace CFF {
     32 
     33 using namespace OT;
     34 
     35 /* an opstr and the parsed out dict value(s) */
     36 struct dict_val_t : op_str_t
     37 {
     38  void init () {}
     39  void fini () {}
     40 };
     41 
     42 typedef dict_val_t num_dict_val_t;
     43 
     44 template <typename VAL> struct dict_values_t : parsed_values_t<VAL> {};
     45 
     46 template <typename OPSTR=op_str_t>
     47 struct top_dict_values_t : dict_values_t<OPSTR>
     48 {
     49  void init ()
     50  {
     51    dict_values_t<OPSTR>::init ();
     52    charStringsOffset = 0;
     53    FDArrayOffset = 0;
     54  }
     55  void fini () { dict_values_t<OPSTR>::fini (); }
     56 
     57  int  charStringsOffset;
     58  int  FDArrayOffset;
     59 };
     60 
     61 struct dict_opset_t : opset_t<number_t>
     62 {
     63  static void process_op (op_code_t op, interp_env_t<number_t>& env)
     64  {
     65    switch (op) {
     66      case OpCode_longintdict:  /* 5-byte integer */
     67 env.argStack.push_longint_from_substr (env.str_ref);
     68 break;
     69 
     70      case OpCode_BCD:  /* real number */
     71 env.argStack.push_real (parse_bcd (env.str_ref));
     72 break;
     73 
     74      default:
     75 opset_t<number_t>::process_op (op, env);
     76 break;
     77    }
     78  }
     79 
     80  /* Turns CFF's BCD format into strtod understandable string */
     81  static double parse_bcd (byte_str_ref_t& str_ref)
     82  {
     83    if (unlikely (str_ref.in_error ())) return .0;
     84 
     85    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
     86 
     87    char buf[32] = {0};
     88    unsigned char byte = 0;
     89    for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count)
     90    {
     91      unsigned nibble;
     92      if (!(i & 1))
     93      {
     94 if (unlikely (!str_ref.avail ())) break;
     95 
     96 byte = str_ref[0];
     97 str_ref.inc ();
     98 nibble = byte >> 4;
     99      }
    100      else
    101 nibble = byte & 0x0F;
    102 
    103      if (unlikely (nibble == RESERVED)) break;
    104      else if (nibble == END)
    105      {
    106 const char *p = buf;
    107 double pv;
    108 if (unlikely (!hb_parse_double (&p, p + count, &pv, true/* whole buffer */)))
    109   break;
    110 return pv;
    111      }
    112      else
    113      {
    114 buf[count] = "0123456789.EE?-?"[nibble];
    115 if (nibble == EXP_NEG)
    116 {
    117   ++count;
    118   if (unlikely (count == ARRAY_LENGTH (buf))) break;
    119   buf[count] = '-';
    120 }
    121      }
    122    }
    123 
    124    str_ref.set_error ();
    125    return .0;
    126  }
    127 
    128  static bool is_hint_op (op_code_t op)
    129  {
    130    switch (op)
    131    {
    132      case OpCode_BlueValues:
    133      case OpCode_OtherBlues:
    134      case OpCode_FamilyBlues:
    135      case OpCode_FamilyOtherBlues:
    136      case OpCode_StemSnapH:
    137      case OpCode_StemSnapV:
    138      case OpCode_StdHW:
    139      case OpCode_StdVW:
    140      case OpCode_BlueScale:
    141      case OpCode_BlueShift:
    142      case OpCode_BlueFuzz:
    143      case OpCode_ForceBold:
    144      case OpCode_LanguageGroup:
    145      case OpCode_ExpansionFactor:
    146 return true;
    147      default:
    148 return false;
    149    }
    150  }
    151 };
    152 
    153 template <typename VAL=op_str_t>
    154 struct top_dict_opset_t : dict_opset_t
    155 {
    156  static void process_op (op_code_t op, interp_env_t<number_t>& env, top_dict_values_t<VAL> & dictval)
    157  {
    158    switch (op) {
    159      case OpCode_CharStrings:
    160 dictval.charStringsOffset = env.argStack.pop_int ();
    161 env.clear_args ();
    162 break;
    163      case OpCode_FDArray:
    164 dictval.FDArrayOffset = env.argStack.pop_int ();
    165 env.clear_args ();
    166 break;
    167      case OpCode_FontMatrix:
    168 env.clear_args ();
    169 break;
    170      default:
    171 dict_opset_t::process_op (op, env);
    172 break;
    173    }
    174  }
    175 };
    176 
    177 template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
    178 struct dict_interpreter_t : interpreter_t<ENV>
    179 {
    180  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
    181 
    182  bool interpret (PARAM& param)
    183  {
    184    param.init ();
    185    while (SUPER::env.str_ref.avail ())
    186    {
    187      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
    188      if (unlikely (SUPER::env.in_error ()))
    189 return false;
    190    }
    191 
    192    return true;
    193  }
    194 
    195  private:
    196  typedef interpreter_t<ENV> SUPER;
    197 };
    198 
    199 } /* namespace CFF */
    200 
    201 #endif /* HB_CFF_INTERP_DICT_COMMON_HH */