Missing methods for the canvas API (`.save()` / `.restore()`)

Hello :wave:

I have an issue with canvas when writing a plugin for Photoshop 2024 - 25.11.0 Release.

For context Paper.js is a very powerful library that uses the canvas APIs, see examples of what can be done with Paper.js: Paper.js β€” Examples

My problem is that the CanvasRenderingContext2D object is missing the save() and .restore() methods.

This line: github dot com/paperjs/paper.js/blob/92775f5279c05fb7f0a743e9e7fa02cd40ec1e70/src/canvas/CanvasProvider.js#L49 throws when loading Paper.js

Error as text

As text for example:

index.js is running...
index.js:3 The vanilla demo (without Paper.js) will run now...
index.js:21 The vanilla demo failed (expected) with: TypeError: ctx.save is not a function
    at index.js:11
    at e.exports.execScript (uxp://uxp-internal/domjs_scripts.js:2)
    at l (uxp://uxp-internal/domjs_scripts.js:2)
    at uxp://uxp-internal/domjs_scripts.js:2
    at s._executeCallbacks (uxp://uxp-internal/domjs_scripts.js:2)
    at s._executeIfReady (uxp://uxp-internal/domjs_scripts.js:2)
    at Array.<anonymous> (uxp://uxp-internal/domjs_scripts.js:2)
    at s._executeCallbacks (uxp://uxp-internal/domjs_scripts.js:2)
    at s.done (uxp://uxp-internal/domjs_scripts.js:2)
    at Object.s [as loadHtmlContent] (uxp://uxp-internal/domjs_scripts.js:2)
(anonymous) @ index.js:21
index.js:26 The demo with Paper.js will run now...
index.js:32 The Paper.js demo failed (expected) with: TypeError: ctx.save is not a function
    at Object.getCanvas (/Users/j42/Dev/fontself/paper-js-demo-panel/paper-core.js:14368:7)
    at Object.getContext (/Users/j42/Dev/fontself/paper-js-demo-panel/paper-core.js:14373:21)
    at new <anonymous> (/Users/j42/Dev/fontself/paper-js-demo-panel/paper-core.js:14572:27)
    at /Users/j42/Dev/fontself/paper-js-demo-panel/paper-core.js:14386:17
    at /Users/j42/Dev/fontself/paper-js-demo-panel/paper-core.js:15703:3
    at e.exports._loadModule (uxp://uxp-internal/runtime_scripts_loader.js:2:21301)
    at e.exports._require (uxp://uxp-internal/runtime_scripts_loader.js:2:19812)
    at a (uxp://uxp-internal/runtime_scripts_loader.js:2:19038)
    at index.js:29:17
    at e.exports.execScript (uxp://uxp-internal/domjs_scripts.js:2:618363)

Here is the reproduction as a Google Drive link since I cannot upload yet to the forum: paper-js-demo-panel.zip - Google Drive

The code

And the main part of the code

console.log('index.js is running...')

console.log('The vanilla demo (without Paper.js) will run now...')

// Example from https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/save
const canvas = document.getElementById('canvas-vanilla')
const ctx = canvas.getContext('2d')

try {
  // Save the current state
  ctx.save()

  ctx.fillStyle = 'green'
  ctx.fillRect(0, 0, 100, 100)

  // // Restore to the state saved by the most recent call to save()
  ctx.restore()

  ctx.fillRect(150, 0, 100, 100)
} catch (error) {
  console.error('The vanilla demo failed (expected) with:', error)
}

// Now let's Try to use Paper.js

console.log('The demo with Paper.js will run now...')
try {
  // Load Paper.js library
  const paper = require('./paper-core.js')
  document.re
} catch (error) {
  console.error('The Paper.js demo failed (expected) with:', error)
}


From what I understand, this might be expected as the implementation of canvas is partial and limited.
It’s really a blocker for me at the moment :slightly_frowning_face:

What would be great to know is if / when are you considering adding these specific APIs? (.save() & .restore())

Do you have any thoughts about this? Thanks!

JoΓ«l

1 Like

As a workaround, you could try setting up a webview ( https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-js/Global%20Members/HTML%20Elements/HTMLWebViewElement/ ) which hosts a webpage containing your usage of paper.js. With this method I was able to get three.js rendering to a canvas inside the webview (where more of the canvas API seems to work).

There are some drawbacks, you’d have to host the webpage on your own server, and any data communicated b/w photoshop and the webview have to go through postMessage(), where they get serialized to a string and then back to an object.

1 Like