protectwise / troika

A JavaScript framework for interactive 3D and 2D visualizations
MIT License
1.64k stars 124 forks source link

Text: allow font to specify unicode character ranges #13

Open lojjic opened 5 years ago

lojjic commented 5 years ago

See corresponding CSS feature: https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range

The font property should accept an array of unicode-range-to-font-file mappings.

lojjic commented 2 years ago

Also see #206 - this unicode-ranges work enables the specification of default fallback fonts for greater out-of-the-box unicode coverage.

morandd commented 2 years ago

+1 request for this feature. Out-of-the-box unicode support is fairly fundamental for the modern web.

Just an idea, is it possible to leverage the system fonts? The Noto font .woff / .ttf files for Japanese alone are 6mb! Leveraging system fonts would afford a big download savings. So the idea would be to render the unicode string to an offscreen canvas using the browser text rendering engine, then use getImageData() to read that canvas and create the SDF which gives the beautiful WebGL fonts.

This Mapbox repo seems to do something like that: https://github.com/mapbox/tiny-sdf

Since global unicode is a hard requirement for my project I'll try now switching to mapbox/tiny-sdf -> canvas -> THREE.CanvasTexture() to generate text, and keep a Watch on troika-text to see if unicode makes an appearance. Troika generates beautiful text easily; just wish it had complete glyph coverage.

lojjic commented 2 years ago

is it possible to leverage the system fonts?

No, unfortunately, there is no browser API yet for accessing system font data. The only way to use system fonts is as you suggested, which works for certain use cases. If that works for you then definitely go for it!

morandd commented 2 years ago

I guess my point was, there are a couple of libraries that will generate SDFs using system fonts:

https://github.com/mapbox/tiny-sdf https://npm.io/package/pixi-richtext https://github.com/mapbox/fontnik

By coupling those SDF generators to the text layout engine, shader, and THREE bindings in this package it should be possible to generate complete sharp, complete, unicode text on the fly without any downloads.

I really appreciate your excellent work on troika. I just post this comment because it seems we are this close to being able to have on-the-fly, 3d, complete unicode text. I wish I had the fluency with GLSL to bind to tiny-sdf and submit a PR instead of merely a comment.

lojjic commented 2 years ago

Ah, if only it were that simple! 😉

The font files are needed for more than just SDFs. They also contain data for glyph metrics, layout, ligatures and joined characters, et cetera. The libraries you mentioned are great for simple glyphs, or for full strings, which is why I said they work for certain use cases - like if you have a relatively small number of short single-line labels. Unfortunately that isn't sufficient for all troika-three-text aims to support.

lojjic commented 2 years ago

I guess I should mention, I do plan at some point to offer an optional fallback mode to utilize canvas rendering to assist with certain characters not covered by an actual font file - mostly for emojis but it could also be a not-perfect-but-fairly-ok option for CJK character sets specifically, which tend to not have complex layout or joining rules and are among the largest font files.

morandd commented 2 years ago

OK, thanks for clarifying. Also, I look forward to when the unicocde-ranges support is released.

short single-line labels.. [snip] ... for CJK character sets

This would be amazing, and I guess would cover 50-80%+ of the common needs.

Your Troika text just looks so much better than canvas text. I wish we could have this for CJK labels.

morandd commented 2 years ago

To add a comment that might help others who stumble into this thread:

I spent a few hours unsuccessfully trying to create a custom font that contains the unicode glyphs to display. Where the file "input.txt" contains all the characters that might need to be rendered, and given GoNotoCurrent.ttf, running the command

pyftsubset GoNotoCurrent.ttf  --layout-features='*' --text-file=./input.txt --output-file=test.ttf 

That generates a manageable 1.2mb font, but I get a bunch of "unsupported GPOS table "errors like "unsupported GPOS table LookupType 6 format 1" from Typr in the browser and still the Tofu no-glyph boxes from Troika-text.

Suggestions welcome. Perhaps some better settings for pyftsubset can fix this. If we can diagnose this problem it could be a workaround for those who want to support more global langauges.

eXponenta commented 8 months ago

is it possible to leverage the system fonts?

No, unfortunately, there is no browser API yet for accessing system font data. The only way to use system fonts is as you suggested, which works for certain use cases. If that works for you then definitely go for it!

https://developer.mozilla.org/en-US/docs/Web/API/Window/queryLocalFonts