Skip to content

Commit 9522bf9

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

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
@@ -77,6 +77,8 @@ class AnnotationEditorLayer {
7777
if (!AnnotationEditorLayer._initialized) {
7878
AnnotationEditorLayer._initialized = true;
7979
FreeTextEditor.initialize(options.l10n);
80+
81+
options.uiManager.registerEditorTypes([FreeTextEditor, InkEditor]);
8082
}
8183
this.#uiManager = options.uiManager;
8284
this.annotationStorage = options.annotationStorage;

src/display/editor/editor.js

+15
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,21 @@ class AnnotationEditor {
313313
this.div.classList.remove("selectedEditor");
314314
}
315315
}
316+
317+
/**
318+
* Update some parameters which have been changed through the UI.
319+
* @param {number} type
320+
* @param {*} value
321+
*/
322+
updateParams(type, value) {}
323+
324+
/**
325+
* Get some properties to update in the UI.
326+
* @returns {Object}
327+
*/
328+
getPropertiesToUpdate() {
329+
return {};
330+
}
316331
}
317332

318333
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.
@@ -41,10 +42,14 @@ class FreeTextEditor extends AnnotationEditor {
4142

4243
static _internalPadding = 0;
4344

45+
static _defaultFontSize = 10;
46+
47+
static _defaultColor = "CanvasText";
48+
4449
constructor(params) {
4550
super({ ...params, name: "freeTextEditor" });
46-
this.#color = params.color || "CanvasText";
47-
this.#fontSize = params.fontSize || 10;
51+
this.#color = params.color || FreeTextEditor._defaultColor;
52+
this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;
4853
}
4954

5055
static initialize(l10n) {
@@ -88,6 +93,64 @@ class FreeTextEditor extends AnnotationEditor {
8893
return editor;
8994
}
9095

96+
static updateDefaultParams(type, value) {
97+
switch (type) {
98+
case AnnotationEditorParamsType.FREETEXT_SIZE:
99+
FreeTextEditor._defaultFontSize = value;
100+
break;
101+
case AnnotationEditorParamsType.FREETEXT_COLOR:
102+
FreeTextEditor._defaultColor = value;
103+
break;
104+
}
105+
}
106+
107+
/** @inheritdoc */
108+
updateParams(type, value) {
109+
switch (type) {
110+
case AnnotationEditorParamsType.FREETEXT_SIZE:
111+
this.#updateFontSize(value);
112+
break;
113+
case AnnotationEditorParamsType.FREETEXT_COLOR:
114+
this.#updateColor(value);
115+
break;
116+
}
117+
}
118+
119+
static getDefaultPropertiesToUpdate() {
120+
return [
121+
[
122+
AnnotationEditorParamsType.FREETEXT_SIZE,
123+
FreeTextEditor._defaultFontSize,
124+
],
125+
[AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor],
126+
];
127+
}
128+
129+
/** @inheritdoc */
130+
getPropertiesToUpdate() {
131+
return [
132+
[AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize],
133+
[AnnotationEditorParamsType.FREETEXT_COLOR, this.#color],
134+
];
135+
}
136+
137+
#updateFontSize(size) {
138+
const diff = size - this.#fontSize;
139+
this.#fontSize = size;
140+
this.editorDiv.style.fontSize = `calc(${
141+
this.#fontSize
142+
}px * var(--zoom-factor))`;
143+
144+
// We must translate this editor in order to keep the base line at
145+
// the same position.
146+
this.translate(0, -diff * this.parent.zoomFactor);
147+
}
148+
149+
#updateColor(color) {
150+
this.#color = color;
151+
this.editorDiv.style.color = color;
152+
}
153+
91154
/** @inheritdoc */
92155
getInitialTranslation() {
93156
// The start of the base line is where the user clicked.
@@ -247,7 +310,7 @@ class FreeTextEditor extends AnnotationEditor {
247310
);
248311
return {
249312
annotationType: AnnotationEditorType.FREETEXT,
250-
color: [0, 0, 0],
313+
color: getRGB(this.#color),
251314
fontSize: this.#fontSize / PixelsPerInch.PDF_TO_CSS_UNITS,
252315
value: this.#content,
253316
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;
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 = [];
@@ -87,6 +96,54 @@ class InkEditor extends AnnotationEditor {
8796
return editor;
8897
}
8998

99+
static updateDefaultParams(type, value) {
100+
switch (type) {
101+
case AnnotationEditorParamsType.INK_THICKNESS:
102+
InkEditor._defaultThickness = value;
103+
break;
104+
case AnnotationEditorParamsType.INK_COLOR:
105+
InkEditor._defaultColor = value;
106+
break;
107+
}
108+
}
109+
110+
/** @inheritdoc */
111+
updateParams(type, value) {
112+
switch (type) {
113+
case AnnotationEditorParamsType.INK_THICKNESS:
114+
this.#updateThickness(value);
115+
break;
116+
case AnnotationEditorParamsType.INK_COLOR:
117+
this.#updateColor(value);
118+
break;
119+
}
120+
}
121+
122+
static getDefaultPropertiesToUpdate() {
123+
return [
124+
[AnnotationEditorParamsType.INK_THICKNESS, InkEditor._defaultThickness],
125+
[AnnotationEditorParamsType.INK_COLOR, InkEditor._defaultColor],
126+
];
127+
}
128+
129+
/** @inheritdoc */
130+
getPropertiesToUpdate() {
131+
return [
132+
[AnnotationEditorParamsType.INK_THICKNESS, this.thickness],
133+
[AnnotationEditorParamsType.INK_COLOR, this.color],
134+
];
135+
}
136+
137+
#updateThickness(thickness) {
138+
this.thickness = thickness;
139+
this.#fitToContent();
140+
}
141+
142+
#updateColor(color) {
143+
this.color = color;
144+
this.#redraw();
145+
}
146+
90147
/** @inheritdoc */
91148
rebuild() {
92149
if (this.div === null) {
@@ -169,7 +226,7 @@ class InkEditor extends AnnotationEditor {
169226
this.ctx.lineWidth =
170227
(this.thickness * this.parent.scaleFactor) / this.scaleFactor;
171228
this.ctx.lineCap = "round";
172-
this.ctx.lineJoin = "miter";
229+
this.ctx.lineJoin = "round";
173230
this.ctx.miterLimit = 10;
174231
this.ctx.strokeStyle = this.color;
175232
}
@@ -703,7 +760,7 @@ class InkEditor extends AnnotationEditor {
703760

704761
return {
705762
annotationType: AnnotationEditorType.INK,
706-
color: [0, 0, 0],
763+
color: getRGB(this.color),
707764
thickness: this.thickness,
708765
paths: this.#serializePaths(
709766
this.scaleFactor / this.parent.scaleFactor,

src/display/editor/tools.js

+52
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ class AnnotationEditorUIManager {
269269

270270
#commandManager = new CommandManager();
271271

272+
#editorTypes = null;
273+
274+
#eventBus = null;
275+
272276
#idManager = new IdManager();
273277

274278
#isAllSelected = false;
@@ -277,6 +281,26 @@ class AnnotationEditorUIManager {
277281

278282
#mode = AnnotationEditorType.NONE;
279283

284+
#previousActiveEditor = null;
285+
286+
constructor(eventBus) {
287+
this.#eventBus = eventBus;
288+
}
289+
290+
#dispatchUpdateUI(details) {
291+
this.#eventBus?.dispatch("annotationeditorparamschanged", {
292+
source: this,
293+
details,
294+
});
295+
}
296+
297+
registerEditorTypes(types) {
298+
this.#editorTypes = types;
299+
for (const editorType of this.#editorTypes) {
300+
this.#dispatchUpdateUI(editorType.getDefaultPropertiesToUpdate());
301+
}
302+
}
303+
280304
/**
281305
* Get an id.
282306
* @returns {string}
@@ -319,6 +343,18 @@ class AnnotationEditorUIManager {
319343
}
320344
}
321345

346+
/**
347+
* Update a parameter in the current editor or globally.
348+
* @param {number} type
349+
* @param {*} value
350+
*/
351+
updateParams(type, value) {
352+
this.#previousActiveEditor?.updateParams(type, value);
353+
for (const editorType of this.#editorTypes) {
354+
editorType.updateDefaultParams(type, value);
355+
}
356+
}
357+
322358
/**
323359
* Enable all the layers.
324360
*/
@@ -388,7 +424,23 @@ class AnnotationEditorUIManager {
388424
* @param {AnnotationEditor} editor
389425
*/
390426
setActiveEditor(editor) {
427+
if (this.#activeEditor !== editor) {
428+
this.#previousActiveEditor = this.#activeEditor;
429+
}
391430
this.#activeEditor = editor;
431+
if (editor) {
432+
this.#dispatchUpdateUI(editor.getPropertiesToUpdate());
433+
} else {
434+
if (this.#previousActiveEditor) {
435+
this.#dispatchUpdateUI(
436+
this.#previousActiveEditor.getPropertiesToUpdate()
437+
);
438+
} else {
439+
for (const editorType of this.#editorTypes) {
440+
this.#dispatchUpdateUI(editorType.getDefaultPropertiesToUpdate());
441+
}
442+
}
443+
}
392444
}
393445

394446
/**

0 commit comments

Comments
 (0)