Coverage Report

Created: 2023-05-18 19:03

/src/harfbuzz/src/hb-aat-layout-common.hh
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright © 2017  Google, 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
 * Google Author(s): Behdad Esfahbod
25
 */
26
27
#ifndef HB_AAT_LAYOUT_COMMON_HH
28
#define HB_AAT_LAYOUT_COMMON_HH
29
30
#include "hb-aat-layout.hh"
31
#include "hb-aat-map.hh"
32
#include "hb-open-type.hh"
33
34
namespace OT {
35
struct GDEF;
36
};
37
38
namespace AAT {
39
40
using namespace OT;
41
42
43
struct ankr;
44
45
struct hb_aat_apply_context_t :
46
       hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY>
47
{
48
0
  const char *get_name () { return "APPLY"; }
49
  template <typename T>
50
22.6k
  return_t dispatch (const T &obj) { return obj.apply (this); }
bool AAT::hb_aat_apply_context_t::dispatch<AAT::RearrangementSubtable<AAT::ExtendedTypes> >(AAT::RearrangementSubtable<AAT::ExtendedTypes> const&)
Line
Count
Source
50
2.16k
  return_t dispatch (const T &obj) { return obj.apply (this); }
bool AAT::hb_aat_apply_context_t::dispatch<AAT::ContextualSubtable<AAT::ExtendedTypes> >(AAT::ContextualSubtable<AAT::ExtendedTypes> const&)
Line
Count
Source
50
4.46k
  return_t dispatch (const T &obj) { return obj.apply (this); }
bool AAT::hb_aat_apply_context_t::dispatch<AAT::LigatureSubtable<AAT::ExtendedTypes> >(AAT::LigatureSubtable<AAT::ExtendedTypes> const&)
Line
Count
Source
50
2.16k
  return_t dispatch (const T &obj) { return obj.apply (this); }
bool AAT::hb_aat_apply_context_t::dispatch<AAT::NoncontextualSubtable<AAT::ExtendedTypes> >(AAT::NoncontextualSubtable<AAT::ExtendedTypes> const&)
Line
Count
Source
50
460
  return_t dispatch (const T &obj) { return obj.apply (this); }
bool AAT::hb_aat_apply_context_t::dispatch<AAT::InsertionSubtable<AAT::ExtendedTypes> >(AAT::InsertionSubtable<AAT::ExtendedTypes> const&)
Line
Count
Source
50
7.42k
  return_t dispatch (const T &obj) { return obj.apply (this); }
bool AAT::hb_aat_apply_context_t::dispatch<AAT::RearrangementSubtable<AAT::ObsoleteTypes> >(AAT::RearrangementSubtable<AAT::ObsoleteTypes> const&)
Line
Count
Source
50
120
  return_t dispatch (const T &obj) { return obj.apply (this); }
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::ContextualSubtable<AAT::ObsoleteTypes> >(AAT::ContextualSubtable<AAT::ObsoleteTypes> const&)
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::LigatureSubtable<AAT::ObsoleteTypes> >(AAT::LigatureSubtable<AAT::ObsoleteTypes> const&)
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::NoncontextualSubtable<AAT::ObsoleteTypes> >(AAT::NoncontextualSubtable<AAT::ObsoleteTypes> const&)
bool AAT::hb_aat_apply_context_t::dispatch<AAT::InsertionSubtable<AAT::ObsoleteTypes> >(AAT::InsertionSubtable<AAT::ObsoleteTypes> const&)
Line
Count
Source
50
60
  return_t dispatch (const T &obj) { return obj.apply (this); }
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat0<AAT::KerxSubTableHeader> >(AAT::KerxSubTableFormat0<AAT::KerxSubTableHeader> const&)
bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat1<AAT::KerxSubTableHeader> >(AAT::KerxSubTableFormat1<AAT::KerxSubTableHeader> const&)
Line
Count
Source
50
60
  return_t dispatch (const T &obj) { return obj.apply (this); }
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat2<AAT::KerxSubTableHeader> >(AAT::KerxSubTableFormat2<AAT::KerxSubTableHeader> const&)
bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader> >(AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader> const&)
Line
Count
Source
50
300
  return_t dispatch (const T &obj) { return obj.apply (this); }
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat6<AAT::KerxSubTableHeader> >(AAT::KerxSubTableFormat6<AAT::KerxSubTableHeader> const&)
bool AAT::hb_aat_apply_context_t::dispatch<OT::KernOT>(OT::KernOT const&)
Line
Count
Source
50
2.10k
  return_t dispatch (const T &obj) { return obj.apply (this); }
bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat0<OT::KernOTSubTableHeader> >(AAT::KerxSubTableFormat0<OT::KernOTSubTableHeader> const&)
Line
Count
Source
50
1.68k
  return_t dispatch (const T &obj) { return obj.apply (this); }
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat1<OT::KernOTSubTableHeader> >(AAT::KerxSubTableFormat1<OT::KernOTSubTableHeader> const&)
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat2<OT::KernOTSubTableHeader> >(AAT::KerxSubTableFormat2<OT::KernOTSubTableHeader> const&)
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<OT::KernSubTableFormat3<OT::KernOTSubTableHeader> >(OT::KernSubTableFormat3<OT::KernOTSubTableHeader> const&)
bool AAT::hb_aat_apply_context_t::dispatch<OT::KernAAT>(OT::KernAAT const&)
Line
Count
Source
50
420
  return_t dispatch (const T &obj) { return obj.apply (this); }
bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat0<OT::KernAATSubTableHeader> >(AAT::KerxSubTableFormat0<OT::KernAATSubTableHeader> const&)
Line
Count
Source
50
420
  return_t dispatch (const T &obj) { return obj.apply (this); }
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat1<OT::KernAATSubTableHeader> >(AAT::KerxSubTableFormat1<OT::KernAATSubTableHeader> const&)
bool AAT::hb_aat_apply_context_t::dispatch<AAT::KerxSubTableFormat2<OT::KernAATSubTableHeader> >(AAT::KerxSubTableFormat2<OT::KernAATSubTableHeader> const&)
Line
Count
Source
50
840
  return_t dispatch (const T &obj) { return obj.apply (this); }
Unexecuted instantiation: bool AAT::hb_aat_apply_context_t::dispatch<OT::KernSubTableFormat3<OT::KernAATSubTableHeader> >(OT::KernSubTableFormat3<OT::KernAATSubTableHeader> const&)
51
540
  static return_t default_return_value () { return false; }
52
0
  bool stop_sublookup_iteration (return_t r) const { return r; }
53
54
  const hb_ot_shape_plan_t *plan;
55
  hb_font_t *font;
56
  hb_face_t *face;
57
  hb_buffer_t *buffer;
58
  hb_sanitize_context_t sanitizer;
59
  const ankr *ankr_table;
60
  const OT::GDEF *gdef_table;
61
  const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
62
  hb_mask_t subtable_flags = 0;
63
64
  /* Unused. For debug tracing only. */
65
  unsigned int lookup_index;
66
67
  HB_INTERNAL hb_aat_apply_context_t (const hb_ot_shape_plan_t *plan_,
68
              hb_font_t *font_,
69
              hb_buffer_t *buffer_,
70
              hb_blob_t *blob = const_cast<hb_blob_t *> (&Null (hb_blob_t)));
71
72
  HB_INTERNAL ~hb_aat_apply_context_t ();
73
74
  HB_INTERNAL void set_ankr_table (const AAT::ankr *ankr_table_);
75
76
35.4k
  void set_lookup_index (unsigned int i) { lookup_index = i; }
77
};
78
79
80
/*
81
 * Lookup Table
82
 */
83
84
template <typename T> struct Lookup;
85
86
template <typename T>
87
struct LookupFormat0
88
{
89
  friend struct Lookup<T>;
90
91
  private:
92
  const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
93
6.48k
  {
94
6.48k
    if (unlikely (glyph_id >= num_glyphs)) return nullptr;
95
5.40k
    return &arrayZ[glyph_id];
96
6.48k
  }
AAT::LookupFormat0<OT::IntType<unsigned short, 2u> >::get_value(unsigned int, unsigned int) const
Line
Count
Source
93
6.48k
  {
94
6.48k
    if (unlikely (glyph_id >= num_glyphs)) return nullptr;
95
5.40k
    return &arrayZ[glyph_id];
96
6.48k
  }
Unexecuted instantiation: AAT::LookupFormat0<OT::HBGlyphID16>::get_value(unsigned int, unsigned int) const
Unexecuted instantiation: AAT::LookupFormat0<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::get_value(unsigned int, unsigned int) const
Unexecuted instantiation: AAT::LookupFormat0<OT::IntType<unsigned int, 4u> >::get_value(unsigned int, unsigned int) const
Unexecuted instantiation: AAT::LookupFormat0<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::get_value(unsigned int, unsigned int) const
97
98
  bool sanitize (hb_sanitize_context_t *c) const
99
180
  {
100
180
    TRACE_SANITIZE (this);
101
180
    return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
102
180
  }
AAT::LookupFormat0<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
99
160
  {
100
160
    TRACE_SANITIZE (this);
101
160
    return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
102
160
  }
AAT::LookupFormat0<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
99
20
  {
100
20
    TRACE_SANITIZE (this);
101
20
    return_trace (arrayZ.sanitize (c, c->get_num_glyphs ()));
102
20
  }
Unexecuted instantiation: AAT::LookupFormat0<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
103
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
104
40
  {
105
40
    TRACE_SANITIZE (this);
106
40
    return_trace (arrayZ.sanitize (c, c->get_num_glyphs (), base));
107
40
  }
AAT::LookupFormat0<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize(hb_sanitize_context_t*, void const*) const
Line
Count
Source
104
40
  {
105
40
    TRACE_SANITIZE (this);
106
40
    return_trace (arrayZ.sanitize (c, c->get_num_glyphs (), base));
107
40
  }
Unexecuted instantiation: AAT::LookupFormat0<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat0<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
108
109
  protected:
110
  HBUINT16  format;   /* Format identifier--format = 0 */
111
  UnsizedArrayOf<T>
112
    arrayZ;   /* Array of lookup values, indexed by glyph index. */
113
  public:
114
  DEFINE_SIZE_UNBOUNDED (2);
115
};
116
117
118
template <typename T>
119
struct LookupSegmentSingle
120
{
121
  static constexpr unsigned TerminationWordCount = 2u;
122
123
  int cmp (hb_codepoint_t g) const
124
4.32k
  { return g < first ? -1 : g <= last ? 0 : +1 ; }
AAT::LookupSegmentSingle<OT::IntType<unsigned short, 2u> >::cmp(unsigned int) const
Line
Count
Source
124
4.32k
  { return g < first ? -1 : g <= last ? 0 : +1 ; }
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::HBGlyphID16>::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::IntType<unsigned int, 4u> >::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::cmp(unsigned int) const
125
126
  bool sanitize (hb_sanitize_context_t *c) const
127
0
  {
128
0
    TRACE_SANITIZE (this);
129
0
    return_trace (c->check_struct (this) && value.sanitize (c));
130
0
  }
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
131
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
132
0
  {
133
0
    TRACE_SANITIZE (this);
134
0
    return_trace (c->check_struct (this) && value.sanitize (c, base));
135
0
  }
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupSegmentSingle<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
136
137
  HBGlyphID16 last;   /* Last GlyphID in this segment */
138
  HBGlyphID16 first;    /* First GlyphID in this segment */
139
  T   value;    /* The lookup value (only one) */
140
  public:
141
  DEFINE_SIZE_STATIC (4 + T::static_size);
142
};
143
144
template <typename T>
145
struct LookupFormat2
146
{
147
  friend struct Lookup<T>;
148
149
  private:
150
  const T* get_value (hb_codepoint_t glyph_id) const
151
2.16k
  {
152
2.16k
    const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
153
2.16k
    return v ? &v->value : nullptr;
154
2.16k
  }
AAT::LookupFormat2<OT::IntType<unsigned short, 2u> >::get_value(unsigned int) const
Line
Count
Source
151
2.16k
  {
152
2.16k
    const LookupSegmentSingle<T> *v = segments.bsearch (glyph_id);
153
2.16k
    return v ? &v->value : nullptr;
154
2.16k
  }
Unexecuted instantiation: AAT::LookupFormat2<OT::HBGlyphID16>::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat2<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat2<OT::IntType<unsigned int, 4u> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat2<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::get_value(unsigned int) const
155
156
  bool sanitize (hb_sanitize_context_t *c) const
157
60
  {
158
60
    TRACE_SANITIZE (this);
159
60
    return_trace (segments.sanitize (c));
160
60
  }
AAT::LookupFormat2<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
157
60
  {
158
60
    TRACE_SANITIZE (this);
159
60
    return_trace (segments.sanitize (c));
160
60
  }
Unexecuted instantiation: AAT::LookupFormat2<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupFormat2<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
161
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
162
0
  {
163
0
    TRACE_SANITIZE (this);
164
0
    return_trace (segments.sanitize (c, base));
165
0
  }
Unexecuted instantiation: AAT::LookupFormat2<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat2<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat2<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
166
167
  protected:
168
  HBUINT16  format;   /* Format identifier--format = 2 */
169
  VarSizedBinSearchArrayOf<LookupSegmentSingle<T>>
170
    segments; /* The actual segments. These must already be sorted,
171
         * according to the first word in each one (the last
172
         * glyph in each segment). */
173
  public:
174
  DEFINE_SIZE_ARRAY (8, segments);
175
};
176
177
template <typename T>
178
struct LookupSegmentArray
179
{
180
  static constexpr unsigned TerminationWordCount = 2u;
181
182
  const T* get_value (hb_codepoint_t glyph_id, const void *base) const
183
0
  {
184
0
    return first <= glyph_id && glyph_id <= last ? &(base+valuesZ)[glyph_id - first] : nullptr;
185
0
  }
Unexecuted instantiation: AAT::LookupSegmentArray<OT::IntType<unsigned short, 2u> >::get_value(unsigned int, void const*) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::HBGlyphID16>::get_value(unsigned int, void const*) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::get_value(unsigned int, void const*) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::IntType<unsigned int, 4u> >::get_value(unsigned int, void const*) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::get_value(unsigned int, void const*) const
186
187
  int cmp (hb_codepoint_t g) const
188
0
  { return g < first ? -1 : g <= last ? 0 : +1; }
Unexecuted instantiation: AAT::LookupSegmentArray<OT::IntType<unsigned short, 2u> >::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::HBGlyphID16>::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::IntType<unsigned int, 4u> >::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::cmp(unsigned int) const
189
190
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
191
0
  {
192
0
    TRACE_SANITIZE (this);
193
0
    return_trace (c->check_struct (this) &&
194
0
      first <= last &&
195
0
      valuesZ.sanitize (c, base, last - first + 1));
196
0
  }
Unexecuted instantiation: AAT::LookupSegmentArray<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupSegmentArray<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*, void const*) const
197
  template <typename ...Ts>
198
  bool sanitize (hb_sanitize_context_t *c, const void *base, Ts&&... ds) const
199
0
  {
200
0
    TRACE_SANITIZE (this);
201
0
    return_trace (c->check_struct (this) &&
202
0
      first <= last &&
203
0
      valuesZ.sanitize (c, base, last - first + 1, std::forward<Ts> (ds)...));
204
0
  }
Unexecuted instantiation: bool AAT::LookupSegmentArray<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize<void const*&>(hb_sanitize_context_t*, void const*, void const*&) const
Unexecuted instantiation: bool AAT::LookupSegmentArray<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize<void const*&>(hb_sanitize_context_t*, void const*, void const*&) const
Unexecuted instantiation: bool AAT::LookupSegmentArray<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize<void const*&>(hb_sanitize_context_t*, void const*, void const*&) const
205
206
  HBGlyphID16 last;   /* Last GlyphID in this segment */
207
  HBGlyphID16 first;    /* First GlyphID in this segment */
208
  NNOffset16To<UnsizedArrayOf<T>>
209
    valuesZ;  /* A 16-bit offset from the start of
210
         * the table to the data. */
211
  public:
212
  DEFINE_SIZE_STATIC (6);
213
};
214
215
template <typename T>
216
struct LookupFormat4
217
{
218
  friend struct Lookup<T>;
219
220
  private:
221
  const T* get_value (hb_codepoint_t glyph_id) const
222
0
  {
223
0
    const LookupSegmentArray<T> *v = segments.bsearch (glyph_id);
224
0
    return v ? v->get_value (glyph_id, this) : nullptr;
225
0
  }
Unexecuted instantiation: AAT::LookupFormat4<OT::IntType<unsigned short, 2u> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat4<OT::HBGlyphID16>::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat4<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat4<OT::IntType<unsigned int, 4u> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat4<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::get_value(unsigned int) const
226
227
  bool sanitize (hb_sanitize_context_t *c) const
228
0
  {
229
0
    TRACE_SANITIZE (this);
230
0
    return_trace (segments.sanitize (c, this));
231
0
  }
Unexecuted instantiation: AAT::LookupFormat4<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupFormat4<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupFormat4<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
232
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
233
0
  {
234
0
    TRACE_SANITIZE (this);
235
0
    return_trace (segments.sanitize (c, this, base));
236
0
  }
Unexecuted instantiation: AAT::LookupFormat4<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat4<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat4<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
237
238
  protected:
239
  HBUINT16  format;   /* Format identifier--format = 4 */
240
  VarSizedBinSearchArrayOf<LookupSegmentArray<T>>
241
    segments; /* The actual segments. These must already be sorted,
242
         * according to the first word in each one (the last
243
         * glyph in each segment). */
244
  public:
245
  DEFINE_SIZE_ARRAY (8, segments);
246
};
247
248
template <typename T>
249
struct LookupSingle
250
{
251
  static constexpr unsigned TerminationWordCount = 1u;
252
253
45.8k
  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
AAT::LookupSingle<OT::IntType<unsigned short, 2u> >::cmp(unsigned int) const
Line
Count
Source
253
43.6k
  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
AAT::LookupSingle<OT::HBGlyphID16>::cmp(unsigned int) const
Line
Count
Source
253
2.14k
  int cmp (hb_codepoint_t g) const { return glyph.cmp (g); }
Unexecuted instantiation: AAT::LookupSingle<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSingle<OT::IntType<unsigned int, 4u> >::cmp(unsigned int) const
Unexecuted instantiation: AAT::LookupSingle<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::cmp(unsigned int) const
254
255
  bool sanitize (hb_sanitize_context_t *c) const
256
0
  {
257
0
    TRACE_SANITIZE (this);
258
0
    return_trace (c->check_struct (this) && value.sanitize (c));
259
0
  }
Unexecuted instantiation: AAT::LookupSingle<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupSingle<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupSingle<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
260
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
261
0
  {
262
0
    TRACE_SANITIZE (this);
263
0
    return_trace (c->check_struct (this) && value.sanitize (c, base));
264
0
  }
Unexecuted instantiation: AAT::LookupSingle<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupSingle<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupSingle<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
265
266
  HBGlyphID16 glyph;    /* Last GlyphID */
267
  T   value;    /* The lookup value (only one) */
268
  public:
269
  DEFINE_SIZE_STATIC (2 + T::static_size);
270
};
271
272
template <typename T>
273
struct LookupFormat6
274
{
275
  friend struct Lookup<T>;
276
277
  private:
278
  const T* get_value (hb_codepoint_t glyph_id) const
279
18.1k
  {
280
18.1k
    const LookupSingle<T> *v = entries.bsearch (glyph_id);
281
18.1k
    return v ? &v->value : nullptr;
282
18.1k
  }
AAT::LookupFormat6<OT::IntType<unsigned short, 2u> >::get_value(unsigned int) const
Line
Count
Source
279
16.2k
  {
280
16.2k
    const LookupSingle<T> *v = entries.bsearch (glyph_id);
281
16.2k
    return v ? &v->value : nullptr;
282
16.2k
  }
AAT::LookupFormat6<OT::HBGlyphID16>::get_value(unsigned int) const
Line
Count
Source
279
1.94k
  {
280
1.94k
    const LookupSingle<T> *v = entries.bsearch (glyph_id);
281
1.94k
    return v ? &v->value : nullptr;
282
1.94k
  }
Unexecuted instantiation: AAT::LookupFormat6<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat6<OT::IntType<unsigned int, 4u> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat6<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::get_value(unsigned int) const
283
284
  bool sanitize (hb_sanitize_context_t *c) const
285
440
  {
286
440
    TRACE_SANITIZE (this);
287
440
    return_trace (entries.sanitize (c));
288
440
  }
AAT::LookupFormat6<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
285
320
  {
286
320
    TRACE_SANITIZE (this);
287
320
    return_trace (entries.sanitize (c));
288
320
  }
AAT::LookupFormat6<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
285
120
  {
286
120
    TRACE_SANITIZE (this);
287
120
    return_trace (entries.sanitize (c));
288
120
  }
Unexecuted instantiation: AAT::LookupFormat6<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
289
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
290
0
  {
291
0
    TRACE_SANITIZE (this);
292
0
    return_trace (entries.sanitize (c, base));
293
0
  }
Unexecuted instantiation: AAT::LookupFormat6<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat6<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat6<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
294
295
  protected:
296
  HBUINT16  format;   /* Format identifier--format = 6 */
297
  VarSizedBinSearchArrayOf<LookupSingle<T>>
298
    entries;  /* The actual entries, sorted by glyph index. */
299
  public:
300
  DEFINE_SIZE_ARRAY (8, entries);
301
};
302
303
template <typename T>
304
struct LookupFormat8
305
{
306
  friend struct Lookup<T>;
307
308
  private:
309
  const T* get_value (hb_codepoint_t glyph_id) const
310
2.19M
  {
311
2.19M
    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ?
312
2.15M
     &valueArrayZ[glyph_id - firstGlyph] : nullptr;
313
2.19M
  }
AAT::LookupFormat8<OT::IntType<unsigned short, 2u> >::get_value(unsigned int) const
Line
Count
Source
310
1.47M
  {
311
1.47M
    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ?
312
1.43M
     &valueArrayZ[glyph_id - firstGlyph] : nullptr;
313
1.47M
  }
AAT::LookupFormat8<OT::HBGlyphID16>::get_value(unsigned int) const
Line
Count
Source
310
718k
  {
311
718k
    return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ?
312
717k
     &valueArrayZ[glyph_id - firstGlyph] : nullptr;
313
718k
  }
Unexecuted instantiation: AAT::LookupFormat8<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat8<OT::IntType<unsigned int, 4u> >::get_value(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat8<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::get_value(unsigned int) const
314
315
  bool sanitize (hb_sanitize_context_t *c) const
316
1.16k
  {
317
1.16k
    TRACE_SANITIZE (this);
318
1.16k
    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
319
1.16k
  }
AAT::LookupFormat8<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
316
900
  {
317
900
    TRACE_SANITIZE (this);
318
900
    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
319
900
  }
AAT::LookupFormat8<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
316
260
  {
317
260
    TRACE_SANITIZE (this);
318
260
    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount));
319
260
  }
Unexecuted instantiation: AAT::LookupFormat8<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
320
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
321
0
  {
322
0
    TRACE_SANITIZE (this);
323
0
    return_trace (c->check_struct (this) && valueArrayZ.sanitize (c, glyphCount, base));
324
0
  }
Unexecuted instantiation: AAT::LookupFormat8<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat8<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::LookupFormat8<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
325
326
  protected:
327
  HBUINT16  format;   /* Format identifier--format = 8 */
328
  HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
329
  HBUINT16  glyphCount; /* Total number of glyphs (equivalent to the last
330
         * glyph minus the value of firstGlyph plus 1). */
331
  UnsizedArrayOf<T>
332
    valueArrayZ;  /* The lookup values (indexed by the glyph index
333
         * minus the value of firstGlyph). */
334
  public:
335
  DEFINE_SIZE_ARRAY (6, valueArrayZ);
336
};
337
338
template <typename T>
339
struct LookupFormat10
340
{
341
  friend struct Lookup<T>;
342
343
  private:
344
  const typename T::type get_value_or_null (hb_codepoint_t glyph_id) const
345
0
  {
346
0
    if (!(firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount))
347
0
      return Null (T);
348
349
0
    const HBUINT8 *p = &valueArrayZ[(glyph_id - firstGlyph) * valueSize];
350
351
0
    unsigned int v = 0;
352
0
    unsigned int count = valueSize;
353
0
    for (unsigned int i = 0; i < count; i++)
354
0
      v = (v << 8) | *p++;
355
356
0
    return v;
357
0
  }
Unexecuted instantiation: AAT::LookupFormat10<OT::IntType<unsigned int, 4u> >::get_value_or_null(unsigned int) const
Unexecuted instantiation: AAT::LookupFormat10<OT::IntType<unsigned short, 2u> >::get_value_or_null(unsigned int) const
358
359
  bool sanitize (hb_sanitize_context_t *c) const
360
0
  {
361
0
    TRACE_SANITIZE (this);
362
0
    return_trace (c->check_struct (this) &&
363
0
      valueSize <= 4 &&
364
0
      valueArrayZ.sanitize (c, glyphCount * valueSize));
365
0
  }
Unexecuted instantiation: AAT::LookupFormat10<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupFormat10<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Unexecuted instantiation: AAT::LookupFormat10<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
366
367
  protected:
368
  HBUINT16  format;   /* Format identifier--format = 8 */
369
  HBUINT16  valueSize;  /* Byte size of each value. */
370
  HBGlyphID16 firstGlyph; /* First glyph index included in the trimmed array. */
371
  HBUINT16  glyphCount; /* Total number of glyphs (equivalent to the last
372
         * glyph minus the value of firstGlyph plus 1). */
373
  UnsizedArrayOf<HBUINT8>
374
    valueArrayZ;  /* The lookup values (indexed by the glyph index
375
         * minus the value of firstGlyph). */
376
  public:
377
  DEFINE_SIZE_ARRAY (8, valueArrayZ);
378
};
379
380
template <typename T>
381
struct Lookup
382
{
383
  const T* get_value (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
384
2.22M
  {
385
2.22M
    switch (u.format) {
386
6.48k
    case 0: return u.format0.get_value (glyph_id, num_glyphs);
387
2.16k
    case 2: return u.format2.get_value (glyph_id);
388
0
    case 4: return u.format4.get_value (glyph_id);
389
18.1k
    case 6: return u.format6.get_value (glyph_id);
390
2.19M
    case 8: return u.format8.get_value (glyph_id);
391
6.12k
    default:return nullptr;
392
2.22M
    }
393
2.22M
  }
AAT::Lookup<OT::IntType<unsigned short, 2u> >::get_value(unsigned int, unsigned int) const
Line
Count
Source
384
1.49M
  {
385
1.49M
    switch (u.format) {
386
6.48k
    case 0: return u.format0.get_value (glyph_id, num_glyphs);
387
2.16k
    case 2: return u.format2.get_value (glyph_id);
388
0
    case 4: return u.format4.get_value (glyph_id);
389
16.2k
    case 6: return u.format6.get_value (glyph_id);
390
1.47M
    case 8: return u.format8.get_value (glyph_id);
391
0
    default:return nullptr;
392
1.49M
    }
393
1.49M
  }
AAT::Lookup<OT::HBGlyphID16>::get_value(unsigned int, unsigned int) const
Line
Count
Source
384
719k
  {
385
719k
    switch (u.format) {
386
0
    case 0: return u.format0.get_value (glyph_id, num_glyphs);
387
0
    case 2: return u.format2.get_value (glyph_id);
388
0
    case 4: return u.format4.get_value (glyph_id);
389
1.94k
    case 6: return u.format6.get_value (glyph_id);
390
718k
    case 8: return u.format8.get_value (glyph_id);
391
0
    default:return nullptr;
392
719k
    }
393
719k
  }
AAT::Lookup<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::get_value(unsigned int, unsigned int) const
Line
Count
Source
384
6.12k
  {
385
6.12k
    switch (u.format) {
386
0
    case 0: return u.format0.get_value (glyph_id, num_glyphs);
387
0
    case 2: return u.format2.get_value (glyph_id);
388
0
    case 4: return u.format4.get_value (glyph_id);
389
0
    case 6: return u.format6.get_value (glyph_id);
390
0
    case 8: return u.format8.get_value (glyph_id);
391
6.12k
    default:return nullptr;
392
6.12k
    }
393
6.12k
  }
Unexecuted instantiation: AAT::Lookup<OT::IntType<unsigned int, 4u> >::get_value(unsigned int, unsigned int) const
Unexecuted instantiation: AAT::Lookup<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::get_value(unsigned int, unsigned int) const
394
395
  const typename T::type get_value_or_null (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
396
0
  {
397
0
    switch (u.format) {
398
      /* Format 10 cannot return a pointer. */
399
0
      case 10: return u.format10.get_value_or_null (glyph_id);
400
0
      default:
401
0
      const T *v = get_value (glyph_id, num_glyphs);
402
0
      return v ? *v : Null (T);
403
0
    }
404
0
  }
Unexecuted instantiation: AAT::Lookup<OT::IntType<unsigned int, 4u> >::get_value_or_null(unsigned int, unsigned int) const
Unexecuted instantiation: AAT::Lookup<OT::IntType<unsigned short, 2u> >::get_value_or_null(unsigned int, unsigned int) const
405
406
  typename T::type get_class (hb_codepoint_t glyph_id,
407
            unsigned int num_glyphs,
408
            unsigned int outOfRange) const
409
1.49M
  {
410
1.49M
    const T *v = get_value (glyph_id, num_glyphs);
411
1.49M
    return v ? *v : outOfRange;
412
1.49M
  }
413
414
  bool sanitize (hb_sanitize_context_t *c) const
415
1.92k
  {
416
1.92k
    TRACE_SANITIZE (this);
417
1.92k
    if (!u.format.sanitize (c)) return_trace (false);
418
1.90k
    switch (u.format) {
419
180
    case 0: return_trace (u.format0.sanitize (c));
420
60
    case 2: return_trace (u.format2.sanitize (c));
421
0
    case 4: return_trace (u.format4.sanitize (c));
422
440
    case 6: return_trace (u.format6.sanitize (c));
423
1.16k
    case 8: return_trace (u.format8.sanitize (c));
424
0
    case 10: return_trace (u.format10.sanitize (c));
425
60
    default:return_trace (true);
426
1.90k
    }
427
1.90k
  }
AAT::Lookup<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
415
1.52k
  {
416
1.52k
    TRACE_SANITIZE (this);
417
1.52k
    if (!u.format.sanitize (c)) return_trace (false);
418
1.50k
    switch (u.format) {
419
160
    case 0: return_trace (u.format0.sanitize (c));
420
60
    case 2: return_trace (u.format2.sanitize (c));
421
0
    case 4: return_trace (u.format4.sanitize (c));
422
320
    case 6: return_trace (u.format6.sanitize (c));
423
900
    case 8: return_trace (u.format8.sanitize (c));
424
0
    case 10: return_trace (u.format10.sanitize (c));
425
60
    default:return_trace (true);
426
1.50k
    }
427
1.50k
  }
AAT::Lookup<OT::HBGlyphID16>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
415
400
  {
416
400
    TRACE_SANITIZE (this);
417
400
    if (!u.format.sanitize (c)) return_trace (false);
418
400
    switch (u.format) {
419
20
    case 0: return_trace (u.format0.sanitize (c));
420
0
    case 2: return_trace (u.format2.sanitize (c));
421
0
    case 4: return_trace (u.format4.sanitize (c));
422
120
    case 6: return_trace (u.format6.sanitize (c));
423
260
    case 8: return_trace (u.format8.sanitize (c));
424
0
    case 10: return_trace (u.format10.sanitize (c));
425
0
    default:return_trace (true);
426
400
    }
427
400
  }
Unexecuted instantiation: AAT::Lookup<OT::IntType<unsigned int, 4u> >::sanitize(hb_sanitize_context_t*) const
428
  bool sanitize (hb_sanitize_context_t *c, const void *base) const
429
40
  {
430
40
    TRACE_SANITIZE (this);
431
40
    if (!u.format.sanitize (c)) return_trace (false);
432
40
    switch (u.format) {
433
40
    case 0: return_trace (u.format0.sanitize (c, base));
434
0
    case 2: return_trace (u.format2.sanitize (c, base));
435
0
    case 4: return_trace (u.format4.sanitize (c, base));
436
0
    case 6: return_trace (u.format6.sanitize (c, base));
437
0
    case 8: return_trace (u.format8.sanitize (c, base));
438
0
    case 10: return_trace (false); /* We don't support format10 here currently. */
439
0
    default:return_trace (true);
440
40
    }
441
40
  }
AAT::Lookup<OT::OffsetTo<OT::ArrayOf<AAT::Anchor, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, false> >::sanitize(hb_sanitize_context_t*, void const*) const
Line
Count
Source
429
40
  {
430
40
    TRACE_SANITIZE (this);
431
40
    if (!u.format.sanitize (c)) return_trace (false);
432
40
    switch (u.format) {
433
40
    case 0: return_trace (u.format0.sanitize (c, base));
434
0
    case 2: return_trace (u.format2.sanitize (c, base));
435
0
    case 4: return_trace (u.format4.sanitize (c, base));
436
0
    case 6: return_trace (u.format6.sanitize (c, base));
437
0
    case 8: return_trace (u.format8.sanitize (c, base));
438
0
    case 10: return_trace (false); /* We don't support format10 here currently. */
439
0
    default:return_trace (true);
440
40
    }
441
40
  }
Unexecuted instantiation: AAT::Lookup<OT::OffsetTo<OT::ArrayOf<AAT::WidthDeltaPair, OT::IntType<unsigned int, 4u> >, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
Unexecuted instantiation: AAT::Lookup<OT::OffsetTo<AAT::OpticalBounds, OT::IntType<unsigned short, 2u>, true> >::sanitize(hb_sanitize_context_t*, void const*) const
442
443
  protected:
444
  union {
445
  HBUINT16    format;   /* Format identifier */
446
  LookupFormat0<T>  format0;
447
  LookupFormat2<T>  format2;
448
  LookupFormat4<T>  format4;
449
  LookupFormat6<T>  format6;
450
  LookupFormat8<T>  format8;
451
  LookupFormat10<T> format10;
452
  } u;
453
  public:
454
  DEFINE_SIZE_UNION (2, format);
455
};
456
DECLARE_NULL_NAMESPACE_BYTES_TEMPLATE1 (AAT, Lookup, 2);
457
458
enum { DELETED_GLYPH = 0xFFFF };
459
460
/*
461
 * (Extended) State Table
462
 */
463
464
template <typename T>
465
struct Entry
466
{
467
  bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
468
  {
469
    TRACE_SANITIZE (this);
470
    /* Note, we don't recurse-sanitize data because we don't access it.
471
     * That said, in our DEFINE_SIZE_STATIC we access T::static_size,
472
     * which ensures that data has a simple sanitize(). To be determined
473
     * if I need to remove that as well.
474
     *
475
     * HOWEVER! Because we are a template, our DEFINE_SIZE_STATIC
476
     * assertion wouldn't be checked, hence the line below. */
477
    static_assert (T::static_size, "");
478
479
    return_trace (c->check_struct (this));
480
  }
481
482
  public:
483
  HBUINT16  newState; /* Byte offset from beginning of state table
484
         * to the new state. Really?!?! Or just state
485
         * number?  The latter in morx for sure. */
486
  HBUINT16  flags;    /* Table specific. */
487
  T   data;   /* Optional offsets to per-glyph tables. */
488
  public:
489
  DEFINE_SIZE_STATIC (4 + T::static_size);
490
};
491
492
template <>
493
struct Entry<void>
494
{
495
  bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
496
0
  {
497
0
    TRACE_SANITIZE (this);
498
0
    return_trace (c->check_struct (this));
499
0
  }
500
501
  public:
502
  HBUINT16  newState; /* Byte offset from beginning of state table to the new state. */
503
  HBUINT16  flags;    /* Table specific. */
504
  public:
505
  DEFINE_SIZE_STATIC (4);
506
};
507
508
template <typename Types, typename Extra>
509
struct StateTable
510
{
511
  typedef typename Types::HBUINT HBUINT;
512
  typedef typename Types::HBUSHORT HBUSHORT;
513
  typedef typename Types::ClassTypeNarrow ClassType;
514
515
  enum State
516
  {
517
    STATE_START_OF_TEXT = 0,
518
    STATE_START_OF_LINE = 1,
519
  };
520
  enum Class
521
  {
522
    CLASS_END_OF_TEXT = 0,
523
    CLASS_OUT_OF_BOUNDS = 1,
524
    CLASS_DELETED_GLYPH = 2,
525
    CLASS_END_OF_LINE = 3,
526
  };
527
528
  int new_state (unsigned int newState) const
529
2.63M
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
AAT::StateTable<AAT::ExtendedTypes, void>::new_state(unsigned int) const
Line
Count
Source
529
21.9k
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
AAT::StateTable<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>::new_state(unsigned int) const
Line
Count
Source
529
738k
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
AAT::StateTable<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData>::new_state(unsigned int) const
Line
Count
Source
529
11.1k
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
AAT::StateTable<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData>::new_state(unsigned int) const
Line
Count
Source
529
746k
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
AAT::StateTable<AAT::ObsoleteTypes, void>::new_state(unsigned int) const
Line
Count
Source
529
985k
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
Unexecuted instantiation: AAT::StateTable<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>::new_state(unsigned int) const
AAT::StateTable<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData>::new_state(unsigned int) const
Line
Count
Source
529
123k
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
AAT::StateTable<AAT::ExtendedTypes, AAT::Format1Entry<true>::EntryData>::new_state(unsigned int) const
Line
Count
Source
529
1.18k
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
AAT::StateTable<AAT::ExtendedTypes, AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::EntryData>::new_state(unsigned int) const
Line
Count
Source
529
6.20k
  { return Types::extended ? newState : ((int) newState - (int) stateArrayTable) / (int) nClasses; }
530
531
  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
532
2.60M
  {
533
2.60M
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
2.60M
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
2.60M
  }
AAT::StateTable<AAT::ExtendedTypes, void>::get_class(unsigned int, unsigned int) const
Line
Count
Source
532
15.4k
  {
533
15.4k
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
15.4k
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
15.4k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>::get_class(unsigned int, unsigned int) const
Line
Count
Source
532
732k
  {
533
732k
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
732k
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
732k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData>::get_class(unsigned int, unsigned int) const
Line
Count
Source
532
6.48k
  {
533
6.48k
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
6.48k
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
6.48k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData>::get_class(unsigned int, unsigned int) const
Line
Count
Source
532
737k
  {
533
737k
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
737k
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
737k
  }
AAT::StateTable<AAT::ObsoleteTypes, void>::get_class(unsigned int, unsigned int) const
Line
Count
Source
532
984k
  {
533
984k
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
984k
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
984k
  }
Unexecuted instantiation: AAT::StateTable<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>::get_class(unsigned int, unsigned int) const
AAT::StateTable<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData>::get_class(unsigned int, unsigned int) const
Line
Count
Source
532
123k
  {
533
123k
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
123k
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
123k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::Format1Entry<true>::EntryData>::get_class(unsigned int, unsigned int) const
Line
Count
Source
532
1.08k
  {
533
1.08k
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
1.08k
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
1.08k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::EntryData>::get_class(unsigned int, unsigned int) const
Line
Count
Source
532
5.40k
  {
533
5.40k
    if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
534
5.40k
    return (this+classTable).get_class (glyph_id, num_glyphs, 1);
535
5.40k
  }
536
537
  const Entry<Extra> *get_entries () const
538
280
  { return (this+entryTable).arrayZ; }
AAT::StateTable<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>::get_entries() const
Line
Count
Source
538
280
  { return (this+entryTable).arrayZ; }
Unexecuted instantiation: AAT::StateTable<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>::get_entries() const
539
540
  const Entry<Extra> &get_entry (int state, unsigned int klass) const
541
2.69M
  {
542
2.69M
    if (unlikely (klass >= nClasses))
543
5.40k
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
2.69M
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
2.69M
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
2.69M
    unsigned int entry = states[state * nClasses + klass];
549
2.69M
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
2.69M
    return entries[entry];
552
2.69M
  }
AAT::StateTable<AAT::ExtendedTypes, void>::get_entry(int, unsigned int) const
Line
Count
Source
541
33.8k
  {
542
33.8k
    if (unlikely (klass >= nClasses))
543
0
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
33.8k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
33.8k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
33.8k
    unsigned int entry = states[state * nClasses + klass];
549
33.8k
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
33.8k
    return entries[entry];
552
33.8k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>::get_entry(int, unsigned int) const
Line
Count
Source
541
755k
  {
542
755k
    if (unlikely (klass >= nClasses))
543
0
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
755k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
755k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
755k
    unsigned int entry = states[state * nClasses + klass];
549
755k
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
755k
    return entries[entry];
552
755k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData>::get_entry(int, unsigned int) const
Line
Count
Source
541
17.3k
  {
542
17.3k
    if (unlikely (klass >= nClasses))
543
0
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
17.3k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
17.3k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
17.3k
    unsigned int entry = states[state * nClasses + klass];
549
17.3k
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
17.3k
    return entries[entry];
552
17.3k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData>::get_entry(int, unsigned int) const
Line
Count
Source
541
772k
  {
542
772k
    if (unlikely (klass >= nClasses))
543
0
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
772k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
772k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
772k
    unsigned int entry = states[state * nClasses + klass];
549
772k
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
772k
    return entries[entry];
552
772k
  }
AAT::StateTable<AAT::ObsoleteTypes, void>::get_entry(int, unsigned int) const
Line
Count
Source
541
985k
  {
542
985k
    if (unlikely (klass >= nClasses))
543
0
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
985k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
985k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
985k
    unsigned int entry = states[state * nClasses + klass];
549
985k
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
985k
    return entries[entry];
552
985k
  }
Unexecuted instantiation: AAT::StateTable<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>::get_entry(int, unsigned int) const
AAT::StateTable<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData>::get_entry(int, unsigned int) const
Line
Count
Source
541
123k
  {
542
123k
    if (unlikely (klass >= nClasses))
543
0
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
123k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
123k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
123k
    unsigned int entry = states[state * nClasses + klass];
549
123k
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
123k
    return entries[entry];
552
123k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::Format1Entry<true>::EntryData>::get_entry(int, unsigned int) const
Line
Count
Source
541
1.14k
  {
542
1.14k
    if (unlikely (klass >= nClasses))
543
0
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
1.14k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
1.14k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
1.14k
    unsigned int entry = states[state * nClasses + klass];
549
1.14k
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
1.14k
    return entries[entry];
552
1.14k
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::EntryData>::get_entry(int, unsigned int) const
Line
Count
Source
541
5.70k
  {
542
5.70k
    if (unlikely (klass >= nClasses))
543
5.40k
      klass = StateTable::CLASS_OUT_OF_BOUNDS;
544
545
5.70k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
546
5.70k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
547
548
5.70k
    unsigned int entry = states[state * nClasses + klass];
549
5.70k
    DEBUG_MSG (APPLY, nullptr, "e%u", entry);
550
551
5.70k
    return entries[entry];
552
5.70k
  }
553
554
  bool sanitize (hb_sanitize_context_t *c,
555
     unsigned int *num_entries_out = nullptr) const
556
1.84k
  {
557
1.84k
    TRACE_SANITIZE (this);
558
1.84k
    if (unlikely (!(c->check_struct (this) &&
559
1.84k
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
1.84k
        classTable.sanitize (c, this)))) return_trace (false);
561
562
1.50k
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
1.50k
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
1.50k
    unsigned int num_classes = nClasses;
566
1.50k
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
1.50k
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
1.50k
    int min_state = 0;
585
1.50k
    int max_state = 0;
586
1.50k
    unsigned int num_entries = 0;
587
588
1.50k
    int state_pos = 0;
589
1.50k
    int state_neg = 0;
590
1.50k
    unsigned int entry = 0;
591
3.54k
    while (min_state < state_neg || state_pos <= max_state)
592
2.10k
    {
593
2.10k
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
2.10k
      if (state_pos <= max_state)
615
2.10k
      {
616
  /* Positive states. */
617
2.10k
  if (unlikely (!c->check_range (states,
618
2.10k
               max_state + 1,
619
2.10k
               row_stride)))
620
0
    return_trace (false);
621
2.10k
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
2.10k
  { /* Sweep new states. */
624
2.10k
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
2.10k
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
2.10k
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
35.1k
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
33.0k
      num_entries = hb_max (num_entries, *p + 1u);
631
2.10k
    state_pos = max_state + 1;
632
2.10k
  }
633
2.10k
      }
634
635
2.10k
      if (unlikely (!c->check_array (entries, num_entries)))
636
60
  return_trace (false);
637
2.04k
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
2.04k
      { /* Sweep new entries. */
640
2.04k
  const Entry<Extra> *stop = &entries[num_entries];
641
9.92k
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
7.88k
  {
643
7.88k
    int newState = new_state (p->newState);
644
7.88k
    min_state = hb_min (min_state, newState);
645
7.88k
    max_state = hb_max (max_state, newState);
646
7.88k
  }
647
2.04k
  entry = num_entries;
648
2.04k
      }
649
2.04k
    }
650
651
1.44k
    if (num_entries_out)
652
280
      *num_entries_out = num_entries;
653
654
1.44k
    return_trace (true);
655
1.50k
  }
AAT::StateTable<AAT::ExtendedTypes, void>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
280
  {
557
280
    TRACE_SANITIZE (this);
558
280
    if (unlikely (!(c->check_struct (this) &&
559
280
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
280
        classTable.sanitize (c, this)))) return_trace (false);
561
562
280
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
280
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
280
    unsigned int num_classes = nClasses;
566
280
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
280
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
280
    int min_state = 0;
585
280
    int max_state = 0;
586
280
    unsigned int num_entries = 0;
587
588
280
    int state_pos = 0;
589
280
    int state_neg = 0;
590
280
    unsigned int entry = 0;
591
680
    while (min_state < state_neg || state_pos <= max_state)
592
400
    {
593
400
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
400
      if (state_pos <= max_state)
615
400
      {
616
  /* Positive states. */
617
400
  if (unlikely (!c->check_range (states,
618
400
               max_state + 1,
619
400
               row_stride)))
620
0
    return_trace (false);
621
400
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
400
  { /* Sweep new states. */
624
400
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
400
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
400
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
4.46k
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
4.06k
      num_entries = hb_max (num_entries, *p + 1u);
631
400
    state_pos = max_state + 1;
632
400
  }
633
400
      }
634
635
400
      if (unlikely (!c->check_array (entries, num_entries)))
636
0
  return_trace (false);
637
400
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
400
      { /* Sweep new entries. */
640
400
  const Entry<Extra> *stop = &entries[num_entries];
641
2.68k
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
2.28k
  {
643
2.28k
    int newState = new_state (p->newState);
644
2.28k
    min_state = hb_min (min_state, newState);
645
2.28k
    max_state = hb_max (max_state, newState);
646
2.28k
  }
647
400
  entry = num_entries;
648
400
      }
649
400
    }
650
651
280
    if (num_entries_out)
652
0
      *num_entries_out = num_entries;
653
654
280
    return_trace (true);
655
280
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
300
  {
557
300
    TRACE_SANITIZE (this);
558
300
    if (unlikely (!(c->check_struct (this) &&
559
300
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
300
        classTable.sanitize (c, this)))) return_trace (false);
561
562
280
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
280
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
280
    unsigned int num_classes = nClasses;
566
280
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
280
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
280
    int min_state = 0;
585
280
    int max_state = 0;
586
280
    unsigned int num_entries = 0;
587
588
280
    int state_pos = 0;
589
280
    int state_neg = 0;
590
280
    unsigned int entry = 0;
591
740
    while (min_state < state_neg || state_pos <= max_state)
592
460
    {
593
460
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
460
      if (state_pos <= max_state)
615
460
      {
616
  /* Positive states. */
617
460
  if (unlikely (!c->check_range (states,
618
460
               max_state + 1,
619
460
               row_stride)))
620
0
    return_trace (false);
621
460
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
460
  { /* Sweep new states. */
624
460
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
460
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
460
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
3.36k
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
2.90k
      num_entries = hb_max (num_entries, *p + 1u);
631
460
    state_pos = max_state + 1;
632
460
  }
633
460
      }
634
635
460
      if (unlikely (!c->check_array (entries, num_entries)))
636
0
  return_trace (false);
637
460
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
460
      { /* Sweep new entries. */
640
460
  const Entry<Extra> *stop = &entries[num_entries];
641
1.30k
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
840
  {
643
840
    int newState = new_state (p->newState);
644
840
    min_state = hb_min (min_state, newState);
645
840
    max_state = hb_max (max_state, newState);
646
840
  }
647
460
  entry = num_entries;
648
460
      }
649
460
    }
650
651
280
    if (num_entries_out)
652
280
      *num_entries_out = num_entries;
653
654
280
    return_trace (true);
655
280
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
120
  {
557
120
    TRACE_SANITIZE (this);
558
120
    if (unlikely (!(c->check_struct (this) &&
559
120
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
120
        classTable.sanitize (c, this)))) return_trace (false);
561
562
120
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
120
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
120
    unsigned int num_classes = nClasses;
566
120
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
120
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
120
    int min_state = 0;
585
120
    int max_state = 0;
586
120
    unsigned int num_entries = 0;
587
588
120
    int state_pos = 0;
589
120
    int state_neg = 0;
590
120
    unsigned int entry = 0;
591
400
    while (min_state < state_neg || state_pos <= max_state)
592
280
    {
593
280
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
280
      if (state_pos <= max_state)
615
280
      {
616
  /* Positive states. */
617
280
  if (unlikely (!c->check_range (states,
618
280
               max_state + 1,
619
280
               row_stride)))
620
0
    return_trace (false);
621
280
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
280
  { /* Sweep new states. */
624
280
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
280
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
280
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
20.7k
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
20.5k
      num_entries = hb_max (num_entries, *p + 1u);
631
280
    state_pos = max_state + 1;
632
280
  }
633
280
      }
634
635
280
      if (unlikely (!c->check_array (entries, num_entries)))
636
0
  return_trace (false);
637
280
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
280
      { /* Sweep new entries. */
640
280
  const Entry<Extra> *stop = &entries[num_entries];
641
2.62k
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
2.34k
  {
643
2.34k
    int newState = new_state (p->newState);
644
2.34k
    min_state = hb_min (min_state, newState);
645
2.34k
    max_state = hb_max (max_state, newState);
646
2.34k
  }
647
280
  entry = num_entries;
648
280
      }
649
280
    }
650
651
120
    if (num_entries_out)
652
0
      *num_entries_out = num_entries;
653
654
120
    return_trace (true);
655
120
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
640
  {
557
640
    TRACE_SANITIZE (this);
558
640
    if (unlikely (!(c->check_struct (this) &&
559
640
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
640
        classTable.sanitize (c, this)))) return_trace (false);
561
562
620
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
620
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
620
    unsigned int num_classes = nClasses;
566
620
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
620
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
620
    int min_state = 0;
585
620
    int max_state = 0;
586
620
    unsigned int num_entries = 0;
587
588
620
    int state_pos = 0;
589
620
    int state_neg = 0;
590
620
    unsigned int entry = 0;
591
1.30k
    while (min_state < state_neg || state_pos <= max_state)
592
720
    {
593
720
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
720
      if (state_pos <= max_state)
615
720
      {
616
  /* Positive states. */
617
720
  if (unlikely (!c->check_range (states,
618
720
               max_state + 1,
619
720
               row_stride)))
620
0
    return_trace (false);
621
720
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
720
  { /* Sweep new states. */
624
720
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
720
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
720
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
5.16k
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
4.44k
      num_entries = hb_max (num_entries, *p + 1u);
631
720
    state_pos = max_state + 1;
632
720
  }
633
720
      }
634
635
720
      if (unlikely (!c->check_array (entries, num_entries)))
636
40
  return_trace (false);
637
680
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
680
      { /* Sweep new entries. */
640
680
  const Entry<Extra> *stop = &entries[num_entries];
641
2.18k
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
1.50k
  {
643
1.50k
    int newState = new_state (p->newState);
644
1.50k
    min_state = hb_min (min_state, newState);
645
1.50k
    max_state = hb_max (max_state, newState);
646
1.50k
  }
647
680
  entry = num_entries;
648
680
      }
649
680
    }
650
651
580
    if (num_entries_out)
652
0
      *num_entries_out = num_entries;
653
654
580
    return_trace (true);
655
620
  }
AAT::StateTable<AAT::ObsoleteTypes, void>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
80
  {
557
80
    TRACE_SANITIZE (this);
558
80
    if (unlikely (!(c->check_struct (this) &&
559
80
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
80
        classTable.sanitize (c, this)))) return_trace (false);
561
562
40
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
40
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
40
    unsigned int num_classes = nClasses;
566
40
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
40
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
40
    int min_state = 0;
585
40
    int max_state = 0;
586
40
    unsigned int num_entries = 0;
587
588
40
    int state_pos = 0;
589
40
    int state_neg = 0;
590
40
    unsigned int entry = 0;
591
120
    while (min_state < state_neg || state_pos <= max_state)
592
80
    {
593
80
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
80
      if (state_pos <= max_state)
615
80
      {
616
  /* Positive states. */
617
80
  if (unlikely (!c->check_range (states,
618
80
               max_state + 1,
619
80
               row_stride)))
620
0
    return_trace (false);
621
80
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
80
  { /* Sweep new states. */
624
80
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
80
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
80
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
480
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
400
      num_entries = hb_max (num_entries, *p + 1u);
631
80
    state_pos = max_state + 1;
632
80
  }
633
80
      }
634
635
80
      if (unlikely (!c->check_array (entries, num_entries)))
636
0
  return_trace (false);
637
80
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
80
      { /* Sweep new entries. */
640
80
  const Entry<Extra> *stop = &entries[num_entries];
641
360
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
280
  {
643
280
    int newState = new_state (p->newState);
644
280
    min_state = hb_min (min_state, newState);
645
280
    max_state = hb_max (max_state, newState);
646
280
  }
647
80
  entry = num_entries;
648
80
      }
649
80
    }
650
651
40
    if (num_entries_out)
652
0
      *num_entries_out = num_entries;
653
654
40
    return_trace (true);
655
40
  }
AAT::StateTable<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
20
  {
557
20
    TRACE_SANITIZE (this);
558
20
    if (unlikely (!(c->check_struct (this) &&
559
20
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
20
        classTable.sanitize (c, this)))) return_trace (false);
561
562
0
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
0
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
0
    unsigned int num_classes = nClasses;
566
0
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
0
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
0
    int min_state = 0;
585
0
    int max_state = 0;
586
0
    unsigned int num_entries = 0;
587
588
0
    int state_pos = 0;
589
0
    int state_neg = 0;
590
0
    unsigned int entry = 0;
591
0
    while (min_state < state_neg || state_pos <= max_state)
592
0
    {
593
0
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
0
      if (state_pos <= max_state)
615
0
      {
616
  /* Positive states. */
617
0
  if (unlikely (!c->check_range (states,
618
0
               max_state + 1,
619
0
               row_stride)))
620
0
    return_trace (false);
621
0
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
0
  { /* Sweep new states. */
624
0
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
0
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
0
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
0
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
0
      num_entries = hb_max (num_entries, *p + 1u);
631
0
    state_pos = max_state + 1;
632
0
  }
633
0
      }
634
635
0
      if (unlikely (!c->check_array (entries, num_entries)))
636
0
  return_trace (false);
637
0
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
0
      { /* Sweep new entries. */
640
0
  const Entry<Extra> *stop = &entries[num_entries];
641
0
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
0
  {
643
0
    int newState = new_state (p->newState);
644
0
    min_state = hb_min (min_state, newState);
645
0
    max_state = hb_max (max_state, newState);
646
0
  }
647
0
  entry = num_entries;
648
0
      }
649
0
    }
650
651
0
    if (num_entries_out)
652
0
      *num_entries_out = num_entries;
653
654
0
    return_trace (true);
655
0
  }
AAT::StateTable<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
40
  {
557
40
    TRACE_SANITIZE (this);
558
40
    if (unlikely (!(c->check_struct (this) &&
559
40
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
40
        classTable.sanitize (c, this)))) return_trace (false);
561
562
20
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
20
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
20
    unsigned int num_classes = nClasses;
566
20
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
20
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
20
    int min_state = 0;
585
20
    int max_state = 0;
586
20
    unsigned int num_entries = 0;
587
588
20
    int state_pos = 0;
589
20
    int state_neg = 0;
590
20
    unsigned int entry = 0;
591
40
    while (min_state < state_neg || state_pos <= max_state)
592
20
    {
593
20
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
20
      if (state_pos <= max_state)
615
20
      {
616
  /* Positive states. */
617
20
  if (unlikely (!c->check_range (states,
618
20
               max_state + 1,
619
20
               row_stride)))
620
0
    return_trace (false);
621
20
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
20
  { /* Sweep new states. */
624
20
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
20
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
20
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
120
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
100
      num_entries = hb_max (num_entries, *p + 1u);
631
20
    state_pos = max_state + 1;
632
20
  }
633
20
      }
634
635
20
      if (unlikely (!c->check_array (entries, num_entries)))
636
0
  return_trace (false);
637
20
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
20
      { /* Sweep new entries. */
640
20
  const Entry<Extra> *stop = &entries[num_entries];
641
120
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
100
  {
643
100
    int newState = new_state (p->newState);
644
100
    min_state = hb_min (min_state, newState);
645
100
    max_state = hb_max (max_state, newState);
646
100
  }
647
20
  entry = num_entries;
648
20
      }
649
20
    }
650
651
20
    if (num_entries_out)
652
0
      *num_entries_out = num_entries;
653
654
20
    return_trace (true);
655
20
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::Format1Entry<true>::EntryData>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
80
  {
557
80
    TRACE_SANITIZE (this);
558
80
    if (unlikely (!(c->check_struct (this) &&
559
80
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
80
        classTable.sanitize (c, this)))) return_trace (false);
561
562
20
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
20
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
20
    unsigned int num_classes = nClasses;
566
20
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
20
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
20
    int min_state = 0;
585
20
    int max_state = 0;
586
20
    unsigned int num_entries = 0;
587
588
20
    int state_pos = 0;
589
20
    int state_neg = 0;
590
20
    unsigned int entry = 0;
591
40
    while (min_state < state_neg || state_pos <= max_state)
592
20
    {
593
20
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
20
      if (state_pos <= max_state)
615
20
      {
616
  /* Positive states. */
617
20
  if (unlikely (!c->check_range (states,
618
20
               max_state + 1,
619
20
               row_stride)))
620
0
    return_trace (false);
621
20
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
20
  { /* Sweep new states. */
624
20
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
20
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
20
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
100
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
80
      num_entries = hb_max (num_entries, *p + 1u);
631
20
    state_pos = max_state + 1;
632
20
  }
633
20
      }
634
635
20
      if (unlikely (!c->check_array (entries, num_entries)))
636
0
  return_trace (false);
637
20
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
20
      { /* Sweep new entries. */
640
20
  const Entry<Extra> *stop = &entries[num_entries];
641
60
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
40
  {
643
40
    int newState = new_state (p->newState);
644
40
    min_state = hb_min (min_state, newState);
645
40
    max_state = hb_max (max_state, newState);
646
40
  }
647
20
  entry = num_entries;
648
20
      }
649
20
    }
650
651
20
    if (num_entries_out)
652
0
      *num_entries_out = num_entries;
653
654
20
    return_trace (true);
655
20
  }
AAT::StateTable<AAT::ExtendedTypes, AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::EntryData>::sanitize(hb_sanitize_context_t*, unsigned int*) const
Line
Count
Source
556
280
  {
557
280
    TRACE_SANITIZE (this);
558
280
    if (unlikely (!(c->check_struct (this) &&
559
280
        nClasses >= 4 /* Ensure pre-defined classes fit.  */ &&
560
280
        classTable.sanitize (c, this)))) return_trace (false);
561
562
120
    const HBUSHORT *states = (this+stateArrayTable).arrayZ;
563
120
    const Entry<Extra> *entries = (this+entryTable).arrayZ;
564
565
120
    unsigned int num_classes = nClasses;
566
120
    if (unlikely (hb_unsigned_mul_overflows (num_classes, states[0].static_size)))
567
0
      return_trace (false);
568
120
    unsigned int row_stride = num_classes * states[0].static_size;
569
570
    /* Apple 'kern' table has this peculiarity:
571
     *
572
     * "Because the stateTableOffset in the state table header is (strictly
573
     * speaking) redundant, some 'kern' tables use it to record an initial
574
     * state where that should not be StartOfText. To determine if this is
575
     * done, calculate what the stateTableOffset should be. If it's different
576
     * from the actual stateTableOffset, use it as the initial state."
577
     *
578
     * We implement this by calling the initial state zero, but allow *negative*
579
     * states if the start state indeed was not the first state.  Since the code
580
     * is shared, this will also apply to 'mort' table.  The 'kerx' / 'morx'
581
     * tables are not affected since those address states by index, not offset.
582
     */
583
584
120
    int min_state = 0;
585
120
    int max_state = 0;
586
120
    unsigned int num_entries = 0;
587
588
120
    int state_pos = 0;
589
120
    int state_neg = 0;
590
120
    unsigned int entry = 0;
591
220
    while (min_state < state_neg || state_pos <= max_state)
592
120
    {
593
120
      if (min_state < state_neg)
594
0
      {
595
  /* Negative states. */
596
0
  if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes)))
597
0
    return_trace (false);
598
0
  if (unlikely (!c->check_range (&states[min_state * num_classes],
599
0
               -min_state,
600
0
               row_stride)))
601
0
    return_trace (false);
602
0
  if ((c->max_ops -= state_neg - min_state) <= 0)
603
0
    return_trace (false);
604
0
  { /* Sweep new states. */
605
0
    const HBUSHORT *stop = &states[min_state * num_classes];
606
0
    if (unlikely (stop > states))
607
0
      return_trace (false);
608
0
    for (const HBUSHORT *p = states; stop < p; p--)
609
0
      num_entries = hb_max (num_entries, *(p - 1) + 1u);
610
0
    state_neg = min_state;
611
0
  }
612
0
      }
613
614
120
      if (state_pos <= max_state)
615
120
      {
616
  /* Positive states. */
617
120
  if (unlikely (!c->check_range (states,
618
120
               max_state + 1,
619
120
               row_stride)))
620
0
    return_trace (false);
621
120
  if ((c->max_ops -= max_state - state_pos + 1) <= 0)
622
0
    return_trace (false);
623
120
  { /* Sweep new states. */
624
120
    if (unlikely (hb_unsigned_mul_overflows ((max_state + 1), num_classes)))
625
0
      return_trace (false);
626
120
    const HBUSHORT *stop = &states[(max_state + 1) * num_classes];
627
120
    if (unlikely (stop < states))
628
0
      return_trace (false);
629
680
    for (const HBUSHORT *p = &states[state_pos * num_classes]; p < stop; p++)
630
560
      num_entries = hb_max (num_entries, *p + 1u);
631
120
    state_pos = max_state + 1;
632
120
  }
633
120
      }
634
635
120
      if (unlikely (!c->check_array (entries, num_entries)))
636
20
  return_trace (false);
637
100
      if ((c->max_ops -= num_entries - entry) <= 0)
638
0
  return_trace (false);
639
100
      { /* Sweep new entries. */
640
100
  const Entry<Extra> *stop = &entries[num_entries];
641
600
  for (const Entry<Extra> *p = &entries[entry]; p < stop; p++)
642
500
  {
643
500
    int newState = new_state (p->newState);
644
500
    min_state = hb_min (min_state, newState);
645
500
    max_state = hb_max (max_state, newState);
646
500
  }
647
100
  entry = num_entries;
648
100
      }
649
100
    }
650
651
100
    if (num_entries_out)
652
0
      *num_entries_out = num_entries;
653
654
100
    return_trace (true);
655
120
  }
656
657
  protected:
658
  HBUINT  nClasses; /* Number of classes, which is the number of indices
659
         * in a single line in the state array. */
660
  NNOffsetTo<ClassType, HBUINT>
661
    classTable; /* Offset to the class table. */
662
  NNOffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
663
    stateArrayTable;/* Offset to the state array. */
664
  NNOffsetTo<UnsizedArrayOf<Entry<Extra>>, HBUINT>
665
    entryTable; /* Offset to the entry array. */
666
667
  public:
668
  DEFINE_SIZE_STATIC (4 * sizeof (HBUINT));
669
};
670
671
template <typename HBUCHAR>
672
struct ClassTable
673
{
674
  unsigned int get_class (hb_codepoint_t glyph_id, unsigned int outOfRange) const
675
1.11M
  {
676
1.11M
    unsigned int i = glyph_id - firstGlyph;
677
1.11M
    return i >= classArray.len ? outOfRange : classArray.arrayZ[i];
678
1.11M
  }
AAT::ClassTable<OT::IntType<unsigned char, 1u> >::get_class(unsigned int, unsigned int) const
Line
Count
Source
675
1.10M
  {
676
1.10M
    unsigned int i = glyph_id - firstGlyph;
677
1.10M
    return i >= classArray.len ? outOfRange : classArray.arrayZ[i];
678
1.10M
  }
AAT::ClassTable<OT::IntType<unsigned short, 2u> >::get_class(unsigned int, unsigned int) const
Line
Count
Source
675
2.64k
  {
676
2.64k
    unsigned int i = glyph_id - firstGlyph;
677
2.64k
    return i >= classArray.len ? outOfRange : classArray.arrayZ[i];
678
2.64k
  }
679
  unsigned int get_class (hb_codepoint_t glyph_id,
680
        unsigned int num_glyphs HB_UNUSED,
681
        unsigned int outOfRange) const
682
1.11M
  {
683
1.11M
    return get_class (glyph_id, outOfRange);
684
1.11M
  }
AAT::ClassTable<OT::IntType<unsigned char, 1u> >::get_class(unsigned int, unsigned int, unsigned int) const
Line
Count
Source
682
1.10M
  {
683
1.10M
    return get_class (glyph_id, outOfRange);
684
1.10M
  }
AAT::ClassTable<OT::IntType<unsigned short, 2u> >::get_class(unsigned int, unsigned int, unsigned int) const
Line
Count
Source
682
2.64k
  {
683
2.64k
    return get_class (glyph_id, outOfRange);
684
2.64k
  }
685
  bool sanitize (hb_sanitize_context_t *c) const
686
180
  {
687
180
    TRACE_SANITIZE (this);
688
180
    return_trace (c->check_struct (this) && classArray.sanitize (c));
689
180
  }
AAT::ClassTable<OT::IntType<unsigned char, 1u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
686
60
  {
687
60
    TRACE_SANITIZE (this);
688
60
    return_trace (c->check_struct (this) && classArray.sanitize (c));
689
60
  }
AAT::ClassTable<OT::IntType<unsigned short, 2u> >::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
686
120
  {
687
120
    TRACE_SANITIZE (this);
688
120
    return_trace (c->check_struct (this) && classArray.sanitize (c));
689
120
  }
690
  protected:
691
  HBGlyphID16   firstGlyph; /* First glyph index included in the trimmed array. */
692
  Array16Of<HBUCHAR>  classArray; /* The class codes (indexed by glyph index minus
693
           * firstGlyph). */
694
  public:
695
  DEFINE_SIZE_ARRAY (4, classArray);
696
};
697
698
struct ObsoleteTypes
699
{
700
  static constexpr bool extended = false;
701
  typedef HBUINT16 HBUINT;
702
  typedef HBUINT8 HBUSHORT;
703
  typedef ClassTable<HBUINT8> ClassTypeNarrow;
704
  typedef ClassTable<HBUINT16> ClassTypeWide;
705
706
  template <typename T>
707
  static unsigned int offsetToIndex (unsigned int offset,
708
             const void *base,
709
             const T *array)
710
1.32k
  {
711
    /* https://github.com/harfbuzz/harfbuzz/issues/3483 */
712
    /* If offset is less than base, return an offset that would
713
     * result in an address half a 32bit address-space away,
714
     * to make sure sanitize fails even on 32bit builds. */
715
1.32k
    if (unlikely (offset < unsigned ((const char *) array - (const char *) base)))
716
1.10k
      return INT_MAX / T::static_size;
717
718
    /* https://github.com/harfbuzz/harfbuzz/issues/2816 */
719
220
    return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
720
1.32k
  }
Unexecuted instantiation: unsigned int AAT::ObsoleteTypes::offsetToIndex<OT::HBGlyphID16>(unsigned int, void const*, OT::HBGlyphID16 const*)
Unexecuted instantiation: unsigned int AAT::ObsoleteTypes::offsetToIndex<OT::IntType<unsigned int, 4u> >(unsigned int, void const*, OT::IntType<unsigned int, 4u> const*)
Unexecuted instantiation: unsigned int AAT::ObsoleteTypes::offsetToIndex<OT::IntType<unsigned short, 2u> >(unsigned int, void const*, OT::IntType<unsigned short, 2u> const*)
unsigned int AAT::ObsoleteTypes::offsetToIndex<OT::IntType<short, 2u> >(unsigned int, void const*, OT::IntType<short, 2u> const*)
Line
Count
Source
710
1.32k
  {
711
    /* https://github.com/harfbuzz/harfbuzz/issues/3483 */
712
    /* If offset is less than base, return an offset that would
713
     * result in an address half a 32bit address-space away,
714
     * to make sure sanitize fails even on 32bit builds. */
715
1.32k
    if (unlikely (offset < unsigned ((const char *) array - (const char *) base)))
716
1.10k
      return INT_MAX / T::static_size;
717
718
    /* https://github.com/harfbuzz/harfbuzz/issues/2816 */
719
220
    return (offset - unsigned ((const char *) array - (const char *) base)) / T::static_size;
720
1.32k
  }
721
  template <typename T>
722
  static unsigned int byteOffsetToIndex (unsigned int offset,
723
           const void *base,
724
           const T *array)
725
0
  {
726
0
    return offsetToIndex (offset, base, array);
727
0
  }
728
  template <typename T>
729
  static unsigned int wordOffsetToIndex (unsigned int offset,
730
           const void *base,
731
           const T *array)
732
0
  {
733
0
    return offsetToIndex (2 * offset, base, array);
734
0
  }
Unexecuted instantiation: unsigned int AAT::ObsoleteTypes::wordOffsetToIndex<OT::HBGlyphID16>(unsigned int, void const*, OT::HBGlyphID16 const*)
Unexecuted instantiation: unsigned int AAT::ObsoleteTypes::wordOffsetToIndex<OT::IntType<unsigned short, 2u> >(unsigned int, void const*, OT::IntType<unsigned short, 2u> const*)
735
};
736
struct ExtendedTypes
737
{
738
  static constexpr bool extended = true;
739
  typedef HBUINT32 HBUINT;
740
  typedef HBUINT16 HBUSHORT;
741
  typedef Lookup<HBUINT16> ClassTypeNarrow;
742
  typedef Lookup<HBUINT16> ClassTypeWide;
743
744
  template <typename T>
745
  static unsigned int offsetToIndex (unsigned int offset,
746
             const void *base HB_UNUSED,
747
             const T *array HB_UNUSED)
748
0
  {
749
0
    return offset;
750
0
  }
Unexecuted instantiation: unsigned int AAT::ExtendedTypes::offsetToIndex<OT::IntType<unsigned int, 4u> >(unsigned int, void const*, OT::IntType<unsigned int, 4u> const*)
Unexecuted instantiation: unsigned int AAT::ExtendedTypes::offsetToIndex<OT::HBGlyphID16>(unsigned int, void const*, OT::HBGlyphID16 const*)
Unexecuted instantiation: unsigned int AAT::ExtendedTypes::offsetToIndex<OT::IntType<short, 2u> >(unsigned int, void const*, OT::IntType<short, 2u> const*)
751
  template <typename T>
752
  static unsigned int byteOffsetToIndex (unsigned int offset,
753
           const void *base HB_UNUSED,
754
           const T *array HB_UNUSED)
755
0
  {
756
0
    return offset / 2;
757
0
  }
758
  template <typename T>
759
  static unsigned int wordOffsetToIndex (unsigned int offset,
760
           const void *base HB_UNUSED,
761
           const T *array HB_UNUSED)
762
0
  {
763
0
    return offset;
764
0
  }
Unexecuted instantiation: unsigned int AAT::ExtendedTypes::wordOffsetToIndex<OT::IntType<unsigned short, 2u> >(unsigned int, void const*, OT::IntType<unsigned short, 2u> const*)
Unexecuted instantiation: unsigned int AAT::ExtendedTypes::wordOffsetToIndex<OT::HBGlyphID16>(unsigned int, void const*, OT::HBGlyphID16 const*)
765
};
766
767
template <typename Types, typename EntryData>
768
struct StateTableDriver
769
{
770
  using StateTableT = StateTable<Types, EntryData>;
771
  using EntryT = Entry<EntryData>;
772
773
  StateTableDriver (const StateTableT &machine_,
774
        hb_buffer_t *buffer_,
775
        hb_face_t *face_) :
776
        machine (machine_),
777
        buffer (buffer_),
778
16.7k
        num_glyphs (face_->get_num_glyphs ()) {}
AAT::StateTableDriver<AAT::ExtendedTypes, void>::StateTableDriver(AAT::StateTable<AAT::ExtendedTypes, void> const&, hb_buffer_t*, hb_face_t*)
Line
Count
Source
778
2.16k
        num_glyphs (face_->get_num_glyphs ()) {}
AAT::StateTableDriver<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>::StateTableDriver(AAT::StateTable<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData> const&, hb_buffer_t*, hb_face_t*)
Line
Count
Source
778
4.46k
        num_glyphs (face_->get_num_glyphs ()) {}
AAT::StateTableDriver<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData>::StateTableDriver(AAT::StateTable<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData> const&, hb_buffer_t*, hb_face_t*)
Line
Count
Source
778
2.16k
        num_glyphs (face_->get_num_glyphs ()) {}
AAT::StateTableDriver<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData>::StateTableDriver(AAT::StateTable<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData> const&, hb_buffer_t*, hb_face_t*)
Line
Count
Source
778
7.42k
        num_glyphs (face_->get_num_glyphs ()) {}
AAT::StateTableDriver<AAT::ObsoleteTypes, void>::StateTableDriver(AAT::StateTable<AAT::ObsoleteTypes, void> const&, hb_buffer_t*, hb_face_t*)
Line
Count
Source
778
120
        num_glyphs (face_->get_num_glyphs ()) {}
Unexecuted instantiation: AAT::StateTableDriver<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>::StateTableDriver(AAT::StateTable<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData> const&, hb_buffer_t*, hb_face_t*)
AAT::StateTableDriver<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData>::StateTableDriver(AAT::StateTable<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData> const&, hb_buffer_t*, hb_face_t*)
Line
Count
Source
778
60
        num_glyphs (face_->get_num_glyphs ()) {}
AAT::StateTableDriver<AAT::ExtendedTypes, AAT::Format1Entry<true>::EntryData>::StateTableDriver(AAT::StateTable<AAT::ExtendedTypes, AAT::Format1Entry<true>::EntryData> const&, hb_buffer_t*, hb_face_t*)
Line
Count
Source
778
60
        num_glyphs (face_->get_num_glyphs ()) {}
AAT::StateTableDriver<AAT::ExtendedTypes, AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::EntryData>::StateTableDriver(AAT::StateTable<AAT::ExtendedTypes, AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::EntryData> const&, hb_buffer_t*, hb_face_t*)
Line
Count
Source
778
300
        num_glyphs (face_->get_num_glyphs ()) {}
779
780
  template <typename context_t>
781
  void drive (context_t *c, hb_aat_apply_context_t *ac)
782
16.7k
  {
783
16.7k
    if (!c->in_place)
784
9.64k
      buffer->clear_output ();
785
786
16.7k
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
16.7k
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
2.62M
    for (buffer->idx = 0; buffer->successful;)
790
2.62M
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
2.62M
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
2.62M
      unsigned int klass = buffer->idx < buffer->len ?
818
2.60M
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
2.62M
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
2.62M
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
2.62M
      const EntryT &entry = machine.get_entry (state, klass);
822
2.62M
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
2.62M
      const EntryT *wouldbe_entry;
853
2.62M
      bool safe_to_break =
854
  /* 1. */
855
2.62M
  !c->is_actionable (this, entry)
856
2.62M
      &&
857
  /* 2. */
858
2.62M
  (
859
    /* 2a. */
860
71.4k
    state == StateTableT::STATE_START_OF_TEXT
861
71.4k
  ||
862
    /* 2b. */
863
71.4k
    (
864
3.80k
      (entry.flags & context_t::DontAdvance) &&
865
3.80k
      next_state == StateTableT::STATE_START_OF_TEXT
866
3.80k
    )
867
71.4k
  ||
868
    /* 2c. */
869
71.4k
    (
870
3.68k
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
3.68k
    ,
872
      /* 2c'. */
873
3.68k
      !c->is_actionable (this, *wouldbe_entry)
874
3.68k
    &&
875
      /* 2c". */
876
3.68k
      (
877
3.48k
        next_state == machine.new_state (wouldbe_entry->newState)
878
3.48k
      &&
879
3.48k
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
3.48k
      )
881
3.68k
    )
882
71.4k
  )
883
2.62M
      &&
884
  /* 3. */
885
2.62M
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
2.62M
      ;
887
888
2.62M
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
1.48M
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
2.62M
      c->transition (this, entry);
892
893
2.62M
      state = next_state;
894
2.62M
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
2.62M
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
16.7k
  break;
898
899
2.60M
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
1.40M
  (void) buffer->next_glyph ();
901
2.60M
    }
902
903
16.7k
    if (!c->in_place)
904
9.64k
      buffer->sync ();
905
16.7k
  }
void AAT::StateTableDriver<AAT::ExtendedTypes, void>::drive<AAT::RearrangementSubtable<AAT::ExtendedTypes>::driver_context_t>(AAT::RearrangementSubtable<AAT::ExtendedTypes>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Line
Count
Source
782
2.16k
  {
783
2.16k
    if (!c->in_place)
784
0
      buffer->clear_output ();
785
786
2.16k
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
2.16k
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
17.6k
    for (buffer->idx = 0; buffer->successful;)
790
17.6k
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
17.6k
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
17.6k
      unsigned int klass = buffer->idx < buffer->len ?
818
15.4k
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
17.6k
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
17.6k
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
17.6k
      const EntryT &entry = machine.get_entry (state, klass);
822
17.6k
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
17.6k
      const EntryT *wouldbe_entry;
853
17.6k
      bool safe_to_break =
854
  /* 1. */
855
17.6k
  !c->is_actionable (this, entry)
856
17.6k
      &&
857
  /* 2. */
858
17.6k
  (
859
    /* 2a. */
860
16.2k
    state == StateTableT::STATE_START_OF_TEXT
861
16.2k
  ||
862
    /* 2b. */
863
16.2k
    (
864
2.12k
      (entry.flags & context_t::DontAdvance) &&
865
2.12k
      next_state == StateTableT::STATE_START_OF_TEXT
866
2.12k
    )
867
16.2k
  ||
868
    /* 2c. */
869
16.2k
    (
870
2.12k
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
2.12k
    ,
872
      /* 2c'. */
873
2.12k
      !c->is_actionable (this, *wouldbe_entry)
874
2.12k
    &&
875
      /* 2c". */
876
2.12k
      (
877
2.08k
        next_state == machine.new_state (wouldbe_entry->newState)
878
2.08k
      &&
879
2.08k
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
2.08k
      )
881
2.12k
    )
882
16.2k
  )
883
17.6k
      &&
884
  /* 3. */
885
17.6k
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
17.6k
      ;
887
888
17.6k
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
5.96k
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
17.6k
      c->transition (this, entry);
892
893
17.6k
      state = next_state;
894
17.6k
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
17.6k
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
2.16k
  break;
898
899
15.4k
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
15.1k
  (void) buffer->next_glyph ();
901
15.4k
    }
902
903
2.16k
    if (!c->in_place)
904
0
      buffer->sync ();
905
2.16k
  }
void AAT::StateTableDriver<AAT::ExtendedTypes, AAT::ContextualSubtable<AAT::ExtendedTypes>::EntryData>::drive<AAT::ContextualSubtable<AAT::ExtendedTypes>::driver_context_t>(AAT::ContextualSubtable<AAT::ExtendedTypes>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Line
Count
Source
782
4.46k
  {
783
4.46k
    if (!c->in_place)
784
0
      buffer->clear_output ();
785
786
4.46k
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
4.46k
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
736k
    for (buffer->idx = 0; buffer->successful;)
790
736k
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
736k
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
736k
      unsigned int klass = buffer->idx < buffer->len ?
818
732k
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
736k
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
736k
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
736k
      const EntryT &entry = machine.get_entry (state, klass);
822
736k
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
736k
      const EntryT *wouldbe_entry;
853
736k
      bool safe_to_break =
854
  /* 1. */
855
736k
  !c->is_actionable (this, entry)
856
736k
      &&
857
  /* 2. */
858
736k
  (
859
    /* 2a. */
860
19.0k
    state == StateTableT::STATE_START_OF_TEXT
861
19.0k
  ||
862
    /* 2b. */
863
19.0k
    (
864
880
      (entry.flags & context_t::DontAdvance) &&
865
880
      next_state == StateTableT::STATE_START_OF_TEXT
866
880
    )
867
19.0k
  ||
868
    /* 2c. */
869
19.0k
    (
870
880
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
880
    ,
872
      /* 2c'. */
873
880
      !c->is_actionable (this, *wouldbe_entry)
874
880
    &&
875
      /* 2c". */
876
880
      (
877
720
        next_state == machine.new_state (wouldbe_entry->newState)
878
720
      &&
879
720
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
720
      )
881
880
    )
882
19.0k
  )
883
736k
      &&
884
  /* 3. */
885
736k
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
736k
      ;
887
888
736k
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
2.46k
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
736k
      c->transition (this, entry);
892
893
736k
      state = next_state;
894
736k
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
736k
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
4.46k
  break;
898
899
732k
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
15.1k
  (void) buffer->next_glyph ();
901
732k
    }
902
903
4.46k
    if (!c->in_place)
904
0
      buffer->sync ();
905
4.46k
  }
void AAT::StateTableDriver<AAT::ExtendedTypes, AAT::LigatureEntry<true>::EntryData>::drive<AAT::LigatureSubtable<AAT::ExtendedTypes>::driver_context_t>(AAT::LigatureSubtable<AAT::ExtendedTypes>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Line
Count
Source
782
2.16k
  {
783
2.16k
    if (!c->in_place)
784
2.16k
      buffer->clear_output ();
785
786
2.16k
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
2.16k
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
8.64k
    for (buffer->idx = 0; buffer->successful;)
790
8.64k
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
8.64k
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
8.64k
      unsigned int klass = buffer->idx < buffer->len ?
818
6.48k
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
8.64k
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
8.64k
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
8.64k
      const EntryT &entry = machine.get_entry (state, klass);
822
8.64k
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
8.64k
      const EntryT *wouldbe_entry;
853
8.64k
      bool safe_to_break =
854
  /* 1. */
855
8.64k
  !c->is_actionable (this, entry)
856
8.64k
      &&
857
  /* 2. */
858
8.64k
  (
859
    /* 2a. */
860
8.64k
    state == StateTableT::STATE_START_OF_TEXT
861
8.64k
  ||
862
    /* 2b. */
863
8.64k
    (
864
120
      (entry.flags & context_t::DontAdvance) &&
865
120
      next_state == StateTableT::STATE_START_OF_TEXT
866
120
    )
867
8.64k
  ||
868
    /* 2c. */
869
8.64k
    (
870
120
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
120
    ,
872
      /* 2c'. */
873
120
      !c->is_actionable (this, *wouldbe_entry)
874
120
    &&
875
      /* 2c". */
876
120
      (
877
120
        next_state == machine.new_state (wouldbe_entry->newState)
878
120
      &&
879
120
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
120
      )
881
120
    )
882
8.64k
  )
883
8.64k
      &&
884
  /* 3. */
885
8.64k
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
8.64k
      ;
887
888
8.64k
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
0
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
8.64k
      c->transition (this, entry);
892
893
8.64k
      state = next_state;
894
8.64k
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
8.64k
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
2.16k
  break;
898
899
6.48k
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
6.48k
  (void) buffer->next_glyph ();
901
6.48k
    }
902
903
2.16k
    if (!c->in_place)
904
2.16k
      buffer->sync ();
905
2.16k
  }
void AAT::StateTableDriver<AAT::ExtendedTypes, AAT::InsertionSubtable<AAT::ExtendedTypes>::EntryData>::drive<AAT::InsertionSubtable<AAT::ExtendedTypes>::driver_context_t>(AAT::InsertionSubtable<AAT::ExtendedTypes>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Line
Count
Source
782
7.42k
  {
783
7.42k
    if (!c->in_place)
784
7.42k
      buffer->clear_output ();
785
786
7.42k
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
7.42k
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
744k
    for (buffer->idx = 0; buffer->successful;)
790
744k
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
744k
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
744k
      unsigned int klass = buffer->idx < buffer->len ?
818
737k
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
744k
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
744k
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
744k
      const EntryT &entry = machine.get_entry (state, klass);
822
744k
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
744k
      const EntryT *wouldbe_entry;
853
744k
      bool safe_to_break =
854
  /* 1. */
855
744k
  !c->is_actionable (this, entry)
856
744k
      &&
857
  /* 2. */
858
744k
  (
859
    /* 2a. */
860
27.3k
    state == StateTableT::STATE_START_OF_TEXT
861
27.3k
  ||
862
    /* 2b. */
863
27.3k
    (
864
560
      (entry.flags & context_t::DontAdvance) &&
865
560
      next_state == StateTableT::STATE_START_OF_TEXT
866
560
    )
867
27.3k
  ||
868
    /* 2c. */
869
27.3k
    (
870
560
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
560
    ,
872
      /* 2c'. */
873
560
      !c->is_actionable (this, *wouldbe_entry)
874
560
    &&
875
      /* 2c". */
876
560
      (
877
560
        next_state == machine.new_state (wouldbe_entry->newState)
878
560
      &&
879
560
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
560
      )
881
560
    )
882
27.3k
  )
883
744k
      &&
884
  /* 3. */
885
744k
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
744k
      ;
887
888
744k
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
359k
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
744k
      c->transition (this, entry);
892
893
744k
      state = next_state;
894
744k
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
744k
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
7.42k
  break;
898
899
737k
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
378k
  (void) buffer->next_glyph ();
901
737k
    }
902
903
7.42k
    if (!c->in_place)
904
7.42k
      buffer->sync ();
905
7.42k
  }
void AAT::StateTableDriver<AAT::ObsoleteTypes, void>::drive<AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t>(AAT::RearrangementSubtable<AAT::ObsoleteTypes>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Line
Count
Source
782
120
  {
783
120
    if (!c->in_place)
784
0
      buffer->clear_output ();
785
786
120
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
120
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
985k
    for (buffer->idx = 0; buffer->successful;)
790
985k
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
985k
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
985k
      unsigned int klass = buffer->idx < buffer->len ?
818
984k
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
985k
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
985k
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
985k
      const EntryT &entry = machine.get_entry (state, klass);
822
985k
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
985k
      const EntryT *wouldbe_entry;
853
985k
      bool safe_to_break =
854
  /* 1. */
855
985k
  !c->is_actionable (this, entry)
856
985k
      &&
857
  /* 2. */
858
985k
  (
859
    /* 2a. */
860
280
    state == StateTableT::STATE_START_OF_TEXT
861
280
  ||
862
    /* 2b. */
863
280
    (
864
120
      (entry.flags & context_t::DontAdvance) &&
865
120
      next_state == StateTableT::STATE_START_OF_TEXT
866
120
    )
867
280
  ||
868
    /* 2c. */
869
280
    (
870
0
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
0
    ,
872
      /* 2c'. */
873
0
      !c->is_actionable (this, *wouldbe_entry)
874
0
    &&
875
      /* 2c". */
876
0
      (
877
0
        next_state == machine.new_state (wouldbe_entry->newState)
878
0
      &&
879
0
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
0
      )
881
0
    )
882
280
  )
883
985k
      &&
884
  /* 3. */
885
985k
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
985k
      ;
887
888
985k
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
984k
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
985k
      c->transition (this, entry);
892
893
985k
      state = next_state;
894
985k
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
985k
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
120
  break;
898
899
984k
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
983k
  (void) buffer->next_glyph ();
901
984k
    }
902
903
120
    if (!c->in_place)
904
0
      buffer->sync ();
905
120
  }
Unexecuted instantiation: void AAT::StateTableDriver<AAT::ObsoleteTypes, AAT::ContextualSubtable<AAT::ObsoleteTypes>::EntryData>::drive<AAT::ContextualSubtable<AAT::ObsoleteTypes>::driver_context_t>(AAT::ContextualSubtable<AAT::ObsoleteTypes>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Unexecuted instantiation: void AAT::StateTableDriver<AAT::ObsoleteTypes, void>::drive<AAT::LigatureSubtable<AAT::ObsoleteTypes>::driver_context_t>(AAT::LigatureSubtable<AAT::ObsoleteTypes>::driver_context_t*, AAT::hb_aat_apply_context_t*)
void AAT::StateTableDriver<AAT::ObsoleteTypes, AAT::InsertionSubtable<AAT::ObsoleteTypes>::EntryData>::drive<AAT::InsertionSubtable<AAT::ObsoleteTypes>::driver_context_t>(AAT::InsertionSubtable<AAT::ObsoleteTypes>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Line
Count
Source
782
60
  {
783
60
    if (!c->in_place)
784
60
      buffer->clear_output ();
785
786
60
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
60
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
123k
    for (buffer->idx = 0; buffer->successful;)
790
123k
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
123k
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
123k
      unsigned int klass = buffer->idx < buffer->len ?
818
123k
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
123k
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
123k
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
123k
      const EntryT &entry = machine.get_entry (state, klass);
822
123k
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
123k
      const EntryT *wouldbe_entry;
853
123k
      bool safe_to_break =
854
  /* 1. */
855
123k
  !c->is_actionable (this, entry)
856
123k
      &&
857
  /* 2. */
858
123k
  (
859
    /* 2a. */
860
0
    state == StateTableT::STATE_START_OF_TEXT
861
0
  ||
862
    /* 2b. */
863
0
    (
864
0
      (entry.flags & context_t::DontAdvance) &&
865
0
      next_state == StateTableT::STATE_START_OF_TEXT
866
0
    )
867
0
  ||
868
    /* 2c. */
869
0
    (
870
0
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
0
    ,
872
      /* 2c'. */
873
0
      !c->is_actionable (this, *wouldbe_entry)
874
0
    &&
875
      /* 2c". */
876
0
      (
877
0
        next_state == machine.new_state (wouldbe_entry->newState)
878
0
      &&
879
0
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
0
      )
881
0
    )
882
0
  )
883
123k
      &&
884
  /* 3. */
885
123k
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
123k
      ;
887
888
123k
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
123k
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
123k
      c->transition (this, entry);
892
893
123k
      state = next_state;
894
123k
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
123k
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
60
  break;
898
899
123k
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
1.08k
  (void) buffer->next_glyph ();
901
123k
    }
902
903
60
    if (!c->in_place)
904
60
      buffer->sync ();
905
60
  }
void AAT::StateTableDriver<AAT::ExtendedTypes, AAT::Format1Entry<true>::EntryData>::drive<AAT::KerxSubTableFormat1<AAT::KerxSubTableHeader>::driver_context_t>(AAT::KerxSubTableFormat1<AAT::KerxSubTableHeader>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Line
Count
Source
782
60
  {
783
60
    if (!c->in_place)
784
0
      buffer->clear_output ();
785
786
60
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
60
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
1.14k
    for (buffer->idx = 0; buffer->successful;)
790
1.14k
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
1.14k
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
1.14k
      unsigned int klass = buffer->idx < buffer->len ?
818
1.08k
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
1.14k
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
1.14k
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
1.14k
      const EntryT &entry = machine.get_entry (state, klass);
822
1.14k
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
1.14k
      const EntryT *wouldbe_entry;
853
1.14k
      bool safe_to_break =
854
  /* 1. */
855
1.14k
  !c->is_actionable (this, entry)
856
1.14k
      &&
857
  /* 2. */
858
1.14k
  (
859
    /* 2a. */
860
0
    state == StateTableT::STATE_START_OF_TEXT
861
0
  ||
862
    /* 2b. */
863
0
    (
864
0
      (entry.flags & context_t::DontAdvance) &&
865
0
      next_state == StateTableT::STATE_START_OF_TEXT
866
0
    )
867
0
  ||
868
    /* 2c. */
869
0
    (
870
0
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
0
    ,
872
      /* 2c'. */
873
0
      !c->is_actionable (this, *wouldbe_entry)
874
0
    &&
875
      /* 2c". */
876
0
      (
877
0
        next_state == machine.new_state (wouldbe_entry->newState)
878
0
      &&
879
0
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
0
      )
881
0
    )
882
0
  )
883
1.14k
      &&
884
  /* 3. */
885
1.14k
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
1.14k
      ;
887
888
1.14k
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
1.02k
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
1.14k
      c->transition (this, entry);
892
893
1.14k
      state = next_state;
894
1.14k
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
1.14k
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
60
  break;
898
899
1.08k
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
1.08k
  (void) buffer->next_glyph ();
901
1.08k
    }
902
903
60
    if (!c->in_place)
904
0
      buffer->sync ();
905
60
  }
void AAT::StateTableDriver<AAT::ExtendedTypes, AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::EntryData>::drive<AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::driver_context_t>(AAT::KerxSubTableFormat4<AAT::KerxSubTableHeader>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Line
Count
Source
782
300
  {
783
300
    if (!c->in_place)
784
0
      buffer->clear_output ();
785
786
300
    int state = StateTableT::STATE_START_OF_TEXT;
787
    // If there's only one range, we already checked the flag.
788
300
    auto *last_range = ac->range_flags && (ac->range_flags->length > 1) ? &(*ac->range_flags)[0] : nullptr;
789
5.70k
    for (buffer->idx = 0; buffer->successful;)
790
5.70k
    {
791
      /* This block is copied in NoncontextualSubtable::apply. Keep in sync. */
792
5.70k
      if (last_range)
793
0
      {
794
0
  auto *range = last_range;
795
0
  if (buffer->idx < buffer->len)
796
0
  {
797
0
    unsigned cluster = buffer->cur().cluster;
798
0
    while (cluster < range->cluster_first)
799
0
      range--;
800
0
    while (cluster > range->cluster_last)
801
0
      range++;
802
803
804
0
    last_range = range;
805
0
  }
806
0
  if (!(range->flags & ac->subtable_flags))
807
0
  {
808
0
    if (buffer->idx == buffer->len || unlikely (!buffer->successful))
809
0
      break;
810
811
0
    state = StateTableT::STATE_START_OF_TEXT;
812
0
    (void) buffer->next_glyph ();
813
0
    continue;
814
0
  }
815
0
      }
816
817
5.70k
      unsigned int klass = buffer->idx < buffer->len ?
818
5.40k
         machine.get_class (buffer->cur().codepoint, num_glyphs) :
819
5.70k
         (unsigned) StateTableT::CLASS_END_OF_TEXT;
820
5.70k
      DEBUG_MSG (APPLY, nullptr, "c%u at %u", klass, buffer->idx);
821
5.70k
      const EntryT &entry = machine.get_entry (state, klass);
822
5.70k
      const int next_state = machine.new_state (entry.newState);
823
824
      /* Conditions under which it's guaranteed safe-to-break before current glyph:
825
       *
826
       * 1. There was no action in this transition; and
827
       *
828
       * 2. If we break before current glyph, the results will be the same. That
829
       *    is guaranteed if:
830
       *
831
       *    2a. We were already in start-of-text state; or
832
       *
833
       *    2b. We are epsilon-transitioning to start-of-text state; or
834
       *
835
       *    2c. Starting from start-of-text state seeing current glyph:
836
       *
837
       *        2c'. There won't be any actions; and
838
       *
839
       *        2c". We would end up in the same state that we were going to end up
840
       *             in now, including whether epsilon-transitioning.
841
       *
842
       *    and
843
       *
844
       * 3. If we break before current glyph, there won't be any end-of-text action
845
       *    after previous glyph.
846
       *
847
       * This triples the transitions we need to look up, but is worth returning
848
       * granular unsafe-to-break results. See eg.:
849
       *
850
       *   https://github.com/harfbuzz/harfbuzz/issues/2860
851
       */
852
5.70k
      const EntryT *wouldbe_entry;
853
5.70k
      bool safe_to_break =
854
  /* 1. */
855
5.70k
  !c->is_actionable (this, entry)
856
5.70k
      &&
857
  /* 2. */
858
5.70k
  (
859
    /* 2a. */
860
0
    state == StateTableT::STATE_START_OF_TEXT
861
0
  ||
862
    /* 2b. */
863
0
    (
864
0
      (entry.flags & context_t::DontAdvance) &&
865
0
      next_state == StateTableT::STATE_START_OF_TEXT
866
0
    )
867
0
  ||
868
    /* 2c. */
869
0
    (
870
0
      wouldbe_entry = &machine.get_entry (StateTableT::STATE_START_OF_TEXT, klass)
871
0
    ,
872
      /* 2c'. */
873
0
      !c->is_actionable (this, *wouldbe_entry)
874
0
    &&
875
      /* 2c". */
876
0
      (
877
0
        next_state == machine.new_state (wouldbe_entry->newState)
878
0
      &&
879
0
        (entry.flags & context_t::DontAdvance) == (wouldbe_entry->flags & context_t::DontAdvance)
880
0
      )
881
0
    )
882
0
  )
883
5.70k
      &&
884
  /* 3. */
885
5.70k
  !c->is_actionable (this, machine.get_entry (state, StateTableT::CLASS_END_OF_TEXT))
886
5.70k
      ;
887
888
5.70k
      if (!safe_to_break && buffer->backtrack_len () && buffer->idx < buffer->len)
889
5.10k
  buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
890
891
5.70k
      c->transition (this, entry);
892
893
5.70k
      state = next_state;
894
5.70k
      DEBUG_MSG (APPLY, nullptr, "s%d", state);
895
896
5.70k
      if (buffer->idx == buffer->len || unlikely (!buffer->successful))
897
300
  break;
898
899
5.40k
      if (!(entry.flags & context_t::DontAdvance) || buffer->max_ops-- <= 0)
900
5.40k
  (void) buffer->next_glyph ();
901
5.40k
    }
902
903
300
    if (!c->in_place)
904
0
      buffer->sync ();
905
300
  }
Unexecuted instantiation: void AAT::StateTableDriver<AAT::ObsoleteTypes, void>::drive<AAT::KerxSubTableFormat1<OT::KernOTSubTableHeader>::driver_context_t>(AAT::KerxSubTableFormat1<OT::KernOTSubTableHeader>::driver_context_t*, AAT::hb_aat_apply_context_t*)
Unexecuted instantiation: void AAT::StateTableDriver<AAT::ObsoleteTypes, void>::drive<AAT::KerxSubTableFormat1<OT::KernAATSubTableHeader>::driver_context_t>(AAT::KerxSubTableFormat1<OT::KernAATSubTableHeader>::driver_context_t*, AAT::hb_aat_apply_context_t*)
906
907
  public:
908
  const StateTableT &machine;
909
  hb_buffer_t *buffer;
910
  unsigned int num_glyphs;
911
};
912
913
914
} /* namespace AAT */
915
916
917
#endif /* HB_AAT_LAYOUT_COMMON_HH */