https://rust-skia.github.io/doc/skia_safe/canvas/struct.Canv...
Looks like it would have been a lot easier if this existed back then. (haven't worked on the site for 5+ years)
We got acqui-hired in 2015 and the product was shut down, but in hindsight I wish we'd open sourced at least those libraries.
It was created by Apple as a wrapper for CoreGraphics back around Mac OS X Tiger 10.4. (IIRC, Canvas even debuted in Apple's Dashboard widgets rather than Safari? I'm not 100% sure.)
I remember writing my own Canvas implementation around 2008-2009 using JavaScriptCore and CoreGraphics. It took maybe two days. I used it for a video application where JS plugins needed to render 2D graphics but I couldn't provide a browser engine because that would have been too slow and unpredictable for render functions that get called in the video render loop.
Also since this was a video application running custom scripts written specifically for that host app, there wasn't a big worry about exact compatibility with any other Canvas-using code.
Anyway, here's the old code that doesn't look like there's anything interesting going on:
https://github.com/pojala/lacqit/blob/main/Lacqit/LQJSBridge...
Looks like I misremembered — it's using Cairo rather than CoreGraphics. I don't remember why that was.
Cairo?
Of course there are 2D drawing libraries on the major platforms (and CoreGraphics and Direct2D are very different, there’s also GDI+), but it was a weird question to start: what’s the use of a portable library. But furthermore, skia is not just a portability wrapper.
Skia is useful because it provides a powerful, performance oriented common target 2D drawing library, and it is more than a lowest common denominator wrapper.
It could be Qt, SDL, SFML, or anything else with similar goals.
We also need to generate vector PDFs serverside — so we use a node library that speaks the HTML Canvas API and can generate PDFs. This way the result is exactly the same as the rendered sheet music in the web browser. Nice!
The upshot is: this kind of library allows for code reuse in non-browser contexts.
Our graphics engine works with Canvas API instructions — like "draw a line from point (A,B) to (C,D)." This API is small enough and low-level enough that it can also generate pristine vector output.
That's in fact one of the features of Skia Canvas (vector output in PDF and SVG).
I am not sure if it would be viable to use for thousands of PDF generation per minute but it worked great. I wasted a lot of time trying to find a good lib for HTML->PDF and they all kinda sucked in different ways. The only downside is that the chrome PDF api doesn't have a way to generate a table of contents with page numbers.
Skia is the most modern library if you want to render shapes onto an image/surface.
According to the example `import {Window} from 'skia-canvas'` you can also use it to draw onto a spawned window on a desktop.
One the one hand this is lower-level. On the other hand, I've used puppeteer as my 2D graphics library. I get Canvas 2D, and WebGL, and WebGPU, and all of HTML/CSS (so Text with effects, background images, CSS transforms, etc). I get image and video loading. I can then use the screenshot functionality to make an image of whatever I put together. It's overkill, but for my use case I don't care. It works, it's cross platform, it solves my problem.
We had a rendering engine backed by canvas, so it was easy to just redirect it to this to get the file output. (not everything was visible on the user's screen all the time so couldn't just save from the client)
It'll also be interesting to see how well this slots into things like VS Code for live-rendering canvas code (or code that has a translation layer for running on a web canvas)
FWIW, node ships with a WASM runtime. See https://nodejs.org/en/learn/getting-started/nodejs-with-weba...
They seem similar?
https://jimp-dev.github.io/jimp/
Maybe there are some killer features?
That's not necessarily better or worse, it's just potentially helpful if you've got lots of Canvas-based code lying around you want to run outside a browser environment.
That library only resizes and does other basic pixel level operations.
Skia is for drawing vector graphics.
What do you mean by "vector graphics"?
Both Canvas and ImageData work only with pixels.
Is it a fork of Skia?
Does it depend on Skia?
Did somebody look at a design diagram of Skia and redo the whole thing from scratch?
Did they read about Skia in a blogpost and get the gist of it?
[1] https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API
[2] The things that jump out to me as "exciting extensions" beyond the Api include: multiline text and text decoration (underlines!)[3]; perspective effects[4]; and Path2D boolean and filter operations[5].
[3] https://skia-canvas.org/api/context#textdecoration
Skia is the graphics engine used by Chrome and Android to render everything: https://skia.org/
This one
The missing C API for Skia is most likely why Cairo is still alive.
It was my first open-source project, released about 3 years ago.
I had plans to also expose WebGL, audio, etc and make it a viable platform for Javascript-based games on desktop.
Life and other projects happened instead, and development was discontinued. Happy to see this project also making Canvas accessible outside the browser!
In a drawing tool / library?
That's just asking for trouble. By spec, SVG allows for XXE shenanigans. I'd rather not worry that any image file I process might exfiltrate my data.
The idea was to have TCP sockets and Websockets to enable that.
Basically, have the same APIs you're familiar with in a Browser, but in a much smaller package that you can ship independently of the Browser.
(this is very similar to Electron)
> but also embeds v8 for a very small runtime instead of using Node.
By how much does embedding just V8 instead of using Node.js decrease the binary size? Node.js uses V8, does most of Node's binary size come from its runtime and not V8?
I tried browsing the website and GitHub repo to find how many kBs or MBs typically is a Window.js binary, but didn't find an answer.
https://github.com/windowjs/windowjs/releases
About 8 MiB in the end. Note that these builds have a binary trimmed by UPX.
Using the Window.js approach of embedding V8, instead of using a windowing library + a Skia Canvas library in Node.js ─really makes sense if you would like to keep the binary size minimally small and only pay for the libraries/modules you actually pull in and use, instead of having them statically linked in the binary by default. For example, an offline app/game that doesn't use the network doesn't need to have a "net" or "http" module in the binary. These may be bad examples though, I don't know how much do those Node runtime modules constitute out of the final Node binary, it may be an insignificant fraction.
Check the docs and examples
- canvaskit-wasm from the skia project - I don't think it's gpu-accelerated: https://github.com/google/skia/tree/main/modules/canvaskit/n...
- @napi-rs/canvas - This is the fastest binding: https://github.com/Brooooooklyn/canvas?tab=readme-ov-file#pe...
- node-canvas - Uses Cairo instead of Skia: https://github.com/Automattic/node-canvas
It can be added by doing "deno add npm:skia-canvas", adding "nodeModulesDir: auto" to the deno.json, and doing a "deno install --allow-scripts".