mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-19 06:38:07 +02:00
[api-major] Add openjpeg.wasm to pdf.js (bug 1935076)
In order to fix bug 1935076, we'll have to add a pure js fallback in case wasm is disabled or simd isn't supported. Unfortunately, this fallback will take some space. So, the main goal of this patch is to reduce the overall size (by ~93k). As a side effect, it should make easier to use an other wasm file (which must export _jp2_decode, _malloc and _free).
This commit is contained in:
parent
711bf2bd12
commit
94b4b54ef6
21 changed files with 274 additions and 19 deletions
5
external/openjpeg/openjpeg.js
vendored
5
external/openjpeg/openjpeg.js
vendored
File diff suppressed because one or more lines are too long
BIN
external/openjpeg/openjpeg.wasm
vendored
Normal file
BIN
external/openjpeg/openjpeg.wasm
vendored
Normal file
Binary file not shown.
16
gulpfile.mjs
16
gulpfile.mjs
|
@ -192,6 +192,7 @@ function createWebpackAlias(defines) {
|
||||||
const libraryAlias = {
|
const libraryAlias = {
|
||||||
"display-cmap_reader_factory": "src/display/stubs.js",
|
"display-cmap_reader_factory": "src/display/stubs.js",
|
||||||
"display-standard_fontdata_factory": "src/display/stubs.js",
|
"display-standard_fontdata_factory": "src/display/stubs.js",
|
||||||
|
"display-wasm_factory": "src/display/stubs.js",
|
||||||
"display-fetch_stream": "src/display/stubs.js",
|
"display-fetch_stream": "src/display/stubs.js",
|
||||||
"display-network": "src/display/stubs.js",
|
"display-network": "src/display/stubs.js",
|
||||||
"display-node_stream": "src/display/stubs.js",
|
"display-node_stream": "src/display/stubs.js",
|
||||||
|
@ -224,6 +225,7 @@ function createWebpackAlias(defines) {
|
||||||
"src/display/cmap_reader_factory.js";
|
"src/display/cmap_reader_factory.js";
|
||||||
libraryAlias["display-standard_fontdata_factory"] =
|
libraryAlias["display-standard_fontdata_factory"] =
|
||||||
"src/display/standard_fontdata_factory.js";
|
"src/display/standard_fontdata_factory.js";
|
||||||
|
libraryAlias["display-wasm_factory"] = "src/display/wasm_factory.js";
|
||||||
libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js";
|
libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js";
|
||||||
libraryAlias["display-network"] = "src/display/network.js";
|
libraryAlias["display-network"] = "src/display/network.js";
|
||||||
|
|
||||||
|
@ -240,6 +242,7 @@ function createWebpackAlias(defines) {
|
||||||
"src/display/cmap_reader_factory.js";
|
"src/display/cmap_reader_factory.js";
|
||||||
libraryAlias["display-standard_fontdata_factory"] =
|
libraryAlias["display-standard_fontdata_factory"] =
|
||||||
"src/display/standard_fontdata_factory.js";
|
"src/display/standard_fontdata_factory.js";
|
||||||
|
libraryAlias["display-wasm_factory"] = "src/display/wasm_factory.js";
|
||||||
libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js";
|
libraryAlias["display-fetch_stream"] = "src/display/fetch_stream.js";
|
||||||
libraryAlias["display-network"] = "src/display/network.js";
|
libraryAlias["display-network"] = "src/display/network.js";
|
||||||
libraryAlias["display-node_stream"] = "src/display/node_stream.js";
|
libraryAlias["display-node_stream"] = "src/display/node_stream.js";
|
||||||
|
@ -646,6 +649,13 @@ function createStandardFontBundle() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createWasmBundle() {
|
||||||
|
return gulp.src(["external/openjpeg/openjpeg.wasm"], {
|
||||||
|
base: "external/openjpeg",
|
||||||
|
encoding: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function checkFile(filePath) {
|
function checkFile(filePath) {
|
||||||
try {
|
try {
|
||||||
const stat = fs.lstatSync(filePath);
|
const stat = fs.lstatSync(filePath);
|
||||||
|
@ -1068,6 +1078,7 @@ function buildGeneric(defines, dir) {
|
||||||
.pipe(gulp.dest(dir + "web")),
|
.pipe(gulp.dest(dir + "web")),
|
||||||
createCMapBundle().pipe(gulp.dest(dir + "web/cmaps")),
|
createCMapBundle().pipe(gulp.dest(dir + "web/cmaps")),
|
||||||
createStandardFontBundle().pipe(gulp.dest(dir + "web/standard_fonts")),
|
createStandardFontBundle().pipe(gulp.dest(dir + "web/standard_fonts")),
|
||||||
|
createWasmBundle().pipe(gulp.dest(dir + "web/wasm")),
|
||||||
|
|
||||||
preprocessHTML("web/viewer.html", defines).pipe(gulp.dest(dir + "web")),
|
preprocessHTML("web/viewer.html", defines).pipe(gulp.dest(dir + "web")),
|
||||||
preprocessCSS("web/viewer.css", defines)
|
preprocessCSS("web/viewer.css", defines)
|
||||||
|
@ -1398,6 +1409,7 @@ gulp.task(
|
||||||
createStandardFontBundle().pipe(
|
createStandardFontBundle().pipe(
|
||||||
gulp.dest(MOZCENTRAL_CONTENT_DIR + "web/standard_fonts")
|
gulp.dest(MOZCENTRAL_CONTENT_DIR + "web/standard_fonts")
|
||||||
),
|
),
|
||||||
|
createWasmBundle().pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + "web/wasm")),
|
||||||
|
|
||||||
preprocessHTML("web/viewer.html", defines).pipe(
|
preprocessHTML("web/viewer.html", defines).pipe(
|
||||||
gulp.dest(MOZCENTRAL_CONTENT_DIR + "web")
|
gulp.dest(MOZCENTRAL_CONTENT_DIR + "web")
|
||||||
|
@ -1500,6 +1512,9 @@ gulp.task(
|
||||||
createStandardFontBundle().pipe(
|
createStandardFontBundle().pipe(
|
||||||
gulp.dest(CHROME_BUILD_CONTENT_DIR + "web/standard_fonts")
|
gulp.dest(CHROME_BUILD_CONTENT_DIR + "web/standard_fonts")
|
||||||
),
|
),
|
||||||
|
createWasmBundle().pipe(
|
||||||
|
gulp.dest(CHROME_BUILD_CONTENT_DIR + "web/wasm")
|
||||||
|
),
|
||||||
|
|
||||||
preprocessHTML("web/viewer.html", defines).pipe(
|
preprocessHTML("web/viewer.html", defines).pipe(
|
||||||
gulp.dest(CHROME_BUILD_CONTENT_DIR + "web")
|
gulp.dest(CHROME_BUILD_CONTENT_DIR + "web")
|
||||||
|
@ -1586,6 +1601,7 @@ function buildLibHelper(bundleDefines, inputStream, outputDir) {
|
||||||
"pdfjs-lib": "../pdf.js",
|
"pdfjs-lib": "../pdf.js",
|
||||||
"display-cmap_reader_factory": "./cmap_reader_factory.js",
|
"display-cmap_reader_factory": "./cmap_reader_factory.js",
|
||||||
"display-standard_fontdata_factory": "./standard_fontdata_factory.js",
|
"display-standard_fontdata_factory": "./standard_fontdata_factory.js",
|
||||||
|
"display-wasm_factory": "./wasm_factory.js",
|
||||||
"display-fetch_stream": "./fetch_stream.js",
|
"display-fetch_stream": "./fetch_stream.js",
|
||||||
"display-network": "./network.js",
|
"display-network": "./network.js",
|
||||||
"display-node_stream": "./node_stream.js",
|
"display-node_stream": "./node_stream.js",
|
||||||
|
|
|
@ -64,6 +64,10 @@ class BaseStream {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isAsyncDecoder() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
get canAsyncDecodeImageFromBuffer() {
|
get canAsyncDecodeImageFromBuffer() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,8 +99,11 @@ class DecodeStream extends BaseStream {
|
||||||
return this.buffer.subarray(pos, end);
|
return this.buffer.subarray(pos, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getImageData(length, decoderOptions = null) {
|
async getImageData(length, decoderOptions) {
|
||||||
if (!this.canAsyncDecodeImageFromBuffer) {
|
if (!this.canAsyncDecodeImageFromBuffer) {
|
||||||
|
if (this.isAsyncDecoder) {
|
||||||
|
return this.decodeImage(null, decoderOptions);
|
||||||
|
}
|
||||||
return this.getBytes(length, decoderOptions);
|
return this.getBytes(length, decoderOptions);
|
||||||
}
|
}
|
||||||
const data = await this.stream.asyncGetBytes();
|
const data = await this.stream.asyncGetBytes();
|
||||||
|
|
|
@ -72,6 +72,7 @@ import { getMetrics } from "./metrics.js";
|
||||||
import { getUnicodeForGlyph } from "./unicode.js";
|
import { getUnicodeForGlyph } from "./unicode.js";
|
||||||
import { ImageResizer } from "./image_resizer.js";
|
import { ImageResizer } from "./image_resizer.js";
|
||||||
import { JpegStream } from "./jpeg_stream.js";
|
import { JpegStream } from "./jpeg_stream.js";
|
||||||
|
import { JpxImage } from "./jpx.js";
|
||||||
import { MurmurHash3_64 } from "../shared/murmurhash3.js";
|
import { MurmurHash3_64 } from "../shared/murmurhash3.js";
|
||||||
import { OperatorList } from "./operator_list.js";
|
import { OperatorList } from "./operator_list.js";
|
||||||
import { PDFImage } from "./image.js";
|
import { PDFImage } from "./image.js";
|
||||||
|
@ -89,6 +90,7 @@ const DefaultPartialEvaluatorOptions = Object.freeze({
|
||||||
useSystemFonts: true,
|
useSystemFonts: true,
|
||||||
cMapUrl: null,
|
cMapUrl: null,
|
||||||
standardFontDataUrl: null,
|
standardFontDataUrl: null,
|
||||||
|
wasmUrl: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
const PatternType = {
|
const PatternType = {
|
||||||
|
@ -236,6 +238,10 @@ class PartialEvaluator {
|
||||||
|
|
||||||
ImageResizer.setOptions(this.options);
|
ImageResizer.setOptions(this.options);
|
||||||
JpegStream.setOptions(this.options);
|
JpegStream.setOptions(this.options);
|
||||||
|
JpxImage.setOptions({
|
||||||
|
wasmUrl: this.options.wasmUrl,
|
||||||
|
handler,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,20 +24,97 @@ class JpxError extends BaseException {
|
||||||
}
|
}
|
||||||
|
|
||||||
class JpxImage {
|
class JpxImage {
|
||||||
static #module = null;
|
static #buffer = null;
|
||||||
|
|
||||||
static decode(data, decoderOptions) {
|
static #handler = null;
|
||||||
decoderOptions ||= {};
|
|
||||||
this.#module ||= OpenJPEG({ warn });
|
static #instantiationFailed = false;
|
||||||
const imageData = this.#module.decode(data, decoderOptions);
|
|
||||||
if (typeof imageData === "string") {
|
static #modulePromise = null;
|
||||||
throw new JpxError(imageData);
|
|
||||||
|
static #wasmUrl = null;
|
||||||
|
|
||||||
|
static setOptions({ handler, wasmUrl }) {
|
||||||
|
if (!this.#buffer) {
|
||||||
|
this.#wasmUrl = wasmUrl || null;
|
||||||
|
if (wasmUrl === null) {
|
||||||
|
this.#handler = handler;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async #instantiateWasm(imports, successCallback) {
|
||||||
|
try {
|
||||||
|
if (!this.#buffer) {
|
||||||
|
if (this.#wasmUrl !== null) {
|
||||||
|
const response = await fetch(`${this.#wasmUrl}openjpeg.wasm`);
|
||||||
|
this.#buffer = await response.arrayBuffer();
|
||||||
|
} else {
|
||||||
|
this.#buffer = await this.#handler.sendWithPromise("FetchWasm", {
|
||||||
|
filename: "openjpeg.wasm",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const results = await WebAssembly.instantiate(this.#buffer, imports);
|
||||||
|
return successCallback(results.instance);
|
||||||
|
} catch (e) {
|
||||||
|
this.#instantiationFailed = true;
|
||||||
|
warn(`Cannot load openjpeg.wasm: "${e}".`);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
this.#handler = null;
|
||||||
|
this.#wasmUrl = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async decode(
|
||||||
|
bytes,
|
||||||
|
{ numComponents = 4, isIndexedColormap = false, smaskInData = false } = {}
|
||||||
|
) {
|
||||||
|
if (this.#instantiationFailed) {
|
||||||
|
throw new JpxError("OpenJPEG failed to instantiate.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#modulePromise ||= OpenJPEG({
|
||||||
|
warn,
|
||||||
|
instantiateWasm: this.#instantiateWasm.bind(this),
|
||||||
|
});
|
||||||
|
|
||||||
|
const module = await this.#modulePromise;
|
||||||
|
let ptr;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const size = bytes.length;
|
||||||
|
ptr = module._malloc(size);
|
||||||
|
module.HEAPU8.set(bytes, ptr);
|
||||||
|
const ret = module._jp2_decode(
|
||||||
|
ptr,
|
||||||
|
size,
|
||||||
|
numComponents > 0 ? numComponents : 0,
|
||||||
|
!!isIndexedColormap,
|
||||||
|
!!smaskInData
|
||||||
|
);
|
||||||
|
if (ret) {
|
||||||
|
const { errorMessages } = module;
|
||||||
|
if (errorMessages) {
|
||||||
|
delete module.errorMessages;
|
||||||
|
throw new JpxError(errorMessages);
|
||||||
|
}
|
||||||
|
throw new JpxError("Unknown error");
|
||||||
|
}
|
||||||
|
const { imageData } = module;
|
||||||
|
module.imageData = null;
|
||||||
|
|
||||||
return imageData;
|
return imageData;
|
||||||
|
} finally {
|
||||||
|
if (ptr) {
|
||||||
|
module._free(ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static cleanup() {
|
static cleanup() {
|
||||||
this.#module = null;
|
this.#modulePromise = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static parseImageProperties(stream) {
|
static parseImageProperties(stream) {
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { shadow, unreachable } from "../shared/util.js";
|
||||||
import { DecodeStream } from "./decode_stream.js";
|
import { DecodeStream } from "./decode_stream.js";
|
||||||
import { JpxImage } from "./jpx.js";
|
import { JpxImage } from "./jpx.js";
|
||||||
import { shadow } from "../shared/util.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For JPEG 2000's we use a library to decode these images and
|
* For JPEG 2000's we use a library to decode these images and
|
||||||
|
@ -42,15 +42,19 @@ class JpxStream extends DecodeStream {
|
||||||
}
|
}
|
||||||
|
|
||||||
readBlock(decoderOptions) {
|
readBlock(decoderOptions) {
|
||||||
this.decodeImage(null, decoderOptions);
|
unreachable("JpxStream.readBlock");
|
||||||
}
|
}
|
||||||
|
|
||||||
decodeImage(bytes, decoderOptions) {
|
get isAsyncDecoder() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async decodeImage(bytes, decoderOptions) {
|
||||||
if (this.eof) {
|
if (this.eof) {
|
||||||
return this.buffer;
|
return this.buffer;
|
||||||
}
|
}
|
||||||
bytes ||= this.bytes;
|
bytes ||= this.bytes;
|
||||||
this.buffer = JpxImage.decode(bytes, decoderOptions);
|
this.buffer = await JpxImage.decode(bytes, decoderOptions);
|
||||||
this.bufferLength = this.buffer.length;
|
this.bufferLength = this.buffer.length;
|
||||||
this.eof = true;
|
this.eof = true;
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,14 @@ import {
|
||||||
NodeCMapReaderFactory,
|
NodeCMapReaderFactory,
|
||||||
NodeFilterFactory,
|
NodeFilterFactory,
|
||||||
NodeStandardFontDataFactory,
|
NodeStandardFontDataFactory,
|
||||||
|
NodeWasmFactory,
|
||||||
} from "display-node_utils";
|
} from "display-node_utils";
|
||||||
import { CanvasGraphics } from "./canvas.js";
|
import { CanvasGraphics } from "./canvas.js";
|
||||||
import { DOMCanvasFactory } from "./canvas_factory.js";
|
import { DOMCanvasFactory } from "./canvas_factory.js";
|
||||||
import { DOMCMapReaderFactory } from "display-cmap_reader_factory";
|
import { DOMCMapReaderFactory } from "display-cmap_reader_factory";
|
||||||
import { DOMFilterFactory } from "./filter_factory.js";
|
import { DOMFilterFactory } from "./filter_factory.js";
|
||||||
import { DOMStandardFontDataFactory } from "display-standard_fontdata_factory";
|
import { DOMStandardFontDataFactory } from "display-standard_fontdata_factory";
|
||||||
|
import { DOMWasmFactory } from "display-wasm_factory";
|
||||||
import { GlobalWorkerOptions } from "./worker_options.js";
|
import { GlobalWorkerOptions } from "./worker_options.js";
|
||||||
import { Metadata } from "./metadata.js";
|
import { Metadata } from "./metadata.js";
|
||||||
import { OptionalContentConfig } from "./optional_content_config.js";
|
import { OptionalContentConfig } from "./optional_content_config.js";
|
||||||
|
@ -88,6 +90,10 @@ const DefaultStandardFontDataFactory =
|
||||||
typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC") && isNodeJS
|
typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC") && isNodeJS
|
||||||
? NodeStandardFontDataFactory
|
? NodeStandardFontDataFactory
|
||||||
: DOMStandardFontDataFactory;
|
: DOMStandardFontDataFactory;
|
||||||
|
const DefaultWasmFactory =
|
||||||
|
typeof PDFJSDev !== "undefined" && PDFJSDev.test("GENERIC") && isNodeJS
|
||||||
|
? NodeWasmFactory
|
||||||
|
: DOMWasmFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef { Int8Array | Uint8Array | Uint8ClampedArray |
|
* @typedef { Int8Array | Uint8Array | Uint8ClampedArray |
|
||||||
|
@ -153,6 +159,12 @@ const DefaultStandardFontDataFactory =
|
||||||
* when reading the standard font files. Providing a custom factory is useful
|
* when reading the standard font files. Providing a custom factory is useful
|
||||||
* for environments without Fetch API or `XMLHttpRequest` support, such as
|
* for environments without Fetch API or `XMLHttpRequest` support, such as
|
||||||
* Node.js. The default value is {DOMStandardFontDataFactory}.
|
* Node.js. The default value is {DOMStandardFontDataFactory}.
|
||||||
|
* @property {string} [wasmUrl] - The URL where the wasm files are located.
|
||||||
|
* Include the trailing slash.
|
||||||
|
* @property {Object} [WasmFactory] - The factory that will be used
|
||||||
|
* when reading the wasm files. Providing a custom factory is useful
|
||||||
|
* for environments without Fetch API or `XMLHttpRequest` support, such as
|
||||||
|
* Node.js. The default value is {DOMWasmFactory}.
|
||||||
* @property {boolean} [useWorkerFetch] - Enable using the Fetch API in the
|
* @property {boolean} [useWorkerFetch] - Enable using the Fetch API in the
|
||||||
* worker-thread when reading CMap and standard font files. When `true`,
|
* worker-thread when reading CMap and standard font files. When `true`,
|
||||||
* the `CMapReaderFactory` and `StandardFontDataFactory` options are ignored.
|
* the `CMapReaderFactory` and `StandardFontDataFactory` options are ignored.
|
||||||
|
@ -280,6 +292,8 @@ function getDocument(src = {}) {
|
||||||
: null;
|
: null;
|
||||||
const StandardFontDataFactory =
|
const StandardFontDataFactory =
|
||||||
src.StandardFontDataFactory || DefaultStandardFontDataFactory;
|
src.StandardFontDataFactory || DefaultStandardFontDataFactory;
|
||||||
|
const wasmUrl = typeof src.wasmUrl === "string" ? src.wasmUrl : null;
|
||||||
|
const WasmFactory = src.WasmFactory || DefaultWasmFactory;
|
||||||
const ignoreErrors = src.stopAtErrors !== true;
|
const ignoreErrors = src.stopAtErrors !== true;
|
||||||
const maxImageSize =
|
const maxImageSize =
|
||||||
Number.isInteger(src.maxImageSize) && src.maxImageSize > -1
|
Number.isInteger(src.maxImageSize) && src.maxImageSize > -1
|
||||||
|
@ -328,10 +342,13 @@ function getDocument(src = {}) {
|
||||||
: (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) ||
|
: (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) ||
|
||||||
(CMapReaderFactory === DOMCMapReaderFactory &&
|
(CMapReaderFactory === DOMCMapReaderFactory &&
|
||||||
StandardFontDataFactory === DOMStandardFontDataFactory &&
|
StandardFontDataFactory === DOMStandardFontDataFactory &&
|
||||||
|
WasmFactory === DOMWasmFactory &&
|
||||||
cMapUrl &&
|
cMapUrl &&
|
||||||
standardFontDataUrl &&
|
standardFontDataUrl &&
|
||||||
|
wasmUrl &&
|
||||||
isValidFetchUrl(cMapUrl, document.baseURI) &&
|
isValidFetchUrl(cMapUrl, document.baseURI) &&
|
||||||
isValidFetchUrl(standardFontDataUrl, document.baseURI));
|
isValidFetchUrl(standardFontDataUrl, document.baseURI) &&
|
||||||
|
isValidFetchUrl(wasmUrl, document.baseURI));
|
||||||
|
|
||||||
// Parameters only intended for development/testing purposes.
|
// Parameters only intended for development/testing purposes.
|
||||||
const styleElement =
|
const styleElement =
|
||||||
|
@ -357,6 +374,11 @@ function getDocument(src = {}) {
|
||||||
useWorkerFetch
|
useWorkerFetch
|
||||||
? null
|
? null
|
||||||
: new StandardFontDataFactory({ baseUrl: standardFontDataUrl }),
|
: new StandardFontDataFactory({ baseUrl: standardFontDataUrl }),
|
||||||
|
wasmFactory:
|
||||||
|
(typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) ||
|
||||||
|
useWorkerFetch
|
||||||
|
? null
|
||||||
|
: new WasmFactory({ baseUrl: wasmUrl }),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!worker) {
|
if (!worker) {
|
||||||
|
@ -397,6 +419,7 @@ function getDocument(src = {}) {
|
||||||
useSystemFonts,
|
useSystemFonts,
|
||||||
cMapUrl: useWorkerFetch ? cMapUrl : null,
|
cMapUrl: useWorkerFetch ? cMapUrl : null,
|
||||||
standardFontDataUrl: useWorkerFetch ? standardFontDataUrl : null,
|
standardFontDataUrl: useWorkerFetch ? standardFontDataUrl : null,
|
||||||
|
wasmUrl: useWorkerFetch ? wasmUrl : null,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const transportParams = {
|
const transportParams = {
|
||||||
|
@ -2423,6 +2446,7 @@ class WorkerTransport {
|
||||||
this.filterFactory = factory.filterFactory;
|
this.filterFactory = factory.filterFactory;
|
||||||
this.cMapReaderFactory = factory.cMapReaderFactory;
|
this.cMapReaderFactory = factory.cMapReaderFactory;
|
||||||
this.standardFontDataFactory = factory.standardFontDataFactory;
|
this.standardFontDataFactory = factory.standardFontDataFactory;
|
||||||
|
this.wasmFactory = factory.wasmFactory;
|
||||||
|
|
||||||
this.destroyed = false;
|
this.destroyed = false;
|
||||||
this.destroyCapability = null;
|
this.destroyCapability = null;
|
||||||
|
@ -2918,6 +2942,21 @@ class WorkerTransport {
|
||||||
}
|
}
|
||||||
return this.standardFontDataFactory.fetch(data);
|
return this.standardFontDataFactory.fetch(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
messageHandler.on("FetchWasm", async data => {
|
||||||
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
||||||
|
throw new Error("Not implemented: FetchWasm");
|
||||||
|
}
|
||||||
|
if (this.destroyed) {
|
||||||
|
throw new Error("Worker was destroyed.");
|
||||||
|
}
|
||||||
|
if (!this.wasmFactory) {
|
||||||
|
throw new Error(
|
||||||
|
"WasmFactory not initialized, see the `useWorkerFetch` parameter."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.wasmFactory.fetch(data);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getData() {
|
getData() {
|
||||||
|
@ -3501,6 +3540,7 @@ export {
|
||||||
DefaultCMapReaderFactory,
|
DefaultCMapReaderFactory,
|
||||||
DefaultFilterFactory,
|
DefaultFilterFactory,
|
||||||
DefaultStandardFontDataFactory,
|
DefaultStandardFontDataFactory,
|
||||||
|
DefaultWasmFactory,
|
||||||
getDocument,
|
getDocument,
|
||||||
LoopbackPort,
|
LoopbackPort,
|
||||||
PDFDataRangeTransport,
|
PDFDataRangeTransport,
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { BaseCanvasFactory } from "./canvas_factory.js";
|
||||||
import { BaseCMapReaderFactory } from "./cmap_reader_factory.js";
|
import { BaseCMapReaderFactory } from "./cmap_reader_factory.js";
|
||||||
import { BaseFilterFactory } from "./filter_factory.js";
|
import { BaseFilterFactory } from "./filter_factory.js";
|
||||||
import { BaseStandardFontDataFactory } from "./standard_fontdata_factory.js";
|
import { BaseStandardFontDataFactory } from "./standard_fontdata_factory.js";
|
||||||
|
import { BaseWasmFactory } from "./wasm_factory.js";
|
||||||
|
|
||||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -108,10 +109,20 @@ class NodeStandardFontDataFactory extends BaseStandardFontDataFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NodeWasmFactory extends BaseWasmFactory {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
async _fetch(url) {
|
||||||
|
return fetchData(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
fetchData,
|
fetchData,
|
||||||
NodeCanvasFactory,
|
NodeCanvasFactory,
|
||||||
NodeCMapReaderFactory,
|
NodeCMapReaderFactory,
|
||||||
NodeFilterFactory,
|
NodeFilterFactory,
|
||||||
NodeStandardFontDataFactory,
|
NodeStandardFontDataFactory,
|
||||||
|
NodeWasmFactory,
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,10 +14,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const DOMCMapReaderFactory = null;
|
const DOMCMapReaderFactory = null;
|
||||||
|
const DOMWasmFactory = null;
|
||||||
const DOMStandardFontDataFactory = null;
|
const DOMStandardFontDataFactory = null;
|
||||||
const NodeCanvasFactory = null;
|
const NodeCanvasFactory = null;
|
||||||
const NodeCMapReaderFactory = null;
|
const NodeCMapReaderFactory = null;
|
||||||
const NodeFilterFactory = null;
|
const NodeFilterFactory = null;
|
||||||
|
const NodeWasmFactory = null;
|
||||||
const NodeStandardFontDataFactory = null;
|
const NodeStandardFontDataFactory = null;
|
||||||
const PDFFetchStream = null;
|
const PDFFetchStream = null;
|
||||||
const PDFNetworkStream = null;
|
const PDFNetworkStream = null;
|
||||||
|
@ -26,10 +28,12 @@ const PDFNodeStream = null;
|
||||||
export {
|
export {
|
||||||
DOMCMapReaderFactory,
|
DOMCMapReaderFactory,
|
||||||
DOMStandardFontDataFactory,
|
DOMStandardFontDataFactory,
|
||||||
|
DOMWasmFactory,
|
||||||
NodeCanvasFactory,
|
NodeCanvasFactory,
|
||||||
NodeCMapReaderFactory,
|
NodeCMapReaderFactory,
|
||||||
NodeFilterFactory,
|
NodeFilterFactory,
|
||||||
NodeStandardFontDataFactory,
|
NodeStandardFontDataFactory,
|
||||||
|
NodeWasmFactory,
|
||||||
PDFFetchStream,
|
PDFFetchStream,
|
||||||
PDFNetworkStream,
|
PDFNetworkStream,
|
||||||
PDFNodeStream,
|
PDFNodeStream,
|
||||||
|
|
63
src/display/wasm_factory.js
Normal file
63
src/display/wasm_factory.js
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/* Copyright 2015 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { fetchData } from "./display_utils.js";
|
||||||
|
import { unreachable } from "../shared/util.js";
|
||||||
|
|
||||||
|
class BaseWasmFactory {
|
||||||
|
constructor({ baseUrl = null }) {
|
||||||
|
if (
|
||||||
|
(typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) &&
|
||||||
|
this.constructor === BaseWasmFactory
|
||||||
|
) {
|
||||||
|
unreachable("Cannot initialize BaseWasmFactory.");
|
||||||
|
}
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetch({ filename }) {
|
||||||
|
if (!this.baseUrl) {
|
||||||
|
throw new Error("Ensure that the `wasmUrl` API parameter is provided.");
|
||||||
|
}
|
||||||
|
if (!filename) {
|
||||||
|
throw new Error("Wasm filename must be specified.");
|
||||||
|
}
|
||||||
|
const url = `${this.baseUrl}${filename}`;
|
||||||
|
|
||||||
|
return this._fetch(url).catch(reason => {
|
||||||
|
throw new Error(`Unable to load wasm data at: ${url}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
* @returns {Promise<Uint8Array>}
|
||||||
|
*/
|
||||||
|
async _fetch(url) {
|
||||||
|
unreachable("Abstract method `_fetch` called.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DOMWasmFactory extends BaseWasmFactory {
|
||||||
|
/**
|
||||||
|
* @ignore
|
||||||
|
*/
|
||||||
|
async _fetch(url) {
|
||||||
|
const data = await fetchData(url, /* type = */ "arraybuffer");
|
||||||
|
return new Uint8Array(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { BaseWasmFactory, DOMWasmFactory };
|
|
@ -31,6 +31,7 @@ const { GenericL10n, parseQueryString, SimpleLinkService } = pdfjsViewer;
|
||||||
const WAITING_TIME = 100; // ms
|
const WAITING_TIME = 100; // ms
|
||||||
const CMAP_URL = "/build/generic/web/cmaps/";
|
const CMAP_URL = "/build/generic/web/cmaps/";
|
||||||
const STANDARD_FONT_DATA_URL = "/build/generic/web/standard_fonts/";
|
const STANDARD_FONT_DATA_URL = "/build/generic/web/standard_fonts/";
|
||||||
|
const WASM_URL = "/build/generic/web/wasm/";
|
||||||
const IMAGE_RESOURCES_PATH = "/web/images/";
|
const IMAGE_RESOURCES_PATH = "/web/images/";
|
||||||
const VIEWER_CSS = "../build/components/pdf_viewer.css";
|
const VIEWER_CSS = "../build/components/pdf_viewer.css";
|
||||||
const VIEWER_LOCALE = "en-US";
|
const VIEWER_LOCALE = "en-US";
|
||||||
|
@ -631,6 +632,7 @@ class Driver {
|
||||||
password: task.password,
|
password: task.password,
|
||||||
cMapUrl: CMAP_URL,
|
cMapUrl: CMAP_URL,
|
||||||
standardFontDataUrl: STANDARD_FONT_DATA_URL,
|
standardFontDataUrl: STANDARD_FONT_DATA_URL,
|
||||||
|
wasmUrl: WASM_URL,
|
||||||
disableAutoFetch: !task.enableAutoFetch,
|
disableAutoFetch: !task.enableAutoFetch,
|
||||||
pdfBug: true,
|
pdfBug: true,
|
||||||
useSystemFonts: task.useSystemFonts,
|
useSystemFonts: task.useSystemFonts,
|
||||||
|
|
|
@ -6371,6 +6371,14 @@
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "issue19326_main_thread_fetch",
|
||||||
|
"file": "pdfs/issue19326.pdf",
|
||||||
|
"md5": "b4d937017daf439a6318501428e0c6ba",
|
||||||
|
"rounds": 1,
|
||||||
|
"type": "eq",
|
||||||
|
"useWorkerFetch": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "bug1140761",
|
"id": "bug1140761",
|
||||||
"file": "pdfs/bug1140761.pdf",
|
"file": "pdfs/bug1140761.pdf",
|
||||||
|
|
|
@ -28,6 +28,8 @@ const STANDARD_FONT_DATA_URL = isNodeJS
|
||||||
? "./external/standard_fonts/"
|
? "./external/standard_fonts/"
|
||||||
: "../../external/standard_fonts/";
|
: "../../external/standard_fonts/";
|
||||||
|
|
||||||
|
const WASM_URL = isNodeJS ? "./external/openjpeg/" : "../../external/openjpeg/";
|
||||||
|
|
||||||
class DefaultFileReaderFactory {
|
class DefaultFileReaderFactory {
|
||||||
static async fetch(params) {
|
static async fetch(params) {
|
||||||
if (isNodeJS) {
|
if (isNodeJS) {
|
||||||
|
@ -44,6 +46,7 @@ function buildGetDocumentParams(filename, options) {
|
||||||
? TEST_PDFS_PATH + filename
|
? TEST_PDFS_PATH + filename
|
||||||
: new URL(TEST_PDFS_PATH + filename, window.location).href;
|
: new URL(TEST_PDFS_PATH + filename, window.location).href;
|
||||||
params.standardFontDataUrl = STANDARD_FONT_DATA_URL;
|
params.standardFontDataUrl = STANDARD_FONT_DATA_URL;
|
||||||
|
params.wasmUrl = WASM_URL;
|
||||||
|
|
||||||
for (const option in options) {
|
for (const option in options) {
|
||||||
params[option] = options[option];
|
params[option] = options[option];
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
"display-cmap_reader_factory": "../../src/display/cmap_reader_factory.js",
|
"display-cmap_reader_factory": "../../src/display/cmap_reader_factory.js",
|
||||||
"display-standard_fontdata_factory": "../../src/display/standard_fontdata_factory.js",
|
"display-standard_fontdata_factory": "../../src/display/standard_fontdata_factory.js",
|
||||||
|
"display-wasm_factory": "../../src/display/wasm_factory.js",
|
||||||
"display-fetch_stream": "../../src/display/fetch_stream.js",
|
"display-fetch_stream": "../../src/display/fetch_stream.js",
|
||||||
"display-network": "../../src/display/network.js",
|
"display-network": "../../src/display/network.js",
|
||||||
"display-node_stream": "../../src/display/stubs.js",
|
"display-node_stream": "../../src/display/stubs.js",
|
||||||
|
|
|
@ -38,6 +38,7 @@ const MIME_TYPES = {
|
||||||
".log": "text/plain",
|
".log": "text/plain",
|
||||||
".bcmap": "application/octet-stream",
|
".bcmap": "application/octet-stream",
|
||||||
".ftl": "text/plain",
|
".ftl": "text/plain",
|
||||||
|
".wasm": "application/wasm",
|
||||||
};
|
};
|
||||||
const DEFAULT_MIME_TYPE = "application/octet-stream";
|
const DEFAULT_MIME_TYPE = "application/octet-stream";
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"display-standard_fontdata_factory": [
|
"display-standard_fontdata_factory": [
|
||||||
"./src/display/standard_fontdata_factory"
|
"./src/display/standard_fontdata_factory"
|
||||||
],
|
],
|
||||||
|
"display-wasm_factory": ["./src/display/wasm_factory"],
|
||||||
"display-fetch_stream": ["./src/display/fetch_stream"],
|
"display-fetch_stream": ["./src/display/fetch_stream"],
|
||||||
"display-network": ["./src/display/network"],
|
"display-network": ["./src/display/network"],
|
||||||
"display-node_stream": ["./src/display/node_stream"],
|
"display-node_stream": ["./src/display/node_stream"],
|
||||||
|
|
|
@ -431,7 +431,17 @@ const defaultOptions = {
|
||||||
value: 1,
|
value: 1,
|
||||||
kind: OptionKind.API,
|
kind: OptionKind.API,
|
||||||
},
|
},
|
||||||
|
wasmUrl: {
|
||||||
|
/** @type {string} */
|
||||||
|
value:
|
||||||
|
// eslint-disable-next-line no-nested-ternary
|
||||||
|
typeof PDFJSDev === "undefined"
|
||||||
|
? "../external/openjpeg/"
|
||||||
|
: PDFJSDev.test("MOZCENTRAL")
|
||||||
|
? "resource://pdf.js/web/wasm/"
|
||||||
|
: "../web/wasm/",
|
||||||
|
kind: OptionKind.API,
|
||||||
|
},
|
||||||
workerPort: {
|
workerPort: {
|
||||||
/** @type {Object} */
|
/** @type {Object} */
|
||||||
value: null,
|
value: null,
|
||||||
|
|
|
@ -61,6 +61,7 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||||
|
|
||||||
"display-cmap_reader_factory": "../src/display/cmap_reader_factory.js",
|
"display-cmap_reader_factory": "../src/display/cmap_reader_factory.js",
|
||||||
"display-standard_fontdata_factory": "../src/display/standard_fontdata_factory.js",
|
"display-standard_fontdata_factory": "../src/display/standard_fontdata_factory.js",
|
||||||
|
"display-wasm_factory": "../src/display/wasm_factory.js",
|
||||||
"display-fetch_stream": "../src/display/fetch_stream.js",
|
"display-fetch_stream": "../src/display/fetch_stream.js",
|
||||||
"display-network": "../src/display/network.js",
|
"display-network": "../src/display/network.js",
|
||||||
"display-node_stream": "../src/display/stubs.js",
|
"display-node_stream": "../src/display/stubs.js",
|
||||||
|
|
|
@ -64,6 +64,7 @@ See https://github.com/adobe-type-tools/cmap-resources
|
||||||
|
|
||||||
"display-cmap_reader_factory": "../src/display/cmap_reader_factory.js",
|
"display-cmap_reader_factory": "../src/display/cmap_reader_factory.js",
|
||||||
"display-standard_fontdata_factory": "../src/display/standard_fontdata_factory.js",
|
"display-standard_fontdata_factory": "../src/display/standard_fontdata_factory.js",
|
||||||
|
"display-wasm_factory": "../src/display/wasm_factory.js",
|
||||||
"display-fetch_stream": "../src/display/fetch_stream.js",
|
"display-fetch_stream": "../src/display/fetch_stream.js",
|
||||||
"display-network": "../src/display/network.js",
|
"display-network": "../src/display/network.js",
|
||||||
"display-node_stream": "../src/display/stubs.js",
|
"display-node_stream": "../src/display/stubs.js",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue