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

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

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

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

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

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

Una volta compilato il database, il widget del selettore caratteri può eseguire query e visualizzare i risultati sullo schermo:

Selettore caratteri riempito di 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 che viene controllato: un elemento personalizzato denominato &quot;bx-fontfamiliypicker&quot;.

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.