Pdf.js: Simplify "to fit page width/height into constrained box" use case

Created on 8 Jan 2015  路  9Comments  路  Source: mozilla/pdf.js

For example, remove CSS_UNIT scaling from the pdf_page_view.js or make it configurable.

There is a confusion when there is an attempt to fit pdfpageview into width/height constraints, see http://logs.glob.uno/?c=mozilla%23pdfjs#c29228

1-other

Most helpful comment

I experienced the same thing as isTravis. Viewport.width was 612, but pdf was rendering 816. My work around was just to declare CSS_UNITS again locally so I could use it to recalculate the scale like this:

PDFJS.workerSrc = '/assets/plugins/PDFjs/web/test/pdf.worker.js';

var DEFAULT_URL = '/assets/plugins/PDFjs/web/test/form.pdf';
var DEFAULT_SCALE = 1.0;
var CSS_UNITS = 96/72;
var container = document.getElementById('pageContainer');

// Fetch the PDF document from the URL using promises.
PDFJS.getDocument(DEFAULT_URL).then(function (doc) {

  // Use a promise to fetch and render the next page.
  var promise = Promise.resolve();
  for (var i = 1; i <= doc.numPages; i++) {
      promise = promise.then(function (pageNum) {
        return doc.getPage(pageNum).then(function (pdfPage) {

            var viewport = pdfPage.getViewport(DEFAULT_SCALE);
            var scale = container.clientWidth / (viewport.width * CSS_UNITS);

            // Create the page view.
            var pdfPageView = new PDFJS.PDFPageView({
              container: container,
              id: pageNum,
              scale: scale,
              defaultViewport: pdfPage.getViewport(scale),
              annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory(),
              renderInteractiveForms: true,
            });

        // Associate the actual page with the view and draw it.
        pdfPageView.setPdfPage(pdfPage);
        return pdfPageView.draw();
      });
    }.bind(null, i));
  }
});

All 9 comments

It seems that this was introduced by @brendandahl in PR #3727.
If we go for the second option ("make it configurable"), would something along the lines of https://github.com/Snuffleupagus/pdf.js/compare/issue-5628 suffice?

There is also another option: give user base viewport already pre-scaled using some utility function, for example:

PDFPageView.getBaseViewport = function (page, rotation) {
  return page.getViewport(CSS_UNITS, rotation === undefined ? page.rotation : rotation);
};

and document this... or even utility to allow autoscale/align

Initial problem was "to fit page width/height into constrained box", so probably we shall look into solving/making it more convinient first.

Any update on this matter? I'm trying to get a page to fit into a box. When manually specifying the canvas width, things worked smoothly. Now though, to get Annotation layers to work, I'm using the web/pdf_viewer.js file and I can't get the same scaling to work. I have code like so:

var container = document.getElementById("container");
const i = 1
// Get desired page
pdf.getPage(i).then(function(pdfPage) {
    const scale = container.offsetWidth / pdfPage.getViewport(1.0).width;
    var pdfPageView = new PDFJS.PDFPageView({
        container: container,
        id: i,
        scale: scale,
        defaultViewport: pdfPage.getViewport(scale),
        // We can enable text/annotations layers, if needed
        textLayerFactory: new PDFJS.DefaultTextLayerFactory(),
        annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory()
    });
    // Associates the actual page with the view, and drawing it
    pdfPageView.setPdfPage(pdfPage);
    return pdfPageView.draw();
});

When calling pdfPage.getViewport(1).width, it returns 612 - but when rendered with a scale of 1.0 it displays at 816px. I can't understand where this discrepancy is coming from (CSS_Units?) or how to fix it for this case.

Thanks for any guidance you may be able to provide!

Get deep into the pdfjs-dist/lib/web/ui_utils.js and I find there is var CSS_UNITS = 96.0 / 72.0; that affects the scale.
I'have no idea why pdf_viewer uses this variable but the simple one doesn't.What I have done is to get my scale multiplied with 1 / CSS_UNITS

Could we get some kind of documentation as to why this is been used? I'm just artificially removing this factor at the moment (which sucks for readability...)

In the html/css world 1in = 96pixels, in PDF the default is 1in = 72pixels. The scale is used so when showing 100% a PDF that is 8.5in should show up on the screen as 8.5in.

I experienced the same thing as isTravis. Viewport.width was 612, but pdf was rendering 816. My work around was just to declare CSS_UNITS again locally so I could use it to recalculate the scale like this:

PDFJS.workerSrc = '/assets/plugins/PDFjs/web/test/pdf.worker.js';

var DEFAULT_URL = '/assets/plugins/PDFjs/web/test/form.pdf';
var DEFAULT_SCALE = 1.0;
var CSS_UNITS = 96/72;
var container = document.getElementById('pageContainer');

// Fetch the PDF document from the URL using promises.
PDFJS.getDocument(DEFAULT_URL).then(function (doc) {

  // Use a promise to fetch and render the next page.
  var promise = Promise.resolve();
  for (var i = 1; i <= doc.numPages; i++) {
      promise = promise.then(function (pageNum) {
        return doc.getPage(pageNum).then(function (pdfPage) {

            var viewport = pdfPage.getViewport(DEFAULT_SCALE);
            var scale = container.clientWidth / (viewport.width * CSS_UNITS);

            // Create the page view.
            var pdfPageView = new PDFJS.PDFPageView({
              container: container,
              id: pageNum,
              scale: scale,
              defaultViewport: pdfPage.getViewport(scale),
              annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory(),
              renderInteractiveForms: true,
            });

        // Associate the actual page with the view and draw it.
        pdfPageView.setPdfPage(pdfPage);
        return pdfPageView.draw();
      });
    }.bind(null, i));
  }
});

thanks @joshuahutchison for the example, I had a similar problem and this fixed it :)

Was this page helpful?
0 / 5 - 0 ratings