Moar PDF.js and Popcorn Maker

Last week I wrote about my addition of a PDF.js plugin to Popcorn Maker. I took some time today to hack on it some more and I figured it was worthwhile to outline what I have accomplished thus far.

I had pretty much gotten the plugin into a working state when I last wrote about it. There were a couple issues that I still had to work out though such as adding background colour to the canvas, centreing and resizing the canvas and upgrading the PDF upload functionality in cornfield.

The first issue to fix was simple. When PDF.js renders a document to a canvas it's focusing solely on the text and image content of the document. What this leaves you with is a canvas that contains the document data, while being completely see-through. A simple question in the PDF.js IRC channel pointed me to the sample PDF reader ( http://mozilla.github.com/pdf.js/web/viewer.html ), where I found a useful bit of code to make the canvas background white:

This code sample was lost because wordpress

The next issue to fix was sizing and centreing of the canvas. In Popcorn Maker, a plugin is commonly "wrapped" in an outer element, usually a <div>. This element is used by the app for sizing and positioning. I had PDF.js calculating the correct ratio based on a canvas exactly the height and width of this wrapper.  This posed a problem aesthetically, as I would often get a canvas the exact same height and width of the container, and a document that was rendered at the correct size, but aligned all the way to the left and top of the wrapper. My solution, after a lot of trial and error, involves first calculating the correct size of the canvas, based on the height/width of the container and the height/width of the PDF document. After obtaining the correct size of the canvas and applying the values to the canvas, I simply had to re-calculate the ratio that PDF.js needed to output the page at.

This code sample was lost because wordpress

To get the newly sized canvas to centre only took one simple CSS declaration:

This code sample was lost because wordpress

Perfect. Here's what it looks like:

The next thing I worked on was fixing up the sketchy uploading code to cornfield (It's still kinda sketchy :P). Initially, I borrowed from the current file-store methods that had been implemented for image uploading, but I realized they weren't quite what I was looking for. When a PDF was dropped, it would always save the file, regardless of if it was already dropped or not. To work around this, I pulled in the crypto library that comes with node.js and used it to generate an md5 hash of the uploaded file. Using that md5 hash as a file name, it was easy to detect if the file already existed, and if it did, I could simply return the link to the file. I'll admit now, a better solution might be to generate the hash client side first, and check before sending the file. This method was easier for now, and I'm not even sure if cross origin policies would let me generate md5 check-sums out of files originating from the filesystem. With that in place, duplicate PDF's were a thing of the past.

What I'm currently working on (not finished yet) is updating the editor UI. It's severely limited right now, and some of the CSS isn't functioning as I would like it to. I also want to keep a map of file names and links to make it easier for different plugin instances to use already uploaded documents, so they can display other pages without having to drag and drop the file each time.