dotnet / announcements

Subscribe to this repo to be notified of Announcements and changes in .NET Core.
Creative Commons Attribution 4.0 International
1.27k stars 44 forks source link

`System.Drawing.Common` will only be supported on Windows #228

Open terrajobst opened 2 years ago

terrajobst commented 2 years ago

This issue is a locked mirror of https://github.com/dotnet/designs/pull/234. See that issue for discussion.

Note: This is a re-post of a design point we already discussed and shipped in .NET 6. I'm posting this here because (1) some people have tried to find it here and (2) some folks have never heard of it.

Moving forward, System.Drawing.Windows will only be supported on Windows. The library is marked as Windows-only (which results in build warnings when used from cross-platform code) and will throw by default when used from a non-Windows OS. For the time being, there is a runtime switch that enables users to still carry and use their own copy of libgdiplus. We intend to remove this functionality eventually as well.

Details

In the .NET Core 2.x days we created the Microsoft.Windows.Compatibility package which exposes many Windows-only APIs so that more people can migrate to .NET Core. As part of this, we also ported System.Drawing.Common. This was mainly meant for .NET Core users that still target Windows, however since Mono already had a cross-platform implementation, we decided to bring that over. The cross-platform functionality is provided via the native library libgdiplus. Sadly, libgdiplus is a community supported library and at this point effectively unmaintained.

While libgdiplus has helped a lot of customers expand to cross-platform it has also caused some headaches. System.Drawing.Common is very Windows driven as it is mostly a wrapper around GDI+ and is heavily coupled to Windows Forms, which keeps evolving and diverging from cross-platform graphics. This has caused some confusion over why some things don't work well on Unix or don't work at all.

The cross-platform implementation of System.Drawing.Common is mainly provided on the native side, via libgdiplus. It's effectively a re-implementation of the parts of Windows that System.Drawing.Common is depending on. As you can imagine, that makes libgdiplus a very non-trivial component. It's around 30k lines of pretty old C code, virtually untested, and lacks a lot of functionality. libgdiplus also has a lot of external dependencies for all the image processing and text rendering, such as cairo, pango, and other native libraries, which makes maintaining and shipping it even more challenging.

Since System.Drawing.Common was really designed to be a thin wrapper over Windows technologies, its cross-platform implementation is a bit like a square peg in a round hole; it's subpar because it was only designed with Windows in mind.

Since the inclusion of the Mono cross-platform implementation we spent lot of time redirecting issues to libgdiplus that never got fixed, or helping people install libgdiplus correctly (because it's not part of .NET Core proper). This is very different from other external dependencies we have taken, for example, icu or openssl, which are high-quality libraries, rather than poorly maintained re-implementation of Windows components. Thus, we have come to believe that it's not viable to get libgdiplus to the point where its feature set and quality is on par with the rest of the .NET stack.

We have noticed (such as from analysis of NuGet packages) that System.Drawing.Common is used on cross-platform mostly for image manipulation like QR code generators and text rendering. We haven't noticed heavy graphics usage as our cross-platform graphics support is very incomplete. For example, right now some components crash on macOS because the native APIs we use have been deprecated and are no longer included with recent macOS releases. We have never gotten a report about that crash; we discovered it ourselves while making System.Drawing.Common trim compatible.

The usages we see of System.Drawing.Common in non-Windows environments are typically well supported with SkiaSharp and ImageSharp.

Thus, we believe it is not worth investing in making System.Drawing.Common work on non-Windows platforms and instead propose we only keep evolving it in the context of Windows Forms and GDI+.

Design Approach

For more details on the design approach, see this design document.