L'API Local Font Access fornisce un meccanismo per accedere ai dati dei caratteri installati localmente dell'utente, inclusi dettagli di livello superiore come nomi, stili e famiglie, nonché i byte non elaborati dei file dei caratteri sottostanti. Scopri in che modo 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, inclusi dettagli di livello superiore come nomi, stili e famiglie, nonché i 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 ho scelto il carattere Marker Felt per il mio testo.
Il codice sottostante è abbastanza semplice. Quando l'utente apre il selettore di famiglie di caratteri per la prima volta, l'applicazione controlla 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 diventerà grigio. All'utente verrà mostrato un testo segnaposto anziché l'elenco dei caratteri:
if (isLocalFontsApiEnabled === false) {
showPlaceholder("no-local-fonts-api");
return;
}
In caso contrario, 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 dei caratteri locali, viene creato un 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. Boxy SVG 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 di selezione dei 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à dei caratteri locali è stata molto apprezzata dagli utenti, che ora possono accedere ai propri caratteri locali per i loro progetti e le loro creazioni. Quando la forma dell'API è cambiata e la funzionalità non è stata disponibile per breve tempo, 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.