diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2020-10-25 05:31:56 +0200 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2022-02-14 20:43:08 +0200 |
commit | c275f0e18037155c9df24e423e1fab0417d0ef21 (patch) | |
tree | 15fa95e9e4d19a9b05807459fd7978a347d18a6c /libass/ass_shaper.c | |
parent | c629be7d70548aea282ea4890c51094055ec66e2 (diff) | |
download | libass-c275f0e18037155c9df24e423e1fab0417d0ef21.tar.bz2 libass-c275f0e18037155c9df24e423e1fab0417d0ef21.tar.xz |
WHOLE_TEXT_LAYOUT: give HarfBuzz context to shape correctly across runs
When WHOLE_TEXT_LAYOUT is disabled, keep calling HarfBuzz with no context at
all. It might seem sensible to give it the whole VSFilter-run as context so
it could shape Arabic correctly across font fallback in case of weird fonts,
but it seems that Uniscribe doesn't behave like this in VSFilter.
For testing that, I created a font with only two glyphs: an isolated ain
and a medial ain; and a GSUB medi lookup that links them together.
Setting \fnMyTestFont on an Arabic word with a medial ain, libass
with WHOLE_TEXT_LAYOUT (i. e. HarfBuzz with context) showed the medial
shape, but VSFilter (i. e. Uniscribe) showed the isolated shape.
BorderStyle 3 confirmed that VSFilter was treating the string
as a single run and therefore passing it to GDI/Uniscribe as a whole.
Diffstat (limited to 'libass/ass_shaper.c')
-rw-r--r-- | libass/ass_shaper.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c index b05a051..0c97ccc 100644 --- a/libass/ass_shaper.c +++ b/libass/ass_shaper.c @@ -703,19 +703,25 @@ static bool shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) level == shaper->emblevels[i + 1]) i++; - int lead_context = 0, trail_context = 0; - if (offset > 0 && !glyphs[offset].starts_new_run && - is_shaping_control(glyphs[offset - 1].symbol)) - lead_context = 1; - if (i < (len - 1) && !glyphs[i + 1].starts_new_run && - is_shaping_control(glyphs[i + 1].symbol)) - trail_context = 1; - hb_buffer_pre_allocate(buf, i - offset + 1); - hb_buffer_add_utf32(buf, - shaper->event_text + offset - lead_context, - i - offset + 1 + lead_context + trail_context, - lead_context, i - offset + 1); + + int lead_context = 0, trail_context = 0; + if (shaper->whole_text_layout) { + hb_buffer_add_utf32(buf, shaper->event_text, len, + offset, i - offset + 1); + } else { + if (offset > 0 && !glyphs[offset].starts_new_run && + is_shaping_control(glyphs[offset - 1].symbol)) + lead_context = 1; + if (i < (len - 1) && !glyphs[i + 1].starts_new_run && + is_shaping_control(glyphs[i + 1].symbol)) + trail_context = 1; + + hb_buffer_add_utf32(buf, + shaper->event_text + offset - lead_context, + i - offset + 1 + lead_context + trail_context, + lead_context, i - offset + 1); + } props.direction = FRIBIDI_LEVEL_IS_RTL(level) ? HB_DIRECTION_RTL : HB_DIRECTION_LTR; @@ -726,7 +732,8 @@ static bool shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len) set_run_features(shaper, glyphs + offset); hb_shape(font, buf, shaper->features, shaper->n_features); - shape_harfbuzz_process_run(glyphs, buf, offset - lead_context); + shape_harfbuzz_process_run(glyphs, buf, + shaper->whole_text_layout ? 0 : offset - lead_context); hb_buffer_reset(buf); } |