Skip to content

Allow overriding font-based normal line-height#12483

Merged
poire-z merged 11 commits into
koreader:masterfrom
moben:normal-line-height
Dec 5, 2024
Merged

Allow overriding font-based normal line-height#12483
poire-z merged 11 commits into
koreader:masterfrom
moben:normal-line-height

Conversation

@moben

@moben moben commented Sep 7, 2024

Copy link
Copy Markdown
Contributor

Allow setting normal line-height based on font size

This likely needs a bit more work to improve the implementation, hence the draft status (see todo below). Also depends on koreader/crengine#603 but I wanted to ask for some feedback if this is even worth pursuing / has a chance of being merged.

Motivation

Fonts have wildly varying

when line-height is set to normal koreader / crengine uses leading from the font metrics. As far as I can tell this is the correct thing to do and matches browser behavior. [1]

However, fonts define wildly varying leading even at the same font size. If one wants smaller line spacing or consistent line spacing when switching fonts, there are a few options:

  1. Adjust the line spacing % each time to get roughly the same result
  2. Use a css style tweak that just overrides e.g. body { line-height: 1.2; }
  3. Use a patched font

I'm currently using option 2 but wanted to explore if there's a way to get something like this built-in.

Proposal

As an opt-in tweak, allow specifying that line-height: normal should yield a consistent line height based on screen and font size.

Common guidance and some experimentation suggest that good values depend on the font size, e.g. line-height: 1.5 might be good for font-size: 12px, but for font-size: 44px, line-height: 1.1 can be enough. [2]

A multiple of the font size plus a fixed offset gives line heights that match this guidance. e.g. this article suggests 2ex + 4px.

Implementation

To the user this feels like a style tweak, but it can't really be one as far as I can tell because a reasonable line-height depends on the font size on that line. So even if style tweaks could be dynamic based on other settings such as font size, they could not take into account what font size is set for a specific line via css.

I originally tried to do this purely in crengine with just a toggle in frontend, but that doesn't work due to the screen-font-size scaling. crengine doesn't know that the 47px font size it sees is actually 22px scaled by screen size, so if it calculates 4px + 2ex that yield a line height of 1.09 instead of 1.18, which is too small. The 4px needs to be scaled by screen size as well.

The current approach presented here works well for me, but it feels like something cleaner should be possible. Maybe crengine should know the screen scaling factor (e.g. via prop) and apply it when setting the font size? Then the same scaling could be applied to this. I'm open to alternative suggestions.

Screenshots

Using Standrard Ebooks The Count of Monte Cristo and a few different fonts at size 22

Default

Literata Literata Book ChareInk6

Size-based line-height: normal

Literata Literata Book ChareInk6

TODO

  • Do some testing with non-english text (any freely accessible recommendations?)
    • Different alphabets and text directions
    • Languages heavy in diacritics
  • Replace magic constants with defines / advanced settings
    • Decide if these should be e.g. advanced frontend settings or custom -cr css properties that can be overridden using css tweaks for both fixed and scaling parts.
  • Figure out where to put this in menu
    • Not sure where a good place is. Style tweaks would might fit better from a user perspective but it's not a style tweak (unless all factors and the on/off toggle are exposed via css).
  • Settle on default values
    • I arrived at slightly different values than defined above
    • This is mostly because there's some rounding going on when passing between frontend and crengine and in crengine 1em == 2ex, which isn't true in desktop browsers

[1] https://developer.mozilla.org/en-US/docs/Web/CSS/line-height says that desktop browsers default to a value of roughly 1.2, but this seems to be outdated. Both Firefox and Chrome use what the font defines. See also w3c/csswg-drafts#1254
[2] https://fonts.google.com/knowledge/using_type/choosing_a_suitable_line_height#setting-line-height


This change is Reviewable

@NiLuJe

NiLuJe commented Sep 7, 2024

Copy link
Copy Markdown
Member

I'm in the "patched font" camp, but this certainly looks like something nice to have, especially for like-minded OCD font nerds ;).

@Frenzie

Frenzie commented Sep 7, 2024

Copy link
Copy Markdown
Member

says that desktop browsers default to a value of roughly 1.2, but this seems to be outdated.

I think they might be trying to say in a roundabout manner that most fonts do so.

@mergen3107

Copy link
Copy Markdown
Contributor

Is this going to be just an option, which is off by default?

I spent too much time with Profiles adjusting each font with its line spacing to have exactly the same number of lines :D

I don’t wanna do this again

@poire-z

poire-z commented Sep 7, 2024

Copy link
Copy Markdown
Contributor

A few thoughts:

I understand your aim, I guess we are all bothered by some fonts being nice, but having non-standard (non-what-we-are-used-to) line height. (I had to skip that upgrade to Bitter because of https://github.com/solmatas/BitterPro/issues/20).

I understand there can be some maths to compute a thing that work. I'm just not sure:

That it really works in all cases. I guess that for a same font size, you would then not use the font creator specified line height, but will use the user-set font size. I think that even at a same font size, a font "body" height (ie. the "x" height or an uppercase "B" height) could vary, so in effect impacting the visual vertical spacing between lines of text, so the perceived line height. Right ? But I get that at least, it will ensure that the nb of lines per page stays fixed (which is another kind of OCD, the one that affects @mergen3107 :))

Your formula is some competent people choice - but it's still just a taste of these people. It's nothing "per specs". It feels a bit odd to push that into crengine.
Isn't there some new CSS properties that aim at people tweaking that, that may be we could implement in a more "per specs" project?

You are pushing a 1.05em into crengine, but allow to set the "extra" (gRenderMinNormalLineHeight, better named gRenderExtraNormalLineHeight ?) from frontend - because you say it depends on our scaleBySize, and this is true. But crengine's idea of a css "px" is unrelated to our scaleBySize, it depends on another setting, the one we set with Zoom/DPI. I'm not really sure that this "extra" should come from either of them.
Our scaleBySize is mostly related to our Screen DPI menu, which is used to zoom in/out our UI items and text size: I don't think this should affect the rendering. We indeed use that to "scale" the user set font size (the number in our bottom menu are somehow "abstract" font sizes in some arbirary abstract unit - that may hopefully results in the same crengine text visual size in devices of different sizes). I don't think they represent enough of a visual font size that can be related to CSS px for that little extra. (All this was confusing to write, I hope you get my point :))
Our Zoom/DPI is mostly related to scaling CSS px, margins, borders, image sizes... All is made (PROP_RENDER_SCALE_FONT_WITH_DPI=0) so that it is orthogonal to the font size.
The most "real" thing is still the scaleBySize font size we give to crengine, and that results in real screen pixels.
So, I'm not sure about all this.

Also, given that the user set font size is how he wants to read it, and that at most, it is scaled by a publisher by 80% to 120%, a user chosing 18 will get most text at a size around 18, and never 44 (except for the book title may be), and mostly may be 25 or 30 for chapter titles (which are mostly one line, the line height won't matter much). So, you could push a fixed preferred line height of 1.05*18 + your scaleBySize(3px) if you want - that you would just scale according to the node's CSS font size * that number / the user set default size. Might work good enough? dunno, and you would just push an integer related and similarly to the font size.

Or you could autocompute (from frontend) the optimal (according to your formula) "Line spacing" depending on the user set font size, scaleBySize, the default font, and you would get 104% with one font, 97% with another. Dunno if that would work :) just throwing the idea.

I'm also not fond of having this using a crengine prop, it means we'd need another toggle/number picker in frontend, dunno where we would put that.
If this would need a toggle/boolean, we could use a -cr-hint: fancy-normal-line-height or implement a line-height: -cr-fancy that could indeed be set via a style tweak.
If this needs one or more numbers, we could implement a new private property -cr-extra-normal-line-height: 3px (or 3 if it should not be scaled by Zoom/DPI) or -cr-extra-normal-line-height: 1.05+3 to allow more user tweaking.
But I don't know if it's worth adding all this for some OCD users :)

@moben moben force-pushed the normal-line-height branch 2 times, most recently from cf85e23 to fad468b Compare September 8, 2024 18:00
@moben

moben commented Sep 8, 2024

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback everyone!

I'm also not fond of having this using a crengine prop, it means we'd need another toggle/number picker in frontend, dunno where we would put that.

I don't really understand this point, maybe I'm missing context for when to use or not use props. It just seemed like the correct thing for such a global property. A private css property would also work but it's a bit weird if font-size: normal means something different for different elements.

My main goals were:

  • exposing this as a toggle instead of needing to write a css tweak for every line spacing you want to use
  • Making it possible to apply this to line-height: normal without overwriting all line heights that might be set (I think impossible with current css tweaks, but would be possible with a private property). This can still be applied to all lines by using the "ignore publisher line heights" tweak.

I dropped the magic formula and constants, I agree it's hard to please everyone there. Instead I just exposed this as a setting:

Reader_2024-09-08_195801

Does this look better? Not sure if it should be per-document, but it would probably need to be integrated with profiles.

@poire-z

poire-z commented Sep 8, 2024

Copy link
Copy Markdown
Contributor

I don't really understand this point, maybe I'm missing context for when to use or not use props. It just seemed like the correct thing for such a global property.

Because you decided to make it a global property.
And it being a global property needs a menu item or a bottom menu widget (and most such global properties are indeed bottom widgets).
There are many "features" that I implemented and decided to make available via style tweaks just to avoid having to clutter our UI with another strange thing (ie. Ensure steady line height, Tailor widths for CJK style tweaks). It's maybe less practical to use and tweak, but it has the benefit to be able to be set per-document or global (without any added frontend code), to be associatable to a profile, and to be able to target only some elements. If I had made them globals, our menu or bottom panel would be overcrowded with many strange things. The question is whether your thing deserves it.

I suggested other ideas just for the sake of discussion (which hasn't happened).

Anyway, all in all, your current koreader/crengine#603 is probably the least crengine-intrusive way to implement this.

                int em = font->getSize();
                if (gRenderNormalLineHeight > 0) {
                    int rem = enode->getDocument()->getDefaultFont()->getSize();
                    // Scale slightly to font size. Line height is partially a fixed offset and
                    // partially relative to font size, so scale half of the offset.
                    // Larger font sizes need less line height
                    line_h = em + (gRenderNormalLineHeight - rem) * (em + rem) / (2 * em);
                }
                else {
                    line_h = font->getHeight(); // line-height: normal
                }

I don't really get your line_h = em + (gRenderNormalLineHeight - rem) * (em + rem) / (2 * em)
(Substracting gRenderNormalLineHeight = 1.22 (an abstract number) and a font size (in pixels) ? Seems like some random math magic/toying. I suck too much at math to appreciate it, so I would appreciate some details/examples.)
I would just expect line_h = em * gRenderNormalLineHeight (that is font size * 1.22). Do I get it right (just asking, not discussing your need for the adjustment) that this is what should just happen if one sets that [x] Set normal line height based on font size and a Normal line height: 1.22 ?

Anyway, as said, I'm not strongly opposed to having that crengine PR, and even your frontend PR (even if making this menu 10 items).
But I would like to hear more feedback and appreciation, so it ends up being not just "@moben fancy idea that makes no real sense to anybody else's use case" :)
@mergen3107 : feel like trying these PRs and see if having that would have helped avoiding you to make all your profiles per font to associate to each the perfect line height ? You wouldn't need yet to drop your profiles :) just see if without using your profiles, you would auto get your perfect line heights - or if it's not really that perfect and you would still prefer your handmade lineheight-per-font.

That it really works in all cases. I guess that for a same font size, you would then not use the font creator specified line height, but will use the user-set font size. I think that even at a same font size, a font "body" height (ie. the "x" height or an uppercase "B" height) could vary, so in effect impacting the visual vertical spacing between lines of text, so the perceived line height. Right ? But I get that at least, it will ensure that the nb of lines per page stays fixed (which is another kind of OCD, the one that affects @mergen3107 :))

You haven't answered that one.

@mergen3107

Copy link
Copy Markdown
Contributor

I need to compile by hand to test. I am not with my compiler machine yet, will try a little later.

@moben

moben commented Sep 9, 2024

Copy link
Copy Markdown
Contributor Author

Sorry I haven't answered all your points in detail @poire-z, will try to do so below. That being said, I think you were right in your first comment that this was too opinionated, which is the initial feedback I was looking for.

I don't really understand this point, maybe I'm missing context for when to use or not use props. It just seemed like the correct thing for such a global property.

Because you decided to make it a global property.
And it being a global property needs a menu item or a bottom menu widget (and most such global properties are indeed bottom widgets).

What I mean is that semantically, this is a global property. It could of course be changed to be a local property, but it might get weird if it's adjusted only for some elements.

[...], our menu or bottom panel would be overcrowded with many strange things. The question is whether your thing deserves it.

I'm also not sure, patched fonts or manually adjusting line heights in profiles might be too small a niche. But at least for me, the whole reason to do this is to make it accessible in a menu. If you don't know how to patch fonts, you currently need a style tweak that globally forces the line height.

In my eyes, a simple tweak that sets line-height has the following disadvantages:

  1. Globaly forces line-height for all font sizes and can't do scaling adjustments
  2. Harder to experiment with. If you want to try different line heights you need to edit the style tweak instead of just pushing a button
  3. Inherently less accessible

Making it a private css property, e.g. -cr-normal-line-height would only address 1. (assuming the crengine change lands).

I think that even at a same font size, a font "body" height (ie. the "x" height or an uppercase "B" height) could vary, so in effect impacting the visual vertical spacing between lines of text, so the perceived line height. Right ? But I get that at least, it will ensure that the nb of lines per page stays fixed

Yes, that's my intention with this.

I'll skip over the discussion of the originally proposed formula, I got rid of that and I think it's better this way. This also means there's no explicit relation to scaleBySize — only to font size.

I don't really get your line_h = em + (gRenderNormalLineHeight - rem) * (em + rem) / (2 * em)
(Substracting gRenderNormalLineHeight = 1.22 (an abstract number) and a font size (in pixels) ?

Actually, gRenderNormalLineHeight is an absolute number for the line height at the root font size, in the same units as font-size (screen px I think?). I thought you suggested just computing it in frontend and scaling a bit in crengine if needed, but maybe I misunderstood? (Also, I didn't want to have deal with passing floats from lua to C++, everything else I've seen was an int)

What this is supposed to do is scale half of the whitespace by the local font size. So e.g. (assuming screen scaling 1:1):

  • your font-size is 22
  • you set line-height: 1.35 via frontend

Then:

  • gRenderNormalLineHeight is 22 * 1.35 (== 30)
    • of that, 30 - 22 (== 8) is white space
  • a line in the same document that has font-size 18 gets line_h = 18 + 8 * 0.5 + 8 * (22 / 18) (== 32)

The intention here is to scale a bit for the ±20% font size differences that you noticed but overall don't change too much from what the user set. While the fully magic formula that I originally proposed is a bit opinionated, there is truth in the idea that line-height can't scale linearly (inversely) with font-size. If there was a line in the same document at size 11, it should not have twice the line-height. On the other hand, this needs to ensure that even large font sizes (e.g. title page) don't get line-height 0.
I can try to make that clearer in the comment.


I hope I covered all points that were brought up so far. I too would be interested if this helps someone else's use case!


For frontend, maybe I should investigate a way to allow style tweaks to have a parameter? Or maybe that already exists and I missed it? I would actually prefer if this could be a style tweak, it thematically fits better there and I'm not really married to the menu placement or prop.

@Frenzie

Frenzie commented Sep 9, 2024

Copy link
Copy Markdown
Member

For frontend, maybe I should investigate a way to allow style tweaks to have a parameter?

I'm not sure what you mean by that exactly, but of course you could easily set some text dynamically as part of the string.

@moben

moben commented Sep 9, 2024

Copy link
Copy Markdown
Contributor Author

I'm not sure what you mean by that exactly, but of course you could easily set some text dynamically as part of the string.

But there are no style tweaks that allow user-input, right? At least I couldn't find any. There's only on/off and e.g. "In-page footnote font size" just has a selection of percentages to choose from.

@Frenzie

Frenzie commented Sep 9, 2024

Copy link
Copy Markdown
Member

Indeed, the general concept is that if you find the default ones insufficient you'll probably be more satisfied writing your own.

@poire-z

poire-z commented Sep 9, 2024

Copy link
Copy Markdown
Contributor

What I mean is that semantically, this is a global property. It could of course be changed to be a local property, but it might get weird if it's adjusted only for some elements.

Well, it's still you deciding it's semantically a global property. With a style tweak, one could target on purpose some specific element, or avoid targeting others.
I can imagine that using math fonts with their normal line-heights (generally bigger) for math formulas will get screwed by your global propery. One could avoid that with math { -cr-dontdothelineheightstuff }.

If you don't know how to patch fonts, you currently need a style tweak that globally forces the line height.

Well, before you proposed that, nobody complained, they were all just fine using our Line Spacing bottom widget to adjust what they want for their preferred font.
I know testing/changeing fonts and comparing is a sport some users enjoy - and it's mostly there that your PRs may really help. Once you're settled on a preferred font and its associated preferred Line Spacing, one is just fine.

Actually, gRenderNormalLineHeight is an absolute number for the line height at the root font size, in the same units as font-size (screen px I think?). I thought you suggested just computing it in frontend and scaling a bit in crengine if needed, but maybe I misunderstood? (Also, I didn't want to have deal with passing floats from lua to C++, everything else I've seen was an int)

Thanks for the explanation and the examples. Yes, that's fine (I didn't really look at the frontend PR to see your were doing * font_size).

I can try to make that clearer in the comment.

Yes, that would be welcome, thanks.

Been testing the crengine changes with just:

--- a/frontend/document/credocument.lua
+++ b/frontend/document/credocument.lua
@@ -1221,6 +1221,7 @@ function CreDocument:setFontSize(new_font_size)
     if new_font_size then
         logger.dbg("CreDocument: set font size", new_font_size)
         self._document:setFontSize(new_font_size)
+        self._document:setIntProperty("crengine.render.normal.line.height", 1.2*self:getFontSize())
     end
 end

For frontend, maybe I should investigate a way to allow style tweaks to have a parameter? Or maybe that already exists and I missed it? I would actually prefer if this could be a style tweak, it thematically fits better there and I'm not really married to the menu placement or prop.

Again, even if I've just shown above why a styletweak could be better, and the possible issue with math fonts, I still prefer the simplicity of the crengine PR as-is. I'd rather not review a bunch of CSS parsing additions for such a little odd feature.

I've tested it on our "Generate font test document", and it is actually quite nice, getting rid of the variations and helping better comparing font (but not really :) we're no longer comparing their creator line heights :))
It feels it could have make @mergen3107 satisfied.
One odd thing is that launching Book information on the first page of the sample text for a few fonts, I don't always get the same number of lines on that page: I sometimes get 23, sometimes 22, not sure why (my sample text has no style=, so there should always be the same nb of lines with the hardcoded line-height your PR enforce).

Comment on lines +738 to +739
checked_func = function()
return G_reader_settings:nilOrTrue("cre_size_based_normal_line_height")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We surely don't want this enabled by default and shuffling users' living room and habits.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Comment on lines +746 to +749
help_text = _([[
Automatically set line height based on font size, instead of font metrics.
]]),
separator = true,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The help_text will need a bit more explanation (and be different).
No separator=true needed between your 2 related menu items.

Comment on lines +767 to +768
value_min = 1,
value_max = 5,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 was usable, so maybe allowing smaller values for people that like their life condensed could be nice.

Comment on lines +774 to +775
G_reader_settings:saveSetting("cre_normal_line_height", spin.value)
self.ui.document:setNormalLineHeight(G_reader_settings:nilOrTrue("cre_size_based_normal_line_height"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these 2 related setting should have a same prefix, ie.:

cre_size_based_normal_line_height_enabled
cre_size_based_normal_line_height_value or _factor

Comment thread frontend/document/credocument.lua Outdated
if new_font_size then
logger.dbg("CreDocument: set font size", new_font_size)
self._document:setFontSize(new_font_size)
self:setNormalLineHeight(G_reader_settings:nilOrTrue("cre_size_based_normal_line_height"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels a little odd to pass one of the 2 settings as arg, and use the other one inside the called function.

@mergen3107

Copy link
Copy Markdown
Contributor

Are the fonts used for menus going to be with minimal line heights? One screenshot above looks scary :D menu items are too condensed

@moben moben force-pushed the normal-line-height branch from fad468b to d43e307 Compare September 13, 2024 23:10
@moben

moben commented Sep 13, 2024

Copy link
Copy Markdown
Contributor Author

As was suggested multiple times, I just made this a style hint now, with a bunch of preset options to choose from, similar to the footnote font size style hints.

I also got rid of the maths that were still there, in all my testing the difference this makes is so miniscule that it's not worth it in my opinion. If someone needs different "normal" line height for different elements (other than a constant factor), this can now be achieved via css.

Are the fonts used for menus going to be with minimal line heights? One screenshot above looks scary :D menu items are too condensed

no, that's just the emulator sometimes not scaling the menu correctly, I think it's related to running in a tiling window manager.

Again, even if I've just shown above why a styletweak could be better, and the possible issue with math fonts, I still prefer the simplicity of the crengine PR as-is. I'd rather not review a bunch of CSS parsing additions for such a little odd feature.

This version has slightly more changes in crengine, but it's all boilerplate to copy the css property around, have defaults and inherit it. The actual parsing is identical to line-height. -cr-normal-line-height just overrides line-height if the latter is normal. -cr-normal-line-height: normal — which is the default — preserves the current behavior.

I hope this is acceptable, you really convinced me now that a style tweak is better. I kept the old version for now for comparison, history can obviously be cleaned up.

I'll away for two weeks and might not have time to check here frequently but will continue afterward if there are more suggestions. Still interested if this solves anyone else's problem as well.

Comment thread frontend/ui/data/css_tweaks.lua Outdated
},
(function()
local sub_table = {
title = _("Override normal font line leight"),

@NiLuJe NiLuJe Sep 14, 2024

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might need a better label, because if I hadn't read the PR, this would just look to me like it's simply enforcing the actual standard line-height CSS property ;).

@poire-z

poire-z commented Sep 14, 2024

Copy link
Copy Markdown
Contributor

I'll away for two weeks and might not have time to check here frequently but will continue afterward if there are more suggestions.

That's fine, it lets us some time to make a stable release, and bring your new stuff only in followup nightlies.

I hope this is acceptable,

Looks ok.

I had in mind earlier when reviewing another thing that I sometimes wished we had: a way to target nodes according to their computed style (to fix/kill it), something like:

*, autoBoxing {
    -cr-hint: late;
    -cr-only-if: (line-height: normal); /* or (line-height: >1.2) */
        line-height: 1.2 !important;
}

but that would need some heavy thinking about parsing & storing & checking the condition.

For now, we have a bit of that with static targetting (that I added mostly for footnotes "fix-up"), and you could just have added another static string, and you could use:

*, autoBoxing {
    -cr-hint: late;
    -cr-only-if: line-height-normal;
        line-height: 1.2 !important;
}

which would be handled like our -cr-only-if: inline:
https://github.com/koreader/crengine/blob/6e6a99398da50b737913f933a75ddec5f58a36db/crengine/src/lvstsheet.cpp#L5291-L5310

May be this is still the way to go (new strings for the little needs we may have), and would avoid having to add new -cr- properties and to think about the combinations/inheritance between line-height and -cr-normal-line-height ?

Comment thread frontend/ui/data/css_tweaks.lua Outdated
Comment on lines +489 to +494
title = T(_("Normal line height: %1"), rem),
css = T([[
body {
-cr-normal-line-height: %1 !important;
}
]], rem),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For small singles ones like this, you can have it on a single line, and no need for !important as it is a private properties no publisher will be using.
css = T([[body { -cr-normal-line-height: %1 }]], rem),
(also, rem feels like not the right variable name, num feels ok)

@Frenzie

Frenzie commented Sep 14, 2024

Copy link
Copy Markdown
Member

That's fine, it lets us some time to make a stable release, and bring your new stuff only in followup nightlies.

The crengine issues were fixed now I believe? But there's apparently still some weirdness with the terminal plugin on Android I (or someone) would have to look into.

@poire-z

poire-z commented Sep 14, 2024

Copy link
Copy Markdown
Contributor

The crengine issues were fixed now I believe?

Yes, things should be stable on the crengine side.

@mergen3107

Copy link
Copy Markdown
Contributor

Do some testing with non-english text (any freely accessible recommendations?)

https://www.gutenberg.org/browse/languages/ru

Figure out where to put this in menu

Easy! Bottom menu, Consistent Line Height right next to Line Spacing :D

Settle on default values

I have a vague understanding that say Amazon is using this kind of methodology for their reading apps. Because in Kindle UI you only have three line spacing options for a very wide range of font sizes and none of them look terrible honestly :D

@mergen3107

Copy link
Copy Markdown
Contributor

I can try this, but my main gripe with fonts is actually not the line spacing, but the "height" of characters and how they define them.

For example, compare Bookerly and Academy Old fonts.
Bookerly's actual character height is almost as high as the character bounding box.
But for Academy Old, the height is like 70% high. That means the same line-height will not look the same on these two fonts.

I have to increase Academy Old's actual font size to make "visible height" equivalent with that of Bookerly.

Is it possible to calculate "average visible height" of characters (says, only a-z, or equivalent, or A-Z) and make crengine scale that instead?

Then, with both these options under control ("average visible height", and line spacing from this PR) it will be much easier to achieve consistent results.

@moben moben force-pushed the normal-line-height branch from d43e307 to 884885a Compare October 5, 2024 23:47
@moben

moben commented Oct 5, 2024

Copy link
Copy Markdown
Contributor Author

Easy! Bottom menu, Consistent Line Height right next to Line Spacing :D

I agree this is slightly at odds with the percentage-based line spacing menu. But when comparing to desktop browsers the default behavior is definitely correct and everyone convinced me that this fits in best as a style tweak. But having the line spacing setting just set the normal line height directly would also work (would probably need to be a crengine prop again though...)

I have a vague understanding that say Amazon is using this kind of methodology for their reading apps. Because in Kindle UI you only have three line spacing options for a very wide range of font sizes and none of them look terrible honestly :D

I've never used a kindle or any reader other than koreader and plato really, but that's interesting to hear. Do their line spacing settings result in the same spacing for each font (and also custom ones)? And do they just override all line-spacing specified in css? Maybe there is more room for improvement. I tried looking through old issues but I don't really have the historical context for why line spacing is set up percentage based in koreader.

Is it possible to calculate "average visible height" of characters (says, only a-z, or equivalent, or A-Z) and make crengine scale that instead?

That might be possible, font metrics probably have ex height somewhere. But if you interpret line-height relative to that you leave the css spec behind and I don't know how much trouble that would cause. Also not sure to which extent a nice line height also depends on e.g. weight.

Generally, the expectation is that most uppercase letters match the font size, but height of lower case letters varies more.


As suggested, I moved the style tweak implementation here to a -cr-only-if: line-height-normal. It's slightly more/different boilerplate in crengine because line-height: inherit — which is of course the default — requires looking at the style of the parent element. (I think technically -cr-only-if: inline would also need this but in practice no-one sets display: inherit manually and it's not the default).

Settings now look like this:

@moben moben marked this pull request as ready for review October 5, 2024 23:48
@mergen3107

Copy link
Copy Markdown
Contributor

Do their line spacing settings result in the same spacing for each font (and also custom ones)? And do they just override all line-spacing specified in css?

I don't know for sure since java code is obfuscated, but it seems they 1) scale line spacing with font size; 2) also scale (or take into account) css-specified line-heights too.

But one thing is certain, the same fonts I use on PC (MS Word) do not look the same in Kindle UI at all, they definitely do something

@Frenzie

Frenzie commented Oct 6, 2024

Copy link
Copy Markdown
Member

If we're talking fonts shipped by Kindle a potential alternative is that they normalize them in the fonts themselves.

@moben moben changed the title Allow calculating a nicer normal line-height Allow overriding font-based normal line-height Nov 1, 2024
Comment thread frontend/ui/data/css_tweaks.lua Outdated
Comment thread frontend/ui/data/css_tweaks.lua Outdated
@benoit-pierre

Copy link
Copy Markdown
Member

fix typoe leight => height

You've got a typo in your "fix typo" commit. :P

@poire-z poire-z merged commit 1438caf into koreader:master Dec 5, 2024
@Frenzie Frenzie added this to the 2025.01 milestone Dec 5, 2024
0xstillb pushed a commit to 0xstillb/koreader-thai that referenced this pull request May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants