Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/Microsoft.Private.PackageBaseline/packageIndex.json
Original file line number Diff line number Diff line change
Expand Up @@ -1709,7 +1709,8 @@
},
"AssemblyVersionInPackageVersion": {
"4.0.0.0": "4.5.0",
"4.0.0.1": "4.5.1"
"4.0.0.1": "4.5.1",
"4.0.0.2": "4.5.2"
}
},
"System.Drawing.Design": {
Expand Down
4 changes: 2 additions & 2 deletions src/System.Drawing.Common/dir.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\dir.props" />
<PropertyGroup>
<AssemblyVersion>4.0.0.1</AssemblyVersion>
<AssemblyVersion>4.0.0.2</AssemblyVersion>
<AssemblyKey>Open</AssemblyKey>
<PackageVersion>4.5.1</PackageVersion>
<PackageVersion>4.5.2</PackageVersion>
</PropertyGroup>
</Project>
19 changes: 18 additions & 1 deletion src/System.Drawing.Common/src/System/Drawing/Graphics.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public sealed partial class Graphics : MarshalByRefObject, IDisposable
private static float defDpiX = 0;
private static float defDpiY = 0;
private IntPtr deviceContextHdc;
private Metafile.MetafileHolder _metafileHolder;

public delegate bool EnumerateMetafileProc(EmfPlusRecordType recordType,
int flags,
Expand All @@ -65,6 +66,14 @@ internal Graphics(IntPtr nativeGraphics)
nativeObject = nativeGraphics;
}

internal Graphics(IntPtr nativeGraphics, Image image) : this(nativeGraphics)
{
if (image is Metafile mf)
{
_metafileHolder = mf.AddMetafileHolder();
}
}

~Graphics()
{
Dispose();
Expand Down Expand Up @@ -287,6 +296,14 @@ public void Dispose()
status = SafeNativeMethods.Gdip.GdipDeleteGraphics(nativeObject);
nativeObject = IntPtr.Zero;
SafeNativeMethods.Gdip.CheckStatus(status);

if (_metafileHolder != null)
{
var mh = _metafileHolder;
_metafileHolder = null;
mh.GraphicsDisposed();
}

disposed = true;
}

Expand Down Expand Up @@ -1735,7 +1752,7 @@ public static Graphics FromImage(Image image)

int status = SafeNativeMethods.Gdip.GdipGetImageGraphicsContext(image.nativeImage, out graphics);
SafeNativeMethods.Gdip.CheckStatus(status);
Graphics result = new Graphics(graphics);
Graphics result = new Graphics(graphics, image);

Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
SafeNativeMethods.Gdip.GdipSetVisibleClip_linux(result.NativeObject, ref rect);
Expand Down
100 changes: 100 additions & 0 deletions src/System.Drawing.Common/src/System/Drawing/Imaging/Metafile.Unix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
using System.IO;
using System.Reflection;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace System.Drawing.Imaging
Expand All @@ -47,6 +48,90 @@ namespace System.Drawing.Imaging
public sealed class Metafile : Image
{

// Non-null if a graphics instance was created using
// Graphics.FromImage(this) The metadata holder is responsible for
// freeing the nativeImage if the Metadata instance is disposed before
// the Graphics instance.
private MetafileHolder _metafileHolder;

// A class responsible for disposing of the native Metafile instance
// if it needs to outlive the managed Metafile instance.
//
// The following are both legal with win32 GDI+:
// Metafile mf = ...; // get a metafile instance
// Graphics g = Graphics.FromImage(mf); // get a graphics instance
// g.Dispose(); mf.Dispose(); // dispose of the graphics instance first
// OR
// mf.Dispose(); g.Dispose(); // dispose of the metafile instance first
//
//
// The metafile holder is designed to take ownership of the native metafile image
// when the managed Metafile instance is disposed while a Graphics instance is still
// not disposed (ie the second code pattern above) and to keep the native image alive until the graphics
// instance is disposed.
//
// Note that the following throws, so we only ever need to keep track of one Graphics
// instance at a time:
// Metafile mf = ...; // get a metafile instance
// Graphics g = Graphics.FromImage(mf);
// Graphics g2 = Graphics.FromImage(mf); // throws OutOfMemoryException on GDI+ on Win32
internal sealed class MetafileHolder : IDisposable
{
private bool _disposed;
private IntPtr _nativeImage;


internal bool Disposed { get => _disposed; }
internal MetafileHolder()
{
_disposed = false;
_nativeImage = IntPtr.Zero;
}

~MetafileHolder() => Dispose(false);

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

internal void Dispose(bool disposing)
{
if (!_disposed)
{
IntPtr nativeImage = _nativeImage;
_nativeImage = IntPtr.Zero;
_disposed = true;
if (nativeImage != IntPtr.Zero)
{
int status = SafeNativeMethods.Gdip.GdipDisposeImage(nativeImage);
SafeNativeMethods.Gdip.CheckStatus(status);
}
}
}

internal void MetafileDisposed(IntPtr nativeImage)
{
_nativeImage = nativeImage;
}

internal void GraphicsDisposed()
{
Dispose();
}
}

internal MetafileHolder AddMetafileHolder()
{
// If _metafileHolder is not null and hasn't been disposed yet, there's already a graphics instance associated with
// this metafile, the native code will return an error status.
if (_metafileHolder != null && !_metafileHolder.Disposed)
return null;
_metafileHolder = new MetafileHolder();
return _metafileHolder;
}

// constructors

internal Metafile(IntPtr ptr) => SetNativeImage(ptr);
Expand Down Expand Up @@ -311,6 +396,21 @@ public Metafile(string fileName, IntPtr referenceHdc, RectangleF frameRect, Meta
SafeNativeMethods.Gdip.CheckStatus(status);
}

protected override void Dispose(bool disposing)
{
if (_metafileHolder != null && !_metafileHolder.Disposed)
{
// There's a graphics instance created from this Metafile,
// transfer responsibility for disposing the nativeImage to the
// MetafileHolder
_metafileHolder.MetafileDisposed(nativeImage);
_metafileHolder = null;
nativeImage = IntPtr.Zero;
}

base.Dispose(disposing);
}

// methods

public IntPtr GetHenhmetafile()
Expand Down
3 changes: 3 additions & 0 deletions src/packages.builds
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
<AdditionalProperties>$(AdditionalProperties)</AdditionalProperties>
</Project>
<!-- add specific builds / pkgproj's here to include in servicing builds -->
<Project Include="$(MSBuildThisFileDirectory)System.Drawing.Common\pkg\System.Drawing.Common.pkgproj">
<AdditionalProperties>$(AdditionalProperties)</AdditionalProperties>
</Project>
</ItemGroup>

<!-- Need the PackageIndexFile file property from baseline.props -->
Expand Down