Skia Canvas

repository·main·Indexed 41 days ago

https://github.com/djdeveloperr/skia_canvas

A high-performance implementation of the HTML Canvas API for the Deno runtime, powered by the Skia graphics engine. It provides a standard CanvasRenderingContext2D interface along with non-standard features like Canvas#save, Canvas#encode, SvgCanvas, and PdfDocument. Supports GPU acceleration via OpenGL and requires --allow-ffi, --allow-env, and --unstable-ffi permissions to run.

Tokens
9.5K
Snippets
34
Records
48
Agent score
100%

What's inside Skia Canvas

  1. Quickstart with Skia Canvas

    main

    Skia Canvas provides a fast HTML Canvas API implementation for Deno using Skia. You can create a canvas, get a 2D context, and use standard Canvas Web API methods to draw shapes, paths, and more. Finally, use canvas.save(path) to export the result to a file.

    import { createCanvas } from "jsr:@gfx/canvas@0.5.6";
    
    const canvas = createCanvas(300, 300);
    const ctx = canvas.getContext("2d");
    
    // Set line width
    ctx.lineWidth = 10;
    
    // Wall
    ctx.strokeRect(75, 140, 150, 110);
    
    // Door
    ctx.fillRect(130, 190, 40, 60);
    
    // Roof
    ctx.beginPath();
    ctx.moveTo(50, 140);
    ctx.lineTo(150, 60);
    ctx.lineTo(250, 140);
    ctx.closePath();
    ctx.stroke();
    
    canvas.save("image.png");
  2. Build Skia Canvas from source

    main

    To build the project locally, follow these steps:

    1. Setup depot_tools.
    2. Clone the repository including submodules.
    3. Run the build tasks:
    deno task build-skia
    deno task build

    Using local binaries

    By default, the module downloads and caches prebuilt binaries. To force the use of your locally built binaries, use one of the following environment variables:

    • Set DENO_SKIA_LOCAL=1 to use local builds.
    • Set DENO_SKIA_PATH to the absolute path of the dynamic library built from the native directory.
  3. Run Skia Canvas in Deno

    main

    Because this library depends on the unstable FFI (Foreign Function Interface) API, you must provide specific permissions when running your Deno script. Without these flags, the module will fail to find and open the native library.

    You can use the following flags:

    • --allow-ffi
    • --allow-env
    • --unstable-ffi

    Alternatively, you can use the -A (all permissions) flag.

    deno run --allow-ffi --allow-env --unstable-ffi <file>
    # or just
    deno run -A --unstable-ffi <file>
  4. Export to PDF using PdfDocument

    main

    The PdfDocument class allows you to create and save PDF files using the standard Canvas 2D API. You initialize a document with optional metadata, create pages using newPage(), and finalize each page with endPage(). Once all pages are finished, you can either save the document to a file using save(path) or encode it into a Uint8Array using encode().

    import { PdfDocument } from "./pdfdocument.ts";
    
    // 1. Initialize the document with optional metadata
    const pdf = new PdfDocument({
      title: "My Document",
      author: "Developer",
    });
    
    // 2. Create a page and get a 2D context
    const ctx = pdf.newPage(600, 800);
    
    // 3. Use standard Canvas 2D API methods
    ctx.fillStyle = "blue";
    ctx.fillRect(50, 50, 100, 100);
    ctx.font = "30px Arial";
    ctx.fillText("Hello PDF", 50, 200);
    
    // 4. Finalize the page
    ctx.endPage();
    
    // 5. Save to file or encode to buffer
    pdf.save("output.pdf");
    // OR
    // const buffer = pdf.encode();
  5. Create a Canvas using createCanvas() or the Canvas class

    main

    You can create a new offscreen canvas using the createCanvas factory function or by instantiating the Canvas class directly. The canvas uses Skia's SkSurface and a raster backend by default.

    GPU Acceleration: You can request a GPU-backed canvas by passing gpu: true. Note: Only use gpu: true if you have an OpenGL context already initialized and made current in your environment.

    import { createCanvas } from "./canvas.ts";
    
    // Create a standard raster canvas
    const canvas = createCanvas(800, 600);
    
    // Create a GPU-backed canvas (requires existing OpenGL context)
    const gpuCanvas = createCanvas(800, 600, true);
  6. Use SvgCanvas for SVG export

    main

    The SvgCanvas class allows you to render graphics using a 2D context and export the result as an SVG file, a byte buffer, or a string.

    Important Lifecycle Rules:

    1. You must call .complete() exactly once when you are finished drawing.
    2. You can only call .save(), .encode(), or .toString() after calling .complete().

    Workflow:

    1. Instantiate SvgCanvas with desired dimensions and options.
    2. Obtain a context via .getContext().
    3. Perform drawing operations using the SvgRenderingContext2D.
    4. Call .complete() to finalize the SVG structure.
    5. Export the result using .save(path), .encode(), or .toString().
    import { SvgCanvas } from './skia_canvas/svgcanvas.ts'; // Adjust path as needed
    
    const canvas = new SvgCanvas(800, 600);
    const ctx = canvas.getContext();
    
    // Draw something
    ctx.fillStyle = 'red';
    ctx.fillRect(10, 10, 100, 100);
    
    // Finalize the canvas before exporting
    canvas.complete();
    
    // Export options:
    canvas.save('output.svg');           // Saves to file system
    const buffer = canvas.encode();      // Returns Uint8Array
    const svgString = canvas.toString(); // Returns SVG string
  7. Configure PdfMetadata for PDF documents

    main

    When instantiating a PdfDocument, you can provide a PdfMetadata object to set document properties. Supported keys include:

    • title?: string
    • author?: string
    • subject?: string
    • keywords?: string
    • creator?: string
    • producer?: string
    • creation?: Date
    • modified?: Date
    • pdfa?: boolean
    • encodingQuality?: number
  8. Configure ImageData color space

    main

    When creating ImageData, you can specify the colorSpace via the ImageDataSettings object.

    Supported ColorSpace values:

    • "srgb" (default)
    • "rec2020"
    • "display-p3"
    import { ImageData, ColorSpace } from "./image.ts";
    
    interface ImageDataSettings {
      colorSpace?: ColorSpace;
    }
    
    const settings: ImageDataSettings = { colorSpace: "display-p3" };
    const imgData = new ImageData(500, 500, settings);
  9. Configure SvgCanvasOptions

    main

    When instantiating SvgCanvas, you can provide an optional SvgCanvasOptions object to control how the SVG is generated.

    OptionTypeDescription
    convertTextsToPathsbooleanIf true, text elements are converted into SVG paths.
    noPrettyXmlbooleanIf true, the resulting XML will not be pretty-printed (minified).
    relativePathEncodingbooleanIf true, enables relative path encoding.
    const options: SvgCanvasOptions = {
      convertTextsToPaths: true,
      noPrettyXml: true,
      relativePathEncoding: false
    };
    
    const canvas = new SvgCanvas(500, 500, options);
  10. Disable system fonts via environment variable

    main

    By default, Skia Canvas loads system fonts at startup. If you want to prevent this behavior (e.g., to reduce startup time or control the font environment strictly), set the CANVAS_DISABLE_SYSTEM_FONTS environment variable to 1.

    export const CANVAS_DISABLE_SYSTEM_FONTS = "1";
  11. Non-standard Skia Canvas APIs

    main

    In addition to the standard Canvas Web API (refer to MDN for standard methods), Skia Canvas provides several non-standard features:

    • Canvas#save - Saves the canvas render as a file.
    • Canvas#encode - Encodes the canvas render into an in-memory buffer.
    • Image - Utility to load image files for drawing on the canvas.
    • Fonts - Utility to manage fonts used by Skia.
    • PdfDocument - Create PDF documents using the 2D Canvas API.
    • SvgCanvas - Similar to Canvas, but produces an SVG as output.
    • Path2D extensions - Includes methods like toSVGString, simplify, difference, xor, etc.
  12. Get the 2D rendering context

    main

    To draw on a canvas, you must retrieve its rendering context using getContext('2d'). This returns a CanvasRenderingContext2D instance which provides the standard Web Canvas API for drawing operations.

    const canvas = createCanvas(400, 400);
    const ctx = canvas.getContext('2d');
    
    if (ctx) {
      ctx.fillStyle = 'red';
      ctx.fillRect(0, 0, 100, 100);
    }