Как приложение для редактирования векторных изображений Boxy SVG использует API доступа к локальным шрифтам, чтобы пользователи могли выбирать свои любимые локальные шрифты

API локального доступа к шрифтам предоставляет механизм доступа к данным локально установленных пользователем шрифтов, включая сведения более высокого уровня, такие как имена, стили и семейства, а также необработанные байты базовых файлов шрифтов. Узнайте, как приложение для редактирования SVG Boxy SVG использует этот API.

Введение

(Эта статья также доступна в виде видео.)

Boxy SVG — редактор векторной графики. Его основной вариант использования — редактирование рисунков в формате SVG для создания иллюстраций, логотипов, значков и других элементов графического дизайна. Оно разработано польским разработчиком Ярославом Фоксой и первоначально выпущено 15 марта 2013 года. Ярослав ведет блог Boxy SVG , в котором объявляет о новых функциях, которые он добавляет в приложение. Разработчик активно поддерживает проект Fugu от Chromium и даже имеет тег Fugu на трекере идей приложения.

Приложение Boxy SVG редактирует SVG значка Project Fugu.

Локальный API доступа к шрифтам в Boxy SVG

Одной из дополнительных функций , о которой Ярослав написал в блоге, был API локального доступа к шрифтам . API локального доступа к шрифтам позволяет пользователям получать доступ к локально установленным шрифтам, включая детали более высокого уровня, такие как имена, стили и семейства, а также необработанные байты базовых файлов шрифтов. На следующем снимке экрана вы можете увидеть, как я предоставил приложению доступ к локально установленным шрифтам на моем MacBook и выбрал шрифт Marker Felt для своего текста.

Приложение Boxy SVG редактирует значок SVG Project Fugu, добавляя текст «Project Fugu Rocks», установленный шрифтом Marker Felt, который отображается выбранным в средстве выбора шрифтов.

Базовый код довольно прост. Когда пользователь впервые открывает средство выбора семейства шрифтов, приложение сначала проверяет, поддерживает ли веб-браузер API локального доступа к шрифтам.

Он также проверяет наличие старой экспериментальной версии API и использует ее, если она есть. Начиная с 2023 года вы можете смело игнорировать старый API, поскольку он был доступен лишь в течение короткого времени через экспериментальные флаги Chrome, но некоторые производные Chromium все еще могут его использовать.

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

Если API локального доступа к шрифтам недоступен, средство выбора семейства шрифтов станет серым. Вместо списка шрифтов пользователю будет отображаться текст-заполнитель:

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

В средстве выбора шрифтов отображается сообщение «Ваш браузер не поддерживает API локального доступа к шрифтам».

В противном случае API локального доступа к шрифтам используется для получения списка всех шрифтов из операционной системы. Обратите внимание на блок try…catch , который необходим для правильной обработки ошибок разрешений.

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

После получения списка локальных шрифтов из него создается упрощенный и нормализованный fontsIndex :

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

Индекс нормализованных шрифтов затем сохраняется в базе данных IndexedDB, чтобы его можно было легко запрашивать, совместно использовать между экземплярами приложения и сохранять между сеансами. Boxy SVG использует Dexie.js для управления базой данных:

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

В разделе «Хранилище Chrome DevTools» показана таблица IndexedDB с кешем шрифтов.

После заполнения базы данных виджет выбора шрифта может запросить ее и отобразить результаты на экране:

Выбор шрифта, заполненный шрифтами.

Стоит отметить, что Boxy SVG отображает список в пользовательском элементе с именем <bx-fontfamilypicker> и стилизует каждый элемент списка шрифтов так, чтобы он отображался в определенном семействе шрифтов. Чтобы изолировать от остальной части страницы, Boxy SVG использует Shadow DOM в этом и других пользовательских элементах.

Панель «Элементы Chrome DevTools», показывающая проверяемый элемент выбора шрифта: пользовательский элемент с именем «bx-fontfamiliypicker».

Выводы

Функция локальных шрифтов оказалась очень популярной: пользователи получили доступ к своим локальным шрифтам для своих проектов и творений. Когда форма API изменилась и функция ненадолго сломалась , пользователи это сразу заметили. Ярослав быстро изменил код на защитный шаблон, который вы можете видеть во фрагменте выше, который работает с последней версией Chrome, а также с другими производными Chromium, которые, возможно, не перешли на последнюю версию. Попробуйте Boxy SVG и обязательно проверьте локально установленные шрифты. Вы можете открыть для себя давно забытую классику, такую ​​как Zapf Dingbats или Webdings .