diff --git a/src/core/annotation.js b/src/core/annotation.js index 2e4cbbb6287b1..d26ddeafbc1aa 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -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) { diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index 9890206659493..cb1b42800bfe6 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -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} */ _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} + */ + _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} */ 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"; diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 82936b8a7054e..6b7ae9e9a13d9 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -392,6 +392,7 @@ !issue11442_reduced.pdf !issue11549_reduced.pdf !issue8097_reduced.pdf +!quadpoints.pdf !transparent.pdf !xobject-image.pdf !ccitt_EndOfBlock_false.pdf diff --git a/test/pdfs/quadpoints.pdf b/test/pdfs/quadpoints.pdf new file mode 100644 index 0000000000000..72ac73dae02fe Binary files /dev/null and b/test/pdfs/quadpoints.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 3336b8e3402fb..7b09f2fc6d823 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -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", diff --git a/test/unit/annotation_spec.js b/test/unit/annotation_spec.js index d72a74aab65d6..75a454d576b89 100644 --- a/test/unit/annotation_spec.js +++ b/test/unit/annotation_spec.js @@ -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, + 19, 11, - 12, - 12, - 13, - 13, - 14, - 14, - 15, - 15, - 16, - 16, - 17, - 17, - 18, - 18, ]); 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();