diff --git a/multi_page_viewer.js b/multi_page_viewer.js index f262734d3..f46038c9c 100644 --- a/multi_page_viewer.js +++ b/multi_page_viewer.js @@ -26,41 +26,53 @@ var PDFViewer = { scale: 1.0, - pageWidth: function() { - return 816 * PDFViewer.scale; + pageWidth: function(page) { + return page.mediaBox[2] * PDFViewer.scale; }, - pageHeight: function() { - return 1056 * PDFViewer.scale; + pageHeight: function(page) { + return page.mediaBox[3] * PDFViewer.scale; }, lastPagesDrawn: [], - visiblePages: function() { - var pageHeight = PDFViewer.pageHeight() + 20; // Add 20 for the margins. + visiblePages: function() { + const pageBottomMargin = 20; var windowTop = window.pageYOffset; var windowBottom = window.pageYOffset + window.innerHeight; - var pageStartIndex = Math.floor(windowTop / pageHeight); - var pageStopIndex = Math.ceil(windowBottom / pageHeight); + + var pageHeight, page; + var i, n = PDFViewer.numberOfPages, currentHeight = 0; + for (i = 1; i <= n; i++) { + var page = PDFViewer.pdf.getPage(i); + pageHeight = PDFViewer.pageHeight(page) + pageBottomMargin; + if (currentHeight + pageHeight > windowTop) + break; + currentHeight += pageHeight; + } var pages = []; - - for (var i = pageStartIndex; i <= pageStopIndex; i++) { - pages.push(i + 1); + for (; i <= n && currentHeight < windowBottom; i++) { + var page = PDFViewer.pdf.getPage(i); + pageHeight = PDFViewer.pageHeight(page) + pageBottomMargin; + currentHeight += pageHeight; + pages.push(i); } return pages; }, createPage: function(num) { + var page = PDFViewer.pdf.getPage(num); + var anchor = document.createElement('a'); anchor.name = '' + num; var div = document.createElement('div'); div.id = 'pageContainer' + num; div.className = 'page'; - div.style.width = PDFViewer.pageWidth() + 'px'; - div.style.height = PDFViewer.pageHeight() + 'px'; + div.style.width = PDFViewer.pageWidth(page) + 'px'; + div.style.height = PDFViewer.pageHeight(page) + 'px'; PDFViewer.element.appendChild(anchor); PDFViewer.element.appendChild(div); @@ -91,8 +103,8 @@ var PDFViewer = { // Canvas dimensions must be specified in CSS pixels. CSS pixels // are always 96 dpi. These dimensions are 8.5in x 11in at 96dpi. - canvas.width = PDFViewer.pageWidth(); - canvas.height = PDFViewer.pageHeight(); + canvas.width = PDFViewer.pageWidth(page); + canvas.height = PDFViewer.pageHeight(page); div.appendChild(canvas); var ctx = canvas.getContext('2d'); diff --git a/pdf.js b/pdf.js index db13acfee..2f21c95f0 100644 --- a/pdf.js +++ b/pdf.js @@ -3081,30 +3081,6 @@ var PDFDoc = (function() { return constructor; })(); -var IDENTITY_MATRIX = [ 1, 0, 0, 1, 0, 0 ]; - -// contexts store most of the state we need natively. -// However, PDF needs a bit more state, which we store here. -var CanvasExtraState = (function() { - function constructor() { - // Are soft masks and alpha values shapes or opacities? - this.alphaIsShape = false; - this.fontSize = 0.0; - this.textMatrix = IDENTITY_MATRIX; - this.leading = 0.0; - this.colorSpace = null; - // Current point (in user coordinates) - this.x = 0.0; - this.y = 0.0; - // Start of text line (in text coordinates) - this.lineX = 0.0; - this.lineY = 0.0; - } - constructor.prototype = { - }; - return constructor; -})(); - var Encodings = { get ExpertEncoding() { return shadow(this, "ExpertEncoding", [ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, @@ -3279,6 +3255,34 @@ var Encodings = { } }; +var IDENTITY_MATRIX = [ 1, 0, 0, 1, 0, 0 ]; + +// contexts store most of the state we need natively. +// However, PDF needs a bit more state, which we store here. +var CanvasExtraState = (function() { + function constructor() { + // Are soft masks and alpha values shapes or opacities? + this.alphaIsShape = false; + this.fontSize = 0; + this.textMatrix = IDENTITY_MATRIX; + this.leading = 0; + this.colorSpace = null; + // Current point (in user coordinates) + this.x = 0; + this.y = 0; + // Start of text line (in text coordinates) + this.lineX = 0; + this.lineY = 0; + // Character and word spacing + this.charSpace = 0; + this.wordSpace = 0; + this.textHScale = 100; + } + constructor.prototype = { + }; + return constructor; +})(); + function ScratchCanvas(width, height) { var canvas = document.createElement("canvas"); canvas.width = width; @@ -3777,13 +3781,13 @@ var CanvasGraphics = (function() { endText: function() { }, setCharSpacing: function(spacing) { - TODO("character (glyph?) spacing"); + this.ctx.charSpacing = spacing; }, setWordSpacing: function(spacing) { - TODO("word spacing"); + this.ctx.wordSpacing = spacing; }, setHScale: function(scale) { - TODO("horizontal text scale"); + this.ctx.textHScale = (scale % 100) * 0.01; }, setLeading: function(leading) { this.current.leading = leading; @@ -3846,6 +3850,8 @@ var CanvasGraphics = (function() { this.moveText(0, this.current.leading); }, showText: function(text) { + // TODO: apply charSpacing, wordSpacing, textHScale + this.ctx.save(); this.ctx.transform.apply(this.ctx, this.current.textMatrix); this.ctx.scale(1, -1); @@ -4008,10 +4014,14 @@ var CanvasGraphics = (function() { // we want the canvas to be as large as the step size var botRight = applyMatrix([x0 + xstep, y0 + ystep], matrix); - var tmpCanvas = new this.ScratchCanvas( - Math.ceil(botRight[0] - topLeft[0]), // width - Math.ceil(botRight[1] - topLeft[1]) // height - ); + var width = botRight[0] - topLeft[0]; + var height = botRight[1] - topLeft[1]; + + // TODO: hack to avoid OOM, remove then pattern code is fixed + if (Math.abs(width) > 8192 || Math.abs(height) > 8192) + return false; + + var tmpCanvas = new this.ScratchCanvas(width, height); // set the new canvas element context as the graphics context var tmpCtx = tmpCanvas.getContext("2d"); diff --git a/test/pdfs/sizes.pdf b/test/pdfs/sizes.pdf new file mode 100644 index 000000000..f621f821e Binary files /dev/null and b/test/pdfs/sizes.pdf differ diff --git a/test/resources/firefox/user.js b/test/resources/firefox/user.js index b01e2eb76..c92af9167 100644 --- a/test/resources/firefox/user.js +++ b/test/resources/firefox/user.js @@ -34,3 +34,5 @@ user_pref("dom.w3c_touch_events.enabled", true); user_pref("extensions.checkCompatibility", false); user_pref("extensions.installDistroAddons", false); // prevent testpilot etc user_pref("browser.safebrowsing.enable", false); // prevent traffic to google servers +user_pref("toolkit.telemetry.prompted", true); // prevent telemetry banner +user_pref("toolkit.telemetry.enabled", false); diff --git a/test/test.py b/test/test.py index 5aece2c24..b867251ee 100644 --- a/test/test.py +++ b/test/test.py @@ -37,6 +37,8 @@ class TestOptions(OptionParser): options.manifestFile = DEFAULT_MANIFEST_FILE if options.browser and options.browserManifestFile: print "Warning: ignoring browser argument since manifest file was also supplied" + if not options.browser and not options.browserManifestFile: + self.error("No test browsers found. Use --browserManifest or --browser args.") return options def prompt(question): @@ -219,10 +221,9 @@ def setUp(options): if options.browserManifestFile: testBrowsers = makeBrowserCommands(options.browserManifestFile) elif options.browser: - testBrowsers = [BrowserCommand({"path":options.browser, "name":"firefox"})] - else: - print "No test browsers found. Use --browserManifest or --browser args." - + testBrowsers = [BrowserCommand({"path":options.browser, "name":"firefox"})] + assert len(testBrowsers) > 0 + with open(options.manifestFile) as mf: manifestList = json.load(mf) @@ -415,6 +416,7 @@ def processResults(): def main(): + t1 = time.time() optionParser = TestOptions() options, args = optionParser.parse_args() options = optionParser.verifyOptions(options) @@ -434,6 +436,8 @@ def main(): processResults() finally: teardownBrowsers(browsers) + t2 = time.time() + print "Runtime was", int(t2 - t1), "seconds" if __name__ == '__main__': main() diff --git a/test/test_manifest.json b/test/test_manifest.json index 9b9d5e333..4c5e912f6 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -25,5 +25,10 @@ "link": true, "rounds": 1, "type": "load" + }, + { "id": "sizes", + "file": "pdfs/sizes.pdf", + "rounds": 1, + "type": "eq" } ] diff --git a/test/test_slave.html b/test/test_slave.html index 32076d075..b87af8364 100644 --- a/test/test_slave.html +++ b/test/test_slave.html @@ -25,9 +25,6 @@ function load() { manifestFile = params.manifestFile; canvas = document.createElement("canvas"); - // 8.5x11in @ 100% ... XXX need something better here - canvas.width = 816; - canvas.height = 1056; canvas.mozOpaque = true; stdout = document.getElementById("stdout"); @@ -93,7 +90,6 @@ function nextPage() { log(" loading page "+ currentTask.pageNum +"... "); var ctx = canvas.getContext("2d"); - clear(ctx); var fonts = []; var gfx = null; @@ -105,6 +101,15 @@ function nextPage() { failure = 'compile: '+ e.toString(); } + try { + // using mediaBox for the canvas size + canvas.width = currentPage.mediaBox[2]; + canvas.height = currentPage.mediaBox[3]; + clear(ctx); + } catch(e) { + failure = 'page setup: '+ e.toString(); + } + var fontLoaderTimer = null; function checkFontsLoaded() { try { @@ -193,16 +198,22 @@ function sendTaskResult(snapshot) { } function clear(ctx) { - var ctx = canvas.getContext("2d"); ctx.save(); ctx.fillStyle = "rgb(255, 255, 255)"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.restore(); } +/* Auto-scroll if the scrollbar is near the bottom, otherwise do nothing. */ +function checkScrolling() { + if ((stdout.scrollHeight - stdout.scrollTop) <= stdout.offsetHeight) { + stdout.scrollTop = stdout.scrollHeight; + } +} + function log(str) { stdout.innerHTML += str; - window.scrollTo(0, stdout.getBoundingClientRect().bottom); + checkScrolling(); } diff --git a/viewer.js b/viewer.js index c7be739bc..3dffa8144 100644 --- a/viewer.js +++ b/viewer.js @@ -60,6 +60,10 @@ function displayPage(num) { var page = pdfDocument.getPage(pageNum = num); + // scale canvas by 2 + canvas.width = 2 * page.mediaBox[2]; + canvas.hieght = 2 * page.mediaBox[3]; + var t1 = Date.now(); var ctx = canvas.getContext("2d"); ctx.save();