summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2020-10-18 03:24:25 +0300
committerOleg Oshmyan <chortos@inbox.lv>2020-10-19 20:36:18 +0300
commit80ce6378d572c230923bfc239f679e8604b8448a (patch)
treef4a70acac0f4abe6d8c22d31c0b050db11455b54
parentafd6dacd232810dc83f7eacebb251538f7d4148e (diff)
downloadlibass-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.c15
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: