[Editor] Handle correctly colors when saving a document in HCM

- for example in Dusk theme (Windows 11), black appears to be white, so
  the user will draw something in white. But if they want to print or
  save the used color must be black.
- fix a bug with the color input which only accepts hex string colors;
- adjust outline color of the selected/hovered editors in HCM.
This commit is contained in:
Calixte Denizet 2022-06-29 15:39:02 +02:00
parent a520fc9d9a
commit 9723c5d377
6 changed files with 120 additions and 17 deletions

View File

@ -589,12 +589,25 @@ function getRGB(color) {
return [0, 0, 0];
}
function getColorValues(colors) {
const span = document.createElement("span");
span.style.visibility = "hidden";
document.body.append(span);
for (const name of colors.keys()) {
span.style.color = name;
const computedColor = window.getComputedStyle(span).color;
colors.set(name, getRGB(computedColor));
}
span.remove();
}
export {
deprecated,
DOMCanvasFactory,
DOMCMapReaderFactory,
DOMStandardFontDataFactory,
DOMSVGFactory,
getColorValues,
getFilenameFromUrl,
getPdfFilenameFromUrl,
getRGB,

View File

@ -16,8 +16,8 @@
// eslint-disable-next-line max-len
/** @typedef {import("./annotation_editor_layer.js").AnnotationEditorLayer} AnnotationEditorLayer */
import { bindEvents } from "./tools.js";
import { unreachable } from "../../shared/util.js";
import { bindEvents, ColorManager } from "./tools.js";
import { shadow, unreachable } from "../../shared/util.js";
/**
* @typedef {Object} AnnotationEditorParameters
@ -33,6 +33,8 @@ import { unreachable } from "../../shared/util.js";
class AnnotationEditor {
#isInEditMode = false;
static _colorManager = new ColorManager();
/**
* @param {AnnotationEditorParameters} parameters
*/
@ -56,6 +58,14 @@ class AnnotationEditor {
this.isAttachedToDOM = false;
}
static get _defaultLineColor() {
return shadow(
this,
"_defaultLineColor",
this._colorManager.getHexCode("CanvasText")
);
}
/**
* This editor will be behind the others.
*/

View File

@ -21,7 +21,6 @@ import {
} 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.
@ -43,13 +42,16 @@ class FreeTextEditor extends AnnotationEditor {
static _internalPadding = 0;
static _defaultFontSize = 10;
static _defaultColor = null;
static _defaultColor = "CanvasText";
static _defaultFontSize = 10;
constructor(params) {
super({ ...params, name: "freeTextEditor" });
this.#color = params.color || FreeTextEditor._defaultColor;
this.#color =
params.color ||
FreeTextEditor._defaultColor ||
AnnotationEditor._defaultLineColor;
this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize;
}
@ -124,7 +126,10 @@ class FreeTextEditor extends AnnotationEditor {
AnnotationEditorParamsType.FREETEXT_SIZE,
FreeTextEditor._defaultFontSize,
],
[AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor],
[
AnnotationEditorParamsType.FREETEXT_COLOR,
FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor,
],
];
}
@ -362,8 +367,9 @@ class FreeTextEditor extends AnnotationEditor {
const padding = FreeTextEditor._internalPadding * this.parent.scaleFactor;
const rect = this.getRect(padding, padding);
// We don't use this.#color directly because it can be CanvasText.
const color = getRGB(getComputedStyle(this.editorDiv).color);
const color = AnnotationEditor._colorManager.convert(
getComputedStyle(this.editorDiv).color
);
return {
annotationType: AnnotationEditorType.FREETEXT,

View File

@ -20,7 +20,6 @@ import {
} from "../../shared/util.js";
import { AnnotationEditor } from "./editor.js";
import { fitCurve } from "./fit_curve/fit_curve.js";
import { getRGB } from "../display_utils.js";
/**
* Basic draw editor in order to generate an Ink annotation.
@ -48,13 +47,16 @@ class InkEditor extends AnnotationEditor {
#realHeight = 0;
static _defaultThickness = 1;
static _defaultColor = null;
static _defaultColor = "CanvasText";
static _defaultThickness = 1;
constructor(params) {
super({ ...params, name: "inkEditor" });
this.color = params.color || InkEditor._defaultColor;
this.color =
params.color ||
InkEditor._defaultColor ||
AnnotationEditor._defaultLineColor;
this.thickness = params.thickness || InkEditor._defaultThickness;
this.paths = [];
this.bezierPath2D = [];
@ -124,7 +126,10 @@ class InkEditor extends AnnotationEditor {
static get defaultPropertiesToUpdate() {
return [
[AnnotationEditorParamsType.INK_THICKNESS, InkEditor._defaultThickness],
[AnnotationEditorParamsType.INK_COLOR, InkEditor._defaultColor],
[
AnnotationEditorParamsType.INK_COLOR,
InkEditor._defaultColor || AnnotationEditor._defaultLineColor,
],
];
}
@ -846,8 +851,7 @@ class InkEditor extends AnnotationEditor {
const height =
this.rotation % 180 === 0 ? rect[3] - rect[1] : rect[2] - rect[0];
// We don't use this.color directly because it can be CanvasText.
const color = getRGB(this.ctx.strokeStyle);
const color = AnnotationEditor._colorManager.convert(this.ctx.strokeStyle);
return {
annotationType: AnnotationEditorType.INK,

View File

@ -21,7 +21,9 @@ import {
AnnotationEditorPrefix,
AnnotationEditorType,
shadow,
Util,
} from "../../shared/util.js";
import { getColorValues, getRGB } from "../display_utils.js";
function bindEvents(obj, element, names) {
for (const name of names) {
@ -279,6 +281,67 @@ class ClipboardManager {
}
}
class ColorManager {
static _colorsMapping = new Map([
["CanvasText", [0, 0, 0]],
["Canvas", [255, 255, 255]],
]);
get _colors() {
if (
typeof PDFJSDev !== "undefined" &&
PDFJSDev.test("LIB") &&
typeof document === "undefined"
) {
return shadow(this, "_colors", ColorManager._colorsMapping);
}
const colors = new Map([
["CanvasText", null],
["Canvas", null],
]);
getColorValues(colors);
return shadow(this, "_colors", colors);
}
/**
* In High Contrast Mode, the color on the screen is not always the
* real color used in the pdf.
* For example in some cases white can appear to be black but when saving
* we want to have white.
* @param {string} color
* @returns {Array<number>}
*/
convert(color) {
const rgb = getRGB(color);
if (!window.matchMedia("(forced-colors: active)").matches) {
return rgb;
}
for (const [name, RGB] of this._colors) {
if (RGB.every((x, i) => x === rgb[i])) {
return ColorManager._colorsMapping.get(name);
}
}
return rgb;
}
/**
* An input element must have its color value as a hex string
* and not as color name.
* So this function converts a name into an hex string.
* @param {string} name
* @returns {string}
*/
getHexCode(name) {
const rgb = this._colors.get(name);
if (!rgb) {
return name;
}
return Util.makeHexColor(...rgb);
}
}
/**
* A pdf has several pages and each of them when it will rendered
* will have an AnnotationEditorLayer which will contain the some
@ -683,4 +746,4 @@ class AnnotationEditorUIManager {
}
}
export { AnnotationEditorUIManager, bindEvents, KeyboardManager };
export { AnnotationEditorUIManager, bindEvents, ColorManager, KeyboardManager };

View File

@ -20,6 +20,13 @@
--freetext-padding: 2px;
}
@media (forced-colors: active) {
:root {
--focus-outline: solid 3px ButtonText;
--hover-outline: dashed 3px ButtonText;
}
}
[data-editor-rotation="90"] {
transform: rotate(90deg);
}