Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[submodule "skia"]
path = skia
url = git@github.com:xamarin/skia.git
url = git@github.com:mono/skia.git
[submodule "depot_tools"]
path = depot_tools
url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
50 changes: 50 additions & 0 deletions Binding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
SkiaSharp provides the same features as the native C++ library through a method of wrapping
the C++ API with a C API that we P/Invoke into.

Then C# wraps the C API to provide an API similar to the object oriented binding provided by C++.

For example, given this C++ API:

```cpp
class SK_API SkPaint {
public:
bool isAntiAlias() const;
void setAntiAlias(bool aa);
};
```

This is then wrapped in a C API:

```cpp
bool sk_paint_is_antialias(const sk_paint_t* cpaint) {
return AsPaint(cpaint)->isAntiAlias();
}
void sk_paint_set_antialias(sk_paint_t* cpaint, bool aa) {
AsPaint(cpaint)->setAntiAlias(aa);
}
```

Which is then pulled into the C# project via P/Invoke:

```csharp
public extern static bool sk_paint_is_antialias (sk_paint_t t);
public extern static void sk_paint_set_antialias (sk_paint_t t, bool aa);
```

Finally, this is wrapped into a neat C# class:

```csharp
public class SKPaint : SKObject
{
public bool IsAntialias {
get { return SkiaApi.sk_paint_is_antialias (Handle); }
set { SkiaApi.sk_paint_set_antialias (Handle, value); }
}
}
```

As a result, the C# API functions and appears the same as the C++ API.

Since the C API is currently a work in progress of the Skia project, we
maintain a fork in github.com/mono/skia that has our additions. We intend
to upstream those changes to Google.
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
all:
echo You can use "make update-docs" to update the docs

update-docs:
(cd binding; xbuild SkiaSharp.Generic.sln)
mdoc update --out=docs/en binding/SkiaSharp.Generic/bin/Debug/SkiaSharp.dll
235 changes: 6 additions & 229 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,247 +1,24 @@
# SkiaSharp

Skia# is a cross-platform, managed binding for the
SkiaSharp is a cross-platform, managed binding for the
Skia Graphics Library (https://skia.org/)

## What is Included

Skia# provides a PCL and platform-specific bindings for:
SkiaSharp provides a PCL and platform-specific bindings for:

- Mac OS X
- Xamarin.Android
- Xamarin.iOS
- Windows Desktop
- Mac Desktop

## Using Skia#

### Creating a SKCanvas

Although all platforms can use the same *drawing* logic, each
platform has a different method for obtaining the surface and
canvas.

#### iOS

var screenScale = UIScreen.MainScreen.Scale;
var width = (int)(Bounds.Width * screenScale);
var height = (int)(Bounds.Height * screenScale);

IntPtr buff = System.Runtime.InteropServices.Marshal.AllocCoTaskMem (width * height * 4);
try {
using (var surface = SKSurface.Create (width, height, SKColorType.N_32, SKAlphaType.Premul, buff, width * 4)) {
var skcanvas = surface.Canvas;
skcanvas.Scale ((float)screenScale, (float)screenScale);
using (new SKAutoCanvasRestore (skcanvas, true)) {
DoDraw (skcanvas);
}
}
using (var colorSpace = CGColorSpace.CreateDeviceRGB ())
using (var bContext = new CGBitmapContext (buff, width, height, 8, width * 4, colorSpace, (CGImageAlphaInfo)bitmapInfo))
using (var image = bContext.ToImage ())
using (var context = UIGraphics.GetCurrentContext ()) {
// flip the image for CGContext.DrawImage
context.TranslateCTM (0, Frame.Height);
context.ScaleCTM (1, -1);
context.DrawImage (Bounds, image);
}
} finally {
if (buff != IntPtr.Zero)
System.Runtime.InteropServices.Marshal.FreeCoTaskMem (buff);
}

#### Android

var width = (float)skiaView.Width;
var height = (float)skiaView.Height;

using (var bitmap = Bitmap.CreateBitmap (canvas.Width, canvas.Height, Bitmap.Config.Argb8888)) {
try {
using (var surface = SKSurface.Create (canvas.Width, canvas.Height, SKColorType.Rgba_8888, SKAlphaType.Premul, bitmap.LockPixels (), canvas.Width * 4)) {
var skcanvas = surface.Canvas;
skcanvas.Scale (((float)canvas.Width)/width, ((float)canvas.Height)/height);
DoDraw (skcanvas);
}
}
finally {
bitmap.UnlockPixels ();
}
canvas.DrawBitmap (bitmap, 0, 0, null);
}

#### OS X

var screenScale = (int)NSScreen.MainScreen.BackingScaleFactor * 2;
var width = (int)Bounds.Width * screenScale;
var height = (int)Bounds.Height * screenScale;

IntPtr buff = System.Runtime.InteropServices.Marshal.AllocCoTaskMem (width * height * 4);
try {
using (var surface = SKSurface.Create (width, height, SKColorType.Rgba_8888, SKAlphaType.Premul, buff, width * 4)) {
var skcanvas = surface.Canvas;
skcanvas.Scale (screenScale, screenScale);
DoDraw (skcanvas);
}
int flag = ((int)CoreGraphics.CGBitmapFlags.ByteOrderDefault) | ((int)CoreGraphics.CGImageAlphaInfo.PremultipliedLast);
using (var colorSpace = CoreGraphics.CGColorSpace.CreateDeviceRGB ())
using (var bContext = new CoreGraphics.CGBitmapContext (buff, width, height, 8, width * 4, colorSpace, (CoreGraphics.CGImageAlphaInfo) flag))
using (var image = bContext.ToImage ())
using (var context = NSGraphicsContext.CurrentContext.GraphicsPort) {
context.DrawImage (Bounds, image);
}
} finally {
if (buff != IntPtr.Zero)
System.Runtime.InteropServices.Marshal.FreeCoTaskMem (buff);
}

#### Windows Desktop / Mac Desktop

var width = Width;
var height = Height;

using (var bitmap = new Bitmap(width, height, PixelFormat.Format32bppPArgb)) {
var data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bitmap.PixelFormat);
using (var surface = SKSurface.Create(width, height, SKColorType.Bgra_8888, SKAlphaType.Premul, data.Scan0, width * 4)) {
var skcanvas = surface.Canvas;
onDrawCallback(skcanvas, width, height);
}
bitmap.UnlockBits(data);
e.Graphics.DrawImage(bitmap, new Rectangle(0, 0, Width, Height));
}

### Drawing on SKCanvas

Below are just a few of the many different things that can be done
with Skia#:

#### Drawing Xamagon

SKCanvas canvas = ...;

// clear the canvas / fill with white
canvas.Clear (SKColors.White);

// set up drawing tools
using (var paint = new SKPaint ()) {
paint.IsAntialias = true;
paint.Color = new SKColor (0x2c, 0x3e, 0x50);
paint.StrokeCap = SKStrokeCap.Round;

// create the Xamagon path
using (var path = new SKPath ()) {
path.MoveTo (71.4311121f, 56f);
path.CubicTo (68.6763107f, 56.0058575f, 65.9796704f, 57.5737917f, 64.5928855f, 59.965729f);
path.LineTo (43.0238921f, 97.5342563f);
path.CubicTo (41.6587026f, 99.9325978f, 41.6587026f, 103.067402f, 43.0238921f, 105.465744f);
path.LineTo (64.5928855f, 143.034271f);
path.CubicTo (65.9798162f, 145.426228f, 68.6763107f, 146.994582f, 71.4311121f, 147f);
path.LineTo (114.568946f, 147f);
path.CubicTo (117.323748f, 146.994143f, 120.020241f, 145.426228f, 121.407172f, 143.034271f);
path.LineTo (142.976161f, 105.465744f);
path.CubicTo (144.34135f, 103.067402f, 144.341209f, 99.9325978f, 142.976161f, 97.5342563f);
path.LineTo (121.407172f, 59.965729f);
path.CubicTo (120.020241f, 57.5737917f, 117.323748f, 56.0054182f, 114.568946f, 56f);
path.LineTo (71.4311121f, 56f);
path.Close ();

// draw the Xamagon path
canvas.DrawPath (path, paint);
}
}
You can also build this on your particular variant of Unix
to create your native libraries.

#### Drawing Text

SKCanvas canvas = ...;

// clear the canvas / fill with white
canvas.DrawColor (SKColors.White);

// set up drawing tools
using (var paint = new SKPaint ()) {
paint.TextSize = 64.0f;
paint.IsAntialias = true;
paint.Color = new SKColor (0x42, 0x81, 0xA4);
paint.IsStroke = false;

// draw the text
canvas.DrawText ("Skia", 0.0f, 64.0f, paint);
}

#### Drawing Bitmaps

SKCanvas canvas = ...;
Stream fileStream = ...; // open a stream to an image file

// clear the canvas / fill with white
canvas.DrawColor (SKColors.White);

// decode the bitmap from the stream
using (var stream = new SKManagedStream(fileStream))
using (var bitmap = SKBitmap.Decode(stream))
using (var paint = new SKPaint()) {
canvas.DrawBitmap(bitmap, SKRect.Create(Width, Height), paint);
}

#### Drawing Image Filters

SKCanvas canvas = ...;
Stream fileStream = ...; // open a stream to an image file

// clear the canvas / fill with white
canvas.DrawColor (SKColors.White);

// decode the bitmap from the stream
using (var stream = new SKManagedStream(fileStream))
using (var bitmap = SKBitmap.Decode(stream))
using (var paint = new SKPaint()) {
// create the image filter
using (var filter = SKImageFilter.CreateBlur(5, 5)) {
paint.ImageFilter = filter;

// draw the bitmap through the filter
canvas.DrawBitmap(bitmap, SKRect.Create(width, height), paint);
}
}

## How Skia# is Built

Skia# provides the same features as the native C++ library through
a method of wrapping the C++ API with a dumb C API. Then C# wraps the
C API to provide an API similar to that of the C++.

For example, given the C++ API:

class SK_API SkPaint {
public:
bool isAntiAlias() const;
void setAntiAlias(bool aa);
};

This is then wrapped in a C API:

bool sk_paint_is_antialias(const sk_paint_t* cpaint) {
return AsPaint(*cpaint).isAntiAlias();
}
void sk_paint_set_antialias(sk_paint_t* cpaint, bool aa) {
AsPaint(cpaint)->setAntiAlias(aa);
}

Which is then pulled into the C# project via P/Invoke:

public extern static bool sk_paint_is_antialias(sk_paint_t t);
public extern static void sk_paint_set_antialias(sk_paint_t t, bool aa);

Finally, this is wrapped into a neat C# class:

public class SKPaint : SKObject
{
public bool IsAntialias {
get { return SkiaApi.sk_paint_is_antialias (Handle); }
set { SkiaApi.sk_paint_set_antialias (Handle, value); }
}
}
## Using Skia#

As a result, the C# API functions and appears the same as the C++ API.
Check our getting [started guide](https://developer.xamarin.com/guides/cross-platform/drawing/)

## Where is Windows Phone / Store

Expand Down
5 changes: 5 additions & 0 deletions docs/SkiaSharp.source
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0"?>
<monodoc>
<node label="SkiaSharp" name="SkiaSharp" parent="libraries"/>
<source provider="ecma" basefile="SkiaSharp" path="SkiaSharp"/>
</monodoc>
67 changes: 67 additions & 0 deletions docs/en/SkiaSharp/SKAlphaType.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<Type Name="SKAlphaType" FullName="SkiaSharp.SKAlphaType">
<TypeSignature Language="C#" Value="public enum SKAlphaType" />
<TypeSignature Language="ILAsm" Value=".class public auto ansi sealed SKAlphaType extends System.Enum" />
<AssemblyInfo>
<AssemblyName>SkiaSharp</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>System.Enum</BaseTypeName>
</Base>
<Docs>
<summary>Describes how to interpret the alpha component of a pixel.</summary>
<remarks>
<para />
</remarks>
</Docs>
<Members>
<Member MemberName="Opaque">
<MemberSignature Language="C#" Value="Opaque" />
<MemberSignature Language="ILAsm" Value=".field public static literal valuetype SkiaSharp.SKAlphaType Opaque = int32(0)" />
<MemberType>Field</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>SkiaSharp.SKAlphaType</ReturnType>
</ReturnValue>
<Docs>
<summary>All pixels are stored as opaque.</summary>
</Docs>
</Member>
<Member MemberName="Premul">
<MemberSignature Language="C#" Value="Premul" />
<MemberSignature Language="ILAsm" Value=".field public static literal valuetype SkiaSharp.SKAlphaType Premul = int32(1)" />
<MemberType>Field</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>SkiaSharp.SKAlphaType</ReturnType>
</ReturnValue>
<Docs>
<summary>
<para>All pixels have their alpha premultiplied in their color components.</para>
<para>This is the natural format for the rendering target pixels.</para>
</summary>
</Docs>
</Member>
<Member MemberName="Unpremul">
<MemberSignature Language="C#" Value="Unpremul" />
<MemberSignature Language="ILAsm" Value=".field public static literal valuetype SkiaSharp.SKAlphaType Unpremul = int32(2)" />
<MemberType>Field</MemberType>
<AssemblyInfo>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
</AssemblyInfo>
<ReturnValue>
<ReturnType>SkiaSharp.SKAlphaType</ReturnType>
</ReturnValue>
<Docs>
<summary>
<para>All pixels have their color components stored without any regard to the alpha. e.g. this is the default configuration for PNG images.</para>
<para>This alpha-type is ONLY supported for input images. Rendering cannot generate this on output.</para>
</summary>
</Docs>
</Member>
</Members>
</Type>
Loading