Skip to content

Commit

Permalink
[Editor] Add the ability to make a free highlight (i.e. without havin…
Browse files Browse the repository at this point in the history
…g to select some text) (bug 1856218)

The free highlighting is enabled when the mouse pointer isn't on some text.
Then we draw a shape with smoothed borders corresponding to the movement of
the mouse.
Printing/saving and changing the thickness will come later.
  • Loading branch information
calixteman committed Jan 12, 2024
1 parent 0d01147 commit c9abf3a
Show file tree
Hide file tree
Showing 6 changed files with 668 additions and 26 deletions.
29 changes: 27 additions & 2 deletions src/display/draw_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class DrawLayer {

#mapping = new Map();

#toUpdate = new Map();

constructor({ pageIndex }) {
this.pageIndex = pageIndex;
}
Expand All @@ -53,7 +55,7 @@ class DrawLayer {
return shadow(this, "_svgFactory", new DOMSVGFactory());
}

static #setBox(element, { x, y, width, height }) {
static #setBox(element, { x = 0, y = 0, width = 1, height = 1 } = {}) {
const { style } = element;
style.top = `${100 * y}%`;
style.left = `${100 * x}%`;
Expand Down Expand Up @@ -83,10 +85,13 @@ class DrawLayer {
return clipPathId;
}

highlight(outlines, color, opacity) {
highlight(outlines, color, opacity, isPathUpdatable = false) {
const id = this.#id++;
const root = this.#createSVG(outlines.box);
root.classList.add("highlight");
if (outlines.free) {
root.classList.add("free");
}
const defs = DrawLayer._svgFactory.createElement("defs");
root.append(defs);
const path = DrawLayer._svgFactory.createElement("path");
Expand All @@ -95,6 +100,10 @@ class DrawLayer {
path.setAttribute("id", pathId);
path.setAttribute("d", outlines.toSVGPath());

if (isPathUpdatable) {
this.#toUpdate.set(id, path);
}

// Create the clipping path for the editor div.
const clipPathId = this.#createClipPath(defs, pathId);

Expand Down Expand Up @@ -139,6 +148,22 @@ class DrawLayer {
return id;
}

finalizeLine(id, line) {
const path = this.#toUpdate.get(id);
this.#toUpdate.delete(id);
this.updateBox(id, line.box);
path.setAttribute("d", line.toSVGPath());
}

removeFreeHighlight(id) {
this.remove(id);
this.#toUpdate.delete(id);
}

updatePath(id, line) {
this.#toUpdate.get(id).setAttribute("d", line.toSVGPath());
}

updateBox(id, box) {
DrawLayer.#setBox(this.#mapping.get(id), box);
}
Expand Down
39 changes: 31 additions & 8 deletions src/display/editor/annotation_editor_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ class AnnotationEditorLayer {

#boundPointerdown = this.pointerdown.bind(this);

#boundTextLayerPointerDown = this.#textLayerPointerDown.bind(this);

#editorFocusTimeoutId = null;

#boundSelectionStart = this.selectionStart.bind(this);
Expand Down Expand Up @@ -199,7 +201,7 @@ class AnnotationEditorLayer {
}
}

const editor = this.#createAndAddNewEditor(
const editor = this.createAndAddNewEditor(
{ offsetX: 0, offsetY: 0 },
/* isCentered = */ false
);
Expand Down Expand Up @@ -328,12 +330,32 @@ class AnnotationEditorLayer {
enableTextSelection() {
if (this.#textLayer?.div) {
document.addEventListener("selectstart", this.#boundSelectionStart);
this.#textLayer.div.addEventListener(
"pointerdown",
this.#boundTextLayerPointerDown
);
}
}

disableTextSelection() {
if (this.#textLayer?.div) {
document.removeEventListener("selectstart", this.#boundSelectionStart);
this.#textLayer.div.removeEventListener(
"pointerdown",
this.#boundTextLayerPointerDown
);
}
}

#textLayerPointerDown(event) {
if (event.target === this.#textLayer.div) {
const { isMac } = FeatureTest.platform;
if (event.button !== 0 || (event.ctrlKey && isMac)) {
// Do nothing on right click.
return;
}
HighlightEditor.startHighlighting(this, event);
event.preventDefault();
}
}

Expand Down Expand Up @@ -565,7 +587,7 @@ class AnnotationEditorLayer {
* @param [Object] data
* @returns {AnnotationEditor}
*/
#createAndAddNewEditor(event, isCentered, data = {}) {
createAndAddNewEditor(event, isCentered, data = {}) {
const id = this.getNextId();
const editor = this.#createNewEditor({
parent: this,
Expand Down Expand Up @@ -603,10 +625,7 @@ class AnnotationEditorLayer {
* Create and add a new editor.
*/
addNewEditor() {
this.#createAndAddNewEditor(
this.#getCenterPoint(),
/* isCentered = */ true
);
this.createAndAddNewEditor(this.#getCenterPoint(), /* isCentered = */ true);
}

/**
Expand Down Expand Up @@ -726,7 +745,7 @@ class AnnotationEditorLayer {
boxes.push(rotator(x, y, width, height));
}
if (boxes.length !== 0) {
this.#createAndAddNewEditor(event, false, {
this.createAndAddNewEditor(event, false, {
boxes,
});
}
Expand Down Expand Up @@ -767,7 +786,7 @@ class AnnotationEditorLayer {
return;
}

this.#createAndAddNewEditor(event, /* isCentered = */ false);
this.createAndAddNewEditor(event, /* isCentered = */ false);
}

/**
Expand Down Expand Up @@ -901,6 +920,10 @@ class AnnotationEditorLayer {
const { pageWidth, pageHeight } = this.viewport.rawDims;
return [pageWidth, pageHeight];
}

get scale() {
return this.#uiManager.viewParameters.realScale;
}
}

export { AnnotationEditorLayer };
Loading

0 comments on commit c9abf3a

Please sign in to comment.