Usar tipografia avançada com fontes locais

Saiba como a API Local Font Access permite acessar as fontes instaladas localmente do usuário e conferir detalhes de baixo nível sobre elas

Fontes seguras para a Web

Se você já trabalha com desenvolvimento da Web há muito tempo, deve se lembrar da chamada fontes seguras para a Web. Essas fontes estão disponíveis em quase todas as instâncias dos sistemas operacionais mais usados. (ou seja, Windows, macOS, as distribuições mais comuns do Linux, Android e iOS). No início dos anos 2000, A Microsoft liderou até iniciativa chamadas fontes principais TrueType para a Web, que forneciam essas fontes para download sem custo financeiro com o que sempre que você visitar um site que as especifique, verá as páginas exatamente como pelo designer do site". Sim, isso inclui sites definidos no Comic Sans MS. Confira pilha de fontes clássicas para Web segura (com o substituto final de qualquer sans-serif ) pode ter esta aparência:

body {
  font-family: Helvetica, Arial, sans-serif;
}

Fontes da Web

A época em que as fontes seguras para a Web eram realmente importantes já se passaram. Hoje, temos fontes da Web, algumas das quais são até mesmo fontes variáveis, que podemos ajustar ainda mais alterando os valores da vários eixos expostos. Você pode usar fontes da Web declarando uma bloco @font-face no início do CSS, que especifica os arquivos de fonte para download:

@font-face {
  font-family: 'FlamboyantSansSerif';
  src: url('flamboyant.woff2');
}

Depois disso, você pode usar a fonte da Web personalizada especificando o font-family, normalmente:

body {
  font-family: 'FlamboyantSansSerif';
}

Fontes locais como vetor de impressão digital

A maioria das fontes da Web vem da Web. Um fato interessante, no entanto, é que os Propriedade src em @font-face de configuração, além das url() também aceita uma local() função. Isso permite que fontes personalizadas sejam carregadas (surpresa!) localmente. Se o usuário tiver FlamboyantSansSerif instalado no sistema operacional, a cópia local será usada em vez que está sendo baixado:

@font-face {
  font-family: 'FlamboyantSansSerif';
  src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}

Essa abordagem fornece um bom mecanismo substituto que potencialmente economiza largura de banda. Na Internet, infelizmente, não podemos ter coisas boas. O problema com a função local() é que ela pode ser usado para técnicas de impressão digital no navegador. A lista de fontes instaladas pelo usuário pode ser bastante se identifica. Muitas empresas têm suas próprias fontes corporativas instaladas nos laptops. Por exemplo, o Google tem uma fonte corporativa chamada Google Sans.

O app Font Book do macOS mostrando uma prévia da fonte Google Sans.
Fonte Google Sans instalada no laptop de um funcionário do Google.

Um invasor pode tentar determinar para qual empresa alguém trabalha testando a existência de um um grande número de fontes corporativas conhecidas, como Google Sans. O invasor tentaria renderizar o texto definido nessas fontes em uma tela e medir os glifos. Se os glifos corresponderem à forma conhecida do fonte corporativa, o atacante acerta. Se os glifos não forem correspondentes, o atacante saberá que um a fonte de substituição padrão foi usada porque a fonte corporativa não foi instalada. Para mais detalhes sobre este e outros ataques de impressão digital do navegador, leia documento de pesquisa de Laperdix et al.

mesmo que apenas a lista de fontes instaladas possa identificar as fontes da empresa. A situação esse vetor de ataque tornou-se tão ruim que, recentemente, a equipe do WebKit decidido para "incluir somente fontes da Web [na lista de fontes disponíveis] e fontes que vêm com o sistema do sistema, mas não para fontes instaladas pelo usuário localmente". (E aqui está eu, com um artigo sobre como conceder acesso para fontes locais.

API Local Font Access

O início deste artigo pode ter colocado você em um humor negativo. Será que não podemos ter recursos coisas Não se preocupe. Achamos que podemos, e talvez tudo não é sem esperança. Mas primeiro, deixe-me responder uma pergunta que você pode estar se fazendo.

Por que a API Local Font Access é necessária quando há fontes da Web?

Ferramentas gráficas e de design de qualidade profissional sempre foram difíceis de entregar da Web. Um problema é a incapacidade de acessar e usar toda a variedade de soluções fontes construídas e sugeridas que os designers instalaram localmente. Com as fontes da Web, é possível publicar mas não permitem o acesso programático às formas de glifo vetorial e às tabelas de fontes usadas pelo rasterizadores para renderizar os contornos de glifo. Da mesma forma, não é possível acessar o binário de uma fonte da Web dados.

  • As ferramentas de design precisam de acesso aos bytes de fonte para fazer a própria implementação do layout OpenType e permitir ferramentas de design para chamar a atenção em níveis mais baixos, para ações como realizar filtros vetoriais ou transformações nas formas glifo.
  • Os desenvolvedores podem ter pilhas de fontes legadas para os aplicativos que estão trazendo para a Web. Essas pilhas geralmente exigem acesso direto aos dados de fontes, algo que as fontes da Web não que oferecem.
  • Algumas fontes podem não estar licenciadas para exibição na Web. Por exemplo, o Linotype tem uma licença para algumas fontes que só são para uso em computadores.

A API Local Font Access é uma tentativa de resolver esses desafios. Ele consiste em duas partes:

  • Uma API de enumeração de fontes, que permite aos usuários conceder acesso a todo o conjunto de sistemas disponíveis fontes.
  • Para cada resultado de enumeração, a capacidade de solicitar o contêiner SFNT de baixo nível (orientado por byte) acesso que inclua os dados completos da fonte.

Suporte ao navegador

Compatibilidade com navegadores

  • Chrome: 103
  • Borda: 103.
  • Firefox: incompatível.
  • Safari: incompatível.

Origem

Como usar a API Local Font Access

Detecção de recursos

Para verificar se a API Local Font Access é compatível, use:

if ('queryLocalFonts' in window) {
  // The Local Font Access API is supported
}

Como enumerar fontes locais

Para conferir uma lista das fontes instaladas localmente, chame window.queryLocalFonts(). A pela primeira vez, isso aciona uma solicitação de permissão, que o usuário pode aprovar ou negar. Se o usuário aprovar a consulta das fontes locais, o navegador retornará uma matriz com os dados de fontes que você pode repetir. Cada fonte é representada como um objeto FontData com as propriedades family (por exemplo, "Comic Sans MS"), fullName (por exemplo, "Comic Sans MS"), postscriptName (por exemplo, "ComicSansMS") e style (por exemplo, "Regular").

// Query for all available fonts and log metadata.
try {
  const availableFonts = await window.queryLocalFonts();
  for (const fontData of availableFonts) {
    console.log(fontData.postscriptName);
    console.log(fontData.fullName);
    console.log(fontData.family);
    console.log(fontData.style);
  }
} catch (err) {
  console.error(err.name, err.message);
}

Se você tiver interesse apenas em um subconjunto de fontes, também poderá filtrá-las com base na linguagem PostScript adicionando um parâmetro postscriptNames.

const availableFonts = await window.queryLocalFonts({
  postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});

Como acessar dados SFNT

O acesso SFNT completo está disponível pelo método blob() da objeto FontData. O SFNT é um formato de arquivo de fonte que pode conter outras fontes, como PostScript, Fontes TrueType, OpenType, Web Open Font Format (WOFF), entre outras.

try {
  const availableFonts = await window.queryLocalFonts({
    postscriptNames: ['ComicSansMS'],
  });
  for (const fontData of availableFonts) {
    // `blob()` returns a Blob containing valid and complete
    // SFNT-wrapped font data.
    const sfnt = await fontData.blob();
    // Slice out only the bytes we need: the first 4 bytes are the SFNT
    // version info.
    // Spec: https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font
    const sfntVersion = await sfnt.slice(0, 4).text();

    let outlineFormat = 'UNKNOWN';
    switch (sfntVersion) {
      case '\x00\x01\x00\x00':
      case 'true':
      case 'typ1':
        outlineFormat = 'truetype';
        break;
      case 'OTTO':
        outlineFormat = 'cff';
        break;
    }
    console.log('Outline format:', outlineFormat);
  }
} catch (err) {
  console.error(err.name, err.message);
}

Demonstração

Você pode ver a API Local Font Access em ação no demo abaixo. Confira também código-fonte. A demonstração mostra um elemento personalizado chamado <font-select>, que implementa um seletor de fontes local.

Considerações sobre privacidade

A permissão "local-fonts" parece fornecer uma plataforma altamente legível. No entanto, navegadores são livres para retornar o que quiserem. Por exemplo, navegadores focados no anonimato podem escolher para fornecer somente um conjunto de fontes padrão integradas ao navegador. Da mesma forma, os navegadores não precisam para fornecer os dados da tabela exatamente como aparecem no disco.

Sempre que possível, a API Local Font Access foi desenvolvida para expor apenas as informações exatas necessárias para viabilizar os casos de uso mencionados. As APIs do sistema podem produzir uma lista de fontes instaladas que não estão aleatória ou em uma ordem classificada, mas na ordem de instalação da fonte. Retornar exatamente a lista de fontes instaladas fornecidas por essa API de sistema podem expor dados adicionais que podem ser usados para técnicas de impressão digital e casos de uso que queremos habilitar não são auxiliados por essa ordem. Como essa API exige que os dados retornados sejam classificados antes de serem retornados.

Segurança e permissões

A equipe do Chrome projetou e implementou a API Local Font Access usando os princípios básicos. definido em Como controlar o acesso a recursos avançados da Web Platform, incluindo controle, transparência e ergonomia.

Controle do usuário

O acesso às fontes de um usuário é totalmente controlado por ele e não será permitido, a menos que "local-fonts", conforme listado nos registro de permissão, é concedida.

Transparência

A permissão de acesso às fontes locais do usuário para um site ficará visível no folha de informações do site.

Persistência da permissão

A permissão "local-fonts" será mantida entre as atualizações de página. Ela pode ser revogada pela de informações do site.

Feedback

A equipe do Chrome quer saber sobre suas experiências com a API Local Font Access.

Fale sobre o design da API

Existe algo na API que não funciona como você esperava? Ou há métodos faltando ou propriedades de que precisa para implementar sua ideia? Tem uma pergunta ou comentário sobre a segurança modelo? Registre um problema de especificação no repositório do GitHub correspondente ou adicione sua opinião a uma problema.

Informar um problema com a implementação

Você encontrou um bug na implementação do Chrome? Ou a implementação é diferente das especificações? Registre um bug em new.crbug.com. Não deixe de incluir o máximo de detalhes possível, instruções simples para reprodução, e digite Blink>Storage>FontAccess na caixa Componentes. O Glitch é ótimo para compartilhar repetições rápidas e fáceis.

Mostrar suporte à API

Você planeja usar a API Local Font Access? Seu apoio público ajuda a equipe do Chrome a priorizar recursos e mostrar a outros fornecedores de navegador como é fundamental oferecer suporte a eles.

Envie um tweet para @ChromiumDev usando a hashtag #LocalFontAccess e permitir saber onde e como você o está usando.

Agradecimentos

A especificação da API Local Font Access foi editada por Emil A. Eklund, Alex Russell, Joshua Bell Olivier Yiptong. Este artigo foi revisado por João Medley, Dominik Röttsches e Olivier Yiptong (link em inglês). Imagem principal de Brett Jordan no Abrir a página.