Merge pull request #12696 from timvandermeij/annotation-quadpoints

Fix non-standard quadpoints orders for annotations
This commit is contained in:
Tim van der Meij 2020-12-06 16:52:33 +01:00 committed by GitHub
commit d784af3f38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 201 additions and 261 deletions

View File

@ -227,7 +227,36 @@ function getQuadPoints(dict, rect) {
quadPointsLists[i].push({ x, y });
}
}
return quadPointsLists;
// The PDF specification states in section 12.5.6.10 (figure 64) that the
// order of the quadpoints should be bottom left, bottom right, top right
// and top left. However, in practice PDF files use a different order,
// namely bottom left, bottom right, top left and top right (this is also
// mentioned on https://github.com/highkite/pdfAnnotate#QuadPoints), so
// this is the actual order we should work with. However, the situation is
// even worse since Adobe's own applications and other applications violate
// the specification and create annotations with other orders, namely top
// left, top right, bottom left and bottom right or even top left, top right,
// bottom right and bottom left. To avoid inconsistency and broken rendering,
// we normalize all lists to put the quadpoints in the same standard order
// (see https://stackoverflow.com/a/10729881).
return quadPointsLists.map(quadPointsList => {
const [minX, maxX, minY, maxY] = quadPointsList.reduce(
([mX, MX, mY, MY], quadPoint) => [
Math.min(mX, quadPoint.x),
Math.max(MX, quadPoint.x),
Math.min(mY, quadPoint.y),
Math.max(MY, quadPoint.y),
],
[Number.MAX_VALUE, Number.MIN_VALUE, Number.MAX_VALUE, Number.MIN_VALUE]
);
return [
{ x: minX, y: maxY },
{ x: maxX, y: maxY },
{ x: minX, y: minY },
{ x: maxX, y: minY },
];
});
}
function getTransformMatrix(rect, bbox, matrix) {

View File

@ -23,6 +23,7 @@ import {
import {
AnnotationBorderStyleType,
AnnotationType,
assert,
stringToPDFString,
unreachable,
Util,
@ -133,7 +134,14 @@ class AnnotationElementFactory {
}
class AnnotationElement {
constructor(parameters, isRenderable = false, ignoreBorder = false) {
constructor(
parameters,
{
isRenderable = false,
ignoreBorder = false,
createQuadrilaterals = false,
} = {}
) {
this.isRenderable = isRenderable;
this.data = parameters.data;
this.layer = parameters.layer;
@ -151,6 +159,9 @@ class AnnotationElement {
if (isRenderable) {
this.container = this._createContainer(ignoreBorder);
}
if (createQuadrilaterals) {
this.quadrilaterals = this._createQuadrilaterals(ignoreBorder);
}
}
/**
@ -245,12 +256,12 @@ class AnnotationElement {
}
/**
* Create quadrilaterals for the quadPoints.
* Create quadrilaterals from the annotation's quadpoints.
*
* @private
* @param {boolean} ignoreBorder
* @memberof AnnotationElement
* @returns {HTMLSectionElement}
* @returns {Array<HTMLSectionElement>}
*/
_createQuadrilaterals(ignoreBorder = false) {
if (!this.data.quadPoints) {
@ -315,10 +326,33 @@ class AnnotationElement {
}
/**
* Render the annotation's HTML element in the empty container.
* Render the quadrilaterals of the annotation.
*
* @private
* @param {string} className
* @memberof AnnotationElement
* @returns {Array<HTMLSectionElement>}
*/
_renderQuadrilaterals(className) {
if (
typeof PDFJSDev === "undefined" ||
PDFJSDev.test("!PRODUCTION || TESTING")
) {
assert(this.quadrilaterals, "Missing quadrilaterals during rendering");
}
this.quadrilaterals.forEach(quadrilateral => {
quadrilateral.className = className;
});
return this.quadrilaterals;
}
/**
* Render the annotation's HTML element(s).
*
* @public
* @memberof AnnotationElement
* @returns {HTMLSectionElement|Array<HTMLSectionElement>}
*/
render() {
unreachable("Abstract method `AnnotationElement.render` called");
@ -333,19 +367,10 @@ class LinkAnnotationElement extends AnnotationElement {
parameters.data.action ||
parameters.data.isTooltipOnly
);
super(parameters, isRenderable);
super(parameters, { isRenderable, createQuadrilaterals: true });
}
/**
* Render the link annotation's HTML element in the empty container.
*
* @public
* @memberof LinkAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "linkAnnotation";
const { data, linkService } = this;
const link = document.createElement("a");
@ -366,6 +391,17 @@ class LinkAnnotationElement extends AnnotationElement {
this._bindLink(link, "");
}
if (this.quadrilaterals) {
return this._renderQuadrilaterals("linkAnnotation").map(
(quadrilateral, index) => {
const linkElement = index === 0 ? link : link.cloneNode();
quadrilateral.appendChild(linkElement);
return quadrilateral;
}
);
}
this.container.className = "linkAnnotation";
this.container.appendChild(link);
return this.container;
}
@ -416,16 +452,9 @@ class TextAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable);
super(parameters, { isRenderable });
}
/**
* Render the text annotation's HTML element in the empty container.
*
* @public
* @memberof TextAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "textAnnotation";
@ -451,13 +480,6 @@ class TextAnnotationElement extends AnnotationElement {
}
class WidgetAnnotationElement extends AnnotationElement {
/**
* Render the widget annotation's HTML element in the empty container.
*
* @public
* @memberof WidgetAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
// Show only the container for unsupported field types.
if (this.data.alternativeText) {
@ -473,16 +495,9 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
const isRenderable =
parameters.renderInteractiveForms ||
(!parameters.data.hasAppearance && !!parameters.data.fieldValue);
super(parameters, isRenderable);
super(parameters, { isRenderable });
}
/**
* Render the text widget annotation's HTML element in the empty container.
*
* @public
* @memberof TextWidgetAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
const TEXT_ALIGNMENT = ["left", "center", "right"];
const storage = this.annotationStorage;
@ -680,17 +695,9 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
constructor(parameters) {
super(parameters, parameters.renderInteractiveForms);
super(parameters, { isRenderable: parameters.renderInteractiveForms });
}
/**
* Render the checkbox widget annotation's HTML element
* in the empty container.
*
* @public
* @memberof CheckboxWidgetAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
const storage = this.annotationStorage;
const data = this.data;
@ -720,17 +727,9 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
constructor(parameters) {
super(parameters, parameters.renderInteractiveForms);
super(parameters, { isRenderable: parameters.renderInteractiveForms });
}
/**
* Render the radio button widget annotation's HTML element
* in the empty container.
*
* @public
* @memberof RadioButtonWidgetAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "buttonWidgetAnnotation radioButton";
const storage = this.annotationStorage;
@ -767,14 +766,6 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
}
class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
/**
* Render the push button widget annotation's HTML element
* in the empty container.
*
* @public
* @memberof PushButtonWidgetAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
// The rendering and functionality of a push button widget annotation is
// equal to that of a link annotation, but may have more functionality, such
@ -792,17 +783,9 @@ class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
constructor(parameters) {
super(parameters, parameters.renderInteractiveForms);
super(parameters, { isRenderable: parameters.renderInteractiveForms });
}
/**
* Render the choice widget annotation's HTML element in the empty
* container.
*
* @public
* @memberof ChoiceWidgetAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "choiceWidgetAnnotation";
const storage = this.annotationStorage;
@ -857,16 +840,9 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
class PopupAnnotationElement extends AnnotationElement {
constructor(parameters) {
const isRenderable = !!(parameters.data.title || parameters.data.contents);
super(parameters, isRenderable);
super(parameters, { isRenderable });
}
/**
* Render the popup annotation's HTML element in the empty container.
*
* @public
* @memberof PopupAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
// Do not render popup annotations for parent elements with these types as
// they create the popups themselves (because of custom trigger divs).
@ -935,13 +911,6 @@ class PopupElement {
this.pinned = false;
}
/**
* Render the popup's HTML element.
*
* @public
* @memberof PopupElement
* @returns {HTMLSectionElement}
*/
render() {
const BACKGROUND_ENLIGHT = 0.7;
@ -1082,16 +1051,9 @@ class FreeTextAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
super(parameters, { isRenderable, ignoreBorder: true });
}
/**
* Render the free text annotation's HTML element in the empty container.
*
* @public
* @memberof FreeTextAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "freeTextAnnotation";
@ -1109,16 +1071,9 @@ class LineAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
super(parameters, { isRenderable, ignoreBorder: true });
}
/**
* Render the line annotation's HTML element in the empty container.
*
* @public
* @memberof LineAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "lineAnnotation";
@ -1160,16 +1115,9 @@ class SquareAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
super(parameters, { isRenderable, ignoreBorder: true });
}
/**
* Render the square annotation's HTML element in the empty container.
*
* @public
* @memberof SquareAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "squareAnnotation";
@ -1214,16 +1162,9 @@ class CircleAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
super(parameters, { isRenderable, ignoreBorder: true });
}
/**
* Render the circle annotation's HTML element in the empty container.
*
* @public
* @memberof CircleAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "circleAnnotation";
@ -1268,19 +1209,12 @@ class PolylineAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
super(parameters, { isRenderable, ignoreBorder: true });
this.containerClassName = "polylineAnnotation";
this.svgElementName = "svg:polyline";
}
/**
* Render the polyline annotation's HTML element in the empty container.
*
* @public
* @memberof PolylineAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = this.containerClassName;
@ -1340,16 +1274,9 @@ class CaretAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
super(parameters, { isRenderable, ignoreBorder: true });
}
/**
* Render the caret annotation's HTML element in the empty container.
*
* @public
* @memberof CaretAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "caretAnnotation";
@ -1367,7 +1294,7 @@ class InkAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
super(parameters, { isRenderable, ignoreBorder: true });
this.containerClassName = "inkAnnotation";
@ -1376,13 +1303,6 @@ class InkAnnotationElement extends AnnotationElement {
this.svgElementName = "svg:polyline";
}
/**
* Render the ink annotation's HTML element in the empty container.
*
* @public
* @memberof InkAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = this.containerClassName;
@ -1433,27 +1353,20 @@ class HighlightAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
this.quadrilaterals = this._createQuadrilaterals(/* ignoreBorder = */ true);
super(parameters, {
isRenderable,
ignoreBorder: true,
createQuadrilaterals: true,
});
}
/**
* Render the highlight annotation's HTML element in the empty container.
*
* @public
* @memberof HighlightAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
if (!this.data.hasPopup) {
this._createPopup(null, this.data);
}
if (this.quadrilaterals) {
this.quadrilaterals.forEach(quadrilateral => {
quadrilateral.className = "highlightAnnotation";
});
return this.quadrilaterals;
return this._renderQuadrilaterals("highlightAnnotation");
}
this.container.className = "highlightAnnotation";
@ -1468,27 +1381,20 @@ class UnderlineAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
this.quadrilaterals = this._createQuadrilaterals(/* ignoreBorder = */ true);
super(parameters, {
isRenderable,
ignoreBorder: true,
createQuadrilaterals: true,
});
}
/**
* Render the underline annotation's HTML element in the empty container.
*
* @public
* @memberof UnderlineAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
if (!this.data.hasPopup) {
this._createPopup(null, this.data);
}
if (this.quadrilaterals) {
this.quadrilaterals.forEach(quadrilateral => {
quadrilateral.className = "underlineAnnotation";
});
return this.quadrilaterals;
return this._renderQuadrilaterals("underlineAnnotation");
}
this.container.className = "underlineAnnotation";
@ -1503,27 +1409,20 @@ class SquigglyAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
this.quadrilaterals = this._createQuadrilaterals(/* ignoreBorder = */ true);
super(parameters, {
isRenderable,
ignoreBorder: true,
createQuadrilaterals: true,
});
}
/**
* Render the squiggly annotation's HTML element in the empty container.
*
* @public
* @memberof SquigglyAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
if (!this.data.hasPopup) {
this._createPopup(null, this.data);
}
if (this.quadrilaterals) {
this.quadrilaterals.forEach(quadrilateral => {
quadrilateral.className = "squigglyAnnotation";
});
return this.quadrilaterals;
return this._renderQuadrilaterals("squigglyAnnotation");
}
this.container.className = "squigglyAnnotation";
@ -1538,27 +1437,20 @@ class StrikeOutAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
this.quadrilaterals = this._createQuadrilaterals(/* ignoreBorder = */ true);
super(parameters, {
isRenderable,
ignoreBorder: true,
createQuadrilaterals: true,
});
}
/**
* Render the strikeout annotation's HTML element in the empty container.
*
* @public
* @memberof StrikeOutAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
if (!this.data.hasPopup) {
this._createPopup(null, this.data);
}
if (this.quadrilaterals) {
this.quadrilaterals.forEach(quadrilateral => {
quadrilateral.className = "strikeoutAnnotation";
});
return this.quadrilaterals;
return this._renderQuadrilaterals("strikeoutAnnotation");
}
this.container.className = "strikeoutAnnotation";
@ -1573,16 +1465,9 @@ class StampAnnotationElement extends AnnotationElement {
parameters.data.title ||
parameters.data.contents
);
super(parameters, isRenderable, /* ignoreBorder = */ true);
super(parameters, { isRenderable, ignoreBorder: true });
}
/**
* Render the stamp annotation's HTML element in the empty container.
*
* @public
* @memberof StampAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "stampAnnotation";
@ -1595,7 +1480,7 @@ class StampAnnotationElement extends AnnotationElement {
class FileAttachmentAnnotationElement extends AnnotationElement {
constructor(parameters) {
super(parameters, /* isRenderable = */ true);
super(parameters, { isRenderable: true });
const { filename, content } = this.data.file;
this.filename = getFilenameFromUrl(filename);
@ -1611,14 +1496,6 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
}
}
/**
* Render the file attachment annotation's HTML element in the empty
* container.
*
* @public
* @memberof FileAttachmentAnnotationElement
* @returns {HTMLSectionElement}
*/
render() {
this.container.className = "fileAttachmentAnnotation";

View File

@ -392,6 +392,7 @@
!issue11442_reduced.pdf
!issue11549_reduced.pdf
!issue8097_reduced.pdf
!quadpoints.pdf
!transparent.pdf
!xobject-image.pdf
!ccitt_EndOfBlock_false.pdf

BIN
test/pdfs/quadpoints.pdf Normal file

Binary file not shown.

View File

@ -4805,6 +4805,13 @@
"lastPage": 1,
"type": "text"
},
{ "id": "quadpoints",
"file": "pdfs/quadpoints.pdf",
"md5": "aadbc9bf826b4604c49a994fc8cd72c1",
"rounds": 1,
"type": "eq",
"annotations": true
},
{ "id": "operator-in-TJ-array",
"file": "pdfs/operator-in-TJ-array.pdf",
"md5": "dfe0f15a45be18eca142adaf760984ee",

View File

@ -216,41 +216,67 @@ describe("annotation", function () {
}
});
it("should process valid quadpoints arrays", function () {
it("should process quadpoints in the standard order", function () {
rect = [10, 10, 20, 20];
dict.set("QuadPoints", [
10,
20,
20,
20,
10,
10,
20,
10,
11,
19,
19,
19,
11,
11,
12,
12,
13,
13,
14,
14,
15,
15,
16,
16,
17,
17,
18,
18,
19,
11,
]);
expect(getQuadPoints(dict, rect)).toEqual([
[
{ x: 11, y: 11 },
{ x: 12, y: 12 },
{ x: 13, y: 13 },
{ x: 14, y: 14 },
{ x: 10, y: 20 },
{ x: 20, y: 20 },
{ x: 10, y: 10 },
{ x: 20, y: 10 },
],
[
{ x: 15, y: 15 },
{ x: 16, y: 16 },
{ x: 17, y: 17 },
{ x: 18, y: 18 },
{ x: 11, y: 19 },
{ x: 19, y: 19 },
{ x: 11, y: 11 },
{ x: 19, y: 11 },
],
]);
});
it("should normalize and process quadpoints in non-standard orders", function () {
rect = [10, 10, 20, 20];
const nonStandardOrders = [
// Bottom left, bottom right, top right and top left.
[10, 20, 20, 20, 20, 10, 10, 10],
// Top left, top right, bottom left and bottom right.
[10, 10, 20, 10, 10, 20, 20, 20],
// Top left, top right, bottom right and bottom left.
[10, 10, 20, 10, 20, 20, 10, 20],
];
for (const nonStandardOrder of nonStandardOrders) {
dict.set("QuadPoints", nonStandardOrder);
expect(getQuadPoints(dict, rect)).toEqual([
[
{ x: 10, y: 20 },
{ x: 20, y: 20 },
{ x: 10, y: 10 },
{ x: 20, y: 10 },
],
]);
}
});
});
describe("Annotation", function () {
@ -1265,7 +1291,7 @@ describe("annotation", function () {
annotationDict.set("Type", Name.get("Annot"));
annotationDict.set("Subtype", Name.get("Link"));
annotationDict.set("Rect", [10, 10, 20, 20]);
annotationDict.set("QuadPoints", [11, 11, 12, 12, 13, 13, 14, 14]);
annotationDict.set("QuadPoints", [10, 20, 20, 20, 10, 10, 20, 10]);
const annotationRef = Ref.get(121, 0);
const xref = new XRefMock([{ ref: annotationRef, data: annotationDict }]);
@ -1279,10 +1305,10 @@ describe("annotation", function () {
expect(data.annotationType).toEqual(AnnotationType.LINK);
expect(data.quadPoints).toEqual([
[
{ x: 11, y: 11 },
{ x: 12, y: 12 },
{ x: 13, y: 13 },
{ x: 14, y: 14 },
{ x: 10, y: 20 },
{ x: 20, y: 20 },
{ x: 10, y: 10 },
{ x: 20, y: 10 },
],
]);
done();
@ -3636,7 +3662,7 @@ describe("annotation", function () {
highlightDict.set("Type", Name.get("Annot"));
highlightDict.set("Subtype", Name.get("Highlight"));
highlightDict.set("Rect", [10, 10, 20, 20]);
highlightDict.set("QuadPoints", [11, 11, 12, 12, 13, 13, 14, 14]);
highlightDict.set("QuadPoints", [10, 20, 20, 20, 10, 10, 20, 10]);
const highlightRef = Ref.get(121, 0);
const xref = new XRefMock([{ ref: highlightRef, data: highlightDict }]);
@ -3650,10 +3676,10 @@ describe("annotation", function () {
expect(data.annotationType).toEqual(AnnotationType.HIGHLIGHT);
expect(data.quadPoints).toEqual([
[
{ x: 11, y: 11 },
{ x: 12, y: 12 },
{ x: 13, y: 13 },
{ x: 14, y: 14 },
{ x: 10, y: 20 },
{ x: 20, y: 20 },
{ x: 10, y: 10 },
{ x: 20, y: 10 },
],
]);
done();
@ -3709,7 +3735,7 @@ describe("annotation", function () {
underlineDict.set("Type", Name.get("Annot"));
underlineDict.set("Subtype", Name.get("Underline"));
underlineDict.set("Rect", [10, 10, 20, 20]);
underlineDict.set("QuadPoints", [11, 11, 12, 12, 13, 13, 14, 14]);
underlineDict.set("QuadPoints", [10, 20, 20, 20, 10, 10, 20, 10]);
const underlineRef = Ref.get(121, 0);
const xref = new XRefMock([{ ref: underlineRef, data: underlineDict }]);
@ -3723,10 +3749,10 @@ describe("annotation", function () {
expect(data.annotationType).toEqual(AnnotationType.UNDERLINE);
expect(data.quadPoints).toEqual([
[
{ x: 11, y: 11 },
{ x: 12, y: 12 },
{ x: 13, y: 13 },
{ x: 14, y: 14 },
{ x: 10, y: 20 },
{ x: 20, y: 20 },
{ x: 10, y: 10 },
{ x: 20, y: 10 },
],
]);
done();
@ -3760,7 +3786,7 @@ describe("annotation", function () {
squigglyDict.set("Type", Name.get("Annot"));
squigglyDict.set("Subtype", Name.get("Squiggly"));
squigglyDict.set("Rect", [10, 10, 20, 20]);
squigglyDict.set("QuadPoints", [11, 11, 12, 12, 13, 13, 14, 14]);
squigglyDict.set("QuadPoints", [10, 20, 20, 20, 10, 10, 20, 10]);
const squigglyRef = Ref.get(121, 0);
const xref = new XRefMock([{ ref: squigglyRef, data: squigglyDict }]);
@ -3774,10 +3800,10 @@ describe("annotation", function () {
expect(data.annotationType).toEqual(AnnotationType.SQUIGGLY);
expect(data.quadPoints).toEqual([
[
{ x: 11, y: 11 },
{ x: 12, y: 12 },
{ x: 13, y: 13 },
{ x: 14, y: 14 },
{ x: 10, y: 20 },
{ x: 20, y: 20 },
{ x: 10, y: 10 },
{ x: 20, y: 10 },
],
]);
done();
@ -3811,7 +3837,7 @@ describe("annotation", function () {
strikeOutDict.set("Type", Name.get("Annot"));
strikeOutDict.set("Subtype", Name.get("StrikeOut"));
strikeOutDict.set("Rect", [10, 10, 20, 20]);
strikeOutDict.set("QuadPoints", [11, 11, 12, 12, 13, 13, 14, 14]);
strikeOutDict.set("QuadPoints", [10, 20, 20, 20, 10, 10, 20, 10]);
const strikeOutRef = Ref.get(121, 0);
const xref = new XRefMock([{ ref: strikeOutRef, data: strikeOutDict }]);
@ -3825,10 +3851,10 @@ describe("annotation", function () {
expect(data.annotationType).toEqual(AnnotationType.STRIKEOUT);
expect(data.quadPoints).toEqual([
[
{ x: 11, y: 11 },
{ x: 12, y: 12 },
{ x: 13, y: 13 },
{ x: 14, y: 14 },
{ x: 10, y: 20 },
{ x: 20, y: 20 },
{ x: 10, y: 10 },
{ x: 20, y: 10 },
],
]);
done();