Как получить контуры букв в виде путей Безье, используя JavaScript?
Я хочу получить информацию об общих чертах глифов шрифтов как пути Безье в HTML5. Это позволило бы мне рандомизировать контуры:
В какао я бы использовал appendBezierPathWithGlyph:inFont:
, В Java я бы использовал TextLayout.getOutline()
, Как это работает в JavaScript?
Я обнаружил, что Mozilla имеет mozPathText
но я не могу заставить его работать.
3 ответа
По необходимости я создал свою собственную библиотеку с именем opentype.js. Он анализирует шрифты OpenType и TrueType. PostScript и WOFF будут поддерживаться в будущем.
Вот как он разбирает гарнитуру:
- Загрузите
.ttf
/.otf
файл с использованиемXMLHttpRequest
, - Разобрать
glyf
а такжеloca
таблица для извлечения буквы форм (глифов). - Разобрать
cname
таблица, которая содержит сопоставление символов и глифов. - Разобрать
head
а такжеhmtx
таблица для получения метрик, в основном интервал между каждой буквой.
Затем он может создать путь Безье:
- Преобразуйте буквы текста в глифы.
- Преобразуйте координаты глифа в квадратичные кривые.
- Отрегулируйте интервал, используя информацию кернинга.
В результате получается путь, который вы можете нарисовать, используя холст HTML5:
var font = opentype.parseFont(arrayBuffer);
var path = font.getPath("Hello, World!", {x:0, y:150, fontSize:72});
path.draw(ctx);
Демо-сайт имеет живой пример.
Разбор низкого уровня
В JavaScript вам придется вручную анализировать файл гарнитуры и извлекать необходимые данные пути. AFAIK, в данный момент для этого нет библиотеки-помощника, так что вы можете сделать это сами.
Для разбора файла вам также необходимо загрузить его вручную и проанализировать как необработанные данные, используя новый File API и возможные типизированные массивы для двоичных форматов шрифтов (ttf).
Можно написать очень длинный ответ для этого, так как это довольно низкоуровневый материал и широкий вопрос, который будет здесь рассмотрен (ИМХО). Тем не менее, вот спецификации формата файла для файлов общих шрифтов:
- WOFF (рекомендуется)
- Встроенный OpenType
- Открытый тип
- Открыть шрифт
- TrueType
- Тип 1 (PDF)
Но есть другой подход, который вы можете использовать в качестве промежуточного шага, избавляющего вас от боли:
Pre-синтаксический анализ
Выберите гарнитуры, которые вы хотите использовать. Запустите их через Java/Cocoa/.NET (WPF) или что угодно, и создайте массивы, содержащие необходимую информацию (например, WPF предоставляет вам данные пути для каждого глифа). Преобразуйте их в массивы JavaScript или объекты JSON и используйте их для рендеринга и манипулирования. Полученные баллы будут в em
значения, которые легко масштабировать.
Теперь вы можете просто просматривать массивы и отображать тип сегмента пути (линия, Безье и т. Д.) И изменять положения точек.
mozPathText
предназначен для холста и содержит только текстовый путь (в настоящее время Path API не предоставляется ни в одном браузере, но будет доступен в будущем - однако его нельзя использовать для этого, так как низкоуровневые данные пути на глиф по многим причинам недоступны, юридические причины могут быть одним).
след
Третий подход заключается в сортировке "OCR" глифов на холсте путем отслеживания каждого отдельного глифа и попытки построения путей из его прослеженного контура.
Это может быть сделано несколькими способами - один из способов - это анализировать построчно и группировать пиксели на основе расстояния / связности, а затем выполнять итерацию по группе / региону, используя нейронные сети или алгоритмы заполнения, чтобы найти внешние границы для глифа.
Или - вы можете нарисовать текст в виде контуров и просто проследить связанные пиксели для каждой фигуры и использовать его в качестве пути линии.
В этом случае вы можете столкнуться с проблемами, которые могут показаться достаточно простыми, но могут оказаться не так.
Пример: буква O
состоят из внешнего пути и внутреннего пути. Внутренний путь пробивает "дыру" во внешнем пути. Вы не можете определить это поведение напрямую, просто указав пути на холсте, поэтому вам нужно добавить "разрезы" между двумя путями после того, как вы определили, что они принадлежат друг другу, а затем соединить их в разрезах.
Использование разных составных режимов может помочь создать иллюзию таких, но вам все равно нужно будет определить, какой путь является сплошной частью, а какой будет нарисован как "дыра".
Деформация / искажение
Последний подход заключается в том, чтобы вообще не использовать пути глифов, а просто деформировать растровое изображение с использованием интерполяции и деформации сетки (обычно используется в связи с 3D-текстурами):
http://davis.wpi.edu/~matt/courses/morph/2d.htm
Деформация (PDF)
Морфинг (pdf)
Определите свои собственные шрифты / пути (ручная трассировка)
Возможно, более очевидный вариант: определить собственные пути шрифтов с нуля. Немного больше работы в области создания дизайнера шрифтов, ручной трассировки изображения или определения путей вручную. "Шрифт-плоттер" (с использованием изображения трассировки) не так сложен, но требует терпения.
Вы можете использовать холст в браузере для записи линий, которые вы строите, и использовать алгоритмы сглаживания (кардинальный сплайн + определение колена), чтобы получить хорошие круглые кривые и острые углы.
Все зависит от того, какой результат вы хотите в итоге и сколько работы вы готовы отложить. К сожалению, в этом отношении нет бесплатного билета, поскольку внутренние данные не разглашаются (и, вероятно, не будут в будущем).
С помощью SVG в некоторых браузерах можно сделать обратное тому, что вы просите: указать собственные глифы шрифтов в качестве более простых путей, а затем выложить текст, используя их. Вы можете импортировать SVG-шрифт и затем выполнить ваши преобразования. Но хотя SVG сейчас широко поддерживается, SVG-шрифты - нет. Только Safari, Chrome и Opera в настоящее время поддерживают их.
Если вы хотите выполнять эти типы преобразований с системными шрифтами векторным способом, это невозможно в любом браузере, о котором я знаю. Там просто нет API в HTML или SVG, чтобы получить контурный путь установленного глифа. (Возможно, есть что-то, что вы можете использовать в плагине, например Flash, я давно не проверял их текстовый API.)
Если вы делаете это растровым способом, вы можете использовать скрытый элемент canvas, чтобы разместить текст в буфере за пределами экрана, а затем получить пиксельную карту результата. Затем вы можете выполнить пиксельное преобразование и нарисовать его во втором видимом элементе canvas.