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