Enable auto-formatting of the entire code-base using Prettier (issue 11444)
Note that Prettier, purposely, has only limited [configuration options](https://prettier.io/docs/en/options.html). The configuration file is based on [the one in `mozilla central`](https://searchfox.org/mozilla-central/source/.prettierrc) with just a few additions (to avoid future breakage if the defaults ever changes). Prettier is being used for a couple of reasons: - To be consistent with `mozilla-central`, where Prettier is already in use across the tree. - To ensure a *consistent* coding style everywhere, which is automatically enforced during linting (since Prettier is used as an ESLint plugin). This thus ends "all" formatting disussions once and for all, removing the need for review comments on most stylistic matters. Many ESLint options are now redundant, and I've tried my best to remove all the now unnecessary options (but I may have missed some). Note also that since Prettier considers the `printWidth` option as a guide, rather than a hard rule, this patch resorts to a small hack in the ESLint config to ensure that *comments* won't become too long. *Please note:* This patch is generated automatically, by appending the `--fix` argument to the ESLint call used in the `gulp lint` task. It will thus require some additional clean-up, which will be done in a *separate* commit. (On a more personal note, I'll readily admit that some of the changes Prettier makes are *extremely* ugly. However, in the name of consistency we'll probably have to live with that.)
This commit is contained in:
parent
8ec1dfde49
commit
de36b2aaba
51
.eslintrc
51
.eslintrc
@ -11,6 +11,10 @@
|
|||||||
"unicorn",
|
"unicorn",
|
||||||
],
|
],
|
||||||
|
|
||||||
|
"extends": [
|
||||||
|
"plugin:prettier/recommended"
|
||||||
|
],
|
||||||
|
|
||||||
"env": {
|
"env": {
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"es6": true,
|
"es6": true,
|
||||||
@ -47,7 +51,6 @@
|
|||||||
"no-empty": ["error", { "allowEmptyCatch": true, }],
|
"no-empty": ["error", { "allowEmptyCatch": true, }],
|
||||||
"no-ex-assign": "error",
|
"no-ex-assign": "error",
|
||||||
"no-extra-boolean-cast": "error",
|
"no-extra-boolean-cast": "error",
|
||||||
"no-extra-semi": "error",
|
|
||||||
"no-func-assign": "error",
|
"no-func-assign": "error",
|
||||||
"no-inner-declarations": ["error", "functions"],
|
"no-inner-declarations": ["error", "functions"],
|
||||||
"no-invalid-regexp": "error",
|
"no-invalid-regexp": "error",
|
||||||
@ -84,9 +87,6 @@
|
|||||||
"no-implied-eval": "error",
|
"no-implied-eval": "error",
|
||||||
"no-iterator": "error",
|
"no-iterator": "error",
|
||||||
"no-lone-blocks": "error",
|
"no-lone-blocks": "error",
|
||||||
"no-multi-spaces": ["error", {
|
|
||||||
"ignoreEOLComments": true,
|
|
||||||
}],
|
|
||||||
"no-multi-str": "error",
|
"no-multi-str": "error",
|
||||||
"no-new-func": "error",
|
"no-new-func": "error",
|
||||||
"no-new-wrappers": "error",
|
"no-new-wrappers": "error",
|
||||||
@ -127,48 +127,16 @@
|
|||||||
}],
|
}],
|
||||||
|
|
||||||
// Stylistic Issues
|
// Stylistic Issues
|
||||||
"array-bracket-spacing": ["error", "never"],
|
|
||||||
"block-spacing": ["error", "always"],
|
|
||||||
"brace-style": ["error", "1tbs", {
|
|
||||||
"allowSingleLine": false,
|
|
||||||
}],
|
|
||||||
"comma-dangle": ["error", {
|
|
||||||
"arrays": "ignore",
|
|
||||||
"objects": "always",
|
|
||||||
"imports": "never",
|
|
||||||
"exports": "always",
|
|
||||||
"functions": "never",
|
|
||||||
}],
|
|
||||||
"comma-spacing": ["error", { "before": false, "after": true, }],
|
|
||||||
"comma-style": ["error", "last"],
|
|
||||||
"eol-last": "error",
|
|
||||||
"func-call-spacing": ["error", "never"],
|
|
||||||
"key-spacing": ["error", { "beforeColon": false, "afterColon": true, "mode": "strict", }],
|
|
||||||
"keyword-spacing": ["error", { "before": true, "after": true, }],
|
|
||||||
"linebreak-style": ["error", "unix"],
|
|
||||||
"lines-between-class-members": ["error", "always"],
|
"lines-between-class-members": ["error", "always"],
|
||||||
"max-len": ["error", {
|
"max-len": ["error", {
|
||||||
"code": 80,
|
"code": 1000,
|
||||||
|
"comments": 80,
|
||||||
"ignoreUrls": true
|
"ignoreUrls": true
|
||||||
}],
|
}],
|
||||||
"new-cap": ["error", { "newIsCap": true, "capIsNew": false, }],
|
"new-cap": ["error", { "newIsCap": true, "capIsNew": false, }],
|
||||||
"new-parens": "error",
|
|
||||||
"no-array-constructor": "error",
|
"no-array-constructor": "error",
|
||||||
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0, "maxBOF": 1, }],
|
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0, "maxBOF": 1, }],
|
||||||
"no-new-object": "error",
|
"no-new-object": "error",
|
||||||
"no-tabs": "error",
|
|
||||||
"no-trailing-spaces": ["error", { "skipBlankLines": false, }],
|
|
||||||
"no-whitespace-before-property": "error",
|
|
||||||
"object-curly-spacing": ["error", "always"],
|
|
||||||
"operator-linebreak": ["error", "after", { "overrides": { ":": "ignore", } }],
|
|
||||||
"quotes": ["error", "single"],
|
|
||||||
"semi-spacing": ["error", { "before": false, "after": true, }],
|
|
||||||
"semi": ["error", "always"],
|
|
||||||
"space-before-blocks": ["error", "always"],
|
|
||||||
"space-before-function-paren": ["error", { "anonymous": "ignore", "named": "never", }],
|
|
||||||
"space-in-parens": ["error", "never"],
|
|
||||||
"space-infix-ops": ["error", { "int32Hint": false }],
|
|
||||||
"space-unary-ops": ["error", { "words": true, "nonwords": false, }],
|
|
||||||
"spaced-comment": ["error", "always", {
|
"spaced-comment": ["error", "always", {
|
||||||
"block": {
|
"block": {
|
||||||
"balanced": true,
|
"balanced": true,
|
||||||
@ -176,12 +144,6 @@
|
|||||||
}],
|
}],
|
||||||
|
|
||||||
// ECMAScript 6
|
// ECMAScript 6
|
||||||
"arrow-body-style": ["error", "always"],
|
|
||||||
"arrow-parens": ["error", "always"],
|
|
||||||
"arrow-spacing": ["error", {
|
|
||||||
"before": true,
|
|
||||||
"after": true,
|
|
||||||
}],
|
|
||||||
"constructor-super": "error",
|
"constructor-super": "error",
|
||||||
"no-class-assign": "error",
|
"no-class-assign": "error",
|
||||||
"no-confusing-arrow": "error",
|
"no-confusing-arrow": "error",
|
||||||
@ -197,7 +159,6 @@
|
|||||||
"avoidQuotes": true,
|
"avoidQuotes": true,
|
||||||
}],
|
}],
|
||||||
"prefer-const": "off",
|
"prefer-const": "off",
|
||||||
"rest-spread-spacing": ["error", "never"],
|
|
||||||
"sort-imports": ["error", {
|
"sort-imports": ["error", {
|
||||||
"ignoreCase": true,
|
"ignoreCase": true,
|
||||||
}],
|
}],
|
||||||
|
8
.prettierrc
Normal file
8
.prettierrc
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"endOfLine": "lf",
|
||||||
|
"printWidth": 80,
|
||||||
|
"semi": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"useTabs": false
|
||||||
|
}
|
@ -13,15 +13,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||||
|
|
||||||
var DEFAULT_URL = '../../test/pdfs/f1040.pdf';
|
var DEFAULT_URL = "../../test/pdfs/f1040.pdf";
|
||||||
var DEFAULT_SCALE = 1.0;
|
var DEFAULT_SCALE = 1.0;
|
||||||
|
|
||||||
var container = document.getElementById('pageContainer');
|
var container = document.getElementById("pageContainer");
|
||||||
|
|
||||||
// Fetch the PDF document from the URL using promises.
|
// Fetch the PDF document from the URL using promises.
|
||||||
var loadingTask = pdfjsLib.getDocument(DEFAULT_URL);
|
var loadingTask = pdfjsLib.getDocument(DEFAULT_URL);
|
||||||
@ -30,16 +30,16 @@ loadingTask.promise.then(function(doc) {
|
|||||||
var promise = Promise.resolve();
|
var promise = Promise.resolve();
|
||||||
|
|
||||||
for (var i = 1; i <= doc.numPages; i++) {
|
for (var i = 1; i <= doc.numPages; i++) {
|
||||||
promise = promise.then(function (pageNum) {
|
promise = promise.then(
|
||||||
|
function(pageNum) {
|
||||||
return doc.getPage(pageNum).then(function(pdfPage) {
|
return doc.getPage(pageNum).then(function(pdfPage) {
|
||||||
// Create the page view.
|
// Create the page view.
|
||||||
var pdfPageView = new pdfjsViewer.PDFPageView({
|
var pdfPageView = new pdfjsViewer.PDFPageView({
|
||||||
container: container,
|
container: container,
|
||||||
id: pageNum,
|
id: pageNum,
|
||||||
scale: DEFAULT_SCALE,
|
scale: DEFAULT_SCALE,
|
||||||
defaultViewport: pdfPage.getViewport({ scale: DEFAULT_SCALE, }),
|
defaultViewport: pdfPage.getViewport({ scale: DEFAULT_SCALE }),
|
||||||
annotationLayerFactory:
|
annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory(),
|
||||||
new pdfjsViewer.DefaultAnnotationLayerFactory(),
|
|
||||||
renderInteractiveForms: true,
|
renderInteractiveForms: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -47,6 +47,7 @@ loadingTask.promise.then(function(doc) {
|
|||||||
pdfPageView.setPdfPage(pdfPage);
|
pdfPageView.setPdfPage(pdfPage);
|
||||||
return pdfPageView.draw();
|
return pdfPageView.draw();
|
||||||
});
|
});
|
||||||
}.bind(null, i));
|
}.bind(null, i)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,36 +1,40 @@
|
|||||||
var gulp = require('gulp');
|
var gulp = require("gulp");
|
||||||
var browserify = require('browserify');
|
var browserify = require("browserify");
|
||||||
var streamify = require('gulp-streamify');
|
var streamify = require("gulp-streamify");
|
||||||
var rename = require('gulp-rename');
|
var rename = require("gulp-rename");
|
||||||
var uglify = require('gulp-uglify');
|
var uglify = require("gulp-uglify");
|
||||||
var source = require('vinyl-source-stream');
|
var source = require("vinyl-source-stream");
|
||||||
|
|
||||||
var OUTPUT_PATH = '../../build/browserify';
|
var OUTPUT_PATH = "../../build/browserify";
|
||||||
var TMP_FILE_PREFIX = '../../build/browserify_';
|
var TMP_FILE_PREFIX = "../../build/browserify_";
|
||||||
|
|
||||||
gulp.task('build-bundle', function() {
|
gulp.task("build-bundle", function() {
|
||||||
return browserify('main.js', { output: TMP_FILE_PREFIX + 'main.tmp', })
|
return browserify("main.js", { output: TMP_FILE_PREFIX + "main.tmp" })
|
||||||
.ignore(require.resolve('pdfjs-dist/build/pdf.worker')) // Reducing size
|
.ignore(require.resolve("pdfjs-dist/build/pdf.worker")) // Reducing size
|
||||||
.bundle()
|
.bundle()
|
||||||
.pipe(source(TMP_FILE_PREFIX + 'main.tmp'))
|
.pipe(source(TMP_FILE_PREFIX + "main.tmp"))
|
||||||
.pipe(streamify(uglify()))
|
.pipe(streamify(uglify()))
|
||||||
.pipe(rename('main.bundle.js'))
|
.pipe(rename("main.bundle.js"))
|
||||||
.pipe(gulp.dest(OUTPUT_PATH));
|
.pipe(gulp.dest(OUTPUT_PATH));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build-worker', function() {
|
gulp.task("build-worker", function() {
|
||||||
// We can create our own viewer (see worker.js) or use already defined one.
|
// We can create our own viewer (see worker.js) or use already defined one.
|
||||||
var workerSrc = require.resolve('pdfjs-dist/build/pdf.worker.entry');
|
var workerSrc = require.resolve("pdfjs-dist/build/pdf.worker.entry");
|
||||||
return browserify(workerSrc, { output: TMP_FILE_PREFIX + 'worker.tmp', })
|
return browserify(workerSrc, { output: TMP_FILE_PREFIX + "worker.tmp" })
|
||||||
.bundle()
|
.bundle()
|
||||||
.pipe(source(TMP_FILE_PREFIX + 'worker.tmp'))
|
.pipe(source(TMP_FILE_PREFIX + "worker.tmp"))
|
||||||
.pipe(streamify(uglify({
|
.pipe(
|
||||||
|
streamify(
|
||||||
|
uglify({
|
||||||
compress: {
|
compress: {
|
||||||
sequences: false, // Chrome has issue with the generated code if true
|
sequences: false, // Chrome has issue with the generated code if true
|
||||||
},
|
},
|
||||||
})))
|
})
|
||||||
.pipe(rename('pdf.worker.bundle.js'))
|
)
|
||||||
|
)
|
||||||
|
.pipe(rename("pdf.worker.bundle.js"))
|
||||||
.pipe(gulp.dest(OUTPUT_PATH));
|
.pipe(gulp.dest(OUTPUT_PATH));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('build', gulp.series('build-bundle', 'build-worker'));
|
gulp.task("build", gulp.series("build-bundle", "build-worker"));
|
||||||
|
@ -3,31 +3,33 @@
|
|||||||
|
|
||||||
// Hello world example for browserify.
|
// Hello world example for browserify.
|
||||||
|
|
||||||
var pdfjsLib = require('pdfjs-dist');
|
var pdfjsLib = require("pdfjs-dist");
|
||||||
|
|
||||||
var pdfPath = '../learning/helloworld.pdf';
|
var pdfPath = "../learning/helloworld.pdf";
|
||||||
|
|
||||||
// Setting worker path to worker bundle.
|
// Setting worker path to worker bundle.
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../build/browserify/pdf.worker.bundle.js';
|
"../../build/browserify/pdf.worker.bundle.js";
|
||||||
|
|
||||||
// Loading a document.
|
// Loading a document.
|
||||||
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
||||||
loadingTask.promise.then(function (pdfDocument) {
|
loadingTask.promise
|
||||||
|
.then(function(pdfDocument) {
|
||||||
// Request a first page
|
// Request a first page
|
||||||
return pdfDocument.getPage(1).then(function(pdfPage) {
|
return pdfDocument.getPage(1).then(function(pdfPage) {
|
||||||
// Display page on the existing canvas with 100% scale.
|
// Display page on the existing canvas with 100% scale.
|
||||||
var viewport = pdfPage.getViewport({ scale: 1.0, });
|
var viewport = pdfPage.getViewport({ scale: 1.0 });
|
||||||
var canvas = document.getElementById('theCanvas');
|
var canvas = document.getElementById("theCanvas");
|
||||||
canvas.width = viewport.width;
|
canvas.width = viewport.width;
|
||||||
canvas.height = viewport.height;
|
canvas.height = viewport.height;
|
||||||
var ctx = canvas.getContext('2d');
|
var ctx = canvas.getContext("2d");
|
||||||
var renderTask = pdfPage.render({
|
var renderTask = pdfPage.render({
|
||||||
canvasContext: ctx,
|
canvasContext: ctx,
|
||||||
viewport: viewport,
|
viewport: viewport,
|
||||||
});
|
});
|
||||||
return renderTask.promise;
|
return renderTask.promise;
|
||||||
});
|
});
|
||||||
}).catch(function (reason) {
|
})
|
||||||
console.error('Error: ' + reason);
|
.catch(function(reason) {
|
||||||
|
console.error("Error: " + reason);
|
||||||
});
|
});
|
||||||
|
@ -3,5 +3,7 @@
|
|||||||
|
|
||||||
// Hello world example for browserify: worker bundle.
|
// Hello world example for browserify: worker bundle.
|
||||||
|
|
||||||
(typeof window !== 'undefined' ? window : {}).pdfjsWorker =
|
(typeof window !== "undefined"
|
||||||
require('pdfjs-dist/build/pdf.worker');
|
? window
|
||||||
|
: {}
|
||||||
|
).pdfjsWorker = require("pdfjs-dist/build/pdf.worker");
|
||||||
|
@ -13,28 +13,29 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFPageView) {
|
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFPageView) {
|
||||||
alert('Please build the pdfjs-dist library using\n' +
|
alert(
|
||||||
' `gulp dist-install`');
|
"Please build the pdfjs-dist library using\n" + " `gulp dist-install`"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The workerSrc property shall be specified.
|
// The workerSrc property shall be specified.
|
||||||
//
|
//
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||||
|
|
||||||
// Some PDFs need external cmaps.
|
// Some PDFs need external cmaps.
|
||||||
//
|
//
|
||||||
var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/';
|
var CMAP_URL = "../../node_modules/pdfjs-dist/cmaps/";
|
||||||
var CMAP_PACKED = true;
|
var CMAP_PACKED = true;
|
||||||
|
|
||||||
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
var PAGE_TO_VIEW = 1;
|
var PAGE_TO_VIEW = 1;
|
||||||
var SCALE = 1.0;
|
var SCALE = 1.0;
|
||||||
|
|
||||||
var container = document.getElementById('pageContainer');
|
var container = document.getElementById("pageContainer");
|
||||||
|
|
||||||
// Loading document.
|
// Loading document.
|
||||||
var loadingTask = pdfjsLib.getDocument({
|
var loadingTask = pdfjsLib.getDocument({
|
||||||
@ -50,7 +51,7 @@ loadingTask.promise.then(function(pdfDocument) {
|
|||||||
container: container,
|
container: container,
|
||||||
id: PAGE_TO_VIEW,
|
id: PAGE_TO_VIEW,
|
||||||
scale: SCALE,
|
scale: SCALE,
|
||||||
defaultViewport: pdfPage.getViewport({ scale: SCALE, }),
|
defaultViewport: pdfPage.getViewport({ scale: SCALE }),
|
||||||
// We can enable text/annotations layers, if needed
|
// We can enable text/annotations layers, if needed
|
||||||
textLayerFactory: new pdfjsViewer.DefaultTextLayerFactory(),
|
textLayerFactory: new pdfjsViewer.DefaultTextLayerFactory(),
|
||||||
annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory(),
|
annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory(),
|
||||||
|
@ -13,27 +13,28 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
|
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
|
||||||
alert('Please build the pdfjs-dist library using\n' +
|
alert(
|
||||||
' `gulp dist-install`');
|
"Please build the pdfjs-dist library using\n" + " `gulp dist-install`"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The workerSrc property shall be specified.
|
// The workerSrc property shall be specified.
|
||||||
//
|
//
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||||
|
|
||||||
// Some PDFs need external cmaps.
|
// Some PDFs need external cmaps.
|
||||||
//
|
//
|
||||||
var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/';
|
var CMAP_URL = "../../node_modules/pdfjs-dist/cmaps/";
|
||||||
var CMAP_PACKED = true;
|
var CMAP_PACKED = true;
|
||||||
|
|
||||||
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
var SEARCH_FOR = ''; // try 'Mozilla';
|
var SEARCH_FOR = ""; // try 'Mozilla';
|
||||||
|
|
||||||
var container = document.getElementById('viewerContainer');
|
var container = document.getElementById("viewerContainer");
|
||||||
|
|
||||||
// (Optionally) enable hyperlinks within PDF files.
|
// (Optionally) enable hyperlinks within PDF files.
|
||||||
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||||
@ -50,12 +51,13 @@ var pdfViewer = new pdfjsViewer.PDFViewer({
|
|||||||
});
|
});
|
||||||
pdfLinkService.setViewer(pdfViewer);
|
pdfLinkService.setViewer(pdfViewer);
|
||||||
|
|
||||||
document.addEventListener('pagesinit', function () {
|
document.addEventListener("pagesinit", function() {
|
||||||
// We can use pdfViewer now, e.g. let's change default scale.
|
// We can use pdfViewer now, e.g. let's change default scale.
|
||||||
pdfViewer.currentScaleValue = 'page-width';
|
pdfViewer.currentScaleValue = "page-width";
|
||||||
|
|
||||||
if (SEARCH_FOR) { // We can try search for things
|
if (SEARCH_FOR) {
|
||||||
pdfFindController.executeCommand('find', { query: SEARCH_FOR, });
|
// We can try search for things
|
||||||
|
pdfFindController.executeCommand("find", { query: SEARCH_FOR });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,27 +13,28 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFSinglePageViewer) {
|
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFSinglePageViewer) {
|
||||||
alert('Please build the pdfjs-dist library using\n' +
|
alert(
|
||||||
' `gulp dist-install`');
|
"Please build the pdfjs-dist library using\n" + " `gulp dist-install`"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The workerSrc property shall be specified.
|
// The workerSrc property shall be specified.
|
||||||
//
|
//
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||||
|
|
||||||
// Some PDFs need external cmaps.
|
// Some PDFs need external cmaps.
|
||||||
//
|
//
|
||||||
var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/';
|
var CMAP_URL = "../../node_modules/pdfjs-dist/cmaps/";
|
||||||
var CMAP_PACKED = true;
|
var CMAP_PACKED = true;
|
||||||
|
|
||||||
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
var SEARCH_FOR = ''; // try 'Mozilla';
|
var SEARCH_FOR = ""; // try 'Mozilla';
|
||||||
|
|
||||||
var container = document.getElementById('viewerContainer');
|
var container = document.getElementById("viewerContainer");
|
||||||
|
|
||||||
// (Optionally) enable hyperlinks within PDF files.
|
// (Optionally) enable hyperlinks within PDF files.
|
||||||
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||||
@ -50,12 +51,13 @@ var pdfSinglePageViewer = new pdfjsViewer.PDFSinglePageViewer({
|
|||||||
});
|
});
|
||||||
pdfLinkService.setViewer(pdfSinglePageViewer);
|
pdfLinkService.setViewer(pdfSinglePageViewer);
|
||||||
|
|
||||||
document.addEventListener('pagesinit', function () {
|
document.addEventListener("pagesinit", function() {
|
||||||
// We can use pdfSinglePageViewer now, e.g. let's change default scale.
|
// We can use pdfSinglePageViewer now, e.g. let's change default scale.
|
||||||
pdfSinglePageViewer.currentScaleValue = 'page-width';
|
pdfSinglePageViewer.currentScaleValue = "page-width";
|
||||||
|
|
||||||
if (SEARCH_FOR) { // We can try search for things
|
if (SEARCH_FOR) {
|
||||||
pdfFindController.executeCommand('find', { query: SEARCH_FOR, });
|
// We can try search for things
|
||||||
|
pdfFindController.executeCommand("find", { query: SEARCH_FOR });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,39 +13,40 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
if (!pdfjsImageDecoders.JpegImage) {
|
if (!pdfjsImageDecoders.JpegImage) {
|
||||||
alert('Please build the pdfjs-dist library using `gulp dist-install`');
|
alert("Please build the pdfjs-dist library using `gulp dist-install`");
|
||||||
}
|
}
|
||||||
|
|
||||||
var JPEG_IMAGE = 'fish.jpg';
|
var JPEG_IMAGE = "fish.jpg";
|
||||||
|
|
||||||
var jpegCanvas = document.getElementById('jpegCanvas');
|
var jpegCanvas = document.getElementById("jpegCanvas");
|
||||||
var jpegCtx = jpegCanvas.getContext('2d');
|
var jpegCtx = jpegCanvas.getContext("2d");
|
||||||
|
|
||||||
// Load the image data, and convert it to a Uint8Array.
|
// Load the image data, and convert it to a Uint8Array.
|
||||||
//
|
//
|
||||||
var nonBinaryRequest = false;
|
var nonBinaryRequest = false;
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
request.open('GET', JPEG_IMAGE, false);
|
request.open("GET", JPEG_IMAGE, false);
|
||||||
try {
|
try {
|
||||||
request.responseType = 'arraybuffer';
|
request.responseType = "arraybuffer";
|
||||||
nonBinaryRequest = request.responseType !== 'arraybuffer';
|
nonBinaryRequest = request.responseType !== "arraybuffer";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
nonBinaryRequest = true;
|
nonBinaryRequest = true;
|
||||||
}
|
}
|
||||||
if (nonBinaryRequest && request.overrideMimeType) {
|
if (nonBinaryRequest && request.overrideMimeType) {
|
||||||
request.overrideMimeType('text/plain; charset=x-user-defined');
|
request.overrideMimeType("text/plain; charset=x-user-defined");
|
||||||
}
|
}
|
||||||
request.send(null);
|
request.send(null);
|
||||||
|
|
||||||
var typedArrayImage;
|
var typedArrayImage;
|
||||||
if (nonBinaryRequest) {
|
if (nonBinaryRequest) {
|
||||||
var str = request.responseText, length = str.length;
|
var str = request.responseText,
|
||||||
|
length = str.length;
|
||||||
var bytes = new Uint8Array(length);
|
var bytes = new Uint8Array(length);
|
||||||
for (var i = 0; i < length; ++i) {
|
for (var i = 0; i < length; ++i) {
|
||||||
bytes[i] = str.charCodeAt(i) & 0xFF;
|
bytes[i] = str.charCodeAt(i) & 0xff;
|
||||||
}
|
}
|
||||||
typedArrayImage = bytes;
|
typedArrayImage = bytes;
|
||||||
} else {
|
} else {
|
||||||
@ -57,7 +58,8 @@ if (nonBinaryRequest) {
|
|||||||
var jpegImage = new pdfjsImageDecoders.JpegImage();
|
var jpegImage = new pdfjsImageDecoders.JpegImage();
|
||||||
jpegImage.parse(typedArrayImage);
|
jpegImage.parse(typedArrayImage);
|
||||||
|
|
||||||
var width = jpegImage.width, height = jpegImage.height;
|
var width = jpegImage.width,
|
||||||
|
height = jpegImage.height;
|
||||||
var jpegData = jpegImage.getData({
|
var jpegData = jpegImage.getData({
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
|
@ -13,26 +13,26 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
|
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
|
||||||
alert('Please build the pdfjs-dist library using\n `gulp dist-install`');
|
alert("Please build the pdfjs-dist library using\n `gulp dist-install`");
|
||||||
}
|
}
|
||||||
|
|
||||||
var USE_ONLY_CSS_ZOOM = true;
|
var USE_ONLY_CSS_ZOOM = true;
|
||||||
var TEXT_LAYER_MODE = 0; // DISABLE
|
var TEXT_LAYER_MODE = 0; // DISABLE
|
||||||
var MAX_IMAGE_SIZE = 1024 * 1024;
|
var MAX_IMAGE_SIZE = 1024 * 1024;
|
||||||
var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/';
|
var CMAP_URL = "../../node_modules/pdfjs-dist/cmaps/";
|
||||||
var CMAP_PACKED = true;
|
var CMAP_PACKED = true;
|
||||||
|
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||||
|
|
||||||
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
var DEFAULT_SCALE_DELTA = 1.1;
|
var DEFAULT_SCALE_DELTA = 1.1;
|
||||||
var MIN_SCALE = 0.25;
|
var MIN_SCALE = 0.25;
|
||||||
var MAX_SCALE = 10.0;
|
var MAX_SCALE = 10.0;
|
||||||
var DEFAULT_SCALE_VALUE = 'auto';
|
var DEFAULT_SCALE_VALUE = "auto";
|
||||||
|
|
||||||
var PDFViewerApplication = {
|
var PDFViewerApplication = {
|
||||||
pdfLoadingTask: null,
|
pdfLoadingTask: null,
|
||||||
@ -49,10 +49,12 @@ var PDFViewerApplication = {
|
|||||||
open: function(params) {
|
open: function(params) {
|
||||||
if (this.pdfLoadingTask) {
|
if (this.pdfLoadingTask) {
|
||||||
// We need to destroy already opened document
|
// We need to destroy already opened document
|
||||||
return this.close().then(function () {
|
return this.close().then(
|
||||||
|
function() {
|
||||||
// ... and repeat the open() call.
|
// ... and repeat the open() call.
|
||||||
return this.open(params);
|
return this.open(params);
|
||||||
}.bind(this));
|
}.bind(this)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var url = params.url;
|
var url = params.url;
|
||||||
@ -72,41 +74,56 @@ var PDFViewerApplication = {
|
|||||||
self.progress(progressData.loaded / progressData.total);
|
self.progress(progressData.loaded / progressData.total);
|
||||||
};
|
};
|
||||||
|
|
||||||
return loadingTask.promise.then(function (pdfDocument) {
|
return loadingTask.promise.then(
|
||||||
|
function(pdfDocument) {
|
||||||
// Document loaded, specifying document for the viewer.
|
// Document loaded, specifying document for the viewer.
|
||||||
self.pdfDocument = pdfDocument;
|
self.pdfDocument = pdfDocument;
|
||||||
self.pdfViewer.setDocument(pdfDocument);
|
self.pdfViewer.setDocument(pdfDocument);
|
||||||
self.pdfLinkService.setDocument(pdfDocument);
|
self.pdfLinkService.setDocument(pdfDocument);
|
||||||
self.pdfHistory.initialize({ fingerprint: pdfDocument.fingerprint, });
|
self.pdfHistory.initialize({ fingerprint: pdfDocument.fingerprint });
|
||||||
|
|
||||||
self.loadingBar.hide();
|
self.loadingBar.hide();
|
||||||
self.setTitleUsingMetadata(pdfDocument);
|
self.setTitleUsingMetadata(pdfDocument);
|
||||||
}, function (exception) {
|
},
|
||||||
|
function(exception) {
|
||||||
var message = exception && exception.message;
|
var message = exception && exception.message;
|
||||||
var l10n = self.l10n;
|
var l10n = self.l10n;
|
||||||
var loadingErrorMessage;
|
var loadingErrorMessage;
|
||||||
|
|
||||||
if (exception instanceof pdfjsLib.InvalidPDFException) {
|
if (exception instanceof pdfjsLib.InvalidPDFException) {
|
||||||
// change error message also for other builds
|
// change error message also for other builds
|
||||||
loadingErrorMessage = l10n.get('invalid_file_error', null,
|
loadingErrorMessage = l10n.get(
|
||||||
'Invalid or corrupted PDF file.');
|
"invalid_file_error",
|
||||||
|
null,
|
||||||
|
"Invalid or corrupted PDF file."
|
||||||
|
);
|
||||||
} else if (exception instanceof pdfjsLib.MissingPDFException) {
|
} else if (exception instanceof pdfjsLib.MissingPDFException) {
|
||||||
// special message for missing PDFs
|
// special message for missing PDFs
|
||||||
loadingErrorMessage = l10n.get('missing_file_error', null,
|
loadingErrorMessage = l10n.get(
|
||||||
'Missing PDF file.');
|
"missing_file_error",
|
||||||
|
null,
|
||||||
|
"Missing PDF file."
|
||||||
|
);
|
||||||
} else if (exception instanceof pdfjsLib.UnexpectedResponseException) {
|
} else if (exception instanceof pdfjsLib.UnexpectedResponseException) {
|
||||||
loadingErrorMessage = l10n.get('unexpected_response_error', null,
|
loadingErrorMessage = l10n.get(
|
||||||
'Unexpected server response.');
|
"unexpected_response_error",
|
||||||
|
null,
|
||||||
|
"Unexpected server response."
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
loadingErrorMessage = l10n.get('loading_error', null,
|
loadingErrorMessage = l10n.get(
|
||||||
'An error occurred while loading the PDF.');
|
"loading_error",
|
||||||
|
null,
|
||||||
|
"An error occurred while loading the PDF."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadingErrorMessage.then(function(msg) {
|
loadingErrorMessage.then(function(msg) {
|
||||||
self.error(msg, { message: message, });
|
self.error(msg, { message: message });
|
||||||
});
|
});
|
||||||
self.loadingBar.hide();
|
self.loadingBar.hide();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -115,8 +132,8 @@ var PDFViewerApplication = {
|
|||||||
* destruction is completed.
|
* destruction is completed.
|
||||||
*/
|
*/
|
||||||
close: function() {
|
close: function() {
|
||||||
var errorWrapper = document.getElementById('errorWrapper');
|
var errorWrapper = document.getElementById("errorWrapper");
|
||||||
errorWrapper.setAttribute('hidden', 'true');
|
errorWrapper.setAttribute("hidden", "true");
|
||||||
|
|
||||||
if (!this.pdfLoadingTask) {
|
if (!this.pdfLoadingTask) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
@ -140,9 +157,9 @@ var PDFViewerApplication = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
get loadingBar() {
|
get loadingBar() {
|
||||||
var bar = new pdfjsViewer.ProgressBar('#loadingBar', {});
|
var bar = new pdfjsViewer.ProgressBar("#loadingBar", {});
|
||||||
|
|
||||||
return pdfjsLib.shadow(this, 'loadingBar', bar);
|
return pdfjsLib.shadow(this, "loadingBar", bar);
|
||||||
},
|
},
|
||||||
|
|
||||||
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
|
setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
|
||||||
@ -160,99 +177,125 @@ var PDFViewerApplication = {
|
|||||||
setTitleUsingMetadata: function(pdfDocument) {
|
setTitleUsingMetadata: function(pdfDocument) {
|
||||||
var self = this;
|
var self = this;
|
||||||
pdfDocument.getMetadata().then(function(data) {
|
pdfDocument.getMetadata().then(function(data) {
|
||||||
var info = data.info, metadata = data.metadata;
|
var info = data.info,
|
||||||
|
metadata = data.metadata;
|
||||||
self.documentInfo = info;
|
self.documentInfo = info;
|
||||||
self.metadata = metadata;
|
self.metadata = metadata;
|
||||||
|
|
||||||
// Provides some basic debug information
|
// Provides some basic debug information
|
||||||
console.log('PDF ' + pdfDocument.fingerprint + ' [' +
|
console.log(
|
||||||
info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() +
|
"PDF " +
|
||||||
' / ' + (info.Creator || '-').trim() + ']' +
|
pdfDocument.fingerprint +
|
||||||
' (PDF.js: ' + (pdfjsLib.version || '-') + ')');
|
" [" +
|
||||||
|
info.PDFFormatVersion +
|
||||||
|
" " +
|
||||||
|
(info.Producer || "-").trim() +
|
||||||
|
" / " +
|
||||||
|
(info.Creator || "-").trim() +
|
||||||
|
"]" +
|
||||||
|
" (PDF.js: " +
|
||||||
|
(pdfjsLib.version || "-") +
|
||||||
|
")"
|
||||||
|
);
|
||||||
|
|
||||||
var pdfTitle;
|
var pdfTitle;
|
||||||
if (metadata && metadata.has('dc:title')) {
|
if (metadata && metadata.has("dc:title")) {
|
||||||
var title = metadata.get('dc:title');
|
var title = metadata.get("dc:title");
|
||||||
// Ghostscript sometimes returns 'Untitled', so prevent setting the
|
// Ghostscript sometimes returns 'Untitled', so prevent setting the
|
||||||
// title to 'Untitled.
|
// title to 'Untitled.
|
||||||
if (title !== 'Untitled') {
|
if (title !== "Untitled") {
|
||||||
pdfTitle = title;
|
pdfTitle = title;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pdfTitle && info && info['Title']) {
|
if (!pdfTitle && info && info["Title"]) {
|
||||||
pdfTitle = info['Title'];
|
pdfTitle = info["Title"];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pdfTitle) {
|
if (pdfTitle) {
|
||||||
self.setTitle(pdfTitle + ' - ' + document.title);
|
self.setTitle(pdfTitle + " - " + document.title);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setTitle: function pdfViewSetTitle(title) {
|
setTitle: function pdfViewSetTitle(title) {
|
||||||
document.title = title;
|
document.title = title;
|
||||||
document.getElementById('title').textContent = title;
|
document.getElementById("title").textContent = title;
|
||||||
},
|
},
|
||||||
|
|
||||||
error: function pdfViewError(message, moreInfo) {
|
error: function pdfViewError(message, moreInfo) {
|
||||||
var l10n = this.l10n;
|
var l10n = this.l10n;
|
||||||
var moreInfoText = [l10n.get('error_version_info',
|
var moreInfoText = [
|
||||||
{ version: pdfjsLib.version || '?',
|
l10n.get(
|
||||||
build: pdfjsLib.build || '?', },
|
"error_version_info",
|
||||||
'PDF.js v{{version}} (build: {{build}})')];
|
{ version: pdfjsLib.version || "?", build: pdfjsLib.build || "?" },
|
||||||
|
"PDF.js v{{version}} (build: {{build}})"
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
if (moreInfo) {
|
if (moreInfo) {
|
||||||
moreInfoText.push(
|
moreInfoText.push(
|
||||||
l10n.get('error_message', { message: moreInfo.message, },
|
l10n.get(
|
||||||
'Message: {{message}}'));
|
"error_message",
|
||||||
|
{ message: moreInfo.message },
|
||||||
|
"Message: {{message}}"
|
||||||
|
)
|
||||||
|
);
|
||||||
if (moreInfo.stack) {
|
if (moreInfo.stack) {
|
||||||
moreInfoText.push(
|
moreInfoText.push(
|
||||||
l10n.get('error_stack', { stack: moreInfo.stack, },
|
l10n.get("error_stack", { stack: moreInfo.stack }, "Stack: {{stack}}")
|
||||||
'Stack: {{stack}}'));
|
);
|
||||||
} else {
|
} else {
|
||||||
if (moreInfo.filename) {
|
if (moreInfo.filename) {
|
||||||
moreInfoText.push(
|
moreInfoText.push(
|
||||||
l10n.get('error_file', { file: moreInfo.filename, },
|
l10n.get(
|
||||||
'File: {{file}}'));
|
"error_file",
|
||||||
|
{ file: moreInfo.filename },
|
||||||
|
"File: {{file}}"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (moreInfo.lineNumber) {
|
if (moreInfo.lineNumber) {
|
||||||
moreInfoText.push(
|
moreInfoText.push(
|
||||||
l10n.get('error_line', { line: moreInfo.lineNumber, },
|
l10n.get(
|
||||||
'Line: {{line}}'));
|
"error_line",
|
||||||
|
{ line: moreInfo.lineNumber },
|
||||||
|
"Line: {{line}}"
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var errorWrapper = document.getElementById('errorWrapper');
|
var errorWrapper = document.getElementById("errorWrapper");
|
||||||
errorWrapper.removeAttribute('hidden');
|
errorWrapper.removeAttribute("hidden");
|
||||||
|
|
||||||
var errorMessage = document.getElementById('errorMessage');
|
var errorMessage = document.getElementById("errorMessage");
|
||||||
errorMessage.textContent = message;
|
errorMessage.textContent = message;
|
||||||
|
|
||||||
var closeButton = document.getElementById('errorClose');
|
var closeButton = document.getElementById("errorClose");
|
||||||
closeButton.onclick = function() {
|
closeButton.onclick = function() {
|
||||||
errorWrapper.setAttribute('hidden', 'true');
|
errorWrapper.setAttribute("hidden", "true");
|
||||||
};
|
};
|
||||||
|
|
||||||
var errorMoreInfo = document.getElementById('errorMoreInfo');
|
var errorMoreInfo = document.getElementById("errorMoreInfo");
|
||||||
var moreInfoButton = document.getElementById('errorShowMore');
|
var moreInfoButton = document.getElementById("errorShowMore");
|
||||||
var lessInfoButton = document.getElementById('errorShowLess');
|
var lessInfoButton = document.getElementById("errorShowLess");
|
||||||
moreInfoButton.onclick = function() {
|
moreInfoButton.onclick = function() {
|
||||||
errorMoreInfo.removeAttribute('hidden');
|
errorMoreInfo.removeAttribute("hidden");
|
||||||
moreInfoButton.setAttribute('hidden', 'true');
|
moreInfoButton.setAttribute("hidden", "true");
|
||||||
lessInfoButton.removeAttribute('hidden');
|
lessInfoButton.removeAttribute("hidden");
|
||||||
errorMoreInfo.style.height = errorMoreInfo.scrollHeight + 'px';
|
errorMoreInfo.style.height = errorMoreInfo.scrollHeight + "px";
|
||||||
};
|
};
|
||||||
lessInfoButton.onclick = function() {
|
lessInfoButton.onclick = function() {
|
||||||
errorMoreInfo.setAttribute('hidden', 'true');
|
errorMoreInfo.setAttribute("hidden", "true");
|
||||||
moreInfoButton.removeAttribute('hidden');
|
moreInfoButton.removeAttribute("hidden");
|
||||||
lessInfoButton.setAttribute('hidden', 'true');
|
lessInfoButton.setAttribute("hidden", "true");
|
||||||
};
|
};
|
||||||
moreInfoButton.removeAttribute('hidden');
|
moreInfoButton.removeAttribute("hidden");
|
||||||
lessInfoButton.setAttribute('hidden', 'true');
|
lessInfoButton.setAttribute("hidden", "true");
|
||||||
Promise.all(moreInfoText).then(function(parts) {
|
Promise.all(moreInfoText).then(function(parts) {
|
||||||
errorMoreInfo.value = parts.join('\n');
|
errorMoreInfo.value = parts.join("\n");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -302,7 +345,7 @@ var PDFViewerApplication = {
|
|||||||
|
|
||||||
this.l10n = pdfjsViewer.NullL10n;
|
this.l10n = pdfjsViewer.NullL10n;
|
||||||
|
|
||||||
var container = document.getElementById('viewerContainer');
|
var container = document.getElementById("viewerContainer");
|
||||||
var pdfViewer = new pdfjsViewer.PDFViewer({
|
var pdfViewer = new pdfjsViewer.PDFViewer({
|
||||||
container: container,
|
container: container,
|
||||||
linkService: linkService,
|
linkService: linkService,
|
||||||
@ -318,29 +361,30 @@ var PDFViewerApplication = {
|
|||||||
});
|
});
|
||||||
linkService.setHistory(this.pdfHistory);
|
linkService.setHistory(this.pdfHistory);
|
||||||
|
|
||||||
document.getElementById('previous').addEventListener('click', function() {
|
document.getElementById("previous").addEventListener("click", function() {
|
||||||
PDFViewerApplication.page--;
|
PDFViewerApplication.page--;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('next').addEventListener('click', function() {
|
document.getElementById("next").addEventListener("click", function() {
|
||||||
PDFViewerApplication.page++;
|
PDFViewerApplication.page++;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('zoomIn').addEventListener('click', function() {
|
document.getElementById("zoomIn").addEventListener("click", function() {
|
||||||
PDFViewerApplication.zoomIn();
|
PDFViewerApplication.zoomIn();
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('zoomOut').addEventListener('click', function() {
|
document.getElementById("zoomOut").addEventListener("click", function() {
|
||||||
PDFViewerApplication.zoomOut();
|
PDFViewerApplication.zoomOut();
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('pageNumber').addEventListener('click', function() {
|
document.getElementById("pageNumber").addEventListener("click", function() {
|
||||||
this.select();
|
this.select();
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('pageNumber').addEventListener('change',
|
document
|
||||||
function() {
|
.getElementById("pageNumber")
|
||||||
PDFViewerApplication.page = (this.value | 0);
|
.addEventListener("change", function() {
|
||||||
|
PDFViewerApplication.page = this.value | 0;
|
||||||
|
|
||||||
// Ensure that the page number input displays the correct value,
|
// Ensure that the page number input displays the correct value,
|
||||||
// even if the value entered by the user was invalid
|
// even if the value entered by the user was invalid
|
||||||
@ -350,31 +394,38 @@ var PDFViewerApplication = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('pagesinit', function () {
|
document.addEventListener("pagesinit", function() {
|
||||||
// We can use pdfViewer now, e.g. let's change default scale.
|
// We can use pdfViewer now, e.g. let's change default scale.
|
||||||
pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
|
pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('pagechanging', function (evt) {
|
document.addEventListener(
|
||||||
|
"pagechanging",
|
||||||
|
function(evt) {
|
||||||
var page = evt.detail.pageNumber;
|
var page = evt.detail.pageNumber;
|
||||||
var numPages = PDFViewerApplication.pagesCount;
|
var numPages = PDFViewerApplication.pagesCount;
|
||||||
|
|
||||||
document.getElementById('pageNumber').value = page;
|
document.getElementById("pageNumber").value = page;
|
||||||
document.getElementById('previous').disabled = (page <= 1);
|
document.getElementById("previous").disabled = page <= 1;
|
||||||
document.getElementById('next').disabled = (page >= numPages);
|
document.getElementById("next").disabled = page >= numPages;
|
||||||
}, true);
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener(
|
||||||
|
"DOMContentLoaded",
|
||||||
|
function() {
|
||||||
PDFViewerApplication.initUI();
|
PDFViewerApplication.initUI();
|
||||||
}, true);
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
(function animationStartedClosure() {
|
(function animationStartedClosure() {
|
||||||
// The offsetParent is not set until the PDF.js iframe or object is visible.
|
// The offsetParent is not set until the PDF.js iframe or object is visible.
|
||||||
// Waiting for first animation.
|
// Waiting for first animation.
|
||||||
PDFViewerApplication.animationStartedPromise = new Promise(
|
PDFViewerApplication.animationStartedPromise = new Promise(function(resolve) {
|
||||||
function (resolve) {
|
|
||||||
window.requestAnimationFrame(resolve);
|
window.requestAnimationFrame(resolve);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
@ -2,10 +2,18 @@
|
|||||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
function xmlEncode(s) {
|
function xmlEncode(s) {
|
||||||
var i = 0, ch;
|
var i = 0,
|
||||||
|
ch;
|
||||||
s = String(s);
|
s = String(s);
|
||||||
while (i < s.length && (ch = s[i]) !== '&' && ch !== '<' &&
|
while (
|
||||||
ch !== '\"' && ch !== '\n' && ch !== '\r' && ch !== '\t') {
|
i < s.length &&
|
||||||
|
(ch = s[i]) !== "&" &&
|
||||||
|
ch !== "<" &&
|
||||||
|
ch !== '"' &&
|
||||||
|
ch !== "\n" &&
|
||||||
|
ch !== "\r" &&
|
||||||
|
ch !== "\t"
|
||||||
|
) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i >= s.length) {
|
if (i >= s.length) {
|
||||||
@ -15,23 +23,23 @@ function xmlEncode(s) {
|
|||||||
while (i < s.length) {
|
while (i < s.length) {
|
||||||
ch = s[i++];
|
ch = s[i++];
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '&':
|
case "&":
|
||||||
buf += '&';
|
buf += "&";
|
||||||
break;
|
break;
|
||||||
case '<':
|
case "<":
|
||||||
buf += '<';
|
buf += "<";
|
||||||
break;
|
break;
|
||||||
case '\"':
|
case '"':
|
||||||
buf += '"';
|
buf += """;
|
||||||
break;
|
break;
|
||||||
case '\n':
|
case "\n":
|
||||||
buf += '
';
|
buf += "
";
|
||||||
break;
|
break;
|
||||||
case '\r':
|
case "\r":
|
||||||
buf += '
';
|
buf += "
";
|
||||||
break;
|
break;
|
||||||
case '\t':
|
case "\t":
|
||||||
buf += '	';
|
buf += "	";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
buf += ch;
|
buf += ch;
|
||||||
@ -45,9 +53,9 @@ function DOMElement(name) {
|
|||||||
this.nodeName = name;
|
this.nodeName = name;
|
||||||
this.childNodes = [];
|
this.childNodes = [];
|
||||||
this.attributes = {};
|
this.attributes = {};
|
||||||
this.textContent = '';
|
this.textContent = "";
|
||||||
|
|
||||||
if (name === 'style') {
|
if (name === "style") {
|
||||||
this.sheet = {
|
this.sheet = {
|
||||||
cssRules: [],
|
cssRules: [],
|
||||||
insertRule: function(rule) {
|
insertRule: function(rule) {
|
||||||
@ -74,7 +82,7 @@ DOMElement.prototype = {
|
|||||||
// Assuming that there is only one matching attribute for a given name,
|
// Assuming that there is only one matching attribute for a given name,
|
||||||
// across all namespaces.
|
// across all namespaces.
|
||||||
if (NS) {
|
if (NS) {
|
||||||
var suffix = ':' + name;
|
var suffix = ":" + name;
|
||||||
for (var fullName in this.attributes) {
|
for (var fullName in this.attributes) {
|
||||||
if (fullName.slice(-suffix.length) === suffix) {
|
if (fullName.slice(-suffix.length) === suffix) {
|
||||||
return this.attributes[fullName];
|
return this.attributes[fullName];
|
||||||
@ -85,7 +93,7 @@ DOMElement.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
setAttribute: function DOMElement_setAttribute(name, value) {
|
setAttribute: function DOMElement_setAttribute(name, value) {
|
||||||
value = value || '';
|
value = value || "";
|
||||||
value = xmlEncode(value);
|
value = xmlEncode(value);
|
||||||
this.attributes[name] = value;
|
this.attributes[name] = value;
|
||||||
},
|
},
|
||||||
@ -123,7 +131,7 @@ DOMElement.prototype = {
|
|||||||
while ((chunk = serializer.getNext()) !== null) {
|
while ((chunk = serializer.getNext()) !== null) {
|
||||||
buf.push(chunk);
|
buf.push(chunk);
|
||||||
}
|
}
|
||||||
return buf.join('');
|
return buf.join("");
|
||||||
},
|
},
|
||||||
|
|
||||||
getSerializer: function DOMElement_getSerializer() {
|
getSerializer: function DOMElement_getSerializer() {
|
||||||
@ -149,12 +157,14 @@ DOMElementSerializer.prototype = {
|
|||||||
switch (this._state) {
|
switch (this._state) {
|
||||||
case 0: // Start opening tag.
|
case 0: // Start opening tag.
|
||||||
++this._state;
|
++this._state;
|
||||||
return '<' + node.nodeName;
|
return "<" + node.nodeName;
|
||||||
case 1: // Add SVG namespace if this is the root element.
|
case 1: // Add SVG namespace if this is the root element.
|
||||||
++this._state;
|
++this._state;
|
||||||
if (node.nodeName === 'svg:svg') {
|
if (node.nodeName === "svg:svg") {
|
||||||
return ' xmlns:xlink="http://www.w3.org/1999/xlink"' +
|
return (
|
||||||
' xmlns:svg="http://www.w3.org/2000/svg"';
|
' xmlns:xlink="http://www.w3.org/1999/xlink"' +
|
||||||
|
' xmlns:svg="http://www.w3.org/2000/svg"'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
/* falls through */
|
/* falls through */
|
||||||
case 2: // Initialize variables for looping over attributes.
|
case 2: // Initialize variables for looping over attributes.
|
||||||
@ -165,12 +175,12 @@ DOMElementSerializer.prototype = {
|
|||||||
case 3: // Serialize any attributes and end opening tag.
|
case 3: // Serialize any attributes and end opening tag.
|
||||||
if (this._loopIndex < this._attributeKeys.length) {
|
if (this._loopIndex < this._attributeKeys.length) {
|
||||||
var name = this._attributeKeys[this._loopIndex++];
|
var name = this._attributeKeys[this._loopIndex++];
|
||||||
return ' ' + name + '="' + xmlEncode(node.attributes[name]) + '"';
|
return " " + name + '="' + xmlEncode(node.attributes[name]) + '"';
|
||||||
}
|
}
|
||||||
++this._state;
|
++this._state;
|
||||||
return '>';
|
return ">";
|
||||||
case 4: // Serialize textContent for tspan/style elements.
|
case 4: // Serialize textContent for tspan/style elements.
|
||||||
if (node.nodeName === 'svg:tspan' || node.nodeName === 'svg:style') {
|
if (node.nodeName === "svg:tspan" || node.nodeName === "svg:style") {
|
||||||
this._state = 6;
|
this._state = 6;
|
||||||
return xmlEncode(node.textContent);
|
return xmlEncode(node.textContent);
|
||||||
}
|
}
|
||||||
@ -196,11 +206,11 @@ DOMElementSerializer.prototype = {
|
|||||||
/* falls through */
|
/* falls through */
|
||||||
case 6: // Ending tag.
|
case 6: // Ending tag.
|
||||||
++this._state;
|
++this._state;
|
||||||
return '</' + node.nodeName + '>';
|
return "</" + node.nodeName + ">";
|
||||||
case 7: // Done.
|
case 7: // Done.
|
||||||
return null;
|
return null;
|
||||||
default:
|
default:
|
||||||
throw new Error('Unexpected serialization state: ' + this._state);
|
throw new Error("Unexpected serialization state: " + this._state);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -209,7 +219,7 @@ const document = {
|
|||||||
childNodes: [],
|
childNodes: [],
|
||||||
|
|
||||||
get currentScript() {
|
get currentScript() {
|
||||||
return { src: '', };
|
return { src: "" };
|
||||||
},
|
},
|
||||||
|
|
||||||
get documentElement() {
|
get documentElement() {
|
||||||
@ -222,12 +232,12 @@ const document = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
createElement: function(element) {
|
createElement: function(element) {
|
||||||
return this.createElementNS('', element);
|
return this.createElementNS("", element);
|
||||||
},
|
},
|
||||||
|
|
||||||
getElementsByTagName: function(element) {
|
getElementsByTagName: function(element) {
|
||||||
if (element === 'head') {
|
if (element === "head") {
|
||||||
return [this.head || (this.head = new DOMElement('head'))];
|
return [this.head || (this.head = new DOMElement("head"))];
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
@ -256,13 +266,13 @@ var exported_symbols = Object.keys(exports);
|
|||||||
|
|
||||||
exports.setStubs = function(namespace) {
|
exports.setStubs = function(namespace) {
|
||||||
exported_symbols.forEach(function(key) {
|
exported_symbols.forEach(function(key) {
|
||||||
console.assert(!(key in namespace), 'property should not be set: ' + key);
|
console.assert(!(key in namespace), "property should not be set: " + key);
|
||||||
namespace[key] = exports[key];
|
namespace[key] = exports[key];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
exports.unsetStubs = function(namespace) {
|
exports.unsetStubs = function(namespace) {
|
||||||
exported_symbols.forEach(function(key) {
|
exported_symbols.forEach(function(key) {
|
||||||
console.assert(key in namespace, 'property should be set: ' + key);
|
console.assert(key in namespace, "property should be set: " + key);
|
||||||
delete namespace[key];
|
delete namespace[key];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -8,28 +8,29 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
// Run `gulp dist-install` to generate 'pdfjs-dist' npm package files.
|
// Run `gulp dist-install` to generate 'pdfjs-dist' npm package files.
|
||||||
var pdfjsLib = require('pdfjs-dist');
|
var pdfjsLib = require("pdfjs-dist");
|
||||||
|
|
||||||
// Loading file from file system into typed array
|
// Loading file from file system into typed array
|
||||||
var pdfPath = process.argv[2] || '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var pdfPath = process.argv[2] || "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
|
|
||||||
// Will be using promises to load document, pages and misc data instead of
|
// Will be using promises to load document, pages and misc data instead of
|
||||||
// callback.
|
// callback.
|
||||||
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
||||||
loadingTask.promise.then(function(doc) {
|
loadingTask.promise
|
||||||
|
.then(function(doc) {
|
||||||
var numPages = doc.numPages;
|
var numPages = doc.numPages;
|
||||||
console.log('# Document Loaded');
|
console.log("# Document Loaded");
|
||||||
console.log('Number of Pages: ' + numPages);
|
console.log("Number of Pages: " + numPages);
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
var lastPromise; // will be used to chain promises
|
var lastPromise; // will be used to chain promises
|
||||||
lastPromise = doc.getMetadata().then(function(data) {
|
lastPromise = doc.getMetadata().then(function(data) {
|
||||||
console.log('# Metadata Is Loaded');
|
console.log("# Metadata Is Loaded");
|
||||||
console.log('## Info');
|
console.log("## Info");
|
||||||
console.log(JSON.stringify(data.info, null, 2));
|
console.log(JSON.stringify(data.info, null, 2));
|
||||||
console.log();
|
console.log();
|
||||||
if (data.metadata) {
|
if (data.metadata) {
|
||||||
console.log('## Metadata');
|
console.log("## Metadata");
|
||||||
console.log(JSON.stringify(data.metadata.getAll(), null, 2));
|
console.log(JSON.stringify(data.metadata.getAll(), null, 2));
|
||||||
console.log();
|
console.log();
|
||||||
}
|
}
|
||||||
@ -37,19 +38,22 @@ loadingTask.promise.then(function(doc) {
|
|||||||
|
|
||||||
var loadPage = function(pageNum) {
|
var loadPage = function(pageNum) {
|
||||||
return doc.getPage(pageNum).then(function(page) {
|
return doc.getPage(pageNum).then(function(page) {
|
||||||
console.log('# Page ' + pageNum);
|
console.log("# Page " + pageNum);
|
||||||
var viewport = page.getViewport({ scale: 1.0, });
|
var viewport = page.getViewport({ scale: 1.0 });
|
||||||
console.log('Size: ' + viewport.width + 'x' + viewport.height);
|
console.log("Size: " + viewport.width + "x" + viewport.height);
|
||||||
console.log();
|
console.log();
|
||||||
return page.getTextContent().then(function (content) {
|
return page
|
||||||
|
.getTextContent()
|
||||||
|
.then(function(content) {
|
||||||
// Content contains lots of information about the text layout and
|
// Content contains lots of information about the text layout and
|
||||||
// styles, but we need only strings at the moment
|
// styles, but we need only strings at the moment
|
||||||
var strings = content.items.map(function(item) {
|
var strings = content.items.map(function(item) {
|
||||||
return item.str;
|
return item.str;
|
||||||
});
|
});
|
||||||
console.log('## Text Content');
|
console.log("## Text Content");
|
||||||
console.log(strings.join(' '));
|
console.log(strings.join(" "));
|
||||||
}).then(function () {
|
})
|
||||||
|
.then(function() {
|
||||||
console.log();
|
console.log();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -60,8 +64,12 @@ loadingTask.promise.then(function(doc) {
|
|||||||
lastPromise = lastPromise.then(loadPage.bind(null, i));
|
lastPromise = lastPromise.then(loadPage.bind(null, i));
|
||||||
}
|
}
|
||||||
return lastPromise;
|
return lastPromise;
|
||||||
}).then(function () {
|
})
|
||||||
console.log('# End of Document');
|
.then(
|
||||||
}, function (err) {
|
function() {
|
||||||
console.error('Error: ' + err);
|
console.log("# End of Document");
|
||||||
});
|
},
|
||||||
|
function(err) {
|
||||||
|
console.error("Error: " + err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
@ -13,16 +13,16 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var Canvas = require('canvas');
|
var Canvas = require("canvas");
|
||||||
var assert = require('assert').strict;
|
var assert = require("assert").strict;
|
||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
|
|
||||||
function NodeCanvasFactory() {}
|
function NodeCanvasFactory() {}
|
||||||
NodeCanvasFactory.prototype = {
|
NodeCanvasFactory.prototype = {
|
||||||
create: function NodeCanvasFactory_create(width, height) {
|
create: function NodeCanvasFactory_create(width, height) {
|
||||||
assert(width > 0 && height > 0, 'Invalid canvas size');
|
assert(width > 0 && height > 0, "Invalid canvas size");
|
||||||
var canvas = Canvas.createCanvas(width, height);
|
var canvas = Canvas.createCanvas(width, height);
|
||||||
var context = canvas.getContext('2d');
|
var context = canvas.getContext("2d");
|
||||||
return {
|
return {
|
||||||
canvas: canvas,
|
canvas: canvas,
|
||||||
context: context,
|
context: context,
|
||||||
@ -30,14 +30,14 @@ NodeCanvasFactory.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
reset: function NodeCanvasFactory_reset(canvasAndContext, width, height) {
|
reset: function NodeCanvasFactory_reset(canvasAndContext, width, height) {
|
||||||
assert(canvasAndContext.canvas, 'Canvas is not specified');
|
assert(canvasAndContext.canvas, "Canvas is not specified");
|
||||||
assert(width > 0 && height > 0, 'Invalid canvas size');
|
assert(width > 0 && height > 0, "Invalid canvas size");
|
||||||
canvasAndContext.canvas.width = width;
|
canvasAndContext.canvas.width = width;
|
||||||
canvasAndContext.canvas.height = height;
|
canvasAndContext.canvas.height = height;
|
||||||
},
|
},
|
||||||
|
|
||||||
destroy: function NodeCanvasFactory_destroy(canvasAndContext) {
|
destroy: function NodeCanvasFactory_destroy(canvasAndContext) {
|
||||||
assert(canvasAndContext.canvas, 'Canvas is not specified');
|
assert(canvasAndContext.canvas, "Canvas is not specified");
|
||||||
|
|
||||||
// Zeroing the width and height cause Firefox to release graphics
|
// Zeroing the width and height cause Firefox to release graphics
|
||||||
// resources immediately, which can greatly reduce memory consumption.
|
// resources immediately, which can greatly reduce memory consumption.
|
||||||
@ -48,26 +48,29 @@ NodeCanvasFactory.prototype = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
var pdfjsLib = require('pdfjs-dist');
|
var pdfjsLib = require("pdfjs-dist");
|
||||||
|
|
||||||
// Relative path of the PDF file.
|
// Relative path of the PDF file.
|
||||||
var pdfURL = '../../../web/compressed.tracemonkey-pldi-09.pdf';
|
var pdfURL = "../../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
|
|
||||||
// Read the PDF file into a typed array so PDF.js can load it.
|
// Read the PDF file into a typed array so PDF.js can load it.
|
||||||
var rawData = new Uint8Array(fs.readFileSync(pdfURL));
|
var rawData = new Uint8Array(fs.readFileSync(pdfURL));
|
||||||
|
|
||||||
// Load the PDF file.
|
// Load the PDF file.
|
||||||
var loadingTask = pdfjsLib.getDocument(rawData);
|
var loadingTask = pdfjsLib.getDocument(rawData);
|
||||||
loadingTask.promise.then(function(pdfDocument) {
|
loadingTask.promise
|
||||||
console.log('# PDF document loaded.');
|
.then(function(pdfDocument) {
|
||||||
|
console.log("# PDF document loaded.");
|
||||||
|
|
||||||
// Get the first page.
|
// Get the first page.
|
||||||
pdfDocument.getPage(1).then(function(page) {
|
pdfDocument.getPage(1).then(function(page) {
|
||||||
// Render the page on a Node canvas with 100% scale.
|
// Render the page on a Node canvas with 100% scale.
|
||||||
var viewport = page.getViewport({ scale: 1.0, });
|
var viewport = page.getViewport({ scale: 1.0 });
|
||||||
var canvasFactory = new NodeCanvasFactory();
|
var canvasFactory = new NodeCanvasFactory();
|
||||||
var canvasAndContext =
|
var canvasAndContext = canvasFactory.create(
|
||||||
canvasFactory.create(viewport.width, viewport.height);
|
viewport.width,
|
||||||
|
viewport.height
|
||||||
|
);
|
||||||
var renderContext = {
|
var renderContext = {
|
||||||
canvasContext: canvasAndContext.context,
|
canvasContext: canvasAndContext.context,
|
||||||
viewport: viewport,
|
viewport: viewport,
|
||||||
@ -78,16 +81,18 @@ loadingTask.promise.then(function(pdfDocument) {
|
|||||||
renderTask.promise.then(function() {
|
renderTask.promise.then(function() {
|
||||||
// Convert the canvas to an image buffer.
|
// Convert the canvas to an image buffer.
|
||||||
var image = canvasAndContext.canvas.toBuffer();
|
var image = canvasAndContext.canvas.toBuffer();
|
||||||
fs.writeFile('output.png', image, function (error) {
|
fs.writeFile("output.png", image, function(error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error('Error: ' + error);
|
console.error("Error: " + error);
|
||||||
} else {
|
} else {
|
||||||
console.log(
|
console.log(
|
||||||
'Finished converting first page of PDF file to a PNG image.');
|
"Finished converting first page of PDF file to a PNG image."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}).catch(function(reason) {
|
})
|
||||||
|
.catch(function(reason) {
|
||||||
console.log(reason);
|
console.log(reason);
|
||||||
});
|
});
|
||||||
|
@ -5,29 +5,29 @@
|
|||||||
// Node tool to dump SVG output into a file.
|
// Node tool to dump SVG output into a file.
|
||||||
//
|
//
|
||||||
|
|
||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var util = require('util');
|
var util = require("util");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
var stream = require('stream');
|
var stream = require("stream");
|
||||||
|
|
||||||
// HACK few hacks to let PDF.js be loaded not as a module in global space.
|
// HACK few hacks to let PDF.js be loaded not as a module in global space.
|
||||||
require('./domstubs.js').setStubs(global);
|
require("./domstubs.js").setStubs(global);
|
||||||
|
|
||||||
// Run `gulp dist-install` to generate 'pdfjs-dist' npm package files.
|
// Run `gulp dist-install` to generate 'pdfjs-dist' npm package files.
|
||||||
var pdfjsLib = require('pdfjs-dist');
|
var pdfjsLib = require("pdfjs-dist");
|
||||||
|
|
||||||
// Loading file from file system into typed array
|
// Loading file from file system into typed array
|
||||||
var pdfPath = process.argv[2] || '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var pdfPath = process.argv[2] || "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
var data = new Uint8Array(fs.readFileSync(pdfPath));
|
var data = new Uint8Array(fs.readFileSync(pdfPath));
|
||||||
|
|
||||||
var outputDirectory = './svgdump';
|
var outputDirectory = "./svgdump";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Note: This creates a directory only one level deep. If you want to create
|
// Note: This creates a directory only one level deep. If you want to create
|
||||||
// multiple subdirectories on the fly, use the mkdirp module from npm.
|
// multiple subdirectories on the fly, use the mkdirp module from npm.
|
||||||
fs.mkdirSync(outputDirectory);
|
fs.mkdirSync(outputDirectory);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code !== 'EEXIST') {
|
if (e.code !== "EEXIST") {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -35,7 +35,7 @@ try {
|
|||||||
// Dumps svg outputs to a folder called svgdump
|
// Dumps svg outputs to a folder called svgdump
|
||||||
function getFilePathForPage(pageNum) {
|
function getFilePathForPage(pageNum) {
|
||||||
var name = path.basename(pdfPath, path.extname(pdfPath));
|
var name = path.basename(pdfPath, path.extname(pdfPath));
|
||||||
return path.join(outputDirectory, name + '-' + pageNum + '.svg');
|
return path.join(outputDirectory, name + "-" + pageNum + ".svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -71,9 +71,9 @@ function writeSvgToFile(svgElement, filePath) {
|
|||||||
});
|
});
|
||||||
var writableStream = fs.createWriteStream(filePath);
|
var writableStream = fs.createWriteStream(filePath);
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
readableSvgStream.once('error', reject);
|
readableSvgStream.once("error", reject);
|
||||||
writableStream.once('error', reject);
|
writableStream.once("error", reject);
|
||||||
writableStream.once('finish', resolve);
|
writableStream.once("finish", resolve);
|
||||||
readableSvgStream.pipe(writableStream);
|
readableSvgStream.pipe(writableStream);
|
||||||
}).catch(function(err) {
|
}).catch(function(err) {
|
||||||
readableSvgStream = null; // Explicitly null because of v8 bug 6512.
|
readableSvgStream = null; // Explicitly null because of v8 bug 6512.
|
||||||
@ -90,30 +90,33 @@ var loadingTask = pdfjsLib.getDocument({
|
|||||||
// processing.
|
// processing.
|
||||||
nativeImageDecoderSupport: pdfjsLib.NativeImageDecoding.DISPLAY,
|
nativeImageDecoderSupport: pdfjsLib.NativeImageDecoding.DISPLAY,
|
||||||
});
|
});
|
||||||
loadingTask.promise.then(function(doc) {
|
loadingTask.promise
|
||||||
|
.then(function(doc) {
|
||||||
var numPages = doc.numPages;
|
var numPages = doc.numPages;
|
||||||
console.log('# Document Loaded');
|
console.log("# Document Loaded");
|
||||||
console.log('Number of Pages: ' + numPages);
|
console.log("Number of Pages: " + numPages);
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
var lastPromise = Promise.resolve(); // will be used to chain promises
|
var lastPromise = Promise.resolve(); // will be used to chain promises
|
||||||
var loadPage = function(pageNum) {
|
var loadPage = function(pageNum) {
|
||||||
return doc.getPage(pageNum).then(function(page) {
|
return doc.getPage(pageNum).then(function(page) {
|
||||||
console.log('# Page ' + pageNum);
|
console.log("# Page " + pageNum);
|
||||||
var viewport = page.getViewport({ scale: 1.0, });
|
var viewport = page.getViewport({ scale: 1.0 });
|
||||||
console.log('Size: ' + viewport.width + 'x' + viewport.height);
|
console.log("Size: " + viewport.width + "x" + viewport.height);
|
||||||
console.log();
|
console.log();
|
||||||
|
|
||||||
return page.getOperatorList().then(function(opList) {
|
return page.getOperatorList().then(function(opList) {
|
||||||
var svgGfx = new pdfjsLib.SVGGraphics(page.commonObjs, page.objs);
|
var svgGfx = new pdfjsLib.SVGGraphics(page.commonObjs, page.objs);
|
||||||
svgGfx.embedFonts = true;
|
svgGfx.embedFonts = true;
|
||||||
return svgGfx.getSVG(opList, viewport).then(function(svg) {
|
return svgGfx.getSVG(opList, viewport).then(function(svg) {
|
||||||
return writeSvgToFile(svg, getFilePathForPage(pageNum))
|
return writeSvgToFile(svg, getFilePathForPage(pageNum)).then(
|
||||||
.then(function () {
|
function() {
|
||||||
console.log('Page: ' + pageNum);
|
console.log("Page: " + pageNum);
|
||||||
}, function(err) {
|
},
|
||||||
console.log('Error: ' + err);
|
function(err) {
|
||||||
});
|
console.log("Error: " + err);
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -123,8 +126,12 @@ loadingTask.promise.then(function(doc) {
|
|||||||
lastPromise = lastPromise.then(loadPage.bind(null, i));
|
lastPromise = lastPromise.then(loadPage.bind(null, i));
|
||||||
}
|
}
|
||||||
return lastPromise;
|
return lastPromise;
|
||||||
}).then(function () {
|
})
|
||||||
console.log('# End of Document');
|
.then(
|
||||||
}, function (err) {
|
function() {
|
||||||
console.error('Error: ' + err);
|
console.log("# End of Document");
|
||||||
});
|
},
|
||||||
|
function(err) {
|
||||||
|
console.error("Error: " + err);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
@ -13,26 +13,27 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
|
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFViewer) {
|
||||||
alert('Please build the pdfjs-dist library using\n' +
|
alert(
|
||||||
' `gulp dist-install`');
|
"Please build the pdfjs-dist library using\n" + " `gulp dist-install`"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The workerSrc property shall be specified.
|
// The workerSrc property shall be specified.
|
||||||
//
|
//
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||||
|
|
||||||
// Some PDFs need external cmaps.
|
// Some PDFs need external cmaps.
|
||||||
//
|
//
|
||||||
var CMAP_URL = '../../node_modules/pdfjs-dist/cmaps/';
|
var CMAP_URL = "../../node_modules/pdfjs-dist/cmaps/";
|
||||||
var CMAP_PACKED = true;
|
var CMAP_PACKED = true;
|
||||||
|
|
||||||
var DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
|
|
||||||
var container = document.getElementById('viewerContainer');
|
var container = document.getElementById("viewerContainer");
|
||||||
|
|
||||||
// (Optionally) enable hyperlinks within PDF files.
|
// (Optionally) enable hyperlinks within PDF files.
|
||||||
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||||
@ -40,14 +41,14 @@ var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
|||||||
var pdfViewer = new pdfjsViewer.PDFViewer({
|
var pdfViewer = new pdfjsViewer.PDFViewer({
|
||||||
container: container,
|
container: container,
|
||||||
linkService: pdfLinkService,
|
linkService: pdfLinkService,
|
||||||
renderer: 'svg',
|
renderer: "svg",
|
||||||
textLayerMode: 0,
|
textLayerMode: 0,
|
||||||
});
|
});
|
||||||
pdfLinkService.setViewer(pdfViewer);
|
pdfLinkService.setViewer(pdfViewer);
|
||||||
|
|
||||||
document.addEventListener('pagesinit', function () {
|
document.addEventListener("pagesinit", function() {
|
||||||
// We can use pdfViewer now, e.g. let's change default scale.
|
// We can use pdfViewer now, e.g. let's change default scale.
|
||||||
pdfViewer.currentScaleValue = 'page-width';
|
pdfViewer.currentScaleValue = "page-width";
|
||||||
});
|
});
|
||||||
|
|
||||||
// Loading document.
|
// Loading document.
|
||||||
|
@ -13,21 +13,21 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var PDF_PATH = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
var PDF_PATH = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||||
var PAGE_NUMBER = 1;
|
var PAGE_NUMBER = 1;
|
||||||
var PAGE_SCALE = 1.5;
|
var PAGE_SCALE = 1.5;
|
||||||
var SVG_NS = 'http://www.w3.org/2000/svg';
|
var SVG_NS = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||||
|
|
||||||
function buildSVG(viewport, textContent) {
|
function buildSVG(viewport, textContent) {
|
||||||
// Building SVG with size of the viewport (for simplicity)
|
// Building SVG with size of the viewport (for simplicity)
|
||||||
var svg = document.createElementNS(SVG_NS, 'svg:svg');
|
var svg = document.createElementNS(SVG_NS, "svg:svg");
|
||||||
svg.setAttribute('width', viewport.width + 'px');
|
svg.setAttribute("width", viewport.width + "px");
|
||||||
svg.setAttribute('height', viewport.height + 'px');
|
svg.setAttribute("height", viewport.height + "px");
|
||||||
// items are transformed to have 1px font size
|
// items are transformed to have 1px font size
|
||||||
svg.setAttribute('font-size', 1);
|
svg.setAttribute("font-size", 1);
|
||||||
|
|
||||||
// processing all items
|
// processing all items
|
||||||
textContent.items.forEach(function(textItem) {
|
textContent.items.forEach(function(textItem) {
|
||||||
@ -35,12 +35,13 @@ function buildSVG(viewport, textContent) {
|
|||||||
// rotation and Y-axis flip, and not forgetting to flip text.
|
// rotation and Y-axis flip, and not forgetting to flip text.
|
||||||
var tx = pdfjsLib.Util.transform(
|
var tx = pdfjsLib.Util.transform(
|
||||||
pdfjsLib.Util.transform(viewport.transform, textItem.transform),
|
pdfjsLib.Util.transform(viewport.transform, textItem.transform),
|
||||||
[1, 0, 0, -1, 0, 0]);
|
[1, 0, 0, -1, 0, 0]
|
||||||
|
);
|
||||||
var style = textContent.styles[textItem.fontName];
|
var style = textContent.styles[textItem.fontName];
|
||||||
// adding text element
|
// adding text element
|
||||||
var text = document.createElementNS(SVG_NS, 'svg:text');
|
var text = document.createElementNS(SVG_NS, "svg:text");
|
||||||
text.setAttribute('transform', 'matrix(' + tx.join(' ') + ')');
|
text.setAttribute("transform", "matrix(" + tx.join(" ") + ")");
|
||||||
text.setAttribute('font-family', style.fontFamily);
|
text.setAttribute("font-family", style.fontFamily);
|
||||||
text.textContent = textItem.str;
|
text.textContent = textItem.str;
|
||||||
svg.appendChild(text);
|
svg.appendChild(text);
|
||||||
});
|
});
|
||||||
@ -49,23 +50,25 @@ function buildSVG(viewport, textContent) {
|
|||||||
|
|
||||||
function pageLoaded() {
|
function pageLoaded() {
|
||||||
// Loading document and page text content
|
// Loading document and page text content
|
||||||
var loadingTask = pdfjsLib.getDocument({ url: PDF_PATH, });
|
var loadingTask = pdfjsLib.getDocument({ url: PDF_PATH });
|
||||||
loadingTask.promise.then(function(pdfDocument) {
|
loadingTask.promise.then(function(pdfDocument) {
|
||||||
pdfDocument.getPage(PAGE_NUMBER).then(function(page) {
|
pdfDocument.getPage(PAGE_NUMBER).then(function(page) {
|
||||||
var viewport = page.getViewport({ scale: PAGE_SCALE, });
|
var viewport = page.getViewport({ scale: PAGE_SCALE });
|
||||||
page.getTextContent().then(function(textContent) {
|
page.getTextContent().then(function(textContent) {
|
||||||
// building SVG and adding that to the DOM
|
// building SVG and adding that to the DOM
|
||||||
var svg = buildSVG(viewport, textContent);
|
var svg = buildSVG(viewport, textContent);
|
||||||
document.getElementById('pageContainer').appendChild(svg);
|
document.getElementById("pageContainer").appendChild(svg);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
if (typeof pdfjsLib === 'undefined') {
|
if (typeof pdfjsLib === "undefined") {
|
||||||
alert('Built version of PDF.js was not found.\n' +
|
alert(
|
||||||
'Please run `gulp dist-install`.');
|
"Built version of PDF.js was not found.\n" +
|
||||||
|
"Please run `gulp dist-install`."
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pageLoaded();
|
pageLoaded();
|
||||||
|
@ -3,31 +3,33 @@
|
|||||||
|
|
||||||
// Hello world example for webpack.
|
// Hello world example for webpack.
|
||||||
|
|
||||||
var pdfjsLib = require('pdfjs-dist');
|
var pdfjsLib = require("pdfjs-dist");
|
||||||
|
|
||||||
var pdfPath = '../learning/helloworld.pdf';
|
var pdfPath = "../learning/helloworld.pdf";
|
||||||
|
|
||||||
// Setting worker path to worker bundle.
|
// Setting worker path to worker bundle.
|
||||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||||
'../../build/webpack/pdf.worker.bundle.js';
|
"../../build/webpack/pdf.worker.bundle.js";
|
||||||
|
|
||||||
// Loading a document.
|
// Loading a document.
|
||||||
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
||||||
loadingTask.promise.then(function (pdfDocument) {
|
loadingTask.promise
|
||||||
|
.then(function(pdfDocument) {
|
||||||
// Request a first page
|
// Request a first page
|
||||||
return pdfDocument.getPage(1).then(function(pdfPage) {
|
return pdfDocument.getPage(1).then(function(pdfPage) {
|
||||||
// Display page on the existing canvas with 100% scale.
|
// Display page on the existing canvas with 100% scale.
|
||||||
var viewport = pdfPage.getViewport({ scale: 1.0, });
|
var viewport = pdfPage.getViewport({ scale: 1.0 });
|
||||||
var canvas = document.getElementById('theCanvas');
|
var canvas = document.getElementById("theCanvas");
|
||||||
canvas.width = viewport.width;
|
canvas.width = viewport.width;
|
||||||
canvas.height = viewport.height;
|
canvas.height = viewport.height;
|
||||||
var ctx = canvas.getContext('2d');
|
var ctx = canvas.getContext("2d");
|
||||||
var renderTask = pdfPage.render({
|
var renderTask = pdfPage.render({
|
||||||
canvasContext: ctx,
|
canvasContext: ctx,
|
||||||
viewport: viewport,
|
viewport: viewport,
|
||||||
});
|
});
|
||||||
return renderTask.promise;
|
return renderTask.promise;
|
||||||
});
|
});
|
||||||
}).catch(function (reason) {
|
})
|
||||||
console.error('Error: ' + reason);
|
.catch(function(reason) {
|
||||||
|
console.error("Error: " + reason);
|
||||||
});
|
});
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
var webpack = require('webpack'); // eslint-disable-line no-unused-vars
|
var webpack = require("webpack"); // eslint-disable-line no-unused-vars
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
context: __dirname,
|
context: __dirname,
|
||||||
entry: {
|
entry: {
|
||||||
'main': './main.js',
|
main: "./main.js",
|
||||||
'pdf.worker': 'pdfjs-dist/build/pdf.worker.entry',
|
"pdf.worker": "pdfjs-dist/build/pdf.worker.entry",
|
||||||
},
|
},
|
||||||
mode: 'none',
|
mode: "none",
|
||||||
output: {
|
output: {
|
||||||
path: path.join(__dirname, '../../build/webpack'),
|
path: path.join(__dirname, "../../build/webpack"),
|
||||||
publicPath: '../../build/webpack/',
|
publicPath: "../../build/webpack/",
|
||||||
filename: '[name].bundle.js',
|
filename: "[name].bundle.js",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -14,22 +14,22 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var VIEWER_URL = chrome.extension.getURL('content/web/viewer.html');
|
var VIEWER_URL = chrome.extension.getURL("content/web/viewer.html");
|
||||||
|
|
||||||
function getViewerURL(pdf_url) {
|
function getViewerURL(pdf_url) {
|
||||||
return VIEWER_URL + '?file=' + encodeURIComponent(pdf_url);
|
return VIEWER_URL + "?file=" + encodeURIComponent(pdf_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CSS.supports('animation', '0s')) {
|
if (CSS.supports("animation", "0s")) {
|
||||||
document.addEventListener('animationstart', onAnimationStart, true);
|
document.addEventListener("animationstart", onAnimationStart, true);
|
||||||
} else {
|
} else {
|
||||||
document.addEventListener('webkitAnimationStart', onAnimationStart, true);
|
document.addEventListener("webkitAnimationStart", onAnimationStart, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onAnimationStart(event) {
|
function onAnimationStart(event) {
|
||||||
if (event.animationName === 'pdfjs-detected-object-or-embed') {
|
if (event.animationName === "pdfjs-detected-object-or-embed") {
|
||||||
watchObjectOrEmbed(event.target);
|
watchObjectOrEmbed(event.target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -40,19 +40,23 @@ function onAnimationStart(event) {
|
|||||||
// invocations have no effect.
|
// invocations have no effect.
|
||||||
function watchObjectOrEmbed(elem) {
|
function watchObjectOrEmbed(elem) {
|
||||||
var mimeType = elem.type;
|
var mimeType = elem.type;
|
||||||
if (mimeType && mimeType.toLowerCase() !== 'application/pdf') {
|
if (mimeType && mimeType.toLowerCase() !== "application/pdf") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// <embed src> <object data>
|
// <embed src> <object data>
|
||||||
var srcAttribute = 'src' in elem ? 'src' : 'data';
|
var srcAttribute = "src" in elem ? "src" : "data";
|
||||||
var path = elem[srcAttribute];
|
var path = elem[srcAttribute];
|
||||||
if (!mimeType && !/\.pdf($|[?#])/i.test(path)) {
|
if (!mimeType && !/\.pdf($|[?#])/i.test(path)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elem.tagName === 'EMBED' && elem.name === 'plugin' &&
|
if (
|
||||||
|
elem.tagName === "EMBED" &&
|
||||||
|
elem.name === "plugin" &&
|
||||||
elem.parentNode === document.body &&
|
elem.parentNode === document.body &&
|
||||||
elem.parentNode.childElementCount === 1 && elem.src === location.href) {
|
elem.parentNode.childElementCount === 1 &&
|
||||||
|
elem.src === location.href
|
||||||
|
) {
|
||||||
// This page is most likely Chrome's default page that embeds a PDF file.
|
// This page is most likely Chrome's default page that embeds a PDF file.
|
||||||
// The fact that the extension's background page did not intercept and
|
// The fact that the extension's background page did not intercept and
|
||||||
// redirect this PDF request means that this PDF cannot be opened by PDF.js,
|
// redirect this PDF request means that this PDF cannot be opened by PDF.js,
|
||||||
@ -62,7 +66,7 @@ function watchObjectOrEmbed(elem) {
|
|||||||
// Until #4483 is fixed, POST requests should be ignored.
|
// Until #4483 is fixed, POST requests should be ignored.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (elem.tagName === 'EMBED' && elem.src === 'about:blank') {
|
if (elem.tagName === "EMBED" && elem.src === "about:blank") {
|
||||||
// Starting from Chrome 76, internal embeds do not have the original URL,
|
// Starting from Chrome 76, internal embeds do not have the original URL,
|
||||||
// but "about:blank" instead.
|
// but "about:blank" instead.
|
||||||
// See https://github.com/mozilla/pdf.js/issues/11137
|
// See https://github.com/mozilla/pdf.js/issues/11137
|
||||||
@ -76,9 +80,9 @@ function watchObjectOrEmbed(elem) {
|
|||||||
|
|
||||||
var tagName = elem.tagName.toUpperCase();
|
var tagName = elem.tagName.toUpperCase();
|
||||||
var updateEmbedOrObject;
|
var updateEmbedOrObject;
|
||||||
if (tagName === 'EMBED') {
|
if (tagName === "EMBED") {
|
||||||
updateEmbedOrObject = updateEmbedElement;
|
updateEmbedOrObject = updateEmbedElement;
|
||||||
} else if (tagName === 'OBJECT') {
|
} else if (tagName === "OBJECT") {
|
||||||
updateEmbedOrObject = updateObjectElement;
|
updateEmbedOrObject = updateObjectElement;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@ -115,7 +119,7 @@ function watchObjectOrEmbed(elem) {
|
|||||||
|
|
||||||
// Display the PDF Viewer in an <embed>.
|
// Display the PDF Viewer in an <embed>.
|
||||||
function updateEmbedElement(elem) {
|
function updateEmbedElement(elem) {
|
||||||
if (elem.type === 'text/html' && elem.src.lastIndexOf(VIEWER_URL, 0) === 0) {
|
if (elem.type === "text/html" && elem.src.lastIndexOf(VIEWER_URL, 0) === 0) {
|
||||||
// The viewer is already shown.
|
// The viewer is already shown.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -126,7 +130,7 @@ function updateEmbedElement(elem) {
|
|||||||
if (parentNode) {
|
if (parentNode) {
|
||||||
parentNode.removeChild(elem);
|
parentNode.removeChild(elem);
|
||||||
}
|
}
|
||||||
elem.type = 'text/html';
|
elem.type = "text/html";
|
||||||
elem.src = getEmbeddedViewerURL(elem.src);
|
elem.src = getEmbeddedViewerURL(elem.src);
|
||||||
if (parentNode) {
|
if (parentNode) {
|
||||||
parentNode.insertBefore(elem, nextSibling);
|
parentNode.insertBefore(elem, nextSibling);
|
||||||
@ -155,21 +159,21 @@ function updateObjectElement(elem) {
|
|||||||
var iframe = elem.firstElementChild;
|
var iframe = elem.firstElementChild;
|
||||||
if (!iframe || !iframe.__inserted_by_pdfjs) {
|
if (!iframe || !iframe.__inserted_by_pdfjs) {
|
||||||
iframe = createFullSizeIframe();
|
iframe = createFullSizeIframe();
|
||||||
elem.textContent = '';
|
elem.textContent = "";
|
||||||
elem.appendChild(iframe);
|
elem.appendChild(iframe);
|
||||||
iframe.__inserted_by_pdfjs = true;
|
iframe.__inserted_by_pdfjs = true;
|
||||||
}
|
}
|
||||||
iframe.src = getEmbeddedViewerURL(elem.data);
|
iframe.src = getEmbeddedViewerURL(elem.data);
|
||||||
|
|
||||||
// Some bogus content type that is not handled by any plugin.
|
// Some bogus content type that is not handled by any plugin.
|
||||||
elem.type = 'application/not-a-pee-dee-eff-type';
|
elem.type = "application/not-a-pee-dee-eff-type";
|
||||||
// Force the <object> to reload and render its fallback content.
|
// Force the <object> to reload and render its fallback content.
|
||||||
elem.data += '';
|
elem.data += "";
|
||||||
|
|
||||||
// Usually the browser renders plugin content in this tag, which is completely
|
// Usually the browser renders plugin content in this tag, which is completely
|
||||||
// oblivious of styles such as padding, but we insert and render child nodes,
|
// oblivious of styles such as padding, but we insert and render child nodes,
|
||||||
// so force padding to be zero to avoid undesired dimension changes.
|
// so force padding to be zero to avoid undesired dimension changes.
|
||||||
elem.style.padding = '0';
|
elem.style.padding = "0";
|
||||||
|
|
||||||
// <object> and <embed> elements have a "display:inline" style by default.
|
// <object> and <embed> elements have a "display:inline" style by default.
|
||||||
// Despite this property, when a plugin is loaded in the tag, the tag is
|
// Despite this property, when a plugin is loaded in the tag, the tag is
|
||||||
@ -180,27 +184,27 @@ function updateObjectElement(elem) {
|
|||||||
// web pages is respected.
|
// web pages is respected.
|
||||||
// (<embed> behaves as expected with the default display value, but setting it
|
// (<embed> behaves as expected with the default display value, but setting it
|
||||||
// to display:inline-block doesn't hurt).
|
// to display:inline-block doesn't hurt).
|
||||||
elem.style.display = 'inline-block';
|
elem.style.display = "inline-block";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an <iframe> element without borders that takes the full width and
|
// Create an <iframe> element without borders that takes the full width and
|
||||||
// height.
|
// height.
|
||||||
function createFullSizeIframe() {
|
function createFullSizeIframe() {
|
||||||
var iframe = document.createElement('iframe');
|
var iframe = document.createElement("iframe");
|
||||||
iframe.style.background = 'none';
|
iframe.style.background = "none";
|
||||||
iframe.style.border = 'none';
|
iframe.style.border = "none";
|
||||||
iframe.style.borderRadius = 'none';
|
iframe.style.borderRadius = "none";
|
||||||
iframe.style.boxShadow = 'none';
|
iframe.style.boxShadow = "none";
|
||||||
iframe.style.cssFloat = 'none';
|
iframe.style.cssFloat = "none";
|
||||||
iframe.style.display = 'block';
|
iframe.style.display = "block";
|
||||||
iframe.style.height = '100%';
|
iframe.style.height = "100%";
|
||||||
iframe.style.margin = '0';
|
iframe.style.margin = "0";
|
||||||
iframe.style.maxHeight = 'none';
|
iframe.style.maxHeight = "none";
|
||||||
iframe.style.maxWidth = 'none';
|
iframe.style.maxWidth = "none";
|
||||||
iframe.style.position = 'static';
|
iframe.style.position = "static";
|
||||||
iframe.style.transform = 'none';
|
iframe.style.transform = "none";
|
||||||
iframe.style.visibility = 'visible';
|
iframe.style.visibility = "visible";
|
||||||
iframe.style.width = '100%';
|
iframe.style.width = "100%";
|
||||||
return iframe;
|
return iframe;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,10 +212,10 @@ function createFullSizeIframe() {
|
|||||||
function getEmbeddedViewerURL(path) {
|
function getEmbeddedViewerURL(path) {
|
||||||
var fragment = /^([^#]*)(#.*)?$/.exec(path);
|
var fragment = /^([^#]*)(#.*)?$/.exec(path);
|
||||||
path = fragment[1];
|
path = fragment[1];
|
||||||
fragment = fragment[2] || '';
|
fragment = fragment[2] || "";
|
||||||
|
|
||||||
// Resolve relative path to document.
|
// Resolve relative path to document.
|
||||||
var a = document.createElement('a');
|
var a = document.createElement("a");
|
||||||
a.href = document.baseURI;
|
a.href = document.baseURI;
|
||||||
a.href = path;
|
a.href = path;
|
||||||
path = a.href;
|
path = a.href;
|
||||||
|
@ -14,24 +14,24 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
(function ExtensionRouterClosure() {
|
(function ExtensionRouterClosure() {
|
||||||
var VIEWER_URL = chrome.extension.getURL('content/web/viewer.html');
|
var VIEWER_URL = chrome.extension.getURL("content/web/viewer.html");
|
||||||
var CRX_BASE_URL = chrome.extension.getURL('/');
|
var CRX_BASE_URL = chrome.extension.getURL("/");
|
||||||
|
|
||||||
var schemes = [
|
var schemes = [
|
||||||
'http',
|
"http",
|
||||||
'https',
|
"https",
|
||||||
'ftp',
|
"ftp",
|
||||||
'file',
|
"file",
|
||||||
'chrome-extension',
|
"chrome-extension",
|
||||||
'blob',
|
"blob",
|
||||||
'data',
|
"data",
|
||||||
// Chromium OS
|
// Chromium OS
|
||||||
'filesystem',
|
"filesystem",
|
||||||
// Chromium OS, shorthand for filesystem:<origin>/external/
|
// Chromium OS, shorthand for filesystem:<origin>/external/
|
||||||
'drive'
|
"drive",
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,8 +47,8 @@ limitations under the License.
|
|||||||
}
|
}
|
||||||
var scheme = url.slice(0, schemeIndex).toLowerCase();
|
var scheme = url.slice(0, schemeIndex).toLowerCase();
|
||||||
if (schemes.includes(scheme)) {
|
if (schemes.includes(scheme)) {
|
||||||
url = url.split('#')[0];
|
url = url.split("#")[0];
|
||||||
if (url.charAt(schemeIndex) === ':') {
|
if (url.charAt(schemeIndex) === ":") {
|
||||||
url = encodeURIComponent(url);
|
url = encodeURIComponent(url);
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
@ -60,55 +60,65 @@ limitations under the License.
|
|||||||
// supported, see http://crbug.com/273589
|
// supported, see http://crbug.com/273589
|
||||||
// (or rewrite the query string parser in viewer.js to get it to
|
// (or rewrite the query string parser in viewer.js to get it to
|
||||||
// recognize the non-URL-encoded PDF URL.)
|
// recognize the non-URL-encoded PDF URL.)
|
||||||
chrome.webRequest.onBeforeRequest.addListener(function(details) {
|
chrome.webRequest.onBeforeRequest.addListener(
|
||||||
|
function(details) {
|
||||||
// This listener converts chrome-extension://.../http://...pdf to
|
// This listener converts chrome-extension://.../http://...pdf to
|
||||||
// chrome-extension://.../content/web/viewer.html?file=http%3A%2F%2F...pdf
|
// chrome-extension://.../content/web/viewer.html?file=http%3A%2F%2F...pdf
|
||||||
var url = parseExtensionURL(details.url);
|
var url = parseExtensionURL(details.url);
|
||||||
if (url) {
|
if (url) {
|
||||||
url = VIEWER_URL + '?file=' + url;
|
url = VIEWER_URL + "?file=" + url;
|
||||||
var i = details.url.indexOf('#');
|
var i = details.url.indexOf("#");
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
url += details.url.slice(i);
|
url += details.url.slice(i);
|
||||||
}
|
}
|
||||||
console.log('Redirecting ' + details.url + ' to ' + url);
|
console.log("Redirecting " + details.url + " to " + url);
|
||||||
return { redirectUrl: url, };
|
return { redirectUrl: url };
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}, {
|
},
|
||||||
types: ['main_frame', 'sub_frame'],
|
{
|
||||||
|
types: ["main_frame", "sub_frame"],
|
||||||
urls: schemes.map(function(scheme) {
|
urls: schemes.map(function(scheme) {
|
||||||
// Format: "chrome-extension://[EXTENSIONID]/<scheme>*"
|
// Format: "chrome-extension://[EXTENSIONID]/<scheme>*"
|
||||||
return CRX_BASE_URL + scheme + '*';
|
return CRX_BASE_URL + scheme + "*";
|
||||||
}),
|
}),
|
||||||
}, ['blocking']);
|
},
|
||||||
|
["blocking"]
|
||||||
|
);
|
||||||
|
|
||||||
// When session restore is used, viewer pages may be loaded before the
|
// When session restore is used, viewer pages may be loaded before the
|
||||||
// webRequest event listener is attached (= page not found).
|
// webRequest event listener is attached (= page not found).
|
||||||
// Or the extension could have been crashed (OOM), leaving a sad tab behind.
|
// Or the extension could have been crashed (OOM), leaving a sad tab behind.
|
||||||
// Reload these tabs.
|
// Reload these tabs.
|
||||||
chrome.tabs.query({
|
chrome.tabs.query(
|
||||||
url: CRX_BASE_URL + '*:*',
|
{
|
||||||
}, function(tabsFromLastSession) {
|
url: CRX_BASE_URL + "*:*",
|
||||||
|
},
|
||||||
|
function(tabsFromLastSession) {
|
||||||
for (var i = 0; i < tabsFromLastSession.length; ++i) {
|
for (var i = 0; i < tabsFromLastSession.length; ++i) {
|
||||||
chrome.tabs.reload(tabsFromLastSession[i].id);
|
chrome.tabs.reload(tabsFromLastSession[i].id);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
console.log('Set up extension URL router.');
|
);
|
||||||
|
console.log("Set up extension URL router.");
|
||||||
|
|
||||||
Object.keys(localStorage).forEach(function(key) {
|
Object.keys(localStorage).forEach(function(key) {
|
||||||
// The localStorage item is set upon unload by chromecom.js.
|
// The localStorage item is set upon unload by chromecom.js.
|
||||||
var parsedKey = /^unload-(\d+)-(true|false)-(.+)/.exec(key);
|
var parsedKey = /^unload-(\d+)-(true|false)-(.+)/.exec(key);
|
||||||
if (parsedKey) {
|
if (parsedKey) {
|
||||||
var timeStart = parseInt(parsedKey[1], 10);
|
var timeStart = parseInt(parsedKey[1], 10);
|
||||||
var isHidden = parsedKey[2] === 'true';
|
var isHidden = parsedKey[2] === "true";
|
||||||
var url = parsedKey[3];
|
var url = parsedKey[3];
|
||||||
if (Date.now() - timeStart < 3000) {
|
if (Date.now() - timeStart < 3000) {
|
||||||
// Is it a new item (younger than 3 seconds)? Assume that the extension
|
// Is it a new item (younger than 3 seconds)? Assume that the extension
|
||||||
// just reloaded, so restore the tab (work-around for crbug.com/511670).
|
// just reloaded, so restore the tab (work-around for crbug.com/511670).
|
||||||
chrome.tabs.create({
|
chrome.tabs.create({
|
||||||
url: chrome.runtime.getURL('restoretab.html') +
|
url:
|
||||||
'?' + encodeURIComponent(url) +
|
chrome.runtime.getURL("restoretab.html") +
|
||||||
'#' + encodeURIComponent(localStorage.getItem(key)),
|
"?" +
|
||||||
|
encodeURIComponent(url) +
|
||||||
|
"#" +
|
||||||
|
encodeURIComponent(localStorage.getItem(key)),
|
||||||
active: !isHidden,
|
active: !isHidden,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
|||||||
/* eslint strict: ["error", "function"] */
|
/* eslint strict: ["error", "function"] */
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
"use strict";
|
||||||
var storageLocal = chrome.storage.local;
|
var storageLocal = chrome.storage.local;
|
||||||
var storageSync = chrome.storage.sync;
|
var storageSync = chrome.storage.sync;
|
||||||
|
|
||||||
@ -40,12 +40,12 @@ limitations under the License.
|
|||||||
function getStorageNames(callback) {
|
function getStorageNames(callback) {
|
||||||
var x = new XMLHttpRequest();
|
var x = new XMLHttpRequest();
|
||||||
var schema_location = chrome.runtime.getManifest().storage.managed_schema;
|
var schema_location = chrome.runtime.getManifest().storage.managed_schema;
|
||||||
x.open('get', chrome.runtime.getURL(schema_location));
|
x.open("get", chrome.runtime.getURL(schema_location));
|
||||||
x.onload = function() {
|
x.onload = function() {
|
||||||
var storageKeys = Object.keys(x.response.properties);
|
var storageKeys = Object.keys(x.response.properties);
|
||||||
callback(storageKeys);
|
callback(storageKeys);
|
||||||
};
|
};
|
||||||
x.responseType = 'json';
|
x.responseType = "json";
|
||||||
x.send();
|
x.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +54,10 @@ limitations under the License.
|
|||||||
function migrateToSyncStorage(values) {
|
function migrateToSyncStorage(values) {
|
||||||
storageSync.set(values, function() {
|
storageSync.set(values, function() {
|
||||||
if (chrome.runtime.lastError) {
|
if (chrome.runtime.lastError) {
|
||||||
console.error('Failed to migrate settings due to an error: ' +
|
console.error(
|
||||||
chrome.runtime.lastError.message);
|
"Failed to migrate settings due to an error: " +
|
||||||
|
chrome.runtime.lastError.message
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Migration successful. Delete local settings.
|
// Migration successful. Delete local settings.
|
||||||
@ -64,7 +66,8 @@ limitations under the License.
|
|||||||
// backend is corrupt), but since storageSync.set succeeded, consider
|
// backend is corrupt), but since storageSync.set succeeded, consider
|
||||||
// the migration successful.
|
// the migration successful.
|
||||||
console.log(
|
console.log(
|
||||||
'Successfully migrated preferences from local to sync storage.');
|
"Successfully migrated preferences from local to sync storage."
|
||||||
|
);
|
||||||
migrateRenamedStorage();
|
migrateRenamedStorage();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -75,61 +78,82 @@ limitations under the License.
|
|||||||
// Note: We cannot modify managed preferences, so the migration logic is
|
// Note: We cannot modify managed preferences, so the migration logic is
|
||||||
// duplicated in web/chromecom.js too.
|
// duplicated in web/chromecom.js too.
|
||||||
function migrateRenamedStorage() {
|
function migrateRenamedStorage() {
|
||||||
storageSync.get([
|
storageSync.get(
|
||||||
'enableHandToolOnLoad',
|
[
|
||||||
'cursorToolOnLoad',
|
"enableHandToolOnLoad",
|
||||||
'disableTextLayer',
|
"cursorToolOnLoad",
|
||||||
'enhanceTextSelection',
|
"disableTextLayer",
|
||||||
'textLayerMode',
|
"enhanceTextSelection",
|
||||||
'showPreviousViewOnLoad',
|
"textLayerMode",
|
||||||
'disablePageMode',
|
"showPreviousViewOnLoad",
|
||||||
'viewOnLoad',
|
"disablePageMode",
|
||||||
], function(items) {
|
"viewOnLoad",
|
||||||
|
],
|
||||||
|
function(items) {
|
||||||
// Migration code for https://github.com/mozilla/pdf.js/pull/7635.
|
// Migration code for https://github.com/mozilla/pdf.js/pull/7635.
|
||||||
if (typeof items.enableHandToolOnLoad === 'boolean') {
|
if (typeof items.enableHandToolOnLoad === "boolean") {
|
||||||
if (items.enableHandToolOnLoad) {
|
if (items.enableHandToolOnLoad) {
|
||||||
storageSync.set({
|
storageSync.set(
|
||||||
|
{
|
||||||
cursorToolOnLoad: 1,
|
cursorToolOnLoad: 1,
|
||||||
}, function() {
|
},
|
||||||
|
function() {
|
||||||
if (!chrome.runtime.lastError) {
|
if (!chrome.runtime.lastError) {
|
||||||
storageSync.remove('enableHandToolOnLoad');
|
storageSync.remove("enableHandToolOnLoad");
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
storageSync.remove('enableHandToolOnLoad');
|
storageSync.remove("enableHandToolOnLoad");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Migration code for https://github.com/mozilla/pdf.js/pull/9479.
|
// Migration code for https://github.com/mozilla/pdf.js/pull/9479.
|
||||||
if (typeof items.disableTextLayer === 'boolean') {
|
if (typeof items.disableTextLayer === "boolean") {
|
||||||
var textLayerMode = items.disableTextLayer ? 0 :
|
var textLayerMode = items.disableTextLayer
|
||||||
items.enhanceTextSelection ? 2 : 1;
|
? 0
|
||||||
|
: items.enhanceTextSelection
|
||||||
|
? 2
|
||||||
|
: 1;
|
||||||
if (textLayerMode !== 1) {
|
if (textLayerMode !== 1) {
|
||||||
// Overwrite if computed textLayerMode is not the default value (1).
|
// Overwrite if computed textLayerMode is not the default value (1).
|
||||||
storageSync.set({
|
storageSync.set(
|
||||||
|
{
|
||||||
textLayerMode: textLayerMode,
|
textLayerMode: textLayerMode,
|
||||||
}, function() {
|
},
|
||||||
|
function() {
|
||||||
if (!chrome.runtime.lastError) {
|
if (!chrome.runtime.lastError) {
|
||||||
storageSync.remove(['disableTextLayer', 'enhanceTextSelection']);
|
storageSync.remove([
|
||||||
|
"disableTextLayer",
|
||||||
|
"enhanceTextSelection",
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
storageSync.remove(['disableTextLayer', 'enhanceTextSelection']);
|
storageSync.remove(["disableTextLayer", "enhanceTextSelection"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Migration code for https://github.com/mozilla/pdf.js/pull/10502.
|
// Migration code for https://github.com/mozilla/pdf.js/pull/10502.
|
||||||
if (typeof items.showPreviousViewOnLoad === 'boolean') {
|
if (typeof items.showPreviousViewOnLoad === "boolean") {
|
||||||
if (!items.showPreviousViewOnLoad) {
|
if (!items.showPreviousViewOnLoad) {
|
||||||
storageSync.set({
|
storageSync.set(
|
||||||
|
{
|
||||||
viewOnLoad: 1,
|
viewOnLoad: 1,
|
||||||
}, function() {
|
},
|
||||||
|
function() {
|
||||||
if (!chrome.runtime.lastError) {
|
if (!chrome.runtime.lastError) {
|
||||||
storageSync.remove(['showPreviousViewOnLoad', 'disablePageMode']);
|
storageSync.remove([
|
||||||
|
"showPreviousViewOnLoad",
|
||||||
|
"disablePageMode",
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
storageSync.remove(['showPreviousViewOnLoad', 'disablePageMode']);
|
storageSync.remove(["showPreviousViewOnLoad", "disablePageMode"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
var storageAreaName = chrome.storage.sync ? 'sync' : 'local';
|
var storageAreaName = chrome.storage.sync ? "sync" : "local";
|
||||||
var storageArea = chrome.storage[storageAreaName];
|
var storageArea = chrome.storage[storageAreaName];
|
||||||
|
|
||||||
Promise.all([
|
Promise.all([
|
||||||
@ -39,14 +39,15 @@ Promise.all([
|
|||||||
// Get the storage schema - a dictionary of preferences.
|
// Get the storage schema - a dictionary of preferences.
|
||||||
var x = new XMLHttpRequest();
|
var x = new XMLHttpRequest();
|
||||||
var schema_location = chrome.runtime.getManifest().storage.managed_schema;
|
var schema_location = chrome.runtime.getManifest().storage.managed_schema;
|
||||||
x.open('get', chrome.runtime.getURL(schema_location));
|
x.open("get", chrome.runtime.getURL(schema_location));
|
||||||
x.onload = function() {
|
x.onload = function() {
|
||||||
resolve(x.response.properties);
|
resolve(x.response.properties);
|
||||||
};
|
};
|
||||||
x.responseType = 'json';
|
x.responseType = "json";
|
||||||
x.send();
|
x.send();
|
||||||
})
|
}),
|
||||||
]).then(function(values) {
|
])
|
||||||
|
.then(function(values) {
|
||||||
var managedPrefs = values[0];
|
var managedPrefs = values[0];
|
||||||
var userPrefs = values[1];
|
var userPrefs = values[1];
|
||||||
var schema = values[2];
|
var schema = values[2];
|
||||||
@ -70,24 +71,26 @@ Promise.all([
|
|||||||
|
|
||||||
// A DOM element with a method renderPreference.
|
// A DOM element with a method renderPreference.
|
||||||
var renderPreference;
|
var renderPreference;
|
||||||
if (prefSchema.type === 'boolean') {
|
if (prefSchema.type === "boolean") {
|
||||||
// Most prefs are booleans, render them in a generic way.
|
// Most prefs are booleans, render them in a generic way.
|
||||||
renderPreference = renderBooleanPref(prefSchema.title,
|
renderPreference = renderBooleanPref(
|
||||||
|
prefSchema.title,
|
||||||
prefSchema.description,
|
prefSchema.description,
|
||||||
prefName);
|
prefName
|
||||||
} else if (prefSchema.type === 'integer' && prefSchema.enum) {
|
);
|
||||||
|
} else if (prefSchema.type === "integer" && prefSchema.enum) {
|
||||||
// Most other prefs are integer-valued enumerations, render them in a
|
// Most other prefs are integer-valued enumerations, render them in a
|
||||||
// generic way too.
|
// generic way too.
|
||||||
// Unlike the renderBooleanPref branch, each preference handled by this
|
// Unlike the renderBooleanPref branch, each preference handled by this
|
||||||
// branch still needs its own template in options.html with
|
// branch still needs its own template in options.html with
|
||||||
// id="$prefName-template".
|
// id="$prefName-template".
|
||||||
renderPreference = renderEnumPref(prefSchema.title, prefName);
|
renderPreference = renderEnumPref(prefSchema.title, prefName);
|
||||||
} else if (prefName === 'defaultZoomValue') {
|
} else if (prefName === "defaultZoomValue") {
|
||||||
renderPreference = renderDefaultZoomValue(prefSchema.title);
|
renderPreference = renderDefaultZoomValue(prefSchema.title);
|
||||||
} else {
|
} else {
|
||||||
// Should NEVER be reached. Only happens if a new type of preference is
|
// Should NEVER be reached. Only happens if a new type of preference is
|
||||||
// added to the storage manifest.
|
// added to the storage manifest.
|
||||||
console.error('Don\'t know how to handle ' + prefName + '!');
|
console.error("Don't know how to handle " + prefName + "!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +102,7 @@ Promise.all([
|
|||||||
var renderedPrefNames = Object.keys(renderPreferenceFunctions);
|
var renderedPrefNames = Object.keys(renderPreferenceFunctions);
|
||||||
|
|
||||||
// Reset button to restore default settings.
|
// Reset button to restore default settings.
|
||||||
document.getElementById('reset-button').onclick = function() {
|
document.getElementById("reset-button").onclick = function() {
|
||||||
userPrefs = {};
|
userPrefs = {};
|
||||||
storageArea.remove(prefNames, function() {
|
storageArea.remove(prefNames, function() {
|
||||||
renderedPrefNames.forEach(function(prefName) {
|
renderedPrefNames.forEach(function(prefName) {
|
||||||
@ -110,13 +113,17 @@ Promise.all([
|
|||||||
|
|
||||||
// Automatically update the UI when the preferences were changed elsewhere.
|
// Automatically update the UI when the preferences were changed elsewhere.
|
||||||
chrome.storage.onChanged.addListener(function(changes, areaName) {
|
chrome.storage.onChanged.addListener(function(changes, areaName) {
|
||||||
var prefs = areaName === storageAreaName ? userPrefs :
|
var prefs =
|
||||||
areaName === 'managed' ? managedPrefs : null;
|
areaName === storageAreaName
|
||||||
|
? userPrefs
|
||||||
|
: areaName === "managed"
|
||||||
|
? managedPrefs
|
||||||
|
: null;
|
||||||
if (prefs) {
|
if (prefs) {
|
||||||
renderedPrefNames.forEach(function(prefName) {
|
renderedPrefNames.forEach(function(prefName) {
|
||||||
var prefChanges = changes[prefName];
|
var prefChanges = changes[prefName];
|
||||||
if (prefChanges) {
|
if (prefChanges) {
|
||||||
if ('newValue' in prefChanges) {
|
if ("newValue" in prefChanges) {
|
||||||
userPrefs[prefName] = prefChanges.newValue;
|
userPrefs[prefName] = prefChanges.newValue;
|
||||||
} else {
|
} else {
|
||||||
// Otherwise the pref was deleted
|
// Otherwise the pref was deleted
|
||||||
@ -127,7 +134,8 @@ Promise.all([
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).then(null, console.error.bind(console));
|
})
|
||||||
|
.then(null, console.error.bind(console));
|
||||||
|
|
||||||
function importTemplate(id) {
|
function importTemplate(id) {
|
||||||
return document.importNode(document.getElementById(id).content, true);
|
return document.importNode(document.getElementById(id).content, true);
|
||||||
@ -137,7 +145,7 @@ function importTemplate(id) {
|
|||||||
// function which updates the UI with the preference.
|
// function which updates the UI with the preference.
|
||||||
|
|
||||||
function renderBooleanPref(shortDescription, description, prefName) {
|
function renderBooleanPref(shortDescription, description, prefName) {
|
||||||
var wrapper = importTemplate('checkbox-template');
|
var wrapper = importTemplate("checkbox-template");
|
||||||
wrapper.title = description;
|
wrapper.title = description;
|
||||||
|
|
||||||
var checkbox = wrapper.querySelector('input[type="checkbox"]');
|
var checkbox = wrapper.querySelector('input[type="checkbox"]');
|
||||||
@ -146,8 +154,8 @@ function renderBooleanPref(shortDescription, description, prefName) {
|
|||||||
pref[prefName] = this.checked;
|
pref[prefName] = this.checked;
|
||||||
storageArea.set(pref);
|
storageArea.set(pref);
|
||||||
};
|
};
|
||||||
wrapper.querySelector('span').textContent = shortDescription;
|
wrapper.querySelector("span").textContent = shortDescription;
|
||||||
document.getElementById('settings-boxes').appendChild(wrapper);
|
document.getElementById("settings-boxes").appendChild(wrapper);
|
||||||
|
|
||||||
function renderPreference(value) {
|
function renderPreference(value) {
|
||||||
checkbox.checked = value;
|
checkbox.checked = value;
|
||||||
@ -156,15 +164,15 @@ function renderBooleanPref(shortDescription, description, prefName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderEnumPref(shortDescription, prefName) {
|
function renderEnumPref(shortDescription, prefName) {
|
||||||
var wrapper = importTemplate(prefName + '-template');
|
var wrapper = importTemplate(prefName + "-template");
|
||||||
var select = wrapper.querySelector('select');
|
var select = wrapper.querySelector("select");
|
||||||
select.onchange = function() {
|
select.onchange = function() {
|
||||||
var pref = {};
|
var pref = {};
|
||||||
pref[prefName] = parseInt(this.value);
|
pref[prefName] = parseInt(this.value);
|
||||||
storageArea.set(pref);
|
storageArea.set(pref);
|
||||||
};
|
};
|
||||||
wrapper.querySelector('span').textContent = shortDescription;
|
wrapper.querySelector("span").textContent = shortDescription;
|
||||||
document.getElementById('settings-boxes').appendChild(wrapper);
|
document.getElementById("settings-boxes").appendChild(wrapper);
|
||||||
|
|
||||||
function renderPreference(value) {
|
function renderPreference(value) {
|
||||||
select.value = value;
|
select.value = value;
|
||||||
@ -173,24 +181,24 @@ function renderEnumPref(shortDescription, prefName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function renderDefaultZoomValue(shortDescription) {
|
function renderDefaultZoomValue(shortDescription) {
|
||||||
var wrapper = importTemplate('defaultZoomValue-template');
|
var wrapper = importTemplate("defaultZoomValue-template");
|
||||||
var select = wrapper.querySelector('select');
|
var select = wrapper.querySelector("select");
|
||||||
select.onchange = function() {
|
select.onchange = function() {
|
||||||
storageArea.set({
|
storageArea.set({
|
||||||
defaultZoomValue: this.value,
|
defaultZoomValue: this.value,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
wrapper.querySelector('span').textContent = shortDescription;
|
wrapper.querySelector("span").textContent = shortDescription;
|
||||||
document.getElementById('settings-boxes').appendChild(wrapper);
|
document.getElementById("settings-boxes").appendChild(wrapper);
|
||||||
|
|
||||||
function renderPreference(value) {
|
function renderPreference(value) {
|
||||||
value = value || 'auto';
|
value = value || "auto";
|
||||||
select.value = value;
|
select.value = value;
|
||||||
var customOption = select.querySelector('option.custom-zoom');
|
var customOption = select.querySelector("option.custom-zoom");
|
||||||
if (select.selectedIndex === -1 && value) {
|
if (select.selectedIndex === -1 && value) {
|
||||||
// Custom zoom percentage, e.g. set via managed preferences.
|
// Custom zoom percentage, e.g. set via managed preferences.
|
||||||
// [zoom] or [zoom],[left],[top]
|
// [zoom] or [zoom],[left],[top]
|
||||||
customOption.text = value.indexOf(',') > 0 ? value : value + '%';
|
customOption.text = value.indexOf(",") > 0 ? value : value + "%";
|
||||||
customOption.value = value;
|
customOption.value = value;
|
||||||
customOption.hidden = false;
|
customOption.hidden = false;
|
||||||
customOption.selected = true;
|
customOption.selected = true;
|
||||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
(function PageActionClosure() {
|
(function PageActionClosure() {
|
||||||
/**
|
/**
|
||||||
@ -29,16 +29,16 @@ limitations under the License.
|
|||||||
url = url[1];
|
url = url[1];
|
||||||
chrome.pageAction.setPopup({
|
chrome.pageAction.setPopup({
|
||||||
tabId: tabId,
|
tabId: tabId,
|
||||||
popup: '/pageAction/popup.html?file=' + encodeURIComponent(url),
|
popup: "/pageAction/popup.html?file=" + encodeURIComponent(url),
|
||||||
});
|
});
|
||||||
chrome.pageAction.show(tabId);
|
chrome.pageAction.show(tabId);
|
||||||
} else {
|
} else {
|
||||||
console.log('Unable to get PDF url from ' + displayUrl);
|
console.log("Unable to get PDF url from " + displayUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function(message, sender) {
|
chrome.runtime.onMessage.addListener(function(message, sender) {
|
||||||
if (message === 'showPageAction' && sender.tab) {
|
if (message === "showPageAction" && sender.tab) {
|
||||||
showPageAction(sender.tab.id, sender.tab.url);
|
showPageAction(sender.tab.id, sender.tab.url);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var url = location.search.match(/[&?]file=([^&]+)/i);
|
var url = location.search.match(/[&?]file=([^&]+)/i);
|
||||||
if (url) {
|
if (url) {
|
||||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
|||||||
/* import-globals-from pdfHandler.js */
|
/* import-globals-from pdfHandler.js */
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
if (!chrome.fileBrowserHandler) {
|
if (!chrome.fileBrowserHandler) {
|
||||||
// Not on Chromium OS, bail out
|
// Not on Chromium OS, bail out
|
||||||
@ -33,7 +33,7 @@ limitations under the License.
|
|||||||
* @param {Object} details Object of type FileHandlerExecuteEventDetails
|
* @param {Object} details Object of type FileHandlerExecuteEventDetails
|
||||||
*/
|
*/
|
||||||
function onExecuteFileBrowserHandler(id, details) {
|
function onExecuteFileBrowserHandler(id, details) {
|
||||||
if (id !== 'open-as-pdf') {
|
if (id !== "open-as-pdf") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var fileEntries = details.entries;
|
var fileEntries = details.entries;
|
||||||
@ -49,7 +49,7 @@ limitations under the License.
|
|||||||
chrome.windows.getLastFocused(function(chromeWindow) {
|
chrome.windows.getLastFocused(function(chromeWindow) {
|
||||||
var windowId = chromeWindow && chromeWindow.id;
|
var windowId = chromeWindow && chromeWindow.id;
|
||||||
if (windowId) {
|
if (windowId) {
|
||||||
chrome.windows.update(windowId, { focused: true, });
|
chrome.windows.update(windowId, { focused: true });
|
||||||
}
|
}
|
||||||
openViewer(windowId, fileEntries);
|
openViewer(windowId, fileEntries);
|
||||||
});
|
});
|
||||||
@ -69,26 +69,34 @@ limitations under the License.
|
|||||||
var fileEntry = fileEntries.shift();
|
var fileEntry = fileEntries.shift();
|
||||||
var url = fileEntry.toURL();
|
var url = fileEntry.toURL();
|
||||||
// Use drive: alias to get shorter (more human-readable) URLs.
|
// Use drive: alias to get shorter (more human-readable) URLs.
|
||||||
url = url.replace(/^filesystem:chrome-extension:\/\/[a-p]{32}\/external\//,
|
url = url.replace(
|
||||||
'drive:');
|
/^filesystem:chrome-extension:\/\/[a-p]{32}\/external\//,
|
||||||
|
"drive:"
|
||||||
|
);
|
||||||
url = getViewerURL(url);
|
url = getViewerURL(url);
|
||||||
|
|
||||||
if (windowId) {
|
if (windowId) {
|
||||||
chrome.tabs.create({
|
chrome.tabs.create(
|
||||||
|
{
|
||||||
windowId: windowId,
|
windowId: windowId,
|
||||||
active: true,
|
active: true,
|
||||||
url: url,
|
url: url,
|
||||||
}, function() {
|
},
|
||||||
|
function() {
|
||||||
openViewer(windowId, fileEntries);
|
openViewer(windowId, fileEntries);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
chrome.windows.create({
|
chrome.windows.create(
|
||||||
type: 'normal',
|
{
|
||||||
|
type: "normal",
|
||||||
focused: true,
|
focused: true,
|
||||||
url: url,
|
url: url,
|
||||||
}, function(chromeWindow) {
|
},
|
||||||
|
function(chromeWindow) {
|
||||||
openViewer(chromeWindow.id, fileEntries);
|
openViewer(chromeWindow.id, fileEntries);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -15,12 +15,12 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
/* import-globals-from preserve-referer.js */
|
/* import-globals-from preserve-referer.js */
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var VIEWER_URL = chrome.extension.getURL('content/web/viewer.html');
|
var VIEWER_URL = chrome.extension.getURL("content/web/viewer.html");
|
||||||
|
|
||||||
function getViewerURL(pdf_url) {
|
function getViewerURL(pdf_url) {
|
||||||
return VIEWER_URL + '?file=' + encodeURIComponent(pdf_url);
|
return VIEWER_URL + "?file=" + encodeURIComponent(pdf_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,7 +29,7 @@ function getViewerURL(pdf_url) {
|
|||||||
* @returns {boolean} True if the PDF file should be downloaded.
|
* @returns {boolean} True if the PDF file should be downloaded.
|
||||||
*/
|
*/
|
||||||
function isPdfDownloadable(details) {
|
function isPdfDownloadable(details) {
|
||||||
if (details.url.includes('pdfjs.action=download')) {
|
if (details.url.includes("pdfjs.action=download")) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Display the PDF viewer regardless of the Content-Disposition header if the
|
// Display the PDF viewer regardless of the Content-Disposition header if the
|
||||||
@ -39,12 +39,13 @@ function isPdfDownloadable(details) {
|
|||||||
// viewer to open the PDF, but first check whether the Content-Disposition
|
// viewer to open the PDF, but first check whether the Content-Disposition
|
||||||
// header specifies an attachment. This allows sites like Google Drive to
|
// header specifies an attachment. This allows sites like Google Drive to
|
||||||
// operate correctly (#6106).
|
// operate correctly (#6106).
|
||||||
if (details.type === 'main_frame' && !details.url.includes('=download')) {
|
if (details.type === "main_frame" && !details.url.includes("=download")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var cdHeader = (details.responseHeaders &&
|
var cdHeader =
|
||||||
getHeaderFromHeaders(details.responseHeaders, 'content-disposition'));
|
details.responseHeaders &&
|
||||||
return (cdHeader && /^attachment/i.test(cdHeader.value));
|
getHeaderFromHeaders(details.responseHeaders, "content-disposition");
|
||||||
|
return cdHeader && /^attachment/i.test(cdHeader.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -70,18 +71,23 @@ function getHeaderFromHeaders(headers, headerName) {
|
|||||||
* @returns {boolean} True if the resource is a PDF file.
|
* @returns {boolean} True if the resource is a PDF file.
|
||||||
*/
|
*/
|
||||||
function isPdfFile(details) {
|
function isPdfFile(details) {
|
||||||
var header = getHeaderFromHeaders(details.responseHeaders, 'content-type');
|
var header = getHeaderFromHeaders(details.responseHeaders, "content-type");
|
||||||
if (header) {
|
if (header) {
|
||||||
var headerValue = header.value.toLowerCase().split(';', 1)[0].trim();
|
var headerValue = header.value
|
||||||
if (headerValue === 'application/pdf') {
|
.toLowerCase()
|
||||||
|
.split(";", 1)[0]
|
||||||
|
.trim();
|
||||||
|
if (headerValue === "application/pdf") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (headerValue === 'application/octet-stream') {
|
if (headerValue === "application/octet-stream") {
|
||||||
if (details.url.toLowerCase().indexOf('.pdf') > 0) {
|
if (details.url.toLowerCase().indexOf(".pdf") > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var cdHeader =
|
var cdHeader = getHeaderFromHeaders(
|
||||||
getHeaderFromHeaders(details.responseHeaders, 'content-disposition');
|
details.responseHeaders,
|
||||||
|
"content-disposition"
|
||||||
|
);
|
||||||
if (cdHeader && /\.pdf(["']|$)/i.test(cdHeader.value)) {
|
if (cdHeader && /\.pdf(["']|$)/i.test(cdHeader.value)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -101,21 +107,21 @@ function isPdfFile(details) {
|
|||||||
*/
|
*/
|
||||||
function getHeadersWithContentDispositionAttachment(details) {
|
function getHeadersWithContentDispositionAttachment(details) {
|
||||||
var headers = details.responseHeaders;
|
var headers = details.responseHeaders;
|
||||||
var cdHeader = getHeaderFromHeaders(headers, 'content-disposition');
|
var cdHeader = getHeaderFromHeaders(headers, "content-disposition");
|
||||||
if (!cdHeader) {
|
if (!cdHeader) {
|
||||||
cdHeader = { name: 'Content-Disposition', };
|
cdHeader = { name: "Content-Disposition" };
|
||||||
headers.push(cdHeader);
|
headers.push(cdHeader);
|
||||||
}
|
}
|
||||||
if (!/^attachment/i.test(cdHeader.value)) {
|
if (!/^attachment/i.test(cdHeader.value)) {
|
||||||
cdHeader.value = 'attachment' + cdHeader.value.replace(/^[^;]+/i, '');
|
cdHeader.value = "attachment" + cdHeader.value.replace(/^[^;]+/i, "");
|
||||||
return { responseHeaders: headers, };
|
return { responseHeaders: headers };
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.webRequest.onHeadersReceived.addListener(
|
chrome.webRequest.onHeadersReceived.addListener(
|
||||||
function(details) {
|
function(details) {
|
||||||
if (details.method !== 'GET') {
|
if (details.method !== "GET") {
|
||||||
// Don't intercept POST requests until http://crbug.com/104058 is fixed.
|
// Don't intercept POST requests until http://crbug.com/104058 is fixed.
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -132,15 +138,14 @@ chrome.webRequest.onHeadersReceived.addListener(
|
|||||||
// Implemented in preserve-referer.js
|
// Implemented in preserve-referer.js
|
||||||
saveReferer(details);
|
saveReferer(details);
|
||||||
|
|
||||||
return { redirectUrl: viewerUrl, };
|
return { redirectUrl: viewerUrl };
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
urls: [
|
urls: ["<all_urls>"],
|
||||||
'<all_urls>'
|
types: ["main_frame", "sub_frame"],
|
||||||
],
|
|
||||||
types: ['main_frame', 'sub_frame'],
|
|
||||||
},
|
},
|
||||||
['blocking', 'responseHeaders']);
|
["blocking", "responseHeaders"]
|
||||||
|
);
|
||||||
|
|
||||||
chrome.webRequest.onBeforeRequest.addListener(
|
chrome.webRequest.onBeforeRequest.addListener(
|
||||||
function(details) {
|
function(details) {
|
||||||
@ -150,26 +155,26 @@ chrome.webRequest.onBeforeRequest.addListener(
|
|||||||
|
|
||||||
var viewerUrl = getViewerURL(details.url);
|
var viewerUrl = getViewerURL(details.url);
|
||||||
|
|
||||||
return { redirectUrl: viewerUrl, };
|
return { redirectUrl: viewerUrl };
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
urls: [
|
urls: [
|
||||||
'file://*/*.pdf',
|
"file://*/*.pdf",
|
||||||
'file://*/*.PDF',
|
"file://*/*.PDF",
|
||||||
...(
|
...// Duck-typing: MediaError.prototype.message was added in Chrome 59.
|
||||||
// Duck-typing: MediaError.prototype.message was added in Chrome 59.
|
(MediaError.prototype.hasOwnProperty("message")
|
||||||
MediaError.prototype.hasOwnProperty('message') ? [] :
|
? []
|
||||||
[
|
: [
|
||||||
// Note: Chrome 59 has disabled ftp resource loading by default:
|
// Note: Chrome 59 has disabled ftp resource loading by default:
|
||||||
// https://www.chromestatus.com/feature/5709390967472128
|
// https://www.chromestatus.com/feature/5709390967472128
|
||||||
'ftp://*/*.pdf',
|
"ftp://*/*.pdf",
|
||||||
'ftp://*/*.PDF',
|
"ftp://*/*.PDF",
|
||||||
]
|
]),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
types: ['main_frame', 'sub_frame'],
|
types: ["main_frame", "sub_frame"],
|
||||||
},
|
},
|
||||||
['blocking']);
|
["blocking"]
|
||||||
|
);
|
||||||
|
|
||||||
chrome.extension.isAllowedFileSchemeAccess(function(isAllowedAccess) {
|
chrome.extension.isAllowedFileSchemeAccess(function(isAllowedAccess) {
|
||||||
if (isAllowedAccess) {
|
if (isAllowedAccess) {
|
||||||
@ -180,29 +185,35 @@ chrome.extension.isAllowedFileSchemeAccess(function(isAllowedAccess) {
|
|||||||
// API though, and we can replace the tab with the viewer.
|
// API though, and we can replace the tab with the viewer.
|
||||||
// The viewer will detect that it has no access to file:-URLs, and prompt the
|
// The viewer will detect that it has no access to file:-URLs, and prompt the
|
||||||
// user to activate file permissions.
|
// user to activate file permissions.
|
||||||
chrome.webNavigation.onBeforeNavigate.addListener(function(details) {
|
chrome.webNavigation.onBeforeNavigate.addListener(
|
||||||
|
function(details) {
|
||||||
if (details.frameId === 0 && !isPdfDownloadable(details)) {
|
if (details.frameId === 0 && !isPdfDownloadable(details)) {
|
||||||
chrome.tabs.update(details.tabId, {
|
chrome.tabs.update(details.tabId, {
|
||||||
url: getViewerURL(details.url),
|
url: getViewerURL(details.url),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
url: [{
|
{
|
||||||
urlPrefix: 'file://',
|
url: [
|
||||||
pathSuffix: '.pdf',
|
{
|
||||||
}, {
|
urlPrefix: "file://",
|
||||||
urlPrefix: 'file://',
|
pathSuffix: ".pdf",
|
||||||
pathSuffix: '.PDF',
|
},
|
||||||
}],
|
{
|
||||||
});
|
urlPrefix: "file://",
|
||||||
|
pathSuffix: ".PDF",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
|
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
|
||||||
if (message && message.action === 'getParentOrigin') {
|
if (message && message.action === "getParentOrigin") {
|
||||||
// getParentOrigin is used to determine whether it is safe to embed a
|
// getParentOrigin is used to determine whether it is safe to embed a
|
||||||
// sensitive (local) file in a frame.
|
// sensitive (local) file in a frame.
|
||||||
if (!sender.tab) {
|
if (!sender.tab) {
|
||||||
sendResponse('');
|
sendResponse("");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
// TODO: This should be the URL of the parent frame, not the tab. But
|
// TODO: This should be the URL of the parent frame, not the tab. But
|
||||||
@ -211,11 +222,11 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
|
|||||||
// for making security decisions.
|
// for making security decisions.
|
||||||
var parentUrl = sender.tab.url;
|
var parentUrl = sender.tab.url;
|
||||||
if (!parentUrl) {
|
if (!parentUrl) {
|
||||||
sendResponse('');
|
sendResponse("");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (parentUrl.lastIndexOf('file:', 0) === 0) {
|
if (parentUrl.lastIndexOf("file:", 0) === 0) {
|
||||||
sendResponse('file://');
|
sendResponse("file://");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
// The regexp should always match for valid URLs, but in case it doesn't,
|
// The regexp should always match for valid URLs, but in case it doesn't,
|
||||||
@ -224,12 +235,12 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
|
|||||||
sendResponse(origin ? origin[1] : parentUrl);
|
sendResponse(origin ? origin[1] : parentUrl);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (message && message.action === 'isAllowedFileSchemeAccess') {
|
if (message && message.action === "isAllowedFileSchemeAccess") {
|
||||||
chrome.extension.isAllowedFileSchemeAccess(sendResponse);
|
chrome.extension.isAllowedFileSchemeAccess(sendResponse);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (message && message.action === 'openExtensionsPageForFileAccess') {
|
if (message && message.action === "openExtensionsPageForFileAccess") {
|
||||||
var url = 'chrome://extensions/?id=' + chrome.runtime.id;
|
var url = "chrome://extensions/?id=" + chrome.runtime.id;
|
||||||
if (message.data.newTab) {
|
if (message.data.newTab) {
|
||||||
chrome.tabs.create({
|
chrome.tabs.create({
|
||||||
windowId: sender.tab.windowId,
|
windowId: sender.tab.windowId,
|
||||||
@ -248,7 +259,7 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
|
|||||||
|
|
||||||
// Remove keys from storage that were once part of the deleted feature-detect.js
|
// Remove keys from storage that were once part of the deleted feature-detect.js
|
||||||
chrome.storage.local.remove([
|
chrome.storage.local.remove([
|
||||||
'featureDetectLastUA',
|
"featureDetectLastUA",
|
||||||
'webRequestRedirectUrl',
|
"webRequestRedirectUrl",
|
||||||
'extensionSupportsFTP',
|
"extensionSupportsFTP",
|
||||||
]);
|
]);
|
||||||
|
@ -15,7 +15,7 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
/* import-globals-from pdfHandler.js */
|
/* import-globals-from pdfHandler.js */
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
/**
|
/**
|
||||||
* This file is one part of the Referer persistency implementation. The other
|
* This file is one part of the Referer persistency implementation. The other
|
||||||
* part resides in chromecom.js.
|
* part resides in chromecom.js.
|
||||||
@ -45,21 +45,25 @@ var extraInfoSpecWithHeaders; // = ['requestHeaders', 'extraHeaders']
|
|||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
var requestFilter = {
|
var requestFilter = {
|
||||||
urls: ['*://*/*'],
|
urls: ["*://*/*"],
|
||||||
types: ['main_frame', 'sub_frame'],
|
types: ["main_frame", "sub_frame"],
|
||||||
};
|
};
|
||||||
function registerListener(extraInfoSpec) {
|
function registerListener(extraInfoSpec) {
|
||||||
extraInfoSpecWithHeaders = extraInfoSpec;
|
extraInfoSpecWithHeaders = extraInfoSpec;
|
||||||
// May throw if the given extraInfoSpec is unsupported.
|
// May throw if the given extraInfoSpec is unsupported.
|
||||||
chrome.webRequest.onSendHeaders.addListener(function(details) {
|
chrome.webRequest.onSendHeaders.addListener(
|
||||||
|
function(details) {
|
||||||
g_requestHeaders[details.requestId] = details.requestHeaders;
|
g_requestHeaders[details.requestId] = details.requestHeaders;
|
||||||
}, requestFilter, extraInfoSpec);
|
},
|
||||||
|
requestFilter,
|
||||||
|
extraInfoSpec
|
||||||
|
);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
registerListener(['requestHeaders', 'extraHeaders']);
|
registerListener(["requestHeaders", "extraHeaders"]);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// "extraHeaders" is not supported in Chrome 71 and earlier.
|
// "extraHeaders" is not supported in Chrome 71 and earlier.
|
||||||
registerListener(['requestHeaders']);
|
registerListener(["requestHeaders"]);
|
||||||
}
|
}
|
||||||
chrome.webRequest.onBeforeRedirect.addListener(forgetHeaders, requestFilter);
|
chrome.webRequest.onBeforeRedirect.addListener(forgetHeaders, requestFilter);
|
||||||
chrome.webRequest.onCompleted.addListener(forgetHeaders, requestFilter);
|
chrome.webRequest.onCompleted.addListener(forgetHeaders, requestFilter);
|
||||||
@ -73,9 +77,10 @@ var extraInfoSpecWithHeaders; // = ['requestHeaders', 'extraHeaders']
|
|||||||
* @param {object} details - onHeadersReceived event data.
|
* @param {object} details - onHeadersReceived event data.
|
||||||
*/
|
*/
|
||||||
function saveReferer(details) {
|
function saveReferer(details) {
|
||||||
var referer = g_requestHeaders[details.requestId] &&
|
var referer =
|
||||||
getHeaderFromHeaders(g_requestHeaders[details.requestId], 'referer');
|
g_requestHeaders[details.requestId] &&
|
||||||
referer = referer && referer.value || '';
|
getHeaderFromHeaders(g_requestHeaders[details.requestId], "referer");
|
||||||
|
referer = (referer && referer.value) || "";
|
||||||
if (!g_referrers[details.tabId]) {
|
if (!g_referrers[details.tabId]) {
|
||||||
g_referrers[details.tabId] = {};
|
g_referrers[details.tabId] = {};
|
||||||
}
|
}
|
||||||
@ -90,11 +95,11 @@ chrome.tabs.onRemoved.addListener(function(tabId) {
|
|||||||
// to matching PDF resource requests (only if the Referer is non-empty). The
|
// to matching PDF resource requests (only if the Referer is non-empty). The
|
||||||
// handler is removed as soon as the PDF viewer frame is unloaded.
|
// handler is removed as soon as the PDF viewer frame is unloaded.
|
||||||
chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
||||||
if (port.name !== 'chromecom-referrer') {
|
if (port.name !== "chromecom-referrer") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Note: sender.frameId is only set in Chrome 41+.
|
// Note: sender.frameId is only set in Chrome 41+.
|
||||||
if (!('frameId' in port.sender)) {
|
if (!("frameId" in port.sender)) {
|
||||||
port.disconnect();
|
port.disconnect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -102,7 +107,7 @@ chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
|||||||
var frameId = port.sender.frameId;
|
var frameId = port.sender.frameId;
|
||||||
|
|
||||||
// If the PDF is viewed for the first time, then the referer will be set here.
|
// If the PDF is viewed for the first time, then the referer will be set here.
|
||||||
var referer = g_referrers[tabId] && g_referrers[tabId][frameId] || '';
|
var referer = (g_referrers[tabId] && g_referrers[tabId][frameId]) || "";
|
||||||
port.onMessage.addListener(function(data) {
|
port.onMessage.addListener(function(data) {
|
||||||
// If the viewer was opened directly (without opening a PDF URL first), then
|
// If the viewer was opened directly (without opening a PDF URL first), then
|
||||||
// the background script does not know about g_referrers, but the viewer may
|
// the background script does not know about g_referrers, but the viewer may
|
||||||
@ -113,11 +118,15 @@ chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
|||||||
chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
|
chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
|
||||||
if (referer) {
|
if (referer) {
|
||||||
// Only add a blocking request handler if the referer has to be rewritten.
|
// Only add a blocking request handler if the referer has to be rewritten.
|
||||||
chrome.webRequest.onBeforeSendHeaders.addListener(onBeforeSendHeaders, {
|
chrome.webRequest.onBeforeSendHeaders.addListener(
|
||||||
|
onBeforeSendHeaders,
|
||||||
|
{
|
||||||
urls: [data.requestUrl],
|
urls: [data.requestUrl],
|
||||||
types: ['xmlhttprequest'],
|
types: ["xmlhttprequest"],
|
||||||
tabId: tabId,
|
tabId: tabId,
|
||||||
}, ['blocking', ...extraInfoSpecWithHeaders]);
|
},
|
||||||
|
["blocking", ...extraInfoSpecWithHeaders]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// Acknowledge the message, and include the latest referer for this frame.
|
// Acknowledge the message, and include the latest referer for this frame.
|
||||||
port.postMessage(referer);
|
port.postMessage(referer);
|
||||||
@ -134,29 +143,35 @@ chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
|||||||
|
|
||||||
// Expose some response headers for fetch API calls from PDF.js;
|
// Expose some response headers for fetch API calls from PDF.js;
|
||||||
// This is a work-around for https://crbug.com/784528
|
// This is a work-around for https://crbug.com/784528
|
||||||
chrome.webRequest.onHeadersReceived.addListener(exposeOnHeadersReceived, {
|
chrome.webRequest.onHeadersReceived.addListener(
|
||||||
urls: ['https://*/*'],
|
exposeOnHeadersReceived,
|
||||||
types: ['xmlhttprequest'],
|
{
|
||||||
|
urls: ["https://*/*"],
|
||||||
|
types: ["xmlhttprequest"],
|
||||||
tabId: tabId,
|
tabId: tabId,
|
||||||
}, ['blocking', 'responseHeaders']);
|
},
|
||||||
|
["blocking", "responseHeaders"]
|
||||||
|
);
|
||||||
|
|
||||||
function onBeforeSendHeaders(details) {
|
function onBeforeSendHeaders(details) {
|
||||||
if (details.frameId !== frameId) {
|
if (details.frameId !== frameId) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
var headers = details.requestHeaders;
|
var headers = details.requestHeaders;
|
||||||
var refererHeader = getHeaderFromHeaders(headers, 'referer');
|
var refererHeader = getHeaderFromHeaders(headers, "referer");
|
||||||
if (!refererHeader) {
|
if (!refererHeader) {
|
||||||
refererHeader = { name: 'Referer', };
|
refererHeader = { name: "Referer" };
|
||||||
headers.push(refererHeader);
|
headers.push(refererHeader);
|
||||||
} else if (refererHeader.value &&
|
} else if (
|
||||||
refererHeader.value.lastIndexOf('chrome-extension:', 0) !== 0) {
|
refererHeader.value &&
|
||||||
|
refererHeader.value.lastIndexOf("chrome-extension:", 0) !== 0
|
||||||
|
) {
|
||||||
// Sanity check. If the referer is set, and the value is not the URL of
|
// Sanity check. If the referer is set, and the value is not the URL of
|
||||||
// this extension, then the request was not initiated by this extension.
|
// this extension, then the request was not initiated by this extension.
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
refererHeader.value = referer;
|
refererHeader.value = referer;
|
||||||
return { requestHeaders: headers, };
|
return { requestHeaders: headers };
|
||||||
}
|
}
|
||||||
|
|
||||||
function exposeOnHeadersReceived(details) {
|
function exposeOnHeadersReceived(details) {
|
||||||
@ -164,16 +179,16 @@ chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
var headers = details.responseHeaders;
|
var headers = details.responseHeaders;
|
||||||
var aceh = getHeaderFromHeaders(headers, 'access-control-expose-headers');
|
var aceh = getHeaderFromHeaders(headers, "access-control-expose-headers");
|
||||||
// List of headers that PDF.js uses in src/display/network_utils.js
|
// List of headers that PDF.js uses in src/display/network_utils.js
|
||||||
var acehValue =
|
var acehValue =
|
||||||
'accept-ranges,content-encoding,content-length,content-disposition';
|
"accept-ranges,content-encoding,content-length,content-disposition";
|
||||||
if (aceh) {
|
if (aceh) {
|
||||||
aceh.value += ',' + acehValue;
|
aceh.value += "," + acehValue;
|
||||||
} else {
|
} else {
|
||||||
aceh = { name: 'Access-Control-Expose-Headers', value: acehValue, };
|
aceh = { name: "Access-Control-Expose-Headers", value: acehValue };
|
||||||
headers.push(aceh);
|
headers.push(aceh);
|
||||||
}
|
}
|
||||||
return { responseHeaders: headers, };
|
return { responseHeaders: headers };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -20,12 +20,12 @@ limitations under the License.
|
|||||||
* - extension-router.js retrieves the saved state and opens restoretab.html
|
* - extension-router.js retrieves the saved state and opens restoretab.html
|
||||||
* - restoretab.html (this script) restores the URL and history state.
|
* - restoretab.html (this script) restores the URL and history state.
|
||||||
*/
|
*/
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var url = decodeURIComponent(location.search.slice(1));
|
var url = decodeURIComponent(location.search.slice(1));
|
||||||
var historyState = decodeURIComponent(location.hash.slice(1));
|
var historyState = decodeURIComponent(location.hash.slice(1));
|
||||||
|
|
||||||
historyState = historyState === 'undefined' ? null : JSON.parse(historyState);
|
historyState = historyState === "undefined" ? null : JSON.parse(historyState);
|
||||||
|
|
||||||
history.replaceState(historyState, null, url);
|
history.replaceState(historyState, null, url);
|
||||||
location.reload();
|
location.reload();
|
||||||
|
@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
// Do not reload the extension when an update becomes available, UNLESS the PDF
|
// Do not reload the extension when an update becomes available, UNLESS the PDF
|
||||||
// viewer is not displaying any PDF files. Otherwise the tabs would close, which
|
// viewer is not displaying any PDF files. Otherwise the tabs would close, which
|
||||||
// is quite disruptive (crbug.com/511670).
|
// is quite disruptive (crbug.com/511670).
|
||||||
chrome.runtime.onUpdateAvailable.addListener(function() {
|
chrome.runtime.onUpdateAvailable.addListener(function() {
|
||||||
if (chrome.extension.getViews({ type: 'tab', }).length === 0) {
|
if (chrome.extension.getViews({ type: "tab" }).length === 0) {
|
||||||
chrome.runtime.reload();
|
chrome.runtime.reload();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -16,19 +16,19 @@ limitations under the License.
|
|||||||
/* eslint strict: ["error", "function"] */
|
/* eslint strict: ["error", "function"] */
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
"use strict";
|
||||||
// This module sends the browser and extension version to a server, to
|
// This module sends the browser and extension version to a server, to
|
||||||
// determine whether it is safe to drop support for old Chrome versions in
|
// determine whether it is safe to drop support for old Chrome versions in
|
||||||
// future extension updates.
|
// future extension updates.
|
||||||
//
|
//
|
||||||
// The source code for the server is available at:
|
// The source code for the server is available at:
|
||||||
// https://github.com/Rob--W/pdfjs-telemetry
|
// https://github.com/Rob--W/pdfjs-telemetry
|
||||||
var LOG_URL = 'https://pdfjs.robwu.nl/logpdfjs';
|
var LOG_URL = "https://pdfjs.robwu.nl/logpdfjs";
|
||||||
|
|
||||||
// The minimum time to wait before sending a ping, so that we don't send too
|
// The minimum time to wait before sending a ping, so that we don't send too
|
||||||
// many requests even if the user restarts their browser very often.
|
// many requests even if the user restarts their browser very often.
|
||||||
// We want one ping a day, so a minimum delay of 12 hours should be OK.
|
// We want one ping a day, so a minimum delay of 12 hours should be OK.
|
||||||
var MINIMUM_TIME_BETWEEN_PING = 12 * 36E5;
|
var MINIMUM_TIME_BETWEEN_PING = 12 * 36e5;
|
||||||
|
|
||||||
if (chrome.extension.inIncognitoContext) {
|
if (chrome.extension.inIncognitoContext) {
|
||||||
// The extension uses incognito split mode, so there are two background
|
// The extension uses incognito split mode, so there are two background
|
||||||
@ -36,14 +36,14 @@ limitations under the License.
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chrome.runtime.id !== 'oemmndcbldboiebfnladdacbdfmadadm') {
|
if (chrome.runtime.id !== "oemmndcbldboiebfnladdacbdfmadadm") {
|
||||||
// Only send telemetry for the official PDF.js extension.
|
// Only send telemetry for the official PDF.js extension.
|
||||||
console.warn('Disabled telemetry because this is not an official build.');
|
console.warn("Disabled telemetry because this is not an official build.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybeSendPing();
|
maybeSendPing();
|
||||||
setInterval(maybeSendPing, 36E5);
|
setInterval(maybeSendPing, 36e5);
|
||||||
|
|
||||||
function maybeSendPing() {
|
function maybeSendPing() {
|
||||||
getLoggingPref(function(didOptOut) {
|
getLoggingPref(function(didOptOut) {
|
||||||
@ -70,28 +70,28 @@ limitations under the License.
|
|||||||
|
|
||||||
var deduplication_id = getDeduplicationId(wasUpdated);
|
var deduplication_id = getDeduplicationId(wasUpdated);
|
||||||
var extension_version = chrome.runtime.getManifest().version;
|
var extension_version = chrome.runtime.getManifest().version;
|
||||||
if (window.Request && 'mode' in Request.prototype) {
|
if (window.Request && "mode" in Request.prototype) {
|
||||||
// fetch is supported in extensions since Chrome 42 (though the above
|
// fetch is supported in extensions since Chrome 42 (though the above
|
||||||
// feature-detection method detects Chrome 43+).
|
// feature-detection method detects Chrome 43+).
|
||||||
// Unlike XMLHttpRequest, fetch omits credentials such as cookies in the
|
// Unlike XMLHttpRequest, fetch omits credentials such as cookies in the
|
||||||
// requests, which guarantees that the server cannot track the client
|
// requests, which guarantees that the server cannot track the client
|
||||||
// via HTTP cookies.
|
// via HTTP cookies.
|
||||||
fetch(LOG_URL, {
|
fetch(LOG_URL, {
|
||||||
method: 'POST',
|
method: "POST",
|
||||||
headers: new Headers({
|
headers: new Headers({
|
||||||
'Deduplication-Id': deduplication_id,
|
"Deduplication-Id": deduplication_id,
|
||||||
'Extension-Version': extension_version,
|
"Extension-Version": extension_version,
|
||||||
}),
|
}),
|
||||||
// Set mode=cors so that the above custom headers are included in the
|
// Set mode=cors so that the above custom headers are included in the
|
||||||
// request.
|
// request.
|
||||||
mode: 'cors',
|
mode: "cors",
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var x = new XMLHttpRequest();
|
var x = new XMLHttpRequest();
|
||||||
x.open('POST', LOG_URL);
|
x.open("POST", LOG_URL);
|
||||||
x.setRequestHeader('Deduplication-Id', deduplication_id);
|
x.setRequestHeader("Deduplication-Id", deduplication_id);
|
||||||
x.setRequestHeader('Extension-Version', extension_version);
|
x.setRequestHeader("Extension-Version", extension_version);
|
||||||
x.send();
|
x.send();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -107,12 +107,12 @@ limitations under the License.
|
|||||||
// so it is OK to change the ID if the browser is updated. By changing the
|
// so it is OK to change the ID if the browser is updated. By changing the
|
||||||
// ID, the server cannot track users for a long period even if it wants to.
|
// ID, the server cannot track users for a long period even if it wants to.
|
||||||
if (!id || !/^[0-9a-f]{10}$/.test(id) || wasUpdated) {
|
if (!id || !/^[0-9a-f]{10}$/.test(id) || wasUpdated) {
|
||||||
id = '';
|
id = "";
|
||||||
var buf = new Uint8Array(5);
|
var buf = new Uint8Array(5);
|
||||||
crypto.getRandomValues(buf);
|
crypto.getRandomValues(buf);
|
||||||
for (var i = 0; i < buf.length; ++i) {
|
for (var i = 0; i < buf.length; ++i) {
|
||||||
var c = buf[i];
|
var c = buf[i];
|
||||||
id += (c >>> 4).toString(16) + (c & 0xF).toString(16);
|
id += (c >>> 4).toString(16) + (c & 0xf).toString(16);
|
||||||
}
|
}
|
||||||
localStorage.telemetryDeduplicationId = id;
|
localStorage.telemetryDeduplicationId = id;
|
||||||
}
|
}
|
||||||
@ -139,12 +139,12 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
function getLoggingPref(callback) {
|
function getLoggingPref(callback) {
|
||||||
// Try to look up the preference in the storage, in the following order:
|
// Try to look up the preference in the storage, in the following order:
|
||||||
var areas = ['sync', 'local', 'managed'];
|
var areas = ["sync", "local", "managed"];
|
||||||
|
|
||||||
next();
|
next();
|
||||||
function next(result) {
|
function next(result) {
|
||||||
var storageAreaName = areas.shift();
|
var storageAreaName = areas.shift();
|
||||||
if (typeof result === 'boolean' || !storageAreaName) {
|
if (typeof result === "boolean" || !storageAreaName) {
|
||||||
callback(result);
|
callback(result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -154,7 +154,7 @@ limitations under the License.
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
chrome.storage[storageAreaName].get('disableTelemetry', function(items) {
|
chrome.storage[storageAreaName].get("disableTelemetry", function(items) {
|
||||||
next(items && items.disableTelemetry);
|
next(items && items.disableTelemetry);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,6 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
// translate an element or document fragment
|
// translate an element or document fragment
|
||||||
translate: translateFragment
|
translate: translateFragment,
|
||||||
};
|
};
|
||||||
})(this);
|
})(this);
|
||||||
|
149
external/builder/builder.js
vendored
149
external/builder/builder.js
vendored
@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var fs = require('fs'),
|
var fs = require("fs"),
|
||||||
path = require('path'),
|
path = require("path"),
|
||||||
vm = require('vm');
|
vm = require("vm");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple preprocessor that is based on the Firefox preprocessor
|
* A simple preprocessor that is based on the Firefox preprocessor
|
||||||
@ -34,9 +34,12 @@ var fs = require('fs'),
|
|||||||
*/
|
*/
|
||||||
function preprocess(inFilename, outFilename, defines) {
|
function preprocess(inFilename, outFilename, defines) {
|
||||||
// TODO make this really read line by line.
|
// TODO make this really read line by line.
|
||||||
var lines = fs.readFileSync(inFilename).toString().split('\n');
|
var lines = fs
|
||||||
|
.readFileSync(inFilename)
|
||||||
|
.toString()
|
||||||
|
.split("\n");
|
||||||
var totalLines = lines.length;
|
var totalLines = lines.length;
|
||||||
var out = '';
|
var out = "";
|
||||||
var i = 0;
|
var i = 0;
|
||||||
function readLine() {
|
function readLine() {
|
||||||
if (i < totalLines) {
|
if (i < totalLines) {
|
||||||
@ -44,19 +47,29 @@ function preprocess(inFilename, outFilename, defines) {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var writeLine = (typeof outFilename === 'function' ? outFilename :
|
var writeLine =
|
||||||
function(line) {
|
typeof outFilename === "function"
|
||||||
out += line + '\n';
|
? outFilename
|
||||||
});
|
: function(line) {
|
||||||
|
out += line + "\n";
|
||||||
|
};
|
||||||
function evaluateCondition(code) {
|
function evaluateCondition(code) {
|
||||||
if (!code || !code.trim()) {
|
if (!code || !code.trim()) {
|
||||||
throw new Error('No JavaScript expression given at ' + loc());
|
throw new Error("No JavaScript expression given at " + loc());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return vm.runInNewContext(code, defines, { displayErrors: false, });
|
return vm.runInNewContext(code, defines, { displayErrors: false });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('Could not evaluate "' + code + '" at ' + loc() + '\n' +
|
throw new Error(
|
||||||
e.name + ': ' + e.message);
|
'Could not evaluate "' +
|
||||||
|
code +
|
||||||
|
'" at ' +
|
||||||
|
loc() +
|
||||||
|
"\n" +
|
||||||
|
e.name +
|
||||||
|
": " +
|
||||||
|
e.message
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function include(file) {
|
function include(file) {
|
||||||
@ -64,15 +77,18 @@ function preprocess(inFilename, outFilename, defines) {
|
|||||||
var dir = path.dirname(realPath);
|
var dir = path.dirname(realPath);
|
||||||
try {
|
try {
|
||||||
var fullpath;
|
var fullpath;
|
||||||
if (file.indexOf('$ROOT/') === 0) {
|
if (file.indexOf("$ROOT/") === 0) {
|
||||||
fullpath = path.join(__dirname, '../..',
|
fullpath = path.join(
|
||||||
file.substring('$ROOT/'.length));
|
__dirname,
|
||||||
|
"../..",
|
||||||
|
file.substring("$ROOT/".length)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
fullpath = path.join(dir, file);
|
fullpath = path.join(dir, file);
|
||||||
}
|
}
|
||||||
preprocess(fullpath, writeLine, defines);
|
preprocess(fullpath, writeLine, defines);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code === 'ENOENT') {
|
if (e.code === "ENOENT") {
|
||||||
throw new Error('Failed to include "' + file + '" at ' + loc());
|
throw new Error('Failed to include "' + file + '" at ' + loc());
|
||||||
}
|
}
|
||||||
throw e; // Some other error
|
throw e; // Some other error
|
||||||
@ -84,7 +100,7 @@ function preprocess(inFilename, outFilename, defines) {
|
|||||||
if (variable in defines) {
|
if (variable in defines) {
|
||||||
return defines[variable];
|
return defines[variable];
|
||||||
}
|
}
|
||||||
return '';
|
return "";
|
||||||
});
|
});
|
||||||
writeLine(line);
|
writeLine(line);
|
||||||
}
|
}
|
||||||
@ -104,104 +120,107 @@ function preprocess(inFilename, outFilename, defines) {
|
|||||||
var line;
|
var line;
|
||||||
var state = STATE_NONE;
|
var state = STATE_NONE;
|
||||||
var stack = [];
|
var stack = [];
|
||||||
var control = // eslint-disable-next-line max-len
|
var control = /^(?:\/\/|<!--)\s*#(if|elif|else|endif|expand|include|error)\b(?:\s+(.*?)(?:-->)?$)?/; // eslint-disable-next-line max-len
|
||||||
/^(?:\/\/|<!--)\s*#(if|elif|else|endif|expand|include|error)\b(?:\s+(.*?)(?:-->)?$)?/;
|
|
||||||
var lineNumber = 0;
|
var lineNumber = 0;
|
||||||
var loc = function() {
|
var loc = function() {
|
||||||
return fs.realpathSync(inFilename) + ':' + lineNumber;
|
return fs.realpathSync(inFilename) + ":" + lineNumber;
|
||||||
};
|
};
|
||||||
while ((line = readLine()) !== null) {
|
while ((line = readLine()) !== null) {
|
||||||
++lineNumber;
|
++lineNumber;
|
||||||
var m = control.exec(line);
|
var m = control.exec(line);
|
||||||
if (m) {
|
if (m) {
|
||||||
switch (m[1]) {
|
switch (m[1]) {
|
||||||
case 'if':
|
case "if":
|
||||||
stack.push(state);
|
stack.push(state);
|
||||||
state = evaluateCondition(m[2]) ? STATE_IF_TRUE : STATE_IF_FALSE;
|
state = evaluateCondition(m[2]) ? STATE_IF_TRUE : STATE_IF_FALSE;
|
||||||
break;
|
break;
|
||||||
case 'elif':
|
case "elif":
|
||||||
if (state === STATE_IF_TRUE || state === STATE_ELSE_FALSE) {
|
if (state === STATE_IF_TRUE || state === STATE_ELSE_FALSE) {
|
||||||
state = STATE_ELSE_FALSE;
|
state = STATE_ELSE_FALSE;
|
||||||
} else if (state === STATE_IF_FALSE) {
|
} else if (state === STATE_IF_FALSE) {
|
||||||
state = evaluateCondition(m[2]) ? STATE_IF_TRUE : STATE_IF_FALSE;
|
state = evaluateCondition(m[2]) ? STATE_IF_TRUE : STATE_IF_FALSE;
|
||||||
} else if (state === STATE_ELSE_TRUE) {
|
} else if (state === STATE_ELSE_TRUE) {
|
||||||
throw new Error('Found #elif after #else at ' + loc());
|
throw new Error("Found #elif after #else at " + loc());
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Found #elif without matching #if at ' + loc());
|
throw new Error("Found #elif without matching #if at " + loc());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'else':
|
case "else":
|
||||||
if (state === STATE_IF_TRUE || state === STATE_ELSE_FALSE) {
|
if (state === STATE_IF_TRUE || state === STATE_ELSE_FALSE) {
|
||||||
state = STATE_ELSE_FALSE;
|
state = STATE_ELSE_FALSE;
|
||||||
} else if (state === STATE_IF_FALSE) {
|
} else if (state === STATE_IF_FALSE) {
|
||||||
state = STATE_ELSE_TRUE;
|
state = STATE_ELSE_TRUE;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Found #else without matching #if at ' + loc());
|
throw new Error("Found #else without matching #if at " + loc());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'endif':
|
case "endif":
|
||||||
if (state === STATE_NONE) {
|
if (state === STATE_NONE) {
|
||||||
throw new Error('Found #endif without #if at ' + loc());
|
throw new Error("Found #endif without #if at " + loc());
|
||||||
}
|
}
|
||||||
state = stack.pop();
|
state = stack.pop();
|
||||||
break;
|
break;
|
||||||
case 'expand':
|
case "expand":
|
||||||
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
||||||
expand(m[2]);
|
expand(m[2]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'include':
|
case "include":
|
||||||
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
||||||
include(m[2]);
|
include(m[2]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'error':
|
case "error":
|
||||||
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
||||||
throw new Error('Found #error ' + m[2] + ' at ' + loc());
|
throw new Error("Found #error " + m[2] + " at " + loc());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (state === STATE_NONE) {
|
if (state === STATE_NONE) {
|
||||||
writeLine(line);
|
writeLine(line);
|
||||||
} else if ((state === STATE_IF_TRUE || state === STATE_ELSE_TRUE) &&
|
} else if (
|
||||||
|
(state === STATE_IF_TRUE || state === STATE_ELSE_TRUE) &&
|
||||||
!stack.includes(STATE_IF_FALSE) &&
|
!stack.includes(STATE_IF_FALSE) &&
|
||||||
!stack.includes(STATE_ELSE_FALSE)) {
|
!stack.includes(STATE_ELSE_FALSE)
|
||||||
writeLine(line.replace(/^\/\/|^<!--|-->$/g, ' '));
|
) {
|
||||||
|
writeLine(line.replace(/^\/\/|^<!--|-->$/g, " "));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (state !== STATE_NONE || stack.length !== 0) {
|
if (state !== STATE_NONE || stack.length !== 0) {
|
||||||
throw new Error('Missing #endif in preprocessor for ' +
|
throw new Error(
|
||||||
fs.realpathSync(inFilename));
|
"Missing #endif in preprocessor for " + fs.realpathSync(inFilename)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (typeof outFilename !== 'function') {
|
if (typeof outFilename !== "function") {
|
||||||
fs.writeFileSync(outFilename, out);
|
fs.writeFileSync(outFilename, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.preprocess = preprocess;
|
exports.preprocess = preprocess;
|
||||||
|
|
||||||
var deprecatedInMozcentral = new RegExp('(^|\\W)(' + [
|
var deprecatedInMozcentral = new RegExp(
|
||||||
'-moz-box-sizing',
|
"(^|\\W)(" + ["-moz-box-sizing", "-moz-grab", "-moz-grabbing"].join("|") + ")"
|
||||||
'-moz-grab',
|
);
|
||||||
'-moz-grabbing'
|
|
||||||
].join('|') + ')');
|
|
||||||
|
|
||||||
function preprocessCSS(mode, source, destination) {
|
function preprocessCSS(mode, source, destination) {
|
||||||
function hasPrefixedFirefox(line) {
|
function hasPrefixedFirefox(line) {
|
||||||
return (/(^|\W)-(ms|o|webkit)-\w/.test(line));
|
return /(^|\W)-(ms|o|webkit)-\w/.test(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasPrefixedMozcentral(line) {
|
function hasPrefixedMozcentral(line) {
|
||||||
return (/(^|\W)-(ms|o|webkit)-\w/.test(line) ||
|
return (
|
||||||
deprecatedInMozcentral.test(line));
|
/(^|\W)-(ms|o|webkit)-\w/.test(line) || deprecatedInMozcentral.test(line)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function expandImports(content, baseUrl) {
|
function expandImports(content, baseUrl) {
|
||||||
return content.replace(/^\s*@import\s+url\(([^\)]+)\);\s*$/gm,
|
return content.replace(/^\s*@import\s+url\(([^\)]+)\);\s*$/gm, function(
|
||||||
function(all, url) {
|
all,
|
||||||
|
url
|
||||||
|
) {
|
||||||
var file = path.join(path.dirname(baseUrl), url);
|
var file = path.join(path.dirname(baseUrl), url);
|
||||||
var imported = fs.readFileSync(file, 'utf8').toString();
|
var imported = fs.readFileSync(file, "utf8").toString();
|
||||||
return expandImports(imported, file);
|
return expandImports(imported, file);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -221,9 +240,9 @@ function preprocessCSS(mode, source, destination) {
|
|||||||
while (j < lines.length && bracketLevel > 0) {
|
while (j < lines.length && bracketLevel > 0) {
|
||||||
var checkBracket = /([{}])\s*$/.exec(lines[j]);
|
var checkBracket = /([{}])\s*$/.exec(lines[j]);
|
||||||
if (checkBracket) {
|
if (checkBracket) {
|
||||||
if (checkBracket[1] === '{') {
|
if (checkBracket[1] === "{") {
|
||||||
bracketLevel++;
|
bracketLevel++;
|
||||||
} else if (!lines[j].includes('{')) {
|
} else if (!lines[j].includes("{")) {
|
||||||
bracketLevel--;
|
bracketLevel--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,30 +255,34 @@ function preprocessCSS(mode, source, destination) {
|
|||||||
// multiline? skipping until next directive or bracket
|
// multiline? skipping until next directive or bracket
|
||||||
do {
|
do {
|
||||||
lines.splice(i, 1);
|
lines.splice(i, 1);
|
||||||
} while (i < lines.length &&
|
} while (
|
||||||
|
i < lines.length &&
|
||||||
!/\}\s*$/.test(lines[i]) &&
|
!/\}\s*$/.test(lines[i]) &&
|
||||||
!lines[i].includes(':'));
|
!lines[i].includes(":")
|
||||||
|
);
|
||||||
if (i < lines.length && /\S\s*}\s*$/.test(lines[i])) {
|
if (i < lines.length && /\S\s*}\s*$/.test(lines[i])) {
|
||||||
lines[i] = lines[i].substring(lines[i].indexOf('}'));
|
lines[i] = lines[i].substring(lines[i].indexOf("}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// collapse whitespaces
|
// collapse whitespaces
|
||||||
while (lines[i] === '' && lines[i - 1] === '') {
|
while (lines[i] === "" && lines[i - 1] === "") {
|
||||||
lines.splice(i, 1);
|
lines.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return lines.join('\n');
|
return lines.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mode) {
|
if (!mode) {
|
||||||
throw new Error('Invalid CSS preprocessor mode');
|
throw new Error("Invalid CSS preprocessor mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
var content = fs.readFileSync(source, 'utf8').toString();
|
var content = fs.readFileSync(source, "utf8").toString();
|
||||||
content = expandImports(content, source);
|
content = expandImports(content, source);
|
||||||
if (mode === 'mozcentral' || mode === 'firefox') {
|
if (mode === "mozcentral" || mode === "firefox") {
|
||||||
content = removePrefixed(content, mode === 'mozcentral' ?
|
content = removePrefixed(
|
||||||
hasPrefixedMozcentral : hasPrefixedFirefox);
|
content,
|
||||||
|
mode === "mozcentral" ? hasPrefixedMozcentral : hasPrefixedFirefox
|
||||||
|
);
|
||||||
}
|
}
|
||||||
fs.writeFileSync(destination, content);
|
fs.writeFileSync(destination, content);
|
||||||
}
|
}
|
||||||
|
234
external/builder/preprocessor2.js
vendored
234
external/builder/preprocessor2.js
vendored
@ -1,103 +1,117 @@
|
|||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var acorn = require('acorn');
|
var acorn = require("acorn");
|
||||||
var escodegen = require('escodegen');
|
var escodegen = require("escodegen");
|
||||||
var vm = require('vm');
|
var vm = require("vm");
|
||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
var PDFJS_PREPROCESSOR_NAME = 'PDFJSDev';
|
var PDFJS_PREPROCESSOR_NAME = "PDFJSDev";
|
||||||
var ROOT_PREFIX = '$ROOT/';
|
var ROOT_PREFIX = "$ROOT/";
|
||||||
|
|
||||||
function isLiteral(obj, value) {
|
function isLiteral(obj, value) {
|
||||||
return obj.type === 'Literal' && obj.value === value;
|
return obj.type === "Literal" && obj.value === value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPDFJSPreprocessor(obj) {
|
function isPDFJSPreprocessor(obj) {
|
||||||
return obj.type === 'Identifier' &&
|
return obj.type === "Identifier" && obj.name === PDFJS_PREPROCESSOR_NAME;
|
||||||
obj.name === PDFJS_PREPROCESSOR_NAME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function evalWithDefines(code, defines, loc) {
|
function evalWithDefines(code, defines, loc) {
|
||||||
if (!code || !code.trim()) {
|
if (!code || !code.trim()) {
|
||||||
throw new Error('No JavaScript expression given');
|
throw new Error("No JavaScript expression given");
|
||||||
}
|
}
|
||||||
return vm.runInNewContext(code, defines, { displayErrors: false, });
|
return vm.runInNewContext(code, defines, { displayErrors: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePreprocessorAction(ctx, actionName, args, loc) {
|
function handlePreprocessorAction(ctx, actionName, args, loc) {
|
||||||
try {
|
try {
|
||||||
var arg;
|
var arg;
|
||||||
switch (actionName) {
|
switch (actionName) {
|
||||||
case 'test':
|
case "test":
|
||||||
arg = args[0];
|
arg = args[0];
|
||||||
if (!arg || arg.type !== 'Literal' ||
|
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
|
||||||
typeof arg.value !== 'string') {
|
throw new Error("No code for testing is given");
|
||||||
throw new Error('No code for testing is given');
|
|
||||||
}
|
}
|
||||||
var isTrue = !!evalWithDefines(arg.value, ctx.defines);
|
var isTrue = !!evalWithDefines(arg.value, ctx.defines);
|
||||||
return { type: 'Literal', value: isTrue, loc: loc, };
|
return { type: "Literal", value: isTrue, loc: loc };
|
||||||
case 'eval':
|
case "eval":
|
||||||
arg = args[0];
|
arg = args[0];
|
||||||
if (!arg || arg.type !== 'Literal' ||
|
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
|
||||||
typeof arg.value !== 'string') {
|
throw new Error("No code for eval is given");
|
||||||
throw new Error('No code for eval is given');
|
|
||||||
}
|
}
|
||||||
var result = evalWithDefines(arg.value, ctx.defines);
|
var result = evalWithDefines(arg.value, ctx.defines);
|
||||||
if (typeof result === 'boolean' || typeof result === 'string' ||
|
if (
|
||||||
typeof result === 'number') {
|
typeof result === "boolean" ||
|
||||||
return { type: 'Literal', value: result, loc: loc, };
|
typeof result === "string" ||
|
||||||
|
typeof result === "number"
|
||||||
|
) {
|
||||||
|
return { type: "Literal", value: result, loc: loc };
|
||||||
}
|
}
|
||||||
if (typeof result === 'object') {
|
if (typeof result === "object") {
|
||||||
var parsedObj = acorn.parse('(' + JSON.stringify(result) + ')');
|
var parsedObj = acorn.parse("(" + JSON.stringify(result) + ")");
|
||||||
parsedObj.body[0].expression.loc = loc;
|
parsedObj.body[0].expression.loc = loc;
|
||||||
return parsedObj.body[0].expression;
|
return parsedObj.body[0].expression;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'json':
|
case "json":
|
||||||
arg = args[0];
|
arg = args[0];
|
||||||
if (!arg || arg.type !== 'Literal' ||
|
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
|
||||||
typeof arg.value !== 'string') {
|
throw new Error("Path to JSON is not provided");
|
||||||
throw new Error('Path to JSON is not provided');
|
|
||||||
}
|
}
|
||||||
var jsonPath = arg.value;
|
var jsonPath = arg.value;
|
||||||
if (jsonPath.indexOf(ROOT_PREFIX) === 0) {
|
if (jsonPath.indexOf(ROOT_PREFIX) === 0) {
|
||||||
jsonPath = path.join(ctx.rootPath,
|
jsonPath = path.join(
|
||||||
jsonPath.substring(ROOT_PREFIX.length));
|
ctx.rootPath,
|
||||||
|
jsonPath.substring(ROOT_PREFIX.length)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var jsonContent = fs.readFileSync(jsonPath).toString();
|
var jsonContent = fs.readFileSync(jsonPath).toString();
|
||||||
var parsedJSON = acorn.parse('(' + jsonContent + ')');
|
var parsedJSON = acorn.parse("(" + jsonContent + ")");
|
||||||
parsedJSON.body[0].expression.loc = loc;
|
parsedJSON.body[0].expression.loc = loc;
|
||||||
return parsedJSON.body[0].expression;
|
return parsedJSON.body[0].expression;
|
||||||
}
|
}
|
||||||
throw new Error('Unsupported action');
|
throw new Error("Unsupported action");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error('Could not process ' + PDFJS_PREPROCESSOR_NAME + '.' +
|
throw new Error(
|
||||||
actionName + ' at ' + JSON.stringify(loc) + '\n' +
|
"Could not process " +
|
||||||
e.name + ': ' + e.message);
|
PDFJS_PREPROCESSOR_NAME +
|
||||||
|
"." +
|
||||||
|
actionName +
|
||||||
|
" at " +
|
||||||
|
JSON.stringify(loc) +
|
||||||
|
"\n" +
|
||||||
|
e.name +
|
||||||
|
": " +
|
||||||
|
e.message
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function postprocessNode(ctx, node) {
|
function postprocessNode(ctx, node) {
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case 'ExportNamedDeclaration':
|
case "ExportNamedDeclaration":
|
||||||
case 'ImportDeclaration':
|
case "ImportDeclaration":
|
||||||
if (node.source && node.source.type === 'Literal' &&
|
if (
|
||||||
ctx.map && ctx.map[node.source.value]) {
|
node.source &&
|
||||||
|
node.source.type === "Literal" &&
|
||||||
|
ctx.map &&
|
||||||
|
ctx.map[node.source.value]
|
||||||
|
) {
|
||||||
var newValue = ctx.map[node.source.value];
|
var newValue = ctx.map[node.source.value];
|
||||||
node.source.value = node.source.raw = newValue;
|
node.source.value = node.source.raw = newValue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'IfStatement':
|
case "IfStatement":
|
||||||
if (isLiteral(node.test, true)) {
|
if (isLiteral(node.test, true)) {
|
||||||
// if (true) stmt1; => stmt1
|
// if (true) stmt1; => stmt1
|
||||||
return node.consequent;
|
return node.consequent;
|
||||||
} else if (isLiteral(node.test, false)) {
|
} else if (isLiteral(node.test, false)) {
|
||||||
// if (false) stmt1; else stmt2; => stmt2
|
// if (false) stmt1; else stmt2; => stmt2
|
||||||
return node.alternate || { type: 'EmptyStatement', loc: node.loc, };
|
return node.alternate || { type: "EmptyStatement", loc: node.loc };
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'ConditionalExpression':
|
case "ConditionalExpression":
|
||||||
if (isLiteral(node.test, true)) {
|
if (isLiteral(node.test, true)) {
|
||||||
// true ? stmt1 : stmt2 => stmt1
|
// true ? stmt1 : stmt2 => stmt1
|
||||||
return node.consequent;
|
return node.consequent;
|
||||||
@ -106,22 +120,23 @@ function postprocessNode(ctx, node) {
|
|||||||
return node.alternate;
|
return node.alternate;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'UnaryExpression':
|
case "UnaryExpression":
|
||||||
if (node.operator === 'typeof' &&
|
if (node.operator === "typeof" && isPDFJSPreprocessor(node.argument)) {
|
||||||
isPDFJSPreprocessor(node.argument)) {
|
|
||||||
// typeof PDFJSDev => 'object'
|
// typeof PDFJSDev => 'object'
|
||||||
return { type: 'Literal', value: 'object', loc: node.loc, };
|
return { type: "Literal", value: "object", loc: node.loc };
|
||||||
}
|
}
|
||||||
if (node.operator === '!' &&
|
if (
|
||||||
node.argument.type === 'Literal' &&
|
node.operator === "!" &&
|
||||||
typeof node.argument.value === 'boolean') {
|
node.argument.type === "Literal" &&
|
||||||
|
typeof node.argument.value === "boolean"
|
||||||
|
) {
|
||||||
// !true => false, !false => true
|
// !true => false, !false => true
|
||||||
return { type: 'Literal', value: !node.argument.value, loc: node.loc, };
|
return { type: "Literal", value: !node.argument.value, loc: node.loc };
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'LogicalExpression':
|
case "LogicalExpression":
|
||||||
switch (node.operator) {
|
switch (node.operator) {
|
||||||
case '&&':
|
case "&&":
|
||||||
if (isLiteral(node.left, true)) {
|
if (isLiteral(node.left, true)) {
|
||||||
return node.right;
|
return node.right;
|
||||||
}
|
}
|
||||||
@ -129,7 +144,7 @@ function postprocessNode(ctx, node) {
|
|||||||
return node.left;
|
return node.left;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '||':
|
case "||":
|
||||||
if (isLiteral(node.left, true)) {
|
if (isLiteral(node.left, true)) {
|
||||||
return node.left;
|
return node.left;
|
||||||
}
|
}
|
||||||
@ -139,24 +154,26 @@ function postprocessNode(ctx, node) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'BinaryExpression':
|
case "BinaryExpression":
|
||||||
switch (node.operator) {
|
switch (node.operator) {
|
||||||
case '==':
|
case "==":
|
||||||
case '===':
|
case "===":
|
||||||
case '!=':
|
case "!=":
|
||||||
case '!==':
|
case "!==":
|
||||||
if (node.left.type === 'Literal' &&
|
if (
|
||||||
node.right.type === 'Literal' &&
|
node.left.type === "Literal" &&
|
||||||
typeof node.left.value === typeof node.right.value) {
|
node.right.type === "Literal" &&
|
||||||
|
typeof node.left.value === typeof node.right.value
|
||||||
|
) {
|
||||||
// folding two literals == and != check
|
// folding two literals == and != check
|
||||||
switch (typeof node.left.value) {
|
switch (typeof node.left.value) {
|
||||||
case 'string':
|
case "string":
|
||||||
case 'boolean':
|
case "boolean":
|
||||||
case 'number':
|
case "number":
|
||||||
var equal = node.left.value === node.right.value;
|
var equal = node.left.value === node.right.value;
|
||||||
return {
|
return {
|
||||||
type: 'Literal',
|
type: "Literal",
|
||||||
value: (node.operator[0] === '=') === equal,
|
value: (node.operator[0] === "=") === equal,
|
||||||
loc: node.loc,
|
loc: node.loc,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -164,54 +181,66 @@ function postprocessNode(ctx, node) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'CallExpression':
|
case "CallExpression":
|
||||||
if (node.callee.type === 'MemberExpression' &&
|
if (
|
||||||
|
node.callee.type === "MemberExpression" &&
|
||||||
isPDFJSPreprocessor(node.callee.object) &&
|
isPDFJSPreprocessor(node.callee.object) &&
|
||||||
node.callee.property.type === 'Identifier') {
|
node.callee.property.type === "Identifier"
|
||||||
|
) {
|
||||||
// PDFJSDev.xxxx(arg1, arg2, ...) => transform
|
// PDFJSDev.xxxx(arg1, arg2, ...) => transform
|
||||||
var action = node.callee.property.name;
|
var action = node.callee.property.name;
|
||||||
return handlePreprocessorAction(ctx, action,
|
return handlePreprocessorAction(ctx, action, node.arguments, node.loc);
|
||||||
node.arguments, node.loc);
|
|
||||||
}
|
}
|
||||||
// require('string')
|
// require('string')
|
||||||
if (node.callee.type === 'Identifier' && node.callee.name === 'require' &&
|
if (
|
||||||
node.arguments.length === 1 && node.arguments[0].type === 'Literal' &&
|
node.callee.type === "Identifier" &&
|
||||||
ctx.map && ctx.map[node.arguments[0].value]) {
|
node.callee.name === "require" &&
|
||||||
|
node.arguments.length === 1 &&
|
||||||
|
node.arguments[0].type === "Literal" &&
|
||||||
|
ctx.map &&
|
||||||
|
ctx.map[node.arguments[0].value]
|
||||||
|
) {
|
||||||
var requireName = node.arguments[0];
|
var requireName = node.arguments[0];
|
||||||
requireName.value = requireName.raw = ctx.map[requireName.value];
|
requireName.value = requireName.raw = ctx.map[requireName.value];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'BlockStatement':
|
case "BlockStatement":
|
||||||
var subExpressionIndex = 0;
|
var subExpressionIndex = 0;
|
||||||
while (subExpressionIndex < node.body.length) {
|
while (subExpressionIndex < node.body.length) {
|
||||||
switch (node.body[subExpressionIndex].type) {
|
switch (node.body[subExpressionIndex].type) {
|
||||||
case 'EmptyStatement':
|
case "EmptyStatement":
|
||||||
// Removing empty statements from the blocks.
|
// Removing empty statements from the blocks.
|
||||||
node.body.splice(subExpressionIndex, 1);
|
node.body.splice(subExpressionIndex, 1);
|
||||||
continue;
|
continue;
|
||||||
case 'BlockStatement':
|
case "BlockStatement":
|
||||||
// Block statements inside a block are moved to the parent one.
|
// Block statements inside a block are moved to the parent one.
|
||||||
var subChildren = node.body[subExpressionIndex].body;
|
var subChildren = node.body[subExpressionIndex].body;
|
||||||
Array.prototype.splice.apply(node.body,
|
Array.prototype.splice.apply(
|
||||||
[subExpressionIndex, 1].concat(subChildren));
|
node.body,
|
||||||
|
[subExpressionIndex, 1].concat(subChildren)
|
||||||
|
);
|
||||||
subExpressionIndex += Math.max(subChildren.length - 1, 0);
|
subExpressionIndex += Math.max(subChildren.length - 1, 0);
|
||||||
continue;
|
continue;
|
||||||
case 'ReturnStatement':
|
case "ReturnStatement":
|
||||||
case 'ThrowStatement':
|
case "ThrowStatement":
|
||||||
// Removing dead code after return or throw.
|
// Removing dead code after return or throw.
|
||||||
node.body.splice(subExpressionIndex + 1,
|
node.body.splice(
|
||||||
node.body.length - subExpressionIndex - 1);
|
subExpressionIndex + 1,
|
||||||
|
node.body.length - subExpressionIndex - 1
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
subExpressionIndex++;
|
subExpressionIndex++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'FunctionDeclaration':
|
case "FunctionDeclaration":
|
||||||
case 'FunctionExpression':
|
case "FunctionExpression":
|
||||||
var block = node.body;
|
var block = node.body;
|
||||||
if (block.body.length > 0 &&
|
if (
|
||||||
block.body[block.body.length - 1].type === 'ReturnStatement' &&
|
block.body.length > 0 &&
|
||||||
!block.body[block.body.length - 1].argument) {
|
block.body[block.body.length - 1].type === "ReturnStatement" &&
|
||||||
|
!block.body[block.body.length - 1].argument
|
||||||
|
) {
|
||||||
// Function body ends with return without arg -- removing it.
|
// Function body ends with return without arg -- removing it.
|
||||||
block.body.pop();
|
block.body.pop();
|
||||||
}
|
}
|
||||||
@ -237,14 +266,16 @@ function fixComments(ctx, node) {
|
|||||||
var type = node.leadingComments[i].type;
|
var type = node.leadingComments[i].type;
|
||||||
var value = node.leadingComments[i].value;
|
var value = node.leadingComments[i].value;
|
||||||
|
|
||||||
if (ctx.saveComments === 'copyright') {
|
if (ctx.saveComments === "copyright") {
|
||||||
// Remove all comments, except Copyright notices and License headers.
|
// Remove all comments, except Copyright notices and License headers.
|
||||||
if (!(type === 'Block' && CopyrightRegExp.test(value))) {
|
if (!(type === "Block" && CopyrightRegExp.test(value))) {
|
||||||
node.leadingComments.splice(i, 1);
|
node.leadingComments.splice(i, 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if ((type === 'Block' && BlockCommentRegExp.test(value)) ||
|
} else if (
|
||||||
(type === 'Line' && LineCommentRegExp.test(value))) {
|
(type === "Block" && BlockCommentRegExp.test(value)) ||
|
||||||
|
(type === "Line" && LineCommentRegExp.test(value))
|
||||||
|
) {
|
||||||
node.leadingComments.splice(i, 1);
|
node.leadingComments.splice(i, 1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -257,15 +288,18 @@ function traverseTree(ctx, node) {
|
|||||||
// generic node processing
|
// generic node processing
|
||||||
for (var i in node) {
|
for (var i in node) {
|
||||||
var child = node[i];
|
var child = node[i];
|
||||||
if (typeof child === 'object' && child !== null && child.type) {
|
if (typeof child === "object" && child !== null && child.type) {
|
||||||
var result = traverseTree(ctx, child);
|
var result = traverseTree(ctx, child);
|
||||||
if (result !== child) {
|
if (result !== child) {
|
||||||
node[i] = result;
|
node[i] = result;
|
||||||
}
|
}
|
||||||
} else if (Array.isArray(child)) {
|
} else if (Array.isArray(child)) {
|
||||||
child.forEach(function(childItem, index) {
|
child.forEach(function(childItem, index) {
|
||||||
if (typeof childItem === 'object' && childItem !== null &&
|
if (
|
||||||
childItem.type) {
|
typeof childItem === "object" &&
|
||||||
|
childItem !== null &&
|
||||||
|
childItem.type
|
||||||
|
) {
|
||||||
var result = traverseTree(ctx, childItem);
|
var result = traverseTree(ctx, childItem);
|
||||||
if (result !== childItem) {
|
if (result !== childItem) {
|
||||||
child[index] = result;
|
child[index] = result;
|
||||||
@ -284,14 +318,14 @@ function traverseTree(ctx, node) {
|
|||||||
function preprocessPDFJSCode(ctx, code) {
|
function preprocessPDFJSCode(ctx, code) {
|
||||||
var format = ctx.format || {
|
var format = ctx.format || {
|
||||||
indent: {
|
indent: {
|
||||||
style: ' ',
|
style: " ",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var parseOptions = {
|
var parseOptions = {
|
||||||
ecmaVersion: 8,
|
ecmaVersion: 8,
|
||||||
locations: true,
|
locations: true,
|
||||||
sourceFile: ctx.sourceFile,
|
sourceFile: ctx.sourceFile,
|
||||||
sourceType: 'module',
|
sourceType: "module",
|
||||||
};
|
};
|
||||||
var codegenOptions = {
|
var codegenOptions = {
|
||||||
format: format,
|
format: format,
|
||||||
|
44
external/builder/test-fixtures.js
vendored
44
external/builder/test-fixtures.js
vendored
@ -1,20 +1,26 @@
|
|||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var builder = require('./builder');
|
var builder = require("./builder");
|
||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
var errors = 0;
|
var errors = 0;
|
||||||
|
|
||||||
var baseDir = path.join(__dirname, 'fixtures');
|
var baseDir = path.join(__dirname, "fixtures");
|
||||||
var files = fs.readdirSync(baseDir).filter(function (name) {
|
var files = fs
|
||||||
|
.readdirSync(baseDir)
|
||||||
|
.filter(function(name) {
|
||||||
return /-expected\./.test(name);
|
return /-expected\./.test(name);
|
||||||
}).map(function (name) {
|
})
|
||||||
|
.map(function(name) {
|
||||||
return path.join(baseDir, name);
|
return path.join(baseDir, name);
|
||||||
});
|
});
|
||||||
files.forEach(function(expectationFilename) {
|
files.forEach(function(expectationFilename) {
|
||||||
var inFilename = expectationFilename.replace('-expected', '');
|
var inFilename = expectationFilename.replace("-expected", "");
|
||||||
var expectation = fs.readFileSync(expectationFilename).toString().trim()
|
var expectation = fs
|
||||||
|
.readFileSync(expectationFilename)
|
||||||
|
.toString()
|
||||||
|
.trim()
|
||||||
.replace(/__filename/g, fs.realpathSync(inFilename));
|
.replace(/__filename/g, fs.realpathSync(inFilename));
|
||||||
var outLines = [];
|
var outLines = [];
|
||||||
|
|
||||||
@ -28,29 +34,29 @@ files.forEach(function(expectationFilename) {
|
|||||||
var out;
|
var out;
|
||||||
try {
|
try {
|
||||||
builder.preprocess(inFilename, outFilename, defines);
|
builder.preprocess(inFilename, outFilename, defines);
|
||||||
out = outLines.join('\n').trim();
|
out = outLines.join("\n").trim();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
out = ('Error: ' + e.message).replace(/^/gm, '//');
|
out = ("Error: " + e.message).replace(/^/gm, "//");
|
||||||
}
|
}
|
||||||
if (out !== expectation) {
|
if (out !== expectation) {
|
||||||
errors++;
|
errors++;
|
||||||
|
|
||||||
console.log('Assertion failed for ' + inFilename);
|
console.log("Assertion failed for " + inFilename);
|
||||||
console.log('--------------------------------------------------');
|
console.log("--------------------------------------------------");
|
||||||
console.log('EXPECTED:');
|
console.log("EXPECTED:");
|
||||||
console.log(expectation);
|
console.log(expectation);
|
||||||
console.log('--------------------------------------------------');
|
console.log("--------------------------------------------------");
|
||||||
console.log('ACTUAL');
|
console.log("ACTUAL");
|
||||||
console.log(out);
|
console.log(out);
|
||||||
console.log('--------------------------------------------------');
|
console.log("--------------------------------------------------");
|
||||||
console.log();
|
console.log();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (errors) {
|
if (errors) {
|
||||||
console.error('Found ' + errors + ' expectation failures.');
|
console.error("Found " + errors + " expectation failures.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
console.log('All tests completed without errors.');
|
console.log("All tests completed without errors.");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
50
external/builder/test-fixtures_esprima.js
vendored
50
external/builder/test-fixtures_esprima.js
vendored
@ -1,62 +1,68 @@
|
|||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var p2 = require('./preprocessor2.js');
|
var p2 = require("./preprocessor2.js");
|
||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
var errors = 0;
|
var errors = 0;
|
||||||
|
|
||||||
var baseDir = path.join(__dirname, 'fixtures_esprima');
|
var baseDir = path.join(__dirname, "fixtures_esprima");
|
||||||
var files = fs.readdirSync(baseDir).filter(function (name) {
|
var files = fs
|
||||||
|
.readdirSync(baseDir)
|
||||||
|
.filter(function(name) {
|
||||||
return /-expected\./.test(name);
|
return /-expected\./.test(name);
|
||||||
}).map(function (name) {
|
})
|
||||||
|
.map(function(name) {
|
||||||
return path.join(baseDir, name);
|
return path.join(baseDir, name);
|
||||||
});
|
});
|
||||||
files.forEach(function(expectationFilename) {
|
files.forEach(function(expectationFilename) {
|
||||||
var inFilename = expectationFilename.replace('-expected', '');
|
var inFilename = expectationFilename.replace("-expected", "");
|
||||||
var expectation = fs.readFileSync(expectationFilename).toString().trim()
|
var expectation = fs
|
||||||
|
.readFileSync(expectationFilename)
|
||||||
|
.toString()
|
||||||
|
.trim()
|
||||||
.replace(/__filename/g, fs.realpathSync(inFilename));
|
.replace(/__filename/g, fs.realpathSync(inFilename));
|
||||||
var input = fs.readFileSync(inFilename).toString();
|
var input = fs.readFileSync(inFilename).toString();
|
||||||
|
|
||||||
var defines = {
|
var defines = {
|
||||||
TRUE: true,
|
TRUE: true,
|
||||||
FALSE: false,
|
FALSE: false,
|
||||||
OBJ: { obj: { i: 1, }, j: 2, },
|
OBJ: { obj: { i: 1 }, j: 2 },
|
||||||
TEXT: 'text',
|
TEXT: "text",
|
||||||
};
|
};
|
||||||
var map = {
|
var map = {
|
||||||
'import-alias': 'import-name',
|
"import-alias": "import-name",
|
||||||
};
|
};
|
||||||
var ctx = {
|
var ctx = {
|
||||||
defines: defines,
|
defines: defines,
|
||||||
map: map,
|
map: map,
|
||||||
rootPath: __dirname + '/../..',
|
rootPath: __dirname + "/../..",
|
||||||
};
|
};
|
||||||
var out;
|
var out;
|
||||||
try {
|
try {
|
||||||
out = p2.preprocessPDFJSCode(ctx, input);
|
out = p2.preprocessPDFJSCode(ctx, input);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
out = ('Error: ' + e.message).replace(/^/gm, '//');
|
out = ("Error: " + e.message).replace(/^/gm, "//");
|
||||||
}
|
}
|
||||||
if (out !== expectation) {
|
if (out !== expectation) {
|
||||||
errors++;
|
errors++;
|
||||||
|
|
||||||
console.log('Assertion failed for ' + inFilename);
|
console.log("Assertion failed for " + inFilename);
|
||||||
console.log('--------------------------------------------------');
|
console.log("--------------------------------------------------");
|
||||||
console.log('EXPECTED:');
|
console.log("EXPECTED:");
|
||||||
console.log(expectation);
|
console.log(expectation);
|
||||||
console.log('--------------------------------------------------');
|
console.log("--------------------------------------------------");
|
||||||
console.log('ACTUAL');
|
console.log("ACTUAL");
|
||||||
console.log(out);
|
console.log(out);
|
||||||
console.log('--------------------------------------------------');
|
console.log("--------------------------------------------------");
|
||||||
console.log();
|
console.log();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (errors) {
|
if (errors) {
|
||||||
console.error('Found ' + errors + ' expectation failures.');
|
console.error("Found " + errors + " expectation failures.");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
} else {
|
} else {
|
||||||
console.log('All tests completed without errors.');
|
console.log("All tests completed without errors.");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
8
external/dist/webpack.js
vendored
8
external/dist/webpack.js
vendored
@ -12,12 +12,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var pdfjs = require('./build/pdf.js');
|
var pdfjs = require("./build/pdf.js");
|
||||||
var PdfjsWorker = require('worker-loader!./build/pdf.worker.js');
|
var PdfjsWorker = require("worker-loader!./build/pdf.worker.js");
|
||||||
|
|
||||||
if (typeof window !== 'undefined' && 'Worker' in window) {
|
if (typeof window !== "undefined" && "Worker" in window) {
|
||||||
pdfjs.GlobalWorkerOptions.workerPort = new PdfjsWorker();
|
pdfjs.GlobalWorkerOptions.workerPort = new PdfjsWorker();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
64
external/importL10n/locales.js
vendored
64
external/importL10n/locales.js
vendored
@ -13,39 +13,40 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var fs = require('fs');
|
var fs = require("fs");
|
||||||
var https = require('https');
|
var https = require("https");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
// Fetches all languages that have an *active* translation in mozilla-central.
|
// Fetches all languages that have an *active* translation in mozilla-central.
|
||||||
// This is used in gulpfile.js for the `importl10n` command.
|
// This is used in gulpfile.js for the `importl10n` command.
|
||||||
|
|
||||||
var DEFAULT_LOCALE = 'en-US';
|
var DEFAULT_LOCALE = "en-US";
|
||||||
|
|
||||||
var EXCLUDE_LANG_CODES = ['ca-valencia', 'ja-JP-mac'];
|
var EXCLUDE_LANG_CODES = ["ca-valencia", "ja-JP-mac"];
|
||||||
|
|
||||||
function normalizeText(s) {
|
function normalizeText(s) {
|
||||||
return s.replace(/\r\n?/g, '\n').replace(/\uFEFF/g, '');
|
return s.replace(/\r\n?/g, "\n").replace(/\uFEFF/g, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadLanguageCodes() {
|
function downloadLanguageCodes() {
|
||||||
console.log('Downloading language codes...\n');
|
console.log("Downloading language codes...\n");
|
||||||
|
|
||||||
var ALL_LOCALES = 'https://hg.mozilla.org/mozilla-central/raw-file/tip/browser/locales/all-locales';
|
var ALL_LOCALES =
|
||||||
|
"https://hg.mozilla.org/mozilla-central/raw-file/tip/browser/locales/all-locales";
|
||||||
|
|
||||||
return new Promise(function(resolve) {
|
return new Promise(function(resolve) {
|
||||||
https.get(ALL_LOCALES, function(response) {
|
https.get(ALL_LOCALES, function(response) {
|
||||||
if (response.statusCode === 200) {
|
if (response.statusCode === 200) {
|
||||||
var content = '';
|
var content = "";
|
||||||
response.setEncoding('utf8');
|
response.setEncoding("utf8");
|
||||||
response.on('data', function(chunk) {
|
response.on("data", function(chunk) {
|
||||||
content += chunk;
|
content += chunk;
|
||||||
});
|
});
|
||||||
response.on('end', function() {
|
response.on("end", function() {
|
||||||
content = content.trim(); // Remove any leading/trailing white-space.
|
content = content.trim(); // Remove any leading/trailing white-space.
|
||||||
var langCodes = normalizeText(content).split('\n');
|
var langCodes = normalizeText(content).split("\n");
|
||||||
// Remove all locales that we don't want to download below.
|
// Remove all locales that we don't want to download below.
|
||||||
for (var langCode of [DEFAULT_LOCALE, ...EXCLUDE_LANG_CODES]) {
|
for (var langCode of [DEFAULT_LOCALE, ...EXCLUDE_LANG_CODES]) {
|
||||||
var i = langCodes.indexOf(langCode);
|
var i = langCodes.indexOf(langCode);
|
||||||
@ -63,15 +64,15 @@ function downloadLanguageCodes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function downloadLanguageFiles(root, langCode) {
|
function downloadLanguageFiles(root, langCode) {
|
||||||
console.log('Downloading ' + langCode + '...');
|
console.log("Downloading " + langCode + "...");
|
||||||
|
|
||||||
// Constants for constructing the URLs. Translations are taken from the
|
// Constants for constructing the URLs. Translations are taken from the
|
||||||
// Nightly channel as those are the most recent ones.
|
// Nightly channel as those are the most recent ones.
|
||||||
var MOZ_CENTRAL_ROOT = 'https://hg.mozilla.org/l10n-central/';
|
var MOZ_CENTRAL_ROOT = "https://hg.mozilla.org/l10n-central/";
|
||||||
var MOZ_CENTRAL_PDFJS_DIR = '/raw-file/default/browser/pdfviewer/';
|
var MOZ_CENTRAL_PDFJS_DIR = "/raw-file/default/browser/pdfviewer/";
|
||||||
|
|
||||||
// Defines which files to download for each language.
|
// Defines which files to download for each language.
|
||||||
var files = ['viewer.properties'];
|
var files = ["viewer.properties"];
|
||||||
var downloadsLeft = files.length;
|
var downloadsLeft = files.length;
|
||||||
|
|
||||||
var outputDir = path.join(root, langCode);
|
var outputDir = path.join(root, langCode);
|
||||||
@ -89,13 +90,13 @@ function downloadLanguageFiles(root, langCode) {
|
|||||||
// Not all files exist for each language. Files without translations
|
// Not all files exist for each language. Files without translations
|
||||||
// have been removed (https://bugzilla.mozilla.org/show_bug.cgi?id=1443175).
|
// have been removed (https://bugzilla.mozilla.org/show_bug.cgi?id=1443175).
|
||||||
if (response.statusCode === 200) {
|
if (response.statusCode === 200) {
|
||||||
var content = '';
|
var content = "";
|
||||||
response.setEncoding('utf8');
|
response.setEncoding("utf8");
|
||||||
response.on('data', function(chunk) {
|
response.on("data", function(chunk) {
|
||||||
content += chunk;
|
content += chunk;
|
||||||
});
|
});
|
||||||
response.on('end', function() {
|
response.on("end", function() {
|
||||||
fs.writeFileSync(outputPath, normalizeText(content), 'utf8');
|
fs.writeFileSync(outputPath, normalizeText(content), "utf8");
|
||||||
if (--downloadsLeft === 0) {
|
if (--downloadsLeft === 0) {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
@ -122,16 +123,23 @@ async function downloadL10n(root, callback) {
|
|||||||
|
|
||||||
var removeCodes = [];
|
var removeCodes = [];
|
||||||
for (var entry of fs.readdirSync(root)) {
|
for (var entry of fs.readdirSync(root)) {
|
||||||
var dirPath = path.join(root, entry), stat = fs.lstatSync(dirPath);
|
var dirPath = path.join(root, entry),
|
||||||
|
stat = fs.lstatSync(dirPath);
|
||||||
|
|
||||||
if (stat.isDirectory() && entry !== DEFAULT_LOCALE &&
|
if (
|
||||||
!langCodes.includes(entry)) {
|
stat.isDirectory() &&
|
||||||
|
entry !== DEFAULT_LOCALE &&
|
||||||
|
!langCodes.includes(entry)
|
||||||
|
) {
|
||||||
removeCodes.push(entry);
|
removeCodes.push(entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (removeCodes.length) {
|
if (removeCodes.length) {
|
||||||
console.log('\nConsider removing the following unmaintained locales:\n' +
|
console.log(
|
||||||
removeCodes.join(', ') + '\n');
|
"\nConsider removing the following unmaintained locales:\n" +
|
||||||
|
removeCodes.join(", ") +
|
||||||
|
"\n"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback) {
|
if (callback) {
|
||||||
|
73
external/systemjs/plugin-babel-cached.js
vendored
73
external/systemjs/plugin-babel-cached.js
vendored
@ -12,12 +12,12 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
var babel = require('plugin-babel');
|
var babel = require("plugin-babel");
|
||||||
|
|
||||||
var cacheExpiration = 60 /* min */ * 60 * 1000;
|
var cacheExpiration = 60 /* min */ * 60 * 1000;
|
||||||
var dbVersion = 1;
|
var dbVersion = 1;
|
||||||
var dbName = 'babelcache';
|
var dbName = "babelcache";
|
||||||
var dbCacheTable = 'translated';
|
var dbCacheTable = "translated";
|
||||||
var dbPromise;
|
var dbPromise;
|
||||||
|
|
||||||
function getDb() {
|
function getDb() {
|
||||||
@ -26,14 +26,14 @@ function getDb() {
|
|||||||
var request = indexedDB.open(dbName, dbVersion);
|
var request = indexedDB.open(dbName, dbVersion);
|
||||||
request.onupgradeneeded = function() {
|
request.onupgradeneeded = function() {
|
||||||
var db = request.result;
|
var db = request.result;
|
||||||
db.createObjectStore(dbCacheTable, { keyPath: 'address', });
|
db.createObjectStore(dbCacheTable, { keyPath: "address" });
|
||||||
};
|
};
|
||||||
request.onsuccess = function() {
|
request.onsuccess = function() {
|
||||||
var db = request.result;
|
var db = request.result;
|
||||||
resolve(db);
|
resolve(db);
|
||||||
};
|
};
|
||||||
request.onerror = function() {
|
request.onerror = function() {
|
||||||
console.warn('getDb: ' + request.error);
|
console.warn("getDb: " + request.error);
|
||||||
reject(request.error);
|
reject(request.error);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -43,7 +43,7 @@ function getDb() {
|
|||||||
|
|
||||||
function storeCache(address, hashCode, translated, format) {
|
function storeCache(address, hashCode, translated, format) {
|
||||||
return getDb().then(function(db) {
|
return getDb().then(function(db) {
|
||||||
var tx = db.transaction(dbCacheTable, 'readwrite');
|
var tx = db.transaction(dbCacheTable, "readwrite");
|
||||||
var store = tx.objectStore(dbCacheTable);
|
var store = tx.objectStore(dbCacheTable);
|
||||||
store.put({
|
store.put({
|
||||||
address: address,
|
address: address,
|
||||||
@ -65,18 +65,22 @@ function storeCache(address, hashCode, translated, format) {
|
|||||||
|
|
||||||
function loadCache(address, hashCode) {
|
function loadCache(address, hashCode) {
|
||||||
return getDb().then(function(db) {
|
return getDb().then(function(db) {
|
||||||
var tx = db.transaction(dbCacheTable, 'readonly');
|
var tx = db.transaction(dbCacheTable, "readonly");
|
||||||
var store = tx.objectStore(dbCacheTable);
|
var store = tx.objectStore(dbCacheTable);
|
||||||
var getAddress = store.get(address);
|
var getAddress = store.get(address);
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
tx.oncomplete = function() {
|
tx.oncomplete = function() {
|
||||||
var found = getAddress.result;
|
var found = getAddress.result;
|
||||||
var isValid = found && found.hashCode === hashCode &&
|
var isValid =
|
||||||
Date.now() < found.expires;
|
found && found.hashCode === hashCode && Date.now() < found.expires;
|
||||||
resolve(isValid ? {
|
resolve(
|
||||||
|
isValid
|
||||||
|
? {
|
||||||
translated: found.translated,
|
translated: found.translated,
|
||||||
format: found.format,
|
format: found.format,
|
||||||
} : null);
|
}
|
||||||
|
: null
|
||||||
|
);
|
||||||
};
|
};
|
||||||
tx.onerror = function() {
|
tx.onerror = function() {
|
||||||
resolve(null);
|
resolve(null);
|
||||||
@ -85,38 +89,59 @@ function loadCache(address, hashCode) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var encoder = new TextEncoder('utf-8');
|
var encoder = new TextEncoder("utf-8");
|
||||||
function sha256(str) {
|
function sha256(str) {
|
||||||
var buffer = encoder.encode(str);
|
var buffer = encoder.encode(str);
|
||||||
return crypto.subtle.digest('SHA-256', buffer).then(function (hash) {
|
return crypto.subtle.digest("SHA-256", buffer).then(function(hash) {
|
||||||
var data = new Int32Array(hash);
|
var data = new Int32Array(hash);
|
||||||
return data[0].toString(36) + '-' + data[1].toString(36) + '-' +
|
return (
|
||||||
data[2].toString(36) + '-' + data[3].toString(36);
|
data[0].toString(36) +
|
||||||
|
"-" +
|
||||||
|
data[1].toString(36) +
|
||||||
|
"-" +
|
||||||
|
data[2].toString(36) +
|
||||||
|
"-" +
|
||||||
|
data[3].toString(36)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.translate = function(load, opt) {
|
exports.translate = function(load, opt) {
|
||||||
var savedHashCode, babelTranslateError;
|
var savedHashCode, babelTranslateError;
|
||||||
return sha256(load.source).then(function (hashCode) {
|
return sha256(load.source)
|
||||||
|
.then(function(hashCode) {
|
||||||
savedHashCode = hashCode;
|
savedHashCode = hashCode;
|
||||||
return loadCache(load.address, hashCode);
|
return loadCache(load.address, hashCode);
|
||||||
}).then(function (cache) {
|
})
|
||||||
|
.then(
|
||||||
|
function(cache) {
|
||||||
if (cache) {
|
if (cache) {
|
||||||
load.metadata.format = cache.format;
|
load.metadata.format = cache.format;
|
||||||
return cache.translated;
|
return cache.translated;
|
||||||
}
|
}
|
||||||
return babel.translate.call(this, load, opt).then(function(translated) {
|
return babel.translate.call(this, load, opt).then(
|
||||||
return storeCache(load.address, savedHashCode,
|
function(translated) {
|
||||||
translated, load.metadata.format).then(function () {
|
return storeCache(
|
||||||
|
load.address,
|
||||||
|
savedHashCode,
|
||||||
|
translated,
|
||||||
|
load.metadata.format
|
||||||
|
).then(function() {
|
||||||
return translated;
|
return translated;
|
||||||
});
|
});
|
||||||
}, function(reason) {
|
},
|
||||||
|
function(reason) {
|
||||||
throw (babelTranslateError = reason);
|
throw (babelTranslateError = reason);
|
||||||
});
|
}
|
||||||
}.bind(this)).catch(function(reason) {
|
);
|
||||||
|
}.bind(this)
|
||||||
|
)
|
||||||
|
.catch(
|
||||||
|
function(reason) {
|
||||||
if (babelTranslateError) {
|
if (babelTranslateError) {
|
||||||
throw babelTranslateError;
|
throw babelTranslateError;
|
||||||
}
|
}
|
||||||
return babel.translate.call(this, load, opt);
|
return babel.translate.call(this, load, opt);
|
||||||
}.bind(this));
|
}.bind(this)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
13
external/webpack/pdfjsdev-loader.js
vendored
13
external/webpack/pdfjsdev-loader.js
vendored
@ -14,21 +14,24 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint-env node */
|
/* eslint-env node */
|
||||||
|
|
||||||
'use strict';
|
"use strict";
|
||||||
|
|
||||||
var preprocessor2 = require('../builder/preprocessor2.js');
|
var preprocessor2 = require("../builder/preprocessor2.js");
|
||||||
var path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
module.exports = function(source) {
|
module.exports = function(source) {
|
||||||
// Options must be specified, ignoring request if not.
|
// Options must be specified, ignoring request if not.
|
||||||
if (!this.query || typeof this.query !== 'object') {
|
if (!this.query || typeof this.query !== "object") {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
this.cacheable();
|
this.cacheable();
|
||||||
|
|
||||||
var filePath = this.resourcePath;
|
var filePath = this.resourcePath;
|
||||||
var context = this.rootContext;
|
var context = this.rootContext;
|
||||||
var sourcePath = path.relative(context, filePath).split(path.sep).join('/');
|
var sourcePath = path
|
||||||
|
.relative(context, filePath)
|
||||||
|
.split(path.sep)
|
||||||
|
.join("/");
|
||||||
|
|
||||||
var ctx = Object.create(this.query);
|
var ctx = Object.create(this.query);
|
||||||
ctx.sourceMap = true;
|
ctx.sourceMap = true;
|
||||||
|
1650
gulpfile.js
1650
gulpfile.js
File diff suppressed because it is too large
Load Diff
@ -15,16 +15,25 @@
|
|||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AnnotationBorderStyleType, AnnotationFieldFlag, AnnotationFlag,
|
AnnotationBorderStyleType,
|
||||||
AnnotationReplyType, AnnotationType, assert, isString, OPS, stringToBytes,
|
AnnotationFieldFlag,
|
||||||
stringToPDFString, Util, warn
|
AnnotationFlag,
|
||||||
} from '../shared/util';
|
AnnotationReplyType,
|
||||||
import { Catalog, FileSpec, ObjectLoader } from './obj';
|
AnnotationType,
|
||||||
import { Dict, isDict, isName, isRef, isStream } from './primitives';
|
assert,
|
||||||
import { ColorSpace } from './colorspace';
|
isString,
|
||||||
import { getInheritableProperty } from './core_utils';
|
OPS,
|
||||||
import { OperatorList } from './operator_list';
|
stringToBytes,
|
||||||
import { Stream } from './stream';
|
stringToPDFString,
|
||||||
|
Util,
|
||||||
|
warn,
|
||||||
|
} from "../shared/util";
|
||||||
|
import { Catalog, FileSpec, ObjectLoader } from "./obj";
|
||||||
|
import { Dict, isDict, isName, isRef, isStream } from "./primitives";
|
||||||
|
import { ColorSpace } from "./colorspace";
|
||||||
|
import { getInheritableProperty } from "./core_utils";
|
||||||
|
import { OperatorList } from "./operator_list";
|
||||||
|
import { Stream } from "./stream";
|
||||||
|
|
||||||
class AnnotationFactory {
|
class AnnotationFactory {
|
||||||
/**
|
/**
|
||||||
@ -40,8 +49,12 @@ class AnnotationFactory {
|
|||||||
* instance.
|
* instance.
|
||||||
*/
|
*/
|
||||||
static create(xref, ref, pdfManager, idFactory) {
|
static create(xref, ref, pdfManager, idFactory) {
|
||||||
return pdfManager.ensure(this, '_create',
|
return pdfManager.ensure(this, "_create", [
|
||||||
[xref, ref, pdfManager, idFactory]);
|
xref,
|
||||||
|
ref,
|
||||||
|
pdfManager,
|
||||||
|
idFactory,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,7 +68,7 @@ class AnnotationFactory {
|
|||||||
const id = isRef(ref) ? ref.toString() : `annot_${idFactory.createObjId()}`;
|
const id = isRef(ref) ? ref.toString() : `annot_${idFactory.createObjId()}`;
|
||||||
|
|
||||||
// Determine the annotation's subtype.
|
// Determine the annotation's subtype.
|
||||||
let subtype = dict.get('Subtype');
|
let subtype = dict.get("Subtype");
|
||||||
subtype = isName(subtype) ? subtype.name : null;
|
subtype = isName(subtype) ? subtype.name : null;
|
||||||
|
|
||||||
// Return the right annotation object based on the subtype and field type.
|
// Return the right annotation object based on the subtype and field type.
|
||||||
@ -68,79 +81,87 @@ class AnnotationFactory {
|
|||||||
};
|
};
|
||||||
|
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case 'Link':
|
case "Link":
|
||||||
return new LinkAnnotation(parameters);
|
return new LinkAnnotation(parameters);
|
||||||
|
|
||||||
case 'Text':
|
case "Text":
|
||||||
return new TextAnnotation(parameters);
|
return new TextAnnotation(parameters);
|
||||||
|
|
||||||
case 'Widget':
|
case "Widget":
|
||||||
let fieldType = getInheritableProperty({ dict, key: 'FT', });
|
let fieldType = getInheritableProperty({ dict, key: "FT" });
|
||||||
fieldType = isName(fieldType) ? fieldType.name : null;
|
fieldType = isName(fieldType) ? fieldType.name : null;
|
||||||
|
|
||||||
switch (fieldType) {
|
switch (fieldType) {
|
||||||
case 'Tx':
|
case "Tx":
|
||||||
return new TextWidgetAnnotation(parameters);
|
return new TextWidgetAnnotation(parameters);
|
||||||
case 'Btn':
|
case "Btn":
|
||||||
return new ButtonWidgetAnnotation(parameters);
|
return new ButtonWidgetAnnotation(parameters);
|
||||||
case 'Ch':
|
case "Ch":
|
||||||
return new ChoiceWidgetAnnotation(parameters);
|
return new ChoiceWidgetAnnotation(parameters);
|
||||||
}
|
}
|
||||||
warn('Unimplemented widget field type "' + fieldType + '", ' +
|
warn(
|
||||||
'falling back to base field type.');
|
'Unimplemented widget field type "' +
|
||||||
|
fieldType +
|
||||||
|
'", ' +
|
||||||
|
"falling back to base field type."
|
||||||
|
);
|
||||||
return new WidgetAnnotation(parameters);
|
return new WidgetAnnotation(parameters);
|
||||||
|
|
||||||
case 'Popup':
|
case "Popup":
|
||||||
return new PopupAnnotation(parameters);
|
return new PopupAnnotation(parameters);
|
||||||
|
|
||||||
case 'FreeText':
|
case "FreeText":
|
||||||
return new FreeTextAnnotation(parameters);
|
return new FreeTextAnnotation(parameters);
|
||||||
|
|
||||||
case 'Line':
|
case "Line":
|
||||||
return new LineAnnotation(parameters);
|
return new LineAnnotation(parameters);
|
||||||
|
|
||||||
case 'Square':
|
case "Square":
|
||||||
return new SquareAnnotation(parameters);
|
return new SquareAnnotation(parameters);
|
||||||
|
|
||||||
case 'Circle':
|
case "Circle":
|
||||||
return new CircleAnnotation(parameters);
|
return new CircleAnnotation(parameters);
|
||||||
|
|
||||||
case 'PolyLine':
|
case "PolyLine":
|
||||||
return new PolylineAnnotation(parameters);
|
return new PolylineAnnotation(parameters);
|
||||||
|
|
||||||
case 'Polygon':
|
case "Polygon":
|
||||||
return new PolygonAnnotation(parameters);
|
return new PolygonAnnotation(parameters);
|
||||||
|
|
||||||
case 'Caret':
|
case "Caret":
|
||||||
return new CaretAnnotation(parameters);
|
return new CaretAnnotation(parameters);
|
||||||
|
|
||||||
case 'Ink':
|
case "Ink":
|
||||||
return new InkAnnotation(parameters);
|
return new InkAnnotation(parameters);
|
||||||
|
|
||||||
case 'Highlight':
|
case "Highlight":
|
||||||
return new HighlightAnnotation(parameters);
|
return new HighlightAnnotation(parameters);
|
||||||
|
|
||||||
case 'Underline':
|
case "Underline":
|
||||||
return new UnderlineAnnotation(parameters);
|
return new UnderlineAnnotation(parameters);
|
||||||
|
|
||||||
case 'Squiggly':
|
case "Squiggly":
|
||||||
return new SquigglyAnnotation(parameters);
|
return new SquigglyAnnotation(parameters);
|
||||||
|
|
||||||
case 'StrikeOut':
|
case "StrikeOut":
|
||||||
return new StrikeOutAnnotation(parameters);
|
return new StrikeOutAnnotation(parameters);
|
||||||
|
|
||||||
case 'Stamp':
|
case "Stamp":
|
||||||
return new StampAnnotation(parameters);
|
return new StampAnnotation(parameters);
|
||||||
|
|
||||||
case 'FileAttachment':
|
case "FileAttachment":
|
||||||
return new FileAttachmentAnnotation(parameters);
|
return new FileAttachmentAnnotation(parameters);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!subtype) {
|
if (!subtype) {
|
||||||
warn('Annotation is missing the required /Subtype.');
|
warn("Annotation is missing the required /Subtype.");
|
||||||
} else {
|
} else {
|
||||||
warn('Unimplemented annotation type "' + subtype + '", ' +
|
warn(
|
||||||
'falling back to base annotation.');
|
'Unimplemented annotation type "' +
|
||||||
|
subtype +
|
||||||
|
'", ' +
|
||||||
|
"falling back to base annotation."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return new Annotation(parameters);
|
return new Annotation(parameters);
|
||||||
}
|
}
|
||||||
@ -148,13 +169,13 @@ class AnnotationFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getQuadPoints(dict, rect) {
|
function getQuadPoints(dict, rect) {
|
||||||
if (!dict.has('QuadPoints')) {
|
if (!dict.has("QuadPoints")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The region is described as a number of quadrilaterals.
|
// The region is described as a number of quadrilaterals.
|
||||||
// Each quadrilateral must consist of eight coordinates.
|
// Each quadrilateral must consist of eight coordinates.
|
||||||
const quadPoints = dict.getArray('QuadPoints');
|
const quadPoints = dict.getArray("QuadPoints");
|
||||||
if (!Array.isArray(quadPoints) || quadPoints.length % 8 > 0) {
|
if (!Array.isArray(quadPoints) || quadPoints.length % 8 > 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -165,7 +186,7 @@ function getQuadPoints(dict, rect) {
|
|||||||
// quadrilateral in the order [x1, y1, x2, y2, x3, y3, x4, y4].
|
// quadrilateral in the order [x1, y1, x2, y2, x3, y3, x4, y4].
|
||||||
// Convert this to an array of objects with x and y coordinates.
|
// Convert this to an array of objects with x and y coordinates.
|
||||||
quadPointsLists.push([]);
|
quadPointsLists.push([]);
|
||||||
for (let j = i * 8, jj = (i * 8) + 8; j < jj; j += 2) {
|
for (let j = i * 8, jj = i * 8 + 8; j < jj; j += 2) {
|
||||||
const x = quadPoints[j];
|
const x = quadPoints[j];
|
||||||
const y = quadPoints[j + 1];
|
const y = quadPoints[j + 1];
|
||||||
|
|
||||||
@ -174,7 +195,7 @@ function getQuadPoints(dict, rect) {
|
|||||||
if (x < rect[0] || x > rect[2] || y < rect[1] || y > rect[3]) {
|
if (x < rect[0] || x > rect[2] || y < rect[1] || y > rect[3]) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
quadPointsLists[i].push({ x, y, });
|
quadPointsLists[i].push({ x, y });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return quadPointsLists;
|
return quadPointsLists;
|
||||||
@ -182,8 +203,10 @@ function getQuadPoints(dict, rect) {
|
|||||||
|
|
||||||
function getTransformMatrix(rect, bbox, matrix) {
|
function getTransformMatrix(rect, bbox, matrix) {
|
||||||
// 12.5.5: Algorithm: Appearance streams
|
// 12.5.5: Algorithm: Appearance streams
|
||||||
const [minX, minY, maxX, maxY] =
|
const [minX, minY, maxX, maxY] = Util.getAxialAlignedBoundingBox(
|
||||||
Util.getAxialAlignedBoundingBox(bbox, matrix);
|
bbox,
|
||||||
|
matrix
|
||||||
|
);
|
||||||
if (minX === maxX || minY === maxY) {
|
if (minX === maxX || minY === maxY) {
|
||||||
// From real-life file, bbox was [0, 0, 0, 0]. In this case,
|
// From real-life file, bbox was [0, 0, 0, 0]. In this case,
|
||||||
// just apply the transform for rect
|
// just apply the transform for rect
|
||||||
@ -198,7 +221,7 @@ function getTransformMatrix(rect, bbox, matrix) {
|
|||||||
0,
|
0,
|
||||||
yRatio,
|
yRatio,
|
||||||
rect[0] - minX * xRatio,
|
rect[0] - minX * xRatio,
|
||||||
rect[1] - minY * yRatio
|
rect[1] - minY * yRatio,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,11 +229,11 @@ class Annotation {
|
|||||||
constructor(params) {
|
constructor(params) {
|
||||||
const dict = params.dict;
|
const dict = params.dict;
|
||||||
|
|
||||||
this.setContents(dict.get('Contents'));
|
this.setContents(dict.get("Contents"));
|
||||||
this.setModificationDate(dict.get('M'));
|
this.setModificationDate(dict.get("M"));
|
||||||
this.setFlags(dict.get('F'));
|
this.setFlags(dict.get("F"));
|
||||||
this.setRectangle(dict.getArray('Rect'));
|
this.setRectangle(dict.getArray("Rect"));
|
||||||
this.setColor(dict.getArray('C'));
|
this.setColor(dict.getArray("C"));
|
||||||
this.setBorderStyle(dict);
|
this.setBorderStyle(dict);
|
||||||
this.setAppearance(dict);
|
this.setAppearance(dict);
|
||||||
|
|
||||||
@ -239,18 +262,22 @@ class Annotation {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_isViewable(flags) {
|
_isViewable(flags) {
|
||||||
return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
return (
|
||||||
|
!this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
||||||
!this._hasFlag(flags, AnnotationFlag.HIDDEN) &&
|
!this._hasFlag(flags, AnnotationFlag.HIDDEN) &&
|
||||||
!this._hasFlag(flags, AnnotationFlag.NOVIEW);
|
!this._hasFlag(flags, AnnotationFlag.NOVIEW)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_isPrintable(flags) {
|
_isPrintable(flags) {
|
||||||
return this._hasFlag(flags, AnnotationFlag.PRINT) &&
|
return (
|
||||||
|
this._hasFlag(flags, AnnotationFlag.PRINT) &&
|
||||||
!this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
!this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
||||||
!this._hasFlag(flags, AnnotationFlag.HIDDEN);
|
!this._hasFlag(flags, AnnotationFlag.HIDDEN)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -283,7 +310,7 @@ class Annotation {
|
|||||||
* description of the annotation's contents
|
* description of the annotation's contents
|
||||||
*/
|
*/
|
||||||
setContents(contents) {
|
setContents(contents) {
|
||||||
this.contents = stringToPDFString(contents || '');
|
this.contents = stringToPDFString(contents || "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -295,8 +322,9 @@ class Annotation {
|
|||||||
* annotation was last modified
|
* annotation was last modified
|
||||||
*/
|
*/
|
||||||
setModificationDate(modificationDate) {
|
setModificationDate(modificationDate) {
|
||||||
this.modificationDate = isString(modificationDate) ?
|
this.modificationDate = isString(modificationDate)
|
||||||
modificationDate : null;
|
? modificationDate
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -309,7 +337,7 @@ class Annotation {
|
|||||||
* @see {@link shared/util.js}
|
* @see {@link shared/util.js}
|
||||||
*/
|
*/
|
||||||
setFlags(flags) {
|
setFlags(flags) {
|
||||||
this.flags = (Number.isInteger(flags) && flags > 0) ? flags : 0;
|
this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -392,32 +420,35 @@ class Annotation {
|
|||||||
* @param {Dict} borderStyle - The border style dictionary
|
* @param {Dict} borderStyle - The border style dictionary
|
||||||
*/
|
*/
|
||||||
setBorderStyle(borderStyle) {
|
setBorderStyle(borderStyle) {
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
assert(this.rectangle, 'setRectangle must have been called previously.');
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
|
) {
|
||||||
|
assert(this.rectangle, "setRectangle must have been called previously.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.borderStyle = new AnnotationBorderStyle();
|
this.borderStyle = new AnnotationBorderStyle();
|
||||||
if (!isDict(borderStyle)) {
|
if (!isDict(borderStyle)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (borderStyle.has('BS')) {
|
if (borderStyle.has("BS")) {
|
||||||
const dict = borderStyle.get('BS');
|
const dict = borderStyle.get("BS");
|
||||||
const dictType = dict.get('Type');
|
const dictType = dict.get("Type");
|
||||||
|
|
||||||
if (!dictType || isName(dictType, 'Border')) {
|
if (!dictType || isName(dictType, "Border")) {
|
||||||
this.borderStyle.setWidth(dict.get('W'), this.rectangle);
|
this.borderStyle.setWidth(dict.get("W"), this.rectangle);
|
||||||
this.borderStyle.setStyle(dict.get('S'));
|
this.borderStyle.setStyle(dict.get("S"));
|
||||||
this.borderStyle.setDashArray(dict.getArray('D'));
|
this.borderStyle.setDashArray(dict.getArray("D"));
|
||||||
}
|
}
|
||||||
} else if (borderStyle.has('Border')) {
|
} else if (borderStyle.has("Border")) {
|
||||||
const array = borderStyle.getArray('Border');
|
const array = borderStyle.getArray("Border");
|
||||||
if (Array.isArray(array) && array.length >= 3) {
|
if (Array.isArray(array) && array.length >= 3) {
|
||||||
this.borderStyle.setHorizontalCornerRadius(array[0]);
|
this.borderStyle.setHorizontalCornerRadius(array[0]);
|
||||||
this.borderStyle.setVerticalCornerRadius(array[1]);
|
this.borderStyle.setVerticalCornerRadius(array[1]);
|
||||||
this.borderStyle.setWidth(array[2], this.rectangle);
|
this.borderStyle.setWidth(array[2], this.rectangle);
|
||||||
|
|
||||||
if (array.length === 4) { // Dash array available
|
if (array.length === 4) {
|
||||||
|
// Dash array available
|
||||||
this.borderStyle.setDashArray(array[3]);
|
this.borderStyle.setDashArray(array[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,13 +472,13 @@ class Annotation {
|
|||||||
setAppearance(dict) {
|
setAppearance(dict) {
|
||||||
this.appearance = null;
|
this.appearance = null;
|
||||||
|
|
||||||
const appearanceStates = dict.get('AP');
|
const appearanceStates = dict.get("AP");
|
||||||
if (!isDict(appearanceStates)) {
|
if (!isDict(appearanceStates)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case the normal appearance is a stream, then it is used directly.
|
// In case the normal appearance is a stream, then it is used directly.
|
||||||
const normalAppearanceState = appearanceStates.get('N');
|
const normalAppearanceState = appearanceStates.get("N");
|
||||||
if (isStream(normalAppearanceState)) {
|
if (isStream(normalAppearanceState)) {
|
||||||
this.appearance = normalAppearanceState;
|
this.appearance = normalAppearanceState;
|
||||||
return;
|
return;
|
||||||
@ -458,7 +489,7 @@ class Annotation {
|
|||||||
|
|
||||||
// In case the normal appearance is a dictionary, the `AS` entry provides
|
// In case the normal appearance is a dictionary, the `AS` entry provides
|
||||||
// the key of the stream in this dictionary.
|
// the key of the stream in this dictionary.
|
||||||
const as = dict.get('AS');
|
const as = dict.get("AS");
|
||||||
if (!isName(as) || !normalAppearanceState.has(as.name)) {
|
if (!isName(as) || !normalAppearanceState.has(as.name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -466,7 +497,7 @@ class Annotation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadResources(keys) {
|
loadResources(keys) {
|
||||||
return this.appearance.dict.getAsync('Resources').then((resources) => {
|
return this.appearance.dict.getAsync("Resources").then(resources => {
|
||||||
if (!resources) {
|
if (!resources) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -486,26 +517,28 @@ class Annotation {
|
|||||||
const data = this.data;
|
const data = this.data;
|
||||||
const appearanceDict = this.appearance.dict;
|
const appearanceDict = this.appearance.dict;
|
||||||
const resourcesPromise = this.loadResources([
|
const resourcesPromise = this.loadResources([
|
||||||
'ExtGState',
|
"ExtGState",
|
||||||
'ColorSpace',
|
"ColorSpace",
|
||||||
'Pattern',
|
"Pattern",
|
||||||
'Shading',
|
"Shading",
|
||||||
'XObject',
|
"XObject",
|
||||||
'Font',
|
"Font",
|
||||||
]);
|
]);
|
||||||
const bbox = appearanceDict.getArray('BBox') || [0, 0, 1, 1];
|
const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
|
||||||
const matrix = appearanceDict.getArray('Matrix') || [1, 0, 0, 1, 0, 0];
|
const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
|
||||||
const transform = getTransformMatrix(data.rect, bbox, matrix);
|
const transform = getTransformMatrix(data.rect, bbox, matrix);
|
||||||
|
|
||||||
return resourcesPromise.then((resources) => {
|
return resourcesPromise.then(resources => {
|
||||||
const opList = new OperatorList();
|
const opList = new OperatorList();
|
||||||
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
|
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
|
||||||
return evaluator.getOperatorList({
|
return evaluator
|
||||||
|
.getOperatorList({
|
||||||
stream: this.appearance,
|
stream: this.appearance,
|
||||||
task,
|
task,
|
||||||
resources,
|
resources,
|
||||||
operatorList: opList,
|
operatorList: opList,
|
||||||
}).then(() => {
|
})
|
||||||
|
.then(() => {
|
||||||
opList.addOp(OPS.endAnnotation, []);
|
opList.addOp(OPS.endAnnotation, []);
|
||||||
this.appearance.reset();
|
this.appearance.reset();
|
||||||
return opList;
|
return opList;
|
||||||
@ -535,10 +568,14 @@ class AnnotationBorderStyle {
|
|||||||
* @param {Array} rect - The annotation `Rect` entry.
|
* @param {Array} rect - The annotation `Rect` entry.
|
||||||
*/
|
*/
|
||||||
setWidth(width, rect = [0, 0, 0, 0]) {
|
setWidth(width, rect = [0, 0, 0, 0]) {
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
assert(Array.isArray(rect) && rect.length === 4,
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
'A valid `rect` parameter must be provided.');
|
) {
|
||||||
|
assert(
|
||||||
|
Array.isArray(rect) && rect.length === 4,
|
||||||
|
"A valid `rect` parameter must be provided."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some corrupt PDF generators may provide the width as a `Name`,
|
// Some corrupt PDF generators may provide the width as a `Name`,
|
||||||
@ -555,8 +592,11 @@ class AnnotationBorderStyle {
|
|||||||
// Ignore large `width`s, since they lead to the Annotation overflowing
|
// Ignore large `width`s, since they lead to the Annotation overflowing
|
||||||
// the size set by the `Rect` entry thus causing the `annotationLayer`
|
// the size set by the `Rect` entry thus causing the `annotationLayer`
|
||||||
// to render it over the surrounding document (fixes bug1552113.pdf).
|
// to render it over the surrounding document (fixes bug1552113.pdf).
|
||||||
if ((maxWidth > 0 && maxHeight > 0) &&
|
if (
|
||||||
(width > maxWidth || width > maxHeight)) {
|
maxWidth > 0 &&
|
||||||
|
maxHeight > 0 &&
|
||||||
|
(width > maxWidth || width > maxHeight)
|
||||||
|
) {
|
||||||
warn(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`);
|
warn(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`);
|
||||||
width = 1;
|
width = 1;
|
||||||
}
|
}
|
||||||
@ -578,23 +618,23 @@ class AnnotationBorderStyle {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (style.name) {
|
switch (style.name) {
|
||||||
case 'S':
|
case "S":
|
||||||
this.style = AnnotationBorderStyleType.SOLID;
|
this.style = AnnotationBorderStyleType.SOLID;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case "D":
|
||||||
this.style = AnnotationBorderStyleType.DASHED;
|
this.style = AnnotationBorderStyleType.DASHED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'B':
|
case "B":
|
||||||
this.style = AnnotationBorderStyleType.BEVELED;
|
this.style = AnnotationBorderStyleType.BEVELED;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'I':
|
case "I":
|
||||||
this.style = AnnotationBorderStyleType.INSET;
|
this.style = AnnotationBorderStyleType.INSET;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'U':
|
case "U":
|
||||||
this.style = AnnotationBorderStyleType.UNDERLINE;
|
this.style = AnnotationBorderStyleType.UNDERLINE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -620,7 +660,7 @@ class AnnotationBorderStyle {
|
|||||||
let isValid = true;
|
let isValid = true;
|
||||||
let allZeros = true;
|
let allZeros = true;
|
||||||
for (const element of dashArray) {
|
for (const element of dashArray) {
|
||||||
const validNumber = (+element >= 0);
|
const validNumber = +element >= 0;
|
||||||
if (!validNumber) {
|
if (!validNumber) {
|
||||||
isValid = false;
|
isValid = false;
|
||||||
break;
|
break;
|
||||||
@ -671,56 +711,56 @@ class MarkupAnnotation extends Annotation {
|
|||||||
|
|
||||||
const dict = parameters.dict;
|
const dict = parameters.dict;
|
||||||
|
|
||||||
if (dict.has('IRT')) {
|
if (dict.has("IRT")) {
|
||||||
const rawIRT = dict.getRaw('IRT');
|
const rawIRT = dict.getRaw("IRT");
|
||||||
this.data.inReplyTo = isRef(rawIRT) ? rawIRT.toString() : null;
|
this.data.inReplyTo = isRef(rawIRT) ? rawIRT.toString() : null;
|
||||||
|
|
||||||
const rt = dict.get('RT');
|
const rt = dict.get("RT");
|
||||||
this.data.replyType = isName(rt) ? rt.name : AnnotationReplyType.REPLY;
|
this.data.replyType = isName(rt) ? rt.name : AnnotationReplyType.REPLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.data.replyType === AnnotationReplyType.GROUP) {
|
if (this.data.replyType === AnnotationReplyType.GROUP) {
|
||||||
// Subordinate annotations in a group should inherit
|
// Subordinate annotations in a group should inherit
|
||||||
// the group attributes from the primary annotation.
|
// the group attributes from the primary annotation.
|
||||||
const parent = dict.get('IRT');
|
const parent = dict.get("IRT");
|
||||||
|
|
||||||
this.data.title = stringToPDFString(parent.get('T') || '');
|
this.data.title = stringToPDFString(parent.get("T") || "");
|
||||||
|
|
||||||
this.setContents(parent.get('Contents'));
|
this.setContents(parent.get("Contents"));
|
||||||
this.data.contents = this.contents;
|
this.data.contents = this.contents;
|
||||||
|
|
||||||
if (!parent.has('CreationDate')) {
|
if (!parent.has("CreationDate")) {
|
||||||
this.data.creationDate = null;
|
this.data.creationDate = null;
|
||||||
} else {
|
} else {
|
||||||
this.setCreationDate(parent.get('CreationDate'));
|
this.setCreationDate(parent.get("CreationDate"));
|
||||||
this.data.creationDate = this.creationDate;
|
this.data.creationDate = this.creationDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parent.has('M')) {
|
if (!parent.has("M")) {
|
||||||
this.data.modificationDate = null;
|
this.data.modificationDate = null;
|
||||||
} else {
|
} else {
|
||||||
this.setModificationDate(parent.get('M'));
|
this.setModificationDate(parent.get("M"));
|
||||||
this.data.modificationDate = this.modificationDate;
|
this.data.modificationDate = this.modificationDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data.hasPopup = parent.has('Popup');
|
this.data.hasPopup = parent.has("Popup");
|
||||||
|
|
||||||
if (!parent.has('C')) {
|
if (!parent.has("C")) {
|
||||||
// Fall back to the default background color.
|
// Fall back to the default background color.
|
||||||
this.data.color = null;
|
this.data.color = null;
|
||||||
} else {
|
} else {
|
||||||
this.setColor(parent.getArray('C'));
|
this.setColor(parent.getArray("C"));
|
||||||
this.data.color = this.color;
|
this.data.color = this.color;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.data.title = stringToPDFString(dict.get('T') || '');
|
this.data.title = stringToPDFString(dict.get("T") || "");
|
||||||
|
|
||||||
this.setCreationDate(dict.get('CreationDate'));
|
this.setCreationDate(dict.get("CreationDate"));
|
||||||
this.data.creationDate = this.creationDate;
|
this.data.creationDate = this.creationDate;
|
||||||
|
|
||||||
this.data.hasPopup = dict.has('Popup');
|
this.data.hasPopup = dict.has("Popup");
|
||||||
|
|
||||||
if (!dict.has('C')) {
|
if (!dict.has("C")) {
|
||||||
// Fall back to the default background color.
|
// Fall back to the default background color.
|
||||||
this.data.color = null;
|
this.data.color = null;
|
||||||
}
|
}
|
||||||
@ -749,16 +789,19 @@ class WidgetAnnotation extends Annotation {
|
|||||||
|
|
||||||
data.annotationType = AnnotationType.WIDGET;
|
data.annotationType = AnnotationType.WIDGET;
|
||||||
data.fieldName = this._constructFieldName(dict);
|
data.fieldName = this._constructFieldName(dict);
|
||||||
data.fieldValue = getInheritableProperty({ dict, key: 'V',
|
data.fieldValue = getInheritableProperty({
|
||||||
getArray: true, });
|
dict,
|
||||||
data.alternativeText = stringToPDFString(dict.get('TU') || '');
|
key: "V",
|
||||||
data.defaultAppearance = getInheritableProperty({ dict, key: 'DA', }) || '';
|
getArray: true,
|
||||||
const fieldType = getInheritableProperty({ dict, key: 'FT', });
|
});
|
||||||
|
data.alternativeText = stringToPDFString(dict.get("TU") || "");
|
||||||
|
data.defaultAppearance = getInheritableProperty({ dict, key: "DA" }) || "";
|
||||||
|
const fieldType = getInheritableProperty({ dict, key: "FT" });
|
||||||
data.fieldType = isName(fieldType) ? fieldType.name : null;
|
data.fieldType = isName(fieldType) ? fieldType.name : null;
|
||||||
this.fieldResources = getInheritableProperty({ dict, key: 'DR', }) ||
|
this.fieldResources =
|
||||||
Dict.empty;
|
getInheritableProperty({ dict, key: "DR" }) || Dict.empty;
|
||||||
|
|
||||||
data.fieldFlags = getInheritableProperty({ dict, key: 'Ff', });
|
data.fieldFlags = getInheritableProperty({ dict, key: "Ff" });
|
||||||
if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) {
|
if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) {
|
||||||
data.fieldFlags = 0;
|
data.fieldFlags = 0;
|
||||||
}
|
}
|
||||||
@ -768,7 +811,7 @@ class WidgetAnnotation extends Annotation {
|
|||||||
// Hide signatures because we cannot validate them, and unset the fieldValue
|
// Hide signatures because we cannot validate them, and unset the fieldValue
|
||||||
// since it's (most likely) a `Dict` which is non-serializable and will thus
|
// since it's (most likely) a `Dict` which is non-serializable and will thus
|
||||||
// cause errors when sending annotations to the main-thread (issue 10347).
|
// cause errors when sending annotations to the main-thread (issue 10347).
|
||||||
if (data.fieldType === 'Sig') {
|
if (data.fieldType === "Sig") {
|
||||||
data.fieldValue = null;
|
data.fieldValue = null;
|
||||||
this.setFlags(AnnotationFlag.HIDDEN);
|
this.setFlags(AnnotationFlag.HIDDEN);
|
||||||
}
|
}
|
||||||
@ -786,26 +829,26 @@ class WidgetAnnotation extends Annotation {
|
|||||||
_constructFieldName(dict) {
|
_constructFieldName(dict) {
|
||||||
// Both the `Parent` and `T` fields are optional. While at least one of
|
// Both the `Parent` and `T` fields are optional. While at least one of
|
||||||
// them should be provided, bad PDF generators may fail to do so.
|
// them should be provided, bad PDF generators may fail to do so.
|
||||||
if (!dict.has('T') && !dict.has('Parent')) {
|
if (!dict.has("T") && !dict.has("Parent")) {
|
||||||
warn('Unknown field name, falling back to empty field name.');
|
warn("Unknown field name, falling back to empty field name.");
|
||||||
return '';
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// If no parent exists, the partial and fully qualified names are equal.
|
// If no parent exists, the partial and fully qualified names are equal.
|
||||||
if (!dict.has('Parent')) {
|
if (!dict.has("Parent")) {
|
||||||
return stringToPDFString(dict.get('T'));
|
return stringToPDFString(dict.get("T"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form the fully qualified field name by appending the partial name to
|
// Form the fully qualified field name by appending the partial name to
|
||||||
// the parent's fully qualified name, separated by a period.
|
// the parent's fully qualified name, separated by a period.
|
||||||
const fieldName = [];
|
const fieldName = [];
|
||||||
if (dict.has('T')) {
|
if (dict.has("T")) {
|
||||||
fieldName.unshift(stringToPDFString(dict.get('T')));
|
fieldName.unshift(stringToPDFString(dict.get("T")));
|
||||||
}
|
}
|
||||||
|
|
||||||
let loopDict = dict;
|
let loopDict = dict;
|
||||||
while (loopDict.has('Parent')) {
|
while (loopDict.has("Parent")) {
|
||||||
loopDict = loopDict.get('Parent');
|
loopDict = loopDict.get("Parent");
|
||||||
if (!isDict(loopDict)) {
|
if (!isDict(loopDict)) {
|
||||||
// Even though it is not allowed according to the PDF specification,
|
// Even though it is not allowed according to the PDF specification,
|
||||||
// bad PDF generators may provide a `Parent` entry that is not a
|
// bad PDF generators may provide a `Parent` entry that is not a
|
||||||
@ -813,11 +856,11 @@ class WidgetAnnotation extends Annotation {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loopDict.has('T')) {
|
if (loopDict.has("T")) {
|
||||||
fieldName.unshift(stringToPDFString(loopDict.get('T')));
|
fieldName.unshift(stringToPDFString(loopDict.get("T")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fieldName.join('.');
|
return fieldName.join(".");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -851,17 +894,17 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
|||||||
const dict = params.dict;
|
const dict = params.dict;
|
||||||
|
|
||||||
// The field value is always a string.
|
// The field value is always a string.
|
||||||
this.data.fieldValue = stringToPDFString(this.data.fieldValue || '');
|
this.data.fieldValue = stringToPDFString(this.data.fieldValue || "");
|
||||||
|
|
||||||
// Determine the alignment of text in the field.
|
// Determine the alignment of text in the field.
|
||||||
let alignment = getInheritableProperty({ dict, key: 'Q', });
|
let alignment = getInheritableProperty({ dict, key: "Q" });
|
||||||
if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {
|
if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {
|
||||||
alignment = null;
|
alignment = null;
|
||||||
}
|
}
|
||||||
this.data.textAlignment = alignment;
|
this.data.textAlignment = alignment;
|
||||||
|
|
||||||
// Determine the maximum length of text in the field.
|
// Determine the maximum length of text in the field.
|
||||||
let maximumLength = getInheritableProperty({ dict, key: 'MaxLen', });
|
let maximumLength = getInheritableProperty({ dict, key: "MaxLen" });
|
||||||
if (!Number.isInteger(maximumLength) || maximumLength < 0) {
|
if (!Number.isInteger(maximumLength) || maximumLength < 0) {
|
||||||
maximumLength = null;
|
maximumLength = null;
|
||||||
}
|
}
|
||||||
@ -869,7 +912,8 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
|||||||
|
|
||||||
// Process field flags for the display layer.
|
// Process field flags for the display layer.
|
||||||
this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE);
|
this.data.multiLine = this.hasFieldFlag(AnnotationFieldFlag.MULTILINE);
|
||||||
this.data.comb = this.hasFieldFlag(AnnotationFieldFlag.COMB) &&
|
this.data.comb =
|
||||||
|
this.hasFieldFlag(AnnotationFieldFlag.COMB) &&
|
||||||
!this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) &&
|
!this.hasFieldFlag(AnnotationFieldFlag.MULTILINE) &&
|
||||||
!this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) &&
|
!this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) &&
|
||||||
!this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
|
!this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
|
||||||
@ -890,12 +934,14 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const stream = new Stream(stringToBytes(this.data.defaultAppearance));
|
const stream = new Stream(stringToBytes(this.data.defaultAppearance));
|
||||||
return evaluator.getOperatorList({
|
return evaluator
|
||||||
|
.getOperatorList({
|
||||||
stream,
|
stream,
|
||||||
task,
|
task,
|
||||||
resources: this.fieldResources,
|
resources: this.fieldResources,
|
||||||
operatorList,
|
operatorList,
|
||||||
}).then(function () {
|
})
|
||||||
|
.then(function() {
|
||||||
return operatorList;
|
return operatorList;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -905,9 +951,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||||||
constructor(params) {
|
constructor(params) {
|
||||||
super(params);
|
super(params);
|
||||||
|
|
||||||
this.data.checkBox = !this.hasFieldFlag(AnnotationFieldFlag.RADIO) &&
|
this.data.checkBox =
|
||||||
|
!this.hasFieldFlag(AnnotationFieldFlag.RADIO) &&
|
||||||
!this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
!this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
||||||
this.data.radioButton = this.hasFieldFlag(AnnotationFieldFlag.RADIO) &&
|
this.data.radioButton =
|
||||||
|
this.hasFieldFlag(AnnotationFieldFlag.RADIO) &&
|
||||||
!this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
!this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
||||||
this.data.pushButton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
this.data.pushButton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
||||||
|
|
||||||
@ -918,7 +966,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||||||
} else if (this.data.pushButton) {
|
} else if (this.data.pushButton) {
|
||||||
this._processPushButton(params);
|
this._processPushButton(params);
|
||||||
} else {
|
} else {
|
||||||
warn('Invalid field flags for button widget annotation');
|
warn("Invalid field flags for button widget annotation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -927,12 +975,12 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||||||
this.data.fieldValue = this.data.fieldValue.name;
|
this.data.fieldValue = this.data.fieldValue.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const customAppearance = params.dict.get('AP');
|
const customAppearance = params.dict.get("AP");
|
||||||
if (!isDict(customAppearance)) {
|
if (!isDict(customAppearance)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const exportValueOptionsDict = customAppearance.get('D');
|
const exportValueOptionsDict = customAppearance.get("D");
|
||||||
if (!isDict(exportValueOptionsDict)) {
|
if (!isDict(exportValueOptionsDict)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -943,8 +991,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data.exportValue = exportValues[0] === 'Off' ?
|
this.data.exportValue =
|
||||||
exportValues[1] : exportValues[0];
|
exportValues[0] === "Off" ? exportValues[1] : exportValues[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
_processRadioButton(params) {
|
_processRadioButton(params) {
|
||||||
@ -952,25 +1000,25 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||||||
|
|
||||||
// The parent field's `V` entry holds a `Name` object with the appearance
|
// The parent field's `V` entry holds a `Name` object with the appearance
|
||||||
// state of whichever child field is currently in the "on" state.
|
// state of whichever child field is currently in the "on" state.
|
||||||
const fieldParent = params.dict.get('Parent');
|
const fieldParent = params.dict.get("Parent");
|
||||||
if (isDict(fieldParent) && fieldParent.has('V')) {
|
if (isDict(fieldParent) && fieldParent.has("V")) {
|
||||||
const fieldParentValue = fieldParent.get('V');
|
const fieldParentValue = fieldParent.get("V");
|
||||||
if (isName(fieldParentValue)) {
|
if (isName(fieldParentValue)) {
|
||||||
this.data.fieldValue = fieldParentValue.name;
|
this.data.fieldValue = fieldParentValue.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The button's value corresponds to its appearance state.
|
// The button's value corresponds to its appearance state.
|
||||||
const appearanceStates = params.dict.get('AP');
|
const appearanceStates = params.dict.get("AP");
|
||||||
if (!isDict(appearanceStates)) {
|
if (!isDict(appearanceStates)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const normalAppearanceState = appearanceStates.get('N');
|
const normalAppearanceState = appearanceStates.get("N");
|
||||||
if (!isDict(normalAppearanceState)) {
|
if (!isDict(normalAppearanceState)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const key of normalAppearanceState.getKeys()) {
|
for (const key of normalAppearanceState.getKeys()) {
|
||||||
if (key !== 'Off') {
|
if (key !== "Off") {
|
||||||
this.data.buttonValue = key;
|
this.data.buttonValue = key;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -978,8 +1026,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_processPushButton(params) {
|
_processPushButton(params) {
|
||||||
if (!params.dict.has('A')) {
|
if (!params.dict.has("A")) {
|
||||||
warn('Push buttons without action dictionaries are not supported');
|
warn("Push buttons without action dictionaries are not supported");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,7 +1054,7 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
|
|||||||
// inherit the options from a parent annotation (issue 8094).
|
// inherit the options from a parent annotation (issue 8094).
|
||||||
this.data.options = [];
|
this.data.options = [];
|
||||||
|
|
||||||
const options = getInheritableProperty({ dict: params.dict, key: 'Opt', });
|
const options = getInheritableProperty({ dict: params.dict, key: "Opt" });
|
||||||
if (Array.isArray(options)) {
|
if (Array.isArray(options)) {
|
||||||
const xref = params.xref;
|
const xref = params.xref;
|
||||||
for (let i = 0, ii = options.length; i < ii; i++) {
|
for (let i = 0, ii = options.length; i < ii; i++) {
|
||||||
@ -1015,8 +1063,9 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
|
|||||||
|
|
||||||
this.data.options[i] = {
|
this.data.options[i] = {
|
||||||
exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option,
|
exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option,
|
||||||
displayValue: stringToPDFString(isOptionArray ?
|
displayValue: stringToPDFString(
|
||||||
xref.fetchIfRef(option[1]) : option),
|
isOptionArray ? xref.fetchIfRef(option[1]) : option
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1044,17 +1093,16 @@ class TextAnnotation extends MarkupAnnotation {
|
|||||||
this.data.annotationType = AnnotationType.TEXT;
|
this.data.annotationType = AnnotationType.TEXT;
|
||||||
|
|
||||||
if (this.data.hasAppearance) {
|
if (this.data.hasAppearance) {
|
||||||
this.data.name = 'NoIcon';
|
this.data.name = "NoIcon";
|
||||||
} else {
|
} else {
|
||||||
this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;
|
this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;
|
||||||
this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;
|
this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;
|
||||||
this.data.name = dict.has('Name') ?
|
this.data.name = dict.has("Name") ? dict.get("Name").name : "Note";
|
||||||
dict.get('Name').name : 'Note';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict.has('State')) {
|
if (dict.has("State")) {
|
||||||
this.data.state = dict.get('State') || null;
|
this.data.state = dict.get("State") || null;
|
||||||
this.data.stateModel = dict.get('StateModel') || null;
|
this.data.stateModel = dict.get("StateModel") || null;
|
||||||
} else {
|
} else {
|
||||||
this.data.state = null;
|
this.data.state = null;
|
||||||
this.data.stateModel = null;
|
this.data.stateModel = null;
|
||||||
@ -1087,36 +1135,36 @@ class PopupAnnotation extends Annotation {
|
|||||||
|
|
||||||
this.data.annotationType = AnnotationType.POPUP;
|
this.data.annotationType = AnnotationType.POPUP;
|
||||||
|
|
||||||
let parentItem = parameters.dict.get('Parent');
|
let parentItem = parameters.dict.get("Parent");
|
||||||
if (!parentItem) {
|
if (!parentItem) {
|
||||||
warn('Popup annotation has a missing or invalid parent annotation.');
|
warn("Popup annotation has a missing or invalid parent annotation.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentSubtype = parentItem.get('Subtype');
|
const parentSubtype = parentItem.get("Subtype");
|
||||||
this.data.parentType = isName(parentSubtype) ? parentSubtype.name : null;
|
this.data.parentType = isName(parentSubtype) ? parentSubtype.name : null;
|
||||||
const rawParent = parameters.dict.getRaw('Parent');
|
const rawParent = parameters.dict.getRaw("Parent");
|
||||||
this.data.parentId = isRef(rawParent) ? rawParent.toString() : null;
|
this.data.parentId = isRef(rawParent) ? rawParent.toString() : null;
|
||||||
|
|
||||||
const rt = parentItem.get('RT');
|
const rt = parentItem.get("RT");
|
||||||
if (isName(rt, AnnotationReplyType.GROUP)) {
|
if (isName(rt, AnnotationReplyType.GROUP)) {
|
||||||
// Subordinate annotations in a group should inherit
|
// Subordinate annotations in a group should inherit
|
||||||
// the group attributes from the primary annotation.
|
// the group attributes from the primary annotation.
|
||||||
parentItem = parentItem.get('IRT');
|
parentItem = parentItem.get("IRT");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parentItem.has('M')) {
|
if (!parentItem.has("M")) {
|
||||||
this.data.modificationDate = null;
|
this.data.modificationDate = null;
|
||||||
} else {
|
} else {
|
||||||
this.setModificationDate(parentItem.get('M'));
|
this.setModificationDate(parentItem.get("M"));
|
||||||
this.data.modificationDate = this.modificationDate;
|
this.data.modificationDate = this.modificationDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parentItem.has('C')) {
|
if (!parentItem.has("C")) {
|
||||||
// Fall back to the default background color.
|
// Fall back to the default background color.
|
||||||
this.data.color = null;
|
this.data.color = null;
|
||||||
} else {
|
} else {
|
||||||
this.setColor(parentItem.getArray('C'));
|
this.setColor(parentItem.getArray("C"));
|
||||||
this.data.color = this.color;
|
this.data.color = this.color;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1124,14 +1172,14 @@ class PopupAnnotation extends Annotation {
|
|||||||
// that is most likely a bug. Fallback to inherit the flags from the parent
|
// that is most likely a bug. Fallback to inherit the flags from the parent
|
||||||
// annotation (this is consistent with the behaviour in Adobe Reader).
|
// annotation (this is consistent with the behaviour in Adobe Reader).
|
||||||
if (!this.viewable) {
|
if (!this.viewable) {
|
||||||
const parentFlags = parentItem.get('F');
|
const parentFlags = parentItem.get("F");
|
||||||
if (this._isViewable(parentFlags)) {
|
if (this._isViewable(parentFlags)) {
|
||||||
this.setFlags(parentFlags);
|
this.setFlags(parentFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data.title = stringToPDFString(parentItem.get('T') || '');
|
this.data.title = stringToPDFString(parentItem.get("T") || "");
|
||||||
this.data.contents = stringToPDFString(parentItem.get('Contents') || '');
|
this.data.contents = stringToPDFString(parentItem.get("Contents") || "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1149,8 +1197,9 @@ class LineAnnotation extends MarkupAnnotation {
|
|||||||
|
|
||||||
this.data.annotationType = AnnotationType.LINE;
|
this.data.annotationType = AnnotationType.LINE;
|
||||||
|
|
||||||
this.data.lineCoordinates =
|
this.data.lineCoordinates = Util.normalizeRect(
|
||||||
Util.normalizeRect(parameters.dict.getArray('L'));
|
parameters.dict.getArray("L")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1179,7 +1228,7 @@ class PolylineAnnotation extends MarkupAnnotation {
|
|||||||
// The vertices array is an array of numbers representing the alternating
|
// The vertices array is an array of numbers representing the alternating
|
||||||
// horizontal and vertical coordinates, respectively, of each vertex.
|
// horizontal and vertical coordinates, respectively, of each vertex.
|
||||||
// Convert this to an array of objects with x and y coordinates.
|
// Convert this to an array of objects with x and y coordinates.
|
||||||
const rawVertices = parameters.dict.getArray('Vertices');
|
const rawVertices = parameters.dict.getArray("Vertices");
|
||||||
this.data.vertices = [];
|
this.data.vertices = [];
|
||||||
for (let i = 0, ii = rawVertices.length; i < ii; i += 2) {
|
for (let i = 0, ii = rawVertices.length; i < ii; i += 2) {
|
||||||
this.data.vertices.push({
|
this.data.vertices.push({
|
||||||
@ -1214,7 +1263,7 @@ class InkAnnotation extends MarkupAnnotation {
|
|||||||
this.data.annotationType = AnnotationType.INK;
|
this.data.annotationType = AnnotationType.INK;
|
||||||
|
|
||||||
const xref = parameters.xref;
|
const xref = parameters.xref;
|
||||||
const originalInkLists = parameters.dict.getArray('InkList');
|
const originalInkLists = parameters.dict.getArray("InkList");
|
||||||
this.data.inkLists = [];
|
this.data.inkLists = [];
|
||||||
for (let i = 0, ii = originalInkLists.length; i < ii; ++i) {
|
for (let i = 0, ii = originalInkLists.length; i < ii; ++i) {
|
||||||
// The raw ink lists array contains arrays of numbers representing
|
// The raw ink lists array contains arrays of numbers representing
|
||||||
@ -1296,7 +1345,7 @@ class FileAttachmentAnnotation extends MarkupAnnotation {
|
|||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
super(parameters);
|
super(parameters);
|
||||||
|
|
||||||
const file = new FileSpec(parameters.dict.get('FS'), parameters.xref);
|
const file = new FileSpec(parameters.dict.get("FS"), parameters.xref);
|
||||||
|
|
||||||
this.data.annotationType = AnnotationType.FILEATTACHMENT;
|
this.data.annotationType = AnnotationType.FILEATTACHMENT;
|
||||||
this.data.file = file.serializable;
|
this.data.file = file.serializable;
|
||||||
|
@ -16,53 +16,53 @@
|
|||||||
|
|
||||||
// Table C-2
|
// Table C-2
|
||||||
const QeTable = [
|
const QeTable = [
|
||||||
{ qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1, },
|
{ qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1 },
|
||||||
{ qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0, },
|
{ qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0 },
|
||||||
{ qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0, },
|
{ qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0 },
|
||||||
{ qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0, },
|
{ qe: 0x0ac1, nmps: 4, nlps: 12, switchFlag: 0 },
|
||||||
{ qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0, },
|
{ qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0 },
|
||||||
{ qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0, },
|
{ qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0 },
|
||||||
{ qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1, },
|
{ qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1 },
|
||||||
{ qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0, },
|
{ qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0 },
|
||||||
{ qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0, },
|
{ qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0 },
|
||||||
{ qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0, },
|
{ qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0 },
|
||||||
{ qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0, },
|
{ qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0 },
|
||||||
{ qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0, },
|
{ qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0 },
|
||||||
{ qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0, },
|
{ qe: 0x1c01, nmps: 13, nlps: 20, switchFlag: 0 },
|
||||||
{ qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0, },
|
{ qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0 },
|
||||||
{ qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1, },
|
{ qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1 },
|
||||||
{ qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0, },
|
{ qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0 },
|
||||||
{ qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0, },
|
{ qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0 },
|
||||||
{ qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0, },
|
{ qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0 },
|
||||||
{ qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0, },
|
{ qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0 },
|
||||||
{ qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0, },
|
{ qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0 },
|
||||||
{ qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0, },
|
{ qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0 },
|
||||||
{ qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0, },
|
{ qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0 },
|
||||||
{ qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0, },
|
{ qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0 },
|
||||||
{ qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0, },
|
{ qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0 },
|
||||||
{ qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0, },
|
{ qe: 0x1c01, nmps: 25, nlps: 22, switchFlag: 0 },
|
||||||
{ qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0, },
|
{ qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0 },
|
||||||
{ qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0, },
|
{ qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0 },
|
||||||
{ qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0, },
|
{ qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0 },
|
||||||
{ qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0, },
|
{ qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0 },
|
||||||
{ qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0, },
|
{ qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0 },
|
||||||
{ qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0, },
|
{ qe: 0x0ac1, nmps: 31, nlps: 28, switchFlag: 0 },
|
||||||
{ qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0, },
|
{ qe: 0x09c1, nmps: 32, nlps: 29, switchFlag: 0 },
|
||||||
{ qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0, },
|
{ qe: 0x08a1, nmps: 33, nlps: 30, switchFlag: 0 },
|
||||||
{ qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0, },
|
{ qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0 },
|
||||||
{ qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0, },
|
{ qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0 },
|
||||||
{ qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0, },
|
{ qe: 0x02a1, nmps: 36, nlps: 33, switchFlag: 0 },
|
||||||
{ qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0, },
|
{ qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0 },
|
||||||
{ qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0, },
|
{ qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0 },
|
||||||
{ qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0, },
|
{ qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0 },
|
||||||
{ qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0, },
|
{ qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0 },
|
||||||
{ qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0, },
|
{ qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0 },
|
||||||
{ qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0, },
|
{ qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0 },
|
||||||
{ qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0, },
|
{ qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0 },
|
||||||
{ qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0, },
|
{ qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0 },
|
||||||
{ qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0, },
|
{ qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0 },
|
||||||
{ qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0, },
|
{ qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0 },
|
||||||
{ qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0, },
|
{ qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0 },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,8 +86,8 @@ class ArithmeticDecoder {
|
|||||||
|
|
||||||
this.byteIn();
|
this.byteIn();
|
||||||
|
|
||||||
this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F);
|
this.chigh = ((this.chigh << 7) & 0xffff) | ((this.clow >> 9) & 0x7f);
|
||||||
this.clow = (this.clow << 7) & 0xFFFF;
|
this.clow = (this.clow << 7) & 0xffff;
|
||||||
this.ct -= 7;
|
this.ct -= 7;
|
||||||
this.a = 0x8000;
|
this.a = 0x8000;
|
||||||
}
|
}
|
||||||
@ -97,25 +97,25 @@ class ArithmeticDecoder {
|
|||||||
const data = this.data;
|
const data = this.data;
|
||||||
let bp = this.bp;
|
let bp = this.bp;
|
||||||
|
|
||||||
if (data[bp] === 0xFF) {
|
if (data[bp] === 0xff) {
|
||||||
if (data[bp + 1] > 0x8F) {
|
if (data[bp + 1] > 0x8f) {
|
||||||
this.clow += 0xFF00;
|
this.clow += 0xff00;
|
||||||
this.ct = 8;
|
this.ct = 8;
|
||||||
} else {
|
} else {
|
||||||
bp++;
|
bp++;
|
||||||
this.clow += (data[bp] << 9);
|
this.clow += data[bp] << 9;
|
||||||
this.ct = 7;
|
this.ct = 7;
|
||||||
this.bp = bp;
|
this.bp = bp;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bp++;
|
bp++;
|
||||||
this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00;
|
this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xff00;
|
||||||
this.ct = 8;
|
this.ct = 8;
|
||||||
this.bp = bp;
|
this.bp = bp;
|
||||||
}
|
}
|
||||||
if (this.clow > 0xFFFF) {
|
if (this.clow > 0xffff) {
|
||||||
this.chigh += (this.clow >> 16);
|
this.chigh += this.clow >> 16;
|
||||||
this.clow &= 0xFFFF;
|
this.clow &= 0xffff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +123,8 @@ class ArithmeticDecoder {
|
|||||||
readBit(contexts, pos) {
|
readBit(contexts, pos) {
|
||||||
// Contexts are packed into 1 byte:
|
// Contexts are packed into 1 byte:
|
||||||
// highest 7 bits carry cx.index, lowest bit carries cx.mps
|
// highest 7 bits carry cx.index, lowest bit carries cx.mps
|
||||||
let cx_index = contexts[pos] >> 1, cx_mps = contexts[pos] & 1;
|
let cx_index = contexts[pos] >> 1,
|
||||||
|
cx_mps = contexts[pos] & 1;
|
||||||
const qeTableIcx = QeTable[cx_index];
|
const qeTableIcx = QeTable[cx_index];
|
||||||
const qeIcx = qeTableIcx.qe;
|
const qeIcx = qeTableIcx.qe;
|
||||||
let d;
|
let d;
|
||||||
@ -168,17 +169,15 @@ class ArithmeticDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
a <<= 1;
|
a <<= 1;
|
||||||
this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1);
|
this.chigh = ((this.chigh << 1) & 0xffff) | ((this.clow >> 15) & 1);
|
||||||
this.clow = (this.clow << 1) & 0xFFFF;
|
this.clow = (this.clow << 1) & 0xffff;
|
||||||
this.ct--;
|
this.ct--;
|
||||||
} while ((a & 0x8000) === 0);
|
} while ((a & 0x8000) === 0);
|
||||||
this.a = a;
|
this.a = a;
|
||||||
|
|
||||||
contexts[pos] = cx_index << 1 | cx_mps;
|
contexts[pos] = (cx_index << 1) | cx_mps;
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { ArithmeticDecoder };
|
||||||
ArithmeticDecoder,
|
|
||||||
};
|
|
||||||
|
181
src/core/bidi.js
181
src/core/bidi.js
@ -13,32 +13,32 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { warn } from '../shared/util';
|
import { warn } from "../shared/util";
|
||||||
|
|
||||||
// Character types for symbols from 0000 to 00FF.
|
// Character types for symbols from 0000 to 00FF.
|
||||||
// Source: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
|
// Source: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
var baseTypes = [
|
var baseTypes = [
|
||||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S',
|
"BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "S", "B", "S",
|
||||||
'WS', 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
"WS", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN",
|
||||||
'BN', 'BN', 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET',
|
"BN", "BN", "BN", "BN", "B", "B", "B", "S", "WS", "ON", "ON", "ET",
|
||||||
'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'ON', 'ES', 'CS', 'ES', 'CS', 'CS',
|
"ET", "ET", "ON", "ON", "ON", "ON", "ON", "ES", "CS", "ES", "CS", "CS",
|
||||||
'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'CS', 'ON',
|
"EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "EN", "CS", "ON",
|
||||||
'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
"ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L",
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
"L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L",
|
||||||
'L', 'L', 'L', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L',
|
"L", "L", "L", "L", "ON", "ON", "ON", "ON", "ON", "ON", "L", "L", "L",
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
"L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L",
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', 'ON', 'ON',
|
"L", "L", "L", "L", "L", "L", "L", "L", "L", "ON", "ON", "ON", "ON",
|
||||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN', 'BN', 'BN', 'BN', 'BN',
|
"BN", "BN", "BN", "BN", "BN", "BN", "B", "BN", "BN", "BN", "BN", "BN",
|
||||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
"BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN",
|
||||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'CS', 'ON', 'ET',
|
"BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "CS", "ON", "ET",
|
||||||
'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON', 'ON', 'BN', 'ON',
|
"ET", "ET", "ET", "ON", "ON", "ON", "ON", "L", "ON", "ON", "BN", "ON",
|
||||||
'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON', 'EN', 'L',
|
"ON", "ET", "ET", "EN", "EN", "ON", "L", "ON", "ON", "ON", "EN", "L",
|
||||||
'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
"ON", "ON", "ON", "ON", "ON", "L", "L", "L", "L", "L", "L", "L", "L",
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
"L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L",
|
||||||
'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
"L", "ON", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L",
|
||||||
'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
"L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L",
|
||||||
'L', 'L', 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
|
"L", "L", "L", "L", "L", "ON", "L", "L", "L", "L", "L", "L", "L", "L"
|
||||||
];
|
];
|
||||||
|
|
||||||
// Character types for symbols from 0600 to 06FF.
|
// Character types for symbols from 0600 to 06FF.
|
||||||
@ -49,28 +49,28 @@ var baseTypes = [
|
|||||||
// empty string is required to properly index the items after it.
|
// empty string is required to properly index the items after it.
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
var arabicTypes = [
|
var arabicTypes = [
|
||||||
'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'ON', 'ON', 'AL', 'ET', 'ET', 'AL',
|
"AN", "AN", "AN", "AN", "AN", "AN", "ON", "ON", "AL", "ET", "ET", "AL",
|
||||||
'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
|
"CS", "AL", "ON", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM",
|
||||||
'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', '', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"NSM", "NSM", "NSM", "NSM", "AL", "AL", "", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
|
"AL", "AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM",
|
||||||
'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
|
"NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM",
|
||||||
'NSM', 'NSM', 'NSM', 'NSM', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN',
|
"NSM", "NSM", "NSM", "NSM", "AN", "AN", "AN", "AN", "AN", "AN", "AN",
|
||||||
'AN', 'AN', 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL',
|
"AN", "AN", "AN", "ET", "AN", "AN", "AL", "AL", "AL", "NSM", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL',
|
"AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL", "AL",
|
||||||
'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AN',
|
"AL", "AL", "AL", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN",
|
||||||
'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'NSM', 'NSM',
|
"ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "NSM", "NSM",
|
||||||
'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'EN', 'EN', 'EN', 'EN',
|
"ON", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "EN", "EN", "EN", "EN",
|
||||||
'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
|
"EN", "EN", "EN", "EN", "EN", "EN", "AL", "AL", "AL", "AL", "AL", "AL"
|
||||||
];
|
];
|
||||||
|
|
||||||
function isOdd(i) {
|
function isOdd(i) {
|
||||||
@ -107,7 +107,7 @@ function reverseValues(arr, start, end) {
|
|||||||
function createBidiText(str, isLTR, vertical) {
|
function createBidiText(str, isLTR, vertical) {
|
||||||
return {
|
return {
|
||||||
str,
|
str,
|
||||||
dir: (vertical ? 'ttb' : (isLTR ? 'ltr' : 'rtl')),
|
dir: vertical ? "ttb" : isLTR ? "ltr" : "rtl",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,20 +133,20 @@ function bidi(str, startLevel, vertical) {
|
|||||||
chars[i] = str.charAt(i);
|
chars[i] = str.charAt(i);
|
||||||
|
|
||||||
var charCode = str.charCodeAt(i);
|
var charCode = str.charCodeAt(i);
|
||||||
var charType = 'L';
|
var charType = "L";
|
||||||
if (charCode <= 0x00ff) {
|
if (charCode <= 0x00ff) {
|
||||||
charType = baseTypes[charCode];
|
charType = baseTypes[charCode];
|
||||||
} else if (0x0590 <= charCode && charCode <= 0x05f4) {
|
} else if (0x0590 <= charCode && charCode <= 0x05f4) {
|
||||||
charType = 'R';
|
charType = "R";
|
||||||
} else if (0x0600 <= charCode && charCode <= 0x06ff) {
|
} else if (0x0600 <= charCode && charCode <= 0x06ff) {
|
||||||
charType = arabicTypes[charCode & 0xff];
|
charType = arabicTypes[charCode & 0xff];
|
||||||
if (!charType) {
|
if (!charType) {
|
||||||
warn('Bidi: invalid Unicode character ' + charCode.toString(16));
|
warn("Bidi: invalid Unicode character " + charCode.toString(16));
|
||||||
}
|
}
|
||||||
} else if (0x0700 <= charCode && charCode <= 0x08AC) {
|
} else if (0x0700 <= charCode && charCode <= 0x08ac) {
|
||||||
charType = 'AL';
|
charType = "AL";
|
||||||
}
|
}
|
||||||
if (charType === 'R' || charType === 'AL' || charType === 'AN') {
|
if (charType === "R" || charType === "AL" || charType === "AN") {
|
||||||
numBidi++;
|
numBidi++;
|
||||||
}
|
}
|
||||||
types[i] = charType;
|
types[i] = charType;
|
||||||
@ -162,7 +162,7 @@ function bidi(str, startLevel, vertical) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (startLevel === -1) {
|
if (startLevel === -1) {
|
||||||
if ((numBidi / strLength) < 0.3) {
|
if (numBidi / strLength < 0.3) {
|
||||||
isLTR = true;
|
isLTR = true;
|
||||||
startLevel = 0;
|
startLevel = 0;
|
||||||
} else {
|
} else {
|
||||||
@ -179,7 +179,7 @@ function bidi(str, startLevel, vertical) {
|
|||||||
/*
|
/*
|
||||||
X1-X10: skip most of this, since we are NOT doing the embeddings.
|
X1-X10: skip most of this, since we are NOT doing the embeddings.
|
||||||
*/
|
*/
|
||||||
var e = (isOdd(startLevel) ? 'R' : 'L');
|
var e = isOdd(startLevel) ? "R" : "L";
|
||||||
var sor = e;
|
var sor = e;
|
||||||
var eor = sor;
|
var eor = sor;
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ function bidi(str, startLevel, vertical) {
|
|||||||
*/
|
*/
|
||||||
var lastType = sor;
|
var lastType = sor;
|
||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
if (types[i] === 'NSM') {
|
if (types[i] === "NSM") {
|
||||||
types[i] = lastType;
|
types[i] = lastType;
|
||||||
} else {
|
} else {
|
||||||
lastType = types[i];
|
lastType = types[i];
|
||||||
@ -206,9 +206,9 @@ function bidi(str, startLevel, vertical) {
|
|||||||
var t;
|
var t;
|
||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
t = types[i];
|
t = types[i];
|
||||||
if (t === 'EN') {
|
if (t === "EN") {
|
||||||
types[i] = (lastType === 'AL') ? 'AN' : 'EN';
|
types[i] = lastType === "AL" ? "AN" : "EN";
|
||||||
} else if (t === 'R' || t === 'L' || t === 'AL') {
|
} else if (t === "R" || t === "L" || t === "AL") {
|
||||||
lastType = t;
|
lastType = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,8 +218,8 @@ function bidi(str, startLevel, vertical) {
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
t = types[i];
|
t = types[i];
|
||||||
if (t === 'AL') {
|
if (t === "AL") {
|
||||||
types[i] = 'R';
|
types[i] = "R";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,12 +229,14 @@ function bidi(str, startLevel, vertical) {
|
|||||||
type changes to that type:
|
type changes to that type:
|
||||||
*/
|
*/
|
||||||
for (i = 1; i < strLength - 1; ++i) {
|
for (i = 1; i < strLength - 1; ++i) {
|
||||||
if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') {
|
if (types[i] === "ES" && types[i - 1] === "EN" && types[i + 1] === "EN") {
|
||||||
types[i] = 'EN';
|
types[i] = "EN";
|
||||||
}
|
}
|
||||||
if (types[i] === 'CS' &&
|
if (
|
||||||
(types[i - 1] === 'EN' || types[i - 1] === 'AN') &&
|
types[i] === "CS" &&
|
||||||
types[i + 1] === types[i - 1]) {
|
(types[i - 1] === "EN" || types[i - 1] === "AN") &&
|
||||||
|
types[i + 1] === types[i - 1]
|
||||||
|
) {
|
||||||
types[i] = types[i - 1];
|
types[i] = types[i - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,21 +246,21 @@ function bidi(str, startLevel, vertical) {
|
|||||||
to all European numbers:
|
to all European numbers:
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
if (types[i] === 'EN') {
|
if (types[i] === "EN") {
|
||||||
// do before
|
// do before
|
||||||
var j;
|
var j;
|
||||||
for (j = i - 1; j >= 0; --j) {
|
for (j = i - 1; j >= 0; --j) {
|
||||||
if (types[j] !== 'ET') {
|
if (types[j] !== "ET") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
types[j] = 'EN';
|
types[j] = "EN";
|
||||||
}
|
}
|
||||||
// do after
|
// do after
|
||||||
for (j = i + 1; j < strLength; ++j) {
|
for (j = i + 1; j < strLength; ++j) {
|
||||||
if (types[j] !== 'ET') {
|
if (types[j] !== "ET") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
types[j] = 'EN';
|
types[j] = "EN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,8 +270,8 @@ function bidi(str, startLevel, vertical) {
|
|||||||
*/
|
*/
|
||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
t = types[i];
|
t = types[i];
|
||||||
if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') {
|
if (t === "WS" || t === "ES" || t === "ET" || t === "CS") {
|
||||||
types[i] = 'ON';
|
types[i] = "ON";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,9 +283,9 @@ function bidi(str, startLevel, vertical) {
|
|||||||
lastType = sor;
|
lastType = sor;
|
||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
t = types[i];
|
t = types[i];
|
||||||
if (t === 'EN') {
|
if (t === "EN") {
|
||||||
types[i] = ((lastType === 'L') ? 'L' : 'EN');
|
types[i] = lastType === "L" ? "L" : "EN";
|
||||||
} else if (t === 'R' || t === 'L') {
|
} else if (t === "R" || t === "L") {
|
||||||
lastType = t;
|
lastType = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,8 +297,8 @@ function bidi(str, startLevel, vertical) {
|
|||||||
end-of-level-run (eor) are used at level run boundaries.
|
end-of-level-run (eor) are used at level run boundaries.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
if (types[i] === 'ON') {
|
if (types[i] === "ON") {
|
||||||
var end = findUnequal(types, i + 1, 'ON');
|
var end = findUnequal(types, i + 1, "ON");
|
||||||
var before = sor;
|
var before = sor;
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
before = types[i - 1];
|
before = types[i - 1];
|
||||||
@ -306,11 +308,11 @@ function bidi(str, startLevel, vertical) {
|
|||||||
if (end + 1 < strLength) {
|
if (end + 1 < strLength) {
|
||||||
after = types[end + 1];
|
after = types[end + 1];
|
||||||
}
|
}
|
||||||
if (before !== 'L') {
|
if (before !== "L") {
|
||||||
before = 'R';
|
before = "R";
|
||||||
}
|
}
|
||||||
if (after !== 'L') {
|
if (after !== "L") {
|
||||||
after = 'R';
|
after = "R";
|
||||||
}
|
}
|
||||||
if (before === after) {
|
if (before === after) {
|
||||||
setValues(types, i, end, before);
|
setValues(types, i, end, before);
|
||||||
@ -323,7 +325,7 @@ function bidi(str, startLevel, vertical) {
|
|||||||
N2. Any remaining neutrals take the embedding direction.
|
N2. Any remaining neutrals take the embedding direction.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
if (types[i] === 'ON') {
|
if (types[i] === "ON") {
|
||||||
types[i] = e;
|
types[i] = e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,13 +340,14 @@ function bidi(str, startLevel, vertical) {
|
|||||||
for (i = 0; i < strLength; ++i) {
|
for (i = 0; i < strLength; ++i) {
|
||||||
t = types[i];
|
t = types[i];
|
||||||
if (isEven(levels[i])) {
|
if (isEven(levels[i])) {
|
||||||
if (t === 'R') {
|
if (t === "R") {
|
||||||
levels[i] += 1;
|
levels[i] += 1;
|
||||||
} else if (t === 'AN' || t === 'EN') {
|
} else if (t === "AN" || t === "EN") {
|
||||||
levels[i] += 2;
|
levels[i] += 2;
|
||||||
}
|
}
|
||||||
} else { // isOdd
|
} else {
|
||||||
if (t === 'L' || t === 'AN' || t === 'EN') {
|
// isOdd
|
||||||
|
if (t === "L" || t === "AN" || t === "EN") {
|
||||||
levels[i] += 1;
|
levels[i] += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -422,13 +425,11 @@ function bidi(str, startLevel, vertical) {
|
|||||||
// Finally, return string
|
// Finally, return string
|
||||||
for (i = 0, ii = chars.length; i < ii; ++i) {
|
for (i = 0, ii = chars.length; i < ii; ++i) {
|
||||||
var ch = chars[i];
|
var ch = chars[i];
|
||||||
if (ch === '<' || ch === '>') {
|
if (ch === "<" || ch === ">") {
|
||||||
chars[i] = '';
|
chars[i] = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return createBidiText(chars.join(''), isLTR);
|
return createBidiText(chars.join(""), isLTR);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { bidi };
|
||||||
bidi,
|
|
||||||
};
|
|
||||||
|
@ -25,10 +25,9 @@
|
|||||||
* or -1 when EOF is reached.
|
* or -1 when EOF is reached.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { info } from '../shared/util';
|
import { info } from "../shared/util";
|
||||||
|
|
||||||
let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||||
|
|
||||||
const ccittEOL = -2;
|
const ccittEOL = -2;
|
||||||
const ccittEOF = -1;
|
const ccittEOF = -1;
|
||||||
const twoDimPass = 0;
|
const twoDimPass = 0;
|
||||||
@ -467,23 +466,23 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
* @param {Object} [options] - Decoding options.
|
* @param {Object} [options] - Decoding options.
|
||||||
*/
|
*/
|
||||||
function CCITTFaxDecoder(source, options = {}) {
|
function CCITTFaxDecoder(source, options = {}) {
|
||||||
if (!source || typeof source.next !== 'function') {
|
if (!source || typeof source.next !== "function") {
|
||||||
throw new Error('CCITTFaxDecoder - invalid "source" parameter.');
|
throw new Error('CCITTFaxDecoder - invalid "source" parameter.');
|
||||||
}
|
}
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.eof = false;
|
this.eof = false;
|
||||||
|
|
||||||
this.encoding = options['K'] || 0;
|
this.encoding = options["K"] || 0;
|
||||||
this.eoline = options['EndOfLine'] || false;
|
this.eoline = options["EndOfLine"] || false;
|
||||||
this.byteAlign = options['EncodedByteAlign'] || false;
|
this.byteAlign = options["EncodedByteAlign"] || false;
|
||||||
this.columns = options['Columns'] || 1728;
|
this.columns = options["Columns"] || 1728;
|
||||||
this.rows = options['Rows'] || 0;
|
this.rows = options["Rows"] || 0;
|
||||||
let eoblock = options['EndOfBlock'];
|
let eoblock = options["EndOfBlock"];
|
||||||
if (eoblock === null || eoblock === undefined) {
|
if (eoblock === null || eoblock === undefined) {
|
||||||
eoblock = true;
|
eoblock = true;
|
||||||
}
|
}
|
||||||
this.eoblock = eoblock;
|
this.eoblock = eoblock;
|
||||||
this.black = options['BlackIs1'] || false;
|
this.black = options["BlackIs1"] || false;
|
||||||
|
|
||||||
this.codingLine = new Uint32Array(this.columns + 1);
|
this.codingLine = new Uint32Array(this.columns + 1);
|
||||||
this.refLine = new Uint32Array(this.columns + 2);
|
this.refLine = new Uint32Array(this.columns + 2);
|
||||||
@ -556,27 +555,33 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
code1 = code2 = 0;
|
code1 = code2 = 0;
|
||||||
if (blackPixels) {
|
if (blackPixels) {
|
||||||
do {
|
do {
|
||||||
code1 += (code3 = this._getBlackCode());
|
code1 += code3 = this._getBlackCode();
|
||||||
} while (code3 >= 64);
|
} while (code3 >= 64);
|
||||||
do {
|
do {
|
||||||
code2 += (code3 = this._getWhiteCode());
|
code2 += code3 = this._getWhiteCode();
|
||||||
} while (code3 >= 64);
|
} while (code3 >= 64);
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
code1 += (code3 = this._getWhiteCode());
|
code1 += code3 = this._getWhiteCode();
|
||||||
} while (code3 >= 64);
|
} while (code3 >= 64);
|
||||||
do {
|
do {
|
||||||
code2 += (code3 = this._getBlackCode());
|
code2 += code3 = this._getBlackCode();
|
||||||
} while (code3 >= 64);
|
} while (code3 >= 64);
|
||||||
}
|
}
|
||||||
this._addPixels(codingLine[this.codingPos] +
|
this._addPixels(
|
||||||
code1, blackPixels);
|
codingLine[this.codingPos] + code1,
|
||||||
|
blackPixels
|
||||||
|
);
|
||||||
if (codingLine[this.codingPos] < columns) {
|
if (codingLine[this.codingPos] < columns) {
|
||||||
this._addPixels(codingLine[this.codingPos] + code2,
|
this._addPixels(
|
||||||
blackPixels ^ 1);
|
codingLine[this.codingPos] + code2,
|
||||||
|
blackPixels ^ 1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
while (
|
||||||
refLine[refPos] < columns) {
|
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||||
|
refLine[refPos] < columns
|
||||||
|
) {
|
||||||
refPos += 2;
|
refPos += 2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -585,8 +590,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
blackPixels ^= 1;
|
blackPixels ^= 1;
|
||||||
if (codingLine[this.codingPos] < columns) {
|
if (codingLine[this.codingPos] < columns) {
|
||||||
++refPos;
|
++refPos;
|
||||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
while (
|
||||||
refLine[refPos] < columns) {
|
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||||
|
refLine[refPos] < columns
|
||||||
|
) {
|
||||||
refPos += 2;
|
refPos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -596,8 +603,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
blackPixels ^= 1;
|
blackPixels ^= 1;
|
||||||
if (codingLine[this.codingPos] < columns) {
|
if (codingLine[this.codingPos] < columns) {
|
||||||
++refPos;
|
++refPos;
|
||||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
while (
|
||||||
refLine[refPos] < columns) {
|
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||||
|
refLine[refPos] < columns
|
||||||
|
) {
|
||||||
refPos += 2;
|
refPos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -607,8 +616,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
blackPixels ^= 1;
|
blackPixels ^= 1;
|
||||||
if (codingLine[this.codingPos] < columns) {
|
if (codingLine[this.codingPos] < columns) {
|
||||||
++refPos;
|
++refPos;
|
||||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
while (
|
||||||
refLine[refPos] < columns) {
|
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||||
|
refLine[refPos] < columns
|
||||||
|
) {
|
||||||
refPos += 2;
|
refPos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,8 +629,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
blackPixels ^= 1;
|
blackPixels ^= 1;
|
||||||
if (codingLine[this.codingPos] < columns) {
|
if (codingLine[this.codingPos] < columns) {
|
||||||
++refPos;
|
++refPos;
|
||||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
while (
|
||||||
refLine[refPos] < columns) {
|
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||||
|
refLine[refPos] < columns
|
||||||
|
) {
|
||||||
refPos += 2;
|
refPos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -633,8 +646,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
} else {
|
} else {
|
||||||
++refPos;
|
++refPos;
|
||||||
}
|
}
|
||||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
while (
|
||||||
refLine[refPos] < columns) {
|
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||||
|
refLine[refPos] < columns
|
||||||
|
) {
|
||||||
refPos += 2;
|
refPos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -648,8 +663,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
} else {
|
} else {
|
||||||
++refPos;
|
++refPos;
|
||||||
}
|
}
|
||||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
while (
|
||||||
refLine[refPos] < columns) {
|
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||||
|
refLine[refPos] < columns
|
||||||
|
) {
|
||||||
refPos += 2;
|
refPos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -663,8 +680,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
} else {
|
} else {
|
||||||
++refPos;
|
++refPos;
|
||||||
}
|
}
|
||||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
while (
|
||||||
refLine[refPos] < columns) {
|
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||||
|
refLine[refPos] < columns
|
||||||
|
) {
|
||||||
refPos += 2;
|
refPos += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -674,7 +693,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
this.eof = true;
|
this.eof = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
info('bad 2d code');
|
info("bad 2d code");
|
||||||
this._addPixels(columns, 0);
|
this._addPixels(columns, 0);
|
||||||
this.err = true;
|
this.err = true;
|
||||||
}
|
}
|
||||||
@ -687,11 +706,11 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
code1 = 0;
|
code1 = 0;
|
||||||
if (blackPixels) {
|
if (blackPixels) {
|
||||||
do {
|
do {
|
||||||
code1 += (code3 = this._getBlackCode());
|
code1 += code3 = this._getBlackCode();
|
||||||
} while (code3 >= 64);
|
} while (code3 >= 64);
|
||||||
} else {
|
} else {
|
||||||
do {
|
do {
|
||||||
code1 += (code3 = this._getWhiteCode());
|
code1 += code3 = this._getWhiteCode();
|
||||||
} while (code3 >= 64);
|
} while (code3 >= 64);
|
||||||
}
|
}
|
||||||
this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
|
this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
|
||||||
@ -745,7 +764,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
for (i = 0; i < 4; ++i) {
|
for (i = 0; i < 4; ++i) {
|
||||||
code1 = this._lookBits(12);
|
code1 = this._lookBits(12);
|
||||||
if (code1 !== 1) {
|
if (code1 !== 1) {
|
||||||
info('bad rtc code: ' + code1);
|
info("bad rtc code: " + code1);
|
||||||
}
|
}
|
||||||
this._eatBits(12);
|
this._eatBits(12);
|
||||||
if (this.encoding > 0) {
|
if (this.encoding > 0) {
|
||||||
@ -763,7 +782,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
this.eof = true;
|
this.eof = true;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if ((code1 >> 1) === 1) {
|
if (code1 >> 1 === 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
this._eatBits(1);
|
this._eatBits(1);
|
||||||
@ -776,21 +795,21 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (codingLine[0] > 0) {
|
if (codingLine[0] > 0) {
|
||||||
this.outputBits = codingLine[this.codingPos = 0];
|
this.outputBits = codingLine[(this.codingPos = 0)];
|
||||||
} else {
|
} else {
|
||||||
this.outputBits = codingLine[this.codingPos = 1];
|
this.outputBits = codingLine[(this.codingPos = 1)];
|
||||||
}
|
}
|
||||||
this.row++;
|
this.row++;
|
||||||
}
|
}
|
||||||
|
|
||||||
let c;
|
let c;
|
||||||
if (this.outputBits >= 8) {
|
if (this.outputBits >= 8) {
|
||||||
c = (this.codingPos & 1) ? 0 : 0xFF;
|
c = this.codingPos & 1 ? 0 : 0xff;
|
||||||
this.outputBits -= 8;
|
this.outputBits -= 8;
|
||||||
if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
|
if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
|
||||||
this.codingPos++;
|
this.codingPos++;
|
||||||
this.outputBits = (codingLine[this.codingPos] -
|
this.outputBits =
|
||||||
codingLine[this.codingPos - 1]);
|
codingLine[this.codingPos] - codingLine[this.codingPos - 1];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bits = 8;
|
bits = 8;
|
||||||
@ -799,21 +818,21 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
if (this.outputBits > bits) {
|
if (this.outputBits > bits) {
|
||||||
c <<= bits;
|
c <<= bits;
|
||||||
if (!(this.codingPos & 1)) {
|
if (!(this.codingPos & 1)) {
|
||||||
c |= 0xFF >> (8 - bits);
|
c |= 0xff >> (8 - bits);
|
||||||
}
|
}
|
||||||
this.outputBits -= bits;
|
this.outputBits -= bits;
|
||||||
bits = 0;
|
bits = 0;
|
||||||
} else {
|
} else {
|
||||||
c <<= this.outputBits;
|
c <<= this.outputBits;
|
||||||
if (!(this.codingPos & 1)) {
|
if (!(this.codingPos & 1)) {
|
||||||
c |= 0xFF >> (8 - this.outputBits);
|
c |= 0xff >> (8 - this.outputBits);
|
||||||
}
|
}
|
||||||
bits -= this.outputBits;
|
bits -= this.outputBits;
|
||||||
this.outputBits = 0;
|
this.outputBits = 0;
|
||||||
if (codingLine[this.codingPos] < columns) {
|
if (codingLine[this.codingPos] < columns) {
|
||||||
this.codingPos++;
|
this.codingPos++;
|
||||||
this.outputBits = (codingLine[this.codingPos] -
|
this.outputBits =
|
||||||
codingLine[this.codingPos - 1]);
|
codingLine[this.codingPos] - codingLine[this.codingPos - 1];
|
||||||
} else if (bits > 0) {
|
} else if (bits > 0) {
|
||||||
c <<= bits;
|
c <<= bits;
|
||||||
bits = 0;
|
bits = 0;
|
||||||
@ -822,7 +841,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
} while (bits);
|
} while (bits);
|
||||||
}
|
}
|
||||||
if (this.black) {
|
if (this.black) {
|
||||||
c ^= 0xFF;
|
c ^= 0xff;
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
},
|
},
|
||||||
@ -836,7 +855,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
|
|
||||||
if (a1 > codingLine[codingPos]) {
|
if (a1 > codingLine[codingPos]) {
|
||||||
if (a1 > this.columns) {
|
if (a1 > this.columns) {
|
||||||
info('row is wrong length');
|
info("row is wrong length");
|
||||||
this.err = true;
|
this.err = true;
|
||||||
a1 = this.columns;
|
a1 = this.columns;
|
||||||
}
|
}
|
||||||
@ -858,7 +877,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
|
|
||||||
if (a1 > codingLine[codingPos]) {
|
if (a1 > codingLine[codingPos]) {
|
||||||
if (a1 > this.columns) {
|
if (a1 > this.columns) {
|
||||||
info('row is wrong length');
|
info("row is wrong length");
|
||||||
this.err = true;
|
this.err = true;
|
||||||
a1 = this.columns;
|
a1 = this.columns;
|
||||||
}
|
}
|
||||||
@ -869,7 +888,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
codingLine[codingPos] = a1;
|
codingLine[codingPos] = a1;
|
||||||
} else if (a1 < codingLine[codingPos]) {
|
} else if (a1 < codingLine[codingPos]) {
|
||||||
if (a1 < 0) {
|
if (a1 < 0) {
|
||||||
info('invalid code');
|
info("invalid code");
|
||||||
this.err = true;
|
this.err = true;
|
||||||
a1 = 0;
|
a1 = 0;
|
||||||
}
|
}
|
||||||
@ -931,7 +950,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
return result[1];
|
return result[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info('Bad two dim code');
|
info("Bad two dim code");
|
||||||
return ccittEOF;
|
return ccittEOF;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -947,7 +966,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((code >> 5) === 0) {
|
if (code >> 5 === 0) {
|
||||||
p = whiteTable1[code];
|
p = whiteTable1[code];
|
||||||
} else {
|
} else {
|
||||||
p = whiteTable2[code >> 3];
|
p = whiteTable2[code >> 3];
|
||||||
@ -968,7 +987,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
return result[1];
|
return result[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info('bad white code');
|
info("bad white code");
|
||||||
this._eatBits(1);
|
this._eatBits(1);
|
||||||
return 1;
|
return 1;
|
||||||
},
|
},
|
||||||
@ -983,9 +1002,9 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
if (code === ccittEOF) {
|
if (code === ccittEOF) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if ((code >> 7) === 0) {
|
if (code >> 7 === 0) {
|
||||||
p = blackTable1[code];
|
p = blackTable1[code];
|
||||||
} else if ((code >> 9) === 0 && (code >> 7) !== 0) {
|
} else if (code >> 9 === 0 && code >> 7 !== 0) {
|
||||||
p = blackTable2[(code >> 1) - 64];
|
p = blackTable2[(code >> 1) - 64];
|
||||||
} else {
|
} else {
|
||||||
p = blackTable3[code >> 7];
|
p = blackTable3[code >> 7];
|
||||||
@ -1011,7 +1030,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
return result[1];
|
return result[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
info('bad black code');
|
info("bad black code");
|
||||||
this._eatBits(1);
|
this._eatBits(1);
|
||||||
return 1;
|
return 1;
|
||||||
},
|
},
|
||||||
@ -1026,13 +1045,12 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
if (this.inputBits === 0) {
|
if (this.inputBits === 0) {
|
||||||
return ccittEOF;
|
return ccittEOF;
|
||||||
}
|
}
|
||||||
return ((this.inputBuf << (n - this.inputBits)) &
|
return (this.inputBuf << (n - this.inputBits)) & (0xffff >> (16 - n));
|
||||||
(0xFFFF >> (16 - n)));
|
|
||||||
}
|
}
|
||||||
this.inputBuf = (this.inputBuf << 8) | c;
|
this.inputBuf = (this.inputBuf << 8) | c;
|
||||||
this.inputBits += 8;
|
this.inputBits += 8;
|
||||||
}
|
}
|
||||||
return (this.inputBuf >> (this.inputBits - n)) & (0xFFFF >> (16 - n));
|
return (this.inputBuf >> (this.inputBits - n)) & (0xffff >> (16 - n));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1048,6 +1066,4 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
|||||||
return CCITTFaxDecoder;
|
return CCITTFaxDecoder;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { CCITTFaxDecoder };
|
||||||
CCITTFaxDecoder,
|
|
||||||
};
|
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Dict, isDict } from './primitives';
|
import { Dict, isDict } from "./primitives";
|
||||||
import { CCITTFaxDecoder } from './ccitt';
|
import { CCITTFaxDecoder } from "./ccitt";
|
||||||
import { DecodeStream } from './stream';
|
import { DecodeStream } from "./stream";
|
||||||
|
|
||||||
var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
||||||
function CCITTFaxStream(str, maybeLength, params) {
|
function CCITTFaxStream(str, maybeLength, params) {
|
||||||
@ -32,13 +32,13 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.ccittFaxDecoder = new CCITTFaxDecoder(source, {
|
this.ccittFaxDecoder = new CCITTFaxDecoder(source, {
|
||||||
K: params.get('K'),
|
K: params.get("K"),
|
||||||
EndOfLine: params.get('EndOfLine'),
|
EndOfLine: params.get("EndOfLine"),
|
||||||
EncodedByteAlign: params.get('EncodedByteAlign'),
|
EncodedByteAlign: params.get("EncodedByteAlign"),
|
||||||
Columns: params.get('Columns'),
|
Columns: params.get("Columns"),
|
||||||
Rows: params.get('Rows'),
|
Rows: params.get("Rows"),
|
||||||
EndOfBlock: params.get('EndOfBlock'),
|
EndOfBlock: params.get("EndOfBlock"),
|
||||||
BlackIs1: params.get('BlackIs1'),
|
BlackIs1: params.get("BlackIs1"),
|
||||||
});
|
});
|
||||||
|
|
||||||
DecodeStream.call(this, maybeLength);
|
DecodeStream.call(this, maybeLength);
|
||||||
@ -61,6 +61,4 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
|||||||
return CCITTFaxStream;
|
return CCITTFaxStream;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { CCITTFaxStream };
|
||||||
CCITTFaxStream,
|
|
||||||
};
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -16,109 +16,105 @@
|
|||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const ISOAdobeCharset = [
|
const ISOAdobeCharset = [
|
||||||
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
|
".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar",
|
||||||
'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
|
"percent", "ampersand", "quoteright", "parenleft", "parenright",
|
||||||
'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
|
"asterisk", "plus", "comma", "hyphen", "period", "slash", "zero",
|
||||||
'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
|
"one", "two", "three", "four", "five", "six", "seven", "eight",
|
||||||
'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question',
|
"nine", "colon", "semicolon", "less", "equal", "greater", "question",
|
||||||
'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
"at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
|
||||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
|
||||||
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
|
"bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
|
||||||
'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
|
"quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
|
||||||
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
"m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||||
'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
|
"braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent",
|
||||||
'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
|
"sterling", "fraction", "yen", "florin", "section", "currency",
|
||||||
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
|
"quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
|
||||||
'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
|
"guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl",
|
||||||
'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
|
"periodcentered", "paragraph", "bullet", "quotesinglbase",
|
||||||
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
|
"quotedblbase", "quotedblright", "guillemotright", "ellipsis",
|
||||||
'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
|
"perthousand", "questiondown", "grave", "acute", "circumflex", "tilde",
|
||||||
'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
|
"macron", "breve", "dotaccent", "dieresis", "ring", "cedilla",
|
||||||
'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
|
"hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine",
|
||||||
'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
|
"Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash",
|
||||||
'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
|
"oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu",
|
||||||
'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
|
"trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter",
|
||||||
'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
|
"divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
|
||||||
'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
|
"registered", "minus", "eth", "multiply", "threesuperior", "copyright",
|
||||||
'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
|
"Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde",
|
||||||
'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
|
"Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute",
|
||||||
'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
|
"Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex",
|
||||||
'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
|
"Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
|
||||||
'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
|
"Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute",
|
||||||
'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
|
"acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla",
|
||||||
'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
|
"eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex",
|
||||||
'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
|
"idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis",
|
||||||
'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
|
"ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
|
||||||
'ugrave', 'yacute', 'ydieresis', 'zcaron'
|
"ugrave", "yacute", "ydieresis", "zcaron"
|
||||||
];
|
];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const ExpertCharset = [
|
const ExpertCharset = [
|
||||||
'.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
|
".notdef", "space", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle",
|
||||||
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
|
"dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior",
|
||||||
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
|
"parenrightsuperior", "twodotenleader", "onedotenleader", "comma",
|
||||||
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
|
"hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle",
|
||||||
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
|
"twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
|
||||||
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
|
"sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle",
|
||||||
'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
|
"colon", "semicolon", "commasuperior", "threequartersemdash",
|
||||||
'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
|
"periodsuperior", "questionsmall", "asuperior", "bsuperior",
|
||||||
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
"centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
|
||||||
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
"msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
|
||||||
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
"tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior",
|
||||||
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
|
"parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
|
||||||
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
|
"Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall",
|
||||||
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
|
"Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
|
||||||
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
|
"Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
|
||||||
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
|
"Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary",
|
||||||
'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
|
"onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle",
|
||||||
'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
|
"Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall",
|
||||||
'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
|
"Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall",
|
||||||
'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
|
"figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall",
|
||||||
'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
|
"Cedillasmall", "onequarter", "onehalf", "threequarters",
|
||||||
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
|
"questiondownsmall", "oneeighth", "threeeighths", "fiveeighths",
|
||||||
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
"seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior",
|
||||||
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
"twosuperior", "threesuperior", "foursuperior", "fivesuperior",
|
||||||
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
"sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior",
|
||||||
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
"zeroinferior", "oneinferior", "twoinferior", "threeinferior",
|
||||||
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
"fourinferior", "fiveinferior", "sixinferior", "seveninferior",
|
||||||
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
"eightinferior", "nineinferior", "centinferior", "dollarinferior",
|
||||||
'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
|
"periodinferior", "commainferior", "Agravesmall", "Aacutesmall",
|
||||||
'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall',
|
"Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall",
|
||||||
'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
|
"AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
|
||||||
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
|
"Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
|
||||||
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
|
"Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
|
||||||
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
|
"Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
|
||||||
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
|
"Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall",
|
||||||
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
|
"Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall",
|
||||||
'Ydieresissmall'
|
"Ydieresissmall"
|
||||||
];
|
];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const ExpertSubsetCharset = [
|
const ExpertSubsetCharset = [
|
||||||
'.notdef', 'space', 'dollaroldstyle', 'dollarsuperior',
|
".notdef", "space", "dollaroldstyle", "dollarsuperior",
|
||||||
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
|
"parenleftsuperior", "parenrightsuperior", "twodotenleader",
|
||||||
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
|
"onedotenleader", "comma", "hyphen", "period", "fraction",
|
||||||
'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
|
"zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle",
|
||||||
'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
|
"fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle",
|
||||||
'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
|
"eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior",
|
||||||
'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior',
|
"threequartersemdash", "periodsuperior", "asuperior", "bsuperior",
|
||||||
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
"centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
|
||||||
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
"msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
|
||||||
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
"tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior",
|
||||||
'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted',
|
"parenrightinferior", "hyphensuperior", "colonmonetary", "onefitted",
|
||||||
'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter',
|
"rupiah", "centoldstyle", "figuredash", "hypheninferior", "onequarter",
|
||||||
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
|
"onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths",
|
||||||
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
"seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior",
|
||||||
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
"twosuperior", "threesuperior", "foursuperior", "fivesuperior",
|
||||||
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
"sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior",
|
||||||
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
"zeroinferior", "oneinferior", "twoinferior", "threeinferior",
|
||||||
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
"fourinferior", "fiveinferior", "sixinferior", "seveninferior",
|
||||||
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
"eightinferior", "nineinferior", "centinferior", "dollarinferior",
|
||||||
'periodinferior', 'commainferior'
|
"periodinferior", "commainferior"
|
||||||
];
|
];
|
||||||
|
|
||||||
export {
|
export { ISOAdobeCharset, ExpertCharset, ExpertSubsetCharset };
|
||||||
ISOAdobeCharset,
|
|
||||||
ExpertCharset,
|
|
||||||
ExpertSubsetCharset,
|
|
||||||
};
|
|
||||||
|
@ -15,9 +15,12 @@
|
|||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
arrayByteLength, arraysToBytes, createPromiseCapability, isEmptyObj
|
arrayByteLength,
|
||||||
} from '../shared/util';
|
arraysToBytes,
|
||||||
import { MissingDataException } from './core_utils';
|
createPromiseCapability,
|
||||||
|
isEmptyObj,
|
||||||
|
} from "../shared/util";
|
||||||
|
import { MissingDataException } from "./core_utils";
|
||||||
|
|
||||||
class ChunkedStream {
|
class ChunkedStream {
|
||||||
constructor(length, chunkSize, manager) {
|
constructor(length, chunkSize, manager) {
|
||||||
@ -86,8 +89,10 @@ class ChunkedStream {
|
|||||||
this.bytes.set(new Uint8Array(data), position);
|
this.bytes.set(new Uint8Array(data), position);
|
||||||
position += data.byteLength;
|
position += data.byteLength;
|
||||||
this.progressiveDataLength = position;
|
this.progressiveDataLength = position;
|
||||||
const endChunk = position >= this.end ? this.numChunks :
|
const endChunk =
|
||||||
Math.floor(position / this.chunkSize);
|
position >= this.end
|
||||||
|
? this.numChunks
|
||||||
|
: Math.floor(position / this.chunkSize);
|
||||||
|
|
||||||
for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
|
for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
|
||||||
if (!this.loadedChunks[curChunk]) {
|
if (!this.loadedChunks[curChunk]) {
|
||||||
@ -194,7 +199,7 @@ class ChunkedStream {
|
|||||||
}
|
}
|
||||||
const subarray = bytes.subarray(pos, strEnd);
|
const subarray = bytes.subarray(pos, strEnd);
|
||||||
// `this.bytes` is always a `Uint8Array` here.
|
// `this.bytes` is always a `Uint8Array` here.
|
||||||
return (forceClamped ? new Uint8ClampedArray(subarray) : subarray);
|
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
|
||||||
}
|
}
|
||||||
|
|
||||||
let end = pos + length;
|
let end = pos + length;
|
||||||
@ -208,7 +213,7 @@ class ChunkedStream {
|
|||||||
this.pos = end;
|
this.pos = end;
|
||||||
const subarray = bytes.subarray(pos, end);
|
const subarray = bytes.subarray(pos, end);
|
||||||
// `this.bytes` is always a `Uint8Array` here.
|
// `this.bytes` is always a `Uint8Array` here.
|
||||||
return (forceClamped ? new Uint8ClampedArray(subarray) : subarray);
|
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
|
||||||
}
|
}
|
||||||
|
|
||||||
peekByte() {
|
peekByte() {
|
||||||
@ -332,16 +337,17 @@ class ChunkedStreamManager {
|
|||||||
rangeReader.onProgress = this.onProgress.bind(this);
|
rangeReader.onProgress = this.onProgress.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
let chunks = [], loaded = 0;
|
let chunks = [],
|
||||||
|
loaded = 0;
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
const readChunk = (chunk) => {
|
const readChunk = chunk => {
|
||||||
try {
|
try {
|
||||||
if (!chunk.done) {
|
if (!chunk.done) {
|
||||||
const data = chunk.value;
|
const data = chunk.value;
|
||||||
chunks.push(data);
|
chunks.push(data);
|
||||||
loaded += arrayByteLength(data);
|
loaded += arrayByteLength(data);
|
||||||
if (rangeReader.isStreamingSupported) {
|
if (rangeReader.isStreamingSupported) {
|
||||||
this.onProgress({ loaded, });
|
this.onProgress({ loaded });
|
||||||
}
|
}
|
||||||
rangeReader.read().then(readChunk, reject);
|
rangeReader.read().then(readChunk, reject);
|
||||||
return;
|
return;
|
||||||
@ -355,11 +361,11 @@ class ChunkedStreamManager {
|
|||||||
};
|
};
|
||||||
rangeReader.read().then(readChunk, reject);
|
rangeReader.read().then(readChunk, reject);
|
||||||
});
|
});
|
||||||
promise.then((data) => {
|
promise.then(data => {
|
||||||
if (this.aborted) {
|
if (this.aborted) {
|
||||||
return; // Ignoring any data after abort.
|
return; // Ignoring any data after abort.
|
||||||
}
|
}
|
||||||
this.onReceiveData({ chunk: data, begin, });
|
this.onReceiveData({ chunk: data, begin });
|
||||||
});
|
});
|
||||||
// TODO check errors
|
// TODO check errors
|
||||||
}
|
}
|
||||||
@ -470,13 +476,11 @@ class ChunkedStreamManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
|
if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
|
||||||
groupedChunks.push({ beginChunk,
|
groupedChunks.push({ beginChunk, endChunk: prevChunk + 1 });
|
||||||
endChunk: prevChunk + 1, });
|
|
||||||
beginChunk = chunk;
|
beginChunk = chunk;
|
||||||
}
|
}
|
||||||
if (i + 1 === chunks.length) {
|
if (i + 1 === chunks.length) {
|
||||||
groupedChunks.push({ beginChunk,
|
groupedChunks.push({ beginChunk, endChunk: chunk + 1 });
|
||||||
endChunk: chunk + 1, });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prevChunk = chunk;
|
prevChunk = chunk;
|
||||||
@ -485,7 +489,7 @@ class ChunkedStreamManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onProgress(args) {
|
onProgress(args) {
|
||||||
this.msgHandler.send('DocProgress', {
|
this.msgHandler.send("DocProgress", {
|
||||||
loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded,
|
loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded,
|
||||||
total: this.length,
|
total: this.length,
|
||||||
});
|
});
|
||||||
@ -498,8 +502,10 @@ class ChunkedStreamManager {
|
|||||||
const end = begin + chunk.byteLength;
|
const end = begin + chunk.byteLength;
|
||||||
|
|
||||||
const beginChunk = Math.floor(begin / this.chunkSize);
|
const beginChunk = Math.floor(begin / this.chunkSize);
|
||||||
const endChunk = end < this.length ? Math.floor(end / this.chunkSize) :
|
const endChunk =
|
||||||
Math.ceil(end / this.chunkSize);
|
end < this.length
|
||||||
|
? Math.floor(end / this.chunkSize)
|
||||||
|
: Math.ceil(end / this.chunkSize);
|
||||||
|
|
||||||
if (isProgressive) {
|
if (isProgressive) {
|
||||||
this.stream.onReceiveProgressiveData(chunk);
|
this.stream.onReceiveProgressiveData(chunk);
|
||||||
@ -557,7 +563,7 @@ class ChunkedStreamManager {
|
|||||||
capability.resolve();
|
capability.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.msgHandler.send('DocProgress', {
|
this.msgHandler.send("DocProgress", {
|
||||||
loaded: this.stream.numChunksLoaded * this.chunkSize,
|
loaded: this.stream.numChunksLoaded * this.chunkSize,
|
||||||
total: this.length,
|
total: this.length,
|
||||||
});
|
});
|
||||||
@ -586,7 +592,4 @@ class ChunkedStreamManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { ChunkedStream, ChunkedStreamManager };
|
||||||
ChunkedStream,
|
|
||||||
ChunkedStreamManager,
|
|
||||||
};
|
|
||||||
|
546
src/core/cmap.js
546
src/core/cmap.js
@ -14,184 +14,189 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CMapCompressionType, FormatError, isString, unreachable, warn
|
CMapCompressionType,
|
||||||
} from '../shared/util';
|
FormatError,
|
||||||
import { isCmd, isEOF, isName, isStream } from './primitives';
|
isString,
|
||||||
import { Lexer } from './parser';
|
unreachable,
|
||||||
import { MissingDataException } from './core_utils';
|
warn,
|
||||||
import { Stream } from './stream';
|
} from "../shared/util";
|
||||||
|
import { isCmd, isEOF, isName, isStream } from "./primitives";
|
||||||
|
import { Lexer } from "./parser";
|
||||||
|
import { MissingDataException } from "./core_utils";
|
||||||
|
import { Stream } from "./stream";
|
||||||
|
|
||||||
var BUILT_IN_CMAPS = [
|
var BUILT_IN_CMAPS = [
|
||||||
// << Start unicode maps.
|
// << Start unicode maps.
|
||||||
'Adobe-GB1-UCS2',
|
"Adobe-GB1-UCS2",
|
||||||
'Adobe-CNS1-UCS2',
|
"Adobe-CNS1-UCS2",
|
||||||
'Adobe-Japan1-UCS2',
|
"Adobe-Japan1-UCS2",
|
||||||
'Adobe-Korea1-UCS2',
|
"Adobe-Korea1-UCS2",
|
||||||
// >> End unicode maps.
|
// >> End unicode maps.
|
||||||
'78-EUC-H',
|
"78-EUC-H",
|
||||||
'78-EUC-V',
|
"78-EUC-V",
|
||||||
'78-H',
|
"78-H",
|
||||||
'78-RKSJ-H',
|
"78-RKSJ-H",
|
||||||
'78-RKSJ-V',
|
"78-RKSJ-V",
|
||||||
'78-V',
|
"78-V",
|
||||||
'78ms-RKSJ-H',
|
"78ms-RKSJ-H",
|
||||||
'78ms-RKSJ-V',
|
"78ms-RKSJ-V",
|
||||||
'83pv-RKSJ-H',
|
"83pv-RKSJ-H",
|
||||||
'90ms-RKSJ-H',
|
"90ms-RKSJ-H",
|
||||||
'90ms-RKSJ-V',
|
"90ms-RKSJ-V",
|
||||||
'90msp-RKSJ-H',
|
"90msp-RKSJ-H",
|
||||||
'90msp-RKSJ-V',
|
"90msp-RKSJ-V",
|
||||||
'90pv-RKSJ-H',
|
"90pv-RKSJ-H",
|
||||||
'90pv-RKSJ-V',
|
"90pv-RKSJ-V",
|
||||||
'Add-H',
|
"Add-H",
|
||||||
'Add-RKSJ-H',
|
"Add-RKSJ-H",
|
||||||
'Add-RKSJ-V',
|
"Add-RKSJ-V",
|
||||||
'Add-V',
|
"Add-V",
|
||||||
'Adobe-CNS1-0',
|
"Adobe-CNS1-0",
|
||||||
'Adobe-CNS1-1',
|
"Adobe-CNS1-1",
|
||||||
'Adobe-CNS1-2',
|
"Adobe-CNS1-2",
|
||||||
'Adobe-CNS1-3',
|
"Adobe-CNS1-3",
|
||||||
'Adobe-CNS1-4',
|
"Adobe-CNS1-4",
|
||||||
'Adobe-CNS1-5',
|
"Adobe-CNS1-5",
|
||||||
'Adobe-CNS1-6',
|
"Adobe-CNS1-6",
|
||||||
'Adobe-GB1-0',
|
"Adobe-GB1-0",
|
||||||
'Adobe-GB1-1',
|
"Adobe-GB1-1",
|
||||||
'Adobe-GB1-2',
|
"Adobe-GB1-2",
|
||||||
'Adobe-GB1-3',
|
"Adobe-GB1-3",
|
||||||
'Adobe-GB1-4',
|
"Adobe-GB1-4",
|
||||||
'Adobe-GB1-5',
|
"Adobe-GB1-5",
|
||||||
'Adobe-Japan1-0',
|
"Adobe-Japan1-0",
|
||||||
'Adobe-Japan1-1',
|
"Adobe-Japan1-1",
|
||||||
'Adobe-Japan1-2',
|
"Adobe-Japan1-2",
|
||||||
'Adobe-Japan1-3',
|
"Adobe-Japan1-3",
|
||||||
'Adobe-Japan1-4',
|
"Adobe-Japan1-4",
|
||||||
'Adobe-Japan1-5',
|
"Adobe-Japan1-5",
|
||||||
'Adobe-Japan1-6',
|
"Adobe-Japan1-6",
|
||||||
'Adobe-Korea1-0',
|
"Adobe-Korea1-0",
|
||||||
'Adobe-Korea1-1',
|
"Adobe-Korea1-1",
|
||||||
'Adobe-Korea1-2',
|
"Adobe-Korea1-2",
|
||||||
'B5-H',
|
"B5-H",
|
||||||
'B5-V',
|
"B5-V",
|
||||||
'B5pc-H',
|
"B5pc-H",
|
||||||
'B5pc-V',
|
"B5pc-V",
|
||||||
'CNS-EUC-H',
|
"CNS-EUC-H",
|
||||||
'CNS-EUC-V',
|
"CNS-EUC-V",
|
||||||
'CNS1-H',
|
"CNS1-H",
|
||||||
'CNS1-V',
|
"CNS1-V",
|
||||||
'CNS2-H',
|
"CNS2-H",
|
||||||
'CNS2-V',
|
"CNS2-V",
|
||||||
'ETHK-B5-H',
|
"ETHK-B5-H",
|
||||||
'ETHK-B5-V',
|
"ETHK-B5-V",
|
||||||
'ETen-B5-H',
|
"ETen-B5-H",
|
||||||
'ETen-B5-V',
|
"ETen-B5-V",
|
||||||
'ETenms-B5-H',
|
"ETenms-B5-H",
|
||||||
'ETenms-B5-V',
|
"ETenms-B5-V",
|
||||||
'EUC-H',
|
"EUC-H",
|
||||||
'EUC-V',
|
"EUC-V",
|
||||||
'Ext-H',
|
"Ext-H",
|
||||||
'Ext-RKSJ-H',
|
"Ext-RKSJ-H",
|
||||||
'Ext-RKSJ-V',
|
"Ext-RKSJ-V",
|
||||||
'Ext-V',
|
"Ext-V",
|
||||||
'GB-EUC-H',
|
"GB-EUC-H",
|
||||||
'GB-EUC-V',
|
"GB-EUC-V",
|
||||||
'GB-H',
|
"GB-H",
|
||||||
'GB-V',
|
"GB-V",
|
||||||
'GBK-EUC-H',
|
"GBK-EUC-H",
|
||||||
'GBK-EUC-V',
|
"GBK-EUC-V",
|
||||||
'GBK2K-H',
|
"GBK2K-H",
|
||||||
'GBK2K-V',
|
"GBK2K-V",
|
||||||
'GBKp-EUC-H',
|
"GBKp-EUC-H",
|
||||||
'GBKp-EUC-V',
|
"GBKp-EUC-V",
|
||||||
'GBT-EUC-H',
|
"GBT-EUC-H",
|
||||||
'GBT-EUC-V',
|
"GBT-EUC-V",
|
||||||
'GBT-H',
|
"GBT-H",
|
||||||
'GBT-V',
|
"GBT-V",
|
||||||
'GBTpc-EUC-H',
|
"GBTpc-EUC-H",
|
||||||
'GBTpc-EUC-V',
|
"GBTpc-EUC-V",
|
||||||
'GBpc-EUC-H',
|
"GBpc-EUC-H",
|
||||||
'GBpc-EUC-V',
|
"GBpc-EUC-V",
|
||||||
'H',
|
"H",
|
||||||
'HKdla-B5-H',
|
"HKdla-B5-H",
|
||||||
'HKdla-B5-V',
|
"HKdla-B5-V",
|
||||||
'HKdlb-B5-H',
|
"HKdlb-B5-H",
|
||||||
'HKdlb-B5-V',
|
"HKdlb-B5-V",
|
||||||
'HKgccs-B5-H',
|
"HKgccs-B5-H",
|
||||||
'HKgccs-B5-V',
|
"HKgccs-B5-V",
|
||||||
'HKm314-B5-H',
|
"HKm314-B5-H",
|
||||||
'HKm314-B5-V',
|
"HKm314-B5-V",
|
||||||
'HKm471-B5-H',
|
"HKm471-B5-H",
|
||||||
'HKm471-B5-V',
|
"HKm471-B5-V",
|
||||||
'HKscs-B5-H',
|
"HKscs-B5-H",
|
||||||
'HKscs-B5-V',
|
"HKscs-B5-V",
|
||||||
'Hankaku',
|
"Hankaku",
|
||||||
'Hiragana',
|
"Hiragana",
|
||||||
'KSC-EUC-H',
|
"KSC-EUC-H",
|
||||||
'KSC-EUC-V',
|
"KSC-EUC-V",
|
||||||
'KSC-H',
|
"KSC-H",
|
||||||
'KSC-Johab-H',
|
"KSC-Johab-H",
|
||||||
'KSC-Johab-V',
|
"KSC-Johab-V",
|
||||||
'KSC-V',
|
"KSC-V",
|
||||||
'KSCms-UHC-H',
|
"KSCms-UHC-H",
|
||||||
'KSCms-UHC-HW-H',
|
"KSCms-UHC-HW-H",
|
||||||
'KSCms-UHC-HW-V',
|
"KSCms-UHC-HW-V",
|
||||||
'KSCms-UHC-V',
|
"KSCms-UHC-V",
|
||||||
'KSCpc-EUC-H',
|
"KSCpc-EUC-H",
|
||||||
'KSCpc-EUC-V',
|
"KSCpc-EUC-V",
|
||||||
'Katakana',
|
"Katakana",
|
||||||
'NWP-H',
|
"NWP-H",
|
||||||
'NWP-V',
|
"NWP-V",
|
||||||
'RKSJ-H',
|
"RKSJ-H",
|
||||||
'RKSJ-V',
|
"RKSJ-V",
|
||||||
'Roman',
|
"Roman",
|
||||||
'UniCNS-UCS2-H',
|
"UniCNS-UCS2-H",
|
||||||
'UniCNS-UCS2-V',
|
"UniCNS-UCS2-V",
|
||||||
'UniCNS-UTF16-H',
|
"UniCNS-UTF16-H",
|
||||||
'UniCNS-UTF16-V',
|
"UniCNS-UTF16-V",
|
||||||
'UniCNS-UTF32-H',
|
"UniCNS-UTF32-H",
|
||||||
'UniCNS-UTF32-V',
|
"UniCNS-UTF32-V",
|
||||||
'UniCNS-UTF8-H',
|
"UniCNS-UTF8-H",
|
||||||
'UniCNS-UTF8-V',
|
"UniCNS-UTF8-V",
|
||||||
'UniGB-UCS2-H',
|
"UniGB-UCS2-H",
|
||||||
'UniGB-UCS2-V',
|
"UniGB-UCS2-V",
|
||||||
'UniGB-UTF16-H',
|
"UniGB-UTF16-H",
|
||||||
'UniGB-UTF16-V',
|
"UniGB-UTF16-V",
|
||||||
'UniGB-UTF32-H',
|
"UniGB-UTF32-H",
|
||||||
'UniGB-UTF32-V',
|
"UniGB-UTF32-V",
|
||||||
'UniGB-UTF8-H',
|
"UniGB-UTF8-H",
|
||||||
'UniGB-UTF8-V',
|
"UniGB-UTF8-V",
|
||||||
'UniJIS-UCS2-H',
|
"UniJIS-UCS2-H",
|
||||||
'UniJIS-UCS2-HW-H',
|
"UniJIS-UCS2-HW-H",
|
||||||
'UniJIS-UCS2-HW-V',
|
"UniJIS-UCS2-HW-V",
|
||||||
'UniJIS-UCS2-V',
|
"UniJIS-UCS2-V",
|
||||||
'UniJIS-UTF16-H',
|
"UniJIS-UTF16-H",
|
||||||
'UniJIS-UTF16-V',
|
"UniJIS-UTF16-V",
|
||||||
'UniJIS-UTF32-H',
|
"UniJIS-UTF32-H",
|
||||||
'UniJIS-UTF32-V',
|
"UniJIS-UTF32-V",
|
||||||
'UniJIS-UTF8-H',
|
"UniJIS-UTF8-H",
|
||||||
'UniJIS-UTF8-V',
|
"UniJIS-UTF8-V",
|
||||||
'UniJIS2004-UTF16-H',
|
"UniJIS2004-UTF16-H",
|
||||||
'UniJIS2004-UTF16-V',
|
"UniJIS2004-UTF16-V",
|
||||||
'UniJIS2004-UTF32-H',
|
"UniJIS2004-UTF32-H",
|
||||||
'UniJIS2004-UTF32-V',
|
"UniJIS2004-UTF32-V",
|
||||||
'UniJIS2004-UTF8-H',
|
"UniJIS2004-UTF8-H",
|
||||||
'UniJIS2004-UTF8-V',
|
"UniJIS2004-UTF8-V",
|
||||||
'UniJISPro-UCS2-HW-V',
|
"UniJISPro-UCS2-HW-V",
|
||||||
'UniJISPro-UCS2-V',
|
"UniJISPro-UCS2-V",
|
||||||
'UniJISPro-UTF8-V',
|
"UniJISPro-UTF8-V",
|
||||||
'UniJISX0213-UTF32-H',
|
"UniJISX0213-UTF32-H",
|
||||||
'UniJISX0213-UTF32-V',
|
"UniJISX0213-UTF32-V",
|
||||||
'UniJISX02132004-UTF32-H',
|
"UniJISX02132004-UTF32-H",
|
||||||
'UniJISX02132004-UTF32-V',
|
"UniJISX02132004-UTF32-V",
|
||||||
'UniKS-UCS2-H',
|
"UniKS-UCS2-H",
|
||||||
'UniKS-UCS2-V',
|
"UniKS-UCS2-V",
|
||||||
'UniKS-UTF16-H',
|
"UniKS-UTF16-H",
|
||||||
'UniKS-UTF16-V',
|
"UniKS-UTF16-V",
|
||||||
'UniKS-UTF32-H',
|
"UniKS-UTF32-H",
|
||||||
'UniKS-UTF32-V',
|
"UniKS-UTF32-V",
|
||||||
'UniKS-UTF8-H',
|
"UniKS-UTF8-H",
|
||||||
'UniKS-UTF8-V',
|
"UniKS-UTF8-V",
|
||||||
'V',
|
"V",
|
||||||
'WP-Symbol'];
|
"WP-Symbol",
|
||||||
|
];
|
||||||
|
|
||||||
// CMap, not to be confused with TrueType's cmap.
|
// CMap, not to be confused with TrueType's cmap.
|
||||||
class CMap {
|
class CMap {
|
||||||
@ -206,7 +211,7 @@ class CMap {
|
|||||||
// - bf chars are variable-length byte sequences, stored as strings, with
|
// - bf chars are variable-length byte sequences, stored as strings, with
|
||||||
// one byte per character.
|
// one byte per character.
|
||||||
this._map = [];
|
this._map = [];
|
||||||
this.name = '';
|
this.name = "";
|
||||||
this.vertical = false;
|
this.vertical = false;
|
||||||
this.useCMap = null;
|
this.useCMap = null;
|
||||||
this.builtInCMap = builtInCMap;
|
this.builtInCMap = builtInCMap;
|
||||||
@ -228,13 +233,15 @@ class CMap {
|
|||||||
while (low <= high) {
|
while (low <= high) {
|
||||||
this._map[low++] = dstLow;
|
this._map[low++] = dstLow;
|
||||||
// Only the last byte has to be incremented.
|
// Only the last byte has to be incremented.
|
||||||
dstLow = dstLow.substring(0, lastByte) +
|
dstLow =
|
||||||
|
dstLow.substring(0, lastByte) +
|
||||||
String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
|
String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapBfRangeToArray(low, high, array) {
|
mapBfRangeToArray(low, high, array) {
|
||||||
let i = 0, ii = array.length;
|
let i = 0,
|
||||||
|
ii = array.length;
|
||||||
while (low <= high && i < ii) {
|
while (low <= high && i < ii) {
|
||||||
this._map[low] = array[i++];
|
this._map[low] = array[i++];
|
||||||
++low;
|
++low;
|
||||||
@ -284,7 +291,7 @@ class CMap {
|
|||||||
}
|
}
|
||||||
for (let charCode in map) {
|
for (let charCode in map) {
|
||||||
if (map[charCode] === value) {
|
if (map[charCode] === value) {
|
||||||
return (charCode | 0);
|
return charCode | 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -322,7 +329,7 @@ class CMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isIdentityCMap() {
|
get isIdentityCMap() {
|
||||||
if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
|
if (!(this.name === "Identity-H" || this.name === "Identity-V")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (this._map.length !== 0x10000) {
|
if (this._map.length !== 0x10000) {
|
||||||
@ -348,23 +355,23 @@ class IdentityCMap extends CMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapCidRange(low, high, dstLow) {
|
mapCidRange(low, high, dstLow) {
|
||||||
unreachable('should not call mapCidRange');
|
unreachable("should not call mapCidRange");
|
||||||
}
|
}
|
||||||
|
|
||||||
mapBfRange(low, high, dstLow) {
|
mapBfRange(low, high, dstLow) {
|
||||||
unreachable('should not call mapBfRange');
|
unreachable("should not call mapBfRange");
|
||||||
}
|
}
|
||||||
|
|
||||||
mapBfRangeToArray(low, high, array) {
|
mapBfRangeToArray(low, high, array) {
|
||||||
unreachable('should not call mapBfRangeToArray');
|
unreachable("should not call mapBfRangeToArray");
|
||||||
}
|
}
|
||||||
|
|
||||||
mapOne(src, dst) {
|
mapOne(src, dst) {
|
||||||
unreachable('should not call mapCidOne');
|
unreachable("should not call mapCidOne");
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup(code) {
|
lookup(code) {
|
||||||
return (Number.isInteger(code) && code <= 0xffff) ? code : undefined;
|
return Number.isInteger(code) && code <= 0xffff ? code : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
contains(code) {
|
contains(code) {
|
||||||
@ -378,7 +385,7 @@ class IdentityCMap extends CMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
charCodeOf(value) {
|
charCodeOf(value) {
|
||||||
return (Number.isInteger(value) && value <= 0xffff) ? value : -1;
|
return Number.isInteger(value) && value <= 0xffff ? value : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMap() {
|
getMap() {
|
||||||
@ -394,8 +401,9 @@ class IdentityCMap extends CMap {
|
|||||||
return 0x10000;
|
return 0x10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
get isIdentityCMap() { // eslint-disable-line getter-return
|
get isIdentityCMap() {
|
||||||
unreachable('should not access .isIdentityCMap');
|
// eslint-disable-line getter-return
|
||||||
|
unreachable("should not access .isIdentityCMap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,34 +469,36 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
do {
|
do {
|
||||||
var b = this.readByte();
|
var b = this.readByte();
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
throw new FormatError('unexpected EOF in bcmap');
|
throw new FormatError("unexpected EOF in bcmap");
|
||||||
}
|
}
|
||||||
last = !(b & 0x80);
|
last = !(b & 0x80);
|
||||||
n = (n << 7) | (b & 0x7F);
|
n = (n << 7) | (b & 0x7f);
|
||||||
} while (!last);
|
} while (!last);
|
||||||
return n;
|
return n;
|
||||||
},
|
},
|
||||||
readSigned() {
|
readSigned() {
|
||||||
var n = this.readNumber();
|
var n = this.readNumber();
|
||||||
return (n & 1) ? ~(n >>> 1) : n >>> 1;
|
return n & 1 ? ~(n >>> 1) : n >>> 1;
|
||||||
},
|
},
|
||||||
readHex(num, size) {
|
readHex(num, size) {
|
||||||
num.set(this.buffer.subarray(this.pos,
|
num.set(this.buffer.subarray(this.pos, this.pos + size + 1));
|
||||||
this.pos + size + 1));
|
|
||||||
this.pos += size + 1;
|
this.pos += size + 1;
|
||||||
},
|
},
|
||||||
readHexNumber(num, size) {
|
readHexNumber(num, size) {
|
||||||
var last;
|
var last;
|
||||||
var stack = this.tmpBuf, sp = 0;
|
var stack = this.tmpBuf,
|
||||||
|
sp = 0;
|
||||||
do {
|
do {
|
||||||
var b = this.readByte();
|
var b = this.readByte();
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
throw new FormatError('unexpected EOF in bcmap');
|
throw new FormatError("unexpected EOF in bcmap");
|
||||||
}
|
}
|
||||||
last = !(b & 0x80);
|
last = !(b & 0x80);
|
||||||
stack[sp++] = b & 0x7F;
|
stack[sp++] = b & 0x7f;
|
||||||
} while (!last);
|
} while (!last);
|
||||||
var i = size, buffer = 0, bufferSize = 0;
|
var i = size,
|
||||||
|
buffer = 0,
|
||||||
|
bufferSize = 0;
|
||||||
while (i >= 0) {
|
while (i >= 0) {
|
||||||
while (bufferSize < 8 && stack.length > 0) {
|
while (bufferSize < 8 && stack.length > 0) {
|
||||||
buffer = (stack[--sp] << bufferSize) | buffer;
|
buffer = (stack[--sp] << bufferSize) | buffer;
|
||||||
@ -511,7 +521,7 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
},
|
},
|
||||||
readString() {
|
readString() {
|
||||||
var len = this.readNumber();
|
var len = this.readNumber();
|
||||||
var s = '';
|
var s = "";
|
||||||
for (var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
s += String.fromCharCode(this.readNumber());
|
s += String.fromCharCode(this.readNumber());
|
||||||
}
|
}
|
||||||
@ -536,8 +546,9 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
var b;
|
var b;
|
||||||
while ((b = stream.readByte()) >= 0) {
|
while ((b = stream.readByte()) >= 0) {
|
||||||
var type = b >> 5;
|
var type = b >> 5;
|
||||||
if (type === 7) { // metadata, e.g. comment or usecmap
|
if (type === 7) {
|
||||||
switch (b & 0x1F) {
|
// metadata, e.g. comment or usecmap
|
||||||
|
switch (b & 0x1f) {
|
||||||
case 0:
|
case 0:
|
||||||
stream.readString(); // skipping comment
|
stream.readString(); // skipping comment
|
||||||
break;
|
break;
|
||||||
@ -551,7 +562,7 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
var dataSize = b & 15;
|
var dataSize = b & 15;
|
||||||
|
|
||||||
if (dataSize + 1 > MAX_NUM_SIZE) {
|
if (dataSize + 1 > MAX_NUM_SIZE) {
|
||||||
throw new Error('processBinaryCMap: Invalid dataSize.');
|
throw new Error("processBinaryCMap: Invalid dataSize.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var ucs2DataSize = 1;
|
var ucs2DataSize = 1;
|
||||||
@ -562,16 +573,22 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
stream.readHex(start, dataSize);
|
stream.readHex(start, dataSize);
|
||||||
stream.readHexNumber(end, dataSize);
|
stream.readHexNumber(end, dataSize);
|
||||||
addHex(end, start, dataSize);
|
addHex(end, start, dataSize);
|
||||||
cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize),
|
cMap.addCodespaceRange(
|
||||||
hexToInt(end, dataSize));
|
dataSize + 1,
|
||||||
|
hexToInt(start, dataSize),
|
||||||
|
hexToInt(end, dataSize)
|
||||||
|
);
|
||||||
for (i = 1; i < subitemsCount; i++) {
|
for (i = 1; i < subitemsCount; i++) {
|
||||||
incHex(end, dataSize);
|
incHex(end, dataSize);
|
||||||
stream.readHexNumber(start, dataSize);
|
stream.readHexNumber(start, dataSize);
|
||||||
addHex(start, end, dataSize);
|
addHex(start, end, dataSize);
|
||||||
stream.readHexNumber(end, dataSize);
|
stream.readHexNumber(end, dataSize);
|
||||||
addHex(end, start, dataSize);
|
addHex(end, start, dataSize);
|
||||||
cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize),
|
cMap.addCodespaceRange(
|
||||||
hexToInt(end, dataSize));
|
dataSize + 1,
|
||||||
|
hexToInt(start, dataSize),
|
||||||
|
hexToInt(end, dataSize)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1: // notdefrange
|
case 1: // notdefrange
|
||||||
@ -609,8 +626,11 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
stream.readHexNumber(end, dataSize);
|
stream.readHexNumber(end, dataSize);
|
||||||
addHex(end, start, dataSize);
|
addHex(end, start, dataSize);
|
||||||
code = stream.readNumber();
|
code = stream.readNumber();
|
||||||
cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize),
|
cMap.mapCidRange(
|
||||||
code);
|
hexToInt(start, dataSize),
|
||||||
|
hexToInt(end, dataSize),
|
||||||
|
code
|
||||||
|
);
|
||||||
for (i = 1; i < subitemsCount; i++) {
|
for (i = 1; i < subitemsCount; i++) {
|
||||||
incHex(end, dataSize);
|
incHex(end, dataSize);
|
||||||
if (!sequence) {
|
if (!sequence) {
|
||||||
@ -622,15 +642,20 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
stream.readHexNumber(end, dataSize);
|
stream.readHexNumber(end, dataSize);
|
||||||
addHex(end, start, dataSize);
|
addHex(end, start, dataSize);
|
||||||
code = stream.readNumber();
|
code = stream.readNumber();
|
||||||
cMap.mapCidRange(hexToInt(start, dataSize),
|
cMap.mapCidRange(
|
||||||
hexToInt(end, dataSize), code);
|
hexToInt(start, dataSize),
|
||||||
|
hexToInt(end, dataSize),
|
||||||
|
code
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4: // bfchar
|
case 4: // bfchar
|
||||||
stream.readHex(char, ucs2DataSize);
|
stream.readHex(char, ucs2DataSize);
|
||||||
stream.readHex(charCode, dataSize);
|
stream.readHex(charCode, dataSize);
|
||||||
cMap.mapOne(hexToInt(char, ucs2DataSize),
|
cMap.mapOne(
|
||||||
hexToStr(charCode, dataSize));
|
hexToInt(char, ucs2DataSize),
|
||||||
|
hexToStr(charCode, dataSize)
|
||||||
|
);
|
||||||
for (i = 1; i < subitemsCount; i++) {
|
for (i = 1; i < subitemsCount; i++) {
|
||||||
incHex(char, ucs2DataSize);
|
incHex(char, ucs2DataSize);
|
||||||
if (!sequence) {
|
if (!sequence) {
|
||||||
@ -640,8 +665,10 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
incHex(charCode, dataSize);
|
incHex(charCode, dataSize);
|
||||||
stream.readHexSigned(tmp, dataSize);
|
stream.readHexSigned(tmp, dataSize);
|
||||||
addHex(charCode, tmp, dataSize);
|
addHex(charCode, tmp, dataSize);
|
||||||
cMap.mapOne(hexToInt(char, ucs2DataSize),
|
cMap.mapOne(
|
||||||
hexToStr(charCode, dataSize));
|
hexToInt(char, ucs2DataSize),
|
||||||
|
hexToStr(charCode, dataSize)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5: // bfrange
|
case 5: // bfrange
|
||||||
@ -649,9 +676,11 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
stream.readHexNumber(end, ucs2DataSize);
|
stream.readHexNumber(end, ucs2DataSize);
|
||||||
addHex(end, start, ucs2DataSize);
|
addHex(end, start, ucs2DataSize);
|
||||||
stream.readHex(charCode, dataSize);
|
stream.readHex(charCode, dataSize);
|
||||||
cMap.mapBfRange(hexToInt(start, ucs2DataSize),
|
cMap.mapBfRange(
|
||||||
|
hexToInt(start, ucs2DataSize),
|
||||||
hexToInt(end, ucs2DataSize),
|
hexToInt(end, ucs2DataSize),
|
||||||
hexToStr(charCode, dataSize));
|
hexToStr(charCode, dataSize)
|
||||||
|
);
|
||||||
for (i = 1; i < subitemsCount; i++) {
|
for (i = 1; i < subitemsCount; i++) {
|
||||||
incHex(end, ucs2DataSize);
|
incHex(end, ucs2DataSize);
|
||||||
if (!sequence) {
|
if (!sequence) {
|
||||||
@ -663,13 +692,15 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
|||||||
stream.readHexNumber(end, ucs2DataSize);
|
stream.readHexNumber(end, ucs2DataSize);
|
||||||
addHex(end, start, ucs2DataSize);
|
addHex(end, start, ucs2DataSize);
|
||||||
stream.readHex(charCode, dataSize);
|
stream.readHex(charCode, dataSize);
|
||||||
cMap.mapBfRange(hexToInt(start, ucs2DataSize),
|
cMap.mapBfRange(
|
||||||
|
hexToInt(start, ucs2DataSize),
|
||||||
hexToInt(end, ucs2DataSize),
|
hexToInt(end, ucs2DataSize),
|
||||||
hexToStr(charCode, dataSize));
|
hexToStr(charCode, dataSize)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
reject(new Error('processBinaryCMap: Unknown type: ' + type));
|
reject(new Error("processBinaryCMap: Unknown type: " + type));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -702,13 +733,13 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
|
|
||||||
function expectString(obj) {
|
function expectString(obj) {
|
||||||
if (!isString(obj)) {
|
if (!isString(obj)) {
|
||||||
throw new FormatError('Malformed CMap: expected string.');
|
throw new FormatError("Malformed CMap: expected string.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectInt(obj) {
|
function expectInt(obj) {
|
||||||
if (!Number.isInteger(obj)) {
|
if (!Number.isInteger(obj)) {
|
||||||
throw new FormatError('Malformed CMap: expected int.');
|
throw new FormatError("Malformed CMap: expected int.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,7 +749,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
if (isEOF(obj)) {
|
if (isEOF(obj)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isCmd(obj, 'endbfchar')) {
|
if (isCmd(obj, "endbfchar")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
expectString(obj);
|
expectString(obj);
|
||||||
@ -737,7 +768,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
if (isEOF(obj)) {
|
if (isEOF(obj)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isCmd(obj, 'endbfrange')) {
|
if (isCmd(obj, "endbfrange")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
expectString(obj);
|
expectString(obj);
|
||||||
@ -749,10 +780,10 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
if (Number.isInteger(obj) || isString(obj)) {
|
if (Number.isInteger(obj) || isString(obj)) {
|
||||||
var dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj;
|
var dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj;
|
||||||
cMap.mapBfRange(low, high, dstLow);
|
cMap.mapBfRange(low, high, dstLow);
|
||||||
} else if (isCmd(obj, '[')) {
|
} else if (isCmd(obj, "[")) {
|
||||||
obj = lexer.getObj();
|
obj = lexer.getObj();
|
||||||
var array = [];
|
var array = [];
|
||||||
while (!isCmd(obj, ']') && !isEOF(obj)) {
|
while (!isCmd(obj, "]") && !isEOF(obj)) {
|
||||||
array.push(obj);
|
array.push(obj);
|
||||||
obj = lexer.getObj();
|
obj = lexer.getObj();
|
||||||
}
|
}
|
||||||
@ -761,7 +792,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new FormatError('Invalid bf range.');
|
throw new FormatError("Invalid bf range.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseCidChar(cMap, lexer) {
|
function parseCidChar(cMap, lexer) {
|
||||||
@ -770,7 +801,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
if (isEOF(obj)) {
|
if (isEOF(obj)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isCmd(obj, 'endcidchar')) {
|
if (isCmd(obj, "endcidchar")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
expectString(obj);
|
expectString(obj);
|
||||||
@ -788,7 +819,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
if (isEOF(obj)) {
|
if (isEOF(obj)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isCmd(obj, 'endcidrange')) {
|
if (isCmd(obj, "endcidrange")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
expectString(obj);
|
expectString(obj);
|
||||||
@ -809,7 +840,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
if (isEOF(obj)) {
|
if (isEOF(obj)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (isCmd(obj, 'endcodespacerange')) {
|
if (isCmd(obj, "endcodespacerange")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isString(obj)) {
|
if (!isString(obj)) {
|
||||||
@ -823,7 +854,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
var high = strToInt(obj);
|
var high = strToInt(obj);
|
||||||
cMap.addCodespaceRange(obj.length, low, high);
|
cMap.addCodespaceRange(obj.length, low, high);
|
||||||
}
|
}
|
||||||
throw new FormatError('Invalid codespace range.');
|
throw new FormatError("Invalid codespace range.");
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseWMode(cMap, lexer) {
|
function parseWMode(cMap, lexer) {
|
||||||
@ -849,34 +880,34 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
if (isEOF(obj)) {
|
if (isEOF(obj)) {
|
||||||
break;
|
break;
|
||||||
} else if (isName(obj)) {
|
} else if (isName(obj)) {
|
||||||
if (obj.name === 'WMode') {
|
if (obj.name === "WMode") {
|
||||||
parseWMode(cMap, lexer);
|
parseWMode(cMap, lexer);
|
||||||
} else if (obj.name === 'CMapName') {
|
} else if (obj.name === "CMapName") {
|
||||||
parseCMapName(cMap, lexer);
|
parseCMapName(cMap, lexer);
|
||||||
}
|
}
|
||||||
previous = obj;
|
previous = obj;
|
||||||
} else if (isCmd(obj)) {
|
} else if (isCmd(obj)) {
|
||||||
switch (obj.cmd) {
|
switch (obj.cmd) {
|
||||||
case 'endcmap':
|
case "endcmap":
|
||||||
break objLoop;
|
break objLoop;
|
||||||
case 'usecmap':
|
case "usecmap":
|
||||||
if (isName(previous)) {
|
if (isName(previous)) {
|
||||||
embeddedUseCMap = previous.name;
|
embeddedUseCMap = previous.name;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'begincodespacerange':
|
case "begincodespacerange":
|
||||||
parseCodespaceRange(cMap, lexer);
|
parseCodespaceRange(cMap, lexer);
|
||||||
break;
|
break;
|
||||||
case 'beginbfchar':
|
case "beginbfchar":
|
||||||
parseBfChar(cMap, lexer);
|
parseBfChar(cMap, lexer);
|
||||||
break;
|
break;
|
||||||
case 'begincidchar':
|
case "begincidchar":
|
||||||
parseCidChar(cMap, lexer);
|
parseCidChar(cMap, lexer);
|
||||||
break;
|
break;
|
||||||
case 'beginbfrange':
|
case "beginbfrange":
|
||||||
parseBfRange(cMap, lexer);
|
parseBfRange(cMap, lexer);
|
||||||
break;
|
break;
|
||||||
case 'begincidrange':
|
case "begincidrange":
|
||||||
parseCidRange(cMap, lexer);
|
parseCidRange(cMap, lexer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -885,7 +916,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
if (ex instanceof MissingDataException) {
|
if (ex instanceof MissingDataException) {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
warn('Invalid cMap data: ' + ex);
|
warn("Invalid cMap data: " + ex);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -926,26 +957,29 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createBuiltInCMap(name, fetchBuiltInCMap) {
|
function createBuiltInCMap(name, fetchBuiltInCMap) {
|
||||||
if (name === 'Identity-H') {
|
if (name === "Identity-H") {
|
||||||
return Promise.resolve(new IdentityCMap(false, 2));
|
return Promise.resolve(new IdentityCMap(false, 2));
|
||||||
} else if (name === 'Identity-V') {
|
} else if (name === "Identity-V") {
|
||||||
return Promise.resolve(new IdentityCMap(true, 2));
|
return Promise.resolve(new IdentityCMap(true, 2));
|
||||||
}
|
}
|
||||||
if (!BUILT_IN_CMAPS.includes(name)) {
|
if (!BUILT_IN_CMAPS.includes(name)) {
|
||||||
return Promise.reject(new Error('Unknown CMap name: ' + name));
|
return Promise.reject(new Error("Unknown CMap name: " + name));
|
||||||
}
|
}
|
||||||
if (!fetchBuiltInCMap) {
|
if (!fetchBuiltInCMap) {
|
||||||
return Promise.reject(new Error(
|
return Promise.reject(
|
||||||
'Built-in CMap parameters are not provided.'));
|
new Error("Built-in CMap parameters are not provided.")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fetchBuiltInCMap(name).then(function(data) {
|
return fetchBuiltInCMap(name).then(function(data) {
|
||||||
var cMapData = data.cMapData, compressionType = data.compressionType;
|
var cMapData = data.cMapData,
|
||||||
|
compressionType = data.compressionType;
|
||||||
var cMap = new CMap(true);
|
var cMap = new CMap(true);
|
||||||
|
|
||||||
if (compressionType === CMapCompressionType.BINARY) {
|
if (compressionType === CMapCompressionType.BINARY) {
|
||||||
return new BinaryCMapReader().process(cMapData, cMap,
|
return new BinaryCMapReader().process(cMapData, cMap, function(
|
||||||
function (useCMap) {
|
useCMap
|
||||||
|
) {
|
||||||
return extendCMap(cMap, fetchBuiltInCMap, useCMap);
|
return extendCMap(cMap, fetchBuiltInCMap, useCMap);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -953,8 +987,11 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
var lexer = new Lexer(new Stream(cMapData));
|
var lexer = new Lexer(new Stream(cMapData));
|
||||||
return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
|
return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
|
||||||
}
|
}
|
||||||
return Promise.reject(new Error(
|
return Promise.reject(
|
||||||
'TODO: Only BINARY/NONE CMap compression is currently supported.'));
|
new Error(
|
||||||
|
"TODO: Only BINARY/NONE CMap compression is currently supported."
|
||||||
|
)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -969,21 +1006,18 @@ var CMapFactory = (function CMapFactoryClosure() {
|
|||||||
} else if (isStream(encoding)) {
|
} else if (isStream(encoding)) {
|
||||||
var cMap = new CMap();
|
var cMap = new CMap();
|
||||||
var lexer = new Lexer(encoding);
|
var lexer = new Lexer(encoding);
|
||||||
return parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap).then(
|
return parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap).then(function(
|
||||||
function (parsedCMap) {
|
parsedCMap
|
||||||
|
) {
|
||||||
if (parsedCMap.isIdentityCMap) {
|
if (parsedCMap.isIdentityCMap) {
|
||||||
return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
|
return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
|
||||||
}
|
}
|
||||||
return parsedCMap;
|
return parsedCMap;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Promise.reject(new Error('Encoding required.'));
|
return Promise.reject(new Error("Encoding required."));
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { CMap, IdentityCMap, CMapFactory };
|
||||||
CMap,
|
|
||||||
IdentityCMap,
|
|
||||||
CMapFactory,
|
|
||||||
};
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import { assert, BaseException, warn } from '../shared/util';
|
import { assert, BaseException, warn } from "../shared/util";
|
||||||
|
|
||||||
function getLookupTableFactory(initializer) {
|
function getLookupTableFactory(initializer) {
|
||||||
let lookup;
|
let lookup;
|
||||||
@ -61,8 +61,12 @@ class XRefParseException extends BaseException { }
|
|||||||
* chain, for example to be able to find `\Resources` placed on multiple
|
* chain, for example to be able to find `\Resources` placed on multiple
|
||||||
* levels of the tree. The default value is `true`.
|
* levels of the tree. The default value is `true`.
|
||||||
*/
|
*/
|
||||||
function getInheritableProperty({ dict, key, getArray = false,
|
function getInheritableProperty({
|
||||||
stopWhenFound = true, }) {
|
dict,
|
||||||
|
key,
|
||||||
|
getArray = false,
|
||||||
|
stopWhenFound = true,
|
||||||
|
}) {
|
||||||
const LOOP_LIMIT = 100;
|
const LOOP_LIMIT = 100;
|
||||||
let loopCount = 0;
|
let loopCount = 0;
|
||||||
let values;
|
let values;
|
||||||
@ -82,16 +86,16 @@ function getInheritableProperty({ dict, key, getArray = false,
|
|||||||
warn(`getInheritableProperty: maximum loop count exceeded for "${key}"`);
|
warn(`getInheritableProperty: maximum loop count exceeded for "${key}"`);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dict = dict.get('Parent');
|
dict = dict.get("Parent");
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const ROMAN_NUMBER_MAP = [
|
const ROMAN_NUMBER_MAP = [
|
||||||
'', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM',
|
"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM",
|
||||||
'', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC',
|
"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC",
|
||||||
'', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'
|
"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -102,13 +106,16 @@ const ROMAN_NUMBER_MAP = [
|
|||||||
* @returns {string} The resulting Roman number.
|
* @returns {string} The resulting Roman number.
|
||||||
*/
|
*/
|
||||||
function toRomanNumerals(number, lowerCase = false) {
|
function toRomanNumerals(number, lowerCase = false) {
|
||||||
assert(Number.isInteger(number) && number > 0,
|
assert(
|
||||||
'The number should be a positive integer.');
|
Number.isInteger(number) && number > 0,
|
||||||
let pos, romanBuf = [];
|
"The number should be a positive integer."
|
||||||
|
);
|
||||||
|
let pos,
|
||||||
|
romanBuf = [];
|
||||||
// Thousands
|
// Thousands
|
||||||
while (number >= 1000) {
|
while (number >= 1000) {
|
||||||
number -= 1000;
|
number -= 1000;
|
||||||
romanBuf.push('M');
|
romanBuf.push("M");
|
||||||
}
|
}
|
||||||
// Hundreds
|
// Hundreds
|
||||||
pos = (number / 100) | 0;
|
pos = (number / 100) | 0;
|
||||||
@ -121,8 +128,8 @@ function toRomanNumerals(number, lowerCase = false) {
|
|||||||
// Ones
|
// Ones
|
||||||
romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
|
romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
|
||||||
|
|
||||||
const romanStr = romanBuf.join('');
|
const romanStr = romanBuf.join("");
|
||||||
return (lowerCase ? romanStr.toLowerCase() : romanStr);
|
return lowerCase ? romanStr.toLowerCase() : romanStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,35 +15,60 @@
|
|||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
assert, FormatError, info, InvalidPDFException, isArrayBuffer, isArrayEqual,
|
assert,
|
||||||
isBool, isNum, isSpace, isString, OPS, shadow, stringToBytes,
|
FormatError,
|
||||||
stringToPDFString, Util, warn
|
info,
|
||||||
} from '../shared/util';
|
InvalidPDFException,
|
||||||
import { Catalog, ObjectLoader, XRef } from './obj';
|
isArrayBuffer,
|
||||||
import { Dict, isDict, isName, isStream, Ref } from './primitives';
|
isArrayEqual,
|
||||||
|
isBool,
|
||||||
|
isNum,
|
||||||
|
isSpace,
|
||||||
|
isString,
|
||||||
|
OPS,
|
||||||
|
shadow,
|
||||||
|
stringToBytes,
|
||||||
|
stringToPDFString,
|
||||||
|
Util,
|
||||||
|
warn,
|
||||||
|
} from "../shared/util";
|
||||||
|
import { Catalog, ObjectLoader, XRef } from "./obj";
|
||||||
|
import { Dict, isDict, isName, isStream, Ref } from "./primitives";
|
||||||
import {
|
import {
|
||||||
getInheritableProperty, MissingDataException, XRefEntryException,
|
getInheritableProperty,
|
||||||
XRefParseException
|
MissingDataException,
|
||||||
} from './core_utils';
|
XRefEntryException,
|
||||||
import { NullStream, Stream, StreamsSequenceStream } from './stream';
|
XRefParseException,
|
||||||
import { AnnotationFactory } from './annotation';
|
} from "./core_utils";
|
||||||
import { calculateMD5 } from './crypto';
|
import { NullStream, Stream, StreamsSequenceStream } from "./stream";
|
||||||
import { Linearization } from './parser';
|
import { AnnotationFactory } from "./annotation";
|
||||||
import { OperatorList } from './operator_list';
|
import { calculateMD5 } from "./crypto";
|
||||||
import { PartialEvaluator } from './evaluator';
|
import { Linearization } from "./parser";
|
||||||
import { PDFFunctionFactory } from './function';
|
import { OperatorList } from "./operator_list";
|
||||||
|
import { PartialEvaluator } from "./evaluator";
|
||||||
|
import { PDFFunctionFactory } from "./function";
|
||||||
|
|
||||||
const DEFAULT_USER_UNIT = 1.0;
|
const DEFAULT_USER_UNIT = 1.0;
|
||||||
const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
|
const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
|
||||||
|
|
||||||
function isAnnotationRenderable(annotation, intent) {
|
function isAnnotationRenderable(annotation, intent) {
|
||||||
return (intent === 'display' && annotation.viewable) ||
|
return (
|
||||||
(intent === 'print' && annotation.printable);
|
(intent === "display" && annotation.viewable) ||
|
||||||
|
(intent === "print" && annotation.printable)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Page {
|
class Page {
|
||||||
constructor({ pdfManager, xref, pageIndex, pageDict, ref, fontCache,
|
constructor({
|
||||||
builtInCMapCache, pdfFunctionFactory, }) {
|
pdfManager,
|
||||||
|
xref,
|
||||||
|
pageIndex,
|
||||||
|
pageDict,
|
||||||
|
ref,
|
||||||
|
fontCache,
|
||||||
|
builtInCMapCache,
|
||||||
|
pdfFunctionFactory,
|
||||||
|
}) {
|
||||||
this.pdfManager = pdfManager;
|
this.pdfManager = pdfManager;
|
||||||
this.pageIndex = pageIndex;
|
this.pageIndex = pageIndex;
|
||||||
this.pageDict = pageDict;
|
this.pageDict = pageDict;
|
||||||
@ -72,8 +97,12 @@ class Page {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_getInheritableProperty(key, getArray = false) {
|
_getInheritableProperty(key, getArray = false) {
|
||||||
const value = getInheritableProperty({ dict: this.pageDict, key, getArray,
|
const value = getInheritableProperty({
|
||||||
stopWhenFound: false, });
|
dict: this.pageDict,
|
||||||
|
key,
|
||||||
|
getArray,
|
||||||
|
stopWhenFound: false,
|
||||||
|
});
|
||||||
if (!Array.isArray(value)) {
|
if (!Array.isArray(value)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -84,22 +113,25 @@ class Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get content() {
|
get content() {
|
||||||
return this.pageDict.get('Contents');
|
return this.pageDict.get("Contents");
|
||||||
}
|
}
|
||||||
|
|
||||||
get resources() {
|
get resources() {
|
||||||
// For robustness: The spec states that a \Resources entry has to be
|
// For robustness: The spec states that a \Resources entry has to be
|
||||||
// present, but can be empty. Some documents still omit it; in this case
|
// present, but can be empty. Some documents still omit it; in this case
|
||||||
// we return an empty dictionary.
|
// we return an empty dictionary.
|
||||||
return shadow(this, 'resources',
|
return shadow(
|
||||||
this._getInheritableProperty('Resources') || Dict.empty);
|
this,
|
||||||
|
"resources",
|
||||||
|
this._getInheritableProperty("Resources") || Dict.empty
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getBoundingBox(name) {
|
_getBoundingBox(name) {
|
||||||
const box = this._getInheritableProperty(name, /* getArray = */ true);
|
const box = this._getInheritableProperty(name, /* getArray = */ true);
|
||||||
|
|
||||||
if (Array.isArray(box) && box.length === 4) {
|
if (Array.isArray(box) && box.length === 4) {
|
||||||
if ((box[2] - box[0]) !== 0 && (box[3] - box[1]) !== 0) {
|
if (box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
|
||||||
return box;
|
return box;
|
||||||
}
|
}
|
||||||
warn(`Empty /${name} entry.`);
|
warn(`Empty /${name} entry.`);
|
||||||
@ -109,22 +141,28 @@ class Page {
|
|||||||
|
|
||||||
get mediaBox() {
|
get mediaBox() {
|
||||||
// Reset invalid media box to letter size.
|
// Reset invalid media box to letter size.
|
||||||
return shadow(this, 'mediaBox',
|
return shadow(
|
||||||
this._getBoundingBox('MediaBox') || LETTER_SIZE_MEDIABOX);
|
this,
|
||||||
|
"mediaBox",
|
||||||
|
this._getBoundingBox("MediaBox") || LETTER_SIZE_MEDIABOX
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get cropBox() {
|
get cropBox() {
|
||||||
// Reset invalid crop box to media box.
|
// Reset invalid crop box to media box.
|
||||||
return shadow(this, 'cropBox',
|
return shadow(
|
||||||
this._getBoundingBox('CropBox') || this.mediaBox);
|
this,
|
||||||
|
"cropBox",
|
||||||
|
this._getBoundingBox("CropBox") || this.mediaBox
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get userUnit() {
|
get userUnit() {
|
||||||
let obj = this.pageDict.get('UserUnit');
|
let obj = this.pageDict.get("UserUnit");
|
||||||
if (!isNum(obj) || obj <= 0) {
|
if (!isNum(obj) || obj <= 0) {
|
||||||
obj = DEFAULT_USER_UNIT;
|
obj = DEFAULT_USER_UNIT;
|
||||||
}
|
}
|
||||||
return shadow(this, 'userUnit', obj);
|
return shadow(this, "userUnit", obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
get view() {
|
get view() {
|
||||||
@ -132,23 +170,23 @@ class Page {
|
|||||||
// "The crop, bleed, trim, and art boxes should not ordinarily
|
// "The crop, bleed, trim, and art boxes should not ordinarily
|
||||||
// extend beyond the boundaries of the media box. If they do, they are
|
// extend beyond the boundaries of the media box. If they do, they are
|
||||||
// effectively reduced to their intersection with the media box."
|
// effectively reduced to their intersection with the media box."
|
||||||
const { cropBox, mediaBox, } = this;
|
const { cropBox, mediaBox } = this;
|
||||||
let view;
|
let view;
|
||||||
if (cropBox === mediaBox || isArrayEqual(cropBox, mediaBox)) {
|
if (cropBox === mediaBox || isArrayEqual(cropBox, mediaBox)) {
|
||||||
view = mediaBox;
|
view = mediaBox;
|
||||||
} else {
|
} else {
|
||||||
const box = Util.intersect(cropBox, mediaBox);
|
const box = Util.intersect(cropBox, mediaBox);
|
||||||
if (box && ((box[2] - box[0]) !== 0 && (box[3] - box[1]) !== 0)) {
|
if (box && box[2] - box[0] !== 0 && box[3] - box[1] !== 0) {
|
||||||
view = box;
|
view = box;
|
||||||
} else {
|
} else {
|
||||||
warn('Empty /CropBox and /MediaBox intersection.');
|
warn("Empty /CropBox and /MediaBox intersection.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shadow(this, 'view', view || mediaBox);
|
return shadow(this, "view", view || mediaBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
get rotate() {
|
get rotate() {
|
||||||
let rotate = this._getInheritableProperty('Rotate') || 0;
|
let rotate = this._getInheritableProperty("Rotate") || 0;
|
||||||
|
|
||||||
// Normalize rotation so it's a multiple of 90 and between 0 and 270.
|
// Normalize rotation so it's a multiple of 90 and between 0 and 270.
|
||||||
if (rotate % 90 !== 0) {
|
if (rotate % 90 !== 0) {
|
||||||
@ -160,7 +198,7 @@ class Page {
|
|||||||
// rotation. The following is the other implementation of modulo.
|
// rotation. The following is the other implementation of modulo.
|
||||||
rotate = ((rotate % 360) + 360) % 360;
|
rotate = ((rotate % 360) + 360) % 360;
|
||||||
}
|
}
|
||||||
return shadow(this, 'rotate', rotate);
|
return shadow(this, "rotate", rotate);
|
||||||
}
|
}
|
||||||
|
|
||||||
getContentStream() {
|
getContentStream() {
|
||||||
@ -187,7 +225,7 @@ class Page {
|
|||||||
loadResources(keys) {
|
loadResources(keys) {
|
||||||
if (!this.resourcesPromise) {
|
if (!this.resourcesPromise) {
|
||||||
// TODO: add async `_getInheritableProperty` and remove this.
|
// TODO: add async `_getInheritableProperty` and remove this.
|
||||||
this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
|
this.resourcesPromise = this.pdfManager.ensure(this, "resources");
|
||||||
}
|
}
|
||||||
return this.resourcesPromise.then(() => {
|
return this.resourcesPromise.then(() => {
|
||||||
const objectLoader = new ObjectLoader(this.resources, keys, this.xref);
|
const objectLoader = new ObjectLoader(this.resources, keys, this.xref);
|
||||||
@ -195,16 +233,18 @@ class Page {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getOperatorList({ handler, sink, task, intent, renderInteractiveForms, }) {
|
getOperatorList({ handler, sink, task, intent, renderInteractiveForms }) {
|
||||||
const contentStreamPromise = this.pdfManager.ensure(this,
|
const contentStreamPromise = this.pdfManager.ensure(
|
||||||
'getContentStream');
|
this,
|
||||||
|
"getContentStream"
|
||||||
|
);
|
||||||
const resourcesPromise = this.loadResources([
|
const resourcesPromise = this.loadResources([
|
||||||
'ExtGState',
|
"ExtGState",
|
||||||
'ColorSpace',
|
"ColorSpace",
|
||||||
'Pattern',
|
"Pattern",
|
||||||
'Shading',
|
"Shading",
|
||||||
'XObject',
|
"XObject",
|
||||||
'Font',
|
"Font",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const partialEvaluator = new PartialEvaluator({
|
const partialEvaluator = new PartialEvaluator({
|
||||||
@ -222,18 +262,20 @@ class Page {
|
|||||||
const pageListPromise = dataPromises.then(([contentStream]) => {
|
const pageListPromise = dataPromises.then(([contentStream]) => {
|
||||||
const opList = new OperatorList(intent, sink, this.pageIndex);
|
const opList = new OperatorList(intent, sink, this.pageIndex);
|
||||||
|
|
||||||
handler.send('StartRenderPage', {
|
handler.send("StartRenderPage", {
|
||||||
transparency: partialEvaluator.hasBlendModes(this.resources),
|
transparency: partialEvaluator.hasBlendModes(this.resources),
|
||||||
pageIndex: this.pageIndex,
|
pageIndex: this.pageIndex,
|
||||||
intent,
|
intent,
|
||||||
});
|
});
|
||||||
|
|
||||||
return partialEvaluator.getOperatorList({
|
return partialEvaluator
|
||||||
|
.getOperatorList({
|
||||||
stream: contentStream,
|
stream: contentStream,
|
||||||
task,
|
task,
|
||||||
resources: this.resources,
|
resources: this.resources,
|
||||||
operatorList: opList,
|
operatorList: opList,
|
||||||
}).then(function() {
|
})
|
||||||
|
.then(function() {
|
||||||
return opList;
|
return opList;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -244,7 +286,7 @@ class Page {
|
|||||||
function([pageOpList, annotations]) {
|
function([pageOpList, annotations]) {
|
||||||
if (annotations.length === 0) {
|
if (annotations.length === 0) {
|
||||||
pageOpList.flush(true);
|
pageOpList.flush(true);
|
||||||
return { length: pageOpList.totalLength, };
|
return { length: pageOpList.totalLength };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect the operator list promises for the annotations. Each promise
|
// Collect the operator list promises for the annotations. Each promise
|
||||||
@ -252,8 +294,13 @@ class Page {
|
|||||||
const opListPromises = [];
|
const opListPromises = [];
|
||||||
for (const annotation of annotations) {
|
for (const annotation of annotations) {
|
||||||
if (isAnnotationRenderable(annotation, intent)) {
|
if (isAnnotationRenderable(annotation, intent)) {
|
||||||
opListPromises.push(annotation.getOperatorList(
|
opListPromises.push(
|
||||||
partialEvaluator, task, renderInteractiveForms));
|
annotation.getOperatorList(
|
||||||
|
partialEvaluator,
|
||||||
|
task,
|
||||||
|
renderInteractiveForms
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,19 +311,27 @@ class Page {
|
|||||||
}
|
}
|
||||||
pageOpList.addOp(OPS.endAnnotations, []);
|
pageOpList.addOp(OPS.endAnnotations, []);
|
||||||
pageOpList.flush(true);
|
pageOpList.flush(true);
|
||||||
return { length: pageOpList.totalLength, };
|
return { length: pageOpList.totalLength };
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
extractTextContent({ handler, task, normalizeWhitespace, sink,
|
extractTextContent({
|
||||||
combineTextItems, }) {
|
handler,
|
||||||
const contentStreamPromise = this.pdfManager.ensure(this,
|
task,
|
||||||
'getContentStream');
|
normalizeWhitespace,
|
||||||
|
sink,
|
||||||
|
combineTextItems,
|
||||||
|
}) {
|
||||||
|
const contentStreamPromise = this.pdfManager.ensure(
|
||||||
|
this,
|
||||||
|
"getContentStream"
|
||||||
|
);
|
||||||
const resourcesPromise = this.loadResources([
|
const resourcesPromise = this.loadResources([
|
||||||
'ExtGState',
|
"ExtGState",
|
||||||
'XObject',
|
"XObject",
|
||||||
'Font',
|
"Font",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
|
const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
|
||||||
@ -316,47 +371,62 @@ class Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get annotations() {
|
get annotations() {
|
||||||
return shadow(this, 'annotations',
|
return shadow(
|
||||||
this._getInheritableProperty('Annots') || []);
|
this,
|
||||||
|
"annotations",
|
||||||
|
this._getInheritableProperty("Annots") || []
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get _parsedAnnotations() {
|
get _parsedAnnotations() {
|
||||||
const parsedAnnotations =
|
const parsedAnnotations = this.pdfManager
|
||||||
this.pdfManager.ensure(this, 'annotations').then(() => {
|
.ensure(this, "annotations")
|
||||||
|
.then(() => {
|
||||||
const annotationRefs = this.annotations;
|
const annotationRefs = this.annotations;
|
||||||
const annotationPromises = [];
|
const annotationPromises = [];
|
||||||
for (let i = 0, ii = annotationRefs.length; i < ii; i++) {
|
for (let i = 0, ii = annotationRefs.length; i < ii; i++) {
|
||||||
annotationPromises.push(AnnotationFactory.create(
|
annotationPromises.push(
|
||||||
this.xref, annotationRefs[i], this.pdfManager, this.idFactory));
|
AnnotationFactory.create(
|
||||||
|
this.xref,
|
||||||
|
annotationRefs[i],
|
||||||
|
this.pdfManager,
|
||||||
|
this.idFactory
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(annotationPromises).then(function(annotations) {
|
return Promise.all(annotationPromises).then(
|
||||||
|
function(annotations) {
|
||||||
return annotations.filter(function isDefined(annotation) {
|
return annotations.filter(function isDefined(annotation) {
|
||||||
return !!annotation;
|
return !!annotation;
|
||||||
});
|
});
|
||||||
}, function(reason) {
|
},
|
||||||
|
function(reason) {
|
||||||
warn(`_parsedAnnotations: "${reason}".`);
|
warn(`_parsedAnnotations: "${reason}".`);
|
||||||
return [];
|
return [];
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return shadow(this, '_parsedAnnotations', parsedAnnotations);
|
return shadow(this, "_parsedAnnotations", parsedAnnotations);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2D]);
|
const PDF_HEADER_SIGNATURE = new Uint8Array([0x25, 0x50, 0x44, 0x46, 0x2d]);
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const STARTXREF_SIGNATURE = new Uint8Array([
|
const STARTXREF_SIGNATURE = new Uint8Array([
|
||||||
0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]);
|
0x73, 0x74, 0x61, 0x72, 0x74, 0x78, 0x72, 0x65, 0x66]);
|
||||||
const ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6E, 0x64, 0x6F, 0x62, 0x6A]);
|
const ENDOBJ_SIGNATURE = new Uint8Array([0x65, 0x6e, 0x64, 0x6f, 0x62, 0x6a]);
|
||||||
|
|
||||||
const FINGERPRINT_FIRST_BYTES = 1024;
|
const FINGERPRINT_FIRST_BYTES = 1024;
|
||||||
const EMPTY_FINGERPRINT =
|
const EMPTY_FINGERPRINT =
|
||||||
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00';
|
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||||
|
|
||||||
function find(stream, signature, limit = 1024, backwards = false) {
|
function find(stream, signature, limit = 1024, backwards = false) {
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
|
) {
|
||||||
assert(limit > 0, 'The "limit" must be a positive integer.');
|
assert(limit > 0, 'The "limit" must be a positive integer.');
|
||||||
}
|
}
|
||||||
const signatureLength = signature.length;
|
const signatureLength = signature.length;
|
||||||
@ -373,24 +443,29 @@ function find(stream, signature, limit = 1024, backwards = false) {
|
|||||||
let pos = scanBytes.length - 1;
|
let pos = scanBytes.length - 1;
|
||||||
while (pos >= signatureEnd) {
|
while (pos >= signatureEnd) {
|
||||||
let j = 0;
|
let j = 0;
|
||||||
while (j < signatureLength &&
|
while (
|
||||||
scanBytes[pos - j] === signature[signatureEnd - j]) {
|
j < signatureLength &&
|
||||||
|
scanBytes[pos - j] === signature[signatureEnd - j]
|
||||||
|
) {
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
if (j >= signatureLength) { // `signature` found.
|
if (j >= signatureLength) {
|
||||||
stream.pos += (pos - signatureEnd);
|
// `signature` found.
|
||||||
|
stream.pos += pos - signatureEnd;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
pos--;
|
pos--;
|
||||||
}
|
}
|
||||||
} else { // forwards
|
} else {
|
||||||
|
// forwards
|
||||||
let pos = 0;
|
let pos = 0;
|
||||||
while (pos <= scanLength) {
|
while (pos <= scanLength) {
|
||||||
let j = 0;
|
let j = 0;
|
||||||
while (j < signatureLength && scanBytes[pos + j] === signature[j]) {
|
while (j < signatureLength && scanBytes[pos + j] === signature[j]) {
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
if (j >= signatureLength) { // `signature` found.
|
if (j >= signatureLength) {
|
||||||
|
// `signature` found.
|
||||||
stream.pos += pos;
|
stream.pos += pos;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -411,11 +486,12 @@ class PDFDocument {
|
|||||||
} else if (isArrayBuffer(arg)) {
|
} else if (isArrayBuffer(arg)) {
|
||||||
stream = new Stream(arg);
|
stream = new Stream(arg);
|
||||||
} else {
|
} else {
|
||||||
throw new Error('PDFDocument: Unknown argument type');
|
throw new Error("PDFDocument: Unknown argument type");
|
||||||
}
|
}
|
||||||
if (stream.length <= 0) {
|
if (stream.length <= 0) {
|
||||||
throw new InvalidPDFException(
|
throw new InvalidPDFException(
|
||||||
'The PDF file is empty, i.e. its size is zero bytes.');
|
"The PDF file is empty, i.e. its size is zero bytes."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pdfManager = pdfManager;
|
this.pdfManager = pdfManager;
|
||||||
@ -432,17 +508,17 @@ class PDFDocument {
|
|||||||
parse(recoveryMode) {
|
parse(recoveryMode) {
|
||||||
this.setup(recoveryMode);
|
this.setup(recoveryMode);
|
||||||
|
|
||||||
const version = this.catalog.catDict.get('Version');
|
const version = this.catalog.catDict.get("Version");
|
||||||
if (isName(version)) {
|
if (isName(version)) {
|
||||||
this.pdfFormatVersion = version.name;
|
this.pdfFormatVersion = version.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if AcroForms are present in the document.
|
// Check if AcroForms are present in the document.
|
||||||
try {
|
try {
|
||||||
this.acroForm = this.catalog.catDict.get('AcroForm');
|
this.acroForm = this.catalog.catDict.get("AcroForm");
|
||||||
if (this.acroForm) {
|
if (this.acroForm) {
|
||||||
this.xfa = this.acroForm.get('XFA');
|
this.xfa = this.acroForm.get("XFA");
|
||||||
const fields = this.acroForm.get('Fields');
|
const fields = this.acroForm.get("Fields");
|
||||||
if ((!Array.isArray(fields) || fields.length === 0) && !this.xfa) {
|
if ((!Array.isArray(fields) || fields.length === 0) && !this.xfa) {
|
||||||
this.acroForm = null; // No fields and no XFA, so it's not a form.
|
this.acroForm = null; // No fields and no XFA, so it's not a form.
|
||||||
}
|
}
|
||||||
@ -451,13 +527,13 @@ class PDFDocument {
|
|||||||
if (ex instanceof MissingDataException) {
|
if (ex instanceof MissingDataException) {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
info('Cannot fetch AcroForm entry; assuming no AcroForms are present');
|
info("Cannot fetch AcroForm entry; assuming no AcroForms are present");
|
||||||
this.acroForm = null;
|
this.acroForm = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a Collection dictionary is present in the document.
|
// Check if a Collection dictionary is present in the document.
|
||||||
try {
|
try {
|
||||||
const collection = this.catalog.catDict.get('Collection');
|
const collection = this.catalog.catDict.get("Collection");
|
||||||
if (isDict(collection) && collection.getKeys().length > 0) {
|
if (isDict(collection) && collection.getKeys().length > 0) {
|
||||||
this.collection = collection;
|
this.collection = collection;
|
||||||
}
|
}
|
||||||
@ -465,7 +541,7 @@ class PDFDocument {
|
|||||||
if (ex instanceof MissingDataException) {
|
if (ex instanceof MissingDataException) {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
info('Cannot fetch Collection dictionary.');
|
info("Cannot fetch Collection dictionary.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,7 +555,7 @@ class PDFDocument {
|
|||||||
}
|
}
|
||||||
info(err);
|
info(err);
|
||||||
}
|
}
|
||||||
return shadow(this, 'linearization', linearization);
|
return shadow(this, "linearization", linearization);
|
||||||
}
|
}
|
||||||
|
|
||||||
get startXRef() {
|
get startXRef() {
|
||||||
@ -490,13 +566,14 @@ class PDFDocument {
|
|||||||
// Find the end of the first object.
|
// Find the end of the first object.
|
||||||
stream.reset();
|
stream.reset();
|
||||||
if (find(stream, ENDOBJ_SIGNATURE)) {
|
if (find(stream, ENDOBJ_SIGNATURE)) {
|
||||||
startXRef = (stream.pos + 6) - stream.start;
|
startXRef = stream.pos + 6 - stream.start;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Find `startxref` by checking backwards from the end of the file.
|
// Find `startxref` by checking backwards from the end of the file.
|
||||||
const step = 1024;
|
const step = 1024;
|
||||||
const startXRefLength = STARTXREF_SIGNATURE.length;
|
const startXRefLength = STARTXREF_SIGNATURE.length;
|
||||||
let found = false, pos = stream.end;
|
let found = false,
|
||||||
|
pos = stream.end;
|
||||||
|
|
||||||
while (!found && pos > 0) {
|
while (!found && pos > 0) {
|
||||||
pos -= step - startXRefLength;
|
pos -= step - startXRefLength;
|
||||||
@ -513,8 +590,9 @@ class PDFDocument {
|
|||||||
do {
|
do {
|
||||||
ch = stream.getByte();
|
ch = stream.getByte();
|
||||||
} while (isSpace(ch));
|
} while (isSpace(ch));
|
||||||
let str = '';
|
let str = "";
|
||||||
while (ch >= 0x20 && ch <= 0x39) { // < '9'
|
while (ch >= 0x20 && ch <= 0x39) {
|
||||||
|
// < '9'
|
||||||
str += String.fromCharCode(ch);
|
str += String.fromCharCode(ch);
|
||||||
ch = stream.getByte();
|
ch = stream.getByte();
|
||||||
}
|
}
|
||||||
@ -524,7 +602,7 @@ class PDFDocument {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shadow(this, 'startXRef', startXRef);
|
return shadow(this, "startXRef", startXRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the header, get the PDF format version and setup the
|
// Find the header, get the PDF format version and setup the
|
||||||
@ -542,8 +620,10 @@ class PDFDocument {
|
|||||||
|
|
||||||
// Read the PDF format version.
|
// Read the PDF format version.
|
||||||
const MAX_PDF_VERSION_LENGTH = 12;
|
const MAX_PDF_VERSION_LENGTH = 12;
|
||||||
let version = '', ch;
|
let version = "",
|
||||||
while ((ch = stream.getByte()) > 0x20) { // Space
|
ch;
|
||||||
|
while ((ch = stream.getByte()) > 0x20) {
|
||||||
|
// Space
|
||||||
if (version.length >= MAX_PDF_VERSION_LENGTH) {
|
if (version.length >= MAX_PDF_VERSION_LENGTH) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -567,7 +647,7 @@ class PDFDocument {
|
|||||||
get numPages() {
|
get numPages() {
|
||||||
const linearization = this.linearization;
|
const linearization = this.linearization;
|
||||||
const num = linearization ? linearization.numPages : this.catalog.numPages;
|
const num = linearization ? linearization.numPages : this.catalog.numPages;
|
||||||
return shadow(this, 'numPages', num);
|
return shadow(this, "numPages", num);
|
||||||
}
|
}
|
||||||
|
|
||||||
get documentInfo() {
|
get documentInfo() {
|
||||||
@ -593,12 +673,12 @@ class PDFDocument {
|
|||||||
|
|
||||||
let infoDict;
|
let infoDict;
|
||||||
try {
|
try {
|
||||||
infoDict = this.xref.trailer.get('Info');
|
infoDict = this.xref.trailer.get("Info");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof MissingDataException) {
|
if (err instanceof MissingDataException) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
info('The document information dictionary is invalid.');
|
info("The document information dictionary is invalid.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDict(infoDict)) {
|
if (isDict(infoDict)) {
|
||||||
@ -610,12 +690,12 @@ class PDFDocument {
|
|||||||
if (DocumentInfoValidators[key]) {
|
if (DocumentInfoValidators[key]) {
|
||||||
// Make sure the (standard) value conforms to the specification.
|
// Make sure the (standard) value conforms to the specification.
|
||||||
if (DocumentInfoValidators[key](value)) {
|
if (DocumentInfoValidators[key](value)) {
|
||||||
docInfo[key] = (typeof value !== 'string' ?
|
docInfo[key] =
|
||||||
value : stringToPDFString(value));
|
typeof value !== "string" ? value : stringToPDFString(value);
|
||||||
} else {
|
} else {
|
||||||
info(`Bad value in document info for "${key}".`);
|
info(`Bad value in document info for "${key}".`);
|
||||||
}
|
}
|
||||||
} else if (typeof key === 'string') {
|
} else if (typeof key === "string") {
|
||||||
// For custom values, only accept white-listed types to prevent
|
// For custom values, only accept white-listed types to prevent
|
||||||
// errors that would occur when trying to send non-serializable
|
// errors that would occur when trying to send non-serializable
|
||||||
// objects to the main-thread (for example `Dict` or `Stream`).
|
// objects to the main-thread (for example `Dict` or `Stream`).
|
||||||
@ -629,52 +709,66 @@ class PDFDocument {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!docInfo['Custom']) {
|
if (!docInfo["Custom"]) {
|
||||||
docInfo['Custom'] = Object.create(null);
|
docInfo["Custom"] = Object.create(null);
|
||||||
}
|
}
|
||||||
docInfo['Custom'][key] = customValue;
|
docInfo["Custom"][key] = customValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shadow(this, 'documentInfo', docInfo);
|
return shadow(this, "documentInfo", docInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
get fingerprint() {
|
get fingerprint() {
|
||||||
let hash;
|
let hash;
|
||||||
const idArray = this.xref.trailer.get('ID');
|
const idArray = this.xref.trailer.get("ID");
|
||||||
if (Array.isArray(idArray) && idArray[0] && isString(idArray[0]) &&
|
if (
|
||||||
idArray[0] !== EMPTY_FINGERPRINT) {
|
Array.isArray(idArray) &&
|
||||||
|
idArray[0] &&
|
||||||
|
isString(idArray[0]) &&
|
||||||
|
idArray[0] !== EMPTY_FINGERPRINT
|
||||||
|
) {
|
||||||
hash = stringToBytes(idArray[0]);
|
hash = stringToBytes(idArray[0]);
|
||||||
} else {
|
} else {
|
||||||
hash = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES),
|
hash = calculateMD5(
|
||||||
0, FINGERPRINT_FIRST_BYTES);
|
this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES),
|
||||||
|
0,
|
||||||
|
FINGERPRINT_FIRST_BYTES
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const fingerprintBuf = [];
|
const fingerprintBuf = [];
|
||||||
for (let i = 0, ii = hash.length; i < ii; i++) {
|
for (let i = 0, ii = hash.length; i < ii; i++) {
|
||||||
const hex = hash[i].toString(16);
|
const hex = hash[i].toString(16);
|
||||||
fingerprintBuf.push(hex.padStart(2, '0'));
|
fingerprintBuf.push(hex.padStart(2, "0"));
|
||||||
}
|
}
|
||||||
return shadow(this, 'fingerprint', fingerprintBuf.join(''));
|
return shadow(this, "fingerprint", fingerprintBuf.join(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
_getLinearizationPage(pageIndex) {
|
_getLinearizationPage(pageIndex) {
|
||||||
const { catalog, linearization, } = this;
|
const { catalog, linearization } = this;
|
||||||
assert(linearization && linearization.pageFirst === pageIndex);
|
assert(linearization && linearization.pageFirst === pageIndex);
|
||||||
|
|
||||||
const ref = Ref.get(linearization.objectNumberFirst, 0);
|
const ref = Ref.get(linearization.objectNumberFirst, 0);
|
||||||
return this.xref.fetchAsync(ref).then((obj) => {
|
return this.xref
|
||||||
|
.fetchAsync(ref)
|
||||||
|
.then(obj => {
|
||||||
// Ensure that the object that was found is actually a Page dictionary.
|
// Ensure that the object that was found is actually a Page dictionary.
|
||||||
if (isDict(obj, 'Page') ||
|
if (
|
||||||
(isDict(obj) && !obj.has('Type') && obj.has('Contents'))) {
|
isDict(obj, "Page") ||
|
||||||
|
(isDict(obj) && !obj.has("Type") && obj.has("Contents"))
|
||||||
|
) {
|
||||||
if (ref && !catalog.pageKidsCountCache.has(ref)) {
|
if (ref && !catalog.pageKidsCountCache.has(ref)) {
|
||||||
catalog.pageKidsCountCache.put(ref, 1); // Cache the Page reference.
|
catalog.pageKidsCountCache.put(ref, 1); // Cache the Page reference.
|
||||||
}
|
}
|
||||||
return [obj, ref];
|
return [obj, ref];
|
||||||
}
|
}
|
||||||
throw new FormatError('The Linearization dictionary doesn\'t point ' +
|
throw new FormatError(
|
||||||
'to a valid Page dictionary.');
|
"The Linearization dictionary doesn't point " +
|
||||||
}).catch((reason) => {
|
"to a valid Page dictionary."
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch(reason => {
|
||||||
info(reason);
|
info(reason);
|
||||||
return catalog.getPageDict(pageIndex);
|
return catalog.getPageDict(pageIndex);
|
||||||
});
|
});
|
||||||
@ -684,12 +778,14 @@ class PDFDocument {
|
|||||||
if (this._pagePromises[pageIndex] !== undefined) {
|
if (this._pagePromises[pageIndex] !== undefined) {
|
||||||
return this._pagePromises[pageIndex];
|
return this._pagePromises[pageIndex];
|
||||||
}
|
}
|
||||||
const { catalog, linearization, } = this;
|
const { catalog, linearization } = this;
|
||||||
|
|
||||||
const promise = (linearization && linearization.pageFirst === pageIndex) ?
|
const promise =
|
||||||
this._getLinearizationPage(pageIndex) : catalog.getPageDict(pageIndex);
|
linearization && linearization.pageFirst === pageIndex
|
||||||
|
? this._getLinearizationPage(pageIndex)
|
||||||
|
: catalog.getPageDict(pageIndex);
|
||||||
|
|
||||||
return this._pagePromises[pageIndex] = promise.then(([pageDict, ref]) => {
|
return (this._pagePromises[pageIndex] = promise.then(([pageDict, ref]) => {
|
||||||
return new Page({
|
return new Page({
|
||||||
pdfManager: this.pdfManager,
|
pdfManager: this.pdfManager,
|
||||||
xref: this.xref,
|
xref: this.xref,
|
||||||
@ -700,11 +796,11 @@ class PDFDocument {
|
|||||||
builtInCMapCache: catalog.builtInCMapCache,
|
builtInCMapCache: catalog.builtInCMapCache,
|
||||||
pdfFunctionFactory: this.pdfFunctionFactory,
|
pdfFunctionFactory: this.pdfFunctionFactory,
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFirstPage() {
|
checkFirstPage() {
|
||||||
return this.getPage(0).catch(async (reason) => {
|
return this.getPage(0).catch(async reason => {
|
||||||
if (reason instanceof XRefEntryException) {
|
if (reason instanceof XRefEntryException) {
|
||||||
// Clear out the various caches to ensure that we haven't stored any
|
// Clear out the various caches to ensure that we haven't stored any
|
||||||
// inconsistent and/or incorrect state, since that could easily break
|
// inconsistent and/or incorrect state, since that could easily break
|
||||||
@ -726,7 +822,4 @@ class PDFDocument {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { Page, PDFDocument };
|
||||||
Page,
|
|
||||||
PDFDocument,
|
|
||||||
};
|
|
||||||
|
@ -15,275 +15,275 @@
|
|||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const ExpertEncoding = [
|
const ExpertEncoding = [
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle',
|
"space", "exclamsmall", "Hungarumlautsmall", "", "dollaroldstyle",
|
||||||
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
|
"dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior",
|
||||||
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
|
"parenrightsuperior", "twodotenleader", "onedotenleader", "comma",
|
||||||
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
|
"hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle",
|
||||||
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
|
"twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
|
||||||
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
|
"sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon",
|
||||||
'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior',
|
"semicolon", "commasuperior", "threequartersemdash", "periodsuperior",
|
||||||
'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior',
|
"questionsmall", "", "asuperior", "bsuperior", "centsuperior", "dsuperior",
|
||||||
'esuperior', '', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
|
"esuperior", "", "", "", "isuperior", "", "", "lsuperior", "msuperior",
|
||||||
'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior',
|
"nsuperior", "osuperior", "", "", "rsuperior", "ssuperior", "tsuperior",
|
||||||
'', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '',
|
"", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "",
|
||||||
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
|
"parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
|
||||||
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
|
"Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall",
|
||||||
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
|
"Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
|
||||||
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
|
"Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
|
||||||
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
|
"Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary",
|
||||||
'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '',
|
"onefitted", "rupiah", "Tildesmall", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
|
"", "", "", "", "", "", "exclamdownsmall", "centoldstyle", "Lslashsmall",
|
||||||
'', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall',
|
"", "", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall",
|
||||||
'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '',
|
"Caronsmall", "", "Dotaccentsmall", "", "", "Macronsmall", "", "",
|
||||||
'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall',
|
"figuredash", "hypheninferior", "", "", "Ogoneksmall", "Ringsmall",
|
||||||
'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
|
"Cedillasmall", "", "", "", "onequarter", "onehalf", "threequarters",
|
||||||
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
|
"questiondownsmall", "oneeighth", "threeeighths", "fiveeighths",
|
||||||
'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior',
|
"seveneighths", "onethird", "twothirds", "", "", "zerosuperior",
|
||||||
'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior',
|
"onesuperior", "twosuperior", "threesuperior", "foursuperior",
|
||||||
'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
|
"fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior",
|
||||||
'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
|
"ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
|
||||||
'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
|
"threeinferior", "fourinferior", "fiveinferior", "sixinferior",
|
||||||
'seveninferior', 'eightinferior', 'nineinferior', 'centinferior',
|
"seveninferior", "eightinferior", "nineinferior", "centinferior",
|
||||||
'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
|
"dollarinferior", "periodinferior", "commainferior", "Agravesmall",
|
||||||
'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
|
"Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall",
|
||||||
'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
|
"Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
|
||||||
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
|
"Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
|
||||||
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
|
"Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
|
||||||
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
|
"Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
|
||||||
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
|
"Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall",
|
||||||
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
|
"Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall",
|
||||||
'Ydieresissmall'];
|
"Ydieresissmall"];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const MacExpertEncoding = [
|
const MacExpertEncoding = [
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle',
|
"space", "exclamsmall", "Hungarumlautsmall", "centoldstyle",
|
||||||
'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
|
"dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
|
||||||
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
|
"parenleftsuperior", "parenrightsuperior", "twodotenleader",
|
||||||
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle',
|
"onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle",
|
||||||
'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle',
|
"oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle",
|
||||||
'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle',
|
"fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle",
|
||||||
'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '',
|
"nineoldstyle", "colon", "semicolon", "", "threequartersemdash", "",
|
||||||
'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter',
|
"questionsmall", "", "", "", "", "Ethsmall", "", "", "onequarter",
|
||||||
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
|
"onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths",
|
||||||
'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff',
|
"seveneighths", "onethird", "twothirds", "", "", "", "", "", "", "ff",
|
||||||
'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior',
|
"fi", "fl", "ffi", "ffl", "parenleftinferior", "", "parenrightinferior",
|
||||||
'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall',
|
"Circumflexsmall", "hypheninferior", "Gravesmall", "Asmall", "Bsmall",
|
||||||
'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
|
"Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall",
|
||||||
'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
|
"Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
|
||||||
'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
|
"Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall",
|
||||||
'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
|
"Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah",
|
||||||
'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '',
|
"Tildesmall", "", "", "asuperior", "centsuperior", "", "", "", "",
|
||||||
'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall',
|
"Aacutesmall", "Agravesmall", "Acircumflexsmall", "Adieresissmall",
|
||||||
'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall',
|
"Atildesmall", "Aringsmall", "Ccedillasmall", "Eacutesmall", "Egravesmall",
|
||||||
'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall',
|
"Ecircumflexsmall", "Edieresissmall", "Iacutesmall", "Igravesmall",
|
||||||
'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall',
|
"Icircumflexsmall", "Idieresissmall", "Ntildesmall", "Oacutesmall",
|
||||||
'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall',
|
"Ogravesmall", "Ocircumflexsmall", "Odieresissmall", "Otildesmall",
|
||||||
'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '',
|
"Uacutesmall", "Ugravesmall", "Ucircumflexsmall", "Udieresissmall", "",
|
||||||
'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior',
|
"eightsuperior", "fourinferior", "threeinferior", "sixinferior",
|
||||||
'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior',
|
"eightinferior", "seveninferior", "Scaronsmall", "", "centinferior",
|
||||||
'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior',
|
"twoinferior", "", "Dieresissmall", "", "Caronsmall", "osuperior",
|
||||||
'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '',
|
"fiveinferior", "", "commainferior", "periodinferior", "Yacutesmall", "",
|
||||||
'dollarinferior', '', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior',
|
"dollarinferior", "", "", "Thornsmall", "", "nineinferior", "zeroinferior",
|
||||||
'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall',
|
"Zcaronsmall", "AEsmall", "Oslashsmall", "questiondownsmall",
|
||||||
'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '',
|
"oneinferior", "Lslashsmall", "", "", "", "", "", "", "Cedillasmall", "",
|
||||||
'', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '',
|
"", "", "", "", "OEsmall", "figuredash", "hyphensuperior", "", "", "", "",
|
||||||
'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior',
|
"exclamdownsmall", "", "Ydieresissmall", "", "onesuperior", "twosuperior",
|
||||||
'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
|
"threesuperior", "foursuperior", "fivesuperior", "sixsuperior",
|
||||||
'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior',
|
"sevensuperior", "ninesuperior", "zerosuperior", "", "esuperior",
|
||||||
'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior',
|
"rsuperior", "tsuperior", "", "", "isuperior", "ssuperior", "dsuperior",
|
||||||
'', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall',
|
"", "", "", "", "", "lsuperior", "Ogoneksmall", "Brevesmall",
|
||||||
'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior',
|
"Macronsmall", "bsuperior", "nsuperior", "msuperior", "commasuperior",
|
||||||
'periodsuperior', 'Dotaccentsmall', 'Ringsmall', '', '', '', ''];
|
"periodsuperior", "Dotaccentsmall", "Ringsmall", "", "", "", ""];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const MacRomanEncoding = [
|
const MacRomanEncoding = [
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
|
"space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
|
||||||
'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
|
"ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus",
|
||||||
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
|
"comma", "hyphen", "period", "slash", "zero", "one", "two", "three",
|
||||||
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
|
"four", "five", "six", "seven", "eight", "nine", "colon", "semicolon",
|
||||||
'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
|
"less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F",
|
||||||
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
|
"G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
|
||||||
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
|
"V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
|
||||||
'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
"asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g",
|
||||||
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
"h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
|
||||||
'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '',
|
"w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "",
|
||||||
'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis',
|
"Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis",
|
||||||
'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde',
|
"Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde",
|
||||||
'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
|
"aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis",
|
||||||
'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute',
|
"iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute",
|
||||||
'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave',
|
"ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave",
|
||||||
'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling',
|
"ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling",
|
||||||
'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright',
|
"section", "bullet", "paragraph", "germandbls", "registered", "copyright",
|
||||||
'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity',
|
"trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity",
|
||||||
'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff',
|
"plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff",
|
||||||
'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine',
|
"summation", "product", "pi", "integral", "ordfeminine", "ordmasculine",
|
||||||
'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot',
|
"Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
|
||||||
'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft',
|
"radical", "florin", "approxequal", "Delta", "guillemotleft",
|
||||||
'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE',
|
"guillemotright", "ellipsis", "space", "Agrave", "Atilde", "Otilde", "OE",
|
||||||
'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft',
|
"oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft",
|
||||||
'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
|
"quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction",
|
||||||
'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl',
|
"currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
|
||||||
'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand',
|
"periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
|
||||||
'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
|
"Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
|
||||||
'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple',
|
"Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple",
|
||||||
'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex',
|
"Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex",
|
||||||
'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
|
"tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut",
|
||||||
'ogonek', 'caron'];
|
"ogonek", "caron"];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const StandardEncoding = [
|
const StandardEncoding = [
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
|
"space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
|
||||||
'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
|
"ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus",
|
||||||
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
|
"comma", "hyphen", "period", "slash", "zero", "one", "two", "three",
|
||||||
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
|
"four", "five", "six", "seven", "eight", "nine", "colon", "semicolon",
|
||||||
'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
|
"less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F",
|
||||||
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
|
"G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
|
||||||
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
|
"V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
|
||||||
'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f',
|
"asciicircum", "underscore", "quoteleft", "a", "b", "c", "d", "e", "f",
|
||||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
|
"g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
|
||||||
'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
|
"v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "exclamdown",
|
||||||
'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
|
"cent", "sterling", "fraction", "yen", "florin", "section", "currency",
|
||||||
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
|
"quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
|
||||||
'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
|
"guilsinglright", "fi", "fl", "", "endash", "dagger", "daggerdbl",
|
||||||
'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
|
"periodcentered", "", "paragraph", "bullet", "quotesinglbase",
|
||||||
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
|
"quotedblbase", "quotedblright", "guillemotright", "ellipsis",
|
||||||
'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
|
"perthousand", "", "questiondown", "", "grave", "acute", "circumflex",
|
||||||
'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla',
|
"tilde", "macron", "breve", "dotaccent", "dieresis", "", "ring", "cedilla",
|
||||||
'', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '',
|
"", "hungarumlaut", "ogonek", "caron", "emdash", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '',
|
"", "", "", "", "", "", "", "", "", "", "AE", "", "ordfeminine", "", "",
|
||||||
'', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae',
|
"", "", "Lslash", "Oslash", "OE", "ordmasculine", "", "", "", "", "", "ae",
|
||||||
'', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls', '',
|
"", "", "", "dotlessi", "", "", "lslash", "oslash", "oe", "germandbls", "",
|
||||||
'', '', ''];
|
"", "", ""];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const WinAnsiEncoding = [
|
const WinAnsiEncoding = [
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
|
"space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
|
||||||
'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
|
"ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus",
|
||||||
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
|
"comma", "hyphen", "period", "slash", "zero", "one", "two", "three",
|
||||||
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
|
"four", "five", "six", "seven", "eight", "nine", "colon", "semicolon",
|
||||||
'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F',
|
"less", "equal", "greater", "question", "at", "A", "B", "C", "D", "E", "F",
|
||||||
'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
|
"G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
|
||||||
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
|
"V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
|
||||||
'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
|
"asciicircum", "underscore", "grave", "a", "b", "c", "d", "e", "f", "g",
|
||||||
'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
"h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
|
||||||
'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
|
"w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde",
|
||||||
'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase',
|
"bullet", "Euro", "bullet", "quotesinglbase", "florin", "quotedblbase",
|
||||||
'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron',
|
"ellipsis", "dagger", "daggerdbl", "circumflex", "perthousand", "Scaron",
|
||||||
'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft',
|
"guilsinglleft", "OE", "bullet", "Zcaron", "bullet", "bullet", "quoteleft",
|
||||||
'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash',
|
"quoteright", "quotedblleft", "quotedblright", "bullet", "endash",
|
||||||
'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet',
|
"emdash", "tilde", "trademark", "scaron", "guilsinglright", "oe", "bullet",
|
||||||
'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling',
|
"zcaron", "Ydieresis", "space", "exclamdown", "cent", "sterling",
|
||||||
'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright',
|
"currency", "yen", "brokenbar", "section", "dieresis", "copyright",
|
||||||
'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered',
|
"ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered",
|
||||||
'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute',
|
"macron", "degree", "plusminus", "twosuperior", "threesuperior", "acute",
|
||||||
'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior',
|
"mu", "paragraph", "periodcentered", "cedilla", "onesuperior",
|
||||||
'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters',
|
"ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters",
|
||||||
'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis',
|
"questiondown", "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis",
|
||||||
'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
|
"Aring", "AE", "Ccedilla", "Egrave", "Eacute", "Ecircumflex", "Edieresis",
|
||||||
'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve',
|
"Igrave", "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde", "Ograve",
|
||||||
'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash',
|
"Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply", "Oslash",
|
||||||
'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn',
|
"Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn",
|
||||||
'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis',
|
"germandbls", "agrave", "aacute", "acircumflex", "atilde", "adieresis",
|
||||||
'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis',
|
"aring", "ae", "ccedilla", "egrave", "eacute", "ecircumflex", "edieresis",
|
||||||
'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
|
"igrave", "iacute", "icircumflex", "idieresis", "eth", "ntilde", "ograve",
|
||||||
'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
|
"oacute", "ocircumflex", "otilde", "odieresis", "divide", "oslash",
|
||||||
'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
|
"ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn",
|
||||||
'ydieresis'];
|
"ydieresis"];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const SymbolSetEncoding = [
|
const SymbolSetEncoding = [
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
|
"space", "exclam", "universal", "numbersign", "existential", "percent",
|
||||||
'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus',
|
"ampersand", "suchthat", "parenleft", "parenright", "asteriskmath", "plus",
|
||||||
'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
|
"comma", "minus", "period", "slash", "zero", "one", "two", "three", "four",
|
||||||
'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
|
"five", "six", "seven", "eight", "nine", "colon", "semicolon", "less",
|
||||||
'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi',
|
"equal", "greater", "question", "congruent", "Alpha", "Beta", "Chi",
|
||||||
'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa',
|
"Delta", "Epsilon", "Phi", "Gamma", "Eta", "Iota", "theta1", "Kappa",
|
||||||
'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau',
|
"Lambda", "Mu", "Nu", "Omicron", "Pi", "Theta", "Rho", "Sigma", "Tau",
|
||||||
'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft',
|
"Upsilon", "sigma1", "Omega", "Xi", "Psi", "Zeta", "bracketleft",
|
||||||
'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex',
|
"therefore", "bracketright", "perpendicular", "underscore", "radicalex",
|
||||||
'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota',
|
"alpha", "beta", "chi", "delta", "epsilon", "phi", "gamma", "eta", "iota",
|
||||||
'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho',
|
"phi1", "kappa", "lambda", "mu", "nu", "omicron", "pi", "theta", "rho",
|
||||||
'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta',
|
"sigma", "tau", "upsilon", "omega1", "omega", "xi", "psi", "zeta",
|
||||||
'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '',
|
"braceleft", "bar", "braceright", "similar", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal',
|
"", "", "", "", "", "", "", "Euro", "Upsilon1", "minute", "lessequal",
|
||||||
'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade',
|
"fraction", "infinity", "florin", "club", "diamond", "heart", "spade",
|
||||||
'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree',
|
"arrowboth", "arrowleft", "arrowup", "arrowright", "arrowdown", "degree",
|
||||||
'plusminus', 'second', 'greaterequal', 'multiply', 'proportional',
|
"plusminus", "second", "greaterequal", "multiply", "proportional",
|
||||||
'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence',
|
"partialdiff", "bullet", "divide", "notequal", "equivalence",
|
||||||
'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn',
|
"approxequal", "ellipsis", "arrowvertex", "arrowhorizex", "carriagereturn",
|
||||||
'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply',
|
"aleph", "Ifraktur", "Rfraktur", "weierstrass", "circlemultiply",
|
||||||
'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset',
|
"circleplus", "emptyset", "intersection", "union", "propersuperset",
|
||||||
'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element',
|
"reflexsuperset", "notsubset", "propersubset", "reflexsubset", "element",
|
||||||
'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif',
|
"notelement", "angle", "gradient", "registerserif", "copyrightserif",
|
||||||
'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot',
|
"trademarkserif", "product", "radical", "dotmath", "logicalnot",
|
||||||
'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup',
|
"logicaland", "logicalor", "arrowdblboth", "arrowdblleft", "arrowdblup",
|
||||||
'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans',
|
"arrowdblright", "arrowdbldown", "lozenge", "angleleft", "registersans",
|
||||||
'copyrightsans', 'trademarksans', 'summation', 'parenlefttp',
|
"copyrightsans", "trademarksans", "summation", "parenlefttp",
|
||||||
'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex',
|
"parenleftex", "parenleftbt", "bracketlefttp", "bracketleftex",
|
||||||
'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex',
|
"bracketleftbt", "bracelefttp", "braceleftmid", "braceleftbt", "braceex",
|
||||||
'', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt',
|
"", "angleright", "integral", "integraltp", "integralex", "integralbt",
|
||||||
'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
|
"parenrighttp", "parenrightex", "parenrightbt", "bracketrighttp",
|
||||||
'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
|
"bracketrightex", "bracketrightbt", "bracerighttp", "bracerightmid",
|
||||||
'bracerightbt', ''];
|
"bracerightbt", ""];
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const ZapfDingbatsEncoding = [
|
const ZapfDingbatsEncoding = [
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||||
'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117',
|
"space", "a1", "a2", "a202", "a3", "a4", "a5", "a119", "a118", "a117",
|
||||||
'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19',
|
"a11", "a12", "a13", "a14", "a15", "a16", "a105", "a17", "a18", "a19",
|
||||||
'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7',
|
"a20", "a21", "a22", "a23", "a24", "a25", "a26", "a27", "a28", "a6", "a7",
|
||||||
'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36',
|
"a8", "a9", "a10", "a29", "a30", "a31", "a32", "a33", "a34", "a35", "a36",
|
||||||
'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46',
|
"a37", "a38", "a39", "a40", "a41", "a42", "a43", "a44", "a45", "a46",
|
||||||
'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56',
|
"a47", "a48", "a49", "a50", "a51", "a52", "a53", "a54", "a55", "a56",
|
||||||
'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66',
|
"a57", "a58", "a59", "a60", "a61", "a62", "a63", "a64", "a65", "a66",
|
||||||
'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75',
|
"a67", "a68", "a69", "a70", "a71", "a72", "a73", "a74", "a203", "a75",
|
||||||
'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97',
|
"a204", "a76", "a77", "a78", "a79", "a81", "a82", "a83", "a84", "a97",
|
||||||
'a98', 'a99', 'a100', '', 'a89', 'a90', 'a93', 'a94', 'a91', 'a92', 'a205',
|
"a98", "a99", "a100", "", "a89", "a90", "a93", "a94", "a91", "a92", "a205",
|
||||||
'a85', 'a206', 'a86', 'a87', 'a88', 'a95', 'a96', '', '', '', '', '', '',
|
"a85", "a206", "a86", "a87", "a88", "a95", "a96", "", "", "", "", "", "",
|
||||||
'', '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103',
|
"", "", "", "", "", "", "", "", "", "", "", "", "", "a101", "a102", "a103",
|
||||||
'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120',
|
"a104", "a106", "a107", "a108", "a112", "a111", "a110", "a109", "a120",
|
||||||
'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129',
|
"a121", "a122", "a123", "a124", "a125", "a126", "a127", "a128", "a129",
|
||||||
'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138',
|
"a130", "a131", "a132", "a133", "a134", "a135", "a136", "a137", "a138",
|
||||||
'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147',
|
"a139", "a140", "a141", "a142", "a143", "a144", "a145", "a146", "a147",
|
||||||
'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156',
|
"a148", "a149", "a150", "a151", "a152", "a153", "a154", "a155", "a156",
|
||||||
'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165',
|
"a157", "a158", "a159", "a160", "a161", "a163", "a164", "a196", "a165",
|
||||||
'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173',
|
"a192", "a166", "a167", "a168", "a169", "a170", "a171", "a172", "a173",
|
||||||
'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180',
|
"a162", "a174", "a175", "a176", "a177", "a178", "a179", "a193", "a180",
|
||||||
'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197', 'a185',
|
"a199", "a181", "a200", "a182", "", "a201", "a183", "a184", "a197", "a185",
|
||||||
'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190', 'a191', ''];
|
"a194", "a198", "a186", "a195", "a187", "a188", "a189", "a190", "a191", ""];
|
||||||
|
|
||||||
function getEncoding(encodingName) {
|
function getEncoding(encodingName) {
|
||||||
switch (encodingName) {
|
switch (encodingName) {
|
||||||
case 'WinAnsiEncoding':
|
case "WinAnsiEncoding":
|
||||||
return WinAnsiEncoding;
|
return WinAnsiEncoding;
|
||||||
case 'StandardEncoding':
|
case "StandardEncoding":
|
||||||
return StandardEncoding;
|
return StandardEncoding;
|
||||||
case 'MacRomanEncoding':
|
case "MacRomanEncoding":
|
||||||
return MacRomanEncoding;
|
return MacRomanEncoding;
|
||||||
case 'SymbolSetEncoding':
|
case "SymbolSetEncoding":
|
||||||
return SymbolSetEncoding;
|
return SymbolSetEncoding;
|
||||||
case 'ZapfDingbatsEncoding':
|
case "ZapfDingbatsEncoding":
|
||||||
return ZapfDingbatsEncoding;
|
return ZapfDingbatsEncoding;
|
||||||
case 'ExpertEncoding':
|
case "ExpertEncoding":
|
||||||
return ExpertEncoding;
|
return ExpertEncoding;
|
||||||
case 'MacExpertEncoding':
|
case "MacExpertEncoding":
|
||||||
return MacExpertEncoding;
|
return MacExpertEncoding;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -14,17 +14,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
bytesToString, FONT_IDENTITY_MATRIX, FormatError, unreachable, warn
|
bytesToString,
|
||||||
} from '../shared/util';
|
FONT_IDENTITY_MATRIX,
|
||||||
import { CFFParser } from './cff_parser';
|
FormatError,
|
||||||
import { getGlyphsUnicode } from './glyphlist';
|
unreachable,
|
||||||
import { StandardEncoding } from './encodings';
|
warn,
|
||||||
import { Stream } from './stream';
|
} from "../shared/util";
|
||||||
|
import { CFFParser } from "./cff_parser";
|
||||||
|
import { getGlyphsUnicode } from "./glyphlist";
|
||||||
|
import { StandardEncoding } from "./encodings";
|
||||||
|
import { Stream } from "./stream";
|
||||||
|
|
||||||
var FontRendererFactory = (function FontRendererFactoryClosure() {
|
var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||||
function getLong(data, offset) {
|
function getLong(data, offset) {
|
||||||
return (data[offset] << 24) | (data[offset + 1] << 16) |
|
return (
|
||||||
(data[offset + 2] << 8) | data[offset + 3];
|
(data[offset] << 24) |
|
||||||
|
(data[offset + 1] << 16) |
|
||||||
|
(data[offset + 2] << 8) |
|
||||||
|
data[offset + 3]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getUshort(data, offset) {
|
function getUshort(data, offset) {
|
||||||
@ -32,8 +40,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseCmap(data, start, end) {
|
function parseCmap(data, start, end) {
|
||||||
var offset = (getUshort(data, start + 2) === 1 ?
|
var offset =
|
||||||
getLong(data, start + 8) : getLong(data, start + 16));
|
getUshort(data, start + 2) === 1
|
||||||
|
? getLong(data, start + 8)
|
||||||
|
: getLong(data, start + 16);
|
||||||
var format = getUshort(data, start + offset);
|
var format = getUshort(data, start + offset);
|
||||||
var ranges, p, i;
|
var ranges, p, i;
|
||||||
if (format === 4) {
|
if (format === 4) {
|
||||||
@ -42,7 +52,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
p = start + offset + 14;
|
p = start + offset + 14;
|
||||||
ranges = [];
|
ranges = [];
|
||||||
for (i = 0; i < segCount; i++, p += 2) {
|
for (i = 0; i < segCount; i++, p += 2) {
|
||||||
ranges[i] = { end: getUshort(data, p), };
|
ranges[i] = { end: getUshort(data, p) };
|
||||||
}
|
}
|
||||||
p += 2;
|
p += 2;
|
||||||
for (i = 0; i < segCount; i++, p += 2) {
|
for (i = 0; i < segCount; i++, p += 2) {
|
||||||
@ -83,13 +93,18 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
|
|
||||||
function parseCff(data, start, end, seacAnalysisEnabled) {
|
function parseCff(data, start, end, seacAnalysisEnabled) {
|
||||||
var properties = {};
|
var properties = {};
|
||||||
var parser = new CFFParser(new Stream(data, start, end - start),
|
var parser = new CFFParser(
|
||||||
properties, seacAnalysisEnabled);
|
new Stream(data, start, end - start),
|
||||||
|
properties,
|
||||||
|
seacAnalysisEnabled
|
||||||
|
);
|
||||||
var cff = parser.parse();
|
var cff = parser.parse();
|
||||||
return {
|
return {
|
||||||
glyphs: cff.charStrings.objects,
|
glyphs: cff.charStrings.objects,
|
||||||
subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex &&
|
subrs:
|
||||||
cff.topDict.privateDict.subrsIndex.objects),
|
cff.topDict.privateDict &&
|
||||||
|
cff.topDict.privateDict.subrsIndex &&
|
||||||
|
cff.topDict.privateDict.subrsIndex.objects,
|
||||||
gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects,
|
gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects,
|
||||||
isCFFCIDFont: cff.isCIDFont,
|
isCFFCIDFont: cff.isCIDFont,
|
||||||
fdSelect: cff.fdSelect,
|
fdSelect: cff.fdSelect,
|
||||||
@ -102,8 +117,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
if (isGlyphLocationsLong) {
|
if (isGlyphLocationsLong) {
|
||||||
itemSize = 4;
|
itemSize = 4;
|
||||||
itemDecode = function fontItemDecodeLong(data, offset) {
|
itemDecode = function fontItemDecodeLong(data, offset) {
|
||||||
return (data[offset] << 24) | (data[offset + 1] << 16) |
|
return (
|
||||||
(data[offset + 2] << 8) | data[offset + 3];
|
(data[offset] << 24) |
|
||||||
|
(data[offset + 1] << 16) |
|
||||||
|
(data[offset + 2] << 8) |
|
||||||
|
data[offset + 3]
|
||||||
|
);
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
itemSize = 2;
|
itemSize = 2;
|
||||||
@ -122,8 +141,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function lookupCmap(ranges, unicode) {
|
function lookupCmap(ranges, unicode) {
|
||||||
var code = unicode.codePointAt(0), gid = 0;
|
var code = unicode.codePointAt(0),
|
||||||
var l = 0, r = ranges.length - 1;
|
gid = 0;
|
||||||
|
var l = 0,
|
||||||
|
r = ranges.length - 1;
|
||||||
while (l < r) {
|
while (l < r) {
|
||||||
var c = (l + r + 1) >> 1;
|
var c = (l + r + 1) >> 1;
|
||||||
if (code < ranges[c].start) {
|
if (code < ranges[c].start) {
|
||||||
@ -133,8 +154,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ranges[l].start <= code && code <= ranges[l].end) {
|
if (ranges[l].start <= code && code <= ranges[l].end) {
|
||||||
gid = (ranges[l].idDelta + (ranges[l].ids ?
|
gid =
|
||||||
ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF;
|
(ranges[l].idDelta +
|
||||||
|
(ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code)) &
|
||||||
|
0xffff;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
charCode: code,
|
charCode: code,
|
||||||
@ -144,19 +167,20 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
|
|
||||||
function compileGlyf(code, cmds, font) {
|
function compileGlyf(code, cmds, font) {
|
||||||
function moveTo(x, y) {
|
function moveTo(x, y) {
|
||||||
cmds.push({ cmd: 'moveTo', args: [x, y], });
|
cmds.push({ cmd: "moveTo", args: [x, y] });
|
||||||
}
|
}
|
||||||
function lineTo(x, y) {
|
function lineTo(x, y) {
|
||||||
cmds.push({ cmd: 'lineTo', args: [x, y], });
|
cmds.push({ cmd: "lineTo", args: [x, y] });
|
||||||
}
|
}
|
||||||
function quadraticCurveTo(xa, ya, x, y) {
|
function quadraticCurveTo(xa, ya, x, y) {
|
||||||
cmds.push({ cmd: 'quadraticCurveTo', args: [xa, ya, x, y], });
|
cmds.push({ cmd: "quadraticCurveTo", args: [xa, ya, x, y] });
|
||||||
}
|
}
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
|
var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
|
||||||
var flags;
|
var flags;
|
||||||
var x = 0, y = 0;
|
var x = 0,
|
||||||
|
y = 0;
|
||||||
i += 10;
|
i += 10;
|
||||||
if (numberOfContours < 0) {
|
if (numberOfContours < 0) {
|
||||||
// composite glyph
|
// composite glyph
|
||||||
@ -165,29 +189,34 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
var glyphIndex = (code[i + 2] << 8) | code[i + 3];
|
var glyphIndex = (code[i + 2] << 8) | code[i + 3];
|
||||||
i += 4;
|
i += 4;
|
||||||
var arg1, arg2;
|
var arg1, arg2;
|
||||||
if ((flags & 0x01)) {
|
if (flags & 0x01) {
|
||||||
arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
|
arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
|
||||||
arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16;
|
arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16;
|
||||||
i += 4;
|
i += 4;
|
||||||
} else {
|
} else {
|
||||||
arg1 = code[i++]; arg2 = code[i++];
|
arg1 = code[i++];
|
||||||
|
arg2 = code[i++];
|
||||||
}
|
}
|
||||||
if ((flags & 0x02)) {
|
if (flags & 0x02) {
|
||||||
x = arg1;
|
x = arg1;
|
||||||
y = arg2;
|
y = arg2;
|
||||||
} else {
|
} else {
|
||||||
x = 0; y = 0; // TODO "they are points" ?
|
x = 0;
|
||||||
|
y = 0; // TODO "they are points" ?
|
||||||
}
|
}
|
||||||
var scaleX = 1, scaleY = 1, scale01 = 0, scale10 = 0;
|
var scaleX = 1,
|
||||||
if ((flags & 0x08)) {
|
scaleY = 1,
|
||||||
scaleX =
|
scale01 = 0,
|
||||||
scaleY = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
scale10 = 0;
|
||||||
|
if (flags & 0x08) {
|
||||||
|
scaleX = scaleY =
|
||||||
|
((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
||||||
i += 2;
|
i += 2;
|
||||||
} else if ((flags & 0x40)) {
|
} else if (flags & 0x40) {
|
||||||
scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
||||||
scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
|
scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
|
||||||
i += 4;
|
i += 4;
|
||||||
} else if ((flags & 0x80)) {
|
} else if (flags & 0x80) {
|
||||||
scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
||||||
scale01 = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
|
scale01 = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
|
||||||
scale10 = ((code[i + 4] << 24) | (code[i + 5] << 16)) / 1073741824;
|
scale10 = ((code[i + 4] << 24) | (code[i + 5] << 16)) / 1073741824;
|
||||||
@ -196,13 +225,15 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
var subglyph = font.glyphs[glyphIndex];
|
var subglyph = font.glyphs[glyphIndex];
|
||||||
if (subglyph) {
|
if (subglyph) {
|
||||||
cmds.push({ cmd: 'save', });
|
cmds.push({ cmd: "save" });
|
||||||
cmds.push({ cmd: 'transform',
|
cmds.push({
|
||||||
args: [scaleX, scale01, scale10, scaleY, x, y], });
|
cmd: "transform",
|
||||||
|
args: [scaleX, scale01, scale10, scaleY, x, y],
|
||||||
|
});
|
||||||
compileGlyf(subglyph, cmds, font);
|
compileGlyf(subglyph, cmds, font);
|
||||||
cmds.push({ cmd: 'restore', });
|
cmds.push({ cmd: "restore" });
|
||||||
}
|
}
|
||||||
} while ((flags & 0x20));
|
} while (flags & 0x20);
|
||||||
} else {
|
} else {
|
||||||
// simple glyph
|
// simple glyph
|
||||||
var endPtsOfContours = [];
|
var endPtsOfContours = [];
|
||||||
@ -218,11 +249,11 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
while (points.length < numberOfPoints) {
|
while (points.length < numberOfPoints) {
|
||||||
flags = code[i++];
|
flags = code[i++];
|
||||||
var repeat = 1;
|
var repeat = 1;
|
||||||
if ((flags & 0x08)) {
|
if (flags & 0x08) {
|
||||||
repeat += code[i++];
|
repeat += code[i++];
|
||||||
}
|
}
|
||||||
while (repeat-- > 0) {
|
while (repeat-- > 0) {
|
||||||
points.push({ flags, });
|
points.push({ flags });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (j = 0; j < numberOfPoints; j++) {
|
for (j = 0; j < numberOfPoints; j++) {
|
||||||
@ -262,9 +293,9 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
// contours might have implicit points, which is located in the middle
|
// contours might have implicit points, which is located in the middle
|
||||||
// between two neighboring off-curve points
|
// between two neighboring off-curve points
|
||||||
var contour = points.slice(startPoint, endPoint + 1);
|
var contour = points.slice(startPoint, endPoint + 1);
|
||||||
if ((contour[0].flags & 1)) {
|
if (contour[0].flags & 1) {
|
||||||
contour.push(contour[0]); // using start point at the contour end
|
contour.push(contour[0]); // using start point at the contour end
|
||||||
} else if ((contour[contour.length - 1].flags & 1)) {
|
} else if (contour[contour.length - 1].flags & 1) {
|
||||||
// first is off-curve point, trying to use one from the end
|
// first is off-curve point, trying to use one from the end
|
||||||
contour.unshift(contour[contour.length - 1]);
|
contour.unshift(contour[contour.length - 1]);
|
||||||
} else {
|
} else {
|
||||||
@ -279,16 +310,23 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
moveTo(contour[0].x, contour[0].y);
|
moveTo(contour[0].x, contour[0].y);
|
||||||
for (j = 1, jj = contour.length; j < jj; j++) {
|
for (j = 1, jj = contour.length; j < jj; j++) {
|
||||||
if ((contour[j].flags & 1)) {
|
if (contour[j].flags & 1) {
|
||||||
lineTo(contour[j].x, contour[j].y);
|
lineTo(contour[j].x, contour[j].y);
|
||||||
} else if ((contour[j + 1].flags & 1)) {
|
} else if (contour[j + 1].flags & 1) {
|
||||||
quadraticCurveTo(contour[j].x, contour[j].y,
|
quadraticCurveTo(
|
||||||
contour[j + 1].x, contour[j + 1].y);
|
contour[j].x,
|
||||||
|
contour[j].y,
|
||||||
|
contour[j + 1].x,
|
||||||
|
contour[j + 1].y
|
||||||
|
);
|
||||||
j++;
|
j++;
|
||||||
} else {
|
} else {
|
||||||
quadraticCurveTo(contour[j].x, contour[j].y,
|
quadraticCurveTo(
|
||||||
|
contour[j].x,
|
||||||
|
contour[j].y,
|
||||||
(contour[j].x + contour[j + 1].x) / 2,
|
(contour[j].x + contour[j + 1].x) / 2,
|
||||||
(contour[j].y + contour[j + 1].y) / 2);
|
(contour[j].y + contour[j + 1].y) / 2
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
startPoint = endPoint + 1;
|
startPoint = endPoint + 1;
|
||||||
@ -298,17 +336,18 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
|
|
||||||
function compileCharString(code, cmds, font, glyphId) {
|
function compileCharString(code, cmds, font, glyphId) {
|
||||||
var stack = [];
|
var stack = [];
|
||||||
var x = 0, y = 0;
|
var x = 0,
|
||||||
|
y = 0;
|
||||||
var stems = 0;
|
var stems = 0;
|
||||||
|
|
||||||
function moveTo(x, y) {
|
function moveTo(x, y) {
|
||||||
cmds.push({ cmd: 'moveTo', args: [x, y], });
|
cmds.push({ cmd: "moveTo", args: [x, y] });
|
||||||
}
|
}
|
||||||
function lineTo(x, y) {
|
function lineTo(x, y) {
|
||||||
cmds.push({ cmd: 'lineTo', args: [x, y], });
|
cmds.push({ cmd: "lineTo", args: [x, y] });
|
||||||
}
|
}
|
||||||
function bezierCurveTo(x1, y1, x2, y2, x, y) {
|
function bezierCurveTo(x1, y1, x2, y2, x, y) {
|
||||||
cmds.push({ cmd: 'bezierCurveTo', args: [x1, y1, x2, y2, x, y], });
|
cmds.push({ cmd: "bezierCurveTo", args: [x1, y1, x2, y2, x, y] });
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse(code) {
|
function parse(code) {
|
||||||
@ -362,9 +401,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
break;
|
break;
|
||||||
case 8: // rrcurveto
|
case 8: // rrcurveto
|
||||||
while (stack.length > 0) {
|
while (stack.length > 0) {
|
||||||
xa = x + stack.shift(); ya = y + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
x = xb + stack.shift(); y = yb + stack.shift();
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb + stack.shift();
|
||||||
|
y = yb + stack.shift();
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -374,19 +416,19 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
if (font.isCFFCIDFont) {
|
if (font.isCFFCIDFont) {
|
||||||
let fdIndex = font.fdSelect.getFDIndex(glyphId);
|
let fdIndex = font.fdSelect.getFDIndex(glyphId);
|
||||||
if (fdIndex >= 0 && fdIndex < font.fdArray.length) {
|
if (fdIndex >= 0 && fdIndex < font.fdArray.length) {
|
||||||
let fontDict = font.fdArray[fdIndex], subrs;
|
let fontDict = font.fdArray[fdIndex],
|
||||||
|
subrs;
|
||||||
if (fontDict.privateDict && fontDict.privateDict.subrsIndex) {
|
if (fontDict.privateDict && fontDict.privateDict.subrsIndex) {
|
||||||
subrs = fontDict.privateDict.subrsIndex.objects;
|
subrs = fontDict.privateDict.subrsIndex.objects;
|
||||||
}
|
}
|
||||||
if (subrs) {
|
if (subrs) {
|
||||||
let numSubrs = subrs.length;
|
let numSubrs = subrs.length;
|
||||||
// Add subroutine bias.
|
// Add subroutine bias.
|
||||||
n += numSubrs < 1240 ? 107 :
|
n += numSubrs < 1240 ? 107 : numSubrs < 33900 ? 1131 : 32768;
|
||||||
(numSubrs < 33900 ? 1131 : 32768);
|
|
||||||
subrCode = subrs[n];
|
subrCode = subrs[n];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn('Invalid fd index for glyph index.');
|
warn("Invalid fd index for glyph index.");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
subrCode = font.subrs[n + font.subrsBias];
|
subrCode = font.subrs[n + font.subrsBias];
|
||||||
@ -402,7 +444,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
switch (v) {
|
switch (v) {
|
||||||
case 34: // flex
|
case 34: // flex
|
||||||
xa = x + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); y1 = y + stack.shift();
|
xb = xa + stack.shift();
|
||||||
|
y1 = y + stack.shift();
|
||||||
x = xb + stack.shift();
|
x = xb + stack.shift();
|
||||||
bezierCurveTo(xa, y, xb, y1, x, y1);
|
bezierCurveTo(xa, y, xb, y1, x, y1);
|
||||||
xa = x + stack.shift();
|
xa = x + stack.shift();
|
||||||
@ -411,35 +454,51 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
bezierCurveTo(xa, y1, xb, y, x, y);
|
bezierCurveTo(xa, y1, xb, y, x, y);
|
||||||
break;
|
break;
|
||||||
case 35: // flex
|
case 35: // flex
|
||||||
xa = x + stack.shift(); ya = y + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
x = xb + stack.shift(); y = yb + stack.shift();
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb + stack.shift();
|
||||||
|
y = yb + stack.shift();
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
xa = x + stack.shift(); ya = y + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
x = xb + stack.shift(); y = yb + stack.shift();
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb + stack.shift();
|
||||||
|
y = yb + stack.shift();
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
stack.pop(); // fd
|
stack.pop(); // fd
|
||||||
break;
|
break;
|
||||||
case 36: // hflex1
|
case 36: // hflex1
|
||||||
xa = x + stack.shift(); y1 = y + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); y2 = y1 + stack.shift();
|
y1 = y + stack.shift();
|
||||||
|
xb = xa + stack.shift();
|
||||||
|
y2 = y1 + stack.shift();
|
||||||
x = xb + stack.shift();
|
x = xb + stack.shift();
|
||||||
bezierCurveTo(xa, y1, xb, y2, x, y2);
|
bezierCurveTo(xa, y1, xb, y2, x, y2);
|
||||||
xa = x + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); y3 = y2 + stack.shift();
|
xb = xa + stack.shift();
|
||||||
|
y3 = y2 + stack.shift();
|
||||||
x = xb + stack.shift();
|
x = xb + stack.shift();
|
||||||
bezierCurveTo(xa, y2, xb, y3, x, y);
|
bezierCurveTo(xa, y2, xb, y3, x, y);
|
||||||
break;
|
break;
|
||||||
case 37: // flex1
|
case 37: // flex1
|
||||||
var x0 = x, y0 = y;
|
var x0 = x,
|
||||||
xa = x + stack.shift(); ya = y + stack.shift();
|
y0 = y;
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
xa = x + stack.shift();
|
||||||
x = xb + stack.shift(); y = yb + stack.shift();
|
ya = y + stack.shift();
|
||||||
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb + stack.shift();
|
||||||
|
y = yb + stack.shift();
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
xa = x + stack.shift(); ya = y + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
x = xb; y = yb;
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb;
|
||||||
|
y = yb;
|
||||||
if (Math.abs(x - x0) > Math.abs(y - y0)) {
|
if (Math.abs(x - x0) > Math.abs(y - y0)) {
|
||||||
x += stack.shift();
|
x += stack.shift();
|
||||||
} else {
|
} else {
|
||||||
@ -457,18 +516,30 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
var bchar = stack.pop();
|
var bchar = stack.pop();
|
||||||
y = stack.pop();
|
y = stack.pop();
|
||||||
x = stack.pop();
|
x = stack.pop();
|
||||||
cmds.push({ cmd: 'save', });
|
cmds.push({ cmd: "save" });
|
||||||
cmds.push({ cmd: 'translate', args: [x, y], });
|
cmds.push({ cmd: "translate", args: [x, y] });
|
||||||
var cmap = lookupCmap(font.cmap, String.fromCharCode(
|
var cmap = lookupCmap(
|
||||||
font.glyphNameMap[StandardEncoding[achar]]));
|
font.cmap,
|
||||||
compileCharString(font.glyphs[cmap.glyphId], cmds, font,
|
String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]])
|
||||||
cmap.glyphId);
|
);
|
||||||
cmds.push({ cmd: 'restore', });
|
compileCharString(
|
||||||
|
font.glyphs[cmap.glyphId],
|
||||||
|
cmds,
|
||||||
|
font,
|
||||||
|
cmap.glyphId
|
||||||
|
);
|
||||||
|
cmds.push({ cmd: "restore" });
|
||||||
|
|
||||||
cmap = lookupCmap(font.cmap, String.fromCharCode(
|
cmap = lookupCmap(
|
||||||
font.glyphNameMap[StandardEncoding[bchar]]));
|
font.cmap,
|
||||||
compileCharString(font.glyphs[cmap.glyphId], cmds, font,
|
String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]])
|
||||||
cmap.glyphId);
|
);
|
||||||
|
compileCharString(
|
||||||
|
font.glyphs[cmap.glyphId],
|
||||||
|
cmds,
|
||||||
|
font,
|
||||||
|
cmap.glyphId
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 18: // hstemhm
|
case 18: // hstemhm
|
||||||
@ -502,9 +573,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
break;
|
break;
|
||||||
case 24: // rcurveline
|
case 24: // rcurveline
|
||||||
while (stack.length > 2) {
|
while (stack.length > 2) {
|
||||||
xa = x + stack.shift(); ya = y + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
x = xb + stack.shift(); y = yb + stack.shift();
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb + stack.shift();
|
||||||
|
y = yb + stack.shift();
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
}
|
}
|
||||||
x += stack.shift();
|
x += stack.shift();
|
||||||
@ -517,9 +591,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
y += stack.shift();
|
y += stack.shift();
|
||||||
lineTo(x, y);
|
lineTo(x, y);
|
||||||
}
|
}
|
||||||
xa = x + stack.shift(); ya = y + stack.shift();
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
x = xb + stack.shift(); y = yb + stack.shift();
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb + stack.shift();
|
||||||
|
y = yb + stack.shift();
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
break;
|
break;
|
||||||
case 26: // vvcurveto
|
case 26: // vvcurveto
|
||||||
@ -527,9 +604,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
x += stack.shift();
|
x += stack.shift();
|
||||||
}
|
}
|
||||||
while (stack.length > 0) {
|
while (stack.length > 0) {
|
||||||
xa = x; ya = y + stack.shift();
|
xa = x;
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
x = xb; y = yb + stack.shift();
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb;
|
||||||
|
y = yb + stack.shift();
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -538,9 +618,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
y += stack.shift();
|
y += stack.shift();
|
||||||
}
|
}
|
||||||
while (stack.length > 0) {
|
while (stack.length > 0) {
|
||||||
xa = x + stack.shift(); ya = y;
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y;
|
||||||
x = xb + stack.shift(); y = yb;
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
|
x = xb + stack.shift();
|
||||||
|
y = yb;
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -557,8 +640,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
break;
|
break;
|
||||||
case 30: // vhcurveto
|
case 30: // vhcurveto
|
||||||
while (stack.length > 0) {
|
while (stack.length > 0) {
|
||||||
xa = x; ya = y + stack.shift();
|
xa = x;
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
x = xb + stack.shift();
|
x = xb + stack.shift();
|
||||||
y = yb + (stack.length === 1 ? stack.shift() : 0);
|
y = yb + (stack.length === 1 ? stack.shift() : 0);
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
@ -566,8 +651,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
xa = x + stack.shift(); ya = y;
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y;
|
||||||
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
y = yb + stack.shift();
|
y = yb + stack.shift();
|
||||||
x = xb + (stack.length === 1 ? stack.shift() : 0);
|
x = xb + (stack.length === 1 ? stack.shift() : 0);
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
@ -575,8 +662,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
break;
|
break;
|
||||||
case 31: // hvcurveto
|
case 31: // hvcurveto
|
||||||
while (stack.length > 0) {
|
while (stack.length > 0) {
|
||||||
xa = x + stack.shift(); ya = y;
|
xa = x + stack.shift();
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y;
|
||||||
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
y = yb + stack.shift();
|
y = yb + stack.shift();
|
||||||
x = xb + (stack.length === 1 ? stack.shift() : 0);
|
x = xb + (stack.length === 1 ? stack.shift() : 0);
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
@ -584,8 +673,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
xa = x; ya = y + stack.shift();
|
xa = x;
|
||||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
ya = y + stack.shift();
|
||||||
|
xb = xa + stack.shift();
|
||||||
|
yb = ya + stack.shift();
|
||||||
x = xb + stack.shift();
|
x = xb + stack.shift();
|
||||||
y = yb + (stack.length === 1 ? stack.shift() : 0);
|
y = yb + (stack.length === 1 ? stack.shift() : 0);
|
||||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||||
@ -602,8 +693,13 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
} else if (v < 255) {
|
} else if (v < 255) {
|
||||||
stack.push(-(v - 251) * 256 - code[i++] - 108);
|
stack.push(-(v - 251) * 256 - code[i++] - 108);
|
||||||
} else {
|
} else {
|
||||||
stack.push(((code[i] << 24) | (code[i + 1] << 16) |
|
stack.push(
|
||||||
(code[i + 2] << 8) | code[i + 3]) / 65536);
|
((code[i] << 24) |
|
||||||
|
(code[i + 1] << 16) |
|
||||||
|
(code[i + 2] << 8) |
|
||||||
|
code[i + 3]) /
|
||||||
|
65536
|
||||||
|
);
|
||||||
i += 4;
|
i += 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -621,7 +717,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
class CompiledFont {
|
class CompiledFont {
|
||||||
constructor(fontMatrix) {
|
constructor(fontMatrix) {
|
||||||
if (this.constructor === CompiledFont) {
|
if (this.constructor === CompiledFont) {
|
||||||
unreachable('Cannot initialize CompiledFont.');
|
unreachable("Cannot initialize CompiledFont.");
|
||||||
}
|
}
|
||||||
this.fontMatrix = fontMatrix;
|
this.fontMatrix = fontMatrix;
|
||||||
|
|
||||||
@ -654,32 +750,34 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
let fdIndex = this.fdSelect.getFDIndex(glyphId);
|
let fdIndex = this.fdSelect.getFDIndex(glyphId);
|
||||||
if (fdIndex >= 0 && fdIndex < this.fdArray.length) {
|
if (fdIndex >= 0 && fdIndex < this.fdArray.length) {
|
||||||
let fontDict = this.fdArray[fdIndex];
|
let fontDict = this.fdArray[fdIndex];
|
||||||
fontMatrix = fontDict.getByName('FontMatrix') || FONT_IDENTITY_MATRIX;
|
fontMatrix = fontDict.getByName("FontMatrix") || FONT_IDENTITY_MATRIX;
|
||||||
} else {
|
} else {
|
||||||
warn('Invalid fd index for glyph index.');
|
warn("Invalid fd index for glyph index.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmds = [];
|
const cmds = [];
|
||||||
cmds.push({ cmd: 'save', });
|
cmds.push({ cmd: "save" });
|
||||||
cmds.push({ cmd: 'transform', args: fontMatrix.slice(), });
|
cmds.push({ cmd: "transform", args: fontMatrix.slice() });
|
||||||
cmds.push({ cmd: 'scale', args: ['size', '-size'], });
|
cmds.push({ cmd: "scale", args: ["size", "-size"] });
|
||||||
|
|
||||||
this.compileGlyphImpl(code, cmds, glyphId);
|
this.compileGlyphImpl(code, cmds, glyphId);
|
||||||
|
|
||||||
cmds.push({ cmd: 'restore', });
|
cmds.push({ cmd: "restore" });
|
||||||
|
|
||||||
return cmds;
|
return cmds;
|
||||||
}
|
}
|
||||||
|
|
||||||
compileGlyphImpl() {
|
compileGlyphImpl() {
|
||||||
unreachable('Children classes should implement this.');
|
unreachable("Children classes should implement this.");
|
||||||
}
|
}
|
||||||
|
|
||||||
hasBuiltPath(unicode) {
|
hasBuiltPath(unicode) {
|
||||||
const cmap = lookupCmap(this.cmap, unicode);
|
const cmap = lookupCmap(this.cmap, unicode);
|
||||||
return (this.compiledGlyphs[cmap.glyphId] !== undefined &&
|
return (
|
||||||
this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined);
|
this.compiledGlyphs[cmap.glyphId] !== undefined &&
|
||||||
|
this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,10 +804,18 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
this.cmap = cmap;
|
this.cmap = cmap;
|
||||||
this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
|
this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
|
||||||
|
|
||||||
this.gsubrsBias = (this.gsubrs.length < 1240 ?
|
this.gsubrsBias =
|
||||||
107 : (this.gsubrs.length < 33900 ? 1131 : 32768));
|
this.gsubrs.length < 1240
|
||||||
this.subrsBias = (this.subrs.length < 1240 ?
|
? 107
|
||||||
107 : (this.subrs.length < 33900 ? 1131 : 32768));
|
: this.gsubrs.length < 33900
|
||||||
|
? 1131
|
||||||
|
: 32768;
|
||||||
|
this.subrsBias =
|
||||||
|
this.subrs.length < 1240
|
||||||
|
? 107
|
||||||
|
: this.subrs.length < 33900
|
||||||
|
? 1131
|
||||||
|
: 32768;
|
||||||
|
|
||||||
this.isCFFCIDFont = cffInfo.isCFFCIDFont;
|
this.isCFFCIDFont = cffInfo.isCFFCIDFont;
|
||||||
this.fdSelect = cffInfo.fdSelect;
|
this.fdSelect = cffInfo.fdSelect;
|
||||||
@ -731,36 +837,38 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
var offset = getLong(data, p + 8);
|
var offset = getLong(data, p + 8);
|
||||||
var length = getLong(data, p + 12);
|
var length = getLong(data, p + 12);
|
||||||
switch (tag) {
|
switch (tag) {
|
||||||
case 'cmap':
|
case "cmap":
|
||||||
cmap = parseCmap(data, offset, offset + length);
|
cmap = parseCmap(data, offset, offset + length);
|
||||||
break;
|
break;
|
||||||
case 'glyf':
|
case "glyf":
|
||||||
glyf = data.subarray(offset, offset + length);
|
glyf = data.subarray(offset, offset + length);
|
||||||
break;
|
break;
|
||||||
case 'loca':
|
case "loca":
|
||||||
loca = data.subarray(offset, offset + length);
|
loca = data.subarray(offset, offset + length);
|
||||||
break;
|
break;
|
||||||
case 'head':
|
case "head":
|
||||||
unitsPerEm = getUshort(data, offset + 18);
|
unitsPerEm = getUshort(data, offset + 18);
|
||||||
indexToLocFormat = getUshort(data, offset + 50);
|
indexToLocFormat = getUshort(data, offset + 50);
|
||||||
break;
|
break;
|
||||||
case 'CFF ':
|
case "CFF ":
|
||||||
cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
|
cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (glyf) {
|
if (glyf) {
|
||||||
var fontMatrix = (!unitsPerEm ? font.fontMatrix :
|
var fontMatrix = !unitsPerEm
|
||||||
[1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]);
|
? font.fontMatrix
|
||||||
|
: [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];
|
||||||
return new TrueTypeCompiled(
|
return new TrueTypeCompiled(
|
||||||
parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
|
parseGlyfTable(glyf, loca, indexToLocFormat),
|
||||||
|
cmap,
|
||||||
|
fontMatrix
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
|
return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { FontRendererFactory };
|
||||||
FontRendererFactory,
|
|
||||||
};
|
|
||||||
|
1777
src/core/fonts.js
1777
src/core/fonts.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -13,12 +13,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { assert, FormatError, ImageKind, info, warn } from '../shared/util';
|
import { assert, FormatError, ImageKind, info, warn } from "../shared/util";
|
||||||
import { isName, isStream, Name } from './primitives';
|
import { isName, isStream, Name } from "./primitives";
|
||||||
import { ColorSpace } from './colorspace';
|
import { ColorSpace } from "./colorspace";
|
||||||
import { DecodeStream } from './stream';
|
import { DecodeStream } from "./stream";
|
||||||
import { JpegStream } from './jpeg_stream';
|
import { JpegStream } from "./jpeg_stream";
|
||||||
import { JpxImage } from './jpx';
|
import { JpxImage } from "./jpx";
|
||||||
|
|
||||||
var PDFImage = (function PDFImageClosure() {
|
var PDFImage = (function PDFImageClosure() {
|
||||||
/**
|
/**
|
||||||
@ -27,9 +27,11 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
*/
|
*/
|
||||||
function handleImageData(image, nativeDecoder) {
|
function handleImageData(image, nativeDecoder) {
|
||||||
if (nativeDecoder && nativeDecoder.canDecode(image)) {
|
if (nativeDecoder && nativeDecoder.canDecode(image)) {
|
||||||
return nativeDecoder.decode(image).catch((reason) => {
|
return nativeDecoder.decode(image).catch(reason => {
|
||||||
warn('Native image decoding failed -- trying to recover: ' +
|
warn(
|
||||||
(reason && reason.message));
|
"Native image decoding failed -- trying to recover: " +
|
||||||
|
(reason && reason.message)
|
||||||
|
);
|
||||||
return image;
|
return image;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -43,7 +45,7 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
function decodeAndClamp(value, addend, coefficient, max) {
|
function decodeAndClamp(value, addend, coefficient, max) {
|
||||||
value = addend + value * coefficient;
|
value = addend + value * coefficient;
|
||||||
// Clamp the value to the range
|
// Clamp the value to the range
|
||||||
return (value < 0 ? 0 : (value > max ? max : value));
|
return value < 0 ? 0 : value > max ? max : value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,11 +60,19 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
*/
|
*/
|
||||||
function resizeImageMask(src, bpc, w1, h1, w2, h2) {
|
function resizeImageMask(src, bpc, w1, h1, w2, h2) {
|
||||||
var length = w2 * h2;
|
var length = w2 * h2;
|
||||||
var dest = (bpc <= 8 ? new Uint8Array(length) :
|
var dest =
|
||||||
(bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length)));
|
bpc <= 8
|
||||||
|
? new Uint8Array(length)
|
||||||
|
: bpc <= 16
|
||||||
|
? new Uint16Array(length)
|
||||||
|
: new Uint32Array(length);
|
||||||
var xRatio = w1 / w2;
|
var xRatio = w1 / w2;
|
||||||
var yRatio = h1 / h2;
|
var yRatio = h1 / h2;
|
||||||
var i, j, py, newIndex = 0, oldIndex;
|
var i,
|
||||||
|
j,
|
||||||
|
py,
|
||||||
|
newIndex = 0,
|
||||||
|
oldIndex;
|
||||||
var xScaled = new Uint16Array(w2);
|
var xScaled = new Uint16Array(w2);
|
||||||
var w1Scanline = w1;
|
var w1Scanline = w1;
|
||||||
|
|
||||||
@ -79,15 +89,23 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
function PDFImage({ xref, res, image, isInline = false, smask = null,
|
function PDFImage({
|
||||||
mask = null, isMask = false, pdfFunctionFactory, }) {
|
xref,
|
||||||
|
res,
|
||||||
|
image,
|
||||||
|
isInline = false,
|
||||||
|
smask = null,
|
||||||
|
mask = null,
|
||||||
|
isMask = false,
|
||||||
|
pdfFunctionFactory,
|
||||||
|
}) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
var dict = image.dict;
|
var dict = image.dict;
|
||||||
|
|
||||||
const filter = dict.get('Filter');
|
const filter = dict.get("Filter");
|
||||||
if (isName(filter)) {
|
if (isName(filter)) {
|
||||||
switch (filter.name) {
|
switch (filter.name) {
|
||||||
case 'JPXDecode':
|
case "JPXDecode":
|
||||||
var jpxImage = new JpxImage();
|
var jpxImage = new JpxImage();
|
||||||
jpxImage.parseImageProperties(image.stream);
|
jpxImage.parseImageProperties(image.stream);
|
||||||
image.stream.reset();
|
image.stream.reset();
|
||||||
@ -97,7 +115,7 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
image.bitsPerComponent = jpxImage.bitsPerComponent;
|
image.bitsPerComponent = jpxImage.bitsPerComponent;
|
||||||
image.numComps = jpxImage.componentsCount;
|
image.numComps = jpxImage.componentsCount;
|
||||||
break;
|
break;
|
||||||
case 'JBIG2Decode':
|
case "JBIG2Decode":
|
||||||
image.bitsPerComponent = 1;
|
image.bitsPerComponent = 1;
|
||||||
image.numComps = 1;
|
image.numComps = 1;
|
||||||
break;
|
break;
|
||||||
@ -105,86 +123,103 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
}
|
}
|
||||||
// TODO cache rendered images?
|
// TODO cache rendered images?
|
||||||
|
|
||||||
let width = dict.get('Width', 'W');
|
let width = dict.get("Width", "W");
|
||||||
let height = dict.get('Height', 'H');
|
let height = dict.get("Height", "H");
|
||||||
|
|
||||||
if ((Number.isInteger(image.width) && image.width > 0) &&
|
if (
|
||||||
(Number.isInteger(image.height) && image.height > 0) &&
|
Number.isInteger(image.width) &&
|
||||||
(image.width !== width || image.height !== height)) {
|
image.width > 0 &&
|
||||||
warn('PDFImage - using the Width/Height of the image data, ' +
|
Number.isInteger(image.height) &&
|
||||||
'rather than the image dictionary.');
|
image.height > 0 &&
|
||||||
|
(image.width !== width || image.height !== height)
|
||||||
|
) {
|
||||||
|
warn(
|
||||||
|
"PDFImage - using the Width/Height of the image data, " +
|
||||||
|
"rather than the image dictionary."
|
||||||
|
);
|
||||||
width = image.width;
|
width = image.width;
|
||||||
height = image.height;
|
height = image.height;
|
||||||
}
|
}
|
||||||
if (width < 1 || height < 1) {
|
if (width < 1 || height < 1) {
|
||||||
throw new FormatError(`Invalid image width: ${width} or ` +
|
throw new FormatError(
|
||||||
`height: ${height}`);
|
`Invalid image width: ${width} or ` + `height: ${height}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
|
||||||
this.interpolate = dict.get('Interpolate', 'I') || false;
|
this.interpolate = dict.get("Interpolate", "I") || false;
|
||||||
this.imageMask = dict.get('ImageMask', 'IM') || false;
|
this.imageMask = dict.get("ImageMask", "IM") || false;
|
||||||
this.matte = dict.get('Matte') || false;
|
this.matte = dict.get("Matte") || false;
|
||||||
|
|
||||||
var bitsPerComponent = image.bitsPerComponent;
|
var bitsPerComponent = image.bitsPerComponent;
|
||||||
if (!bitsPerComponent) {
|
if (!bitsPerComponent) {
|
||||||
bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
|
bitsPerComponent = dict.get("BitsPerComponent", "BPC");
|
||||||
if (!bitsPerComponent) {
|
if (!bitsPerComponent) {
|
||||||
if (this.imageMask) {
|
if (this.imageMask) {
|
||||||
bitsPerComponent = 1;
|
bitsPerComponent = 1;
|
||||||
} else {
|
} else {
|
||||||
throw new FormatError(
|
throw new FormatError(
|
||||||
`Bits per component missing in image: ${this.imageMask}`);
|
`Bits per component missing in image: ${this.imageMask}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.bpc = bitsPerComponent;
|
this.bpc = bitsPerComponent;
|
||||||
|
|
||||||
if (!this.imageMask) {
|
if (!this.imageMask) {
|
||||||
var colorSpace = dict.get('ColorSpace', 'CS');
|
var colorSpace = dict.get("ColorSpace", "CS");
|
||||||
if (!colorSpace) {
|
if (!colorSpace) {
|
||||||
info('JPX images (which do not require color spaces)');
|
info("JPX images (which do not require color spaces)");
|
||||||
switch (image.numComps) {
|
switch (image.numComps) {
|
||||||
case 1:
|
case 1:
|
||||||
colorSpace = Name.get('DeviceGray');
|
colorSpace = Name.get("DeviceGray");
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
colorSpace = Name.get('DeviceRGB');
|
colorSpace = Name.get("DeviceRGB");
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
colorSpace = Name.get('DeviceCMYK');
|
colorSpace = Name.get("DeviceCMYK");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error(`JPX images with ${image.numComps} ` +
|
throw new Error(
|
||||||
'color components not supported.');
|
`JPX images with ${image.numComps} ` +
|
||||||
|
"color components not supported."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let resources = isInline ? res : null;
|
let resources = isInline ? res : null;
|
||||||
this.colorSpace = ColorSpace.parse(colorSpace, xref, resources,
|
this.colorSpace = ColorSpace.parse(
|
||||||
pdfFunctionFactory);
|
colorSpace,
|
||||||
|
xref,
|
||||||
|
resources,
|
||||||
|
pdfFunctionFactory
|
||||||
|
);
|
||||||
this.numComps = this.colorSpace.numComps;
|
this.numComps = this.colorSpace.numComps;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.decode = dict.getArray('Decode', 'D');
|
this.decode = dict.getArray("Decode", "D");
|
||||||
this.needsDecode = false;
|
this.needsDecode = false;
|
||||||
if (this.decode &&
|
if (
|
||||||
|
this.decode &&
|
||||||
((this.colorSpace &&
|
((this.colorSpace &&
|
||||||
!this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent)) ||
|
!this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent)) ||
|
||||||
(isMask &&
|
(isMask &&
|
||||||
!ColorSpace.isDefaultDecode(this.decode, /* numComps = */ 1)))) {
|
!ColorSpace.isDefaultDecode(this.decode, /* numComps = */ 1)))
|
||||||
|
) {
|
||||||
this.needsDecode = true;
|
this.needsDecode = true;
|
||||||
// Do some preprocessing to avoid more math.
|
// Do some preprocessing to avoid more math.
|
||||||
var max = (1 << bitsPerComponent) - 1;
|
var max = (1 << bitsPerComponent) - 1;
|
||||||
this.decodeCoefficients = [];
|
this.decodeCoefficients = [];
|
||||||
this.decodeAddends = [];
|
this.decodeAddends = [];
|
||||||
const isIndexed = this.colorSpace && this.colorSpace.name === 'Indexed';
|
const isIndexed = this.colorSpace && this.colorSpace.name === "Indexed";
|
||||||
for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
|
for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
|
||||||
var dmin = this.decode[i];
|
var dmin = this.decode[i];
|
||||||
var dmax = this.decode[i + 1];
|
var dmax = this.decode[i + 1];
|
||||||
this.decodeCoefficients[j] = isIndexed ? ((dmax - dmin) / max) :
|
this.decodeCoefficients[j] = isIndexed
|
||||||
(dmax - dmin);
|
? (dmax - dmin) / max
|
||||||
this.decodeAddends[j] = isIndexed ? dmin : (max * dmin);
|
: dmax - dmin;
|
||||||
|
this.decodeAddends[j] = isIndexed ? dmin : max * dmin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,9 +233,10 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
});
|
});
|
||||||
} else if (mask) {
|
} else if (mask) {
|
||||||
if (isStream(mask)) {
|
if (isStream(mask)) {
|
||||||
var maskDict = mask.dict, imageMask = maskDict.get('ImageMask', 'IM');
|
var maskDict = mask.dict,
|
||||||
|
imageMask = maskDict.get("ImageMask", "IM");
|
||||||
if (!imageMask) {
|
if (!imageMask) {
|
||||||
warn('Ignoring /Mask in image without /ImageMask.');
|
warn("Ignoring /Mask in image without /ImageMask.");
|
||||||
} else {
|
} else {
|
||||||
this.mask = new PDFImage({
|
this.mask = new PDFImage({
|
||||||
xref,
|
xref,
|
||||||
@ -221,15 +257,21 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
* Handles processing of image data and returns the Promise that is resolved
|
* Handles processing of image data and returns the Promise that is resolved
|
||||||
* with a PDFImage when the image is ready to be used.
|
* with a PDFImage when the image is ready to be used.
|
||||||
*/
|
*/
|
||||||
PDFImage.buildImage = function({ handler, xref, res, image, isInline = false,
|
PDFImage.buildImage = function({
|
||||||
|
handler,
|
||||||
|
xref,
|
||||||
|
res,
|
||||||
|
image,
|
||||||
|
isInline = false,
|
||||||
nativeDecoder = null,
|
nativeDecoder = null,
|
||||||
pdfFunctionFactory, }) {
|
pdfFunctionFactory,
|
||||||
|
}) {
|
||||||
var imagePromise = handleImageData(image, nativeDecoder);
|
var imagePromise = handleImageData(image, nativeDecoder);
|
||||||
var smaskPromise;
|
var smaskPromise;
|
||||||
var maskPromise;
|
var maskPromise;
|
||||||
|
|
||||||
var smask = image.dict.get('SMask');
|
var smask = image.dict.get("SMask");
|
||||||
var mask = image.dict.get('Mask');
|
var mask = image.dict.get("Mask");
|
||||||
|
|
||||||
if (smask) {
|
if (smask) {
|
||||||
smaskPromise = handleImageData(smask, nativeDecoder);
|
smaskPromise = handleImageData(smask, nativeDecoder);
|
||||||
@ -242,7 +284,7 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
} else if (Array.isArray(mask)) {
|
} else if (Array.isArray(mask)) {
|
||||||
maskPromise = Promise.resolve(mask);
|
maskPromise = Promise.resolve(mask);
|
||||||
} else {
|
} else {
|
||||||
warn('Unsupported mask format.');
|
warn("Unsupported mask format.");
|
||||||
maskPromise = Promise.resolve(null);
|
maskPromise = Promise.resolve(null);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -260,15 +302,25 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
mask: maskData,
|
mask: maskData,
|
||||||
pdfFunctionFactory,
|
pdfFunctionFactory,
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
PDFImage.createMask = function({ imgArray, width, height,
|
PDFImage.createMask = function({
|
||||||
imageIsFromDecodeStream, inverseDecode, }) {
|
imgArray,
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
width,
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
height,
|
||||||
assert(imgArray instanceof Uint8ClampedArray,
|
imageIsFromDecodeStream,
|
||||||
'PDFImage.createMask: Unsupported "imgArray" type.');
|
inverseDecode,
|
||||||
|
}) {
|
||||||
|
if (
|
||||||
|
typeof PDFJSDev === "undefined" ||
|
||||||
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
|
) {
|
||||||
|
assert(
|
||||||
|
imgArray instanceof Uint8ClampedArray,
|
||||||
|
'PDFImage.createMask: Unsupported "imgArray" type.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// |imgArray| might not contain full data for every pixel of the mask, so
|
// |imgArray| might not contain full data for every pixel of the mask, so
|
||||||
// we need to distinguish between |computedLength| and |actualLength|.
|
// we need to distinguish between |computedLength| and |actualLength|.
|
||||||
@ -301,24 +353,28 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
// in this thread can be relying on its contents.
|
// in this thread can be relying on its contents.
|
||||||
if (inverseDecode) {
|
if (inverseDecode) {
|
||||||
for (i = 0; i < actualLength; i++) {
|
for (i = 0; i < actualLength; i++) {
|
||||||
data[i] ^= 0xFF;
|
data[i] ^= 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { data, width, height, };
|
return { data, width, height };
|
||||||
};
|
};
|
||||||
|
|
||||||
PDFImage.prototype = {
|
PDFImage.prototype = {
|
||||||
get drawWidth() {
|
get drawWidth() {
|
||||||
return Math.max(this.width,
|
return Math.max(
|
||||||
this.smask && this.smask.width || 0,
|
this.width,
|
||||||
this.mask && this.mask.width || 0);
|
(this.smask && this.smask.width) || 0,
|
||||||
|
(this.mask && this.mask.width) || 0
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
get drawHeight() {
|
get drawHeight() {
|
||||||
return Math.max(this.height,
|
return Math.max(
|
||||||
this.smask && this.smask.height || 0,
|
this.height,
|
||||||
this.mask && this.mask.height || 0);
|
(this.smask && this.smask.height) || 0,
|
||||||
|
(this.mask && this.mask.height) || 0
|
||||||
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
decodeBuffer(buffer) {
|
decodeBuffer(buffer) {
|
||||||
@ -333,15 +389,19 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
if (bpc === 1) {
|
if (bpc === 1) {
|
||||||
// If the buffer needed decode that means it just needs to be inverted.
|
// If the buffer needed decode that means it just needs to be inverted.
|
||||||
for (i = 0, ii = buffer.length; i < ii; i++) {
|
for (i = 0, ii = buffer.length; i < ii; i++) {
|
||||||
buffer[i] = +!(buffer[i]);
|
buffer[i] = +!buffer[i];
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var index = 0;
|
var index = 0;
|
||||||
for (i = 0, ii = this.width * this.height; i < ii; i++) {
|
for (i = 0, ii = this.width * this.height; i < ii; i++) {
|
||||||
for (var j = 0; j < numComps; j++) {
|
for (var j = 0; j < numComps; j++) {
|
||||||
buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j],
|
buffer[index] = decodeAndClamp(
|
||||||
decodeCoefficients[j], max);
|
buffer[index],
|
||||||
|
decodeAddends[j],
|
||||||
|
decodeCoefficients[j],
|
||||||
|
max
|
||||||
|
);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,12 +421,18 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
|
|
||||||
var length = width * height * numComps;
|
var length = width * height * numComps;
|
||||||
var bufferPos = 0;
|
var bufferPos = 0;
|
||||||
var output = (bpc <= 8 ? new Uint8Array(length) :
|
var output =
|
||||||
(bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length)));
|
bpc <= 8
|
||||||
|
? new Uint8Array(length)
|
||||||
|
: bpc <= 16
|
||||||
|
? new Uint16Array(length)
|
||||||
|
: new Uint32Array(length);
|
||||||
var rowComps = width * numComps;
|
var rowComps = width * numComps;
|
||||||
|
|
||||||
var max = (1 << bpc) - 1;
|
var max = (1 << bpc) - 1;
|
||||||
var i = 0, ii, buf;
|
var i = 0,
|
||||||
|
ii,
|
||||||
|
buf;
|
||||||
|
|
||||||
if (bpc === 1) {
|
if (bpc === 1) {
|
||||||
// Optimization for reading 1 bpc images.
|
// Optimization for reading 1 bpc images.
|
||||||
@ -416,7 +482,7 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
|
|
||||||
var remainingBits = bits - bpc;
|
var remainingBits = bits - bpc;
|
||||||
var value = buf >> remainingBits;
|
var value = buf >> remainingBits;
|
||||||
output[i] = (value < 0 ? 0 : (value > max ? max : value));
|
output[i] = value < 0 ? 0 : value > max ? max : value;
|
||||||
buf = buf & ((1 << remainingBits) - 1);
|
buf = buf & ((1 << remainingBits) - 1);
|
||||||
bits = remainingBits;
|
bits = remainingBits;
|
||||||
}
|
}
|
||||||
@ -425,10 +491,14 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
fillOpacity(rgbaBuf, width, height, actualHeight, image) {
|
fillOpacity(rgbaBuf, width, height, actualHeight, image) {
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
assert(rgbaBuf instanceof Uint8ClampedArray,
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
'PDFImage.fillOpacity: Unsupported "rgbaBuf" type.');
|
) {
|
||||||
|
assert(
|
||||||
|
rgbaBuf instanceof Uint8ClampedArray,
|
||||||
|
'PDFImage.fillOpacity: Unsupported "rgbaBuf" type.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var smask = this.smask;
|
var smask = this.smask;
|
||||||
var mask = this.mask;
|
var mask = this.mask;
|
||||||
@ -440,8 +510,14 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
alphaBuf = new Uint8ClampedArray(sw * sh);
|
alphaBuf = new Uint8ClampedArray(sw * sh);
|
||||||
smask.fillGrayBuffer(alphaBuf);
|
smask.fillGrayBuffer(alphaBuf);
|
||||||
if (sw !== width || sh !== height) {
|
if (sw !== width || sh !== height) {
|
||||||
alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh,
|
alphaBuf = resizeImageMask(
|
||||||
width, height);
|
alphaBuf,
|
||||||
|
smask.bpc,
|
||||||
|
sw,
|
||||||
|
sh,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (mask) {
|
} else if (mask) {
|
||||||
if (mask instanceof PDFImage) {
|
if (mask instanceof PDFImage) {
|
||||||
@ -457,8 +533,14 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sw !== width || sh !== height) {
|
if (sw !== width || sh !== height) {
|
||||||
alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh,
|
alphaBuf = resizeImageMask(
|
||||||
width, height);
|
alphaBuf,
|
||||||
|
mask.bpc,
|
||||||
|
sw,
|
||||||
|
sh,
|
||||||
|
width,
|
||||||
|
height
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (Array.isArray(mask)) {
|
} else if (Array.isArray(mask)) {
|
||||||
// Color key mask: if any of the components are outside the range
|
// Color key mask: if any of the components are outside the range
|
||||||
@ -479,7 +561,7 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
alphaBuf[i] = opacity;
|
alphaBuf[i] = opacity;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new FormatError('Unknown mask format.');
|
throw new FormatError("Unknown mask format.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,10 +578,14 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
undoPreblend(buffer, width, height) {
|
undoPreblend(buffer, width, height) {
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
assert(buffer instanceof Uint8ClampedArray,
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
'PDFImage.undoPreblend: Unsupported "buffer" type.');
|
) {
|
||||||
|
assert(
|
||||||
|
buffer instanceof Uint8ClampedArray,
|
||||||
|
'PDFImage.undoPreblend: Unsupported "buffer" type.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var matte = this.smask && this.smask.matte;
|
var matte = this.smask && this.smask.matte;
|
||||||
if (!matte) {
|
if (!matte) {
|
||||||
@ -530,7 +616,8 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
createImageData(forceRGBA = false) {
|
createImageData(forceRGBA = false) {
|
||||||
var drawWidth = this.drawWidth;
|
var drawWidth = this.drawWidth;
|
||||||
var drawHeight = this.drawHeight;
|
var drawHeight = this.drawHeight;
|
||||||
var imgData = { // other fields are filled in below
|
var imgData = {
|
||||||
|
// other fields are filled in below
|
||||||
width: drawWidth,
|
width: drawWidth,
|
||||||
height: drawHeight,
|
height: drawHeight,
|
||||||
kind: 0,
|
kind: 0,
|
||||||
@ -555,14 +642,22 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
// Similarly, if it is a 24-bit-per pixel RGB image without any
|
// Similarly, if it is a 24-bit-per pixel RGB image without any
|
||||||
// complications, we avoid expanding by 1.333x to RGBA form.
|
// complications, we avoid expanding by 1.333x to RGBA form.
|
||||||
var kind;
|
var kind;
|
||||||
if (this.colorSpace.name === 'DeviceGray' && bpc === 1) {
|
if (this.colorSpace.name === "DeviceGray" && bpc === 1) {
|
||||||
kind = ImageKind.GRAYSCALE_1BPP;
|
kind = ImageKind.GRAYSCALE_1BPP;
|
||||||
} else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 &&
|
} else if (
|
||||||
!this.needsDecode) {
|
this.colorSpace.name === "DeviceRGB" &&
|
||||||
|
bpc === 8 &&
|
||||||
|
!this.needsDecode
|
||||||
|
) {
|
||||||
kind = ImageKind.RGB_24BPP;
|
kind = ImageKind.RGB_24BPP;
|
||||||
}
|
}
|
||||||
if (kind && !this.smask && !this.mask &&
|
if (
|
||||||
drawWidth === originalWidth && drawHeight === originalHeight) {
|
kind &&
|
||||||
|
!this.smask &&
|
||||||
|
!this.mask &&
|
||||||
|
drawWidth === originalWidth &&
|
||||||
|
drawHeight === originalHeight
|
||||||
|
) {
|
||||||
imgData.kind = kind;
|
imgData.kind = kind;
|
||||||
|
|
||||||
imgArray = this.getImageBytes(originalHeight * rowBytes);
|
imgArray = this.getImageBytes(originalHeight * rowBytes);
|
||||||
@ -580,8 +675,10 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
}
|
}
|
||||||
if (this.needsDecode) {
|
if (this.needsDecode) {
|
||||||
// Invert the buffer (which must be grayscale if we reached here).
|
// Invert the buffer (which must be grayscale if we reached here).
|
||||||
assert(kind === ImageKind.GRAYSCALE_1BPP,
|
assert(
|
||||||
'PDFImage.createImageData: The image must be grayscale.');
|
kind === ImageKind.GRAYSCALE_1BPP,
|
||||||
|
"PDFImage.createImageData: The image must be grayscale."
|
||||||
|
);
|
||||||
var buffer = imgData.data;
|
var buffer = imgData.data;
|
||||||
for (var i = 0, ii = buffer.length; i < ii; i++) {
|
for (var i = 0, ii = buffer.length; i < ii; i++) {
|
||||||
buffer[i] ^= 0xff;
|
buffer[i] ^= 0xff;
|
||||||
@ -592,16 +689,20 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
if (this.image instanceof JpegStream && !this.smask && !this.mask) {
|
if (this.image instanceof JpegStream && !this.smask && !this.mask) {
|
||||||
let imageLength = originalHeight * rowBytes;
|
let imageLength = originalHeight * rowBytes;
|
||||||
switch (this.colorSpace.name) {
|
switch (this.colorSpace.name) {
|
||||||
case 'DeviceGray':
|
case "DeviceGray":
|
||||||
// Avoid truncating the image, since `JpegImage.getData`
|
// Avoid truncating the image, since `JpegImage.getData`
|
||||||
// will expand the image data when `forceRGB === true`.
|
// will expand the image data when `forceRGB === true`.
|
||||||
imageLength *= 3;
|
imageLength *= 3;
|
||||||
/* falls through */
|
/* falls through */
|
||||||
case 'DeviceRGB':
|
case "DeviceRGB":
|
||||||
case 'DeviceCMYK':
|
case "DeviceCMYK":
|
||||||
imgData.kind = ImageKind.RGB_24BPP;
|
imgData.kind = ImageKind.RGB_24BPP;
|
||||||
imgData.data = this.getImageBytes(imageLength,
|
imgData.data = this.getImageBytes(
|
||||||
drawWidth, drawHeight, /* forceRGB = */ true);
|
imageLength,
|
||||||
|
drawWidth,
|
||||||
|
drawHeight,
|
||||||
|
/* forceRGB = */ true
|
||||||
|
);
|
||||||
return imgData;
|
return imgData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -609,8 +710,8 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
|
|
||||||
imgArray = this.getImageBytes(originalHeight * rowBytes);
|
imgArray = this.getImageBytes(originalHeight * rowBytes);
|
||||||
// imgArray can be incomplete (e.g. after CCITT fax encoding).
|
// imgArray can be incomplete (e.g. after CCITT fax encoding).
|
||||||
var actualHeight = 0 | (imgArray.length / rowBytes *
|
var actualHeight =
|
||||||
drawHeight / originalHeight);
|
0 | (((imgArray.length / rowBytes) * drawHeight) / originalHeight);
|
||||||
|
|
||||||
var comps = this.getComponents(imgArray);
|
var comps = this.getComponents(imgArray);
|
||||||
|
|
||||||
@ -629,16 +730,29 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
maybeUndoPreblend = true;
|
maybeUndoPreblend = true;
|
||||||
|
|
||||||
// Color key masking (opacity) must be performed before decoding.
|
// Color key masking (opacity) must be performed before decoding.
|
||||||
this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight,
|
this.fillOpacity(
|
||||||
comps);
|
imgData.data,
|
||||||
|
drawWidth,
|
||||||
|
drawHeight,
|
||||||
|
actualHeight,
|
||||||
|
comps
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.needsDecode) {
|
if (this.needsDecode) {
|
||||||
this.decodeBuffer(comps);
|
this.decodeBuffer(comps);
|
||||||
}
|
}
|
||||||
this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight,
|
this.colorSpace.fillRgb(
|
||||||
drawWidth, drawHeight, actualHeight, bpc, comps,
|
imgData.data,
|
||||||
alpha01);
|
originalWidth,
|
||||||
|
originalHeight,
|
||||||
|
drawWidth,
|
||||||
|
drawHeight,
|
||||||
|
actualHeight,
|
||||||
|
bpc,
|
||||||
|
comps,
|
||||||
|
alpha01
|
||||||
|
);
|
||||||
if (maybeUndoPreblend) {
|
if (maybeUndoPreblend) {
|
||||||
this.undoPreblend(imgData.data, drawWidth, actualHeight);
|
this.undoPreblend(imgData.data, drawWidth, actualHeight);
|
||||||
}
|
}
|
||||||
@ -647,15 +761,20 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
fillGrayBuffer(buffer) {
|
fillGrayBuffer(buffer) {
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
assert(buffer instanceof Uint8ClampedArray,
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
'PDFImage.fillGrayBuffer: Unsupported "buffer" type.');
|
) {
|
||||||
|
assert(
|
||||||
|
buffer instanceof Uint8ClampedArray,
|
||||||
|
'PDFImage.fillGrayBuffer: Unsupported "buffer" type.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var numComps = this.numComps;
|
var numComps = this.numComps;
|
||||||
if (numComps !== 1) {
|
if (numComps !== 1) {
|
||||||
throw new FormatError(
|
throw new FormatError(
|
||||||
`Reading gray scale from a color image: ${numComps}`);
|
`Reading gray scale from a color image: ${numComps}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var width = this.width;
|
var width = this.width;
|
||||||
@ -680,7 +799,7 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
} else {
|
} else {
|
||||||
// scale to {0, 255}
|
// scale to {0, 255}
|
||||||
for (i = 0; i < length; ++i) {
|
for (i = 0; i < length; ++i) {
|
||||||
buffer[i] = (-comps[i]) & 255;
|
buffer[i] = -comps[i] & 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -708,6 +827,4 @@ var PDFImage = (function PDFImageClosure() {
|
|||||||
return PDFImage;
|
return PDFImage;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { PDFImage };
|
||||||
PDFImage,
|
|
||||||
};
|
|
||||||
|
@ -14,13 +14,18 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import { ColorSpace } from './colorspace';
|
import { ColorSpace } from "./colorspace";
|
||||||
import { JpegStream } from './jpeg_stream';
|
import { JpegStream } from "./jpeg_stream";
|
||||||
import { Stream } from './stream';
|
import { Stream } from "./stream";
|
||||||
|
|
||||||
class NativeImageDecoder {
|
class NativeImageDecoder {
|
||||||
constructor({ xref, resources, handler, forceDataSchema = false,
|
constructor({
|
||||||
pdfFunctionFactory, }) {
|
xref,
|
||||||
|
resources,
|
||||||
|
handler,
|
||||||
|
forceDataSchema = false,
|
||||||
|
pdfFunctionFactory,
|
||||||
|
}) {
|
||||||
this.xref = xref;
|
this.xref = xref;
|
||||||
this.resources = resources;
|
this.resources = resources;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
@ -29,21 +34,34 @@ class NativeImageDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
canDecode(image) {
|
canDecode(image) {
|
||||||
return image instanceof JpegStream &&
|
return (
|
||||||
NativeImageDecoder.isDecodable(image, this.xref, this.resources,
|
image instanceof JpegStream &&
|
||||||
this.pdfFunctionFactory);
|
NativeImageDecoder.isDecodable(
|
||||||
|
image,
|
||||||
|
this.xref,
|
||||||
|
this.resources,
|
||||||
|
this.pdfFunctionFactory
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
decode(image) {
|
decode(image) {
|
||||||
// For natively supported JPEGs send them to the main thread for decoding.
|
// For natively supported JPEGs send them to the main thread for decoding.
|
||||||
const dict = image.dict;
|
const dict = image.dict;
|
||||||
let colorSpace = dict.get('ColorSpace', 'CS');
|
let colorSpace = dict.get("ColorSpace", "CS");
|
||||||
colorSpace = ColorSpace.parse(colorSpace, this.xref, this.resources,
|
colorSpace = ColorSpace.parse(
|
||||||
this.pdfFunctionFactory);
|
colorSpace,
|
||||||
|
this.xref,
|
||||||
|
this.resources,
|
||||||
|
this.pdfFunctionFactory
|
||||||
|
);
|
||||||
|
|
||||||
return this.handler.sendWithPromise('JpegDecode', [
|
return this.handler
|
||||||
image.getIR(this.forceDataSchema), colorSpace.numComps
|
.sendWithPromise("JpegDecode", [
|
||||||
]).then(function({ data, width, height, }) {
|
image.getIR(this.forceDataSchema),
|
||||||
|
colorSpace.numComps,
|
||||||
|
])
|
||||||
|
.then(function({ data, width, height }) {
|
||||||
return new Stream(data, 0, data.length, dict);
|
return new Stream(data, 0, data.length, dict);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -54,14 +72,20 @@ class NativeImageDecoder {
|
|||||||
*/
|
*/
|
||||||
static isSupported(image, xref, res, pdfFunctionFactory) {
|
static isSupported(image, xref, res, pdfFunctionFactory) {
|
||||||
const dict = image.dict;
|
const dict = image.dict;
|
||||||
if (dict.has('DecodeParms') || dict.has('DP')) {
|
if (dict.has("DecodeParms") || dict.has("DP")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res,
|
const cs = ColorSpace.parse(
|
||||||
pdfFunctionFactory);
|
dict.get("ColorSpace", "CS"),
|
||||||
|
xref,
|
||||||
|
res,
|
||||||
|
pdfFunctionFactory
|
||||||
|
);
|
||||||
// isDefaultDecode() of DeviceGray and DeviceRGB needs no `bpc` argument.
|
// isDefaultDecode() of DeviceGray and DeviceRGB needs no `bpc` argument.
|
||||||
return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') &&
|
return (
|
||||||
cs.isDefaultDecode(dict.getArray('Decode', 'D'));
|
(cs.name === "DeviceGray" || cs.name === "DeviceRGB") &&
|
||||||
|
cs.isDefaultDecode(dict.getArray("Decode", "D"))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,17 +93,21 @@ class NativeImageDecoder {
|
|||||||
*/
|
*/
|
||||||
static isDecodable(image, xref, res, pdfFunctionFactory) {
|
static isDecodable(image, xref, res, pdfFunctionFactory) {
|
||||||
const dict = image.dict;
|
const dict = image.dict;
|
||||||
if (dict.has('DecodeParms') || dict.has('DP')) {
|
if (dict.has("DecodeParms") || dict.has("DP")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res,
|
const cs = ColorSpace.parse(
|
||||||
pdfFunctionFactory);
|
dict.get("ColorSpace", "CS"),
|
||||||
const bpc = dict.get('BitsPerComponent', 'BPC') || 1;
|
xref,
|
||||||
return (cs.numComps === 1 || cs.numComps === 3) &&
|
res,
|
||||||
cs.isDefaultDecode(dict.getArray('Decode', 'D'), bpc);
|
pdfFunctionFactory
|
||||||
|
);
|
||||||
|
const bpc = dict.get("BitsPerComponent", "BPC") || 1;
|
||||||
|
return (
|
||||||
|
(cs.numComps === 1 || cs.numComps === 3) &&
|
||||||
|
cs.isDefaultDecode(dict.getArray("Decode", "D"), bpc)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { NativeImageDecoder };
|
||||||
NativeImageDecoder,
|
|
||||||
};
|
|
||||||
|
1348
src/core/jbig2.js
1348
src/core/jbig2.js
File diff suppressed because it is too large
Load Diff
@ -13,10 +13,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isDict, isStream } from './primitives';
|
import { isDict, isStream } from "./primitives";
|
||||||
import { DecodeStream } from './stream';
|
import { DecodeStream } from "./stream";
|
||||||
import { Jbig2Image } from './jbig2';
|
import { Jbig2Image } from "./jbig2";
|
||||||
import { shadow } from '../shared/util';
|
import { shadow } from "../shared/util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For JBIG2's we use a library to decode these images and
|
* For JBIG2's we use a library to decode these images and
|
||||||
@ -34,10 +34,10 @@ let Jbig2Stream = (function Jbig2StreamClosure() {
|
|||||||
|
|
||||||
Jbig2Stream.prototype = Object.create(DecodeStream.prototype);
|
Jbig2Stream.prototype = Object.create(DecodeStream.prototype);
|
||||||
|
|
||||||
Object.defineProperty(Jbig2Stream.prototype, 'bytes', {
|
Object.defineProperty(Jbig2Stream.prototype, "bytes", {
|
||||||
get() {
|
get() {
|
||||||
// If `this.maybeLength` is null, we'll get the entire stream.
|
// If `this.maybeLength` is null, we'll get the entire stream.
|
||||||
return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
|
return shadow(this, "bytes", this.stream.getBytes(this.maybeLength));
|
||||||
},
|
},
|
||||||
configurable: true,
|
configurable: true,
|
||||||
});
|
});
|
||||||
@ -55,19 +55,19 @@ let Jbig2Stream = (function Jbig2StreamClosure() {
|
|||||||
|
|
||||||
let chunks = [];
|
let chunks = [];
|
||||||
if (isDict(this.params)) {
|
if (isDict(this.params)) {
|
||||||
let globalsStream = this.params.get('JBIG2Globals');
|
let globalsStream = this.params.get("JBIG2Globals");
|
||||||
if (isStream(globalsStream)) {
|
if (isStream(globalsStream)) {
|
||||||
let globals = globalsStream.getBytes();
|
let globals = globalsStream.getBytes();
|
||||||
chunks.push({ data: globals, start: 0, end: globals.length, });
|
chunks.push({ data: globals, start: 0, end: globals.length });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chunks.push({ data: this.bytes, start: 0, end: this.bytes.length, });
|
chunks.push({ data: this.bytes, start: 0, end: this.bytes.length });
|
||||||
let data = jbig2Image.parseChunks(chunks);
|
let data = jbig2Image.parseChunks(chunks);
|
||||||
let dataLength = data.length;
|
let dataLength = data.length;
|
||||||
|
|
||||||
// JBIG2 had black as 1 and white as 0, inverting the colors
|
// JBIG2 had black as 1 and white as 0, inverting the colors
|
||||||
for (let i = 0; i < dataLength; i++) {
|
for (let i = 0; i < dataLength; i++) {
|
||||||
data[i] ^= 0xFF;
|
data[i] ^= 0xff;
|
||||||
}
|
}
|
||||||
this.buffer = data;
|
this.buffer = data;
|
||||||
this.bufferLength = dataLength;
|
this.bufferLength = dataLength;
|
||||||
@ -77,6 +77,4 @@ let Jbig2Stream = (function Jbig2StreamClosure() {
|
|||||||
return Jbig2Stream;
|
return Jbig2Stream;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { Jbig2Stream };
|
||||||
Jbig2Stream,
|
|
||||||
};
|
|
||||||
|
@ -13,10 +13,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createObjectURL, shadow } from '../shared/util';
|
import { createObjectURL, shadow } from "../shared/util";
|
||||||
import { DecodeStream } from './stream';
|
import { DecodeStream } from "./stream";
|
||||||
import { isDict } from './primitives';
|
import { isDict } from "./primitives";
|
||||||
import { JpegImage } from './jpg';
|
import { JpegImage } from "./jpg";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Depending on the type of JPEG a JpegStream is handled in different ways. For
|
* Depending on the type of JPEG a JpegStream is handled in different ways. For
|
||||||
@ -31,7 +31,8 @@ let JpegStream = (function JpegStreamClosure() {
|
|||||||
// Note: this seems to mainly affect inline images.
|
// Note: this seems to mainly affect inline images.
|
||||||
let ch;
|
let ch;
|
||||||
while ((ch = stream.getByte()) !== -1) {
|
while ((ch = stream.getByte()) !== -1) {
|
||||||
if (ch === 0xFF) { // Find the first byte of the SOI marker (0xFFD8).
|
if (ch === 0xff) {
|
||||||
|
// Find the first byte of the SOI marker (0xFFD8).
|
||||||
stream.skip(-1); // Reset the stream position to the SOI.
|
stream.skip(-1); // Reset the stream position to the SOI.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -46,10 +47,10 @@ let JpegStream = (function JpegStreamClosure() {
|
|||||||
|
|
||||||
JpegStream.prototype = Object.create(DecodeStream.prototype);
|
JpegStream.prototype = Object.create(DecodeStream.prototype);
|
||||||
|
|
||||||
Object.defineProperty(JpegStream.prototype, 'bytes', {
|
Object.defineProperty(JpegStream.prototype, "bytes", {
|
||||||
get: function JpegStream_bytes() {
|
get: function JpegStream_bytes() {
|
||||||
// If `this.maybeLength` is null, we'll get the entire stream.
|
// If `this.maybeLength` is null, we'll get the entire stream.
|
||||||
return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
|
return shadow(this, "bytes", this.stream.getBytes(this.maybeLength));
|
||||||
},
|
},
|
||||||
configurable: true,
|
configurable: true,
|
||||||
});
|
});
|
||||||
@ -69,9 +70,9 @@ let JpegStream = (function JpegStreamClosure() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Checking if values need to be transformed before conversion.
|
// Checking if values need to be transformed before conversion.
|
||||||
let decodeArr = this.dict.getArray('Decode', 'D');
|
let decodeArr = this.dict.getArray("Decode", "D");
|
||||||
if (this.forceRGB && Array.isArray(decodeArr)) {
|
if (this.forceRGB && Array.isArray(decodeArr)) {
|
||||||
let bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
|
let bitsPerComponent = this.dict.get("BitsPerComponent") || 8;
|
||||||
let decodeArrLength = decodeArr.length;
|
let decodeArrLength = decodeArr.length;
|
||||||
let transform = new Int32Array(decodeArrLength);
|
let transform = new Int32Array(decodeArrLength);
|
||||||
let transformNeeded = false;
|
let transformNeeded = false;
|
||||||
@ -89,7 +90,7 @@ let JpegStream = (function JpegStreamClosure() {
|
|||||||
}
|
}
|
||||||
// Fetching the 'ColorTransform' entry, if it exists.
|
// Fetching the 'ColorTransform' entry, if it exists.
|
||||||
if (isDict(this.params)) {
|
if (isDict(this.params)) {
|
||||||
let colorTransform = this.params.get('ColorTransform');
|
let colorTransform = this.params.get("ColorTransform");
|
||||||
if (Number.isInteger(colorTransform)) {
|
if (Number.isInteger(colorTransform)) {
|
||||||
jpegOptions.colorTransform = colorTransform;
|
jpegOptions.colorTransform = colorTransform;
|
||||||
}
|
}
|
||||||
@ -109,12 +110,10 @@ let JpegStream = (function JpegStreamClosure() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
JpegStream.prototype.getIR = function(forceDataSchema = false) {
|
JpegStream.prototype.getIR = function(forceDataSchema = false) {
|
||||||
return createObjectURL(this.bytes, 'image/jpeg', forceDataSchema);
|
return createObjectURL(this.bytes, "image/jpeg", forceDataSchema);
|
||||||
};
|
};
|
||||||
|
|
||||||
return JpegStream;
|
return JpegStream;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { JpegStream };
|
||||||
JpegStream,
|
|
||||||
};
|
|
||||||
|
484
src/core/jpg.js
484
src/core/jpg.js
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint-disable no-multi-spaces */
|
/* eslint-disable no-multi-spaces */
|
||||||
|
|
||||||
import { assert, BaseException, warn } from '../shared/util';
|
import { assert, BaseException, warn } from "../shared/util";
|
||||||
|
|
||||||
class JpegError extends BaseException {
|
class JpegError extends BaseException {
|
||||||
constructor(msg) {
|
constructor(msg) {
|
||||||
@ -73,18 +73,23 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
var dctSqrt2 = 5793; // sqrt(2)
|
var dctSqrt2 = 5793; // sqrt(2)
|
||||||
var dctSqrt1d2 = 2896; // sqrt(2) / 2
|
var dctSqrt1d2 = 2896; // sqrt(2) / 2
|
||||||
|
|
||||||
function JpegImage({ decodeTransform = null, colorTransform = -1, } = {}) {
|
function JpegImage({ decodeTransform = null, colorTransform = -1 } = {}) {
|
||||||
this._decodeTransform = decodeTransform;
|
this._decodeTransform = decodeTransform;
|
||||||
this._colorTransform = colorTransform;
|
this._colorTransform = colorTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildHuffmanTable(codeLengths, values) {
|
function buildHuffmanTable(codeLengths, values) {
|
||||||
var k = 0, code = [], i, j, length = 16;
|
var k = 0,
|
||||||
|
code = [],
|
||||||
|
i,
|
||||||
|
j,
|
||||||
|
length = 16;
|
||||||
while (length > 0 && !codeLengths[length - 1]) {
|
while (length > 0 && !codeLengths[length - 1]) {
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
code.push({ children: [], index: 0, });
|
code.push({ children: [], index: 0 });
|
||||||
var p = code[0], q;
|
var p = code[0],
|
||||||
|
q;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
for (j = 0; j < codeLengths[i]; j++) {
|
for (j = 0; j < codeLengths[i]; j++) {
|
||||||
p = code.pop();
|
p = code.pop();
|
||||||
@ -95,7 +100,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
p.index++;
|
p.index++;
|
||||||
code.push(p);
|
code.push(p);
|
||||||
while (code.length <= i) {
|
while (code.length <= i) {
|
||||||
code.push(q = { children: [], index: 0, });
|
code.push((q = { children: [], index: 0 }));
|
||||||
p.children[p.index] = q.children;
|
p.children[p.index] = q.children;
|
||||||
p = q;
|
p = q;
|
||||||
}
|
}
|
||||||
@ -103,7 +108,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
if (i + 1 < length) {
|
if (i + 1 < length) {
|
||||||
// p here points to last code
|
// p here points to last code
|
||||||
code.push(q = { children: [], index: 0, });
|
code.push((q = { children: [], index: 0 }));
|
||||||
p.children[p.index] = q.children;
|
p.children[p.index] = q.children;
|
||||||
p = q;
|
p = q;
|
||||||
}
|
}
|
||||||
@ -115,13 +120,24 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
return 64 * ((component.blocksPerLine + 1) * row + col);
|
return 64 * ((component.blocksPerLine + 1) * row + col);
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeScan(data, offset, frame, components, resetInterval,
|
function decodeScan(
|
||||||
spectralStart, spectralEnd, successivePrev, successive,
|
data,
|
||||||
parseDNLMarker = false) {
|
offset,
|
||||||
|
frame,
|
||||||
|
components,
|
||||||
|
resetInterval,
|
||||||
|
spectralStart,
|
||||||
|
spectralEnd,
|
||||||
|
successivePrev,
|
||||||
|
successive,
|
||||||
|
parseDNLMarker = false
|
||||||
|
) {
|
||||||
var mcusPerLine = frame.mcusPerLine;
|
var mcusPerLine = frame.mcusPerLine;
|
||||||
var progressive = frame.progressive;
|
var progressive = frame.progressive;
|
||||||
|
|
||||||
var startOffset = offset, bitsData = 0, bitsCount = 0;
|
var startOffset = offset,
|
||||||
|
bitsData = 0,
|
||||||
|
bitsCount = 0;
|
||||||
|
|
||||||
function readBit() {
|
function readBit() {
|
||||||
if (bitsCount > 0) {
|
if (bitsCount > 0) {
|
||||||
@ -129,22 +145,28 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
return (bitsData >> bitsCount) & 1;
|
return (bitsData >> bitsCount) & 1;
|
||||||
}
|
}
|
||||||
bitsData = data[offset++];
|
bitsData = data[offset++];
|
||||||
if (bitsData === 0xFF) {
|
if (bitsData === 0xff) {
|
||||||
var nextByte = data[offset++];
|
var nextByte = data[offset++];
|
||||||
if (nextByte) {
|
if (nextByte) {
|
||||||
if (nextByte === 0xDC && parseDNLMarker) { // DNL == 0xFFDC
|
if (nextByte === 0xdc && parseDNLMarker) {
|
||||||
|
// DNL == 0xFFDC
|
||||||
offset += 2; // Skip data length.
|
offset += 2; // Skip data length.
|
||||||
const scanLines = (data[offset++] << 8) | data[offset++];
|
const scanLines = (data[offset++] << 8) | data[offset++];
|
||||||
if (scanLines > 0 && scanLines !== frame.scanLines) {
|
if (scanLines > 0 && scanLines !== frame.scanLines) {
|
||||||
throw new DNLMarkerError(
|
throw new DNLMarkerError(
|
||||||
'Found DNL marker (0xFFDC) while parsing scan data', scanLines);
|
"Found DNL marker (0xFFDC) while parsing scan data",
|
||||||
|
scanLines
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else if (nextByte === 0xD9) { // EOI == 0xFFD9
|
} else if (nextByte === 0xd9) {
|
||||||
|
// EOI == 0xFFD9
|
||||||
throw new EOIMarkerError(
|
throw new EOIMarkerError(
|
||||||
'Found EOI marker (0xFFD9) while parsing scan data');
|
"Found EOI marker (0xFFD9) while parsing scan data"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
throw new JpegError(
|
throw new JpegError(
|
||||||
`unexpected marker ${((bitsData << 8) | nextByte).toString(16)}`);
|
`unexpected marker ${((bitsData << 8) | nextByte).toString(16)}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// unstuff 0
|
// unstuff 0
|
||||||
}
|
}
|
||||||
@ -156,11 +178,11 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
var node = tree;
|
var node = tree;
|
||||||
while (true) {
|
while (true) {
|
||||||
node = node[readBit()];
|
node = node[readBit()];
|
||||||
if (typeof node === 'number') {
|
if (typeof node === "number") {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (typeof node !== 'object') {
|
if (typeof node !== "object") {
|
||||||
throw new JpegError('invalid huffman sequence');
|
throw new JpegError("invalid huffman sequence");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -188,11 +210,12 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
function decodeBaseline(component, offset) {
|
function decodeBaseline(component, offset) {
|
||||||
var t = decodeHuffman(component.huffmanTableDC);
|
var t = decodeHuffman(component.huffmanTableDC);
|
||||||
var diff = t === 0 ? 0 : receiveAndExtend(t);
|
var diff = t === 0 ? 0 : receiveAndExtend(t);
|
||||||
component.blockData[offset] = (component.pred += diff);
|
component.blockData[offset] = component.pred += diff;
|
||||||
var k = 1;
|
var k = 1;
|
||||||
while (k < 64) {
|
while (k < 64) {
|
||||||
var rs = decodeHuffman(component.huffmanTableAC);
|
var rs = decodeHuffman(component.huffmanTableAC);
|
||||||
var s = rs & 15, r = rs >> 4;
|
var s = rs & 15,
|
||||||
|
r = rs >> 4;
|
||||||
if (s === 0) {
|
if (s === 0) {
|
||||||
if (r < 15) {
|
if (r < 15) {
|
||||||
break;
|
break;
|
||||||
@ -209,8 +232,8 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
|
|
||||||
function decodeDCFirst(component, offset) {
|
function decodeDCFirst(component, offset) {
|
||||||
var t = decodeHuffman(component.huffmanTableDC);
|
var t = decodeHuffman(component.huffmanTableDC);
|
||||||
var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
|
var diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
|
||||||
component.blockData[offset] = (component.pred += diff);
|
component.blockData[offset] = component.pred += diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeDCSuccessive(component, offset) {
|
function decodeDCSuccessive(component, offset) {
|
||||||
@ -223,10 +246,12 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
eobrun--;
|
eobrun--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var k = spectralStart, e = spectralEnd;
|
var k = spectralStart,
|
||||||
|
e = spectralEnd;
|
||||||
while (k <= e) {
|
while (k <= e) {
|
||||||
var rs = decodeHuffman(component.huffmanTableAC);
|
var rs = decodeHuffman(component.huffmanTableAC);
|
||||||
var s = rs & 15, r = rs >> 4;
|
var s = rs & 15,
|
||||||
|
r = rs >> 4;
|
||||||
if (s === 0) {
|
if (s === 0) {
|
||||||
if (r < 15) {
|
if (r < 15) {
|
||||||
eobrun = receive(r) + (1 << r) - 1;
|
eobrun = receive(r) + (1 << r) - 1;
|
||||||
@ -243,7 +268,8 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var successiveACState = 0, successiveACNextValue;
|
var successiveACState = 0,
|
||||||
|
successiveACNextValue;
|
||||||
function decodeACSuccessive(component, offset) {
|
function decodeACSuccessive(component, offset) {
|
||||||
var k = spectralStart;
|
var k = spectralStart;
|
||||||
var e = spectralEnd;
|
var e = spectralEnd;
|
||||||
@ -268,7 +294,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (s !== 1) {
|
if (s !== 1) {
|
||||||
throw new JpegError('invalid ACn encoding');
|
throw new JpegError("invalid ACn encoding");
|
||||||
}
|
}
|
||||||
successiveACNextValue = receiveAndExtend(s);
|
successiveACNextValue = receiveAndExtend(s);
|
||||||
successiveACState = r ? 2 : 3;
|
successiveACState = r ? 2 : 3;
|
||||||
@ -339,7 +365,8 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
decodeFn = decodeBaseline;
|
decodeFn = decodeBaseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mcu = 0, fileMarker;
|
var mcu = 0,
|
||||||
|
fileMarker;
|
||||||
var mcuExpected;
|
var mcuExpected;
|
||||||
if (componentsLength === 1) {
|
if (componentsLength === 1) {
|
||||||
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
|
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
|
||||||
@ -350,8 +377,9 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
var h, v;
|
var h, v;
|
||||||
while (mcu < mcuExpected) {
|
while (mcu < mcuExpected) {
|
||||||
// reset interval stuff
|
// reset interval stuff
|
||||||
var mcuToRead = resetInterval ?
|
var mcuToRead = resetInterval
|
||||||
Math.min(mcuExpected - mcu, resetInterval) : mcuExpected;
|
? Math.min(mcuExpected - mcu, resetInterval)
|
||||||
|
: mcuExpected;
|
||||||
for (i = 0; i < componentsLength; i++) {
|
for (i = 0; i < componentsLength; i++) {
|
||||||
components[i].pred = 0;
|
components[i].pred = 0;
|
||||||
}
|
}
|
||||||
@ -388,16 +416,19 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
} else if (fileMarker.invalid) {
|
} else if (fileMarker.invalid) {
|
||||||
// Some bad images seem to pad Scan blocks with e.g. zero bytes, skip
|
// Some bad images seem to pad Scan blocks with e.g. zero bytes, skip
|
||||||
// past those to attempt to find a valid marker (fixes issue4090.pdf).
|
// past those to attempt to find a valid marker (fixes issue4090.pdf).
|
||||||
warn('decodeScan - unexpected MCU data, current marker is: ' +
|
warn(
|
||||||
fileMarker.invalid);
|
"decodeScan - unexpected MCU data, current marker is: " +
|
||||||
|
fileMarker.invalid
|
||||||
|
);
|
||||||
offset = fileMarker.offset;
|
offset = fileMarker.offset;
|
||||||
}
|
}
|
||||||
var marker = fileMarker && fileMarker.marker;
|
var marker = fileMarker && fileMarker.marker;
|
||||||
if (!marker || marker <= 0xFF00) {
|
if (!marker || marker <= 0xff00) {
|
||||||
throw new JpegError('decodeScan - a valid marker was not found.');
|
throw new JpegError("decodeScan - a valid marker was not found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx
|
if (marker >= 0xffd0 && marker <= 0xffd7) {
|
||||||
|
// RSTx
|
||||||
offset += 2;
|
offset += 2;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -408,8 +439,10 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
// Some images include more Scan blocks than expected, skip past those and
|
// Some images include more Scan blocks than expected, skip past those and
|
||||||
// attempt to find the next valid marker (fixes issue8182.pdf).
|
// attempt to find the next valid marker (fixes issue8182.pdf).
|
||||||
if (fileMarker && fileMarker.invalid) {
|
if (fileMarker && fileMarker.invalid) {
|
||||||
warn('decodeScan - unexpected Scan data, current marker is: ' +
|
warn(
|
||||||
fileMarker.invalid);
|
"decodeScan - unexpected Scan data, current marker is: " +
|
||||||
|
fileMarker.invalid
|
||||||
|
);
|
||||||
offset = fileMarker.offset;
|
offset = fileMarker.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,13 +455,14 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
|
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
|
||||||
// 988-991.
|
// 988-991.
|
||||||
function quantizeAndInverse(component, blockBufferOffset, p) {
|
function quantizeAndInverse(component, blockBufferOffset, p) {
|
||||||
var qt = component.quantizationTable, blockData = component.blockData;
|
var qt = component.quantizationTable,
|
||||||
|
blockData = component.blockData;
|
||||||
var v0, v1, v2, v3, v4, v5, v6, v7;
|
var v0, v1, v2, v3, v4, v5, v6, v7;
|
||||||
var p0, p1, p2, p3, p4, p5, p6, p7;
|
var p0, p1, p2, p3, p4, p5, p6, p7;
|
||||||
var t;
|
var t;
|
||||||
|
|
||||||
if (!qt) {
|
if (!qt) {
|
||||||
throw new JpegError('missing required Quantization Table.');
|
throw new JpegError("missing required Quantization Table.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// inverse DCT on rows
|
// inverse DCT on rows
|
||||||
@ -527,7 +561,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
|
if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
|
||||||
t = (dctSqrt2 * p0 + 8192) >> 14;
|
t = (dctSqrt2 * p0 + 8192) >> 14;
|
||||||
// convert to 8 bit
|
// convert to 8 bit
|
||||||
t = (t < -2040) ? 0 : (t >= 2024) ? 255 : (t + 2056) >> 4;
|
t = t < -2040 ? 0 : t >= 2024 ? 255 : (t + 2056) >> 4;
|
||||||
blockData[blockBufferOffset + col] = t;
|
blockData[blockBufferOffset + col] = t;
|
||||||
blockData[blockBufferOffset + col + 8] = t;
|
blockData[blockBufferOffset + col + 8] = t;
|
||||||
blockData[blockBufferOffset + col + 16] = t;
|
blockData[blockBufferOffset + col + 16] = t;
|
||||||
@ -585,14 +619,14 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
p4 = v3 - v4;
|
p4 = v3 - v4;
|
||||||
|
|
||||||
// convert to 8-bit integers
|
// convert to 8-bit integers
|
||||||
p0 = (p0 < 16) ? 0 : (p0 >= 4080) ? 255 : p0 >> 4;
|
p0 = p0 < 16 ? 0 : p0 >= 4080 ? 255 : p0 >> 4;
|
||||||
p1 = (p1 < 16) ? 0 : (p1 >= 4080) ? 255 : p1 >> 4;
|
p1 = p1 < 16 ? 0 : p1 >= 4080 ? 255 : p1 >> 4;
|
||||||
p2 = (p2 < 16) ? 0 : (p2 >= 4080) ? 255 : p2 >> 4;
|
p2 = p2 < 16 ? 0 : p2 >= 4080 ? 255 : p2 >> 4;
|
||||||
p3 = (p3 < 16) ? 0 : (p3 >= 4080) ? 255 : p3 >> 4;
|
p3 = p3 < 16 ? 0 : p3 >= 4080 ? 255 : p3 >> 4;
|
||||||
p4 = (p4 < 16) ? 0 : (p4 >= 4080) ? 255 : p4 >> 4;
|
p4 = p4 < 16 ? 0 : p4 >= 4080 ? 255 : p4 >> 4;
|
||||||
p5 = (p5 < 16) ? 0 : (p5 >= 4080) ? 255 : p5 >> 4;
|
p5 = p5 < 16 ? 0 : p5 >= 4080 ? 255 : p5 >> 4;
|
||||||
p6 = (p6 < 16) ? 0 : (p6 >= 4080) ? 255 : p6 >> 4;
|
p6 = p6 < 16 ? 0 : p6 >= 4080 ? 255 : p6 >> 4;
|
||||||
p7 = (p7 < 16) ? 0 : (p7 >= 4080) ? 255 : p7 >> 4;
|
p7 = p7 < 16 ? 0 : p7 >= 4080 ? 255 : p7 >> 4;
|
||||||
|
|
||||||
// store block data
|
// store block data
|
||||||
blockData[blockBufferOffset + col] = p0;
|
blockData[blockBufferOffset + col] = p0;
|
||||||
@ -632,7 +666,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
return null; // Don't attempt to read non-existent data and just return.
|
return null; // Don't attempt to read non-existent data and just return.
|
||||||
}
|
}
|
||||||
var currentMarker = peekUint16(currentPos);
|
var currentMarker = peekUint16(currentPos);
|
||||||
if (currentMarker >= 0xFFC0 && currentMarker <= 0xFFFE) {
|
if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) {
|
||||||
return {
|
return {
|
||||||
invalid: null,
|
invalid: null,
|
||||||
marker: currentMarker,
|
marker: currentMarker,
|
||||||
@ -640,7 +674,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
var newMarker = peekUint16(newPos);
|
var newMarker = peekUint16(newPos);
|
||||||
while (!(newMarker >= 0xFFC0 && newMarker <= 0xFFFE)) {
|
while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) {
|
||||||
if (++newPos >= maxPos) {
|
if (++newPos >= maxPos) {
|
||||||
return null; // Don't attempt to read non-existent data and just return.
|
return null; // Don't attempt to read non-existent data and just return.
|
||||||
}
|
}
|
||||||
@ -654,8 +688,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JpegImage.prototype = {
|
JpegImage.prototype = {
|
||||||
parse(data, { dnlScanLines = null, } = {}) {
|
parse(data, { dnlScanLines = null } = {}) {
|
||||||
|
|
||||||
function readUint16() {
|
function readUint16() {
|
||||||
var value = (data[offset] << 8) | data[offset + 1];
|
var value = (data[offset] << 8) | data[offset + 1];
|
||||||
offset += 2;
|
offset += 2;
|
||||||
@ -668,8 +701,10 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
|
|
||||||
var fileMarker = findNextFileMarker(data, endOffset, offset);
|
var fileMarker = findNextFileMarker(data, endOffset, offset);
|
||||||
if (fileMarker && fileMarker.invalid) {
|
if (fileMarker && fileMarker.invalid) {
|
||||||
warn('readDataBlock - incorrect length, current marker is: ' +
|
warn(
|
||||||
fileMarker.invalid);
|
"readDataBlock - incorrect length, current marker is: " +
|
||||||
|
fileMarker.invalid
|
||||||
|
);
|
||||||
endOffset = fileMarker.offset;
|
endOffset = fileMarker.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -683,15 +718,17 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
|
var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
|
||||||
for (var i = 0; i < frame.components.length; i++) {
|
for (var i = 0; i < frame.components.length; i++) {
|
||||||
component = frame.components[i];
|
component = frame.components[i];
|
||||||
var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) *
|
var blocksPerLine = Math.ceil(
|
||||||
component.h / frame.maxH);
|
(Math.ceil(frame.samplesPerLine / 8) * component.h) / frame.maxH
|
||||||
var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) *
|
);
|
||||||
component.v / frame.maxV);
|
var blocksPerColumn = Math.ceil(
|
||||||
|
(Math.ceil(frame.scanLines / 8) * component.v) / frame.maxV
|
||||||
|
);
|
||||||
var blocksPerLineForMcu = mcusPerLine * component.h;
|
var blocksPerLineForMcu = mcusPerLine * component.h;
|
||||||
var blocksPerColumnForMcu = mcusPerColumn * component.v;
|
var blocksPerColumnForMcu = mcusPerColumn * component.v;
|
||||||
|
|
||||||
var blocksBufferSize = 64 * blocksPerColumnForMcu *
|
var blocksBufferSize =
|
||||||
(blocksPerLineForMcu + 1);
|
64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
|
||||||
component.blockData = new Int16Array(blocksBufferSize);
|
component.blockData = new Int16Array(blocksBufferSize);
|
||||||
component.blocksPerLine = blocksPerLine;
|
component.blocksPerLine = blocksPerLine;
|
||||||
component.blocksPerColumn = blocksPerColumn;
|
component.blocksPerColumn = blocksPerColumn;
|
||||||
@ -706,56 +743,71 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
var frame, resetInterval;
|
var frame, resetInterval;
|
||||||
let numSOSMarkers = 0;
|
let numSOSMarkers = 0;
|
||||||
var quantizationTables = [];
|
var quantizationTables = [];
|
||||||
var huffmanTablesAC = [], huffmanTablesDC = [];
|
var huffmanTablesAC = [],
|
||||||
|
huffmanTablesDC = [];
|
||||||
var fileMarker = readUint16();
|
var fileMarker = readUint16();
|
||||||
if (fileMarker !== 0xFFD8) { // SOI (Start of Image)
|
if (fileMarker !== 0xffd8) {
|
||||||
throw new JpegError('SOI not found');
|
// SOI (Start of Image)
|
||||||
|
throw new JpegError("SOI not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
fileMarker = readUint16();
|
fileMarker = readUint16();
|
||||||
markerLoop: while (fileMarker !== 0xFFD9) { // EOI (End of image)
|
markerLoop: while (fileMarker !== 0xffd9) {
|
||||||
|
// EOI (End of image)
|
||||||
var i, j, l;
|
var i, j, l;
|
||||||
switch (fileMarker) {
|
switch (fileMarker) {
|
||||||
case 0xFFE0: // APP0 (Application Specific)
|
case 0xffe0: // APP0 (Application Specific)
|
||||||
case 0xFFE1: // APP1
|
case 0xffe1: // APP1
|
||||||
case 0xFFE2: // APP2
|
case 0xffe2: // APP2
|
||||||
case 0xFFE3: // APP3
|
case 0xffe3: // APP3
|
||||||
case 0xFFE4: // APP4
|
case 0xffe4: // APP4
|
||||||
case 0xFFE5: // APP5
|
case 0xffe5: // APP5
|
||||||
case 0xFFE6: // APP6
|
case 0xffe6: // APP6
|
||||||
case 0xFFE7: // APP7
|
case 0xffe7: // APP7
|
||||||
case 0xFFE8: // APP8
|
case 0xffe8: // APP8
|
||||||
case 0xFFE9: // APP9
|
case 0xffe9: // APP9
|
||||||
case 0xFFEA: // APP10
|
case 0xffea: // APP10
|
||||||
case 0xFFEB: // APP11
|
case 0xffeb: // APP11
|
||||||
case 0xFFEC: // APP12
|
case 0xffec: // APP12
|
||||||
case 0xFFED: // APP13
|
case 0xffed: // APP13
|
||||||
case 0xFFEE: // APP14
|
case 0xffee: // APP14
|
||||||
case 0xFFEF: // APP15
|
case 0xffef: // APP15
|
||||||
case 0xFFFE: // COM (Comment)
|
case 0xfffe: // COM (Comment)
|
||||||
var appData = readDataBlock();
|
var appData = readDataBlock();
|
||||||
|
|
||||||
if (fileMarker === 0xFFE0) {
|
if (fileMarker === 0xffe0) {
|
||||||
if (appData[0] === 0x4A && appData[1] === 0x46 &&
|
if (
|
||||||
appData[2] === 0x49 && appData[3] === 0x46 &&
|
appData[0] === 0x4a &&
|
||||||
appData[4] === 0) { // 'JFIF\x00'
|
appData[1] === 0x46 &&
|
||||||
|
appData[2] === 0x49 &&
|
||||||
|
appData[3] === 0x46 &&
|
||||||
|
appData[4] === 0
|
||||||
|
) {
|
||||||
|
// 'JFIF\x00'
|
||||||
jfif = {
|
jfif = {
|
||||||
version: { major: appData[5], minor: appData[6], },
|
version: { major: appData[5], minor: appData[6] },
|
||||||
densityUnits: appData[7],
|
densityUnits: appData[7],
|
||||||
xDensity: (appData[8] << 8) | appData[9],
|
xDensity: (appData[8] << 8) | appData[9],
|
||||||
yDensity: (appData[10] << 8) | appData[11],
|
yDensity: (appData[10] << 8) | appData[11],
|
||||||
thumbWidth: appData[12],
|
thumbWidth: appData[12],
|
||||||
thumbHeight: appData[13],
|
thumbHeight: appData[13],
|
||||||
thumbData: appData.subarray(14, 14 +
|
thumbData: appData.subarray(
|
||||||
3 * appData[12] * appData[13]),
|
14,
|
||||||
|
14 + 3 * appData[12] * appData[13]
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO APP1 - Exif
|
// TODO APP1 - Exif
|
||||||
if (fileMarker === 0xFFEE) {
|
if (fileMarker === 0xffee) {
|
||||||
if (appData[0] === 0x41 && appData[1] === 0x64 &&
|
if (
|
||||||
appData[2] === 0x6F && appData[3] === 0x62 &&
|
appData[0] === 0x41 &&
|
||||||
appData[4] === 0x65) { // 'Adobe'
|
appData[1] === 0x64 &&
|
||||||
|
appData[2] === 0x6f &&
|
||||||
|
appData[3] === 0x62 &&
|
||||||
|
appData[4] === 0x65
|
||||||
|
) {
|
||||||
|
// 'Adobe'
|
||||||
adobe = {
|
adobe = {
|
||||||
version: (appData[5] << 8) | appData[6],
|
version: (appData[5] << 8) | appData[6],
|
||||||
flags0: (appData[7] << 8) | appData[8],
|
flags0: (appData[7] << 8) | appData[8],
|
||||||
@ -766,48 +818,52 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFFDB: // DQT (Define Quantization Tables)
|
case 0xffdb: // DQT (Define Quantization Tables)
|
||||||
var quantizationTablesLength = readUint16();
|
var quantizationTablesLength = readUint16();
|
||||||
var quantizationTablesEnd = quantizationTablesLength + offset - 2;
|
var quantizationTablesEnd = quantizationTablesLength + offset - 2;
|
||||||
var z;
|
var z;
|
||||||
while (offset < quantizationTablesEnd) {
|
while (offset < quantizationTablesEnd) {
|
||||||
var quantizationTableSpec = data[offset++];
|
var quantizationTableSpec = data[offset++];
|
||||||
var tableData = new Uint16Array(64);
|
var tableData = new Uint16Array(64);
|
||||||
if ((quantizationTableSpec >> 4) === 0) { // 8 bit values
|
if (quantizationTableSpec >> 4 === 0) {
|
||||||
|
// 8 bit values
|
||||||
for (j = 0; j < 64; j++) {
|
for (j = 0; j < 64; j++) {
|
||||||
z = dctZigZag[j];
|
z = dctZigZag[j];
|
||||||
tableData[z] = data[offset++];
|
tableData[z] = data[offset++];
|
||||||
}
|
}
|
||||||
} else if ((quantizationTableSpec >> 4) === 1) { // 16 bit values
|
} else if (quantizationTableSpec >> 4 === 1) {
|
||||||
|
// 16 bit values
|
||||||
for (j = 0; j < 64; j++) {
|
for (j = 0; j < 64; j++) {
|
||||||
z = dctZigZag[j];
|
z = dctZigZag[j];
|
||||||
tableData[z] = readUint16();
|
tableData[z] = readUint16();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new JpegError('DQT - invalid table spec');
|
throw new JpegError("DQT - invalid table spec");
|
||||||
}
|
}
|
||||||
quantizationTables[quantizationTableSpec & 15] = tableData;
|
quantizationTables[quantizationTableSpec & 15] = tableData;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT)
|
case 0xffc0: // SOF0 (Start of Frame, Baseline DCT)
|
||||||
case 0xFFC1: // SOF1 (Start of Frame, Extended DCT)
|
case 0xffc1: // SOF1 (Start of Frame, Extended DCT)
|
||||||
case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT)
|
case 0xffc2: // SOF2 (Start of Frame, Progressive DCT)
|
||||||
if (frame) {
|
if (frame) {
|
||||||
throw new JpegError('Only single frame JPEGs supported');
|
throw new JpegError("Only single frame JPEGs supported");
|
||||||
}
|
}
|
||||||
readUint16(); // skip data length
|
readUint16(); // skip data length
|
||||||
frame = {};
|
frame = {};
|
||||||
frame.extended = (fileMarker === 0xFFC1);
|
frame.extended = fileMarker === 0xffc1;
|
||||||
frame.progressive = (fileMarker === 0xFFC2);
|
frame.progressive = fileMarker === 0xffc2;
|
||||||
frame.precision = data[offset++];
|
frame.precision = data[offset++];
|
||||||
const sofScanLines = readUint16();
|
const sofScanLines = readUint16();
|
||||||
frame.scanLines = dnlScanLines || sofScanLines;
|
frame.scanLines = dnlScanLines || sofScanLines;
|
||||||
frame.samplesPerLine = readUint16();
|
frame.samplesPerLine = readUint16();
|
||||||
frame.components = [];
|
frame.components = [];
|
||||||
frame.componentIds = {};
|
frame.componentIds = {};
|
||||||
var componentsCount = data[offset++], componentId;
|
var componentsCount = data[offset++],
|
||||||
var maxH = 0, maxV = 0;
|
componentId;
|
||||||
|
var maxH = 0,
|
||||||
|
maxV = 0;
|
||||||
for (i = 0; i < componentsCount; i++) {
|
for (i = 0; i < componentsCount; i++) {
|
||||||
componentId = data[offset];
|
componentId = data[offset];
|
||||||
var h = data[offset + 1] >> 4;
|
var h = data[offset + 1] >> 4;
|
||||||
@ -833,14 +889,14 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
prepareComponents(frame);
|
prepareComponents(frame);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFFC4: // DHT (Define Huffman Tables)
|
case 0xffc4: // DHT (Define Huffman Tables)
|
||||||
var huffmanLength = readUint16();
|
var huffmanLength = readUint16();
|
||||||
for (i = 2; i < huffmanLength; ) {
|
for (i = 2; i < huffmanLength; ) {
|
||||||
var huffmanTableSpec = data[offset++];
|
var huffmanTableSpec = data[offset++];
|
||||||
var codeLengths = new Uint8Array(16);
|
var codeLengths = new Uint8Array(16);
|
||||||
var codeLengthSum = 0;
|
var codeLengthSum = 0;
|
||||||
for (j = 0; j < 16; j++, offset++) {
|
for (j = 0; j < 16; j++, offset++) {
|
||||||
codeLengthSum += (codeLengths[j] = data[offset]);
|
codeLengthSum += codeLengths[j] = data[offset];
|
||||||
}
|
}
|
||||||
var huffmanValues = new Uint8Array(codeLengthSum);
|
var huffmanValues = new Uint8Array(codeLengthSum);
|
||||||
for (j = 0; j < codeLengthSum; j++, offset++) {
|
for (j = 0; j < codeLengthSum; j++, offset++) {
|
||||||
@ -848,27 +904,28 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
i += 17 + codeLengthSum;
|
i += 17 + codeLengthSum;
|
||||||
|
|
||||||
((huffmanTableSpec >> 4) === 0 ?
|
(huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[
|
||||||
huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] =
|
huffmanTableSpec & 15
|
||||||
buildHuffmanTable(codeLengths, huffmanValues);
|
] = buildHuffmanTable(codeLengths, huffmanValues);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFFDD: // DRI (Define Restart Interval)
|
case 0xffdd: // DRI (Define Restart Interval)
|
||||||
readUint16(); // skip data length
|
readUint16(); // skip data length
|
||||||
resetInterval = readUint16();
|
resetInterval = readUint16();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFFDA: // SOS (Start of Scan)
|
case 0xffda: // SOS (Start of Scan)
|
||||||
// A DNL marker (0xFFDC), if it exists, is only allowed at the end
|
// A DNL marker (0xFFDC), if it exists, is only allowed at the end
|
||||||
// of the first scan segment and may only occur once in an image.
|
// of the first scan segment and may only occur once in an image.
|
||||||
// Furthermore, to prevent an infinite loop, do *not* attempt to
|
// Furthermore, to prevent an infinite loop, do *not* attempt to
|
||||||
// parse DNL markers during re-parsing of the JPEG scan data.
|
// parse DNL markers during re-parsing of the JPEG scan data.
|
||||||
const parseDNLMarker = (++numSOSMarkers) === 1 && !dnlScanLines;
|
const parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines;
|
||||||
|
|
||||||
readUint16(); // scanLength
|
readUint16(); // scanLength
|
||||||
var selectorsCount = data[offset++];
|
var selectorsCount = data[offset++];
|
||||||
var components = [], component;
|
var components = [],
|
||||||
|
component;
|
||||||
for (i = 0; i < selectorsCount; i++) {
|
for (i = 0; i < selectorsCount; i++) {
|
||||||
var componentIndex = frame.componentIds[data[offset++]];
|
var componentIndex = frame.componentIds[data[offset++]];
|
||||||
component = frame.components[componentIndex];
|
component = frame.components[componentIndex];
|
||||||
@ -881,16 +938,23 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
var spectralEnd = data[offset++];
|
var spectralEnd = data[offset++];
|
||||||
var successiveApproximation = data[offset++];
|
var successiveApproximation = data[offset++];
|
||||||
try {
|
try {
|
||||||
var processed = decodeScan(data, offset,
|
var processed = decodeScan(
|
||||||
frame, components, resetInterval,
|
data,
|
||||||
spectralStart, spectralEnd,
|
offset,
|
||||||
successiveApproximation >> 4, successiveApproximation & 15,
|
frame,
|
||||||
parseDNLMarker);
|
components,
|
||||||
|
resetInterval,
|
||||||
|
spectralStart,
|
||||||
|
spectralEnd,
|
||||||
|
successiveApproximation >> 4,
|
||||||
|
successiveApproximation & 15,
|
||||||
|
parseDNLMarker
|
||||||
|
);
|
||||||
offset += processed;
|
offset += processed;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (ex instanceof DNLMarkerError) {
|
if (ex instanceof DNLMarkerError) {
|
||||||
warn(`${ex.message} -- attempting to re-parse the JPEG image.`);
|
warn(`${ex.message} -- attempting to re-parse the JPEG image.`);
|
||||||
return this.parse(data, { dnlScanLines: ex.scanLines, });
|
return this.parse(data, { dnlScanLines: ex.scanLines });
|
||||||
} else if (ex instanceof EOIMarkerError) {
|
} else if (ex instanceof EOIMarkerError) {
|
||||||
warn(`${ex.message} -- ignoring the rest of the image data.`);
|
warn(`${ex.message} -- ignoring the rest of the image data.`);
|
||||||
break markerLoop;
|
break markerLoop;
|
||||||
@ -899,20 +963,24 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFFDC: // DNL (Define Number of Lines)
|
case 0xffdc: // DNL (Define Number of Lines)
|
||||||
// Ignore the marker, since it's being handled in `decodeScan`.
|
// Ignore the marker, since it's being handled in `decodeScan`.
|
||||||
offset += 4;
|
offset += 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFFFF: // Fill bytes
|
case 0xffff: // Fill bytes
|
||||||
if (data[offset] !== 0xFF) { // Avoid skipping a valid marker.
|
if (data[offset] !== 0xff) {
|
||||||
|
// Avoid skipping a valid marker.
|
||||||
offset--;
|
offset--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (data[offset - 3] === 0xFF &&
|
if (
|
||||||
data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
|
data[offset - 3] === 0xff &&
|
||||||
|
data[offset - 2] >= 0xc0 &&
|
||||||
|
data[offset - 2] <= 0xfe
|
||||||
|
) {
|
||||||
// could be incorrect encoding -- last 0xFF byte of the previous
|
// could be incorrect encoding -- last 0xFF byte of the previous
|
||||||
// block was eaten by the encoder
|
// block was eaten by the encoder
|
||||||
offset -= 3;
|
offset -= 3;
|
||||||
@ -920,18 +988,23 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
let nextFileMarker = findNextFileMarker(data, offset - 2);
|
let nextFileMarker = findNextFileMarker(data, offset - 2);
|
||||||
if (nextFileMarker && nextFileMarker.invalid) {
|
if (nextFileMarker && nextFileMarker.invalid) {
|
||||||
warn('JpegImage.parse - unexpected data, current marker is: ' +
|
warn(
|
||||||
nextFileMarker.invalid);
|
"JpegImage.parse - unexpected data, current marker is: " +
|
||||||
|
nextFileMarker.invalid
|
||||||
|
);
|
||||||
offset = nextFileMarker.offset;
|
offset = nextFileMarker.offset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (offset > (data.length - 2)) {
|
if (offset > data.length - 2) {
|
||||||
warn('JpegImage.parse - reached the end of the image data ' +
|
warn(
|
||||||
'without finding an EOI marker (0xFFD9).');
|
"JpegImage.parse - reached the end of the image data " +
|
||||||
|
"without finding an EOI marker (0xFFD9)."
|
||||||
|
);
|
||||||
break markerLoop;
|
break markerLoop;
|
||||||
}
|
}
|
||||||
throw new JpegError('JpegImage.parse - unknown marker: ' +
|
throw new JpegError(
|
||||||
fileMarker.toString(16));
|
"JpegImage.parse - unknown marker: " + fileMarker.toString(16)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
fileMarker = readUint16();
|
fileMarker = readUint16();
|
||||||
}
|
}
|
||||||
@ -965,7 +1038,8 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
_getLinearizedBlockData(width, height, isSourcePDF = false) {
|
_getLinearizedBlockData(width, height, isSourcePDF = false) {
|
||||||
var scaleX = this.width / width, scaleY = this.height / height;
|
var scaleX = this.width / width,
|
||||||
|
scaleY = this.height / height;
|
||||||
|
|
||||||
var component, componentScaleX, componentScaleY, blocksPerScanline;
|
var component, componentScaleX, componentScaleY, blocksPerScanline;
|
||||||
var x, y, i, j, k;
|
var x, y, i, j, k;
|
||||||
@ -993,7 +1067,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
// linearize the blocks of the component
|
// linearize the blocks of the component
|
||||||
for (y = 0; y < height; y++) {
|
for (y = 0; y < height; y++) {
|
||||||
j = 0 | (y * componentScaleY);
|
j = 0 | (y * componentScaleY);
|
||||||
index = blocksPerScanline * (j & mask3LSB) | ((j & 7) << 3);
|
index = (blocksPerScanline * (j & mask3LSB)) | ((j & 7) << 3);
|
||||||
for (x = 0; x < width; x++) {
|
for (x = 0; x < width; x++) {
|
||||||
data[offset] = output[index + xScaleBlockOffset[x]];
|
data[offset] = output[index + xScaleBlockOffset[x]];
|
||||||
offset += numComponents;
|
offset += numComponents;
|
||||||
@ -1077,33 +1151,60 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
Cr = data[i + 2];
|
Cr = data[i + 2];
|
||||||
k = data[i + 3];
|
k = data[i + 3];
|
||||||
|
|
||||||
data[offset++] = -122.67195406894 +
|
data[offset++] =
|
||||||
Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr -
|
-122.67195406894 +
|
||||||
5.4080610064599e-5 * Y + 0.00048449797120281 * k -
|
Cb *
|
||||||
|
(-6.60635669420364e-5 * Cb +
|
||||||
|
0.000437130475926232 * Cr -
|
||||||
|
5.4080610064599e-5 * Y +
|
||||||
|
0.00048449797120281 * k -
|
||||||
0.154362151871126) +
|
0.154362151871126) +
|
||||||
Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y -
|
Cr *
|
||||||
0.00477271405408747 * k + 1.53380253221734) +
|
(-0.000957964378445773 * Cr +
|
||||||
Y * (0.000961250184130688 * Y - 0.00266257332283933 * k +
|
0.000817076911346625 * Y -
|
||||||
|
0.00477271405408747 * k +
|
||||||
|
1.53380253221734) +
|
||||||
|
Y *
|
||||||
|
(0.000961250184130688 * Y -
|
||||||
|
0.00266257332283933 * k +
|
||||||
0.48357088451265) +
|
0.48357088451265) +
|
||||||
k * (-0.000336197177618394 * k + 0.484791561490776);
|
k * (-0.000336197177618394 * k + 0.484791561490776);
|
||||||
|
|
||||||
data[offset++] = 107.268039397724 +
|
data[offset++] =
|
||||||
Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr +
|
107.268039397724 +
|
||||||
0.000659397001245577 * Y + 0.000426105652938837 * k -
|
Cb *
|
||||||
|
(2.19927104525741e-5 * Cb -
|
||||||
|
0.000640992018297945 * Cr +
|
||||||
|
0.000659397001245577 * Y +
|
||||||
|
0.000426105652938837 * k -
|
||||||
0.176491792462875) +
|
0.176491792462875) +
|
||||||
Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y +
|
Cr *
|
||||||
0.000770482631801132 * k - 0.151051492775562) +
|
(-0.000778269941513683 * Cr +
|
||||||
Y * (0.00126935368114843 * Y - 0.00265090189010898 * k +
|
0.00130872261408275 * Y +
|
||||||
|
0.000770482631801132 * k -
|
||||||
|
0.151051492775562) +
|
||||||
|
Y *
|
||||||
|
(0.00126935368114843 * Y -
|
||||||
|
0.00265090189010898 * k +
|
||||||
0.25802910206845) +
|
0.25802910206845) +
|
||||||
k * (-0.000318913117588328 * k - 0.213742400323665);
|
k * (-0.000318913117588328 * k - 0.213742400323665);
|
||||||
|
|
||||||
data[offset++] = -20.810012546947 +
|
data[offset++] =
|
||||||
Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr +
|
-20.810012546947 +
|
||||||
0.0020741088115012 * Y - 0.00288260236853442 * k +
|
Cb *
|
||||||
|
(-0.000570115196973677 * Cb -
|
||||||
|
2.63409051004589e-5 * Cr +
|
||||||
|
0.0020741088115012 * Y -
|
||||||
|
0.00288260236853442 * k +
|
||||||
0.814272968359295) +
|
0.814272968359295) +
|
||||||
Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y +
|
Cr *
|
||||||
0.000560833691242812 * k - 0.195152027534049) +
|
(-1.53496057440975e-5 * Cr -
|
||||||
Y * (0.00174418132927582 * Y - 0.00255243321439347 * k +
|
0.000132689043961446 * Y +
|
||||||
|
0.000560833691242812 * k -
|
||||||
|
0.195152027534049) +
|
||||||
|
Y *
|
||||||
|
(0.00174418132927582 * Y -
|
||||||
|
0.00255243321439347 * k +
|
||||||
0.116935020465145) +
|
0.116935020465145) +
|
||||||
k * (-0.000343531996510555 * k + 0.24165260232407);
|
k * (-0.000343531996510555 * k + 0.24165260232407);
|
||||||
}
|
}
|
||||||
@ -1135,33 +1236,58 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
y = data[i + 2] * scale;
|
y = data[i + 2] * scale;
|
||||||
k = data[i + 3] * scale;
|
k = data[i + 3] * scale;
|
||||||
|
|
||||||
data[offset++] = 255 +
|
data[offset++] =
|
||||||
c * (-4.387332384609988 * c + 54.48615194189176 * m +
|
255 +
|
||||||
18.82290502165302 * y + 212.25662451639585 * k -
|
c *
|
||||||
|
(-4.387332384609988 * c +
|
||||||
|
54.48615194189176 * m +
|
||||||
|
18.82290502165302 * y +
|
||||||
|
212.25662451639585 * k -
|
||||||
285.2331026137004) +
|
285.2331026137004) +
|
||||||
m * (1.7149763477362134 * m - 5.6096736904047315 * y -
|
m *
|
||||||
17.873870861415444 * k - 5.497006427196366) +
|
(1.7149763477362134 * m -
|
||||||
y * (-2.5217340131683033 * y - 21.248923337353073 * k +
|
5.6096736904047315 * y -
|
||||||
|
17.873870861415444 * k -
|
||||||
|
5.497006427196366) +
|
||||||
|
y *
|
||||||
|
(-2.5217340131683033 * y -
|
||||||
|
21.248923337353073 * k +
|
||||||
17.5119270841813) -
|
17.5119270841813) -
|
||||||
k * (21.86122147463605 * k + 189.48180835922747);
|
k * (21.86122147463605 * k + 189.48180835922747);
|
||||||
|
|
||||||
data[offset++] = 255 +
|
data[offset++] =
|
||||||
c * (8.841041422036149 * c + 60.118027045597366 * m +
|
255 +
|
||||||
6.871425592049007 * y + 31.159100130055922 * k -
|
c *
|
||||||
|
(8.841041422036149 * c +
|
||||||
|
60.118027045597366 * m +
|
||||||
|
6.871425592049007 * y +
|
||||||
|
31.159100130055922 * k -
|
||||||
79.2970844816548) +
|
79.2970844816548) +
|
||||||
m * (-15.310361306967817 * m + 17.575251261109482 * y +
|
m *
|
||||||
131.35250912493976 * k - 190.9453302588951) +
|
(-15.310361306967817 * m +
|
||||||
y * (4.444339102852739 * y + 9.8632861493405 * k -
|
17.575251261109482 * y +
|
||||||
24.86741582555878) -
|
131.35250912493976 * k -
|
||||||
|
190.9453302588951) +
|
||||||
|
y *
|
||||||
|
(4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) -
|
||||||
k * (20.737325471181034 * k + 187.80453709719578);
|
k * (20.737325471181034 * k + 187.80453709719578);
|
||||||
|
|
||||||
data[offset++] = 255 +
|
data[offset++] =
|
||||||
c * (0.8842522430003296 * c + 8.078677503112928 * m +
|
255 +
|
||||||
30.89978309703729 * y - 0.23883238689178934 * k -
|
c *
|
||||||
|
(0.8842522430003296 * c +
|
||||||
|
8.078677503112928 * m +
|
||||||
|
30.89978309703729 * y -
|
||||||
|
0.23883238689178934 * k -
|
||||||
14.183576799673286) +
|
14.183576799673286) +
|
||||||
m * (10.49593273432072 * m + 63.02378494754052 * y +
|
m *
|
||||||
50.606957656360734 * k - 112.23884253719248) +
|
(10.49593273432072 * m +
|
||||||
y * (0.03296041114873217 * y + 115.60384449646641 * k -
|
63.02378494754052 * y +
|
||||||
|
50.606957656360734 * k -
|
||||||
|
112.23884253719248) +
|
||||||
|
y *
|
||||||
|
(0.03296041114873217 * y +
|
||||||
|
115.60384449646641 * k -
|
||||||
193.58209356861505) -
|
193.58209356861505) -
|
||||||
k * (22.33816807309886 * k + 180.12613974708367);
|
k * (22.33816807309886 * k + 180.12613974708367);
|
||||||
}
|
}
|
||||||
@ -1169,13 +1295,15 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
return data.subarray(0, offset);
|
return data.subarray(0, offset);
|
||||||
},
|
},
|
||||||
|
|
||||||
getData({ width, height, forceRGB = false, isSourcePDF = false, }) {
|
getData({ width, height, forceRGB = false, isSourcePDF = false }) {
|
||||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('TESTING && !LIB')) {
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING && !LIB")) {
|
||||||
assert(isSourcePDF === true,
|
assert(
|
||||||
'JpegImage.getData: Unexpected "isSourcePDF" value for PDF files.');
|
isSourcePDF === true,
|
||||||
|
'JpegImage.getData: Unexpected "isSourcePDF" value for PDF files.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (this.numComponents > 4) {
|
if (this.numComponents > 4) {
|
||||||
throw new JpegError('Unsupported color mode');
|
throw new JpegError("Unsupported color mode");
|
||||||
}
|
}
|
||||||
// Type of data: Uint8ClampedArray(width * height * numComponents)
|
// Type of data: Uint8ClampedArray(width * height * numComponents)
|
||||||
var data = this._getLinearizedBlockData(width, height, isSourcePDF);
|
var data = this._getLinearizedBlockData(width, height, isSourcePDF);
|
||||||
@ -1210,6 +1338,4 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
return JpegImage;
|
return JpegImage;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { JpegImage };
|
||||||
JpegImage,
|
|
||||||
};
|
|
||||||
|
605
src/core/jpx.js
605
src/core/jpx.js
File diff suppressed because it is too large
Load Diff
@ -13,9 +13,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { DecodeStream } from './stream';
|
import { DecodeStream } from "./stream";
|
||||||
import { JpxImage } from './jpx';
|
import { JpxImage } from "./jpx";
|
||||||
import { shadow } from '../shared/util';
|
import { shadow } from "../shared/util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For JPEG 2000's we use a library to decode these images and
|
* For JPEG 2000's we use a library to decode these images and
|
||||||
@ -33,10 +33,10 @@ let JpxStream = (function JpxStreamClosure() {
|
|||||||
|
|
||||||
JpxStream.prototype = Object.create(DecodeStream.prototype);
|
JpxStream.prototype = Object.create(DecodeStream.prototype);
|
||||||
|
|
||||||
Object.defineProperty(JpxStream.prototype, 'bytes', {
|
Object.defineProperty(JpxStream.prototype, "bytes", {
|
||||||
get: function JpxStream_bytes() {
|
get: function JpxStream_bytes() {
|
||||||
// If `this.maybeLength` is null, we'll get the entire stream.
|
// If `this.maybeLength` is null, we'll get the entire stream.
|
||||||
return shadow(this, 'bytes', this.stream.getBytes(this.maybeLength));
|
return shadow(this, "bytes", this.stream.getBytes(this.maybeLength));
|
||||||
},
|
},
|
||||||
configurable: true,
|
configurable: true,
|
||||||
});
|
});
|
||||||
@ -91,6 +91,4 @@ let JpxStream = (function JpxStreamClosure() {
|
|||||||
return JpxStream;
|
return JpxStream;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { JpxStream };
|
||||||
JpxStream,
|
|
||||||
};
|
|
||||||
|
5858
src/core/metrics.js
5858
src/core/metrics.js
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import { isArrayBuffer, isString } from '../shared/util';
|
import { isArrayBuffer, isString } from "../shared/util";
|
||||||
|
|
||||||
const SEED = 0xc3d2e1f0;
|
const SEED = 0xc3d2e1f0;
|
||||||
// Workaround for missing math precision in JS.
|
// Workaround for missing math precision in JS.
|
||||||
@ -49,35 +49,41 @@ class MurmurHash3_64 {
|
|||||||
data = input;
|
data = input;
|
||||||
length = data.byteLength;
|
length = data.byteLength;
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Wrong data format in MurmurHash3_64_update. ' +
|
throw new Error(
|
||||||
'Input must be a string or array.');
|
"Wrong data format in MurmurHash3_64_update. " +
|
||||||
|
"Input must be a string or array."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const blockCounts = length >> 2;
|
const blockCounts = length >> 2;
|
||||||
const tailLength = length - blockCounts * 4;
|
const tailLength = length - blockCounts * 4;
|
||||||
// We don't care about endianness here.
|
// We don't care about endianness here.
|
||||||
const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
|
const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
|
||||||
let k1 = 0, k2 = 0;
|
let k1 = 0,
|
||||||
let h1 = this.h1, h2 = this.h2;
|
k2 = 0;
|
||||||
const C1 = 0xcc9e2d51, C2 = 0x1b873593;
|
let h1 = this.h1,
|
||||||
const C1_LOW = C1 & MASK_LOW, C2_LOW = C2 & MASK_LOW;
|
h2 = this.h2;
|
||||||
|
const C1 = 0xcc9e2d51,
|
||||||
|
C2 = 0x1b873593;
|
||||||
|
const C1_LOW = C1 & MASK_LOW,
|
||||||
|
C2_LOW = C2 & MASK_LOW;
|
||||||
|
|
||||||
for (let i = 0; i < blockCounts; i++) {
|
for (let i = 0; i < blockCounts; i++) {
|
||||||
if (i & 1) {
|
if (i & 1) {
|
||||||
k1 = dataUint32[i];
|
k1 = dataUint32[i];
|
||||||
k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW);
|
k1 = ((k1 * C1) & MASK_HIGH) | ((k1 * C1_LOW) & MASK_LOW);
|
||||||
k1 = k1 << 15 | k1 >>> 17;
|
k1 = (k1 << 15) | (k1 >>> 17);
|
||||||
k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW);
|
k1 = ((k1 * C2) & MASK_HIGH) | ((k1 * C2_LOW) & MASK_LOW);
|
||||||
h1 ^= k1;
|
h1 ^= k1;
|
||||||
h1 = h1 << 13 | h1 >>> 19;
|
h1 = (h1 << 13) | (h1 >>> 19);
|
||||||
h1 = h1 * 5 + 0xe6546b64;
|
h1 = h1 * 5 + 0xe6546b64;
|
||||||
} else {
|
} else {
|
||||||
k2 = dataUint32[i];
|
k2 = dataUint32[i];
|
||||||
k2 = (k2 * C1 & MASK_HIGH) | (k2 * C1_LOW & MASK_LOW);
|
k2 = ((k2 * C1) & MASK_HIGH) | ((k2 * C1_LOW) & MASK_LOW);
|
||||||
k2 = k2 << 15 | k2 >>> 17;
|
k2 = (k2 << 15) | (k2 >>> 17);
|
||||||
k2 = (k2 * C2 & MASK_HIGH) | (k2 * C2_LOW & MASK_LOW);
|
k2 = ((k2 * C2) & MASK_HIGH) | ((k2 * C2_LOW) & MASK_LOW);
|
||||||
h2 ^= k2;
|
h2 ^= k2;
|
||||||
h2 = h2 << 13 | h2 >>> 19;
|
h2 = (h2 << 13) | (h2 >>> 19);
|
||||||
h2 = h2 * 5 + 0xe6546b64;
|
h2 = h2 * 5 + 0xe6546b64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,9 +101,9 @@ class MurmurHash3_64 {
|
|||||||
k1 ^= data[blockCounts * 4];
|
k1 ^= data[blockCounts * 4];
|
||||||
/* falls through */
|
/* falls through */
|
||||||
|
|
||||||
k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW);
|
k1 = ((k1 * C1) & MASK_HIGH) | ((k1 * C1_LOW) & MASK_LOW);
|
||||||
k1 = k1 << 15 | k1 >>> 17;
|
k1 = (k1 << 15) | (k1 >>> 17);
|
||||||
k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW);
|
k1 = ((k1 * C2) & MASK_HIGH) | ((k1 * C2_LOW) & MASK_LOW);
|
||||||
if (blockCounts & 1) {
|
if (blockCounts & 1) {
|
||||||
h1 ^= k1;
|
h1 ^= k1;
|
||||||
} else {
|
} else {
|
||||||
@ -110,23 +116,25 @@ class MurmurHash3_64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hexdigest() {
|
hexdigest() {
|
||||||
let h1 = this.h1, h2 = this.h2;
|
let h1 = this.h1,
|
||||||
|
h2 = this.h2;
|
||||||
|
|
||||||
h1 ^= h2 >>> 1;
|
h1 ^= h2 >>> 1;
|
||||||
h1 = (h1 * 0xed558ccd & MASK_HIGH) | (h1 * 0x8ccd & MASK_LOW);
|
h1 = ((h1 * 0xed558ccd) & MASK_HIGH) | ((h1 * 0x8ccd) & MASK_LOW);
|
||||||
h2 = (h2 * 0xff51afd7 & MASK_HIGH) |
|
h2 =
|
||||||
(((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16);
|
((h2 * 0xff51afd7) & MASK_HIGH) |
|
||||||
|
(((((h2 << 16) | (h1 >>> 16)) * 0xafd7ed55) & MASK_HIGH) >>> 16);
|
||||||
h1 ^= h2 >>> 1;
|
h1 ^= h2 >>> 1;
|
||||||
h1 = (h1 * 0x1a85ec53 & MASK_HIGH) | (h1 * 0xec53 & MASK_LOW);
|
h1 = ((h1 * 0x1a85ec53) & MASK_HIGH) | ((h1 * 0xec53) & MASK_LOW);
|
||||||
h2 = (h2 * 0xc4ceb9fe & MASK_HIGH) |
|
h2 =
|
||||||
(((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16);
|
((h2 * 0xc4ceb9fe) & MASK_HIGH) |
|
||||||
|
(((((h2 << 16) | (h1 >>> 16)) * 0xb9fe1a85) & MASK_HIGH) >>> 16);
|
||||||
h1 ^= h2 >>> 1;
|
h1 ^= h2 >>> 1;
|
||||||
|
|
||||||
const hex1 = (h1 >>> 0).toString(16), hex2 = (h2 >>> 0).toString(16);
|
const hex1 = (h1 >>> 0).toString(16),
|
||||||
return hex1.padStart(8, '0') + hex2.padStart(8, '0');
|
hex2 = (h2 >>> 0).toString(16);
|
||||||
|
return hex1.padStart(8, "0") + hex2.padStart(8, "0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { MurmurHash3_64 };
|
||||||
MurmurHash3_64,
|
|
||||||
};
|
|
||||||
|
912
src/core/obj.js
912
src/core/obj.js
File diff suppressed because it is too large
Load Diff
@ -14,14 +14,14 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint-disable no-unsanitized/method */
|
/* eslint-disable no-unsanitized/method */
|
||||||
|
|
||||||
import { assert, ImageKind, OPS } from '../shared/util';
|
import { assert, ImageKind, OPS } from "../shared/util";
|
||||||
|
|
||||||
var QueueOptimizer = (function QueueOptimizerClosure() {
|
var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||||
function addState(parentState, pattern, checkFn, iterateFn, processFn) {
|
function addState(parentState, pattern, checkFn, iterateFn, processFn) {
|
||||||
var state = parentState;
|
var state = parentState;
|
||||||
for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
|
for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
|
||||||
var item = pattern[i];
|
var item = pattern[i];
|
||||||
state = (state[item] || (state[item] = []));
|
state = state[item] || (state[item] = []);
|
||||||
}
|
}
|
||||||
state[pattern[pattern.length - 1]] = {
|
state[pattern[pattern.length - 1]] = {
|
||||||
checkFn,
|
checkFn,
|
||||||
@ -30,8 +30,12 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePaintSolidColorImageMask(iFirstSave, count, fnArray,
|
function handlePaintSolidColorImageMask(
|
||||||
argsArray) {
|
iFirstSave,
|
||||||
|
count,
|
||||||
|
fnArray,
|
||||||
|
argsArray
|
||||||
|
) {
|
||||||
// Handles special case of mainly LaTeX documents which use image masks to
|
// Handles special case of mainly LaTeX documents which use image masks to
|
||||||
// draw lines with the current fill style.
|
// draw lines with the current fill style.
|
||||||
// 'count' groups of (save, transform, paintImageMaskXObject, restore)+
|
// 'count' groups of (save, transform, paintImageMaskXObject, restore)+
|
||||||
@ -40,9 +44,13 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
for (var i = 0; i < count; i++) {
|
for (var i = 0; i < count; i++) {
|
||||||
var arg = argsArray[iFirstPIMXO + 4 * i];
|
var arg = argsArray[iFirstPIMXO + 4 * i];
|
||||||
var imageMask = arg.length === 1 && arg[0];
|
var imageMask = arg.length === 1 && arg[0];
|
||||||
if (imageMask && imageMask.width === 1 && imageMask.height === 1 &&
|
if (
|
||||||
|
imageMask &&
|
||||||
|
imageMask.width === 1 &&
|
||||||
|
imageMask.height === 1 &&
|
||||||
(!imageMask.data.length ||
|
(!imageMask.data.length ||
|
||||||
(imageMask.data.length === 1 && imageMask.data[0] === 0))) {
|
(imageMask.data.length === 1 && imageMask.data[0] === 0))
|
||||||
|
) {
|
||||||
fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask;
|
fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -55,7 +63,8 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
|
|
||||||
// This replaces (save, transform, paintInlineImageXObject, restore)+
|
// This replaces (save, transform, paintInlineImageXObject, restore)+
|
||||||
// sequences with one |paintInlineImageXObjectGroup| operation.
|
// sequences with one |paintInlineImageXObjectGroup| operation.
|
||||||
addState(InitialState,
|
addState(
|
||||||
|
InitialState,
|
||||||
[OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore],
|
[OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore],
|
||||||
null,
|
null,
|
||||||
function iterateInlineImageGroup(context, i) {
|
function iterateInlineImageGroup(context, i) {
|
||||||
@ -80,23 +89,28 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
var MAX_WIDTH = 1000;
|
var MAX_WIDTH = 1000;
|
||||||
var IMAGE_PADDING = 1;
|
var IMAGE_PADDING = 1;
|
||||||
|
|
||||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
var fnArray = context.fnArray,
|
||||||
|
argsArray = context.argsArray;
|
||||||
var curr = context.iCurr;
|
var curr = context.iCurr;
|
||||||
var iFirstSave = curr - 3;
|
var iFirstSave = curr - 3;
|
||||||
var iFirstTransform = curr - 2;
|
var iFirstTransform = curr - 2;
|
||||||
var iFirstPIIXO = curr - 1;
|
var iFirstPIIXO = curr - 1;
|
||||||
|
|
||||||
var count = Math.min(Math.floor((i - iFirstSave) / 4),
|
var count = Math.min(
|
||||||
MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
|
Math.floor((i - iFirstSave) / 4),
|
||||||
|
MAX_IMAGES_IN_INLINE_IMAGES_BLOCK
|
||||||
|
);
|
||||||
if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
|
if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
|
||||||
return i - (i - iFirstSave) % 4;
|
return i - ((i - iFirstSave) % 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// assuming that heights of those image is too small (~1 pixel)
|
// assuming that heights of those image is too small (~1 pixel)
|
||||||
// packing as much as possible by lines
|
// packing as much as possible by lines
|
||||||
var maxX = 0;
|
var maxX = 0;
|
||||||
var map = [], maxLineHeight = 0;
|
var map = [],
|
||||||
var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING;
|
maxLineHeight = 0;
|
||||||
|
var currentX = IMAGE_PADDING,
|
||||||
|
currentY = IMAGE_PADDING;
|
||||||
var q;
|
var q;
|
||||||
for (q = 0; q < count; q++) {
|
for (q = 0; q < count; q++) {
|
||||||
var transform = argsArray[iFirstTransform + (q << 2)];
|
var transform = argsArray[iFirstTransform + (q << 2)];
|
||||||
@ -110,8 +124,10 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
}
|
}
|
||||||
map.push({
|
map.push({
|
||||||
transform,
|
transform,
|
||||||
x: currentX, y: currentY,
|
x: currentX,
|
||||||
w: img.width, h: img.height,
|
y: currentY,
|
||||||
|
w: img.width,
|
||||||
|
h: img.height,
|
||||||
});
|
});
|
||||||
currentX += img.width + 2 * IMAGE_PADDING;
|
currentX += img.width + 2 * IMAGE_PADDING;
|
||||||
maxLineHeight = Math.max(maxLineHeight, img.height);
|
maxLineHeight = Math.max(maxLineHeight, img.height);
|
||||||
@ -148,17 +164,25 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
|
|
||||||
// Replace queue items.
|
// Replace queue items.
|
||||||
fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup);
|
fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup);
|
||||||
argsArray.splice(iFirstSave, count * 4,
|
argsArray.splice(iFirstSave, count * 4, [
|
||||||
[{ width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP,
|
{
|
||||||
data: imgData, }, map]);
|
width: imgWidth,
|
||||||
|
height: imgHeight,
|
||||||
|
kind: ImageKind.RGBA_32BPP,
|
||||||
|
data: imgData,
|
||||||
|
},
|
||||||
|
map,
|
||||||
|
]);
|
||||||
|
|
||||||
return iFirstSave + 1;
|
return iFirstSave + 1;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// This replaces (save, transform, paintImageMaskXObject, restore)+
|
// This replaces (save, transform, paintImageMaskXObject, restore)+
|
||||||
// sequences with one |paintImageMaskXObjectGroup| or one
|
// sequences with one |paintImageMaskXObjectGroup| or one
|
||||||
// |paintImageMaskXObjectRepeat| operation.
|
// |paintImageMaskXObjectRepeat| operation.
|
||||||
addState(InitialState,
|
addState(
|
||||||
|
InitialState,
|
||||||
[OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore],
|
[OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore],
|
||||||
null,
|
null,
|
||||||
function iterateImageMaskGroup(context, i) {
|
function iterateImageMaskGroup(context, i) {
|
||||||
@ -182,7 +206,8 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
var MAX_IMAGES_IN_MASKS_BLOCK = 100;
|
var MAX_IMAGES_IN_MASKS_BLOCK = 100;
|
||||||
var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
|
var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
|
||||||
|
|
||||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
var fnArray = context.fnArray,
|
||||||
|
argsArray = context.argsArray;
|
||||||
var curr = context.iCurr;
|
var curr = context.iCurr;
|
||||||
var iFirstSave = curr - 3;
|
var iFirstSave = curr - 3;
|
||||||
var iFirstTransform = curr - 2;
|
var iFirstTransform = curr - 2;
|
||||||
@ -191,18 +216,24 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
// At this point, i is the index of the first op past the last valid
|
// At this point, i is the index of the first op past the last valid
|
||||||
// quartet.
|
// quartet.
|
||||||
var count = Math.floor((i - iFirstSave) / 4);
|
var count = Math.floor((i - iFirstSave) / 4);
|
||||||
count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray,
|
count = handlePaintSolidColorImageMask(
|
||||||
argsArray);
|
iFirstSave,
|
||||||
|
count,
|
||||||
|
fnArray,
|
||||||
|
argsArray
|
||||||
|
);
|
||||||
if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
|
if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
|
||||||
return i - (i - iFirstSave) % 4;
|
return i - ((i - iFirstSave) % 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
var q;
|
var q;
|
||||||
var isSameImage = false;
|
var isSameImage = false;
|
||||||
var iTransform, transformArgs;
|
var iTransform, transformArgs;
|
||||||
var firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
|
var firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
|
||||||
if (argsArray[iFirstTransform][1] === 0 &&
|
if (
|
||||||
argsArray[iFirstTransform][2] === 0) {
|
argsArray[iFirstTransform][1] === 0 &&
|
||||||
|
argsArray[iFirstTransform][2] === 0
|
||||||
|
) {
|
||||||
isSameImage = true;
|
isSameImage = true;
|
||||||
var firstTransformArg0 = argsArray[iFirstTransform][0];
|
var firstTransformArg0 = argsArray[iFirstTransform][0];
|
||||||
var firstTransformArg3 = argsArray[iFirstTransform][3];
|
var firstTransformArg3 = argsArray[iFirstTransform][3];
|
||||||
@ -210,11 +241,13 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
var iPIMXO = iFirstPIMXO + 4;
|
var iPIMXO = iFirstPIMXO + 4;
|
||||||
for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
|
for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
|
||||||
transformArgs = argsArray[iTransform];
|
transformArgs = argsArray[iTransform];
|
||||||
if (argsArray[iPIMXO][0] !== firstPIMXOArg0 ||
|
if (
|
||||||
|
argsArray[iPIMXO][0] !== firstPIMXOArg0 ||
|
||||||
transformArgs[0] !== firstTransformArg0 ||
|
transformArgs[0] !== firstTransformArg0 ||
|
||||||
transformArgs[1] !== 0 ||
|
transformArgs[1] !== 0 ||
|
||||||
transformArgs[2] !== 0 ||
|
transformArgs[2] !== 0 ||
|
||||||
transformArgs[3] !== firstTransformArg3) {
|
transformArgs[3] !== firstTransformArg3
|
||||||
|
) {
|
||||||
if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
|
if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
|
||||||
isSameImage = false;
|
isSameImage = false;
|
||||||
} else {
|
} else {
|
||||||
@ -231,23 +264,30 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
iTransform = iFirstTransform;
|
iTransform = iFirstTransform;
|
||||||
for (q = 0; q < count; q++, iTransform += 4) {
|
for (q = 0; q < count; q++, iTransform += 4) {
|
||||||
transformArgs = argsArray[iTransform];
|
transformArgs = argsArray[iTransform];
|
||||||
positions[(q << 1)] = transformArgs[4];
|
positions[q << 1] = transformArgs[4];
|
||||||
positions[(q << 1) + 1] = transformArgs[5];
|
positions[(q << 1) + 1] = transformArgs[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace queue items.
|
// Replace queue items.
|
||||||
fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat);
|
fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat);
|
||||||
argsArray.splice(iFirstSave, count * 4,
|
argsArray.splice(iFirstSave, count * 4, [
|
||||||
[firstPIMXOArg0, firstTransformArg0, firstTransformArg3, positions]);
|
firstPIMXOArg0,
|
||||||
|
firstTransformArg0,
|
||||||
|
firstTransformArg3,
|
||||||
|
positions,
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
|
count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
|
||||||
var images = [];
|
var images = [];
|
||||||
for (q = 0; q < count; q++) {
|
for (q = 0; q < count; q++) {
|
||||||
transformArgs = argsArray[iFirstTransform + (q << 2)];
|
transformArgs = argsArray[iFirstTransform + (q << 2)];
|
||||||
var maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
|
var maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
|
||||||
images.push({ data: maskParams.data, width: maskParams.width,
|
images.push({
|
||||||
|
data: maskParams.data,
|
||||||
|
width: maskParams.width,
|
||||||
height: maskParams.height,
|
height: maskParams.height,
|
||||||
transform: transformArgs, });
|
transform: transformArgs,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace queue items.
|
// Replace queue items.
|
||||||
@ -256,21 +296,26 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return iFirstSave + 1;
|
return iFirstSave + 1;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// This replaces (save, transform, paintImageXObject, restore)+ sequences
|
// This replaces (save, transform, paintImageXObject, restore)+ sequences
|
||||||
// with one paintImageXObjectRepeat operation, if the |transform| and
|
// with one paintImageXObjectRepeat operation, if the |transform| and
|
||||||
// |paintImageXObjectRepeat| ops are appropriate.
|
// |paintImageXObjectRepeat| ops are appropriate.
|
||||||
addState(InitialState,
|
addState(
|
||||||
|
InitialState,
|
||||||
[OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore],
|
[OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore],
|
||||||
function(context) {
|
function(context) {
|
||||||
var argsArray = context.argsArray;
|
var argsArray = context.argsArray;
|
||||||
var iFirstTransform = context.iCurr - 2;
|
var iFirstTransform = context.iCurr - 2;
|
||||||
return argsArray[iFirstTransform][1] === 0 &&
|
return (
|
||||||
argsArray[iFirstTransform][2] === 0;
|
argsArray[iFirstTransform][1] === 0 &&
|
||||||
|
argsArray[iFirstTransform][2] === 0
|
||||||
|
);
|
||||||
},
|
},
|
||||||
function iterateImageGroup(context, i) {
|
function iterateImageGroup(context, i) {
|
||||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
var fnArray = context.fnArray,
|
||||||
|
argsArray = context.argsArray;
|
||||||
var iFirstSave = context.iCurr - 3;
|
var iFirstSave = context.iCurr - 3;
|
||||||
var pos = (i - iFirstSave) % 4;
|
var pos = (i - iFirstSave) % 4;
|
||||||
switch (pos) {
|
switch (pos) {
|
||||||
@ -283,10 +328,12 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
var iFirstTransform = context.iCurr - 2;
|
var iFirstTransform = context.iCurr - 2;
|
||||||
var firstTransformArg0 = argsArray[iFirstTransform][0];
|
var firstTransformArg0 = argsArray[iFirstTransform][0];
|
||||||
var firstTransformArg3 = argsArray[iFirstTransform][3];
|
var firstTransformArg3 = argsArray[iFirstTransform][3];
|
||||||
if (argsArray[i][0] !== firstTransformArg0 ||
|
if (
|
||||||
|
argsArray[i][0] !== firstTransformArg0 ||
|
||||||
argsArray[i][1] !== 0 ||
|
argsArray[i][1] !== 0 ||
|
||||||
argsArray[i][2] !== 0 ||
|
argsArray[i][2] !== 0 ||
|
||||||
argsArray[i][3] !== firstTransformArg3) {
|
argsArray[i][3] !== firstTransformArg3
|
||||||
|
) {
|
||||||
return false; // transforms don't match
|
return false; // transforms don't match
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -309,7 +356,8 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
var MIN_IMAGES_IN_BLOCK = 3;
|
var MIN_IMAGES_IN_BLOCK = 3;
|
||||||
var MAX_IMAGES_IN_BLOCK = 1000;
|
var MAX_IMAGES_IN_BLOCK = 1000;
|
||||||
|
|
||||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
var fnArray = context.fnArray,
|
||||||
|
argsArray = context.argsArray;
|
||||||
var curr = context.iCurr;
|
var curr = context.iCurr;
|
||||||
var iFirstSave = curr - 3;
|
var iFirstSave = curr - 3;
|
||||||
var iFirstTransform = curr - 2;
|
var iFirstTransform = curr - 2;
|
||||||
@ -320,10 +368,12 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
|
|
||||||
// At this point, i is the index of the first op past the last valid
|
// At this point, i is the index of the first op past the last valid
|
||||||
// quartet.
|
// quartet.
|
||||||
var count = Math.min(Math.floor((i - iFirstSave) / 4),
|
var count = Math.min(
|
||||||
MAX_IMAGES_IN_BLOCK);
|
Math.floor((i - iFirstSave) / 4),
|
||||||
|
MAX_IMAGES_IN_BLOCK
|
||||||
|
);
|
||||||
if (count < MIN_IMAGES_IN_BLOCK) {
|
if (count < MIN_IMAGES_IN_BLOCK) {
|
||||||
return i - (i - iFirstSave) % 4;
|
return i - ((i - iFirstSave) % 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the (x,y) positions from all of the matching transforms.
|
// Extract the (x,y) positions from all of the matching transforms.
|
||||||
@ -331,27 +381,34 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
var iTransform = iFirstTransform;
|
var iTransform = iFirstTransform;
|
||||||
for (var q = 0; q < count; q++, iTransform += 4) {
|
for (var q = 0; q < count; q++, iTransform += 4) {
|
||||||
var transformArgs = argsArray[iTransform];
|
var transformArgs = argsArray[iTransform];
|
||||||
positions[(q << 1)] = transformArgs[4];
|
positions[q << 1] = transformArgs[4];
|
||||||
positions[(q << 1) + 1] = transformArgs[5];
|
positions[(q << 1) + 1] = transformArgs[5];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace queue items.
|
// Replace queue items.
|
||||||
var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3,
|
var args = [
|
||||||
positions];
|
firstPIXOArg0,
|
||||||
|
firstTransformArg0,
|
||||||
|
firstTransformArg3,
|
||||||
|
positions,
|
||||||
|
];
|
||||||
fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat);
|
fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat);
|
||||||
argsArray.splice(iFirstSave, count * 4, args);
|
argsArray.splice(iFirstSave, count * 4, args);
|
||||||
|
|
||||||
return iFirstSave + 1;
|
return iFirstSave + 1;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// This replaces (beginText, setFont, setTextMatrix, showText, endText)+
|
// This replaces (beginText, setFont, setTextMatrix, showText, endText)+
|
||||||
// sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+
|
// sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+
|
||||||
// sequences, if the font for each one is the same.
|
// sequences, if the font for each one is the same.
|
||||||
addState(InitialState,
|
addState(
|
||||||
|
InitialState,
|
||||||
[OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText],
|
[OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText],
|
||||||
null,
|
null,
|
||||||
function iterateShowTextGroup(context, i) {
|
function iterateShowTextGroup(context, i) {
|
||||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
var fnArray = context.fnArray,
|
||||||
|
argsArray = context.argsArray;
|
||||||
var iFirstSave = context.iCurr - 4;
|
var iFirstSave = context.iCurr - 4;
|
||||||
var pos = (i - iFirstSave) % 5;
|
var pos = (i - iFirstSave) % 5;
|
||||||
switch (pos) {
|
switch (pos) {
|
||||||
@ -368,8 +425,10 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
var iFirstSetFont = context.iCurr - 3;
|
var iFirstSetFont = context.iCurr - 3;
|
||||||
var firstSetFontArg0 = argsArray[iFirstSetFont][0];
|
var firstSetFontArg0 = argsArray[iFirstSetFont][0];
|
||||||
var firstSetFontArg1 = argsArray[iFirstSetFont][1];
|
var firstSetFontArg1 = argsArray[iFirstSetFont][1];
|
||||||
if (argsArray[i][0] !== firstSetFontArg0 ||
|
if (
|
||||||
argsArray[i][1] !== firstSetFontArg1) {
|
argsArray[i][0] !== firstSetFontArg0 ||
|
||||||
|
argsArray[i][1] !== firstSetFontArg1
|
||||||
|
) {
|
||||||
return false; // fonts don't match
|
return false; // fonts don't match
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -382,7 +441,8 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
var MIN_CHARS_IN_BLOCK = 3;
|
var MIN_CHARS_IN_BLOCK = 3;
|
||||||
var MAX_CHARS_IN_BLOCK = 1000;
|
var MAX_CHARS_IN_BLOCK = 1000;
|
||||||
|
|
||||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
var fnArray = context.fnArray,
|
||||||
|
argsArray = context.argsArray;
|
||||||
var curr = context.iCurr;
|
var curr = context.iCurr;
|
||||||
var iFirstBeginText = curr - 4;
|
var iFirstBeginText = curr - 4;
|
||||||
var iFirstSetFont = curr - 3;
|
var iFirstSetFont = curr - 3;
|
||||||
@ -394,23 +454,27 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
|
|
||||||
// At this point, i is the index of the first op past the last valid
|
// At this point, i is the index of the first op past the last valid
|
||||||
// quintet.
|
// quintet.
|
||||||
var count = Math.min(Math.floor((i - iFirstBeginText) / 5),
|
var count = Math.min(
|
||||||
MAX_CHARS_IN_BLOCK);
|
Math.floor((i - iFirstBeginText) / 5),
|
||||||
|
MAX_CHARS_IN_BLOCK
|
||||||
|
);
|
||||||
if (count < MIN_CHARS_IN_BLOCK) {
|
if (count < MIN_CHARS_IN_BLOCK) {
|
||||||
return i - (i - iFirstBeginText) % 5;
|
return i - ((i - iFirstBeginText) % 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the preceding quintet is (<something>, setFont, setTextMatrix,
|
// If the preceding quintet is (<something>, setFont, setTextMatrix,
|
||||||
// showText, endText), include that as well. (E.g. <something> might be
|
// showText, endText), include that as well. (E.g. <something> might be
|
||||||
// |dependency|.)
|
// |dependency|.)
|
||||||
var iFirst = iFirstBeginText;
|
var iFirst = iFirstBeginText;
|
||||||
if (iFirstBeginText >= 4 &&
|
if (
|
||||||
|
iFirstBeginText >= 4 &&
|
||||||
fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] &&
|
fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] &&
|
||||||
fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] &&
|
fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] &&
|
||||||
fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] &&
|
fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] &&
|
||||||
fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] &&
|
fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] &&
|
||||||
argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 &&
|
argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 &&
|
||||||
argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
|
argsArray[iFirstBeginText - 4][1] === firstSetFontArg1
|
||||||
|
) {
|
||||||
count++;
|
count++;
|
||||||
iFirst -= 5;
|
iFirst -= 5;
|
||||||
}
|
}
|
||||||
@ -424,7 +488,8 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return iEndText + 1;
|
return iEndText + 1;
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
function QueueOptimizer(queue) {
|
function QueueOptimizer(queue) {
|
||||||
this.queue = queue;
|
this.queue = queue;
|
||||||
@ -442,10 +507,11 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
|||||||
_optimize() {
|
_optimize() {
|
||||||
// Process new fnArray item(s) chunk.
|
// Process new fnArray item(s) chunk.
|
||||||
const fnArray = this.queue.fnArray;
|
const fnArray = this.queue.fnArray;
|
||||||
let i = this.lastProcessed, ii = fnArray.length;
|
let i = this.lastProcessed,
|
||||||
|
ii = fnArray.length;
|
||||||
let state = this.state;
|
let state = this.state;
|
||||||
let match = this.match;
|
let match = this.match;
|
||||||
if (!state && !match && (i + 1 === ii) && !InitialState[fnArray[i]]) {
|
if (!state && !match && i + 1 === ii && !InitialState[fnArray[i]]) {
|
||||||
// Micro-optimization for the common case: last item is not
|
// Micro-optimization for the common case: last item is not
|
||||||
// optimizable, just skipping it.
|
// optimizable, just skipping it.
|
||||||
this.lastProcessed = ii;
|
this.lastProcessed = ii;
|
||||||
@ -545,7 +611,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
this._streamSink = streamSink;
|
this._streamSink = streamSink;
|
||||||
this.fnArray = [];
|
this.fnArray = [];
|
||||||
this.argsArray = [];
|
this.argsArray = [];
|
||||||
if (streamSink && intent !== 'oplist') {
|
if (streamSink && intent !== "oplist") {
|
||||||
this.optimizer = new QueueOptimizer(this);
|
this.optimizer = new QueueOptimizer(this);
|
||||||
} else {
|
} else {
|
||||||
this.optimizer = new NullOptimizer(this);
|
this.optimizer = new NullOptimizer(this);
|
||||||
@ -572,7 +638,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
* `this.length === 0` after flushing.
|
* `this.length === 0` after flushing.
|
||||||
*/
|
*/
|
||||||
get totalLength() {
|
get totalLength() {
|
||||||
return (this._totalLength + this.length);
|
return this._totalLength + this.length;
|
||||||
},
|
},
|
||||||
|
|
||||||
addOp(fn, args) {
|
addOp(fn, args) {
|
||||||
@ -581,8 +647,10 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
if (this._streamSink) {
|
if (this._streamSink) {
|
||||||
if (this.weight >= CHUNK_SIZE) {
|
if (this.weight >= CHUNK_SIZE) {
|
||||||
this.flush();
|
this.flush();
|
||||||
} else if (this.weight >= CHUNK_SIZE_ABOUT &&
|
} else if (
|
||||||
(fn === OPS.restore || fn === OPS.endText)) {
|
this.weight >= CHUNK_SIZE_ABOUT &&
|
||||||
|
(fn === OPS.restore || fn === OPS.endText)
|
||||||
|
) {
|
||||||
// heuristic to flush on boundary of restore or endText
|
// heuristic to flush on boundary of restore or endText
|
||||||
this.flush();
|
this.flush();
|
||||||
}
|
}
|
||||||
@ -620,7 +688,7 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
|
|
||||||
get _transfers() {
|
get _transfers() {
|
||||||
const transfers = [];
|
const transfers = [];
|
||||||
const { fnArray, argsArray, length, } = this;
|
const { fnArray, argsArray, length } = this;
|
||||||
for (let i = 0; i < length; i++) {
|
for (let i = 0; i < length; i++) {
|
||||||
switch (fnArray[i]) {
|
switch (fnArray[i]) {
|
||||||
case OPS.paintInlineImageXObject:
|
case OPS.paintInlineImageXObject:
|
||||||
@ -628,10 +696,14 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
case OPS.paintImageMaskXObject:
|
case OPS.paintImageMaskXObject:
|
||||||
const arg = argsArray[i][0]; // first param in imgData
|
const arg = argsArray[i][0]; // first param in imgData
|
||||||
|
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
assert(arg.data instanceof Uint8ClampedArray,
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
'OperatorList._transfers: Unsupported "arg.data" type.');
|
) {
|
||||||
|
assert(
|
||||||
|
arg.data instanceof Uint8ClampedArray,
|
||||||
|
'OperatorList._transfers: Unsupported "arg.data" type.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!arg.cached) {
|
if (!arg.cached) {
|
||||||
transfers.push(arg.data.buffer);
|
transfers.push(arg.data.buffer);
|
||||||
@ -647,12 +719,16 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
const length = this.length;
|
const length = this.length;
|
||||||
this._totalLength += length;
|
this._totalLength += length;
|
||||||
|
|
||||||
this._streamSink.enqueue({
|
this._streamSink.enqueue(
|
||||||
|
{
|
||||||
fnArray: this.fnArray,
|
fnArray: this.fnArray,
|
||||||
argsArray: this.argsArray,
|
argsArray: this.argsArray,
|
||||||
lastChunk,
|
lastChunk,
|
||||||
length,
|
length,
|
||||||
}, 1, this._transfers);
|
},
|
||||||
|
1,
|
||||||
|
this._transfers
|
||||||
|
);
|
||||||
|
|
||||||
this.dependencies = Object.create(null);
|
this.dependencies = Object.create(null);
|
||||||
this.fnArray.length = 0;
|
this.fnArray.length = 0;
|
||||||
@ -665,6 +741,4 @@ var OperatorList = (function OperatorListClosure() {
|
|||||||
return OperatorList;
|
return OperatorList;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { OperatorList };
|
||||||
OperatorList,
|
|
||||||
};
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -15,11 +15,17 @@
|
|||||||
/* eslint-disable no-multi-spaces */
|
/* eslint-disable no-multi-spaces */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
assert, FormatError, info, unreachable, UNSUPPORTED_FEATURES, Util, warn
|
assert,
|
||||||
} from '../shared/util';
|
FormatError,
|
||||||
import { ColorSpace } from './colorspace';
|
info,
|
||||||
import { isStream } from './primitives';
|
unreachable,
|
||||||
import { MissingDataException } from './core_utils';
|
UNSUPPORTED_FEATURES,
|
||||||
|
Util,
|
||||||
|
warn,
|
||||||
|
} from "../shared/util";
|
||||||
|
import { ColorSpace } from "./colorspace";
|
||||||
|
import { isStream } from "./primitives";
|
||||||
|
import { MissingDataException } from "./core_utils";
|
||||||
|
|
||||||
var ShadingType = {
|
var ShadingType = {
|
||||||
FUNCTION_BASED: 1,
|
FUNCTION_BASED: 1,
|
||||||
@ -34,7 +40,7 @@ var ShadingType = {
|
|||||||
var Pattern = (function PatternClosure() {
|
var Pattern = (function PatternClosure() {
|
||||||
// Constructor should define this.getPattern
|
// Constructor should define this.getPattern
|
||||||
function Pattern() {
|
function Pattern() {
|
||||||
unreachable('should not call Pattern constructor');
|
unreachable("should not call Pattern constructor");
|
||||||
}
|
}
|
||||||
|
|
||||||
Pattern.prototype = {
|
Pattern.prototype = {
|
||||||
@ -45,33 +51,50 @@ var Pattern = (function PatternClosure() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Pattern.parseShading = function(shading, matrix, xref, res, handler,
|
Pattern.parseShading = function(
|
||||||
pdfFunctionFactory) {
|
shading,
|
||||||
|
matrix,
|
||||||
|
xref,
|
||||||
|
res,
|
||||||
|
handler,
|
||||||
|
pdfFunctionFactory
|
||||||
|
) {
|
||||||
var dict = isStream(shading) ? shading.dict : shading;
|
var dict = isStream(shading) ? shading.dict : shading;
|
||||||
var type = dict.get('ShadingType');
|
var type = dict.get("ShadingType");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ShadingType.AXIAL:
|
case ShadingType.AXIAL:
|
||||||
case ShadingType.RADIAL:
|
case ShadingType.RADIAL:
|
||||||
// Both radial and axial shadings are handled by RadialAxial shading.
|
// Both radial and axial shadings are handled by RadialAxial shading.
|
||||||
return new Shadings.RadialAxial(dict, matrix, xref, res,
|
return new Shadings.RadialAxial(
|
||||||
pdfFunctionFactory);
|
dict,
|
||||||
|
matrix,
|
||||||
|
xref,
|
||||||
|
res,
|
||||||
|
pdfFunctionFactory
|
||||||
|
);
|
||||||
case ShadingType.FREE_FORM_MESH:
|
case ShadingType.FREE_FORM_MESH:
|
||||||
case ShadingType.LATTICE_FORM_MESH:
|
case ShadingType.LATTICE_FORM_MESH:
|
||||||
case ShadingType.COONS_PATCH_MESH:
|
case ShadingType.COONS_PATCH_MESH:
|
||||||
case ShadingType.TENSOR_PATCH_MESH:
|
case ShadingType.TENSOR_PATCH_MESH:
|
||||||
return new Shadings.Mesh(shading, matrix, xref, res,
|
return new Shadings.Mesh(
|
||||||
pdfFunctionFactory);
|
shading,
|
||||||
|
matrix,
|
||||||
|
xref,
|
||||||
|
res,
|
||||||
|
pdfFunctionFactory
|
||||||
|
);
|
||||||
default:
|
default:
|
||||||
throw new FormatError('Unsupported ShadingType: ' + type);
|
throw new FormatError("Unsupported ShadingType: " + type);
|
||||||
}
|
}
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (ex instanceof MissingDataException) {
|
if (ex instanceof MissingDataException) {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
handler.send('UnsupportedFeature',
|
handler.send("UnsupportedFeature", {
|
||||||
{ featureId: UNSUPPORTED_FEATURES.shadingPattern, });
|
featureId: UNSUPPORTED_FEATURES.shadingPattern,
|
||||||
|
});
|
||||||
warn(ex);
|
warn(ex);
|
||||||
return new Shadings.Dummy();
|
return new Shadings.Dummy();
|
||||||
}
|
}
|
||||||
@ -90,35 +113,39 @@ Shadings.SMALL_NUMBER = 1e-6;
|
|||||||
Shadings.RadialAxial = (function RadialAxialClosure() {
|
Shadings.RadialAxial = (function RadialAxialClosure() {
|
||||||
function RadialAxial(dict, matrix, xref, res, pdfFunctionFactory) {
|
function RadialAxial(dict, matrix, xref, res, pdfFunctionFactory) {
|
||||||
this.matrix = matrix;
|
this.matrix = matrix;
|
||||||
this.coordsArr = dict.getArray('Coords');
|
this.coordsArr = dict.getArray("Coords");
|
||||||
this.shadingType = dict.get('ShadingType');
|
this.shadingType = dict.get("ShadingType");
|
||||||
this.type = 'Pattern';
|
this.type = "Pattern";
|
||||||
var cs = dict.get('ColorSpace', 'CS');
|
var cs = dict.get("ColorSpace", "CS");
|
||||||
cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
|
cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
|
||||||
this.cs = cs;
|
this.cs = cs;
|
||||||
const bbox = dict.getArray('BBox');
|
const bbox = dict.getArray("BBox");
|
||||||
if (Array.isArray(bbox) && bbox.length === 4) {
|
if (Array.isArray(bbox) && bbox.length === 4) {
|
||||||
this.bbox = Util.normalizeRect(bbox);
|
this.bbox = Util.normalizeRect(bbox);
|
||||||
} else {
|
} else {
|
||||||
this.bbox = null;
|
this.bbox = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var t0 = 0.0, t1 = 1.0;
|
var t0 = 0.0,
|
||||||
if (dict.has('Domain')) {
|
t1 = 1.0;
|
||||||
var domainArr = dict.getArray('Domain');
|
if (dict.has("Domain")) {
|
||||||
|
var domainArr = dict.getArray("Domain");
|
||||||
t0 = domainArr[0];
|
t0 = domainArr[0];
|
||||||
t1 = domainArr[1];
|
t1 = domainArr[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
var extendStart = false, extendEnd = false;
|
var extendStart = false,
|
||||||
if (dict.has('Extend')) {
|
extendEnd = false;
|
||||||
var extendArr = dict.getArray('Extend');
|
if (dict.has("Extend")) {
|
||||||
|
var extendArr = dict.getArray("Extend");
|
||||||
extendStart = extendArr[0];
|
extendStart = extendArr[0];
|
||||||
extendEnd = extendArr[1];
|
extendEnd = extendArr[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.shadingType === ShadingType.RADIAL &&
|
if (
|
||||||
(!extendStart || !extendEnd)) {
|
this.shadingType === ShadingType.RADIAL &&
|
||||||
|
(!extendStart || !extendEnd)
|
||||||
|
) {
|
||||||
// Radial gradient only currently works if either circle is fully within
|
// Radial gradient only currently works if either circle is fully within
|
||||||
// the other circle.
|
// the other circle.
|
||||||
var x1 = this.coordsArr[0];
|
var x1 = this.coordsArr[0];
|
||||||
@ -128,16 +155,15 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
|||||||
var y2 = this.coordsArr[4];
|
var y2 = this.coordsArr[4];
|
||||||
var r2 = this.coordsArr[5];
|
var r2 = this.coordsArr[5];
|
||||||
var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
|
var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
|
||||||
if (r1 <= r2 + distance &&
|
if (r1 <= r2 + distance && r2 <= r1 + distance) {
|
||||||
r2 <= r1 + distance) {
|
warn("Unsupported radial gradient.");
|
||||||
warn('Unsupported radial gradient.');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.extendStart = extendStart;
|
this.extendStart = extendStart;
|
||||||
this.extendEnd = extendEnd;
|
this.extendEnd = extendEnd;
|
||||||
|
|
||||||
var fnObj = dict.get('Function');
|
var fnObj = dict.get("Function");
|
||||||
var fn = pdfFunctionFactory.createFromArray(fnObj);
|
var fn = pdfFunctionFactory.createFromArray(fnObj);
|
||||||
|
|
||||||
// 10 samples seems good enough for now, but probably won't work
|
// 10 samples seems good enough for now, but probably won't work
|
||||||
@ -146,17 +172,18 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
|||||||
const NUMBER_OF_SAMPLES = 10;
|
const NUMBER_OF_SAMPLES = 10;
|
||||||
const step = (t1 - t0) / NUMBER_OF_SAMPLES;
|
const step = (t1 - t0) / NUMBER_OF_SAMPLES;
|
||||||
|
|
||||||
var colorStops = this.colorStops = [];
|
var colorStops = (this.colorStops = []);
|
||||||
|
|
||||||
// Protect against bad domains.
|
// Protect against bad domains.
|
||||||
if (t0 >= t1 || step <= 0) {
|
if (t0 >= t1 || step <= 0) {
|
||||||
// Acrobat doesn't seem to handle these cases so we'll ignore for
|
// Acrobat doesn't seem to handle these cases so we'll ignore for
|
||||||
// now.
|
// now.
|
||||||
info('Bad shading domain.');
|
info("Bad shading domain.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var color = new Float32Array(cs.numComps), ratio = new Float32Array(1);
|
var color = new Float32Array(cs.numComps),
|
||||||
|
ratio = new Float32Array(1);
|
||||||
var rgbColor;
|
var rgbColor;
|
||||||
for (let i = 0; i <= NUMBER_OF_SAMPLES; i++) {
|
for (let i = 0; i <= NUMBER_OF_SAMPLES; i++) {
|
||||||
ratio[0] = t0 + i * step;
|
ratio[0] = t0 + i * step;
|
||||||
@ -166,9 +193,9 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
|||||||
colorStops.push([i / NUMBER_OF_SAMPLES, cssColor]);
|
colorStops.push([i / NUMBER_OF_SAMPLES, cssColor]);
|
||||||
}
|
}
|
||||||
|
|
||||||
var background = 'transparent';
|
var background = "transparent";
|
||||||
if (dict.has('Background')) {
|
if (dict.has("Background")) {
|
||||||
rgbColor = cs.getRgb(dict.get('Background'), 0);
|
rgbColor = cs.getRgb(dict.get("Background"), 0);
|
||||||
background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
|
background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -197,13 +224,13 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
|||||||
p1 = [coordsArr[2], coordsArr[3]];
|
p1 = [coordsArr[2], coordsArr[3]];
|
||||||
r0 = null;
|
r0 = null;
|
||||||
r1 = null;
|
r1 = null;
|
||||||
type = 'axial';
|
type = "axial";
|
||||||
} else if (shadingType === ShadingType.RADIAL) {
|
} else if (shadingType === ShadingType.RADIAL) {
|
||||||
p0 = [coordsArr[0], coordsArr[1]];
|
p0 = [coordsArr[0], coordsArr[1]];
|
||||||
p1 = [coordsArr[3], coordsArr[4]];
|
p1 = [coordsArr[3], coordsArr[4]];
|
||||||
r0 = coordsArr[2];
|
r0 = coordsArr[2];
|
||||||
r1 = coordsArr[5];
|
r1 = coordsArr[5];
|
||||||
type = 'radial';
|
type = "radial";
|
||||||
} else {
|
} else {
|
||||||
unreachable(`getPattern type unknown: ${shadingType}`);
|
unreachable(`getPattern type unknown: ${shadingType}`);
|
||||||
}
|
}
|
||||||
@ -219,7 +246,7 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ['RadialAxial', type, this.bbox, this.colorStops, p0, p1, r0, r1];
|
return ["RadialAxial", type, this.bbox, this.colorStops, p0, p1, r0, r1];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -238,8 +265,9 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
var numComps = context.numComps;
|
var numComps = context.numComps;
|
||||||
this.tmpCompsBuf = new Float32Array(numComps);
|
this.tmpCompsBuf = new Float32Array(numComps);
|
||||||
var csNumComps = context.colorSpace.numComps;
|
var csNumComps = context.colorSpace.numComps;
|
||||||
this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) :
|
this.tmpCsCompsBuf = context.colorFn
|
||||||
this.tmpCompsBuf;
|
? new Float32Array(csNumComps)
|
||||||
|
: this.tmpCompsBuf;
|
||||||
}
|
}
|
||||||
MeshStreamReader.prototype = {
|
MeshStreamReader.prototype = {
|
||||||
get hasData() {
|
get hasData() {
|
||||||
@ -262,16 +290,26 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
var bufferLength = this.bufferLength;
|
var bufferLength = this.bufferLength;
|
||||||
if (n === 32) {
|
if (n === 32) {
|
||||||
if (bufferLength === 0) {
|
if (bufferLength === 0) {
|
||||||
return ((this.stream.getByte() << 24) |
|
return (
|
||||||
(this.stream.getByte() << 16) | (this.stream.getByte() << 8) |
|
((this.stream.getByte() << 24) |
|
||||||
this.stream.getByte()) >>> 0;
|
(this.stream.getByte() << 16) |
|
||||||
|
(this.stream.getByte() << 8) |
|
||||||
|
this.stream.getByte()) >>>
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
buffer = (buffer << 24) | (this.stream.getByte() << 16) |
|
buffer =
|
||||||
(this.stream.getByte() << 8) | this.stream.getByte();
|
(buffer << 24) |
|
||||||
|
(this.stream.getByte() << 16) |
|
||||||
|
(this.stream.getByte() << 8) |
|
||||||
|
this.stream.getByte();
|
||||||
var nextByte = this.stream.getByte();
|
var nextByte = this.stream.getByte();
|
||||||
this.buffer = nextByte & ((1 << bufferLength) - 1);
|
this.buffer = nextByte & ((1 << bufferLength) - 1);
|
||||||
return ((buffer << (8 - bufferLength)) |
|
return (
|
||||||
((nextByte & 0xFF) >> bufferLength)) >>> 0;
|
((buffer << (8 - bufferLength)) |
|
||||||
|
((nextByte & 0xff) >> bufferLength)) >>>
|
||||||
|
0
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (n === 8 && bufferLength === 0) {
|
if (n === 8 && bufferLength === 0) {
|
||||||
return this.stream.getByte();
|
return this.stream.getByte();
|
||||||
@ -297,18 +335,22 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
var xi = this.readBits(bitsPerCoordinate);
|
var xi = this.readBits(bitsPerCoordinate);
|
||||||
var yi = this.readBits(bitsPerCoordinate);
|
var yi = this.readBits(bitsPerCoordinate);
|
||||||
var decode = this.context.decode;
|
var decode = this.context.decode;
|
||||||
var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) :
|
var scale =
|
||||||
2.3283064365386963e-10; // 2 ^ -32
|
bitsPerCoordinate < 32
|
||||||
|
? 1 / ((1 << bitsPerCoordinate) - 1)
|
||||||
|
: 2.3283064365386963e-10; // 2 ^ -32
|
||||||
return [
|
return [
|
||||||
xi * scale * (decode[1] - decode[0]) + decode[0],
|
xi * scale * (decode[1] - decode[0]) + decode[0],
|
||||||
yi * scale * (decode[3] - decode[2]) + decode[2]
|
yi * scale * (decode[3] - decode[2]) + decode[2],
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
readComponents: function MeshStreamReader_readComponents() {
|
readComponents: function MeshStreamReader_readComponents() {
|
||||||
var numComps = this.context.numComps;
|
var numComps = this.context.numComps;
|
||||||
var bitsPerComponent = this.context.bitsPerComponent;
|
var bitsPerComponent = this.context.bitsPerComponent;
|
||||||
var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) :
|
var scale =
|
||||||
2.3283064365386963e-10; // 2 ^ -32
|
bitsPerComponent < 32
|
||||||
|
? 1 / ((1 << bitsPerComponent) - 1)
|
||||||
|
: 2.3283064365386963e-10; // 2 ^ -32
|
||||||
var decode = this.context.decode;
|
var decode = this.context.decode;
|
||||||
var components = this.tmpCompsBuf;
|
var components = this.tmpCompsBuf;
|
||||||
for (var i = 0, j = 4; i < numComps; i++, j += 2) {
|
for (var i = 0, j = 4; i < numComps; i++, j += 2) {
|
||||||
@ -333,9 +375,10 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
var f = reader.readFlag();
|
var f = reader.readFlag();
|
||||||
var coord = reader.readCoordinate();
|
var coord = reader.readCoordinate();
|
||||||
var color = reader.readComponents();
|
var color = reader.readComponents();
|
||||||
if (verticesLeft === 0) { // ignoring flags if we started a triangle
|
if (verticesLeft === 0) {
|
||||||
|
// ignoring flags if we started a triangle
|
||||||
if (!(0 <= f && f <= 2)) {
|
if (!(0 <= f && f <= 2)) {
|
||||||
throw new FormatError('Unknown type4 flag');
|
throw new FormatError("Unknown type4 flag");
|
||||||
}
|
}
|
||||||
switch (f) {
|
switch (f) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -360,7 +403,7 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
reader.align();
|
reader.align();
|
||||||
}
|
}
|
||||||
mesh.figures.push({
|
mesh.figures.push({
|
||||||
type: 'triangles',
|
type: "triangles",
|
||||||
coords: new Int32Array(ps),
|
coords: new Int32Array(ps),
|
||||||
colors: new Int32Array(ps),
|
colors: new Int32Array(ps),
|
||||||
});
|
});
|
||||||
@ -378,7 +421,7 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
colors.push(color);
|
colors.push(color);
|
||||||
}
|
}
|
||||||
mesh.figures.push({
|
mesh.figures.push({
|
||||||
type: 'lattice',
|
type: "lattice",
|
||||||
coords: new Int32Array(ps),
|
coords: new Int32Array(ps),
|
||||||
colors: new Int32Array(ps),
|
colors: new Int32Array(ps),
|
||||||
verticesPerRow,
|
verticesPerRow,
|
||||||
@ -394,9 +437,16 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
function buildB(count) {
|
function buildB(count) {
|
||||||
var lut = [];
|
var lut = [];
|
||||||
for (var i = 0; i <= count; i++) {
|
for (var i = 0; i <= count; i++) {
|
||||||
var t = i / count, t_ = 1 - t;
|
var t = i / count,
|
||||||
lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_,
|
t_ = 1 - t;
|
||||||
3 * t * t * t_, t * t * t]));
|
lut.push(
|
||||||
|
new Float32Array([
|
||||||
|
t_ * t_ * t_,
|
||||||
|
3 * t * t_ * t_,
|
||||||
|
3 * t * t * t_,
|
||||||
|
t * t * t,
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return lut;
|
return lut;
|
||||||
}
|
}
|
||||||
@ -411,37 +461,66 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
|
|
||||||
function buildFigureFromPatch(mesh, index) {
|
function buildFigureFromPatch(mesh, index) {
|
||||||
var figure = mesh.figures[index];
|
var figure = mesh.figures[index];
|
||||||
assert(figure.type === 'patch', 'Unexpected patch mesh figure');
|
assert(figure.type === "patch", "Unexpected patch mesh figure");
|
||||||
|
|
||||||
var coords = mesh.coords, colors = mesh.colors;
|
var coords = mesh.coords,
|
||||||
|
colors = mesh.colors;
|
||||||
var pi = figure.coords;
|
var pi = figure.coords;
|
||||||
var ci = figure.colors;
|
var ci = figure.colors;
|
||||||
|
|
||||||
var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0],
|
var figureMinX = Math.min(
|
||||||
coords[pi[12]][0], coords[pi[15]][0]);
|
coords[pi[0]][0],
|
||||||
var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1],
|
coords[pi[3]][0],
|
||||||
coords[pi[12]][1], coords[pi[15]][1]);
|
coords[pi[12]][0],
|
||||||
var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0],
|
coords[pi[15]][0]
|
||||||
coords[pi[12]][0], coords[pi[15]][0]);
|
);
|
||||||
var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1],
|
var figureMinY = Math.min(
|
||||||
coords[pi[12]][1], coords[pi[15]][1]);
|
coords[pi[0]][1],
|
||||||
var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY /
|
coords[pi[3]][1],
|
||||||
(mesh.bounds[2] - mesh.bounds[0]));
|
coords[pi[12]][1],
|
||||||
splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
coords[pi[15]][1]
|
||||||
Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
|
);
|
||||||
var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY /
|
var figureMaxX = Math.max(
|
||||||
(mesh.bounds[3] - mesh.bounds[1]));
|
coords[pi[0]][0],
|
||||||
splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
coords[pi[3]][0],
|
||||||
Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
|
coords[pi[12]][0],
|
||||||
|
coords[pi[15]][0]
|
||||||
|
);
|
||||||
|
var figureMaxY = Math.max(
|
||||||
|
coords[pi[0]][1],
|
||||||
|
coords[pi[3]][1],
|
||||||
|
coords[pi[12]][1],
|
||||||
|
coords[pi[15]][1]
|
||||||
|
);
|
||||||
|
var splitXBy = Math.ceil(
|
||||||
|
((figureMaxX - figureMinX) * TRIANGLE_DENSITY) /
|
||||||
|
(mesh.bounds[2] - mesh.bounds[0])
|
||||||
|
);
|
||||||
|
splitXBy = Math.max(
|
||||||
|
MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
||||||
|
Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy)
|
||||||
|
);
|
||||||
|
var splitYBy = Math.ceil(
|
||||||
|
((figureMaxY - figureMinY) * TRIANGLE_DENSITY) /
|
||||||
|
(mesh.bounds[3] - mesh.bounds[1])
|
||||||
|
);
|
||||||
|
splitYBy = Math.max(
|
||||||
|
MIN_SPLIT_PATCH_CHUNKS_AMOUNT,
|
||||||
|
Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy)
|
||||||
|
);
|
||||||
|
|
||||||
var verticesPerRow = splitXBy + 1;
|
var verticesPerRow = splitXBy + 1;
|
||||||
var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
|
var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
|
||||||
var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
|
var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
|
||||||
var k = 0;
|
var k = 0;
|
||||||
var cl = new Uint8Array(3), cr = new Uint8Array(3);
|
var cl = new Uint8Array(3),
|
||||||
var c0 = colors[ci[0]], c1 = colors[ci[1]],
|
cr = new Uint8Array(3);
|
||||||
c2 = colors[ci[2]], c3 = colors[ci[3]];
|
var c0 = colors[ci[0]],
|
||||||
var bRow = getB(splitYBy), bCol = getB(splitXBy);
|
c1 = colors[ci[1]],
|
||||||
|
c2 = colors[ci[2]],
|
||||||
|
c3 = colors[ci[3]];
|
||||||
|
var bRow = getB(splitYBy),
|
||||||
|
bCol = getB(splitXBy);
|
||||||
for (var row = 0; row <= splitYBy; row++) {
|
for (var row = 0; row <= splitYBy; row++) {
|
||||||
cl[0] = ((c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy) | 0;
|
cl[0] = ((c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy) | 0;
|
||||||
cl[1] = ((c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy) | 0;
|
cl[1] = ((c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy) | 0;
|
||||||
@ -452,11 +531,14 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
cr[2] = ((c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy) | 0;
|
cr[2] = ((c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy) | 0;
|
||||||
|
|
||||||
for (var col = 0; col <= splitXBy; col++, k++) {
|
for (var col = 0; col <= splitXBy; col++, k++) {
|
||||||
if ((row === 0 || row === splitYBy) &&
|
if (
|
||||||
(col === 0 || col === splitXBy)) {
|
(row === 0 || row === splitYBy) &&
|
||||||
|
(col === 0 || col === splitXBy)
|
||||||
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var x = 0, y = 0;
|
var x = 0,
|
||||||
|
y = 0;
|
||||||
var q = 0;
|
var q = 0;
|
||||||
for (var i = 0; i <= 3; i++) {
|
for (var i = 0; i <= 3; i++) {
|
||||||
for (var j = 0; j <= 3; j++, q++) {
|
for (var j = 0; j <= 3; j++, q++) {
|
||||||
@ -485,7 +567,7 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
|
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
|
||||||
|
|
||||||
mesh.figures[index] = {
|
mesh.figures[index] = {
|
||||||
type: 'lattice',
|
type: "lattice",
|
||||||
coords: figureCoords,
|
coords: figureCoords,
|
||||||
colors: figureColors,
|
colors: figureColors,
|
||||||
verticesPerRow,
|
verticesPerRow,
|
||||||
@ -501,15 +583,15 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
while (reader.hasData) {
|
while (reader.hasData) {
|
||||||
var f = reader.readFlag();
|
var f = reader.readFlag();
|
||||||
if (!(0 <= f && f <= 3)) {
|
if (!(0 <= f && f <= 3)) {
|
||||||
throw new FormatError('Unknown type6 flag');
|
throw new FormatError("Unknown type6 flag");
|
||||||
}
|
}
|
||||||
var i, ii;
|
var i, ii;
|
||||||
var pi = coords.length;
|
var pi = coords.length;
|
||||||
for (i = 0, ii = (f !== 0 ? 8 : 12); i < ii; i++) {
|
for (i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
|
||||||
coords.push(reader.readCoordinate());
|
coords.push(reader.readCoordinate());
|
||||||
}
|
}
|
||||||
var ci = colors.length;
|
var ci = colors.length;
|
||||||
for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) {
|
for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
||||||
colors.push(reader.readComponents());
|
colors.push(reader.readComponents());
|
||||||
}
|
}
|
||||||
var tmp1, tmp2, tmp3, tmp4;
|
var tmp1, tmp2, tmp3, tmp4;
|
||||||
@ -559,50 +641,66 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
// set p11, p12, p21, p22
|
// set p11, p12, p21, p22
|
||||||
ps[5] = coords.length;
|
ps[5] = coords.length;
|
||||||
coords.push([
|
coords.push([
|
||||||
(-4 * coords[ps[0]][0] - coords[ps[15]][0] +
|
(-4 * coords[ps[0]][0] -
|
||||||
|
coords[ps[15]][0] +
|
||||||
6 * (coords[ps[4]][0] + coords[ps[1]][0]) -
|
6 * (coords[ps[4]][0] + coords[ps[1]][0]) -
|
||||||
2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
|
2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
|
||||||
3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
|
3 * (coords[ps[13]][0] + coords[ps[7]][0])) /
|
||||||
(-4 * coords[ps[0]][1] - coords[ps[15]][1] +
|
9,
|
||||||
|
(-4 * coords[ps[0]][1] -
|
||||||
|
coords[ps[15]][1] +
|
||||||
6 * (coords[ps[4]][1] + coords[ps[1]][1]) -
|
6 * (coords[ps[4]][1] + coords[ps[1]][1]) -
|
||||||
2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
|
2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
|
||||||
3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9
|
3 * (coords[ps[13]][1] + coords[ps[7]][1])) /
|
||||||
|
9,
|
||||||
]);
|
]);
|
||||||
ps[6] = coords.length;
|
ps[6] = coords.length;
|
||||||
coords.push([
|
coords.push([
|
||||||
(-4 * coords[ps[3]][0] - coords[ps[12]][0] +
|
(-4 * coords[ps[3]][0] -
|
||||||
|
coords[ps[12]][0] +
|
||||||
6 * (coords[ps[2]][0] + coords[ps[7]][0]) -
|
6 * (coords[ps[2]][0] + coords[ps[7]][0]) -
|
||||||
2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
|
2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
|
||||||
3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
|
3 * (coords[ps[4]][0] + coords[ps[14]][0])) /
|
||||||
(-4 * coords[ps[3]][1] - coords[ps[12]][1] +
|
9,
|
||||||
|
(-4 * coords[ps[3]][1] -
|
||||||
|
coords[ps[12]][1] +
|
||||||
6 * (coords[ps[2]][1] + coords[ps[7]][1]) -
|
6 * (coords[ps[2]][1] + coords[ps[7]][1]) -
|
||||||
2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
|
2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
|
||||||
3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9
|
3 * (coords[ps[4]][1] + coords[ps[14]][1])) /
|
||||||
|
9,
|
||||||
]);
|
]);
|
||||||
ps[9] = coords.length;
|
ps[9] = coords.length;
|
||||||
coords.push([
|
coords.push([
|
||||||
(-4 * coords[ps[12]][0] - coords[ps[3]][0] +
|
(-4 * coords[ps[12]][0] -
|
||||||
|
coords[ps[3]][0] +
|
||||||
6 * (coords[ps[8]][0] + coords[ps[13]][0]) -
|
6 * (coords[ps[8]][0] + coords[ps[13]][0]) -
|
||||||
2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
|
2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
|
||||||
3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
|
3 * (coords[ps[11]][0] + coords[ps[1]][0])) /
|
||||||
(-4 * coords[ps[12]][1] - coords[ps[3]][1] +
|
9,
|
||||||
|
(-4 * coords[ps[12]][1] -
|
||||||
|
coords[ps[3]][1] +
|
||||||
6 * (coords[ps[8]][1] + coords[ps[13]][1]) -
|
6 * (coords[ps[8]][1] + coords[ps[13]][1]) -
|
||||||
2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
|
2 * (coords[ps[0]][1] + coords[ps[15]][1]) +
|
||||||
3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9
|
3 * (coords[ps[11]][1] + coords[ps[1]][1])) /
|
||||||
|
9,
|
||||||
]);
|
]);
|
||||||
ps[10] = coords.length;
|
ps[10] = coords.length;
|
||||||
coords.push([
|
coords.push([
|
||||||
(-4 * coords[ps[15]][0] - coords[ps[0]][0] +
|
(-4 * coords[ps[15]][0] -
|
||||||
|
coords[ps[0]][0] +
|
||||||
6 * (coords[ps[11]][0] + coords[ps[14]][0]) -
|
6 * (coords[ps[11]][0] + coords[ps[14]][0]) -
|
||||||
2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
|
2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
|
||||||
3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
|
3 * (coords[ps[2]][0] + coords[ps[8]][0])) /
|
||||||
(-4 * coords[ps[15]][1] - coords[ps[0]][1] +
|
9,
|
||||||
|
(-4 * coords[ps[15]][1] -
|
||||||
|
coords[ps[0]][1] +
|
||||||
6 * (coords[ps[11]][1] + coords[ps[14]][1]) -
|
6 * (coords[ps[11]][1] + coords[ps[14]][1]) -
|
||||||
2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
|
2 * (coords[ps[12]][1] + coords[ps[3]][1]) +
|
||||||
3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9
|
3 * (coords[ps[2]][1] + coords[ps[8]][1])) /
|
||||||
|
9,
|
||||||
]);
|
]);
|
||||||
mesh.figures.push({
|
mesh.figures.push({
|
||||||
type: 'patch',
|
type: "patch",
|
||||||
coords: new Int32Array(ps), // making copies of ps and cs
|
coords: new Int32Array(ps), // making copies of ps and cs
|
||||||
colors: new Int32Array(cs),
|
colors: new Int32Array(cs),
|
||||||
});
|
});
|
||||||
@ -617,15 +715,15 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
while (reader.hasData) {
|
while (reader.hasData) {
|
||||||
var f = reader.readFlag();
|
var f = reader.readFlag();
|
||||||
if (!(0 <= f && f <= 3)) {
|
if (!(0 <= f && f <= 3)) {
|
||||||
throw new FormatError('Unknown type7 flag');
|
throw new FormatError("Unknown type7 flag");
|
||||||
}
|
}
|
||||||
var i, ii;
|
var i, ii;
|
||||||
var pi = coords.length;
|
var pi = coords.length;
|
||||||
for (i = 0, ii = (f !== 0 ? 12 : 16); i < ii; i++) {
|
for (i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
|
||||||
coords.push(reader.readCoordinate());
|
coords.push(reader.readCoordinate());
|
||||||
}
|
}
|
||||||
var ci = colors.length;
|
var ci = colors.length;
|
||||||
for (i = 0, ii = (f !== 0 ? 2 : 4); i < ii; i++) {
|
for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
|
||||||
colors.push(reader.readComponents());
|
colors.push(reader.readComponents());
|
||||||
}
|
}
|
||||||
var tmp1, tmp2, tmp3, tmp4;
|
var tmp1, tmp2, tmp3, tmp4;
|
||||||
@ -673,7 +771,7 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mesh.figures.push({
|
mesh.figures.push({
|
||||||
type: 'patch',
|
type: "patch",
|
||||||
coords: new Int32Array(ps), // making copies of ps and cs
|
coords: new Int32Array(ps), // making copies of ps and cs
|
||||||
colors: new Int32Array(cs),
|
colors: new Int32Array(cs),
|
||||||
});
|
});
|
||||||
@ -681,10 +779,13 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateBounds(mesh) {
|
function updateBounds(mesh) {
|
||||||
var minX = mesh.coords[0][0], minY = mesh.coords[0][1],
|
var minX = mesh.coords[0][0],
|
||||||
maxX = minX, maxY = minY;
|
minY = mesh.coords[0][1],
|
||||||
|
maxX = minX,
|
||||||
|
maxY = minY;
|
||||||
for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
|
for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
|
||||||
var x = mesh.coords[i][0], y = mesh.coords[i][1];
|
var x = mesh.coords[i][0],
|
||||||
|
y = mesh.coords[i][1];
|
||||||
minX = minX > x ? x : minX;
|
minX = minX > x ? x : minX;
|
||||||
minY = minY > y ? y : minY;
|
minY = minY > y ? y : minY;
|
||||||
maxX = maxX < x ? x : maxX;
|
maxX = maxX < x ? x : maxX;
|
||||||
@ -717,7 +818,9 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
|
|
||||||
var figures = mesh.figures;
|
var figures = mesh.figures;
|
||||||
for (i = 0, ii = figures.length; i < ii; i++) {
|
for (i = 0, ii = figures.length; i < ii; i++) {
|
||||||
var figure = figures[i], ps = figure.coords, cs = figure.colors;
|
var figure = figures[i],
|
||||||
|
ps = figure.coords,
|
||||||
|
cs = figure.colors;
|
||||||
for (j = 0, jj = ps.length; j < jj; j++) {
|
for (j = 0, jj = ps.length; j < jj; j++) {
|
||||||
ps[j] *= 2;
|
ps[j] *= 2;
|
||||||
cs[j] *= 3;
|
cs[j] *= 3;
|
||||||
@ -727,25 +830,26 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
|
|
||||||
function Mesh(stream, matrix, xref, res, pdfFunctionFactory) {
|
function Mesh(stream, matrix, xref, res, pdfFunctionFactory) {
|
||||||
if (!isStream(stream)) {
|
if (!isStream(stream)) {
|
||||||
throw new FormatError('Mesh data is not a stream');
|
throw new FormatError("Mesh data is not a stream");
|
||||||
}
|
}
|
||||||
var dict = stream.dict;
|
var dict = stream.dict;
|
||||||
this.matrix = matrix;
|
this.matrix = matrix;
|
||||||
this.shadingType = dict.get('ShadingType');
|
this.shadingType = dict.get("ShadingType");
|
||||||
this.type = 'Pattern';
|
this.type = "Pattern";
|
||||||
const bbox = dict.getArray('BBox');
|
const bbox = dict.getArray("BBox");
|
||||||
if (Array.isArray(bbox) && bbox.length === 4) {
|
if (Array.isArray(bbox) && bbox.length === 4) {
|
||||||
this.bbox = Util.normalizeRect(bbox);
|
this.bbox = Util.normalizeRect(bbox);
|
||||||
} else {
|
} else {
|
||||||
this.bbox = null;
|
this.bbox = null;
|
||||||
}
|
}
|
||||||
var cs = dict.get('ColorSpace', 'CS');
|
var cs = dict.get("ColorSpace", "CS");
|
||||||
cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
|
cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
|
||||||
this.cs = cs;
|
this.cs = cs;
|
||||||
this.background = dict.has('Background') ?
|
this.background = dict.has("Background")
|
||||||
cs.getRgb(dict.get('Background'), 0) : null;
|
? cs.getRgb(dict.get("Background"), 0)
|
||||||
|
: null;
|
||||||
|
|
||||||
var fnObj = dict.get('Function');
|
var fnObj = dict.get("Function");
|
||||||
var fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
|
var fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
|
||||||
|
|
||||||
this.coords = [];
|
this.coords = [];
|
||||||
@ -753,10 +857,10 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
this.figures = [];
|
this.figures = [];
|
||||||
|
|
||||||
var decodeContext = {
|
var decodeContext = {
|
||||||
bitsPerCoordinate: dict.get('BitsPerCoordinate'),
|
bitsPerCoordinate: dict.get("BitsPerCoordinate"),
|
||||||
bitsPerComponent: dict.get('BitsPerComponent'),
|
bitsPerComponent: dict.get("BitsPerComponent"),
|
||||||
bitsPerFlag: dict.get('BitsPerFlag'),
|
bitsPerFlag: dict.get("BitsPerFlag"),
|
||||||
decode: dict.getArray('Decode'),
|
decode: dict.getArray("Decode"),
|
||||||
colorFn: fn,
|
colorFn: fn,
|
||||||
colorSpace: cs,
|
colorSpace: cs,
|
||||||
numComps: fn ? 1 : cs.numComps,
|
numComps: fn ? 1 : cs.numComps,
|
||||||
@ -769,9 +873,9 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
decodeType4Shading(this, reader);
|
decodeType4Shading(this, reader);
|
||||||
break;
|
break;
|
||||||
case ShadingType.LATTICE_FORM_MESH:
|
case ShadingType.LATTICE_FORM_MESH:
|
||||||
var verticesPerRow = dict.get('VerticesPerRow') | 0;
|
var verticesPerRow = dict.get("VerticesPerRow") | 0;
|
||||||
if (verticesPerRow < 2) {
|
if (verticesPerRow < 2) {
|
||||||
throw new FormatError('Invalid VerticesPerRow');
|
throw new FormatError("Invalid VerticesPerRow");
|
||||||
}
|
}
|
||||||
decodeType5Shading(this, reader, verticesPerRow);
|
decodeType5Shading(this, reader, verticesPerRow);
|
||||||
break;
|
break;
|
||||||
@ -784,7 +888,7 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
patchMesh = true;
|
patchMesh = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
unreachable('Unsupported mesh type.');
|
unreachable("Unsupported mesh type.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,8 +907,17 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
|
|
||||||
Mesh.prototype = {
|
Mesh.prototype = {
|
||||||
getIR: function Mesh_getIR() {
|
getIR: function Mesh_getIR() {
|
||||||
return ['Mesh', this.shadingType, this.coords, this.colors, this.figures,
|
return [
|
||||||
this.bounds, this.matrix, this.bbox, this.background];
|
"Mesh",
|
||||||
|
this.shadingType,
|
||||||
|
this.coords,
|
||||||
|
this.colors,
|
||||||
|
this.figures,
|
||||||
|
this.bounds,
|
||||||
|
this.matrix,
|
||||||
|
this.bbox,
|
||||||
|
this.background,
|
||||||
|
];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -813,38 +926,42 @@ Shadings.Mesh = (function MeshClosure() {
|
|||||||
|
|
||||||
Shadings.Dummy = (function DummyClosure() {
|
Shadings.Dummy = (function DummyClosure() {
|
||||||
function Dummy() {
|
function Dummy() {
|
||||||
this.type = 'Pattern';
|
this.type = "Pattern";
|
||||||
}
|
}
|
||||||
|
|
||||||
Dummy.prototype = {
|
Dummy.prototype = {
|
||||||
getIR: function Dummy_getIR() {
|
getIR: function Dummy_getIR() {
|
||||||
return ['Dummy'];
|
return ["Dummy"];
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return Dummy;
|
return Dummy;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
function getTilingPatternIR(operatorList, dict, args) {
|
function getTilingPatternIR(operatorList, dict, args) {
|
||||||
let matrix = dict.getArray('Matrix');
|
let matrix = dict.getArray("Matrix");
|
||||||
let bbox = Util.normalizeRect(dict.getArray('BBox'));
|
let bbox = Util.normalizeRect(dict.getArray("BBox"));
|
||||||
let xstep = dict.get('XStep');
|
let xstep = dict.get("XStep");
|
||||||
let ystep = dict.get('YStep');
|
let ystep = dict.get("YStep");
|
||||||
let paintType = dict.get('PaintType');
|
let paintType = dict.get("PaintType");
|
||||||
let tilingType = dict.get('TilingType');
|
let tilingType = dict.get("TilingType");
|
||||||
|
|
||||||
// Ensure that the pattern has a non-zero width and height, to prevent errors
|
// Ensure that the pattern has a non-zero width and height, to prevent errors
|
||||||
// in `pattern_helper.js` (fixes issue8330.pdf).
|
// in `pattern_helper.js` (fixes issue8330.pdf).
|
||||||
if ((bbox[2] - bbox[0]) === 0 || (bbox[3] - bbox[1]) === 0) {
|
if (bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) {
|
||||||
throw new FormatError(`Invalid getTilingPatternIR /BBox array: [${bbox}].`);
|
throw new FormatError(`Invalid getTilingPatternIR /BBox array: [${bbox}].`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep,
|
"TilingPattern",
|
||||||
paintType, tilingType
|
args,
|
||||||
|
operatorList,
|
||||||
|
matrix,
|
||||||
|
bbox,
|
||||||
|
xstep,
|
||||||
|
ystep,
|
||||||
|
paintType,
|
||||||
|
tilingType,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { Pattern, getTilingPatternIR };
|
||||||
Pattern,
|
|
||||||
getTilingPatternIR,
|
|
||||||
};
|
|
||||||
|
@ -14,17 +14,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createValidAbsoluteUrl, shadow, unreachable, warn
|
createValidAbsoluteUrl,
|
||||||
} from '../shared/util';
|
shadow,
|
||||||
import { ChunkedStreamManager } from './chunked_stream';
|
unreachable,
|
||||||
import { MissingDataException } from './core_utils';
|
warn,
|
||||||
import { PDFDocument } from './document';
|
} from "../shared/util";
|
||||||
import { Stream } from './stream';
|
import { ChunkedStreamManager } from "./chunked_stream";
|
||||||
|
import { MissingDataException } from "./core_utils";
|
||||||
|
import { PDFDocument } from "./document";
|
||||||
|
import { Stream } from "./stream";
|
||||||
|
|
||||||
class BasePdfManager {
|
class BasePdfManager {
|
||||||
constructor() {
|
constructor() {
|
||||||
if (this.constructor === BasePdfManager) {
|
if (this.constructor === BasePdfManager) {
|
||||||
unreachable('Cannot initialize BasePdfManager.');
|
unreachable("Cannot initialize BasePdfManager.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,11 +49,11 @@ class BasePdfManager {
|
|||||||
warn(`Invalid absolute docBaseUrl: "${this._docBaseUrl}".`);
|
warn(`Invalid absolute docBaseUrl: "${this._docBaseUrl}".`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shadow(this, 'docBaseUrl', docBaseUrl);
|
return shadow(this, "docBaseUrl", docBaseUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoadedStream() {
|
onLoadedStream() {
|
||||||
unreachable('Abstract method `onLoadedStream` called');
|
unreachable("Abstract method `onLoadedStream` called");
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureDoc(prop, args) {
|
ensureDoc(prop, args) {
|
||||||
@ -78,19 +81,19 @@ class BasePdfManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async ensure(obj, prop, args) {
|
async ensure(obj, prop, args) {
|
||||||
unreachable('Abstract method `ensure` called');
|
unreachable("Abstract method `ensure` called");
|
||||||
}
|
}
|
||||||
|
|
||||||
requestRange(begin, end) {
|
requestRange(begin, end) {
|
||||||
unreachable('Abstract method `requestRange` called');
|
unreachable("Abstract method `requestRange` called");
|
||||||
}
|
}
|
||||||
|
|
||||||
requestLoadedStream() {
|
requestLoadedStream() {
|
||||||
unreachable('Abstract method `requestLoadedStream` called');
|
unreachable("Abstract method `requestLoadedStream` called");
|
||||||
}
|
}
|
||||||
|
|
||||||
sendProgressiveData(chunk) {
|
sendProgressiveData(chunk) {
|
||||||
unreachable('Abstract method `sendProgressiveData` called');
|
unreachable("Abstract method `sendProgressiveData` called");
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePassword(password) {
|
updatePassword(password) {
|
||||||
@ -98,7 +101,7 @@ class BasePdfManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
terminate(reason) {
|
terminate(reason) {
|
||||||
unreachable('Abstract method `terminate` called');
|
unreachable("Abstract method `terminate` called");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +121,7 @@ class LocalPdfManager extends BasePdfManager {
|
|||||||
|
|
||||||
async ensure(obj, prop, args) {
|
async ensure(obj, prop, args) {
|
||||||
const value = obj[prop];
|
const value = obj[prop];
|
||||||
if (typeof value === 'function') {
|
if (typeof value === "function") {
|
||||||
return value.apply(obj, args);
|
return value.apply(obj, args);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
@ -159,7 +162,7 @@ class NetworkPdfManager extends BasePdfManager {
|
|||||||
async ensure(obj, prop, args) {
|
async ensure(obj, prop, args) {
|
||||||
try {
|
try {
|
||||||
const value = obj[prop];
|
const value = obj[prop];
|
||||||
if (typeof value === 'function') {
|
if (typeof value === "function") {
|
||||||
return value.apply(obj, args);
|
return value.apply(obj, args);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
@ -181,7 +184,7 @@ class NetworkPdfManager extends BasePdfManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendProgressiveData(chunk) {
|
sendProgressiveData(chunk) {
|
||||||
this.streamManager.onReceiveData({ chunk, });
|
this.streamManager.onReceiveData({ chunk });
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoadedStream() {
|
onLoadedStream() {
|
||||||
@ -193,7 +196,4 @@ class NetworkPdfManager extends BasePdfManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { LocalPdfManager, NetworkPdfManager };
|
||||||
LocalPdfManager,
|
|
||||||
NetworkPdfManager,
|
|
||||||
};
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
/* uses XRef */
|
/* uses XRef */
|
||||||
|
|
||||||
import { assert } from '../shared/util';
|
import { assert } from "../shared/util";
|
||||||
|
|
||||||
var EOF = {};
|
var EOF = {};
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ var Name = (function NameClosure() {
|
|||||||
|
|
||||||
Name.get = function Name_get(name) {
|
Name.get = function Name_get(name) {
|
||||||
var nameValue = nameCache[name];
|
var nameValue = nameCache[name];
|
||||||
return (nameValue ? nameValue : (nameCache[name] = new Name(name)));
|
return nameValue ? nameValue : (nameCache[name] = new Name(name));
|
||||||
};
|
};
|
||||||
|
|
||||||
Name._clearCache = function() {
|
Name._clearCache = function() {
|
||||||
@ -50,7 +50,7 @@ var Cmd = (function CmdClosure() {
|
|||||||
|
|
||||||
Cmd.get = function Cmd_get(cmd) {
|
Cmd.get = function Cmd_get(cmd) {
|
||||||
var cmdValue = cmdCache[cmd];
|
var cmdValue = cmdCache[cmd];
|
||||||
return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd)));
|
return cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd));
|
||||||
};
|
};
|
||||||
|
|
||||||
Cmd._clearCache = function() {
|
Cmd._clearCache = function() {
|
||||||
@ -193,9 +193,9 @@ var Ref = (function RefClosure() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ref.get = function(num, gen) {
|
Ref.get = function(num, gen) {
|
||||||
const key = (gen === 0 ? `${num}R` : `${num}R${gen}`);
|
const key = gen === 0 ? `${num}R` : `${num}R${gen}`;
|
||||||
const refValue = refCache[key];
|
const refValue = refCache[key];
|
||||||
return (refValue ? refValue : (refCache[key] = new Ref(num, gen)));
|
return refValue ? refValue : (refCache[key] = new Ref(num, gen));
|
||||||
};
|
};
|
||||||
|
|
||||||
Ref._clearCache = function() {
|
Ref._clearCache = function() {
|
||||||
@ -266,7 +266,7 @@ var RefSetCache = (function RefSetCacheClosure() {
|
|||||||
})();
|
})();
|
||||||
|
|
||||||
function isEOF(v) {
|
function isEOF(v) {
|
||||||
return (v === EOF);
|
return v === EOF;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isName(v, name) {
|
function isName(v, name) {
|
||||||
@ -278,8 +278,9 @@ function isCmd(v, cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isDict(v, type) {
|
function isDict(v, type) {
|
||||||
return v instanceof Dict &&
|
return (
|
||||||
(type === undefined || isName(v.get('Type'), type));
|
v instanceof Dict && (type === undefined || isName(v.get("Type"), type))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRef(v) {
|
function isRef(v) {
|
||||||
@ -287,16 +288,20 @@ function isRef(v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isRefsEqual(v1, v2) {
|
function isRefsEqual(v1, v2) {
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
assert(v1 instanceof Ref && v2 instanceof Ref,
|
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||||
'isRefsEqual: Both parameters should be `Ref`s.');
|
) {
|
||||||
|
assert(
|
||||||
|
v1 instanceof Ref && v2 instanceof Ref,
|
||||||
|
"isRefsEqual: Both parameters should be `Ref`s."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return v1.num === v2.num && v1.gen === v2.gen;
|
return v1.num === v2.num && v1.gen === v2.gen;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isStream(v) {
|
function isStream(v) {
|
||||||
return typeof v === 'object' && v !== null && v.getBytes !== undefined;
|
return typeof v === "object" && v !== null && v.getBytes !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearPrimitiveCaches() {
|
function clearPrimitiveCaches() {
|
||||||
|
@ -14,8 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import { FormatError, isSpace, shadow } from '../shared/util';
|
import { FormatError, isSpace, shadow } from "../shared/util";
|
||||||
import { EOF } from './primitives';
|
import { EOF } from "./primitives";
|
||||||
|
|
||||||
class PostScriptParser {
|
class PostScriptParser {
|
||||||
constructor(lexer) {
|
constructor(lexer) {
|
||||||
@ -43,7 +43,8 @@ class PostScriptParser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
throw new FormatError(
|
throw new FormatError(
|
||||||
`Unexpected symbol: found ${this.token.type} expected ${type}.`);
|
`Unexpected symbol: found ${this.token.type} expected ${type}.`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
parse() {
|
parse() {
|
||||||
@ -79,7 +80,7 @@ class PostScriptParser {
|
|||||||
// The true block is right after the 'if' so it just falls through on true
|
// The true block is right after the 'if' so it just falls through on true
|
||||||
// else it jumps and skips the true block.
|
// else it jumps and skips the true block.
|
||||||
this.operators[conditionLocation] = this.operators.length;
|
this.operators[conditionLocation] = this.operators.length;
|
||||||
this.operators[conditionLocation + 1] = 'jz';
|
this.operators[conditionLocation + 1] = "jz";
|
||||||
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
|
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
|
||||||
const jumpLocation = this.operators.length;
|
const jumpLocation = this.operators.length;
|
||||||
this.operators.push(null, null);
|
this.operators.push(null, null);
|
||||||
@ -89,12 +90,12 @@ class PostScriptParser {
|
|||||||
this.expect(PostScriptTokenTypes.IFELSE);
|
this.expect(PostScriptTokenTypes.IFELSE);
|
||||||
// The jump is added at the end of the true block to skip the false block.
|
// The jump is added at the end of the true block to skip the false block.
|
||||||
this.operators[jumpLocation] = this.operators.length;
|
this.operators[jumpLocation] = this.operators.length;
|
||||||
this.operators[jumpLocation + 1] = 'j';
|
this.operators[jumpLocation + 1] = "j";
|
||||||
|
|
||||||
this.operators[conditionLocation] = endOfTrue;
|
this.operators[conditionLocation] = endOfTrue;
|
||||||
this.operators[conditionLocation + 1] = 'jz';
|
this.operators[conditionLocation + 1] = "jz";
|
||||||
} else {
|
} else {
|
||||||
throw new FormatError('PS Function: error parsing conditional.');
|
throw new FormatError("PS Function: error parsing conditional.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,28 +123,42 @@ const PostScriptToken = (function PostScriptTokenClosure() {
|
|||||||
if (opValue) {
|
if (opValue) {
|
||||||
return opValue;
|
return opValue;
|
||||||
}
|
}
|
||||||
return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR,
|
return (opCache[op] = new PostScriptToken(
|
||||||
op);
|
PostScriptTokenTypes.OPERATOR,
|
||||||
|
op
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
static get LBRACE() {
|
static get LBRACE() {
|
||||||
return shadow(this, 'LBRACE',
|
return shadow(
|
||||||
new PostScriptToken(PostScriptTokenTypes.LBRACE, '{'));
|
this,
|
||||||
|
"LBRACE",
|
||||||
|
new PostScriptToken(PostScriptTokenTypes.LBRACE, "{")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get RBRACE() {
|
static get RBRACE() {
|
||||||
return shadow(this, 'RBRACE',
|
return shadow(
|
||||||
new PostScriptToken(PostScriptTokenTypes.RBRACE, '}'));
|
this,
|
||||||
|
"RBRACE",
|
||||||
|
new PostScriptToken(PostScriptTokenTypes.RBRACE, "}")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get IF() {
|
static get IF() {
|
||||||
return shadow(this, 'IF',
|
return shadow(
|
||||||
new PostScriptToken(PostScriptTokenTypes.IF, 'IF'));
|
this,
|
||||||
|
"IF",
|
||||||
|
new PostScriptToken(PostScriptTokenTypes.IF, "IF")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get IFELSE() {
|
static get IFELSE() {
|
||||||
return shadow(this, 'IFELSE',
|
return shadow(
|
||||||
new PostScriptToken(PostScriptTokenTypes.IFELSE, 'IFELSE'));
|
this,
|
||||||
|
"IFELSE",
|
||||||
|
new PostScriptToken(PostScriptTokenTypes.IFELSE, "IFELSE")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return PostScriptToken;
|
return PostScriptToken;
|
||||||
@ -172,10 +187,11 @@ class PostScriptLexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (comment) {
|
if (comment) {
|
||||||
if (ch === 0x0A || ch === 0x0D) {
|
if (ch === 0x0a || ch === 0x0d) {
|
||||||
comment = false;
|
comment = false;
|
||||||
}
|
}
|
||||||
} else if (ch === 0x25) { // '%'
|
} else if (ch === 0x25) {
|
||||||
|
// '%'
|
||||||
comment = true;
|
comment = true;
|
||||||
} else if (!isSpace(ch)) {
|
} else if (!isSpace(ch)) {
|
||||||
break;
|
break;
|
||||||
@ -183,15 +199,27 @@ class PostScriptLexer {
|
|||||||
ch = this.nextChar();
|
ch = this.nextChar();
|
||||||
}
|
}
|
||||||
switch (ch | 0) {
|
switch (ch | 0) {
|
||||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
|
case 0x30:
|
||||||
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
|
case 0x31:
|
||||||
case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
|
case 0x32:
|
||||||
return new PostScriptToken(PostScriptTokenTypes.NUMBER,
|
case 0x33:
|
||||||
this.getNumber());
|
case 0x34: // '0'-'4'
|
||||||
case 0x7B: // '{'
|
case 0x35:
|
||||||
|
case 0x36:
|
||||||
|
case 0x37:
|
||||||
|
case 0x38:
|
||||||
|
case 0x39: // '5'-'9'
|
||||||
|
case 0x2b:
|
||||||
|
case 0x2d:
|
||||||
|
case 0x2e: // '+', '-', '.'
|
||||||
|
return new PostScriptToken(
|
||||||
|
PostScriptTokenTypes.NUMBER,
|
||||||
|
this.getNumber()
|
||||||
|
);
|
||||||
|
case 0x7b: // '{'
|
||||||
this.nextChar();
|
this.nextChar();
|
||||||
return PostScriptToken.LBRACE;
|
return PostScriptToken.LBRACE;
|
||||||
case 0x7D: // '}'
|
case 0x7d: // '}'
|
||||||
this.nextChar();
|
this.nextChar();
|
||||||
return PostScriptToken.RBRACE;
|
return PostScriptToken.RBRACE;
|
||||||
}
|
}
|
||||||
@ -200,15 +228,17 @@ class PostScriptLexer {
|
|||||||
strBuf.length = 0;
|
strBuf.length = 0;
|
||||||
strBuf[0] = String.fromCharCode(ch);
|
strBuf[0] = String.fromCharCode(ch);
|
||||||
|
|
||||||
while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
|
while (
|
||||||
((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
|
(ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
|
||||||
|
((ch >= 0x41 && ch <= 0x5a) || (ch >= 0x61 && ch <= 0x7a))
|
||||||
|
) {
|
||||||
strBuf.push(String.fromCharCode(ch));
|
strBuf.push(String.fromCharCode(ch));
|
||||||
}
|
}
|
||||||
const str = strBuf.join('');
|
const str = strBuf.join("");
|
||||||
switch (str.toLowerCase()) {
|
switch (str.toLowerCase()) {
|
||||||
case 'if':
|
case "if":
|
||||||
return PostScriptToken.IF;
|
return PostScriptToken.IF;
|
||||||
case 'ifelse':
|
case "ifelse":
|
||||||
return PostScriptToken.IFELSE;
|
return PostScriptToken.IFELSE;
|
||||||
default:
|
default:
|
||||||
return PostScriptToken.getOperator(str);
|
return PostScriptToken.getOperator(str);
|
||||||
@ -222,14 +252,18 @@ class PostScriptLexer {
|
|||||||
strBuf[0] = String.fromCharCode(ch);
|
strBuf[0] = String.fromCharCode(ch);
|
||||||
|
|
||||||
while ((ch = this.nextChar()) >= 0) {
|
while ((ch = this.nextChar()) >= 0) {
|
||||||
if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
|
if (
|
||||||
ch === 0x2D || ch === 0x2E) { // '-', '.'
|
(ch >= 0x30 && ch <= 0x39) || // '0'-'9'
|
||||||
|
ch === 0x2d ||
|
||||||
|
ch === 0x2e
|
||||||
|
) {
|
||||||
|
// '-', '.'
|
||||||
strBuf.push(String.fromCharCode(ch));
|
strBuf.push(String.fromCharCode(ch));
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const value = parseFloat(strBuf.join(''));
|
const value = parseFloat(strBuf.join(""));
|
||||||
if (isNaN(value)) {
|
if (isNaN(value)) {
|
||||||
throw new FormatError(`Invalid floating point number: ${value}`);
|
throw new FormatError(`Invalid floating point number: ${value}`);
|
||||||
}
|
}
|
||||||
@ -237,7 +271,4 @@ class PostScriptLexer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { PostScriptLexer, PostScriptParser };
|
||||||
PostScriptLexer,
|
|
||||||
PostScriptParser,
|
|
||||||
};
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,17 +20,22 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FormatError, isSpace, stringToBytes, unreachable
|
FormatError,
|
||||||
} from '../shared/util';
|
isSpace,
|
||||||
import { isDict } from './primitives';
|
stringToBytes,
|
||||||
|
unreachable,
|
||||||
|
} from "../shared/util";
|
||||||
|
import { isDict } from "./primitives";
|
||||||
|
|
||||||
var Stream = (function StreamClosure() {
|
var Stream = (function StreamClosure() {
|
||||||
function Stream(arrayBuffer, start, length, dict) {
|
function Stream(arrayBuffer, start, length, dict) {
|
||||||
this.bytes = (arrayBuffer instanceof Uint8Array ?
|
this.bytes =
|
||||||
arrayBuffer : new Uint8Array(arrayBuffer));
|
arrayBuffer instanceof Uint8Array
|
||||||
|
? arrayBuffer
|
||||||
|
: new Uint8Array(arrayBuffer);
|
||||||
this.start = start || 0;
|
this.start = start || 0;
|
||||||
this.pos = this.start;
|
this.pos = this.start;
|
||||||
this.end = (start + length) || this.bytes.length;
|
this.end = start + length || this.bytes.length;
|
||||||
this.dict = dict;
|
this.dict = dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,7 +78,7 @@ var Stream = (function StreamClosure() {
|
|||||||
if (!length) {
|
if (!length) {
|
||||||
let subarray = bytes.subarray(pos, strEnd);
|
let subarray = bytes.subarray(pos, strEnd);
|
||||||
// `this.bytes` is always a `Uint8Array` here.
|
// `this.bytes` is always a `Uint8Array` here.
|
||||||
return (forceClamped ? new Uint8ClampedArray(subarray) : subarray);
|
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
|
||||||
}
|
}
|
||||||
var end = pos + length;
|
var end = pos + length;
|
||||||
if (end > strEnd) {
|
if (end > strEnd) {
|
||||||
@ -82,7 +87,7 @@ var Stream = (function StreamClosure() {
|
|||||||
this.pos = end;
|
this.pos = end;
|
||||||
let subarray = bytes.subarray(pos, end);
|
let subarray = bytes.subarray(pos, end);
|
||||||
// `this.bytes` is always a `Uint8Array` here.
|
// `this.bytes` is always a `Uint8Array` here.
|
||||||
return (forceClamped ? new Uint8ClampedArray(subarray) : subarray);
|
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
|
||||||
},
|
},
|
||||||
peekByte: function Stream_peekByte() {
|
peekByte: function Stream_peekByte() {
|
||||||
var peekedByte = this.getByte();
|
var peekedByte = this.getByte();
|
||||||
@ -208,7 +213,8 @@ var DecodeStream = (function DecodeStreamClosure() {
|
|||||||
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
|
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
|
||||||
},
|
},
|
||||||
getBytes(length, forceClamped = false) {
|
getBytes(length, forceClamped = false) {
|
||||||
var end, pos = this.pos;
|
var end,
|
||||||
|
pos = this.pos;
|
||||||
|
|
||||||
if (length) {
|
if (length) {
|
||||||
this.ensureBuffer(pos + length);
|
this.ensureBuffer(pos + length);
|
||||||
@ -231,8 +237,9 @@ var DecodeStream = (function DecodeStreamClosure() {
|
|||||||
this.pos = end;
|
this.pos = end;
|
||||||
let subarray = this.buffer.subarray(pos, end);
|
let subarray = this.buffer.subarray(pos, end);
|
||||||
// `this.buffer` is either a `Uint8Array` or `Uint8ClampedArray` here.
|
// `this.buffer` is either a `Uint8Array` or `Uint8ClampedArray` here.
|
||||||
return (forceClamped && !(subarray instanceof Uint8ClampedArray) ?
|
return forceClamped && !(subarray instanceof Uint8ClampedArray)
|
||||||
new Uint8ClampedArray(subarray) : subarray);
|
? new Uint8ClampedArray(subarray)
|
||||||
|
: subarray;
|
||||||
},
|
},
|
||||||
peekByte: function DecodeStream_peekByte() {
|
peekByte: function DecodeStream_peekByte() {
|
||||||
var peekedByte = this.getByte();
|
var peekedByte = this.getByte();
|
||||||
@ -255,7 +262,7 @@ var DecodeStream = (function DecodeStreamClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
getByteRange(begin, end) {
|
getByteRange(begin, end) {
|
||||||
unreachable('Should not call DecodeStream.getByteRange');
|
unreachable("Should not call DecodeStream.getByteRange");
|
||||||
},
|
},
|
||||||
|
|
||||||
skip: function DecodeStream_skip(n) {
|
skip: function DecodeStream_skip(n) {
|
||||||
@ -296,9 +303,7 @@ var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
|
|||||||
|
|
||||||
StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
|
StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
|
||||||
|
|
||||||
StreamsSequenceStream.prototype.readBlock =
|
StreamsSequenceStream.prototype.readBlock = function streamSequenceStreamReadBlock() {
|
||||||
function streamSequenceStreamReadBlock() {
|
|
||||||
|
|
||||||
var streams = this.streams;
|
var streams = this.streams;
|
||||||
if (streams.length === 0) {
|
if (streams.length === 0) {
|
||||||
this.eof = true;
|
this.eof = true;
|
||||||
@ -313,9 +318,7 @@ var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
|
|||||||
this.bufferLength = newLength;
|
this.bufferLength = newLength;
|
||||||
};
|
};
|
||||||
|
|
||||||
StreamsSequenceStream.prototype.getBaseStreams =
|
StreamsSequenceStream.prototype.getBaseStreams = function StreamsSequenceStream_getBaseStreams() {
|
||||||
function StreamsSequenceStream_getBaseStreams() {
|
|
||||||
|
|
||||||
var baseStreams = [];
|
var baseStreams = [];
|
||||||
for (var i = 0, ii = this.streams.length; i < ii; i++) {
|
for (var i = 0, ii = this.streams.length; i < ii; i++) {
|
||||||
var stream = this.streams[i];
|
var stream = this.streams[i];
|
||||||
@ -434,19 +437,18 @@ var FlateStream = (function FlateStreamClosure() {
|
|||||||
var cmf = str.getByte();
|
var cmf = str.getByte();
|
||||||
var flg = str.getByte();
|
var flg = str.getByte();
|
||||||
if (cmf === -1 || flg === -1) {
|
if (cmf === -1 || flg === -1) {
|
||||||
throw new FormatError(
|
throw new FormatError(`Invalid header in flate stream: ${cmf}, ${flg}`);
|
||||||
`Invalid header in flate stream: ${cmf}, ${flg}`);
|
|
||||||
}
|
}
|
||||||
if ((cmf & 0x0f) !== 0x08) {
|
if ((cmf & 0x0f) !== 0x08) {
|
||||||
throw new FormatError(
|
throw new FormatError(
|
||||||
`Unknown compression method in flate stream: ${cmf}, ${flg}`);
|
`Unknown compression method in flate stream: ${cmf}, ${flg}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if ((((cmf << 8) + flg) % 31) !== 0) {
|
if (((cmf << 8) + flg) % 31 !== 0) {
|
||||||
throw new FormatError(`Bad FCHECK in flate stream: ${cmf}, ${flg}`);
|
throw new FormatError(`Bad FCHECK in flate stream: ${cmf}, ${flg}`);
|
||||||
}
|
}
|
||||||
if (flg & 0x20) {
|
if (flg & 0x20) {
|
||||||
throw new FormatError(
|
throw new FormatError(`FDICT bit set in flate stream: ${cmf}, ${flg}`);
|
||||||
`FDICT bit set in flate stream: ${cmf}, ${flg}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.codeSize = 0;
|
this.codeSize = 0;
|
||||||
@ -465,7 +467,7 @@ var FlateStream = (function FlateStreamClosure() {
|
|||||||
var b;
|
var b;
|
||||||
while (codeSize < bits) {
|
while (codeSize < bits) {
|
||||||
if ((b = str.getByte()) === -1) {
|
if ((b = str.getByte()) === -1) {
|
||||||
throw new FormatError('Bad encoding in flate stream');
|
throw new FormatError("Bad encoding in flate stream");
|
||||||
}
|
}
|
||||||
codeBuf |= b << codeSize;
|
codeBuf |= b << codeSize;
|
||||||
codeSize += 8;
|
codeSize += 8;
|
||||||
@ -491,22 +493,23 @@ var FlateStream = (function FlateStreamClosure() {
|
|||||||
// codeSize < codeLen check below guards against incomplete codeVal.
|
// codeSize < codeLen check below guards against incomplete codeVal.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
codeBuf |= (b << codeSize);
|
codeBuf |= b << codeSize;
|
||||||
codeSize += 8;
|
codeSize += 8;
|
||||||
}
|
}
|
||||||
var code = codes[codeBuf & ((1 << maxLen) - 1)];
|
var code = codes[codeBuf & ((1 << maxLen) - 1)];
|
||||||
var codeLen = code >> 16;
|
var codeLen = code >> 16;
|
||||||
var codeVal = code & 0xffff;
|
var codeVal = code & 0xffff;
|
||||||
if (codeLen < 1 || codeSize < codeLen) {
|
if (codeLen < 1 || codeSize < codeLen) {
|
||||||
throw new FormatError('Bad encoding in flate stream');
|
throw new FormatError("Bad encoding in flate stream");
|
||||||
}
|
}
|
||||||
this.codeBuf = (codeBuf >> codeLen);
|
this.codeBuf = codeBuf >> codeLen;
|
||||||
this.codeSize = (codeSize - codeLen);
|
this.codeSize = codeSize - codeLen;
|
||||||
return codeVal;
|
return codeVal;
|
||||||
};
|
};
|
||||||
|
|
||||||
FlateStream.prototype.generateHuffmanTable =
|
FlateStream.prototype.generateHuffmanTable = function flateStreamGenerateHuffmanTable(
|
||||||
function flateStreamGenerateHuffmanTable(lengths) {
|
lengths
|
||||||
|
) {
|
||||||
var n = lengths.length;
|
var n = lengths.length;
|
||||||
|
|
||||||
// find max code length
|
// find max code length
|
||||||
@ -521,9 +524,11 @@ var FlateStream = (function FlateStreamClosure() {
|
|||||||
// build the table
|
// build the table
|
||||||
var size = 1 << maxLen;
|
var size = 1 << maxLen;
|
||||||
var codes = new Int32Array(size);
|
var codes = new Int32Array(size);
|
||||||
for (var len = 1, code = 0, skip = 2;
|
for (
|
||||||
|
var len = 1, code = 0, skip = 2;
|
||||||
len <= maxLen;
|
len <= maxLen;
|
||||||
++len, code <<= 1, skip <<= 1) {
|
++len, code <<= 1, skip <<= 1
|
||||||
|
) {
|
||||||
for (var val = 0; val < n; ++val) {
|
for (var val = 0; val < n; ++val) {
|
||||||
if (lengths[val] === len) {
|
if (lengths[val] === len) {
|
||||||
// bit-reverse the code
|
// bit-reverse the code
|
||||||
@ -556,36 +561,36 @@ var FlateStream = (function FlateStreamClosure() {
|
|||||||
}
|
}
|
||||||
hdr >>= 1;
|
hdr >>= 1;
|
||||||
|
|
||||||
if (hdr === 0) { // uncompressed block
|
if (hdr === 0) {
|
||||||
|
// uncompressed block
|
||||||
var b;
|
var b;
|
||||||
|
|
||||||
if ((b = str.getByte()) === -1) {
|
if ((b = str.getByte()) === -1) {
|
||||||
throw new FormatError('Bad block header in flate stream');
|
throw new FormatError("Bad block header in flate stream");
|
||||||
}
|
}
|
||||||
var blockLen = b;
|
var blockLen = b;
|
||||||
if ((b = str.getByte()) === -1) {
|
if ((b = str.getByte()) === -1) {
|
||||||
throw new FormatError('Bad block header in flate stream');
|
throw new FormatError("Bad block header in flate stream");
|
||||||
}
|
}
|
||||||
blockLen |= (b << 8);
|
blockLen |= b << 8;
|
||||||
if ((b = str.getByte()) === -1) {
|
if ((b = str.getByte()) === -1) {
|
||||||
throw new FormatError('Bad block header in flate stream');
|
throw new FormatError("Bad block header in flate stream");
|
||||||
}
|
}
|
||||||
var check = b;
|
var check = b;
|
||||||
if ((b = str.getByte()) === -1) {
|
if ((b = str.getByte()) === -1) {
|
||||||
throw new FormatError('Bad block header in flate stream');
|
throw new FormatError("Bad block header in flate stream");
|
||||||
}
|
}
|
||||||
check |= (b << 8);
|
check |= b << 8;
|
||||||
if (check !== (~blockLen & 0xffff) &&
|
if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) {
|
||||||
(blockLen !== 0 || check !== 0)) {
|
|
||||||
// Ignoring error for bad "empty" block (see issue 1277)
|
// Ignoring error for bad "empty" block (see issue 1277)
|
||||||
throw new FormatError(
|
throw new FormatError("Bad uncompressed block length in flate stream");
|
||||||
'Bad uncompressed block length in flate stream');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.codeBuf = 0;
|
this.codeBuf = 0;
|
||||||
this.codeSize = 0;
|
this.codeSize = 0;
|
||||||
|
|
||||||
const bufferLength = this.bufferLength, end = bufferLength + blockLen;
|
const bufferLength = this.bufferLength,
|
||||||
|
end = bufferLength + blockLen;
|
||||||
buffer = this.ensureBuffer(end);
|
buffer = this.ensureBuffer(end);
|
||||||
this.bufferLength = end;
|
this.bufferLength = end;
|
||||||
|
|
||||||
@ -605,10 +610,12 @@ var FlateStream = (function FlateStreamClosure() {
|
|||||||
|
|
||||||
var litCodeTable;
|
var litCodeTable;
|
||||||
var distCodeTable;
|
var distCodeTable;
|
||||||
if (hdr === 1) { // compressed block, fixed codes
|
if (hdr === 1) {
|
||||||
|
// compressed block, fixed codes
|
||||||
litCodeTable = fixedLitCodeTab;
|
litCodeTable = fixedLitCodeTab;
|
||||||
distCodeTable = fixedDistCodeTab;
|
distCodeTable = fixedDistCodeTab;
|
||||||
} else if (hdr === 2) { // compressed block, dynamic codes
|
} else if (hdr === 2) {
|
||||||
|
// compressed block, dynamic codes
|
||||||
var numLitCodes = this.getBits(5) + 257;
|
var numLitCodes = this.getBits(5) + 257;
|
||||||
var numDistCodes = this.getBits(5) + 1;
|
var numDistCodes = this.getBits(5) + 1;
|
||||||
var numCodeLenCodes = this.getBits(4) + 4;
|
var numCodeLenCodes = this.getBits(4) + 4;
|
||||||
@ -631,11 +638,17 @@ var FlateStream = (function FlateStreamClosure() {
|
|||||||
while (i < codes) {
|
while (i < codes) {
|
||||||
var code = this.getCode(codeLenCodeTab);
|
var code = this.getCode(codeLenCodeTab);
|
||||||
if (code === 16) {
|
if (code === 16) {
|
||||||
bitsLength = 2; bitsOffset = 3; what = len;
|
bitsLength = 2;
|
||||||
|
bitsOffset = 3;
|
||||||
|
what = len;
|
||||||
} else if (code === 17) {
|
} else if (code === 17) {
|
||||||
bitsLength = 3; bitsOffset = 3; what = (len = 0);
|
bitsLength = 3;
|
||||||
|
bitsOffset = 3;
|
||||||
|
what = len = 0;
|
||||||
} else if (code === 18) {
|
} else if (code === 18) {
|
||||||
bitsLength = 7; bitsOffset = 11; what = (len = 0);
|
bitsLength = 7;
|
||||||
|
bitsOffset = 11;
|
||||||
|
what = len = 0;
|
||||||
} else {
|
} else {
|
||||||
codeLengths[i++] = len = code;
|
codeLengths[i++] = len = code;
|
||||||
continue;
|
continue;
|
||||||
@ -647,12 +660,14 @@ var FlateStream = (function FlateStreamClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
litCodeTable =
|
litCodeTable = this.generateHuffmanTable(
|
||||||
this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));
|
codeLengths.subarray(0, numLitCodes)
|
||||||
distCodeTable =
|
);
|
||||||
this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));
|
distCodeTable = this.generateHuffmanTable(
|
||||||
|
codeLengths.subarray(numLitCodes, codes)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
throw new FormatError('Unknown block type in flate stream');
|
throw new FormatError("Unknown block type in flate stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = this.buffer;
|
buffer = this.buffer;
|
||||||
@ -704,7 +719,7 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
if (!isDict(params)) {
|
if (!isDict(params)) {
|
||||||
return str; // no prediction
|
return str; // no prediction
|
||||||
}
|
}
|
||||||
var predictor = this.predictor = params.get('Predictor') || 1;
|
var predictor = (this.predictor = params.get("Predictor") || 1);
|
||||||
|
|
||||||
if (predictor <= 1) {
|
if (predictor <= 1) {
|
||||||
return str; // no prediction
|
return str; // no prediction
|
||||||
@ -722,9 +737,9 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
this.str = str;
|
this.str = str;
|
||||||
this.dict = str.dict;
|
this.dict = str.dict;
|
||||||
|
|
||||||
var colors = this.colors = params.get('Colors') || 1;
|
var colors = (this.colors = params.get("Colors") || 1);
|
||||||
var bits = this.bits = params.get('BitsPerComponent') || 8;
|
var bits = (this.bits = params.get("BitsPerComponent") || 8);
|
||||||
var columns = this.columns = params.get('Columns') || 1;
|
var columns = (this.columns = params.get("Columns") || 1);
|
||||||
|
|
||||||
this.pixBytes = (colors * bits + 7) >> 3;
|
this.pixBytes = (colors * bits + 7) >> 3;
|
||||||
this.rowBytes = (columns * colors * bits + 7) >> 3;
|
this.rowBytes = (columns * colors * bits + 7) >> 3;
|
||||||
@ -735,8 +750,7 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
|
|
||||||
PredictorStream.prototype = Object.create(DecodeStream.prototype);
|
PredictorStream.prototype = Object.create(DecodeStream.prototype);
|
||||||
|
|
||||||
PredictorStream.prototype.readBlockTiff =
|
PredictorStream.prototype.readBlockTiff = function predictorStreamReadBlockTiff() {
|
||||||
function predictorStreamReadBlockTiff() {
|
|
||||||
var rowBytes = this.rowBytes;
|
var rowBytes = this.rowBytes;
|
||||||
|
|
||||||
var bufferLength = this.bufferLength;
|
var bufferLength = this.bufferLength;
|
||||||
@ -751,8 +765,10 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var inbuf = 0, outbuf = 0;
|
var inbuf = 0,
|
||||||
var inbits = 0, outbits = 0;
|
outbuf = 0;
|
||||||
|
var inbits = 0,
|
||||||
|
outbits = 0;
|
||||||
var pos = bufferLength;
|
var pos = bufferLength;
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
@ -781,46 +797,46 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
buffer[pos++] = rawBytes[i];
|
buffer[pos++] = rawBytes[i];
|
||||||
}
|
}
|
||||||
for (; i < rowBytes; i += 2) {
|
for (; i < rowBytes; i += 2) {
|
||||||
var sum = ((rawBytes[i] & 0xFF) << 8) +
|
var sum =
|
||||||
(rawBytes[i + 1] & 0xFF) +
|
((rawBytes[i] & 0xff) << 8) +
|
||||||
((buffer[pos - bytesPerPixel] & 0xFF) << 8) +
|
(rawBytes[i + 1] & 0xff) +
|
||||||
(buffer[pos - bytesPerPixel + 1] & 0xFF);
|
((buffer[pos - bytesPerPixel] & 0xff) << 8) +
|
||||||
buffer[pos++] = ((sum >> 8) & 0xFF);
|
(buffer[pos - bytesPerPixel + 1] & 0xff);
|
||||||
buffer[pos++] = (sum & 0xFF);
|
buffer[pos++] = (sum >> 8) & 0xff;
|
||||||
|
buffer[pos++] = sum & 0xff;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var compArray = new Uint8Array(colors + 1);
|
var compArray = new Uint8Array(colors + 1);
|
||||||
var bitMask = (1 << bits) - 1;
|
var bitMask = (1 << bits) - 1;
|
||||||
var j = 0, k = bufferLength;
|
var j = 0,
|
||||||
|
k = bufferLength;
|
||||||
var columns = this.columns;
|
var columns = this.columns;
|
||||||
for (i = 0; i < columns; ++i) {
|
for (i = 0; i < columns; ++i) {
|
||||||
for (var kk = 0; kk < colors; ++kk) {
|
for (var kk = 0; kk < colors; ++kk) {
|
||||||
if (inbits < bits) {
|
if (inbits < bits) {
|
||||||
inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF);
|
inbuf = (inbuf << 8) | (rawBytes[j++] & 0xff);
|
||||||
inbits += 8;
|
inbits += 8;
|
||||||
}
|
}
|
||||||
compArray[kk] = (compArray[kk] +
|
compArray[kk] =
|
||||||
(inbuf >> (inbits - bits))) & bitMask;
|
(compArray[kk] + (inbuf >> (inbits - bits))) & bitMask;
|
||||||
inbits -= bits;
|
inbits -= bits;
|
||||||
outbuf = (outbuf << bits) | compArray[kk];
|
outbuf = (outbuf << bits) | compArray[kk];
|
||||||
outbits += bits;
|
outbits += bits;
|
||||||
if (outbits >= 8) {
|
if (outbits >= 8) {
|
||||||
buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF;
|
buffer[k++] = (outbuf >> (outbits - 8)) & 0xff;
|
||||||
outbits -= 8;
|
outbits -= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (outbits > 0) {
|
if (outbits > 0) {
|
||||||
buffer[k++] = (outbuf << (8 - outbits)) +
|
buffer[k++] =
|
||||||
(inbuf & ((1 << (8 - outbits)) - 1));
|
(outbuf << (8 - outbits)) + (inbuf & ((1 << (8 - outbits)) - 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.bufferLength += rowBytes;
|
this.bufferLength += rowBytes;
|
||||||
};
|
};
|
||||||
|
|
||||||
PredictorStream.prototype.readBlockPng =
|
PredictorStream.prototype.readBlockPng = function predictorStreamReadBlockPng() {
|
||||||
function predictorStreamReadBlockPng() {
|
|
||||||
|
|
||||||
var rowBytes = this.rowBytes;
|
var rowBytes = this.rowBytes;
|
||||||
var pixBytes = this.pixBytes;
|
var pixBytes = this.pixBytes;
|
||||||
|
|
||||||
@ -839,7 +855,10 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
prevRow = new Uint8Array(rowBytes);
|
prevRow = new Uint8Array(rowBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
var i, j = bufferLength, up, c;
|
var i,
|
||||||
|
j = bufferLength,
|
||||||
|
up,
|
||||||
|
c;
|
||||||
switch (predictor) {
|
switch (predictor) {
|
||||||
case 0:
|
case 0:
|
||||||
for (i = 0; i < rowBytes; ++i) {
|
for (i = 0; i < rowBytes; ++i) {
|
||||||
@ -851,13 +870,13 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
buffer[j++] = rawBytes[i];
|
buffer[j++] = rawBytes[i];
|
||||||
}
|
}
|
||||||
for (; i < rowBytes; ++i) {
|
for (; i < rowBytes; ++i) {
|
||||||
buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF;
|
buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xff;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
for (i = 0; i < rowBytes; ++i) {
|
for (i = 0; i < rowBytes; ++i) {
|
||||||
buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
|
buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xff;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
@ -865,8 +884,8 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
|
buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
|
||||||
}
|
}
|
||||||
for (; i < rowBytes; ++i) {
|
for (; i < rowBytes; ++i) {
|
||||||
buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) +
|
buffer[j] =
|
||||||
rawBytes[i]) & 0xFF;
|
(((prevRow[i] + buffer[j - pixBytes]) >> 1) + rawBytes[i]) & 0xff;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -950,7 +969,8 @@ var DecryptStream = (function DecryptStreamClosure() {
|
|||||||
chunk = decrypt(chunk, !hasMoreData);
|
chunk = decrypt(chunk, !hasMoreData);
|
||||||
|
|
||||||
var bufferLength = this.bufferLength;
|
var bufferLength = this.bufferLength;
|
||||||
var i, n = chunk.length;
|
var i,
|
||||||
|
n = chunk.length;
|
||||||
var buffer = this.ensureBuffer(bufferLength + n);
|
var buffer = this.ensureBuffer(bufferLength + n);
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
buffer[bufferLength++] = chunk[i];
|
buffer[bufferLength++] = chunk[i];
|
||||||
@ -978,8 +998,8 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
|
|||||||
Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
|
Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
|
||||||
|
|
||||||
Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
|
Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
|
||||||
var TILDA_CHAR = 0x7E; // '~'
|
var TILDA_CHAR = 0x7e; // '~'
|
||||||
var Z_LOWER_CHAR = 0x7A; // 'z'
|
var Z_LOWER_CHAR = 0x7a; // 'z'
|
||||||
var EOF = -1;
|
var EOF = -1;
|
||||||
|
|
||||||
var str = this.str;
|
var str = this.str;
|
||||||
@ -994,7 +1014,8 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bufferLength = this.bufferLength, buffer;
|
var bufferLength = this.bufferLength,
|
||||||
|
buffer;
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
// special code for z
|
// special code for z
|
||||||
@ -1035,7 +1056,7 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 3; i >= 0; --i) {
|
for (i = 3; i >= 0; --i) {
|
||||||
buffer[bufferLength + i] = t & 0xFF;
|
buffer[bufferLength + i] = t & 0xff;
|
||||||
t >>= 8;
|
t >>= 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1075,16 +1096,20 @@ var AsciiHexStream = (function AsciiHexStreamClosure() {
|
|||||||
|
|
||||||
var firstDigit = this.firstDigit;
|
var firstDigit = this.firstDigit;
|
||||||
for (var i = 0, ii = bytes.length; i < ii; i++) {
|
for (var i = 0, ii = bytes.length; i < ii; i++) {
|
||||||
var ch = bytes[i], digit;
|
var ch = bytes[i],
|
||||||
if (ch >= 0x30 && ch <= 0x39) { // '0'-'9'
|
digit;
|
||||||
digit = ch & 0x0F;
|
if (ch >= 0x30 && ch <= 0x39) {
|
||||||
|
// '0'-'9'
|
||||||
|
digit = ch & 0x0f;
|
||||||
} else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) {
|
} else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) {
|
||||||
// 'A'-'Z', 'a'-'z'
|
// 'A'-'Z', 'a'-'z'
|
||||||
digit = (ch & 0x0F) + 9;
|
digit = (ch & 0x0f) + 9;
|
||||||
} else if (ch === 0x3E) { // '>'
|
} else if (ch === 0x3e) {
|
||||||
|
// '>'
|
||||||
this.eof = true;
|
this.eof = true;
|
||||||
break;
|
break;
|
||||||
} else { // probably whitespace
|
} else {
|
||||||
|
// probably whitespace
|
||||||
continue; // ignoring
|
continue; // ignoring
|
||||||
}
|
}
|
||||||
if (firstDigit < 0) {
|
if (firstDigit < 0) {
|
||||||
@ -1096,7 +1121,7 @@ var AsciiHexStream = (function AsciiHexStreamClosure() {
|
|||||||
}
|
}
|
||||||
if (firstDigit >= 0 && this.eof) {
|
if (firstDigit >= 0 && this.eof) {
|
||||||
// incomplete byte
|
// incomplete byte
|
||||||
buffer[bufferLength++] = (firstDigit << 4);
|
buffer[bufferLength++] = firstDigit << 4;
|
||||||
firstDigit = -1;
|
firstDigit = -1;
|
||||||
}
|
}
|
||||||
this.firstDigit = firstDigit;
|
this.firstDigit = firstDigit;
|
||||||
@ -1194,7 +1219,7 @@ var LZWStream = (function LZWStreamClosure() {
|
|||||||
cachedData = (cachedData << 8) | c;
|
cachedData = (cachedData << 8) | c;
|
||||||
bitsCached += 8;
|
bitsCached += 8;
|
||||||
}
|
}
|
||||||
this.bitsCached = (bitsCached -= n);
|
this.bitsCached = bitsCached -= n;
|
||||||
this.cachedData = cachedData;
|
this.cachedData = cachedData;
|
||||||
this.lastCode = null;
|
this.lastCode = null;
|
||||||
return (cachedData >>> bitsCached) & ((1 << n) - 1);
|
return (cachedData >>> bitsCached) & ((1 << n) - 1);
|
||||||
@ -1202,7 +1227,8 @@ var LZWStream = (function LZWStreamClosure() {
|
|||||||
|
|
||||||
LZWStream.prototype.readBlock = function LZWStream_readBlock() {
|
LZWStream.prototype.readBlock = function LZWStream_readBlock() {
|
||||||
var blockSize = 512;
|
var blockSize = 512;
|
||||||
var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
|
var estimatedDecodedSize = blockSize * 2,
|
||||||
|
decodedSizeDelta = blockSize;
|
||||||
var i, j, q;
|
var i, j, q;
|
||||||
|
|
||||||
var lzwState = this.lzwState;
|
var lzwState = this.lzwState;
|
||||||
@ -1256,9 +1282,13 @@ var LZWStream = (function LZWStreamClosure() {
|
|||||||
dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
|
dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
|
||||||
dictionaryValues[nextCode] = currentSequence[0];
|
dictionaryValues[nextCode] = currentSequence[0];
|
||||||
nextCode++;
|
nextCode++;
|
||||||
codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ?
|
codeLength =
|
||||||
codeLength : Math.min(Math.log(nextCode + earlyChange) /
|
(nextCode + earlyChange) & (nextCode + earlyChange - 1)
|
||||||
0.6931471805599453 + 1, 12) | 0;
|
? codeLength
|
||||||
|
: Math.min(
|
||||||
|
Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1,
|
||||||
|
12
|
||||||
|
) | 0;
|
||||||
}
|
}
|
||||||
prevCode = code;
|
prevCode = code;
|
||||||
|
|
||||||
|
@ -13,9 +13,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isSpace, warn } from '../shared/util';
|
import { isSpace, warn } from "../shared/util";
|
||||||
import { getEncoding } from './encodings';
|
import { getEncoding } from "./encodings";
|
||||||
import { Stream } from './stream';
|
import { Stream } from "./stream";
|
||||||
|
|
||||||
// Hinting is currently disabled due to unknown problems on windows
|
// Hinting is currently disabled due to unknown problems on windows
|
||||||
// in tracemonkey and various other pdfs with type1 fonts.
|
// in tracemonkey and various other pdfs with type1 fonts.
|
||||||
@ -61,21 +61,21 @@ var HINTING_ENABLED = false;
|
|||||||
*/
|
*/
|
||||||
var Type1CharString = (function Type1CharStringClosure() {
|
var Type1CharString = (function Type1CharStringClosure() {
|
||||||
var COMMAND_MAP = {
|
var COMMAND_MAP = {
|
||||||
'hstem': [1],
|
hstem: [1],
|
||||||
'vstem': [3],
|
vstem: [3],
|
||||||
'vmoveto': [4],
|
vmoveto: [4],
|
||||||
'rlineto': [5],
|
rlineto: [5],
|
||||||
'hlineto': [6],
|
hlineto: [6],
|
||||||
'vlineto': [7],
|
vlineto: [7],
|
||||||
'rrcurveto': [8],
|
rrcurveto: [8],
|
||||||
'callsubr': [10],
|
callsubr: [10],
|
||||||
'flex': [12, 35],
|
flex: [12, 35],
|
||||||
'drop': [12, 18],
|
drop: [12, 18],
|
||||||
'endchar': [14],
|
endchar: [14],
|
||||||
'rmoveto': [21],
|
rmoveto: [21],
|
||||||
'hmoveto': [22],
|
hmoveto: [22],
|
||||||
'vhcurveto': [30],
|
vhcurveto: [30],
|
||||||
'hvcurveto': [31],
|
hvcurveto: [31],
|
||||||
};
|
};
|
||||||
|
|
||||||
function Type1CharString() {
|
function Type1CharString() {
|
||||||
@ -87,8 +87,11 @@ var Type1CharString = (function Type1CharStringClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Type1CharString.prototype = {
|
Type1CharString.prototype = {
|
||||||
convert: function Type1CharString_convert(encoded, subrs,
|
convert: function Type1CharString_convert(
|
||||||
seacAnalysisEnabled) {
|
encoded,
|
||||||
|
subrs,
|
||||||
|
seacAnalysisEnabled
|
||||||
|
) {
|
||||||
var count = encoded.length;
|
var count = encoded.length;
|
||||||
var error = false;
|
var error = false;
|
||||||
var wx, sbx, subrNumber;
|
var wx, sbx, subrNumber;
|
||||||
@ -154,8 +157,11 @@ var Type1CharString = (function Type1CharStringClosure() {
|
|||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
error = this.convert(subrs[subrNumber], subrs,
|
error = this.convert(
|
||||||
seacAnalysisEnabled);
|
subrs[subrNumber],
|
||||||
|
subrs,
|
||||||
|
seacAnalysisEnabled
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case 11: // return
|
case 11: // return
|
||||||
return error;
|
return error;
|
||||||
@ -308,12 +314,15 @@ var Type1CharString = (function Type1CharStringClosure() {
|
|||||||
} else if (value <= 246) {
|
} else if (value <= 246) {
|
||||||
value = value - 139;
|
value = value - 139;
|
||||||
} else if (value <= 250) {
|
} else if (value <= 250) {
|
||||||
value = ((value - 247) * 256) + encoded[++i] + 108;
|
value = (value - 247) * 256 + encoded[++i] + 108;
|
||||||
} else if (value <= 254) {
|
} else if (value <= 254) {
|
||||||
value = -((value - 251) * 256) - encoded[++i] - 108;
|
value = -((value - 251) * 256) - encoded[++i] - 108;
|
||||||
} else {
|
} else {
|
||||||
value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 |
|
value =
|
||||||
(encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;
|
((encoded[++i] & 0xff) << 24) |
|
||||||
|
((encoded[++i] & 0xff) << 16) |
|
||||||
|
((encoded[++i] & 0xff) << 8) |
|
||||||
|
((encoded[++i] & 0xff) << 0);
|
||||||
}
|
}
|
||||||
this.stack.push(value);
|
this.stack.push(value);
|
||||||
}
|
}
|
||||||
@ -330,13 +339,16 @@ var Type1CharString = (function Type1CharStringClosure() {
|
|||||||
var value = this.stack[i];
|
var value = this.stack[i];
|
||||||
if (Number.isInteger(value)) {
|
if (Number.isInteger(value)) {
|
||||||
this.output.push(28, (value >> 8) & 0xff, value & 0xff);
|
this.output.push(28, (value >> 8) & 0xff, value & 0xff);
|
||||||
} else { // fixed point
|
} else {
|
||||||
|
// fixed point
|
||||||
value = (65536 * value) | 0;
|
value = (65536 * value) | 0;
|
||||||
this.output.push(255,
|
this.output.push(
|
||||||
(value >> 24) & 0xFF,
|
255,
|
||||||
(value >> 16) & 0xFF,
|
(value >> 24) & 0xff,
|
||||||
(value >> 8) & 0xFF,
|
(value >> 16) & 0xff,
|
||||||
value & 0xFF);
|
(value >> 8) & 0xff,
|
||||||
|
value & 0xff
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.output.push.apply(this.output, command);
|
this.output.push.apply(this.output, command);
|
||||||
@ -370,16 +382,22 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
var CHAR_STRS_ENCRYPT_KEY = 4330;
|
var CHAR_STRS_ENCRYPT_KEY = 4330;
|
||||||
|
|
||||||
function isHexDigit(code) {
|
function isHexDigit(code) {
|
||||||
return code >= 48 && code <= 57 || // '0'-'9'
|
return (
|
||||||
code >= 65 && code <= 70 || // 'A'-'F'
|
(code >= 48 && code <= 57) || // '0'-'9'
|
||||||
code >= 97 && code <= 102; // 'a'-'f'
|
(code >= 65 && code <= 70) || // 'A'-'F'
|
||||||
|
(code >= 97 && code <= 102)
|
||||||
|
); // 'a'-'f'
|
||||||
}
|
}
|
||||||
|
|
||||||
function decrypt(data, key, discardNumber) {
|
function decrypt(data, key, discardNumber) {
|
||||||
if (discardNumber >= data.length) {
|
if (discardNumber >= data.length) {
|
||||||
return new Uint8Array(0);
|
return new Uint8Array(0);
|
||||||
}
|
}
|
||||||
var r = key | 0, c1 = 52845, c2 = 22719, i, j;
|
var r = key | 0,
|
||||||
|
c1 = 52845,
|
||||||
|
c2 = 22719,
|
||||||
|
i,
|
||||||
|
j;
|
||||||
for (i = 0; i < discardNumber; i++) {
|
for (i = 0; i < discardNumber; i++) {
|
||||||
r = ((data[i] + r) * c1 + c2) & ((1 << 16) - 1);
|
r = ((data[i] + r) * c1 + c2) & ((1 << 16) - 1);
|
||||||
}
|
}
|
||||||
@ -394,8 +412,11 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function decryptAscii(data, key, discardNumber) {
|
function decryptAscii(data, key, discardNumber) {
|
||||||
var r = key | 0, c1 = 52845, c2 = 22719;
|
var r = key | 0,
|
||||||
var count = data.length, maybeLength = count >>> 1;
|
c1 = 52845,
|
||||||
|
c2 = 22719;
|
||||||
|
var count = data.length,
|
||||||
|
maybeLength = count >>> 1;
|
||||||
var decrypted = new Uint8Array(maybeLength);
|
var decrypted = new Uint8Array(maybeLength);
|
||||||
var i, j;
|
var i, j;
|
||||||
for (i = 0, j = 0; i < count; i++) {
|
for (i = 0, j = 0; i < count; i++) {
|
||||||
@ -405,7 +426,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
var digit2;
|
var digit2;
|
||||||
while (i < count && !isHexDigit(digit2 = data[i])) {
|
while (i < count && !isHexDigit((digit2 = data[i]))) {
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i < count) {
|
if (i < count) {
|
||||||
@ -418,19 +439,31 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isSpecial(c) {
|
function isSpecial(c) {
|
||||||
return c === 0x2F || // '/'
|
return (
|
||||||
c === 0x5B || c === 0x5D || // '[', ']'
|
c === 0x2f || // '/'
|
||||||
c === 0x7B || c === 0x7D || // '{', '}'
|
c === 0x5b ||
|
||||||
c === 0x28 || c === 0x29; // '(', ')'
|
c === 0x5d || // '[', ']'
|
||||||
|
c === 0x7b ||
|
||||||
|
c === 0x7d || // '{', '}'
|
||||||
|
c === 0x28 ||
|
||||||
|
c === 0x29
|
||||||
|
); // '(', ')'
|
||||||
}
|
}
|
||||||
|
|
||||||
function Type1Parser(stream, encrypted, seacAnalysisEnabled) {
|
function Type1Parser(stream, encrypted, seacAnalysisEnabled) {
|
||||||
if (encrypted) {
|
if (encrypted) {
|
||||||
var data = stream.getBytes();
|
var data = stream.getBytes();
|
||||||
var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) &&
|
var isBinary = !(
|
||||||
isHexDigit(data[2]) && isHexDigit(data[3]));
|
isHexDigit(data[0]) &&
|
||||||
stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) :
|
isHexDigit(data[1]) &&
|
||||||
decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
|
isHexDigit(data[2]) &&
|
||||||
|
isHexDigit(data[3])
|
||||||
|
);
|
||||||
|
stream = new Stream(
|
||||||
|
isBinary
|
||||||
|
? decrypt(data, EEXEC_ENCRYPT_KEY, 4)
|
||||||
|
: decryptAscii(data, EEXEC_ENCRYPT_KEY, 4)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this.seacAnalysisEnabled = !!seacAnalysisEnabled;
|
this.seacAnalysisEnabled = !!seacAnalysisEnabled;
|
||||||
|
|
||||||
@ -444,7 +477,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
var array = [];
|
var array = [];
|
||||||
while (true) {
|
while (true) {
|
||||||
var token = this.getToken();
|
var token = this.getToken();
|
||||||
if (token === null || token === ']' || token === '}') {
|
if (token === null || token === "]" || token === "}") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
array.push(parseFloat(token || 0));
|
array.push(parseFloat(token || 0));
|
||||||
@ -468,7 +501,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
var token = this.getToken();
|
var token = this.getToken();
|
||||||
|
|
||||||
// Use 1 and 0 since that's what type2 charstrings use.
|
// Use 1 and 0 since that's what type2 charstrings use.
|
||||||
return token === 'true' ? 1 : 0;
|
return token === "true" ? 1 : 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
nextChar: function Type1_nextChar() {
|
nextChar: function Type1_nextChar() {
|
||||||
@ -485,10 +518,11 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (comment) {
|
if (comment) {
|
||||||
if (ch === 0x0A || ch === 0x0D) {
|
if (ch === 0x0a || ch === 0x0d) {
|
||||||
comment = false;
|
comment = false;
|
||||||
}
|
}
|
||||||
} else if (ch === 0x25) { // '%'
|
} else if (ch === 0x25) {
|
||||||
|
// '%'
|
||||||
comment = true;
|
comment = true;
|
||||||
} else if (!isSpace(ch)) {
|
} else if (!isSpace(ch)) {
|
||||||
break;
|
break;
|
||||||
@ -499,7 +533,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
this.nextChar();
|
this.nextChar();
|
||||||
return String.fromCharCode(ch);
|
return String.fromCharCode(ch);
|
||||||
}
|
}
|
||||||
var token = '';
|
var token = "";
|
||||||
do {
|
do {
|
||||||
token += String.fromCharCode(ch);
|
token += String.fromCharCode(ch);
|
||||||
ch = this.nextChar();
|
ch = this.nextChar();
|
||||||
@ -523,24 +557,25 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
extractFontProgram: function Type1Parser_extractFontProgram(properties) {
|
extractFontProgram: function Type1Parser_extractFontProgram(properties) {
|
||||||
var stream = this.stream;
|
var stream = this.stream;
|
||||||
|
|
||||||
var subrs = [], charstrings = [];
|
var subrs = [],
|
||||||
|
charstrings = [];
|
||||||
var privateData = Object.create(null);
|
var privateData = Object.create(null);
|
||||||
privateData['lenIV'] = 4;
|
privateData["lenIV"] = 4;
|
||||||
var program = {
|
var program = {
|
||||||
subrs: [],
|
subrs: [],
|
||||||
charstrings: [],
|
charstrings: [],
|
||||||
properties: {
|
properties: {
|
||||||
'privateData': privateData,
|
privateData,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var token, length, data, lenIV, encoded;
|
var token, length, data, lenIV, encoded;
|
||||||
while ((token = this.getToken()) !== null) {
|
while ((token = this.getToken()) !== null) {
|
||||||
if (token !== '/') {
|
if (token !== "/") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
token = this.getToken();
|
token = this.getToken();
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case 'CharStrings':
|
case "CharStrings":
|
||||||
// The number immediately following CharStrings must be greater or
|
// The number immediately following CharStrings must be greater or
|
||||||
// equal to the number of CharStrings.
|
// equal to the number of CharStrings.
|
||||||
this.getToken();
|
this.getToken();
|
||||||
@ -549,22 +584,22 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
this.getToken(); // read in 'begin'
|
this.getToken(); // read in 'begin'
|
||||||
while (true) {
|
while (true) {
|
||||||
token = this.getToken();
|
token = this.getToken();
|
||||||
if (token === null || token === 'end') {
|
if (token === null || token === "end") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token !== '/') {
|
if (token !== "/") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var glyph = this.getToken();
|
var glyph = this.getToken();
|
||||||
length = this.readInt();
|
length = this.readInt();
|
||||||
this.getToken(); // read in 'RD' or '-|'
|
this.getToken(); // read in 'RD' or '-|'
|
||||||
data = (length > 0 ? stream.getBytes(length) : new Uint8Array(0));
|
data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
|
||||||
lenIV = program.properties.privateData['lenIV'];
|
lenIV = program.properties.privateData["lenIV"];
|
||||||
encoded = this.readCharStrings(data, lenIV);
|
encoded = this.readCharStrings(data, lenIV);
|
||||||
this.nextChar();
|
this.nextChar();
|
||||||
token = this.getToken(); // read in 'ND' or '|-'
|
token = this.getToken(); // read in 'ND' or '|-'
|
||||||
if (token === 'noaccess') {
|
if (token === "noaccess") {
|
||||||
this.getToken(); // read in 'def'
|
this.getToken(); // read in 'def'
|
||||||
}
|
}
|
||||||
charstrings.push({
|
charstrings.push({
|
||||||
@ -573,54 +608,56 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'Subrs':
|
case "Subrs":
|
||||||
this.readInt(); // num
|
this.readInt(); // num
|
||||||
this.getToken(); // read in 'array'
|
this.getToken(); // read in 'array'
|
||||||
while (this.getToken() === 'dup') {
|
while (this.getToken() === "dup") {
|
||||||
var index = this.readInt();
|
var index = this.readInt();
|
||||||
length = this.readInt();
|
length = this.readInt();
|
||||||
this.getToken(); // read in 'RD' or '-|'
|
this.getToken(); // read in 'RD' or '-|'
|
||||||
data = (length > 0 ? stream.getBytes(length) : new Uint8Array(0));
|
data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
|
||||||
lenIV = program.properties.privateData['lenIV'];
|
lenIV = program.properties.privateData["lenIV"];
|
||||||
encoded = this.readCharStrings(data, lenIV);
|
encoded = this.readCharStrings(data, lenIV);
|
||||||
this.nextChar();
|
this.nextChar();
|
||||||
token = this.getToken(); // read in 'NP' or '|'
|
token = this.getToken(); // read in 'NP' or '|'
|
||||||
if (token === 'noaccess') {
|
if (token === "noaccess") {
|
||||||
this.getToken(); // read in 'put'
|
this.getToken(); // read in 'put'
|
||||||
}
|
}
|
||||||
subrs[index] = encoded;
|
subrs[index] = encoded;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'BlueValues':
|
case "BlueValues":
|
||||||
case 'OtherBlues':
|
case "OtherBlues":
|
||||||
case 'FamilyBlues':
|
case "FamilyBlues":
|
||||||
case 'FamilyOtherBlues':
|
case "FamilyOtherBlues":
|
||||||
var blueArray = this.readNumberArray();
|
var blueArray = this.readNumberArray();
|
||||||
// *Blue* values may contain invalid data: disables reading of
|
// *Blue* values may contain invalid data: disables reading of
|
||||||
// those values when hinting is disabled.
|
// those values when hinting is disabled.
|
||||||
if (blueArray.length > 0 && (blueArray.length % 2) === 0 &&
|
if (
|
||||||
HINTING_ENABLED) {
|
blueArray.length > 0 &&
|
||||||
|
blueArray.length % 2 === 0 &&
|
||||||
|
HINTING_ENABLED
|
||||||
|
) {
|
||||||
program.properties.privateData[token] = blueArray;
|
program.properties.privateData[token] = blueArray;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'StemSnapH':
|
case "StemSnapH":
|
||||||
case 'StemSnapV':
|
case "StemSnapV":
|
||||||
program.properties.privateData[token] = this.readNumberArray();
|
program.properties.privateData[token] = this.readNumberArray();
|
||||||
break;
|
break;
|
||||||
case 'StdHW':
|
case "StdHW":
|
||||||
case 'StdVW':
|
case "StdVW":
|
||||||
program.properties.privateData[token] =
|
program.properties.privateData[token] = this.readNumberArray()[0];
|
||||||
this.readNumberArray()[0];
|
|
||||||
break;
|
break;
|
||||||
case 'BlueShift':
|
case "BlueShift":
|
||||||
case 'lenIV':
|
case "lenIV":
|
||||||
case 'BlueFuzz':
|
case "BlueFuzz":
|
||||||
case 'BlueScale':
|
case "BlueScale":
|
||||||
case 'LanguageGroup':
|
case "LanguageGroup":
|
||||||
case 'ExpansionFactor':
|
case "ExpansionFactor":
|
||||||
program.properties.privateData[token] = this.readNumber();
|
program.properties.privateData[token] = this.readNumber();
|
||||||
break;
|
break;
|
||||||
case 'ForceBold':
|
case "ForceBold":
|
||||||
program.properties.privateData[token] = this.readBoolean();
|
program.properties.privateData[token] = this.readBoolean();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -630,8 +667,11 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
glyph = charstrings[i].glyph;
|
glyph = charstrings[i].glyph;
|
||||||
encoded = charstrings[i].encoded;
|
encoded = charstrings[i].encoded;
|
||||||
var charString = new Type1CharString();
|
var charString = new Type1CharString();
|
||||||
var error = charString.convert(encoded, subrs,
|
var error = charString.convert(
|
||||||
this.seacAnalysisEnabled);
|
encoded,
|
||||||
|
subrs,
|
||||||
|
this.seacAnalysisEnabled
|
||||||
|
);
|
||||||
var output = charString.output;
|
var output = charString.output;
|
||||||
if (error) {
|
if (error) {
|
||||||
// It seems when FreeType encounters an error while evaluating a glyph
|
// It seems when FreeType encounters an error while evaluating a glyph
|
||||||
@ -651,8 +691,12 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
// entry, with ones from the font data (fixes issue11150_reduced.pdf).
|
// entry, with ones from the font data (fixes issue11150_reduced.pdf).
|
||||||
if (properties.builtInEncoding) {
|
if (properties.builtInEncoding) {
|
||||||
const index = properties.builtInEncoding.indexOf(glyph);
|
const index = properties.builtInEncoding.indexOf(glyph);
|
||||||
if (index > -1 && properties.widths[index] === undefined &&
|
if (
|
||||||
index >= properties.firstChar && index <= properties.lastChar) {
|
index > -1 &&
|
||||||
|
properties.widths[index] === undefined &&
|
||||||
|
index >= properties.firstChar &&
|
||||||
|
index <= properties.lastChar
|
||||||
|
) {
|
||||||
properties.widths[index] = charString.width;
|
properties.widths[index] = charString.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -664,16 +708,16 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
extractFontHeader: function Type1Parser_extractFontHeader(properties) {
|
extractFontHeader: function Type1Parser_extractFontHeader(properties) {
|
||||||
var token;
|
var token;
|
||||||
while ((token = this.getToken()) !== null) {
|
while ((token = this.getToken()) !== null) {
|
||||||
if (token !== '/') {
|
if (token !== "/") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
token = this.getToken();
|
token = this.getToken();
|
||||||
switch (token) {
|
switch (token) {
|
||||||
case 'FontMatrix':
|
case "FontMatrix":
|
||||||
var matrix = this.readNumberArray();
|
var matrix = this.readNumberArray();
|
||||||
properties.fontMatrix = matrix;
|
properties.fontMatrix = matrix;
|
||||||
break;
|
break;
|
||||||
case 'Encoding':
|
case "Encoding":
|
||||||
var encodingArg = this.getToken();
|
var encodingArg = this.getToken();
|
||||||
var encoding;
|
var encoding;
|
||||||
if (!/^\d+$/.test(encodingArg)) {
|
if (!/^\d+$/.test(encodingArg)) {
|
||||||
@ -687,13 +731,13 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
for (var j = 0; j < size; j++) {
|
for (var j = 0; j < size; j++) {
|
||||||
token = this.getToken();
|
token = this.getToken();
|
||||||
// skipping till first dup or def (e.g. ignoring for statement)
|
// skipping till first dup or def (e.g. ignoring for statement)
|
||||||
while (token !== 'dup' && token !== 'def') {
|
while (token !== "dup" && token !== "def") {
|
||||||
token = this.getToken();
|
token = this.getToken();
|
||||||
if (token === null) {
|
if (token === null) {
|
||||||
return; // invalid header
|
return; // invalid header
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (token === 'def') {
|
if (token === "def") {
|
||||||
break; // read all array data
|
break; // read all array data
|
||||||
}
|
}
|
||||||
var index = this.readInt();
|
var index = this.readInt();
|
||||||
@ -705,7 +749,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
}
|
}
|
||||||
properties.builtInEncoding = encoding;
|
properties.builtInEncoding = encoding;
|
||||||
break;
|
break;
|
||||||
case 'FontBBox':
|
case "FontBBox":
|
||||||
var fontBBox = this.readNumberArray();
|
var fontBBox = this.readNumberArray();
|
||||||
// adjusting ascent/descent
|
// adjusting ascent/descent
|
||||||
properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
|
properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
|
||||||
@ -720,6 +764,4 @@ var Type1Parser = (function Type1ParserClosure() {
|
|||||||
return Type1Parser;
|
return Type1Parser;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { Type1Parser };
|
||||||
Type1Parser,
|
|
||||||
};
|
|
||||||
|
3071
src/core/unicode.js
3071
src/core/unicode.js
File diff suppressed because it is too large
Load Diff
@ -14,17 +14,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AbortException, arrayByteLength, arraysToBytes, createPromiseCapability,
|
AbortException,
|
||||||
getVerbosityLevel, info, InvalidPDFException, MissingPDFException,
|
arrayByteLength,
|
||||||
PasswordException, setVerbosityLevel, UnexpectedResponseException,
|
arraysToBytes,
|
||||||
UnknownErrorException, UNSUPPORTED_FEATURES, VerbosityLevel, warn
|
createPromiseCapability,
|
||||||
} from '../shared/util';
|
getVerbosityLevel,
|
||||||
import { clearPrimitiveCaches, Ref } from './primitives';
|
info,
|
||||||
import { LocalPdfManager, NetworkPdfManager } from './pdf_manager';
|
InvalidPDFException,
|
||||||
import { isNodeJS } from '../shared/is_node';
|
MissingPDFException,
|
||||||
import { MessageHandler } from '../shared/message_handler';
|
PasswordException,
|
||||||
import { PDFWorkerStream } from './worker_stream';
|
setVerbosityLevel,
|
||||||
import { XRefParseException } from './core_utils';
|
UnexpectedResponseException,
|
||||||
|
UnknownErrorException,
|
||||||
|
UNSUPPORTED_FEATURES,
|
||||||
|
VerbosityLevel,
|
||||||
|
warn,
|
||||||
|
} from "../shared/util";
|
||||||
|
import { clearPrimitiveCaches, Ref } from "./primitives";
|
||||||
|
import { LocalPdfManager, NetworkPdfManager } from "./pdf_manager";
|
||||||
|
import { isNodeJS } from "../shared/is_node";
|
||||||
|
import { MessageHandler } from "../shared/message_handler";
|
||||||
|
import { PDFWorkerStream } from "./worker_stream";
|
||||||
|
import { XRefParseException } from "./core_utils";
|
||||||
|
|
||||||
var WorkerTask = (function WorkerTaskClosure() {
|
var WorkerTask = (function WorkerTaskClosure() {
|
||||||
function WorkerTask(name) {
|
function WorkerTask(name) {
|
||||||
@ -48,7 +59,7 @@ var WorkerTask = (function WorkerTaskClosure() {
|
|||||||
|
|
||||||
ensureNotTerminated() {
|
ensureNotTerminated() {
|
||||||
if (this.terminated) {
|
if (this.terminated) {
|
||||||
throw new Error('Worker task was terminated');
|
throw new Error("Worker task was terminated");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -59,7 +70,7 @@ var WorkerTask = (function WorkerTaskClosure() {
|
|||||||
var WorkerMessageHandler = {
|
var WorkerMessageHandler = {
|
||||||
setup(handler, port) {
|
setup(handler, port) {
|
||||||
var testMessageProcessed = false;
|
var testMessageProcessed = false;
|
||||||
handler.on('test', function wphSetupTest(data) {
|
handler.on("test", function wphSetupTest(data) {
|
||||||
if (testMessageProcessed) {
|
if (testMessageProcessed) {
|
||||||
return; // we already processed 'test' message once
|
return; // we already processed 'test' message once
|
||||||
}
|
}
|
||||||
@ -67,21 +78,21 @@ var WorkerMessageHandler = {
|
|||||||
|
|
||||||
// check if Uint8Array can be sent to worker
|
// check if Uint8Array can be sent to worker
|
||||||
if (!(data instanceof Uint8Array)) {
|
if (!(data instanceof Uint8Array)) {
|
||||||
handler.send('test', null);
|
handler.send("test", null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// making sure postMessage transfers are working
|
// making sure postMessage transfers are working
|
||||||
const supportTransfers = data[0] === 255;
|
const supportTransfers = data[0] === 255;
|
||||||
handler.postMessageTransfers = supportTransfers;
|
handler.postMessageTransfers = supportTransfers;
|
||||||
|
|
||||||
handler.send('test', { supportTransfers, });
|
handler.send("test", { supportTransfers });
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('configure', function wphConfigure(data) {
|
handler.on("configure", function wphConfigure(data) {
|
||||||
setVerbosityLevel(data.verbosity);
|
setVerbosityLevel(data.verbosity);
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetDocRequest', function wphSetupDoc(data) {
|
handler.on("GetDocRequest", function wphSetupDoc(data) {
|
||||||
return WorkerMessageHandler.createDocumentHandler(data, port);
|
return WorkerMessageHandler.createDocumentHandler(data, port);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -96,16 +107,19 @@ var WorkerMessageHandler = {
|
|||||||
|
|
||||||
const apiVersion = docParams.apiVersion;
|
const apiVersion = docParams.apiVersion;
|
||||||
const workerVersion =
|
const workerVersion =
|
||||||
typeof PDFJSDev !== 'undefined' && !PDFJSDev.test('TESTING') ?
|
typeof PDFJSDev !== "undefined" && !PDFJSDev.test("TESTING")
|
||||||
PDFJSDev.eval('BUNDLE_VERSION') : null;
|
? PDFJSDev.eval("BUNDLE_VERSION")
|
||||||
|
: null;
|
||||||
if (apiVersion !== workerVersion) {
|
if (apiVersion !== workerVersion) {
|
||||||
throw new Error(`The API version "${apiVersion}" does not match ` +
|
throw new Error(
|
||||||
`the Worker version "${workerVersion}".`);
|
`The API version "${apiVersion}" does not match ` +
|
||||||
|
`the Worker version "${workerVersion}".`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var docId = docParams.docId;
|
var docId = docParams.docId;
|
||||||
var docBaseUrl = docParams.docBaseUrl;
|
var docBaseUrl = docParams.docBaseUrl;
|
||||||
var workerHandlerName = docParams.docId + '_worker';
|
var workerHandlerName = docParams.docId + "_worker";
|
||||||
var handler = new MessageHandler(workerHandlerName, docId, port);
|
var handler = new MessageHandler(workerHandlerName, docId, port);
|
||||||
|
|
||||||
// Ensure that postMessage transfers are always correctly enabled/disabled,
|
// Ensure that postMessage transfers are always correctly enabled/disabled,
|
||||||
@ -114,7 +128,7 @@ var WorkerMessageHandler = {
|
|||||||
|
|
||||||
function ensureNotTerminated() {
|
function ensureNotTerminated() {
|
||||||
if (terminated) {
|
if (terminated) {
|
||||||
throw new Error('Worker was terminated');
|
throw new Error("Worker was terminated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,21 +143,21 @@ var WorkerMessageHandler = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadDocument(recoveryMode) {
|
async function loadDocument(recoveryMode) {
|
||||||
await pdfManager.ensureDoc('checkHeader');
|
await pdfManager.ensureDoc("checkHeader");
|
||||||
await pdfManager.ensureDoc('parseStartXRef');
|
await pdfManager.ensureDoc("parseStartXRef");
|
||||||
await pdfManager.ensureDoc('parse', [recoveryMode]);
|
await pdfManager.ensureDoc("parse", [recoveryMode]);
|
||||||
|
|
||||||
if (!recoveryMode) {
|
if (!recoveryMode) {
|
||||||
// Check that at least the first page can be successfully loaded,
|
// Check that at least the first page can be successfully loaded,
|
||||||
// since otherwise the XRef table is definitely not valid.
|
// since otherwise the XRef table is definitely not valid.
|
||||||
await pdfManager.ensureDoc('checkFirstPage');
|
await pdfManager.ensureDoc("checkFirstPage");
|
||||||
}
|
}
|
||||||
|
|
||||||
const [numPages, fingerprint] = await Promise.all([
|
const [numPages, fingerprint] = await Promise.all([
|
||||||
pdfManager.ensureDoc('numPages'),
|
pdfManager.ensureDoc("numPages"),
|
||||||
pdfManager.ensureDoc('fingerprint'),
|
pdfManager.ensureDoc("fingerprint"),
|
||||||
]);
|
]);
|
||||||
return { numPages, fingerprint, };
|
return { numPages, fingerprint };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPdfManager(data, evaluatorOptions) {
|
function getPdfManager(data, evaluatorOptions) {
|
||||||
@ -153,8 +167,13 @@ var WorkerMessageHandler = {
|
|||||||
var source = data.source;
|
var source = data.source;
|
||||||
if (source.data) {
|
if (source.data) {
|
||||||
try {
|
try {
|
||||||
pdfManager = new LocalPdfManager(docId, source.data, source.password,
|
pdfManager = new LocalPdfManager(
|
||||||
evaluatorOptions, docBaseUrl);
|
docId,
|
||||||
|
source.data,
|
||||||
|
source.password,
|
||||||
|
evaluatorOptions,
|
||||||
|
docBaseUrl
|
||||||
|
);
|
||||||
pdfManagerCapability.resolve(pdfManager);
|
pdfManagerCapability.resolve(pdfManager);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
pdfManagerCapability.reject(ex);
|
pdfManagerCapability.reject(ex);
|
||||||
@ -162,7 +181,8 @@ var WorkerMessageHandler = {
|
|||||||
return pdfManagerCapability.promise;
|
return pdfManagerCapability.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pdfStream, cachedChunks = [];
|
var pdfStream,
|
||||||
|
cachedChunks = [];
|
||||||
try {
|
try {
|
||||||
pdfStream = new PDFWorkerStream(handler);
|
pdfStream = new PDFWorkerStream(handler);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
@ -171,21 +191,28 @@ var WorkerMessageHandler = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fullRequest = pdfStream.getFullReader();
|
var fullRequest = pdfStream.getFullReader();
|
||||||
fullRequest.headersReady.then(function () {
|
fullRequest.headersReady
|
||||||
|
.then(function() {
|
||||||
if (!fullRequest.isRangeSupported) {
|
if (!fullRequest.isRangeSupported) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't need auto-fetch when streaming is enabled.
|
// We don't need auto-fetch when streaming is enabled.
|
||||||
var disableAutoFetch = source.disableAutoFetch ||
|
var disableAutoFetch =
|
||||||
fullRequest.isStreamingSupported;
|
source.disableAutoFetch || fullRequest.isStreamingSupported;
|
||||||
pdfManager = new NetworkPdfManager(docId, pdfStream, {
|
pdfManager = new NetworkPdfManager(
|
||||||
|
docId,
|
||||||
|
pdfStream,
|
||||||
|
{
|
||||||
msgHandler: handler,
|
msgHandler: handler,
|
||||||
password: source.password,
|
password: source.password,
|
||||||
length: fullRequest.contentLength,
|
length: fullRequest.contentLength,
|
||||||
disableAutoFetch,
|
disableAutoFetch,
|
||||||
rangeChunkSize: source.rangeChunkSize,
|
rangeChunkSize: source.rangeChunkSize,
|
||||||
}, evaluatorOptions, docBaseUrl);
|
},
|
||||||
|
evaluatorOptions,
|
||||||
|
docBaseUrl
|
||||||
|
);
|
||||||
// There may be a chance that `pdfManager` is not initialized
|
// There may be a chance that `pdfManager` is not initialized
|
||||||
// for first few runs of `readchunk` block of code. Be sure
|
// for first few runs of `readchunk` block of code. Be sure
|
||||||
// to send all cached chunks, if any, to chunked_stream via
|
// to send all cached chunks, if any, to chunked_stream via
|
||||||
@ -197,7 +224,8 @@ var WorkerMessageHandler = {
|
|||||||
cachedChunks = [];
|
cachedChunks = [];
|
||||||
pdfManagerCapability.resolve(pdfManager);
|
pdfManagerCapability.resolve(pdfManager);
|
||||||
cancelXHRs = null;
|
cancelXHRs = null;
|
||||||
}).catch(function (reason) {
|
})
|
||||||
|
.catch(function(reason) {
|
||||||
pdfManagerCapability.reject(reason);
|
pdfManagerCapability.reject(reason);
|
||||||
cancelXHRs = null;
|
cancelXHRs = null;
|
||||||
});
|
});
|
||||||
@ -206,12 +234,17 @@ var WorkerMessageHandler = {
|
|||||||
var flushChunks = function() {
|
var flushChunks = function() {
|
||||||
var pdfFile = arraysToBytes(cachedChunks);
|
var pdfFile = arraysToBytes(cachedChunks);
|
||||||
if (source.length && pdfFile.length !== source.length) {
|
if (source.length && pdfFile.length !== source.length) {
|
||||||
warn('reported HTTP length is different from actual');
|
warn("reported HTTP length is different from actual");
|
||||||
}
|
}
|
||||||
// the data is array, instantiating directly from it
|
// the data is array, instantiating directly from it
|
||||||
try {
|
try {
|
||||||
pdfManager = new LocalPdfManager(docId, pdfFile, source.password,
|
pdfManager = new LocalPdfManager(
|
||||||
evaluatorOptions, docBaseUrl);
|
docId,
|
||||||
|
pdfFile,
|
||||||
|
source.password,
|
||||||
|
evaluatorOptions,
|
||||||
|
docBaseUrl
|
||||||
|
);
|
||||||
pdfManagerCapability.resolve(pdfManager);
|
pdfManagerCapability.resolve(pdfManager);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
pdfManagerCapability.reject(ex);
|
pdfManagerCapability.reject(ex);
|
||||||
@ -233,7 +266,7 @@ var WorkerMessageHandler = {
|
|||||||
var data = chunk.value;
|
var data = chunk.value;
|
||||||
loaded += arrayByteLength(data);
|
loaded += arrayByteLength(data);
|
||||||
if (!fullRequest.isStreamingSupported) {
|
if (!fullRequest.isStreamingSupported) {
|
||||||
handler.send('DocProgress', {
|
handler.send("DocProgress", {
|
||||||
loaded,
|
loaded,
|
||||||
total: Math.max(loaded, fullRequest.contentLength || 0),
|
total: Math.max(loaded, fullRequest.contentLength || 0),
|
||||||
});
|
});
|
||||||
@ -267,7 +300,7 @@ var WorkerMessageHandler = {
|
|||||||
function setupDoc(data) {
|
function setupDoc(data) {
|
||||||
function onSuccess(doc) {
|
function onSuccess(doc) {
|
||||||
ensureNotTerminated();
|
ensureNotTerminated();
|
||||||
handler.send('GetDoc', { pdfInfo: doc, });
|
handler.send("GetDoc", { pdfInfo: doc });
|
||||||
}
|
}
|
||||||
|
|
||||||
function onFailure(ex) {
|
function onFailure(ex) {
|
||||||
@ -277,29 +310,38 @@ var WorkerMessageHandler = {
|
|||||||
var task = new WorkerTask(`PasswordException: response ${ex.code}`);
|
var task = new WorkerTask(`PasswordException: response ${ex.code}`);
|
||||||
startWorkerTask(task);
|
startWorkerTask(task);
|
||||||
|
|
||||||
handler.sendWithPromise('PasswordRequest', ex).then(function(data) {
|
handler
|
||||||
|
.sendWithPromise("PasswordRequest", ex)
|
||||||
|
.then(function(data) {
|
||||||
finishWorkerTask(task);
|
finishWorkerTask(task);
|
||||||
pdfManager.updatePassword(data.password);
|
pdfManager.updatePassword(data.password);
|
||||||
pdfManagerReady();
|
pdfManagerReady();
|
||||||
}).catch(function() {
|
})
|
||||||
|
.catch(function() {
|
||||||
finishWorkerTask(task);
|
finishWorkerTask(task);
|
||||||
handler.send('DocException', ex);
|
handler.send("DocException", ex);
|
||||||
});
|
});
|
||||||
} else if (ex instanceof InvalidPDFException ||
|
} else if (
|
||||||
|
ex instanceof InvalidPDFException ||
|
||||||
ex instanceof MissingPDFException ||
|
ex instanceof MissingPDFException ||
|
||||||
ex instanceof UnexpectedResponseException ||
|
ex instanceof UnexpectedResponseException ||
|
||||||
ex instanceof UnknownErrorException) {
|
ex instanceof UnknownErrorException
|
||||||
handler.send('DocException', ex);
|
) {
|
||||||
|
handler.send("DocException", ex);
|
||||||
} else {
|
} else {
|
||||||
handler.send('DocException',
|
handler.send(
|
||||||
new UnknownErrorException(ex.message, ex.toString()));
|
"DocException",
|
||||||
|
new UnknownErrorException(ex.message, ex.toString())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function pdfManagerReady() {
|
function pdfManagerReady() {
|
||||||
ensureNotTerminated();
|
ensureNotTerminated();
|
||||||
|
|
||||||
loadDocument(false).then(onSuccess, function loadFailure(ex) {
|
loadDocument(false).then(
|
||||||
|
onSuccess,
|
||||||
|
function loadFailure(ex) {
|
||||||
ensureNotTerminated();
|
ensureNotTerminated();
|
||||||
|
|
||||||
// Try again with recoveryMode == true
|
// Try again with recoveryMode == true
|
||||||
@ -313,7 +355,9 @@ var WorkerMessageHandler = {
|
|||||||
|
|
||||||
loadDocument(true).then(onSuccess, onFailure);
|
loadDocument(true).then(onSuccess, onFailure);
|
||||||
});
|
});
|
||||||
}, onFailure);
|
},
|
||||||
|
onFailure
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureNotTerminated();
|
ensureNotTerminated();
|
||||||
@ -327,28 +371,32 @@ var WorkerMessageHandler = {
|
|||||||
isEvalSupported: data.isEvalSupported,
|
isEvalSupported: data.isEvalSupported,
|
||||||
};
|
};
|
||||||
|
|
||||||
getPdfManager(data, evaluatorOptions).then(function (newPdfManager) {
|
getPdfManager(data, evaluatorOptions)
|
||||||
|
.then(function(newPdfManager) {
|
||||||
if (terminated) {
|
if (terminated) {
|
||||||
// We were in a process of setting up the manager, but it got
|
// We were in a process of setting up the manager, but it got
|
||||||
// terminated in the middle.
|
// terminated in the middle.
|
||||||
newPdfManager.terminate(new AbortException('Worker was terminated.'));
|
newPdfManager.terminate(
|
||||||
throw new Error('Worker was terminated');
|
new AbortException("Worker was terminated.")
|
||||||
|
);
|
||||||
|
throw new Error("Worker was terminated");
|
||||||
}
|
}
|
||||||
pdfManager = newPdfManager;
|
pdfManager = newPdfManager;
|
||||||
|
|
||||||
pdfManager.onLoadedStream().then(function(stream) {
|
pdfManager.onLoadedStream().then(function(stream) {
|
||||||
handler.send('DataLoaded', { length: stream.bytes.byteLength, });
|
handler.send("DataLoaded", { length: stream.bytes.byteLength });
|
||||||
});
|
});
|
||||||
}).then(pdfManagerReady, onFailure);
|
})
|
||||||
|
.then(pdfManagerReady, onFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.on('GetPage', function wphSetupGetPage(data) {
|
handler.on("GetPage", function wphSetupGetPage(data) {
|
||||||
return pdfManager.getPage(data.pageIndex).then(function(page) {
|
return pdfManager.getPage(data.pageIndex).then(function(page) {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
pdfManager.ensure(page, 'rotate'),
|
pdfManager.ensure(page, "rotate"),
|
||||||
pdfManager.ensure(page, 'ref'),
|
pdfManager.ensure(page, "ref"),
|
||||||
pdfManager.ensure(page, 'userUnit'),
|
pdfManager.ensure(page, "userUnit"),
|
||||||
pdfManager.ensure(page, 'view'),
|
pdfManager.ensure(page, "view"),
|
||||||
]).then(function([rotate, ref, userUnit, view]) {
|
]).then(function([rotate, ref, userUnit, view]) {
|
||||||
return {
|
return {
|
||||||
rotate,
|
rotate,
|
||||||
@ -360,163 +408,167 @@ var WorkerMessageHandler = {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetPageIndex', function wphSetupGetPageIndex(data) {
|
handler.on("GetPageIndex", function wphSetupGetPageIndex(data) {
|
||||||
var ref = Ref.get(data.ref.num, data.ref.gen);
|
var ref = Ref.get(data.ref.num, data.ref.gen);
|
||||||
var catalog = pdfManager.pdfDocument.catalog;
|
var catalog = pdfManager.pdfDocument.catalog;
|
||||||
return catalog.getPageIndex(ref);
|
return catalog.getPageIndex(ref);
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetDestinations',
|
handler.on("GetDestinations", function wphSetupGetDestinations(data) {
|
||||||
function wphSetupGetDestinations(data) {
|
return pdfManager.ensureCatalog("destinations");
|
||||||
return pdfManager.ensureCatalog('destinations');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
handler.on('GetDestination',
|
|
||||||
function wphSetupGetDestination(data) {
|
|
||||||
return pdfManager.ensureCatalog('getDestination', [data.id]);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
handler.on('GetPageLabels',
|
|
||||||
function wphSetupGetPageLabels(data) {
|
|
||||||
return pdfManager.ensureCatalog('pageLabels');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
handler.on('GetPageLayout', function wphSetupGetPageLayout(data) {
|
|
||||||
return pdfManager.ensureCatalog('pageLayout');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetPageMode', function wphSetupGetPageMode(data) {
|
handler.on("GetDestination", function wphSetupGetDestination(data) {
|
||||||
return pdfManager.ensureCatalog('pageMode');
|
return pdfManager.ensureCatalog("getDestination", [data.id]);
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetViewerPreferences', function(data) {
|
handler.on("GetPageLabels", function wphSetupGetPageLabels(data) {
|
||||||
return pdfManager.ensureCatalog('viewerPreferences');
|
return pdfManager.ensureCatalog("pageLabels");
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetOpenActionDestination', function(data) {
|
handler.on("GetPageLayout", function wphSetupGetPageLayout(data) {
|
||||||
return pdfManager.ensureCatalog('openActionDestination');
|
return pdfManager.ensureCatalog("pageLayout");
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetAttachments',
|
handler.on("GetPageMode", function wphSetupGetPageMode(data) {
|
||||||
function wphSetupGetAttachments(data) {
|
return pdfManager.ensureCatalog("pageMode");
|
||||||
return pdfManager.ensureCatalog('attachments');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
handler.on('GetJavaScript',
|
|
||||||
function wphSetupGetJavaScript(data) {
|
|
||||||
return pdfManager.ensureCatalog('javaScript');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
handler.on('GetOutline',
|
|
||||||
function wphSetupGetOutline(data) {
|
|
||||||
return pdfManager.ensureCatalog('documentOutline');
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
handler.on('GetPermissions', function(data) {
|
|
||||||
return pdfManager.ensureCatalog('permissions');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetMetadata',
|
handler.on("GetViewerPreferences", function(data) {
|
||||||
function wphSetupGetMetadata(data) {
|
return pdfManager.ensureCatalog("viewerPreferences");
|
||||||
return Promise.all([pdfManager.ensureDoc('documentInfo'),
|
});
|
||||||
pdfManager.ensureCatalog('metadata')]);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
handler.on('GetData', function wphSetupGetData(data) {
|
handler.on("GetOpenActionDestination", function(data) {
|
||||||
|
return pdfManager.ensureCatalog("openActionDestination");
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.on("GetAttachments", function wphSetupGetAttachments(data) {
|
||||||
|
return pdfManager.ensureCatalog("attachments");
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.on("GetJavaScript", function wphSetupGetJavaScript(data) {
|
||||||
|
return pdfManager.ensureCatalog("javaScript");
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.on("GetOutline", function wphSetupGetOutline(data) {
|
||||||
|
return pdfManager.ensureCatalog("documentOutline");
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.on("GetPermissions", function(data) {
|
||||||
|
return pdfManager.ensureCatalog("permissions");
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.on("GetMetadata", function wphSetupGetMetadata(data) {
|
||||||
|
return Promise.all([
|
||||||
|
pdfManager.ensureDoc("documentInfo"),
|
||||||
|
pdfManager.ensureCatalog("metadata"),
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
handler.on("GetData", function wphSetupGetData(data) {
|
||||||
pdfManager.requestLoadedStream();
|
pdfManager.requestLoadedStream();
|
||||||
return pdfManager.onLoadedStream().then(function(stream) {
|
return pdfManager.onLoadedStream().then(function(stream) {
|
||||||
return stream.bytes;
|
return stream.bytes;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetStats',
|
handler.on("GetStats", function wphSetupGetStats(data) {
|
||||||
function wphSetupGetStats(data) {
|
|
||||||
return pdfManager.pdfDocument.xref.stats;
|
return pdfManager.pdfDocument.xref.stats;
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
handler.on('GetAnnotations', function({ pageIndex, intent, }) {
|
handler.on("GetAnnotations", function({ pageIndex, intent }) {
|
||||||
return pdfManager.getPage(pageIndex).then(function(page) {
|
return pdfManager.getPage(pageIndex).then(function(page) {
|
||||||
return page.getAnnotationsData(intent);
|
return page.getAnnotationsData(intent);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('GetOperatorList', function wphSetupRenderPage(data, sink) {
|
handler.on(
|
||||||
|
"GetOperatorList",
|
||||||
|
function wphSetupRenderPage(data, sink) {
|
||||||
var pageIndex = data.pageIndex;
|
var pageIndex = data.pageIndex;
|
||||||
pdfManager.getPage(pageIndex).then(function(page) {
|
pdfManager.getPage(pageIndex).then(function(page) {
|
||||||
var task = new WorkerTask(`GetOperatorList: page ${pageIndex}`);
|
var task = new WorkerTask(`GetOperatorList: page ${pageIndex}`);
|
||||||
startWorkerTask(task);
|
startWorkerTask(task);
|
||||||
|
|
||||||
// NOTE: Keep this condition in sync with the `info` helper function.
|
// NOTE: Keep this condition in sync with the `info` helper function.
|
||||||
const start = (verbosity >= VerbosityLevel.INFOS ? Date.now() : 0);
|
const start = verbosity >= VerbosityLevel.INFOS ? Date.now() : 0;
|
||||||
|
|
||||||
// Pre compile the pdf page and fetch the fonts/images.
|
// Pre compile the pdf page and fetch the fonts/images.
|
||||||
page.getOperatorList({
|
page
|
||||||
|
.getOperatorList({
|
||||||
handler,
|
handler,
|
||||||
sink,
|
sink,
|
||||||
task,
|
task,
|
||||||
intent: data.intent,
|
intent: data.intent,
|
||||||
renderInteractiveForms: data.renderInteractiveForms,
|
renderInteractiveForms: data.renderInteractiveForms,
|
||||||
}).then(function(operatorListInfo) {
|
})
|
||||||
|
.then(
|
||||||
|
function(operatorListInfo) {
|
||||||
finishWorkerTask(task);
|
finishWorkerTask(task);
|
||||||
|
|
||||||
if (start) {
|
if (start) {
|
||||||
info(`page=${pageIndex + 1} - getOperatorList: time=` +
|
info(
|
||||||
`${Date.now() - start}ms, len=${operatorListInfo.length}`);
|
`page=${pageIndex + 1} - getOperatorList: time=` +
|
||||||
|
`${Date.now() - start}ms, len=${operatorListInfo.length}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
sink.close();
|
sink.close();
|
||||||
}, function(reason) {
|
},
|
||||||
|
function(reason) {
|
||||||
finishWorkerTask(task);
|
finishWorkerTask(task);
|
||||||
if (task.terminated) {
|
if (task.terminated) {
|
||||||
return; // ignoring errors from the terminated thread
|
return; // ignoring errors from the terminated thread
|
||||||
}
|
}
|
||||||
// For compatibility with older behavior, generating unknown
|
// For compatibility with older behavior, generating unknown
|
||||||
// unsupported feature notification on errors.
|
// unsupported feature notification on errors.
|
||||||
handler.send('UnsupportedFeature',
|
handler.send("UnsupportedFeature", {
|
||||||
{ featureId: UNSUPPORTED_FEATURES.unknown, });
|
featureId: UNSUPPORTED_FEATURES.unknown,
|
||||||
|
});
|
||||||
|
|
||||||
sink.error(reason);
|
sink.error(reason);
|
||||||
|
|
||||||
// TODO: Should `reason` be re-thrown here (currently that casues
|
// TODO: Should `reason` be re-thrown here (currently that casues
|
||||||
// "Uncaught exception: ..." messages in the console)?
|
// "Uncaught exception: ..." messages in the console)?
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
},
|
||||||
}, this);
|
this
|
||||||
|
);
|
||||||
|
|
||||||
handler.on('GetTextContent', function wphExtractText(data, sink) {
|
handler.on("GetTextContent", function wphExtractText(data, sink) {
|
||||||
var pageIndex = data.pageIndex;
|
var pageIndex = data.pageIndex;
|
||||||
sink.onPull = function(desiredSize) {};
|
sink.onPull = function(desiredSize) {};
|
||||||
sink.onCancel = function(reason) {};
|
sink.onCancel = function(reason) {};
|
||||||
|
|
||||||
pdfManager.getPage(pageIndex).then(function(page) {
|
pdfManager.getPage(pageIndex).then(function(page) {
|
||||||
var task = new WorkerTask('GetTextContent: page ' + pageIndex);
|
var task = new WorkerTask("GetTextContent: page " + pageIndex);
|
||||||
startWorkerTask(task);
|
startWorkerTask(task);
|
||||||
|
|
||||||
// NOTE: Keep this condition in sync with the `info` helper function.
|
// NOTE: Keep this condition in sync with the `info` helper function.
|
||||||
const start = (verbosity >= VerbosityLevel.INFOS ? Date.now() : 0);
|
const start = verbosity >= VerbosityLevel.INFOS ? Date.now() : 0;
|
||||||
|
|
||||||
page.extractTextContent({
|
page
|
||||||
|
.extractTextContent({
|
||||||
handler,
|
handler,
|
||||||
task,
|
task,
|
||||||
sink,
|
sink,
|
||||||
normalizeWhitespace: data.normalizeWhitespace,
|
normalizeWhitespace: data.normalizeWhitespace,
|
||||||
combineTextItems: data.combineTextItems,
|
combineTextItems: data.combineTextItems,
|
||||||
}).then(function() {
|
})
|
||||||
|
.then(
|
||||||
|
function() {
|
||||||
finishWorkerTask(task);
|
finishWorkerTask(task);
|
||||||
|
|
||||||
if (start) {
|
if (start) {
|
||||||
info(`page=${pageIndex + 1} - getTextContent: time=` +
|
info(
|
||||||
`${Date.now() - start}ms`);
|
`page=${pageIndex + 1} - getTextContent: time=` +
|
||||||
|
`${Date.now() - start}ms`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
sink.close();
|
sink.close();
|
||||||
}, function (reason) {
|
},
|
||||||
|
function(reason) {
|
||||||
finishWorkerTask(task);
|
finishWorkerTask(task);
|
||||||
if (task.terminated) {
|
if (task.terminated) {
|
||||||
return; // ignoring errors from the terminated thread
|
return; // ignoring errors from the terminated thread
|
||||||
@ -525,26 +577,27 @@ var WorkerMessageHandler = {
|
|||||||
|
|
||||||
// TODO: Should `reason` be re-thrown here (currently that casues
|
// TODO: Should `reason` be re-thrown here (currently that casues
|
||||||
// "Uncaught exception: ..." messages in the console)?
|
// "Uncaught exception: ..." messages in the console)?
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('FontFallback', function(data) {
|
handler.on("FontFallback", function(data) {
|
||||||
return pdfManager.fontFallback(data.id, handler);
|
return pdfManager.fontFallback(data.id, handler);
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('Cleanup', function wphCleanup(data) {
|
handler.on("Cleanup", function wphCleanup(data) {
|
||||||
return pdfManager.cleanup();
|
return pdfManager.cleanup();
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('Terminate', function wphTerminate(data) {
|
handler.on("Terminate", function wphTerminate(data) {
|
||||||
terminated = true;
|
terminated = true;
|
||||||
if (pdfManager) {
|
if (pdfManager) {
|
||||||
pdfManager.terminate(new AbortException('Worker was terminated.'));
|
pdfManager.terminate(new AbortException("Worker was terminated."));
|
||||||
pdfManager = null;
|
pdfManager = null;
|
||||||
}
|
}
|
||||||
if (cancelXHRs) {
|
if (cancelXHRs) {
|
||||||
cancelXHRs(new AbortException('Worker was terminated.'));
|
cancelXHRs(new AbortException("Worker was terminated."));
|
||||||
}
|
}
|
||||||
clearPrimitiveCaches();
|
clearPrimitiveCaches();
|
||||||
|
|
||||||
@ -562,31 +615,33 @@ var WorkerMessageHandler = {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on('Ready', function wphReady(data) {
|
handler.on("Ready", function wphReady(data) {
|
||||||
setupDoc(docParams);
|
setupDoc(docParams);
|
||||||
docParams = null; // we don't need docParams anymore -- saving memory.
|
docParams = null; // we don't need docParams anymore -- saving memory.
|
||||||
});
|
});
|
||||||
return workerHandlerName;
|
return workerHandlerName;
|
||||||
},
|
},
|
||||||
initializeFromPort(port) {
|
initializeFromPort(port) {
|
||||||
var handler = new MessageHandler('worker', 'main', port);
|
var handler = new MessageHandler("worker", "main", port);
|
||||||
WorkerMessageHandler.setup(handler, port);
|
WorkerMessageHandler.setup(handler, port);
|
||||||
handler.send('ready', null);
|
handler.send("ready", null);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function isMessagePort(maybePort) {
|
function isMessagePort(maybePort) {
|
||||||
return typeof maybePort.postMessage === 'function' &&
|
return (
|
||||||
('onmessage' in maybePort);
|
typeof maybePort.postMessage === "function" && "onmessage" in maybePort
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Worker thread (and not node.js)?
|
// Worker thread (and not node.js)?
|
||||||
if (typeof window === 'undefined' && !isNodeJS &&
|
if (
|
||||||
typeof self !== 'undefined' && isMessagePort(self)) {
|
typeof window === "undefined" &&
|
||||||
|
!isNodeJS &&
|
||||||
|
typeof self !== "undefined" &&
|
||||||
|
isMessagePort(self)
|
||||||
|
) {
|
||||||
WorkerMessageHandler.initializeFromPort(self);
|
WorkerMessageHandler.initializeFromPort(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { WorkerTask, WorkerMessageHandler };
|
||||||
WorkerTask,
|
|
||||||
WorkerMessageHandler,
|
|
||||||
};
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import { assert } from '../shared/util';
|
import { assert } from "../shared/util";
|
||||||
|
|
||||||
/** @implements {IPDFStream} */
|
/** @implements {IPDFStream} */
|
||||||
class PDFWorkerStream {
|
class PDFWorkerStream {
|
||||||
@ -58,11 +58,12 @@ class PDFWorkerStreamReader {
|
|||||||
this._isRangeSupported = false;
|
this._isRangeSupported = false;
|
||||||
this._isStreamingSupported = false;
|
this._isStreamingSupported = false;
|
||||||
|
|
||||||
const readableStream = this._msgHandler.sendWithStream('GetReader');
|
const readableStream = this._msgHandler.sendWithStream("GetReader");
|
||||||
this._reader = readableStream.getReader();
|
this._reader = readableStream.getReader();
|
||||||
|
|
||||||
this._headersReady = this._msgHandler.sendWithPromise('ReaderHeadersReady').
|
this._headersReady = this._msgHandler
|
||||||
then((data) => {
|
.sendWithPromise("ReaderHeadersReady")
|
||||||
|
.then(data => {
|
||||||
this._isStreamingSupported = data.isStreamingSupported;
|
this._isStreamingSupported = data.isStreamingSupported;
|
||||||
this._isRangeSupported = data.isRangeSupported;
|
this._isRangeSupported = data.isRangeSupported;
|
||||||
this._contentLength = data.contentLength;
|
this._contentLength = data.contentLength;
|
||||||
@ -86,13 +87,13 @@ class PDFWorkerStreamReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async read() {
|
async read() {
|
||||||
const { value, done, } = await this._reader.read();
|
const { value, done } = await this._reader.read();
|
||||||
if (done) {
|
if (done) {
|
||||||
return { value: undefined, done: true, };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
// `value` is wrapped into Uint8Array, we need to
|
// `value` is wrapped into Uint8Array, we need to
|
||||||
// unwrap it to ArrayBuffer for further processing.
|
// unwrap it to ArrayBuffer for further processing.
|
||||||
return { value: value.buffer, done: false, };
|
return { value: value.buffer, done: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
@ -106,8 +107,10 @@ class PDFWorkerStreamRangeReader {
|
|||||||
this._msgHandler = msgHandler;
|
this._msgHandler = msgHandler;
|
||||||
this.onProgress = null;
|
this.onProgress = null;
|
||||||
|
|
||||||
const readableStream = this._msgHandler.sendWithStream('GetRangeReader',
|
const readableStream = this._msgHandler.sendWithStream("GetRangeReader", {
|
||||||
{ begin, end, });
|
begin,
|
||||||
|
end,
|
||||||
|
});
|
||||||
this._reader = readableStream.getReader();
|
this._reader = readableStream.getReader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,11 +119,11 @@ class PDFWorkerStreamRangeReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async read() {
|
async read() {
|
||||||
const { value, done, } = await this._reader.read();
|
const { value, done } = await this._reader.read();
|
||||||
if (done) {
|
if (done) {
|
||||||
return { value: undefined, done: true, };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
return { value: value.buffer, done: false, };
|
return { value: value.buffer, done: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
@ -128,6 +131,4 @@ class PDFWorkerStreamRangeReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { PDFWorkerStream };
|
||||||
PDFWorkerStream,
|
|
||||||
};
|
|
||||||
|
@ -15,13 +15,20 @@
|
|||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
addLinkAttributes, DOMSVGFactory, getFilenameFromUrl, LinkTarget,
|
addLinkAttributes,
|
||||||
PDFDateString
|
DOMSVGFactory,
|
||||||
} from './display_utils';
|
getFilenameFromUrl,
|
||||||
|
LinkTarget,
|
||||||
|
PDFDateString,
|
||||||
|
} from "./display_utils";
|
||||||
import {
|
import {
|
||||||
AnnotationBorderStyleType, AnnotationType, stringToPDFString, unreachable,
|
AnnotationBorderStyleType,
|
||||||
Util, warn
|
AnnotationType,
|
||||||
} from '../shared/util';
|
stringToPDFString,
|
||||||
|
unreachable,
|
||||||
|
Util,
|
||||||
|
warn,
|
||||||
|
} from "../shared/util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} AnnotationElementParameters
|
* @typedef {Object} AnnotationElementParameters
|
||||||
@ -56,16 +63,16 @@ class AnnotationElementFactory {
|
|||||||
const fieldType = parameters.data.fieldType;
|
const fieldType = parameters.data.fieldType;
|
||||||
|
|
||||||
switch (fieldType) {
|
switch (fieldType) {
|
||||||
case 'Tx':
|
case "Tx":
|
||||||
return new TextWidgetAnnotationElement(parameters);
|
return new TextWidgetAnnotationElement(parameters);
|
||||||
case 'Btn':
|
case "Btn":
|
||||||
if (parameters.data.radioButton) {
|
if (parameters.data.radioButton) {
|
||||||
return new RadioButtonWidgetAnnotationElement(parameters);
|
return new RadioButtonWidgetAnnotationElement(parameters);
|
||||||
} else if (parameters.data.checkBox) {
|
} else if (parameters.data.checkBox) {
|
||||||
return new CheckboxWidgetAnnotationElement(parameters);
|
return new CheckboxWidgetAnnotationElement(parameters);
|
||||||
}
|
}
|
||||||
return new PushButtonWidgetAnnotationElement(parameters);
|
return new PushButtonWidgetAnnotationElement(parameters);
|
||||||
case 'Ch':
|
case "Ch":
|
||||||
return new ChoiceWidgetAnnotationElement(parameters);
|
return new ChoiceWidgetAnnotationElement(parameters);
|
||||||
}
|
}
|
||||||
return new WidgetAnnotationElement(parameters);
|
return new WidgetAnnotationElement(parameters);
|
||||||
@ -148,12 +155,14 @@ class AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
_createContainer(ignoreBorder = false) {
|
_createContainer(ignoreBorder = false) {
|
||||||
const data = this.data, page = this.page, viewport = this.viewport;
|
const data = this.data,
|
||||||
const container = document.createElement('section');
|
page = this.page,
|
||||||
|
viewport = this.viewport;
|
||||||
|
const container = document.createElement("section");
|
||||||
let width = data.rect[2] - data.rect[0];
|
let width = data.rect[2] - data.rect[0];
|
||||||
let height = data.rect[3] - data.rect[1];
|
let height = data.rect[3] - data.rect[1];
|
||||||
|
|
||||||
container.setAttribute('data-annotation-id', data.id);
|
container.setAttribute("data-annotation-id", data.id);
|
||||||
|
|
||||||
// Do *not* modify `data.rect`, since that will corrupt the annotation
|
// Do *not* modify `data.rect`, since that will corrupt the annotation
|
||||||
// position on subsequent calls to `_createContainer` (see issue 6804).
|
// position on subsequent calls to `_createContainer` (see issue 6804).
|
||||||
@ -161,10 +170,10 @@ class AnnotationElement {
|
|||||||
data.rect[0],
|
data.rect[0],
|
||||||
page.view[3] - data.rect[1] + page.view[1],
|
page.view[3] - data.rect[1] + page.view[1],
|
||||||
data.rect[2],
|
data.rect[2],
|
||||||
page.view[3] - data.rect[3] + page.view[1]
|
page.view[3] - data.rect[3] + page.view[1],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
container.style.transform = `matrix(${viewport.transform.join(',')})`;
|
container.style.transform = `matrix(${viewport.transform.join(",")})`;
|
||||||
container.style.transformOrigin = `-${rect[0]}px -${rect[1]}px`;
|
container.style.transformOrigin = `-${rect[0]}px -${rect[1]}px`;
|
||||||
|
|
||||||
if (!ignoreBorder && data.borderStyle.width > 0) {
|
if (!ignoreBorder && data.borderStyle.width > 0) {
|
||||||
@ -186,23 +195,23 @@ class AnnotationElement {
|
|||||||
|
|
||||||
switch (data.borderStyle.style) {
|
switch (data.borderStyle.style) {
|
||||||
case AnnotationBorderStyleType.SOLID:
|
case AnnotationBorderStyleType.SOLID:
|
||||||
container.style.borderStyle = 'solid';
|
container.style.borderStyle = "solid";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AnnotationBorderStyleType.DASHED:
|
case AnnotationBorderStyleType.DASHED:
|
||||||
container.style.borderStyle = 'dashed';
|
container.style.borderStyle = "dashed";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AnnotationBorderStyleType.BEVELED:
|
case AnnotationBorderStyleType.BEVELED:
|
||||||
warn('Unimplemented border style: beveled');
|
warn("Unimplemented border style: beveled");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AnnotationBorderStyleType.INSET:
|
case AnnotationBorderStyleType.INSET:
|
||||||
warn('Unimplemented border style: inset');
|
warn("Unimplemented border style: inset");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AnnotationBorderStyleType.UNDERLINE:
|
case AnnotationBorderStyleType.UNDERLINE:
|
||||||
container.style.borderBottomStyle = 'solid';
|
container.style.borderBottomStyle = "solid";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -210,9 +219,11 @@ class AnnotationElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.color) {
|
if (data.color) {
|
||||||
container.style.borderColor = Util.makeCssRgb(data.color[0] | 0,
|
container.style.borderColor = Util.makeCssRgb(
|
||||||
|
data.color[0] | 0,
|
||||||
data.color[1] | 0,
|
data.color[1] | 0,
|
||||||
data.color[2] | 0);
|
data.color[2] | 0
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// Transparent (invisible) border, so do not draw it at all.
|
// Transparent (invisible) border, so do not draw it at all.
|
||||||
container.style.borderWidth = 0;
|
container.style.borderWidth = 0;
|
||||||
@ -240,7 +251,7 @@ class AnnotationElement {
|
|||||||
_createPopup(container, trigger, data) {
|
_createPopup(container, trigger, data) {
|
||||||
// If no trigger element is specified, create it.
|
// If no trigger element is specified, create it.
|
||||||
if (!trigger) {
|
if (!trigger) {
|
||||||
trigger = document.createElement('div');
|
trigger = document.createElement("div");
|
||||||
trigger.style.height = container.style.height;
|
trigger.style.height = container.style.height;
|
||||||
trigger.style.width = container.style.width;
|
trigger.style.width = container.style.width;
|
||||||
container.appendChild(trigger);
|
container.appendChild(trigger);
|
||||||
@ -270,14 +281,17 @@ class AnnotationElement {
|
|||||||
* @memberof AnnotationElement
|
* @memberof AnnotationElement
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
unreachable('Abstract method `AnnotationElement.render` called');
|
unreachable("Abstract method `AnnotationElement.render` called");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class LinkAnnotationElement extends AnnotationElement {
|
class LinkAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.url || parameters.data.dest ||
|
const isRenderable = !!(
|
||||||
parameters.data.action);
|
parameters.data.url ||
|
||||||
|
parameters.data.dest ||
|
||||||
|
parameters.data.action
|
||||||
|
);
|
||||||
super(parameters, isRenderable);
|
super(parameters, isRenderable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,16 +303,17 @@ class LinkAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'linkAnnotation';
|
this.container.className = "linkAnnotation";
|
||||||
|
|
||||||
const { data, linkService, } = this;
|
const { data, linkService } = this;
|
||||||
const link = document.createElement('a');
|
const link = document.createElement("a");
|
||||||
|
|
||||||
if (data.url) {
|
if (data.url) {
|
||||||
addLinkAttributes(link, {
|
addLinkAttributes(link, {
|
||||||
url: data.url,
|
url: data.url,
|
||||||
target: (data.newWindow ?
|
target: data.newWindow
|
||||||
LinkTarget.BLANK : linkService.externalLinkTarget),
|
? LinkTarget.BLANK
|
||||||
|
: linkService.externalLinkTarget,
|
||||||
rel: linkService.externalLinkRel,
|
rel: linkService.externalLinkRel,
|
||||||
enabled: linkService.externalLinkEnabled,
|
enabled: linkService.externalLinkEnabled,
|
||||||
});
|
});
|
||||||
@ -329,7 +344,7 @@ class LinkAnnotationElement extends AnnotationElement {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
if (destination) {
|
if (destination) {
|
||||||
link.className = 'internalLink';
|
link.className = "internalLink";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,19 +357,22 @@ class LinkAnnotationElement extends AnnotationElement {
|
|||||||
* @memberof LinkAnnotationElement
|
* @memberof LinkAnnotationElement
|
||||||
*/
|
*/
|
||||||
_bindNamedAction(link, action) {
|
_bindNamedAction(link, action) {
|
||||||
link.href = this.linkService.getAnchorUrl('');
|
link.href = this.linkService.getAnchorUrl("");
|
||||||
link.onclick = () => {
|
link.onclick = () => {
|
||||||
this.linkService.executeNamedAction(action);
|
this.linkService.executeNamedAction(action);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
link.className = 'internalLink';
|
link.className = "internalLink";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextAnnotationElement extends AnnotationElement {
|
class TextAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable);
|
super(parameters, isRenderable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,16 +384,19 @@ class TextAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'textAnnotation';
|
this.container.className = "textAnnotation";
|
||||||
|
|
||||||
const image = document.createElement('img');
|
const image = document.createElement("img");
|
||||||
image.style.height = this.container.style.height;
|
image.style.height = this.container.style.height;
|
||||||
image.style.width = this.container.style.width;
|
image.style.width = this.container.style.width;
|
||||||
image.src = this.imageResourcesPath + 'annotation-' +
|
image.src =
|
||||||
this.data.name.toLowerCase() + '.svg';
|
this.imageResourcesPath +
|
||||||
image.alt = '[{{type}} Annotation]';
|
"annotation-" +
|
||||||
image.dataset.l10nId = 'text_annotation_type';
|
this.data.name.toLowerCase() +
|
||||||
image.dataset.l10nArgs = JSON.stringify({ type: this.data.name, });
|
".svg";
|
||||||
|
image.alt = "[{{type}} Annotation]";
|
||||||
|
image.dataset.l10nId = "text_annotation_type";
|
||||||
|
image.dataset.l10nArgs = JSON.stringify({ type: this.data.name });
|
||||||
|
|
||||||
if (!this.data.hasPopup) {
|
if (!this.data.hasPopup) {
|
||||||
this._createPopup(this.container, image, this.data);
|
this._createPopup(this.container, image, this.data);
|
||||||
@ -402,7 +423,8 @@ class WidgetAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = parameters.renderInteractiveForms ||
|
const isRenderable =
|
||||||
|
parameters.renderInteractiveForms ||
|
||||||
(!parameters.data.hasAppearance && !!parameters.data.fieldValue);
|
(!parameters.data.hasAppearance && !!parameters.data.fieldValue);
|
||||||
super(parameters, isRenderable);
|
super(parameters, isRenderable);
|
||||||
}
|
}
|
||||||
@ -415,9 +437,9 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const TEXT_ALIGNMENT = ['left', 'center', 'right'];
|
const TEXT_ALIGNMENT = ["left", "center", "right"];
|
||||||
|
|
||||||
this.container.className = 'textWidgetAnnotation';
|
this.container.className = "textWidgetAnnotation";
|
||||||
|
|
||||||
let element = null;
|
let element = null;
|
||||||
if (this.renderInteractiveForms) {
|
if (this.renderInteractiveForms) {
|
||||||
@ -425,12 +447,12 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
// prevents the AnnotationLayer rasterizer in `test/driver.js`
|
// prevents the AnnotationLayer rasterizer in `test/driver.js`
|
||||||
// from parsing the elements correctly for the reference tests.
|
// from parsing the elements correctly for the reference tests.
|
||||||
if (this.data.multiLine) {
|
if (this.data.multiLine) {
|
||||||
element = document.createElement('textarea');
|
element = document.createElement("textarea");
|
||||||
element.textContent = this.data.fieldValue;
|
element.textContent = this.data.fieldValue;
|
||||||
} else {
|
} else {
|
||||||
element = document.createElement('input');
|
element = document.createElement("input");
|
||||||
element.type = 'text';
|
element.type = "text";
|
||||||
element.setAttribute('value', this.data.fieldValue);
|
element.setAttribute("value", this.data.fieldValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
element.disabled = this.data.readOnly;
|
element.disabled = this.data.readOnly;
|
||||||
@ -443,18 +465,20 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
const fieldWidth = this.data.rect[2] - this.data.rect[0];
|
const fieldWidth = this.data.rect[2] - this.data.rect[0];
|
||||||
const combWidth = fieldWidth / this.data.maxLen;
|
const combWidth = fieldWidth / this.data.maxLen;
|
||||||
|
|
||||||
element.classList.add('comb');
|
element.classList.add("comb");
|
||||||
element.style.letterSpacing = `calc(${combWidth}px - 1ch)`;
|
element.style.letterSpacing = `calc(${combWidth}px - 1ch)`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
element = document.createElement('div');
|
element = document.createElement("div");
|
||||||
element.textContent = this.data.fieldValue;
|
element.textContent = this.data.fieldValue;
|
||||||
element.style.verticalAlign = 'middle';
|
element.style.verticalAlign = "middle";
|
||||||
element.style.display = 'table-cell';
|
element.style.display = "table-cell";
|
||||||
|
|
||||||
let font = null;
|
let font = null;
|
||||||
if (this.data.fontRefName &&
|
if (
|
||||||
this.page.commonObjs.has(this.data.fontRefName)) {
|
this.data.fontRefName &&
|
||||||
|
this.page.commonObjs.has(this.data.fontRefName)
|
||||||
|
) {
|
||||||
font = this.page.commonObjs.get(this.data.fontRefName);
|
font = this.page.commonObjs.get(this.data.fontRefName);
|
||||||
}
|
}
|
||||||
this._setTextStyle(element, font);
|
this._setTextStyle(element, font);
|
||||||
@ -480,20 +504,24 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
// TODO: This duplicates some of the logic in CanvasGraphics.setFont().
|
// TODO: This duplicates some of the logic in CanvasGraphics.setFont().
|
||||||
const style = element.style;
|
const style = element.style;
|
||||||
style.fontSize = `${this.data.fontSize}px`;
|
style.fontSize = `${this.data.fontSize}px`;
|
||||||
style.direction = (this.data.fontDirection < 0 ? 'rtl' : 'ltr');
|
style.direction = this.data.fontDirection < 0 ? "rtl" : "ltr";
|
||||||
|
|
||||||
if (!font) {
|
if (!font) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
style.fontWeight = (font.black ?
|
style.fontWeight = font.black
|
||||||
(font.bold ? '900' : 'bold') :
|
? font.bold
|
||||||
(font.bold ? 'bold' : 'normal'));
|
? "900"
|
||||||
style.fontStyle = (font.italic ? 'italic' : 'normal');
|
: "bold"
|
||||||
|
: font.bold
|
||||||
|
? "bold"
|
||||||
|
: "normal";
|
||||||
|
style.fontStyle = font.italic ? "italic" : "normal";
|
||||||
|
|
||||||
// Use a reasonable default font if the font doesn't specify a fallback.
|
// Use a reasonable default font if the font doesn't specify a fallback.
|
||||||
const fontFamily = font.loadedName ? `"${font.loadedName}", ` : '';
|
const fontFamily = font.loadedName ? `"${font.loadedName}", ` : "";
|
||||||
const fallbackName = font.fallbackName || 'Helvetica, sans-serif';
|
const fallbackName = font.fallbackName || "Helvetica, sans-serif";
|
||||||
style.fontFamily = fontFamily + fallbackName;
|
style.fontFamily = fontFamily + fallbackName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -512,13 +540,13 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'buttonWidgetAnnotation checkBox';
|
this.container.className = "buttonWidgetAnnotation checkBox";
|
||||||
|
|
||||||
const element = document.createElement('input');
|
const element = document.createElement("input");
|
||||||
element.disabled = this.data.readOnly;
|
element.disabled = this.data.readOnly;
|
||||||
element.type = 'checkbox';
|
element.type = "checkbox";
|
||||||
if (this.data.fieldValue && this.data.fieldValue !== 'Off') {
|
if (this.data.fieldValue && this.data.fieldValue !== "Off") {
|
||||||
element.setAttribute('checked', true);
|
element.setAttribute("checked", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.container.appendChild(element);
|
this.container.appendChild(element);
|
||||||
@ -540,14 +568,14 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'buttonWidgetAnnotation radioButton';
|
this.container.className = "buttonWidgetAnnotation radioButton";
|
||||||
|
|
||||||
const element = document.createElement('input');
|
const element = document.createElement("input");
|
||||||
element.disabled = this.data.readOnly;
|
element.disabled = this.data.readOnly;
|
||||||
element.type = 'radio';
|
element.type = "radio";
|
||||||
element.name = this.data.fieldName;
|
element.name = this.data.fieldName;
|
||||||
if (this.data.fieldValue === this.data.buttonValue) {
|
if (this.data.fieldValue === this.data.buttonValue) {
|
||||||
element.setAttribute('checked', true);
|
element.setAttribute("checked", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.container.appendChild(element);
|
this.container.appendChild(element);
|
||||||
@ -569,7 +597,7 @@ class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
|
|||||||
// equal to that of a link annotation, but may have more functionality, such
|
// equal to that of a link annotation, but may have more functionality, such
|
||||||
// as performing actions on form fields (resetting, submitting, et cetera).
|
// as performing actions on form fields (resetting, submitting, et cetera).
|
||||||
const container = super.render();
|
const container = super.render();
|
||||||
container.className = 'buttonWidgetAnnotation pushButton';
|
container.className = "buttonWidgetAnnotation pushButton";
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -588,9 +616,9 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'choiceWidgetAnnotation';
|
this.container.className = "choiceWidgetAnnotation";
|
||||||
|
|
||||||
const selectElement = document.createElement('select');
|
const selectElement = document.createElement("select");
|
||||||
selectElement.disabled = this.data.readOnly;
|
selectElement.disabled = this.data.readOnly;
|
||||||
|
|
||||||
if (!this.data.combo) {
|
if (!this.data.combo) {
|
||||||
@ -603,11 +631,11 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
|
|
||||||
// Insert the options into the choice field.
|
// Insert the options into the choice field.
|
||||||
for (const option of this.data.options) {
|
for (const option of this.data.options) {
|
||||||
const optionElement = document.createElement('option');
|
const optionElement = document.createElement("option");
|
||||||
optionElement.textContent = option.displayValue;
|
optionElement.textContent = option.displayValue;
|
||||||
optionElement.value = option.exportValue;
|
optionElement.value = option.exportValue;
|
||||||
if (this.data.fieldValue.includes(option.displayValue)) {
|
if (this.data.fieldValue.includes(option.displayValue)) {
|
||||||
optionElement.setAttribute('selected', true);
|
optionElement.setAttribute("selected", true);
|
||||||
}
|
}
|
||||||
selectElement.appendChild(optionElement);
|
selectElement.appendChild(optionElement);
|
||||||
}
|
}
|
||||||
@ -634,15 +662,15 @@ class PopupAnnotationElement extends AnnotationElement {
|
|||||||
// Do not render popup annotations for parent elements with these types as
|
// Do not render popup annotations for parent elements with these types as
|
||||||
// they create the popups themselves (because of custom trigger divs).
|
// they create the popups themselves (because of custom trigger divs).
|
||||||
const IGNORE_TYPES = [
|
const IGNORE_TYPES = [
|
||||||
'Line',
|
"Line",
|
||||||
'Square',
|
"Square",
|
||||||
'Circle',
|
"Circle",
|
||||||
'PolyLine',
|
"PolyLine",
|
||||||
'Polygon',
|
"Polygon",
|
||||||
'Ink',
|
"Ink",
|
||||||
];
|
];
|
||||||
|
|
||||||
this.container.className = 'popupAnnotation';
|
this.container.className = "popupAnnotation";
|
||||||
|
|
||||||
if (IGNORE_TYPES.includes(this.data.parentType)) {
|
if (IGNORE_TYPES.includes(this.data.parentType)) {
|
||||||
return this.container;
|
return this.container;
|
||||||
@ -667,8 +695,9 @@ class PopupAnnotationElement extends AnnotationElement {
|
|||||||
// PDF viewers ignore a popup annotation's rectangle.
|
// PDF viewers ignore a popup annotation's rectangle.
|
||||||
const parentLeft = parseFloat(parentElement.style.left);
|
const parentLeft = parseFloat(parentElement.style.left);
|
||||||
const parentWidth = parseFloat(parentElement.style.width);
|
const parentWidth = parseFloat(parentElement.style.width);
|
||||||
this.container.style.transformOrigin =
|
this.container.style.transformOrigin = `-${parentLeft + parentWidth}px -${
|
||||||
`-${parentLeft + parentWidth}px -${parentElement.style.top}`;
|
parentElement.style.top
|
||||||
|
}`;
|
||||||
this.container.style.left = `${parentLeft + parentWidth}px`;
|
this.container.style.left = `${parentLeft + parentWidth}px`;
|
||||||
|
|
||||||
this.container.appendChild(popup.render());
|
this.container.appendChild(popup.render());
|
||||||
@ -699,18 +728,18 @@ class PopupElement {
|
|||||||
render() {
|
render() {
|
||||||
const BACKGROUND_ENLIGHT = 0.7;
|
const BACKGROUND_ENLIGHT = 0.7;
|
||||||
|
|
||||||
const wrapper = document.createElement('div');
|
const wrapper = document.createElement("div");
|
||||||
wrapper.className = 'popupWrapper';
|
wrapper.className = "popupWrapper";
|
||||||
|
|
||||||
// For Popup annotations we hide the entire section because it contains
|
// For Popup annotations we hide the entire section because it contains
|
||||||
// only the popup. However, for Text annotations without a separate Popup
|
// only the popup. However, for Text annotations without a separate Popup
|
||||||
// annotation, we cannot hide the entire container as the image would
|
// annotation, we cannot hide the entire container as the image would
|
||||||
// disappear too. In that special case, hiding the wrapper suffices.
|
// disappear too. In that special case, hiding the wrapper suffices.
|
||||||
this.hideElement = (this.hideWrapper ? wrapper : this.container);
|
this.hideElement = this.hideWrapper ? wrapper : this.container;
|
||||||
this.hideElement.setAttribute('hidden', true);
|
this.hideElement.setAttribute("hidden", true);
|
||||||
|
|
||||||
const popup = document.createElement('div');
|
const popup = document.createElement("div");
|
||||||
popup.className = 'popup';
|
popup.className = "popup";
|
||||||
|
|
||||||
const color = this.color;
|
const color = this.color;
|
||||||
if (color) {
|
if (color) {
|
||||||
@ -721,7 +750,7 @@ class PopupElement {
|
|||||||
popup.style.backgroundColor = Util.makeCssRgb(r | 0, g | 0, b | 0);
|
popup.style.backgroundColor = Util.makeCssRgb(r | 0, g | 0, b | 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = document.createElement('h1');
|
const title = document.createElement("h1");
|
||||||
title.textContent = this.title;
|
title.textContent = this.title;
|
||||||
popup.appendChild(title);
|
popup.appendChild(title);
|
||||||
|
|
||||||
@ -730,9 +759,9 @@ class PopupElement {
|
|||||||
// consistent with other viewers such as Adobe Acrobat.
|
// consistent with other viewers such as Adobe Acrobat.
|
||||||
const dateObject = PDFDateString.toDateObject(this.modificationDate);
|
const dateObject = PDFDateString.toDateObject(this.modificationDate);
|
||||||
if (dateObject) {
|
if (dateObject) {
|
||||||
const modificationDate = document.createElement('span');
|
const modificationDate = document.createElement("span");
|
||||||
modificationDate.textContent = '{{date}}, {{time}}';
|
modificationDate.textContent = "{{date}}, {{time}}";
|
||||||
modificationDate.dataset.l10nId = 'annotation_date_string';
|
modificationDate.dataset.l10nId = "annotation_date_string";
|
||||||
modificationDate.dataset.l10nArgs = JSON.stringify({
|
modificationDate.dataset.l10nArgs = JSON.stringify({
|
||||||
date: dateObject.toLocaleDateString(),
|
date: dateObject.toLocaleDateString(),
|
||||||
time: dateObject.toLocaleTimeString(),
|
time: dateObject.toLocaleTimeString(),
|
||||||
@ -744,10 +773,10 @@ class PopupElement {
|
|||||||
popup.appendChild(contents);
|
popup.appendChild(contents);
|
||||||
|
|
||||||
// Attach the event listeners to the trigger element.
|
// Attach the event listeners to the trigger element.
|
||||||
this.trigger.addEventListener('click', this._toggle.bind(this));
|
this.trigger.addEventListener("click", this._toggle.bind(this));
|
||||||
this.trigger.addEventListener('mouseover', this._show.bind(this, false));
|
this.trigger.addEventListener("mouseover", this._show.bind(this, false));
|
||||||
this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
|
this.trigger.addEventListener("mouseout", this._hide.bind(this, false));
|
||||||
popup.addEventListener('click', this._hide.bind(this, true));
|
popup.addEventListener("click", this._hide.bind(this, true));
|
||||||
|
|
||||||
wrapper.appendChild(popup);
|
wrapper.appendChild(popup);
|
||||||
return wrapper;
|
return wrapper;
|
||||||
@ -762,13 +791,13 @@ class PopupElement {
|
|||||||
* @returns {HTMLParagraphElement}
|
* @returns {HTMLParagraphElement}
|
||||||
*/
|
*/
|
||||||
_formatContents(contents) {
|
_formatContents(contents) {
|
||||||
const p = document.createElement('p');
|
const p = document.createElement("p");
|
||||||
const lines = contents.split(/(?:\r\n?|\n)/);
|
const lines = contents.split(/(?:\r\n?|\n)/);
|
||||||
for (let i = 0, ii = lines.length; i < ii; ++i) {
|
for (let i = 0, ii = lines.length; i < ii; ++i) {
|
||||||
const line = lines[i];
|
const line = lines[i];
|
||||||
p.appendChild(document.createTextNode(line));
|
p.appendChild(document.createTextNode(line));
|
||||||
if (i < (ii - 1)) {
|
if (i < ii - 1) {
|
||||||
p.appendChild(document.createElement('br'));
|
p.appendChild(document.createElement("br"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
@ -799,8 +828,8 @@ class PopupElement {
|
|||||||
if (pin) {
|
if (pin) {
|
||||||
this.pinned = true;
|
this.pinned = true;
|
||||||
}
|
}
|
||||||
if (this.hideElement.hasAttribute('hidden')) {
|
if (this.hideElement.hasAttribute("hidden")) {
|
||||||
this.hideElement.removeAttribute('hidden');
|
this.hideElement.removeAttribute("hidden");
|
||||||
this.container.style.zIndex += 1;
|
this.container.style.zIndex += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -816,8 +845,8 @@ class PopupElement {
|
|||||||
if (unpin) {
|
if (unpin) {
|
||||||
this.pinned = false;
|
this.pinned = false;
|
||||||
}
|
}
|
||||||
if (!this.hideElement.hasAttribute('hidden') && !this.pinned) {
|
if (!this.hideElement.hasAttribute("hidden") && !this.pinned) {
|
||||||
this.hideElement.setAttribute('hidden', true);
|
this.hideElement.setAttribute("hidden", true);
|
||||||
this.container.style.zIndex -= 1;
|
this.container.style.zIndex -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -825,8 +854,11 @@ class PopupElement {
|
|||||||
|
|
||||||
class FreeTextAnnotationElement extends AnnotationElement {
|
class FreeTextAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -838,7 +870,7 @@ class FreeTextAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'freeTextAnnotation';
|
this.container.className = "freeTextAnnotation";
|
||||||
|
|
||||||
if (!this.data.hasPopup) {
|
if (!this.data.hasPopup) {
|
||||||
this._createPopup(this.container, null, this.data);
|
this._createPopup(this.container, null, this.data);
|
||||||
@ -849,8 +881,11 @@ class FreeTextAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class LineAnnotationElement extends AnnotationElement {
|
class LineAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -862,7 +897,7 @@ class LineAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'lineAnnotation';
|
this.container.className = "lineAnnotation";
|
||||||
|
|
||||||
// Create an invisible line with the same starting and ending coordinates
|
// Create an invisible line with the same starting and ending coordinates
|
||||||
// that acts as the trigger for the popup. Only the line itself should
|
// that acts as the trigger for the popup. Only the line itself should
|
||||||
@ -874,15 +909,15 @@ class LineAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
// PDF coordinates are calculated from a bottom left origin, so transform
|
// PDF coordinates are calculated from a bottom left origin, so transform
|
||||||
// the line coordinates to a top left origin for the SVG element.
|
// the line coordinates to a top left origin for the SVG element.
|
||||||
const line = this.svgFactory.createElement('svg:line');
|
const line = this.svgFactory.createElement("svg:line");
|
||||||
line.setAttribute('x1', data.rect[2] - data.lineCoordinates[0]);
|
line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]);
|
||||||
line.setAttribute('y1', data.rect[3] - data.lineCoordinates[1]);
|
line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]);
|
||||||
line.setAttribute('x2', data.rect[2] - data.lineCoordinates[2]);
|
line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]);
|
||||||
line.setAttribute('y2', data.rect[3] - data.lineCoordinates[3]);
|
line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]);
|
||||||
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
||||||
// won't be possible to open/close the popup (note e.g. issue 11122).
|
// won't be possible to open/close the popup (note e.g. issue 11122).
|
||||||
line.setAttribute('stroke-width', data.borderStyle.width || 1);
|
line.setAttribute("stroke-width", data.borderStyle.width || 1);
|
||||||
line.setAttribute('stroke', 'transparent');
|
line.setAttribute("stroke", "transparent");
|
||||||
|
|
||||||
svg.appendChild(line);
|
svg.appendChild(line);
|
||||||
this.container.append(svg);
|
this.container.append(svg);
|
||||||
@ -897,8 +932,11 @@ class LineAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class SquareAnnotationElement extends AnnotationElement {
|
class SquareAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -910,7 +948,7 @@ class SquareAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'squareAnnotation';
|
this.container.className = "squareAnnotation";
|
||||||
|
|
||||||
// Create an invisible square with the same rectangle that acts as the
|
// Create an invisible square with the same rectangle that acts as the
|
||||||
// trigger for the popup. Only the square itself should trigger the
|
// trigger for the popup. Only the square itself should trigger the
|
||||||
@ -924,16 +962,16 @@ class SquareAnnotationElement extends AnnotationElement {
|
|||||||
// the borders outside the square by default. This behavior cannot be
|
// the borders outside the square by default. This behavior cannot be
|
||||||
// changed programmatically, so correct for that here.
|
// changed programmatically, so correct for that here.
|
||||||
const borderWidth = data.borderStyle.width;
|
const borderWidth = data.borderStyle.width;
|
||||||
const square = this.svgFactory.createElement('svg:rect');
|
const square = this.svgFactory.createElement("svg:rect");
|
||||||
square.setAttribute('x', borderWidth / 2);
|
square.setAttribute("x", borderWidth / 2);
|
||||||
square.setAttribute('y', borderWidth / 2);
|
square.setAttribute("y", borderWidth / 2);
|
||||||
square.setAttribute('width', width - borderWidth);
|
square.setAttribute("width", width - borderWidth);
|
||||||
square.setAttribute('height', height - borderWidth);
|
square.setAttribute("height", height - borderWidth);
|
||||||
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
||||||
// won't be possible to open/close the popup (note e.g. issue 11122).
|
// won't be possible to open/close the popup (note e.g. issue 11122).
|
||||||
square.setAttribute('stroke-width', borderWidth || 1);
|
square.setAttribute("stroke-width", borderWidth || 1);
|
||||||
square.setAttribute('stroke', 'transparent');
|
square.setAttribute("stroke", "transparent");
|
||||||
square.setAttribute('fill', 'none');
|
square.setAttribute("fill", "none");
|
||||||
|
|
||||||
svg.appendChild(square);
|
svg.appendChild(square);
|
||||||
this.container.append(svg);
|
this.container.append(svg);
|
||||||
@ -948,8 +986,11 @@ class SquareAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class CircleAnnotationElement extends AnnotationElement {
|
class CircleAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,7 +1002,7 @@ class CircleAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'circleAnnotation';
|
this.container.className = "circleAnnotation";
|
||||||
|
|
||||||
// Create an invisible circle with the same ellipse that acts as the
|
// Create an invisible circle with the same ellipse that acts as the
|
||||||
// trigger for the popup. Only the circle itself should trigger the
|
// trigger for the popup. Only the circle itself should trigger the
|
||||||
@ -975,16 +1016,16 @@ class CircleAnnotationElement extends AnnotationElement {
|
|||||||
// the borders outside the circle by default. This behavior cannot be
|
// the borders outside the circle by default. This behavior cannot be
|
||||||
// changed programmatically, so correct for that here.
|
// changed programmatically, so correct for that here.
|
||||||
const borderWidth = data.borderStyle.width;
|
const borderWidth = data.borderStyle.width;
|
||||||
const circle = this.svgFactory.createElement('svg:ellipse');
|
const circle = this.svgFactory.createElement("svg:ellipse");
|
||||||
circle.setAttribute('cx', width / 2);
|
circle.setAttribute("cx", width / 2);
|
||||||
circle.setAttribute('cy', height / 2);
|
circle.setAttribute("cy", height / 2);
|
||||||
circle.setAttribute('rx', (width / 2) - (borderWidth / 2));
|
circle.setAttribute("rx", width / 2 - borderWidth / 2);
|
||||||
circle.setAttribute('ry', (height / 2) - (borderWidth / 2));
|
circle.setAttribute("ry", height / 2 - borderWidth / 2);
|
||||||
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
||||||
// won't be possible to open/close the popup (note e.g. issue 11122).
|
// won't be possible to open/close the popup (note e.g. issue 11122).
|
||||||
circle.setAttribute('stroke-width', borderWidth || 1);
|
circle.setAttribute("stroke-width", borderWidth || 1);
|
||||||
circle.setAttribute('stroke', 'transparent');
|
circle.setAttribute("stroke", "transparent");
|
||||||
circle.setAttribute('fill', 'none');
|
circle.setAttribute("fill", "none");
|
||||||
|
|
||||||
svg.appendChild(circle);
|
svg.appendChild(circle);
|
||||||
this.container.append(svg);
|
this.container.append(svg);
|
||||||
@ -999,12 +1040,15 @@ class CircleAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class PolylineAnnotationElement extends AnnotationElement {
|
class PolylineAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
|
|
||||||
this.containerClassName = 'polylineAnnotation';
|
this.containerClassName = "polylineAnnotation";
|
||||||
this.svgElementName = 'svg:polyline';
|
this.svgElementName = "svg:polyline";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1033,17 +1077,17 @@ class PolylineAnnotationElement extends AnnotationElement {
|
|||||||
for (const coordinate of data.vertices) {
|
for (const coordinate of data.vertices) {
|
||||||
const x = coordinate.x - data.rect[0];
|
const x = coordinate.x - data.rect[0];
|
||||||
const y = data.rect[3] - coordinate.y;
|
const y = data.rect[3] - coordinate.y;
|
||||||
points.push(x + ',' + y);
|
points.push(x + "," + y);
|
||||||
}
|
}
|
||||||
points = points.join(' ');
|
points = points.join(" ");
|
||||||
|
|
||||||
const polyline = this.svgFactory.createElement(this.svgElementName);
|
const polyline = this.svgFactory.createElement(this.svgElementName);
|
||||||
polyline.setAttribute('points', points);
|
polyline.setAttribute("points", points);
|
||||||
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
||||||
// won't be possible to open/close the popup (note e.g. issue 11122).
|
// won't be possible to open/close the popup (note e.g. issue 11122).
|
||||||
polyline.setAttribute('stroke-width', data.borderStyle.width || 1);
|
polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
|
||||||
polyline.setAttribute('stroke', 'transparent');
|
polyline.setAttribute("stroke", "transparent");
|
||||||
polyline.setAttribute('fill', 'none');
|
polyline.setAttribute("fill", "none");
|
||||||
|
|
||||||
svg.appendChild(polyline);
|
svg.appendChild(polyline);
|
||||||
this.container.append(svg);
|
this.container.append(svg);
|
||||||
@ -1061,15 +1105,18 @@ class PolygonAnnotationElement extends PolylineAnnotationElement {
|
|||||||
// Polygons are specific forms of polylines, so reuse their logic.
|
// Polygons are specific forms of polylines, so reuse their logic.
|
||||||
super(parameters);
|
super(parameters);
|
||||||
|
|
||||||
this.containerClassName = 'polygonAnnotation';
|
this.containerClassName = "polygonAnnotation";
|
||||||
this.svgElementName = 'svg:polygon';
|
this.svgElementName = "svg:polygon";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CaretAnnotationElement extends AnnotationElement {
|
class CaretAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1081,7 +1128,7 @@ class CaretAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'caretAnnotation';
|
this.container.className = "caretAnnotation";
|
||||||
|
|
||||||
if (!this.data.hasPopup) {
|
if (!this.data.hasPopup) {
|
||||||
this._createPopup(this.container, null, this.data);
|
this._createPopup(this.container, null, this.data);
|
||||||
@ -1092,15 +1139,18 @@ class CaretAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class InkAnnotationElement extends AnnotationElement {
|
class InkAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
|
|
||||||
this.containerClassName = 'inkAnnotation';
|
this.containerClassName = "inkAnnotation";
|
||||||
|
|
||||||
// Use the polyline SVG element since it allows us to use coordinates
|
// Use the polyline SVG element since it allows us to use coordinates
|
||||||
// directly and to draw both straight lines and curves.
|
// directly and to draw both straight lines and curves.
|
||||||
this.svgElementName = 'svg:polyline';
|
this.svgElementName = "svg:polyline";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1131,15 +1181,15 @@ class InkAnnotationElement extends AnnotationElement {
|
|||||||
const y = data.rect[3] - coordinate.y;
|
const y = data.rect[3] - coordinate.y;
|
||||||
points.push(`${x},${y}`);
|
points.push(`${x},${y}`);
|
||||||
}
|
}
|
||||||
points = points.join(' ');
|
points = points.join(" ");
|
||||||
|
|
||||||
const polyline = this.svgFactory.createElement(this.svgElementName);
|
const polyline = this.svgFactory.createElement(this.svgElementName);
|
||||||
polyline.setAttribute('points', points);
|
polyline.setAttribute("points", points);
|
||||||
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
// Ensure that the 'stroke-width' is always non-zero, since otherwise it
|
||||||
// won't be possible to open/close the popup (note e.g. issue 11122).
|
// won't be possible to open/close the popup (note e.g. issue 11122).
|
||||||
polyline.setAttribute('stroke-width', data.borderStyle.width || 1);
|
polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
|
||||||
polyline.setAttribute('stroke', 'transparent');
|
polyline.setAttribute("stroke", "transparent");
|
||||||
polyline.setAttribute('fill', 'none');
|
polyline.setAttribute("fill", "none");
|
||||||
|
|
||||||
// Create the popup ourselves so that we can bind it to the polyline
|
// Create the popup ourselves so that we can bind it to the polyline
|
||||||
// instead of to the entire container (which is the default).
|
// instead of to the entire container (which is the default).
|
||||||
@ -1155,8 +1205,11 @@ class InkAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class HighlightAnnotationElement extends AnnotationElement {
|
class HighlightAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1168,7 +1221,7 @@ class HighlightAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'highlightAnnotation';
|
this.container.className = "highlightAnnotation";
|
||||||
|
|
||||||
if (!this.data.hasPopup) {
|
if (!this.data.hasPopup) {
|
||||||
this._createPopup(this.container, null, this.data);
|
this._createPopup(this.container, null, this.data);
|
||||||
@ -1179,8 +1232,11 @@ class HighlightAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class UnderlineAnnotationElement extends AnnotationElement {
|
class UnderlineAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1192,7 +1248,7 @@ class UnderlineAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'underlineAnnotation';
|
this.container.className = "underlineAnnotation";
|
||||||
|
|
||||||
if (!this.data.hasPopup) {
|
if (!this.data.hasPopup) {
|
||||||
this._createPopup(this.container, null, this.data);
|
this._createPopup(this.container, null, this.data);
|
||||||
@ -1203,8 +1259,11 @@ class UnderlineAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class SquigglyAnnotationElement extends AnnotationElement {
|
class SquigglyAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1216,7 +1275,7 @@ class SquigglyAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'squigglyAnnotation';
|
this.container.className = "squigglyAnnotation";
|
||||||
|
|
||||||
if (!this.data.hasPopup) {
|
if (!this.data.hasPopup) {
|
||||||
this._createPopup(this.container, null, this.data);
|
this._createPopup(this.container, null, this.data);
|
||||||
@ -1227,8 +1286,11 @@ class SquigglyAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class StrikeOutAnnotationElement extends AnnotationElement {
|
class StrikeOutAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1240,7 +1302,7 @@ class StrikeOutAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'strikeoutAnnotation';
|
this.container.className = "strikeoutAnnotation";
|
||||||
|
|
||||||
if (!this.data.hasPopup) {
|
if (!this.data.hasPopup) {
|
||||||
this._createPopup(this.container, null, this.data);
|
this._createPopup(this.container, null, this.data);
|
||||||
@ -1251,8 +1313,11 @@ class StrikeOutAnnotationElement extends AnnotationElement {
|
|||||||
|
|
||||||
class StampAnnotationElement extends AnnotationElement {
|
class StampAnnotationElement extends AnnotationElement {
|
||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
const isRenderable = !!(parameters.data.hasPopup ||
|
const isRenderable = !!(
|
||||||
parameters.data.title || parameters.data.contents);
|
parameters.data.hasPopup ||
|
||||||
|
parameters.data.title ||
|
||||||
|
parameters.data.contents
|
||||||
|
);
|
||||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1264,7 +1329,7 @@ class StampAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'stampAnnotation';
|
this.container.className = "stampAnnotation";
|
||||||
|
|
||||||
if (!this.data.hasPopup) {
|
if (!this.data.hasPopup) {
|
||||||
this._createPopup(this.container, null, this.data);
|
this._createPopup(this.container, null, this.data);
|
||||||
@ -1277,12 +1342,12 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
|||||||
constructor(parameters) {
|
constructor(parameters) {
|
||||||
super(parameters, /* isRenderable = */ true);
|
super(parameters, /* isRenderable = */ true);
|
||||||
|
|
||||||
const { filename, content, } = this.data.file;
|
const { filename, content } = this.data.file;
|
||||||
this.filename = getFilenameFromUrl(filename);
|
this.filename = getFilenameFromUrl(filename);
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
|
||||||
if (this.linkService.eventBus) {
|
if (this.linkService.eventBus) {
|
||||||
this.linkService.eventBus.dispatch('fileattachmentannotation', {
|
this.linkService.eventBus.dispatch("fileattachmentannotation", {
|
||||||
source: this,
|
source: this,
|
||||||
id: stringToPDFString(filename),
|
id: stringToPDFString(filename),
|
||||||
filename,
|
filename,
|
||||||
@ -1300,12 +1365,12 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
|||||||
* @returns {HTMLSectionElement}
|
* @returns {HTMLSectionElement}
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
this.container.className = 'fileAttachmentAnnotation';
|
this.container.className = "fileAttachmentAnnotation";
|
||||||
|
|
||||||
const trigger = document.createElement('div');
|
const trigger = document.createElement("div");
|
||||||
trigger.style.height = this.container.style.height;
|
trigger.style.height = this.container.style.height;
|
||||||
trigger.style.width = this.container.style.width;
|
trigger.style.width = this.container.style.width;
|
||||||
trigger.addEventListener('dblclick', this._download.bind(this));
|
trigger.addEventListener("dblclick", this._download.bind(this));
|
||||||
|
|
||||||
if (!this.data.hasPopup && (this.data.title || this.data.contents)) {
|
if (!this.data.hasPopup && (this.data.title || this.data.contents)) {
|
||||||
this._createPopup(this.container, trigger, this.data);
|
this._createPopup(this.container, trigger, this.data);
|
||||||
@ -1323,10 +1388,10 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
|||||||
*/
|
*/
|
||||||
_download() {
|
_download() {
|
||||||
if (!this.downloadManager) {
|
if (!this.downloadManager) {
|
||||||
warn('Download cannot be started due to unavailable download manager');
|
warn("Download cannot be started due to unavailable download manager");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.downloadManager.downloadData(this.content, this.filename, '');
|
this.downloadManager.downloadData(this.content, this.filename, "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1363,7 +1428,7 @@ class AnnotationLayer {
|
|||||||
viewport: parameters.viewport,
|
viewport: parameters.viewport,
|
||||||
linkService: parameters.linkService,
|
linkService: parameters.linkService,
|
||||||
downloadManager: parameters.downloadManager,
|
downloadManager: parameters.downloadManager,
|
||||||
imageResourcesPath: parameters.imageResourcesPath || '',
|
imageResourcesPath: parameters.imageResourcesPath || "",
|
||||||
renderInteractiveForms: parameters.renderInteractiveForms || false,
|
renderInteractiveForms: parameters.renderInteractiveForms || false,
|
||||||
svgFactory: new DOMSVGFactory(),
|
svgFactory: new DOMSVGFactory(),
|
||||||
});
|
});
|
||||||
@ -1383,16 +1448,16 @@ class AnnotationLayer {
|
|||||||
static update(parameters) {
|
static update(parameters) {
|
||||||
for (const data of parameters.annotations) {
|
for (const data of parameters.annotations) {
|
||||||
const element = parameters.div.querySelector(
|
const element = parameters.div.querySelector(
|
||||||
`[data-annotation-id="${data.id}"]`);
|
`[data-annotation-id="${data.id}"]`
|
||||||
|
);
|
||||||
if (element) {
|
if (element) {
|
||||||
element.style.transform =
|
element.style.transform = `matrix(${parameters.viewport.transform.join(
|
||||||
`matrix(${parameters.viewport.transform.join(',')})`;
|
","
|
||||||
|
)})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parameters.div.removeAttribute('hidden');
|
parameters.div.removeAttribute("hidden");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { AnnotationLayer };
|
||||||
AnnotationLayer,
|
|
||||||
};
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -14,11 +14,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
let compatibilityParams = Object.create(null);
|
let compatibilityParams = Object.create(null);
|
||||||
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
|
||||||
const { isNodeJS, } = require('../shared/is_node');
|
const { isNodeJS } = require("../shared/is_node");
|
||||||
|
|
||||||
const userAgent =
|
const userAgent =
|
||||||
(typeof navigator !== 'undefined' && navigator.userAgent) || '';
|
(typeof navigator !== "undefined" && navigator.userAgent) || "";
|
||||||
const isIE = /Trident/.test(userAgent);
|
const isIE = /Trident/.test(userAgent);
|
||||||
const isIOSChrome = /CriOS/.test(userAgent);
|
const isIOSChrome = /CriOS/.test(userAgent);
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
|||||||
// Node.js is missing native support for `@font-face` and `Image`.
|
// Node.js is missing native support for `@font-face` and `Image`.
|
||||||
if (isNodeJS) {
|
if (isNodeJS) {
|
||||||
compatibilityParams.disableFontFace = true;
|
compatibilityParams.disableFontFace = true;
|
||||||
compatibilityParams.nativeImageDecoderSupport = 'none';
|
compatibilityParams.nativeImageDecoderSupport = "none";
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -31,7 +31,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
let needsEncodingFixup = true;
|
let needsEncodingFixup = true;
|
||||||
|
|
||||||
// filename*=ext-value ("ext-value" from RFC 5987, referenced by RFC 6266).
|
// filename*=ext-value ("ext-value" from RFC 5987, referenced by RFC 6266).
|
||||||
let tmp = toParamRegExp('filename\\*', 'i').exec(contentDisposition);
|
let tmp = toParamRegExp("filename\\*", "i").exec(contentDisposition);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
tmp = tmp[1];
|
tmp = tmp[1];
|
||||||
let filename = rfc2616unquote(tmp);
|
let filename = rfc2616unquote(tmp);
|
||||||
@ -52,7 +52,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// filename=value (RFC 5987, section 4.1).
|
// filename=value (RFC 5987, section 4.1).
|
||||||
tmp = toParamRegExp('filename', 'i').exec(contentDisposition);
|
tmp = toParamRegExp("filename", "i").exec(contentDisposition);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
tmp = tmp[1];
|
tmp = tmp[1];
|
||||||
let filename = rfc2616unquote(tmp);
|
let filename = rfc2616unquote(tmp);
|
||||||
@ -65,14 +65,18 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
// declarations...
|
// declarations...
|
||||||
function toParamRegExp(attributePattern, flags) {
|
function toParamRegExp(attributePattern, flags) {
|
||||||
return new RegExp(
|
return new RegExp(
|
||||||
'(?:^|;)\\s*' + attributePattern + '\\s*=\\s*' +
|
"(?:^|;)\\s*" +
|
||||||
|
attributePattern +
|
||||||
|
"\\s*=\\s*" +
|
||||||
// Captures: value = token | quoted-string
|
// Captures: value = token | quoted-string
|
||||||
// (RFC 2616, section 3.6 and referenced by RFC 6266 4.1)
|
// (RFC 2616, section 3.6 and referenced by RFC 6266 4.1)
|
||||||
'(' +
|
"(" +
|
||||||
'[^";\\s][^;\\s]*' +
|
'[^";\\s][^;\\s]*' +
|
||||||
'|' +
|
"|" +
|
||||||
'"(?:[^"\\\\]|\\\\"?)+"?' +
|
'"(?:[^"\\\\]|\\\\"?)+"?' +
|
||||||
')', flags);
|
")",
|
||||||
|
flags
|
||||||
|
);
|
||||||
}
|
}
|
||||||
function textdecode(encoding, value) {
|
function textdecode(encoding, value) {
|
||||||
if (encoding) {
|
if (encoding) {
|
||||||
@ -80,9 +84,9 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let decoder = new TextDecoder(encoding, { fatal: true, });
|
let decoder = new TextDecoder(encoding, { fatal: true });
|
||||||
let bytes = Array.from(value, function(ch) {
|
let bytes = Array.from(value, function(ch) {
|
||||||
return ch.charCodeAt(0) & 0xFF;
|
return ch.charCodeAt(0) & 0xff;
|
||||||
});
|
});
|
||||||
value = decoder.decode(new Uint8Array(bytes));
|
value = decoder.decode(new Uint8Array(bytes));
|
||||||
needsEncodingFixup = false;
|
needsEncodingFixup = false;
|
||||||
@ -94,8 +98,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
try {
|
try {
|
||||||
value = decodeURIComponent(escape(value));
|
value = decodeURIComponent(escape(value));
|
||||||
needsEncodingFixup = false;
|
needsEncodingFixup = false;
|
||||||
} catch (err) {
|
} catch (err) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,19 +107,20 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
function fixupEncoding(value) {
|
function fixupEncoding(value) {
|
||||||
if (needsEncodingFixup && /[\x80-\xff]/.test(value)) {
|
if (needsEncodingFixup && /[\x80-\xff]/.test(value)) {
|
||||||
// Maybe multi-byte UTF-8.
|
// Maybe multi-byte UTF-8.
|
||||||
value = textdecode('utf-8', value);
|
value = textdecode("utf-8", value);
|
||||||
if (needsEncodingFixup) {
|
if (needsEncodingFixup) {
|
||||||
// Try iso-8859-1 encoding.
|
// Try iso-8859-1 encoding.
|
||||||
value = textdecode('iso-8859-1', value);
|
value = textdecode("iso-8859-1", value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
function rfc2231getparam(contentDisposition) {
|
function rfc2231getparam(contentDisposition) {
|
||||||
let matches = [], match;
|
let matches = [],
|
||||||
|
match;
|
||||||
// Iterate over all filename*n= and filename*n*= with n being an integer
|
// Iterate over all filename*n= and filename*n*= with n being an integer
|
||||||
// of at least zero. Any non-zero number must not start with '0'.
|
// of at least zero. Any non-zero number must not start with '0'.
|
||||||
let iter = toParamRegExp('filename\\*((?!0\\d)\\d+)(\\*?)', 'ig');
|
let iter = toParamRegExp("filename\\*((?!0\\d)\\d+)(\\*?)", "ig");
|
||||||
while ((match = iter.exec(contentDisposition)) !== null) {
|
while ((match = iter.exec(contentDisposition)) !== null) {
|
||||||
let [, n, quot, part] = match;
|
let [, n, quot, part] = match;
|
||||||
n = parseInt(n, 10);
|
n = parseInt(n, 10);
|
||||||
@ -145,7 +149,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
}
|
}
|
||||||
parts.push(part);
|
parts.push(part);
|
||||||
}
|
}
|
||||||
return parts.join('');
|
return parts.join("");
|
||||||
}
|
}
|
||||||
function rfc2616unquote(value) {
|
function rfc2616unquote(value) {
|
||||||
if (value.startsWith('"')) {
|
if (value.startsWith('"')) {
|
||||||
@ -157,7 +161,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
parts[i] = parts[i].slice(0, quotindex);
|
parts[i] = parts[i].slice(0, quotindex);
|
||||||
parts.length = i + 1; // Truncates and stop the iteration.
|
parts.length = i + 1; // Truncates and stop the iteration.
|
||||||
}
|
}
|
||||||
parts[i] = parts[i].replace(/\\(.)/g, '$1');
|
parts[i] = parts[i].replace(/\\(.)/g, "$1");
|
||||||
}
|
}
|
||||||
value = parts.join('"');
|
value = parts.join('"');
|
||||||
}
|
}
|
||||||
@ -165,7 +169,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
}
|
}
|
||||||
function rfc5987decode(extvalue) {
|
function rfc5987decode(extvalue) {
|
||||||
// Decodes "ext-value" from RFC 5987.
|
// Decodes "ext-value" from RFC 5987.
|
||||||
let encodingend = extvalue.indexOf('\'');
|
let encodingend = extvalue.indexOf("'");
|
||||||
if (encodingend === -1) {
|
if (encodingend === -1) {
|
||||||
// Some servers send "filename*=" without encoding 'language' prefix,
|
// Some servers send "filename*=" without encoding 'language' prefix,
|
||||||
// e.g. in https://github.com/Rob--W/open-in-browser/issues/26
|
// e.g. in https://github.com/Rob--W/open-in-browser/issues/26
|
||||||
@ -175,7 +179,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
let encoding = extvalue.slice(0, encodingend);
|
let encoding = extvalue.slice(0, encodingend);
|
||||||
let langvalue = extvalue.slice(encodingend + 1);
|
let langvalue = extvalue.slice(encodingend + 1);
|
||||||
// Ignore language (RFC 5987 section 3.2.1, and RFC 6266 section 4.1 ).
|
// Ignore language (RFC 5987 section 3.2.1, and RFC 6266 section 4.1 ).
|
||||||
let value = langvalue.replace(/^[^']*'/, '');
|
let value = langvalue.replace(/^[^']*'/, "");
|
||||||
return textdecode(encoding, value);
|
return textdecode(encoding, value);
|
||||||
}
|
}
|
||||||
function rfc2047decode(value) {
|
function rfc2047decode(value) {
|
||||||
@ -189,7 +193,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
|
|
||||||
// Firefox also decodes words even where RFC 2047 section 5 states:
|
// Firefox also decodes words even where RFC 2047 section 5 states:
|
||||||
// "An 'encoded-word' MUST NOT appear within a 'quoted-string'."
|
// "An 'encoded-word' MUST NOT appear within a 'quoted-string'."
|
||||||
if (!value.startsWith('=?') || /[\x00-\x19\x80-\xff]/.test(value)) {
|
if (!value.startsWith("=?") || /[\x00-\x19\x80-\xff]/.test(value)) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
// RFC 2047, section 2.4
|
// RFC 2047, section 2.4
|
||||||
@ -199,11 +203,12 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
// encoding = q or b
|
// encoding = q or b
|
||||||
// encoded-text = any printable ASCII character other than ? or space.
|
// encoded-text = any printable ASCII character other than ? or space.
|
||||||
// ... but Firefox permits ? and space.
|
// ... but Firefox permits ? and space.
|
||||||
return value.replace(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g,
|
return value.replace(
|
||||||
|
/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g,
|
||||||
function(_, charset, encoding, text) {
|
function(_, charset, encoding, text) {
|
||||||
if (encoding === 'q' || encoding === 'Q') {
|
if (encoding === "q" || encoding === "Q") {
|
||||||
// RFC 2047 section 4.2.
|
// RFC 2047 section 4.2.
|
||||||
text = text.replace(/_/g, ' ');
|
text = text.replace(/_/g, " ");
|
||||||
text = text.replace(/=([0-9a-fA-F]{2})/g, function(_, hex) {
|
text = text.replace(/=([0-9a-fA-F]{2})/g, function(_, hex) {
|
||||||
return String.fromCharCode(parseInt(hex, 16));
|
return String.fromCharCode(parseInt(hex, 16));
|
||||||
});
|
});
|
||||||
@ -211,15 +216,13 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
|||||||
} // else encoding is b or B - base64 (RFC 2047 section 4.1)
|
} // else encoding is b or B - base64 (RFC 2047 section 4.1)
|
||||||
try {
|
try {
|
||||||
text = atob(text);
|
text = atob(text);
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
return textdecode(charset, text);
|
return textdecode(charset, text);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { getFilenameFromContentDispositionHeader };
|
||||||
getFilenameFromContentDispositionHeader,
|
|
||||||
};
|
|
||||||
|
@ -15,20 +15,26 @@
|
|||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
assert, BaseException, CMapCompressionType, isString, removeNullCharacters,
|
assert,
|
||||||
stringToBytes, Util, warn
|
BaseException,
|
||||||
} from '../shared/util';
|
CMapCompressionType,
|
||||||
|
isString,
|
||||||
|
removeNullCharacters,
|
||||||
|
stringToBytes,
|
||||||
|
Util,
|
||||||
|
warn,
|
||||||
|
} from "../shared/util";
|
||||||
|
|
||||||
const DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
|
const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
|
||||||
const SVG_NS = 'http://www.w3.org/2000/svg';
|
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
class DOMCanvasFactory {
|
class DOMCanvasFactory {
|
||||||
create(width, height) {
|
create(width, height) {
|
||||||
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
||||||
throw new Error('Invalid canvas size');
|
throw new Error("Invalid canvas size");
|
||||||
}
|
}
|
||||||
const canvas = document.createElement('canvas');
|
const canvas = document.createElement("canvas");
|
||||||
const context = canvas.getContext('2d');
|
const context = canvas.getContext("2d");
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
return {
|
return {
|
||||||
@ -39,10 +45,10 @@ class DOMCanvasFactory {
|
|||||||
|
|
||||||
reset(canvasAndContext, width, height) {
|
reset(canvasAndContext, width, height) {
|
||||||
if (!canvasAndContext.canvas) {
|
if (!canvasAndContext.canvas) {
|
||||||
throw new Error('Canvas is not specified');
|
throw new Error("Canvas is not specified");
|
||||||
}
|
}
|
||||||
if (width <= 0 || height <= 0) {
|
if (width <= 0 || height <= 0) {
|
||||||
throw new Error('Invalid canvas size');
|
throw new Error("Invalid canvas size");
|
||||||
}
|
}
|
||||||
canvasAndContext.canvas.width = width;
|
canvasAndContext.canvas.width = width;
|
||||||
canvasAndContext.canvas.height = height;
|
canvasAndContext.canvas.height = height;
|
||||||
@ -50,7 +56,7 @@ class DOMCanvasFactory {
|
|||||||
|
|
||||||
destroy(canvasAndContext) {
|
destroy(canvasAndContext) {
|
||||||
if (!canvasAndContext.canvas) {
|
if (!canvasAndContext.canvas) {
|
||||||
throw new Error('Canvas is not specified');
|
throw new Error("Canvas is not specified");
|
||||||
}
|
}
|
||||||
// Zeroing the width and height cause Firefox to release graphics
|
// Zeroing the width and height cause Firefox to release graphics
|
||||||
// resources immediately, which can greatly reduce memory consumption.
|
// resources immediately, which can greatly reduce memory consumption.
|
||||||
@ -62,27 +68,32 @@ class DOMCanvasFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class DOMCMapReaderFactory {
|
class DOMCMapReaderFactory {
|
||||||
constructor({ baseUrl = null, isCompressed = false, }) {
|
constructor({ baseUrl = null, isCompressed = false }) {
|
||||||
this.baseUrl = baseUrl;
|
this.baseUrl = baseUrl;
|
||||||
this.isCompressed = isCompressed;
|
this.isCompressed = isCompressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetch({ name, }) {
|
async fetch({ name }) {
|
||||||
if (!this.baseUrl) {
|
if (!this.baseUrl) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'The CMap "baseUrl" parameter must be specified, ensure that ' +
|
'The CMap "baseUrl" parameter must be specified, ensure that ' +
|
||||||
'the "cMapUrl" and "cMapPacked" API parameters are provided.');
|
'the "cMapUrl" and "cMapPacked" API parameters are provided.'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!name) {
|
if (!name) {
|
||||||
throw new Error('CMap name must be specified.');
|
throw new Error("CMap name must be specified.");
|
||||||
}
|
}
|
||||||
const url = this.baseUrl + name + (this.isCompressed ? '.bcmap' : '');
|
const url = this.baseUrl + name + (this.isCompressed ? ".bcmap" : "");
|
||||||
const compressionType = (this.isCompressed ? CMapCompressionType.BINARY :
|
const compressionType = this.isCompressed
|
||||||
CMapCompressionType.NONE);
|
? CMapCompressionType.BINARY
|
||||||
|
: CMapCompressionType.NONE;
|
||||||
|
|
||||||
if ((typeof PDFJSDev !== 'undefined' && PDFJSDev.test('MOZCENTRAL')) ||
|
if (
|
||||||
(isFetchSupported() && isValidFetchUrl(url, document.baseURI))) {
|
(typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) ||
|
||||||
return fetch(url).then(async (response) => {
|
(isFetchSupported() && isValidFetchUrl(url, document.baseURI))
|
||||||
|
) {
|
||||||
|
return fetch(url)
|
||||||
|
.then(async response => {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(response.statusText);
|
throw new Error(response.statusText);
|
||||||
}
|
}
|
||||||
@ -92,20 +103,23 @@ class DOMCMapReaderFactory {
|
|||||||
} else {
|
} else {
|
||||||
cMapData = stringToBytes(await response.text());
|
cMapData = stringToBytes(await response.text());
|
||||||
}
|
}
|
||||||
return { cMapData, compressionType, };
|
return { cMapData, compressionType };
|
||||||
}).catch((reason) => {
|
})
|
||||||
throw new Error(`Unable to load ${this.isCompressed ? 'binary ' : ''}` +
|
.catch(reason => {
|
||||||
`CMap at: ${url}`);
|
throw new Error(
|
||||||
|
`Unable to load ${this.isCompressed ? "binary " : ""}` +
|
||||||
|
`CMap at: ${url}`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Fetch API is not supported.
|
// The Fetch API is not supported.
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const request = new XMLHttpRequest();
|
const request = new XMLHttpRequest();
|
||||||
request.open('GET', url, true);
|
request.open("GET", url, true);
|
||||||
|
|
||||||
if (this.isCompressed) {
|
if (this.isCompressed) {
|
||||||
request.responseType = 'arraybuffer';
|
request.responseType = "arraybuffer";
|
||||||
}
|
}
|
||||||
request.onreadystatechange = () => {
|
request.onreadystatechange = () => {
|
||||||
if (request.readyState !== XMLHttpRequest.DONE) {
|
if (request.readyState !== XMLHttpRequest.DONE) {
|
||||||
@ -119,7 +133,7 @@ class DOMCMapReaderFactory {
|
|||||||
cMapData = stringToBytes(request.responseText);
|
cMapData = stringToBytes(request.responseText);
|
||||||
}
|
}
|
||||||
if (cMapData) {
|
if (cMapData) {
|
||||||
resolve({ cMapData, compressionType, });
|
resolve({ cMapData, compressionType });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,29 +141,31 @@ class DOMCMapReaderFactory {
|
|||||||
};
|
};
|
||||||
|
|
||||||
request.send(null);
|
request.send(null);
|
||||||
}).catch((reason) => {
|
}).catch(reason => {
|
||||||
throw new Error(`Unable to load ${this.isCompressed ? 'binary ' : ''}` +
|
throw new Error(
|
||||||
`CMap at: ${url}`);
|
`Unable to load ${this.isCompressed ? "binary " : ""}` +
|
||||||
|
`CMap at: ${url}`
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DOMSVGFactory {
|
class DOMSVGFactory {
|
||||||
create(width, height) {
|
create(width, height) {
|
||||||
assert(width > 0 && height > 0, 'Invalid SVG dimensions');
|
assert(width > 0 && height > 0, "Invalid SVG dimensions");
|
||||||
|
|
||||||
const svg = document.createElementNS(SVG_NS, 'svg:svg');
|
const svg = document.createElementNS(SVG_NS, "svg:svg");
|
||||||
svg.setAttribute('version', '1.1');
|
svg.setAttribute("version", "1.1");
|
||||||
svg.setAttribute('width', width + 'px');
|
svg.setAttribute("width", width + "px");
|
||||||
svg.setAttribute('height', height + 'px');
|
svg.setAttribute("height", height + "px");
|
||||||
svg.setAttribute('preserveAspectRatio', 'none');
|
svg.setAttribute("preserveAspectRatio", "none");
|
||||||
svg.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
|
svg.setAttribute("viewBox", "0 0 " + width + " " + height);
|
||||||
|
|
||||||
return svg;
|
return svg;
|
||||||
}
|
}
|
||||||
|
|
||||||
createElement(type) {
|
createElement(type) {
|
||||||
assert(typeof type === 'string', 'Invalid SVG element type');
|
assert(typeof type === "string", "Invalid SVG element type");
|
||||||
|
|
||||||
return document.createElementNS(SVG_NS, type);
|
return document.createElementNS(SVG_NS, type);
|
||||||
}
|
}
|
||||||
@ -189,8 +205,14 @@ class PageViewport {
|
|||||||
/**
|
/**
|
||||||
* @param {PageViewportParameters}
|
* @param {PageViewportParameters}
|
||||||
*/
|
*/
|
||||||
constructor({ viewBox, scale, rotation, offsetX = 0, offsetY = 0,
|
constructor({
|
||||||
dontFlip = false, }) {
|
viewBox,
|
||||||
|
scale,
|
||||||
|
rotation,
|
||||||
|
offsetX = 0,
|
||||||
|
offsetY = 0,
|
||||||
|
dontFlip = false,
|
||||||
|
}) {
|
||||||
this.viewBox = viewBox;
|
this.viewBox = viewBox;
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
this.rotation = rotation;
|
this.rotation = rotation;
|
||||||
@ -206,22 +228,35 @@ class PageViewport {
|
|||||||
rotation = rotation < 0 ? rotation + 360 : rotation;
|
rotation = rotation < 0 ? rotation + 360 : rotation;
|
||||||
switch (rotation) {
|
switch (rotation) {
|
||||||
case 180:
|
case 180:
|
||||||
rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
|
rotateA = -1;
|
||||||
|
rotateB = 0;
|
||||||
|
rotateC = 0;
|
||||||
|
rotateD = 1;
|
||||||
break;
|
break;
|
||||||
case 90:
|
case 90:
|
||||||
rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
|
rotateA = 0;
|
||||||
|
rotateB = 1;
|
||||||
|
rotateC = 1;
|
||||||
|
rotateD = 0;
|
||||||
break;
|
break;
|
||||||
case 270:
|
case 270:
|
||||||
rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
|
rotateA = 0;
|
||||||
|
rotateB = -1;
|
||||||
|
rotateC = -1;
|
||||||
|
rotateD = 0;
|
||||||
break;
|
break;
|
||||||
// case 0:
|
// case 0:
|
||||||
default:
|
default:
|
||||||
rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
|
rotateA = 1;
|
||||||
|
rotateB = 0;
|
||||||
|
rotateC = 0;
|
||||||
|
rotateD = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dontFlip) {
|
if (dontFlip) {
|
||||||
rotateC = -rotateC; rotateD = -rotateD;
|
rotateC = -rotateC;
|
||||||
|
rotateD = -rotateD;
|
||||||
}
|
}
|
||||||
|
|
||||||
let offsetCanvasX, offsetCanvasY;
|
let offsetCanvasX, offsetCanvasY;
|
||||||
@ -246,7 +281,7 @@ class PageViewport {
|
|||||||
rotateC * scale,
|
rotateC * scale,
|
||||||
rotateD * scale,
|
rotateD * scale,
|
||||||
offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
|
offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
|
||||||
offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
|
offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY,
|
||||||
];
|
];
|
||||||
|
|
||||||
this.width = width;
|
this.width = width;
|
||||||
@ -258,8 +293,13 @@ class PageViewport {
|
|||||||
* @param {PageViewportCloneParameters} [params]
|
* @param {PageViewportCloneParameters} [params]
|
||||||
* @returns {PageViewport} Cloned viewport.
|
* @returns {PageViewport} Cloned viewport.
|
||||||
*/
|
*/
|
||||||
clone({ scale = this.scale, rotation = this.rotation, offsetX = this.offsetX,
|
clone({
|
||||||
offsetY = this.offsetY, dontFlip = false, } = {}) {
|
scale = this.scale,
|
||||||
|
rotation = this.rotation,
|
||||||
|
offsetX = this.offsetX,
|
||||||
|
offsetY = this.offsetY,
|
||||||
|
dontFlip = false,
|
||||||
|
} = {}) {
|
||||||
return new PageViewport({
|
return new PageViewport({
|
||||||
viewBox: this.viewBox.slice(),
|
viewBox: this.viewBox.slice(),
|
||||||
scale,
|
scale,
|
||||||
@ -343,50 +383,54 @@ const LinkTarget = {
|
|||||||
* @param {HTMLLinkElement} link - The link element.
|
* @param {HTMLLinkElement} link - The link element.
|
||||||
* @param {ExternalLinkParameters} params
|
* @param {ExternalLinkParameters} params
|
||||||
*/
|
*/
|
||||||
function addLinkAttributes(link, { url, target, rel, enabled = true, } = {}) {
|
function addLinkAttributes(link, { url, target, rel, enabled = true } = {}) {
|
||||||
assert(url && typeof url === 'string',
|
assert(
|
||||||
'addLinkAttributes: A valid "url" parameter must provided.');
|
url && typeof url === "string",
|
||||||
|
'addLinkAttributes: A valid "url" parameter must provided.'
|
||||||
|
);
|
||||||
|
|
||||||
const urlNullRemoved = removeNullCharacters(url);
|
const urlNullRemoved = removeNullCharacters(url);
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
link.href = link.title = urlNullRemoved;
|
link.href = link.title = urlNullRemoved;
|
||||||
} else {
|
} else {
|
||||||
link.href = '';
|
link.href = "";
|
||||||
link.title = `Disabled: ${urlNullRemoved}`;
|
link.title = `Disabled: ${urlNullRemoved}`;
|
||||||
link.onclick = () => {
|
link.onclick = () => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let targetStr = ''; // LinkTarget.NONE
|
let targetStr = ""; // LinkTarget.NONE
|
||||||
switch (target) {
|
switch (target) {
|
||||||
case LinkTarget.NONE:
|
case LinkTarget.NONE:
|
||||||
break;
|
break;
|
||||||
case LinkTarget.SELF:
|
case LinkTarget.SELF:
|
||||||
targetStr = '_self';
|
targetStr = "_self";
|
||||||
break;
|
break;
|
||||||
case LinkTarget.BLANK:
|
case LinkTarget.BLANK:
|
||||||
targetStr = '_blank';
|
targetStr = "_blank";
|
||||||
break;
|
break;
|
||||||
case LinkTarget.PARENT:
|
case LinkTarget.PARENT:
|
||||||
targetStr = '_parent';
|
targetStr = "_parent";
|
||||||
break;
|
break;
|
||||||
case LinkTarget.TOP:
|
case LinkTarget.TOP:
|
||||||
targetStr = '_top';
|
targetStr = "_top";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
link.target = targetStr;
|
link.target = targetStr;
|
||||||
|
|
||||||
link.rel = (typeof rel === 'string' ? rel : DEFAULT_LINK_REL);
|
link.rel = typeof rel === "string" ? rel : DEFAULT_LINK_REL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets the file name from a given URL.
|
// Gets the file name from a given URL.
|
||||||
function getFilenameFromUrl(url) {
|
function getFilenameFromUrl(url) {
|
||||||
const anchor = url.indexOf('#');
|
const anchor = url.indexOf("#");
|
||||||
const query = url.indexOf('?');
|
const query = url.indexOf("?");
|
||||||
const end = Math.min(anchor > 0 ? anchor : url.length,
|
const end = Math.min(
|
||||||
query > 0 ? query : url.length);
|
anchor > 0 ? anchor : url.length,
|
||||||
return url.substring(url.lastIndexOf('/', end) + 1, end);
|
query > 0 ? query : url.length
|
||||||
|
);
|
||||||
|
return url.substring(url.lastIndexOf("/", end) + 1, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
class StatTimer {
|
class StatTimer {
|
||||||
@ -407,9 +451,9 @@ class StatTimer {
|
|||||||
warn(`Timer has not been started for ${name}`);
|
warn(`Timer has not been started for ${name}`);
|
||||||
}
|
}
|
||||||
this.times.push({
|
this.times.push({
|
||||||
'name': name,
|
name,
|
||||||
'start': this.started[name],
|
start: this.started[name],
|
||||||
'end': Date.now(),
|
end: Date.now(),
|
||||||
});
|
});
|
||||||
// Remove timer from started so it can be called again.
|
// Remove timer from started so it can be called again.
|
||||||
delete this.started[name];
|
delete this.started[name];
|
||||||
@ -417,7 +461,8 @@ class StatTimer {
|
|||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
// Find the longest name for padding purposes.
|
// Find the longest name for padding purposes.
|
||||||
let outBuf = [], longest = 0;
|
let outBuf = [],
|
||||||
|
longest = 0;
|
||||||
for (const time of this.times) {
|
for (const time of this.times) {
|
||||||
const name = time.name;
|
const name = time.name;
|
||||||
if (name.length > longest) {
|
if (name.length > longest) {
|
||||||
@ -428,21 +473,24 @@ class StatTimer {
|
|||||||
const duration = time.end - time.start;
|
const duration = time.end - time.start;
|
||||||
outBuf.push(`${time.name.padEnd(longest)} ${duration}ms\n`);
|
outBuf.push(`${time.name.padEnd(longest)} ${duration}ms\n`);
|
||||||
}
|
}
|
||||||
return outBuf.join('');
|
return outBuf.join("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isFetchSupported() {
|
function isFetchSupported() {
|
||||||
return (typeof fetch !== 'undefined' &&
|
return (
|
||||||
typeof Response !== 'undefined' && 'body' in Response.prototype &&
|
typeof fetch !== "undefined" &&
|
||||||
typeof ReadableStream !== 'undefined');
|
typeof Response !== "undefined" &&
|
||||||
|
"body" in Response.prototype &&
|
||||||
|
typeof ReadableStream !== "undefined"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isValidFetchUrl(url, baseUrl) {
|
function isValidFetchUrl(url, baseUrl) {
|
||||||
try {
|
try {
|
||||||
const { protocol, } = baseUrl ? new URL(url, baseUrl) : new URL(url);
|
const { protocol } = baseUrl ? new URL(url, baseUrl) : new URL(url);
|
||||||
// The Fetch API only supports the http/https protocols, and not file/ftp.
|
// The Fetch API only supports the http/https protocols, and not file/ftp.
|
||||||
return (protocol === 'http:' || protocol === 'https:');
|
return protocol === "http:" || protocol === "https:";
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
return false; // `new URL()` will throw on incorrect data.
|
return false; // `new URL()` will throw on incorrect data.
|
||||||
}
|
}
|
||||||
@ -450,7 +498,7 @@ function isValidFetchUrl(url, baseUrl) {
|
|||||||
|
|
||||||
function loadScript(src) {
|
function loadScript(src) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const script = document.createElement('script');
|
const script = document.createElement("script");
|
||||||
script.src = src;
|
script.src = src;
|
||||||
|
|
||||||
script.onload = resolve;
|
script.onload = resolve;
|
||||||
@ -463,18 +511,21 @@ function loadScript(src) {
|
|||||||
|
|
||||||
// Deprecated API function -- display regardless of the `verbosity` setting.
|
// Deprecated API function -- display regardless of the `verbosity` setting.
|
||||||
function deprecated(details) {
|
function deprecated(details) {
|
||||||
console.log('Deprecated API usage: ' + details);
|
console.log("Deprecated API usage: " + details);
|
||||||
}
|
}
|
||||||
|
|
||||||
function releaseImageResources(img) {
|
function releaseImageResources(img) {
|
||||||
assert(img instanceof Image, 'Invalid `img` parameter.');
|
assert(img instanceof Image, "Invalid `img` parameter.");
|
||||||
|
|
||||||
const url = img.src;
|
const url = img.src;
|
||||||
if (typeof url === 'string' && url.startsWith('blob:') &&
|
if (
|
||||||
URL.revokeObjectURL) {
|
typeof url === "string" &&
|
||||||
|
url.startsWith("blob:") &&
|
||||||
|
URL.revokeObjectURL
|
||||||
|
) {
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
}
|
}
|
||||||
img.removeAttribute('src');
|
img.removeAttribute("src");
|
||||||
}
|
}
|
||||||
|
|
||||||
let pdfDateStringRegex;
|
let pdfDateStringRegex;
|
||||||
@ -504,18 +555,18 @@ class PDFDateString {
|
|||||||
// Lazily initialize the regular expression.
|
// Lazily initialize the regular expression.
|
||||||
if (!pdfDateStringRegex) {
|
if (!pdfDateStringRegex) {
|
||||||
pdfDateStringRegex = new RegExp(
|
pdfDateStringRegex = new RegExp(
|
||||||
'^D:' + // Prefix (required)
|
"^D:" + // Prefix (required)
|
||||||
'(\\d{4})' + // Year (required)
|
"(\\d{4})" + // Year (required)
|
||||||
'(\\d{2})?' + // Month (optional)
|
"(\\d{2})?" + // Month (optional)
|
||||||
'(\\d{2})?' + // Day (optional)
|
"(\\d{2})?" + // Day (optional)
|
||||||
'(\\d{2})?' + // Hour (optional)
|
"(\\d{2})?" + // Hour (optional)
|
||||||
'(\\d{2})?' + // Minute (optional)
|
"(\\d{2})?" + // Minute (optional)
|
||||||
'(\\d{2})?' + // Second (optional)
|
"(\\d{2})?" + // Second (optional)
|
||||||
'([Z|+|-])?' + // Universal time relation (optional)
|
"([Z|+|-])?" + // Universal time relation (optional)
|
||||||
'(\\d{2})?' + // Offset hour (optional)
|
"(\\d{2})?" + // Offset hour (optional)
|
||||||
'\'?' + // Splitting apostrophe (optional)
|
"'?" + // Splitting apostrophe (optional)
|
||||||
'(\\d{2})?' + // Offset minute (optional)
|
"(\\d{2})?" + // Offset minute (optional)
|
||||||
'\'?' // Trailing apostrophe (optional)
|
"'?" // Trailing apostrophe (optional)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,29 +582,29 @@ class PDFDateString {
|
|||||||
// instead of 1 and 12, so we have to correct for that.
|
// instead of 1 and 12, so we have to correct for that.
|
||||||
const year = parseInt(matches[1], 10);
|
const year = parseInt(matches[1], 10);
|
||||||
let month = parseInt(matches[2], 10);
|
let month = parseInt(matches[2], 10);
|
||||||
month = (month >= 1 && month <= 12) ? month - 1 : 0;
|
month = month >= 1 && month <= 12 ? month - 1 : 0;
|
||||||
let day = parseInt(matches[3], 10);
|
let day = parseInt(matches[3], 10);
|
||||||
day = (day >= 1 && day <= 31) ? day : 1;
|
day = day >= 1 && day <= 31 ? day : 1;
|
||||||
let hour = parseInt(matches[4], 10);
|
let hour = parseInt(matches[4], 10);
|
||||||
hour = (hour >= 0 && hour <= 23) ? hour : 0;
|
hour = hour >= 0 && hour <= 23 ? hour : 0;
|
||||||
let minute = parseInt(matches[5], 10);
|
let minute = parseInt(matches[5], 10);
|
||||||
minute = (minute >= 0 && minute <= 59) ? minute : 0;
|
minute = minute >= 0 && minute <= 59 ? minute : 0;
|
||||||
let second = parseInt(matches[6], 10);
|
let second = parseInt(matches[6], 10);
|
||||||
second = (second >= 0 && second <= 59) ? second : 0;
|
second = second >= 0 && second <= 59 ? second : 0;
|
||||||
const universalTimeRelation = matches[7] || 'Z';
|
const universalTimeRelation = matches[7] || "Z";
|
||||||
let offsetHour = parseInt(matches[8], 10);
|
let offsetHour = parseInt(matches[8], 10);
|
||||||
offsetHour = (offsetHour >= 0 && offsetHour <= 23) ? offsetHour : 0;
|
offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0;
|
||||||
let offsetMinute = parseInt(matches[9], 10) || 0;
|
let offsetMinute = parseInt(matches[9], 10) || 0;
|
||||||
offsetMinute = (offsetMinute >= 0 && offsetMinute <= 59) ? offsetMinute : 0;
|
offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0;
|
||||||
|
|
||||||
// Universal time relation 'Z' means that the local time is equal to the
|
// Universal time relation 'Z' means that the local time is equal to the
|
||||||
// universal time, whereas the relations '+'/'-' indicate that the local
|
// universal time, whereas the relations '+'/'-' indicate that the local
|
||||||
// time is later respectively earlier than the universal time. Every date
|
// time is later respectively earlier than the universal time. Every date
|
||||||
// is normalized to universal time.
|
// is normalized to universal time.
|
||||||
if (universalTimeRelation === '-') {
|
if (universalTimeRelation === "-") {
|
||||||
hour += offsetHour;
|
hour += offsetHour;
|
||||||
minute += offsetMinute;
|
minute += offsetMinute;
|
||||||
} else if (universalTimeRelation === '+') {
|
} else if (universalTimeRelation === "+") {
|
||||||
hour -= offsetHour;
|
hour -= offsetHour;
|
||||||
minute -= offsetMinute;
|
minute -= offsetMinute;
|
||||||
}
|
}
|
||||||
|
@ -15,21 +15,25 @@
|
|||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AbortException, assert, createPromiseCapability
|
AbortException,
|
||||||
} from '../shared/util';
|
assert,
|
||||||
|
createPromiseCapability,
|
||||||
|
} from "../shared/util";
|
||||||
import {
|
import {
|
||||||
createResponseStatusError, extractFilenameFromHeader,
|
createResponseStatusError,
|
||||||
validateRangeRequestCapabilities, validateResponseStatus
|
extractFilenameFromHeader,
|
||||||
} from './network_utils';
|
validateRangeRequestCapabilities,
|
||||||
|
validateResponseStatus,
|
||||||
|
} from "./network_utils";
|
||||||
|
|
||||||
function createFetchOptions(headers, withCredentials, abortController) {
|
function createFetchOptions(headers, withCredentials, abortController) {
|
||||||
return {
|
return {
|
||||||
method: 'GET',
|
method: "GET",
|
||||||
headers,
|
headers,
|
||||||
signal: abortController && abortController.signal,
|
signal: abortController && abortController.signal,
|
||||||
mode: 'cors',
|
mode: "cors",
|
||||||
credentials: withCredentials ? 'include' : 'same-origin',
|
credentials: withCredentials ? "include" : "same-origin",
|
||||||
redirect: 'follow',
|
redirect: "follow",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,7 +41,7 @@ function createHeaders(httpHeaders) {
|
|||||||
const headers = new Headers();
|
const headers = new Headers();
|
||||||
for (const property in httpHeaders) {
|
for (const property in httpHeaders) {
|
||||||
const value = httpHeaders[property];
|
const value = httpHeaders[property];
|
||||||
if (typeof value === 'undefined') {
|
if (typeof value === "undefined") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
headers.append(property, value);
|
headers.append(property, value);
|
||||||
@ -57,7 +61,7 @@ class PDFFetchStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get _progressiveDataLength() {
|
get _progressiveDataLength() {
|
||||||
return (this._fullRequestReader ? this._fullRequestReader._loaded : 0);
|
return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFullReader() {
|
getFullReader() {
|
||||||
@ -103,7 +107,7 @@ class PDFFetchStreamReader {
|
|||||||
this._disableRange = true;
|
this._disableRange = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof AbortController !== 'undefined') {
|
if (typeof AbortController !== "undefined") {
|
||||||
this._abortController = new AbortController();
|
this._abortController = new AbortController();
|
||||||
}
|
}
|
||||||
this._isStreamingSupported = !source.disableStream;
|
this._isStreamingSupported = !source.disableStream;
|
||||||
@ -112,19 +116,28 @@ class PDFFetchStreamReader {
|
|||||||
this._headers = createHeaders(this._stream.httpHeaders);
|
this._headers = createHeaders(this._stream.httpHeaders);
|
||||||
|
|
||||||
const url = source.url;
|
const url = source.url;
|
||||||
fetch(url, createFetchOptions(this._headers, this._withCredentials,
|
fetch(
|
||||||
this._abortController)).then((response) => {
|
url,
|
||||||
|
createFetchOptions(
|
||||||
|
this._headers,
|
||||||
|
this._withCredentials,
|
||||||
|
this._abortController
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(response => {
|
||||||
if (!validateResponseStatus(response.status)) {
|
if (!validateResponseStatus(response.status)) {
|
||||||
throw createResponseStatusError(response.status, url);
|
throw createResponseStatusError(response.status, url);
|
||||||
}
|
}
|
||||||
this._reader = response.body.getReader();
|
this._reader = response.body.getReader();
|
||||||
this._headersCapability.resolve();
|
this._headersCapability.resolve();
|
||||||
|
|
||||||
const getResponseHeader = (name) => {
|
const getResponseHeader = name => {
|
||||||
return response.headers.get(name);
|
return response.headers.get(name);
|
||||||
};
|
};
|
||||||
const { allowRangeRequests, suggestedLength, } =
|
const {
|
||||||
validateRangeRequestCapabilities({
|
allowRangeRequests,
|
||||||
|
suggestedLength,
|
||||||
|
} = validateRangeRequestCapabilities({
|
||||||
getResponseHeader,
|
getResponseHeader,
|
||||||
isHttp: this._stream.isHttp,
|
isHttp: this._stream.isHttp,
|
||||||
rangeChunkSize: this._rangeChunkSize,
|
rangeChunkSize: this._rangeChunkSize,
|
||||||
@ -140,9 +153,10 @@ class PDFFetchStreamReader {
|
|||||||
// We need to stop reading when range is supported and streaming is
|
// We need to stop reading when range is supported and streaming is
|
||||||
// disabled.
|
// disabled.
|
||||||
if (!this._isStreamingSupported && this._isRangeSupported) {
|
if (!this._isStreamingSupported && this._isRangeSupported) {
|
||||||
this.cancel(new AbortException('Streaming is disabled.'));
|
this.cancel(new AbortException("Streaming is disabled."));
|
||||||
}
|
}
|
||||||
}).catch(this._headersCapability.reject);
|
})
|
||||||
|
.catch(this._headersCapability.reject);
|
||||||
|
|
||||||
this.onProgress = null;
|
this.onProgress = null;
|
||||||
}
|
}
|
||||||
@ -169,9 +183,9 @@ class PDFFetchStreamReader {
|
|||||||
|
|
||||||
async read() {
|
async read() {
|
||||||
await this._headersCapability.promise;
|
await this._headersCapability.promise;
|
||||||
const { value, done, } = await this._reader.read();
|
const { value, done } = await this._reader.read();
|
||||||
if (done) {
|
if (done) {
|
||||||
return { value, done, };
|
return { value, done };
|
||||||
}
|
}
|
||||||
this._loaded += value.byteLength;
|
this._loaded += value.byteLength;
|
||||||
if (this.onProgress) {
|
if (this.onProgress) {
|
||||||
@ -181,7 +195,7 @@ class PDFFetchStreamReader {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
const buffer = new Uint8Array(value).buffer;
|
const buffer = new Uint8Array(value).buffer;
|
||||||
return { value: buffer, done: false, };
|
return { value: buffer, done: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
@ -205,16 +219,22 @@ class PDFFetchStreamRangeReader {
|
|||||||
this._readCapability = createPromiseCapability();
|
this._readCapability = createPromiseCapability();
|
||||||
this._isStreamingSupported = !source.disableStream;
|
this._isStreamingSupported = !source.disableStream;
|
||||||
|
|
||||||
if (typeof AbortController !== 'undefined') {
|
if (typeof AbortController !== "undefined") {
|
||||||
this._abortController = new AbortController();
|
this._abortController = new AbortController();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._headers = createHeaders(this._stream.httpHeaders);
|
this._headers = createHeaders(this._stream.httpHeaders);
|
||||||
this._headers.append('Range', `bytes=${begin}-${end - 1}`);
|
this._headers.append("Range", `bytes=${begin}-${end - 1}`);
|
||||||
|
|
||||||
const url = source.url;
|
const url = source.url;
|
||||||
fetch(url, createFetchOptions(this._headers, this._withCredentials,
|
fetch(
|
||||||
this._abortController)).then((response) => {
|
url,
|
||||||
|
createFetchOptions(
|
||||||
|
this._headers,
|
||||||
|
this._withCredentials,
|
||||||
|
this._abortController
|
||||||
|
)
|
||||||
|
).then(response => {
|
||||||
if (!validateResponseStatus(response.status)) {
|
if (!validateResponseStatus(response.status)) {
|
||||||
throw createResponseStatusError(response.status, url);
|
throw createResponseStatusError(response.status, url);
|
||||||
}
|
}
|
||||||
@ -231,16 +251,16 @@ class PDFFetchStreamRangeReader {
|
|||||||
|
|
||||||
async read() {
|
async read() {
|
||||||
await this._readCapability.promise;
|
await this._readCapability.promise;
|
||||||
const { value, done, } = await this._reader.read();
|
const { value, done } = await this._reader.read();
|
||||||
if (done) {
|
if (done) {
|
||||||
return { value, done, };
|
return { value, done };
|
||||||
}
|
}
|
||||||
this._loaded += value.byteLength;
|
this._loaded += value.byteLength;
|
||||||
if (this.onProgress) {
|
if (this.onProgress) {
|
||||||
this.onProgress({ loaded: this._loaded, });
|
this.onProgress({ loaded: this._loaded });
|
||||||
}
|
}
|
||||||
const buffer = new Uint8Array(value).buffer;
|
const buffer = new Uint8Array(value).buffer;
|
||||||
return { value: buffer, done: false, };
|
return { value: buffer, done: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
@ -253,6 +273,4 @@ class PDFFetchStreamRangeReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { PDFFetchStream };
|
||||||
PDFFetchStream,
|
|
||||||
};
|
|
||||||
|
@ -14,14 +14,20 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
assert, bytesToString, isEvalSupported, shadow, string32, unreachable,
|
assert,
|
||||||
UNSUPPORTED_FEATURES, warn
|
bytesToString,
|
||||||
} from '../shared/util';
|
isEvalSupported,
|
||||||
|
shadow,
|
||||||
|
string32,
|
||||||
|
unreachable,
|
||||||
|
UNSUPPORTED_FEATURES,
|
||||||
|
warn,
|
||||||
|
} from "../shared/util";
|
||||||
|
|
||||||
class BaseFontLoader {
|
class BaseFontLoader {
|
||||||
constructor({ docId, onUnsupportedFeature, }) {
|
constructor({ docId, onUnsupportedFeature }) {
|
||||||
if (this.constructor === BaseFontLoader) {
|
if (this.constructor === BaseFontLoader) {
|
||||||
unreachable('Cannot initialize BaseFontLoader.');
|
unreachable("Cannot initialize BaseFontLoader.");
|
||||||
}
|
}
|
||||||
this.docId = docId;
|
this.docId = docId;
|
||||||
this._onUnsupportedFeature = onUnsupportedFeature;
|
this._onUnsupportedFeature = onUnsupportedFeature;
|
||||||
@ -38,10 +44,11 @@ class BaseFontLoader {
|
|||||||
insertRule(rule) {
|
insertRule(rule) {
|
||||||
let styleElement = this.styleElement;
|
let styleElement = this.styleElement;
|
||||||
if (!styleElement) {
|
if (!styleElement) {
|
||||||
styleElement = this.styleElement = document.createElement('style');
|
styleElement = this.styleElement = document.createElement("style");
|
||||||
styleElement.id = `PDFJS_FONT_STYLE_TAG_${this.docId}`;
|
styleElement.id = `PDFJS_FONT_STYLE_TAG_${this.docId}`;
|
||||||
document.documentElement.getElementsByTagName('head')[0].appendChild(
|
document.documentElement
|
||||||
styleElement);
|
.getElementsByTagName("head")[0]
|
||||||
|
.appendChild(styleElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
const styleSheet = styleElement.sheet;
|
const styleSheet = styleElement.sheet;
|
||||||
@ -75,7 +82,7 @@ class BaseFontLoader {
|
|||||||
try {
|
try {
|
||||||
await nativeFontFace.loaded;
|
await nativeFontFace.loaded;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
this._onUnsupportedFeature({ featureId: UNSUPPORTED_FEATURES.font, });
|
this._onUnsupportedFeature({ featureId: UNSUPPORTED_FEATURES.font });
|
||||||
warn(`Failed to load font '${nativeFontFace.family}': '${ex}'.`);
|
warn(`Failed to load font '${nativeFontFace.family}': '${ex}'.`);
|
||||||
|
|
||||||
// When font loading failed, fall back to the built-in font renderer.
|
// When font loading failed, fall back to the built-in font renderer.
|
||||||
@ -94,7 +101,7 @@ class BaseFontLoader {
|
|||||||
if (this.isSyncFontLoadingSupported) {
|
if (this.isSyncFontLoadingSupported) {
|
||||||
return undefined; // The font was, synchronously, loaded.
|
return undefined; // The font was, synchronously, loaded.
|
||||||
}
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise(resolve => {
|
||||||
const request = this._queueLoadingCallback(resolve);
|
const request = this._queueLoadingCallback(resolve);
|
||||||
this._prepareFontLoadEvent([rule], [font], request);
|
this._prepareFontLoadEvent([rule], [font], request);
|
||||||
});
|
});
|
||||||
@ -103,41 +110,46 @@ class BaseFontLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_queueLoadingCallback(callback) {
|
_queueLoadingCallback(callback) {
|
||||||
unreachable('Abstract method `_queueLoadingCallback`.');
|
unreachable("Abstract method `_queueLoadingCallback`.");
|
||||||
}
|
}
|
||||||
|
|
||||||
get isFontLoadingAPISupported() { // eslint-disable-line getter-return
|
get isFontLoadingAPISupported() {
|
||||||
unreachable('Abstract method `isFontLoadingAPISupported`.');
|
// eslint-disable-line getter-return
|
||||||
|
unreachable("Abstract method `isFontLoadingAPISupported`.");
|
||||||
}
|
}
|
||||||
|
|
||||||
get isSyncFontLoadingSupported() { // eslint-disable-line getter-return
|
get isSyncFontLoadingSupported() {
|
||||||
unreachable('Abstract method `isSyncFontLoadingSupported`.');
|
// eslint-disable-line getter-return
|
||||||
|
unreachable("Abstract method `isSyncFontLoadingSupported`.");
|
||||||
}
|
}
|
||||||
|
|
||||||
get _loadTestFont() { // eslint-disable-line getter-return
|
get _loadTestFont() {
|
||||||
unreachable('Abstract method `_loadTestFont`.');
|
// eslint-disable-line getter-return
|
||||||
|
unreachable("Abstract method `_loadTestFont`.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_prepareFontLoadEvent(rules, fontsToLoad, request) {
|
_prepareFontLoadEvent(rules, fontsToLoad, request) {
|
||||||
unreachable('Abstract method `_prepareFontLoadEvent`.');
|
unreachable("Abstract method `_prepareFontLoadEvent`.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let FontLoader;
|
let FontLoader;
|
||||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('MOZCENTRAL')) {
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
||||||
|
|
||||||
FontLoader = class MozcentralFontLoader extends BaseFontLoader {
|
FontLoader = class MozcentralFontLoader extends BaseFontLoader {
|
||||||
get isFontLoadingAPISupported() {
|
get isFontLoadingAPISupported() {
|
||||||
return shadow(this, 'isFontLoadingAPISupported',
|
return shadow(
|
||||||
typeof document !== 'undefined' && !!document.fonts);
|
this,
|
||||||
|
"isFontLoadingAPISupported",
|
||||||
|
typeof document !== "undefined" && !!document.fonts
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get isSyncFontLoadingSupported() {
|
get isSyncFontLoadingSupported() {
|
||||||
return shadow(this, 'isSyncFontLoadingSupported', true);
|
return shadow(this, "isSyncFontLoadingSupported", true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
} else { // PDFJSDev.test('CHROME || GENERIC')
|
// PDFJSDev.test('CHROME || GENERIC')
|
||||||
|
|
||||||
FontLoader = class GenericFontLoader extends BaseFontLoader {
|
FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||||
constructor(docId) {
|
constructor(docId) {
|
||||||
@ -150,10 +162,13 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isFontLoadingAPISupported() {
|
get isFontLoadingAPISupported() {
|
||||||
let supported = (typeof document !== 'undefined' && !!document.fonts);
|
let supported = typeof document !== "undefined" && !!document.fonts;
|
||||||
|
|
||||||
if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME')) &&
|
if (
|
||||||
(supported && typeof navigator !== 'undefined')) {
|
(typeof PDFJSDev === "undefined" || !PDFJSDev.test("CHROME")) &&
|
||||||
|
supported &&
|
||||||
|
typeof navigator !== "undefined"
|
||||||
|
) {
|
||||||
// The Firefox Font Loading API does not work with `mozPrintCallback`
|
// The Firefox Font Loading API does not work with `mozPrintCallback`
|
||||||
// prior to version 63; see https://bugzilla.mozilla.org/show_bug.cgi?id=1473742
|
// prior to version 63; see https://bugzilla.mozilla.org/show_bug.cgi?id=1473742
|
||||||
const m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
|
const m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
|
||||||
@ -161,31 +176,33 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
supported = false;
|
supported = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shadow(this, 'isFontLoadingAPISupported', supported);
|
return shadow(this, "isFontLoadingAPISupported", supported);
|
||||||
}
|
}
|
||||||
|
|
||||||
get isSyncFontLoadingSupported() {
|
get isSyncFontLoadingSupported() {
|
||||||
let supported = false;
|
let supported = false;
|
||||||
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME')) {
|
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("CHROME")) {
|
||||||
if (typeof navigator === 'undefined') {
|
if (typeof navigator === "undefined") {
|
||||||
// Node.js - we can pretend that sync font loading is supported.
|
// Node.js - we can pretend that sync font loading is supported.
|
||||||
supported = true;
|
supported = true;
|
||||||
} else {
|
} else {
|
||||||
// User agent string sniffing is bad, but there is no reliable way to
|
// User agent string sniffing is bad, but there is no reliable way to
|
||||||
// tell if the font is fully loaded and ready to be used with canvas.
|
// tell if the font is fully loaded and ready to be used with canvas.
|
||||||
const m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
|
const m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(
|
||||||
|
navigator.userAgent
|
||||||
|
);
|
||||||
if (m && m[1] >= 14) {
|
if (m && m[1] >= 14) {
|
||||||
supported = true;
|
supported = true;
|
||||||
}
|
}
|
||||||
// TODO - other browsers...
|
// TODO - other browsers...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shadow(this, 'isSyncFontLoadingSupported', supported);
|
return shadow(this, "isSyncFontLoadingSupported", supported);
|
||||||
}
|
}
|
||||||
|
|
||||||
_queueLoadingCallback(callback) {
|
_queueLoadingCallback(callback) {
|
||||||
function completeRequest() {
|
function completeRequest() {
|
||||||
assert(!request.done, 'completeRequest() cannot be called twice.');
|
assert(!request.done, "completeRequest() cannot be called twice.");
|
||||||
request.done = true;
|
request.done = true;
|
||||||
|
|
||||||
// Sending all completed requests in order of how they were queued.
|
// Sending all completed requests in order of how they were queued.
|
||||||
@ -211,30 +228,31 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
// This is a CFF font with 1 glyph for '.' that fills its entire width and
|
// This is a CFF font with 1 glyph for '.' that fills its entire width and
|
||||||
// height.
|
// height.
|
||||||
return atob(
|
return atob(
|
||||||
'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA' +
|
"T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA" +
|
||||||
'FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA' +
|
"FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA" +
|
||||||
'ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA' +
|
"ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA" +
|
||||||
'AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1' +
|
"AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1" +
|
||||||
'AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD' +
|
"AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD" +
|
||||||
'6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM' +
|
"6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM" +
|
||||||
'AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D' +
|
"AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D" +
|
||||||
'IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA' +
|
"IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA" +
|
||||||
'AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA' +
|
"AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA" +
|
||||||
'AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB' +
|
"AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB" +
|
||||||
'AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY' +
|
"AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY" +
|
||||||
'AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA' +
|
"AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA" +
|
||||||
'AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
"AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||||
'AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
"AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA' +
|
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA" +
|
||||||
'AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC' +
|
"AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC" +
|
||||||
'AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3' +
|
"AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3" +
|
||||||
'Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj' +
|
"Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj" +
|
||||||
'FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA==');
|
"FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA=="
|
||||||
|
);
|
||||||
};
|
};
|
||||||
return shadow(this, '_loadTestFont', getLoadTestFont());
|
return shadow(this, "_loadTestFont", getLoadTestFont());
|
||||||
}
|
}
|
||||||
|
|
||||||
_prepareFontLoadEvent(rules, fonts, request) {
|
_prepareFontLoadEvent(rules, fonts, request) {
|
||||||
@ -245,10 +263,12 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
// the desired fonts and then test for the loading of that test font.
|
// the desired fonts and then test for the loading of that test font.
|
||||||
|
|
||||||
function int32(data, offset) {
|
function int32(data, offset) {
|
||||||
return (data.charCodeAt(offset) << 24) |
|
return (
|
||||||
|
(data.charCodeAt(offset) << 24) |
|
||||||
(data.charCodeAt(offset + 1) << 16) |
|
(data.charCodeAt(offset + 1) << 16) |
|
||||||
(data.charCodeAt(offset + 2) << 8) |
|
(data.charCodeAt(offset + 2) << 8) |
|
||||||
(data.charCodeAt(offset + 3) & 0xff);
|
(data.charCodeAt(offset + 3) & 0xff)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
function spliceString(s, offset, remove, insert) {
|
function spliceString(s, offset, remove, insert) {
|
||||||
let chunk1 = s.substring(0, offset);
|
let chunk1 = s.substring(0, offset);
|
||||||
@ -258,22 +278,22 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
let i, ii;
|
let i, ii;
|
||||||
|
|
||||||
// The temporary canvas is used to determine if fonts are loaded.
|
// The temporary canvas is used to determine if fonts are loaded.
|
||||||
let canvas = document.createElement('canvas');
|
let canvas = document.createElement("canvas");
|
||||||
canvas.width = 1;
|
canvas.width = 1;
|
||||||
canvas.height = 1;
|
canvas.height = 1;
|
||||||
let ctx = canvas.getContext('2d');
|
let ctx = canvas.getContext("2d");
|
||||||
|
|
||||||
let called = 0;
|
let called = 0;
|
||||||
function isFontReady(name, callback) {
|
function isFontReady(name, callback) {
|
||||||
called++;
|
called++;
|
||||||
// With setTimeout clamping this gives the font ~100ms to load.
|
// With setTimeout clamping this gives the font ~100ms to load.
|
||||||
if (called > 30) {
|
if (called > 30) {
|
||||||
warn('Load test font never loaded.');
|
warn("Load test font never loaded.");
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ctx.font = '30px ' + name;
|
ctx.font = "30px " + name;
|
||||||
ctx.fillText('.', 0, 20);
|
ctx.fillText(".", 0, 20);
|
||||||
let imageData = ctx.getImageData(0, 0, 1, 1);
|
let imageData = ctx.getImageData(0, 0, 1, 1);
|
||||||
if (imageData.data[3] > 0) {
|
if (imageData.data[3] > 0) {
|
||||||
callback();
|
callback();
|
||||||
@ -290,8 +310,12 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
// font by splitting it in chunks before hand and padding the font id.
|
// font by splitting it in chunks before hand and padding the font id.
|
||||||
let data = this._loadTestFont;
|
let data = this._loadTestFont;
|
||||||
let COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
|
let COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
|
||||||
data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length,
|
data = spliceString(
|
||||||
loadTestFontId);
|
data,
|
||||||
|
COMMENT_OFFSET,
|
||||||
|
loadTestFontId.length,
|
||||||
|
loadTestFontId
|
||||||
|
);
|
||||||
// CFF checksum is important for IE, adjusting it
|
// CFF checksum is important for IE, adjusting it
|
||||||
let CFF_CHECKSUM_OFFSET = 16;
|
let CFF_CHECKSUM_OFFSET = 16;
|
||||||
let XXXX_VALUE = 0x58585858; // the "comment" filled with 'X'
|
let XXXX_VALUE = 0x58585858; // the "comment" filled with 'X'
|
||||||
@ -299,8 +323,10 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
|
for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
|
||||||
checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0;
|
checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0;
|
||||||
}
|
}
|
||||||
if (i < loadTestFontId.length) { // align to 4 bytes boundary
|
if (i < loadTestFontId.length) {
|
||||||
checksum = (checksum - XXXX_VALUE + int32(loadTestFontId + 'XXX', i)) | 0;
|
// align to 4 bytes boundary
|
||||||
|
checksum =
|
||||||
|
(checksum - XXXX_VALUE + int32(loadTestFontId + "XXX", i)) | 0;
|
||||||
}
|
}
|
||||||
data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
|
data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
|
||||||
|
|
||||||
@ -314,13 +340,16 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
}
|
}
|
||||||
names.push(loadTestFontId);
|
names.push(loadTestFontId);
|
||||||
|
|
||||||
let div = document.createElement('div');
|
let div = document.createElement("div");
|
||||||
div.setAttribute('style', 'visibility: hidden;' +
|
div.setAttribute(
|
||||||
'width: 10px; height: 10px;' +
|
"style",
|
||||||
'position: absolute; top: 0px; left: 0px;');
|
"visibility: hidden;" +
|
||||||
|
"width: 10px; height: 10px;" +
|
||||||
|
"position: absolute; top: 0px; left: 0px;"
|
||||||
|
);
|
||||||
for (i = 0, ii = names.length; i < ii; ++i) {
|
for (i = 0, ii = names.length; i < ii; ++i) {
|
||||||
let span = document.createElement('span');
|
let span = document.createElement("span");
|
||||||
span.textContent = 'Hi';
|
span.textContent = "Hi";
|
||||||
span.style.fontFamily = names[i];
|
span.style.fontFamily = names[i];
|
||||||
div.appendChild(span);
|
div.appendChild(span);
|
||||||
}
|
}
|
||||||
@ -333,21 +362,25 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
|||||||
/** Hack end */
|
/** Hack end */
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // End of PDFJSDev.test('CHROME || GENERIC')
|
} // End of PDFJSDev.test('CHROME || GENERIC')
|
||||||
|
|
||||||
const IsEvalSupportedCached = {
|
const IsEvalSupportedCached = {
|
||||||
get value() {
|
get value() {
|
||||||
return shadow(this, 'value', isEvalSupported());
|
return shadow(this, "value", isEvalSupported());
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
class FontFaceObject {
|
class FontFaceObject {
|
||||||
constructor(translatedData, { isEvalSupported = true,
|
constructor(
|
||||||
|
translatedData,
|
||||||
|
{
|
||||||
|
isEvalSupported = true,
|
||||||
disableFontFace = false,
|
disableFontFace = false,
|
||||||
ignoreErrors = false,
|
ignoreErrors = false,
|
||||||
onUnsupportedFeature = null,
|
onUnsupportedFeature = null,
|
||||||
fontRegistry = null, }) {
|
fontRegistry = null,
|
||||||
|
}
|
||||||
|
) {
|
||||||
this.compiledGlyphs = Object.create(null);
|
this.compiledGlyphs = Object.create(null);
|
||||||
// importing translated data
|
// importing translated data
|
||||||
for (let i in translatedData) {
|
for (let i in translatedData) {
|
||||||
@ -394,53 +427,51 @@ class FontFaceObject {
|
|||||||
|
|
||||||
let cmds, current;
|
let cmds, current;
|
||||||
try {
|
try {
|
||||||
cmds = objs.get(this.loadedName + '_path_' + character);
|
cmds = objs.get(this.loadedName + "_path_" + character);
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (!this.ignoreErrors) {
|
if (!this.ignoreErrors) {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
if (this._onUnsupportedFeature) {
|
if (this._onUnsupportedFeature) {
|
||||||
this._onUnsupportedFeature({ featureId: UNSUPPORTED_FEATURES.font, });
|
this._onUnsupportedFeature({ featureId: UNSUPPORTED_FEATURES.font });
|
||||||
}
|
}
|
||||||
warn(`getPathGenerator - ignoring character: "${ex}".`);
|
warn(`getPathGenerator - ignoring character: "${ex}".`);
|
||||||
|
|
||||||
return this.compiledGlyphs[character] = function(c, size) {
|
return (this.compiledGlyphs[character] = function(c, size) {
|
||||||
// No-op function, to allow rendering to continue.
|
// No-op function, to allow rendering to continue.
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we can, compile cmds into JS for MAXIMUM SPEED...
|
// If we can, compile cmds into JS for MAXIMUM SPEED...
|
||||||
if (this.isEvalSupported && IsEvalSupportedCached.value) {
|
if (this.isEvalSupported && IsEvalSupportedCached.value) {
|
||||||
let args, js = '';
|
let args,
|
||||||
|
js = "";
|
||||||
for (let i = 0, ii = cmds.length; i < ii; i++) {
|
for (let i = 0, ii = cmds.length; i < ii; i++) {
|
||||||
current = cmds[i];
|
current = cmds[i];
|
||||||
|
|
||||||
if (current.args !== undefined) {
|
if (current.args !== undefined) {
|
||||||
args = current.args.join(',');
|
args = current.args.join(",");
|
||||||
} else {
|
} else {
|
||||||
args = '';
|
args = "";
|
||||||
}
|
}
|
||||||
js += 'c.' + current.cmd + '(' + args + ');\n';
|
js += "c." + current.cmd + "(" + args + ");\n";
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line no-new-func
|
// eslint-disable-next-line no-new-func
|
||||||
return this.compiledGlyphs[character] = new Function('c', 'size', js);
|
return (this.compiledGlyphs[character] = new Function("c", "size", js));
|
||||||
}
|
}
|
||||||
// ... but fall back on using Function.prototype.apply() if we're
|
// ... but fall back on using Function.prototype.apply() if we're
|
||||||
// blocked from using eval() for whatever reason (like CSP policies).
|
// blocked from using eval() for whatever reason (like CSP policies).
|
||||||
return this.compiledGlyphs[character] = function(c, size) {
|
return (this.compiledGlyphs[character] = function(c, size) {
|
||||||
for (let i = 0, ii = cmds.length; i < ii; i++) {
|
for (let i = 0, ii = cmds.length; i < ii; i++) {
|
||||||
current = cmds[i];
|
current = cmds[i];
|
||||||
|
|
||||||
if (current.cmd === 'scale') {
|
if (current.cmd === "scale") {
|
||||||
current.args = [size, -size];
|
current.args = [size, -size];
|
||||||
}
|
}
|
||||||
c[current.cmd].apply(c, current.args);
|
c[current.cmd].apply(c, current.args);
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { FontFaceObject, FontLoader };
|
||||||
FontFaceObject,
|
|
||||||
FontLoader,
|
|
||||||
};
|
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { assert } from '../shared/util';
|
import { assert } from "../shared/util";
|
||||||
import { SimpleXMLParser } from './xml_parser';
|
import { SimpleXMLParser } from "./xml_parser";
|
||||||
|
|
||||||
class Metadata {
|
class Metadata {
|
||||||
constructor(data) {
|
constructor(data) {
|
||||||
assert(typeof data === 'string', 'Metadata: input is not a string');
|
assert(typeof data === "string", "Metadata: input is not a string");
|
||||||
|
|
||||||
// Ghostscript may produce invalid metadata, so try to repair that first.
|
// Ghostscript may produce invalid metadata, so try to repair that first.
|
||||||
data = this._repair(data);
|
data = this._repair(data);
|
||||||
@ -36,66 +36,74 @@ class Metadata {
|
|||||||
|
|
||||||
_repair(data) {
|
_repair(data) {
|
||||||
// Start by removing any "junk" before the first tag (see issue 10395).
|
// Start by removing any "junk" before the first tag (see issue 10395).
|
||||||
return data.replace(/^([^<]+)/, '').replace(/>\\376\\377([^<]+)/g,
|
return data
|
||||||
function(all, codes) {
|
.replace(/^([^<]+)/, "")
|
||||||
let bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
|
.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
|
||||||
function(code, d1, d2, d3) {
|
let bytes = codes
|
||||||
|
.replace(/\\([0-3])([0-7])([0-7])/g, function(code, d1, d2, d3) {
|
||||||
return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
|
return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
|
||||||
}).replace(/&(amp|apos|gt|lt|quot);/g, function(str, name) {
|
})
|
||||||
|
.replace(/&(amp|apos|gt|lt|quot);/g, function(str, name) {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'amp':
|
case "amp":
|
||||||
return '&';
|
return "&";
|
||||||
case 'apos':
|
case "apos":
|
||||||
return '\'';
|
return "'";
|
||||||
case 'gt':
|
case "gt":
|
||||||
return '>';
|
return ">";
|
||||||
case 'lt':
|
case "lt":
|
||||||
return '<';
|
return "<";
|
||||||
case 'quot':
|
case "quot":
|
||||||
return '\"';
|
return '"';
|
||||||
}
|
}
|
||||||
throw new Error(`_repair: ${name} isn't defined.`);
|
throw new Error(`_repair: ${name} isn't defined.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
let chars = '';
|
let chars = "";
|
||||||
for (let i = 0, ii = bytes.length; i < ii; i += 2) {
|
for (let i = 0, ii = bytes.length; i < ii; i += 2) {
|
||||||
let code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
|
let code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
|
||||||
if (code >= 32 && code < 127 && code !== 60 && code !== 62 &&
|
if (
|
||||||
code !== 38) {
|
code >= 32 &&
|
||||||
|
code < 127 &&
|
||||||
|
code !== 60 &&
|
||||||
|
code !== 62 &&
|
||||||
|
code !== 38
|
||||||
|
) {
|
||||||
chars += String.fromCharCode(code);
|
chars += String.fromCharCode(code);
|
||||||
} else {
|
} else {
|
||||||
chars += '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
|
chars += "&#x" + (0x10000 + code).toString(16).substring(1) + ";";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return '>' + chars;
|
return ">" + chars;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_parse(xmlDocument) {
|
_parse(xmlDocument) {
|
||||||
let rdf = xmlDocument.documentElement;
|
let rdf = xmlDocument.documentElement;
|
||||||
|
|
||||||
if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') { // Wrapped in <xmpmeta>
|
if (rdf.nodeName.toLowerCase() !== "rdf:rdf") {
|
||||||
|
// Wrapped in <xmpmeta>
|
||||||
rdf = rdf.firstChild;
|
rdf = rdf.firstChild;
|
||||||
while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
|
while (rdf && rdf.nodeName.toLowerCase() !== "rdf:rdf") {
|
||||||
rdf = rdf.nextSibling;
|
rdf = rdf.nextSibling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let nodeName = rdf ? rdf.nodeName.toLowerCase() : null;
|
let nodeName = rdf ? rdf.nodeName.toLowerCase() : null;
|
||||||
if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) {
|
if (!rdf || nodeName !== "rdf:rdf" || !rdf.hasChildNodes()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let children = rdf.childNodes;
|
let children = rdf.childNodes;
|
||||||
for (let i = 0, ii = children.length; i < ii; i++) {
|
for (let i = 0, ii = children.length; i < ii; i++) {
|
||||||
let desc = children[i];
|
let desc = children[i];
|
||||||
if (desc.nodeName.toLowerCase() !== 'rdf:description') {
|
if (desc.nodeName.toLowerCase() !== "rdf:description") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let j = 0, jj = desc.childNodes.length; j < jj; j++) {
|
for (let j = 0, jj = desc.childNodes.length; j < jj; j++) {
|
||||||
if (desc.childNodes[j].nodeName.toLowerCase() !== '#text') {
|
if (desc.childNodes[j].nodeName.toLowerCase() !== "#text") {
|
||||||
let entry = desc.childNodes[j];
|
let entry = desc.childNodes[j];
|
||||||
let name = entry.nodeName.toLowerCase();
|
let name = entry.nodeName.toLowerCase();
|
||||||
|
|
||||||
@ -107,7 +115,7 @@ class Metadata {
|
|||||||
|
|
||||||
get(name) {
|
get(name) {
|
||||||
const data = this._metadata[name];
|
const data = this._metadata[name];
|
||||||
return (typeof data !== 'undefined' ? data : null);
|
return typeof data !== "undefined" ? data : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAll() {
|
getAll() {
|
||||||
@ -115,10 +123,8 @@ class Metadata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
has(name) {
|
has(name) {
|
||||||
return typeof this._metadata[name] !== 'undefined';
|
return typeof this._metadata[name] !== "undefined";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { Metadata };
|
||||||
Metadata,
|
|
||||||
};
|
|
||||||
|
@ -14,15 +14,18 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import { assert, createPromiseCapability, stringToBytes } from '../shared/util';
|
import { assert, createPromiseCapability, stringToBytes } from "../shared/util";
|
||||||
import {
|
import {
|
||||||
createResponseStatusError, extractFilenameFromHeader,
|
createResponseStatusError,
|
||||||
validateRangeRequestCapabilities
|
extractFilenameFromHeader,
|
||||||
} from './network_utils';
|
validateRangeRequestCapabilities,
|
||||||
|
} from "./network_utils";
|
||||||
|
|
||||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("FIREFOX || MOZCENTRAL")) {
|
||||||
throw new Error('Module "./network" shall not ' +
|
throw new Error(
|
||||||
'be used with FIREFOX or MOZCENTRAL build.');
|
'Module "./network" shall not ' +
|
||||||
|
"be used with FIREFOX or MOZCENTRAL build."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const OK_RESPONSE = 200;
|
const OK_RESPONSE = 200;
|
||||||
@ -30,7 +33,7 @@ const PARTIAL_CONTENT_RESPONSE = 206;
|
|||||||
|
|
||||||
function getArrayBuffer(xhr) {
|
function getArrayBuffer(xhr) {
|
||||||
const data = xhr.response;
|
const data = xhr.response;
|
||||||
if (typeof data !== 'string') {
|
if (typeof data !== "string") {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
const array = stringToBytes(data);
|
const array = stringToBytes(data);
|
||||||
@ -44,7 +47,8 @@ class NetworkManager {
|
|||||||
this.isHttp = /^https?:/i.test(url);
|
this.isHttp = /^https?:/i.test(url);
|
||||||
this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
|
this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
|
||||||
this.withCredentials = args.withCredentials || false;
|
this.withCredentials = args.withCredentials || false;
|
||||||
this.getXhr = args.getXhr ||
|
this.getXhr =
|
||||||
|
args.getXhr ||
|
||||||
function NetworkManager_getXhr() {
|
function NetworkManager_getXhr() {
|
||||||
return new XMLHttpRequest();
|
return new XMLHttpRequest();
|
||||||
};
|
};
|
||||||
@ -71,26 +75,26 @@ class NetworkManager {
|
|||||||
request(args) {
|
request(args) {
|
||||||
const xhr = this.getXhr();
|
const xhr = this.getXhr();
|
||||||
const xhrId = this.currXhrId++;
|
const xhrId = this.currXhrId++;
|
||||||
const pendingRequest = this.pendingRequests[xhrId] = {
|
const pendingRequest = (this.pendingRequests[xhrId] = {
|
||||||
xhr,
|
xhr,
|
||||||
};
|
});
|
||||||
|
|
||||||
xhr.open('GET', this.url);
|
xhr.open("GET", this.url);
|
||||||
xhr.withCredentials = this.withCredentials;
|
xhr.withCredentials = this.withCredentials;
|
||||||
for (const property in this.httpHeaders) {
|
for (const property in this.httpHeaders) {
|
||||||
const value = this.httpHeaders[property];
|
const value = this.httpHeaders[property];
|
||||||
if (typeof value === 'undefined') {
|
if (typeof value === "undefined") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
xhr.setRequestHeader(property, value);
|
xhr.setRequestHeader(property, value);
|
||||||
}
|
}
|
||||||
if (this.isHttp && 'begin' in args && 'end' in args) {
|
if (this.isHttp && "begin" in args && "end" in args) {
|
||||||
xhr.setRequestHeader('Range', `bytes=${args.begin}-${args.end - 1}`);
|
xhr.setRequestHeader("Range", `bytes=${args.begin}-${args.end - 1}`);
|
||||||
pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE;
|
pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE;
|
||||||
} else {
|
} else {
|
||||||
pendingRequest.expectedStatus = OK_RESPONSE;
|
pendingRequest.expectedStatus = OK_RESPONSE;
|
||||||
}
|
}
|
||||||
xhr.responseType = 'arraybuffer';
|
xhr.responseType = "arraybuffer";
|
||||||
|
|
||||||
if (args.onError) {
|
if (args.onError) {
|
||||||
xhr.onerror = function(evt) {
|
xhr.onerror = function(evt) {
|
||||||
@ -163,8 +167,10 @@ class NetworkManager {
|
|||||||
xhrStatus === OK_RESPONSE &&
|
xhrStatus === OK_RESPONSE &&
|
||||||
pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
|
pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
|
||||||
|
|
||||||
if (!ok_response_on_range_request &&
|
if (
|
||||||
xhrStatus !== pendingRequest.expectedStatus) {
|
!ok_response_on_range_request &&
|
||||||
|
xhrStatus !== pendingRequest.expectedStatus
|
||||||
|
) {
|
||||||
if (pendingRequest.onError) {
|
if (pendingRequest.onError) {
|
||||||
pendingRequest.onError(xhr.status);
|
pendingRequest.onError(xhr.status);
|
||||||
}
|
}
|
||||||
@ -173,7 +179,7 @@ class NetworkManager {
|
|||||||
|
|
||||||
const chunk = getArrayBuffer(xhr);
|
const chunk = getArrayBuffer(xhr);
|
||||||
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
|
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
|
||||||
const rangeHeader = xhr.getResponseHeader('Content-Range');
|
const rangeHeader = xhr.getResponseHeader("Content-Range");
|
||||||
const matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
|
const matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
|
||||||
pendingRequest.onDone({
|
pendingRequest.onDone({
|
||||||
begin: parseInt(matches[1], 10),
|
begin: parseInt(matches[1], 10),
|
||||||
@ -239,14 +245,19 @@ class PDFNetworkStream {
|
|||||||
|
|
||||||
getFullReader() {
|
getFullReader() {
|
||||||
assert(!this._fullRequestReader);
|
assert(!this._fullRequestReader);
|
||||||
this._fullRequestReader =
|
this._fullRequestReader = new PDFNetworkStreamFullRequestReader(
|
||||||
new PDFNetworkStreamFullRequestReader(this._manager, this._source);
|
this._manager,
|
||||||
|
this._source
|
||||||
|
);
|
||||||
return this._fullRequestReader;
|
return this._fullRequestReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRangeReader(begin, end) {
|
getRangeReader(begin, end) {
|
||||||
const reader = new PDFNetworkStreamRangeRequestReader(this._manager,
|
const reader = new PDFNetworkStreamRangeRequestReader(
|
||||||
begin, end);
|
this._manager,
|
||||||
|
begin,
|
||||||
|
end
|
||||||
|
);
|
||||||
reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
|
reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
|
||||||
this._rangeRequestReaders.push(reader);
|
this._rangeRequestReaders.push(reader);
|
||||||
return reader;
|
return reader;
|
||||||
@ -300,11 +311,13 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
const fullRequestXhrId = this._fullRequestId;
|
const fullRequestXhrId = this._fullRequestId;
|
||||||
const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);
|
const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);
|
||||||
|
|
||||||
const getResponseHeader = (name) => {
|
const getResponseHeader = name => {
|
||||||
return fullRequestXhr.getResponseHeader(name);
|
return fullRequestXhr.getResponseHeader(name);
|
||||||
};
|
};
|
||||||
const { allowRangeRequests, suggestedLength, } =
|
const {
|
||||||
validateRangeRequestCapabilities({
|
allowRangeRequests,
|
||||||
|
suggestedLength,
|
||||||
|
} = validateRangeRequestCapabilities({
|
||||||
getResponseHeader,
|
getResponseHeader,
|
||||||
isHttp: this._manager.isHttp,
|
isHttp: this._manager.isHttp,
|
||||||
rangeChunkSize: this._rangeChunkSize,
|
rangeChunkSize: this._rangeChunkSize,
|
||||||
@ -334,7 +347,7 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
if (args) {
|
if (args) {
|
||||||
if (this._requests.length > 0) {
|
if (this._requests.length > 0) {
|
||||||
const requestCapability = this._requests.shift();
|
const requestCapability = this._requests.shift();
|
||||||
requestCapability.resolve({ value: args.chunk, done: false, });
|
requestCapability.resolve({ value: args.chunk, done: false });
|
||||||
} else {
|
} else {
|
||||||
this._cachedChunks.push(args.chunk);
|
this._cachedChunks.push(args.chunk);
|
||||||
}
|
}
|
||||||
@ -344,7 +357,7 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this._requests.forEach(function(requestCapability) {
|
this._requests.forEach(function(requestCapability) {
|
||||||
requestCapability.resolve({ value: undefined, done: true, });
|
requestCapability.resolve({ value: undefined, done: true });
|
||||||
});
|
});
|
||||||
this._requests = [];
|
this._requests = [];
|
||||||
}
|
}
|
||||||
@ -396,10 +409,10 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
}
|
}
|
||||||
if (this._cachedChunks.length > 0) {
|
if (this._cachedChunks.length > 0) {
|
||||||
const chunk = this._cachedChunks.shift();
|
const chunk = this._cachedChunks.shift();
|
||||||
return { value: chunk, done: false, };
|
return { value: chunk, done: false };
|
||||||
}
|
}
|
||||||
if (this._done) {
|
if (this._done) {
|
||||||
return { value: undefined, done: true, };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
const requestCapability = createPromiseCapability();
|
const requestCapability = createPromiseCapability();
|
||||||
this._requests.push(requestCapability);
|
this._requests.push(requestCapability);
|
||||||
@ -410,7 +423,7 @@ class PDFNetworkStreamFullRequestReader {
|
|||||||
this._done = true;
|
this._done = true;
|
||||||
this._headersReceivedCapability.reject(reason);
|
this._headersReceivedCapability.reject(reason);
|
||||||
this._requests.forEach(function(requestCapability) {
|
this._requests.forEach(function(requestCapability) {
|
||||||
requestCapability.resolve({ value: undefined, done: true, });
|
requestCapability.resolve({ value: undefined, done: true });
|
||||||
});
|
});
|
||||||
this._requests = [];
|
this._requests = [];
|
||||||
if (this._manager.isPendingRequest(this._fullRequestId)) {
|
if (this._manager.isPendingRequest(this._fullRequestId)) {
|
||||||
@ -447,13 +460,13 @@ class PDFNetworkStreamRangeRequestReader {
|
|||||||
const chunk = data.chunk;
|
const chunk = data.chunk;
|
||||||
if (this._requests.length > 0) {
|
if (this._requests.length > 0) {
|
||||||
const requestCapability = this._requests.shift();
|
const requestCapability = this._requests.shift();
|
||||||
requestCapability.resolve({ value: chunk, done: false, });
|
requestCapability.resolve({ value: chunk, done: false });
|
||||||
} else {
|
} else {
|
||||||
this._queuedChunk = chunk;
|
this._queuedChunk = chunk;
|
||||||
}
|
}
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this._requests.forEach(function(requestCapability) {
|
this._requests.forEach(function(requestCapability) {
|
||||||
requestCapability.resolve({ value: undefined, done: true, });
|
requestCapability.resolve({ value: undefined, done: true });
|
||||||
});
|
});
|
||||||
this._requests = [];
|
this._requests = [];
|
||||||
this._close();
|
this._close();
|
||||||
@ -475,10 +488,10 @@ class PDFNetworkStreamRangeRequestReader {
|
|||||||
if (this._queuedChunk !== null) {
|
if (this._queuedChunk !== null) {
|
||||||
const chunk = this._queuedChunk;
|
const chunk = this._queuedChunk;
|
||||||
this._queuedChunk = null;
|
this._queuedChunk = null;
|
||||||
return { value: chunk, done: false, };
|
return { value: chunk, done: false };
|
||||||
}
|
}
|
||||||
if (this._done) {
|
if (this._done) {
|
||||||
return { value: undefined, done: true, };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
const requestCapability = createPromiseCapability();
|
const requestCapability = createPromiseCapability();
|
||||||
this._requests.push(requestCapability);
|
this._requests.push(requestCapability);
|
||||||
@ -488,7 +501,7 @@ class PDFNetworkStreamRangeRequestReader {
|
|||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this._requests.forEach(function(requestCapability) {
|
this._requests.forEach(function(requestCapability) {
|
||||||
requestCapability.resolve({ value: undefined, done: true, });
|
requestCapability.resolve({ value: undefined, done: true });
|
||||||
});
|
});
|
||||||
this._requests = [];
|
this._requests = [];
|
||||||
if (this._manager.isPendingRequest(this._requestId)) {
|
if (this._manager.isPendingRequest(this._requestId)) {
|
||||||
@ -498,6 +511,4 @@ class PDFNetworkStreamRangeRequestReader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { PDFNetworkStream };
|
||||||
PDFNetworkStream,
|
|
||||||
};
|
|
||||||
|
@ -14,21 +14,25 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
assert, MissingPDFException, UnexpectedResponseException
|
assert,
|
||||||
} from '../shared/util';
|
MissingPDFException,
|
||||||
import {
|
UnexpectedResponseException,
|
||||||
getFilenameFromContentDispositionHeader
|
} from "../shared/util";
|
||||||
} from './content_disposition';
|
import { getFilenameFromContentDispositionHeader } from "./content_disposition";
|
||||||
|
|
||||||
function validateRangeRequestCapabilities({ getResponseHeader, isHttp,
|
function validateRangeRequestCapabilities({
|
||||||
rangeChunkSize, disableRange, }) {
|
getResponseHeader,
|
||||||
assert(rangeChunkSize > 0, 'Range chunk size must be larger than zero');
|
isHttp,
|
||||||
|
rangeChunkSize,
|
||||||
|
disableRange,
|
||||||
|
}) {
|
||||||
|
assert(rangeChunkSize > 0, "Range chunk size must be larger than zero");
|
||||||
let returnValues = {
|
let returnValues = {
|
||||||
allowRangeRequests: false,
|
allowRangeRequests: false,
|
||||||
suggestedLength: undefined,
|
suggestedLength: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
let length = parseInt(getResponseHeader('Content-Length'), 10);
|
let length = parseInt(getResponseHeader("Content-Length"), 10);
|
||||||
if (!Number.isInteger(length)) {
|
if (!Number.isInteger(length)) {
|
||||||
return returnValues;
|
return returnValues;
|
||||||
}
|
}
|
||||||
@ -44,12 +48,12 @@ function validateRangeRequestCapabilities({ getResponseHeader, isHttp,
|
|||||||
if (disableRange || !isHttp) {
|
if (disableRange || !isHttp) {
|
||||||
return returnValues;
|
return returnValues;
|
||||||
}
|
}
|
||||||
if (getResponseHeader('Accept-Ranges') !== 'bytes') {
|
if (getResponseHeader("Accept-Ranges") !== "bytes") {
|
||||||
return returnValues;
|
return returnValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
let contentEncoding = getResponseHeader('Content-Encoding') || 'identity';
|
let contentEncoding = getResponseHeader("Content-Encoding") || "identity";
|
||||||
if (contentEncoding !== 'identity') {
|
if (contentEncoding !== "identity") {
|
||||||
return returnValues;
|
return returnValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,10 +62,10 @@ function validateRangeRequestCapabilities({ getResponseHeader, isHttp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
function extractFilenameFromHeader(getResponseHeader) {
|
function extractFilenameFromHeader(getResponseHeader) {
|
||||||
const contentDisposition = getResponseHeader('Content-Disposition');
|
const contentDisposition = getResponseHeader("Content-Disposition");
|
||||||
if (contentDisposition) {
|
if (contentDisposition) {
|
||||||
let filename = getFilenameFromContentDispositionHeader(contentDisposition);
|
let filename = getFilenameFromContentDispositionHeader(contentDisposition);
|
||||||
if (filename.includes('%')) {
|
if (filename.includes("%")) {
|
||||||
try {
|
try {
|
||||||
filename = decodeURIComponent(filename);
|
filename = decodeURIComponent(filename);
|
||||||
} catch (ex) {}
|
} catch (ex) {}
|
||||||
@ -74,12 +78,17 @@ function extractFilenameFromHeader(getResponseHeader) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createResponseStatusError(status, url) {
|
function createResponseStatusError(status, url) {
|
||||||
if (status === 404 || status === 0 && /^file:/.test(url)) {
|
if (status === 404 || (status === 0 && /^file:/.test(url))) {
|
||||||
return new MissingPDFException('Missing PDF "' + url + '".');
|
return new MissingPDFException('Missing PDF "' + url + '".');
|
||||||
}
|
}
|
||||||
return new UnexpectedResponseException(
|
return new UnexpectedResponseException(
|
||||||
'Unexpected server response (' + status +
|
"Unexpected server response (" +
|
||||||
') while retrieving PDF "' + url + '".', status);
|
status +
|
||||||
|
') while retrieving PDF "' +
|
||||||
|
url +
|
||||||
|
'".',
|
||||||
|
status
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateResponseStatus(status) {
|
function validateResponseStatus(status) {
|
||||||
|
@ -14,23 +14,27 @@
|
|||||||
*/
|
*/
|
||||||
/* globals __non_webpack_require__ */
|
/* globals __non_webpack_require__ */
|
||||||
|
|
||||||
let fs = __non_webpack_require__('fs');
|
let fs = __non_webpack_require__("fs");
|
||||||
let http = __non_webpack_require__('http');
|
let http = __non_webpack_require__("http");
|
||||||
let https = __non_webpack_require__('https');
|
let https = __non_webpack_require__("https");
|
||||||
let url = __non_webpack_require__('url');
|
let url = __non_webpack_require__("url");
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AbortException, assert, createPromiseCapability, MissingPDFException
|
AbortException,
|
||||||
} from '../shared/util';
|
assert,
|
||||||
|
createPromiseCapability,
|
||||||
|
MissingPDFException,
|
||||||
|
} from "../shared/util";
|
||||||
import {
|
import {
|
||||||
extractFilenameFromHeader, validateRangeRequestCapabilities
|
extractFilenameFromHeader,
|
||||||
} from './network_utils';
|
validateRangeRequestCapabilities,
|
||||||
|
} from "./network_utils";
|
||||||
|
|
||||||
const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
|
const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
|
||||||
|
|
||||||
function parseUrl(sourceUrl) {
|
function parseUrl(sourceUrl) {
|
||||||
let parsedUrl = url.parse(sourceUrl);
|
let parsedUrl = url.parse(sourceUrl);
|
||||||
if (parsedUrl.protocol === 'file:' || parsedUrl.host) {
|
if (parsedUrl.protocol === "file:" || parsedUrl.host) {
|
||||||
return parsedUrl;
|
return parsedUrl;
|
||||||
}
|
}
|
||||||
// Prepending 'file:///' to Windows absolute path.
|
// Prepending 'file:///' to Windows absolute path.
|
||||||
@ -39,7 +43,7 @@ function parseUrl(sourceUrl) {
|
|||||||
}
|
}
|
||||||
// Changes protocol to 'file:' if url refers to filesystem.
|
// Changes protocol to 'file:' if url refers to filesystem.
|
||||||
if (!parsedUrl.host) {
|
if (!parsedUrl.host) {
|
||||||
parsedUrl.protocol = 'file:';
|
parsedUrl.protocol = "file:";
|
||||||
}
|
}
|
||||||
return parsedUrl;
|
return parsedUrl;
|
||||||
}
|
}
|
||||||
@ -48,10 +52,10 @@ class PDFNodeStream {
|
|||||||
constructor(source) {
|
constructor(source) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.url = parseUrl(source.url);
|
this.url = parseUrl(source.url);
|
||||||
this.isHttp = this.url.protocol === 'http:' ||
|
this.isHttp =
|
||||||
this.url.protocol === 'https:';
|
this.url.protocol === "http:" || this.url.protocol === "https:";
|
||||||
// Check if url refers to filesystem.
|
// Check if url refers to filesystem.
|
||||||
this.isFsUrl = this.url.protocol === 'file:';
|
this.isFsUrl = this.url.protocol === "file:";
|
||||||
this.httpHeaders = (this.isHttp && source.httpHeaders) || {};
|
this.httpHeaders = (this.isHttp && source.httpHeaders) || {};
|
||||||
|
|
||||||
this._fullRequestReader = null;
|
this._fullRequestReader = null;
|
||||||
@ -59,14 +63,14 @@ class PDFNodeStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get _progressiveDataLength() {
|
get _progressiveDataLength() {
|
||||||
return (this._fullRequestReader ? this._fullRequestReader._loaded : 0);
|
return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
getFullReader() {
|
getFullReader() {
|
||||||
assert(!this._fullRequestReader);
|
assert(!this._fullRequestReader);
|
||||||
this._fullRequestReader = this.isFsUrl ?
|
this._fullRequestReader = this.isFsUrl
|
||||||
new PDFNodeStreamFsFullReader(this) :
|
? new PDFNodeStreamFsFullReader(this)
|
||||||
new PDFNodeStreamFullReader(this);
|
: new PDFNodeStreamFullReader(this);
|
||||||
return this._fullRequestReader;
|
return this._fullRequestReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,9 +78,9 @@ class PDFNodeStream {
|
|||||||
if (end <= this._progressiveDataLength) {
|
if (end <= this._progressiveDataLength) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let rangeReader = this.isFsUrl ?
|
let rangeReader = this.isFsUrl
|
||||||
new PDFNodeStreamFsRangeReader(this, start, end) :
|
? new PDFNodeStreamFsRangeReader(this, start, end)
|
||||||
new PDFNodeStreamRangeReader(this, start, end);
|
: new PDFNodeStreamRangeReader(this, start, end);
|
||||||
this._rangeRequestReaders.push(rangeReader);
|
this._rangeRequestReaders.push(rangeReader);
|
||||||
return rangeReader;
|
return rangeReader;
|
||||||
}
|
}
|
||||||
@ -141,7 +145,7 @@ class BaseFullReader {
|
|||||||
async read() {
|
async read() {
|
||||||
await this._readCapability.promise;
|
await this._readCapability.promise;
|
||||||
if (this._done) {
|
if (this._done) {
|
||||||
return { value: undefined, done: true, };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
if (this._storedError) {
|
if (this._storedError) {
|
||||||
throw this._storedError;
|
throw this._storedError;
|
||||||
@ -161,7 +165,7 @@ class BaseFullReader {
|
|||||||
}
|
}
|
||||||
// Ensure that `read()` method returns ArrayBuffer.
|
// Ensure that `read()` method returns ArrayBuffer.
|
||||||
let buffer = new Uint8Array(chunk).buffer;
|
let buffer = new Uint8Array(chunk).buffer;
|
||||||
return { value: buffer, done: false, };
|
return { value: buffer, done: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
@ -181,25 +185,25 @@ class BaseFullReader {
|
|||||||
|
|
||||||
_setReadableStream(readableStream) {
|
_setReadableStream(readableStream) {
|
||||||
this._readableStream = readableStream;
|
this._readableStream = readableStream;
|
||||||
readableStream.on('readable', () => {
|
readableStream.on("readable", () => {
|
||||||
this._readCapability.resolve();
|
this._readCapability.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
readableStream.on('end', () => {
|
readableStream.on("end", () => {
|
||||||
// Destroy readable to minimize resource usage.
|
// Destroy readable to minimize resource usage.
|
||||||
readableStream.destroy();
|
readableStream.destroy();
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this._readCapability.resolve();
|
this._readCapability.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
readableStream.on('error', (reason) => {
|
readableStream.on("error", reason => {
|
||||||
this._error(reason);
|
this._error(reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
// We need to stop reading when range is supported and streaming is
|
// We need to stop reading when range is supported and streaming is
|
||||||
// disabled.
|
// disabled.
|
||||||
if (!this._isStreamingSupported && this._isRangeSupported) {
|
if (!this._isStreamingSupported && this._isRangeSupported) {
|
||||||
this._error(new AbortException('streaming is disabled'));
|
this._error(new AbortException("streaming is disabled"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy ReadableStream if already in errored state.
|
// Destroy ReadableStream if already in errored state.
|
||||||
@ -229,7 +233,7 @@ class BaseRangeReader {
|
|||||||
async read() {
|
async read() {
|
||||||
await this._readCapability.promise;
|
await this._readCapability.promise;
|
||||||
if (this._done) {
|
if (this._done) {
|
||||||
return { value: undefined, done: true, };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
if (this._storedError) {
|
if (this._storedError) {
|
||||||
throw this._storedError;
|
throw this._storedError;
|
||||||
@ -242,11 +246,11 @@ class BaseRangeReader {
|
|||||||
}
|
}
|
||||||
this._loaded += chunk.length;
|
this._loaded += chunk.length;
|
||||||
if (this.onProgress) {
|
if (this.onProgress) {
|
||||||
this.onProgress({ loaded: this._loaded, });
|
this.onProgress({ loaded: this._loaded });
|
||||||
}
|
}
|
||||||
// Ensure that `read()` method returns ArrayBuffer.
|
// Ensure that `read()` method returns ArrayBuffer.
|
||||||
let buffer = new Uint8Array(chunk).buffer;
|
let buffer = new Uint8Array(chunk).buffer;
|
||||||
return { value: buffer, done: false, };
|
return { value: buffer, done: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
@ -266,18 +270,18 @@ class BaseRangeReader {
|
|||||||
|
|
||||||
_setReadableStream(readableStream) {
|
_setReadableStream(readableStream) {
|
||||||
this._readableStream = readableStream;
|
this._readableStream = readableStream;
|
||||||
readableStream.on('readable', () => {
|
readableStream.on("readable", () => {
|
||||||
this._readCapability.resolve();
|
this._readCapability.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
readableStream.on('end', () => {
|
readableStream.on("end", () => {
|
||||||
// Destroy readableStream to minimize resource usage.
|
// Destroy readableStream to minimize resource usage.
|
||||||
readableStream.destroy();
|
readableStream.destroy();
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this._readCapability.resolve();
|
this._readCapability.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
readableStream.on('error', (reason) => {
|
readableStream.on("error", reason => {
|
||||||
this._error(reason);
|
this._error(reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -295,7 +299,7 @@ function createRequestOptions(url, headers) {
|
|||||||
host: url.hostname,
|
host: url.hostname,
|
||||||
port: url.port,
|
port: url.port,
|
||||||
path: url.path,
|
path: url.path,
|
||||||
method: 'GET',
|
method: "GET",
|
||||||
headers,
|
headers,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -304,7 +308,7 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||||||
constructor(stream) {
|
constructor(stream) {
|
||||||
super(stream);
|
super(stream);
|
||||||
|
|
||||||
let handleResponse = (response) => {
|
let handleResponse = response => {
|
||||||
if (response.statusCode === 404) {
|
if (response.statusCode === 404) {
|
||||||
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
||||||
this._storedError = error;
|
this._storedError = error;
|
||||||
@ -314,13 +318,15 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||||||
this._headersCapability.resolve();
|
this._headersCapability.resolve();
|
||||||
this._setReadableStream(response);
|
this._setReadableStream(response);
|
||||||
|
|
||||||
const getResponseHeader = (name) => {
|
const getResponseHeader = name => {
|
||||||
// Make sure that headers name are in lower case, as mentioned
|
// Make sure that headers name are in lower case, as mentioned
|
||||||
// here: https://nodejs.org/api/http.html#http_message_headers.
|
// here: https://nodejs.org/api/http.html#http_message_headers.
|
||||||
return this._readableStream.headers[name.toLowerCase()];
|
return this._readableStream.headers[name.toLowerCase()];
|
||||||
};
|
};
|
||||||
let { allowRangeRequests, suggestedLength, } =
|
let {
|
||||||
validateRangeRequestCapabilities({
|
allowRangeRequests,
|
||||||
|
suggestedLength,
|
||||||
|
} = validateRangeRequestCapabilities({
|
||||||
getResponseHeader,
|
getResponseHeader,
|
||||||
isHttp: stream.isHttp,
|
isHttp: stream.isHttp,
|
||||||
rangeChunkSize: this._rangeChunkSize,
|
rangeChunkSize: this._rangeChunkSize,
|
||||||
@ -335,17 +341,19 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this._request = null;
|
this._request = null;
|
||||||
if (this._url.protocol === 'http:') {
|
if (this._url.protocol === "http:") {
|
||||||
this._request = http.request(
|
this._request = http.request(
|
||||||
createRequestOptions(this._url, stream.httpHeaders),
|
createRequestOptions(this._url, stream.httpHeaders),
|
||||||
handleResponse);
|
handleResponse
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this._request = https.request(
|
this._request = https.request(
|
||||||
createRequestOptions(this._url, stream.httpHeaders),
|
createRequestOptions(this._url, stream.httpHeaders),
|
||||||
handleResponse);
|
handleResponse
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._request.on('error', (reason) => {
|
this._request.on("error", reason => {
|
||||||
this._storedError = reason;
|
this._storedError = reason;
|
||||||
this._headersCapability.reject(reason);
|
this._headersCapability.reject(reason);
|
||||||
});
|
});
|
||||||
@ -363,14 +371,14 @@ class PDFNodeStreamRangeReader extends BaseRangeReader {
|
|||||||
this._httpHeaders = {};
|
this._httpHeaders = {};
|
||||||
for (let property in stream.httpHeaders) {
|
for (let property in stream.httpHeaders) {
|
||||||
let value = stream.httpHeaders[property];
|
let value = stream.httpHeaders[property];
|
||||||
if (typeof value === 'undefined') {
|
if (typeof value === "undefined") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
this._httpHeaders[property] = value;
|
this._httpHeaders[property] = value;
|
||||||
}
|
}
|
||||||
this._httpHeaders['Range'] = `bytes=${start}-${end - 1}`;
|
this._httpHeaders["Range"] = `bytes=${start}-${end - 1}`;
|
||||||
|
|
||||||
let handleResponse = (response) => {
|
let handleResponse = response => {
|
||||||
if (response.statusCode === 404) {
|
if (response.statusCode === 404) {
|
||||||
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
||||||
this._storedError = error;
|
this._storedError = error;
|
||||||
@ -380,17 +388,19 @@ class PDFNodeStreamRangeReader extends BaseRangeReader {
|
|||||||
};
|
};
|
||||||
|
|
||||||
this._request = null;
|
this._request = null;
|
||||||
if (this._url.protocol === 'http:') {
|
if (this._url.protocol === "http:") {
|
||||||
this._request = http.request(
|
this._request = http.request(
|
||||||
createRequestOptions(this._url, this._httpHeaders),
|
createRequestOptions(this._url, this._httpHeaders),
|
||||||
handleResponse);
|
handleResponse
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this._request = https.request(
|
this._request = https.request(
|
||||||
createRequestOptions(this._url, this._httpHeaders),
|
createRequestOptions(this._url, this._httpHeaders),
|
||||||
handleResponse);
|
handleResponse
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._request.on('error', (reason) => {
|
this._request.on("error", reason => {
|
||||||
this._storedError = reason;
|
this._storedError = reason;
|
||||||
});
|
});
|
||||||
this._request.end();
|
this._request.end();
|
||||||
@ -405,12 +415,12 @@ class PDFNodeStreamFsFullReader extends BaseFullReader {
|
|||||||
|
|
||||||
// Remove the extra slash to get right path from url like `file:///C:/`
|
// Remove the extra slash to get right path from url like `file:///C:/`
|
||||||
if (fileUriRegex.test(this._url.href)) {
|
if (fileUriRegex.test(this._url.href)) {
|
||||||
path = path.replace(/^\//, '');
|
path = path.replace(/^\//, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.lstat(path, (error, stat) => {
|
fs.lstat(path, (error, stat) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
if (error.code === 'ENOENT') {
|
if (error.code === "ENOENT") {
|
||||||
error = new MissingPDFException(`Missing PDF "${path}".`);
|
error = new MissingPDFException(`Missing PDF "${path}".`);
|
||||||
}
|
}
|
||||||
this._storedError = error;
|
this._storedError = error;
|
||||||
@ -434,14 +444,11 @@ class PDFNodeStreamFsRangeReader extends BaseRangeReader {
|
|||||||
|
|
||||||
// Remove the extra slash to get right path from url like `file:///C:/`
|
// Remove the extra slash to get right path from url like `file:///C:/`
|
||||||
if (fileUriRegex.test(this._url.href)) {
|
if (fileUriRegex.test(this._url.href)) {
|
||||||
path = path.replace(/^\//, '');
|
path = path.replace(/^\//, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
this._setReadableStream(
|
this._setReadableStream(fs.createReadStream(path, { start, end: end - 1 }));
|
||||||
fs.createReadStream(path, { start, end: end - 1, }));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { PDFNodeStream };
|
||||||
PDFNodeStream,
|
|
||||||
};
|
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FormatError, info, Util } from '../shared/util';
|
import { FormatError, info, Util } from "../shared/util";
|
||||||
|
|
||||||
var ShadingIRs = {};
|
var ShadingIRs = {};
|
||||||
|
|
||||||
function applyBoundingBox(ctx, bbox) {
|
function applyBoundingBox(ctx, bbox) {
|
||||||
if (!bbox || typeof Path2D === 'undefined') {
|
if (!bbox || typeof Path2D === "undefined") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const width = bbox[2] - bbox[0];
|
const width = bbox[2] - bbox[0];
|
||||||
@ -38,13 +38,13 @@ ShadingIRs.RadialAxial = {
|
|||||||
var r0 = raw[6];
|
var r0 = raw[6];
|
||||||
var r1 = raw[7];
|
var r1 = raw[7];
|
||||||
return {
|
return {
|
||||||
type: 'Pattern',
|
type: "Pattern",
|
||||||
getPattern: function RadialAxial_getPattern(ctx) {
|
getPattern: function RadialAxial_getPattern(ctx) {
|
||||||
applyBoundingBox(ctx, bbox);
|
applyBoundingBox(ctx, bbox);
|
||||||
var grad;
|
var grad;
|
||||||
if (type === 'axial') {
|
if (type === "axial") {
|
||||||
grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
|
grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
|
||||||
} else if (type === 'radial') {
|
} else if (type === "radial") {
|
||||||
grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
|
grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,17 +61,34 @@ ShadingIRs.RadialAxial = {
|
|||||||
var createMeshCanvas = (function createMeshCanvasClosure() {
|
var createMeshCanvas = (function createMeshCanvasClosure() {
|
||||||
function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
|
function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
|
||||||
// Very basic Gouraud-shaded triangle rasterization algorithm.
|
// Very basic Gouraud-shaded triangle rasterization algorithm.
|
||||||
var coords = context.coords, colors = context.colors;
|
var coords = context.coords,
|
||||||
var bytes = data.data, rowSize = data.width * 4;
|
colors = context.colors;
|
||||||
|
var bytes = data.data,
|
||||||
|
rowSize = data.width * 4;
|
||||||
var tmp;
|
var tmp;
|
||||||
if (coords[p1 + 1] > coords[p2 + 1]) {
|
if (coords[p1 + 1] > coords[p2 + 1]) {
|
||||||
tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp;
|
tmp = p1;
|
||||||
|
p1 = p2;
|
||||||
|
p2 = tmp;
|
||||||
|
tmp = c1;
|
||||||
|
c1 = c2;
|
||||||
|
c2 = tmp;
|
||||||
}
|
}
|
||||||
if (coords[p2 + 1] > coords[p3 + 1]) {
|
if (coords[p2 + 1] > coords[p3 + 1]) {
|
||||||
tmp = p2; p2 = p3; p3 = tmp; tmp = c2; c2 = c3; c3 = tmp;
|
tmp = p2;
|
||||||
|
p2 = p3;
|
||||||
|
p3 = tmp;
|
||||||
|
tmp = c2;
|
||||||
|
c2 = c3;
|
||||||
|
c3 = tmp;
|
||||||
}
|
}
|
||||||
if (coords[p1 + 1] > coords[p2 + 1]) {
|
if (coords[p1 + 1] > coords[p2 + 1]) {
|
||||||
tmp = p1; p1 = p2; p2 = tmp; tmp = c1; c1 = c2; c2 = tmp;
|
tmp = p1;
|
||||||
|
p1 = p2;
|
||||||
|
p2 = tmp;
|
||||||
|
tmp = c1;
|
||||||
|
c1 = c2;
|
||||||
|
c2 = tmp;
|
||||||
}
|
}
|
||||||
var x1 = (coords[p1] + context.offsetX) * context.scaleX;
|
var x1 = (coords[p1] + context.offsetX) * context.scaleX;
|
||||||
var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
|
var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
|
||||||
@ -82,11 +99,18 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
|||||||
if (y1 >= y3) {
|
if (y1 >= y3) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var c1r = colors[c1], c1g = colors[c1 + 1], c1b = colors[c1 + 2];
|
var c1r = colors[c1],
|
||||||
var c2r = colors[c2], c2g = colors[c2 + 1], c2b = colors[c2 + 2];
|
c1g = colors[c1 + 1],
|
||||||
var c3r = colors[c3], c3g = colors[c3 + 1], c3b = colors[c3 + 2];
|
c1b = colors[c1 + 2];
|
||||||
|
var c2r = colors[c2],
|
||||||
|
c2g = colors[c2 + 1],
|
||||||
|
c2b = colors[c2 + 2];
|
||||||
|
var c3r = colors[c3],
|
||||||
|
c3g = colors[c3 + 1],
|
||||||
|
c3b = colors[c3 + 2];
|
||||||
|
|
||||||
var minY = Math.round(y1), maxY = Math.round(y3);
|
var minY = Math.round(y1),
|
||||||
|
maxY = Math.round(y3);
|
||||||
var xa, car, cag, cab;
|
var xa, car, cag, cab;
|
||||||
var xb, cbr, cbg, cbb;
|
var xb, cbr, cbg, cbb;
|
||||||
var k;
|
var k;
|
||||||
@ -128,36 +152,65 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
|||||||
var cs = figure.colors;
|
var cs = figure.colors;
|
||||||
var i, ii;
|
var i, ii;
|
||||||
switch (figure.type) {
|
switch (figure.type) {
|
||||||
case 'lattice':
|
case "lattice":
|
||||||
var verticesPerRow = figure.verticesPerRow;
|
var verticesPerRow = figure.verticesPerRow;
|
||||||
var rows = Math.floor(ps.length / verticesPerRow) - 1;
|
var rows = Math.floor(ps.length / verticesPerRow) - 1;
|
||||||
var cols = verticesPerRow - 1;
|
var cols = verticesPerRow - 1;
|
||||||
for (i = 0; i < rows; i++) {
|
for (i = 0; i < rows; i++) {
|
||||||
var q = i * verticesPerRow;
|
var q = i * verticesPerRow;
|
||||||
for (var j = 0; j < cols; j++, q++) {
|
for (var j = 0; j < cols; j++, q++) {
|
||||||
drawTriangle(data, context,
|
drawTriangle(
|
||||||
ps[q], ps[q + 1], ps[q + verticesPerRow],
|
data,
|
||||||
cs[q], cs[q + 1], cs[q + verticesPerRow]);
|
context,
|
||||||
drawTriangle(data, context,
|
ps[q],
|
||||||
ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow],
|
ps[q + 1],
|
||||||
cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);
|
ps[q + verticesPerRow],
|
||||||
|
cs[q],
|
||||||
|
cs[q + 1],
|
||||||
|
cs[q + verticesPerRow]
|
||||||
|
);
|
||||||
|
drawTriangle(
|
||||||
|
data,
|
||||||
|
context,
|
||||||
|
ps[q + verticesPerRow + 1],
|
||||||
|
ps[q + 1],
|
||||||
|
ps[q + verticesPerRow],
|
||||||
|
cs[q + verticesPerRow + 1],
|
||||||
|
cs[q + 1],
|
||||||
|
cs[q + verticesPerRow]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'triangles':
|
case "triangles":
|
||||||
for (i = 0, ii = ps.length; i < ii; i += 3) {
|
for (i = 0, ii = ps.length; i < ii; i += 3) {
|
||||||
drawTriangle(data, context,
|
drawTriangle(
|
||||||
ps[i], ps[i + 1], ps[i + 2],
|
data,
|
||||||
cs[i], cs[i + 1], cs[i + 2]);
|
context,
|
||||||
|
ps[i],
|
||||||
|
ps[i + 1],
|
||||||
|
ps[i + 2],
|
||||||
|
cs[i],
|
||||||
|
cs[i + 1],
|
||||||
|
cs[i + 2]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error('illegal figure');
|
throw new Error("illegal figure");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createMeshCanvas(bounds, combinesScale, coords, colors, figures,
|
function createMeshCanvas(
|
||||||
backgroundColor, cachedCanvases, webGLContext) {
|
bounds,
|
||||||
|
combinesScale,
|
||||||
|
coords,
|
||||||
|
colors,
|
||||||
|
figures,
|
||||||
|
backgroundColor,
|
||||||
|
cachedCanvases,
|
||||||
|
webGLContext
|
||||||
|
) {
|
||||||
// we will increase scale on some weird factor to let antialiasing take
|
// we will increase scale on some weird factor to let antialiasing take
|
||||||
// care of "rough" edges
|
// care of "rough" edges
|
||||||
var EXPECTED_SCALE = 1.1;
|
var EXPECTED_SCALE = 1.1;
|
||||||
@ -172,10 +225,14 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
|||||||
var boundsWidth = Math.ceil(bounds[2]) - offsetX;
|
var boundsWidth = Math.ceil(bounds[2]) - offsetX;
|
||||||
var boundsHeight = Math.ceil(bounds[3]) - offsetY;
|
var boundsHeight = Math.ceil(bounds[3]) - offsetY;
|
||||||
|
|
||||||
var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] *
|
var width = Math.min(
|
||||||
EXPECTED_SCALE)), MAX_PATTERN_SIZE);
|
Math.ceil(Math.abs(boundsWidth * combinesScale[0] * EXPECTED_SCALE)),
|
||||||
var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] *
|
MAX_PATTERN_SIZE
|
||||||
EXPECTED_SCALE)), MAX_PATTERN_SIZE);
|
);
|
||||||
|
var height = Math.min(
|
||||||
|
Math.ceil(Math.abs(boundsHeight * combinesScale[1] * EXPECTED_SCALE)),
|
||||||
|
MAX_PATTERN_SIZE
|
||||||
|
);
|
||||||
var scaleX = boundsWidth / width;
|
var scaleX = boundsWidth / width;
|
||||||
var scaleY = boundsHeight / height;
|
var scaleY = boundsHeight / height;
|
||||||
|
|
||||||
@ -201,13 +258,21 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
|||||||
context,
|
context,
|
||||||
});
|
});
|
||||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=972126
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=972126
|
||||||
tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight,
|
tmpCanvas = cachedCanvases.getCanvas(
|
||||||
false);
|
"mesh",
|
||||||
|
paddedWidth,
|
||||||
|
paddedHeight,
|
||||||
|
false
|
||||||
|
);
|
||||||
tmpCanvas.context.drawImage(canvas, BORDER_SIZE, BORDER_SIZE);
|
tmpCanvas.context.drawImage(canvas, BORDER_SIZE, BORDER_SIZE);
|
||||||
canvas = tmpCanvas.canvas;
|
canvas = tmpCanvas.canvas;
|
||||||
} else {
|
} else {
|
||||||
tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight,
|
tmpCanvas = cachedCanvases.getCanvas(
|
||||||
false);
|
"mesh",
|
||||||
|
paddedWidth,
|
||||||
|
paddedHeight,
|
||||||
|
false
|
||||||
|
);
|
||||||
var tmpCtx = tmpCanvas.context;
|
var tmpCtx = tmpCanvas.context;
|
||||||
|
|
||||||
var data = tmpCtx.createImageData(width, height);
|
var data = tmpCtx.createImageData(width, height);
|
||||||
@ -249,7 +314,7 @@ ShadingIRs.Mesh = {
|
|||||||
var bbox = raw[7];
|
var bbox = raw[7];
|
||||||
var background = raw[8];
|
var background = raw[8];
|
||||||
return {
|
return {
|
||||||
type: 'Pattern',
|
type: "Pattern",
|
||||||
getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
|
getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
|
||||||
applyBoundingBox(ctx, bbox);
|
applyBoundingBox(ctx, bbox);
|
||||||
var scale;
|
var scale;
|
||||||
@ -260,16 +325,22 @@ ShadingIRs.Mesh = {
|
|||||||
scale = Util.singularValueDecompose2dScale(owner.baseTransform);
|
scale = Util.singularValueDecompose2dScale(owner.baseTransform);
|
||||||
if (matrix) {
|
if (matrix) {
|
||||||
var matrixScale = Util.singularValueDecompose2dScale(matrix);
|
var matrixScale = Util.singularValueDecompose2dScale(matrix);
|
||||||
scale = [scale[0] * matrixScale[0],
|
scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]];
|
||||||
scale[1] * matrixScale[1]];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rasterizing on the main thread since sending/queue large canvases
|
// Rasterizing on the main thread since sending/queue large canvases
|
||||||
// might cause OOM.
|
// might cause OOM.
|
||||||
var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords,
|
var temporaryPatternCanvas = createMeshCanvas(
|
||||||
colors, figures, shadingFill ? null : background,
|
bounds,
|
||||||
owner.cachedCanvases, owner.webGLContext);
|
scale,
|
||||||
|
coords,
|
||||||
|
colors,
|
||||||
|
figures,
|
||||||
|
shadingFill ? null : background,
|
||||||
|
owner.cachedCanvases,
|
||||||
|
owner.webGLContext
|
||||||
|
);
|
||||||
|
|
||||||
if (!shadingFill) {
|
if (!shadingFill) {
|
||||||
ctx.setTransform.apply(ctx, owner.baseTransform);
|
ctx.setTransform.apply(ctx, owner.baseTransform);
|
||||||
@ -278,12 +349,13 @@ ShadingIRs.Mesh = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.translate(temporaryPatternCanvas.offsetX,
|
ctx.translate(
|
||||||
temporaryPatternCanvas.offsetY);
|
temporaryPatternCanvas.offsetX,
|
||||||
ctx.scale(temporaryPatternCanvas.scaleX,
|
temporaryPatternCanvas.offsetY
|
||||||
temporaryPatternCanvas.scaleY);
|
);
|
||||||
|
ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
|
||||||
|
|
||||||
return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat');
|
return ctx.createPattern(temporaryPatternCanvas.canvas, "no-repeat");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -292,9 +364,9 @@ ShadingIRs.Mesh = {
|
|||||||
ShadingIRs.Dummy = {
|
ShadingIRs.Dummy = {
|
||||||
fromIR: function Dummy_fromIR() {
|
fromIR: function Dummy_fromIR() {
|
||||||
return {
|
return {
|
||||||
type: 'Pattern',
|
type: "Pattern",
|
||||||
getPattern: function Dummy_fromIR_getPattern() {
|
getPattern: function Dummy_fromIR_getPattern() {
|
||||||
return 'hotpink';
|
return "hotpink";
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
@ -327,7 +399,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
this.color = color;
|
this.color = color;
|
||||||
this.canvasGraphicsFactory = canvasGraphicsFactory;
|
this.canvasGraphicsFactory = canvasGraphicsFactory;
|
||||||
this.baseTransform = baseTransform;
|
this.baseTransform = baseTransform;
|
||||||
this.type = 'Pattern';
|
this.type = "Pattern";
|
||||||
this.ctx = ctx;
|
this.ctx = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +414,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
var color = this.color;
|
var color = this.color;
|
||||||
var canvasGraphicsFactory = this.canvasGraphicsFactory;
|
var canvasGraphicsFactory = this.canvasGraphicsFactory;
|
||||||
|
|
||||||
info('TilingType: ' + tilingType);
|
info("TilingType: " + tilingType);
|
||||||
|
|
||||||
// A tiling pattern as defined by PDF spec 8.7.2 is a cell whose size is
|
// A tiling pattern as defined by PDF spec 8.7.2 is a cell whose size is
|
||||||
// described by bbox, and may repeat regularly by shifting the cell by
|
// described by bbox, and may repeat regularly by shifting the cell by
|
||||||
@ -364,25 +436,41 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
// TODO: Fix the implementation, to allow this scenario to be painted
|
// TODO: Fix the implementation, to allow this scenario to be painted
|
||||||
// correctly.
|
// correctly.
|
||||||
|
|
||||||
var x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3];
|
var x0 = bbox[0],
|
||||||
|
y0 = bbox[1],
|
||||||
|
x1 = bbox[2],
|
||||||
|
y1 = bbox[3];
|
||||||
|
|
||||||
// Obtain scale from matrix and current transformation matrix.
|
// Obtain scale from matrix and current transformation matrix.
|
||||||
var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
|
var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
|
||||||
var curMatrixScale = Util.singularValueDecompose2dScale(
|
var curMatrixScale = Util.singularValueDecompose2dScale(
|
||||||
this.baseTransform);
|
this.baseTransform
|
||||||
var combinedScale = [matrixScale[0] * curMatrixScale[0],
|
);
|
||||||
matrixScale[1] * curMatrixScale[1]];
|
var combinedScale = [
|
||||||
|
matrixScale[0] * curMatrixScale[0],
|
||||||
|
matrixScale[1] * curMatrixScale[1],
|
||||||
|
];
|
||||||
|
|
||||||
// Use width and height values that are as close as possible to the end
|
// Use width and height values that are as close as possible to the end
|
||||||
// result when the pattern is used. Too low value makes the pattern look
|
// result when the pattern is used. Too low value makes the pattern look
|
||||||
// blurry. Too large value makes it look too crispy.
|
// blurry. Too large value makes it look too crispy.
|
||||||
var dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width,
|
var dimx = this.getSizeAndScale(
|
||||||
combinedScale[0]);
|
xstep,
|
||||||
var dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height,
|
this.ctx.canvas.width,
|
||||||
combinedScale[1]);
|
combinedScale[0]
|
||||||
|
);
|
||||||
|
var dimy = this.getSizeAndScale(
|
||||||
|
ystep,
|
||||||
|
this.ctx.canvas.height,
|
||||||
|
combinedScale[1]
|
||||||
|
);
|
||||||
|
|
||||||
var tmpCanvas = owner.cachedCanvases.getCanvas('pattern',
|
var tmpCanvas = owner.cachedCanvases.getCanvas(
|
||||||
dimx.size, dimy.size, true);
|
"pattern",
|
||||||
|
dimx.size,
|
||||||
|
dimy.size,
|
||||||
|
true
|
||||||
|
);
|
||||||
var tmpCtx = tmpCanvas.context;
|
var tmpCtx = tmpCanvas.context;
|
||||||
var graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
|
var graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
|
||||||
graphics.groupLevel = owner.groupLevel;
|
graphics.groupLevel = owner.groupLevel;
|
||||||
@ -406,8 +494,11 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
return tmpCanvas.canvas;
|
return tmpCanvas.canvas;
|
||||||
},
|
},
|
||||||
|
|
||||||
getSizeAndScale:
|
getSizeAndScale: function TilingPattern_getSizeAndScale(
|
||||||
function TilingPattern_getSizeAndScale(step, realOutputSize, scale) {
|
step,
|
||||||
|
realOutputSize,
|
||||||
|
scale
|
||||||
|
) {
|
||||||
// xstep / ystep may be negative -- normalize.
|
// xstep / ystep may be negative -- normalize.
|
||||||
step = Math.abs(step);
|
step = Math.abs(step);
|
||||||
// MAX_PATTERN_SIZE is used to avoid OOM situation.
|
// MAX_PATTERN_SIZE is used to avoid OOM situation.
|
||||||
@ -421,7 +512,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
} else {
|
} else {
|
||||||
scale = size / step;
|
scale = size / step;
|
||||||
}
|
}
|
||||||
return { scale, size, };
|
return { scale, size };
|
||||||
},
|
},
|
||||||
|
|
||||||
clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
|
clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
|
||||||
@ -434,9 +525,13 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setFillAndStrokeStyleToContext:
|
setFillAndStrokeStyleToContext: function setFillAndStrokeStyleToContext(
|
||||||
function setFillAndStrokeStyleToContext(graphics, paintType, color) {
|
graphics,
|
||||||
let context = graphics.ctx, current = graphics.current;
|
paintType,
|
||||||
|
color
|
||||||
|
) {
|
||||||
|
let context = graphics.ctx,
|
||||||
|
current = graphics.current;
|
||||||
switch (paintType) {
|
switch (paintType) {
|
||||||
case PaintType.COLORED:
|
case PaintType.COLORED:
|
||||||
var ctx = this.ctx;
|
var ctx = this.ctx;
|
||||||
@ -466,14 +561,11 @@ var TilingPattern = (function TilingPatternClosure() {
|
|||||||
|
|
||||||
var temporaryPatternCanvas = this.createPatternCanvas(owner);
|
var temporaryPatternCanvas = this.createPatternCanvas(owner);
|
||||||
|
|
||||||
return ctx.createPattern(temporaryPatternCanvas, 'repeat');
|
return ctx.createPattern(temporaryPatternCanvas, "repeat");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return TilingPattern;
|
return TilingPattern;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { getShadingPatternFromIR, TilingPattern };
|
||||||
getShadingPatternFromIR,
|
|
||||||
TilingPattern,
|
|
||||||
};
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AbortException, createPromiseCapability, Util } from '../shared/util';
|
import { AbortException, createPromiseCapability, Util } from "../shared/util";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text layer render parameters.
|
* Text layer render parameters.
|
||||||
@ -48,7 +48,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
|
|
||||||
function appendText(task, geom, styles) {
|
function appendText(task, geom, styles) {
|
||||||
// Initialize all used properties to keep the caches monomorphic.
|
// Initialize all used properties to keep the caches monomorphic.
|
||||||
var textDiv = document.createElement('span');
|
var textDiv = document.createElement("span");
|
||||||
var textDivProperties = {
|
var textDivProperties = {
|
||||||
angle: 0,
|
angle: 0,
|
||||||
canvasWidth: 0,
|
canvasWidth: 0,
|
||||||
@ -74,7 +74,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
if (style.vertical) {
|
if (style.vertical) {
|
||||||
angle += Math.PI / 2;
|
angle += Math.PI / 2;
|
||||||
}
|
}
|
||||||
var fontHeight = Math.sqrt((tx[2] * tx[2]) + (tx[3] * tx[3]));
|
var fontHeight = Math.sqrt(tx[2] * tx[2] + tx[3] * tx[3]);
|
||||||
var fontAscent = fontHeight;
|
var fontAscent = fontHeight;
|
||||||
if (style.ascent) {
|
if (style.ascent) {
|
||||||
fontAscent = style.ascent * fontAscent;
|
fontAscent = style.ascent * fontAscent;
|
||||||
@ -87,8 +87,8 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
left = tx[4];
|
left = tx[4];
|
||||||
top = tx[5] - fontAscent;
|
top = tx[5] - fontAscent;
|
||||||
} else {
|
} else {
|
||||||
left = tx[4] + (fontAscent * Math.sin(angle));
|
left = tx[4] + fontAscent * Math.sin(angle);
|
||||||
top = tx[5] - (fontAscent * Math.cos(angle));
|
top = tx[5] - fontAscent * Math.cos(angle);
|
||||||
}
|
}
|
||||||
// Setting the style properties individually, rather than all at once,
|
// Setting the style properties individually, rather than all at once,
|
||||||
// should be OK since the `textDiv` isn't appended to the document yet.
|
// should be OK since the `textDiv` isn't appended to the document yet.
|
||||||
@ -122,13 +122,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (task._enhanceTextSelection) {
|
if (task._enhanceTextSelection) {
|
||||||
var angleCos = 1, angleSin = 0;
|
var angleCos = 1,
|
||||||
|
angleSin = 0;
|
||||||
if (angle !== 0) {
|
if (angle !== 0) {
|
||||||
angleCos = Math.cos(angle);
|
angleCos = Math.cos(angle);
|
||||||
angleSin = Math.sin(angle);
|
angleSin = Math.sin(angle);
|
||||||
}
|
}
|
||||||
var divWidth = (style.vertical ? geom.height : geom.width) *
|
var divWidth =
|
||||||
task._viewport.scale;
|
(style.vertical ? geom.height : geom.width) * task._viewport.scale;
|
||||||
var divHeight = fontHeight;
|
var divHeight = fontHeight;
|
||||||
|
|
||||||
var m, b;
|
var m, b;
|
||||||
@ -195,8 +196,11 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
}
|
}
|
||||||
// Box is rotated -- trying to find padding so rotated div will not
|
// Box is rotated -- trying to find padding so rotated div will not
|
||||||
// exceed its expanded bounds.
|
// exceed its expanded bounds.
|
||||||
var e = expanded[i], b = bounds[i];
|
var e = expanded[i],
|
||||||
var m = b.m, c = m[0], s = m[1];
|
b = bounds[i];
|
||||||
|
var m = b.m,
|
||||||
|
c = m[0],
|
||||||
|
s = m[1];
|
||||||
// Finding intersections with expanded box.
|
// Finding intersections with expanded box.
|
||||||
var points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
|
var points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
|
||||||
var ts = new Float64Array(64);
|
var ts = new Float64Array(64);
|
||||||
@ -270,7 +274,8 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
// Rotating on 90 degrees and extending extended boxes. Reusing the bounds
|
// Rotating on 90 degrees and extending extended boxes. Reusing the bounds
|
||||||
// array and objects.
|
// array and objects.
|
||||||
boxes.map(function(box, i) {
|
boxes.map(function(box, i) {
|
||||||
var e = expanded[i], b = bounds[i];
|
var e = expanded[i],
|
||||||
|
b = bounds[i];
|
||||||
b.x1 = box.top;
|
b.x1 = box.top;
|
||||||
b.y1 = width - e.right;
|
b.y1 = width - e.right;
|
||||||
b.x2 = box.bottom;
|
b.x2 = box.bottom;
|
||||||
@ -305,11 +310,13 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
x1New: 0,
|
x1New: 0,
|
||||||
x2New: 0,
|
x2New: 0,
|
||||||
};
|
};
|
||||||
var horizon = [{
|
var horizon = [
|
||||||
|
{
|
||||||
start: -Infinity,
|
start: -Infinity,
|
||||||
end: Infinity,
|
end: Infinity,
|
||||||
boundary: fakeBoundary,
|
boundary: fakeBoundary,
|
||||||
}];
|
},
|
||||||
|
];
|
||||||
|
|
||||||
bounds.forEach(function(boundary) {
|
bounds.forEach(function(boundary) {
|
||||||
// Searching for the affected part of horizon.
|
// Searching for the affected part of horizon.
|
||||||
@ -324,7 +331,9 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var horizonPart, affectedBoundary;
|
var horizonPart, affectedBoundary;
|
||||||
var q, k, maxXNew = -Infinity;
|
var q,
|
||||||
|
k,
|
||||||
|
maxXNew = -Infinity;
|
||||||
for (q = i; q <= j; q++) {
|
for (q = i; q <= j; q++) {
|
||||||
horizonPart = horizon[q];
|
horizonPart = horizon[q];
|
||||||
affectedBoundary = horizonPart.boundary;
|
affectedBoundary = horizonPart.boundary;
|
||||||
@ -333,8 +342,10 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
// In the middle of the previous element, new x shall be at the
|
// In the middle of the previous element, new x shall be at the
|
||||||
// boundary start. Extending if further if the affected boundary
|
// boundary start. Extending if further if the affected boundary
|
||||||
// placed on top of the current one.
|
// placed on top of the current one.
|
||||||
xNew = affectedBoundary.index > boundary.index ?
|
xNew =
|
||||||
affectedBoundary.x1New : boundary.x1;
|
affectedBoundary.index > boundary.index
|
||||||
|
? affectedBoundary.x1New
|
||||||
|
: boundary.x1;
|
||||||
} else if (affectedBoundary.x2New === undefined) {
|
} else if (affectedBoundary.x2New === undefined) {
|
||||||
// We have some space in between, new x in middle will be a fair
|
// We have some space in between, new x in middle will be a fair
|
||||||
// choice.
|
// choice.
|
||||||
@ -373,13 +384,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fixing the horizon.
|
// Fixing the horizon.
|
||||||
var changedHorizon = [], lastBoundary = null;
|
var changedHorizon = [],
|
||||||
|
lastBoundary = null;
|
||||||
for (q = i; q <= j; q++) {
|
for (q = i; q <= j; q++) {
|
||||||
horizonPart = horizon[q];
|
horizonPart = horizon[q];
|
||||||
affectedBoundary = horizonPart.boundary;
|
affectedBoundary = horizonPart.boundary;
|
||||||
// Checking which boundary will be visible.
|
// Checking which boundary will be visible.
|
||||||
var useBoundary = affectedBoundary.x2 > boundary.x2 ?
|
var useBoundary =
|
||||||
affectedBoundary : boundary;
|
affectedBoundary.x2 > boundary.x2 ? affectedBoundary : boundary;
|
||||||
if (lastBoundary === useBoundary) {
|
if (lastBoundary === useBoundary) {
|
||||||
// Merging with previous.
|
// Merging with previous.
|
||||||
changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
|
changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
|
||||||
@ -419,12 +431,18 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var used = false;
|
var used = false;
|
||||||
for (k = i - 1; !used && k >= 0 &&
|
for (
|
||||||
horizon[k].start >= affectedBoundary.y1; k--) {
|
k = i - 1;
|
||||||
|
!used && k >= 0 && horizon[k].start >= affectedBoundary.y1;
|
||||||
|
k--
|
||||||
|
) {
|
||||||
used = horizon[k].boundary === affectedBoundary;
|
used = horizon[k].boundary === affectedBoundary;
|
||||||
}
|
}
|
||||||
for (k = j + 1; !used && k < horizon.length &&
|
for (
|
||||||
horizon[k].end <= affectedBoundary.y2; k++) {
|
k = j + 1;
|
||||||
|
!used && k < horizon.length && horizon[k].end <= affectedBoundary.y2;
|
||||||
|
k++
|
||||||
|
) {
|
||||||
used = horizon[k].boundary === affectedBoundary;
|
used = horizon[k].boundary === affectedBoundary;
|
||||||
}
|
}
|
||||||
for (k = 0; !used && k < changedHorizon.length; k++) {
|
for (k = 0; !used && k < changedHorizon.length; k++) {
|
||||||
@ -435,8 +453,10 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Array.prototype.splice.apply(horizon,
|
Array.prototype.splice.apply(
|
||||||
[i, j - i + 1].concat(changedHorizon));
|
horizon,
|
||||||
|
[i, j - i + 1].concat(changedHorizon)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Set new x2 for all unset boundaries.
|
// Set new x2 for all unset boundaries.
|
||||||
@ -458,9 +478,15 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
* @param {boolean} enhanceTextSelection
|
* @param {boolean} enhanceTextSelection
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function TextLayerRenderTask({ textContent, textContentStream, container,
|
function TextLayerRenderTask({
|
||||||
viewport, textDivs, textContentItemsStr,
|
textContent,
|
||||||
enhanceTextSelection, }) {
|
textContentStream,
|
||||||
|
container,
|
||||||
|
viewport,
|
||||||
|
textDivs,
|
||||||
|
textContentItemsStr,
|
||||||
|
enhanceTextSelection,
|
||||||
|
}) {
|
||||||
this._textContent = textContent;
|
this._textContent = textContent;
|
||||||
this._textContentStream = textContentStream;
|
this._textContentStream = textContentStream;
|
||||||
this._container = container;
|
this._container = container;
|
||||||
@ -468,8 +494,9 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
this._textDivs = textDivs || [];
|
this._textDivs = textDivs || [];
|
||||||
this._textContentItemsStr = textContentItemsStr || [];
|
this._textContentItemsStr = textContentItemsStr || [];
|
||||||
this._enhanceTextSelection = !!enhanceTextSelection;
|
this._enhanceTextSelection = !!enhanceTextSelection;
|
||||||
this._fontInspectorEnabled = !!(globalThis.FontInspector &&
|
this._fontInspectorEnabled = !!(
|
||||||
globalThis.FontInspector.enabled);
|
globalThis.FontInspector && globalThis.FontInspector.enabled
|
||||||
|
);
|
||||||
|
|
||||||
this._reader = null;
|
this._reader = null;
|
||||||
this._layoutTextLastFontSize = null;
|
this._layoutTextLastFontSize = null;
|
||||||
@ -483,7 +510,8 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
this._bounds = [];
|
this._bounds = [];
|
||||||
|
|
||||||
// Always clean-up the temporary canvas once rendering is no longer pending.
|
// Always clean-up the temporary canvas once rendering is no longer pending.
|
||||||
this._capability.promise.finally(() => {
|
this._capability.promise
|
||||||
|
.finally(() => {
|
||||||
if (this._layoutTextCtx) {
|
if (this._layoutTextCtx) {
|
||||||
// Zeroing the width and height cause Firefox to release graphics
|
// Zeroing the width and height cause Firefox to release graphics
|
||||||
// resources immediately, which can greatly reduce memory consumption.
|
// resources immediately, which can greatly reduce memory consumption.
|
||||||
@ -491,7 +519,10 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
this._layoutTextCtx.canvas.height = 0;
|
this._layoutTextCtx.canvas.height = 0;
|
||||||
this._layoutTextCtx = null;
|
this._layoutTextCtx = null;
|
||||||
}
|
}
|
||||||
}).catch(() => { /* Avoid "Uncaught promise" messages in the console. */ });
|
})
|
||||||
|
.catch(() => {
|
||||||
|
/* Avoid "Uncaught promise" messages in the console. */
|
||||||
|
});
|
||||||
}
|
}
|
||||||
TextLayerRenderTask.prototype = {
|
TextLayerRenderTask.prototype = {
|
||||||
get promise() {
|
get promise() {
|
||||||
@ -501,14 +532,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
cancel: function TextLayer_cancel() {
|
cancel: function TextLayer_cancel() {
|
||||||
this._canceled = true;
|
this._canceled = true;
|
||||||
if (this._reader) {
|
if (this._reader) {
|
||||||
this._reader.cancel(new AbortException('TextLayer task cancelled.'));
|
this._reader.cancel(new AbortException("TextLayer task cancelled."));
|
||||||
this._reader = null;
|
this._reader = null;
|
||||||
}
|
}
|
||||||
if (this._renderTimer !== null) {
|
if (this._renderTimer !== null) {
|
||||||
clearTimeout(this._renderTimer);
|
clearTimeout(this._renderTimer);
|
||||||
this._renderTimer = null;
|
this._renderTimer = null;
|
||||||
}
|
}
|
||||||
this._capability.reject(new Error('TextLayer task cancelled.'));
|
this._capability.reject(new Error("TextLayer task cancelled."));
|
||||||
},
|
},
|
||||||
|
|
||||||
_processItems(items, styleCache) {
|
_processItems(items, styleCache) {
|
||||||
@ -524,19 +555,21 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let transform = '';
|
let transform = "";
|
||||||
if (textDivProperties.canvasWidth !== 0) {
|
if (textDivProperties.canvasWidth !== 0) {
|
||||||
const { fontSize, fontFamily, } = textDiv.style;
|
const { fontSize, fontFamily } = textDiv.style;
|
||||||
|
|
||||||
// Only build font string and set to context if different from last.
|
// Only build font string and set to context if different from last.
|
||||||
if (fontSize !== this._layoutTextLastFontSize ||
|
if (
|
||||||
fontFamily !== this._layoutTextLastFontFamily) {
|
fontSize !== this._layoutTextLastFontSize ||
|
||||||
|
fontFamily !== this._layoutTextLastFontFamily
|
||||||
|
) {
|
||||||
this._layoutTextCtx.font = `${fontSize} ${fontFamily}`;
|
this._layoutTextCtx.font = `${fontSize} ${fontFamily}`;
|
||||||
this._layoutTextLastFontSize = fontSize;
|
this._layoutTextLastFontSize = fontSize;
|
||||||
this._layoutTextLastFontFamily = fontFamily;
|
this._layoutTextLastFontFamily = fontFamily;
|
||||||
}
|
}
|
||||||
// Only measure the width for multi-char text divs, see `appendText`.
|
// Only measure the width for multi-char text divs, see `appendText`.
|
||||||
const { width, } = this._layoutTextCtx.measureText(textDiv.textContent);
|
const { width } = this._layoutTextCtx.measureText(textDiv.textContent);
|
||||||
|
|
||||||
if (width > 0) {
|
if (width > 0) {
|
||||||
textDivProperties.scale = textDivProperties.canvasWidth / width;
|
textDivProperties.scale = textDivProperties.canvasWidth / width;
|
||||||
@ -561,12 +594,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
let styleCache = Object.create(null);
|
let styleCache = Object.create(null);
|
||||||
|
|
||||||
// The temporary canvas is used to measure text length in the DOM.
|
// The temporary canvas is used to measure text length in the DOM.
|
||||||
let canvas = document.createElement('canvas');
|
let canvas = document.createElement("canvas");
|
||||||
if (typeof PDFJSDev === 'undefined' ||
|
if (
|
||||||
PDFJSDev.test('FIREFOX || MOZCENTRAL || GENERIC')) {
|
typeof PDFJSDev === "undefined" ||
|
||||||
|
PDFJSDev.test("FIREFOX || MOZCENTRAL || GENERIC")
|
||||||
|
) {
|
||||||
canvas.mozOpaque = true;
|
canvas.mozOpaque = true;
|
||||||
}
|
}
|
||||||
this._layoutTextCtx = canvas.getContext('2d', { alpha: false, });
|
this._layoutTextCtx = canvas.getContext("2d", { alpha: false });
|
||||||
|
|
||||||
if (this._textContent) {
|
if (this._textContent) {
|
||||||
let textItems = this._textContent.items;
|
let textItems = this._textContent.items;
|
||||||
@ -575,7 +610,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
capability.resolve();
|
capability.resolve();
|
||||||
} else if (this._textContentStream) {
|
} else if (this._textContentStream) {
|
||||||
let pump = () => {
|
let pump = () => {
|
||||||
this._reader.read().then(({ value, done, }) => {
|
this._reader.read().then(({ value, done }) => {
|
||||||
if (done) {
|
if (done) {
|
||||||
capability.resolve();
|
capability.resolve();
|
||||||
return;
|
return;
|
||||||
@ -590,15 +625,19 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
this._reader = this._textContentStream.getReader();
|
this._reader = this._textContentStream.getReader();
|
||||||
pump();
|
pump();
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Neither "textContent" nor "textContentStream"' +
|
throw new Error(
|
||||||
' parameters specified.');
|
'Neither "textContent" nor "textContentStream"' +
|
||||||
|
" parameters specified."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
capability.promise.then(() => {
|
capability.promise.then(() => {
|
||||||
styleCache = null;
|
styleCache = null;
|
||||||
if (!timeout) { // Render right away
|
if (!timeout) {
|
||||||
|
// Render right away
|
||||||
render(this);
|
render(this);
|
||||||
} else { // Schedule
|
} else {
|
||||||
|
// Schedule
|
||||||
this._renderTimer = setTimeout(() => {
|
this._renderTimer = setTimeout(() => {
|
||||||
render(this);
|
render(this);
|
||||||
this._renderTimer = null;
|
this._renderTimer = null;
|
||||||
@ -615,8 +654,9 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
expand(this);
|
expand(this);
|
||||||
this._bounds = null;
|
this._bounds = null;
|
||||||
}
|
}
|
||||||
const NO_PADDING = '0 0 0 0';
|
const NO_PADDING = "0 0 0 0";
|
||||||
const transformBuf = [], paddingBuf = [];
|
const transformBuf = [],
|
||||||
|
paddingBuf = [];
|
||||||
|
|
||||||
for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
|
for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
|
||||||
const div = this._textDivs[i];
|
const div = this._textDivs[i];
|
||||||
@ -651,17 +691,18 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
if (divProps.paddingLeft > 0) {
|
if (divProps.paddingLeft > 0) {
|
||||||
paddingBuf.push(`${divProps.paddingLeft / divProps.scale}px`);
|
paddingBuf.push(`${divProps.paddingLeft / divProps.scale}px`);
|
||||||
transformBuf.push(
|
transformBuf.push(
|
||||||
`translateX(${-divProps.paddingLeft / divProps.scale}px)`);
|
`translateX(${-divProps.paddingLeft / divProps.scale}px)`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
paddingBuf.push(0);
|
paddingBuf.push(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const padding = paddingBuf.join(' ');
|
const padding = paddingBuf.join(" ");
|
||||||
if (padding !== NO_PADDING) {
|
if (padding !== NO_PADDING) {
|
||||||
div.style.padding = padding;
|
div.style.padding = padding;
|
||||||
}
|
}
|
||||||
if (transformBuf.length) {
|
if (transformBuf.length) {
|
||||||
div.style.transform = transformBuf.join(' ');
|
div.style.transform = transformBuf.join(" ");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
div.style.padding = null;
|
div.style.padding = null;
|
||||||
@ -694,6 +735,4 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
|||||||
return renderTextLayer;
|
return renderTextLayer;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { renderTextLayer };
|
||||||
renderTextLayer,
|
|
||||||
};
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint no-var: error */
|
/* eslint no-var: error */
|
||||||
|
|
||||||
import { assert, createPromiseCapability } from '../shared/util';
|
import { assert, createPromiseCapability } from "../shared/util";
|
||||||
|
|
||||||
/** @implements {IPDFStream} */
|
/** @implements {IPDFStream} */
|
||||||
class PDFDataTransportStream {
|
class PDFDataTransportStream {
|
||||||
@ -39,15 +39,15 @@ class PDFDataTransportStream {
|
|||||||
this._rangeReaders = [];
|
this._rangeReaders = [];
|
||||||
|
|
||||||
this._pdfDataRangeTransport.addRangeListener((begin, chunk) => {
|
this._pdfDataRangeTransport.addRangeListener((begin, chunk) => {
|
||||||
this._onReceiveData({ begin, chunk, });
|
this._onReceiveData({ begin, chunk });
|
||||||
});
|
});
|
||||||
|
|
||||||
this._pdfDataRangeTransport.addProgressListener((loaded, total) => {
|
this._pdfDataRangeTransport.addProgressListener((loaded, total) => {
|
||||||
this._onProgress({ loaded, total, });
|
this._onProgress({ loaded, total });
|
||||||
});
|
});
|
||||||
|
|
||||||
this._pdfDataRangeTransport.addProgressiveReadListener((chunk) => {
|
this._pdfDataRangeTransport.addProgressiveReadListener(chunk => {
|
||||||
this._onReceiveData({ chunk, });
|
this._onReceiveData({ chunk });
|
||||||
});
|
});
|
||||||
|
|
||||||
this._pdfDataRangeTransport.addProgressiveDoneListener(() => {
|
this._pdfDataRangeTransport.addProgressiveDoneListener(() => {
|
||||||
@ -78,7 +78,7 @@ class PDFDataTransportStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get _progressiveDataLength() {
|
get _progressiveDataLength() {
|
||||||
return (this._fullRequestReader ? this._fullRequestReader._loaded : 0);
|
return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_onProgress(evt) {
|
_onProgress(evt) {
|
||||||
@ -86,12 +86,12 @@ class PDFDataTransportStream {
|
|||||||
// Reporting to first range reader, if it exists.
|
// Reporting to first range reader, if it exists.
|
||||||
const firstReader = this._rangeReaders[0];
|
const firstReader = this._rangeReaders[0];
|
||||||
if (firstReader && firstReader.onProgress) {
|
if (firstReader && firstReader.onProgress) {
|
||||||
firstReader.onProgress({ loaded: evt.loaded, });
|
firstReader.onProgress({ loaded: evt.loaded });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const fullReader = this._fullRequestReader;
|
const fullReader = this._fullRequestReader;
|
||||||
if (fullReader && fullReader.onProgress) {
|
if (fullReader && fullReader.onProgress) {
|
||||||
fullReader.onProgress({ loaded: evt.loaded, total: evt.total, });
|
fullReader.onProgress({ loaded: evt.loaded, total: evt.total });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -114,8 +114,11 @@ class PDFDataTransportStream {
|
|||||||
assert(!this._fullRequestReader);
|
assert(!this._fullRequestReader);
|
||||||
const queuedChunks = this._queuedChunks;
|
const queuedChunks = this._queuedChunks;
|
||||||
this._queuedChunks = null;
|
this._queuedChunks = null;
|
||||||
return new PDFDataTransportStreamReader(this, queuedChunks,
|
return new PDFDataTransportStreamReader(
|
||||||
this._progressiveDone);
|
this,
|
||||||
|
queuedChunks,
|
||||||
|
this._progressiveDone
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRangeReader(begin, end) {
|
getRangeReader(begin, end) {
|
||||||
@ -164,7 +167,7 @@ class PDFDataTransportStreamReader {
|
|||||||
}
|
}
|
||||||
if (this._requests.length > 0) {
|
if (this._requests.length > 0) {
|
||||||
const requestCapability = this._requests.shift();
|
const requestCapability = this._requests.shift();
|
||||||
requestCapability.resolve({ value: chunk, done: false, });
|
requestCapability.resolve({ value: chunk, done: false });
|
||||||
} else {
|
} else {
|
||||||
this._queuedChunks.push(chunk);
|
this._queuedChunks.push(chunk);
|
||||||
}
|
}
|
||||||
@ -194,10 +197,10 @@ class PDFDataTransportStreamReader {
|
|||||||
async read() {
|
async read() {
|
||||||
if (this._queuedChunks.length > 0) {
|
if (this._queuedChunks.length > 0) {
|
||||||
const chunk = this._queuedChunks.shift();
|
const chunk = this._queuedChunks.shift();
|
||||||
return { value: chunk, done: false, };
|
return { value: chunk, done: false };
|
||||||
}
|
}
|
||||||
if (this._done) {
|
if (this._done) {
|
||||||
return { value: undefined, done: true, };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
const requestCapability = createPromiseCapability();
|
const requestCapability = createPromiseCapability();
|
||||||
this._requests.push(requestCapability);
|
this._requests.push(requestCapability);
|
||||||
@ -207,7 +210,7 @@ class PDFDataTransportStreamReader {
|
|||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this._requests.forEach(function(requestCapability) {
|
this._requests.forEach(function(requestCapability) {
|
||||||
requestCapability.resolve({ value: undefined, done: true, });
|
requestCapability.resolve({ value: undefined, done: true });
|
||||||
});
|
});
|
||||||
this._requests = [];
|
this._requests = [];
|
||||||
}
|
}
|
||||||
@ -241,9 +244,9 @@ class PDFDataTransportStreamRangeReader {
|
|||||||
this._queuedChunk = chunk;
|
this._queuedChunk = chunk;
|
||||||
} else {
|
} else {
|
||||||
const requestsCapability = this._requests.shift();
|
const requestsCapability = this._requests.shift();
|
||||||
requestsCapability.resolve({ value: chunk, done: false, });
|
requestsCapability.resolve({ value: chunk, done: false });
|
||||||
this._requests.forEach(function(requestCapability) {
|
this._requests.forEach(function(requestCapability) {
|
||||||
requestCapability.resolve({ value: undefined, done: true, });
|
requestCapability.resolve({ value: undefined, done: true });
|
||||||
});
|
});
|
||||||
this._requests = [];
|
this._requests = [];
|
||||||
}
|
}
|
||||||
@ -259,10 +262,10 @@ class PDFDataTransportStreamRangeReader {
|
|||||||
if (this._queuedChunk) {
|
if (this._queuedChunk) {
|
||||||
const chunk = this._queuedChunk;
|
const chunk = this._queuedChunk;
|
||||||
this._queuedChunk = null;
|
this._queuedChunk = null;
|
||||||
return { value: chunk, done: false, };
|
return { value: chunk, done: false };
|
||||||
}
|
}
|
||||||
if (this._done) {
|
if (this._done) {
|
||||||
return { value: undefined, done: true, };
|
return { value: undefined, done: true };
|
||||||
}
|
}
|
||||||
const requestCapability = createPromiseCapability();
|
const requestCapability = createPromiseCapability();
|
||||||
this._requests.push(requestCapability);
|
this._requests.push(requestCapability);
|
||||||
@ -272,13 +275,11 @@ class PDFDataTransportStreamRangeReader {
|
|||||||
cancel(reason) {
|
cancel(reason) {
|
||||||
this._done = true;
|
this._done = true;
|
||||||
this._requests.forEach(function(requestCapability) {
|
this._requests.forEach(function(requestCapability) {
|
||||||
requestCapability.resolve({ value: undefined, done: true, });
|
requestCapability.resolve({ value: undefined, done: true });
|
||||||
});
|
});
|
||||||
this._requests = [];
|
this._requests = [];
|
||||||
this._stream._removeRangeReader(this);
|
this._stream._removeRangeReader(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { PDFDataTransportStream };
|
||||||
PDFDataTransportStream,
|
|
||||||
};
|
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
*/
|
*/
|
||||||
/* eslint-disable no-multi-str */
|
/* eslint-disable no-multi-str */
|
||||||
|
|
||||||
import { shadow } from '../shared/util';
|
import { shadow } from "../shared/util";
|
||||||
|
|
||||||
class WebGLContext {
|
class WebGLContext {
|
||||||
constructor({ enable = false, }) {
|
constructor({ enable = false }) {
|
||||||
this._enabled = enable === true;
|
this._enabled = enable === true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,16 +26,21 @@ class WebGLContext {
|
|||||||
if (enabled) {
|
if (enabled) {
|
||||||
enabled = WebGLUtils.tryInitGL();
|
enabled = WebGLUtils.tryInitGL();
|
||||||
}
|
}
|
||||||
return shadow(this, 'isEnabled', enabled);
|
return shadow(this, "isEnabled", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
composeSMask({ layer, mask, properties, }) {
|
composeSMask({ layer, mask, properties }) {
|
||||||
return WebGLUtils.composeSMask(layer, mask, properties);
|
return WebGLUtils.composeSMask(layer, mask, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
drawFigures({ width, height, backgroundColor, figures, context, }) {
|
drawFigures({ width, height, backgroundColor, figures, context }) {
|
||||||
return WebGLUtils.drawFigures(width, height, backgroundColor, figures,
|
return WebGLUtils.drawFigures(
|
||||||
context);
|
width,
|
||||||
|
height,
|
||||||
|
backgroundColor,
|
||||||
|
figures,
|
||||||
|
context
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
@ -51,7 +56,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
||||||
if (!compiled) {
|
if (!compiled) {
|
||||||
var errorMsg = gl.getShaderInfoLog(shader);
|
var errorMsg = gl.getShaderInfoLog(shader);
|
||||||
throw new Error('Error during shader compilation: ' + errorMsg);
|
throw new Error("Error during shader compilation: " + errorMsg);
|
||||||
}
|
}
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
@ -70,7 +75,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
||||||
if (!linked) {
|
if (!linked) {
|
||||||
var errorMsg = gl.getProgramInfoLog(program);
|
var errorMsg = gl.getProgramInfoLog(program);
|
||||||
throw new Error('Error during program linking: ' + errorMsg);
|
throw new Error("Error during program linking: " + errorMsg);
|
||||||
}
|
}
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
@ -97,12 +102,14 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The temporary canvas is used in the WebGL context.
|
// The temporary canvas is used in the WebGL context.
|
||||||
currentCanvas = document.createElement('canvas');
|
currentCanvas = document.createElement("canvas");
|
||||||
currentGL = currentCanvas.getContext('webgl',
|
currentGL = currentCanvas.getContext("webgl", {
|
||||||
{ premultipliedalpha: false, });
|
premultipliedalpha: false,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var smaskVertexShaderCode = '\
|
var smaskVertexShaderCode =
|
||||||
|
"\
|
||||||
attribute vec2 a_position; \
|
attribute vec2 a_position; \
|
||||||
attribute vec2 a_texCoord; \
|
attribute vec2 a_texCoord; \
|
||||||
\
|
\
|
||||||
@ -115,9 +122,10 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
|
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
|
||||||
\
|
\
|
||||||
v_texCoord = a_texCoord; \
|
v_texCoord = a_texCoord; \
|
||||||
} ';
|
} ";
|
||||||
|
|
||||||
var smaskFragmentShaderCode = '\
|
var smaskFragmentShaderCode =
|
||||||
|
"\
|
||||||
precision mediump float; \
|
precision mediump float; \
|
||||||
\
|
\
|
||||||
uniform vec4 u_backdrop; \
|
uniform vec4 u_backdrop; \
|
||||||
@ -144,7 +152,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
imageColor.a *= lum; \
|
imageColor.a *= lum; \
|
||||||
imageColor.rgb *= imageColor.a; \
|
imageColor.rgb *= imageColor.a; \
|
||||||
gl_FragColor = imageColor; \
|
gl_FragColor = imageColor; \
|
||||||
} ';
|
} ";
|
||||||
|
|
||||||
var smaskCache = null;
|
var smaskCache = null;
|
||||||
|
|
||||||
@ -166,14 +174,14 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
var cache = {};
|
var cache = {};
|
||||||
cache.gl = gl;
|
cache.gl = gl;
|
||||||
cache.canvas = canvas;
|
cache.canvas = canvas;
|
||||||
cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
|
cache.resolutionLocation = gl.getUniformLocation(program, "u_resolution");
|
||||||
cache.positionLocation = gl.getAttribLocation(program, 'a_position');
|
cache.positionLocation = gl.getAttribLocation(program, "a_position");
|
||||||
cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop');
|
cache.backdropLocation = gl.getUniformLocation(program, "u_backdrop");
|
||||||
cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype');
|
cache.subtypeLocation = gl.getUniformLocation(program, "u_subtype");
|
||||||
|
|
||||||
var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
|
var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");
|
||||||
var texLayerLocation = gl.getUniformLocation(program, 'u_image');
|
var texLayerLocation = gl.getUniformLocation(program, "u_image");
|
||||||
var texMaskLocation = gl.getUniformLocation(program, 'u_mask');
|
var texMaskLocation = gl.getUniformLocation(program, "u_mask");
|
||||||
|
|
||||||
// provide texture coordinates for the rectangle.
|
// provide texture coordinates for the rectangle.
|
||||||
var texCoordBuffer = gl.createBuffer();
|
var texCoordBuffer = gl.createBuffer();
|
||||||
@ -196,25 +204,35 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function composeSMask(layer, mask, properties) {
|
function composeSMask(layer, mask, properties) {
|
||||||
var width = layer.width, height = layer.height;
|
var width = layer.width,
|
||||||
|
height = layer.height;
|
||||||
|
|
||||||
if (!smaskCache) {
|
if (!smaskCache) {
|
||||||
initSmaskGL();
|
initSmaskGL();
|
||||||
}
|
}
|
||||||
var cache = smaskCache, canvas = cache.canvas, gl = cache.gl;
|
var cache = smaskCache,
|
||||||
|
canvas = cache.canvas,
|
||||||
|
gl = cache.gl;
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
||||||
gl.uniform2f(cache.resolutionLocation, width, height);
|
gl.uniform2f(cache.resolutionLocation, width, height);
|
||||||
|
|
||||||
if (properties.backdrop) {
|
if (properties.backdrop) {
|
||||||
gl.uniform4f(cache.resolutionLocation, properties.backdrop[0],
|
gl.uniform4f(
|
||||||
properties.backdrop[1], properties.backdrop[2], 1);
|
cache.resolutionLocation,
|
||||||
|
properties.backdrop[0],
|
||||||
|
properties.backdrop[1],
|
||||||
|
properties.backdrop[2],
|
||||||
|
1
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0);
|
gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
gl.uniform1i(cache.subtypeLocation,
|
gl.uniform1i(
|
||||||
properties.subtype === 'Luminosity' ? 1 : 0);
|
cache.subtypeLocation,
|
||||||
|
properties.subtype === "Luminosity" ? 1 : 0
|
||||||
|
);
|
||||||
|
|
||||||
// Create a textures
|
// Create a textures
|
||||||
var texture = createTexture(gl, layer, gl.TEXTURE0);
|
var texture = createTexture(gl, layer, gl.TEXTURE0);
|
||||||
@ -252,7 +270,8 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
return canvas;
|
return canvas;
|
||||||
}
|
}
|
||||||
|
|
||||||
var figuresVertexShaderCode = '\
|
var figuresVertexShaderCode =
|
||||||
|
"\
|
||||||
attribute vec2 a_position; \
|
attribute vec2 a_position; \
|
||||||
attribute vec3 a_color; \
|
attribute vec3 a_color; \
|
||||||
\
|
\
|
||||||
@ -268,16 +287,17 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
|
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
|
||||||
\
|
\
|
||||||
v_color = vec4(a_color / 255.0, 1.0); \
|
v_color = vec4(a_color / 255.0, 1.0); \
|
||||||
} ';
|
} ";
|
||||||
|
|
||||||
var figuresFragmentShaderCode = '\
|
var figuresFragmentShaderCode =
|
||||||
|
"\
|
||||||
precision mediump float; \
|
precision mediump float; \
|
||||||
\
|
\
|
||||||
varying vec4 v_color; \
|
varying vec4 v_color; \
|
||||||
\
|
\
|
||||||
void main() { \
|
void main() { \
|
||||||
gl_FragColor = v_color; \
|
gl_FragColor = v_color; \
|
||||||
} ';
|
} ";
|
||||||
|
|
||||||
var figuresCache = null;
|
var figuresCache = null;
|
||||||
|
|
||||||
@ -299,11 +319,11 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
var cache = {};
|
var cache = {};
|
||||||
cache.gl = gl;
|
cache.gl = gl;
|
||||||
cache.canvas = canvas;
|
cache.canvas = canvas;
|
||||||
cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
|
cache.resolutionLocation = gl.getUniformLocation(program, "u_resolution");
|
||||||
cache.scaleLocation = gl.getUniformLocation(program, 'u_scale');
|
cache.scaleLocation = gl.getUniformLocation(program, "u_scale");
|
||||||
cache.offsetLocation = gl.getUniformLocation(program, 'u_offset');
|
cache.offsetLocation = gl.getUniformLocation(program, "u_offset");
|
||||||
cache.positionLocation = gl.getAttribLocation(program, 'a_position');
|
cache.positionLocation = gl.getAttribLocation(program, "a_position");
|
||||||
cache.colorLocation = gl.getAttribLocation(program, 'a_color');
|
cache.colorLocation = gl.getAttribLocation(program, "a_color");
|
||||||
|
|
||||||
figuresCache = cache;
|
figuresCache = cache;
|
||||||
}
|
}
|
||||||
@ -312,7 +332,9 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
if (!figuresCache) {
|
if (!figuresCache) {
|
||||||
initFiguresGL();
|
initFiguresGL();
|
||||||
}
|
}
|
||||||
var cache = figuresCache, canvas = cache.canvas, gl = cache.gl;
|
var cache = figuresCache,
|
||||||
|
canvas = cache.canvas,
|
||||||
|
gl = cache.gl;
|
||||||
|
|
||||||
canvas.width = width;
|
canvas.width = width;
|
||||||
canvas.height = height;
|
canvas.height = height;
|
||||||
@ -324,11 +346,11 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
var i, ii, rows;
|
var i, ii, rows;
|
||||||
for (i = 0, ii = figures.length; i < ii; i++) {
|
for (i = 0, ii = figures.length; i < ii; i++) {
|
||||||
switch (figures[i].type) {
|
switch (figures[i].type) {
|
||||||
case 'lattice':
|
case "lattice":
|
||||||
rows = (figures[i].coords.length / figures[i].verticesPerRow) | 0;
|
rows = (figures[i].coords.length / figures[i].verticesPerRow) | 0;
|
||||||
count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6;
|
count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6;
|
||||||
break;
|
break;
|
||||||
case 'triangles':
|
case "triangles":
|
||||||
count += figures[i].coords.length;
|
count += figures[i].coords.length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -336,12 +358,16 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
// transfer data
|
// transfer data
|
||||||
var coords = new Float32Array(count * 2);
|
var coords = new Float32Array(count * 2);
|
||||||
var colors = new Uint8Array(count * 3);
|
var colors = new Uint8Array(count * 3);
|
||||||
var coordsMap = context.coords, colorsMap = context.colors;
|
var coordsMap = context.coords,
|
||||||
var pIndex = 0, cIndex = 0;
|
colorsMap = context.colors;
|
||||||
|
var pIndex = 0,
|
||||||
|
cIndex = 0;
|
||||||
for (i = 0, ii = figures.length; i < ii; i++) {
|
for (i = 0, ii = figures.length; i < ii; i++) {
|
||||||
var figure = figures[i], ps = figure.coords, cs = figure.colors;
|
var figure = figures[i],
|
||||||
|
ps = figure.coords,
|
||||||
|
cs = figure.colors;
|
||||||
switch (figure.type) {
|
switch (figure.type) {
|
||||||
case 'lattice':
|
case "lattice":
|
||||||
var cols = figure.verticesPerRow;
|
var cols = figure.verticesPerRow;
|
||||||
rows = (ps.length / cols) | 0;
|
rows = (ps.length / cols) | 0;
|
||||||
for (var row = 1; row < rows; row++) {
|
for (var row = 1; row < rows; row++) {
|
||||||
@ -383,7 +409,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'triangles':
|
case "triangles":
|
||||||
for (var j = 0, jj = ps.length; j < jj; j++) {
|
for (var j = 0, jj = ps.length; j < jj; j++) {
|
||||||
coords[pIndex] = coordsMap[ps[j]];
|
coords[pIndex] = coordsMap[ps[j]];
|
||||||
coords[pIndex + 1] = coordsMap[ps[j] + 1];
|
coords[pIndex + 1] = coordsMap[ps[j] + 1];
|
||||||
@ -399,8 +425,12 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
|
|
||||||
// draw
|
// draw
|
||||||
if (backgroundColor) {
|
if (backgroundColor) {
|
||||||
gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255,
|
gl.clearColor(
|
||||||
backgroundColor[2] / 255, 1.0);
|
backgroundColor[0] / 255,
|
||||||
|
backgroundColor[1] / 255,
|
||||||
|
backgroundColor[2] / 255,
|
||||||
|
1.0
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
gl.clearColor(0, 0, 0, 0);
|
gl.clearColor(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@ -416,8 +446,14 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
|
gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
|
||||||
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
|
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
|
||||||
gl.enableVertexAttribArray(cache.colorLocation);
|
gl.enableVertexAttribArray(cache.colorLocation);
|
||||||
gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false,
|
gl.vertexAttribPointer(
|
||||||
0, 0);
|
cache.colorLocation,
|
||||||
|
3,
|
||||||
|
gl.UNSIGNED_BYTE,
|
||||||
|
false,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
|
||||||
gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY);
|
gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY);
|
||||||
gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY);
|
gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY);
|
||||||
@ -460,6 +496,4 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
|||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export {
|
export { WebGLContext };
|
||||||
WebGLContext,
|
|
||||||
};
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user