Merge pull request #12012 from Snuffleupagus/ColorSpace-parse-cache

Improve (local) caching of parsed `ColorSpace`s (PR 12001 follow-up)
This commit is contained in:
Tim van der Meij 2020-06-25 00:06:32 +02:00 committed by GitHub
commit 276d917b7c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 491 additions and 94 deletions

View File

@ -22,7 +22,8 @@ import {
unreachable,
warn,
} from "../shared/util.js";
import { isDict, isName, isStream } from "./primitives.js";
import { isDict, isName, isStream, Name, Ref } from "./primitives.js";
import { MissingDataException } from "./core_utils.js";
/**
* Resizes an RGB image with 3 components.
@ -259,9 +260,109 @@ class ColorSpace {
return shadow(this, "usesZeroToOneRange", true);
}
static parse(cs, xref, res, pdfFunctionFactory) {
const IR = this.parseToIR(cs, xref, res, pdfFunctionFactory);
return this.fromIR(IR);
/**
* @private
*/
static _cache(cacheKey, xref, localColorSpaceCache, parsedColorSpace) {
if (!localColorSpaceCache) {
throw new Error(
'ColorSpace._cache - expected "localColorSpaceCache" argument.'
);
}
if (!parsedColorSpace) {
throw new Error(
'ColorSpace._cache - expected "parsedColorSpace" argument.'
);
}
let csName, csRef;
if (cacheKey instanceof Ref) {
csRef = cacheKey;
// If parsing succeeded, we know that this call cannot throw.
cacheKey = xref.fetch(cacheKey);
}
if (cacheKey instanceof Name) {
csName = cacheKey.name;
}
if (csName || csRef) {
localColorSpaceCache.set(csName, csRef, parsedColorSpace);
}
}
static getCached(cacheKey, xref, localColorSpaceCache) {
if (!localColorSpaceCache) {
throw new Error(
'ColorSpace.getCached - expected "localColorSpaceCache" argument.'
);
}
if (cacheKey instanceof Ref) {
const localColorSpace = localColorSpaceCache.getByRef(cacheKey);
if (localColorSpace) {
return localColorSpace;
}
try {
cacheKey = xref.fetch(cacheKey);
} catch (ex) {
if (ex instanceof MissingDataException) {
throw ex;
}
// Any errors should be handled during parsing, rather than here.
}
}
if (cacheKey instanceof Name) {
const localColorSpace = localColorSpaceCache.getByName(cacheKey.name);
if (localColorSpace) {
return localColorSpace;
}
}
return null;
}
static async parseAsync({
cs,
xref,
resources = null,
pdfFunctionFactory,
localColorSpaceCache,
}) {
if (
typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")
) {
assert(
!this.getCached(cs, xref, localColorSpaceCache),
"Expected `ColorSpace.getCached` to have been manually checked " +
"before calling `ColorSpace.parseAsync`."
);
}
const IR = this.parseToIR(cs, xref, resources, pdfFunctionFactory);
const parsedColorSpace = this.fromIR(IR);
// Attempt to cache the parsed ColorSpace, by name and/or reference.
this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);
return parsedColorSpace;
}
static parse({
cs,
xref,
resources = null,
pdfFunctionFactory,
localColorSpaceCache,
}) {
const cachedColorSpace = this.getCached(cs, xref, localColorSpaceCache);
if (cachedColorSpace) {
return cachedColorSpace;
}
const IR = this.parseToIR(cs, xref, resources, pdfFunctionFactory);
const parsedColorSpace = this.fromIR(IR);
// Attempt to cache the parsed ColorSpace, by name and/or reference.
this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);
return parsedColorSpace;
}
static fromIR(IR) {
@ -312,7 +413,7 @@ class ColorSpace {
}
}
static parseToIR(cs, xref, res = null, pdfFunctionFactory) {
static parseToIR(cs, xref, resources = null, pdfFunctionFactory) {
cs = xref.fetchIfRef(cs);
if (isName(cs)) {
switch (cs.name) {
@ -328,15 +429,20 @@ class ColorSpace {
case "Pattern":
return ["PatternCS", null];
default:
if (isDict(res)) {
const colorSpaces = res.get("ColorSpace");
if (isDict(resources)) {
const colorSpaces = resources.get("ColorSpace");
if (isDict(colorSpaces)) {
const resCS = colorSpaces.get(cs.name);
if (resCS) {
if (isName(resCS)) {
return this.parseToIR(resCS, xref, res, pdfFunctionFactory);
const resourcesCS = colorSpaces.get(cs.name);
if (resourcesCS) {
if (isName(resourcesCS)) {
return this.parseToIR(
resourcesCS,
xref,
resources,
pdfFunctionFactory
);
}
cs = resCS;
cs = resourcesCS;
break;
}
}
@ -377,10 +483,15 @@ class ColorSpace {
numComps = dict.get("N");
alt = dict.get("Alternate");
if (alt) {
const altIR = this.parseToIR(alt, xref, res, pdfFunctionFactory);
const altIR = this.parseToIR(
alt,
xref,
resources,
pdfFunctionFactory
);
// Parse the /Alternate CS to ensure that the number of components
// are correct, and also (indirectly) that it is not a PatternCS.
const altCS = this.fromIR(altIR, pdfFunctionFactory);
const altCS = this.fromIR(altIR);
if (altCS.numComps === numComps) {
return altIR;
}
@ -400,7 +511,7 @@ class ColorSpace {
basePatternCS = this.parseToIR(
basePatternCS,
xref,
res,
resources,
pdfFunctionFactory
);
}
@ -410,7 +521,7 @@ class ColorSpace {
const baseIndexedCS = this.parseToIR(
cs[1],
xref,
res,
resources,
pdfFunctionFactory
);
const hiVal = xref.fetchIfRef(cs[2]) + 1;
@ -423,7 +534,7 @@ class ColorSpace {
case "DeviceN":
const name = xref.fetchIfRef(cs[1]);
numComps = Array.isArray(name) ? name.length : 1;
alt = this.parseToIR(cs[2], xref, res, pdfFunctionFactory);
alt = this.parseToIR(cs[2], xref, resources, pdfFunctionFactory);
const tintFn = pdfFunctionFactory.create(xref.fetchIfRef(cs[3]));
return ["AlternateCS", numComps, alt, tintFn];
case "Lab":

View File

@ -73,13 +73,13 @@ import {
} from "./standard_fonts.js";
import { getTilingPatternIR, Pattern } from "./pattern.js";
import { Lexer, Parser } from "./parser.js";
import { LocalColorSpaceCache, LocalImageCache } from "./image_utils.js";
import { bidi } from "./bidi.js";
import { ColorSpace } from "./colorspace.js";
import { DecodeStream } from "./stream.js";
import { getGlyphsUnicode } from "./glyphlist.js";
import { getMetrics } from "./metrics.js";
import { isPDFFunction } from "./function.js";
import { LocalImageCache } from "./image_utils.js";
import { MurmurHash3_64 } from "./murmurhash3.js";
import { OperatorList } from "./operator_list.js";
import { PDFImage } from "./image.js";
@ -411,12 +411,15 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
groupOptions.isolated = group.get("I") || false;
groupOptions.knockout = group.get("K") || false;
if (group.has("CS")) {
const cs = group.get("CS");
const cs = group.getRaw("CS");
const localColorSpace =
cs instanceof Name && localColorSpaceCache.getByName(cs.name);
if (localColorSpace) {
colorSpace = localColorSpace;
const cachedColorSpace = ColorSpace.getCached(
cs,
this.xref,
localColorSpaceCache
);
if (cachedColorSpace) {
colorSpace = cachedColorSpace;
} else {
colorSpace = await this.parseColorSpace({
cs,
@ -483,6 +486,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
operatorList,
cacheKey,
localImageCache,
localColorSpaceCache,
}) {
var dict = image.dict;
const imageRef = dict.objId;
@ -549,6 +553,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
image,
isInline,
pdfFunctionFactory: this.pdfFunctionFactory,
localColorSpaceCache,
});
// We force the use of RGBA_32BPP images here, because we can't handle
// any other kind.
@ -585,6 +590,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
image,
isInline,
pdfFunctionFactory: this.pdfFunctionFactory,
localColorSpaceCache,
})
.then(imageObj => {
imgData = imageObj.createImageData(/* forceRGBA = */ false);
@ -1135,19 +1141,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
},
parseColorSpace({ cs, resources, localColorSpaceCache }) {
return new Promise(resolve => {
const parsedColorSpace = ColorSpace.parse(
cs,
this.xref,
resources,
this.pdfFunctionFactory
);
const csName = cs instanceof Name ? cs.name : null;
if (csName) {
localColorSpaceCache.set(csName, /* ref = */ null, parsedColorSpace);
}
resolve(parsedColorSpace);
return ColorSpace.parseAsync({
cs,
xref: this.xref,
resources,
pdfFunctionFactory: this.pdfFunctionFactory,
localColorSpaceCache,
}).catch(reason => {
if (reason instanceof AbortException) {
return null;
@ -1165,7 +1164,16 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
});
},
async handleColorN(operatorList, fn, args, cs, patterns, resources, task) {
async handleColorN(
operatorList,
fn,
args,
cs,
patterns,
resources,
task,
localColorSpaceCache
) {
// compile tiling patterns
var patternName = args[args.length - 1];
// SCN/scn applies patterns along with normal colors
@ -1194,7 +1202,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
this.xref,
resources,
this.handler,
this.pdfFunctionFactory
this.pdfFunctionFactory,
localColorSpaceCache
);
operatorList.addOp(fn, pattern.getIR());
return undefined;
@ -1224,7 +1233,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var xref = this.xref;
let parsingText = false;
const localImageCache = new LocalImageCache();
const localColorSpaceCache = new LocalImageCache();
const localColorSpaceCache = new LocalColorSpaceCache();
var xobjs = resources.get("XObject") || Dict.empty;
var patterns = resources.get("Pattern") || Dict.empty;
@ -1352,6 +1361,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
operatorList,
cacheKey: name,
localImageCache,
localColorSpaceCache,
})
.then(resolveXObject, rejectXObject);
return;
@ -1425,6 +1435,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
operatorList,
cacheKey,
localImageCache,
localColorSpaceCache,
})
);
return;
@ -1483,11 +1494,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
break;
case OPS.setFillColorSpace: {
const localColorSpace =
args[0] instanceof Name &&
localColorSpaceCache.getByName(args[0].name);
if (localColorSpace) {
stateManager.state.fillColorSpace = localColorSpace;
const cachedColorSpace = ColorSpace.getCached(
args[0],
xref,
localColorSpaceCache
);
if (cachedColorSpace) {
stateManager.state.fillColorSpace = cachedColorSpace;
continue;
}
@ -1507,11 +1520,13 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
return;
}
case OPS.setStrokeColorSpace: {
const localColorSpace =
args[0] instanceof Name &&
localColorSpaceCache.getByName(args[0].name);
if (localColorSpace) {
stateManager.state.strokeColorSpace = localColorSpace;
const cachedColorSpace = ColorSpace.getCached(
args[0],
xref,
localColorSpaceCache
);
if (cachedColorSpace) {
stateManager.state.strokeColorSpace = cachedColorSpace;
continue;
}
@ -1579,7 +1594,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
cs,
patterns,
resources,
task
task,
localColorSpaceCache
)
);
return;
@ -1598,7 +1614,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
cs,
patterns,
resources,
task
task,
localColorSpaceCache
)
);
return;
@ -1624,7 +1641,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
xref,
resources,
self.handler,
self.pdfFunctionFactory
self.pdfFunctionFactory,
localColorSpaceCache
);
var patternIR = shadingFill.getIR();
args = [patternIR];

View File

@ -89,6 +89,7 @@ var PDFImage = (function PDFImageClosure() {
mask = null,
isMask = false,
pdfFunctionFactory,
localColorSpaceCache,
}) {
this.image = image;
var dict = image.dict;
@ -159,7 +160,7 @@ var PDFImage = (function PDFImageClosure() {
this.bpc = bitsPerComponent;
if (!this.imageMask) {
var colorSpace = dict.get("ColorSpace", "CS");
let colorSpace = dict.getRaw("ColorSpace") || dict.getRaw("CS");
if (!colorSpace) {
info("JPX images (which do not require color spaces)");
switch (image.numComps) {
@ -179,13 +180,13 @@ var PDFImage = (function PDFImageClosure() {
);
}
}
const resources = isInline ? res : null;
this.colorSpace = ColorSpace.parse(
colorSpace,
this.colorSpace = ColorSpace.parse({
cs: colorSpace,
xref,
resources,
pdfFunctionFactory
);
resources: isInline ? res : null,
pdfFunctionFactory,
localColorSpaceCache,
});
this.numComps = this.colorSpace.numComps;
}
@ -221,6 +222,7 @@ var PDFImage = (function PDFImageClosure() {
image: smask,
isInline,
pdfFunctionFactory,
localColorSpaceCache,
});
} else if (mask) {
if (isStream(mask)) {
@ -236,6 +238,7 @@ var PDFImage = (function PDFImageClosure() {
isInline,
isMask: true,
pdfFunctionFactory,
localColorSpaceCache,
});
}
} else {
@ -254,6 +257,7 @@ var PDFImage = (function PDFImageClosure() {
image,
isInline = false,
pdfFunctionFactory,
localColorSpaceCache,
}) {
const imageData = image;
let smaskData = null;
@ -280,6 +284,7 @@ var PDFImage = (function PDFImageClosure() {
smask: smaskData,
mask: maskData,
pdfFunctionFactory,
localColorSpaceCache,
});
};

View File

@ -14,11 +14,14 @@
*/
/* eslint no-var: error */
import { assert, info, shadow } from "../shared/util.js";
import { assert, info, shadow, unreachable } from "../shared/util.js";
import { RefSetCache } from "./primitives.js";
class LocalImageCache {
class BaseLocalCache {
constructor() {
if (this.constructor === BaseLocalCache) {
unreachable("Cannot initialize BaseLocalCache.");
}
this._nameRefMap = new Map();
this._imageMap = new Map();
this._imageCache = new RefSetCache();
@ -36,6 +39,12 @@ class LocalImageCache {
return this._imageCache.get(ref) || null;
}
set(name, ref, data) {
unreachable("Abstract method `set` called.");
}
}
class LocalImageCache extends BaseLocalCache {
set(name, ref = null, data) {
if (!name) {
throw new Error('LocalImageCache.set - expected "name" argument.');
@ -56,6 +65,32 @@ class LocalImageCache {
}
}
class LocalColorSpaceCache extends BaseLocalCache {
set(name = null, ref = null, data) {
if (!name && !ref) {
throw new Error(
'LocalColorSpaceCache.set - expected "name" and/or "ref" argument.'
);
}
if (ref) {
if (this._imageCache.has(ref)) {
return;
}
if (name) {
// Optional when `ref` is defined.
this._nameRefMap.set(name, ref);
}
this._imageCache.put(ref, data);
return;
}
// name
if (this._imageMap.has(name)) {
return;
}
this._imageMap.set(name, data);
}
}
class GlobalImageCache {
static get NUM_PAGES_THRESHOLD() {
return shadow(this, "NUM_PAGES_THRESHOLD", 2);
@ -149,4 +184,4 @@ class GlobalImageCache {
}
}
export { LocalImageCache, GlobalImageCache };
export { LocalImageCache, LocalColorSpaceCache, GlobalImageCache };

View File

@ -57,7 +57,8 @@ var Pattern = (function PatternClosure() {
xref,
res,
handler,
pdfFunctionFactory
pdfFunctionFactory,
localColorSpaceCache
) {
var dict = isStream(shading) ? shading.dict : shading;
var type = dict.get("ShadingType");
@ -72,7 +73,8 @@ var Pattern = (function PatternClosure() {
matrix,
xref,
res,
pdfFunctionFactory
pdfFunctionFactory,
localColorSpaceCache
);
case ShadingType.FREE_FORM_MESH:
case ShadingType.LATTICE_FORM_MESH:
@ -83,7 +85,8 @@ var Pattern = (function PatternClosure() {
matrix,
xref,
res,
pdfFunctionFactory
pdfFunctionFactory,
localColorSpaceCache
);
default:
throw new FormatError("Unsupported ShadingType: " + type);
@ -111,13 +114,25 @@ Shadings.SMALL_NUMBER = 1e-6;
// Radial and axial shading have very similar implementations
// If needed, the implementations can be broken into two classes
Shadings.RadialAxial = (function RadialAxialClosure() {
function RadialAxial(dict, matrix, xref, res, pdfFunctionFactory) {
function RadialAxial(
dict,
matrix,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache
) {
this.matrix = matrix;
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);
const cs = ColorSpace.parse({
cs: dict.getRaw("ColorSpace") || dict.getRaw("CS"),
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache,
});
this.cs = cs;
const bbox = dict.getArray("BBox");
if (Array.isArray(bbox) && bbox.length === 4) {
@ -830,7 +845,14 @@ Shadings.Mesh = (function MeshClosure() {
}
}
function Mesh(stream, matrix, xref, res, pdfFunctionFactory) {
function Mesh(
stream,
matrix,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache
) {
if (!isStream(stream)) {
throw new FormatError("Mesh data is not a stream");
}
@ -844,8 +866,13 @@ Shadings.Mesh = (function MeshClosure() {
} else {
this.bbox = null;
}
var cs = dict.get("ColorSpace", "CS");
cs = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const cs = ColorSpace.parse({
cs: dict.getRaw("ColorSpace") || dict.getRaw("CS"),
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache,
});
this.cs = cs;
this.background = dict.has("Background")
? cs.getRgb(dict.get("Background"), 0)

View File

@ -16,18 +16,21 @@
import { Dict, Name, Ref } from "../../src/core/primitives.js";
import { Stream, StringStream } from "../../src/core/stream.js";
import { ColorSpace } from "../../src/core/colorspace.js";
import { LocalColorSpaceCache } from "../../src/core/image_utils.js";
import { PDFFunctionFactory } from "../../src/core/function.js";
import { XRefMock } from "./test_utils.js";
describe("colorspace", function () {
describe("ColorSpace", function () {
describe("ColorSpace.isDefaultDecode", function () {
it("should be true if decode is not an array", function () {
expect(ColorSpace.isDefaultDecode("string", 0)).toBeTruthy();
});
it("should be true if length of decode array is not correct", function () {
expect(ColorSpace.isDefaultDecode([0], 1)).toBeTruthy();
expect(ColorSpace.isDefaultDecode([0, 1, 0], 1)).toBeTruthy();
});
it("should be true if decode map matches the default decode map", function () {
expect(ColorSpace.isDefaultDecode([], 0)).toBeTruthy();
@ -46,6 +49,138 @@ describe("colorspace", function () {
});
});
describe("ColorSpace caching", function () {
let localColorSpaceCache = null;
beforeAll(function (done) {
localColorSpaceCache = new LocalColorSpaceCache();
done();
});
afterAll(function (done) {
localColorSpaceCache = null;
done();
});
it("caching by Name", function () {
const xref = new XRefMock();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace1 = ColorSpace.parse({
cs: Name.get("Pattern"),
xref,
resources: null,
pdfFunctionFactory,
localColorSpaceCache,
});
expect(colorSpace1.name).toEqual("Pattern");
const colorSpace2 = ColorSpace.parse({
cs: Name.get("Pattern"),
xref,
resources: null,
pdfFunctionFactory,
localColorSpaceCache,
});
expect(colorSpace2.name).toEqual("Pattern");
const colorSpaceNonCached = ColorSpace.parse({
cs: Name.get("Pattern"),
xref,
resources: null,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
expect(colorSpaceNonCached.name).toEqual("Pattern");
const colorSpaceOther = ColorSpace.parse({
cs: Name.get("RGB"),
xref,
resources: null,
pdfFunctionFactory,
localColorSpaceCache,
});
expect(colorSpaceOther.name).toEqual("DeviceRGB");
// These two must be *identical* if caching worked as intended.
expect(colorSpace1).toBe(colorSpace2);
expect(colorSpace1).not.toBe(colorSpaceNonCached);
expect(colorSpace1).not.toBe(colorSpaceOther);
});
it("caching by Ref", function () {
const paramsCalGray = new Dict();
paramsCalGray.set("WhitePoint", [1, 1, 1]);
paramsCalGray.set("BlackPoint", [0, 0, 0]);
paramsCalGray.set("Gamma", 2.0);
const paramsCalRGB = new Dict();
paramsCalRGB.set("WhitePoint", [1, 1, 1]);
paramsCalRGB.set("BlackPoint", [0, 0, 0]);
paramsCalRGB.set("Gamma", [1, 1, 1]);
paramsCalRGB.set("Matrix", [1, 0, 0, 0, 1, 0, 0, 0, 1]);
const xref = new XRefMock([
{
ref: Ref.get(50, 0),
data: [Name.get("CalGray"), paramsCalGray],
},
{
ref: Ref.get(100, 0),
data: [Name.get("CalRGB"), paramsCalRGB],
},
]);
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace1 = ColorSpace.parse({
cs: Ref.get(50, 0),
xref,
resources: null,
pdfFunctionFactory,
localColorSpaceCache,
});
expect(colorSpace1.name).toEqual("CalGray");
const colorSpace2 = ColorSpace.parse({
cs: Ref.get(50, 0),
xref,
resources: null,
pdfFunctionFactory,
localColorSpaceCache,
});
expect(colorSpace2.name).toEqual("CalGray");
const colorSpaceNonCached = ColorSpace.parse({
cs: Ref.get(50, 0),
xref,
resources: null,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
expect(colorSpaceNonCached.name).toEqual("CalGray");
const colorSpaceOther = ColorSpace.parse({
cs: Ref.get(100, 0),
xref,
resources: null,
pdfFunctionFactory,
localColorSpaceCache,
});
expect(colorSpaceOther.name).toEqual("CalRGB");
// These two must be *identical* if caching worked as intended.
expect(colorSpace1).toBe(colorSpace2);
expect(colorSpace1).not.toBe(colorSpaceNonCached);
expect(colorSpace1).not.toBe(colorSpaceOther);
});
});
describe("DeviceGrayCS", function () {
it("should handle the case when cs is a Name object", function () {
const cs = Name.get("DeviceGray");
@ -55,12 +190,18 @@ describe("colorspace", function () {
data: new Dict(),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
const testSrc = new Uint8Array([27, 125, 250, 131]);
const testDest = new Uint8ClampedArray(4 * 4 * 3);
@ -100,12 +241,18 @@ describe("colorspace", function () {
data: Name.get("DeviceGray"),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
const testSrc = new Uint8Array([27, 125, 250, 131]);
const testDest = new Uint8ClampedArray(3 * 3 * 3);
@ -141,12 +288,18 @@ describe("colorspace", function () {
data: new Dict(),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
// prettier-ignore
const testSrc = new Uint8Array([
@ -192,12 +345,18 @@ describe("colorspace", function () {
data: Name.get("DeviceRGB"),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
// prettier-ignore
const testSrc = new Uint8Array([
@ -239,12 +398,18 @@ describe("colorspace", function () {
data: new Dict(),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
// prettier-ignore
const testSrc = new Uint8Array([
@ -290,12 +455,18 @@ describe("colorspace", function () {
data: Name.get("DeviceCMYK"),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
// prettier-ignore
const testSrc = new Uint8Array([
@ -342,12 +513,18 @@ describe("colorspace", function () {
data: new Dict(),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
const testSrc = new Uint8Array([27, 125, 250, 131]);
const testDest = new Uint8ClampedArray(4 * 4 * 3);
@ -396,12 +573,18 @@ describe("colorspace", function () {
data: new Dict(),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
// prettier-ignore
const testSrc = new Uint8Array([
@ -448,12 +631,18 @@ describe("colorspace", function () {
data: new Dict(),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
// prettier-ignore
const testSrc = new Uint8Array([
@ -502,12 +691,18 @@ describe("colorspace", function () {
data: new Dict(),
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
const testSrc = new Uint8Array([2, 2, 0, 1]);
const testDest = new Uint8ClampedArray(3 * 3 * 3);
@ -564,12 +759,18 @@ describe("colorspace", function () {
data: fn,
},
]);
const res = new Dict();
const resources = new Dict();
const pdfFunctionFactory = new PDFFunctionFactory({
xref,
});
const colorSpace = ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
const colorSpace = ColorSpace.parse({
cs,
xref,
resources,
pdfFunctionFactory,
localColorSpaceCache: new LocalColorSpaceCache(),
});
const testSrc = new Uint8Array([27, 25, 50, 31]);
const testDest = new Uint8ClampedArray(3 * 3 * 3);