Положение текста в DirectWrite отличается от размера шрифта
Я использую DirectWrite для визуализации текста в окне. Кажется, что все работает, кроме позиционирования при использовании шрифтов разных размеров: я ожидаю, что 2 текста с размером шрифта v1 и v2 и оба с (x, y) = (0, 0) будут в верхнем левом углу, но, как вы можете видеть:
ни "Test", ни "X" на самом деле не слева вверху.
Есть ли способ сделать эту работу?
3 ответа
Добро пожаловать в мир шрифтов. Шрифты, вероятно, являются наиболее трудными для использования, потому что сами шрифты неожиданны (есть так много новых стандартов, которые должны решить все и просто запутать больше, потому что почти 100% шрифтов не поддерживают его на 100%, даже некоторые "классические" шрифты имеют частичная / неверная информация в них) GDI, GDI+, DirectDraw не рисуют шрифт в одной и той же позиции в пикселях из-за математики, округления координат, сглаживания... (вы можете получить еще один бонус, если вы выполните математику с свободный тип).
При попытке напечатать шрифт есть другие pb. Так что единственный способ обойти это для меня. Даже не пытайтесь рисовать шрифт с определенными координатами пикселей. Делайте свою работу по рисованию шрифтов, рисунков, линий на экране, которые хорошо отрисовываются, делайте все возможное, чтобы преобразовать их в координаты печати для экспорта, но никогда не ожидайте управления пикселями в шрифтах, все округляется приблизительно.
PS: не доверяйте внутренним полям в шрифтах. В Arial они хороши для всех остальных шрифтов, некоторые из которых отсутствуют или инициализированы нулем, но "забавная" часть - это не всегда одно и то же поле, которого нет, это зависит от шрифтов. Вы можете использовать только поля, если вы попробуете их раньше шрифтом. Да, шрифты фантастические!
Термин @evilruff имеет в виду, называется "внутреннее лидерство". Вы можете использовать IDWriteFontFace::GetMetrics или, возможно, IDWriteFontFace::GetDesignGlyphMetrics, чтобы получить это значение (для GetMetrics наиболее вероятным является значение, которое вы ищете) metrics.ascent - metrics.capHeight
).
Здесь значения приведены в единицах дизайна шрифта, а не в пикселях (любого рода). Вы можете преобразовать эти значения в их высоту, разделив на metrics.designUnitsPerEm
; как правило, размеры шрифта в DirectWrite определяются размером пикселя (в нижнем регистре) m; поэтому, если вы умножаете значения в ems на размер шрифта, вы должны получить значения в пикселях.
Я предполагаю, что вы используете IDWriteTextLayout вместе с DrawTextLayout (а не создаете свой собственный DWRITE_GLYPH_RUN). IDWriteTextLayout выравнивает глифы по их ячейке макета (включая полное всплытие и разрыв строки), а не по чернилам глифа, и это верно практически для всех текстовых макетов, будь то веб-браузеры или текстовые процессоры или простые элементы управления редактированием. Если бы они этого не сделали (вместо выравнивания по верху буквы), то диакритические знаки в таких словах, как ishis, были бы вырезаны.
Если вы всегда хотите выровнять по чернилам, создайте IDWriteTextLayout, вызовите IDWriteTextLayout::GetOverhangMetrics, а затем вызовите DrawTextLayout с источником, равным отрицательному DWRITE_OVERHANG_METRICS::left&top. Если вы хотите выровнять по высоте колпачка всегда (таким образом, "привет" и "привет" будут рисовать с одинаковой вертикальной координатой), то подход Эрика будет работать.