Coverage Report

Created: 2024-06-09 06:54

/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.12M
  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
996k
  {
53
996k
    dict_values_t<OPSTR>::init ();
54
996k
    charStringsOffset = 0;
55
996k
    FDArrayOffset = 0;
56
996k
  }
CFF::top_dict_values_t<CFF::cff1_top_dict_val_t>::init()
Line
Count
Source
52
508k
  {
53
508k
    dict_values_t<OPSTR>::init ();
54
508k
    charStringsOffset = 0;
55
508k
    FDArrayOffset = 0;
56
508k
  }
CFF::top_dict_values_t<CFF::op_str_t>::init()
Line
Count
Source
52
488k
  {
53
488k
    dict_values_t<OPSTR>::init ();
54
488k
    charStringsOffset = 0;
55
488k
    FDArrayOffset = 0;
56
488k
  }
57
1.73M
  void fini () { dict_values_t<OPSTR>::fini (); }
CFF::top_dict_values_t<CFF::cff1_top_dict_val_t>::fini()
Line
Count
Source
57
904k
  void fini () { dict_values_t<OPSTR>::fini (); }
CFF::top_dict_values_t<CFF::op_str_t>::fini()
Line
Count
Source
57
829k
  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.61M
  {
67
4.61M
    switch (op) {
68
216k
      case OpCode_longintdict:  /* 5-byte integer */
69
216k
  env.argStack.push_longint_from_substr (env.str_ref);
70
216k
  break;
71
72
77.8k
      case OpCode_BCD:  /* real number */
73
77.8k
  env.argStack.push_real (parse_bcd (env.str_ref));
74
77.8k
  break;
75
76
4.32M
      default:
77
4.32M
  opset_t<number_t>::process_op (op, env);
78
4.32M
  break;
79
4.61M
    }
80
4.61M
  }
81
82
  /* Turns CFF's BCD format into strtod understandable string */
83
  static double parse_bcd (byte_str_ref_t& str_ref)
84
77.8k
  {
85
77.8k
    if (unlikely (str_ref.in_error ())) return .0;
86
87
77.8k
    enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END };
88
89
77.8k
    char buf[32];
90
77.8k
    unsigned char byte = 0;
91
620k
    for (unsigned i = 0, count = 0; count < ARRAY_LENGTH (buf); ++i, ++count)
92
620k
    {
93
620k
      unsigned nibble;
94
620k
      if (!(i & 1))
95
328k
      {
96
328k
  if (unlikely (!str_ref.avail ())) break;
97
98
328k
  byte = str_ref[0];
99
328k
  str_ref.inc ();
100
328k
  nibble = byte >> 4;
101
328k
      }
102
291k
      else
103
291k
  nibble = byte & 0x0F;
104
105
620k
      if (unlikely (nibble == RESERVED)) break;
106
620k
      else if (nibble == END)
107
77.4k
      {
108
77.4k
  const char *p = buf;
109
77.4k
  double pv;
110
77.4k
  if (unlikely (!hb_parse_double (&p, p + count, &pv, true/* whole buffer */)))
111
501
    break;
112
76.9k
  return pv;
113
77.4k
      }
114
542k
      else
115
542k
      {
116
542k
  buf[count] = "0123456789.EE?-?"[nibble];
117
542k
  if (nibble == EXP_NEG)
118
3.14k
  {
119
3.14k
    ++count;
120
3.14k
    if (unlikely (count == ARRAY_LENGTH (buf))) break;
121
3.12k
    buf[count] = '-';
122
3.12k
  }
123
542k
      }
124
620k
    }
125
126
963
    str_ref.set_error ();
127
963
    return .0;
128
77.8k
  }
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
1.01M
  {
160
1.01M
    switch (op) {
161
68.1k
      case OpCode_CharStrings:
162
68.1k
  dictval.charStringsOffset = env.argStack.pop_uint ();
163
68.1k
  env.clear_args ();
164
68.1k
  break;
165
34.0k
      case OpCode_FDArray:
166
34.0k
  dictval.FDArrayOffset = env.argStack.pop_uint ();
167
34.0k
  env.clear_args ();
168
34.0k
  break;
169
19.1k
      case OpCode_FontMatrix:
170
19.1k
  env.clear_args ();
171
19.1k
  break;
172
897k
      default:
173
897k
  dict_opset_t::process_op (op, env);
174
897k
  break;
175
1.01M
    }
176
1.01M
  }
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
795k
  {
160
795k
    switch (op) {
161
37.2k
      case OpCode_CharStrings:
162
37.2k
  dictval.charStringsOffset = env.argStack.pop_uint ();
163
37.2k
  env.clear_args ();
164
37.2k
  break;
165
3.65k
      case OpCode_FDArray:
166
3.65k
  dictval.FDArrayOffset = env.argStack.pop_uint ();
167
3.65k
  env.clear_args ();
168
3.65k
  break;
169
19.1k
      case OpCode_FontMatrix:
170
19.1k
  env.clear_args ();
171
19.1k
  break;
172
735k
      default:
173
735k
  dict_opset_t::process_op (op, env);
174
735k
  break;
175
795k
    }
176
795k
  }
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
222k
  {
160
222k
    switch (op) {
161
30.9k
      case OpCode_CharStrings:
162
30.9k
  dictval.charStringsOffset = env.argStack.pop_uint ();
163
30.9k
  env.clear_args ();
164
30.9k
  break;
165
30.4k
      case OpCode_FDArray:
166
30.4k
  dictval.FDArrayOffset = env.argStack.pop_uint ();
167
30.4k
  env.clear_args ();
168
30.4k
  break;
169
0
      case OpCode_FontMatrix:
170
0
  env.clear_args ();
171
0
  break;
172
161k
      default:
173
161k
  dict_opset_t::process_op (op, env);
174
161k
  break;
175
222k
    }
176
222k
  }
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.47M
  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
41.5k
  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
219k
  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
247k
  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
31.2k
  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
470k
  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
469k
  dict_interpreter_t (ENV& env_) : interpreter_t<ENV> (env_) {}
183
184
  bool interpret (PARAM& param)
185
1.47M
  {
186
1.47M
    param.init ();
187
7.24M
    while (SUPER::env.str_ref.avail ())
188
5.77M
    {
189
5.77M
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
5.77M
      if (unlikely (SUPER::env.in_error ()))
191
9.27k
  return false;
192
5.77M
    }
193
194
1.46M
    return true;
195
1.47M
  }
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
41.5k
  {
186
41.5k
    param.init ();
187
1.20M
    while (SUPER::env.str_ref.avail ())
188
1.17M
    {
189
1.17M
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
1.17M
      if (unlikely (SUPER::env.in_error ()))
191
3.97k
  return false;
192
1.17M
    }
193
194
37.6k
    return true;
195
41.5k
  }
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
218k
  {
186
218k
    param.init ();
187
512k
    while (SUPER::env.str_ref.avail ())
188
294k
    {
189
294k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
294k
      if (unlikely (SUPER::env.in_error ()))
191
496
  return false;
192
294k
    }
193
194
218k
    return true;
195
218k
  }
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
247k
  {
186
247k
    param.init ();
187
1.71M
    while (SUPER::env.str_ref.avail ())
188
1.46M
    {
189
1.46M
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
1.46M
      if (unlikely (SUPER::env.in_error ()))
191
1.65k
  return false;
192
1.46M
    }
193
194
245k
    return true;
195
247k
  }
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
31.2k
  {
186
31.2k
    param.init ();
187
283k
    while (SUPER::env.str_ref.avail ())
188
252k
    {
189
252k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
252k
      if (unlikely (SUPER::env.in_error ()))
191
863
  return false;
192
252k
    }
193
194
30.3k
    return true;
195
31.2k
  }
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
470k
  {
186
470k
    param.init ();
187
1.41M
    while (SUPER::env.str_ref.avail ())
188
945k
    {
189
945k
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
945k
      if (unlikely (SUPER::env.in_error ()))
191
971
  return false;
192
945k
    }
193
194
469k
    return true;
195
470k
  }
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
469k
  {
186
469k
    param.init ();
187
2.11M
    while (SUPER::env.str_ref.avail ())
188
1.64M
    {
189
1.64M
      OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
190
1.64M
      if (unlikely (SUPER::env.in_error ()))
191
1.31k
  return false;
192
1.64M
    }
193
194
468k
    return true;
195
469k
  }
196
197
  private:
198
  typedef interpreter_t<ENV> SUPER;
199
};
200
201
} /* namespace CFF */
202
203
#endif /* HB_CFF_INTERP_DICT_COMMON_HH */