comparison mupdf-source/thirdparty/harfbuzz/src/OT/Layout/GPOS/PairSet.hh @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 #ifndef OT_LAYOUT_GPOS_PAIRSET_HH
2 #define OT_LAYOUT_GPOS_PAIRSET_HH
3
4 #include "PairValueRecord.hh"
5
6 namespace OT {
7 namespace Layout {
8 namespace GPOS_impl {
9
10
11 template <typename Types>
12 struct PairSet
13 {
14 template <typename Types2>
15 friend struct PairPosFormat1_3;
16
17 using PairValueRecord = GPOS_impl::PairValueRecord<Types>;
18
19 protected:
20 HBUINT16 len; /* Number of PairValueRecords */
21 PairValueRecord firstPairValueRecord;
22 /* Array of PairValueRecords--ordered
23 * by GlyphID of the second glyph */
24 public:
25 DEFINE_SIZE_MIN (2);
26
27 struct sanitize_closure_t
28 {
29 const ValueFormat *valueFormats;
30 unsigned int len1; /* valueFormats[0].get_len() */
31 unsigned int stride; /* 1 + len1 + len2 */
32 };
33
34 bool sanitize (hb_sanitize_context_t *c, const sanitize_closure_t *closure) const
35 {
36 TRACE_SANITIZE (this);
37 if (!(c->check_struct (this)
38 && c->check_range (&firstPairValueRecord,
39 len,
40 HBUINT16::static_size,
41 closure->stride))) return_trace (false);
42
43 unsigned int count = len;
44 const PairValueRecord *record = &firstPairValueRecord;
45 return_trace (closure->valueFormats[0].sanitize_values_stride_unsafe (c, this, &record->values[0], count, closure->stride) &&
46 closure->valueFormats[1].sanitize_values_stride_unsafe (c, this, &record->values[closure->len1], count, closure->stride));
47 }
48
49 bool intersects (const hb_set_t *glyphs,
50 const ValueFormat *valueFormats) const
51 {
52 unsigned int len1 = valueFormats[0].get_len ();
53 unsigned int len2 = valueFormats[1].get_len ();
54 unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
55
56 const PairValueRecord *record = &firstPairValueRecord;
57 unsigned int count = len;
58 for (unsigned int i = 0; i < count; i++)
59 {
60 if (glyphs->has (record->secondGlyph))
61 return true;
62 record = &StructAtOffset<const PairValueRecord> (record, record_size);
63 }
64 return false;
65 }
66
67 void collect_glyphs (hb_collect_glyphs_context_t *c,
68 const ValueFormat *valueFormats) const
69 {
70 unsigned int len1 = valueFormats[0].get_len ();
71 unsigned int len2 = valueFormats[1].get_len ();
72 unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
73
74 const PairValueRecord *record = &firstPairValueRecord;
75 c->input->add_array (&record->secondGlyph, len, record_size);
76 }
77
78 void collect_variation_indices (hb_collect_variation_indices_context_t *c,
79 const ValueFormat *valueFormats) const
80 {
81 unsigned len1 = valueFormats[0].get_len ();
82 unsigned len2 = valueFormats[1].get_len ();
83 unsigned record_size = HBUINT16::static_size * (1 + len1 + len2);
84
85 const PairValueRecord *record = &firstPairValueRecord;
86 unsigned count = len;
87 for (unsigned i = 0; i < count; i++)
88 {
89 if (c->glyph_set->has (record->secondGlyph))
90 { record->collect_variation_indices (c, valueFormats, this); }
91
92 record = &StructAtOffset<const PairValueRecord> (record, record_size);
93 }
94 }
95
96 bool apply (hb_ot_apply_context_t *c,
97 const ValueFormat *valueFormats,
98 unsigned int pos) const
99 {
100 TRACE_APPLY (this);
101 hb_buffer_t *buffer = c->buffer;
102 unsigned int len1 = valueFormats[0].get_len ();
103 unsigned int len2 = valueFormats[1].get_len ();
104 unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
105
106 const PairValueRecord *record = hb_bsearch (buffer->info[pos].codepoint,
107 &firstPairValueRecord,
108 len,
109 record_size);
110 if (record)
111 {
112 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
113 {
114 c->buffer->message (c->font,
115 "try kerning glyphs at %d,%d",
116 c->buffer->idx, pos);
117 }
118
119 bool applied_first = valueFormats[0].apply_value (c, this, &record->values[0], buffer->cur_pos());
120 bool applied_second = valueFormats[1].apply_value (c, this, &record->values[len1], buffer->pos[pos]);
121
122 if (applied_first || applied_second)
123 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
124 {
125 c->buffer->message (c->font,
126 "kerned glyphs at %d,%d",
127 c->buffer->idx, pos);
128 }
129
130 if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
131 {
132 c->buffer->message (c->font,
133 "tried kerning glyphs at %d,%d",
134 c->buffer->idx, pos);
135 }
136
137 if (applied_first || applied_second)
138 buffer->unsafe_to_break (buffer->idx, pos + 1);
139
140 if (len2)
141 {
142 pos++;
143 // https://github.com/harfbuzz/harfbuzz/issues/3824
144 // https://github.com/harfbuzz/harfbuzz/issues/3888#issuecomment-1326781116
145 buffer->unsafe_to_break (buffer->idx, pos + 1);
146 }
147
148 buffer->idx = pos;
149 return_trace (true);
150 }
151 buffer->unsafe_to_concat (buffer->idx, pos + 1);
152 return_trace (false);
153 }
154
155 bool subset (hb_subset_context_t *c,
156 const ValueFormat valueFormats[2],
157 const ValueFormat newFormats[2]) const
158 {
159 TRACE_SUBSET (this);
160 auto snap = c->serializer->snapshot ();
161
162 auto *out = c->serializer->start_embed (*this);
163 if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
164 out->len = 0;
165
166 const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
167 const hb_map_t &glyph_map = *c->plan->glyph_map;
168
169 unsigned len1 = valueFormats[0].get_len ();
170 unsigned len2 = valueFormats[1].get_len ();
171 unsigned record_size = HBUINT16::static_size + Value::static_size * (len1 + len2);
172
173 typename PairValueRecord::context_t context =
174 {
175 this,
176 valueFormats,
177 newFormats,
178 len1,
179 &glyph_map,
180 c->plan->layout_variation_idx_delta_map
181 };
182
183 const PairValueRecord *record = &firstPairValueRecord;
184 unsigned count = len, num = 0;
185 for (unsigned i = 0; i < count; i++)
186 {
187 if (glyphset.has (record->secondGlyph)
188 && record->subset (c, &context)) num++;
189 record = &StructAtOffset<const PairValueRecord> (record, record_size);
190 }
191
192 out->len = num;
193 if (!num) c->serializer->revert (snap);
194 return_trace (num);
195 }
196 };
197
198
199 }
200 }
201 }
202
203 #endif // OT_LAYOUT_GPOS_PAIRSET_HH