Skip to content

Commit

Permalink
[Editor] Add support for printing newly added FreeText annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
calixteman authored and pull[bot] committed Aug 28, 2022
1 parent 637ea69 commit 6287a4d
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 79 deletions.
157 changes: 79 additions & 78 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,21 +265,17 @@ class AnnotationFactory {
promises.push(
FreeTextAnnotation.createNewAnnotation(
xref,
evaluator,
task,
annotation,
baseFontRef,
results,
dependencies
dependencies,
{ evaluator, task, baseFontRef }
)
);
break;
case AnnotationEditorType.INK:
promises.push(
InkAnnotation.createNewAnnotation(
xref,
evaluator,
task,
annotation,
results,
dependencies
Expand All @@ -306,11 +302,18 @@ class AnnotationFactory {
for (const annotation of annotations) {
switch (annotation.annotationType) {
case AnnotationEditorType.FREETEXT:
promises.push(
FreeTextAnnotation.createNewPrintAnnotation(xref, annotation, {
evaluator,
task,
})
);
break;
case AnnotationEditorType.INK:
promises.push(
InkAnnotation.createNewPrintAnnotation(annotation, xref)
InkAnnotation.createNewPrintAnnotation(xref, annotation)
);
break;
}
}

Expand Down Expand Up @@ -1356,6 +1359,44 @@ class MarkupAnnotation extends Annotation {
// so `this.appearance` is not pushed yet in the `Annotation` constructor.
this._streams.push(this.appearance, appearanceStream);
}

static async createNewAnnotation(
xref,
annotation,
results,
dependencies,
params
) {
const annotationRef = xref.getNewRef();
const apRef = xref.getNewRef();
const annotationDict = this.createNewDict(annotation, xref, { apRef });
const ap = await this.createNewAppearanceStream(annotation, xref, params);

const buffer = [];
let transform = xref.encrypt
? xref.encrypt.createCipherTransform(apRef.num, apRef.gen)
: null;
writeObject(apRef, ap, buffer, transform);
dependencies.push({ ref: apRef, data: buffer.join("") });

buffer.length = 0;
transform = xref.encrypt
? xref.encrypt.createCipherTransform(annotationRef.num, annotationRef.gen)
: null;
writeObject(annotationRef, annotationDict, buffer, transform);

results.push({ ref: annotationRef, data: buffer.join("") });
}

static async createNewPrintAnnotation(xref, annotation, params) {
const ap = await this.createNewAppearanceStream(annotation, xref, params);
const annotationDict = this.createNewDict(annotation, xref, { ap });

return new this.prototype.constructor({
dict: annotationDict,
xref,
});
}
}

class WidgetAnnotation extends Annotation {
Expand Down Expand Up @@ -3157,17 +3198,8 @@ class FreeTextAnnotation extends MarkupAnnotation {
this.data.annotationType = AnnotationType.FREETEXT;
}

static async createNewAnnotation(
xref,
evaluator,
task,
annotation,
baseFontRef,
results,
dependencies
) {
static createNewDict(annotation, xref, { apRef, ap }) {
const { color, fontSize, rect, user, value } = annotation;
const freetextRef = xref.getNewRef();
const freetext = new Dict(xref);
freetext.set("Type", Name.get("Annot"));
freetext.set("Subtype", Name.get("FreeText"));
Expand All @@ -3184,9 +3216,35 @@ class FreeTextAnnotation extends MarkupAnnotation {
freetext.set("T", stringToUTF8String(user));
}

const n = new Dict(xref);
freetext.set("AP", n);

if (apRef) {
n.set("N", apRef);
} else {
n.set("N", ap);
}

return freetext;
}

static async createNewAppearanceStream(annotation, xref, params) {
const { baseFontRef, evaluator, task } = params;
const { color, fontSize, rect, value } = annotation;

const resources = new Dict(xref);
const font = new Dict(xref);
font.set("Helv", baseFontRef);

if (baseFontRef) {
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"));
font.set("Helv", baseFont);
}
resources.set("Font", font);

const helv = await WidgetAnnotation._getFontData(
Expand Down Expand Up @@ -3260,25 +3318,7 @@ class FreeTextAnnotation extends MarkupAnnotation {
const ap = new StringStream(appearance);
ap.dict = appearanceStreamDict;

buffer.length = 0;
const apRef = xref.getNewRef();
let transform = xref.encrypt
? xref.encrypt.createCipherTransform(apRef.num, apRef.gen)
: null;
writeObject(apRef, ap, buffer, transform);
dependencies.push({ ref: apRef, data: buffer.join("") });

const n = new Dict(xref);
n.set("N", apRef);
freetext.set("AP", n);

buffer.length = 0;
transform = xref.encrypt
? xref.encrypt.createCipherTransform(freetextRef.num, freetextRef.gen)
: null;
writeObject(freetextRef, freetext, buffer, transform);

results.push({ ref: freetextRef, data: buffer.join("") });
return ap;
}
}

Expand Down Expand Up @@ -3642,7 +3682,7 @@ class InkAnnotation extends MarkupAnnotation {
}
}

static createInkDict(annotation, xref, { apRef, ap }) {
static createNewDict(annotation, xref, { apRef, ap }) {
const ink = new Dict(xref);
ink.set("Type", Name.get("Annot"));
ink.set("Subtype", Name.get("Ink"));
Expand All @@ -3668,7 +3708,7 @@ class InkAnnotation extends MarkupAnnotation {
return ink;
}

static createNewAppearanceStream(annotation, xref) {
static async createNewAppearanceStream(annotation, xref, params) {
const [x1, y1, x2, y2] = annotation.rect;
const w = x2 - x1;
const h = y2 - y1;
Expand Down Expand Up @@ -3707,45 +3747,6 @@ class InkAnnotation extends MarkupAnnotation {

return ap;
}

static async createNewAnnotation(
xref,
evaluator,
task,
annotation,
results,
others
) {
const inkRef = xref.getNewRef();
const apRef = xref.getNewRef();
const ink = this.createInkDict(annotation, xref, { apRef });
const ap = this.createNewAppearanceStream(annotation, xref);

const buffer = [];
let transform = xref.encrypt
? xref.encrypt.createCipherTransform(apRef.num, apRef.gen)
: null;
writeObject(apRef, ap, buffer, transform);
others.push({ ref: apRef, data: buffer.join("") });

buffer.length = 0;
transform = xref.encrypt
? xref.encrypt.createCipherTransform(inkRef.num, inkRef.gen)
: null;
writeObject(inkRef, ink, buffer, transform);

results.push({ ref: inkRef, data: buffer.join("") });
}

static async createNewPrintAnnotation(annotation, xref) {
const ap = this.createNewAppearanceStream(annotation, xref);
const ink = this.createInkDict(annotation, xref, { ap });

return new InkAnnotation({
dict: ink,
xref,
});
}
}

class HighlightAnnotation extends MarkupAnnotation {
Expand Down
44 changes: 44 additions & 0 deletions test/unit/annotation_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4069,6 +4069,50 @@ describe("annotation", function () {
"endobj\n"
);
});

it("should render an added FreeText annotation for printing", async function () {
partialEvaluator.xref = new XRefMock();
const task = new WorkerTask("test FreeText printing");
const freetextAnnotation = (
await AnnotationFactory.printNewAnnotations(partialEvaluator, task, [
{
annotationType: AnnotationEditorType.FREETEXT,
rect: [12, 34, 56, 78],
fontSize: 10,
color: [0, 0, 0],
value: "A",
},
])
)[0];

const operatorList = await freetextAnnotation.getOperatorList(
partialEvaluator,
task,
RenderingIntentFlag.PRINT,
false,
null
);

expect(operatorList.fnArray.length).toEqual(16);
expect(operatorList.fnArray).toEqual([
OPS.beginAnnotation,
OPS.save,
OPS.constructPath,
OPS.clip,
OPS.endPath,
OPS.beginText,
OPS.setTextMatrix,
OPS.setCharSpacing,
OPS.setFillRGBColor,
OPS.dependency,
OPS.setFont,
OPS.moveText,
OPS.showText,
OPS.endText,
OPS.restore,
OPS.endAnnotation,
]);
});
});

describe("InkAnnotation", function () {
Expand Down
3 changes: 2 additions & 1 deletion test/unit/test_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
* limitations under the License.
*/

import { NullStream, StringStream } from "../../src/core/stream.js";
import { Page, PDFDocument } from "../../src/core/document.js";
import { assert } from "../../src/shared/util.js";
import { DocStats } from "../../src/core/core_utils.js";
import { isNodeJS } from "../../src/shared/is_node.js";
import { Ref } from "../../src/core/primitives.js";
import { StringStream } from "../../src/core/stream.js";

const TEST_PDFS_PATH = isNodeJS ? "./test/pdfs/" : "../pdfs/";

Expand Down Expand Up @@ -79,6 +79,7 @@ class XRefMock {
this._map = Object.create(null);
this.stats = new DocStats({ send: () => {} });
this._newRefNum = null;
this.stream = new NullStream();

for (const key in array) {
const obj = array[key];
Expand Down

0 comments on commit 6287a4d

Please sign in to comment.