diff options
Diffstat (limited to 'src/hb-ot-shape.cc')
-rw-r--r-- | src/hb-ot-shape.cc | 151 |
1 files changed, 84 insertions, 67 deletions
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 4e8a4bc3d..bbdfc214a 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -37,7 +37,7 @@ #include "hb-shaper-impl.hh" #include "hb-ot-shape.hh" -#include "hb-ot-shape-complex.hh" +#include "hb-ot-shaper.hh" #include "hb-ot-shape-fallback.hh" #include "hb-ot-shape-normalize.hh" @@ -47,14 +47,17 @@ #include "hb-aat-layout.hh" +static inline bool +_hb_codepoint_is_regional_indicator (hb_codepoint_t u) +{ return hb_in_range<hb_codepoint_t> (u, 0x1F1E6u, 0x1F1FFu); } #ifndef HB_NO_AAT_SHAPE static inline bool -_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t *props) +_hb_apply_morx (hb_face_t *face, const hb_segment_properties_t &props) { /* https://github.com/harfbuzz/harfbuzz/issues/2124 */ return hb_aat_layout_has_substitution (face) && - (HB_DIRECTION_IS_HORIZONTAL (props->direction) || !hb_ot_layout_has_substitution (face)); + (HB_DIRECTION_IS_HORIZONTAL (props.direction) || !hb_ot_layout_has_substitution (face)); } #endif @@ -74,23 +77,25 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, unsigned int num_user_features); hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face, - const hb_segment_properties_t *props) : + const hb_segment_properties_t &props) : face (face), - props (*props), + props (props), map (face, props), aat_map (face, props) #ifndef HB_NO_AAT_SHAPE , apply_morx (_hb_apply_morx (face, props)) #endif { - shaper = hb_ot_shape_complex_categorize (this); + shaper = hb_ot_shaper_categorize (this); script_zero_marks = shaper->zero_width_marks != HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE; script_fallback_mark_positioning = shaper->fallback_position; +#ifndef HB_NO_AAT_SHAPE /* https://github.com/harfbuzz/harfbuzz/issues/1528 */ - if (apply_morx && shaper != &_hb_ot_complex_shaper_default) - shaper = &_hb_ot_complex_shaper_dumber; + if (apply_morx && shaper != &_hb_ot_shaper_default) + shaper = &_hb_ot_shaper_dumber; +#endif } void @@ -222,7 +227,7 @@ hb_ot_shape_plan_t::init0 (hb_face_t *face, #endif hb_ot_shape_planner_t planner (face, - &key->props); + key->props); hb_ot_shape_collect_features (&planner, key->user_features, @@ -504,9 +509,9 @@ hb_set_unicode_props (hb_buffer_t *buffer) } /* Regional_Indicators are hairy as hell... * https://github.com/harfbuzz/harfbuzz/issues/2265 */ - else if (unlikely (i && hb_in_range<hb_codepoint_t> (info[i].codepoint, 0x1F1E6u, 0x1F1FFu))) + else if (unlikely (i && _hb_codepoint_is_regional_indicator (info[i].codepoint))) { - if (hb_in_range<hb_codepoint_t> (info[i - 1].codepoint, 0x1F1E6u, 0x1F1FFu) && + if (_hb_codepoint_is_regional_indicator (info[i - 1].codepoint) && !_hb_glyph_info_is_continuation (&info[i - 1])) _hb_glyph_info_set_continuation (&info[i]); } @@ -524,18 +529,20 @@ hb_set_unicode_props (hb_buffer_t *buffer) } #endif /* Or part of the Other_Grapheme_Extend that is not marks. - * As of Unicode 11 that is just: + * As of Unicode 15 that is just: * * 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER * FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK * E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG * * ZWNJ is special, we don't want to merge it as there's no need, and keeping - * it separate results in more granular clusters. Ignore Katakana for now. + * it separate results in more granular clusters. * Tags are used for Emoji sub-region flag sequences: * https://github.com/harfbuzz/harfbuzz/issues/1556 + * Katakana ones were requested: + * https://github.com/harfbuzz/harfbuzz/issues/3844 */ - else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu))) + else if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0xFF9Eu, 0xFF9Fu, 0xE0020u, 0xE007Fu))) _hb_glyph_info_set_continuation (&info[i]); } } @@ -566,7 +573,7 @@ hb_insert_dotted_circle (hb_buffer_t *buffer, hb_font_t *font) info.mask = buffer->cur().mask; (void) buffer->output_info (info); - buffer->swap_buffers (); + buffer->sync (); } static void @@ -598,24 +605,33 @@ hb_ensure_native_direction (hb_buffer_t *buffer) * direction, so that features like ligatures will work as intended. * * https://github.com/harfbuzz/harfbuzz/issues/501 + * + * Similar thing about Regional_Indicators; They are bidi=L, but Script=Common. + * If they are present in a run of natively-RTL text, they get assigned a script + * with natively RTL direction, which would result in wrong shaping if we + * assign such native RTL direction to them then. Detect that as well. + * + * https://github.com/harfbuzz/harfbuzz/issues/3314 */ if (unlikely (horiz_dir == HB_DIRECTION_RTL && direction == HB_DIRECTION_LTR)) { - bool found_number = false, found_letter = false; + bool found_number = false, found_letter = false, found_ri = false; const auto* info = buffer->info; const auto count = buffer->len; for (unsigned i = 0; i < count; i++) { auto gc = _hb_glyph_info_get_general_category (&info[i]); if (gc == HB_UNICODE_GENERAL_CATEGORY_DECIMAL_NUMBER) - found_number = true; + found_number = true; else if (HB_UNICODE_GENERAL_CATEGORY_IS_LETTER (gc)) { - found_letter = true; - break; + found_letter = true; + break; } + else if (_hb_codepoint_is_regional_indicator (info[i].codepoint)) + found_ri = true; } - if (found_number && !found_letter) + if ((found_number || found_ri) && !found_letter) horiz_dir = HB_DIRECTION_LTR; } @@ -628,20 +644,7 @@ hb_ensure_native_direction (hb_buffer_t *buffer) (HB_DIRECTION_IS_VERTICAL (direction) && direction != HB_DIRECTION_TTB)) { - - if (buffer->cluster_level == HB_BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS) - foreach_grapheme (buffer, start, end) - { - buffer->merge_clusters (start, end); - buffer->reverse_range (start, end); - } - else - foreach_grapheme (buffer, start, end) - /* form_clusters() merged clusters already, we don't merge. */ - buffer->reverse_range (start, end); - - buffer->reverse (); - + _hb_ot_layout_reverse_graphemes (buffer); buffer->props.direction = HB_DIRECTION_REVERSE (buffer->props.direction); } } @@ -651,6 +654,7 @@ hb_ensure_native_direction (hb_buffer_t *buffer) * Substitute */ +#ifndef HB_NO_VERTICAL static hb_codepoint_t hb_vert_char_for (hb_codepoint_t u) { @@ -701,6 +705,7 @@ hb_vert_char_for (hb_codepoint_t u) return u; } +#endif static inline void hb_ot_rotate_chars (const hb_ot_shape_context_t *c) @@ -723,6 +728,7 @@ hb_ot_rotate_chars (const hb_ot_shape_context_t *c) } } +#ifndef HB_NO_VERTICAL if (HB_DIRECTION_IS_VERTICAL (c->target_direction) && !c->plan->has_vert) { for (unsigned int i = 0; i < count; i++) { @@ -731,6 +737,7 @@ hb_ot_rotate_chars (const hb_ot_shape_context_t *c) info[i].codepoint = codepoint; } } +#endif } static inline void @@ -859,7 +866,7 @@ hb_ot_hide_default_ignorables (hb_buffer_t *buffer, } } else - hb_ot_layout_delete_glyphs_inplace (buffer, _hb_glyph_info_is_default_ignorable); + buffer->delete_glyphs_inplace (_hb_glyph_info_is_default_ignorable); } @@ -924,7 +931,7 @@ hb_ot_substitute_default (const hb_ot_shape_context_t *c) } static inline void -hb_ot_substitute_complex (const hb_ot_shape_context_t *c) +hb_ot_substitute_plan (const hb_ot_shape_context_t *c) { hb_buffer_t *buffer = c->buffer; @@ -943,18 +950,24 @@ hb_ot_substitute_pre (const hb_ot_shape_context_t *c) _hb_buffer_allocate_gsubgpos_vars (c->buffer); - hb_ot_substitute_complex (c); + hb_ot_substitute_plan (c); + +#ifndef HB_NO_AAT_SHAPE + if (c->plan->apply_morx && c->plan->apply_gpos) + hb_aat_layout_remove_deleted_glyphs (c->buffer); +#endif } static inline void hb_ot_substitute_post (const hb_ot_shape_context_t *c) { - hb_ot_hide_default_ignorables (c->buffer, c->font); #ifndef HB_NO_AAT_SHAPE - if (c->plan->apply_morx) + if (c->plan->apply_morx && !c->plan->apply_gpos) hb_aat_layout_remove_deleted_glyphs (c->buffer); #endif + hb_ot_hide_default_ignorables (c->buffer, c->font); + if (c->plan->shaper->postprocess_glyphs && c->buffer->message(c->font, "start postprocess-glyphs")) { c->plan->shaper->postprocess_glyphs (c->plan, c->buffer, c->font); @@ -1030,7 +1043,7 @@ hb_ot_position_default (const hb_ot_shape_context_t *c) } static inline void -hb_ot_position_complex (const hb_ot_shape_context_t *c) +hb_ot_position_plan (const hb_ot_shape_context_t *c) { unsigned int count = c->buffer->len; hb_glyph_info_t *info = c->buffer->info; @@ -1043,7 +1056,7 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) * hanging over the next glyph after the final reordering. * * Note: If fallback positinoing happens, we don't care about - * this as it will be overriden. + * this as it will be overridden. */ bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing && HB_DIRECTION_IS_FORWARD (c->buffer->props.direction); @@ -1115,7 +1128,7 @@ hb_ot_position (const hb_ot_shape_context_t *c) hb_ot_position_default (c); - hb_ot_position_complex (c); + hb_ot_position_plan (c); if (HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction)) hb_buffer_reverse (c->buffer); @@ -1129,23 +1142,42 @@ hb_propagate_flags (hb_buffer_t *buffer) /* Propagate cluster-level glyph flags to be the same on all cluster glyphs. * Simplifies using them. */ - if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_UNSAFE_TO_BREAK)) + if (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS)) return; + /* If we are producing SAFE_TO_INSERT_TATWEEL, then do two things: + * + * - If the places that the Arabic shaper marked as SAFE_TO_INSERT_TATWEEL, + * are UNSAFE_TO_BREAK, then clear the SAFE_TO_INSERT_TATWEEL, + * - Any place that is SAFE_TO_INSERT_TATWEEL, is also now UNSAFE_TO_BREAK. + * + * We couldn't make this interaction earlier. It has to be done here. + */ + bool flip_tatweel = buffer->flags & HB_BUFFER_FLAG_PRODUCE_SAFE_TO_INSERT_TATWEEL; + + bool clear_concat = (buffer->flags & HB_BUFFER_FLAG_PRODUCE_UNSAFE_TO_CONCAT) == 0; + hb_glyph_info_t *info = buffer->info; foreach_cluster (buffer, start, end) { unsigned int mask = 0; for (unsigned int i = start; i < end; i++) - if (info[i].mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) - { - mask = HB_GLYPH_FLAG_UNSAFE_TO_BREAK; - break; - } - if (mask) - for (unsigned int i = start; i < end; i++) - info[i].mask |= mask; + mask |= info[i].mask & HB_GLYPH_FLAG_DEFINED; + + if (flip_tatweel) + { + if (mask & HB_GLYPH_FLAG_UNSAFE_TO_BREAK) + mask &= ~HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL; + if (mask & HB_GLYPH_FLAG_SAFE_TO_INSERT_TATWEEL) + mask |= HB_GLYPH_FLAG_UNSAFE_TO_BREAK | HB_GLYPH_FLAG_UNSAFE_TO_CONCAT; + } + + if (clear_concat) + mask &= ~HB_GLYPH_FLAG_UNSAFE_TO_CONCAT; + + for (unsigned int i = start; i < end; i++) + info[i].mask = mask; } } @@ -1154,19 +1186,6 @@ hb_propagate_flags (hb_buffer_t *buffer) static void hb_ot_shape_internal (hb_ot_shape_context_t *c) { - c->buffer->deallocate_var_all (); - c->buffer->scratch_flags = HB_BUFFER_SCRATCH_FLAG_DEFAULT; - if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_LEN_FACTOR))) - { - c->buffer->max_len = hb_max (c->buffer->len * HB_BUFFER_MAX_LEN_FACTOR, - (unsigned) HB_BUFFER_MAX_LEN_MIN); - } - if (likely (!hb_unsigned_mul_overflows (c->buffer->len, HB_BUFFER_MAX_OPS_FACTOR))) - { - c->buffer->max_ops = hb_max (c->buffer->len * HB_BUFFER_MAX_OPS_FACTOR, - (unsigned) HB_BUFFER_MAX_OPS_MIN); - } - /* Save the original direction, we use it later. */ c->target_direction = c->buffer->props.direction; @@ -1197,9 +1216,7 @@ hb_ot_shape_internal (hb_ot_shape_context_t *c) c->buffer->props.direction = c->target_direction; - c->buffer->max_len = HB_BUFFER_MAX_LEN_DEFAULT; - c->buffer->max_ops = HB_BUFFER_MAX_OPS_DEFAULT; - c->buffer->deallocate_var_all (); + c->buffer->leave (); } |