mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
[Editor] Try to make the position of an edited FreeText the more accurated as possible
- Take into account the page translation, - Take into account the correct translation for the editor border, - Take into account the position of the first glyph in the annotation, - Take into account the rotation of the editor. Close #16633.
This commit is contained in:
parent
35202ec0f3
commit
944c68ee85
11 changed files with 424 additions and 59 deletions
|
@ -546,7 +546,7 @@ class Annotation {
|
|||
|
||||
const MK = dict.get("MK");
|
||||
this.setBorderAndBackgroundColors(MK);
|
||||
this.setRotation(MK);
|
||||
this.setRotation(MK, dict);
|
||||
this.ref = params.ref instanceof Ref ? params.ref : null;
|
||||
|
||||
this._streams = [];
|
||||
|
@ -838,18 +838,21 @@ class Annotation {
|
|||
}
|
||||
}
|
||||
|
||||
setRotation(mk) {
|
||||
setRotation(mk, dict) {
|
||||
this.rotation = 0;
|
||||
let angle;
|
||||
if (mk instanceof Dict) {
|
||||
let angle = mk.get("R") || 0;
|
||||
if (Number.isInteger(angle) && angle !== 0) {
|
||||
angle %= 360;
|
||||
if (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
if (angle % 90 === 0) {
|
||||
this.rotation = angle;
|
||||
}
|
||||
angle = mk.get("R") || 0;
|
||||
} else {
|
||||
angle = dict.get("Rotate") || 0;
|
||||
}
|
||||
if (Number.isInteger(angle) && angle !== 0) {
|
||||
angle %= 360;
|
||||
if (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
if (angle % 90 === 0) {
|
||||
this.rotation = angle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1069,6 +1072,7 @@ class Annotation {
|
|||
|
||||
const text = [];
|
||||
const buffer = [];
|
||||
let firstPosition = null;
|
||||
const sink = {
|
||||
desiredSize: Math.Infinity,
|
||||
ready: true,
|
||||
|
@ -1078,6 +1082,7 @@ class Annotation {
|
|||
if (item.str === undefined) {
|
||||
continue;
|
||||
}
|
||||
firstPosition ||= item.transform.slice(-2);
|
||||
buffer.push(item.str);
|
||||
if (item.hasEOL) {
|
||||
text.push(buffer.join(""));
|
||||
|
@ -1102,6 +1107,17 @@ class Annotation {
|
|||
}
|
||||
|
||||
if (text.length > 1 || text[0]) {
|
||||
const appearanceDict = this.appearance.dict;
|
||||
const bbox = appearanceDict.getArray("BBox") || [0, 0, 1, 1];
|
||||
const matrix = appearanceDict.getArray("Matrix") || [1, 0, 0, 1, 0, 0];
|
||||
const rect = this.data.rect;
|
||||
const transform = getTransformMatrix(rect, bbox, matrix);
|
||||
transform[4] -= rect[0];
|
||||
transform[5] -= rect[1];
|
||||
firstPosition = Util.applyTransform(firstPosition, transform);
|
||||
firstPosition = Util.applyTransform(firstPosition, matrix);
|
||||
|
||||
this.data.textPosition = firstPosition;
|
||||
this.data.textContent = text;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -304,6 +304,9 @@ class AnnotationElement {
|
|||
}
|
||||
|
||||
setRotation(angle, container = this.container) {
|
||||
if (!this.data.rect) {
|
||||
return;
|
||||
}
|
||||
const { pageWidth, pageHeight } = this.parent.viewport.rawDims;
|
||||
const { width, height } = getRectDims(this.data.rect);
|
||||
|
||||
|
@ -2210,6 +2213,7 @@ class FreeTextAnnotationElement extends AnnotationElement {
|
|||
);
|
||||
super(parameters, { isRenderable, ignoreBorder: true });
|
||||
this.textContent = parameters.data.textContent;
|
||||
this.textPosition = parameters.data.textPosition;
|
||||
this.annotationEditorType = AnnotationEditorType.FREETEXT;
|
||||
}
|
||||
|
||||
|
|
|
@ -296,6 +296,24 @@ class AnnotationEditor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a page translation into a screen one.
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
*/
|
||||
pageTranslationToScreen(x, y) {
|
||||
switch (this.parentRotation) {
|
||||
case 90:
|
||||
return [-y, x];
|
||||
case 180:
|
||||
return [-x, -y];
|
||||
case 270:
|
||||
return [y, -x];
|
||||
default:
|
||||
return [x, y];
|
||||
}
|
||||
}
|
||||
|
||||
get parentScale() {
|
||||
return this._uiManager.viewParameters.realScale;
|
||||
}
|
||||
|
@ -398,6 +416,9 @@ class AnnotationEditor {
|
|||
this.#hasBeenSelected = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the current rect into a page one.
|
||||
*/
|
||||
getRect(tx, ty) {
|
||||
const scale = this.parentScale;
|
||||
const [pageWidth, pageHeight] = this.pageDimensions;
|
||||
|
|
|
@ -502,8 +502,47 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
// This editor was created in using copy (ctrl+c).
|
||||
const [parentWidth, parentHeight] = this.parentDimensions;
|
||||
if (this.annotationElementId) {
|
||||
const [tx] = this.getInitialTranslation();
|
||||
this.setAt(baseX * parentWidth, baseY * parentHeight, tx, tx);
|
||||
// This stuff is hard to test: if something is changed here, please
|
||||
// test with the following PDF file:
|
||||
// - freetexts.pdf
|
||||
// - rotated_freetexts.pdf
|
||||
// Only small variations between the original annotation and its editor
|
||||
// are allowed.
|
||||
|
||||
// position is the position of the first glyph in the annotation
|
||||
// and it's relative to its container.
|
||||
const { position } = this.#initialData;
|
||||
let [tx, ty] = this.getInitialTranslation();
|
||||
[tx, ty] = this.pageTranslationToScreen(tx, ty);
|
||||
const [pageWidth, pageHeight] = this.pageDimensions;
|
||||
const [pageX, pageY] = this.pageTranslation;
|
||||
let posX, posY;
|
||||
switch (this.rotation) {
|
||||
case 0:
|
||||
posX = baseX + (position[0] - pageX) / pageWidth;
|
||||
posY = baseY + this.height - (position[1] - pageY) / pageHeight;
|
||||
break;
|
||||
case 90:
|
||||
posX = baseX + (position[0] - pageX) / pageWidth;
|
||||
posY = baseY - (position[1] - pageY) / pageHeight;
|
||||
[tx, ty] = [ty, -tx];
|
||||
break;
|
||||
case 180:
|
||||
posX = baseX - this.width + (position[0] - pageX) / pageWidth;
|
||||
posY = baseY - (position[1] - pageY) / pageHeight;
|
||||
[tx, ty] = [-tx, -ty];
|
||||
break;
|
||||
case 270:
|
||||
posX =
|
||||
baseX +
|
||||
(position[0] - pageX - this.height * pageHeight) / pageWidth;
|
||||
posY =
|
||||
baseY +
|
||||
(position[1] - pageY - this.width * pageWidth) / pageHeight;
|
||||
[tx, ty] = [-ty, tx];
|
||||
break;
|
||||
}
|
||||
this.setAt(posX * parentWidth, posY * parentHeight, tx, ty);
|
||||
} else {
|
||||
this.setAt(
|
||||
baseX * parentWidth,
|
||||
|
@ -521,6 +560,10 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
this.editorDiv.contentEditable = true;
|
||||
}
|
||||
|
||||
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING")) {
|
||||
this.div.setAttribute("annotation-id", this.annotationElementId);
|
||||
}
|
||||
|
||||
return this.div;
|
||||
}
|
||||
|
||||
|
@ -554,6 +597,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
id,
|
||||
},
|
||||
textContent,
|
||||
textPosition,
|
||||
parent: {
|
||||
page: { pageNumber },
|
||||
},
|
||||
|
@ -569,6 +613,7 @@ class FreeTextEditor extends AnnotationEditor {
|
|||
color: Array.from(fontColor),
|
||||
fontSize,
|
||||
value: textContent.join("\n"),
|
||||
position: textPosition,
|
||||
pageIndex: pageNumber - 1,
|
||||
rect,
|
||||
rotation,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue