Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display current character in reference fonts #997

Merged
merged 22 commits into from
Dec 22, 2023
Merged
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
297c213
Display current character in reference fonts
fatih-erikli Nov 23, 2023
0f13728
Current glyph overridden by custom character
fatih-erikli Nov 23, 2023
be0a699
Display character field instead of glyphName
fatih-erikli Nov 23, 2023
2793330
Display the glyph by codepoint if the glyph name contains dot
fatih-erikli Dec 4, 2023
cf1c545
Move the slider before text
fatih-erikli Dec 13, 2023
55b4ee8
Listen to oninput event
fatih-erikli Dec 13, 2023
df0cca9
Convert range input into range slider
fatih-erikli Dec 14, 2023
c846583
Font size max 200
fatih-erikli Dec 14, 2023
7b78e6c
Apply language code
fatih-erikli Dec 14, 2023
1b1128f
Delete async function
fatih-erikli Dec 14, 2023
6944d5c
Fontsize persisted in localstorage
fatih-erikli Dec 15, 2023
43adbab
Listen to language code input when rendering reference font example
fatih-erikli Dec 15, 2023
58be6a4
Ensure reference fonts preview loaded once at a time
fatih-erikli Dec 18, 2023
cb4da8c
Fix overlapping grid cell
fatih-erikli Dec 18, 2023
e46d8f7
Exclude range slider from scroll area
fatih-erikli Dec 19, 2023
6a8d2c7
Delete unused import
fatih-erikli Dec 20, 2023
c5bc0d3
Make max fontsize 300, Add default value
fatih-erikli Dec 20, 2023
c518468
Make font-size constant
fatih-erikli Dec 20, 2023
477890a
Delete duplicated code block
fatih-erikli Dec 21, 2023
c027b77
Delete the element children by setting innerHTML empty string
fatih-erikli Dec 21, 2023
c7eabc8
Listen to selectedGlyphName key
fatih-erikli Dec 21, 2023
8335acb
Use a string key name for listening to a single event name
fatih-erikli Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 152 additions & 22 deletions src/fontra/views/editor/panel-reference-font.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import Panel from "./panel.js";
import * as html from "/core/html-utils.js";

import { div, input, label, option, select } from "/core/html-utils.js";
import { getSelectedGlyphInfo } from "./scene-model.js";
import {
createDomElement,
div,
input,
label,
option,
select,
span,
} from "/core/html-utils.js";
import { ObservableController } from "/core/observable-object.js";
import { fetchJSON, fileNameExtension, withTimeout } from "/core/utils.js";
import { dialog } from "/web-components/modal-dialog.js";
import "/web-components/range-slider.js";
import { UIList } from "/web-components/ui-list.js";

import "/third-party/lib-font/inflate.js";
Expand All @@ -19,6 +28,7 @@ import { registerVisualizationLayerDefinition } from "./visualization-layer-defi
let referenceFontModel;

const fontFileExtensions = new Set(["ttf", "otf", "woff", "woff2"]);
const DEFAULT_FONT_SIZE = 100;

registerVisualizationLayerDefinition({
identifier: "fontra.reference.font",
Expand Down Expand Up @@ -244,6 +254,19 @@ export default class ReferenceFontPanel extends Panel {
font-family: fontra-ui-regular;
font-feature-settings: "tnum" 1;
}

.current-character {
overflow: auto;
}

.current-character-font-size {
width: 100%;
}

.reference-font-preview {
display: grid;
overflow: auto;
}
`;

constructor(editorController) {
Expand All @@ -264,15 +287,115 @@ export default class ReferenceFontPanel extends Panel {

this.controller.addKeyListener("charOverride", (event) => {
this.editorController.canvasController.requestUpdate();
this.requestReferenceFontsPreview();
});

this.controller.addKeyListener("languageCode", (event) => {
this.editorController.canvasController.setLangAttribute(this.model.languageCode);
this.requestReferenceFontsPreview();
});

this.editorController.canvasController.setLangAttribute(this.model.languageCode);

referenceFontModel = this.model;

this.editorController.sceneSettingsController.addKeyListener(
["selectedGlyph", "glyphLines"],
justvanrossum marked this conversation as resolved.
Show resolved Hide resolved
(event) => {
this.requestReferenceFontsPreview();
}
);
}

async requestReferenceFontsPreview() {
if (this.referenceFontsPreviewPromise) {
return this.referenceFontsPreviewPromise;
}
this.referenceFontsPreviewPromise = this.displayCurrentGlyphInReferenceFonts();
await this.referenceFontsPreviewPromise;
delete this.referenceFontsPreviewPromise;
}

async displayCurrentGlyphInReferenceFonts() {
const container = this.contentElement.querySelector(".reference-font-preview");
while (container.firstChild) {
justvanrossum marked this conversation as resolved.
Show resolved Hide resolved
container.removeChild(container.firstChild);
}
const selectedGlyphInfo = getSelectedGlyphInfo(
this.editorController.sceneSettings.selectedGlyph,
this.editorController.sceneSettings.glyphLines
);

let textToDisplay;

if (this.model.charOverride) {
textToDisplay = this.model.charOverride.charAt(0);
} else {
if (selectedGlyphInfo) {
if (selectedGlyphInfo.glyphName.includes(".")) {
const baseGlyphName = selectedGlyphInfo.glyphName.split(".")[0];
const codePoint = (this.editorController.fontController.glyphMap[
baseGlyphName
] || [])[0];
if (codePoint) {
textToDisplay = String.fromCodePoint(codePoint);
}
} else {
textToDisplay = selectedGlyphInfo.character;
}
}
}

if (!textToDisplay) {
return;
}

if (
!textToDisplay &&
selectedGlyphInfo &&
selectedGlyphInfo.glyphName.includes(".")
) {
const baseGlyphName = positionedGlyph.glyphName.split(".")[0];
justvanrossum marked this conversation as resolved.
Show resolved Hide resolved
const codePoint = (this.editorController.fontController.glyphMap[baseGlyphName] ||
[])[0];
if (codePoint) {
textToDisplay = String.fromCodePoint(codePoint);
}
}

if (!textToDisplay) {
return;
}

const currentCharacter = div(
{
class: "current-character",
style: `font-size: ${this.model.fontSize}px`,
lang: this.model.languageCode,
},
[]
);
const rangeSlider = createDomElement("range-slider", {
type: "range",
value: this.model.fontSize,
minValue: 10,
defaultValue: DEFAULT_FONT_SIZE,
maxValue: 300,
step: 0.1,
onChangeCallback: (event) => {
currentCharacter.style.fontSize = `${event.value}px`;
this.model.fontSize = event.value;
},
});

for (const font of this.model.fontList) {
await this.ensureFontLoaded(font);
currentCharacter.appendChild(
span({ style: `font-family: ${font.fontIdentifier};` }, [` ${textToDisplay}`])
);
}
container.appendChild(rangeSlider);
container.appendChild(currentCharacter);
}

_fontListChangedHandler(event) {
Expand Down Expand Up @@ -366,18 +489,7 @@ export default class ReferenceFontPanel extends Panel {
});
}

async _listSelectionChangedHandler() {
const fontItem = this.filesUIList.getSelectedItem();
if (!fontItem) {
this.model.referenceFontName = "";
this.model.selectedFontIndex = -1;
return;
}

const selectedFontIndex = this.filesUIList.getSelectedItemIndex();
this.model.selectedFontIndex =
selectedFontIndex !== undefined ? selectedFontIndex : -1;

async ensureFontLoaded(fontItem) {
if (!fontItem.fontFace) {
if (!fontItem.objectURL) {
fontItem.objectURL = URL.createObjectURL(
Expand All @@ -392,6 +504,21 @@ export default class ReferenceFontPanel extends Panel {
document.fonts.add(fontItem.fontFace);
await fontItem.fontFace.load();
}
}

async _listSelectionChangedHandler() {
const fontItem = this.filesUIList.getSelectedItem();
if (!fontItem) {
this.model.referenceFontName = "";
this.model.selectedFontIndex = -1;
return;
}

const selectedFontIndex = this.filesUIList.getSelectedItemIndex();
this.model.selectedFontIndex =
selectedFontIndex !== undefined ? selectedFontIndex : -1;

await this.ensureFontLoaded(fontItem);
this.model.referenceFontName = fontItem.fontIdentifier;

if (fontItem.fontIdentifier in this.supportedLanguagesMemoized) {
Expand Down Expand Up @@ -479,15 +606,17 @@ export default class ReferenceFontPanel extends Panel {

this.controller = new ObservableController({
languageCode: "",
fontSize: DEFAULT_FONT_SIZE,
selectedFontIndex: -1,
fontList: [],
charOverride: "",
referenceFontName: "",
});
this.controller.synchronizeWithLocalStorage("fontra.reference-font.");
this.controller.addKeyListener("fontList", (event) =>
this._fontListChangedHandler(event)
);
this.controller.addKeyListener("fontList", (event) => {
this._fontListChangedHandler(event);
this.requestReferenceFontsPreview();
});
garbageCollectUnusedFiles(this.model.fontList);

const columnDescriptions = [
Expand All @@ -505,9 +634,9 @@ export default class ReferenceFontPanel extends Panel {

this.filesUIList.onFilesDrop = (files) => this._filesDropHandler(files);

this.filesUIList.addEventListener("listSelectionChanged", () =>
this._listSelectionChangedHandler()
);
this.filesUIList.addEventListener("listSelectionChanged", () => {
this._listSelectionChangedHandler();
});

this.filesUIList.addEventListener("deleteKey", () =>
this._deleteSelectedItemHandler()
Expand All @@ -530,12 +659,12 @@ export default class ReferenceFontPanel extends Panel {
[]
);

return html.div(
return div(
{
class: "sidebar-reference-font",
},
[
html.div(
div(
{
id: "reference-font",
},
Expand Down Expand Up @@ -566,6 +695,7 @@ export default class ReferenceFontPanel extends Panel {
this.languageCodeInput,
]
),
div({ class: "reference-font-preview" }, []),
]
),
]
Expand Down