diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2020-10-18 03:24:25 +0300 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2020-10-19 20:36:18 +0300 |
commit | 80ce6378d572c230923bfc239f679e8604b8448a (patch) | |
tree | f4a70acac0f4abe6d8c22d31c0b050db11455b54 | |
parent | afd6dacd232810dc83f7eacebb251538f7d4148e (diff) | |
download | libass-80ce6378d572c230923bfc239f679e8604b8448a.tar.bz2 libass-80ce6378d572c230923bfc239f679e8604b8448a.tar.xz |
shaper: don't mingle run ID and bidi embedding level
A libass-chosen shaping run boundary can coincide with a bidi embedding level
boundary such that the differences in shaper_run_id and emblevel cancel out.
For example:
English עבריתEnglish again (with parentheses)
(with no space after the Hebrew)
has ass_shaper_find_runs split runs after the Hebrew, adding 1 to shape_run_id,
while the RTL embed also ends in the same place, removing 1 from emblevel.
As a result, two shape runs that should be separate merge together.
In this example, this leads to HarfBuzz thinking that "English again (with
parentheses)" is still right-to-left, so it flips the parenthesis glyphs.
To avoid this, don't attempt to add these numbers together. Just require
explicitly that both numbers stay constant, rather than their sum.
-rw-r--r-- | libass/ass_shaper.c | 15 |
1 files changed, 6 insertions, 9 deletions
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c index 2de12d5..4e93d2b 100644 --- a/libass/ass_shaper.c +++ b/libass/ass_shaper.c @@ -639,18 +639,20 @@ static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) for (i = 0; i < len; i++) { int offset = i; hb_font_t *font = get_hb_font(shaper, glyphs + offset); - int level = glyphs[offset].shape_run_id; - int direction = FRIBIDI_LEVEL_IS_RTL(shaper->emblevels[offset]); + int run_id = glyphs[offset].shape_run_id; + int level = shaper->emblevels[offset]; // advance in text until end of run - while (i < (len - 1) && level == glyphs[i+1].shape_run_id) + while (i < (len - 1) && run_id == glyphs[i + 1].shape_run_id && + level == shaper->emblevels[i + 1]) i++; hb_buffer_pre_allocate(buf, i - offset + 1); hb_buffer_add_utf32(buf, shaper->event_text + offset, i - offset + 1, 0, i - offset + 1); - props.direction = direction ? HB_DIRECTION_RTL : HB_DIRECTION_LTR; + props.direction = FRIBIDI_LEVEL_IS_RTL(level) ? + HB_DIRECTION_RTL : HB_DIRECTION_LTR; props.script = glyphs[offset].script; props.language = hb_shaper_get_run_language(shaper, props.script); hb_buffer_set_segment_properties(buf, &props); @@ -910,11 +912,6 @@ int ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info) } } - // add embedding levels to shape runs for final runs - for (i = 0; i < text_info->length; i++) { - glyphs[i].shape_run_id += shaper->emblevels[i]; - } - #ifdef CONFIG_HARFBUZZ switch (shaper->shaping_level) { case ASS_SHAPING_SIMPLE: |