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

Bold/Italic Emulation implementation needed. #677

Open
ILOVEPIE opened this issue Feb 26, 2024 · 5 comments
Open

Bold/Italic Emulation implementation needed. #677

ILOVEPIE opened this issue Feb 26, 2024 · 5 comments

Comments

@ILOVEPIE
Copy link
Contributor

Given a font opentype.js should be able to output glyphs with a different weight or italicization from the original font.

Expected Behavior

Given a font we should be able to generate glyphs with a different weight or italicization similar to how libfreetype does.

Current Behavior

We don't do this.

Possible Solution

We should look at how libfreetype does this.

Context

I need this functionality for my library that depends on opentype.js.

@axkibe
Copy link
Contributor

axkibe commented Mar 28, 2024

Short version: Can you point at the freetype API you are referring too? I don't think it can do something like this and I don't think opentype.js should.

Mid: Can it be you are confusing what most font engines do with font families? If you look for example at a feature complete like Roboto: https://fonts.google.com/specimen/Roboto this one font "family" are actually 12 fonts files, one font for every different weight and italic on/off. Some other fonts even have different variations on slanting vs italics etc. Selecting a font from a family is not what should be part of opentype.js nor is it in freetype, this is part of a layouting system like pango. This are seperated libraries on the desktop and I'd suggest to stop tying to mush it all together into opentype.js, opentype.js should do more or less what libfreetype does (minus rasterization, we have canvas in js native for that)

Long: Well aside of this kind of functionality actually should be properly reflected by loading and using the right font of a family, there do exist "tricks" how cheat to get a bold variant of a font who doesn't have one properly designed. One classic trick is just to render it a second time with one pixel offset. It will look thicker, the x-height is correctly maintained, but the proportions between horizontal and vertical aspects might be off. Another very often used trick is to load the font as path (this API already exists in opentype.js) and usually one just calls canvas_context.fill() to draw the text. However, you can canvas_context.stroke() first, this will stroke along the outer rim of the font... also making it thicker. This keeps proportions but for example x height is off. Properly designed a bold variant of a normal font is more tricky than simply stroking the path. Then there is one thing I once did with more general shapes and that is "encompassing" it by moving the individual shape parts on normal angles, proplonging the lines and finding intersections again. This is hard enough with straight lines, with bezier curves this gets super complicated (and even a bit open as in how to properly prolong a bezier beyond its originally defined area, straigh line from last defined point? Or you keep the curve? Or you also keep the second derivate of the curving?). Anyway all this tricks definitely should also not be part of opentype.js. And the double drawing or stroking trick you can do with little effort right away. PS Forgot to mention, italics can be cheated similary with a skewing-tranformation matrix. Also this you can do with canvas now.

@ILOVEPIE
Copy link
Contributor Author

Short version: Can you point at the freetype API you are referring too? I don't think it can do something like this and I don't think opentype.js should.

This is a feature of free type when there is no font available for the specific parameters. It simulates the font by modifying the font to have those options when rendering. It's a fallback in case the correct font is missing. I know it's not ideal to do this, but it's what LibFreeType does. And we need to have some functionality to either do this for users or to let users implement this themselves.
I'm more inclined for us to implement it than to make users implement it themselves because that reduces complexity for the users.
Users here means devs using our library.

@axkibe
Copy link
Contributor

axkibe commented Apr 12, 2024

ILOVEPIE, I asked you to link the specific API function calls of freetype you are referring to. I'm not aware it can do what you claim it does and a long time ago I studied it quite a bit.

If I'm wrong on this, which is very possible, it would certainly be very helpful to see what strategy they exmploy, because as I explained this is not straight forward.

@Giwayume
Copy link

The web browser simulates bold and italics. If you load "Roboto-Regular.ttf" for example, and set font-weight to bold, it doesn't try to search the internet for "Robot-Bold.ttf". It manipulates the glyphs.

Bold can be thought of as a similar operation to expanding the border of each character using a stroke (an offset operation), except it then scales down the character after the stroke so the top and bottom of the character are at the same y-position as they were before the bold operation.

Italics can be thought of as a skew transformation of each character's glyph, then the kerning is adjusted so the characters are closer together.

@axkibe
Copy link
Contributor

axkibe commented Jun 5, 2024

You are right, however I just tried it out, it looks like it simply does a stroke() a long with a fill() with correcting the baseline (aka the start positon). (that means the x-height shifts), so you can do this today. No change in the lib itself necesarry

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants