diff --git a/binding/Binding/Definitions.cs b/binding/Binding/Definitions.cs index 482d226b..ccc591df 100644 --- a/binding/Binding/Definitions.cs +++ b/binding/Binding/Definitions.cs @@ -2235,6 +2235,28 @@ namespace SkiaSharp Vulkan, } + [Flags] + public enum GRGlBackendState : UInt32 { + RenderTarget = 1 << 0, + TextureBinding = 1 << 1, + View = 1 << 2, // scissor and viewport + Blend = 1 << 3, + MSAAEnable = 1 << 4, + Vertex = 1 << 5, + Stencil = 1 << 6, + PixelStore = 1 << 7, + Program = 1 << 8, + FixedFunction = 1 << 9, + Misc = 1 << 10, + PathRendering = 1 << 11, + All = 0xffff + } + + [Flags] + public enum GRBackendState : UInt32 { + All = 0xffffffff, + } + [Flags] public enum GRBackendTextureDescFlags { None = 0, @@ -2653,6 +2675,20 @@ namespace SkiaSharp Lcd16, } + public enum SKMatrix44TypeMask { + Identity = 0, + Translate = 0x01, + Scale = 0x02, + Affine = 0x04, + Perspective = 0x08 + } + + public enum SKVertexMode { + Triangles, + TriangleStrip, + TriangleFan, + } + public enum SKImageCachingHint { Allow, Disallow, diff --git a/binding/Binding/GRContext.cs b/binding/Binding/GRContext.cs index a89135f4..63129106 100644 --- a/binding/Binding/GRContext.cs +++ b/binding/Binding/GRContext.cs @@ -78,6 +78,21 @@ namespace SkiaSharp maxResourceBytes = (long)maxResourceBytesPtr; } + public void ResetContext (GRGlBackendState state) + { + ResetContext ((uint) state); + } + + public void ResetContext (GRBackendState state = GRBackendState.All) + { + ResetContext ((uint) state); + } + + public void ResetContext (uint state) + { + SkiaApi.gr_context_reset_context (Handle, state); + } + public void Flush () { SkiaApi.gr_context_flush (Handle); diff --git a/binding/Binding/SKBitmap.cs b/binding/Binding/SKBitmap.cs index 8201694d..4b43b9d7 100644 --- a/binding/Binding/SKBitmap.cs +++ b/binding/Binding/SKBitmap.cs @@ -537,6 +537,7 @@ namespace SkiaSharp public static bool Resize (SKBitmap dst, SKBitmap src, SKBitmapResizeMethod method) { + using (new SKAutoLockPixels (src)) using (var srcPix = src.PeekPixels ()) using (var dstPix = dst.PeekPixels ()) { return SKPixmap.Resize (dstPix, srcPix, method);// && dst.InstallPixels (dstPix); diff --git a/binding/Binding/SKCanvas.cs b/binding/Binding/SKCanvas.cs index 50e5e040..d98c219a 100644 --- a/binding/Binding/SKCanvas.cs +++ b/binding/Binding/SKCanvas.cs @@ -678,6 +678,39 @@ namespace SkiaSharp } public int SaveCount => SkiaApi.sk_canvas_get_save_count (Handle); + + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKColor[] colors, SKPaint paint) + { + DrawVertices (vmode, vertices, null, colors, null, paint); + } + + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKPaint paint) + { + DrawVertices (vmode, vertices, texs, colors, null, paint); + } + + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, UInt16[] indices, SKPaint paint) + { + DrawVertices (vmode, vertices, texs, colors, SKBlendMode.Modulate, indices, paint); + } + + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKBlendMode mode, UInt16[] indices, SKPaint paint) + { + if (vertices == null) + throw new ArgumentNullException (nameof (vertices)); + if (paint == null) + throw new ArgumentNullException (nameof (paint)); + + if (texs != null && vertices.Length != texs.Length) + throw new ArgumentException ("The number of texture coordinates must match the number of vertices.", nameof (texs)); + if (colors != null && vertices.Length != colors.Length) + throw new ArgumentException ("The number of colors must match the number of vertices.", nameof (colors)); + + var vertexCount = vertices.Length; + var indexCount = indices?.Length ?? 0; + + SkiaApi.sk_canvas_draw_vertices (Handle, vmode, vertexCount, vertices, texs, colors, mode, indices, indexCount, paint.Handle); + } } public class SKAutoCanvasRestore : IDisposable diff --git a/binding/Binding/SKColorTable.cs b/binding/Binding/SKColorTable.cs index db8f02e3..3defcff4 100644 --- a/binding/Binding/SKColorTable.cs +++ b/binding/Binding/SKColorTable.cs @@ -61,14 +61,13 @@ namespace SkiaSharp get { var count = Count; - var colors = new SKColor[count]; - var type = typeof(SKColor); - var size = Marshal.SizeOf (type); var pointer = ReadColors (); - for (var i = 0; i < count; i++) { - colors[i] = (SKColor)Marshal.PtrToStructure (pointer + (i * size), type); + + if (count == 0 || pointer == IntPtr.Zero) { + return new SKColor[0]; } - return colors; + + return PtrToStructureArray (pointer, count); } } @@ -83,9 +82,7 @@ namespace SkiaSharp throw new ArgumentOutOfRangeException (nameof (index)); } - var type = typeof(SKColor); - var size = Marshal.SizeOf (type); - return (SKColor)Marshal.PtrToStructure (pointer + (index * size), type); + return PtrToStructure (pointer, index); } } diff --git a/binding/Binding/SKData.cs b/binding/Binding/SKData.cs index 70942f2c..9cef5c0a 100644 --- a/binding/Binding/SKData.cs +++ b/binding/Binding/SKData.cs @@ -44,7 +44,7 @@ namespace SkiaSharp public SKData (IntPtr bytes, ulong length) : this (IntPtr.Zero, true) { - if (Marshal.SizeOf (typeof(IntPtr)) == 4 && length > UInt32.MaxValue) + if (SizeOf () == 4 && length > UInt32.MaxValue) throw new ArgumentOutOfRangeException (nameof (length), "The length exceeds the size of pointers."); Handle = SkiaApi.sk_data_new_with_copy (bytes, (IntPtr) length); if (Handle == IntPtr.Zero) { @@ -67,7 +67,7 @@ namespace SkiaSharp public static SKData FromMallocMemory (IntPtr bytes, ulong length) { - if (Marshal.SizeOf (typeof(IntPtr)) == 4 && length > UInt32.MaxValue) + if (SizeOf () == 4 && length > UInt32.MaxValue) throw new ArgumentOutOfRangeException (nameof (length), "The length exceeds the size of pointers."); return GetObject (SkiaApi.sk_data_new_from_malloc (bytes, (IntPtr) length)); } @@ -80,7 +80,7 @@ namespace SkiaSharp public SKData Subset (ulong offset, ulong length) { - if (Marshal.SizeOf (typeof(IntPtr)) == 4) { + if (SizeOf () == 4) { if (length > UInt32.MaxValue) throw new ArgumentOutOfRangeException (nameof (length), "The length exceeds the size of pointers."); if (offset > UInt32.MaxValue) diff --git a/binding/Binding/SKMatrix.cs b/binding/Binding/SKMatrix.cs index ca5f3517..85f34d50 100644 --- a/binding/Binding/SKMatrix.cs +++ b/binding/Binding/SKMatrix.cs @@ -560,31 +560,49 @@ typeMask = Mask.Scale | Mask.RectStaysRect SkiaApi.sk_3dview_rotate_x_degrees (Handle, degrees); } - public void RotateXRadians (float radians) + public void RotateX (float radians) { SkiaApi.sk_3dview_rotate_x_radians (Handle, radians); } + [Obsolete ("Use RotateX instead.")] + public void RotateXRadians (float radians) + { + RotateX (radians); + } + public void RotateYDegrees (float degrees) { SkiaApi.sk_3dview_rotate_y_degrees (Handle, degrees); } - public void RotateYRadians (float radians) + public void RotateY (float radians) { SkiaApi.sk_3dview_rotate_y_radians (Handle, radians); } + [Obsolete ("Use RotateY instead.")] + public void RotateYRadians (float radians) + { + RotateY (radians); + } + public void RotateZDegrees (float degrees) { SkiaApi.sk_3dview_rotate_z_degrees (Handle, degrees); } - public void RotateZRadians (float radians) + public void RotateZ (float radians) { SkiaApi.sk_3dview_rotate_z_radians (Handle, radians); } + [Obsolete ("Use RotateZ instead.")] + public void RotateZRadians (float radians) + { + RotateZ (radians); + } + public void ApplyToCanvas (SKCanvas canvas) { if (canvas == null) @@ -598,4 +616,419 @@ typeMask = Mask.Scale | Mask.RectStaysRect return SkiaApi.sk_3dview_dot_with_normal (Handle, dx, dy, dz); } } + + public class SKMatrix44 : SKObject + { + protected override void Dispose (bool disposing) + { + if (Handle != IntPtr.Zero && OwnsHandle) { + SkiaApi.sk_matrix44_destroy (Handle); + } + + base.Dispose (disposing); + } + + [Preserve] + internal SKMatrix44 (IntPtr x, bool owns) + : base (x, owns) + { + } + + public SKMatrix44 () + : this (SkiaApi.sk_matrix44_new(), true) + { + if (Handle == IntPtr.Zero) { + throw new InvalidOperationException ("Unable to create a new SKMatrix44 instance."); + } + } + + public SKMatrix44 (SKMatrix44 src) + : this (IntPtr.Zero, true) + { + if (src == null) { + throw new ArgumentNullException (nameof (src)); + } + Handle = SkiaApi.sk_matrix44_new_copy (src.Handle); + if (Handle == IntPtr.Zero) { + throw new InvalidOperationException ("Unable to create a new SKMatrix44 instance."); + } + } + + public SKMatrix44 (SKMatrix44 a, SKMatrix44 b) + : this (IntPtr.Zero, true) + { + if (a == null) { + throw new ArgumentNullException (nameof (a)); + } + if (b == null) { + throw new ArgumentNullException (nameof (b)); + } + + Handle = SkiaApi.sk_matrix44_new_concat (a.Handle, b.Handle); + if (Handle == IntPtr.Zero) { + throw new InvalidOperationException ("Unable to create a new SKMatrix44 instance."); + } + } + + public SKMatrix44 (SKMatrix src) + : this (SkiaApi.sk_matrix44_new_matrix (ref src), true) + { + if (Handle == IntPtr.Zero) { + throw new InvalidOperationException ("Unable to create a new SKMatrix44 instance."); + } + } + + public static SKMatrix44 CreateIdentity () + { + var matrix = new SKMatrix44(); + matrix.SetIdentity (); + return matrix; + } + + public static SKMatrix44 CreateTranslate (float x, float y, float z) + { + var matrix = new SKMatrix44(); + matrix.SetTranslate (x, y, z); + return matrix; + } + + public static SKMatrix44 CreateScale (float x, float y, float z) + { + var matrix = new SKMatrix44(); + matrix.SetScale (x, y, z); + return matrix; + } + + public static SKMatrix44 CreateRotation (float x, float y, float z, float radians) + { + var matrix = new SKMatrix44(); + matrix.SetRotationAbout (x, y, z, radians); + return matrix; + } + + public static SKMatrix44 CreateRotationDegrees (float x, float y, float z, float degrees) + { + var matrix = new SKMatrix44(); + matrix.SetRotationAboutDegrees (x, y, z, degrees); + return matrix; + } + + public static SKMatrix44 FromRowMajor (float [] src) + { + var matrix = new SKMatrix44(); + matrix.SetRowMajor (src); + return matrix; + } + + public static SKMatrix44 FromColumnMajor (float [] src) + { + var matrix = new SKMatrix44(); + matrix.SetColumnMajor (src); + return matrix; + } + + public static bool Equal (SKMatrix44 left, SKMatrix44 right) + { + if (left == null) { + throw new ArgumentNullException (nameof (left)); + } + if (right == null) { + throw new ArgumentNullException (nameof (right)); + } + + return SkiaApi.sk_matrix44_equals (left.Handle, right.Handle); + } + + public SKMatrix Matrix { + get { + SKMatrix matrix; + SkiaApi.sk_matrix44_to_matrix (Handle, out matrix); + return matrix; + } + } + + public SKMatrix44TypeMask Type => SkiaApi.sk_matrix44_get_type (Handle); + + public void SetIdentity () + { + SkiaApi.sk_matrix44_set_identity (Handle); + } + + public float this [int row, int column] { + get { + return SkiaApi.sk_matrix44_get (Handle, row, column); + } + set { + SkiaApi.sk_matrix44_set (Handle, row, column, value); + } + } + + public float [] ToColumnMajor () + { + var dst = new float [16]; + ToColumnMajor (dst); + return dst; + } + + public void ToColumnMajor (float [] dst) + { + if (dst == null) { + throw new ArgumentNullException (nameof (dst)); + } + if (dst.Length != 16) { + throw new ArgumentException ("The destination array must be 16 entries.", nameof (dst)); + } + SkiaApi.sk_matrix44_as_col_major (Handle, dst); + } + + public float [] ToRowMajor () + { + var dst = new float [16]; + ToRowMajor (dst); + return dst; + } + + public void ToRowMajor (float [] dst) + { + if (dst == null) { + throw new ArgumentNullException (nameof (dst)); + } + if (dst.Length != 16) { + throw new ArgumentException ("The destination array must be 16 entries.", nameof (dst)); + } + SkiaApi.sk_matrix44_as_row_major (Handle, dst); + } + + public void SetColumnMajor (float [] src) + { + if (src == null) { + throw new ArgumentNullException (nameof (src)); + } + if (src.Length != 16) { + throw new ArgumentException ("The source array must be 16 entries.", nameof (src)); + } + SkiaApi.sk_matrix44_set_col_major (Handle, src); + } + + public void SetRowMajor (float [] src) + { + if (src == null) { + throw new ArgumentNullException (nameof (src)); + } + if (src.Length != 16) { + throw new ArgumentException ("The source array must be 16 entries.", nameof (src)); + } + SkiaApi.sk_matrix44_set_row_major (Handle, src); + } + + public void SetTranslate (float dx, float dy, float dz) + { + SkiaApi.sk_matrix44_set_translate (Handle, dx, dy, dz); + } + + public void PreTranslate (float dx, float dy, float dz) + { + SkiaApi.sk_matrix44_pre_translate (Handle, dx, dy, dz); + } + + public void PostTranslate (float dx, float dy, float dz) + { + SkiaApi.sk_matrix44_post_translate (Handle, dx, dy, dz); + } + + public void SetScale (float sx, float sy, float sz) + { + SkiaApi.sk_matrix44_set_scale (Handle, sx, sy, sz); + } + + public void PreScale (float sx, float sy, float sz) + { + SkiaApi.sk_matrix44_pre_scale (Handle, sx, sy, sz); + } + + public void PostScale (float sx, float sy, float sz) + { + SkiaApi.sk_matrix44_post_scale (Handle, sx, sy, sz); + } + + public void SetRotationAboutDegrees (float x, float y, float z, float degrees) + { + SkiaApi.sk_matrix44_set_rotate_about_degrees (Handle, x, y, z, degrees); + } + + public void SetRotationAbout (float x, float y, float z, float radians) + { + SkiaApi.sk_matrix44_set_rotate_about_radians (Handle, x, y, z, radians); + } + + public void SetRotationAboutUnit (float x, float y, float z, float radians) + { + SkiaApi.sk_matrix44_set_rotate_about_radians_unit (Handle, x, y, z, radians); + } + + public void SetConcat (SKMatrix44 a, SKMatrix44 b) + { + if (a == null) { + throw new ArgumentNullException (nameof (a)); + } + if (b == null) { + throw new ArgumentNullException (nameof (b)); + } + + SkiaApi.sk_matrix44_set_concat (Handle, a.Handle, b.Handle); + } + + public void PreConcat (SKMatrix44 m) + { + if (m == null) { + throw new ArgumentNullException (nameof (m)); + } + + SkiaApi.sk_matrix44_pre_concat (Handle, m.Handle); + } + + public void PostConcat (SKMatrix44 m) + { + if (m == null) { + throw new ArgumentNullException (nameof (m)); + } + + SkiaApi.sk_matrix44_post_concat (Handle, m.Handle); + } + + public SKMatrix44 Invert () + { + var inverse = new SKMatrix44 (); + if (Invert (inverse)) { + return inverse; + } else { + inverse.Dispose (); + return null; + } + } + + public bool Invert (SKMatrix44 inverse) + { + if (inverse == null) { + throw new ArgumentNullException (nameof (inverse)); + } + + return SkiaApi.sk_matrix44_invert (Handle, inverse.Handle); + } + + public void Transpose () + { + SkiaApi.sk_matrix44_transpose (Handle); + } + + public float [] MapScalars (float x, float y, float z, float w) + { + var srcVector4 = new float [4] { x, y, z, w }; + var dstVector4 = new float [4]; + MapScalars (srcVector4, dstVector4); + return dstVector4; + } + + public float [] MapScalars (float [] srcVector4) + { + var dstVector4 = new float [4]; + MapScalars (srcVector4, dstVector4); + return dstVector4; + } + + public void MapScalars (float [] srcVector4, float [] dstVector4) + { + if (srcVector4 == null) { + throw new ArgumentNullException (nameof (srcVector4)); + } + if (srcVector4.Length != 4) { + throw new ArgumentException ("The source vector array must be 4 entries.", nameof (srcVector4)); + } + if (dstVector4 == null) { + throw new ArgumentNullException (nameof (dstVector4)); + } + if (dstVector4.Length != 4) { + throw new ArgumentException ("The destination vector array must be 4 entries.", nameof (dstVector4)); + } + + SkiaApi.sk_matrix44_map_scalars (Handle, srcVector4, dstVector4); + } + + public SKPoint MapPoint (SKPoint src) + { + return MapPoints (new [] { src }) [0]; + } + + public SKPoint [] MapPoints (SKPoint[] src) + { + if (src == null) { + throw new ArgumentNullException (nameof (src)); + } + + var count = src.Length; + var src2Length = count * 2; + var src4Length = count * 4; + + var src2 = new float [src2Length]; + for (int i = 0, i2 = 0; i < count; i++, i2 += 2) { + src2 [i2] = src [i].X; + src2 [i2 + 1] = src [i].Y; + } + + var dst4 = MapVector2 (src2); + + var dst = new SKPoint [count]; + for (int i = 0, i4 = 0; i < count; i++, i4 += 4) { + dst [i].X = dst4 [i4]; + dst [i].Y = dst4 [i4 + 1]; + } + + return dst; + } + + public float [] MapVector2 (float [] src2) + { + if (src2 == null) { + throw new ArgumentNullException (nameof (src2)); + } + if (src2.Length % 2 != 0) { + throw new ArgumentException ("The source vector array must be a set of pairs.", nameof (src2)); + } + + var dst4 = new float [src2.Length * 2]; + MapVector2 (src2, dst4); + return dst4; + } + + public void MapVector2 (float [] src2, float [] dst4) + { + if (src2 == null) { + throw new ArgumentNullException (nameof (src2)); + } + if (src2.Length % 2 != 0) { + throw new ArgumentException ("The source vector array must be a set of pairs.", nameof (src2)); + } + if (dst4 == null) { + throw new ArgumentNullException (nameof (dst4)); + } + if (dst4.Length % 4 != 0) { + throw new ArgumentException ("The destination vector array must be a set quads.", nameof (dst4)); + } + if (src2.Length / 2 != dst4.Length / 4) { + throw new ArgumentException ("The source vector array must have the same number of pairs as the destination vector array has quads.", nameof (dst4)); + } + + SkiaApi.sk_matrix44_map2 (Handle, src2, src2.Length / 2, dst4); + } + + public bool Preserves2DAxisAlignment (float epsilon) + { + return SkiaApi.sk_matrix44_preserves_2d_axis_alignment (Handle, epsilon); + } + + public double Determinant () + { + return SkiaApi.sk_matrix44_determinant (Handle); + } + } } diff --git a/binding/Binding/SKObject.cs b/binding/Binding/SKObject.cs index b394bcc5..b72f277b 100644 --- a/binding/Binding/SKObject.cs +++ b/binding/Binding/SKObject.cs @@ -12,6 +12,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; namespace SkiaSharp { @@ -174,6 +175,42 @@ namespace SkiaSharp this.RevokeOwnership (); } } + + internal static int SizeOf () + { +#if WINDOWS_UWP || NET_STANDARD + return Marshal.SizeOf (); +#else + return Marshal.SizeOf (typeof (IntPtr)); +#endif + } + + internal T PtrToStructure (IntPtr intPtr) + { +#if WINDOWS_UWP || NET_STANDARD + return Marshal.PtrToStructure (intPtr); +#else + return (T) Marshal.PtrToStructure (intPtr, typeof (T)); +#endif + } + + internal T[] PtrToStructureArray (IntPtr intPtr, int count) + { + var items = new T[count]; + var size = SizeOf (); + for (var i = 0; i < count; i++) { + var newPtr = new IntPtr (intPtr.ToInt64 () + (i * size)); + items[i] = PtrToStructure (newPtr); + } + return items; + } + + internal T PtrToStructure (IntPtr intPtr, int index) + { + var size = SizeOf (); + var newPtr = new IntPtr (intPtr.ToInt64 () + (index * size)); + return PtrToStructure (newPtr); + } } public class SKNativeObject : IDisposable diff --git a/binding/Binding/SKPath.cs b/binding/Binding/SKPath.cs index 8755fa32..dbc1c835 100644 --- a/binding/Binding/SKPath.cs +++ b/binding/Binding/SKPath.cs @@ -10,18 +10,44 @@ using System; namespace SkiaSharp { + public enum SKPathVerb + { + Move, + Line, + Quad, + Conic, + Cubic, + Close, + Done + } + + public enum SKPathAddMode + { + Append, + Extend + } + public class SKPath : SKObject { - public enum Verb { - Move, Line, Quad, Conic, Cubic, Close, Done + [Obsolete ("Use SKPathVerb instead.")] + public enum Verb + { + Move = SKPathVerb.Move, + Line = SKPathVerb.Line, + Quad = SKPathVerb.Quad, + Conic = SKPathVerb.Conic, + Cubic = SKPathVerb.Cubic, + Close = SKPathVerb.Close, + Done = SKPathVerb.Done } - public enum AddMode { - Append, - Extend + [Obsolete ("Use SKPathAddMode instead.")] + public enum AddMode + { + Append = SKPathAddMode.Append, + Extend = SKPathAddMode.Extend } - [Preserve] internal SKPath (IntPtr handle, bool owns) : base (handle, owns) @@ -354,7 +380,13 @@ namespace SkiaSharp SkiaApi.sk_path_transform (Handle, ref matrix); } - public void AddPath (SKPath other, float dx, float dy, AddMode mode = AddMode.Append) + [Obsolete ("Use AddPath(SKPath, float, float, SKPathAddMode) instead.")] + public void AddPath (SKPath other, float dx, float dy, SKPath.AddMode mode) + { + AddPath (other, dx, dy, (SKPathAddMode)mode); + } + + public void AddPath (SKPath other, float dx, float dy, SKPathAddMode mode = SKPathAddMode.Append) { if (other == null) throw new ArgumentNullException (nameof (other)); @@ -362,7 +394,13 @@ namespace SkiaSharp SkiaApi.sk_path_add_path_offset (Handle, other.Handle, dx, dy, mode); } - public void AddPath (SKPath other, ref SKMatrix matrix, AddMode mode = AddMode.Append) + [Obsolete ("Use AddPath(SKPath, ref SKMatrix, SKPathAddMode) instead.")] + public void AddPath (SKPath other, ref SKMatrix matrix, AddMode mode) + { + AddPath (other, ref matrix, (SKPathAddMode)mode); + } + + public void AddPath (SKPath other, ref SKMatrix matrix, SKPathAddMode mode = SKPathAddMode.Append) { if (other == null) throw new ArgumentNullException (nameof (other)); @@ -370,7 +408,13 @@ namespace SkiaSharp SkiaApi.sk_path_add_path_matrix (Handle, other.Handle, ref matrix, mode); } - public void AddPath (SKPath other, AddMode mode = AddMode.Append) + [Obsolete ("Use AddPath(SKPath, SKPathAddMode) instead.")] + public void AddPath (SKPath other, AddMode mode) + { + AddPath (other, (SKPathAddMode)mode); + } + + public void AddPath (SKPath other, SKPathAddMode mode = SKPathAddMode.Append) { if (other == null) throw new ArgumentNullException (nameof (other)); @@ -520,7 +564,7 @@ namespace SkiaSharp base.Dispose (disposing); } - public Verb Next (SKPoint [] points, bool doConsumeDegenerates = true, bool exact = false) + public SKPathVerb Next (SKPoint [] points, bool doConsumeDegenerates = true, bool exact = false) { if (points == null) throw new ArgumentNullException (nameof (points)); @@ -555,7 +599,7 @@ namespace SkiaSharp base.Dispose (disposing); } - public Verb Next (SKPoint [] points) + public SKPathVerb Next (SKPoint [] points) { if (points == null) throw new ArgumentNullException (nameof (points)); @@ -565,7 +609,7 @@ namespace SkiaSharp } public float ConicWeight () => SkiaApi.sk_path_rawiter_conic_weight (Handle); - public Verb Peek () => SkiaApi.sk_path_rawiter_peek (Handle); + public SKPathVerb Peek () => SkiaApi.sk_path_rawiter_peek (Handle); } public class OpBuilder : SKNativeObject diff --git a/binding/Binding/SKPathMeasure.cs b/binding/Binding/SKPathMeasure.cs index 8eba6183..2412446f 100644 --- a/binding/Binding/SKPathMeasure.cs +++ b/binding/Binding/SKPathMeasure.cs @@ -10,13 +10,23 @@ using System; namespace SkiaSharp { + [Flags] + public enum SKPathMeasureMatrixFlags + { + GetPosition = 0x01, + GetTangent = 0x02, + GetPositionAndTangent = GetPosition | GetTangent, + } + public class SKPathMeasure : SKObject { [Flags] - public enum MatrixFlags { - GetPosition = 0x01, - GetTangent = 0x02, - GetPositionAndTangent = GetPosition | GetTangent, + [Obsolete ("Use SKPathMeasureMatrixFlags instead.")] + public enum MatrixFlags + { + GetPosition = SKPathMeasureMatrixFlags.GetPosition, + GetTangent = SKPathMeasureMatrixFlags.GetTangent, + GetPositionAndTangent = SKPathMeasureMatrixFlags.GetPositionAndTangent, } [Preserve] @@ -82,7 +92,13 @@ namespace SkiaSharp return SkiaApi.sk_pathmeasure_get_pos_tan (Handle, distance, IntPtr.Zero, out tangent); } + [Obsolete ("Use GetMatrix(float, out SKMatrix, SKPathMeasureMatrixFlags) instead.")] public bool GetMatrix (float distance, out SKMatrix matrix, MatrixFlags flags) + { + return GetMatrix (distance, out matrix, (SKPathMeasureMatrixFlags)flags); + } + + public bool GetMatrix (float distance, out SKMatrix matrix, SKPathMeasureMatrixFlags flags) { return SkiaApi.sk_pathmeasure_get_matrix (Handle, distance, out matrix, flags); } diff --git a/binding/Binding/SkiaApi.cs b/binding/Binding/SkiaApi.cs index 3beeb6ca..b3317e9a 100755 --- a/binding/Binding/SkiaApi.cs +++ b/binding/Binding/SkiaApi.cs @@ -57,6 +57,7 @@ using sk_wstream_managedstream_t = System.IntPtr; using sk_xmlstreamwriter_t = System.IntPtr; using sk_xmlwriter_t = System.IntPtr; using sk_3dview_t = System.IntPtr; +using sk_matrix44_t = System.IntPtr; namespace SkiaSharp { @@ -241,6 +242,8 @@ namespace SkiaSharp public extern static void sk_canvas_draw_image_lattice(sk_canvas_t t, sk_image_t image, ref SKLatticeInternal lattice, ref SKRect dst, sk_paint_t paint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_canvas_destroy(sk_canvas_t canvas); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_canvas_draw_vertices(sk_canvas_t canvas, SKVertexMode vmode, int vertexCount, [In] SKPoint[] vertices, [In] SKPoint[] texs, [In] SKColor[] colors, SKBlendMode mode, UInt16[] indices, int indexCount, sk_paint_t paint); // Paint @@ -548,11 +551,11 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_path_add_arc(sk_path_t t, ref SKRect rect, float startAngle, float sweepAngle); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_path_add_path_offset (sk_path_t t, sk_path_t other, float dx, float dy, SKPath.AddMode mode); + public extern static void sk_path_add_path_offset (sk_path_t t, sk_path_t other, float dx, float dy, SKPathAddMode mode); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_path_add_path_matrix (sk_path_t t, sk_path_t other, ref SKMatrix matrix, SKPath.AddMode mode); + public extern static void sk_path_add_path_matrix (sk_path_t t, sk_path_t other, ref SKMatrix matrix, SKPathAddMode mode); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_path_add_path (sk_path_t t, sk_path_t other, SKPath.AddMode mode); + public extern static void sk_path_add_path (sk_path_t t, sk_path_t other, SKPathAddMode mode); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_path_add_path_reverse (sk_path_t t, sk_path_t other); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -624,7 +627,7 @@ namespace SkiaSharp 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); + public extern static bool sk_pathmeasure_get_matrix(sk_pathmeasure_t pathMeasure, float distance, out SKMatrix matrix, SKPathMeasureMatrixFlags 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); @@ -661,7 +664,7 @@ namespace SkiaSharp [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_path_iterator_t sk_path_create_iter (sk_path_t path, int forceClose); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static SKPath.Verb sk_path_iter_next (sk_path_iterator_t iterator, [Out] SKPoint [] points, int doConsumeDegenerates, int exact); + public extern static SKPathVerb sk_path_iter_next (sk_path_iterator_t iterator, [Out] SKPoint [] points, int doConsumeDegenerates, int exact); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static float sk_path_iter_conic_weight (sk_path_iterator_t iterator); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -675,9 +678,9 @@ namespace SkiaSharp [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_path_iterator_t sk_path_create_rawiter (sk_path_t path); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static SKPath.Verb sk_path_rawiter_next (sk_path_iterator_t iterator, [Out] SKPoint [] points); + public extern static SKPathVerb sk_path_rawiter_next (sk_path_iterator_t iterator, [Out] SKPoint [] points); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static SKPath.Verb sk_path_rawiter_peek (sk_path_iterator_t iterator); + public extern static SKPathVerb sk_path_rawiter_peek (sk_path_iterator_t iterator); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static float sk_path_rawiter_conic_weight (sk_path_iterator_t iterator); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -1379,6 +1382,80 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static float sk_3dview_dot_with_normal (sk_3dview_t cview, float dx, float dy, float dz); + // Matrix44 + + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_destroy (sk_matrix44_t matrix); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static sk_matrix44_t sk_matrix44_new (); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static sk_matrix44_t sk_matrix44_new_identity (); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static sk_matrix44_t sk_matrix44_new_copy (sk_matrix44_t src); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static sk_matrix44_t sk_matrix44_new_concat (sk_matrix44_t a, sk_matrix44_t b); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static sk_matrix44_t sk_matrix44_new_matrix (ref SKMatrix src); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public extern static bool sk_matrix44_equals (sk_matrix44_t matrix, sk_matrix44_t other); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_to_matrix (sk_matrix44_t matrix, out SKMatrix dst); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static SKMatrix44TypeMask sk_matrix44_get_type (sk_matrix44_t matrix); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_identity (sk_matrix44_t matrix); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static float sk_matrix44_get (sk_matrix44_t matrix, int row, int col); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set (sk_matrix44_t matrix, int row, int col, float value); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_as_col_major (sk_matrix44_t matrix, [Out] float[] dst); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_as_row_major (sk_matrix44_t matrix, [Out] float[] dst); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_col_major (sk_matrix44_t matrix, [In] float[] src); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_row_major (sk_matrix44_t matrix, [In] float[] src); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_translate (sk_matrix44_t matrix, float dx, float dy, float dz); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_pre_translate (sk_matrix44_t matrix, float dx, float dy, float dz); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_post_translate (sk_matrix44_t matrix, float dx, float dy, float dz); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_scale (sk_matrix44_t matrix, float sx, float sy, float sz); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_pre_scale (sk_matrix44_t matrix, float sx, float sy, float sz); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_post_scale (sk_matrix44_t matrix, float sx, float sy, float sz); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_rotate_about_degrees (sk_matrix44_t matrix, float x, float y, float z, float degrees); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_rotate_about_radians (sk_matrix44_t matrix, float x, float y, float z, float radians); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_rotate_about_radians_unit (sk_matrix44_t matrix, float x, float y, float z, float radians); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_set_concat (sk_matrix44_t matrix, sk_matrix44_t a, sk_matrix44_t b); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_pre_concat (sk_matrix44_t matrix, sk_matrix44_t m); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_post_concat (sk_matrix44_t matrix, sk_matrix44_t m); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public extern static bool sk_matrix44_invert (sk_matrix44_t matrix, sk_matrix44_t inverse); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_transpose (sk_matrix44_t matrix); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_map_scalars (sk_matrix44_t matrix, [In] float[] src, float[] dst); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void sk_matrix44_map2 (sk_matrix44_t matrix, [In] float[] src2, int count, float[] dst); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.I1)] + public extern static bool sk_matrix44_preserves_2d_axis_alignment (sk_matrix44_t matrix, float epsilon); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static double sk_matrix44_determinant (sk_matrix44_t matrix); + // Path Effect [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -1435,6 +1512,8 @@ namespace SkiaSharp public extern static int gr_context_get_recommended_sample_count (gr_context_t context, GRPixelConfig config, float dpi); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void gr_context_flush (gr_context_t context); + [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] + public extern static void gr_context_reset_context (gr_context_t context, UInt32 state); // GLInterface diff --git a/binding/SkiaSharp.Desktop/SkiaSharp.Desktop.csproj b/binding/SkiaSharp.Desktop/SkiaSharp.Desktop.csproj index fd05b1ca..3444cb90 100644 --- a/binding/SkiaSharp.Desktop/SkiaSharp.Desktop.csproj +++ b/binding/SkiaSharp.Desktop/SkiaSharp.Desktop.csproj @@ -52,26 +52,26 @@ nuget\runtimes\win7-x64\native\libSkiaSharp.dll - Always + PreserveNewest nuget\runtimes\win7-x86\native\libSkiaSharp.dll - Always + PreserveNewest nuget\runtimes\osx\native\libSkiaSharp.dylib - Always + PreserveNewest - Always + PreserveNewest Designer - Always + PreserveNewest Designer diff --git a/binding/SkiaSharp.Desktop/nuget/build/net45/SkiaSharp.Desktop.targets b/binding/SkiaSharp.Desktop/nuget/build/net45/SkiaSharp.Desktop.targets index d85d9b19..3634b32f 100644 --- a/binding/SkiaSharp.Desktop/nuget/build/net45/SkiaSharp.Desktop.targets +++ b/binding/SkiaSharp.Desktop/nuget/build/net45/SkiaSharp.Desktop.targets @@ -1,4 +1,4 @@ - + diff --git a/build.cake b/build.cake index 81e43576..d9155567 100644 --- a/build.cake +++ b/build.cake @@ -9,6 +9,7 @@ using System.Xml; using System.Xml.Linq; var TARGET = Argument ("t", Argument ("target", Argument ("Target", "Default"))); +var VERBOSITY = (Verbosity) Enum.Parse (typeof(Verbosity), Argument ("v", Argument ("verbosity", Argument ("Verbosity", "Verbose"))), true); var NuGetSources = new [] { MakeAbsolute (Directory ("./output")).FullPath, "https://api.nuget.org/v3/index.json" }; var NugetToolPath = GetToolPath ("nuget.exe"); @@ -26,6 +27,7 @@ var VERSION_PACKAGES = new Dictionary { { "SkiaSharp.Views", "1.56.1" }, { "SkiaSharp.Views.Forms", "1.56.1" }, { "SkiaSharp.Svg", "1.56.1" }, + { "SkiaSharp.Extended", "1.56.1-beta" }, }; string ANDROID_HOME = EnvironmentVariable ("ANDROID_HOME") ?? EnvironmentVariable ("HOME") + "/Library/Developer/Xamarin/android-sdk-macosx"; @@ -75,6 +77,7 @@ Task ("libs") ReplaceTextInFiles ("./source/SkiaSharp.Views/SkiaSharp.Views.Shared/Properties/SkiaSharpViewsAssemblyInfo.cs", "{GIT_SHA}", sha); ReplaceTextInFiles ("./source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/Properties/SkiaSharpViewsFormsAssemblyInfo.cs", "{GIT_SHA}", sha); ReplaceTextInFiles ("./source/SkiaSharp.Svg/SkiaSharp.Svg.Shared/Properties/SkiaSharpSvgAssemblyInfo.cs", "{GIT_SHA}", sha); + ReplaceTextInFiles ("./source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/Properties/SkiaSharpExtendedAssemblyInfo.cs", "{GIT_SHA}", sha); } // create all the directories @@ -94,6 +97,7 @@ Task ("libs") RunNuGetRestore ("binding/SkiaSharp.Windows.sln"); DotNetBuild ("binding/SkiaSharp.Windows.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); // copy build output @@ -110,6 +114,7 @@ Task ("libs") RunNuGetRestore ("./source/SkiaSharpSource.Windows.sln"); DotNetBuild ("./source/SkiaSharpSource.Windows.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); // copy the managed views @@ -121,6 +126,9 @@ Task ("libs") // copy SVG CopyFileToDirectory ("./source/SkiaSharp.Svg/SkiaSharp.Svg/bin/Release/SkiaSharp.Svg.dll", "./output/portable/"); + + // copy Extended + CopyFileToDirectory ("./source/SkiaSharp.Extended/SkiaSharp.Extended/bin/Release/SkiaSharp.Extended.dll", "./output/portable/"); } if (IsRunningOnMac ()) { @@ -128,6 +136,7 @@ Task ("libs") RunNuGetRestore ("binding/SkiaSharp.Mac.sln"); DotNetBuild ("binding/SkiaSharp.Mac.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); // copy build output @@ -145,6 +154,7 @@ Task ("libs") RunNuGetRestore ("./source/SkiaSharpSource.Mac.sln"); DotNetBuild ("./source/SkiaSharpSource.Mac.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); // copy other outputs @@ -158,6 +168,9 @@ Task ("libs") // copy SVG CopyFileToDirectory ("./source/SkiaSharp.Svg/SkiaSharp.Svg/bin/Release/SkiaSharp.Svg.dll", "./output/portable/"); + + // copy Extended + CopyFileToDirectory ("./source/SkiaSharp.Extended/SkiaSharp.Extended/bin/Release/SkiaSharp.Extended.dll", "./output/portable/"); } if (IsRunningOnLinux ()) { @@ -165,6 +178,7 @@ Task ("libs") RunNuGetRestore ("binding/SkiaSharp.Linux.sln"); DotNetBuild ("binding/SkiaSharp.Linux.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); // copy build output @@ -174,10 +188,14 @@ Task ("libs") RunNuGetRestore ("./source/SkiaSharpSource.Linux.sln"); DotNetBuild ("./source/SkiaSharpSource.Linux.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); // copy SVG CopyFileToDirectory ("./source/SkiaSharp.Svg/SkiaSharp.Svg/bin/Release/SkiaSharp.Svg.dll", "./output/portable/"); + + // copy Extended + CopyFileToDirectory ("./source/SkiaSharp.Extended/SkiaSharp.Extended/bin/Release/SkiaSharp.Extended.dll", "./output/portable/"); } // .NET Standard / .NET Core @@ -185,16 +203,44 @@ Task ("libs") RunDotNetCoreRestore ("binding/SkiaSharp.NetStandard"); DotNetBuild ("binding/SkiaSharp.NetStandard.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); // copy build output CopyFileToDirectory ("./binding/SkiaSharp.NetStandard/bin/Release/SkiaSharp.dll", "./output/netstandard/"); // build other source RunDotNetCoreRestore ("source/SkiaSharp.Svg/SkiaSharp.Svg.NetStandard"); + RunDotNetCoreRestore ("source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard"); DotNetBuild ("./source/SkiaSharpSource.NetStandard.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); // copy SVG CopyFileToDirectory ("./source/SkiaSharp.Svg/SkiaSharp.Svg.NetStandard/bin/Release/SkiaSharp.Svg.dll", "./output/netstandard/"); + // copy Extended + CopyFileToDirectory ("./source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/bin/Release/SkiaSharp.Extended.dll", "./output/netstandard/"); +}); + +Task ("workbooks") + .IsDependentOn ("externals") + .IsDependentOn ("libs") + .Does (() => +{ + // the dir + if (!DirectoryExists ("./output/workbooks/")) CreateDirectory ("./output/workbooks/"); + + // the managed bits + CopyFileToDirectory ("./binding/SkiaSharp.Desktop/bin/Release/nuget/build/net45/SkiaSharp.dll.config", "./output/workbooks/"); + CopyFileToDirectory ("./binding/SkiaSharp.NetStandard/bin/Release/SkiaSharp.dll", "./output/workbooks/"); + CopyFileToDirectory ("./source/SkiaSharp.Svg/SkiaSharp.Svg.NetStandard/bin/Release/SkiaSharp.Svg.dll", "./output/workbooks/"); + CopyFileToDirectory ("./source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/bin/Release/SkiaSharp.Extended.dll", "./output/workbooks/"); + + // the native bits + if (IsRunningOnWindows ()) { + CopyFileToDirectory ("./native-builds/lib/windows/x64/libSkiaSharp.dll", "./output/workbooks/"); + } + if (IsRunningOnMac ()) { + CopyFileToDirectory ("./native-builds/lib/osx/libSkiaSharp.dylib", "./output/workbooks/"); + } }); //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -215,11 +261,13 @@ Task ("tests") DotNetBuild ("./tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { "x86" }; + c.Verbosity = VERBOSITY; }); RunTests("./tests/SkiaSharp.Desktop.Tests/bin/x86/Release/SkiaSharp.Desktop.Tests.dll"); DotNetBuild ("./tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { "x64" }; + c.Verbosity = VERBOSITY; }); RunTests("./tests/SkiaSharp.Desktop.Tests/bin/x64/Release/SkiaSharp.Desktop.Tests.dll"); } @@ -227,6 +275,7 @@ Task ("tests") if (IsRunningOnMac ()) { DotNetBuild ("./tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); RunTests("./tests/SkiaSharp.Desktop.Tests/bin/AnyCPU/Release/SkiaSharp.Desktop.Tests.dll"); } @@ -261,16 +310,19 @@ Task ("samples") RunNuGetRestore ("./samples/MacSample/MacSample.sln"); DotNetBuild ("./samples/MacSample/MacSample.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); RunNuGetRestore ("./samples/FormsSample/FormsSample.Mac.sln"); DotNetBuild ("./samples/FormsSample/FormsSample.Mac.sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { "iPhone" }; + c.Verbosity = VERBOSITY; }); RunNuGetRestore ("./samples/TvSample/TvSample.sln"); DotNetBuild ("./samples/TvSample/TvSample.sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { "iPhoneSimulator" }; + c.Verbosity = VERBOSITY; }); } @@ -279,19 +331,23 @@ Task ("samples") DotNetBuild ("./samples/WPFSample/WPFSample.sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { "x86" }; + c.Verbosity = VERBOSITY; }); RunNuGetRestore ("./samples/UWPSample/UWPSample.sln"); DotNetBuild ("./samples/UWPSample/UWPSample.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); RunNuGetRestore ("./samples/FormsSample/FormsSample.Windows.sln"); DotNetBuild ("./samples/FormsSample/FormsSample.Windows.sln", c => { c.Configuration = "Release"; + c.Verbosity = VERBOSITY; }); RunNuGetRestore ("./samples/WindowsSample/WindowsSample.sln"); DotNetBuild ("./samples/WindowsSample/WindowsSample.sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { "x86" }; + c.Verbosity = VERBOSITY; }); } }); @@ -368,6 +424,7 @@ Task ("update-docs") // types aren't needed here DotNetBuild ("./externals/Windows.Foundation.UniversalApiContract/Windows.Foundation.UniversalApiContract.csproj", c => { c.Verbosity = Verbosity.Quiet; + c.Verbosity = VERBOSITY; }); refs = refs.Union (new DirectoryPath [] { "./externals/Windows.Foundation.UniversalApiContract/bin/Release", @@ -493,6 +550,8 @@ Task ("nuget") } // SVG is a PCL PackageNuGet ("./nuget/SkiaSharp.Svg.nuspec", "./output/"); + // Extended is a PCL + PackageNuGet ("./nuget/SkiaSharp.Extended.nuspec", "./output/"); }); //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -575,6 +634,9 @@ Task ("set-versions") UpdateAssemblyInfo ( "./source/SkiaSharp.Svg/SkiaSharp.Svg.Shared/Properties/SkiaSharpSvgAssemblyInfo.cs", VERSION_ASSEMBLY, VERSION_FILE, sha); + UpdateAssemblyInfo ( + "./source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/Properties/SkiaSharpExtendedAssemblyInfo.cs", + VERSION_ASSEMBLY, VERSION_FILE, sha); }); //////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/cake/BuildExternals.cake b/cake/BuildExternals.cake index a01469c4..6e858a6e 100644 --- a/cake/BuildExternals.cake +++ b/cake/BuildExternals.cake @@ -80,6 +80,7 @@ Task ("externals-genapi") DotNetBuild ("binding/SkiaSharp.Generic.sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { "\"Any CPU\"" }; + c.Verbosity = VERBOSITY; }); // generate the PCL @@ -167,6 +168,7 @@ Task ("externals-windows") DotNetBuild ("native-builds/libSkiaSharp_windows/libSkiaSharp_" + dir + ".sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { platform }; + c.Verbosity = VERBOSITY; }); if (!DirectoryExists ("native-builds/lib/windows/" + dir)) CreateDirectory ("native-builds/lib/windows/" + dir); CopyFileToDirectory ("native-builds/libSkiaSharp_windows/bin/" + platform + "/Release/libSkiaSharp.lib", "native-builds/lib/windows/" + dir); @@ -204,6 +206,7 @@ Task ("externals-uwp") DotNetBuild ("native-builds/libSkiaSharp_uwp/libSkiaSharp_" + arch + ".sln", c => { c.Configuration = "Release"; c.Properties ["Platform"] = new [] { platform }; + c.Verbosity = VERBOSITY; }); if (!DirectoryExists ("native-builds/lib/uwp/" + arch)) CreateDirectory ("native-builds/lib/uwp/" + arch); CopyFileToDirectory ("native-builds/libSkiaSharp_uwp/bin/" + platform + "/Release/libSkiaSharp.lib", "native-builds/lib/uwp/" + arch); diff --git a/cake/UtilsManaged.cake b/cake/UtilsManaged.cake index 101e212d..ec35fb96 100644 --- a/cake/UtilsManaged.cake +++ b/cake/UtilsManaged.cake @@ -1,11 +1,30 @@ using System.Runtime.InteropServices; +var VERBOSITY_NUGET = NuGetVerbosity.Detailed; +var VERBOSITY_NUGETCORE = DotNetCoreRestoreVerbosity.Verbose; +switch (VERBOSITY) { + case Verbosity.Quiet: + case Verbosity.Minimal: + VERBOSITY_NUGET = NuGetVerbosity.Quiet; + VERBOSITY_NUGETCORE = DotNetCoreRestoreVerbosity.Minimal; + break; + case Verbosity.Normal: + VERBOSITY_NUGET = NuGetVerbosity.Normal; + VERBOSITY_NUGETCORE = DotNetCoreRestoreVerbosity.Warning; + break; + case Verbosity.Verbose: + case Verbosity.Diagnostic: + VERBOSITY_NUGET = NuGetVerbosity.Detailed; + VERBOSITY_NUGETCORE = DotNetCoreRestoreVerbosity.Verbose; + break; +}; + var RunNuGetRestore = new Action ((solution) => { NuGetRestore (solution, new NuGetRestoreSettings { ToolPath = NugetToolPath, Source = NuGetSources, - Verbosity = NuGetVerbosity.Detailed + Verbosity = VERBOSITY_NUGET }); }); @@ -13,7 +32,7 @@ var RunDotNetCoreRestore = new Action ((solution) => { DotNetCoreRestore (solution, new DotNetCoreRestoreSettings { Sources = NuGetSources, - Verbosity = DotNetCoreRestoreVerbosity.Verbose + Verbosity = VERBOSITY_NUGETCORE }); }); @@ -24,7 +43,7 @@ var PackageNuGet = new Action ((nuspecPath, outputPath) } NuGetPack (nuspecPath, new NuGetPackSettings { - Verbosity = NuGetVerbosity.Detailed, + Verbosity = VERBOSITY_NUGET, OutputDirectory = outputPath, BasePath = "./", ToolPath = NugetToolPath diff --git a/nuget/SkiaSharp.Extended.nuspec b/nuget/SkiaSharp.Extended.nuspec new file mode 100644 index 00000000..8d9ea26a --- /dev/null +++ b/nuget/SkiaSharp.Extended.nuspec @@ -0,0 +1,23 @@ + + + + SkiaSharp.Extended + SkiaSharp.Extended + 1.56.1-beta + Xamarin Inc. + Xamarin Inc. + false + This package adds many additional features and utilities for use with SkiaSharp. + Copyright (c) Xamarin Inc. 2016 + https://github.com/mono/SkiaSharp/blob/master/LICENSE.md + https://github.com/mono/SkiaSharp + https://cdn.rawgit.com/mono/SkiaSharp/v1.53.0/images/skia_256x256.png + + + + + + + + + \ No newline at end of file diff --git a/samples/SkiaSharpSample.Shared/Samples/DrawVerticesSample.cs b/samples/SkiaSharpSample.Shared/Samples/DrawVerticesSample.cs new file mode 100644 index 00000000..a759b5c3 --- /dev/null +++ b/samples/SkiaSharpSample.Shared/Samples/DrawVerticesSample.cs @@ -0,0 +1,33 @@ +using System; + +using SkiaSharp; + +namespace SkiaSharpSample.Samples +{ + [Preserve(AllMembers = true)] + public class DrawVerticesSample : SampleBase + { + [Preserve] + public DrawVerticesSample() + { + } + + public override string Title => "Draw Vertices"; + + public override SampleCategories Category => SampleCategories.General; + + protected override void OnDrawSample(SKCanvas canvas, int width, int height) + { + canvas.Clear(SKColors.White); + var paint = new SKPaint + { + IsAntialias = true + }; + + var vertices = new[] { new SKPoint(110, 20), new SKPoint(160, 200), new SKPoint(10, 200) }; + var colors = new[] { SKColors.Red, SKColors.Green, SKColors.Blue }; + + canvas.DrawVertices(SKVertexMode.Triangles, vertices, colors, paint); + } + } +} diff --git a/samples/SkiaSharpSample.Shared/SkiaSharpSample.Shared.projitems b/samples/SkiaSharpSample.Shared/SkiaSharpSample.Shared.projitems index 3a8301d6..cc13acaf 100644 --- a/samples/SkiaSharpSample.Shared/SkiaSharpSample.Shared.projitems +++ b/samples/SkiaSharpSample.Shared/SkiaSharpSample.Shared.projitems @@ -17,6 +17,7 @@ + diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/Properties/AssemblyInfo.cs b/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/SkiaSharp.Extended.NetStandard.csproj b/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/SkiaSharp.Extended.NetStandard.csproj new file mode 100644 index 00000000..560e2135 --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/SkiaSharp.Extended.NetStandard.csproj @@ -0,0 +1,59 @@ + + + + + 14.0 + Debug + AnyCPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2} + Library + Properties + SkiaSharp.Extended + SkiaSharp.Extended + en-US + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + v5.0 + true + ..\..\..\mono.snk + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + {4e0924f8-d546-4428-9412-4b9411fba5ff} + SkiaSharp.NetStandard + + + + + + \ No newline at end of file diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/project.json b/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/project.json new file mode 100644 index 00000000..5196e931 --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended.NetStandard/project.json @@ -0,0 +1,9 @@ +{ + "supports": {}, + "dependencies": { + "NETStandard.Library": "1.6.0" + }, + "frameworks": { + "netstandard1.3": {} + } +} \ No newline at end of file diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/Properties/SkiaSharpExtendedAssemblyInfo.cs b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/Properties/SkiaSharpExtendedAssemblyInfo.cs new file mode 100644 index 00000000..8a6899ee --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/Properties/SkiaSharpExtendedAssemblyInfo.cs @@ -0,0 +1,17 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by Cake. +// +//------------------------------------------------------------------------------ +using System.Reflection; + +[assembly: AssemblyTitle("SkiaSharp.Extended")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SkiaSharp.Extended")] +[assembly: AssemblyVersion("1.56.0.0")] +[assembly: AssemblyFileVersion("1.56.1.0")] +[assembly: AssemblyInformationalVersion("1.56.1.0-{GIT_SHA}")] +[assembly: AssemblyCopyright("Xamarin Inc.")] +[assembly: AssemblyTrademark("")] + diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SKGeometry.cs b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SKGeometry.cs new file mode 100644 index 00000000..d24a77b5 --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SKGeometry.cs @@ -0,0 +1,194 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SkiaSharp.Extended +{ + public static class SKGeometry + { + public const float PI = (float)Math.PI; + + private const float UprightAngle = PI / 2f; + private const float TotalAngle = 2f * PI; + + public static SKPoint GetCirclePoint(float r, float angle) + { + return new SKPoint(r * (float)Math.Cos(angle), r * (float)Math.Sin(angle)); + } + + public static SKPath CreateSectorPath(float start, float end, float outerRadius, float innerRadius = 0.0f, float margin = 0.0f, float explodeDistance = 0.0f, SKPathDirection direction = SKPathDirection.Clockwise) + { + var path = new SKPath(); + + // if the sector has no size, then it has no path + if (start == end) + { + return path; + } + + // the the sector is a full circle, then do that + if (end - start == 1.0f) + { + path.AddCircle(0, 0, outerRadius, direction); + path.AddCircle(0, 0, innerRadius, direction); + path.FillType = SKPathFillType.EvenOdd; + return path; + } + + // calculate the angles + var startAngle = TotalAngle * start - UprightAngle; + var endAngle = TotalAngle * end - UprightAngle; + var large = endAngle - startAngle > PI ? SKPathArcSize.Large : SKPathArcSize.Small; + var sectorCenterAngle = (endAngle - startAngle) / 2f + startAngle; + + // get the radius bits + var cectorCenterRadius = (outerRadius - innerRadius) / 2f + innerRadius; + + // move explosion around 90 degrees, since matrix use down as 0 + var explosionMatrix = SKMatrix.MakeRotation(sectorCenterAngle - (PI / 2f)); + var offset = explosionMatrix.MapPoint(new SKPoint(0, explodeDistance)); + + // calculate the angle for the margins + margin = direction == SKPathDirection.Clockwise ? margin : -margin; + var offsetR = outerRadius == 0 ? 0 : ((margin / (TotalAngle * outerRadius)) * TotalAngle); + var offsetr = innerRadius == 0 ? 0 : ((margin / (TotalAngle * innerRadius)) * TotalAngle); + + // get the points + var a = GetCirclePoint(outerRadius, startAngle + offsetR) + offset; + var b = GetCirclePoint(outerRadius, endAngle - offsetR) + offset; + var c = GetCirclePoint(innerRadius, endAngle - offsetr) + offset; + var d = GetCirclePoint(innerRadius, startAngle + offsetr) + offset; + + // add the points to the path + path.MoveTo(a); + path.ArcTo(outerRadius, outerRadius, 0, large, direction, b.X, b.Y); + path.LineTo(c); + if (innerRadius == 0.0f) + { + // take a short cut + path.LineTo(d); + } + else + { + var reverseDirection = direction == SKPathDirection.Clockwise ? SKPathDirection.CounterClockwise : SKPathDirection.Clockwise; + path.ArcTo(innerRadius, innerRadius, 0, large, reverseDirection, d.X, d.Y); + } + path.Close(); + + return path; + } + + public static SKPath CreatePiePath(IEnumerable sectorSizes, float outerRadius, float innerRadius = 0.0f, float spacing = 0.0f, float explodeDistance = 0.0f, SKPathDirection direction = SKPathDirection.Clockwise) + { + var path = new SKPath(); + + float cursor = 0; + var sum = sectorSizes.Sum(); + foreach (var sectorSize in sectorSizes) + { + var sector = CreateSectorPath(cursor, cursor + sectorSize, outerRadius, innerRadius, spacing / 2f, explodeDistance, direction); + + cursor += sectorSize; + + path.AddPath(sector, SKPath.AddMode.Append); + } + + return path; + } + + public static SKPath CreateSquarePath(float side, SKPathDirection direction = SKPathDirection.Clockwise) + { + return CreateRectanglePath(side, side, direction); + } + + public static SKPath CreateRectanglePath(float width, float height, SKPathDirection direction = SKPathDirection.Clockwise) + { + var path = new SKPath(); + path.AddRect(new SKRect(width / -2, height / -2, width / 2, height / 2), direction); + path.Close(); + return path; + } + + public static SKPath CreateTrianglePath(float width, float height, SKPathDirection direction = SKPathDirection.Clockwise) + { + var path = new SKPath(); + path.MoveTo(0, height / -2); + if (direction == SKPathDirection.Clockwise) + { + path.LineTo(width / -2, height / 2); + path.LineTo(width / 2, height / 2); + } + else + { + path.LineTo(width / 2, height / 2); + path.LineTo(width / -2, height / 2); + } + path.Close(); + return path; + } + + public static SKPath CreateTrianglePath(float radius, SKPathDirection direction = SKPathDirection.Clockwise) + { + return CreateRegularPolygonPath(radius, 3, direction); + } + + public static SKPath CreateRegularPolygonPath(float radius, int points, SKPathDirection direction = SKPathDirection.Clockwise) + { + var path = new SKPath(); + + float stepAngle = TotalAngle / points; + if (direction == SKPathDirection.CounterClockwise) + { + stepAngle = -stepAngle; + } + + for (int p = 0; p < points; p++) + { + float angle = stepAngle * p - UprightAngle; + float x = radius * (float)Math.Cos(angle); + float y = radius * (float)Math.Sin(angle); + + if (p == 0) + path.MoveTo(x, y); + else + path.LineTo(x, y); + } + + path.Close(); + return path; + } + + public static SKPath CreateRegularStarPath(float outerRadius, float innerRadius, int points, SKPathDirection direction = SKPathDirection.Clockwise) + { + var path = new SKPath(); + + bool isInner = false; + points *= 2; + + float stepAngle = TotalAngle / points; + if (direction == SKPathDirection.CounterClockwise) + { + stepAngle = -stepAngle; + } + + for (int p = 0; p < points; p++) + { + float radius = isInner ? innerRadius : outerRadius; + + float angle = stepAngle * p - UprightAngle; + float x = radius * (float)Math.Cos(angle); + float y = radius * (float)Math.Sin(angle); + + if (p == 0) + path.MoveTo(x, y); + else + path.LineTo(x, y); + + isInner = !isInner; + } + + path.Close(); + return path; + } + } +} diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SKGeometryExtensions.cs b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SKGeometryExtensions.cs new file mode 100644 index 00000000..209d19b6 --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SKGeometryExtensions.cs @@ -0,0 +1,47 @@ +namespace SkiaSharp.Extended +{ + public static class SKGeometryExtensions + { + public static void DrawSquare(this SKCanvas canvas, float cx, float cy, float side, SKPaint paint) + { + var path = SKGeometry.CreateSquarePath(side); + path.Offset(cx, cy); + canvas.DrawPath(path, paint); + } + + public static void DrawRect(this SKCanvas canvas, float cx, float cy, float width, float height, SKPaint paint) + { + var path = SKGeometry.CreateRectanglePath(width, height); + path.Offset(cx, cy); + canvas.DrawPath(path, paint); + } + + public static void DrawTriangle(this SKCanvas canvas, float cx, float cy, float width, float height, SKPaint paint) + { + var path = SKGeometry.CreateTrianglePath(width, height); + path.Offset(cx, cy); + canvas.DrawPath(path, paint); + } + + public static void DrawTriangle(this SKCanvas canvas, float cx, float cy, float radius, SKPaint paint) + { + var path = SKGeometry.CreateTrianglePath(radius); + path.Offset(cx, cy); + canvas.DrawPath(path, paint); + } + + public static void DrawRegularPolygon(this SKCanvas canvas, float cx, float cy, float radius, int points, SKPaint paint) + { + var path = SKGeometry.CreateRegularPolygonPath(radius, points); + path.Offset(cx, cy); + canvas.DrawPath(path, paint); + } + + public static void DrawStar(this SKCanvas canvas, float cx, float cy, float outerRadius, float innerRadius, int points, SKPaint paint) + { + var path = SKGeometry.CreateRegularStarPath(outerRadius, innerRadius, points); + path.Offset(cx, cy); + canvas.DrawPath(path, paint); + } + } +} diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SkiaSharp.Extended.Shared.projitems b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SkiaSharp.Extended.Shared.projitems new file mode 100644 index 00000000..52dfc7e3 --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SkiaSharp.Extended.Shared.projitems @@ -0,0 +1,16 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + e3290ce6-0ada-486b-9bab-8bcf07f9be45 + + + SkiaSharp.Extended + + + + + + + \ No newline at end of file diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SkiaSharp.Extended.Shared.shproj b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SkiaSharp.Extended.Shared.shproj new file mode 100644 index 00000000..87c7fe0e --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended.Shared/SkiaSharp.Extended.Shared.shproj @@ -0,0 +1,13 @@ + + + + e3290ce6-0ada-486b-9bab-8bcf07f9be45 + 14.0 + + + + + + + + diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended/Properties/AssemblyInfo.cs b/source/SkiaSharp.Extended/SkiaSharp.Extended/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..5f282702 --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended/Properties/AssemblyInfo.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/source/SkiaSharp.Extended/SkiaSharp.Extended/SkiaSharp.Extended.csproj b/source/SkiaSharp.Extended/SkiaSharp.Extended/SkiaSharp.Extended.csproj new file mode 100644 index 00000000..a105b59d --- /dev/null +++ b/source/SkiaSharp.Extended/SkiaSharp.Extended/SkiaSharp.Extended.csproj @@ -0,0 +1,57 @@ + + + + + 14.0 + Debug + AnyCPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19} + Library + Properties + SkiaSharp.Extended + SkiaSharp.Extended + en-US + 512 + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Profile78 + v4.5 + true + ..\..\..\mono.snk + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + {7aa90628-2fdd-4585-af2f-cc51cfa8b52a} + SkiaSharp.Portable + + + + + + + + + \ No newline at end of file diff --git a/source/SkiaSharp.Svg/SkiaSharp.Svg.Shared/SKSvg.cs b/source/SkiaSharp.Svg/SkiaSharp.Svg.Shared/SKSvg.cs index 58a70d1b..0a80abc7 100644 --- a/source/SkiaSharp.Svg/SkiaSharp.Svg.Shared/SKSvg.cs +++ b/source/SkiaSharp.Svg/SkiaSharp.Svg.Shared/SKSvg.cs @@ -128,8 +128,9 @@ namespace SkiaSharp using (var recorder = new SKPictureRecorder()) using (var canvas = recorder.BeginRecording(SKRect.Create(CanvasSize))) { + // if there is no viewbox, then we don't do anything, otherwise // scale the SVG dimensions to fit inside the user dimensions - if (ViewBox.Width != CanvasSize.Width || ViewBox.Height != CanvasSize.Height) + if (!ViewBox.IsEmpty && (ViewBox.Width != CanvasSize.Width || ViewBox.Height != CanvasSize.Height)) { if (preserveAspectRatio == "none") { @@ -148,6 +149,12 @@ namespace SkiaSharp // translate the canvas by the viewBox origin canvas.Translate(-ViewBox.Left, -ViewBox.Top); + // if the viewbox was specified, then crop to that + if (!ViewBox.IsEmpty) + { + canvas.ClipRect(ViewBox); + } + LoadElements(svg.Elements(), canvas); Picture = recorder.EndRecording(); diff --git a/source/SkiaSharpSource.Linux.sln b/source/SkiaSharpSource.Linux.sln index 332a6fd6..30623814 100644 --- a/source/SkiaSharpSource.Linux.sln +++ b/source/SkiaSharpSource.Linux.sln @@ -15,7 +15,20 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Svg", "SkiaSharp. EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Svg.Shared", "SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.shproj", "{B201E760-DB91-485C-A99A-814BDED90BDB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Extended", "SkiaSharp.Extended", "{CD6A8CE6-9521-4ADB-B49C-77E8B2A8441F}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Extended.Shared", "SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.shproj", "{E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Extended", "SkiaSharp.Extended\SkiaSharp.Extended\SkiaSharp.Extended.csproj", "{FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}" +EndProject Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{04c4399a-6740-4733-b6b7-f968232a76c8}*SharedItemsImports = 4 + ..\binding\Binding\Binding.projitems*{9c502b9a-25d4-473f-89bd-5a13dde16354}*SharedItemsImports = 13 + SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{b201e760-db91-485c-a99a-814bded90bdb}*SharedItemsImports = 13 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{e3290ce6-0ada-486b-9bab-8bcf07f9be45}*SharedItemsImports = 13 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{fea1fec9-950c-46c0-9eb0-a515e0ab8f19}*SharedItemsImports = 4 + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU @@ -29,6 +42,10 @@ Global {04C4399A-6740-4733-B6B7-F968232A76C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|Any CPU.Build.0 = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -38,5 +55,7 @@ Global {7AA90628-2FDD-4585-AF2F-CC51CFA8B52A} = {C335869B-7CC8-4239-B4A5-8031AA9758D3} {04C4399A-6740-4733-B6B7-F968232A76C8} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} {B201E760-DB91-485C-A99A-814BDED90BDB} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} + {E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45} = {CD6A8CE6-9521-4ADB-B49C-77E8B2A8441F} + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19} = {CD6A8CE6-9521-4ADB-B49C-77E8B2A8441F} EndGlobalSection EndGlobal diff --git a/source/SkiaSharpSource.Mac.sln b/source/SkiaSharpSource.Mac.sln index 81bf2cad..7140fc16 100644 --- a/source/SkiaSharpSource.Mac.sln +++ b/source/SkiaSharpSource.Mac.sln @@ -49,6 +49,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Views.Forms", "Sk EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Svg.Shared", "SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.shproj", "{B201E760-DB91-485C-A99A-814BDED90BDB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Extras", "SkiaSharp.Extras", "{8570A43F-3AD6-4EC4-8CD1-92EF9AC23916}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Extended.Shared", "SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.shproj", "{E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Extended", "SkiaSharp.Extended\SkiaSharp.Extended\SkiaSharp.Extended.csproj", "{FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{04c4399a-6740-4733-b6b7-f968232a76c8}*SharedItemsImports = 4 @@ -70,9 +76,11 @@ Global SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{b201e760-db91-485c-a99a-814bded90bdb}*SharedItemsImports = 13 ..\Binding\Binding\Binding.projitems*{c737dc80-5b71-4b26-a2dc-da30421788b0}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.Apple\SkiaSharp.Views.Apple.projitems*{cbca14e7-96c9-4697-909c-19b1ef7298f7}*SharedItemsImports = 13 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{e3290ce6-0ada-486b-9bab-8bcf07f9be45}*SharedItemsImports = 13 SkiaSharp.Views\SkiaSharp.Views.AppleiOS\SkiaSharp.Views.AppleiOS.projitems*{e5973829-6c8b-43e4-b81b-c8492df26c90}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.Apple\SkiaSharp.Views.Apple.projitems*{e5973829-6c8b-43e4-b81b-c8492df26c90}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.Shared\SkiaSharp.Views.Shared.projitems*{e5973829-6c8b-43e4-b81b-c8492df26c90}*SharedItemsImports = 4 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{fea1fec9-950c-46c0-9eb0-a515e0ab8f19}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.AppleiOS\SkiaSharp.Views.AppleiOS.projitems*{ff4c9f9f-7a6a-44d1-8338-d30e39e4e9d4}*SharedItemsImports = 13 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -132,6 +140,10 @@ Global {04C4399A-6740-4733-B6B7-F968232A76C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|Any CPU.Build.0 = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -156,5 +168,7 @@ Global {7AA90628-2FDD-4585-AF2F-CC51CFA8B52A} = {C335869B-7CC8-4239-B4A5-8031AA9758D3} {04C4399A-6740-4733-B6B7-F968232A76C8} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} {B201E760-DB91-485C-A99A-814BDED90BDB} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} + {E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45} = {8570A43F-3AD6-4EC4-8CD1-92EF9AC23916} + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19} = {8570A43F-3AD6-4EC4-8CD1-92EF9AC23916} EndGlobalSection EndGlobal diff --git a/source/SkiaSharpSource.NetStandard.sln b/source/SkiaSharpSource.NetStandard.sln index ba38787b..c5b44fa3 100644 --- a/source/SkiaSharpSource.NetStandard.sln +++ b/source/SkiaSharpSource.NetStandard.sln @@ -15,7 +15,21 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Svg.NetStandard", EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Svg.Shared", "SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.shproj", "{B201E760-DB91-485C-A99A-814BDED90BDB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Extended", "SkiaSharp.Extended", "{1DE47CE5-7542-40CD-89ED-296CB9B212EB}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Extended.Shared", "SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.shproj", "{E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Extended.NetStandard", "SkiaSharp.Extended\SkiaSharp.Extended.NetStandard\SkiaSharp.Extended.NetStandard.csproj", "{36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}" +EndProject Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{36456f7f-388a-49e1-b9c5-cc2dec82d2c2}*SharedItemsImports = 4 + ..\binding\Binding\Binding.projitems*{4e0924f8-d546-4428-9412-4b9411fba5ff}*SharedItemsImports = 4 + ..\binding\Binding\Binding.projitems*{9c502b9a-25d4-473f-89bd-5a13dde16354}*SharedItemsImports = 13 + SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{b201e760-db91-485c-a99a-814bded90bdb}*SharedItemsImports = 13 + SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{e19ffaf3-31a4-4a52-8460-de0c00221439}*SharedItemsImports = 4 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{e3290ce6-0ada-486b-9bab-8bcf07f9be45}*SharedItemsImports = 13 + EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU @@ -29,6 +43,10 @@ Global {E19FFAF3-31A4-4A52-8460-DE0C00221439}.Debug|Any CPU.Build.0 = Debug|Any CPU {E19FFAF3-31A4-4A52-8460-DE0C00221439}.Release|Any CPU.ActiveCfg = Release|Any CPU {E19FFAF3-31A4-4A52-8460-DE0C00221439}.Release|Any CPU.Build.0 = Release|Any CPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -38,5 +56,7 @@ Global {4E0924F8-D546-4428-9412-4B9411FBA5FF} = {C335869B-7CC8-4239-B4A5-8031AA9758D3} {E19FFAF3-31A4-4A52-8460-DE0C00221439} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} {B201E760-DB91-485C-A99A-814BDED90BDB} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} + {E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45} = {1DE47CE5-7542-40CD-89ED-296CB9B212EB} + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2} = {1DE47CE5-7542-40CD-89ED-296CB9B212EB} EndGlobalSection EndGlobal diff --git a/source/SkiaSharpSource.Windows.sln b/source/SkiaSharpSource.Windows.sln index 363a5136..9499ed5f 100644 --- a/source/SkiaSharpSource.Windows.sln +++ b/source/SkiaSharpSource.Windows.sln @@ -37,6 +37,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Views.Forms", "Sk EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Svg.Shared", "SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.shproj", "{B201E760-DB91-485C-A99A-814BDED90BDB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Extended", "SkiaSharp.Extended", "{2F0684AA-463A-443A-AB75-A2DA9B15D975}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Extended.Shared", "SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.shproj", "{E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Extended", "SkiaSharp.Extended\SkiaSharp.Extended\SkiaSharp.Extended.csproj", "{FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{04c4399a-6740-4733-b6b7-f968232a76c8}*SharedItemsImports = 4 @@ -48,9 +54,10 @@ Global ..\Binding\Binding\Binding.projitems*{9c502b9a-25d4-473f-89bd-5a13dde16354}*SharedItemsImports = 13 SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{b201e760-db91-485c-a99a-814bded90bdb}*SharedItemsImports = 13 ..\Binding\Binding\Binding.projitems*{bab615aa-956e-4079-b260-dd7b1f52ec7d}*SharedItemsImports = 4 - SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{e19ffaf3-31a4-4a52-8460-de0c00221439}*SharedItemsImports = 4 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{e3290ce6-0ada-486b-9bab-8bcf07f9be45}*SharedItemsImports = 13 SkiaSharp.Views\SkiaSharp.Views.Shared\SkiaSharp.Views.Shared.projitems*{e5a90865-c185-45ad-88d1-6da7d6004b03}*SharedItemsImports = 4 ..\Binding\Binding\Binding.projitems*{eb1bbdcc-fb07-40d5-8b9e-0079e2c2f2df}*SharedItemsImports = 4 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{fea1fec9-950c-46c0-9eb0-a515e0ab8f19}*SharedItemsImports = 4 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -93,6 +100,10 @@ Global {04C4399A-6740-4733-B6B7-F968232A76C8}.Debug|Any CPU.Build.0 = Debug|Any CPU {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|Any CPU.ActiveCfg = Release|Any CPU {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|Any CPU.Build.0 = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -111,5 +122,7 @@ Global {743CF830-D458-41A9-865A-F85126562015} = {F19E1537-81B2-4D4F-A69E-78DC73ACC141} {04C4399A-6740-4733-B6B7-F968232A76C8} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} {B201E760-DB91-485C-A99A-814BDED90BDB} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} + {E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45} = {2F0684AA-463A-443A-AB75-A2DA9B15D975} + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19} = {2F0684AA-463A-443A-AB75-A2DA9B15D975} EndGlobalSection EndGlobal diff --git a/source/SkiaSharpSource.sln b/source/SkiaSharpSource.sln index 29936206..9c384205 100644 --- a/source/SkiaSharpSource.sln +++ b/source/SkiaSharpSource.sln @@ -65,12 +65,21 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Svg.NetStandard", EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Svg.Shared", "SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.shproj", "{B201E760-DB91-485C-A99A-814BDED90BDB}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SkiaSharp.Extended", "SkiaSharp.Extended", "{06F5DF49-E622-4A4C-8F01-0DB0E04721CE}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Extended.Shared", "SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.shproj", "{E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Extended", "SkiaSharp.Extended\SkiaSharp.Extended\SkiaSharp.Extended.csproj", "{FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Extended.NetStandard", "SkiaSharp.Extended\SkiaSharp.Extended.NetStandard\SkiaSharp.Extended.NetStandard.csproj", "{36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{04c4399a-6740-4733-b6b7-f968232a76c8}*SharedItemsImports = 4 SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Shared\SkiaSharp.Views.Forms.Shared.projitems*{1555d119-8598-4e4d-91ac-d313f94a1673}*SharedItemsImports = 4 SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Shared\SkiaSharp.Views.Forms.Shared.projitems*{2f94f024-1841-47e8-b521-74aa4e3eba54}*SharedItemsImports = 4 SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Shared\SkiaSharp.Views.Forms.Shared.projitems*{314fb505-9858-4e03-b799-91b0ba627d05}*SharedItemsImports = 13 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{36456f7f-388a-49e1-b9c5-cc2dec82d2c2}*SharedItemsImports = 4 SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Shared\SkiaSharp.Views.Forms.Shared.projitems*{3a1277b5-cfae-48cc-b64b-4dae1222a3eb}*SharedItemsImports = 4 ..\Binding\Binding\Binding.projitems*{4588a759-3853-49b8-8a68-6c7917be9220}*SharedItemsImports = 4 SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Shared\SkiaSharp.Views.Forms.Shared.projitems*{4ac36d63-bf11-445f-81ee-107c0cef4fc9}*SharedItemsImports = 4 @@ -91,11 +100,13 @@ Global ..\Binding\Binding\Binding.projitems*{c737dc80-5b71-4b26-a2dc-da30421788b0}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.Apple\SkiaSharp.Views.Apple.projitems*{cbca14e7-96c9-4697-909c-19b1ef7298f7}*SharedItemsImports = 13 SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{e19ffaf3-31a4-4a52-8460-de0c00221439}*SharedItemsImports = 4 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{e3290ce6-0ada-486b-9bab-8bcf07f9be45}*SharedItemsImports = 13 SkiaSharp.Views\SkiaSharp.Views.AppleiOS\SkiaSharp.Views.AppleiOS.projitems*{e5973829-6c8b-43e4-b81b-c8492df26c90}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.Apple\SkiaSharp.Views.Apple.projitems*{e5973829-6c8b-43e4-b81b-c8492df26c90}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.Shared\SkiaSharp.Views.Shared.projitems*{e5973829-6c8b-43e4-b81b-c8492df26c90}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.Shared\SkiaSharp.Views.Shared.projitems*{e5a90865-c185-45ad-88d1-6da7d6004b03}*SharedItemsImports = 4 ..\Binding\Binding\Binding.projitems*{eb1bbdcc-fb07-40d5-8b9e-0079e2c2f2df}*SharedItemsImports = 4 + SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.projitems*{fea1fec9-950c-46c0-9eb0-a515e0ab8f19}*SharedItemsImports = 4 SkiaSharp.Views\SkiaSharp.Views.AppleiOS\SkiaSharp.Views.AppleiOS.projitems*{ff4c9f9f-7a6a-44d1-8338-d30e39e4e9d4}*SharedItemsImports = 13 EndGlobalSection GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -187,6 +198,14 @@ Global {E19FFAF3-31A4-4A52-8460-DE0C00221439}.Debug|Any CPU.Build.0 = Debug|Any CPU {E19FFAF3-31A4-4A52-8460-DE0C00221439}.Release|Any CPU.ActiveCfg = Release|Any CPU {E19FFAF3-31A4-4A52-8460-DE0C00221439}.Release|Any CPU.Build.0 = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.Build.0 = Release|Any CPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -219,5 +238,8 @@ Global {4E0924F8-D546-4428-9412-4B9411FBA5FF} = {C335869B-7CC8-4239-B4A5-8031AA9758D3} {E19FFAF3-31A4-4A52-8460-DE0C00221439} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} {B201E760-DB91-485C-A99A-814BDED90BDB} = {F9C7D51F-468C-4E58-BB75-2317DB99C8A7} + {E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45} = {06F5DF49-E622-4A4C-8F01-0DB0E04721CE} + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19} = {06F5DF49-E622-4A4C-8F01-0DB0E04721CE} + {36456F7F-388A-49E1-B9C5-CC2DEC82D2C2} = {06F5DF49-E622-4A4C-8F01-0DB0E04721CE} EndGlobalSection EndGlobal diff --git a/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.csproj b/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.csproj index 5aff5b90..76a27968 100644 --- a/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.csproj +++ b/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.csproj @@ -1,4 +1,4 @@ - + @@ -190,6 +190,9 @@ SKSvgTest.cs + + SKGeometryTest.cs + SKTest.cs @@ -269,6 +272,10 @@ {04C4399A-6740-4733-B6B7-F968232A76C8} SkiaSharp.Svg + + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19} + SkiaSharp.Extended + diff --git a/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.sln b/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.sln index 6cae4947..9760549f 100644 --- a/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.sln +++ b/tests/SkiaSharp.Desktop.Tests/SkiaSharp.Desktop.Tests.sln @@ -15,6 +15,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Svg", "..\..\sour EndProject Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Svg.Shared", "..\..\source\SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.shproj", "{B201E760-DB91-485C-A99A-814BDED90BDB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SkiaSharp.Extended", "..\..\source\SkiaSharp.Extended\SkiaSharp.Extended\SkiaSharp.Extended.csproj", "{FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "SkiaSharp.Extended.Shared", "..\..\source\SkiaSharp.Extended\SkiaSharp.Extended.Shared\SkiaSharp.Extended.Shared.shproj", "{E3290CE6-0ADA-486B-9BAB-8BCF07F9BE45}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ..\..\source\SkiaSharp.Svg\SkiaSharp.Svg.Shared\SkiaSharp.Svg.Shared.projitems*{04c4399a-6740-4733-b6b7-f968232a76c8}*SharedItemsImports = 4 @@ -79,6 +83,18 @@ Global {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|x64.Build.0 = Release|Any CPU {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|x86.ActiveCfg = Release|Any CPU {04C4399A-6740-4733-B6B7-F968232A76C8}.Release|x86.Build.0 = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|x64.ActiveCfg = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|x64.Build.0 = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|x86.ActiveCfg = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Debug|x86.Build.0 = Debug|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|Any CPU.Build.0 = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|x64.ActiveCfg = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|x64.Build.0 = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|x86.ActiveCfg = Release|Any CPU + {FEA1FEC9-950C-46C0-9EB0-A515E0AB8F19}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/tests/SkiaSharp.NetCore.Tests/project.json b/tests/SkiaSharp.NetCore.Tests/project.json index fb71a194..943654d0 100644 --- a/tests/SkiaSharp.NetCore.Tests/project.json +++ b/tests/SkiaSharp.NetCore.Tests/project.json @@ -24,7 +24,8 @@ "dotnet-test-nunit": "3.4.0-beta-3", "SkiaSharp": "1.56.1", - "SkiaSharp.Svg": "1.56.1" + "SkiaSharp.Svg": "1.56.1", + "SkiaSharp.Extended": "1.56.1-beta" }, "testRunner": "nunit", "frameworks": { diff --git a/tests/Tests/SKBasicTypesTest.cs b/tests/Tests/SKBasicTypesTest.cs index 1eba7b7d..35d10cf8 100644 --- a/tests/Tests/SKBasicTypesTest.cs +++ b/tests/Tests/SKBasicTypesTest.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; namespace SkiaSharp.Tests @@ -7,6 +8,7 @@ namespace SkiaSharp.Tests public class SKBasicTypesTest : SKTest { private const float EPSILON = 0.0001f; + private const int PRECISION = 4; [Test] public void RectanlgeHasCorrectProperties() @@ -211,5 +213,140 @@ namespace SkiaSharp.Tests mask.FreeImage(); } + + [Test] + public void Matrix44CreatesIdentity() + { + var matrix = SKMatrix44.CreateIdentity(); + + var expectedRowMajor = new float[] { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }; + var rowMajor = matrix.ToRowMajor(); + + Assert.AreEqual(expectedRowMajor, rowMajor); + } + + [Test] + public void Matrix44Inverts() + { + var rowMajor = new float[] { + 1, 2, 3, 0, + 0, 1, 4, 0, + 5, 6, 1, 0, + 0, 0, 0, 1, + }; + var expectedRowMajor = new float[] { + -11.5f, 8, 2.5f, 0, + 10, -7, -2, 0, + -2.5f, 2, 0.5f, 0, + 0, 0, 0, 1, + }; + var determinant = 2f; + + var matrix = SKMatrix44.FromRowMajor(rowMajor); + + Assert.AreEqual(rowMajor, matrix.ToRowMajor()); + Assert.AreEqual(determinant, matrix.Determinant()); + + var inverted = matrix.Invert(); + + Assert.AreEqual(1f / determinant, inverted.Determinant()); + + var actualRowMajor = inverted.ToRowMajor(); + Assert.AreEqual(expectedRowMajor, actualRowMajor); + } + + [Test] + public void Matrix44ConvertsToMatrix() + { + var rowMajor44 = new float[] { + 2, 3, 4, 5, + 4, 6, 8, 10, + 6, 9, 12, 15, + 8, 12, 16, 20, + }; + var rowMajor = new float[] { + rowMajor44[0], rowMajor44[1], rowMajor44[3], + rowMajor44[4], rowMajor44[5], rowMajor44[7], + rowMajor44[12], rowMajor44[13], rowMajor44[15], + }; + + var matrix44 = SKMatrix44.FromRowMajor(rowMajor44); + + Assert.AreEqual(rowMajor, matrix44.Matrix.Values); + + matrix44 = SKMatrix44.CreateRotationDegrees(0, 0, 1, 45); + Assert.AreEqual(SKMatrix.MakeRotationDegrees(45).Values, matrix44.Matrix.Values); + } + + [Test] + public void Matrix44MapsScalars() + { + // translate + var matrixTranslate = SKMatrix44.CreateTranslate(10, 20, 0); + + var resultTranslateZero = matrixTranslate.MapScalars(0, 0, 0, 1); + var resultTranslateValue = matrixTranslate.MapScalars(5, 25, 0, 1); + + Assert.AreEqual(new[] { 10f, 20f, 0f, 1f }, resultTranslateZero); + Assert.AreEqual(new[] { 15f, 45f, 0f, 1f }, resultTranslateValue); + + // rotate + var matrixRotate = SKMatrix44.CreateRotationDegrees(0, 1, 0, 90); + + var resultRotateZero = matrixRotate.MapScalars(0, 0, 0, 1); + var resultRotateValue = matrixRotate.MapScalars(5, 25, 0, 1); + + Assert.AreEqual(new[] { 0f, 0f, 0f, 1f }, resultRotateZero); + Assert.AreEqual(new[] { 0f, 25f, -5f, 1f }, resultRotateValue.Select(v => (int)(v / EPSILON) * EPSILON)); + } + + [Test] + public void Matrix44MapsPoints() + { + // translate + var matrixTranslate = SKMatrix44.CreateTranslate(10, 20, 0); + + var resultTranslateZero = matrixTranslate.MapPoint(SKPoint.Empty); + var resultTranslateValue = matrixTranslate.MapPoint(new SKPoint(5, 25)); + + Assert.AreEqual(new SKPoint(10f, 20f), resultTranslateZero); + Assert.AreEqual(new SKPoint(15f, 45f), resultTranslateValue); + + // rotate + var matrixRotate = SKMatrix44.CreateRotationDegrees(0, 1, 0, 90); + + var resultRotateZero = matrixRotate.MapPoint(SKPoint.Empty); + var resultRotateValue = matrixRotate.MapPoint(new SKPoint(5, 25)); + + Assert.AreEqual(new SKPoint(0f, 0f), resultRotateZero); + Assert.AreEqual(0, resultRotateValue.X, PRECISION); + Assert.AreEqual(25, resultRotateValue.Y, PRECISION); + } + + [Test] + public void Matrix44MapsPointsBulk() + { + var rnd = new Random(); + + var matrixTranslate = SKMatrix44.CreateTranslate(10, 25, 0); + + // generate some points + var points = new SKPoint[1000]; + var results = new SKPoint[points.Length]; + for (int i = 0; i < points.Length; i++) + { + points[i] = new SKPoint(rnd.Next(1000) / 10f, rnd.Next(1000) / 10f); + results[i] = new SKPoint(points[i].X + 10, points[i].Y + 25); + } + + var actualResults = matrixTranslate.MapPoints(points); + + Assert.AreEqual(results, actualResults); + } } } diff --git a/tests/Tests/SKGeometryTest.cs b/tests/Tests/SKGeometryTest.cs new file mode 100644 index 00000000..b713bad2 --- /dev/null +++ b/tests/Tests/SKGeometryTest.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; + +using SkiaSharp.Extended; + +namespace SkiaSharp.Tests +{ + public class SKGeometryTest : SKTest + { + [Test] + public void GeometryGeneratesRectPath() + { + var rectPath = SKGeometry.CreateTrianglePath(100); + + Assert.AreEqual(3, rectPath.PointCount); + } + } +} diff --git a/workbooks/BlankSkiaSharp.workbook/SkiaSharp.csx b/workbooks/BlankSkiaSharp.workbook/SkiaSharp.csx new file mode 100644 index 00000000..a0dd0bfd --- /dev/null +++ b/workbooks/BlankSkiaSharp.workbook/SkiaSharp.csx @@ -0,0 +1,15 @@ +using System; +using System.IO; +using SkiaSharp; + +var assemblyLocation = Path.GetDirectoryName(typeof(SKBitmap).Assembly.Location); +var packageLocation = Path.GetDirectoryName(Path.GetDirectoryName(assemblyLocation)); +var isMac = Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix; +var runtime = isMac ? "osx" : ("win7-" + (Environment.Is64BitProcess ? "x64" : "x86")); +var nativeName = isMac ? "libSkiaSharp.dylib" : "libSkiaSharp.dll"; +var nativeLocation = Path.Combine(packageLocation, "runtimes", runtime, "native", nativeName); +var newLocation = Path.Combine(assemblyLocation, nativeName); + +if (!File.Exists(newLocation)) { + File.Copy(nativeLocation, newLocation, true); +} diff --git a/workbooks/BlankSkiaSharp.workbook/index.workbook b/workbooks/BlankSkiaSharp.workbook/index.workbook new file mode 100644 index 00000000..8ecf3290 --- /dev/null +++ b/workbooks/BlankSkiaSharp.workbook/index.workbook @@ -0,0 +1,44 @@ +--- +uti: com.xamarin.workbook +platforms: +- Console +packages: +- id: SkiaSharp.Svg + version: 1.56.1 +- id: SkiaSharp + version: 1.56.1 +--- + +```csharp +#r "SkiaSharp" +#r "SkiaSharp.Svg" +#load "SkiaSharp.csx" + +using SkiaSharp; +``` + +```csharp +var bitmap = new SKBitmap(256, 256); +var canvas = new SKCanvas(bitmap); + +canvas.Clear(SKColors.Transparent); +``` + +```csharp +canvas.Clear(SKColors.Transparent); + +var paint = new SKPaint { + IsAntialias = true, + TextSize = 50, + TextAlign = SKTextAlign.Center, + Color = 0xFF3498DB, // Xamarin light blue + Style = SKPaintStyle.Fill, + Typeface = SKTypeface.FromFamilyName("Trebuchet") +}; + +canvas.DrawText("SkiaSharp", 128, 128 + (paint.TextSize / 2), paint); +``` + +```csharp +bitmap +``` \ No newline at end of file diff --git a/workbooks/Development.workbook/index.workbook b/workbooks/Development.workbook/index.workbook new file mode 100644 index 00000000..70c896f7 --- /dev/null +++ b/workbooks/Development.workbook/index.workbook @@ -0,0 +1,40 @@ +--- +uti: com.xamarin.workbook +platforms: +- Console +--- + +```csharp +#r "../../output/workbooks/SkiaSharp.dll" +#r "../../output/workbooks/SkiaSharp.Svg.dll" +#r "../../output/workbooks/SkiaSharp.Extended.dll" + +using SkiaSharp; +using SkiaSharp.Extended; +``` + +```csharp +var bitmap = new SKBitmap(256, 256); +var canvas = new SKCanvas(bitmap); + +canvas.Clear(SKColors.Transparent); +``` + +```csharp +canvas.Clear(SKColors.Transparent); + +var paint = new SKPaint { + IsAntialias = true, + TextSize = 50, + TextAlign = SKTextAlign.Center, + Color = 0xFF3498DB, // Xamarin light blue + Style = SKPaintStyle.Fill, + Typeface = SKTypeface.FromFamilyName("Trebuchet") +}; + +canvas.DrawText("SkiaSharp", 128, 128 + (paint.TextSize / 2), paint); +``` + +```csharp +bitmap +``` \ No newline at end of file