|
|
|
|
@ -361,10 +361,10 @@ class AnnotationFactory {
|
|
|
|
|
case AnnotationEditorType.FREETEXT:
|
|
|
|
|
if (!baseFontRef) {
|
|
|
|
|
const baseFont = new Dict(xref);
|
|
|
|
|
baseFont.set("BaseFont", Name.get("Helvetica"));
|
|
|
|
|
baseFont.set("Type", Name.get("Font"));
|
|
|
|
|
baseFont.set("Subtype", Name.get("Type1"));
|
|
|
|
|
baseFont.set("Encoding", Name.get("WinAnsiEncoding"));
|
|
|
|
|
baseFont.setIfName("BaseFont", "Helvetica");
|
|
|
|
|
baseFont.setIfName("Type", "Font");
|
|
|
|
|
baseFont.setIfName("Subtype", "Type1");
|
|
|
|
|
baseFont.setIfName("Encoding", "WinAnsiEncoding");
|
|
|
|
|
baseFontRef = xref.getNewTemporaryRef();
|
|
|
|
|
changes.put(baseFontRef, {
|
|
|
|
|
data: baseFont,
|
|
|
|
|
@ -571,8 +571,8 @@ function getRgbColor(color, defaultColor = new Uint8ClampedArray(3)) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getPdfColorArray(color) {
|
|
|
|
|
return Array.from(color, c => c / 255);
|
|
|
|
|
function getPdfColorArray(color, defaultValue = null) {
|
|
|
|
|
return (color && Array.from(color, c => c / 255)) || defaultValue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function getQuadPoints(dict, rect) {
|
|
|
|
|
@ -1741,7 +1741,7 @@ class MarkupAnnotation extends Annotation {
|
|
|
|
|
|
|
|
|
|
const formDict = new Dict(xref);
|
|
|
|
|
const appearanceStreamDict = new Dict(xref);
|
|
|
|
|
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceStreamDict.setIfName("Subtype", "Form");
|
|
|
|
|
|
|
|
|
|
const appearanceStream = new StringStream(buffer.join(" "));
|
|
|
|
|
appearanceStream.dict = appearanceStreamDict;
|
|
|
|
|
@ -1749,14 +1749,10 @@ class MarkupAnnotation extends Annotation {
|
|
|
|
|
|
|
|
|
|
const gsDict = new Dict(xref);
|
|
|
|
|
if (blendMode) {
|
|
|
|
|
gsDict.set("BM", Name.get(blendMode));
|
|
|
|
|
}
|
|
|
|
|
if (typeof strokeAlpha === "number") {
|
|
|
|
|
gsDict.set("CA", strokeAlpha);
|
|
|
|
|
}
|
|
|
|
|
if (typeof fillAlpha === "number") {
|
|
|
|
|
gsDict.set("ca", fillAlpha);
|
|
|
|
|
gsDict.setIfName("BM", blendMode);
|
|
|
|
|
}
|
|
|
|
|
gsDict.setIfNumber("CA", strokeAlpha);
|
|
|
|
|
gsDict.setIfNumber("ca", fillAlpha);
|
|
|
|
|
|
|
|
|
|
const stateDict = new Dict(xref);
|
|
|
|
|
stateDict.set("GS0", gsDict);
|
|
|
|
|
@ -2107,12 +2103,8 @@ class WidgetAnnotation extends Annotation {
|
|
|
|
|
if (rotation) {
|
|
|
|
|
mk.set("R", rotation);
|
|
|
|
|
}
|
|
|
|
|
if (this.borderColor) {
|
|
|
|
|
mk.set("BC", getPdfColorArray(this.borderColor));
|
|
|
|
|
}
|
|
|
|
|
if (this.backgroundColor) {
|
|
|
|
|
mk.set("BG", getPdfColorArray(this.backgroundColor));
|
|
|
|
|
}
|
|
|
|
|
mk.setIfArray("BC", getPdfColorArray(this.borderColor));
|
|
|
|
|
mk.setIfArray("BG", getPdfColorArray(this.backgroundColor));
|
|
|
|
|
return mk.size > 0 ? mk : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -2248,7 +2240,7 @@ class WidgetAnnotation extends Annotation {
|
|
|
|
|
const resources = this._getSaveFieldResources(xref);
|
|
|
|
|
const appearanceStream = new StringStream(appearance);
|
|
|
|
|
const appearanceDict = (appearanceStream.dict = new Dict(xref));
|
|
|
|
|
appearanceDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceDict.setIfName("Subtype", "Form");
|
|
|
|
|
appearanceDict.set("Resources", resources);
|
|
|
|
|
const bbox =
|
|
|
|
|
rotation % 180 === 0
|
|
|
|
|
@ -3272,8 +3264,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|
|
|
|
|
|
|
|
|
const appearanceStreamDict = new Dict(params.xref);
|
|
|
|
|
appearanceStreamDict.set("FormType", 1);
|
|
|
|
|
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceStreamDict.set("Type", Name.get("XObject"));
|
|
|
|
|
appearanceStreamDict.setIfName("Subtype", "Form");
|
|
|
|
|
appearanceStreamDict.setIfName("Type", "XObject");
|
|
|
|
|
appearanceStreamDict.set("BBox", bbox);
|
|
|
|
|
appearanceStreamDict.set("Matrix", [1, 0, 0, 1, 0, 0]);
|
|
|
|
|
appearanceStreamDict.set("Length", appearance.length);
|
|
|
|
|
@ -3460,10 +3452,10 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|
|
|
|
|
|
|
|
|
get fallbackFontDict() {
|
|
|
|
|
const dict = new Dict();
|
|
|
|
|
dict.set("BaseFont", Name.get("ZapfDingbats"));
|
|
|
|
|
dict.set("Type", Name.get("FallbackType"));
|
|
|
|
|
dict.set("Subtype", Name.get("FallbackType"));
|
|
|
|
|
dict.set("Encoding", Name.get("ZapfDingbatsEncoding"));
|
|
|
|
|
dict.setIfName("BaseFont", "ZapfDingbats");
|
|
|
|
|
dict.setIfName("Type", "FallbackType");
|
|
|
|
|
dict.setIfName("Subtype", "FallbackType");
|
|
|
|
|
dict.setIfName("Encoding", "ZapfDingbatsEncoding");
|
|
|
|
|
|
|
|
|
|
return shadow(this, "fallbackFontDict", dict);
|
|
|
|
|
}
|
|
|
|
|
@ -3958,8 +3950,8 @@ class FreeTextAnnotation extends MarkupAnnotation {
|
|
|
|
|
const { color, fontSize, oldAnnotation, rect, rotation, user, value } =
|
|
|
|
|
annotation;
|
|
|
|
|
const freetext = oldAnnotation || new Dict(xref);
|
|
|
|
|
freetext.set("Type", Name.get("Annot"));
|
|
|
|
|
freetext.set("Subtype", Name.get("FreeText"));
|
|
|
|
|
freetext.setIfNotExists("Type", Name.get("Annot"));
|
|
|
|
|
freetext.setIfNotExists("Subtype", Name.get("FreeText"));
|
|
|
|
|
if (oldAnnotation) {
|
|
|
|
|
freetext.set("M", `D:${getModificationDate()}`);
|
|
|
|
|
// TODO: We should try to generate a new RC from the content we've.
|
|
|
|
|
@ -3968,27 +3960,19 @@ class FreeTextAnnotation extends MarkupAnnotation {
|
|
|
|
|
} else {
|
|
|
|
|
freetext.set("CreationDate", `D:${getModificationDate()}`);
|
|
|
|
|
}
|
|
|
|
|
freetext.set("Rect", rect);
|
|
|
|
|
freetext.setIfArray("Rect", rect);
|
|
|
|
|
const da = `/Helv ${fontSize} Tf ${getPdfColor(color, /* isFill */ true)}`;
|
|
|
|
|
freetext.set("DA", da);
|
|
|
|
|
freetext.set("Contents", stringToAsciiOrUTF16BE(value));
|
|
|
|
|
freetext.set("F", 4);
|
|
|
|
|
freetext.set("Border", [0, 0, 0]);
|
|
|
|
|
freetext.set("Rotate", rotation);
|
|
|
|
|
|
|
|
|
|
if (user) {
|
|
|
|
|
freetext.set("T", stringToAsciiOrUTF16BE(user));
|
|
|
|
|
}
|
|
|
|
|
freetext.setIfDefined("Contents", stringToAsciiOrUTF16BE(value));
|
|
|
|
|
freetext.setIfNotExists("F", 4);
|
|
|
|
|
freetext.setIfNotExists("Border", [0, 0, 0]);
|
|
|
|
|
freetext.setIfNumber("Rotate", rotation);
|
|
|
|
|
freetext.setIfDefined("T", stringToAsciiOrUTF16BE(user));
|
|
|
|
|
|
|
|
|
|
if (apRef || ap) {
|
|
|
|
|
const n = new Dict(xref);
|
|
|
|
|
freetext.set("AP", n);
|
|
|
|
|
|
|
|
|
|
if (apRef) {
|
|
|
|
|
n.set("N", apRef);
|
|
|
|
|
} else {
|
|
|
|
|
n.set("N", ap);
|
|
|
|
|
}
|
|
|
|
|
n.set("N", apRef || ap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return freetext;
|
|
|
|
|
@ -3997,6 +3981,9 @@ class FreeTextAnnotation extends MarkupAnnotation {
|
|
|
|
|
static async createNewAppearanceStream(annotation, xref, params) {
|
|
|
|
|
const { baseFontRef, evaluator, task } = params;
|
|
|
|
|
const { color, fontSize, rect, rotation, value } = annotation;
|
|
|
|
|
if (!color) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const resources = new Dict(xref);
|
|
|
|
|
const font = new Dict(xref);
|
|
|
|
|
@ -4005,10 +3992,10 @@ class FreeTextAnnotation extends MarkupAnnotation {
|
|
|
|
|
font.set("Helv", baseFontRef);
|
|
|
|
|
} else {
|
|
|
|
|
const baseFont = new Dict(xref);
|
|
|
|
|
baseFont.set("BaseFont", Name.get("Helvetica"));
|
|
|
|
|
baseFont.set("Type", Name.get("Font"));
|
|
|
|
|
baseFont.set("Subtype", Name.get("Type1"));
|
|
|
|
|
baseFont.set("Encoding", Name.get("WinAnsiEncoding"));
|
|
|
|
|
baseFont.setIfName("BaseFont", "Helvetica");
|
|
|
|
|
baseFont.setIfName("Type", "Font");
|
|
|
|
|
baseFont.setIfName("Subtype", "Type1");
|
|
|
|
|
baseFont.setIfName("Encoding", "WinAnsiEncoding");
|
|
|
|
|
font.set("Helv", baseFont);
|
|
|
|
|
}
|
|
|
|
|
resources.set("Font", font);
|
|
|
|
|
@ -4110,8 +4097,8 @@ class FreeTextAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
const appearanceStreamDict = new Dict(xref);
|
|
|
|
|
appearanceStreamDict.set("FormType", 1);
|
|
|
|
|
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceStreamDict.set("Type", Name.get("XObject"));
|
|
|
|
|
appearanceStreamDict.setIfName("Subtype", "Form");
|
|
|
|
|
appearanceStreamDict.setIfName("Type", "XObject");
|
|
|
|
|
appearanceStreamDict.set("BBox", rect);
|
|
|
|
|
appearanceStreamDict.set("Resources", resources);
|
|
|
|
|
appearanceStreamDict.set("Matrix", [1, 0, 0, 1, -rect[0], -rect[1]]);
|
|
|
|
|
@ -4142,13 +4129,13 @@ class LineAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
if (!this.appearance) {
|
|
|
|
|
// The default stroke color is black.
|
|
|
|
|
const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
|
|
|
|
|
const strokeColor = getPdfColorArray(this.color, [0, 0, 0]);
|
|
|
|
|
const strokeAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
const interiorColor = getRgbColor(dict.getArray("IC"), null);
|
|
|
|
|
// The default fill color is transparent. Setting the fill colour is
|
|
|
|
|
// necessary if/when we want to add support for non-default line endings.
|
|
|
|
|
const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;
|
|
|
|
|
const fillColor = getPdfColorArray(interiorColor);
|
|
|
|
|
const fillAlpha = fillColor ? strokeAlpha : null;
|
|
|
|
|
|
|
|
|
|
const borderWidth = this.borderStyle.width || 1,
|
|
|
|
|
@ -4202,12 +4189,12 @@ class SquareAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
if (!this.appearance) {
|
|
|
|
|
// The default stroke color is black.
|
|
|
|
|
const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
|
|
|
|
|
const strokeColor = getPdfColorArray(this.color, [0, 0, 0]);
|
|
|
|
|
const strokeAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
const interiorColor = getRgbColor(dict.getArray("IC"), null);
|
|
|
|
|
// The default fill color is transparent.
|
|
|
|
|
const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;
|
|
|
|
|
const fillColor = getPdfColorArray(interiorColor);
|
|
|
|
|
const fillAlpha = fillColor ? strokeAlpha : null;
|
|
|
|
|
|
|
|
|
|
if (this.borderStyle.width === 0 && !fillColor) {
|
|
|
|
|
@ -4249,12 +4236,12 @@ class CircleAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
if (!this.appearance) {
|
|
|
|
|
// The default stroke color is black.
|
|
|
|
|
const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
|
|
|
|
|
const strokeColor = getPdfColorArray(this.color, [0, 0, 0]);
|
|
|
|
|
const strokeAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
const interiorColor = getRgbColor(dict.getArray("IC"), null);
|
|
|
|
|
// The default fill color is transparent.
|
|
|
|
|
const fillColor = interiorColor ? getPdfColorArray(interiorColor) : null;
|
|
|
|
|
const fillColor = getPdfColorArray(interiorColor);
|
|
|
|
|
const fillAlpha = fillColor ? strokeAlpha : null;
|
|
|
|
|
|
|
|
|
|
if (this.borderStyle.width === 0 && !fillColor) {
|
|
|
|
|
@ -4334,7 +4321,7 @@ class PolylineAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
if (!this.appearance) {
|
|
|
|
|
// The default stroke color is black.
|
|
|
|
|
const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
|
|
|
|
|
const strokeColor = getPdfColorArray(this.color, [0, 0, 0]);
|
|
|
|
|
const strokeAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
let fillColor = getRgbColor(dict.getArray("IC"), null);
|
|
|
|
|
@ -4453,7 +4440,7 @@ class InkAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
if (!this.appearance) {
|
|
|
|
|
// The default stroke color is black.
|
|
|
|
|
const strokeColor = this.color ? getPdfColorArray(this.color) : [0, 0, 0];
|
|
|
|
|
const strokeColor = getPdfColorArray(this.color, [0, 0, 0]);
|
|
|
|
|
const strokeAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
const borderWidth = this.borderStyle.width || 1,
|
|
|
|
|
@ -4514,44 +4501,40 @@ class InkAnnotation extends MarkupAnnotation {
|
|
|
|
|
user,
|
|
|
|
|
} = annotation;
|
|
|
|
|
const ink = oldAnnotation || new Dict(xref);
|
|
|
|
|
ink.set("Type", Name.get("Annot"));
|
|
|
|
|
ink.set("Subtype", Name.get("Ink"));
|
|
|
|
|
ink.setIfNotExists("Type", Name.get("Annot"));
|
|
|
|
|
ink.setIfNotExists("Subtype", Name.get("Ink"));
|
|
|
|
|
ink.set(oldAnnotation ? "M" : "CreationDate", `D:${getModificationDate()}`);
|
|
|
|
|
ink.set("Rect", rect);
|
|
|
|
|
ink.set("InkList", outlines?.points || paths.points);
|
|
|
|
|
ink.set("F", 4);
|
|
|
|
|
ink.set("Rotate", rotation);
|
|
|
|
|
|
|
|
|
|
if (user) {
|
|
|
|
|
ink.set("T", stringToAsciiOrUTF16BE(user));
|
|
|
|
|
}
|
|
|
|
|
ink.setIfArray("Rect", rect);
|
|
|
|
|
ink.setIfArray("InkList", outlines?.points || paths?.points);
|
|
|
|
|
ink.setIfNotExists("F", 4);
|
|
|
|
|
ink.setIfNumber("Rotate", rotation);
|
|
|
|
|
ink.setIfDefined("T", stringToAsciiOrUTF16BE(user));
|
|
|
|
|
|
|
|
|
|
if (outlines) {
|
|
|
|
|
// Free highlight.
|
|
|
|
|
// There's nothing about this in the spec, but it's used when highlighting
|
|
|
|
|
// in Edge's viewer. Acrobat takes into account this parameter to indicate
|
|
|
|
|
// that the Ink is used for highlighting.
|
|
|
|
|
ink.set("IT", Name.get("InkHighlight"));
|
|
|
|
|
ink.setIfName("IT", "InkHighlight");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Line thickness.
|
|
|
|
|
const bs = new Dict(xref);
|
|
|
|
|
ink.set("BS", bs);
|
|
|
|
|
bs.set("W", thickness);
|
|
|
|
|
if (thickness > 0) {
|
|
|
|
|
const bs = new Dict(xref);
|
|
|
|
|
ink.set("BS", bs);
|
|
|
|
|
bs.set("W", thickness);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Color.
|
|
|
|
|
ink.set("C", getPdfColorArray(color));
|
|
|
|
|
ink.setIfArray("C", getPdfColorArray(color));
|
|
|
|
|
|
|
|
|
|
// Opacity.
|
|
|
|
|
ink.set("CA", opacity);
|
|
|
|
|
ink.setIfNumber("CA", opacity);
|
|
|
|
|
|
|
|
|
|
const n = new Dict(xref);
|
|
|
|
|
ink.set("AP", n);
|
|
|
|
|
|
|
|
|
|
if (apRef) {
|
|
|
|
|
n.set("N", apRef);
|
|
|
|
|
} else {
|
|
|
|
|
n.set("N", ap);
|
|
|
|
|
if (ap || apRef) {
|
|
|
|
|
const n = new Dict(xref);
|
|
|
|
|
ink.set("AP", n);
|
|
|
|
|
n.set("N", apRef || ap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ink;
|
|
|
|
|
@ -4566,6 +4549,9 @@ class InkAnnotation extends MarkupAnnotation {
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
const { color, rect, paths, thickness, opacity } = annotation;
|
|
|
|
|
if (!color) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const appearanceBuffer = [
|
|
|
|
|
`${thickness} w 1 J 1 j`,
|
|
|
|
|
@ -4606,8 +4592,8 @@ class InkAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
const appearanceStreamDict = new Dict(xref);
|
|
|
|
|
appearanceStreamDict.set("FormType", 1);
|
|
|
|
|
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceStreamDict.set("Type", Name.get("XObject"));
|
|
|
|
|
appearanceStreamDict.setIfName("Subtype", "Form");
|
|
|
|
|
appearanceStreamDict.setIfName("Type", "XObject");
|
|
|
|
|
appearanceStreamDict.set("BBox", rect);
|
|
|
|
|
appearanceStreamDict.set("Length", appearance.length);
|
|
|
|
|
|
|
|
|
|
@ -4616,7 +4602,7 @@ class InkAnnotation extends MarkupAnnotation {
|
|
|
|
|
const extGState = new Dict(xref);
|
|
|
|
|
const r0 = new Dict(xref);
|
|
|
|
|
r0.set("CA", opacity);
|
|
|
|
|
r0.set("Type", Name.get("ExtGState"));
|
|
|
|
|
r0.setIfName("Type", "ExtGState");
|
|
|
|
|
extGState.set("R0", r0);
|
|
|
|
|
resources.set("ExtGState", extGState);
|
|
|
|
|
appearanceStreamDict.set("Resources", resources);
|
|
|
|
|
@ -4635,6 +4621,9 @@ class InkAnnotation extends MarkupAnnotation {
|
|
|
|
|
outlines: { outline },
|
|
|
|
|
opacity,
|
|
|
|
|
} = annotation;
|
|
|
|
|
if (!color) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
const appearanceBuffer = [
|
|
|
|
|
`${getPdfColor(color, /* isFill */ true)}`,
|
|
|
|
|
"/R0 gs",
|
|
|
|
|
@ -4662,8 +4651,8 @@ class InkAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
const appearanceStreamDict = new Dict(xref);
|
|
|
|
|
appearanceStreamDict.set("FormType", 1);
|
|
|
|
|
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceStreamDict.set("Type", Name.get("XObject"));
|
|
|
|
|
appearanceStreamDict.setIfName("Subtype", "Form");
|
|
|
|
|
appearanceStreamDict.setIfName("Type", "XObject");
|
|
|
|
|
appearanceStreamDict.set("BBox", rect);
|
|
|
|
|
appearanceStreamDict.set("Length", appearance.length);
|
|
|
|
|
|
|
|
|
|
@ -4673,11 +4662,11 @@ class InkAnnotation extends MarkupAnnotation {
|
|
|
|
|
appearanceStreamDict.set("Resources", resources);
|
|
|
|
|
const r0 = new Dict(xref);
|
|
|
|
|
extGState.set("R0", r0);
|
|
|
|
|
r0.set("BM", Name.get("Multiply"));
|
|
|
|
|
r0.setIfName("BM", "Multiply");
|
|
|
|
|
|
|
|
|
|
if (opacity !== 1) {
|
|
|
|
|
r0.set("ca", opacity);
|
|
|
|
|
r0.set("Type", Name.get("ExtGState"));
|
|
|
|
|
r0.setIfName("Type", "ExtGState");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ap = new StringStream(appearance);
|
|
|
|
|
@ -4711,7 +4700,7 @@ class HighlightAnnotation extends MarkupAnnotation {
|
|
|
|
|
warn("HighlightAnnotation - ignoring built-in appearance stream.");
|
|
|
|
|
}
|
|
|
|
|
// Default color is yellow in Acrobat Reader
|
|
|
|
|
const fillColor = this.color ? getPdfColorArray(this.color) : [1, 1, 0];
|
|
|
|
|
const fillColor = getPdfColorArray(this.color, [1, 1, 0]);
|
|
|
|
|
const fillAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
this._setDefaultAppearance({
|
|
|
|
|
@ -4743,29 +4732,19 @@ class HighlightAnnotation extends MarkupAnnotation {
|
|
|
|
|
static createNewDict(annotation, xref, { apRef, ap }) {
|
|
|
|
|
const { color, oldAnnotation, opacity, rect, rotation, user, quadPoints } =
|
|
|
|
|
annotation;
|
|
|
|
|
const date = `D:${getModificationDate()}`;
|
|
|
|
|
const highlight = oldAnnotation || new Dict(xref);
|
|
|
|
|
highlight.set("Type", Name.get("Annot"));
|
|
|
|
|
highlight.set("Subtype", Name.get("Highlight"));
|
|
|
|
|
highlight.set(
|
|
|
|
|
oldAnnotation ? "M" : "CreationDate",
|
|
|
|
|
`D:${getModificationDate()}`
|
|
|
|
|
);
|
|
|
|
|
highlight.set("CreationDate", `D:${getModificationDate()}`);
|
|
|
|
|
highlight.set("Rect", rect);
|
|
|
|
|
highlight.set("F", 4);
|
|
|
|
|
highlight.set("Border", [0, 0, 0]);
|
|
|
|
|
highlight.set("Rotate", rotation);
|
|
|
|
|
highlight.set("QuadPoints", quadPoints);
|
|
|
|
|
|
|
|
|
|
// Color.
|
|
|
|
|
highlight.set("C", getPdfColorArray(color));
|
|
|
|
|
|
|
|
|
|
// Opacity.
|
|
|
|
|
highlight.set("CA", opacity);
|
|
|
|
|
|
|
|
|
|
if (user) {
|
|
|
|
|
highlight.set("T", stringToAsciiOrUTF16BE(user));
|
|
|
|
|
}
|
|
|
|
|
highlight.setIfNotExists("Type", Name.get("Annot"));
|
|
|
|
|
highlight.setIfNotExists("Subtype", Name.get("Highlight"));
|
|
|
|
|
highlight.set(oldAnnotation ? "M" : "CreationDate", date);
|
|
|
|
|
highlight.setIfArray("Rect", rect);
|
|
|
|
|
highlight.setIfNotExists("F", 4);
|
|
|
|
|
highlight.setIfNotExists("Border", [0, 0, 0]);
|
|
|
|
|
highlight.setIfNumber("Rotate", rotation);
|
|
|
|
|
highlight.setIfArray("QuadPoints", quadPoints);
|
|
|
|
|
highlight.setIfArray("C", getPdfColorArray(color));
|
|
|
|
|
highlight.setIfNumber("CA", opacity);
|
|
|
|
|
highlight.setIfDefined("T", stringToAsciiOrUTF16BE(user));
|
|
|
|
|
|
|
|
|
|
if (apRef || ap) {
|
|
|
|
|
const n = new Dict(xref);
|
|
|
|
|
@ -4778,6 +4757,9 @@ class HighlightAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
static async createNewAppearanceStream(annotation, xref, params) {
|
|
|
|
|
const { color, rect, outlines, opacity } = annotation;
|
|
|
|
|
if (!color) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const appearanceBuffer = [
|
|
|
|
|
`${getPdfColor(color, /* isFill */ true)}`,
|
|
|
|
|
@ -4803,8 +4785,8 @@ class HighlightAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
const appearanceStreamDict = new Dict(xref);
|
|
|
|
|
appearanceStreamDict.set("FormType", 1);
|
|
|
|
|
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceStreamDict.set("Type", Name.get("XObject"));
|
|
|
|
|
appearanceStreamDict.setIfName("Subtype", "Form");
|
|
|
|
|
appearanceStreamDict.setIfName("Type", "XObject");
|
|
|
|
|
appearanceStreamDict.set("BBox", rect);
|
|
|
|
|
appearanceStreamDict.set("Length", appearance.length);
|
|
|
|
|
|
|
|
|
|
@ -4814,11 +4796,11 @@ class HighlightAnnotation extends MarkupAnnotation {
|
|
|
|
|
appearanceStreamDict.set("Resources", resources);
|
|
|
|
|
const r0 = new Dict(xref);
|
|
|
|
|
extGState.set("R0", r0);
|
|
|
|
|
r0.set("BM", Name.get("Multiply"));
|
|
|
|
|
r0.setIfName("BM", "Multiply");
|
|
|
|
|
|
|
|
|
|
if (opacity !== 1) {
|
|
|
|
|
r0.set("ca", opacity);
|
|
|
|
|
r0.set("Type", Name.get("ExtGState"));
|
|
|
|
|
r0.setIfName("Type", "ExtGState");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const ap = new StringStream(appearance);
|
|
|
|
|
@ -4839,9 +4821,7 @@ class UnderlineAnnotation extends MarkupAnnotation {
|
|
|
|
|
if (quadPoints) {
|
|
|
|
|
if (!this.appearance) {
|
|
|
|
|
// Default color is black
|
|
|
|
|
const strokeColor = this.color
|
|
|
|
|
? getPdfColorArray(this.color)
|
|
|
|
|
: [0, 0, 0];
|
|
|
|
|
const strokeColor = getPdfColorArray(this.color, [0, 0, 0]);
|
|
|
|
|
const strokeAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
// The values 0.571 and 1.3 below corresponds to what Acrobat is doing.
|
|
|
|
|
@ -4881,9 +4861,7 @@ class SquigglyAnnotation extends MarkupAnnotation {
|
|
|
|
|
if (quadPoints) {
|
|
|
|
|
if (!this.appearance) {
|
|
|
|
|
// Default color is black
|
|
|
|
|
const strokeColor = this.color
|
|
|
|
|
? getPdfColorArray(this.color)
|
|
|
|
|
: [0, 0, 0];
|
|
|
|
|
const strokeColor = getPdfColorArray(this.color, [0, 0, 0]);
|
|
|
|
|
const strokeAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
this._setDefaultAppearance({
|
|
|
|
|
@ -4929,9 +4907,7 @@ class StrikeOutAnnotation extends MarkupAnnotation {
|
|
|
|
|
if (quadPoints) {
|
|
|
|
|
if (!this.appearance) {
|
|
|
|
|
// Default color is black
|
|
|
|
|
const strokeColor = this.color
|
|
|
|
|
? getPdfColorArray(this.color)
|
|
|
|
|
: [0, 0, 0];
|
|
|
|
|
const strokeColor = getPdfColorArray(this.color, [0, 0, 0]);
|
|
|
|
|
const strokeAlpha = dict.get("CA");
|
|
|
|
|
|
|
|
|
|
this._setDefaultAppearance({
|
|
|
|
|
@ -5030,8 +5006,8 @@ class StampAnnotation extends MarkupAnnotation {
|
|
|
|
|
image.set("Type", xobjectName);
|
|
|
|
|
image.set("Subtype", imageName);
|
|
|
|
|
image.set("BitsPerComponent", 8);
|
|
|
|
|
image.set("ColorSpace", Name.get("DeviceRGB"));
|
|
|
|
|
image.set("Filter", Name.get("DCTDecode"));
|
|
|
|
|
image.setIfName("ColorSpace", "DeviceRGB");
|
|
|
|
|
image.setIfName("Filter", "DCTDecode");
|
|
|
|
|
image.set("BBox", [0, 0, width, height]);
|
|
|
|
|
image.set("Width", width);
|
|
|
|
|
image.set("Height", height);
|
|
|
|
|
@ -5053,7 +5029,7 @@ class StampAnnotation extends MarkupAnnotation {
|
|
|
|
|
smask.set("Type", xobjectName);
|
|
|
|
|
smask.set("Subtype", imageName);
|
|
|
|
|
smask.set("BitsPerComponent", 8);
|
|
|
|
|
smask.set("ColorSpace", Name.get("DeviceGray"));
|
|
|
|
|
smask.setIfName("ColorSpace", "DeviceGray");
|
|
|
|
|
smask.set("Width", width);
|
|
|
|
|
smask.set("Height", height);
|
|
|
|
|
|
|
|
|
|
@ -5071,31 +5047,21 @@ class StampAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
static createNewDict(annotation, xref, { apRef, ap }) {
|
|
|
|
|
const { oldAnnotation, rect, rotation, user } = annotation;
|
|
|
|
|
const date = `D:${getModificationDate(annotation.date)}`;
|
|
|
|
|
const stamp = oldAnnotation || new Dict(xref);
|
|
|
|
|
stamp.set("Type", Name.get("Annot"));
|
|
|
|
|
stamp.set("Subtype", Name.get("Stamp"));
|
|
|
|
|
stamp.set(
|
|
|
|
|
oldAnnotation ? "M" : "CreationDate",
|
|
|
|
|
`D:${getModificationDate()}`
|
|
|
|
|
);
|
|
|
|
|
stamp.set("Rect", rect);
|
|
|
|
|
stamp.set("F", 4);
|
|
|
|
|
stamp.set("Border", [0, 0, 0]);
|
|
|
|
|
stamp.set("Rotate", rotation);
|
|
|
|
|
|
|
|
|
|
if (user) {
|
|
|
|
|
stamp.set("T", stringToAsciiOrUTF16BE(user));
|
|
|
|
|
}
|
|
|
|
|
stamp.setIfNotExists("Type", Name.get("Annot"));
|
|
|
|
|
stamp.setIfNotExists("Subtype", Name.get("Stamp"));
|
|
|
|
|
stamp.set(oldAnnotation ? "M" : "CreationDate", date);
|
|
|
|
|
stamp.setIfArray("Rect", rect);
|
|
|
|
|
stamp.setIfNotExists("F", 4);
|
|
|
|
|
stamp.setIfNotExists("Border", [0, 0, 0]);
|
|
|
|
|
stamp.setIfNumber("Rotate", rotation);
|
|
|
|
|
stamp.setIfDefined("T", stringToAsciiOrUTF16BE(user));
|
|
|
|
|
|
|
|
|
|
if (apRef || ap) {
|
|
|
|
|
const n = new Dict(xref);
|
|
|
|
|
stamp.set("AP", n);
|
|
|
|
|
|
|
|
|
|
if (apRef) {
|
|
|
|
|
n.set("N", apRef);
|
|
|
|
|
} else {
|
|
|
|
|
n.set("N", ap);
|
|
|
|
|
}
|
|
|
|
|
n.set("N", apRef || ap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stamp;
|
|
|
|
|
@ -5103,6 +5069,9 @@ class StampAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
static async #createNewAppearanceStreamForDrawing(annotation, xref) {
|
|
|
|
|
const { areContours, color, rect, lines, thickness } = annotation;
|
|
|
|
|
if (!color) {
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const appearanceBuffer = [
|
|
|
|
|
`${thickness} w 1 J 1 j`,
|
|
|
|
|
@ -5137,8 +5106,8 @@ class StampAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
const appearanceStreamDict = new Dict(xref);
|
|
|
|
|
appearanceStreamDict.set("FormType", 1);
|
|
|
|
|
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceStreamDict.set("Type", Name.get("XObject"));
|
|
|
|
|
appearanceStreamDict.setIfName("Subtype", "Form");
|
|
|
|
|
appearanceStreamDict.setIfName("Type", "XObject");
|
|
|
|
|
appearanceStreamDict.set("BBox", rect);
|
|
|
|
|
appearanceStreamDict.set("Length", appearance.length);
|
|
|
|
|
|
|
|
|
|
@ -5167,8 +5136,8 @@ class StampAnnotation extends MarkupAnnotation {
|
|
|
|
|
|
|
|
|
|
const appearanceStreamDict = new Dict(xref);
|
|
|
|
|
appearanceStreamDict.set("FormType", 1);
|
|
|
|
|
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
|
|
|
|
appearanceStreamDict.set("Type", Name.get("XObject"));
|
|
|
|
|
appearanceStreamDict.setIfName("Subtype", "Form");
|
|
|
|
|
appearanceStreamDict.setIfName("Type", "XObject");
|
|
|
|
|
appearanceStreamDict.set("BBox", [0, 0, width, height]);
|
|
|
|
|
appearanceStreamDict.set("Resources", resources);
|
|
|
|
|
|
|
|
|
|
|