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