Skip to content

Commit 3874dc7

Browse files
committed
[editor] Add some UI elements in order to set font size & color, and ink thickness & color
1 parent b868812 commit 3874dc7

19 files changed

+466
-43
lines changed

l10n/en-US/viewer.properties

+6
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,9 @@ editor_ink.title=Add Ink Annotation
259259
editor_ink_label=Ink Annotation
260260

261261
freetext_default_content=Enter some text…
262+
263+
# Editor Parameters
264+
editor_free_text_font_color=Font Color
265+
editor_free_text_font_size=Font Size
266+
editor_ink_line_color=Line Color
267+
editor_ink_line_thickness=Line Thickness

src/core/annotation.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3458,7 +3458,7 @@ class InkAnnotation extends MarkupAnnotation {
34583458
const h = y2 - y1;
34593459

34603460
const appearanceBuffer = [
3461-
`${annotation.thickness} w`,
3461+
`${annotation.thickness} w 1 J 1 j`,
34623462
`${getPdfColor(annotation.color, /* isFill */ false)}`,
34633463
];
34643464
const buffer = [];

src/display/canvas.js

+2-5
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ import {
2626
Util,
2727
warn,
2828
} from "../shared/util.js";
29+
import { getRGB, PixelsPerInch } from "./display_utils.js";
2930
import {
3031
getShadingPattern,
3132
PathType,
3233
TilingPattern,
3334
} from "./pattern_helper.js";
3435
import { applyMaskImageData } from "../shared/image_utils.js";
3536
import { isNodeJS } from "../shared/is_node.js";
36-
import { PixelsPerInch } from "./display_utils.js";
3737

3838
// <canvas> contexts store most of the state we need natively.
3939
// However, PDF needs a bit more state, which we store here.
@@ -1326,10 +1326,7 @@ class CanvasGraphics {
13261326
// Then for every color in the pdf, if its rounded luminance is the
13271327
// same as the background one then it's replaced by the new
13281328
// background color else by the foreground one.
1329-
const cB = parseInt(defaultBg.slice(1), 16);
1330-
const rB = (cB && 0xff0000) >> 16;
1331-
const gB = (cB && 0x00ff00) >> 8;
1332-
const bB = cB && 0x0000ff;
1329+
const [rB, gB, bB] = getRGB(defaultBg);
13331330
const newComp = x => {
13341331
x /= 255;
13351332
return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;

src/display/display_utils.js

+6
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,11 @@ function getXfaPageViewport(xfaPage, { scale = 1, rotation = 0 }) {
567567
});
568568
}
569569

570+
function getRGB(hexColor) {
571+
const color = parseInt(hexColor.slice(1), 16);
572+
return [(color & 0xff0000) >> 16, (color & 0x00ff00) >> 8, color & 0x0000ff];
573+
}
574+
570575
export {
571576
deprecated,
572577
DOMCanvasFactory,
@@ -575,6 +580,7 @@ export {
575580
DOMSVGFactory,
576581
getFilenameFromUrl,
577582
getPdfFilenameFromUrl,
583+
getRGB,
578584
getXfaPageViewport,
579585
isDataScheme,
580586
isPdfFile,

src/display/editor/annotation_editor_layer.js

+2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ class AnnotationEditorLayer {
7979
if (!AnnotationEditorLayer._initialized) {
8080
AnnotationEditorLayer._initialized = true;
8181
FreeTextEditor.initialize(options.l10n);
82+
83+
options.uiManager.registerEditorTypes([FreeTextEditor, InkEditor]);
8284
}
8385
this.#uiManager = options.uiManager;
8486
this.annotationStorage = options.annotationStorage;

src/display/editor/editor.js

+15
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,21 @@ class AnnotationEditor {
330330
this.div.classList.remove("selectedEditor");
331331
}
332332
}
333+
334+
/**
335+
* Update some parameters which have been changed through the UI.
336+
* @param {number} type
337+
* @param {*} value
338+
*/
339+
updateParams(type, value) {}
340+
341+
/**
342+
* Get some properties to update in the UI.
343+
* @returns {Object}
344+
*/
345+
getPropertiesToUpdate() {
346+
return {};
347+
}
333348
}
334349

335350
export { AnnotationEditor };

src/display/editor/freetext.js

+67-4
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,15 @@
1414
*/
1515

1616
import {
17+
AnnotationEditorParamsType,
1718
AnnotationEditorType,
1819
assert,
1920
LINE_FACTOR,
2021
Util,
2122
} from "../../shared/util.js";
23+
import { getRGB, PixelsPerInch } from "../display_utils.js";
2224
import { AnnotationEditor } from "./editor.js";
2325
import { bindEvents } from "./tools.js";
24-
import { PixelsPerInch } from "../display_utils.js";
2526

2627
/**
2728
* Basic text editor in order to create a FreeTex annotation.
@@ -43,10 +44,14 @@ class FreeTextEditor extends AnnotationEditor {
4344

4445
static _internalPadding = 0;
4546

47+
static _defaultFontSize = 10;
48+
49+
static _defaultColor = "CanvasText";
50+
4651
constructor(params) {
4752
super({ ...params, name: "freeTextEditor" });
48-
this.#color = params.color || "CanvasText";
49-
this.#fontSize = params.fontSize || 10;
53+
this.#color = params.color || FreeTextEditor._defaultColor;
54+
this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;
5055
}
5156

5257
static initialize(l10n) {
@@ -90,6 +95,64 @@ class FreeTextEditor extends AnnotationEditor {
9095
return editor;
9196
}
9297

98+
static updateDefaultParams(type, value) {
99+
switch (type) {
100+
case AnnotationEditorParamsType.FREETEXT_SIZE:
101+
FreeTextEditor._defaultFontSize = value;
102+
break;
103+
case AnnotationEditorParamsType.FREETEXT_COLOR:
104+
FreeTextEditor._defaultColor = value;
105+
break;
106+
}
107+
}
108+
109+
/** @inheritdoc */
110+
updateParams(type, value) {
111+
switch (type) {
112+
case AnnotationEditorParamsType.FREETEXT_SIZE:
113+
this.#updateFontSize(value);
114+
break;
115+
case AnnotationEditorParamsType.FREETEXT_COLOR:
116+
this.#updateColor(value);
117+
break;
118+
}
119+
}
120+
121+
static getDefaultPropertiesToUpdate() {
122+
return [
123+
[
124+
AnnotationEditorParamsType.FREETEXT_SIZE,
125+
FreeTextEditor._defaultFontSize,
126+
],
127+
[AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor],
128+
];
129+
}
130+
131+
/** @inheritdoc */
132+
getPropertiesToUpdate() {
133+
return [
134+
[AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize],
135+
[AnnotationEditorParamsType.FREETEXT_COLOR, this.#color],
136+
];
137+
}
138+
139+
#updateFontSize(size) {
140+
const diff = size - this.#fontSize;
141+
this.#fontSize = size;
142+
this.editorDiv.style.fontSize = `calc(${
143+
this.#fontSize
144+
}px * var(--zoom-factor))`;
145+
146+
// We must translate this editor in order to keep the base line at
147+
// the same position.
148+
this.translate(0, -diff * this.parent.zoomFactor);
149+
}
150+
151+
#updateColor(color) {
152+
this.#color = color;
153+
this.editorDiv.style.color = color;
154+
}
155+
93156
/** @inheritdoc */
94157
getInitialTranslation() {
95158
// The start of the base line is where the user clicked.
@@ -256,7 +319,7 @@ class FreeTextEditor extends AnnotationEditor {
256319
);
257320
return {
258321
annotationType: AnnotationEditorType.FREETEXT,
259-
color: [0, 0, 0],
322+
color: getRGB(this.#color),
260323
fontSize: this.#fontSize / PixelsPerInch.PDF_TO_CSS_UNITS,
261324
value: this.#content,
262325
pageIndex: this.parent.pageIndex,

src/display/editor/ink.js

+62-5
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@
1313
* limitations under the License.
1414
*/
1515

16-
import { AnnotationEditorType, Util } from "../../shared/util.js";
16+
import {
17+
AnnotationEditorParamsType,
18+
AnnotationEditorType,
19+
Util,
20+
} from "../../shared/util.js";
1721
import { AnnotationEditor } from "./editor.js";
1822
import { fitCurve } from "./fit_curve/fit_curve.js";
23+
import { getRGB } from "../display_utils.js";
1924

2025
/**
2126
* Basic draw editor in order to generate an Ink annotation.
@@ -39,10 +44,14 @@ class InkEditor extends AnnotationEditor {
3944

4045
#observer = null;
4146

47+
static _defaultThickness = 1;
48+
49+
static _defaultColor = "CanvasText";
50+
4251
constructor(params) {
4352
super({ ...params, name: "inkEditor" });
44-
this.color = params.color || "CanvasText";
45-
this.thickness = params.thickness || 1;
53+
this.color = params.color || InkEditor._defaultColor;
54+
this.thickness = params.thickness || InkEditor._defaultThickness;
4655
this.paths = [];
4756
this.bezierPath2D = [];
4857
this.currentPath = [];
@@ -83,6 +92,54 @@ class InkEditor extends AnnotationEditor {
8392
return editor;
8493
}
8594

95+
static updateDefaultParams(type, value) {
96+
switch (type) {
97+
case AnnotationEditorParamsType.INK_THICKNESS:
98+
InkEditor._defaultThickness = value;
99+
break;
100+
case AnnotationEditorParamsType.INK_COLOR:
101+
InkEditor._defaultColor = value;
102+
break;
103+
}
104+
}
105+
106+
/** @inheritdoc */
107+
updateParams(type, value) {
108+
switch (type) {
109+
case AnnotationEditorParamsType.INK_THICKNESS:
110+
this.#updateThickness(value);
111+
break;
112+
case AnnotationEditorParamsType.INK_COLOR:
113+
this.#updateColor(value);
114+
break;
115+
}
116+
}
117+
118+
static getDefaultPropertiesToUpdate() {
119+
return [
120+
[AnnotationEditorParamsType.INK_THICKNESS, InkEditor._defaultThickness],
121+
[AnnotationEditorParamsType.INK_COLOR, InkEditor._defaultColor],
122+
];
123+
}
124+
125+
/** @inheritdoc */
126+
getPropertiesToUpdate() {
127+
return [
128+
[AnnotationEditorParamsType.INK_THICKNESS, this.thickness],
129+
[AnnotationEditorParamsType.INK_COLOR, this.color],
130+
];
131+
}
132+
133+
#updateThickness(thickness) {
134+
this.thickness = thickness;
135+
this.#fitToContent();
136+
}
137+
138+
#updateColor(color) {
139+
this.color = color;
140+
this.#redraw();
141+
}
142+
86143
/** @inheritdoc */
87144
rebuild() {
88145
if (this.div === null) {
@@ -166,7 +223,7 @@ class InkEditor extends AnnotationEditor {
166223
this.ctx.lineWidth =
167224
(this.thickness * this.parent.scaleFactor) / this.scaleFactor;
168225
this.ctx.lineCap = "round";
169-
this.ctx.lineJoin = "miter";
226+
this.ctx.lineJoin = "round";
170227
this.ctx.miterLimit = 10;
171228
this.ctx.strokeStyle = this.color;
172229
}
@@ -717,7 +774,7 @@ class InkEditor extends AnnotationEditor {
717774

718775
return {
719776
annotationType: AnnotationEditorType.INK,
720-
color: [0, 0, 0],
777+
color: getRGB(this.color),
721778
thickness: this.thickness,
722779
paths: this.#serializePaths(
723780
this.scaleFactor / this.parent.scaleFactor,

src/display/editor/tools.js

+52
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,10 @@ class AnnotationEditorUIManager {
273273

274274
#commandManager = new CommandManager();
275275

276+
#editorTypes = null;
277+
278+
#eventBus = null;
279+
276280
#idManager = new IdManager();
277281

278282
#isAllSelected = false;
@@ -281,6 +285,26 @@ class AnnotationEditorUIManager {
281285

282286
#mode = AnnotationEditorType.NONE;
283287

288+
#previousActiveEditor = null;
289+
290+
constructor(eventBus) {
291+
this.#eventBus = eventBus;
292+
}
293+
294+
#dispatchUpdateUI(details) {
295+
this.#eventBus?.dispatch("annotationeditorparamschanged", {
296+
source: this,
297+
details,
298+
});
299+
}
300+
301+
registerEditorTypes(types) {
302+
this.#editorTypes = types;
303+
for (const editorType of this.#editorTypes) {
304+
this.#dispatchUpdateUI(editorType.getDefaultPropertiesToUpdate());
305+
}
306+
}
307+
284308
/**
285309
* Get an id.
286310
* @returns {string}
@@ -326,6 +350,18 @@ class AnnotationEditorUIManager {
326350
}
327351
}
328352

353+
/**
354+
* Update a parameter in the current editor or globally.
355+
* @param {number} type
356+
* @param {*} value
357+
*/
358+
updateParams(type, value) {
359+
this.#previousActiveEditor?.updateParams(type, value);
360+
for (const editorType of this.#editorTypes) {
361+
editorType.updateDefaultParams(type, value);
362+
}
363+
}
364+
329365
/**
330366
* Enable all the layers.
331367
*/
@@ -395,7 +431,23 @@ class AnnotationEditorUIManager {
395431
* @param {AnnotationEditor} editor
396432
*/
397433
setActiveEditor(editor) {
434+
if (this.#activeEditor !== editor) {
435+
this.#previousActiveEditor = this.#activeEditor;
436+
}
398437
this.#activeEditor = editor;
438+
if (editor) {
439+
this.#dispatchUpdateUI(editor.getPropertiesToUpdate());
440+
} else {
441+
if (this.#previousActiveEditor) {
442+
this.#dispatchUpdateUI(
443+
this.#previousActiveEditor.getPropertiesToUpdate()
444+
);
445+
} else {
446+
for (const editorType of this.#editorTypes) {
447+
this.#dispatchUpdateUI(editorType.getDefaultPropertiesToUpdate());
448+
}
449+
}
450+
}
399451
}
400452

401453
/**

0 commit comments

Comments
 (0)