Compare commits

..

No commits in common. "e75a7cfd62a9dc14c5bbcd2808894d4761268d14" and "5873e1cbc082dfe710b7b5d31c8ffad0337d125e" have entirely different histories.

9 changed files with 63 additions and 56 deletions

View File

@ -346,13 +346,13 @@ class ChunkedStreamManager {
const chunksToRequest = []; const chunksToRequest = [];
for (const chunk of chunksNeeded) { for (const chunk of chunksNeeded) {
const requestIds = this._requestsByChunk.getOrInsertComputed( let requestIds = this._requestsByChunk.get(chunk);
chunk, if (!requestIds) {
() => { requestIds = [];
this._requestsByChunk.set(chunk, requestIds);
chunksToRequest.push(chunk); chunksToRequest.push(chunk);
return [];
} }
);
requestIds.push(requestId); requestIds.push(requestId);
} }

View File

@ -37,7 +37,7 @@ import {
RefSetCache, RefSetCache,
} from "../primitives.js"; } from "../primitives.js";
import { incrementalUpdate, writeValue } from "../writer.js"; import { incrementalUpdate, writeValue } from "../writer.js";
import { isArrayEqual, makeArr, stringToBytes } from "../../shared/util.js"; import { isArrayEqual, stringToBytes } from "../../shared/util.js";
import { NameTree, NumberTree } from "../name_number_tree.js"; import { NameTree, NumberTree } from "../name_number_tree.js";
import { stringToAsciiOrUTF16BE, stringToPDFString } from "../string_utils.js"; import { stringToAsciiOrUTF16BE, stringToPDFString } from "../string_utils.js";
import { AnnotationFactory } from "../annotation.js"; import { AnnotationFactory } from "../annotation.js";
@ -514,7 +514,8 @@ class PDFEditor {
const bytes = this.#rawStreamBytes(stream); const bytes = this.#rawStreamBytes(stream);
const key = this.#resourceStreamKey(dictStr, bytes); const key = this.#resourceStreamKey(dictStr, bytes);
const bucket = this.#resourceStreamCache.getOrInsertComputed(key, makeArr); let bucket = this.#resourceStreamCache.get(key);
if (bucket) {
// Same key only means "maybe equal": confirm with an exact comparison. // Same key only means "maybe equal": confirm with an exact comparison.
for (const entry of bucket) { for (const entry of bucket) {
if ( if (
@ -524,6 +525,10 @@ class PDFEditor {
return entry.ref; return entry.ref;
} }
} }
} else {
bucket = [];
this.#resourceStreamCache.set(key, bucket);
}
const ref = this.newRef; const ref = this.newRef;
this.xref[ref.num] = stream; this.xref[ref.num] = stream;
bucket.push({ ref, dictStr, stream }); bucket.push({ ref, dictStr, stream });

View File

@ -128,6 +128,7 @@ class JpegStream extends DecodeStream {
height: this.drawHeight, height: this.drawHeight,
forceRGBA: this.forceRGBA, forceRGBA: this.forceRGBA,
forceRGB: this.forceRGB, forceRGB: this.forceRGB,
isSourcePDF: true,
}); });
this.buffer = data; this.buffer = data;
this.bufferLength = data.length; this.bufferLength = data.length;

View File

@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { BaseException, warn } from "../shared/util.js"; import { assert, BaseException, warn } from "../shared/util.js";
import { ColorSpaceUtils } from "./colorspace_utils.js"; import { ColorSpaceUtils } from "./colorspace_utils.js";
import { DeviceCmykCS } from "./colorspace.js"; import { DeviceCmykCS } from "./colorspace.js";
import { grayToRGBA } from "../shared/image_utils.js"; import { grayToRGBA } from "../shared/image_utils.js";
@ -1203,7 +1203,7 @@ class JpegImage {
return undefined; return undefined;
} }
#getLinearizedBlockData(width, height, isSourcePDF) { _getLinearizedBlockData(width, height, isSourcePDF = false) {
const scaleX = this.width / width, const scaleX = this.width / width,
scaleY = this.height / height; scaleY = this.height / height;
@ -1257,18 +1257,11 @@ class JpegImage {
// //
// Unfortunately it's not (always) possible to tell, from the image data // Unfortunately it's not (always) possible to tell, from the image data
// alone, if it needs to be inverted. Thus in an attempt to provide better // alone, if it needs to be inverted. Thus in an attempt to provide better
// out-of-the-box behaviour when `JpegImage` is used standalone, default to // out-of-box behaviour when `JpegImage` is used standalone, default to
// inverting JPEG (CMYK) images if and only if the image data does *not* // inverting JPEG (CMYK) images if and only if the image data does *not*
// come from a PDF file and no `decodeTransform` was passed by the user. // come from a PDF file and no `decodeTransform` was passed by the user.
if ( if (!isSourcePDF && numComponents === 4 && !transform) {
typeof PDFJSDev !== "undefined" && transform = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]);
PDFJSDev.test("IMAGE_DECODERS") &&
!isSourcePDF &&
numComponents === 4
) {
transform ||= new Int32Array([
-256, 255, -256, 255, -256, 255, -256, 255,
]);
} }
if (transform) { if (transform) {
@ -1315,7 +1308,7 @@ class JpegImage {
_convertYccToRgb(data) { _convertYccToRgb(data) {
let Y, Cb, Cr; let Y, Cb, Cr;
for (let i = 0, ii = data.length; i < ii; i += 3) { for (let i = 0, length = data.length; i < length; i += 3) {
Y = data[i]; Y = data[i];
Cb = data[i + 1]; Cb = data[i + 1];
Cr = data[i + 2]; Cr = data[i + 2];
@ -1327,7 +1320,7 @@ class JpegImage {
} }
_convertYccToRgba(data, out) { _convertYccToRgba(data, out) {
for (let i = 0, j = 0, ii = data.length; i < ii; i += 3, j += 4) { for (let i = 0, j = 0, length = data.length; i < length; i += 3, j += 4) {
const Y = data[i]; const Y = data[i];
const Cb = data[i + 1]; const Cb = data[i + 1];
const Cr = data[i + 2]; const Cr = data[i + 2];
@ -1351,7 +1344,7 @@ class JpegImage {
_convertYcckToCmyk(data) { _convertYcckToCmyk(data) {
let Y, Cb, Cr; let Y, Cb, Cr;
for (let i = 0, ii = data.length; i < ii; i += 4) { for (let i = 0, length = data.length; i < length; i += 4) {
Y = data[i]; Y = data[i];
Cb = data[i + 1]; Cb = data[i + 1];
Cr = data[i + 2]; Cr = data[i + 2];
@ -1386,14 +1379,19 @@ class JpegImage {
height, height,
forceRGBA = false, forceRGBA = false,
forceRGB = false, forceRGB = false,
isSourcePDF = typeof PDFJSDev === "undefined" || isSourcePDF = false,
!PDFJSDev.test("IMAGE_DECODERS"),
}) { }) {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
assert(
isSourcePDF === true,
'JpegImage.getData: Unexpected "isSourcePDF" value for PDF files.'
);
}
if (this.numComponents > 4) { if (this.numComponents > 4) {
throw new JpegError("Unsupported color mode"); throw new JpegError("Unsupported color mode");
} }
// Type of data: Uint8ClampedArray(width * height * numComponents) // Type of data: Uint8ClampedArray(width * height * numComponents)
const data = this.#getLinearizedBlockData(width, height, isSourcePDF); const data = this._getLinearizedBlockData(width, height, isSourcePDF);
if (this.numComponents === 1 && (forceRGBA || forceRGB)) { if (this.numComponents === 1 && (forceRGBA || forceRGB)) {
const len = data.length * (forceRGBA ? 4 : 3); const len = data.length * (forceRGBA ? 4 : 3);

View File

@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { assert, makeArr, shadow, unreachable } from "../shared/util.js"; import { assert, shadow, unreachable } from "../shared/util.js";
const CIRCULAR_REF = Symbol("CIRCULAR_REF"); const CIRCULAR_REF = Symbol("CIRCULAR_REF");
const EOF = Symbol("EOF"); const EOF = Symbol("EOF");
@ -242,9 +242,11 @@ class Dict {
continue; continue;
} }
for (const [key, value] of dict.getRawEntries()) { for (const [key, value] of dict.getRawEntries()) {
const property = properties.getOrInsertComputed(key, makeArr); let property = properties.get(key);
if (property === undefined) {
if (property.length && !(mergeSubDicts && value instanceof Dict)) { property = [];
properties.set(key, property);
} else if (!mergeSubDicts || !(value instanceof Dict)) {
// Ignore additional entries, if either: // Ignore additional entries, if either:
// - This is a "shallow" merge, where only the first element matters. // - This is a "shallow" merge, where only the first element matters.
// - The value is *not* a `Dict`, since other types cannot be merged. // - The value is *not* a `Dict`, since other types cannot be merged.

View File

@ -241,10 +241,9 @@ class AnnotationStorage {
continue; continue;
} }
const { type } = editorStats; const { type } = editorStats;
typeToEditor.getOrInsertComputed( if (!typeToEditor.has(type)) {
type, typeToEditor.set(type, Object.getPrototypeOf(value).constructor);
() => Object.getPrototypeOf(value).constructor }
);
stats ||= Object.create(null); stats ||= Object.create(null);
const map = (stats[type] ||= new Map()); const map = (stats[type] ||= new Map());
for (const [key, val] of Object.entries(editorStats)) { for (const [key, val] of Object.entries(editorStats)) {

View File

@ -23,7 +23,6 @@ import {
FONT_IDENTITY_MATRIX, FONT_IDENTITY_MATRIX,
ImageKind, ImageKind,
info, info,
makeArr,
makeMap, makeMap,
OPS, OPS,
shadow, shadow,
@ -1508,10 +1507,11 @@ class CanvasGraphics {
} }
let knockoutFilter = "none"; let knockoutFilter = "none";
if (needsAlphaScaling && this.#knockoutFilterCache instanceof Map) { if (needsAlphaScaling && this.#knockoutFilterCache instanceof Map) {
knockoutFilter = this.#knockoutFilterCache.getOrInsertComputed( knockoutFilter = this.#knockoutFilterCache.get(alpha);
alpha, if (!knockoutFilter) {
() => this.filterFactory.addKnockoutFilter(alpha) knockoutFilter = this.filterFactory.addKnockoutFilter(alpha);
); this.#knockoutFilterCache.set(alpha, knockoutFilter);
}
} }
if (!needsAlphaScaling || knockoutFilter !== "none") { if (!needsAlphaScaling || knockoutFilter !== "none") {
@ -3682,10 +3682,11 @@ class CanvasGraphics {
); );
const { canvas, context } = this.annotationCanvas; const { canvas, context } = this.annotationCanvas;
if (canvasName) { if (canvasName) {
const canvases = this.annotationCanvasMap.getOrInsertComputed( let canvases = this.annotationCanvasMap.get(id);
id, if (!canvases) {
makeArr canvases = [];
); this.annotationCanvasMap.set(id, canvases);
}
canvas.setAttribute("data-canvas-name", canvasName); canvas.setAttribute("data-canvas-name", canvasName);
// Replace any same-named canvas from a previous render so stale // Replace any same-named canvas from a previous render so stale
// low-resolution canvases don't pile up across zooms. // low-resolution canvases don't pile up across zooms.

View File

@ -23,7 +23,6 @@ import {
AnnotationEditorType, AnnotationEditorType,
FeatureTest, FeatureTest,
getUuid, getUuid,
makeArr,
shadow, shadow,
SVG_NS, SVG_NS,
Util, Util,
@ -551,7 +550,7 @@ class KeyboardManager {
continue; continue;
} }
this.callbacks this.callbacks
.getOrInsertComputed(keyName, makeArr) .getOrInsertComputed(keyName, () => [])
.push({ callback, options, modifiers }); .push({ callback, options, modifiers });
} }
} }

View File

@ -459,9 +459,11 @@ class Stepper {
const dependents = new Map(); const dependents = new Map();
for (const [dependentIdx, { dependencies: ownDependencies }] of metadata) { for (const [dependentIdx, { dependencies: ownDependencies }] of metadata) {
for (const dependencyIdx of ownDependencies) { for (const dependencyIdx of ownDependencies) {
dependents let ownDependents = dependents.get(dependencyIdx);
.getOrInsertComputed(dependencyIdx, () => new Set()) if (!ownDependents) {
.add(dependentIdx); dependents.set(dependencyIdx, (ownDependents = new Set()));
}
ownDependents.add(dependentIdx);
} }
} }