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 сумма высоты с надстрочным элементом и высоты подстрочного элемента (которая представлена в таблице) представляет действительную высоту знаков шрифта.

Межстрочный интервал состоит из трех компонентов: высота с надстрочным элементом над базовой линией, высота подстрочного элемента под базовой линией и дополнительное место под подстрочным элементом, как показано на рисунке:


Рис. 9.9.

Для некоторых шрифтов значение межстрочного интервала больше, чем сумма высоты с надстрочным элементом и высоты подстрочного элемента, а для некоторых они равны.

Не пытайтесь найти эм-высоту на этом рисунке! Она служит для связи с другими метриками дизайна.

Давайте создадим 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. Если вычесть ее из вертикальной координаты базовой линии, получим координаты для размещения текста на базовой линии:


Рис. 9.10.

Если приглядеться, можно заметить, что закругленные части некоторых букв располагаются немного ниже базовой линии. Так и должно быть.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz