Merge pull request #16110 from calixteman/norotate
[Annotation] Don't rotate an annotation when it has the NoRotate flag
This commit is contained in:
commit
e11371c75f
@ -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");
|
||||
|
@ -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 (
|
||||
|
@ -19,7 +19,7 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.annotationLayer .buttonWidgetAnnotation.pushButton > img {
|
||||
.annotationLayer .wasCanvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
]
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user