Skip to content

[FEAT]: OffscreenCanvas API compatibility #2539

@ShaMan123

Description

@ShaMan123

Motivation

Related #876 #2127

Creating platform agnostic canvas apps/products is very powerful.
Whether web, offscreen or node a product will probably use all in various scenarios.
This makes compatibility and standardization important.
Node canvas is an amazing repo and is nearly fully compatible with the OffscreenCanvas API.
Meaning that in most cases you can drop your app into node and it works.
I would like node canvas to be fully (or more) compatible so there is even less friction and am willing to contribute.

ImageBitmap

In order to align Image to ImageBitmap it seems this is enough:

class CompatibleImage extends Image implements ImageBitmap {
  /**
   * Free resources
   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap#instance_methods spec}
   */
  close(): void {
    this.src = "";
    this.width = 0;
    this.height = 0;
  }
}

OffscreenCanvas

In order to align Canvas to OffscreenCanvas it seems this is enough:

export class CompatibleCanvas extends Canvas implements OffscreenCanvas {
  /**
   * Can be sync but spec returns a promise
   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas/convertToBlob#return_value spec}
   *
   */
  async convertToBlob() {
    return new Blob([this.toBuffer()]);
  }
  transferToImageBitmap(): ImageBitmap {
    const img = new CompatibleImage();
    img.src = this.toBuffer();
    return img;
  }
  oncontextlost() {}
  oncontextrestored() {}
  addEventListener() {}
  removeEventListener() {}
  /**
   *
   * @returns `false` as if event was cancelled
   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent#return_value spec}
   */
  dispatchEvent(): boolean {
    return false;
  }
}

OffscreenCanvasRenderingContext2D

This has a bit more difference, mainly in text props.
Focusing on methods is more important for compatibility IMO and that is not far off.

class CompatibleCanvasRenderingContext2D
  extends CanvasRenderingContext2D
  implements OffscreenCanvasRenderingContext2D
{
  fontKerning: CanvasFontKerning;
  fontStretch: CanvasFontStretch;
  fontVariantCaps: CanvasFontVariantCaps;
  letterSpacing: string;
  textRendering: CanvasTextRendering;
  wordSpacing: string;
  filter: string;
  imageSmoothingQuality: ImageSmoothingQuality;
  canvas: CompatibleCanvas;

  isPointInStroke(path: unknown, x: unknown, y?: unknown): boolean {
    //  enhance isPointInPath?
    throw new Error("Method not implemented.");
  }

  createConicGradient(
    startAngle: number,
    x: number,
    y: number
  ): CanvasGradient {
    throw new Error("Method not implemented.");
  }

  /**
   * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/reset spec}
   */
  reset(): void {
    this.resetTransform();
    // reset all saved values, clip path, path etc.
  }

  /**
   * noop
   */
  isContextLost() {
    return false;
  }
}

Discussion

Before PRing I wanted to drop this here and see what maintainers think.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions