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;
|
break;
|
||||||
|
case AnnotationEditorType.HIGHLIGHT:
|
||||||
|
promises.push(
|
||||||
|
HighlightAnnotation.createNewAnnotation(
|
||||||
|
xref,
|
||||||
|
annotation,
|
||||||
|
dependencies
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
case AnnotationEditorType.INK:
|
case AnnotationEditorType.INK:
|
||||||
promises.push(
|
promises.push(
|
||||||
InkAnnotation.createNewAnnotation(xref, annotation, dependencies)
|
InkAnnotation.createNewAnnotation(xref, annotation, dependencies)
|
||||||
@ -429,6 +438,18 @@ class AnnotationFactory {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case AnnotationEditorType.HIGHLIGHT:
|
||||||
|
promises.push(
|
||||||
|
HighlightAnnotation.createNewPrintAnnotation(
|
||||||
|
annotationGlobals,
|
||||||
|
xref,
|
||||||
|
annotation,
|
||||||
|
{
|
||||||
|
evaluatorOptions: options,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
case AnnotationEditorType.INK:
|
case AnnotationEditorType.INK:
|
||||||
promises.push(
|
promises.push(
|
||||||
InkAnnotation.createNewPrintAnnotation(
|
InkAnnotation.createNewPrintAnnotation(
|
||||||
@ -4432,6 +4453,94 @@ class HighlightAnnotation extends MarkupAnnotation {
|
|||||||
this.data.popupRef = null;
|
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 {
|
class UnderlineAnnotation extends MarkupAnnotation {
|
||||||
|
@ -72,6 +72,7 @@ const AnnotationEditorType = {
|
|||||||
DISABLE: -1,
|
DISABLE: -1,
|
||||||
NONE: 0,
|
NONE: 0,
|
||||||
FREETEXT: 3,
|
FREETEXT: 3,
|
||||||
|
HIGHLIGHT: 9,
|
||||||
STAMP: 13,
|
STAMP: 13,
|
||||||
INK: 15,
|
INK: 15,
|
||||||
};
|
};
|
||||||
|
@ -8228,5 +8228,138 @@
|
|||||||
"md5": "71591f11ee717e12887f529c84d5ae89",
|
"md5": "71591f11ee717e12887f529c84d5ae89",
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "highlight"
|
"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 () {
|
it("should set quadpoints to null if not defined", async function () {
|
||||||
const highlightDict = new Dict();
|
const highlightDict = new Dict();
|
||||||
highlightDict.set("Type", Name.get("Annot"));
|
highlightDict.set("Type", Name.get("Annot"));
|
||||||
@ -4619,6 +4619,97 @@ describe("annotation", function () {
|
|||||||
expect(data.annotationType).toEqual(AnnotationType.HIGHLIGHT);
|
expect(data.annotationType).toEqual(AnnotationType.HIGHLIGHT);
|
||||||
expect(data.quadPoints).toEqual(null);
|
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 () {
|
describe("UnderlineAnnotation", function () {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user