using System;
using System.Drawing;
namespace PaintDotNet
{
///
/// Encapsulates the arguments passed to a Render function.
/// This way we can do on-demand and once-only creation of Bitmap and Graphics
/// objects from a given Surface object.
///
///
/// Use of the Bitmap and Graphics objects is not thread safe because of how GDI+ works.
/// You must wrap use of these objects with a critical section, like so:
/// object lockObject = new object();
/// lock (lockObject)
/// {
/// Graphics g = ra.Graphics;
/// g.DrawRectangle(...);
/// // etc.
/// }
///
public sealed class RenderArgs
: IDisposable
{
private Surface surface;
private Bitmap bitmap;
private Graphics graphics;
private bool disposed = false;
///
/// Gets the Surface that has been associated with this instance of RenderArgs.
///
public Surface Surface
{
get
{
if (this.disposed)
{
throw new ObjectDisposedException("RenderArgs");
}
return this.surface;
}
}
///
/// Gets a Bitmap reference that aliases the Surface.
///
public Bitmap Bitmap
{
get
{
if (this.disposed)
{
throw new ObjectDisposedException("RenderArgs");
}
if (this.bitmap == null)
{
this.bitmap = surface.CreateAliasedBitmap();
}
return this.bitmap;
}
}
///
/// Retrieves a Graphics instance that can be used to draw on to the Surface.
///
///
/// Use of this object is not thread-safe. You must wrap retrieval and consumption of this
/// property with a critical section.
///
public Graphics Graphics
{
get
{
if (this.disposed)
{
throw new ObjectDisposedException("RenderArgs");
}
if (this.graphics == null)
{
this.graphics = Graphics.FromImage(Bitmap);
}
return this.graphics;
}
}
///
/// Gets the size of the associated Surface object.
///
///
/// This is a convenience method equivalent to using RenderArgs.Surface.Bounds.
///
public Rectangle Bounds
{
get
{
if (this.disposed)
{
throw new ObjectDisposedException("RenderArgs");
}
return this.Surface.Bounds;
}
}
///
/// Gets the size of the associated Surface object.
///
///
/// This is a convenient method equivalent to using RenderArgs.Surface.Size.
///
public Size Size
{
get
{
if (this.disposed)
{
throw new ObjectDisposedException("RenderArgs");
}
return this.Surface.Size;
}
}
///
/// Gets the width of the associated Surface object.
///
///
/// This is a convenience method equivalent to using RenderArgs.Surface.Width.
///
public int Width
{
get
{
if (this.disposed)
{
throw new ObjectDisposedException("RenderArgs");
}
return this.surface.Width;
}
}
///
/// Gets the height of the associated Surface object.
///
///
/// This is a convenience method equivalent to using RenderArgs.Surface.Height.
///
public int Height
{
get
{
if (this.disposed)
{
throw new ObjectDisposedException("RenderArgs");
}
return this.surface.Height;
}
}
///
/// Creates an instance of the RenderArgs class.
///
///
/// The Surface to associate with this instance. This instance of RenderArgs does not
/// take ownership of this Surface.
///
public RenderArgs(Surface surface)
{
this.surface = surface;
this.bitmap = null;
this.graphics = null;
}
~RenderArgs()
{
//Dispose(false);
}
///
/// Disposes of the contained Bitmap and Graphics instances, if necessary.
///
///
/// Note that since this class does not take ownership of the Surface, it
/// is not disposed.
///
public void Dispose()
{
//Dispose(true);
//GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
this.disposed = true;
if (disposing)
{
if (this.graphics != null)
{
this.graphics.Dispose();
this.graphics = null;
}
if (this.bitmap != null)
{
this.bitmap.Dispose();
this.bitmap = null;
}
}
}
}
}
}