A API Local Font Access oferece um mecanismo para acessar os dados de fontes instalados localmente do usuário, incluindo detalhes de nível superior, como nomes, estilos e famílias, além dos bytes brutos dos arquivos de fontes. Saiba como o app de edição SVG Boxy SVG usa essa API.
Introdução
Este artigo também está disponível em formato de vídeo.
O Boxy SVG é um editor de gráficos vetoriais. O principal caso de uso é editar desenhos no formato de arquivo SVG para criar ilustrações, logotipos, ícones e outros elementos de design gráfico. Ele foi desenvolvido pelo desenvolvedor polonês Jarosław Foksa e lançado inicialmente em 15 de março de 2013. Jarosław mantém um blog do Boxy SVG em que anuncia novos recursos adicionados ao app. O desenvolvedor é um grande defensor do Projeto Fugu do Chromium e até tem uma tag Fugu no rastreador de ideias do app.
API Local Fonts Access no SVG Boxy
Uma adição de recurso que Jarosław mencionou no blog foi a API Local Fonts Access. A API Local Fonts Access permite que os usuários acessem as fontes instaladas localmente, incluindo detalhes de nível mais alto, como nomes, estilos e famílias, além dos bytes brutos dos arquivos de fonte. Na captura de tela a seguir, você pode conferir como dei acesso ao app às fontes instaladas localmente no meu MacBook e escolhi a fonte Marker Felt para o texto.
O código é bastante simples. Quando o usuário abre o seletor da família de fontes pela primeira vez, o aplicativo verifica primeiro se o navegador da Web é compatível com a API Local Font Access.
Ela também verifica a versão experimental antiga da API e a usa, se estiver presente. A partir de 2023, você pode ignorar a API antiga com segurança, já que ela estava disponível apenas por um curto período com flags experimentais do Chrome, mas algumas derivadas do Chromium ainda podem usá-la.
let isLocalFontsApiEnabled = (
// Local Font Access API, Chrome >= 102
window.queryLocalFonts !== undefined ||
// Experimental Local Font Access API, Chrome < 102
navigator.fonts?.query !== undefined
);
Se a API Local Font Access não estiver disponível, o seletor de famílias de fontes ficará cinza. Um texto de marcador de posição será exibido para o usuário em vez da lista de fontes:
if (isLocalFontsApiEnabled === false) {
showPlaceholder("no-local-fonts-api");
return;
}
Caso contrário, a API Local Font Access é usada para recuperar a lista de todas as fontes do sistema operacional. Observe o bloco try…catch
, que é necessário para processar erros de permissão corretamente.
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);
}
}
Depois que a lista de fontes locais é recuperada, uma fontsIndex
simplificada e normalizada é criada a partir dela:
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();
}
O índice de fontes normalizado é armazenado no banco de dados IndexedDB para que possa ser consultado com facilidade, compartilhado entre instâncias de app e preservado entre sessões. O Boxy SVG usa o Dexie.js para gerenciar o banco de dados:
let database = new Dexie("LocalFontsManager");
database.version(1).stores({cache: "family"}).
await database.cache.clear();
await database.cache.bulkPut(fontsIndex);
Depois que o banco de dados é preenchido, o widget de seletor de fontes pode consultar e mostrar os resultados na tela:
Vale a pena mencionar que o Boxy SVG renderiza a lista em um elemento personalizado chamado <bx-fontfamilypicker>
e estiliza cada item da lista de fontes para que seja exibido na família de fontes específica. Para isolar o resto da página, o Boxy SVG usa o Shadow DOM neste e em outros elementos personalizados.
Conclusões
O recurso de fontes locais tem sido muito usado, e os usuários estão aproveitando o acesso às fontes locais para os designs e criações. Quando a forma da API mudou e o recurso foi interrompido por um breve período, os usuários notaram imediatamente. Jarosław mudou rapidamente o código para o padrão defensivo mostrado no snippet acima, que funciona com o Chrome atualizado e outros derivados do Chromium que talvez não tenham mudado para a versão mais recente. Teste o Boxy SVG e confira as fontes instaladas localmente. Talvez você encontre clássicos esquecidos, como Zapf Dingbats ou Webdings.