/// <summary>
	/// <para>Blit a drawable's entire contents to this graphics context.</para>
	/// </summary>
	///
	/// <param name="x">
	/// <para>The X co-ordinate of the top-left point of
	/// the destination bounding rectangle.</para>
	/// </param>
	///
	/// <param name="y">
	/// <para>The Y co-ordinate of the top-left point of
	/// the destination bounding rectangle.</para>
	/// </param>
	///
	/// <param name="drawable">
	/// <para>The drawable to copy from.</para>
	/// </param>
	///
	/// <exception cref="T:System.ArgumentNullException">
	/// <para>Raised if <paramref name="drawable"/> is <see langword="null"/>.
	/// </para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XException">
	/// <para>One of the co-ordinate or size values is out of range.</para>
	/// </exception>
	public void BitBlt(int x, int y, Drawable drawable)
			{
				// Validate the drawable parameter.
				if(drawable == null)
				{
					throw new ArgumentNullException("drawable");
				}

				// Perform the blit operation.
				BitBlt(x, y, drawable, 0, 0, drawable.Width, drawable.Height);
			}
	/// <summary>
	/// <para>Constructs a new <see cref="T:Xsharp.Graphics"/> object and
	/// attaches it to a <see cref="T:Xsharp.Drawable"/> instance.</para>
	/// </summary>
	///
	/// <param name="drawable">
	/// <para>The drawable to attach this graphics context to.  If the
	/// drawable is a widget, the foreground and background colors of the
	/// graphics object will be initially set to the widget's standard
	/// foreground and background colors.</para>
	/// </param>
	///
	/// <exception cref="T:System.ArgumentNullException">
	/// <para>Raised if <paramref name="drawable"/> is <see langword="null"/>.
	/// </para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XInvalidOperationException">
	/// <para>Raised if <paramref name="drawable"/> does not support
	/// output, is disposed, or is the root window.</para>
	/// </exception>
	public Graphics(Drawable drawable)
			{
				if(drawable == null)
				{
					throw new ArgumentNullException("drawable");
				}
				else if(drawable.Kind == DrawableKind.InputOnlyWidget)
				{
					throw new XInvalidOperationException
						(S._("X_GraphicsIsOutputOnly"));
				}
				else if(drawable is RootWindow)
				{
					throw new XInvalidOperationException
						(S._("X_NonRootOperation"));
				}
				dpy = drawable.dpy;
				this.drawable = drawable;
				XGCValues gcValues = new XGCValues();
				InputOutputWidget widget = (drawable as InputOutputWidget);
				DoubleBuffer buffer = (drawable as DoubleBuffer);
				Bitmap bitmap = (drawable as Bitmap);
				if(widget != null)
				{
					foreground = widget.Foreground;
					background = widget.Background;
				}
				else if(buffer != null)
				{
					foreground = buffer.Widget.Foreground;
					background = buffer.Widget.Background;
				}
				else if(bitmap != null)
				{
					foreground = new Color(0x00, 0x00, 0x00);
					background = new Color(0xFF, 0xFF, 0xFF);
				}
				else
				{
					foreground = new Color (StandardColor.Foreground);
					background = new Color (StandardColor.Background);
				}
				gcValues.foreground = drawable.ToPixel(foreground);
				gcValues.background = drawable.ToPixel(background);
				if(drawable is DoubleBuffer)
				{
					((DoubleBuffer)drawable).Start(this);
				}
				try
				{
					IntPtr display = dpy.Lock();
					drawableHandle = drawable.GetGCHandle();
					gc = drawable.screen.GetGC(bitmap != null);
					if(gc == IntPtr.Zero)
					{
						// Create a new GC because the cache is empty.
						gc = Xlib.XCreateGC(display, drawableHandle,
											(uint)(GCValueMask.GCForeground |
												   GCValueMask.GCBackground),
											ref gcValues);
						if(gc == IntPtr.Zero)
						{
							Display.OutOfMemory();
						}
					}
					else
					{
						// Reset the cached GC back to the default settings.
						// Xlib will take care of stripping the list down
						// to just the changes that need to be applied.
						gcValues.function = Xsharp.GCFunction.GXcopy;
						gcValues.plane_mask = ~((XPixel)0);
						gcValues.line_width = 0;
						gcValues.line_style = Xsharp.LineStyle.LineSolid;
						gcValues.cap_style = Xsharp.CapStyle.CapButt;
						gcValues.join_style = Xsharp.JoinStyle.JoinMiter;
						gcValues.fill_style = Xsharp.FillStyle.FillSolid;
						gcValues.fill_rule = Xsharp.FillRule.EvenOddRule;
						gcValues.arc_mode = Xsharp.ArcMode.ArcPieSlice;
						gcValues.ts_x_origin = 0;
						gcValues.ts_y_origin = 0;
						gcValues.subwindow_mode =
							Xsharp.SubwindowMode.ClipByChildren;
						gcValues.graphics_exposures = true;
						gcValues.clip_x_origin = 0;
						gcValues.clip_y_origin = 0;
						gcValues.clip_mask = XPixmap.Zero;
						gcValues.dash_offset = 0;
						gcValues.dashes = (sbyte)4;
						Xlib.XChangeGC(display, gc,
									   (uint)(GCValueMask.GCFunction |
											  GCValueMask.GCPlaneMask |
											  GCValueMask.GCForeground |
											  GCValueMask.GCBackground |
											  GCValueMask.GCLineWidth |
											  GCValueMask.GCLineStyle |
											  GCValueMask.GCCapStyle |
											  GCValueMask.GCJoinStyle |
											  GCValueMask.GCFillStyle |
											  GCValueMask.GCFillRule |
											  GCValueMask.GCTileStipXOrigin |
											  GCValueMask.GCTileStipYOrigin |
											  GCValueMask.GCSubwindowMode |
											  GCValueMask.GCGraphicsExposures |
											  GCValueMask.GCClipXOrigin |
											  GCValueMask.GCClipYOrigin |
											  GCValueMask.GCClipMask |
											  GCValueMask.GCDashOffset |
											  GCValueMask.GCDashList |
											  GCValueMask.GCArcMode),
									   ref gcValues);
					}

					int sn = drawable.screen.ScreenNumber;
					double px, mm;

					px = (double)Xlib.XDisplayWidth(display, sn);
					mm = (double)Xlib.XDisplayWidthMM(display, sn);
					dpiX = (float)((px * 25.4) / mm);

					px = (double)Xlib.XDisplayHeight(display, sn);
					mm = (double)Xlib.XDisplayHeightMM(display, sn);
					dpiY = (float)((px * 25.4) / mm);
				}
				finally
				{
					dpy.Unlock();
				}
				if(drawable is DoubleBuffer)
				{
					((DoubleBuffer)drawable).ClearAtStart(this);
				}

				isDisposed = false;
			}
	/// <summary>
	/// <para>Blit a drawable sub-part to this graphics context.</para>
	/// </summary>
	///
	/// <param name="x">
	/// <para>The X co-ordinate of the top-left point of
	/// the destination bounding rectangle.</para>
	/// </param>
	///
	/// <param name="y">
	/// <para>The Y co-ordinate of the top-left point of
	/// the destination bounding rectangle.</para>
	/// </param>
	///
	/// <param name="drawable">
	/// <para>The drawable to copy from.</para>
	/// </param>
	///
	/// <param name="srcX">
	/// <para>The X co-ordinate of the top-left point of
	/// the drawable sub-part to be drawn.</para>
	/// </param>
	///
	/// <param name="srcY">
	/// <para>The Y co-ordinate of the top-left point of
	/// the drawable sub-part to be drawn.</para>
	/// </param>
	///
	/// <param name="srcWidth">
	/// <para>The width of the drawable sub-part to be drawn.</para>
	/// </param>
	///
	/// <param name="srcHeight">
	/// <para>The height of the drawable sub-part to be drawn.</para>
	/// </param>
	///
	/// <exception cref="T:System.ArgumentNullException">
	/// <para>Raised if <paramref name="drawable"/> is <see langword="null"/>.
	/// </para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XException">
	/// <para>One of the co-ordinate or size values is out of range.</para>
	/// </exception>
	public void BitBlt(int x, int y, Drawable drawable,
					   int srcX, int srcY, int srcWidth, int srcHeight)
			{
				// Validate the drawable parameter.
				if(drawable == null)
				{
					throw new ArgumentNullException("drawable");
				}

				// Bail out if the source co-ordinates are out of range.
				int width, height;
				width = drawable.Width;
				height = drawable.Height;
				if(srcX < 0 || srcX >= width ||
				   srcY < 0 || srcY >= height ||
				   srcWidth <= 0 || srcHeight <= 0 ||
				   srcWidth > width || srcHeight > height ||
				   srcX > (width - srcWidth) ||
				   srcY > (height - srcHeight))
				{
					throw new XException(S._("X_RectCoordRange"));
				}

				// Blit the contents of the drawable.
				try
				{
					IntPtr display = Lock();
					Xlib.XCopyArea(display, drawable.GetGCHandle(),
								   drawableHandle, gc,
								   srcX, srcY,
								   (uint)srcWidth, (uint)srcHeight,
								   x, y);
				}
				finally
				{
					dpy.Unlock();
				}
			}