diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2021-09-01 17:20:51 +0300 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2021-09-09 02:32:49 +0300 |
commit | d170d895941b70c5a4bb7a5f555132acb34e9013 (patch) | |
tree | e687bb4965e88c1a3029d38c6ff27651cc61b37c | |
parent | 14f1f0480ffb7af9a33e224287428161a18e7cf2 (diff) | |
download | libass-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.c | 9 |
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; } |