Come l'app di modifica di immagini vettoriale Boxy SVG utilizza l'API Local Font Access per consentire agli utenti di scegliere i loro caratteri locali preferiti

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.

Jarek Foksa
Jarek Foksa

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.

L'app SVG di Boxy che modifica il formato SVG dell'icona di Project Fugu.

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.

L'app SVG di Boxy che modifica l'icona SVG di Project Fugu aggiungendo il testo "Project Fugu rocks" impostato nel carattere Marker Felt, che viene mostrato selezionato nel selettore di caratteri.

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;
}

Selettore dei caratteri che mostra il messaggio &quot;Il browser non supporta l&#39;API Local Font Access&quot;.

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);

Sezione Spazio di archiviazione di Chrome DevTools che mostra la tabella IndexedDB con la cache dei caratteri.

Una volta che il database è completato, il widget di selezione dei caratteri può eseguire query e visualizzare i risultati sullo schermo:

Selettore dei caratteri completato con i caratteri.

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.

Riquadro Elementi di DevTools di Chrome che mostra il selettore di caratteri che viene controllato: un elemento personalizzato denominato &quot;bx-fontfamiliypicker&quot;.

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.