Kerning sobre la marcha

10

¿Alguien conoce algún algoritmo que calcule automáticamente el interletraje de caracteres basado en formas de glifo cuando el usuario escribe texto?

No me refiero al cálculo trivial de los anchos de avance o similares, me refiero a analizar la forma de los glifos para estimar la distancia visual óptima entre los caracteres. Por ejemplo, si colocamos tres caracteres secuencialmente en una línea, el personaje del medio debería PARECER estar en el centro de la línea a pesar de las formas del personaje. Un ejemplo ilumina la funcionalidad kerning-on-the-fly:

Un ejemplo de kerning-on-the-fly:

Captura de pantalla

En la imagen de arriba aparece ser demasiado correcta. Debería desplazarse una cierta cantidad hacia Tpara que parezca estar en el medio de Ty g. El algoritmo debe examinar las formas de Ty a(y posiblemente otras letras también) y decidir cuánto ase debe desplazar hacia la izquierda. Esta cierta cantidad es lo que debe calcular el algoritmo, SIN EXAMINAR LOS POSIBLES PARES DE KERNING DE LA FUENTE.

Estoy pensando en codificar un programa javascript (+ svg + html) que use fuentes dibujadas a mano y muchas de ellas carecen de pares de interletraje. Los campos de texto serán editables y pueden incluir texto de múltiples fuentes. Creo que el interletraje sobre la marcha podría ser una forma de garantizar el flujo de texto medio en este caso.

EDITAR: Un punto de partida para esto podría ser usar la fuente svg, por lo que es fácil obtener valores de ruta. En la fuente svg, la ruta se define de esta manera:

<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"/>

El algoritmo (o código javascript) debe examinar esas rutas de alguna manera y determinar la distancia óptima entre ellas.

Timo Kähkönen
fuente
1
Si está buscando una solución de codificación, sería mejor pedirla en SO. ¿Es eso lo que estás buscando? Si es así, migraré la pregunta allí.
Alan Gilbertson
2
Estoy de acuerdo en que esta es una pregunta TAN. Hice la misma pregunta en SO, pero estaba cerrada como fuera de tema allí. Luego preguntó en math.stackexchange, pero ocurrió el mismo cierre. Este es el tercer lugar, puede ser este el lugar correcto, quien lo sepa.
Timo Kähkönen
2
No sé cómo funciona el algoritmo, pero InDesign puede hacer esto: "El interletraje óptico ajusta el espacio entre los caracteres adyacentes en función de sus formas. Algunas fuentes incluyen especificaciones robustas de pares de kern. Sin embargo, cuando una fuente incluye solo un mínimo incorporado kerning o ninguno en absoluto, o si usa dos tipos de letra o tamaños diferentes en una o más palabras en una línea, puede usar la opción de kerning óptico ". help.adobe.com/en_US/indesign/cs/using/…
e100
2
Creo que esto probablemente esté dentro del alcance en lo que respecta a un algoritmo general: una secuencia de pasos que se deben llevar a cabo para resolver un problema. Pero no creo que los detalles de la implementación en JS u otro lenguaje pertenezcan, y estoy editando para mencionar solo a JS como caso de uso en segundo plano.
e100
1
Creo que el primer orden del día es definir "óptimo" de una manera que sea útil para un algoritmo de máquina.
Horacio

Respuestas:

4

Sé que esto es viejo. Estoy trabajando en esto ahora mismo en una implementación WebGL de texto tambaleante (lo que sea). La solución en la que estoy trabajando es así:

  1. Obtenga una versión de mapa de bits del par de glifos (o hágalo con vectores si lo desea)
  2. Para cada fila de píxeles (o unidad vertical arbitraria si utiliza vectores), verifique que ambos glifos tengan al menos un píxel presente
  3. Para cada fila que pasa el paso 2, calcule la distancia entre el píxel más a la derecha del primer glifo y el píxel más a la izquierda del segundo glifo
  4. Mueva el segundo glifo lo más a la izquierda posible mientras cumple con estos criterios:
    • el espacio en esa fila de píxeles es mayor que el espacio mínimo que especificó
    • el área total (ignorando las filas sin píxeles en uno de los glifos) es mayor que el área mínima que especificó

De esa manera, el 'área' vacía entre letras debería exprimirse a un promedio bastante común. Especifique el espacio mínimo y el área mínima usando prueba y error y su propio gusto, y tal vez permita que esos parámetros sean ajustados por algún otro agente también ... como un valor de interletraje manual.

Hurra :)

Editar: He implementado esto con éxito ahora y funciona muy bien :)

jaya
fuente
¡Buena respuesta! Bienvenido a GD.SE :)
Yisela
Gracias por la bienvenida: D !! Debo agregar que el área debe dividirse por el número de filas que realmente se están probando (lo que en realidad lo convierte en un espacio promedio y no realmente un área). Y también sería bueno probar si el intervalo de una fila es un valor atípico estadístico e ignorar esa fila si lo es. Eso ayudará a evitar apretar letras demasiado cerca cuando hay una gran apertura como en 'G'
jaya
Parece que hay algunos problemas secundarios aquí y allá, como T- o o ', por ejemplo, en algunos estilos de fuente de algunas fuentes. T- deje que el guión se acerque demasiado a la T, y o 'no compartió ningún píxel en la misma fila, así que hice una reserva para usar las filas más cercanas con un píxel cada vez que eso sucede. Para hacer que el algoritmo anterior sea más robusto, de alguna manera necesitaría verificar este tipo de problemas. Para mis propósitos, no fue necesario.
jaya
3

Este es un algoritmo bastante simple que probé una vez, y puede ser lo suficientemente bueno.

Renderice los caracteres en baja resolución, digamos seis o siete píxeles de alto (altura del capital típico) aproximadamente igual horizontalmente. Desea un mapa binario simple de dónde hay espacio vacío frente a partes de la letra, en una cuadrícula simple de baja resolución.

"Engordar" estos mapas de letras. Es decir, llene cada celda vacía que está adyacente a una celda llena. Esto es para reclamar el territorio vacío más cercano a los bordes de la letra, para que la letra vecina no se acerque demasiado.

Juega "Tetris horizontal" con los mapas de letras resultantes. Deje que la gravedad actúe a la izquierda. El abultado "vientre" izquierdo de la "a" "caerá" en la cavidad debajo de la barra superior de la "T". ¿Cuántas células se movió la "a"? Escale eso en proporción al tamaño real de las letras y así de lejos es el núcleo de la alta resolución "a" hacia la izquierda.

DarenW
fuente
1
¡Gracias! Para visualizar su algoritmo, ¿podría proporcionar un ejemplo de imagen de baja resolución usando pares "db", "AA", "Ta" y "c-" usando Arial.
Timo Kähkönen
Buen comienzo, pero creo que esto puede ser limitado cuando los pares de caracteres protruberantes no "Tetris" juntos, por ejemplo, "bd", "TT", "pq", "gj"
e100
@ e100: a primera vista, ese emparejamiento en particular no tendría cuadros delimitadores superpuestos ...
horatio
Pero, en términos generales, deben ser más ajustados que "MM", "NN", etc.
e100
2

Ya existen algoritmos para el kerning automático. Ninguno es infalible y tienden a necesitar un poco de agarre manual y corrección manual de ciertos aspectos, especialmente si su seguimiento es relativamente estrecho.

Pero esos algoritmos son para aplicar el interletraje al archivo de fuente , no a las letras, ya que se generan a partir del archivo de fuente.

¿Has considerado aplicar el kerning automático al archivo de fuente?

Fontforge (código abierto) y Fontlab (comercial) contienen algoritmos de interletraje automático. Tendrían una curva de aprendizaje relativamente pronunciada: debe estar familiarizado con los aspectos técnicos de cómo funcionan las fuentes.

También hay iKern que es un tipo que ofrece un comercial font-kerning de servicio por el que él interletraje su fuente para usted y hace un lugar excelente trabajo. No sé cuánto costaría.

thomasrutter
fuente
Pero la pregunta es realmente "¿cómo funcionaría un algoritmo así?" - ¿Puedes agregar algún detalle sobre cómo funciona FontForge?
e100
0

No tengo tiempo para pensarlo completamente, o dibujar ilustraciones, pero tenía una idea a medias basada en la primera bisección vertical de cada glifo.

Luego, para cada mitad, determine dos ejes verticales: - la bisectriz - exactamente la mitad entre los extremos izquierdo y derecho - el eje de "peso" - exactamente la mitad de la tinta en cada lado

Luego mueva el glifo vecino adyacente hacia o lejos del medio glifo de prueba según las posiciones relativas de los dos ejes.

Entonces, por ejemplo, en el par "AV", la mitad derecha de la A es pesada y "atrae" la V; la mitad izquierda de la V es pesada y derecha "atrae" a la A, por lo tanto se agrupan significativamente.

Sin embargo, estoy seguro de que hay una falla en que "AA" se agruparía tanto como "AV".

e100
fuente
0

Teniendo en cuenta mayúsculas y minúsculas, hay 56X55=2652situaciones de pares de fuentes que debe preocupar, todas las soluciones pueden romperse fácilmente porque si cambia el estilo de fuente, todas las reglas desaparecen.

La mejor manera es usar la técnica de aprendizaje automático, tratar de establecer un modelo de estudio de redes neuronales e importar múltiples imágenes de texto o vectores o cosas así, entrenar ese modelo y usar ese modelo entrenado para ajustar de manera inteligente cualquier tipo de fuente.

Debido a que no existe un algoritmo estático para ajustar la fuente perfectamente en la raíz, el aprendizaje automático sería una buena solución para este tipo de problema.

Súper ilad
fuente
No si solo hay criterios mayormente subjetivos. "¿Es este un perro o un gato?", No importa cuán raro se vea el perro, todavía tiene una respuesta exacta. (Incluso si se necesita un veterinario para verificar).
usr2564301