Now with Javascript: Reading PDF and XPS on your Windows 8 application using WinRT

Following my previous article on “Reading PDF and XPS on your Windows 8 application using WinRT”, I would like to share with you the same example but with Javascript code.

Many of you sent me a mail to get this code, so feel free to grab it here (I would like to thank Mehdi Lahlou for his original version):

https://www.catuhe.com/msdn/js.PDFReader.zip

The principle is the same as for C#: I use a FlipView control that uses a custom template to generate.

The FlipView is nothing but a standard WinJS control:

 <div data-win-control="WinJS.UI.FlipView" id="flipView">
 </div>

To open the PDF file, we can use the following code (standard WinRT code):

openPDF: function(filename) {
    return Windows.ApplicationModel.Package.current.installedLocation.getFileAsync(filename).then(function(file) {
        return Windows.Storage.FileIO.readBufferAsync(file).then(function(fileBuffer) {
            return MuPDFWinRT.Document.create(fileBuffer, MuPDFWinRT.DocumentType.pdf, 
Windows.Graphics.Display.DisplayProperties.logicalDpi); }); }); },

Please note that the MuPDFWinRT component used here is strictly the same as the one used by C#

Once the PDF is opened we can configure the FlipView using this code:

this.openPDF("test.pdf").then(function (pdfDocument) {
    var array = [];
    for (var i = 0; i < pdfDocument.pageCount; i++) {
        array.push(i);
    }
    var dataList = new WinJS.Binding.List(array);
    var flipViewDOM = document.getElementById("flipView");
    var flipView = flipViewDOM.winControl;
    var width = flipViewDOM.clientWidth;
    var height = flipViewDOM.clientHeight;

    flipView.itemDataSource = dataList.dataSource;
    flipView.itemTemplate = (function (itemPromise) {
        return itemPromise.then(function (item) {
            // root element for the item
            var canvas = document.createElement("canvas");

            canvas.style.width = width;
            canvas.style.height = height;

            var canvasContext = canvas.getContext("2d");

            that.drawPage(pdfDocument, canvasContext, item.index);
            return canvas;
        });
    });
});

Each page will be generated using a canvas stretched to fill the FlipView. Each canvas is then filled using this code:

drawPage: function (pdfDocument, canvasContext, index) {
    var size = pdfDocument.getPageSize(index);

    canvasContext.canvas.width = size.x;
    canvasContext.canvas.height = size.y;

    var imageData = canvasContext.createImageData(size.x, size.y);

    var current = new Int32Array(size.x * size.y);

    pdfDocument.drawPage(index, current, 0, 0, size.x, size.y, false);

    // from  ARGB to ABGR
    for (var i = 0; i < current.length; i++) {

        var val = current[i];

        var cursor = i * 4;

        imageData.data[cursor] = (val >> 16) & 0xFF; //r
        imageData.data[cursor + 1] = (val >> 8) & 0xFF; //g
        imageData.data[cursor + 2] = val & 0xFF; //b
        imageData.data[cursor + 3] = 255; // a
    }            
    canvasContext.putImageData(imageData, 0, 0);

Using pdfDocument.drawPage, you can fill the image data object created by the canvas. You must then invert pixel color components to switch from ARGB to ABGR and finally paste the result Inside the canvas.

And voila!