Страницы

Поиск по вопросам

понедельник, 1 октября 2018 г.

Магия шрифтов по умолчанию в WPF

Я заметил, что если при создании шрифта указать пустую строку, то используется шрифт Arial, но он почему-то отрисовывается на несколько пикселей выше, чем Arial, хотя Baseline у них одинаковый и равен 0,921630859375. (VS2015, Windows 10) С чем это может быть связано и как исправить такое поведение?
textBlock1.FontFamily = new FontFamily("Arial"); // Red, Baseline = 0,921630859375 textBlock2.FontFamily = new FontFamily(""); // Green, Baseline = 0,921630859375

Также заметил, что если при создании шрифта указать несуществующий шрифт, то используется уже шрифт Segoe UI и отрисовывается уже прилично выше, чем Segoe UI. Причиной тому скорей всего отличия в Baseline. Почему Baseline отличаются? Как его можно задать вручную?
textBlock1.FontFamily = new FontFamily("Segoe UI"); // Red, Baseline = 1,0791015625 textBlock2.FontFamily = new FontFamily("non-existent"); // Green, Baseline = 0,921630859375
или то же самое в XAML


Ответ

В WPF существует механизм автоматического замещения (fallback) шрифтов. (См. MSDN: FontFamily.) Если указанный физический шрифт не удается найти на целевой системе, вместо него используется составной (composite) шрифт Global User Interface. По сути это XML-файл, который содержит параметры шрифта (в т.ч. и Baseline) и сопоставления диапазонов символов физическим шрифтам. Этот файл лежит в
%WINDIR%\MICROSOFT.NET\Framework\версия\WPF\Fonts\GlobalUserInterface.COMPOSITEFONT
Диапазону символов 0000-052F (куда и входят английские буквы) в нем сопоставлены следующие шрифты:
Segoe UI, Tahoma, Arial, Simplified Arabic, Traditional Arabic, Arial Unicode MS, Microsoft Sans Serif, Lucida Sans Unicode
Параметры шрифта по умолчанию следующие:
Baseline: 0.9
Line spacing: 1.2
Таким образом, как Segoe UI, так и Arial могут, в зависимости от ситуации, замещать не найденные шрифты (при этом вид будет отличаться от соответствующих "нормальных" шрифтов, из-за отличающихся LineSpacing и BaseLine). При указании пустой строки вместо шрифта используется Arial, поскольку он прописан как NullFontFamilyCanonicalName в коде модуля FontFamily.cs
internal static readonly CanonicalFontFamilyReference NullFontFamilyCanonicalName = CanonicalFontFamilyReference.Create(null, "#ARIAL");
При указании несуществующего шрифта используется Segoe UI, так как он является шрифтом по умолчанию для GUI в Windows Vista и всех более поздних ОC. См. Change the Default Font of a WPF Application
Если вас не устраивают параметры Composite Font по умолчанию, можно отредактировать XML-файл (там несколько секций, надо брать соответствующую вашей ОС). Но лучше, я полагаю, этого не делать, и просто не ошибаться в шрифтах.

Комментариев нет:

Отправить комментарий