Кернинг на лету


10

Кто-нибудь знает какой-либо алгоритм, который будет автоматически рассчитывать кернинг символов на основе глифов, когда пользователь вводит текст?

Я не имею в виду тривиальное вычисление ширины и т. Д., Я имею в виду анализ формы глифов для оценки визуально оптимального расстояния между символами. Например, если мы последовательно выкладываем три символа в строке, средний символ должен выглядеть так, как если бы он находился в центре строки, несмотря на формы символов. Пример раскрывает функциональность кернинга на лету:

Пример кернинга на лету:

Скриншот

На изображении выше, aкажется, слишком правильно. Он должен быть смещен на определенную величину в сторону, Tчтобы он находился посередине Tи g. Алгоритм должен изучить формы Tи a(и, возможно, других букв) и решить, сколько aдолжно быть смещено влево. Это определенное количество - это то, что алгоритм должен вычислять - БЕЗ ИЗУЧЕНИЯ ВОЗМОЖНЫХ ПАР КЕРНИНГА Шрифта.

Я думаю о кодировании javascript (+ svg + html) программы, которая использует шрифты, нарисованные от руки, и во многих из них отсутствуют пары кернинга. Текстовые поля будут редактируемыми и могут содержать текст нескольких шрифтов. Я думаю, что кернинг на лету может быть одним из способов обеспечения среднего потока текста в этом случае.

РЕДАКТИРОВАТЬ: Одна из отправных точек для этого может быть использование шрифта svg, поэтому легко получить значения пути. В шрифте svg путь определяется следующим образом:

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

Алгоритм (или код JavaScript) должен каким-то образом исследовать эти пути и определять оптимальное расстояние между ними.


1
Если вы ищете решение для кодирования, об этом лучше спросить на SO. Это то, что вы ищете? Если так, я перенесу вопрос туда.
Алан Гилбертсон

2
Я согласен, что это так вопрос. Я задал тот же вопрос в SO, но там он был закрыт как не по теме. Затем спросил на math.stackexchange, но произошло то же самое закрытие. Это третье место, может быть, это правильное место, кто бы ни знал.
Тимо Кяхконен

2
Я не знаю, как работает алгоритм, но InDesign может сделать это: «Оптический кернинг регулирует расстояние между смежными символами на основе их форм. Некоторые шрифты включают надежные спецификации пары керн. Однако, когда шрифт включает только минимальный встроенный кернинг или его вообще нет, или если вы используете две разные гарнитуры или размеры в одном или нескольких словах в строке, вы можете использовать опцию оптического кернинга. " help.adobe.com/en_US/indesign/cs/using/...
e100

2
Я думаю, что это возможно в рамках общего алгоритма - последовательности шагов, которые необходимо выполнить для решения проблемы. Но я не думаю, что специфические особенности реализации в JS или другом языке принадлежат, и я редактирую, чтобы упомянуть только JS как фоновый вариант использования.
e100

1
Я думаю, что первым делом нужно определить «оптимальный» способ, который полезен для машинного алгоритма.
Горацио

Ответы:


4

Я знаю, что это старый. Я работаю над этим прямо сейчас в реализации WebGL шаткого текста (что угодно). Решение, над которым я работаю, выглядит так:

  1. Получите растровую версию пары глифов (или сделайте это с векторами, если хотите)
  2. Для каждой строки пикселей (или произвольной вертикальной единицы, если вы идете с векторами), убедитесь, что на обоих глифах присутствует хотя бы один пиксель
  3. Для каждой строки, которая проходит шаг 2, вычислите расстояние между самым правым пикселем первого глифа и самым левым пикселем второго глифа
  4. Переместите второй глиф как можно дальше влево, все еще удовлетворяя этим критериям:
    • промежуток в этом ряду пикселей больше некоторого минимального промежутка, который вы указали
    • общая площадь (игнорирование строк без пикселя в одном из глифов) превышает указанную вами минимальную площадь

Таким образом, пустая «область» между буквами должна сжиматься до довольно обычного среднего значения. Укажите минимальный зазор и минимальную площадь, используя метод проб и ошибок и свой собственный вкус, и, возможно, разрешите настройку этих параметров другим агентом ... например, значением ручного кернинга.

ура :)

Редактировать: я успешно реализовал это сейчас, и это работает очень хорошо :)


Хороший ответ! Добро пожаловать в GD.SE :)
Yisela

Спасибо за прием: D !! Я должен добавить, что область должна быть разделена на количество строк, которые фактически тестируются (что фактически делает его средним разрывом, а не областью). А также было бы хорошо проверить, является ли разрыв строки статистическим выбросом, и игнорировать этот ряд, если он есть. Это поможет избежать сжатия букв слишком близко, когда есть большое отверстие, как в «G»
Джая

Кажется, тут и там есть несколько проблемных потомков, например, T- или o ', например, в некоторых стилях шрифтов некоторых шрифтов. T - пусть дефис окажется слишком близко к T, и o 'не разделит ни одного пикселя в одной строке, поэтому я сделал отступление, чтобы использовать самые близкие строки с одним пикселем каждый, когда это происходит. Чтобы сделать вышеописанный алгоритм более надежным, вам нужно как-то проверить наличие подобных проблем. Для моих целей это было не нужно.
Джая

3

Это довольно простой алгоритм, который я пробовал однажды, и может быть достаточно хорошим.

Рендеринг символов в низком разрешении - скажем, шесть или семь пикселей в высоту (высота обычной буквы) примерно одинаковы по горизонтали. Вы хотите простую двоичную карту, где есть пустое пространство против частей буквы, на простой сетке низкого разрешения.

"Откормить" эти буквы карты. То есть заполните каждую пустую ячейку, которая находится рядом с заполненной ячейкой. Это означает, что пустая территория ближе всего к краям буквы, поэтому соседняя буква не подходит слишком близко.

Сыграйте в «горизонтальный тетрис» с полученными буквами карт. Пусть гравитация действует влево. Выпуклый левый «живот» «а» «упадет» в полость под перекладиной «Т». Сколько клеток сдвинуло «а»? Масштабируйте это пропорционально фактическому размеру букв, и это - как далеко к реальному разрешению "a" влево.


1
Спасибо! Для наглядности вашего алгоритма вы можете предоставить пример изображения с низким разрешением, используя пары «db», «AA», «Ta» и «c-», используя Arial.
Тимо Кяхконен

Хорошее начало, но я думаю, что это может быть ограничено, когда пары выпуклых символов не "тетрис" вместе, например, "bd", "TT", "pq", "gj"
e100

@ e100: На первый взгляд, эти особые пары не будут иметь перекрывающихся ограничивающих рамок ...
Горацио

Но, вообще говоря, они должны быть более жесткими, чем "MM", "NN" и т. Д.
e100

2

Алгоритмы автокернинга уже существуют. Ни один из них не защищен от ошибок, и им, как правило, требуется немного ручного и ручного исправления некоторых аспектов, особенно если ваше отслеживание относительно жесткое.

Но эти алгоритмы предназначены для применения кернинга к файлу шрифта , а не к буквам, поскольку они генерируются из файла шрифта.

Вы рассматривали возможность применения авто-кернинга к файлу шрифта?

Fontforge (с открытым исходным кодом) и Fontlab (коммерческий) содержат алгоритмы авто-кернинга. У них будет относительно крутая кривая обучения - вы должны быть знакомы с техническими аспектами работы шрифтов.

Есть также iKern, который предлагает коммерческий сервис кернинга шрифтов, посредством которого он кернует ваш шрифт для вас и делает довольно хорошую работу. Я не знаю, сколько это будет стоить.


Но вопрос на самом деле "как будет работать такой алгоритм?" - Можете ли вы добавить какие-либо подробности о том, как работает FontForge?
e100


0

У меня нет времени полностью обдумать это или нарисовать иллюстрации, но у меня была полу-идея, основанная на первом разделении каждого глифа по вертикали.

Затем для каждой половины определите две вертикальные оси: - биссектриса - ровно половина между левой и правой крайностями - ось «веса» - ровно половина чернил на каждой стороне

Затем переместите соседний глиф соседа к тестовому полулифу или от него на основе относительных положений двух осей.

Так, например, в паре «AV» правая половина буквы A тяжелая слева и «притягивает» V; левая половина V тяжела справа "притягивает" A, таким образом, они значительно соединяются вместе.

Тем не менее, я уверен, что есть недостаток в том, что "AA" будет объединен так же, как "AV".


0

Учитывая заглавные и строчные буквы, есть 56X55=2652ситуации с парами шрифтов, которые вам следует учитывать, все решения могут быть легко нарушены, потому что если вы измените стиль шрифта, все правила исчезнут.

Лучший способ - использовать технику машинного обучения, попытаться создать модель обучения нейронной сети и импортировать несколько текстовых изображений или векторов с кернингом или тому подобное, обучить эту модель и использовать эту обученную модель для разумной настройки любого типа шрифта.

Поскольку не существует статического алгоритма для точной настройки шрифта в корне, машинное обучение было бы хорошим решением для такого рода проблем!


Нет, если есть только в основном субъективные критерии. «Это собака или кошка?», Как бы странно ни выглядел пес, у него все равно есть точный ответ. (Даже если для проверки требуется ветеринар.)
usr2564301
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.