| 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 | < Назад | Оглавление | Далее > |