L'API Local Font Access fornisce un meccanismo per accedere ai dati dei caratteri installati localmente, inclusi dettagli di livello superiore come nomi, stili e famiglie, nonché i byte non elaborati dei file di caratteri sottostanti. Scopri come l'app di modifica SVG Boxy SVG utilizza questa API.
Introduzione
Questo articolo è disponibile anche sotto forma di video.
Boxy SVG è un editor di grafica vettoriale. Il suo caso d'uso principale è la modifica di disegni nel formato file SVG, per la creazione di illustrazioni, loghi, icone e altri elementi di design grafico. È stato sviluppato dallo sviluppatore polacco Jarosław Foksa ed è stato inizialmente rilasciato il 15 marzo 2013. Jarosław gestisce un blog Boxy SVG in cui annuncia le nuove funzionalità che aggiunge all'app. Lo sviluppatore è un grande sostenitore di Project Fugu di Chromium e ha persino un tag Fugu nel tracker delle idee dell'app.
API Accesso ai caratteri locali in Boxy SVG
Una delle funzionalità aggiunte di cui Jarosław ha scritto nel suo blog è l'API Local Fonts Access. L'API Local Font Access consente agli utenti di accedere ai caratteri installati localmente, compresi i dettagli di livello superiore come nomi, stili e famiglie, nonché ai byte non elaborati dei file dei caratteri sottostanti. Nello screenshot seguente puoi vedere come ho concesso all'app l'accesso ai caratteri installati localmente sul mio MacBook e come ho scelto il carattere Marker Felt per il mio testo.
Il codice sottostante è piuttosto semplice. Quando l'utente apre il selettore della famiglia di caratteri per la prima volta, l'applicazione verifica innanzitutto se il browser web supporta l'API Local Font Access.
Controlla anche la vecchia versione sperimentale dell'API e la utilizza se presente. A partire dal 2023, puoi ignorare in tutta sicurezza la vecchia API, poiché era disponibile solo per poco tempo tramite i flag sperimentali di Chrome, ma alcuni derivati di Chromium potrebbero ancora utilizzarla.
let isLocalFontsApiEnabled = (
// Local Font Access API, Chrome >= 102
window.queryLocalFonts !== undefined ||
// Experimental Local Font Access API, Chrome < 102
navigator.fonts?.query !== undefined
);
Se l'API Accesso ai caratteri locali non è disponibile, il selettore di famiglie di caratteri diventa grigio. All'utente verrà mostrato un testo segnaposto anziché l'elenco dei caratteri:
if (isLocalFontsApiEnabled === false) {
showPlaceholder("no-local-fonts-api");
return;
}
Altrimenti, viene utilizzata l'API Local Font Access per recuperare l'elenco di tutti i caratteri dal sistema operativo. Tieni presente il blocco try…catch
necessario per gestire correttamente gli errori di autorizzazione.
let localFonts;
if (isLocalFontsApiEnabled === true) {
try {
// Local Font Access API, Chrome >= 102
if (window.queryLocalFonts) {
localFonts = await window.queryLocalFonts();
}
// Experimental Local Font Access API, Chrome < 102
else if (navigator.fonts?.query) {
localFonts = await navigator.fonts.query({
persistentAccess: true,
});
}
} catch (error) {
showError(error.message, error.name);
}
}
Una volta recuperato l'elenco di caratteri locali, viene creato un file fontsIndex
semplificato e normalizzato:
let fontsIndex = [];
for (let localFont of localFonts) {
let face = "400";
// Determine the face name
{
let subfamily = localFont.style.toLowerCase();
subfamily = subfamily.replaceAll(" ", "");
subfamily = subfamily.replaceAll("-", "");
subfamily = subfamily.replaceAll("_", "");
if (subfamily.includes("thin")) {
face = "100";
} else if (subfamily.includes("extralight")) {
face = "200";
} else if (subfamily.includes("light")) {
face = "300";
} else if (subfamily.includes("medium")) {
face = "500";
} else if (subfamily.includes("semibold")) {
face = "600";
} else if (subfamily.includes("extrabold")) {
face = "800";
} else if (subfamily.includes("ultrabold")) {
face = "900";
} else if (subfamily.includes("bold")) {
face = "700";
}
if (subfamily.includes("italic")) {
face += "i";
}
}
let descriptor = fontsIndex.find((descriptor) => {
return descriptor.family === localFont.family);
});
if (descriptor) {
if (descriptor.faces.includes(face) === false) {
descriptor.faces.push(face);
}
} else {
let descriptor = {
family: localFont.family,
faces: [face],
};
fontsIndex.push(descriptor);
}
}
for (let descriptor of fontsIndex) {
descriptor.faces.sort();
}
L'indice dei caratteri normalizzati viene poi archiviato nel database IndexedDB in modo che possa essere facilmente sottoposto a query, condiviso tra le istanze dell'app e conservato tra le sessioni. Il formato SVG boxy utilizza Dexie.js per gestire il database:
let database = new Dexie("LocalFontsManager");
database.version(1).stores({cache: "family"}).
await database.cache.clear();
await database.cache.bulkPut(fontsIndex);
Una volta compilato il database, il widget del selettore caratteri può eseguire query e visualizzare i risultati sullo schermo:
Vale la pena ricordare che Boxy SVG esegue il rendering dell'elenco in un elemento personalizzato denominato <bx-fontfamilypicker>
e applica uno stile a ogni elemento dell'elenco dei caratteri in modo che venga visualizzato nella famiglia di caratteri in questione. Per isolare gli elementi dal resto della pagina, Boxy SVG utilizza shadow DOM in questo e in altri elementi personalizzati.
Conclusioni
La funzionalità caratteri locali ha riscosso molto successo e gli utenti si sono divertiti a utilizzare i caratteri locali per i loro design e le loro creazioni. Quando la forma dell'API è cambiata e la funzionalità si è interrotta per un breve periodo, gli utenti l'hanno notato immediatamente. Jarosław ha subito modificato il codice in modo da adottare il pattern difensivo che puoi vedere nello snippet riportato sopra, che funziona con Chrome aggiornato e anche con altri derivati di Chromium che potrebbero non aver eseguito la transizione alla versione più recente. Prova Boxy SVG e assicurati di controllare i caratteri installati localmente. Potresti scoprire alcuni classici dimenticati da tempo, come Zapf Dingbats o Webdings.