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
@ -148,8 +148,7 @@ class AnnotationFactory {
|
|||||||
needAppearances:
|
needAppearances:
|
||||||
!collectFields && acroFormDict.get("NeedAppearances") === true,
|
!collectFields && acroFormDict.get("NeedAppearances") === true,
|
||||||
pageIndex,
|
pageIndex,
|
||||||
isOffscreenCanvasSupported:
|
evaluatorOptions: pdfManager.evaluatorOptions,
|
||||||
pdfManager.evaluatorOptions.isOffscreenCanvasSupported,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
@ -341,7 +340,7 @@ class AnnotationFactory {
|
|||||||
xref,
|
xref,
|
||||||
annotation,
|
annotation,
|
||||||
dependencies,
|
dependencies,
|
||||||
image
|
{ image }
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@ -364,8 +363,7 @@ class AnnotationFactory {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const xref = evaluator.xref;
|
const { options, xref } = evaluator;
|
||||||
const { isOffscreenCanvasSupported } = evaluator.options;
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
for (const annotation of annotations) {
|
for (const annotation of annotations) {
|
||||||
if (annotation.deleted) {
|
if (annotation.deleted) {
|
||||||
@ -377,19 +375,19 @@ class AnnotationFactory {
|
|||||||
FreeTextAnnotation.createNewPrintAnnotation(xref, annotation, {
|
FreeTextAnnotation.createNewPrintAnnotation(xref, annotation, {
|
||||||
evaluator,
|
evaluator,
|
||||||
task,
|
task,
|
||||||
isOffscreenCanvasSupported,
|
evaluatorOptions: options,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case AnnotationEditorType.INK:
|
case AnnotationEditorType.INK:
|
||||||
promises.push(
|
promises.push(
|
||||||
InkAnnotation.createNewPrintAnnotation(xref, annotation, {
|
InkAnnotation.createNewPrintAnnotation(xref, annotation, {
|
||||||
isOffscreenCanvasSupported,
|
evaluatorOptions: options,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case AnnotationEditorType.STAMP:
|
case AnnotationEditorType.STAMP:
|
||||||
if (!isOffscreenCanvasSupported) {
|
if (!options.isOffscreenCanvasSupported) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const image = await imagePromises.get(annotation.bitmapId);
|
const image = await imagePromises.get(annotation.bitmapId);
|
||||||
@ -402,7 +400,10 @@ class AnnotationFactory {
|
|||||||
image.imageStream = image.smaskStream = null;
|
image.imageStream = image.smaskStream = null;
|
||||||
}
|
}
|
||||||
promises.push(
|
promises.push(
|
||||||
StampAnnotation.createNewPrintAnnotation(xref, annotation, image)
|
StampAnnotation.createNewPrintAnnotation(xref, annotation, {
|
||||||
|
image,
|
||||||
|
evaluatorOptions: options,
|
||||||
|
})
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -600,7 +601,8 @@ class Annotation {
|
|||||||
this.data.pageIndex = params.pageIndex;
|
this.data.pageIndex = params.pageIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._isOffscreenCanvasSupported = params.isOffscreenCanvasSupported;
|
this._isOffscreenCanvasSupported =
|
||||||
|
params.evaluatorOptions.isOffscreenCanvasSupported;
|
||||||
this._fallbackFontDict = null;
|
this._fallbackFontDict = null;
|
||||||
this._needAppearances = false;
|
this._needAppearances = false;
|
||||||
}
|
}
|
||||||
@ -1587,7 +1589,7 @@ class MarkupAnnotation extends Annotation {
|
|||||||
const newAnnotation = new this.prototype.constructor({
|
const newAnnotation = new this.prototype.constructor({
|
||||||
dict: annotationDict,
|
dict: annotationDict,
|
||||||
xref,
|
xref,
|
||||||
isOffscreenCanvasSupported: params.isOffscreenCanvasSupported,
|
evaluatorOptions: params.evaluatorOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (annotation.ref) {
|
if (annotation.ref) {
|
||||||
@ -3648,11 +3650,15 @@ class FreeTextAnnotation extends MarkupAnnotation {
|
|||||||
|
|
||||||
this.data.hasOwnCanvas = true;
|
this.data.hasOwnCanvas = true;
|
||||||
|
|
||||||
const { xref } = params;
|
const { evaluatorOptions, xref } = params;
|
||||||
this.data.annotationType = AnnotationType.FREETEXT;
|
this.data.annotationType = AnnotationType.FREETEXT;
|
||||||
this.setDefaultAppearance(params);
|
this.setDefaultAppearance(params);
|
||||||
if (this.appearance) {
|
if (this.appearance) {
|
||||||
const { fontColor, fontSize } = parseAppearanceStream(this.appearance);
|
const { fontColor, fontSize } = parseAppearanceStream(
|
||||||
|
this.appearance,
|
||||||
|
evaluatorOptions,
|
||||||
|
xref
|
||||||
|
);
|
||||||
this.data.defaultAppearanceData.fontColor = fontColor;
|
this.data.defaultAppearanceData.fontColor = fontColor;
|
||||||
this.data.defaultAppearanceData.fontSize = fontSize || 10;
|
this.data.defaultAppearanceData.fontSize = fontSize || 10;
|
||||||
} else if (this._isOffscreenCanvasSupported) {
|
} else if (this._isOffscreenCanvasSupported) {
|
||||||
@ -4570,7 +4576,7 @@ class StampAnnotation extends MarkupAnnotation {
|
|||||||
|
|
||||||
static async createNewAppearanceStream(annotation, xref, params) {
|
static async createNewAppearanceStream(annotation, xref, params) {
|
||||||
const { rotation } = annotation;
|
const { rotation } = annotation;
|
||||||
const { imageRef, width, height } = params;
|
const { imageRef, width, height } = params.image;
|
||||||
const resources = new Dict(xref);
|
const resources = new Dict(xref);
|
||||||
const xobject = new Dict(xref);
|
const xobject = new Dict(xref);
|
||||||
resources.set("XObject", xobject);
|
resources.set("XObject", xobject);
|
||||||
|
@ -20,9 +20,17 @@ import {
|
|||||||
numberToString,
|
numberToString,
|
||||||
stringToUTF16HexString,
|
stringToUTF16HexString,
|
||||||
} from "./core_utils.js";
|
} from "./core_utils.js";
|
||||||
import { LINE_DESCENT_FACTOR, LINE_FACTOR, OPS, warn } from "../shared/util.js";
|
import {
|
||||||
|
LINE_DESCENT_FACTOR,
|
||||||
|
LINE_FACTOR,
|
||||||
|
OPS,
|
||||||
|
shadow,
|
||||||
|
warn,
|
||||||
|
} from "../shared/util.js";
|
||||||
import { ColorSpace } from "./colorspace.js";
|
import { ColorSpace } from "./colorspace.js";
|
||||||
import { EvaluatorPreprocessor } from "./evaluator.js";
|
import { EvaluatorPreprocessor } from "./evaluator.js";
|
||||||
|
import { LocalColorSpaceCache } from "./image_utils.js";
|
||||||
|
import { PDFFunctionFactory } from "./function.js";
|
||||||
import { StringStream } from "./stream.js";
|
import { StringStream } from "./stream.js";
|
||||||
|
|
||||||
class DefaultAppearanceEvaluator extends EvaluatorPreprocessor {
|
class DefaultAppearanceEvaluator extends EvaluatorPreprocessor {
|
||||||
@ -88,9 +96,13 @@ function parseDefaultAppearance(str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
|
class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
|
||||||
constructor(stream) {
|
constructor(stream, evaluatorOptions, xref) {
|
||||||
super(stream);
|
super(stream);
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
|
this.evaluatorOptions = evaluatorOptions;
|
||||||
|
this.xref = xref;
|
||||||
|
|
||||||
|
this.resources = stream.dict?.get("Resources");
|
||||||
}
|
}
|
||||||
|
|
||||||
parse() {
|
parse() {
|
||||||
@ -103,6 +115,7 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
|
|||||||
fontSize: 0,
|
fontSize: 0,
|
||||||
fontName: "",
|
fontName: "",
|
||||||
fontColor: /* black = */ new Uint8ClampedArray(3),
|
fontColor: /* black = */ new Uint8ClampedArray(3),
|
||||||
|
fillColorSpace: ColorSpace.singletons.gray,
|
||||||
};
|
};
|
||||||
let breakLoop = false;
|
let breakLoop = false;
|
||||||
const stack = [];
|
const stack = [];
|
||||||
@ -123,6 +136,7 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
|
|||||||
fontSize: result.fontSize,
|
fontSize: result.fontSize,
|
||||||
fontName: result.fontName,
|
fontName: result.fontName,
|
||||||
fontColor: result.fontColor.slice(),
|
fontColor: result.fontColor.slice(),
|
||||||
|
fillColorSpace: result.fillColorSpace,
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case OPS.restore:
|
case OPS.restore:
|
||||||
@ -140,6 +154,19 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
|
|||||||
result.fontSize = fontSize * result.scaleFactor;
|
result.fontSize = fontSize * result.scaleFactor;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case OPS.setFillColorSpace:
|
||||||
|
result.fillColorSpace = ColorSpace.parse({
|
||||||
|
cs: args[0],
|
||||||
|
xref: this.xref,
|
||||||
|
resources: this.resources,
|
||||||
|
pdfFunctionFactory: this._pdfFunctionFactory,
|
||||||
|
localColorSpaceCache: this._localColorSpaceCache,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case OPS.setFillColor:
|
||||||
|
const cs = result.fillColorSpace;
|
||||||
|
cs.getRgbItem(args, 0, result.fontColor, 0);
|
||||||
|
break;
|
||||||
case OPS.setFillRGBColor:
|
case OPS.setFillRGBColor:
|
||||||
ColorSpace.singletons.rgb.getRgbItem(args, 0, result.fontColor, 0);
|
ColorSpace.singletons.rgb.getRgbItem(args, 0, result.fontColor, 0);
|
||||||
break;
|
break;
|
||||||
@ -162,15 +189,28 @@ class AppearanceStreamEvaluator extends EvaluatorPreprocessor {
|
|||||||
}
|
}
|
||||||
this.stream.reset();
|
this.stream.reset();
|
||||||
delete result.scaleFactor;
|
delete result.scaleFactor;
|
||||||
|
delete result.fillColorSpace;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get _localColorSpaceCache() {
|
||||||
|
return shadow(this, "_localColorSpaceCache", new LocalColorSpaceCache());
|
||||||
|
}
|
||||||
|
|
||||||
|
get _pdfFunctionFactory() {
|
||||||
|
const pdfFunctionFactory = new PDFFunctionFactory({
|
||||||
|
xref: this.xref,
|
||||||
|
isEvalSupported: this.evaluatorOptions.isEvalSupported,
|
||||||
|
});
|
||||||
|
return shadow(this, "_pdfFunctionFactory", pdfFunctionFactory);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse appearance stream to extract font and color information.
|
// Parse appearance stream to extract font and color information.
|
||||||
// It returns the font properties used to render the first text object.
|
// It returns the font properties used to render the first text object.
|
||||||
function parseAppearanceStream(stream) {
|
function parseAppearanceStream(stream, evaluatorOptions, xref) {
|
||||||
return new AppearanceStreamEvaluator(stream).parse();
|
return new AppearanceStreamEvaluator(stream, evaluatorOptions, xref).parse();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPdfColor(color, isFill) {
|
function getPdfColor(color, isFill) {
|
||||||
|
@ -57,6 +57,7 @@ describe("annotation", function () {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
this.evaluatorOptions = {
|
this.evaluatorOptions = {
|
||||||
|
isEvalSupported: true,
|
||||||
isOffscreenCanvasSupported: false,
|
isOffscreenCanvasSupported: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -314,35 +315,55 @@ describe("annotation", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should set and get valid contents", 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");
|
annotation.setContents("Foo bar baz");
|
||||||
|
|
||||||
expect(annotation._contents).toEqual({ str: "Foo bar baz", dir: "ltr" });
|
expect(annotation._contents).toEqual({ str: "Foo bar baz", dir: "ltr" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not set and get invalid contents", function () {
|
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);
|
annotation.setContents(undefined);
|
||||||
|
|
||||||
expect(annotation._contents).toEqual({ str: "", dir: "ltr" });
|
expect(annotation._contents).toEqual({ str: "", dir: "ltr" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set and get a valid modification date", function () {
|
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");
|
annotation.setModificationDate("D:20190422");
|
||||||
|
|
||||||
expect(annotation.modificationDate).toEqual("D:20190422");
|
expect(annotation.modificationDate).toEqual("D:20190422");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not set and get an invalid modification date", function () {
|
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);
|
annotation.setModificationDate(undefined);
|
||||||
|
|
||||||
expect(annotation.modificationDate).toEqual(null);
|
expect(annotation.modificationDate).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set and get flags", function () {
|
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);
|
annotation.setFlags(13);
|
||||||
|
|
||||||
expect(annotation.hasFlag(AnnotationFlag.INVISIBLE)).toEqual(true);
|
expect(annotation.hasFlag(AnnotationFlag.INVISIBLE)).toEqual(true);
|
||||||
@ -353,63 +374,99 @@ describe("annotation", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should be viewable and not printable by default", 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.viewable).toEqual(true);
|
||||||
expect(annotation.printable).toEqual(false);
|
expect(annotation.printable).toEqual(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set and get a valid rectangle", function () {
|
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]);
|
annotation.setRectangle([117, 694, 164.298, 720]);
|
||||||
|
|
||||||
expect(annotation.rectangle).toEqual([117, 694, 164.298, 720]);
|
expect(annotation.rectangle).toEqual([117, 694, 164.298, 720]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not set and get an invalid rectangle", function () {
|
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]);
|
annotation.setRectangle([117, 694, 164.298]);
|
||||||
|
|
||||||
expect(annotation.rectangle).toEqual([0, 0, 0, 0]);
|
expect(annotation.rectangle).toEqual([0, 0, 0, 0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should reject a color if it is not an array", function () {
|
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");
|
annotation.setColor("red");
|
||||||
|
|
||||||
expect(annotation.color).toEqual(new Uint8ClampedArray([0, 0, 0]));
|
expect(annotation.color).toEqual(new Uint8ClampedArray([0, 0, 0]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set and get a transparent color", function () {
|
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([]);
|
annotation.setColor([]);
|
||||||
|
|
||||||
expect(annotation.color).toEqual(null);
|
expect(annotation.color).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set and get a grayscale color", function () {
|
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]);
|
annotation.setColor([0.4]);
|
||||||
|
|
||||||
expect(annotation.color).toEqual(new Uint8ClampedArray([102, 102, 102]));
|
expect(annotation.color).toEqual(new Uint8ClampedArray([102, 102, 102]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set and get an RGB color", function () {
|
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]);
|
annotation.setColor([0, 0, 1]);
|
||||||
|
|
||||||
expect(annotation.color).toEqual(new Uint8ClampedArray([0, 0, 255]));
|
expect(annotation.color).toEqual(new Uint8ClampedArray([0, 0, 255]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should set and get a CMYK color", function () {
|
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]);
|
annotation.setColor([0.1, 0.92, 0.84, 0.02]);
|
||||||
|
|
||||||
expect(annotation.color).toEqual(new Uint8ClampedArray([234, 59, 48]));
|
expect(annotation.color).toEqual(new Uint8ClampedArray([234, 59, 48]));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not set and get an invalid color", function () {
|
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]);
|
annotation.setColor([0.4, 0.6]);
|
||||||
|
|
||||||
expect(annotation.color).toEqual(new Uint8ClampedArray([0, 0, 0]));
|
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 () {
|
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");
|
markupAnnotation.setCreationDate("D:20190422");
|
||||||
|
|
||||||
expect(markupAnnotation.creationDate).toEqual("D:20190422");
|
expect(markupAnnotation.creationDate).toEqual("D:20190422");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not set and get an invalid creation date", function () {
|
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);
|
markupAnnotation.setCreationDate(undefined);
|
||||||
|
|
||||||
expect(markupAnnotation.creationDate).toEqual(null);
|
expect(markupAnnotation.creationDate).toEqual(null);
|
||||||
|
@ -18,7 +18,9 @@ import {
|
|||||||
parseAppearanceStream,
|
parseAppearanceStream,
|
||||||
parseDefaultAppearance,
|
parseDefaultAppearance,
|
||||||
} from "../../src/core/default_appearance.js";
|
} 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("Default appearance", function () {
|
||||||
describe("parseDefaultAppearance and createDefaultAppearance", function () {
|
describe("parseDefaultAppearance and createDefaultAppearance", function () {
|
||||||
@ -54,6 +56,21 @@ describe("Default appearance", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("parseAppearanceStream", () => {
|
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", () => {
|
it("should parse a FreeText (from Acrobat) appearance", () => {
|
||||||
const appearance = new StringStream(`
|
const appearance = new StringStream(`
|
||||||
0 w
|
0 w
|
||||||
@ -84,7 +101,9 @@ describe("Default appearance", function () {
|
|||||||
fontName: "Helv",
|
fontName: "Helv",
|
||||||
fontColor: new Uint8ClampedArray([107, 217, 41]),
|
fontColor: new Uint8ClampedArray([107, 217, 41]),
|
||||||
};
|
};
|
||||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||||
|
result
|
||||||
|
);
|
||||||
expect(appearance.pos).toEqual(0);
|
expect(appearance.pos).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -103,23 +122,46 @@ describe("Default appearance", function () {
|
|||||||
fontName: "Helv",
|
fontName: "Helv",
|
||||||
fontColor: new Uint8ClampedArray([237, 43, 112]),
|
fontColor: new Uint8ClampedArray([237, 43, 112]),
|
||||||
};
|
};
|
||||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||||
|
result
|
||||||
|
);
|
||||||
expect(appearance.pos).toEqual(0);
|
expect(appearance.pos).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should parse a FreeText (from Preview) appearance", () => {
|
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(`
|
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 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
|
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
|
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
|
(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`);
|
(vi) -0.2 (e) -0.2 (w) ] TJ ET Q Q`);
|
||||||
|
appearance.dict = appearanceDict;
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
fontSize: 22.00539,
|
fontSize: 22.00539,
|
||||||
fontName: "TT1",
|
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);
|
expect(appearance.pos).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -140,7 +182,9 @@ describe("Default appearance", function () {
|
|||||||
fontName: "Helv",
|
fontName: "Helv",
|
||||||
fontColor: new Uint8ClampedArray([16, 124, 16]),
|
fontColor: new Uint8ClampedArray([16, 124, 16]),
|
||||||
};
|
};
|
||||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||||
|
result
|
||||||
|
);
|
||||||
expect(appearance.pos).toEqual(0);
|
expect(appearance.pos).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -164,7 +208,9 @@ describe("Default appearance", function () {
|
|||||||
fontName: "FXF0",
|
fontName: "FXF0",
|
||||||
fontColor: new Uint8ClampedArray([149, 63, 60]),
|
fontColor: new Uint8ClampedArray([149, 63, 60]),
|
||||||
};
|
};
|
||||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||||
|
result
|
||||||
|
);
|
||||||
expect(appearance.pos).toEqual(0);
|
expect(appearance.pos).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -186,7 +232,9 @@ describe("Default appearance", function () {
|
|||||||
fontName: "Invalid_font",
|
fontName: "Invalid_font",
|
||||||
fontColor: new Uint8ClampedArray([0, 85, 127]),
|
fontColor: new Uint8ClampedArray([0, 85, 127]),
|
||||||
};
|
};
|
||||||
expect(parseAppearanceStream(appearance)).toEqual(result);
|
expect(parseAppearanceStream(appearance, evaluatorOptions, xref)).toEqual(
|
||||||
|
result
|
||||||
|
);
|
||||||
expect(appearance.pos).toEqual(0);
|
expect(appearance.pos).toEqual(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user