From 18bd93fe23ed242f4a9e4d48112f68ece6985c14 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Tue, 19 Nov 2024 21:03:28 +0100 Subject: [PATCH 01/17] Refactor getBackgroundImage() so we can make better use of the cacheEntry object --- src/fontra/client/core/font-controller.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/fontra/client/core/font-controller.js b/src/fontra/client/core/font-controller.js index f49ad22e9..542f29872 100644 --- a/src/fontra/client/core/font-controller.js +++ b/src/fontra/client/core/font-controller.js @@ -132,12 +132,17 @@ export class FontController { } getBackgroundImage(imageIdentifier) { + const cacheEntry = this._getBackgroundImageCacheEntry(imageIdentifier); + return cacheEntry.imagePromise; + } + + _getBackgroundImageCacheEntry(imageIdentifier) { // This returns a promise for the requested background image let cacheEntry = this._backgroundImageCache.get(imageIdentifier); if (!cacheEntry) { cacheEntry = this._cacheBackgroundImageFromIdentifier(imageIdentifier); } - return cacheEntry.imagePromise; + return cacheEntry; } getBackgroundImageCached(imageIdentifier, onLoad = null) { From c858ac122af5dd1fb8d37db4292f0e893da35cff Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Tue, 19 Nov 2024 21:04:53 +0100 Subject: [PATCH 02/17] Add colorizeImage() helper function --- src/fontra/client/core/utils.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/fontra/client/core/utils.js b/src/fontra/client/core/utils.js index b308688be..fc5327d60 100644 --- a/src/fontra/client/core/utils.js +++ b/src/fontra/client/core/utils.js @@ -635,3 +635,29 @@ export function readFileOrBlobAsDataURL(fileOrBlob) { reader.readAsDataURL(fileOrBlob); }); } + +export function colorizeImage(inputImage, color) { + const canvas = document.createElement("canvas"); + const w = inputImage.naturalWidth; + const h = inputImage.naturalHeight; + canvas.width = w; + canvas.height = h; + const context = canvas.getContext("2d"); + + context.drawImage(inputImage, 0, 0, w, h); + context.fillStyle = "black"; + context.globalCompositeOperation = "saturation"; + context.fillRect(0, 0, w, h); + context.fillStyle = color; + context.globalCompositeOperation = "screen"; + context.fillRect(0, 0, w, h); + + const outputImage = new Image(); + outputImage.width = inputImage.width; + outputImage.height = inputImage.height; + + return new Promise((resolve, reject) => { + outputImage.onload = (event) => resolve(outputImage); + outputImage.src = canvas.toDataURL("image/png"); + }); +} From c2a3b3c68343fe2421dc0a2fbb0282ef4241bd3e Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Tue, 19 Nov 2024 21:30:04 +0100 Subject: [PATCH 03/17] Add 'colorized' versions for the getBackgroundImageXxx methods; use this is the vis layer for bg images --- src/fontra/client/core/font-controller.js | 38 +++++++++++++++++++ .../editor/visualization-layer-definitions.js | 9 ++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/fontra/client/core/font-controller.js b/src/fontra/client/core/font-controller.js index 542f29872..ddabd4e87 100644 --- a/src/fontra/client/core/font-controller.js +++ b/src/fontra/client/core/font-controller.js @@ -16,6 +16,7 @@ import { TaskPool } from "./task-pool.js"; import { assert, chain, + colorizeImage, getCharFromCodePoint, mapObjectValues, throttleCalls, @@ -136,6 +137,30 @@ export class FontController { return cacheEntry.imagePromise; } + getBackgroundImageColorized(imageIdentifier, color) { + if (!color) { + return this.getBackgroundImage(imageIdentifier); + } + const cacheEntry = this._getBackgroundImageCacheEntry(imageIdentifier); + if (cacheEntry.color !== color) { + delete cacheEntry.imageColorized; + cacheEntry.color = color; + cacheEntry.imageColorizedPromise = new Promise((resolve, reject) => { + cacheEntry.imagePromise.then((image) => { + if (image) { + colorizeImage(image, color).then((image) => { + cacheEntry.imageColorized = image; + resolve(image); + }); + } else { + resolve(null); + } + }); + }); + } + return cacheEntry.imageColorizedPromise; + } + _getBackgroundImageCacheEntry(imageIdentifier) { // This returns a promise for the requested background image let cacheEntry = this._backgroundImageCache.get(imageIdentifier); @@ -161,6 +186,19 @@ export class FontController { return cacheEntry?.image; } + getBackgroundImageColorizedCached(imageIdentifier, color, onLoad = null) { + if (!color) { + return this.getBackgroundImageCached(imageIdentifier, onLoad); + } + const cacheEntry = this._backgroundImageCache.get(imageIdentifier); + if ((!cacheEntry?.imageColorizedPromise || cacheEntry.color !== color) && onLoad) { + this.getBackgroundImageColorized(imageIdentifier, color).then((image) => + onLoad(image) + ); + } + return cacheEntry?.imageColorized; + } + _cacheBackgroundImageFromIdentifier(imageIdentifier) { return this._cacheBackgroundImageFromDataURLPromise( imageIdentifier, diff --git a/src/fontra/views/editor/visualization-layer-definitions.js b/src/fontra/views/editor/visualization-layer-definitions.js index 5b25b9d3c..6414b2696 100644 --- a/src/fontra/views/editor/visualization-layer-definitions.js +++ b/src/fontra/views/editor/visualization-layer-definitions.js @@ -427,8 +427,15 @@ registerVisualizationLayerDefinition({ return; } - const image = model.fontController.getBackgroundImageCached( + const image = model.fontController.getBackgroundImageColorizedCached( backgroundImage.identifier, + backgroundImage.color + ? rgbaToCSS([ + backgroundImage.color.red, + backgroundImage.color.green, + backgroundImage.color.blue, + ]) + : null, () => controller.requestUpdate() ); From e76b5a5f14ae65227626c693d744b0328aaae51b Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Tue, 19 Nov 2024 21:47:29 +0100 Subject: [PATCH 04/17] Added some comments --- src/fontra/client/core/utils.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fontra/client/core/utils.js b/src/fontra/client/core/utils.js index fc5327d60..451974ca8 100644 --- a/src/fontra/client/core/utils.js +++ b/src/fontra/client/core/utils.js @@ -644,10 +644,13 @@ export function colorizeImage(inputImage, color) { canvas.height = h; const context = canvas.getContext("2d"); + // First step, draw the image context.drawImage(inputImage, 0, 0, w, h); + // Second step, reduce saturation to zero (making the image grayscale) context.fillStyle = "black"; context.globalCompositeOperation = "saturation"; context.fillRect(0, 0, w, h); + // Last step, colorize the image, using screen (inverse multiply) context.fillStyle = color; context.globalCompositeOperation = "screen"; context.fillRect(0, 0, w, h); From b9be699faf93ce8f4ca1147d3b7af524e5094d6f Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Tue, 19 Nov 2024 21:59:55 +0100 Subject: [PATCH 05/17] Be kinder to memory management by using a blob instead of a data url --- src/fontra/client/core/utils.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/fontra/client/core/utils.js b/src/fontra/client/core/utils.js index 451974ca8..df55e0ffa 100644 --- a/src/fontra/client/core/utils.js +++ b/src/fontra/client/core/utils.js @@ -655,12 +655,17 @@ export function colorizeImage(inputImage, color) { context.globalCompositeOperation = "screen"; context.fillRect(0, 0, w, h); - const outputImage = new Image(); - outputImage.width = inputImage.width; - outputImage.height = inputImage.height; - return new Promise((resolve, reject) => { - outputImage.onload = (event) => resolve(outputImage); - outputImage.src = canvas.toDataURL("image/png"); + canvas.toBlob((blob) => { + const outputImage = new Image(); + outputImage.width = inputImage.width; + outputImage.height = inputImage.height; + const url = URL.createObjectURL(blob); + outputImage.onload = () => { + URL.revokeObjectURL(url); + resolve(outputImage); + }; + outputImage.src = url; + }); }); } From de7866802f71bfc7d78249112758741587130b57 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Tue, 19 Nov 2024 22:38:32 +0100 Subject: [PATCH 06/17] Move line --- src/fontra/client/core/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fontra/client/core/utils.js b/src/fontra/client/core/utils.js index df55e0ffa..d3d82fb82 100644 --- a/src/fontra/client/core/utils.js +++ b/src/fontra/client/core/utils.js @@ -637,9 +637,9 @@ export function readFileOrBlobAsDataURL(fileOrBlob) { } export function colorizeImage(inputImage, color) { - const canvas = document.createElement("canvas"); const w = inputImage.naturalWidth; const h = inputImage.naturalHeight; + const canvas = document.createElement("canvas"); canvas.width = w; canvas.height = h; const context = canvas.getContext("2d"); From ed142ae43136b44ef59809889ac858849b193f3f Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Tue, 19 Nov 2024 22:42:59 +0100 Subject: [PATCH 07/17] Fix comments --- src/fontra/client/core/font-controller.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fontra/client/core/font-controller.js b/src/fontra/client/core/font-controller.js index ddabd4e87..497ef52f1 100644 --- a/src/fontra/client/core/font-controller.js +++ b/src/fontra/client/core/font-controller.js @@ -133,11 +133,13 @@ export class FontController { } getBackgroundImage(imageIdentifier) { + // This returns a promise for the requested background image const cacheEntry = this._getBackgroundImageCacheEntry(imageIdentifier); return cacheEntry.imagePromise; } getBackgroundImageColorized(imageIdentifier, color) { + // This returns a promise for the requested colorized background image if (!color) { return this.getBackgroundImage(imageIdentifier); } @@ -162,7 +164,6 @@ export class FontController { } _getBackgroundImageCacheEntry(imageIdentifier) { - // This returns a promise for the requested background image let cacheEntry = this._backgroundImageCache.get(imageIdentifier); if (!cacheEntry) { cacheEntry = this._cacheBackgroundImageFromIdentifier(imageIdentifier); From 24756d9f535fb95ae7a207ab2a9c9996eb028b57 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 09:51:04 +0100 Subject: [PATCH 08/17] Add color picker field type --- src/fontra/client/web-components/ui-form.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/fontra/client/web-components/ui-form.js b/src/fontra/client/web-components/ui-form.js index d03b362d8..96a9972a8 100644 --- a/src/fontra/client/web-components/ui-form.js +++ b/src/fontra/client/web-components/ui-form.js @@ -79,6 +79,11 @@ export class Form extends SimpleElement { height: 1.6em; } + .ui-form-value input[type="color"] { + height: 2em; + width: 4em; + } + .ui-form-value input[type="text"] { width: 100%; } @@ -404,6 +409,21 @@ export class Form extends SimpleElement { valueElement.appendChild(rangeElement); } + _addColorPicker(valueElement, fieldItem) { + const colorInputElement = html.input({ type: "color" }); + colorInputElement.value = fieldItem.formatColor + ? fieldItem.formatColor(fieldItem.value) + : fieldItem.value; + colorInputElement.onchange = (event) => + this._fieldChanging( + fieldItem, + fieldItem.parseColor + ? fieldItem.parseColor(colorInputElement.value) + : colorInputElement.value + ); + valueElement.appendChild(colorInputElement); + } + addEventListener(eventName, handler, options) { this.contentElement.addEventListener(eventName, handler, options); } From da5442a0506e370bdbbb97b5e202edf1ed86eb37 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 09:51:36 +0100 Subject: [PATCH 09/17] Add color picker for bg image coloriazation --- src/fontra/views/editor/panel-selection-info.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/fontra/views/editor/panel-selection-info.js b/src/fontra/views/editor/panel-selection-info.js index 7b1c66afd..00a631e22 100644 --- a/src/fontra/views/editor/panel-selection-info.js +++ b/src/fontra/views/editor/panel-selection-info.js @@ -11,6 +11,7 @@ import { makeUPlusStringFromCodePoint, parseSelection, range, + rgbaToHex, round, splitGlyphNameExtension, throttleCalls, @@ -292,6 +293,20 @@ export default class SelectionInfoPanel extends Panel { }), }); + formContents.push({ + type: "color-picker", + key: backgroundImageKey("color"), + label: translate("background-image.labels.colorize"), + value: backgroundImage.color, + parseColor: (value) => { + const matches = value.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i); + const channels = matches.slice(1, 4).map((ch) => parseInt(ch, 16) / 255); + return { red: channels[0], green: channels[1], blue: channels[2] }; + }, + formatColor: (value) => + value ? rgbaToHex([value.red, value.green, value.blue]) : "#000000", + }); + formContents.push({ type: "edit-number-slider", key: backgroundImageKey("opacity"), From 317d5d8554bf5370d4931da75808b7f814c484a8 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 10:01:51 +0100 Subject: [PATCH 10/17] Make color picker work with live changes --- src/fontra/client/web-components/ui-form.js | 45 ++++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/fontra/client/web-components/ui-form.js b/src/fontra/client/web-components/ui-form.js index 96a9972a8..5255eeb28 100644 --- a/src/fontra/client/web-components/ui-form.js +++ b/src/fontra/client/web-components/ui-form.js @@ -410,17 +410,42 @@ export class Form extends SimpleElement { } _addColorPicker(valueElement, fieldItem) { + const parseColor = fieldItem.parseColor || ((v) => v); + const formatColor = fieldItem.formatColor || ((v) => v); + const colorInputElement = html.input({ type: "color" }); - colorInputElement.value = fieldItem.formatColor - ? fieldItem.formatColor(fieldItem.value) - : fieldItem.value; - colorInputElement.onchange = (event) => - this._fieldChanging( - fieldItem, - fieldItem.parseColor - ? fieldItem.parseColor(colorInputElement.value) - : colorInputElement.value - ); + colorInputElement.value = formatColor(fieldItem.value); + + { + // color picker change closure + let valueStream = undefined; + + colorInputElement.oninput = (event) => { + const value = parseColor(colorInputElement.value); + if (!valueStream) { + valueStream = new QueueIterator(5, true); + this._fieldChanging(fieldItem, value, valueStream); + } + + if (valueStream) { + valueStream.put(value); + this._dispatchEvent("doChange", { key: fieldItem.key, value: value }); + } else { + this._fieldChanging(fieldItem, value, undefined); + } + }; + + colorInputElement.onchange = (event) => { + if (valueStream) { + valueStream.done(); + valueStream = undefined; + this._dispatchEvent("endChange", { key: fieldItem.key }); + } else { + this._dispatchEvent("doChange", { key: fieldItem.key, value: value }); + } + }; + } + valueElement.appendChild(colorInputElement); } From e016825facb8c23a1b774b8d28175af0a2f59e9a Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 10:11:01 +0100 Subject: [PATCH 11/17] Don't delete the cached colorized image to avoid flickering: better to show the wrong color briefly than no image --- src/fontra/client/core/font-controller.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fontra/client/core/font-controller.js b/src/fontra/client/core/font-controller.js index 497ef52f1..fa67618e2 100644 --- a/src/fontra/client/core/font-controller.js +++ b/src/fontra/client/core/font-controller.js @@ -145,7 +145,6 @@ export class FontController { } const cacheEntry = this._getBackgroundImageCacheEntry(imageIdentifier); if (cacheEntry.color !== color) { - delete cacheEntry.imageColorized; cacheEntry.color = color; cacheEntry.imageColorizedPromise = new Promise((resolve, reject) => { cacheEntry.imagePromise.then((image) => { From 76edfa5c190636a774d04519293af5a2bf848f96 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 13:13:19 +0100 Subject: [PATCH 12/17] Return timeoutID from scheduled call --- src/fontra/client/core/utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fontra/client/core/utils.js b/src/fontra/client/core/utils.js index d3d82fb82..9a8d96b87 100644 --- a/src/fontra/client/core/utils.js +++ b/src/fontra/client/core/utils.js @@ -63,6 +63,7 @@ export function scheduleCalls(func, timeout = 0) { timeoutID = null; func(...args); }, timeout); + return timeoutID; }; } From fdcdb0206526e757c7a66408515d621caffd8316 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 13:23:28 +0100 Subject: [PATCH 13/17] Allow color picker changes to be scheduled to prevent flooding the listener --- src/fontra/client/web-components/ui-form.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/fontra/client/web-components/ui-form.js b/src/fontra/client/web-components/ui-form.js index 5255eeb28..2dc0fd905 100644 --- a/src/fontra/client/web-components/ui-form.js +++ b/src/fontra/client/web-components/ui-form.js @@ -1,7 +1,12 @@ import * as html from "../core/html-utils.js"; import { SimpleElement } from "../core/html-utils.js"; import { QueueIterator } from "../core/queue-iterator.js"; -import { enumerate, hyphenatedToCamelCase, round } from "../core/utils.js"; +import { + enumerate, + hyphenatedToCamelCase, + round, + scheduleCalls, +} from "../core/utils.js"; import { RangeSlider } from "/web-components/range-slider.js"; import "/web-components/rotary-control.js"; @@ -420,7 +425,7 @@ export class Form extends SimpleElement { // color picker change closure let valueStream = undefined; - colorInputElement.oninput = (event) => { + const oninputFunc = scheduleCalls((event) => { const value = parseColor(colorInputElement.value); if (!valueStream) { valueStream = new QueueIterator(5, true); @@ -433,12 +438,22 @@ export class Form extends SimpleElement { } else { this._fieldChanging(fieldItem, value, undefined); } + }, fieldItem.continuousDelay || 0); + + let oninputTimer; + + colorInputElement.oninput = (event) => { + oninputTimer = oninputFunc(event); }; colorInputElement.onchange = (event) => { if (valueStream) { valueStream.done(); valueStream = undefined; + if (oninputTimer) { + clearTimeout(oninputTimer); + oninputTimer = undefined; + } this._dispatchEvent("endChange", { key: fieldItem.key }); } else { this._dispatchEvent("doChange", { key: fieldItem.key, value: value }); From ba0674628a74769809bd36c4f04d34119b851efb Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 13:24:16 +0100 Subject: [PATCH 14/17] Make sure we don't get flooded with colorize requests --- src/fontra/views/editor/panel-selection-info.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/fontra/views/editor/panel-selection-info.js b/src/fontra/views/editor/panel-selection-info.js index 00a631e22..192e7058c 100644 --- a/src/fontra/views/editor/panel-selection-info.js +++ b/src/fontra/views/editor/panel-selection-info.js @@ -297,6 +297,7 @@ export default class SelectionInfoPanel extends Panel { type: "color-picker", key: backgroundImageKey("color"), label: translate("background-image.labels.colorize"), + continuousDelay: 150, value: backgroundImage.color, parseColor: (value) => { const matches = value.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i); From 0cc15c42be3fd008d1db9b3993de005b75b90e60 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 13:52:29 +0100 Subject: [PATCH 15/17] Add checkbox to enable/disable colorization --- src/fontra/client/web-components/ui-form.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/fontra/client/web-components/ui-form.js b/src/fontra/client/web-components/ui-form.js index 2dc0fd905..f86c0648b 100644 --- a/src/fontra/client/web-components/ui-form.js +++ b/src/fontra/client/web-components/ui-form.js @@ -84,6 +84,11 @@ export class Form extends SimpleElement { height: 1.6em; } + .ui-form-value input[type="checkbox"] { + width: initial; + height: initial; + } + .ui-form-value input[type="color"] { height: 2em; width: 4em; @@ -426,6 +431,7 @@ export class Form extends SimpleElement { let valueStream = undefined; const oninputFunc = scheduleCalls((event) => { + checkboxElement.checked = true; const value = parseColor(colorInputElement.value); if (!valueStream) { valueStream = new QueueIterator(5, true); @@ -447,6 +453,7 @@ export class Form extends SimpleElement { }; colorInputElement.onchange = (event) => { + checkboxElement.checked = true; if (valueStream) { valueStream.done(); valueStream = undefined; @@ -462,6 +469,19 @@ export class Form extends SimpleElement { } valueElement.appendChild(colorInputElement); + + const checkboxElement = html.input({ + type: "checkbox", + checked: !!fieldItem.value, + onchange: (event) => { + this._fieldChanging( + fieldItem, + checkboxElement.checked ? parseColor(colorInputElement.value) : undefined, + undefined + ); + }, + }); + valueElement.appendChild(checkboxElement); } addEventListener(eventName, handler, options) { From 638db6e7babe76447ea23cd4e80aae94ee1b9b4f Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 14:10:30 +0100 Subject: [PATCH 16/17] Make checkbox optional --- src/fontra/client/web-components/ui-form.js | 35 +++++++++++-------- .../views/editor/panel-selection-info.js | 1 + 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/fontra/client/web-components/ui-form.js b/src/fontra/client/web-components/ui-form.js index f86c0648b..bdea2d094 100644 --- a/src/fontra/client/web-components/ui-form.js +++ b/src/fontra/client/web-components/ui-form.js @@ -423,6 +423,7 @@ export class Form extends SimpleElement { const parseColor = fieldItem.parseColor || ((v) => v); const formatColor = fieldItem.formatColor || ((v) => v); + let checkboxElement; const colorInputElement = html.input({ type: "color" }); colorInputElement.value = formatColor(fieldItem.value); @@ -431,7 +432,9 @@ export class Form extends SimpleElement { let valueStream = undefined; const oninputFunc = scheduleCalls((event) => { - checkboxElement.checked = true; + if (checkboxElement) { + checkboxElement.checked = true; + } const value = parseColor(colorInputElement.value); if (!valueStream) { valueStream = new QueueIterator(5, true); @@ -453,7 +456,9 @@ export class Form extends SimpleElement { }; colorInputElement.onchange = (event) => { - checkboxElement.checked = true; + if (checkboxElement) { + checkboxElement.checked = true; + } if (valueStream) { valueStream.done(); valueStream = undefined; @@ -470,18 +475,20 @@ export class Form extends SimpleElement { valueElement.appendChild(colorInputElement); - const checkboxElement = html.input({ - type: "checkbox", - checked: !!fieldItem.value, - onchange: (event) => { - this._fieldChanging( - fieldItem, - checkboxElement.checked ? parseColor(colorInputElement.value) : undefined, - undefined - ); - }, - }); - valueElement.appendChild(checkboxElement); + if (fieldItem.allowNoColor) { + checkboxElement = html.input({ + type: "checkbox", + checked: !!fieldItem.value, + onchange: (event) => { + this._fieldChanging( + fieldItem, + checkboxElement.checked ? parseColor(colorInputElement.value) : undefined, + undefined + ); + }, + }); + valueElement.appendChild(checkboxElement); + } } addEventListener(eventName, handler, options) { diff --git a/src/fontra/views/editor/panel-selection-info.js b/src/fontra/views/editor/panel-selection-info.js index 192e7058c..b736ab9b6 100644 --- a/src/fontra/views/editor/panel-selection-info.js +++ b/src/fontra/views/editor/panel-selection-info.js @@ -298,6 +298,7 @@ export default class SelectionInfoPanel extends Panel { key: backgroundImageKey("color"), label: translate("background-image.labels.colorize"), continuousDelay: 150, + allowNoColor: true, value: backgroundImage.color, parseColor: (value) => { const matches = value.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i); From 6af58b34d53108a0c819dee7a061dbcb821b1923 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Wed, 20 Nov 2024 14:12:25 +0100 Subject: [PATCH 17/17] Add colorize label --- src/fontra/client/lang/de.js | 1 + src/fontra/client/lang/en.js | 1 + src/fontra/client/lang/fr.js | 1 + src/fontra/client/lang/ja.js | 1 + src/fontra/client/lang/nl.js | 1 + src/fontra/client/lang/zh-CN.js | 1 + 6 files changed, 6 insertions(+) diff --git a/src/fontra/client/lang/de.js b/src/fontra/client/lang/de.js index 367b79022..c7116337c 100644 --- a/src/fontra/client/lang/de.js +++ b/src/fontra/client/lang/de.js @@ -101,6 +101,7 @@ export const strings = { "axes.undo.add": "Achse %0 hinzufügen", "axes.undo.delete": "Achse %0 entfernen", "axes.undo.edit": "Achse %0 bearbeiten", + "background-image.labels.colorize": "Colorize", "background-image.labels.opacity": "Transparenz", "canvas.clean-view-and-hand-tool": "Ungehinderte Sicht und Hand Werkzeug", "cross-axis-mapping.axis-participates": diff --git a/src/fontra/client/lang/en.js b/src/fontra/client/lang/en.js index 23abb9c54..332e45392 100644 --- a/src/fontra/client/lang/en.js +++ b/src/fontra/client/lang/en.js @@ -101,6 +101,7 @@ export const strings = { "axes.undo.add": "add axis %0", "axes.undo.delete": "delete axis %0", "axes.undo.edit": "edit axis %0", + "background-image.labels.colorize": "Colorize", "background-image.labels.opacity": "Opacity", "canvas.clean-view-and-hand-tool": "Clean View and Hand Tool", "cross-axis-mapping.axis-participates": diff --git a/src/fontra/client/lang/fr.js b/src/fontra/client/lang/fr.js index 3717b9a7b..3bbce8312 100644 --- a/src/fontra/client/lang/fr.js +++ b/src/fontra/client/lang/fr.js @@ -101,6 +101,7 @@ export const strings = { "axes.undo.add": "add axis %0", "axes.undo.delete": "delete axis %0", "axes.undo.edit": "edit axis %0", + "background-image.labels.colorize": "Colorize", "background-image.labels.opacity": "Opacity", "canvas.clean-view-and-hand-tool": "Prévisualisation et outil de déplacement", "cross-axis-mapping.axis-participates": diff --git a/src/fontra/client/lang/ja.js b/src/fontra/client/lang/ja.js index 3405b3550..a882704c3 100644 --- a/src/fontra/client/lang/ja.js +++ b/src/fontra/client/lang/ja.js @@ -101,6 +101,7 @@ export const strings = { "axes.undo.add": "補完軸%0を追加", "axes.undo.delete": "補完軸%0を削除", "axes.undo.edit": "補完軸%0を編集", + "background-image.labels.colorize": "Colorize", "background-image.labels.opacity": "Opacity", "canvas.clean-view-and-hand-tool": "塗りのプレビューと手のひらツール", "cross-axis-mapping.axis-participates": diff --git a/src/fontra/client/lang/nl.js b/src/fontra/client/lang/nl.js index baf544225..ba86c2da9 100644 --- a/src/fontra/client/lang/nl.js +++ b/src/fontra/client/lang/nl.js @@ -101,6 +101,7 @@ export const strings = { "axes.undo.add": "add axis %0", "axes.undo.delete": "delete axis %0", "axes.undo.edit": "edit axis %0", + "background-image.labels.colorize": "Colorize", "background-image.labels.opacity": "Opacity", "canvas.clean-view-and-hand-tool": "Schone weergave en Hand gereedschap", "cross-axis-mapping.axis-participates": diff --git a/src/fontra/client/lang/zh-CN.js b/src/fontra/client/lang/zh-CN.js index 9637becbe..c7b93362b 100644 --- a/src/fontra/client/lang/zh-CN.js +++ b/src/fontra/client/lang/zh-CN.js @@ -101,6 +101,7 @@ export const strings = { "axes.undo.add": "添加参数轴 %0", "axes.undo.delete": "删除参数轴 %0", "axes.undo.edit": "编辑参数轴 %0", + "background-image.labels.colorize": "Colorize", "background-image.labels.opacity": "透明度", "canvas.clean-view-and-hand-tool": "预览与拖拽工具", "cross-axis-mapping.axis-participates": "选中后,该参数轴参与映射",