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