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 #define HB_SHAPER ot
30 #define hb_ot_shaper_face_data_t hb_ot_layout_t
31 #define hb_ot_shaper_shape_plan_data_t hb_ot_shape_plan_t
32 #include "hb-shaper-impl-private.hh"
33 
34 #include "hb-ot-shape-private.hh"
35 #include "hb-ot-shape-complex-private.hh"
36 #include "hb-ot-shape-fallback-private.hh"
37 #include "hb-ot-shape-normalize-private.hh"
38 
39 #include "hb-ot-layout-private.hh"
40 #include "hb-unicode-private.hh"
41 #include "hb-set-private.hh"
42 
43 
44 static hb_tag_t common_features[] = {
45   HB_TAG('c','c','m','p'),
46   HB_TAG('l','o','c','l'),
47   HB_TAG('m','a','r','k'),
48   HB_TAG('m','k','m','k'),
49   HB_TAG('r','l','i','g'),
50 };
51 
52 
53 static hb_tag_t horizontal_features[] = {
54   HB_TAG('c','a','l','t'),
55   HB_TAG('c','l','i','g'),
56   HB_TAG('c','u','r','s'),
57   HB_TAG('k','e','r','n'),
58   HB_TAG('l','i','g','a'),
59   HB_TAG('r','c','l','t'),
60 };
61 
62 
63 
64 static void
hb_ot_shape_collect_features(hb_ot_shape_planner_t * planner,const hb_segment_properties_t * props,const hb_feature_t * user_features,unsigned int num_user_features)65 hb_ot_shape_collect_features (hb_ot_shape_planner_t          *planner,
66 			      const hb_segment_properties_t  *props,
67 			      const hb_feature_t             *user_features,
68 			      unsigned int                    num_user_features)
69 {
70   hb_ot_map_builder_t *map = &planner->map;
71 
72   map->add_global_bool_feature (HB_TAG('r','v','r','n'));
73   map->add_gsub_pause (nullptr);
74 
75   switch (props->direction) {
76     case HB_DIRECTION_LTR:
77       map->add_global_bool_feature (HB_TAG ('l','t','r','a'));
78       map->add_global_bool_feature (HB_TAG ('l','t','r','m'));
79       break;
80     case HB_DIRECTION_RTL:
81       map->add_global_bool_feature (HB_TAG ('r','t','l','a'));
82       map->add_feature (HB_TAG ('r','t','l','m'), 1, F_NONE);
83       break;
84     case HB_DIRECTION_TTB:
85     case HB_DIRECTION_BTT:
86     case HB_DIRECTION_INVALID:
87     default:
88       break;
89   }
90 
91   map->add_feature (HB_TAG ('f','r','a','c'), 1, F_NONE);
92   map->add_feature (HB_TAG ('n','u','m','r'), 1, F_NONE);
93   map->add_feature (HB_TAG ('d','n','o','m'), 1, F_NONE);
94 
95   if (planner->shaper->collect_features)
96     planner->shaper->collect_features (planner);
97 
98   for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++)
99     map->add_global_bool_feature (common_features[i]);
100 
101   if (HB_DIRECTION_IS_HORIZONTAL (props->direction))
102     for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++)
103       map->add_feature (horizontal_features[i], 1, F_GLOBAL |
104 			(horizontal_features[i] == HB_TAG('k','e','r','n') ?
105 			 F_HAS_FALLBACK : F_NONE));
106   else
107   {
108     /* We really want to find a 'vert' feature if there's any in the font, no
109      * matter which script/langsys it is listed (or not) under.
110      * See various bugs referenced from:
111      * https://github.com/harfbuzz/harfbuzz/issues/63 */
112     map->add_feature (HB_TAG ('v','e','r','t'), 1, F_GLOBAL | F_GLOBAL_SEARCH);
113   }
114 
115   if (planner->shaper->override_features)
116     planner->shaper->override_features (planner);
117 
118   for (unsigned int i = 0; i < num_user_features; i++) {
119     const hb_feature_t *feature = &user_features[i];
120     map->add_feature (feature->tag, feature->value,
121 		      (feature->start == 0 && feature->end == (unsigned int) -1) ?
122 		       F_GLOBAL : F_NONE);
123   }
124 }
125 
126 
127 /*
128  * shaper face data
129  */
130 
HB_SHAPER_DATA_ENSURE_DEFINE(ot,face)131 HB_SHAPER_DATA_ENSURE_DEFINE(ot, face)
132 
133 hb_ot_shaper_face_data_t *
134 _hb_ot_shaper_face_data_create (hb_face_t *face)
135 {
136   return _hb_ot_layout_create (face);
137 }
138 
139 void
_hb_ot_shaper_face_data_destroy(hb_ot_shaper_face_data_t * data)140 _hb_ot_shaper_face_data_destroy (hb_ot_shaper_face_data_t *data)
141 {
142   _hb_ot_layout_destroy (data);
143 }
144 
145 
146 /*
147  * shaper font data
148  */
149 
150 HB_SHAPER_DATA_ENSURE_DEFINE(ot, font)
151 
152 struct hb_ot_shaper_font_data_t {};
153 
154 hb_ot_shaper_font_data_t *
_hb_ot_shaper_font_data_create(hb_font_t * font HB_UNUSED)155 _hb_ot_shaper_font_data_create (hb_font_t *font HB_UNUSED)
156 {
157   return (hb_ot_shaper_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
158 }
159 
160 void
_hb_ot_shaper_font_data_destroy(hb_ot_shaper_font_data_t * data)161 _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data)
162 {
163 }
164 
165 
166 /*
167  * shaper shape_plan data
168  */
169 
170 hb_ot_shaper_shape_plan_data_t *
_hb_ot_shaper_shape_plan_data_create(hb_shape_plan_t * shape_plan,const hb_feature_t * user_features,unsigned int num_user_features,const int * coords,unsigned int num_coords)171 _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t    *shape_plan,
172 				      const hb_feature_t *user_features,
173 				      unsigned int        num_user_features,
174 				      const int          *coords,
175 				      unsigned int        num_coords)
176 {
177   hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
178   if (unlikely (!plan))
179     return nullptr;
180 
181   hb_ot_shape_planner_t planner (shape_plan);
182 
183   planner.shaper = hb_ot_shape_complex_categorize (&planner);
184 
185   hb_ot_shape_collect_features (&planner, &shape_plan->props,
186 				user_features, num_user_features);
187 
188   planner.compile (*plan, coords, num_coords);
189 
190   if (plan->shaper->data_create) {
191     plan->data = plan->shaper->data_create (plan);
192     if (unlikely (!plan->data))
193       return nullptr;
194   }
195 
196   return plan;
197 }
198 
199 void
_hb_ot_shaper_shape_plan_data_destroy(hb_ot_shaper_shape_plan_data_t * plan)200 _hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
201 {
202   if (plan->shaper->data_destroy)
203     plan->shaper->data_destroy (const_cast<void *> (plan->data));
204 
205   plan->finish ();
206 
207   free (plan);
208 }
209 
210 
211 /*
212  * shaper
213  */
214 
215 struct hb_ot_shape_context_t
216 {
217   hb_ot_shape_plan_t *plan;
218   hb_font_t *font;
219   hb_face_t *face;
220   hb_buffer_t  *buffer;
221   const hb_feature_t *user_features;
222   unsigned int        num_user_features;
223 
224   /* Transient stuff */
225   bool fallback_positioning;
226   bool fallback_glyph_classes;
227   hb_direction_t target_direction;
228 };
229 
230 
231 
232 /* Main shaper */
233 
234 
235 /* Prepare */
236 
237 static void
hb_set_unicode_props(hb_buffer_t * buffer)238 hb_set_unicode_props (hb_buffer_t *buffer)
239 {
240   unsigned int count = buffer->len;
241   hb_glyph_info_t *info = buffer->info;
242   for (unsigned int i = 0; i < count; i++)
243     _hb_glyph_info_set_unicode_props (&info[i], buffer);
244 }
245 
246 static void
hb_insert_dotted_circle(hb_buffer_t * buffer,hb_font_t * font)247 hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font)
248 {
249   if (!(buffer->flags & HB_BUFFER_FLAG_BOT) ||
250       buffer->context_len[0] ||
251       _hb_glyph_info_get_general_category (&buffer->info[0]) !=
252       HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK)
253     return;
254 
255   if (!font->has_glyph (0x25CCu))
256     return;
257 
258   hb_glyph_info_t dottedcircle = {0};
259   dottedcircle.codepoint = 0x25CCu;
260   _hb_glyph_info_set_unicode_props (&dottedcircle, buffer);
261 
262   buffer->clear_output ();
263 
264   buffer->idx = 0;
265   hb_glyph_info_t info = dottedcircle;
266   info.cluster = buffer->cur().cluster;
267   info.mask = buffer->cur().mask;
268   buffer->output_info (info);
269   while (buffer->idx < buffer->len && !buffer->in_error)
270     buffer->next_glyph ();
271 
272   buffer->swap_buffers ();
273 }
274 
275 static void
hb_form_clusters(hb_buffer_t * buffer)276 hb_form_clusters (hb_buffer_t *buffer)
277 {
278   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII))
279     return;
280 
281   /* Loop duplicated in hb_ensure_native_direction(), and in _hb-coretext.cc */
282   unsigned int base = 0;
283   unsigned int count = buffer->len;
284   hb_glyph_info_t *info = buffer->info;
285   for (unsigned int i = 1; i < count; i++)
286   {
287     if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i])) &&
288 		!_hb_glyph_info_is_joiner (&info[i])))
289     {
290       if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
291 	buffer->merge_clusters (base, i);
292       else
293 	buffer->unsafe_to_break (base, i);
294       base = i;
295     }
296   }
297   if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_GRAPHEMES)
298     buffer->merge_clusters (base, count);
299   else
300     buffer->unsafe_to_break (base, count);
301 }
302 
303 static void
hb_ensure_native_direction(hb_buffer_t * buffer)304 hb_ensure_native_direction (hb_buffer_t *buffer)
305 {
306   hb_direction_t direction = buffer->props.direction;
307 
308   /* TODO vertical:
309    * The only BTT vertical script is Ogham, but it's not clear to me whether OpenType
310    * Ogham fonts are supposed to be implemented BTT or not.  Need to research that
311    * first. */
312   if ((HB_DIRECTION_IS_HORIZONTAL (direction) && direction != hb_script_get_horizontal_direction (buffer->props.script)) ||
313       (HB_DIRECTION_IS_VERTICAL   (direction) && direction != HB_DIRECTION_TTB))
314   {
315     /* Same loop as hb_form_clusters().
316      * Since form_clusters() merged clusters already, we don't merge. */
317     unsigned int base = 0;
318     unsigned int count = buffer->len;
319     hb_glyph_info_t *info = buffer->info;
320     for (unsigned int i = 1; i < count; i++)
321     {
322       if (likely (!HB_UNICODE_GENERAL_CATEGORY_IS_MARK (_hb_glyph_info_get_general_category (&info[i]))))
323       {
324 	if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
325 	  buffer->merge_clusters (base, i);
326 	buffer->reverse_range (base, i);
327 
328 	base = i;
329       }
330     }
331     if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)
332       buffer->merge_clusters (base, count);
333     buffer->reverse_range (base, count);
334 
335     buffer->reverse ();
336 
337     buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction);
338   }
339 }
340 
341 
342 /* Substitute */
343 
344 static inline void
hb_ot_mirror_chars(hb_ot_shape_context_t * c)345 hb_ot_mirror_chars (hb_ot_shape_context_t *c)
346 {
347   if (HB_DIRECTION_IS_FORWARD (c->target_direction))
348     return;
349 
350   hb_buffer_t *buffer = c->buffer;
351   hb_unicode_funcs_t *unicode = buffer->unicode;
352   hb_mask_t rtlm_mask = c->plan->rtlm_mask;
353 
354   unsigned int count = buffer->len;
355   hb_glyph_info_t *info = buffer->info;
356   for (unsigned int i = 0; i < count; i++) {
357     hb_codepoint_t codepoint = unicode->mirroring (info[i].codepoint);
358     if (likely (codepoint == info[i].codepoint || !c->font->has_glyph (codepoint)))
359       info[i].mask |= rtlm_mask;
360     else
361       info[i].codepoint = codepoint;
362   }
363 }
364 
365 static inline void
hb_ot_shape_setup_masks_fraction(hb_ot_shape_context_t * c)366 hb_ot_shape_setup_masks_fraction (hb_ot_shape_context_t *c)
367 {
368   if (!(c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_NON_ASCII) ||
369       !c->plan->has_frac)
370     return;
371 
372   hb_buffer_t *buffer = c->buffer;
373 
374   hb_mask_t pre_mask, post_mask;
375   if (HB_DIRECTION_IS_FORWARD (buffer->props.direction))
376   {
377     pre_mask = c->plan->numr_mask | c->plan->frac_mask;
378     post_mask = c->plan->frac_mask | c->plan->dnom_mask;
379   }
380   else
381   {
382     pre_mask = c->plan->frac_mask | c->plan->dnom_mask;
383     post_mask = c->plan->numr_mask | c->plan->frac_mask;
384   }
385 
386   unsigned int count = buffer->len;
387   hb_glyph_info_t *info = buffer->info;
388   for (unsigned int i = 0; i < count; i++)
389   {
390     if (info[i].codepoint == 0x2044u) /* FRACTION SLASH */
391     {
392       unsigned int start = i, end = i + 1;
393       while (start &&
394 	     _hb_glyph_info_get_general_category (&info[start - 1]) ==
395 	     HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
396         start--;
397       while (end < count &&
398 	     _hb_glyph_info_get_general_category (&info[end]) ==
399 	     HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER)
400         end++;
401 
402       buffer->unsafe_to_break (start, end);
403 
404       for (unsigned int j = start; j < i; j++)
405         info[j].mask |= pre_mask;
406       info[i].mask |= c->plan->frac_mask;
407       for (unsigned int j = i + 1; j < end; j++)
408         info[j].mask |= post_mask;
409 
410       i = end - 1;
411     }
412   }
413 }
414 
415 static inline void
hb_ot_shape_initialize_masks(hb_ot_shape_context_t * c)416 hb_ot_shape_initialize_masks (hb_ot_shape_context_t *c)
417 {
418   hb_ot_map_t *map = &c->plan->map;
419   hb_buffer_t *buffer = c->buffer;
420 
421   hb_mask_t global_mask = map->get_global_mask ();
422   buffer->reset_masks (global_mask);
423 }
424 
425 static inline void
hb_ot_shape_setup_masks(hb_ot_shape_context_t * c)426 hb_ot_shape_setup_masks (hb_ot_shape_context_t *c)
427 {
428   hb_ot_map_t *map = &c->plan->map;
429   hb_buffer_t *buffer = c->buffer;
430 
431   hb_ot_shape_setup_masks_fraction (c);
432 
433   if (c->plan->shaper->setup_masks)
434     c->plan->shaper->setup_masks (c->plan, buffer, c->font);
435 
436   for (unsigned int i = 0; i < c->num_user_features; i++)
437   {
438     const hb_feature_t *feature = &c->user_features[i];
439     if (!(feature->start == 0 && feature->end == (unsigned int)-1)) {
440       unsigned int shift;
441       hb_mask_t mask = map->get_mask (feature->tag, &shift);
442       buffer->set_masks (feature->value << shift, mask, feature->start, feature->end);
443     }
444   }
445 }
446 
447 static void
hb_ot_zero_width_default_ignorables(hb_ot_shape_context_t * c)448 hb_ot_zero_width_default_ignorables (hb_ot_shape_context_t *c)
449 {
450   hb_buffer_t *buffer = c->buffer;
451 
452   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
453       (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
454     return;
455 
456   unsigned int count = buffer->len;
457   hb_glyph_info_t *info = buffer->info;
458   hb_glyph_position_t *pos = buffer->pos;
459   unsigned int i = 0;
460   for (i = 0; i < count; i++)
461     if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
462       pos[i].x_advance = pos[i].y_advance = pos[i].x_offset = pos[i].y_offset = 0;
463 }
464 
465 static void
hb_ot_hide_default_ignorables(hb_ot_shape_context_t * c)466 hb_ot_hide_default_ignorables (hb_ot_shape_context_t *c)
467 {
468   hb_buffer_t *buffer = c->buffer;
469 
470   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_DEFAULT_IGNORABLES) ||
471       (buffer->flags & HB_BUFFER_FLAG_PRESERVE_DEFAULT_IGNORABLES))
472     return;
473 
474   unsigned int count = buffer->len;
475   hb_glyph_info_t *info = buffer->info;
476   hb_glyph_position_t *pos = buffer->pos;
477   unsigned int i = 0;
478   for (i = 0; i < count; i++)
479   {
480     if (unlikely (_hb_glyph_info_is_default_ignorable (&info[i])))
481       break;
482   }
483 
484   /* No default-ignorables found; return. */
485   if (i == count)
486     return;
487 
488   hb_codepoint_t space;
489   if (c->font->get_nominal_glyph (' ', &space))
490   {
491     /* Replace default-ignorables with a zero-advance space glyph. */
492     for (/*continue*/; i < count; i++)
493     {
494       if (_hb_glyph_info_is_default_ignorable (&info[i]))
495 	info[i].codepoint = space;
496     }
497   }
498   else
499   {
500     /* Merge clusters and delete default-ignorables.
501      * NOTE! We can't use out-buffer as we have positioning data. */
502     unsigned int j = i;
503     for (; i < count; i++)
504     {
505       if (_hb_glyph_info_is_default_ignorable (&info[i]))
506       {
507 	/* Merge clusters.
508 	 * Same logic as buffer->delete_glyph(), but for in-place removal. */
509 
510 	unsigned int cluster = info[i].cluster;
511 	if (i + 1 < count && cluster == info[i + 1].cluster)
512 	  continue; /* Cluster survives; do nothing. */
513 
514 	if (j)
515 	{
516 	  /* Merge cluster backward. */
517 	  if (cluster < info[j - 1].cluster)
518 	  {
519 	    unsigned int mask = info[i].mask;
520 	    unsigned int old_cluster = info[j - 1].cluster;
521 	    for (unsigned k = j; k && info[k - 1].cluster == old_cluster; k--)
522 	      buffer->set_cluster (info[k - 1], cluster, mask);
523 	  }
524 	  continue;
525 	}
526 
527 	if (i + 1 < count)
528 	  buffer->merge_clusters (i, i + 2); /* Merge cluster forward. */
529 
530 	continue;
531       }
532 
533       if (j != i)
534       {
535 	info[j] = info[i];
536 	pos[j] = pos[i];
537       }
538       j++;
539     }
540     buffer->len = j;
541   }
542 }
543 
544 
545 static inline void
hb_ot_map_glyphs_fast(hb_buffer_t * buffer)546 hb_ot_map_glyphs_fast (hb_buffer_t  *buffer)
547 {
548   /* Normalization process sets up glyph_index(), we just copy it. */
549   unsigned int count = buffer->len;
550   hb_glyph_info_t *info = buffer->info;
551   for (unsigned int i = 0; i < count; i++)
552     info[i].codepoint = info[i].glyph_index();
553 
554   buffer->content_type = HB_BUFFER_CONTENT_TYPE_GLYPHS;
555 }
556 
557 static inline void
hb_synthesize_glyph_classes(hb_ot_shape_context_t * c)558 hb_synthesize_glyph_classes (hb_ot_shape_context_t *c)
559 {
560   unsigned int count = c->buffer->len;
561   hb_glyph_info_t *info = c->buffer->info;
562   for (unsigned int i = 0; i < count; i++)
563   {
564     hb_ot_layout_glyph_props_flags_t klass;
565 
566     /* Never mark default-ignorables as marks.
567      * They won't get in the way of lookups anyway,
568      * but having them as mark will cause them to be skipped
569      * over if the lookup-flag says so, but at least for the
570      * Mongolian variation selectors, looks like Uniscribe
571      * marks them as non-mark.  Some Mongolian fonts without
572      * GDEF rely on this.  Another notable character that
573      * this applies to is COMBINING GRAPHEME JOINER. */
574     klass = (_hb_glyph_info_get_general_category (&info[i]) !=
575 	     HB_UNICODE_GENERAL_CATEGORY_NON_SPACING_MARK ||
576 	     _hb_glyph_info_is_default_ignorable (&info[i])) ?
577 	    HB_OT_LAYOUT_GLYPH_PROPS_BASE_GLYPH :
578 	    HB_OT_LAYOUT_GLYPH_PROPS_MARK;
579     _hb_glyph_info_set_glyph_props (&info[i], klass);
580   }
581 }
582 
583 static inline void
hb_ot_substitute_default(hb_ot_shape_context_t * c)584 hb_ot_substitute_default (hb_ot_shape_context_t *c)
585 {
586   hb_buffer_t *buffer = c->buffer;
587 
588   hb_ot_mirror_chars (c);
589 
590   HB_BUFFER_ALLOCATE_VAR (buffer, glyph_index);
591 
592   _hb_ot_shape_normalize (c->plan, buffer, c->font);
593 
594   hb_ot_shape_setup_masks (c);
595 
596   /* This is unfortunate to go here, but necessary... */
597   if (c->fallback_positioning)
598     _hb_ot_shape_fallback_position_recategorize_marks (c->plan, c->font, buffer);
599 
600   hb_ot_map_glyphs_fast (buffer);
601 
602   HB_BUFFER_DEALLOCATE_VAR (buffer, glyph_index);
603 }
604 
605 static inline void
hb_ot_substitute_complex(hb_ot_shape_context_t * c)606 hb_ot_substitute_complex (hb_ot_shape_context_t *c)
607 {
608   hb_buffer_t *buffer = c->buffer;
609 
610   hb_ot_layout_substitute_start (c->font, buffer);
611 
612   if (!hb_ot_layout_has_glyph_classes (c->face))
613     hb_synthesize_glyph_classes (c);
614 
615   c->plan->substitute (c->font, buffer);
616 
617   return;
618 }
619 
620 static inline void
hb_ot_substitute(hb_ot_shape_context_t * c)621 hb_ot_substitute (hb_ot_shape_context_t *c)
622 {
623   hb_ot_substitute_default (c);
624 
625   _hb_buffer_allocate_gsubgpos_vars (c->buffer);
626 
627   hb_ot_substitute_complex (c);
628 }
629 
630 /* Position */
631 
632 static inline void
adjust_mark_offsets(hb_glyph_position_t * pos)633 adjust_mark_offsets (hb_glyph_position_t *pos)
634 {
635   pos->x_offset -= pos->x_advance;
636   pos->y_offset -= pos->y_advance;
637 }
638 
639 static inline void
zero_mark_width(hb_glyph_position_t * pos)640 zero_mark_width (hb_glyph_position_t *pos)
641 {
642   pos->x_advance = 0;
643   pos->y_advance = 0;
644 }
645 
646 static inline void
zero_mark_widths_by_gdef(hb_buffer_t * buffer,bool adjust_offsets)647 zero_mark_widths_by_gdef (hb_buffer_t *buffer, bool adjust_offsets)
648 {
649   unsigned int count = buffer->len;
650   hb_glyph_info_t *info = buffer->info;
651   for (unsigned int i = 0; i < count; i++)
652     if (_hb_glyph_info_is_mark (&info[i]))
653     {
654       if (adjust_offsets)
655         adjust_mark_offsets (&buffer->pos[i]);
656       zero_mark_width (&buffer->pos[i]);
657     }
658 }
659 
660 static inline void
hb_ot_position_default(hb_ot_shape_context_t * c)661 hb_ot_position_default (hb_ot_shape_context_t *c)
662 {
663   hb_direction_t direction = c->buffer->props.direction;
664   unsigned int count = c->buffer->len;
665   hb_glyph_info_t *info = c->buffer->info;
666   hb_glyph_position_t *pos = c->buffer->pos;
667 
668   if (HB_DIRECTION_IS_HORIZONTAL (direction))
669   {
670     for (unsigned int i = 0; i < count; i++)
671       pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint);
672     /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
673     if (c->font->has_glyph_h_origin_func ())
674       for (unsigned int i = 0; i < count; i++)
675 	c->font->subtract_glyph_h_origin (info[i].codepoint,
676 					  &pos[i].x_offset,
677 					  &pos[i].y_offset);
678   }
679   else
680   {
681     for (unsigned int i = 0; i < count; i++)
682     {
683       pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint);
684       c->font->subtract_glyph_v_origin (info[i].codepoint,
685 					&pos[i].x_offset,
686 					&pos[i].y_offset);
687     }
688   }
689   if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
690     _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
691 }
692 
693 static inline void
hb_ot_position_complex(hb_ot_shape_context_t * c)694 hb_ot_position_complex (hb_ot_shape_context_t *c)
695 {
696   unsigned int count = c->buffer->len;
697   hb_glyph_info_t *info = c->buffer->info;
698   hb_glyph_position_t *pos = c->buffer->pos;
699 
700   /* If the font has no GPOS, AND, no fallback positioning will
701    * happen, AND, direction is forward, then when zeroing mark
702    * widths, we shift the mark with it, such that the mark
703    * is positioned hanging over the previous glyph.  When
704    * direction is backward we don't shift and it will end up
705    * hanging over the next glyph after the final reordering.
706    * If fallback positinoing happens or GPOS is present, we don't
707    * care.
708    */
709   bool adjust_offsets_when_zeroing = c->fallback_positioning &&
710 				     !c->plan->shaper->fallback_position &&
711 				     HB_DIRECTION_IS_FORWARD (c->buffer->props.direction);
712 
713   /* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
714 
715   /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
716   if (c->font->has_glyph_h_origin_func ())
717     for (unsigned int i = 0; i < count; i++)
718       c->font->add_glyph_h_origin (info[i].codepoint,
719 				   &pos[i].x_offset,
720 				   &pos[i].y_offset);
721 
722   hb_ot_layout_position_start (c->font, c->buffer);
723 
724   switch (c->plan->shaper->zero_width_marks)
725   {
726     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
727       zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
728       break;
729 
730     default:
731     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
732     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
733       break;
734   }
735 
736   if (likely (!c->fallback_positioning))
737     c->plan->position (c->font, c->buffer);
738 
739   switch (c->plan->shaper->zero_width_marks)
740   {
741     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE:
742       zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing);
743       break;
744 
745     default:
746     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE:
747     case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY:
748       break;
749   }
750 
751   /* Finishing off GPOS has to follow a certain order. */
752   hb_ot_layout_position_finish_advances (c->font, c->buffer);
753   hb_ot_zero_width_default_ignorables (c);
754   hb_ot_layout_position_finish_offsets (c->font, c->buffer);
755 
756   /* The nil glyph_h_origin() func returns 0, so no need to apply it. */
757   if (c->font->has_glyph_h_origin_func ())
758     for (unsigned int i = 0; i < count; i++)
759       c->font->subtract_glyph_h_origin (info[i].codepoint,
760 					&pos[i].x_offset,
761 					&pos[i].y_offset);
762 }
763 
764 static inline void
hb_ot_position(hb_ot_shape_context_t * c)765 hb_ot_position (hb_ot_shape_context_t *c)
766 {
767   c->buffer->clear_positions ();
768 
769   hb_ot_position_default (c);
770 
771   hb_ot_position_complex (c);
772 
773   if (c->fallback_positioning && c->plan->shaper->fallback_position)
774     _hb_ot_shape_fallback_position (c->plan, c->font, c->buffer);
775 
776   if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction))
777     hb_buffer_reverse (c->buffer);
778 
779   /* Visual fallback goes here. */
780 
781   if (c->fallback_positioning)
782     _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
783 
784   _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
785 }
786 
787 static inline void
hb_propagate_flags(hb_buffer_t * buffer)788 hb_propagate_flags (hb_buffer_t *buffer)
789 {
790   /* Propagate cluster-level glyph flags to be the same on all cluster glyphs.
791    * Simplifies using them. */
792 
793   if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK))
794     return;
795 
796   hb_glyph_info_t *info = buffer->info;
797 
798   foreach_cluster (buffer, start, end)
799   {
800     unsigned int mask = 0;
801     for (unsigned int i = start; i < end; i++)
802       if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK)
803       {
804 	 mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK;
805 	 break;
806       }
807     if (mask)
808       for (unsigned int i = start; i < end; i++)
809 	info[i].mask |= mask;
810   }
811 }
812 
813 /* Pull it all together! */
814 
815 static void
hb_ot_shape_internal(hb_ot_shape_context_t * c)816 hb_ot_shape_internal (hb_ot_shape_context_t *c)
817 {
818   c->buffer->deallocate_var_all ();
819   c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT;
820   if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR)))
821   {
822     c->buffer->max_len = MAX (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR,
823 			      (unsigned) HB_BUFFER_MAX_LEN_MIN);
824   }
825   if (likely (!_hb_unsigned_int_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR)))
826   {
827     c->buffer->max_ops = MAX (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR,
828 			      (unsigned) HB_BUFFER_MAX_OPS_MIN);
829   }
830 
831   bool disable_otl = c->plan->shaper->disable_otl && c->plan->shaper->disable_otl (c->plan);
832   //c->fallback_substitute     = disable_otl || !hb_ot_layout_has_substitution (c->face);
833   c->fallback_positioning    = disable_otl || !hb_ot_layout_has_positioning (c->face);
834   c->fallback_glyph_classes  = disable_otl || !hb_ot_layout_has_glyph_classes (c->face);
835 
836   /* Save the original direction, we use it later. */
837   c->target_direction = c->buffer->props.direction;
838 
839   _hb_buffer_allocate_unicode_vars (c->buffer);
840 
841   c->buffer->clear_output ();
842 
843   hb_ot_shape_initialize_masks (c);
844   hb_set_unicode_props (c->buffer);
845   hb_insert_dotted_circle (c->buffer, c->font);
846 
847   hb_form_clusters (c->buffer);
848 
849   hb_ensure_native_direction (c->buffer);
850 
851   if (c->plan->shaper->preprocess_text)
852     c->plan->shaper->preprocess_text (c->plan, c->buffer, c->font);
853 
854   hb_ot_substitute (c);
855   hb_ot_position (c);
856 
857   hb_ot_hide_default_ignorables (c);
858 
859   if (c->plan->shaper->postprocess_glyphs)
860     c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font);
861 
862   hb_propagate_flags (c->buffer);
863 
864   _hb_buffer_deallocate_unicode_vars (c->buffer);
865 
866   c->buffer->props.direction = c->target_direction;
867 
868   c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT;
869   c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT;
870   c->buffer->deallocate_var_all ();
871 }
872 
873 
874 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)875 _hb_ot_shape (hb_shape_plan_t    *shape_plan,
876 	      hb_font_t          *font,
877 	      hb_buffer_t        *buffer,
878 	      const hb_feature_t *features,
879 	      unsigned int        num_features)
880 {
881   hb_ot_shape_context_t c = {HB_SHAPER_DATA_GET (shape_plan), font, font->face, buffer, features, num_features};
882   hb_ot_shape_internal (&c);
883 
884   return true;
885 }
886 
887 
888 /**
889  * hb_ot_shape_plan_collect_lookups:
890  *
891  * Since: 0.9.7
892  **/
893 void
hb_ot_shape_plan_collect_lookups(hb_shape_plan_t * shape_plan,hb_tag_t table_tag,hb_set_t * lookup_indexes)894 hb_ot_shape_plan_collect_lookups (hb_shape_plan_t *shape_plan,
895 				  hb_tag_t         table_tag,
896 				  hb_set_t        *lookup_indexes /* OUT */)
897 {
898   /* XXX Does the first part always succeed? */
899   HB_SHAPER_DATA_GET (shape_plan)->collect_lookups (table_tag, lookup_indexes);
900 }
901 
902 
903 /* TODO Move this to hb-ot-shape-normalize, make it do decompose, and make it public. */
904 static void
add_char(hb_font_t * font,hb_unicode_funcs_t * unicode,hb_bool_t mirror,hb_codepoint_t u,hb_set_t * glyphs)905 add_char (hb_font_t          *font,
906 	  hb_unicode_funcs_t *unicode,
907 	  hb_bool_t           mirror,
908 	  hb_codepoint_t      u,
909 	  hb_set_t           *glyphs)
910 {
911   hb_codepoint_t glyph;
912   if (font->get_nominal_glyph (u, &glyph))
913     glyphs->add (glyph);
914   if (mirror)
915   {
916     hb_codepoint_t m = unicode->mirroring (u);
917     if (m != u && font->get_nominal_glyph (m, &glyph))
918       glyphs->add (glyph);
919   }
920 }
921 
922 
923 /**
924  * hb_ot_shape_glyphs_closure:
925  *
926  * Since: 0.9.2
927  **/
928 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)929 hb_ot_shape_glyphs_closure (hb_font_t          *font,
930 			    hb_buffer_t        *buffer,
931 			    const hb_feature_t *features,
932 			    unsigned int        num_features,
933 			    hb_set_t           *glyphs)
934 {
935   hb_ot_shape_plan_t plan;
936 
937   const char *shapers[] = {"ot", nullptr};
938   hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props,
939 							     features, num_features, shapers);
940 
941   bool mirror = hb_script_get_horizontal_direction (buffer->props.script) == HB_DIRECTION_RTL;
942 
943   unsigned int count = buffer->len;
944   hb_glyph_info_t *info = buffer->info;
945   for (unsigned int i = 0; i < count; i++)
946     add_char (font, buffer->unicode, mirror, info[i].codepoint, glyphs);
947 
948   hb_set_t *lookups = hb_set_create ();
949   hb_ot_shape_plan_collect_lookups (shape_plan, HB_OT_TAG_GSUB, lookups);
950 
951   /* And find transitive closure. */
952   hb_set_t *copy = hb_set_create ();
953   do {
954     copy->set (glyphs);
955     for (hb_codepoint_t lookup_index = -1; hb_set_next (lookups, &lookup_index);)
956       hb_ot_layout_lookup_substitute_closure (font->face, lookup_index, glyphs);
957   } while (!copy->is_equal (glyphs));
958   hb_set_destroy (copy);
959 
960   hb_set_destroy (lookups);
961 
962   hb_shape_plan_destroy (shape_plan);
963 }
964