Coverage Report

Created: 2025-07-11 06:34

/src/harfbuzz/src/hb-ot-cff-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_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:OT::CFFIndex<OT::NumType<true, unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<OT::CFFIndex<OT::NumType<true, 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::NumType<true, unsigned short, 2u> const&>(void const*, int, hb_sanitize_context_t&, OT::NumType<true, 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::NumType<true, unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::NumType<true, 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::NumType<true, unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::NumType<true, 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:OT::CFFIndex<OT::NumType<true, unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<OT::CFFIndex<OT::NumType<true, 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::NumType<true, unsigned int, 4u> const&>(void const*, int, hb_sanitize_context_t&, OT::NumType<true, unsigned int, 4u> const&)
Unexecuted instantiation: hb-ot-font.cc:CFF::Subrs<OT::NumType<true, unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::NumType<true, 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:OT::CFFIndex<OT::NumType<true, unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<OT::CFFIndex<OT::NumType<true, 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::NumType<true, unsigned int, 4u> const&>(void const*, int, hb_sanitize_context_t&, OT::NumType<true, 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:OT::CFFIndex<OT::NumType<true, unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<OT::CFFIndex<OT::NumType<true, 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::NumType<true, unsigned short, 2u> const&>(void const*, int, hb_sanitize_context_t&, OT::NumType<true, 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::NumType<true, unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::NumType<true, unsigned short, 2u> >>(void const*, int, hb_sanitize_context_t&)
Unexecuted instantiation: hb-ot-cff1-table.cc:OT::CFFIndex<OT::NumType<true, unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<OT::CFFIndex<OT::NumType<true, 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::NumType<true, unsigned short, 2u> const&>(void const*, int, hb_sanitize_context_t&, OT::NumType<true, 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::NumType<true, unsigned short, 2u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::NumType<true, 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::NumType<true, unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<CFF::Subrs<OT::NumType<true, 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:OT::CFFIndex<OT::NumType<true, unsigned int, 4u> > const& CFF::StructAtOffsetOrNull<OT::CFFIndex<OT::NumType<true, 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::NumType<true, unsigned int, 4u> const&>(void const*, int, hb_sanitize_context_t&, OT::NumType<true, 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
/* 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], std::forward<Ts> (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
0
  {
91
0
    if (unlikely ((!serialize_int<T, V> (c, intOp, value))))
92
0
      return false;
93
0
94
0
    TRACE_SERIALIZE (this);
95
0
    /* serialize the opcode */
96
0
    HBUINT8 *p = c->allocate_size<HBUINT8> (OpCode_Size (op), false);
97
0
    if (unlikely (!p)) return_trace (false);
98
0
    if (Is_OpCode_ESC (op))
99
0
    {
100
0
      *p = OpCode_escape;
101
0
      op = Unmake_OpCode_ESC (op);
102
0
      p++;
103
0
    }
104
0
    *p = op;
105
0
    return_trace (true);
106
0
  }
Unexecuted instantiation: bool CFF::Dict::serialize_int_op<OT::NumType<true, int, 4u>, int>(hb_serialize_context_t*, unsigned int, int, unsigned int)
Unexecuted instantiation: bool CFF::Dict::serialize_int_op<OT::NumType<true, short, 2u>, int>(hb_serialize_context_t*, unsigned int, int, unsigned int)
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
0
  {
119
0
    T &ofs = *(T *) (c->head + OpCode_Size (int_op));
120
0
    if (unlikely (!serialize_int_op<T> (c, op, 0, int_op))) return false;
121
0
    c->add_link (ofs, link, whence);
122
0
    return true;
123
0
  }
Unexecuted instantiation: bool CFF::Dict::serialize_link_op<OT::NumType<true, 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::NumType<true, short, 2u>, 28>(hb_serialize_context_t*, unsigned int, unsigned int, hb_serialize_context_t::whence_t)
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
0
  { 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
0
  { 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
0
  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
0
  {
188
0
    TRACE_SANITIZE (this);
189
0
    if (unlikely (!(c->check_struct (this))))
190
0
      return_trace (false);
191
0
    hb_barrier ();
192
0
    if (unlikely (!c->check_array (fds, c->get_num_glyphs ())))
193
0
      return_trace (false);
194
195
0
    return_trace (true);
196
0
  }
197
198
  unsigned get_fd (hb_codepoint_t glyph) const
199
0
  { return fds[glyph]; }
200
201
  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
202
0
  { return {fds[glyph], glyph + 1}; }
203
204
  unsigned int get_size (unsigned int num_glyphs) const
205
0
  { 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
0
  {
217
0
    TRACE_SANITIZE (this);
218
0
    return_trace (c->check_struct (this) &&
219
0
      hb_barrier () &&
220
0
      first < c->get_num_glyphs () && (fd < fdcount));
221
0
  }
Unexecuted instantiation: CFF::FDSelect3_4_Range<OT::NumType<true, unsigned short, 2u>, OT::NumType<true, unsigned char, 1u> >::sanitize(hb_sanitize_context_t*, void const*, unsigned int) const
Unexecuted instantiation: CFF::FDSelect3_4_Range<OT::NumType<true, unsigned int, 4u>, OT::NumType<true, unsigned short, 2u> >::sanitize(hb_sanitize_context_t*, void const*, unsigned int) const
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
0
  { return GID_TYPE::static_size * 2 + ranges.get_size (); }
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned short, 2u>, OT::NumType<true, unsigned char, 1u> >::get_size() const
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned int, 4u>, OT::NumType<true, unsigned short, 2u> >::get_size() const
234
235
  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
236
0
  {
237
0
    TRACE_SANITIZE (this);
238
0
    if (unlikely (!(c->check_struct (this) &&
239
0
        ranges.sanitize (c, nullptr, fdcount) &&
240
0
        hb_barrier () &&
241
0
        (nRanges () != 0) &&
242
0
        ranges[0].first == 0)))
243
0
      return_trace (false);
244
245
0
    for (unsigned int i = 1; i < nRanges (); i++)
246
0
      if (unlikely (ranges[i - 1].first >= ranges[i].first))
247
0
  return_trace (false);
248
249
0
    if (unlikely (!(sentinel().sanitize (c) &&
250
0
       hb_barrier () &&
251
0
       (sentinel() == c->get_num_glyphs ()))))
252
0
      return_trace (false);
253
254
0
    return_trace (true);
255
0
  }
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned short, 2u>, OT::NumType<true, unsigned char, 1u> >::sanitize(hb_sanitize_context_t*, unsigned int) const
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned int, 4u>, OT::NumType<true, unsigned short, 2u> >::sanitize(hb_sanitize_context_t*, unsigned int) const
256
257
  static int _cmp_range (const void *_key, const void *_item)
258
0
  {
259
0
    hb_codepoint_t glyph = * (hb_codepoint_t *) _key;
260
0
    FDSelect3_4_Range<GID_TYPE, FD_TYPE> *range = (FDSelect3_4_Range<GID_TYPE, FD_TYPE> *) _item;
261
262
0
    if (glyph < range[0].first) return -1;
263
0
    if (glyph < range[1].first) return 0;
264
0
    return +1;
265
0
  }
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned short, 2u>, OT::NumType<true, unsigned char, 1u> >::_cmp_range(void const*, void const*)
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned int, 4u>, OT::NumType<true, unsigned short, 2u> >::_cmp_range(void const*, void const*)
266
267
  unsigned get_fd (hb_codepoint_t glyph) const
268
0
  {
269
0
    auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
270
0
    return range ? range->fd : ranges[nRanges () - 1].fd;
271
0
  }
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned short, 2u>, OT::NumType<true, unsigned char, 1u> >::get_fd(unsigned int) const
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned int, 4u>, OT::NumType<true, unsigned short, 2u> >::get_fd(unsigned int) const
272
273
  hb_pair_t<unsigned, hb_codepoint_t> get_fd_range (hb_codepoint_t glyph) const
274
0
  {
275
0
    auto *range = hb_bsearch (glyph, &ranges[0], nRanges () - 1, sizeof (ranges[0]), _cmp_range);
276
0
    unsigned fd = range ? range->fd : ranges[nRanges () - 1].fd;
277
0
    hb_codepoint_t end = range ? range[1].first : ranges[nRanges () - 1].first;
278
0
    return {fd, end};
279
0
  }
280
281
  GID_TYPE        &nRanges ()       { return ranges.len; }
282
0
  GID_TYPE         nRanges () const { return ranges.len; }
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned short, 2u>, OT::NumType<true, unsigned char, 1u> >::nRanges() const
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned int, 4u>, OT::NumType<true, unsigned short, 2u> >::nRanges() const
283
  GID_TYPE       &sentinel ()       { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
284
0
  const GID_TYPE &sentinel () const { return StructAfter<GID_TYPE> (ranges[nRanges () - 1]); }
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned short, 2u>, OT::NumType<true, unsigned char, 1u> >::sentinel() const
Unexecuted instantiation: CFF::FDSelect3_4<OT::NumType<true, unsigned int, 4u>, OT::NumType<true, unsigned short, 2u> >::sentinel() const
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
0
  {
299
0
    TRACE_SERIALIZE (this);
300
0
    unsigned int size = src.get_size (num_glyphs);
301
0
    FDSelect *dest = c->allocate_size<FDSelect> (size, false);
302
0
    if (unlikely (!dest)) return_trace (false);
303
0
    hb_memcpy (dest, &src, size);
304
0
    return_trace (true);
305
0
  }
306
307
  unsigned int get_size (unsigned int num_glyphs) const
308
0
  {
309
0
    switch (format)
310
0
    {
311
0
    case 0: hb_barrier (); return format.static_size + u.format0.get_size (num_glyphs);
312
0
    case 3: hb_barrier (); return format.static_size + u.format3.get_size ();
313
0
    default:return 0;
314
0
    }
315
0
  }
316
317
  unsigned get_fd (hb_codepoint_t glyph) const
318
0
  {
319
0
    if (this == &Null (FDSelect)) return 0;
320
321
0
    switch (format)
322
0
    {
323
0
    case 0: hb_barrier (); return u.format0.get_fd (glyph);
324
0
    case 3: hb_barrier (); return u.format3.get_fd (glyph);
325
0
    default:return 0;
326
0
    }
327
0
  }
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
0
  {
331
0
    if (this == &Null (FDSelect)) return {0, 1};
332
0
333
0
    switch (format)
334
0
    {
335
0
    case 0: hb_barrier (); return u.format0.get_fd_range (glyph);
336
0
    case 3: hb_barrier (); return u.format3.get_fd_range (glyph);
337
0
    default:return {0, 1};
338
0
    }
339
0
  }
340
341
  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
342
0
  {
343
0
    TRACE_SANITIZE (this);
344
0
    if (unlikely (!c->check_struct (this)))
345
0
      return_trace (false);
346
0
    hb_barrier ();
347
348
0
    switch (format)
349
0
    {
350
0
    case 0: hb_barrier (); return_trace (u.format0.sanitize (c, fdcount));
351
0
    case 3: hb_barrier (); return_trace (u.format3.sanitize (c, fdcount));
352
0
    default:return_trace (false);
353
0
    }
354
0
  }
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 */