Coverage Report

Created: 2025-10-14 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/OT/Layout/GSUB/ReverseChainSingleSubstFormat1.hh
Line
Count
Source
1
#ifndef OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH
2
#define OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH
3
4
#include "Common.hh"
5
6
namespace OT {
7
namespace Layout {
8
namespace GSUB_impl {
9
10
struct ReverseChainSingleSubstFormat1
11
{
12
  protected:
13
  HBUINT16      format;                 /* Format identifier--format = 1 */
14
  Offset16To<Coverage>
15
                coverage;               /* Offset to Coverage table--from
16
                                         * beginning of table */
17
  Array16OfOffset16To<Coverage>
18
                backtrack;              /* Array of coverage tables
19
                                         * in backtracking sequence, in glyph
20
                                         * sequence order */
21
  Array16OfOffset16To<Coverage>
22
                lookaheadX;             /* Array of coverage tables
23
                                         * in lookahead sequence, in glyph
24
                                         * sequence order */
25
  Array16Of<HBGlyphID16>
26
                substituteX;            /* Array of substitute
27
                                         * GlyphIDs--ordered by Coverage Index */
28
  public:
29
  DEFINE_SIZE_MIN (10);
30
31
  bool sanitize (hb_sanitize_context_t *c) const
32
0
  {
33
0
    TRACE_SANITIZE (this);
34
0
    if (!(coverage.sanitize (c, this) && backtrack.sanitize (c, this)))
35
0
      return_trace (false);
36
0
    hb_barrier ();
37
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
38
0
    if (!lookahead.sanitize (c, this))
39
0
      return_trace (false);
40
0
    hb_barrier ();
41
0
    const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
42
0
    return_trace (substitute.sanitize (c));
43
0
  }
44
45
  bool intersects (const hb_set_t *glyphs) const
46
0
  {
47
0
    if (!(this+coverage).intersects (glyphs))
48
0
      return false;
49
50
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
51
52
0
    unsigned int count;
53
54
0
    count = backtrack.len;
55
0
    for (unsigned int i = 0; i < count; i++)
56
0
      if (!(this+backtrack[i]).intersects (glyphs))
57
0
        return false;
58
59
0
    count = lookahead.len;
60
0
    for (unsigned int i = 0; i < count; i++)
61
0
      if (!(this+lookahead[i]).intersects (glyphs))
62
0
        return false;
63
64
0
    return true;
65
0
  }
66
67
  bool may_have_non_1to1 () const
68
0
  { return false; }
69
70
  void closure (hb_closure_context_t *c) const
71
0
  {
72
0
    if (!intersects (c->glyphs)) return;
73
74
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
75
0
    const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
76
77
0
    + hb_zip (this+coverage, substitute)
78
0
    | hb_filter (c->parent_active_glyphs (), hb_first)
79
0
    | hb_map (hb_second)
80
0
    | hb_sink (c->output)
81
0
    ;
82
0
  }
83
84
0
  void closure_lookups (hb_closure_lookups_context_t *c) const {}
85
86
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
87
0
  {
88
0
    if (unlikely (!(this+coverage).collect_coverage (c->input))) return;
89
90
0
    unsigned int count;
91
92
0
    count = backtrack.len;
93
0
    for (unsigned int i = 0; i < count; i++)
94
0
      if (unlikely (!(this+backtrack[i]).collect_coverage (c->before))) return;
95
96
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
97
0
    count = lookahead.len;
98
0
    for (unsigned int i = 0; i < count; i++)
99
0
      if (unlikely (!(this+lookahead[i]).collect_coverage (c->after))) return;
100
101
0
    const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
102
0
    count = substitute.len;
103
0
    c->output->add_array (substitute.arrayZ, substitute.len);
104
0
  }
105
106
0
  const Coverage &get_coverage () const { return this+coverage; }
107
108
  bool would_apply (hb_would_apply_context_t *c) const
109
0
  { return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
110
111
  bool apply (hb_ot_apply_context_t *c) const
112
0
  {
113
0
    TRACE_APPLY (this);
114
0
    unsigned int index = (this+coverage).get_coverage (c->buffer->cur ().codepoint);
115
0
    if (index == NOT_COVERED) return_trace (false);
116
117
0
    if (unlikely (c->nesting_level_left != HB_MAX_NESTING_LEVEL))
118
0
      return_trace (false); /* No chaining to this type */
119
120
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
121
0
    const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
122
123
0
    if (unlikely (index >= substitute.len)) return_trace (false);
124
125
0
    unsigned int start_index = 0, end_index = 0;
126
0
    if (match_backtrack (c,
127
0
                         backtrack.len, (HBUINT16 *) backtrack.arrayZ,
128
0
                         match_coverage, this,
129
0
                         &start_index) &&
130
0
        match_lookahead (c,
131
0
                         lookahead.len, (HBUINT16 *) lookahead.arrayZ,
132
0
                         match_coverage, this,
133
0
                         c->buffer->idx + 1, &end_index))
134
0
    {
135
0
      c->buffer->unsafe_to_break_from_outbuffer (start_index, end_index);
136
137
0
      if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
138
0
      {
139
0
  c->buffer->message (c->font,
140
0
          "replacing glyph at %u (reverse chaining substitution)",
141
0
          c->buffer->idx);
142
0
      }
143
144
0
      c->replace_glyph_inplace (substitute[index]);
145
146
0
      if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
147
0
      {
148
0
  c->buffer->message (c->font,
149
0
          "replaced glyph at %u (reverse chaining substitution)",
150
0
          c->buffer->idx);
151
0
      }
152
153
      /* Note: We DON'T decrease buffer->idx.  The main loop does it
154
       * for us.  This is useful for preventing surprises if someone
155
       * calls us through a Context lookup. */
156
0
      return_trace (true);
157
0
    }
158
0
    else
159
0
    {
160
0
      c->buffer->unsafe_to_concat_from_outbuffer (start_index, end_index);
161
0
      return_trace (false);
162
0
    }
163
0
  }
164
165
  template<typename Iterator,
166
           hb_requires (hb_is_iterator (Iterator))>
167
  bool serialize_coverage_offset_array (hb_subset_context_t *c, Iterator it) const
168
0
  {
169
0
    TRACE_SERIALIZE (this);
170
0
    auto *out = c->serializer->start_embed<Array16OfOffset16To<Coverage>> ();
171
0
172
0
    if (unlikely (!c->serializer->allocate_size<HBUINT16> (HBUINT16::static_size)))
173
0
      return_trace (false);
174
0
175
0
    for (auto& offset : it) {
176
0
      auto *o = out->serialize_append (c->serializer);
177
0
      if (unlikely (!o) || !o->serialize_subset (c, offset, this))
178
0
        return_trace (false);
179
0
    }
180
0
181
0
    return_trace (true);
182
0
  }
183
184
  template<typename Iterator, typename BacktrackIterator, typename LookaheadIterator,
185
           hb_requires (hb_is_sorted_source_of (Iterator, hb_codepoint_pair_t)),
186
           hb_requires (hb_is_iterator (BacktrackIterator)),
187
           hb_requires (hb_is_iterator (LookaheadIterator))>
188
  bool serialize (hb_subset_context_t *c,
189
                  Iterator coverage_subst_iter,
190
                  BacktrackIterator backtrack_iter,
191
                  LookaheadIterator lookahead_iter) const
192
0
  {
193
0
    TRACE_SERIALIZE (this);
194
0
195
0
    auto *out = c->serializer->start_embed (this);
196
0
    if (unlikely (!c->serializer->embed (this->format))) return_trace (false);
197
0
    if (unlikely (!c->serializer->embed (this->coverage))) return_trace (false);
198
0
199
0
    if (!serialize_coverage_offset_array (c, backtrack_iter)) return_trace (false);
200
0
    if (!serialize_coverage_offset_array (c, lookahead_iter)) return_trace (false);
201
0
202
0
    auto *substitute_out = c->serializer->start_embed<Array16Of<HBGlyphID16>> ();
203
0
    auto substitutes =
204
0
    + coverage_subst_iter
205
0
    | hb_map (hb_second)
206
0
    ;
207
0
208
0
    auto glyphs =
209
0
    + coverage_subst_iter
210
0
    | hb_map_retains_sorting (hb_first)
211
0
    ;
212
0
    if (unlikely (! c->serializer->check_success (substitute_out->serialize (c->serializer, substitutes))))
213
0
        return_trace (false);
214
0
215
0
    if (unlikely (!out->coverage.serialize_serialize (c->serializer, glyphs)))
216
0
      return_trace (false);
217
0
    return_trace (true);
218
0
  }
Unexecuted instantiation: hb-ot-face.cc:_ZNK2OT6Layout9GSUB_impl30ReverseChainSingleSubstFormat19serializeI13hb_map_iter_tI16hb_filter_iter_tIS5_I13hb_zip_iter_tINS0_6Common8Coverage6iter_tE10hb_array_tIKNS_11HBGlyphID16EEERK8hb_set_tRK3$_6LPv0EESH_RK3$_7LSL_0EEZNKS2_6subsetEP19hb_subset_context_tEUl9hb_pair_tIjRSC_EE_L24hb_function_sortedness_t1ELSL_0EESA_IKNS_8OffsetToIS8_NS_7NumTypeILb1EtLj2EEEvLb1EEEES14_TnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_ST_IjjEEE5valuesrS16_18is_sorted_iteratorEvE4typeELSL_0ETnPNS15_IXsr17hb_is_iterator_ofIT0_NS1B_6item_tEEE5valueEvE4typeELSL_0ETnPNS15_IXsr17hb_is_iterator_ofIT1_NS1G_6item_tEEE5valueEvE4typeELSL_0EEEbSS_S16_S1B_S1G_
Unexecuted instantiation: hb-aat-layout.cc:_ZNK2OT6Layout9GSUB_impl30ReverseChainSingleSubstFormat19serializeI13hb_map_iter_tI16hb_filter_iter_tIS5_I13hb_zip_iter_tINS0_6Common8Coverage6iter_tE10hb_array_tIKNS_11HBGlyphID16EEERK8hb_set_tRK3$_6LPv0EESH_RK3$_7LSL_0EEZNKS2_6subsetEP19hb_subset_context_tEUl9hb_pair_tIjRSC_EE_L24hb_function_sortedness_t1ELSL_0EESA_IKNS_8OffsetToIS8_NS_7NumTypeILb1EtLj2EEEvLb1EEEES14_TnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_ST_IjjEEE5valuesrS16_18is_sorted_iteratorEvE4typeELSL_0ETnPNS15_IXsr17hb_is_iterator_ofIT0_NS1B_6item_tEEE5valueEvE4typeELSL_0ETnPNS15_IXsr17hb_is_iterator_ofIT1_NS1G_6item_tEEE5valueEvE4typeELSL_0EEEbSS_S16_S1B_S1G_
Unexecuted instantiation: hb-ot-layout.cc:_ZNK2OT6Layout9GSUB_impl30ReverseChainSingleSubstFormat19serializeI13hb_map_iter_tI16hb_filter_iter_tIS5_I13hb_zip_iter_tINS0_6Common8Coverage6iter_tE10hb_array_tIKNS_11HBGlyphID16EEERK8hb_set_tRK3$_6LPv0EESH_RK3$_7LSL_0EEZNKS2_6subsetEP19hb_subset_context_tEUl9hb_pair_tIjRSC_EE_L24hb_function_sortedness_t1ELSL_0EESA_IKNS_8OffsetToIS8_NS_7NumTypeILb1EtLj2EEEvLb1EEEES14_TnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_ST_IjjEEE5valuesrS16_18is_sorted_iteratorEvE4typeELSL_0ETnPNS15_IXsr17hb_is_iterator_ofIT0_NS1B_6item_tEEE5valueEvE4typeELSL_0ETnPNS15_IXsr17hb_is_iterator_ofIT1_NS1G_6item_tEEE5valueEvE4typeELSL_0EEEbSS_S16_S1B_S1G_
Unexecuted instantiation: hb-ot-shaper-arabic.cc:_ZNK2OT6Layout9GSUB_impl30ReverseChainSingleSubstFormat19serializeI13hb_map_iter_tI16hb_filter_iter_tIS5_I13hb_zip_iter_tINS0_6Common8Coverage6iter_tE10hb_array_tIKNS_11HBGlyphID16EEERK8hb_set_tRK3$_6LPv0EESH_RK3$_7LSL_0EEZNKS2_6subsetEP19hb_subset_context_tEUl9hb_pair_tIjRSC_EE_L24hb_function_sortedness_t1ELSL_0EESA_IKNS_8OffsetToIS8_NS_7NumTypeILb1EtLj2EEEvLb1EEEES14_TnPN12hb_enable_ifIXaasr15hb_is_source_ofIT_ST_IjjEEE5valuesrS16_18is_sorted_iteratorEvE4typeELSL_0ETnPNS15_IXsr17hb_is_iterator_ofIT0_NS1B_6item_tEEE5valueEvE4typeELSL_0ETnPNS15_IXsr17hb_is_iterator_ofIT1_NS1G_6item_tEEE5valueEvE4typeELSL_0EEEbSS_S16_S1B_S1G_
219
220
  bool subset (hb_subset_context_t *c) const
221
0
  {
222
0
    TRACE_SUBSET (this);
223
0
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
224
0
    const hb_map_t &glyph_map = *c->plan->glyph_map;
225
0
226
0
    const auto &lookahead = StructAfter<decltype (lookaheadX)> (backtrack);
227
0
    const auto &substitute = StructAfter<decltype (substituteX)> (lookahead);
228
0
229
0
    auto it =
230
0
    + hb_zip (this+coverage, substitute)
231
0
    | hb_filter (glyphset, hb_first)
232
0
    | hb_filter (glyphset, hb_second)
233
0
    | hb_map_retains_sorting ([&] (hb_pair_t<hb_codepoint_t, const HBGlyphID16 &> p) -> hb_codepoint_pair_t
234
0
                              { return hb_pair (glyph_map[p.first], glyph_map[p.second]); })
235
0
    ;
236
0
237
0
    return_trace (bool (it) && serialize (c, it, backtrack.iter (), lookahead.iter ()));
238
0
  }
239
};
240
241
}
242
}
243
}
244
245
#endif  /* HB_OT_LAYOUT_GSUB_REVERSECHAINSINGLESUBSTFORMAT1_HH */