Coverage Report

Created: 2026-06-30 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/harfbuzz/src/OT/Layout/GPOS/MarkMarkPosFormat1.hh
Line
Count
Source
1
#ifndef OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
2
#define OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH
3
4
#include "MarkMarkPosFormat1.hh"
5
6
namespace OT {
7
namespace Layout {
8
namespace GPOS_impl {
9
10
typedef AnchorMatrix Mark2Array;        /* mark2-major--
11
                                         * in order of Mark2Coverage Index--,
12
                                         * mark1-minor--
13
                                         * ordered by class--zero-based. */
14
15
template <typename Types>
16
struct MarkMarkPosFormat1_2
17
{
18
  protected:
19
  HBUINT16      format;                 /* Format identifier--format = 1 */
20
  typename Types::template OffsetTo<Coverage>
21
                mark1Coverage;          /* Offset to Combining Mark1 Coverage
22
                                         * table--from beginning of MarkMarkPos
23
                                         * subtable */
24
  typename Types::template OffsetTo<Coverage>
25
                mark2Coverage;          /* Offset to Combining Mark2 Coverage
26
                                         * table--from beginning of MarkMarkPos
27
                                         * subtable */
28
  HBUINT16      classCount;             /* Number of defined mark classes */
29
  typename Types::template OffsetTo<MarkArray>
30
                mark1Array;             /* Offset to Mark1Array table--from
31
                                         * beginning of MarkMarkPos subtable */
32
  typename Types::template OffsetTo<Mark2Array>
33
                mark2Array;             /* Offset to Mark2Array table--from
34
                                         * beginning of MarkMarkPos subtable */
35
  public:
36
  DEFINE_SIZE_STATIC (4 + 4 * Types::size);
37
38
  bool sanitize (hb_sanitize_context_t *c) const
39
10.5k
  {
40
10.5k
    TRACE_SANITIZE (this);
41
10.5k
    return_trace (c->check_struct (this) &&
42
10.5k
                  mark1Coverage.sanitize (c, this) &&
43
10.5k
                  mark2Coverage.sanitize (c, this) &&
44
10.5k
                  mark1Array.sanitize (c, this) &&
45
10.5k
      hb_barrier () &&
46
10.5k
                  mark2Array.sanitize (c, this, (unsigned int) classCount));
47
10.5k
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
39
6.42k
  {
40
6.42k
    TRACE_SANITIZE (this);
41
6.42k
    return_trace (c->check_struct (this) &&
42
6.42k
                  mark1Coverage.sanitize (c, this) &&
43
6.42k
                  mark2Coverage.sanitize (c, this) &&
44
6.42k
                  mark1Array.sanitize (c, this) &&
45
6.42k
      hb_barrier () &&
46
6.42k
                  mark2Array.sanitize (c, this, (unsigned int) classCount));
47
6.42k
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::sanitize(hb_sanitize_context_t*) const
Line
Count
Source
39
4.10k
  {
40
4.10k
    TRACE_SANITIZE (this);
41
4.10k
    return_trace (c->check_struct (this) &&
42
4.10k
                  mark1Coverage.sanitize (c, this) &&
43
4.10k
                  mark2Coverage.sanitize (c, this) &&
44
4.10k
                  mark1Array.sanitize (c, this) &&
45
4.10k
      hb_barrier () &&
46
4.10k
                  mark2Array.sanitize (c, this, (unsigned int) classCount));
47
4.10k
  }
48
49
  bool intersects (const hb_set_t *glyphs) const
50
2.84k
  {
51
2.84k
    return (this+mark1Coverage).intersects (glyphs) &&
52
2.01k
           (this+mark2Coverage).intersects (glyphs);
53
2.84k
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::intersects(hb_set_t const*) const
Line
Count
Source
50
2.32k
  {
51
2.32k
    return (this+mark1Coverage).intersects (glyphs) &&
52
1.58k
           (this+mark2Coverage).intersects (glyphs);
53
2.32k
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::intersects(hb_set_t const*) const
Line
Count
Source
50
529
  {
51
529
    return (this+mark1Coverage).intersects (glyphs) &&
52
430
           (this+mark2Coverage).intersects (glyphs);
53
529
  }
54
55
1.35k
  void closure_lookups (hb_closure_lookups_context_t *c) const {}
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::closure_lookups(OT::hb_closure_lookups_context_t*) const
Line
Count
Source
55
1.04k
  void closure_lookups (hb_closure_lookups_context_t *c) const {}
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::closure_lookups(OT::hb_closure_lookups_context_t*) const
Line
Count
Source
55
306
  void closure_lookups (hb_closure_lookups_context_t *c) const {}
56
57
  void collect_variation_indices (hb_collect_variation_indices_context_t *c) const
58
1.07k
  {
59
1.07k
    + hb_zip (this+mark1Coverage, this+mark1Array)
60
1.07k
    | hb_filter (c->glyph_set, hb_first)
61
1.07k
    | hb_map (hb_second)
62
3.79k
    | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::collect_variation_indices(OT::hb_collect_variation_indices_context_t*) const::{lambda(OT::Layout::GPOS_impl::MarkRecord const&)#1}::operator()(OT::Layout::GPOS_impl::MarkRecord const&) const
Line
Count
Source
62
3.79k
    | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::collect_variation_indices(OT::hb_collect_variation_indices_context_t*) const::{lambda(OT::Layout::GPOS_impl::MarkRecord const&)#1}::operator()(OT::Layout::GPOS_impl::MarkRecord const&) const
Line
Count
Source
62
5
    | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
63
1.07k
    ;
64
65
1.07k
    hb_map_t klass_mapping;
66
1.07k
    Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
67
68
1.07k
    unsigned mark2_count = (this+mark2Array).rows;
69
1.07k
    auto mark2_iter =
70
1.07k
    + hb_zip (this+mark2Coverage, hb_range (mark2_count))
71
1.07k
    | hb_filter (c->glyph_set, hb_first)
72
1.07k
    | hb_map (hb_second)
73
1.07k
    ;
74
75
1.07k
    hb_sorted_vector_t<unsigned> mark2_indexes;
76
1.07k
    for (const unsigned row : mark2_iter)
77
873
    {
78
873
      + hb_range ((unsigned) classCount)
79
873
      | hb_filter (klass_mapping)
80
873
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::collect_variation_indices(OT::hb_collect_variation_indices_context_t*) const::{lambda(unsigned int)#1}::operator()(unsigned int) const
Line
Count
Source
80
838
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::collect_variation_indices(OT::hb_collect_variation_indices_context_t*) const::{lambda(unsigned int)#1}::operator()(unsigned int) const
81
873
      | hb_sink (mark2_indexes)
82
873
      ;
83
873
    }
84
1.07k
    (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
85
1.07k
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::collect_variation_indices(OT::hb_collect_variation_indices_context_t*) const
Line
Count
Source
58
952
  {
59
952
    + hb_zip (this+mark1Coverage, this+mark1Array)
60
952
    | hb_filter (c->glyph_set, hb_first)
61
952
    | hb_map (hb_second)
62
952
    | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
63
952
    ;
64
65
952
    hb_map_t klass_mapping;
66
952
    Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
67
68
952
    unsigned mark2_count = (this+mark2Array).rows;
69
952
    auto mark2_iter =
70
952
    + hb_zip (this+mark2Coverage, hb_range (mark2_count))
71
952
    | hb_filter (c->glyph_set, hb_first)
72
952
    | hb_map (hb_second)
73
952
    ;
74
75
952
    hb_sorted_vector_t<unsigned> mark2_indexes;
76
952
    for (const unsigned row : mark2_iter)
77
845
    {
78
845
      + hb_range ((unsigned) classCount)
79
845
      | hb_filter (klass_mapping)
80
845
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
81
845
      | hb_sink (mark2_indexes)
82
845
      ;
83
845
    }
84
952
    (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
85
952
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::collect_variation_indices(OT::hb_collect_variation_indices_context_t*) const
Line
Count
Source
58
121
  {
59
121
    + hb_zip (this+mark1Coverage, this+mark1Array)
60
121
    | hb_filter (c->glyph_set, hb_first)
61
121
    | hb_map (hb_second)
62
121
    | hb_apply ([&] (const MarkRecord& record) { record.collect_variation_indices (c, &(this+mark1Array)); })
63
121
    ;
64
65
121
    hb_map_t klass_mapping;
66
121
    Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, *c->glyph_set, &klass_mapping);
67
68
121
    unsigned mark2_count = (this+mark2Array).rows;
69
121
    auto mark2_iter =
70
121
    + hb_zip (this+mark2Coverage, hb_range (mark2_count))
71
121
    | hb_filter (c->glyph_set, hb_first)
72
121
    | hb_map (hb_second)
73
121
    ;
74
75
121
    hb_sorted_vector_t<unsigned> mark2_indexes;
76
121
    for (const unsigned row : mark2_iter)
77
28
    {
78
28
      + hb_range ((unsigned) classCount)
79
28
      | hb_filter (klass_mapping)
80
28
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
81
28
      | hb_sink (mark2_indexes)
82
28
      ;
83
28
    }
84
121
    (this+mark2Array).collect_variation_indices (c, mark2_indexes.iter ());
85
121
  }
86
87
  void collect_glyphs (hb_collect_glyphs_context_t *c) const
88
0
  {
89
0
    if (unlikely (!(this+mark1Coverage).collect_coverage (c->input))) return;
90
0
    if (unlikely (!(this+mark2Coverage).collect_coverage (c->input))) return;
91
0
  }
Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::collect_glyphs(OT::hb_collect_glyphs_context_t*) const
Unexecuted instantiation: OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::collect_glyphs(OT::hb_collect_glyphs_context_t*) const
92
93
2.87k
  const Coverage &get_coverage () const { return this+mark1Coverage; }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::get_coverage() const
Line
Count
Source
93
1.20k
  const Coverage &get_coverage () const { return this+mark1Coverage; }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::get_coverage() const
Line
Count
Source
93
1.67k
  const Coverage &get_coverage () const { return this+mark1Coverage; }
94
95
  bool apply (hb_ot_apply_context_t *c) const
96
1.34M
  {
97
1.34M
    TRACE_APPLY (this);
98
1.34M
    hb_buffer_t *buffer = c->buffer;
99
1.34M
    unsigned int mark1_index = (this+mark1Coverage).get_coverage  (buffer->cur().codepoint);
100
1.34M
    if (likely (mark1_index == NOT_COVERED)) return_trace (false);
101
102
    /* now we search backwards for a suitable mark glyph until a non-mark glyph */
103
1.29M
    auto &skippy_iter = c->iter_input;
104
1.29M
    skippy_iter.reset_fast (buffer->idx);
105
1.29M
    skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
106
1.29M
    unsigned unsafe_from;
107
1.29M
    if (unlikely (!skippy_iter.prev (&unsafe_from)))
108
10.3k
    {
109
10.3k
      buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
110
10.3k
      return_trace (false);
111
10.3k
    }
112
113
1.28M
    if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])))
114
1.24M
    {
115
1.24M
      buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
116
1.24M
      return_trace (false);
117
1.24M
    }
118
119
47.3k
    unsigned int j = skippy_iter.idx;
120
121
47.3k
    unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
122
47.3k
    unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
123
47.3k
    unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
124
47.3k
    unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
125
126
47.3k
    if (likely (id1 == id2))
127
44.8k
    {
128
44.8k
      if (id1 == 0) /* Marks belonging to the same base. */
129
43.6k
        goto good;
130
1.14k
      else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
131
611
        goto good;
132
44.8k
    }
133
2.56k
    else
134
2.56k
    {
135
      /* If ligature ids don't match, it may be the case that one of the marks
136
       * itself is a ligature.  In which case match. */
137
2.56k
      if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
138
1.22k
        goto good;
139
2.56k
    }
140
141
    /* Didn't match. */
142
1.86k
    buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
143
1.86k
    return_trace (false);
144
145
45.5k
    good:
146
45.5k
    unsigned int mark2_index = (this+mark2Coverage).get_coverage  (buffer->info[j].codepoint);
147
45.5k
    if (mark2_index == NOT_COVERED)
148
16.0k
    {
149
16.0k
      buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
150
16.0k
      return_trace (false);
151
16.0k
    }
152
153
45.5k
    return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
154
45.5k
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::apply(OT::hb_ot_apply_context_t*) const
Line
Count
Source
96
1.32M
  {
97
1.32M
    TRACE_APPLY (this);
98
1.32M
    hb_buffer_t *buffer = c->buffer;
99
1.32M
    unsigned int mark1_index = (this+mark1Coverage).get_coverage  (buffer->cur().codepoint);
100
1.32M
    if (likely (mark1_index == NOT_COVERED)) return_trace (false);
101
102
    /* now we search backwards for a suitable mark glyph until a non-mark glyph */
103
1.28M
    auto &skippy_iter = c->iter_input;
104
1.28M
    skippy_iter.reset_fast (buffer->idx);
105
1.28M
    skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
106
1.28M
    unsigned unsafe_from;
107
1.28M
    if (unlikely (!skippy_iter.prev (&unsafe_from)))
108
8.79k
    {
109
8.79k
      buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
110
8.79k
      return_trace (false);
111
8.79k
    }
112
113
1.27M
    if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])))
114
1.22M
    {
115
1.22M
      buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
116
1.22M
      return_trace (false);
117
1.22M
    }
118
119
45.8k
    unsigned int j = skippy_iter.idx;
120
121
45.8k
    unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
122
45.8k
    unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
123
45.8k
    unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
124
45.8k
    unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
125
126
45.8k
    if (likely (id1 == id2))
127
43.5k
    {
128
43.5k
      if (id1 == 0) /* Marks belonging to the same base. */
129
42.6k
        goto good;
130
967
      else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
131
552
        goto good;
132
43.5k
    }
133
2.31k
    else
134
2.31k
    {
135
      /* If ligature ids don't match, it may be the case that one of the marks
136
       * itself is a ligature.  In which case match. */
137
2.31k
      if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
138
1.09k
        goto good;
139
2.31k
    }
140
141
    /* Didn't match. */
142
1.63k
    buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
143
1.63k
    return_trace (false);
144
145
44.2k
    good:
146
44.2k
    unsigned int mark2_index = (this+mark2Coverage).get_coverage  (buffer->info[j].codepoint);
147
44.2k
    if (mark2_index == NOT_COVERED)
148
15.2k
    {
149
15.2k
      buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
150
15.2k
      return_trace (false);
151
15.2k
    }
152
153
28.9k
    return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
154
44.2k
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::apply(OT::hb_ot_apply_context_t*) const
Line
Count
Source
96
19.5k
  {
97
19.5k
    TRACE_APPLY (this);
98
19.5k
    hb_buffer_t *buffer = c->buffer;
99
19.5k
    unsigned int mark1_index = (this+mark1Coverage).get_coverage  (buffer->cur().codepoint);
100
19.5k
    if (likely (mark1_index == NOT_COVERED)) return_trace (false);
101
102
    /* now we search backwards for a suitable mark glyph until a non-mark glyph */
103
17.9k
    auto &skippy_iter = c->iter_input;
104
17.9k
    skippy_iter.reset_fast (buffer->idx);
105
17.9k
    skippy_iter.set_lookup_props (c->lookup_props & ~(uint32_t)LookupFlag::IgnoreFlags);
106
17.9k
    unsigned unsafe_from;
107
17.9k
    if (unlikely (!skippy_iter.prev (&unsafe_from)))
108
1.53k
    {
109
1.53k
      buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
110
1.53k
      return_trace (false);
111
1.53k
    }
112
113
16.4k
    if (likely (!_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx])))
114
14.9k
    {
115
14.9k
      buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
116
14.9k
      return_trace (false);
117
14.9k
    }
118
119
1.48k
    unsigned int j = skippy_iter.idx;
120
121
1.48k
    unsigned int id1 = _hb_glyph_info_get_lig_id (&buffer->cur());
122
1.48k
    unsigned int id2 = _hb_glyph_info_get_lig_id (&buffer->info[j]);
123
1.48k
    unsigned int comp1 = _hb_glyph_info_get_lig_comp (&buffer->cur());
124
1.48k
    unsigned int comp2 = _hb_glyph_info_get_lig_comp (&buffer->info[j]);
125
126
1.48k
    if (likely (id1 == id2))
127
1.23k
    {
128
1.23k
      if (id1 == 0) /* Marks belonging to the same base. */
129
1.05k
        goto good;
130
179
      else if (comp1 == comp2) /* Marks belonging to the same ligature component. */
131
59
        goto good;
132
1.23k
    }
133
247
    else
134
247
    {
135
      /* If ligature ids don't match, it may be the case that one of the marks
136
       * itself is a ligature.  In which case match. */
137
247
      if ((id1 > 0 && !comp1) || (id2 > 0 && !comp2))
138
135
        goto good;
139
247
    }
140
141
    /* Didn't match. */
142
232
    buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
143
232
    return_trace (false);
144
145
1.25k
    good:
146
1.25k
    unsigned int mark2_index = (this+mark2Coverage).get_coverage  (buffer->info[j].codepoint);
147
1.25k
    if (mark2_index == NOT_COVERED)
148
826
    {
149
826
      buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
150
826
      return_trace (false);
151
826
    }
152
153
424
    return_trace ((this+mark1Array).apply (c, mark1_index, mark2_index, this+mark2Array, classCount, j));
154
1.25k
  }
155
156
  bool subset (hb_subset_context_t *c) const
157
912
  {
158
912
    TRACE_SUBSET (this);
159
912
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
160
912
    const hb_map_t &glyph_map = *c->plan->glyph_map;
161
162
912
    auto *out = c->serializer->start_embed (*this);
163
912
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
164
912
    out->format = format;
165
166
912
    hb_map_t klass_mapping;
167
912
    Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
168
169
912
    if (!klass_mapping.get_population ()) return_trace (false);
170
788
    out->classCount = klass_mapping.get_population ();
171
172
788
    auto mark1_iter =
173
788
    + hb_zip (this+mark1Coverage, this+mark1Array)
174
788
    | hb_filter (glyphset, hb_first)
175
788
    ;
176
177
788
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
178
788
    + mark1_iter
179
788
    | hb_map (hb_first)
180
788
    | hb_map (glyph_map)
181
788
    | hb_sink (new_coverage)
182
788
    ;
183
184
788
    if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
185
17
      return_trace (false);
186
187
771
    if (unlikely (!out->mark1Array.serialize_subset (c, mark1Array, this,
188
771
                 (this+mark1Coverage).iter (),
189
771
                 &klass_mapping)))
190
90
      return_trace (false);
191
192
681
    unsigned mark2count = (this+mark2Array).rows;
193
681
    auto mark2_iter =
194
681
    + hb_zip (this+mark2Coverage, hb_range (mark2count))
195
681
    | hb_filter (glyphset, hb_first)
196
681
    ;
197
198
681
    new_coverage.reset ();
199
681
    hb_sorted_vector_t<unsigned> mark2_indexes;
200
681
    auto &mark2_array = (this+mark2Array);
201
681
    for (const auto _ : + mark2_iter)
202
18.7k
    {
203
18.7k
      unsigned row = _.second;
204
205
18.7k
      bool non_empty = + hb_range ((unsigned) classCount)
206
18.7k
                       | hb_filter (klass_mapping)
207
20.7k
                       | hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); })
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::subset(hb_subset_context_t*) const::{lambda(unsigned int)#1}::operator()(unsigned int) const
Line
Count
Source
207
13.8k
                       | hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); })
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::subset(hb_subset_context_t*) const::{lambda(unsigned int)#1}::operator()(unsigned int) const
Line
Count
Source
207
6.88k
                       | hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); })
208
18.7k
                       | hb_any
209
18.7k
                       ;
210
211
18.7k
      if (!non_empty) continue;
212
213
5.13k
      hb_codepoint_t new_g = glyph_map.get ( _.first);
214
5.13k
      new_coverage.push (new_g);
215
216
5.13k
      + hb_range ((unsigned) classCount)
217
5.13k
      | hb_filter (klass_mapping)
218
11.4k
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::subset(hb_subset_context_t*) const::{lambda(unsigned int)#2}::operator()(unsigned int) const
Line
Count
Source
218
11.0k
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::subset(hb_subset_context_t*) const::{lambda(unsigned int)#2}::operator()(unsigned int) const
Line
Count
Source
218
418
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
219
5.13k
      | hb_sink (mark2_indexes)
220
5.13k
      ;
221
5.13k
    }
222
223
681
    if (!new_coverage) return_trace (false);
224
394
    if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
225
1
      return_trace (false);
226
227
394
    return_trace (out->mark2Array.serialize_subset (c, mark2Array, this,
228
394
                mark2_iter.len (),
229
394
                mark2_indexes.iter ()));
230
231
394
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::SmallTypes>::subset(hb_subset_context_t*) const
Line
Count
Source
157
732
  {
158
732
    TRACE_SUBSET (this);
159
732
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
160
732
    const hb_map_t &glyph_map = *c->plan->glyph_map;
161
162
732
    auto *out = c->serializer->start_embed (*this);
163
732
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
164
732
    out->format = format;
165
166
732
    hb_map_t klass_mapping;
167
732
    Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
168
169
732
    if (!klass_mapping.get_population ()) return_trace (false);
170
616
    out->classCount = klass_mapping.get_population ();
171
172
616
    auto mark1_iter =
173
616
    + hb_zip (this+mark1Coverage, this+mark1Array)
174
616
    | hb_filter (glyphset, hb_first)
175
616
    ;
176
177
616
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
178
616
    + mark1_iter
179
616
    | hb_map (hb_first)
180
616
    | hb_map (glyph_map)
181
616
    | hb_sink (new_coverage)
182
616
    ;
183
184
616
    if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
185
17
      return_trace (false);
186
187
599
    if (unlikely (!out->mark1Array.serialize_subset (c, mark1Array, this,
188
599
                 (this+mark1Coverage).iter (),
189
599
                 &klass_mapping)))
190
70
      return_trace (false);
191
192
529
    unsigned mark2count = (this+mark2Array).rows;
193
529
    auto mark2_iter =
194
529
    + hb_zip (this+mark2Coverage, hb_range (mark2count))
195
529
    | hb_filter (glyphset, hb_first)
196
529
    ;
197
198
529
    new_coverage.reset ();
199
529
    hb_sorted_vector_t<unsigned> mark2_indexes;
200
529
    auto &mark2_array = (this+mark2Array);
201
529
    for (const auto _ : + mark2_iter)
202
7.14k
    {
203
7.14k
      unsigned row = _.second;
204
205
7.14k
      bool non_empty = + hb_range ((unsigned) classCount)
206
7.14k
                       | hb_filter (klass_mapping)
207
7.14k
                       | hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); })
208
7.14k
                       | hb_any
209
7.14k
                       ;
210
211
7.14k
      if (!non_empty) continue;
212
213
4.95k
      hb_codepoint_t new_g = glyph_map.get ( _.first);
214
4.95k
      new_coverage.push (new_g);
215
216
4.95k
      + hb_range ((unsigned) classCount)
217
4.95k
      | hb_filter (klass_mapping)
218
4.95k
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
219
4.95k
      | hb_sink (mark2_indexes)
220
4.95k
      ;
221
4.95k
    }
222
223
529
    if (!new_coverage) return_trace (false);
224
331
    if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
225
1
      return_trace (false);
226
227
331
    return_trace (out->mark2Array.serialize_subset (c, mark2Array, this,
228
331
                mark2_iter.len (),
229
331
                mark2_indexes.iter ()));
230
231
331
  }
OT::Layout::GPOS_impl::MarkMarkPosFormat1_2<OT::Layout::MediumTypes>::subset(hb_subset_context_t*) const
Line
Count
Source
157
180
  {
158
180
    TRACE_SUBSET (this);
159
180
    const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
160
180
    const hb_map_t &glyph_map = *c->plan->glyph_map;
161
162
180
    auto *out = c->serializer->start_embed (*this);
163
180
    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
164
180
    out->format = format;
165
166
180
    hb_map_t klass_mapping;
167
180
    Markclass_closure_and_remap_indexes (this+mark1Coverage, this+mark1Array, glyphset, &klass_mapping);
168
169
180
    if (!klass_mapping.get_population ()) return_trace (false);
170
172
    out->classCount = klass_mapping.get_population ();
171
172
172
    auto mark1_iter =
173
172
    + hb_zip (this+mark1Coverage, this+mark1Array)
174
172
    | hb_filter (glyphset, hb_first)
175
172
    ;
176
177
172
    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
178
172
    + mark1_iter
179
172
    | hb_map (hb_first)
180
172
    | hb_map (glyph_map)
181
172
    | hb_sink (new_coverage)
182
172
    ;
183
184
172
    if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
185
0
      return_trace (false);
186
187
172
    if (unlikely (!out->mark1Array.serialize_subset (c, mark1Array, this,
188
172
                 (this+mark1Coverage).iter (),
189
172
                 &klass_mapping)))
190
20
      return_trace (false);
191
192
152
    unsigned mark2count = (this+mark2Array).rows;
193
152
    auto mark2_iter =
194
152
    + hb_zip (this+mark2Coverage, hb_range (mark2count))
195
152
    | hb_filter (glyphset, hb_first)
196
152
    ;
197
198
152
    new_coverage.reset ();
199
152
    hb_sorted_vector_t<unsigned> mark2_indexes;
200
152
    auto &mark2_array = (this+mark2Array);
201
152
    for (const auto _ : + mark2_iter)
202
11.5k
    {
203
11.5k
      unsigned row = _.second;
204
205
11.5k
      bool non_empty = + hb_range ((unsigned) classCount)
206
11.5k
                       | hb_filter (klass_mapping)
207
11.5k
                       | hb_map ([&] (const unsigned col) { return !mark2_array.offset_is_null (row, col, (unsigned) classCount); })
208
11.5k
                       | hb_any
209
11.5k
                       ;
210
211
11.5k
      if (!non_empty) continue;
212
213
186
      hb_codepoint_t new_g = glyph_map.get ( _.first);
214
186
      new_coverage.push (new_g);
215
216
186
      + hb_range ((unsigned) classCount)
217
186
      | hb_filter (klass_mapping)
218
186
      | hb_map ([&] (const unsigned col) { return row * (unsigned) classCount + col; })
219
186
      | hb_sink (mark2_indexes)
220
186
      ;
221
186
    }
222
223
152
    if (!new_coverage) return_trace (false);
224
63
    if (!out->mark2Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
225
0
      return_trace (false);
226
227
63
    return_trace (out->mark2Array.serialize_subset (c, mark2Array, this,
228
63
                mark2_iter.len (),
229
63
                mark2_indexes.iter ()));
230
231
63
  }
232
};
233
234
235
}
236
}
237
}
238
239
#endif /* OT_LAYOUT_GPOS_MARKMARKPOSFORMAT1_HH */