As falsas fontes da sua biografia não são fontes: o que são realmente esses caracteres
Publicado a 26/09/2025 · 14 min de leitura · Ferramentas de texto e idioma
Daniel Okonkwo — Programador front-end e redator de Tecnologia na OneKitly
Desempenho web · Formatos de ficheiro
Verificado a partir de 5 fontes
Os geradores que prometem cem fontes para o seu perfil não mudam fonte nenhuma. Trocam cada letra por um carácter diferente que por acaso é desenhado noutro estilo. Passe «OneKitly» por um gerador de negrito e obtém os pontos de código U+1D400 U+1D425 U+1D425 U+1D422 U+1D427 — nenhum deles é a letra A, l, l, i ou n. São MATHEMATICAL BOLD CAPITAL A e os seus vizinhos, caracteres que o Padrão Unicode acrescentou para que um artigo de física distinga um vetor a negrito de um escalar em itálico. Por serem caracteres diferentes, tudo o que compara texto deixa de funcionar: "OneKitly".includes(negrito) devolve false, toLowerCase() não lhes toca, /\w/ e /[a-zA-Z]/ não os reconhecem e Number("𝟏𝟐𝟑") é NaN. Uma frase de 33 caracteres passa de 33 para 117 bytes UTF-8. As tecnologias de apoio leem o buffer que recebem, e estes caracteres não trazem pronúncia: uma biografia assim escrita é anunciada mal ou saltada. O bloco tem ainda 28 buracos onde certas letras já estavam codificadas noutro lado, e é por isso que todo o gerador traz uma tabela de remendos. A normalização NFKC devolve tudo a ASCII, pelo que uma plataforma que normaliza apaga o efeito em silêncio.
Um 𝐀 que parece negrito não é a letra A a negrito — é U+1D400, um carácter distinto inventado para a matemática. Imprimimos os pontos de código, medimos o custo em bytes, partimos a pesquisa, a ordenação e a contagem de palavras com eles, e percorremos o bloco para encontrar os seus 28 buracos.
O que o gerador faz na realidade
Uma fonte é um ficheiro. Contém contornos e associa a letra A a uma forma. Escolher uma fonte a negrito não muda a letra A; muda como a letra A é desenhada. Todos os estilos que um gerador de biografias oferece funcionam ao contrário: a letra é substituída, e o desenho é o que a fonte da plataforma já tinha para o substituto.
Imprima os pontos de código e a substituição salta à vista. A palavra OneKitly em estilo negrito é U+1D400 U+1D425 U+1D425 U+1D422 U+1D427; em duplo traço U+1D538 U+1D55D U+1D55D U+1D55A U+1D55F; em monoespaçado U+1D670 U+1D695 U+1D695 U+1D692 U+1D697. Cinco letras visíveis, cinco pontos de código, nenhum na gama ASCII. Em JavaScript a cadeia declara .length 10, porque cada um destes caracteres ocupa duas unidades UTF-16.
Também custam mais a armazenar. A frase «Building tools for six languages.» tem 33 caracteres e 33 bytes UTF-8 porque é ASCII puro. A mesma frase a negrito continua a ter 33 caracteres, mas 61 unidades UTF-16 e 117 bytes UTF-8 — três vezes e meia a carga para as mesmas palavras. Numa plataforma que mede uma biografia em bytes em vez de caracteres, é quase todo o seu orçamento gasto em nada.
Tudo o que compara texto deixa de corresponder
A pesquisa de subcadeia falha primeiro. "OneKitly".includes(negrito) devolve false, e o inverso também, porque não partilham um único ponto de código. Uma pesquisa interna, o localizar-na-página do navegador, uma cláusula LIKE de base de dados e um índice de etiquetas reduzem-se à mesma comparação, e todos falham. Se o seu nome visível estiver escrito a negrito matemático, quem escrever o seu nome real na pesquisa não o encontrará.
A conversão de maiúsculas e minúsculas não faz nada. negrito.toLowerCase() devolve exatamente a mesma cadeia, porque as correspondências de caixa do Unicode para os alfanuméricos matemáticos associam cada carácter a si próprio. Portanto uma pesquisa insensível à caixa que passa ambos os lados a minúsculas também falha. A única coisa que funciona é a colação: Intl.Collator("en", { sensitivity: "base" }).compare("𝐀", "A") devolve 0, porque as tabelas de colação do ICU dobram as letras estilizadas sobre as suas letras de base. Vale a pena saber, porque explica porque é que a mesma cadeia é encontrável num produto e invisível noutro: depende de o caminho de pesquisa ter passado por um colador ou por uma igualdade de cadeias.
As classes de caracteres contradizem-se. /[a-zA-Z]/.test("𝐀") é falso, /\w/u.test("𝐀") é falso, mas /\p{L}/u.test("𝐀") é verdadeiro: o carácter é mesmo uma letra segundo a categoria geral do Unicode (Lu para a maiúscula, Ll para a minúscula), apenas não é uma letra ASCII. Os dígitos comportam-se do mesmo modo: /\d/u.test("𝟏") é falso enquanto /\p{Nd}/u.test("𝟏") é verdadeiro, e Number("𝟏𝟐𝟑") é NaN embora a mesma cadeia depois de NFKC seja lida como 123. Dois validadores escritos por duas equipas chegarão portanto a veredictos opostos sobre a mesma biografia.
A ordenação divide a diferença. Um Array.prototype.sort() simples compara unidades UTF-16, pelo que ["𝐁rown", "Adams", "Clark"] sai como Adams, Clark, 𝐁rown: o nome estilizado é exilado para o fim da lista porque U+1D400 é numericamente maior do que qualquer letra ASCII. Mude para localeCompare e os mesmos três dão Adams, 𝐁rown, Clark, que é o que um leitor espera. Nenhum está errado; respondem a perguntas diferentes, e um diretório que use o rápido não o arquiva em lado nenhum.
O custo de acessibilidade, dito sem rodeios
Um leitor de ecrã não vê a sua biografia. Recebe a sequência de caracteres que a plataforma guardou e entrega-a a um sintetizador de voz, que procura cada carácter num dicionário de pronúncia. Esse dicionário é feito para as letras com que se escreve. U+1D400 não é uma delas. O sintetizador tem três opções: ler em voz alta o nome Unicode do carácter, ler um substituto genérico, ou saltá-lo. As três acontecem na prática, e qual delas depende do leitor, da voz e do nível de verbosidade — não de algo que o autor controle.
O custo é fácil de subestimar porque a falha é invisível para quem a causou. Você vê um nome elegante. Um leitor cego pode ouvir trinta nomes de caracteres seguidos, ou ver o nome da sua conta desaparecer por completo, deixando um cartão com uma imagem e nenhum título. Não há definição que esse leitor possa mudar para o resolver, porque para a máquina o texto diz realmente outra coisa. É todo o argumento; não precisa de moral nenhuma por cima.
Uma família é pior do que as outras. Os conjuntos em círculo e em círculo invertido — Ⓐ U+24B6, 🅐 U+1F150 — não são letras de todo: a sua categoria geral é So, símbolo/outro. Um programa que filtre um campo deixando apenas letras e espaços elimina-os, e um que conte letras contará zero.
Os 28 buracos do bloco, e porque todo o gerador tem uma tabela de remendos
O bloco Mathematical Alphanumeric Symbols vai de U+1D400 a U+1D7FF, ou seja 1024 pontos de código. Ao percorrê-lo à procura de caracteres atribuídos aparecem 996, portanto 28 posições estão vazias: sobram 652 letras latinas (treze estilos de 52, menos as que faltam), 294 caracteres gregos e afins, e 50 algarismos em cinco estilos.
Quatro dos 28 são simples enchimento reservado: U+1D6A6 e U+1D6A7 ficam entre o j itálico sem ponto e o alfa maiúsculo a negrito, e U+1D7CC e U+1D7CD entre o digama minúsculo a negrito e o algarismo zero a negrito. Os outros 24 são casas de letras deixadas vazias de propósito porque esse carácter exato já tinha sido codificado anos antes no bloco Letterlike Symbols, em U+2100–U+214F.
A lista é curta o bastante para ser dada por inteiro. Falta o h itálico porque já existia como U+210E PLANCK CONSTANT. À script faltam B, E, F, H, I, L, M, R (vivem em U+212C, U+2130, U+2131, U+210B, U+2110, U+2112, U+2133, U+211B) e as minúsculas e, g, o (U+212F, U+210A, U+2134). À fraktur faltam C, H, I, R, Z (U+212D, U+210C, U+2111, U+211C, U+2128). À de duplo traço faltam C, H, N, P, Q, R, Z (U+2102, U+210D, U+2115, U+2119, U+211A, U+211D, U+2124) — as letras da teoria dos conjuntos que todo o matemático já tinha.
É por isso que o bloco denuncia a sua origem. Um gerador que mapeia letras por simples aritmética — pegar no ponto de código do A e somar o desvio do estilo — produz pontos de código não atribuídos para essas 24 letras, e um ponto de código não atribuído aparece como um quadrado vazio. Um gerador bem feito traz a tabela de remendos. Um gerador apressado não, e é por isso que o texto script tem tantas vezes um buraco exatamente onde devia estar um E ou um R.
Onde estes caracteres são a resposta certa
Nada disto faz destes caracteres um erro. Existem porque em matemática o estilo é o significado. Um R a negrito e um R em itálico não são o mesmo símbolo lido de duas maneiras; são dois símbolos. ℝ são os reais, R pode ser um anel, e um vetor a negrito não é o escalar escrito com a mesma letra. Codificar os estilos como caracteres distintos é o que permite que uma fórmula sobreviva a ser copiada de um artigo para um e-mail sem perder o conteúdo.
Esse é também o critério para saber se os usa bem. Se o estilo transporta informação que se perderia sem ele, o carácter é a ferramenta certa. Se o estilo é enfeite sobre prosa vulgar, então letras normais mais formatação a sério — o negrito que o seu editor produz, que deixa a letra A ser a letra A — é a ferramenta certa, e é a única que um leitor de ecrã, um índice de pesquisa e uma rotina de ordenação conseguem tratar todos.
NFKC, e as plataformas que apagam o efeito sem o avisar
O Unicode define uma decomposição de compatibilidade para cada um destes caracteres: o próprio padrão regista que U+1D400 é uma variante de formatação de A. A forma de normalização NFKC aplica essas decomposições e depois recompõe, pelo que negrito.normalize("NFKC") sobre a nossa frase de teste devolve o original ASCII, carácter a carácter — comparámos as duas cadeias e são iguais. O mesmo acontece ao texto de largura total (U+FF21 passa a A), às letras em círculo (U+24B6 passa a A) e às letras modificadoras sobrescritas (U+1D2C passa a A).
Muitos serviços normalizam à entrada, quase sempre para impedir que duas contas tenham nomes de aspeto idêntico. Quando o fazem, o estilo que colou já desapareceu no momento de gravar, e nada lho diz: submete uma biografia estilizada e recebe uma vulgar de volta. Nada está partido; a plataforma limitou-se a perguntar à base de caracteres o que o seu texto dizia realmente e guardou essa resposta.
Duas famílias sobrevivem ao NFKC, e saber quais é útil. As versaletes — ᴀ é U+1D00 LATIN LETTER SMALL CAPITAL A — são letras fonéticas das extensões AFI, sem qualquer decomposição de compatibilidade, pelo que atravessam a normalização intactas. Também as letras em círculo invertido, 🅐 U+1F150 e companhia. Aos olhos do padrão não são variantes estilísticas de A; são caracteres por direito próprio. Isso torna-as mais duráveis e não mais legíveis, que é a troca em que assenta toda a categoria.
Uma regra prática para um perfil
Mantenha em letras normais os campos pelos quais se pesquisa: o seu nome, o seu identificador, as palavras que alguém escreveria para o encontrar. É aí que a substituição lhe custa algo mensurável. Se quiser um floreado, ponha-o onde ninguém consulta — um separador, um único carácter decorativo — e deixe as palavras à volta em claro.
E guarde uma cópia da versão simples. Como a transformação é uma tabela de correspondência, o regresso também o é: normalize com NFKC e recupera exatamente o original para as famílias matemática, de largura total, em círculo e sobrescrita. Para as versaletes e as em círculo invertido precisa de um mapa inverso, porque a normalização não o fará por si.
| Carácter | Ponto de código | Nome Unicode | Categoria | Depois de NFKC |
|---|---|---|---|---|
| A | U+0041 | LATIN CAPITAL LETTER A | Lu (letra) | A (sem alteração) |
| 𝐀 | U+1D400 | MATHEMATICAL BOLD CAPITAL A | Lu (letra) | A |
| 𝔸 | U+1D538 | MATHEMATICAL DOUBLE-STRUCK CAPITAL A | Lu (letra) | A |
| A | U+FF21 | FULLWIDTH LATIN CAPITAL LETTER A | Lu (letra) | A |
| Ⓐ | U+24B6 | CIRCLED LATIN CAPITAL LETTER A | So (símbolo, não uma letra) | A |
| ᴀ | U+1D00 | LATIN LETTER SMALL CAPITAL A | Ll (letra) | ᴀ (sobrevive) |
Perguntas frequentes
- Uma biografia em falsa fonte prejudica o meu alcance?
- Retira-o da pesquisa textual sobre essas palavras, o que é mensurável e independente de qualquer algoritmo de classificação. "OneKitly".includes(negrito) é falso, portanto uma consulta com o seu nome normal não pode corresponder a um estilizado por subcadeia. Se uma plataforma concreta compensa depende de normalizar ou colacionar antes de indexar, e as plataformas não o publicam. A leitura prudente: toda a palavra pela qual queira ser encontrado deve ir em letras normais.
- Porque é que algumas letras aparecem como quadrados vazios?
- Duas razões diferentes com o mesmo aspeto. Ou o gerador emitiu um dos 28 pontos de código não atribuídos do bloco — muitas vezes uma letra script, fraktur ou de duplo traço de entre os 24 buracos — ou o carácter existe mas a fonte do aparelho do leitor não tem glifo para ele. O primeiro caso é um erro do gerador e vê-se em toda a gente; o segundo depende do aparelho, e é por isso que a mesma mensagem fica bem no seu telemóvel e partida no de outra pessoa.
- Como converto texto estilizado de volta para letras normais?
- Para as famílias matemática, de largura total, em círculo e sobrescrita, basta uma chamada: texto.normalize("NFKC"). Verificámos que devolve uma frase inteira exatamente: a frase a negrito normalizada fica igual ao original ASCII. As versaletes e as em círculo invertido não têm decomposição de compatibilidade e sobrevivem à normalização, pelo que exigem uma tabela inversa explícita. Uma ferramenta de conversão traz ambos os caminhos; um normalize de uma linha cobre a maioria.
- Há algum estilo que seja seguro usar?
- Não no sentido de ser invisível para o software — todos eles mudam os pontos de código, e é esse todo o mecanismo. O que varia é quanto se perde. Substituir um carácter decorativo entre duas palavras normais não custa quase nada. Substituir um nome visível inteiro custa a pesquisa, a ordenação e a capacidade das tecnologias de apoio de o ler. A dimensão do dano acompanha o número de letras substituídas: use-os ao carácter, não à frase.
- Porque é que o meu texto estilizado por vezes volta normal depois de gravar?
- O serviço normalizou-o. NFKC é a forma padrão de decidir se duas cadeias são «o mesmo texto», e as plataformas aplicam-na a nomes visíveis e identificadores para impedir a personificação por semelhança. Uma vez aplicada, U+1D400 passa a A e não sobra nada para desfazer. Nada está partido e não aparece erro nenhum, porque do ponto de vista da plataforma ela guardou exatamente o que escreveu — segundo a definição de «o que escreveu» que a base de caracteres fornece.
- Estes caracteres contam para um limite de caracteres?
- Depende inteiramente do que o limite conta, que é o problema de sempre dos limites de caracteres. Por pontos de código, a nossa frase de teste são 33 em ambos os casos. Por unidades UTF-16 — o que .length devolve em JavaScript e o que muitos validadores de formulário usam — a frase normal são 33 e a de negrito 61. Por bytes UTF-8 são 33 contra 117. Um formulário que o deixa escrever 33 caracteres normais pode aceitar apenas 16 estilizados, e o contador ao lado do campo não o explicará.
Artigos que podem interessar-lhe
Todos os guias →Ferramentas relacionadas
Fontes
- Unicode Consortium — The Unicode Standard — Mathematical Alphanumeric Symbols (U+1D400–U+1D7FF) code chart
- Unicode Consortium — UAX #15: Unicode Normalization Forms (NFC, NFD, NFKC, NFKD)
- Unicode Consortium — UTS #39: Unicode Security Mechanisms — confusables and identifier restrictions
- Mozilla — MDN Web Docs — String.prototype.normalize()
- W3C — Web Content Accessibility Guidelines (WCAG) 2.2 — Readable and Text Alternatives
Detetaste um erro neste artigo?