netlib.narod.ru | < Назад | Оглавление | Далее > |
Программисты, имеющие опыт работы со шрифтами в Windows или в других графических средах, возможно, согласятся, что в Windows Forms не хватает графических средств для работы с метриками шрифтов. До сих пор мы имели дело только с тремя параметрами, относящимися к высоте знаков: кеглем (который, как я подчеркивал, является понятием типографского дизайна и имеет лишь косвенное отношение к метрическим размерам знаков шрифта), максимальным размером знаков, который можно получить из MeasureString, и рекомендуемым межстрочным интервалом, определяемым методом GetHeight, а в целочисленном виде, подходящем только для мониторов, — Height.
Нужна еще одна метрика шрифта, определяющая положение базовой линии (baseline) — линии, выше которой располагаются надстрочные элементы, а ниже — подстрочные элементы. Если требуется совмещать разные шрифты на одной строчке, то нужно знать положение базовой линии по отношению к верхней или нижней точке знаков (то, что задается в методе DrawString).
На самом деле эта информация содержится в классе FontFamily. Это не так очевидно и не будет работать для некоторых восточных шрифтов, но это лучшее средство, имеющееся в нашем распоряжении.
Класс FontFamily содержит четыре метода, позволяющих получить дополнительную метрическую информацию о шрифте. В каждом из этих методов в качестве аргумента выступает перечисление FontStyle.
Методы FontFamily (выборочно)
int GetEmHeight(FontStyle fs) |
int GetCellAscent(FontStyle fs) |
int GetCellDescent(FontStyle fs) |
int int GetLineSpacing(FontStyle fs) |
Эти величины называются метриками дизайна, потому что задаются дизайнером шрифтов (по крайней мере для шрифтов TrueType). Они не связаны с конечным размером шрифта.
Рассмотрим пример. Если создать FontFamily на основе гарнитуры Times New Roman и вызвать эти четыре метода с аргументом FontStyle.Regular (или любой другой величиной FontStyle), получатся такие значения:
Метрики дизайна шрифта Times New Roman
Метрика | Значение |
Эм-высота (Em Height) | 2048 |
Высота с надстрочным элементом (Ascent) | 1825 |
Высота подстрочного элемента (Descent) | 443 |
Высота с надстрочным элементом + высота подстрочного элемента | 2268 |
Межстрочный интервал | 2355 |
Эм-высота характеризует сетку, позволяющую дизайнеру шрифта задавать координаты линий и кривых, определяющих внешний вид знаков шрифта. Обычно используется значение 2 048, реже 1 000 или 256.
Высота с надстрочным элементом — это высота знаков шрифта над базовой линией шрифта (включая диакритические знаки), а высота подстрочного элемента — это высота знаков под базовой линией шрифта. Для гарнитуры Times New Roman сумма высоты с надстрочным элементом и высоты подстрочного элемента (которая представлена в таблице) представляет действительную высоту знаков шрифта.
Межстрочный интервал состоит из трех компонентов: высота с надстрочным элементом над базовой линией, высота подстрочного элемента под базовой линией и дополнительное место под подстрочным элементом, как показано на рисунке:
Для некоторых шрифтов значение межстрочного интервала больше, чем сумма высоты с надстрочным элементом и высоты подстрочного элемента, а для некоторых они равны.
Не пытайтесь найти эм-высоту на этом рисунке! Она служит для связи с другими метриками дизайна.
Давайте создадим 72-пунктный шрифт Times New Roman и присвоим свойству PageUnit значение GraphicsUnit.Point. Это значит, что GetHeight возвращает значение в пунктах независимо от разрешения графического устройства. Мы получим такие значения (округленные до двух знаков после запятой):
Метрики шрифта Times New Roman
Свойство или метод | Значение (в пунктах) |
font.SizeInPoints | 72.00 |
font.GetHeight(grfx) | 82.79 |
Есть ли соответствие между этой таблицей и предыдущей, показывающей метрики дизайна? Да, потому что величина, полученная из GetHeight, выводится из метрик дизайна. Метрика дизайна, названная эм-высотой, соответствует кеглю шрифта. Если разделить 72 на 2 048 мы получим 0,03515625. Это коэффициент масштабирования для преобразования координат знаков шрифта в кегль. Умножив его на межстрочный интервал (2355), вы получите 82,79 — величину, возвращаемую методом GetHeight.
Смысл в том. что можно применить один и тот же коэффициент отдельно к высоте с надстрочным элементом и к высоте подстрочного элемента метрик дизайна, чтобы получить величины, которых у нас до этого не было:
Метрики Times New Roman
Метрика | Значение метрики дизайна | Значение для 72-пунктного шрифта (в пунктах) | Свойство или метод |
Эм-высота | 2048 | 72.00 | font.SizeInPoints |
Высота с надстрочным элементом | 1825 | 64.16 | |
Высота подстрочного элемента | 443 | 15.57 | |
Высота надстрочного элемента + высота подстрочного элемента | 2268 | 79.73 | |
Межстрочный интервал | 2355 | 82.79 | font.GetHeight(grfx) |
Информацию, полученную из метрик дизайна, можно использовать для позиционирования текста на базовой линии шрифта. Предположим, мы хотим поместить базовую линию горизонтально в центре клиентской области и разместить 144-пунктный шрифт Times New Roman на этой линии. Вот программа, которая делает это.
TextOnBaseline.cs
//----------------------------------------------- // TextOnBaseline.cs (C) 2001 by Charles Petzold //----------------------------------------------- using System; using System.Drawing; using System.Windows.Forms; class TextOnBaseline: PrintableForm { public new static void Main() { Application.Run(new TextOnBaseline()); } public TextOnBaseline() { Text = "Text on Baseline"; } protected override void DoPage(Graphics grfx, Color clr, int cx, int cy) { float yBaseline = cy / 2; Pen pen = new Pen(clr); // Рисуем базовую линию в центре клиентской области grfx.DrawLine(pen, 0, yBaseline, cx, yBaseline); // Создаем 144-пунктный шрифт Font font = new Font("Times New Roman", 144); // Получаем и вычисляем метрики float cyLineSpace = font.GetHeight(grfx); int iCellSpace = font.FontFamily.GetLineSpacing(font.Style); int iCellAscent = font.FontFamily.GetCellAscent(font.Style); float cyAscent = cyLineSpace * iCellAscent / iCellSpace; // Отображаем текст на базовой линии grfx.DrawString("Baseline", font, new SolidBrush(clr), 0, yBaseline - cyAscent); } }
Величина cyAscent — это высота с надстрочным элементом для 144-пунктного шрифта Times New Roman. Если вычесть ее из вертикальной координаты базовой линии, получим координаты для размещения текста на базовой линии:
Если приглядеться, можно заметить, что закругленные части некоторых букв располагаются немного ниже базовой линии. Так и должно быть.
netlib.narod.ru | < Назад | Оглавление | Далее > |