Merge pull request #16110 from calixteman/norotate

[Annotation] Don't rotate an annotation when it has the NoRotate flag
This commit is contained in:
calixteman 2023-03-06 19:17:44 +01:00 committed by GitHub
commit e11371c75f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 105 additions and 36 deletions

View File

@ -486,6 +486,7 @@ class Annotation {
rect: this.rectangle,
subtype: params.subtype,
hasOwnCanvas: false,
noRotate: !!(this.flags & AnnotationFlag.NOROTATE),
};
if (params.collectFields) {
@ -3415,6 +3416,7 @@ class SignatureWidgetAnnotation extends WidgetAnnotation {
// non-serializable and will thus cause errors when sending annotations
// to the main-thread (issue 10347).
this.data.fieldValue = null;
this.data.hasOwnCanvas = this.data.noRotate;
}
getFieldObject() {
@ -3433,6 +3435,10 @@ class TextAnnotation extends MarkupAnnotation {
super(params);
// No rotation for Text (see 12.5.6.4).
this.data.noRotate = true;
this.data.hasOwnCanvas = this.data.noRotate;
const { dict } = params;
this.data.annotationType = AnnotationType.TEXT;
@ -3551,6 +3557,8 @@ class FreeTextAnnotation extends MarkupAnnotation {
constructor(params) {
super(params);
this.data.hasOwnCanvas = this.data.noRotate;
const { xref } = params;
this.data.annotationType = AnnotationType.FREETEXT;
this.setDefaultAppearance(params);
@ -3731,6 +3739,7 @@ class LineAnnotation extends MarkupAnnotation {
const { dict, xref } = params;
this.data.annotationType = AnnotationType.LINE;
this.data.hasOwnCanvas = this.data.noRotate;
const lineCoordinates = dict.getArray("L");
this.data.lineCoordinates = Util.normalizeRect(lineCoordinates);
@ -3795,6 +3804,7 @@ class SquareAnnotation extends MarkupAnnotation {
const { dict, xref } = params;
this.data.annotationType = AnnotationType.SQUARE;
this.data.hasOwnCanvas = this.data.noRotate;
if (!this.appearance) {
// The default stroke color is black.
@ -3906,6 +3916,7 @@ class PolylineAnnotation extends MarkupAnnotation {
const { dict, xref } = params;
this.data.annotationType = AnnotationType.POLYLINE;
this.data.hasOwnCanvas = this.data.noRotate;
this.data.vertices = [];
if (!(this instanceof PolygonAnnotation)) {
@ -3990,6 +4001,8 @@ class InkAnnotation extends MarkupAnnotation {
constructor(params) {
super(params);
this.data.hasOwnCanvas = this.data.noRotate;
const { dict, xref } = params;
this.data.annotationType = AnnotationType.INK;
this.data.inkLists = [];
@ -4325,6 +4338,7 @@ class StampAnnotation extends MarkupAnnotation {
super(params);
this.data.annotationType = AnnotationType.STAMP;
this.data.hasOwnCanvas = this.data.noRotate;
}
}
@ -4336,6 +4350,7 @@ class FileAttachmentAnnotation extends MarkupAnnotation {
const file = new FileSpec(dict.get("FS"), xref);
this.data.annotationType = AnnotationType.FILEATTACHMENT;
this.data.hasOwnCanvas = this.data.noRotate;
this.data.file = file.serializable;
const name = dict.get("Name");

View File

@ -199,6 +199,10 @@ class AnnotationElement {
const container = document.createElement("section");
container.setAttribute("data-annotation-id", data.id);
if (data.noRotate) {
container.classList.add("norotate");
}
const { pageWidth, pageHeight, pageX, pageY } = viewport.rawDims;
const { width, height } = getRectDims(data.rect);
@ -454,7 +458,7 @@ class AnnotationElement {
// If no trigger element is specified, create it.
if (!trigger) {
trigger = document.createElement("div");
trigger.className = "popupTriggerArea";
trigger.classList.add("popupTriggerArea");
container.append(trigger);
}
@ -493,7 +497,7 @@ class AnnotationElement {
}
for (const quadrilateral of this.quadrilaterals) {
quadrilateral.className = className;
quadrilateral.classList.add(className);
}
return this.quadrilaterals;
}
@ -622,7 +626,7 @@ class LinkAnnotationElement extends AnnotationElement {
);
}
this.container.className = "linkAnnotation";
this.container.classList.add("linkAnnotation");
if (isBound) {
this.container.append(link);
}
@ -857,7 +861,7 @@ class TextAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "textAnnotation";
this.container.classList.add("textAnnotation");
const image = document.createElement("img");
image.src =
@ -1029,7 +1033,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
const storage = this.annotationStorage;
const id = this.data.id;
this.container.className = "textWidgetAnnotation";
this.container.classList.add("textWidgetAnnotation");
let element = null;
if (this.renderForms) {
@ -1357,7 +1361,7 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
storage.setValue(id, { value });
}
this.container.className = "buttonWidgetAnnotation checkBox";
this.container.classList.add("buttonWidgetAnnotation", "checkBox");
const element = document.createElement("input");
GetElementsByNameSet.add(element);
@ -1431,7 +1435,7 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
}
render() {
this.container.className = "buttonWidgetAnnotation radioButton";
this.container.classList.add("buttonWidgetAnnotation", "radioButton");
const storage = this.annotationStorage;
const data = this.data;
const id = data.id;
@ -1525,7 +1529,7 @@ class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
// equal to that of a link annotation, but may have more functionality, such
// as performing actions on form fields (resetting, submitting, et cetera).
const container = super.render();
container.className = "buttonWidgetAnnotation pushButton";
container.classList.add("buttonWidgetAnnotation", "pushButton");
if (this.data.alternativeText) {
container.title = this.data.alternativeText;
@ -1550,7 +1554,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
}
render() {
this.container.className = "choiceWidgetAnnotation";
this.container.classList.add("choiceWidgetAnnotation");
const storage = this.annotationStorage;
const id = this.data.id;
@ -1810,7 +1814,7 @@ class PopupAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "popupAnnotation";
this.container.classList.add("popupAnnotation");
const parentElements = this.layer.querySelectorAll(
`[data-annotation-id="${this.data.parentId}"]`
@ -1870,7 +1874,7 @@ class PopupElement {
const BACKGROUND_ENLIGHT = 0.7;
const wrapper = document.createElement("div");
wrapper.className = "popupWrapper";
wrapper.classList.add("popupWrapper");
// For Popup annotations we hide the entire section because it contains
// only the popup. However, for Text annotations without a separate Popup
@ -1880,7 +1884,7 @@ class PopupElement {
this.hideElement.hidden = true;
const popup = document.createElement("div");
popup.className = "popup";
popup.classList.add("popup");
const color = this.color;
if (color) {
@ -1902,7 +1906,7 @@ class PopupElement {
const dateObject = PDFDateString.toDateObject(this.modificationDate);
if (dateObject) {
const modificationDate = document.createElement("span");
modificationDate.className = "popupDate";
modificationDate.classList.add("popupDate");
modificationDate.textContent = "{{date}}, {{time}}";
modificationDate.dataset.l10nId = "annotation_date_string";
modificationDate.dataset.l10nArgs = JSON.stringify({
@ -1921,7 +1925,7 @@ class PopupElement {
intent: "richText",
div: popup,
});
popup.lastChild.className = "richText popupContent";
popup.lastChild.classList.add("richText", "popupContent");
} else {
const contents = this._formatContents(this.contentsObj);
popup.append(contents);
@ -1953,7 +1957,7 @@ class PopupElement {
*/
_formatContents({ str, dir }) {
const p = document.createElement("p");
p.className = "popupContent";
p.classList.add("popupContent");
p.dir = dir;
const lines = str.split(/(?:\r\n?|\n)/);
for (let i = 0, ii = lines.length; i < ii; ++i) {
@ -2030,11 +2034,11 @@ class FreeTextAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "freeTextAnnotation";
this.container.classList.add("freeTextAnnotation");
if (this.textContent) {
const content = document.createElement("div");
content.className = "annotationTextContent";
content.classList.add("annotationTextContent");
content.setAttribute("role", "comment");
for (const line of this.textContent) {
const lineSpan = document.createElement("span");
@ -2063,7 +2067,7 @@ class LineAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "lineAnnotation";
this.container.classList.add("lineAnnotation");
// Create an invisible line with the same starting and ending coordinates
// that acts as the trigger for the popup. Only the line itself should
@ -2112,7 +2116,7 @@ class SquareAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "squareAnnotation";
this.container.classList.add("squareAnnotation");
// Create an invisible square with the same rectangle that acts as the
// trigger for the popup. Only the square itself should trigger the
@ -2163,7 +2167,7 @@ class CircleAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "circleAnnotation";
this.container.classList.add("circleAnnotation");
// Create an invisible circle with the same ellipse that acts as the
// trigger for the popup. Only the circle itself should trigger the
@ -2217,7 +2221,7 @@ class PolylineAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = this.containerClassName;
this.container.classList.add(this.containerClassName);
// Create an invisible polyline with the same points that acts as the
// trigger for the popup. Only the polyline itself should trigger the
@ -2283,7 +2287,7 @@ class CaretAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "caretAnnotation";
this.container.classList.add("caretAnnotation");
if (!this.data.hasPopup) {
this._createPopup(null, this.data);
@ -2310,7 +2314,7 @@ class InkAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = this.containerClassName;
this.container.classList.add(this.containerClassName);
// Create an invisible polyline with the same points that acts as the
// trigger for the popup.
@ -2379,7 +2383,7 @@ class HighlightAnnotationElement extends AnnotationElement {
return this._renderQuadrilaterals("highlightAnnotation");
}
this.container.className = "highlightAnnotation";
this.container.classList.add("highlightAnnotation");
return this.container;
}
}
@ -2408,7 +2412,7 @@ class UnderlineAnnotationElement extends AnnotationElement {
return this._renderQuadrilaterals("underlineAnnotation");
}
this.container.className = "underlineAnnotation";
this.container.classList.add("underlineAnnotation");
return this.container;
}
}
@ -2437,7 +2441,7 @@ class SquigglyAnnotationElement extends AnnotationElement {
return this._renderQuadrilaterals("squigglyAnnotation");
}
this.container.className = "squigglyAnnotation";
this.container.classList.add("squigglyAnnotation");
return this.container;
}
}
@ -2466,7 +2470,7 @@ class StrikeOutAnnotationElement extends AnnotationElement {
return this._renderQuadrilaterals("strikeoutAnnotation");
}
this.container.className = "strikeoutAnnotation";
this.container.classList.add("strikeoutAnnotation");
return this.container;
}
}
@ -2483,7 +2487,7 @@ class StampAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "stampAnnotation";
this.container.classList.add("stampAnnotation");
if (!this.data.hasPopup) {
this._createPopup(null, this.data);
@ -2508,7 +2512,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
}
render() {
this.container.className = "fileAttachmentAnnotation";
this.container.classList.add("fileAttachmentAnnotation");
let trigger;
if (this.data.hasAppearance) {
@ -2524,7 +2528,7 @@ class FileAttachmentAnnotationElement extends AnnotationElement {
/paperclip/i.test(this.data.name) ? "paperclip" : "pushpin"
}.svg`;
}
trigger.className = "popupTriggerArea";
trigger.classList.add("popupTriggerArea");
trigger.addEventListener("dblclick", this._download.bind(this));
if (

View File

@ -19,7 +19,7 @@
position: absolute;
}
.annotationLayer .buttonWidgetAnnotation.pushButton > img {
.annotationLayer .wasCanvas {
width: 100%;
height: 100%;
position: absolute;

View File

@ -135,6 +135,7 @@ async function convertCanvasesToImages(annotationCanvasMap, outputScale) {
new Promise(resolve => {
canvas.toBlob(blob => {
const image = document.createElement("img");
image.classList.add("wasCanvas");
image.onload = function () {
image.style.width = Math.floor(image.width / outputScale) + "px";
resolve();
@ -625,6 +626,9 @@ class Driver {
let viewport = page.getViewport({
scale: PixelsPerInch.PDF_TO_CSS_UNITS,
});
if (task.rotation) {
viewport = viewport.clone({ rotation: task.rotation });
}
// Restrict the test from creating a canvas that is too big.
const MAX_CANVAS_PIXEL_DIMENSION = 4096;
const largestDimension = Math.max(viewport.width, viewport.height);

View File

@ -7394,5 +7394,32 @@
"rounds": 1,
"link": true,
"type": "eq"
},
{
"id": "annotation-link-text-popup-rotated-90",
"file": "pdfs/annotation-link-text-popup.pdf",
"md5": "4bbf56e81d47232de5f305124ab0ba27",
"rounds": 1,
"type": "eq",
"annotations": true,
"rotation": 90
},
{
"id": "annotation-link-text-popup-rotated-180",
"file": "pdfs/annotation-link-text-popup.pdf",
"md5": "4bbf56e81d47232de5f305124ab0ba27",
"rounds": 1,
"type": "eq",
"annotations": true,
"rotation": 180
},
{
"id": "annotation-link-text-popup-rotated-270",
"file": "pdfs/annotation-link-text-popup.pdf",
"md5": "4bbf56e81d47232de5f305124ab0ba27",
"rounds": 1,
"type": "eq",
"annotations": true,
"rotation": 270
}
]

View File

@ -53,6 +53,22 @@
z-index: 3;
}
.annotationLayer[data-main-rotation="90"] .norotate {
transform: rotate(270deg) translateX(-100%);
}
.annotationLayer[data-main-rotation="180"] .norotate {
transform: rotate(180deg) translate(-100%, -100%);
}
.annotationLayer[data-main-rotation="270"] .norotate {
transform: rotate(90deg) translateY(-100%);
}
.annotationLayer canvas {
position: absolute;
width: 100%;
height: 100%;
}
.annotationLayer section {
position: absolute;
text-align: initial;
@ -75,11 +91,6 @@
height: 100%;
}
.annotationLayer .buttonWidgetAnnotation.pushButton > canvas {
width: 100%;
height: 100%;
}
.annotationLayer .linkAnnotation > a:hover,
.annotationLayer .buttonWidgetAnnotation.pushButton > a:hover {
opacity: 0.2;
@ -92,6 +103,8 @@
cursor: pointer;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.annotationLayer .textWidgetAnnotation input,
@ -237,6 +250,10 @@
width: 100%;
}
.annotationLayer .fileAttachmentAnnotation .popupTriggerArea {
position: absolute;
}
.annotationLayer .popupWrapper {
position: absolute;
font-size: calc(9px * var(--scale-factor));
@ -306,6 +323,8 @@
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
.annotationLayer .annotationTextContent {