Comment l'application de retouche d'images vectorielles Boxy SVG utilise l'API Local Font Access pour permettre aux utilisateurs de choisir leurs polices locales préférées

L'API Local Font Access fournit un mécanisme permettant d'accéder aux données de police installées localement par l'utilisateur, y compris des détails de niveau supérieur tels que les noms, les styles et les familles, ainsi que les octets bruts des fichiers de police sous-jacents. Découvrez comment l'appli de retouche SVG Boxy SVG utilise cette API.

Introduction

(Cet article est également disponible sous forme de vidéo).

Boxy SVG est un éditeur de graphique vectoriel. Son principal cas d'utilisation consiste à modifier des dessins au format SVG, pour créer des illustrations, des logos, des icônes et d'autres éléments de conception graphique. Il a été développé par le développeur polonais Jarosław Foksa et est sorti initialement le 15 mars 2013. Jarosław tient un blog Boxy SVG dans lequel il annonce les nouvelles fonctionnalités qu'il ajoute à l'application. Le développeur est un fervent défenseur du projet Fugu de Chromium et a même ajouté un tag Fugu dans l'outil de suivi des idées de l'application.

L'application SVG Boxy modifiant le fichier SVG de l'icône Project Fugu.

API Local Font Access dans Boxy SVG

L'API Local Font Access est une fonctionnalité que Jarosław a évoquée dans son blog. L'API Local Font Access permet aux utilisateurs d'accéder aux polices installées localement, y compris des détails de niveau supérieur tels que les noms, les styles et les familles, ainsi qu'aux octets bruts des fichiers de police sous-jacents. Dans la capture d'écran suivante, vous pouvez voir comment j'ai autorisé l'application à accéder aux polices installées localement sur mon MacBook et choisi la police "Marker Felt" pour mon texte.

L'application SVG Boxy modifiant l'icône SVG Project Fugu et ajoutant le texte "Project Fugu rocks" défini dans le feutre de la police, qui est sélectionné dans le sélecteur de police

Le code sous-jacent est assez simple. Lorsque l'utilisateur ouvre l'outil de sélection de famille de polices pour la première fois, l'application vérifie d'abord si le navigateur Web est compatible avec l'API Local Font Access.

Il recherche également l'ancienne version expérimentale de l'API et l'utilise, le cas échéant. Depuis 2023, vous pouvez ignorer l'ancienne API en toute sécurité, car elle n'était disponible que pendant une courte période via les indicateurs Chrome expérimentaux. Toutefois, certains dérivés de Chromium peuvent continuer à l'utiliser.

let isLocalFontsApiEnabled = (
  // Local Font Access API, Chrome >= 102
  window.queryLocalFonts !== undefined ||
  // Experimental Local Font Access API, Chrome < 102
  navigator.fonts?.query !== undefined
);

Si l'API Local Font Access n'est pas disponible, l'outil de sélection de famille de polices devient gris. Un espace réservé s'affichera pour l'utilisateur à la place de la liste des polices:

if (isLocalFontsApiEnabled === false) {
  showPlaceholder("no-local-fonts-api");
  return;
}

Sélecteur de police affichant le message &quot;Your browser is not support the Local Font Access API&quot; (Votre navigateur n&#39;est pas compatible avec l&#39;API Local Font Access).

Sinon, l'API Local Font Access est utilisée pour récupérer la liste de toutes les polices à partir du système d'exploitation. Notez le bloc try…catch, qui est nécessaire pour gérer correctement les erreurs d'autorisation.

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

Une fois la liste des polices locales récupérée, un fontsIndex simplifié et normalisé est créé à partir de celle-ci:

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'index des polices normalisées est ensuite stocké dans la base de données IndexedDB afin de pouvoir être facilement interrogé, partagé entre les instances d'application et préservé entre les sessions. Boxy SVG utilise Dexie.js pour gérer la base de données:

let database = new Dexie("LocalFontsManager");
database.version(1).stores({cache: "family"}).
await database.cache.clear();
await database.cache.bulkPut(fontsIndex);

Section &quot;Stockage des outils pour les développeurs Chrome&quot; affichant la table IndexedDB avec le cache des polices.

Une fois la base de données renseignée, le widget de sélection de police peut l'interroger et afficher les résultats à l'écran:

Sélecteur de police renseigné avec des polices.

Notez que Boxy SVG affiche la liste dans un élément personnalisé nommé <bx-fontfamilypicker> et applique un style à chaque élément de la liste de polices afin qu'elle s'affiche dans la famille de polices concernée. Pour isoler les éléments du reste de la page, Boxy SVG utilise le Shadow DOM dans cet élément et dans d'autres éléments personnalisés.

Panneau Chrome DevTools Elements affichant le sélecteur de police en cours d&#39;inspection: un élément personnalisé nommé &quot;bx-fontfamiliypicker&quot;.

Conclusions

La fonctionnalité de police locale est très populaire, et les utilisateurs apprécient d'avoir accès à leurs polices locales pour leurs conceptions et créations. Lorsque la forme de l'API a changé et que la fonctionnalité est tombée en panne brièvement, les utilisateurs l'ont immédiatement noté. Jarosław n'a pas tardé à remplacer le code par le modèle défensif que vous voyez dans l'extrait ci-dessus. Celui-ci fonctionne avec la dernière version de Chrome, ainsi qu'avec d'autres dérivés de Chromium qui ne sont peut-être pas passés à la dernière version. Essayez Boxy SVG et vérifiez les polices installées localement. Vous découvrirez peut-être des classiques oubliés depuis longtemps, tels que Zapf Dingbats ou Webdings.