Skip to content

Commit

Permalink
feat: support canvas in drawImage and upgrade canvaskit version (#23)
Browse files Browse the repository at this point in the history
* chore: upgrade canvaskit version

* feat: support canvas in drawImage
  • Loading branch information
DjDeveloperr authored Jan 18, 2022
1 parent baa7688 commit a8c66d4
Show file tree
Hide file tree
Showing 16 changed files with 5,908 additions and 5,873 deletions.
100 changes: 55 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,55 @@
# deno-canvas

Canvas API for Deno, ported from
[canvaskit-wasm (Skia)](https://github.com/google/skia/tree/main/modules/canvaskit).

## Installation

Import from https://deno.land/x/canvas/mod.ts or just import from raw GitHub
URL, https://raw.githubusercontent.com/DjDeveloperr/deno-canvas/master/mod.ts.

## Usage

`mod.ts` provides a default export exposing the complete CanvasKit API, and
other exports from the file are types and utility functions.

```ts
import { createCanvas } from "https://deno.land/x/canvas/mod.ts";
import { serve } from "https://deno.land/std/http/server.ts";

const canvas = createCanvas(200, 200);
const ctx = canvas.getContext("2d");

ctx.fillStyle = "red";
ctx.fillRect(10, 10, 200 - 20, 200 - 20);

await Deno.writeFile("image.png", canvas.toBuffer());
```

And run with `deno run --allow-write filename.ts`.

You can also try this HTTP server example,
https://raw.githubusercontent.com/DjDeveloperr/deno-canvas/master/examples/square.ts

For using images, use `loadImage` method exported from `mod.ts`.

```ts
const image = await loadImage(myURL);
ctx.drawImage(image, x, y);
```

## License

Check [LICENSE](./LICENSE) for more info.

Copyright 2022 © DjDeveloperr
# deno-canvas

Canvas API for Deno, ported from
[canvaskit-wasm (Skia)](https://github.com/google/skia/tree/main/modules/canvaskit).

## Installation

Import from https://deno.land/x/canvas/mod.ts or just import from raw GitHub
URL, https://raw.githubusercontent.com/DjDeveloperr/deno-canvas/master/mod.ts.

## Usage

`mod.ts` provides a default export exposing the complete CanvasKit API, and
other exports from the file are types and utility functions.

```ts
import { createCanvas } from "https://deno.land/x/canvas/mod.ts";
import { serve } from "https://deno.land/std/http/server.ts";

const canvas = createCanvas(200, 200);
const ctx = canvas.getContext("2d");

ctx.fillStyle = "red";
ctx.fillRect(10, 10, 200 - 20, 200 - 20);

await Deno.writeFile("image.png", canvas.toBuffer());
```

And run with `deno run --allow-write filename.ts`.

You can also try this HTTP server example,
https://raw.githubusercontent.com/DjDeveloperr/deno-canvas/master/examples/square.ts

For using images, use `loadImage` method exported from `mod.ts`.

```ts
const image = await loadImage(myURL);
ctx.drawImage(image, x, y);
```

## Limitations

[Just like original canvaskit-wasm, the emulated Canvas has some limitations:](https://github.com/google/skia/tree/main/modules/canvaskit/npm_build#known-issues-with-canvas2d-emulation-layer)

- measureText returns width only and does no shaping. It is only sort of valid
with ASCII letters.
- textAlign is not supported.
- textBaseAlign is not supported.
- fillText does not support the width parameter.

## License

Check [LICENSE](./LICENSE) for more info.

Copyright 2022 © DjDeveloperr
8 changes: 4 additions & 4 deletions deps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export {
decode,
encode,
} from "https://deno.land/std@0.106.0/encoding/base64.ts";
export {
decode,
encode,
} from "https://deno.land/std@0.106.0/encoding/base64.ts";
18 changes: 9 additions & 9 deletions examples/basic.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { createCanvas } from "../mod.ts";

const canvas = createCanvas(200, 200);
const ctx = canvas.getContext("2d");

ctx.fillStyle = "hsl(0, 100%, 50%)";
ctx.fillRect(10, 10, 200 - 20, 200 - 20);

await Deno.writeFile("image.png", canvas.toBuffer());
import { createCanvas } from "../mod.ts";

const canvas = createCanvas(200, 200);
const ctx = canvas.getContext("2d");

ctx.fillStyle = "hsl(0, 100%, 50%)";
ctx.fillRect(10, 10, 200 - 20, 200 - 20);

await Deno.writeFile("image.png", canvas.toBuffer());
76 changes: 0 additions & 76 deletions examples/chart.js

This file was deleted.

52 changes: 0 additions & 52 deletions examples/deploy.jsx

This file was deleted.

46 changes: 28 additions & 18 deletions examples/image.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import { createCanvas, loadImage } from "../mod.ts";

const canvas = createCanvas(200, 200);
const ctx = canvas.getContext("2d");

ctx.fillStyle = "red";
ctx.fillRect(10, 10, 200 - 20, 200 - 20);

const img = await loadImage(
"https://cdn.discordapp.com/emojis/587737413330272291.gif?v=1",
);
ctx.drawImage(img, 100 - img.width() / 2, 100 - img.height() / 2);

const img2 = await loadImage('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAC8UlEQVRIx42V32vVdRjHXx5F3MBld4FWDGXSopoW1brTuwVhRGiwC8HyIhz9wIu6iCQ00uG6UBAJ3am/oNCgWNrCH6PEaDuj5VYzZiPM8ixTtzPa2auLz/f7Pd/za6fnc/F9Ps/n+fV9Ps/7+SyjFrXwHFtpp4NVQIFhxhjkFP/wP2g9WeYR9/i2iPhi+M6TZcPSxs30UgxGm1z0u8hB3omIo0gvzfXMN5IjVvSoekzENS76maUTRtlYy7yDfErJIfWpiN9tJpG/Z6vk6aiOnkcc8ECkeN3f0lGTdcXvRfLlWTSH5LerA5HiicRVWG94w5fFx+0Mkly6Fr1B6WP1/Zpx8Yy6o1zWG5tviCv/g//aVMfBtH9WyoqsDw6yeMUt4m3Ho8M3/cYp77rojJOe9iW/9UJ01uUNDwW+P3TdfJ9F28Rxj4svOG4lLXjWRyIH/erhwBdogW4c8WqS2F7vpgwLTiX8hG0iXnbBB2P9bjiJs34eCZ42Xxb5U/GnZBc6828nS3U4uYL2Hpo4F9XzLe4ta48n+YgHUrt3mOEezpcU2mFuVxKfVMK1acQnPOPz4l4vuVxmiU13etWd3mrgYC4JdclF14mZOJdttLKGOw2wvop9CeqvMQ3AXPA44W3xKxvRl1G++oXIbIZhgNW08jNwkJsNcngIgC5gCGAkw1io/gpywFle49qSDu5nMzDDOPsBxqAbcZc/2iWu9JYfeMScd+r+xNE0HrqhJUzAsA6on0T8Ol9xj39VObhYMi/QEoGpPmgHqhykUJmNb6RYD7SverDGT+xIwTkDTNIXl+h3BlMFO8GxmrfybPj0MVkx0uK13d0J7tbWqMK5qpGWDNW4qaYj3P0iTlSYT7m1aqiWjfX7XPCy2KOeigpboqGKsZ5ggWE6GQV4neWMAo8Cg8BUovIHh3iGX0fpDP1b92k77DaxzXdF3K/OmvPDhk9bfKn9FNIlfdieuG2y8Rwu0bIln/fHaALmGGGMrzld63n/D5IUk9MNidXBAAAAAElFTkSuQmCC')

ctx.drawImage(img2, 0, 0);

await Deno.writeFile("image.png", canvas.toBuffer());
import { createCanvas, loadImage } from "../mod.ts";

const canvas = createCanvas(200, 200);
const ctx = canvas.getContext("2d");

ctx.fillStyle = "red";
ctx.fillRect(10, 10, 200 - 20, 200 - 20);

const img = await loadImage(
"https://cdn.discordapp.com/emojis/587737413330272291.gif?v=1",
);
ctx.drawImage(img, 100 - img.width() / 2, 100 - img.height() / 2);

const canvas2 = createCanvas(200, 200);
const ctx2 = canvas2.getContext("2d");

const img2 = await loadImage(
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAC8UlEQVRIx42V32vVdRjHXx5F3MBld4FWDGXSopoW1brTuwVhRGiwC8HyIhz9wIu6iCQ00uG6UBAJ3am/oNCgWNrCH6PEaDuj5VYzZiPM8ixTtzPa2auLz/f7Pd/za6fnc/F9Ps/n+fV9Ps/7+SyjFrXwHFtpp4NVQIFhxhjkFP/wP2g9WeYR9/i2iPhi+M6TZcPSxs30UgxGm1z0u8hB3omIo0gvzfXMN5IjVvSoekzENS76maUTRtlYy7yDfErJIfWpiN9tJpG/Z6vk6aiOnkcc8ECkeN3f0lGTdcXvRfLlWTSH5LerA5HiicRVWG94w5fFx+0Mkly6Fr1B6WP1/Zpx8Yy6o1zWG5tviCv/g//aVMfBtH9WyoqsDw6yeMUt4m3Ho8M3/cYp77rojJOe9iW/9UJ01uUNDwW+P3TdfJ9F28Rxj4svOG4lLXjWRyIH/erhwBdogW4c8WqS2F7vpgwLTiX8hG0iXnbBB2P9bjiJs34eCZ42Xxb5U/GnZBc6828nS3U4uYL2Hpo4F9XzLe4ta48n+YgHUrt3mOEezpcU2mFuVxKfVMK1acQnPOPz4l4vuVxmiU13etWd3mrgYC4JdclF14mZOJdttLKGOw2wvop9CeqvMQ3AXPA44W3xKxvRl1G++oXIbIZhgNW08jNwkJsNcngIgC5gCGAkw1io/gpywFle49qSDu5nMzDDOPsBxqAbcZc/2iWu9JYfeMScd+r+xNE0HrqhJUzAsA6on0T8Ol9xj39VObhYMi/QEoGpPmgHqhykUJmNb6RYD7SverDGT+xIwTkDTNIXl+h3BlMFO8GxmrfybPj0MVkx0uK13d0J7tbWqMK5qpGWDNW4qaYj3P0iTlSYT7m1aqiWjfX7XPCy2KOeigpboqGKsZ5ggWE6GQV4neWMAo8Cg8BUovIHh3iGX0fpDP1b92k77DaxzXdF3K/OmvPDhk9bfKn9FNIlfdieuG2y8Rwu0bIln/fHaALmGGGMrzld63n/D5IUk9MNidXBAAAAAElFTkSuQmCC",
);

ctx2.drawImage(img2, 0, 0);
ctx.drawImage(canvas2, 0, 0);

await Deno.writeFile("image.png", canvas.toBuffer());

// Explicitly just exit because canvaskit has some background cleanup
// going on.
Deno.exit();
14 changes: 7 additions & 7 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { init } from "./src/canvas.ts";

const canvas = await init();

export { canvas };
export default canvas;
export * from "./src/canvas.ts";
import { init } from "./src/canvas.ts";

const canvas = await init();

export { canvas };
export default canvas;
export * from "./src/canvas.ts";
50 changes: 25 additions & 25 deletions src/base64.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { decode, encode } from "../deps.ts";

// core is unstable (in sense of actual stability not --unstable)
// so we'll fallback to pure js impl
// why use internal op? it's super fast

export function decodeBase64(value: string): Uint8Array {
let res;
try {
res = (Deno as any).core.opSync("op_base64_decode", value);
} catch (e) {
res = decode(value);
}
return res;
}

export function encodeBase64(value: Uint8Array): string {
let res;
try {
res = (Deno as any).core.opSync("op_base64_encode", value);
} catch (e) {
res = encode(value);
}
return res;
}
import { decode, encode } from "../deps.ts";

// core is unstable (in sense of actual stability not --unstable)
// so we'll fallback to pure js impl
// why use internal op? it's super fast

export function decodeBase64(value: string): Uint8Array {
let res;
try {
res = (Deno as any).core.opSync("op_base64_decode", value);
} catch (e) {
res = decode(value);
}
return res;
}

export function encodeBase64(value: Uint8Array): string {
let res;
try {
res = (Deno as any).core.opSync("op_base64_encode", value);
} catch (e) {
res = encode(value);
}
return res;
}
Loading

0 comments on commit a8c66d4

Please sign in to comment.