Added SKPathMeasure to the C# API

This commit is contained in:
Matthew Leibowitz 2016-10-15 03:40:10 +02:00
Родитель 7fa8a4aac1
Коммит 9c2d2697a2
7 изменённых файлов: 218 добавлений и 1 удалений

Просмотреть файл

@ -21,6 +21,7 @@
<Compile Include="$(MSBuildThisFileDirectory)SKDocument.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKPathEffect.cs" />
<Compile Include="$(MSBuildThisFileDirectory)GRContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKPathMeasure.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKSurface.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKCanvas.cs" />
<Compile Include="$(MSBuildThisFileDirectory)SKShader.cs" />

Просмотреть файл

@ -0,0 +1,98 @@
//
// Bindings for SKPathMeasure
//
// Author:
// Matthew Leibowitz
//
// Copyright 2016 Xamarin Inc
//
using System;
namespace SkiaSharp
{
public class SKPathMeasure : SKObject
{
[Flags]
public enum MatrixFlags {
GetPosition = 0x01,
GetTangent = 0x02,
GetPositionAndTangent = GetPosition | GetTangent,
}
[Preserve]
internal SKPathMeasure (IntPtr handle, bool owns)
: base (handle, owns)
{
}
public SKPathMeasure ()
: this (SkiaApi.sk_pathmeasure_new (), true)
{
if (Handle == IntPtr.Zero) {
throw new InvalidOperationException ("Unable to create a new SKPathMeasure instance.");
}
}
public SKPathMeasure (SKPath path, bool forceClosed = false, float resScale = 1)
: this (SkiaApi.sk_pathmeasure_new_with_path (path == null ? IntPtr.Zero : path.Handle, forceClosed, resScale), true)
{
if (Handle == IntPtr.Zero) {
throw new InvalidOperationException ("Unable to create a new SKPathMeasure instance.");
}
}
protected override void Dispose (bool disposing)
{
if (Handle != IntPtr.Zero && OwnsHandle) {
SkiaApi.sk_pathmeasure_destroy (Handle);
}
base.Dispose (disposing);
}
public float Length {
get {
return SkiaApi.sk_pathmeasure_get_length (Handle);
}
}
public bool IsClosed {
get {
return SkiaApi.sk_pathmeasure_is_closed (Handle);
}
}
public void SetPath (SKPath path, bool forceClosed)
{
SkiaApi.sk_pathmeasure_set_path (Handle, path == null ? IntPtr.Zero : path.Handle, forceClosed);
}
public bool GetPositionAndTangent (float distance, out SKPoint position, out SKPoint tangent)
{
return SkiaApi.sk_pathmeasure_get_pos_tan (Handle, distance, out position, out tangent);
}
public bool GetPosition (float distance, out SKPoint position)
{
return SkiaApi.sk_pathmeasure_get_pos_tan (Handle, distance, out position, IntPtr.Zero);
}
public bool GetTangent (float distance, out SKPoint tangent)
{
return SkiaApi.sk_pathmeasure_get_pos_tan (Handle, distance, IntPtr.Zero, out tangent);
}
public bool GetMatrix (float distance, out SKMatrix matrix, MatrixFlags flags)
{
return SkiaApi.sk_pathmeasure_get_matrix (Handle, distance, out matrix, flags);
}
public bool GetSegment (float start, float stop, SKPath dst, bool startWithMoveTo)
{
if (dst == null)
throw new ArgumentNullException (nameof (dst));
return SkiaApi.sk_pathmeasure_get_segment (Handle, start, stop, dst.Handle, startWithMoveTo);
}
}
}

Просмотреть файл

@ -43,6 +43,7 @@ using sk_document_t = System.IntPtr;
using sk_colorspace_t = System.IntPtr;
using sk_path_iterator_t = System.IntPtr;
using sk_path_effect_t = System.IntPtr;
using sk_pathmeasure_t = System.IntPtr;
using sk_pixelref_factory_t = System.IntPtr;
using sk_colortable_t = System.IntPtr;
using gr_context_t = System.IntPtr;
@ -504,6 +505,38 @@ namespace SkiaSharp
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static int sk_path_convert_conic_to_quads(ref SKPoint p0, ref SKPoint p1, ref SKPoint p2, float w, [Out] SKPoint[] pts, int pow2);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static sk_pathmeasure_t sk_pathmeasure_new();
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static sk_pathmeasure_t sk_pathmeasure_new_with_path(sk_path_t path, bool forceClosed, float resScale);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_pathmeasure_destroy(sk_pathmeasure_t pathMeasure);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_pathmeasure_set_path(sk_pathmeasure_t pathMeasure, sk_path_t path, bool forceClosed);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static float sk_pathmeasure_get_length(sk_pathmeasure_t pathMeasure);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public extern static bool sk_pathmeasure_get_pos_tan(sk_pathmeasure_t pathMeasure, float distance, out SKPoint position, out SKPoint tangent);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public extern static bool sk_pathmeasure_get_pos_tan(sk_pathmeasure_t pathMeasure, float distance, IntPtr positionZero, out SKPoint tangent);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public extern static bool sk_pathmeasure_get_pos_tan(sk_pathmeasure_t pathMeasure, float distance, out SKPoint position, IntPtr tangentZero);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public extern static bool sk_pathmeasure_get_matrix(sk_pathmeasure_t pathMeasure, float distance, out SKMatrix matrix, SKPathMeasure.MatrixFlags flags);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public extern static bool sk_pathmeasure_get_segment(sk_pathmeasure_t pathMeasure, float start, float stop, sk_path_t dst, bool startWithMoveTo);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public extern static bool sk_pathmeasure_is_closed(sk_pathmeasure_t pathMeasure);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
public extern static bool sk_pathmeasure_next_contour(sk_pathmeasure_t pathMeasure);
// path ops
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]

2
externals/skia поставляемый

@ -1 +1 @@
Subproject commit 801831b60769f40f1fc606feb9ad624c7d12d9e3
Subproject commit b1d9ddd8bacc8464f93583c314799d910b056ab3

Просмотреть файл

@ -0,0 +1,61 @@
using SkiaSharp;
namespace SkiaSharpSample.Samples
{
[Preserve(AllMembers = true)]
public class PathMeasureSample : SampleBase
{
[Preserve]
public PathMeasureSample()
{
}
public override string Title => "Path Measure";
public override SampleCategories Category => SampleCategories.Paths;
protected override void OnDrawSample(SKCanvas canvas, int width, int height)
{
canvas.Clear(SKColors.White);
using (SKPaint paint = new SKPaint())
using (SKPath path = new SKPath())
{
paint.Style = SKPaintStyle.Stroke;
paint.StrokeWidth = 10;
paint.IsAntialias = true;
paint.StrokeCap = SKStrokeCap.Round;
paint.StrokeJoin = SKStrokeJoin.Round;
path.MoveTo(20, 20);
path.LineTo(400, 50);
path.LineTo(80, 100);
path.LineTo(300, 150);
paint.Color = SampleMedia.Colors.XamarinDarkBlue;
canvas.DrawPath(path, paint);
using (var measure = new SKPathMeasure(path, false))
using (var dst = new SKPath())
{
var length = measure.Length;
dst.Reset();
measure.GetSegment(length * 0.05f, length * 0.2f, dst, true);
paint.Color = SampleMedia.Colors.XamarinPurple;
canvas.DrawPath(dst, paint);
dst.Reset();
measure.GetSegment(length * 0.2f, length * 0.8f, dst, true);
paint.Color = SampleMedia.Colors.XamarinGreen;
canvas.DrawPath(dst, paint);
dst.Reset();
measure.GetSegment(length * 0.8f, length * 0.95f, dst, true);
paint.Color = SampleMedia.Colors.XamarinLightBlue;
canvas.DrawPath(dst, paint);
}
}
}
}
}

Просмотреть файл

@ -18,6 +18,7 @@
<Compile Include="$(MSBuildThisFileDirectory)SampleMedia.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Samples\BitmapSubsetDecoderSample.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Samples\ManipulatedBitmapShaderSample.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Samples\PathMeasureSample.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Samples\PathConicToQuadsSample.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Samples\XamagonSample.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Samples\TextSample.cs" />

Просмотреть файл

@ -211,5 +211,28 @@ namespace SkiaSharp.Tests
Assert.AreEqual (14.185303f, tightBounds.Bottom, EPSILON);
}
}
[Test]
public void MeasuringSegementsWorks ()
{
const float EPSILON = 0.000001f;
using (SKPath path = new SKPath ())
{
path.MoveTo (10f, 10f);
path.LineTo (110f, 10f);
var measure = new SKPathMeasure (path);
Assert.AreEqual (100f, measure.Length, EPSILON);
var segment = new SKPath ();
var result = measure.GetSegment (20, 50, segment, true);
Assert.IsTrue (result);
Assert.AreEqual (2, segment.PointCount);
Assert.AreEqual (new SKPoint (30, 10), segment.Points [0]);
Assert.AreEqual (new SKPoint (60, 10), segment.Points [1]);
}
}
}
}