mapbox / tiny-sdf

Browser-side SDF font generator
http://mapbox.github.io/tiny-sdf/
BSD 2-Clause "Simplified" License
567 stars 58 forks source link

Font Kerning #6

Open joafalves opened 6 years ago

joafalves commented 6 years ago

Hello :)

Do you have any plans to support font kerning on this? When we use chars with different widths, the spacing between characters is always the same.

What are your thoughts on a possible implementation?

Thanks.

mourner commented 6 years ago

I have no idea how to implement this unfortunately. I made this library for CJK glyphs use case, where all characters are the same size. But I'm welcome to any ideas.

joafalves commented 6 years ago

I've recently stumbled on this: https://opentype.js.org It has all the features we needed to adjust the font rendering correctly 👍

joafalves commented 6 years ago

We are using it on our all-in-one platform though (https://github.com/scarlettgamestudio/scarlett-editor) you might need to adjust for a "tiny" integration :)

monfera commented 2 years ago

I was wondering about memory, CPU/runtime and Canvas2d scalability, as rendering all words (ahead of time or on demand) can be resource intensive or sometimes prohibitive. This thread answers it, it's per glyph, so no or low resource issue. May be worth mentioning it in the description that it's glyph based and specifically for monospaced fonts (and I guess tile and sprite based 2D games)

mourner commented 2 years ago

@monfera good point — probably needs clarification. Although technically nothing prevents drawing TinySDF for whole labels if a use case doesn't require too many. Also, the primary use case for it currently is rendering Chinese/Japanese/Korean glyphs in Mapbox GL JS — so not necessarily monospaced, if the language uses relatively same-size glyphs and doesn't depend on kerning.

controversial commented 1 year ago

You can calculate the kerning for a pair of characters on a canvas by comparing the measured width of the combined characters to the measured width of the characters individually:

const unkernedWidth = tinySdf.ctx.measureText('A').width + tinySdf.ctx.measureText('V').width;
const kernedWidth = tinySdf.ctx.measureText('AV').width;
const kerning = kernedWidth - unkernedWidth; // a negative value indicates you should adjust the SDFs closer together by that much