Show HN: Skia-canvas, a browserless implementation of the Canvas API for Node.js
github.com
github.com
The downside is that it's slower than Skia [1].
But, it should be possible to modify skia-canvas to work with raqote. The JS API would stay the same.
It also doesn't appear to support Windows yet, whereas node-canvas does.
There's probably other differences, e.g. performance, size, etc. but you'd have to measure them.
Check the demo by running 'cargo run --example demo'.
It's a really good way to understand 2d graphics.
I'm asking because usually Skia produces different aliasing results on different platforms (eg: Windows vs macOS).
On Windows, for example, Skia will render text closer to Direct2D/DirectWrite. On MacOS to CoreText.
For the reference, here is rendering of the same UI (HTML/CSS) in Sciter using Direct2D (left) and Skia/OpenGl (right):
https://sciter.com/wp-content/uploads/2020/09/d2d-vs-skia.pn...
Maybe that's why Chrome looks so different on both platforms.
So what you're saying is that Skia changes the aliasing to look like the platform it's running on?
Damn, I wish I could make Chrome on Windows render text like it does macOS.
Here is MacOS rendering https://sciter.com/wp-content/uploads/2020/09/mac-os-front.p...
It depends. Skia can either be used as software or GPU renderer.
GPU AA rendering can slightly differs when using MSAA. When MSAA is turned on, Skia has different path renderer strategies (that could be CPU-based, like SDF, or GPU-based using coverage counting). In that case (msaa turned off), AA result should be identical on all platforms, at the cost of performance.
Worth keeping in mind that what Skia's GPU backend decides to do depends on GPU features, and sometimes on GPU workarounds. There's no guaranteed way to force it to render identically on all platforms short of something like swiftshader.
I thought GrGlCaps was supposed to fallback most of the time to equivalents. Also thought that golden images baseline where pixel tested against a large set of different hardware.
But yeah, Skia blacklists MSAA for Intel GPU, so if you opt-in for sampling, you're not guaranted it's going to be enabled and therefore observe differences
I ended up using puppeteer[2]. Would love to switch to `skia-canvas`, however `ctx.measureFont` doesn't seem to work correctly yet. Measuring cap `M` produces positive `actualBoundingBoxDescent`, although `M` should sit comfortably on top of baseline.
[1]: https://github.com/adambisek/string-pixel-width
[2]: https://github.com/shikijs/shiki/blob/master/packages/render...
I thought browser canvas was a completely raster tool? What if I drew a million lines onto skia-canvas -- which is something you can do in a browser canvas -- would that result in a huge stack of vector operations getting saved somewhere for the possibility of future vector export?
And true - on Linux a X11 frame buffer DISPLAY is required, but I would still consider this to be headless. On other platforms, it should be truly headless. (I could be sorely mistaken)
See this issue, Angle can support headless completely with vulkan backend, but progress is BlockedOn angleproject.
That said, the Angle version we use is decently old. If we updated it, we would be able to implement WebGL 2 (OpenGL ES 3.0) support. Unfortunately, it's no easy feat to update and integrate the latest Angle, and the project is more-or-less in maintenance mode until someone else comes to take on the task (the project's been revived several times before, so not totally unimaginable!)
[1] https://www.khronos.org/registry/webgl/conformance-suites/1....
https://www.npmjs.com/package/canvaskit-wasm
Can be used with node as well
Not that that would make much sense. I’ve not been very successful at understanding what kind of problem canvaskit is trying to solve
What I am trying to do is the same as it was more than a year ago (https://news.ycombinator.com/item?id=20339574): A tile based, web based view with prerendered image tiles from the server and on the fly rendered tiles on the client. Ideally the client side rendering is super fast, whether that means gpu is enough or multi threaded cpu I don’t know yet
So what I understand so far is that I can’t have anything multithreaded (yet?) in the web client and probably native canvas is the most performant. Even canvaskit with webgl won’t reach that performance (not sure here)
Otoh canvaskit could possibly be used in other browsers if they don’t natively implement canvas via skia itself to minimize render diffs
And lastly this project here could be the backend renderer instead of either headless browser via canvas api (hacky) or canvaskit in node (slow because cpu only)
But none of these offer and kind of performance increase over native canvas which is limited to single thread because of spectre and meltdown
Wasm also does have some overhead too; some of that will get better with upcoming changes; at least wasm-SIMD support and threads are both only available in some environments.
But don't get me wrong, I'm certainly not suggesting the skia-wasm project is pointless, there's just trade-offs here.
So far I’ve mostly heard about porting apps that require native skia to the web. But that wouldn’t explain why google spent all that effort building a canvas compatible api and didn’t just stick to the skia api
I was hoping that skia would be more efficient in this tiling context where rendering tile images and putting them together in the final view isn’t that great with browser canvas. But I realize now that lack of multithreaded tile rendering means it doesn’t matter much anyways whether image tiles can be copied to another image quickly or not
Now I have a feeling that webgl might be a necessary step for me to look at.
This project has been dormant for a year now and I have to start again. Not an easy area to navigate with all those different and not necessarily comparable solutions
Last I played around with canvaskit I found the performance in the browser to be better than native canvas for certain things but worse for most. Why that is or if this follows any rules I don’t know. Perhaps I’m also mistaken
Usually wasm is twice slower than native code: https://www.usenix.org/conference/atc19/presentation/jangda
WebAssembly is essentially a bytecode that needs to be JITted before running. That's pretty much the same situation as with Java, you may have comparable performance but usually comparable Java code runs slower that native.
https://github.com/samizdatco/skia-canvas/blob/master/packag...
If the benefit is to use the drawing API in a Node context outside of a server environment, that makes more sense to me.
We had an application where a canvas-based editor was used to create diagrams, and then these diagrams were saved to a library. We wanted to have each saved diagram to have a preview image to better visually distinguish between them while scrolling. The ability to render a png on the server from the canvas would have saved us a lot of trouble.
15 years ago I was driving GD and ImageMagick from PHP to render things like staff ID cards, barcode labels for things, etc.
It was trivial to write a script that would render something quickly and just output raw image data, so you could <img src="whatever.php?name=Joe&department=Meat" /> and the image would be dynamically created and sent with the right MIME type.
Plenty of great use cases for this.
It could start with something simple like tic-tac-toe and only two players. A player would tell the app a number between 1 and 9 corresponding to the place he/she chose. Then the server/bot would send the updated image to the conversation.
What do you think? :)
As such, the backend would do the heavy lifting of rendering the board, and send the rendered board back into the message group.
Of course one might be able to use emoji or text as a representation of said state if the game allows for it.
It was so much easier to build the animation in canvas for the site and just replay it to get frames for a video on the server than to try to make the video in some other environment and then show it in the browser.
There are plenty of reasons to want to generate an image dynamically on a server. Dynamic image resizing to fit client requirements is one that immediately comes to mind.
This would be really useful for similar modern projects.
However I also needed to implement a server-side version of it that prerendered all the cards to PNG so that they're browsable without having clients consume excessive cpu/battery. Doing it using a separate codebase would have been hell to reconcile. Hence node-canvas.
* visitors counter
* request IP
* game stats in forum signature (implemented this with gd and ruby)