-
-
Notifications
You must be signed in to change notification settings - Fork 72
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
Fix Font Hinting #295
Fix Font Hinting #295
Conversation
/// </para> | ||
/// </summary> | ||
private static readonly string[] BadHintList = { "Arial", "Times New Roman", "Tahoma", "Palatino Linotype", "Segoe UI" }; | ||
private bool? shouldHint; |
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.
There's a LOT of knowledge in this document, unfortunately I couldn't find a way to get these fonts to hint well. They're all older ones that have known issues with hinting so to save effort I've disabled hinting of them for now.
http://rastertragedy.com/RTRCh4.htm#Sec1
Every single modern font I tested seems to work really well.
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.
is there any metadata in the font we can use to determine if we should enable hinting? some created date maybe or so versioning flag difference? anything to save just hard coding a set of font names.
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.
Unfortunately not. 😔
There's some guidance for how to actually mitigate the issues I saw but I spent a few days and couldn't translate it into code. Nor could I find reference in FreeType that provided a complete workaround matching that guidance.
Accordingly I was looking for an approach that combines the advantages of overscaling before constraint application with the “safety” of overscaling after constraint application. To do so I “jury rigged” the rasterizer to dynamically re-interpret all rounding instructions to mean “round to sample boundary” if the rendering method is ClearType and if the direction of the projection vector p is not parallel to the long side of the LCD sub-pixels, else to keep the meaning “round to pixel boundary” as before:
- Apply contextually interpreted constraints (“hints”) to outlines
- Overscale constrained outlines in x-direction by 6x
- Sample overscaled constrained outlines into overscaled bitmaps
- Apply anti-aliasing filter to downsample overscaled bitmaps
Semantically, the two interpretations of rounding instructions are most similar. In fact, if you consider full-pixel bi-level rendering (colloquially “black-and-white” rendering) as “oversampling” at the rate of one sample per pixel, then the two interpretations are identical. Practically, this approach eliminates the “explosions” and it overcomes the absence of a TrueType instruction that would permit “finer grained” rounding than to the nearest 1/2 of a pixel (cf 4.3.0).
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 do wonder whether we just just try tagging the chap who built the original interpreter to see if he knows how?
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 hate to do this and apologies in advance but @MikePopoloski would you have any insight into how to implement some of these workarounds?
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.
Oh hello. No sorry, I haven't thought much about font rendering in like 7 years. Glad someone is making use of the interpreter though, it's a neat bit of code and there aren't (or at least weren't when I built it) too many open source implementations of a TT interpreter.
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.
Thanks for replying! That was a bit of a hit and hope tagging you like that.
I think there's very few people in the world who actually understand the TT interpreter. I've yet to find an implementation other than yours in the .NET ecosystem and elsewhere there just appears to be using Freetype.
I'll persevere though and continue to do my own research. Fongers crossed I can figure it all out. It's an interesting challenge!
Codecov Report
@@ Coverage Diff @@
## main #295 +/- ##
=====================================
- Coverage 83% 83% -1%
=====================================
Files 222 224 +2
Lines 12281 12299 +18
Branches 1784 1788 +4
=====================================
+ Hits 10272 10279 +7
- Misses 1585 1600 +15
+ Partials 424 420 -4
Flags with carried forward coverage won't be shown. Click here to find out more.
📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
src/SixLabors.Fonts/Tables/TrueType/Hinting/TrueTypeInterpreter.cs
Outdated
Show resolved
Hide resolved
@tocsoft I've cracked it! 🎉 I had a good dig through the FreeType interpreter code and accompanying docs and figured out what they did to get their interpreter working well with legacy fonts. Basically, they never move anything horizontally when hinting at all which fixes most issues then there's a couple of additional tweaks for legacy fonts. No need for lists or targeted hacks - it just works! Here's Tahoma (This was really bad before with odd offsetting of individual glyphs.)
And here's Open Sans
For most fonts there really miniscule difference between What do you think? |
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.
This looks fantastic, congrats on getting it working without the black list.
@tocsoft It gets better. Turns out I had my enum wired back-to-front in GlyphVector and I was oversampling in XY mode not Y. The default output was the best one! I've deleted the oversampling code and changed the enum to |
Prerequisites
Description
Fixes #293 and #294
We were passing the multiplied pixel size when we shouldn't have. Some pre-cleartype fonts don't seem to work all that well so I've internally disabled hinting for them for now.