Line data Source code
1 : /*
2 : * Copyright © 2007,2008,2009 Red Hat, Inc.
3 : * Copyright © 2012,2013 Google, Inc.
4 : *
5 : * This is part of HarfBuzz, a text shaping library.
6 : *
7 : * Permission is hereby granted, without written agreement and without
8 : * license or royalty fees, to use, copy, modify, and distribute this
9 : * software and its documentation for any purpose, provided that the
10 : * above copyright notice and the following two paragraphs appear in
11 : * all copies of this software.
12 : *
13 : * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14 : * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15 : * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16 : * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17 : * DAMAGE.
18 : *
19 : * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20 : * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 : * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
22 : * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23 : * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 : *
25 : * Red Hat Author(s): Behdad Esfahbod
26 : * Google Author(s): Behdad Esfahbod
27 : */
28 :
29 : #ifndef HB_OT_LAYOUT_PRIVATE_HH
30 : #define HB_OT_LAYOUT_PRIVATE_HH
31 :
32 : #include "hb-private.hh"
33 :
34 : #include "hb-font-private.hh"
35 : #include "hb-buffer-private.hh"
36 : #include "hb-set-private.hh"
37 : #include "hb-open-type-private.hh"
38 :
39 :
40 : /* Private API corresponding to hb-ot-layout.h: */
41 :
42 : HB_INTERNAL hb_bool_t
43 : hb_ot_layout_table_find_feature (hb_face_t *face,
44 : hb_tag_t table_tag,
45 : hb_tag_t feature_tag,
46 : unsigned int *feature_index);
47 :
48 :
49 : /*
50 : * GDEF
51 : */
52 :
53 : enum hb_ot_layout_glyph_props_flags_t
54 : {
55 : /* The following three match LookupFlags::Ignore* numbers. */
56 : HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH = 0x02u,
57 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE = 0x04u,
58 : HB_OT_LAYOUT_GLYPH_PROPS_MARK = 0x08u,
59 :
60 : /* The following are used internally; not derived from GDEF. */
61 : HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED = 0x10u,
62 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATED = 0x20u,
63 : HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED = 0x40u,
64 :
65 : HB_OT_LAYOUT_GLYPH_PROPS_PRESERVE = HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED |
66 : HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
67 : HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED
68 : };
69 0 : HB_MARK_AS_FLAG_T (hb_ot_layout_glyph_props_flags_t);
70 :
71 :
72 : /*
73 : * GSUB/GPOS
74 : */
75 :
76 : HB_INTERNAL hb_bool_t
77 : hb_ot_layout_lookup_would_substitute_fast (hb_face_t *face,
78 : unsigned int lookup_index,
79 : const hb_codepoint_t *glyphs,
80 : unsigned int glyphs_length,
81 : hb_bool_t zero_context);
82 :
83 :
84 : /* Should be called before all the substitute_lookup's are done. */
85 : HB_INTERNAL void
86 : hb_ot_layout_substitute_start (hb_font_t *font,
87 : hb_buffer_t *buffer);
88 :
89 :
90 : struct hb_ot_layout_lookup_accelerator_t;
91 :
92 : namespace OT {
93 : struct hb_apply_context_t;
94 : struct SubstLookup;
95 : }
96 :
97 : HB_INTERNAL void
98 : hb_ot_layout_substitute_lookup (OT::hb_apply_context_t *c,
99 : const OT::SubstLookup &lookup,
100 : const hb_ot_layout_lookup_accelerator_t &accel);
101 :
102 :
103 : /* Should be called before all the position_lookup's are done. */
104 : HB_INTERNAL void
105 : hb_ot_layout_position_start (hb_font_t *font,
106 : hb_buffer_t *buffer);
107 :
108 : /* Should be called after all the position_lookup's are done, to finish advances. */
109 : HB_INTERNAL void
110 : hb_ot_layout_position_finish_advances (hb_font_t *font,
111 : hb_buffer_t *buffer);
112 :
113 : /* Should be called after hb_ot_layout_position_finish_advances, to finish offsets. */
114 : HB_INTERNAL void
115 : hb_ot_layout_position_finish_offsets (hb_font_t *font,
116 : hb_buffer_t *buffer);
117 :
118 :
119 :
120 : /*
121 : * hb_ot_layout_t
122 : */
123 :
124 : namespace OT {
125 : struct GDEF;
126 : struct GSUB;
127 : struct GPOS;
128 : struct MATH;
129 : struct fvar;
130 : struct avar;
131 : }
132 :
133 : struct hb_ot_layout_lookup_accelerator_t
134 : {
135 : template <typename TLookup>
136 102 : inline void init (const TLookup &lookup)
137 : {
138 102 : digest.init ();
139 102 : lookup.add_coverage (&digest);
140 102 : }
141 :
142 51 : inline void fini (void)
143 : {
144 51 : }
145 :
146 3970 : inline bool may_have (hb_codepoint_t g) const {
147 3970 : return digest.may_have (g);
148 : }
149 :
150 : private:
151 : hb_set_digest_t digest;
152 : };
153 :
154 : struct hb_ot_layout_t
155 : {
156 : hb_blob_t *gdef_blob;
157 : hb_blob_t *gsub_blob;
158 : hb_blob_t *gpos_blob;
159 :
160 : const struct OT::GDEF *gdef;
161 : const struct OT::GSUB *gsub;
162 : const struct OT::GPOS *gpos;
163 :
164 : /* TODO Move the following out of this struct. */
165 : OT::hb_lazy_table_loader_t<struct OT::MATH> math;
166 : OT::hb_lazy_table_loader_t<struct OT::fvar> fvar;
167 : OT::hb_lazy_table_loader_t<struct OT::avar> avar;
168 :
169 : unsigned int gsub_lookup_count;
170 : unsigned int gpos_lookup_count;
171 :
172 : hb_ot_layout_lookup_accelerator_t *gsub_accels;
173 : hb_ot_layout_lookup_accelerator_t *gpos_accels;
174 : };
175 :
176 :
177 : HB_INTERNAL hb_ot_layout_t *
178 : _hb_ot_layout_create (hb_face_t *face);
179 :
180 : HB_INTERNAL void
181 : _hb_ot_layout_destroy (hb_ot_layout_t *layout);
182 :
183 :
184 : #define hb_ot_layout_from_face(face) ((hb_ot_layout_t *) face->shaper_data.ot)
185 :
186 :
187 : /*
188 : * Buffer var routines.
189 : */
190 :
191 : /* buffer var allocations, used during the entire shaping process */
192 : #define unicode_props() var2.u16[0]
193 :
194 : /* buffer var allocations, used during the GSUB/GPOS processing */
195 : #define glyph_props() var1.u16[0] /* GDEF glyph properties */
196 : #define lig_props() var1.u8[2] /* GSUB/GPOS ligature tracking */
197 : #define syllable() var1.u8[3] /* GSUB/GPOS shaping boundaries */
198 :
199 :
200 : /* loop over syllables */
201 :
202 : #define foreach_syllable(buffer, start, end) \
203 : for (unsigned int \
204 : _count = buffer->len, \
205 : start = 0, end = _count ? _next_syllable (buffer, 0) : 0; \
206 : start < _count; \
207 : start = end, end = _next_syllable (buffer, start))
208 :
209 : static inline unsigned int
210 0 : _next_syllable (hb_buffer_t *buffer, unsigned int start)
211 : {
212 0 : hb_glyph_info_t *info = buffer->info;
213 0 : unsigned int count = buffer->len;
214 :
215 0 : unsigned int syllable = info[start].syllable();
216 0 : while (++start < count && syllable == info[start].syllable())
217 : ;
218 :
219 0 : return start;
220 : }
221 :
222 :
223 : /* unicode_props */
224 :
225 : /* Design:
226 : * unicode_props() is a two-byte number. The low byte includes:
227 : * - General_Category: 5 bits.
228 : * - A bit each for:
229 : * * Is it Default_Ignorable(); we have a modified Default_Ignorable().
230 : * * Whether it's one of the three Mongolian Free Variation Selectors.
231 : * * One free bit right now.
232 : *
233 : * The high-byte has different meanings, switched by the Gen-Cat:
234 : * - For Mn,Mc,Me: the modified Combining_Class.
235 : * - For Cf: whether it's ZWJ, ZWNJ, or something else.
236 : * - For Ws: index of which space character this is, if space fallback
237 : * is needed, ie. we don't set this by default, only if asked to.
238 : */
239 :
240 : enum hb_unicode_props_flags_t {
241 : UPROPS_MASK_GEN_CAT = 0x001Fu,
242 : UPROPS_MASK_IGNORABLE = 0x0020u,
243 : UPROPS_MASK_FVS = 0x0040u, /* MONGOLIAN FREE VARIATION SELECTOR 1..3 */
244 :
245 : /* If GEN_CAT=FORMAT, top byte masks: */
246 : UPROPS_MASK_Cf_ZWJ = 0x0100u,
247 : UPROPS_MASK_Cf_ZWNJ = 0x0200u
248 : };
249 204 : HB_MARK_AS_FLAG_T (hb_unicode_props_flags_t);
250 :
251 : static inline void
252 265 : _hb_glyph_info_set_unicode_props (hb_glyph_info_t *info, hb_buffer_t *buffer)
253 : {
254 265 : hb_unicode_funcs_t *unicode = buffer->unicode;
255 265 : unsigned int u = info->codepoint;
256 265 : unsigned int gen_cat = (unsigned int) unicode->general_category (u);
257 265 : unsigned int props = gen_cat;
258 :
259 265 : if (u >= 0x80)
260 : {
261 2 : buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII;
262 2 : if (unlikely (unicode->is_default_ignorable (u)))
263 : {
264 0 : buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES;
265 0 : props |= UPROPS_MASK_IGNORABLE;
266 0 : if (u == 0x200Cu) props |= UPROPS_MASK_Cf_ZWNJ;
267 0 : if (u == 0x200Du) props |= UPROPS_MASK_Cf_ZWJ;
268 : /* Mongolian Free Variation Selectors need to be remembered
269 : * because although we need to hide them like default-ignorables,
270 : * they need to non-ignorable during shaping. This is similar to
271 : * what we do for joiners in Indic-like shapers, but since the
272 : * FVSes are GC=Mn, we have use a separate bit to remember them.
273 : * Fixes:
274 : * https://github.com/behdad/harfbuzz/issues/234
275 : */
276 0 : if (unlikely (hb_in_range (u, 0x180Bu, 0x180Du))) props |= UPROPS_MASK_FVS;
277 : }
278 2 : else if (unlikely (HB_UNICODE_GENERAL_CATEGORY_IS_NON_ENCLOSING_MARK_OR_MODIFIER_SYMBOL (gen_cat)))
279 : {
280 : /* The above check is just an optimization to let in only things we need further
281 : * processing on. */
282 :
283 : /* Only Mn and Mc can have non-zero ccc:
284 : * http://www.unicode.org/policies/stability_policy.html#Property_Value
285 : * """
286 : * Canonical_Combining_Class, General_Category
287 : * All characters other than those with General_Category property values
288 : * Spacing_Mark (Mc) and Nonspacing_Mark (Mn) have the Canonical_Combining_Class
289 : * property value 0.
290 : * 1.1.5+
291 : * """
292 : *
293 : * Also, all Mn's that are Default_Ignorable, have ccc=0, hence
294 : * the "else if".
295 : */
296 0 : props |= unicode->modified_combining_class (info->codepoint)<<8;
297 :
298 : /* Recategorize emoji skin-tone modifiers as Unicode mark, so they
299 : * behave correctly in non-native directionality. They originally
300 : * are MODIFIER_SYMBOL. Fixes:
301 : * https://github.com/behdad/harfbuzz/issues/169
302 : */
303 0 : if (unlikely (hb_in_range (u, 0x1F3FBu, 0x1F3FFu)))
304 : {
305 0 : props = gen_cat = HB_UNICODE_GENERAL_CATEGORY_ENCLOSING_MARK;
306 : }
307 : }
308 : }
309 :
310 265 : info->unicode_props() = props;
311 265 : }
312 :
313 : static inline void
314 0 : _hb_glyph_info_set_general_category (hb_glyph_info_t *info,
315 : hb_unicode_general_category_t gen_cat)
316 : {
317 : /* Clears top-byte. */
318 0 : info->unicode_props() = (unsigned int) gen_cat | (info->unicode_props() & (0xFF & ~UPROPS_MASK_GEN_CAT));
319 0 : }
320 :
321 : static inline hb_unicode_general_category_t
322 700 : _hb_glyph_info_get_general_category (const hb_glyph_info_t *info)
323 : {
324 700 : return (hb_unicode_general_category_t) (info->unicode_props() & UPROPS_MASK_GEN_CAT);
325 : }
326 :
327 : static inline bool
328 496 : _hb_glyph_info_is_unicode_mark (const hb_glyph_info_t *info)
329 : {
330 496 : return HB_UNICODE_GENERAL_CATEGORY_IS_MARK (info->unicode_props() & UPROPS_MASK_GEN_CAT);
331 : }
332 : static inline void
333 0 : _hb_glyph_info_set_modified_combining_class (hb_glyph_info_t *info,
334 : unsigned int modified_class)
335 : {
336 0 : if (unlikely (!_hb_glyph_info_is_unicode_mark (info)))
337 0 : return;
338 0 : info->unicode_props() = (modified_class<<8) | (info->unicode_props() & 0xFF);
339 : }
340 : static inline unsigned int
341 496 : _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
342 : {
343 496 : return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
344 : }
345 :
346 : static inline bool
347 0 : _hb_glyph_info_is_unicode_space (const hb_glyph_info_t *info)
348 : {
349 0 : return _hb_glyph_info_get_general_category (info) ==
350 0 : HB_UNICODE_GENERAL_CATEGORY_SPACE_SEPARATOR;
351 : }
352 : static inline void
353 0 : _hb_glyph_info_set_unicode_space_fallback_type (hb_glyph_info_t *info, hb_unicode_funcs_t::space_t s)
354 : {
355 0 : if (unlikely (!_hb_glyph_info_is_unicode_space (info)))
356 0 : return;
357 0 : info->unicode_props() = (((unsigned int) s)<<8) | (info->unicode_props() & 0xFF);
358 : }
359 : static inline hb_unicode_funcs_t::space_t
360 0 : _hb_glyph_info_get_unicode_space_fallback_type (const hb_glyph_info_t *info)
361 : {
362 0 : return _hb_glyph_info_is_unicode_space (info) ?
363 0 : (hb_unicode_funcs_t::space_t) (info->unicode_props()>>8) :
364 0 : hb_unicode_funcs_t::NOT_SPACE;
365 : }
366 :
367 : static inline bool _hb_glyph_info_ligated (const hb_glyph_info_t *info);
368 :
369 : static inline hb_bool_t
370 0 : _hb_glyph_info_is_default_ignorable (const hb_glyph_info_t *info)
371 : {
372 0 : return (info->unicode_props() & UPROPS_MASK_IGNORABLE) &&
373 0 : !_hb_glyph_info_ligated (info);
374 : }
375 : static inline hb_bool_t
376 204 : _hb_glyph_info_is_default_ignorable_and_not_fvs (const hb_glyph_info_t *info)
377 : {
378 204 : return ((info->unicode_props() & (UPROPS_MASK_IGNORABLE|UPROPS_MASK_FVS))
379 204 : == UPROPS_MASK_IGNORABLE) &&
380 204 : !_hb_glyph_info_ligated (info);
381 : }
382 :
383 : static inline bool
384 0 : _hb_glyph_info_is_unicode_format (const hb_glyph_info_t *info)
385 : {
386 0 : return _hb_glyph_info_get_general_category (info) ==
387 0 : HB_UNICODE_GENERAL_CATEGORY_FORMAT;
388 : }
389 : static inline hb_bool_t
390 0 : _hb_glyph_info_is_zwnj (const hb_glyph_info_t *info)
391 : {
392 0 : return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWNJ);
393 : }
394 : static inline hb_bool_t
395 0 : _hb_glyph_info_is_zwj (const hb_glyph_info_t *info)
396 : {
397 0 : return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & UPROPS_MASK_Cf_ZWJ);
398 : }
399 : static inline hb_bool_t
400 0 : _hb_glyph_info_is_joiner (const hb_glyph_info_t *info)
401 : {
402 0 : return _hb_glyph_info_is_unicode_format (info) && (info->unicode_props() & (UPROPS_MASK_Cf_ZWNJ|UPROPS_MASK_Cf_ZWJ));
403 : }
404 : static inline void
405 0 : _hb_glyph_info_flip_joiners (hb_glyph_info_t *info)
406 : {
407 0 : if (!_hb_glyph_info_is_unicode_format (info))
408 0 : return;
409 0 : info->unicode_props() ^= UPROPS_MASK_Cf_ZWNJ | UPROPS_MASK_Cf_ZWJ;
410 : }
411 :
412 : /* lig_props: aka lig_id / lig_comp
413 : *
414 : * When a ligature is formed:
415 : *
416 : * - The ligature glyph and any marks in between all the same newly allocated
417 : * lig_id,
418 : * - The ligature glyph will get lig_num_comps set to the number of components
419 : * - The marks get lig_comp > 0, reflecting which component of the ligature
420 : * they were applied to.
421 : * - This is used in GPOS to attach marks to the right component of a ligature
422 : * in MarkLigPos,
423 : * - Note that when marks are ligated together, much of the above is skipped
424 : * and the current lig_id reused.
425 : *
426 : * When a multiple-substitution is done:
427 : *
428 : * - All resulting glyphs will have lig_id = 0,
429 : * - The resulting glyphs will have lig_comp = 0, 1, 2, ... respectively.
430 : * - This is used in GPOS to attach marks to the first component of a
431 : * multiple substitution in MarkBasePos.
432 : *
433 : * The numbers are also used in GPOS to do mark-to-mark positioning only
434 : * to marks that belong to the same component of the same ligature.
435 : */
436 :
437 : static inline void
438 265 : _hb_glyph_info_clear_lig_props (hb_glyph_info_t *info)
439 : {
440 265 : info->lig_props() = 0;
441 265 : }
442 :
443 : #define IS_LIG_BASE 0x10
444 :
445 : static inline void
446 0 : _hb_glyph_info_set_lig_props_for_ligature (hb_glyph_info_t *info,
447 : unsigned int lig_id,
448 : unsigned int lig_num_comps)
449 : {
450 0 : info->lig_props() = (lig_id << 5) | IS_LIG_BASE | (lig_num_comps & 0x0F);
451 0 : }
452 :
453 : static inline void
454 0 : _hb_glyph_info_set_lig_props_for_mark (hb_glyph_info_t *info,
455 : unsigned int lig_id,
456 : unsigned int lig_comp)
457 : {
458 0 : info->lig_props() = (lig_id << 5) | (lig_comp & 0x0F);
459 0 : }
460 :
461 : static inline void
462 0 : _hb_glyph_info_set_lig_props_for_component (hb_glyph_info_t *info, unsigned int comp)
463 : {
464 0 : _hb_glyph_info_set_lig_props_for_mark (info, 0, comp);
465 0 : }
466 :
467 : static inline unsigned int
468 11 : _hb_glyph_info_get_lig_id (const hb_glyph_info_t *info)
469 : {
470 11 : return info->lig_props() >> 5;
471 : }
472 :
473 : static inline bool
474 11 : _hb_glyph_info_ligated_internal (const hb_glyph_info_t *info)
475 : {
476 11 : return !!(info->lig_props() & IS_LIG_BASE);
477 : }
478 :
479 : static inline unsigned int
480 11 : _hb_glyph_info_get_lig_comp (const hb_glyph_info_t *info)
481 : {
482 11 : if (_hb_glyph_info_ligated_internal (info))
483 0 : return 0;
484 : else
485 11 : return info->lig_props() & 0x0F;
486 : }
487 :
488 : static inline unsigned int
489 11 : _hb_glyph_info_get_lig_num_comps (const hb_glyph_info_t *info)
490 : {
491 11 : if ((info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE) &&
492 0 : _hb_glyph_info_ligated_internal (info))
493 0 : return info->lig_props() & 0x0F;
494 : else
495 11 : return 1;
496 : }
497 :
498 : static inline uint8_t
499 0 : _hb_allocate_lig_id (hb_buffer_t *buffer) {
500 0 : uint8_t lig_id = buffer->next_serial () & 0x07;
501 0 : if (unlikely (!lig_id))
502 0 : lig_id = _hb_allocate_lig_id (buffer); /* in case of overflow */
503 0 : return lig_id;
504 : }
505 :
506 : /* glyph_props: */
507 :
508 : static inline void
509 503 : _hb_glyph_info_set_glyph_props (hb_glyph_info_t *info, unsigned int props)
510 : {
511 503 : info->glyph_props() = props;
512 503 : }
513 :
514 : static inline unsigned int
515 1175 : _hb_glyph_info_get_glyph_props (const hb_glyph_info_t *info)
516 : {
517 1175 : return info->glyph_props();
518 : }
519 :
520 : static inline bool
521 : _hb_glyph_info_is_base_glyph (const hb_glyph_info_t *info)
522 : {
523 : return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH);
524 : }
525 :
526 : static inline bool
527 0 : _hb_glyph_info_is_ligature (const hb_glyph_info_t *info)
528 : {
529 0 : return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATURE);
530 : }
531 :
532 : static inline bool
533 276 : _hb_glyph_info_is_mark (const hb_glyph_info_t *info)
534 : {
535 276 : return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MARK);
536 : }
537 :
538 : static inline bool
539 0 : _hb_glyph_info_substituted (const hb_glyph_info_t *info)
540 : {
541 0 : return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
542 : }
543 :
544 : static inline bool
545 0 : _hb_glyph_info_ligated (const hb_glyph_info_t *info)
546 : {
547 0 : return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_LIGATED);
548 : }
549 :
550 : static inline bool
551 0 : _hb_glyph_info_multiplied (const hb_glyph_info_t *info)
552 : {
553 0 : return !!(info->glyph_props() & HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
554 : }
555 :
556 : static inline bool
557 0 : _hb_glyph_info_ligated_and_didnt_multiply (const hb_glyph_info_t *info)
558 : {
559 0 : return _hb_glyph_info_ligated (info) && !_hb_glyph_info_multiplied (info);
560 : }
561 :
562 : static inline void
563 0 : _hb_glyph_info_clear_ligated_and_multiplied (hb_glyph_info_t *info)
564 : {
565 0 : info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_LIGATED |
566 0 : HB_OT_LAYOUT_GLYPH_PROPS_MULTIPLIED);
567 0 : }
568 :
569 : static inline void
570 0 : _hb_glyph_info_clear_substituted (hb_glyph_info_t *info)
571 : {
572 0 : info->glyph_props() &= ~(HB_OT_LAYOUT_GLYPH_PROPS_SUBSTITUTED);
573 0 : }
574 :
575 :
576 : /* Allocation / deallocation. */
577 :
578 : static inline void
579 34 : _hb_buffer_allocate_unicode_vars (hb_buffer_t *buffer)
580 : {
581 34 : HB_BUFFER_ALLOCATE_VAR (buffer, unicode_props);
582 34 : }
583 :
584 : static inline void
585 34 : _hb_buffer_deallocate_unicode_vars (hb_buffer_t *buffer)
586 : {
587 34 : HB_BUFFER_DEALLOCATE_VAR (buffer, unicode_props);
588 34 : }
589 :
590 : static inline void
591 34 : _hb_buffer_assert_unicode_vars (hb_buffer_t *buffer)
592 : {
593 34 : HB_BUFFER_ASSERT_VAR (buffer, unicode_props);
594 34 : }
595 :
596 : static inline void
597 34 : _hb_buffer_allocate_gsubgpos_vars (hb_buffer_t *buffer)
598 : {
599 34 : HB_BUFFER_ALLOCATE_VAR (buffer, glyph_props);
600 34 : HB_BUFFER_ALLOCATE_VAR (buffer, lig_props);
601 34 : HB_BUFFER_ALLOCATE_VAR (buffer, syllable);
602 34 : }
603 :
604 : static inline void
605 34 : _hb_buffer_deallocate_gsubgpos_vars (hb_buffer_t *buffer)
606 : {
607 34 : HB_BUFFER_DEALLOCATE_VAR (buffer, syllable);
608 34 : HB_BUFFER_DEALLOCATE_VAR (buffer, lig_props);
609 34 : HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_props);
610 34 : }
611 :
612 : static inline void
613 68 : _hb_buffer_assert_gsubgpos_vars (hb_buffer_t *buffer)
614 : {
615 68 : HB_BUFFER_ASSERT_VAR (buffer, glyph_props);
616 68 : HB_BUFFER_ASSERT_VAR (buffer, lig_props);
617 68 : HB_BUFFER_ASSERT_VAR (buffer, syllable);
618 68 : }
619 :
620 : /* Make sure no one directly touches our props... */
621 : #undef unicode_props0
622 : #undef unicode_props1
623 : #undef lig_props
624 : #undef glyph_props
625 :
626 : #endif /* HB_OT_LAYOUT_PRIVATE_HH */
|