mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
[api-minor] Use the NodeCanvasFactory
/NodeCMapReaderFactory
classes as defaults in Node.js environments (issue 11900)
This moves, and slightly simplifies, code that's currently residing in the unit-test utils into the actual library, such that it's bundled with `GENERIC`-builds and used in e.g. the API-code. As an added bonus, this also brings out-of-the-box support for CMaps in e.g. the Node.js examples.
This commit is contained in:
parent
fe3df495cc
commit
4a7e29865d
10 changed files with 164 additions and 123 deletions
|
@ -47,6 +47,7 @@ import {
|
|||
StatTimer,
|
||||
} from "./display_utils.js";
|
||||
import { FontFaceObject, FontLoader } from "./font_loader.js";
|
||||
import { NodeCanvasFactory, NodeCMapReaderFactory } from "./node_utils.js";
|
||||
import { apiCompatibilityParams } from "./api_compatibility.js";
|
||||
import { CanvasGraphics } from "./canvas.js";
|
||||
import { GlobalWorkerOptions } from "./worker_options.js";
|
||||
|
@ -59,6 +60,15 @@ import { WebGLContext } from "./webgl.js";
|
|||
const DEFAULT_RANGE_CHUNK_SIZE = 65536; // 2^16 = 65536
|
||||
const RENDERING_CANCELLED_TIMEOUT = 100; // ms
|
||||
|
||||
const DefaultCanvasFactory =
|
||||
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) && isNodeJS
|
||||
? NodeCanvasFactory
|
||||
: DOMCanvasFactory;
|
||||
const DefaultCMapReaderFactory =
|
||||
(typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) && isNodeJS
|
||||
? NodeCMapReaderFactory
|
||||
: DOMCMapReaderFactory;
|
||||
|
||||
/**
|
||||
* @typedef {function} IPDFStreamFactory
|
||||
* @param {DocumentInitParameters} params - The document initialization
|
||||
|
@ -242,7 +252,8 @@ function getDocument(src) {
|
|||
}
|
||||
|
||||
params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
|
||||
params.CMapReaderFactory = params.CMapReaderFactory || DOMCMapReaderFactory;
|
||||
params.CMapReaderFactory =
|
||||
params.CMapReaderFactory || DefaultCMapReaderFactory;
|
||||
params.ignoreErrors = params.stopAtErrors !== true;
|
||||
params.fontExtraProperties = params.fontExtraProperties === true;
|
||||
params.pdfBug = params.pdfBug === true;
|
||||
|
@ -863,9 +874,9 @@ class PDFDocumentProxy {
|
|||
* just before viewport transform.
|
||||
* @property {Object} [imageLayer] - An object that has beginLayout,
|
||||
* endLayout and appendImage functions.
|
||||
* @property {Object} [canvasFactory] - The factory that will be used
|
||||
* @property {Object} [canvasFactory] - The factory instance that will be used
|
||||
* when creating canvases. The default value is
|
||||
* {DOMCanvasFactory}.
|
||||
* {new DOMCanvasFactory()}.
|
||||
* @property {Object} [background] - Background to use for the canvas.
|
||||
* Can use any valid canvas.fillStyle: A DOMString parsed as
|
||||
* CSS <color> value, a CanvasGradient object (a linear or
|
||||
|
@ -1015,7 +1026,7 @@ class PDFPageProxy {
|
|||
intentState.streamReaderCancelTimeout = null;
|
||||
}
|
||||
|
||||
const canvasFactoryInstance = canvasFactory || new DOMCanvasFactory();
|
||||
const canvasFactoryInstance = canvasFactory || new DefaultCanvasFactory();
|
||||
const webGLContext = new WebGLContext({
|
||||
enable: enableWebGL,
|
||||
});
|
||||
|
|
|
@ -21,6 +21,7 @@ import {
|
|||
isString,
|
||||
removeNullCharacters,
|
||||
stringToBytes,
|
||||
unreachable,
|
||||
Util,
|
||||
warn,
|
||||
} from "../shared/util.js";
|
||||
|
@ -28,19 +29,15 @@ import {
|
|||
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");
|
||||
class BaseCanvasFactory {
|
||||
constructor() {
|
||||
if (this.constructor === BaseCanvasFactory) {
|
||||
unreachable("Cannot initialize BaseCanvasFactory.");
|
||||
}
|
||||
const canvas = document.createElement("canvas");
|
||||
const context = canvas.getContext("2d");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return {
|
||||
canvas,
|
||||
context,
|
||||
};
|
||||
}
|
||||
|
||||
create(width, height) {
|
||||
unreachable("Abstract method `create` called.");
|
||||
}
|
||||
|
||||
reset(canvasAndContext, width, height) {
|
||||
|
@ -67,8 +64,27 @@ class DOMCanvasFactory {
|
|||
}
|
||||
}
|
||||
|
||||
class DOMCMapReaderFactory {
|
||||
class DOMCanvasFactory extends BaseCanvasFactory {
|
||||
create(width, height) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new Error("Invalid canvas size");
|
||||
}
|
||||
const canvas = document.createElement("canvas");
|
||||
const context = canvas.getContext("2d");
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
return {
|
||||
canvas,
|
||||
context,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class BaseCMapReaderFactory {
|
||||
constructor({ baseUrl = null, isCompressed = false }) {
|
||||
if (this.constructor === BaseCMapReaderFactory) {
|
||||
unreachable("Cannot initialize BaseCMapReaderFactory.");
|
||||
}
|
||||
this.baseUrl = baseUrl;
|
||||
this.isCompressed = isCompressed;
|
||||
}
|
||||
|
@ -88,29 +104,39 @@ class DOMCMapReaderFactory {
|
|||
? CMapCompressionType.BINARY
|
||||
: CMapCompressionType.NONE;
|
||||
|
||||
return this._fetchData(url, compressionType).catch(reason => {
|
||||
throw new Error(
|
||||
`Unable to load ${this.isCompressed ? "binary " : ""}CMap at: ${url}`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_fetchData(url, compressionType) {
|
||||
unreachable("Abstract method `_fetchData` called.");
|
||||
}
|
||||
}
|
||||
|
||||
class DOMCMapReaderFactory extends BaseCMapReaderFactory {
|
||||
_fetchData(url, compressionType) {
|
||||
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);
|
||||
}
|
||||
let cMapData;
|
||||
if (this.isCompressed) {
|
||||
cMapData = new Uint8Array(await response.arrayBuffer());
|
||||
} else {
|
||||
cMapData = stringToBytes(await response.text());
|
||||
}
|
||||
return { cMapData, compressionType };
|
||||
})
|
||||
.catch(reason => {
|
||||
throw new Error(
|
||||
`Unable to load ${this.isCompressed ? "binary " : ""}` +
|
||||
`CMap at: ${url}`
|
||||
);
|
||||
});
|
||||
return fetch(url).then(async response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
let cMapData;
|
||||
if (this.isCompressed) {
|
||||
cMapData = new Uint8Array(await response.arrayBuffer());
|
||||
} else {
|
||||
cMapData = stringToBytes(await response.text());
|
||||
}
|
||||
return { cMapData, compressionType };
|
||||
});
|
||||
}
|
||||
|
||||
// The Fetch API is not supported.
|
||||
|
@ -141,11 +167,6 @@ class DOMCMapReaderFactory {
|
|||
};
|
||||
|
||||
request.send(null);
|
||||
}).catch(reason => {
|
||||
throw new Error(
|
||||
`Unable to load ${this.isCompressed ? "binary " : ""}` +
|
||||
`CMap at: ${url}`
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -609,7 +630,9 @@ export {
|
|||
getFilenameFromUrl,
|
||||
LinkTarget,
|
||||
DEFAULT_LINK_REL,
|
||||
BaseCanvasFactory,
|
||||
DOMCanvasFactory,
|
||||
BaseCMapReaderFactory,
|
||||
DOMCMapReaderFactory,
|
||||
DOMSVGFactory,
|
||||
StatTimer,
|
||||
|
|
65
src/display/node_utils.js
Normal file
65
src/display/node_utils.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
/* Copyright 2020 Mozilla Foundation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/* globals __non_webpack_require__ */
|
||||
/* eslint no-var: error */
|
||||
|
||||
import { BaseCanvasFactory, BaseCMapReaderFactory } from "./display_utils.js";
|
||||
import { isNodeJS } from "../shared/is_node.js";
|
||||
import { unreachable } from "../shared/util.js";
|
||||
|
||||
let NodeCanvasFactory = class {
|
||||
constructor() {
|
||||
unreachable("Not implemented: NodeCanvasFactory");
|
||||
}
|
||||
};
|
||||
|
||||
let NodeCMapReaderFactory = class {
|
||||
constructor() {
|
||||
unreachable("Not implemented: NodeCMapReaderFactory");
|
||||
}
|
||||
};
|
||||
|
||||
if ((typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) && isNodeJS) {
|
||||
NodeCanvasFactory = class extends BaseCanvasFactory {
|
||||
create(width, height) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new Error("Invalid canvas size");
|
||||
}
|
||||
const Canvas = __non_webpack_require__("canvas");
|
||||
const canvas = Canvas.createCanvas(width, height);
|
||||
return {
|
||||
canvas,
|
||||
context: canvas.getContext("2d"),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
NodeCMapReaderFactory = class extends BaseCMapReaderFactory {
|
||||
_fetchData(url, compressionType) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fs = __non_webpack_require__("fs");
|
||||
fs.readFile(url, (error, data) => {
|
||||
if (error || !data) {
|
||||
reject(new Error(error));
|
||||
return;
|
||||
}
|
||||
resolve({ cMapData: new Uint8Array(data), compressionType });
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export { NodeCanvasFactory, NodeCMapReaderFactory };
|
Loading…
Add table
Add a link
Reference in a new issue