Merge pull request #17304 from calixteman/editor_highlight2
[Editor] Add support for saving/printing a newly added Highlight annotation (bug 1865708)
This commit is contained in:
commit
09ff1b98ee
@ -354,6 +354,15 @@ class AnnotationFactory {
|
||||
)
|
||||
);
|
||||
break;
|
||||
case AnnotationEditorType.HIGHLIGHT:
|
||||
promises.push(
|
||||
HighlightAnnotation.createNewAnnotation(
|
||||
xref,
|
||||
annotation,
|
||||
dependencies
|
||||
)
|
||||
);
|
||||
break;
|
||||
case AnnotationEditorType.INK:
|
||||
promises.push(
|
||||
InkAnnotation.createNewAnnotation(xref, annotation, dependencies)
|
||||
@ -429,6 +438,18 @@ class AnnotationFactory {
|
||||
)
|
||||
);
|
||||
break;
|
||||
case AnnotationEditorType.HIGHLIGHT:
|
||||
promises.push(
|
||||
HighlightAnnotation.createNewPrintAnnotation(
|
||||
annotationGlobals,
|
||||
xref,
|
||||
annotation,
|
||||
{
|
||||
evaluatorOptions: options,
|
||||
}
|
||||
)
|
||||
);
|
||||
break;
|
||||
case AnnotationEditorType.INK:
|
||||
promises.push(
|
||||
InkAnnotation.createNewPrintAnnotation(
|
||||
@ -4432,6 +4453,94 @@ class HighlightAnnotation extends MarkupAnnotation {
|
||||
this.data.popupRef = null;
|
||||
}
|
||||
}
|
||||
|
||||
static createNewDict(annotation, xref, { apRef, ap }) {
|
||||
const { color, opacity, rect, rotation, user, quadPoints } = annotation;
|
||||
const highlight = new Dict(xref);
|
||||
highlight.set("Type", Name.get("Annot"));
|
||||
highlight.set("Subtype", Name.get("Highlight"));
|
||||
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",
|
||||
Array.from(color, c => c / 255)
|
||||
);
|
||||
|
||||
// Opacity.
|
||||
highlight.set("CA", opacity);
|
||||
|
||||
if (user) {
|
||||
highlight.set(
|
||||
"T",
|
||||
isAscii(user) ? user : stringToUTF16String(user, /* bigEndian = */ true)
|
||||
);
|
||||
}
|
||||
|
||||
if (apRef || ap) {
|
||||
const n = new Dict(xref);
|
||||
highlight.set("AP", n);
|
||||
n.set("N", apRef || ap);
|
||||
}
|
||||
|
||||
return highlight;
|
||||
}
|
||||
|
||||
static async createNewAppearanceStream(annotation, xref, params) {
|
||||
const { color, rect, outlines, opacity } = annotation;
|
||||
|
||||
const appearanceBuffer = [
|
||||
`${getPdfColor(color, /* isFill */ true)}`,
|
||||
"/R0 gs",
|
||||
];
|
||||
|
||||
const buffer = [];
|
||||
for (const outline of outlines) {
|
||||
buffer.length = 0;
|
||||
buffer.push(
|
||||
`${numberToString(outline[0])} ${numberToString(outline[1])} m`
|
||||
);
|
||||
for (let i = 2, ii = outline.length; i < ii; i += 2) {
|
||||
buffer.push(
|
||||
`${numberToString(outline[i])} ${numberToString(outline[i + 1])} l`
|
||||
);
|
||||
}
|
||||
buffer.push("h");
|
||||
appearanceBuffer.push(buffer.join("\n"));
|
||||
}
|
||||
appearanceBuffer.push("f*");
|
||||
const appearance = appearanceBuffer.join("\n");
|
||||
|
||||
const appearanceStreamDict = new Dict(xref);
|
||||
appearanceStreamDict.set("FormType", 1);
|
||||
appearanceStreamDict.set("Subtype", Name.get("Form"));
|
||||
appearanceStreamDict.set("Type", Name.get("XObject"));
|
||||
appearanceStreamDict.set("BBox", rect);
|
||||
appearanceStreamDict.set("Length", appearance.length);
|
||||
|
||||
const resources = new Dict(xref);
|
||||
const extGState = new Dict(xref);
|
||||
resources.set("ExtGState", extGState);
|
||||
appearanceStreamDict.set("Resources", resources);
|
||||
const r0 = new Dict(xref);
|
||||
extGState.set("R0", r0);
|
||||
r0.set("BM", Name.get("Multiply"));
|
||||
|
||||
if (opacity !== 1) {
|
||||
r0.set("ca", opacity);
|
||||
r0.set("Type", Name.get("ExtGState"));
|
||||
}
|
||||
|
||||
const ap = new StringStream(appearance);
|
||||
ap.dict = appearanceStreamDict;
|
||||
|
||||
return ap;
|
||||
}
|
||||
}
|
||||
|
||||
class UnderlineAnnotation extends MarkupAnnotation {
|
||||
|
@ -72,6 +72,7 @@ const AnnotationEditorType = {
|
||||
DISABLE: -1,
|
||||
NONE: 0,
|
||||
FREETEXT: 3,
|
||||
HIGHLIGHT: 9,
|
||||
STAMP: 13,
|
||||
INK: 15,
|
||||
};
|
||||
|
@ -8228,5 +8228,138 @@
|
||||
"md5": "71591f11ee717e12887f529c84d5ae89",
|
||||
"rounds": 1,
|
||||
"type": "highlight"
|
||||
},
|
||||
{
|
||||
"id": "tracemonkey-highlight-editor-print",
|
||||
"file": "pdfs/tracemonkey.pdf",
|
||||
"md5": "9a192d8b1a7dc652a19835f6f08098bd",
|
||||
"rounds": 1,
|
||||
"lastPage": 1,
|
||||
"type": "eq",
|
||||
"print": true,
|
||||
"annotationStorage": {
|
||||
"pdfjs_internal_editor_0": {
|
||||
"annotationType": 9,
|
||||
"color": [
|
||||
255,
|
||||
240,
|
||||
102
|
||||
],
|
||||
"opacity": 0.4,
|
||||
"quadPoints": [
|
||||
80.53230785208449,
|
||||
696.385203481336,
|
||||
528.9234102584737,
|
||||
696.385203481336,
|
||||
80.53230785208449,
|
||||
716.3783153330397,
|
||||
528.9234102584737,
|
||||
716.3783153330397,
|
||||
263.70067924380567,
|
||||
676.5056819423341,
|
||||
346.3002317296901,
|
||||
676.5056819423341,
|
||||
263.70067924380567,
|
||||
696.4987937940379,
|
||||
346.3002317296901,
|
||||
696.4987937940379
|
||||
],
|
||||
"outlines": [
|
||||
[
|
||||
79.866,
|
||||
695.5343999999999,
|
||||
79.866,
|
||||
717.2352,
|
||||
529.5636000000001,
|
||||
717.2352,
|
||||
529.5636000000001,
|
||||
695.5343999999999,
|
||||
346.94280000000003,
|
||||
695.5343999999999,
|
||||
346.94280000000003,
|
||||
675.6551999999999,
|
||||
263.0376,
|
||||
675.6551999999999,
|
||||
263.0376,
|
||||
695.5343999999999
|
||||
]
|
||||
],
|
||||
"pageIndex": 0,
|
||||
"rect": [
|
||||
79.866,
|
||||
675.6551999999999,
|
||||
529.5636000000001,
|
||||
717.2352
|
||||
],
|
||||
"rotation": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "tracemonkey-highlight-editor-save-print",
|
||||
"file": "pdfs/tracemonkey.pdf",
|
||||
"md5": "9a192d8b1a7dc652a19835f6f08098bd",
|
||||
"rounds": 1,
|
||||
"lastPage": 1,
|
||||
"type": "eq",
|
||||
"save": true,
|
||||
"print": true,
|
||||
"annotationStorage": {
|
||||
"pdfjs_internal_editor_0": {
|
||||
"annotationType": 9,
|
||||
"color": [
|
||||
249,
|
||||
108,
|
||||
147
|
||||
],
|
||||
"opacity": 0.4,
|
||||
"quadPoints": [
|
||||
80.53230785208449,
|
||||
696.385203481336,
|
||||
528.9234102584737,
|
||||
696.385203481336,
|
||||
80.53230785208449,
|
||||
716.3783153330397,
|
||||
528.9234102584737,
|
||||
716.3783153330397,
|
||||
263.70067924380567,
|
||||
676.5056819423341,
|
||||
346.3002317296901,
|
||||
676.5056819423341,
|
||||
263.70067924380567,
|
||||
696.4987937940379,
|
||||
346.3002317296901,
|
||||
696.4987937940379
|
||||
],
|
||||
"outlines": [
|
||||
[
|
||||
79.866,
|
||||
695.5343999999999,
|
||||
79.866,
|
||||
717.2352,
|
||||
529.5636000000001,
|
||||
717.2352,
|
||||
529.5636000000001,
|
||||
695.5343999999999,
|
||||
346.94280000000003,
|
||||
695.5343999999999,
|
||||
346.94280000000003,
|
||||
675.6551999999999,
|
||||
263.0376,
|
||||
675.6551999999999,
|
||||
263.0376,
|
||||
695.5343999999999
|
||||
]
|
||||
],
|
||||
"pageIndex": 0,
|
||||
"rect": [
|
||||
79.866,
|
||||
675.6551999999999,
|
||||
529.5636000000001,
|
||||
717.2352
|
||||
],
|
||||
"rotation": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -4554,7 +4554,7 @@ describe("annotation", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("HightlightAnnotation", function () {
|
||||
describe("HighlightAnnotation", function () {
|
||||
it("should set quadpoints to null if not defined", async function () {
|
||||
const highlightDict = new Dict();
|
||||
highlightDict.set("Type", Name.get("Annot"));
|
||||
@ -4619,6 +4619,97 @@ describe("annotation", function () {
|
||||
expect(data.annotationType).toEqual(AnnotationType.HIGHLIGHT);
|
||||
expect(data.quadPoints).toEqual(null);
|
||||
});
|
||||
|
||||
it("should create a new Highlight annotation", async function () {
|
||||
partialEvaluator.xref = new XRefMock();
|
||||
const task = new WorkerTask("test Highlight creation");
|
||||
const data = await AnnotationFactory.saveNewAnnotations(
|
||||
partialEvaluator,
|
||||
task,
|
||||
[
|
||||
{
|
||||
annotationType: AnnotationEditorType.HIGHLIGHT,
|
||||
rect: [12, 34, 56, 78],
|
||||
rotation: 0,
|
||||
opacity: 1,
|
||||
color: [0, 0, 0],
|
||||
quadPoints: [1, 2, 3, 4, 5, 6, 7],
|
||||
outlines: [
|
||||
[8, 9, 10, 11],
|
||||
[12, 13, 14, 15],
|
||||
],
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
const base = data.annotations[0].data.replace(/\(D:\d+\)/, "(date)");
|
||||
expect(base).toEqual(
|
||||
"1 0 obj\n" +
|
||||
"<< /Type /Annot /Subtype /Highlight /CreationDate (date) /Rect [12 34 56 78] " +
|
||||
"/F 4 /Border [0 0 0] /Rotate 0 /QuadPoints [1 2 3 4 5 6 7] /C [0 0 0] " +
|
||||
"/CA 1 /AP << /N 2 0 R>>>>\n" +
|
||||
"endobj\n"
|
||||
);
|
||||
|
||||
const appearance = data.dependencies[0].data;
|
||||
expect(appearance).toEqual(
|
||||
"2 0 obj\n" +
|
||||
"<< /FormType 1 /Subtype /Form /Type /XObject /BBox [12 34 56 78] " +
|
||||
"/Length 47 /Resources << /ExtGState << /R0 << /BM /Multiply>>>>>>>> stream\n" +
|
||||
"0 g\n" +
|
||||
"/R0 gs\n" +
|
||||
"8 9 m\n" +
|
||||
"10 11 l\n" +
|
||||
"h\n" +
|
||||
"12 13 m\n" +
|
||||
"14 15 l\n" +
|
||||
"h\n" +
|
||||
"f*\n" +
|
||||
"endstream\n" +
|
||||
"endobj\n"
|
||||
);
|
||||
});
|
||||
|
||||
it("should render a new Highlight annotation for printing", async function () {
|
||||
partialEvaluator.xref = new XRefMock();
|
||||
const task = new WorkerTask("test Highlight printing");
|
||||
const highlightAnnotation = (
|
||||
await AnnotationFactory.printNewAnnotations(
|
||||
annotationGlobalsMock,
|
||||
partialEvaluator,
|
||||
task,
|
||||
[
|
||||
{
|
||||
annotationType: AnnotationEditorType.HIGHLIGHT,
|
||||
rect: [12, 34, 56, 78],
|
||||
rotation: 0,
|
||||
opacity: 0.5,
|
||||
color: [0, 255, 0],
|
||||
quadPoints: [1, 2, 3, 4, 5, 6, 7],
|
||||
outlines: [[8, 9, 10, 11]],
|
||||
},
|
||||
]
|
||||
)
|
||||
)[0];
|
||||
|
||||
const { opList } = await highlightAnnotation.getOperatorList(
|
||||
partialEvaluator,
|
||||
task,
|
||||
RenderingIntentFlag.PRINT,
|
||||
false,
|
||||
null
|
||||
);
|
||||
|
||||
expect(opList.argsArray.length).toEqual(6);
|
||||
expect(opList.fnArray).toEqual([
|
||||
OPS.beginAnnotation,
|
||||
OPS.setFillRGBColor,
|
||||
OPS.setGState,
|
||||
OPS.constructPath,
|
||||
OPS.eoFill,
|
||||
OPS.endAnnotation,
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("UnderlineAnnotation", function () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user