Closed jean-airoldie closed 1 year ago
After some experimentation, I find that this issue only happen with font size below or equal to 12 points using the ubuntu ttf font. So this might be anti-aliasing limitation rather than a bug.
Nevermind, this appears to be a bug. If I purposely use a wider rasterizer, you can see the smudging extend well beyond the end of the glyph itself.
Here's an example of a normal vs. smudged character:
You can clearly see that gray smudge extending to the full width of the image.
Digging up a ubuntu.ttf font and using it with the image example (tweaked to similar settings) I see no such issue.
When I observe the outline coords the _abglyph image example computes, for example the letter t
. I get
reset: 5x9
line: (1.0588459,2.2016497) (3.225665,2.2016497)
line: (3.225665,2.2016497) (3.225665,3.059578)
line: (3.225665,3.059578) (1.0588459,3.059578)
line: (1.0588459,3.059578) (1.0588459,5.699358)
quad: (1.0588459,5.699358) (1.0588459,6.1283226) (1.1248404,6.408799)
quad: (1.1248404,6.408799) (1.1908349,6.6892757) (1.322824,6.8487625)
quad: (1.322824,6.8487625) (1.454813,7.0082493) (1.6527963,7.0742435)
quad: (1.6527963,7.0742435) (1.85078,7.1402383) (2.114758,7.1402383)
quad: (2.114758,7.1402383) (2.5767193,7.1402383) (2.857196,7.035747)
quad: (2.857196,7.035747) (3.1376727,6.9312553) (3.2476635,6.8872595)
line: (3.2476635,6.8872595) (3.4456472,7.7341886)
quad: (3.4456472,7.7341886) (3.2916598,7.811182) (2.906692,7.9266725)
quad: (2.906692,7.9266725) (2.521724,8.042163) (2.0267653,8.042163)
quad: (2.0267653,8.042163) (1.4438138,8.042163) (1.0643454,7.8936753)
quad: (1.0643454,7.8936753) (0.68487704,7.7451878) (0.45389628,7.4482126)
quad: (0.45389628,7.4482126) (0.22291553,7.1512375) (0.12942332,6.7167735)
quad: (0.12942332,6.7167735) (0.03593111,6.2823095) (0.03593111,5.710357)
line: (0.03593111,5.710357) (0.03593111,0.60678244)
line: (0.03593111,0.60678244) (1.0588459,0.4307971)
line: (1.0588459,0.4307971) (1.0588459,2.2016497)
line: (1.0588459,2.2016497) (1.0588459,2.2016497)
Plugging that into your example mostly renders fine. (Though I would suggest you only set the alpha pixel value with the rasterizer coverage rather than r, g, b and alpha as you are doing as this will over-darken non-100% covered areas. E.g. use [255, 255, 255, coverage]
for each pixel.).
This suggests the issue is with your outline coords.
Digging up a ubuntu.ttf font and using it with the image example (tweaked to similar settings) I see no such issue.
We use a different offset to do the compuation. From what i recall of your implementation you use a rounded x and y offset https://github.com/alexheretic/ab-glyph/blob/7491c2be4e49ea18d0de53e226810cdd529d211d/glyph/src/outlined.rs#L94
...but In my own implementation I use an exact x offset and a rounded y offset because it results in sharper text. So obviously your coordinates will differ from mine.
Plugging that into your example mostly renders fine. (Though I would suggest you only set the alpha pixel value with the rasterizer coverage rather than r, g, b and alpha as you are doing as this will over-darken non-100% covered areas. E.g. use [255, 255, 255, coverage] for each pixel.).
Noted.
This suggests the issue is with your outline coords.
How could the outline coordinates that I've provited result in this smudging that exceeds beyond the coordinates? I will try to find the specific command that causes this to happen.
I think dodgy outlines can do that, if the outside becomes the inside. ab_glyph-rasterizer is quite low-level, it needs a well formed outline to work properly.
Regarding rounding, ab_glyph uses exact subpixel draw offsets. Out of interest, where are you seeing this rounding?
On Tue, 28 Mar 2023, 02:36 jean-airoldie, @.***> wrote:
Digging up a ubuntu.ttf font and using it with the image example (tweaked to similar settings) I see no such issue.
We use a different offset to do the compuation. From what i recall of your implementation you use a rounded x and y offset
...but In my own implementation I use an exact x offset and a rounded y offset because it results in sharper text. So obviously your coordinates will differ from mine.
Plugging that into your example mostly renders fine. (Though I would suggest you only set the alpha pixel value with the rasterizer coverage rather than r, g, b and alpha as you are doing as this will over-darken non-100% covered areas. E.g. use [255, 255, 255, coverage] for each pixel.).
Noted.
This suggests the issue is with your outline coords.
How could the outline coordinates that I've provited result in this smudging that exceeds beyond the coordinates? I will try to find the specific command that causes this to happen.
— Reply to this email directly, view it on GitHub https://github.com/alexheretic/ab-glyph/issues/77#issuecomment-1486082615, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARZHV3KGIW6VMJRODLMJY3W6I6BRANCNFSM6AAAAAAWJY6TYQ . You are receiving this because you commented.Message ID: @.***>
So the callgraph looks like this:
https://github.com/alexheretic/ab-glyph/blob/7491c2be4e49ea18d0de53e226810cdd529d211d/glyph/src/outlined.rs#L94 https://github.com/alexheretic/ab-glyph/blob/7491c2be4e49ea18d0de53e226810cdd529d211d/glyph/src/outlined.rs#L57 https://github.com/alexheretic/ab-glyph/blob/7491c2be4e49ea18d0de53e226810cdd529d211d/glyph/src/outlined.rs#L18
Where use you this
Now in my use case the position of the glyph is always on the pixel boudary so x_fract & x_trunc becomes zero, so its just a floor & ceiling rounding.
If i contrast with my implementation, is use a similar rounding method to determine the size of the rasterizer, but the offset i use when I scale the font coordinates (pos.x * scale + offset) is exact. This results in sharper text.
In practice I use an exact x offset and a rounded y offset because most fonts are not pixel perfect, and using an exact y results in fonts of visibly mismatched vertical height. Hopefully this is somewhat clear.
I'm talking about this offset specifically:
I think dodgy outlines can do that, if the outside becomes the inside. ab_glyph-rasterizer is quite low-level, it needs a well formed outline to work properly.
Since I'm using an exact offset, my coordinates often start or stop at 0, so I'm guessing this is what can cause this malformed outline. I'll try to isolate.
I have isolated the cause of the issue:
$ diff fonts/ubuntu_t_12pts.txt fonts/ubuntu_t_12pts_minimized.txt
< quad: (0.090990186,6.827832) (0.0,6.4049954) (0.0,5.8483496)
< line: (0.0,5.8483496) (0.0,0.88135576)
< line: (0.0,0.88135576) (0.9955397,0.71008015)
---
> quad: (0.090990186,6.827832) (0.00001,6.4049954) (0.00001,5.8483496)
> line: (0.00001,5.8483496) (0.00001,0.88135576)
> line: (0.00001,0.88135576) (0.9955397,0.71008015)
fonts/ubuntu_t_12pts.txt
fonts/ubuntu_t_12pts_minimized.txt
It seems that for some reason using exactly zero in the coordinates causes this issue.
That's the calculation of the pixel bounds, not the offset. Of course the pixel bounds are integers, the rasterizer works on a w*h integer coverage grid. The offset is simply made relative to the pixel bounds, their subpixel positions aren't rounded at all.
On Tue, 28 Mar 2023, 03:11 jean-airoldie, @.***> wrote:
I think dodgy outlines can do that, if the outside becomes the inside. ab_glyph-rasterizer is quite low-level, it needs a well formed outline to work properly.
Since I'm using an exact offset, my coordinates often start or stop at 0, so I'm guessing this is what can cause this malformed outline. I'll try to isolate.
— Reply to this email directly, view it on GitHub https://github.com/alexheretic/ab-glyph/issues/77#issuecomment-1486104818, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARZHV5ZQS6MARTTXL4WEL3W6JCENANCNFSM6AAAAAAWJY6TYQ . You are receiving this because you commented.Message ID: @.***>
The offset is simply made relative to the pixel bounds, their subpixel positions aren't rounded at all.
You use the pixel bound calculation as your offset that you use when scaling up.
This is rounded. https://github.com/alexheretic/ab-glyph/blob/7491c2be4e49ea18d0de53e226810cdd529d211d/glyph/src/outlined.rs#L94
Therefore this is also rounded https://github.com/alexheretic/ab-glyph/blob/7491c2be4e49ea18d0de53e226810cdd529d211d/glyph/src/outlined.rs#L116
I don't do that, i use the exact pixel bounds calculated when oulining the glyph therefore this result in a different outline. Anyway this is besides the point.
But it isn't rounded. It is a difference, between the absolute position and the pixel bounds. So it is an exact position relative to the coverage grid. Rounding is a kind of data loss and that isn't happening here.
This maybe is important because if you are not calculating the whole-pixel bounds properly you are probably not using ab_glyph_rasterizer correctly. It renders on a grid of whole-pixels that should be 1-to-1 with screen pixels. The min size is the exact bounds widened to an integer w & h. So if you're using the non-int exact-bounds to calculate the offset here then the outline positions will probably be wrong. All coords during rasterization are relative to the whole-pixel bounds of the Rasterizer.
On Tue, 28 Mar 2023, 03:22 jean-airoldie, @.***> wrote:
The offset is simply made relative to the pixel bounds, their subpixel positions aren't rounded at all.
You use the pixel bound calculation as your offset that you use when scaling up.
This is rounded.
Therefore this is also rounded
— Reply to this email directly, view it on GitHub https://github.com/alexheretic/ab-glyph/issues/77#issuecomment-1486112024, or unsubscribe https://github.com/notifications/unsubscribe-auth/AARZHV2EAYCRHTFK25F7WITW6JDQBANCNFSM6AAAAAAWJY6TYQ . You are receiving this because you commented.Message ID: @.***>
The reason you haven't experienced my issue before, is because your (x, y) coordinates that you obtain after scaling are not aligned with a pixel boundary. If they were aligned, then some of your (x, y) coordinates you be 0.0
. If we look back at the ubuntu ttf that you used, it produced the following commands:
reset: 5x9
line: (1.0588459,2.2016497) (3.225665,2.2016497)
line: (3.225665,2.2016497) (3.225665,3.059578)
line: (3.225665,3.059578) (1.0588459,3.059578)
line: (1.0588459,3.059578) (1.0588459,5.699358)
quad: (1.0588459,5.699358) (1.0588459,6.1283226) (1.1248404,6.408799)
quad: (1.1248404,6.408799) (1.1908349,6.6892757) (1.322824,6.8487625)
quad: (1.322824,6.8487625) (1.454813,7.0082493) (1.6527963,7.0742435)
quad: (1.6527963,7.0742435) (1.85078,7.1402383) (2.114758,7.1402383)
quad: (2.114758,7.1402383) (2.5767193,7.1402383) (2.857196,7.035747)
quad: (2.857196,7.035747) (3.1376727,6.9312553) (3.2476635,6.8872595)
line: (3.2476635,6.8872595) (3.4456472,7.7341886)
quad: (3.4456472,7.7341886) (3.2916598,7.811182) (2.906692,7.9266725)
quad: (2.906692,7.9266725) (2.521724,8.042163) (2.0267653,8.042163)
quad: (2.0267653,8.042163) (1.4438138,8.042163) (1.0643454,7.8936753)
quad: (1.0643454,7.8936753) (0.68487704,7.7451878) (0.45389628,7.4482126)
quad: (0.45389628,7.4482126) (0.22291553,7.1512375) (0.12942332,6.7167735)
quad: (0.12942332,6.7167735) (0.03593111,6.2823095) (0.03593111,5.710357)
line: (0.03593111,5.710357) (0.03593111,0.60678244)
line: (0.03593111,0.60678244) (1.0588459,0.4307971)
line: (1.0588459,0.4307971) (1.0588459,2.2016497)
line: (1.0588459,2.2016497) (1.0588459,2.2016497)
You can see that at no point is there a 0.0
coordinate for either the x
or the y
axis. If you used an exact offset for either the x or the y axis, then at least some of the points would be 0.0
.
Conceptually using an exact offset here would be the equivalent of starting the outline at the point (0.0, 0.0)
instead of whatever point the original author intended (human error). The exact offset in this case would be calculated by using the glyph bounding box exactly without rounding.
So In my implementation I use two sets of bounds, exact and rounded. I use the exact bounds as the offset for the scale * x + offset
calculation and I use the rounded ones to determine the size of the rasterizer. This results in crisper text.
Anyway,
Thanks for your time, I'll fix this issue some other way.
Hi,
I wrote a small 2d lib which implements font rendering. I use
ab_glyph_rasterizer
to rasterize TrueType fonts, which works pretty well. However under specifc combinations of font size and font type I get a weird issue where the font doesn't rasterize properly and it create a smudging effect.I have included a repository that replicates this issue. The README explains how it works in details.
In context, it results in these kinds of visual artifacts: