L'API Local Font Access offre un meccanismo per accedere ai dati sui caratteri installati localmente, 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 è modificare disegni nel formato file SVG, per creare illustrazioni, loghi, icone e altri elementi di graphic design. È sviluppato dallo sviluppatore polacco Jarosław Foksa e inizialmente è stato rilasciato il 15 marzo 2013. Jarosław gestisce un blog in formato SVG di Boxy in cui annuncia le nuove funzionalità che aggiunge all'app. Lo sviluppatore è un sostenitore convinto del progetto Fugu di Chromium e ha persino un tag Fuugu nello strumento di monitoraggio delle idee dell'app.
API Local Font Access in Boxy SVG
Un'aggiunta di funzionalità su cui Jarosław ha scritto sul blog era l'API Local Font 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. Nel seguente screenshot 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 è 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.
Verifica inoltre la vecchia versione sperimentale dell'API e la utilizza, se presente. A partire dal 2023, puoi ignorare tranquillamente la vecchia API poiché era disponibile solo per un breve periodo di tempo tramite 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 Local Font Access non è disponibile, il selettore della famiglia 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. Nota 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 fontsIndex
semplificato e normalizzato a partire da questo:
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 quindi archiviato nel database IndexedDB in modo che possa essere facilmente interrogato, condiviso tra istanze dell'app e mantenuto tra le sessioni. Il file SVG di 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 che il database è completato, il widget di selezione dei caratteri può eseguire query e visualizzare i risultati sullo schermo:
Vale la pena ricordare che il formato SVG di Boxy esegue il rendering dell'elenco in un elemento personalizzato denominato <bx-fontfamilypicker>
e applica uno stile a ciascun elemento dell'elenco di caratteri in modo che venga visualizzato nella specifica famiglia di caratteri. Per isolare il testo dal resto della pagina, il file SVG di Boxy utilizza il DOM Shadow in questo e in altri elementi personalizzati.
Conclusioni
La funzionalità dei caratteri locali ha riscosso un grande successo: gli utenti hanno apprezzato l'accesso ai caratteri locali per i design e le creazioni. Quando la forma dell'API è cambiata e la funzionalità non funzionava per breve tempo, gli utenti l'hanno annotata immediatamente. Jarosław è stato in grado di modificare rapidamente il codice adottando lo schema difensivo riportato nello snippet riportato sopra che funziona con la versione aggiornata di Chrome e con altre derivate di Chromium che potrebbero non essere passati all'ultima versione. Prova il formato SVG di Boxy e assicurati di dare un'occhiata ai caratteri installati localmente. Potresti scoprire alcuni classici dimenticati da tempo come Zapf Dingbats o Webdings.