Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run PDF.js canvas rendering in a web-worker #10319

Closed
brianmhunt opened this issue Nov 29, 2018 · 6 comments
Closed

Run PDF.js canvas rendering in a web-worker #10319

brianmhunt opened this issue Nov 29, 2018 · 6 comments
Labels

Comments

@brianmhunt
Copy link

Configuration:

  • Chrome 71
  • Operating system and its version: any
  • PDF.js version: 2.0.943
  • Is a browser extension: no

Steps to reproduce the problem:

  1. Write a web worker like this:
function onmessage () {
  const pdfDocument = await pdfjs.getDocument('/some-hard-coded.pdf')
  const page = await pdfDocument.getPage(1)
  const viewport = pdfPage.getViewport(1)
  const width = 250
  const height = viewport.height * (width / viewport.width)
  const canvas = new OffscreenCanvas(width, height)
  const canvasContext = canvas.getContext('2d', { alpha: false })
  return page.render({ canvasContext, viewport })
})
  1. Call this with e.g. w = new Worker('sample-pdf.js');

What is the expected behavior? (add screenshot)

PDF would render to the OffscreenCanvas

What went wrong? (add screenshot)

ReferenceError: document is not defined
at GenericFontLoader.insertRule (pdf.js:10154)
at GenericFontLoader.bind (pdf.js:10205)
at WorkerTransport. (pdf.js:9177)
at LoopbackPort.MessageHandler._onComObjOnMessage (pdf.js:12833)
at LoopbackPort. (pdf.js:8681)
at Array.forEach ()

i.e. this is failing:

styleElement = this.styleElement = document.createElement('style');

The problem is the absence of a DOM. The issue might be one of documentation, as PDF.js has a Node example, or there may be issues lurking in the deep. In any case I wanted to report it in case there were some obvious guidelines here.

@Snuffleupagus
Copy link
Collaborator

Looks (essentially) like a duplicate of issue #10039; most likely, a fair amount of re-factoring would be required for OffscreenCanvas to be supported out-of-the-box.

@brianmhunt
Copy link
Author

Thanks. @Snuffleupagus I saw that issue, and should've linked it; the problems are not identical in the sense that:

  1. OffscreenCanvas can be used in the main thread (i.e. its use is not limited to web workers);
  2. A web worker needn't use OffscreenCanvas (i.e. a Canvas polyfill other than OffscreenCanvas might work);
  3. A working OffscreenCanvas might not be the only problem PDF.js has in web workers.

In other words OffscreenCanvas support is another problem that happens to be a possible alternative to CanvasElement, but that alone may not be sufficient to resolve this issue.

@jsoo1
Copy link

jsoo1 commented May 8, 2019

Looking at https://github.com/mozilla/pdf.js/blob/master/examples/node/pdf2png/pdf2png.js (a node example), it looks like you may need to make a canvasFactory, too. What happens if you do that?

@tandat2209
Copy link

tandat2209 commented Apr 24, 2020

How do you use pdf.js inside a web-worker?

I imported it by this.

// Worker.ts
import { pdfjs } from "react-pdf";
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;

pdfjs.getDocument(...) => errors

But when using getDocument. It returns an error

Uncaught (in promise) Error: Setting up fake worker failed: "webpack_require(...).ensure is not a function"

@Snuffleupagus
Copy link
Collaborator

Duplicate of #10039

@Snuffleupagus Snuffleupagus marked this as a duplicate of #10039 Aug 28, 2021
@GeoffreyChen777
Copy link

I finally figured out how to use the OffscreenCanvas in a web worker to render the PDF.

In the worker script, we need to use workerPort to set the GlobalWorkerOptions.

const pdfjs = require('pdfjs-dist');
const worker = new Worker('pdf.worker.js');
pdfjs.GlobalWorkerOptions.workerPort = worker;

we also need to provide a fake ownerDocument, If we don't do that, the PDF can still be rendered, but fonts and figures is incorrect:

    const document = {
      fonts: self.fonts,
      createElement: (name) => {
        if (name == 'canvas') {
          return new OffscreenCanvas(1, 1);
        }
        return null;
      },
    };

    const pdf = await pdfjs.getDocument({
      url, // @ts-ignore
      ownerDocument: document,
    }).promise;

It works good in my project. But I'm not sure if this will cause any potential problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants