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