-
Notifications
You must be signed in to change notification settings - Fork 376
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
Add SDF HintingMode #1966
base: 12.0-development
Are you sure you want to change the base?
Add SDF HintingMode #1966
Conversation
I tried to apply and use this change on Windows with the default font (
0x13 is |
That's the main problem I was having with the prebuilt love-apple-dependencies on macOS. After building it myself from the official FreeType 2.12.0 source instead of from the megasource, it worked with no errors. From FreeType's changelog they state that SDF support is available since 2.11.0, is there a reason the megasource's FreeType could be different from the official source? |
It's the same source code. Maybe it's an opt-in compile time feature when building the library? If that's the case and it's not enabled by default in Linux distros, this gets a lot more complicated to support because we can't guarantee that it's available in every copy of a given love version. Speaking of Linux distros, I think Ubuntu 20.04 LTS may not provide 2.11+. |
I've investigated it further, and it looks like the Commenting out lines 303-309 in /* the rows and pitch must be valid after presetting the */
/* bitmap using outline */
//if ( !bitmap->rows || !bitmap->pitch )
//{
// FT_ERROR(( "ft_sdf_render: failed to preset bitmap\n" ));
// error = FT_THROW( Cannot_Render_Glyph );
// goto Exit;
//} Would it be possible and/or favorable to modify the FreeType source within the megasource (assuming this small change does not cause any other problems)? Also, I don't see how supporting Ubuntu 20.04 is relevant to this issue since the 12.x branch of the megasource already includes FreeType 2.12.0. |
Yeah that'd do it, love creates a glyph of the space character in Font constructors. It might be possible to modify TrueTypeRasterizer.cpp so it detects glyphs which would have invisible/zero-size bitmaps and has an alternate codepath that doesn't try rasterizing those. Or sdf support could only be turned on at runtime when a newer version of freetype with that fix is used - although I'm hesitant about doing that because of the versions used in package managers.
I don't think that's a good idea, it adds a burden for us to maintain the patch and it would only apply to one platform out of 5 (see below).
As I said (and is said in the readmes), megasource is primarily for Windows. It's not used for official builds on other platforms. Linux AppImages use a different build process, and Linux distro-maintained love packages use shared system dependencies which are not under our control at all. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's working for me in Windows now, thanks!
I think the hinting stuff still needs to be figured out, but aside from that it looks good. It's too bad Freetype doesn't have an option for a more advanced SDF technique since single-value SDFs can have some noticeable visual issues around corners of letters.
@@ -236,6 +247,7 @@ FT_UInt TrueTypeRasterizer::hintingToLoadOption(Hinting hint) | |||
return FT_LOAD_TARGET_LIGHT; | |||
case HINTING_MONO: | |||
return FT_LOAD_TARGET_MONO; | |||
case HINTING_SDF: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SDF freetype glyphs are still affected by whatever hinting load mode is being used (if I change the code to use different ones than NO_HINTING
here I get different visual results).
I don't know whether it makes sense to expose SDF versus normal glyph generation as a separate option from the hinting mode, but either way making it always use NO_HINTING
probably isn't desirable since it can stop things from looking like how the font author intended.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Conceptually the hinting mode is a different thing from SDF versus bitmap rasterized glyphs, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assumed that because SDF rendering is made to be scalable, hinting would become irrelevant since the source and target pixel grids will almost certainly not match up.
Taking this into account, I chose to use NO_HINTING
because it preserves the exact shape of the text, which is optimal for dynamic scaling.
Also, the resulting shape of the text (and appearance of "visual issues") depends mostly on the texture filtering settings and the original size the font was initialized at.
I understand that there are other methods more advanced than pure SDF rendering, such as MSDF which preserves sharp corners in fonts, but I think that's out of the scope of this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because SDF rendering is made to be scalable, hinting would become irrelevant
I think it's still relevant because it combines with the input font size to affect the look of the SDF glyphs. Maybe some people might even want mono hinting with it. In this code example you can see the 'e' renders differently with normal hinting (red) versus SDF + no hinting (green), whereas SDF + normal hinting matches the non-SDF version more closely.
font1 = love.graphics.newFont(20, "sdf")
font2 = love.graphics.newFont(20)
shader = love.graphics.newShader[[
vec4 effect(vec4 vcolor, Image tex, vec2 tc, vec2 pc)
{
float dist = Texel(tex, tc).a;
float edgeWidth = 1 * length(vec2(dFdx(dist), dFdy(dist)));
float edgeDistance = 0.5;
float opacity = smoothstep(edgeDistance - edgeWidth, edgeDistance + edgeWidth, dist);
vcolor.a *= opacity;
return vcolor;
}
]]
function love.draw()
love.graphics.setShader()
love.graphics.setColor(1, 0, 0)
love.graphics.print("Hello World", font2, 10, 10, 0, 1)
love.graphics.setShader(shader)
love.graphics.setColor(0, 1, 0)
love.graphics.print("Hello World", font1, 10, 10, 0, 1)
end
I think that's out of the scope of this PR.
I agree, I was just commenting that it's not a totally perfect solution to a general SDF font request (the original github issue), although it's still a nice feature to have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it combines with the input font size to affect the look of the SDF glyphs. Maybe some people might even want mono hinting with it.
I hadn't even tested that before. Then instead of adding "sdf" as a HintingMode, what do you suggest? Combining it with the existing HintingModes ("sdfnormal", "sdfmono", etc.)? Adding it as another parameter to love.graphics.newFont
? Or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably add it as a separate parameter. However the parameter list is getting kind of long so maybe it should be turned into a settings table (like what newImage etc. have) instead. Since that's sort of a separate change I could do that without the sdf support part some time this week.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the parameter list is getting kind of long so maybe it should be turned into a settings table (like what newImage etc. have) instead.
I've done this in 5a0a6a1.
For the sdf setting, I think you'll just want to have a sdf
boolean in the Settings
struct (defaulted to false), and the table part of luax_checktruetypesettings
would be modified to check for a sdf
boolean field (also defaulted to false).
The |
I was having trouble building this with the prebuilt FreeType macOS framework, I'm not sure why, so I had to build it myself to make sure this built correctly.