Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Editor] Add a new base class to allow to add a drawing in the SVG layer. #19093

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 30 additions & 26 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -4466,7 +4466,7 @@ class InkAnnotation extends MarkupAnnotation {
ink.set("Subtype", Name.get("Ink"));
ink.set("CreationDate", `D:${getModificationDate()}`);
ink.set("Rect", rect);
ink.set("InkList", outlines?.points || paths.map(p => p.points));
ink.set("InkList", outlines?.points || paths.points);
ink.set("F", 4);
ink.set("Rotate", rotation);

Expand Down Expand Up @@ -4523,28 +4523,31 @@ class InkAnnotation extends MarkupAnnotation {
appearanceBuffer.push("/R0 gs");
}

const buffer = [];
for (const { bezier } of paths) {
buffer.length = 0;
buffer.push(
`${numberToString(bezier[0])} ${numberToString(bezier[1])} m`
);
if (bezier.length === 2) {
buffer.push(
`${numberToString(bezier[0])} ${numberToString(bezier[1])} l S`
);
} else {
for (let i = 2, ii = bezier.length; i < ii; i += 6) {
const curve = bezier
.slice(i, i + 6)
.map(numberToString)
.join(" ");
buffer.push(`${curve} c`);
for (const outline of paths.lines) {
for (let i = 0, ii = outline.length; i < ii; i += 6) {
if (isNaN(outline[i])) {
calixteman marked this conversation as resolved.
Show resolved Hide resolved
appearanceBuffer.push(
`${numberToString(outline[i + 4])} ${numberToString(
outline[i + 5]
)} m`
);
} else {
const [c1x, c1y, c2x, c2y, x, y] = outline.slice(i, i + 6);
appearanceBuffer.push(
`${numberToString(c1x)} ${numberToString(c1y)} ` +
`${numberToString(c2x)} ${numberToString(c2y)} ` +
`${numberToString(x)} ${numberToString(y)} c`
);
}
buffer.push("S");
}
appearanceBuffer.push(buffer.join("\n"));
if (outline.length === 6) {
appearanceBuffer.push(
`${numberToString(outline[4])} ${numberToString(outline[5])} l`
);
}
}
appearanceBuffer.push("S");

const appearance = appearanceBuffer.join("\n");

const appearanceStreamDict = new Dict(xref);
Expand Down Expand Up @@ -4587,18 +4590,19 @@ class InkAnnotation extends MarkupAnnotation {
`${numberToString(outline[4])} ${numberToString(outline[5])} m`
);
for (let i = 6, ii = outline.length; i < ii; i += 6) {
if (isNaN(outline[i]) || outline[i] === null) {
if (isNaN(outline[i])) {
appearanceBuffer.push(
`${numberToString(outline[i + 4])} ${numberToString(
outline[i + 5]
)} l`
);
} else {
const curve = outline
.slice(i, i + 6)
.map(numberToString)
.join(" ");
appearanceBuffer.push(`${curve} c`);
const [c1x, c1y, c2x, c2y, x, y] = outline.slice(i, i + 6);
appearanceBuffer.push(
`${numberToString(c1x)} ${numberToString(c1y)} ` +
`${numberToString(c2x)} ${numberToString(c2y)} ` +
`${numberToString(x)} ${numberToString(y)} c`
);
}
}
appearanceBuffer.push("h f");
Expand Down
22 changes: 21 additions & 1 deletion src/display/draw_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,18 @@ class DrawLayer {
this.updateProperties(id, properties);
}

updateProperties(elementOrId, { root, bbox, rootClass, path }) {
updateProperties(elementOrId, properties) {
if (!properties) {
return;
}
const { root, bbox, rootClass, path } = properties;
const element =
typeof elementOrId === "number"
? this.#mapping.get(elementOrId)
: elementOrId;
if (!element) {
return;
}
if (root) {
this.#updateProperties(element, root);
}
Expand All @@ -207,6 +214,19 @@ class DrawLayer {
}
}

updateParent(id, layer) {
if (layer === this) {
return;
}
const root = this.#mapping.get(id);
if (!root) {
return;
}
layer.#parent.append(root);
this.#mapping.delete(id);
layer.#mapping.set(id, root);
}

remove(id) {
this.#toUpdate.delete(id);
if (this.#parent === null) {
Expand Down
108 changes: 71 additions & 37 deletions src/display/editor/annotation_editor_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ class AnnotationEditorLayer {

#hadPointerDown = false;

#isCleaningUp = false;

#isDisabling = false;

#drawingAC = null;

#textLayer = null;

#textSelectionAC = null;
Expand Down Expand Up @@ -160,12 +160,9 @@ class AnnotationEditorLayer {
this.disableClick();
return;
case AnnotationEditorType.INK:
// We always want to have an ink editor ready to draw in.
this.addInkEditorIfNeeded(false);

this.disableTextSelection();
this.togglePointerEvents(true);
this.disableClick();
this.enableClick();
break;
case AnnotationEditorType.HIGHLIGHT:
this.enableTextSelection();
Expand Down Expand Up @@ -193,30 +190,6 @@ class AnnotationEditorLayer {
return textLayer === this.#textLayer?.div;
}

addInkEditorIfNeeded(isCommitting) {
if (this.#uiManager.getMode() !== AnnotationEditorType.INK) {
// We don't want to add an ink editor if we're not in ink mode!
return;
}

if (!isCommitting) {
// We're removing an editor but an empty one can already exist so in this
// case we don't need to create a new one.
for (const editor of this.#editors.values()) {
if (editor.isEmpty()) {
editor.setInBackground();
return;
}
}
}

const editor = this.createAndAddNewEditor(
{ offsetX: 0, offsetY: 0 },
/* isCentered = */ false
);
editor.setInBackground();
}

/**
* Set the editing state.
* @param {boolean} isEditing
Expand All @@ -233,6 +206,10 @@ class AnnotationEditorLayer {
this.#uiManager.addCommands(params);
}

cleanUndoStack(type) {
this.#uiManager.cleanUndoStack(type);
}

toggleDrawing(enabled = false) {
this.div.classList.toggle("drawing", !enabled);
}
Expand Down Expand Up @@ -482,10 +459,6 @@ class AnnotationEditorLayer {
this.#uiManager.removeEditor(editor);
editor.div.remove();
editor.isAttachedToDOM = false;

if (!this.#isCleaningUp) {
this.addInkEditorIfNeeded(/* isCommitting = */ false);
}
}

/**
Expand Down Expand Up @@ -766,6 +739,13 @@ class AnnotationEditorLayer {
}
this.#hadPointerDown = false;

if (
this.#currentEditorType?.isDrawer &&
this.#currentEditorType.supportMultipleDrawings
) {
return;
}

if (!this.#allowClick) {
this.#allowClick = true;
return;
Expand Down Expand Up @@ -808,10 +788,50 @@ class AnnotationEditorLayer {

this.#hadPointerDown = true;

if (this.#currentEditorType?.isDrawer) {
this.startDrawingSession(event);
return;
}

const editor = this.#uiManager.getActive();
this.#allowClick = !editor || editor.isEmpty();
}

startDrawingSession(event) {
this.div.focus();
if (this.#drawingAC) {
this.#currentEditorType.startDrawing(this, this.#uiManager, false, event);
return;
}

this.#uiManager.unselectAll();
this.#drawingAC = new AbortController();
const signal = this.#uiManager.combinedSignal(this.#drawingAC);
this.div.addEventListener(
"blur",
({ relatedTarget }) => {
if (relatedTarget && !this.div.contains(relatedTarget)) {
this.commitOrRemove();
}
},
{
signal,
}
);
this.#uiManager.disableUserSelect(true);
this.#currentEditorType.startDrawing(this, this.#uiManager, false, event);
}

endDrawingSession() {
if (!this.#drawingAC) {
return;
}
this.#drawingAC.abort();
this.#drawingAC = null;
this.#uiManager.disableUserSelect(false);
this.#currentEditorType.endDrawing();
}

/**
*
* @param {AnnotationEditor} editor
Expand All @@ -828,10 +848,26 @@ class AnnotationEditorLayer {
return true;
}

commitOrRemove() {
if (this.#drawingAC) {
this.endDrawingSession();
return true;
}
return false;
}

onScaleChanging() {
if (!this.#drawingAC) {
return;
}
this.#currentEditorType.onScaleChangingWhenDrawing(this);
}

/**
* Destroy the main editor.
*/
destroy() {
this.commitOrRemove();
if (this.#uiManager.getActive()?.parent === this) {
// We need to commit the current editor before destroying the layer.
this.#uiManager.commitOrRemove();
Expand All @@ -858,13 +894,11 @@ class AnnotationEditorLayer {
// When we're cleaning up, some editors are removed but we don't want
// to add a new one which will induce an addition in this.#editors, hence
// an infinite loop.
this.#isCleaningUp = true;
for (const editor of this.#editors.values()) {
if (editor.isEmpty()) {
editor.remove();
}
}
this.#isCleaningUp = false;
}

/**
Expand Down Expand Up @@ -896,14 +930,14 @@ class AnnotationEditorLayer {

const oldRotation = this.viewport.rotation;
const rotation = viewport.rotation;

this.viewport = viewport;
setLayerDimensions(this.div, { rotation });
if (oldRotation !== rotation) {
for (const editor of this.#editors.values()) {
editor.rotate(rotation);
}
}
this.addInkEditorIfNeeded(/* isCommitting = */ false);
}

/**
Expand Down
Loading