Coverage Report

Created: 2023-03-26 14:46

/src/harfbuzz/src/hb-cff-interp-dict-common.hh
Line
Count
Source (jump to first uncovered line)
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
3.41M
  void init () { single_val.set_int (0); }
39
0
  void fini () {}
40
41
  number_t        single_val;
42
};
43
44
typedef dict_val_t num_dict_val_t;
45
46
template <typename VAL> struct dict_values_t : parsed_values_t<VAL> {};
47
48
template <typename OPSTR=op_str_t>
49
struct top_dict_values_t : dict_values_t<OPSTR>
50
{
51
  void init ()
52
1.19M
  {
53
1.19M
    dict_values_t<OPSTR>::init ();
54
1.19M
    charStringsOffset = 0;
55
1.19M
    FDArrayOffset = 0;
56
1.19M
  }
CFF::top_dict_values_t<CFF::cff1_top_dict_val_t>::init()
Line
Count
Source
52
607k
  {
53
607k
    dict_values_t<OPSTR>::init ();
54
607k
    charStringsOffset = 0;
55
607k
    FDArrayOffset = 0;
56
607k
  }
CFF::top_dict_values_t<CFF::op_str_t>::init()
Line
Count
Source
52
586k
  {
53
586k
    dict_values_t<OPSTR>::init ();
54
586k
    charStringsOffset = 0;
55
586k
    FDArrayOffset = 0;
56
586k
  }
57
2.20M
  void fini () { dict_values_t<OPSTR>::fini (); }
CFF::top_dict_values_t<CFF::cff1_top_dict_val_t>::fini()
Line
Count
Source
57
1.12M
  void fini () { dict_values_t<OPSTR>::fini (); }
CFF::top_dict_values_t<CFF::op_str_t>::fini()
Line
Count
Source
57
1.07M
  void fini () { dict_values_t<OPSTR>::fini (); }
58
59
  unsigned int  charStringsOffset;
60
  unsigned int  FDArrayOffset;
61
};
62
63
struct dict_opset_t : opset_t<number_t>
64
{
65
  static void process_op (op_code_t op, interp_env_t<number_t>& env)
66
4.39M
  {
67
4.39M
    switch (op) {
68
189k
      case OpCode_longintdict:  /* 5-byte integer */
69
189k
  env.argStack.push_longint_from_substr (env.str_ref);
70
189k
  break;
71
72
55.3k
      case OpCode_BCD:  /* real number */
73
55.3k
  env.argStack.push_real (parse_bcd (env.str_ref));
74
55.3k
  break;
75
76
4.15M
      default:
77
4.15M
  opset_t<number_t>::process_op (op, env);
78
4.15M
  break;
79
4.39M
    }
80
4.39M
  }
81
82
  /* Turns CFF's BCD format into strtod understandable string */
83
  static double parse_bcd (byte_str_ref_t& str_ref)
84
55.3k
  {
85
55.3k
    if (unlikely (str_ref.in_error ())) return .0;
86
87
55.3k
    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
88
89
55.3k
    char buf[32];
90
55.3k
    unsigned char byte = 0;
91
450k
    for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count)
92
450k
    {
93
450k
      unsigned nibble;
94
450k
      if (!(i & 1))
95
235k
      {
96
235k
  if (unlikely (!str_ref.avail ())) break;
97
98
235k
  byte = str_ref[0];
99
235k
  str_ref.inc ();
100
235k
  nibble = byte >> 4;
101
235k
      }
102
215k
      else
103
215k
  nibble = byte & 0x0F;
104
105
450k
      if (unlikely (nibble == RESERVED)) break;
106
450k
      else if (nibble == END)
107
54.9k
      {
108
54.9k
  const char *p = buf;
109
54.9k
  double pv;
110
54.9k
  if (unlikely (!hb_parse_double (&p, p + count, &pv, true/* whole buffer */)))
111
438
    break;
112
54.5k
  return pv;
113
54.9k
      }
114
395k
      else
115
395k
      {
116
395k
  buf[count] = "0123456789.EE?-?"[nibble];
117
395k
  if (nibble == EXP_NEG)
118
1.75k
  {
119
1.75k
    ++count;
120
1.75k
    if (unlikely (count == ARRAY_LENGTH (buf))) break;
121
1.73k
    buf[count] = '-';
122
1.73k
  }
123
395k
      }
124
450k
    }
125
126
794
    str_ref.set_error ();
127
794
    return .0;
128
55.3k
  }
129
130
  static bool is_hint_op (op_code_t op)
131
0
  {
132
0
    switch (op)
133
0
    {
134
0
      case OpCode_BlueValues:
135
0
      case OpCode_OtherBlues:
136
0
      case OpCode_FamilyBlues:
137
0
      case OpCode_FamilyOtherBlues:
138
0
      case OpCode_StemSnapH:
139
0
      case OpCode_StemSnapV:
140
0
      case OpCode_StdHW:
141
0
      case OpCode_StdVW:
142
0
      case OpCode_BlueScale:
143
0
      case OpCode_BlueShift:
144
0
      case OpCode_BlueFuzz:
145
0
      case OpCode_ForceBold:
146
0
      case OpCode_LanguageGroup:
147
0
      case OpCode_ExpansionFactor:
148
0
  return true;
149
0
      default:
150
0
  return false;
151
0
    }
152
0
  }
153
};
154
155
template <typename VAL=op_str_t>
156
struct top_dict_opset_t : dict_opset_t
157
{
158
  static void process_op (op_code_t op, interp_env_t<number_t>& env, top_dict_values_t<VAL> & dictval)
159
762k
  {
160
762k
    switch (op) {
161
49.8k
      case OpCode_CharStrings:
162
49.8k
  dictval.charStringsOffset = env.argStack.pop_uint ();
163
49.8k
  env.clear_args ();
164
49.8k
  break;
165
23.7k
      case OpCode_FDArray:
166
23.7k
  dictval.FDArrayOffset = env.argStack.pop_uint ();
167
23.7k
  env.clear_args ();
168
23.7k
  break;
169
13.9k
      case OpCode_FontMatrix:
170
13.9k
  env.clear_args ();
171
13.9k
  break;
172
674k
      default:
173
674k
  dict_opset_t::process_op (op, env);
174
674k
  break;
175
762k
    }
176
762k
  }
CFF::top_dict_opset_t<CFF::cff1_top_dict_val_t>::process_op(unsigned int, CFF::interp_env_t<CFF::number_t>&, CFF::top_dict_values_t<CFF::cff1_top_dict_val_t>&)
Line
Count
Source
159
610k
  {
160
610k
    switch (op) {
161
29.3k
      case OpCode_CharStrings:
162
29.3k
  dictval.charStringsOffset = env.argStack.pop_uint ();
163
29.3k
  env.clear_args ();
164
29.3k
  break;
165
3.81k
      case OpCode_FDArray:
166
3.81k
  dictval.FDArrayOffset = env.argStack.pop_uint ();
167
3.81k
  env.clear_args ();
168
3.81k
  break;
169
13.9k
      case OpCode_FontMatrix:
170
13.9k
  env.clear_args ();
171
13.9k
  break;
172
563k
      default:
173
563k
  dict_opset_t::process_op (op, env);
174
563k
  break;
175
610k
    }
176
610k
  }
CFF::top_dict_opset_t<CFF::op_str_t>::process_op(unsigned int, CFF::interp_env_t<CFF::number_t>&, CFF::top_dict_values_t<CFF::op_str_t>&)
Line
Count
Source
159
151k
  {
160
151k
    switch (op) {
161
20.5k
      case OpCode_CharStrings:
162
20.5k
  dictval.charStringsOffset = env.argStack.pop_uint ();
163
20.5k
  env.clear_args ();
164
20.5k
  break;
165
19.9k
      case OpCode_FDArray:
166
19.9k
  dictval.FDArrayOffset = env.argStack.pop_uint ();
167
19.9k
  env.clear_args ();
168
19.9k
  break;
169
0
      case OpCode_FontMatrix:
170
0
  env.clear_args ();
171
0
  break;
172
111k
      default:
173
111k
  dict_opset_t::process_op (op, env);
174
111k
  break;
175
151k
    }
176
151k
  }
177
};
178
179
template <typename OPSET, typename PARAM, typename ENV=num_interp_env_t>
180
struct dict_interpreter_t : interpreter_t<ENV>
181
{
182
1.52M
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff1_top_dict_opset_t, CFF::cff1_top_dict_values_t, CFF::cff1_top_dict_interp_env_t>::dict_interpreter_t(CFF::cff1_top_dict_interp_env_t&)
Line
Count
Source
182
32.6k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff1_font_dict_opset_t, CFF::cff1_font_dict_values_t, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
182
462k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff1_private_dict_opset_t, CFF::cff1_private_dict_values_base_t<CFF::dict_val_t>, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
182
485k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff2_top_dict_opset_t, CFF::cff2_top_dict_values_t, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
182
20.5k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff2_font_dict_opset_t, CFF::cff2_font_dict_values_t, CFF::interp_env_t<CFF::number_t> >::dict_interpreter_t(CFF::interp_env_t<CFF::number_t>&)
Line
Count
Source
182
262k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
CFF::dict_interpreter_t<CFF::cff2_private_dict_opset_t, CFF::cff2_private_dict_values_base_t<CFF::dict_val_t>, CFF::cff2_priv_dict_interp_env_t>::dict_interpreter_t(CFF::cff2_priv_dict_interp_env_t&)
Line
Count
Source
182
261k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
183
184
  bool interpret (PARAM& param)
185
1.52M
  {
186
1.52M
    param.init ();
187
7.42M
    while (SUPER::env.str_ref.avail ())
188
5.90M
    {
189
5.90M
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
5.90M
      if (unlikely (SUPER::env.in_error ()))
191
6.13k
  return false;
192
5.90M
    }
193
194
1.51M
    return true;
195
1.52M
  }
CFF::dict_interpreter_t<CFF::cff1_top_dict_opset_t, CFF::cff1_top_dict_values_t, CFF::cff1_top_dict_interp_env_t>::interpret(CFF::cff1_top_dict_values_t&)
Line
Count
Source
185
32.6k
  {
186
32.6k
    param.init ();
187
914k
    while (SUPER::env.str_ref.avail ())
188
885k
    {
189
885k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
885k
      if (unlikely (SUPER::env.in_error ()))
191
3.16k
  return false;
192
885k
    }
193
194
29.4k
    return true;
195
32.6k
  }
CFF::dict_interpreter_t<CFF::cff1_font_dict_opset_t, CFF::cff1_font_dict_values_t, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff1_font_dict_values_t&)
Line
Count
Source
185
462k
  {
186
462k
    param.init ();
187
1.40M
    while (SUPER::env.str_ref.avail ())
188
943k
    {
189
943k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
943k
      if (unlikely (SUPER::env.in_error ()))
191
284
  return false;
192
943k
    }
193
194
462k
    return true;
195
462k
  }
CFF::dict_interpreter_t<CFF::cff1_private_dict_opset_t, CFF::cff1_private_dict_values_base_t<CFF::dict_val_t>, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff1_private_dict_values_base_t<CFF::dict_val_t>&)
Line
Count
Source
185
485k
  {
186
485k
    param.init ();
187
3.13M
    while (SUPER::env.str_ref.avail ())
188
2.65M
    {
189
2.65M
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
2.65M
      if (unlikely (SUPER::env.in_error ()))
191
693
  return false;
192
2.65M
    }
193
194
484k
    return true;
195
485k
  }
CFF::dict_interpreter_t<CFF::cff2_top_dict_opset_t, CFF::cff2_top_dict_values_t, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff2_top_dict_values_t&)
Line
Count
Source
185
20.5k
  {
186
20.5k
    param.init ();
187
188k
    while (SUPER::env.str_ref.avail ())
188
169k
    {
189
169k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
169k
      if (unlikely (SUPER::env.in_error ()))
191
1.04k
  return false;
192
169k
    }
193
194
19.5k
    return true;
195
20.5k
  }
CFF::dict_interpreter_t<CFF::cff2_font_dict_opset_t, CFF::cff2_font_dict_values_t, CFF::interp_env_t<CFF::number_t> >::interpret(CFF::cff2_font_dict_values_t&)
Line
Count
Source
185
262k
  {
186
262k
    param.init ();
187
762k
    while (SUPER::env.str_ref.avail ())
188
500k
    {
189
500k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
500k
      if (unlikely (SUPER::env.in_error ()))
191
554
  return false;
192
500k
    }
193
194
261k
    return true;
195
262k
  }
CFF::dict_interpreter_t<CFF::cff2_private_dict_opset_t, CFF::cff2_private_dict_values_base_t<CFF::dict_val_t>, CFF::cff2_priv_dict_interp_env_t>::interpret(CFF::cff2_private_dict_values_base_t<CFF::dict_val_t>&)
Line
Count
Source
185
261k
  {
186
261k
    param.init ();
187
1.01M
    while (SUPER::env.str_ref.avail ())
188
753k
    {
189
753k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
753k
      if (unlikely (SUPER::env.in_error ()))
191
386
  return false;
192
753k
    }
193
194
261k
    return true;
195
261k
  }
196
197
  private:
198
  typedef interpreter_t<ENV> SUPER;
199
};
200
201
} /* namespace CFF */
202
203
#endif /* HB_CFF_INTERP_DICT_COMMON_HH */