Skip to content
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

Better Bangle.js fonts #3109

Open
gfwilliams opened this issue Nov 20, 2023 · 12 comments
Open

Better Bangle.js fonts #3109

gfwilliams opened this issue Nov 20, 2023 · 12 comments
Labels
area-graphics Bangle2 Related to Bangle.js 2 help wanted Extra attention is needed question Further information is requested type-enhancement New feature or request

Comments

@gfwilliams
Copy link
Member

There have been discussions about this in the past (I'm afraid I can't find any good links at the moment - they're probably on the forum). But vaguely related issues are #1145 and #1311

Problem

  • Smaller fonts are too thin to be readable
  • Big/small font styles don't match
  • We don't support any characters outside ISO8859-1 0..255 codepage with current fonts
  • We don't have a nice way of choosing what font to use right now - every app implements its own solution, using hard-coded fonts

Where we are

  • There is an awesome free font in different sizes, specifically designed for the Bangle's display (well, pebble's): https://github.com/pebble-dev/renaissance/tree/master - it's in PBF format
  • Bangle.js now supports PBF loading and rendering
  • Bangle.js 2 also now supports Unicode so can render non-ASCII chars too
  • There's also GNU unifont which I've turned into a PBF file so we can even support full chinese/japanese/etc locally

So what's the issue?

It'd be nice if we had a global way of changing fonts (eg by installing an app/library via the App Loader) - to either change the look and feel, size of fonts, or to add native support for more character sets.

While we could have a library/function that handled simple font selection, eg require("font").getFont("big"/"medium"/"small") I don't think that's really useful enough.

I think we need something that'll choose a font based on some text and how much space there is. For example:

... = require("font").getFont({
  w : 176, h : 120, 
  wrap : true,
  text : "Hello this is a lot of text I want to display on the screen"
});

... = require("font").getFont({
  w : 60, h : 60, 
  wrap : false,
  text : "10m"
})

Any thoughts on this? I think the main things it needs to be able to handle are:

  • Blocks of text in messages
  • Small bits of text for labels or values (eg the 'run' app)
  • Ideally being aware of images in the text - no point using a tiny font when there are images that are 16px high anyway
  • Maybe returning the pre-wrapped, pre-cropped (with ...) text as well as the font just to save on computing things twice
  • Specifying a maximum/minimum font height?
  • Do we need to think about multiple text items? For example if we have a list (like in the Launcher) maybe we want to make everything in the list the same size?

I guess it might be good to think about existing apps that would benefit from this (messagegui, launcher, run, E.showMenu, E.showPrompt, etc) and what kind of features they would need?

Also, I guess this may need to be something that runs quite fast - so do we actually want a built-in function that just looks at a list of available fonts? Or maybe we get it working in JS first, then if it's slow we look at moving it inside the firmware.

@gfwilliams gfwilliams added type-enhancement New feature or request help wanted Extra attention is needed question Further information is requested Bangle2 Related to Bangle.js 2 labels Nov 20, 2023
@bobrippling
Copy link
Collaborator

Examples

Yes, I like the sound of this, currently I have widclk and widalarmeta both displaying slightly different 7-segment fonts in the widget bar and having this more globally configurable would be nice.

Plan/points

I think getFont({ w, h, ... }) sounds like good, and later down the line, the layout library would be able to lean on it too.

  • +1 for also returning the pre-wrapped/cropped text
  • For whether we have min/max font height, I suppose it depends how we implement getFont(), although thinking about it from what I've typed below, I think just a height parameter would work, as we'd probably handle it as a max height:
    • If we have min/max, and there's two fonts that satisfy, do we always go for larger? (probably yes)
    • If we just have a height passed instead, do we always go for the largest font under (or at) that height?
    • So it's the same behaviour really, I don't think minimum size comes into play (except for this next point)
  • For multiple text items, we could either have something in the API where we accept an array of max heights (of which we take the smallest), or we leave that logic up to the app itself - I'd vote for the latter, at least for the first implementation

I'd also like to add, for existing apps that would use this API / an initial implementation, I think it would be nice if we could let the user configure a single font for widgets, as mentioned at the start of my post

Initial approach

User config

  • Ability to install fonts from the apploader, add entry to settings to enable/disable?
    • Later implementation: permit configuring this via settings
  • Permit user to upload/specify a font for the widget bar

Test apps

Perhaps we use run and E.showMenu as trials - run for a full screen app with variable text, E.showMenu as an "app" where we want consistent display of text for all items?

And yes, +1 for initial implementation in JS, then performance checks

@gfwilliams
Copy link
Member Author

Thanks!

Ability to install fonts from the apploader, add entry to settings to enable/disable?

I'm not sure I understand about enable/disable? Surely you just disable by uninstalling the font app?

Permit user to upload/specify a font for the widget bar

Maybe getFont could have an optional use:"widget" field, so that you could manually specify fonts for specific types of things? I guess having use:"numeric" might be handy too so some fonts can choose to use 7 segment/etc.

While we can definitely add some settings to the font library (eg minimum font size, lock widget font, etc) I'm expecting that as long as we give enough info to getFont, other users might contribute different font apps with different fonts/behaviour.

I'm thinking at first maybe we have one lightweight font app that mirrors the existing behaviour (with built in fonts) which is the default that gets auto-installed, and then a second app using the Pebble fonts mentioned above. And when we're happy with the Pebble font one I think we just swap over.

@bobrippling
Copy link
Collaborator

I'm not sure I understand about enable/disable? Surely you just disable by uninstalling the font app?

Good point - yes the enable/disable is unnecessary

Maybe getFont could have an optional use:"widget" field, so that you could manually specify fonts for specific types of things? I guess having use:"numeric" might be handy too so some fonts can choose to use 7 segment/etc.

Excellent idea, yes I think that'll work nicely for the font settings app being able to present the user with these use-types.

While we can definitely add some settings to the font library (eg minimum font size, lock widget font, etc) I'm expecting that as long as we give enough info to getFont, other users might contribute different font apps with different fonts/behaviour.

I'm interested in what font apps will do, are they effectively the setup for the builtin code that will sit behind getFont() ? Or will they provide getFont() as a module, a bit like textinput or provides_modules?

@gfwilliams
Copy link
Member Author

I'm interested in what font apps will do

Right now I'm thinking they'll provide a font module that provides getFont - exactly as you say with provides_modules. That way everything is already there to auto-install and get rid of duplicates

@Mineinjava
Copy link
Contributor

The Renaissance font looks good. To what extent will a raster font be speedier to draw than a vector font, especially at high resolutions?

@gfwilliams
Copy link
Member Author

You'd have to do some testing but as a guess I'd say any font is faster as a raster unless it's over 40px high. Also for smaller fonts the final rendering is much better.

Basically any normal font that's not filling the screen is better as raster

@gfwilliams
Copy link
Member Author

Some work towards this now in 591c1f8

@gfwilliams
Copy link
Member Author

It appears to work! https://forum.espruino.com/conversations/394649/?offset=25#comment17323914

Just checked and you can even send messages from (the latest) Gadgetbridge too

@Mineinjava
Copy link
Contributor

The ț character (U+021B) still doesn't appear in notifications on iOS, will test later today.

I am using the extended fonts

@gfwilliams
Copy link
Member Author

So does g.clear(1).setFontIntl().drawString("\u021B") not do anything for you? What about other chars outside the 0..255 range?

I see it in 'all fonts' at least, and in extended fonts we do up to char code 1103 so 0x21B should be in there

@bobrippling
Copy link
Collaborator

It appears to work! https://forum.espruino.com/conversations/394649/?offset=25#comment17323914

Just checked and you can even send messages from (the latest) Gadgetbridge too

Great stuff! I'm quite keen on having consistent fonts across a few widgets I have, I'm quite short on time over the next few weeks but looking forward to incorporating this

@gfwilliams
Copy link
Member Author

Great! I should add that while there are now these font libraries available, the getFont function described in this issue isn't properly implemented (it just returns Intl for everything) - I just figured it was better to get the fonts in and usable in the messages app (even if it was a slight hack), rather than not having the functionality at all while I waited to try and implement the function nicely.

So ideally, before we start using the font all over the place we should probably implement getFont a bit better in these libraries and then try and use that, so we're not spreading slightly hacky code all over the place.

Also thanks for your time recently @bobrippling - I know you've been busy :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-graphics Bangle2 Related to Bangle.js 2 help wanted Extra attention is needed question Further information is requested type-enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants