Ejemplo n.º 1
0
		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);
		}