Merge pull request #12696 from timvandermeij/annotation-quadpoints
Fix non-standard quadpoints orders for annotations
This commit is contained in:
commit
d784af3f38
@ -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) {
|
||||
|
@ -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";
|
||||
|
||||
|
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -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
BIN
test/pdfs/quadpoints.pdf
Normal file
Binary file not shown.
@ -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",
|
||||
|
@ -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();
|
||||
|
Loading…
x
Reference in New Issue
Block a user