tdewolff / canvas

Cairo in Go: vector to raster, SVG, PDF, EPS, WASM, OpenGL, Gio, etc.
MIT License
1.5k stars 102 forks source link

lack of font hinting #205

Closed zpl-zak closed 1 year ago

zpl-zak commented 1 year ago

Hi, this is more of a question than a bug report. As mentioned in #204 , we've upgraded our canvas build to the latest version from https://github.com/tdewolff/canvas/commit/6566432f4b20533e6485f52ad8affdddb9c1fd80.

However, we've noticed text or image rendering has changed a bit. We use a rasterizer backend.

I will present two examples that showcase the changes:

1) text appears more pixelated (preview zoomed-in to highlight the issue better) msedge_qLZwy8kn4X msedge_3ERKHu76OU

2) images don't appear blurry anymore

OLD slack_E0eWxU084E

NEW slack_Y5fpT3HVBB

While the second case is favorable for images of barcodes etc., the 1st case does cause some text readability issues. Initially, we thought this would be related to the #204 issue (as we first noticed this occurrence in the text itself), but it appears some other factors are at play.

Do you know which direction we should head and what to look at so we can better understand what to tweak to improve the results?

Thanks!

tdewolff commented 1 year ago

Thanks for raising the issue. This may be related to how quadratic/cubic beziers are flattened and may indicate a bug. The first image of text shows that the character glyphs have some bulky parts and some thin parts. The image case I don't know what could have caused that. Could you send the code to reproduce both cases (including the font and image) so I can verify?

tdewolff commented 1 year ago

What font did you use?

mufty commented 1 year ago

He's working on an example including code and the font used. Just so you know we are trying to use your library in a bigger project that's all about generating all kinds of images so extracting examples takes bit of time ;)

We used the nodejs canvas wrapper before but it was a bit slow and overall kinda crap so switching to something quicker like this seems to work much better so far.

You are being very helpful so far thank you for that. We might be able to help if you want data from a wide range of rendering different types of elements we can help with that as we do use most if not all element types from canvas and have tests for all of that.

tdewolff commented 1 year ago

Excellent, thank you for the feedback. I'll await his response in order to track down the commit and the bug!

I'm very interested in some help to debug and test all facets of canvas, as well as pain points in using the library or potential improvements. Keep me updated! ;-)

zpl-zak commented 1 year ago

I apologize for the slight delay; I've prepared three examples in a test app.

1) pathIssue_draw is the original test case from #204 kept for reference. 2) unclearText_draw showcases a render of a small light text with some readability issues. 3) kitchensink_draw is a complete example of images we generally render with various fonts, font sizes, and positioning used.

As for the barcode image from the original issue, I could not reproduce it this time when using canvas directly (old commit and new); I don't think canvas has anything to do with the blurriness/aliasing in this case, so I believe we can ignore this one.

I hope this helps; once again, feel free to ask anything, and we can provide more resources.

canvas_bug.zip

EDIT: After some back and forth between commits, the text seems to look the same way, showing that text seems to lack anti-aliasing, which is why some letters appear cut abruptly at such a small DPI.

tdewolff commented 1 year ago

Thank you so much for the elaborate cases! Regarding the unclearText example, this has probably to do with a lack of font hinting capabilities in canvas. While the infrastructure is there, the implementation is lacking still. Font hinting basically involves moving characters individually so that is snaps/fits to pixel lines. This improves results significantly when rasterizing, since the fonts have been designed to work well that way. For this specific example, I note that the stems (vertical lines) of the m in Lorem and the g in adipiscing are disappearing, while stems from L and r in Lorem and the p in ipsum are blurry horizontally. This leads me to believe that horizontal font hinting will resolve this issue.

issue_unclear_text

Regarding the image, this may be a similar problem. When drawing an image and then rasterizing it at a 1:1 scale but translated 0.5px horizontally, this will blur/antialias horizontally when resampling the image when rasterizing. The resampling algorithm uses CatmullRom in https://pkg.go.dev/golang.org/x/image/draw#pkg-variables which is slow but very good according to the description. The other interpolators will most certainly give worse results such as pixel lines disappearing or thickening, but will probably be more crisp. Since this is no longer a problem I will keep it as is, but an idea might be to add an option to select the interpolator manually.

Then regarding the kitchensink example, the bigger font appears blurry both vertically and horizontally (again, hinting I suspect). The smallest font gets cut-off significantly, especially the top rows. This is also probably a lack of font hinting!

issue_kitchensink

I will work on implementing font hinting and keep you updated in this issue!

tdewolff commented 1 year ago

I've added a fix that makes the smaller font much more readable. Nothing to do with font hinting, but the path edges of the characters were cutoff in the rasterizer. Adding more padding to the target pixel raster fixed the issue.

issue_kitchensink

Additionally, the characters in the following example improved as well:

issue_unclear_text

What is left perhaps is some simple vertical "hinting" (or rather, aligning with the pixel grid) to improve sharpness of e.g. the biggest font in the first image that says NO EXCUSES looking at the horizontal lines of the E for example.

tdewolff commented 1 year ago

I've added vertical grid fit (enabled by default) which improves the sharpness of the text lines. I think this solves the issue, let me know how it looks on your end!

issue_kitchensink

issue_unclear_text

zpl-zak commented 1 year ago

Thank you for all the improvements. I will check these changes out tomorrow and let you know.

zpl-zak commented 1 year ago

Thanks again. The text looks great on our side! I will close this issue now, if we happen to spot anything else worth looking at I will let you know, kudos for the changes.