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",
|
||||
],
|
||||
|
||||
"extends": [
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
@ -47,7 +51,6 @@
|
||||
"no-empty": ["error", { "allowEmptyCatch": true, }],
|
||||
"no-ex-assign": "error",
|
||||
"no-extra-boolean-cast": "error",
|
||||
"no-extra-semi": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-inner-declarations": ["error", "functions"],
|
||||
"no-invalid-regexp": "error",
|
||||
@ -84,9 +87,6 @@
|
||||
"no-implied-eval": "error",
|
||||
"no-iterator": "error",
|
||||
"no-lone-blocks": "error",
|
||||
"no-multi-spaces": ["error", {
|
||||
"ignoreEOLComments": true,
|
||||
}],
|
||||
"no-multi-str": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
@ -127,48 +127,16 @@
|
||||
}],
|
||||
|
||||
// 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"],
|
||||
"max-len": ["error", {
|
||||
"code": 80,
|
||||
"code": 1000,
|
||||
"comments": 80,
|
||||
"ignoreUrls": true
|
||||
}],
|
||||
"new-cap": ["error", { "newIsCap": true, "capIsNew": false, }],
|
||||
"new-parens": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0, "maxBOF": 1, }],
|
||||
"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", {
|
||||
"block": {
|
||||
"balanced": true,
|
||||
@ -176,12 +144,6 @@
|
||||
}],
|
||||
|
||||
// ECMAScript 6
|
||||
"arrow-body-style": ["error", "always"],
|
||||
"arrow-parens": ["error", "always"],
|
||||
"arrow-spacing": ["error", {
|
||||
"before": true,
|
||||
"after": true,
|
||||
}],
|
||||
"constructor-super": "error",
|
||||
"no-class-assign": "error",
|
||||
"no-confusing-arrow": "error",
|
||||
@ -197,7 +159,6 @@
|
||||
"avoidQuotes": true,
|
||||
}],
|
||||
"prefer-const": "off",
|
||||
"rest-spread-spacing": ["error", "never"],
|
||||
"sort-imports": ["error", {
|
||||
"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.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
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 container = document.getElementById('pageContainer');
|
||||
var container = document.getElementById("pageContainer");
|
||||
|
||||
// Fetch the PDF document from the URL using promises.
|
||||
var loadingTask = pdfjsLib.getDocument(DEFAULT_URL);
|
||||
@ -30,16 +30,16 @@ loadingTask.promise.then(function(doc) {
|
||||
var promise = Promise.resolve();
|
||||
|
||||
for (var i = 1; i <= doc.numPages; i++) {
|
||||
promise = promise.then(function (pageNum) {
|
||||
return doc.getPage(pageNum).then(function (pdfPage) {
|
||||
promise = promise.then(
|
||||
function(pageNum) {
|
||||
return doc.getPage(pageNum).then(function(pdfPage) {
|
||||
// Create the page view.
|
||||
var pdfPageView = new pdfjsViewer.PDFPageView({
|
||||
container: container,
|
||||
id: pageNum,
|
||||
scale: DEFAULT_SCALE,
|
||||
defaultViewport: pdfPage.getViewport({ scale: DEFAULT_SCALE, }),
|
||||
annotationLayerFactory:
|
||||
new pdfjsViewer.DefaultAnnotationLayerFactory(),
|
||||
defaultViewport: pdfPage.getViewport({ scale: DEFAULT_SCALE }),
|
||||
annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory(),
|
||||
renderInteractiveForms: true,
|
||||
});
|
||||
|
||||
@ -47,6 +47,7 @@ loadingTask.promise.then(function(doc) {
|
||||
pdfPageView.setPdfPage(pdfPage);
|
||||
return pdfPageView.draw();
|
||||
});
|
||||
}.bind(null, i));
|
||||
}.bind(null, i)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -1,36 +1,40 @@
|
||||
var gulp = require('gulp');
|
||||
var browserify = require('browserify');
|
||||
var streamify = require('gulp-streamify');
|
||||
var rename = require('gulp-rename');
|
||||
var uglify = require('gulp-uglify');
|
||||
var source = require('vinyl-source-stream');
|
||||
var gulp = require("gulp");
|
||||
var browserify = require("browserify");
|
||||
var streamify = require("gulp-streamify");
|
||||
var rename = require("gulp-rename");
|
||||
var uglify = require("gulp-uglify");
|
||||
var source = require("vinyl-source-stream");
|
||||
|
||||
var OUTPUT_PATH = '../../build/browserify';
|
||||
var TMP_FILE_PREFIX = '../../build/browserify_';
|
||||
var OUTPUT_PATH = "../../build/browserify";
|
||||
var TMP_FILE_PREFIX = "../../build/browserify_";
|
||||
|
||||
gulp.task('build-bundle', function() {
|
||||
return browserify('main.js', { output: TMP_FILE_PREFIX + 'main.tmp', })
|
||||
.ignore(require.resolve('pdfjs-dist/build/pdf.worker')) // Reducing size
|
||||
gulp.task("build-bundle", function() {
|
||||
return browserify("main.js", { output: TMP_FILE_PREFIX + "main.tmp" })
|
||||
.ignore(require.resolve("pdfjs-dist/build/pdf.worker")) // Reducing size
|
||||
.bundle()
|
||||
.pipe(source(TMP_FILE_PREFIX + 'main.tmp'))
|
||||
.pipe(source(TMP_FILE_PREFIX + "main.tmp"))
|
||||
.pipe(streamify(uglify()))
|
||||
.pipe(rename('main.bundle.js'))
|
||||
.pipe(rename("main.bundle.js"))
|
||||
.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.
|
||||
var workerSrc = require.resolve('pdfjs-dist/build/pdf.worker.entry');
|
||||
return browserify(workerSrc, { output: TMP_FILE_PREFIX + 'worker.tmp', })
|
||||
var workerSrc = require.resolve("pdfjs-dist/build/pdf.worker.entry");
|
||||
return browserify(workerSrc, { output: TMP_FILE_PREFIX + "worker.tmp" })
|
||||
.bundle()
|
||||
.pipe(source(TMP_FILE_PREFIX + 'worker.tmp'))
|
||||
.pipe(streamify(uglify({
|
||||
.pipe(source(TMP_FILE_PREFIX + "worker.tmp"))
|
||||
.pipe(
|
||||
streamify(
|
||||
uglify({
|
||||
compress: {
|
||||
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));
|
||||
});
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||
'../../build/browserify/pdf.worker.bundle.js';
|
||||
"../../build/browserify/pdf.worker.bundle.js";
|
||||
|
||||
// Loading a document.
|
||||
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
||||
loadingTask.promise.then(function (pdfDocument) {
|
||||
loadingTask.promise
|
||||
.then(function(pdfDocument) {
|
||||
// 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.
|
||||
var viewport = pdfPage.getViewport({ scale: 1.0, });
|
||||
var canvas = document.getElementById('theCanvas');
|
||||
var viewport = pdfPage.getViewport({ scale: 1.0 });
|
||||
var canvas = document.getElementById("theCanvas");
|
||||
canvas.width = viewport.width;
|
||||
canvas.height = viewport.height;
|
||||
var ctx = canvas.getContext('2d');
|
||||
var ctx = canvas.getContext("2d");
|
||||
var renderTask = pdfPage.render({
|
||||
canvasContext: ctx,
|
||||
viewport: viewport,
|
||||
});
|
||||
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.
|
||||
|
||||
(typeof window !== 'undefined' ? window : {}).pdfjsWorker =
|
||||
require('pdfjs-dist/build/pdf.worker');
|
||||
(typeof window !== "undefined"
|
||||
? window
|
||||
: {}
|
||||
).pdfjsWorker = require("pdfjs-dist/build/pdf.worker");
|
||||
|
@ -13,28 +13,29 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFPageView) {
|
||||
alert('Please build the pdfjs-dist library using\n' +
|
||||
' `gulp dist-install`');
|
||||
alert(
|
||||
"Please build the pdfjs-dist library using\n" + " `gulp dist-install`"
|
||||
);
|
||||
}
|
||||
|
||||
// The workerSrc property shall be specified.
|
||||
//
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
||||
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||
|
||||
// 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 DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
||||
var DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||
var PAGE_TO_VIEW = 1;
|
||||
var SCALE = 1.0;
|
||||
|
||||
var container = document.getElementById('pageContainer');
|
||||
var container = document.getElementById("pageContainer");
|
||||
|
||||
// Loading document.
|
||||
var loadingTask = pdfjsLib.getDocument({
|
||||
@ -44,13 +45,13 @@ var loadingTask = pdfjsLib.getDocument({
|
||||
});
|
||||
loadingTask.promise.then(function(pdfDocument) {
|
||||
// Document loaded, retrieving the page.
|
||||
return pdfDocument.getPage(PAGE_TO_VIEW).then(function (pdfPage) {
|
||||
return pdfDocument.getPage(PAGE_TO_VIEW).then(function(pdfPage) {
|
||||
// Creating the page view with default parameters.
|
||||
var pdfPageView = new pdfjsViewer.PDFPageView({
|
||||
container: container,
|
||||
id: PAGE_TO_VIEW,
|
||||
scale: SCALE,
|
||||
defaultViewport: pdfPage.getViewport({ scale: SCALE, }),
|
||||
defaultViewport: pdfPage.getViewport({ scale: SCALE }),
|
||||
// We can enable text/annotations layers, if needed
|
||||
textLayerFactory: new pdfjsViewer.DefaultTextLayerFactory(),
|
||||
annotationLayerFactory: new pdfjsViewer.DefaultAnnotationLayerFactory(),
|
||||
|
@ -13,27 +13,28 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
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`"
|
||||
);
|
||||
}
|
||||
|
||||
// The workerSrc property shall be specified.
|
||||
//
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
||||
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||
|
||||
// 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 DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
||||
var SEARCH_FOR = ''; // try 'Mozilla';
|
||||
var DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||
var SEARCH_FOR = ""; // try 'Mozilla';
|
||||
|
||||
var container = document.getElementById('viewerContainer');
|
||||
var container = document.getElementById("viewerContainer");
|
||||
|
||||
// (Optionally) enable hyperlinks within PDF files.
|
||||
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||
@ -50,12 +51,13 @@ var pdfViewer = new pdfjsViewer.PDFViewer({
|
||||
});
|
||||
pdfLinkService.setViewer(pdfViewer);
|
||||
|
||||
document.addEventListener('pagesinit', function () {
|
||||
document.addEventListener("pagesinit", function() {
|
||||
// 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
|
||||
pdfFindController.executeCommand('find', { query: SEARCH_FOR, });
|
||||
if (SEARCH_FOR) {
|
||||
// We can try search for things
|
||||
pdfFindController.executeCommand("find", { query: SEARCH_FOR });
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -13,27 +13,28 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
if (!pdfjsLib.getDocument || !pdfjsViewer.PDFSinglePageViewer) {
|
||||
alert('Please build the pdfjs-dist library using\n' +
|
||||
' `gulp dist-install`');
|
||||
alert(
|
||||
"Please build the pdfjs-dist library using\n" + " `gulp dist-install`"
|
||||
);
|
||||
}
|
||||
|
||||
// The workerSrc property shall be specified.
|
||||
//
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
||||
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||
|
||||
// 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 DEFAULT_URL = '../../web/compressed.tracemonkey-pldi-09.pdf';
|
||||
var SEARCH_FOR = ''; // try 'Mozilla';
|
||||
var DEFAULT_URL = "../../web/compressed.tracemonkey-pldi-09.pdf";
|
||||
var SEARCH_FOR = ""; // try 'Mozilla';
|
||||
|
||||
var container = document.getElementById('viewerContainer');
|
||||
var container = document.getElementById("viewerContainer");
|
||||
|
||||
// (Optionally) enable hyperlinks within PDF files.
|
||||
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||
@ -50,12 +51,13 @@ var pdfSinglePageViewer = new pdfjsViewer.PDFSinglePageViewer({
|
||||
});
|
||||
pdfLinkService.setViewer(pdfSinglePageViewer);
|
||||
|
||||
document.addEventListener('pagesinit', function () {
|
||||
document.addEventListener("pagesinit", function() {
|
||||
// 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
|
||||
pdfFindController.executeCommand('find', { query: SEARCH_FOR, });
|
||||
if (SEARCH_FOR) {
|
||||
// We can try search for things
|
||||
pdfFindController.executeCommand("find", { query: SEARCH_FOR });
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -13,39 +13,40 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
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 jpegCtx = jpegCanvas.getContext('2d');
|
||||
var jpegCanvas = document.getElementById("jpegCanvas");
|
||||
var jpegCtx = jpegCanvas.getContext("2d");
|
||||
|
||||
// Load the image data, and convert it to a Uint8Array.
|
||||
//
|
||||
var nonBinaryRequest = false;
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('GET', JPEG_IMAGE, false);
|
||||
request.open("GET", JPEG_IMAGE, false);
|
||||
try {
|
||||
request.responseType = 'arraybuffer';
|
||||
nonBinaryRequest = request.responseType !== 'arraybuffer';
|
||||
request.responseType = "arraybuffer";
|
||||
nonBinaryRequest = request.responseType !== "arraybuffer";
|
||||
} catch (e) {
|
||||
nonBinaryRequest = true;
|
||||
}
|
||||
if (nonBinaryRequest && request.overrideMimeType) {
|
||||
request.overrideMimeType('text/plain; charset=x-user-defined');
|
||||
request.overrideMimeType("text/plain; charset=x-user-defined");
|
||||
}
|
||||
request.send(null);
|
||||
|
||||
var typedArrayImage;
|
||||
if (nonBinaryRequest) {
|
||||
var str = request.responseText, length = str.length;
|
||||
var str = request.responseText,
|
||||
length = str.length;
|
||||
var bytes = new Uint8Array(length);
|
||||
for (var i = 0; i < length; ++i) {
|
||||
bytes[i] = str.charCodeAt(i) & 0xFF;
|
||||
bytes[i] = str.charCodeAt(i) & 0xff;
|
||||
}
|
||||
typedArrayImage = bytes;
|
||||
} else {
|
||||
@ -57,7 +58,8 @@ if (nonBinaryRequest) {
|
||||
var jpegImage = new pdfjsImageDecoders.JpegImage();
|
||||
jpegImage.parse(typedArrayImage);
|
||||
|
||||
var width = jpegImage.width, height = jpegImage.height;
|
||||
var width = jpegImage.width,
|
||||
height = jpegImage.height;
|
||||
var jpegData = jpegImage.getData({
|
||||
width: width,
|
||||
height: height,
|
||||
@ -68,7 +70,7 @@ var jpegData = jpegImage.getData({
|
||||
//
|
||||
var imageData = jpegCtx.createImageData(width, height);
|
||||
var imageBytes = imageData.data;
|
||||
for (var j = 0, k = 0, jj = width * height * 4; j < jj;) {
|
||||
for (var j = 0, k = 0, jj = width * height * 4; j < jj; ) {
|
||||
imageBytes[j++] = jpegData[k++];
|
||||
imageBytes[j++] = jpegData[k++];
|
||||
imageBytes[j++] = jpegData[k++];
|
||||
|
@ -13,26 +13,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
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 TEXT_LAYER_MODE = 0; // DISABLE
|
||||
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;
|
||||
|
||||
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 MIN_SCALE = 0.25;
|
||||
var MAX_SCALE = 10.0;
|
||||
var DEFAULT_SCALE_VALUE = 'auto';
|
||||
var DEFAULT_SCALE_VALUE = "auto";
|
||||
|
||||
var PDFViewerApplication = {
|
||||
pdfLoadingTask: null,
|
||||
@ -49,10 +49,12 @@ var PDFViewerApplication = {
|
||||
open: function(params) {
|
||||
if (this.pdfLoadingTask) {
|
||||
// We need to destroy already opened document
|
||||
return this.close().then(function () {
|
||||
return this.close().then(
|
||||
function() {
|
||||
// ... and repeat the open() call.
|
||||
return this.open(params);
|
||||
}.bind(this));
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
var url = params.url;
|
||||
@ -68,45 +70,60 @@ var PDFViewerApplication = {
|
||||
});
|
||||
this.pdfLoadingTask = loadingTask;
|
||||
|
||||
loadingTask.onProgress = function (progressData) {
|
||||
loadingTask.onProgress = function(progressData) {
|
||||
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.
|
||||
self.pdfDocument = pdfDocument;
|
||||
self.pdfViewer.setDocument(pdfDocument);
|
||||
self.pdfLinkService.setDocument(pdfDocument);
|
||||
self.pdfHistory.initialize({ fingerprint: pdfDocument.fingerprint, });
|
||||
self.pdfHistory.initialize({ fingerprint: pdfDocument.fingerprint });
|
||||
|
||||
self.loadingBar.hide();
|
||||
self.setTitleUsingMetadata(pdfDocument);
|
||||
}, function (exception) {
|
||||
},
|
||||
function(exception) {
|
||||
var message = exception && exception.message;
|
||||
var l10n = self.l10n;
|
||||
var loadingErrorMessage;
|
||||
|
||||
if (exception instanceof pdfjsLib.InvalidPDFException) {
|
||||
// change error message also for other builds
|
||||
loadingErrorMessage = l10n.get('invalid_file_error', null,
|
||||
'Invalid or corrupted PDF file.');
|
||||
loadingErrorMessage = l10n.get(
|
||||
"invalid_file_error",
|
||||
null,
|
||||
"Invalid or corrupted PDF file."
|
||||
);
|
||||
} else if (exception instanceof pdfjsLib.MissingPDFException) {
|
||||
// special message for missing PDFs
|
||||
loadingErrorMessage = l10n.get('missing_file_error', null,
|
||||
'Missing PDF file.');
|
||||
loadingErrorMessage = l10n.get(
|
||||
"missing_file_error",
|
||||
null,
|
||||
"Missing PDF file."
|
||||
);
|
||||
} else if (exception instanceof pdfjsLib.UnexpectedResponseException) {
|
||||
loadingErrorMessage = l10n.get('unexpected_response_error', null,
|
||||
'Unexpected server response.');
|
||||
loadingErrorMessage = l10n.get(
|
||||
"unexpected_response_error",
|
||||
null,
|
||||
"Unexpected server response."
|
||||
);
|
||||
} else {
|
||||
loadingErrorMessage = l10n.get('loading_error', null,
|
||||
'An error occurred while loading the PDF.');
|
||||
loadingErrorMessage = l10n.get(
|
||||
"loading_error",
|
||||
null,
|
||||
"An error occurred while loading the PDF."
|
||||
);
|
||||
}
|
||||
|
||||
loadingErrorMessage.then(function (msg) {
|
||||
self.error(msg, { message: message, });
|
||||
loadingErrorMessage.then(function(msg) {
|
||||
self.error(msg, { message: message });
|
||||
});
|
||||
self.loadingBar.hide();
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -115,8 +132,8 @@ var PDFViewerApplication = {
|
||||
* destruction is completed.
|
||||
*/
|
||||
close: function() {
|
||||
var errorWrapper = document.getElementById('errorWrapper');
|
||||
errorWrapper.setAttribute('hidden', 'true');
|
||||
var errorWrapper = document.getElementById("errorWrapper");
|
||||
errorWrapper.setAttribute("hidden", "true");
|
||||
|
||||
if (!this.pdfLoadingTask) {
|
||||
return Promise.resolve();
|
||||
@ -140,9 +157,9 @@ var PDFViewerApplication = {
|
||||
},
|
||||
|
||||
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) {
|
||||
@ -160,99 +177,125 @@ var PDFViewerApplication = {
|
||||
setTitleUsingMetadata: function(pdfDocument) {
|
||||
var self = this;
|
||||
pdfDocument.getMetadata().then(function(data) {
|
||||
var info = data.info, metadata = data.metadata;
|
||||
var info = data.info,
|
||||
metadata = data.metadata;
|
||||
self.documentInfo = info;
|
||||
self.metadata = metadata;
|
||||
|
||||
// Provides some basic debug information
|
||||
console.log('PDF ' + pdfDocument.fingerprint + ' [' +
|
||||
info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() +
|
||||
' / ' + (info.Creator || '-').trim() + ']' +
|
||||
' (PDF.js: ' + (pdfjsLib.version || '-') + ')');
|
||||
console.log(
|
||||
"PDF " +
|
||||
pdfDocument.fingerprint +
|
||||
" [" +
|
||||
info.PDFFormatVersion +
|
||||
" " +
|
||||
(info.Producer || "-").trim() +
|
||||
" / " +
|
||||
(info.Creator || "-").trim() +
|
||||
"]" +
|
||||
" (PDF.js: " +
|
||||
(pdfjsLib.version || "-") +
|
||||
")"
|
||||
);
|
||||
|
||||
var pdfTitle;
|
||||
if (metadata && metadata.has('dc:title')) {
|
||||
var title = metadata.get('dc:title');
|
||||
if (metadata && metadata.has("dc:title")) {
|
||||
var title = metadata.get("dc:title");
|
||||
// Ghostscript sometimes returns 'Untitled', so prevent setting the
|
||||
// title to 'Untitled.
|
||||
if (title !== 'Untitled') {
|
||||
if (title !== "Untitled") {
|
||||
pdfTitle = title;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pdfTitle && info && info['Title']) {
|
||||
pdfTitle = info['Title'];
|
||||
if (!pdfTitle && info && info["Title"]) {
|
||||
pdfTitle = info["Title"];
|
||||
}
|
||||
|
||||
if (pdfTitle) {
|
||||
self.setTitle(pdfTitle + ' - ' + document.title);
|
||||
self.setTitle(pdfTitle + " - " + document.title);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setTitle: function pdfViewSetTitle(title) {
|
||||
document.title = title;
|
||||
document.getElementById('title').textContent = title;
|
||||
document.getElementById("title").textContent = title;
|
||||
},
|
||||
|
||||
error: function pdfViewError(message, moreInfo) {
|
||||
var l10n = this.l10n;
|
||||
var moreInfoText = [l10n.get('error_version_info',
|
||||
{ version: pdfjsLib.version || '?',
|
||||
build: pdfjsLib.build || '?', },
|
||||
'PDF.js v{{version}} (build: {{build}})')];
|
||||
var moreInfoText = [
|
||||
l10n.get(
|
||||
"error_version_info",
|
||||
{ version: pdfjsLib.version || "?", build: pdfjsLib.build || "?" },
|
||||
"PDF.js v{{version}} (build: {{build}})"
|
||||
),
|
||||
];
|
||||
|
||||
if (moreInfo) {
|
||||
moreInfoText.push(
|
||||
l10n.get('error_message', { message: moreInfo.message, },
|
||||
'Message: {{message}}'));
|
||||
l10n.get(
|
||||
"error_message",
|
||||
{ message: moreInfo.message },
|
||||
"Message: {{message}}"
|
||||
)
|
||||
);
|
||||
if (moreInfo.stack) {
|
||||
moreInfoText.push(
|
||||
l10n.get('error_stack', { stack: moreInfo.stack, },
|
||||
'Stack: {{stack}}'));
|
||||
l10n.get("error_stack", { stack: moreInfo.stack }, "Stack: {{stack}}")
|
||||
);
|
||||
} else {
|
||||
if (moreInfo.filename) {
|
||||
moreInfoText.push(
|
||||
l10n.get('error_file', { file: moreInfo.filename, },
|
||||
'File: {{file}}'));
|
||||
l10n.get(
|
||||
"error_file",
|
||||
{ file: moreInfo.filename },
|
||||
"File: {{file}}"
|
||||
)
|
||||
);
|
||||
}
|
||||
if (moreInfo.lineNumber) {
|
||||
moreInfoText.push(
|
||||
l10n.get('error_line', { line: moreInfo.lineNumber, },
|
||||
'Line: {{line}}'));
|
||||
l10n.get(
|
||||
"error_line",
|
||||
{ line: moreInfo.lineNumber },
|
||||
"Line: {{line}}"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var errorWrapper = document.getElementById('errorWrapper');
|
||||
errorWrapper.removeAttribute('hidden');
|
||||
var errorWrapper = document.getElementById("errorWrapper");
|
||||
errorWrapper.removeAttribute("hidden");
|
||||
|
||||
var errorMessage = document.getElementById('errorMessage');
|
||||
var errorMessage = document.getElementById("errorMessage");
|
||||
errorMessage.textContent = message;
|
||||
|
||||
var closeButton = document.getElementById('errorClose');
|
||||
var closeButton = document.getElementById("errorClose");
|
||||
closeButton.onclick = function() {
|
||||
errorWrapper.setAttribute('hidden', 'true');
|
||||
errorWrapper.setAttribute("hidden", "true");
|
||||
};
|
||||
|
||||
var errorMoreInfo = document.getElementById('errorMoreInfo');
|
||||
var moreInfoButton = document.getElementById('errorShowMore');
|
||||
var lessInfoButton = document.getElementById('errorShowLess');
|
||||
var errorMoreInfo = document.getElementById("errorMoreInfo");
|
||||
var moreInfoButton = document.getElementById("errorShowMore");
|
||||
var lessInfoButton = document.getElementById("errorShowLess");
|
||||
moreInfoButton.onclick = function() {
|
||||
errorMoreInfo.removeAttribute('hidden');
|
||||
moreInfoButton.setAttribute('hidden', 'true');
|
||||
lessInfoButton.removeAttribute('hidden');
|
||||
errorMoreInfo.style.height = errorMoreInfo.scrollHeight + 'px';
|
||||
errorMoreInfo.removeAttribute("hidden");
|
||||
moreInfoButton.setAttribute("hidden", "true");
|
||||
lessInfoButton.removeAttribute("hidden");
|
||||
errorMoreInfo.style.height = errorMoreInfo.scrollHeight + "px";
|
||||
};
|
||||
lessInfoButton.onclick = function() {
|
||||
errorMoreInfo.setAttribute('hidden', 'true');
|
||||
moreInfoButton.removeAttribute('hidden');
|
||||
lessInfoButton.setAttribute('hidden', 'true');
|
||||
errorMoreInfo.setAttribute("hidden", "true");
|
||||
moreInfoButton.removeAttribute("hidden");
|
||||
lessInfoButton.setAttribute("hidden", "true");
|
||||
};
|
||||
moreInfoButton.removeAttribute('hidden');
|
||||
lessInfoButton.setAttribute('hidden', 'true');
|
||||
Promise.all(moreInfoText).then(function (parts) {
|
||||
errorMoreInfo.value = parts.join('\n');
|
||||
moreInfoButton.removeAttribute("hidden");
|
||||
lessInfoButton.setAttribute("hidden", "true");
|
||||
Promise.all(moreInfoText).then(function(parts) {
|
||||
errorMoreInfo.value = parts.join("\n");
|
||||
});
|
||||
},
|
||||
|
||||
@ -302,7 +345,7 @@ var PDFViewerApplication = {
|
||||
|
||||
this.l10n = pdfjsViewer.NullL10n;
|
||||
|
||||
var container = document.getElementById('viewerContainer');
|
||||
var container = document.getElementById("viewerContainer");
|
||||
var pdfViewer = new pdfjsViewer.PDFViewer({
|
||||
container: container,
|
||||
linkService: linkService,
|
||||
@ -318,29 +361,30 @@ var PDFViewerApplication = {
|
||||
});
|
||||
linkService.setHistory(this.pdfHistory);
|
||||
|
||||
document.getElementById('previous').addEventListener('click', function() {
|
||||
document.getElementById("previous").addEventListener("click", function() {
|
||||
PDFViewerApplication.page--;
|
||||
});
|
||||
|
||||
document.getElementById('next').addEventListener('click', function() {
|
||||
document.getElementById("next").addEventListener("click", function() {
|
||||
PDFViewerApplication.page++;
|
||||
});
|
||||
|
||||
document.getElementById('zoomIn').addEventListener('click', function() {
|
||||
document.getElementById("zoomIn").addEventListener("click", function() {
|
||||
PDFViewerApplication.zoomIn();
|
||||
});
|
||||
|
||||
document.getElementById('zoomOut').addEventListener('click', function() {
|
||||
document.getElementById("zoomOut").addEventListener("click", function() {
|
||||
PDFViewerApplication.zoomOut();
|
||||
});
|
||||
|
||||
document.getElementById('pageNumber').addEventListener('click', function() {
|
||||
document.getElementById("pageNumber").addEventListener("click", function() {
|
||||
this.select();
|
||||
});
|
||||
|
||||
document.getElementById('pageNumber').addEventListener('change',
|
||||
function() {
|
||||
PDFViewerApplication.page = (this.value | 0);
|
||||
document
|
||||
.getElementById("pageNumber")
|
||||
.addEventListener("change", function() {
|
||||
PDFViewerApplication.page = this.value | 0;
|
||||
|
||||
// Ensure that the page number input displays the correct value,
|
||||
// even if the value entered by the user was invalid
|
||||
@ -350,37 +394,44 @@ var PDFViewerApplication = {
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('pagesinit', function () {
|
||||
document.addEventListener("pagesinit", function() {
|
||||
// We can use pdfViewer now, e.g. let's change default scale.
|
||||
pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
|
||||
});
|
||||
|
||||
document.addEventListener('pagechanging', function (evt) {
|
||||
document.addEventListener(
|
||||
"pagechanging",
|
||||
function(evt) {
|
||||
var page = evt.detail.pageNumber;
|
||||
var numPages = PDFViewerApplication.pagesCount;
|
||||
|
||||
document.getElementById('pageNumber').value = page;
|
||||
document.getElementById('previous').disabled = (page <= 1);
|
||||
document.getElementById('next').disabled = (page >= numPages);
|
||||
}, true);
|
||||
document.getElementById("pageNumber").value = page;
|
||||
document.getElementById("previous").disabled = page <= 1;
|
||||
document.getElementById("next").disabled = page >= numPages;
|
||||
},
|
||||
true
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.addEventListener(
|
||||
"DOMContentLoaded",
|
||||
function() {
|
||||
PDFViewerApplication.initUI();
|
||||
}, true);
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
(function animationStartedClosure() {
|
||||
// The offsetParent is not set until the PDF.js iframe or object is visible.
|
||||
// Waiting for first animation.
|
||||
PDFViewerApplication.animationStartedPromise = new Promise(
|
||||
function (resolve) {
|
||||
PDFViewerApplication.animationStartedPromise = new Promise(function(resolve) {
|
||||
window.requestAnimationFrame(resolve);
|
||||
});
|
||||
})();
|
||||
|
||||
// We need to delay opening until all HTML is loaded.
|
||||
PDFViewerApplication.animationStartedPromise.then(function () {
|
||||
PDFViewerApplication.animationStartedPromise.then(function() {
|
||||
PDFViewerApplication.open({
|
||||
url: DEFAULT_URL,
|
||||
});
|
||||
|
@ -2,10 +2,18 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function xmlEncode(s) {
|
||||
var i = 0, ch;
|
||||
var i = 0,
|
||||
ch;
|
||||
s = String(s);
|
||||
while (i < s.length && (ch = s[i]) !== '&' && ch !== '<' &&
|
||||
ch !== '\"' && ch !== '\n' && ch !== '\r' && ch !== '\t') {
|
||||
while (
|
||||
i < s.length &&
|
||||
(ch = s[i]) !== "&" &&
|
||||
ch !== "<" &&
|
||||
ch !== '"' &&
|
||||
ch !== "\n" &&
|
||||
ch !== "\r" &&
|
||||
ch !== "\t"
|
||||
) {
|
||||
i++;
|
||||
}
|
||||
if (i >= s.length) {
|
||||
@ -15,23 +23,23 @@ function xmlEncode(s) {
|
||||
while (i < s.length) {
|
||||
ch = s[i++];
|
||||
switch (ch) {
|
||||
case '&':
|
||||
buf += '&';
|
||||
case "&":
|
||||
buf += "&";
|
||||
break;
|
||||
case '<':
|
||||
buf += '<';
|
||||
case "<":
|
||||
buf += "<";
|
||||
break;
|
||||
case '\"':
|
||||
buf += '"';
|
||||
case '"':
|
||||
buf += """;
|
||||
break;
|
||||
case '\n':
|
||||
buf += '
';
|
||||
case "\n":
|
||||
buf += "
";
|
||||
break;
|
||||
case '\r':
|
||||
buf += '
';
|
||||
case "\r":
|
||||
buf += "
";
|
||||
break;
|
||||
case '\t':
|
||||
buf += '	';
|
||||
case "\t":
|
||||
buf += "	";
|
||||
break;
|
||||
default:
|
||||
buf += ch;
|
||||
@ -45,9 +53,9 @@ function DOMElement(name) {
|
||||
this.nodeName = name;
|
||||
this.childNodes = [];
|
||||
this.attributes = {};
|
||||
this.textContent = '';
|
||||
this.textContent = "";
|
||||
|
||||
if (name === 'style') {
|
||||
if (name === "style") {
|
||||
this.sheet = {
|
||||
cssRules: [],
|
||||
insertRule: function(rule) {
|
||||
@ -74,7 +82,7 @@ DOMElement.prototype = {
|
||||
// Assuming that there is only one matching attribute for a given name,
|
||||
// across all namespaces.
|
||||
if (NS) {
|
||||
var suffix = ':' + name;
|
||||
var suffix = ":" + name;
|
||||
for (var fullName in this.attributes) {
|
||||
if (fullName.slice(-suffix.length) === suffix) {
|
||||
return this.attributes[fullName];
|
||||
@ -85,7 +93,7 @@ DOMElement.prototype = {
|
||||
},
|
||||
|
||||
setAttribute: function DOMElement_setAttribute(name, value) {
|
||||
value = value || '';
|
||||
value = value || "";
|
||||
value = xmlEncode(value);
|
||||
this.attributes[name] = value;
|
||||
},
|
||||
@ -123,7 +131,7 @@ DOMElement.prototype = {
|
||||
while ((chunk = serializer.getNext()) !== null) {
|
||||
buf.push(chunk);
|
||||
}
|
||||
return buf.join('');
|
||||
return buf.join("");
|
||||
},
|
||||
|
||||
getSerializer: function DOMElement_getSerializer() {
|
||||
@ -149,12 +157,14 @@ DOMElementSerializer.prototype = {
|
||||
switch (this._state) {
|
||||
case 0: // Start opening tag.
|
||||
++this._state;
|
||||
return '<' + node.nodeName;
|
||||
return "<" + node.nodeName;
|
||||
case 1: // Add SVG namespace if this is the root element.
|
||||
++this._state;
|
||||
if (node.nodeName === 'svg:svg') {
|
||||
return ' xmlns:xlink="http://www.w3.org/1999/xlink"' +
|
||||
' xmlns:svg="http://www.w3.org/2000/svg"';
|
||||
if (node.nodeName === "svg:svg") {
|
||||
return (
|
||||
' xmlns:xlink="http://www.w3.org/1999/xlink"' +
|
||||
' xmlns:svg="http://www.w3.org/2000/svg"'
|
||||
);
|
||||
}
|
||||
/* falls through */
|
||||
case 2: // Initialize variables for looping over attributes.
|
||||
@ -165,12 +175,12 @@ DOMElementSerializer.prototype = {
|
||||
case 3: // Serialize any attributes and end opening tag.
|
||||
if (this._loopIndex < this._attributeKeys.length) {
|
||||
var name = this._attributeKeys[this._loopIndex++];
|
||||
return ' ' + name + '="' + xmlEncode(node.attributes[name]) + '"';
|
||||
return " " + name + '="' + xmlEncode(node.attributes[name]) + '"';
|
||||
}
|
||||
++this._state;
|
||||
return '>';
|
||||
return ">";
|
||||
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;
|
||||
return xmlEncode(node.textContent);
|
||||
}
|
||||
@ -196,11 +206,11 @@ DOMElementSerializer.prototype = {
|
||||
/* falls through */
|
||||
case 6: // Ending tag.
|
||||
++this._state;
|
||||
return '</' + node.nodeName + '>';
|
||||
return "</" + node.nodeName + ">";
|
||||
case 7: // Done.
|
||||
return null;
|
||||
default:
|
||||
throw new Error('Unexpected serialization state: ' + this._state);
|
||||
throw new Error("Unexpected serialization state: " + this._state);
|
||||
}
|
||||
},
|
||||
};
|
||||
@ -209,7 +219,7 @@ const document = {
|
||||
childNodes: [],
|
||||
|
||||
get currentScript() {
|
||||
return { src: '', };
|
||||
return { src: "" };
|
||||
},
|
||||
|
||||
get documentElement() {
|
||||
@ -222,12 +232,12 @@ const document = {
|
||||
},
|
||||
|
||||
createElement: function(element) {
|
||||
return this.createElementNS('', element);
|
||||
return this.createElementNS("", element);
|
||||
},
|
||||
|
||||
getElementsByTagName: function(element) {
|
||||
if (element === 'head') {
|
||||
return [this.head || (this.head = new DOMElement('head'))];
|
||||
if (element === "head") {
|
||||
return [this.head || (this.head = new DOMElement("head"))];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
@ -256,13 +266,13 @@ var exported_symbols = Object.keys(exports);
|
||||
|
||||
exports.setStubs = function(namespace) {
|
||||
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];
|
||||
});
|
||||
};
|
||||
exports.unsetStubs = function(namespace) {
|
||||
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];
|
||||
});
|
||||
};
|
||||
|
@ -8,48 +8,52 @@
|
||||
//
|
||||
|
||||
// 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
|
||||
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
|
||||
// callback.
|
||||
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
||||
loadingTask.promise.then(function(doc) {
|
||||
loadingTask.promise
|
||||
.then(function(doc) {
|
||||
var numPages = doc.numPages;
|
||||
console.log('# Document Loaded');
|
||||
console.log('Number of Pages: ' + numPages);
|
||||
console.log("# Document Loaded");
|
||||
console.log("Number of Pages: " + numPages);
|
||||
console.log();
|
||||
|
||||
var lastPromise; // will be used to chain promises
|
||||
lastPromise = doc.getMetadata().then(function (data) {
|
||||
console.log('# Metadata Is Loaded');
|
||||
console.log('## Info');
|
||||
lastPromise = doc.getMetadata().then(function(data) {
|
||||
console.log("# Metadata Is Loaded");
|
||||
console.log("## Info");
|
||||
console.log(JSON.stringify(data.info, null, 2));
|
||||
console.log();
|
||||
if (data.metadata) {
|
||||
console.log('## Metadata');
|
||||
console.log("## Metadata");
|
||||
console.log(JSON.stringify(data.metadata.getAll(), null, 2));
|
||||
console.log();
|
||||
}
|
||||
});
|
||||
|
||||
var loadPage = function (pageNum) {
|
||||
return doc.getPage(pageNum).then(function (page) {
|
||||
console.log('# Page ' + pageNum);
|
||||
var viewport = page.getViewport({ scale: 1.0, });
|
||||
console.log('Size: ' + viewport.width + 'x' + viewport.height);
|
||||
var loadPage = function(pageNum) {
|
||||
return doc.getPage(pageNum).then(function(page) {
|
||||
console.log("# Page " + pageNum);
|
||||
var viewport = page.getViewport({ scale: 1.0 });
|
||||
console.log("Size: " + viewport.width + "x" + viewport.height);
|
||||
console.log();
|
||||
return page.getTextContent().then(function (content) {
|
||||
return page
|
||||
.getTextContent()
|
||||
.then(function(content) {
|
||||
// Content contains lots of information about the text layout and
|
||||
// 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;
|
||||
});
|
||||
console.log('## Text Content');
|
||||
console.log(strings.join(' '));
|
||||
}).then(function () {
|
||||
console.log("## Text Content");
|
||||
console.log(strings.join(" "));
|
||||
})
|
||||
.then(function() {
|
||||
console.log();
|
||||
});
|
||||
});
|
||||
@ -60,8 +64,12 @@ loadingTask.promise.then(function(doc) {
|
||||
lastPromise = lastPromise.then(loadPage.bind(null, i));
|
||||
}
|
||||
return lastPromise;
|
||||
}).then(function () {
|
||||
console.log('# End of Document');
|
||||
}, function (err) {
|
||||
console.error('Error: ' + err);
|
||||
});
|
||||
})
|
||||
.then(
|
||||
function() {
|
||||
console.log("# End of Document");
|
||||
},
|
||||
function(err) {
|
||||
console.error("Error: " + err);
|
||||
}
|
||||
);
|
||||
|
@ -13,16 +13,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var Canvas = require('canvas');
|
||||
var assert = require('assert').strict;
|
||||
var fs = require('fs');
|
||||
var Canvas = require("canvas");
|
||||
var assert = require("assert").strict;
|
||||
var fs = require("fs");
|
||||
|
||||
function NodeCanvasFactory() {}
|
||||
NodeCanvasFactory.prototype = {
|
||||
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 context = canvas.getContext('2d');
|
||||
var context = canvas.getContext("2d");
|
||||
return {
|
||||
canvas: canvas,
|
||||
context: context,
|
||||
@ -30,14 +30,14 @@ NodeCanvasFactory.prototype = {
|
||||
},
|
||||
|
||||
reset: function NodeCanvasFactory_reset(canvasAndContext, width, height) {
|
||||
assert(canvasAndContext.canvas, 'Canvas is not specified');
|
||||
assert(width > 0 && height > 0, 'Invalid canvas size');
|
||||
assert(canvasAndContext.canvas, "Canvas is not specified");
|
||||
assert(width > 0 && height > 0, "Invalid canvas size");
|
||||
canvasAndContext.canvas.width = width;
|
||||
canvasAndContext.canvas.height = height;
|
||||
},
|
||||
|
||||
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
|
||||
// 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.
|
||||
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.
|
||||
var rawData = new Uint8Array(fs.readFileSync(pdfURL));
|
||||
|
||||
// Load the PDF file.
|
||||
var loadingTask = pdfjsLib.getDocument(rawData);
|
||||
loadingTask.promise.then(function(pdfDocument) {
|
||||
console.log('# PDF document loaded.');
|
||||
loadingTask.promise
|
||||
.then(function(pdfDocument) {
|
||||
console.log("# PDF document loaded.");
|
||||
|
||||
// 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.
|
||||
var viewport = page.getViewport({ scale: 1.0, });
|
||||
var viewport = page.getViewport({ scale: 1.0 });
|
||||
var canvasFactory = new NodeCanvasFactory();
|
||||
var canvasAndContext =
|
||||
canvasFactory.create(viewport.width, viewport.height);
|
||||
var canvasAndContext = canvasFactory.create(
|
||||
viewport.width,
|
||||
viewport.height
|
||||
);
|
||||
var renderContext = {
|
||||
canvasContext: canvasAndContext.context,
|
||||
viewport: viewport,
|
||||
@ -78,16 +81,18 @@ loadingTask.promise.then(function(pdfDocument) {
|
||||
renderTask.promise.then(function() {
|
||||
// Convert the canvas to an image buffer.
|
||||
var image = canvasAndContext.canvas.toBuffer();
|
||||
fs.writeFile('output.png', image, function (error) {
|
||||
fs.writeFile("output.png", image, function(error) {
|
||||
if (error) {
|
||||
console.error('Error: ' + error);
|
||||
console.error("Error: " + error);
|
||||
} else {
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
@ -5,29 +5,29 @@
|
||||
// Node tool to dump SVG output into a file.
|
||||
//
|
||||
|
||||
var fs = require('fs');
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
var stream = require('stream');
|
||||
var fs = require("fs");
|
||||
var util = require("util");
|
||||
var path = require("path");
|
||||
var stream = require("stream");
|
||||
|
||||
// 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.
|
||||
var pdfjsLib = require('pdfjs-dist');
|
||||
var pdfjsLib = require("pdfjs-dist");
|
||||
|
||||
// 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 outputDirectory = './svgdump';
|
||||
var outputDirectory = "./svgdump";
|
||||
|
||||
try {
|
||||
// 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.
|
||||
fs.mkdirSync(outputDirectory);
|
||||
} catch (e) {
|
||||
if (e.code !== 'EEXIST') {
|
||||
if (e.code !== "EEXIST") {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
@ -35,7 +35,7 @@ try {
|
||||
// Dumps svg outputs to a folder called svgdump
|
||||
function getFilePathForPage(pageNum) {
|
||||
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);
|
||||
return new Promise(function(resolve, reject) {
|
||||
readableSvgStream.once('error', reject);
|
||||
writableStream.once('error', reject);
|
||||
writableStream.once('finish', resolve);
|
||||
readableSvgStream.once("error", reject);
|
||||
writableStream.once("error", reject);
|
||||
writableStream.once("finish", resolve);
|
||||
readableSvgStream.pipe(writableStream);
|
||||
}).catch(function(err) {
|
||||
readableSvgStream = null; // Explicitly null because of v8 bug 6512.
|
||||
@ -90,30 +90,33 @@ var loadingTask = pdfjsLib.getDocument({
|
||||
// processing.
|
||||
nativeImageDecoderSupport: pdfjsLib.NativeImageDecoding.DISPLAY,
|
||||
});
|
||||
loadingTask.promise.then(function(doc) {
|
||||
loadingTask.promise
|
||||
.then(function(doc) {
|
||||
var numPages = doc.numPages;
|
||||
console.log('# Document Loaded');
|
||||
console.log('Number of Pages: ' + numPages);
|
||||
console.log("# Document Loaded");
|
||||
console.log("Number of Pages: " + numPages);
|
||||
console.log();
|
||||
|
||||
var lastPromise = Promise.resolve(); // will be used to chain promises
|
||||
var loadPage = function (pageNum) {
|
||||
return doc.getPage(pageNum).then(function (page) {
|
||||
console.log('# Page ' + pageNum);
|
||||
var viewport = page.getViewport({ scale: 1.0, });
|
||||
console.log('Size: ' + viewport.width + 'x' + viewport.height);
|
||||
var loadPage = function(pageNum) {
|
||||
return doc.getPage(pageNum).then(function(page) {
|
||||
console.log("# Page " + pageNum);
|
||||
var viewport = page.getViewport({ scale: 1.0 });
|
||||
console.log("Size: " + viewport.width + "x" + viewport.height);
|
||||
console.log();
|
||||
|
||||
return page.getOperatorList().then(function (opList) {
|
||||
return page.getOperatorList().then(function(opList) {
|
||||
var svgGfx = new pdfjsLib.SVGGraphics(page.commonObjs, page.objs);
|
||||
svgGfx.embedFonts = true;
|
||||
return svgGfx.getSVG(opList, viewport).then(function (svg) {
|
||||
return writeSvgToFile(svg, getFilePathForPage(pageNum))
|
||||
.then(function () {
|
||||
console.log('Page: ' + pageNum);
|
||||
}, function(err) {
|
||||
console.log('Error: ' + err);
|
||||
});
|
||||
return svgGfx.getSVG(opList, viewport).then(function(svg) {
|
||||
return writeSvgToFile(svg, getFilePathForPage(pageNum)).then(
|
||||
function() {
|
||||
console.log("Page: " + pageNum);
|
||||
},
|
||||
function(err) {
|
||||
console.log("Error: " + err);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -123,8 +126,12 @@ loadingTask.promise.then(function(doc) {
|
||||
lastPromise = lastPromise.then(loadPage.bind(null, i));
|
||||
}
|
||||
return lastPromise;
|
||||
}).then(function () {
|
||||
console.log('# End of Document');
|
||||
}, function (err) {
|
||||
console.error('Error: ' + err);
|
||||
});
|
||||
})
|
||||
.then(
|
||||
function() {
|
||||
console.log("# End of Document");
|
||||
},
|
||||
function(err) {
|
||||
console.error("Error: " + err);
|
||||
}
|
||||
);
|
||||
|
@ -13,26 +13,27 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
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`"
|
||||
);
|
||||
}
|
||||
|
||||
// The workerSrc property shall be specified.
|
||||
//
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
||||
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||
|
||||
// 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 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.
|
||||
var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||
@ -40,14 +41,14 @@ var pdfLinkService = new pdfjsViewer.PDFLinkService();
|
||||
var pdfViewer = new pdfjsViewer.PDFViewer({
|
||||
container: container,
|
||||
linkService: pdfLinkService,
|
||||
renderer: 'svg',
|
||||
renderer: "svg",
|
||||
textLayerMode: 0,
|
||||
});
|
||||
pdfLinkService.setViewer(pdfViewer);
|
||||
|
||||
document.addEventListener('pagesinit', function () {
|
||||
document.addEventListener("pagesinit", function() {
|
||||
// We can use pdfViewer now, e.g. let's change default scale.
|
||||
pdfViewer.currentScaleValue = 'page-width';
|
||||
pdfViewer.currentScaleValue = "page-width";
|
||||
});
|
||||
|
||||
// Loading document.
|
||||
|
@ -13,34 +13,35 @@
|
||||
* 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_SCALE = 1.5;
|
||||
var SVG_NS = 'http://www.w3.org/2000/svg';
|
||||
var SVG_NS = "http://www.w3.org/2000/svg";
|
||||
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||
'../../node_modules/pdfjs-dist/build/pdf.worker.js';
|
||||
"../../node_modules/pdfjs-dist/build/pdf.worker.js";
|
||||
|
||||
function buildSVG(viewport, textContent) {
|
||||
// Building SVG with size of the viewport (for simplicity)
|
||||
var svg = document.createElementNS(SVG_NS, 'svg:svg');
|
||||
svg.setAttribute('width', viewport.width + 'px');
|
||||
svg.setAttribute('height', viewport.height + 'px');
|
||||
var svg = document.createElementNS(SVG_NS, "svg:svg");
|
||||
svg.setAttribute("width", viewport.width + "px");
|
||||
svg.setAttribute("height", viewport.height + "px");
|
||||
// items are transformed to have 1px font size
|
||||
svg.setAttribute('font-size', 1);
|
||||
svg.setAttribute("font-size", 1);
|
||||
|
||||
// processing all items
|
||||
textContent.items.forEach(function (textItem) {
|
||||
textContent.items.forEach(function(textItem) {
|
||||
// we have to take in account viewport transform, which includes scale,
|
||||
// rotation and Y-axis flip, and not forgetting to flip text.
|
||||
var tx = pdfjsLib.Util.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];
|
||||
// adding text element
|
||||
var text = document.createElementNS(SVG_NS, 'svg:text');
|
||||
text.setAttribute('transform', 'matrix(' + tx.join(' ') + ')');
|
||||
text.setAttribute('font-family', style.fontFamily);
|
||||
var text = document.createElementNS(SVG_NS, "svg:text");
|
||||
text.setAttribute("transform", "matrix(" + tx.join(" ") + ")");
|
||||
text.setAttribute("font-family", style.fontFamily);
|
||||
text.textContent = textItem.str;
|
||||
svg.appendChild(text);
|
||||
});
|
||||
@ -49,23 +50,25 @@ function buildSVG(viewport, textContent) {
|
||||
|
||||
function pageLoaded() {
|
||||
// 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) {
|
||||
pdfDocument.getPage(PAGE_NUMBER).then(function (page) {
|
||||
var viewport = page.getViewport({ scale: PAGE_SCALE, });
|
||||
page.getTextContent().then(function (textContent) {
|
||||
pdfDocument.getPage(PAGE_NUMBER).then(function(page) {
|
||||
var viewport = page.getViewport({ scale: PAGE_SCALE });
|
||||
page.getTextContent().then(function(textContent) {
|
||||
// building SVG and adding that to the DOM
|
||||
var svg = buildSVG(viewport, textContent);
|
||||
document.getElementById('pageContainer').appendChild(svg);
|
||||
document.getElementById("pageContainer").appendChild(svg);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
if (typeof pdfjsLib === 'undefined') {
|
||||
alert('Built version of PDF.js was not found.\n' +
|
||||
'Please run `gulp dist-install`.');
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
if (typeof pdfjsLib === "undefined") {
|
||||
alert(
|
||||
"Built version of PDF.js was not found.\n" +
|
||||
"Please run `gulp dist-install`."
|
||||
);
|
||||
return;
|
||||
}
|
||||
pageLoaded();
|
||||
|
@ -3,31 +3,33 @@
|
||||
|
||||
// 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.
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
||||
'../../build/webpack/pdf.worker.bundle.js';
|
||||
"../../build/webpack/pdf.worker.bundle.js";
|
||||
|
||||
// Loading a document.
|
||||
var loadingTask = pdfjsLib.getDocument(pdfPath);
|
||||
loadingTask.promise.then(function (pdfDocument) {
|
||||
loadingTask.promise
|
||||
.then(function(pdfDocument) {
|
||||
// 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.
|
||||
var viewport = pdfPage.getViewport({ scale: 1.0, });
|
||||
var canvas = document.getElementById('theCanvas');
|
||||
var viewport = pdfPage.getViewport({ scale: 1.0 });
|
||||
var canvas = document.getElementById("theCanvas");
|
||||
canvas.width = viewport.width;
|
||||
canvas.height = viewport.height;
|
||||
var ctx = canvas.getContext('2d');
|
||||
var ctx = canvas.getContext("2d");
|
||||
var renderTask = pdfPage.render({
|
||||
canvasContext: ctx,
|
||||
viewport: viewport,
|
||||
});
|
||||
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 path = require('path');
|
||||
var webpack = require("webpack"); // eslint-disable-line no-unused-vars
|
||||
var path = require("path");
|
||||
|
||||
module.exports = {
|
||||
context: __dirname,
|
||||
entry: {
|
||||
'main': './main.js',
|
||||
'pdf.worker': 'pdfjs-dist/build/pdf.worker.entry',
|
||||
main: "./main.js",
|
||||
"pdf.worker": "pdfjs-dist/build/pdf.worker.entry",
|
||||
},
|
||||
mode: 'none',
|
||||
mode: "none",
|
||||
output: {
|
||||
path: path.join(__dirname, '../../build/webpack'),
|
||||
publicPath: '../../build/webpack/',
|
||||
filename: '[name].bundle.js',
|
||||
path: path.join(__dirname, "../../build/webpack"),
|
||||
publicPath: "../../build/webpack/",
|
||||
filename: "[name].bundle.js",
|
||||
},
|
||||
};
|
||||
|
@ -14,22 +14,22 @@ See the License for the specific language governing permissions and
|
||||
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) {
|
||||
return VIEWER_URL + '?file=' + encodeURIComponent(pdf_url);
|
||||
return VIEWER_URL + "?file=" + encodeURIComponent(pdf_url);
|
||||
}
|
||||
|
||||
if (CSS.supports('animation', '0s')) {
|
||||
document.addEventListener('animationstart', onAnimationStart, true);
|
||||
if (CSS.supports("animation", "0s")) {
|
||||
document.addEventListener("animationstart", onAnimationStart, true);
|
||||
} else {
|
||||
document.addEventListener('webkitAnimationStart', onAnimationStart, true);
|
||||
document.addEventListener("webkitAnimationStart", onAnimationStart, true);
|
||||
}
|
||||
|
||||
function onAnimationStart(event) {
|
||||
if (event.animationName === 'pdfjs-detected-object-or-embed') {
|
||||
if (event.animationName === "pdfjs-detected-object-or-embed") {
|
||||
watchObjectOrEmbed(event.target);
|
||||
}
|
||||
}
|
||||
@ -40,19 +40,23 @@ function onAnimationStart(event) {
|
||||
// invocations have no effect.
|
||||
function watchObjectOrEmbed(elem) {
|
||||
var mimeType = elem.type;
|
||||
if (mimeType && mimeType.toLowerCase() !== 'application/pdf') {
|
||||
if (mimeType && mimeType.toLowerCase() !== "application/pdf") {
|
||||
return;
|
||||
}
|
||||
// <embed src> <object data>
|
||||
var srcAttribute = 'src' in elem ? 'src' : 'data';
|
||||
var srcAttribute = "src" in elem ? "src" : "data";
|
||||
var path = elem[srcAttribute];
|
||||
if (!mimeType && !/\.pdf($|[?#])/i.test(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (elem.tagName === 'EMBED' && elem.name === 'plugin' &&
|
||||
if (
|
||||
elem.tagName === "EMBED" &&
|
||||
elem.name === "plugin" &&
|
||||
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.
|
||||
// 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,
|
||||
@ -62,7 +66,7 @@ function watchObjectOrEmbed(elem) {
|
||||
// Until #4483 is fixed, POST requests should be ignored.
|
||||
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,
|
||||
// but "about:blank" instead.
|
||||
// See https://github.com/mozilla/pdf.js/issues/11137
|
||||
@ -76,9 +80,9 @@ function watchObjectOrEmbed(elem) {
|
||||
|
||||
var tagName = elem.tagName.toUpperCase();
|
||||
var updateEmbedOrObject;
|
||||
if (tagName === 'EMBED') {
|
||||
if (tagName === "EMBED") {
|
||||
updateEmbedOrObject = updateEmbedElement;
|
||||
} else if (tagName === 'OBJECT') {
|
||||
} else if (tagName === "OBJECT") {
|
||||
updateEmbedOrObject = updateObjectElement;
|
||||
} else {
|
||||
return;
|
||||
@ -115,7 +119,7 @@ function watchObjectOrEmbed(elem) {
|
||||
|
||||
// Display the PDF Viewer in an <embed>.
|
||||
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.
|
||||
return;
|
||||
}
|
||||
@ -126,7 +130,7 @@ function updateEmbedElement(elem) {
|
||||
if (parentNode) {
|
||||
parentNode.removeChild(elem);
|
||||
}
|
||||
elem.type = 'text/html';
|
||||
elem.type = "text/html";
|
||||
elem.src = getEmbeddedViewerURL(elem.src);
|
||||
if (parentNode) {
|
||||
parentNode.insertBefore(elem, nextSibling);
|
||||
@ -155,21 +159,21 @@ function updateObjectElement(elem) {
|
||||
var iframe = elem.firstElementChild;
|
||||
if (!iframe || !iframe.__inserted_by_pdfjs) {
|
||||
iframe = createFullSizeIframe();
|
||||
elem.textContent = '';
|
||||
elem.textContent = "";
|
||||
elem.appendChild(iframe);
|
||||
iframe.__inserted_by_pdfjs = true;
|
||||
}
|
||||
iframe.src = getEmbeddedViewerURL(elem.data);
|
||||
|
||||
// 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.
|
||||
elem.data += '';
|
||||
elem.data += "";
|
||||
|
||||
// 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,
|
||||
// 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.
|
||||
// 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.
|
||||
// (<embed> behaves as expected with the default display value, but setting it
|
||||
// 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
|
||||
// height.
|
||||
function createFullSizeIframe() {
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.style.background = 'none';
|
||||
iframe.style.border = 'none';
|
||||
iframe.style.borderRadius = 'none';
|
||||
iframe.style.boxShadow = 'none';
|
||||
iframe.style.cssFloat = 'none';
|
||||
iframe.style.display = 'block';
|
||||
iframe.style.height = '100%';
|
||||
iframe.style.margin = '0';
|
||||
iframe.style.maxHeight = 'none';
|
||||
iframe.style.maxWidth = 'none';
|
||||
iframe.style.position = 'static';
|
||||
iframe.style.transform = 'none';
|
||||
iframe.style.visibility = 'visible';
|
||||
iframe.style.width = '100%';
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.style.background = "none";
|
||||
iframe.style.border = "none";
|
||||
iframe.style.borderRadius = "none";
|
||||
iframe.style.boxShadow = "none";
|
||||
iframe.style.cssFloat = "none";
|
||||
iframe.style.display = "block";
|
||||
iframe.style.height = "100%";
|
||||
iframe.style.margin = "0";
|
||||
iframe.style.maxHeight = "none";
|
||||
iframe.style.maxWidth = "none";
|
||||
iframe.style.position = "static";
|
||||
iframe.style.transform = "none";
|
||||
iframe.style.visibility = "visible";
|
||||
iframe.style.width = "100%";
|
||||
return iframe;
|
||||
}
|
||||
|
||||
@ -208,10 +212,10 @@ function createFullSizeIframe() {
|
||||
function getEmbeddedViewerURL(path) {
|
||||
var fragment = /^([^#]*)(#.*)?$/.exec(path);
|
||||
path = fragment[1];
|
||||
fragment = fragment[2] || '';
|
||||
fragment = fragment[2] || "";
|
||||
|
||||
// Resolve relative path to document.
|
||||
var a = document.createElement('a');
|
||||
var a = document.createElement("a");
|
||||
a.href = document.baseURI;
|
||||
a.href = path;
|
||||
path = a.href;
|
||||
|
@ -14,24 +14,24 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
(function ExtensionRouterClosure() {
|
||||
var VIEWER_URL = chrome.extension.getURL('content/web/viewer.html');
|
||||
var CRX_BASE_URL = chrome.extension.getURL('/');
|
||||
var VIEWER_URL = chrome.extension.getURL("content/web/viewer.html");
|
||||
var CRX_BASE_URL = chrome.extension.getURL("/");
|
||||
|
||||
var schemes = [
|
||||
'http',
|
||||
'https',
|
||||
'ftp',
|
||||
'file',
|
||||
'chrome-extension',
|
||||
'blob',
|
||||
'data',
|
||||
"http",
|
||||
"https",
|
||||
"ftp",
|
||||
"file",
|
||||
"chrome-extension",
|
||||
"blob",
|
||||
"data",
|
||||
// Chromium OS
|
||||
'filesystem',
|
||||
"filesystem",
|
||||
// Chromium OS, shorthand for filesystem:<origin>/external/
|
||||
'drive'
|
||||
"drive",
|
||||
];
|
||||
|
||||
/**
|
||||
@ -47,8 +47,8 @@ limitations under the License.
|
||||
}
|
||||
var scheme = url.slice(0, schemeIndex).toLowerCase();
|
||||
if (schemes.includes(scheme)) {
|
||||
url = url.split('#')[0];
|
||||
if (url.charAt(schemeIndex) === ':') {
|
||||
url = url.split("#")[0];
|
||||
if (url.charAt(schemeIndex) === ":") {
|
||||
url = encodeURIComponent(url);
|
||||
}
|
||||
return url;
|
||||
@ -60,55 +60,65 @@ limitations under the License.
|
||||
// supported, see http://crbug.com/273589
|
||||
// (or rewrite the query string parser in viewer.js to get it to
|
||||
// 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
|
||||
// chrome-extension://.../content/web/viewer.html?file=http%3A%2F%2F...pdf
|
||||
var url = parseExtensionURL(details.url);
|
||||
if (url) {
|
||||
url = VIEWER_URL + '?file=' + url;
|
||||
var i = details.url.indexOf('#');
|
||||
url = VIEWER_URL + "?file=" + url;
|
||||
var i = details.url.indexOf("#");
|
||||
if (i > 0) {
|
||||
url += details.url.slice(i);
|
||||
}
|
||||
console.log('Redirecting ' + details.url + ' to ' + url);
|
||||
return { redirectUrl: url, };
|
||||
console.log("Redirecting " + details.url + " to " + url);
|
||||
return { redirectUrl: url };
|
||||
}
|
||||
return undefined;
|
||||
}, {
|
||||
types: ['main_frame', 'sub_frame'],
|
||||
},
|
||||
{
|
||||
types: ["main_frame", "sub_frame"],
|
||||
urls: schemes.map(function(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
|
||||
// webRequest event listener is attached (= page not found).
|
||||
// Or the extension could have been crashed (OOM), leaving a sad tab behind.
|
||||
// Reload these tabs.
|
||||
chrome.tabs.query({
|
||||
url: CRX_BASE_URL + '*:*',
|
||||
}, function(tabsFromLastSession) {
|
||||
chrome.tabs.query(
|
||||
{
|
||||
url: CRX_BASE_URL + "*:*",
|
||||
},
|
||||
function(tabsFromLastSession) {
|
||||
for (var i = 0; i < tabsFromLastSession.length; ++i) {
|
||||
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) {
|
||||
// The localStorage item is set upon unload by chromecom.js.
|
||||
var parsedKey = /^unload-(\d+)-(true|false)-(.+)/.exec(key);
|
||||
if (parsedKey) {
|
||||
var timeStart = parseInt(parsedKey[1], 10);
|
||||
var isHidden = parsedKey[2] === 'true';
|
||||
var isHidden = parsedKey[2] === "true";
|
||||
var url = parsedKey[3];
|
||||
if (Date.now() - timeStart < 3000) {
|
||||
// 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).
|
||||
chrome.tabs.create({
|
||||
url: chrome.runtime.getURL('restoretab.html') +
|
||||
'?' + encodeURIComponent(url) +
|
||||
'#' + encodeURIComponent(localStorage.getItem(key)),
|
||||
url:
|
||||
chrome.runtime.getURL("restoretab.html") +
|
||||
"?" +
|
||||
encodeURIComponent(url) +
|
||||
"#" +
|
||||
encodeURIComponent(localStorage.getItem(key)),
|
||||
active: !isHidden,
|
||||
});
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||
/* eslint strict: ["error", "function"] */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
"use strict";
|
||||
var storageLocal = chrome.storage.local;
|
||||
var storageSync = chrome.storage.sync;
|
||||
|
||||
@ -40,12 +40,12 @@ limitations under the License.
|
||||
function getStorageNames(callback) {
|
||||
var x = new XMLHttpRequest();
|
||||
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() {
|
||||
var storageKeys = Object.keys(x.response.properties);
|
||||
callback(storageKeys);
|
||||
};
|
||||
x.responseType = 'json';
|
||||
x.responseType = "json";
|
||||
x.send();
|
||||
}
|
||||
|
||||
@ -54,8 +54,10 @@ limitations under the License.
|
||||
function migrateToSyncStorage(values) {
|
||||
storageSync.set(values, function() {
|
||||
if (chrome.runtime.lastError) {
|
||||
console.error('Failed to migrate settings due to an error: ' +
|
||||
chrome.runtime.lastError.message);
|
||||
console.error(
|
||||
"Failed to migrate settings due to an error: " +
|
||||
chrome.runtime.lastError.message
|
||||
);
|
||||
return;
|
||||
}
|
||||
// Migration successful. Delete local settings.
|
||||
@ -64,7 +66,8 @@ limitations under the License.
|
||||
// backend is corrupt), but since storageSync.set succeeded, consider
|
||||
// the migration successful.
|
||||
console.log(
|
||||
'Successfully migrated preferences from local to sync storage.');
|
||||
"Successfully migrated preferences from local to sync storage."
|
||||
);
|
||||
migrateRenamedStorage();
|
||||
});
|
||||
});
|
||||
@ -75,61 +78,82 @@ limitations under the License.
|
||||
// Note: We cannot modify managed preferences, so the migration logic is
|
||||
// duplicated in web/chromecom.js too.
|
||||
function migrateRenamedStorage() {
|
||||
storageSync.get([
|
||||
'enableHandToolOnLoad',
|
||||
'cursorToolOnLoad',
|
||||
'disableTextLayer',
|
||||
'enhanceTextSelection',
|
||||
'textLayerMode',
|
||||
'showPreviousViewOnLoad',
|
||||
'disablePageMode',
|
||||
'viewOnLoad',
|
||||
], function(items) {
|
||||
storageSync.get(
|
||||
[
|
||||
"enableHandToolOnLoad",
|
||||
"cursorToolOnLoad",
|
||||
"disableTextLayer",
|
||||
"enhanceTextSelection",
|
||||
"textLayerMode",
|
||||
"showPreviousViewOnLoad",
|
||||
"disablePageMode",
|
||||
"viewOnLoad",
|
||||
],
|
||||
function(items) {
|
||||
// Migration code for https://github.com/mozilla/pdf.js/pull/7635.
|
||||
if (typeof items.enableHandToolOnLoad === 'boolean') {
|
||||
if (typeof items.enableHandToolOnLoad === "boolean") {
|
||||
if (items.enableHandToolOnLoad) {
|
||||
storageSync.set({
|
||||
storageSync.set(
|
||||
{
|
||||
cursorToolOnLoad: 1,
|
||||
}, function() {
|
||||
},
|
||||
function() {
|
||||
if (!chrome.runtime.lastError) {
|
||||
storageSync.remove('enableHandToolOnLoad');
|
||||
storageSync.remove("enableHandToolOnLoad");
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
storageSync.remove('enableHandToolOnLoad');
|
||||
storageSync.remove("enableHandToolOnLoad");
|
||||
}
|
||||
}
|
||||
// Migration code for https://github.com/mozilla/pdf.js/pull/9479.
|
||||
if (typeof items.disableTextLayer === 'boolean') {
|
||||
var textLayerMode = items.disableTextLayer ? 0 :
|
||||
items.enhanceTextSelection ? 2 : 1;
|
||||
if (typeof items.disableTextLayer === "boolean") {
|
||||
var textLayerMode = items.disableTextLayer
|
||||
? 0
|
||||
: items.enhanceTextSelection
|
||||
? 2
|
||||
: 1;
|
||||
if (textLayerMode !== 1) {
|
||||
// Overwrite if computed textLayerMode is not the default value (1).
|
||||
storageSync.set({
|
||||
storageSync.set(
|
||||
{
|
||||
textLayerMode: textLayerMode,
|
||||
}, function() {
|
||||
},
|
||||
function() {
|
||||
if (!chrome.runtime.lastError) {
|
||||
storageSync.remove(['disableTextLayer', 'enhanceTextSelection']);
|
||||
storageSync.remove([
|
||||
"disableTextLayer",
|
||||
"enhanceTextSelection",
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
storageSync.remove(['disableTextLayer', 'enhanceTextSelection']);
|
||||
storageSync.remove(["disableTextLayer", "enhanceTextSelection"]);
|
||||
}
|
||||
}
|
||||
// Migration code for https://github.com/mozilla/pdf.js/pull/10502.
|
||||
if (typeof items.showPreviousViewOnLoad === 'boolean') {
|
||||
if (typeof items.showPreviousViewOnLoad === "boolean") {
|
||||
if (!items.showPreviousViewOnLoad) {
|
||||
storageSync.set({
|
||||
storageSync.set(
|
||||
{
|
||||
viewOnLoad: 1,
|
||||
}, function() {
|
||||
},
|
||||
function() {
|
||||
if (!chrome.runtime.lastError) {
|
||||
storageSync.remove(['showPreviousViewOnLoad', 'disablePageMode']);
|
||||
storageSync.remove([
|
||||
"showPreviousViewOnLoad",
|
||||
"disablePageMode",
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
} 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.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
var storageAreaName = chrome.storage.sync ? 'sync' : 'local';
|
||||
"use strict";
|
||||
var storageAreaName = chrome.storage.sync ? "sync" : "local";
|
||||
var storageArea = chrome.storage[storageAreaName];
|
||||
|
||||
Promise.all([
|
||||
@ -39,14 +39,15 @@ Promise.all([
|
||||
// Get the storage schema - a dictionary of preferences.
|
||||
var x = new XMLHttpRequest();
|
||||
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() {
|
||||
resolve(x.response.properties);
|
||||
};
|
||||
x.responseType = 'json';
|
||||
x.responseType = "json";
|
||||
x.send();
|
||||
})
|
||||
]).then(function(values) {
|
||||
}),
|
||||
])
|
||||
.then(function(values) {
|
||||
var managedPrefs = values[0];
|
||||
var userPrefs = values[1];
|
||||
var schema = values[2];
|
||||
@ -70,24 +71,26 @@ Promise.all([
|
||||
|
||||
// A DOM element with a method renderPreference.
|
||||
var renderPreference;
|
||||
if (prefSchema.type === 'boolean') {
|
||||
if (prefSchema.type === "boolean") {
|
||||
// Most prefs are booleans, render them in a generic way.
|
||||
renderPreference = renderBooleanPref(prefSchema.title,
|
||||
renderPreference = renderBooleanPref(
|
||||
prefSchema.title,
|
||||
prefSchema.description,
|
||||
prefName);
|
||||
} else if (prefSchema.type === 'integer' && prefSchema.enum) {
|
||||
prefName
|
||||
);
|
||||
} else if (prefSchema.type === "integer" && prefSchema.enum) {
|
||||
// Most other prefs are integer-valued enumerations, render them in a
|
||||
// generic way too.
|
||||
// Unlike the renderBooleanPref branch, each preference handled by this
|
||||
// branch still needs its own template in options.html with
|
||||
// id="$prefName-template".
|
||||
renderPreference = renderEnumPref(prefSchema.title, prefName);
|
||||
} else if (prefName === 'defaultZoomValue') {
|
||||
} else if (prefName === "defaultZoomValue") {
|
||||
renderPreference = renderDefaultZoomValue(prefSchema.title);
|
||||
} else {
|
||||
// Should NEVER be reached. Only happens if a new type of preference is
|
||||
// added to the storage manifest.
|
||||
console.error('Don\'t know how to handle ' + prefName + '!');
|
||||
console.error("Don't know how to handle " + prefName + "!");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -99,7 +102,7 @@ Promise.all([
|
||||
var renderedPrefNames = Object.keys(renderPreferenceFunctions);
|
||||
|
||||
// Reset button to restore default settings.
|
||||
document.getElementById('reset-button').onclick = function() {
|
||||
document.getElementById("reset-button").onclick = function() {
|
||||
userPrefs = {};
|
||||
storageArea.remove(prefNames, function() {
|
||||
renderedPrefNames.forEach(function(prefName) {
|
||||
@ -110,13 +113,17 @@ Promise.all([
|
||||
|
||||
// Automatically update the UI when the preferences were changed elsewhere.
|
||||
chrome.storage.onChanged.addListener(function(changes, areaName) {
|
||||
var prefs = areaName === storageAreaName ? userPrefs :
|
||||
areaName === 'managed' ? managedPrefs : null;
|
||||
var prefs =
|
||||
areaName === storageAreaName
|
||||
? userPrefs
|
||||
: areaName === "managed"
|
||||
? managedPrefs
|
||||
: null;
|
||||
if (prefs) {
|
||||
renderedPrefNames.forEach(function(prefName) {
|
||||
var prefChanges = changes[prefName];
|
||||
if (prefChanges) {
|
||||
if ('newValue' in prefChanges) {
|
||||
if ("newValue" in prefChanges) {
|
||||
userPrefs[prefName] = prefChanges.newValue;
|
||||
} else {
|
||||
// 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) {
|
||||
return document.importNode(document.getElementById(id).content, true);
|
||||
@ -137,7 +145,7 @@ function importTemplate(id) {
|
||||
// function which updates the UI with the preference.
|
||||
|
||||
function renderBooleanPref(shortDescription, description, prefName) {
|
||||
var wrapper = importTemplate('checkbox-template');
|
||||
var wrapper = importTemplate("checkbox-template");
|
||||
wrapper.title = description;
|
||||
|
||||
var checkbox = wrapper.querySelector('input[type="checkbox"]');
|
||||
@ -146,8 +154,8 @@ function renderBooleanPref(shortDescription, description, prefName) {
|
||||
pref[prefName] = this.checked;
|
||||
storageArea.set(pref);
|
||||
};
|
||||
wrapper.querySelector('span').textContent = shortDescription;
|
||||
document.getElementById('settings-boxes').appendChild(wrapper);
|
||||
wrapper.querySelector("span").textContent = shortDescription;
|
||||
document.getElementById("settings-boxes").appendChild(wrapper);
|
||||
|
||||
function renderPreference(value) {
|
||||
checkbox.checked = value;
|
||||
@ -156,15 +164,15 @@ function renderBooleanPref(shortDescription, description, prefName) {
|
||||
}
|
||||
|
||||
function renderEnumPref(shortDescription, prefName) {
|
||||
var wrapper = importTemplate(prefName + '-template');
|
||||
var select = wrapper.querySelector('select');
|
||||
var wrapper = importTemplate(prefName + "-template");
|
||||
var select = wrapper.querySelector("select");
|
||||
select.onchange = function() {
|
||||
var pref = {};
|
||||
pref[prefName] = parseInt(this.value);
|
||||
storageArea.set(pref);
|
||||
};
|
||||
wrapper.querySelector('span').textContent = shortDescription;
|
||||
document.getElementById('settings-boxes').appendChild(wrapper);
|
||||
wrapper.querySelector("span").textContent = shortDescription;
|
||||
document.getElementById("settings-boxes").appendChild(wrapper);
|
||||
|
||||
function renderPreference(value) {
|
||||
select.value = value;
|
||||
@ -173,24 +181,24 @@ function renderEnumPref(shortDescription, prefName) {
|
||||
}
|
||||
|
||||
function renderDefaultZoomValue(shortDescription) {
|
||||
var wrapper = importTemplate('defaultZoomValue-template');
|
||||
var select = wrapper.querySelector('select');
|
||||
var wrapper = importTemplate("defaultZoomValue-template");
|
||||
var select = wrapper.querySelector("select");
|
||||
select.onchange = function() {
|
||||
storageArea.set({
|
||||
defaultZoomValue: this.value,
|
||||
});
|
||||
};
|
||||
wrapper.querySelector('span').textContent = shortDescription;
|
||||
document.getElementById('settings-boxes').appendChild(wrapper);
|
||||
wrapper.querySelector("span").textContent = shortDescription;
|
||||
document.getElementById("settings-boxes").appendChild(wrapper);
|
||||
|
||||
function renderPreference(value) {
|
||||
value = value || 'auto';
|
||||
value = value || "auto";
|
||||
select.value = value;
|
||||
var customOption = select.querySelector('option.custom-zoom');
|
||||
var customOption = select.querySelector("option.custom-zoom");
|
||||
if (select.selectedIndex === -1 && value) {
|
||||
// Custom zoom percentage, e.g. set via managed preferences.
|
||||
// [zoom] or [zoom],[left],[top]
|
||||
customOption.text = value.indexOf(',') > 0 ? value : value + '%';
|
||||
customOption.text = value.indexOf(",") > 0 ? value : value + "%";
|
||||
customOption.value = value;
|
||||
customOption.hidden = false;
|
||||
customOption.selected = true;
|
||||
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
(function PageActionClosure() {
|
||||
/**
|
||||
@ -29,16 +29,16 @@ limitations under the License.
|
||||
url = url[1];
|
||||
chrome.pageAction.setPopup({
|
||||
tabId: tabId,
|
||||
popup: '/pageAction/popup.html?file=' + encodeURIComponent(url),
|
||||
popup: "/pageAction/popup.html?file=" + encodeURIComponent(url),
|
||||
});
|
||||
chrome.pageAction.show(tabId);
|
||||
} 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) {
|
||||
if (message === 'showPageAction' && sender.tab) {
|
||||
if (message === "showPageAction" && sender.tab) {
|
||||
showPageAction(sender.tab.id, sender.tab.url);
|
||||
}
|
||||
});
|
||||
|
@ -13,7 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var url = location.search.match(/[&?]file=([^&]+)/i);
|
||||
if (url) {
|
||||
|
@ -17,7 +17,7 @@ limitations under the License.
|
||||
/* import-globals-from pdfHandler.js */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
if (!chrome.fileBrowserHandler) {
|
||||
// Not on Chromium OS, bail out
|
||||
@ -33,7 +33,7 @@ limitations under the License.
|
||||
* @param {Object} details Object of type FileHandlerExecuteEventDetails
|
||||
*/
|
||||
function onExecuteFileBrowserHandler(id, details) {
|
||||
if (id !== 'open-as-pdf') {
|
||||
if (id !== "open-as-pdf") {
|
||||
return;
|
||||
}
|
||||
var fileEntries = details.entries;
|
||||
@ -49,7 +49,7 @@ limitations under the License.
|
||||
chrome.windows.getLastFocused(function(chromeWindow) {
|
||||
var windowId = chromeWindow && chromeWindow.id;
|
||||
if (windowId) {
|
||||
chrome.windows.update(windowId, { focused: true, });
|
||||
chrome.windows.update(windowId, { focused: true });
|
||||
}
|
||||
openViewer(windowId, fileEntries);
|
||||
});
|
||||
@ -69,26 +69,34 @@ limitations under the License.
|
||||
var fileEntry = fileEntries.shift();
|
||||
var url = fileEntry.toURL();
|
||||
// Use drive: alias to get shorter (more human-readable) URLs.
|
||||
url = url.replace(/^filesystem:chrome-extension:\/\/[a-p]{32}\/external\//,
|
||||
'drive:');
|
||||
url = url.replace(
|
||||
/^filesystem:chrome-extension:\/\/[a-p]{32}\/external\//,
|
||||
"drive:"
|
||||
);
|
||||
url = getViewerURL(url);
|
||||
|
||||
if (windowId) {
|
||||
chrome.tabs.create({
|
||||
chrome.tabs.create(
|
||||
{
|
||||
windowId: windowId,
|
||||
active: true,
|
||||
url: url,
|
||||
}, function() {
|
||||
},
|
||||
function() {
|
||||
openViewer(windowId, fileEntries);
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
chrome.windows.create({
|
||||
type: 'normal',
|
||||
chrome.windows.create(
|
||||
{
|
||||
type: "normal",
|
||||
focused: true,
|
||||
url: url,
|
||||
}, function(chromeWindow) {
|
||||
},
|
||||
function(chromeWindow) {
|
||||
openViewer(chromeWindow.id, fileEntries);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -15,12 +15,12 @@ limitations under the License.
|
||||
*/
|
||||
/* 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) {
|
||||
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.
|
||||
*/
|
||||
function isPdfDownloadable(details) {
|
||||
if (details.url.includes('pdfjs.action=download')) {
|
||||
if (details.url.includes("pdfjs.action=download")) {
|
||||
return true;
|
||||
}
|
||||
// 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
|
||||
// header specifies an attachment. This allows sites like Google Drive to
|
||||
// operate correctly (#6106).
|
||||
if (details.type === 'main_frame' && !details.url.includes('=download')) {
|
||||
if (details.type === "main_frame" && !details.url.includes("=download")) {
|
||||
return false;
|
||||
}
|
||||
var cdHeader = (details.responseHeaders &&
|
||||
getHeaderFromHeaders(details.responseHeaders, 'content-disposition'));
|
||||
return (cdHeader && /^attachment/i.test(cdHeader.value));
|
||||
var cdHeader =
|
||||
details.responseHeaders &&
|
||||
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.
|
||||
*/
|
||||
function isPdfFile(details) {
|
||||
var header = getHeaderFromHeaders(details.responseHeaders, 'content-type');
|
||||
var header = getHeaderFromHeaders(details.responseHeaders, "content-type");
|
||||
if (header) {
|
||||
var headerValue = header.value.toLowerCase().split(';', 1)[0].trim();
|
||||
if (headerValue === 'application/pdf') {
|
||||
var headerValue = header.value
|
||||
.toLowerCase()
|
||||
.split(";", 1)[0]
|
||||
.trim();
|
||||
if (headerValue === "application/pdf") {
|
||||
return true;
|
||||
}
|
||||
if (headerValue === 'application/octet-stream') {
|
||||
if (details.url.toLowerCase().indexOf('.pdf') > 0) {
|
||||
if (headerValue === "application/octet-stream") {
|
||||
if (details.url.toLowerCase().indexOf(".pdf") > 0) {
|
||||
return true;
|
||||
}
|
||||
var cdHeader =
|
||||
getHeaderFromHeaders(details.responseHeaders, 'content-disposition');
|
||||
var cdHeader = getHeaderFromHeaders(
|
||||
details.responseHeaders,
|
||||
"content-disposition"
|
||||
);
|
||||
if (cdHeader && /\.pdf(["']|$)/i.test(cdHeader.value)) {
|
||||
return true;
|
||||
}
|
||||
@ -101,21 +107,21 @@ function isPdfFile(details) {
|
||||
*/
|
||||
function getHeadersWithContentDispositionAttachment(details) {
|
||||
var headers = details.responseHeaders;
|
||||
var cdHeader = getHeaderFromHeaders(headers, 'content-disposition');
|
||||
var cdHeader = getHeaderFromHeaders(headers, "content-disposition");
|
||||
if (!cdHeader) {
|
||||
cdHeader = { name: 'Content-Disposition', };
|
||||
cdHeader = { name: "Content-Disposition" };
|
||||
headers.push(cdHeader);
|
||||
}
|
||||
if (!/^attachment/i.test(cdHeader.value)) {
|
||||
cdHeader.value = 'attachment' + cdHeader.value.replace(/^[^;]+/i, '');
|
||||
return { responseHeaders: headers, };
|
||||
cdHeader.value = "attachment" + cdHeader.value.replace(/^[^;]+/i, "");
|
||||
return { responseHeaders: headers };
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
chrome.webRequest.onHeadersReceived.addListener(
|
||||
function(details) {
|
||||
if (details.method !== 'GET') {
|
||||
if (details.method !== "GET") {
|
||||
// Don't intercept POST requests until http://crbug.com/104058 is fixed.
|
||||
return undefined;
|
||||
}
|
||||
@ -132,15 +138,14 @@ chrome.webRequest.onHeadersReceived.addListener(
|
||||
// Implemented in preserve-referer.js
|
||||
saveReferer(details);
|
||||
|
||||
return { redirectUrl: viewerUrl, };
|
||||
return { redirectUrl: viewerUrl };
|
||||
},
|
||||
{
|
||||
urls: [
|
||||
'<all_urls>'
|
||||
],
|
||||
types: ['main_frame', 'sub_frame'],
|
||||
urls: ["<all_urls>"],
|
||||
types: ["main_frame", "sub_frame"],
|
||||
},
|
||||
['blocking', 'responseHeaders']);
|
||||
["blocking", "responseHeaders"]
|
||||
);
|
||||
|
||||
chrome.webRequest.onBeforeRequest.addListener(
|
||||
function(details) {
|
||||
@ -150,26 +155,26 @@ chrome.webRequest.onBeforeRequest.addListener(
|
||||
|
||||
var viewerUrl = getViewerURL(details.url);
|
||||
|
||||
return { redirectUrl: viewerUrl, };
|
||||
return { redirectUrl: viewerUrl };
|
||||
},
|
||||
{
|
||||
urls: [
|
||||
'file://*/*.pdf',
|
||||
'file://*/*.PDF',
|
||||
...(
|
||||
// Duck-typing: MediaError.prototype.message was added in Chrome 59.
|
||||
MediaError.prototype.hasOwnProperty('message') ? [] :
|
||||
[
|
||||
"file://*/*.pdf",
|
||||
"file://*/*.PDF",
|
||||
...// Duck-typing: MediaError.prototype.message was added in Chrome 59.
|
||||
(MediaError.prototype.hasOwnProperty("message")
|
||||
? []
|
||||
: [
|
||||
// Note: Chrome 59 has disabled ftp resource loading by default:
|
||||
// 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) {
|
||||
if (isAllowedAccess) {
|
||||
@ -180,29 +185,35 @@ chrome.extension.isAllowedFileSchemeAccess(function(isAllowedAccess) {
|
||||
// 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
|
||||
// user to activate file permissions.
|
||||
chrome.webNavigation.onBeforeNavigate.addListener(function(details) {
|
||||
chrome.webNavigation.onBeforeNavigate.addListener(
|
||||
function(details) {
|
||||
if (details.frameId === 0 && !isPdfDownloadable(details)) {
|
||||
chrome.tabs.update(details.tabId, {
|
||||
url: getViewerURL(details.url),
|
||||
});
|
||||
}
|
||||
}, {
|
||||
url: [{
|
||||
urlPrefix: 'file://',
|
||||
pathSuffix: '.pdf',
|
||||
}, {
|
||||
urlPrefix: 'file://',
|
||||
pathSuffix: '.PDF',
|
||||
}],
|
||||
});
|
||||
},
|
||||
{
|
||||
url: [
|
||||
{
|
||||
urlPrefix: "file://",
|
||||
pathSuffix: ".pdf",
|
||||
},
|
||||
{
|
||||
urlPrefix: "file://",
|
||||
pathSuffix: ".PDF",
|
||||
},
|
||||
],
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
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
|
||||
// sensitive (local) file in a frame.
|
||||
if (!sender.tab) {
|
||||
sendResponse('');
|
||||
sendResponse("");
|
||||
return undefined;
|
||||
}
|
||||
// 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.
|
||||
var parentUrl = sender.tab.url;
|
||||
if (!parentUrl) {
|
||||
sendResponse('');
|
||||
sendResponse("");
|
||||
return undefined;
|
||||
}
|
||||
if (parentUrl.lastIndexOf('file:', 0) === 0) {
|
||||
sendResponse('file://');
|
||||
if (parentUrl.lastIndexOf("file:", 0) === 0) {
|
||||
sendResponse("file://");
|
||||
return undefined;
|
||||
}
|
||||
// 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);
|
||||
return true;
|
||||
}
|
||||
if (message && message.action === 'isAllowedFileSchemeAccess') {
|
||||
if (message && message.action === "isAllowedFileSchemeAccess") {
|
||||
chrome.extension.isAllowedFileSchemeAccess(sendResponse);
|
||||
return true;
|
||||
}
|
||||
if (message && message.action === 'openExtensionsPageForFileAccess') {
|
||||
var url = 'chrome://extensions/?id=' + chrome.runtime.id;
|
||||
if (message && message.action === "openExtensionsPageForFileAccess") {
|
||||
var url = "chrome://extensions/?id=" + chrome.runtime.id;
|
||||
if (message.data.newTab) {
|
||||
chrome.tabs.create({
|
||||
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
|
||||
chrome.storage.local.remove([
|
||||
'featureDetectLastUA',
|
||||
'webRequestRedirectUrl',
|
||||
'extensionSupportsFTP',
|
||||
"featureDetectLastUA",
|
||||
"webRequestRedirectUrl",
|
||||
"extensionSupportsFTP",
|
||||
]);
|
||||
|
@ -15,7 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
/* import-globals-from pdfHandler.js */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
/**
|
||||
* This file is one part of the Referer persistency implementation. The other
|
||||
* part resides in chromecom.js.
|
||||
@ -45,21 +45,25 @@ var extraInfoSpecWithHeaders; // = ['requestHeaders', 'extraHeaders']
|
||||
|
||||
(function() {
|
||||
var requestFilter = {
|
||||
urls: ['*://*/*'],
|
||||
types: ['main_frame', 'sub_frame'],
|
||||
urls: ["*://*/*"],
|
||||
types: ["main_frame", "sub_frame"],
|
||||
};
|
||||
function registerListener(extraInfoSpec) {
|
||||
extraInfoSpecWithHeaders = extraInfoSpec;
|
||||
// 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;
|
||||
}, requestFilter, extraInfoSpec);
|
||||
},
|
||||
requestFilter,
|
||||
extraInfoSpec
|
||||
);
|
||||
}
|
||||
try {
|
||||
registerListener(['requestHeaders', 'extraHeaders']);
|
||||
registerListener(["requestHeaders", "extraHeaders"]);
|
||||
} catch (e) {
|
||||
// "extraHeaders" is not supported in Chrome 71 and earlier.
|
||||
registerListener(['requestHeaders']);
|
||||
registerListener(["requestHeaders"]);
|
||||
}
|
||||
chrome.webRequest.onBeforeRedirect.addListener(forgetHeaders, requestFilter);
|
||||
chrome.webRequest.onCompleted.addListener(forgetHeaders, requestFilter);
|
||||
@ -73,9 +77,10 @@ var extraInfoSpecWithHeaders; // = ['requestHeaders', 'extraHeaders']
|
||||
* @param {object} details - onHeadersReceived event data.
|
||||
*/
|
||||
function saveReferer(details) {
|
||||
var referer = g_requestHeaders[details.requestId] &&
|
||||
getHeaderFromHeaders(g_requestHeaders[details.requestId], 'referer');
|
||||
referer = referer && referer.value || '';
|
||||
var referer =
|
||||
g_requestHeaders[details.requestId] &&
|
||||
getHeaderFromHeaders(g_requestHeaders[details.requestId], "referer");
|
||||
referer = (referer && referer.value) || "";
|
||||
if (!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
|
||||
// handler is removed as soon as the PDF viewer frame is unloaded.
|
||||
chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
||||
if (port.name !== 'chromecom-referrer') {
|
||||
if (port.name !== "chromecom-referrer") {
|
||||
return;
|
||||
}
|
||||
// Note: sender.frameId is only set in Chrome 41+.
|
||||
if (!('frameId' in port.sender)) {
|
||||
if (!("frameId" in port.sender)) {
|
||||
port.disconnect();
|
||||
return;
|
||||
}
|
||||
@ -102,7 +107,7 @@ chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
||||
var frameId = port.sender.frameId;
|
||||
|
||||
// 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) {
|
||||
// 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
|
||||
@ -113,11 +118,15 @@ chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
||||
chrome.webRequest.onBeforeSendHeaders.removeListener(onBeforeSendHeaders);
|
||||
if (referer) {
|
||||
// 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],
|
||||
types: ['xmlhttprequest'],
|
||||
types: ["xmlhttprequest"],
|
||||
tabId: tabId,
|
||||
}, ['blocking', ...extraInfoSpecWithHeaders]);
|
||||
},
|
||||
["blocking", ...extraInfoSpecWithHeaders]
|
||||
);
|
||||
}
|
||||
// Acknowledge the message, and include the latest referer for this frame.
|
||||
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;
|
||||
// This is a work-around for https://crbug.com/784528
|
||||
chrome.webRequest.onHeadersReceived.addListener(exposeOnHeadersReceived, {
|
||||
urls: ['https://*/*'],
|
||||
types: ['xmlhttprequest'],
|
||||
chrome.webRequest.onHeadersReceived.addListener(
|
||||
exposeOnHeadersReceived,
|
||||
{
|
||||
urls: ["https://*/*"],
|
||||
types: ["xmlhttprequest"],
|
||||
tabId: tabId,
|
||||
}, ['blocking', 'responseHeaders']);
|
||||
},
|
||||
["blocking", "responseHeaders"]
|
||||
);
|
||||
|
||||
function onBeforeSendHeaders(details) {
|
||||
if (details.frameId !== frameId) {
|
||||
return undefined;
|
||||
}
|
||||
var headers = details.requestHeaders;
|
||||
var refererHeader = getHeaderFromHeaders(headers, 'referer');
|
||||
var refererHeader = getHeaderFromHeaders(headers, "referer");
|
||||
if (!refererHeader) {
|
||||
refererHeader = { name: 'Referer', };
|
||||
refererHeader = { name: "Referer" };
|
||||
headers.push(refererHeader);
|
||||
} else if (refererHeader.value &&
|
||||
refererHeader.value.lastIndexOf('chrome-extension:', 0) !== 0) {
|
||||
} else if (
|
||||
refererHeader.value &&
|
||||
refererHeader.value.lastIndexOf("chrome-extension:", 0) !== 0
|
||||
) {
|
||||
// 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.
|
||||
return undefined;
|
||||
}
|
||||
refererHeader.value = referer;
|
||||
return { requestHeaders: headers, };
|
||||
return { requestHeaders: headers };
|
||||
}
|
||||
|
||||
function exposeOnHeadersReceived(details) {
|
||||
@ -164,16 +179,16 @@ chrome.runtime.onConnect.addListener(function onReceivePort(port) {
|
||||
return undefined;
|
||||
}
|
||||
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
|
||||
var acehValue =
|
||||
'accept-ranges,content-encoding,content-length,content-disposition';
|
||||
"accept-ranges,content-encoding,content-length,content-disposition";
|
||||
if (aceh) {
|
||||
aceh.value += ',' + acehValue;
|
||||
aceh.value += "," + acehValue;
|
||||
} else {
|
||||
aceh = { name: 'Access-Control-Expose-Headers', value: acehValue, };
|
||||
aceh = { name: "Access-Control-Expose-Headers", value: acehValue };
|
||||
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
|
||||
* - restoretab.html (this script) restores the URL and history state.
|
||||
*/
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var url = decodeURIComponent(location.search.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);
|
||||
location.reload();
|
||||
|
@ -14,13 +14,13 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
// 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
|
||||
// is quite disruptive (crbug.com/511670).
|
||||
chrome.runtime.onUpdateAvailable.addListener(function() {
|
||||
if (chrome.extension.getViews({ type: 'tab', }).length === 0) {
|
||||
if (chrome.extension.getViews({ type: "tab" }).length === 0) {
|
||||
chrome.runtime.reload();
|
||||
}
|
||||
});
|
||||
|
@ -16,19 +16,19 @@ limitations under the License.
|
||||
/* eslint strict: ["error", "function"] */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
"use strict";
|
||||
// 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
|
||||
// future extension updates.
|
||||
//
|
||||
// The source code for the server is available at:
|
||||
// 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
|
||||
// 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.
|
||||
var MINIMUM_TIME_BETWEEN_PING = 12 * 36E5;
|
||||
var MINIMUM_TIME_BETWEEN_PING = 12 * 36e5;
|
||||
|
||||
if (chrome.extension.inIncognitoContext) {
|
||||
// The extension uses incognito split mode, so there are two background
|
||||
@ -36,14 +36,14 @@ limitations under the License.
|
||||
return;
|
||||
}
|
||||
|
||||
if (chrome.runtime.id !== 'oemmndcbldboiebfnladdacbdfmadadm') {
|
||||
if (chrome.runtime.id !== "oemmndcbldboiebfnladdacbdfmadadm") {
|
||||
// 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;
|
||||
}
|
||||
|
||||
maybeSendPing();
|
||||
setInterval(maybeSendPing, 36E5);
|
||||
setInterval(maybeSendPing, 36e5);
|
||||
|
||||
function maybeSendPing() {
|
||||
getLoggingPref(function(didOptOut) {
|
||||
@ -70,28 +70,28 @@ limitations under the License.
|
||||
|
||||
var deduplication_id = getDeduplicationId(wasUpdated);
|
||||
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
|
||||
// feature-detection method detects Chrome 43+).
|
||||
// Unlike XMLHttpRequest, fetch omits credentials such as cookies in the
|
||||
// requests, which guarantees that the server cannot track the client
|
||||
// via HTTP cookies.
|
||||
fetch(LOG_URL, {
|
||||
method: 'POST',
|
||||
method: "POST",
|
||||
headers: new Headers({
|
||||
'Deduplication-Id': deduplication_id,
|
||||
'Extension-Version': extension_version,
|
||||
"Deduplication-Id": deduplication_id,
|
||||
"Extension-Version": extension_version,
|
||||
}),
|
||||
// Set mode=cors so that the above custom headers are included in the
|
||||
// request.
|
||||
mode: 'cors',
|
||||
mode: "cors",
|
||||
});
|
||||
return;
|
||||
}
|
||||
var x = new XMLHttpRequest();
|
||||
x.open('POST', LOG_URL);
|
||||
x.setRequestHeader('Deduplication-Id', deduplication_id);
|
||||
x.setRequestHeader('Extension-Version', extension_version);
|
||||
x.open("POST", LOG_URL);
|
||||
x.setRequestHeader("Deduplication-Id", deduplication_id);
|
||||
x.setRequestHeader("Extension-Version", extension_version);
|
||||
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
|
||||
// ID, the server cannot track users for a long period even if it wants to.
|
||||
if (!id || !/^[0-9a-f]{10}$/.test(id) || wasUpdated) {
|
||||
id = '';
|
||||
id = "";
|
||||
var buf = new Uint8Array(5);
|
||||
crypto.getRandomValues(buf);
|
||||
for (var i = 0; i < buf.length; ++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;
|
||||
}
|
||||
@ -139,12 +139,12 @@ limitations under the License.
|
||||
*/
|
||||
function getLoggingPref(callback) {
|
||||
// Try to look up the preference in the storage, in the following order:
|
||||
var areas = ['sync', 'local', 'managed'];
|
||||
var areas = ["sync", "local", "managed"];
|
||||
|
||||
next();
|
||||
function next(result) {
|
||||
var storageAreaName = areas.shift();
|
||||
if (typeof result === 'boolean' || !storageAreaName) {
|
||||
if (typeof result === "boolean" || !storageAreaName) {
|
||||
callback(result);
|
||||
return;
|
||||
}
|
||||
@ -154,7 +154,7 @@ limitations under the License.
|
||||
return;
|
||||
}
|
||||
|
||||
chrome.storage[storageAreaName].get('disableTelemetry', function(items) {
|
||||
chrome.storage[storageAreaName].get("disableTelemetry", function(items) {
|
||||
next(items && items.disableTelemetry);
|
||||
});
|
||||
}
|
||||
|
@ -126,6 +126,6 @@
|
||||
},
|
||||
|
||||
// translate an element or document fragment
|
||||
translate: translateFragment
|
||||
translate: translateFragment,
|
||||
};
|
||||
})(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'),
|
||||
path = require('path'),
|
||||
vm = require('vm');
|
||||
var fs = require("fs"),
|
||||
path = require("path"),
|
||||
vm = require("vm");
|
||||
|
||||
/**
|
||||
* A simple preprocessor that is based on the Firefox preprocessor
|
||||
@ -34,9 +34,12 @@ var fs = require('fs'),
|
||||
*/
|
||||
function preprocess(inFilename, outFilename, defines) {
|
||||
// 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 out = '';
|
||||
var out = "";
|
||||
var i = 0;
|
||||
function readLine() {
|
||||
if (i < totalLines) {
|
||||
@ -44,19 +47,29 @@ function preprocess(inFilename, outFilename, defines) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
var writeLine = (typeof outFilename === 'function' ? outFilename :
|
||||
function(line) {
|
||||
out += line + '\n';
|
||||
});
|
||||
var writeLine =
|
||||
typeof outFilename === "function"
|
||||
? outFilename
|
||||
: function(line) {
|
||||
out += line + "\n";
|
||||
};
|
||||
function evaluateCondition(code) {
|
||||
if (!code || !code.trim()) {
|
||||
throw new Error('No JavaScript expression given at ' + loc());
|
||||
throw new Error("No JavaScript expression given at " + loc());
|
||||
}
|
||||
try {
|
||||
return vm.runInNewContext(code, defines, { displayErrors: false, });
|
||||
return vm.runInNewContext(code, defines, { displayErrors: false });
|
||||
} catch (e) {
|
||||
throw new Error('Could not evaluate "' + code + '" at ' + loc() + '\n' +
|
||||
e.name + ': ' + e.message);
|
||||
throw new Error(
|
||||
'Could not evaluate "' +
|
||||
code +
|
||||
'" at ' +
|
||||
loc() +
|
||||
"\n" +
|
||||
e.name +
|
||||
": " +
|
||||
e.message
|
||||
);
|
||||
}
|
||||
}
|
||||
function include(file) {
|
||||
@ -64,15 +77,18 @@ function preprocess(inFilename, outFilename, defines) {
|
||||
var dir = path.dirname(realPath);
|
||||
try {
|
||||
var fullpath;
|
||||
if (file.indexOf('$ROOT/') === 0) {
|
||||
fullpath = path.join(__dirname, '../..',
|
||||
file.substring('$ROOT/'.length));
|
||||
if (file.indexOf("$ROOT/") === 0) {
|
||||
fullpath = path.join(
|
||||
__dirname,
|
||||
"../..",
|
||||
file.substring("$ROOT/".length)
|
||||
);
|
||||
} else {
|
||||
fullpath = path.join(dir, file);
|
||||
}
|
||||
preprocess(fullpath, writeLine, defines);
|
||||
} catch (e) {
|
||||
if (e.code === 'ENOENT') {
|
||||
if (e.code === "ENOENT") {
|
||||
throw new Error('Failed to include "' + file + '" at ' + loc());
|
||||
}
|
||||
throw e; // Some other error
|
||||
@ -84,7 +100,7 @@ function preprocess(inFilename, outFilename, defines) {
|
||||
if (variable in defines) {
|
||||
return defines[variable];
|
||||
}
|
||||
return '';
|
||||
return "";
|
||||
});
|
||||
writeLine(line);
|
||||
}
|
||||
@ -104,104 +120,107 @@ function preprocess(inFilename, outFilename, defines) {
|
||||
var line;
|
||||
var state = STATE_NONE;
|
||||
var stack = [];
|
||||
var control = // eslint-disable-next-line max-len
|
||||
/^(?:\/\/|<!--)\s*#(if|elif|else|endif|expand|include|error)\b(?:\s+(.*?)(?:-->)?$)?/;
|
||||
var control = /^(?:\/\/|<!--)\s*#(if|elif|else|endif|expand|include|error)\b(?:\s+(.*?)(?:-->)?$)?/; // eslint-disable-next-line max-len
|
||||
var lineNumber = 0;
|
||||
var loc = function() {
|
||||
return fs.realpathSync(inFilename) + ':' + lineNumber;
|
||||
return fs.realpathSync(inFilename) + ":" + lineNumber;
|
||||
};
|
||||
while ((line = readLine()) !== null) {
|
||||
++lineNumber;
|
||||
var m = control.exec(line);
|
||||
if (m) {
|
||||
switch (m[1]) {
|
||||
case 'if':
|
||||
case "if":
|
||||
stack.push(state);
|
||||
state = evaluateCondition(m[2]) ? STATE_IF_TRUE : STATE_IF_FALSE;
|
||||
break;
|
||||
case 'elif':
|
||||
case "elif":
|
||||
if (state === STATE_IF_TRUE || state === STATE_ELSE_FALSE) {
|
||||
state = STATE_ELSE_FALSE;
|
||||
} else if (state === STATE_IF_FALSE) {
|
||||
state = evaluateCondition(m[2]) ? STATE_IF_TRUE : STATE_IF_FALSE;
|
||||
} 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 {
|
||||
throw new Error('Found #elif without matching #if at ' + loc());
|
||||
throw new Error("Found #elif without matching #if at " + loc());
|
||||
}
|
||||
break;
|
||||
case 'else':
|
||||
case "else":
|
||||
if (state === STATE_IF_TRUE || state === STATE_ELSE_FALSE) {
|
||||
state = STATE_ELSE_FALSE;
|
||||
} else if (state === STATE_IF_FALSE) {
|
||||
state = STATE_ELSE_TRUE;
|
||||
} else {
|
||||
throw new Error('Found #else without matching #if at ' + loc());
|
||||
throw new Error("Found #else without matching #if at " + loc());
|
||||
}
|
||||
break;
|
||||
case 'endif':
|
||||
case "endif":
|
||||
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();
|
||||
break;
|
||||
case 'expand':
|
||||
case "expand":
|
||||
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
||||
expand(m[2]);
|
||||
}
|
||||
break;
|
||||
case 'include':
|
||||
case "include":
|
||||
if (state !== STATE_IF_FALSE && state !== STATE_ELSE_FALSE) {
|
||||
include(m[2]);
|
||||
}
|
||||
break;
|
||||
case 'error':
|
||||
case "error":
|
||||
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;
|
||||
}
|
||||
} else {
|
||||
if (state === STATE_NONE) {
|
||||
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_ELSE_FALSE)) {
|
||||
writeLine(line.replace(/^\/\/|^<!--|-->$/g, ' '));
|
||||
!stack.includes(STATE_ELSE_FALSE)
|
||||
) {
|
||||
writeLine(line.replace(/^\/\/|^<!--|-->$/g, " "));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (state !== STATE_NONE || stack.length !== 0) {
|
||||
throw new Error('Missing #endif in preprocessor for ' +
|
||||
fs.realpathSync(inFilename));
|
||||
throw new Error(
|
||||
"Missing #endif in preprocessor for " + fs.realpathSync(inFilename)
|
||||
);
|
||||
}
|
||||
if (typeof outFilename !== 'function') {
|
||||
if (typeof outFilename !== "function") {
|
||||
fs.writeFileSync(outFilename, out);
|
||||
}
|
||||
}
|
||||
exports.preprocess = preprocess;
|
||||
|
||||
var deprecatedInMozcentral = new RegExp('(^|\\W)(' + [
|
||||
'-moz-box-sizing',
|
||||
'-moz-grab',
|
||||
'-moz-grabbing'
|
||||
].join('|') + ')');
|
||||
var deprecatedInMozcentral = new RegExp(
|
||||
"(^|\\W)(" + ["-moz-box-sizing", "-moz-grab", "-moz-grabbing"].join("|") + ")"
|
||||
);
|
||||
|
||||
function preprocessCSS(mode, source, destination) {
|
||||
function hasPrefixedFirefox(line) {
|
||||
return (/(^|\W)-(ms|o|webkit)-\w/.test(line));
|
||||
return /(^|\W)-(ms|o|webkit)-\w/.test(line);
|
||||
}
|
||||
|
||||
function hasPrefixedMozcentral(line) {
|
||||
return (/(^|\W)-(ms|o|webkit)-\w/.test(line) ||
|
||||
deprecatedInMozcentral.test(line));
|
||||
return (
|
||||
/(^|\W)-(ms|o|webkit)-\w/.test(line) || deprecatedInMozcentral.test(line)
|
||||
);
|
||||
}
|
||||
|
||||
function expandImports(content, baseUrl) {
|
||||
return content.replace(/^\s*@import\s+url\(([^\)]+)\);\s*$/gm,
|
||||
function(all, url) {
|
||||
return content.replace(/^\s*@import\s+url\(([^\)]+)\);\s*$/gm, function(
|
||||
all,
|
||||
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);
|
||||
});
|
||||
}
|
||||
@ -221,9 +240,9 @@ function preprocessCSS(mode, source, destination) {
|
||||
while (j < lines.length && bracketLevel > 0) {
|
||||
var checkBracket = /([{}])\s*$/.exec(lines[j]);
|
||||
if (checkBracket) {
|
||||
if (checkBracket[1] === '{') {
|
||||
if (checkBracket[1] === "{") {
|
||||
bracketLevel++;
|
||||
} else if (!lines[j].includes('{')) {
|
||||
} else if (!lines[j].includes("{")) {
|
||||
bracketLevel--;
|
||||
}
|
||||
}
|
||||
@ -236,30 +255,34 @@ function preprocessCSS(mode, source, destination) {
|
||||
// multiline? skipping until next directive or bracket
|
||||
do {
|
||||
lines.splice(i, 1);
|
||||
} while (i < lines.length &&
|
||||
} while (
|
||||
i < lines.length &&
|
||||
!/\}\s*$/.test(lines[i]) &&
|
||||
!lines[i].includes(':'));
|
||||
!lines[i].includes(":")
|
||||
);
|
||||
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
|
||||
while (lines[i] === '' && lines[i - 1] === '') {
|
||||
while (lines[i] === "" && lines[i - 1] === "") {
|
||||
lines.splice(i, 1);
|
||||
}
|
||||
}
|
||||
return lines.join('\n');
|
||||
return lines.join("\n");
|
||||
}
|
||||
|
||||
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);
|
||||
if (mode === 'mozcentral' || mode === 'firefox') {
|
||||
content = removePrefixed(content, mode === 'mozcentral' ?
|
||||
hasPrefixedMozcentral : hasPrefixedFirefox);
|
||||
if (mode === "mozcentral" || mode === "firefox") {
|
||||
content = removePrefixed(
|
||||
content,
|
||||
mode === "mozcentral" ? hasPrefixedMozcentral : hasPrefixedFirefox
|
||||
);
|
||||
}
|
||||
fs.writeFileSync(destination, content);
|
||||
}
|
||||
|
236
external/builder/preprocessor2.js
vendored
236
external/builder/preprocessor2.js
vendored
@ -1,103 +1,117 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var acorn = require('acorn');
|
||||
var escodegen = require('escodegen');
|
||||
var vm = require('vm');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var acorn = require("acorn");
|
||||
var escodegen = require("escodegen");
|
||||
var vm = require("vm");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var PDFJS_PREPROCESSOR_NAME = 'PDFJSDev';
|
||||
var ROOT_PREFIX = '$ROOT/';
|
||||
var PDFJS_PREPROCESSOR_NAME = "PDFJSDev";
|
||||
var ROOT_PREFIX = "$ROOT/";
|
||||
|
||||
function isLiteral(obj, value) {
|
||||
return obj.type === 'Literal' && obj.value === value;
|
||||
return obj.type === "Literal" && obj.value === value;
|
||||
}
|
||||
|
||||
function isPDFJSPreprocessor(obj) {
|
||||
return obj.type === 'Identifier' &&
|
||||
obj.name === PDFJS_PREPROCESSOR_NAME;
|
||||
return obj.type === "Identifier" && obj.name === PDFJS_PREPROCESSOR_NAME;
|
||||
}
|
||||
|
||||
function evalWithDefines(code, defines, loc) {
|
||||
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) {
|
||||
try {
|
||||
var arg;
|
||||
switch (actionName) {
|
||||
case 'test':
|
||||
case "test":
|
||||
arg = args[0];
|
||||
if (!arg || arg.type !== 'Literal' ||
|
||||
typeof arg.value !== 'string') {
|
||||
throw new Error('No code for testing is given');
|
||||
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
|
||||
throw new Error("No code for testing is given");
|
||||
}
|
||||
var isTrue = !!evalWithDefines(arg.value, ctx.defines);
|
||||
return { type: 'Literal', value: isTrue, loc: loc, };
|
||||
case 'eval':
|
||||
return { type: "Literal", value: isTrue, loc: loc };
|
||||
case "eval":
|
||||
arg = args[0];
|
||||
if (!arg || arg.type !== 'Literal' ||
|
||||
typeof arg.value !== 'string') {
|
||||
throw new Error('No code for eval is given');
|
||||
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
|
||||
throw new Error("No code for eval is given");
|
||||
}
|
||||
var result = evalWithDefines(arg.value, ctx.defines);
|
||||
if (typeof result === 'boolean' || typeof result === 'string' ||
|
||||
typeof result === 'number') {
|
||||
return { type: 'Literal', value: result, loc: loc, };
|
||||
if (
|
||||
typeof result === "boolean" ||
|
||||
typeof result === "string" ||
|
||||
typeof result === "number"
|
||||
) {
|
||||
return { type: "Literal", value: result, loc: loc };
|
||||
}
|
||||
if (typeof result === 'object') {
|
||||
var parsedObj = acorn.parse('(' + JSON.stringify(result) + ')');
|
||||
if (typeof result === "object") {
|
||||
var parsedObj = acorn.parse("(" + JSON.stringify(result) + ")");
|
||||
parsedObj.body[0].expression.loc = loc;
|
||||
return parsedObj.body[0].expression;
|
||||
}
|
||||
break;
|
||||
case 'json':
|
||||
case "json":
|
||||
arg = args[0];
|
||||
if (!arg || arg.type !== 'Literal' ||
|
||||
typeof arg.value !== 'string') {
|
||||
throw new Error('Path to JSON is not provided');
|
||||
if (!arg || arg.type !== "Literal" || typeof arg.value !== "string") {
|
||||
throw new Error("Path to JSON is not provided");
|
||||
}
|
||||
var jsonPath = arg.value;
|
||||
if (jsonPath.indexOf(ROOT_PREFIX) === 0) {
|
||||
jsonPath = path.join(ctx.rootPath,
|
||||
jsonPath.substring(ROOT_PREFIX.length));
|
||||
jsonPath = path.join(
|
||||
ctx.rootPath,
|
||||
jsonPath.substring(ROOT_PREFIX.length)
|
||||
);
|
||||
}
|
||||
var jsonContent = fs.readFileSync(jsonPath).toString();
|
||||
var parsedJSON = acorn.parse('(' + jsonContent + ')');
|
||||
var parsedJSON = acorn.parse("(" + jsonContent + ")");
|
||||
parsedJSON.body[0].expression.loc = loc;
|
||||
return parsedJSON.body[0].expression;
|
||||
}
|
||||
throw new Error('Unsupported action');
|
||||
throw new Error("Unsupported action");
|
||||
} catch (e) {
|
||||
throw new Error('Could not process ' + PDFJS_PREPROCESSOR_NAME + '.' +
|
||||
actionName + ' at ' + JSON.stringify(loc) + '\n' +
|
||||
e.name + ': ' + e.message);
|
||||
throw new Error(
|
||||
"Could not process " +
|
||||
PDFJS_PREPROCESSOR_NAME +
|
||||
"." +
|
||||
actionName +
|
||||
" at " +
|
||||
JSON.stringify(loc) +
|
||||
"\n" +
|
||||
e.name +
|
||||
": " +
|
||||
e.message
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function postprocessNode(ctx, node) {
|
||||
switch (node.type) {
|
||||
case 'ExportNamedDeclaration':
|
||||
case 'ImportDeclaration':
|
||||
if (node.source && node.source.type === 'Literal' &&
|
||||
ctx.map && ctx.map[node.source.value]) {
|
||||
case "ExportNamedDeclaration":
|
||||
case "ImportDeclaration":
|
||||
if (
|
||||
node.source &&
|
||||
node.source.type === "Literal" &&
|
||||
ctx.map &&
|
||||
ctx.map[node.source.value]
|
||||
) {
|
||||
var newValue = ctx.map[node.source.value];
|
||||
node.source.value = node.source.raw = newValue;
|
||||
}
|
||||
break;
|
||||
case 'IfStatement':
|
||||
case "IfStatement":
|
||||
if (isLiteral(node.test, true)) {
|
||||
// if (true) stmt1; => stmt1
|
||||
return node.consequent;
|
||||
} else if (isLiteral(node.test, false)) {
|
||||
// if (false) stmt1; else stmt2; => stmt2
|
||||
return node.alternate || { type: 'EmptyStatement', loc: node.loc, };
|
||||
return node.alternate || { type: "EmptyStatement", loc: node.loc };
|
||||
}
|
||||
break;
|
||||
case 'ConditionalExpression':
|
||||
case "ConditionalExpression":
|
||||
if (isLiteral(node.test, true)) {
|
||||
// true ? stmt1 : stmt2 => stmt1
|
||||
return node.consequent;
|
||||
@ -106,22 +120,23 @@ function postprocessNode(ctx, node) {
|
||||
return node.alternate;
|
||||
}
|
||||
break;
|
||||
case 'UnaryExpression':
|
||||
if (node.operator === 'typeof' &&
|
||||
isPDFJSPreprocessor(node.argument)) {
|
||||
case "UnaryExpression":
|
||||
if (node.operator === "typeof" && isPDFJSPreprocessor(node.argument)) {
|
||||
// typeof PDFJSDev => 'object'
|
||||
return { type: 'Literal', value: 'object', loc: node.loc, };
|
||||
return { type: "Literal", value: "object", loc: node.loc };
|
||||
}
|
||||
if (node.operator === '!' &&
|
||||
node.argument.type === 'Literal' &&
|
||||
typeof node.argument.value === 'boolean') {
|
||||
if (
|
||||
node.operator === "!" &&
|
||||
node.argument.type === "Literal" &&
|
||||
typeof node.argument.value === "boolean"
|
||||
) {
|
||||
// !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;
|
||||
case 'LogicalExpression':
|
||||
case "LogicalExpression":
|
||||
switch (node.operator) {
|
||||
case '&&':
|
||||
case "&&":
|
||||
if (isLiteral(node.left, true)) {
|
||||
return node.right;
|
||||
}
|
||||
@ -129,7 +144,7 @@ function postprocessNode(ctx, node) {
|
||||
return node.left;
|
||||
}
|
||||
break;
|
||||
case '||':
|
||||
case "||":
|
||||
if (isLiteral(node.left, true)) {
|
||||
return node.left;
|
||||
}
|
||||
@ -139,24 +154,26 @@ function postprocessNode(ctx, node) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'BinaryExpression':
|
||||
case "BinaryExpression":
|
||||
switch (node.operator) {
|
||||
case '==':
|
||||
case '===':
|
||||
case '!=':
|
||||
case '!==':
|
||||
if (node.left.type === 'Literal' &&
|
||||
node.right.type === 'Literal' &&
|
||||
typeof node.left.value === typeof node.right.value) {
|
||||
case "==":
|
||||
case "===":
|
||||
case "!=":
|
||||
case "!==":
|
||||
if (
|
||||
node.left.type === "Literal" &&
|
||||
node.right.type === "Literal" &&
|
||||
typeof node.left.value === typeof node.right.value
|
||||
) {
|
||||
// folding two literals == and != check
|
||||
switch (typeof node.left.value) {
|
||||
case 'string':
|
||||
case 'boolean':
|
||||
case 'number':
|
||||
case "string":
|
||||
case "boolean":
|
||||
case "number":
|
||||
var equal = node.left.value === node.right.value;
|
||||
return {
|
||||
type: 'Literal',
|
||||
value: (node.operator[0] === '=') === equal,
|
||||
type: "Literal",
|
||||
value: (node.operator[0] === "=") === equal,
|
||||
loc: node.loc,
|
||||
};
|
||||
}
|
||||
@ -164,54 +181,66 @@ function postprocessNode(ctx, node) {
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'CallExpression':
|
||||
if (node.callee.type === 'MemberExpression' &&
|
||||
case "CallExpression":
|
||||
if (
|
||||
node.callee.type === "MemberExpression" &&
|
||||
isPDFJSPreprocessor(node.callee.object) &&
|
||||
node.callee.property.type === 'Identifier') {
|
||||
node.callee.property.type === "Identifier"
|
||||
) {
|
||||
// PDFJSDev.xxxx(arg1, arg2, ...) => transform
|
||||
var action = node.callee.property.name;
|
||||
return handlePreprocessorAction(ctx, action,
|
||||
node.arguments, node.loc);
|
||||
return handlePreprocessorAction(ctx, action, node.arguments, node.loc);
|
||||
}
|
||||
// require('string')
|
||||
if (node.callee.type === 'Identifier' && node.callee.name === 'require' &&
|
||||
node.arguments.length === 1 && node.arguments[0].type === 'Literal' &&
|
||||
ctx.map && ctx.map[node.arguments[0].value]) {
|
||||
if (
|
||||
node.callee.type === "Identifier" &&
|
||||
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];
|
||||
requireName.value = requireName.raw = ctx.map[requireName.value];
|
||||
}
|
||||
break;
|
||||
case 'BlockStatement':
|
||||
case "BlockStatement":
|
||||
var subExpressionIndex = 0;
|
||||
while (subExpressionIndex < node.body.length) {
|
||||
switch (node.body[subExpressionIndex].type) {
|
||||
case 'EmptyStatement':
|
||||
case "EmptyStatement":
|
||||
// Removing empty statements from the blocks.
|
||||
node.body.splice(subExpressionIndex, 1);
|
||||
continue;
|
||||
case 'BlockStatement':
|
||||
case "BlockStatement":
|
||||
// Block statements inside a block are moved to the parent one.
|
||||
var subChildren = node.body[subExpressionIndex].body;
|
||||
Array.prototype.splice.apply(node.body,
|
||||
[subExpressionIndex, 1].concat(subChildren));
|
||||
Array.prototype.splice.apply(
|
||||
node.body,
|
||||
[subExpressionIndex, 1].concat(subChildren)
|
||||
);
|
||||
subExpressionIndex += Math.max(subChildren.length - 1, 0);
|
||||
continue;
|
||||
case 'ReturnStatement':
|
||||
case 'ThrowStatement':
|
||||
case "ReturnStatement":
|
||||
case "ThrowStatement":
|
||||
// Removing dead code after return or throw.
|
||||
node.body.splice(subExpressionIndex + 1,
|
||||
node.body.length - subExpressionIndex - 1);
|
||||
node.body.splice(
|
||||
subExpressionIndex + 1,
|
||||
node.body.length - subExpressionIndex - 1
|
||||
);
|
||||
break;
|
||||
}
|
||||
subExpressionIndex++;
|
||||
}
|
||||
break;
|
||||
case 'FunctionDeclaration':
|
||||
case 'FunctionExpression':
|
||||
case "FunctionDeclaration":
|
||||
case "FunctionExpression":
|
||||
var block = node.body;
|
||||
if (block.body.length > 0 &&
|
||||
block.body[block.body.length - 1].type === 'ReturnStatement' &&
|
||||
!block.body[block.body.length - 1].argument) {
|
||||
if (
|
||||
block.body.length > 0 &&
|
||||
block.body[block.body.length - 1].type === "ReturnStatement" &&
|
||||
!block.body[block.body.length - 1].argument
|
||||
) {
|
||||
// Function body ends with return without arg -- removing it.
|
||||
block.body.pop();
|
||||
}
|
||||
@ -237,14 +266,16 @@ function fixComments(ctx, node) {
|
||||
var type = node.leadingComments[i].type;
|
||||
var value = node.leadingComments[i].value;
|
||||
|
||||
if (ctx.saveComments === 'copyright') {
|
||||
if (ctx.saveComments === "copyright") {
|
||||
// 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);
|
||||
continue;
|
||||
}
|
||||
} else if ((type === 'Block' && BlockCommentRegExp.test(value)) ||
|
||||
(type === 'Line' && LineCommentRegExp.test(value))) {
|
||||
} else if (
|
||||
(type === "Block" && BlockCommentRegExp.test(value)) ||
|
||||
(type === "Line" && LineCommentRegExp.test(value))
|
||||
) {
|
||||
node.leadingComments.splice(i, 1);
|
||||
continue;
|
||||
}
|
||||
@ -257,15 +288,18 @@ function traverseTree(ctx, node) {
|
||||
// generic node processing
|
||||
for (var i in node) {
|
||||
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);
|
||||
if (result !== child) {
|
||||
node[i] = result;
|
||||
}
|
||||
} else if (Array.isArray(child)) {
|
||||
child.forEach(function (childItem, index) {
|
||||
if (typeof childItem === 'object' && childItem !== null &&
|
||||
childItem.type) {
|
||||
child.forEach(function(childItem, index) {
|
||||
if (
|
||||
typeof childItem === "object" &&
|
||||
childItem !== null &&
|
||||
childItem.type
|
||||
) {
|
||||
var result = traverseTree(ctx, childItem);
|
||||
if (result !== childItem) {
|
||||
child[index] = result;
|
||||
@ -284,14 +318,14 @@ function traverseTree(ctx, node) {
|
||||
function preprocessPDFJSCode(ctx, code) {
|
||||
var format = ctx.format || {
|
||||
indent: {
|
||||
style: ' ',
|
||||
style: " ",
|
||||
},
|
||||
};
|
||||
var parseOptions = {
|
||||
ecmaVersion: 8,
|
||||
locations: true,
|
||||
sourceFile: ctx.sourceFile,
|
||||
sourceType: 'module',
|
||||
sourceType: "module",
|
||||
};
|
||||
var codegenOptions = {
|
||||
format: format,
|
||||
|
46
external/builder/test-fixtures.js
vendored
46
external/builder/test-fixtures.js
vendored
@ -1,20 +1,26 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var builder = require('./builder');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var builder = require("./builder");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var errors = 0;
|
||||
|
||||
var baseDir = path.join(__dirname, 'fixtures');
|
||||
var files = fs.readdirSync(baseDir).filter(function (name) {
|
||||
var baseDir = path.join(__dirname, "fixtures");
|
||||
var files = fs
|
||||
.readdirSync(baseDir)
|
||||
.filter(function(name) {
|
||||
return /-expected\./.test(name);
|
||||
}).map(function (name) {
|
||||
})
|
||||
.map(function(name) {
|
||||
return path.join(baseDir, name);
|
||||
});
|
||||
});
|
||||
files.forEach(function(expectationFilename) {
|
||||
var inFilename = expectationFilename.replace('-expected', '');
|
||||
var expectation = fs.readFileSync(expectationFilename).toString().trim()
|
||||
var inFilename = expectationFilename.replace("-expected", "");
|
||||
var expectation = fs
|
||||
.readFileSync(expectationFilename)
|
||||
.toString()
|
||||
.trim()
|
||||
.replace(/__filename/g, fs.realpathSync(inFilename));
|
||||
var outLines = [];
|
||||
|
||||
@ -28,29 +34,29 @@ files.forEach(function(expectationFilename) {
|
||||
var out;
|
||||
try {
|
||||
builder.preprocess(inFilename, outFilename, defines);
|
||||
out = outLines.join('\n').trim();
|
||||
out = outLines.join("\n").trim();
|
||||
} catch (e) {
|
||||
out = ('Error: ' + e.message).replace(/^/gm, '//');
|
||||
out = ("Error: " + e.message).replace(/^/gm, "//");
|
||||
}
|
||||
if (out !== expectation) {
|
||||
errors++;
|
||||
|
||||
console.log('Assertion failed for ' + inFilename);
|
||||
console.log('--------------------------------------------------');
|
||||
console.log('EXPECTED:');
|
||||
console.log("Assertion failed for " + inFilename);
|
||||
console.log("--------------------------------------------------");
|
||||
console.log("EXPECTED:");
|
||||
console.log(expectation);
|
||||
console.log('--------------------------------------------------');
|
||||
console.log('ACTUAL');
|
||||
console.log("--------------------------------------------------");
|
||||
console.log("ACTUAL");
|
||||
console.log(out);
|
||||
console.log('--------------------------------------------------');
|
||||
console.log("--------------------------------------------------");
|
||||
console.log();
|
||||
}
|
||||
});
|
||||
|
||||
if (errors) {
|
||||
console.error('Found ' + errors + ' expectation failures.');
|
||||
console.error("Found " + errors + " expectation failures.");
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('All tests completed without errors.');
|
||||
console.log("All tests completed without errors.");
|
||||
process.exit(0);
|
||||
}
|
||||
|
52
external/builder/test-fixtures_esprima.js
vendored
52
external/builder/test-fixtures_esprima.js
vendored
@ -1,62 +1,68 @@
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var p2 = require('./preprocessor2.js');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var p2 = require("./preprocessor2.js");
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
|
||||
var errors = 0;
|
||||
|
||||
var baseDir = path.join(__dirname, 'fixtures_esprima');
|
||||
var files = fs.readdirSync(baseDir).filter(function (name) {
|
||||
var baseDir = path.join(__dirname, "fixtures_esprima");
|
||||
var files = fs
|
||||
.readdirSync(baseDir)
|
||||
.filter(function(name) {
|
||||
return /-expected\./.test(name);
|
||||
}).map(function (name) {
|
||||
})
|
||||
.map(function(name) {
|
||||
return path.join(baseDir, name);
|
||||
});
|
||||
});
|
||||
files.forEach(function(expectationFilename) {
|
||||
var inFilename = expectationFilename.replace('-expected', '');
|
||||
var expectation = fs.readFileSync(expectationFilename).toString().trim()
|
||||
var inFilename = expectationFilename.replace("-expected", "");
|
||||
var expectation = fs
|
||||
.readFileSync(expectationFilename)
|
||||
.toString()
|
||||
.trim()
|
||||
.replace(/__filename/g, fs.realpathSync(inFilename));
|
||||
var input = fs.readFileSync(inFilename).toString();
|
||||
|
||||
var defines = {
|
||||
TRUE: true,
|
||||
FALSE: false,
|
||||
OBJ: { obj: { i: 1, }, j: 2, },
|
||||
TEXT: 'text',
|
||||
OBJ: { obj: { i: 1 }, j: 2 },
|
||||
TEXT: "text",
|
||||
};
|
||||
var map = {
|
||||
'import-alias': 'import-name',
|
||||
"import-alias": "import-name",
|
||||
};
|
||||
var ctx = {
|
||||
defines: defines,
|
||||
map: map,
|
||||
rootPath: __dirname + '/../..',
|
||||
rootPath: __dirname + "/../..",
|
||||
};
|
||||
var out;
|
||||
try {
|
||||
out = p2.preprocessPDFJSCode(ctx, input);
|
||||
} catch (e) {
|
||||
out = ('Error: ' + e.message).replace(/^/gm, '//');
|
||||
out = ("Error: " + e.message).replace(/^/gm, "//");
|
||||
}
|
||||
if (out !== expectation) {
|
||||
errors++;
|
||||
|
||||
console.log('Assertion failed for ' + inFilename);
|
||||
console.log('--------------------------------------------------');
|
||||
console.log('EXPECTED:');
|
||||
console.log("Assertion failed for " + inFilename);
|
||||
console.log("--------------------------------------------------");
|
||||
console.log("EXPECTED:");
|
||||
console.log(expectation);
|
||||
console.log('--------------------------------------------------');
|
||||
console.log('ACTUAL');
|
||||
console.log("--------------------------------------------------");
|
||||
console.log("ACTUAL");
|
||||
console.log(out);
|
||||
console.log('--------------------------------------------------');
|
||||
console.log("--------------------------------------------------");
|
||||
console.log();
|
||||
}
|
||||
});
|
||||
|
||||
if (errors) {
|
||||
console.error('Found ' + errors + ' expectation failures.');
|
||||
console.error("Found " + errors + " expectation failures.");
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('All tests completed without errors.');
|
||||
console.log("All tests completed without errors.");
|
||||
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
|
||||
* limitations under the License.
|
||||
*/
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var pdfjs = require('./build/pdf.js');
|
||||
var PdfjsWorker = require('worker-loader!./build/pdf.worker.js');
|
||||
var pdfjs = require("./build/pdf.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();
|
||||
}
|
||||
|
||||
|
64
external/importL10n/locales.js
vendored
64
external/importL10n/locales.js
vendored
@ -13,39 +13,40 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var fs = require('fs');
|
||||
var https = require('https');
|
||||
var path = require('path');
|
||||
var fs = require("fs");
|
||||
var https = require("https");
|
||||
var path = require("path");
|
||||
|
||||
// Fetches all languages that have an *active* translation in mozilla-central.
|
||||
// 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) {
|
||||
return s.replace(/\r\n?/g, '\n').replace(/\uFEFF/g, '');
|
||||
return s.replace(/\r\n?/g, "\n").replace(/\uFEFF/g, "");
|
||||
}
|
||||
|
||||
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) {
|
||||
https.get(ALL_LOCALES, function(response) {
|
||||
if (response.statusCode === 200) {
|
||||
var content = '';
|
||||
response.setEncoding('utf8');
|
||||
response.on('data', function(chunk) {
|
||||
var content = "";
|
||||
response.setEncoding("utf8");
|
||||
response.on("data", function(chunk) {
|
||||
content += chunk;
|
||||
});
|
||||
response.on('end', function() {
|
||||
response.on("end", function() {
|
||||
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.
|
||||
for (var langCode of [DEFAULT_LOCALE, ...EXCLUDE_LANG_CODES]) {
|
||||
var i = langCodes.indexOf(langCode);
|
||||
@ -63,15 +64,15 @@ function downloadLanguageCodes() {
|
||||
}
|
||||
|
||||
function downloadLanguageFiles(root, langCode) {
|
||||
console.log('Downloading ' + langCode + '...');
|
||||
console.log("Downloading " + langCode + "...");
|
||||
|
||||
// Constants for constructing the URLs. Translations are taken from the
|
||||
// Nightly channel as those are the most recent ones.
|
||||
var MOZ_CENTRAL_ROOT = 'https://hg.mozilla.org/l10n-central/';
|
||||
var MOZ_CENTRAL_PDFJS_DIR = '/raw-file/default/browser/pdfviewer/';
|
||||
var MOZ_CENTRAL_ROOT = "https://hg.mozilla.org/l10n-central/";
|
||||
var MOZ_CENTRAL_PDFJS_DIR = "/raw-file/default/browser/pdfviewer/";
|
||||
|
||||
// Defines which files to download for each language.
|
||||
var files = ['viewer.properties'];
|
||||
var files = ["viewer.properties"];
|
||||
var downloadsLeft = files.length;
|
||||
|
||||
var outputDir = path.join(root, langCode);
|
||||
@ -89,13 +90,13 @@ function downloadLanguageFiles(root, langCode) {
|
||||
// Not all files exist for each language. Files without translations
|
||||
// have been removed (https://bugzilla.mozilla.org/show_bug.cgi?id=1443175).
|
||||
if (response.statusCode === 200) {
|
||||
var content = '';
|
||||
response.setEncoding('utf8');
|
||||
response.on('data', function(chunk) {
|
||||
var content = "";
|
||||
response.setEncoding("utf8");
|
||||
response.on("data", function(chunk) {
|
||||
content += chunk;
|
||||
});
|
||||
response.on('end', function() {
|
||||
fs.writeFileSync(outputPath, normalizeText(content), 'utf8');
|
||||
response.on("end", function() {
|
||||
fs.writeFileSync(outputPath, normalizeText(content), "utf8");
|
||||
if (--downloadsLeft === 0) {
|
||||
resolve();
|
||||
}
|
||||
@ -122,16 +123,23 @@ async function downloadL10n(root, callback) {
|
||||
|
||||
var removeCodes = [];
|
||||
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 &&
|
||||
!langCodes.includes(entry)) {
|
||||
if (
|
||||
stat.isDirectory() &&
|
||||
entry !== DEFAULT_LOCALE &&
|
||||
!langCodes.includes(entry)
|
||||
) {
|
||||
removeCodes.push(entry);
|
||||
}
|
||||
}
|
||||
if (removeCodes.length) {
|
||||
console.log('\nConsider removing the following unmaintained locales:\n' +
|
||||
removeCodes.join(', ') + '\n');
|
||||
console.log(
|
||||
"\nConsider removing the following unmaintained locales:\n" +
|
||||
removeCodes.join(", ") +
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
|
95
external/systemjs/plugin-babel-cached.js
vendored
95
external/systemjs/plugin-babel-cached.js
vendored
@ -12,28 +12,28 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
var babel = require('plugin-babel');
|
||||
var babel = require("plugin-babel");
|
||||
|
||||
var cacheExpiration = 60 /* min */ * 60 * 1000;
|
||||
var dbVersion = 1;
|
||||
var dbName = 'babelcache';
|
||||
var dbCacheTable = 'translated';
|
||||
var dbName = "babelcache";
|
||||
var dbCacheTable = "translated";
|
||||
var dbPromise;
|
||||
|
||||
function getDb() {
|
||||
if (!dbPromise) {
|
||||
dbPromise = new Promise(function (resolve, reject) {
|
||||
dbPromise = new Promise(function(resolve, reject) {
|
||||
var request = indexedDB.open(dbName, dbVersion);
|
||||
request.onupgradeneeded = function() {
|
||||
var db = request.result;
|
||||
db.createObjectStore(dbCacheTable, { keyPath: 'address', });
|
||||
db.createObjectStore(dbCacheTable, { keyPath: "address" });
|
||||
};
|
||||
request.onsuccess = function() {
|
||||
var db = request.result;
|
||||
resolve(db);
|
||||
};
|
||||
request.onerror = function () {
|
||||
console.warn('getDb: ' + request.error);
|
||||
request.onerror = function() {
|
||||
console.warn("getDb: " + request.error);
|
||||
reject(request.error);
|
||||
};
|
||||
});
|
||||
@ -42,8 +42,8 @@ function getDb() {
|
||||
}
|
||||
|
||||
function storeCache(address, hashCode, translated, format) {
|
||||
return getDb().then(function (db) {
|
||||
var tx = db.transaction(dbCacheTable, 'readwrite');
|
||||
return getDb().then(function(db) {
|
||||
var tx = db.transaction(dbCacheTable, "readwrite");
|
||||
var store = tx.objectStore(dbCacheTable);
|
||||
store.put({
|
||||
address: address,
|
||||
@ -52,11 +52,11 @@ function storeCache(address, hashCode, translated, format) {
|
||||
expires: Date.now() + cacheExpiration,
|
||||
format: format,
|
||||
});
|
||||
return new Promise(function (resolve, reject) {
|
||||
tx.oncomplete = function () {
|
||||
return new Promise(function(resolve, reject) {
|
||||
tx.oncomplete = function() {
|
||||
resolve();
|
||||
};
|
||||
tx.onerror = function () {
|
||||
tx.onerror = function() {
|
||||
resolve();
|
||||
};
|
||||
});
|
||||
@ -64,59 +64,84 @@ function storeCache(address, hashCode, translated, format) {
|
||||
}
|
||||
|
||||
function loadCache(address, hashCode) {
|
||||
return getDb().then(function (db) {
|
||||
var tx = db.transaction(dbCacheTable, 'readonly');
|
||||
return getDb().then(function(db) {
|
||||
var tx = db.transaction(dbCacheTable, "readonly");
|
||||
var store = tx.objectStore(dbCacheTable);
|
||||
var getAddress = store.get(address);
|
||||
return new Promise(function (resolve, reject) {
|
||||
tx.oncomplete = function () {
|
||||
return new Promise(function(resolve, reject) {
|
||||
tx.oncomplete = function() {
|
||||
var found = getAddress.result;
|
||||
var isValid = found && found.hashCode === hashCode &&
|
||||
Date.now() < found.expires;
|
||||
resolve(isValid ? {
|
||||
var isValid =
|
||||
found && found.hashCode === hashCode && Date.now() < found.expires;
|
||||
resolve(
|
||||
isValid
|
||||
? {
|
||||
translated: found.translated,
|
||||
format: found.format,
|
||||
} : null);
|
||||
}
|
||||
: null
|
||||
);
|
||||
};
|
||||
tx.onerror = function () {
|
||||
tx.onerror = function() {
|
||||
resolve(null);
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var encoder = new TextEncoder('utf-8');
|
||||
var encoder = new TextEncoder("utf-8");
|
||||
function sha256(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);
|
||||
return data[0].toString(36) + '-' + data[1].toString(36) + '-' +
|
||||
data[2].toString(36) + '-' + data[3].toString(36);
|
||||
return (
|
||||
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;
|
||||
return sha256(load.source).then(function (hashCode) {
|
||||
return sha256(load.source)
|
||||
.then(function(hashCode) {
|
||||
savedHashCode = hashCode;
|
||||
return loadCache(load.address, hashCode);
|
||||
}).then(function (cache) {
|
||||
})
|
||||
.then(
|
||||
function(cache) {
|
||||
if (cache) {
|
||||
load.metadata.format = cache.format;
|
||||
return cache.translated;
|
||||
}
|
||||
return babel.translate.call(this, load, opt).then(function(translated) {
|
||||
return storeCache(load.address, savedHashCode,
|
||||
translated, load.metadata.format).then(function () {
|
||||
return babel.translate.call(this, load, opt).then(
|
||||
function(translated) {
|
||||
return storeCache(
|
||||
load.address,
|
||||
savedHashCode,
|
||||
translated,
|
||||
load.metadata.format
|
||||
).then(function() {
|
||||
return translated;
|
||||
});
|
||||
}, function(reason) {
|
||||
},
|
||||
function(reason) {
|
||||
throw (babelTranslateError = reason);
|
||||
});
|
||||
}.bind(this)).catch(function(reason) {
|
||||
}
|
||||
);
|
||||
}.bind(this)
|
||||
)
|
||||
.catch(
|
||||
function(reason) {
|
||||
if (babelTranslateError) {
|
||||
throw babelTranslateError;
|
||||
}
|
||||
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 */
|
||||
|
||||
'use strict';
|
||||
"use strict";
|
||||
|
||||
var preprocessor2 = require('../builder/preprocessor2.js');
|
||||
var path = require('path');
|
||||
var preprocessor2 = require("../builder/preprocessor2.js");
|
||||
var path = require("path");
|
||||
|
||||
module.exports = function(source) {
|
||||
// Options must be specified, ignoring request if not.
|
||||
if (!this.query || typeof this.query !== 'object') {
|
||||
if (!this.query || typeof this.query !== "object") {
|
||||
return source;
|
||||
}
|
||||
this.cacheable();
|
||||
|
||||
var filePath = this.resourcePath;
|
||||
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);
|
||||
ctx.sourceMap = true;
|
||||
|
1666
gulpfile.js
1666
gulpfile.js
File diff suppressed because it is too large
Load Diff
@ -15,16 +15,25 @@
|
||||
/* eslint no-var: error */
|
||||
|
||||
import {
|
||||
AnnotationBorderStyleType, AnnotationFieldFlag, AnnotationFlag,
|
||||
AnnotationReplyType, AnnotationType, assert, isString, OPS, stringToBytes,
|
||||
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';
|
||||
AnnotationBorderStyleType,
|
||||
AnnotationFieldFlag,
|
||||
AnnotationFlag,
|
||||
AnnotationReplyType,
|
||||
AnnotationType,
|
||||
assert,
|
||||
isString,
|
||||
OPS,
|
||||
stringToBytes,
|
||||
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 {
|
||||
/**
|
||||
@ -40,8 +49,12 @@ class AnnotationFactory {
|
||||
* instance.
|
||||
*/
|
||||
static create(xref, ref, pdfManager, idFactory) {
|
||||
return pdfManager.ensure(this, '_create',
|
||||
[xref, ref, pdfManager, idFactory]);
|
||||
return pdfManager.ensure(this, "_create", [
|
||||
xref,
|
||||
ref,
|
||||
pdfManager,
|
||||
idFactory,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +68,7 @@ class AnnotationFactory {
|
||||
const id = isRef(ref) ? ref.toString() : `annot_${idFactory.createObjId()}`;
|
||||
|
||||
// Determine the annotation's subtype.
|
||||
let subtype = dict.get('Subtype');
|
||||
let subtype = dict.get("Subtype");
|
||||
subtype = isName(subtype) ? subtype.name : null;
|
||||
|
||||
// Return the right annotation object based on the subtype and field type.
|
||||
@ -68,79 +81,87 @@ class AnnotationFactory {
|
||||
};
|
||||
|
||||
switch (subtype) {
|
||||
case 'Link':
|
||||
case "Link":
|
||||
return new LinkAnnotation(parameters);
|
||||
|
||||
case 'Text':
|
||||
case "Text":
|
||||
return new TextAnnotation(parameters);
|
||||
|
||||
case 'Widget':
|
||||
let fieldType = getInheritableProperty({ dict, key: 'FT', });
|
||||
case "Widget":
|
||||
let fieldType = getInheritableProperty({ dict, key: "FT" });
|
||||
fieldType = isName(fieldType) ? fieldType.name : null;
|
||||
|
||||
switch (fieldType) {
|
||||
case 'Tx':
|
||||
case "Tx":
|
||||
return new TextWidgetAnnotation(parameters);
|
||||
case 'Btn':
|
||||
case "Btn":
|
||||
return new ButtonWidgetAnnotation(parameters);
|
||||
case 'Ch':
|
||||
case "Ch":
|
||||
return new ChoiceWidgetAnnotation(parameters);
|
||||
}
|
||||
warn('Unimplemented widget field type "' + fieldType + '", ' +
|
||||
'falling back to base field type.');
|
||||
warn(
|
||||
'Unimplemented widget field type "' +
|
||||
fieldType +
|
||||
'", ' +
|
||||
"falling back to base field type."
|
||||
);
|
||||
return new WidgetAnnotation(parameters);
|
||||
|
||||
case 'Popup':
|
||||
case "Popup":
|
||||
return new PopupAnnotation(parameters);
|
||||
|
||||
case 'FreeText':
|
||||
case "FreeText":
|
||||
return new FreeTextAnnotation(parameters);
|
||||
|
||||
case 'Line':
|
||||
case "Line":
|
||||
return new LineAnnotation(parameters);
|
||||
|
||||
case 'Square':
|
||||
case "Square":
|
||||
return new SquareAnnotation(parameters);
|
||||
|
||||
case 'Circle':
|
||||
case "Circle":
|
||||
return new CircleAnnotation(parameters);
|
||||
|
||||
case 'PolyLine':
|
||||
case "PolyLine":
|
||||
return new PolylineAnnotation(parameters);
|
||||
|
||||
case 'Polygon':
|
||||
case "Polygon":
|
||||
return new PolygonAnnotation(parameters);
|
||||
|
||||
case 'Caret':
|
||||
case "Caret":
|
||||
return new CaretAnnotation(parameters);
|
||||
|
||||
case 'Ink':
|
||||
case "Ink":
|
||||
return new InkAnnotation(parameters);
|
||||
|
||||
case 'Highlight':
|
||||
case "Highlight":
|
||||
return new HighlightAnnotation(parameters);
|
||||
|
||||
case 'Underline':
|
||||
case "Underline":
|
||||
return new UnderlineAnnotation(parameters);
|
||||
|
||||
case 'Squiggly':
|
||||
case "Squiggly":
|
||||
return new SquigglyAnnotation(parameters);
|
||||
|
||||
case 'StrikeOut':
|
||||
case "StrikeOut":
|
||||
return new StrikeOutAnnotation(parameters);
|
||||
|
||||
case 'Stamp':
|
||||
case "Stamp":
|
||||
return new StampAnnotation(parameters);
|
||||
|
||||
case 'FileAttachment':
|
||||
case "FileAttachment":
|
||||
return new FileAttachmentAnnotation(parameters);
|
||||
|
||||
default:
|
||||
if (!subtype) {
|
||||
warn('Annotation is missing the required /Subtype.');
|
||||
warn("Annotation is missing the required /Subtype.");
|
||||
} else {
|
||||
warn('Unimplemented annotation type "' + subtype + '", ' +
|
||||
'falling back to base annotation.');
|
||||
warn(
|
||||
'Unimplemented annotation type "' +
|
||||
subtype +
|
||||
'", ' +
|
||||
"falling back to base annotation."
|
||||
);
|
||||
}
|
||||
return new Annotation(parameters);
|
||||
}
|
||||
@ -148,13 +169,13 @@ class AnnotationFactory {
|
||||
}
|
||||
|
||||
function getQuadPoints(dict, rect) {
|
||||
if (!dict.has('QuadPoints')) {
|
||||
if (!dict.has("QuadPoints")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// The region is described as a number of quadrilaterals.
|
||||
// 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) {
|
||||
return null;
|
||||
}
|
||||
@ -165,7 +186,7 @@ function getQuadPoints(dict, rect) {
|
||||
// quadrilateral in the order [x1, y1, x2, y2, x3, y3, x4, y4].
|
||||
// Convert this to an array of objects with x and y coordinates.
|
||||
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 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]) {
|
||||
return null;
|
||||
}
|
||||
quadPointsLists[i].push({ x, y, });
|
||||
quadPointsLists[i].push({ x, y });
|
||||
}
|
||||
}
|
||||
return quadPointsLists;
|
||||
@ -182,8 +203,10 @@ function getQuadPoints(dict, rect) {
|
||||
|
||||
function getTransformMatrix(rect, bbox, matrix) {
|
||||
// 12.5.5: Algorithm: Appearance streams
|
||||
const [minX, minY, maxX, maxY] =
|
||||
Util.getAxialAlignedBoundingBox(bbox, matrix);
|
||||
const [minX, minY, maxX, maxY] = Util.getAxialAlignedBoundingBox(
|
||||
bbox,
|
||||
matrix
|
||||
);
|
||||
if (minX === maxX || minY === maxY) {
|
||||
// From real-life file, bbox was [0, 0, 0, 0]. In this case,
|
||||
// just apply the transform for rect
|
||||
@ -198,7 +221,7 @@ function getTransformMatrix(rect, bbox, matrix) {
|
||||
0,
|
||||
yRatio,
|
||||
rect[0] - minX * xRatio,
|
||||
rect[1] - minY * yRatio
|
||||
rect[1] - minY * yRatio,
|
||||
];
|
||||
}
|
||||
|
||||
@ -206,11 +229,11 @@ class Annotation {
|
||||
constructor(params) {
|
||||
const dict = params.dict;
|
||||
|
||||
this.setContents(dict.get('Contents'));
|
||||
this.setModificationDate(dict.get('M'));
|
||||
this.setFlags(dict.get('F'));
|
||||
this.setRectangle(dict.getArray('Rect'));
|
||||
this.setColor(dict.getArray('C'));
|
||||
this.setContents(dict.get("Contents"));
|
||||
this.setModificationDate(dict.get("M"));
|
||||
this.setFlags(dict.get("F"));
|
||||
this.setRectangle(dict.getArray("Rect"));
|
||||
this.setColor(dict.getArray("C"));
|
||||
this.setBorderStyle(dict);
|
||||
this.setAppearance(dict);
|
||||
|
||||
@ -239,18 +262,22 @@ class Annotation {
|
||||
* @private
|
||||
*/
|
||||
_isViewable(flags) {
|
||||
return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
||||
return (
|
||||
!this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.HIDDEN) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.NOVIEW);
|
||||
!this._hasFlag(flags, AnnotationFlag.NOVIEW)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_isPrintable(flags) {
|
||||
return this._hasFlag(flags, AnnotationFlag.PRINT) &&
|
||||
return (
|
||||
this._hasFlag(flags, AnnotationFlag.PRINT) &&
|
||||
!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
|
||||
*/
|
||||
setContents(contents) {
|
||||
this.contents = stringToPDFString(contents || '');
|
||||
this.contents = stringToPDFString(contents || "");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -295,8 +322,9 @@ class Annotation {
|
||||
* annotation was last modified
|
||||
*/
|
||||
setModificationDate(modificationDate) {
|
||||
this.modificationDate = isString(modificationDate) ?
|
||||
modificationDate : null;
|
||||
this.modificationDate = isString(modificationDate)
|
||||
? modificationDate
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -309,7 +337,7 @@ class Annotation {
|
||||
* @see {@link shared/util.js}
|
||||
*/
|
||||
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
|
||||
*/
|
||||
setBorderStyle(borderStyle) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
assert(this.rectangle, 'setRectangle must have been called previously.');
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||
) {
|
||||
assert(this.rectangle, "setRectangle must have been called previously.");
|
||||
}
|
||||
|
||||
this.borderStyle = new AnnotationBorderStyle();
|
||||
if (!isDict(borderStyle)) {
|
||||
return;
|
||||
}
|
||||
if (borderStyle.has('BS')) {
|
||||
const dict = borderStyle.get('BS');
|
||||
const dictType = dict.get('Type');
|
||||
if (borderStyle.has("BS")) {
|
||||
const dict = borderStyle.get("BS");
|
||||
const dictType = dict.get("Type");
|
||||
|
||||
if (!dictType || isName(dictType, 'Border')) {
|
||||
this.borderStyle.setWidth(dict.get('W'), this.rectangle);
|
||||
this.borderStyle.setStyle(dict.get('S'));
|
||||
this.borderStyle.setDashArray(dict.getArray('D'));
|
||||
if (!dictType || isName(dictType, "Border")) {
|
||||
this.borderStyle.setWidth(dict.get("W"), this.rectangle);
|
||||
this.borderStyle.setStyle(dict.get("S"));
|
||||
this.borderStyle.setDashArray(dict.getArray("D"));
|
||||
}
|
||||
} else if (borderStyle.has('Border')) {
|
||||
const array = borderStyle.getArray('Border');
|
||||
} else if (borderStyle.has("Border")) {
|
||||
const array = borderStyle.getArray("Border");
|
||||
if (Array.isArray(array) && array.length >= 3) {
|
||||
this.borderStyle.setHorizontalCornerRadius(array[0]);
|
||||
this.borderStyle.setVerticalCornerRadius(array[1]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
@ -441,13 +472,13 @@ class Annotation {
|
||||
setAppearance(dict) {
|
||||
this.appearance = null;
|
||||
|
||||
const appearanceStates = dict.get('AP');
|
||||
const appearanceStates = dict.get("AP");
|
||||
if (!isDict(appearanceStates)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
this.appearance = normalAppearanceState;
|
||||
return;
|
||||
@ -458,7 +489,7 @@ class Annotation {
|
||||
|
||||
// In case the normal appearance is a dictionary, the `AS` entry provides
|
||||
// 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)) {
|
||||
return;
|
||||
}
|
||||
@ -466,7 +497,7 @@ class Annotation {
|
||||
}
|
||||
|
||||
loadResources(keys) {
|
||||
return this.appearance.dict.getAsync('Resources').then((resources) => {
|
||||
return this.appearance.dict.getAsync("Resources").then(resources => {
|
||||
if (!resources) {
|
||||
return undefined;
|
||||
}
|
||||
@ -486,26 +517,28 @@ class Annotation {
|
||||
const data = this.data;
|
||||
const appearanceDict = this.appearance.dict;
|
||||
const resourcesPromise = this.loadResources([
|
||||
'ExtGState',
|
||||
'ColorSpace',
|
||||
'Pattern',
|
||||
'Shading',
|
||||
'XObject',
|
||||
'Font',
|
||||
"ExtGState",
|
||||
"ColorSpace",
|
||||
"Pattern",
|
||||
"Shading",
|
||||
"XObject",
|
||||
"Font",
|
||||
]);
|
||||
const bbox = appearanceDict.getArray('BBox') || [0, 0, 1, 1];
|
||||
const matrix = appearanceDict.getArray('Matrix') || [1, 0, 0, 1, 0, 0];
|
||||
const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
|
||||
const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
|
||||
const transform = getTransformMatrix(data.rect, bbox, matrix);
|
||||
|
||||
return resourcesPromise.then((resources) => {
|
||||
return resourcesPromise.then(resources => {
|
||||
const opList = new OperatorList();
|
||||
opList.addOp(OPS.beginAnnotation, [data.rect, transform, matrix]);
|
||||
return evaluator.getOperatorList({
|
||||
return evaluator
|
||||
.getOperatorList({
|
||||
stream: this.appearance,
|
||||
task,
|
||||
resources,
|
||||
operatorList: opList,
|
||||
}).then(() => {
|
||||
})
|
||||
.then(() => {
|
||||
opList.addOp(OPS.endAnnotation, []);
|
||||
this.appearance.reset();
|
||||
return opList;
|
||||
@ -535,10 +568,14 @@ class AnnotationBorderStyle {
|
||||
* @param {Array} rect - The annotation `Rect` entry.
|
||||
*/
|
||||
setWidth(width, rect = [0, 0, 0, 0]) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
assert(Array.isArray(rect) && rect.length === 4,
|
||||
'A valid `rect` parameter must be provided.');
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||
) {
|
||||
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`,
|
||||
@ -555,8 +592,11 @@ class AnnotationBorderStyle {
|
||||
// Ignore large `width`s, since they lead to the Annotation overflowing
|
||||
// the size set by the `Rect` entry thus causing the `annotationLayer`
|
||||
// to render it over the surrounding document (fixes bug1552113.pdf).
|
||||
if ((maxWidth > 0 && maxHeight > 0) &&
|
||||
(width > maxWidth || width > maxHeight)) {
|
||||
if (
|
||||
maxWidth > 0 &&
|
||||
maxHeight > 0 &&
|
||||
(width > maxWidth || width > maxHeight)
|
||||
) {
|
||||
warn(`AnnotationBorderStyle.setWidth - ignoring width: ${width}`);
|
||||
width = 1;
|
||||
}
|
||||
@ -578,23 +618,23 @@ class AnnotationBorderStyle {
|
||||
return;
|
||||
}
|
||||
switch (style.name) {
|
||||
case 'S':
|
||||
case "S":
|
||||
this.style = AnnotationBorderStyleType.SOLID;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
case "D":
|
||||
this.style = AnnotationBorderStyleType.DASHED;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
case "B":
|
||||
this.style = AnnotationBorderStyleType.BEVELED;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
case "I":
|
||||
this.style = AnnotationBorderStyleType.INSET;
|
||||
break;
|
||||
|
||||
case 'U':
|
||||
case "U":
|
||||
this.style = AnnotationBorderStyleType.UNDERLINE;
|
||||
break;
|
||||
|
||||
@ -620,7 +660,7 @@ class AnnotationBorderStyle {
|
||||
let isValid = true;
|
||||
let allZeros = true;
|
||||
for (const element of dashArray) {
|
||||
const validNumber = (+element >= 0);
|
||||
const validNumber = +element >= 0;
|
||||
if (!validNumber) {
|
||||
isValid = false;
|
||||
break;
|
||||
@ -671,56 +711,56 @@ class MarkupAnnotation extends Annotation {
|
||||
|
||||
const dict = parameters.dict;
|
||||
|
||||
if (dict.has('IRT')) {
|
||||
const rawIRT = dict.getRaw('IRT');
|
||||
if (dict.has("IRT")) {
|
||||
const rawIRT = dict.getRaw("IRT");
|
||||
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;
|
||||
}
|
||||
|
||||
if (this.data.replyType === AnnotationReplyType.GROUP) {
|
||||
// Subordinate annotations in a group should inherit
|
||||
// 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;
|
||||
|
||||
if (!parent.has('CreationDate')) {
|
||||
if (!parent.has("CreationDate")) {
|
||||
this.data.creationDate = null;
|
||||
} else {
|
||||
this.setCreationDate(parent.get('CreationDate'));
|
||||
this.setCreationDate(parent.get("CreationDate"));
|
||||
this.data.creationDate = this.creationDate;
|
||||
}
|
||||
|
||||
if (!parent.has('M')) {
|
||||
if (!parent.has("M")) {
|
||||
this.data.modificationDate = null;
|
||||
} else {
|
||||
this.setModificationDate(parent.get('M'));
|
||||
this.setModificationDate(parent.get("M"));
|
||||
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.
|
||||
this.data.color = null;
|
||||
} else {
|
||||
this.setColor(parent.getArray('C'));
|
||||
this.setColor(parent.getArray("C"));
|
||||
this.data.color = this.color;
|
||||
}
|
||||
} 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.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.
|
||||
this.data.color = null;
|
||||
}
|
||||
@ -749,16 +789,19 @@ class WidgetAnnotation extends Annotation {
|
||||
|
||||
data.annotationType = AnnotationType.WIDGET;
|
||||
data.fieldName = this._constructFieldName(dict);
|
||||
data.fieldValue = getInheritableProperty({ dict, key: 'V',
|
||||
getArray: true, });
|
||||
data.alternativeText = stringToPDFString(dict.get('TU') || '');
|
||||
data.defaultAppearance = getInheritableProperty({ dict, key: 'DA', }) || '';
|
||||
const fieldType = getInheritableProperty({ dict, key: 'FT', });
|
||||
data.fieldValue = getInheritableProperty({
|
||||
dict,
|
||||
key: "V",
|
||||
getArray: true,
|
||||
});
|
||||
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;
|
||||
this.fieldResources = getInheritableProperty({ dict, key: 'DR', }) ||
|
||||
Dict.empty;
|
||||
this.fieldResources =
|
||||
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) {
|
||||
data.fieldFlags = 0;
|
||||
}
|
||||
@ -768,7 +811,7 @@ class WidgetAnnotation extends Annotation {
|
||||
// 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
|
||||
// cause errors when sending annotations to the main-thread (issue 10347).
|
||||
if (data.fieldType === 'Sig') {
|
||||
if (data.fieldType === "Sig") {
|
||||
data.fieldValue = null;
|
||||
this.setFlags(AnnotationFlag.HIDDEN);
|
||||
}
|
||||
@ -786,26 +829,26 @@ class WidgetAnnotation extends Annotation {
|
||||
_constructFieldName(dict) {
|
||||
// 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.
|
||||
if (!dict.has('T') && !dict.has('Parent')) {
|
||||
warn('Unknown field name, falling back to empty field name.');
|
||||
return '';
|
||||
if (!dict.has("T") && !dict.has("Parent")) {
|
||||
warn("Unknown field name, falling back to empty field name.");
|
||||
return "";
|
||||
}
|
||||
|
||||
// If no parent exists, the partial and fully qualified names are equal.
|
||||
if (!dict.has('Parent')) {
|
||||
return stringToPDFString(dict.get('T'));
|
||||
if (!dict.has("Parent")) {
|
||||
return stringToPDFString(dict.get("T"));
|
||||
}
|
||||
|
||||
// Form the fully qualified field name by appending the partial name to
|
||||
// the parent's fully qualified name, separated by a period.
|
||||
const fieldName = [];
|
||||
if (dict.has('T')) {
|
||||
fieldName.unshift(stringToPDFString(dict.get('T')));
|
||||
if (dict.has("T")) {
|
||||
fieldName.unshift(stringToPDFString(dict.get("T")));
|
||||
}
|
||||
|
||||
let loopDict = dict;
|
||||
while (loopDict.has('Parent')) {
|
||||
loopDict = loopDict.get('Parent');
|
||||
while (loopDict.has("Parent")) {
|
||||
loopDict = loopDict.get("Parent");
|
||||
if (!isDict(loopDict)) {
|
||||
// Even though it is not allowed according to the PDF specification,
|
||||
// bad PDF generators may provide a `Parent` entry that is not a
|
||||
@ -813,11 +856,11 @@ class WidgetAnnotation extends Annotation {
|
||||
break;
|
||||
}
|
||||
|
||||
if (loopDict.has('T')) {
|
||||
fieldName.unshift(stringToPDFString(loopDict.get('T')));
|
||||
if (loopDict.has("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;
|
||||
|
||||
// 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.
|
||||
let alignment = getInheritableProperty({ dict, key: 'Q', });
|
||||
let alignment = getInheritableProperty({ dict, key: "Q" });
|
||||
if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {
|
||||
alignment = null;
|
||||
}
|
||||
this.data.textAlignment = alignment;
|
||||
|
||||
// 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) {
|
||||
maximumLength = null;
|
||||
}
|
||||
@ -869,7 +912,8 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
||||
|
||||
// Process field flags for the display layer.
|
||||
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.PASSWORD) &&
|
||||
!this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
|
||||
@ -890,12 +934,14 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
||||
}
|
||||
|
||||
const stream = new Stream(stringToBytes(this.data.defaultAppearance));
|
||||
return evaluator.getOperatorList({
|
||||
return evaluator
|
||||
.getOperatorList({
|
||||
stream,
|
||||
task,
|
||||
resources: this.fieldResources,
|
||||
operatorList,
|
||||
}).then(function () {
|
||||
})
|
||||
.then(function() {
|
||||
return operatorList;
|
||||
});
|
||||
}
|
||||
@ -905,9 +951,11 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
constructor(params) {
|
||||
super(params);
|
||||
|
||||
this.data.checkBox = !this.hasFieldFlag(AnnotationFieldFlag.RADIO) &&
|
||||
this.data.checkBox =
|
||||
!this.hasFieldFlag(AnnotationFieldFlag.RADIO) &&
|
||||
!this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
||||
this.data.radioButton = this.hasFieldFlag(AnnotationFieldFlag.RADIO) &&
|
||||
this.data.radioButton =
|
||||
this.hasFieldFlag(AnnotationFieldFlag.RADIO) &&
|
||||
!this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
||||
this.data.pushButton = this.hasFieldFlag(AnnotationFieldFlag.PUSHBUTTON);
|
||||
|
||||
@ -918,7 +966,7 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
} else if (this.data.pushButton) {
|
||||
this._processPushButton(params);
|
||||
} 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;
|
||||
}
|
||||
|
||||
const customAppearance = params.dict.get('AP');
|
||||
const customAppearance = params.dict.get("AP");
|
||||
if (!isDict(customAppearance)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const exportValueOptionsDict = customAppearance.get('D');
|
||||
const exportValueOptionsDict = customAppearance.get("D");
|
||||
if (!isDict(exportValueOptionsDict)) {
|
||||
return;
|
||||
}
|
||||
@ -943,8 +991,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
return;
|
||||
}
|
||||
|
||||
this.data.exportValue = exportValues[0] === 'Off' ?
|
||||
exportValues[1] : exportValues[0];
|
||||
this.data.exportValue =
|
||||
exportValues[0] === "Off" ? exportValues[1] : exportValues[0];
|
||||
}
|
||||
|
||||
_processRadioButton(params) {
|
||||
@ -952,25 +1000,25 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
|
||||
// The parent field's `V` entry holds a `Name` object with the appearance
|
||||
// state of whichever child field is currently in the "on" state.
|
||||
const fieldParent = params.dict.get('Parent');
|
||||
if (isDict(fieldParent) && fieldParent.has('V')) {
|
||||
const fieldParentValue = fieldParent.get('V');
|
||||
const fieldParent = params.dict.get("Parent");
|
||||
if (isDict(fieldParent) && fieldParent.has("V")) {
|
||||
const fieldParentValue = fieldParent.get("V");
|
||||
if (isName(fieldParentValue)) {
|
||||
this.data.fieldValue = fieldParentValue.name;
|
||||
}
|
||||
}
|
||||
|
||||
// The button's value corresponds to its appearance state.
|
||||
const appearanceStates = params.dict.get('AP');
|
||||
const appearanceStates = params.dict.get("AP");
|
||||
if (!isDict(appearanceStates)) {
|
||||
return;
|
||||
}
|
||||
const normalAppearanceState = appearanceStates.get('N');
|
||||
const normalAppearanceState = appearanceStates.get("N");
|
||||
if (!isDict(normalAppearanceState)) {
|
||||
return;
|
||||
}
|
||||
for (const key of normalAppearanceState.getKeys()) {
|
||||
if (key !== 'Off') {
|
||||
if (key !== "Off") {
|
||||
this.data.buttonValue = key;
|
||||
break;
|
||||
}
|
||||
@ -978,8 +1026,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
||||
}
|
||||
|
||||
_processPushButton(params) {
|
||||
if (!params.dict.has('A')) {
|
||||
warn('Push buttons without action dictionaries are not supported');
|
||||
if (!params.dict.has("A")) {
|
||||
warn("Push buttons without action dictionaries are not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1006,7 +1054,7 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
|
||||
// inherit the options from a parent annotation (issue 8094).
|
||||
this.data.options = [];
|
||||
|
||||
const options = getInheritableProperty({ dict: params.dict, key: 'Opt', });
|
||||
const options = getInheritableProperty({ dict: params.dict, key: "Opt" });
|
||||
if (Array.isArray(options)) {
|
||||
const xref = params.xref;
|
||||
for (let i = 0, ii = options.length; i < ii; i++) {
|
||||
@ -1015,8 +1063,9 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
|
||||
|
||||
this.data.options[i] = {
|
||||
exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option,
|
||||
displayValue: stringToPDFString(isOptionArray ?
|
||||
xref.fetchIfRef(option[1]) : option),
|
||||
displayValue: stringToPDFString(
|
||||
isOptionArray ? xref.fetchIfRef(option[1]) : option
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1044,17 +1093,16 @@ class TextAnnotation extends MarkupAnnotation {
|
||||
this.data.annotationType = AnnotationType.TEXT;
|
||||
|
||||
if (this.data.hasAppearance) {
|
||||
this.data.name = 'NoIcon';
|
||||
this.data.name = "NoIcon";
|
||||
} else {
|
||||
this.data.rect[1] = this.data.rect[3] - DEFAULT_ICON_SIZE;
|
||||
this.data.rect[2] = this.data.rect[0] + DEFAULT_ICON_SIZE;
|
||||
this.data.name = dict.has('Name') ?
|
||||
dict.get('Name').name : 'Note';
|
||||
this.data.name = dict.has("Name") ? dict.get("Name").name : "Note";
|
||||
}
|
||||
|
||||
if (dict.has('State')) {
|
||||
this.data.state = dict.get('State') || null;
|
||||
this.data.stateModel = dict.get('StateModel') || null;
|
||||
if (dict.has("State")) {
|
||||
this.data.state = dict.get("State") || null;
|
||||
this.data.stateModel = dict.get("StateModel") || null;
|
||||
} else {
|
||||
this.data.state = null;
|
||||
this.data.stateModel = null;
|
||||
@ -1087,36 +1135,36 @@ class PopupAnnotation extends Annotation {
|
||||
|
||||
this.data.annotationType = AnnotationType.POPUP;
|
||||
|
||||
let parentItem = parameters.dict.get('Parent');
|
||||
let parentItem = parameters.dict.get("Parent");
|
||||
if (!parentItem) {
|
||||
warn('Popup annotation has a missing or invalid parent annotation.');
|
||||
warn("Popup annotation has a missing or invalid parent annotation.");
|
||||
return;
|
||||
}
|
||||
|
||||
const parentSubtype = parentItem.get('Subtype');
|
||||
const parentSubtype = parentItem.get("Subtype");
|
||||
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;
|
||||
|
||||
const rt = parentItem.get('RT');
|
||||
const rt = parentItem.get("RT");
|
||||
if (isName(rt, AnnotationReplyType.GROUP)) {
|
||||
// Subordinate annotations in a group should inherit
|
||||
// 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;
|
||||
} else {
|
||||
this.setModificationDate(parentItem.get('M'));
|
||||
this.setModificationDate(parentItem.get("M"));
|
||||
this.data.modificationDate = this.modificationDate;
|
||||
}
|
||||
|
||||
if (!parentItem.has('C')) {
|
||||
if (!parentItem.has("C")) {
|
||||
// Fall back to the default background color.
|
||||
this.data.color = null;
|
||||
} else {
|
||||
this.setColor(parentItem.getArray('C'));
|
||||
this.setColor(parentItem.getArray("C"));
|
||||
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
|
||||
// annotation (this is consistent with the behaviour in Adobe Reader).
|
||||
if (!this.viewable) {
|
||||
const parentFlags = parentItem.get('F');
|
||||
const parentFlags = parentItem.get("F");
|
||||
if (this._isViewable(parentFlags)) {
|
||||
this.setFlags(parentFlags);
|
||||
}
|
||||
}
|
||||
|
||||
this.data.title = stringToPDFString(parentItem.get('T') || '');
|
||||
this.data.contents = stringToPDFString(parentItem.get('Contents') || '');
|
||||
this.data.title = stringToPDFString(parentItem.get("T") || "");
|
||||
this.data.contents = stringToPDFString(parentItem.get("Contents") || "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1149,8 +1197,9 @@ class LineAnnotation extends MarkupAnnotation {
|
||||
|
||||
this.data.annotationType = AnnotationType.LINE;
|
||||
|
||||
this.data.lineCoordinates =
|
||||
Util.normalizeRect(parameters.dict.getArray('L'));
|
||||
this.data.lineCoordinates = Util.normalizeRect(
|
||||
parameters.dict.getArray("L")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1179,7 +1228,7 @@ class PolylineAnnotation extends MarkupAnnotation {
|
||||
// The vertices array is an array of numbers representing the alternating
|
||||
// horizontal and vertical coordinates, respectively, of each vertex.
|
||||
// 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 = [];
|
||||
for (let i = 0, ii = rawVertices.length; i < ii; i += 2) {
|
||||
this.data.vertices.push({
|
||||
@ -1214,7 +1263,7 @@ class InkAnnotation extends MarkupAnnotation {
|
||||
this.data.annotationType = AnnotationType.INK;
|
||||
|
||||
const xref = parameters.xref;
|
||||
const originalInkLists = parameters.dict.getArray('InkList');
|
||||
const originalInkLists = parameters.dict.getArray("InkList");
|
||||
this.data.inkLists = [];
|
||||
for (let i = 0, ii = originalInkLists.length; i < ii; ++i) {
|
||||
// The raw ink lists array contains arrays of numbers representing
|
||||
@ -1296,7 +1345,7 @@ class FileAttachmentAnnotation extends MarkupAnnotation {
|
||||
constructor(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.file = file.serializable;
|
||||
|
@ -16,53 +16,53 @@
|
||||
|
||||
// Table C-2
|
||||
const QeTable = [
|
||||
{ qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1, },
|
||||
{ qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0, },
|
||||
{ qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0, },
|
||||
{ qe: 0x0AC1, nmps: 4, nlps: 12, switchFlag: 0, },
|
||||
{ qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0, },
|
||||
{ qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0, },
|
||||
{ qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1, },
|
||||
{ qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0, },
|
||||
{ qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0, },
|
||||
{ qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0, },
|
||||
{ qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0, },
|
||||
{ qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0, },
|
||||
{ qe: 0x1C01, nmps: 13, nlps: 20, switchFlag: 0, },
|
||||
{ qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0, },
|
||||
{ qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1, },
|
||||
{ qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0, },
|
||||
{ qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0, },
|
||||
{ qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0, },
|
||||
{ qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0, },
|
||||
{ qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0, },
|
||||
{ qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0, },
|
||||
{ qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0, },
|
||||
{ qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0, },
|
||||
{ qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0, },
|
||||
{ qe: 0x1C01, nmps: 25, nlps: 22, switchFlag: 0, },
|
||||
{ qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0, },
|
||||
{ qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0, },
|
||||
{ qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0, },
|
||||
{ qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0, },
|
||||
{ qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0, },
|
||||
{ qe: 0x0AC1, nmps: 31, nlps: 28, switchFlag: 0, },
|
||||
{ qe: 0x09C1, nmps: 32, nlps: 29, switchFlag: 0, },
|
||||
{ qe: 0x08A1, nmps: 33, nlps: 30, switchFlag: 0, },
|
||||
{ qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0, },
|
||||
{ qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0, },
|
||||
{ qe: 0x02A1, nmps: 36, nlps: 33, switchFlag: 0, },
|
||||
{ qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0, },
|
||||
{ qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0, },
|
||||
{ qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0, },
|
||||
{ qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0, },
|
||||
{ qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0, },
|
||||
{ qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0, },
|
||||
{ qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0, },
|
||||
{ qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0, },
|
||||
{ qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0, },
|
||||
{ qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0, },
|
||||
{ qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0, },
|
||||
{ qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1 },
|
||||
{ qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0 },
|
||||
{ qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0 },
|
||||
{ qe: 0x0ac1, nmps: 4, nlps: 12, switchFlag: 0 },
|
||||
{ qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0 },
|
||||
{ qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0 },
|
||||
{ qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1 },
|
||||
{ qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0 },
|
||||
{ qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0 },
|
||||
{ qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0 },
|
||||
{ qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0 },
|
||||
{ qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0 },
|
||||
{ qe: 0x1c01, nmps: 13, nlps: 20, switchFlag: 0 },
|
||||
{ qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0 },
|
||||
{ qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1 },
|
||||
{ qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0 },
|
||||
{ qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0 },
|
||||
{ qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0 },
|
||||
{ qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0 },
|
||||
{ qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0 },
|
||||
{ qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0 },
|
||||
{ qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0 },
|
||||
{ qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0 },
|
||||
{ qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0 },
|
||||
{ qe: 0x1c01, nmps: 25, nlps: 22, switchFlag: 0 },
|
||||
{ qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0 },
|
||||
{ qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0 },
|
||||
{ qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0 },
|
||||
{ qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0 },
|
||||
{ qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0 },
|
||||
{ qe: 0x0ac1, nmps: 31, nlps: 28, switchFlag: 0 },
|
||||
{ qe: 0x09c1, nmps: 32, nlps: 29, switchFlag: 0 },
|
||||
{ qe: 0x08a1, nmps: 33, nlps: 30, switchFlag: 0 },
|
||||
{ qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0 },
|
||||
{ qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0 },
|
||||
{ qe: 0x02a1, nmps: 36, nlps: 33, switchFlag: 0 },
|
||||
{ qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0 },
|
||||
{ qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0 },
|
||||
{ qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0 },
|
||||
{ qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0 },
|
||||
{ qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0 },
|
||||
{ qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0 },
|
||||
{ qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0 },
|
||||
{ qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0 },
|
||||
{ qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0 },
|
||||
{ qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0 },
|
||||
{ qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0 },
|
||||
];
|
||||
|
||||
/**
|
||||
@ -86,8 +86,8 @@ class ArithmeticDecoder {
|
||||
|
||||
this.byteIn();
|
||||
|
||||
this.chigh = ((this.chigh << 7) & 0xFFFF) | ((this.clow >> 9) & 0x7F);
|
||||
this.clow = (this.clow << 7) & 0xFFFF;
|
||||
this.chigh = ((this.chigh << 7) & 0xffff) | ((this.clow >> 9) & 0x7f);
|
||||
this.clow = (this.clow << 7) & 0xffff;
|
||||
this.ct -= 7;
|
||||
this.a = 0x8000;
|
||||
}
|
||||
@ -97,25 +97,25 @@ class ArithmeticDecoder {
|
||||
const data = this.data;
|
||||
let bp = this.bp;
|
||||
|
||||
if (data[bp] === 0xFF) {
|
||||
if (data[bp + 1] > 0x8F) {
|
||||
this.clow += 0xFF00;
|
||||
if (data[bp] === 0xff) {
|
||||
if (data[bp + 1] > 0x8f) {
|
||||
this.clow += 0xff00;
|
||||
this.ct = 8;
|
||||
} else {
|
||||
bp++;
|
||||
this.clow += (data[bp] << 9);
|
||||
this.clow += data[bp] << 9;
|
||||
this.ct = 7;
|
||||
this.bp = bp;
|
||||
}
|
||||
} else {
|
||||
bp++;
|
||||
this.clow += bp < this.dataEnd ? (data[bp] << 8) : 0xFF00;
|
||||
this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xff00;
|
||||
this.ct = 8;
|
||||
this.bp = bp;
|
||||
}
|
||||
if (this.clow > 0xFFFF) {
|
||||
this.chigh += (this.clow >> 16);
|
||||
this.clow &= 0xFFFF;
|
||||
if (this.clow > 0xffff) {
|
||||
this.chigh += this.clow >> 16;
|
||||
this.clow &= 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,7 +123,8 @@ class ArithmeticDecoder {
|
||||
readBit(contexts, pos) {
|
||||
// Contexts are packed into 1 byte:
|
||||
// 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 qeIcx = qeTableIcx.qe;
|
||||
let d;
|
||||
@ -168,17 +169,15 @@ class ArithmeticDecoder {
|
||||
}
|
||||
|
||||
a <<= 1;
|
||||
this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1);
|
||||
this.clow = (this.clow << 1) & 0xFFFF;
|
||||
this.chigh = ((this.chigh << 1) & 0xffff) | ((this.clow >> 15) & 1);
|
||||
this.clow = (this.clow << 1) & 0xffff;
|
||||
this.ct--;
|
||||
} while ((a & 0x8000) === 0);
|
||||
this.a = a;
|
||||
|
||||
contexts[pos] = cx_index << 1 | cx_mps;
|
||||
contexts[pos] = (cx_index << 1) | cx_mps;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
ArithmeticDecoder,
|
||||
};
|
||||
export { ArithmeticDecoder };
|
||||
|
181
src/core/bidi.js
181
src/core/bidi.js
@ -13,32 +13,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { warn } from '../shared/util';
|
||||
import { warn } from "../shared/util";
|
||||
|
||||
// Character types for symbols from 0000 to 00FF.
|
||||
// Source: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
|
||||
// prettier-ignore
|
||||
var baseTypes = [
|
||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S',
|
||||
'WS', 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
||||
'BN', 'BN', 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET',
|
||||
'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'ON', 'ES', 'CS', 'ES', 'CS', 'CS',
|
||||
'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',
|
||||
'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', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L',
|
||||
'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', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN',
|
||||
'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'CS', 'ON', 'ET',
|
||||
'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', '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', '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', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
|
||||
"BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "S", "B", "S",
|
||||
"WS", "B", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN",
|
||||
"BN", "BN", "BN", "BN", "B", "B", "B", "S", "WS", "ON", "ON", "ET",
|
||||
"ET", "ET", "ON", "ON", "ON", "ON", "ON", "ES", "CS", "ES", "CS", "CS",
|
||||
"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",
|
||||
"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", "L", "L", "L", "L", "L", "L", "L", "L", "L", "L",
|
||||
"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", "BN", "BN", "BN", "BN", "BN", "BN",
|
||||
"BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "BN", "CS", "ON", "ET",
|
||||
"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", "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", "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", "ON", "L", "L", "L", "L", "L", "L", "L", "L"
|
||||
];
|
||||
|
||||
// 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.
|
||||
// prettier-ignore
|
||||
var arabicTypes = [
|
||||
'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'ON', 'ON', 'AL', 'ET', 'ET', 'AL',
|
||||
'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM',
|
||||
'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', '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',
|
||||
'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', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AN',
|
||||
'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'NSM', 'NSM',
|
||||
'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'EN', 'EN', 'EN', 'EN',
|
||||
'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'
|
||||
"AN", "AN", "AN", "AN", "AN", "AN", "ON", "ON", "AL", "ET", "ET", "AL",
|
||||
"CS", "AL", "ON", "ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM",
|
||||
"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", "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",
|
||||
"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", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AN",
|
||||
"ON", "NSM", "NSM", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "NSM", "NSM",
|
||||
"ON", "NSM", "NSM", "NSM", "NSM", "AL", "AL", "EN", "EN", "EN", "EN",
|
||||
"EN", "EN", "EN", "EN", "EN", "EN", "AL", "AL", "AL", "AL", "AL", "AL"
|
||||
];
|
||||
|
||||
function isOdd(i) {
|
||||
@ -107,7 +107,7 @@ function reverseValues(arr, start, end) {
|
||||
function createBidiText(str, isLTR, vertical) {
|
||||
return {
|
||||
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);
|
||||
|
||||
var charCode = str.charCodeAt(i);
|
||||
var charType = 'L';
|
||||
var charType = "L";
|
||||
if (charCode <= 0x00ff) {
|
||||
charType = baseTypes[charCode];
|
||||
} else if (0x0590 <= charCode && charCode <= 0x05f4) {
|
||||
charType = 'R';
|
||||
charType = "R";
|
||||
} else if (0x0600 <= charCode && charCode <= 0x06ff) {
|
||||
charType = arabicTypes[charCode & 0xff];
|
||||
if (!charType) {
|
||||
warn('Bidi: invalid Unicode character ' + charCode.toString(16));
|
||||
warn("Bidi: invalid Unicode character " + charCode.toString(16));
|
||||
}
|
||||
} else if (0x0700 <= charCode && charCode <= 0x08AC) {
|
||||
charType = 'AL';
|
||||
} else if (0x0700 <= charCode && charCode <= 0x08ac) {
|
||||
charType = "AL";
|
||||
}
|
||||
if (charType === 'R' || charType === 'AL' || charType === 'AN') {
|
||||
if (charType === "R" || charType === "AL" || charType === "AN") {
|
||||
numBidi++;
|
||||
}
|
||||
types[i] = charType;
|
||||
@ -162,7 +162,7 @@ function bidi(str, startLevel, vertical) {
|
||||
}
|
||||
|
||||
if (startLevel === -1) {
|
||||
if ((numBidi / strLength) < 0.3) {
|
||||
if (numBidi / strLength < 0.3) {
|
||||
isLTR = true;
|
||||
startLevel = 0;
|
||||
} else {
|
||||
@ -179,7 +179,7 @@ function bidi(str, startLevel, vertical) {
|
||||
/*
|
||||
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 eor = sor;
|
||||
|
||||
@ -190,7 +190,7 @@ function bidi(str, startLevel, vertical) {
|
||||
*/
|
||||
var lastType = sor;
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
if (types[i] === 'NSM') {
|
||||
if (types[i] === "NSM") {
|
||||
types[i] = lastType;
|
||||
} else {
|
||||
lastType = types[i];
|
||||
@ -206,9 +206,9 @@ function bidi(str, startLevel, vertical) {
|
||||
var t;
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
t = types[i];
|
||||
if (t === 'EN') {
|
||||
types[i] = (lastType === 'AL') ? 'AN' : 'EN';
|
||||
} else if (t === 'R' || t === 'L' || t === 'AL') {
|
||||
if (t === "EN") {
|
||||
types[i] = lastType === "AL" ? "AN" : "EN";
|
||||
} else if (t === "R" || t === "L" || t === "AL") {
|
||||
lastType = t;
|
||||
}
|
||||
}
|
||||
@ -218,8 +218,8 @@ function bidi(str, startLevel, vertical) {
|
||||
*/
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
t = types[i];
|
||||
if (t === 'AL') {
|
||||
types[i] = 'R';
|
||||
if (t === "AL") {
|
||||
types[i] = "R";
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,12 +229,14 @@ function bidi(str, startLevel, vertical) {
|
||||
type changes to that type:
|
||||
*/
|
||||
for (i = 1; i < strLength - 1; ++i) {
|
||||
if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') {
|
||||
types[i] = 'EN';
|
||||
if (types[i] === "ES" && types[i - 1] === "EN" && types[i + 1] === "EN") {
|
||||
types[i] = "EN";
|
||||
}
|
||||
if (types[i] === 'CS' &&
|
||||
(types[i - 1] === 'EN' || types[i - 1] === 'AN') &&
|
||||
types[i + 1] === types[i - 1]) {
|
||||
if (
|
||||
types[i] === "CS" &&
|
||||
(types[i - 1] === "EN" || types[i - 1] === "AN") &&
|
||||
types[i + 1] === types[i - 1]
|
||||
) {
|
||||
types[i] = types[i - 1];
|
||||
}
|
||||
}
|
||||
@ -244,21 +246,21 @@ function bidi(str, startLevel, vertical) {
|
||||
to all European numbers:
|
||||
*/
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
if (types[i] === 'EN') {
|
||||
if (types[i] === "EN") {
|
||||
// do before
|
||||
var j;
|
||||
for (j = i - 1; j >= 0; --j) {
|
||||
if (types[j] !== 'ET') {
|
||||
if (types[j] !== "ET") {
|
||||
break;
|
||||
}
|
||||
types[j] = 'EN';
|
||||
types[j] = "EN";
|
||||
}
|
||||
// do after
|
||||
for (j = i + 1; j < strLength; ++j) {
|
||||
if (types[j] !== 'ET') {
|
||||
if (types[j] !== "ET") {
|
||||
break;
|
||||
}
|
||||
types[j] = 'EN';
|
||||
types[j] = "EN";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -268,8 +270,8 @@ function bidi(str, startLevel, vertical) {
|
||||
*/
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
t = types[i];
|
||||
if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') {
|
||||
types[i] = 'ON';
|
||||
if (t === "WS" || t === "ES" || t === "ET" || t === "CS") {
|
||||
types[i] = "ON";
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,9 +283,9 @@ function bidi(str, startLevel, vertical) {
|
||||
lastType = sor;
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
t = types[i];
|
||||
if (t === 'EN') {
|
||||
types[i] = ((lastType === 'L') ? 'L' : 'EN');
|
||||
} else if (t === 'R' || t === 'L') {
|
||||
if (t === "EN") {
|
||||
types[i] = lastType === "L" ? "L" : "EN";
|
||||
} else if (t === "R" || t === "L") {
|
||||
lastType = t;
|
||||
}
|
||||
}
|
||||
@ -295,8 +297,8 @@ function bidi(str, startLevel, vertical) {
|
||||
end-of-level-run (eor) are used at level run boundaries.
|
||||
*/
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
if (types[i] === 'ON') {
|
||||
var end = findUnequal(types, i + 1, 'ON');
|
||||
if (types[i] === "ON") {
|
||||
var end = findUnequal(types, i + 1, "ON");
|
||||
var before = sor;
|
||||
if (i > 0) {
|
||||
before = types[i - 1];
|
||||
@ -306,11 +308,11 @@ function bidi(str, startLevel, vertical) {
|
||||
if (end + 1 < strLength) {
|
||||
after = types[end + 1];
|
||||
}
|
||||
if (before !== 'L') {
|
||||
before = 'R';
|
||||
if (before !== "L") {
|
||||
before = "R";
|
||||
}
|
||||
if (after !== 'L') {
|
||||
after = 'R';
|
||||
if (after !== "L") {
|
||||
after = "R";
|
||||
}
|
||||
if (before === after) {
|
||||
setValues(types, i, end, before);
|
||||
@ -323,7 +325,7 @@ function bidi(str, startLevel, vertical) {
|
||||
N2. Any remaining neutrals take the embedding direction.
|
||||
*/
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
if (types[i] === 'ON') {
|
||||
if (types[i] === "ON") {
|
||||
types[i] = e;
|
||||
}
|
||||
}
|
||||
@ -338,13 +340,14 @@ function bidi(str, startLevel, vertical) {
|
||||
for (i = 0; i < strLength; ++i) {
|
||||
t = types[i];
|
||||
if (isEven(levels[i])) {
|
||||
if (t === 'R') {
|
||||
if (t === "R") {
|
||||
levels[i] += 1;
|
||||
} else if (t === 'AN' || t === 'EN') {
|
||||
} else if (t === "AN" || t === "EN") {
|
||||
levels[i] += 2;
|
||||
}
|
||||
} else { // isOdd
|
||||
if (t === 'L' || t === 'AN' || t === 'EN') {
|
||||
} else {
|
||||
// isOdd
|
||||
if (t === "L" || t === "AN" || t === "EN") {
|
||||
levels[i] += 1;
|
||||
}
|
||||
}
|
||||
@ -422,13 +425,11 @@ function bidi(str, startLevel, vertical) {
|
||||
// Finally, return string
|
||||
for (i = 0, ii = chars.length; i < ii; ++i) {
|
||||
var ch = chars[i];
|
||||
if (ch === '<' || ch === '>') {
|
||||
chars[i] = '';
|
||||
if (ch === "<" || ch === ">") {
|
||||
chars[i] = "";
|
||||
}
|
||||
}
|
||||
return createBidiText(chars.join(''), isLTR);
|
||||
return createBidiText(chars.join(""), isLTR);
|
||||
}
|
||||
|
||||
export {
|
||||
bidi,
|
||||
};
|
||||
export { bidi };
|
||||
|
@ -25,10 +25,9 @@
|
||||
* or -1 when EOF is reached.
|
||||
*/
|
||||
|
||||
import { info } from '../shared/util';
|
||||
import { info } from "../shared/util";
|
||||
|
||||
let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
|
||||
const ccittEOL = -2;
|
||||
const ccittEOF = -1;
|
||||
const twoDimPass = 0;
|
||||
@ -467,23 +466,23 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
* @param {Object} [options] - Decoding options.
|
||||
*/
|
||||
function CCITTFaxDecoder(source, options = {}) {
|
||||
if (!source || typeof source.next !== 'function') {
|
||||
if (!source || typeof source.next !== "function") {
|
||||
throw new Error('CCITTFaxDecoder - invalid "source" parameter.');
|
||||
}
|
||||
this.source = source;
|
||||
this.eof = false;
|
||||
|
||||
this.encoding = options['K'] || 0;
|
||||
this.eoline = options['EndOfLine'] || false;
|
||||
this.byteAlign = options['EncodedByteAlign'] || false;
|
||||
this.columns = options['Columns'] || 1728;
|
||||
this.rows = options['Rows'] || 0;
|
||||
let eoblock = options['EndOfBlock'];
|
||||
this.encoding = options["K"] || 0;
|
||||
this.eoline = options["EndOfLine"] || false;
|
||||
this.byteAlign = options["EncodedByteAlign"] || false;
|
||||
this.columns = options["Columns"] || 1728;
|
||||
this.rows = options["Rows"] || 0;
|
||||
let eoblock = options["EndOfBlock"];
|
||||
if (eoblock === null || eoblock === undefined) {
|
||||
eoblock = true;
|
||||
}
|
||||
this.eoblock = eoblock;
|
||||
this.black = options['BlackIs1'] || false;
|
||||
this.black = options["BlackIs1"] || false;
|
||||
|
||||
this.codingLine = new Uint32Array(this.columns + 1);
|
||||
this.refLine = new Uint32Array(this.columns + 2);
|
||||
@ -556,27 +555,33 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
code1 = code2 = 0;
|
||||
if (blackPixels) {
|
||||
do {
|
||||
code1 += (code3 = this._getBlackCode());
|
||||
code1 += code3 = this._getBlackCode();
|
||||
} while (code3 >= 64);
|
||||
do {
|
||||
code2 += (code3 = this._getWhiteCode());
|
||||
code2 += code3 = this._getWhiteCode();
|
||||
} while (code3 >= 64);
|
||||
} else {
|
||||
do {
|
||||
code1 += (code3 = this._getWhiteCode());
|
||||
code1 += code3 = this._getWhiteCode();
|
||||
} while (code3 >= 64);
|
||||
do {
|
||||
code2 += (code3 = this._getBlackCode());
|
||||
code2 += code3 = this._getBlackCode();
|
||||
} while (code3 >= 64);
|
||||
}
|
||||
this._addPixels(codingLine[this.codingPos] +
|
||||
code1, blackPixels);
|
||||
this._addPixels(
|
||||
codingLine[this.codingPos] + code1,
|
||||
blackPixels
|
||||
);
|
||||
if (codingLine[this.codingPos] < columns) {
|
||||
this._addPixels(codingLine[this.codingPos] + code2,
|
||||
blackPixels ^ 1);
|
||||
this._addPixels(
|
||||
codingLine[this.codingPos] + code2,
|
||||
blackPixels ^ 1
|
||||
);
|
||||
}
|
||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns) {
|
||||
while (
|
||||
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns
|
||||
) {
|
||||
refPos += 2;
|
||||
}
|
||||
break;
|
||||
@ -585,8 +590,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
blackPixels ^= 1;
|
||||
if (codingLine[this.codingPos] < columns) {
|
||||
++refPos;
|
||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns) {
|
||||
while (
|
||||
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns
|
||||
) {
|
||||
refPos += 2;
|
||||
}
|
||||
}
|
||||
@ -596,8 +603,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
blackPixels ^= 1;
|
||||
if (codingLine[this.codingPos] < columns) {
|
||||
++refPos;
|
||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns) {
|
||||
while (
|
||||
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns
|
||||
) {
|
||||
refPos += 2;
|
||||
}
|
||||
}
|
||||
@ -607,8 +616,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
blackPixels ^= 1;
|
||||
if (codingLine[this.codingPos] < columns) {
|
||||
++refPos;
|
||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns) {
|
||||
while (
|
||||
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns
|
||||
) {
|
||||
refPos += 2;
|
||||
}
|
||||
}
|
||||
@ -618,8 +629,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
blackPixels ^= 1;
|
||||
if (codingLine[this.codingPos] < columns) {
|
||||
++refPos;
|
||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns) {
|
||||
while (
|
||||
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns
|
||||
) {
|
||||
refPos += 2;
|
||||
}
|
||||
}
|
||||
@ -633,8 +646,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
} else {
|
||||
++refPos;
|
||||
}
|
||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns) {
|
||||
while (
|
||||
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns
|
||||
) {
|
||||
refPos += 2;
|
||||
}
|
||||
}
|
||||
@ -648,8 +663,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
} else {
|
||||
++refPos;
|
||||
}
|
||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns) {
|
||||
while (
|
||||
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns
|
||||
) {
|
||||
refPos += 2;
|
||||
}
|
||||
}
|
||||
@ -663,8 +680,10 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
} else {
|
||||
++refPos;
|
||||
}
|
||||
while (refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns) {
|
||||
while (
|
||||
refLine[refPos] <= codingLine[this.codingPos] &&
|
||||
refLine[refPos] < columns
|
||||
) {
|
||||
refPos += 2;
|
||||
}
|
||||
}
|
||||
@ -674,7 +693,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
this.eof = true;
|
||||
break;
|
||||
default:
|
||||
info('bad 2d code');
|
||||
info("bad 2d code");
|
||||
this._addPixels(columns, 0);
|
||||
this.err = true;
|
||||
}
|
||||
@ -687,11 +706,11 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
code1 = 0;
|
||||
if (blackPixels) {
|
||||
do {
|
||||
code1 += (code3 = this._getBlackCode());
|
||||
code1 += code3 = this._getBlackCode();
|
||||
} while (code3 >= 64);
|
||||
} else {
|
||||
do {
|
||||
code1 += (code3 = this._getWhiteCode());
|
||||
code1 += code3 = this._getWhiteCode();
|
||||
} while (code3 >= 64);
|
||||
}
|
||||
this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
|
||||
@ -745,7 +764,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
for (i = 0; i < 4; ++i) {
|
||||
code1 = this._lookBits(12);
|
||||
if (code1 !== 1) {
|
||||
info('bad rtc code: ' + code1);
|
||||
info("bad rtc code: " + code1);
|
||||
}
|
||||
this._eatBits(12);
|
||||
if (this.encoding > 0) {
|
||||
@ -763,7 +782,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
this.eof = true;
|
||||
return -1;
|
||||
}
|
||||
if ((code1 >> 1) === 1) {
|
||||
if (code1 >> 1 === 1) {
|
||||
break;
|
||||
}
|
||||
this._eatBits(1);
|
||||
@ -776,21 +795,21 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
}
|
||||
|
||||
if (codingLine[0] > 0) {
|
||||
this.outputBits = codingLine[this.codingPos = 0];
|
||||
this.outputBits = codingLine[(this.codingPos = 0)];
|
||||
} else {
|
||||
this.outputBits = codingLine[this.codingPos = 1];
|
||||
this.outputBits = codingLine[(this.codingPos = 1)];
|
||||
}
|
||||
this.row++;
|
||||
}
|
||||
|
||||
let c;
|
||||
if (this.outputBits >= 8) {
|
||||
c = (this.codingPos & 1) ? 0 : 0xFF;
|
||||
c = this.codingPos & 1 ? 0 : 0xff;
|
||||
this.outputBits -= 8;
|
||||
if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
|
||||
this.codingPos++;
|
||||
this.outputBits = (codingLine[this.codingPos] -
|
||||
codingLine[this.codingPos - 1]);
|
||||
this.outputBits =
|
||||
codingLine[this.codingPos] - codingLine[this.codingPos - 1];
|
||||
}
|
||||
} else {
|
||||
bits = 8;
|
||||
@ -799,21 +818,21 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
if (this.outputBits > bits) {
|
||||
c <<= bits;
|
||||
if (!(this.codingPos & 1)) {
|
||||
c |= 0xFF >> (8 - bits);
|
||||
c |= 0xff >> (8 - bits);
|
||||
}
|
||||
this.outputBits -= bits;
|
||||
bits = 0;
|
||||
} else {
|
||||
c <<= this.outputBits;
|
||||
if (!(this.codingPos & 1)) {
|
||||
c |= 0xFF >> (8 - this.outputBits);
|
||||
c |= 0xff >> (8 - this.outputBits);
|
||||
}
|
||||
bits -= this.outputBits;
|
||||
this.outputBits = 0;
|
||||
if (codingLine[this.codingPos] < columns) {
|
||||
this.codingPos++;
|
||||
this.outputBits = (codingLine[this.codingPos] -
|
||||
codingLine[this.codingPos - 1]);
|
||||
this.outputBits =
|
||||
codingLine[this.codingPos] - codingLine[this.codingPos - 1];
|
||||
} else if (bits > 0) {
|
||||
c <<= bits;
|
||||
bits = 0;
|
||||
@ -822,7 +841,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
} while (bits);
|
||||
}
|
||||
if (this.black) {
|
||||
c ^= 0xFF;
|
||||
c ^= 0xff;
|
||||
}
|
||||
return c;
|
||||
},
|
||||
@ -836,7 +855,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
|
||||
if (a1 > codingLine[codingPos]) {
|
||||
if (a1 > this.columns) {
|
||||
info('row is wrong length');
|
||||
info("row is wrong length");
|
||||
this.err = true;
|
||||
a1 = this.columns;
|
||||
}
|
||||
@ -858,7 +877,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
|
||||
if (a1 > codingLine[codingPos]) {
|
||||
if (a1 > this.columns) {
|
||||
info('row is wrong length');
|
||||
info("row is wrong length");
|
||||
this.err = true;
|
||||
a1 = this.columns;
|
||||
}
|
||||
@ -869,7 +888,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
codingLine[codingPos] = a1;
|
||||
} else if (a1 < codingLine[codingPos]) {
|
||||
if (a1 < 0) {
|
||||
info('invalid code');
|
||||
info("invalid code");
|
||||
this.err = true;
|
||||
a1 = 0;
|
||||
}
|
||||
@ -931,7 +950,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
return result[1];
|
||||
}
|
||||
}
|
||||
info('Bad two dim code');
|
||||
info("Bad two dim code");
|
||||
return ccittEOF;
|
||||
},
|
||||
|
||||
@ -947,7 +966,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((code >> 5) === 0) {
|
||||
if (code >> 5 === 0) {
|
||||
p = whiteTable1[code];
|
||||
} else {
|
||||
p = whiteTable2[code >> 3];
|
||||
@ -968,7 +987,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
return result[1];
|
||||
}
|
||||
}
|
||||
info('bad white code');
|
||||
info("bad white code");
|
||||
this._eatBits(1);
|
||||
return 1;
|
||||
},
|
||||
@ -983,9 +1002,9 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
if (code === ccittEOF) {
|
||||
return 1;
|
||||
}
|
||||
if ((code >> 7) === 0) {
|
||||
if (code >> 7 === 0) {
|
||||
p = blackTable1[code];
|
||||
} else if ((code >> 9) === 0 && (code >> 7) !== 0) {
|
||||
} else if (code >> 9 === 0 && code >> 7 !== 0) {
|
||||
p = blackTable2[(code >> 1) - 64];
|
||||
} else {
|
||||
p = blackTable3[code >> 7];
|
||||
@ -1011,7 +1030,7 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
return result[1];
|
||||
}
|
||||
}
|
||||
info('bad black code');
|
||||
info("bad black code");
|
||||
this._eatBits(1);
|
||||
return 1;
|
||||
},
|
||||
@ -1026,13 +1045,12 @@ let CCITTFaxDecoder = (function CCITTFaxDecoder() {
|
||||
if (this.inputBits === 0) {
|
||||
return ccittEOF;
|
||||
}
|
||||
return ((this.inputBuf << (n - this.inputBits)) &
|
||||
(0xFFFF >> (16 - n)));
|
||||
return (this.inputBuf << (n - this.inputBits)) & (0xffff >> (16 - n));
|
||||
}
|
||||
this.inputBuf = (this.inputBuf << 8) | c;
|
||||
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;
|
||||
})();
|
||||
|
||||
export {
|
||||
CCITTFaxDecoder,
|
||||
};
|
||||
export { CCITTFaxDecoder };
|
||||
|
@ -13,9 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Dict, isDict } from './primitives';
|
||||
import { CCITTFaxDecoder } from './ccitt';
|
||||
import { DecodeStream } from './stream';
|
||||
import { Dict, isDict } from "./primitives";
|
||||
import { CCITTFaxDecoder } from "./ccitt";
|
||||
import { DecodeStream } from "./stream";
|
||||
|
||||
var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
||||
function CCITTFaxStream(str, maybeLength, params) {
|
||||
@ -32,13 +32,13 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
||||
},
|
||||
};
|
||||
this.ccittFaxDecoder = new CCITTFaxDecoder(source, {
|
||||
K: params.get('K'),
|
||||
EndOfLine: params.get('EndOfLine'),
|
||||
EncodedByteAlign: params.get('EncodedByteAlign'),
|
||||
Columns: params.get('Columns'),
|
||||
Rows: params.get('Rows'),
|
||||
EndOfBlock: params.get('EndOfBlock'),
|
||||
BlackIs1: params.get('BlackIs1'),
|
||||
K: params.get("K"),
|
||||
EndOfLine: params.get("EndOfLine"),
|
||||
EncodedByteAlign: params.get("EncodedByteAlign"),
|
||||
Columns: params.get("Columns"),
|
||||
Rows: params.get("Rows"),
|
||||
EndOfBlock: params.get("EndOfBlock"),
|
||||
BlackIs1: params.get("BlackIs1"),
|
||||
});
|
||||
|
||||
DecodeStream.call(this, maybeLength);
|
||||
@ -61,6 +61,4 @@ var CCITTFaxStream = (function CCITTFaxStreamClosure() {
|
||||
return CCITTFaxStream;
|
||||
})();
|
||||
|
||||
export {
|
||||
CCITTFaxStream,
|
||||
};
|
||||
export { CCITTFaxStream };
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,109 +16,105 @@
|
||||
|
||||
// prettier-ignore
|
||||
const ISOAdobeCharset = [
|
||||
'.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar',
|
||||
'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright',
|
||||
'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero',
|
||||
'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
|
||||
'nine', 'colon', 'semicolon', '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', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore',
|
||||
'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',
|
||||
'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent',
|
||||
'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
|
||||
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
|
||||
'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl',
|
||||
'periodcentered', 'paragraph', 'bullet', 'quotesinglbase',
|
||||
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
|
||||
'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde',
|
||||
'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla',
|
||||
'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine',
|
||||
'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash',
|
||||
'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu',
|
||||
'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter',
|
||||
'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior',
|
||||
'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright',
|
||||
'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde',
|
||||
'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute',
|
||||
'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex',
|
||||
'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex',
|
||||
'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute',
|
||||
'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla',
|
||||
'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex',
|
||||
'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis',
|
||||
'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis',
|
||||
'ugrave', 'yacute', 'ydieresis', 'zcaron'
|
||||
".notdef", "space", "exclam", "quotedbl", "numbersign", "dollar",
|
||||
"percent", "ampersand", "quoteright", "parenleft", "parenright",
|
||||
"asterisk", "plus", "comma", "hyphen", "period", "slash", "zero",
|
||||
"one", "two", "three", "four", "five", "six", "seven", "eight",
|
||||
"nine", "colon", "semicolon", "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", "V", "W", "X", "Y", "Z",
|
||||
"bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
|
||||
"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",
|
||||
"braceleft", "bar", "braceright", "asciitilde", "exclamdown", "cent",
|
||||
"sterling", "fraction", "yen", "florin", "section", "currency",
|
||||
"quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
|
||||
"guilsinglright", "fi", "fl", "endash", "dagger", "daggerdbl",
|
||||
"periodcentered", "paragraph", "bullet", "quotesinglbase",
|
||||
"quotedblbase", "quotedblright", "guillemotright", "ellipsis",
|
||||
"perthousand", "questiondown", "grave", "acute", "circumflex", "tilde",
|
||||
"macron", "breve", "dotaccent", "dieresis", "ring", "cedilla",
|
||||
"hungarumlaut", "ogonek", "caron", "emdash", "AE", "ordfeminine",
|
||||
"Lslash", "Oslash", "OE", "ordmasculine", "ae", "dotlessi", "lslash",
|
||||
"oslash", "oe", "germandbls", "onesuperior", "logicalnot", "mu",
|
||||
"trademark", "Eth", "onehalf", "plusminus", "Thorn", "onequarter",
|
||||
"divide", "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
|
||||
"registered", "minus", "eth", "multiply", "threesuperior", "copyright",
|
||||
"Aacute", "Acircumflex", "Adieresis", "Agrave", "Aring", "Atilde",
|
||||
"Ccedilla", "Eacute", "Ecircumflex", "Edieresis", "Egrave", "Iacute",
|
||||
"Icircumflex", "Idieresis", "Igrave", "Ntilde", "Oacute", "Ocircumflex",
|
||||
"Odieresis", "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
|
||||
"Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron", "aacute",
|
||||
"acircumflex", "adieresis", "agrave", "aring", "atilde", "ccedilla",
|
||||
"eacute", "ecircumflex", "edieresis", "egrave", "iacute", "icircumflex",
|
||||
"idieresis", "igrave", "ntilde", "oacute", "ocircumflex", "odieresis",
|
||||
"ograve", "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
|
||||
"ugrave", "yacute", "ydieresis", "zcaron"
|
||||
];
|
||||
|
||||
// prettier-ignore
|
||||
const ExpertCharset = [
|
||||
'.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle',
|
||||
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
|
||||
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
|
||||
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
|
||||
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
|
||||
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle',
|
||||
'colon', 'semicolon', 'commasuperior', 'threequartersemdash',
|
||||
'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior',
|
||||
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
||||
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
||||
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
||||
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
|
||||
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
|
||||
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
|
||||
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
|
||||
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
|
||||
'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle',
|
||||
'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall',
|
||||
'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall',
|
||||
'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall',
|
||||
'Cedillasmall', 'onequarter', 'onehalf', 'threequarters',
|
||||
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
||||
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
||||
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
||||
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
||||
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
||||
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
||||
'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall',
|
||||
'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall',
|
||||
'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
|
||||
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
|
||||
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
|
||||
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
|
||||
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
|
||||
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
|
||||
'Ydieresissmall'
|
||||
".notdef", "space", "exclamsmall", "Hungarumlautsmall", "dollaroldstyle",
|
||||
"dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior",
|
||||
"parenrightsuperior", "twodotenleader", "onedotenleader", "comma",
|
||||
"hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle",
|
||||
"twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
|
||||
"sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle",
|
||||
"colon", "semicolon", "commasuperior", "threequartersemdash",
|
||||
"periodsuperior", "questionsmall", "asuperior", "bsuperior",
|
||||
"centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
|
||||
"msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
|
||||
"tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior",
|
||||
"parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
|
||||
"Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall",
|
||||
"Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
|
||||
"Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
|
||||
"Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary",
|
||||
"onefitted", "rupiah", "Tildesmall", "exclamdownsmall", "centoldstyle",
|
||||
"Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall",
|
||||
"Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall",
|
||||
"figuredash", "hypheninferior", "Ogoneksmall", "Ringsmall",
|
||||
"Cedillasmall", "onequarter", "onehalf", "threequarters",
|
||||
"questiondownsmall", "oneeighth", "threeeighths", "fiveeighths",
|
||||
"seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior",
|
||||
"twosuperior", "threesuperior", "foursuperior", "fivesuperior",
|
||||
"sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior",
|
||||
"zeroinferior", "oneinferior", "twoinferior", "threeinferior",
|
||||
"fourinferior", "fiveinferior", "sixinferior", "seveninferior",
|
||||
"eightinferior", "nineinferior", "centinferior", "dollarinferior",
|
||||
"periodinferior", "commainferior", "Agravesmall", "Aacutesmall",
|
||||
"Acircumflexsmall", "Atildesmall", "Adieresissmall", "Aringsmall",
|
||||
"AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
|
||||
"Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
|
||||
"Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
|
||||
"Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
|
||||
"Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall",
|
||||
"Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall",
|
||||
"Ydieresissmall"
|
||||
];
|
||||
|
||||
// prettier-ignore
|
||||
const ExpertSubsetCharset = [
|
||||
'.notdef', 'space', 'dollaroldstyle', 'dollarsuperior',
|
||||
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
|
||||
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction',
|
||||
'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle',
|
||||
'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle',
|
||||
'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior',
|
||||
'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior',
|
||||
'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior',
|
||||
'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior',
|
||||
'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior',
|
||||
'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted',
|
||||
'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter',
|
||||
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||
'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior',
|
||||
'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior',
|
||||
'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior',
|
||||
'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior',
|
||||
'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior',
|
||||
'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior',
|
||||
'periodinferior', 'commainferior'
|
||||
".notdef", "space", "dollaroldstyle", "dollarsuperior",
|
||||
"parenleftsuperior", "parenrightsuperior", "twodotenleader",
|
||||
"onedotenleader", "comma", "hyphen", "period", "fraction",
|
||||
"zerooldstyle", "oneoldstyle", "twooldstyle", "threeoldstyle",
|
||||
"fouroldstyle", "fiveoldstyle", "sixoldstyle", "sevenoldstyle",
|
||||
"eightoldstyle", "nineoldstyle", "colon", "semicolon", "commasuperior",
|
||||
"threequartersemdash", "periodsuperior", "asuperior", "bsuperior",
|
||||
"centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
|
||||
"msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
|
||||
"tsuperior", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior",
|
||||
"parenrightinferior", "hyphensuperior", "colonmonetary", "onefitted",
|
||||
"rupiah", "centoldstyle", "figuredash", "hypheninferior", "onequarter",
|
||||
"onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths",
|
||||
"seveneighths", "onethird", "twothirds", "zerosuperior", "onesuperior",
|
||||
"twosuperior", "threesuperior", "foursuperior", "fivesuperior",
|
||||
"sixsuperior", "sevensuperior", "eightsuperior", "ninesuperior",
|
||||
"zeroinferior", "oneinferior", "twoinferior", "threeinferior",
|
||||
"fourinferior", "fiveinferior", "sixinferior", "seveninferior",
|
||||
"eightinferior", "nineinferior", "centinferior", "dollarinferior",
|
||||
"periodinferior", "commainferior"
|
||||
];
|
||||
|
||||
export {
|
||||
ISOAdobeCharset,
|
||||
ExpertCharset,
|
||||
ExpertSubsetCharset,
|
||||
};
|
||||
export { ISOAdobeCharset, ExpertCharset, ExpertSubsetCharset };
|
||||
|
@ -15,9 +15,12 @@
|
||||
/* eslint no-var: error */
|
||||
|
||||
import {
|
||||
arrayByteLength, arraysToBytes, createPromiseCapability, isEmptyObj
|
||||
} from '../shared/util';
|
||||
import { MissingDataException } from './core_utils';
|
||||
arrayByteLength,
|
||||
arraysToBytes,
|
||||
createPromiseCapability,
|
||||
isEmptyObj,
|
||||
} from "../shared/util";
|
||||
import { MissingDataException } from "./core_utils";
|
||||
|
||||
class ChunkedStream {
|
||||
constructor(length, chunkSize, manager) {
|
||||
@ -86,8 +89,10 @@ class ChunkedStream {
|
||||
this.bytes.set(new Uint8Array(data), position);
|
||||
position += data.byteLength;
|
||||
this.progressiveDataLength = position;
|
||||
const endChunk = position >= this.end ? this.numChunks :
|
||||
Math.floor(position / this.chunkSize);
|
||||
const endChunk =
|
||||
position >= this.end
|
||||
? this.numChunks
|
||||
: Math.floor(position / this.chunkSize);
|
||||
|
||||
for (let curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
|
||||
if (!this.loadedChunks[curChunk]) {
|
||||
@ -194,7 +199,7 @@ class ChunkedStream {
|
||||
}
|
||||
const subarray = bytes.subarray(pos, strEnd);
|
||||
// `this.bytes` is always a `Uint8Array` here.
|
||||
return (forceClamped ? new Uint8ClampedArray(subarray) : subarray);
|
||||
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
|
||||
}
|
||||
|
||||
let end = pos + length;
|
||||
@ -208,7 +213,7 @@ class ChunkedStream {
|
||||
this.pos = end;
|
||||
const subarray = bytes.subarray(pos, end);
|
||||
// `this.bytes` is always a `Uint8Array` here.
|
||||
return (forceClamped ? new Uint8ClampedArray(subarray) : subarray);
|
||||
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
|
||||
}
|
||||
|
||||
peekByte() {
|
||||
@ -332,16 +337,17 @@ class ChunkedStreamManager {
|
||||
rangeReader.onProgress = this.onProgress.bind(this);
|
||||
}
|
||||
|
||||
let chunks = [], loaded = 0;
|
||||
let chunks = [],
|
||||
loaded = 0;
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const readChunk = (chunk) => {
|
||||
const readChunk = chunk => {
|
||||
try {
|
||||
if (!chunk.done) {
|
||||
const data = chunk.value;
|
||||
chunks.push(data);
|
||||
loaded += arrayByteLength(data);
|
||||
if (rangeReader.isStreamingSupported) {
|
||||
this.onProgress({ loaded, });
|
||||
this.onProgress({ loaded });
|
||||
}
|
||||
rangeReader.read().then(readChunk, reject);
|
||||
return;
|
||||
@ -355,11 +361,11 @@ class ChunkedStreamManager {
|
||||
};
|
||||
rangeReader.read().then(readChunk, reject);
|
||||
});
|
||||
promise.then((data) => {
|
||||
promise.then(data => {
|
||||
if (this.aborted) {
|
||||
return; // Ignoring any data after abort.
|
||||
}
|
||||
this.onReceiveData({ chunk: data, begin, });
|
||||
this.onReceiveData({ chunk: data, begin });
|
||||
});
|
||||
// TODO check errors
|
||||
}
|
||||
@ -470,13 +476,11 @@ class ChunkedStreamManager {
|
||||
}
|
||||
|
||||
if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
|
||||
groupedChunks.push({ beginChunk,
|
||||
endChunk: prevChunk + 1, });
|
||||
groupedChunks.push({ beginChunk, endChunk: prevChunk + 1 });
|
||||
beginChunk = chunk;
|
||||
}
|
||||
if (i + 1 === chunks.length) {
|
||||
groupedChunks.push({ beginChunk,
|
||||
endChunk: chunk + 1, });
|
||||
groupedChunks.push({ beginChunk, endChunk: chunk + 1 });
|
||||
}
|
||||
|
||||
prevChunk = chunk;
|
||||
@ -485,7 +489,7 @@ class ChunkedStreamManager {
|
||||
}
|
||||
|
||||
onProgress(args) {
|
||||
this.msgHandler.send('DocProgress', {
|
||||
this.msgHandler.send("DocProgress", {
|
||||
loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded,
|
||||
total: this.length,
|
||||
});
|
||||
@ -498,8 +502,10 @@ class ChunkedStreamManager {
|
||||
const end = begin + chunk.byteLength;
|
||||
|
||||
const beginChunk = Math.floor(begin / this.chunkSize);
|
||||
const endChunk = end < this.length ? Math.floor(end / this.chunkSize) :
|
||||
Math.ceil(end / this.chunkSize);
|
||||
const endChunk =
|
||||
end < this.length
|
||||
? Math.floor(end / this.chunkSize)
|
||||
: Math.ceil(end / this.chunkSize);
|
||||
|
||||
if (isProgressive) {
|
||||
this.stream.onReceiveProgressiveData(chunk);
|
||||
@ -557,7 +563,7 @@ class ChunkedStreamManager {
|
||||
capability.resolve();
|
||||
}
|
||||
|
||||
this.msgHandler.send('DocProgress', {
|
||||
this.msgHandler.send("DocProgress", {
|
||||
loaded: this.stream.numChunksLoaded * this.chunkSize,
|
||||
total: this.length,
|
||||
});
|
||||
@ -586,7 +592,4 @@ class ChunkedStreamManager {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
ChunkedStream,
|
||||
ChunkedStreamManager,
|
||||
};
|
||||
export { ChunkedStream, ChunkedStreamManager };
|
||||
|
556
src/core/cmap.js
556
src/core/cmap.js
@ -14,184 +14,189 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
CMapCompressionType, FormatError, isString, unreachable, warn
|
||||
} from '../shared/util';
|
||||
import { isCmd, isEOF, isName, isStream } from './primitives';
|
||||
import { Lexer } from './parser';
|
||||
import { MissingDataException } from './core_utils';
|
||||
import { Stream } from './stream';
|
||||
CMapCompressionType,
|
||||
FormatError,
|
||||
isString,
|
||||
unreachable,
|
||||
warn,
|
||||
} 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 = [
|
||||
// << Start unicode maps.
|
||||
'Adobe-GB1-UCS2',
|
||||
'Adobe-CNS1-UCS2',
|
||||
'Adobe-Japan1-UCS2',
|
||||
'Adobe-Korea1-UCS2',
|
||||
// >> End unicode maps.
|
||||
'78-EUC-H',
|
||||
'78-EUC-V',
|
||||
'78-H',
|
||||
'78-RKSJ-H',
|
||||
'78-RKSJ-V',
|
||||
'78-V',
|
||||
'78ms-RKSJ-H',
|
||||
'78ms-RKSJ-V',
|
||||
'83pv-RKSJ-H',
|
||||
'90ms-RKSJ-H',
|
||||
'90ms-RKSJ-V',
|
||||
'90msp-RKSJ-H',
|
||||
'90msp-RKSJ-V',
|
||||
'90pv-RKSJ-H',
|
||||
'90pv-RKSJ-V',
|
||||
'Add-H',
|
||||
'Add-RKSJ-H',
|
||||
'Add-RKSJ-V',
|
||||
'Add-V',
|
||||
'Adobe-CNS1-0',
|
||||
'Adobe-CNS1-1',
|
||||
'Adobe-CNS1-2',
|
||||
'Adobe-CNS1-3',
|
||||
'Adobe-CNS1-4',
|
||||
'Adobe-CNS1-5',
|
||||
'Adobe-CNS1-6',
|
||||
'Adobe-GB1-0',
|
||||
'Adobe-GB1-1',
|
||||
'Adobe-GB1-2',
|
||||
'Adobe-GB1-3',
|
||||
'Adobe-GB1-4',
|
||||
'Adobe-GB1-5',
|
||||
'Adobe-Japan1-0',
|
||||
'Adobe-Japan1-1',
|
||||
'Adobe-Japan1-2',
|
||||
'Adobe-Japan1-3',
|
||||
'Adobe-Japan1-4',
|
||||
'Adobe-Japan1-5',
|
||||
'Adobe-Japan1-6',
|
||||
'Adobe-Korea1-0',
|
||||
'Adobe-Korea1-1',
|
||||
'Adobe-Korea1-2',
|
||||
'B5-H',
|
||||
'B5-V',
|
||||
'B5pc-H',
|
||||
'B5pc-V',
|
||||
'CNS-EUC-H',
|
||||
'CNS-EUC-V',
|
||||
'CNS1-H',
|
||||
'CNS1-V',
|
||||
'CNS2-H',
|
||||
'CNS2-V',
|
||||
'ETHK-B5-H',
|
||||
'ETHK-B5-V',
|
||||
'ETen-B5-H',
|
||||
'ETen-B5-V',
|
||||
'ETenms-B5-H',
|
||||
'ETenms-B5-V',
|
||||
'EUC-H',
|
||||
'EUC-V',
|
||||
'Ext-H',
|
||||
'Ext-RKSJ-H',
|
||||
'Ext-RKSJ-V',
|
||||
'Ext-V',
|
||||
'GB-EUC-H',
|
||||
'GB-EUC-V',
|
||||
'GB-H',
|
||||
'GB-V',
|
||||
'GBK-EUC-H',
|
||||
'GBK-EUC-V',
|
||||
'GBK2K-H',
|
||||
'GBK2K-V',
|
||||
'GBKp-EUC-H',
|
||||
'GBKp-EUC-V',
|
||||
'GBT-EUC-H',
|
||||
'GBT-EUC-V',
|
||||
'GBT-H',
|
||||
'GBT-V',
|
||||
'GBTpc-EUC-H',
|
||||
'GBTpc-EUC-V',
|
||||
'GBpc-EUC-H',
|
||||
'GBpc-EUC-V',
|
||||
'H',
|
||||
'HKdla-B5-H',
|
||||
'HKdla-B5-V',
|
||||
'HKdlb-B5-H',
|
||||
'HKdlb-B5-V',
|
||||
'HKgccs-B5-H',
|
||||
'HKgccs-B5-V',
|
||||
'HKm314-B5-H',
|
||||
'HKm314-B5-V',
|
||||
'HKm471-B5-H',
|
||||
'HKm471-B5-V',
|
||||
'HKscs-B5-H',
|
||||
'HKscs-B5-V',
|
||||
'Hankaku',
|
||||
'Hiragana',
|
||||
'KSC-EUC-H',
|
||||
'KSC-EUC-V',
|
||||
'KSC-H',
|
||||
'KSC-Johab-H',
|
||||
'KSC-Johab-V',
|
||||
'KSC-V',
|
||||
'KSCms-UHC-H',
|
||||
'KSCms-UHC-HW-H',
|
||||
'KSCms-UHC-HW-V',
|
||||
'KSCms-UHC-V',
|
||||
'KSCpc-EUC-H',
|
||||
'KSCpc-EUC-V',
|
||||
'Katakana',
|
||||
'NWP-H',
|
||||
'NWP-V',
|
||||
'RKSJ-H',
|
||||
'RKSJ-V',
|
||||
'Roman',
|
||||
'UniCNS-UCS2-H',
|
||||
'UniCNS-UCS2-V',
|
||||
'UniCNS-UTF16-H',
|
||||
'UniCNS-UTF16-V',
|
||||
'UniCNS-UTF32-H',
|
||||
'UniCNS-UTF32-V',
|
||||
'UniCNS-UTF8-H',
|
||||
'UniCNS-UTF8-V',
|
||||
'UniGB-UCS2-H',
|
||||
'UniGB-UCS2-V',
|
||||
'UniGB-UTF16-H',
|
||||
'UniGB-UTF16-V',
|
||||
'UniGB-UTF32-H',
|
||||
'UniGB-UTF32-V',
|
||||
'UniGB-UTF8-H',
|
||||
'UniGB-UTF8-V',
|
||||
'UniJIS-UCS2-H',
|
||||
'UniJIS-UCS2-HW-H',
|
||||
'UniJIS-UCS2-HW-V',
|
||||
'UniJIS-UCS2-V',
|
||||
'UniJIS-UTF16-H',
|
||||
'UniJIS-UTF16-V',
|
||||
'UniJIS-UTF32-H',
|
||||
'UniJIS-UTF32-V',
|
||||
'UniJIS-UTF8-H',
|
||||
'UniJIS-UTF8-V',
|
||||
'UniJIS2004-UTF16-H',
|
||||
'UniJIS2004-UTF16-V',
|
||||
'UniJIS2004-UTF32-H',
|
||||
'UniJIS2004-UTF32-V',
|
||||
'UniJIS2004-UTF8-H',
|
||||
'UniJIS2004-UTF8-V',
|
||||
'UniJISPro-UCS2-HW-V',
|
||||
'UniJISPro-UCS2-V',
|
||||
'UniJISPro-UTF8-V',
|
||||
'UniJISX0213-UTF32-H',
|
||||
'UniJISX0213-UTF32-V',
|
||||
'UniJISX02132004-UTF32-H',
|
||||
'UniJISX02132004-UTF32-V',
|
||||
'UniKS-UCS2-H',
|
||||
'UniKS-UCS2-V',
|
||||
'UniKS-UTF16-H',
|
||||
'UniKS-UTF16-V',
|
||||
'UniKS-UTF32-H',
|
||||
'UniKS-UTF32-V',
|
||||
'UniKS-UTF8-H',
|
||||
'UniKS-UTF8-V',
|
||||
'V',
|
||||
'WP-Symbol'];
|
||||
// << Start unicode maps.
|
||||
"Adobe-GB1-UCS2",
|
||||
"Adobe-CNS1-UCS2",
|
||||
"Adobe-Japan1-UCS2",
|
||||
"Adobe-Korea1-UCS2",
|
||||
// >> End unicode maps.
|
||||
"78-EUC-H",
|
||||
"78-EUC-V",
|
||||
"78-H",
|
||||
"78-RKSJ-H",
|
||||
"78-RKSJ-V",
|
||||
"78-V",
|
||||
"78ms-RKSJ-H",
|
||||
"78ms-RKSJ-V",
|
||||
"83pv-RKSJ-H",
|
||||
"90ms-RKSJ-H",
|
||||
"90ms-RKSJ-V",
|
||||
"90msp-RKSJ-H",
|
||||
"90msp-RKSJ-V",
|
||||
"90pv-RKSJ-H",
|
||||
"90pv-RKSJ-V",
|
||||
"Add-H",
|
||||
"Add-RKSJ-H",
|
||||
"Add-RKSJ-V",
|
||||
"Add-V",
|
||||
"Adobe-CNS1-0",
|
||||
"Adobe-CNS1-1",
|
||||
"Adobe-CNS1-2",
|
||||
"Adobe-CNS1-3",
|
||||
"Adobe-CNS1-4",
|
||||
"Adobe-CNS1-5",
|
||||
"Adobe-CNS1-6",
|
||||
"Adobe-GB1-0",
|
||||
"Adobe-GB1-1",
|
||||
"Adobe-GB1-2",
|
||||
"Adobe-GB1-3",
|
||||
"Adobe-GB1-4",
|
||||
"Adobe-GB1-5",
|
||||
"Adobe-Japan1-0",
|
||||
"Adobe-Japan1-1",
|
||||
"Adobe-Japan1-2",
|
||||
"Adobe-Japan1-3",
|
||||
"Adobe-Japan1-4",
|
||||
"Adobe-Japan1-5",
|
||||
"Adobe-Japan1-6",
|
||||
"Adobe-Korea1-0",
|
||||
"Adobe-Korea1-1",
|
||||
"Adobe-Korea1-2",
|
||||
"B5-H",
|
||||
"B5-V",
|
||||
"B5pc-H",
|
||||
"B5pc-V",
|
||||
"CNS-EUC-H",
|
||||
"CNS-EUC-V",
|
||||
"CNS1-H",
|
||||
"CNS1-V",
|
||||
"CNS2-H",
|
||||
"CNS2-V",
|
||||
"ETHK-B5-H",
|
||||
"ETHK-B5-V",
|
||||
"ETen-B5-H",
|
||||
"ETen-B5-V",
|
||||
"ETenms-B5-H",
|
||||
"ETenms-B5-V",
|
||||
"EUC-H",
|
||||
"EUC-V",
|
||||
"Ext-H",
|
||||
"Ext-RKSJ-H",
|
||||
"Ext-RKSJ-V",
|
||||
"Ext-V",
|
||||
"GB-EUC-H",
|
||||
"GB-EUC-V",
|
||||
"GB-H",
|
||||
"GB-V",
|
||||
"GBK-EUC-H",
|
||||
"GBK-EUC-V",
|
||||
"GBK2K-H",
|
||||
"GBK2K-V",
|
||||
"GBKp-EUC-H",
|
||||
"GBKp-EUC-V",
|
||||
"GBT-EUC-H",
|
||||
"GBT-EUC-V",
|
||||
"GBT-H",
|
||||
"GBT-V",
|
||||
"GBTpc-EUC-H",
|
||||
"GBTpc-EUC-V",
|
||||
"GBpc-EUC-H",
|
||||
"GBpc-EUC-V",
|
||||
"H",
|
||||
"HKdla-B5-H",
|
||||
"HKdla-B5-V",
|
||||
"HKdlb-B5-H",
|
||||
"HKdlb-B5-V",
|
||||
"HKgccs-B5-H",
|
||||
"HKgccs-B5-V",
|
||||
"HKm314-B5-H",
|
||||
"HKm314-B5-V",
|
||||
"HKm471-B5-H",
|
||||
"HKm471-B5-V",
|
||||
"HKscs-B5-H",
|
||||
"HKscs-B5-V",
|
||||
"Hankaku",
|
||||
"Hiragana",
|
||||
"KSC-EUC-H",
|
||||
"KSC-EUC-V",
|
||||
"KSC-H",
|
||||
"KSC-Johab-H",
|
||||
"KSC-Johab-V",
|
||||
"KSC-V",
|
||||
"KSCms-UHC-H",
|
||||
"KSCms-UHC-HW-H",
|
||||
"KSCms-UHC-HW-V",
|
||||
"KSCms-UHC-V",
|
||||
"KSCpc-EUC-H",
|
||||
"KSCpc-EUC-V",
|
||||
"Katakana",
|
||||
"NWP-H",
|
||||
"NWP-V",
|
||||
"RKSJ-H",
|
||||
"RKSJ-V",
|
||||
"Roman",
|
||||
"UniCNS-UCS2-H",
|
||||
"UniCNS-UCS2-V",
|
||||
"UniCNS-UTF16-H",
|
||||
"UniCNS-UTF16-V",
|
||||
"UniCNS-UTF32-H",
|
||||
"UniCNS-UTF32-V",
|
||||
"UniCNS-UTF8-H",
|
||||
"UniCNS-UTF8-V",
|
||||
"UniGB-UCS2-H",
|
||||
"UniGB-UCS2-V",
|
||||
"UniGB-UTF16-H",
|
||||
"UniGB-UTF16-V",
|
||||
"UniGB-UTF32-H",
|
||||
"UniGB-UTF32-V",
|
||||
"UniGB-UTF8-H",
|
||||
"UniGB-UTF8-V",
|
||||
"UniJIS-UCS2-H",
|
||||
"UniJIS-UCS2-HW-H",
|
||||
"UniJIS-UCS2-HW-V",
|
||||
"UniJIS-UCS2-V",
|
||||
"UniJIS-UTF16-H",
|
||||
"UniJIS-UTF16-V",
|
||||
"UniJIS-UTF32-H",
|
||||
"UniJIS-UTF32-V",
|
||||
"UniJIS-UTF8-H",
|
||||
"UniJIS-UTF8-V",
|
||||
"UniJIS2004-UTF16-H",
|
||||
"UniJIS2004-UTF16-V",
|
||||
"UniJIS2004-UTF32-H",
|
||||
"UniJIS2004-UTF32-V",
|
||||
"UniJIS2004-UTF8-H",
|
||||
"UniJIS2004-UTF8-V",
|
||||
"UniJISPro-UCS2-HW-V",
|
||||
"UniJISPro-UCS2-V",
|
||||
"UniJISPro-UTF8-V",
|
||||
"UniJISX0213-UTF32-H",
|
||||
"UniJISX0213-UTF32-V",
|
||||
"UniJISX02132004-UTF32-H",
|
||||
"UniJISX02132004-UTF32-V",
|
||||
"UniKS-UCS2-H",
|
||||
"UniKS-UCS2-V",
|
||||
"UniKS-UTF16-H",
|
||||
"UniKS-UTF16-V",
|
||||
"UniKS-UTF32-H",
|
||||
"UniKS-UTF32-V",
|
||||
"UniKS-UTF8-H",
|
||||
"UniKS-UTF8-V",
|
||||
"V",
|
||||
"WP-Symbol",
|
||||
];
|
||||
|
||||
// CMap, not to be confused with TrueType's cmap.
|
||||
class CMap {
|
||||
@ -206,7 +211,7 @@ class CMap {
|
||||
// - bf chars are variable-length byte sequences, stored as strings, with
|
||||
// one byte per character.
|
||||
this._map = [];
|
||||
this.name = '';
|
||||
this.name = "";
|
||||
this.vertical = false;
|
||||
this.useCMap = null;
|
||||
this.builtInCMap = builtInCMap;
|
||||
@ -228,13 +233,15 @@ class CMap {
|
||||
while (low <= high) {
|
||||
this._map[low++] = dstLow;
|
||||
// Only the last byte has to be incremented.
|
||||
dstLow = dstLow.substring(0, lastByte) +
|
||||
dstLow =
|
||||
dstLow.substring(0, lastByte) +
|
||||
String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
mapBfRangeToArray(low, high, array) {
|
||||
let i = 0, ii = array.length;
|
||||
let i = 0,
|
||||
ii = array.length;
|
||||
while (low <= high && i < ii) {
|
||||
this._map[low] = array[i++];
|
||||
++low;
|
||||
@ -284,7 +291,7 @@ class CMap {
|
||||
}
|
||||
for (let charCode in map) {
|
||||
if (map[charCode] === value) {
|
||||
return (charCode | 0);
|
||||
return charCode | 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
@ -303,7 +310,7 @@ class CMap {
|
||||
c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0;
|
||||
// Check each codespace range to see if it falls within.
|
||||
const codespaceRange = codespaceRanges[n];
|
||||
for (let k = 0, kk = codespaceRange.length; k < kk;) {
|
||||
for (let k = 0, kk = codespaceRange.length; k < kk; ) {
|
||||
const low = codespaceRange[k++];
|
||||
const high = codespaceRange[k++];
|
||||
if (c >= low && c <= high) {
|
||||
@ -322,7 +329,7 @@ class CMap {
|
||||
}
|
||||
|
||||
get isIdentityCMap() {
|
||||
if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
|
||||
if (!(this.name === "Identity-H" || this.name === "Identity-V")) {
|
||||
return false;
|
||||
}
|
||||
if (this._map.length !== 0x10000) {
|
||||
@ -348,23 +355,23 @@ class IdentityCMap extends CMap {
|
||||
}
|
||||
|
||||
mapCidRange(low, high, dstLow) {
|
||||
unreachable('should not call mapCidRange');
|
||||
unreachable("should not call mapCidRange");
|
||||
}
|
||||
|
||||
mapBfRange(low, high, dstLow) {
|
||||
unreachable('should not call mapBfRange');
|
||||
unreachable("should not call mapBfRange");
|
||||
}
|
||||
|
||||
mapBfRangeToArray(low, high, array) {
|
||||
unreachable('should not call mapBfRangeToArray');
|
||||
unreachable("should not call mapBfRangeToArray");
|
||||
}
|
||||
|
||||
mapOne(src, dst) {
|
||||
unreachable('should not call mapCidOne');
|
||||
unreachable("should not call mapCidOne");
|
||||
}
|
||||
|
||||
lookup(code) {
|
||||
return (Number.isInteger(code) && code <= 0xffff) ? code : undefined;
|
||||
return Number.isInteger(code) && code <= 0xffff ? code : undefined;
|
||||
}
|
||||
|
||||
contains(code) {
|
||||
@ -378,7 +385,7 @@ class IdentityCMap extends CMap {
|
||||
}
|
||||
|
||||
charCodeOf(value) {
|
||||
return (Number.isInteger(value) && value <= 0xffff) ? value : -1;
|
||||
return Number.isInteger(value) && value <= 0xffff ? value : -1;
|
||||
}
|
||||
|
||||
getMap() {
|
||||
@ -394,8 +401,9 @@ class IdentityCMap extends CMap {
|
||||
return 0x10000;
|
||||
}
|
||||
|
||||
get isIdentityCMap() { // eslint-disable-line getter-return
|
||||
unreachable('should not access .isIdentityCMap');
|
||||
get isIdentityCMap() {
|
||||
// eslint-disable-line getter-return
|
||||
unreachable("should not access .isIdentityCMap");
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,34 +469,36 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
do {
|
||||
var b = this.readByte();
|
||||
if (b < 0) {
|
||||
throw new FormatError('unexpected EOF in bcmap');
|
||||
throw new FormatError("unexpected EOF in bcmap");
|
||||
}
|
||||
last = !(b & 0x80);
|
||||
n = (n << 7) | (b & 0x7F);
|
||||
n = (n << 7) | (b & 0x7f);
|
||||
} while (!last);
|
||||
return n;
|
||||
},
|
||||
readSigned() {
|
||||
var n = this.readNumber();
|
||||
return (n & 1) ? ~(n >>> 1) : n >>> 1;
|
||||
return n & 1 ? ~(n >>> 1) : n >>> 1;
|
||||
},
|
||||
readHex(num, size) {
|
||||
num.set(this.buffer.subarray(this.pos,
|
||||
this.pos + size + 1));
|
||||
num.set(this.buffer.subarray(this.pos, this.pos + size + 1));
|
||||
this.pos += size + 1;
|
||||
},
|
||||
readHexNumber(num, size) {
|
||||
var last;
|
||||
var stack = this.tmpBuf, sp = 0;
|
||||
var stack = this.tmpBuf,
|
||||
sp = 0;
|
||||
do {
|
||||
var b = this.readByte();
|
||||
if (b < 0) {
|
||||
throw new FormatError('unexpected EOF in bcmap');
|
||||
throw new FormatError("unexpected EOF in bcmap");
|
||||
}
|
||||
last = !(b & 0x80);
|
||||
stack[sp++] = b & 0x7F;
|
||||
stack[sp++] = b & 0x7f;
|
||||
} while (!last);
|
||||
var i = size, buffer = 0, bufferSize = 0;
|
||||
var i = size,
|
||||
buffer = 0,
|
||||
bufferSize = 0;
|
||||
while (i >= 0) {
|
||||
while (bufferSize < 8 && stack.length > 0) {
|
||||
buffer = (stack[--sp] << bufferSize) | buffer;
|
||||
@ -511,7 +521,7 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
},
|
||||
readString() {
|
||||
var len = this.readNumber();
|
||||
var s = '';
|
||||
var s = "";
|
||||
for (var i = 0; i < len; i++) {
|
||||
s += String.fromCharCode(this.readNumber());
|
||||
}
|
||||
@ -520,7 +530,7 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
};
|
||||
|
||||
function processBinaryCMap(data, cMap, extend) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var stream = new BinaryCMapStream(data);
|
||||
var header = stream.readByte();
|
||||
cMap.vertical = !!(header & 1);
|
||||
@ -536,8 +546,9 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
var b;
|
||||
while ((b = stream.readByte()) >= 0) {
|
||||
var type = b >> 5;
|
||||
if (type === 7) { // metadata, e.g. comment or usecmap
|
||||
switch (b & 0x1F) {
|
||||
if (type === 7) {
|
||||
// metadata, e.g. comment or usecmap
|
||||
switch (b & 0x1f) {
|
||||
case 0:
|
||||
stream.readString(); // skipping comment
|
||||
break;
|
||||
@ -551,7 +562,7 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
var dataSize = b & 15;
|
||||
|
||||
if (dataSize + 1 > MAX_NUM_SIZE) {
|
||||
throw new Error('processBinaryCMap: Invalid dataSize.');
|
||||
throw new Error("processBinaryCMap: Invalid dataSize.");
|
||||
}
|
||||
|
||||
var ucs2DataSize = 1;
|
||||
@ -562,16 +573,22 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
stream.readHex(start, dataSize);
|
||||
stream.readHexNumber(end, dataSize);
|
||||
addHex(end, start, dataSize);
|
||||
cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize),
|
||||
hexToInt(end, dataSize));
|
||||
cMap.addCodespaceRange(
|
||||
dataSize + 1,
|
||||
hexToInt(start, dataSize),
|
||||
hexToInt(end, dataSize)
|
||||
);
|
||||
for (i = 1; i < subitemsCount; i++) {
|
||||
incHex(end, dataSize);
|
||||
stream.readHexNumber(start, dataSize);
|
||||
addHex(start, end, dataSize);
|
||||
stream.readHexNumber(end, dataSize);
|
||||
addHex(end, start, dataSize);
|
||||
cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize),
|
||||
hexToInt(end, dataSize));
|
||||
cMap.addCodespaceRange(
|
||||
dataSize + 1,
|
||||
hexToInt(start, dataSize),
|
||||
hexToInt(end, dataSize)
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 1: // notdefrange
|
||||
@ -609,8 +626,11 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
stream.readHexNumber(end, dataSize);
|
||||
addHex(end, start, dataSize);
|
||||
code = stream.readNumber();
|
||||
cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize),
|
||||
code);
|
||||
cMap.mapCidRange(
|
||||
hexToInt(start, dataSize),
|
||||
hexToInt(end, dataSize),
|
||||
code
|
||||
);
|
||||
for (i = 1; i < subitemsCount; i++) {
|
||||
incHex(end, dataSize);
|
||||
if (!sequence) {
|
||||
@ -622,15 +642,20 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
stream.readHexNumber(end, dataSize);
|
||||
addHex(end, start, dataSize);
|
||||
code = stream.readNumber();
|
||||
cMap.mapCidRange(hexToInt(start, dataSize),
|
||||
hexToInt(end, dataSize), code);
|
||||
cMap.mapCidRange(
|
||||
hexToInt(start, dataSize),
|
||||
hexToInt(end, dataSize),
|
||||
code
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 4: // bfchar
|
||||
stream.readHex(char, ucs2DataSize);
|
||||
stream.readHex(charCode, dataSize);
|
||||
cMap.mapOne(hexToInt(char, ucs2DataSize),
|
||||
hexToStr(charCode, dataSize));
|
||||
cMap.mapOne(
|
||||
hexToInt(char, ucs2DataSize),
|
||||
hexToStr(charCode, dataSize)
|
||||
);
|
||||
for (i = 1; i < subitemsCount; i++) {
|
||||
incHex(char, ucs2DataSize);
|
||||
if (!sequence) {
|
||||
@ -640,8 +665,10 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
incHex(charCode, dataSize);
|
||||
stream.readHexSigned(tmp, dataSize);
|
||||
addHex(charCode, tmp, dataSize);
|
||||
cMap.mapOne(hexToInt(char, ucs2DataSize),
|
||||
hexToStr(charCode, dataSize));
|
||||
cMap.mapOne(
|
||||
hexToInt(char, ucs2DataSize),
|
||||
hexToStr(charCode, dataSize)
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 5: // bfrange
|
||||
@ -649,9 +676,11 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
stream.readHexNumber(end, ucs2DataSize);
|
||||
addHex(end, start, ucs2DataSize);
|
||||
stream.readHex(charCode, dataSize);
|
||||
cMap.mapBfRange(hexToInt(start, ucs2DataSize),
|
||||
cMap.mapBfRange(
|
||||
hexToInt(start, ucs2DataSize),
|
||||
hexToInt(end, ucs2DataSize),
|
||||
hexToStr(charCode, dataSize));
|
||||
hexToStr(charCode, dataSize)
|
||||
);
|
||||
for (i = 1; i < subitemsCount; i++) {
|
||||
incHex(end, ucs2DataSize);
|
||||
if (!sequence) {
|
||||
@ -663,13 +692,15 @@ var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
stream.readHexNumber(end, ucs2DataSize);
|
||||
addHex(end, start, ucs2DataSize);
|
||||
stream.readHex(charCode, dataSize);
|
||||
cMap.mapBfRange(hexToInt(start, ucs2DataSize),
|
||||
cMap.mapBfRange(
|
||||
hexToInt(start, ucs2DataSize),
|
||||
hexToInt(end, ucs2DataSize),
|
||||
hexToStr(charCode, dataSize));
|
||||
hexToStr(charCode, dataSize)
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
reject(new Error('processBinaryCMap: Unknown type: ' + type));
|
||||
reject(new Error("processBinaryCMap: Unknown type: " + type));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -702,13 +733,13 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
|
||||
function expectString(obj) {
|
||||
if (!isString(obj)) {
|
||||
throw new FormatError('Malformed CMap: expected string.');
|
||||
throw new FormatError("Malformed CMap: expected string.");
|
||||
}
|
||||
}
|
||||
|
||||
function expectInt(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)) {
|
||||
break;
|
||||
}
|
||||
if (isCmd(obj, 'endbfchar')) {
|
||||
if (isCmd(obj, "endbfchar")) {
|
||||
return;
|
||||
}
|
||||
expectString(obj);
|
||||
@ -737,7 +768,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
if (isEOF(obj)) {
|
||||
break;
|
||||
}
|
||||
if (isCmd(obj, 'endbfrange')) {
|
||||
if (isCmd(obj, "endbfrange")) {
|
||||
return;
|
||||
}
|
||||
expectString(obj);
|
||||
@ -749,10 +780,10 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
if (Number.isInteger(obj) || isString(obj)) {
|
||||
var dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj;
|
||||
cMap.mapBfRange(low, high, dstLow);
|
||||
} else if (isCmd(obj, '[')) {
|
||||
} else if (isCmd(obj, "[")) {
|
||||
obj = lexer.getObj();
|
||||
var array = [];
|
||||
while (!isCmd(obj, ']') && !isEOF(obj)) {
|
||||
while (!isCmd(obj, "]") && !isEOF(obj)) {
|
||||
array.push(obj);
|
||||
obj = lexer.getObj();
|
||||
}
|
||||
@ -761,7 +792,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
throw new FormatError('Invalid bf range.');
|
||||
throw new FormatError("Invalid bf range.");
|
||||
}
|
||||
|
||||
function parseCidChar(cMap, lexer) {
|
||||
@ -770,7 +801,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
if (isEOF(obj)) {
|
||||
break;
|
||||
}
|
||||
if (isCmd(obj, 'endcidchar')) {
|
||||
if (isCmd(obj, "endcidchar")) {
|
||||
return;
|
||||
}
|
||||
expectString(obj);
|
||||
@ -788,7 +819,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
if (isEOF(obj)) {
|
||||
break;
|
||||
}
|
||||
if (isCmd(obj, 'endcidrange')) {
|
||||
if (isCmd(obj, "endcidrange")) {
|
||||
return;
|
||||
}
|
||||
expectString(obj);
|
||||
@ -809,7 +840,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
if (isEOF(obj)) {
|
||||
break;
|
||||
}
|
||||
if (isCmd(obj, 'endcodespacerange')) {
|
||||
if (isCmd(obj, "endcodespacerange")) {
|
||||
return;
|
||||
}
|
||||
if (!isString(obj)) {
|
||||
@ -823,7 +854,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
var high = strToInt(obj);
|
||||
cMap.addCodespaceRange(obj.length, low, high);
|
||||
}
|
||||
throw new FormatError('Invalid codespace range.');
|
||||
throw new FormatError("Invalid codespace range.");
|
||||
}
|
||||
|
||||
function parseWMode(cMap, lexer) {
|
||||
@ -849,34 +880,34 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
if (isEOF(obj)) {
|
||||
break;
|
||||
} else if (isName(obj)) {
|
||||
if (obj.name === 'WMode') {
|
||||
if (obj.name === "WMode") {
|
||||
parseWMode(cMap, lexer);
|
||||
} else if (obj.name === 'CMapName') {
|
||||
} else if (obj.name === "CMapName") {
|
||||
parseCMapName(cMap, lexer);
|
||||
}
|
||||
previous = obj;
|
||||
} else if (isCmd(obj)) {
|
||||
switch (obj.cmd) {
|
||||
case 'endcmap':
|
||||
case "endcmap":
|
||||
break objLoop;
|
||||
case 'usecmap':
|
||||
case "usecmap":
|
||||
if (isName(previous)) {
|
||||
embeddedUseCMap = previous.name;
|
||||
}
|
||||
break;
|
||||
case 'begincodespacerange':
|
||||
case "begincodespacerange":
|
||||
parseCodespaceRange(cMap, lexer);
|
||||
break;
|
||||
case 'beginbfchar':
|
||||
case "beginbfchar":
|
||||
parseBfChar(cMap, lexer);
|
||||
break;
|
||||
case 'begincidchar':
|
||||
case "begincidchar":
|
||||
parseCidChar(cMap, lexer);
|
||||
break;
|
||||
case 'beginbfrange':
|
||||
case "beginbfrange":
|
||||
parseBfRange(cMap, lexer);
|
||||
break;
|
||||
case 'begincidrange':
|
||||
case "begincidrange":
|
||||
parseCidRange(cMap, lexer);
|
||||
break;
|
||||
}
|
||||
@ -885,7 +916,7 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
if (ex instanceof MissingDataException) {
|
||||
throw ex;
|
||||
}
|
||||
warn('Invalid cMap data: ' + ex);
|
||||
warn("Invalid cMap data: " + ex);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -926,26 +957,29 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
}
|
||||
|
||||
function createBuiltInCMap(name, fetchBuiltInCMap) {
|
||||
if (name === 'Identity-H') {
|
||||
if (name === "Identity-H") {
|
||||
return Promise.resolve(new IdentityCMap(false, 2));
|
||||
} else if (name === 'Identity-V') {
|
||||
} else if (name === "Identity-V") {
|
||||
return Promise.resolve(new IdentityCMap(true, 2));
|
||||
}
|
||||
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) {
|
||||
return Promise.reject(new Error(
|
||||
'Built-in CMap parameters are not provided.'));
|
||||
return Promise.reject(
|
||||
new Error("Built-in CMap parameters are not provided.")
|
||||
);
|
||||
}
|
||||
|
||||
return fetchBuiltInCMap(name).then(function (data) {
|
||||
var cMapData = data.cMapData, compressionType = data.compressionType;
|
||||
return fetchBuiltInCMap(name).then(function(data) {
|
||||
var cMapData = data.cMapData,
|
||||
compressionType = data.compressionType;
|
||||
var cMap = new CMap(true);
|
||||
|
||||
if (compressionType === CMapCompressionType.BINARY) {
|
||||
return new BinaryCMapReader().process(cMapData, cMap,
|
||||
function (useCMap) {
|
||||
return new BinaryCMapReader().process(cMapData, cMap, function(
|
||||
useCMap
|
||||
) {
|
||||
return extendCMap(cMap, fetchBuiltInCMap, useCMap);
|
||||
});
|
||||
}
|
||||
@ -953,8 +987,11 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
var lexer = new Lexer(new Stream(cMapData));
|
||||
return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
|
||||
}
|
||||
return Promise.reject(new Error(
|
||||
'TODO: Only BINARY/NONE CMap compression is currently supported.'));
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
"TODO: Only BINARY/NONE CMap compression is currently supported."
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@ -969,21 +1006,18 @@ var CMapFactory = (function CMapFactoryClosure() {
|
||||
} else if (isStream(encoding)) {
|
||||
var cMap = new CMap();
|
||||
var lexer = new Lexer(encoding);
|
||||
return parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap).then(
|
||||
function (parsedCMap) {
|
||||
return parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap).then(function(
|
||||
parsedCMap
|
||||
) {
|
||||
if (parsedCMap.isIdentityCMap) {
|
||||
return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
|
||||
}
|
||||
return parsedCMap;
|
||||
});
|
||||
}
|
||||
return Promise.reject(new Error('Encoding required.'));
|
||||
return Promise.reject(new Error("Encoding required."));
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
||||
export {
|
||||
CMap,
|
||||
IdentityCMap,
|
||||
CMapFactory,
|
||||
};
|
||||
export { CMap, IdentityCMap, CMapFactory };
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@
|
||||
*/
|
||||
/* eslint no-var: error */
|
||||
|
||||
import { assert, BaseException, warn } from '../shared/util';
|
||||
import { assert, BaseException, warn } from "../shared/util";
|
||||
|
||||
function getLookupTableFactory(initializer) {
|
||||
let lookup;
|
||||
@ -36,9 +36,9 @@ class MissingDataException extends BaseException {
|
||||
}
|
||||
}
|
||||
|
||||
class XRefEntryException extends BaseException { }
|
||||
class XRefEntryException extends BaseException {}
|
||||
|
||||
class XRefParseException extends BaseException { }
|
||||
class XRefParseException extends BaseException {}
|
||||
|
||||
/**
|
||||
* Get the value of an inheritable property.
|
||||
@ -61,8 +61,12 @@ class XRefParseException extends BaseException { }
|
||||
* chain, for example to be able to find `\Resources` placed on multiple
|
||||
* levels of the tree. The default value is `true`.
|
||||
*/
|
||||
function getInheritableProperty({ dict, key, getArray = false,
|
||||
stopWhenFound = true, }) {
|
||||
function getInheritableProperty({
|
||||
dict,
|
||||
key,
|
||||
getArray = false,
|
||||
stopWhenFound = true,
|
||||
}) {
|
||||
const LOOP_LIMIT = 100;
|
||||
let loopCount = 0;
|
||||
let values;
|
||||
@ -82,16 +86,16 @@ function getInheritableProperty({ dict, key, getArray = false,
|
||||
warn(`getInheritableProperty: maximum loop count exceeded for "${key}"`);
|
||||
break;
|
||||
}
|
||||
dict = dict.get('Parent');
|
||||
dict = dict.get("Parent");
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
const ROMAN_NUMBER_MAP = [
|
||||
'', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM',
|
||||
'', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC',
|
||||
'', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'
|
||||
"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM",
|
||||
"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC",
|
||||
"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"
|
||||
];
|
||||
|
||||
/**
|
||||
@ -102,13 +106,16 @@ const ROMAN_NUMBER_MAP = [
|
||||
* @returns {string} The resulting Roman number.
|
||||
*/
|
||||
function toRomanNumerals(number, lowerCase = false) {
|
||||
assert(Number.isInteger(number) && number > 0,
|
||||
'The number should be a positive integer.');
|
||||
let pos, romanBuf = [];
|
||||
assert(
|
||||
Number.isInteger(number) && number > 0,
|
||||
"The number should be a positive integer."
|
||||
);
|
||||
let pos,
|
||||
romanBuf = [];
|
||||
// Thousands
|
||||
while (number >= 1000) {
|
||||
number -= 1000;
|
||||
romanBuf.push('M');
|
||||
romanBuf.push("M");
|
||||
}
|
||||
// Hundreds
|
||||
pos = (number / 100) | 0;
|
||||
@ -121,8 +128,8 @@ function toRomanNumerals(number, lowerCase = false) {
|
||||
// Ones
|
||||
romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
|
||||
|
||||
const romanStr = romanBuf.join('');
|
||||
return (lowerCase ? romanStr.toLowerCase() : romanStr);
|
||||
const romanStr = romanBuf.join("");
|
||||
return lowerCase ? romanStr.toLowerCase() : romanStr;
|
||||
}
|
||||
|
||||
export {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,35 +15,60 @@
|
||||
/* eslint no-var: error */
|
||||
|
||||
import {
|
||||
assert, FormatError, info, InvalidPDFException, isArrayBuffer, 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';
|
||||
assert,
|
||||
FormatError,
|
||||
info,
|
||||
InvalidPDFException,
|
||||
isArrayBuffer,
|
||||
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 {
|
||||
getInheritableProperty, MissingDataException, XRefEntryException,
|
||||
XRefParseException
|
||||
} from './core_utils';
|
||||
import { NullStream, Stream, StreamsSequenceStream } from './stream';
|
||||
import { AnnotationFactory } from './annotation';
|
||||
import { calculateMD5 } from './crypto';
|
||||
import { Linearization } from './parser';
|
||||
import { OperatorList } from './operator_list';
|
||||
import { PartialEvaluator } from './evaluator';
|
||||
import { PDFFunctionFactory } from './function';
|
||||
getInheritableProperty,
|
||||
MissingDataException,
|
||||
XRefEntryException,
|
||||
XRefParseException,
|
||||
} from "./core_utils";
|
||||
import { NullStream, Stream, StreamsSequenceStream } from "./stream";
|
||||
import { AnnotationFactory } from "./annotation";
|
||||
import { calculateMD5 } from "./crypto";
|
||||
import { Linearization } from "./parser";
|
||||
import { OperatorList } from "./operator_list";
|
||||
import { PartialEvaluator } from "./evaluator";
|
||||
import { PDFFunctionFactory } from "./function";
|
||||
|
||||
const DEFAULT_USER_UNIT = 1.0;
|
||||
const LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
|
||||
|
||||
function isAnnotationRenderable(annotation, intent) {
|
||||
return (intent === 'display' && annotation.viewable) ||
|
||||
(intent === 'print' && annotation.printable);
|
||||
return (
|
||||
(intent === "display" && annotation.viewable) ||
|
||||
(intent === "print" && annotation.printable)
|
||||
);
|
||||
}
|
||||
|
||||
class Page {
|
||||
constructor({ pdfManager, xref, pageIndex, pageDict, ref, fontCache,
|
||||
builtInCMapCache, pdfFunctionFactory, }) {
|
||||
constructor({
|
||||
pdfManager,
|
||||
xref,
|
||||
pageIndex,
|
||||
pageDict,
|
||||
ref,
|
||||
fontCache,
|
||||
builtInCMapCache,
|
||||
pdfFunctionFactory,
|
||||
}) {
|
||||
this.pdfManager = pdfManager;
|
||||
this.pageIndex = pageIndex;
|
||||
this.pageDict = pageDict;
|
||||
@ -72,8 +97,12 @@ class Page {
|
||||
* @private
|
||||
*/
|
||||
_getInheritableProperty(key, getArray = false) {
|
||||
const value = getInheritableProperty({ dict: this.pageDict, key, getArray,
|
||||
stopWhenFound: false, });
|
||||
const value = getInheritableProperty({
|
||||
dict: this.pageDict,
|
||||
key,
|
||||
getArray,
|
||||
stopWhenFound: false,
|
||||
});
|
||||
if (!Array.isArray(value)) {
|
||||
return value;
|
||||
}
|
||||
@ -84,22 +113,25 @@ class Page {
|
||||
}
|
||||
|
||||
get content() {
|
||||
return this.pageDict.get('Contents');
|
||||
return this.pageDict.get("Contents");
|
||||
}
|
||||
|
||||
get resources() {
|
||||
// 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
|
||||
// we return an empty dictionary.
|
||||
return shadow(this, 'resources',
|
||||
this._getInheritableProperty('Resources') || Dict.empty);
|
||||
return shadow(
|
||||
this,
|
||||
"resources",
|
||||
this._getInheritableProperty("Resources") || Dict.empty
|
||||
);
|
||||
}
|
||||
|
||||
_getBoundingBox(name) {
|
||||
const box = this._getInheritableProperty(name, /* getArray = */ true);
|
||||
|
||||
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;
|
||||
}
|
||||
warn(`Empty /${name} entry.`);
|
||||
@ -109,22 +141,28 @@ class Page {
|
||||
|
||||
get mediaBox() {
|
||||
// Reset invalid media box to letter size.
|
||||
return shadow(this, 'mediaBox',
|
||||
this._getBoundingBox('MediaBox') || LETTER_SIZE_MEDIABOX);
|
||||
return shadow(
|
||||
this,
|
||||
"mediaBox",
|
||||
this._getBoundingBox("MediaBox") || LETTER_SIZE_MEDIABOX
|
||||
);
|
||||
}
|
||||
|
||||
get cropBox() {
|
||||
// Reset invalid crop box to media box.
|
||||
return shadow(this, 'cropBox',
|
||||
this._getBoundingBox('CropBox') || this.mediaBox);
|
||||
return shadow(
|
||||
this,
|
||||
"cropBox",
|
||||
this._getBoundingBox("CropBox") || this.mediaBox
|
||||
);
|
||||
}
|
||||
|
||||
get userUnit() {
|
||||
let obj = this.pageDict.get('UserUnit');
|
||||
let obj = this.pageDict.get("UserUnit");
|
||||
if (!isNum(obj) || obj <= 0) {
|
||||
obj = DEFAULT_USER_UNIT;
|
||||
}
|
||||
return shadow(this, 'userUnit', obj);
|
||||
return shadow(this, "userUnit", obj);
|
||||
}
|
||||
|
||||
get view() {
|
||||
@ -132,23 +170,23 @@ class Page {
|
||||
// "The crop, bleed, trim, and art boxes should not ordinarily
|
||||
// extend beyond the boundaries of the media box. If they do, they are
|
||||
// effectively reduced to their intersection with the media box."
|
||||
const { cropBox, mediaBox, } = this;
|
||||
const { cropBox, mediaBox } = this;
|
||||
let view;
|
||||
if (cropBox === mediaBox || isArrayEqual(cropBox, mediaBox)) {
|
||||
view = mediaBox;
|
||||
} else {
|
||||
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;
|
||||
} 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() {
|
||||
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.
|
||||
if (rotate % 90 !== 0) {
|
||||
@ -160,7 +198,7 @@ class Page {
|
||||
// rotation. The following is the other implementation of modulo.
|
||||
rotate = ((rotate % 360) + 360) % 360;
|
||||
}
|
||||
return shadow(this, 'rotate', rotate);
|
||||
return shadow(this, "rotate", rotate);
|
||||
}
|
||||
|
||||
getContentStream() {
|
||||
@ -187,7 +225,7 @@ class Page {
|
||||
loadResources(keys) {
|
||||
if (!this.resourcesPromise) {
|
||||
// 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(() => {
|
||||
const objectLoader = new ObjectLoader(this.resources, keys, this.xref);
|
||||
@ -195,16 +233,18 @@ class Page {
|
||||
});
|
||||
}
|
||||
|
||||
getOperatorList({ handler, sink, task, intent, renderInteractiveForms, }) {
|
||||
const contentStreamPromise = this.pdfManager.ensure(this,
|
||||
'getContentStream');
|
||||
getOperatorList({ handler, sink, task, intent, renderInteractiveForms }) {
|
||||
const contentStreamPromise = this.pdfManager.ensure(
|
||||
this,
|
||||
"getContentStream"
|
||||
);
|
||||
const resourcesPromise = this.loadResources([
|
||||
'ExtGState',
|
||||
'ColorSpace',
|
||||
'Pattern',
|
||||
'Shading',
|
||||
'XObject',
|
||||
'Font',
|
||||
"ExtGState",
|
||||
"ColorSpace",
|
||||
"Pattern",
|
||||
"Shading",
|
||||
"XObject",
|
||||
"Font",
|
||||
]);
|
||||
|
||||
const partialEvaluator = new PartialEvaluator({
|
||||
@ -222,18 +262,20 @@ class Page {
|
||||
const pageListPromise = dataPromises.then(([contentStream]) => {
|
||||
const opList = new OperatorList(intent, sink, this.pageIndex);
|
||||
|
||||
handler.send('StartRenderPage', {
|
||||
handler.send("StartRenderPage", {
|
||||
transparency: partialEvaluator.hasBlendModes(this.resources),
|
||||
pageIndex: this.pageIndex,
|
||||
intent,
|
||||
});
|
||||
|
||||
return partialEvaluator.getOperatorList({
|
||||
return partialEvaluator
|
||||
.getOperatorList({
|
||||
stream: contentStream,
|
||||
task,
|
||||
resources: this.resources,
|
||||
operatorList: opList,
|
||||
}).then(function() {
|
||||
})
|
||||
.then(function() {
|
||||
return opList;
|
||||
});
|
||||
});
|
||||
@ -244,7 +286,7 @@ class Page {
|
||||
function([pageOpList, annotations]) {
|
||||
if (annotations.length === 0) {
|
||||
pageOpList.flush(true);
|
||||
return { length: pageOpList.totalLength, };
|
||||
return { length: pageOpList.totalLength };
|
||||
}
|
||||
|
||||
// Collect the operator list promises for the annotations. Each promise
|
||||
@ -252,8 +294,13 @@ class Page {
|
||||
const opListPromises = [];
|
||||
for (const annotation of annotations) {
|
||||
if (isAnnotationRenderable(annotation, intent)) {
|
||||
opListPromises.push(annotation.getOperatorList(
|
||||
partialEvaluator, task, renderInteractiveForms));
|
||||
opListPromises.push(
|
||||
annotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
renderInteractiveForms
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,19 +311,27 @@ class Page {
|
||||
}
|
||||
pageOpList.addOp(OPS.endAnnotations, []);
|
||||
pageOpList.flush(true);
|
||||
return { length: pageOpList.totalLength, };
|
||||
});
|
||||
return { length: pageOpList.totalLength };
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
extractTextContent({ handler, task, normalizeWhitespace, sink,
|
||||
combineTextItems, }) {
|
||||
const contentStreamPromise = this.pdfManager.ensure(this,
|
||||
'getContentStream');
|
||||
extractTextContent({
|
||||
handler,
|
||||
task,
|
||||
normalizeWhitespace,
|
||||
sink,
|
||||
combineTextItems,
|
||||
}) {
|
||||
const contentStreamPromise = this.pdfManager.ensure(
|
||||
this,
|
||||
"getContentStream"
|
||||
);
|
||||
const resourcesPromise = this.loadResources([
|
||||
'ExtGState',
|
||||
'XObject',
|
||||
'Font',
|
||||
"ExtGState",
|
||||
"XObject",
|
||||
"Font",
|
||||
]);
|
||||
|
||||
const dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
|
||||
@ -316,47 +371,62 @@ class Page {
|
||||
}
|
||||
|
||||
get annotations() {
|
||||
return shadow(this, 'annotations',
|
||||
this._getInheritableProperty('Annots') || []);
|
||||
return shadow(
|
||||
this,
|
||||
"annotations",
|
||||
this._getInheritableProperty("Annots") || []
|
||||
);
|
||||
}
|
||||
|
||||
get _parsedAnnotations() {
|
||||
const parsedAnnotations =
|
||||
this.pdfManager.ensure(this, 'annotations').then(() => {
|
||||
const parsedAnnotations = this.pdfManager
|
||||
.ensure(this, "annotations")
|
||||
.then(() => {
|
||||
const annotationRefs = this.annotations;
|
||||
const annotationPromises = [];
|
||||
for (let i = 0, ii = annotationRefs.length; i < ii; i++) {
|
||||
annotationPromises.push(AnnotationFactory.create(
|
||||
this.xref, annotationRefs[i], this.pdfManager, this.idFactory));
|
||||
annotationPromises.push(
|
||||
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 !!annotation;
|
||||
});
|
||||
}, function(reason) {
|
||||
},
|
||||
function(reason) {
|
||||
warn(`_parsedAnnotations: "${reason}".`);
|
||||
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
|
||||
const STARTXREF_SIGNATURE = new Uint8Array([
|
||||
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 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) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||
) {
|
||||
assert(limit > 0, 'The "limit" must be a positive integer.');
|
||||
}
|
||||
const signatureLength = signature.length;
|
||||
@ -373,24 +443,29 @@ function find(stream, signature, limit = 1024, backwards = false) {
|
||||
let pos = scanBytes.length - 1;
|
||||
while (pos >= signatureEnd) {
|
||||
let j = 0;
|
||||
while (j < signatureLength &&
|
||||
scanBytes[pos - j] === signature[signatureEnd - j]) {
|
||||
while (
|
||||
j < signatureLength &&
|
||||
scanBytes[pos - j] === signature[signatureEnd - j]
|
||||
) {
|
||||
j++;
|
||||
}
|
||||
if (j >= signatureLength) { // `signature` found.
|
||||
stream.pos += (pos - signatureEnd);
|
||||
if (j >= signatureLength) {
|
||||
// `signature` found.
|
||||
stream.pos += pos - signatureEnd;
|
||||
return true;
|
||||
}
|
||||
pos--;
|
||||
}
|
||||
} else { // forwards
|
||||
} else {
|
||||
// forwards
|
||||
let pos = 0;
|
||||
while (pos <= scanLength) {
|
||||
let j = 0;
|
||||
while (j < signatureLength && scanBytes[pos + j] === signature[j]) {
|
||||
j++;
|
||||
}
|
||||
if (j >= signatureLength) { // `signature` found.
|
||||
if (j >= signatureLength) {
|
||||
// `signature` found.
|
||||
stream.pos += pos;
|
||||
return true;
|
||||
}
|
||||
@ -411,11 +486,12 @@ class PDFDocument {
|
||||
} else if (isArrayBuffer(arg)) {
|
||||
stream = new Stream(arg);
|
||||
} else {
|
||||
throw new Error('PDFDocument: Unknown argument type');
|
||||
throw new Error("PDFDocument: Unknown argument type");
|
||||
}
|
||||
if (stream.length <= 0) {
|
||||
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;
|
||||
@ -432,17 +508,17 @@ class PDFDocument {
|
||||
parse(recoveryMode) {
|
||||
this.setup(recoveryMode);
|
||||
|
||||
const version = this.catalog.catDict.get('Version');
|
||||
const version = this.catalog.catDict.get("Version");
|
||||
if (isName(version)) {
|
||||
this.pdfFormatVersion = version.name;
|
||||
}
|
||||
|
||||
// Check if AcroForms are present in the document.
|
||||
try {
|
||||
this.acroForm = this.catalog.catDict.get('AcroForm');
|
||||
this.acroForm = this.catalog.catDict.get("AcroForm");
|
||||
if (this.acroForm) {
|
||||
this.xfa = this.acroForm.get('XFA');
|
||||
const fields = this.acroForm.get('Fields');
|
||||
this.xfa = this.acroForm.get("XFA");
|
||||
const fields = this.acroForm.get("Fields");
|
||||
if ((!Array.isArray(fields) || fields.length === 0) && !this.xfa) {
|
||||
this.acroForm = null; // No fields and no XFA, so it's not a form.
|
||||
}
|
||||
@ -451,13 +527,13 @@ class PDFDocument {
|
||||
if (ex instanceof MissingDataException) {
|
||||
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;
|
||||
}
|
||||
|
||||
// Check if a Collection dictionary is present in the document.
|
||||
try {
|
||||
const collection = this.catalog.catDict.get('Collection');
|
||||
const collection = this.catalog.catDict.get("Collection");
|
||||
if (isDict(collection) && collection.getKeys().length > 0) {
|
||||
this.collection = collection;
|
||||
}
|
||||
@ -465,7 +541,7 @@ class PDFDocument {
|
||||
if (ex instanceof MissingDataException) {
|
||||
throw ex;
|
||||
}
|
||||
info('Cannot fetch Collection dictionary.');
|
||||
info("Cannot fetch Collection dictionary.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,7 +555,7 @@ class PDFDocument {
|
||||
}
|
||||
info(err);
|
||||
}
|
||||
return shadow(this, 'linearization', linearization);
|
||||
return shadow(this, "linearization", linearization);
|
||||
}
|
||||
|
||||
get startXRef() {
|
||||
@ -490,13 +566,14 @@ class PDFDocument {
|
||||
// Find the end of the first object.
|
||||
stream.reset();
|
||||
if (find(stream, ENDOBJ_SIGNATURE)) {
|
||||
startXRef = (stream.pos + 6) - stream.start;
|
||||
startXRef = stream.pos + 6 - stream.start;
|
||||
}
|
||||
} else {
|
||||
// Find `startxref` by checking backwards from the end of the file.
|
||||
const step = 1024;
|
||||
const startXRefLength = STARTXREF_SIGNATURE.length;
|
||||
let found = false, pos = stream.end;
|
||||
let found = false,
|
||||
pos = stream.end;
|
||||
|
||||
while (!found && pos > 0) {
|
||||
pos -= step - startXRefLength;
|
||||
@ -513,8 +590,9 @@ class PDFDocument {
|
||||
do {
|
||||
ch = stream.getByte();
|
||||
} while (isSpace(ch));
|
||||
let str = '';
|
||||
while (ch >= 0x20 && ch <= 0x39) { // < '9'
|
||||
let str = "";
|
||||
while (ch >= 0x20 && ch <= 0x39) {
|
||||
// < '9'
|
||||
str += String.fromCharCode(ch);
|
||||
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
|
||||
@ -542,8 +620,10 @@ class PDFDocument {
|
||||
|
||||
// Read the PDF format version.
|
||||
const MAX_PDF_VERSION_LENGTH = 12;
|
||||
let version = '', ch;
|
||||
while ((ch = stream.getByte()) > 0x20) { // Space
|
||||
let version = "",
|
||||
ch;
|
||||
while ((ch = stream.getByte()) > 0x20) {
|
||||
// Space
|
||||
if (version.length >= MAX_PDF_VERSION_LENGTH) {
|
||||
break;
|
||||
}
|
||||
@ -567,7 +647,7 @@ class PDFDocument {
|
||||
get numPages() {
|
||||
const linearization = this.linearization;
|
||||
const num = linearization ? linearization.numPages : this.catalog.numPages;
|
||||
return shadow(this, 'numPages', num);
|
||||
return shadow(this, "numPages", num);
|
||||
}
|
||||
|
||||
get documentInfo() {
|
||||
@ -593,12 +673,12 @@ class PDFDocument {
|
||||
|
||||
let infoDict;
|
||||
try {
|
||||
infoDict = this.xref.trailer.get('Info');
|
||||
infoDict = this.xref.trailer.get("Info");
|
||||
} catch (err) {
|
||||
if (err instanceof MissingDataException) {
|
||||
throw err;
|
||||
}
|
||||
info('The document information dictionary is invalid.');
|
||||
info("The document information dictionary is invalid.");
|
||||
}
|
||||
|
||||
if (isDict(infoDict)) {
|
||||
@ -610,12 +690,12 @@ class PDFDocument {
|
||||
if (DocumentInfoValidators[key]) {
|
||||
// Make sure the (standard) value conforms to the specification.
|
||||
if (DocumentInfoValidators[key](value)) {
|
||||
docInfo[key] = (typeof value !== 'string' ?
|
||||
value : stringToPDFString(value));
|
||||
docInfo[key] =
|
||||
typeof value !== "string" ? value : stringToPDFString(value);
|
||||
} else {
|
||||
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
|
||||
// errors that would occur when trying to send non-serializable
|
||||
// objects to the main-thread (for example `Dict` or `Stream`).
|
||||
@ -629,52 +709,66 @@ class PDFDocument {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!docInfo['Custom']) {
|
||||
docInfo['Custom'] = Object.create(null);
|
||||
if (!docInfo["Custom"]) {
|
||||
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() {
|
||||
let hash;
|
||||
const idArray = this.xref.trailer.get('ID');
|
||||
if (Array.isArray(idArray) && idArray[0] && isString(idArray[0]) &&
|
||||
idArray[0] !== EMPTY_FINGERPRINT) {
|
||||
const idArray = this.xref.trailer.get("ID");
|
||||
if (
|
||||
Array.isArray(idArray) &&
|
||||
idArray[0] &&
|
||||
isString(idArray[0]) &&
|
||||
idArray[0] !== EMPTY_FINGERPRINT
|
||||
) {
|
||||
hash = stringToBytes(idArray[0]);
|
||||
} else {
|
||||
hash = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES),
|
||||
0, FINGERPRINT_FIRST_BYTES);
|
||||
hash = calculateMD5(
|
||||
this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES),
|
||||
0,
|
||||
FINGERPRINT_FIRST_BYTES
|
||||
);
|
||||
}
|
||||
|
||||
const fingerprintBuf = [];
|
||||
for (let i = 0, ii = hash.length; i < ii; i++) {
|
||||
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) {
|
||||
const { catalog, linearization, } = this;
|
||||
const { catalog, linearization } = this;
|
||||
assert(linearization && linearization.pageFirst === pageIndex);
|
||||
|
||||
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.
|
||||
if (isDict(obj, 'Page') ||
|
||||
(isDict(obj) && !obj.has('Type') && obj.has('Contents'))) {
|
||||
if (
|
||||
isDict(obj, "Page") ||
|
||||
(isDict(obj) && !obj.has("Type") && obj.has("Contents"))
|
||||
) {
|
||||
if (ref && !catalog.pageKidsCountCache.has(ref)) {
|
||||
catalog.pageKidsCountCache.put(ref, 1); // Cache the Page reference.
|
||||
}
|
||||
return [obj, ref];
|
||||
}
|
||||
throw new FormatError('The Linearization dictionary doesn\'t point ' +
|
||||
'to a valid Page dictionary.');
|
||||
}).catch((reason) => {
|
||||
throw new FormatError(
|
||||
"The Linearization dictionary doesn't point " +
|
||||
"to a valid Page dictionary."
|
||||
);
|
||||
})
|
||||
.catch(reason => {
|
||||
info(reason);
|
||||
return catalog.getPageDict(pageIndex);
|
||||
});
|
||||
@ -684,12 +778,14 @@ class PDFDocument {
|
||||
if (this._pagePromises[pageIndex] !== undefined) {
|
||||
return this._pagePromises[pageIndex];
|
||||
}
|
||||
const { catalog, linearization, } = this;
|
||||
const { catalog, linearization } = this;
|
||||
|
||||
const promise = (linearization && linearization.pageFirst === pageIndex) ?
|
||||
this._getLinearizationPage(pageIndex) : catalog.getPageDict(pageIndex);
|
||||
const promise =
|
||||
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({
|
||||
pdfManager: this.pdfManager,
|
||||
xref: this.xref,
|
||||
@ -700,11 +796,11 @@ class PDFDocument {
|
||||
builtInCMapCache: catalog.builtInCMapCache,
|
||||
pdfFunctionFactory: this.pdfFunctionFactory,
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
checkFirstPage() {
|
||||
return this.getPage(0).catch(async (reason) => {
|
||||
return this.getPage(0).catch(async reason => {
|
||||
if (reason instanceof XRefEntryException) {
|
||||
// Clear out the various caches to ensure that we haven't stored any
|
||||
// inconsistent and/or incorrect state, since that could easily break
|
||||
@ -726,7 +822,4 @@ class PDFDocument {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Page,
|
||||
PDFDocument,
|
||||
};
|
||||
export { Page, PDFDocument };
|
||||
|
@ -15,275 +15,275 @@
|
||||
|
||||
// prettier-ignore
|
||||
const ExpertEncoding = [
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle',
|
||||
'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior',
|
||||
'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma',
|
||||
'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle',
|
||||
'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle',
|
||||
'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon',
|
||||
'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior',
|
||||
'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior',
|
||||
'esuperior', '', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior',
|
||||
'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior',
|
||||
'', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '',
|
||||
'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall',
|
||||
'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall',
|
||||
'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall',
|
||||
'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall',
|
||||
'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary',
|
||||
'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall',
|
||||
'', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall',
|
||||
'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '',
|
||||
'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall',
|
||||
'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters',
|
||||
'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||
'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior',
|
||||
'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior',
|
||||
'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior',
|
||||
'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior',
|
||||
'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior',
|
||||
'seveninferior', 'eightinferior', 'nineinferior', 'centinferior',
|
||||
'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall',
|
||||
'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall',
|
||||
'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall',
|
||||
'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall',
|
||||
'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall',
|
||||
'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall',
|
||||
'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall',
|
||||
'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall',
|
||||
'Ydieresissmall'];
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"space", "exclamsmall", "Hungarumlautsmall", "", "dollaroldstyle",
|
||||
"dollarsuperior", "ampersandsmall", "Acutesmall", "parenleftsuperior",
|
||||
"parenrightsuperior", "twodotenleader", "onedotenleader", "comma",
|
||||
"hyphen", "period", "fraction", "zerooldstyle", "oneoldstyle",
|
||||
"twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
|
||||
"sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "colon",
|
||||
"semicolon", "commasuperior", "threequartersemdash", "periodsuperior",
|
||||
"questionsmall", "", "asuperior", "bsuperior", "centsuperior", "dsuperior",
|
||||
"esuperior", "", "", "", "isuperior", "", "", "lsuperior", "msuperior",
|
||||
"nsuperior", "osuperior", "", "", "rsuperior", "ssuperior", "tsuperior",
|
||||
"", "ff", "fi", "fl", "ffi", "ffl", "parenleftinferior", "",
|
||||
"parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
|
||||
"Asmall", "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall",
|
||||
"Hsmall", "Ismall", "Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall",
|
||||
"Osmall", "Psmall", "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
|
||||
"Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall", "colonmonetary",
|
||||
"onefitted", "rupiah", "Tildesmall", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "exclamdownsmall", "centoldstyle", "Lslashsmall",
|
||||
"", "", "Scaronsmall", "Zcaronsmall", "Dieresissmall", "Brevesmall",
|
||||
"Caronsmall", "", "Dotaccentsmall", "", "", "Macronsmall", "", "",
|
||||
"figuredash", "hypheninferior", "", "", "Ogoneksmall", "Ringsmall",
|
||||
"Cedillasmall", "", "", "", "onequarter", "onehalf", "threequarters",
|
||||
"questiondownsmall", "oneeighth", "threeeighths", "fiveeighths",
|
||||
"seveneighths", "onethird", "twothirds", "", "", "zerosuperior",
|
||||
"onesuperior", "twosuperior", "threesuperior", "foursuperior",
|
||||
"fivesuperior", "sixsuperior", "sevensuperior", "eightsuperior",
|
||||
"ninesuperior", "zeroinferior", "oneinferior", "twoinferior",
|
||||
"threeinferior", "fourinferior", "fiveinferior", "sixinferior",
|
||||
"seveninferior", "eightinferior", "nineinferior", "centinferior",
|
||||
"dollarinferior", "periodinferior", "commainferior", "Agravesmall",
|
||||
"Aacutesmall", "Acircumflexsmall", "Atildesmall", "Adieresissmall",
|
||||
"Aringsmall", "AEsmall", "Ccedillasmall", "Egravesmall", "Eacutesmall",
|
||||
"Ecircumflexsmall", "Edieresissmall", "Igravesmall", "Iacutesmall",
|
||||
"Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
|
||||
"Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
|
||||
"Odieresissmall", "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall",
|
||||
"Ucircumflexsmall", "Udieresissmall", "Yacutesmall", "Thornsmall",
|
||||
"Ydieresissmall"];
|
||||
|
||||
// prettier-ignore
|
||||
const MacExpertEncoding = [
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle',
|
||||
'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall',
|
||||
'parenleftsuperior', 'parenrightsuperior', 'twodotenleader',
|
||||
'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle',
|
||||
'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle',
|
||||
'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle',
|
||||
'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '',
|
||||
'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter',
|
||||
'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths',
|
||||
'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff',
|
||||
'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior',
|
||||
'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall',
|
||||
'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall',
|
||||
'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall',
|
||||
'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall',
|
||||
'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah',
|
||||
'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '',
|
||||
'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall',
|
||||
'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall',
|
||||
'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall',
|
||||
'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall',
|
||||
'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall',
|
||||
'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '',
|
||||
'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior',
|
||||
'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior',
|
||||
'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior',
|
||||
'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '',
|
||||
'dollarinferior', '', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior',
|
||||
'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall',
|
||||
'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '',
|
||||
'', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '',
|
||||
'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior',
|
||||
'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior',
|
||||
'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior',
|
||||
'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior',
|
||||
'', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall',
|
||||
'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior',
|
||||
'periodsuperior', 'Dotaccentsmall', 'Ringsmall', '', '', '', ''];
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"space", "exclamsmall", "Hungarumlautsmall", "centoldstyle",
|
||||
"dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
|
||||
"parenleftsuperior", "parenrightsuperior", "twodotenleader",
|
||||
"onedotenleader", "comma", "hyphen", "period", "fraction", "zerooldstyle",
|
||||
"oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle",
|
||||
"fiveoldstyle", "sixoldstyle", "sevenoldstyle", "eightoldstyle",
|
||||
"nineoldstyle", "colon", "semicolon", "", "threequartersemdash", "",
|
||||
"questionsmall", "", "", "", "", "Ethsmall", "", "", "onequarter",
|
||||
"onehalf", "threequarters", "oneeighth", "threeeighths", "fiveeighths",
|
||||
"seveneighths", "onethird", "twothirds", "", "", "", "", "", "", "ff",
|
||||
"fi", "fl", "ffi", "ffl", "parenleftinferior", "", "parenrightinferior",
|
||||
"Circumflexsmall", "hypheninferior", "Gravesmall", "Asmall", "Bsmall",
|
||||
"Csmall", "Dsmall", "Esmall", "Fsmall", "Gsmall", "Hsmall", "Ismall",
|
||||
"Jsmall", "Ksmall", "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
|
||||
"Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall", "Vsmall", "Wsmall",
|
||||
"Xsmall", "Ysmall", "Zsmall", "colonmonetary", "onefitted", "rupiah",
|
||||
"Tildesmall", "", "", "asuperior", "centsuperior", "", "", "", "",
|
||||
"Aacutesmall", "Agravesmall", "Acircumflexsmall", "Adieresissmall",
|
||||
"Atildesmall", "Aringsmall", "Ccedillasmall", "Eacutesmall", "Egravesmall",
|
||||
"Ecircumflexsmall", "Edieresissmall", "Iacutesmall", "Igravesmall",
|
||||
"Icircumflexsmall", "Idieresissmall", "Ntildesmall", "Oacutesmall",
|
||||
"Ogravesmall", "Ocircumflexsmall", "Odieresissmall", "Otildesmall",
|
||||
"Uacutesmall", "Ugravesmall", "Ucircumflexsmall", "Udieresissmall", "",
|
||||
"eightsuperior", "fourinferior", "threeinferior", "sixinferior",
|
||||
"eightinferior", "seveninferior", "Scaronsmall", "", "centinferior",
|
||||
"twoinferior", "", "Dieresissmall", "", "Caronsmall", "osuperior",
|
||||
"fiveinferior", "", "commainferior", "periodinferior", "Yacutesmall", "",
|
||||
"dollarinferior", "", "", "Thornsmall", "", "nineinferior", "zeroinferior",
|
||||
"Zcaronsmall", "AEsmall", "Oslashsmall", "questiondownsmall",
|
||||
"oneinferior", "Lslashsmall", "", "", "", "", "", "", "Cedillasmall", "",
|
||||
"", "", "", "", "OEsmall", "figuredash", "hyphensuperior", "", "", "", "",
|
||||
"exclamdownsmall", "", "Ydieresissmall", "", "onesuperior", "twosuperior",
|
||||
"threesuperior", "foursuperior", "fivesuperior", "sixsuperior",
|
||||
"sevensuperior", "ninesuperior", "zerosuperior", "", "esuperior",
|
||||
"rsuperior", "tsuperior", "", "", "isuperior", "ssuperior", "dsuperior",
|
||||
"", "", "", "", "", "lsuperior", "Ogoneksmall", "Brevesmall",
|
||||
"Macronsmall", "bsuperior", "nsuperior", "msuperior", "commasuperior",
|
||||
"periodsuperior", "Dotaccentsmall", "Ringsmall", "", "", "", ""];
|
||||
|
||||
// prettier-ignore
|
||||
const MacRomanEncoding = [
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
|
||||
'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
|
||||
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
|
||||
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
|
||||
'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',
|
||||
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
|
||||
'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',
|
||||
'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '',
|
||||
'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis',
|
||||
'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde',
|
||||
'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis',
|
||||
'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute',
|
||||
'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave',
|
||||
'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling',
|
||||
'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright',
|
||||
'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity',
|
||||
'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff',
|
||||
'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine',
|
||||
'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot',
|
||||
'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft',
|
||||
'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE',
|
||||
'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft',
|
||||
'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction',
|
||||
'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl',
|
||||
'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand',
|
||||
'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute',
|
||||
'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple',
|
||||
'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex',
|
||||
'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut',
|
||||
'ogonek', 'caron'];
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
|
||||
"ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus",
|
||||
"comma", "hyphen", "period", "slash", "zero", "one", "two", "three",
|
||||
"four", "five", "six", "seven", "eight", "nine", "colon", "semicolon",
|
||||
"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",
|
||||
"V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
|
||||
"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",
|
||||
"w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", "",
|
||||
"Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis",
|
||||
"Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde",
|
||||
"aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis",
|
||||
"iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute",
|
||||
"ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave",
|
||||
"ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling",
|
||||
"section", "bullet", "paragraph", "germandbls", "registered", "copyright",
|
||||
"trademark", "acute", "dieresis", "notequal", "AE", "Oslash", "infinity",
|
||||
"plusminus", "lessequal", "greaterequal", "yen", "mu", "partialdiff",
|
||||
"summation", "product", "pi", "integral", "ordfeminine", "ordmasculine",
|
||||
"Omega", "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
|
||||
"radical", "florin", "approxequal", "Delta", "guillemotleft",
|
||||
"guillemotright", "ellipsis", "space", "Agrave", "Atilde", "Otilde", "OE",
|
||||
"oe", "endash", "emdash", "quotedblleft", "quotedblright", "quoteleft",
|
||||
"quoteright", "divide", "lozenge", "ydieresis", "Ydieresis", "fraction",
|
||||
"currency", "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
|
||||
"periodcentered", "quotesinglbase", "quotedblbase", "perthousand",
|
||||
"Acircumflex", "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
|
||||
"Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", "apple",
|
||||
"Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", "circumflex",
|
||||
"tilde", "macron", "breve", "dotaccent", "ring", "cedilla", "hungarumlaut",
|
||||
"ogonek", "caron"];
|
||||
|
||||
// prettier-ignore
|
||||
const StandardEncoding = [
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
|
||||
'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus',
|
||||
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
|
||||
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
|
||||
'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',
|
||||
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
|
||||
'asciicircum', 'underscore', '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', 'braceleft', 'bar', 'braceright', 'asciitilde',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown',
|
||||
'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency',
|
||||
'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft',
|
||||
'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl',
|
||||
'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase',
|
||||
'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis',
|
||||
'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex',
|
||||
'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla',
|
||||
'', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '',
|
||||
'', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae',
|
||||
'', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls', '',
|
||||
'', '', ''];
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
|
||||
"ampersand", "quoteright", "parenleft", "parenright", "asterisk", "plus",
|
||||
"comma", "hyphen", "period", "slash", "zero", "one", "two", "three",
|
||||
"four", "five", "six", "seven", "eight", "nine", "colon", "semicolon",
|
||||
"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",
|
||||
"V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
|
||||
"asciicircum", "underscore", "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", "braceleft", "bar", "braceright", "asciitilde",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "exclamdown",
|
||||
"cent", "sterling", "fraction", "yen", "florin", "section", "currency",
|
||||
"quotesingle", "quotedblleft", "guillemotleft", "guilsinglleft",
|
||||
"guilsinglright", "fi", "fl", "", "endash", "dagger", "daggerdbl",
|
||||
"periodcentered", "", "paragraph", "bullet", "quotesinglbase",
|
||||
"quotedblbase", "quotedblright", "guillemotright", "ellipsis",
|
||||
"perthousand", "", "questiondown", "", "grave", "acute", "circumflex",
|
||||
"tilde", "macron", "breve", "dotaccent", "dieresis", "", "ring", "cedilla",
|
||||
"", "hungarumlaut", "ogonek", "caron", "emdash", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "AE", "", "ordfeminine", "", "",
|
||||
"", "", "Lslash", "Oslash", "OE", "ordmasculine", "", "", "", "", "", "ae",
|
||||
"", "", "", "dotlessi", "", "", "lslash", "oslash", "oe", "germandbls", "",
|
||||
"", "", ""];
|
||||
|
||||
// prettier-ignore
|
||||
const WinAnsiEncoding = [
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent',
|
||||
'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus',
|
||||
'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three',
|
||||
'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon',
|
||||
'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',
|
||||
'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright',
|
||||
'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',
|
||||
'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde',
|
||||
'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase',
|
||||
'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron',
|
||||
'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft',
|
||||
'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash',
|
||||
'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet',
|
||||
'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling',
|
||||
'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright',
|
||||
'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered',
|
||||
'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute',
|
||||
'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior',
|
||||
'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters',
|
||||
'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis',
|
||||
'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis',
|
||||
'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve',
|
||||
'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash',
|
||||
'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn',
|
||||
'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis',
|
||||
'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis',
|
||||
'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve',
|
||||
'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash',
|
||||
'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn',
|
||||
'ydieresis'];
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
|
||||
"ampersand", "quotesingle", "parenleft", "parenright", "asterisk", "plus",
|
||||
"comma", "hyphen", "period", "slash", "zero", "one", "two", "three",
|
||||
"four", "five", "six", "seven", "eight", "nine", "colon", "semicolon",
|
||||
"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",
|
||||
"V", "W", "X", "Y", "Z", "bracketleft", "backslash", "bracketright",
|
||||
"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",
|
||||
"w", "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde",
|
||||
"bullet", "Euro", "bullet", "quotesinglbase", "florin", "quotedblbase",
|
||||
"ellipsis", "dagger", "daggerdbl", "circumflex", "perthousand", "Scaron",
|
||||
"guilsinglleft", "OE", "bullet", "Zcaron", "bullet", "bullet", "quoteleft",
|
||||
"quoteright", "quotedblleft", "quotedblright", "bullet", "endash",
|
||||
"emdash", "tilde", "trademark", "scaron", "guilsinglright", "oe", "bullet",
|
||||
"zcaron", "Ydieresis", "space", "exclamdown", "cent", "sterling",
|
||||
"currency", "yen", "brokenbar", "section", "dieresis", "copyright",
|
||||
"ordfeminine", "guillemotleft", "logicalnot", "hyphen", "registered",
|
||||
"macron", "degree", "plusminus", "twosuperior", "threesuperior", "acute",
|
||||
"mu", "paragraph", "periodcentered", "cedilla", "onesuperior",
|
||||
"ordmasculine", "guillemotright", "onequarter", "onehalf", "threequarters",
|
||||
"questiondown", "Agrave", "Aacute", "Acircumflex", "Atilde", "Adieresis",
|
||||
"Aring", "AE", "Ccedilla", "Egrave", "Eacute", "Ecircumflex", "Edieresis",
|
||||
"Igrave", "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde", "Ograve",
|
||||
"Oacute", "Ocircumflex", "Otilde", "Odieresis", "multiply", "Oslash",
|
||||
"Ugrave", "Uacute", "Ucircumflex", "Udieresis", "Yacute", "Thorn",
|
||||
"germandbls", "agrave", "aacute", "acircumflex", "atilde", "adieresis",
|
||||
"aring", "ae", "ccedilla", "egrave", "eacute", "ecircumflex", "edieresis",
|
||||
"igrave", "iacute", "icircumflex", "idieresis", "eth", "ntilde", "ograve",
|
||||
"oacute", "ocircumflex", "otilde", "odieresis", "divide", "oslash",
|
||||
"ugrave", "uacute", "ucircumflex", "udieresis", "yacute", "thorn",
|
||||
"ydieresis"];
|
||||
|
||||
// prettier-ignore
|
||||
const SymbolSetEncoding = [
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent',
|
||||
'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus',
|
||||
'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four',
|
||||
'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less',
|
||||
'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi',
|
||||
'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa',
|
||||
'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau',
|
||||
'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft',
|
||||
'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex',
|
||||
'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota',
|
||||
'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho',
|
||||
'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta',
|
||||
'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal',
|
||||
'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade',
|
||||
'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree',
|
||||
'plusminus', 'second', 'greaterequal', 'multiply', 'proportional',
|
||||
'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence',
|
||||
'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn',
|
||||
'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply',
|
||||
'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset',
|
||||
'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element',
|
||||
'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif',
|
||||
'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot',
|
||||
'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup',
|
||||
'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans',
|
||||
'copyrightsans', 'trademarksans', 'summation', 'parenlefttp',
|
||||
'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex',
|
||||
'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex',
|
||||
'', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt',
|
||||
'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp',
|
||||
'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid',
|
||||
'bracerightbt', ''];
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"space", "exclam", "universal", "numbersign", "existential", "percent",
|
||||
"ampersand", "suchthat", "parenleft", "parenright", "asteriskmath", "plus",
|
||||
"comma", "minus", "period", "slash", "zero", "one", "two", "three", "four",
|
||||
"five", "six", "seven", "eight", "nine", "colon", "semicolon", "less",
|
||||
"equal", "greater", "question", "congruent", "Alpha", "Beta", "Chi",
|
||||
"Delta", "Epsilon", "Phi", "Gamma", "Eta", "Iota", "theta1", "Kappa",
|
||||
"Lambda", "Mu", "Nu", "Omicron", "Pi", "Theta", "Rho", "Sigma", "Tau",
|
||||
"Upsilon", "sigma1", "Omega", "Xi", "Psi", "Zeta", "bracketleft",
|
||||
"therefore", "bracketright", "perpendicular", "underscore", "radicalex",
|
||||
"alpha", "beta", "chi", "delta", "epsilon", "phi", "gamma", "eta", "iota",
|
||||
"phi1", "kappa", "lambda", "mu", "nu", "omicron", "pi", "theta", "rho",
|
||||
"sigma", "tau", "upsilon", "omega1", "omega", "xi", "psi", "zeta",
|
||||
"braceleft", "bar", "braceright", "similar", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "Euro", "Upsilon1", "minute", "lessequal",
|
||||
"fraction", "infinity", "florin", "club", "diamond", "heart", "spade",
|
||||
"arrowboth", "arrowleft", "arrowup", "arrowright", "arrowdown", "degree",
|
||||
"plusminus", "second", "greaterequal", "multiply", "proportional",
|
||||
"partialdiff", "bullet", "divide", "notequal", "equivalence",
|
||||
"approxequal", "ellipsis", "arrowvertex", "arrowhorizex", "carriagereturn",
|
||||
"aleph", "Ifraktur", "Rfraktur", "weierstrass", "circlemultiply",
|
||||
"circleplus", "emptyset", "intersection", "union", "propersuperset",
|
||||
"reflexsuperset", "notsubset", "propersubset", "reflexsubset", "element",
|
||||
"notelement", "angle", "gradient", "registerserif", "copyrightserif",
|
||||
"trademarkserif", "product", "radical", "dotmath", "logicalnot",
|
||||
"logicaland", "logicalor", "arrowdblboth", "arrowdblleft", "arrowdblup",
|
||||
"arrowdblright", "arrowdbldown", "lozenge", "angleleft", "registersans",
|
||||
"copyrightsans", "trademarksans", "summation", "parenlefttp",
|
||||
"parenleftex", "parenleftbt", "bracketlefttp", "bracketleftex",
|
||||
"bracketleftbt", "bracelefttp", "braceleftmid", "braceleftbt", "braceex",
|
||||
"", "angleright", "integral", "integraltp", "integralex", "integralbt",
|
||||
"parenrighttp", "parenrightex", "parenrightbt", "bracketrighttp",
|
||||
"bracketrightex", "bracketrightbt", "bracerighttp", "bracerightmid",
|
||||
"bracerightbt", ""];
|
||||
|
||||
// prettier-ignore
|
||||
const ZapfDingbatsEncoding = [
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '',
|
||||
'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117',
|
||||
'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19',
|
||||
'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7',
|
||||
'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36',
|
||||
'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46',
|
||||
'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56',
|
||||
'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66',
|
||||
'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75',
|
||||
'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97',
|
||||
'a98', 'a99', 'a100', '', 'a89', 'a90', 'a93', 'a94', 'a91', 'a92', 'a205',
|
||||
'a85', 'a206', 'a86', 'a87', 'a88', 'a95', 'a96', '', '', '', '', '', '',
|
||||
'', '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103',
|
||||
'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120',
|
||||
'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129',
|
||||
'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138',
|
||||
'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147',
|
||||
'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156',
|
||||
'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165',
|
||||
'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173',
|
||||
'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180',
|
||||
'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197', 'a185',
|
||||
'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190', 'a191', ''];
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
|
||||
"space", "a1", "a2", "a202", "a3", "a4", "a5", "a119", "a118", "a117",
|
||||
"a11", "a12", "a13", "a14", "a15", "a16", "a105", "a17", "a18", "a19",
|
||||
"a20", "a21", "a22", "a23", "a24", "a25", "a26", "a27", "a28", "a6", "a7",
|
||||
"a8", "a9", "a10", "a29", "a30", "a31", "a32", "a33", "a34", "a35", "a36",
|
||||
"a37", "a38", "a39", "a40", "a41", "a42", "a43", "a44", "a45", "a46",
|
||||
"a47", "a48", "a49", "a50", "a51", "a52", "a53", "a54", "a55", "a56",
|
||||
"a57", "a58", "a59", "a60", "a61", "a62", "a63", "a64", "a65", "a66",
|
||||
"a67", "a68", "a69", "a70", "a71", "a72", "a73", "a74", "a203", "a75",
|
||||
"a204", "a76", "a77", "a78", "a79", "a81", "a82", "a83", "a84", "a97",
|
||||
"a98", "a99", "a100", "", "a89", "a90", "a93", "a94", "a91", "a92", "a205",
|
||||
"a85", "a206", "a86", "a87", "a88", "a95", "a96", "", "", "", "", "", "",
|
||||
"", "", "", "", "", "", "", "", "", "", "", "", "", "a101", "a102", "a103",
|
||||
"a104", "a106", "a107", "a108", "a112", "a111", "a110", "a109", "a120",
|
||||
"a121", "a122", "a123", "a124", "a125", "a126", "a127", "a128", "a129",
|
||||
"a130", "a131", "a132", "a133", "a134", "a135", "a136", "a137", "a138",
|
||||
"a139", "a140", "a141", "a142", "a143", "a144", "a145", "a146", "a147",
|
||||
"a148", "a149", "a150", "a151", "a152", "a153", "a154", "a155", "a156",
|
||||
"a157", "a158", "a159", "a160", "a161", "a163", "a164", "a196", "a165",
|
||||
"a192", "a166", "a167", "a168", "a169", "a170", "a171", "a172", "a173",
|
||||
"a162", "a174", "a175", "a176", "a177", "a178", "a179", "a193", "a180",
|
||||
"a199", "a181", "a200", "a182", "", "a201", "a183", "a184", "a197", "a185",
|
||||
"a194", "a198", "a186", "a195", "a187", "a188", "a189", "a190", "a191", ""];
|
||||
|
||||
function getEncoding(encodingName) {
|
||||
switch (encodingName) {
|
||||
case 'WinAnsiEncoding':
|
||||
case "WinAnsiEncoding":
|
||||
return WinAnsiEncoding;
|
||||
case 'StandardEncoding':
|
||||
case "StandardEncoding":
|
||||
return StandardEncoding;
|
||||
case 'MacRomanEncoding':
|
||||
case "MacRomanEncoding":
|
||||
return MacRomanEncoding;
|
||||
case 'SymbolSetEncoding':
|
||||
case "SymbolSetEncoding":
|
||||
return SymbolSetEncoding;
|
||||
case 'ZapfDingbatsEncoding':
|
||||
case "ZapfDingbatsEncoding":
|
||||
return ZapfDingbatsEncoding;
|
||||
case 'ExpertEncoding':
|
||||
case "ExpertEncoding":
|
||||
return ExpertEncoding;
|
||||
case 'MacExpertEncoding':
|
||||
case "MacExpertEncoding":
|
||||
return MacExpertEncoding;
|
||||
default:
|
||||
return null;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,17 +14,25 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
bytesToString, FONT_IDENTITY_MATRIX, FormatError, unreachable, warn
|
||||
} from '../shared/util';
|
||||
import { CFFParser } from './cff_parser';
|
||||
import { getGlyphsUnicode } from './glyphlist';
|
||||
import { StandardEncoding } from './encodings';
|
||||
import { Stream } from './stream';
|
||||
bytesToString,
|
||||
FONT_IDENTITY_MATRIX,
|
||||
FormatError,
|
||||
unreachable,
|
||||
warn,
|
||||
} from "../shared/util";
|
||||
import { CFFParser } from "./cff_parser";
|
||||
import { getGlyphsUnicode } from "./glyphlist";
|
||||
import { StandardEncoding } from "./encodings";
|
||||
import { Stream } from "./stream";
|
||||
|
||||
var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
function getLong(data, offset) {
|
||||
return (data[offset] << 24) | (data[offset + 1] << 16) |
|
||||
(data[offset + 2] << 8) | data[offset + 3];
|
||||
return (
|
||||
(data[offset] << 24) |
|
||||
(data[offset + 1] << 16) |
|
||||
(data[offset + 2] << 8) |
|
||||
data[offset + 3]
|
||||
);
|
||||
}
|
||||
|
||||
function getUshort(data, offset) {
|
||||
@ -32,8 +40,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
}
|
||||
|
||||
function parseCmap(data, start, end) {
|
||||
var offset = (getUshort(data, start + 2) === 1 ?
|
||||
getLong(data, start + 8) : getLong(data, start + 16));
|
||||
var offset =
|
||||
getUshort(data, start + 2) === 1
|
||||
? getLong(data, start + 8)
|
||||
: getLong(data, start + 16);
|
||||
var format = getUshort(data, start + offset);
|
||||
var ranges, p, i;
|
||||
if (format === 4) {
|
||||
@ -42,7 +52,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
p = start + offset + 14;
|
||||
ranges = [];
|
||||
for (i = 0; i < segCount; i++, p += 2) {
|
||||
ranges[i] = { end: getUshort(data, p), };
|
||||
ranges[i] = { end: getUshort(data, p) };
|
||||
}
|
||||
p += 2;
|
||||
for (i = 0; i < segCount; i++, p += 2) {
|
||||
@ -83,13 +93,18 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
|
||||
function parseCff(data, start, end, seacAnalysisEnabled) {
|
||||
var properties = {};
|
||||
var parser = new CFFParser(new Stream(data, start, end - start),
|
||||
properties, seacAnalysisEnabled);
|
||||
var parser = new CFFParser(
|
||||
new Stream(data, start, end - start),
|
||||
properties,
|
||||
seacAnalysisEnabled
|
||||
);
|
||||
var cff = parser.parse();
|
||||
return {
|
||||
glyphs: cff.charStrings.objects,
|
||||
subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex &&
|
||||
cff.topDict.privateDict.subrsIndex.objects),
|
||||
subrs:
|
||||
cff.topDict.privateDict &&
|
||||
cff.topDict.privateDict.subrsIndex &&
|
||||
cff.topDict.privateDict.subrsIndex.objects,
|
||||
gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects,
|
||||
isCFFCIDFont: cff.isCIDFont,
|
||||
fdSelect: cff.fdSelect,
|
||||
@ -102,8 +117,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
if (isGlyphLocationsLong) {
|
||||
itemSize = 4;
|
||||
itemDecode = function fontItemDecodeLong(data, offset) {
|
||||
return (data[offset] << 24) | (data[offset + 1] << 16) |
|
||||
(data[offset + 2] << 8) | data[offset + 3];
|
||||
return (
|
||||
(data[offset] << 24) |
|
||||
(data[offset + 1] << 16) |
|
||||
(data[offset + 2] << 8) |
|
||||
data[offset + 3]
|
||||
);
|
||||
};
|
||||
} else {
|
||||
itemSize = 2;
|
||||
@ -122,8 +141,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
}
|
||||
|
||||
function lookupCmap(ranges, unicode) {
|
||||
var code = unicode.codePointAt(0), gid = 0;
|
||||
var l = 0, r = ranges.length - 1;
|
||||
var code = unicode.codePointAt(0),
|
||||
gid = 0;
|
||||
var l = 0,
|
||||
r = ranges.length - 1;
|
||||
while (l < r) {
|
||||
var c = (l + r + 1) >> 1;
|
||||
if (code < ranges[c].start) {
|
||||
@ -133,8 +154,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
}
|
||||
}
|
||||
if (ranges[l].start <= code && code <= ranges[l].end) {
|
||||
gid = (ranges[l].idDelta + (ranges[l].ids ?
|
||||
ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF;
|
||||
gid =
|
||||
(ranges[l].idDelta +
|
||||
(ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code)) &
|
||||
0xffff;
|
||||
}
|
||||
return {
|
||||
charCode: code,
|
||||
@ -144,19 +167,20 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
|
||||
function compileGlyf(code, cmds, font) {
|
||||
function moveTo(x, y) {
|
||||
cmds.push({ cmd: 'moveTo', args: [x, y], });
|
||||
cmds.push({ cmd: "moveTo", args: [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) {
|
||||
cmds.push({ cmd: 'quadraticCurveTo', args: [xa, ya, x, y], });
|
||||
cmds.push({ cmd: "quadraticCurveTo", args: [xa, ya, x, y] });
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var numberOfContours = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
|
||||
var flags;
|
||||
var x = 0, y = 0;
|
||||
var x = 0,
|
||||
y = 0;
|
||||
i += 10;
|
||||
if (numberOfContours < 0) {
|
||||
// composite glyph
|
||||
@ -165,29 +189,34 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
var glyphIndex = (code[i + 2] << 8) | code[i + 3];
|
||||
i += 4;
|
||||
var arg1, arg2;
|
||||
if ((flags & 0x01)) {
|
||||
if (flags & 0x01) {
|
||||
arg1 = ((code[i] << 24) | (code[i + 1] << 16)) >> 16;
|
||||
arg2 = ((code[i + 2] << 24) | (code[i + 3] << 16)) >> 16;
|
||||
i += 4;
|
||||
} else {
|
||||
arg1 = code[i++]; arg2 = code[i++];
|
||||
arg1 = code[i++];
|
||||
arg2 = code[i++];
|
||||
}
|
||||
if ((flags & 0x02)) {
|
||||
if (flags & 0x02) {
|
||||
x = arg1;
|
||||
y = arg2;
|
||||
} 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;
|
||||
if ((flags & 0x08)) {
|
||||
scaleX =
|
||||
scaleY = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
||||
var scaleX = 1,
|
||||
scaleY = 1,
|
||||
scale01 = 0,
|
||||
scale10 = 0;
|
||||
if (flags & 0x08) {
|
||||
scaleX = scaleY =
|
||||
((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
||||
i += 2;
|
||||
} else if ((flags & 0x40)) {
|
||||
} else if (flags & 0x40) {
|
||||
scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
||||
scaleY = ((code[i + 2] << 24) | (code[i + 3] << 16)) / 1073741824;
|
||||
i += 4;
|
||||
} else if ((flags & 0x80)) {
|
||||
} else if (flags & 0x80) {
|
||||
scaleX = ((code[i] << 24) | (code[i + 1] << 16)) / 1073741824;
|
||||
scale01 = ((code[i + 2] << 24) | (code[i + 3] << 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];
|
||||
if (subglyph) {
|
||||
cmds.push({ cmd: 'save', });
|
||||
cmds.push({ cmd: 'transform',
|
||||
args: [scaleX, scale01, scale10, scaleY, x, y], });
|
||||
cmds.push({ cmd: "save" });
|
||||
cmds.push({
|
||||
cmd: "transform",
|
||||
args: [scaleX, scale01, scale10, scaleY, x, y],
|
||||
});
|
||||
compileGlyf(subglyph, cmds, font);
|
||||
cmds.push({ cmd: 'restore', });
|
||||
cmds.push({ cmd: "restore" });
|
||||
}
|
||||
} while ((flags & 0x20));
|
||||
} while (flags & 0x20);
|
||||
} else {
|
||||
// simple glyph
|
||||
var endPtsOfContours = [];
|
||||
@ -218,11 +249,11 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
while (points.length < numberOfPoints) {
|
||||
flags = code[i++];
|
||||
var repeat = 1;
|
||||
if ((flags & 0x08)) {
|
||||
if (flags & 0x08) {
|
||||
repeat += code[i++];
|
||||
}
|
||||
while (repeat-- > 0) {
|
||||
points.push({ flags, });
|
||||
points.push({ flags });
|
||||
}
|
||||
}
|
||||
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
|
||||
// between two neighboring off-curve points
|
||||
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
|
||||
} 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
|
||||
contour.unshift(contour[contour.length - 1]);
|
||||
} else {
|
||||
@ -279,16 +310,23 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
}
|
||||
moveTo(contour[0].x, contour[0].y);
|
||||
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);
|
||||
} else if ((contour[j + 1].flags & 1)) {
|
||||
quadraticCurveTo(contour[j].x, contour[j].y,
|
||||
contour[j + 1].x, contour[j + 1].y);
|
||||
} else if (contour[j + 1].flags & 1) {
|
||||
quadraticCurveTo(
|
||||
contour[j].x,
|
||||
contour[j].y,
|
||||
contour[j + 1].x,
|
||||
contour[j + 1].y
|
||||
);
|
||||
j++;
|
||||
} 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].y + contour[j + 1].y) / 2);
|
||||
(contour[j].y + contour[j + 1].y) / 2
|
||||
);
|
||||
}
|
||||
}
|
||||
startPoint = endPoint + 1;
|
||||
@ -298,17 +336,18 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
|
||||
function compileCharString(code, cmds, font, glyphId) {
|
||||
var stack = [];
|
||||
var x = 0, y = 0;
|
||||
var x = 0,
|
||||
y = 0;
|
||||
var stems = 0;
|
||||
|
||||
function moveTo(x, y) {
|
||||
cmds.push({ cmd: 'moveTo', args: [x, y], });
|
||||
cmds.push({ cmd: "moveTo", args: [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) {
|
||||
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) {
|
||||
@ -362,9 +401,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
break;
|
||||
case 8: // rrcurveto
|
||||
while (stack.length > 0) {
|
||||
xa = x + stack.shift(); ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb + stack.shift(); y = yb + stack.shift();
|
||||
xa = x + 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);
|
||||
}
|
||||
break;
|
||||
@ -374,19 +416,19 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
if (font.isCFFCIDFont) {
|
||||
let fdIndex = font.fdSelect.getFDIndex(glyphId);
|
||||
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) {
|
||||
subrs = fontDict.privateDict.subrsIndex.objects;
|
||||
}
|
||||
if (subrs) {
|
||||
let numSubrs = subrs.length;
|
||||
// Add subroutine bias.
|
||||
n += numSubrs < 1240 ? 107 :
|
||||
(numSubrs < 33900 ? 1131 : 32768);
|
||||
n += numSubrs < 1240 ? 107 : numSubrs < 33900 ? 1131 : 32768;
|
||||
subrCode = subrs[n];
|
||||
}
|
||||
} else {
|
||||
warn('Invalid fd index for glyph index.');
|
||||
warn("Invalid fd index for glyph index.");
|
||||
}
|
||||
} else {
|
||||
subrCode = font.subrs[n + font.subrsBias];
|
||||
@ -402,7 +444,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
switch (v) {
|
||||
case 34: // flex
|
||||
xa = x + stack.shift();
|
||||
xb = xa + stack.shift(); y1 = y + stack.shift();
|
||||
xb = xa + stack.shift();
|
||||
y1 = y + stack.shift();
|
||||
x = xb + stack.shift();
|
||||
bezierCurveTo(xa, y, xb, y1, x, y1);
|
||||
xa = x + stack.shift();
|
||||
@ -411,35 +454,51 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
bezierCurveTo(xa, y1, xb, y, x, y);
|
||||
break;
|
||||
case 35: // flex
|
||||
xa = x + stack.shift(); ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb + stack.shift(); y = yb + stack.shift();
|
||||
xa = x + 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);
|
||||
xa = x + stack.shift(); ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb + stack.shift(); y = yb + stack.shift();
|
||||
xa = x + 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);
|
||||
stack.pop(); // fd
|
||||
break;
|
||||
case 36: // hflex1
|
||||
xa = x + stack.shift(); y1 = y + stack.shift();
|
||||
xb = xa + stack.shift(); y2 = y1 + stack.shift();
|
||||
xa = x + stack.shift();
|
||||
y1 = y + stack.shift();
|
||||
xb = xa + stack.shift();
|
||||
y2 = y1 + stack.shift();
|
||||
x = xb + stack.shift();
|
||||
bezierCurveTo(xa, y1, xb, y2, x, y2);
|
||||
xa = x + stack.shift();
|
||||
xb = xa + stack.shift(); y3 = y2 + stack.shift();
|
||||
xb = xa + stack.shift();
|
||||
y3 = y2 + stack.shift();
|
||||
x = xb + stack.shift();
|
||||
bezierCurveTo(xa, y2, xb, y3, x, y);
|
||||
break;
|
||||
case 37: // flex1
|
||||
var x0 = x, y0 = y;
|
||||
xa = x + stack.shift(); ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb + stack.shift(); y = yb + stack.shift();
|
||||
var x0 = x,
|
||||
y0 = y;
|
||||
xa = x + 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);
|
||||
xa = x + stack.shift(); ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb; y = yb;
|
||||
xa = x + stack.shift();
|
||||
ya = y + stack.shift();
|
||||
xb = xa + stack.shift();
|
||||
yb = ya + stack.shift();
|
||||
x = xb;
|
||||
y = yb;
|
||||
if (Math.abs(x - x0) > Math.abs(y - y0)) {
|
||||
x += stack.shift();
|
||||
} else {
|
||||
@ -457,18 +516,30 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
var bchar = stack.pop();
|
||||
y = stack.pop();
|
||||
x = stack.pop();
|
||||
cmds.push({ cmd: 'save', });
|
||||
cmds.push({ cmd: 'translate', args: [x, y], });
|
||||
var cmap = lookupCmap(font.cmap, String.fromCharCode(
|
||||
font.glyphNameMap[StandardEncoding[achar]]));
|
||||
compileCharString(font.glyphs[cmap.glyphId], cmds, font,
|
||||
cmap.glyphId);
|
||||
cmds.push({ cmd: 'restore', });
|
||||
cmds.push({ cmd: "save" });
|
||||
cmds.push({ cmd: "translate", args: [x, y] });
|
||||
var cmap = lookupCmap(
|
||||
font.cmap,
|
||||
String.fromCharCode(font.glyphNameMap[StandardEncoding[achar]])
|
||||
);
|
||||
compileCharString(
|
||||
font.glyphs[cmap.glyphId],
|
||||
cmds,
|
||||
font,
|
||||
cmap.glyphId
|
||||
);
|
||||
cmds.push({ cmd: "restore" });
|
||||
|
||||
cmap = lookupCmap(font.cmap, String.fromCharCode(
|
||||
font.glyphNameMap[StandardEncoding[bchar]]));
|
||||
compileCharString(font.glyphs[cmap.glyphId], cmds, font,
|
||||
cmap.glyphId);
|
||||
cmap = lookupCmap(
|
||||
font.cmap,
|
||||
String.fromCharCode(font.glyphNameMap[StandardEncoding[bchar]])
|
||||
);
|
||||
compileCharString(
|
||||
font.glyphs[cmap.glyphId],
|
||||
cmds,
|
||||
font,
|
||||
cmap.glyphId
|
||||
);
|
||||
}
|
||||
return;
|
||||
case 18: // hstemhm
|
||||
@ -502,9 +573,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
break;
|
||||
case 24: // rcurveline
|
||||
while (stack.length > 2) {
|
||||
xa = x + stack.shift(); ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb + stack.shift(); y = yb + stack.shift();
|
||||
xa = x + 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);
|
||||
}
|
||||
x += stack.shift();
|
||||
@ -517,9 +591,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
y += stack.shift();
|
||||
lineTo(x, y);
|
||||
}
|
||||
xa = x + stack.shift(); ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb + stack.shift(); y = yb + stack.shift();
|
||||
xa = x + 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);
|
||||
break;
|
||||
case 26: // vvcurveto
|
||||
@ -527,9 +604,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
x += stack.shift();
|
||||
}
|
||||
while (stack.length > 0) {
|
||||
xa = x; ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb; y = yb + stack.shift();
|
||||
xa = x;
|
||||
ya = y + stack.shift();
|
||||
xb = xa + stack.shift();
|
||||
yb = ya + stack.shift();
|
||||
x = xb;
|
||||
y = yb + stack.shift();
|
||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||
}
|
||||
break;
|
||||
@ -538,9 +618,12 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
y += stack.shift();
|
||||
}
|
||||
while (stack.length > 0) {
|
||||
xa = x + stack.shift(); ya = y;
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
x = xb + stack.shift(); y = yb;
|
||||
xa = x + stack.shift();
|
||||
ya = y;
|
||||
xb = xa + stack.shift();
|
||||
yb = ya + stack.shift();
|
||||
x = xb + stack.shift();
|
||||
y = yb;
|
||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||
}
|
||||
break;
|
||||
@ -557,8 +640,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
break;
|
||||
case 30: // vhcurveto
|
||||
while (stack.length > 0) {
|
||||
xa = x; ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
xa = x;
|
||||
ya = y + stack.shift();
|
||||
xb = xa + stack.shift();
|
||||
yb = ya + stack.shift();
|
||||
x = xb + stack.shift();
|
||||
y = yb + (stack.length === 1 ? stack.shift() : 0);
|
||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||
@ -566,8 +651,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
break;
|
||||
}
|
||||
|
||||
xa = x + stack.shift(); ya = y;
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
xa = x + stack.shift();
|
||||
ya = y;
|
||||
xb = xa + stack.shift();
|
||||
yb = ya + stack.shift();
|
||||
y = yb + stack.shift();
|
||||
x = xb + (stack.length === 1 ? stack.shift() : 0);
|
||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||
@ -575,8 +662,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
break;
|
||||
case 31: // hvcurveto
|
||||
while (stack.length > 0) {
|
||||
xa = x + stack.shift(); ya = y;
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
xa = x + stack.shift();
|
||||
ya = y;
|
||||
xb = xa + stack.shift();
|
||||
yb = ya + stack.shift();
|
||||
y = yb + stack.shift();
|
||||
x = xb + (stack.length === 1 ? stack.shift() : 0);
|
||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||
@ -584,8 +673,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
break;
|
||||
}
|
||||
|
||||
xa = x; ya = y + stack.shift();
|
||||
xb = xa + stack.shift(); yb = ya + stack.shift();
|
||||
xa = x;
|
||||
ya = y + stack.shift();
|
||||
xb = xa + stack.shift();
|
||||
yb = ya + stack.shift();
|
||||
x = xb + stack.shift();
|
||||
y = yb + (stack.length === 1 ? stack.shift() : 0);
|
||||
bezierCurveTo(xa, ya, xb, yb, x, y);
|
||||
@ -602,8 +693,13 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
} else if (v < 255) {
|
||||
stack.push(-(v - 251) * 256 - code[i++] - 108);
|
||||
} else {
|
||||
stack.push(((code[i] << 24) | (code[i + 1] << 16) |
|
||||
(code[i + 2] << 8) | code[i + 3]) / 65536);
|
||||
stack.push(
|
||||
((code[i] << 24) |
|
||||
(code[i + 1] << 16) |
|
||||
(code[i + 2] << 8) |
|
||||
code[i + 3]) /
|
||||
65536
|
||||
);
|
||||
i += 4;
|
||||
}
|
||||
break;
|
||||
@ -621,7 +717,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
class CompiledFont {
|
||||
constructor(fontMatrix) {
|
||||
if (this.constructor === CompiledFont) {
|
||||
unreachable('Cannot initialize CompiledFont.');
|
||||
unreachable("Cannot initialize CompiledFont.");
|
||||
}
|
||||
this.fontMatrix = fontMatrix;
|
||||
|
||||
@ -654,32 +750,34 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
let fdIndex = this.fdSelect.getFDIndex(glyphId);
|
||||
if (fdIndex >= 0 && fdIndex < this.fdArray.length) {
|
||||
let fontDict = this.fdArray[fdIndex];
|
||||
fontMatrix = fontDict.getByName('FontMatrix') || FONT_IDENTITY_MATRIX;
|
||||
fontMatrix = fontDict.getByName("FontMatrix") || FONT_IDENTITY_MATRIX;
|
||||
} else {
|
||||
warn('Invalid fd index for glyph index.');
|
||||
warn("Invalid fd index for glyph index.");
|
||||
}
|
||||
}
|
||||
|
||||
const cmds = [];
|
||||
cmds.push({ cmd: 'save', });
|
||||
cmds.push({ cmd: 'transform', args: fontMatrix.slice(), });
|
||||
cmds.push({ cmd: 'scale', args: ['size', '-size'], });
|
||||
cmds.push({ cmd: "save" });
|
||||
cmds.push({ cmd: "transform", args: fontMatrix.slice() });
|
||||
cmds.push({ cmd: "scale", args: ["size", "-size"] });
|
||||
|
||||
this.compileGlyphImpl(code, cmds, glyphId);
|
||||
|
||||
cmds.push({ cmd: 'restore', });
|
||||
cmds.push({ cmd: "restore" });
|
||||
|
||||
return cmds;
|
||||
}
|
||||
|
||||
compileGlyphImpl() {
|
||||
unreachable('Children classes should implement this.');
|
||||
unreachable("Children classes should implement this.");
|
||||
}
|
||||
|
||||
hasBuiltPath(unicode) {
|
||||
const cmap = lookupCmap(this.cmap, unicode);
|
||||
return (this.compiledGlyphs[cmap.glyphId] !== undefined &&
|
||||
this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined);
|
||||
return (
|
||||
this.compiledGlyphs[cmap.glyphId] !== undefined &&
|
||||
this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -706,10 +804,18 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
this.cmap = cmap;
|
||||
this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
|
||||
|
||||
this.gsubrsBias = (this.gsubrs.length < 1240 ?
|
||||
107 : (this.gsubrs.length < 33900 ? 1131 : 32768));
|
||||
this.subrsBias = (this.subrs.length < 1240 ?
|
||||
107 : (this.subrs.length < 33900 ? 1131 : 32768));
|
||||
this.gsubrsBias =
|
||||
this.gsubrs.length < 1240
|
||||
? 107
|
||||
: this.gsubrs.length < 33900
|
||||
? 1131
|
||||
: 32768;
|
||||
this.subrsBias =
|
||||
this.subrs.length < 1240
|
||||
? 107
|
||||
: this.subrs.length < 33900
|
||||
? 1131
|
||||
: 32768;
|
||||
|
||||
this.isCFFCIDFont = cffInfo.isCFFCIDFont;
|
||||
this.fdSelect = cffInfo.fdSelect;
|
||||
@ -731,36 +837,38 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
var offset = getLong(data, p + 8);
|
||||
var length = getLong(data, p + 12);
|
||||
switch (tag) {
|
||||
case 'cmap':
|
||||
case "cmap":
|
||||
cmap = parseCmap(data, offset, offset + length);
|
||||
break;
|
||||
case 'glyf':
|
||||
case "glyf":
|
||||
glyf = data.subarray(offset, offset + length);
|
||||
break;
|
||||
case 'loca':
|
||||
case "loca":
|
||||
loca = data.subarray(offset, offset + length);
|
||||
break;
|
||||
case 'head':
|
||||
case "head":
|
||||
unitsPerEm = getUshort(data, offset + 18);
|
||||
indexToLocFormat = getUshort(data, offset + 50);
|
||||
break;
|
||||
case 'CFF ':
|
||||
case "CFF ":
|
||||
cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (glyf) {
|
||||
var fontMatrix = (!unitsPerEm ? font.fontMatrix :
|
||||
[1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0]);
|
||||
var fontMatrix = !unitsPerEm
|
||||
? font.fontMatrix
|
||||
: [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];
|
||||
return new TrueTypeCompiled(
|
||||
parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
|
||||
parseGlyfTable(glyf, loca, indexToLocFormat),
|
||||
cmap,
|
||||
fontMatrix
|
||||
);
|
||||
}
|
||||
return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
||||
export {
|
||||
FontRendererFactory,
|
||||
};
|
||||
export { FontRendererFactory };
|
||||
|
1785
src/core/fonts.js
1785
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.
|
||||
*/
|
||||
|
||||
import { assert, FormatError, ImageKind, info, warn } from '../shared/util';
|
||||
import { isName, isStream, Name } from './primitives';
|
||||
import { ColorSpace } from './colorspace';
|
||||
import { DecodeStream } from './stream';
|
||||
import { JpegStream } from './jpeg_stream';
|
||||
import { JpxImage } from './jpx';
|
||||
import { assert, FormatError, ImageKind, info, warn } from "../shared/util";
|
||||
import { isName, isStream, Name } from "./primitives";
|
||||
import { ColorSpace } from "./colorspace";
|
||||
import { DecodeStream } from "./stream";
|
||||
import { JpegStream } from "./jpeg_stream";
|
||||
import { JpxImage } from "./jpx";
|
||||
|
||||
var PDFImage = (function PDFImageClosure() {
|
||||
/**
|
||||
@ -27,9 +27,11 @@ var PDFImage = (function PDFImageClosure() {
|
||||
*/
|
||||
function handleImageData(image, nativeDecoder) {
|
||||
if (nativeDecoder && nativeDecoder.canDecode(image)) {
|
||||
return nativeDecoder.decode(image).catch((reason) => {
|
||||
warn('Native image decoding failed -- trying to recover: ' +
|
||||
(reason && reason.message));
|
||||
return nativeDecoder.decode(image).catch(reason => {
|
||||
warn(
|
||||
"Native image decoding failed -- trying to recover: " +
|
||||
(reason && reason.message)
|
||||
);
|
||||
return image;
|
||||
});
|
||||
}
|
||||
@ -43,7 +45,7 @@ var PDFImage = (function PDFImageClosure() {
|
||||
function decodeAndClamp(value, addend, coefficient, max) {
|
||||
value = addend + value * coefficient;
|
||||
// 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) {
|
||||
var length = w2 * h2;
|
||||
var dest = (bpc <= 8 ? new Uint8Array(length) :
|
||||
(bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length)));
|
||||
var dest =
|
||||
bpc <= 8
|
||||
? new Uint8Array(length)
|
||||
: bpc <= 16
|
||||
? new Uint16Array(length)
|
||||
: new Uint32Array(length);
|
||||
var xRatio = w1 / w2;
|
||||
var yRatio = h1 / h2;
|
||||
var i, j, py, newIndex = 0, oldIndex;
|
||||
var i,
|
||||
j,
|
||||
py,
|
||||
newIndex = 0,
|
||||
oldIndex;
|
||||
var xScaled = new Uint16Array(w2);
|
||||
var w1Scanline = w1;
|
||||
|
||||
@ -79,15 +89,23 @@ var PDFImage = (function PDFImageClosure() {
|
||||
return dest;
|
||||
}
|
||||
|
||||
function PDFImage({ xref, res, image, isInline = false, smask = null,
|
||||
mask = null, isMask = false, pdfFunctionFactory, }) {
|
||||
function PDFImage({
|
||||
xref,
|
||||
res,
|
||||
image,
|
||||
isInline = false,
|
||||
smask = null,
|
||||
mask = null,
|
||||
isMask = false,
|
||||
pdfFunctionFactory,
|
||||
}) {
|
||||
this.image = image;
|
||||
var dict = image.dict;
|
||||
|
||||
const filter = dict.get('Filter');
|
||||
const filter = dict.get("Filter");
|
||||
if (isName(filter)) {
|
||||
switch (filter.name) {
|
||||
case 'JPXDecode':
|
||||
case "JPXDecode":
|
||||
var jpxImage = new JpxImage();
|
||||
jpxImage.parseImageProperties(image.stream);
|
||||
image.stream.reset();
|
||||
@ -97,7 +115,7 @@ var PDFImage = (function PDFImageClosure() {
|
||||
image.bitsPerComponent = jpxImage.bitsPerComponent;
|
||||
image.numComps = jpxImage.componentsCount;
|
||||
break;
|
||||
case 'JBIG2Decode':
|
||||
case "JBIG2Decode":
|
||||
image.bitsPerComponent = 1;
|
||||
image.numComps = 1;
|
||||
break;
|
||||
@ -105,86 +123,103 @@ var PDFImage = (function PDFImageClosure() {
|
||||
}
|
||||
// TODO cache rendered images?
|
||||
|
||||
let width = dict.get('Width', 'W');
|
||||
let height = dict.get('Height', 'H');
|
||||
let width = dict.get("Width", "W");
|
||||
let height = dict.get("Height", "H");
|
||||
|
||||
if ((Number.isInteger(image.width) && image.width > 0) &&
|
||||
(Number.isInteger(image.height) && image.height > 0) &&
|
||||
(image.width !== width || image.height !== height)) {
|
||||
warn('PDFImage - using the Width/Height of the image data, ' +
|
||||
'rather than the image dictionary.');
|
||||
if (
|
||||
Number.isInteger(image.width) &&
|
||||
image.width > 0 &&
|
||||
Number.isInteger(image.height) &&
|
||||
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;
|
||||
height = image.height;
|
||||
}
|
||||
if (width < 1 || height < 1) {
|
||||
throw new FormatError(`Invalid image width: ${width} or ` +
|
||||
`height: ${height}`);
|
||||
throw new FormatError(
|
||||
`Invalid image width: ${width} or ` + `height: ${height}`
|
||||
);
|
||||
}
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
this.interpolate = dict.get('Interpolate', 'I') || false;
|
||||
this.imageMask = dict.get('ImageMask', 'IM') || false;
|
||||
this.matte = dict.get('Matte') || false;
|
||||
this.interpolate = dict.get("Interpolate", "I") || false;
|
||||
this.imageMask = dict.get("ImageMask", "IM") || false;
|
||||
this.matte = dict.get("Matte") || false;
|
||||
|
||||
var bitsPerComponent = image.bitsPerComponent;
|
||||
if (!bitsPerComponent) {
|
||||
bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
|
||||
bitsPerComponent = dict.get("BitsPerComponent", "BPC");
|
||||
if (!bitsPerComponent) {
|
||||
if (this.imageMask) {
|
||||
bitsPerComponent = 1;
|
||||
} else {
|
||||
throw new FormatError(
|
||||
`Bits per component missing in image: ${this.imageMask}`);
|
||||
`Bits per component missing in image: ${this.imageMask}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.bpc = bitsPerComponent;
|
||||
|
||||
if (!this.imageMask) {
|
||||
var colorSpace = dict.get('ColorSpace', 'CS');
|
||||
var colorSpace = dict.get("ColorSpace", "CS");
|
||||
if (!colorSpace) {
|
||||
info('JPX images (which do not require color spaces)');
|
||||
info("JPX images (which do not require color spaces)");
|
||||
switch (image.numComps) {
|
||||
case 1:
|
||||
colorSpace = Name.get('DeviceGray');
|
||||
colorSpace = Name.get("DeviceGray");
|
||||
break;
|
||||
case 3:
|
||||
colorSpace = Name.get('DeviceRGB');
|
||||
colorSpace = Name.get("DeviceRGB");
|
||||
break;
|
||||
case 4:
|
||||
colorSpace = Name.get('DeviceCMYK');
|
||||
colorSpace = Name.get("DeviceCMYK");
|
||||
break;
|
||||
default:
|
||||
throw new Error(`JPX images with ${image.numComps} ` +
|
||||
'color components not supported.');
|
||||
throw new Error(
|
||||
`JPX images with ${image.numComps} ` +
|
||||
"color components not supported."
|
||||
);
|
||||
}
|
||||
}
|
||||
let resources = isInline ? res : null;
|
||||
this.colorSpace = ColorSpace.parse(colorSpace, xref, resources,
|
||||
pdfFunctionFactory);
|
||||
this.colorSpace = ColorSpace.parse(
|
||||
colorSpace,
|
||||
xref,
|
||||
resources,
|
||||
pdfFunctionFactory
|
||||
);
|
||||
this.numComps = this.colorSpace.numComps;
|
||||
}
|
||||
|
||||
this.decode = dict.getArray('Decode', 'D');
|
||||
this.decode = dict.getArray("Decode", "D");
|
||||
this.needsDecode = false;
|
||||
if (this.decode &&
|
||||
if (
|
||||
this.decode &&
|
||||
((this.colorSpace &&
|
||||
!this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent)) ||
|
||||
(isMask &&
|
||||
!ColorSpace.isDefaultDecode(this.decode, /* numComps = */ 1)))) {
|
||||
!ColorSpace.isDefaultDecode(this.decode, /* numComps = */ 1)))
|
||||
) {
|
||||
this.needsDecode = true;
|
||||
// Do some preprocessing to avoid more math.
|
||||
var max = (1 << bitsPerComponent) - 1;
|
||||
this.decodeCoefficients = [];
|
||||
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) {
|
||||
var dmin = this.decode[i];
|
||||
var dmax = this.decode[i + 1];
|
||||
this.decodeCoefficients[j] = isIndexed ? ((dmax - dmin) / max) :
|
||||
(dmax - dmin);
|
||||
this.decodeAddends[j] = isIndexed ? dmin : (max * dmin);
|
||||
this.decodeCoefficients[j] = isIndexed
|
||||
? (dmax - dmin) / max
|
||||
: dmax - dmin;
|
||||
this.decodeAddends[j] = isIndexed ? dmin : max * dmin;
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,9 +233,10 @@ var PDFImage = (function PDFImageClosure() {
|
||||
});
|
||||
} else if (mask) {
|
||||
if (isStream(mask)) {
|
||||
var maskDict = mask.dict, imageMask = maskDict.get('ImageMask', 'IM');
|
||||
var maskDict = mask.dict,
|
||||
imageMask = maskDict.get("ImageMask", "IM");
|
||||
if (!imageMask) {
|
||||
warn('Ignoring /Mask in image without /ImageMask.');
|
||||
warn("Ignoring /Mask in image without /ImageMask.");
|
||||
} else {
|
||||
this.mask = new PDFImage({
|
||||
xref,
|
||||
@ -221,15 +257,21 @@ var PDFImage = (function PDFImageClosure() {
|
||||
* Handles processing of image data and returns the Promise that is resolved
|
||||
* 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,
|
||||
pdfFunctionFactory, }) {
|
||||
pdfFunctionFactory,
|
||||
}) {
|
||||
var imagePromise = handleImageData(image, nativeDecoder);
|
||||
var smaskPromise;
|
||||
var maskPromise;
|
||||
|
||||
var smask = image.dict.get('SMask');
|
||||
var mask = image.dict.get('Mask');
|
||||
var smask = image.dict.get("SMask");
|
||||
var mask = image.dict.get("Mask");
|
||||
|
||||
if (smask) {
|
||||
smaskPromise = handleImageData(smask, nativeDecoder);
|
||||
@ -242,7 +284,7 @@ var PDFImage = (function PDFImageClosure() {
|
||||
} else if (Array.isArray(mask)) {
|
||||
maskPromise = Promise.resolve(mask);
|
||||
} else {
|
||||
warn('Unsupported mask format.');
|
||||
warn("Unsupported mask format.");
|
||||
maskPromise = Promise.resolve(null);
|
||||
}
|
||||
} else {
|
||||
@ -260,15 +302,25 @@ var PDFImage = (function PDFImageClosure() {
|
||||
mask: maskData,
|
||||
pdfFunctionFactory,
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
PDFImage.createMask = function({ imgArray, width, height,
|
||||
imageIsFromDecodeStream, inverseDecode, }) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
assert(imgArray instanceof Uint8ClampedArray,
|
||||
'PDFImage.createMask: Unsupported "imgArray" type.');
|
||||
PDFImage.createMask = function({
|
||||
imgArray,
|
||||
width,
|
||||
height,
|
||||
imageIsFromDecodeStream,
|
||||
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
|
||||
// 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.
|
||||
if (inverseDecode) {
|
||||
for (i = 0; i < actualLength; i++) {
|
||||
data[i] ^= 0xFF;
|
||||
data[i] ^= 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
return { data, width, height, };
|
||||
return { data, width, height };
|
||||
};
|
||||
|
||||
PDFImage.prototype = {
|
||||
get drawWidth() {
|
||||
return Math.max(this.width,
|
||||
this.smask && this.smask.width || 0,
|
||||
this.mask && this.mask.width || 0);
|
||||
return Math.max(
|
||||
this.width,
|
||||
(this.smask && this.smask.width) || 0,
|
||||
(this.mask && this.mask.width) || 0
|
||||
);
|
||||
},
|
||||
|
||||
get drawHeight() {
|
||||
return Math.max(this.height,
|
||||
this.smask && this.smask.height || 0,
|
||||
this.mask && this.mask.height || 0);
|
||||
return Math.max(
|
||||
this.height,
|
||||
(this.smask && this.smask.height) || 0,
|
||||
(this.mask && this.mask.height) || 0
|
||||
);
|
||||
},
|
||||
|
||||
decodeBuffer(buffer) {
|
||||
@ -333,15 +389,19 @@ var PDFImage = (function PDFImageClosure() {
|
||||
if (bpc === 1) {
|
||||
// If the buffer needed decode that means it just needs to be inverted.
|
||||
for (i = 0, ii = buffer.length; i < ii; i++) {
|
||||
buffer[i] = +!(buffer[i]);
|
||||
buffer[i] = +!buffer[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
var index = 0;
|
||||
for (i = 0, ii = this.width * this.height; i < ii; i++) {
|
||||
for (var j = 0; j < numComps; j++) {
|
||||
buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j],
|
||||
decodeCoefficients[j], max);
|
||||
buffer[index] = decodeAndClamp(
|
||||
buffer[index],
|
||||
decodeAddends[j],
|
||||
decodeCoefficients[j],
|
||||
max
|
||||
);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
@ -361,12 +421,18 @@ var PDFImage = (function PDFImageClosure() {
|
||||
|
||||
var length = width * height * numComps;
|
||||
var bufferPos = 0;
|
||||
var output = (bpc <= 8 ? new Uint8Array(length) :
|
||||
(bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length)));
|
||||
var output =
|
||||
bpc <= 8
|
||||
? new Uint8Array(length)
|
||||
: bpc <= 16
|
||||
? new Uint16Array(length)
|
||||
: new Uint32Array(length);
|
||||
var rowComps = width * numComps;
|
||||
|
||||
var max = (1 << bpc) - 1;
|
||||
var i = 0, ii, buf;
|
||||
var i = 0,
|
||||
ii,
|
||||
buf;
|
||||
|
||||
if (bpc === 1) {
|
||||
// Optimization for reading 1 bpc images.
|
||||
@ -416,7 +482,7 @@ var PDFImage = (function PDFImageClosure() {
|
||||
|
||||
var remainingBits = bits - bpc;
|
||||
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);
|
||||
bits = remainingBits;
|
||||
}
|
||||
@ -425,10 +491,14 @@ var PDFImage = (function PDFImageClosure() {
|
||||
},
|
||||
|
||||
fillOpacity(rgbaBuf, width, height, actualHeight, image) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
assert(rgbaBuf instanceof Uint8ClampedArray,
|
||||
'PDFImage.fillOpacity: Unsupported "rgbaBuf" type.');
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||
) {
|
||||
assert(
|
||||
rgbaBuf instanceof Uint8ClampedArray,
|
||||
'PDFImage.fillOpacity: Unsupported "rgbaBuf" type.'
|
||||
);
|
||||
}
|
||||
var smask = this.smask;
|
||||
var mask = this.mask;
|
||||
@ -440,8 +510,14 @@ var PDFImage = (function PDFImageClosure() {
|
||||
alphaBuf = new Uint8ClampedArray(sw * sh);
|
||||
smask.fillGrayBuffer(alphaBuf);
|
||||
if (sw !== width || sh !== height) {
|
||||
alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh,
|
||||
width, height);
|
||||
alphaBuf = resizeImageMask(
|
||||
alphaBuf,
|
||||
smask.bpc,
|
||||
sw,
|
||||
sh,
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
} else if (mask) {
|
||||
if (mask instanceof PDFImage) {
|
||||
@ -457,8 +533,14 @@ var PDFImage = (function PDFImageClosure() {
|
||||
}
|
||||
|
||||
if (sw !== width || sh !== height) {
|
||||
alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh,
|
||||
width, height);
|
||||
alphaBuf = resizeImageMask(
|
||||
alphaBuf,
|
||||
mask.bpc,
|
||||
sw,
|
||||
sh,
|
||||
width,
|
||||
height
|
||||
);
|
||||
}
|
||||
} else if (Array.isArray(mask)) {
|
||||
// Color key mask: if any of the components are outside the range
|
||||
@ -479,7 +561,7 @@ var PDFImage = (function PDFImageClosure() {
|
||||
alphaBuf[i] = opacity;
|
||||
}
|
||||
} 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) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
assert(buffer instanceof Uint8ClampedArray,
|
||||
'PDFImage.undoPreblend: Unsupported "buffer" type.');
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||
) {
|
||||
assert(
|
||||
buffer instanceof Uint8ClampedArray,
|
||||
'PDFImage.undoPreblend: Unsupported "buffer" type.'
|
||||
);
|
||||
}
|
||||
var matte = this.smask && this.smask.matte;
|
||||
if (!matte) {
|
||||
@ -530,7 +616,8 @@ var PDFImage = (function PDFImageClosure() {
|
||||
createImageData(forceRGBA = false) {
|
||||
var drawWidth = this.drawWidth;
|
||||
var drawHeight = this.drawHeight;
|
||||
var imgData = { // other fields are filled in below
|
||||
var imgData = {
|
||||
// other fields are filled in below
|
||||
width: drawWidth,
|
||||
height: drawHeight,
|
||||
kind: 0,
|
||||
@ -555,14 +642,22 @@ var PDFImage = (function PDFImageClosure() {
|
||||
// Similarly, if it is a 24-bit-per pixel RGB image without any
|
||||
// complications, we avoid expanding by 1.333x to RGBA form.
|
||||
var kind;
|
||||
if (this.colorSpace.name === 'DeviceGray' && bpc === 1) {
|
||||
if (this.colorSpace.name === "DeviceGray" && bpc === 1) {
|
||||
kind = ImageKind.GRAYSCALE_1BPP;
|
||||
} else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 &&
|
||||
!this.needsDecode) {
|
||||
} else if (
|
||||
this.colorSpace.name === "DeviceRGB" &&
|
||||
bpc === 8 &&
|
||||
!this.needsDecode
|
||||
) {
|
||||
kind = ImageKind.RGB_24BPP;
|
||||
}
|
||||
if (kind && !this.smask && !this.mask &&
|
||||
drawWidth === originalWidth && drawHeight === originalHeight) {
|
||||
if (
|
||||
kind &&
|
||||
!this.smask &&
|
||||
!this.mask &&
|
||||
drawWidth === originalWidth &&
|
||||
drawHeight === originalHeight
|
||||
) {
|
||||
imgData.kind = kind;
|
||||
|
||||
imgArray = this.getImageBytes(originalHeight * rowBytes);
|
||||
@ -580,8 +675,10 @@ var PDFImage = (function PDFImageClosure() {
|
||||
}
|
||||
if (this.needsDecode) {
|
||||
// Invert the buffer (which must be grayscale if we reached here).
|
||||
assert(kind === ImageKind.GRAYSCALE_1BPP,
|
||||
'PDFImage.createImageData: The image must be grayscale.');
|
||||
assert(
|
||||
kind === ImageKind.GRAYSCALE_1BPP,
|
||||
"PDFImage.createImageData: The image must be grayscale."
|
||||
);
|
||||
var buffer = imgData.data;
|
||||
for (var i = 0, ii = buffer.length; i < ii; i++) {
|
||||
buffer[i] ^= 0xff;
|
||||
@ -592,16 +689,20 @@ var PDFImage = (function PDFImageClosure() {
|
||||
if (this.image instanceof JpegStream && !this.smask && !this.mask) {
|
||||
let imageLength = originalHeight * rowBytes;
|
||||
switch (this.colorSpace.name) {
|
||||
case 'DeviceGray':
|
||||
case "DeviceGray":
|
||||
// Avoid truncating the image, since `JpegImage.getData`
|
||||
// will expand the image data when `forceRGB === true`.
|
||||
imageLength *= 3;
|
||||
/* falls through */
|
||||
case 'DeviceRGB':
|
||||
case 'DeviceCMYK':
|
||||
case "DeviceRGB":
|
||||
case "DeviceCMYK":
|
||||
imgData.kind = ImageKind.RGB_24BPP;
|
||||
imgData.data = this.getImageBytes(imageLength,
|
||||
drawWidth, drawHeight, /* forceRGB = */ true);
|
||||
imgData.data = this.getImageBytes(
|
||||
imageLength,
|
||||
drawWidth,
|
||||
drawHeight,
|
||||
/* forceRGB = */ true
|
||||
);
|
||||
return imgData;
|
||||
}
|
||||
}
|
||||
@ -609,8 +710,8 @@ var PDFImage = (function PDFImageClosure() {
|
||||
|
||||
imgArray = this.getImageBytes(originalHeight * rowBytes);
|
||||
// imgArray can be incomplete (e.g. after CCITT fax encoding).
|
||||
var actualHeight = 0 | (imgArray.length / rowBytes *
|
||||
drawHeight / originalHeight);
|
||||
var actualHeight =
|
||||
0 | (((imgArray.length / rowBytes) * drawHeight) / originalHeight);
|
||||
|
||||
var comps = this.getComponents(imgArray);
|
||||
|
||||
@ -629,16 +730,29 @@ var PDFImage = (function PDFImageClosure() {
|
||||
maybeUndoPreblend = true;
|
||||
|
||||
// Color key masking (opacity) must be performed before decoding.
|
||||
this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight,
|
||||
comps);
|
||||
this.fillOpacity(
|
||||
imgData.data,
|
||||
drawWidth,
|
||||
drawHeight,
|
||||
actualHeight,
|
||||
comps
|
||||
);
|
||||
}
|
||||
|
||||
if (this.needsDecode) {
|
||||
this.decodeBuffer(comps);
|
||||
}
|
||||
this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight,
|
||||
drawWidth, drawHeight, actualHeight, bpc, comps,
|
||||
alpha01);
|
||||
this.colorSpace.fillRgb(
|
||||
imgData.data,
|
||||
originalWidth,
|
||||
originalHeight,
|
||||
drawWidth,
|
||||
drawHeight,
|
||||
actualHeight,
|
||||
bpc,
|
||||
comps,
|
||||
alpha01
|
||||
);
|
||||
if (maybeUndoPreblend) {
|
||||
this.undoPreblend(imgData.data, drawWidth, actualHeight);
|
||||
}
|
||||
@ -647,15 +761,20 @@ var PDFImage = (function PDFImageClosure() {
|
||||
},
|
||||
|
||||
fillGrayBuffer(buffer) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
assert(buffer instanceof Uint8ClampedArray,
|
||||
'PDFImage.fillGrayBuffer: Unsupported "buffer" type.');
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||
) {
|
||||
assert(
|
||||
buffer instanceof Uint8ClampedArray,
|
||||
'PDFImage.fillGrayBuffer: Unsupported "buffer" type.'
|
||||
);
|
||||
}
|
||||
var numComps = this.numComps;
|
||||
if (numComps !== 1) {
|
||||
throw new FormatError(
|
||||
`Reading gray scale from a color image: ${numComps}`);
|
||||
`Reading gray scale from a color image: ${numComps}`
|
||||
);
|
||||
}
|
||||
|
||||
var width = this.width;
|
||||
@ -680,7 +799,7 @@ var PDFImage = (function PDFImageClosure() {
|
||||
} else {
|
||||
// scale to {0, 255}
|
||||
for (i = 0; i < length; ++i) {
|
||||
buffer[i] = (-comps[i]) & 255;
|
||||
buffer[i] = -comps[i] & 255;
|
||||
}
|
||||
}
|
||||
return;
|
||||
@ -708,6 +827,4 @@ var PDFImage = (function PDFImageClosure() {
|
||||
return PDFImage;
|
||||
})();
|
||||
|
||||
export {
|
||||
PDFImage,
|
||||
};
|
||||
export { PDFImage };
|
||||
|
@ -14,13 +14,18 @@
|
||||
*/
|
||||
/* eslint no-var: error */
|
||||
|
||||
import { ColorSpace } from './colorspace';
|
||||
import { JpegStream } from './jpeg_stream';
|
||||
import { Stream } from './stream';
|
||||
import { ColorSpace } from "./colorspace";
|
||||
import { JpegStream } from "./jpeg_stream";
|
||||
import { Stream } from "./stream";
|
||||
|
||||
class NativeImageDecoder {
|
||||
constructor({ xref, resources, handler, forceDataSchema = false,
|
||||
pdfFunctionFactory, }) {
|
||||
constructor({
|
||||
xref,
|
||||
resources,
|
||||
handler,
|
||||
forceDataSchema = false,
|
||||
pdfFunctionFactory,
|
||||
}) {
|
||||
this.xref = xref;
|
||||
this.resources = resources;
|
||||
this.handler = handler;
|
||||
@ -29,21 +34,34 @@ class NativeImageDecoder {
|
||||
}
|
||||
|
||||
canDecode(image) {
|
||||
return image instanceof JpegStream &&
|
||||
NativeImageDecoder.isDecodable(image, this.xref, this.resources,
|
||||
this.pdfFunctionFactory);
|
||||
return (
|
||||
image instanceof JpegStream &&
|
||||
NativeImageDecoder.isDecodable(
|
||||
image,
|
||||
this.xref,
|
||||
this.resources,
|
||||
this.pdfFunctionFactory
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
decode(image) {
|
||||
// For natively supported JPEGs send them to the main thread for decoding.
|
||||
const dict = image.dict;
|
||||
let colorSpace = dict.get('ColorSpace', 'CS');
|
||||
colorSpace = ColorSpace.parse(colorSpace, this.xref, this.resources,
|
||||
this.pdfFunctionFactory);
|
||||
let colorSpace = dict.get("ColorSpace", "CS");
|
||||
colorSpace = ColorSpace.parse(
|
||||
colorSpace,
|
||||
this.xref,
|
||||
this.resources,
|
||||
this.pdfFunctionFactory
|
||||
);
|
||||
|
||||
return this.handler.sendWithPromise('JpegDecode', [
|
||||
image.getIR(this.forceDataSchema), colorSpace.numComps
|
||||
]).then(function({ data, width, height, }) {
|
||||
return this.handler
|
||||
.sendWithPromise("JpegDecode", [
|
||||
image.getIR(this.forceDataSchema),
|
||||
colorSpace.numComps,
|
||||
])
|
||||
.then(function({ data, width, height }) {
|
||||
return new Stream(data, 0, data.length, dict);
|
||||
});
|
||||
}
|
||||
@ -54,14 +72,20 @@ class NativeImageDecoder {
|
||||
*/
|
||||
static isSupported(image, xref, res, pdfFunctionFactory) {
|
||||
const dict = image.dict;
|
||||
if (dict.has('DecodeParms') || dict.has('DP')) {
|
||||
if (dict.has("DecodeParms") || dict.has("DP")) {
|
||||
return false;
|
||||
}
|
||||
const cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res,
|
||||
pdfFunctionFactory);
|
||||
const cs = ColorSpace.parse(
|
||||
dict.get("ColorSpace", "CS"),
|
||||
xref,
|
||||
res,
|
||||
pdfFunctionFactory
|
||||
);
|
||||
// isDefaultDecode() of DeviceGray and DeviceRGB needs no `bpc` argument.
|
||||
return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') &&
|
||||
cs.isDefaultDecode(dict.getArray('Decode', 'D'));
|
||||
return (
|
||||
(cs.name === "DeviceGray" || cs.name === "DeviceRGB") &&
|
||||
cs.isDefaultDecode(dict.getArray("Decode", "D"))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,17 +93,21 @@ class NativeImageDecoder {
|
||||
*/
|
||||
static isDecodable(image, xref, res, pdfFunctionFactory) {
|
||||
const dict = image.dict;
|
||||
if (dict.has('DecodeParms') || dict.has('DP')) {
|
||||
if (dict.has("DecodeParms") || dict.has("DP")) {
|
||||
return false;
|
||||
}
|
||||
const cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res,
|
||||
pdfFunctionFactory);
|
||||
const bpc = dict.get('BitsPerComponent', 'BPC') || 1;
|
||||
return (cs.numComps === 1 || cs.numComps === 3) &&
|
||||
cs.isDefaultDecode(dict.getArray('Decode', 'D'), bpc);
|
||||
const cs = ColorSpace.parse(
|
||||
dict.get("ColorSpace", "CS"),
|
||||
xref,
|
||||
res,
|
||||
pdfFunctionFactory
|
||||
);
|
||||
const bpc = dict.get("BitsPerComponent", "BPC") || 1;
|
||||
return (
|
||||
(cs.numComps === 1 || cs.numComps === 3) &&
|
||||
cs.isDefaultDecode(dict.getArray("Decode", "D"), bpc)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
NativeImageDecoder,
|
||||
};
|
||||
export { NativeImageDecoder };
|
||||
|
1352
src/core/jbig2.js
1352
src/core/jbig2.js
File diff suppressed because it is too large
Load Diff
@ -13,10 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isDict, isStream } from './primitives';
|
||||
import { DecodeStream } from './stream';
|
||||
import { Jbig2Image } from './jbig2';
|
||||
import { shadow } from '../shared/util';
|
||||
import { isDict, isStream } from "./primitives";
|
||||
import { DecodeStream } from "./stream";
|
||||
import { Jbig2Image } from "./jbig2";
|
||||
import { shadow } from "../shared/util";
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
Object.defineProperty(Jbig2Stream.prototype, 'bytes', {
|
||||
Object.defineProperty(Jbig2Stream.prototype, "bytes", {
|
||||
get() {
|
||||
// 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,
|
||||
});
|
||||
@ -55,19 +55,19 @@ let Jbig2Stream = (function Jbig2StreamClosure() {
|
||||
|
||||
let chunks = [];
|
||||
if (isDict(this.params)) {
|
||||
let globalsStream = this.params.get('JBIG2Globals');
|
||||
let globalsStream = this.params.get("JBIG2Globals");
|
||||
if (isStream(globalsStream)) {
|
||||
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 dataLength = data.length;
|
||||
|
||||
// JBIG2 had black as 1 and white as 0, inverting the colors
|
||||
for (let i = 0; i < dataLength; i++) {
|
||||
data[i] ^= 0xFF;
|
||||
data[i] ^= 0xff;
|
||||
}
|
||||
this.buffer = data;
|
||||
this.bufferLength = dataLength;
|
||||
@ -77,6 +77,4 @@ let Jbig2Stream = (function Jbig2StreamClosure() {
|
||||
return Jbig2Stream;
|
||||
})();
|
||||
|
||||
export {
|
||||
Jbig2Stream,
|
||||
};
|
||||
export { Jbig2Stream };
|
||||
|
@ -13,10 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createObjectURL, shadow } from '../shared/util';
|
||||
import { DecodeStream } from './stream';
|
||||
import { isDict } from './primitives';
|
||||
import { JpegImage } from './jpg';
|
||||
import { createObjectURL, shadow } from "../shared/util";
|
||||
import { DecodeStream } from "./stream";
|
||||
import { isDict } from "./primitives";
|
||||
import { JpegImage } from "./jpg";
|
||||
|
||||
/**
|
||||
* 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.
|
||||
let ch;
|
||||
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.
|
||||
break;
|
||||
}
|
||||
@ -46,10 +47,10 @@ let JpegStream = (function JpegStreamClosure() {
|
||||
|
||||
JpegStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
Object.defineProperty(JpegStream.prototype, 'bytes', {
|
||||
Object.defineProperty(JpegStream.prototype, "bytes", {
|
||||
get: function JpegStream_bytes() {
|
||||
// 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,
|
||||
});
|
||||
@ -69,9 +70,9 @@ let JpegStream = (function JpegStreamClosure() {
|
||||
};
|
||||
|
||||
// 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)) {
|
||||
let bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
|
||||
let bitsPerComponent = this.dict.get("BitsPerComponent") || 8;
|
||||
let decodeArrLength = decodeArr.length;
|
||||
let transform = new Int32Array(decodeArrLength);
|
||||
let transformNeeded = false;
|
||||
@ -89,7 +90,7 @@ let JpegStream = (function JpegStreamClosure() {
|
||||
}
|
||||
// Fetching the 'ColorTransform' entry, if it exists.
|
||||
if (isDict(this.params)) {
|
||||
let colorTransform = this.params.get('ColorTransform');
|
||||
let colorTransform = this.params.get("ColorTransform");
|
||||
if (Number.isInteger(colorTransform)) {
|
||||
jpegOptions.colorTransform = colorTransform;
|
||||
}
|
||||
@ -109,12 +110,10 @@ let JpegStream = (function JpegStreamClosure() {
|
||||
};
|
||||
|
||||
JpegStream.prototype.getIR = function(forceDataSchema = false) {
|
||||
return createObjectURL(this.bytes, 'image/jpeg', forceDataSchema);
|
||||
return createObjectURL(this.bytes, "image/jpeg", forceDataSchema);
|
||||
};
|
||||
|
||||
return JpegStream;
|
||||
})();
|
||||
|
||||
export {
|
||||
JpegStream,
|
||||
};
|
||||
export { JpegStream };
|
||||
|
490
src/core/jpg.js
490
src/core/jpg.js
@ -14,7 +14,7 @@
|
||||
*/
|
||||
/* eslint-disable no-multi-spaces */
|
||||
|
||||
import { assert, BaseException, warn } from '../shared/util';
|
||||
import { assert, BaseException, warn } from "../shared/util";
|
||||
|
||||
class JpegError extends BaseException {
|
||||
constructor(msg) {
|
||||
@ -29,7 +29,7 @@ class DNLMarkerError extends BaseException {
|
||||
}
|
||||
}
|
||||
|
||||
class EOIMarkerError extends BaseException { }
|
||||
class EOIMarkerError extends BaseException {}
|
||||
|
||||
/**
|
||||
* This code was forked from https://github.com/notmasteryet/jpgjs.
|
||||
@ -73,18 +73,23 @@ var JpegImage = (function JpegImageClosure() {
|
||||
var dctSqrt2 = 5793; // sqrt(2)
|
||||
var dctSqrt1d2 = 2896; // sqrt(2) / 2
|
||||
|
||||
function JpegImage({ decodeTransform = null, colorTransform = -1, } = {}) {
|
||||
function JpegImage({ decodeTransform = null, colorTransform = -1 } = {}) {
|
||||
this._decodeTransform = decodeTransform;
|
||||
this._colorTransform = colorTransform;
|
||||
}
|
||||
|
||||
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]) {
|
||||
length--;
|
||||
}
|
||||
code.push({ children: [], index: 0, });
|
||||
var p = code[0], q;
|
||||
code.push({ children: [], index: 0 });
|
||||
var p = code[0],
|
||||
q;
|
||||
for (i = 0; i < length; i++) {
|
||||
for (j = 0; j < codeLengths[i]; j++) {
|
||||
p = code.pop();
|
||||
@ -95,7 +100,7 @@ var JpegImage = (function JpegImageClosure() {
|
||||
p.index++;
|
||||
code.push(p);
|
||||
while (code.length <= i) {
|
||||
code.push(q = { children: [], index: 0, });
|
||||
code.push((q = { children: [], index: 0 }));
|
||||
p.children[p.index] = q.children;
|
||||
p = q;
|
||||
}
|
||||
@ -103,7 +108,7 @@ var JpegImage = (function JpegImageClosure() {
|
||||
}
|
||||
if (i + 1 < length) {
|
||||
// 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 = q;
|
||||
}
|
||||
@ -115,13 +120,24 @@ var JpegImage = (function JpegImageClosure() {
|
||||
return 64 * ((component.blocksPerLine + 1) * row + col);
|
||||
}
|
||||
|
||||
function decodeScan(data, offset, frame, components, resetInterval,
|
||||
spectralStart, spectralEnd, successivePrev, successive,
|
||||
parseDNLMarker = false) {
|
||||
function decodeScan(
|
||||
data,
|
||||
offset,
|
||||
frame,
|
||||
components,
|
||||
resetInterval,
|
||||
spectralStart,
|
||||
spectralEnd,
|
||||
successivePrev,
|
||||
successive,
|
||||
parseDNLMarker = false
|
||||
) {
|
||||
var mcusPerLine = frame.mcusPerLine;
|
||||
var progressive = frame.progressive;
|
||||
|
||||
var startOffset = offset, bitsData = 0, bitsCount = 0;
|
||||
var startOffset = offset,
|
||||
bitsData = 0,
|
||||
bitsCount = 0;
|
||||
|
||||
function readBit() {
|
||||
if (bitsCount > 0) {
|
||||
@ -129,22 +145,28 @@ var JpegImage = (function JpegImageClosure() {
|
||||
return (bitsData >> bitsCount) & 1;
|
||||
}
|
||||
bitsData = data[offset++];
|
||||
if (bitsData === 0xFF) {
|
||||
if (bitsData === 0xff) {
|
||||
var nextByte = data[offset++];
|
||||
if (nextByte) {
|
||||
if (nextByte === 0xDC && parseDNLMarker) { // DNL == 0xFFDC
|
||||
if (nextByte === 0xdc && parseDNLMarker) {
|
||||
// DNL == 0xFFDC
|
||||
offset += 2; // Skip data length.
|
||||
const scanLines = (data[offset++] << 8) | data[offset++];
|
||||
if (scanLines > 0 && scanLines !== frame.scanLines) {
|
||||
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(
|
||||
'Found EOI marker (0xFFD9) while parsing scan data');
|
||||
"Found EOI marker (0xFFD9) while parsing scan data"
|
||||
);
|
||||
}
|
||||
throw new JpegError(
|
||||
`unexpected marker ${((bitsData << 8) | nextByte).toString(16)}`);
|
||||
`unexpected marker ${((bitsData << 8) | nextByte).toString(16)}`
|
||||
);
|
||||
}
|
||||
// unstuff 0
|
||||
}
|
||||
@ -156,11 +178,11 @@ var JpegImage = (function JpegImageClosure() {
|
||||
var node = tree;
|
||||
while (true) {
|
||||
node = node[readBit()];
|
||||
if (typeof node === 'number') {
|
||||
if (typeof node === "number") {
|
||||
return node;
|
||||
}
|
||||
if (typeof node !== 'object') {
|
||||
throw new JpegError('invalid huffman sequence');
|
||||
if (typeof node !== "object") {
|
||||
throw new JpegError("invalid huffman sequence");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -188,11 +210,12 @@ var JpegImage = (function JpegImageClosure() {
|
||||
function decodeBaseline(component, offset) {
|
||||
var t = decodeHuffman(component.huffmanTableDC);
|
||||
var diff = t === 0 ? 0 : receiveAndExtend(t);
|
||||
component.blockData[offset] = (component.pred += diff);
|
||||
component.blockData[offset] = component.pred += diff;
|
||||
var k = 1;
|
||||
while (k < 64) {
|
||||
var rs = decodeHuffman(component.huffmanTableAC);
|
||||
var s = rs & 15, r = rs >> 4;
|
||||
var s = rs & 15,
|
||||
r = rs >> 4;
|
||||
if (s === 0) {
|
||||
if (r < 15) {
|
||||
break;
|
||||
@ -209,8 +232,8 @@ var JpegImage = (function JpegImageClosure() {
|
||||
|
||||
function decodeDCFirst(component, offset) {
|
||||
var t = decodeHuffman(component.huffmanTableDC);
|
||||
var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive);
|
||||
component.blockData[offset] = (component.pred += diff);
|
||||
var diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
|
||||
component.blockData[offset] = component.pred += diff;
|
||||
}
|
||||
|
||||
function decodeDCSuccessive(component, offset) {
|
||||
@ -223,10 +246,12 @@ var JpegImage = (function JpegImageClosure() {
|
||||
eobrun--;
|
||||
return;
|
||||
}
|
||||
var k = spectralStart, e = spectralEnd;
|
||||
var k = spectralStart,
|
||||
e = spectralEnd;
|
||||
while (k <= e) {
|
||||
var rs = decodeHuffman(component.huffmanTableAC);
|
||||
var s = rs & 15, r = rs >> 4;
|
||||
var s = rs & 15,
|
||||
r = rs >> 4;
|
||||
if (s === 0) {
|
||||
if (r < 15) {
|
||||
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) {
|
||||
var k = spectralStart;
|
||||
var e = spectralEnd;
|
||||
@ -268,7 +294,7 @@ var JpegImage = (function JpegImageClosure() {
|
||||
}
|
||||
} else {
|
||||
if (s !== 1) {
|
||||
throw new JpegError('invalid ACn encoding');
|
||||
throw new JpegError("invalid ACn encoding");
|
||||
}
|
||||
successiveACNextValue = receiveAndExtend(s);
|
||||
successiveACState = r ? 2 : 3;
|
||||
@ -339,7 +365,8 @@ var JpegImage = (function JpegImageClosure() {
|
||||
decodeFn = decodeBaseline;
|
||||
}
|
||||
|
||||
var mcu = 0, fileMarker;
|
||||
var mcu = 0,
|
||||
fileMarker;
|
||||
var mcuExpected;
|
||||
if (componentsLength === 1) {
|
||||
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
|
||||
@ -350,8 +377,9 @@ var JpegImage = (function JpegImageClosure() {
|
||||
var h, v;
|
||||
while (mcu < mcuExpected) {
|
||||
// reset interval stuff
|
||||
var mcuToRead = resetInterval ?
|
||||
Math.min(mcuExpected - mcu, resetInterval) : mcuExpected;
|
||||
var mcuToRead = resetInterval
|
||||
? Math.min(mcuExpected - mcu, resetInterval)
|
||||
: mcuExpected;
|
||||
for (i = 0; i < componentsLength; i++) {
|
||||
components[i].pred = 0;
|
||||
}
|
||||
@ -388,16 +416,19 @@ var JpegImage = (function JpegImageClosure() {
|
||||
} else if (fileMarker.invalid) {
|
||||
// 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).
|
||||
warn('decodeScan - unexpected MCU data, current marker is: ' +
|
||||
fileMarker.invalid);
|
||||
warn(
|
||||
"decodeScan - unexpected MCU data, current marker is: " +
|
||||
fileMarker.invalid
|
||||
);
|
||||
offset = fileMarker.offset;
|
||||
}
|
||||
var marker = fileMarker && fileMarker.marker;
|
||||
if (!marker || marker <= 0xFF00) {
|
||||
throw new JpegError('decodeScan - a valid marker was not found.');
|
||||
if (!marker || marker <= 0xff00) {
|
||||
throw new JpegError("decodeScan - a valid marker was not found.");
|
||||
}
|
||||
|
||||
if (marker >= 0xFFD0 && marker <= 0xFFD7) { // RSTx
|
||||
if (marker >= 0xffd0 && marker <= 0xffd7) {
|
||||
// RSTx
|
||||
offset += 2;
|
||||
} else {
|
||||
break;
|
||||
@ -408,8 +439,10 @@ var JpegImage = (function JpegImageClosure() {
|
||||
// Some images include more Scan blocks than expected, skip past those and
|
||||
// attempt to find the next valid marker (fixes issue8182.pdf).
|
||||
if (fileMarker && fileMarker.invalid) {
|
||||
warn('decodeScan - unexpected Scan data, current marker is: ' +
|
||||
fileMarker.invalid);
|
||||
warn(
|
||||
"decodeScan - unexpected Scan data, current marker is: " +
|
||||
fileMarker.invalid
|
||||
);
|
||||
offset = fileMarker.offset;
|
||||
}
|
||||
|
||||
@ -422,13 +455,14 @@ var JpegImage = (function JpegImageClosure() {
|
||||
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
|
||||
// 988-991.
|
||||
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 p0, p1, p2, p3, p4, p5, p6, p7;
|
||||
var t;
|
||||
|
||||
if (!qt) {
|
||||
throw new JpegError('missing required Quantization Table.');
|
||||
throw new JpegError("missing required Quantization Table.");
|
||||
}
|
||||
|
||||
// inverse DCT on rows
|
||||
@ -527,7 +561,7 @@ var JpegImage = (function JpegImageClosure() {
|
||||
if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
|
||||
t = (dctSqrt2 * p0 + 8192) >> 14;
|
||||
// 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 + 8] = t;
|
||||
blockData[blockBufferOffset + col + 16] = t;
|
||||
@ -585,14 +619,14 @@ var JpegImage = (function JpegImageClosure() {
|
||||
p4 = v3 - v4;
|
||||
|
||||
// convert to 8-bit integers
|
||||
p0 = (p0 < 16) ? 0 : (p0 >= 4080) ? 255 : p0 >> 4;
|
||||
p1 = (p1 < 16) ? 0 : (p1 >= 4080) ? 255 : p1 >> 4;
|
||||
p2 = (p2 < 16) ? 0 : (p2 >= 4080) ? 255 : p2 >> 4;
|
||||
p3 = (p3 < 16) ? 0 : (p3 >= 4080) ? 255 : p3 >> 4;
|
||||
p4 = (p4 < 16) ? 0 : (p4 >= 4080) ? 255 : p4 >> 4;
|
||||
p5 = (p5 < 16) ? 0 : (p5 >= 4080) ? 255 : p5 >> 4;
|
||||
p6 = (p6 < 16) ? 0 : (p6 >= 4080) ? 255 : p6 >> 4;
|
||||
p7 = (p7 < 16) ? 0 : (p7 >= 4080) ? 255 : p7 >> 4;
|
||||
p0 = p0 < 16 ? 0 : p0 >= 4080 ? 255 : p0 >> 4;
|
||||
p1 = p1 < 16 ? 0 : p1 >= 4080 ? 255 : p1 >> 4;
|
||||
p2 = p2 < 16 ? 0 : p2 >= 4080 ? 255 : p2 >> 4;
|
||||
p3 = p3 < 16 ? 0 : p3 >= 4080 ? 255 : p3 >> 4;
|
||||
p4 = p4 < 16 ? 0 : p4 >= 4080 ? 255 : p4 >> 4;
|
||||
p5 = p5 < 16 ? 0 : p5 >= 4080 ? 255 : p5 >> 4;
|
||||
p6 = p6 < 16 ? 0 : p6 >= 4080 ? 255 : p6 >> 4;
|
||||
p7 = p7 < 16 ? 0 : p7 >= 4080 ? 255 : p7 >> 4;
|
||||
|
||||
// store block data
|
||||
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.
|
||||
}
|
||||
var currentMarker = peekUint16(currentPos);
|
||||
if (currentMarker >= 0xFFC0 && currentMarker <= 0xFFFE) {
|
||||
if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) {
|
||||
return {
|
||||
invalid: null,
|
||||
marker: currentMarker,
|
||||
@ -640,7 +674,7 @@ var JpegImage = (function JpegImageClosure() {
|
||||
};
|
||||
}
|
||||
var newMarker = peekUint16(newPos);
|
||||
while (!(newMarker >= 0xFFC0 && newMarker <= 0xFFFE)) {
|
||||
while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) {
|
||||
if (++newPos >= maxPos) {
|
||||
return null; // Don't attempt to read non-existent data and just return.
|
||||
}
|
||||
@ -654,8 +688,7 @@ var JpegImage = (function JpegImageClosure() {
|
||||
}
|
||||
|
||||
JpegImage.prototype = {
|
||||
parse(data, { dnlScanLines = null, } = {}) {
|
||||
|
||||
parse(data, { dnlScanLines = null } = {}) {
|
||||
function readUint16() {
|
||||
var value = (data[offset] << 8) | data[offset + 1];
|
||||
offset += 2;
|
||||
@ -668,8 +701,10 @@ var JpegImage = (function JpegImageClosure() {
|
||||
|
||||
var fileMarker = findNextFileMarker(data, endOffset, offset);
|
||||
if (fileMarker && fileMarker.invalid) {
|
||||
warn('readDataBlock - incorrect length, current marker is: ' +
|
||||
fileMarker.invalid);
|
||||
warn(
|
||||
"readDataBlock - incorrect length, current marker is: " +
|
||||
fileMarker.invalid
|
||||
);
|
||||
endOffset = fileMarker.offset;
|
||||
}
|
||||
|
||||
@ -683,15 +718,17 @@ var JpegImage = (function JpegImageClosure() {
|
||||
var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
|
||||
for (var i = 0; i < frame.components.length; i++) {
|
||||
component = frame.components[i];
|
||||
var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) *
|
||||
component.h / frame.maxH);
|
||||
var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) *
|
||||
component.v / frame.maxV);
|
||||
var blocksPerLine = Math.ceil(
|
||||
(Math.ceil(frame.samplesPerLine / 8) * component.h) / frame.maxH
|
||||
);
|
||||
var blocksPerColumn = Math.ceil(
|
||||
(Math.ceil(frame.scanLines / 8) * component.v) / frame.maxV
|
||||
);
|
||||
var blocksPerLineForMcu = mcusPerLine * component.h;
|
||||
var blocksPerColumnForMcu = mcusPerColumn * component.v;
|
||||
|
||||
var blocksBufferSize = 64 * blocksPerColumnForMcu *
|
||||
(blocksPerLineForMcu + 1);
|
||||
var blocksBufferSize =
|
||||
64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
|
||||
component.blockData = new Int16Array(blocksBufferSize);
|
||||
component.blocksPerLine = blocksPerLine;
|
||||
component.blocksPerColumn = blocksPerColumn;
|
||||
@ -706,56 +743,71 @@ var JpegImage = (function JpegImageClosure() {
|
||||
var frame, resetInterval;
|
||||
let numSOSMarkers = 0;
|
||||
var quantizationTables = [];
|
||||
var huffmanTablesAC = [], huffmanTablesDC = [];
|
||||
var huffmanTablesAC = [],
|
||||
huffmanTablesDC = [];
|
||||
var fileMarker = readUint16();
|
||||
if (fileMarker !== 0xFFD8) { // SOI (Start of Image)
|
||||
throw new JpegError('SOI not found');
|
||||
if (fileMarker !== 0xffd8) {
|
||||
// SOI (Start of Image)
|
||||
throw new JpegError("SOI not found");
|
||||
}
|
||||
|
||||
fileMarker = readUint16();
|
||||
markerLoop: while (fileMarker !== 0xFFD9) { // EOI (End of image)
|
||||
markerLoop: while (fileMarker !== 0xffd9) {
|
||||
// EOI (End of image)
|
||||
var i, j, l;
|
||||
switch (fileMarker) {
|
||||
case 0xFFE0: // APP0 (Application Specific)
|
||||
case 0xFFE1: // APP1
|
||||
case 0xFFE2: // APP2
|
||||
case 0xFFE3: // APP3
|
||||
case 0xFFE4: // APP4
|
||||
case 0xFFE5: // APP5
|
||||
case 0xFFE6: // APP6
|
||||
case 0xFFE7: // APP7
|
||||
case 0xFFE8: // APP8
|
||||
case 0xFFE9: // APP9
|
||||
case 0xFFEA: // APP10
|
||||
case 0xFFEB: // APP11
|
||||
case 0xFFEC: // APP12
|
||||
case 0xFFED: // APP13
|
||||
case 0xFFEE: // APP14
|
||||
case 0xFFEF: // APP15
|
||||
case 0xFFFE: // COM (Comment)
|
||||
case 0xffe0: // APP0 (Application Specific)
|
||||
case 0xffe1: // APP1
|
||||
case 0xffe2: // APP2
|
||||
case 0xffe3: // APP3
|
||||
case 0xffe4: // APP4
|
||||
case 0xffe5: // APP5
|
||||
case 0xffe6: // APP6
|
||||
case 0xffe7: // APP7
|
||||
case 0xffe8: // APP8
|
||||
case 0xffe9: // APP9
|
||||
case 0xffea: // APP10
|
||||
case 0xffeb: // APP11
|
||||
case 0xffec: // APP12
|
||||
case 0xffed: // APP13
|
||||
case 0xffee: // APP14
|
||||
case 0xffef: // APP15
|
||||
case 0xfffe: // COM (Comment)
|
||||
var appData = readDataBlock();
|
||||
|
||||
if (fileMarker === 0xFFE0) {
|
||||
if (appData[0] === 0x4A && appData[1] === 0x46 &&
|
||||
appData[2] === 0x49 && appData[3] === 0x46 &&
|
||||
appData[4] === 0) { // 'JFIF\x00'
|
||||
if (fileMarker === 0xffe0) {
|
||||
if (
|
||||
appData[0] === 0x4a &&
|
||||
appData[1] === 0x46 &&
|
||||
appData[2] === 0x49 &&
|
||||
appData[3] === 0x46 &&
|
||||
appData[4] === 0
|
||||
) {
|
||||
// 'JFIF\x00'
|
||||
jfif = {
|
||||
version: { major: appData[5], minor: appData[6], },
|
||||
version: { major: appData[5], minor: appData[6] },
|
||||
densityUnits: appData[7],
|
||||
xDensity: (appData[8] << 8) | appData[9],
|
||||
yDensity: (appData[10] << 8) | appData[11],
|
||||
thumbWidth: appData[12],
|
||||
thumbHeight: appData[13],
|
||||
thumbData: appData.subarray(14, 14 +
|
||||
3 * appData[12] * appData[13]),
|
||||
thumbData: appData.subarray(
|
||||
14,
|
||||
14 + 3 * appData[12] * appData[13]
|
||||
),
|
||||
};
|
||||
}
|
||||
}
|
||||
// TODO APP1 - Exif
|
||||
if (fileMarker === 0xFFEE) {
|
||||
if (appData[0] === 0x41 && appData[1] === 0x64 &&
|
||||
appData[2] === 0x6F && appData[3] === 0x62 &&
|
||||
appData[4] === 0x65) { // 'Adobe'
|
||||
if (fileMarker === 0xffee) {
|
||||
if (
|
||||
appData[0] === 0x41 &&
|
||||
appData[1] === 0x64 &&
|
||||
appData[2] === 0x6f &&
|
||||
appData[3] === 0x62 &&
|
||||
appData[4] === 0x65
|
||||
) {
|
||||
// 'Adobe'
|
||||
adobe = {
|
||||
version: (appData[5] << 8) | appData[6],
|
||||
flags0: (appData[7] << 8) | appData[8],
|
||||
@ -766,48 +818,52 @@ var JpegImage = (function JpegImageClosure() {
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFFDB: // DQT (Define Quantization Tables)
|
||||
case 0xffdb: // DQT (Define Quantization Tables)
|
||||
var quantizationTablesLength = readUint16();
|
||||
var quantizationTablesEnd = quantizationTablesLength + offset - 2;
|
||||
var z;
|
||||
while (offset < quantizationTablesEnd) {
|
||||
var quantizationTableSpec = data[offset++];
|
||||
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++) {
|
||||
z = dctZigZag[j];
|
||||
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++) {
|
||||
z = dctZigZag[j];
|
||||
tableData[z] = readUint16();
|
||||
}
|
||||
} else {
|
||||
throw new JpegError('DQT - invalid table spec');
|
||||
throw new JpegError("DQT - invalid table spec");
|
||||
}
|
||||
quantizationTables[quantizationTableSpec & 15] = tableData;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFFC0: // SOF0 (Start of Frame, Baseline DCT)
|
||||
case 0xFFC1: // SOF1 (Start of Frame, Extended DCT)
|
||||
case 0xFFC2: // SOF2 (Start of Frame, Progressive DCT)
|
||||
case 0xffc0: // SOF0 (Start of Frame, Baseline DCT)
|
||||
case 0xffc1: // SOF1 (Start of Frame, Extended DCT)
|
||||
case 0xffc2: // SOF2 (Start of Frame, Progressive DCT)
|
||||
if (frame) {
|
||||
throw new JpegError('Only single frame JPEGs supported');
|
||||
throw new JpegError("Only single frame JPEGs supported");
|
||||
}
|
||||
readUint16(); // skip data length
|
||||
frame = {};
|
||||
frame.extended = (fileMarker === 0xFFC1);
|
||||
frame.progressive = (fileMarker === 0xFFC2);
|
||||
frame.extended = fileMarker === 0xffc1;
|
||||
frame.progressive = fileMarker === 0xffc2;
|
||||
frame.precision = data[offset++];
|
||||
const sofScanLines = readUint16();
|
||||
frame.scanLines = dnlScanLines || sofScanLines;
|
||||
frame.samplesPerLine = readUint16();
|
||||
frame.components = [];
|
||||
frame.componentIds = {};
|
||||
var componentsCount = data[offset++], componentId;
|
||||
var maxH = 0, maxV = 0;
|
||||
var componentsCount = data[offset++],
|
||||
componentId;
|
||||
var maxH = 0,
|
||||
maxV = 0;
|
||||
for (i = 0; i < componentsCount; i++) {
|
||||
componentId = data[offset];
|
||||
var h = data[offset + 1] >> 4;
|
||||
@ -833,14 +889,14 @@ var JpegImage = (function JpegImageClosure() {
|
||||
prepareComponents(frame);
|
||||
break;
|
||||
|
||||
case 0xFFC4: // DHT (Define Huffman Tables)
|
||||
case 0xffc4: // DHT (Define Huffman Tables)
|
||||
var huffmanLength = readUint16();
|
||||
for (i = 2; i < huffmanLength;) {
|
||||
for (i = 2; i < huffmanLength; ) {
|
||||
var huffmanTableSpec = data[offset++];
|
||||
var codeLengths = new Uint8Array(16);
|
||||
var codeLengthSum = 0;
|
||||
for (j = 0; j < 16; j++, offset++) {
|
||||
codeLengthSum += (codeLengths[j] = data[offset]);
|
||||
codeLengthSum += codeLengths[j] = data[offset];
|
||||
}
|
||||
var huffmanValues = new Uint8Array(codeLengthSum);
|
||||
for (j = 0; j < codeLengthSum; j++, offset++) {
|
||||
@ -848,27 +904,28 @@ var JpegImage = (function JpegImageClosure() {
|
||||
}
|
||||
i += 17 + codeLengthSum;
|
||||
|
||||
((huffmanTableSpec >> 4) === 0 ?
|
||||
huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] =
|
||||
buildHuffmanTable(codeLengths, huffmanValues);
|
||||
(huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[
|
||||
huffmanTableSpec & 15
|
||||
] = buildHuffmanTable(codeLengths, huffmanValues);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xFFDD: // DRI (Define Restart Interval)
|
||||
case 0xffdd: // DRI (Define Restart Interval)
|
||||
readUint16(); // skip data length
|
||||
resetInterval = readUint16();
|
||||
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
|
||||
// of the first scan segment and may only occur once in an image.
|
||||
// Furthermore, to prevent an infinite loop, do *not* attempt to
|
||||
// parse DNL markers during re-parsing of the JPEG scan data.
|
||||
const parseDNLMarker = (++numSOSMarkers) === 1 && !dnlScanLines;
|
||||
const parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines;
|
||||
|
||||
readUint16(); // scanLength
|
||||
var selectorsCount = data[offset++];
|
||||
var components = [], component;
|
||||
var components = [],
|
||||
component;
|
||||
for (i = 0; i < selectorsCount; i++) {
|
||||
var componentIndex = frame.componentIds[data[offset++]];
|
||||
component = frame.components[componentIndex];
|
||||
@ -881,16 +938,23 @@ var JpegImage = (function JpegImageClosure() {
|
||||
var spectralEnd = data[offset++];
|
||||
var successiveApproximation = data[offset++];
|
||||
try {
|
||||
var processed = decodeScan(data, offset,
|
||||
frame, components, resetInterval,
|
||||
spectralStart, spectralEnd,
|
||||
successiveApproximation >> 4, successiveApproximation & 15,
|
||||
parseDNLMarker);
|
||||
var processed = decodeScan(
|
||||
data,
|
||||
offset,
|
||||
frame,
|
||||
components,
|
||||
resetInterval,
|
||||
spectralStart,
|
||||
spectralEnd,
|
||||
successiveApproximation >> 4,
|
||||
successiveApproximation & 15,
|
||||
parseDNLMarker
|
||||
);
|
||||
offset += processed;
|
||||
} catch (ex) {
|
||||
if (ex instanceof DNLMarkerError) {
|
||||
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) {
|
||||
warn(`${ex.message} -- ignoring the rest of the image data.`);
|
||||
break markerLoop;
|
||||
@ -899,20 +963,24 @@ var JpegImage = (function JpegImageClosure() {
|
||||
}
|
||||
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`.
|
||||
offset += 4;
|
||||
break;
|
||||
|
||||
case 0xFFFF: // Fill bytes
|
||||
if (data[offset] !== 0xFF) { // Avoid skipping a valid marker.
|
||||
case 0xffff: // Fill bytes
|
||||
if (data[offset] !== 0xff) {
|
||||
// Avoid skipping a valid marker.
|
||||
offset--;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (data[offset - 3] === 0xFF &&
|
||||
data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
|
||||
if (
|
||||
data[offset - 3] === 0xff &&
|
||||
data[offset - 2] >= 0xc0 &&
|
||||
data[offset - 2] <= 0xfe
|
||||
) {
|
||||
// could be incorrect encoding -- last 0xFF byte of the previous
|
||||
// block was eaten by the encoder
|
||||
offset -= 3;
|
||||
@ -920,18 +988,23 @@ var JpegImage = (function JpegImageClosure() {
|
||||
}
|
||||
let nextFileMarker = findNextFileMarker(data, offset - 2);
|
||||
if (nextFileMarker && nextFileMarker.invalid) {
|
||||
warn('JpegImage.parse - unexpected data, current marker is: ' +
|
||||
nextFileMarker.invalid);
|
||||
warn(
|
||||
"JpegImage.parse - unexpected data, current marker is: " +
|
||||
nextFileMarker.invalid
|
||||
);
|
||||
offset = nextFileMarker.offset;
|
||||
break;
|
||||
}
|
||||
if (offset > (data.length - 2)) {
|
||||
warn('JpegImage.parse - reached the end of the image data ' +
|
||||
'without finding an EOI marker (0xFFD9).');
|
||||
if (offset > data.length - 2) {
|
||||
warn(
|
||||
"JpegImage.parse - reached the end of the image data " +
|
||||
"without finding an EOI marker (0xFFD9)."
|
||||
);
|
||||
break markerLoop;
|
||||
}
|
||||
throw new JpegError('JpegImage.parse - unknown marker: ' +
|
||||
fileMarker.toString(16));
|
||||
throw new JpegError(
|
||||
"JpegImage.parse - unknown marker: " + fileMarker.toString(16)
|
||||
);
|
||||
}
|
||||
fileMarker = readUint16();
|
||||
}
|
||||
@ -965,7 +1038,8 @@ var JpegImage = (function JpegImageClosure() {
|
||||
},
|
||||
|
||||
_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 x, y, i, j, k;
|
||||
@ -993,7 +1067,7 @@ var JpegImage = (function JpegImageClosure() {
|
||||
// linearize the blocks of the component
|
||||
for (y = 0; y < height; y++) {
|
||||
j = 0 | (y * componentScaleY);
|
||||
index = blocksPerScanline * (j & mask3LSB) | ((j & 7) << 3);
|
||||
index = (blocksPerScanline * (j & mask3LSB)) | ((j & 7) << 3);
|
||||
for (x = 0; x < width; x++) {
|
||||
data[offset] = output[index + xScaleBlockOffset[x]];
|
||||
offset += numComponents;
|
||||
@ -1022,7 +1096,7 @@ var JpegImage = (function JpegImageClosure() {
|
||||
}
|
||||
|
||||
if (transform) {
|
||||
for (i = 0; i < dataLength;) {
|
||||
for (i = 0; i < dataLength; ) {
|
||||
for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) {
|
||||
data[i] = ((data[i] * transform[k]) >> 8) + transform[k + 1];
|
||||
}
|
||||
@ -1077,33 +1151,60 @@ var JpegImage = (function JpegImageClosure() {
|
||||
Cr = data[i + 2];
|
||||
k = data[i + 3];
|
||||
|
||||
data[offset++] = -122.67195406894 +
|
||||
Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr -
|
||||
5.4080610064599e-5 * Y + 0.00048449797120281 * k -
|
||||
data[offset++] =
|
||||
-122.67195406894 +
|
||||
Cb *
|
||||
(-6.60635669420364e-5 * Cb +
|
||||
0.000437130475926232 * Cr -
|
||||
5.4080610064599e-5 * Y +
|
||||
0.00048449797120281 * k -
|
||||
0.154362151871126) +
|
||||
Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y -
|
||||
0.00477271405408747 * k + 1.53380253221734) +
|
||||
Y * (0.000961250184130688 * Y - 0.00266257332283933 * k +
|
||||
Cr *
|
||||
(-0.000957964378445773 * Cr +
|
||||
0.000817076911346625 * Y -
|
||||
0.00477271405408747 * k +
|
||||
1.53380253221734) +
|
||||
Y *
|
||||
(0.000961250184130688 * Y -
|
||||
0.00266257332283933 * k +
|
||||
0.48357088451265) +
|
||||
k * (-0.000336197177618394 * k + 0.484791561490776);
|
||||
|
||||
data[offset++] = 107.268039397724 +
|
||||
Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr +
|
||||
0.000659397001245577 * Y + 0.000426105652938837 * k -
|
||||
data[offset++] =
|
||||
107.268039397724 +
|
||||
Cb *
|
||||
(2.19927104525741e-5 * Cb -
|
||||
0.000640992018297945 * Cr +
|
||||
0.000659397001245577 * Y +
|
||||
0.000426105652938837 * k -
|
||||
0.176491792462875) +
|
||||
Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y +
|
||||
0.000770482631801132 * k - 0.151051492775562) +
|
||||
Y * (0.00126935368114843 * Y - 0.00265090189010898 * k +
|
||||
Cr *
|
||||
(-0.000778269941513683 * Cr +
|
||||
0.00130872261408275 * Y +
|
||||
0.000770482631801132 * k -
|
||||
0.151051492775562) +
|
||||
Y *
|
||||
(0.00126935368114843 * Y -
|
||||
0.00265090189010898 * k +
|
||||
0.25802910206845) +
|
||||
k * (-0.000318913117588328 * k - 0.213742400323665);
|
||||
|
||||
data[offset++] = -20.810012546947 +
|
||||
Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr +
|
||||
0.0020741088115012 * Y - 0.00288260236853442 * k +
|
||||
data[offset++] =
|
||||
-20.810012546947 +
|
||||
Cb *
|
||||
(-0.000570115196973677 * Cb -
|
||||
2.63409051004589e-5 * Cr +
|
||||
0.0020741088115012 * Y -
|
||||
0.00288260236853442 * k +
|
||||
0.814272968359295) +
|
||||
Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y +
|
||||
0.000560833691242812 * k - 0.195152027534049) +
|
||||
Y * (0.00174418132927582 * Y - 0.00255243321439347 * k +
|
||||
Cr *
|
||||
(-1.53496057440975e-5 * Cr -
|
||||
0.000132689043961446 * Y +
|
||||
0.000560833691242812 * k -
|
||||
0.195152027534049) +
|
||||
Y *
|
||||
(0.00174418132927582 * Y -
|
||||
0.00255243321439347 * k +
|
||||
0.116935020465145) +
|
||||
k * (-0.000343531996510555 * k + 0.24165260232407);
|
||||
}
|
||||
@ -1135,33 +1236,58 @@ var JpegImage = (function JpegImageClosure() {
|
||||
y = data[i + 2] * scale;
|
||||
k = data[i + 3] * scale;
|
||||
|
||||
data[offset++] = 255 +
|
||||
c * (-4.387332384609988 * c + 54.48615194189176 * m +
|
||||
18.82290502165302 * y + 212.25662451639585 * k -
|
||||
data[offset++] =
|
||||
255 +
|
||||
c *
|
||||
(-4.387332384609988 * c +
|
||||
54.48615194189176 * m +
|
||||
18.82290502165302 * y +
|
||||
212.25662451639585 * k -
|
||||
285.2331026137004) +
|
||||
m * (1.7149763477362134 * m - 5.6096736904047315 * y -
|
||||
17.873870861415444 * k - 5.497006427196366) +
|
||||
y * (-2.5217340131683033 * y - 21.248923337353073 * k +
|
||||
m *
|
||||
(1.7149763477362134 * m -
|
||||
5.6096736904047315 * y -
|
||||
17.873870861415444 * k -
|
||||
5.497006427196366) +
|
||||
y *
|
||||
(-2.5217340131683033 * y -
|
||||
21.248923337353073 * k +
|
||||
17.5119270841813) -
|
||||
k * (21.86122147463605 * k + 189.48180835922747);
|
||||
|
||||
data[offset++] = 255 +
|
||||
c * (8.841041422036149 * c + 60.118027045597366 * m +
|
||||
6.871425592049007 * y + 31.159100130055922 * k -
|
||||
data[offset++] =
|
||||
255 +
|
||||
c *
|
||||
(8.841041422036149 * c +
|
||||
60.118027045597366 * m +
|
||||
6.871425592049007 * y +
|
||||
31.159100130055922 * k -
|
||||
79.2970844816548) +
|
||||
m * (-15.310361306967817 * m + 17.575251261109482 * y +
|
||||
131.35250912493976 * k - 190.9453302588951) +
|
||||
y * (4.444339102852739 * y + 9.8632861493405 * k -
|
||||
24.86741582555878) -
|
||||
m *
|
||||
(-15.310361306967817 * m +
|
||||
17.575251261109482 * y +
|
||||
131.35250912493976 * k -
|
||||
190.9453302588951) +
|
||||
y *
|
||||
(4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) -
|
||||
k * (20.737325471181034 * k + 187.80453709719578);
|
||||
|
||||
data[offset++] = 255 +
|
||||
c * (0.8842522430003296 * c + 8.078677503112928 * m +
|
||||
30.89978309703729 * y - 0.23883238689178934 * k -
|
||||
data[offset++] =
|
||||
255 +
|
||||
c *
|
||||
(0.8842522430003296 * c +
|
||||
8.078677503112928 * m +
|
||||
30.89978309703729 * y -
|
||||
0.23883238689178934 * k -
|
||||
14.183576799673286) +
|
||||
m * (10.49593273432072 * m + 63.02378494754052 * y +
|
||||
50.606957656360734 * k - 112.23884253719248) +
|
||||
y * (0.03296041114873217 * y + 115.60384449646641 * k -
|
||||
m *
|
||||
(10.49593273432072 * m +
|
||||
63.02378494754052 * y +
|
||||
50.606957656360734 * k -
|
||||
112.23884253719248) +
|
||||
y *
|
||||
(0.03296041114873217 * y +
|
||||
115.60384449646641 * k -
|
||||
193.58209356861505) -
|
||||
k * (22.33816807309886 * k + 180.12613974708367);
|
||||
}
|
||||
@ -1169,13 +1295,15 @@ var JpegImage = (function JpegImageClosure() {
|
||||
return data.subarray(0, offset);
|
||||
},
|
||||
|
||||
getData({ width, height, forceRGB = false, isSourcePDF = false, }) {
|
||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('TESTING && !LIB')) {
|
||||
assert(isSourcePDF === true,
|
||||
'JpegImage.getData: Unexpected "isSourcePDF" value for PDF files.');
|
||||
getData({ width, height, forceRGB = false, isSourcePDF = false }) {
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING && !LIB")) {
|
||||
assert(
|
||||
isSourcePDF === true,
|
||||
'JpegImage.getData: Unexpected "isSourcePDF" value for PDF files.'
|
||||
);
|
||||
}
|
||||
if (this.numComponents > 4) {
|
||||
throw new JpegError('Unsupported color mode');
|
||||
throw new JpegError("Unsupported color mode");
|
||||
}
|
||||
// Type of data: Uint8ClampedArray(width * height * numComponents)
|
||||
var data = this._getLinearizedBlockData(width, height, isSourcePDF);
|
||||
@ -1210,6 +1338,4 @@ var JpegImage = (function JpegImageClosure() {
|
||||
return JpegImage;
|
||||
})();
|
||||
|
||||
export {
|
||||
JpegImage,
|
||||
};
|
||||
export { JpegImage };
|
||||
|
615
src/core/jpx.js
615
src/core/jpx.js
File diff suppressed because it is too large
Load Diff
@ -13,9 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DecodeStream } from './stream';
|
||||
import { JpxImage } from './jpx';
|
||||
import { shadow } from '../shared/util';
|
||||
import { DecodeStream } from "./stream";
|
||||
import { JpxImage } from "./jpx";
|
||||
import { shadow } from "../shared/util";
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
Object.defineProperty(JpxStream.prototype, 'bytes', {
|
||||
Object.defineProperty(JpxStream.prototype, "bytes", {
|
||||
get: function JpxStream_bytes() {
|
||||
// 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,
|
||||
});
|
||||
@ -91,6 +91,4 @@ let JpxStream = (function JpxStreamClosure() {
|
||||
return JpxStream;
|
||||
})();
|
||||
|
||||
export {
|
||||
JpxStream,
|
||||
};
|
||||
export { JpxStream };
|
||||
|
5860
src/core/metrics.js
5860
src/core/metrics.js
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@
|
||||
*/
|
||||
/* eslint no-var: error */
|
||||
|
||||
import { isArrayBuffer, isString } from '../shared/util';
|
||||
import { isArrayBuffer, isString } from "../shared/util";
|
||||
|
||||
const SEED = 0xc3d2e1f0;
|
||||
// Workaround for missing math precision in JS.
|
||||
@ -49,35 +49,41 @@ class MurmurHash3_64 {
|
||||
data = input;
|
||||
length = data.byteLength;
|
||||
} else {
|
||||
throw new Error('Wrong data format in MurmurHash3_64_update. ' +
|
||||
'Input must be a string or array.');
|
||||
throw new Error(
|
||||
"Wrong data format in MurmurHash3_64_update. " +
|
||||
"Input must be a string or array."
|
||||
);
|
||||
}
|
||||
|
||||
const blockCounts = length >> 2;
|
||||
const tailLength = length - blockCounts * 4;
|
||||
// We don't care about endianness here.
|
||||
const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
|
||||
let k1 = 0, k2 = 0;
|
||||
let h1 = this.h1, h2 = this.h2;
|
||||
const C1 = 0xcc9e2d51, C2 = 0x1b873593;
|
||||
const C1_LOW = C1 & MASK_LOW, C2_LOW = C2 & MASK_LOW;
|
||||
let k1 = 0,
|
||||
k2 = 0;
|
||||
let h1 = this.h1,
|
||||
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++) {
|
||||
if (i & 1) {
|
||||
k1 = dataUint32[i];
|
||||
k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW);
|
||||
k1 = k1 << 15 | k1 >>> 17;
|
||||
k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW);
|
||||
k1 = ((k1 * C1) & MASK_HIGH) | ((k1 * C1_LOW) & MASK_LOW);
|
||||
k1 = (k1 << 15) | (k1 >>> 17);
|
||||
k1 = ((k1 * C2) & MASK_HIGH) | ((k1 * C2_LOW) & MASK_LOW);
|
||||
h1 ^= k1;
|
||||
h1 = h1 << 13 | h1 >>> 19;
|
||||
h1 = (h1 << 13) | (h1 >>> 19);
|
||||
h1 = h1 * 5 + 0xe6546b64;
|
||||
} else {
|
||||
k2 = dataUint32[i];
|
||||
k2 = (k2 * C1 & MASK_HIGH) | (k2 * C1_LOW & MASK_LOW);
|
||||
k2 = k2 << 15 | k2 >>> 17;
|
||||
k2 = (k2 * C2 & MASK_HIGH) | (k2 * C2_LOW & MASK_LOW);
|
||||
k2 = ((k2 * C1) & MASK_HIGH) | ((k2 * C1_LOW) & MASK_LOW);
|
||||
k2 = (k2 << 15) | (k2 >>> 17);
|
||||
k2 = ((k2 * C2) & MASK_HIGH) | ((k2 * C2_LOW) & MASK_LOW);
|
||||
h2 ^= k2;
|
||||
h2 = h2 << 13 | h2 >>> 19;
|
||||
h2 = (h2 << 13) | (h2 >>> 19);
|
||||
h2 = h2 * 5 + 0xe6546b64;
|
||||
}
|
||||
}
|
||||
@ -95,9 +101,9 @@ class MurmurHash3_64 {
|
||||
k1 ^= data[blockCounts * 4];
|
||||
/* falls through */
|
||||
|
||||
k1 = (k1 * C1 & MASK_HIGH) | (k1 * C1_LOW & MASK_LOW);
|
||||
k1 = k1 << 15 | k1 >>> 17;
|
||||
k1 = (k1 * C2 & MASK_HIGH) | (k1 * C2_LOW & MASK_LOW);
|
||||
k1 = ((k1 * C1) & MASK_HIGH) | ((k1 * C1_LOW) & MASK_LOW);
|
||||
k1 = (k1 << 15) | (k1 >>> 17);
|
||||
k1 = ((k1 * C2) & MASK_HIGH) | ((k1 * C2_LOW) & MASK_LOW);
|
||||
if (blockCounts & 1) {
|
||||
h1 ^= k1;
|
||||
} else {
|
||||
@ -110,23 +116,25 @@ class MurmurHash3_64 {
|
||||
}
|
||||
|
||||
hexdigest() {
|
||||
let h1 = this.h1, h2 = this.h2;
|
||||
let h1 = this.h1,
|
||||
h2 = this.h2;
|
||||
|
||||
h1 ^= h2 >>> 1;
|
||||
h1 = (h1 * 0xed558ccd & MASK_HIGH) | (h1 * 0x8ccd & MASK_LOW);
|
||||
h2 = (h2 * 0xff51afd7 & MASK_HIGH) |
|
||||
(((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16);
|
||||
h1 = ((h1 * 0xed558ccd) & MASK_HIGH) | ((h1 * 0x8ccd) & MASK_LOW);
|
||||
h2 =
|
||||
((h2 * 0xff51afd7) & MASK_HIGH) |
|
||||
(((((h2 << 16) | (h1 >>> 16)) * 0xafd7ed55) & MASK_HIGH) >>> 16);
|
||||
h1 ^= h2 >>> 1;
|
||||
h1 = (h1 * 0x1a85ec53 & MASK_HIGH) | (h1 * 0xec53 & MASK_LOW);
|
||||
h2 = (h2 * 0xc4ceb9fe & MASK_HIGH) |
|
||||
(((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16);
|
||||
h1 = ((h1 * 0x1a85ec53) & MASK_HIGH) | ((h1 * 0xec53) & MASK_LOW);
|
||||
h2 =
|
||||
((h2 * 0xc4ceb9fe) & MASK_HIGH) |
|
||||
(((((h2 << 16) | (h1 >>> 16)) * 0xb9fe1a85) & MASK_HIGH) >>> 16);
|
||||
h1 ^= h2 >>> 1;
|
||||
|
||||
const hex1 = (h1 >>> 0).toString(16), hex2 = (h2 >>> 0).toString(16);
|
||||
return hex1.padStart(8, '0') + hex2.padStart(8, '0');
|
||||
const hex1 = (h1 >>> 0).toString(16),
|
||||
hex2 = (h2 >>> 0).toString(16);
|
||||
return hex1.padStart(8, "0") + hex2.padStart(8, "0");
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
MurmurHash3_64,
|
||||
};
|
||||
export { 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 */
|
||||
|
||||
import { assert, ImageKind, OPS } from '../shared/util';
|
||||
import { assert, ImageKind, OPS } from "../shared/util";
|
||||
|
||||
var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
function addState(parentState, pattern, checkFn, iterateFn, processFn) {
|
||||
var state = parentState;
|
||||
for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
|
||||
var item = pattern[i];
|
||||
state = (state[item] || (state[item] = []));
|
||||
state = state[item] || (state[item] = []);
|
||||
}
|
||||
state[pattern[pattern.length - 1]] = {
|
||||
checkFn,
|
||||
@ -30,8 +30,12 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
};
|
||||
}
|
||||
|
||||
function handlePaintSolidColorImageMask(iFirstSave, count, fnArray,
|
||||
argsArray) {
|
||||
function handlePaintSolidColorImageMask(
|
||||
iFirstSave,
|
||||
count,
|
||||
fnArray,
|
||||
argsArray
|
||||
) {
|
||||
// Handles special case of mainly LaTeX documents which use image masks to
|
||||
// draw lines with the current fill style.
|
||||
// 'count' groups of (save, transform, paintImageMaskXObject, restore)+
|
||||
@ -40,9 +44,13 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
for (var i = 0; i < count; i++) {
|
||||
var arg = argsArray[iFirstPIMXO + 4 * i];
|
||||
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 === 1 && imageMask.data[0] === 0))) {
|
||||
(imageMask.data.length === 1 && imageMask.data[0] === 0))
|
||||
) {
|
||||
fnArray[iFirstPIMXO + 4 * i] = OPS.paintSolidColorImageMask;
|
||||
continue;
|
||||
}
|
||||
@ -55,7 +63,8 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
|
||||
// This replaces (save, transform, paintInlineImageXObject, restore)+
|
||||
// sequences with one |paintInlineImageXObjectGroup| operation.
|
||||
addState(InitialState,
|
||||
addState(
|
||||
InitialState,
|
||||
[OPS.save, OPS.transform, OPS.paintInlineImageXObject, OPS.restore],
|
||||
null,
|
||||
function iterateInlineImageGroup(context, i) {
|
||||
@ -80,23 +89,28 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
var MAX_WIDTH = 1000;
|
||||
var IMAGE_PADDING = 1;
|
||||
|
||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
||||
var fnArray = context.fnArray,
|
||||
argsArray = context.argsArray;
|
||||
var curr = context.iCurr;
|
||||
var iFirstSave = curr - 3;
|
||||
var iFirstTransform = curr - 2;
|
||||
var iFirstPIIXO = curr - 1;
|
||||
|
||||
var count = Math.min(Math.floor((i - iFirstSave) / 4),
|
||||
MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
|
||||
var count = Math.min(
|
||||
Math.floor((i - iFirstSave) / 4),
|
||||
MAX_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)
|
||||
// packing as much as possible by lines
|
||||
var maxX = 0;
|
||||
var map = [], maxLineHeight = 0;
|
||||
var currentX = IMAGE_PADDING, currentY = IMAGE_PADDING;
|
||||
var map = [],
|
||||
maxLineHeight = 0;
|
||||
var currentX = IMAGE_PADDING,
|
||||
currentY = IMAGE_PADDING;
|
||||
var q;
|
||||
for (q = 0; q < count; q++) {
|
||||
var transform = argsArray[iFirstTransform + (q << 2)];
|
||||
@ -110,8 +124,10 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
}
|
||||
map.push({
|
||||
transform,
|
||||
x: currentX, y: currentY,
|
||||
w: img.width, h: img.height,
|
||||
x: currentX,
|
||||
y: currentY,
|
||||
w: img.width,
|
||||
h: img.height,
|
||||
});
|
||||
currentX += img.width + 2 * IMAGE_PADDING;
|
||||
maxLineHeight = Math.max(maxLineHeight, img.height);
|
||||
@ -148,17 +164,25 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
|
||||
// Replace queue items.
|
||||
fnArray.splice(iFirstSave, count * 4, OPS.paintInlineImageXObjectGroup);
|
||||
argsArray.splice(iFirstSave, count * 4,
|
||||
[{ width: imgWidth, height: imgHeight, kind: ImageKind.RGBA_32BPP,
|
||||
data: imgData, }, map]);
|
||||
argsArray.splice(iFirstSave, count * 4, [
|
||||
{
|
||||
width: imgWidth,
|
||||
height: imgHeight,
|
||||
kind: ImageKind.RGBA_32BPP,
|
||||
data: imgData,
|
||||
},
|
||||
map,
|
||||
]);
|
||||
|
||||
return iFirstSave + 1;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// This replaces (save, transform, paintImageMaskXObject, restore)+
|
||||
// sequences with one |paintImageMaskXObjectGroup| or one
|
||||
// |paintImageMaskXObjectRepeat| operation.
|
||||
addState(InitialState,
|
||||
addState(
|
||||
InitialState,
|
||||
[OPS.save, OPS.transform, OPS.paintImageMaskXObject, OPS.restore],
|
||||
null,
|
||||
function iterateImageMaskGroup(context, i) {
|
||||
@ -182,7 +206,8 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
var MAX_IMAGES_IN_MASKS_BLOCK = 100;
|
||||
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 iFirstSave = curr - 3;
|
||||
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
|
||||
// quartet.
|
||||
var count = Math.floor((i - iFirstSave) / 4);
|
||||
count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray,
|
||||
argsArray);
|
||||
count = handlePaintSolidColorImageMask(
|
||||
iFirstSave,
|
||||
count,
|
||||
fnArray,
|
||||
argsArray
|
||||
);
|
||||
if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
|
||||
return i - (i - iFirstSave) % 4;
|
||||
return i - ((i - iFirstSave) % 4);
|
||||
}
|
||||
|
||||
var q;
|
||||
var isSameImage = false;
|
||||
var iTransform, transformArgs;
|
||||
var firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
|
||||
if (argsArray[iFirstTransform][1] === 0 &&
|
||||
argsArray[iFirstTransform][2] === 0) {
|
||||
if (
|
||||
argsArray[iFirstTransform][1] === 0 &&
|
||||
argsArray[iFirstTransform][2] === 0
|
||||
) {
|
||||
isSameImage = true;
|
||||
var firstTransformArg0 = argsArray[iFirstTransform][0];
|
||||
var firstTransformArg3 = argsArray[iFirstTransform][3];
|
||||
@ -210,11 +241,13 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
var iPIMXO = iFirstPIMXO + 4;
|
||||
for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
|
||||
transformArgs = argsArray[iTransform];
|
||||
if (argsArray[iPIMXO][0] !== firstPIMXOArg0 ||
|
||||
if (
|
||||
argsArray[iPIMXO][0] !== firstPIMXOArg0 ||
|
||||
transformArgs[0] !== firstTransformArg0 ||
|
||||
transformArgs[1] !== 0 ||
|
||||
transformArgs[2] !== 0 ||
|
||||
transformArgs[3] !== firstTransformArg3) {
|
||||
transformArgs[3] !== firstTransformArg3
|
||||
) {
|
||||
if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
|
||||
isSameImage = false;
|
||||
} else {
|
||||
@ -231,23 +264,30 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
iTransform = iFirstTransform;
|
||||
for (q = 0; q < count; q++, iTransform += 4) {
|
||||
transformArgs = argsArray[iTransform];
|
||||
positions[(q << 1)] = transformArgs[4];
|
||||
positions[q << 1] = transformArgs[4];
|
||||
positions[(q << 1) + 1] = transformArgs[5];
|
||||
}
|
||||
|
||||
// Replace queue items.
|
||||
fnArray.splice(iFirstSave, count * 4, OPS.paintImageMaskXObjectRepeat);
|
||||
argsArray.splice(iFirstSave, count * 4,
|
||||
[firstPIMXOArg0, firstTransformArg0, firstTransformArg3, positions]);
|
||||
argsArray.splice(iFirstSave, count * 4, [
|
||||
firstPIMXOArg0,
|
||||
firstTransformArg0,
|
||||
firstTransformArg3,
|
||||
positions,
|
||||
]);
|
||||
} else {
|
||||
count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
|
||||
var images = [];
|
||||
for (q = 0; q < count; q++) {
|
||||
transformArgs = argsArray[iFirstTransform + (q << 2)];
|
||||
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,
|
||||
transform: transformArgs, });
|
||||
transform: transformArgs,
|
||||
});
|
||||
}
|
||||
|
||||
// Replace queue items.
|
||||
@ -256,21 +296,26 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
}
|
||||
|
||||
return iFirstSave + 1;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// This replaces (save, transform, paintImageXObject, restore)+ sequences
|
||||
// with one paintImageXObjectRepeat operation, if the |transform| and
|
||||
// |paintImageXObjectRepeat| ops are appropriate.
|
||||
addState(InitialState,
|
||||
addState(
|
||||
InitialState,
|
||||
[OPS.save, OPS.transform, OPS.paintImageXObject, OPS.restore],
|
||||
function (context) {
|
||||
function(context) {
|
||||
var argsArray = context.argsArray;
|
||||
var iFirstTransform = context.iCurr - 2;
|
||||
return argsArray[iFirstTransform][1] === 0 &&
|
||||
argsArray[iFirstTransform][2] === 0;
|
||||
return (
|
||||
argsArray[iFirstTransform][1] === 0 &&
|
||||
argsArray[iFirstTransform][2] === 0
|
||||
);
|
||||
},
|
||||
function iterateImageGroup(context, i) {
|
||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
||||
var fnArray = context.fnArray,
|
||||
argsArray = context.argsArray;
|
||||
var iFirstSave = context.iCurr - 3;
|
||||
var pos = (i - iFirstSave) % 4;
|
||||
switch (pos) {
|
||||
@ -283,10 +328,12 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
var iFirstTransform = context.iCurr - 2;
|
||||
var firstTransformArg0 = argsArray[iFirstTransform][0];
|
||||
var firstTransformArg3 = argsArray[iFirstTransform][3];
|
||||
if (argsArray[i][0] !== firstTransformArg0 ||
|
||||
if (
|
||||
argsArray[i][0] !== firstTransformArg0 ||
|
||||
argsArray[i][1] !== 0 ||
|
||||
argsArray[i][2] !== 0 ||
|
||||
argsArray[i][3] !== firstTransformArg3) {
|
||||
argsArray[i][3] !== firstTransformArg3
|
||||
) {
|
||||
return false; // transforms don't match
|
||||
}
|
||||
return true;
|
||||
@ -305,11 +352,12 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
}
|
||||
throw new Error(`iterateImageGroup - invalid pos: ${pos}`);
|
||||
},
|
||||
function (context, i) {
|
||||
function(context, i) {
|
||||
var MIN_IMAGES_IN_BLOCK = 3;
|
||||
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 iFirstSave = curr - 3;
|
||||
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
|
||||
// quartet.
|
||||
var count = Math.min(Math.floor((i - iFirstSave) / 4),
|
||||
MAX_IMAGES_IN_BLOCK);
|
||||
var count = Math.min(
|
||||
Math.floor((i - iFirstSave) / 4),
|
||||
MAX_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.
|
||||
@ -331,27 +381,34 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
var iTransform = iFirstTransform;
|
||||
for (var q = 0; q < count; q++, iTransform += 4) {
|
||||
var transformArgs = argsArray[iTransform];
|
||||
positions[(q << 1)] = transformArgs[4];
|
||||
positions[q << 1] = transformArgs[4];
|
||||
positions[(q << 1) + 1] = transformArgs[5];
|
||||
}
|
||||
|
||||
// Replace queue items.
|
||||
var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3,
|
||||
positions];
|
||||
var args = [
|
||||
firstPIXOArg0,
|
||||
firstTransformArg0,
|
||||
firstTransformArg3,
|
||||
positions,
|
||||
];
|
||||
fnArray.splice(iFirstSave, count * 4, OPS.paintImageXObjectRepeat);
|
||||
argsArray.splice(iFirstSave, count * 4, args);
|
||||
|
||||
return iFirstSave + 1;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// This replaces (beginText, setFont, setTextMatrix, showText, endText)+
|
||||
// sequences with (beginText, setFont, (setTextMatrix, showText)+, endText)+
|
||||
// sequences, if the font for each one is the same.
|
||||
addState(InitialState,
|
||||
addState(
|
||||
InitialState,
|
||||
[OPS.beginText, OPS.setFont, OPS.setTextMatrix, OPS.showText, OPS.endText],
|
||||
null,
|
||||
function iterateShowTextGroup(context, i) {
|
||||
var fnArray = context.fnArray, argsArray = context.argsArray;
|
||||
var fnArray = context.fnArray,
|
||||
argsArray = context.argsArray;
|
||||
var iFirstSave = context.iCurr - 4;
|
||||
var pos = (i - iFirstSave) % 5;
|
||||
switch (pos) {
|
||||
@ -368,8 +425,10 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
var iFirstSetFont = context.iCurr - 3;
|
||||
var firstSetFontArg0 = argsArray[iFirstSetFont][0];
|
||||
var firstSetFontArg1 = argsArray[iFirstSetFont][1];
|
||||
if (argsArray[i][0] !== firstSetFontArg0 ||
|
||||
argsArray[i][1] !== firstSetFontArg1) {
|
||||
if (
|
||||
argsArray[i][0] !== firstSetFontArg0 ||
|
||||
argsArray[i][1] !== firstSetFontArg1
|
||||
) {
|
||||
return false; // fonts don't match
|
||||
}
|
||||
return true;
|
||||
@ -378,11 +437,12 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
}
|
||||
throw new Error(`iterateShowTextGroup - invalid pos: ${pos}`);
|
||||
},
|
||||
function (context, i) {
|
||||
function(context, i) {
|
||||
var MIN_CHARS_IN_BLOCK = 3;
|
||||
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 iFirstBeginText = curr - 4;
|
||||
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
|
||||
// quintet.
|
||||
var count = Math.min(Math.floor((i - iFirstBeginText) / 5),
|
||||
MAX_CHARS_IN_BLOCK);
|
||||
var count = Math.min(
|
||||
Math.floor((i - iFirstBeginText) / 5),
|
||||
MAX_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,
|
||||
// showText, endText), include that as well. (E.g. <something> might be
|
||||
// |dependency|.)
|
||||
var iFirst = iFirstBeginText;
|
||||
if (iFirstBeginText >= 4 &&
|
||||
if (
|
||||
iFirstBeginText >= 4 &&
|
||||
fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] &&
|
||||
fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] &&
|
||||
fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] &&
|
||||
fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] &&
|
||||
argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 &&
|
||||
argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
|
||||
argsArray[iFirstBeginText - 4][1] === firstSetFontArg1
|
||||
) {
|
||||
count++;
|
||||
iFirst -= 5;
|
||||
}
|
||||
@ -424,7 +488,8 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
}
|
||||
|
||||
return iEndText + 1;
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
function QueueOptimizer(queue) {
|
||||
this.queue = queue;
|
||||
@ -442,10 +507,11 @@ var QueueOptimizer = (function QueueOptimizerClosure() {
|
||||
_optimize() {
|
||||
// Process new fnArray item(s) chunk.
|
||||
const fnArray = this.queue.fnArray;
|
||||
let i = this.lastProcessed, ii = fnArray.length;
|
||||
let i = this.lastProcessed,
|
||||
ii = fnArray.length;
|
||||
let state = this.state;
|
||||
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
|
||||
// optimizable, just skipping it.
|
||||
this.lastProcessed = ii;
|
||||
@ -529,9 +595,9 @@ var NullOptimizer = (function NullOptimizerClosure() {
|
||||
this.queue.argsArray.push(args);
|
||||
},
|
||||
|
||||
flush() { },
|
||||
flush() {},
|
||||
|
||||
reset() { },
|
||||
reset() {},
|
||||
};
|
||||
|
||||
return NullOptimizer;
|
||||
@ -545,7 +611,7 @@ var OperatorList = (function OperatorListClosure() {
|
||||
this._streamSink = streamSink;
|
||||
this.fnArray = [];
|
||||
this.argsArray = [];
|
||||
if (streamSink && intent !== 'oplist') {
|
||||
if (streamSink && intent !== "oplist") {
|
||||
this.optimizer = new QueueOptimizer(this);
|
||||
} else {
|
||||
this.optimizer = new NullOptimizer(this);
|
||||
@ -572,7 +638,7 @@ var OperatorList = (function OperatorListClosure() {
|
||||
* `this.length === 0` after flushing.
|
||||
*/
|
||||
get totalLength() {
|
||||
return (this._totalLength + this.length);
|
||||
return this._totalLength + this.length;
|
||||
},
|
||||
|
||||
addOp(fn, args) {
|
||||
@ -581,8 +647,10 @@ var OperatorList = (function OperatorListClosure() {
|
||||
if (this._streamSink) {
|
||||
if (this.weight >= CHUNK_SIZE) {
|
||||
this.flush();
|
||||
} else if (this.weight >= CHUNK_SIZE_ABOUT &&
|
||||
(fn === OPS.restore || fn === OPS.endText)) {
|
||||
} else if (
|
||||
this.weight >= CHUNK_SIZE_ABOUT &&
|
||||
(fn === OPS.restore || fn === OPS.endText)
|
||||
) {
|
||||
// heuristic to flush on boundary of restore or endText
|
||||
this.flush();
|
||||
}
|
||||
@ -620,7 +688,7 @@ var OperatorList = (function OperatorListClosure() {
|
||||
|
||||
get _transfers() {
|
||||
const transfers = [];
|
||||
const { fnArray, argsArray, length, } = this;
|
||||
const { fnArray, argsArray, length } = this;
|
||||
for (let i = 0; i < length; i++) {
|
||||
switch (fnArray[i]) {
|
||||
case OPS.paintInlineImageXObject:
|
||||
@ -628,10 +696,14 @@ var OperatorList = (function OperatorListClosure() {
|
||||
case OPS.paintImageMaskXObject:
|
||||
const arg = argsArray[i][0]; // first param in imgData
|
||||
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
assert(arg.data instanceof Uint8ClampedArray,
|
||||
'OperatorList._transfers: Unsupported "arg.data" type.');
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||
) {
|
||||
assert(
|
||||
arg.data instanceof Uint8ClampedArray,
|
||||
'OperatorList._transfers: Unsupported "arg.data" type.'
|
||||
);
|
||||
}
|
||||
if (!arg.cached) {
|
||||
transfers.push(arg.data.buffer);
|
||||
@ -647,12 +719,16 @@ var OperatorList = (function OperatorListClosure() {
|
||||
const length = this.length;
|
||||
this._totalLength += length;
|
||||
|
||||
this._streamSink.enqueue({
|
||||
this._streamSink.enqueue(
|
||||
{
|
||||
fnArray: this.fnArray,
|
||||
argsArray: this.argsArray,
|
||||
lastChunk,
|
||||
length,
|
||||
}, 1, this._transfers);
|
||||
},
|
||||
1,
|
||||
this._transfers
|
||||
);
|
||||
|
||||
this.dependencies = Object.create(null);
|
||||
this.fnArray.length = 0;
|
||||
@ -665,6 +741,4 @@ var OperatorList = (function OperatorListClosure() {
|
||||
return OperatorList;
|
||||
})();
|
||||
|
||||
export {
|
||||
OperatorList,
|
||||
};
|
||||
export { OperatorList };
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -15,11 +15,17 @@
|
||||
/* eslint-disable no-multi-spaces */
|
||||
|
||||
import {
|
||||
assert, FormatError, info, unreachable, UNSUPPORTED_FEATURES, Util, warn
|
||||
} from '../shared/util';
|
||||
import { ColorSpace } from './colorspace';
|
||||
import { isStream } from './primitives';
|
||||
import { MissingDataException } from './core_utils';
|
||||
assert,
|
||||
FormatError,
|
||||
info,
|
||||
unreachable,
|
||||
UNSUPPORTED_FEATURES,
|
||||
Util,
|
||||
warn,
|
||||
} from "../shared/util";
|
||||
import { ColorSpace } from "./colorspace";
|
||||
import { isStream } from "./primitives";
|
||||
import { MissingDataException } from "./core_utils";
|
||||
|
||||
var ShadingType = {
|
||||
FUNCTION_BASED: 1,
|
||||
@ -34,7 +40,7 @@ var ShadingType = {
|
||||
var Pattern = (function PatternClosure() {
|
||||
// Constructor should define this.getPattern
|
||||
function Pattern() {
|
||||
unreachable('should not call Pattern constructor');
|
||||
unreachable("should not call Pattern constructor");
|
||||
}
|
||||
|
||||
Pattern.prototype = {
|
||||
@ -45,33 +51,50 @@ var Pattern = (function PatternClosure() {
|
||||
},
|
||||
};
|
||||
|
||||
Pattern.parseShading = function(shading, matrix, xref, res, handler,
|
||||
pdfFunctionFactory) {
|
||||
Pattern.parseShading = function(
|
||||
shading,
|
||||
matrix,
|
||||
xref,
|
||||
res,
|
||||
handler,
|
||||
pdfFunctionFactory
|
||||
) {
|
||||
var dict = isStream(shading) ? shading.dict : shading;
|
||||
var type = dict.get('ShadingType');
|
||||
var type = dict.get("ShadingType");
|
||||
|
||||
try {
|
||||
switch (type) {
|
||||
case ShadingType.AXIAL:
|
||||
case ShadingType.RADIAL:
|
||||
// Both radial and axial shadings are handled by RadialAxial shading.
|
||||
return new Shadings.RadialAxial(dict, matrix, xref, res,
|
||||
pdfFunctionFactory);
|
||||
return new Shadings.RadialAxial(
|
||||
dict,
|
||||
matrix,
|
||||
xref,
|
||||
res,
|
||||
pdfFunctionFactory
|
||||
);
|
||||
case ShadingType.FREE_FORM_MESH:
|
||||
case ShadingType.LATTICE_FORM_MESH:
|
||||
case ShadingType.COONS_PATCH_MESH:
|
||||
case ShadingType.TENSOR_PATCH_MESH:
|
||||
return new Shadings.Mesh(shading, matrix, xref, res,
|
||||
pdfFunctionFactory);
|
||||
return new Shadings.Mesh(
|
||||
shading,
|
||||
matrix,
|
||||
xref,
|
||||
res,
|
||||
pdfFunctionFactory
|
||||
);
|
||||
default:
|
||||
throw new FormatError('Unsupported ShadingType: ' + type);
|
||||
throw new FormatError("Unsupported ShadingType: " + type);
|
||||
}
|
||||
} catch (ex) {
|
||||
if (ex instanceof MissingDataException) {
|
||||
throw ex;
|
||||
}
|
||||
handler.send('UnsupportedFeature',
|
||||
{ featureId: UNSUPPORTED_FEATURES.shadingPattern, });
|
||||
handler.send("UnsupportedFeature", {
|
||||
featureId: UNSUPPORTED_FEATURES.shadingPattern,
|
||||
});
|
||||
warn(ex);
|
||||
return new Shadings.Dummy();
|
||||
}
|
||||
@ -90,35 +113,39 @@ Shadings.SMALL_NUMBER = 1e-6;
|
||||
Shadings.RadialAxial = (function RadialAxialClosure() {
|
||||
function RadialAxial(dict, matrix, xref, res, pdfFunctionFactory) {
|
||||
this.matrix = matrix;
|
||||
this.coordsArr = dict.getArray('Coords');
|
||||
this.shadingType = dict.get('ShadingType');
|
||||
this.type = 'Pattern';
|
||||
var cs = dict.get('ColorSpace', 'CS');
|
||||
this.coordsArr = dict.getArray("Coords");
|
||||
this.shadingType = dict.get("ShadingType");
|
||||
this.type = "Pattern";
|
||||
var cs = dict.get("ColorSpace", "CS");
|
||||
cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
|
||||
this.cs = cs;
|
||||
const bbox = dict.getArray('BBox');
|
||||
const bbox = dict.getArray("BBox");
|
||||
if (Array.isArray(bbox) && bbox.length === 4) {
|
||||
this.bbox = Util.normalizeRect(bbox);
|
||||
} else {
|
||||
this.bbox = null;
|
||||
}
|
||||
|
||||
var t0 = 0.0, t1 = 1.0;
|
||||
if (dict.has('Domain')) {
|
||||
var domainArr = dict.getArray('Domain');
|
||||
var t0 = 0.0,
|
||||
t1 = 1.0;
|
||||
if (dict.has("Domain")) {
|
||||
var domainArr = dict.getArray("Domain");
|
||||
t0 = domainArr[0];
|
||||
t1 = domainArr[1];
|
||||
}
|
||||
|
||||
var extendStart = false, extendEnd = false;
|
||||
if (dict.has('Extend')) {
|
||||
var extendArr = dict.getArray('Extend');
|
||||
var extendStart = false,
|
||||
extendEnd = false;
|
||||
if (dict.has("Extend")) {
|
||||
var extendArr = dict.getArray("Extend");
|
||||
extendStart = extendArr[0];
|
||||
extendEnd = extendArr[1];
|
||||
}
|
||||
|
||||
if (this.shadingType === ShadingType.RADIAL &&
|
||||
(!extendStart || !extendEnd)) {
|
||||
if (
|
||||
this.shadingType === ShadingType.RADIAL &&
|
||||
(!extendStart || !extendEnd)
|
||||
) {
|
||||
// Radial gradient only currently works if either circle is fully within
|
||||
// the other circle.
|
||||
var x1 = this.coordsArr[0];
|
||||
@ -128,16 +155,15 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
||||
var y2 = this.coordsArr[4];
|
||||
var r2 = this.coordsArr[5];
|
||||
var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
|
||||
if (r1 <= r2 + distance &&
|
||||
r2 <= r1 + distance) {
|
||||
warn('Unsupported radial gradient.');
|
||||
if (r1 <= r2 + distance && r2 <= r1 + distance) {
|
||||
warn("Unsupported radial gradient.");
|
||||
}
|
||||
}
|
||||
|
||||
this.extendStart = extendStart;
|
||||
this.extendEnd = extendEnd;
|
||||
|
||||
var fnObj = dict.get('Function');
|
||||
var fnObj = dict.get("Function");
|
||||
var fn = pdfFunctionFactory.createFromArray(fnObj);
|
||||
|
||||
// 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 step = (t1 - t0) / NUMBER_OF_SAMPLES;
|
||||
|
||||
var colorStops = this.colorStops = [];
|
||||
var colorStops = (this.colorStops = []);
|
||||
|
||||
// Protect against bad domains.
|
||||
if (t0 >= t1 || step <= 0) {
|
||||
// Acrobat doesn't seem to handle these cases so we'll ignore for
|
||||
// now.
|
||||
info('Bad shading domain.');
|
||||
info("Bad shading domain.");
|
||||
return;
|
||||
}
|
||||
|
||||
var color = new Float32Array(cs.numComps), ratio = new Float32Array(1);
|
||||
var color = new Float32Array(cs.numComps),
|
||||
ratio = new Float32Array(1);
|
||||
var rgbColor;
|
||||
for (let i = 0; i <= NUMBER_OF_SAMPLES; i++) {
|
||||
ratio[0] = t0 + i * step;
|
||||
@ -166,9 +193,9 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
||||
colorStops.push([i / NUMBER_OF_SAMPLES, cssColor]);
|
||||
}
|
||||
|
||||
var background = 'transparent';
|
||||
if (dict.has('Background')) {
|
||||
rgbColor = cs.getRgb(dict.get('Background'), 0);
|
||||
var background = "transparent";
|
||||
if (dict.has("Background")) {
|
||||
rgbColor = cs.getRgb(dict.get("Background"), 0);
|
||||
background = Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
|
||||
}
|
||||
|
||||
@ -197,13 +224,13 @@ Shadings.RadialAxial = (function RadialAxialClosure() {
|
||||
p1 = [coordsArr[2], coordsArr[3]];
|
||||
r0 = null;
|
||||
r1 = null;
|
||||
type = 'axial';
|
||||
type = "axial";
|
||||
} else if (shadingType === ShadingType.RADIAL) {
|
||||
p0 = [coordsArr[0], coordsArr[1]];
|
||||
p1 = [coordsArr[3], coordsArr[4]];
|
||||
r0 = coordsArr[2];
|
||||
r1 = coordsArr[5];
|
||||
type = 'radial';
|
||||
type = "radial";
|
||||
} else {
|
||||
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;
|
||||
this.tmpCompsBuf = new Float32Array(numComps);
|
||||
var csNumComps = context.colorSpace.numComps;
|
||||
this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) :
|
||||
this.tmpCompsBuf;
|
||||
this.tmpCsCompsBuf = context.colorFn
|
||||
? new Float32Array(csNumComps)
|
||||
: this.tmpCompsBuf;
|
||||
}
|
||||
MeshStreamReader.prototype = {
|
||||
get hasData() {
|
||||
@ -262,16 +290,26 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
var bufferLength = this.bufferLength;
|
||||
if (n === 32) {
|
||||
if (bufferLength === 0) {
|
||||
return ((this.stream.getByte() << 24) |
|
||||
(this.stream.getByte() << 16) | (this.stream.getByte() << 8) |
|
||||
this.stream.getByte()) >>> 0;
|
||||
return (
|
||||
((this.stream.getByte() << 24) |
|
||||
(this.stream.getByte() << 16) |
|
||||
(this.stream.getByte() << 8) |
|
||||
this.stream.getByte()) >>>
|
||||
0
|
||||
);
|
||||
}
|
||||
buffer = (buffer << 24) | (this.stream.getByte() << 16) |
|
||||
(this.stream.getByte() << 8) | this.stream.getByte();
|
||||
buffer =
|
||||
(buffer << 24) |
|
||||
(this.stream.getByte() << 16) |
|
||||
(this.stream.getByte() << 8) |
|
||||
this.stream.getByte();
|
||||
var nextByte = this.stream.getByte();
|
||||
this.buffer = nextByte & ((1 << bufferLength) - 1);
|
||||
return ((buffer << (8 - bufferLength)) |
|
||||
((nextByte & 0xFF) >> bufferLength)) >>> 0;
|
||||
return (
|
||||
((buffer << (8 - bufferLength)) |
|
||||
((nextByte & 0xff) >> bufferLength)) >>>
|
||||
0
|
||||
);
|
||||
}
|
||||
if (n === 8 && bufferLength === 0) {
|
||||
return this.stream.getByte();
|
||||
@ -297,18 +335,22 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
var xi = this.readBits(bitsPerCoordinate);
|
||||
var yi = this.readBits(bitsPerCoordinate);
|
||||
var decode = this.context.decode;
|
||||
var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) :
|
||||
2.3283064365386963e-10; // 2 ^ -32
|
||||
var scale =
|
||||
bitsPerCoordinate < 32
|
||||
? 1 / ((1 << bitsPerCoordinate) - 1)
|
||||
: 2.3283064365386963e-10; // 2 ^ -32
|
||||
return [
|
||||
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() {
|
||||
var numComps = this.context.numComps;
|
||||
var bitsPerComponent = this.context.bitsPerComponent;
|
||||
var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) :
|
||||
2.3283064365386963e-10; // 2 ^ -32
|
||||
var scale =
|
||||
bitsPerComponent < 32
|
||||
? 1 / ((1 << bitsPerComponent) - 1)
|
||||
: 2.3283064365386963e-10; // 2 ^ -32
|
||||
var decode = this.context.decode;
|
||||
var components = this.tmpCompsBuf;
|
||||
for (var i = 0, j = 4; i < numComps; i++, j += 2) {
|
||||
@ -333,9 +375,10 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
var f = reader.readFlag();
|
||||
var coord = reader.readCoordinate();
|
||||
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)) {
|
||||
throw new FormatError('Unknown type4 flag');
|
||||
throw new FormatError("Unknown type4 flag");
|
||||
}
|
||||
switch (f) {
|
||||
case 0:
|
||||
@ -360,7 +403,7 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
reader.align();
|
||||
}
|
||||
mesh.figures.push({
|
||||
type: 'triangles',
|
||||
type: "triangles",
|
||||
coords: new Int32Array(ps),
|
||||
colors: new Int32Array(ps),
|
||||
});
|
||||
@ -378,7 +421,7 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
colors.push(color);
|
||||
}
|
||||
mesh.figures.push({
|
||||
type: 'lattice',
|
||||
type: "lattice",
|
||||
coords: new Int32Array(ps),
|
||||
colors: new Int32Array(ps),
|
||||
verticesPerRow,
|
||||
@ -394,9 +437,16 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
function buildB(count) {
|
||||
var lut = [];
|
||||
for (var i = 0; i <= count; i++) {
|
||||
var t = i / count, t_ = 1 - t;
|
||||
lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_,
|
||||
3 * t * t * t_, t * t * t]));
|
||||
var t = i / count,
|
||||
t_ = 1 - t;
|
||||
lut.push(
|
||||
new Float32Array([
|
||||
t_ * t_ * t_,
|
||||
3 * t * t_ * t_,
|
||||
3 * t * t * t_,
|
||||
t * t * t,
|
||||
])
|
||||
);
|
||||
}
|
||||
return lut;
|
||||
}
|
||||
@ -411,37 +461,66 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
|
||||
function buildFigureFromPatch(mesh, 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 ci = figure.colors;
|
||||
|
||||
var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0],
|
||||
coords[pi[12]][0], coords[pi[15]][0]);
|
||||
var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1],
|
||||
coords[pi[12]][1], coords[pi[15]][1]);
|
||||
var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0],
|
||||
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 figureMinX = Math.min(
|
||||
coords[pi[0]][0],
|
||||
coords[pi[3]][0],
|
||||
coords[pi[12]][0],
|
||||
coords[pi[15]][0]
|
||||
);
|
||||
var figureMinY = Math.min(
|
||||
coords[pi[0]][1],
|
||||
coords[pi[3]][1],
|
||||
coords[pi[12]][1],
|
||||
coords[pi[15]][1]
|
||||
);
|
||||
var figureMaxX = Math.max(
|
||||
coords[pi[0]][0],
|
||||
coords[pi[3]][0],
|
||||
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 figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
|
||||
var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
|
||||
var k = 0;
|
||||
var cl = new Uint8Array(3), cr = new Uint8Array(3);
|
||||
var c0 = colors[ci[0]], c1 = colors[ci[1]],
|
||||
c2 = colors[ci[2]], c3 = colors[ci[3]];
|
||||
var bRow = getB(splitYBy), bCol = getB(splitXBy);
|
||||
var cl = new Uint8Array(3),
|
||||
cr = new Uint8Array(3);
|
||||
var c0 = colors[ci[0]],
|
||||
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++) {
|
||||
cl[0] = ((c0[0] * (splitYBy - row) + c2[0] * 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;
|
||||
|
||||
for (var col = 0; col <= splitXBy; col++, k++) {
|
||||
if ((row === 0 || row === splitYBy) &&
|
||||
(col === 0 || col === splitXBy)) {
|
||||
if (
|
||||
(row === 0 || row === splitYBy) &&
|
||||
(col === 0 || col === splitXBy)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
var x = 0, y = 0;
|
||||
var x = 0,
|
||||
y = 0;
|
||||
var q = 0;
|
||||
for (var i = 0; i <= 3; i++) {
|
||||
for (var j = 0; j <= 3; j++, q++) {
|
||||
@ -485,7 +567,7 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
|
||||
|
||||
mesh.figures[index] = {
|
||||
type: 'lattice',
|
||||
type: "lattice",
|
||||
coords: figureCoords,
|
||||
colors: figureColors,
|
||||
verticesPerRow,
|
||||
@ -501,15 +583,15 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
while (reader.hasData) {
|
||||
var f = reader.readFlag();
|
||||
if (!(0 <= f && f <= 3)) {
|
||||
throw new FormatError('Unknown type6 flag');
|
||||
throw new FormatError("Unknown type6 flag");
|
||||
}
|
||||
var i, ii;
|
||||
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());
|
||||
}
|
||||
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());
|
||||
}
|
||||
var tmp1, tmp2, tmp3, tmp4;
|
||||
@ -559,50 +641,66 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
// set p11, p12, p21, p22
|
||||
ps[5] = coords.length;
|
||||
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]) -
|
||||
2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
|
||||
3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9,
|
||||
(-4 * coords[ps[0]][1] - coords[ps[15]][1] +
|
||||
3 * (coords[ps[13]][0] + coords[ps[7]][0])) /
|
||||
9,
|
||||
(-4 * coords[ps[0]][1] -
|
||||
coords[ps[15]][1] +
|
||||
6 * (coords[ps[4]][1] + coords[ps[1]][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;
|
||||
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]) -
|
||||
2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
|
||||
3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9,
|
||||
(-4 * coords[ps[3]][1] - coords[ps[12]][1] +
|
||||
3 * (coords[ps[4]][0] + coords[ps[14]][0])) /
|
||||
9,
|
||||
(-4 * coords[ps[3]][1] -
|
||||
coords[ps[12]][1] +
|
||||
6 * (coords[ps[2]][1] + coords[ps[7]][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;
|
||||
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]) -
|
||||
2 * (coords[ps[0]][0] + coords[ps[15]][0]) +
|
||||
3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9,
|
||||
(-4 * coords[ps[12]][1] - coords[ps[3]][1] +
|
||||
3 * (coords[ps[11]][0] + coords[ps[1]][0])) /
|
||||
9,
|
||||
(-4 * coords[ps[12]][1] -
|
||||
coords[ps[3]][1] +
|
||||
6 * (coords[ps[8]][1] + coords[ps[13]][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;
|
||||
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]) -
|
||||
2 * (coords[ps[12]][0] + coords[ps[3]][0]) +
|
||||
3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9,
|
||||
(-4 * coords[ps[15]][1] - coords[ps[0]][1] +
|
||||
3 * (coords[ps[2]][0] + coords[ps[8]][0])) /
|
||||
9,
|
||||
(-4 * coords[ps[15]][1] -
|
||||
coords[ps[0]][1] +
|
||||
6 * (coords[ps[11]][1] + coords[ps[14]][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({
|
||||
type: 'patch',
|
||||
type: "patch",
|
||||
coords: new Int32Array(ps), // making copies of ps and cs
|
||||
colors: new Int32Array(cs),
|
||||
});
|
||||
@ -617,15 +715,15 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
while (reader.hasData) {
|
||||
var f = reader.readFlag();
|
||||
if (!(0 <= f && f <= 3)) {
|
||||
throw new FormatError('Unknown type7 flag');
|
||||
throw new FormatError("Unknown type7 flag");
|
||||
}
|
||||
var i, ii;
|
||||
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());
|
||||
}
|
||||
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());
|
||||
}
|
||||
var tmp1, tmp2, tmp3, tmp4;
|
||||
@ -673,7 +771,7 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
break;
|
||||
}
|
||||
mesh.figures.push({
|
||||
type: 'patch',
|
||||
type: "patch",
|
||||
coords: new Int32Array(ps), // making copies of ps and cs
|
||||
colors: new Int32Array(cs),
|
||||
});
|
||||
@ -681,10 +779,13 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
}
|
||||
|
||||
function updateBounds(mesh) {
|
||||
var minX = mesh.coords[0][0], minY = mesh.coords[0][1],
|
||||
maxX = minX, maxY = minY;
|
||||
var minX = mesh.coords[0][0],
|
||||
minY = mesh.coords[0][1],
|
||||
maxX = minX,
|
||||
maxY = minY;
|
||||
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;
|
||||
minY = minY > y ? y : minY;
|
||||
maxX = maxX < x ? x : maxX;
|
||||
@ -717,7 +818,9 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
|
||||
var figures = mesh.figures;
|
||||
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++) {
|
||||
ps[j] *= 2;
|
||||
cs[j] *= 3;
|
||||
@ -727,25 +830,26 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
|
||||
function Mesh(stream, matrix, xref, res, pdfFunctionFactory) {
|
||||
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;
|
||||
this.matrix = matrix;
|
||||
this.shadingType = dict.get('ShadingType');
|
||||
this.type = 'Pattern';
|
||||
const bbox = dict.getArray('BBox');
|
||||
this.shadingType = dict.get("ShadingType");
|
||||
this.type = "Pattern";
|
||||
const bbox = dict.getArray("BBox");
|
||||
if (Array.isArray(bbox) && bbox.length === 4) {
|
||||
this.bbox = Util.normalizeRect(bbox);
|
||||
} else {
|
||||
this.bbox = null;
|
||||
}
|
||||
var cs = dict.get('ColorSpace', 'CS');
|
||||
var cs = dict.get("ColorSpace", "CS");
|
||||
cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
|
||||
this.cs = cs;
|
||||
this.background = dict.has('Background') ?
|
||||
cs.getRgb(dict.get('Background'), 0) : null;
|
||||
this.background = dict.has("Background")
|
||||
? cs.getRgb(dict.get("Background"), 0)
|
||||
: null;
|
||||
|
||||
var fnObj = dict.get('Function');
|
||||
var fnObj = dict.get("Function");
|
||||
var fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
|
||||
|
||||
this.coords = [];
|
||||
@ -753,10 +857,10 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
this.figures = [];
|
||||
|
||||
var decodeContext = {
|
||||
bitsPerCoordinate: dict.get('BitsPerCoordinate'),
|
||||
bitsPerComponent: dict.get('BitsPerComponent'),
|
||||
bitsPerFlag: dict.get('BitsPerFlag'),
|
||||
decode: dict.getArray('Decode'),
|
||||
bitsPerCoordinate: dict.get("BitsPerCoordinate"),
|
||||
bitsPerComponent: dict.get("BitsPerComponent"),
|
||||
bitsPerFlag: dict.get("BitsPerFlag"),
|
||||
decode: dict.getArray("Decode"),
|
||||
colorFn: fn,
|
||||
colorSpace: cs,
|
||||
numComps: fn ? 1 : cs.numComps,
|
||||
@ -769,9 +873,9 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
decodeType4Shading(this, reader);
|
||||
break;
|
||||
case ShadingType.LATTICE_FORM_MESH:
|
||||
var verticesPerRow = dict.get('VerticesPerRow') | 0;
|
||||
var verticesPerRow = dict.get("VerticesPerRow") | 0;
|
||||
if (verticesPerRow < 2) {
|
||||
throw new FormatError('Invalid VerticesPerRow');
|
||||
throw new FormatError("Invalid VerticesPerRow");
|
||||
}
|
||||
decodeType5Shading(this, reader, verticesPerRow);
|
||||
break;
|
||||
@ -784,7 +888,7 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
patchMesh = true;
|
||||
break;
|
||||
default:
|
||||
unreachable('Unsupported mesh type.');
|
||||
unreachable("Unsupported mesh type.");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -803,8 +907,17 @@ Shadings.Mesh = (function MeshClosure() {
|
||||
|
||||
Mesh.prototype = {
|
||||
getIR: function Mesh_getIR() {
|
||||
return ['Mesh', this.shadingType, this.coords, this.colors, this.figures,
|
||||
this.bounds, this.matrix, this.bbox, this.background];
|
||||
return [
|
||||
"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() {
|
||||
function Dummy() {
|
||||
this.type = 'Pattern';
|
||||
this.type = "Pattern";
|
||||
}
|
||||
|
||||
Dummy.prototype = {
|
||||
getIR: function Dummy_getIR() {
|
||||
return ['Dummy'];
|
||||
return ["Dummy"];
|
||||
},
|
||||
};
|
||||
return Dummy;
|
||||
})();
|
||||
|
||||
function getTilingPatternIR(operatorList, dict, args) {
|
||||
let matrix = dict.getArray('Matrix');
|
||||
let bbox = Util.normalizeRect(dict.getArray('BBox'));
|
||||
let xstep = dict.get('XStep');
|
||||
let ystep = dict.get('YStep');
|
||||
let paintType = dict.get('PaintType');
|
||||
let tilingType = dict.get('TilingType');
|
||||
let matrix = dict.getArray("Matrix");
|
||||
let bbox = Util.normalizeRect(dict.getArray("BBox"));
|
||||
let xstep = dict.get("XStep");
|
||||
let ystep = dict.get("YStep");
|
||||
let paintType = dict.get("PaintType");
|
||||
let tilingType = dict.get("TilingType");
|
||||
|
||||
// Ensure that the pattern has a non-zero width and height, to prevent errors
|
||||
// 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}].`);
|
||||
}
|
||||
|
||||
return [
|
||||
'TilingPattern', args, operatorList, matrix, bbox, xstep, ystep,
|
||||
paintType, tilingType
|
||||
"TilingPattern",
|
||||
args,
|
||||
operatorList,
|
||||
matrix,
|
||||
bbox,
|
||||
xstep,
|
||||
ystep,
|
||||
paintType,
|
||||
tilingType,
|
||||
];
|
||||
}
|
||||
|
||||
export {
|
||||
Pattern,
|
||||
getTilingPatternIR,
|
||||
};
|
||||
export { Pattern, getTilingPatternIR };
|
||||
|
@ -14,17 +14,20 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
createValidAbsoluteUrl, shadow, unreachable, warn
|
||||
} from '../shared/util';
|
||||
import { ChunkedStreamManager } from './chunked_stream';
|
||||
import { MissingDataException } from './core_utils';
|
||||
import { PDFDocument } from './document';
|
||||
import { Stream } from './stream';
|
||||
createValidAbsoluteUrl,
|
||||
shadow,
|
||||
unreachable,
|
||||
warn,
|
||||
} from "../shared/util";
|
||||
import { ChunkedStreamManager } from "./chunked_stream";
|
||||
import { MissingDataException } from "./core_utils";
|
||||
import { PDFDocument } from "./document";
|
||||
import { Stream } from "./stream";
|
||||
|
||||
class BasePdfManager {
|
||||
constructor() {
|
||||
if (this.constructor === BasePdfManager) {
|
||||
unreachable('Cannot initialize BasePdfManager.');
|
||||
unreachable("Cannot initialize BasePdfManager.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,11 +49,11 @@ class BasePdfManager {
|
||||
warn(`Invalid absolute docBaseUrl: "${this._docBaseUrl}".`);
|
||||
}
|
||||
}
|
||||
return shadow(this, 'docBaseUrl', docBaseUrl);
|
||||
return shadow(this, "docBaseUrl", docBaseUrl);
|
||||
}
|
||||
|
||||
onLoadedStream() {
|
||||
unreachable('Abstract method `onLoadedStream` called');
|
||||
unreachable("Abstract method `onLoadedStream` called");
|
||||
}
|
||||
|
||||
ensureDoc(prop, args) {
|
||||
@ -78,19 +81,19 @@ class BasePdfManager {
|
||||
}
|
||||
|
||||
async ensure(obj, prop, args) {
|
||||
unreachable('Abstract method `ensure` called');
|
||||
unreachable("Abstract method `ensure` called");
|
||||
}
|
||||
|
||||
requestRange(begin, end) {
|
||||
unreachable('Abstract method `requestRange` called');
|
||||
unreachable("Abstract method `requestRange` called");
|
||||
}
|
||||
|
||||
requestLoadedStream() {
|
||||
unreachable('Abstract method `requestLoadedStream` called');
|
||||
unreachable("Abstract method `requestLoadedStream` called");
|
||||
}
|
||||
|
||||
sendProgressiveData(chunk) {
|
||||
unreachable('Abstract method `sendProgressiveData` called');
|
||||
unreachable("Abstract method `sendProgressiveData` called");
|
||||
}
|
||||
|
||||
updatePassword(password) {
|
||||
@ -98,7 +101,7 @@ class BasePdfManager {
|
||||
}
|
||||
|
||||
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) {
|
||||
const value = obj[prop];
|
||||
if (typeof value === 'function') {
|
||||
if (typeof value === "function") {
|
||||
return value.apply(obj, args);
|
||||
}
|
||||
return value;
|
||||
@ -159,7 +162,7 @@ class NetworkPdfManager extends BasePdfManager {
|
||||
async ensure(obj, prop, args) {
|
||||
try {
|
||||
const value = obj[prop];
|
||||
if (typeof value === 'function') {
|
||||
if (typeof value === "function") {
|
||||
return value.apply(obj, args);
|
||||
}
|
||||
return value;
|
||||
@ -181,7 +184,7 @@ class NetworkPdfManager extends BasePdfManager {
|
||||
}
|
||||
|
||||
sendProgressiveData(chunk) {
|
||||
this.streamManager.onReceiveData({ chunk, });
|
||||
this.streamManager.onReceiveData({ chunk });
|
||||
}
|
||||
|
||||
onLoadedStream() {
|
||||
@ -193,7 +196,4 @@ class NetworkPdfManager extends BasePdfManager {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
LocalPdfManager,
|
||||
NetworkPdfManager,
|
||||
};
|
||||
export { LocalPdfManager, NetworkPdfManager };
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
/* uses XRef */
|
||||
|
||||
import { assert } from '../shared/util';
|
||||
import { assert } from "../shared/util";
|
||||
|
||||
var EOF = {};
|
||||
|
||||
@ -29,7 +29,7 @@ var Name = (function NameClosure() {
|
||||
|
||||
Name.get = function Name_get(name) {
|
||||
var nameValue = nameCache[name];
|
||||
return (nameValue ? nameValue : (nameCache[name] = new Name(name)));
|
||||
return nameValue ? nameValue : (nameCache[name] = new Name(name));
|
||||
};
|
||||
|
||||
Name._clearCache = function() {
|
||||
@ -50,7 +50,7 @@ var Cmd = (function CmdClosure() {
|
||||
|
||||
Cmd.get = function Cmd_get(cmd) {
|
||||
var cmdValue = cmdCache[cmd];
|
||||
return (cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd)));
|
||||
return cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd));
|
||||
};
|
||||
|
||||
Cmd._clearCache = function() {
|
||||
@ -193,9 +193,9 @@ var Ref = (function RefClosure() {
|
||||
};
|
||||
|
||||
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];
|
||||
return (refValue ? refValue : (refCache[key] = new Ref(num, gen)));
|
||||
return refValue ? refValue : (refCache[key] = new Ref(num, gen));
|
||||
};
|
||||
|
||||
Ref._clearCache = function() {
|
||||
@ -266,7 +266,7 @@ var RefSetCache = (function RefSetCacheClosure() {
|
||||
})();
|
||||
|
||||
function isEOF(v) {
|
||||
return (v === EOF);
|
||||
return v === EOF;
|
||||
}
|
||||
|
||||
function isName(v, name) {
|
||||
@ -278,8 +278,9 @@ function isCmd(v, cmd) {
|
||||
}
|
||||
|
||||
function isDict(v, type) {
|
||||
return v instanceof Dict &&
|
||||
(type === undefined || isName(v.get('Type'), type));
|
||||
return (
|
||||
v instanceof Dict && (type === undefined || isName(v.get("Type"), type))
|
||||
);
|
||||
}
|
||||
|
||||
function isRef(v) {
|
||||
@ -287,16 +288,20 @@ function isRef(v) {
|
||||
}
|
||||
|
||||
function isRefsEqual(v1, v2) {
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('!PRODUCTION || TESTING')) {
|
||||
assert(v1 instanceof Ref && v2 instanceof Ref,
|
||||
'isRefsEqual: Both parameters should be `Ref`s.');
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("!PRODUCTION || TESTING")
|
||||
) {
|
||||
assert(
|
||||
v1 instanceof Ref && v2 instanceof Ref,
|
||||
"isRefsEqual: Both parameters should be `Ref`s."
|
||||
);
|
||||
}
|
||||
return v1.num === v2.num && v1.gen === v2.gen;
|
||||
}
|
||||
|
||||
function isStream(v) {
|
||||
return typeof v === 'object' && v !== null && v.getBytes !== undefined;
|
||||
return typeof v === "object" && v !== null && v.getBytes !== undefined;
|
||||
}
|
||||
|
||||
function clearPrimitiveCaches() {
|
||||
|
@ -14,8 +14,8 @@
|
||||
*/
|
||||
/* eslint no-var: error */
|
||||
|
||||
import { FormatError, isSpace, shadow } from '../shared/util';
|
||||
import { EOF } from './primitives';
|
||||
import { FormatError, isSpace, shadow } from "../shared/util";
|
||||
import { EOF } from "./primitives";
|
||||
|
||||
class PostScriptParser {
|
||||
constructor(lexer) {
|
||||
@ -43,7 +43,8 @@ class PostScriptParser {
|
||||
return true;
|
||||
}
|
||||
throw new FormatError(
|
||||
`Unexpected symbol: found ${this.token.type} expected ${type}.`);
|
||||
`Unexpected symbol: found ${this.token.type} expected ${type}.`
|
||||
);
|
||||
}
|
||||
|
||||
parse() {
|
||||
@ -79,7 +80,7 @@ class PostScriptParser {
|
||||
// The true block is right after the 'if' so it just falls through on true
|
||||
// else it jumps and skips the true block.
|
||||
this.operators[conditionLocation] = this.operators.length;
|
||||
this.operators[conditionLocation + 1] = 'jz';
|
||||
this.operators[conditionLocation + 1] = "jz";
|
||||
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
|
||||
const jumpLocation = this.operators.length;
|
||||
this.operators.push(null, null);
|
||||
@ -89,12 +90,12 @@ class PostScriptParser {
|
||||
this.expect(PostScriptTokenTypes.IFELSE);
|
||||
// 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 + 1] = 'j';
|
||||
this.operators[jumpLocation + 1] = "j";
|
||||
|
||||
this.operators[conditionLocation] = endOfTrue;
|
||||
this.operators[conditionLocation + 1] = 'jz';
|
||||
this.operators[conditionLocation + 1] = "jz";
|
||||
} 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) {
|
||||
return opValue;
|
||||
}
|
||||
return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR,
|
||||
op);
|
||||
return (opCache[op] = new PostScriptToken(
|
||||
PostScriptTokenTypes.OPERATOR,
|
||||
op
|
||||
));
|
||||
}
|
||||
|
||||
static get LBRACE() {
|
||||
return shadow(this, 'LBRACE',
|
||||
new PostScriptToken(PostScriptTokenTypes.LBRACE, '{'));
|
||||
return shadow(
|
||||
this,
|
||||
"LBRACE",
|
||||
new PostScriptToken(PostScriptTokenTypes.LBRACE, "{")
|
||||
);
|
||||
}
|
||||
|
||||
static get RBRACE() {
|
||||
return shadow(this, 'RBRACE',
|
||||
new PostScriptToken(PostScriptTokenTypes.RBRACE, '}'));
|
||||
return shadow(
|
||||
this,
|
||||
"RBRACE",
|
||||
new PostScriptToken(PostScriptTokenTypes.RBRACE, "}")
|
||||
);
|
||||
}
|
||||
|
||||
static get IF() {
|
||||
return shadow(this, 'IF',
|
||||
new PostScriptToken(PostScriptTokenTypes.IF, 'IF'));
|
||||
return shadow(
|
||||
this,
|
||||
"IF",
|
||||
new PostScriptToken(PostScriptTokenTypes.IF, "IF")
|
||||
);
|
||||
}
|
||||
|
||||
static get IFELSE() {
|
||||
return shadow(this, 'IFELSE',
|
||||
new PostScriptToken(PostScriptTokenTypes.IFELSE, 'IFELSE'));
|
||||
return shadow(
|
||||
this,
|
||||
"IFELSE",
|
||||
new PostScriptToken(PostScriptTokenTypes.IFELSE, "IFELSE")
|
||||
);
|
||||
}
|
||||
}
|
||||
return PostScriptToken;
|
||||
@ -172,10 +187,11 @@ class PostScriptLexer {
|
||||
}
|
||||
|
||||
if (comment) {
|
||||
if (ch === 0x0A || ch === 0x0D) {
|
||||
if (ch === 0x0a || ch === 0x0d) {
|
||||
comment = false;
|
||||
}
|
||||
} else if (ch === 0x25) { // '%'
|
||||
} else if (ch === 0x25) {
|
||||
// '%'
|
||||
comment = true;
|
||||
} else if (!isSpace(ch)) {
|
||||
break;
|
||||
@ -183,15 +199,27 @@ class PostScriptLexer {
|
||||
ch = this.nextChar();
|
||||
}
|
||||
switch (ch | 0) {
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
|
||||
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: // '{'
|
||||
case 0x30:
|
||||
case 0x31:
|
||||
case 0x32:
|
||||
case 0x33:
|
||||
case 0x34: // '0'-'4'
|
||||
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();
|
||||
return PostScriptToken.LBRACE;
|
||||
case 0x7D: // '}'
|
||||
case 0x7d: // '}'
|
||||
this.nextChar();
|
||||
return PostScriptToken.RBRACE;
|
||||
}
|
||||
@ -200,15 +228,17 @@ class PostScriptLexer {
|
||||
strBuf.length = 0;
|
||||
strBuf[0] = String.fromCharCode(ch);
|
||||
|
||||
while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
|
||||
((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
|
||||
while (
|
||||
(ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
|
||||
((ch >= 0x41 && ch <= 0x5a) || (ch >= 0x61 && ch <= 0x7a))
|
||||
) {
|
||||
strBuf.push(String.fromCharCode(ch));
|
||||
}
|
||||
const str = strBuf.join('');
|
||||
const str = strBuf.join("");
|
||||
switch (str.toLowerCase()) {
|
||||
case 'if':
|
||||
case "if":
|
||||
return PostScriptToken.IF;
|
||||
case 'ifelse':
|
||||
case "ifelse":
|
||||
return PostScriptToken.IFELSE;
|
||||
default:
|
||||
return PostScriptToken.getOperator(str);
|
||||
@ -222,14 +252,18 @@ class PostScriptLexer {
|
||||
strBuf[0] = String.fromCharCode(ch);
|
||||
|
||||
while ((ch = this.nextChar()) >= 0) {
|
||||
if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
|
||||
ch === 0x2D || ch === 0x2E) { // '-', '.'
|
||||
if (
|
||||
(ch >= 0x30 && ch <= 0x39) || // '0'-'9'
|
||||
ch === 0x2d ||
|
||||
ch === 0x2e
|
||||
) {
|
||||
// '-', '.'
|
||||
strBuf.push(String.fromCharCode(ch));
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const value = parseFloat(strBuf.join(''));
|
||||
const value = parseFloat(strBuf.join(""));
|
||||
if (isNaN(value)) {
|
||||
throw new FormatError(`Invalid floating point number: ${value}`);
|
||||
}
|
||||
@ -237,7 +271,4 @@ class PostScriptLexer {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PostScriptLexer,
|
||||
PostScriptParser,
|
||||
};
|
||||
export { PostScriptLexer, PostScriptParser };
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,17 +20,22 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
FormatError, isSpace, stringToBytes, unreachable
|
||||
} from '../shared/util';
|
||||
import { isDict } from './primitives';
|
||||
FormatError,
|
||||
isSpace,
|
||||
stringToBytes,
|
||||
unreachable,
|
||||
} from "../shared/util";
|
||||
import { isDict } from "./primitives";
|
||||
|
||||
var Stream = (function StreamClosure() {
|
||||
function Stream(arrayBuffer, start, length, dict) {
|
||||
this.bytes = (arrayBuffer instanceof Uint8Array ?
|
||||
arrayBuffer : new Uint8Array(arrayBuffer));
|
||||
this.bytes =
|
||||
arrayBuffer instanceof Uint8Array
|
||||
? arrayBuffer
|
||||
: new Uint8Array(arrayBuffer);
|
||||
this.start = start || 0;
|
||||
this.pos = this.start;
|
||||
this.end = (start + length) || this.bytes.length;
|
||||
this.end = start + length || this.bytes.length;
|
||||
this.dict = dict;
|
||||
}
|
||||
|
||||
@ -73,7 +78,7 @@ var Stream = (function StreamClosure() {
|
||||
if (!length) {
|
||||
let subarray = bytes.subarray(pos, strEnd);
|
||||
// `this.bytes` is always a `Uint8Array` here.
|
||||
return (forceClamped ? new Uint8ClampedArray(subarray) : subarray);
|
||||
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
|
||||
}
|
||||
var end = pos + length;
|
||||
if (end > strEnd) {
|
||||
@ -82,7 +87,7 @@ var Stream = (function StreamClosure() {
|
||||
this.pos = end;
|
||||
let subarray = bytes.subarray(pos, end);
|
||||
// `this.bytes` is always a `Uint8Array` here.
|
||||
return (forceClamped ? new Uint8ClampedArray(subarray) : subarray);
|
||||
return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
|
||||
},
|
||||
peekByte: function Stream_peekByte() {
|
||||
var peekedByte = this.getByte();
|
||||
@ -208,7 +213,8 @@ var DecodeStream = (function DecodeStreamClosure() {
|
||||
return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
|
||||
},
|
||||
getBytes(length, forceClamped = false) {
|
||||
var end, pos = this.pos;
|
||||
var end,
|
||||
pos = this.pos;
|
||||
|
||||
if (length) {
|
||||
this.ensureBuffer(pos + length);
|
||||
@ -231,8 +237,9 @@ var DecodeStream = (function DecodeStreamClosure() {
|
||||
this.pos = end;
|
||||
let subarray = this.buffer.subarray(pos, end);
|
||||
// `this.buffer` is either a `Uint8Array` or `Uint8ClampedArray` here.
|
||||
return (forceClamped && !(subarray instanceof Uint8ClampedArray) ?
|
||||
new Uint8ClampedArray(subarray) : subarray);
|
||||
return forceClamped && !(subarray instanceof Uint8ClampedArray)
|
||||
? new Uint8ClampedArray(subarray)
|
||||
: subarray;
|
||||
},
|
||||
peekByte: function DecodeStream_peekByte() {
|
||||
var peekedByte = this.getByte();
|
||||
@ -255,7 +262,7 @@ var DecodeStream = (function DecodeStreamClosure() {
|
||||
},
|
||||
|
||||
getByteRange(begin, end) {
|
||||
unreachable('Should not call DecodeStream.getByteRange');
|
||||
unreachable("Should not call DecodeStream.getByteRange");
|
||||
},
|
||||
|
||||
skip: function DecodeStream_skip(n) {
|
||||
@ -296,9 +303,7 @@ var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
|
||||
|
||||
StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
StreamsSequenceStream.prototype.readBlock =
|
||||
function streamSequenceStreamReadBlock() {
|
||||
|
||||
StreamsSequenceStream.prototype.readBlock = function streamSequenceStreamReadBlock() {
|
||||
var streams = this.streams;
|
||||
if (streams.length === 0) {
|
||||
this.eof = true;
|
||||
@ -313,9 +318,7 @@ var StreamsSequenceStream = (function StreamsSequenceStreamClosure() {
|
||||
this.bufferLength = newLength;
|
||||
};
|
||||
|
||||
StreamsSequenceStream.prototype.getBaseStreams =
|
||||
function StreamsSequenceStream_getBaseStreams() {
|
||||
|
||||
StreamsSequenceStream.prototype.getBaseStreams = function StreamsSequenceStream_getBaseStreams() {
|
||||
var baseStreams = [];
|
||||
for (var i = 0, ii = this.streams.length; i < ii; i++) {
|
||||
var stream = this.streams[i];
|
||||
@ -434,19 +437,18 @@ var FlateStream = (function FlateStreamClosure() {
|
||||
var cmf = str.getByte();
|
||||
var flg = str.getByte();
|
||||
if (cmf === -1 || flg === -1) {
|
||||
throw new FormatError(
|
||||
`Invalid header in flate stream: ${cmf}, ${flg}`);
|
||||
throw new FormatError(`Invalid header in flate stream: ${cmf}, ${flg}`);
|
||||
}
|
||||
if ((cmf & 0x0f) !== 0x08) {
|
||||
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}`);
|
||||
}
|
||||
if (flg & 0x20) {
|
||||
throw new FormatError(
|
||||
`FDICT bit set in flate stream: ${cmf}, ${flg}`);
|
||||
throw new FormatError(`FDICT bit set in flate stream: ${cmf}, ${flg}`);
|
||||
}
|
||||
|
||||
this.codeSize = 0;
|
||||
@ -465,7 +467,7 @@ var FlateStream = (function FlateStreamClosure() {
|
||||
var b;
|
||||
while (codeSize < bits) {
|
||||
if ((b = str.getByte()) === -1) {
|
||||
throw new FormatError('Bad encoding in flate stream');
|
||||
throw new FormatError("Bad encoding in flate stream");
|
||||
}
|
||||
codeBuf |= b << codeSize;
|
||||
codeSize += 8;
|
||||
@ -491,22 +493,23 @@ var FlateStream = (function FlateStreamClosure() {
|
||||
// codeSize < codeLen check below guards against incomplete codeVal.
|
||||
break;
|
||||
}
|
||||
codeBuf |= (b << codeSize);
|
||||
codeBuf |= b << codeSize;
|
||||
codeSize += 8;
|
||||
}
|
||||
var code = codes[codeBuf & ((1 << maxLen) - 1)];
|
||||
var codeLen = code >> 16;
|
||||
var codeVal = code & 0xffff;
|
||||
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.codeSize = (codeSize - codeLen);
|
||||
this.codeBuf = codeBuf >> codeLen;
|
||||
this.codeSize = codeSize - codeLen;
|
||||
return codeVal;
|
||||
};
|
||||
|
||||
FlateStream.prototype.generateHuffmanTable =
|
||||
function flateStreamGenerateHuffmanTable(lengths) {
|
||||
FlateStream.prototype.generateHuffmanTable = function flateStreamGenerateHuffmanTable(
|
||||
lengths
|
||||
) {
|
||||
var n = lengths.length;
|
||||
|
||||
// find max code length
|
||||
@ -521,9 +524,11 @@ var FlateStream = (function FlateStreamClosure() {
|
||||
// build the table
|
||||
var size = 1 << maxLen;
|
||||
var codes = new Int32Array(size);
|
||||
for (var len = 1, code = 0, skip = 2;
|
||||
for (
|
||||
var len = 1, code = 0, skip = 2;
|
||||
len <= maxLen;
|
||||
++len, code <<= 1, skip <<= 1) {
|
||||
++len, code <<= 1, skip <<= 1
|
||||
) {
|
||||
for (var val = 0; val < n; ++val) {
|
||||
if (lengths[val] === len) {
|
||||
// bit-reverse the code
|
||||
@ -556,36 +561,36 @@ var FlateStream = (function FlateStreamClosure() {
|
||||
}
|
||||
hdr >>= 1;
|
||||
|
||||
if (hdr === 0) { // uncompressed block
|
||||
if (hdr === 0) {
|
||||
// uncompressed block
|
||||
var b;
|
||||
|
||||
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;
|
||||
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) {
|
||||
throw new FormatError('Bad block header in flate stream');
|
||||
throw new FormatError("Bad block header in flate stream");
|
||||
}
|
||||
var check = b;
|
||||
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);
|
||||
if (check !== (~blockLen & 0xffff) &&
|
||||
(blockLen !== 0 || check !== 0)) {
|
||||
check |= b << 8;
|
||||
if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) {
|
||||
// Ignoring error for bad "empty" block (see issue 1277)
|
||||
throw new FormatError(
|
||||
'Bad uncompressed block length in flate stream');
|
||||
throw new FormatError("Bad uncompressed block length in flate stream");
|
||||
}
|
||||
|
||||
this.codeBuf = 0;
|
||||
this.codeSize = 0;
|
||||
|
||||
const bufferLength = this.bufferLength, end = bufferLength + blockLen;
|
||||
const bufferLength = this.bufferLength,
|
||||
end = bufferLength + blockLen;
|
||||
buffer = this.ensureBuffer(end);
|
||||
this.bufferLength = end;
|
||||
|
||||
@ -605,10 +610,12 @@ var FlateStream = (function FlateStreamClosure() {
|
||||
|
||||
var litCodeTable;
|
||||
var distCodeTable;
|
||||
if (hdr === 1) { // compressed block, fixed codes
|
||||
if (hdr === 1) {
|
||||
// compressed block, fixed codes
|
||||
litCodeTable = fixedLitCodeTab;
|
||||
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 numDistCodes = this.getBits(5) + 1;
|
||||
var numCodeLenCodes = this.getBits(4) + 4;
|
||||
@ -631,11 +638,17 @@ var FlateStream = (function FlateStreamClosure() {
|
||||
while (i < codes) {
|
||||
var code = this.getCode(codeLenCodeTab);
|
||||
if (code === 16) {
|
||||
bitsLength = 2; bitsOffset = 3; what = len;
|
||||
bitsLength = 2;
|
||||
bitsOffset = 3;
|
||||
what = len;
|
||||
} else if (code === 17) {
|
||||
bitsLength = 3; bitsOffset = 3; what = (len = 0);
|
||||
bitsLength = 3;
|
||||
bitsOffset = 3;
|
||||
what = len = 0;
|
||||
} else if (code === 18) {
|
||||
bitsLength = 7; bitsOffset = 11; what = (len = 0);
|
||||
bitsLength = 7;
|
||||
bitsOffset = 11;
|
||||
what = len = 0;
|
||||
} else {
|
||||
codeLengths[i++] = len = code;
|
||||
continue;
|
||||
@ -647,12 +660,14 @@ var FlateStream = (function FlateStreamClosure() {
|
||||
}
|
||||
}
|
||||
|
||||
litCodeTable =
|
||||
this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));
|
||||
distCodeTable =
|
||||
this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));
|
||||
litCodeTable = this.generateHuffmanTable(
|
||||
codeLengths.subarray(0, numLitCodes)
|
||||
);
|
||||
distCodeTable = this.generateHuffmanTable(
|
||||
codeLengths.subarray(numLitCodes, codes)
|
||||
);
|
||||
} else {
|
||||
throw new FormatError('Unknown block type in flate stream');
|
||||
throw new FormatError("Unknown block type in flate stream");
|
||||
}
|
||||
|
||||
buffer = this.buffer;
|
||||
@ -704,7 +719,7 @@ var PredictorStream = (function PredictorStreamClosure() {
|
||||
if (!isDict(params)) {
|
||||
return str; // no prediction
|
||||
}
|
||||
var predictor = this.predictor = params.get('Predictor') || 1;
|
||||
var predictor = (this.predictor = params.get("Predictor") || 1);
|
||||
|
||||
if (predictor <= 1) {
|
||||
return str; // no prediction
|
||||
@ -722,9 +737,9 @@ var PredictorStream = (function PredictorStreamClosure() {
|
||||
this.str = str;
|
||||
this.dict = str.dict;
|
||||
|
||||
var colors = this.colors = params.get('Colors') || 1;
|
||||
var bits = this.bits = params.get('BitsPerComponent') || 8;
|
||||
var columns = this.columns = params.get('Columns') || 1;
|
||||
var colors = (this.colors = params.get("Colors") || 1);
|
||||
var bits = (this.bits = params.get("BitsPerComponent") || 8);
|
||||
var columns = (this.columns = params.get("Columns") || 1);
|
||||
|
||||
this.pixBytes = (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.readBlockTiff =
|
||||
function predictorStreamReadBlockTiff() {
|
||||
PredictorStream.prototype.readBlockTiff = function predictorStreamReadBlockTiff() {
|
||||
var rowBytes = this.rowBytes;
|
||||
|
||||
var bufferLength = this.bufferLength;
|
||||
@ -751,8 +765,10 @@ var PredictorStream = (function PredictorStreamClosure() {
|
||||
return;
|
||||
}
|
||||
|
||||
var inbuf = 0, outbuf = 0;
|
||||
var inbits = 0, outbits = 0;
|
||||
var inbuf = 0,
|
||||
outbuf = 0;
|
||||
var inbits = 0,
|
||||
outbits = 0;
|
||||
var pos = bufferLength;
|
||||
var i;
|
||||
|
||||
@ -781,46 +797,46 @@ var PredictorStream = (function PredictorStreamClosure() {
|
||||
buffer[pos++] = rawBytes[i];
|
||||
}
|
||||
for (; i < rowBytes; i += 2) {
|
||||
var sum = ((rawBytes[i] & 0xFF) << 8) +
|
||||
(rawBytes[i + 1] & 0xFF) +
|
||||
((buffer[pos - bytesPerPixel] & 0xFF) << 8) +
|
||||
(buffer[pos - bytesPerPixel + 1] & 0xFF);
|
||||
buffer[pos++] = ((sum >> 8) & 0xFF);
|
||||
buffer[pos++] = (sum & 0xFF);
|
||||
var sum =
|
||||
((rawBytes[i] & 0xff) << 8) +
|
||||
(rawBytes[i + 1] & 0xff) +
|
||||
((buffer[pos - bytesPerPixel] & 0xff) << 8) +
|
||||
(buffer[pos - bytesPerPixel + 1] & 0xff);
|
||||
buffer[pos++] = (sum >> 8) & 0xff;
|
||||
buffer[pos++] = sum & 0xff;
|
||||
}
|
||||
} else {
|
||||
var compArray = new Uint8Array(colors + 1);
|
||||
var bitMask = (1 << bits) - 1;
|
||||
var j = 0, k = bufferLength;
|
||||
var j = 0,
|
||||
k = bufferLength;
|
||||
var columns = this.columns;
|
||||
for (i = 0; i < columns; ++i) {
|
||||
for (var kk = 0; kk < colors; ++kk) {
|
||||
if (inbits < bits) {
|
||||
inbuf = (inbuf << 8) | (rawBytes[j++] & 0xFF);
|
||||
inbuf = (inbuf << 8) | (rawBytes[j++] & 0xff);
|
||||
inbits += 8;
|
||||
}
|
||||
compArray[kk] = (compArray[kk] +
|
||||
(inbuf >> (inbits - bits))) & bitMask;
|
||||
compArray[kk] =
|
||||
(compArray[kk] + (inbuf >> (inbits - bits))) & bitMask;
|
||||
inbits -= bits;
|
||||
outbuf = (outbuf << bits) | compArray[kk];
|
||||
outbits += bits;
|
||||
if (outbits >= 8) {
|
||||
buffer[k++] = (outbuf >> (outbits - 8)) & 0xFF;
|
||||
buffer[k++] = (outbuf >> (outbits - 8)) & 0xff;
|
||||
outbits -= 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (outbits > 0) {
|
||||
buffer[k++] = (outbuf << (8 - outbits)) +
|
||||
(inbuf & ((1 << (8 - outbits)) - 1));
|
||||
buffer[k++] =
|
||||
(outbuf << (8 - outbits)) + (inbuf & ((1 << (8 - outbits)) - 1));
|
||||
}
|
||||
}
|
||||
this.bufferLength += rowBytes;
|
||||
};
|
||||
|
||||
PredictorStream.prototype.readBlockPng =
|
||||
function predictorStreamReadBlockPng() {
|
||||
|
||||
PredictorStream.prototype.readBlockPng = function predictorStreamReadBlockPng() {
|
||||
var rowBytes = this.rowBytes;
|
||||
var pixBytes = this.pixBytes;
|
||||
|
||||
@ -839,7 +855,10 @@ var PredictorStream = (function PredictorStreamClosure() {
|
||||
prevRow = new Uint8Array(rowBytes);
|
||||
}
|
||||
|
||||
var i, j = bufferLength, up, c;
|
||||
var i,
|
||||
j = bufferLength,
|
||||
up,
|
||||
c;
|
||||
switch (predictor) {
|
||||
case 0:
|
||||
for (i = 0; i < rowBytes; ++i) {
|
||||
@ -851,13 +870,13 @@ var PredictorStream = (function PredictorStreamClosure() {
|
||||
buffer[j++] = rawBytes[i];
|
||||
}
|
||||
for (; i < rowBytes; ++i) {
|
||||
buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xFF;
|
||||
buffer[j] = (buffer[j - pixBytes] + rawBytes[i]) & 0xff;
|
||||
j++;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for (i = 0; i < rowBytes; ++i) {
|
||||
buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xFF;
|
||||
buffer[j++] = (prevRow[i] + rawBytes[i]) & 0xff;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
@ -865,8 +884,8 @@ var PredictorStream = (function PredictorStreamClosure() {
|
||||
buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
|
||||
}
|
||||
for (; i < rowBytes; ++i) {
|
||||
buffer[j] = (((prevRow[i] + buffer[j - pixBytes]) >> 1) +
|
||||
rawBytes[i]) & 0xFF;
|
||||
buffer[j] =
|
||||
(((prevRow[i] + buffer[j - pixBytes]) >> 1) + rawBytes[i]) & 0xff;
|
||||
j++;
|
||||
}
|
||||
break;
|
||||
@ -950,7 +969,8 @@ var DecryptStream = (function DecryptStreamClosure() {
|
||||
chunk = decrypt(chunk, !hasMoreData);
|
||||
|
||||
var bufferLength = this.bufferLength;
|
||||
var i, n = chunk.length;
|
||||
var i,
|
||||
n = chunk.length;
|
||||
var buffer = this.ensureBuffer(bufferLength + n);
|
||||
for (i = 0; i < n; i++) {
|
||||
buffer[bufferLength++] = chunk[i];
|
||||
@ -978,8 +998,8 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
|
||||
Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
|
||||
|
||||
Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
|
||||
var TILDA_CHAR = 0x7E; // '~'
|
||||
var Z_LOWER_CHAR = 0x7A; // 'z'
|
||||
var TILDA_CHAR = 0x7e; // '~'
|
||||
var Z_LOWER_CHAR = 0x7a; // 'z'
|
||||
var EOF = -1;
|
||||
|
||||
var str = this.str;
|
||||
@ -994,7 +1014,8 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
|
||||
return;
|
||||
}
|
||||
|
||||
var bufferLength = this.bufferLength, buffer;
|
||||
var bufferLength = this.bufferLength,
|
||||
buffer;
|
||||
var i;
|
||||
|
||||
// special code for z
|
||||
@ -1035,7 +1056,7 @@ var Ascii85Stream = (function Ascii85StreamClosure() {
|
||||
}
|
||||
|
||||
for (i = 3; i >= 0; --i) {
|
||||
buffer[bufferLength + i] = t & 0xFF;
|
||||
buffer[bufferLength + i] = t & 0xff;
|
||||
t >>= 8;
|
||||
}
|
||||
}
|
||||
@ -1075,16 +1096,20 @@ var AsciiHexStream = (function AsciiHexStreamClosure() {
|
||||
|
||||
var firstDigit = this.firstDigit;
|
||||
for (var i = 0, ii = bytes.length; i < ii; i++) {
|
||||
var ch = bytes[i], digit;
|
||||
if (ch >= 0x30 && ch <= 0x39) { // '0'-'9'
|
||||
digit = ch & 0x0F;
|
||||
var ch = bytes[i],
|
||||
digit;
|
||||
if (ch >= 0x30 && ch <= 0x39) {
|
||||
// '0'-'9'
|
||||
digit = ch & 0x0f;
|
||||
} else if ((ch >= 0x41 && ch <= 0x46) || (ch >= 0x61 && ch <= 0x66)) {
|
||||
// 'A'-'Z', 'a'-'z'
|
||||
digit = (ch & 0x0F) + 9;
|
||||
} else if (ch === 0x3E) { // '>'
|
||||
digit = (ch & 0x0f) + 9;
|
||||
} else if (ch === 0x3e) {
|
||||
// '>'
|
||||
this.eof = true;
|
||||
break;
|
||||
} else { // probably whitespace
|
||||
} else {
|
||||
// probably whitespace
|
||||
continue; // ignoring
|
||||
}
|
||||
if (firstDigit < 0) {
|
||||
@ -1096,7 +1121,7 @@ var AsciiHexStream = (function AsciiHexStreamClosure() {
|
||||
}
|
||||
if (firstDigit >= 0 && this.eof) {
|
||||
// incomplete byte
|
||||
buffer[bufferLength++] = (firstDigit << 4);
|
||||
buffer[bufferLength++] = firstDigit << 4;
|
||||
firstDigit = -1;
|
||||
}
|
||||
this.firstDigit = firstDigit;
|
||||
@ -1194,7 +1219,7 @@ var LZWStream = (function LZWStreamClosure() {
|
||||
cachedData = (cachedData << 8) | c;
|
||||
bitsCached += 8;
|
||||
}
|
||||
this.bitsCached = (bitsCached -= n);
|
||||
this.bitsCached = bitsCached -= n;
|
||||
this.cachedData = cachedData;
|
||||
this.lastCode = null;
|
||||
return (cachedData >>> bitsCached) & ((1 << n) - 1);
|
||||
@ -1202,7 +1227,8 @@ var LZWStream = (function LZWStreamClosure() {
|
||||
|
||||
LZWStream.prototype.readBlock = function LZWStream_readBlock() {
|
||||
var blockSize = 512;
|
||||
var estimatedDecodedSize = blockSize * 2, decodedSizeDelta = blockSize;
|
||||
var estimatedDecodedSize = blockSize * 2,
|
||||
decodedSizeDelta = blockSize;
|
||||
var i, j, q;
|
||||
|
||||
var lzwState = this.lzwState;
|
||||
@ -1256,9 +1282,13 @@ var LZWStream = (function LZWStreamClosure() {
|
||||
dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
|
||||
dictionaryValues[nextCode] = currentSequence[0];
|
||||
nextCode++;
|
||||
codeLength = (nextCode + earlyChange) & (nextCode + earlyChange - 1) ?
|
||||
codeLength : Math.min(Math.log(nextCode + earlyChange) /
|
||||
0.6931471805599453 + 1, 12) | 0;
|
||||
codeLength =
|
||||
(nextCode + earlyChange) & (nextCode + earlyChange - 1)
|
||||
? codeLength
|
||||
: Math.min(
|
||||
Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1,
|
||||
12
|
||||
) | 0;
|
||||
}
|
||||
prevCode = code;
|
||||
|
||||
|
@ -13,9 +13,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { isSpace, warn } from '../shared/util';
|
||||
import { getEncoding } from './encodings';
|
||||
import { Stream } from './stream';
|
||||
import { isSpace, warn } from "../shared/util";
|
||||
import { getEncoding } from "./encodings";
|
||||
import { Stream } from "./stream";
|
||||
|
||||
// Hinting is currently disabled due to unknown problems on windows
|
||||
// in tracemonkey and various other pdfs with type1 fonts.
|
||||
@ -61,21 +61,21 @@ var HINTING_ENABLED = false;
|
||||
*/
|
||||
var Type1CharString = (function Type1CharStringClosure() {
|
||||
var COMMAND_MAP = {
|
||||
'hstem': [1],
|
||||
'vstem': [3],
|
||||
'vmoveto': [4],
|
||||
'rlineto': [5],
|
||||
'hlineto': [6],
|
||||
'vlineto': [7],
|
||||
'rrcurveto': [8],
|
||||
'callsubr': [10],
|
||||
'flex': [12, 35],
|
||||
'drop': [12, 18],
|
||||
'endchar': [14],
|
||||
'rmoveto': [21],
|
||||
'hmoveto': [22],
|
||||
'vhcurveto': [30],
|
||||
'hvcurveto': [31],
|
||||
hstem: [1],
|
||||
vstem: [3],
|
||||
vmoveto: [4],
|
||||
rlineto: [5],
|
||||
hlineto: [6],
|
||||
vlineto: [7],
|
||||
rrcurveto: [8],
|
||||
callsubr: [10],
|
||||
flex: [12, 35],
|
||||
drop: [12, 18],
|
||||
endchar: [14],
|
||||
rmoveto: [21],
|
||||
hmoveto: [22],
|
||||
vhcurveto: [30],
|
||||
hvcurveto: [31],
|
||||
};
|
||||
|
||||
function Type1CharString() {
|
||||
@ -87,8 +87,11 @@ var Type1CharString = (function Type1CharStringClosure() {
|
||||
}
|
||||
|
||||
Type1CharString.prototype = {
|
||||
convert: function Type1CharString_convert(encoded, subrs,
|
||||
seacAnalysisEnabled) {
|
||||
convert: function Type1CharString_convert(
|
||||
encoded,
|
||||
subrs,
|
||||
seacAnalysisEnabled
|
||||
) {
|
||||
var count = encoded.length;
|
||||
var error = false;
|
||||
var wx, sbx, subrNumber;
|
||||
@ -154,8 +157,11 @@ var Type1CharString = (function Type1CharStringClosure() {
|
||||
error = true;
|
||||
break;
|
||||
}
|
||||
error = this.convert(subrs[subrNumber], subrs,
|
||||
seacAnalysisEnabled);
|
||||
error = this.convert(
|
||||
subrs[subrNumber],
|
||||
subrs,
|
||||
seacAnalysisEnabled
|
||||
);
|
||||
break;
|
||||
case 11: // return
|
||||
return error;
|
||||
@ -308,12 +314,15 @@ var Type1CharString = (function Type1CharStringClosure() {
|
||||
} else if (value <= 246) {
|
||||
value = value - 139;
|
||||
} else if (value <= 250) {
|
||||
value = ((value - 247) * 256) + encoded[++i] + 108;
|
||||
value = (value - 247) * 256 + encoded[++i] + 108;
|
||||
} else if (value <= 254) {
|
||||
value = -((value - 251) * 256) - encoded[++i] - 108;
|
||||
} else {
|
||||
value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 |
|
||||
(encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;
|
||||
value =
|
||||
((encoded[++i] & 0xff) << 24) |
|
||||
((encoded[++i] & 0xff) << 16) |
|
||||
((encoded[++i] & 0xff) << 8) |
|
||||
((encoded[++i] & 0xff) << 0);
|
||||
}
|
||||
this.stack.push(value);
|
||||
}
|
||||
@ -330,13 +339,16 @@ var Type1CharString = (function Type1CharStringClosure() {
|
||||
var value = this.stack[i];
|
||||
if (Number.isInteger(value)) {
|
||||
this.output.push(28, (value >> 8) & 0xff, value & 0xff);
|
||||
} else { // fixed point
|
||||
} else {
|
||||
// fixed point
|
||||
value = (65536 * value) | 0;
|
||||
this.output.push(255,
|
||||
(value >> 24) & 0xFF,
|
||||
(value >> 16) & 0xFF,
|
||||
(value >> 8) & 0xFF,
|
||||
value & 0xFF);
|
||||
this.output.push(
|
||||
255,
|
||||
(value >> 24) & 0xff,
|
||||
(value >> 16) & 0xff,
|
||||
(value >> 8) & 0xff,
|
||||
value & 0xff
|
||||
);
|
||||
}
|
||||
}
|
||||
this.output.push.apply(this.output, command);
|
||||
@ -370,16 +382,22 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
var CHAR_STRS_ENCRYPT_KEY = 4330;
|
||||
|
||||
function isHexDigit(code) {
|
||||
return code >= 48 && code <= 57 || // '0'-'9'
|
||||
code >= 65 && code <= 70 || // 'A'-'F'
|
||||
code >= 97 && code <= 102; // 'a'-'f'
|
||||
return (
|
||||
(code >= 48 && code <= 57) || // '0'-'9'
|
||||
(code >= 65 && code <= 70) || // 'A'-'F'
|
||||
(code >= 97 && code <= 102)
|
||||
); // 'a'-'f'
|
||||
}
|
||||
|
||||
function decrypt(data, key, discardNumber) {
|
||||
if (discardNumber >= data.length) {
|
||||
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++) {
|
||||
r = ((data[i] + r) * c1 + c2) & ((1 << 16) - 1);
|
||||
}
|
||||
@ -394,8 +412,11 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
}
|
||||
|
||||
function decryptAscii(data, key, discardNumber) {
|
||||
var r = key | 0, c1 = 52845, c2 = 22719;
|
||||
var count = data.length, maybeLength = count >>> 1;
|
||||
var r = key | 0,
|
||||
c1 = 52845,
|
||||
c2 = 22719;
|
||||
var count = data.length,
|
||||
maybeLength = count >>> 1;
|
||||
var decrypted = new Uint8Array(maybeLength);
|
||||
var i, j;
|
||||
for (i = 0, j = 0; i < count; i++) {
|
||||
@ -405,7 +426,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
}
|
||||
i++;
|
||||
var digit2;
|
||||
while (i < count && !isHexDigit(digit2 = data[i])) {
|
||||
while (i < count && !isHexDigit((digit2 = data[i]))) {
|
||||
i++;
|
||||
}
|
||||
if (i < count) {
|
||||
@ -418,19 +439,31 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
}
|
||||
|
||||
function isSpecial(c) {
|
||||
return c === 0x2F || // '/'
|
||||
c === 0x5B || c === 0x5D || // '[', ']'
|
||||
c === 0x7B || c === 0x7D || // '{', '}'
|
||||
c === 0x28 || c === 0x29; // '(', ')'
|
||||
return (
|
||||
c === 0x2f || // '/'
|
||||
c === 0x5b ||
|
||||
c === 0x5d || // '[', ']'
|
||||
c === 0x7b ||
|
||||
c === 0x7d || // '{', '}'
|
||||
c === 0x28 ||
|
||||
c === 0x29
|
||||
); // '(', ')'
|
||||
}
|
||||
|
||||
function Type1Parser(stream, encrypted, seacAnalysisEnabled) {
|
||||
if (encrypted) {
|
||||
var data = stream.getBytes();
|
||||
var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) &&
|
||||
isHexDigit(data[2]) && isHexDigit(data[3]));
|
||||
stream = new Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) :
|
||||
decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
|
||||
var isBinary = !(
|
||||
isHexDigit(data[0]) &&
|
||||
isHexDigit(data[1]) &&
|
||||
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;
|
||||
|
||||
@ -444,7 +477,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
var array = [];
|
||||
while (true) {
|
||||
var token = this.getToken();
|
||||
if (token === null || token === ']' || token === '}') {
|
||||
if (token === null || token === "]" || token === "}") {
|
||||
break;
|
||||
}
|
||||
array.push(parseFloat(token || 0));
|
||||
@ -468,7 +501,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
var token = this.getToken();
|
||||
|
||||
// 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() {
|
||||
@ -485,10 +518,11 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
}
|
||||
|
||||
if (comment) {
|
||||
if (ch === 0x0A || ch === 0x0D) {
|
||||
if (ch === 0x0a || ch === 0x0d) {
|
||||
comment = false;
|
||||
}
|
||||
} else if (ch === 0x25) { // '%'
|
||||
} else if (ch === 0x25) {
|
||||
// '%'
|
||||
comment = true;
|
||||
} else if (!isSpace(ch)) {
|
||||
break;
|
||||
@ -499,7 +533,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
this.nextChar();
|
||||
return String.fromCharCode(ch);
|
||||
}
|
||||
var token = '';
|
||||
var token = "";
|
||||
do {
|
||||
token += String.fromCharCode(ch);
|
||||
ch = this.nextChar();
|
||||
@ -523,24 +557,25 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
extractFontProgram: function Type1Parser_extractFontProgram(properties) {
|
||||
var stream = this.stream;
|
||||
|
||||
var subrs = [], charstrings = [];
|
||||
var subrs = [],
|
||||
charstrings = [];
|
||||
var privateData = Object.create(null);
|
||||
privateData['lenIV'] = 4;
|
||||
privateData["lenIV"] = 4;
|
||||
var program = {
|
||||
subrs: [],
|
||||
charstrings: [],
|
||||
properties: {
|
||||
'privateData': privateData,
|
||||
privateData,
|
||||
},
|
||||
};
|
||||
var token, length, data, lenIV, encoded;
|
||||
while ((token = this.getToken()) !== null) {
|
||||
if (token !== '/') {
|
||||
if (token !== "/") {
|
||||
continue;
|
||||
}
|
||||
token = this.getToken();
|
||||
switch (token) {
|
||||
case 'CharStrings':
|
||||
case "CharStrings":
|
||||
// The number immediately following CharStrings must be greater or
|
||||
// equal to the number of CharStrings.
|
||||
this.getToken();
|
||||
@ -549,22 +584,22 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
this.getToken(); // read in 'begin'
|
||||
while (true) {
|
||||
token = this.getToken();
|
||||
if (token === null || token === 'end') {
|
||||
if (token === null || token === "end") {
|
||||
break;
|
||||
}
|
||||
|
||||
if (token !== '/') {
|
||||
if (token !== "/") {
|
||||
continue;
|
||||
}
|
||||
var glyph = this.getToken();
|
||||
length = this.readInt();
|
||||
this.getToken(); // read in 'RD' or '-|'
|
||||
data = (length > 0 ? stream.getBytes(length) : new Uint8Array(0));
|
||||
lenIV = program.properties.privateData['lenIV'];
|
||||
data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
|
||||
lenIV = program.properties.privateData["lenIV"];
|
||||
encoded = this.readCharStrings(data, lenIV);
|
||||
this.nextChar();
|
||||
token = this.getToken(); // read in 'ND' or '|-'
|
||||
if (token === 'noaccess') {
|
||||
if (token === "noaccess") {
|
||||
this.getToken(); // read in 'def'
|
||||
}
|
||||
charstrings.push({
|
||||
@ -573,54 +608,56 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'Subrs':
|
||||
case "Subrs":
|
||||
this.readInt(); // num
|
||||
this.getToken(); // read in 'array'
|
||||
while (this.getToken() === 'dup') {
|
||||
while (this.getToken() === "dup") {
|
||||
var index = this.readInt();
|
||||
length = this.readInt();
|
||||
this.getToken(); // read in 'RD' or '-|'
|
||||
data = (length > 0 ? stream.getBytes(length) : new Uint8Array(0));
|
||||
lenIV = program.properties.privateData['lenIV'];
|
||||
data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
|
||||
lenIV = program.properties.privateData["lenIV"];
|
||||
encoded = this.readCharStrings(data, lenIV);
|
||||
this.nextChar();
|
||||
token = this.getToken(); // read in 'NP' or '|'
|
||||
if (token === 'noaccess') {
|
||||
if (token === "noaccess") {
|
||||
this.getToken(); // read in 'put'
|
||||
}
|
||||
subrs[index] = encoded;
|
||||
}
|
||||
break;
|
||||
case 'BlueValues':
|
||||
case 'OtherBlues':
|
||||
case 'FamilyBlues':
|
||||
case 'FamilyOtherBlues':
|
||||
case "BlueValues":
|
||||
case "OtherBlues":
|
||||
case "FamilyBlues":
|
||||
case "FamilyOtherBlues":
|
||||
var blueArray = this.readNumberArray();
|
||||
// *Blue* values may contain invalid data: disables reading of
|
||||
// those values when hinting is disabled.
|
||||
if (blueArray.length > 0 && (blueArray.length % 2) === 0 &&
|
||||
HINTING_ENABLED) {
|
||||
if (
|
||||
blueArray.length > 0 &&
|
||||
blueArray.length % 2 === 0 &&
|
||||
HINTING_ENABLED
|
||||
) {
|
||||
program.properties.privateData[token] = blueArray;
|
||||
}
|
||||
break;
|
||||
case 'StemSnapH':
|
||||
case 'StemSnapV':
|
||||
case "StemSnapH":
|
||||
case "StemSnapV":
|
||||
program.properties.privateData[token] = this.readNumberArray();
|
||||
break;
|
||||
case 'StdHW':
|
||||
case 'StdVW':
|
||||
program.properties.privateData[token] =
|
||||
this.readNumberArray()[0];
|
||||
case "StdHW":
|
||||
case "StdVW":
|
||||
program.properties.privateData[token] = this.readNumberArray()[0];
|
||||
break;
|
||||
case 'BlueShift':
|
||||
case 'lenIV':
|
||||
case 'BlueFuzz':
|
||||
case 'BlueScale':
|
||||
case 'LanguageGroup':
|
||||
case 'ExpansionFactor':
|
||||
case "BlueShift":
|
||||
case "lenIV":
|
||||
case "BlueFuzz":
|
||||
case "BlueScale":
|
||||
case "LanguageGroup":
|
||||
case "ExpansionFactor":
|
||||
program.properties.privateData[token] = this.readNumber();
|
||||
break;
|
||||
case 'ForceBold':
|
||||
case "ForceBold":
|
||||
program.properties.privateData[token] = this.readBoolean();
|
||||
break;
|
||||
}
|
||||
@ -630,8 +667,11 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
glyph = charstrings[i].glyph;
|
||||
encoded = charstrings[i].encoded;
|
||||
var charString = new Type1CharString();
|
||||
var error = charString.convert(encoded, subrs,
|
||||
this.seacAnalysisEnabled);
|
||||
var error = charString.convert(
|
||||
encoded,
|
||||
subrs,
|
||||
this.seacAnalysisEnabled
|
||||
);
|
||||
var output = charString.output;
|
||||
if (error) {
|
||||
// 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).
|
||||
if (properties.builtInEncoding) {
|
||||
const index = properties.builtInEncoding.indexOf(glyph);
|
||||
if (index > -1 && properties.widths[index] === undefined &&
|
||||
index >= properties.firstChar && index <= properties.lastChar) {
|
||||
if (
|
||||
index > -1 &&
|
||||
properties.widths[index] === undefined &&
|
||||
index >= properties.firstChar &&
|
||||
index <= properties.lastChar
|
||||
) {
|
||||
properties.widths[index] = charString.width;
|
||||
}
|
||||
}
|
||||
@ -664,16 +708,16 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
extractFontHeader: function Type1Parser_extractFontHeader(properties) {
|
||||
var token;
|
||||
while ((token = this.getToken()) !== null) {
|
||||
if (token !== '/') {
|
||||
if (token !== "/") {
|
||||
continue;
|
||||
}
|
||||
token = this.getToken();
|
||||
switch (token) {
|
||||
case 'FontMatrix':
|
||||
case "FontMatrix":
|
||||
var matrix = this.readNumberArray();
|
||||
properties.fontMatrix = matrix;
|
||||
break;
|
||||
case 'Encoding':
|
||||
case "Encoding":
|
||||
var encodingArg = this.getToken();
|
||||
var encoding;
|
||||
if (!/^\d+$/.test(encodingArg)) {
|
||||
@ -687,13 +731,13 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
for (var j = 0; j < size; j++) {
|
||||
token = this.getToken();
|
||||
// skipping till first dup or def (e.g. ignoring for statement)
|
||||
while (token !== 'dup' && token !== 'def') {
|
||||
while (token !== "dup" && token !== "def") {
|
||||
token = this.getToken();
|
||||
if (token === null) {
|
||||
return; // invalid header
|
||||
}
|
||||
}
|
||||
if (token === 'def') {
|
||||
if (token === "def") {
|
||||
break; // read all array data
|
||||
}
|
||||
var index = this.readInt();
|
||||
@ -705,7 +749,7 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
}
|
||||
properties.builtInEncoding = encoding;
|
||||
break;
|
||||
case 'FontBBox':
|
||||
case "FontBBox":
|
||||
var fontBBox = this.readNumberArray();
|
||||
// adjusting ascent/descent
|
||||
properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
|
||||
@ -720,6 +764,4 @@ var Type1Parser = (function Type1ParserClosure() {
|
||||
return Type1Parser;
|
||||
})();
|
||||
|
||||
export {
|
||||
Type1Parser,
|
||||
};
|
||||
export { Type1Parser };
|
||||
|
3075
src/core/unicode.js
3075
src/core/unicode.js
File diff suppressed because it is too large
Load Diff
@ -14,17 +14,28 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
AbortException, arrayByteLength, arraysToBytes, createPromiseCapability,
|
||||
getVerbosityLevel, info, InvalidPDFException, MissingPDFException,
|
||||
PasswordException, setVerbosityLevel, 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';
|
||||
AbortException,
|
||||
arrayByteLength,
|
||||
arraysToBytes,
|
||||
createPromiseCapability,
|
||||
getVerbosityLevel,
|
||||
info,
|
||||
InvalidPDFException,
|
||||
MissingPDFException,
|
||||
PasswordException,
|
||||
setVerbosityLevel,
|
||||
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() {
|
||||
function WorkerTask(name) {
|
||||
@ -48,7 +59,7 @@ var WorkerTask = (function WorkerTaskClosure() {
|
||||
|
||||
ensureNotTerminated() {
|
||||
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 = {
|
||||
setup(handler, port) {
|
||||
var testMessageProcessed = false;
|
||||
handler.on('test', function wphSetupTest(data) {
|
||||
handler.on("test", function wphSetupTest(data) {
|
||||
if (testMessageProcessed) {
|
||||
return; // we already processed 'test' message once
|
||||
}
|
||||
@ -67,21 +78,21 @@ var WorkerMessageHandler = {
|
||||
|
||||
// check if Uint8Array can be sent to worker
|
||||
if (!(data instanceof Uint8Array)) {
|
||||
handler.send('test', null);
|
||||
handler.send("test", null);
|
||||
return;
|
||||
}
|
||||
// making sure postMessage transfers are working
|
||||
const supportTransfers = data[0] === 255;
|
||||
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);
|
||||
});
|
||||
|
||||
handler.on('GetDocRequest', function wphSetupDoc(data) {
|
||||
handler.on("GetDocRequest", function wphSetupDoc(data) {
|
||||
return WorkerMessageHandler.createDocumentHandler(data, port);
|
||||
});
|
||||
},
|
||||
@ -96,16 +107,19 @@ var WorkerMessageHandler = {
|
||||
|
||||
const apiVersion = docParams.apiVersion;
|
||||
const workerVersion =
|
||||
typeof PDFJSDev !== 'undefined' && !PDFJSDev.test('TESTING') ?
|
||||
PDFJSDev.eval('BUNDLE_VERSION') : null;
|
||||
typeof PDFJSDev !== "undefined" && !PDFJSDev.test("TESTING")
|
||||
? PDFJSDev.eval("BUNDLE_VERSION")
|
||||
: null;
|
||||
if (apiVersion !== workerVersion) {
|
||||
throw new Error(`The API version "${apiVersion}" does not match ` +
|
||||
`the Worker version "${workerVersion}".`);
|
||||
throw new Error(
|
||||
`The API version "${apiVersion}" does not match ` +
|
||||
`the Worker version "${workerVersion}".`
|
||||
);
|
||||
}
|
||||
|
||||
var docId = docParams.docId;
|
||||
var docBaseUrl = docParams.docBaseUrl;
|
||||
var workerHandlerName = docParams.docId + '_worker';
|
||||
var workerHandlerName = docParams.docId + "_worker";
|
||||
var handler = new MessageHandler(workerHandlerName, docId, port);
|
||||
|
||||
// Ensure that postMessage transfers are always correctly enabled/disabled,
|
||||
@ -114,7 +128,7 @@ var WorkerMessageHandler = {
|
||||
|
||||
function ensureNotTerminated() {
|
||||
if (terminated) {
|
||||
throw new Error('Worker was terminated');
|
||||
throw new Error("Worker was terminated");
|
||||
}
|
||||
}
|
||||
|
||||
@ -129,21 +143,21 @@ var WorkerMessageHandler = {
|
||||
}
|
||||
|
||||
async function loadDocument(recoveryMode) {
|
||||
await pdfManager.ensureDoc('checkHeader');
|
||||
await pdfManager.ensureDoc('parseStartXRef');
|
||||
await pdfManager.ensureDoc('parse', [recoveryMode]);
|
||||
await pdfManager.ensureDoc("checkHeader");
|
||||
await pdfManager.ensureDoc("parseStartXRef");
|
||||
await pdfManager.ensureDoc("parse", [recoveryMode]);
|
||||
|
||||
if (!recoveryMode) {
|
||||
// Check that at least the first page can be successfully loaded,
|
||||
// since otherwise the XRef table is definitely not valid.
|
||||
await pdfManager.ensureDoc('checkFirstPage');
|
||||
await pdfManager.ensureDoc("checkFirstPage");
|
||||
}
|
||||
|
||||
const [numPages, fingerprint] = await Promise.all([
|
||||
pdfManager.ensureDoc('numPages'),
|
||||
pdfManager.ensureDoc('fingerprint'),
|
||||
pdfManager.ensureDoc("numPages"),
|
||||
pdfManager.ensureDoc("fingerprint"),
|
||||
]);
|
||||
return { numPages, fingerprint, };
|
||||
return { numPages, fingerprint };
|
||||
}
|
||||
|
||||
function getPdfManager(data, evaluatorOptions) {
|
||||
@ -153,8 +167,13 @@ var WorkerMessageHandler = {
|
||||
var source = data.source;
|
||||
if (source.data) {
|
||||
try {
|
||||
pdfManager = new LocalPdfManager(docId, source.data, source.password,
|
||||
evaluatorOptions, docBaseUrl);
|
||||
pdfManager = new LocalPdfManager(
|
||||
docId,
|
||||
source.data,
|
||||
source.password,
|
||||
evaluatorOptions,
|
||||
docBaseUrl
|
||||
);
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
@ -162,7 +181,8 @@ var WorkerMessageHandler = {
|
||||
return pdfManagerCapability.promise;
|
||||
}
|
||||
|
||||
var pdfStream, cachedChunks = [];
|
||||
var pdfStream,
|
||||
cachedChunks = [];
|
||||
try {
|
||||
pdfStream = new PDFWorkerStream(handler);
|
||||
} catch (ex) {
|
||||
@ -171,21 +191,28 @@ var WorkerMessageHandler = {
|
||||
}
|
||||
|
||||
var fullRequest = pdfStream.getFullReader();
|
||||
fullRequest.headersReady.then(function () {
|
||||
fullRequest.headersReady
|
||||
.then(function() {
|
||||
if (!fullRequest.isRangeSupported) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't need auto-fetch when streaming is enabled.
|
||||
var disableAutoFetch = source.disableAutoFetch ||
|
||||
fullRequest.isStreamingSupported;
|
||||
pdfManager = new NetworkPdfManager(docId, pdfStream, {
|
||||
var disableAutoFetch =
|
||||
source.disableAutoFetch || fullRequest.isStreamingSupported;
|
||||
pdfManager = new NetworkPdfManager(
|
||||
docId,
|
||||
pdfStream,
|
||||
{
|
||||
msgHandler: handler,
|
||||
password: source.password,
|
||||
length: fullRequest.contentLength,
|
||||
disableAutoFetch,
|
||||
rangeChunkSize: source.rangeChunkSize,
|
||||
}, evaluatorOptions, docBaseUrl);
|
||||
},
|
||||
evaluatorOptions,
|
||||
docBaseUrl
|
||||
);
|
||||
// There may be a chance that `pdfManager` is not initialized
|
||||
// for first few runs of `readchunk` block of code. Be sure
|
||||
// to send all cached chunks, if any, to chunked_stream via
|
||||
@ -197,29 +224,35 @@ var WorkerMessageHandler = {
|
||||
cachedChunks = [];
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
cancelXHRs = null;
|
||||
}).catch(function (reason) {
|
||||
})
|
||||
.catch(function(reason) {
|
||||
pdfManagerCapability.reject(reason);
|
||||
cancelXHRs = null;
|
||||
});
|
||||
|
||||
var loaded = 0;
|
||||
var flushChunks = function () {
|
||||
var flushChunks = function() {
|
||||
var pdfFile = arraysToBytes(cachedChunks);
|
||||
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
|
||||
try {
|
||||
pdfManager = new LocalPdfManager(docId, pdfFile, source.password,
|
||||
evaluatorOptions, docBaseUrl);
|
||||
pdfManager = new LocalPdfManager(
|
||||
docId,
|
||||
pdfFile,
|
||||
source.password,
|
||||
evaluatorOptions,
|
||||
docBaseUrl
|
||||
);
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
}
|
||||
cachedChunks = [];
|
||||
};
|
||||
var readPromise = new Promise(function (resolve, reject) {
|
||||
var readChunk = function (chunk) {
|
||||
var readPromise = new Promise(function(resolve, reject) {
|
||||
var readChunk = function(chunk) {
|
||||
try {
|
||||
ensureNotTerminated();
|
||||
if (chunk.done) {
|
||||
@ -233,7 +266,7 @@ var WorkerMessageHandler = {
|
||||
var data = chunk.value;
|
||||
loaded += arrayByteLength(data);
|
||||
if (!fullRequest.isStreamingSupported) {
|
||||
handler.send('DocProgress', {
|
||||
handler.send("DocProgress", {
|
||||
loaded,
|
||||
total: Math.max(loaded, fullRequest.contentLength || 0),
|
||||
});
|
||||
@ -252,7 +285,7 @@ var WorkerMessageHandler = {
|
||||
};
|
||||
fullRequest.read().then(readChunk, reject);
|
||||
});
|
||||
readPromise.catch(function (e) {
|
||||
readPromise.catch(function(e) {
|
||||
pdfManagerCapability.reject(e);
|
||||
cancelXHRs = null;
|
||||
});
|
||||
@ -267,7 +300,7 @@ var WorkerMessageHandler = {
|
||||
function setupDoc(data) {
|
||||
function onSuccess(doc) {
|
||||
ensureNotTerminated();
|
||||
handler.send('GetDoc', { pdfInfo: doc, });
|
||||
handler.send("GetDoc", { pdfInfo: doc });
|
||||
}
|
||||
|
||||
function onFailure(ex) {
|
||||
@ -277,29 +310,38 @@ var WorkerMessageHandler = {
|
||||
var task = new WorkerTask(`PasswordException: response ${ex.code}`);
|
||||
startWorkerTask(task);
|
||||
|
||||
handler.sendWithPromise('PasswordRequest', ex).then(function(data) {
|
||||
handler
|
||||
.sendWithPromise("PasswordRequest", ex)
|
||||
.then(function(data) {
|
||||
finishWorkerTask(task);
|
||||
pdfManager.updatePassword(data.password);
|
||||
pdfManagerReady();
|
||||
}).catch(function() {
|
||||
})
|
||||
.catch(function() {
|
||||
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 UnexpectedResponseException ||
|
||||
ex instanceof UnknownErrorException) {
|
||||
handler.send('DocException', ex);
|
||||
ex instanceof UnknownErrorException
|
||||
) {
|
||||
handler.send("DocException", ex);
|
||||
} else {
|
||||
handler.send('DocException',
|
||||
new UnknownErrorException(ex.message, ex.toString()));
|
||||
handler.send(
|
||||
"DocException",
|
||||
new UnknownErrorException(ex.message, ex.toString())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function pdfManagerReady() {
|
||||
ensureNotTerminated();
|
||||
|
||||
loadDocument(false).then(onSuccess, function loadFailure(ex) {
|
||||
loadDocument(false).then(
|
||||
onSuccess,
|
||||
function loadFailure(ex) {
|
||||
ensureNotTerminated();
|
||||
|
||||
// Try again with recoveryMode == true
|
||||
@ -313,7 +355,9 @@ var WorkerMessageHandler = {
|
||||
|
||||
loadDocument(true).then(onSuccess, onFailure);
|
||||
});
|
||||
}, onFailure);
|
||||
},
|
||||
onFailure
|
||||
);
|
||||
}
|
||||
|
||||
ensureNotTerminated();
|
||||
@ -327,28 +371,32 @@ var WorkerMessageHandler = {
|
||||
isEvalSupported: data.isEvalSupported,
|
||||
};
|
||||
|
||||
getPdfManager(data, evaluatorOptions).then(function (newPdfManager) {
|
||||
getPdfManager(data, evaluatorOptions)
|
||||
.then(function(newPdfManager) {
|
||||
if (terminated) {
|
||||
// We were in a process of setting up the manager, but it got
|
||||
// terminated in the middle.
|
||||
newPdfManager.terminate(new AbortException('Worker was terminated.'));
|
||||
throw new Error('Worker was terminated');
|
||||
newPdfManager.terminate(
|
||||
new AbortException("Worker was terminated.")
|
||||
);
|
||||
throw new Error("Worker was terminated");
|
||||
}
|
||||
pdfManager = newPdfManager;
|
||||
|
||||
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 Promise.all([
|
||||
pdfManager.ensure(page, 'rotate'),
|
||||
pdfManager.ensure(page, 'ref'),
|
||||
pdfManager.ensure(page, 'userUnit'),
|
||||
pdfManager.ensure(page, 'view'),
|
||||
pdfManager.ensure(page, "rotate"),
|
||||
pdfManager.ensure(page, "ref"),
|
||||
pdfManager.ensure(page, "userUnit"),
|
||||
pdfManager.ensure(page, "view"),
|
||||
]).then(function([rotate, ref, userUnit, view]) {
|
||||
return {
|
||||
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 catalog = pdfManager.pdfDocument.catalog;
|
||||
return catalog.getPageIndex(ref);
|
||||
});
|
||||
|
||||
handler.on('GetDestinations',
|
||||
function wphSetupGetDestinations(data) {
|
||||
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("GetDestinations", function wphSetupGetDestinations(data) {
|
||||
return pdfManager.ensureCatalog("destinations");
|
||||
});
|
||||
|
||||
handler.on('GetPageMode', function wphSetupGetPageMode(data) {
|
||||
return pdfManager.ensureCatalog('pageMode');
|
||||
handler.on("GetDestination", function wphSetupGetDestination(data) {
|
||||
return pdfManager.ensureCatalog("getDestination", [data.id]);
|
||||
});
|
||||
|
||||
handler.on('GetViewerPreferences', function(data) {
|
||||
return pdfManager.ensureCatalog('viewerPreferences');
|
||||
handler.on("GetPageLabels", function wphSetupGetPageLabels(data) {
|
||||
return pdfManager.ensureCatalog("pageLabels");
|
||||
});
|
||||
|
||||
handler.on('GetOpenActionDestination', function(data) {
|
||||
return pdfManager.ensureCatalog('openActionDestination');
|
||||
handler.on("GetPageLayout", function wphSetupGetPageLayout(data) {
|
||||
return pdfManager.ensureCatalog("pageLayout");
|
||||
});
|
||||
|
||||
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("GetPageMode", function wphSetupGetPageMode(data) {
|
||||
return pdfManager.ensureCatalog("pageMode");
|
||||
});
|
||||
|
||||
handler.on('GetMetadata',
|
||||
function wphSetupGetMetadata(data) {
|
||||
return Promise.all([pdfManager.ensureDoc('documentInfo'),
|
||||
pdfManager.ensureCatalog('metadata')]);
|
||||
}
|
||||
);
|
||||
handler.on("GetViewerPreferences", function(data) {
|
||||
return pdfManager.ensureCatalog("viewerPreferences");
|
||||
});
|
||||
|
||||
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();
|
||||
return pdfManager.onLoadedStream().then(function(stream) {
|
||||
return stream.bytes;
|
||||
});
|
||||
});
|
||||
|
||||
handler.on('GetStats',
|
||||
function wphSetupGetStats(data) {
|
||||
handler.on("GetStats", function wphSetupGetStats(data) {
|
||||
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 page.getAnnotationsData(intent);
|
||||
});
|
||||
});
|
||||
|
||||
handler.on('GetOperatorList', function wphSetupRenderPage(data, sink) {
|
||||
handler.on(
|
||||
"GetOperatorList",
|
||||
function wphSetupRenderPage(data, sink) {
|
||||
var pageIndex = data.pageIndex;
|
||||
pdfManager.getPage(pageIndex).then(function(page) {
|
||||
var task = new WorkerTask(`GetOperatorList: page ${pageIndex}`);
|
||||
startWorkerTask(task);
|
||||
|
||||
// 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.
|
||||
page.getOperatorList({
|
||||
page
|
||||
.getOperatorList({
|
||||
handler,
|
||||
sink,
|
||||
task,
|
||||
intent: data.intent,
|
||||
renderInteractiveForms: data.renderInteractiveForms,
|
||||
}).then(function(operatorListInfo) {
|
||||
})
|
||||
.then(
|
||||
function(operatorListInfo) {
|
||||
finishWorkerTask(task);
|
||||
|
||||
if (start) {
|
||||
info(`page=${pageIndex + 1} - getOperatorList: time=` +
|
||||
`${Date.now() - start}ms, len=${operatorListInfo.length}`);
|
||||
info(
|
||||
`page=${pageIndex + 1} - getOperatorList: time=` +
|
||||
`${Date.now() - start}ms, len=${operatorListInfo.length}`
|
||||
);
|
||||
}
|
||||
sink.close();
|
||||
}, function(reason) {
|
||||
},
|
||||
function(reason) {
|
||||
finishWorkerTask(task);
|
||||
if (task.terminated) {
|
||||
return; // ignoring errors from the terminated thread
|
||||
}
|
||||
// For compatibility with older behavior, generating unknown
|
||||
// unsupported feature notification on errors.
|
||||
handler.send('UnsupportedFeature',
|
||||
{ featureId: UNSUPPORTED_FEATURES.unknown, });
|
||||
handler.send("UnsupportedFeature", {
|
||||
featureId: UNSUPPORTED_FEATURES.unknown,
|
||||
});
|
||||
|
||||
sink.error(reason);
|
||||
|
||||
// TODO: Should `reason` be re-thrown here (currently that casues
|
||||
// "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;
|
||||
sink.onPull = function (desiredSize) { };
|
||||
sink.onCancel = function (reason) { };
|
||||
sink.onPull = function(desiredSize) {};
|
||||
sink.onCancel = function(reason) {};
|
||||
|
||||
pdfManager.getPage(pageIndex).then(function(page) {
|
||||
var task = new WorkerTask('GetTextContent: page ' + pageIndex);
|
||||
var task = new WorkerTask("GetTextContent: page " + pageIndex);
|
||||
startWorkerTask(task);
|
||||
|
||||
// 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,
|
||||
task,
|
||||
sink,
|
||||
normalizeWhitespace: data.normalizeWhitespace,
|
||||
combineTextItems: data.combineTextItems,
|
||||
}).then(function() {
|
||||
})
|
||||
.then(
|
||||
function() {
|
||||
finishWorkerTask(task);
|
||||
|
||||
if (start) {
|
||||
info(`page=${pageIndex + 1} - getTextContent: time=` +
|
||||
`${Date.now() - start}ms`);
|
||||
info(
|
||||
`page=${pageIndex + 1} - getTextContent: time=` +
|
||||
`${Date.now() - start}ms`
|
||||
);
|
||||
}
|
||||
sink.close();
|
||||
}, function (reason) {
|
||||
},
|
||||
function(reason) {
|
||||
finishWorkerTask(task);
|
||||
if (task.terminated) {
|
||||
return; // ignoring errors from the terminated thread
|
||||
@ -525,36 +577,37 @@ var WorkerMessageHandler = {
|
||||
|
||||
// TODO: Should `reason` be re-thrown here (currently that casues
|
||||
// "Uncaught exception: ..." messages in the console)?
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
handler.on('FontFallback', function(data) {
|
||||
handler.on("FontFallback", function(data) {
|
||||
return pdfManager.fontFallback(data.id, handler);
|
||||
});
|
||||
|
||||
handler.on('Cleanup', function wphCleanup(data) {
|
||||
handler.on("Cleanup", function wphCleanup(data) {
|
||||
return pdfManager.cleanup();
|
||||
});
|
||||
|
||||
handler.on('Terminate', function wphTerminate(data) {
|
||||
handler.on("Terminate", function wphTerminate(data) {
|
||||
terminated = true;
|
||||
if (pdfManager) {
|
||||
pdfManager.terminate(new AbortException('Worker was terminated.'));
|
||||
pdfManager.terminate(new AbortException("Worker was terminated."));
|
||||
pdfManager = null;
|
||||
}
|
||||
if (cancelXHRs) {
|
||||
cancelXHRs(new AbortException('Worker was terminated.'));
|
||||
cancelXHRs(new AbortException("Worker was terminated."));
|
||||
}
|
||||
clearPrimitiveCaches();
|
||||
|
||||
var waitOn = [];
|
||||
WorkerTasks.forEach(function (task) {
|
||||
WorkerTasks.forEach(function(task) {
|
||||
waitOn.push(task.finished);
|
||||
task.terminate();
|
||||
});
|
||||
|
||||
return Promise.all(waitOn).then(function () {
|
||||
return Promise.all(waitOn).then(function() {
|
||||
// Notice that even if we destroying handler, resolved response promise
|
||||
// must be sent back.
|
||||
handler.destroy();
|
||||
@ -562,31 +615,33 @@ var WorkerMessageHandler = {
|
||||
});
|
||||
});
|
||||
|
||||
handler.on('Ready', function wphReady(data) {
|
||||
handler.on("Ready", function wphReady(data) {
|
||||
setupDoc(docParams);
|
||||
docParams = null; // we don't need docParams anymore -- saving memory.
|
||||
});
|
||||
return workerHandlerName;
|
||||
},
|
||||
initializeFromPort(port) {
|
||||
var handler = new MessageHandler('worker', 'main', port);
|
||||
var handler = new MessageHandler("worker", "main", port);
|
||||
WorkerMessageHandler.setup(handler, port);
|
||||
handler.send('ready', null);
|
||||
handler.send("ready", null);
|
||||
},
|
||||
};
|
||||
|
||||
function isMessagePort(maybePort) {
|
||||
return typeof maybePort.postMessage === 'function' &&
|
||||
('onmessage' in maybePort);
|
||||
return (
|
||||
typeof maybePort.postMessage === "function" && "onmessage" in maybePort
|
||||
);
|
||||
}
|
||||
|
||||
// Worker thread (and not node.js)?
|
||||
if (typeof window === 'undefined' && !isNodeJS &&
|
||||
typeof self !== 'undefined' && isMessagePort(self)) {
|
||||
if (
|
||||
typeof window === "undefined" &&
|
||||
!isNodeJS &&
|
||||
typeof self !== "undefined" &&
|
||||
isMessagePort(self)
|
||||
) {
|
||||
WorkerMessageHandler.initializeFromPort(self);
|
||||
}
|
||||
|
||||
export {
|
||||
WorkerTask,
|
||||
WorkerMessageHandler,
|
||||
};
|
||||
export { WorkerTask, WorkerMessageHandler };
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
/* eslint no-var: error */
|
||||
|
||||
import { assert } from '../shared/util';
|
||||
import { assert } from "../shared/util";
|
||||
|
||||
/** @implements {IPDFStream} */
|
||||
class PDFWorkerStream {
|
||||
@ -58,11 +58,12 @@ class PDFWorkerStreamReader {
|
||||
this._isRangeSupported = false;
|
||||
this._isStreamingSupported = false;
|
||||
|
||||
const readableStream = this._msgHandler.sendWithStream('GetReader');
|
||||
const readableStream = this._msgHandler.sendWithStream("GetReader");
|
||||
this._reader = readableStream.getReader();
|
||||
|
||||
this._headersReady = this._msgHandler.sendWithPromise('ReaderHeadersReady').
|
||||
then((data) => {
|
||||
this._headersReady = this._msgHandler
|
||||
.sendWithPromise("ReaderHeadersReady")
|
||||
.then(data => {
|
||||
this._isStreamingSupported = data.isStreamingSupported;
|
||||
this._isRangeSupported = data.isRangeSupported;
|
||||
this._contentLength = data.contentLength;
|
||||
@ -86,13 +87,13 @@ class PDFWorkerStreamReader {
|
||||
}
|
||||
|
||||
async read() {
|
||||
const { value, done, } = await this._reader.read();
|
||||
const { value, done } = await this._reader.read();
|
||||
if (done) {
|
||||
return { value: undefined, done: true, };
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
// `value` is wrapped into Uint8Array, we need to
|
||||
// unwrap it to ArrayBuffer for further processing.
|
||||
return { value: value.buffer, done: false, };
|
||||
return { value: value.buffer, done: false };
|
||||
}
|
||||
|
||||
cancel(reason) {
|
||||
@ -106,8 +107,10 @@ class PDFWorkerStreamRangeReader {
|
||||
this._msgHandler = msgHandler;
|
||||
this.onProgress = null;
|
||||
|
||||
const readableStream = this._msgHandler.sendWithStream('GetRangeReader',
|
||||
{ begin, end, });
|
||||
const readableStream = this._msgHandler.sendWithStream("GetRangeReader", {
|
||||
begin,
|
||||
end,
|
||||
});
|
||||
this._reader = readableStream.getReader();
|
||||
}
|
||||
|
||||
@ -116,11 +119,11 @@ class PDFWorkerStreamRangeReader {
|
||||
}
|
||||
|
||||
async read() {
|
||||
const { value, done, } = await this._reader.read();
|
||||
const { value, done } = await this._reader.read();
|
||||
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) {
|
||||
@ -128,6 +131,4 @@ class PDFWorkerStreamRangeReader {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PDFWorkerStream,
|
||||
};
|
||||
export { PDFWorkerStream };
|
||||
|
@ -15,13 +15,20 @@
|
||||
/* eslint no-var: error */
|
||||
|
||||
import {
|
||||
addLinkAttributes, DOMSVGFactory, getFilenameFromUrl, LinkTarget,
|
||||
PDFDateString
|
||||
} from './display_utils';
|
||||
addLinkAttributes,
|
||||
DOMSVGFactory,
|
||||
getFilenameFromUrl,
|
||||
LinkTarget,
|
||||
PDFDateString,
|
||||
} from "./display_utils";
|
||||
import {
|
||||
AnnotationBorderStyleType, AnnotationType, stringToPDFString, unreachable,
|
||||
Util, warn
|
||||
} from '../shared/util';
|
||||
AnnotationBorderStyleType,
|
||||
AnnotationType,
|
||||
stringToPDFString,
|
||||
unreachable,
|
||||
Util,
|
||||
warn,
|
||||
} from "../shared/util";
|
||||
|
||||
/**
|
||||
* @typedef {Object} AnnotationElementParameters
|
||||
@ -56,16 +63,16 @@ class AnnotationElementFactory {
|
||||
const fieldType = parameters.data.fieldType;
|
||||
|
||||
switch (fieldType) {
|
||||
case 'Tx':
|
||||
case "Tx":
|
||||
return new TextWidgetAnnotationElement(parameters);
|
||||
case 'Btn':
|
||||
case "Btn":
|
||||
if (parameters.data.radioButton) {
|
||||
return new RadioButtonWidgetAnnotationElement(parameters);
|
||||
} else if (parameters.data.checkBox) {
|
||||
return new CheckboxWidgetAnnotationElement(parameters);
|
||||
}
|
||||
return new PushButtonWidgetAnnotationElement(parameters);
|
||||
case 'Ch':
|
||||
case "Ch":
|
||||
return new ChoiceWidgetAnnotationElement(parameters);
|
||||
}
|
||||
return new WidgetAnnotationElement(parameters);
|
||||
@ -148,12 +155,14 @@ class AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
_createContainer(ignoreBorder = false) {
|
||||
const data = this.data, page = this.page, viewport = this.viewport;
|
||||
const container = document.createElement('section');
|
||||
const data = this.data,
|
||||
page = this.page,
|
||||
viewport = this.viewport;
|
||||
const container = document.createElement("section");
|
||||
let width = data.rect[2] - data.rect[0];
|
||||
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
|
||||
// position on subsequent calls to `_createContainer` (see issue 6804).
|
||||
@ -161,10 +170,10 @@ class AnnotationElement {
|
||||
data.rect[0],
|
||||
page.view[3] - data.rect[1] + page.view[1],
|
||||
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`;
|
||||
|
||||
if (!ignoreBorder && data.borderStyle.width > 0) {
|
||||
@ -186,23 +195,23 @@ class AnnotationElement {
|
||||
|
||||
switch (data.borderStyle.style) {
|
||||
case AnnotationBorderStyleType.SOLID:
|
||||
container.style.borderStyle = 'solid';
|
||||
container.style.borderStyle = "solid";
|
||||
break;
|
||||
|
||||
case AnnotationBorderStyleType.DASHED:
|
||||
container.style.borderStyle = 'dashed';
|
||||
container.style.borderStyle = "dashed";
|
||||
break;
|
||||
|
||||
case AnnotationBorderStyleType.BEVELED:
|
||||
warn('Unimplemented border style: beveled');
|
||||
warn("Unimplemented border style: beveled");
|
||||
break;
|
||||
|
||||
case AnnotationBorderStyleType.INSET:
|
||||
warn('Unimplemented border style: inset');
|
||||
warn("Unimplemented border style: inset");
|
||||
break;
|
||||
|
||||
case AnnotationBorderStyleType.UNDERLINE:
|
||||
container.style.borderBottomStyle = 'solid';
|
||||
container.style.borderBottomStyle = "solid";
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -210,9 +219,11 @@ class AnnotationElement {
|
||||
}
|
||||
|
||||
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[2] | 0);
|
||||
data.color[2] | 0
|
||||
);
|
||||
} else {
|
||||
// Transparent (invisible) border, so do not draw it at all.
|
||||
container.style.borderWidth = 0;
|
||||
@ -240,7 +251,7 @@ class AnnotationElement {
|
||||
_createPopup(container, trigger, data) {
|
||||
// If no trigger element is specified, create it.
|
||||
if (!trigger) {
|
||||
trigger = document.createElement('div');
|
||||
trigger = document.createElement("div");
|
||||
trigger.style.height = container.style.height;
|
||||
trigger.style.width = container.style.width;
|
||||
container.appendChild(trigger);
|
||||
@ -270,14 +281,17 @@ class AnnotationElement {
|
||||
* @memberof AnnotationElement
|
||||
*/
|
||||
render() {
|
||||
unreachable('Abstract method `AnnotationElement.render` called');
|
||||
unreachable("Abstract method `AnnotationElement.render` called");
|
||||
}
|
||||
}
|
||||
|
||||
class LinkAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.url || parameters.data.dest ||
|
||||
parameters.data.action);
|
||||
const isRenderable = !!(
|
||||
parameters.data.url ||
|
||||
parameters.data.dest ||
|
||||
parameters.data.action
|
||||
);
|
||||
super(parameters, isRenderable);
|
||||
}
|
||||
|
||||
@ -289,16 +303,17 @@ class LinkAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'linkAnnotation';
|
||||
this.container.className = "linkAnnotation";
|
||||
|
||||
const { data, linkService, } = this;
|
||||
const link = document.createElement('a');
|
||||
const { data, linkService } = this;
|
||||
const link = document.createElement("a");
|
||||
|
||||
if (data.url) {
|
||||
addLinkAttributes(link, {
|
||||
url: data.url,
|
||||
target: (data.newWindow ?
|
||||
LinkTarget.BLANK : linkService.externalLinkTarget),
|
||||
target: data.newWindow
|
||||
? LinkTarget.BLANK
|
||||
: linkService.externalLinkTarget,
|
||||
rel: linkService.externalLinkRel,
|
||||
enabled: linkService.externalLinkEnabled,
|
||||
});
|
||||
@ -329,7 +344,7 @@ class LinkAnnotationElement extends AnnotationElement {
|
||||
return false;
|
||||
};
|
||||
if (destination) {
|
||||
link.className = 'internalLink';
|
||||
link.className = "internalLink";
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,19 +357,22 @@ class LinkAnnotationElement extends AnnotationElement {
|
||||
* @memberof LinkAnnotationElement
|
||||
*/
|
||||
_bindNamedAction(link, action) {
|
||||
link.href = this.linkService.getAnchorUrl('');
|
||||
link.href = this.linkService.getAnchorUrl("");
|
||||
link.onclick = () => {
|
||||
this.linkService.executeNamedAction(action);
|
||||
return false;
|
||||
};
|
||||
link.className = 'internalLink';
|
||||
link.className = "internalLink";
|
||||
}
|
||||
}
|
||||
|
||||
class TextAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable);
|
||||
}
|
||||
|
||||
@ -366,16 +384,19 @@ class TextAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
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.width = this.container.style.width;
|
||||
image.src = this.imageResourcesPath + 'annotation-' +
|
||||
this.data.name.toLowerCase() + '.svg';
|
||||
image.alt = '[{{type}} Annotation]';
|
||||
image.dataset.l10nId = 'text_annotation_type';
|
||||
image.dataset.l10nArgs = JSON.stringify({ type: this.data.name, });
|
||||
image.src =
|
||||
this.imageResourcesPath +
|
||||
"annotation-" +
|
||||
this.data.name.toLowerCase() +
|
||||
".svg";
|
||||
image.alt = "[{{type}} Annotation]";
|
||||
image.dataset.l10nId = "text_annotation_type";
|
||||
image.dataset.l10nArgs = JSON.stringify({ type: this.data.name });
|
||||
|
||||
if (!this.data.hasPopup) {
|
||||
this._createPopup(this.container, image, this.data);
|
||||
@ -402,7 +423,8 @@ class WidgetAnnotationElement extends AnnotationElement {
|
||||
|
||||
class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = parameters.renderInteractiveForms ||
|
||||
const isRenderable =
|
||||
parameters.renderInteractiveForms ||
|
||||
(!parameters.data.hasAppearance && !!parameters.data.fieldValue);
|
||||
super(parameters, isRenderable);
|
||||
}
|
||||
@ -415,9 +437,9 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
const TEXT_ALIGNMENT = ['left', 'center', 'right'];
|
||||
const TEXT_ALIGNMENT = ["left", "center", "right"];
|
||||
|
||||
this.container.className = 'textWidgetAnnotation';
|
||||
this.container.className = "textWidgetAnnotation";
|
||||
|
||||
let element = null;
|
||||
if (this.renderInteractiveForms) {
|
||||
@ -425,12 +447,12 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
// prevents the AnnotationLayer rasterizer in `test/driver.js`
|
||||
// from parsing the elements correctly for the reference tests.
|
||||
if (this.data.multiLine) {
|
||||
element = document.createElement('textarea');
|
||||
element = document.createElement("textarea");
|
||||
element.textContent = this.data.fieldValue;
|
||||
} else {
|
||||
element = document.createElement('input');
|
||||
element.type = 'text';
|
||||
element.setAttribute('value', this.data.fieldValue);
|
||||
element = document.createElement("input");
|
||||
element.type = "text";
|
||||
element.setAttribute("value", this.data.fieldValue);
|
||||
}
|
||||
|
||||
element.disabled = this.data.readOnly;
|
||||
@ -443,18 +465,20 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
const fieldWidth = this.data.rect[2] - this.data.rect[0];
|
||||
const combWidth = fieldWidth / this.data.maxLen;
|
||||
|
||||
element.classList.add('comb');
|
||||
element.classList.add("comb");
|
||||
element.style.letterSpacing = `calc(${combWidth}px - 1ch)`;
|
||||
}
|
||||
} else {
|
||||
element = document.createElement('div');
|
||||
element = document.createElement("div");
|
||||
element.textContent = this.data.fieldValue;
|
||||
element.style.verticalAlign = 'middle';
|
||||
element.style.display = 'table-cell';
|
||||
element.style.verticalAlign = "middle";
|
||||
element.style.display = "table-cell";
|
||||
|
||||
let font = null;
|
||||
if (this.data.fontRefName &&
|
||||
this.page.commonObjs.has(this.data.fontRefName)) {
|
||||
if (
|
||||
this.data.fontRefName &&
|
||||
this.page.commonObjs.has(this.data.fontRefName)
|
||||
) {
|
||||
font = this.page.commonObjs.get(this.data.fontRefName);
|
||||
}
|
||||
this._setTextStyle(element, font);
|
||||
@ -480,20 +504,24 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
// TODO: This duplicates some of the logic in CanvasGraphics.setFont().
|
||||
const style = element.style;
|
||||
style.fontSize = `${this.data.fontSize}px`;
|
||||
style.direction = (this.data.fontDirection < 0 ? 'rtl' : 'ltr');
|
||||
style.direction = this.data.fontDirection < 0 ? "rtl" : "ltr";
|
||||
|
||||
if (!font) {
|
||||
return;
|
||||
}
|
||||
|
||||
style.fontWeight = (font.black ?
|
||||
(font.bold ? '900' : 'bold') :
|
||||
(font.bold ? 'bold' : 'normal'));
|
||||
style.fontStyle = (font.italic ? 'italic' : 'normal');
|
||||
style.fontWeight = font.black
|
||||
? font.bold
|
||||
? "900"
|
||||
: "bold"
|
||||
: font.bold
|
||||
? "bold"
|
||||
: "normal";
|
||||
style.fontStyle = font.italic ? "italic" : "normal";
|
||||
|
||||
// Use a reasonable default font if the font doesn't specify a fallback.
|
||||
const fontFamily = font.loadedName ? `"${font.loadedName}", ` : '';
|
||||
const fallbackName = font.fallbackName || 'Helvetica, sans-serif';
|
||||
const fontFamily = font.loadedName ? `"${font.loadedName}", ` : "";
|
||||
const fallbackName = font.fallbackName || "Helvetica, sans-serif";
|
||||
style.fontFamily = fontFamily + fallbackName;
|
||||
}
|
||||
}
|
||||
@ -512,13 +540,13 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
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.type = 'checkbox';
|
||||
if (this.data.fieldValue && this.data.fieldValue !== 'Off') {
|
||||
element.setAttribute('checked', true);
|
||||
element.type = "checkbox";
|
||||
if (this.data.fieldValue && this.data.fieldValue !== "Off") {
|
||||
element.setAttribute("checked", true);
|
||||
}
|
||||
|
||||
this.container.appendChild(element);
|
||||
@ -540,14 +568,14 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
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.type = 'radio';
|
||||
element.type = "radio";
|
||||
element.name = this.data.fieldName;
|
||||
if (this.data.fieldValue === this.data.buttonValue) {
|
||||
element.setAttribute('checked', true);
|
||||
element.setAttribute("checked", true);
|
||||
}
|
||||
|
||||
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
|
||||
// as performing actions on form fields (resetting, submitting, et cetera).
|
||||
const container = super.render();
|
||||
container.className = 'buttonWidgetAnnotation pushButton';
|
||||
container.className = "buttonWidgetAnnotation pushButton";
|
||||
return container;
|
||||
}
|
||||
}
|
||||
@ -588,9 +616,9 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'choiceWidgetAnnotation';
|
||||
this.container.className = "choiceWidgetAnnotation";
|
||||
|
||||
const selectElement = document.createElement('select');
|
||||
const selectElement = document.createElement("select");
|
||||
selectElement.disabled = this.data.readOnly;
|
||||
|
||||
if (!this.data.combo) {
|
||||
@ -603,11 +631,11 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
|
||||
// Insert the options into the choice field.
|
||||
for (const option of this.data.options) {
|
||||
const optionElement = document.createElement('option');
|
||||
const optionElement = document.createElement("option");
|
||||
optionElement.textContent = option.displayValue;
|
||||
optionElement.value = option.exportValue;
|
||||
if (this.data.fieldValue.includes(option.displayValue)) {
|
||||
optionElement.setAttribute('selected', true);
|
||||
optionElement.setAttribute("selected", true);
|
||||
}
|
||||
selectElement.appendChild(optionElement);
|
||||
}
|
||||
@ -634,15 +662,15 @@ class PopupAnnotationElement extends AnnotationElement {
|
||||
// Do not render popup annotations for parent elements with these types as
|
||||
// they create the popups themselves (because of custom trigger divs).
|
||||
const IGNORE_TYPES = [
|
||||
'Line',
|
||||
'Square',
|
||||
'Circle',
|
||||
'PolyLine',
|
||||
'Polygon',
|
||||
'Ink',
|
||||
"Line",
|
||||
"Square",
|
||||
"Circle",
|
||||
"PolyLine",
|
||||
"Polygon",
|
||||
"Ink",
|
||||
];
|
||||
|
||||
this.container.className = 'popupAnnotation';
|
||||
this.container.className = "popupAnnotation";
|
||||
|
||||
if (IGNORE_TYPES.includes(this.data.parentType)) {
|
||||
return this.container;
|
||||
@ -667,8 +695,9 @@ class PopupAnnotationElement extends AnnotationElement {
|
||||
// PDF viewers ignore a popup annotation's rectangle.
|
||||
const parentLeft = parseFloat(parentElement.style.left);
|
||||
const parentWidth = parseFloat(parentElement.style.width);
|
||||
this.container.style.transformOrigin =
|
||||
`-${parentLeft + parentWidth}px -${parentElement.style.top}`;
|
||||
this.container.style.transformOrigin = `-${parentLeft + parentWidth}px -${
|
||||
parentElement.style.top
|
||||
}`;
|
||||
this.container.style.left = `${parentLeft + parentWidth}px`;
|
||||
|
||||
this.container.appendChild(popup.render());
|
||||
@ -699,18 +728,18 @@ class PopupElement {
|
||||
render() {
|
||||
const BACKGROUND_ENLIGHT = 0.7;
|
||||
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'popupWrapper';
|
||||
const wrapper = document.createElement("div");
|
||||
wrapper.className = "popupWrapper";
|
||||
|
||||
// For Popup annotations we hide the entire section because it contains
|
||||
// only the popup. However, for Text annotations without a separate Popup
|
||||
// annotation, we cannot hide the entire container as the image would
|
||||
// disappear too. In that special case, hiding the wrapper suffices.
|
||||
this.hideElement = (this.hideWrapper ? wrapper : this.container);
|
||||
this.hideElement.setAttribute('hidden', true);
|
||||
this.hideElement = this.hideWrapper ? wrapper : this.container;
|
||||
this.hideElement.setAttribute("hidden", true);
|
||||
|
||||
const popup = document.createElement('div');
|
||||
popup.className = 'popup';
|
||||
const popup = document.createElement("div");
|
||||
popup.className = "popup";
|
||||
|
||||
const color = this.color;
|
||||
if (color) {
|
||||
@ -721,7 +750,7 @@ class PopupElement {
|
||||
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;
|
||||
popup.appendChild(title);
|
||||
|
||||
@ -730,9 +759,9 @@ class PopupElement {
|
||||
// consistent with other viewers such as Adobe Acrobat.
|
||||
const dateObject = PDFDateString.toDateObject(this.modificationDate);
|
||||
if (dateObject) {
|
||||
const modificationDate = document.createElement('span');
|
||||
modificationDate.textContent = '{{date}}, {{time}}';
|
||||
modificationDate.dataset.l10nId = 'annotation_date_string';
|
||||
const modificationDate = document.createElement("span");
|
||||
modificationDate.textContent = "{{date}}, {{time}}";
|
||||
modificationDate.dataset.l10nId = "annotation_date_string";
|
||||
modificationDate.dataset.l10nArgs = JSON.stringify({
|
||||
date: dateObject.toLocaleDateString(),
|
||||
time: dateObject.toLocaleTimeString(),
|
||||
@ -744,10 +773,10 @@ class PopupElement {
|
||||
popup.appendChild(contents);
|
||||
|
||||
// Attach the event listeners to the trigger element.
|
||||
this.trigger.addEventListener('click', this._toggle.bind(this));
|
||||
this.trigger.addEventListener('mouseover', this._show.bind(this, false));
|
||||
this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
|
||||
popup.addEventListener('click', this._hide.bind(this, true));
|
||||
this.trigger.addEventListener("click", this._toggle.bind(this));
|
||||
this.trigger.addEventListener("mouseover", this._show.bind(this, false));
|
||||
this.trigger.addEventListener("mouseout", this._hide.bind(this, false));
|
||||
popup.addEventListener("click", this._hide.bind(this, true));
|
||||
|
||||
wrapper.appendChild(popup);
|
||||
return wrapper;
|
||||
@ -762,13 +791,13 @@ class PopupElement {
|
||||
* @returns {HTMLParagraphElement}
|
||||
*/
|
||||
_formatContents(contents) {
|
||||
const p = document.createElement('p');
|
||||
const p = document.createElement("p");
|
||||
const lines = contents.split(/(?:\r\n?|\n)/);
|
||||
for (let i = 0, ii = lines.length; i < ii; ++i) {
|
||||
const line = lines[i];
|
||||
p.appendChild(document.createTextNode(line));
|
||||
if (i < (ii - 1)) {
|
||||
p.appendChild(document.createElement('br'));
|
||||
if (i < ii - 1) {
|
||||
p.appendChild(document.createElement("br"));
|
||||
}
|
||||
}
|
||||
return p;
|
||||
@ -799,8 +828,8 @@ class PopupElement {
|
||||
if (pin) {
|
||||
this.pinned = true;
|
||||
}
|
||||
if (this.hideElement.hasAttribute('hidden')) {
|
||||
this.hideElement.removeAttribute('hidden');
|
||||
if (this.hideElement.hasAttribute("hidden")) {
|
||||
this.hideElement.removeAttribute("hidden");
|
||||
this.container.style.zIndex += 1;
|
||||
}
|
||||
}
|
||||
@ -816,8 +845,8 @@ class PopupElement {
|
||||
if (unpin) {
|
||||
this.pinned = false;
|
||||
}
|
||||
if (!this.hideElement.hasAttribute('hidden') && !this.pinned) {
|
||||
this.hideElement.setAttribute('hidden', true);
|
||||
if (!this.hideElement.hasAttribute("hidden") && !this.pinned) {
|
||||
this.hideElement.setAttribute("hidden", true);
|
||||
this.container.style.zIndex -= 1;
|
||||
}
|
||||
}
|
||||
@ -825,8 +854,11 @@ class PopupElement {
|
||||
|
||||
class FreeTextAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -838,7 +870,7 @@ class FreeTextAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'freeTextAnnotation';
|
||||
this.container.className = "freeTextAnnotation";
|
||||
|
||||
if (!this.data.hasPopup) {
|
||||
this._createPopup(this.container, null, this.data);
|
||||
@ -849,8 +881,11 @@ class FreeTextAnnotationElement extends AnnotationElement {
|
||||
|
||||
class LineAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -862,7 +897,7 @@ class LineAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'lineAnnotation';
|
||||
this.container.className = "lineAnnotation";
|
||||
|
||||
// Create an invisible line with the same starting and ending coordinates
|
||||
// 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
|
||||
// the line coordinates to a top left origin for the SVG element.
|
||||
const line = this.svgFactory.createElement('svg:line');
|
||||
line.setAttribute('x1', data.rect[2] - data.lineCoordinates[0]);
|
||||
line.setAttribute('y1', data.rect[3] - data.lineCoordinates[1]);
|
||||
line.setAttribute('x2', data.rect[2] - data.lineCoordinates[2]);
|
||||
line.setAttribute('y2', data.rect[3] - data.lineCoordinates[3]);
|
||||
const line = this.svgFactory.createElement("svg:line");
|
||||
line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]);
|
||||
line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]);
|
||||
line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]);
|
||||
line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]);
|
||||
// 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).
|
||||
line.setAttribute('stroke-width', data.borderStyle.width || 1);
|
||||
line.setAttribute('stroke', 'transparent');
|
||||
line.setAttribute("stroke-width", data.borderStyle.width || 1);
|
||||
line.setAttribute("stroke", "transparent");
|
||||
|
||||
svg.appendChild(line);
|
||||
this.container.append(svg);
|
||||
@ -897,8 +932,11 @@ class LineAnnotationElement extends AnnotationElement {
|
||||
|
||||
class SquareAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -910,7 +948,7 @@ class SquareAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'squareAnnotation';
|
||||
this.container.className = "squareAnnotation";
|
||||
|
||||
// Create an invisible square with the same rectangle that acts as 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
|
||||
// changed programmatically, so correct for that here.
|
||||
const borderWidth = data.borderStyle.width;
|
||||
const square = this.svgFactory.createElement('svg:rect');
|
||||
square.setAttribute('x', borderWidth / 2);
|
||||
square.setAttribute('y', borderWidth / 2);
|
||||
square.setAttribute('width', width - borderWidth);
|
||||
square.setAttribute('height', height - borderWidth);
|
||||
const square = this.svgFactory.createElement("svg:rect");
|
||||
square.setAttribute("x", borderWidth / 2);
|
||||
square.setAttribute("y", borderWidth / 2);
|
||||
square.setAttribute("width", width - borderWidth);
|
||||
square.setAttribute("height", height - borderWidth);
|
||||
// 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).
|
||||
square.setAttribute('stroke-width', borderWidth || 1);
|
||||
square.setAttribute('stroke', 'transparent');
|
||||
square.setAttribute('fill', 'none');
|
||||
square.setAttribute("stroke-width", borderWidth || 1);
|
||||
square.setAttribute("stroke", "transparent");
|
||||
square.setAttribute("fill", "none");
|
||||
|
||||
svg.appendChild(square);
|
||||
this.container.append(svg);
|
||||
@ -948,8 +986,11 @@ class SquareAnnotationElement extends AnnotationElement {
|
||||
|
||||
class CircleAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -961,7 +1002,7 @@ class CircleAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'circleAnnotation';
|
||||
this.container.className = "circleAnnotation";
|
||||
|
||||
// Create an invisible circle with the same ellipse that acts as 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
|
||||
// changed programmatically, so correct for that here.
|
||||
const borderWidth = data.borderStyle.width;
|
||||
const circle = this.svgFactory.createElement('svg:ellipse');
|
||||
circle.setAttribute('cx', width / 2);
|
||||
circle.setAttribute('cy', height / 2);
|
||||
circle.setAttribute('rx', (width / 2) - (borderWidth / 2));
|
||||
circle.setAttribute('ry', (height / 2) - (borderWidth / 2));
|
||||
const circle = this.svgFactory.createElement("svg:ellipse");
|
||||
circle.setAttribute("cx", width / 2);
|
||||
circle.setAttribute("cy", height / 2);
|
||||
circle.setAttribute("rx", width / 2 - borderWidth / 2);
|
||||
circle.setAttribute("ry", height / 2 - borderWidth / 2);
|
||||
// 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).
|
||||
circle.setAttribute('stroke-width', borderWidth || 1);
|
||||
circle.setAttribute('stroke', 'transparent');
|
||||
circle.setAttribute('fill', 'none');
|
||||
circle.setAttribute("stroke-width", borderWidth || 1);
|
||||
circle.setAttribute("stroke", "transparent");
|
||||
circle.setAttribute("fill", "none");
|
||||
|
||||
svg.appendChild(circle);
|
||||
this.container.append(svg);
|
||||
@ -999,12 +1040,15 @@ class CircleAnnotationElement extends AnnotationElement {
|
||||
|
||||
class PolylineAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
|
||||
this.containerClassName = 'polylineAnnotation';
|
||||
this.svgElementName = 'svg:polyline';
|
||||
this.containerClassName = "polylineAnnotation";
|
||||
this.svgElementName = "svg:polyline";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1033,17 +1077,17 @@ class PolylineAnnotationElement extends AnnotationElement {
|
||||
for (const coordinate of data.vertices) {
|
||||
const x = coordinate.x - data.rect[0];
|
||||
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);
|
||||
polyline.setAttribute('points', points);
|
||||
polyline.setAttribute("points", points);
|
||||
// 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).
|
||||
polyline.setAttribute('stroke-width', data.borderStyle.width || 1);
|
||||
polyline.setAttribute('stroke', 'transparent');
|
||||
polyline.setAttribute('fill', 'none');
|
||||
polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
|
||||
polyline.setAttribute("stroke", "transparent");
|
||||
polyline.setAttribute("fill", "none");
|
||||
|
||||
svg.appendChild(polyline);
|
||||
this.container.append(svg);
|
||||
@ -1061,15 +1105,18 @@ class PolygonAnnotationElement extends PolylineAnnotationElement {
|
||||
// Polygons are specific forms of polylines, so reuse their logic.
|
||||
super(parameters);
|
||||
|
||||
this.containerClassName = 'polygonAnnotation';
|
||||
this.svgElementName = 'svg:polygon';
|
||||
this.containerClassName = "polygonAnnotation";
|
||||
this.svgElementName = "svg:polygon";
|
||||
}
|
||||
}
|
||||
|
||||
class CaretAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -1081,7 +1128,7 @@ class CaretAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'caretAnnotation';
|
||||
this.container.className = "caretAnnotation";
|
||||
|
||||
if (!this.data.hasPopup) {
|
||||
this._createPopup(this.container, null, this.data);
|
||||
@ -1092,15 +1139,18 @@ class CaretAnnotationElement extends AnnotationElement {
|
||||
|
||||
class InkAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
|
||||
this.containerClassName = 'inkAnnotation';
|
||||
this.containerClassName = "inkAnnotation";
|
||||
|
||||
// Use the polyline SVG element since it allows us to use coordinates
|
||||
// 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;
|
||||
points.push(`${x},${y}`);
|
||||
}
|
||||
points = points.join(' ');
|
||||
points = points.join(" ");
|
||||
|
||||
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
|
||||
// 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', 'transparent');
|
||||
polyline.setAttribute('fill', 'none');
|
||||
polyline.setAttribute("stroke-width", data.borderStyle.width || 1);
|
||||
polyline.setAttribute("stroke", "transparent");
|
||||
polyline.setAttribute("fill", "none");
|
||||
|
||||
// Create the popup ourselves so that we can bind it to the polyline
|
||||
// instead of to the entire container (which is the default).
|
||||
@ -1155,8 +1205,11 @@ class InkAnnotationElement extends AnnotationElement {
|
||||
|
||||
class HighlightAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -1168,7 +1221,7 @@ class HighlightAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'highlightAnnotation';
|
||||
this.container.className = "highlightAnnotation";
|
||||
|
||||
if (!this.data.hasPopup) {
|
||||
this._createPopup(this.container, null, this.data);
|
||||
@ -1179,8 +1232,11 @@ class HighlightAnnotationElement extends AnnotationElement {
|
||||
|
||||
class UnderlineAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -1192,7 +1248,7 @@ class UnderlineAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'underlineAnnotation';
|
||||
this.container.className = "underlineAnnotation";
|
||||
|
||||
if (!this.data.hasPopup) {
|
||||
this._createPopup(this.container, null, this.data);
|
||||
@ -1203,8 +1259,11 @@ class UnderlineAnnotationElement extends AnnotationElement {
|
||||
|
||||
class SquigglyAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -1216,7 +1275,7 @@ class SquigglyAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'squigglyAnnotation';
|
||||
this.container.className = "squigglyAnnotation";
|
||||
|
||||
if (!this.data.hasPopup) {
|
||||
this._createPopup(this.container, null, this.data);
|
||||
@ -1227,8 +1286,11 @@ class SquigglyAnnotationElement extends AnnotationElement {
|
||||
|
||||
class StrikeOutAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -1240,7 +1302,7 @@ class StrikeOutAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'strikeoutAnnotation';
|
||||
this.container.className = "strikeoutAnnotation";
|
||||
|
||||
if (!this.data.hasPopup) {
|
||||
this._createPopup(this.container, null, this.data);
|
||||
@ -1251,8 +1313,11 @@ class StrikeOutAnnotationElement extends AnnotationElement {
|
||||
|
||||
class StampAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
const isRenderable = !!(parameters.data.hasPopup ||
|
||||
parameters.data.title || parameters.data.contents);
|
||||
const isRenderable = !!(
|
||||
parameters.data.hasPopup ||
|
||||
parameters.data.title ||
|
||||
parameters.data.contents
|
||||
);
|
||||
super(parameters, isRenderable, /* ignoreBorder = */ true);
|
||||
}
|
||||
|
||||
@ -1264,7 +1329,7 @@ class StampAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
render() {
|
||||
this.container.className = 'stampAnnotation';
|
||||
this.container.className = "stampAnnotation";
|
||||
|
||||
if (!this.data.hasPopup) {
|
||||
this._createPopup(this.container, null, this.data);
|
||||
@ -1277,12 +1342,12 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
||||
constructor(parameters) {
|
||||
super(parameters, /* isRenderable = */ true);
|
||||
|
||||
const { filename, content, } = this.data.file;
|
||||
const { filename, content } = this.data.file;
|
||||
this.filename = getFilenameFromUrl(filename);
|
||||
this.content = content;
|
||||
|
||||
if (this.linkService.eventBus) {
|
||||
this.linkService.eventBus.dispatch('fileattachmentannotation', {
|
||||
this.linkService.eventBus.dispatch("fileattachmentannotation", {
|
||||
source: this,
|
||||
id: stringToPDFString(filename),
|
||||
filename,
|
||||
@ -1300,12 +1365,12 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
||||
* @returns {HTMLSectionElement}
|
||||
*/
|
||||
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.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)) {
|
||||
this._createPopup(this.container, trigger, this.data);
|
||||
@ -1323,10 +1388,10 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
|
||||
*/
|
||||
_download() {
|
||||
if (!this.downloadManager) {
|
||||
warn('Download cannot be started due to unavailable download manager');
|
||||
warn("Download cannot be started due to unavailable download manager");
|
||||
return;
|
||||
}
|
||||
this.downloadManager.downloadData(this.content, this.filename, '');
|
||||
this.downloadManager.downloadData(this.content, this.filename, "");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1363,7 +1428,7 @@ class AnnotationLayer {
|
||||
viewport: parameters.viewport,
|
||||
linkService: parameters.linkService,
|
||||
downloadManager: parameters.downloadManager,
|
||||
imageResourcesPath: parameters.imageResourcesPath || '',
|
||||
imageResourcesPath: parameters.imageResourcesPath || "",
|
||||
renderInteractiveForms: parameters.renderInteractiveForms || false,
|
||||
svgFactory: new DOMSVGFactory(),
|
||||
});
|
||||
@ -1383,16 +1448,16 @@ class AnnotationLayer {
|
||||
static update(parameters) {
|
||||
for (const data of parameters.annotations) {
|
||||
const element = parameters.div.querySelector(
|
||||
`[data-annotation-id="${data.id}"]`);
|
||||
`[data-annotation-id="${data.id}"]`
|
||||
);
|
||||
if (element) {
|
||||
element.style.transform =
|
||||
`matrix(${parameters.viewport.transform.join(',')})`;
|
||||
element.style.transform = `matrix(${parameters.viewport.transform.join(
|
||||
","
|
||||
)})`;
|
||||
}
|
||||
}
|
||||
parameters.div.removeAttribute('hidden');
|
||||
parameters.div.removeAttribute("hidden");
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
AnnotationLayer,
|
||||
};
|
||||
export { AnnotationLayer };
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,11 +14,11 @@
|
||||
*/
|
||||
|
||||
let compatibilityParams = Object.create(null);
|
||||
if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
|
||||
const { isNodeJS, } = require('../shared/is_node');
|
||||
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
|
||||
const { isNodeJS } = require("../shared/is_node");
|
||||
|
||||
const userAgent =
|
||||
(typeof navigator !== 'undefined' && navigator.userAgent) || '';
|
||||
(typeof navigator !== "undefined" && navigator.userAgent) || "";
|
||||
const isIE = /Trident/.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`.
|
||||
if (isNodeJS) {
|
||||
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;
|
||||
|
||||
// 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) {
|
||||
tmp = tmp[1];
|
||||
let filename = rfc2616unquote(tmp);
|
||||
@ -52,7 +52,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
}
|
||||
|
||||
// filename=value (RFC 5987, section 4.1).
|
||||
tmp = toParamRegExp('filename', 'i').exec(contentDisposition);
|
||||
tmp = toParamRegExp("filename", "i").exec(contentDisposition);
|
||||
if (tmp) {
|
||||
tmp = tmp[1];
|
||||
let filename = rfc2616unquote(tmp);
|
||||
@ -65,14 +65,18 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
// declarations...
|
||||
function toParamRegExp(attributePattern, flags) {
|
||||
return new RegExp(
|
||||
'(?:^|;)\\s*' + attributePattern + '\\s*=\\s*' +
|
||||
"(?:^|;)\\s*" +
|
||||
attributePattern +
|
||||
"\\s*=\\s*" +
|
||||
// Captures: value = token | quoted-string
|
||||
// (RFC 2616, section 3.6 and referenced by RFC 6266 4.1)
|
||||
'(' +
|
||||
"(" +
|
||||
'[^";\\s][^;\\s]*' +
|
||||
'|' +
|
||||
"|" +
|
||||
'"(?:[^"\\\\]|\\\\"?)+"?' +
|
||||
')', flags);
|
||||
")",
|
||||
flags
|
||||
);
|
||||
}
|
||||
function textdecode(encoding, value) {
|
||||
if (encoding) {
|
||||
@ -80,9 +84,9 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
return value;
|
||||
}
|
||||
try {
|
||||
let decoder = new TextDecoder(encoding, { fatal: true, });
|
||||
let decoder = new TextDecoder(encoding, { fatal: true });
|
||||
let bytes = Array.from(value, function(ch) {
|
||||
return ch.charCodeAt(0) & 0xFF;
|
||||
return ch.charCodeAt(0) & 0xff;
|
||||
});
|
||||
value = decoder.decode(new Uint8Array(bytes));
|
||||
needsEncodingFixup = false;
|
||||
@ -94,8 +98,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
try {
|
||||
value = decodeURIComponent(escape(value));
|
||||
needsEncodingFixup = false;
|
||||
} catch (err) {
|
||||
}
|
||||
} catch (err) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -104,19 +107,20 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
function fixupEncoding(value) {
|
||||
if (needsEncodingFixup && /[\x80-\xff]/.test(value)) {
|
||||
// Maybe multi-byte UTF-8.
|
||||
value = textdecode('utf-8', value);
|
||||
value = textdecode("utf-8", value);
|
||||
if (needsEncodingFixup) {
|
||||
// Try iso-8859-1 encoding.
|
||||
value = textdecode('iso-8859-1', value);
|
||||
value = textdecode("iso-8859-1", value);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
function rfc2231getparam(contentDisposition) {
|
||||
let matches = [], match;
|
||||
let matches = [],
|
||||
match;
|
||||
// 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'.
|
||||
let iter = toParamRegExp('filename\\*((?!0\\d)\\d+)(\\*?)', 'ig');
|
||||
let iter = toParamRegExp("filename\\*((?!0\\d)\\d+)(\\*?)", "ig");
|
||||
while ((match = iter.exec(contentDisposition)) !== null) {
|
||||
let [, n, quot, part] = match;
|
||||
n = parseInt(n, 10);
|
||||
@ -145,7 +149,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
}
|
||||
parts.push(part);
|
||||
}
|
||||
return parts.join('');
|
||||
return parts.join("");
|
||||
}
|
||||
function rfc2616unquote(value) {
|
||||
if (value.startsWith('"')) {
|
||||
@ -157,7 +161,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
parts[i] = parts[i].slice(0, quotindex);
|
||||
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('"');
|
||||
}
|
||||
@ -165,7 +169,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
}
|
||||
function rfc5987decode(extvalue) {
|
||||
// Decodes "ext-value" from RFC 5987.
|
||||
let encodingend = extvalue.indexOf('\'');
|
||||
let encodingend = extvalue.indexOf("'");
|
||||
if (encodingend === -1) {
|
||||
// Some servers send "filename*=" without encoding 'language' prefix,
|
||||
// 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 langvalue = extvalue.slice(encodingend + 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);
|
||||
}
|
||||
function rfc2047decode(value) {
|
||||
@ -189,7 +193,7 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
|
||||
// Firefox also decodes words even where RFC 2047 section 5 states:
|
||||
// "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;
|
||||
}
|
||||
// RFC 2047, section 2.4
|
||||
@ -199,11 +203,12 @@ function getFilenameFromContentDispositionHeader(contentDisposition) {
|
||||
// encoding = q or b
|
||||
// encoded-text = any printable ASCII character other than ? or space.
|
||||
// ... but Firefox permits ? and space.
|
||||
return value.replace(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g,
|
||||
return value.replace(
|
||||
/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g,
|
||||
function(_, charset, encoding, text) {
|
||||
if (encoding === 'q' || encoding === 'Q') {
|
||||
if (encoding === "q" || encoding === "Q") {
|
||||
// RFC 2047 section 4.2.
|
||||
text = text.replace(/_/g, ' ');
|
||||
text = text.replace(/_/g, " ");
|
||||
text = text.replace(/=([0-9a-fA-F]{2})/g, function(_, hex) {
|
||||
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)
|
||||
try {
|
||||
text = atob(text);
|
||||
} catch (e) {
|
||||
}
|
||||
} catch (e) {}
|
||||
return textdecode(charset, text);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return '';
|
||||
return "";
|
||||
}
|
||||
|
||||
export {
|
||||
getFilenameFromContentDispositionHeader,
|
||||
};
|
||||
export { getFilenameFromContentDispositionHeader };
|
||||
|
@ -15,20 +15,26 @@
|
||||
/* eslint no-var: error */
|
||||
|
||||
import {
|
||||
assert, BaseException, CMapCompressionType, isString, removeNullCharacters,
|
||||
stringToBytes, Util, warn
|
||||
} from '../shared/util';
|
||||
assert,
|
||||
BaseException,
|
||||
CMapCompressionType,
|
||||
isString,
|
||||
removeNullCharacters,
|
||||
stringToBytes,
|
||||
Util,
|
||||
warn,
|
||||
} from "../shared/util";
|
||||
|
||||
const DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
|
||||
const SVG_NS = 'http://www.w3.org/2000/svg';
|
||||
const DEFAULT_LINK_REL = "noopener noreferrer nofollow";
|
||||
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||
|
||||
class DOMCanvasFactory {
|
||||
create(width, height) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new Error('Invalid canvas size');
|
||||
throw new Error("Invalid canvas size");
|
||||
}
|
||||
const canvas = document.createElement('canvas');
|
||||
const context = canvas.getContext('2d');
|
||||
const canvas = document.createElement("canvas");
|
||||
const context = canvas.getContext("2d");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return {
|
||||
@ -39,10 +45,10 @@ class DOMCanvasFactory {
|
||||
|
||||
reset(canvasAndContext, width, height) {
|
||||
if (!canvasAndContext.canvas) {
|
||||
throw new Error('Canvas is not specified');
|
||||
throw new Error("Canvas is not specified");
|
||||
}
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new Error('Invalid canvas size');
|
||||
throw new Error("Invalid canvas size");
|
||||
}
|
||||
canvasAndContext.canvas.width = width;
|
||||
canvasAndContext.canvas.height = height;
|
||||
@ -50,7 +56,7 @@ class DOMCanvasFactory {
|
||||
|
||||
destroy(canvasAndContext) {
|
||||
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
|
||||
// resources immediately, which can greatly reduce memory consumption.
|
||||
@ -62,27 +68,32 @@ class DOMCanvasFactory {
|
||||
}
|
||||
|
||||
class DOMCMapReaderFactory {
|
||||
constructor({ baseUrl = null, isCompressed = false, }) {
|
||||
constructor({ baseUrl = null, isCompressed = false }) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.isCompressed = isCompressed;
|
||||
}
|
||||
|
||||
async fetch({ name, }) {
|
||||
async fetch({ name }) {
|
||||
if (!this.baseUrl) {
|
||||
throw new Error(
|
||||
'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) {
|
||||
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 compressionType = (this.isCompressed ? CMapCompressionType.BINARY :
|
||||
CMapCompressionType.NONE);
|
||||
const url = this.baseUrl + name + (this.isCompressed ? ".bcmap" : "");
|
||||
const compressionType = this.isCompressed
|
||||
? CMapCompressionType.BINARY
|
||||
: CMapCompressionType.NONE;
|
||||
|
||||
if ((typeof PDFJSDev !== 'undefined' && PDFJSDev.test('MOZCENTRAL')) ||
|
||||
(isFetchSupported() && isValidFetchUrl(url, document.baseURI))) {
|
||||
return fetch(url).then(async (response) => {
|
||||
if (
|
||||
(typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) ||
|
||||
(isFetchSupported() && isValidFetchUrl(url, document.baseURI))
|
||||
) {
|
||||
return fetch(url)
|
||||
.then(async response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
@ -92,20 +103,23 @@ class DOMCMapReaderFactory {
|
||||
} else {
|
||||
cMapData = stringToBytes(await response.text());
|
||||
}
|
||||
return { cMapData, compressionType, };
|
||||
}).catch((reason) => {
|
||||
throw new Error(`Unable to load ${this.isCompressed ? 'binary ' : ''}` +
|
||||
`CMap at: ${url}`);
|
||||
return { cMapData, compressionType };
|
||||
})
|
||||
.catch(reason => {
|
||||
throw new Error(
|
||||
`Unable to load ${this.isCompressed ? "binary " : ""}` +
|
||||
`CMap at: ${url}`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// The Fetch API is not supported.
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = new XMLHttpRequest();
|
||||
request.open('GET', url, true);
|
||||
request.open("GET", url, true);
|
||||
|
||||
if (this.isCompressed) {
|
||||
request.responseType = 'arraybuffer';
|
||||
request.responseType = "arraybuffer";
|
||||
}
|
||||
request.onreadystatechange = () => {
|
||||
if (request.readyState !== XMLHttpRequest.DONE) {
|
||||
@ -119,7 +133,7 @@ class DOMCMapReaderFactory {
|
||||
cMapData = stringToBytes(request.responseText);
|
||||
}
|
||||
if (cMapData) {
|
||||
resolve({ cMapData, compressionType, });
|
||||
resolve({ cMapData, compressionType });
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -127,29 +141,31 @@ class DOMCMapReaderFactory {
|
||||
};
|
||||
|
||||
request.send(null);
|
||||
}).catch((reason) => {
|
||||
throw new Error(`Unable to load ${this.isCompressed ? 'binary ' : ''}` +
|
||||
`CMap at: ${url}`);
|
||||
}).catch(reason => {
|
||||
throw new Error(
|
||||
`Unable to load ${this.isCompressed ? "binary " : ""}` +
|
||||
`CMap at: ${url}`
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class DOMSVGFactory {
|
||||
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');
|
||||
svg.setAttribute('version', '1.1');
|
||||
svg.setAttribute('width', width + 'px');
|
||||
svg.setAttribute('height', height + 'px');
|
||||
svg.setAttribute('preserveAspectRatio', 'none');
|
||||
svg.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
|
||||
const svg = document.createElementNS(SVG_NS, "svg:svg");
|
||||
svg.setAttribute("version", "1.1");
|
||||
svg.setAttribute("width", width + "px");
|
||||
svg.setAttribute("height", height + "px");
|
||||
svg.setAttribute("preserveAspectRatio", "none");
|
||||
svg.setAttribute("viewBox", "0 0 " + width + " " + height);
|
||||
|
||||
return svg;
|
||||
}
|
||||
|
||||
createElement(type) {
|
||||
assert(typeof type === 'string', 'Invalid SVG element type');
|
||||
assert(typeof type === "string", "Invalid SVG element type");
|
||||
|
||||
return document.createElementNS(SVG_NS, type);
|
||||
}
|
||||
@ -189,8 +205,14 @@ class PageViewport {
|
||||
/**
|
||||
* @param {PageViewportParameters}
|
||||
*/
|
||||
constructor({ viewBox, scale, rotation, offsetX = 0, offsetY = 0,
|
||||
dontFlip = false, }) {
|
||||
constructor({
|
||||
viewBox,
|
||||
scale,
|
||||
rotation,
|
||||
offsetX = 0,
|
||||
offsetY = 0,
|
||||
dontFlip = false,
|
||||
}) {
|
||||
this.viewBox = viewBox;
|
||||
this.scale = scale;
|
||||
this.rotation = rotation;
|
||||
@ -206,22 +228,35 @@ class PageViewport {
|
||||
rotation = rotation < 0 ? rotation + 360 : rotation;
|
||||
switch (rotation) {
|
||||
case 180:
|
||||
rotateA = -1; rotateB = 0; rotateC = 0; rotateD = 1;
|
||||
rotateA = -1;
|
||||
rotateB = 0;
|
||||
rotateC = 0;
|
||||
rotateD = 1;
|
||||
break;
|
||||
case 90:
|
||||
rotateA = 0; rotateB = 1; rotateC = 1; rotateD = 0;
|
||||
rotateA = 0;
|
||||
rotateB = 1;
|
||||
rotateC = 1;
|
||||
rotateD = 0;
|
||||
break;
|
||||
case 270:
|
||||
rotateA = 0; rotateB = -1; rotateC = -1; rotateD = 0;
|
||||
rotateA = 0;
|
||||
rotateB = -1;
|
||||
rotateC = -1;
|
||||
rotateD = 0;
|
||||
break;
|
||||
// case 0:
|
||||
default:
|
||||
rotateA = 1; rotateB = 0; rotateC = 0; rotateD = -1;
|
||||
rotateA = 1;
|
||||
rotateB = 0;
|
||||
rotateC = 0;
|
||||
rotateD = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dontFlip) {
|
||||
rotateC = -rotateC; rotateD = -rotateD;
|
||||
rotateC = -rotateC;
|
||||
rotateD = -rotateD;
|
||||
}
|
||||
|
||||
let offsetCanvasX, offsetCanvasY;
|
||||
@ -246,7 +281,7 @@ class PageViewport {
|
||||
rotateC * scale,
|
||||
rotateD * scale,
|
||||
offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY,
|
||||
offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY
|
||||
offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY,
|
||||
];
|
||||
|
||||
this.width = width;
|
||||
@ -258,8 +293,13 @@ class PageViewport {
|
||||
* @param {PageViewportCloneParameters} [params]
|
||||
* @returns {PageViewport} Cloned viewport.
|
||||
*/
|
||||
clone({ scale = this.scale, rotation = this.rotation, offsetX = this.offsetX,
|
||||
offsetY = this.offsetY, dontFlip = false, } = {}) {
|
||||
clone({
|
||||
scale = this.scale,
|
||||
rotation = this.rotation,
|
||||
offsetX = this.offsetX,
|
||||
offsetY = this.offsetY,
|
||||
dontFlip = false,
|
||||
} = {}) {
|
||||
return new PageViewport({
|
||||
viewBox: this.viewBox.slice(),
|
||||
scale,
|
||||
@ -343,50 +383,54 @@ const LinkTarget = {
|
||||
* @param {HTMLLinkElement} link - The link element.
|
||||
* @param {ExternalLinkParameters} params
|
||||
*/
|
||||
function addLinkAttributes(link, { url, target, rel, enabled = true, } = {}) {
|
||||
assert(url && typeof url === 'string',
|
||||
'addLinkAttributes: A valid "url" parameter must provided.');
|
||||
function addLinkAttributes(link, { url, target, rel, enabled = true } = {}) {
|
||||
assert(
|
||||
url && typeof url === "string",
|
||||
'addLinkAttributes: A valid "url" parameter must provided.'
|
||||
);
|
||||
|
||||
const urlNullRemoved = removeNullCharacters(url);
|
||||
if (enabled) {
|
||||
link.href = link.title = urlNullRemoved;
|
||||
} else {
|
||||
link.href = '';
|
||||
link.href = "";
|
||||
link.title = `Disabled: ${urlNullRemoved}`;
|
||||
link.onclick = () => {
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
let targetStr = ''; // LinkTarget.NONE
|
||||
let targetStr = ""; // LinkTarget.NONE
|
||||
switch (target) {
|
||||
case LinkTarget.NONE:
|
||||
break;
|
||||
case LinkTarget.SELF:
|
||||
targetStr = '_self';
|
||||
targetStr = "_self";
|
||||
break;
|
||||
case LinkTarget.BLANK:
|
||||
targetStr = '_blank';
|
||||
targetStr = "_blank";
|
||||
break;
|
||||
case LinkTarget.PARENT:
|
||||
targetStr = '_parent';
|
||||
targetStr = "_parent";
|
||||
break;
|
||||
case LinkTarget.TOP:
|
||||
targetStr = '_top';
|
||||
targetStr = "_top";
|
||||
break;
|
||||
}
|
||||
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.
|
||||
function getFilenameFromUrl(url) {
|
||||
const anchor = url.indexOf('#');
|
||||
const query = url.indexOf('?');
|
||||
const end = Math.min(anchor > 0 ? anchor : url.length,
|
||||
query > 0 ? query : url.length);
|
||||
return url.substring(url.lastIndexOf('/', end) + 1, end);
|
||||
const anchor = url.indexOf("#");
|
||||
const query = url.indexOf("?");
|
||||
const end = Math.min(
|
||||
anchor > 0 ? anchor : url.length,
|
||||
query > 0 ? query : url.length
|
||||
);
|
||||
return url.substring(url.lastIndexOf("/", end) + 1, end);
|
||||
}
|
||||
|
||||
class StatTimer {
|
||||
@ -407,9 +451,9 @@ class StatTimer {
|
||||
warn(`Timer has not been started for ${name}`);
|
||||
}
|
||||
this.times.push({
|
||||
'name': name,
|
||||
'start': this.started[name],
|
||||
'end': Date.now(),
|
||||
name,
|
||||
start: this.started[name],
|
||||
end: Date.now(),
|
||||
});
|
||||
// Remove timer from started so it can be called again.
|
||||
delete this.started[name];
|
||||
@ -417,7 +461,8 @@ class StatTimer {
|
||||
|
||||
toString() {
|
||||
// Find the longest name for padding purposes.
|
||||
let outBuf = [], longest = 0;
|
||||
let outBuf = [],
|
||||
longest = 0;
|
||||
for (const time of this.times) {
|
||||
const name = time.name;
|
||||
if (name.length > longest) {
|
||||
@ -428,21 +473,24 @@ class StatTimer {
|
||||
const duration = time.end - time.start;
|
||||
outBuf.push(`${time.name.padEnd(longest)} ${duration}ms\n`);
|
||||
}
|
||||
return outBuf.join('');
|
||||
return outBuf.join("");
|
||||
}
|
||||
}
|
||||
|
||||
function isFetchSupported() {
|
||||
return (typeof fetch !== 'undefined' &&
|
||||
typeof Response !== 'undefined' && 'body' in Response.prototype &&
|
||||
typeof ReadableStream !== 'undefined');
|
||||
return (
|
||||
typeof fetch !== "undefined" &&
|
||||
typeof Response !== "undefined" &&
|
||||
"body" in Response.prototype &&
|
||||
typeof ReadableStream !== "undefined"
|
||||
);
|
||||
}
|
||||
|
||||
function isValidFetchUrl(url, baseUrl) {
|
||||
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.
|
||||
return (protocol === 'http:' || protocol === 'https:');
|
||||
return protocol === "http:" || protocol === "https:";
|
||||
} catch (ex) {
|
||||
return false; // `new URL()` will throw on incorrect data.
|
||||
}
|
||||
@ -450,7 +498,7 @@ function isValidFetchUrl(url, baseUrl) {
|
||||
|
||||
function loadScript(src) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
const script = document.createElement("script");
|
||||
script.src = src;
|
||||
|
||||
script.onload = resolve;
|
||||
@ -463,18 +511,21 @@ function loadScript(src) {
|
||||
|
||||
// Deprecated API function -- display regardless of the `verbosity` setting.
|
||||
function deprecated(details) {
|
||||
console.log('Deprecated API usage: ' + details);
|
||||
console.log("Deprecated API usage: " + details);
|
||||
}
|
||||
|
||||
function releaseImageResources(img) {
|
||||
assert(img instanceof Image, 'Invalid `img` parameter.');
|
||||
assert(img instanceof Image, "Invalid `img` parameter.");
|
||||
|
||||
const url = img.src;
|
||||
if (typeof url === 'string' && url.startsWith('blob:') &&
|
||||
URL.revokeObjectURL) {
|
||||
if (
|
||||
typeof url === "string" &&
|
||||
url.startsWith("blob:") &&
|
||||
URL.revokeObjectURL
|
||||
) {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
img.removeAttribute('src');
|
||||
img.removeAttribute("src");
|
||||
}
|
||||
|
||||
let pdfDateStringRegex;
|
||||
@ -504,18 +555,18 @@ class PDFDateString {
|
||||
// Lazily initialize the regular expression.
|
||||
if (!pdfDateStringRegex) {
|
||||
pdfDateStringRegex = new RegExp(
|
||||
'^D:' + // Prefix (required)
|
||||
'(\\d{4})' + // Year (required)
|
||||
'(\\d{2})?' + // Month (optional)
|
||||
'(\\d{2})?' + // Day (optional)
|
||||
'(\\d{2})?' + // Hour (optional)
|
||||
'(\\d{2})?' + // Minute (optional)
|
||||
'(\\d{2})?' + // Second (optional)
|
||||
'([Z|+|-])?' + // Universal time relation (optional)
|
||||
'(\\d{2})?' + // Offset hour (optional)
|
||||
'\'?' + // Splitting apostrophe (optional)
|
||||
'(\\d{2})?' + // Offset minute (optional)
|
||||
'\'?' // Trailing apostrophe (optional)
|
||||
"^D:" + // Prefix (required)
|
||||
"(\\d{4})" + // Year (required)
|
||||
"(\\d{2})?" + // Month (optional)
|
||||
"(\\d{2})?" + // Day (optional)
|
||||
"(\\d{2})?" + // Hour (optional)
|
||||
"(\\d{2})?" + // Minute (optional)
|
||||
"(\\d{2})?" + // Second (optional)
|
||||
"([Z|+|-])?" + // Universal time relation (optional)
|
||||
"(\\d{2})?" + // Offset hour (optional)
|
||||
"'?" + // Splitting apostrophe (optional)
|
||||
"(\\d{2})?" + // Offset minute (optional)
|
||||
"'?" // Trailing apostrophe (optional)
|
||||
);
|
||||
}
|
||||
|
||||
@ -531,29 +582,29 @@ class PDFDateString {
|
||||
// instead of 1 and 12, so we have to correct for that.
|
||||
const year = parseInt(matches[1], 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);
|
||||
day = (day >= 1 && day <= 31) ? day : 1;
|
||||
day = day >= 1 && day <= 31 ? day : 1;
|
||||
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);
|
||||
minute = (minute >= 0 && minute <= 59) ? minute : 0;
|
||||
minute = minute >= 0 && minute <= 59 ? minute : 0;
|
||||
let second = parseInt(matches[6], 10);
|
||||
second = (second >= 0 && second <= 59) ? second : 0;
|
||||
const universalTimeRelation = matches[7] || 'Z';
|
||||
second = second >= 0 && second <= 59 ? second : 0;
|
||||
const universalTimeRelation = matches[7] || "Z";
|
||||
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;
|
||||
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, whereas the relations '+'/'-' indicate that the local
|
||||
// time is later respectively earlier than the universal time. Every date
|
||||
// is normalized to universal time.
|
||||
if (universalTimeRelation === '-') {
|
||||
if (universalTimeRelation === "-") {
|
||||
hour += offsetHour;
|
||||
minute += offsetMinute;
|
||||
} else if (universalTimeRelation === '+') {
|
||||
} else if (universalTimeRelation === "+") {
|
||||
hour -= offsetHour;
|
||||
minute -= offsetMinute;
|
||||
}
|
||||
|
@ -15,21 +15,25 @@
|
||||
/* eslint no-var: error */
|
||||
|
||||
import {
|
||||
AbortException, assert, createPromiseCapability
|
||||
} from '../shared/util';
|
||||
AbortException,
|
||||
assert,
|
||||
createPromiseCapability,
|
||||
} from "../shared/util";
|
||||
import {
|
||||
createResponseStatusError, extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities, validateResponseStatus
|
||||
} from './network_utils';
|
||||
createResponseStatusError,
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
validateResponseStatus,
|
||||
} from "./network_utils";
|
||||
|
||||
function createFetchOptions(headers, withCredentials, abortController) {
|
||||
return {
|
||||
method: 'GET',
|
||||
method: "GET",
|
||||
headers,
|
||||
signal: abortController && abortController.signal,
|
||||
mode: 'cors',
|
||||
credentials: withCredentials ? 'include' : 'same-origin',
|
||||
redirect: 'follow',
|
||||
mode: "cors",
|
||||
credentials: withCredentials ? "include" : "same-origin",
|
||||
redirect: "follow",
|
||||
};
|
||||
}
|
||||
|
||||
@ -37,7 +41,7 @@ function createHeaders(httpHeaders) {
|
||||
const headers = new Headers();
|
||||
for (const property in httpHeaders) {
|
||||
const value = httpHeaders[property];
|
||||
if (typeof value === 'undefined') {
|
||||
if (typeof value === "undefined") {
|
||||
continue;
|
||||
}
|
||||
headers.append(property, value);
|
||||
@ -57,7 +61,7 @@ class PDFFetchStream {
|
||||
}
|
||||
|
||||
get _progressiveDataLength() {
|
||||
return (this._fullRequestReader ? this._fullRequestReader._loaded : 0);
|
||||
return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
|
||||
}
|
||||
|
||||
getFullReader() {
|
||||
@ -103,7 +107,7 @@ class PDFFetchStreamReader {
|
||||
this._disableRange = true;
|
||||
}
|
||||
|
||||
if (typeof AbortController !== 'undefined') {
|
||||
if (typeof AbortController !== "undefined") {
|
||||
this._abortController = new AbortController();
|
||||
}
|
||||
this._isStreamingSupported = !source.disableStream;
|
||||
@ -112,19 +116,28 @@ class PDFFetchStreamReader {
|
||||
this._headers = createHeaders(this._stream.httpHeaders);
|
||||
|
||||
const url = source.url;
|
||||
fetch(url, createFetchOptions(this._headers, this._withCredentials,
|
||||
this._abortController)).then((response) => {
|
||||
fetch(
|
||||
url,
|
||||
createFetchOptions(
|
||||
this._headers,
|
||||
this._withCredentials,
|
||||
this._abortController
|
||||
)
|
||||
)
|
||||
.then(response => {
|
||||
if (!validateResponseStatus(response.status)) {
|
||||
throw createResponseStatusError(response.status, url);
|
||||
}
|
||||
this._reader = response.body.getReader();
|
||||
this._headersCapability.resolve();
|
||||
|
||||
const getResponseHeader = (name) => {
|
||||
const getResponseHeader = name => {
|
||||
return response.headers.get(name);
|
||||
};
|
||||
const { allowRangeRequests, suggestedLength, } =
|
||||
validateRangeRequestCapabilities({
|
||||
const {
|
||||
allowRangeRequests,
|
||||
suggestedLength,
|
||||
} = validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
isHttp: this._stream.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
@ -140,9 +153,10 @@ class PDFFetchStreamReader {
|
||||
// We need to stop reading when range is supported and streaming is
|
||||
// disabled.
|
||||
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;
|
||||
}
|
||||
@ -169,9 +183,9 @@ class PDFFetchStreamReader {
|
||||
|
||||
async read() {
|
||||
await this._headersCapability.promise;
|
||||
const { value, done, } = await this._reader.read();
|
||||
const { value, done } = await this._reader.read();
|
||||
if (done) {
|
||||
return { value, done, };
|
||||
return { value, done };
|
||||
}
|
||||
this._loaded += value.byteLength;
|
||||
if (this.onProgress) {
|
||||
@ -181,7 +195,7 @@ class PDFFetchStreamReader {
|
||||
});
|
||||
}
|
||||
const buffer = new Uint8Array(value).buffer;
|
||||
return { value: buffer, done: false, };
|
||||
return { value: buffer, done: false };
|
||||
}
|
||||
|
||||
cancel(reason) {
|
||||
@ -205,16 +219,22 @@ class PDFFetchStreamRangeReader {
|
||||
this._readCapability = createPromiseCapability();
|
||||
this._isStreamingSupported = !source.disableStream;
|
||||
|
||||
if (typeof AbortController !== 'undefined') {
|
||||
if (typeof AbortController !== "undefined") {
|
||||
this._abortController = new AbortController();
|
||||
}
|
||||
|
||||
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;
|
||||
fetch(url, createFetchOptions(this._headers, this._withCredentials,
|
||||
this._abortController)).then((response) => {
|
||||
fetch(
|
||||
url,
|
||||
createFetchOptions(
|
||||
this._headers,
|
||||
this._withCredentials,
|
||||
this._abortController
|
||||
)
|
||||
).then(response => {
|
||||
if (!validateResponseStatus(response.status)) {
|
||||
throw createResponseStatusError(response.status, url);
|
||||
}
|
||||
@ -231,16 +251,16 @@ class PDFFetchStreamRangeReader {
|
||||
|
||||
async read() {
|
||||
await this._readCapability.promise;
|
||||
const { value, done, } = await this._reader.read();
|
||||
const { value, done } = await this._reader.read();
|
||||
if (done) {
|
||||
return { value, done, };
|
||||
return { value, done };
|
||||
}
|
||||
this._loaded += value.byteLength;
|
||||
if (this.onProgress) {
|
||||
this.onProgress({ loaded: this._loaded, });
|
||||
this.onProgress({ loaded: this._loaded });
|
||||
}
|
||||
const buffer = new Uint8Array(value).buffer;
|
||||
return { value: buffer, done: false, };
|
||||
return { value: buffer, done: false };
|
||||
}
|
||||
|
||||
cancel(reason) {
|
||||
@ -253,6 +273,4 @@ class PDFFetchStreamRangeReader {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PDFFetchStream,
|
||||
};
|
||||
export { PDFFetchStream };
|
||||
|
@ -14,14 +14,20 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
assert, bytesToString, isEvalSupported, shadow, string32, unreachable,
|
||||
UNSUPPORTED_FEATURES, warn
|
||||
} from '../shared/util';
|
||||
assert,
|
||||
bytesToString,
|
||||
isEvalSupported,
|
||||
shadow,
|
||||
string32,
|
||||
unreachable,
|
||||
UNSUPPORTED_FEATURES,
|
||||
warn,
|
||||
} from "../shared/util";
|
||||
|
||||
class BaseFontLoader {
|
||||
constructor({ docId, onUnsupportedFeature, }) {
|
||||
constructor({ docId, onUnsupportedFeature }) {
|
||||
if (this.constructor === BaseFontLoader) {
|
||||
unreachable('Cannot initialize BaseFontLoader.');
|
||||
unreachable("Cannot initialize BaseFontLoader.");
|
||||
}
|
||||
this.docId = docId;
|
||||
this._onUnsupportedFeature = onUnsupportedFeature;
|
||||
@ -38,10 +44,11 @@ class BaseFontLoader {
|
||||
insertRule(rule) {
|
||||
let styleElement = this.styleElement;
|
||||
if (!styleElement) {
|
||||
styleElement = this.styleElement = document.createElement('style');
|
||||
styleElement = this.styleElement = document.createElement("style");
|
||||
styleElement.id = `PDFJS_FONT_STYLE_TAG_${this.docId}`;
|
||||
document.documentElement.getElementsByTagName('head')[0].appendChild(
|
||||
styleElement);
|
||||
document.documentElement
|
||||
.getElementsByTagName("head")[0]
|
||||
.appendChild(styleElement);
|
||||
}
|
||||
|
||||
const styleSheet = styleElement.sheet;
|
||||
@ -75,7 +82,7 @@ class BaseFontLoader {
|
||||
try {
|
||||
await nativeFontFace.loaded;
|
||||
} catch (ex) {
|
||||
this._onUnsupportedFeature({ featureId: UNSUPPORTED_FEATURES.font, });
|
||||
this._onUnsupportedFeature({ featureId: UNSUPPORTED_FEATURES.font });
|
||||
warn(`Failed to load font '${nativeFontFace.family}': '${ex}'.`);
|
||||
|
||||
// When font loading failed, fall back to the built-in font renderer.
|
||||
@ -94,7 +101,7 @@ class BaseFontLoader {
|
||||
if (this.isSyncFontLoadingSupported) {
|
||||
return undefined; // The font was, synchronously, loaded.
|
||||
}
|
||||
return new Promise((resolve) => {
|
||||
return new Promise(resolve => {
|
||||
const request = this._queueLoadingCallback(resolve);
|
||||
this._prepareFontLoadEvent([rule], [font], request);
|
||||
});
|
||||
@ -103,43 +110,48 @@ class BaseFontLoader {
|
||||
}
|
||||
|
||||
_queueLoadingCallback(callback) {
|
||||
unreachable('Abstract method `_queueLoadingCallback`.');
|
||||
unreachable("Abstract method `_queueLoadingCallback`.");
|
||||
}
|
||||
|
||||
get isFontLoadingAPISupported() { // eslint-disable-line getter-return
|
||||
unreachable('Abstract method `isFontLoadingAPISupported`.');
|
||||
get isFontLoadingAPISupported() {
|
||||
// eslint-disable-line getter-return
|
||||
unreachable("Abstract method `isFontLoadingAPISupported`.");
|
||||
}
|
||||
|
||||
get isSyncFontLoadingSupported() { // eslint-disable-line getter-return
|
||||
unreachable('Abstract method `isSyncFontLoadingSupported`.');
|
||||
get isSyncFontLoadingSupported() {
|
||||
// eslint-disable-line getter-return
|
||||
unreachable("Abstract method `isSyncFontLoadingSupported`.");
|
||||
}
|
||||
|
||||
get _loadTestFont() { // eslint-disable-line getter-return
|
||||
unreachable('Abstract method `_loadTestFont`.');
|
||||
get _loadTestFont() {
|
||||
// eslint-disable-line getter-return
|
||||
unreachable("Abstract method `_loadTestFont`.");
|
||||
}
|
||||
|
||||
_prepareFontLoadEvent(rules, fontsToLoad, request) {
|
||||
unreachable('Abstract method `_prepareFontLoadEvent`.');
|
||||
unreachable("Abstract method `_prepareFontLoadEvent`.");
|
||||
}
|
||||
}
|
||||
|
||||
let FontLoader;
|
||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('MOZCENTRAL')) {
|
||||
|
||||
FontLoader = class MozcentralFontLoader extends BaseFontLoader {
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
||||
FontLoader = class MozcentralFontLoader extends BaseFontLoader {
|
||||
get isFontLoadingAPISupported() {
|
||||
return shadow(this, 'isFontLoadingAPISupported',
|
||||
typeof document !== 'undefined' && !!document.fonts);
|
||||
return shadow(
|
||||
this,
|
||||
"isFontLoadingAPISupported",
|
||||
typeof document !== "undefined" && !!document.fonts
|
||||
);
|
||||
}
|
||||
|
||||
get isSyncFontLoadingSupported() {
|
||||
return shadow(this, 'isSyncFontLoadingSupported', true);
|
||||
return shadow(this, "isSyncFontLoadingSupported", true);
|
||||
}
|
||||
};
|
||||
};
|
||||
} else {
|
||||
// PDFJSDev.test('CHROME || GENERIC')
|
||||
|
||||
} else { // PDFJSDev.test('CHROME || GENERIC')
|
||||
|
||||
FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||
FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||
constructor(docId) {
|
||||
super(docId);
|
||||
this.loadingContext = {
|
||||
@ -150,10 +162,13 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||
}
|
||||
|
||||
get isFontLoadingAPISupported() {
|
||||
let supported = (typeof document !== 'undefined' && !!document.fonts);
|
||||
let supported = typeof document !== "undefined" && !!document.fonts;
|
||||
|
||||
if ((typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME')) &&
|
||||
(supported && typeof navigator !== 'undefined')) {
|
||||
if (
|
||||
(typeof PDFJSDev === "undefined" || !PDFJSDev.test("CHROME")) &&
|
||||
supported &&
|
||||
typeof navigator !== "undefined"
|
||||
) {
|
||||
// The Firefox Font Loading API does not work with `mozPrintCallback`
|
||||
// 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);
|
||||
@ -161,31 +176,33 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||
supported = false;
|
||||
}
|
||||
}
|
||||
return shadow(this, 'isFontLoadingAPISupported', supported);
|
||||
return shadow(this, "isFontLoadingAPISupported", supported);
|
||||
}
|
||||
|
||||
get isSyncFontLoadingSupported() {
|
||||
let supported = false;
|
||||
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('CHROME')) {
|
||||
if (typeof navigator === 'undefined') {
|
||||
if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("CHROME")) {
|
||||
if (typeof navigator === "undefined") {
|
||||
// Node.js - we can pretend that sync font loading is supported.
|
||||
supported = true;
|
||||
} else {
|
||||
// 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.
|
||||
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) {
|
||||
supported = true;
|
||||
}
|
||||
// TODO - other browsers...
|
||||
}
|
||||
}
|
||||
return shadow(this, 'isSyncFontLoadingSupported', supported);
|
||||
return shadow(this, "isSyncFontLoadingSupported", supported);
|
||||
}
|
||||
|
||||
_queueLoadingCallback(callback) {
|
||||
function completeRequest() {
|
||||
assert(!request.done, 'completeRequest() cannot be called twice.');
|
||||
assert(!request.done, "completeRequest() cannot be called twice.");
|
||||
request.done = true;
|
||||
|
||||
// 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
|
||||
// height.
|
||||
return atob(
|
||||
'T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA' +
|
||||
'FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA' +
|
||||
'ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA' +
|
||||
'AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1' +
|
||||
'AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD' +
|
||||
'6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM' +
|
||||
'AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D' +
|
||||
'IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA' +
|
||||
'AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA' +
|
||||
'AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB' +
|
||||
'AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY' +
|
||||
'AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA' +
|
||||
'AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' +
|
||||
'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA' +
|
||||
'AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC' +
|
||||
'AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3' +
|
||||
'Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj' +
|
||||
'FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA==');
|
||||
"T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA" +
|
||||
"FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA" +
|
||||
"ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA" +
|
||||
"AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1" +
|
||||
"AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD" +
|
||||
"6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM" +
|
||||
"AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D" +
|
||||
"IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA" +
|
||||
"AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA" +
|
||||
"AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB" +
|
||||
"AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY" +
|
||||
"AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA" +
|
||||
"AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||
"AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" +
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA" +
|
||||
"AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC" +
|
||||
"AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3" +
|
||||
"Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj" +
|
||||
"FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA=="
|
||||
);
|
||||
};
|
||||
return shadow(this, '_loadTestFont', getLoadTestFont());
|
||||
return shadow(this, "_loadTestFont", getLoadTestFont());
|
||||
}
|
||||
|
||||
_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.
|
||||
|
||||
function int32(data, offset) {
|
||||
return (data.charCodeAt(offset) << 24) |
|
||||
return (
|
||||
(data.charCodeAt(offset) << 24) |
|
||||
(data.charCodeAt(offset + 1) << 16) |
|
||||
(data.charCodeAt(offset + 2) << 8) |
|
||||
(data.charCodeAt(offset + 3) & 0xff);
|
||||
(data.charCodeAt(offset + 3) & 0xff)
|
||||
);
|
||||
}
|
||||
function spliceString(s, offset, remove, insert) {
|
||||
let chunk1 = s.substring(0, offset);
|
||||
@ -258,22 +278,22 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||
let i, ii;
|
||||
|
||||
// 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.height = 1;
|
||||
let ctx = canvas.getContext('2d');
|
||||
let ctx = canvas.getContext("2d");
|
||||
|
||||
let called = 0;
|
||||
function isFontReady(name, callback) {
|
||||
called++;
|
||||
// With setTimeout clamping this gives the font ~100ms to load.
|
||||
if (called > 30) {
|
||||
warn('Load test font never loaded.');
|
||||
warn("Load test font never loaded.");
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
ctx.font = '30px ' + name;
|
||||
ctx.fillText('.', 0, 20);
|
||||
ctx.font = "30px " + name;
|
||||
ctx.fillText(".", 0, 20);
|
||||
let imageData = ctx.getImageData(0, 0, 1, 1);
|
||||
if (imageData.data[3] > 0) {
|
||||
callback();
|
||||
@ -290,8 +310,12 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||
// font by splitting it in chunks before hand and padding the font id.
|
||||
let data = this._loadTestFont;
|
||||
let COMMENT_OFFSET = 976; // has to be on 4 byte boundary (for checksum)
|
||||
data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length,
|
||||
loadTestFontId);
|
||||
data = spliceString(
|
||||
data,
|
||||
COMMENT_OFFSET,
|
||||
loadTestFontId.length,
|
||||
loadTestFontId
|
||||
);
|
||||
// CFF checksum is important for IE, adjusting it
|
||||
let CFF_CHECKSUM_OFFSET = 16;
|
||||
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) {
|
||||
checksum = (checksum - XXXX_VALUE + int32(loadTestFontId, i)) | 0;
|
||||
}
|
||||
if (i < loadTestFontId.length) { // align to 4 bytes boundary
|
||||
checksum = (checksum - XXXX_VALUE + int32(loadTestFontId + 'XXX', i)) | 0;
|
||||
if (i < loadTestFontId.length) {
|
||||
// align to 4 bytes boundary
|
||||
checksum =
|
||||
(checksum - XXXX_VALUE + int32(loadTestFontId + "XXX", i)) | 0;
|
||||
}
|
||||
data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum));
|
||||
|
||||
@ -314,13 +340,16 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||
}
|
||||
names.push(loadTestFontId);
|
||||
|
||||
let div = document.createElement('div');
|
||||
div.setAttribute('style', 'visibility: hidden;' +
|
||||
'width: 10px; height: 10px;' +
|
||||
'position: absolute; top: 0px; left: 0px;');
|
||||
let div = document.createElement("div");
|
||||
div.setAttribute(
|
||||
"style",
|
||||
"visibility: hidden;" +
|
||||
"width: 10px; height: 10px;" +
|
||||
"position: absolute; top: 0px; left: 0px;"
|
||||
);
|
||||
for (i = 0, ii = names.length; i < ii; ++i) {
|
||||
let span = document.createElement('span');
|
||||
span.textContent = 'Hi';
|
||||
let span = document.createElement("span");
|
||||
span.textContent = "Hi";
|
||||
span.style.fontFamily = names[i];
|
||||
div.appendChild(span);
|
||||
}
|
||||
@ -332,22 +361,26 @@ FontLoader = class GenericFontLoader extends BaseFontLoader {
|
||||
});
|
||||
/** Hack end */
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
} // End of PDFJSDev.test('CHROME || GENERIC')
|
||||
|
||||
const IsEvalSupportedCached = {
|
||||
get value() {
|
||||
return shadow(this, 'value', isEvalSupported());
|
||||
return shadow(this, "value", isEvalSupported());
|
||||
},
|
||||
};
|
||||
|
||||
class FontFaceObject {
|
||||
constructor(translatedData, { isEvalSupported = true,
|
||||
constructor(
|
||||
translatedData,
|
||||
{
|
||||
isEvalSupported = true,
|
||||
disableFontFace = false,
|
||||
ignoreErrors = false,
|
||||
onUnsupportedFeature = null,
|
||||
fontRegistry = null, }) {
|
||||
fontRegistry = null,
|
||||
}
|
||||
) {
|
||||
this.compiledGlyphs = Object.create(null);
|
||||
// importing translated data
|
||||
for (let i in translatedData) {
|
||||
@ -394,53 +427,51 @@ class FontFaceObject {
|
||||
|
||||
let cmds, current;
|
||||
try {
|
||||
cmds = objs.get(this.loadedName + '_path_' + character);
|
||||
cmds = objs.get(this.loadedName + "_path_" + character);
|
||||
} catch (ex) {
|
||||
if (!this.ignoreErrors) {
|
||||
throw ex;
|
||||
}
|
||||
if (this._onUnsupportedFeature) {
|
||||
this._onUnsupportedFeature({ featureId: UNSUPPORTED_FEATURES.font, });
|
||||
this._onUnsupportedFeature({ featureId: UNSUPPORTED_FEATURES.font });
|
||||
}
|
||||
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.
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// If we can, compile cmds into JS for MAXIMUM SPEED...
|
||||
if (this.isEvalSupported && IsEvalSupportedCached.value) {
|
||||
let args, js = '';
|
||||
let args,
|
||||
js = "";
|
||||
for (let i = 0, ii = cmds.length; i < ii; i++) {
|
||||
current = cmds[i];
|
||||
|
||||
if (current.args !== undefined) {
|
||||
args = current.args.join(',');
|
||||
args = current.args.join(",");
|
||||
} else {
|
||||
args = '';
|
||||
args = "";
|
||||
}
|
||||
js += 'c.' + current.cmd + '(' + args + ');\n';
|
||||
js += "c." + current.cmd + "(" + args + ");\n";
|
||||
}
|
||||
// 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
|
||||
// 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++) {
|
||||
current = cmds[i];
|
||||
|
||||
if (current.cmd === 'scale') {
|
||||
if (current.cmd === "scale") {
|
||||
current.args = [size, -size];
|
||||
}
|
||||
c[current.cmd].apply(c, current.args);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
FontFaceObject,
|
||||
FontLoader,
|
||||
};
|
||||
export { FontFaceObject, FontLoader };
|
||||
|
@ -13,12 +13,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { assert } from '../shared/util';
|
||||
import { SimpleXMLParser } from './xml_parser';
|
||||
import { assert } from "../shared/util";
|
||||
import { SimpleXMLParser } from "./xml_parser";
|
||||
|
||||
class Metadata {
|
||||
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.
|
||||
data = this._repair(data);
|
||||
@ -36,66 +36,74 @@ class Metadata {
|
||||
|
||||
_repair(data) {
|
||||
// Start by removing any "junk" before the first tag (see issue 10395).
|
||||
return data.replace(/^([^<]+)/, '').replace(/>\\376\\377([^<]+)/g,
|
||||
function(all, codes) {
|
||||
let bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g,
|
||||
function(code, d1, d2, d3) {
|
||||
return data
|
||||
.replace(/^([^<]+)/, "")
|
||||
.replace(/>\\376\\377([^<]+)/g, function(all, codes) {
|
||||
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);
|
||||
}).replace(/&(amp|apos|gt|lt|quot);/g, function(str, name) {
|
||||
})
|
||||
.replace(/&(amp|apos|gt|lt|quot);/g, function(str, name) {
|
||||
switch (name) {
|
||||
case 'amp':
|
||||
return '&';
|
||||
case 'apos':
|
||||
return '\'';
|
||||
case 'gt':
|
||||
return '>';
|
||||
case 'lt':
|
||||
return '<';
|
||||
case 'quot':
|
||||
return '\"';
|
||||
case "amp":
|
||||
return "&";
|
||||
case "apos":
|
||||
return "'";
|
||||
case "gt":
|
||||
return ">";
|
||||
case "lt":
|
||||
return "<";
|
||||
case "quot":
|
||||
return '"';
|
||||
}
|
||||
throw new Error(`_repair: ${name} isn't defined.`);
|
||||
});
|
||||
|
||||
let chars = '';
|
||||
let chars = "";
|
||||
for (let i = 0, ii = bytes.length; i < ii; i += 2) {
|
||||
let code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
|
||||
if (code >= 32 && code < 127 && code !== 60 && code !== 62 &&
|
||||
code !== 38) {
|
||||
if (
|
||||
code >= 32 &&
|
||||
code < 127 &&
|
||||
code !== 60 &&
|
||||
code !== 62 &&
|
||||
code !== 38
|
||||
) {
|
||||
chars += String.fromCharCode(code);
|
||||
} else {
|
||||
chars += '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
|
||||
chars += "&#x" + (0x10000 + code).toString(16).substring(1) + ";";
|
||||
}
|
||||
}
|
||||
|
||||
return '>' + chars;
|
||||
return ">" + chars;
|
||||
});
|
||||
}
|
||||
|
||||
_parse(xmlDocument) {
|
||||
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;
|
||||
while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
|
||||
while (rdf && rdf.nodeName.toLowerCase() !== "rdf:rdf") {
|
||||
rdf = rdf.nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
let nodeName = rdf ? rdf.nodeName.toLowerCase() : null;
|
||||
if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) {
|
||||
if (!rdf || nodeName !== "rdf:rdf" || !rdf.hasChildNodes()) {
|
||||
return;
|
||||
}
|
||||
|
||||
let children = rdf.childNodes;
|
||||
for (let i = 0, ii = children.length; i < ii; i++) {
|
||||
let desc = children[i];
|
||||
if (desc.nodeName.toLowerCase() !== 'rdf:description') {
|
||||
if (desc.nodeName.toLowerCase() !== "rdf:description") {
|
||||
continue;
|
||||
}
|
||||
|
||||
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 name = entry.nodeName.toLowerCase();
|
||||
|
||||
@ -107,7 +115,7 @@ class Metadata {
|
||||
|
||||
get(name) {
|
||||
const data = this._metadata[name];
|
||||
return (typeof data !== 'undefined' ? data : null);
|
||||
return typeof data !== "undefined" ? data : null;
|
||||
}
|
||||
|
||||
getAll() {
|
||||
@ -115,10 +123,8 @@ class Metadata {
|
||||
}
|
||||
|
||||
has(name) {
|
||||
return typeof this._metadata[name] !== 'undefined';
|
||||
return typeof this._metadata[name] !== "undefined";
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
Metadata,
|
||||
};
|
||||
export { Metadata };
|
||||
|
@ -14,15 +14,18 @@
|
||||
*/
|
||||
/* eslint no-var: error */
|
||||
|
||||
import { assert, createPromiseCapability, stringToBytes } from '../shared/util';
|
||||
import { assert, createPromiseCapability, stringToBytes } from "../shared/util";
|
||||
import {
|
||||
createResponseStatusError, extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities
|
||||
} from './network_utils';
|
||||
createResponseStatusError,
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
} from "./network_utils";
|
||||
|
||||
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
|
||||
throw new Error('Module "./network" shall not ' +
|
||||
'be used with FIREFOX or MOZCENTRAL build.');
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("FIREFOX || MOZCENTRAL")) {
|
||||
throw new Error(
|
||||
'Module "./network" shall not ' +
|
||||
"be used with FIREFOX or MOZCENTRAL build."
|
||||
);
|
||||
}
|
||||
|
||||
const OK_RESPONSE = 200;
|
||||
@ -30,7 +33,7 @@ const PARTIAL_CONTENT_RESPONSE = 206;
|
||||
|
||||
function getArrayBuffer(xhr) {
|
||||
const data = xhr.response;
|
||||
if (typeof data !== 'string') {
|
||||
if (typeof data !== "string") {
|
||||
return data;
|
||||
}
|
||||
const array = stringToBytes(data);
|
||||
@ -44,7 +47,8 @@ class NetworkManager {
|
||||
this.isHttp = /^https?:/i.test(url);
|
||||
this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
|
||||
this.withCredentials = args.withCredentials || false;
|
||||
this.getXhr = args.getXhr ||
|
||||
this.getXhr =
|
||||
args.getXhr ||
|
||||
function NetworkManager_getXhr() {
|
||||
return new XMLHttpRequest();
|
||||
};
|
||||
@ -71,26 +75,26 @@ class NetworkManager {
|
||||
request(args) {
|
||||
const xhr = this.getXhr();
|
||||
const xhrId = this.currXhrId++;
|
||||
const pendingRequest = this.pendingRequests[xhrId] = {
|
||||
const pendingRequest = (this.pendingRequests[xhrId] = {
|
||||
xhr,
|
||||
};
|
||||
});
|
||||
|
||||
xhr.open('GET', this.url);
|
||||
xhr.open("GET", this.url);
|
||||
xhr.withCredentials = this.withCredentials;
|
||||
for (const property in this.httpHeaders) {
|
||||
const value = this.httpHeaders[property];
|
||||
if (typeof value === 'undefined') {
|
||||
if (typeof value === "undefined") {
|
||||
continue;
|
||||
}
|
||||
xhr.setRequestHeader(property, value);
|
||||
}
|
||||
if (this.isHttp && 'begin' in args && 'end' in args) {
|
||||
xhr.setRequestHeader('Range', `bytes=${args.begin}-${args.end - 1}`);
|
||||
if (this.isHttp && "begin" in args && "end" in args) {
|
||||
xhr.setRequestHeader("Range", `bytes=${args.begin}-${args.end - 1}`);
|
||||
pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE;
|
||||
} else {
|
||||
pendingRequest.expectedStatus = OK_RESPONSE;
|
||||
}
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.responseType = "arraybuffer";
|
||||
|
||||
if (args.onError) {
|
||||
xhr.onerror = function(evt) {
|
||||
@ -163,8 +167,10 @@ class NetworkManager {
|
||||
xhrStatus === OK_RESPONSE &&
|
||||
pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
|
||||
|
||||
if (!ok_response_on_range_request &&
|
||||
xhrStatus !== pendingRequest.expectedStatus) {
|
||||
if (
|
||||
!ok_response_on_range_request &&
|
||||
xhrStatus !== pendingRequest.expectedStatus
|
||||
) {
|
||||
if (pendingRequest.onError) {
|
||||
pendingRequest.onError(xhr.status);
|
||||
}
|
||||
@ -173,7 +179,7 @@ class NetworkManager {
|
||||
|
||||
const chunk = getArrayBuffer(xhr);
|
||||
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);
|
||||
pendingRequest.onDone({
|
||||
begin: parseInt(matches[1], 10),
|
||||
@ -239,14 +245,19 @@ class PDFNetworkStream {
|
||||
|
||||
getFullReader() {
|
||||
assert(!this._fullRequestReader);
|
||||
this._fullRequestReader =
|
||||
new PDFNetworkStreamFullRequestReader(this._manager, this._source);
|
||||
this._fullRequestReader = new PDFNetworkStreamFullRequestReader(
|
||||
this._manager,
|
||||
this._source
|
||||
);
|
||||
return this._fullRequestReader;
|
||||
}
|
||||
|
||||
getRangeReader(begin, end) {
|
||||
const reader = new PDFNetworkStreamRangeRequestReader(this._manager,
|
||||
begin, end);
|
||||
const reader = new PDFNetworkStreamRangeRequestReader(
|
||||
this._manager,
|
||||
begin,
|
||||
end
|
||||
);
|
||||
reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
|
||||
this._rangeRequestReaders.push(reader);
|
||||
return reader;
|
||||
@ -300,11 +311,13 @@ class PDFNetworkStreamFullRequestReader {
|
||||
const fullRequestXhrId = this._fullRequestId;
|
||||
const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);
|
||||
|
||||
const getResponseHeader = (name) => {
|
||||
const getResponseHeader = name => {
|
||||
return fullRequestXhr.getResponseHeader(name);
|
||||
};
|
||||
const { allowRangeRequests, suggestedLength, } =
|
||||
validateRangeRequestCapabilities({
|
||||
const {
|
||||
allowRangeRequests,
|
||||
suggestedLength,
|
||||
} = validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
isHttp: this._manager.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
@ -334,7 +347,7 @@ class PDFNetworkStreamFullRequestReader {
|
||||
if (args) {
|
||||
if (this._requests.length > 0) {
|
||||
const requestCapability = this._requests.shift();
|
||||
requestCapability.resolve({ value: args.chunk, done: false, });
|
||||
requestCapability.resolve({ value: args.chunk, done: false });
|
||||
} else {
|
||||
this._cachedChunks.push(args.chunk);
|
||||
}
|
||||
@ -344,7 +357,7 @@ class PDFNetworkStreamFullRequestReader {
|
||||
return;
|
||||
}
|
||||
this._requests.forEach(function(requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true, });
|
||||
requestCapability.resolve({ value: undefined, done: true });
|
||||
});
|
||||
this._requests = [];
|
||||
}
|
||||
@ -396,10 +409,10 @@ class PDFNetworkStreamFullRequestReader {
|
||||
}
|
||||
if (this._cachedChunks.length > 0) {
|
||||
const chunk = this._cachedChunks.shift();
|
||||
return { value: chunk, done: false, };
|
||||
return { value: chunk, done: false };
|
||||
}
|
||||
if (this._done) {
|
||||
return { value: undefined, done: true, };
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
const requestCapability = createPromiseCapability();
|
||||
this._requests.push(requestCapability);
|
||||
@ -409,8 +422,8 @@ class PDFNetworkStreamFullRequestReader {
|
||||
cancel(reason) {
|
||||
this._done = true;
|
||||
this._headersReceivedCapability.reject(reason);
|
||||
this._requests.forEach(function (requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true, });
|
||||
this._requests.forEach(function(requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true });
|
||||
});
|
||||
this._requests = [];
|
||||
if (this._manager.isPendingRequest(this._fullRequestId)) {
|
||||
@ -447,13 +460,13 @@ class PDFNetworkStreamRangeRequestReader {
|
||||
const chunk = data.chunk;
|
||||
if (this._requests.length > 0) {
|
||||
const requestCapability = this._requests.shift();
|
||||
requestCapability.resolve({ value: chunk, done: false, });
|
||||
requestCapability.resolve({ value: chunk, done: false });
|
||||
} else {
|
||||
this._queuedChunk = chunk;
|
||||
}
|
||||
this._done = true;
|
||||
this._requests.forEach(function(requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true, });
|
||||
requestCapability.resolve({ value: undefined, done: true });
|
||||
});
|
||||
this._requests = [];
|
||||
this._close();
|
||||
@ -475,10 +488,10 @@ class PDFNetworkStreamRangeRequestReader {
|
||||
if (this._queuedChunk !== null) {
|
||||
const chunk = this._queuedChunk;
|
||||
this._queuedChunk = null;
|
||||
return { value: chunk, done: false, };
|
||||
return { value: chunk, done: false };
|
||||
}
|
||||
if (this._done) {
|
||||
return { value: undefined, done: true, };
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
const requestCapability = createPromiseCapability();
|
||||
this._requests.push(requestCapability);
|
||||
@ -487,8 +500,8 @@ class PDFNetworkStreamRangeRequestReader {
|
||||
|
||||
cancel(reason) {
|
||||
this._done = true;
|
||||
this._requests.forEach(function (requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true, });
|
||||
this._requests.forEach(function(requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true });
|
||||
});
|
||||
this._requests = [];
|
||||
if (this._manager.isPendingRequest(this._requestId)) {
|
||||
@ -498,6 +511,4 @@ class PDFNetworkStreamRangeRequestReader {
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PDFNetworkStream,
|
||||
};
|
||||
export { PDFNetworkStream };
|
||||
|
@ -14,21 +14,25 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
assert, MissingPDFException, UnexpectedResponseException
|
||||
} from '../shared/util';
|
||||
import {
|
||||
getFilenameFromContentDispositionHeader
|
||||
} from './content_disposition';
|
||||
assert,
|
||||
MissingPDFException,
|
||||
UnexpectedResponseException,
|
||||
} from "../shared/util";
|
||||
import { getFilenameFromContentDispositionHeader } from "./content_disposition";
|
||||
|
||||
function validateRangeRequestCapabilities({ getResponseHeader, isHttp,
|
||||
rangeChunkSize, disableRange, }) {
|
||||
assert(rangeChunkSize > 0, 'Range chunk size must be larger than zero');
|
||||
function validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
isHttp,
|
||||
rangeChunkSize,
|
||||
disableRange,
|
||||
}) {
|
||||
assert(rangeChunkSize > 0, "Range chunk size must be larger than zero");
|
||||
let returnValues = {
|
||||
allowRangeRequests: false,
|
||||
suggestedLength: undefined,
|
||||
};
|
||||
|
||||
let length = parseInt(getResponseHeader('Content-Length'), 10);
|
||||
let length = parseInt(getResponseHeader("Content-Length"), 10);
|
||||
if (!Number.isInteger(length)) {
|
||||
return returnValues;
|
||||
}
|
||||
@ -44,12 +48,12 @@ function validateRangeRequestCapabilities({ getResponseHeader, isHttp,
|
||||
if (disableRange || !isHttp) {
|
||||
return returnValues;
|
||||
}
|
||||
if (getResponseHeader('Accept-Ranges') !== 'bytes') {
|
||||
if (getResponseHeader("Accept-Ranges") !== "bytes") {
|
||||
return returnValues;
|
||||
}
|
||||
|
||||
let contentEncoding = getResponseHeader('Content-Encoding') || 'identity';
|
||||
if (contentEncoding !== 'identity') {
|
||||
let contentEncoding = getResponseHeader("Content-Encoding") || "identity";
|
||||
if (contentEncoding !== "identity") {
|
||||
return returnValues;
|
||||
}
|
||||
|
||||
@ -58,10 +62,10 @@ function validateRangeRequestCapabilities({ getResponseHeader, isHttp,
|
||||
}
|
||||
|
||||
function extractFilenameFromHeader(getResponseHeader) {
|
||||
const contentDisposition = getResponseHeader('Content-Disposition');
|
||||
const contentDisposition = getResponseHeader("Content-Disposition");
|
||||
if (contentDisposition) {
|
||||
let filename = getFilenameFromContentDispositionHeader(contentDisposition);
|
||||
if (filename.includes('%')) {
|
||||
if (filename.includes("%")) {
|
||||
try {
|
||||
filename = decodeURIComponent(filename);
|
||||
} catch (ex) {}
|
||||
@ -74,12 +78,17 @@ function extractFilenameFromHeader(getResponseHeader) {
|
||||
}
|
||||
|
||||
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 UnexpectedResponseException(
|
||||
'Unexpected server response (' + status +
|
||||
') while retrieving PDF "' + url + '".', status);
|
||||
"Unexpected server response (" +
|
||||
status +
|
||||
') while retrieving PDF "' +
|
||||
url +
|
||||
'".',
|
||||
status
|
||||
);
|
||||
}
|
||||
|
||||
function validateResponseStatus(status) {
|
||||
|
@ -14,23 +14,27 @@
|
||||
*/
|
||||
/* globals __non_webpack_require__ */
|
||||
|
||||
let fs = __non_webpack_require__('fs');
|
||||
let http = __non_webpack_require__('http');
|
||||
let https = __non_webpack_require__('https');
|
||||
let url = __non_webpack_require__('url');
|
||||
let fs = __non_webpack_require__("fs");
|
||||
let http = __non_webpack_require__("http");
|
||||
let https = __non_webpack_require__("https");
|
||||
let url = __non_webpack_require__("url");
|
||||
|
||||
import {
|
||||
AbortException, assert, createPromiseCapability, MissingPDFException
|
||||
} from '../shared/util';
|
||||
AbortException,
|
||||
assert,
|
||||
createPromiseCapability,
|
||||
MissingPDFException,
|
||||
} from "../shared/util";
|
||||
import {
|
||||
extractFilenameFromHeader, validateRangeRequestCapabilities
|
||||
} from './network_utils';
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
} from "./network_utils";
|
||||
|
||||
const fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
|
||||
|
||||
function parseUrl(sourceUrl) {
|
||||
let parsedUrl = url.parse(sourceUrl);
|
||||
if (parsedUrl.protocol === 'file:' || parsedUrl.host) {
|
||||
if (parsedUrl.protocol === "file:" || parsedUrl.host) {
|
||||
return parsedUrl;
|
||||
}
|
||||
// Prepending 'file:///' to Windows absolute path.
|
||||
@ -39,7 +43,7 @@ function parseUrl(sourceUrl) {
|
||||
}
|
||||
// Changes protocol to 'file:' if url refers to filesystem.
|
||||
if (!parsedUrl.host) {
|
||||
parsedUrl.protocol = 'file:';
|
||||
parsedUrl.protocol = "file:";
|
||||
}
|
||||
return parsedUrl;
|
||||
}
|
||||
@ -48,10 +52,10 @@ class PDFNodeStream {
|
||||
constructor(source) {
|
||||
this.source = source;
|
||||
this.url = parseUrl(source.url);
|
||||
this.isHttp = this.url.protocol === 'http:' ||
|
||||
this.url.protocol === 'https:';
|
||||
this.isHttp =
|
||||
this.url.protocol === "http:" || this.url.protocol === "https:";
|
||||
// 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._fullRequestReader = null;
|
||||
@ -59,14 +63,14 @@ class PDFNodeStream {
|
||||
}
|
||||
|
||||
get _progressiveDataLength() {
|
||||
return (this._fullRequestReader ? this._fullRequestReader._loaded : 0);
|
||||
return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
|
||||
}
|
||||
|
||||
getFullReader() {
|
||||
assert(!this._fullRequestReader);
|
||||
this._fullRequestReader = this.isFsUrl ?
|
||||
new PDFNodeStreamFsFullReader(this) :
|
||||
new PDFNodeStreamFullReader(this);
|
||||
this._fullRequestReader = this.isFsUrl
|
||||
? new PDFNodeStreamFsFullReader(this)
|
||||
: new PDFNodeStreamFullReader(this);
|
||||
return this._fullRequestReader;
|
||||
}
|
||||
|
||||
@ -74,9 +78,9 @@ class PDFNodeStream {
|
||||
if (end <= this._progressiveDataLength) {
|
||||
return null;
|
||||
}
|
||||
let rangeReader = this.isFsUrl ?
|
||||
new PDFNodeStreamFsRangeReader(this, start, end) :
|
||||
new PDFNodeStreamRangeReader(this, start, end);
|
||||
let rangeReader = this.isFsUrl
|
||||
? new PDFNodeStreamFsRangeReader(this, start, end)
|
||||
: new PDFNodeStreamRangeReader(this, start, end);
|
||||
this._rangeRequestReaders.push(rangeReader);
|
||||
return rangeReader;
|
||||
}
|
||||
@ -141,7 +145,7 @@ class BaseFullReader {
|
||||
async read() {
|
||||
await this._readCapability.promise;
|
||||
if (this._done) {
|
||||
return { value: undefined, done: true, };
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
if (this._storedError) {
|
||||
throw this._storedError;
|
||||
@ -161,7 +165,7 @@ class BaseFullReader {
|
||||
}
|
||||
// Ensure that `read()` method returns ArrayBuffer.
|
||||
let buffer = new Uint8Array(chunk).buffer;
|
||||
return { value: buffer, done: false, };
|
||||
return { value: buffer, done: false };
|
||||
}
|
||||
|
||||
cancel(reason) {
|
||||
@ -181,25 +185,25 @@ class BaseFullReader {
|
||||
|
||||
_setReadableStream(readableStream) {
|
||||
this._readableStream = readableStream;
|
||||
readableStream.on('readable', () => {
|
||||
readableStream.on("readable", () => {
|
||||
this._readCapability.resolve();
|
||||
});
|
||||
|
||||
readableStream.on('end', () => {
|
||||
readableStream.on("end", () => {
|
||||
// Destroy readable to minimize resource usage.
|
||||
readableStream.destroy();
|
||||
this._done = true;
|
||||
this._readCapability.resolve();
|
||||
});
|
||||
|
||||
readableStream.on('error', (reason) => {
|
||||
readableStream.on("error", reason => {
|
||||
this._error(reason);
|
||||
});
|
||||
|
||||
// We need to stop reading when range is supported and streaming is
|
||||
// disabled.
|
||||
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.
|
||||
@ -229,7 +233,7 @@ class BaseRangeReader {
|
||||
async read() {
|
||||
await this._readCapability.promise;
|
||||
if (this._done) {
|
||||
return { value: undefined, done: true, };
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
if (this._storedError) {
|
||||
throw this._storedError;
|
||||
@ -242,11 +246,11 @@ class BaseRangeReader {
|
||||
}
|
||||
this._loaded += chunk.length;
|
||||
if (this.onProgress) {
|
||||
this.onProgress({ loaded: this._loaded, });
|
||||
this.onProgress({ loaded: this._loaded });
|
||||
}
|
||||
// Ensure that `read()` method returns ArrayBuffer.
|
||||
let buffer = new Uint8Array(chunk).buffer;
|
||||
return { value: buffer, done: false, };
|
||||
return { value: buffer, done: false };
|
||||
}
|
||||
|
||||
cancel(reason) {
|
||||
@ -266,18 +270,18 @@ class BaseRangeReader {
|
||||
|
||||
_setReadableStream(readableStream) {
|
||||
this._readableStream = readableStream;
|
||||
readableStream.on('readable', () => {
|
||||
readableStream.on("readable", () => {
|
||||
this._readCapability.resolve();
|
||||
});
|
||||
|
||||
readableStream.on('end', () => {
|
||||
readableStream.on("end", () => {
|
||||
// Destroy readableStream to minimize resource usage.
|
||||
readableStream.destroy();
|
||||
this._done = true;
|
||||
this._readCapability.resolve();
|
||||
});
|
||||
|
||||
readableStream.on('error', (reason) => {
|
||||
readableStream.on("error", reason => {
|
||||
this._error(reason);
|
||||
});
|
||||
|
||||
@ -295,7 +299,7 @@ function createRequestOptions(url, headers) {
|
||||
host: url.hostname,
|
||||
port: url.port,
|
||||
path: url.path,
|
||||
method: 'GET',
|
||||
method: "GET",
|
||||
headers,
|
||||
};
|
||||
}
|
||||
@ -304,7 +308,7 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
||||
constructor(stream) {
|
||||
super(stream);
|
||||
|
||||
let handleResponse = (response) => {
|
||||
let handleResponse = response => {
|
||||
if (response.statusCode === 404) {
|
||||
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
||||
this._storedError = error;
|
||||
@ -314,13 +318,15 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
||||
this._headersCapability.resolve();
|
||||
this._setReadableStream(response);
|
||||
|
||||
const getResponseHeader = (name) => {
|
||||
const getResponseHeader = name => {
|
||||
// Make sure that headers name are in lower case, as mentioned
|
||||
// here: https://nodejs.org/api/http.html#http_message_headers.
|
||||
return this._readableStream.headers[name.toLowerCase()];
|
||||
};
|
||||
let { allowRangeRequests, suggestedLength, } =
|
||||
validateRangeRequestCapabilities({
|
||||
let {
|
||||
allowRangeRequests,
|
||||
suggestedLength,
|
||||
} = validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
isHttp: stream.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
@ -335,17 +341,19 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
||||
};
|
||||
|
||||
this._request = null;
|
||||
if (this._url.protocol === 'http:') {
|
||||
if (this._url.protocol === "http:") {
|
||||
this._request = http.request(
|
||||
createRequestOptions(this._url, stream.httpHeaders),
|
||||
handleResponse);
|
||||
handleResponse
|
||||
);
|
||||
} else {
|
||||
this._request = https.request(
|
||||
createRequestOptions(this._url, stream.httpHeaders),
|
||||
handleResponse);
|
||||
handleResponse
|
||||
);
|
||||
}
|
||||
|
||||
this._request.on('error', (reason) => {
|
||||
this._request.on("error", reason => {
|
||||
this._storedError = reason;
|
||||
this._headersCapability.reject(reason);
|
||||
});
|
||||
@ -363,14 +371,14 @@ class PDFNodeStreamRangeReader extends BaseRangeReader {
|
||||
this._httpHeaders = {};
|
||||
for (let property in stream.httpHeaders) {
|
||||
let value = stream.httpHeaders[property];
|
||||
if (typeof value === 'undefined') {
|
||||
if (typeof value === "undefined") {
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
||||
this._storedError = error;
|
||||
@ -380,17 +388,19 @@ class PDFNodeStreamRangeReader extends BaseRangeReader {
|
||||
};
|
||||
|
||||
this._request = null;
|
||||
if (this._url.protocol === 'http:') {
|
||||
if (this._url.protocol === "http:") {
|
||||
this._request = http.request(
|
||||
createRequestOptions(this._url, this._httpHeaders),
|
||||
handleResponse);
|
||||
handleResponse
|
||||
);
|
||||
} else {
|
||||
this._request = https.request(
|
||||
createRequestOptions(this._url, this._httpHeaders),
|
||||
handleResponse);
|
||||
handleResponse
|
||||
);
|
||||
}
|
||||
|
||||
this._request.on('error', (reason) => {
|
||||
this._request.on("error", reason => {
|
||||
this._storedError = reason;
|
||||
});
|
||||
this._request.end();
|
||||
@ -405,12 +415,12 @@ class PDFNodeStreamFsFullReader extends BaseFullReader {
|
||||
|
||||
// Remove the extra slash to get right path from url like `file:///C:/`
|
||||
if (fileUriRegex.test(this._url.href)) {
|
||||
path = path.replace(/^\//, '');
|
||||
path = path.replace(/^\//, "");
|
||||
}
|
||||
|
||||
fs.lstat(path, (error, stat) => {
|
||||
if (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
if (error.code === "ENOENT") {
|
||||
error = new MissingPDFException(`Missing PDF "${path}".`);
|
||||
}
|
||||
this._storedError = error;
|
||||
@ -434,14 +444,11 @@ class PDFNodeStreamFsRangeReader extends BaseRangeReader {
|
||||
|
||||
// Remove the extra slash to get right path from url like `file:///C:/`
|
||||
if (fileUriRegex.test(this._url.href)) {
|
||||
path = path.replace(/^\//, '');
|
||||
path = path.replace(/^\//, "");
|
||||
}
|
||||
|
||||
this._setReadableStream(
|
||||
fs.createReadStream(path, { start, end: end - 1, }));
|
||||
this._setReadableStream(fs.createReadStream(path, { start, end: end - 1 }));
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PDFNodeStream,
|
||||
};
|
||||
export { PDFNodeStream };
|
||||
|
@ -13,12 +13,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { FormatError, info, Util } from '../shared/util';
|
||||
import { FormatError, info, Util } from "../shared/util";
|
||||
|
||||
var ShadingIRs = {};
|
||||
|
||||
function applyBoundingBox(ctx, bbox) {
|
||||
if (!bbox || typeof Path2D === 'undefined') {
|
||||
if (!bbox || typeof Path2D === "undefined") {
|
||||
return;
|
||||
}
|
||||
const width = bbox[2] - bbox[0];
|
||||
@ -38,13 +38,13 @@ ShadingIRs.RadialAxial = {
|
||||
var r0 = raw[6];
|
||||
var r1 = raw[7];
|
||||
return {
|
||||
type: 'Pattern',
|
||||
type: "Pattern",
|
||||
getPattern: function RadialAxial_getPattern(ctx) {
|
||||
applyBoundingBox(ctx, bbox);
|
||||
var grad;
|
||||
if (type === 'axial') {
|
||||
if (type === "axial") {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -61,17 +61,34 @@ ShadingIRs.RadialAxial = {
|
||||
var createMeshCanvas = (function createMeshCanvasClosure() {
|
||||
function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
|
||||
// Very basic Gouraud-shaded triangle rasterization algorithm.
|
||||
var coords = context.coords, colors = context.colors;
|
||||
var bytes = data.data, rowSize = data.width * 4;
|
||||
var coords = context.coords,
|
||||
colors = context.colors;
|
||||
var bytes = data.data,
|
||||
rowSize = data.width * 4;
|
||||
var tmp;
|
||||
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]) {
|
||||
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]) {
|
||||
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 y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
|
||||
@ -82,11 +99,18 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
||||
if (y1 >= y3) {
|
||||
return;
|
||||
}
|
||||
var c1r = colors[c1], c1g = colors[c1 + 1], 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 c1r = colors[c1],
|
||||
c1g = colors[c1 + 1],
|
||||
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 xb, cbr, cbg, cbb;
|
||||
var k;
|
||||
@ -128,36 +152,65 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
||||
var cs = figure.colors;
|
||||
var i, ii;
|
||||
switch (figure.type) {
|
||||
case 'lattice':
|
||||
case "lattice":
|
||||
var verticesPerRow = figure.verticesPerRow;
|
||||
var rows = Math.floor(ps.length / verticesPerRow) - 1;
|
||||
var cols = verticesPerRow - 1;
|
||||
for (i = 0; i < rows; i++) {
|
||||
var q = i * verticesPerRow;
|
||||
for (var j = 0; j < cols; j++, q++) {
|
||||
drawTriangle(data, context,
|
||||
ps[q], ps[q + 1], 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]);
|
||||
drawTriangle(
|
||||
data,
|
||||
context,
|
||||
ps[q],
|
||||
ps[q + 1],
|
||||
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;
|
||||
case 'triangles':
|
||||
case "triangles":
|
||||
for (i = 0, ii = ps.length; i < ii; i += 3) {
|
||||
drawTriangle(data, context,
|
||||
ps[i], ps[i + 1], ps[i + 2],
|
||||
cs[i], cs[i + 1], cs[i + 2]);
|
||||
drawTriangle(
|
||||
data,
|
||||
context,
|
||||
ps[i],
|
||||
ps[i + 1],
|
||||
ps[i + 2],
|
||||
cs[i],
|
||||
cs[i + 1],
|
||||
cs[i + 2]
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error('illegal figure');
|
||||
throw new Error("illegal figure");
|
||||
}
|
||||
}
|
||||
|
||||
function createMeshCanvas(bounds, combinesScale, coords, colors, figures,
|
||||
backgroundColor, cachedCanvases, webGLContext) {
|
||||
function createMeshCanvas(
|
||||
bounds,
|
||||
combinesScale,
|
||||
coords,
|
||||
colors,
|
||||
figures,
|
||||
backgroundColor,
|
||||
cachedCanvases,
|
||||
webGLContext
|
||||
) {
|
||||
// we will increase scale on some weird factor to let antialiasing take
|
||||
// care of "rough" edges
|
||||
var EXPECTED_SCALE = 1.1;
|
||||
@ -172,10 +225,14 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
||||
var boundsWidth = Math.ceil(bounds[2]) - offsetX;
|
||||
var boundsHeight = Math.ceil(bounds[3]) - offsetY;
|
||||
|
||||
var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] *
|
||||
EXPECTED_SCALE)), MAX_PATTERN_SIZE);
|
||||
var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] *
|
||||
EXPECTED_SCALE)), MAX_PATTERN_SIZE);
|
||||
var width = Math.min(
|
||||
Math.ceil(Math.abs(boundsWidth * combinesScale[0] * 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 scaleY = boundsHeight / height;
|
||||
|
||||
@ -201,13 +258,21 @@ var createMeshCanvas = (function createMeshCanvasClosure() {
|
||||
context,
|
||||
});
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=972126
|
||||
tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight,
|
||||
false);
|
||||
tmpCanvas = cachedCanvases.getCanvas(
|
||||
"mesh",
|
||||
paddedWidth,
|
||||
paddedHeight,
|
||||
false
|
||||
);
|
||||
tmpCanvas.context.drawImage(canvas, BORDER_SIZE, BORDER_SIZE);
|
||||
canvas = tmpCanvas.canvas;
|
||||
} else {
|
||||
tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight,
|
||||
false);
|
||||
tmpCanvas = cachedCanvases.getCanvas(
|
||||
"mesh",
|
||||
paddedWidth,
|
||||
paddedHeight,
|
||||
false
|
||||
);
|
||||
var tmpCtx = tmpCanvas.context;
|
||||
|
||||
var data = tmpCtx.createImageData(width, height);
|
||||
@ -249,7 +314,7 @@ ShadingIRs.Mesh = {
|
||||
var bbox = raw[7];
|
||||
var background = raw[8];
|
||||
return {
|
||||
type: 'Pattern',
|
||||
type: "Pattern",
|
||||
getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
|
||||
applyBoundingBox(ctx, bbox);
|
||||
var scale;
|
||||
@ -260,16 +325,22 @@ ShadingIRs.Mesh = {
|
||||
scale = Util.singularValueDecompose2dScale(owner.baseTransform);
|
||||
if (matrix) {
|
||||
var matrixScale = Util.singularValueDecompose2dScale(matrix);
|
||||
scale = [scale[0] * matrixScale[0],
|
||||
scale[1] * matrixScale[1]];
|
||||
scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]];
|
||||
}
|
||||
}
|
||||
|
||||
// Rasterizing on the main thread since sending/queue large canvases
|
||||
// might cause OOM.
|
||||
var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords,
|
||||
colors, figures, shadingFill ? null : background,
|
||||
owner.cachedCanvases, owner.webGLContext);
|
||||
var temporaryPatternCanvas = createMeshCanvas(
|
||||
bounds,
|
||||
scale,
|
||||
coords,
|
||||
colors,
|
||||
figures,
|
||||
shadingFill ? null : background,
|
||||
owner.cachedCanvases,
|
||||
owner.webGLContext
|
||||
);
|
||||
|
||||
if (!shadingFill) {
|
||||
ctx.setTransform.apply(ctx, owner.baseTransform);
|
||||
@ -278,12 +349,13 @@ ShadingIRs.Mesh = {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.translate(temporaryPatternCanvas.offsetX,
|
||||
temporaryPatternCanvas.offsetY);
|
||||
ctx.scale(temporaryPatternCanvas.scaleX,
|
||||
temporaryPatternCanvas.scaleY);
|
||||
ctx.translate(
|
||||
temporaryPatternCanvas.offsetX,
|
||||
temporaryPatternCanvas.offsetY
|
||||
);
|
||||
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 = {
|
||||
fromIR: function Dummy_fromIR() {
|
||||
return {
|
||||
type: 'Pattern',
|
||||
type: "Pattern",
|
||||
getPattern: function Dummy_fromIR_getPattern() {
|
||||
return 'hotpink';
|
||||
return "hotpink";
|
||||
},
|
||||
};
|
||||
},
|
||||
@ -327,7 +399,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
this.color = color;
|
||||
this.canvasGraphicsFactory = canvasGraphicsFactory;
|
||||
this.baseTransform = baseTransform;
|
||||
this.type = 'Pattern';
|
||||
this.type = "Pattern";
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
@ -342,7 +414,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
var color = this.color;
|
||||
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
|
||||
// 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
|
||||
// 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.
|
||||
var matrixScale = Util.singularValueDecompose2dScale(this.matrix);
|
||||
var curMatrixScale = Util.singularValueDecompose2dScale(
|
||||
this.baseTransform);
|
||||
var combinedScale = [matrixScale[0] * curMatrixScale[0],
|
||||
matrixScale[1] * curMatrixScale[1]];
|
||||
this.baseTransform
|
||||
);
|
||||
var combinedScale = [
|
||||
matrixScale[0] * curMatrixScale[0],
|
||||
matrixScale[1] * curMatrixScale[1],
|
||||
];
|
||||
|
||||
// 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
|
||||
// blurry. Too large value makes it look too crispy.
|
||||
var dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width,
|
||||
combinedScale[0]);
|
||||
var dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height,
|
||||
combinedScale[1]);
|
||||
var dimx = this.getSizeAndScale(
|
||||
xstep,
|
||||
this.ctx.canvas.width,
|
||||
combinedScale[0]
|
||||
);
|
||||
var dimy = this.getSizeAndScale(
|
||||
ystep,
|
||||
this.ctx.canvas.height,
|
||||
combinedScale[1]
|
||||
);
|
||||
|
||||
var tmpCanvas = owner.cachedCanvases.getCanvas('pattern',
|
||||
dimx.size, dimy.size, true);
|
||||
var tmpCanvas = owner.cachedCanvases.getCanvas(
|
||||
"pattern",
|
||||
dimx.size,
|
||||
dimy.size,
|
||||
true
|
||||
);
|
||||
var tmpCtx = tmpCanvas.context;
|
||||
var graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
|
||||
graphics.groupLevel = owner.groupLevel;
|
||||
@ -406,8 +494,11 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
return tmpCanvas.canvas;
|
||||
},
|
||||
|
||||
getSizeAndScale:
|
||||
function TilingPattern_getSizeAndScale(step, realOutputSize, scale) {
|
||||
getSizeAndScale: function TilingPattern_getSizeAndScale(
|
||||
step,
|
||||
realOutputSize,
|
||||
scale
|
||||
) {
|
||||
// xstep / ystep may be negative -- normalize.
|
||||
step = Math.abs(step);
|
||||
// MAX_PATTERN_SIZE is used to avoid OOM situation.
|
||||
@ -421,7 +512,7 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
} else {
|
||||
scale = size / step;
|
||||
}
|
||||
return { scale, size, };
|
||||
return { scale, size };
|
||||
},
|
||||
|
||||
clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
|
||||
@ -434,9 +525,13 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
}
|
||||
},
|
||||
|
||||
setFillAndStrokeStyleToContext:
|
||||
function setFillAndStrokeStyleToContext(graphics, paintType, color) {
|
||||
let context = graphics.ctx, current = graphics.current;
|
||||
setFillAndStrokeStyleToContext: function setFillAndStrokeStyleToContext(
|
||||
graphics,
|
||||
paintType,
|
||||
color
|
||||
) {
|
||||
let context = graphics.ctx,
|
||||
current = graphics.current;
|
||||
switch (paintType) {
|
||||
case PaintType.COLORED:
|
||||
var ctx = this.ctx;
|
||||
@ -466,14 +561,11 @@ var TilingPattern = (function TilingPatternClosure() {
|
||||
|
||||
var temporaryPatternCanvas = this.createPatternCanvas(owner);
|
||||
|
||||
return ctx.createPattern(temporaryPatternCanvas, 'repeat');
|
||||
return ctx.createPattern(temporaryPatternCanvas, "repeat");
|
||||
},
|
||||
};
|
||||
|
||||
return TilingPattern;
|
||||
})();
|
||||
|
||||
export {
|
||||
getShadingPatternFromIR,
|
||||
TilingPattern,
|
||||
};
|
||||
export { getShadingPatternFromIR, TilingPattern };
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AbortException, createPromiseCapability, Util } from '../shared/util';
|
||||
import { AbortException, createPromiseCapability, Util } from "../shared/util";
|
||||
|
||||
/**
|
||||
* Text layer render parameters.
|
||||
@ -48,7 +48,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
|
||||
function appendText(task, geom, styles) {
|
||||
// Initialize all used properties to keep the caches monomorphic.
|
||||
var textDiv = document.createElement('span');
|
||||
var textDiv = document.createElement("span");
|
||||
var textDivProperties = {
|
||||
angle: 0,
|
||||
canvasWidth: 0,
|
||||
@ -74,7 +74,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
if (style.vertical) {
|
||||
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;
|
||||
if (style.ascent) {
|
||||
fontAscent = style.ascent * fontAscent;
|
||||
@ -87,8 +87,8 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
left = tx[4];
|
||||
top = tx[5] - fontAscent;
|
||||
} else {
|
||||
left = tx[4] + (fontAscent * Math.sin(angle));
|
||||
top = tx[5] - (fontAscent * Math.cos(angle));
|
||||
left = tx[4] + fontAscent * Math.sin(angle);
|
||||
top = tx[5] - fontAscent * Math.cos(angle);
|
||||
}
|
||||
// Setting the style properties individually, rather than all at once,
|
||||
// should be OK since the `textDiv` isn't appended to the document yet.
|
||||
@ -122,13 +122,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
}
|
||||
|
||||
if (task._enhanceTextSelection) {
|
||||
var angleCos = 1, angleSin = 0;
|
||||
var angleCos = 1,
|
||||
angleSin = 0;
|
||||
if (angle !== 0) {
|
||||
angleCos = Math.cos(angle);
|
||||
angleSin = Math.sin(angle);
|
||||
}
|
||||
var divWidth = (style.vertical ? geom.height : geom.width) *
|
||||
task._viewport.scale;
|
||||
var divWidth =
|
||||
(style.vertical ? geom.height : geom.width) * task._viewport.scale;
|
||||
var divHeight = fontHeight;
|
||||
|
||||
var m, b;
|
||||
@ -195,12 +196,15 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
}
|
||||
// Box is rotated -- trying to find padding so rotated div will not
|
||||
// exceed its expanded bounds.
|
||||
var e = expanded[i], b = bounds[i];
|
||||
var m = b.m, c = m[0], s = m[1];
|
||||
var e = expanded[i],
|
||||
b = bounds[i];
|
||||
var m = b.m,
|
||||
c = m[0],
|
||||
s = m[1];
|
||||
// Finding intersections with expanded box.
|
||||
var points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
|
||||
var ts = new Float64Array(64);
|
||||
points.forEach(function (p, i) {
|
||||
points.forEach(function(p, i) {
|
||||
var t = Util.applyTransform(p, m);
|
||||
ts[i + 0] = c && (e.left - t[0]) / c;
|
||||
ts[i + 4] = s && (e.top - t[1]) / s;
|
||||
@ -222,7 +226,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
ts[i + 56] = s && (e.right - t[0]) / s;
|
||||
ts[i + 60] = c && (e.bottom - t[1]) / -c;
|
||||
});
|
||||
var findPositiveMin = function (ts, offset, count) {
|
||||
var findPositiveMin = function(ts, offset, count) {
|
||||
var result = 0;
|
||||
for (var i = 0; i < count; i++) {
|
||||
var t = ts[offset++];
|
||||
@ -244,7 +248,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
}
|
||||
|
||||
function expandBounds(width, height, boxes) {
|
||||
var bounds = boxes.map(function (box, i) {
|
||||
var bounds = boxes.map(function(box, i) {
|
||||
return {
|
||||
x1: box.left,
|
||||
y1: box.top,
|
||||
@ -257,7 +261,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
});
|
||||
expandBoundsLTR(width, bounds);
|
||||
var expanded = new Array(boxes.length);
|
||||
bounds.forEach(function (b) {
|
||||
bounds.forEach(function(b) {
|
||||
var i = b.index;
|
||||
expanded[i] = {
|
||||
left: b.x1New,
|
||||
@ -269,8 +273,9 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
|
||||
// Rotating on 90 degrees and extending extended boxes. Reusing the bounds
|
||||
// array and objects.
|
||||
boxes.map(function (box, i) {
|
||||
var e = expanded[i], b = bounds[i];
|
||||
boxes.map(function(box, i) {
|
||||
var e = expanded[i],
|
||||
b = bounds[i];
|
||||
b.x1 = box.top;
|
||||
b.y1 = width - e.right;
|
||||
b.x2 = box.bottom;
|
||||
@ -281,7 +286,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
});
|
||||
expandBoundsLTR(height, bounds);
|
||||
|
||||
bounds.forEach(function (b) {
|
||||
bounds.forEach(function(b) {
|
||||
var i = b.index;
|
||||
expanded[i].top = b.x1New;
|
||||
expanded[i].bottom = b.x2New;
|
||||
@ -291,7 +296,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
|
||||
function expandBoundsLTR(width, bounds) {
|
||||
// Sorting by x1 coordinate and walk by the bounds in the same order.
|
||||
bounds.sort(function (a, b) {
|
||||
bounds.sort(function(a, b) {
|
||||
return a.x1 - b.x1 || a.index - b.index;
|
||||
});
|
||||
|
||||
@ -305,13 +310,15 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
x1New: 0,
|
||||
x2New: 0,
|
||||
};
|
||||
var horizon = [{
|
||||
var horizon = [
|
||||
{
|
||||
start: -Infinity,
|
||||
end: Infinity,
|
||||
boundary: fakeBoundary,
|
||||
}];
|
||||
},
|
||||
];
|
||||
|
||||
bounds.forEach(function (boundary) {
|
||||
bounds.forEach(function(boundary) {
|
||||
// Searching for the affected part of horizon.
|
||||
// TODO red-black tree or simple binary search
|
||||
var i = 0;
|
||||
@ -324,7 +331,9 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
}
|
||||
|
||||
var horizonPart, affectedBoundary;
|
||||
var q, k, maxXNew = -Infinity;
|
||||
var q,
|
||||
k,
|
||||
maxXNew = -Infinity;
|
||||
for (q = i; q <= j; q++) {
|
||||
horizonPart = horizon[q];
|
||||
affectedBoundary = horizonPart.boundary;
|
||||
@ -333,8 +342,10 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
// In the middle of the previous element, new x shall be at the
|
||||
// boundary start. Extending if further if the affected boundary
|
||||
// placed on top of the current one.
|
||||
xNew = affectedBoundary.index > boundary.index ?
|
||||
affectedBoundary.x1New : boundary.x1;
|
||||
xNew =
|
||||
affectedBoundary.index > boundary.index
|
||||
? affectedBoundary.x1New
|
||||
: boundary.x1;
|
||||
} else if (affectedBoundary.x2New === undefined) {
|
||||
// We have some space in between, new x in middle will be a fair
|
||||
// choice.
|
||||
@ -373,13 +384,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
}
|
||||
|
||||
// Fixing the horizon.
|
||||
var changedHorizon = [], lastBoundary = null;
|
||||
var changedHorizon = [],
|
||||
lastBoundary = null;
|
||||
for (q = i; q <= j; q++) {
|
||||
horizonPart = horizon[q];
|
||||
affectedBoundary = horizonPart.boundary;
|
||||
// Checking which boundary will be visible.
|
||||
var useBoundary = affectedBoundary.x2 > boundary.x2 ?
|
||||
affectedBoundary : boundary;
|
||||
var useBoundary =
|
||||
affectedBoundary.x2 > boundary.x2 ? affectedBoundary : boundary;
|
||||
if (lastBoundary === useBoundary) {
|
||||
// Merging with previous.
|
||||
changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
|
||||
@ -419,12 +431,18 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
continue;
|
||||
}
|
||||
var used = false;
|
||||
for (k = i - 1; !used && k >= 0 &&
|
||||
horizon[k].start >= affectedBoundary.y1; k--) {
|
||||
for (
|
||||
k = i - 1;
|
||||
!used && k >= 0 && horizon[k].start >= affectedBoundary.y1;
|
||||
k--
|
||||
) {
|
||||
used = horizon[k].boundary === affectedBoundary;
|
||||
}
|
||||
for (k = j + 1; !used && k < horizon.length &&
|
||||
horizon[k].end <= affectedBoundary.y2; k++) {
|
||||
for (
|
||||
k = j + 1;
|
||||
!used && k < horizon.length && horizon[k].end <= affectedBoundary.y2;
|
||||
k++
|
||||
) {
|
||||
used = horizon[k].boundary === affectedBoundary;
|
||||
}
|
||||
for (k = 0; !used && k < changedHorizon.length; k++) {
|
||||
@ -435,12 +453,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
}
|
||||
}
|
||||
|
||||
Array.prototype.splice.apply(horizon,
|
||||
[i, j - i + 1].concat(changedHorizon));
|
||||
Array.prototype.splice.apply(
|
||||
horizon,
|
||||
[i, j - i + 1].concat(changedHorizon)
|
||||
);
|
||||
});
|
||||
|
||||
// Set new x2 for all unset boundaries.
|
||||
horizon.forEach(function (horizonPart) {
|
||||
horizon.forEach(function(horizonPart) {
|
||||
var affectedBoundary = horizonPart.boundary;
|
||||
if (affectedBoundary.x2New === undefined) {
|
||||
affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
|
||||
@ -458,9 +478,15 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
* @param {boolean} enhanceTextSelection
|
||||
* @private
|
||||
*/
|
||||
function TextLayerRenderTask({ textContent, textContentStream, container,
|
||||
viewport, textDivs, textContentItemsStr,
|
||||
enhanceTextSelection, }) {
|
||||
function TextLayerRenderTask({
|
||||
textContent,
|
||||
textContentStream,
|
||||
container,
|
||||
viewport,
|
||||
textDivs,
|
||||
textContentItemsStr,
|
||||
enhanceTextSelection,
|
||||
}) {
|
||||
this._textContent = textContent;
|
||||
this._textContentStream = textContentStream;
|
||||
this._container = container;
|
||||
@ -468,8 +494,9 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
this._textDivs = textDivs || [];
|
||||
this._textContentItemsStr = textContentItemsStr || [];
|
||||
this._enhanceTextSelection = !!enhanceTextSelection;
|
||||
this._fontInspectorEnabled = !!(globalThis.FontInspector &&
|
||||
globalThis.FontInspector.enabled);
|
||||
this._fontInspectorEnabled = !!(
|
||||
globalThis.FontInspector && globalThis.FontInspector.enabled
|
||||
);
|
||||
|
||||
this._reader = null;
|
||||
this._layoutTextLastFontSize = null;
|
||||
@ -483,7 +510,8 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
this._bounds = [];
|
||||
|
||||
// Always clean-up the temporary canvas once rendering is no longer pending.
|
||||
this._capability.promise.finally(() => {
|
||||
this._capability.promise
|
||||
.finally(() => {
|
||||
if (this._layoutTextCtx) {
|
||||
// Zeroing the width and height cause Firefox to release graphics
|
||||
// resources immediately, which can greatly reduce memory consumption.
|
||||
@ -491,7 +519,10 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
this._layoutTextCtx.canvas.height = 0;
|
||||
this._layoutTextCtx = null;
|
||||
}
|
||||
}).catch(() => { /* Avoid "Uncaught promise" messages in the console. */ });
|
||||
})
|
||||
.catch(() => {
|
||||
/* Avoid "Uncaught promise" messages in the console. */
|
||||
});
|
||||
}
|
||||
TextLayerRenderTask.prototype = {
|
||||
get promise() {
|
||||
@ -501,14 +532,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
cancel: function TextLayer_cancel() {
|
||||
this._canceled = true;
|
||||
if (this._reader) {
|
||||
this._reader.cancel(new AbortException('TextLayer task cancelled.'));
|
||||
this._reader.cancel(new AbortException("TextLayer task cancelled."));
|
||||
this._reader = null;
|
||||
}
|
||||
if (this._renderTimer !== null) {
|
||||
clearTimeout(this._renderTimer);
|
||||
this._renderTimer = null;
|
||||
}
|
||||
this._capability.reject(new Error('TextLayer task cancelled.'));
|
||||
this._capability.reject(new Error("TextLayer task cancelled."));
|
||||
},
|
||||
|
||||
_processItems(items, styleCache) {
|
||||
@ -524,19 +555,21 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
return;
|
||||
}
|
||||
|
||||
let transform = '';
|
||||
let transform = "";
|
||||
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.
|
||||
if (fontSize !== this._layoutTextLastFontSize ||
|
||||
fontFamily !== this._layoutTextLastFontFamily) {
|
||||
if (
|
||||
fontSize !== this._layoutTextLastFontSize ||
|
||||
fontFamily !== this._layoutTextLastFontFamily
|
||||
) {
|
||||
this._layoutTextCtx.font = `${fontSize} ${fontFamily}`;
|
||||
this._layoutTextLastFontSize = fontSize;
|
||||
this._layoutTextLastFontFamily = fontFamily;
|
||||
}
|
||||
// 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) {
|
||||
textDivProperties.scale = textDivProperties.canvasWidth / width;
|
||||
@ -561,12 +594,14 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
let styleCache = Object.create(null);
|
||||
|
||||
// The temporary canvas is used to measure text length in the DOM.
|
||||
let canvas = document.createElement('canvas');
|
||||
if (typeof PDFJSDev === 'undefined' ||
|
||||
PDFJSDev.test('FIREFOX || MOZCENTRAL || GENERIC')) {
|
||||
let canvas = document.createElement("canvas");
|
||||
if (
|
||||
typeof PDFJSDev === "undefined" ||
|
||||
PDFJSDev.test("FIREFOX || MOZCENTRAL || GENERIC")
|
||||
) {
|
||||
canvas.mozOpaque = true;
|
||||
}
|
||||
this._layoutTextCtx = canvas.getContext('2d', { alpha: false, });
|
||||
this._layoutTextCtx = canvas.getContext("2d", { alpha: false });
|
||||
|
||||
if (this._textContent) {
|
||||
let textItems = this._textContent.items;
|
||||
@ -575,7 +610,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
capability.resolve();
|
||||
} else if (this._textContentStream) {
|
||||
let pump = () => {
|
||||
this._reader.read().then(({ value, done, }) => {
|
||||
this._reader.read().then(({ value, done }) => {
|
||||
if (done) {
|
||||
capability.resolve();
|
||||
return;
|
||||
@ -590,15 +625,19 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
this._reader = this._textContentStream.getReader();
|
||||
pump();
|
||||
} else {
|
||||
throw new Error('Neither "textContent" nor "textContentStream"' +
|
||||
' parameters specified.');
|
||||
throw new Error(
|
||||
'Neither "textContent" nor "textContentStream"' +
|
||||
" parameters specified."
|
||||
);
|
||||
}
|
||||
|
||||
capability.promise.then(() => {
|
||||
styleCache = null;
|
||||
if (!timeout) { // Render right away
|
||||
if (!timeout) {
|
||||
// Render right away
|
||||
render(this);
|
||||
} else { // Schedule
|
||||
} else {
|
||||
// Schedule
|
||||
this._renderTimer = setTimeout(() => {
|
||||
render(this);
|
||||
this._renderTimer = null;
|
||||
@ -615,8 +654,9 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
expand(this);
|
||||
this._bounds = null;
|
||||
}
|
||||
const NO_PADDING = '0 0 0 0';
|
||||
const transformBuf = [], paddingBuf = [];
|
||||
const NO_PADDING = "0 0 0 0";
|
||||
const transformBuf = [],
|
||||
paddingBuf = [];
|
||||
|
||||
for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
|
||||
const div = this._textDivs[i];
|
||||
@ -651,17 +691,18 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
if (divProps.paddingLeft > 0) {
|
||||
paddingBuf.push(`${divProps.paddingLeft / divProps.scale}px`);
|
||||
transformBuf.push(
|
||||
`translateX(${-divProps.paddingLeft / divProps.scale}px)`);
|
||||
`translateX(${-divProps.paddingLeft / divProps.scale}px)`
|
||||
);
|
||||
} else {
|
||||
paddingBuf.push(0);
|
||||
}
|
||||
|
||||
const padding = paddingBuf.join(' ');
|
||||
const padding = paddingBuf.join(" ");
|
||||
if (padding !== NO_PADDING) {
|
||||
div.style.padding = padding;
|
||||
}
|
||||
if (transformBuf.length) {
|
||||
div.style.transform = transformBuf.join(' ');
|
||||
div.style.transform = transformBuf.join(" ");
|
||||
}
|
||||
} else {
|
||||
div.style.padding = null;
|
||||
@ -694,6 +735,4 @@ var renderTextLayer = (function renderTextLayerClosure() {
|
||||
return renderTextLayer;
|
||||
})();
|
||||
|
||||
export {
|
||||
renderTextLayer,
|
||||
};
|
||||
export { renderTextLayer };
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
/* eslint no-var: error */
|
||||
|
||||
import { assert, createPromiseCapability } from '../shared/util';
|
||||
import { assert, createPromiseCapability } from "../shared/util";
|
||||
|
||||
/** @implements {IPDFStream} */
|
||||
class PDFDataTransportStream {
|
||||
@ -39,15 +39,15 @@ class PDFDataTransportStream {
|
||||
this._rangeReaders = [];
|
||||
|
||||
this._pdfDataRangeTransport.addRangeListener((begin, chunk) => {
|
||||
this._onReceiveData({ begin, chunk, });
|
||||
this._onReceiveData({ begin, chunk });
|
||||
});
|
||||
|
||||
this._pdfDataRangeTransport.addProgressListener((loaded, total) => {
|
||||
this._onProgress({ loaded, total, });
|
||||
this._onProgress({ loaded, total });
|
||||
});
|
||||
|
||||
this._pdfDataRangeTransport.addProgressiveReadListener((chunk) => {
|
||||
this._onReceiveData({ chunk, });
|
||||
this._pdfDataRangeTransport.addProgressiveReadListener(chunk => {
|
||||
this._onReceiveData({ chunk });
|
||||
});
|
||||
|
||||
this._pdfDataRangeTransport.addProgressiveDoneListener(() => {
|
||||
@ -78,7 +78,7 @@ class PDFDataTransportStream {
|
||||
}
|
||||
|
||||
get _progressiveDataLength() {
|
||||
return (this._fullRequestReader ? this._fullRequestReader._loaded : 0);
|
||||
return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
|
||||
}
|
||||
|
||||
_onProgress(evt) {
|
||||
@ -86,12 +86,12 @@ class PDFDataTransportStream {
|
||||
// Reporting to first range reader, if it exists.
|
||||
const firstReader = this._rangeReaders[0];
|
||||
if (firstReader && firstReader.onProgress) {
|
||||
firstReader.onProgress({ loaded: evt.loaded, });
|
||||
firstReader.onProgress({ loaded: evt.loaded });
|
||||
}
|
||||
} else {
|
||||
const fullReader = this._fullRequestReader;
|
||||
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);
|
||||
const queuedChunks = this._queuedChunks;
|
||||
this._queuedChunks = null;
|
||||
return new PDFDataTransportStreamReader(this, queuedChunks,
|
||||
this._progressiveDone);
|
||||
return new PDFDataTransportStreamReader(
|
||||
this,
|
||||
queuedChunks,
|
||||
this._progressiveDone
|
||||
);
|
||||
}
|
||||
|
||||
getRangeReader(begin, end) {
|
||||
@ -164,7 +167,7 @@ class PDFDataTransportStreamReader {
|
||||
}
|
||||
if (this._requests.length > 0) {
|
||||
const requestCapability = this._requests.shift();
|
||||
requestCapability.resolve({ value: chunk, done: false, });
|
||||
requestCapability.resolve({ value: chunk, done: false });
|
||||
} else {
|
||||
this._queuedChunks.push(chunk);
|
||||
}
|
||||
@ -194,10 +197,10 @@ class PDFDataTransportStreamReader {
|
||||
async read() {
|
||||
if (this._queuedChunks.length > 0) {
|
||||
const chunk = this._queuedChunks.shift();
|
||||
return { value: chunk, done: false, };
|
||||
return { value: chunk, done: false };
|
||||
}
|
||||
if (this._done) {
|
||||
return { value: undefined, done: true, };
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
const requestCapability = createPromiseCapability();
|
||||
this._requests.push(requestCapability);
|
||||
@ -207,7 +210,7 @@ class PDFDataTransportStreamReader {
|
||||
cancel(reason) {
|
||||
this._done = true;
|
||||
this._requests.forEach(function(requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true, });
|
||||
requestCapability.resolve({ value: undefined, done: true });
|
||||
});
|
||||
this._requests = [];
|
||||
}
|
||||
@ -241,9 +244,9 @@ class PDFDataTransportStreamRangeReader {
|
||||
this._queuedChunk = chunk;
|
||||
} else {
|
||||
const requestsCapability = this._requests.shift();
|
||||
requestsCapability.resolve({ value: chunk, done: false, });
|
||||
requestsCapability.resolve({ value: chunk, done: false });
|
||||
this._requests.forEach(function(requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true, });
|
||||
requestCapability.resolve({ value: undefined, done: true });
|
||||
});
|
||||
this._requests = [];
|
||||
}
|
||||
@ -259,10 +262,10 @@ class PDFDataTransportStreamRangeReader {
|
||||
if (this._queuedChunk) {
|
||||
const chunk = this._queuedChunk;
|
||||
this._queuedChunk = null;
|
||||
return { value: chunk, done: false, };
|
||||
return { value: chunk, done: false };
|
||||
}
|
||||
if (this._done) {
|
||||
return { value: undefined, done: true, };
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
const requestCapability = createPromiseCapability();
|
||||
this._requests.push(requestCapability);
|
||||
@ -272,13 +275,11 @@ class PDFDataTransportStreamRangeReader {
|
||||
cancel(reason) {
|
||||
this._done = true;
|
||||
this._requests.forEach(function(requestCapability) {
|
||||
requestCapability.resolve({ value: undefined, done: true, });
|
||||
requestCapability.resolve({ value: undefined, done: true });
|
||||
});
|
||||
this._requests = [];
|
||||
this._stream._removeRangeReader(this);
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PDFDataTransportStream,
|
||||
};
|
||||
export { PDFDataTransportStream };
|
||||
|
@ -14,10 +14,10 @@
|
||||
*/
|
||||
/* eslint-disable no-multi-str */
|
||||
|
||||
import { shadow } from '../shared/util';
|
||||
import { shadow } from "../shared/util";
|
||||
|
||||
class WebGLContext {
|
||||
constructor({ enable = false, }) {
|
||||
constructor({ enable = false }) {
|
||||
this._enabled = enable === true;
|
||||
}
|
||||
|
||||
@ -26,16 +26,21 @@ class WebGLContext {
|
||||
if (enabled) {
|
||||
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);
|
||||
}
|
||||
|
||||
drawFigures({ width, height, backgroundColor, figures, context, }) {
|
||||
return WebGLUtils.drawFigures(width, height, backgroundColor, figures,
|
||||
context);
|
||||
drawFigures({ width, height, backgroundColor, figures, context }) {
|
||||
return WebGLUtils.drawFigures(
|
||||
width,
|
||||
height,
|
||||
backgroundColor,
|
||||
figures,
|
||||
context
|
||||
);
|
||||
}
|
||||
|
||||
clear() {
|
||||
@ -51,7 +56,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
|
||||
if (!compiled) {
|
||||
var errorMsg = gl.getShaderInfoLog(shader);
|
||||
throw new Error('Error during shader compilation: ' + errorMsg);
|
||||
throw new Error("Error during shader compilation: " + errorMsg);
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
@ -70,7 +75,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
|
||||
if (!linked) {
|
||||
var errorMsg = gl.getProgramInfoLog(program);
|
||||
throw new Error('Error during program linking: ' + errorMsg);
|
||||
throw new Error("Error during program linking: " + errorMsg);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
@ -97,12 +102,14 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
}
|
||||
|
||||
// The temporary canvas is used in the WebGL context.
|
||||
currentCanvas = document.createElement('canvas');
|
||||
currentGL = currentCanvas.getContext('webgl',
|
||||
{ premultipliedalpha: false, });
|
||||
currentCanvas = document.createElement("canvas");
|
||||
currentGL = currentCanvas.getContext("webgl", {
|
||||
premultipliedalpha: false,
|
||||
});
|
||||
}
|
||||
|
||||
var smaskVertexShaderCode = '\
|
||||
var smaskVertexShaderCode =
|
||||
"\
|
||||
attribute vec2 a_position; \
|
||||
attribute vec2 a_texCoord; \
|
||||
\
|
||||
@ -115,9 +122,10 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
|
||||
\
|
||||
v_texCoord = a_texCoord; \
|
||||
} ';
|
||||
} ";
|
||||
|
||||
var smaskFragmentShaderCode = '\
|
||||
var smaskFragmentShaderCode =
|
||||
"\
|
||||
precision mediump float; \
|
||||
\
|
||||
uniform vec4 u_backdrop; \
|
||||
@ -144,7 +152,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
imageColor.a *= lum; \
|
||||
imageColor.rgb *= imageColor.a; \
|
||||
gl_FragColor = imageColor; \
|
||||
} ';
|
||||
} ";
|
||||
|
||||
var smaskCache = null;
|
||||
|
||||
@ -166,14 +174,14 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
var cache = {};
|
||||
cache.gl = gl;
|
||||
cache.canvas = canvas;
|
||||
cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
|
||||
cache.positionLocation = gl.getAttribLocation(program, 'a_position');
|
||||
cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop');
|
||||
cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype');
|
||||
cache.resolutionLocation = gl.getUniformLocation(program, "u_resolution");
|
||||
cache.positionLocation = gl.getAttribLocation(program, "a_position");
|
||||
cache.backdropLocation = gl.getUniformLocation(program, "u_backdrop");
|
||||
cache.subtypeLocation = gl.getUniformLocation(program, "u_subtype");
|
||||
|
||||
var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
|
||||
var texLayerLocation = gl.getUniformLocation(program, 'u_image');
|
||||
var texMaskLocation = gl.getUniformLocation(program, 'u_mask');
|
||||
var texCoordLocation = gl.getAttribLocation(program, "a_texCoord");
|
||||
var texLayerLocation = gl.getUniformLocation(program, "u_image");
|
||||
var texMaskLocation = gl.getUniformLocation(program, "u_mask");
|
||||
|
||||
// provide texture coordinates for the rectangle.
|
||||
var texCoordBuffer = gl.createBuffer();
|
||||
@ -196,25 +204,35 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
}
|
||||
|
||||
function composeSMask(layer, mask, properties) {
|
||||
var width = layer.width, height = layer.height;
|
||||
var width = layer.width,
|
||||
height = layer.height;
|
||||
|
||||
if (!smaskCache) {
|
||||
initSmaskGL();
|
||||
}
|
||||
var cache = smaskCache, canvas = cache.canvas, gl = cache.gl;
|
||||
var cache = smaskCache,
|
||||
canvas = cache.canvas,
|
||||
gl = cache.gl;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
|
||||
gl.uniform2f(cache.resolutionLocation, width, height);
|
||||
|
||||
if (properties.backdrop) {
|
||||
gl.uniform4f(cache.resolutionLocation, properties.backdrop[0],
|
||||
properties.backdrop[1], properties.backdrop[2], 1);
|
||||
gl.uniform4f(
|
||||
cache.resolutionLocation,
|
||||
properties.backdrop[0],
|
||||
properties.backdrop[1],
|
||||
properties.backdrop[2],
|
||||
1
|
||||
);
|
||||
} else {
|
||||
gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0);
|
||||
}
|
||||
gl.uniform1i(cache.subtypeLocation,
|
||||
properties.subtype === 'Luminosity' ? 1 : 0);
|
||||
gl.uniform1i(
|
||||
cache.subtypeLocation,
|
||||
properties.subtype === "Luminosity" ? 1 : 0
|
||||
);
|
||||
|
||||
// Create a textures
|
||||
var texture = createTexture(gl, layer, gl.TEXTURE0);
|
||||
@ -252,7 +270,8 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
return canvas;
|
||||
}
|
||||
|
||||
var figuresVertexShaderCode = '\
|
||||
var figuresVertexShaderCode =
|
||||
"\
|
||||
attribute vec2 a_position; \
|
||||
attribute vec3 a_color; \
|
||||
\
|
||||
@ -268,16 +287,17 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); \
|
||||
\
|
||||
v_color = vec4(a_color / 255.0, 1.0); \
|
||||
} ';
|
||||
} ";
|
||||
|
||||
var figuresFragmentShaderCode = '\
|
||||
var figuresFragmentShaderCode =
|
||||
"\
|
||||
precision mediump float; \
|
||||
\
|
||||
varying vec4 v_color; \
|
||||
\
|
||||
void main() { \
|
||||
gl_FragColor = v_color; \
|
||||
} ';
|
||||
} ";
|
||||
|
||||
var figuresCache = null;
|
||||
|
||||
@ -299,11 +319,11 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
var cache = {};
|
||||
cache.gl = gl;
|
||||
cache.canvas = canvas;
|
||||
cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
|
||||
cache.scaleLocation = gl.getUniformLocation(program, 'u_scale');
|
||||
cache.offsetLocation = gl.getUniformLocation(program, 'u_offset');
|
||||
cache.positionLocation = gl.getAttribLocation(program, 'a_position');
|
||||
cache.colorLocation = gl.getAttribLocation(program, 'a_color');
|
||||
cache.resolutionLocation = gl.getUniformLocation(program, "u_resolution");
|
||||
cache.scaleLocation = gl.getUniformLocation(program, "u_scale");
|
||||
cache.offsetLocation = gl.getUniformLocation(program, "u_offset");
|
||||
cache.positionLocation = gl.getAttribLocation(program, "a_position");
|
||||
cache.colorLocation = gl.getAttribLocation(program, "a_color");
|
||||
|
||||
figuresCache = cache;
|
||||
}
|
||||
@ -312,7 +332,9 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
if (!figuresCache) {
|
||||
initFiguresGL();
|
||||
}
|
||||
var cache = figuresCache, canvas = cache.canvas, gl = cache.gl;
|
||||
var cache = figuresCache,
|
||||
canvas = cache.canvas,
|
||||
gl = cache.gl;
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
@ -324,11 +346,11 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
var i, ii, rows;
|
||||
for (i = 0, ii = figures.length; i < ii; i++) {
|
||||
switch (figures[i].type) {
|
||||
case 'lattice':
|
||||
case "lattice":
|
||||
rows = (figures[i].coords.length / figures[i].verticesPerRow) | 0;
|
||||
count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6;
|
||||
break;
|
||||
case 'triangles':
|
||||
case "triangles":
|
||||
count += figures[i].coords.length;
|
||||
break;
|
||||
}
|
||||
@ -336,12 +358,16 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
// transfer data
|
||||
var coords = new Float32Array(count * 2);
|
||||
var colors = new Uint8Array(count * 3);
|
||||
var coordsMap = context.coords, colorsMap = context.colors;
|
||||
var pIndex = 0, cIndex = 0;
|
||||
var coordsMap = context.coords,
|
||||
colorsMap = context.colors;
|
||||
var pIndex = 0,
|
||||
cIndex = 0;
|
||||
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) {
|
||||
case 'lattice':
|
||||
case "lattice":
|
||||
var cols = figure.verticesPerRow;
|
||||
rows = (ps.length / cols) | 0;
|
||||
for (var row = 1; row < rows; row++) {
|
||||
@ -383,7 +409,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'triangles':
|
||||
case "triangles":
|
||||
for (var j = 0, jj = ps.length; j < jj; j++) {
|
||||
coords[pIndex] = coordsMap[ps[j]];
|
||||
coords[pIndex + 1] = coordsMap[ps[j] + 1];
|
||||
@ -399,8 +425,12 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
|
||||
// draw
|
||||
if (backgroundColor) {
|
||||
gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255,
|
||||
backgroundColor[2] / 255, 1.0);
|
||||
gl.clearColor(
|
||||
backgroundColor[0] / 255,
|
||||
backgroundColor[1] / 255,
|
||||
backgroundColor[2] / 255,
|
||||
1.0
|
||||
);
|
||||
} else {
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
}
|
||||
@ -416,8 +446,14 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
|
||||
gl.enableVertexAttribArray(cache.colorLocation);
|
||||
gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false,
|
||||
0, 0);
|
||||
gl.vertexAttribPointer(
|
||||
cache.colorLocation,
|
||||
3,
|
||||
gl.UNSIGNED_BYTE,
|
||||
false,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY);
|
||||
gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY);
|
||||
@ -437,7 +473,7 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
try {
|
||||
generateGL();
|
||||
return !!currentGL;
|
||||
} catch (ex) { }
|
||||
} catch (ex) {}
|
||||
return false;
|
||||
},
|
||||
|
||||
@ -460,6 +496,4 @@ var WebGLUtils = (function WebGLUtilsClosure() {
|
||||
};
|
||||
})();
|
||||
|
||||
export {
|
||||
WebGLContext,
|
||||
};
|
||||
export { WebGLContext };
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user