Skip to content

Commit

Permalink
[editor] Add some UI elements in order to set font size & color, and …
Browse files Browse the repository at this point in the history
…ink thickness & color
  • Loading branch information
calixteman committed Jun 21, 2022
1 parent 6ee538e commit ca4db4e
Show file tree
Hide file tree
Showing 20 changed files with 622 additions and 74 deletions.
6 changes: 6 additions & 0 deletions l10n/en-US/viewer.properties
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,9 @@ editor_ink.title=Add Ink Annotation
editor_ink_label=Ink Annotation

freetext_default_content=Enter some text…

# Editor Parameters
editor_free_text_font_color=Font Color
editor_free_text_font_size=Font Size
editor_ink_line_color=Line Color
editor_ink_line_thickness=Line Thickness
2 changes: 1 addition & 1 deletion src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -3458,7 +3458,7 @@ class InkAnnotation extends MarkupAnnotation {
const h = y2 - y1;

const appearanceBuffer = [
`${annotation.thickness} w`,
`${annotation.thickness} w 1 J 1 j`,
`${getPdfColor(annotation.color, /* isFill */ false)}`,
];
const buffer = [];
Expand Down
7 changes: 2 additions & 5 deletions src/display/canvas.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ import {
Util,
warn,
} from "../shared/util.js";
import { getRGB, PixelsPerInch } from "./display_utils.js";
import {
getShadingPattern,
PathType,
TilingPattern,
} from "./pattern_helper.js";
import { applyMaskImageData } from "../shared/image_utils.js";
import { isNodeJS } from "../shared/is_node.js";
import { PixelsPerInch } from "./display_utils.js";

// <canvas> contexts store most of the state we need natively.
// However, PDF needs a bit more state, which we store here.
Expand Down Expand Up @@ -1326,10 +1326,7 @@ class CanvasGraphics {
// Then for every color in the pdf, if its rounded luminance is the
// same as the background one then it's replaced by the new
// background color else by the foreground one.
const cB = parseInt(defaultBg.slice(1), 16);
const rB = (cB && 0xff0000) >> 16;
const gB = (cB && 0x00ff00) >> 8;
const bB = cB && 0x0000ff;
const [rB, gB, bB] = getRGB(defaultBg);
const newComp = x => {
x /= 255;
return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
Expand Down
23 changes: 23 additions & 0 deletions src/display/display_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,28 @@ function getXfaPageViewport(xfaPage, { scale = 1, rotation = 0 }) {
});
}

function getRGB(color) {
if (color.charAt(0) === "#") {
const colorRGB = parseInt(color.slice(1), 16);
return [
(colorRGB & 0xff0000) >> 16,
(colorRGB & 0x00ff00) >> 8,
colorRGB & 0x0000ff,
];
}

if (color.startsWith("rgb(")) {
// getComputedStyle(...).color returns a `rgb(R, G, B)` color.
return color
.slice(/* "rgb(".length */ 4, -1) // Strip out "rgb(" and ")".
.split(",")
.map(x => parseInt(x));
}

warn(`Not a valid color format: "${color}"`);
return [0, 0, 0];
}

export {
deprecated,
DOMCanvasFactory,
Expand All @@ -575,6 +597,7 @@ export {
DOMSVGFactory,
getFilenameFromUrl,
getPdfFilenameFromUrl,
getRGB,
getXfaPageViewport,
isDataScheme,
isPdfFile,
Expand Down
20 changes: 11 additions & 9 deletions src/display/editor/annotation_editor_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class AnnotationEditorLayer {
if (!AnnotationEditorLayer._initialized) {
AnnotationEditorLayer._initialized = true;
FreeTextEditor.initialize(options.l10n);

options.uiManager.registerEditorTypes([FreeTextEditor, InkEditor]);
}
this.#uiManager = options.uiManager;
this.annotationStorage = options.annotationStorage;
Expand Down Expand Up @@ -129,13 +131,10 @@ class AnnotationEditorLayer {

/**
* Add some commands into the CommandManager (undo/redo stuff).
* @param {function} cmd
* @param {function} undo
* @param {boolean} mustExec - If true the command is executed after having
* been added.
* @param {Object} params
*/
addCommands(cmd, undo, mustExec) {
this.#uiManager.addCommands(cmd, undo, mustExec);
addCommands(params) {
this.#uiManager.addCommands(params);
}

/**
Expand Down Expand Up @@ -231,7 +230,10 @@ class AnnotationEditorLayer {
this.unselectAll();
this.div.removeEventListener("click", this.#boundClick);
} else {
this.#uiManager.allowClick = false;
// When in Ink mode, setting the editor to null allows the
// user to have to make one click in order to start drawing.
this.#uiManager.allowClick =
this.#uiManager.getMode() === AnnotationEditorType.INK;
this.div.addEventListener("click", this.#boundClick);
}
}
Expand Down Expand Up @@ -326,7 +328,7 @@ class AnnotationEditorLayer {
editor.remove();
};

this.addCommands(cmd, undo, true);
this.addCommands({ cmd, undo, mustExec: true });
}

/**
Expand All @@ -341,7 +343,7 @@ class AnnotationEditorLayer {
editor.remove();
};

this.addCommands(cmd, undo, false);
this.addCommands({ cmd, undo, mustExec: false });
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/display/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,21 @@ class AnnotationEditor {
this.div.classList.remove("selectedEditor");
}
}

/**
* Update some parameters which have been changed through the UI.
* @param {number} type
* @param {*} value
*/
updateParams(type, value) {}

/**
* Get some properties to update in the UI.
* @returns {Object}
*/
get propertiesToUpdate() {
return {};
}
}

export { AnnotationEditor };
111 changes: 106 additions & 5 deletions src/display/editor/freetext.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@
*/

import {
AnnotationEditorParamsType,
AnnotationEditorType,
assert,
LINE_FACTOR,
Util,
} from "../../shared/util.js";
import { AnnotationEditor } from "./editor.js";
import { bindEvents } from "./tools.js";
import { getRGB } from "../display_utils.js";

/**
* Basic text editor in order to create a FreeTex annotation.
Expand All @@ -42,10 +44,14 @@ class FreeTextEditor extends AnnotationEditor {

static _internalPadding = 0;

static _defaultFontSize = 10;

static _defaultColor = "CanvasText";

constructor(params) {
super({ ...params, name: "freeTextEditor" });
this.#color = params.color || "CanvasText";
this.#fontSize = params.fontSize || 10;
this.#color = params.color || FreeTextEditor._defaultColor;
this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;
}

static initialize(l10n) {
Expand Down Expand Up @@ -89,6 +95,94 @@ class FreeTextEditor extends AnnotationEditor {
return editor;
}

static updateDefaultParams(type, value) {
switch (type) {
case AnnotationEditorParamsType.FREETEXT_SIZE:
FreeTextEditor._defaultFontSize = value;
break;
case AnnotationEditorParamsType.FREETEXT_COLOR:
FreeTextEditor._defaultColor = value;
break;
}
}

/** @inheritdoc */
updateParams(type, value) {
switch (type) {
case AnnotationEditorParamsType.FREETEXT_SIZE:
this.#updateFontSize(value);
break;
case AnnotationEditorParamsType.FREETEXT_COLOR:
this.#updateColor(value);
break;
}
}

static get defaultPropertiesToUpdate() {
return [
[
AnnotationEditorParamsType.FREETEXT_SIZE,
FreeTextEditor._defaultFontSize,
],
[AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor],
];
}

/** @inheritdoc */
get propertiesToUpdate() {
return [
[AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize],
[AnnotationEditorParamsType.FREETEXT_COLOR, this.#color],
];
}

/**
* Update the font size and make this action as undoable.
* @param {number} fontSize
*/
#updateFontSize(fontSize) {
const setFontsize = size => {
this.editorDiv.style.fontSize = `calc(${size}px * var(--scale-factor))`;
this.translate(0, -(size - this.#fontSize) * this.parent.scaleFactor);
this.#fontSize = size;
};
const savedFontsize = this.#fontSize;
this.parent.addCommands({
cmd: () => {
setFontsize(fontSize);
},
undo: () => {
setFontsize(savedFontsize);
},
mustExec: true,
type: AnnotationEditorParamsType.FREETEXT_SIZE,
overwriteIfSameType: true,
keepUndo: true,
});
}

/**
* Update the color and make this action undoable.
* @param {string} color
*/
#updateColor(color) {
const savedColor = this.#color;
this.parent.addCommands({
cmd: () => {
this.#color = color;
this.editorDiv.style.color = color;
},
undo: () => {
this.#color = savedColor;
this.editorDiv.style.color = savedColor;
},
mustExec: true,
type: AnnotationEditorParamsType.FREETEXT_SIZE,
overwriteIfSameType: true,
keepUndo: true,
});
}

/** @inheritdoc */
getInitialTranslation() {
// The start of the base line is where the user clicked.
Expand Down Expand Up @@ -216,7 +310,7 @@ class FreeTextEditor extends AnnotationEditor {
this.editorDiv.contentEditable = true;

const { style } = this.editorDiv;
style.fontSize = `${this.#fontSize}%`;
style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`;
style.color = this.#color;

this.div.append(this.editorDiv);
Expand All @@ -232,9 +326,11 @@ class FreeTextEditor extends AnnotationEditor {

if (this.width) {
// This editor was created in using copy (ctrl+c).
this.setAt(this.x + this.width, this.y + this.height);
const [tx, ty] = this.getInitialTranslation();
this.setAt(this.x + this.width - tx, this.y + this.height - ty);
// eslint-disable-next-line no-unsanitized/property
this.editorDiv.innerHTML = this.#contentHTML;
this.div.draggable = true;
}

return this.div;
Expand All @@ -253,9 +349,14 @@ class FreeTextEditor extends AnnotationEditor {
[this.x + padding + rect.width, this.y + padding],
this.parent.inverseViewportTransform
);

// We don't use this.#color directly because it can
// be CanvasText.
const color = getRGB(getComputedStyle(this.editorDiv).color);

return {
annotationType: AnnotationEditorType.FREETEXT,
color: [0, 0, 0],
color,
fontSize: this.#fontSize,
value: this.#content,
pageIndex: this.parent.pageIndex,
Expand Down
Loading

0 comments on commit ca4db4e

Please sign in to comment.