diff --git a/Makefile b/Makefile index adeb91b12..c1062d49d 100644 --- a/Makefile +++ b/Makefile @@ -3,6 +3,7 @@ BUILD_DIR := build BUILD_TARGET := $(BUILD_DIR)/pdf.js DEFAULT_BROWSERS := resources/browser_manifests/browser_manifest.json DEFAULT_TESTS := test_manifest.json +DEFAULT_PYTHON := python2.7 EXTENSION_SRC := ./extensions/ EXTENSION_BASE_VERSION := 4bb289ec499013de66eb421737a4dbb4a9273eda @@ -36,6 +37,7 @@ PDF_JS_FILES = \ stream.js \ worker.js \ ../external/jpgjs/jpg.js \ + jpx.js \ $(NULL) # make server @@ -43,7 +45,7 @@ PDF_JS_FILES = \ # This target starts a local web server at localhost:8888. This can be # used for testing all browsers. server: - @cd test; python test.py --port=8888; + @cd test; $(DEFAULT_PYTHON) test.py --port=8888; # make test # @@ -106,7 +108,7 @@ browser-test: fi; cd test; \ - python test.py --reftest \ + $(DEFAULT_PYTHON) test.py --reftest \ --browserManifestFile=$(PDF_BROWSERS) \ --manifestFile=$(PDF_TESTS) diff --git a/README.md b/README.md index 97db68d36..09cc95039 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,6 @@ -# pdf.js +# PDF.JS - -## Overview - pdf.js is an HTML5 technology experiment that explores building a faithful and efficient Portable Document Format (PDF) renderer without native code assistance. @@ -14,9 +11,9 @@ rendering PDFs, and eventually release a PDF reader extension powered by pdf.js. Integration with Firefox is a possibility if the experiment proves successful. + - -## Getting started +# Getting started ### Online demo @@ -29,11 +26,12 @@ using the pdf.js API. ### Extension -An up-to-date Firefox extension is also available: +A Firefox extension is also available: + http://mozilla.github.com/pdf.js/extensions/firefox/pdf.js.xpi -(The above link is updated upon every merge to our master branch). +Note that this extension is self-updating, and by default Firefox will auto-update extensions on a +daily basis (you can change this through the `extensions.update.interval` option in `about:config`). For an experimental Chrome extension, get the code as explained below and issue `make extension`. Then open Chrome with the flag `--enable-experimental-extension-apis`, go to `Tools > Extension` @@ -68,12 +66,12 @@ In order to bundle all `src/` files into a final `pdf.js`, issue: This will generate the file `build/pdf.js` that can be included in your final project. (WARNING: That's a large file! Consider minifying it). -## Learning +# Learning Here are some initial pointers to help contributors get off the ground. Additional resources are available in a separate section below. -#### Hello world +### Hello world For a "hello world" example, take a look at: @@ -82,7 +80,7 @@ For a "hello world" example, take a look at: This example illustrates the bare minimum ingredients for integrating pdf.js in a custom project. -#### Introductory video +### Introductory video Check out the presentation by our contributor Julian Viereck on the inner workings of PDF and pdf.js: @@ -92,7 +90,7 @@ workings of PDF and pdf.js: -## Contributing +# Contributing pdf.js is a community-driven project, so contributors are always welcome. Simply fork our repo and contribute away. Good starting places for picking @@ -122,7 +120,7 @@ You can add your name to it! :) -## Running the tests +# Running the tests pdf.js comes with browser-level regression tests that allow one to probe whether it's able to successfully parse PDFs, as well as compare its output @@ -148,7 +146,7 @@ images. The test type `load` simply tests whether the file loads without raising any errors. -## Running tests through our bot +### Running tests through our bot If you are a reviewer, you can use our remote bot to issue comprehensive tests against reference images before merging pull requests. @@ -158,7 +156,7 @@ See the bot repo for details: + https://github.com/mozilla/pdf.js-bot -## Additional resources +# Additional resources Gallery of user projects and modifications: @@ -188,7 +186,7 @@ Follow us on twitter: @pdfjs -## PDF-related resources +### PDF-related resources A really basic overview of PDF is described here: diff --git a/examples/acroforms/index.html b/examples/acroforms/index.html index 5fad4648a..8a9053f78 100644 --- a/examples/acroforms/index.html +++ b/examples/acroforms/index.html @@ -23,6 +23,7 @@ + + + + diff --git a/web/viewer.js b/web/viewer.js index 3431e18c4..04339ca66 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -6,6 +6,7 @@ var kDefaultURL = 'compressed.tracemonkey-pldi-09.pdf'; var kDefaultScale = 'auto'; var kDefaultScaleDelta = 1.1; +var kUnknownScale = 0; var kCacheSize = 20; var kCssUnits = 96.0 / 72.0; var kScrollbarPadding = 40; @@ -157,7 +158,7 @@ var currentPageNumber = 1; var PDFView = { pages: [], thumbnails: [], - currentScale: 0, + currentScale: kUnknownScale, currentScaleValue: null, initialBookmark: document.location.hash.substring(1), @@ -212,12 +213,12 @@ var PDFView = { zoomIn: function pdfViewZoomIn() { var newScale = Math.min(kMaxScale, this.currentScale * kDefaultScaleDelta); - this.setScale(newScale, true); + this.parseScale(newScale, true); }, zoomOut: function pdfViewZoomOut() { var newScale = Math.max(kMinScale, this.currentScale / kDefaultScaleDelta); - this.setScale(newScale, true); + this.parseScale(newScale, true); }, set page(val) { @@ -478,10 +479,16 @@ var PDFView = { } else if (storedHash) this.setHash(storedHash); - else { - this.parseScale(scale || kDefaultScale, true); + else if (scale) { + this.parseScale(scale, true); this.page = 1; } + + if (PDFView.currentScale === kUnknownScale) { + // Scale was not initialized: invalid bookmark or scale was not specified. + // Setting the default one. + this.parseScale(kDefaultScale, true); + } }, setHash: function pdfViewSetHash(hash) { @@ -776,6 +783,8 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight, if (scale && scale !== PDFView.currentScale) PDFView.parseScale(scale, true); + else if (PDFView.currentScale === kUnknownScale) + PDFView.parseScale(kDefaultScale, true); setTimeout(function pageViewScrollIntoViewRelayout() { // letting page to re-layout before scrolling @@ -994,22 +1003,55 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { var self = this; var textDivs = this.textDivs; var textLayerDiv = this.textLayerDiv; - this.textLayerTimer = setInterval(function renderTextLayer() { + var renderTimer = null; + var renderingDone = false; + var renderInterval = 0; + var resumeInterval = 500; // in ms + + // Render the text layer, one div at a time + function renderTextLayer() { if (textDivs.length === 0) { - clearInterval(self.textLayerTimer); + clearInterval(renderTimer); + renderingDone = true; return; } var textDiv = textDivs.shift(); - if (textDiv.dataset.textLength >= 1) { // avoid div by zero + if (textDiv.dataset.textLength > 0) { textLayerDiv.appendChild(textDiv); - // Adjust div width (via letterSpacing) to match canvas text - // Due to the .offsetWidth calls, this is slow - textDiv.style.letterSpacing = - ((textDiv.dataset.canvasWidth - textDiv.offsetWidth) / - (textDiv.dataset.textLength - 1)) + 'px'; + + if (textDiv.dataset.textLength > 1) { // avoid div by zero + // Adjust div width (via letterSpacing) to match canvas text + // Due to the .offsetWidth calls, this is slow + // This needs to come after appending to the DOM + textDiv.style.letterSpacing = + ((textDiv.dataset.canvasWidth - textDiv.offsetWidth) / + (textDiv.dataset.textLength - 1)) + 'px'; + } + } // textLength > 0 + } + renderTimer = setInterval(renderTextLayer, renderInterval); + + // Stop rendering when user scrolls. Resume after XXX milliseconds + // of no scroll events + var scrollTimer = null; + function textLayerOnScroll() { + if (renderingDone) { + window.removeEventListener('scroll', textLayerOnScroll, false); + return; } - }, 0); - }; + + // Immediately pause rendering + clearInterval(renderTimer); + + clearTimeout(scrollTimer); + scrollTimer = setTimeout(function textLayerScrollTimer() { + // Resume rendering + renderTimer = setInterval(renderTextLayer, renderInterval); + }, resumeInterval); + }; // textLayerOnScroll + + window.addEventListener('scroll', textLayerOnScroll, false); + }; // endLayout this.appendText = function textLayerBuilderAppendText(text, fontName, fontSize) { @@ -1274,7 +1316,7 @@ window.addEventListener('keydown', function keydown(evt) { handled = true; break; case 48: // '0' - PDFView.setScale(kDefaultScale, true); + PDFView.parseScale(kDefaultScale, true); handled = true; break; case 37: // left arrow