/work/workdir/UnpackedTarball/harfbuzz/src/hb-buffer.hh
Line | Count | Source |
1 | | /* |
2 | | * Copyright © 1998-2004 David Turner and Werner Lemberg |
3 | | * Copyright © 2004,2007,2009,2010 Red Hat, Inc. |
4 | | * Copyright © 2011,2012 Google, Inc. |
5 | | * |
6 | | * This is part of HarfBuzz, a text shaping library. |
7 | | * |
8 | | * Permission is hereby granted, without written agreement and without |
9 | | * license or royalty fees, to use, copy, modify, and distribute this |
10 | | * software and its documentation for any purpose, provided that the |
11 | | * above copyright notice and the following two paragraphs appear in |
12 | | * all copies of this software. |
13 | | * |
14 | | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
15 | | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
16 | | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
17 | | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
18 | | * DAMAGE. |
19 | | * |
20 | | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
21 | | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
22 | | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
23 | | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
24 | | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
25 | | * |
26 | | * Red Hat Author(s): Owen Taylor, Behdad Esfahbod |
27 | | * Google Author(s): Behdad Esfahbod |
28 | | */ |
29 | | |
30 | | #ifndef HB_BUFFER_HH |
31 | | #define HB_BUFFER_HH |
32 | | |
33 | | #include "hb.hh" |
34 | | #include "hb-unicode.hh" |
35 | | #include "hb-set-digest.hh" |
36 | | |
37 | | |
38 | | static_assert ((sizeof (hb_glyph_info_t) == 20), ""); |
39 | | static_assert ((sizeof (hb_glyph_info_t) == sizeof (hb_glyph_position_t)), ""); |
40 | | |
41 | | HB_MARK_AS_FLAG_T (hb_glyph_flags_t); |
42 | | HB_MARK_AS_FLAG_T (hb_buffer_flags_t); |
43 | | HB_MARK_AS_FLAG_T (hb_buffer_serialize_flags_t); |
44 | | HB_MARK_AS_FLAG_T (hb_buffer_diff_flags_t); |
45 | | |
46 | | enum hb_buffer_scratch_flags_t { |
47 | | HB_BUFFER_SCRATCH_FLAG_DEFAULT = 0x00000000u, |
48 | | HB_BUFFER_SCRATCH_FLAG_HAS_FRACTION_SLASH = 0x00000001u, |
49 | | HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES = 0x00000002u, |
50 | | HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK = 0x00000004u, |
51 | | HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT = 0x00000008u, |
52 | | HB_BUFFER_SCRATCH_FLAG_HAS_CGJ = 0x00000010u, |
53 | | HB_BUFFER_SCRATCH_FLAG_HAS_BROKEN_SYLLABLE = 0x00000020u, |
54 | | HB_BUFFER_SCRATCH_FLAG_HAS_VARIATION_SELECTOR_FALLBACK= 0x00000040u, |
55 | | HB_BUFFER_SCRATCH_FLAG_HAS_CONTINUATIONS = 0x00000080u, |
56 | | |
57 | | /* Reserved for shapers' internal use. */ |
58 | | HB_BUFFER_SCRATCH_FLAG_SHAPER0 = 0x01000000u, |
59 | | HB_BUFFER_SCRATCH_FLAG_SHAPER1 = 0x02000000u, |
60 | | HB_BUFFER_SCRATCH_FLAG_SHAPER2 = 0x04000000u, |
61 | | HB_BUFFER_SCRATCH_FLAG_SHAPER3 = 0x08000000u, |
62 | | }; |
63 | | HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t); |
64 | | |
65 | | |
66 | | /* |
67 | | * hb_buffer_t |
68 | | */ |
69 | | |
70 | | struct hb_buffer_t |
71 | | { |
72 | | hb_object_header_t header; |
73 | | |
74 | | /* |
75 | | * Information about how the text in the buffer should be treated. |
76 | | */ |
77 | | |
78 | | hb_unicode_funcs_t *unicode; /* Unicode functions */ |
79 | | hb_buffer_flags_t flags; /* BOT / EOT / etc. */ |
80 | | hb_buffer_cluster_level_t cluster_level; |
81 | | hb_codepoint_t replacement; /* U+FFFD or something else. */ |
82 | | hb_codepoint_t invisible; /* 0 or something else. */ |
83 | | hb_codepoint_t not_found; /* 0 or something else. */ |
84 | | hb_codepoint_t not_found_variation_selector; /* HB_CODEPOINT_INVALID or something else. */ |
85 | | |
86 | | /* |
87 | | * Buffer contents |
88 | | */ |
89 | | |
90 | | hb_buffer_content_type_t content_type; |
91 | | hb_segment_properties_t props; /* Script, language, direction */ |
92 | | |
93 | | bool successful; /* Allocations successful */ |
94 | | bool have_output; /* Whether we have an output buffer going on */ |
95 | | bool have_positions; /* Whether we have positions */ |
96 | | |
97 | | unsigned int idx; /* Cursor into ->info and ->pos arrays */ |
98 | | unsigned int len; /* Length of ->info and ->pos arrays */ |
99 | | unsigned int out_len; /* Length of ->out_info array if have_output */ |
100 | | |
101 | | unsigned int allocated; /* Length of allocated arrays */ |
102 | | hb_glyph_info_t *info; |
103 | | hb_glyph_info_t *out_info; |
104 | | hb_glyph_position_t *pos; |
105 | | |
106 | | /* Text before / after the main buffer contents. |
107 | | * Always in Unicode, and ordered outward. |
108 | | * Index 0 is for "pre-context", 1 for "post-context". */ |
109 | | static constexpr unsigned CONTEXT_LENGTH = 5u; |
110 | | hb_codepoint_t context[2][CONTEXT_LENGTH]; |
111 | | unsigned int context_len[2]; |
112 | | |
113 | | hb_set_digest_t digest; /* Manually updated sometimes */ |
114 | | |
115 | | /* |
116 | | * Managed by enter / leave |
117 | | */ |
118 | | |
119 | | uint8_t allocated_var_bits; |
120 | | uint8_t serial; |
121 | | uint32_t random_state; |
122 | | hb_buffer_scratch_flags_t scratch_flags; /* Have space-fallback, etc. */ |
123 | | unsigned int max_len; /* Maximum allowed len. */ |
124 | | int max_ops; /* Maximum allowed operations. */ |
125 | | /* The bits here reflect current allocations of the bytes in glyph_info_t's var1 and var2. */ |
126 | | |
127 | | |
128 | | /* |
129 | | * Messaging callback |
130 | | */ |
131 | | |
132 | | #ifndef HB_NO_BUFFER_MESSAGE |
133 | | typedef void (*changed_func_t) (hb_buffer_t *buffer, void *user_data); |
134 | | |
135 | | hb_buffer_message_func_t message_func; |
136 | | void *message_data; |
137 | | hb_destroy_func_t message_destroy; |
138 | | changed_func_t changed_func; |
139 | | void *changed_data; |
140 | | unsigned message_depth; /* How deeply are we inside a message callback? */ |
141 | | #else |
142 | | static constexpr unsigned message_depth = 0u; |
143 | | #endif |
144 | | |
145 | | |
146 | | |
147 | | /* Methods */ |
148 | | |
149 | 0 | HB_NODISCARD bool in_error () const { return !successful; } |
150 | | |
151 | | void allocate_var (unsigned int start, unsigned int count) |
152 | 126M | { |
153 | 126M | unsigned int end = start + count; |
154 | 126M | assert (end <= 8); |
155 | 126M | unsigned int bits = (1u<<end) - (1u<<start); |
156 | 126M | assert (0 == (allocated_var_bits & bits)); |
157 | 126M | allocated_var_bits |= bits; |
158 | 126M | } |
159 | | bool try_allocate_var (unsigned int start, unsigned int count) |
160 | 0 | { |
161 | 0 | unsigned int end = start + count; |
162 | 0 | assert (end <= 8); |
163 | 0 | unsigned int bits = (1u<<end) - (1u<<start); |
164 | 0 | if (allocated_var_bits & bits) |
165 | 0 | return false; |
166 | 0 | allocated_var_bits |= bits; |
167 | 0 | return true; |
168 | 0 | } |
169 | | void deallocate_var (unsigned int start, unsigned int count) |
170 | 126M | { |
171 | 126M | unsigned int end = start + count; |
172 | 126M | assert (end <= 8); |
173 | 126M | unsigned int bits = (1u<<end) - (1u<<start); |
174 | 126M | assert (bits == (allocated_var_bits & bits)); |
175 | 126M | allocated_var_bits &= ~bits; |
176 | 126M | } |
177 | | void assert_var (unsigned int start, unsigned int count) |
178 | 154M | { |
179 | 154M | unsigned int end = start + count; |
180 | 154M | assert (end <= 8); |
181 | 154M | HB_UNUSED unsigned int bits = (1u<<end) - (1u<<start); |
182 | 154M | assert (bits == (allocated_var_bits & bits)); |
183 | 154M | } |
184 | | void deallocate_var_all () |
185 | 107M | { |
186 | 107M | allocated_var_bits = 0; |
187 | 107M | } |
188 | | |
189 | | HB_ALWAYS_INLINE |
190 | 678M | hb_glyph_info_t &cur (unsigned int i = 0) { return info[idx + i]; } |
191 | | HB_ALWAYS_INLINE |
192 | 0 | hb_glyph_info_t cur (unsigned int i = 0) const { return info[idx + i]; } |
193 | | |
194 | | HB_ALWAYS_INLINE |
195 | 1.26M | hb_glyph_position_t &cur_pos (unsigned int i = 0) { return pos[idx + i]; } |
196 | | HB_ALWAYS_INLINE |
197 | 0 | hb_glyph_position_t cur_pos (unsigned int i = 0) const { return pos[idx + i]; } |
198 | | |
199 | | HB_ALWAYS_INLINE |
200 | 29.4M | hb_glyph_info_t &prev () { return out_info[out_len ? out_len - 1 : 0]; } |
201 | | HB_ALWAYS_INLINE |
202 | 0 | hb_glyph_info_t prev () const { return out_info[out_len ? out_len - 1 : 0]; } |
203 | | |
204 | | template <typename set_t> |
205 | | void collect_codepoints (set_t &d) const |
206 | 34.3M | { d.clear (); d.add_array (&info[0].codepoint, len, sizeof (info[0])); }void hb_buffer_t::collect_codepoints<hb_bit_set_t>(hb_bit_set_t&) const Line | Count | Source | 206 | 2.60M | { d.clear (); d.add_array (&info[0].codepoint, len, sizeof (info[0])); } |
void hb_buffer_t::collect_codepoints<hb_set_digest_t>(hb_set_digest_t&) const Line | Count | Source | 206 | 31.7M | { d.clear (); d.add_array (&info[0].codepoint, len, sizeof (info[0])); } |
|
207 | | |
208 | | void update_digest () |
209 | 31.7M | { |
210 | 31.7M | digest = hb_set_digest_t (); |
211 | 31.7M | collect_codepoints (digest); |
212 | 31.7M | } |
213 | | |
214 | | HB_INTERNAL void similar (const hb_buffer_t &src); |
215 | | HB_INTERNAL void reset (); |
216 | | HB_INTERNAL void clear (); |
217 | | |
218 | | /* Called around shape() */ |
219 | | HB_INTERNAL void enter (); |
220 | | HB_INTERNAL void leave (); |
221 | | |
222 | | #ifndef HB_NO_BUFFER_VERIFY |
223 | | HB_INTERNAL |
224 | | #endif |
225 | | bool verify (hb_buffer_t *text_buffer, |
226 | | hb_font_t *font, |
227 | | const hb_feature_t *features, |
228 | | unsigned int num_features, |
229 | | const char * const *shapers) |
230 | | #ifndef HB_NO_BUFFER_VERIFY |
231 | | ; |
232 | | #else |
233 | | { return true; } |
234 | | #endif |
235 | | |
236 | 887k | unsigned int backtrack_len () const { return have_output ? out_len : idx; } |
237 | 16.3k | unsigned int lookahead_len () const { return len - idx; } |
238 | 0 | uint8_t next_serial () { return ++serial ? serial : ++serial; } |
239 | | |
240 | | HB_INTERNAL void add (hb_codepoint_t codepoint, |
241 | | unsigned int cluster); |
242 | | HB_INTERNAL void add_info (const hb_glyph_info_t &glyph_info); |
243 | | HB_INTERNAL void add_info_and_pos (const hb_glyph_info_t &glyph_info, |
244 | | const hb_glyph_position_t &glyph_pos); |
245 | | |
246 | | void reverse_range (unsigned start, unsigned end) |
247 | 84.6M | { |
248 | 84.6M | hb_array_t<hb_glyph_info_t> (info, len).reverse (start, end); |
249 | 84.6M | if (have_positions) |
250 | 1.56M | hb_array_t<hb_glyph_position_t> (pos, len).reverse (start, end); |
251 | 84.6M | } |
252 | 3.85M | void reverse () { reverse_range (0, len); } |
253 | | |
254 | | template <typename FuncType> |
255 | | void reverse_groups (const FuncType& group, |
256 | | bool merge_clusters = false) |
257 | 2.29M | { |
258 | 2.29M | if (unlikely (!len)) |
259 | 0 | return; |
260 | | |
261 | 2.29M | unsigned start = 0; |
262 | 2.29M | unsigned i; |
263 | 81.1M | for (i = 1; i < len; i++) |
264 | 78.8M | { |
265 | 78.8M | if (!group (info[i - 1], info[i])) |
266 | 78.5M | { |
267 | 78.5M | if (merge_clusters) |
268 | 0 | this->merge_clusters (start, i); |
269 | 78.5M | reverse_range (start, i); |
270 | 78.5M | start = i; |
271 | 78.5M | } |
272 | 78.8M | } |
273 | 2.29M | if (merge_clusters) |
274 | 0 | this->merge_clusters (start, i); |
275 | 2.29M | reverse_range (start, i); |
276 | | |
277 | 2.29M | reverse (); |
278 | 2.29M | } |
279 | | |
280 | | template <typename FuncType> |
281 | | unsigned group_end (unsigned start, const FuncType& group) const |
282 | 452M | { |
283 | 458M | while (++start < len && group (info[start - 1], info[start])) |
284 | 5.27M | ; |
285 | | |
286 | 452M | return start; |
287 | 452M | } |
288 | | |
289 | | static bool _cluster_group_func (const hb_glyph_info_t& a, |
290 | | const hb_glyph_info_t& b) |
291 | 337M | { return a.cluster == b.cluster; } |
292 | | |
293 | 0 | void reverse_clusters () { reverse_groups (_cluster_group_func); } |
294 | | |
295 | | HB_INTERNAL void guess_segment_properties (); |
296 | | |
297 | | HB_INTERNAL bool sync (); |
298 | | HB_INTERNAL int sync_so_far (); |
299 | | HB_INTERNAL void clear_output (); |
300 | | HB_INTERNAL void clear_positions (); |
301 | | |
302 | | template <typename T> |
303 | | HB_NODISCARD bool replace_glyphs (unsigned int num_in, |
304 | | unsigned int num_out, |
305 | | const T *glyph_data) |
306 | 295k | { |
307 | 295k | if (unlikely (!make_room_for (num_in, num_out))) return false; |
308 | | |
309 | 295k | assert (idx + num_in <= len); |
310 | | |
311 | 295k | merge_clusters (idx, idx + num_in); |
312 | | |
313 | 295k | hb_glyph_info_t &orig_info = idx < len ? cur() : prev(); |
314 | | |
315 | 295k | hb_glyph_info_t *pinfo = &out_info[out_len]; |
316 | 593k | for (unsigned int i = 0; i < num_out; i++) |
317 | 297k | { |
318 | 297k | *pinfo = orig_info; |
319 | 297k | pinfo->codepoint = glyph_data[i]; |
320 | 297k | pinfo++; |
321 | 297k | } |
322 | | |
323 | 295k | idx += num_in; |
324 | 295k | out_len += num_out; |
325 | 295k | return true; |
326 | 295k | } |
327 | | |
328 | | HB_NODISCARD bool replace_glyph (hb_codepoint_t glyph_index) |
329 | 90.5k | { return replace_glyphs (1, 1, &glyph_index); } |
330 | | |
331 | | /* Makes a copy of the glyph at idx to output and replace glyph_index */ |
332 | | HB_NODISCARD bool output_glyph (hb_codepoint_t glyph_index) |
333 | 203k | { return replace_glyphs (0, 1, &glyph_index); } |
334 | | |
335 | | HB_NODISCARD bool output_info (const hb_glyph_info_t &glyph_info) |
336 | 209k | { |
337 | 209k | if (unlikely (!make_room_for (0, 1))) return false; |
338 | | |
339 | 209k | out_info[out_len] = glyph_info; |
340 | | |
341 | 209k | out_len++; |
342 | 209k | return true; |
343 | 209k | } |
344 | | /* Copies glyph at idx to output but doesn't advance idx */ |
345 | | HB_NODISCARD bool copy_glyph () |
346 | 0 | { |
347 | | /* Extra copy because cur()'s return can be freed within |
348 | | * output_info() call if buffer reallocates. */ |
349 | 0 | return output_info (hb_glyph_info_t (cur())); |
350 | 0 | } |
351 | | |
352 | | /* Copies glyph at idx to output and advance idx. |
353 | | * If there's no output, just advance idx. */ |
354 | | HB_NODISCARD bool next_glyph () |
355 | 301M | { |
356 | 301M | if (have_output) |
357 | 140M | { |
358 | 140M | if (out_info != info || out_len != idx) |
359 | 2.93M | { |
360 | 2.93M | if (unlikely (!ensure (out_len + 1))) return false; |
361 | 2.93M | out_info[out_len] = info[idx]; |
362 | 2.93M | } |
363 | 140M | out_len++; |
364 | 140M | } |
365 | | |
366 | 301M | idx++; |
367 | 301M | return true; |
368 | 301M | } |
369 | | /* Copies n glyphs at idx to output and advance idx. |
370 | | * If there's no output, just advance idx. */ |
371 | | HB_NODISCARD bool next_glyphs (unsigned int n) |
372 | 81.4M | { |
373 | 81.4M | if (have_output) |
374 | 66.3M | { |
375 | 66.3M | if (out_info != info || out_len != idx) |
376 | 430k | { |
377 | 430k | if (unlikely (!ensure (out_len + n))) return false; |
378 | 430k | memmove (out_info + out_len, info + idx, n * sizeof (out_info[0])); |
379 | 430k | } |
380 | 66.3M | out_len += n; |
381 | 66.3M | } |
382 | | |
383 | 81.4M | idx += n; |
384 | 81.4M | return true; |
385 | 81.4M | } |
386 | | /* Advance idx without copying to output. */ |
387 | 76.6k | void skip_glyph () { idx++; } |
388 | | void reset_masks (hb_mask_t mask) |
389 | 30.9M | { |
390 | 399M | for (unsigned int j = 0; j < len; j++) |
391 | 368M | info[j].mask = mask; |
392 | 30.9M | } |
393 | | void add_masks (hb_mask_t mask) |
394 | 0 | { |
395 | 0 | for (unsigned int j = 0; j < len; j++) |
396 | 0 | info[j].mask |= mask; |
397 | 0 | } |
398 | | HB_INTERNAL void set_masks (hb_mask_t value, hb_mask_t mask, |
399 | | unsigned int cluster_start, unsigned int cluster_end); |
400 | | |
401 | | void merge_clusters (unsigned int start, unsigned int end) |
402 | 345k | { |
403 | 345k | if (end - start < 2) |
404 | 296k | return; |
405 | 49.0k | if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level)) |
406 | 8 | { |
407 | 8 | unsafe_to_break (start, end); |
408 | 8 | return; |
409 | 8 | } |
410 | 49.0k | merge_clusters_impl (start, end); |
411 | 49.0k | } |
412 | | void merge_grapheme_clusters (unsigned int start, unsigned int end) |
413 | 53.9M | { |
414 | 53.9M | if (end - start < 2) |
415 | 52.6M | return; |
416 | 1.33M | if (!HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES (cluster_level)) |
417 | 1.10k | { |
418 | 1.10k | unsafe_to_break (start, end); |
419 | 1.10k | return; |
420 | 1.10k | } |
421 | 1.33M | merge_clusters_impl (start, end); |
422 | 1.33M | } |
423 | | HB_INTERNAL void merge_clusters_impl (unsigned int start, unsigned int end); |
424 | | void merge_out_clusters (unsigned int start, unsigned int end) |
425 | 72.5k | { |
426 | 72.5k | if (end - start < 2) |
427 | 0 | return; |
428 | 72.5k | if (!HB_BUFFER_CLUSTER_LEVEL_IS_MONOTONE (cluster_level)) |
429 | 57 | return; |
430 | 72.5k | merge_out_clusters_impl (start, end); |
431 | 72.5k | } |
432 | | void merge_out_grapheme_clusters (unsigned int start, unsigned int end) |
433 | 53.0k | { |
434 | 53.0k | if (end - start < 2) |
435 | 0 | return; |
436 | 53.0k | if (!HB_BUFFER_CLUSTER_LEVEL_IS_GRAPHEMES (cluster_level)) |
437 | 0 | return; |
438 | 53.0k | merge_out_clusters_impl (start, end); |
439 | 53.0k | } |
440 | | HB_INTERNAL void merge_out_clusters_impl (unsigned int start, unsigned int end); |
441 | | /* Merge clusters for deleting current glyph, and skip it. */ |
442 | | HB_INTERNAL void delete_glyph (); |
443 | | HB_INTERNAL void delete_glyphs_inplace (bool (*filter) (const hb_glyph_info_t *info)); |
444 | | |
445 | | |
446 | | |
447 | | /* Adds glyph flags in mask to infos with clusters between start and end. |
448 | | * The start index will be from out-buffer if from_out_buffer is true. |
449 | | * If interior is true, then the cluster having the minimum value is skipped. */ |
450 | | void _set_glyph_flags_impl (hb_mask_t mask, |
451 | | unsigned start, |
452 | | unsigned end, |
453 | | bool interior, |
454 | | bool from_out_buffer) |
455 | 1.57M | { |
456 | 1.57M | if (!from_out_buffer || !have_output) |
457 | 1.57M | { |
458 | 1.57M | if (!interior) |
459 | 0 | { |
460 | 0 | for (unsigned i = start; i < end; i++) |
461 | 0 | info[i].mask |= mask; |
462 | 0 | } |
463 | 1.57M | else |
464 | 1.57M | { |
465 | 1.57M | unsigned cluster = _infos_find_min_cluster (info, start, end); |
466 | 1.57M | _infos_set_glyph_flags (info, start, end, cluster, mask); |
467 | 1.57M | } |
468 | 1.57M | } |
469 | 776 | else |
470 | 776 | { |
471 | 776 | assert (start <= out_len); |
472 | 776 | assert (idx <= end); |
473 | | |
474 | 776 | if (!interior) |
475 | 0 | { |
476 | 0 | for (unsigned i = start; i < out_len; i++) |
477 | 0 | out_info[i].mask |= mask; |
478 | 0 | for (unsigned i = idx; i < end; i++) |
479 | 0 | info[i].mask |= mask; |
480 | 0 | } |
481 | 776 | else |
482 | 776 | { |
483 | 776 | unsigned cluster = _infos_find_min_cluster (info, idx, end); |
484 | 776 | cluster = _infos_find_min_cluster (out_info, start, out_len, cluster); |
485 | | |
486 | 776 | _infos_set_glyph_flags (out_info, start, out_len, cluster, mask); |
487 | 776 | _infos_set_glyph_flags (info, idx, end, cluster, mask); |
488 | 776 | } |
489 | 776 | } |
490 | 1.57M | } |
491 | | |
492 | | HB_ALWAYS_INLINE |
493 | | void _set_glyph_flags (hb_mask_t mask, |
494 | | unsigned start = 0, |
495 | | unsigned end = (unsigned) -1, |
496 | | bool interior = false, |
497 | | bool from_out_buffer = false) |
498 | 3.79M | { |
499 | 3.79M | if (unlikely (end != (unsigned) -1 && end - start > 255)) |
500 | 10.1k | return; |
501 | | |
502 | 3.78M | end = hb_min (end, len); |
503 | | |
504 | 3.78M | if (interior && !from_out_buffer && end - start < 2) |
505 | 2.21M | return; |
506 | | |
507 | 1.57M | _set_glyph_flags_impl (mask, start, end, interior, from_out_buffer); |
508 | 1.57M | } |
509 | | |
510 | | |
511 | | void unsafe_to_break (unsigned int start = 0, unsigned int end = -1) |
512 | 3.68M | { |
513 | 3.68M | _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, |
514 | 3.68M | start, end, |
515 | 3.68M | true); |
516 | 3.68M | } |
517 | | void safe_to_insert_tatweel (unsigned int start = 0, unsigned int end = -1) |
518 | 101k | { |
519 | 101k | if ((flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL) == 0) |
520 | 0 | { |
521 | 0 | unsafe_to_break (start, end); |
522 | 0 | return; |
523 | 0 | } |
524 | 101k | _set_glyph_flags (HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL, |
525 | 101k | start, end, |
526 | 101k | true); |
527 | 101k | } |
528 | | #ifndef HB_OPTIMIZE_SIZE |
529 | | HB_ALWAYS_INLINE |
530 | | #endif |
531 | | void unsafe_to_concat (unsigned int start = 0, unsigned int end = -1) |
532 | 42.3M | { |
533 | 42.3M | if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) |
534 | 42.3M | return; |
535 | 0 | _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, |
536 | 0 | start, end, |
537 | 0 | false); |
538 | 0 | } |
539 | | void unsafe_to_break_from_outbuffer (unsigned int start = 0, unsigned int end = -1) |
540 | 8.56k | { |
541 | 8.56k | _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, |
542 | 8.56k | start, end, |
543 | 8.56k | true, true); |
544 | 8.56k | } |
545 | | #ifndef HB_OPTIMIZE_SIZE |
546 | | HB_ALWAYS_INLINE |
547 | | #endif |
548 | | void unsafe_to_concat_from_outbuffer (unsigned int start = 0, unsigned int end = -1) |
549 | 1.53M | { |
550 | 1.53M | if (likely ((flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0)) |
551 | 1.53M | return; |
552 | 0 | _set_glyph_flags (HB_GLYPH_FLAG_UNSAFE_TO_CONCAT, |
553 | 0 | start, end, |
554 | 0 | false, true); |
555 | 0 | } |
556 | | |
557 | | |
558 | | /* Internal methods */ |
559 | | HB_NODISCARD HB_INTERNAL bool move_to (unsigned int i); /* i is output-buffer index. */ |
560 | | |
561 | | HB_NODISCARD HB_INTERNAL bool enlarge (unsigned int size); |
562 | | |
563 | | HB_NODISCARD bool resize (unsigned length) |
564 | 0 | { |
565 | 0 | assert (!have_output); |
566 | 0 | if (unlikely (!ensure (length))) return false; |
567 | 0 | len = length; |
568 | 0 | return true; |
569 | 0 | } |
570 | | HB_NODISCARD bool ensure (unsigned int size) |
571 | 418M | { return likely (!size || size < allocated) ? true : enlarge (size); } |
572 | | |
573 | | HB_NODISCARD bool ensure_inplace (unsigned int size) |
574 | 0 | { return likely (!size || size < allocated); } |
575 | | |
576 | | void assert_glyphs () |
577 | 0 | { |
578 | 0 | assert ((content_type == HB_BUFFER_CONTENT_TYPE_GLYPHS) || |
579 | 0 | (!len && (content_type == HB_BUFFER_CONTENT_TYPE_INVALID))); |
580 | 0 | } |
581 | | void assert_unicode () |
582 | 61.9M | { |
583 | 61.9M | assert ((content_type == HB_BUFFER_CONTENT_TYPE_UNICODE) || |
584 | 61.9M | (!len && (content_type == HB_BUFFER_CONTENT_TYPE_INVALID))); |
585 | 61.9M | } |
586 | | HB_NODISCARD bool ensure_glyphs () |
587 | 0 | { |
588 | 0 | if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_GLYPHS)) |
589 | 0 | { |
590 | 0 | if (content_type != HB_BUFFER_CONTENT_TYPE_INVALID) |
591 | 0 | return false; |
592 | 0 | assert (len == 0); |
593 | 0 | content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS; |
594 | 0 | } |
595 | 0 | return true; |
596 | 0 | } |
597 | | HB_NODISCARD bool ensure_unicode () |
598 | 0 | { |
599 | 0 | if (unlikely (content_type != HB_BUFFER_CONTENT_TYPE_UNICODE)) |
600 | 0 | { |
601 | 0 | if (content_type != HB_BUFFER_CONTENT_TYPE_INVALID) |
602 | 0 | return false; |
603 | 0 | assert (len == 0); |
604 | 0 | content_type = HB_BUFFER_CONTENT_TYPE_UNICODE; |
605 | 0 | } |
606 | 0 | return true; |
607 | 0 | } |
608 | | |
609 | | HB_NODISCARD HB_INTERNAL bool make_room_for (unsigned int num_in, unsigned int num_out); |
610 | | HB_NODISCARD HB_INTERNAL bool shift_forward (unsigned int count); |
611 | | |
612 | | typedef long scratch_buffer_t; |
613 | | HB_INTERNAL scratch_buffer_t *get_scratch_buffer (unsigned int *size); |
614 | | |
615 | 51.3M | void clear_context (unsigned int side) { context_len[side] = 0; } |
616 | | |
617 | | HB_INTERNAL void sort (unsigned int start, unsigned int end, int(*compar)(const hb_glyph_info_t *, const hb_glyph_info_t *)); |
618 | | |
619 | | bool messaging () |
620 | 771M | { |
621 | | #ifdef HB_NO_BUFFER_MESSAGE |
622 | | return false; |
623 | | #else |
624 | 771M | return unlikely (message_func); |
625 | 771M | #endif |
626 | 771M | } |
627 | | bool message (hb_font_t *font, const char *fmt, ...) HB_PRINTF_FUNC(3, 4) |
628 | 142M | { |
629 | | #ifdef HB_NO_BUFFER_MESSAGE |
630 | | return true; |
631 | | #else |
632 | 142M | if (likely (!messaging ())) |
633 | 142M | return true; |
634 | | |
635 | 0 | va_list ap; |
636 | 0 | va_start (ap, fmt); |
637 | 0 | bool ret = message_impl (font, fmt, ap); |
638 | 0 | va_end (ap); |
639 | |
|
640 | 0 | return ret; |
641 | 142M | #endif |
642 | 142M | } |
643 | | HB_INTERNAL bool message_impl (hb_font_t *font, const char *fmt, va_list ap) HB_PRINTF_FUNC(3, 0); |
644 | | HB_INTERNAL void changed (); |
645 | | |
646 | | static void |
647 | | set_cluster (hb_glyph_info_t &inf, unsigned int cluster, unsigned int mask = 0) |
648 | 5.47M | { |
649 | 5.47M | if (inf.cluster != cluster) |
650 | 2.52M | inf.mask = (inf.mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED); |
651 | 5.47M | inf.cluster = cluster; |
652 | 5.47M | } |
653 | | void |
654 | | _infos_set_glyph_flags (hb_glyph_info_t *infos, |
655 | | unsigned int start, unsigned int end, |
656 | | unsigned int cluster, |
657 | | hb_mask_t mask) |
658 | 1.57M | { |
659 | 1.57M | if (unlikely (start == end)) |
660 | 776 | return; |
661 | | |
662 | 1.57M | max_ops -= end - start; |
663 | 1.57M | if (unlikely (max_ops < 0)) |
664 | 0 | successful = false; |
665 | | |
666 | 1.57M | unsigned cluster_first = infos[start].cluster; |
667 | 1.57M | unsigned cluster_last = infos[end - 1].cluster; |
668 | | |
669 | 1.57M | if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS || |
670 | 1.56M | (cluster != cluster_first && cluster != cluster_last)) |
671 | 8.59k | { |
672 | 25.8k | for (unsigned int i = start; i < end; i++) |
673 | 17.2k | if (cluster != infos[i].cluster) |
674 | 8.65k | infos[i].mask |= mask; |
675 | 8.59k | return; |
676 | 8.59k | } |
677 | | |
678 | | /* Monotone clusters */ |
679 | | |
680 | 1.56M | if (cluster == cluster_first) |
681 | 1.38M | { |
682 | 2.53M | for (unsigned int i = end; start < i && infos[i - 1].cluster != cluster_first; i--) |
683 | 1.15M | infos[i - 1].mask |= mask; |
684 | 1.38M | } |
685 | 180k | else /* cluster == cluster_last */ |
686 | 180k | { |
687 | 360k | for (unsigned int i = start; i < end && infos[i].cluster != cluster_last; i++) |
688 | 180k | infos[i].mask |= mask; |
689 | 180k | } |
690 | 1.56M | } |
691 | | unsigned |
692 | | _infos_find_min_cluster (const hb_glyph_info_t *infos, |
693 | | unsigned start, unsigned end, |
694 | | unsigned cluster = UINT_MAX) |
695 | 1.57M | { |
696 | 1.57M | if (unlikely (start == end)) |
697 | 776 | return cluster; |
698 | | |
699 | 1.57M | if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS) |
700 | 8.59k | { |
701 | 25.8k | for (unsigned int i = start; i < end; i++) |
702 | 17.2k | cluster = hb_min (cluster, infos[i].cluster); |
703 | 8.59k | return cluster; |
704 | 8.59k | } |
705 | | |
706 | 1.56M | return hb_min (cluster, hb_min (infos[start].cluster, infos[end - 1].cluster)); |
707 | 1.57M | } |
708 | | |
709 | | void clear_glyph_flags (hb_mask_t mask = 0) |
710 | 0 | { |
711 | 0 | for (unsigned int i = 0; i < len; i++) |
712 | 0 | info[i].mask = (info[i].mask & ~HB_GLYPH_FLAG_DEFINED) | (mask & HB_GLYPH_FLAG_DEFINED); |
713 | 0 | } |
714 | | }; |
715 | | DECLARE_NULL_INSTANCE (hb_buffer_t); |
716 | | |
717 | | |
718 | | #define foreach_group(buffer, start, end, group_func) \ |
719 | 32.6M | for (unsigned int \ |
720 | 32.6M | _count = buffer->len, \ |
721 | 32.6M | start = 0, end = _count ? buffer->group_end (0, group_func) : 0; \ |
722 | 452M | start < _count; \ |
723 | 420M | start = end, end = buffer->group_end (start, group_func)) |
724 | | |
725 | | #define foreach_cluster(buffer, start, end) \ |
726 | 30.9M | foreach_group (buffer, start, end, hb_buffer_t::_cluster_group_func) |
727 | | |
728 | | |
729 | | #define HB_BUFFER_XALLOCATE_VAR(b, func, var) \ |
730 | 408M | b->func (offsetof (hb_glyph_info_t, var) - offsetof(hb_glyph_info_t, var1), \ |
731 | 408M | sizeof (b->info[0].var)) |
732 | 126M | #define HB_BUFFER_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, allocate_var, var ()) |
733 | 0 | #define HB_BUFFER_TRY_ALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, try_allocate_var, var ()) |
734 | 126M | #define HB_BUFFER_DEALLOCATE_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, deallocate_var, var ()) |
735 | 154M | #define HB_BUFFER_ASSERT_VAR(b, var) HB_BUFFER_XALLOCATE_VAR (b, assert_var, var ()) |
736 | | |
737 | | |
738 | | #endif /* HB_BUFFER_HH */ |