-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow providing and using multiple fallback fonts #339
Conversation
with the recently added libunibreak changes. Witnessed with an embedded float (so, malloc'ed dynamic buffers), being a <bdi> which made text start with U+2068 (FIRST STRONG ISOLATE, which happens to be breakable after a leading space), leading to "|= LCHAR_ALLOW_WRAP_AFTER" modifying byte at -1, causing a double free (while "&= ~LCHAR_ALLOW_WRAP_AFTER", done when no break allowed, did not cause any harm.) Also switch to using a Zero-Width Joiner instead of a space as the initial libunibreak char.
Rework f41517d so it works even when there are leading collapsed spaces, and probably too on BiDi/RTL text.
As our use of the fallback font was a recursive calls, we can provide chained fallback fonts. As one of the fallback font could be the main font, we need to use first getFallbackFont() (to get the first fallback font, even on a font among these fallback fonts), and getNextFallbackFont() to get the chained fallback font. Caveat: we might try rendering/drawing with the main font twice if it is among the fallback fonts (but avoiding that wouldn't make this change as simple).
LGTM, at a glance ;). Yay for cascading fallbacks (not that I'll ever use it, but, still, yay ;p). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm too
@poire-z Multiple fallback fonts are a great idea, but maybe you are making crengine more and more complex. You add new argument to few of LVFont functions: (bool is_fallback), add new field to LVFreeTypeFace (LVFontRef _nextFallbackFont) and corresponding getter/setter. Perhaps I didn’t fully understand the essence of these changes, but maybe it was just necessary to allow the recursion of the fallback font, i.e. font, if necessary, delegates their functions to _fallbackFont recursively without restrictions (but while _fallbackFont not NULL, of course). |
Well, adding new features is doomed to make the code more complex, sorry :) This fallback font stuff took me a long time thinking about how to do it. And, for once, I found the end result rather clean and lean :)
That was of course my first idea, but then, the main issue with a single chain was that:
So, let's say you set as fallbacks fonts, this chain: You set But, if you set So, my trick to have a _nextFallbackFont when it is used as a fallback font, so, there, for Font2:
which will cause the above test case to do: |
Yes, I suspected that it’s not so simple. |
What you think about plain list of the fallback fonts instead of single (couple) fallback font reference? And some wrapper functions to delegate font functions to this list. This would make the code more understandable. |
I don't know, I can't really picture your proposal :/ But in my mind when thinking may be about such a main method to ask for a fallback font, you still need to know (in the recursive calls of font rendering, like with harfbuzz) if you are the first font, or already a next/fallback font - so you would need to keep passing I don't find it that complex: d980059 Note that in KOReader, we allow the user to set its first prefered fallback font, and we build the list of fallback fonts dynamically from that. As of today, we pass: But I made it compatible so your existing code can still pass a single font name. |
Well, ok, I renamed SetFallbackFontFace to SetFallbackFontFaces :/ so it needs some frontend update on your side. |
@virxkane : I had a look at your fallback font rework https://github.com/virxkane/coolreader/commit/634438c743ebcc712e58a10dbadedf09a31ded0f But I like your idea of using a I'm not sure I get all what's happening in https://github.com/virxkane/coolreader/blob/634438c743ebcc712e58a10dbadedf09a31ded0f/crengine/src/private/lvfreetypeface.cpp#L321 right, but it feels there are 2 caveats (that I explicitely wanted to avoid):
Also, in your added Btw, about https://github.com/virxkane/coolreader/commit/f299ac5015651d9b18aab8e2219f2b2fda38a819 , what were the compilation warnings? |
My version seems more clear to me :)
I thought to replace lUInt32 with LVHashTable<lString8, bool> so as not to limit the number of fonts to 32. :)
Yes, this is a drawback, but it's more reliable, but maybe I'll fix it.
To be honest, I didn't think about it at all. I thought that the main task was to display the glyph with some of the fallback fonts, instead of the question mark. Is it really that important?
The same thing, but it's easy to fix.
Many times this warning:
But it is actually used, but only in one file. |
It was for me - but that's for you to judge on the CoolReader side :) depending on whether you allow the user to set the fallback fonts and their order or not - and what fonts you ship - and the risk to find them referenced by publishers in EPUBs via Let's say you ship NotoSansArabic (a good arabic font) and FreeSerif (a good fallback font with many unicode scripts, but smaller glyphs and so-so arabic and let's say so-so cyrillic - dunno if it really has any cyrillic) and you hardcode these as fallback in that order. Or let's say you have the same hardcoded fallback fonts, and the user reads Arabic and set NotoSansArabic as his main font. He'll have everything else picked from FreeSerif instead of from the other nicer fallback fonts you set before FreeSerif in your hardcoded list. So, these might be edge cases you can decide to ignore :)
OK, I see. (I did mostly like for the existing |
«I'll think about it tomorrow» ©
Sarcasm mode: good example, funny :) Although, an Arabic textbook in Russian? In general, I plan to add a selection of fallback fonts to the interface. |
Simplify libunibreak includes
See #337 (comment)
Text: fix read/write outside array bounds
Fix crash that could happen (in rare situations) since #337.
(The large diff is just wrapping that section with
if ( pos > 0 ) {
).Witnessed with an embedded float (so, malloc'ed dynamic buffers), being a
<bdi>
which made text start with U+2068 (FIRST STRONG ISOLATE, which happens to be breakable after a leading space), leading to|= LCHAR_ALLOW_WRAP_AFTER
modifying byte at -1, causing a double free (while&= ~LCHAR_ALLOW_WRAP_AFTER
, done when no break allowed, did not cause any harm.)Also switch to using a Zero-Width Joiner instead of a space as the initial libunibreak char.
lvtextfm: dont adjust space after initial quotation mark/dash (rework)
Rework f41517d so it works even when there are leading collapsed spaces, and probably too on BiDi/RTL text (not tested).
Didn't work when there were a collapsed space at start before the dash, like with the 2nd line here (before | after):
Fonts: allow providing and using multiple fallback fonts
As our use of the fallback font was a recursive calls, we can provide chained fallback fonts.
As one of the fallback font could be the main font, we need to use first getFallbackFont() (to get the first fallback font, even on a font among these fallback fonts), and getNextFallbackFont() to get the chained fallback font.
Caveat: we might try rendering/drawing with the main font twice if it is among the fallback fonts (but avoiding that wouldn't make this change as simple).
Wished for in #307.
We'll have in frontend something like that (can be discussed, we already had a first round of discussion for the UI fallback fonts in koreader/koreader#3942):
Users will still be able to only set one fallback font, which will be put at start of this list. If the font is already in that list, it will be moved first. This allows some bit of customisation, while always providing large coverage.
Might allow closing koreader/koreader#5277.
We get complete coverage for https://r12a.github.io/scripts/tutorial/summaries/wrapping :
and quite a bit more for https://r12a.github.io/scripts/phrases, except:
Balinese, Khmer, Mongolian, Myanmar, Telugu, Tibetan (and hyeroglyphs for Ancient egyptian :)
And possibly Urdu which should be a bit tilted arabic and expects a "nastaliq" font we don't provide - and that it seems we/HB wouldn't render very well if provided.
This change is