Coverage Report

Created: 2025-11-16 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pango/subprojects/harfbuzz/src/hb-ot-cff-common.hh
Line
Count
Source
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
0
#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
0
{
48
0
  if (!offset) return Null (Type);
49
50
0
  const char *p = (const char *) P + offset;
51
0
  if (!sc.check_point (p)) return Null (Type);
52
53
0
  const Type &obj = *reinterpret_cast<const Type *> (p);
54
0
  if (!obj.sanitize (&sc, std::forward<Ts> (ds)...)) return Null (Type);
55
56
0
  return obj;
57
0
}
Unexecuted instantiation: hb-ot-face.cc:CFF::CFFIndex<OT::IntType<unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::CFFIndex<OT::IntType<unsigned short, 2u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::Charset const& CFF::StructAtOffsetOrNull<CFF::Charset, unsigned int*>(void const*, int, hb_sanitize_context_t&, unsigned int*&&)
Unexecuted instantiation: hb-ot-face.cc:CFF::CFF1FDArray const& CFF::StructAtOffsetOrNull<CFF::CFF1FDArray>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::CFF1FDSelect const& CFF::StructAtOffsetOrNull<CFF::CFF1FDSelect, OT::IntType<unsigned short, 2u> const&>(void const*, int, hb_sanitize_context_t&, OT::IntType<unsigned short, 2u> const&)
Unexecuted instantiation: hb-ot-face.cc:CFF::Encoding const& CFF::StructAtOffsetOrNull<CFF::Encoding>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::CFF1StringIndex const& CFF::StructAtOffsetOrNull<CFF::CFF1StringIndex>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::Subrs<OT::IntType<unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::IntType<unsigned short, 2u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::UnsizedByteStr const& CFF::StructAtOffsetOrNull<CFF::UnsizedByteStr, unsigned int&>(void const*, int, hb_sanitize_context_t&, unsigned int&)
Unexecuted instantiation: hb-ot-face.cc:CFF::Subrs<OT::IntType<unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::IntType<unsigned int, 4u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::CFF2ItemVariationStore const& CFF::StructAtOffsetOrNull<CFF::CFF2ItemVariationStore>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::CFFIndex<OT::IntType<unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::CFFIndex<OT::IntType<unsigned int, 4u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::CFF2FDArray const& CFF::StructAtOffsetOrNull<CFF::CFF2FDArray>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-face.cc:CFF::CFF2FDSelect const& CFF::StructAtOffsetOrNull<CFF::CFF2FDSelect, OT::IntType<unsigned int, 4u> const&>(void const*, int, hb_sanitize_context_t&, OT::IntType<unsigned int, 4u> const&)
Unexecuted instantiation: hb-ot-font.cc:CFF::Subrs<OT::IntType<unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::IntType<unsigned int, 4u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-font.cc:CFF::CFF2ItemVariationStore const& CFF::StructAtOffsetOrNull<CFF::CFF2ItemVariationStore>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-font.cc:CFF::CFFIndex<OT::IntType<unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::CFFIndex<OT::IntType<unsigned int, 4u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-font.cc:CFF::CFF2FDArray const& CFF::StructAtOffsetOrNull<CFF::CFF2FDArray>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-font.cc:CFF::CFF2FDSelect const& CFF::StructAtOffsetOrNull<CFF::CFF2FDSelect, OT::IntType<unsigned int, 4u> const&>(void const*, int, hb_sanitize_context_t&, OT::IntType<unsigned int, 4u> const&)
Unexecuted instantiation: hb-ot-font.cc:CFF::UnsizedByteStr const& CFF::StructAtOffsetOrNull<CFF::UnsizedByteStr, unsigned int&>(void const*, int, hb_sanitize_context_t&, unsigned int&)
Unexecuted instantiation: hb-ot-font.cc:CFF::CFFIndex<OT::IntType<unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::CFFIndex<OT::IntType<unsigned short, 2u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-font.cc:CFF::Charset const& CFF::StructAtOffsetOrNull<CFF::Charset, unsigned int*>(void const*, int, hb_sanitize_context_t&, unsigned int*&&)
Unexecuted instantiation: hb-ot-font.cc:CFF::CFF1FDArray const& CFF::StructAtOffsetOrNull<CFF::CFF1FDArray>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-font.cc:CFF::CFF1FDSelect const& CFF::StructAtOffsetOrNull<CFF::CFF1FDSelect, OT::IntType<unsigned short, 2u> const&>(void const*, int, hb_sanitize_context_t&, OT::IntType<unsigned short, 2u> const&)
Unexecuted instantiation: hb-ot-font.cc:CFF::Encoding const& CFF::StructAtOffsetOrNull<CFF::Encoding>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-font.cc:CFF::CFF1StringIndex const& CFF::StructAtOffsetOrNull<CFF::CFF1StringIndex>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-font.cc:CFF::Subrs<OT::IntType<unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::IntType<unsigned short, 2u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff1-table.cc:CFF::CFFIndex<OT::IntType<unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::CFFIndex<OT::IntType<unsigned short, 2u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff1-table.cc:CFF::Charset const& CFF::StructAtOffsetOrNull<CFF::Charset, unsigned int*>(void const*, int, hb_sanitize_context_t&, unsigned int*&&)
Unexecuted instantiation: hb-ot-cff1-table.cc:CFF::CFF1FDArray const& CFF::StructAtOffsetOrNull<CFF::CFF1FDArray>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff1-table.cc:CFF::CFF1FDSelect const& CFF::StructAtOffsetOrNull<CFF::CFF1FDSelect, OT::IntType<unsigned short, 2u> const&>(void const*, int, hb_sanitize_context_t&, OT::IntType<unsigned short, 2u> const&)
Unexecuted instantiation: hb-ot-cff1-table.cc:CFF::Encoding const& CFF::StructAtOffsetOrNull<CFF::Encoding>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff1-table.cc:CFF::CFF1StringIndex const& CFF::StructAtOffsetOrNull<CFF::CFF1StringIndex>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff1-table.cc:CFF::Subrs<OT::IntType<unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::IntType<unsigned short, 2u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff1-table.cc:CFF::UnsizedByteStr const& CFF::StructAtOffsetOrNull<CFF::UnsizedByteStr, unsigned int&>(void const*, int, hb_sanitize_context_t&, unsigned int&)
Unexecuted instantiation: hb-ot-cff2-table.cc:CFF::Subrs<OT::IntType<unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::IntType<unsigned int, 4u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff2-table.cc:CFF::CFF2ItemVariationStore const& CFF::StructAtOffsetOrNull<CFF::CFF2ItemVariationStore>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff2-table.cc:CFF::CFFIndex<OT::IntType<unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::CFFIndex<OT::IntType<unsigned int, 4u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff2-table.cc:CFF::CFF2FDArray const& CFF::StructAtOffsetOrNull<CFF::CFF2FDArray>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff2-table.cc:CFF::CFF2FDSelect const& CFF::StructAtOffsetOrNull<CFF::CFF2FDSelect, OT::IntType<unsigned int, 4u> const&>(void const*, int, hb_sanitize_context_t&, OT::IntType<unsigned int, 4u> const&)
Unexecuted instantiation: hb-ot-cff2-table.cc:CFF::UnsizedByteStr const& CFF::StructAtOffsetOrNull<CFF::UnsizedByteStr, unsigned int&>(void const*, int, hb_sanitize_context_t&, unsigned int&)
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
struct length_f_t
72
{
73
  template <typename Iterable,
74
      hb_requires (hb_is_iterable (Iterable))>
75
0
  unsigned operator () (const Iterable &_) const { return hb_len (hb_iter (_)); }
76
77
0
  unsigned operator () (unsigned _) const { return _; }
78
}
79
HB_FUNCOBJ (length_f);
80
81
/* CFF INDEX */
82
template <typename COUNT>
83
struct CFFIndex
84
{
85
  unsigned int offset_array_size () const
86
0
  { return offSize * (count + 1); }
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned short, 2u> >::offset_array_size() const
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned int, 4u> >::offset_array_size() const
87
88
  template <typename Iterable,
89
      hb_requires (hb_is_iterable (Iterable))>
90
  bool serialize (hb_serialize_context_t *c,
91
      const Iterable &iterable,
92
      const unsigned *p_data_size = nullptr,
93
                  unsigned min_off_size = 0)
94
0
  {
95
0
    TRACE_SERIALIZE (this);
96
0
    unsigned data_size;
97
0
    if (p_data_size)
98
0
      data_size = *p_data_size;
99
0
    else
100
0
      total_size (iterable, &data_size);
101
0
102
0
    auto it = hb_iter (iterable);
103
0
    if (unlikely (!serialize_header (c, +it, data_size, min_off_size))) return_trace (false);
104
0
    unsigned char *ret = c->allocate_size<unsigned char> (data_size, false);
105
0
    if (unlikely (!ret)) return_trace (false);
106
0
    for (const auto &_ : +it)
107
0
    {
108
0
      unsigned len = _.length;
109
0
      if (!len)
110
0
  continue;
111
0
      if (len <= 1)
112
0
      {
113
0
  *ret++ = *_.arrayZ;
114
0
  continue;
115
0
      }
116
0
      hb_memcpy (ret, _.arrayZ, len);
117
0
      ret += len;
118
0
    }
119
0
    return_trace (true);
120
0
  }
121
122
  template <typename Iterator,
123
      hb_requires (hb_is_iterator (Iterator))>
124
  bool serialize_header (hb_serialize_context_t *c,
125
       Iterator it,
126
       unsigned data_size,
127
                         unsigned min_off_size = 0)
128
0
  {
129
0
    TRACE_SERIALIZE (this);
130
0
131
0
    unsigned off_size = (hb_bit_storage (data_size + 1) + 7) / 8;
132
0
    off_size = hb_max(min_off_size, off_size);
133
0
134
0
    /* serialize CFFIndex header */
135
0
    if (unlikely (!c->extend_min (this))) return_trace (false);
136
0
    this->count = hb_len (it);
137
0
    if (!this->count) return_trace (true);
138
0
    if (unlikely (!c->extend (this->offSize))) return_trace (false);
139
0
    this->offSize = off_size;
140
0
    if (unlikely (!c->allocate_size<HBUINT8> (off_size * (this->count + 1), false)))
141
0
      return_trace (false);
142
0
143
0
    /* serialize indices */
144
0
    unsigned int offset = 1;
145
0
    if (HB_OPTIMIZE_SIZE_VAL)
146
0
    {
147
0
      unsigned int i = 0;
148
0
      for (const auto &_ : +it)
149
0
      {
150
0
  set_offset_at (i++, offset);
151
0
  offset += length_f (_);
152
0
      }
153
0
      set_offset_at (i, offset);
154
0
    }
155
0
    else
156
0
      switch (off_size)
157
0
      {
158
0
  case 1:
159
0
  {
160
0
    HBUINT8 *p = (HBUINT8 *) offsets;
161
0
    for (const auto &_ : +it)
162
0
    {
163
0
      *p++ = offset;
164
0
      offset += length_f (_);
165
0
    }
166
0
    *p = offset;
167
0
  }
168
0
  break;
169
0
  case 2:
170
0
  {
171
0
    HBUINT16 *p = (HBUINT16 *) offsets;
172
0
    for (const auto &_ : +it)
173
0
    {
174
0
      *p++ = offset;
175
0
      offset += length_f (_);
176
0
    }
177
0
    *p = offset;
178
0
  }
179
0
  break;
180
0
  case 3:
181
0
  {
182
0
    HBUINT24 *p = (HBUINT24 *) offsets;
183
0
    for (const auto &_ : +it)
184
0
    {
185
0
      *p++ = offset;
186
0
      offset += length_f (_);
187
0
    }
188
0
    *p = offset;
189
0
  }
190
0
  break;
191
0
  case 4:
192
0
  {
193
0
    HBUINT32 *p = (HBUINT32 *) offsets;
194
0
    for (const auto &_ : +it)
195
0
    {
196
0
      *p++ = offset;
197
0
      offset += length_f (_);
198
0
    }
199
0
    *p = offset;
200
0
  }
201
0
  break;
202
0
  default:
203
0
  break;
204
0
      }
205
0
206
0
    assert (offset == data_size + 1);
207
0
    return_trace (true);
208
0
  }
209
210
  template <typename Iterable,
211
      hb_requires (hb_is_iterable (Iterable))>
212
  static unsigned total_size (const Iterable &iterable, unsigned *data_size = nullptr, unsigned min_off_size = 0)
213
0
  {
214
0
    auto it = + hb_iter (iterable);
215
0
    if (!it)
216
0
    {
217
0
      if (data_size) *data_size = 0;
218
0
      return min_size;
219
0
    }
220
0
221
0
    unsigned total = 0;
222
0
    for (const auto &_ : +it)
223
0
      total += length_f (_);
224
0
225
0
    if (data_size) *data_size = total;
226
0
227
0
    unsigned off_size = (hb_bit_storage (total + 1) + 7) / 8;
228
0
    off_size = hb_max(min_off_size, off_size);
229
0
230
0
    return min_size + HBUINT8::static_size + (hb_len (it) + 1) * off_size + total;
231
0
  }
232
233
  void set_offset_at (unsigned int index, unsigned int offset)
234
0
  {
235
0
    assert (index <= count);
236
0
237
0
    unsigned int size = offSize;
238
0
    const HBUINT8 *p = offsets;
239
0
    switch (size)
240
0
    {
241
0
      case 1: ((HBUINT8  *) p)[index] = offset; break;
242
0
      case 2: ((HBUINT16 *) p)[index] = offset; break;
243
0
      case 3: ((HBUINT24 *) p)[index] = offset; break;
244
0
      case 4: ((HBUINT32 *) p)[index] = offset; break;
245
0
      default: return;
246
0
    }
247
0
  }
248
249
  private:
250
  unsigned int offset_at (unsigned int index) const
251
0
  {
252
0
    assert (index <= count);
253
254
0
    unsigned int size = offSize;
255
0
    const HBUINT8 *p = offsets;
256
0
    switch (size)
257
0
    {
258
0
      case 1: return ((HBUINT8  *) p)[index];
259
0
      case 2: return ((HBUINT16 *) p)[index];
260
0
      case 3: return ((HBUINT24 *) p)[index];
261
0
      case 4: return ((HBUINT32 *) p)[index];
262
0
      default: return 0;
263
0
    }
264
0
  }
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned short, 2u> >::offset_at(unsigned int) const
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned int, 4u> >::offset_at(unsigned int) const
265
266
  const unsigned char *data_base () const
267
0
  { return (const unsigned char *) this + min_size + offSize.static_size - 1 + offset_array_size (); }
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned short, 2u> >::data_base() const
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned int, 4u> >::data_base() const
268
  public:
269
270
  hb_ubytes_t operator [] (unsigned int index) const
271
0
  {
272
0
    if (unlikely (index >= count)) return hb_ubytes_t ();
273
0
    _hb_compiler_memory_r_barrier ();
274
0
    unsigned offset0 = offset_at (index);
275
0
    unsigned offset1 = offset_at (index + 1);
276
0
    if (unlikely (offset1 < offset0 || offset1 > offset_at (count)))
277
0
      return hb_ubytes_t ();
278
0
    return hb_ubytes_t (data_base () + offset0, offset1 - offset0);
279
0
  }
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned short, 2u> >::operator[](unsigned int) const
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned int, 4u> >::operator[](unsigned int) const
280
281
  unsigned int get_size () const
282
0
  {
283
0
    if (count)
284
0
      return min_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1);
285
0
    return min_size;  /* empty CFFIndex contains count only */
286
0
  }
287
288
  bool sanitize (hb_sanitize_context_t *c) const
289
0
  {
290
0
    TRACE_SANITIZE (this);
291
0
    return_trace (likely (c->check_struct (this) &&
292
0
        hb_barrier () &&
293
0
        (count == 0 || /* empty INDEX */
294
0
         (count < count + 1u &&
295
0
          hb_barrier () &&
296
0
          c->check_struct (&offSize) && offSize >= 1 && offSize <= 4 &&
297
0
          c->check_array (offsets, offSize, count + 1u) &&
298
0
          c->check_array ((const HBUINT8*) data_base (), 1, offset_at (count))))));
299
0
  }
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: CFF::CFFIndex<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
300
301
  public:
302
  COUNT   count;    /* Number of object data. Note there are (count+1) offsets */
303
  private:
304
  HBUINT8 offSize;  /* The byte size of each offset in the offsets array. */
305
  HBUINT8 offsets[HB_VAR_ARRAY];
306
        /* The array of (count + 1) offsets into objects array (1-base). */
307
  /* HBUINT8 data[HB_VAR_ARRAY];  Object data */
308
  public:
309
  DEFINE_SIZE_MIN (COUNT::static_size);
310
};
311
312
/* Top Dict, Font Dict, Private Dict */
313
struct Dict : UnsizedByteStr
314
{
315
  template <typename DICTVAL, typename OP_SERIALIZER, typename ...Ts>
316
  bool serialize (hb_serialize_context_t *c,
317
      const DICTVAL &dictval,
318
      OP_SERIALIZER& opszr,
319
      Ts&&... ds)
320
  {
321
    TRACE_SERIALIZE (this);
322
    for (unsigned int i = 0; i < dictval.get_count (); i++)
323
      if (unlikely (!opszr.serialize (c, dictval[i], std::forward<Ts> (ds)...)))
324
  return_trace (false);
325
326
    return_trace (true);
327
  }
328
329
  template <typename T, typename V>
330
  static bool serialize_int_op (hb_serialize_context_t *c, op_code_t op, V value, op_code_t intOp)
331
0
  {
332
0
    if (unlikely ((!serialize_int<T, V> (c, intOp, value))))
333
0
      return false;
334
0
335
0
    TRACE_SERIALIZE (this);
336
0
    /* serialize the opcode */
337
0
    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op), false);
338
0
    if (unlikely (!p)) return_trace (false);
339
0
    if (Is_OpCode_ESC (op))
340
0
    {
341
0
      *p = OpCode_escape;
342
0
      op = Unmake_OpCode_ESC (op);
343
0
      p++;
344
0
    }
345
0
    *p = op;
346
0
    return_trace (true);
347
0
  }
Unexecuted instantiation: bool CFF::Dict::serialize_int_op<OT::IntType<int, 4u>, int>(hb_serialize_context_t*, unsigned int, int, unsigned int)
Unexecuted instantiation: bool CFF::Dict::serialize_int_op<OT::IntType<short, 2u>, int>(hb_serialize_context_t*, unsigned int, int, unsigned int)
348
349
  template <typename V>
350
  static bool serialize_int4_op (hb_serialize_context_t *c, op_code_t op, V value)
351
  { return serialize_int_op<HBINT32> (c, op, value, OpCode_longintdict); }
352
353
  template <typename V>
354
  static bool serialize_int2_op (hb_serialize_context_t *c, op_code_t op, V value)
355
  { return serialize_int_op<HBINT16> (c, op, value, OpCode_shortint); }
356
357
  template <typename T, int int_op>
358
  static bool serialize_link_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence)
359
0
  {
360
0
    T &ofs = *(T *) (c->head + OpCode_Size (int_op));
361
0
    if (unlikely (!serialize_int_op<T> (c, op, 0, int_op))) return false;
362
0
    c->add_link (ofs, link, whence);
363
0
    return true;
364
0
  }
Unexecuted instantiation: bool CFF::Dict::serialize_link_op<OT::IntType<int, 4u>, 29>(hb_serialize_context_t*, unsigned int, unsigned int, hb_serialize_context_t::whence_t)
Unexecuted instantiation: bool CFF::Dict::serialize_link_op<OT::IntType<short, 2u>, 28>(hb_serialize_context_t*, unsigned int, unsigned int, hb_serialize_context_t::whence_t)
365
366
  static bool serialize_link4_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head)
367
0
  { return serialize_link_op<HBINT32, OpCode_longintdict> (c, op, link, whence); }
368
369
  static bool serialize_link2_op (hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence = whence_t::Head)
370
0
  { return serialize_link_op<HBINT16, OpCode_shortint> (c, op, link, whence); }
371
};
372
373
struct TopDict : Dict {};
374
struct FontDict : Dict {};
375
struct PrivateDict : Dict {};
376
377
struct table_info_t
378
{
379
0
  void init () { offset = size = 0; link = 0; }
380
381
  unsigned int    offset;
382
  unsigned int    size;
383
  objidx_t    link;
384
};
385
386
template <typename COUNT>
387
struct FDArray : CFFIndex<COUNT>
388
{
389
  template <typename DICTVAL, typename INFO, typename Iterator, typename OP_SERIALIZER>
390
  bool serialize (hb_serialize_context_t *c,
391
      Iterator it,
392
      OP_SERIALIZER& opszr)
393
  {
394
    TRACE_SERIALIZE (this);
395
396
    /* serialize INDEX data */
397
    hb_vector_t<unsigned> sizes;
398
    if (it.is_random_access_iterator)
399
      sizes.alloc (hb_len (it));
400
401
    c->push ();
402
    char *data_base = c->head;
403
    + it
404
    | hb_map ([&] (const hb_pair_t<const DICTVAL&, const INFO&> &_)
405
    {
406
      FontDict *dict = c->start_embed<FontDict> ();
407
    dict->serialize (c, _.first, opszr, _.second);
408
    return c->head - (const char*)dict;
409
        })
410
    | hb_sink (sizes)
411
    ;
412
    unsigned data_size = c->head - data_base;
413
    c->pop_pack (false);
414
415
    if (unlikely (sizes.in_error ())) return_trace (false);
416
417
    /* It just happens that the above is packed right after the header below.
418
     * Such a hack. */
419
420
    /* serialize INDEX header */
421
    return_trace (CFFIndex<COUNT>::serialize_header (c, hb_iter (sizes), data_size));
422
  }
423
};
424
425
/* FDSelect */
426
struct FDSelect0 {
427
  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
428
0
  {
429
0
    TRACE_SANITIZE (this);
430
0
    if (unlikely (!(c->check_struct (this))))
431
0
      return_trace (false);
432
0
    hb_barrier ();
433
0
    if (unlikely (!c->check_array (fds, c->get_num_glyphs ())))
434
0
      return_trace (false);
435
436
0
    return_trace (true);
437
0
  }
438
439
  unsigned get_fd (hb_codepoint_t glyph) const
440
0
  { return fds[glyph]; }
441
442
  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
443
0
  { return {fds[glyph], glyph + 1}; }
444
445
  unsigned int get_size (unsigned int num_glyphs) const
446
0
  { return HBUINT8::static_size * num_glyphs; }
447
448
  HBUINT8     fds[HB_VAR_ARRAY];
449
450
  DEFINE_SIZE_MIN (0);
451
};
452
453
template <typename GID_TYPE, typename FD_TYPE>
454
struct FDSelect3_4_Range
455
{
456
  bool sanitize (hb_sanitize_context_t *c, const void * /*nullptr*/, unsigned int fdcount) const
457
0
  {
458
0
    TRACE_SANITIZE (this);
459
0
    return_trace (c->check_struct (this) &&
460
0
      hb_barrier () &&
461
0
      first < c->get_num_glyphs () && (fd < fdcount));
462
0
  }
Unexecuted instantiation: CFF::FDSelect3_4_Range<OT::IntType<unsigned short, 2u>, OT::IntType<unsigned char, 1u> >::sanitize(hb_sanitize_context_t*, void const*, unsigned int) const
Unexecuted instantiation: CFF::FDSelect3_4_Range<OT::IntType<unsigned int, 4u>, OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*, void const*, unsigned int) const
463
464
  GID_TYPE    first;
465
  FD_TYPE     fd;
466
  public:
467
  DEFINE_SIZE_STATIC (GID_TYPE::static_size + FD_TYPE::static_size);
468
};
469
470
template <typename GID_TYPE, typename FD_TYPE>
471
struct FDSelect3_4
472
{
473
  unsigned int get_size () const
474
0
  { return GID_TYPE::static_size * 2 + ranges.get_size (); }
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned short, 2u>, OT::IntType<unsigned char, 1u> >::get_size() const
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned int, 4u>, OT::IntType<unsigned short, 2u> >::get_size() const
475
476
  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
477
0
  {
478
0
    TRACE_SANITIZE (this);
479
0
    if (unlikely (!(c->check_struct (this) &&
480
0
        ranges.sanitize (c, nullptr, fdcount) &&
481
0
        hb_barrier () &&
482
0
        (nRanges () != 0) &&
483
0
        ranges[0].first == 0)))
484
0
      return_trace (false);
485
486
0
    for (unsigned int i = 1; i < nRanges (); i++)
487
0
      if (unlikely (ranges[i - 1].first >= ranges[i].first))
488
0
  return_trace (false);
489
490
0
    if (unlikely (!(sentinel().sanitize (c) &&
491
0
       hb_barrier () &&
492
0
       (sentinel() == c->get_num_glyphs ()))))
493
0
      return_trace (false);
494
495
0
    return_trace (true);
496
0
  }
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned short, 2u>, OT::IntType<unsigned char, 1u> >::sanitize(hb_sanitize_context_t*, unsigned int) const
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned int, 4u>, OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*, unsigned int) const
497
498
  static int _cmp_range (const void *_key, const void *_item)
499
0
  {
500
0
    hb_codepoint_t glyph = * (hb_codepoint_t *) _key;
501
0
    FDSelect3_4_Range<GID_TYPE, FD_TYPE> *range = (FDSelect3_4_Range<GID_TYPE, FD_TYPE> *) _item;
502
503
0
    if (glyph < range[0].first) return -1;
504
0
    if (glyph < range[1].first) return 0;
505
0
    return +1;
506
0
  }
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned short, 2u>, OT::IntType<unsigned char, 1u> >::_cmp_range(void const*, void const*)
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned int, 4u>, OT::IntType<unsigned short, 2u> >::_cmp_range(void const*, void const*)
507
508
  unsigned get_fd (hb_codepoint_t glyph) const
509
0
  {
510
0
    auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
511
0
    return range ? range->fd : ranges[nRanges () - 1].fd;
512
0
  }
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned short, 2u>, OT::IntType<unsigned char, 1u> >::get_fd(unsigned int) const
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned int, 4u>, OT::IntType<unsigned short, 2u> >::get_fd(unsigned int) const
513
514
  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
515
0
  {
516
0
    auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
517
0
    unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd;
518
0
    hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first;
519
0
    return {fd, end};
520
0
  }
521
522
  GID_TYPE        &nRanges ()       { return ranges.len; }
523
0
  GID_TYPE         nRanges () const { return ranges.len; }
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned short, 2u>, OT::IntType<unsigned char, 1u> >::nRanges() const
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned int, 4u>, OT::IntType<unsigned short, 2u> >::nRanges() const
524
  GID_TYPE       &sentinel ()       { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
525
0
  const GID_TYPE &sentinel () const { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned short, 2u>, OT::IntType<unsigned char, 1u> >::sentinel() const
Unexecuted instantiation: CFF::FDSelect3_4<OT::IntType<unsigned int, 4u>, OT::IntType<unsigned short, 2u> >::sentinel() const
526
527
  ArrayOf<FDSelect3_4_Range<GID_TYPE, FD_TYPE>, GID_TYPE> ranges;
528
  /* GID_TYPE sentinel */
529
530
  DEFINE_SIZE_ARRAY (GID_TYPE::static_size, ranges);
531
};
532
533
typedef FDSelect3_4<HBUINT16, HBUINT8> FDSelect3;
534
typedef FDSelect3_4_Range<HBUINT16, HBUINT8> FDSelect3_Range;
535
536
struct FDSelect
537
{
538
  bool serialize (hb_serialize_context_t *c, const FDSelect &src, unsigned int num_glyphs)
539
0
  {
540
0
    TRACE_SERIALIZE (this);
541
0
    unsigned int size = src.get_size (num_glyphs);
542
0
    FDSelect *dest = c->allocate_size<FDSelect> (size, false);
543
0
    if (unlikely (!dest)) return_trace (false);
544
0
    hb_memcpy (dest, &src, size);
545
0
    return_trace (true);
546
0
  }
547
548
  unsigned int get_size (unsigned int num_glyphs) const
549
0
  {
550
0
    switch (format)
551
0
    {
552
0
    case 0: return format.static_size + u.format0.get_size (num_glyphs);
553
0
    case 3: return format.static_size + u.format3.get_size ();
554
0
    default:return 0;
555
0
    }
556
0
  }
557
558
  unsigned get_fd (hb_codepoint_t glyph) const
559
0
  {
560
0
    if (this == &Null (FDSelect)) return 0;
561
562
0
    switch (format)
563
0
    {
564
0
    case 0: return u.format0.get_fd (glyph);
565
0
    case 3: return u.format3.get_fd (glyph);
566
0
    default:return 0;
567
0
    }
568
0
  }
569
  /* Returns pair of fd and one after last glyph in range. */
570
  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
571
0
  {
572
0
    if (this == &Null (FDSelect)) return {0, 1};
573
0
574
0
    switch (format)
575
0
    {
576
0
    case 0: return u.format0.get_fd_range (glyph);
577
0
    case 3: return u.format3.get_fd_range (glyph);
578
0
    default:return {0, 1};
579
0
    }
580
0
  }
581
582
  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
583
0
  {
584
0
    TRACE_SANITIZE (this);
585
0
    if (unlikely (!c->check_struct (this)))
586
0
      return_trace (false);
587
0
    hb_barrier ();
588
589
0
    switch (format)
590
0
    {
591
0
    case 0: return_trace (u.format0.sanitize (c, fdcount));
592
0
    case 3: return_trace (u.format3.sanitize (c, fdcount));
593
0
    default:return_trace (false);
594
0
    }
595
0
  }
596
597
  HBUINT8 format;
598
  union {
599
  FDSelect0 format0;
600
  FDSelect3 format3;
601
  } u;
602
  public:
603
  DEFINE_SIZE_MIN (1);
604
};
605
606
template <typename COUNT>
607
struct Subrs : CFFIndex<COUNT>
608
{
609
  typedef COUNT count_type;
610
  typedef CFFIndex<COUNT> SUPER;
611
};
612
613
} /* namespace CFF */
614
615
#endif /* HB_OT_CFF_COMMON_HH */