summaryrefslogtreecommitdiffstats
path: root/libass/ass_shaper.c
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2020-10-25 05:31:56 +0200
committerOleg Oshmyan <chortos@inbox.lv>2022-02-14 20:43:08 +0200
commitc275f0e18037155c9df24e423e1fab0417d0ef21 (patch)
tree15fa95e9e4d19a9b05807459fd7978a347d18a6c /libass/ass_shaper.c
parentc629be7d70548aea282ea4890c51094055ec66e2 (diff)
downloadlibass-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.c33
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);
}