Самый простой и надежный подход - просто запросить у самого макета текстовые метрики, поскольку это одна из двух вещей, для которых он был разработан: рисование и измерение.Вы должны создать IDWriteTextLayout
, используя текстовый формат, и вызвать GetMetrics
, чтобы получить DWRITE_TEXT_METRICS::height
.Я предполагаю, что вы используете ID2D1RenderTarget::DrawText
и передаете текстовый формат, так что вы, возможно, не создали макет напрямую, но вызов DrawText
- это все равно, что вызвать CreateTextLayout
самостоятельно, а затем DrawTextLayout
.
Остерегайтесь того, что, проходя через нижние уровни, чтобы получить этот ответ (IDWriteFontFace
и т. П.), Делаются определенные предположения, которые не должен предполагать общий текстовый готовый текстовый элемент управления, например, предполагается, что будет использован базовый шрифт, и что все строкитакой же высоты.До тех пор, пока все символы присутствуют в данном базовом шрифте, это сработает (скорее всего, вы в основном отображаете английский, поэтому все выглядит хорошо), но добавьте некоторые языки CJK или RTL (базовый шрифт, такой как Times)Новый римлянин, конечно, не поддерживает), и высота строки будет увеличиваться или уменьшаться в соответствии с заменяемыми шрифтами.GDI изменяет размеры замененных шрифтов таким образом, чтобы они соответствовали высоте основного шрифта, но это приводит к плохо сжатым буквам на языках, таких как тайский и тибетский, которые нуждаются в большем пространстве для подъема и спуска.IDWriteTextLayout
и другие макеты, подобные тем, которые есть в WPF / Word, сохраняют все глифы шрифтов одинакового размера em, что означает, что они располагаются лучше, когда они расположены рядом друг с другом;но это означает, что высота строки является переменной.
Если вы просто нарисуете каждую строку текста, как если бы они были все одинаковой высоты, вы можете увидеть перекрытие между глифами и неоднородные базовые линии между строками или отсечениевверху и внизу элемента управления.Таким образом, идеальная вещь - это использовать фактическую высоту каждой строки;но если вам нужно, чтобы они все были одинаковой высоты (или если это слишком усложняет элемент управления), то, по крайней мере, установите явный межстрочный интервал, используя SetLineSpacing
с DWRITE_LINE_SPACING_UNIFORM
равным основному шрифту - таким образом, базовые линииравномерно распределены.
Хотя, для любопытных, да, высота линии действительно определяется с использованием метрик дизайна шрифта ascent + descent, плюс любой lineGap, который присутствует (большинство шрифтов устанавливают это значение на ноль, но Gabriolaявляется хорошим примером большого разрыва строки), умноженного на размер em и деленного на единицы на em.Обратите внимание, что все размеры em указаны в DIP (что при типичном 96DPI означает 1: 1, DIP точно == пиксели), а не в точках (1/72 дюйма).