Иногда приходится копнуть глубже
Когда-то делала посимвольную подсветку текста поверх Quill (либа для создания текстового редактора) и столкнулась с багом: маркеры под отдельными буквами съезжали. Оказалось, шрифт объединял f и i в одну лигатуру, а моя подсветка рассчитывалась на две отдельные буквы. Пришлось разбираться, как определить границу между ними, если на экране это один общий рисунок.
Например, в EB Garamond есть такая лигатура fi. Это отдельный глиф в шрифте, а не два изображения, которые браузер придвинул друг к другу.
Подстановка происходит на этапе shaping. Шейпер, например HarfBuzz, получает исходный текст, применяет правила шрифта и возвращает глифы с их позициями. При этом сохраняет соответствие: вот этот глиф получился из вот этого участка строки. Поэтому после объединения f и i информация о двух исходных буквах никуда не исчезает.
А чтобы их разделить, в OpenType предусмотрены специальные данные: внутри лигатуры можно указать позиции курсора. Для fi — одну внутреннюю границу, для ffi — две. Они хранятся в таблице GDEF. То есть автор шрифта может описать не только внешний вид слитных букв, но и места, по которым их можно разделять при взаимодействии с текстом. Если этих данных нет или движок их не использует, границы приходится рассчитывать самому движку. Простое деление ширины пополам не всегда удачно: части лигатуры могут занимать разное место, поэтому точность положения курсора и подсветки зависит ещё и от реализации текстового движка.
Я в итоге убрала собственный расчёт ширины букв, и для каждого нужного участка текста создавала DOM Range и получала его прямоугольники через getClientRects(). И уже по ним размещала маркеры поверх редактора.
· 27.10
Лигатуры это фи...
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
коммент удалён
· 27.10
И не поспоришь 😂
0
ответить
коммент скрыт — часть юзеров считает его токсичным или некорректным
ответ удалён