You've already forked linux-packaging-mono
Imported Upstream version 6.12.0.122
Former-commit-id: d3ff4118f95cc6907059c6001e5157df8832a115
This commit is contained in:
parent
bb7877ea56
commit
a0d6f2d6ec
@@ -41,6 +41,93 @@ namespace System.Drawing.Imaging {
|
||||
[Editor ("System.Drawing.Design.MetafileEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
|
||||
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
|
||||
//
|
||||
// ligbgdiplus has a bug where disposing of the metafile instance first will
|
||||
// trigger a use of freed memory when the graphics instance is disposed, which
|
||||
// could lead to crashes when the native memory is reused.
|
||||
//
|
||||
// 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)
|
||||
{
|
||||
Status status = GDIPlus.GdipDisposeImage(nativeImage);
|
||||
GDIPlus.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)
|
||||
@@ -324,6 +411,21 @@ namespace System.Drawing.Imaging {
|
||||
GDIPlus.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(nativeObject);
|
||||
_metafileHolder = null;
|
||||
nativeObject = IntPtr.Zero;
|
||||
}
|
||||
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
// methods
|
||||
|
||||
public IntPtr GetHenhmetafile ()
|
||||
|
Reference in New Issue
Block a user