Графика.DrawString vs TextRenderer.То drawtext?Что может поставить лучшее качество

TextRenderer основан на GDI и графике.Шнурок основан на GDI+.Какая из этих функций может обеспечить лучшее качество текста при рисовании текста на изображении.

4 ответов


только мои 2 цента: я всегда использую графику.Шнурок,за исключением когда мне нужно сделать пользовательскую роспись для моих (Windows Forms) элементов управления. Например, в списке с набором OwnerDraw, если я прикрепляю обработчик событий DrawItem, который полностью рисует элементы, включая текст элемента. Или в пользовательском контроле я должен нарисовать себя.

в приложении, которое использует визуальные стили в ОС, которая поддерживает его и имеет его включен, текст, нарисованный с графикой.DrawString выглядит "выключенным" при сравнении обычный текст, нарисованный другими элементами управления. Это, по-видимому, в основном из-за различий в способе обработки "ClearType" (или нет), хотя я не уверен, и у меня нет документов для резервного копирования этого оператора. (Он вроде выглядит как текст на .Объем 1.x или при переключении FlatStyle со стандартного на системный и v. v.)

только в таких случаях (рисование текста на элементах управления Winforms) я использую TextRenderer.DrawText, чтобы сделать текст лучше смешаться с другим контроли.

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


я кросс-пост моего ответа из-за здесь, просто чтобы информация распространилась.


существует два способа рисования текста в .NET:

  • GDI+ (graphics.MeasureString и graphics.DrawString)
  • GDI (TextRenderer.MeasureText и TextRenderer.DrawText)

в .NET 1.1 все используется GDI+ для отрисовки текста. но были некоторые проблемы:

  • есть некоторые проблемы с производительностью, вызванные несколько апатридным характером GDI+, где контексты устройства будут установлены, а затем восстановлены после каждого вызова.
  • механизмы формирования для международного текста были обновлены много раз для Windows/Uniscribe и для Avalon (Windows Presentation Foundation), но не были обновлены для GDI+, что приводит к международной поддержке рендеринга для новых языков, чтобы не иметь тот же уровень качества.

поэтому они знали, что хотят изменить .NET framework, чтобы прекратить использовать GDI+система рендеринга текста, и использовать GDI. Сначала они надеялись, что смогут просто измениться:--38-->

graphics.DrawString

называть старой DrawText API вместо GDI+. Но!--69-->они не могли сделать текстовую обертку и интервал точно такими же, как GDI+!--37-->.

в Windows Forms 2.0 добавлена поддержка рисования текста GDI. На сначала у нас были грандиозные планы тыкать и подталкивать API DrawText, чтобы мы могли сделать его точно таким, как работает API DrawString GDI+. Я действительно думаю, что мы довольно близки, но есть фундаментальные различия в обертывании слов и интервале символов, которые как простые потребители обоих API, Windows Forms не могли решить.

Итак, теперь перед нами проблема: мы хотим переключить всех на новый API TextRenderer, чтобы текст выглядел лучше, локализовать лучше рисовать более последовательно с другими диалогами в операционной системе... ...но мы не хотим разбивать людей, рассчитывающих на строку измерения GDI+ для расчетов того, где их текст должен выстраиваться.

поэтому они были вынуждены держать graphics.DrawString для вызова GDI+ (причины совместимости; люди, которые звонили graphics.DrawString внезапно обнаружил бы, что их текст не обернулся так, как раньше). из MSDN:

основанный GDI TextRenderer класс был представлен в .NET Framework 2.0 для повышения производительности, улучшения внешнего вида текста и улучшения поддержки международных шрифтов. В более ранних версиях .NET Framework GDI + based графика класс использовался для выполнения всего рендеринга текста. GDI вычисляет интервал между символами и перенос слов по-разному от GDI+. В приложении Windows Forms, использующем графика класс для рендеринга текста, это может привести к тексту для элементы управления, которые используют TextRenderer чтобы отличаться от другого текста в приложении. Чтобы устранить эту несовместимость, вы можете установить UseCompatibleTextRendering свойство правда для конкретного управления. Установить UseCompatibleTextRendering to правда для всех поддерживаемых элементов управления в приложении, вызов приложение.SetCompatibleTextRenderingDefault метод с параметром правда.

новый статический TextRenderer класс создан для переноса отрисовки текста GDI. Он имеет два метода:

TextRenderer.MeasureText
TextRenderer.DrawText

Примечание: TextRenderer является оберткой вокруг GDI, в то время как graphics.DrawString все еще обертка вокруг GDI+.


затем возникла проблема, что делать со всеми существующими элементами управления .NET, например:

  • Label
  • Button
  • TextBox

они хотели переключить их на использование TextRenderer (т. е. GDI), но они должны были быть осторожны. Могут быть люди, которые зависят от своих элементов управления, как в .NET 1.1. И так родился "совместимый рендеринг текста".

по умолчанию элементы управления в приложении ведут себя так же, как в .NET 1.1 (они"совместимость").

вы выключить режим совместимости с вызовом:

Application.SetCompatibleTextRenderingDefault(false);

это делает ваше приложение лучше, быстрее, с Лучшая международная поддержка. Подводя итог:

SetCompatibleTextRenderingDefault(true)  SetCompatibleTextRenderingDefault(false)
=======================================  ========================================
 default                                  opt-in
 bad                                      good
 the one we don't want to use             the one we want to use
 uses GDI+ for text rendering             uses GDI for text rendering
 graphics.MeasureString                   TextRenderer.MeasureText
 graphics.DrawString                      TextRenderer.DrawText
 Behaves same as 1.1                      Behaves *similar* to 1.1
                                          Looks better
                                          Localizes better
                                          Faster

также полезно отметить сопоставление между GDI+TextRenderingHint и тегом LOGFONT качество используется для рисования шрифта GDI:

TextRenderingHint           mapped by TextRenderer to LOGFONT quality
========================    =========================================================
ClearTypeGridFit            CLEARTYPE_QUALITY (5) (Windows XP: CLEARTYPE_NATURAL (6))
AntiAliasGridFit            ANTIALIASED_QUALITY (4)
AntiAlias                   ANTIALIASED_QUALITY (4)
SingleBitPerPixelGridFit    PROOF_QUALITY (2)
SingleBitPerPixel           DRAFT_QUALITY (1)
else (e.g.SystemDefault)    DEFAULT_QUALITY (0)

образцы

вот некоторые сравнения GDI+ (графика.DrawString) стихи GDI (TextRenderer.DrawText) рендеринг текста:

GDI+: TextRenderingHintClearTypeGridFit, GDI: CLEARTYPE_QUALITY:

enter image description here

GDI+: TextRenderingHintAntiAlias, GDI: ANTIALIASED_QUALITY:

enter image description here

GDI+: TextRenderingHintAntiAliasGridFit, GDI: не поддерживается, использует ANTIALIASED_QUALITY:

enter image description here

GDI+: TextRenderingHintSingleBitPerPixelGridFit, GDI: PROOF_QUALITY:

enter image description here

GDI+: TextRenderingHintSingleBitPerPixel, GDI: DRAFT_QUALITY:

enter image description here

мне кажется странным, что DRAFT_QUALITY идентичен PROOF_QUALITY, который идентичен CLEARTYPE_QUALITY.

см. также


мой личный опыт (я знаю только эти два отличия):

DrawString поддерживает Альфа-канал, сглаживание

TextRenderer поддерживает Uniscribe


Я просто добавлю тестовый код:

class Form1: Form
{
    private string str = "hello world hello world hello world";
    private int x = 32, yLabel = 0, yDraw = 64, yRenderer = 32;

    public Form1()
    {
        Font = new Font("Times", 16);

        Label label = new Label();
        label.BorderStyle = BorderStyle.FixedSingle;
        label.AutoSize = true;
        label.Text = str;
        label.Location = new Point(x, yLabel);
        Controls.Add(label);
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        SizeF a;

        // TextRenderer
        a = TextRenderer.MeasureText(str, Font);
        TextRenderer.DrawText(e.Graphics, str, Font, new Point(x, yRenderer), Color.Pink);
        e.Graphics.DrawRectangle(new Pen(Color.Blue), x, yRenderer, a.Width, a.Height);

        // DrawString
        e.Graphics.DrawString(str, Font, new SolidBrush(Color.Red), x, yDraw);
        a = e.Graphics.MeasureString(str, Font);
        e.Graphics.DrawRectangle(new Pen(Color.Lime), x, yDraw, a.Width, a.Height);

        base.OnPaint(e);
    }
}

нижняя строка: по сравнению с простой меткой TextRenderer является более точным.