# Managed Graphics

## Overview

.NET (formerly .NET Core) version 7.0.0 and later [no longer supports](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/system-drawing-common-windows-only) `System.Drawing.Common` on Linux. This change leaves Linux users without a direct, Microsoft-provided alternative.

{% hint style="warning" %}
If you're developing cross-platform applications, be particularly mindful of graphics-related code. While our managed implementation provides consistent behavior across platforms, you should still test the target platform thoroughly to ensure compatibility.

Until version `6.0.0`, you could set the `System.Drawing.EnableUnixSupport` application switch to use `System.Drawing.Common` on Linux systems with libgdiplus. This is why Wisej.NET references version `6.0.0` of the `System.Drawing.Common` NuGet package.
{% endhint %}

Additionally, .NET code running on iOS or Android platforms has never supported any version of `System.Drawing.Common`. Microsoft recommends using [alternative libraries](#alternative-libraries) such as `ImageSharp` or `SkiaSharp` for these platforms.

In Wisej.NET 3, there are three graphics implementations: `GDI+` on Windows, `libgdiplus` on Linux, [ImageSharp](https://sixlabors.com/products/imagesharp/) on iOS and Android. All three implementations provide different font measurements, leading to inconsistencies across platforms.

Our new `System.Drawing.Managed` implementation delivers consistent performance across all platforms and aligns much more closely with the browsers' font measurements. This ensures a uniform experience regardless of the deployment platform.

{% hint style="info" %}
Any reference to "`net8.0`" indicates the version against which Wisej.NET 4 is compiled. In your projects, you can use "`net9.0`" or "`net10.0`".
{% endhint %}

## Wisej.NET 4 Usage

Wisej.NET requires a graphics library for loading images from files or embedded resources and measuring text on the server side for controls  `AutoSize` set to `true`. No painting functionality is needed within Wisej.NET.

Applications built on Wisej.NET can use the [Paint](https://docs.wisej.com/docs/controls/general/custom-painting) event to draw on controls or within grid cells, enabling complex UI features.

The Wisej.NET 4 package includes this dependency:

```xml
<PackageReference Include="Managed.System.Drawing" Version="4.0.*-*" />
```

{% hint style="info" %}
We named the package "`Managed.System.Drawing`" because the "System" root name on nuget.org is reserved for Microsoft.
{% endhint %}

The namespace remains `System.Drawing`, so no code changes are needed. All primitives like `Point`, `Size`, and `Color` come from `System.Drawing.Primitives`. `System.Drawing.Managed` classes like `Font` and `Image` can cast to and from their `System.Drawing.Common` (GDI+) counterparts.

## Platforms Support

`System.Drawing.Managed` (and [ImageSharp](https://sixlabors.com/products/imagesharp/)) has two major implementations: Font and Graphics. Font handles loading, measuring, and rendering fonts. Graphics handles loading, saving, and drawing images, providing operations available in `System.Drawing.Graphics`.

Only the Font implementation is available on the .NET Framework because [ImageSharp](https://sixlabors.com/products/imagesharp/)'s Graphics implementation relies on graphics acceleration primitives exclusive to .NET Core.

In Wisej.NET 4 for .NET Framework, we shield developers from this difference. Although `Font` and `Image` come from `System.Drawing.Common`, all font measurements use the managed `System.Drawing.Font` internally, ensuring compatibility with .NET Core deployments.

As explained on the .NET Core Designer page, using the Visual Studio Designer required building a version of Wisej.Framework compatible with "`net8.0-windows`". This build uses `System.Drawing.Common` for public properties.

| Feature  | Windows (.NET Fx) | .NET Core All Platforms | .NET Core Designer |
| -------- | ----------------- | ----------------------- | ------------------ |
| Font     | Managed           | Managed                 | Managed            |
| Graphics | GDI+              | Managed                 | GDI+               |

For deployment, we recommend using the non-OS-specific `net8.0` target instead of "`net8.0-windows`" as it uses only managed code.

| Deployment Target | Target Framework             |
| ----------------- | ---------------------------- |
| Windows           | `net481` or `net8.0`         |
| Linux or MacOS    | `net8.0`                     |
| iOS Hybrid        | `net8.0-ios`                 |
| Android Hybrid    | `net8.0-android`             |
| MacOS Hybrid      | `net8.0-maccatalyst`         |
| Windows Hybrid    | `net8.0-windows10.0.19041.0` |

As shown above, `System.Drawing` (GDI+) is only used for deployment on Windows servers using the .NET Framework.

## Namespace Collision

Wisej.NET imports `System.Drawing` on .NET Framework targets and `System.Drawing.Common` on .NET Core targets to enable multi-targeting. It also imports `System.Drawing.Managed`. Since all three use the same namespace, failing to alias them may cause compiler errors, such as the `Font` class being available in multiple assemblies.

Since all three use the same namespace, failing to reference one of the assemblies correctly may cause compiler errors, such as the `Font` class being available in multiple assemblies.

In Wisej.NET 4, we reference and alias `System.Drawing.Common`  like this:

{% code title="Wisej-4.props" %}

```xml
<!-- NETCORE:
	Include aliased System.Drawing.Common, it's almost never used. It's a required dependency for
	Managed.System.Drawing on netcore to provide optional implicit casting to/from native GDI+ types.
-->
<ItemGroup Condition="!$(TargetFramework.Contains(`-windows`)) And '$(TargetFramework.TrimEnd(`0123456789`))'!='net'">
	<PackageReference Include="System.Drawing.Common" Version="$(_TargetFrameworkVersionWithoutV).0" Aliases="sdc" ExcludeAssets="compile"/>
</ItemGroup>
```

{% endcode %}

{% hint style="danger" %}

* If you get a namespace collision error, remove any `System.Drawing.Common` reference from your projects, as it's included with the Wisej.NET 4 NuGet package.
* If a third party NuGet pulls in a reference to System.Drawing.Common with a different version causing compiler errors, you can instead add a `<PackageReference>` item in your project with the same version and add `Alias="sdc`" to the tag.
  {% endhint %}

## Alternative Libraries

Here are Microsoft's four alternatives and our assessment of each:

### [ImageSharp](https://sixlabors.com/products/imagesharp/)

Fully Managed Code: With no native dependencies or interop code, ImageSharp simplifies development and can be installed anywhere  supports[`.NET 6+`](https://docs.microsoft.com/en-us/dotnet/standard/net-standard)- anything from external devices to embedded/IoT scenarios.

[ImageSharp](https://sixlabors.com/products/imagesharp/) is a managed graphics library that handles various graphic formats, including `WebP`. Combined with its Fonts library, it provides a foundation for implementing a cross-platform version of `System.Drawing`.

We licensed the [ImageSharp](https://sixlabors.com/products/imagesharp/) source code and worked with SixLabors' founder to create `System.Drawing.Managed`. This single, self-contained, managed .NET library replaces `System.Drawing.Common` on all platforms, ensuring consistent font measurements across browsers and platforms.

{% hint style="info" %}
We plan to release the `4.0.0` NuGet package on nuget.org for use independently of Wisej.NET 4. Version `3.5` is incomplete and required only by Wisej.NET Hybrid for iOS and Android.
{% endhint %}

### [SkiaSharp](https://github.com/mono/SkiaSharp)

SkiaSharp is a cross-platform 2D graphics API for .NET platforms based on Google's [Skia Graphics Library](https://skia.org/). It provides a comprehensive 2D API for rendering images for mobile, server, and desktop models.

Developed by the Mono team, this library offers classes built around Google's native [Skia](https://skia.org/) library. It requires different native assets for platforms and differs from `System.Drawing` basic operations like reading font size or measuring text. It cannot measure wrapping lines of text without extensions. Our tests showed font measurements that differed from those of Chromepite Chrome using [Skia](https://skia.org/); it appears to use many extensions and modifications.

### [Aspose.Drawing](https://products.aspose.com/drawing/net/)

The `Aspose.Drawing` package provides a completely managed re-implementation of `System.Drawing`. While it offers excellent GDI+ compatibility, it uses a different namespace and requires a commercial license.

### [Microsoft.Maui.Graphics](https://maui.graphics/)

Provides interfaces, classes, and supporting types for .NET MAUI Graphics, the abstracted, unified drawing APIs that work cross-platform.

A thin wrapper with limited functionality around [Microsoft.Graphics.Win2D](https://microsoft.github.io/Win2D/html/Introduction.htm) (a wrapper around UWP and WinUI platforms) and [Microsoft.Maui.Graphics.Skia](https://www.nuget.org/packages/Microsoft.Maui.Graphics.Skia) (a wrapper around [SkiaSharp](https://github.com/mono/SkiaSharp), which wraps [Skia](https://skia.org/)).

It provides minimal functionality to replace `System.Drawing.Font` or `Image` and gives different results on different platforms. It requires many dependencies and native bindings from various sources.
