summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2021-09-01 17:20:51 +0300
committerOleg Oshmyan <chortos@inbox.lv>2021-09-09 02:32:49 +0300
commitd170d895941b70c5a4bb7a5f555132acb34e9013 (patch)
treee687bb4965e88c1a3029d38c6ff27651cc61b37c
parent14f1f0480ffb7af9a33e224287428161a18e7cf2 (diff)
downloadlibass-d170d895941b70c5a4bb7a5f555132acb34e9013.tar.bz2
libass-d170d895941b70c5a4bb7a5f555132acb34e9013.tar.xz
shaper: don't try to look up glyphs for invisible characters
Fonts don't need to contain any glyphs for these code points. Their special effect on layout (if any) will be handled by FriBidi and/or HarfBuzz, and they will be replaced by zero-width glyphs regardless of whether any font glyph was provided. By trying hard to find a glyph as we currently do, we end up mistakenly splitting shape runs on control characters that lack font glyphs and therefore ruining shaping, as well as logging unnecessary warnings about the missing glyphs. There are some quirks and exceptions. In particular, font glyphs for normally-invisible characters may be retained by recent HarfBuzz if OpenType substitutions are involved (which sometimes matches and sometimes doesn't match Uniscribe). This commit happens to retain this behavior for visible glyphs contained in the main font (as opposed to any arbitrarily-chosen fallback fonts) by virtue of defaulting run-leading invisibles to face_index 0, where HarfBuzz will find the glyphs on its own. Meanwhile, the case of _fallback_ fonts inserting visible glyphs doesn't even seem to be desirable to begin with. Preliminary testing shows this commit's logic matches Uniscribe in some common cases, but tests with musical symbols show strange results. More research is needed to match Uniscribe and hence VSFilter even better. On the other hand, this logic is likely not sophisticated enough for "optimal" typesetting without regard to Uniscribe compatibility. For example, Blink does not look up glyphs and split font-fallback runs prior to running HarfBuzz at all, and instead runs HarfBuzz on the whole higher-level run at once and then reruns it with the next fallback font on just those substrings that HarfBuzz failed to shape. In any case, some Default_Ignorable glyphs are more appropriately viewed as logical prefixes than suffixes and should be grouped with the following, not preceding, character in case of doubt. Furthermore, when a fallback font is used for a sequence of text, it may be desirable to use the same font for intervening or surrounding whitespace or punctuation even if the main font (or another fallback font) also contains glyphs for them; and whitespace characters can be synthesized in lieu of import from another font, and indeed HarfBuzz does synthesize them, but this is not always desirable. Additionally, the glyph HarfBuzz uses for zero-width substitutes may actually be visible as it defaults to the font's basic space glyph: if we were to forget about Uniscribe, we should define a custom, fake glyph index and translate it into `skip`. Finally, our higher-level shape run splitting is not perfect either: bidi splitting after script splitting can create awkward short runs, and in general, script splitting seems problematic in itself. Fixes https://github.com/libass/libass/issues/507 (log messages). Supersedes and closes https://github.com/libass/libass/pull/508. Fixes misshaping such as in the sample in https://github.com/libass/libass/issues/71#issuecomment-48186912, https://github.com/libass/libass/issues/71#issuecomment-61705139. However, this particular sample was actually a combined result of unnecessary font fallback (which this commit fixes) with another bug that was fixed in commit 80ce6378d572c230923bfc239f679e8604b8448a: it already renders correctly since that commit, but the current commit alone would also have fixed it.
-rw-r--r--libass/ass_shaper.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c
index dc47759..c4a157f 100644
--- a/libass/ass_shaper.c
+++ b/libass/ass_shaper.c
@@ -842,19 +842,22 @@ void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv,
// find appropriate fonts for the shape runs
for (i = 0; i < len; i++) {
GlyphInfo *info = glyphs + i;
- if (!info->drawing_text.str) {
- // set size and get glyph index
+ if (!info->drawing_text.str && !info->skip) {
+ // get font face and glyph index
ass_font_get_index(render_priv->fontselect, info->font,
info->symbol, &info->face_index, &info->glyph_index);
}
if (i > 0) {
GlyphInfo *last = glyphs + i - 1;
if ((last->font != info->font ||
- last->face_index != info->face_index ||
+ (!info->skip &&
+ last->face_index != info->face_index) ||
last->script != info->script ||
info->starts_new_run ||
last->flags != info->flags))
shape_run++;
+ else if (info->skip)
+ info->face_index = last->face_index;
}
info->shape_run_id = shape_run;
}