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

Подгонка сетки и текста

Часть GDI+, отвечающая за работу с текстом, не зависит от устройства вывода. С практической точки зрения, это значит, что MeasureString возвращает размеры текста, не зависящие от устройства вывода. Если установить одинаковое преобразование страницы для экрана и принтера, MeasureString вернет одинаковое значение для заданной текстовой строки и заданного шрифта. Такая согласованность облегчает форматирование текста, чтобы он выглядел на экране так же, как при печати на принтере.

Однако желаемый принцип WYSIWYG трудно реализовать. Проблема в пикселях. Когда знаки шрифта растеризуются, координаты, выраженные числами c плавающей запятой, должны быть округлены с учетом дискретности пикселов. Такая подгонка под координатную сетку (grid fitting) требует специальных действий для сохранения читабельности шрифта. Скажем, два вертикальных штриха в заглавной букве H должны быть одинаковой ширины. Даже для шрифтов маленьких размеров эти два штриха должны иметь ширину не менее 1 пиксела и должны быть разнесены не менее чем на 1 пиксел. (Если размер точки слишком мал в сравнении с разрешением устройства вывода, такое требование теряет смысл, потому что текст не будет разборчивым в любом случае.)

Иногда, особенно для малых кеглей на устройствах с низким разрешением (таких как монитор), подгонка может привести к тому, что преобразованные шрифты будут гораздо больше, чем их теоретические размеры. Если собрать такие знаки (скажем, строчные знаки i гарнитуры Arial) вместе, это может привести к тому, что строка текста будет выглядеть на мониторе значительно больше, чем на принтере. (В статье на сайте http://www.gotdotnet.com/team/windowsforms/gdiptext.aspx эта проблема рассмотрена подробнее).

Соединяя разные фрагменты текста с помощью DrawString и MeasureString (как, например, в программе BoldAndItalic), что бы вы предпочли: иметь дополнительное пустое место между фрагментами или чтобы фрагменты текста перекрывались? Думаю, вы согласитесь, что наложение текста неприемлемо. Чтобы его предотвратить, в методы DrawString и MeasureString предусмотрительно заложена возможность включения небольшого дополнительного пустого места. Таким образом, если растеризатору потребуется больше места для прорисовки какого-либо шрифта, он его получит.

По умолчанию у объекта SizeF, возвращаемого MeasureString, свойство Height на 1/8 размера эм больше, чем теоретически нужно, и свойство Width на 1/3 размера эм больше, чем теоретическая ширина. (Помните: размер эм численно равен кеглю шрифта. Например, для 24-пунктного шрифта 1/3 размера эм равна 8 пт.) По умолчанию DrawString начинает выводить текст на монитор на 1/6 размера эм ниже заданной вертикальной координаты. Фактически MeasureString возвращает прямоугольник, который справа и слева шире, чем предполагаемая текстовая строка на 1/6 размера эм.

Поэтому в BoldAndItalic и, более наглядно, в BoldAndItalicBigger видны лишние пустые места между соединенными фрагментами текста.

Следует помнить, что проблема подгонки к координатной сетке имеет место только для шрифтов с маленькими кеглями, которые выводятся на устройства с низким разрешением. Чтобы добиться независимости от устройства, добавление пустого места в DrawString и MeasureString должно реализовываться одинаково для устройств как с высоким, так и с низким разрешением. Дополнительное пространство должно быть также пропорциональным размеру шрифтов. Для 720-пунктного шрифта MeasureString должен вернуть размер текста в 100 раз больше, чем для 7,2-пунктного шрифта.

Что делать, если не желательно оставлять пустые места в тексте? Использовать объект StringFormat, основанный на StringFormat.GenericTypographic. Вот версия программы BoldAndItalic, которая имеет дело с таким объектом:

BoldAndItalicTighter.cs

  //-----------------------------------------------------
  // BoldAndItalicTighter.cs (C) 2001 by Charles Petzold
  //-----------------------------------------------------
  using System;
  using System.Drawing;
  using System.Drawing.Text;
  using System.Windows.Forms;

  class BoldAndItalicTighter: PrintableForm
  {
      public new static void Main()
      {
          Application.Run(new BoldAndItalicTighter());
      }
      public BoldAndItalicTighter()
      {
          Text = "Bold and Italic (Tighter)";
          Font = new Font("Times New Roman", 24);
      }
      protected override void DoPage(Graphics grfx, Color clr, int cx, int cy)
      {
          const string str1        = "This is some ";
          const string str2        = "bold";
          const string str3        = " text, and this is some ";
          const string str4        = "italic";
          const string str5        = " text.";
          Brush        brush       = new SolidBrush(clr);
          Font         fontRegular = Font;
          Font         fontBold    = new Font(fontRegular, FontStyle.Bold);
          Font         fontItalic  = new Font(fontRegular, FontStyle.Italic);
          PointF       ptf         = new PointF(0, 0);
          StringFormat strfmt      = StringFormat.GenericTypographic;
          strfmt.FormatFlags      |= StringFormatFlags.MeasureTrailingSpaces;

          grfx.DrawString(str1, fontRegular, brush, ptf, strfmt);
          ptf.X += grfx.MeasureString(str1, fontRegular, ptf, strfmt).Width;

          grfx.DrawString(str2, fontBold, brush, ptf, strfmt);
          ptf.X += grfx.MeasureString(str2, fontBold, ptf, strfmt).Width;

          grfx.DrawString(str3, fontRegular, brush, ptf, strfmt);
          ptf.X += grfx.MeasureString(str3, fontRegular, ptf, strfmt).Width;

          grfx.DrawString(str4, fontItalic, brush, ptf, strfmt);
          ptf.X += grfx.MeasureString(str4, fontItalic, ptf, strfmt).Width;

          grfx.DrawString(str5, fontRegular, brush, ptf, strfmt);
      }
  }

Заметьте: в программе установлен флаг MeasureTrailingSpaces. Результат выглядит неплохо:


Рис. 9.13.

В программе BoldAndItalicTighter можно обойтись без объекта GenericTypographic, потому что заранее известно, что шрифт достаточно велик и несколько пикселов не имеют значения. Если вы хотите использовать GenericTypographic с малыми размерами шрифта на мониторе, вы также должны применить сглаживание краевых эффектов. При сглаживании не требуется подгонка к координатной сетке, потому что каждый пиксел окрашивается в зависимости от его удаленности от теоретического контура.


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

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