QtBase  v6.3.1
hb-ot-shape.cc
Go to the documentation of this file.
1 /*
2  * Copyright © 2009,2010 Red Hat, Inc.
3  * Copyright © 2010,2011,2012 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 #include "hb.hh"
30 
31 #ifndef HB_NO_OT_SHAPE
32 
33 #ifdef HB_NO_OT_LAYOUT
34 #error "Cannot compile 'ot' shaper with HB_NO_OT_LAYOUT."
35 #endif
36 
37 #include "hb-shaper-impl.hh"
38 
39 #include "hb-ot-shape.hh"
40 #include "hb-ot-shape-complex.hh"
41 #include "hb-ot-shape-fallback.hh"
42 #include "hb-ot-shape-normalize.hh"
43 
44 #include "hb-ot-face.hh"
45 
46 #include "hb-set.hh"
47 
48 #include "hb-aat-layout.hh"
49 
50 static inline bool
51 _hb_codepoint_is_regional_indicator (hb_codepoint_t u)
52 { return hb_in_range<hb_codepoint_t> (u, 0x1F1E6u, 0x1F1FFu); }
53 
54 #ifndef HB_NO_AAT_SHAPE
55 static inline bool
56 _hb_apply_morx (hb_face_t *face, const hb_segment_properties_t *props)
57 {
58  /* https://github.com/harfbuzz/harfbuzz/issues/2124 */
61 }
62 #endif
63 
74 static void
75 hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
76  const hb_feature_t *user_features,
77  unsigned int num_user_features);
78 
81  face (face),
82  props (*props),
83  map (face, props),
84  aat_map (face, props)
85 #ifndef HB_NO_AAT_SHAPE
86  , apply_morx (_hb_apply_morx (face, props))
87 #endif
88 {
89  shaper = hb_ot_shape_complex_categorize (this);
90 
93 
94  /* https://github.com/harfbuzz/harfbuzz/issues/1528 */
97 }
98 
99 void
102 {
103  plan.props = props;
104  plan.shaper = shaper;
105  map.compile (plan.map, key);
106 #ifndef HB_NO_AAT_SHAPE
107  if (apply_morx)
108  aat_map.compile (plan.aat_map);
109 #endif
110 
111 #ifndef HB_NO_OT_SHAPE_FRACTIONS
112  plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c'));
113  plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r'));
114  plan.dnom_mask = plan.map.get_1_mask (HB_TAG ('d','n','o','m'));
115  plan.has_frac = plan.frac_mask || (plan.numr_mask && plan.dnom_mask);
116 #endif
117 
118  plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m'));
119  plan.has_vert = !!plan.map.get_1_mask (HB_TAG ('v','e','r','t'));
120 
121  hb_tag_t kern_tag = HB_DIRECTION_IS_HORIZONTAL (props.direction) ?
122  HB_TAG ('k','e','r','n') : HB_TAG ('v','k','r','n');
123 #ifndef HB_NO_OT_KERN
124  plan.kern_mask = plan.map.get_mask (kern_tag);
125  plan.requested_kerning = !!plan.kern_mask;
126 #endif
127 #ifndef HB_NO_AAT_SHAPE
128  plan.trak_mask = plan.map.get_mask (HB_TAG ('t','r','a','k'));
129  plan.requested_tracking = !!plan.trak_mask;
130 #endif
131 
132  bool has_gpos_kern = plan.map.get_feature_index (1, kern_tag) != HB_OT_LAYOUT_NO_FEATURE_INDEX;
133  bool disable_gpos = plan.shaper->gpos_tag &&
134  plan.shaper->gpos_tag != plan.map.chosen_script[1];
135 
136  /*
137  * Decide who provides glyph classes. GDEF or Unicode.
138  */
139 
141  plan.fallback_glyph_classes = true;
142 
143  /*
144  * Decide who does substitutions. GSUB, morx, or fallback.
145  */
146 
147 #ifndef HB_NO_AAT_SHAPE
148  plan.apply_morx = apply_morx;
149 #endif
150 
151  /*
152  * Decide who does positioning. GPOS, kerx, kern, or fallback.
153  */
154 
155 #ifndef HB_NO_AAT_SHAPE
156  bool has_kerx = hb_aat_layout_has_positioning (face);
157  bool has_gsub = !apply_morx && hb_ot_layout_has_substitution (face);
158 #endif
159  bool has_gpos = !disable_gpos && hb_ot_layout_has_positioning (face);
160  if (false)
161  ;
162 #ifndef HB_NO_AAT_SHAPE
163  /* Prefer GPOS over kerx if GSUB is present;
164  * https://github.com/harfbuzz/harfbuzz/issues/3008 */
165  else if (has_kerx && !(has_gsub && has_gpos))
166  plan.apply_kerx = true;
167 #endif
168  else if (has_gpos)
169  plan.apply_gpos = true;
170 
171  if (!plan.apply_kerx && (!has_gpos_kern || !plan.apply_gpos))
172  {
173 #ifndef HB_NO_AAT_SHAPE
174  if (has_kerx)
175  plan.apply_kerx = true;
176  else
177 #endif
178 #ifndef HB_NO_OT_KERN
180  plan.apply_kern = true;
181 #endif
182  }
183 
184  plan.apply_fallback_kern = !(plan.apply_gpos || plan.apply_kerx || plan.apply_kern);
185 
186  plan.zero_marks = script_zero_marks &&
187  !plan.apply_kerx &&
188  (!plan.apply_kern
189 #ifndef HB_NO_OT_KERN
191 #endif
192  );
193  plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k'));
194 
196  !plan.apply_kerx &&
197  (!plan.apply_kern
198 #ifndef HB_NO_OT_KERN
200 #endif
201  );
202 
205 
206 #ifndef HB_NO_AAT_SHAPE
207  /* If we're using morx shaping, we cancel mark position adjustment because
208  Apple Color Emoji assumes this will NOT be done when forming emoji sequences;
209  https://github.com/harfbuzz/harfbuzz/issues/2967. */
210  if (plan.apply_morx)
212 
213  /* Currently we always apply trak. */
215 #endif
216 }
217 
218 bool
220  const hb_shape_plan_key_t *key)
221 {
222  map.init ();
223 #ifndef HB_NO_AAT_SHAPE
224  aat_map.init ();
225 #endif
226 
227  hb_ot_shape_planner_t planner (face,
228  &key->props);
229 
230  hb_ot_shape_collect_features (&planner,
231  key->user_features,
232  key->num_user_features);
233 
234  planner.compile (*this, key->ot);
235 
236  if (shaper->data_create)
237  {
238  data = shaper->data_create (this);
239  if (unlikely (!data))
240  {
241  map.fini ();
242 #ifndef HB_NO_AAT_SHAPE
243  aat_map.fini ();
244 #endif
245  return false;
246  }
247  }
248 
249  return true;
250 }
251 
252 void
254 {
255  if (shaper->data_destroy)
256  shaper->data_destroy (const_cast<void *> (data));
257 
258  map.fini ();
259 #ifndef HB_NO_AAT_SHAPE
260  aat_map.fini ();
261 #endif
262 }
263 
264 void
266  hb_buffer_t *buffer) const
267 {
268 #ifndef HB_NO_AAT_SHAPE
269  if (unlikely (apply_morx))
271  else
272 #endif
273  map.substitute (this, font, buffer);
274 }
275 
276 void
278  hb_buffer_t *buffer) const
279 {
280  if (this->apply_gpos)
281  map.position (this, font, buffer);
282 #ifndef HB_NO_AAT_SHAPE
283  else if (this->apply_kerx)
284  hb_aat_layout_position (this, font, buffer);
285 #endif
286 
287 #ifndef HB_NO_OT_KERN
288  if (this->apply_kern)
289  hb_ot_layout_kern (this, font, buffer);
290 #endif
291  else if (this->apply_fallback_kern)
292  _hb_ot_shape_fallback_kern (this, font, buffer);
293 
294 #ifndef HB_NO_AAT_SHAPE
295  if (this->apply_trak)
296  hb_aat_layout_track (this, font, buffer);
297 #endif
298 }
299 
300 
301 static const hb_ot_map_feature_t
302 common_features[] =
303 {
304  {HB_TAG('a','b','v','m'), F_GLOBAL},
305  {HB_TAG('b','l','w','m'), F_GLOBAL},
306  {HB_TAG('c','c','m','p'), F_GLOBAL},
307  {HB_TAG('l','o','c','l'), F_GLOBAL},
308  {HB_TAG('m','a','r','k'), F_GLOBAL_MANUAL_JOINERS},
309  {HB_TAG('m','k','m','k'), F_GLOBAL_MANUAL_JOINERS},
310  {HB_TAG('r','l','i','g'), F_GLOBAL},
311 };
312 
313 
314 static const hb_ot_map_feature_t
315 horizontal_features[] =
316 {
317  {HB_TAG('c','a','l','t'), F_GLOBAL},
318  {HB_TAG('c','l','i','g'), F_GLOBAL},
319  {HB_TAG('c','u','r','s'), F_GLOBAL},
320  {HB_TAG('d','i','s','t'), F_GLOBAL},
321  {HB_TAG('k','e','r','n'), F_GLOBAL_HAS_FALLBACK},
322  {HB_TAG('l','i','g','a'), F_GLOBAL},
323  {HB_TAG('r','c','l','t'), F_GLOBAL},
324 };
325 
326 static void
327 hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner,
328  const hb_feature_t *user_features,
329  unsigned int num_user_features)
330 {
331  hb_ot_map_builder_t *map = &planner->map;
332 
333  map->enable_feature (HB_TAG('r','v','r','n'));
334  map->add_gsub_pause (nullptr);
335 
336  switch (planner->props.direction)
337  {
338  case HB_DIRECTION_LTR:
339  map->enable_feature (HB_TAG ('l','t','r','a'));
340  map->enable_feature (HB_TAG ('l','t','r','m'));
341  break;
342  case HB_DIRECTION_RTL:
343  map->enable_feature (HB_TAG ('r','t','l','a'));
344  map->add_feature (HB_TAG ('r','t','l','m'));
345  break;
346  case HB_DIRECTION_TTB:
347  case HB_DIRECTION_BTT:
349  default:
350  break;
351  }
352 
353 #ifndef HB_NO_OT_SHAPE_FRACTIONS
354  /* Automatic fractions. */
355  map->add_feature (HB_TAG ('f','r','a','c'));
356  map->add_feature (HB_TAG ('n','u','m','r'));
357  map->add_feature (HB_TAG ('d','n','o','m'));
358 #endif
359 
360  /* Random! */
361  map->enable_feature (HB_TAG ('r','a','n','d'), F_RANDOM, HB_OT_MAP_MAX_VALUE);
362 
363 #ifndef HB_NO_AAT_SHAPE
364  /* Tracking. We enable dummy feature here just to allow disabling
365  * AAT 'trak' table using features.
366  * https://github.com/harfbuzz/harfbuzz/issues/1303 */
367  map->enable_feature (HB_TAG ('t','r','a','k'), F_HAS_FALLBACK);
368 #endif
369 
370  map->enable_feature (HB_TAG ('H','a','r','f')); /* Considered required. */
371  map->enable_feature (HB_TAG ('H','A','R','F')); /* Considered discretionary. */
372 
373  if (planner->shaper->collect_features)
374  planner->shaper->collect_features (planner);
375 
376  map->enable_feature (HB_TAG ('B','u','z','z')); /* Considered required. */
377  map->enable_feature (HB_TAG ('B','U','Z','Z')); /* Considered discretionary. */
378 
379  for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
380  map->add_feature (common_features[i]);
381 
383  for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
384  map->add_feature (horizontal_features[i]);
385  else
386  {
387  /* We only apply `vert` feature. See:
388  * https://github.com/harfbuzz/harfbuzz/commit/d71c0df2d17f4590d5611239577a6cb532c26528
389  * https://lists.freedesktop.org/archives/harfbuzz/2013-August/003490.html */
390 
391  /* We really want to find a 'vert' feature if there's any in the font, no
392  * matter which script/langsys it is listed (or not) under.
393  * See various bugs referenced from:
394  * https://github.com/harfbuzz/harfbuzz/issues/63 */
395  map->enable_feature (HB_TAG ('v','e','r','t'), F_GLOBAL_SEARCH);
396  }
397 
398  for (unsigned int i = 0; i < num_user_features; i++)
399  {
400  const hb_feature_t *feature = &user_features[i];
401  map->add_feature (feature->tag,
402  (feature->start == HB_FEATURE_GLOBAL_START &&
403  feature->end == HB_FEATURE_GLOBAL_END) ? F_GLOBAL : F_NONE,
404  feature->value);
405  }
406 
407 #ifndef HB_NO_AAT_SHAPE
408  if (planner->apply_morx)
409  {
410  hb_aat_map_builder_t *aat_map = &planner->aat_map;
411  for (unsigned int i = 0; i < num_user_features; i++)
412  {
413  const hb_feature_t *feature = &user_features[i];
414  aat_map->add_feature (feature->tag, feature->value);
415  }
416  }
417 #endif
418 
419  if (planner->shaper->override_features)
420  planner->shaper->override_features (planner);
421 }
422 
423 
424 /*
425  * shaper face data
426  */
427 
429 
432 {
434 }
435 
436 void
438 {
439 }
440 
441 
442 /*
443  * shaper font data
444  */
445 
447 
450 {
452 }
453 
454 void
456 {
457 }
458 
459 
460 /*
461  * shaper
462  */
463 
465 {
471  unsigned int num_user_features;
472 
473  /* Transient stuff */
475 };
476 
477 
478 
479 /* Main shaper */
480 
481 
482 /* Prepare */
483 
484 static void
485 hb_set_unicode_props (hb_buffer_t *buffer)
486 {
487  /* Implement enough of Unicode Graphemes here that shaping
488  * in reverse-direction wouldn't break graphemes. Namely,
489  * we mark all marks and ZWJ and ZWJ,Extended_Pictographic
490  * sequences as continuations. The foreach_grapheme()
491  * macro uses this bit.
492  *
493  * https://www.unicode.org/reports/tr29/#Regex_Definitions
494  */
495  unsigned int count = buffer->len;
496  hb_glyph_info_t *info = buffer->info;
497  for (unsigned int i = 0; i < count; i++)
498  {
499  _hb_glyph_info_set_unicode_props (&info[i], buffer);
500 
501  /* Marks are already set as continuation by the above line.
502  * Handle Emoji_Modifier and ZWJ-continuation. */
503  if (unlikely (_hb_glyph_info_get_general_category (&info[i]) == HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL &&
504  hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F3FBu, 0x1F3FFu)))
505  {
506  _hb_glyph_info_set_continuation (&info[i]);
507  }
508  /* Regional_Indicators are hairy as hell...
509  * https://github.com/harfbuzz/harfbuzz/issues/2265 */
510  else if (unlikely (i && _hb_codepoint_is_regional_indicator (info[i].codepoint)))
511  {
512  if (_hb_codepoint_is_regional_indicator (info[i - 1].codepoint) &&
513  !_hb_glyph_info_is_continuation (&info[i - 1]))
514  _hb_glyph_info_set_continuation (&info[i]);
515  }
516 #ifndef HB_NO_EMOJI_SEQUENCES
517  else if (unlikely (_hb_glyph_info_is_zwj (&info[i])))
518  {
519  _hb_glyph_info_set_continuation (&info[i]);
520  if (i + 1 < count &&
522  {
523  i++;
524  _hb_glyph_info_set_unicode_props (&info[i], buffer);
525  _hb_glyph_info_set_continuation (&info[i]);
526  }
527  }
528 #endif
529  /* Or part of the Other_Grapheme_Extend that is not marks.
530  * As of Unicode 11 that is just:
531  *
532  * 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER
533  * FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
534  * E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
535  *
536  * ZWNJ is special, we don't want to merge it as there's no need, and keeping
537  * it separate results in more granular clusters. Ignore Katakana for now.
538  * Tags are used for Emoji sub-region flag sequences:
539  * https://github.com/harfbuzz/harfbuzz/issues/1556
540  */
541  else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu)))
542  _hb_glyph_info_set_continuation (&info[i]);
543  }
544 }
545 
546 static void
547 hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
548 {
550  return;
551 
552  if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
553  buffer->context_len[0] ||
554  !_hb_glyph_info_is_unicode_mark (&buffer->info[0]))
555  return;
556 
557  if (!font->has_glyph (0x25CCu))
558  return;
559 
560  hb_glyph_info_t dottedcircle = {0};
561  dottedcircle.codepoint = 0x25CCu;
562  _hb_glyph_info_set_unicode_props (&dottedcircle, buffer);
563 
564  buffer->clear_output ();
565 
566  buffer->idx = 0;
567  hb_glyph_info_t info = dottedcircle;
568  info.cluster = buffer->cur().cluster;
569  info.mask = buffer->cur().mask;
570  (void) buffer->output_info (info);
571 
572  buffer->sync ();
573 }
574 
575 static void
576 hb_form_clusters (hb_buffer_t *buffer)
577 {
578  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
579  return;
580 
583  buffer->merge_clusters (start, end);
584  else
586  buffer->unsafe_to_break (start, end);
587 }
588 
589 static void
590 hb_ensure_native_direction (hb_buffer_t *buffer)
591 {
592  hb_direction_t direction = buffer->props.direction;
593  hb_direction_t horiz_dir = hb_script_get_horizontal_direction (buffer->props.script);
594 
595  /* Numeric runs in natively-RTL scripts are actually native-LTR, so we reset
596  * the horiz_dir if the run contains at least one decimal-number char, and no
597  * letter chars (ideally we should be checking for chars with strong
598  * directionality but hb-unicode currently lacks bidi categories).
599  *
600  * This allows digit sequences in Arabic etc to be shaped in "native"
601  * direction, so that features like ligatures will work as intended.
602  *
603  * https://github.com/harfbuzz/harfbuzz/issues/501
604  *
605  * Similar thing about Regional_Indicators; They are bidi=L, but Script=Common.
606  * If they are present in a run of natively-RTL text, they get assigned a script
607  * with natively RTL direction, which would result in wrong shaping if we
608  * assign such native RTL direction to them then. Detect that as well.
609  *
610  * https://github.com/harfbuzz/harfbuzz/issues/3314
611  */
612  if (unlikely (horiz_dir == HB_DIRECTION_RTL && direction == HB_DIRECTION_LTR))
613  {
614  bool found_number = false, found_letter = false, found_ri = false;
615  const auto* info = buffer->info;
616  const auto count = buffer->len;
617  for (unsigned i = 0; i < count; i++)
618  {
619  auto gc = _hb_glyph_info_get_general_category (&info[i]);
621  found_number = true;
623  {
624  found_letter = true;
625  break;
626  }
627  else if (_hb_codepoint_is_regional_indicator (info[i].codepoint))
628  found_ri = true;
629  }
630  if ((found_number || found_ri) && !found_letter)
631  horiz_dir = HB_DIRECTION_LTR;
632  }
633 
634  /* TODO vertical:
635  * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
636  * Ogham fonts are supposed to be implemented BTT or not. Need to research that
637  * first. */
639  direction != horiz_dir && horiz_dir != HB_DIRECTION_INVALID) ||
642  {
643  _hb_ot_layout_reverse_graphemes (buffer);
644  buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
645  }
646 }
647 
648 
649 /*
650  * Substitute
651  */
652 
653 #ifndef HB_NO_VERTICAL
654 static hb_codepoint_t
655 hb_vert_char_for (hb_codepoint_t u)
656 {
657  switch (u >> 8)
658  {
659  case 0x20: switch (u) {
660  case 0x2013u: return 0xfe32u; // EN DASH
661  case 0x2014u: return 0xfe31u; // EM DASH
662  case 0x2025u: return 0xfe30u; // TWO DOT LEADER
663  case 0x2026u: return 0xfe19u; // HORIZONTAL ELLIPSIS
664  } break;
665  case 0x30: switch (u) {
666  case 0x3001u: return 0xfe11u; // IDEOGRAPHIC COMMA
667  case 0x3002u: return 0xfe12u; // IDEOGRAPHIC FULL STOP
668  case 0x3008u: return 0xfe3fu; // LEFT ANGLE BRACKET
669  case 0x3009u: return 0xfe40u; // RIGHT ANGLE BRACKET
670  case 0x300au: return 0xfe3du; // LEFT DOUBLE ANGLE BRACKET
671  case 0x300bu: return 0xfe3eu; // RIGHT DOUBLE ANGLE BRACKET
672  case 0x300cu: return 0xfe41u; // LEFT CORNER BRACKET
673  case 0x300du: return 0xfe42u; // RIGHT CORNER BRACKET
674  case 0x300eu: return 0xfe43u; // LEFT WHITE CORNER BRACKET
675  case 0x300fu: return 0xfe44u; // RIGHT WHITE CORNER BRACKET
676  case 0x3010u: return 0xfe3bu; // LEFT BLACK LENTICULAR BRACKET
677  case 0x3011u: return 0xfe3cu; // RIGHT BLACK LENTICULAR BRACKET
678  case 0x3014u: return 0xfe39u; // LEFT TORTOISE SHELL BRACKET
679  case 0x3015u: return 0xfe3au; // RIGHT TORTOISE SHELL BRACKET
680  case 0x3016u: return 0xfe17u; // LEFT WHITE LENTICULAR BRACKET
681  case 0x3017u: return 0xfe18u; // RIGHT WHITE LENTICULAR BRACKET
682  } break;
683  case 0xfe: switch (u) {
684  case 0xfe4fu: return 0xfe34u; // WAVY LOW LINE
685  } break;
686  case 0xff: switch (u) {
687  case 0xff01u: return 0xfe15u; // FULLWIDTH EXCLAMATION MARK
688  case 0xff08u: return 0xfe35u; // FULLWIDTH LEFT PARENTHESIS
689  case 0xff09u: return 0xfe36u; // FULLWIDTH RIGHT PARENTHESIS
690  case 0xff0cu: return 0xfe10u; // FULLWIDTH COMMA
691  case 0xff1au: return 0xfe13u; // FULLWIDTH COLON
692  case 0xff1bu: return 0xfe14u; // FULLWIDTH SEMICOLON
693  case 0xff1fu: return 0xfe16u; // FULLWIDTH QUESTION MARK
694  case 0xff3bu: return 0xfe47u; // FULLWIDTH LEFT SQUARE BRACKET
695  case 0xff3du: return 0xfe48u; // FULLWIDTH RIGHT SQUARE BRACKET
696  case 0xff3fu: return 0xfe33u; // FULLWIDTH LOW LINE
697  case 0xff5bu: return 0xfe37u; // FULLWIDTH LEFT CURLY BRACKET
698  case 0xff5du: return 0xfe38u; // FULLWIDTH RIGHT CURLY BRACKET
699  } break;
700  }
701 
702  return u;
703 }
704 #endif
705 
706 static inline void
707 hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
708 {
709  hb_buffer_t *buffer = c->buffer;
710  unsigned int count = buffer->len;
711  hb_glyph_info_t *info = buffer->info;
712 
713  if (HB_DIRECTION_IS_BACKWARD (c->target_direction))
714  {
715  hb_unicode_funcs_t *unicode = buffer->unicode;
716  hb_mask_t rtlm_mask = c->plan->rtlm_mask;
717 
718  for (unsigned int i = 0; i < count; i++) {
719  hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
720  if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
721  info[i].codepoint = codepoint;
722  else
723  info[i].mask |= rtlm_mask;
724  }
725  }
726 
727 #ifndef HB_NO_VERTICAL
728  if (HB_DIRECTION_IS_VERTICAL (c->target_direction) && !c->plan->has_vert)
729  {
730  for (unsigned int i = 0; i < count; i++) {
731  hb_codepoint_t codepoint = hb_vert_char_for (info[i].codepoint);
732  if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
733  info[i].codepoint = codepoint;
734  }
735  }
736 #endif
737 }
738 
739 static inline void
740 hb_ot_shape_setup_masks_fraction (const hb_ot_shape_context_t *c)
741 {
742 #ifdef HB_NO_OT_SHAPE_FRACTIONS
743  return;
744 #endif
745 
746  if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
747  !c->plan->has_frac)
748  return;
749 
750  hb_buffer_t *buffer = c->buffer;
751 
752  hb_mask_t pre_mask, post_mask;
753  if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
754  {
755  pre_mask = c->plan->numr_mask | c->plan->frac_mask;
756  post_mask = c->plan->frac_mask | c->plan->dnom_mask;
757  }
758  else
759  {
760  pre_mask = c->plan->frac_mask | c->plan->dnom_mask;
761  post_mask = c->plan->numr_mask | c->plan->frac_mask;
762  }
763 
764  unsigned int count = buffer->len;
765  hb_glyph_info_t *info = buffer->info;
766  for (unsigned int i = 0; i < count; i++)
767  {
768  if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
769  {
770  unsigned int start = i, end = i + 1;
771  while (start &&
772  _hb_glyph_info_get_general_category (&info[start - 1]) ==
774  start--;
775  while (end < count &&
776  _hb_glyph_info_get_general_category (&info[end]) ==
778  end++;
779 
780  buffer->unsafe_to_break (start, end);
781 
782  for (unsigned int j = start; j < i; j++)
783  info[j].mask |= pre_mask;
784  info[i].mask |= c->plan->frac_mask;
785  for (unsigned int j = i + 1; j < end; j++)
786  info[j].mask |= post_mask;
787 
788  i = end - 1;
789  }
790  }
791 }
792 
793 static inline void
794 hb_ot_shape_initialize_masks (const hb_ot_shape_context_t *c)
795 {
796  hb_ot_map_t *map = &c->plan->map;
797  hb_buffer_t *buffer = c->buffer;
798 
799  hb_mask_t global_mask = map->get_global_mask ();
800  buffer->reset_masks (global_mask);
801 }
802 
803 static inline void
804 hb_ot_shape_setup_masks (const hb_ot_shape_context_t *c)
805 {
806  hb_ot_map_t *map = &c->plan->map;
807  hb_buffer_t *buffer = c->buffer;
808 
809  hb_ot_shape_setup_masks_fraction (c);
810 
811  if (c->plan->shaper->setup_masks)
812  c->plan->shaper->setup_masks (c->plan, buffer, c->font);
813 
814  for (unsigned int i = 0; i < c->num_user_features; i++)
815  {
816  const hb_feature_t *feature = &c->user_features[i];
817  if (!(feature->start == HB_FEATURE_GLOBAL_START && feature->end == HB_FEATURE_GLOBAL_END)) {
818  unsigned int shift;
819  hb_mask_t mask = map->get_mask (feature->tag, &shift);
820  buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
821  }
822  }
823 }
824 
825 static void
826 hb_ot_zero_width_default_ignorables (const hb_buffer_t *buffer)
827 {
828  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
831  return;
832 
833  unsigned int count = buffer->len;
834  hb_glyph_info_t *info = buffer->info;
836  unsigned int i = 0;
837  for (i = 0; i < count; i++)
838  if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
839  pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
840 }
841 
842 static void
843 hb_ot_hide_default_ignorables (hb_buffer_t *buffer,
844  hb_font_t *font)
845 {
846  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
848  return;
849 
850  unsigned int count = buffer->len;
851  hb_glyph_info_t *info = buffer->info;
852 
853  hb_codepoint_t invisible = buffer->invisible;
855  (invisible || font->get_nominal_glyph (' ', &invisible)))
856  {
857  /* Replace default-ignorables with a zero-advance invisible glyph. */
858  for (unsigned int i = 0; i < count; i++)
859  {
860  if (_hb_glyph_info_is_default_ignorable (&info[i]))
861  info[i].codepoint = invisible;
862  }
863  }
864  else
865  hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable);
866 }
867 
868 
869 static inline void
870 hb_ot_map_glyphs_fast (hb_buffer_t *buffer)
871 {
872  /* Normalization process sets up glyph_index(), we just copy it. */
873  unsigned int count = buffer->len;
874  hb_glyph_info_t *info = buffer->info;
875  for (unsigned int i = 0; i < count; i++)
876  info[i].codepoint = info[i].glyph_index();
877 
878  buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
879 }
880 
881 static inline void
882 hb_synthesize_glyph_classes (hb_buffer_t *buffer)
883 {
884  unsigned int count = buffer->len;
885  hb_glyph_info_t *info = buffer->info;
886  for (unsigned int i = 0; i < count; i++)
887  {
889 
890  /* Never mark default-ignorables as marks.
891  * They won't get in the way of lookups anyway,
892  * but having them as mark will cause them to be skipped
893  * over if the lookup-flag says so, but at least for the
894  * Mongolian variation selectors, looks like Uniscribe
895  * marks them as non-mark. Some Mongolian fonts without
896  * GDEF rely on this. Another notable character that
897  * this applies to is COMBINING GRAPHEME JOINER. */
898  klass = (_hb_glyph_info_get_general_category (&info[i]) !=
900  _hb_glyph_info_is_default_ignorable (&info[i])) ?
903  _hb_glyph_info_set_glyph_props (&info[i], klass);
904  }
905 }
906 
907 static inline void
908 hb_ot_substitute_default (const hb_ot_shape_context_t *c)
909 {
910  hb_buffer_t *buffer = c->buffer;
911 
912  hb_ot_rotate_chars (c);
913 
915 
916  _hb_ot_shape_normalize (c->plan, buffer, c->font);
917 
918  hb_ot_shape_setup_masks (c);
919 
920  /* This is unfortunate to go here, but necessary... */
921  if (c->plan->fallback_mark_positioning)
923 
924  hb_ot_map_glyphs_fast (buffer);
925 
927 }
928 
929 static inline void
930 hb_ot_substitute_complex (const hb_ot_shape_context_t *c)
931 {
932  hb_buffer_t *buffer = c->buffer;
933 
935 
936  if (c->plan->fallback_glyph_classes)
937  hb_synthesize_glyph_classes (c->buffer);
938 
939  c->plan->substitute (c->font, buffer);
940 }
941 
942 static inline void
943 hb_ot_substitute_pre (const hb_ot_shape_context_t *c)
944 {
945  hb_ot_substitute_default (c);
946 
947  _hb_buffer_allocate_gsubgpos_vars (c->buffer);
948 
949  hb_ot_substitute_complex (c);
950 
951 #ifndef HB_NO_AAT_SHAPE
952  if (c->plan->apply_morx && c->plan->apply_gpos)
954 #endif
955 }
956 
957 static inline void
958 hb_ot_substitute_post (const hb_ot_shape_context_t *c)
959 {
960 #ifndef HB_NO_AAT_SHAPE
961  if (c->plan->apply_morx && !c->plan->apply_gpos)
963 #endif
964 
965  hb_ot_hide_default_ignorables (c->buffer, c->font);
966 
967  if (c->plan->shaper->postprocess_glyphs &&
968  c->buffer->message(c->font, "start postprocess-glyphs")) {
969  c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
970  (void) c->buffer->message(c->font, "end postprocess-glyphs");
971  }
972 }
973 
974 
975 /*
976  * Position
977  */
978 
979 static inline void
980 adjust_mark_offsets (hb_glyph_position_t *pos)
981 {
982  pos->x_offset -= pos->x_advance;
983  pos->y_offset -= pos->y_advance;
984 }
985 
986 static inline void
987 zero_mark_width (hb_glyph_position_t *pos)
988 {
989  pos->x_advance = 0;
990  pos->y_advance = 0;
991 }
992 
993 static inline void
994 zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
995 {
996  unsigned int count = buffer->len;
997  hb_glyph_info_t *info = buffer->info;
998  for (unsigned int i = 0; i < count; i++)
999  if (_hb_glyph_info_is_mark (&info[i]))
1000  {
1001  if (adjust_offsets)
1002  adjust_mark_offsets (&buffer->pos[i]);
1003  zero_mark_width (&buffer->pos[i]);
1004  }
1005 }
1006 
1007 static inline void
1008 hb_ot_position_default (const hb_ot_shape_context_t *c)
1009 {
1010  hb_direction_t direction = c->buffer->props.direction;
1011  unsigned int count = c->buffer->len;
1012  hb_glyph_info_t *info = c->buffer->info;
1013  hb_glyph_position_t *pos = c->buffer->pos;
1014 
1016  {
1017  c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
1018  &pos[0].x_advance, sizeof(pos[0]));
1019  /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
1020  if (c->font->has_glyph_h_origin_func ())
1021  for (unsigned int i = 0; i < count; i++)
1022  c->font->subtract_glyph_h_origin (info[i].codepoint,
1023  &pos[i].x_offset,
1024  &pos[i].y_offset);
1025  }
1026  else
1027  {
1028  c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
1029  &pos[0].y_advance, sizeof(pos[0]));
1030  for (unsigned int i = 0; i < count; i++)
1031  {
1032  c->font->subtract_glyph_v_origin (info[i].codepoint,
1033  &pos[i].x_offset,
1034  &pos[i].y_offset);
1035  }
1036  }
1037  if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
1038  _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
1039 }
1040 
1041 static inline void
1042 hb_ot_position_complex (const hb_ot_shape_context_t *c)
1043 {
1044  unsigned int count = c->buffer->len;
1045  hb_glyph_info_t *info = c->buffer->info;
1046  hb_glyph_position_t *pos = c->buffer->pos;
1047 
1048  /* If the font has no GPOS and direction is forward, then when
1049  * zeroing mark widths, we shift the mark with it, such that the
1050  * mark is positioned hanging over the previous glyph. When
1051  * direction is backward we don't shift and it will end up
1052  * hanging over the next glyph after the final reordering.
1053  *
1054  * Note: If fallback positinoing happens, we don't care about
1055  * this as it will be overridden.
1056  */
1057  bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
1058  HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
1059 
1060  /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
1061 
1062  /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
1063  if (c->font->has_glyph_h_origin_func ())
1064  for (unsigned int i = 0; i < count; i++)
1065  c->font->add_glyph_h_origin (info[i].codepoint,
1066  &pos[i].x_offset,
1067  &pos[i].y_offset);
1068 
1069  hb_ot_layout_position_start (c->font, c->buffer);
1070 
1071  if (c->plan->zero_marks)
1072  switch (c->plan->shaper->zero_width_marks)
1073  {
1075  zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
1076  break;
1077 
1078  default:
1081  break;
1082  }
1083 
1084  c->plan->position (c->font, c->buffer);
1085 
1086  if (c->plan->zero_marks)
1087  switch (c->plan->shaper->zero_width_marks)
1088  {
1090  zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
1091  break;
1092 
1093  default:
1096  break;
1097  }
1098 
1099  /* Finish off. Has to follow a certain order. */
1100  hb_ot_layout_position_finish_advances (c->font, c->buffer);
1101  hb_ot_zero_width_default_ignorables (c->buffer);
1102 #ifndef HB_NO_AAT_SHAPE
1103  if (c->plan->apply_morx)
1105 #endif
1106  hb_ot_layout_position_finish_offsets (c->font, c->buffer);
1107 
1108  /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
1109  if (c->font->has_glyph_h_origin_func ())
1110  for (unsigned int i = 0; i < count; i++)
1111  c->font->subtract_glyph_h_origin (info[i].codepoint,
1112  &pos[i].x_offset,
1113  &pos[i].y_offset);
1114 
1115  if (c->plan->fallback_mark_positioning)
1116  _hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer,
1117  adjust_offsets_when_zeroing);
1118 }
1119 
1120 static inline void
1121 hb_ot_position (const hb_ot_shape_context_t *c)
1122 {
1123  c->buffer->clear_positions ();
1124 
1125  hb_ot_position_default (c);
1126 
1127  hb_ot_position_complex (c);
1128 
1129  if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
1130  hb_buffer_reverse (c->buffer);
1131 
1132  _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
1133 }
1134 
1135 static inline void
1136 hb_propagate_flags (hb_buffer_t *buffer)
1137 {
1138  /* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
1139  * Simplifies using them. */
1140 
1141  if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS))
1142  return;
1143 
1144  hb_glyph_info_t *info = buffer->info;
1145 
1147  {
1148  unsigned int mask = 0;
1149  for (unsigned int i = start; i < end; i++)
1151  if (mask)
1152  for (unsigned int i = start; i < end; i++)
1153  info[i].mask |= mask;
1154  }
1155 }
1156 
1157 /* Pull it all together! */
1158 
1159 static void
1160 hb_ot_shape_internal (hb_ot_shape_context_t *c)
1161 {
1162  c->buffer->enter ();
1163 
1164  /* Save the original direction, we use it later. */
1165  c->target_direction = c->buffer->props.direction;
1166 
1167  _hb_buffer_allocate_unicode_vars (c->buffer);
1168 
1169  hb_ot_shape_initialize_masks (c);
1170  hb_set_unicode_props (c->buffer);
1171  hb_insert_dotted_circle (c->buffer, c->font);
1172 
1173  hb_form_clusters (c->buffer);
1174 
1175  hb_ensure_native_direction (c->buffer);
1176 
1177  if (c->plan->shaper->preprocess_text &&
1178  c->buffer->message(c->font, "start preprocess-text"))
1179  {
1180  c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
1181  (void) c->buffer->message(c->font, "end preprocess-text");
1182  }
1183 
1184  hb_ot_substitute_pre (c);
1185  hb_ot_position (c);
1186  hb_ot_substitute_post (c);
1187 
1188  hb_propagate_flags (c->buffer);
1189 
1190  _hb_buffer_deallocate_unicode_vars (c->buffer);
1191 
1192  c->buffer->props.direction = c->target_direction;
1193 
1194  c->buffer->leave ();
1195 }
1196 
1197 
1198 hb_bool_t
1200  hb_font_t *font,
1202  const hb_feature_t *features,
1203  unsigned int num_features)
1204 {
1205  hb_ot_shape_context_t c = {&shape_plan->ot, font, font->face, buffer, features, num_features};
1206  hb_ot_shape_internal (&c);
1207 
1208  return true;
1209 }
1210 
1211 
1223 void
1226  hb_set_t *lookup_indexes /* OUT */)
1227 {
1228  shape_plan->ot.collect_lookups (table_tag, lookup_indexes);
1229 }
1230 
1231 
1232 /* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
1233 static void
1234 add_char (hb_font_t *font,
1235  hb_unicode_funcs_t *unicode,
1236  hb_bool_t mirror,
1237  hb_codepoint_t u,
1238  hb_set_t *glyphs)
1239 {
1240  hb_codepoint_t glyph;
1241  if (font->get_nominal_glyph (u, &glyph))
1242  glyphs->add (glyph);
1243  if (mirror)
1244  {
1245  hb_codepoint_t m = unicode->mirroring (u);
1246  if (m != u && font->get_nominal_glyph (m, &glyph))
1247  glyphs->add (glyph);
1248  }
1249 }
1250 
1251 
1266 void
1269  const hb_feature_t *features,
1270  unsigned int num_features,
1271  hb_set_t *glyphs)
1272 {
1273  const char *shapers[] = {"ot", nullptr};
1274  hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
1275  features, num_features, shapers);
1276 
1277  bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
1278 
1279  unsigned int count = buffer->len;
1280  hb_glyph_info_t *info = buffer->info;
1281  for (unsigned int i = 0; i < count; i++)
1282  add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
1283 
1284  hb_set_t *lookups = hb_set_create ();
1285  hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups);
1286  hb_ot_layout_lookups_substitute_closure (font->face, lookups, glyphs);
1287 
1288  hb_set_destroy (lookups);
1289 
1290  hb_shape_plan_destroy (shape_plan);
1291 }
1292 
1293 
1294 #endif
small capitals from c petite p scientific f u
Definition: afcover.h:88
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
QMap< QString, QString > map
[6]
direction
void hb_aat_layout_substitute(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer)
void hb_aat_layout_track(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer)
void hb_aat_layout_zero_width_deleted_glyphs(hb_buffer_t *buffer)
hb_bool_t hb_aat_layout_has_substitution(hb_face_t *face)
void hb_aat_layout_remove_deleted_glyphs(hb_buffer_t *buffer)
hb_bool_t hb_aat_layout_has_positioning(hb_face_t *face)
void hb_aat_layout_position(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer)
hb_bool_t hb_aat_layout_has_tracking(hb_face_t *face)
void hb_buffer_reverse(hb_buffer_t *buffer)
Definition: hb-buffer.cc:1495
#define HB_BUFFER_DEALLOCATE_VAR(b, var)
Definition: hb-buffer.hh:623
@ HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES
Definition: hb-buffer.hh:67
@ HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK
Definition: hb-buffer.hh:68
@ HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS
Definition: hb-buffer.hh:71
@ HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII
Definition: hb-buffer.hh:66
#define HB_BUFFER_ALLOCATE_VAR(b, var)
Definition: hb-buffer.hh:622
#define foreach_cluster(buffer, start, end)
Definition: hb-buffer.hh:615
hb_direction_t hb_script_get_horizontal_direction(hb_script_t script)
Definition: hb-common.cc:551
void const void *obj HB_UNUSED
Definition: hb-debug.hh:180
HB_EXTERN hb_tag_t table_tag
bool hb_ot_layout_has_kerning(hb_face_t *face)
Definition: hb-ot-layout.cc:85
bool hb_ot_layout_has_machine_kerning(hb_face_t *face)
void hb_ot_layout_position_finish_offsets(hb_font_t *font, hb_buffer_t *buffer)
void hb_ot_layout_position_finish_advances(hb_font_t *font, hb_buffer_t *buffer)
bool hb_ot_layout_has_cross_kerning(hb_face_t *face)
void hb_ot_layout_substitute_start(hb_font_t *font, hb_buffer_t *buffer)
hb_bool_t hb_ot_layout_has_glyph_classes(hb_face_t *face)
hb_bool_t hb_ot_layout_has_positioning(hb_face_t *face)
void hb_ot_layout_kern(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer)
hb_bool_t hb_ot_layout_has_substitution(hb_face_t *face)
void hb_ot_layout_lookups_substitute_closure(hb_face_t *face, const hb_set_t *lookups, hb_set_t *glyphs)
void hb_ot_layout_position_start(hb_font_t *font, hb_buffer_t *buffer)
void hb_ot_layout_delete_glyphs_inplace(hb_buffer_t *buffer, bool(*filter)(const hb_glyph_info_t *info))
#define foreach_grapheme(buffer, start, end)
hb_ot_layout_glyph_props_flags_t
Definition: hb-ot-layout.hh:77
@ HB_OT_LAYOUT_GLYPH_PROPS_MARK
Definition: hb-ot-layout.hh:81
@ HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH
Definition: hb-ot-layout.hh:79
#define HB_OT_MAP_MAX_VALUE
Definition: hb-ot-map.hh:36
@ F_HAS_FALLBACK
Definition: hb-ot-map.hh:181
@ F_GLOBAL_SEARCH
Definition: hb-ot-map.hh:187
@ F_GLOBAL_HAS_FALLBACK
Definition: hb-ot-map.hh:186
@ F_GLOBAL_MANUAL_JOINERS
Definition: hb-ot-map.hh:185
@ F_GLOBAL
Definition: hb-ot-map.hh:180
@ F_RANDOM
Definition: hb-ot-map.hh:188
@ F_NONE
Definition: hb-ot-map.hh:179
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_dumber
const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default
@ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY
@ HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE
@ HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE
void _hb_ot_shape_fallback_kern(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer)
void _hb_ot_shape_fallback_spaces(const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font, hb_buffer_t *buffer)
void _hb_ot_shape_fallback_mark_position_recategorize_marks(const hb_ot_shape_plan_t *plan HB_UNUSED, hb_font_t *font HB_UNUSED, hb_buffer_t *buffer)
void _hb_ot_shape_fallback_mark_position(const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer, bool adjust_offsets_when_zeroing)
void _hb_ot_shape_normalize(const hb_ot_shape_plan_t *plan, hb_buffer_t *buffer, hb_font_t *font)
#define glyph_index()
void _hb_ot_shaper_face_data_destroy(hb_ot_face_data_t *data)
Definition: hb-ot-shape.cc:437
hb_bool_t _hb_ot_shape(hb_shape_plan_t *shape_plan, hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features)
void _hb_ot_shaper_font_data_destroy(hb_ot_font_data_t *data HB_UNUSED)
Definition: hb-ot-shape.cc:455
void hb_ot_shape_plan_collect_lookups(hb_shape_plan_t *shape_plan, hb_tag_t table_tag, hb_set_t *lookup_indexes)
hb_ot_face_data_t * _hb_ot_shaper_face_data_create(hb_face_t *face)
Definition: hb-ot-shape.cc:431
hb_ot_font_data_t * _hb_ot_shaper_font_data_create(hb_font_t *font HB_UNUSED)
Definition: hb-ot-shape.cc:449
void hb_ot_shape_glyphs_closure(hb_font_t *font, hb_buffer_t *buffer, const hb_feature_t *features, unsigned int num_features, hb_set_t *glyphs)
hb_set_t * hb_set_create()
Definition: hb-set.cc:52
void hb_set_destroy(hb_set_t *set)
Definition: hb-set.cc:106
void hb_shape_plan_destroy(hb_shape_plan_t *shape_plan)
hb_shape_plan_t * hb_shape_plan_create_cached(hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, const char *const *shaper_list)
#define HB_SHAPER_DATA_SUCCEEDED
Definition: hb-shaper.hh:71
bool _hb_unicode_is_emoji_Extended_Pictographic(hb_codepoint_t cp)
Definition: hb-unicode.cc:611
#define HB_UNICODE_GENERAL_CATEGORY_IS_LETTER(gen_cat)
Definition: hb-unicode.hh:363
#define unlikely(expr)
Definition: hb.hh:251
backing_store_ptr info
[4]
Definition: jmemsys.h:161
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld SRC pixld MASK if DST_R else pixld DST_R endif if
void
Definition: png.h:1080
#define ARRAY_LENGTH(a)
Definition: qkmsdevice.cpp:52
bool int shift
const GLfloat * m
GLuint64 key
GLuint GLuint end
GLenum GLenum GLsizei count
GLenum face
GLenum GLuint buffer
GLenum GLuint GLsizei const GLenum * props
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint start
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
const GLubyte * c
Definition: qopenglext.h:12701
@ HB_GLYPH_FLAG_DEFINED
Definition: hb-buffer.h:155
@ HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES
Definition: hb-buffer.h:428
@ HB_BUFFER_CONTENT_TYPE_GLYPHS
Definition: hb-buffer.h:284
@ HB_BUFFER_FLAG_DO_NOT_INSERT_DOTTED_CIRCLE
Definition: hb-buffer.h:387
@ HB_BUFFER_FLAG_REMOVE_DEFAULT_IGNORABLES
Definition: hb-buffer.h:386
@ HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES
Definition: hb-buffer.h:385
@ HB_BUFFER_FLAG_BOT
Definition: hb-buffer.h:383
HB_BEGIN_DECLS typedef int hb_bool_t
Definition: hb-common.h:97
uint32_t hb_codepoint_t
Definition: hb-common.h:106
#define HB_TAG(c1, c2, c3, c4)
Definition: hb-common.h:169
uint32_t hb_mask_t
Definition: hb-common.h:122
#define HB_DIRECTION_REVERSE(dir)
Definition: hb-common.h:297
#define HB_FEATURE_GLOBAL_END
Definition: hb-common.h:794
#define HB_DIRECTION_IS_FORWARD(dir)
Definition: hb-common.h:279
#define HB_DIRECTION_IS_VERTICAL(dir)
Definition: hb-common.h:270
#define HB_DIRECTION_IS_BACKWARD(dir)
Definition: hb-common.h:288
uint32_t hb_tag_t
Definition: hb-common.h:157
hb_direction_t
Definition: hb-common.h:229
@ HB_DIRECTION_BTT
Definition: hb-common.h:234
@ HB_DIRECTION_TTB
Definition: hb-common.h:233
@ HB_DIRECTION_INVALID
Definition: hb-common.h:230
@ HB_DIRECTION_RTL
Definition: hb-common.h:232
@ HB_DIRECTION_LTR
Definition: hb-common.h:231
#define HB_FEATURE_GLOBAL_START
Definition: hb-common.h:784
#define HB_DIRECTION_IS_HORIZONTAL(dir)
Definition: hb-common.h:261
#define HB_OT_TAG_GSUB
Definition: hb-ot-layout.h:58
#define HB_OT_LAYOUT_NO_FEATURE_INDEX
Definition: hb-ot-layout.h:199
@ HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER
Definition: hb-unicode.h:106
@ HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK
Definition: hb-unicode.h:105
@ HB_UNICODE_GENERAL_CATEGORY_MODIFIER_SYMBOL
Definition: hb-unicode.h:117
HB_INTERNAL void compile(hb_aat_map_t &m)
Definition: hb-aat-map.cc:81
HB_INTERNAL void add_feature(hb_tag_t tag, unsigned int value=1)
Definition: hb-aat-map.cc:39
void init()
Definition: hb-aat-map.hh:39
void fini()
Definition: hb-aat-map.hh:44
unsigned int len
Definition: hb-buffer.hh:113
unsigned int end
Definition: hb-common.h:815
unsigned int start
Definition: hb-common.h:814
hb_tag_t tag
Definition: hb-common.h:812
uint32_t value
Definition: hb-common.h:813
hb_codepoint_t codepoint
Definition: hb-buffer.h:63
void(* collect_features)(hb_ot_shape_planner_t *plan)
hb_ot_shape_zero_width_marks_type_t zero_width_marks
void(* data_destroy)(void *data)
void(* override_features)(hb_ot_shape_planner_t *plan)
void *(* data_create)(const hb_ot_shape_plan_t *plan)
HB_INTERNAL void compile(hb_ot_map_t &m, const hb_ot_shape_plan_key_t &key)
Definition: hb-ot-map.cc:167
hb_mask_t get_mask(hb_tag_t feature_tag, unsigned int *shift=nullptr) const
Definition: hb-ot-map.hh:111
hb_mask_t get_1_mask(hb_tag_t feature_tag) const
Definition: hb-ot-map.hh:124
HB_INTERNAL void position(const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
hb_tag_t chosen_script[2]
Definition: hb-ot-map.hh:165
void init()
Definition: hb-ot-map.hh:88
void fini()
Definition: hb-ot-map.hh:99
unsigned int get_feature_index(unsigned int table_index, hb_tag_t feature_tag) const
Definition: hb-ot-map.hh:130
HB_INTERNAL void substitute(const struct hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) const
hb_buffer_t * buffer
Definition: hb-ot-shape.cc:469
hb_direction_t target_direction
Definition: hb-ot-shape.cc:474
hb_ot_shape_plan_t * plan
Definition: hb-ot-shape.cc:466
unsigned int num_user_features
Definition: hb-ot-shape.cc:471
const hb_feature_t * user_features
Definition: hb-ot-shape.cc:470
hb_mask_t rtlm_mask
Definition: hb-ot-shape.hh:75
HB_INTERNAL void position(hb_font_t *font, hb_buffer_t *buffer) const
Definition: hb-ot-shape.cc:277
bool fallback_mark_positioning
Definition: hb-ot-shape.hh:106
hb_mask_t frac_mask
Definition: hb-ot-shape.hh:69
HB_INTERNAL bool init0(hb_face_t *face, const hb_shape_plan_key_t *key)
Definition: hb-ot-shape.cc:219
hb_aat_map_t aat_map
Definition: hb-ot-shape.hh:66
void collect_lookups(hb_tag_t table_tag, hb_set_t *lookups) const
Definition: hb-ot-shape.hh:126
HB_INTERNAL void fini()
Definition: hb-ot-shape.cc:253
hb_ot_map_t map
Definition: hb-ot-shape.hh:65
hb_mask_t trak_mask
Definition: hb-ot-shape.hh:82
hb_mask_t numr_mask
Definition: hb-ot-shape.hh:69
HB_INTERNAL void substitute(hb_font_t *font, hb_buffer_t *buffer) const
Definition: hb-ot-shape.cc:265
bool adjust_mark_positioning_when_zeroing
Definition: hb-ot-shape.hh:107
hb_mask_t kern_mask
Definition: hb-ot-shape.hh:77
hb_segment_properties_t props
Definition: hb-ot-shape.hh:63
hb_mask_t dnom_mask
Definition: hb-ot-shape.hh:69
const struct hb_ot_complex_shaper_t * shaper
Definition: hb-ot-shape.hh:64
HB_INTERNAL void compile(hb_ot_shape_plan_t &plan, const hb_ot_shape_plan_key_t &key)
Definition: hb-ot-shape.cc:100
const struct hb_ot_complex_shaper_t * shaper
Definition: hb-ot-shape.hh:161
HB_INTERNAL hb_ot_shape_planner_t(hb_face_t *face, const hb_segment_properties_t *props)
Definition: hb-ot-shape.cc:79
hb_segment_properties_t props
Definition: hb-ot-shape.hh:151
hb_aat_map_builder_t aat_map
Definition: hb-ot-shape.hh:153
hb_ot_map_builder_t map
Definition: hb-ot-shape.hh:152
bool script_fallback_mark_positioning
Definition: hb-ot-shape.hh:160
hb_direction_t direction
Definition: hb-buffer.h:202
hb_ot_shape_plan_t ot
void add(hb_codepoint_t g)
Definition: hb-set.hh:85