Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
be634e9
docs: add GPU and offscreen surfaces guides (incl. Graphite)
Copilot Jul 21, 2026
8bb3333
docs: refine GPU surface guides per Graphite review feedback
Copilot Jul 21, 2026
962f061
docs: mention SKGraphiteAsyncReadResult.CopyPlaneTo in readback note
Copilot Jul 21, 2026
4e4ab14
docs: fold in Graphite backend learnings (platforms, Silk.NET, gotchas)
Copilot Jul 24, 2026
8995e95
docs: flesh out the Graphite wrap+draw+release loop
Copilot Jul 24, 2026
a7deaca
docs: reconcile Graphite read-back prose with SKImageReadPixelsResult
Copilot Jul 28, 2026
cda104e
docs: reconcile Graphite guide with current PR state (budget, Snap nu…
Copilot Jul 28, 2026
4c7301a
docs: reference tracking issue #4555 for the iOS-simulator gradient l…
Copilot Jul 28, 2026
a69ea70
docs: enrich Graphite guide with threading model, pipeline compilatio…
Copilot Jul 28, 2026
4ed99d8
Improve GPU surface guides and documentation skill
mattleibow Aug 4, 2026
f1bf2ce
Harden automated API documentation waves
mattleibow Aug 4, 2026
7c862a2
Split documentation skill from GPU guides
mattleibow Aug 5, 2026
b66fa80
Refine GPU guides after independent review
mattleibow Aug 5, 2026
ecd3eb0
Reorganize surface guides by backend
mattleibow Aug 5, 2026
7f353fa
Add document output guides
mattleibow Aug 5, 2026
af0b0ac
Reorganize surface and view guides
mattleibow Aug 6, 2026
8c721c4
Harden surface guide accuracy
mattleibow Aug 6, 2026
42dff4c
Simplify surface guide snippets
mattleibow Aug 6, 2026
c95fcb4
Use American English spelling in Graphite guides
mattleibow Aug 6, 2026
edc966c
Merge branch 'main' into mattleibow-graphite-surface-docs
mattleibow Aug 11, 2026
197cc41
docs: clarify Graphite CPU recording vs serialized submission vs GPU …
Copilot Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 56 additions & 1 deletion documentation/docfx/guides/TOC.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- name: Overview
- name: SkiaSharp guides
href: index.md
- name: Drawing Basics
href: basics/index.md
Expand Down Expand Up @@ -115,3 +115,58 @@
href: effects/image-filters.md
- name: Color Filters
href: effects/color-filters.md
- name: Drawing destinations
href: surfaces/index.md
items:
- name: Raster surfaces
href: surfaces/raster/index.md
- name: Ganesh GPU surfaces
href: surfaces/ganesh/index.md
items:
- name: OpenGL
href: surfaces/ganesh/opengl.md
- name: Vulkan
href: surfaces/ganesh/vulkan.md
- name: Metal
href: surfaces/ganesh/metal.md
- name: Direct3D
href: surfaces/ganesh/direct3d.md
- name: Graphite GPU surfaces
href: surfaces/graphite/index.md
items:
- name: Vulkan
href: surfaces/graphite/vulkan.md
- name: Metal
href: surfaces/graphite/metal.md
- name: Dawn and WebGPU
href: surfaces/graphite/dawn.md
- name: Migrate from Ganesh
href: surfaces/graphite/migrate-from-ganesh.md
- name: Documents
href: surfaces/documents/index.md
items:
- name: Create a PDF document
href: surfaces/documents/pdf.md
- name: Create an SVG document
href: surfaces/documents/svg.md
- name: Create an XPS document
href: surfaces/documents/xps.md
- name: Choose a SkiaSharp view
href: surfaces/views/index.md
items:
- name: .NET MAUI
href: surfaces/views/maui.md
- name: Android
href: surfaces/views/android.md
- name: Apple platforms
href: surfaces/views/apple.md
- name: Windows
href: surfaces/views/windows.md
- name: Linux
href: surfaces/views/linux.md
- name: Tizen
href: surfaces/views/tizen.md
- name: Uno Platform
href: surfaces/views/uno.md
- name: Blazor WebAssembly
href: surfaces/views/blazor.md
26 changes: 16 additions & 10 deletions documentation/docfx/guides/index.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
---
title: "Overview"
description: "SkiaSharp is a 2D graphics system for .NET and C# powered by the open-source Skia graphics engine that is used extensively in Google products such as Google Chrome, ChromeOS, and Android, in Chromium-based products like Microsoft Edge, in applications like LibreOffice, and in .NET UI frameworks like Uno Platform. This guide explains how to use SkiaSharp for 2D graphics in your .NET MAUI applications."
title: "SkiaSharp guides"
description: "Learn how to use SkiaSharp across .NET applications, from drawing basics to surfaces, document output, and platform views."
---

# SkiaSharp Graphics in .NET MAUI
# SkiaSharp guides

_Use SkiaSharp for 2D graphics in your .NET MAUI applications_
_Use SkiaSharp for 2D graphics in .NET applications_

SkiaSharp is a 2D graphics system for .NET and C# powered by the open-source Skia graphics engine that is used extensively in Google products such as Google Chrome, ChromeOS, and Android, in Chromium-based products like Microsoft Edge, in applications like LibreOffice, and in .NET UI frameworks like Uno Platform. You can use SkiaSharp in your .NET MAUI applications to draw 2D vector graphics, bitmaps, and text.
SkiaSharp is a 2D graphics system for .NET and C# powered by the open-source Skia graphics engine that is used extensively in Google products such as Google Chrome, ChromeOS, and Android, in Chromium-based products like Microsoft Edge, in applications like LibreOffice, and in .NET UI frameworks like Uno Platform. You can use SkiaSharp to draw 2D vector graphics, bitmaps, and text in UI, offscreen, document, and headless workloads.

The introductory drawing articles use .NET MAUI views for their examples, but the underlying `SKCanvas` drawing APIs apply across SkiaSharp integrations. The [drawing destinations](surfaces/index.md) section covers manually managed surfaces, document output, and platform-specific views.

## Get started with .NET MAUI

> [!IMPORTANT]
> In .NET MAUI, you must initialize SkiaSharp by calling `UseSkiaSharp()` on the `MauiAppBuilder` in your `MauiProgram.cs` file. This requires adding a `using` directive for the `SkiaSharp.Views.Maui.Controls.Hosting` namespace.

This guide assumes that you are familiar with .NET MAUI programming.

## SkiaSharp Preliminaries
The introductory articles assume that you are familiar with .NET MAUI programming.

SkiaSharp for .NET MAUI is packaged as a NuGet package. After you've created a .NET MAUI solution in Visual Studio or Visual Studio for Mac, you can use the NuGet package manager to search for the **SkiaSharp.Views.Maui.Controls** package and add it to your solution. If you check the **References** section of each project after adding SkiaSharp, you can see that various **SkiaSharp** libraries have been added to each of the projects in the solution.
After creating a .NET MAUI project, add the **SkiaSharp.Views.Maui.Controls** NuGet package. The package brings in the SkiaSharp libraries required by the target platforms.

In any C# page that uses SkiaSharp you'll want to include a `using` directive for the [`SkiaSharp`](xref:SkiaSharp) namespace, which encompasses all the SkiaSharp classes, structures, and enumerations that you'll use in your graphics programming. You'll also want a `using` directive for the [`SkiaSharp.Views.Maui.Controls`](xref:SkiaSharp.Views.Maui.Controls) namespace for the classes specific to .NET MAUI. This is a much smaller namespace, with the most important class being [`SKCanvasView`](xref:SkiaSharp.Views.Maui.Controls.SKCanvasView). This class derives from the .NET MAUI `View` class and hosts your SkiaSharp graphics output.

> [!IMPORTANT]
> The `SkiaSharp.Views.Maui.Controls` namespace also contains an `SKGLView` class that derives from `View` but uses OpenGL for rendering graphics. For purposes of simplicity, this guide restricts itself to `SKCanvasView`, but using `SKGLView` instead is quite similar.
> The `SkiaSharp.Views.Maui.Controls` namespace also contains an `SKGLView` class that derives from `View` and uses a GPU backend selected by the platform handler. These introductory articles use `SKCanvasView`; see [Render with SkiaSharp in .NET MAUI](surfaces/views/maui.md) before choosing `SKGLView`.

## [SkiaSharp Drawing Basics](basics/index.md)

Expand All @@ -47,6 +49,10 @@ Bitmaps are rectangular arrays of bits corresponding to the pixels of a display

Effects are properties that alter the normal display of graphics, including linear and circular gradients, bitmap tiling, blend modes, blur, and others.

## [Drawing destinations](surfaces/index.md)

Choose a manually managed raster, Ganesh, or Graphite surface; draw into PDF, SVG, or XPS documents; or let a platform view manage its surface and presentation.

## Related Links

- [SkiaSharp APIs](https://learn.microsoft.com/dotnet/api/skiasharp)
38 changes: 38 additions & 0 deletions documentation/docfx/guides/surfaces/documents/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: "Documents"
description: "Choose PDF, SVG, or XPS output and learn how each SkiaSharp document API supplies a canvas and finalizes its stream safely."
---

# Documents

Use a SkiaSharp document canvas when drawing should be serialized to a file or stream instead of rendered into an [`SKSurface`](xref:SkiaSharp.SKSurface). You still draw with an [`SKCanvas`](xref:SkiaSharp.SKCanvas), but the document canvas encodes those draw calls as PDF, SVG, or XPS output in a caller-supplied stream.

Start with PDF for multi-page output unless the consumer specifically requires XPS. Choose SVG when you need one scalable vector graphic represented as XML.

## Choose a format

| Format | Use when | Canvas lifecycle | Main constraint |
| --- | --- | --- | --- |
| PDF | You need portable, multi-page document output | Create an `SKDocument`, call `BeginPage` and `EndPage` for each page, then call `Close` | Page dimensions use points; close the document before reading the completed output |
| SVG | You need one scalable vector graphic or SVG markup | Create an `SKCanvas` with `SKSvgCanvas.Create`, draw your content, then dispose the canvas | There is no page lifecycle; the SVG is not complete until the canvas is disposed |
| XPS | A Windows workflow specifically requires XPS output | Use the same `SKDocument` page lifecycle as PDF | Requires the Windows XPS Object Model and COM; creation returns `null` where unavailable |

PDF and XPS page sizes use point units, where 72 points equal one inch. Their raster DPI options control how drawing operations without a native document representation are rasterized; DPI does not change the page coordinate system.

## How document canvases differ from surfaces

An `SKSurface` exposes pixels in CPU memory or a GPU resource. You can snapshot it, read its pixels, or present it through a view. A document canvas instead serializes draw calls to an output stream. The public document workflow has no surface to snapshot or read back.

This distinction lets you reuse drawing code. Put the drawing itself in a method that accepts `SKCanvas`, then call it with a surface canvas, a document page canvas, or an SVG canvas as appropriate. Keep destination-specific setup and finalization outside that method.

## In this section

- [Create a PDF document](pdf.md) - write and finalize a multi-page PDF, set metadata, and handle incomplete output.
- [Create an SVG document](svg.md) - draw one bounded SVG graphic and complete its XML by disposing the canvas.
- [Create an XPS document](xps.md) - initialize COM and write a multi-page XPS file on supported Windows systems.

## Related output paths

- To produce PNG, JPEG, WebP, or another raster image, [render and encode bitmap pixels](../../bitmaps/saving.md).
- To record Skia drawing commands for replay or Skia-specific serialization, use [`SKPictureRecorder`](xref:SkiaSharp.SKPictureRecorder) and [`SKPicture`](xref:SkiaSharp.SKPicture). An `SKPicture` is not a standard document format.
- To render into pixels rather than a document stream, [choose a SkiaSharp surface](../index.md).
87 changes: 87 additions & 0 deletions documentation/docfx/guides/surfaces/documents/pdf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: "Create a PDF document with SkiaSharp"
description: "Create and finalize a multi-page PDF with SKDocument, point-based page sizes, metadata, and safe stream ownership."
---

# Create a PDF document with SkiaSharp

Use [`SKDocument`](xref:SkiaSharp.SKDocument) to draw a multi-page PDF into a file or writable stream. Create the document, begin and end each page, and call `Close` after the final page. PDF page dimensions use points, where 72 points equal one inch.

## Create and finalize the pages

The following complete example writes a two-page US Letter PDF. The page canvas is valid only until `EndPage` or `Close` is called.

```csharp
using System.IO;
using SkiaSharp;

const string outputPath = "sample.pdf";

using (var output = File.Create(outputPath))
{
WritePdf(output);
}

static void WritePdf(Stream output)
{
const float pageWidth = 612; // 8.5 inches * 72 points
const float pageHeight = 792; // 11 inches * 72 points

var metadata = SKDocumentPdfMetadata.Default;
metadata.Title = "SkiaSharp PDF example";
metadata.Author = "Example application";

using var document = SKDocument.CreatePdf(output, metadata);
using var paint = new SKPaint
{
IsAntialias = true,
Color = SKColors.CornflowerBlue,
};

for (var pageNumber = 1; pageNumber <= 2; pageNumber++)
{
var canvas = document.BeginPage(pageWidth, pageHeight);
canvas.Clear(SKColors.White);
canvas.DrawCircle(
pageWidth / 2,
220 + pageNumber * 120,
100,
paint);

document.EndPage();
}

document.Close();
}
```

`SKDocument` owns the native page canvas and invalidates it when the page ends. Scope the managed canvas wrapper to one page and do not use it after `EndPage`.

The `Stream` overload keeps the caller's .NET stream open. `Close` finalizes the PDF into that stream; disposing the document then releases its internal stream wrapper. The caller remains responsible for disposing the .NET stream.

## Configure metadata and raster fallback

Start with `SKDocumentPdfMetadata.Default`, then change the fields you need. A newly zero-initialized `SKDocumentPdfMetadata` does not contain the documented raster DPI and encoding-quality defaults.

The most relevant options are:

- `Title`, `Author`, `Subject`, `Keywords`, `Creator`, `Producer`, `Creation`, and `Modified` set PDF metadata.
- `RasterDpi` controls the resolution used when a draw operation must be rasterized because PDF has no native representation for it. It does not change page dimensions.
- `EncodingQuality` is `101` by default, which selects lossless image encoding. Values of `100` or less allow opaque images to use JPEG at that quality.
- `PdfA` requests the additional metadata and output intent needed by Skia's PDF/A-2b path. Validate the resulting file against any conformance rules your application must meet.

## Handle incomplete output

Call `Abort` if page generation cannot complete. After an abort, discard the output stream contents; they are not a valid document. The example uses a `finally` block so the original failure still propagates while the document is abandoned.

Call `Close` before reading or publishing the result. Disposing a PDF document also closes it when needed, but an explicit `Close` makes the successful completion point clear and ensures final bytes have reached the stream.

## Verify the result

The resulting file should be non-empty, begin with the PDF header `%PDF-`, and open as a two-page US Letter document. Verify text, images, effects, and links in the PDF viewer used by your target workflow.

## Related links

- [Documents](index.md)
- [Create an XPS document](xps.md)
- [Save SkiaSharp bitmaps to files](../../bitmaps/saving.md)
60 changes: 60 additions & 0 deletions documentation/docfx/guides/surfaces/documents/svg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: "Create an SVG document with SkiaSharp"
description: "Create a single SVG document with SKSvgCanvas, draw through SKCanvas, and finalize valid XML without closing the caller-owned stream."
---

# Create an SVG document with SkiaSharp

Use [`SKSvgCanvas`](xref:SkiaSharp.SKSvgCanvas) to translate `SKCanvas` draw calls into a Scalable Vector Graphics (SVG) stream. Unlike PDF and XPS, SVG creation returns the canvas directly and has no page lifecycle. Dispose the canvas to complete the XML.

## Create and complete the SVG

The bounds passed to `SKSvgCanvas.Create` define the initial SVG viewport. This complete example writes a 640 by 480 SVG:

```csharp
using System.IO;
using SkiaSharp;

const string outputPath = "drawing.svg";
var bounds = SKRect.Create(640, 480);

using (var output = File.Create(outputPath))
using (var canvas = SKSvgCanvas.Create(bounds, output))
using (var backgroundPaint = new SKPaint { Color = SKColors.White })
using (var paint = new SKPaint
{
IsAntialias = true,
Color = SKColors.CornflowerBlue,
})
{
canvas.DrawRect(bounds, backgroundPaint);
canvas.DrawCircle(bounds.MidX, bounds.MidY, 140, paint);
}
```

The SVG canvas may buffer output. Its closing XML is not guaranteed to be present until the canvas is disposed. Keep the output stream alive for the full canvas lifetime and dispose the canvas before reading, sending, or closing the stream.

The `Stream` overload does not dispose the caller's .NET stream. In the example, the nested `using` statements dispose the canvas first and the file stream second.

## Reuse drawing code

`SKSvgCanvas.Create` returns an ordinary `SKCanvas`, so drawing helpers that accept `SKCanvas` can target SVG without an `SKSurface`. Keep the SVG bounds and stream lifecycle in the caller:

```csharp
static void DrawBadge(SKCanvas canvas, SKRect bounds, SKPaint paint)
{
canvas.DrawCircle(bounds.MidX, bounds.MidY, 64, paint);
}
```

The SVG output represents drawing commands rather than a pixel snapshot. Open the result in the browsers or SVG renderers your application supports. If you require exact raster pixels instead, [render to a raster surface](../raster/index.md) and encode the resulting image.

## Verify the result

The file should parse as XML with an `svg` root element whose width and height are `640` and `480`. It should display a blue circle on a white background.

## Related links

- [Documents](index.md)
- [Create a PDF document](pdf.md)
- [SVG path data in SkiaSharp](../../curves/path-data.md)
77 changes: 77 additions & 0 deletions documentation/docfx/guides/surfaces/documents/xps.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
title: "Create an XPS document with SkiaSharp"
description: "Create and finalize a multi-page XPS document on supported Windows systems, including COM setup and point-based pages."
---

# Create an XPS document with SkiaSharp

Use [`SKDocument.CreateXps`](xref:SkiaSharp.SKDocument.CreateXps*) when a Windows workflow specifically requires XML Paper Specification (XPS) output. XPS uses the same `BeginPage`, `EndPage`, and `Close` lifecycle as PDF, but the native factory requires the Windows XPS Object Model and an initialized Component Object Model (COM) apartment.

XPS document creation is supported on desktop and server Windows where the XPS Object Model is available. It is not supported on non-Windows systems or Nano Server. `CreateXps` returns `null` when the native XPS factory is unavailable.

## Initialize COM and create the document

Keep [`SKAutoCoInitialize`](xref:SkiaSharp.SKAutoCoInitialize) alive for the complete XPS document lifetime. The following complete example writes a two-page US Letter XPS file:

```csharp
using System.IO;
using SkiaSharp;

const string outputPath = "sample.xps";

using (var com = new SKAutoCoInitialize())
{
using var output = File.Create(outputPath);
using var document = SKDocument.CreateXps(output);

const float pageWidth = 612; // 8.5 inches * 72 points
const float pageHeight = 792; // 11 inches * 72 points

using var paint = new SKPaint
{
IsAntialias = true,
Color = SKColors.CornflowerBlue,
};

for (var pageNumber = 1; pageNumber <= 2; pageNumber++)
{
var canvas = document.BeginPage(pageWidth, pageHeight);
canvas.Clear(SKColors.White);
canvas.DrawRect(
SKRect.Create(96, 96 + pageNumber * 80, 420, 180),
paint);

document.EndPage();
}

document.Close();
}
```

The `using` order keeps COM and the output stream alive while the XPS document uses them. The page canvas is invalid after `EndPage`.

## Set the raster DPI

XPS page dimensions use points, where 72 points equal one inch. Within the Windows and COM scope shown in the complete example, the optional `dpi` argument to `CreateXps` controls the resolution used when document content must be rasterized; it does not change the page coordinate system. Keep the writable `Stream output` alive for the document lifetime:

```csharp
using var document = SKDocument.CreateXps(output, dpi: 144);
```

The default raster DPI is `SKDocument.DefaultRasterDpi`, which is 72. Increase it only when rasterized content needs more detail and the additional document size and processing cost are acceptable.

## Handle unavailable or incomplete output

Production code can check the nullable result from `CreateXps` when it needs to handle systems where the XPS Object Model factory is unavailable.

If generation fails after document creation, call `Abort` and discard the stream contents. Call `Close` after the final page before reading or publishing the file.

## Verify the result

The resulting file should be non-empty and open as a two-page XPS document in the viewer or print workflow your application targets. Run this verification on the Windows versions you support.

## Related links

- [Documents](index.md)
- [Create a PDF document](pdf.md)
- [Create an SVG document](svg.md)
Loading
Loading