From 48695aa802c9ffce173839d192e8d0b26382b868 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Sun, 13 May 2012 22:48:23 -0500 Subject: [PATCH 01/39] Set Gecko 10 as min version for the extension --- extensions/firefox/install.rdf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/firefox/install.rdf b/extensions/firefox/install.rdf index a5094c19a..bf8766ed0 100644 --- a/extensions/firefox/install.rdf +++ b/extensions/firefox/install.rdf @@ -13,7 +13,7 @@ {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - 6.0 + 10.0 15.0a1 @@ -22,7 +22,7 @@ {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} - 2.1.* + 2.7 2.12a1 From 9ae859f594c4ff57ec97718002d5e645e479d705 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 18 Jul 2012 11:20:20 -0700 Subject: [PATCH 02/39] Fix initial scroll direction detection. --- web/viewer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index cbe20bb66..92b4bad13 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -912,7 +912,6 @@ var PDFView = { } if ('page' in params) { var pageNumber = (params.page | 0) || 1; - this.page = pageNumber; if ('zoom' in params) { var zoomArgs = params.zoom.split(','); // scale,left,top // building destination array @@ -928,8 +927,9 @@ var PDFView = { (zoomArgs[2] | 0), zoomArg]; var currentPage = this.pages[pageNumber - 1]; currentPage.scrollIntoView(dest); - } else + } else { this.page = params.page; // simple page + } return; } } else if (/^\d+$/.test(hash)) // page number From a341c66db66cf973dc8118a557bb65be649a36f1 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Tue, 31 Jul 2012 13:58:25 -0700 Subject: [PATCH 03/39] Fix nit. --- web/viewer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index 92b4bad13..96984a22f 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -928,7 +928,7 @@ var PDFView = { var currentPage = this.pages[pageNumber - 1]; currentPage.scrollIntoView(dest); } else { - this.page = params.page; // simple page + this.page = pageNumber; // simple page } return; } From 8aab1a7a7ba92573cce69d6bb60e6bbefac408a4 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 31 Jul 2012 17:58:28 -0500 Subject: [PATCH 04/39] Fix loading of the font widths --- src/evaluator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evaluator.js b/src/evaluator.js index 059ff113f..fe369db27 100644 --- a/src/evaluator.js +++ b/src/evaluator.js @@ -765,7 +765,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { if (widths) { var start = 0, end = 0; for (var i = 0, ii = widths.length; i < ii; i++) { - var code = widths[i]; + var code = xref.fetchIfRef(widths[i]); if (isArray(code)) { for (var j = 0, jj = code.length; j < jj; j++) glyphsWidths[start++] = code[j]; From 9c14b1abfb08b55d55810d0a7dbbfcee736f6ef5 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 1 Aug 2012 11:05:33 -0500 Subject: [PATCH 05/39] Add ref test --- test/test_manifest.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/test_manifest.json b/test/test_manifest.json index 1b372e906..c3054ed54 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -363,6 +363,14 @@ "link": true, "type": "eq" }, + { "id": "issue1944", + "file": "pdfs/issue1944.pdf", + "md5": "a4ef22c380b55747fb3d4a1c276b0950", + "rounds": 1, + "pageLimit": 2, + "link": true, + "type": "eq" + }, { "id": "issue1586", "file": "pdfs/pdfjsbad1586.pdf", "md5": "793d0870f0b0c613799b0677d64daca4", From 12bc84fd2412a081a7ca529b56bb0a9914fec3a9 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 1 Aug 2012 12:20:52 -0500 Subject: [PATCH 06/39] Missing .link file --- test/pdfs/issue1944.pdf.link | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/pdfs/issue1944.pdf.link diff --git a/test/pdfs/issue1944.pdf.link b/test/pdfs/issue1944.pdf.link new file mode 100644 index 000000000..6a233f06a --- /dev/null +++ b/test/pdfs/issue1944.pdf.link @@ -0,0 +1 @@ +http://mygenshare.com/slideshows/13452/original/original.pdf \ No newline at end of file From 6d35073a9ce2e5f399f913ba80268a80aae6b8bf Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 27 Jul 2012 15:19:43 -0700 Subject: [PATCH 07/39] Initial build for b2g. --- make.js | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ src/core.js | 6 ++-- web/viewer.html | 1 + web/viewer.js | 21 +++++++++++- 4 files changed, 113 insertions(+), 3 deletions(-) diff --git a/make.js b/make.js index 727e740ca..cc6274fac 100755 --- a/make.js +++ b/make.js @@ -1,5 +1,7 @@ #!/usr/bin/env node require('./external/shelljs/make'); +var fs = require('fs'); +var vm = require('vm'); var ROOT_DIR = __dirname + '/', // absolute path to project's root BUILD_DIR = 'build/', @@ -15,6 +17,49 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root MOZCENTRAL_STREAM_CONVERTER_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2291', FIREFOX_STREAM_CONVERTER_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb1'; +function preprocess(inFilename, outFilename, flags) { + // TODO make this really read line by line. + var lines = fs.readFileSync(inFilename).toString().split("\n"); + var totalLines = lines.length; + var out = ''; + var i = 0; + function readLine() { + if (i < totalLines) { + return lines[i++]; + } + return null; + } + function writeLine(line) { + out += line + '\n'; + } + + var s, state = 0, stack = []; + while ((s = readLine()) !== null) { + var m = new RegExp(/^\/\/\s*#(if|else|endif)\b(?:\s+(.*))?/).exec(s); + if (m) { + if (m[1] === "if") { + stack.push(state); + state = vm.runInNewContext(m[2], flags) ? 3 : 1; + } else if (m[1] === "else") { + state = state === 1 ? 3 : 2; + } else { + state = stack.pop(); + } + } else { + if (state === 0) { + writeLine(s); + } else if(state === 3) { + writeLine(s.replace(/^\/\//g, " ")); + } + } + } + fs.writeFileSync(outFilename, out); +} + +target.pre = function() { + preprocess('in.txt', 'out.txt', {B2G: true}); +} + // // make all // @@ -482,6 +527,49 @@ target.mozcentral = function() { cp('-Rf', 'test/mozcentral/*', MOZCENTRAL_TEST_DIR); }; +target.b2g = function() { + echo(); + echo('### Building B2G (Firefox OS App)'); + var B2G_BUILD_DIR = BUILD_DIR + '/b2g/', + B2G_BUILD_CONTENT_DIR = B2G_BUILD_DIR + '/content/'; + target.production(); + target.buildnumber(); + + // Clear out everything in the b2g build directory + cd(ROOT_DIR); + rm('-Rf', B2G_BUILD_DIR); + mkdir('-p', B2G_BUILD_CONTENT_DIR); + mkdir('-p', B2G_BUILD_CONTENT_DIR + BUILD_DIR); + mkdir('-p', B2G_BUILD_CONTENT_DIR + '/web'); + + // Copy a standalone version of pdf.js inside the content directory + cp(BUILD_TARGET, B2G_BUILD_CONTENT_DIR + BUILD_DIR); + cp('-R', EXTENSION_WEB_FILES, B2G_BUILD_CONTENT_DIR + '/web'); + cp('web/viewer-snippet-b2g.html', B2G_BUILD_CONTENT_DIR + '/web/'); + // Replacing the l10n.js file with regular gh-pages one + rm(B2G_BUILD_CONTENT_DIR + '/web/l10n.js'); + cp('external/webL10n/l10n.js', B2G_BUILD_CONTENT_DIR + '/web'); + cp('web/locale.properties', B2G_BUILD_CONTENT_DIR + '/web'); + + mv('-f', B2G_BUILD_CONTENT_DIR + '/web/viewer-production.html', + B2G_BUILD_CONTENT_DIR + '/web/viewer.html'); + cd(B2G_BUILD_CONTENT_DIR + '/web'); + sed('-i', /.*PDFJSSCRIPT_INCLUDE_B2G.*\n/, cat('viewer-snippet-b2g.html'), 'viewer.html'); + rm('viewer-snippet-b2g.html'); + cd(ROOT_DIR); + + var flags = { + B2G: true + }; + var prep = [ + B2G_BUILD_CONTENT_DIR + '/web/viewer.js', + B2G_BUILD_CONTENT_DIR + '/build/pdf.js' + ]; + for (var i in prep) { + preprocess(prep[i], prep[i], flags); + } +}; + // // make chrome // diff --git a/src/core.js b/src/core.js index e8d008074..6d051b152 100644 --- a/src/core.js +++ b/src/core.js @@ -29,9 +29,11 @@ function getPdf(arg, callback) { var params = arg; if (typeof arg === 'string') params = { url: arg }; - +//#if !B2G var xhr = new XMLHttpRequest(); - +//#else +//var xhr = new XMLHttpRequest({mozSystem: true}); +//#endif xhr.open('GET', params.url); var headers = params.headers; diff --git a/web/viewer.html b/web/viewer.html index 58b35464f..d7a57fee4 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -38,6 +38,7 @@ + diff --git a/web/viewer.js b/web/viewer.js index 4de66b5af..f6874f9a9 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1880,8 +1880,9 @@ window.addEventListener('load', function webViewerLoad(evt) { PDFView.sidebarOpen = outerContainer.classList.contains('sidebarOpen'); PDFView.renderHighestPriority(); }); - +//#if !B2G PDFView.open(file, 0); +//#endif }, true); function updateViewarea() { @@ -2140,3 +2141,21 @@ window.addEventListener('afterprint', function afterPrint(evt) { window.addEventListener('mozfullscreenchange', fullscreenChange, false); window.addEventListener('webkitfullscreenchange', fullscreenChange, false); })(); + +//#if B2G +// window.navigator.mozSetMessageHandler('activity', function(activity) { +// var url = activity.source.data.url; +// // Temporarily get the data here since the cross domain xhr is broken in +// // the worker currently, see bug 761227. +// var params = { +// url: url, +// error: function(e) { +// PDFView.error(mozL10n.get('loading_error', null, +// 'An error occurred while loading the PDF.'), e); +// } +// }; +// PDFJS.getPdf(params, function successCallback(data) { +// PDFView.open(data, 0); +// }); +// }); +//#endif From 492fa6edb40fb905059c01b20270535e633247ad Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 11:29:13 -0700 Subject: [PATCH 08/39] Add the new preprocessor. --- make.js | 430 +++++++++++++--------- src/api.js | 25 +- src/pdf.js | 10 +- web/viewer-snippet-firefox-extension.html | 5 +- web/viewer.html | 81 ++-- web/viewer.js | 195 +++++----- 6 files changed, 431 insertions(+), 315 deletions(-) diff --git a/make.js b/make.js index cc6274fac..bb9896391 100755 --- a/make.js +++ b/make.js @@ -1,6 +1,7 @@ #!/usr/bin/env node require('./external/shelljs/make'); var fs = require('fs'); +var path = require('path'); var vm = require('vm'); var ROOT_DIR = __dirname + '/', // absolute path to project's root @@ -10,6 +11,7 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root EXTENSION_SRC_DIR = 'extensions/', LOCALE_SRC_DIR = 'l10n/', GH_PAGES_DIR = BUILD_DIR + 'gh-pages/', + GENERIC_DIR = BUILD_DIR + 'generic/', REPO = 'git@github.com:mozilla/pdf.js.git', PYTHON_BIN = 'python2.7', MOZCENTRAL_PREF_PREFIX = 'pdfjs', @@ -17,48 +19,147 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root MOZCENTRAL_STREAM_CONVERTER_ID = 'd0c5195d-e798-49d4-b1d3-9324328b2291', FIREFOX_STREAM_CONVERTER_ID = '6457a96b-2d68-439a-bcfa-44465fbcdbb1'; -function preprocess(inFilename, outFilename, flags) { - // TODO make this really read line by line. - var lines = fs.readFileSync(inFilename).toString().split("\n"); - var totalLines = lines.length; - var out = ''; - var i = 0; - function readLine() { - if (i < totalLines) { - return lines[i++]; - } - return null; - } - function writeLine(line) { - out += line + '\n'; - } +var DEFINES = { + PRODUCTION: true, + // The main build targets: + GENERIC: false, + FIREFOX: false, + MOZCENTRAL: false, + B2G: false, + CHROME: false +}; - var s, state = 0, stack = []; - while ((s = readLine()) !== null) { - var m = new RegExp(/^\/\/\s*#(if|else|endif)\b(?:\s+(.*))?/).exec(s); - if (m) { - if (m[1] === "if") { - stack.push(state); - state = vm.runInNewContext(m[2], flags) ? 3 : 1; - } else if (m[1] === "else") { - state = state === 1 ? 3 : 2; +function extendDefines(obj) { + var ret = {}; + for (var key in DEFINES) + ret[key] = DEFINES[key]; + for (key in obj) + ret[key] = obj[key]; + return ret; +} + +var BuildHelper = { + /** + * A simple preprocessor that is based on the firefox preprocessor + * see (https://developer.mozilla.org/en/Build/Text_Preprocessor). The main + * difference is that this supports a subset of the commands and it supports + * preproccesor commands in html style comments. + * Currently Supported commands: + * - if + * - else + * - endif + * - include + * - expand + */ + preprocess: function preprocess(inFilename, outFilename, defines) { + // TODO make this really read line by line. + var lines = fs.readFileSync(inFilename).toString().split('\n'); + var totalLines = lines.length; + var out = ''; + var i = 0; + function readLine() { + if (i < totalLines) { + return lines[i++]; + } + return null; + } + var writeLine = typeof outFilename === 'function' ? outFilename : function(line) { + out += line + '\n'; + } + function include(file) { + var realPath = fs.realpathSync(inFilename); + var dir = path.dirname(realPath); + preprocess(path.join(dir, file), writeLine, defines); + } + function expand(line) { + line = line.replace(/__[\w]+__/g, function(variable) { + variable = variable.substring(2, variable.length - 2); + if (variable in defines) { + return defines[variable]; + } + return ''; + }); + writeLine(line); + } + + var s, state = 0, stack = []; + var control = /^(?:\/\/|)?$)?/; + var lineNumber = 0; + while ((s = readLine()) !== null) { + ++lineNumber; + var m = control.exec(s); + if (m) { + switch (m[1]) { + case 'if': + stack.push(state); + try { + state = vm.runInNewContext(m[2], defines) ? 3 : 1; + } catch (e) { + console.error('Could not evalute line \'' + m[2] + '\' at ' + + fs.realpathSync(inFilename) + ':' + lineNumber); + throw e; + } + break; + case 'else': + state = state === 1 ? 3 : 2; + break; + case 'endif': + state = stack.pop(); + break; + case 'expand': + if (state === 0 || state === 3) + expand(m[2]); + break; + case 'include': + if (state === 0 || state === 3) + include(m[2]); + break; + } } else { - state = stack.pop(); - } - } else { - if (state === 0) { - writeLine(s); - } else if(state === 3) { - writeLine(s.replace(/^\/\//g, " ")); + if (state === 0) { + writeLine(s); + } else if(state === 3) { + writeLine(s.replace(/^\/\/|^/g, " ")); + } } } - } - fs.writeFileSync(outFilename, out); -} + if (state !== 0 || stack.length !== 0) + throw new Error('Missing endif in preprocessor.'); + if (typeof outFilename !== 'function') + fs.writeFileSync(outFilename, out); + }, + /** + * Simplifies common build steps. + * @param setup + * .defines defines for preprocessors + * .copy array of arrays of source and destination pairs of files to copy + * .preprocess array of arrays of source and destination pairs of files + * run through preprocessor + */ + build: function build(setup) { + var defines = setup.defines; -target.pre = function() { - preprocess('in.txt', 'out.txt', {B2G: true}); -} + setup.copy.forEach(function(option) { + var source = option[0]; + var destination = option[1]; + cp('-R', source, destination); + }); + + setup.preprocess.forEach(function(option) { + var sources = option[0]; + var destination = option[1]; + + sources = ls('-R', sources); + sources.forEach(function(source) { + // ??? Warn if the source is wildcard and dest is file? + var destWithFolder = destination; + if (test('-d', destination)) + destWithFolder += '/' + path.basename(source); + BuildHelper.preprocess(source, destWithFolder, defines); + }); + }); + } +}; // // make all @@ -76,14 +177,59 @@ target.all = function() { // Production stuff // +// Files that need to be included in every build. +var COMMON_WEB_FILES = + ['web/viewer.css', + 'web/images', + 'web/debugger.js'], + COMMON_WEB_FILES_PREPROCESS = + ['web/viewer.js', + 'web/viewer.html']; + +// +// make generic +// Builds the generic production viewer that should be compatible with most +// modern HTML5 browsers. +// +target.generic = function() { + target.bundle(); + target.locale(); + + cd(ROOT_DIR); + echo(); + echo('### Creating generic viewer'); + + rm('-rf', GENERIC_DIR); + mkdir('-p', GENERIC_DIR); + mkdir('-p', GENERIC_DIR + BUILD_DIR); + mkdir('-p', GENERIC_DIR + '/web'); + + var defines = extendDefines({GENERIC: true}); + + var setup = { + defines: defines, + copy: [ + [COMMON_WEB_FILES, GENERIC_DIR + '/web'], + ['external/webL10n/l10n.js', GENERIC_DIR + '/web'], + ['web/compatibility.js', GENERIC_DIR + '/web'], + ['web/compressed.tracemonkey-pldi-09.pdf', GENERIC_DIR + '/web'], + ['web/locale.properties', GENERIC_DIR + '/web'] + ], + preprocess: [ + [BUILD_TARGET, GENERIC_DIR + BUILD_TARGET], + [COMMON_WEB_FILES_PREPROCESS, GENERIC_DIR + '/web'] + ] + }; + BuildHelper.build(setup); +}; + // // make web // Generates the website for the project, by checking out the gh-pages branch underneath // the build directory, and then moving the various viewer files into place. // target.web = function() { - target.production(); - target.locale(); + target.generic(); target.extension(); target.pagesrepo(); @@ -91,25 +237,18 @@ target.web = function() { echo(); echo('### Creating web site'); - var GH_PAGES_SRC_FILES = [ - 'web/*', - 'external/webL10n/l10n.js' - ]; - - cp(BUILD_TARGET, GH_PAGES_DIR + BUILD_TARGET); - cp('-R', GH_PAGES_SRC_FILES, GH_PAGES_DIR + '/web'); + cp('-R', GENERIC_DIR + '/*', GH_PAGES_DIR); cp(FIREFOX_BUILD_DIR + '/*.xpi', FIREFOX_BUILD_DIR + '/*.rdf', - GH_PAGES_DIR + EXTENSION_SRC_DIR + 'firefox/'); - cp(GH_PAGES_DIR + '/web/index.html.template', GH_PAGES_DIR + '/index.html'); - mv('-f', GH_PAGES_DIR + '/web/viewer-production.html', - GH_PAGES_DIR + '/web/viewer.html'); + GH_PAGES_DIR + EXTENSION_SRC_DIR + 'firefox/'); + cp('web/index.html.template', GH_PAGES_DIR + '/index.html'); + cd(GH_PAGES_DIR); exec('git add -A'); echo(); echo("Website built in " + GH_PAGES_DIR); echo("Don't forget to cd into " + GH_PAGES_DIR + - " and issue 'git commit' to push changes."); + " and issue 'git commit' to push changes."); }; // @@ -169,20 +308,10 @@ target.locale = function() { chromeManifestContent.to(CHROME_MANIFEST_OUTPUT); }; -// -// make production -// Creates production output (pdf.js, and corresponding changes to web/ files) -// -target.production = function() { - target.bundle(); - target.viewer(); -}; - // // make bundle // Bundles all source files into one wrapper 'pdf.js' file, in the given order. // - target.bundle = function() { cd(ROOT_DIR); echo(); @@ -223,29 +352,12 @@ target.bundle = function() { bundleVersion = exec('git log --format="%h" -n 1', {silent: true}).output.replace('\n', ''); - sed(/.*PDFJSSCRIPT_INCLUDE_ALL.*\n/, bundle, 'pdf.js') - .to(ROOT_DIR + BUILD_TARGET); - sed('-i', 'PDFJSSCRIPT_BUNDLE_VER', bundleVersion, ROOT_DIR + BUILD_TARGET); + // This just preprocesses the empty pdf.js file, we don't actually want to + // preprocess everything yet since other build targets use this file. + BuildHelper.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET, + {BUNDLE: bundle, BUNDLE_VERSION: bundleVersion}); }; -// -// make viewer -// Changes development - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/web/viewer.js b/web/viewer.js index f6874f9a9..e2b2e1260 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -90,6 +90,7 @@ var ProgressBar = (function ProgressBarClosure() { return ProgressBar; })(); +//#if FIREFOX || MOZCENTRAL var FirefoxCom = (function FirefoxComClosure() { return { /** @@ -150,6 +151,7 @@ var FirefoxCom = (function FirefoxComClosure() { } }; })(); +//#endif // Settings Manager - This is a utility for saving settings // First we see if localStorage is available @@ -167,17 +169,17 @@ var Settings = (function SettingsClosure() { } })(); - var isFirefoxExtension = PDFJS.isFirefoxExtension; - function Settings(fingerprint) { var database = null; var index; - if (isFirefoxExtension) - database = FirefoxCom.requestSync('getDatabase', null) || '{}'; - else if (isLocalStorageEnabled) +//#if !(FIREFOX || MOZCENTRAL) + if (isLocalStorageEnabled) database = localStorage.getItem('database') || '{}'; else return false; +//#else +// database = FirefoxCom.requestSync('getDatabase', null) || '{}'; +//#endif database = JSON.parse(database); if (!('files' in database)) @@ -205,10 +207,12 @@ var Settings = (function SettingsClosure() { var file = this.file; file[name] = val; var database = JSON.stringify(this.database); - if (isFirefoxExtension) - FirefoxCom.requestSync('setDatabase', database); - else if (isLocalStorageEnabled) +//#if !(FIREFOX || MOZCENTRAL) + if (isLocalStorageEnabled) localStorage.setItem('database', database); +//#else +// FirefoxCom.requestSync('setDatabase', database); +//#endif }, get: function settingsGet(name, defaultValue) { @@ -460,52 +464,54 @@ var PDFView = { } var url = this.url.split('#')[0]; - if (PDFJS.isFirefoxExtension) { - // Document isn't ready just try to download with the url. - if (!this.pdfDocument) { - noData(); - return; - } - this.pdfDocument.getData().then( - function getDataSuccess(data) { - var bb = new MozBlobBuilder(); - bb.append(data.buffer); - var blobUrl = window.URL.createObjectURL( - bb.getBlob('application/pdf')); - - FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url }, - function response(err) { - if (err) { - // This error won't really be helpful because it's likely the - // fallback won't work either (or is already open). - PDFView.error('PDF failed to download.'); - } - window.URL.revokeObjectURL(blobUrl); - } - ); - }, - noData // Error ocurred try downloading with just the url. - ); - } else { - url += '#pdfjs.action=download', '_parent'; - window.open(url, '_parent'); - } +//#if !(FIREFOX || MOZCENTRAL) + url += '#pdfjs.action=download', '_parent'; + window.open(url, '_parent'); +//#else +// // Document isn't ready just try to download with the url. +// if (!this.pdfDocument) { +// noData(); +// return; +// } +// this.pdfDocument.getData().then( +// function getDataSuccess(data) { +// var bb = new MozBlobBuilder(); +// bb.append(data.buffer); +// var blobUrl = window.URL.createObjectURL( +// bb.getBlob('application/pdf')); +// +// FirefoxCom.request('download', { blobUrl: blobUrl, originalUrl: url }, +// function response(err) { +// if (err) { +// // This error won't really be helpful because it's likely the +// // fallback won't work either (or is already open). +// PDFView.error('PDF failed to download.'); +// } +// window.URL.revokeObjectURL(blobUrl); +// } +// ); +// }, +// noData // Error ocurred try downloading with just the url. +// ); +//#endif }, fallback: function pdfViewFallback() { - if (!PDFJS.isFirefoxExtension) +//#if !(FIREFOX || MOZCENTRAL) return; - // Only trigger the fallback once so we don't spam the user with messages - // for one PDF. - if (this.fellback) - return; - this.fellback = true; - var url = this.url.split('#')[0]; - FirefoxCom.request('fallback', url, function response(download) { - if (!download) - return; - PDFView.download(); - }); +//#else +// // Only trigger the fallback once so we don't spam the user with messages +// // for one PDF. +// if (this.fellback) +// return; +// this.fellback = true; +// var url = this.url.split('#')[0]; +// FirefoxCom.request('fallback', url, function response(download) { +// if (!download) +// return; +// PDFView.download(); +// }); +//#endif }, navigateTo: function pdfViewNavigateTo(dest) { @@ -557,9 +563,11 @@ var PDFView = { * @param {String} anchor The anchor hash include the #. */ getAnchorUrl: function getAnchorUrl(anchor) { - if (PDFJS.isFirefoxExtension) - return this.url.split('#')[0] + anchor; +//#if !(FIREFOX || MOZCENTRAL) return anchor; +//#else +// return this.url.split('#')[0] + anchor; +//#endif }, /** @@ -593,11 +601,7 @@ var PDFView = { } } } - if (PDFJS.isFirefoxExtension) { - console.error(message + '\n' + moreInfoText); - this.fallback(); - return; - } +//#if !(FIREFOX || MOZCENTRAL) var errorWrapper = document.getElementById('errorWrapper'); errorWrapper.removeAttribute('hidden'); @@ -627,6 +631,10 @@ var PDFView = { errorMoreInfo.value = moreInfoText; errorMoreInfo.rows = moreInfoText.split('\n').length - 1; +//#else +// console.error(message + '\n' + moreInfoText); +// this.fallback(); +//#endif }, progress: function pdfViewProgress(level) { @@ -1804,15 +1812,21 @@ window.addEventListener('load', function webViewerLoad(evt) { PDFView.initialize(); var params = PDFView.parseQueryString(document.location.search.substring(1)); - var file = PDFJS.isFirefoxExtension ? - window.location.toString() : params.file || kDefaultURL; +//#if !(FIREFOX || MOZCENTRAL) + var file = params.file || kDefaultURL; +//#else +//var file = window.location.toString() +//#endif - if (PDFJS.isFirefoxExtension || !window.File || !window.FileReader || - !window.FileList || !window.Blob) { +//#if !(FIREFOX || MOZCENTRAL) + if (!window.File || !window.FileReader || !window.FileList || !window.Blob) { document.getElementById('openFile').setAttribute('hidden', 'true'); } else { document.getElementById('fileInput').value = null; } +//#else +//document.getElementById('openFile').setAttribute('hidden', 'true'); +//#endif // Special debugging flags in the hash section of the URL. var hash = document.location.hash.substring(1); @@ -1821,18 +1835,21 @@ window.addEventListener('load', function webViewerLoad(evt) { if ('disableWorker' in hashParams) PDFJS.disableWorker = (hashParams['disableWorker'] === 'true'); - if (!PDFJS.isFirefoxExtension) { - var locale = navigator.language; - if ('locale' in hashParams) - locale = hashParams['locale']; - mozL10n.language.code = locale; - } +//#if !(FIREFOX || MOZCENTRAL) + var locale = navigator.language; + if ('locale' in hashParams) + locale = hashParams['locale']; + mozL10n.language.code = locale; +//#endif if ('disableTextLayer' in hashParams) PDFJS.disableTextLayer = (hashParams['disableTextLayer'] === 'true'); - if ('pdfBug' in hashParams && - (!PDFJS.isFirefoxExtension || FirefoxCom.requestSync('pdfBugEnabled'))) { +//#if !(FIREFOX || MOZCENTRAL) + if ('pdfBug' in hashParams) { +//#else +//if ('pdfBug' in hashParams && FirefoxCom.requestSync('pdfBugEnabled')) { +//#endif PDFJS.pdfBug = true; var pdfBug = hashParams['pdfBug']; var enabled = pdfBug.split(','); @@ -1840,10 +1857,12 @@ window.addEventListener('load', function webViewerLoad(evt) { PDFBug.init(); } - if (!PDFJS.isFirefoxExtension || - (PDFJS.isFirefoxExtension && FirefoxCom.requestSync('searchEnabled'))) { - document.querySelector('#viewSearch').classList.remove('hidden'); - } +//#if !(FIREFOX || MOZCENTRAL) +//#else +//if (FirefoxCom.requestSync('searchEnabled')) { +// document.querySelector('#viewSearch').classList.remove('hidden'); +//} +//#endif if (!PDFView.supportsPrinting) { document.getElementById('print').classList.add('hidden'); @@ -2143,19 +2162,19 @@ window.addEventListener('afterprint', function afterPrint(evt) { })(); //#if B2G -// window.navigator.mozSetMessageHandler('activity', function(activity) { -// var url = activity.source.data.url; -// // Temporarily get the data here since the cross domain xhr is broken in -// // the worker currently, see bug 761227. -// var params = { -// url: url, -// error: function(e) { -// PDFView.error(mozL10n.get('loading_error', null, -// 'An error occurred while loading the PDF.'), e); -// } -// }; -// PDFJS.getPdf(params, function successCallback(data) { -// PDFView.open(data, 0); -// }); -// }); +//window.navigator.mozSetMessageHandler('activity', function(activity) { +// var url = activity.source.data.url; +// // Temporarily get the data here since the cross domain xhr is broken in +// // the worker currently, see bug 761227. +// var params = { +// url: url, +// error: function(e) { +// PDFView.error(mozL10n.get('loading_error', null, +// 'An error occurred while loading the PDF.'), e); +// } +// }; +// PDFJS.getPdf(params, function successCallback(data) { +// PDFView.open(data, 0); +// }); +//}); //#endif From dd22f449538a2a56c09e91e390874ac6da2e4847 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 11:52:14 -0700 Subject: [PATCH 09/39] Update the readme to reflect build changes. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3b8d86bb1..34b1a3f5e 100644 --- a/README.md +++ b/README.md @@ -61,13 +61,13 @@ You can also view all the test pdf files on the right side serving + http://localhost:8888/test/pdfs/?frame -### Building pdf.js +### Building pdf.js. -In order to bundle all `src/` files into a final `pdf.js`, issue: +In order to bundle all `src/` files into a final `pdf.js` and build the generic viewer, issue: - $ node make bundle + $ node make generic -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). +This will generate the file `build/generic/build/pdf.js` that can be included in your final project. The pdf.js file is large and should be minified for production. Also, if you would like to support more browsers than firefox you'll also need to include `compatibility.js` from `build/generic/web/`. # Learning From 2c1eae5819933f9ef8fe4d8776debb7af6fcb4dd Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 12:05:03 -0700 Subject: [PATCH 10/39] Remove trailing whitespace. --- make.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make.js b/make.js index bb9896391..670aa6645 100755 --- a/make.js +++ b/make.js @@ -178,7 +178,7 @@ target.all = function() { // // Files that need to be included in every build. -var COMMON_WEB_FILES = +var COMMON_WEB_FILES = ['web/viewer.css', 'web/images', 'web/debugger.js'], From 44a6afb282e298581ad61284bcce28da38197e2c Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 12:16:28 -0700 Subject: [PATCH 11/39] Fix mozcentral build. --- web/viewer.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/viewer.html b/web/viewer.html index b97ba3a4c..daec51172 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -5,7 +5,7 @@ PDF.js viewer - + @@ -14,7 +14,7 @@ - + From 41a427246370eccef480c6177b3b18def3877af1 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 1 Aug 2012 15:10:48 -0500 Subject: [PATCH 12/39] Implement textRise; reduce ref test to one page --- src/canvas.js | 5 +++-- test/test_manifest.json | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index 32c171216..058b57b7e 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -157,6 +157,7 @@ var CanvasExtraState = (function CanvasExtraStateClosure() { this.wordSpacing = 0; this.textHScale = 1; this.textRenderingMode = TextRenderingMode.FILL; + this.textRise = 0; // Color spaces this.fillColorSpace = new DeviceGrayCS(); this.fillColorSpaceObj = null; @@ -601,7 +602,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { this.current.textRenderingMode = mode; }, setTextRise: function CanvasGraphics_setTextRise(rise) { - TODO('text rise: ' + rise); + this.current.textRise = rise; }, moveText: function CanvasGraphics_moveText(x, y) { this.current.x = this.current.lineX += x; @@ -628,7 +629,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { ctx.transform.apply(ctx, current.textMatrix); ctx.scale(1, -1); - ctx.translate(current.x, -1 * current.y); + ctx.translate(current.x, -current.y - current.textRise); ctx.transform.apply(ctx, fontMatrix); ctx.scale(textHScale, 1); }, diff --git a/test/test_manifest.json b/test/test_manifest.json index c3054ed54..8651fc953 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -367,7 +367,7 @@ "file": "pdfs/issue1944.pdf", "md5": "a4ef22c380b55747fb3d4a1c276b0950", "rounds": 1, - "pageLimit": 2, + "pageLimit": 1, "link": true, "type": "eq" }, From e0a6b233dc6880a357024b5d7955902f01b0c7cb Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 14:27:42 -0700 Subject: [PATCH 13/39] Move builder/preprocessor into its own file. --- external/builder/builder.js | 142 ++++++++++++++++++++++++++++++++ make.js | 160 +++--------------------------------- 2 files changed, 155 insertions(+), 147 deletions(-) create mode 100644 external/builder/builder.js diff --git a/external/builder/builder.js b/external/builder/builder.js new file mode 100644 index 000000000..6eb0cd6ae --- /dev/null +++ b/external/builder/builder.js @@ -0,0 +1,142 @@ +require('../shelljs/make'); +var fs = require('fs'), + path = require('path'), + vm = require('vm'); + +/** + * A simple preprocessor that is based on the firefox preprocessor + * see (https://developer.mozilla.org/en/Build/Text_Preprocessor). The main + * difference is that this supports a subset of the commands and it supports + * preproccesor commands in html style comments. + * Currently Supported commands: + * - if + * - else + * - endif + * - include + * - expand + */ +function preprocess(inFilename, outFilename, defines) { + // TODO make this really read line by line. + var lines = fs.readFileSync(inFilename).toString().split('\n'); + var totalLines = lines.length; + var out = ''; + var i = 0; + function readLine() { + if (i < totalLines) { + return lines[i++]; + } + return null; + } + var writeLine = typeof outFilename === 'function' ? outFilename : function(line) { + out += line + '\n'; + } + function include(file) { + var realPath = fs.realpathSync(inFilename); + var dir = path.dirname(realPath); + preprocess(path.join(dir, file), writeLine, defines); + } + function expand(line) { + line = line.replace(/__[\w]+__/g, function(variable) { + variable = variable.substring(2, variable.length - 2); + if (variable in defines) { + return defines[variable]; + } + return ''; + }); + writeLine(line); + } + + var s, state = 0, stack = []; + var control = /^(?:\/\/|)?$)?/; + var lineNumber = 0; + while ((s = readLine()) !== null) { + ++lineNumber; + var m = control.exec(s); + if (m) { + switch (m[1]) { + case 'if': + stack.push(state); + try { + state = vm.runInNewContext(m[2], defines) ? 3 : 1; + } catch (e) { + console.error('Could not evalute line \'' + m[2] + '\' at ' + + fs.realpathSync(inFilename) + ':' + lineNumber); + throw e; + } + break; + case 'else': + state = state === 1 ? 3 : 2; + break; + case 'endif': + state = stack.pop(); + break; + case 'expand': + if (state === 0 || state === 3) + expand(m[2]); + break; + case 'include': + if (state === 0 || state === 3) + include(m[2]); + break; + } + } else { + if (state === 0) { + writeLine(s); + } else if(state === 3) { + writeLine(s.replace(/^\/\/|^/g, " ")); + } + } + } + if (state !== 0 || stack.length !== 0) + throw new Error('Missing endif in preprocessor.'); + if (typeof outFilename !== 'function') + fs.writeFileSync(outFilename, out); +} +exports.preprocess = preprocess; + +/** + * Simplifies common build steps. + * @param setup + * .defines defines for preprocessors + * .copy array of arrays of source and destination pairs of files to copy + * .preprocess array of arrays of source and destination pairs of files + * run through preprocessor + */ +function build(setup) { + var defines = setup.defines; + + setup.copy.forEach(function(option) { + var source = option[0]; + var destination = option[1]; + cp('-R', source, destination); + }); + + setup.preprocess.forEach(function(option) { + var sources = option[0]; + var destination = option[1]; + + sources = ls('-R', sources); + sources.forEach(function(source) { + // ??? Warn if the source is wildcard and dest is file? + var destWithFolder = destination; + if (test('-d', destination)) + destWithFolder += '/' + path.basename(source); + preprocess(source, destWithFolder, defines); + }); + }); +} +exports.build = build; + +/** + * Merge two defines arrays. Values in the second param will override values in + * the first. + */ +function merge(defaults, defines) { + var ret = {}; + for (var key in defaults) + ret[key] = defaults[key]; + for (key in defines) + ret[key] = defines[key]; + return ret; +} +exports.merge = merge; diff --git a/make.js b/make.js index 670aa6645..1d2e5cfcf 100755 --- a/make.js +++ b/make.js @@ -1,8 +1,6 @@ #!/usr/bin/env node require('./external/shelljs/make'); -var fs = require('fs'); -var path = require('path'); -var vm = require('vm'); +var builder = require('./external/builder/builder.js'); var ROOT_DIR = __dirname + '/', // absolute path to project's root BUILD_DIR = 'build/', @@ -29,138 +27,6 @@ var DEFINES = { CHROME: false }; -function extendDefines(obj) { - var ret = {}; - for (var key in DEFINES) - ret[key] = DEFINES[key]; - for (key in obj) - ret[key] = obj[key]; - return ret; -} - -var BuildHelper = { - /** - * A simple preprocessor that is based on the firefox preprocessor - * see (https://developer.mozilla.org/en/Build/Text_Preprocessor). The main - * difference is that this supports a subset of the commands and it supports - * preproccesor commands in html style comments. - * Currently Supported commands: - * - if - * - else - * - endif - * - include - * - expand - */ - preprocess: function preprocess(inFilename, outFilename, defines) { - // TODO make this really read line by line. - var lines = fs.readFileSync(inFilename).toString().split('\n'); - var totalLines = lines.length; - var out = ''; - var i = 0; - function readLine() { - if (i < totalLines) { - return lines[i++]; - } - return null; - } - var writeLine = typeof outFilename === 'function' ? outFilename : function(line) { - out += line + '\n'; - } - function include(file) { - var realPath = fs.realpathSync(inFilename); - var dir = path.dirname(realPath); - preprocess(path.join(dir, file), writeLine, defines); - } - function expand(line) { - line = line.replace(/__[\w]+__/g, function(variable) { - variable = variable.substring(2, variable.length - 2); - if (variable in defines) { - return defines[variable]; - } - return ''; - }); - writeLine(line); - } - - var s, state = 0, stack = []; - var control = /^(?:\/\/|)?$)?/; - var lineNumber = 0; - while ((s = readLine()) !== null) { - ++lineNumber; - var m = control.exec(s); - if (m) { - switch (m[1]) { - case 'if': - stack.push(state); - try { - state = vm.runInNewContext(m[2], defines) ? 3 : 1; - } catch (e) { - console.error('Could not evalute line \'' + m[2] + '\' at ' + - fs.realpathSync(inFilename) + ':' + lineNumber); - throw e; - } - break; - case 'else': - state = state === 1 ? 3 : 2; - break; - case 'endif': - state = stack.pop(); - break; - case 'expand': - if (state === 0 || state === 3) - expand(m[2]); - break; - case 'include': - if (state === 0 || state === 3) - include(m[2]); - break; - } - } else { - if (state === 0) { - writeLine(s); - } else if(state === 3) { - writeLine(s.replace(/^\/\/|^/g, " ")); - } - } - } - if (state !== 0 || stack.length !== 0) - throw new Error('Missing endif in preprocessor.'); - if (typeof outFilename !== 'function') - fs.writeFileSync(outFilename, out); - }, - /** - * Simplifies common build steps. - * @param setup - * .defines defines for preprocessors - * .copy array of arrays of source and destination pairs of files to copy - * .preprocess array of arrays of source and destination pairs of files - * run through preprocessor - */ - build: function build(setup) { - var defines = setup.defines; - - setup.copy.forEach(function(option) { - var source = option[0]; - var destination = option[1]; - cp('-R', source, destination); - }); - - setup.preprocess.forEach(function(option) { - var sources = option[0]; - var destination = option[1]; - - sources = ls('-R', sources); - sources.forEach(function(source) { - // ??? Warn if the source is wildcard and dest is file? - var destWithFolder = destination; - if (test('-d', destination)) - destWithFolder += '/' + path.basename(source); - BuildHelper.preprocess(source, destWithFolder, defines); - }); - }); - } -}; - // // make all // @@ -204,7 +70,7 @@ target.generic = function() { mkdir('-p', GENERIC_DIR + BUILD_DIR); mkdir('-p', GENERIC_DIR + '/web'); - var defines = extendDefines({GENERIC: true}); + var defines = builder.merge(DEFINES, {GENERIC: true}); var setup = { defines: defines, @@ -220,7 +86,7 @@ target.generic = function() { [COMMON_WEB_FILES_PREPROCESS, GENERIC_DIR + '/web'] ] }; - BuildHelper.build(setup); + builder.build(setup); }; // @@ -354,7 +220,7 @@ target.bundle = function() { // This just preprocesses the empty pdf.js file, we don't actually want to // preprocess everything yet since other build targets use this file. - BuildHelper.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET, + builder.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET, {BUNDLE: bundle, BUNDLE_VERSION: bundleVersion}); }; @@ -435,7 +301,7 @@ target.firefox = function() { cd(ROOT_DIR); echo(); echo('### Building Firefox extension'); - var defines = extendDefines({FIREFOX: true}); + var defines = builder.merge(DEFINES, {FIREFOX: true}); var FIREFOX_BUILD_CONTENT_DIR = FIREFOX_BUILD_DIR + '/content/', FIREFOX_EXTENSION_DIR = 'extensions/firefox/', @@ -488,7 +354,7 @@ target.firefox = function() { [COMMON_WEB_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR + '/web'] ] }; - BuildHelper.build(setup); + builder.build(setup); // Remove '.DS_Store' and other hidden files find(FIREFOX_BUILD_DIR).forEach(function(file) { @@ -531,7 +397,7 @@ target.mozcentral = function() { cd(ROOT_DIR); echo(); echo('### Building mozilla-central extension'); - var defines = extendDefines({MOZCENTRAL: true}); + var defines = builder.merge(DEFINES, {MOZCENTRAL: true}); var MOZCENTRAL_DIR = BUILD_DIR + 'mozcentral/', MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + 'browser/extensions/pdfjs/', @@ -586,7 +452,7 @@ target.mozcentral = function() { [COMMON_WEB_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR + '/web'] ] }; - BuildHelper.build(setup); + builder.build(setup); // Remove '.DS_Store' and other hidden files find(MOZCENTRAL_DIR).forEach(function(file) { @@ -624,9 +490,9 @@ target.b2g = function() { echo('### Building B2G (Firefox OS App)'); var B2G_BUILD_DIR = BUILD_DIR + '/b2g/', B2G_BUILD_CONTENT_DIR = B2G_BUILD_DIR + '/content/'; - var defines = extendDefines({ B2G: true }); + var defines = builder.merge(DEFINES, { B2G: true }); target.bundle(); - + // Clear out everything in the b2g build directory cd(ROOT_DIR); rm('-Rf', B2G_BUILD_DIR); @@ -646,7 +512,7 @@ target.b2g = function() { [BUILD_TARGET, B2G_BUILD_CONTENT_DIR + BUILD_TARGET] ] }; - BuildHelper.build(setup); + builder.build(setup); }; // @@ -656,7 +522,7 @@ target.chrome = function() { cd(ROOT_DIR); echo(); echo('### Building Chrome extension'); - var defines = extendDefines({CHROME: true}); + var defines = builder.merge(DEFINES, {CHROME: true}); var CHROME_BUILD_DIR = BUILD_DIR + '/chrome/', CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + '/content/'; @@ -684,7 +550,7 @@ target.chrome = function() { ['web/locale.properties', CHROME_BUILD_CONTENT_DIR + '/web'] ] }; - BuildHelper.build(setup); + builder.build(setup); }; From 11be208388a7760240ad4ebd841e639d4e488227 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 1 Aug 2012 15:31:25 -0700 Subject: [PATCH 14/39] Move firefoxcom to its own file. --- web/firefoxcom.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++ web/viewer.js | 61 +---------------------------------------------- 2 files changed, 61 insertions(+), 60 deletions(-) create mode 100644 web/firefoxcom.js diff --git a/web/firefoxcom.js b/web/firefoxcom.js new file mode 100644 index 000000000..f60c26aed --- /dev/null +++ b/web/firefoxcom.js @@ -0,0 +1,60 @@ +var FirefoxCom = (function FirefoxComClosure() { + return { + /** + * Creates an event that the extension is listening for and will + * synchronously respond to. + * NOTE: It is reccomended to use request() instead since one day we may not + * be able to synchronously reply. + * @param {String} action The action to trigger. + * @param {String} data Optional data to send. + * @return {*} The response. + */ + requestSync: function(action, data) { + var request = document.createTextNode(''); + request.setUserData('action', action, null); + request.setUserData('data', data, null); + request.setUserData('sync', true, null); + document.documentElement.appendChild(request); + + var sender = document.createEvent('Events'); + sender.initEvent('pdf.js.message', true, false); + request.dispatchEvent(sender); + var response = request.getUserData('response'); + document.documentElement.removeChild(request); + return response; + }, + /** + * Creates an event that the extension is listening for and will + * asynchronously respond by calling the callback. + * @param {String} action The action to trigger. + * @param {String} data Optional data to send. + * @param {Function} callback Optional response callback that will be called + * with one data argument. + */ + request: function(action, data, callback) { + var request = document.createTextNode(''); + request.setUserData('action', action, null); + request.setUserData('data', data, null); + request.setUserData('sync', false, null); + if (callback) { + request.setUserData('callback', callback, null); + + document.addEventListener('pdf.js.response', function listener(event) { + var node = event.target, + callback = node.getUserData('callback'), + response = node.getUserData('response'); + + document.documentElement.removeChild(node); + + document.removeEventListener('pdf.js.response', listener, false); + return callback(response); + }, false); + } + document.documentElement.appendChild(request); + + var sender = document.createEvent('HTMLEvents'); + sender.initEvent('pdf.js.message', true, false); + return request.dispatchEvent(sender); + } + }; +})(); diff --git a/web/viewer.js b/web/viewer.js index e2b2e1260..92c38c31e 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -91,66 +91,7 @@ var ProgressBar = (function ProgressBarClosure() { })(); //#if FIREFOX || MOZCENTRAL -var FirefoxCom = (function FirefoxComClosure() { - return { - /** - * Creates an event that the extension is listening for and will - * synchronously respond to. - * NOTE: It is reccomended to use request() instead since one day we may not - * be able to synchronously reply. - * @param {String} action The action to trigger. - * @param {String} data Optional data to send. - * @return {*} The response. - */ - requestSync: function(action, data) { - var request = document.createTextNode(''); - request.setUserData('action', action, null); - request.setUserData('data', data, null); - request.setUserData('sync', true, null); - document.documentElement.appendChild(request); - - var sender = document.createEvent('Events'); - sender.initEvent('pdf.js.message', true, false); - request.dispatchEvent(sender); - var response = request.getUserData('response'); - document.documentElement.removeChild(request); - return response; - }, - /** - * Creates an event that the extension is listening for and will - * asynchronously respond by calling the callback. - * @param {String} action The action to trigger. - * @param {String} data Optional data to send. - * @param {Function} callback Optional response callback that will be called - * with one data argument. - */ - request: function(action, data, callback) { - var request = document.createTextNode(''); - request.setUserData('action', action, null); - request.setUserData('data', data, null); - request.setUserData('sync', false, null); - if (callback) { - request.setUserData('callback', callback, null); - - document.addEventListener('pdf.js.response', function listener(event) { - var node = event.target, - callback = node.getUserData('callback'), - response = node.getUserData('response'); - - document.documentElement.removeChild(node); - - document.removeEventListener('pdf.js.response', listener, false); - return callback(response); - }, false); - } - document.documentElement.appendChild(request); - - var sender = document.createEvent('HTMLEvents'); - sender.initEvent('pdf.js.message', true, false); - return request.dispatchEvent(sender); - } - }; -})(); +//#include firefoxcom.js //#endif // Settings Manager - This is a utility for saving settings From 0bf583412a4817d8b0c6eb62eaf558b1fc65dcf4 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 2 Aug 2012 09:09:07 -0700 Subject: [PATCH 15/39] Add missing b2g snippet. --- web/viewer-snippet-b2g.html | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 web/viewer-snippet-b2g.html diff --git a/web/viewer-snippet-b2g.html b/web/viewer-snippet-b2g.html new file mode 100644 index 000000000..86a09d255 --- /dev/null +++ b/web/viewer-snippet-b2g.html @@ -0,0 +1,9 @@ + + + + + From 3c4efb2f796b5ab10b06a53452e6b371ca2a4652 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 2 Aug 2012 11:54:40 -0500 Subject: [PATCH 16/39] Removes issue1944 reftest --- test/pdfs/issue1944.pdf.link | 1 - test/test_manifest.json | 8 -------- 2 files changed, 9 deletions(-) delete mode 100644 test/pdfs/issue1944.pdf.link diff --git a/test/pdfs/issue1944.pdf.link b/test/pdfs/issue1944.pdf.link deleted file mode 100644 index 6a233f06a..000000000 --- a/test/pdfs/issue1944.pdf.link +++ /dev/null @@ -1 +0,0 @@ -http://mygenshare.com/slideshows/13452/original/original.pdf \ No newline at end of file diff --git a/test/test_manifest.json b/test/test_manifest.json index 8651fc953..1b372e906 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -363,14 +363,6 @@ "link": true, "type": "eq" }, - { "id": "issue1944", - "file": "pdfs/issue1944.pdf", - "md5": "a4ef22c380b55747fb3d4a1c276b0950", - "rounds": 1, - "pageLimit": 1, - "link": true, - "type": "eq" - }, { "id": "issue1586", "file": "pdfs/pdfjsbad1586.pdf", "md5": "793d0870f0b0c613799b0677d64daca4", From 129e81de9fbfa7d2e6a59f81e3129f7075a6fda8 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Thu, 2 Aug 2012 12:06:43 -0700 Subject: [PATCH 17/39] Clean up the test manifest file. --- test/pdfs/issue1001.pdf.link | 1 - test/pdfs/lista_preliminar.pdf.link | 1 - test/pdfs/wdsg_fitc.pdf.link | 2 +- test/test_manifest.json | 17 +---------------- 4 files changed, 2 insertions(+), 19 deletions(-) delete mode 100644 test/pdfs/issue1001.pdf.link delete mode 100644 test/pdfs/lista_preliminar.pdf.link diff --git a/test/pdfs/issue1001.pdf.link b/test/pdfs/issue1001.pdf.link deleted file mode 100644 index 24e1bebc2..000000000 --- a/test/pdfs/issue1001.pdf.link +++ /dev/null @@ -1 +0,0 @@ -http://www.myhillsapartment.com/island_club/floorplans/images/links/Island_IC_brochure.pdf diff --git a/test/pdfs/lista_preliminar.pdf.link b/test/pdfs/lista_preliminar.pdf.link deleted file mode 100644 index 54102b3b1..000000000 --- a/test/pdfs/lista_preliminar.pdf.link +++ /dev/null @@ -1 +0,0 @@ -http://www.lfg.com.br/concursodebolsas/lista_preliminar_classificao.pdf diff --git a/test/pdfs/wdsg_fitc.pdf.link b/test/pdfs/wdsg_fitc.pdf.link index 77d3b590d..bd22b86ba 100644 --- a/test/pdfs/wdsg_fitc.pdf.link +++ b/test/pdfs/wdsg_fitc.pdf.link @@ -1 +1 @@ -http://www.airgid.com/book/wdsg_fitc.pdf +http://www.airgid.com/wp-content/uploads/2012/06/wdsg_fitc.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 1b372e906..0a22160b9 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -334,14 +334,6 @@ "skipPages": [1], "type": "eq" }, - { "id": "lista_preliminar", - "file": "pdfs/lista_preliminar.pdf", - "md5": "4eff251319eeb660ba8a7a5cfac7787d", - "rounds": 1, - "link": true, - "pageLimit": 3, - "type": "eq" - }, { "id": "issue919", "file": "pdfs/issue919.pdf", "md5": "3a1716a512aca4d7a8d6106bd4885d14", @@ -356,13 +348,6 @@ "rounds": 1, "type": "eq" }, - { "id": "issue1001", - "file": "pdfs/issue1001.pdf", - "md5": "0f1496e80a82a923e91d9e74c55ad94e", - "rounds": 1, - "link": true, - "type": "eq" - }, { "id": "issue1586", "file": "pdfs/pdfjsbad1586.pdf", "md5": "793d0870f0b0c613799b0677d64daca4", @@ -421,7 +406,7 @@ "file": "pdfs/issue1096.pdf", "md5": "7f75d2b4b93c78d401ff39e8c1b00612", "rounds": 1, - "pageLimit": 10, + "pageLimit": 9, "link": true, "type": "eq" }, From 29263836c24053180e7b38d4d2b2d885f6bda6de Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 3 Aug 2012 16:11:43 -0700 Subject: [PATCH 18/39] Sanitize the document info. --- src/core.js | 43 +++++++++++++++++++++++++++++------- test/pdfs/issue1729.pdf.link | 2 ++ test/test_manifest.json | 8 +++++++ 3 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 test/pdfs/issue1729.pdf.link diff --git a/src/core.js b/src/core.js index e8d008074..1ee01d7e5 100644 --- a/src/core.js +++ b/src/core.js @@ -403,6 +403,24 @@ var PDFDocument = (function PDFDocumentClosure() { return true; /* found */ } + var DOCUMENT_INFO = { + get entries() { + // Lazily build this since all the validation functions below are not + // defined until after this file loads. + return shadow(this, 'entries', { + Title: isString, + Author: isString, + Subject: isString, + Keywords: isString, + Creator: isString, + Producer: isString, + CreationDate: isString, + ModDate: isString, + Trapped: isName + }); + } + }; + PDFDocument.prototype = { get linearization() { var length = this.stream.length; @@ -495,18 +513,27 @@ var PDFDocument = (function PDFDocumentClosure() { return shadow(this, 'numPages', num); }, getDocumentInfo: function PDFDocument_getDocumentInfo() { - var info; + var docInfo; if (this.xref.trailer.has('Info')) { var infoDict = this.xref.trailer.get('Info'); - info = {}; - infoDict.forEach(function(key, value) { - info[key] = typeof value !== 'string' ? value : - stringToPDFString(value); - }); + docInfo = {}; + var validEntries = DOCUMENT_INFO.entries; + // Only fill the document info with valid entries from the spec. + for (var key in validEntries) { + if (infoDict.has(key)) { + var value = infoDict.get(key); + // Make sure the value conforms to the spec. + if (validEntries[key](value)) { + docInfo[key] = typeof value !== 'string' ? value : + stringToPDFString(value); + } else { + info('Bad value in document info for "' + key + '"'); + } + } + } } - - return shadow(this, 'getDocumentInfo', info); + return shadow(this, 'getDocumentInfo', docInfo); }, getFingerprint: function PDFDocument_getFingerprint() { var xref = this.xref, fileID; diff --git a/test/pdfs/issue1729.pdf.link b/test/pdfs/issue1729.pdf.link new file mode 100644 index 000000000..ca6fa690c --- /dev/null +++ b/test/pdfs/issue1729.pdf.link @@ -0,0 +1,2 @@ +http://www.environmentallights.com/files/documents/ir_light_hazard.pdf + diff --git a/test/test_manifest.json b/test/test_manifest.json index 0a22160b9..166b4fdc7 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -626,5 +626,13 @@ "pageLimit": 1, "link": true, "type": "eq" + }, + { "id": "issue1729", + "file": "pdfs/issue1729.pdf", + "md5": "29b0eddc3e1dcb23a44384037032d470", + "rounds": 1, + "pageLimit": 1, + "link": true, + "type": "load" } ] From 41b8a9816b727945d9f0cc6ff28065a6ed361453 Mon Sep 17 00:00:00 2001 From: Adolfo Jayme Barrientos Date: Sat, 4 Aug 2012 08:30:35 -0500 Subject: [PATCH 19/39] Update Spanish l10n New strings added, a few tweaks have been made as well. --- l10n/es/viewer.properties | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/l10n/es/viewer.properties b/l10n/es/viewer.properties index 8e7080d03..8485cbf17 100644 --- a/l10n/es/viewer.properties +++ b/l10n/es/viewer.properties @@ -18,11 +18,13 @@ zoom_in_label=Ampliar zoom.title=Ampliación print.title=Imprimir print_label=Imprimir +fullscreen.title=Pantalla completa +fullscreen_label=Pantalla completa open_file.title=Abrir archivo open_file_label=Abrir download.title=Descargar download_label=Descargar -bookmark.title=Vista actual (copiar o abrir en una ventana nueva) +bookmark.title=Vista actual (copie o abra en una ventana nueva) bookmark_label=Vista actual # Tooltips and alt text for side panel toolbar buttons @@ -69,7 +71,7 @@ error_stack=Pila: {{stack}} error_file=Archivo: {{file}} # LOCALIZATION NOTE (error_line): "{{line}}" will be replaced with a line number error_line=Línea: {{line}} -rendering_error=Ocurrió un error al renderizar la página. +rendering_error=Ocurrió un error mientras se renderizaba la página. # Predefined zoom values page_scale_width=Anchura de página @@ -79,7 +81,7 @@ page_scale_actual=Tamaño real # Loading indicator messages loading_error_indicator=Error -loading_error=Ocurrió un error al cargar el PDF. +loading_error=Ocurrió un error mientras se cargaba el PDF. # LOCALIZATION NOTE (text_annotation_type): This is used as a tooltip. # "{{type}}" will be replaced with an annotation type from a list defined in @@ -87,3 +89,5 @@ loading_error=Ocurrió un error al cargar el PDF. # Some common types are e.g.: "Check", "Text", "Comment", "Note" text_annotation_type=[Anotación {{type}}] request_password=El PDF está protegido con una contraseña: + +printing_not_supported=Aviso: La impresión no es compatible totalmente con este navegador. From 69eca3c50f29a53c60823f19c7a2659e9e652513 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Mon, 6 Aug 2012 08:51:20 -0700 Subject: [PATCH 20/39] Use timeout for font ready callback to avoid intermittent chrome failures. --- src/fonts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fonts.js b/src/fonts.js index 7b2dfbd4a..b16c2621a 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -418,7 +418,8 @@ var FontLoader = { document.documentElement.removeEventListener( 'pdfjsFontLoad', checkFontsLoaded, false); - callback(); + // Use timeout to fix chrome intermittent failures on font loading. + setTimeout(callback, 0); return true; } From c515bd2c523c5ce4c3c2b77d6c18b0c25ca7f389 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 6 Aug 2012 11:47:34 -0500 Subject: [PATCH 21/39] Adds overrideMimeType for IE10 --- web/compatibility.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/web/compatibility.js b/web/compatibility.js index 4b7119c63..2b8fb8c84 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -127,21 +127,24 @@ // No XMLHttpRequest.response ? (function checkXMLHttpRequestResponseCompatibility() { var xhrPrototype = XMLHttpRequest.prototype; + if (!('overrideMimeType' in xhrPrototype)) { + // IE10 might have response, but not overrideMimeType + Object.defineProperty(xhrPrototype, 'overrideMimeType', { + value: function xmlHttpRequestOverrideMimeType(mimeType) {} + }); + } if ('response' in xhrPrototype || 'mozResponseArrayBuffer' in xhrPrototype || 'mozResponse' in xhrPrototype || 'responseArrayBuffer' in xhrPrototype) return; - // IE ? + // IE9 ? if (typeof VBArray !== 'undefined') { Object.defineProperty(xhrPrototype, 'response', { get: function xmlHttpRequestResponseGet() { return new Uint8Array(new VBArray(this.responseBody).toArray()); } }); - Object.defineProperty(xhrPrototype, 'overrideMimeType', { - value: function xmlHttpRequestOverrideMimeType(mimeType) {} - }); return; } From b272cb7d1d692db353eb52c67f91fdf7e4ba4c4a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Mon, 6 Aug 2012 12:50:47 -0500 Subject: [PATCH 22/39] Using readAsArrayBuffer --- web/compatibility.js | 36 ++++++++++++++++++++++++++++++++++++ web/viewer.js | 11 ++--------- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/web/compatibility.js b/web/compatibility.js index 2b8fb8c84..5a16b3d7f 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -124,6 +124,42 @@ }; })(); +// No readAsArrayBuffer ? +(function checkFileReaderReadAsArrayBuffer() { + if (typeof FileReader === 'undefined') + return; // FileReader is not implemented + var frPrototype = FileReader.prototype; + // Older versions of Firefox might not have readAsArrayBuffer + if ('readAsArrayBuffer' in frPrototype) + return; // readAsArrayBuffer is implemented + Object.defineProperty(frPrototype, 'readAsArrayBuffer', { + value: function fileReaderReadAsArrayBuffer(blob) { + var fileReader = new FileReader(); + var originalReader = this; + fileReader.onload = function fileReaderOnload(evt) { + var data = evt.target.result; + var buffer = new ArrayBuffer(data.length); + var uint8Array = new Uint8Array(buffer); + + for (var i = 0; i < data.length; i++) + uint8Array[i] = data.charCodeAt(i); + + Object.defineProperty(originalReader, 'result', { + value: buffer, + enumerable: true, + writable: false, + configurable: true + }); + + var event = document.createEvent('HTMLEvents'); + event.initEvent('load', false, false); + originalReader.dispatchEvent(event); + }; + fileReader.readAsBinaryString(blob); + } + }); +})(); + // No XMLHttpRequest.response ? (function checkXMLHttpRequestResponseCompatibility() { var xhrPrototype = XMLHttpRequest.prototype; diff --git a/web/viewer.js b/web/viewer.js index 40102852b..324f229cb 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1944,20 +1944,13 @@ window.addEventListener('change', function webViewerChange(evt) { // Read the local file into a Uint8Array. var fileReader = new FileReader(); fileReader.onload = function webViewerChangeFileReaderOnload(evt) { - var data = evt.target.result; - var buffer = new ArrayBuffer(data.length); + var buffer = evt.target.result; var uint8Array = new Uint8Array(buffer); - - for (var i = 0; i < data.length; i++) - uint8Array[i] = data.charCodeAt(i); - PDFView.open(uint8Array, 0); }; - // Read as a binary string since "readAsArrayBuffer" is not yet - // implemented in Firefox. var file = files[0]; - fileReader.readAsBinaryString(file); + fileReader.readAsArrayBuffer(file); document.title = file.name; // URL does not reflect proper document location - hiding some icons. From 70e415900c0accbe1ef3bd84ec9c6867ef7f70f6 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Mon, 6 Aug 2012 14:32:54 -0700 Subject: [PATCH 23/39] Address review comments. --- src/core.js | 4 ++-- test/pdfs/issue1729.pdf.link | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/core.js b/src/core.js index 1ee01d7e5..8519e2e68 100644 --- a/src/core.js +++ b/src/core.js @@ -403,7 +403,7 @@ var PDFDocument = (function PDFDocumentClosure() { return true; /* found */ } - var DOCUMENT_INFO = { + var DocumentInfoValidators = { get entries() { // Lazily build this since all the validation functions below are not // defined until after this file loads. @@ -518,7 +518,7 @@ var PDFDocument = (function PDFDocumentClosure() { var infoDict = this.xref.trailer.get('Info'); docInfo = {}; - var validEntries = DOCUMENT_INFO.entries; + var validEntries = DocumentInfoValidators.entries; // Only fill the document info with valid entries from the spec. for (var key in validEntries) { if (infoDict.has(key)) { diff --git a/test/pdfs/issue1729.pdf.link b/test/pdfs/issue1729.pdf.link index ca6fa690c..a6a73d5a7 100644 --- a/test/pdfs/issue1729.pdf.link +++ b/test/pdfs/issue1729.pdf.link @@ -1,2 +1 @@ http://www.environmentallights.com/files/documents/ir_light_hazard.pdf - From a114d13308dea037045ac00a5491901c7c5ce0c7 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Tue, 7 Aug 2012 17:00:42 +0200 Subject: [PATCH 24/39] Fix some minor issues/nits detected by JetBrains' WebStorm inspector. --- web/viewer.js | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 40102852b..237c082db 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -177,7 +177,7 @@ var Settings = (function SettingsClosure() { else if (isLocalStorageEnabled) database = localStorage.getItem('database') || '{}'; else - return false; + return; database = JSON.parse(database); if (!('files' in database)) @@ -351,8 +351,8 @@ var PDFView = { set page(val) { var pages = this.pages; var input = document.getElementById('pageNumber'); + var event = document.createEvent('UIEvents'); if (!(0 < val && val <= pages.length)) { - var event = document.createEvent('UIEvents'); event.initUIEvent('pagechange', false, false, window, 0); event.pageNumber = this.page; window.dispatchEvent(event); @@ -361,7 +361,6 @@ var PDFView = { pages[val - 1].updateStats(); currentPageNumber = val; - var event = document.createEvent('UIEvents'); event.initUIEvent('pagechange', false, false, window, 0); event.pageNumber = val; window.dispatchEvent(event); @@ -487,7 +486,7 @@ var PDFView = { noData // Error ocurred try downloading with just the url. ); } else { - url += '#pdfjs.action=download', '_parent'; + url += '#pdfjs.action=download'; window.open(url, '_parent'); } }, @@ -795,7 +794,7 @@ var PDFView = { // 2 if last scrolled up page before the visible pages var numVisible = visibleViews.length; if (numVisible === 0) { - info('No visible views.'); + //info('No visible views.'); return false; } for (var i = 0; i < numVisible; ++i) { @@ -944,7 +943,6 @@ var PDFView = { } else { this.page = pageNumber; // simple page } - return; } } else if (/^\d+$/.test(hash)) // page number this.page = hash; @@ -1015,7 +1013,7 @@ var PDFView = { extractPageText(pageIndex + 1); } ); - }; + } extractPageText(0); }, @@ -1701,13 +1699,13 @@ var CustomStyle = (function CustomStyleClosure() { //if all fails then set to undefined return (_cache[propName] = 'undefined'); - } + }; CustomStyle.setProp = function set(propName, element, str) { var prop = this.getProp(propName); if (prop != 'undefined') element.style[prop] = str; - } + }; return CustomStyle; })(); @@ -1776,7 +1774,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { // Resume rendering renderTimer = setInterval(renderTextLayer, renderInterval); }, resumeInterval); - }; // textLayerOnScroll + } // textLayerOnScroll window.addEventListener('scroll', textLayerOnScroll, false); }; // endLayout From d01071f426c0d782f46531d7436323b29cb29882 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Tue, 7 Aug 2012 17:54:05 +0200 Subject: [PATCH 25/39] Remove the commented out call to info() --- web/viewer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/web/viewer.js b/web/viewer.js index 237c082db..eb3a1cfbb 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -794,7 +794,6 @@ var PDFView = { // 2 if last scrolled up page before the visible pages var numVisible = visibleViews.length; if (numVisible === 0) { - //info('No visible views.'); return false; } for (var i = 0; i < numVisible; ++i) { From fdc6dc7ee4b068ad6abb72ea18901b5da687a948 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Wed, 8 Aug 2012 01:52:22 +0200 Subject: [PATCH 26/39] Improved page tracking on scrolling [squashed] --- web/viewer.js | 76 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/web/viewer.js b/web/viewer.js index 40102852b..e3cce776c 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -785,7 +785,7 @@ var PDFView = { } }, - getHighestPriority: function pdfViewGetHighestPriority(visibleViews, views, + getHighestPriority: function pdfViewGetHighestPriority(visible, views, scrolledDown) { // The state has changed figure out which page has the highest priority to // render next (if any). @@ -793,6 +793,8 @@ var PDFView = { // 1 visible pages // 2 if last scrolled down page after the visible pages // 2 if last scrolled up page before the visible pages + var visibleViews = visible.views; + var numVisible = visibleViews.length; if (numVisible === 0) { info('No visible views.'); @@ -806,13 +808,12 @@ var PDFView = { // All the visible views have rendered, try to render next/previous pages. if (scrolledDown) { - var lastVisible = visibleViews[visibleViews.length - 1]; - var nextPageIndex = lastVisible.id; + var nextPageIndex = visible.last.id; // ID's start at 1 so no need to add 1. if (views[nextPageIndex] && !this.isViewFinished(views[nextPageIndex])) return views[nextPageIndex]; } else { - var previousPageIndex = visibleViews[0].id - 2; + var previousPageIndex = visible.first.id - 2; if (views[previousPageIndex] && !this.isViewFinished(views[previousPageIndex])) return views[previousPageIndex]; @@ -1021,7 +1022,7 @@ var PDFView = { getVisiblePages: function pdfViewGetVisiblePages() { return this.getVisibleElements(this.container, - this.pages); + this.pages, true); }, getVisibleThumbs: function pdfViewGetVisibleThumbs() { @@ -1030,11 +1031,12 @@ var PDFView = { }, // Generic helper to find out what elements are visible within a scroll pane. - getVisibleElements: function pdfViewGetVisibleElements(scrollEl, views) { + getVisibleElements: function pdfViewGetVisibleElements( + scrollEl, views, sortByVisibility) { var currentHeight = 0, view; var top = scrollEl.scrollTop; - for (var i = 1; i <= views.length; ++i) { + for (var i = 1, ii = views.length; i <= ii; ++i) { view = views[i - 1]; currentHeight = view.el.offsetTop; if (currentHeight + view.el.clientHeight > top) @@ -1052,19 +1054,38 @@ var PDFView = { view: currentPage }); - return visible; + return { first: currentPage, last: currentPage, views: visible}; } var bottom = top + scrollEl.clientHeight; - for (; i <= views.length && currentHeight < bottom; ++i) { + var nextHeight, hidden, percent, viewHeight; + for (; i <= ii && currentHeight < bottom; ++i) { view = views[i - 1]; + viewHeight = view.el.clientHeight; currentHeight = view.el.offsetTop; + nextHeight = currentHeight + viewHeight; + hidden = Math.max(0, top - currentHeight) + + Math.max(0, nextHeight - bottom); + percent = Math.floor((viewHeight - hidden) * 100.0 / viewHeight); visible.push({ id: view.id, y: currentHeight, - view: view }); - currentHeight += view.el.clientHeight; + view: view, percent: percent }); + currentHeight = nextHeight; } - return visible; + var first = visible[0]; + var last = visible[visible.length - 1]; + + if (sortByVisibility) { + visible.sort(function(a, b) { + var pc = a.percent - b.percent; + if (Math.abs(pc) > 0.001) + return -pc; + + return a.id - b.id; // ensure stability + }); + } + + return {first: first, last: last, views: visible}; }, // Helper function to parse query string (e.g. ?param1=value&parm2=...). @@ -1885,18 +1906,37 @@ window.addEventListener('load', function webViewerLoad(evt) { }, true); function updateViewarea() { + if (!PDFView.initialized) return; - var visiblePages = PDFView.getVisiblePages(); + var visible = PDFView.getVisiblePages(); + var visiblePages = visible.views; PDFView.renderHighestPriority(); var currentId = PDFView.page; - var firstPage = visiblePages[0]; + var firstPage = visible.first; + + for (var i = 0, ii = visiblePages.length, stillFullyVisible = false; + i < ii; ++i) { + var page = visiblePages[i]; + + if (page.percent < 100) + break; + + if (page.id === PDFView.page) { + stillFullyVisible = true; + break; + } + } + + if (!stillFullyVisible) { + currentId = visiblePages[0].id; + } if (!PDFView.isFullscreen) { updateViewarea.inProgress = true; // used in "set page" - PDFView.page = firstPage.id; + PDFView.page = currentId; updateViewarea.inProgress = false; } @@ -2015,13 +2055,13 @@ window.addEventListener('pagechange', function pagechange(evt) { var thumbnail = document.getElementById('thumbnailContainer' + page); thumbnail.classList.add('selected'); var visibleThumbs = PDFView.getVisibleThumbs(); - var numVisibleThumbs = visibleThumbs.length; + var numVisibleThumbs = visibleThumbs.views.length; // If the thumbnail isn't currently visible scroll it into view. if (numVisibleThumbs > 0) { - var first = visibleThumbs[0].id; + var first = visibleThumbs.first.id; // Account for only one thumbnail being visible. var last = numVisibleThumbs > 1 ? - visibleThumbs[numVisibleThumbs - 1].id : first; + visibleThumbs.last.id : first; if (page <= first || page >= last) thumbnail.scrollIntoView(); } From bfa9dea7c541deb54911dda8f6170cbb44e4a053 Mon Sep 17 00:00:00 2001 From: Clauber Stipkovic Date: Tue, 7 Aug 2012 21:49:19 -0300 Subject: [PATCH 27/39] Added .DS_Store reference in gitignore file --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9b20a7778..b779eac0b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ local.mk build/ tags - +.DS_Store From 2ca8c0d99975a0ef11e032eccae71dd7d79ade9c Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Wed, 8 Aug 2012 09:07:31 -0700 Subject: [PATCH 28/39] Cleanup references to dom elements. --- src/canvas.js | 5 ++++- web/viewer.js | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/canvas.js b/src/canvas.js index 058b57b7e..122dd5e59 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -1258,7 +1258,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { return CanvasGraphics; })(); -if (!isWorker) { +function checkPutBinaryImageDataCompatibility() { // Feature detection if the browser can use an Uint8Array directly as imgData. var canvas = document.createElement('canvas'); canvas.width = 1; @@ -1293,3 +1293,6 @@ if (!isWorker) { }; } } +if (!isWorker) { + checkPutBinaryImageDataCompatibility(); +} diff --git a/web/viewer.js b/web/viewer.js index a631bc004..b8118567c 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -1707,6 +1707,7 @@ var TextLayerBuilder = function textLayerBuilder(textLayerDiv) { if (textDivs.length === 0) { clearInterval(renderTimer); renderingDone = true; + self.textLayerDiv = textLayerDiv = canvas = ctx = null; return; } var textDiv = textDivs.shift(); From eaffcfa9206645edfc8cce2e2382071d75cccdd7 Mon Sep 17 00:00:00 2001 From: gigaherz Date: Wed, 8 Aug 2012 20:26:24 +0200 Subject: [PATCH 29/39] Fix some typos in comments and variable names. Fix some nits in debugger.js. --- web/debugger.js | 14 +++++++------- web/viewer.js | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/web/debugger.js b/web/debugger.js index aeb3ab4ce..0cfe26355 100644 --- a/web/debugger.js +++ b/web/debugger.js @@ -44,7 +44,7 @@ var FontInspector = (function FontInspectorClosure() { } } return { - // Poperties/functions needed by PDFBug. + // Properties/functions needed by PDFBug. id: 'FontInspector', name: 'Font Inspector', panel: null, @@ -140,7 +140,7 @@ var StepperManager = (function StepperManagerClosure() { var stepperChooser = null; var breakPoints = {}; return { - // Poperties/functions needed by PDFBug. + // Properties/functions needed by PDFBug. id: 'Stepper', name: 'Stepper', panel: null, @@ -207,7 +207,7 @@ var StepperManager = (function StepperManagerClosure() { var Stepper = (function StepperClosure() { function Stepper(panel, pageIndex, initialBreakPoints) { this.panel = panel; - this.len; + this.len = 0; this.breakPoint = 0; this.nextBreakPoint = null; this.pageIndex = pageIndex; @@ -236,6 +236,7 @@ var Stepper = (function StepperClosure() { headerRow.appendChild(c('th', 'fn')); headerRow.appendChild(c('th', 'args')); + var self = this; for (var i = 0; i < IRQueue.fnArray.length; i++) { var line = c('tr'); line.className = 'line'; @@ -249,7 +250,6 @@ var Stepper = (function StepperClosure() { cbox.type = 'checkbox'; cbox.className = 'points'; cbox.checked = checked; - var self = this; cbox.onclick = (function(x) { return function() { if (this.checked) @@ -298,7 +298,7 @@ var Stepper = (function StepperClosure() { callback(); break; } - } + }; dom.addEventListener('keydown', listener, false); self.goTo(idx); }, @@ -331,7 +331,7 @@ var Stats = (function Stats() { return false; } return { - // Poperties/functions needed by PDFBug. + // Properties/functions needed by PDFBug. id: 'Stats', name: 'Stats', panel: null, @@ -429,12 +429,12 @@ var PDFBug = (function PDFBugClosure() { // Initialize all the debugging tools. var tools = this.tools; + var self = this; for (var i = 0; i < tools.length; ++i) { var tool = tools[i]; var panel = document.createElement('div'); var panelButton = document.createElement('button'); panelButton.textContent = tool.name; - var self = this; panelButton.addEventListener('click', (function(selected) { return function(event) { event.preventDefault(); diff --git a/web/viewer.js b/web/viewer.js index 9b810b76f..1e6bf8a12 100644 --- a/web/viewer.js +++ b/web/viewer.js @@ -431,7 +431,7 @@ var PDFView = { // } // ); // }, -// noData // Error ocurred try downloading with just the url. +// noData // Error occurred try downloading with just the url. // ); //#endif }, @@ -798,14 +798,14 @@ var PDFView = { search: function pdfViewStartSearch() { // Limit this function to run every ms. var SEARCH_TIMEOUT = 250; - var lastSeach = this.lastSearch; + var lastSearch = this.lastSearch; var now = Date.now(); - if (lastSeach && (now - lastSeach) < SEARCH_TIMEOUT) { + if (lastSearch && (now - lastSearch) < SEARCH_TIMEOUT) { if (!this.searchTimer) { this.searchTimer = setTimeout(function resumeSearch() { PDFView.search(); }, - SEARCH_TIMEOUT - (now - lastSeach) + SEARCH_TIMEOUT - (now - lastSearch) ); } return; From 5b583e596a83f26e56d7d8cde0c10c7d8400531d Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 8 Aug 2012 13:31:15 -0500 Subject: [PATCH 30/39] data.length optimization --- web/compatibility.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/compatibility.js b/web/compatibility.js index 5a16b3d7f..cb2941042 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -141,7 +141,7 @@ var buffer = new ArrayBuffer(data.length); var uint8Array = new Uint8Array(buffer); - for (var i = 0; i < data.length; i++) + for (var i = 0, ii = data.length; i < ii; i++) uint8Array[i] = data.charCodeAt(i); Object.defineProperty(originalReader, 'result', { From 65bc78d8709884edcc6f6bbfb128864e3240c28a Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 9 Aug 2012 10:41:18 -0500 Subject: [PATCH 31/39] Using fast pixels copy in putBinaryImageData --- src/canvas.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/canvas.js b/src/canvas.js index 122dd5e59..97ff8f8d4 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -1281,12 +1281,14 @@ function checkPutBinaryImageDataCompatibility() { function CanvasGraphicsPutBinaryImageDataShim(ctx, imgData, w, h) { var tmpImgData = ctx.getImageData(0, 0, w, h); - // Copy over the imageData pixel by pixel. var tmpImgDataPixels = tmpImgData.data; - var len = tmpImgDataPixels.length; - - while (len--) { - tmpImgDataPixels[len] = imgData.data[len]; + var data = imgData.data; + if ('set' in tmpImgDataPixels) + tmpImgDataPixels.set(data); + else { + // Copy over the imageData pixel by pixel. + for (var i = 0, ii = tmpImgDataPixels.length; i < ii; i++) + tmpImgDataPixels[i] = data[i]; } ctx.putImageData(tmpImgData, 0, 0); From 55b3b005b8cd11fb93202dfc74714d3de23f00fd Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 9 Aug 2012 13:40:40 -0500 Subject: [PATCH 32/39] Using createImageData when available --- src/canvas.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/canvas.js b/src/canvas.js index 97ff8f8d4..9f61ba77b 100644 --- a/src/canvas.js +++ b/src/canvas.js @@ -1279,7 +1279,8 @@ function checkPutBinaryImageDataCompatibility() { } catch (e) { CanvasGraphics.prototype.putBinaryImageData = function CanvasGraphicsPutBinaryImageDataShim(ctx, imgData, w, h) { - var tmpImgData = ctx.getImageData(0, 0, w, h); + var tmpImgData = 'createImageData' in ctx ? ctx.createImageData(w, h) : + ctx.getImageData(0, 0, w, h); var tmpImgDataPixels = tmpImgData.data; var data = imgData.data; From 4de0d3131822145d6ca6ddb09aa377bea274df40 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Thu, 9 Aug 2012 17:07:41 -0500 Subject: [PATCH 33/39] Finds correct window/notification box for fallback message --- .../firefox/components/PdfStreamConverter.js | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/extensions/firefox/components/PdfStreamConverter.js b/extensions/firefox/components/PdfStreamConverter.js index d371e50cd..7fb42c0cd 100644 --- a/extensions/firefox/components/PdfStreamConverter.js +++ b/extensions/firefox/components/PdfStreamConverter.js @@ -219,9 +219,26 @@ ChromeActions.prototype = { var strings = getLocalizedStrings('chrome.properties'); var message = getLocalizedString(strings, 'unsupported_feature'); - var win = Services.wm.getMostRecentWindow('navigator:browser'); - var browser = win.gBrowser.getBrowserForDocument(domWindow.top.document); - var notificationBox = win.gBrowser.getNotificationBox(browser); + var notificationBox = null; + // Multiple browser windows can be opened, finding one for notification box + var windowsEnum = Services.wm + .getZOrderDOMWindowEnumerator('navigator:browser', true); + while (windowsEnum.hasMoreElements()) { + var win = windowsEnum.getNext(); + if (win.closed) + continue; + var browser = win.gBrowser.getBrowserForDocument(domWindow.top.document); + if (browser) { + // right window/browser is found, getting the notification box + notificationBox = win.gBrowser.getNotificationBox(browser); + break; + } + } + if (!notificationBox) { + log('Unable to get a notification box for the fallback message'); + return; + } + // Flag so we don't call the response callback twice, since if the user // clicks open with different viewer both the button callback and // eventCallback will be called. From 5e3882ab6956f52f70e3b40f244a1f98479d9741 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 10 Aug 2012 08:30:20 -0500 Subject: [PATCH 34/39] Changing cubic spline interpolation error to TODO --- src/function.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/function.js b/src/function.js index 56b405ede..2088ee219 100644 --- a/src/function.js +++ b/src/function.js @@ -103,11 +103,12 @@ var PDFFunction = (function PDFFunctionClosure() { var size = dict.get('Size'); var bps = dict.get('BitsPerSample'); - var order = dict.get('Order'); - if (!order) - order = 1; - if (order !== 1) - error('No support for cubic spline interpolation: ' + order); + var order = dict.get('Order') || 1; + if (order !== 1) { + // No description how cubic spline interpolation works in PDF32000:2008 + // As in poppler, ignoring order, linear interpolation may work as good + TODO('No support for cubic spline interpolation: ' + order); + } var encode = dict.get('Encode'); if (!encode) { From 309342748015b483a91a26a00221453ce2e13fed Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Fri, 10 Aug 2012 21:31:33 -0500 Subject: [PATCH 35/39] Marks xref entries with offset 0 as free --- src/obj.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/obj.js b/src/obj.js index c01ffab58..d04234f07 100644 --- a/src/obj.js +++ b/src/obj.js @@ -624,7 +624,7 @@ var XRef = (function XRefClosure() { var e = this.entries[i]; if (e === null) return null; - return e.free ? null : e; // returns null is the entry is free + return e.free || !e.offset ? null : e; // returns null if entry is free }, fetchIfRef: function XRef_fetchIfRef(obj) { if (!isRef(obj)) From b4d75ca83b1a5b74986021a21be4efc89e074f4d Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Sat, 11 Aug 2012 11:57:42 -0500 Subject: [PATCH 36/39] Adds callothersubr support --- src/fonts.js | 49 +++++++++++++++++++++++++++---------- test/pdfs/issue845.pdf.link | 1 + test/test_manifest.json | 7 ++++++ 3 files changed, 44 insertions(+), 13 deletions(-) create mode 100644 test/pdfs/issue845.pdf.link diff --git a/src/fonts.js b/src/fonts.js index b16c2621a..ae6d330b5 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -3293,6 +3293,14 @@ var Font = (function FontClosure() { return Font; })(); +var CallothersubrCmd = (function CallothersubrCmdClosure() { + function CallothersubrCmd(index) { + this.index = index; + } + + return CallothersubrCmd; +})(); + /* * Type1Parser encapsulate the needed code for parsing a Type1 font * program. Some of its logic depends on the Type2 charstrings @@ -3498,6 +3506,10 @@ var Type1Parser = function type1Parser() { i++; continue; } + + assert(argc == 0, 'callothersubr with arguments is not supported'); + charstring.push(new CallothersubrCmd(index)); + continue; } else if (escape == 17 || escape == 33) { // pop or setcurrentpoint commands can be ignored // since we are not doing callothersubr @@ -4017,14 +4029,14 @@ Type1Font.prototype = { }, getType2Charstrings: function Type1Font_getType2Charstrings( - type1Charstrings) { + type1Subrs) { var type2Charstrings = []; - var count = type1Charstrings.length; - for (var i = 0; i < count; i++) { - var charstring = type1Charstrings[i].charstring; - type2Charstrings.push(this.flattenCharstring(charstring.slice(), - this.commandsMap)); - } + var count = type1Subrs.length; + var type1Charstrings = []; + for (var i = 0; i < count; i++) + type1Charstrings.push(type1Subrs[i].charstring.slice()); + for (var i = 0; i < count; i++) + type2Charstrings.push(this.flattenCharstring(type1Charstrings, i)); return type2Charstrings; }, @@ -4044,11 +4056,7 @@ Type1Font.prototype = { type2Subrs.push([0x0B]); for (var i = 0; i < count; i++) { - var subr = type1Subrs[i]; - if (!subr) - subr = [0x0B]; - - type2Subrs.push(this.flattenCharstring(subr, this.commandsMap)); + type2Subrs.push(this.flattenCharstring(type1Subrs, i)); } return type2Subrs; @@ -4080,7 +4088,11 @@ Type1Font.prototype = { 'hvcurveto': 31 }, - flattenCharstring: function Type1Font_flattenCharstring(charstring, map) { + flattenCharstring: function Type1Font_flattenCharstring(charstrings, index) { + var charstring = charstrings[index]; + if (!charstring) + return [0x0B]; + var map = this.commandsMap; // charstring changes size - can't cache .length in loop for (var i = 0; i < charstring.length; i++) { var command = charstring[i]; @@ -4092,6 +4104,17 @@ Type1Font.prototype = { charstring.splice(i++, 1, cmd[0], cmd[1]); else charstring[i] = cmd; + } else if (command instanceof CallothersubrCmd) { + var otherSubrCharstring = charstrings[command.index]; + if (otherSubrCharstring) { + var lastCommand = otherSubrCharstring.indexOf('return'); + if (lastCommand >= 0) + otherSubrCharstring = otherSubrCharstring.slice(0, lastCommand); + charstring.splice.apply(charstring, + [i, 1].concat(otherSubrCharstring)); + } else + charstring.splice(i, 1); // ignoring empty subr call + i--; } else { // Type1 charstring use a division for number above 32000 if (command > 32000) { diff --git a/test/pdfs/issue845.pdf.link b/test/pdfs/issue845.pdf.link new file mode 100644 index 000000000..b315abebb --- /dev/null +++ b/test/pdfs/issue845.pdf.link @@ -0,0 +1 @@ +http://www.mediafire.com/?k8t1he9aa1pt840 diff --git a/test/test_manifest.json b/test/test_manifest.json index 166b4fdc7..d894a97a1 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -619,6 +619,13 @@ "link": true, "type": "eq" }, + { "id": "issue845", + "file": "pdfs/issue845.pdf", + "md5": "89ddf9e63cac4fa2dedcfe32a62e5407", + "rounds": 1, + "link": true, + "type": "eq" + }, { "id": "issue818", "file": "pdfs/issue818.pdf", "md5": "dd2f8a5bd65164ad74da2b45a6ca90cc", From 6277e6eda77a34509f84ec9058156a870c91b5e0 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Sat, 11 Aug 2012 20:10:31 -0500 Subject: [PATCH 37/39] Fixes bias calculation for type2 subr --- src/fonts.js | 4 ++-- test/pdfs/issue1655.pdf.link | 1 + test/test_manifest.json | 8 ++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 test/pdfs/issue1655.pdf.link diff --git a/src/fonts.js b/src/fonts.js index b16c2621a..0e086bff2 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -4031,9 +4031,9 @@ Type1Font.prototype = { getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) { var bias = 0; var count = type1Subrs.length; - if (count < 1240) + if (count < 1133) bias = 107; - else if (count < 33900) + else if (count < 33769) bias = 1131; else bias = 32768; diff --git a/test/pdfs/issue1655.pdf.link b/test/pdfs/issue1655.pdf.link new file mode 100644 index 000000000..ee983a687 --- /dev/null +++ b/test/pdfs/issue1655.pdf.link @@ -0,0 +1 @@ +http://bblum.net/thesis-draft.pdf diff --git a/test/test_manifest.json b/test/test_manifest.json index 166b4fdc7..d5ba5a1aa 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -515,6 +515,14 @@ "link": true, "type": "eq" }, + { "id": "issue1655", + "file": "pdfs/issue1655.pdf", + "md5": "696ef6de6f4f71643771419ef04fc968", + "rounds": 1, + "pageLimit": 9, + "link": true, + "type": "eq" + }, { "id": "issue1133", "file": "pdfs/issue1133.pdf", "md5": "d1b61580cb100e3df93d33703af1773a", From c52cb76091957c5881acaabb6d72e9e34a8ac2da Mon Sep 17 00:00:00 2001 From: Haebaru Date: Tue, 14 Aug 2012 01:58:24 +0900 Subject: [PATCH 38/39] Update Japanese l10n --- l10n/ja/viewer.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/l10n/ja/viewer.properties b/l10n/ja/viewer.properties index b7981ecf0..c8bfde461 100644 --- a/l10n/ja/viewer.properties +++ b/l10n/ja/viewer.properties @@ -18,6 +18,8 @@ zoom_in_label=拡大 zoom.title=ズーム print.title=印刷 print_label=印刷 +fullscreen.title=全画面表示 +fullscreen_label=全画面表示 open_file.title=ファイルを開く open_file_label=開く download.title=ダウンロード From 477ca87a4ee3ae0100531b9b9807348c7f1bf28f Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Tue, 14 Aug 2012 11:39:06 -0500 Subject: [PATCH 39/39] Ignoring the pages 1-8 --- test/test_manifest.json | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_manifest.json b/test/test_manifest.json index d5ba5a1aa..7b1281803 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -519,6 +519,7 @@ "file": "pdfs/issue1655.pdf", "md5": "696ef6de6f4f71643771419ef04fc968", "rounds": 1, + "skipPages": [1, 2, 3, 4, 5, 6, 7, 8], "pageLimit": 9, "link": true, "type": "eq"