src/java.desktop/share/native/libfontmanager/harfbuzz/hb-ot-shape-complex-use.cc
changeset 54232 7c11a7cc7c1d
parent 50826 f5b95be8b6e2
equal deleted inserted replaced
54231:e4813eded7cb 54232:7c11a7cc7c1d
    24  *
    24  *
    25  * Mozilla Author(s): Jonathan Kew
    25  * Mozilla Author(s): Jonathan Kew
    26  * Google Author(s): Behdad Esfahbod
    26  * Google Author(s): Behdad Esfahbod
    27  */
    27  */
    28 
    28 
    29 #include "hb-ot-shape-complex-use-private.hh"
    29 #include "hb-ot-shape-complex-use.hh"
    30 #include "hb-ot-shape-complex-arabic-private.hh"
    30 #include "hb-ot-shape-complex-arabic.hh"
       
    31 #include "hb-ot-shape-complex-vowel-constraints.hh"
    31 
    32 
    32 /* buffer var allocations */
    33 /* buffer var allocations */
    33 #define use_category() complex_var_u8_0()
    34 #define use_category() complex_var_u8_0()
    34 
    35 
    35 
    36 
    77 static const hb_tag_t
    78 static const hb_tag_t
    78 other_features[] =
    79 other_features[] =
    79 {
    80 {
    80   /*
    81   /*
    81    * Other features.
    82    * Other features.
    82    * These features are applied all at once, after reordering.
    83    * These features are applied all at once, after reordering and
       
    84    * clearing syllables.
    83    */
    85    */
    84   HB_TAG('a','b','v','s'),
    86   HB_TAG('a','b','v','s'),
    85   HB_TAG('b','l','w','s'),
    87   HB_TAG('b','l','w','s'),
    86   HB_TAG('h','a','l','n'),
    88   HB_TAG('h','a','l','n'),
    87   HB_TAG('p','r','e','s'),
    89   HB_TAG('p','r','e','s'),
    88   HB_TAG('p','s','t','s'),
    90   HB_TAG('p','s','t','s'),
    89   /* Positioning features, though we don't care about the types. */
    91 };
       
    92 static const hb_tag_t
       
    93 positioning_features[] =
       
    94 {
       
    95   /*
       
    96    * Positioning features.
       
    97    * We don't care about the types.
       
    98    */
    90   HB_TAG('d','i','s','t'),
    99   HB_TAG('d','i','s','t'),
    91   HB_TAG('a','b','v','m'),
   100   HB_TAG('a','b','v','m'),
    92   HB_TAG('b','l','w','m'),
   101   HB_TAG('b','l','w','m'),
    93 };
   102 };
    94 
   103 
   110              hb_buffer_t *buffer);
   119              hb_buffer_t *buffer);
   111 static void
   120 static void
   112 reorder (const hb_ot_shape_plan_t *plan,
   121 reorder (const hb_ot_shape_plan_t *plan,
   113          hb_font_t *font,
   122          hb_font_t *font,
   114          hb_buffer_t *buffer);
   123          hb_buffer_t *buffer);
       
   124 static void
       
   125 clear_syllables (const hb_ot_shape_plan_t *plan,
       
   126                  hb_font_t *font,
       
   127                  hb_buffer_t *buffer);
   115 
   128 
   116 static void
   129 static void
   117 collect_features_use (hb_ot_shape_planner_t *plan)
   130 collect_features_use (hb_ot_shape_planner_t *plan)
   118 {
   131 {
   119   hb_ot_map_builder_t *map = &plan->map;
   132   hb_ot_map_builder_t *map = &plan->map;
   120 
   133 
   121   /* Do this before any lookups have been applied. */
   134   /* Do this before any lookups have been applied. */
   122   map->add_gsub_pause (setup_syllables);
   135   map->add_gsub_pause (setup_syllables);
   123 
   136 
   124   /* "Default glyph pre-processing group" */
   137   /* "Default glyph pre-processing group" */
   125   map->add_global_bool_feature (HB_TAG('l','o','c','l'));
   138   map->enable_feature (HB_TAG('l','o','c','l'));
   126   map->add_global_bool_feature (HB_TAG('c','c','m','p'));
   139   map->enable_feature (HB_TAG('c','c','m','p'));
   127   map->add_global_bool_feature (HB_TAG('n','u','k','t'));
   140   map->enable_feature (HB_TAG('n','u','k','t'));
   128   map->add_global_bool_feature (HB_TAG('a','k','h','n'));
   141   map->enable_feature (HB_TAG('a','k','h','n'), F_MANUAL_ZWJ);
   129 
   142 
   130   /* "Reordering group" */
   143   /* "Reordering group" */
   131   map->add_gsub_pause (clear_substitution_flags);
   144   map->add_gsub_pause (clear_substitution_flags);
   132   map->add_feature (HB_TAG('r','p','h','f'), 1, F_MANUAL_ZWJ);
   145   map->add_feature (HB_TAG('r','p','h','f'), F_MANUAL_ZWJ);
   133   map->add_gsub_pause (record_rphf);
   146   map->add_gsub_pause (record_rphf);
   134   map->add_gsub_pause (clear_substitution_flags);
   147   map->add_gsub_pause (clear_substitution_flags);
   135   map->add_feature (HB_TAG('p','r','e','f'), 1, F_GLOBAL | F_MANUAL_ZWJ);
   148   map->enable_feature (HB_TAG('p','r','e','f'), F_MANUAL_ZWJ);
   136   map->add_gsub_pause (record_pref);
   149   map->add_gsub_pause (record_pref);
   137 
   150 
   138   /* "Orthographic unit shaping group" */
   151   /* "Orthographic unit shaping group" */
   139   for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
   152   for (unsigned int i = 0; i < ARRAY_LENGTH (basic_features); i++)
   140     map->add_feature (basic_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
   153     map->enable_feature (basic_features[i], F_MANUAL_ZWJ);
   141 
   154 
   142   map->add_gsub_pause (reorder);
   155   map->add_gsub_pause (reorder);
       
   156   map->add_gsub_pause (clear_syllables);
   143 
   157 
   144   /* "Topographical features" */
   158   /* "Topographical features" */
   145   for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
   159   for (unsigned int i = 0; i < ARRAY_LENGTH (arabic_features); i++)
   146     map->add_feature (arabic_features[i], 1, F_NONE);
   160     map->add_feature (arabic_features[i]);
   147   map->add_gsub_pause (nullptr);
   161   map->add_gsub_pause (nullptr);
   148 
   162 
   149   /* "Standard typographic presentation" and "Positional feature application" */
   163   /* "Standard typographic presentation" */
   150   for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
   164   for (unsigned int i = 0; i < ARRAY_LENGTH (other_features); i++)
   151     map->add_feature (other_features[i], 1, F_GLOBAL | F_MANUAL_ZWJ);
   165     map->enable_feature (other_features[i], F_MANUAL_ZWJ);
       
   166 
       
   167   /* "Positional feature application" */
       
   168   for (unsigned int i = 0; i < ARRAY_LENGTH (positioning_features); i++)
       
   169     map->enable_feature (positioning_features[i]);
   152 }
   170 }
   153 
   171 
   154 struct use_shape_plan_t
   172 struct use_shape_plan_t
   155 {
   173 {
   156   ASSERT_POD ();
       
   157 
       
   158   hb_mask_t rphf_mask;
   174   hb_mask_t rphf_mask;
   159 
   175 
   160   arabic_shape_plan_t *arabic_plan;
   176   arabic_shape_plan_t *arabic_plan;
   161 };
   177 };
   162 
   178 
   359   setup_rphf_mask (plan, buffer);
   375   setup_rphf_mask (plan, buffer);
   360   setup_topographical_masks (plan, buffer);
   376   setup_topographical_masks (plan, buffer);
   361 }
   377 }
   362 
   378 
   363 static void
   379 static void
   364 clear_substitution_flags (const hb_ot_shape_plan_t *plan,
   380 clear_substitution_flags (const hb_ot_shape_plan_t *plan HB_UNUSED,
   365                           hb_font_t *font HB_UNUSED,
   381                           hb_font_t *font HB_UNUSED,
   366                           hb_buffer_t *buffer)
   382                           hb_buffer_t *buffer)
   367 {
   383 {
   368   hb_glyph_info_t *info = buffer->info;
   384   hb_glyph_info_t *info = buffer->info;
   369   unsigned int count = buffer->len;
   385   unsigned int count = buffer->len;
   371     _hb_glyph_info_clear_substituted (&info[i]);
   387     _hb_glyph_info_clear_substituted (&info[i]);
   372 }
   388 }
   373 
   389 
   374 static void
   390 static void
   375 record_rphf (const hb_ot_shape_plan_t *plan,
   391 record_rphf (const hb_ot_shape_plan_t *plan,
   376              hb_font_t *font,
   392              hb_font_t *font HB_UNUSED,
   377              hb_buffer_t *buffer)
   393              hb_buffer_t *buffer)
   378 {
   394 {
   379   const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
   395   const use_shape_plan_t *use_plan = (const use_shape_plan_t *) plan->data;
   380 
   396 
   381   hb_mask_t mask = use_plan->rphf_mask;
   397   hb_mask_t mask = use_plan->rphf_mask;
   393       }
   409       }
   394   }
   410   }
   395 }
   411 }
   396 
   412 
   397 static void
   413 static void
   398 record_pref (const hb_ot_shape_plan_t *plan,
   414 record_pref (const hb_ot_shape_plan_t *plan HB_UNUSED,
   399              hb_font_t *font,
   415              hb_font_t *font HB_UNUSED,
   400              hb_buffer_t *buffer)
   416              hb_buffer_t *buffer)
   401 {
   417 {
   402   hb_glyph_info_t *info = buffer->info;
   418   hb_glyph_info_t *info = buffer->info;
   403 
   419 
   404   foreach_syllable (buffer, start, end)
   420   foreach_syllable (buffer, start, end)
   414 }
   430 }
   415 
   431 
   416 static inline bool
   432 static inline bool
   417 is_halant (const hb_glyph_info_t &info)
   433 is_halant (const hb_glyph_info_t &info)
   418 {
   434 {
   419   return info.use_category() == USE_H && !_hb_glyph_info_ligated (&info);
   435   return (info.use_category() == USE_H || info.use_category() == USE_HVM) &&
       
   436          !_hb_glyph_info_ligated (&info);
   420 }
   437 }
   421 
   438 
   422 static void
   439 static void
   423 reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
   440 reorder_syllable (hb_buffer_t *buffer, unsigned int start, unsigned int end)
   424 {
   441 {
   431                    0))))
   448                    0))))
   432     return;
   449     return;
   433 
   450 
   434   hb_glyph_info_t *info = buffer->info;
   451   hb_glyph_info_t *info = buffer->info;
   435 
   452 
   436 #define BASE_FLAGS (FLAG (USE_B) | FLAG (USE_GB))
   453 #define POST_BASE_FLAGS64 (FLAG64 (USE_FM) | \
       
   454                            FLAG64 (USE_FAbv) | \
       
   455                            FLAG64 (USE_FBlw) | \
       
   456                            FLAG64 (USE_FPst) | \
       
   457                            FLAG64 (USE_MAbv) | \
       
   458                            FLAG64 (USE_MBlw) | \
       
   459                            FLAG64 (USE_MPst) | \
       
   460                            FLAG64 (USE_MPre) | \
       
   461                            FLAG64 (USE_VAbv) | \
       
   462                            FLAG64 (USE_VBlw) | \
       
   463                            FLAG64 (USE_VPst) | \
       
   464                            FLAG64 (USE_VPre) | \
       
   465                            FLAG64 (USE_VMAbv) | \
       
   466                            FLAG64 (USE_VMBlw) | \
       
   467                            FLAG64 (USE_VMPst) | \
       
   468                            FLAG64 (USE_VMPre))
   437 
   469 
   438   /* Move things forward. */
   470   /* Move things forward. */
   439   if (info[start].use_category() == USE_R && end - start > 1)
   471   if (info[start].use_category() == USE_R && end - start > 1)
   440   {
   472   {
   441     /* Got a repha.  Reorder it to after first base, before first halant. */
   473     /* Got a repha.  Reorder it towards the end, but before the first post-base
       
   474      * glyph. */
   442     for (unsigned int i = start + 1; i < end; i++)
   475     for (unsigned int i = start + 1; i < end; i++)
   443       if ((FLAG_UNSAFE (info[i].use_category()) & (BASE_FLAGS)) || is_halant (info[i]))
   476     {
       
   477       bool is_post_base_glyph = (FLAG64_UNSAFE (info[i].use_category()) & POST_BASE_FLAGS64) ||
       
   478                                 is_halant (info[i]);
       
   479       if (is_post_base_glyph || i == end - 1)
   444       {
   480       {
   445         /* If we hit a halant, move before it; otherwise it's a base: move to it's
   481         /* If we hit a post-base glyph, move before it; otherwise move to the
   446          * place, and shift things in between backward. */
   482          * end. Shift things in between backward. */
   447 
   483 
   448         if (is_halant (info[i]))
   484         if (is_post_base_glyph)
   449           i--;
   485           i--;
   450 
   486 
   451         buffer->merge_clusters (start, i + 1);
   487         buffer->merge_clusters (start, i + 1);
   452         hb_glyph_info_t t = info[start];
   488         hb_glyph_info_t t = info[start];
   453         memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0]));
   489         memmove (&info[start], &info[start + 1], (i - start) * sizeof (info[0]));
   454         info[i] = t;
   490         info[i] = t;
   455 
   491 
   456         break;
   492         break;
   457       }
   493       }
       
   494     }
   458   }
   495   }
   459 
   496 
   460   /* Move things back. */
   497   /* Move things back. */
   461   unsigned int j = end;
   498   unsigned int j = start;
   462   for (unsigned int i = start; i < end; i++)
   499   for (unsigned int i = start; i < end; i++)
   463   {
   500   {
   464     uint32_t flag = FLAG_UNSAFE (info[i].use_category());
   501     uint32_t flag = FLAG_UNSAFE (info[i].use_category());
   465     if ((flag & (BASE_FLAGS)) || is_halant (info[i]))
   502     if (is_halant (info[i]))
   466     {
   503     {
   467       /* If we hit a halant, move after it; otherwise it's a base: move to it's
   504       /* If we hit a halant, move after it; otherwise move to the beginning, and
   468        * place, and shift things in between backward. */
   505        * shift things in between forward. */
   469       if (is_halant (info[i]))
   506       j = i + 1;
   470         j = i + 1;
       
   471       else
       
   472         j = i;
       
   473     }
   507     }
   474     else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
   508     else if (((flag) & (FLAG (USE_VPre) | FLAG (USE_VMPre))) &&
   475              /* Only move the first component of a MultipleSubst. */
   509              /* Only move the first component of a MultipleSubst. */
   476              0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
   510              0 == _hb_glyph_info_get_lig_comp (&info[i]) &&
   477              j < i)
   511              j < i)
   534       buffer->output_info (ginfo);
   568       buffer->output_info (ginfo);
   535     }
   569     }
   536     else
   570     else
   537       buffer->next_glyph ();
   571       buffer->next_glyph ();
   538   }
   572   }
   539 
       
   540   buffer->swap_buffers ();
   573   buffer->swap_buffers ();
   541 }
   574 }
   542 
   575 
   543 static void
   576 static void
   544 reorder (const hb_ot_shape_plan_t *plan,
   577 reorder (const hb_ot_shape_plan_t *plan,
   545          hb_font_t *font,
   578          hb_font_t *font,
   546          hb_buffer_t *buffer)
   579          hb_buffer_t *buffer)
   547 {
   580 {
   548   insert_dotted_circles (plan, font, buffer);
   581   insert_dotted_circles (plan, font, buffer);
   549 
   582 
   550   hb_glyph_info_t *info = buffer->info;
       
   551 
       
   552   foreach_syllable (buffer, start, end)
   583   foreach_syllable (buffer, start, end)
   553     reorder_syllable (buffer, start, end);
   584     reorder_syllable (buffer, start, end);
   554 
   585 
   555   /* Zero syllables now... */
   586   HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
       
   587 }
       
   588 
       
   589 static void
       
   590 clear_syllables (const hb_ot_shape_plan_t *plan HB_UNUSED,
       
   591                  hb_font_t *font HB_UNUSED,
       
   592                  hb_buffer_t *buffer)
       
   593 {
       
   594   hb_glyph_info_t *info = buffer->info;
   556   unsigned int count = buffer->len;
   595   unsigned int count = buffer->len;
   557   for (unsigned int i = 0; i < count; i++)
   596   for (unsigned int i = 0; i < count; i++)
   558     info[i].syllable() = 0;
   597     info[i].syllable() = 0;
   559 
   598 }
   560   HB_BUFFER_DEALLOCATE_VAR (buffer, use_category);
   599 
   561 }
   600 
   562 
   601 static void
   563 static bool
   602 preprocess_text_use (const hb_ot_shape_plan_t *plan,
   564 decompose_use (const hb_ot_shape_normalize_context_t *c,
   603                      hb_buffer_t              *buffer,
   565                 hb_codepoint_t  ab,
   604                      hb_font_t                *font)
   566                 hb_codepoint_t *a,
   605 {
   567                 hb_codepoint_t *b)
   606   _hb_preprocess_text_vowel_constraints (plan, buffer, font);
   568 {
       
   569   switch (ab)
       
   570   {
       
   571     /* Chakma:
       
   572      * Special case where the Unicode decomp gives matras in the wrong order
       
   573      * for cluster validation.
       
   574      */
       
   575     case 0x1112Eu : *a = 0x11127u; *b= 0x11131u; return true;
       
   576     case 0x1112Fu : *a = 0x11127u; *b= 0x11132u; return true;
       
   577   }
       
   578 
       
   579   return (bool) c->unicode->decompose (ab, a, b);
       
   580 }
   607 }
   581 
   608 
   582 static bool
   609 static bool
   583 compose_use (const hb_ot_shape_normalize_context_t *c,
   610 compose_use (const hb_ot_shape_normalize_context_t *c,
   584              hb_codepoint_t  a,
   611              hb_codepoint_t  a,
   597 {
   624 {
   598   collect_features_use,
   625   collect_features_use,
   599   nullptr, /* override_features */
   626   nullptr, /* override_features */
   600   data_create_use,
   627   data_create_use,
   601   data_destroy_use,
   628   data_destroy_use,
   602   nullptr, /* preprocess_text */
   629   preprocess_text_use,
   603   nullptr, /* postprocess_glyphs */
   630   nullptr, /* postprocess_glyphs */
   604   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   631   HB_OT_SHAPE_NORMALIZATION_MODE_COMPOSED_DIACRITICS_NO_SHORT_CIRCUIT,
   605   decompose_use,
   632   nullptr, /* decompose */
   606   compose_use,
   633   compose_use,
   607   setup_masks_use,
   634   setup_masks_use,
   608   nullptr, /* disable_otl */
   635   HB_TAG_NONE, /* gpos_tag */
   609   nullptr, /* reorder_marks */
   636   nullptr, /* reorder_marks */
   610   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   637   HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY,
   611   false, /* fallback_position */
   638   false, /* fallback_position */
   612 };
   639 };