Kerning na mosca

10

Alguém conhece algum algoritmo que calcule o kerning automático de caracteres com base em formas de glifo quando o usuário digita texto?

Não me refiro a cálculos triviais de larguras avançadas ou similares, mas a analisar a forma dos glifos para estimar a distância visualmente ideal entre os caracteres. Por exemplo, se colocarmos três caracteres seqüencialmente em uma linha, o caractere do meio deverá parecer estar no centro da linha, apesar das formas do personagem. Um exemplo ilustra a funcionalidade do kerning-on-the-fly:

Um exemplo de kerning-on-the-fly:

Captura de tela

Na imagem acima aparece estar muito certo. Ele deve ser deslocado uma certa quantidade para Tque pareça estar no meio de Te g. O algoritmo deve examinar as formas Te a(e possivelmente outras letras também) e decidir quanto adeve ser deslocado para a esquerda. Essa quantia é o que o algoritmo deve calcular - SEM EXAMINAR OS PARES KERNING POSSÍVEIS DA PIA BATISMAL.

Estou pensando em codificar um programa javascript (+ svg + html) que usa fontes desenhadas à mão e muitas delas não possuem pares de kerning. Os campos de texto serão editáveis ​​e podem incluir texto de várias fontes. Eu acho que o kerning-on-the-fly pode ser uma maneira de garantir um fluxo médio de texto nesse caso.

EDIT: Um ponto de partida para isso pode ser o uso da fonte svg, por isso é fácil obter valores de caminho. Na fonte svg, o caminho é definido desta maneira:

<glyph glyph-name="T" unicode="T" horiz-adv-x="1251" d="M531 0v1293h
-483v173h1162v-173h-485v-1293h-194z"/>

<glyph glyph-name="a" unicode="a" horiz-adv-x="1139" d="M828 131q-100 -85
-192.5 -120t-198.5 -35q-175 0 -269 85.5t-94 218.5q0 78 35.5 142.5t93
103.5t129.5 59q53 14 160 27q218 26 321 62q1 37 1 47q0 110 -51 155q-69 61
-205 61q-127 0 -187.5 -44.5t-89.5 -157.5l-176 24q24 113 79 182.5t159
107t241 37.5 q136 0 221 -32t125 -80.5t56 -122.5q9 -46 9 -166v-240q0
-251 11.5 -317.5t45.5 -127.5h-188q-28 56 -36 131zM813 533q-98 -40 -294
-68q-111 -16 -157 -36t-71 -58.5t-25 -85.5q0 -72 54.5 -120t159.5 -48q104
0 185 45.5t119 124.5q29 61 29 180v66z"/>

O algoritmo (ou código javascript) deve examinar esses caminhos de alguma maneira e determinar a distância ideal entre eles.

Timo Kähkönen
fonte
11
Se você está procurando uma solução de codificação, isso seria melhor solicitado no SO. É isso que você está procurando? Nesse caso, migrarei a pergunta para lá.
Alan Gilbertson
2
Concordo que esta é uma pergunta tão. Fiz a mesma pergunta no SO, mas foi encerrada como fora de tópico. Em seguida, perguntou em math.stackexchange, mas o mesmo fechamento aconteceu. Este é o terceiro lugar, pode ser que seja o lugar certo, quem sabe.
Timo Kähkönen 14/10/12
2
Não sei como o algoritmo funciona, mas o InDesign pode fazer o seguinte: "O kerning óptico ajusta o espaçamento entre caracteres adjacentes com base em suas formas. Algumas fontes incluem especificações robustas de pares de kerns. No entanto, quando uma fonte inclui apenas o mínimo incorporado kerning ou nenhum, ou se você usar dois tipos ou tamanhos diferentes em uma ou mais palavras em uma linha, poderá usar a opção de kerning óptico ". help.adobe.com/en_US/indesign/cs/using/...
e100
2
Eu acho que isso provavelmente está dentro do escopo no que diz respeito a um algoritmo geral - uma sequência de etapas a serem executadas para resolver um problema. Mas não acho que as especificações da implementação em JS ou outra linguagem pertençam e estou editando para mencionar apenas JS como caso de uso em segundo plano.
e100
11
Penso que a primeira ordem do dia é definir "ideal" de uma maneira que seja útil para um algoritmo de máquina.
horatio

Respostas:

4

Eu sei que isso é velho. Estou trabalhando nisso agora em uma implementação WebGL de texto instável (tanto faz). A solução em que estou trabalhando é assim:

  1. Obtenha uma versão em bitmap do par de glifos (ou faça-o com vetores, se desejar)
  2. Para cada linha de pixels (ou unidade vertical arbitrária, se você usar vetores), verifique se os dois glifos têm pelo menos um pixel presente
  3. Para cada linha que passa na etapa 2, calcule a distância entre o pixel mais à direita do primeiro glifo e o pixel mais à esquerda do segundo glifo
  4. Mova o segundo glifo para a esquerda possível, enquanto ainda atende a estes critérios:
    • o espaço nessa linha de pixels é maior que o espaço mínimo especificado
    • a área total (ignorando linhas sem pixel em um dos glifos) é maior que a área mínima especificada

Dessa forma, a 'área' vazia entre as letras deve ser reduzida a uma média bastante comum. Especifique o intervalo mínimo e a área mínima usando tentativa e erro e seu próprio gosto, e talvez permita que esses parâmetros sejam ajustados por outro agente também ... como um valor de kerning manual.

yay :)

Edit: Eu implementei isso com sucesso agora e funciona muito bem :)

jaya
fonte
Boa resposta! Bem-vindo ao GD.SE :)
Yisela
Obrigado pela recepção: D !! Devo acrescentar que a área deve ser dividida pelo número de linhas realmente sendo testadas (o que na verdade faz apenas uma diferença média e não realmente uma área). E também seria bom testar se o intervalo de uma linha é um desvio estatístico e ignorá-lo, se for. Isso ajudará a evitar apertar cartas muito perto quando há uma grande abertura como no 'G'
jaya
Parece haver alguns filhos problemáticos aqui e ali, como T- ou o ', por exemplo, em alguns estilos de fonte de algumas fontes. T- deixe o hífen chegar muito perto do T e o 'não compartilhou nenhum pixel na mesma linha, então fiz um fallback para usar as linhas mais próximas com um pixel cada quando isso acontece. Para tornar o algoritmo acima mais robusto, você precisa verificar esses tipos de problemas de alguma forma. Para meus propósitos, não era necessário.
jaya
3

Este é um algoritmo bastante simples que eu tentei uma vez e pode ser bom o suficiente.

Renderize os caracteres em baixa resolução - diga seis ou sete pixels de altura (altura do capital típico) aproximadamente na mesma horizontalmente. Você deseja um mapa binário simples de onde há espaço vazio versus partes da carta, em uma grade simples de baixa resolução.

"Engorda" esses mapas de letras. Ou seja, preencha cada célula vazia adjacente a uma célula preenchida. Isso significa reivindicar um território vazio mais próximo das bordas da letra, para que a letra vizinha não chegue muito perto.

Jogue "Tetris horizontal" com os mapas de letras resultantes. Deixe a gravidade agir para a esquerda. A "barriga" esquerda abaulada do "a" cairá na cavidade sob a barra do "T". Quantas células o "a" moveu? Aumente isso proporcionalmente ao tamanho real das letras e é até onde o kern de alta resolução é "a" para a esquerda.

DarenW
fonte
11
Obrigado! Para visualizar seu algoritmo, você pode fornecer um exemplo de imagem de baixa resolução usando os pares "db", "AA", "Ta" e "c-" usando Arial.
Timo Kähkönen 19/10/12
Bom começo, mas estou pensando que esta pode ser limitada, onde pares de caracteres salientes não "Tetris" em conjunto, por exemplo, "bd", "TT", "pq", "gj"
e100
@ e100: À primeira vista os emparelhamento particular não teria sobreposição caixas delimitadoras ...
Horatio
Mas de modo geral, eles devem ser kerned mais apertado do que "MM", "NN" etc
e100
2

Já existem algoritmos para auto-kerning. Nenhum é à prova de idiotas e eles tendem a precisar de um pouco de manipulação manual e correção manual de certos aspectos, especialmente se o seu rastreamento for relativamente apertado.

Mas esses algoritmos são para aplicar o kerning ao arquivo de fonte , não às letras, pois são gerados a partir do arquivo de fonte.

Você já pensou em aplicar o kerning automático ao arquivo de fonte?

Fontforge (código aberto) e Fontlab (comercial) contêm algoritmos de kerning automático. Eles teriam uma curva de aprendizado relativamente íngreme - você precisa estar familiarizado com aspectos técnicos de como as fontes funcionam.

Há também iKern que é um cara que oferece um comercial-kerning fonte de serviços pelo qual ele Kerns sua fonte para você e faz um excelente trabalho em vez. Não sei quanto custaria.

thomasrutter
fonte
Mas a questão é realmente "como esse algoritmo funcionaria?" - você pode adicionar algum detalhe sobre como o FontForge funciona?
e100
0

Não tenho tempo para refletir completamente ou desenhar ilustrações, mas tive uma meia ideia baseada em dividir primeiro cada glifo verticalmente.

Em seguida, para cada metade, determine dois eixos verticais: - a bissetriz - exatamente metade entre os extremos esquerdo e direito - o eixo "peso" - exatamente metade da tinta de cada lado

Em seguida, mova o glifo vizinho adjacente na direção ou para longe do meio-glifo de teste com base nas posições relativas dos dois eixos.

Assim, por exemplo, no par "AV", a metade direita do A é pesada para a esquerda e "atrai" o V; a metade esquerda do V é pesada à direita "atrai" o A, assim eles são unidos significativamente.

No entanto, tenho certeza de que há uma falha no "AA" ser agrupado tanto quanto "AV".

e100
fonte
0

Considerando maiúsculas e minúsculas, há 56X55=2652situações de par de fontes que você deve se preocupar; todas as soluções podem ser facilmente quebradas , pois se você alterar o estilo da fonte, todas as regras foram cumpridas.

A melhor maneira é usar a técnica de aprendizado de máquina, tentar estabelecer um modelo de estudo de rede neural e importar várias imagens ou vetores de texto kerned ou coisas assim, treinar esse modelo e usar esse modelo treinado para ajustar inteligentemente qualquer tipo de fonte.

Como não há algoritmo estático para ajustar perfeitamente a fonte na raiz, o aprendizado de máquina seria uma boa solução para esse tipo de problema!

Super-ilad
fonte
Não se houver apenas critérios principalmente subjetivos. "Isso é um cachorro ou um gato?", Por mais estranho que o cão pareça, ainda tem uma resposta exata. (Mesmo que seja necessário um veterinário para verificar.)
usr2564301 3/03