void Paint (WidgetType widgetType, Rectangle bounds, IDeviceContext dc, TransparencyType transparencyType, Color background, DeviceContextType deviceContextType, Rectangle clippingArea, Painter painter, Rectangle excludedArea) { Rectangle painted_area = Rectangle.Intersect (bounds, clippingArea); if (painted_area.Width == 0 || painted_area.Height == 0) return; painted_area.Offset (-bounds.X, -bounds.Y); excludedArea.Offset (-bounds.X, -bounds.Y); GdkDrawablePointer drawable = gdk_pixmap_new (IntPtr.Zero, bounds.Width, bounds.Height, 24); painter.AttachStyle (widgetType, drawable, this); GdkPixbufPointer pixbuf; IntPtr pixel_data; int rowstride; GdkGCPointer gc = gdk_gc_new (drawable); GdkColor color = new GdkColor (background); gdk_gc_set_rgb_fg_color (gc, ref color); Paint (drawable, gc, bounds, widgetType, out pixbuf, out pixel_data, out rowstride, painted_area, painter, excludedArea); GdkPixbufPointer white_pixbuf = IntPtr.Zero; IntPtr white_pixel_data = IntPtr.Zero; int white_rowstride = 0; GdkColor white_color = new GdkColor(); if (transparencyType == TransparencyType.Alpha) { white_color.red = guint16.MaxValue; white_color.green = guint16.MaxValue; white_color.blue = guint16.MaxValue; gdk_gc_set_rgb_fg_color (gc, ref white_color); Paint (drawable, gc, bounds, widgetType, out white_pixbuf, out white_pixel_data, out white_rowstride, painted_area, painter, excludedArea); } g_object_unref (gc); unsafe { byte* row = (byte*)pixel_data; byte* pixel; byte* white_row = (byte*)white_pixel_data; byte* white_pixel; for (int row_index = 0; row_index < painted_area.Height; row_index++) { pixel = row; white_pixel = white_row; for (int pixel_index = 0; pixel_index < painted_area.Width; pixel_index++) { const int GdkRedOffset = 0; const int GdkGreenOffset = 1; const int GdkBlueOffset = 2; const int BitmapAlphaOffset = 3; const int BitmapRedOffset = 2; const int BitmapBlueOffset = 0; switch (transparencyType) { case TransparencyType.Alpha: pixel [BitmapAlphaOffset] = (byte)(pixel [GdkRedOffset] - white_pixel [GdkRedOffset] + byte.MaxValue); break; case TransparencyType.Color: if ( pixel [GdkRedOffset] == background.R && pixel [GdkGreenOffset] == background.G && pixel [GdkBlueOffset] == background.B) { const int AlphaFullyTransparent = 0; pixel [BitmapAlphaOffset] = AlphaFullyTransparent; } break; } byte temporary = pixel [GdkRedOffset]; pixel [BitmapBlueOffset] = pixel [GdkBlueOffset]; pixel [BitmapRedOffset] = temporary; const int PixelSize = 4; pixel += PixelSize; white_pixel += PixelSize; } row += rowstride; white_row += white_rowstride; } } if (transparencyType == TransparencyType.Alpha) g_object_unref (white_pixbuf); g_object_unref (drawable); Bitmap bitmap = new Bitmap (painted_area.Width, painted_area.Height, rowstride, PixelFormat.Format32bppPArgb, pixel_data); Graphics g; bool graphics_is_from_hdc = false; switch (deviceContextType) { case DeviceContextType.Graphics: g = (Graphics)dc; break; case DeviceContextType.Native: g = Graphics.FromHdc (dc.GetHdc ()); break; default: g = dc as Graphics; if (g == null) { graphics_is_from_hdc = true; g = Graphics.FromHdc (dc.GetHdc ()); } else graphics_is_from_hdc = false; break; } painted_area.Offset (bounds.X, bounds.Y); g.DrawImage (bitmap, painted_area.Location); switch (deviceContextType) { case DeviceContextType.Graphics: break; case DeviceContextType.Native: g.Dispose (); dc.ReleaseHdc (); break; default: if (graphics_is_from_hdc) { g.Dispose (); dc.ReleaseHdc (); } break; } bitmap.Dispose (); g_object_unref (pixbuf); }