dotnet / winforms

Windows Forms is a .NET UI framework for building Windows desktop applications.
MIT License
4.41k stars 982 forks source link

[Umbrella-Item] Investigate feasibility and implement Direct2D and DirectWrite Support #10740

Open KlausLoeffelmann opened 9 months ago

KlausLoeffelmann commented 9 months ago

Motivation behind this are performance and ability short-comings we are more and more facing with Font rendering and Bitmap (most of all transparancy) performance in certain contexts (DrawText, Label, Button, CheckBox, Owner-Drawing items, non-Win32-wrapped controls like DataGridView and ToolStripItems).

Note: This is NOT priority-planned for the .NET 9, might be changing though in priority, should the requirements change (A11Y, Localization, Performance).

While the Font-Rendering performance in WinForms has certainly room for improvement, the primary motivation behind this is another: we need rather be concerned about A11Y and localization issues in the future, which makes it important to already have this on our radar and start becoming prepared. (See below for a more detailed explanation around those concerns).

Details - concerns about Font-Rendering abilities mid- and long-term:

We can generally expect issues with fonts that have complex scripts, ligatures, or advanced typographic features. These fonts are more likely to benefit from DirectWrite for proper rendering or will need DirectWrite to be rendered at all. Here are some examples of font scenarios where GDI/GDI+ may face or already has challenges:

Fonts with Complex Scripts: Fonts designed for languages with complex scripts like Arabic, Hebrew, or Indic languages may not render correctly or fail to render correctly with GDI/GDI+ due to the intricate shaping and contextual glyph substitution required for these scripts. This would quickly lead to A11Y and serious localization issues.

Ligature-Heavy Fonts: Fonts that make extensive use of ligatures (special character combinations) may not display ligatures correctly with GDI/GDI+. DirectWrite can handle ligatures more effectively, or even address ligature rendering altogether, where GDI/GDI+ would fail.

Variable Fonts:: Variable fonts, which allow for variations in weight, width, or other attributes within a single font file, may not be or not sufficiently supported by GDI/GDI+.

Color Fonts:: Fonts that include color information (e.g., emoji fonts) will not render correctly with GDI/GDI+. This will also become more important in the future, since rendering text for all kind of aspects of UI will rely on Fonts providing Symbols, Pictograms, Emoticons, and will quickly turn into A11Y challenges.

OpenType Features: Fonts with advanced OpenType features like stylistic alternates, swashes, or discretionary ligatures may not or not sufficiently supported by GDI/GDI+.

elachlan commented 9 months ago

I am very excited about this feature and anything that improves overall performance.

I'd suggest the DirectX feature have a function of flag to turn on/off at runtime. In our production app that utilizes the DevExpress implementation, we enable DirectX if the user isn't using Terminal Services via a check against SystemInformation.TerminalServerSession.

I like the idea of the paint code being transparent to the user, so it just uses whatever renderer is configured and the user doesn't have to change how they do things. I am unsure if this is desired if we eventually want to expose more features to developers.

elachlan commented 9 months ago

CC: @weltkante / @willibrandon / @kant2002 / @halgab / @gpetrou If you are interested in Direct2D in winforms.

weltkante commented 9 months ago

I am very excited about this feature and anything that improves overall performance.

I wouldn't expect any significant performance improvements, as it would only affect code that is doing very expensive drawing, which WinForms itself doesn't really have as far as I'm aware (since most controls aren't very complex in the first place).

In my experience the more visible performance impact comes from composition, having a lot of controls on a form, the overhead is in the infrastructure and not in WinForms. Adopting a "windowless control" approach (where not every control has a HWND) would be the solution and probably have more impact than changing the rendering API. As far as my experience goes developers are more likely to compose controls than to write a complex custom control doing direct rendering. Note that developers who do write complex controls already can make use of Direct2D rendering today, though it may be beneficial to lower the barrier and make it easier.

merriemcgaw commented 9 months ago

CC: @weltkante / @willibrandon / @kant2002 / @halgab / @gpetrou If you are interested in Direct2D in winforms.

There goes @elachlan rallying the troops 🥁. Can't promise a particular release for some of these, but it's the direction we want to explore for sure.

tbolon commented 9 months ago

In my experience the more visible performance impact comes from composition, having a lot of controls on a form, the overhead is in the infrastructure and not in WinForms. Adopting a "windowless control" approach (where not every control has a HWND) would be the solution and probably have more impact than changing the rendering API. As far as my experience goes developers are more likely to compose controls than to write a complex custom control doing direct rendering. Note that developers who do write complex controls already can make use of Direct2D rendering today, though it may be beneficial to lower the barrier and make it easier.

I can only approve this message. We have multiple forms where we have reduced our usage of container controls / user control to increase performances. This reduced the clean aspect of our project, forcing us to duplicate code instead of reuse common component because of this.

KlausLoeffelmann commented 8 months ago

There are some scenarios, which are definitely profiting of this. Also, the initial utilization of DirectX/DirectWrite would be focused on this. As I said in the initial description:

I started a while ago messing with this on the side for a private project I was doing at the time, and I scoped it to just those API I needed, so, the approach is surely discussable and/or improvable. But there most likely are a few things giving you ideas. @JeremyKuhne FYI.

https://github.com/KlausLoeffelmann/WinFormsDx

JeremyKuhne commented 8 months ago

One of the things I want to do is whittle away at places where Bitmap and DrawImage can be a problem. Probably some combination of using the CachedBitmap class and rendering with a Direct2d bitmap. Probably will add a non-animated Direct2D "PictureBox".