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 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.

L'app Boxy SVG che modifica l'icona SVG di Project Fugu.

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.

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

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

Il selettore dei caratteri mostra il messaggio &quot;Il tuo 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. 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);

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

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

Selettore di caratteri compilato con i caratteri.

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.

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

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.