Что заставляет Calibri терять ClearType между 9 и 14 pt?

Что именно заставляет GDI+ переключаться на двоичное сглаживание при использовании по умолчанию шрифта Microsoft Office Calibri между 9 и 14 pt с указанным ClearTypeGridFit?

Это несколько сбивает с толку. На сколько других шрифтов также влияет то, что стоит за этим, и в каких размерах? Есть ли обходной путь? (За исключением GDI, который не имеет таких же функций макета текста?)

Вот код, который я использовал для создания изображения:

private void Form1_Paint(object sender, PaintEventArgs e)
{
    e.Graphics.TextRenderingHint = TextRenderingHint.ClearTypeGridFit;

    var height = 0;
    for (var i = 1; i <= 17; i++)
    {
        using (var font = new Font("Calibri", i))
        {
            var text = "ClearTypeGridFit " + i + "pt";
            e.Graphics.DrawString(text, font, SystemBrushes.ControlText, 0, height);
            height += (int)e.Graphics.MeasureString(text, font).Height;
        }
    }
}

person jnm2    schedule 01.05.2015    source источник
comment
Graphics.DrawString() производит достойный вывод только на устройствах с высоким DPI. Принтеры, а не мониторы. Используйте TextRenderer.DrawText(e.Graphics, текст, шрифт, новая точка (0, высота), SystemColors.ControlText); вместо.   -  person Hans Passant    schedule 01.05.2015
comment
@HansPassant Понятно. Вопрос по-прежнему интересен и важен для меня. Это то, над чем я работаю.   -  person jnm2    schedule 01.05.2015
comment
Ясно, что вы будете ждать, пока DevEx поднимет свою задницу и что-нибудь с этим сделает. Между тем, используйте шрифт, который ведет себя лучше, шрифты XP не имеют этой проблемы. Пользовательский интерфейс Segoe тоже в порядке.   -  person Hans Passant    schedule 01.05.2015
comment
Наверное будет. А пока я очень надеюсь, что кто-то достаточно осведомлен, чтобы пролить свет на эту тайну. Поскольку я не контролирую шрифт, кто знает, где еще это может появиться с другими шрифтами?   -  person jnm2    schedule 01.05.2015
comment
Люди @HansPassant столкнутся с этой проблемой и получат гораздо больше пользы от вашего комментария, если вместо этого вы напишете его как ответ, даже если это не точный ответ на вопрос.   -  person Mike 'Pomax' Kamermans    schedule 01.05.2015


Ответы (1)


Calibri поставляется с таблицей EBLC и EBDT, которая сообщает текстовым механизмам, что для определенных размеров точек им не следует пробовать "свои собственные алгоритмы масштабирования", а просто использовать растровые изображения. вместо этого хранятся непосредственно в шрифте.

Каждый размер шрифта может поставляться со своим собственным списком «следующие глифы должны быть растровыми изображениями этого размера», называемыми «зачеркиваниями», поэтому один глиф может иметь несколько растровых изображений для разных размеров (но могут быть пробелы, и когда это происходит, растровые изображения необходимо масштабировать, и все может пойти катастрофически неправильно).

Например, у Calibri есть страйки для размеров точек 12, 13, 15, 16, 17 и 19, а пример растрового изображения для A:

<ebdt_bitmap_format_1 name="A">
  <SmallGlyphMetrics>
    <height value="8"/>
    <width value="7"/>
    <BearingX value="0"/>
    <BearingY value="8"/>
    <Advance value="7"/>
  </SmallGlyphMetrics>
  <rawimagedata>
    10102828 447c8282  
  </rawimagedata>
</ebdt_bitmap_format_1>

На это растровое изображение указывает размер шрифта 12, и оно закодировано как растровое изображение размером 7x8 пикселей. Поскольку 12 — это наименьшее значение, мы сталкиваемся с проблемами, когда используем размер шрифта меньше 12: внезапно нам приходится масштабировать растровое изображение. Это может пойти только ужасно неправильно.

Если вы посмотрите на что-то вроде WordPad, вы увидите, что механизм Microsoft Uniscribe (используемый с GDI+; современным эквивалентом является Direct2D с DirectWrite в качестве текстового движка) может довольно хорошо масштабировать эти растровые изображения (показано размеры от 5 до 20), но даже собственная технология Microsoft имеет явные ограничения. Мы видим, что при размерах шрифта 5, 6 и 7 пикселей растровые изображения довольно ужасны, и даже 8, 10 и 11 выглядят довольно шатко:

A размером от 5 до 20

Масштабируется до:

A в размерах от 5 до 20, увеличение в 3 раза

Все становится еще интереснее, потому что не каждый глиф представлен в каждом штрихе, поэтому, хотя «А» имеет растровое изображение с размером точки 12, существуют глифы, для которых наименьший размер точки с явным растровым изображением может быть 13, 15 или 16. или 17, или даже 19.

Это означает, что у вас есть три проблемы:

  1. Шрифт может «требовать», чтобы текстовый движок использовал его растровые изображения вместо того, чтобы пытаться растеризовать векторные контуры в соответствии с алгоритмами текстового движка, и
  2. Не существует волшебного размера шрифта, выше которого все символы отображаются «хорошо», а ниже — «плохо». Шрифт может иметь любое количество «штрихов», содержащих любое подмножество закодированных глифов шрифта, что фактически означает, что каждый символ может иметь свои собственные правила относительно того, когда текстовый движок должен переключаться с растеризованного вектора на встроенное растровое изображение, и
  3. Текстовые движки могут полностью игнорировать «требования» шрифта и в любом случае заниматься своими делами, и выяснить, какой движок что делает, практически невозможно, несмотря на то, что в нашем распоряжении есть Интернет. Это одна из тех вещей, которые, кажется, никто не документирует.

Самый простой способ узнать, какие шрифты будут это делать, — просто проверить шрифт для таблицы EBDT — если она есть, этот шрифт заставит движки использовать растровые изображения для очень маленьких (а иногда и очень больших) размеров шрифта. Если вам нужны подробности, вы можете запустить шрифт через TTX, а затем найти начало таблицы <EBDT>, чтобы увидеть что происходит на самом деле.

Однако приготовьтесь к тому, что вас переполнят. Например, только в Calibri растровые изображения указаны для более чем тысячи глифов.

person Mike 'Pomax' Kamermans    schedule 01.05.2015
comment
Эти удары не совпадают с 9-14 pt, но в остальном ваше объяснение имеет смысл. Я думал, что все современные движки рендеринга текста используют векторный рендеринг (очевидно, кешированный) — можете ли вы сказать, что в целом верно то, что большинство шрифтов рендерятся с использованием встроенных растров? - person jnm2; 02.05.2015
comment
Для профессиональных шрифтов TTF-OpenType, таких как Calibri, встроенные растровые изображения будут намного лучше, чем то, что может создать векторный растеризатор (rastertragedy.com объясняет, почему это так, в самых удивительных подробностях). Таким образом, хорошие текстовые движки будут использовать их, но не все. И то, что вы работаете в Windows, не означает, что вы всегда используете один и тот же движок: я думаю, что GDI+ использует Uniscribe, но современные версии Windows будут использовать Direct2D с DirectWrite. Тем не менее, я не программировал для Windows с Windows 95, так что это заслуживает проверки. - person Mike 'Pomax' Kamermans; 02.05.2015