<commit_before>﻿using System;
using System.ComponentModel;
using SkiaSharp.Views.Desktop;

namespace SkiaSharp.Views.Gtk
{
	[ToolboxItem(true)]
	public class SKWidget : global::Gtk.DrawingArea
	{
		private Gdk.Pixbuf pix;

		public SKWidget()
		{
			DoubleBuffered = false;
		}

		public SKSize CanvasSize => pix == null ? SKSize.Empty : new SKSize(pix.Width, pix.Height);

		[Category("Appearance")]
		public event EventHandler<SKPaintSurfaceEventArgs> PaintSurface;

		protected override bool OnExposeEvent(Gdk.EventExpose evnt)
		{
			var result = base.OnExposeEvent(evnt);

			var window = evnt.Window;
			var area = evnt.Area;

			// get the pixbuf
			CreatePixbuf();
			var info = new SKImageInfo(pix.Width, pix.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul);

			// create the surface
			using (var surface = SKSurface.Create(info, pix.Pixels, info.RowBytes))
			{
				// start drawing
				OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info));

				surface.Canvas.Flush();

				// swap R and B
				if (info.ColorType == SKColorType.Bgra8888)
				{
					using (var pixmap = surface.PeekPixels())
					{
						SKSwizzle.SwapRedBlue(pixmap.GetPixels(), info.Width * info.Height);
					}
				}
			}

			// write the pixbuf to the graphics
			window.Clear();
			window.DrawPixbuf(null, pix, 0, 0, 0, 0, -1, -1, Gdk.RgbDither.None, 0, 0);

			return result;
		}

		protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e)
		{
			// invoke the event
			PaintSurface?.Invoke(this, e);
		}

		~SKWidget()
		{
			Dispose(false);
		}

		public override void Destroy()
		{
			GC.SuppressFinalize(this);
			Dispose(true);

			base.Destroy();
		}

		public override void Dispose()
		{
			GC.SuppressFinalize(this);
			Dispose(true);

			base.Dispose();
		}

		public virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				FreePixbuf();
			}
		}

		private void CreatePixbuf()
		{
			var alloc = Allocation;
			var w = alloc.Width;
			var h = alloc.Height;
			if (pix == null || pix.Width != w || pix.Height != h)
			{
				FreePixbuf();

				pix = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, true, 8, w, h);
			}
		}

		private void FreePixbuf()
		{
			if (pix != null)
			{
				pix.Dispose();
				pix = null;
			}
		}
	}
}<commit_msg>Improve rendering speed for Gtk#'s SKWidget<commit_after>﻿using System;
using System.ComponentModel;
using SkiaSharp.Views.Desktop;

namespace SkiaSharp.Views.Gtk
{
	[ToolboxItem(true)]
	public class SKWidget : global::Gtk.DrawingArea
	{
		private Gdk.Pixbuf pix;
		private SKImageInfo imgInfo;
		private SKSurface surface;

		public SKWidget()
		{
		}

		public SKSize CanvasSize => pix == null ? SKSize.Empty : new SKSize(pix.Width, pix.Height);

		[Category("Appearance")]
		public event EventHandler<SKPaintSurfaceEventArgs> PaintSurface;

		protected override bool OnExposeEvent(Gdk.EventExpose evnt)
		{
			var window = evnt.Window;
			var area = evnt.Area;

			// get the pixbuf
			CreateDrawingObjects();

				// start drawing
			OnPaintSurface(new SKPaintSurfaceEventArgs(surface, imgInfo));

			surface.Canvas.Flush();

			// swap R and B
			if (imgInfo.ColorType == SKColorType.Bgra8888)
			{
				using (var pixmap = surface.PeekPixels())
				{
					SKSwizzle.SwapRedBlue(pixmap.GetPixels(), imgInfo.Width * imgInfo.Height);
				}
			}

			// write the pixbuf to the graphics
			window.Clear();
			window.DrawPixbuf(null, pix, 0, 0, 0, 0, -1, -1, Gdk.RgbDither.None, 0, 0);

			return true;
		}

		protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e)
		{
			// invoke the event
			PaintSurface?.Invoke(this, e);
		}

		~SKWidget()
		{
			Dispose(false);
		}

		public override void Destroy()
		{
			GC.SuppressFinalize(this);
			Dispose(true);

			base.Destroy();
		}

		public override void Dispose()
		{
			GC.SuppressFinalize(this);
			Dispose(true);

			base.Dispose();
		}

		public virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				FreeDrawingObjects();
			}
		}

		private void CreateDrawingObjects()
		{
			var alloc = Allocation;
			var w = alloc.Width;
			var h = alloc.Height;
			if (pix == null || pix.Width != w || pix.Height != h)
			{
				FreeDrawingObjects();

				pix = new Gdk.Pixbuf(Gdk.Colorspace.Rgb, true, 8, w, h);

				// (Re)create the Skia Drawing objects
				imgInfo = new SKImageInfo(pix.Width, pix.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
				surface = SKSurface.Create(imgInfo, pix.Pixels, imgInfo.RowBytes);
			}
		}

		private void FreeDrawingObjects()
		{
			if (pix != null)
			{
				pix.Dispose();
				pix = null;

				// Skia objects should only exist if the Pixbuf is set as well
				surface?.Dispose();
				surface = null;
			}
		}
	}
}
{'fraction_non_alphanumeric': 0.12300149221914304, 'fraction_numerical': 0.005542528245576636, 'mean_word_length': 3.0623376623376624, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6983193', 'n_tokens_mistral': 2005, 'n_tokens_neox': 1601, 'n_words': 376}