В то время как Джефим правильно ответил на свой вопрос, я хотел объяснить, почему вы получаете такое поведение при использовании этого конкретного набора функций.Джефим предполагает, что это ошибка в WPF, но это не так.Проблема возникает в результате запроса WPF сделать что-то невозможное.Нужно искать компромисс, когда вы просили эту невозможную вещь, и в результате вы видите то, что вы видите выше.
Объяснение довольно длинное для комментария, поэтому я помещаю его вотдельный ответ.
В этом примере используются две взаимно противоречивые возможности WPF.Эти функции:
- Способность последовательно визуализировать визуалы в любом масштабе
- Способность отображать текст таким же образом, как GDI32 отображает текст
Youне может использовать обе функции одновременно.GDI32 отображает текст способом, который не может быть последовательно масштабирован: если конкретный фрагмент текста с определенным размером шрифта имеет ширину 200 пикселей, если вы умножаете размер шрифта на 3 и визуализируете тот же текст в том же семействе шрифтов вэтот новый размер шрифта, в GDI32 он, вероятно, не будет 600 пикселей - он будет близок, но, как правило, он будет не совсем правильным.
GDI32 портит форму и ширину символов для улучшениячеткость и четкость текста.В частности, он изгибает буквы не в форме, так что их функции лучше совпадают с пикселями на экране.И при необходимости, он будет регулировать ширину отдельных символов, чтобы быть точным числом пикселей в ширину.Поскольку это изгибание букв основано на реальных пикселях, оно изгибает текст по-разному с разными размерами шрифта.
Несмотря на то, что это дает хороший четкий текст, он выглядит совершенно ужасно, если вы пытаетесь постепенно изменять масштаб.Если вы попытаетесь анимировать размер шрифта некоторого текста, отображаемого таким образом, то эта вещь будет мерцать и дрожать, потому что корректировки, внесенные во имя ясности, в конечном итоге будут немного отличаться для каждого размера шрифта.Даже если вы не анимируете, это может привести к плохим результатам - если у вас есть один шрифт, показанный на нескольких размерах, он может выглядеть совершенно по-разному для каждого размера;если в вашем приложении есть функция масштабирования, то при увеличении и уменьшении изображения характер текста может существенно измениться.(То же самое можно сделать и с макетом. Если вы используете Microsoft Word, вы, возможно, заметили, что иногда между некоторыми словами появляются странные очень широкие пробелы. Это результат борьбы Word с GDI32 - Word пытается сохранить макет на экране.как можно ближе к тому, как все будет выглядеть при печати, а это означает, что иногда он вступает в конфликт с сеткой GDI32.)
Таким образом, WPF предлагает другой подход к визуализации текста: он может отображать текст максимально точно.насколько это возможно с оригинальным дизайном шрифта.Это меньше искажает текст, и это означает, что вы не получите разрывов при масштабировании.
Недостатком является то, что текст выглядит размытым по сравнению с тем, как выглядит текст, отображаемый с помощью GDI32.(Искажения, сделанные GDI32, направлены на повышение четкости.)
Поэтому в WPF 4.0 Microsoft добавила возможность рендеринга текста так, как это делает GDI32.Это то, что делает TextOptions.TextFormattingMode="Display"
.
Включая эту опцию, вы говорите: «Мне не нужно постоянное масштабирование, и я бы предпочел четкость, поэтому генерируйте те же пиксели, которые вы сделали бы в GDI32."Если вы затем продолжите применять масштабирование, сказав WPF, что вам не нужна масштабируемость, вы получите дрянные результаты.WPF тщательно сгенерировал растровое представление текста в точном соответствии с вашими спецификациями, а затем вы сказали ему визуализировать этот текст в другом масштабе.И вот так это выглядит: масштабированное растровое изображение текста, сгенерированного для другого разрешения.
Вы можете утверждать, что WPF может сделать что-то другое здесь: если вы примените преобразование масштаба в GDI32, вы увидите другое поведение - вы увидите несогласованность в различных масштабах, описанных ранее. Если вы действительно хотите этот эффект в WPF, вы можете получить его, изменив размер шрифта напрямую. Но WPF не имеет приоритета для получения того же эффекта - его цели - сделать так, чтобы можно было получать четкий текст в стиле GDI32, когда он вам действительно нужен, и обеспечить согласованное масштабирование по умолчанию.
И здесь вы сталкиваетесь с «последовательным масштабированием». Включение рендеринга текста в стиле GDI32 не нарушает согласованного масштабирования: применение масштабного коэффициента (либо напрямую, через ScaleTransform
, либо косвенно через Viewbox
) изменит размеры визуала точно на указанный коэффициент масштабирования. Если бы он заново генерировал текстовые визуальные эффекты путем подгонки сетки к вновь масштабированному размеру, текст получился бы с другой шириной. Это на самом деле вызовет проблемы Viewbox
: он применяет масштабный коэффициент, основанный на натуральном размере контента, который разработан так, чтобы он соответствовал доступному пространству. Но если после масштабирования будет выполнена повторная подгонка сетки, это фактически изменит ширину. Из-за несоответствий, присущих тому, как работает рендеринг текста в GDI32, ViewBox
может даже не найти подходящий масштаб - можно найти фрагмент текста, который при рендеринге определенным шрифтом никогда не будет выйти на 200 пикселей в ширину. Для некоторых размеров шрифта округление, присущее подгонке к сетке, может уменьшить размер, скажем, до 198, и оно может придерживаться этого, когда вы делаете крошечные приращения размера шрифта, пока не достигнете некоторого порогового значения, в котором точка может перейти до 202 пикселей.
Для Viewbox
, пытающегося заставить текст вписаться точно в 200 пикселей, это будет проблемой. Но Viewbox
не работает таким образом - он использует согласованное масштабирование WPF ниже точки, в которой вы выбрали размер шрифта, с которым работает рендеринг текста в стиле GDI32. Таким образом, Viewbox
всегда сможет сделать то, для чего он предназначен, но это задача, которая принципиально несовместима с рендерингом текста в стиле GDI32.
Короче говоря, WPF отображает текст для размера шрифта, который вы запрашивали, а затем масштабирует результат.
Так что вам нужно выбрать только одну функцию - вы не можете иметь обе, потому что это просто невозможно. Либо не пытайтесь отображать текст в контексте, в котором может быть применен произвольный масштабный коэффициент (например, Viewbox
), либо не включайте отображение текста в стиле GDI32. В противном случае вы получите тот странный пиксельный текст, с которым вы столкнулись.