/// <summary> /// Handles the paint. /// </summary> internal unsafe void HandlePaintEvent(IntPtr sourceBuffer, Rect rect, int dx, int dy, Rect scrollRect) { System.Drawing.Imaging.BitmapData sourceData; var clientRect = new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height); byte[] TemporaryBuffer = null; if (dx != 0 || dy != 0) { var sourceRect = new Rectangle(scrollRect.Left, scrollRect.Top, scrollRect.Width, scrollRect.Height); var destRect = sourceRect; destRect.X += dx; destRect.Y += dy; // We want to only draw the overlapping portion of the scrolled and unscrolled // rectangles, since the scrolled rectangle is probably partially offscreen var overlap = Rectangle.Intersect(destRect, sourceRect); // We need to handle scrolling to the left if (destRect.Left < 0) { sourceRect.X -= destRect.Left; destRect.X = 0; } // And upward if (destRect.Top < 0) { sourceRect.Y -= destRect.Top; destRect.Y = 0; } destRect.Width = sourceRect.Width = overlap.Width; destRect.Height = sourceRect.Height = overlap.Height; // If the clipping calculations resulted in a rect that contains zero pixels, // don't bother trying to do the blit. if ((sourceRect.Width > 0) && (sourceRect.Height > 0)) { sourceData = WindowBitmap.LockBits( sourceRect, System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb ); int totalSize = sourceData.Stride * sourceData.Height; if ((TemporaryBuffer == null) || (totalSize > TemporaryBuffer.Length)) TemporaryBuffer = new byte[totalSize]; Marshal.Copy(sourceData.Scan0, TemporaryBuffer, 0, totalSize); WindowBitmap.UnlockBits(sourceData); fixed (byte* ptr = &(TemporaryBuffer[0])) { sourceData.Scan0 = new IntPtr(ptr); var destData = WindowBitmap.LockBits( destRect, System.Drawing.Imaging.ImageLockMode.WriteOnly | System.Drawing.Imaging.ImageLockMode.UserInputBuffer, System.Drawing.Imaging.PixelFormat.Format32bppRgb, sourceData ); WindowBitmap.UnlockBits(destData); } InvalidateBerkelium(); } } // If we get a paint event after a resize, the rect can be larger than the buffer. if ((clientRect.Right > WindowBitmap.Width) || (clientRect.Bottom > WindowBitmap.Height)) return; sourceData = new System.Drawing.Imaging.BitmapData(); sourceData.Width = clientRect.Width; sourceData.Height = clientRect.Height; sourceData.PixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppRgb; sourceData.Stride = clientRect.Width * 4; sourceData.Scan0 = sourceBuffer; // Sometimes this can fail if we process an old paint event after we // request a resize, so we just eat the exception in that case. // Yes, this is terrible. //Bitmap windowBitmap = new Bitmap(clientRect.Width, clientRect.Height); try { // This oddball form of LockBits performs a write to the bitmap's // internal buffer by copying from another BitmapData you pass in. // In this case we're passing in the source buffer. var bd = WindowBitmap.LockBits( clientRect, System.Drawing.Imaging.ImageLockMode.WriteOnly | System.Drawing.Imaging.ImageLockMode.UserInputBuffer, System.Drawing.Imaging.PixelFormat.Format32bppRgb, sourceData ); // For some reason we still have to unlock the bits afterward. WindowBitmap.UnlockBits(bd); InvalidateBerkelium(); } catch { } }
private void WebKit_Paint(Berkelium.Managed.Window window, IntPtr sourceBuffer, Rect rect, int dx, int dy, Rect scrollRect) { HandlePaintEvent(sourceBuffer, rect, dx, dy, scrollRect); }