{"id":29646,"date":"2017-02-06T10:00:14","date_gmt":"2017-02-06T18:00:14","guid":{"rendered":"https:\/\/blog.xamarin.com\/?p=29646"},"modified":"2019-04-04T09:01:35","modified_gmt":"2019-04-04T16:01:35","slug":"drawing-with-skiasharp","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/drawing-with-skiasharp\/","title":{"rendered":"Cross-Platform Drawing with SkiaSharp"},"content":{"rendered":"<p>\t\t\t\tThere are millions of mobile apps created every day that all do different things. However, they still have one thing in common: they will display some form of information to the user. Sometimes this will be a graph or a chart, sometimes it will be an interactive interface control. Sometimes it will just be plain text and sometimes it might be a fully interactive mobile game.<\/p>\n<p>Each mobile platform has its own powerful graphics API, ranging from iOS&#8217; CoreGraphics and Android&#8217;s graphics, to Windows&#8217; media and imaging. There are also a variety of hardware accelerated graphics APIs with OpenGL, OpenGL ES, and DirectX. Although the various toolkits are powerful, they differ greatly in many important ways, making sharing logic and code almost impossible.<\/p>\n<p>Even with advanced cross-platform libraries such as Xamarin.Forms, graphics processing and rendering is quite limited. This is where we introduce SkiaSharp.<\/p>\n<h2>Introducing SkiaSharp<\/h2>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/skia_512x512.png\" alt=\"SkiaSharp\" width=\"128\" height=\"128\" class=\"alignright\" style=\"margin-top:0\" \/>SkiaSharp is a fully cross-platform, rich 2D graphics drawing API powered by <a href=\"https:\/\/skia.org\/\" target=\"_blank\">Google&#8217;s Skia library<\/a>, the same library that drives Google Chrome, Mozilla Firefox, and Android&#8217;s graphics stack. Not only is SkiaSharp powerful, is&#8217;s also very simple to use\u2014all you need to do is install the <a href=\"https:\/\/www.nuget.org\/packages\/SkiaSharp\" target=\"_blank\">SkiaSharp NuGet<\/a>.<\/p>\n<p>SkiaSharp can be used to render images on many platforms, including iOS, macOS, tvOS, Android, and Universal Windows Platform (UWP). Not only does SkiaSharp support native mobile apps, it also supports .NET Standard 1.3 and .NET Core on macOS and Windows, as well as Classic Windows Desktop and WPF applications.<\/p>\n<h3>Installing SkiaSharp<\/h3>\n<p>Today, we&#8217;re going to look at creating a simple mobile app that demonstrates a few of the many SkiaSharp features. The source code for this app can be found on GitHub: <a href=\"https:\/\/github.com\/mattleibow\/SkiaSharpDemo\" target=\"_blank\">mattleibow\/SkiaSharpDemo<\/a>. <\/p>\n<p>We&#8217;re going to use XAML with <a href=\"https:\/\/developer.xamarin.com\/guides\/xamarin-forms\/getting-started\/\" target=\"_blank\">Xamarin.Forms<\/a> to create our app, but we could use any of the native Xamarin or Windows platforms. The app we create will draw shapes, paths, and text on the screen:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/circle-cross-text-cropped.png\" width=\"357\" height=\"357\" alt=\"Final Drawing\" class=\"aligncenter\" \/><\/p>\n<p>To get started, let&#8217;s create a new Xamarin.Forms app in Xamarin Studio or Visual Studio. Once the app is created, install the <a href=\"https:\/\/www.nuget.org\/packages\/SkiaSharp\" target=\"_blank\">SkiaSharp<\/a> NuGet and the <a href=\"https:\/\/www.nuget.org\/packages\/SkiaSharp.Views.Forms\" target=\"_blank\">SkiaSharp.Views.Forms<\/a> NuGet in all of the the projects. <\/p>\n<p>The SkiaSharp NuGet contains the native rendering engine for all the platforms, but this is just for in-memory rendering. To display the rendered images on the screen, we can make use of the various views in the SkiaSharp.Views.Forms NuGet. <\/p>\n<p><em>If we we weren&#8217;t using Xamarin.Forms, but rather going native, we would instead install the <a href=\"https:\/\/www.nuget.org\/packages\/SkiaSharp.Views\" target=\"_blank\">SkiaSharp.Views<\/a> NuGet. This package contains views for all the platforms supported by SkiaSharp.<\/em><\/p>\n<h3>Adding SkiaSharp Views<\/h3>\n<p>Once the NuGets are installed, we can add the SkiaSharp view to the XAML. Here, we&#8217;re adding a <a href=\"https:\/\/developer.xamarin.com\/api\/type\/SkiaSharp.Views.Forms.SKCanvasView\" target=\"_blank\"><code>SKCanvasView<\/code><\/a>, the CPU-based drawing surface, but we could also use the <a href=\"https:\/\/developer.xamarin.com\/api\/type\/SkiaSharp.Views.Forms.SKGLView\" target=\"_blank\"><code>SKGLView<\/code><\/a>, the GPU-based drawing surface:<\/p>\n<pre class=\"theme:vs2012 lang:xml decode:true\">\n<code>&lt;ContentPage ... xmlns:views=\"clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms\"&gt;\n    &lt;Grid&gt;\n        &lt;views:SKCanvasView PaintSurface=\"OnPainting\" \/&gt;\n    &lt;\/Grid&gt;\n&lt;\/ContentPage&gt;<\/code>\n<\/pre>\n<p>Then we add the event handler in the code-behind for the page:<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\n<code>using SkiaSharp;\nusing SkiaSharp.Views.Forms;\n\nprivate void OnPainting(object sender, SKPaintSurfaceEventArgs e)\n{\n    \/\/ we will draw here\n}<\/code>\n<\/pre>\n<p><em>Note: If we run our app now, we&#8217;ll see a plain screen and perhaps some artifacts or strange pixels. This is because we are not drawing anything yet, just rendering what was in memory last, which is random data.<\/em><\/p>\n<h2>Drawing with SkiaSharp<\/h2>\n<p>Now that we have the views in place, we can write the drawing code for the view. Drawing in SkiaSharp takes the form of three basic steps:<\/p>\n<ol>\n<li>Get a surface to hold the drawing<\/li>\n<li>Get a canvas to draw on<\/li>\n<li>Draw on the canvas with paint<\/li>\n<\/ol>\n<p>When we use the SkiaSharp views, the first step (getting a surface) is done for us automatically, and we can simply query the surface for a canvas. The three main components are the <code>SKSurface<\/code>, the <code>SKCanvas<\/code>, and the <code>SKPaint<\/code>.<\/p>\n<p>The <a href=\"https:\/\/developer.xamarin.com\/api\/type\/SkiaSharp.SKSurface\/\" target=\"_blank\"><code>SKSurface<\/code><\/a> is the layer that directs drawing commands from SkiaSharp onto the underlying native drawing area. This area could be a memory location for software drawing, a framebuffer ID for an OpenGL framebuffer object, or a texture object. There are several ways to create this surface, either by creating a new surface or by using an existing memory location or framebuffer object. More information can be found by looking at the <code>SKSurface.Create(...)<\/code> APIs.<\/p>\n<p>The next component is the <a href=\"https:\/\/developer.xamarin.com\/api\/type\/SkiaSharp.SKCanvas\/\" target=\"_blank\"><code>SKCanvas<\/code><\/a>. This is the layer that translates your drawing commands, such as <code>DrawRect<\/code> and <code>DrawPath<\/code>, into the appropriate commands for drawing on the current surface. Typically, you obtain the canvas from a surface directly using the <code>SKSurface.Canvas<\/code> property. The canvas has numerous methods, from drawing shapes (<code>DrawRect<\/code>, <code>DrawOval<\/code>, and <code>DrawPath<\/code>) to text (<code>DrawText<\/code>) and images (<code>DrawBitmap<\/code> and <code>DrawBitmapLattice<\/code>) to manipulating the drawing matrix and clipping (<code>RotateDegrees<\/code>, <code>Skew<\/code>, and <code>ClipRect<\/code>).<\/p>\n<p>Finally, the <a href=\"https:\/\/developer.xamarin.com\/api\/type\/SkiaSharp.SKPaint\/\" target=\"_blank\"><code>SKPaint<\/code><\/a> type is where you control what the drawing looks like. You can call the <code>DrawRect<\/code> method multiple times and by only changing the paint, the rectangle will look totally different. Some of the properties of <code>SKPaint<\/code> directly control the way things appear (<code>IsAntialias<\/code>, <code>Color<\/code>, <code>Style<\/code>, and <code>StrokeWidth<\/code>), some control how text is drawn (<code>Typeface<\/code>, <code>UnderlineText<\/code>, <code>TextSize<\/code>, and <code>TextAlign<\/code>), plus there are the shaders, mask filters, color filters, image filters, and blend modes.<\/p>\n<h3>Clearing the Canvas<\/h3>\n<p>In our <code>OnPainting<\/code> method, we first need to get the canvas for drawing, and then we can prepare the canvas by clearing it and painting it a nice white:<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\n<code>private void OnPainting(object sender, SKPaintSurfaceEventArgs e)\n{\n    \/\/ we get the current surface from the event args\n    var surface = e.Surface;\n    \/\/ then we get the canvas that we can draw on\n    var canvas = surface.Canvas;\n    \/\/ clear the canvas \/ view\n    canvas.Clear(SKColors.White);\n}<\/code>\n<\/pre>\n<p>When we run this code, we&#8217;ll see a white screen, which we can start drawing shapes on:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/white-cropped.png\" width=\"357\" height=\"357\" alt=\"Final Drawing\" class=\"aligncenter\" \/><\/p>\n<h3>Drawing Shapes<\/h3>\n<p>The first thing we&#8217;ll draw is a simple circle using the <a href=\"https:\/\/developer.xamarin.com\/api\/member\/SkiaSharp.SKCanvas.DrawCircle\/p\/System.Single\/System.Single\/System.Single\/SkiaSharp.SKPaint\" target=\"_blank\"><code>SKCanvas.DrawCircle(cx, cy, radius, paint)<\/code><\/a> method. As you can see, this method has an <code>SKPaint<\/code> parameter, which we&#8217;ll use to draw a filled circle with a border:<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\n<code>\/\/ create the paint for the filled circle\nvar circleFill = new SKPaint {\n    IsAntialias = true,\n    Style = SKPaintStyle.Fill,\n    Color = SKColors.Blue\n};\n\n\/\/ draw the circle fill\ncanvas.DrawCircle(100, 100, 40, circleFill);\n\n\/\/ create the paint for the circle border\nvar circleBorder = new SKPaint {\n    IsAntialias = true,\n    Style = SKPaintStyle.Stroke,\n    Color = SKColors.Red,\n    StrokeWidth = 5\n};\n\n\/\/ draw the circle border\ncanvas.DrawCircle(100, 100, 40, circleBorder);<\/code>\n<\/pre>\n<p>We can see the circle on the screen when we run our app now:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/circle-cropped.png\" width=\"357\" height=\"357\" alt=\"Final Drawing\" class=\"aligncenter\" \/><\/p>\n<h3>Drawing Paths<\/h3>\n<p>We can also draw more complex shapes using a <a href=\"https:\/\/developer.xamarin.com\/api\/type\/SkiaSharp.SKPath\" target=\"_blank\"><code>SKPath<\/code><\/a> and the <a href=\"https:\/\/developer.xamarin.com\/api\/member\/SkiaSharp.SKCanvas.DrawPath\/p\/SkiaSharp.SKPath\/SkiaSharp.SKPaint\" target=\"_blank\"><code>SKCanvas.DrawPath(path, paint)<\/code><\/a> method:<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\n<code>\/\/ create the paint for the path\nvar pathStroke = new SKPaint {\n    IsAntialias = true,\n    Style = SKPaintStyle.Stroke,\n    Color = SKColors.Green,\n    StrokeWidth = 5\n};\n\n\/\/ create a path\nvar path = new SKPath();\npath.MoveTo(160, 60);\npath.LineTo(240, 140);\npath.MoveTo(240, 60);\npath.LineTo(160, 140);\n\n\/\/ draw the path\ncanvas.DrawPath(path, pathStroke);<\/code>\n<\/pre>\n<p>Now we&#8217;ll see an X next to the circle we drew previously when we run the app:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/circle-cross-cropped.png\" width=\"357\" height=\"357\" alt=\"Final Drawing\" class=\"aligncenter\" \/><\/p>\n<h3>Drawing Text<\/h3>\n<p>The last thing we&#8217;ll look at here is text. It&#8217;s just as easy to draw text using SkiaSharp; all we need to do is use the <a href=\"https:\/\/developer.xamarin.com\/api\/member\/SkiaSharp.SKCanvas.DrawText\/p\/System.String\/System.Single\/System.Single\/SkiaSharp.SKPaint\" target=\"_blank\"><code>SKCanvas.DrawText(text, x, y, paint)<\/code><\/a> method:<\/p>\n<pre class=\"theme:vs2012 lang:csharp decode:true\">\n<code>\/\/ create the paint for the text\nvar textPaint = new SKPaint\n{\n    IsAntialias = true,\n    Style = SKPaintStyle.Fill,\n    Color = SKColors.Orange,\n    TextSize = 80\n};\n\n\/\/ draw the text (from the baseline)\ncanvas.DrawText(\"SkiaSharp\", 60, 160 + 80, textPaint);<\/code>\n<\/pre>\n<p>We&#8217;ll now see orange text below our shapes and paths that were drawn earlier:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/44\/2019\/03\/circle-cross-text-cropped.png\" width=\"357\" height=\"357\" alt=\"Final Drawing\" class=\"aligncenter\" \/><\/p>\n<h2>Overview<\/h2>\n<p>Getting off the ground with SkiaSharp is easy\u2014all you need is one NuGet: <a href=\"https:\/\/www.nuget.org\/packages\/SkiaSharp\" target=\"_blank\">SkiaSharp<\/a>. This package provides everything necessary to create and manipulate drawings on any platform.<\/p>\n<p>If you&#8217;re looking to display your drawings on-screen, you can check out the <a href=\"https:\/\/www.nuget.org\/packages\/SkiaSharp.Views\" target=\"_blank\">SkiaSharp.Views<\/a> NuGet package. This package has a set of views, layers, and controls that get you going with displaying your drawing on-screen. If you have a Xamarin.Forms app, then you can install the <a href=\"https:\/\/www.nuget.org\/packages\/SkiaSharp.Views.Forms\" target=\"_blank\">SkiaSharp.Views.Forms<\/a> NuGet package, which provides the same views for Xamarin.Forms.<\/p>\n<p>Finally, we have a lightweight SVG loading library that can be used to load an SVG into a <a href=\"https:\/\/developer.xamarin.com\/api\/type\/SkiaSharp.SKPicture\/\" target=\"_blank\"><code>SKPicture<\/code><\/a>: <a href=\"https:\/\/www.nuget.org\/packages\/SkiaSharp.Svg\" target=\"_blank\">SkiaSharp.Svg<\/a>.<\/p>\n<h2>Documentation and Forums<\/h2>\n<p>We&#8217;ve documented all of the APIs of SkiaSharp on the <a href=\"https:\/\/developer.xamarin.com\/api\/root\/SkiaSharp\/\" target=\"_blank\">Xamarin developer site<\/a>, along with the <a href=\"https:\/\/developer.xamarin.com\/guides\/cross-platform\/drawing\/\" target=\"_blank\">developer guides<\/a>, which provide even more information.<\/p>\n<p>You can also ask questions on the <a href=\"https:\/\/forums.xamarin.com\/\" target=\"_blank\">Xamarin SkiaSharp forums<\/a>. If you prefer StackOverflow, <a href=\"http:\/\/stackoverflow.com\/questions\/tagged\/skiasharp\" target=\"_blank\">we&#8217;re there, too<\/a>!<\/p>\n<p>Hang out on Gitter to ask questions and add comments &#8211; here: <a href=\"https:\/\/gitter.im\/xamarin\/XamarinComponents\" target=\"_blank\">xamarin\/XamarinComponents<\/a>.<\/p>\n<h2>Code, Issues and Suggestions<\/h2>\n<p>The SkiaSharp codebase is constantly growing and improving. If you want to contribute, you can do so by forking on GitHub: <a href=\"https:\/\/github.com\/mono\/SkiaSharp\" target=\"_blank\">mono\/SkiaSharp<\/a>.<\/p>\n<p>If you have any questions, bugs or suggestions, we welcome them as <a href=\"https:\/\/github.com\/mono\/SkiaSharp\/issues\" target=\"_blank\">issues<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are millions of mobile apps created every day that all do different things. However, they still have one thing in common: they will display some form of information to the user. Sometimes this will be a graph or a chart, sometimes it will be an interactive interface control. Sometimes it will just be plain [&hellip;]<\/p>\n","protected":false},"author":550,"featured_media":29684,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[4,16],"class_list":["post-29646","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-xamarin-platform","tag-xamarin-forms"],"acf":[],"blog_post_summary":"<p>There are millions of mobile apps created every day that all do different things. However, they still have one thing in common: they will display some form of information to the user. Sometimes this will be a graph or a chart, sometimes it will be an interactive interface control. Sometimes it will just be plain [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/29646","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/550"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=29646"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/29646\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=29646"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=29646"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=29646"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}