diff --git a/views/SkiaSharp.Views.Desktop/SKControl.cs b/views/SkiaSharp.Views.Desktop/SKControl.cs new file mode 100644 index 00000000..9009b895 --- /dev/null +++ b/views/SkiaSharp.Views.Desktop/SKControl.cs @@ -0,0 +1,83 @@ +using System; +using System.ComponentModel; +using System.Drawing; +using System.Drawing.Imaging; +using System.Windows.Forms; + +namespace SkiaSharp.Views +{ + public class SKControl : Control + { + private readonly bool designMode; + + private Bitmap bitmap; + + public SKControl() + { + DoubleBuffered = true; + SetStyle(ControlStyles.ResizeRedraw, true); + + designMode = DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; + } + + public event EventHandler PaintSurface; + + protected override void OnPaint(PaintEventArgs e) + { + if (designMode) + return; + + base.OnPaint(e); + + // get the bitmap + CreateBitmap(); + var data = bitmap.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); + + // create the surface + var info = new SKImageInfo(Width, Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); + using (var surface = SKSurface.Create(info, data.Scan0, data.Stride)) + { + // start drawing + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + + surface.Canvas.Flush(); + } + + // write the bitmap to the graphics + bitmap.UnlockBits(data); + e.Graphics.DrawImage(bitmap, 0, 0); + } + + protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e) + { + // invoke the event + PaintSurface?.Invoke(this, e); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + FreeBitmap(); + } + + private void CreateBitmap() + { + if (bitmap == null || bitmap.Width != Width || bitmap.Height != Height) + { + FreeBitmap(); + + bitmap = new Bitmap(Width, Height, PixelFormat.Format32bppPArgb); + } + } + + private void FreeBitmap() + { + if (bitmap != null) + { + bitmap.Dispose(); + bitmap = null; + } + } + } +} diff --git a/views/SkiaSharp.Views.Desktop/SKGLControl.cs b/views/SkiaSharp.Views.Desktop/SKGLControl.cs new file mode 100644 index 00000000..43922ed0 --- /dev/null +++ b/views/SkiaSharp.Views.Desktop/SKGLControl.cs @@ -0,0 +1,75 @@ +using System; +using System.ComponentModel; +using System.Windows.Forms; +using OpenTK; + +namespace SkiaSharp.Views +{ + public class SKGLControl : GLControl + { + private readonly bool designMode; + + private GRContext grContext; + private GRBackendRenderTargetDesc renderTarget; + + public SKGLControl() + { + designMode = DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; + + ResizeRedraw = true; + } + + public event EventHandler PaintSurface; + + protected override void OnPaint(PaintEventArgs e) + { + if (designMode) + { + e.Graphics.Clear(BackColor); + return; + } + + base.OnPaint(e); + + // create the contexts if not done already + if (grContext == null) + { + var glInterface = GRGlInterface.CreateNativeInterface(); + grContext = GRContext.Create(GRBackend.OpenGL, glInterface); + + // get initial details + renderTarget = SKGLDrawable.CreateRenderTarget(); + } + + // update to the latest dimensions + renderTarget.Width = Width; + renderTarget.Height = Height; + + // create the surface + using (var surface = SKSurface.Create(grContext, renderTarget)) + { + // start drawing + OnPaintSurface(new SKPaintGLSurfaceEventArgs(surface, renderTarget)); + + surface.Canvas.Flush(); + } + + // update the control + SwapBuffers(); + } + + protected virtual void OnPaintSurface(SKPaintGLSurfaceEventArgs e) + { + // invoke the event + PaintSurface?.Invoke(this, e); + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + + // clean up + grContext.Dispose(); + } + } +} diff --git a/views/SkiaSharp.Views.Desktop/SKPaintGLSurfaceEventArgs.cs b/views/SkiaSharp.Views.Desktop/SKPaintGLSurfaceEventArgs.cs new file mode 100644 index 00000000..905a7ea7 --- /dev/null +++ b/views/SkiaSharp.Views.Desktop/SKPaintGLSurfaceEventArgs.cs @@ -0,0 +1,17 @@ +using System; + +namespace SkiaSharp.Views +{ + public class SKPaintGLSurfaceEventArgs : EventArgs + { + public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTargetDesc renderTarget) + { + Surface = surface; + RenderTarget = renderTarget; + } + + public SKSurface Surface { get; private set; } + + public GRBackendRenderTargetDesc RenderTarget { get; private set; } + } +} diff --git a/views/SkiaSharp.Views.Desktop/SKPaintSurfaceEventArgs.cs b/views/SkiaSharp.Views.Desktop/SKPaintSurfaceEventArgs.cs new file mode 100644 index 00000000..4a43c8ca --- /dev/null +++ b/views/SkiaSharp.Views.Desktop/SKPaintSurfaceEventArgs.cs @@ -0,0 +1,17 @@ +using System; + +namespace SkiaSharp.Views +{ + public class SKPaintSurfaceEventArgs : EventArgs + { + public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info) + { + Surface = surface; + Info = info; + } + + public SKSurface Surface { get; private set; } + + public SKImageInfo Info { get; private set; } + } +} diff --git a/views/SkiaSharp.Views.Desktop/SkiaSharp.Views.Desktop.csproj b/views/SkiaSharp.Views.Desktop/SkiaSharp.Views.Desktop.csproj index 1b2bb3fa..c656e47f 100644 --- a/views/SkiaSharp.Views.Desktop/SkiaSharp.Views.Desktop.csproj +++ b/views/SkiaSharp.Views.Desktop/SkiaSharp.Views.Desktop.csproj @@ -20,7 +20,7 @@ full false bin\Debug\ - DEBUG;TRACE + TRACE;DEBUG;__DESKTOP__ prompt 4 @@ -28,30 +28,44 @@ pdbonly true bin\Release\ - TRACE + TRACE;__DESKTOP__ prompt 4 + + ..\packages\OpenTK.1.1.2349.61993\lib\NET40\OpenTK.dll + True + + + ..\packages\OpenTK.GLControl.1.1.2349.61993\lib\NET40\OpenTK.GLControl.dll + True + ..\packages\SkiaSharp.1.54.0\lib\net45\SkiaSharp.dll True - - + + - - - + + Component + + + UserControl + + + + diff --git a/views/SkiaSharp.Views.Desktop/packages.config b/views/SkiaSharp.Views.Desktop/packages.config index 7affb245..d7d424f1 100644 --- a/views/SkiaSharp.Views.Desktop/packages.config +++ b/views/SkiaSharp.Views.Desktop/packages.config @@ -1,4 +1,6 @@  + + \ No newline at end of file