Skip to content

[FEAT]: OffscreenCanvas API compatibility #2539

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions