1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-22 16:18:08 +02:00

Merge pull request #11601 from Snuffleupagus/rm-nativeImageDecoderSupport

[api-minor] Decode all JPEG images with the built-in PDF.js decoder in `src/core/jpg.js`
This commit is contained in:
Tim van der Meij 2020-05-23 15:33:46 +02:00 committed by GitHub
commit 3b615e4ca3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 57 additions and 682 deletions

View file

@ -25,7 +25,6 @@ import {
isArrayEqual,
isNum,
isString,
NativeImageDecoding,
OPS,
stringToPDFString,
TextRenderingMode,
@ -80,18 +79,14 @@ import { DecodeStream } from "./stream.js";
import { getGlyphsUnicode } from "./glyphlist.js";
import { getMetrics } from "./metrics.js";
import { isPDFFunction } from "./function.js";
import { JpegStream } from "./jpeg_stream.js";
import { MurmurHash3_64 } from "./murmurhash3.js";
import { NativeImageDecoder } from "./image_utils.js";
import { OperatorList } from "./operator_list.js";
import { PDFImage } from "./image.js";
var PartialEvaluator = (function PartialEvaluatorClosure() {
const DefaultPartialEvaluatorOptions = {
forceDataSchema: false,
maxImageSize: -1,
disableFontFace: false,
nativeImageDecoderSupport: NativeImageDecoding.DECODE,
ignoreErrors: false,
isEvalSupported: true,
fontExtraProperties: false,
@ -450,7 +445,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
operatorList,
cacheKey,
imageCache,
forceDisableNativeImageDecoder = false,
}) {
var dict = image.dict;
const imageRef = dict.objId;
@ -510,13 +504,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var SMALL_IMAGE_DIMENSIONS = 200;
// Inlining small images into the queue as RGB data
if (
isInline &&
!softMask &&
!mask &&
!(image instanceof JpegStream) &&
w + h < SMALL_IMAGE_DIMENSIONS
) {
if (isInline && !softMask && !mask && w + h < SMALL_IMAGE_DIMENSIONS) {
const imageObj = new PDFImage({
xref: this.xref,
res: resources,
@ -531,20 +519,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return undefined;
}
let nativeImageDecoderSupport = forceDisableNativeImageDecoder
? NativeImageDecoding.NONE
: this.options.nativeImageDecoderSupport;
// If there is no imageMask, create the PDFImage and a lot
// of image processing can be done here.
let objId = `img_${this.idFactory.createObjId()}`,
cacheGlobally = false;
if (this.parsingType3Font) {
assert(
nativeImageDecoderSupport === NativeImageDecoding.NONE,
"Type3 image resources should be completely decoded in the worker."
);
objId = `${this.idFactory.getDocId()}_type3res_${objId}`;
} else if (imageRef) {
cacheGlobally = this.globalImageCache.shouldCache(
@ -553,102 +533,19 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
);
if (cacheGlobally) {
// Ensure that the image is *completely* decoded on the worker-thread,
// in order to simplify the caching/rendering code on the main-thread.
nativeImageDecoderSupport = NativeImageDecoding.NONE;
objId = `${this.idFactory.getDocId()}_${objId}`;
}
}
if (
nativeImageDecoderSupport !== NativeImageDecoding.NONE &&
!softMask &&
!mask &&
image instanceof JpegStream &&
image.maybeValidDimensions &&
NativeImageDecoder.isSupported(
image,
this.xref,
resources,
this.pdfFunctionFactory
)
) {
// These JPEGs don't need any more processing so we can just send it.
return this.handler
.sendWithPromise("obj", [
objId,
this.pageIndex,
"JpegStream",
image.getIR(this.options.forceDataSchema),
])
.then(
() => {
// Only add the dependency once we know that the native JPEG
// decoding succeeded, to ensure that rendering will always
// complete.
operatorList.addDependency(objId);
args = [objId, w, h];
operatorList.addOp(OPS.paintJpegXObject, args);
if (cacheKey) {
imageCache[cacheKey] = {
fn: OPS.paintJpegXObject,
args,
};
if (imageRef) {
this.globalImageCache.addPageIndex(imageRef, this.pageIndex);
}
}
},
reason => {
warn(
"Native JPEG decoding failed -- trying to recover: " +
(reason && reason.message)
);
// Try to decode the JPEG image with the built-in decoder instead.
return this.buildPaintImageXObject({
resources,
image,
isInline,
operatorList,
cacheKey,
imageCache,
forceDisableNativeImageDecoder: true,
});
}
);
}
// Creates native image decoder only if a JPEG image or mask is present.
var nativeImageDecoder = null;
if (
nativeImageDecoderSupport === NativeImageDecoding.DECODE &&
(image instanceof JpegStream ||
mask instanceof JpegStream ||
softMask instanceof JpegStream)
) {
nativeImageDecoder = new NativeImageDecoder({
xref: this.xref,
resources,
handler: this.handler,
forceDataSchema: this.options.forceDataSchema,
pdfFunctionFactory: this.pdfFunctionFactory,
});
}
// Ensure that the dependency is added before the image is decoded.
operatorList.addDependency(objId);
args = [objId, w, h];
const imgPromise = PDFImage.buildImage({
handler: this.handler,
xref: this.xref,
res: resources,
image,
isInline,
nativeDecoder: nativeImageDecoder,
pdfFunctionFactory: this.pdfFunctionFactory,
})
.then(imageObj => {
@ -3393,7 +3290,6 @@ class TranslatedFont {
// the rendering code on the main-thread (see issue10717.pdf).
var type3Options = Object.create(evaluator.options);
type3Options.ignoreErrors = false;
type3Options.nativeImageDecoderSupport = NativeImageDecoding.NONE;
var type3Evaluator = evaluator.clone(type3Options);
type3Evaluator.parsingType3Font = true;

View file

@ -21,23 +21,6 @@ import { JpegStream } from "./jpeg_stream.js";
import { JpxImage } from "./jpx.js";
var PDFImage = (function PDFImageClosure() {
/**
* Decodes the image using native decoder if possible. Resolves the promise
* when the image data is ready.
*/
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 image;
});
}
return Promise.resolve(image);
}
/**
* Decode and clamp a value. The formula is different from the spec because we
* don't decode to float range [0,1], we decode it in the [0,max] range.
@ -266,51 +249,38 @@ var PDFImage = (function PDFImageClosure() {
* with a PDFImage when the image is ready to be used.
*/
PDFImage.buildImage = function ({
handler,
xref,
res,
image,
isInline = false,
nativeDecoder = null,
pdfFunctionFactory,
}) {
var imagePromise = handleImageData(image, nativeDecoder);
var smaskPromise;
var maskPromise;
const imageData = image;
let smaskData = null;
let maskData = null;
var smask = image.dict.get("SMask");
var mask = image.dict.get("Mask");
const smask = image.dict.get("SMask");
const mask = image.dict.get("Mask");
if (smask) {
smaskPromise = handleImageData(smask, nativeDecoder);
maskPromise = Promise.resolve(null);
} else {
smaskPromise = Promise.resolve(null);
if (mask) {
if (isStream(mask)) {
maskPromise = handleImageData(mask, nativeDecoder);
} else if (Array.isArray(mask)) {
maskPromise = Promise.resolve(mask);
} else {
warn("Unsupported mask format.");
maskPromise = Promise.resolve(null);
}
smaskData = smask;
} else if (mask) {
if (isStream(mask) || Array.isArray(mask)) {
maskData = mask;
} else {
maskPromise = Promise.resolve(null);
warn("Unsupported mask format.");
}
}
return Promise.all([imagePromise, smaskPromise, maskPromise]).then(
function ([imageData, smaskData, maskData]) {
return new PDFImage({
xref,
res,
image: imageData,
isInline,
smask: smaskData,
mask: maskData,
pdfFunctionFactory,
});
}
return Promise.resolve(
new PDFImage({
xref,
res,
image: imageData,
isInline,
smask: smaskData,
mask: maskData,
pdfFunctionFactory,
})
);
};

View file

@ -15,103 +15,7 @@
/* eslint no-var: error */
import { assert, info, shadow } from "../shared/util.js";
import { ColorSpace } from "./colorspace.js";
import { JpegStream } from "./jpeg_stream.js";
import { RefSetCache } from "./primitives.js";
import { Stream } from "./stream.js";
class NativeImageDecoder {
constructor({
xref,
resources,
handler,
forceDataSchema = false,
pdfFunctionFactory,
}) {
this.xref = xref;
this.resources = resources;
this.handler = handler;
this.forceDataSchema = forceDataSchema;
this.pdfFunctionFactory = pdfFunctionFactory;
}
canDecode(image) {
return (
image instanceof JpegStream &&
image.maybeValidDimensions &&
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
);
return this.handler
.sendWithPromise("JpegDecode", [
image.getIR(this.forceDataSchema),
colorSpace.numComps,
])
.then(function ({ data, width, height }) {
return new Stream(data, 0, data.length, dict);
});
}
/**
* Checks if the image can be decoded and displayed by the browser without any
* further processing such as color space conversions.
*/
static isSupported(image, xref, res, pdfFunctionFactory) {
const dict = image.dict;
if (dict.has("DecodeParms") || dict.has("DP")) {
return false;
}
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"))
);
}
/**
* Checks if the image can be decoded by the browser.
*/
static isDecodable(image, xref, res, pdfFunctionFactory) {
const dict = image.dict;
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)
);
}
}
class GlobalImageCache {
static get NUM_PAGES_THRESHOLD() {
@ -207,4 +111,4 @@ class GlobalImageCache {
}
}
export { NativeImageDecoder, GlobalImageCache };
export { GlobalImageCache };

View file

@ -13,17 +13,14 @@
* limitations under the License.
*/
import { createObjectURL, shadow } from "../shared/util.js";
import { DecodeStream } from "./stream.js";
import { isDict } from "./primitives.js";
import { JpegImage } from "./jpg.js";
import { shadow } from "../shared/util.js";
/**
* Depending on the type of JPEG a JpegStream is handled in different ways. For
* JPEG's that are supported natively such as DeviceGray and DeviceRGB the image
* data is stored and then loaded by the browser. For unsupported JPEG's we use
* a library to decode these images and the stream behaves like all the other
* DecodeStreams.
* For JPEG's we use a library to decode these images and the stream behaves
* like all the other DecodeStreams.
*/
const JpegStream = (function JpegStreamClosure() {
// eslint-disable-next-line no-shadow
@ -110,150 +107,6 @@ const JpegStream = (function JpegStreamClosure() {
this.eof = true;
};
Object.defineProperty(JpegStream.prototype, "maybeValidDimensions", {
get: function JpegStream_maybeValidDimensions() {
const { dict, stream } = this;
const dictHeight = dict.get("Height", "H");
const startPos = stream.pos;
let validDimensions = true,
foundSOF = false,
b;
while ((b = stream.getByte()) !== -1) {
if (b !== 0xff) {
// Not a valid marker.
continue;
}
switch (stream.getByte()) {
case 0xc0: // SOF0
case 0xc1: // SOF1
case 0xc2: // SOF2
// These three SOF{n} markers are the only ones that the built-in
// PDF.js JPEG decoder currently supports.
foundSOF = true;
stream.pos += 2; // Skip marker length.
stream.pos += 1; // Skip precision.
const scanLines = stream.getUint16();
const samplesPerLine = stream.getUint16();
// Letting the browser handle the JPEG decoding, on the main-thread,
// will cause a *large* increase in peak memory usage since there's
// a handful of short-lived copies of the image data. For very big
// JPEG images, always let the PDF.js image decoder handle them to
// reduce overall memory usage during decoding (see issue 11694).
if (scanLines * samplesPerLine > 1e6) {
validDimensions = false;
break;
}
// The "normal" case, where the image data and dictionary agrees.
if (scanLines === dictHeight) {
break;
}
// A DNL (Define Number of Lines) marker is expected,
// which browsers (usually) cannot decode natively.
if (scanLines === 0) {
validDimensions = false;
break;
}
// The dimensions of the image, among other properties, should
// always be taken from the image data *itself* rather than the
// XObject dictionary. However there's cases of corrupt images that
// browsers cannot decode natively, for example:
// - JPEG images with DNL markers, where the SOF `scanLines`
// parameter has an unexpected value (see issue 8614).
// - JPEG images with too large SOF `scanLines` parameter, where
// the EOI marker is encountered prematurely (see issue 10880).
// In an attempt to handle these kinds of corrupt images, compare
// the dimensions in the image data with the dictionary and *always*
// let the PDF.js JPEG decoder (rather than the browser) handle the
// image if the difference is larger than one order of magnitude
// (since that would generally suggest that something is off).
if (scanLines > dictHeight * 10) {
validDimensions = false;
break;
}
break;
case 0xc3: // SOF3
/* falls through */
case 0xc5: // SOF5
case 0xc6: // SOF6
case 0xc7: // SOF7
/* falls through */
case 0xc9: // SOF9
case 0xca: // SOF10
case 0xcb: // SOF11
/* falls through */
case 0xcd: // SOF13
case 0xce: // SOF14
case 0xcf: // SOF15
foundSOF = true;
break;
case 0xc4: // DHT
case 0xcc: // DAC
/* falls through */
case 0xda: // SOS
case 0xdb: // DQT
case 0xdc: // DNL
case 0xdd: // DRI
case 0xde: // DHP
case 0xdf: // EXP
/* falls through */
case 0xe0: // APP0
case 0xe1: // APP1
case 0xe2: // APP2
case 0xe3: // APP3
case 0xe4: // APP4
case 0xe5: // APP5
case 0xe6: // APP6
case 0xe7: // APP7
case 0xe8: // APP8
case 0xe9: // APP9
case 0xea: // APP10
case 0xeb: // APP11
case 0xec: // APP12
case 0xed: // APP13
case 0xee: // APP14
case 0xef: // APP15
/* falls through */
case 0xfe: // COM
const markerLength = stream.getUint16();
if (markerLength > 2) {
stream.skip(markerLength - 2); // Jump to the next marker.
} else {
// The marker length is invalid, resetting the stream position.
stream.skip(-2);
}
break;
case 0xff: // Fill byte.
// Avoid skipping a valid marker, resetting the stream position.
stream.skip(-1);
break;
case 0xd9: // EOI
foundSOF = true;
break;
}
if (foundSOF) {
break;
}
}
// Finally, don't forget to reset the stream position.
stream.pos = startPos;
return shadow(this, "maybeValidDimensions", validDimensions);
},
configurable: true,
});
JpegStream.prototype.getIR = function (forceDataSchema = false) {
return createObjectURL(this.bytes, "image/jpeg", forceDataSchema);
};
return JpegStream;
})();

View file

@ -399,10 +399,8 @@ var WorkerMessageHandler = {
ensureNotTerminated();
var evaluatorOptions = {
forceDataSchema: data.disableCreateObjectURL,
maxImageSize: data.maxImageSize,
disableFontFace: data.disableFontFace,
nativeImageDecoderSupport: data.nativeImageDecoderSupport,
ignoreErrors: data.ignoreErrors,
isEvalSupported: data.isEvalSupported,
fontExtraProperties: data.fontExtraProperties,

View file

@ -28,7 +28,6 @@ import {
isArrayBuffer,
isSameOrigin,
MissingPDFException,
NativeImageDecoding,
PasswordException,
setVerbosityLevel,
shadow,
@ -44,7 +43,6 @@ import {
DOMCMapReaderFactory,
loadScript,
PageViewport,
releaseImageResources,
RenderingCancelledException,
StatTimer,
} from "./display_utils.js";
@ -116,14 +114,6 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) {
* @property {string} [docBaseUrl] - The base URL of the document,
* used when attempting to recover valid absolute URLs for annotations, and
* outline items, that (incorrectly) only specify relative URLs.
* @property {string} [nativeImageDecoderSupport] - Strategy for
* decoding certain (simple) JPEG images in the browser. This is useful for
* environments without DOM image and canvas support, such as e.g. Node.js.
* Valid values are 'decode', 'display' or 'none'; where 'decode' is intended
* for browsers with full image/canvas support, 'display' for environments
* with limited image support through stubs (useful for SVG conversion),
* and 'none' where JPEG images will be decoded entirely by PDF.js.
* The default value is 'decode'.
* @property {string} [cMapUrl] - The URL where the predefined
* Adobe CMaps are located. Include trailing slash.
* @property {boolean} [cMapPacked] - Specifies if the Adobe CMaps are
@ -164,9 +154,6 @@ function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) {
* The default value is `false`.
* NOTE: It is also necessary to disable streaming, see above,
* in order for disabling of pre-fetching to work correctly.
* @property {boolean} [disableCreateObjectURL] - Disable the use of
* `URL.createObjectURL`, for compatibility with older browsers.
* The default value is `false`.
* @property {boolean} [pdfBug] - Enables special hooks for debugging
* PDF.js (see `web/debugger.js`). The default value is `false`.
*/
@ -260,15 +247,6 @@ function getDocument(src) {
params.fontExtraProperties = params.fontExtraProperties === true;
params.pdfBug = params.pdfBug === true;
const NativeImageDecoderValues = Object.values(NativeImageDecoding);
if (
params.nativeImageDecoderSupport === undefined ||
!NativeImageDecoderValues.includes(params.nativeImageDecoderSupport)
) {
params.nativeImageDecoderSupport =
apiCompatibilityParams.nativeImageDecoderSupport ||
NativeImageDecoding.DECODE;
}
if (!Number.isInteger(params.maxImageSize)) {
params.maxImageSize = -1;
}
@ -288,10 +266,6 @@ function getDocument(src) {
if (typeof params.disableAutoFetch !== "boolean") {
params.disableAutoFetch = false;
}
if (typeof params.disableCreateObjectURL !== "boolean") {
params.disableCreateObjectURL =
apiCompatibilityParams.disableCreateObjectURL || false;
}
// Set the main-thread verbosity level.
setVerbosityLevel(params.verbosity);
@ -414,10 +388,8 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
},
maxImageSize: source.maxImageSize,
disableFontFace: source.disableFontFace,
disableCreateObjectURL: source.disableCreateObjectURL,
postMessageTransfers: worker.postMessageTransfers,
docBaseUrl: source.docBaseUrl,
nativeImageDecoderSupport: source.nativeImageDecoderSupport,
ignoreErrors: source.ignoreErrors,
isEvalSupported: source.isEvalSupported,
fontExtraProperties: source.fontExtraProperties,
@ -2309,26 +2281,6 @@ class WorkerTransport {
}
switch (type) {
case "JpegStream":
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = function () {
resolve(img);
};
img.onerror = function () {
// Note that when the browser image loading/decoding fails,
// we'll fallback to the built-in PDF.js JPEG decoder; see
// `PartialEvaluator.buildPaintImageXObject` in the
// `src/core/evaluator.js` file.
reject(new Error("Error during JPEG image loading"));
// Always remember to release the image data if errors occurred.
releaseImageResources(img);
};
img.src = imageData;
}).then(img => {
pageProxy.objs.resolve(id, img);
});
case "Image":
pageProxy.objs.resolve(id, imageData);
@ -2366,69 +2318,6 @@ class WorkerTransport {
this._onUnsupportedFeature.bind(this)
);
messageHandler.on("JpegDecode", ([imageUrl, components]) => {
if (this.destroyed) {
return Promise.reject(new Error("Worker was destroyed"));
}
if (typeof document === "undefined") {
// Make sure that this code is not executing in node.js, as
// it's using DOM image, and there is no library to support that.
return Promise.reject(new Error('"document" is not defined.'));
}
if (components !== 3 && components !== 1) {
return Promise.reject(
new Error("Only 3 components or 1 component can be returned")
);
}
return new Promise(function (resolve, reject) {
const img = new Image();
img.onload = function () {
const { width, height } = img;
const size = width * height;
const rgbaLength = size * 4;
const buf = new Uint8ClampedArray(size * components);
let tmpCanvas = document.createElement("canvas");
tmpCanvas.width = width;
tmpCanvas.height = height;
let tmpCtx = tmpCanvas.getContext("2d");
tmpCtx.drawImage(img, 0, 0);
const data = tmpCtx.getImageData(0, 0, width, height).data;
if (components === 3) {
for (let i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
buf[j] = data[i];
buf[j + 1] = data[i + 1];
buf[j + 2] = data[i + 2];
}
} else if (components === 1) {
for (let i = 0, j = 0; i < rgbaLength; i += 4, j++) {
buf[j] = data[i];
}
}
resolve({ data: buf, width, height });
// Immediately release the image data once decoding has finished.
releaseImageResources(img);
// Zeroing the width and height cause Firefox to release graphics
// resources immediately, which can greatly reduce memory consumption.
tmpCanvas.width = 0;
tmpCanvas.height = 0;
tmpCanvas = null;
tmpCtx = null;
};
img.onerror = function () {
reject(new Error("JpegDecode failed to load image"));
// Always remember to release the image data if errors occurred.
releaseImageResources(img);
};
img.src = imageUrl;
});
});
messageHandler.on("FetchBuiltInCMap", (data, sink) => {
if (this.destroyed) {
sink.error(new Error("Worker was destroyed"));
@ -2608,9 +2497,7 @@ class WorkerTransport {
const params = this._params;
return shadow(this, "loadingParams", {
disableAutoFetch: params.disableAutoFetch,
disableCreateObjectURL: params.disableCreateObjectURL,
disableFontFace: params.disableFontFace,
nativeImageDecoderSupport: params.nativeImageDecoderSupport,
});
}
}
@ -2684,14 +2571,6 @@ class PDFObjects {
}
clear() {
for (const objId in this._objs) {
const { data } = this._objs[objId];
if (typeof Image !== "undefined" && data instanceof Image) {
// Always release the image data when clearing out the cached objects.
releaseImageResources(data);
}
}
this._objs = Object.create(null);
}
}

View file

@ -17,27 +17,11 @@ import { isNodeJS } from "../shared/is_node.js";
const compatibilityParams = Object.create(null);
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
const userAgent =
(typeof navigator !== "undefined" && navigator.userAgent) || "";
const isIE = /Trident/.test(userAgent);
const isIOSChrome = /CriOS/.test(userAgent);
// Checks if possible to use URL.createObjectURL()
// Support: IE, Chrome on iOS
(function checkOnBlobSupport() {
// Sometimes IE and Chrome on iOS losing the data created with
// createObjectURL(), see issues #3977 and #8081.
if (isIE || isIOSChrome) {
compatibilityParams.disableCreateObjectURL = true;
}
})();
// Support: Node.js
(function checkFontFaceAndImage() {
// Node.js is missing native support for `@font-face` and `Image`.
(function checkFontFace() {
// Node.js is missing native support for `@font-face`.
if (isNodeJS) {
compatibilityParams.disableFontFace = true;
compatibilityParams.nativeImageDecoderSupport = "none";
}
})();
}

View file

@ -2113,46 +2113,6 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
this.restore();
},
paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
const domImage = objId.startsWith("g_")
? this.commonObjs.get(objId)
: this.objs.get(objId);
if (!domImage) {
warn("Dependent image isn't ready yet");
return;
}
this.save();
var ctx = this.ctx;
// scale the image to the unit square
ctx.scale(1 / w, -1 / h);
ctx.drawImage(
domImage,
0,
0,
domImage.width,
domImage.height,
0,
-h,
w,
h
);
if (this.imageLayer) {
var currentTransform = ctx.mozCurrentTransformInverse;
var position = this.getCanvasPosition(0, 0);
this.imageLayer.appendImage({
objId,
left: position[0],
top: position[1],
width: w / currentTransform[0],
height: h / currentTransform[3],
});
}
this.restore();
},
paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) {
var ctx = this.ctx;
var width = img.width,
@ -2353,9 +2313,9 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
var paintWidth = width,
paintHeight = height;
var tmpCanvasId = "prescale1";
// Vertial or horizontal scaling shall not be more than 2 to not loose the
// Vertical or horizontal scaling shall not be more than 2 to not lose the
// pixels during drawImage operation, painting on the temporary canvas(es)
// that are twice smaller in size
// that are twice smaller in size.
while (
(widthScale > 2 && paintWidth > 1) ||
(heightScale > 2 && paintHeight > 1)

View file

@ -517,20 +517,6 @@ function deprecated(details) {
console.log("Deprecated API usage: " + details);
}
function releaseImageResources(img) {
assert(img instanceof Image, "Invalid `img` parameter.");
const url = img.src;
if (
typeof url === "string" &&
url.startsWith("blob:") &&
URL.revokeObjectURL
) {
URL.revokeObjectURL(url);
}
img.removeAttribute("src");
}
let pdfDateStringRegex;
class PDFDateString {
@ -631,6 +617,5 @@ export {
isValidFetchUrl,
loadScript,
deprecated,
releaseImageResources,
PDFDateString,
};

View file

@ -440,7 +440,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
// eslint-disable-next-line no-shadow
SVGGraphics = class SVGGraphics {
constructor(commonObjs, objs, forceDataSchema) {
constructor(commonObjs, objs, forceDataSchema = false) {
this.svgFactory = new DOMSVGFactory();
this.current = new SVGExtraState();
@ -664,9 +664,6 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
case OPS.paintSolidColorImageMask:
this.paintSolidColorImageMask();
break;
case OPS.paintJpegXObject:
this.paintJpegXObject(args[0], args[1], args[2]);
break;
case OPS.paintImageXObject:
this.paintImageXObject(args[0]);
break;
@ -1559,23 +1556,6 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
this._ensureTransformGroup().appendChild(rect);
}
paintJpegXObject(objId, w, h) {
const imgObj = this.objs.get(objId);
const imgEl = this.svgFactory.createElement("svg:image");
imgEl.setAttributeNS(XLINK_NS, "xlink:href", imgObj.src);
imgEl.setAttributeNS(null, "width", pf(w));
imgEl.setAttributeNS(null, "height", pf(h));
imgEl.setAttributeNS(null, "x", "0");
imgEl.setAttributeNS(null, "y", pf(-h));
imgEl.setAttributeNS(
null,
"transform",
`scale(${pf(1 / w)} ${pf(-1 / h)})`
);
this._ensureTransformGroup().appendChild(imgEl);
}
paintImageXObject(objId) {
const imgData = this.objs.get(objId);
if (!imgData) {

View file

@ -39,7 +39,6 @@ import {
createValidAbsoluteUrl,
InvalidPDFException,
MissingPDFException,
NativeImageDecoding,
OPS,
PasswordResponses,
PermissionFlag,
@ -143,7 +142,6 @@ export {
createValidAbsoluteUrl,
InvalidPDFException,
MissingPDFException,
NativeImageDecoding,
OPS,
PasswordResponses,
PermissionFlag,

View file

@ -19,12 +19,6 @@ import "./compatibility.js";
const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
const NativeImageDecoding = {
NONE: "none",
DECODE: "decode",
DISPLAY: "display",
};
// Permission flags from Table 22, Section 7.6.3.2 of the PDF specification.
const PermissionFlag = {
PRINT: 0x04,
@ -917,7 +911,6 @@ export {
AbortException,
InvalidPDFException,
MissingPDFException,
NativeImageDecoding,
PasswordException,
PasswordResponses,
PermissionFlag,