mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-24 09:08:07 +02:00
Improve parseAppearanceStream
to handle more "complex" ColorSpaces
The existing code is unable to *correctly* extract the color from the appearance-stream when the ColorSpace-data is "complex". To reproduce this: - Open `freetexts.pdf` in the viewer. - Note the purple color of the "Hello World from Preview" annotation. - Enable any of the Editors. - Note how the relevant annotation is now black.
This commit is contained in:
parent
8281bb8858
commit
6442a6cc4e
4 changed files with 201 additions and 42 deletions
|
@ -57,6 +57,7 @@ describe("annotation", function () {
|
|||
},
|
||||
};
|
||||
this.evaluatorOptions = {
|
||||
isEvalSupported: true,
|
||||
isOffscreenCanvasSupported: false,
|
||||
};
|
||||
}
|
||||
|
@ -314,35 +315,55 @@ describe("annotation", function () {
|
|||
});
|
||||
|
||||
it("should set and get valid contents", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setContents("Foo bar baz");
|
||||
|
||||
expect(annotation._contents).toEqual({ str: "Foo bar baz", dir: "ltr" });
|
||||
});
|
||||
|
||||
it("should not set and get invalid contents", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setContents(undefined);
|
||||
|
||||
expect(annotation._contents).toEqual({ str: "", dir: "ltr" });
|
||||
});
|
||||
|
||||
it("should set and get a valid modification date", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setModificationDate("D:20190422");
|
||||
|
||||
expect(annotation.modificationDate).toEqual("D:20190422");
|
||||
});
|
||||
|
||||
it("should not set and get an invalid modification date", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setModificationDate(undefined);
|
||||
|
||||
expect(annotation.modificationDate).toEqual(null);
|
||||
});
|
||||
|
||||
it("should set and get flags", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setFlags(13);
|
||||
|
||||
expect(annotation.hasFlag(AnnotationFlag.INVISIBLE)).toEqual(true);
|
||||
|
@ -353,63 +374,99 @@ describe("annotation", function () {
|
|||
});
|
||||
|
||||
it("should be viewable and not printable by default", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
|
||||
expect(annotation.viewable).toEqual(true);
|
||||
expect(annotation.printable).toEqual(false);
|
||||
});
|
||||
|
||||
it("should set and get a valid rectangle", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setRectangle([117, 694, 164.298, 720]);
|
||||
|
||||
expect(annotation.rectangle).toEqual([117, 694, 164.298, 720]);
|
||||
});
|
||||
|
||||
it("should not set and get an invalid rectangle", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setRectangle([117, 694, 164.298]);
|
||||
|
||||
expect(annotation.rectangle).toEqual([0, 0, 0, 0]);
|
||||
});
|
||||
|
||||
it("should reject a color if it is not an array", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setColor("red");
|
||||
|
||||
expect(annotation.color).toEqual(new Uint8ClampedArray([0, 0, 0]));
|
||||
});
|
||||
|
||||
it("should set and get a transparent color", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setColor([]);
|
||||
|
||||
expect(annotation.color).toEqual(null);
|
||||
});
|
||||
|
||||
it("should set and get a grayscale color", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setColor([0.4]);
|
||||
|
||||
expect(annotation.color).toEqual(new Uint8ClampedArray([102, 102, 102]));
|
||||
});
|
||||
|
||||
it("should set and get an RGB color", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setColor([0, 0, 1]);
|
||||
|
||||
expect(annotation.color).toEqual(new Uint8ClampedArray([0, 0, 255]));
|
||||
});
|
||||
|
||||
it("should set and get a CMYK color", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setColor([0.1, 0.92, 0.84, 0.02]);
|
||||
|
||||
expect(annotation.color).toEqual(new Uint8ClampedArray([234, 59, 48]));
|
||||
});
|
||||
|
||||
it("should not set and get an invalid color", function () {
|
||||
const annotation = new Annotation({ dict, ref });
|
||||
const annotation = new Annotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
annotation.setColor([0.4, 0.6]);
|
||||
|
||||
expect(annotation.color).toEqual(new Uint8ClampedArray([0, 0, 0]));
|
||||
|
@ -514,14 +571,22 @@ describe("annotation", function () {
|
|||
});
|
||||
|
||||
it("should set and get a valid creation date", function () {
|
||||
const markupAnnotation = new MarkupAnnotation({ dict, ref });
|
||||
const markupAnnotation = new MarkupAnnotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
markupAnnotation.setCreationDate("D:20190422");
|
||||
|
||||
expect(markupAnnotation.creationDate).toEqual("D:20190422");
|
||||
});
|
||||
|
||||
it("should not set and get an invalid creation date", function () {
|
||||
const markupAnnotation = new MarkupAnnotation({ dict, ref });
|
||||
const markupAnnotation = new MarkupAnnotation({
|
||||
dict,
|
||||
ref,
|
||||
evaluatorOptions: pdfManagerMock.evaluatorOptions,
|
||||
});
|
||||
markupAnnotation.setCreationDate(undefined);
|
||||
|
||||
expect(markupAnnotation.creationDate).toEqual(null);
|
||||
|
|
|
@ -18,7 +18,9 @@ import {
|
|||
parseAppearanceStream,
|
||||
parseDefaultAppearance,
|
||||
} from "../../src/core/default_appearance.js";
|
||||
import { StringStream } from "../../src/core/stream.js";
|
||||
import { Dict, Name } from "../../src/core/primitives.js";
|
||||
import { NullStream, StringStream } from "../../src/core/stream.js";
|
||||
import { XRefMock } from "./test_utils.js";
|
||||
|
||||
describe("Default appearance", function () {
|
||||
describe("parseDefaultAppearance and createDefaultAppearance", function () {
|
||||
|
@ -54,6 +56,21 @@ describe("Default appearance", function () {
|
|||
});
|
||||
|
||||
describe("parseAppearanceStream", () => {
|
||||
let evaluatorOptions, xref;
|
||||
|
||||
beforeAll(function () {
|
||||
evaluatorOptions = {
|
||||
isEvalSupported: true,
|
||||
isOffscreenCanvasSupported: false,
|
||||
};
|
||||
xref = new XRefMock();
|
||||
});
|
||||
|
||||
afterAll(function () {
|
||||
evaluatorOptions = null;
|
||||
xref = null;
|
||||
});
|
||||
|
||||
it("should parse a FreeText (from Acrobat) appearance", () => {
|
||||
const appearance = new StringStream(`
|
||||
0 w
|
||||
|
@ -84,7 +101,9 @@ describe("Default appearance", function () {
|
|||
fontName: "Helv",
|
||||
fontColor: new Uint8ClampedArray([107, 217, 41]),
|
||||
};
|
||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
||||
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||
result
|
||||
);
|
||||
expect(appearance.pos).toEqual(0);
|
||||
});
|
||||
|
||||
|
@ -103,23 +122,46 @@ describe("Default appearance", function () {
|
|||
fontName: "Helv",
|
||||
fontColor: new Uint8ClampedArray([237, 43, 112]),
|
||||
};
|
||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
||||
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||
result
|
||||
);
|
||||
expect(appearance.pos).toEqual(0);
|
||||
});
|
||||
|
||||
it("should parse a FreeText (from Preview) appearance", () => {
|
||||
const indexedDict = new Dict(xref);
|
||||
indexedDict.set("Alternate", Name.get("DeviceRGB"));
|
||||
indexedDict.set("N", 3);
|
||||
indexedDict.set("Length", 0);
|
||||
|
||||
const indexedStream = new NullStream();
|
||||
indexedStream.dict = indexedDict;
|
||||
|
||||
const colorSpaceDict = new Dict(xref);
|
||||
colorSpaceDict.set("Cs1", [Name.get("ICCBased"), indexedStream]);
|
||||
|
||||
const resourcesDict = new Dict(xref);
|
||||
resourcesDict.set("ColorSpace", colorSpaceDict);
|
||||
|
||||
const appearanceDict = new Dict(xref);
|
||||
appearanceDict.set("Resources", resourcesDict);
|
||||
|
||||
const appearance = new StringStream(`
|
||||
q Q q 2.128482 2.128482 247.84 26 re W n /Cs1 cs 0.52799 0.3071 0.99498 sc
|
||||
q 1 0 0 -1 -108.3364 459.8485 cm BT 22.00539 0 0 -22.00539 110.5449 452.72
|
||||
Tm /TT1 1 Tf [ (H) -0.2 (e) -0.2 (l) -0.2 (l) -0.2 (o) -0.2 ( ) 0.2 (W) 17.7
|
||||
(o) -0.2 (rl) -0.2 (d) -0.2 ( ) 0.2 (f) 0.2 (ro) -0.2 (m ) 0.2 (Pre) -0.2
|
||||
(vi) -0.2 (e) -0.2 (w) ] TJ ET Q Q`);
|
||||
appearance.dict = appearanceDict;
|
||||
|
||||
const result = {
|
||||
fontSize: 22.00539,
|
||||
fontName: "TT1",
|
||||
fontColor: new Uint8ClampedArray([0, 0, 0]),
|
||||
fontColor: new Uint8ClampedArray([135, 78, 254]),
|
||||
};
|
||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
||||
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||
result
|
||||
);
|
||||
expect(appearance.pos).toEqual(0);
|
||||
});
|
||||
|
||||
|
@ -140,7 +182,9 @@ describe("Default appearance", function () {
|
|||
fontName: "Helv",
|
||||
fontColor: new Uint8ClampedArray([16, 124, 16]),
|
||||
};
|
||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
||||
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||
result
|
||||
);
|
||||
expect(appearance.pos).toEqual(0);
|
||||
});
|
||||
|
||||
|
@ -164,7 +208,9 @@ describe("Default appearance", function () {
|
|||
fontName: "FXF0",
|
||||
fontColor: new Uint8ClampedArray([149, 63, 60]),
|
||||
};
|
||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
||||
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||
result
|
||||
);
|
||||
expect(appearance.pos).toEqual(0);
|
||||
});
|
||||
|
||||
|
@ -186,7 +232,9 @@ describe("Default appearance", function () {
|
|||
fontName: "Invalid_font",
|
||||
fontColor: new Uint8ClampedArray([0, 85, 127]),
|
||||
};
|
||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
||||
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||
result
|
||||
);
|
||||
expect(appearance.pos).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue