Блог переехал. Актуальная версия поста находится по адресу: http://aakinshin.net/ru/blog/dotnet/fonts/.
Сегодня мы поговорим о замечательном классе Font. Иногда при работе с шрифтами возникают некоторые вопросы, которые не настолько очевидны, как хотелось бы. Рассмотрим несколько из них.
Q: Как опознать моноширинный шрифт?
A: Это не такой простой вопрос. Если немного погуглить, то можно найти следующий совет: описываем у себя в проекте класс LOGFONT и используем метод ToLogFont для конвертации шрифта в соответствующий объект. После этого (согласно легенде) в поле lfPitchAndFamily первый бит должен определять моноширинность шрифта. Так вот, это враньё, в современном мире поле всегда будет равно нулю. Когда-то где-то этот способ работал, но сейчас не работает. В реальности приходится использовать не очень красивое, но весьма эффективное решение типа такого:
// graphics — заранее созданный экземпляр класса Graphics public static bool IsMonospace(Font font) { return Math.Abs(graphics.MeasureString("iii", font).Width - graphics.MeasureString("WWW", font).Width) < 1e-3; }
Q: А как узнать размеры, которые будет занимать строчка при рисовании данным шрифтом?
A: Нам понадобится Graphics, с помощью которого мы собираемся рисовать, а именно — его метод MeasureString. Передаём ему рисуемый текст и используемый шрифт — а он нам в ответ отдаёт его размеры.
Q: А если мне нужен размер не всей строчки, а только заданных её частей?
A: Это можно сделать с помощью метода Graphics.MeasureCharacterRanges. Но сначала (в msdn есть хороший пример) нужно задать целевые интервалы символов с помощью метода StringFormat.SetMeasurableCharacterRanges. Это метод обладает занимательным ограничением — ему нельзя передавать более 32-х интервалов.
Q: Этот метод выдаёт какие-то слишком большие границы. В них попадают не только сами символы, но и немного пространства около них. Что делать?
A: Действительно, возвращаемые регионы содержат интересующие нас символы так, как они идут в исходном шрифте — вместе с небольшой пустотой около них. Красивого способа получить точные границы нет. Придётся явно создавать картинку с целевыми символами, попиксельно её просмотреть (только не используйте метод Bitmap.GetPixel, он очень долгий, есть более быстрые способы) и найти крайние нарисованные символы нашей строки.
Q: Я создал шрифт, используя его строковое название, никаких исключений не вылетело. А этот шрифт точно есть в системе?
A: Не обязательно. Конструктор класса Font попытается подобрать самый подходящий (по его мнению) шрифт для данного названия. Лучше проверить, что создался правильный шрифт:
var font = new Font(fontName, 12); vat isExist = font.Name == fontName;А ещё не помешает проверить, поддерживает ли используемое вами семейство шрифтов ваш FontStyle:
var fontFamily = new FontFamily(fontName); isExist &= fontFamily.IsStyleAvailable(fontStyle);
Комментариев нет:
Отправить комментарий