Merge pull request #12083 from Snuffleupagus/ColorSpace-rm-IR
Remove the IR (internal representation) part of the ColorSpace parsing
This commit is contained in:
commit
c11fc3acfc
@ -17,7 +17,6 @@ import {
|
|||||||
assert,
|
assert,
|
||||||
FormatError,
|
FormatError,
|
||||||
info,
|
info,
|
||||||
isString,
|
|
||||||
shadow,
|
shadow,
|
||||||
unreachable,
|
unreachable,
|
||||||
warn,
|
warn,
|
||||||
@ -336,8 +335,12 @@ class ColorSpace {
|
|||||||
"before calling `ColorSpace.parseAsync`."
|
"before calling `ColorSpace.parseAsync`."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const IR = this.parseToIR(cs, xref, resources, pdfFunctionFactory);
|
const parsedColorSpace = this._parse(
|
||||||
const parsedColorSpace = this.fromIR(IR);
|
cs,
|
||||||
|
xref,
|
||||||
|
resources,
|
||||||
|
pdfFunctionFactory
|
||||||
|
);
|
||||||
|
|
||||||
// Attempt to cache the parsed ColorSpace, by name and/or reference.
|
// Attempt to cache the parsed ColorSpace, by name and/or reference.
|
||||||
this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);
|
this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);
|
||||||
@ -356,8 +359,12 @@ class ColorSpace {
|
|||||||
if (cachedColorSpace) {
|
if (cachedColorSpace) {
|
||||||
return cachedColorSpace;
|
return cachedColorSpace;
|
||||||
}
|
}
|
||||||
const IR = this.parseToIR(cs, xref, resources, pdfFunctionFactory);
|
const parsedColorSpace = this._parse(
|
||||||
const parsedColorSpace = this.fromIR(IR);
|
cs,
|
||||||
|
xref,
|
||||||
|
resources,
|
||||||
|
pdfFunctionFactory
|
||||||
|
);
|
||||||
|
|
||||||
// Attempt to cache the parsed ColorSpace, by name and/or reference.
|
// Attempt to cache the parsed ColorSpace, by name and/or reference.
|
||||||
this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);
|
this._cache(cs, xref, localColorSpaceCache, parsedColorSpace);
|
||||||
@ -365,69 +372,24 @@ class ColorSpace {
|
|||||||
return parsedColorSpace;
|
return parsedColorSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromIR(IR) {
|
/**
|
||||||
const name = Array.isArray(IR) ? IR[0] : IR;
|
* @private
|
||||||
let whitePoint, blackPoint, gamma;
|
*/
|
||||||
|
static _parse(cs, xref, resources = null, pdfFunctionFactory) {
|
||||||
switch (name) {
|
|
||||||
case "DeviceGrayCS":
|
|
||||||
return this.singletons.gray;
|
|
||||||
case "DeviceRgbCS":
|
|
||||||
return this.singletons.rgb;
|
|
||||||
case "DeviceCmykCS":
|
|
||||||
return this.singletons.cmyk;
|
|
||||||
case "CalGrayCS":
|
|
||||||
whitePoint = IR[1];
|
|
||||||
blackPoint = IR[2];
|
|
||||||
gamma = IR[3];
|
|
||||||
return new CalGrayCS(whitePoint, blackPoint, gamma);
|
|
||||||
case "CalRGBCS":
|
|
||||||
whitePoint = IR[1];
|
|
||||||
blackPoint = IR[2];
|
|
||||||
gamma = IR[3];
|
|
||||||
const matrix = IR[4];
|
|
||||||
return new CalRGBCS(whitePoint, blackPoint, gamma, matrix);
|
|
||||||
case "PatternCS":
|
|
||||||
let basePatternCS = IR[1];
|
|
||||||
if (basePatternCS) {
|
|
||||||
basePatternCS = this.fromIR(basePatternCS);
|
|
||||||
}
|
|
||||||
return new PatternCS(basePatternCS);
|
|
||||||
case "IndexedCS":
|
|
||||||
const baseIndexedCS = IR[1];
|
|
||||||
const hiVal = IR[2];
|
|
||||||
const lookup = IR[3];
|
|
||||||
return new IndexedCS(this.fromIR(baseIndexedCS), hiVal, lookup);
|
|
||||||
case "AlternateCS":
|
|
||||||
const numComps = IR[1];
|
|
||||||
const alt = IR[2];
|
|
||||||
const tintFn = IR[3];
|
|
||||||
return new AlternateCS(numComps, this.fromIR(alt), tintFn);
|
|
||||||
case "LabCS":
|
|
||||||
whitePoint = IR[1];
|
|
||||||
blackPoint = IR[2];
|
|
||||||
const range = IR[3];
|
|
||||||
return new LabCS(whitePoint, blackPoint, range);
|
|
||||||
default:
|
|
||||||
throw new FormatError(`Unknown colorspace name: ${name}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static parseToIR(cs, xref, resources = null, pdfFunctionFactory) {
|
|
||||||
cs = xref.fetchIfRef(cs);
|
cs = xref.fetchIfRef(cs);
|
||||||
if (isName(cs)) {
|
if (isName(cs)) {
|
||||||
switch (cs.name) {
|
switch (cs.name) {
|
||||||
case "DeviceGray":
|
case "DeviceGray":
|
||||||
case "G":
|
case "G":
|
||||||
return "DeviceGrayCS";
|
return this.singletons.gray;
|
||||||
case "DeviceRGB":
|
case "DeviceRGB":
|
||||||
case "RGB":
|
case "RGB":
|
||||||
return "DeviceRgbCS";
|
return this.singletons.rgb;
|
||||||
case "DeviceCMYK":
|
case "DeviceCMYK":
|
||||||
case "CMYK":
|
case "CMYK":
|
||||||
return "DeviceCmykCS";
|
return this.singletons.cmyk;
|
||||||
case "Pattern":
|
case "Pattern":
|
||||||
return ["PatternCS", null];
|
return new PatternCS(/* baseCS = */ null);
|
||||||
default:
|
default:
|
||||||
if (isDict(resources)) {
|
if (isDict(resources)) {
|
||||||
const colorSpaces = resources.get("ColorSpace");
|
const colorSpaces = resources.get("ColorSpace");
|
||||||
@ -435,7 +397,7 @@ class ColorSpace {
|
|||||||
const resourcesCS = colorSpaces.get(cs.name);
|
const resourcesCS = colorSpaces.get(cs.name);
|
||||||
if (resourcesCS) {
|
if (resourcesCS) {
|
||||||
if (isName(resourcesCS)) {
|
if (isName(resourcesCS)) {
|
||||||
return this.parseToIR(
|
return this._parse(
|
||||||
resourcesCS,
|
resourcesCS,
|
||||||
xref,
|
xref,
|
||||||
resources,
|
resources,
|
||||||
@ -447,107 +409,88 @@ class ColorSpace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new FormatError(`unrecognized colorspace ${cs.name}`);
|
throw new FormatError(`Unrecognized ColorSpace: ${cs.name}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Array.isArray(cs)) {
|
if (Array.isArray(cs)) {
|
||||||
const mode = xref.fetchIfRef(cs[0]).name;
|
const mode = xref.fetchIfRef(cs[0]).name;
|
||||||
let numComps, params, alt, whitePoint, blackPoint, gamma;
|
let params, numComps, baseCS, whitePoint, blackPoint, gamma;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case "DeviceGray":
|
case "DeviceGray":
|
||||||
case "G":
|
case "G":
|
||||||
return "DeviceGrayCS";
|
return this.singletons.gray;
|
||||||
case "DeviceRGB":
|
case "DeviceRGB":
|
||||||
case "RGB":
|
case "RGB":
|
||||||
return "DeviceRgbCS";
|
return this.singletons.rgb;
|
||||||
case "DeviceCMYK":
|
case "DeviceCMYK":
|
||||||
case "CMYK":
|
case "CMYK":
|
||||||
return "DeviceCmykCS";
|
return this.singletons.cmyk;
|
||||||
case "CalGray":
|
case "CalGray":
|
||||||
params = xref.fetchIfRef(cs[1]);
|
params = xref.fetchIfRef(cs[1]);
|
||||||
whitePoint = params.getArray("WhitePoint");
|
whitePoint = params.getArray("WhitePoint");
|
||||||
blackPoint = params.getArray("BlackPoint");
|
blackPoint = params.getArray("BlackPoint");
|
||||||
gamma = params.get("Gamma");
|
gamma = params.get("Gamma");
|
||||||
return ["CalGrayCS", whitePoint, blackPoint, gamma];
|
return new CalGrayCS(whitePoint, blackPoint, gamma);
|
||||||
case "CalRGB":
|
case "CalRGB":
|
||||||
params = xref.fetchIfRef(cs[1]);
|
params = xref.fetchIfRef(cs[1]);
|
||||||
whitePoint = params.getArray("WhitePoint");
|
whitePoint = params.getArray("WhitePoint");
|
||||||
blackPoint = params.getArray("BlackPoint");
|
blackPoint = params.getArray("BlackPoint");
|
||||||
gamma = params.getArray("Gamma");
|
gamma = params.getArray("Gamma");
|
||||||
const matrix = params.getArray("Matrix");
|
const matrix = params.getArray("Matrix");
|
||||||
return ["CalRGBCS", whitePoint, blackPoint, gamma, matrix];
|
return new CalRGBCS(whitePoint, blackPoint, gamma, matrix);
|
||||||
case "ICCBased":
|
case "ICCBased":
|
||||||
const stream = xref.fetchIfRef(cs[1]);
|
const stream = xref.fetchIfRef(cs[1]);
|
||||||
const dict = stream.dict;
|
const dict = stream.dict;
|
||||||
numComps = dict.get("N");
|
numComps = dict.get("N");
|
||||||
alt = dict.get("Alternate");
|
const alt = dict.get("Alternate");
|
||||||
if (alt) {
|
if (alt) {
|
||||||
const altIR = this.parseToIR(
|
const altCS = this._parse(alt, xref, resources, pdfFunctionFactory);
|
||||||
alt,
|
// Ensure that the number of components are correct,
|
||||||
xref,
|
// and also (indirectly) that it is not a PatternCS.
|
||||||
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);
|
|
||||||
if (altCS.numComps === numComps) {
|
if (altCS.numComps === numComps) {
|
||||||
return altIR;
|
return altCS;
|
||||||
}
|
}
|
||||||
warn("ICCBased color space: Ignoring incorrect /Alternate entry.");
|
warn("ICCBased color space: Ignoring incorrect /Alternate entry.");
|
||||||
}
|
}
|
||||||
if (numComps === 1) {
|
if (numComps === 1) {
|
||||||
return "DeviceGrayCS";
|
return this.singletons.gray;
|
||||||
} else if (numComps === 3) {
|
} else if (numComps === 3) {
|
||||||
return "DeviceRgbCS";
|
return this.singletons.rgb;
|
||||||
} else if (numComps === 4) {
|
} else if (numComps === 4) {
|
||||||
return "DeviceCmykCS";
|
return this.singletons.cmyk;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "Pattern":
|
case "Pattern":
|
||||||
let basePatternCS = cs[1] || null;
|
baseCS = cs[1] || null;
|
||||||
if (basePatternCS) {
|
if (baseCS) {
|
||||||
basePatternCS = this.parseToIR(
|
baseCS = this._parse(baseCS, xref, resources, pdfFunctionFactory);
|
||||||
basePatternCS,
|
|
||||||
xref,
|
|
||||||
resources,
|
|
||||||
pdfFunctionFactory
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return ["PatternCS", basePatternCS];
|
return new PatternCS(baseCS);
|
||||||
case "Indexed":
|
case "Indexed":
|
||||||
case "I":
|
case "I":
|
||||||
const baseIndexedCS = this.parseToIR(
|
baseCS = this._parse(cs[1], xref, resources, pdfFunctionFactory);
|
||||||
cs[1],
|
|
||||||
xref,
|
|
||||||
resources,
|
|
||||||
pdfFunctionFactory
|
|
||||||
);
|
|
||||||
const hiVal = xref.fetchIfRef(cs[2]) + 1;
|
const hiVal = xref.fetchIfRef(cs[2]) + 1;
|
||||||
let lookup = xref.fetchIfRef(cs[3]);
|
const lookup = xref.fetchIfRef(cs[3]);
|
||||||
if (isStream(lookup)) {
|
return new IndexedCS(baseCS, hiVal, lookup);
|
||||||
lookup = lookup.getBytes();
|
|
||||||
}
|
|
||||||
return ["IndexedCS", baseIndexedCS, hiVal, lookup];
|
|
||||||
case "Separation":
|
case "Separation":
|
||||||
case "DeviceN":
|
case "DeviceN":
|
||||||
const name = xref.fetchIfRef(cs[1]);
|
const name = xref.fetchIfRef(cs[1]);
|
||||||
numComps = Array.isArray(name) ? name.length : 1;
|
numComps = Array.isArray(name) ? name.length : 1;
|
||||||
alt = this.parseToIR(cs[2], xref, resources, pdfFunctionFactory);
|
baseCS = this._parse(cs[2], xref, resources, pdfFunctionFactory);
|
||||||
const tintFn = pdfFunctionFactory.create(cs[3]);
|
const tintFn = pdfFunctionFactory.create(cs[3]);
|
||||||
return ["AlternateCS", numComps, alt, tintFn];
|
return new AlternateCS(numComps, baseCS, tintFn);
|
||||||
case "Lab":
|
case "Lab":
|
||||||
params = xref.fetchIfRef(cs[1]);
|
params = xref.fetchIfRef(cs[1]);
|
||||||
whitePoint = params.getArray("WhitePoint");
|
whitePoint = params.getArray("WhitePoint");
|
||||||
blackPoint = params.getArray("BlackPoint");
|
blackPoint = params.getArray("BlackPoint");
|
||||||
const range = params.getArray("Range");
|
const range = params.getArray("Range");
|
||||||
return ["LabCS", whitePoint, blackPoint, range];
|
return new LabCS(whitePoint, blackPoint, range);
|
||||||
default:
|
default:
|
||||||
throw new FormatError(`unimplemented color space object "${mode}"`);
|
throw new FormatError(`Unimplemented ColorSpace object: ${mode}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new FormatError(`unrecognized color space object: "${cs}"`);
|
throw new FormatError(`Unrecognized ColorSpace object: ${cs}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -696,22 +639,18 @@ class IndexedCS extends ColorSpace {
|
|||||||
this.base = base;
|
this.base = base;
|
||||||
this.highVal = highVal;
|
this.highVal = highVal;
|
||||||
|
|
||||||
const baseNumComps = base.numComps;
|
const length = base.numComps * highVal;
|
||||||
const length = baseNumComps * highVal;
|
this.lookup = new Uint8Array(length);
|
||||||
|
|
||||||
if (isStream(lookup)) {
|
if (isStream(lookup)) {
|
||||||
this.lookup = new Uint8Array(length);
|
|
||||||
const bytes = lookup.getBytes(length);
|
const bytes = lookup.getBytes(length);
|
||||||
this.lookup.set(bytes);
|
this.lookup.set(bytes);
|
||||||
} else if (isString(lookup)) {
|
} else if (typeof lookup === "string") {
|
||||||
this.lookup = new Uint8Array(length);
|
|
||||||
for (let i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
this.lookup[i] = lookup.charCodeAt(i);
|
this.lookup[i] = lookup.charCodeAt(i) & 0xff;
|
||||||
}
|
}
|
||||||
} else if (lookup instanceof Uint8Array) {
|
|
||||||
this.lookup = lookup;
|
|
||||||
} else {
|
} else {
|
||||||
throw new FormatError(`Unrecognized lookup table: ${lookup}`);
|
throw new FormatError(`IndexedCS - unrecognized lookup table: ${lookup}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,11 +679,13 @@ describe("colorspace", function () {
|
|||||||
describe("IndexedCS", function () {
|
describe("IndexedCS", function () {
|
||||||
it("should handle the case when cs is an array", function () {
|
it("should handle the case when cs is an array", function () {
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
const lookup = new Uint8Array([
|
const lookup = new Stream(
|
||||||
|
new Uint8Array([
|
||||||
23, 155, 35,
|
23, 155, 35,
|
||||||
147, 69, 93,
|
147, 69, 93,
|
||||||
255, 109, 70
|
255, 109, 70
|
||||||
]);
|
])
|
||||||
|
);
|
||||||
const cs = [Name.get("Indexed"), Name.get("DeviceRGB"), 2, lookup];
|
const cs = [Name.get("Indexed"), Name.get("DeviceRGB"), 2, lookup];
|
||||||
const xref = new XRefMock([
|
const xref = new XRefMock([
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user