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

Problem with PDF background image in Macbook pro retina screen (Chrome) #8837

Closed
Huespal opened this issue Aug 29, 2017 · 14 comments
Closed

Comments

@Huespal
Copy link

Huespal commented Aug 29, 2017

Link to PDF file (or attach file here):
Dropbox 'Getting Started.pdf' PDF -> https://www.dropbox.com/s/zwfzuaampxim8bi/Getting%20Started.pdf?dl=0

Configuration:

  • Web browser and its version: Chrome 60.0.3112.101.
  • Operating system and its version: macOS Sierra 10.12.6
  • PDF.js version: 1.8.571
  • Is an extension: Is the pdfjs-dist npm.
    The project is using Angular 1.x JS Framework.

Steps to reproduce the problem:

  1. Upload a pdf with a background image, like the default Dropbox PDF, using pdfjs library in an angular 1.x project, in Chrome on a macOS.
  2. Render it in the Mac screen.

What is the expected behavior? (add screenshot)

A well perfectly scaled blue Dropbox box in background image. Like in the real life.

screen shot 2017-08-29 at 10 13 24

What went wrong? (add screenshot)

Bad scaled background Dropbox box image. Background is rendered as if CSS styles or canvas width, height are not applying, is my first idea. But I don't know exactly. It fails only in this configuration. Works in FF in all OS. Works in Chrome both in ubuntu and windows. Works in Mac in another screen. I can only reproduce the bug in the Macbook pro default retina display. Which is important because the target of people using Macbook pro screen and chrome is huge.

screen shot 2017-08-29 at 10 39 17

Canvas dimensions I'm applying:

 /**
         * @desc
         *  Sets canvas dimensions
         * @param {Object} canvas - The canvas object.
         * @param {number} w - Canvas width.
         * @param {number} h - Canvas height.
         */
        let setCanvasDimensions = function(canvas, w, h) {
            let ratio = backingScale(canvas);
            canvas.width = Math.floor(w * ratio);
            canvas.height = Math.floor(h * ratio);
            canvas.style.width = Math.floor(w) + 'px';
            canvas.style.height = Math.floor(h) + 'px';
            canvas.getContext('2d').setTransform(ratio, 0, 0, ratio, 0, 0);
            return canvas;
        };

     /**
         * @desc
         *  Backing on scale.
         * @param {Object} canvas - The canvas object.
         * @returns {number}
         */
    let backingScale        = function(canvas) {
            let ctx = canvas.getContext('2d');
            let dpr = window.devicePixelRatio || 1;
            let bsr = ctx.webkitBackingStorePixelRatio ||
                ctx.mozBackingStorePixelRatio ||
                ctx.msBackingStorePixelRatio ||
                ctx.oBackingStorePixelRatio ||
                ctx.backingStorePixelRatio || 1;

            return dpr / bsr;
        };

The best part:
It just happens every first time PDF is rendered in page load. Page 1 is first rendered, and fails. If I go to the next PDF page, 2, page renders ok. Going going back to the page 1, now is ok. Same exact function is called for every page:

function renderPDF() {
[...]
// canvas and ctx are set globally. I put here to better understand code.
let canvas = document.getElementById('pdf-canvas');
let ctx = canvas.getContext('2d');
pdfDoc.getPage(num).then(function(page) {
                       let viewport, pageWidthScale, renderContext;                        
                       viewport = page.getViewport(scale); // scale = 0.8.
                       setCanvasDimensions(canvas, viewport.width, viewport.height);

                       renderContext = {
                           canvasContext: ctx,
                           viewport: viewport
                       };

                       renderTask = page.render(renderContext);
                       renderTask.promise.then(function() {
                           if (typeof scope.onPageRender === 'function') {
                               scope.onPageRender();
                           }
                       }).catch( (reason) => console.log(reason));
                   });
[...]
}

Thanks

@yurydelendik
Copy link
Contributor

I can only reproduce the bug in the Macbook pro default retina display.

I cannot reproduce that on MBP with FF or Safari with default retina display using default viewer. What browser you are using?

Can you publish complete example online? (You have the complete code -- I have to spend time to re-type and re-build code from snippets)

@Huespal
Copy link
Author

Huespal commented Aug 29, 2017

The browser used by me is in the issue description, and title. 🐙
Only happens in Chrome, version Chrome 60.0.3112.101.
I can publish complete example online. But it will take a while. Please wait for it.

@yurydelendik
Copy link
Contributor

yurydelendik commented Aug 29, 2017

Only happens in Chrome, version Chrome 60.0.3112.101

Missed that somehow. Marking as such. I was able to reproduce with Chrome something different with demo viewer.

@yurydelendik
Copy link
Contributor

That's version 60.0.3112.113 (Official Build) (64-bit) though

@Huespal
Copy link
Author

Huespal commented Aug 29, 2017

Yes, now I'm also on Version 60.0.3112.113 (Official Build) (64-bit). Chrome updates are really quick.

@yurydelendik
Copy link
Contributor

I was able to reproduce with Chrome something different with demo viewer.

I was not able to reproduce with demo viewer. (Last picture was for SVG backend.)

Chrome updates are really quick.

@Huespal do you still has problem with new chrome version?

@Huespal
Copy link
Author

Huespal commented Aug 29, 2017

Yes. I still have the same problem with the new chrome version.

@Huespal
Copy link
Author

Huespal commented Aug 30, 2017

A quick update. I'm getting the:

Warning: Setting up fake worker

warning message. I wonder if a good worker configuration can solve the issue.

The way I'm setting up the worker is like wojtekmaj said on 13 Jul in this issue:

#7612

Especially because the workerSrc path (I can not put an static string pointing to the worker file like the official example in my project environment).

Is there some way to debug pdf worker errors?

I will update the issue if I get worker configured.

EDIT:
I get worker configured and issue still happens.

@Huespal
Copy link
Author

Huespal commented Aug 30, 2017

Just in case someone is suffering the same issue. I 'solve it' by rendering again only in the first PDF render:

From the code above is called onPageRender, so:

let initial = true;

/**
 * @desc
*  Callback triggered when page is rendered.
*/
scope.onPageRender  = function() {
    // PDF is rendered again to prevent the 
    // https://github.com/mozilla/pdf.js/issues/8837 issue.
    if(initial &&
    navigator.platform.toUpperCase().indexOf('MAC')>=0 && // is Mac
    /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor) // is Chrome
        ) {
            renderPDF();
            initial = false;
       }
};

I don't like it. So I still want to solve the issue in a correct way.

EDIT:
Found the correct way. See last message.

@yurydelendik
Copy link
Contributor

@Huespal the snippet above is not part PDF.js library code -- please contact the vendor of the component directly. The #7612 looks like connected with some custom library as well.

Here is my sandbox for playing with pdfjs, webpack and react if you want to change a base library and start using pdf.js directly: https://github.com/yurydelendik/pdfjs-react

@Huespal
Copy link
Author

Huespal commented Aug 30, 2017

Yes, you are right. That damn component vendor (me :))
I finally found the problem.
Just replacing this

setCanvasDimensions(canvas, viewport.width, viewport.height);

for this:

 canvas.width    = viewport.width;
 canvas.height   = viewport.height;

I don't remember why I code it.

Thanks for pointing to the sandbox. I saw it before, but dismissed because not in angular.

@yurydelendik
Copy link
Contributor

@Huespal since you are an angular person, can you publish a basic example for me? (see also #8836)

@Huespal
Copy link
Author

Huespal commented Aug 30, 2017

mmm he is asking about current angular (>2.x), different from this issue's angular (1.x). But I can try it this weekend.

@timvandermeij
Copy link
Contributor

Thank you. Having a minimal Angular example in https://github.com/mozilla/pdf.js/tree/master/examples would probably help out quite a bit of people. I think we should aim for Angular > 2.x since that's simply more modern, but having an AngularJS example (1.x) would already be better than nothing. People could probably alter it for usage in Angular > 2.x anyway.

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

No branches or pull requests

3 participants