LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+
+SkiaSharp
+
+Copyright (c) 2015-2016 Xamarin, Inc.
+Copyright (c) 2017-2018 Microsoft Corporation.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Source0: %{name}-%{version}.tar.gz
Source1: %{name}.manifest
-BuildArch: noarch
AutoReqProv: no
ExcludeArch: aarch64
%define DOTNET_ASSEMBLY_PATH /usr/share/dotnet.tizen/framework
%define DOTNET_NUGET_SOURCE /nuget
+%define SKIA_LIBRARY_PATH /usr/lib
+%define LIB_HARFBUZZ_NAME libHarfBuzzSharp.2.6.1.so
+%define LIB_SKIASHARP_NAME libSkiaSharp.1.68.2.so
BuildRequires: dotnet-build-tools
-
Requires: coreclr
Requires: mscorlib
Requires: corefx-native
mkdir -p %{buildroot}%{DOTNET_ASSEMBLY_PATH}
mv ./src/XSF/bin/Release/netstandard2.0/XSF.dll %{buildroot}%{DOTNET_ASSEMBLY_PATH}
+mkdir -p %{buildroot}%{SKIA_LIBRARY_PATH}
+%ifarch %{ix86}
+mv ./src/XSF/lib/x86/%{LIB_HARFBUZZ_NAME} %{buildroot}%{SKIA_LIBRARY_PATH}
+mv ./src/XSF/lib/x86/%{LIB_SKIASHARP_NAME} %{buildroot}%{SKIA_LIBRARY_PATH}
+%else
+mv ./src/XSF/lib/armel/%{LIB_HARFBUZZ_NAME} %{buildroot}%{SKIA_LIBRARY_PATH}
+mv ./src/XSF/lib/armel/%{LIB_SKIASHARP_NAME} %{buildroot}%{SKIA_LIBRARY_PATH}
+%endif
+
%files
%manifest %{name}.manifest
%license LICENSE LICENSE.Flora-1.1 LICENSE.Apache-2.0
%attr(644,root,root) %{DOTNET_ASSEMBLY_PATH}/*.dll
+%attr(644,root,root) %{SKIA_LIBRARY_PATH}/*.so
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.IO;
+
+namespace HarfBuzzSharp
+{
+ public class Blob : NativeObject
+ {
+ private static readonly Lazy<Blob> emptyBlob = new Lazy<Blob> (() => new StaticBlob (HarfBuzzApi.hb_blob_get_empty ()));
+
+ public static Blob Empty => emptyBlob.Value;
+
+ internal Blob (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Blob(IntPtr, int, MemoryMode, ReleaseDelegate) instead.")]
+ public Blob (IntPtr data, uint length, MemoryMode mode, object userData, BlobReleaseDelegate releaseDelegate)
+ : this (data, (int)length, mode, () => releaseDelegate?.Invoke (userData))
+ {
+ }
+
+ public Blob (IntPtr data, int length, MemoryMode mode)
+ : this (data, length, mode, null)
+ {
+ }
+
+ public Blob (IntPtr data, int length, MemoryMode mode, ReleaseDelegate releaseDelegate)
+ : this (Create (data, length, mode, releaseDelegate))
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeHandler ()
+ {
+ if (Handle != IntPtr.Zero) {
+ HarfBuzzApi.hb_blob_destroy (Handle);
+ }
+ }
+
+ public int Length => HarfBuzzApi.hb_blob_get_length (Handle);
+
+ public int FaceCount => HarfBuzzApi.hb_face_count (Handle);
+
+ public bool IsImmutable => HarfBuzzApi.hb_blob_is_immutable (Handle);
+
+ public void MakeImmutable () => HarfBuzzApi.hb_blob_make_immutable (Handle);
+
+ public unsafe Stream AsStream ()
+ {
+ var dataPtr = HarfBuzzApi.hb_blob_get_data (Handle, out var length);
+ return new UnmanagedMemoryStream (dataPtr, length);
+ }
+
+ public unsafe ReadOnlySpan<byte> AsSpan ()
+ {
+ var dataPtr = HarfBuzzApi.hb_blob_get_data (Handle, out var length);
+ return new ReadOnlySpan<byte> (dataPtr, length);
+ }
+
+ public static Blob FromFile (string fileName)
+ {
+ if (!File.Exists (fileName)) {
+ throw new FileNotFoundException ("Unable to find file.", fileName);
+ }
+
+ var blob = HarfBuzzApi.hb_blob_create_from_file (fileName);
+ return new Blob (blob);
+ }
+
+ public static unsafe Blob FromStream (Stream stream)
+ {
+ // TODO: check to see if we can avoid the second copy (the ToArray)
+
+ using (var ms = new MemoryStream ()) {
+ stream.CopyTo (ms);
+ var data = ms.ToArray ();
+
+ fixed (byte* dataPtr = data) {
+ return new Blob ((IntPtr)dataPtr, data.Length, MemoryMode.ReadOnly, () => ms.Dispose ());
+ }
+ }
+ }
+
+ private static IntPtr Create (IntPtr data, int length, MemoryMode mode, ReleaseDelegate releaseProc)
+ {
+ var proxy = DelegateProxies.Create (releaseProc, DelegateProxies.ReleaseDelegateProxy, out _, out var ctx);
+ return HarfBuzzApi.hb_blob_create (data, length, mode, ctx, proxy);
+ }
+
+ private class StaticBlob : Blob
+ {
+ public StaticBlob (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Buffers;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace HarfBuzzSharp
+{
+ public class Buffer : NativeObject
+ {
+ public const int DefaultReplacementCodepoint = '\uFFFD';
+
+ internal Buffer (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ public Buffer ()
+ : this (HarfBuzzApi.hb_buffer_create ())
+ {
+ }
+
+ public ContentType ContentType {
+ get => HarfBuzzApi.hb_buffer_get_content_type (Handle);
+ set => HarfBuzzApi.hb_buffer_set_content_type (Handle, value);
+ }
+
+ public Direction Direction {
+ get => HarfBuzzApi.hb_buffer_get_direction (Handle);
+ set => HarfBuzzApi.hb_buffer_set_direction (Handle, value);
+ }
+
+ public Language Language {
+ get => new Language (HarfBuzzApi.hb_buffer_get_language (Handle));
+ set => HarfBuzzApi.hb_buffer_set_language (Handle, value.Handle);
+ }
+
+ public BufferFlags Flags {
+ get => HarfBuzzApi.hb_buffer_get_flags (Handle);
+ set => HarfBuzzApi.hb_buffer_set_flags (Handle, value);
+ }
+
+ public ClusterLevel ClusterLevel {
+ get => HarfBuzzApi.hb_buffer_get_cluster_level (Handle);
+ set => HarfBuzzApi.hb_buffer_set_cluster_level (Handle, value);
+ }
+
+ public uint ReplacementCodepoint {
+ get => HarfBuzzApi.hb_buffer_get_replacement_codepoint (Handle);
+ set => HarfBuzzApi.hb_buffer_set_replacement_codepoint (Handle, value);
+ }
+
+ public uint InvisibleGlyph {
+ get => HarfBuzzApi.hb_buffer_get_invisible_glyph (Handle);
+ set => HarfBuzzApi.hb_buffer_set_invisible_glyph (Handle, value);
+ }
+
+ public Script Script {
+ get => HarfBuzzApi.hb_buffer_get_script (Handle);
+ set => HarfBuzzApi.hb_buffer_set_script (Handle, value);
+ }
+
+ public int Length {
+ get => HarfBuzzApi.hb_buffer_get_length (Handle);
+ set => HarfBuzzApi.hb_buffer_set_length (Handle, value);
+ }
+
+ public UnicodeFunctions UnicodeFunctions {
+ get => new UnicodeFunctions (HarfBuzzApi.hb_buffer_get_unicode_funcs (Handle));
+ set => HarfBuzzApi.hb_buffer_set_unicode_funcs (Handle, value.Handle);
+ }
+
+ public GlyphInfo[] GlyphInfos {
+ get {
+ var array = GetGlyphInfoSpan ().ToArray ();
+ GC.KeepAlive (this);
+ return array;
+ }
+ }
+
+ public GlyphPosition[] GlyphPositions {
+ get {
+ var array = GetGlyphPositionSpan ().ToArray ();
+ GC.KeepAlive (this);
+ return array;
+ }
+ }
+
+ public void Add (int codepoint, int cluster) => Add ((uint)codepoint, (uint)cluster);
+
+ public void Add (uint codepoint, uint cluster)
+ {
+ if (Length != 0 && ContentType != ContentType.Unicode)
+ throw new InvalidOperationException ("Non empty buffer's ContentType must be of type Unicode.");
+ if (ContentType == ContentType.Glyphs)
+ throw new InvalidOperationException ("ContentType must not be of type Glyphs");
+
+ HarfBuzzApi.hb_buffer_add (Handle, codepoint, cluster);
+ }
+
+ public void AddUtf8 (string utf8text) => AddUtf8 (Encoding.UTF8.GetBytes (utf8text), 0, -1);
+
+ public void AddUtf8 (byte[] bytes) => AddUtf8 (new ReadOnlySpan<byte> (bytes));
+
+ public void AddUtf8 (ReadOnlySpan<byte> text) => AddUtf8 (text, 0, -1);
+
+ public unsafe void AddUtf8 (ReadOnlySpan<byte> text, int itemOffset, int itemLength)
+ {
+ fixed (byte* bytes = text) {
+ AddUtf8 ((IntPtr)bytes, text.Length, itemOffset, itemLength);
+ }
+ }
+
+ public void AddUtf8 (IntPtr text, int textLength) => AddUtf8 (text, textLength, 0, -1);
+
+ public void AddUtf8 (IntPtr text, int textLength, int itemOffset, int itemLength)
+ {
+ if (itemOffset < 0)
+ throw new ArgumentOutOfRangeException (nameof (itemOffset), "ItemOffset must be non negative.");
+ if (Length != 0 && ContentType != ContentType.Unicode)
+ throw new InvalidOperationException ("Non empty buffer's ContentType must be of type Unicode.");
+ if (ContentType == ContentType.Glyphs)
+ throw new InvalidOperationException ("ContentType must not be Glyphs");
+
+ HarfBuzzApi.hb_buffer_add_utf8 (Handle, text, textLength, itemOffset, itemLength);
+ }
+
+ public void AddUtf16 (string text) => AddUtf16 (text, 0, -1);
+
+ public unsafe void AddUtf16 (string text, int itemOffset, int itemLength)
+ {
+ fixed (char* chars = text) {
+ AddUtf16 ((IntPtr)chars, text.Length, itemOffset, itemLength);
+ }
+ }
+
+ public unsafe void AddUtf16 (ReadOnlySpan<byte> text)
+ {
+ fixed (byte* bytes = text) {
+ AddUtf16 ((IntPtr)bytes, text.Length / 2);
+ }
+ }
+
+ public void AddUtf16 (ReadOnlySpan<char> text) => AddUtf16 (text, 0, -1);
+
+ public unsafe void AddUtf16 (ReadOnlySpan<char> text, int itemOffset, int itemLength)
+ {
+ fixed (char* chars = text) {
+ AddUtf16 ((IntPtr)chars, text.Length, itemOffset, itemLength);
+ }
+ }
+
+ public void AddUtf16 (IntPtr text, int textLength) =>
+ AddUtf16 (text, textLength, 0, -1);
+
+ public void AddUtf16 (IntPtr text, int textLength, int itemOffset, int itemLength)
+ {
+ if (itemOffset < 0)
+ throw new ArgumentOutOfRangeException (nameof (itemOffset), "ItemOffset must be non negative.");
+ if (Length != 0 && ContentType != ContentType.Unicode)
+ throw new InvalidOperationException ("Non empty buffer's ContentType must be of type Unicode.");
+ if (ContentType == ContentType.Glyphs)
+ throw new InvalidOperationException ("ContentType must not be of type Glyphs");
+
+ HarfBuzzApi.hb_buffer_add_utf16 (Handle, text, textLength, itemOffset, itemLength);
+ }
+
+ public void AddUtf32 (string text) => AddUtf32 (Encoding.UTF32.GetBytes (text));
+
+ public unsafe void AddUtf32 (ReadOnlySpan<byte> text)
+ {
+ fixed (byte* bytes = text) {
+ AddUtf32 ((IntPtr)bytes, text.Length / 4);
+ }
+ }
+
+ public void AddUtf32 (ReadOnlySpan<uint> text) => AddUtf32 (text, 0, -1);
+
+ public unsafe void AddUtf32 (ReadOnlySpan<uint> text, int itemOffset, int itemLength)
+ {
+ fixed (uint* integers = text) {
+ AddUtf32 ((IntPtr)integers, text.Length, itemOffset, itemLength);
+ }
+ }
+
+ public void AddUtf32 (ReadOnlySpan<int> text) => AddUtf32 (text, 0, -1);
+
+ public unsafe void AddUtf32 (ReadOnlySpan<int> text, int itemOffset, int itemLength)
+ {
+ fixed (int* integers = text) {
+ AddUtf32 ((IntPtr)integers, text.Length, itemOffset, itemLength);
+ }
+ }
+
+ public void AddUtf32 (IntPtr text, int textLength) =>
+ AddUtf32 (text, textLength, 0, -1);
+
+ public void AddUtf32 (IntPtr text, int textLength, int itemOffset, int itemLength)
+ {
+ if (itemOffset < 0)
+ throw new ArgumentOutOfRangeException (nameof (itemOffset), "ItemOffset must be non negative.");
+ if (Length != 0 && ContentType != ContentType.Unicode)
+ throw new InvalidOperationException ("Non empty buffer's ContentType must be of type Unicode.");
+ if (ContentType == ContentType.Glyphs)
+ throw new InvalidOperationException ("ContentType must not be of type Glyphs");
+
+ HarfBuzzApi.hb_buffer_add_utf32 (Handle, text, textLength, itemOffset, itemLength);
+ }
+
+ public void AddCodepoints (ReadOnlySpan<uint> text) => AddCodepoints (text, 0, -1);
+
+ public unsafe void AddCodepoints (ReadOnlySpan<uint> text, int itemOffset, int itemLength)
+ {
+ fixed (uint* codepoints = text) {
+ AddCodepoints ((IntPtr)codepoints, text.Length, itemOffset, itemLength);
+ }
+ }
+
+ public void AddCodepoints (ReadOnlySpan<int> text) => AddCodepoints (text, 0, -1);
+
+ public unsafe void AddCodepoints (ReadOnlySpan<int> text, int itemOffset, int itemLength)
+ {
+ fixed (int* codepoints = text) {
+ AddCodepoints ((IntPtr)codepoints, text.Length, itemOffset, itemLength);
+ }
+ }
+
+ public void AddCodepoints (IntPtr text, int textLength) => AddCodepoints (text, textLength, 0, -1);
+
+ public void AddCodepoints (IntPtr text, int textLength, int itemOffset, int itemLength)
+ {
+ if (itemOffset < 0)
+ throw new ArgumentOutOfRangeException (nameof (itemOffset), "ItemOffset must be non negative.");
+ if (Length != 0 && ContentType != ContentType.Unicode)
+ throw new InvalidOperationException ("Non empty buffer's ContentType must be of type Unicode.");
+ if (ContentType == ContentType.Glyphs)
+ throw new InvalidOperationException ("ContentType must not be of type Glyphs");
+
+ HarfBuzzApi.hb_buffer_add_codepoints (Handle, text, textLength, itemOffset, itemLength);
+ }
+
+ public unsafe ReadOnlySpan<GlyphInfo> GetGlyphInfoSpan ()
+ {
+ var infoPtrs = HarfBuzzApi.hb_buffer_get_glyph_infos (Handle, out var length);
+ return new ReadOnlySpan<GlyphInfo> (infoPtrs, length);
+ }
+
+ public unsafe ReadOnlySpan<GlyphPosition> GetGlyphPositionSpan ()
+ {
+ var infoPtrs = HarfBuzzApi.hb_buffer_get_glyph_positions (Handle, out var length);
+ return new ReadOnlySpan<GlyphPosition> (infoPtrs, length);
+ }
+
+ public void GuessSegmentProperties ()
+ {
+ if (ContentType != ContentType.Unicode)
+ throw new InvalidOperationException ("ContentType must be of type Unicode.");
+
+ HarfBuzzApi.hb_buffer_guess_segment_properties (Handle);
+ }
+
+ public void ClearContents () => HarfBuzzApi.hb_buffer_clear_contents (Handle);
+
+ public void Reset () => HarfBuzzApi.hb_buffer_reset (Handle);
+
+ public void Append (Buffer buffer) => Append (buffer, 0, -1);
+
+ public void Append (Buffer buffer, int start, int end)
+ {
+ if (buffer.Length == 0)
+ throw new ArgumentException ("Buffer must be non empty.", nameof (buffer));
+ if (buffer.ContentType != ContentType)
+ throw new InvalidOperationException ("ContentType must be of same type.");
+
+ HarfBuzzApi.hb_buffer_append (Handle, buffer.Handle, start, end == -1 ? buffer.Length : end);
+ }
+
+ public void NormalizeGlyphs ()
+ {
+ if (ContentType != ContentType.Glyphs)
+ throw new InvalidOperationException ("ContentType must be of type Glyphs.");
+ if (GlyphPositions.Length == 0)
+ throw new InvalidOperationException ("GlyphPositions can't be empty.");
+
+ HarfBuzzApi.hb_buffer_normalize_glyphs (Handle);
+ }
+
+ public void Reverse () => HarfBuzzApi.hb_buffer_reverse (Handle);
+
+ public void ReverseRange (int start, int end) =>
+ HarfBuzzApi.hb_buffer_reverse_range (Handle, start, end == -1 ? Length : end);
+
+ public void ReverseClusters () => HarfBuzzApi.hb_buffer_reverse_clusters (Handle);
+
+ public string SerializeGlyphs () =>
+ SerializeGlyphs (0, -1, null, SerializeFormat.Text, SerializeFlag.Default);
+
+ public string SerializeGlyphs (int start, int end) =>
+ SerializeGlyphs (start, end, null, SerializeFormat.Text, SerializeFlag.Default);
+
+ public string SerializeGlyphs (Font font) =>
+ SerializeGlyphs (0, -1, font, SerializeFormat.Text, SerializeFlag.Default);
+
+ public string SerializeGlyphs (Font font, SerializeFormat format, SerializeFlag flags) =>
+ SerializeGlyphs (0, -1, font, format, flags);
+
+ public unsafe string SerializeGlyphs (int start, int end, Font font, SerializeFormat format, SerializeFlag flags)
+ {
+ if (Length == 0)
+ throw new InvalidOperationException ("Buffer should not be empty.");
+ if (ContentType != ContentType.Glyphs)
+ throw new InvalidOperationException ("ContentType should be of type Glyphs.");
+
+ if (end == -1)
+ end = Length;
+
+ using (var buffer = MemoryPool<byte>.Shared.Rent ())
+ using (var pinned = buffer.Memory.Pin ()) {
+ var bufferSize = buffer.Memory.Length;
+ var currentPosition = start;
+ var builder = new StringBuilder (bufferSize);
+
+ while (currentPosition < end) {
+ currentPosition += HarfBuzzApi.hb_buffer_serialize_glyphs (
+ Handle,
+ currentPosition,
+ end,
+ (IntPtr)pinned.Pointer,
+ bufferSize,
+ out var consumed,
+ font?.Handle ?? IntPtr.Zero,
+ format,
+ flags);
+
+ builder.Append (Marshal.PtrToStringAnsi ((IntPtr)pinned.Pointer, consumed));
+ }
+
+ return builder.ToString ();
+ }
+ }
+
+ public void DeserializeGlyphs (string data) =>
+ DeserializeGlyphs (data, null, SerializeFormat.Text);
+
+ public void DeserializeGlyphs (string data, Font font) =>
+ DeserializeGlyphs (data, font, SerializeFormat.Text);
+
+ public void DeserializeGlyphs (string data, Font font, SerializeFormat format)
+ {
+ if (Length != 0)
+ throw new InvalidOperationException ("Buffer must be empty.");
+ if (ContentType == ContentType.Glyphs)
+ throw new InvalidOperationException ("ContentType must not be Glyphs.");
+
+ HarfBuzzApi.hb_buffer_deserialize_glyphs (Handle, data, -1, out _, font?.Handle ?? IntPtr.Zero, format);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeHandler ()
+ {
+ if (Handle != IntPtr.Zero) {
+ HarfBuzzApi.hb_buffer_destroy (Handle);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using hb_codepoint_t = System.UInt32;
+using hb_mask_t = System.UInt32;
+using hb_position_t = System.Int32;
+using hb_var_int_t = System.Int32;
+
+namespace HarfBuzzSharp
+{
+ public enum MemoryMode
+ {
+ Duplicate,
+ ReadOnly,
+ Writeable,
+ ReadOnlyMayMakeWriteable
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public struct Feature
+ {
+ private const int MaxFeatureStringSize = 128;
+
+ private Tag tag;
+ private uint val;
+ private uint start;
+ private uint end;
+
+ public Feature (Tag tag)
+ : this (tag, 1u, 0, uint.MaxValue)
+ {
+ }
+
+ public Feature (Tag tag, uint value)
+ : this (tag, value, 0, uint.MaxValue)
+ {
+ }
+
+ public Feature (Tag tag, uint value, uint start, uint end)
+ {
+ this.tag = tag;
+ this.val = value;
+ this.start = start;
+ this.end = end;
+ }
+
+ public Tag Tag {
+ get => tag;
+ set => tag = value;
+ }
+
+ public uint Value {
+ get => val;
+ set => val = value;
+ }
+
+ public uint Start {
+ get => start;
+ set => start = value;
+ }
+
+ public uint End {
+ get => end;
+ set => end = value;
+ }
+
+ public override string ToString ()
+ {
+ var buffer = new StringBuilder (MaxFeatureStringSize);
+ HarfBuzzApi.hb_feature_to_string (ref this, buffer, MaxFeatureStringSize);
+ return buffer.ToString ();
+ }
+
+ public static bool TryParse (string s, out Feature feature) =>
+ HarfBuzzApi.hb_feature_from_string (s, -1, out feature);
+
+ public static Feature Parse (string s) =>
+ TryParse (s, out var feature) ? feature : throw new FormatException ("Unrecognized feature string format.");
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public struct GlyphInfo
+ {
+ private hb_codepoint_t codepoint;
+ private hb_mask_t mask;
+ private uint cluster;
+
+ // < private >
+ private hb_var_int_t var1;
+ private hb_var_int_t var2;
+
+ public hb_codepoint_t Codepoint {
+ get => codepoint;
+ set => codepoint = value;
+ }
+
+ public hb_mask_t Mask {
+ get => mask;
+ set => mask = value;
+ }
+
+ public uint Cluster {
+ get => cluster;
+ set => cluster = value;
+ }
+
+ public GlyphFlags GlyphFlags =>
+ HarfBuzzApi.hb_glyph_info_get_glyph_flags (ref this);
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ public struct GlyphPosition
+ {
+ private hb_position_t x_advance;
+ private hb_position_t y_advance;
+ private hb_position_t x_offset;
+ private hb_position_t y_offset;
+
+ // < private >
+ private hb_var_int_t var;
+
+ public hb_position_t XAdvance {
+ get => x_advance;
+ set => x_advance = value;
+ }
+
+ public hb_position_t YAdvance {
+ get => y_advance;
+ set => y_advance = value;
+ }
+
+ public hb_position_t XOffset {
+ get => x_offset;
+ set => x_offset = value;
+ }
+
+ public hb_position_t YOffset {
+ get => y_offset;
+ set => y_offset = value;
+ }
+ }
+
+ public enum Direction
+ {
+ Invalid = 0,
+
+ LeftToRight = 4,
+ RightToLeft,
+ TopToBottom,
+ BottomToTop
+ }
+
+ public enum ClusterLevel
+ {
+ MonotoneGraphemes = 0,
+ MonotoneCharacters = 1,
+ Characters = 2,
+ Default = MonotoneGraphemes
+ }
+
+ [Flags]
+ public enum BufferFlags : uint
+ {
+ Default = 0x00000000u,
+ BeginningOfText = 0x00000001u,
+ EndOfText = 0x00000002u,
+ PreserveDefaultIgnorables = 0x00000004u,
+ RemoveDefaultIgnorables = 0x00000008u,
+ DoNotInsertDottedCircle = 0x00000010u,
+ }
+
+ public enum ContentType
+ {
+ Invalid = 0,
+ Unicode,
+ Glyphs
+ }
+
+ [Flags]
+ public enum GlyphFlags
+ {
+ UnsafeToBreak = 0x00000001,
+ Defined = 0x00000001
+ }
+
+ [Flags]
+ public enum SerializeFlag : uint
+ {
+ Default = 0x00000000u,
+ NoClusters = 0x00000001u,
+ NoPositions = 0x00000002u,
+ NoGlyphNames = 0x00000004u,
+ GlyphExtents = 0x00000008u,
+ GlyphFlags = 0x00000010u,
+ NoAdvances = 0x00000020u
+ }
+
+ public enum SerializeFormat : uint
+ {
+ Text = (((byte)'T' << 24) | ((byte)'E' << 16) | ((byte)'X' << 8) | (byte)'T'),
+ Json = (((byte)'J' << 24) | ((byte)'S' << 16) | ((byte)'O' << 8) | (byte)'N'),
+ Invalid = 0
+ }
+
+ public struct GlyphExtents
+ {
+ hb_position_t x_bearing; /* left side of glyph from origin. */
+ hb_position_t y_bearing; /* top side of glyph from origin. */
+ hb_position_t width; /* distance from left to right side. */
+ hb_position_t height; /* distance from top to bottom side. */
+
+ public hb_position_t XBearing {
+ get => x_bearing;
+ set => x_bearing = value;
+ }
+ public hb_position_t YBearing {
+ get => y_bearing;
+ set => y_bearing = value;
+ }
+ public hb_position_t Width {
+ get => width;
+ set => width = value;
+ }
+ public hb_position_t Height {
+ get => height;
+ set => height = value;
+ }
+ }
+
+ public struct FontExtents
+ {
+ private hb_position_t ascender; // typographic ascender.
+ private hb_position_t descender; // typographic descender.
+ private hb_position_t line_gap; // suggested line spacing gap.
+
+ // < private >
+ private hb_position_t reserved9;
+ private hb_position_t reserved8;
+ private hb_position_t reserved7;
+ private hb_position_t reserved6;
+ private hb_position_t reserved5;
+ private hb_position_t reserved4;
+ private hb_position_t reserved3;
+ private hb_position_t reserved2;
+ private hb_position_t reserved1;
+
+ public hb_position_t Ascender {
+ get => ascender;
+ set => ascender = value;
+ }
+
+ public hb_position_t Descender {
+ get => descender;
+ set => descender = value;
+ }
+
+ public hb_position_t LineGap {
+ get => line_gap;
+ set => line_gap = value;
+ }
+ }
+
+ public enum UnicodeCombiningClass
+ {
+ NotReordered = 0,
+ Overlay = 1,
+ Nukta = 7,
+ KanaVoicing = 8,
+ Virama = 9,
+
+ // Hebrew
+ CCC10 = 10,
+ CCC11 = 11,
+ CCC12 = 12,
+ CCC13 = 13,
+ CCC14 = 14,
+ CCC15 = 15,
+ CCC16 = 16,
+ CCC17 = 17,
+ CCC18 = 18,
+ CCC19 = 19,
+ CCC20 = 20,
+ CCC21 = 21,
+ CCC22 = 22,
+ CCC23 = 23,
+ CCC24 = 24,
+ CCC25 = 25,
+ CCC26 = 26,
+
+ // Arabic
+ CCC27 = 27,
+ CCC28 = 28,
+ CCC29 = 29,
+ CCC30 = 30,
+ CCC31 = 31,
+ CCC32 = 32,
+ CCC33 = 33,
+ CCC34 = 34,
+ CCC35 = 35,
+
+ // Syriac
+ CCC36 = 36,
+
+ // Telugu
+ CCC84 = 84,
+ CCC91 = 91,
+
+ // Thai
+ CCC103 = 103,
+ CCC107 = 107,
+
+ // Lao
+ CCC118 = 118,
+ CCC122 = 122,
+
+ // Tibetan
+ CCC129 = 129,
+ CCC130 = 130,
+ CCC133 = 132,
+
+ AttachedBelowLeft = 200,
+ AttachedBelow = 202,
+ AttachedAbove = 214,
+ AttachedAboveRight = 216,
+ BelowLeft = 218,
+ Below = 220,
+ BelowRight = 222,
+ Left = 224,
+ Right = 226,
+ AboveLeft = 228,
+ Above = 230,
+ AboveRight = 232,
+ DoubleBelow = 233,
+ DoubleAbove = 234,
+ IotaSubscript = 240,
+
+ Invalid = 255
+ }
+
+ public enum UnicodeGeneralCategory
+ {
+ Control, // Cc
+ Format, // Cf
+ Unassigned, // Cn
+ PrivateUse, // Co
+ Surrogate, // Cs
+
+ LowercaseLetter, // Ll
+ ModifierLetter, // Lm
+ OtherLetter, // Lo
+ TitlecaseLetter, // Lt
+ UppercaseLetter, // Lu
+
+ SpacingMark, // Mc
+ EnclosingMark, // Me
+ NonSpacingMark, // Mn
+
+ DecimalNumber, // Nd
+ LetterNumber, // Nl
+ OtherNumber, // No
+
+ ConnectPunctuation, // Pc
+ DashPunctuation, // Pd
+ ClosePunctuation, // Pe
+ FinalPunctuation, // Pf
+ InitialPunctuation, // Pi
+ OtherPunctuation, // Po
+ OpenPunctuation, // Ps
+
+ CurrencySymbol, // Sc
+ ModifierSymbol, // Sk
+ MathSymbol, // Sm
+ OtherSymbol, // So
+
+ LineSeparator, // Zl
+ ParagraphSeparator, // Zp
+ SpaceSeparator // Zs
+ }
+
+ public enum OpenTypeMetricsTag : uint
+ {
+ HorizontalAscender = (((byte)'h' << 24) | ((byte)'a' << 16) | ((byte)'s' << 8) | (byte)'c'),
+ HorizontalDescender = (((byte)'h' << 24) | ((byte)'d' << 16) | ((byte)'s' << 8) | (byte)'c'),
+ HorizontalLineGap = (((byte)'h' << 24) | ((byte)'l' << 16) | ((byte)'g' << 8) | (byte)'p'),
+ HorizontalClippingAscent = (((byte)'h' << 24) | ((byte)'c' << 16) | ((byte)'l' << 8) | (byte)'a'),
+ HorizontalClippingDescent = (((byte)'h' << 24) | ((byte)'c' << 16) | ((byte)'l' << 8) | (byte)'d'),
+
+ VerticalAscender = (((byte)'v' << 24) | ((byte)'a' << 16) | ((byte)'s' << 8) | (byte)'c'),
+ VerticalDescender = (((byte)'v' << 24) | ((byte)'d' << 16) | ((byte)'s' << 8) | (byte)'c'),
+ VerticalLineGap = (((byte)'v' << 24) | ((byte)'l' << 16) | ((byte)'g' << 8) | (byte)'p'),
+
+ HorizontalCaretRise = (((byte)'h' << 24) | ((byte)'c' << 16) | ((byte)'r' << 8) | (byte)'s'),
+ HorizontalCaretRun = (((byte)'h' << 24) | ((byte)'c' << 16) | ((byte)'r' << 8) | (byte)'n'),
+ HorizontalCaretOffset = (((byte)'h' << 24) | ((byte)'c' << 16) | ((byte)'o' << 8) | (byte)'f'),
+
+ VerticalCaretRise = (((byte)'v' << 24) | ((byte)'c' << 16) | ((byte)'r' << 8) | (byte)'s'),
+ VerticalCaretRun = (((byte)'v' << 24) | ((byte)'c' << 16) | ((byte)'r' << 8) | (byte)'n'),
+ VerticalCaretOffset = (((byte)'v' << 24) | ((byte)'c' << 16) | ((byte)'o' << 8) | (byte)'f'),
+
+ XHeight = (((byte)'x' << 24) | ((byte)'h' << 16) | ((byte)'g' << 8) | (byte)'t'),
+
+ CapHeight = (((byte)'c' << 24) | ((byte)'p' << 16) | ((byte)'h' << 8) | (byte)'t'),
+
+ SubScriptEmXSize = (((byte)'s' << 24) | ((byte)'b' << 16) | ((byte)'x' << 8) | (byte)'s'),
+ SubScriptEmYSize = (((byte)'s' << 24) | ((byte)'b' << 16) | ((byte)'y' << 8) | (byte)'s'),
+ SubScriptEmXOffset = (((byte)'s' << 24) | ((byte)'b' << 16) | ((byte)'x' << 8) | (byte)'o'),
+ SubScriptEmYOffset = (((byte)'s' << 24) | ((byte)'b' << 16) | ((byte)'y' << 8) | (byte)'o'),
+
+ SuperScriptEmXSize = (((byte)'s' << 24) | ((byte)'p' << 16) | ((byte)'x' << 8) | (byte)'s'),
+ SuperScriptEmYSize = (((byte)'s' << 24) | ((byte)'p' << 16) | ((byte)'y' << 8) | (byte)'s'),
+ SuperScriptEmXOffset = (((byte)'s' << 24) | ((byte)'p' << 16) | ((byte)'x' << 8) | (byte)'o'),
+ SuperScriptEmYOffset = (((byte)'s' << 24) | ((byte)'p' << 16) | ((byte)'y' << 8) | (byte)'o'),
+
+ StrikeoutSize = (((byte)'s' << 24) | ((byte)'t' << 16) | ((byte)'r' << 8) | (byte)'s'),
+ StrikeoutOffset = (((byte)'s' << 24) | ((byte)'t' << 16) | ((byte)'r' << 8) | (byte)'o'),
+
+ UnderlineSize = (((byte)'u' << 24) | ((byte)'n' << 16) | ((byte)'d' << 8) | (byte)'s'),
+ UnderlineOffset = (((byte)'u' << 24) | ((byte)'n' << 16) | ((byte)'d' << 8) | (byte)'o'),
+ }
+
+ public readonly struct OpenTypeMetrics
+ {
+ private readonly IntPtr font;
+
+ public OpenTypeMetrics (IntPtr font)
+ {
+ this.font = font;
+ }
+
+ public bool TryGetPosition (OpenTypeMetricsTag metricsTag, out int position) =>
+ HarfBuzzApi.hb_ot_metrics_get_position (font, metricsTag, out position);
+
+ public float GetVariation (OpenTypeMetricsTag metricsTag) =>
+ HarfBuzzApi.hb_ot_metrics_get_variation (font, metricsTag);
+
+ public int GetXVariation (OpenTypeMetricsTag metricsTag) =>
+ HarfBuzzApi.hb_ot_metrics_get_x_variation (font, metricsTag);
+
+ public int GetYVariation (OpenTypeMetricsTag metricsTag) =>
+ HarfBuzzApi.hb_ot_metrics_get_y_variation (font, metricsTag);
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace HarfBuzzSharp
+{
+ // public delegates
+
+ public delegate void ReleaseDelegate ();
+
+ public delegate Blob GetTableDelegate (Face face, Tag tag);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use ReleaseDelegate instead.")]
+ public delegate void BlobReleaseDelegate (object context);
+
+ // internal proxy delegates
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate void ReleaseDelegateProxyDelegate (IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate IntPtr GetTableDelegateProxyDelegate (IntPtr face, Tag tag, IntPtr context);
+
+ internal static partial class DelegateProxies
+ {
+ // references to the proxy implementations
+ public static readonly ReleaseDelegateProxyDelegate ReleaseDelegateProxy = ReleaseDelegateProxyImplementation;
+ public static readonly ReleaseDelegateProxyDelegate ReleaseDelegateProxyForMulti = ReleaseDelegateProxyImplementationForMulti;
+ public static readonly GetTableDelegateProxyDelegate GetTableDelegateProxy = GetTableDelegateProxyImplementation;
+
+ // internal proxy implementations
+
+ [MonoPInvokeCallback (typeof (ReleaseDelegateProxyDelegate))]
+ private static void ReleaseDelegateProxyImplementation (IntPtr context)
+ {
+ var del = Get<ReleaseDelegate> (context, out var gch);
+ try {
+ del.Invoke ();
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ [MonoPInvokeCallback (typeof (GetTableDelegateProxyDelegate))]
+ private static IntPtr GetTableDelegateProxyImplementation (IntPtr face, Tag tag, IntPtr context)
+ {
+ GetMultiUserData<GetTableDelegate, Face> (context, out var getTable, out var userData, out _);
+ var blob = getTable.Invoke (userData, tag);
+ return blob?.Handle ?? IntPtr.Zero;
+ }
+
+ [MonoPInvokeCallback (typeof (ReleaseDelegateProxyDelegate))]
+ private static void ReleaseDelegateProxyImplementationForMulti (IntPtr context)
+ {
+ var del = GetMulti<ReleaseDelegate> (context, out var gch);
+ try {
+ del?.Invoke ();
+ } finally {
+ gch.Free ();
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace HarfBuzzSharp
+{
+ // public delegates
+
+ public delegate bool FontExtentsDelegate (Font font, object fontData, out FontExtents extents);
+
+ public delegate bool NominalGlyphDelegate (Font font, object fontData, uint unicode, out uint glyph);
+
+ public delegate uint NominalGlyphsDelegate (Font font, object fontData, uint count, ReadOnlySpan<uint> codepoints, Span<uint> glyphs);
+
+ public delegate bool VariationGlyphDelegate (Font font, object fontData, uint unicode, uint variationSelector, out uint glyph);
+
+ public delegate int GlyphAdvanceDelegate (Font font, object fontData, uint glyph);
+
+ public delegate void GlyphAdvancesDelegate (Font font, object fontData, uint count, ReadOnlySpan<uint> glyphs, Span<int> advances);
+
+ public delegate bool GlyphOriginDelegate (Font font, object fontData, uint glyph, out int x, out int y);
+
+ public delegate int GlyphKerningDelegate (Font font, object fontData, uint firstGlyph, uint secondGlyph);
+
+ public delegate bool GlyphExtentsDelegate (Font font, object fontData, uint glyph, out GlyphExtents extents);
+
+ public delegate bool GlyphContourPointDelegate (Font font, object fontData, uint glyph, uint pointIndex, out int x, out int y);
+
+ public delegate bool GlyphNameDelegate (Font font, object fontData, uint glyph, out string name);
+
+ public delegate bool GlyphFromNameDelegate (Font font, object fontData, string name, out uint glyph);
+
+ // internal proxy delegates
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal delegate bool FontExtentsProxyDelegate (IntPtr font, IntPtr fontData, out FontExtents extents, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal delegate bool NominalGlyphProxyDelegate (IntPtr font, IntPtr fontData, uint unicode, out uint glyph, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate uint NominalGlyphsProxyDelegate (IntPtr font, IntPtr fontData, uint count, uint* firstUnicode, uint unicodeStride, uint* firstGlyph, uint glyphStride, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal delegate bool VariationGlyphProxyDelegate (IntPtr font, IntPtr fontData, uint unicode, uint variationSelector, out uint glyph, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate int GlyphAdvanceProxyDelegate (IntPtr font, IntPtr fontData, uint glyph, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void GlyphAdvancesProxyDelegate (IntPtr font, IntPtr fontData, uint count, uint* firstGlyph, uint glyphStride, int* firstAdvance, uint advanceStride, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal delegate bool GlyphOriginProxyDelegate (IntPtr font, IntPtr fontData, uint glyph, out int x, out int y, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate int GlyphKerningProxyDelegate (IntPtr font, IntPtr fontData, uint firstGlyph, uint secondGlyph, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal delegate bool GlyphExtentsProxyDelegate (IntPtr font, IntPtr fontData, uint glyph, out GlyphExtents extents, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal delegate bool GlyphContourPointProxyDelegate (IntPtr font, IntPtr fontData, uint glyph, uint pointIndex, out int x, out int y, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool GlyphNameProxyDelegate (IntPtr font, IntPtr fontData, uint glyph, char* name, int size, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool GlyphFromNameProxyDelegate (IntPtr font, IntPtr fontData, char* name, int len, out uint glyph, IntPtr context);
+
+ internal static unsafe partial class DelegateProxies
+ {
+ // references to the proxy implementations
+ public static readonly FontExtentsProxyDelegate FontExtentsProxy = FontExtentsProxyImplementation;
+ public static readonly NominalGlyphProxyDelegate NominalGlyphProxy = NominalGlyphProxyImplementation;
+ public static readonly VariationGlyphProxyDelegate VariationGlyphProxy = VariationGlyphProxyImplementation;
+ public static readonly NominalGlyphsProxyDelegate NominalGlyphsProxy = NominalGlyphsProxyImplementation;
+ public static readonly GlyphAdvanceProxyDelegate GlyphAdvanceProxy = GlyphAdvanceProxyImplementation;
+ public static readonly GlyphAdvancesProxyDelegate GlyphAdvancesProxy = GlyphAdvancesProxyImplementation;
+ public static readonly GlyphOriginProxyDelegate GlyphOriginProxy = GlyphOriginProxyImplementation;
+ public static readonly GlyphKerningProxyDelegate GlyphKerningProxy = GlyphKerningProxyImplementation;
+ public static readonly GlyphExtentsProxyDelegate GlyphExtentsProxy = GlyphExtentsProxyImplementation;
+ public static readonly GlyphContourPointProxyDelegate GlyphContourPointProxy = GlyphContourPointProxyImplementation;
+ public static readonly GlyphNameProxyDelegate GlyphNameProxy = GlyphNameProxyImplementation;
+ public static readonly GlyphFromNameProxyDelegate GlyphFromNameProxy = GlyphFromNameProxyImplementation;
+
+ // internal proxy implementations
+
+ [MonoPInvokeCallback (typeof (FontExtentsProxyDelegate))]
+ private static bool FontExtentsProxyImplementation (IntPtr font, IntPtr fontData, out FontExtents extents, IntPtr context)
+ {
+ var del = GetMulti<FontExtentsDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, out extents);
+ }
+
+ [MonoPInvokeCallback (typeof (NominalGlyphProxyDelegate))]
+ private static bool NominalGlyphProxyImplementation (IntPtr font, IntPtr fontData, uint unicode, out uint glyph, IntPtr context)
+ {
+ var del = GetMulti<NominalGlyphDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, unicode, out glyph);
+ }
+
+ [MonoPInvokeCallback (typeof (NominalGlyphsProxyDelegate))]
+ private static uint NominalGlyphsProxyImplementation (IntPtr font, IntPtr fontData, uint count, uint* firstUnicode, uint unicodeStride, uint* firstGlyph, uint glyphStride, IntPtr context)
+ {
+ var del = GetMulti<NominalGlyphsDelegate> (context, out _);
+ var unicodes = new ReadOnlySpan<uint> (firstUnicode, (int)count);
+ var glyphs = new Span<uint> (firstGlyph, (int)count);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, count, unicodes, glyphs);
+ }
+
+ [MonoPInvokeCallback (typeof (VariationGlyphProxyDelegate))]
+ private static bool VariationGlyphProxyImplementation (IntPtr font, IntPtr fontData, uint unicode, uint variationSelector, out uint glyph, IntPtr context)
+ {
+ var del = GetMulti<VariationGlyphDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, unicode, variationSelector, out glyph);
+ }
+
+ [MonoPInvokeCallback (typeof (GlyphAdvanceProxyDelegate))]
+ private static int GlyphAdvanceProxyImplementation (IntPtr font, IntPtr fontData, uint glyph, IntPtr context)
+ {
+ var del = GetMulti<GlyphAdvanceDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, glyph);
+ }
+
+ [MonoPInvokeCallback (typeof (GlyphAdvancesProxyDelegate))]
+ private static void GlyphAdvancesProxyImplementation (IntPtr font, IntPtr fontData, uint count, uint* firstGlyph, uint glyphStride, int* firstAdvance, uint advanceStride, IntPtr context)
+ {
+ var del = GetMulti<GlyphAdvancesDelegate> (context, out _);
+ var glyphs = new ReadOnlySpan<uint> (firstGlyph, (int)count);
+ var advances = new Span<int> (firstAdvance, (int)count);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ del.Invoke (userData.Font, userData.FontData, count, glyphs, advances);
+ }
+
+ [MonoPInvokeCallback (typeof (GlyphOriginProxyDelegate))]
+ private static bool GlyphOriginProxyImplementation (IntPtr font, IntPtr fontData, uint glyph, out int x, out int y, IntPtr context)
+ {
+ var del = GetMulti<GlyphOriginDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, glyph, out x, out y);
+ }
+
+ [MonoPInvokeCallback (typeof (GlyphKerningProxyDelegate))]
+ private static int GlyphKerningProxyImplementation (IntPtr font, IntPtr fontData, uint firstGlyph, uint secondGlyph, IntPtr context)
+ {
+ var del = GetMulti<GlyphKerningDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, firstGlyph, secondGlyph);
+ }
+
+ [MonoPInvokeCallback (typeof (GlyphExtentsProxyDelegate))]
+ private static bool GlyphExtentsProxyImplementation (IntPtr font, IntPtr fontData, uint glyph, out GlyphExtents extents, IntPtr context)
+ {
+ var del = GetMulti<GlyphExtentsDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, glyph, out extents);
+ }
+
+ [MonoPInvokeCallback (typeof (GlyphContourPointProxyDelegate))]
+ private static bool GlyphContourPointProxyImplementation (IntPtr font, IntPtr fontData, uint glyph, uint pointIndex, out int x, out int y, IntPtr context)
+ {
+ var del = GetMulti<GlyphContourPointDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ return del.Invoke (userData.Font, userData.FontData, glyph, pointIndex, out x, out y);
+ }
+
+ [MonoPInvokeCallback (typeof (GlyphNameProxyDelegate))]
+ private static bool GlyphNameProxyImplementation (IntPtr font, IntPtr fontData, uint glyph, char* nameBuffer, int size, IntPtr context)
+ {
+ var del = GetMulti<GlyphNameDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+ var result = del.Invoke (userData.Font, userData.FontData, glyph, out var realName);
+
+ var nameSpan = realName.AsSpan ();
+ var bufferSpan = new Span<char> (nameBuffer, size);
+ nameSpan.CopyTo (bufferSpan);
+
+ return result;
+ }
+
+ [MonoPInvokeCallback (typeof (GlyphFromNameProxyDelegate))]
+ private static bool GlyphFromNameProxyImplementation (IntPtr font, IntPtr fontData, char* name, int len, out uint glyph, IntPtr context)
+ {
+ var del = GetMulti<GlyphFromNameDelegate> (context, out _);
+ var userData = GetMultiUserData<FontUserData> (fontData, out _);
+
+ var actualName = len < 0
+ ? new string (name)
+ : new string (name, 0, len);
+
+ return del.Invoke (userData.Font, userData.FontData, actualName, out glyph);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Concurrent;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace HarfBuzzSharp
+{
+#if THROW_OBJECT_EXCEPTIONS
+ using GCHandle = GCHandleProxy;
+#endif
+
+ // helper delegates
+
+ internal delegate Delegate GetMultiDelegateDelegate (Type index);
+
+ internal delegate object UserDataDelegate ();
+
+ internal static partial class DelegateProxies
+ {
+ // normal delegates
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static T Create<T> (object managedDel, T nativeDel, out GCHandle gch, out IntPtr contextPtr)
+ {
+ if (managedDel == null) {
+ gch = default (GCHandle);
+ contextPtr = IntPtr.Zero;
+ return default (T);
+ }
+
+ gch = GCHandle.Alloc (managedDel);
+ contextPtr = GCHandle.ToIntPtr (gch);
+ return nativeDel;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void Create (object managedDel, out GCHandle gch, out IntPtr contextPtr)
+ {
+ if (managedDel == null) {
+ gch = default (GCHandle);
+ contextPtr = IntPtr.Zero;
+ return;
+ }
+
+ gch = GCHandle.Alloc (managedDel);
+ contextPtr = GCHandle.ToIntPtr (gch);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static T Get<T> (IntPtr contextPtr, out GCHandle gch)
+ {
+ if (contextPtr == IntPtr.Zero) {
+ gch = default (GCHandle);
+ return default (T);
+ }
+
+ gch = GCHandle.FromIntPtr (contextPtr);
+ return (T)gch.Target;
+ }
+
+ // user data delegates
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateUserData (object userData, bool makeWeak = false)
+ {
+ userData = makeWeak ? new WeakReference (userData) : userData;
+ var del = new UserDataDelegate (() => userData);
+ Create (del, out _, out var ctx);
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static T GetUserData<T> (IntPtr contextPtr, out GCHandle gch)
+ {
+ var del = Get<UserDataDelegate> (contextPtr, out gch);
+ var value = del.Invoke ();
+ return value is WeakReference weak ? (T)weak.Target : (T)value;
+ }
+
+ // multi-value delegates
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMulti<T1, T2> (T1 wrappedDelegate1, T2 wrappedDelegate2)
+ where T1 : Delegate
+ where T2 : Delegate
+ {
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T1))
+ return wrappedDelegate1;
+ if (type == typeof (T2))
+ return wrappedDelegate2;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMulti<T1, T2, T3> (T1 wrappedDelegate1, T2 wrappedDelegate2, T3 wrappedDelegate3)
+ where T1 : Delegate
+ where T2 : Delegate
+ where T3 : Delegate
+ {
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T1))
+ return wrappedDelegate1;
+ if (type == typeof (T2))
+ return wrappedDelegate2;
+ if (type == typeof (T3))
+ return wrappedDelegate3;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static T GetMulti<T> (IntPtr contextPtr, out GCHandle gch)
+ where T : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ return (T)multi.Invoke (typeof (T));
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMulti<T1, T2> (IntPtr contextPtr, out T1 wrappedDelegate1, out T2 wrappedDelegate2, out GCHandle gch)
+ where T1 : Delegate
+ where T2 : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate1 = (T1)multi.Invoke (typeof (T1));
+ wrappedDelegate2 = (T2)multi.Invoke (typeof (T2));
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMulti<T1, T2, T3> (IntPtr contextPtr, out T1 wrappedDelegate1, out T2 wrappedDelegate2, out T3 wrappedDelegate3, out GCHandle gch)
+ where T1 : Delegate
+ where T2 : Delegate
+ where T3 : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate1 = (T1)multi.Invoke (typeof (T1));
+ wrappedDelegate2 = (T2)multi.Invoke (typeof (T2));
+ wrappedDelegate3 = (T3)multi.Invoke (typeof (T3));
+ }
+
+ // multi-value delegate with user data
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMultiUserData<T> (T wrappedDelegate, object userData, bool makeWeak = false)
+ where T : Delegate
+ {
+ userData = makeWeak ? new WeakReference (userData) : userData;
+ var userDataDelegate = new UserDataDelegate (() => userData);
+
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T))
+ return wrappedDelegate;
+ if (type == typeof (UserDataDelegate))
+ return userDataDelegate;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMultiUserData<T1, T2> (T1 wrappedDelegate1, T2 wrappedDelegate2, object userData, bool makeWeak = false)
+ where T1 : Delegate
+ where T2 : Delegate
+ {
+ userData = makeWeak ? new WeakReference (userData) : userData;
+ var userDataDelegate = new UserDataDelegate (() => userData);
+
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T1))
+ return wrappedDelegate1;
+ if (type == typeof (T2))
+ return wrappedDelegate2;
+ if (type == typeof (UserDataDelegate))
+ return userDataDelegate;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMultiUserData<T1, T2, T3> (T1 wrappedDelegate1, T2 wrappedDelegate2, T3 wrappedDelegate3, object userData, bool makeWeak = false)
+ where T1 : Delegate
+ where T2 : Delegate
+ where T3 : Delegate
+ {
+ userData = makeWeak ? new WeakReference (userData) : userData;
+ var userDataDelegate = new UserDataDelegate (() => userData);
+
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T1))
+ return wrappedDelegate1;
+ if (type == typeof (T2))
+ return wrappedDelegate2;
+ if (type == typeof (T3))
+ return wrappedDelegate3;
+ if (type == typeof (UserDataDelegate))
+ return userDataDelegate;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static TUserData GetMultiUserData<TUserData> (IntPtr contextPtr, out GCHandle gch)
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ return GetUserData<TUserData> (multi);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMultiUserData<T, TUserData> (IntPtr contextPtr, out T wrappedDelegate, out TUserData userData, out GCHandle gch)
+ where T : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate = (T)multi.Invoke (typeof (T));
+ userData = GetUserData<TUserData> (multi);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMultiUserData<T1, T2, TUserData> (IntPtr contextPtr, out T1 wrappedDelegate1, out T2 wrappedDelegate2, out TUserData userData, out GCHandle gch)
+ where T1 : Delegate
+ where T2 : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate1 = (T1)multi.Invoke (typeof (T1));
+ wrappedDelegate2 = (T2)multi.Invoke (typeof (T2));
+ userData = GetUserData<TUserData> (multi);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMultiUserData<T1, T2, T3, TUserData> (IntPtr contextPtr, out T1 wrappedDelegate1, out T2 wrappedDelegate2, out T3 wrappedDelegate3, out TUserData userData, out GCHandle gch)
+ where T1 : Delegate
+ where T2 : Delegate
+ where T3 : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate1 = (T1)multi.Invoke (typeof (T1));
+ wrappedDelegate2 = (T2)multi.Invoke (typeof (T2));
+ wrappedDelegate3 = (T3)multi.Invoke (typeof (T3));
+ userData = GetUserData<TUserData> (multi);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static TUserData GetUserData<TUserData> (GetMultiDelegateDelegate multi)
+ {
+ var userDataDelegate = (UserDataDelegate)multi.Invoke (typeof (UserDataDelegate));
+ var value = userDataDelegate.Invoke ();
+ return value is WeakReference weak ? (TUserData)weak.Target : (TUserData)value;
+ }
+ }
+
+#if THROW_OBJECT_EXCEPTIONS
+ // an internal, debug-only proxy that we can use to make sure we are not
+ // leaking GC handles by accident
+ internal struct GCHandleProxy
+ {
+ internal static readonly ConcurrentDictionary<IntPtr, WeakReference> allocatedHandles = new ConcurrentDictionary<IntPtr, WeakReference> ();
+
+ private System.Runtime.InteropServices.GCHandle gch;
+
+ public GCHandleProxy (System.Runtime.InteropServices.GCHandle gcHandle)
+ {
+ gch = gcHandle;
+ }
+
+ public bool IsAllocated => gch.IsAllocated;
+
+ public object Target => gch.Target;
+
+ public void Free ()
+ {
+ if (!allocatedHandles.TryRemove (ToIntPtr (this), out _))
+ throw new InvalidOperationException ($"Allocated GC handle has already been freed.");
+
+ gch.Free ();
+ }
+
+ internal static GCHandleProxy Alloc (object value)
+ {
+ var gch = new GCHandleProxy (System.Runtime.InteropServices.GCHandle.Alloc (value));
+
+ var weak = new WeakReference (value);
+ var oldWeak = allocatedHandles.GetOrAdd (ToIntPtr (gch), weak);
+ if (weak != oldWeak)
+ throw new InvalidOperationException (
+ $"GC handle has already been allocated for this memory location. " +
+ $"Old: {oldWeak.Target} New: {value}");
+
+ return gch;
+ }
+
+ internal static GCHandleProxy FromIntPtr (IntPtr value) =>
+ new GCHandleProxy (System.Runtime.InteropServices.GCHandle.FromIntPtr (value));
+
+ internal static IntPtr ToIntPtr (GCHandleProxy value) =>
+ System.Runtime.InteropServices.GCHandle.ToIntPtr (value.gch);
+ }
+#endif
+
+ [AttributeUsage (AttributeTargets.Method)]
+ internal sealed class MonoPInvokeCallbackAttribute : Attribute
+ {
+ public MonoPInvokeCallbackAttribute (Type type)
+ {
+ Type = type;
+ }
+
+ public Type Type { get; private set; }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace HarfBuzzSharp
+{
+ // public delegates
+
+ public delegate UnicodeCombiningClass CombiningClassDelegate (UnicodeFunctions ufuncs, uint unicode);
+
+ public delegate UnicodeGeneralCategory GeneralCategoryDelegate (UnicodeFunctions ufuncs, uint unicode);
+
+ public delegate uint MirroringDelegate (UnicodeFunctions ufuncs, uint unicode);
+
+ public delegate Script ScriptDelegate (UnicodeFunctions ufuncs, uint unicode);
+
+ public delegate bool ComposeDelegate (UnicodeFunctions ufuncs, uint a, uint b, out uint ab);
+
+ public delegate bool DecomposeDelegate (UnicodeFunctions ufuncs, uint ab, out uint a, out uint b);
+
+ // internal proxy delegates
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate UnicodeCombiningClass hb_unicode_combining_class_func_t (IntPtr ufuncs, uint unicode, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate UnicodeGeneralCategory hb_unicode_general_category_func_t (IntPtr ufuncs, uint unicode, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate uint hb_unicode_mirroring_func_t (IntPtr ufuncs, uint unicode, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal delegate uint hb_unicode_script_func_t (IntPtr ufuncs, uint unicode, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal delegate bool hb_unicode_compose_func_t (IntPtr ufuncs, uint a, uint b, out uint ab, IntPtr context);
+
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal delegate bool hb_unicode_decompose_func_t (IntPtr ufuncs, uint ab, out uint a, out uint b, IntPtr context);
+
+ internal static partial class DelegateProxies
+ {
+ public static readonly hb_unicode_combining_class_func_t CombiningClassProxy = CombiningClassProxyImplementation;
+ public static readonly hb_unicode_general_category_func_t GeneralCategoryProxy = GeneralCategoryProxyImplementation;
+ public static readonly hb_unicode_mirroring_func_t MirroringProxy = MirroringProxyImplementation;
+ public static readonly hb_unicode_script_func_t ScriptProxy = ScriptProxyImplementation;
+ public static readonly hb_unicode_compose_func_t ComposeProxy = ComposeProxyImplementation;
+ public static readonly hb_unicode_decompose_func_t DecomposeProxy = DecomposeProxyImplementation;
+
+ [MonoPInvokeCallback (typeof (hb_unicode_combining_class_func_t))]
+ private static UnicodeCombiningClass CombiningClassProxyImplementation (IntPtr ufuncs, uint unicode, IntPtr context)
+ {
+ GetMultiUserData<CombiningClassDelegate, UnicodeFunctions> (context, out var del, out var functions, out _);
+ return del.Invoke (functions, unicode);
+ }
+
+ [MonoPInvokeCallback (typeof (hb_unicode_general_category_func_t))]
+ private static UnicodeGeneralCategory GeneralCategoryProxyImplementation (IntPtr ufuncs, uint unicode, IntPtr context)
+ {
+ GetMultiUserData<GeneralCategoryDelegate, UnicodeFunctions> (context, out var del, out var functions, out _);
+ return del.Invoke (functions, unicode);
+ }
+
+ [MonoPInvokeCallback (typeof (hb_unicode_mirroring_func_t))]
+ private static uint MirroringProxyImplementation (IntPtr ufuncs, uint unicode, IntPtr context)
+ {
+ GetMultiUserData<MirroringDelegate, UnicodeFunctions> (context, out var del, out var functions, out _);
+ return del.Invoke (functions, unicode);
+ }
+
+ [MonoPInvokeCallback (typeof (hb_unicode_script_func_t))]
+ private static uint ScriptProxyImplementation (IntPtr ufuncs, uint unicode, IntPtr context)
+ {
+ GetMultiUserData<ScriptDelegate, UnicodeFunctions> (context, out var del, out var functions, out _);
+ return del.Invoke (functions, unicode);
+ }
+
+ [MonoPInvokeCallback (typeof (hb_unicode_compose_func_t))]
+ private static bool ComposeProxyImplementation (IntPtr ufuncs, uint a, uint b, out uint ab, IntPtr context)
+ {
+ GetMultiUserData<ComposeDelegate, UnicodeFunctions> (context, out var del, out var functions, out _);
+ return del.Invoke (functions, a, b, out ab);
+ }
+
+ [MonoPInvokeCallback (typeof (hb_unicode_decompose_func_t))]
+ private static bool DecomposeProxyImplementation (IntPtr ufuncs, uint ab, out uint a, out uint b, IntPtr context)
+ {
+ GetMultiUserData<DecomposeDelegate, UnicodeFunctions> (context, out var del, out var functions, out _);
+ return del.Invoke (functions, ab, out a, out b);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace HarfBuzzSharp
+{
+ public class Face : NativeObject
+ {
+ private static readonly Lazy<Face> emptyFace = new Lazy<Face> (() => new StaticFace (HarfBuzzApi.hb_face_get_empty ()));
+
+ public static Face Empty => emptyFace.Value;
+
+ public Face (Blob blob, uint index)
+ : this (blob, (int)index)
+ {
+ }
+
+ public Face (Blob blob, int index)
+ : this (IntPtr.Zero)
+ {
+ if (blob == null) {
+ throw new ArgumentNullException (nameof (blob));
+ }
+
+ if (index < 0) {
+ throw new ArgumentOutOfRangeException (nameof (index), "Index must be non negative.");
+ }
+
+ Handle = HarfBuzzApi.hb_face_create (blob.Handle, index);
+ }
+
+ public Face (GetTableDelegate getTable)
+ : this (getTable, null)
+ {
+ }
+
+ public Face (GetTableDelegate getTable, ReleaseDelegate destroy)
+ : this (IntPtr.Zero)
+ {
+ if (getTable == null)
+ throw new ArgumentNullException (nameof (getTable));
+
+ Handle = HarfBuzzApi.hb_face_create_for_tables (
+ DelegateProxies.GetTableDelegateProxy,
+ DelegateProxies.CreateMultiUserData (getTable, destroy, this),
+ DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ internal Face (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ public int Index {
+ get => HarfBuzzApi.hb_face_get_index (Handle);
+ set => HarfBuzzApi.hb_face_set_index (Handle, value);
+ }
+
+ public int UnitsPerEm {
+ get => HarfBuzzApi.hb_face_get_upem (Handle);
+ set => HarfBuzzApi.hb_face_set_upem (Handle, value);
+ }
+
+ public int GlyphCount {
+ get => HarfBuzzApi.hb_face_get_glyph_count (Handle);
+ set => HarfBuzzApi.hb_face_set_glyph_count (Handle, value);
+ }
+
+ public unsafe Tag[] Tables {
+ get {
+ var tableCount = 0;
+ var count = HarfBuzzApi.hb_face_get_table_tags (Handle, 0, ref tableCount, IntPtr.Zero);
+ var buffer = new Tag[count];
+ fixed (Tag* ptr = buffer) {
+ HarfBuzzApi.hb_face_get_table_tags (Handle, 0, ref count, (IntPtr)ptr);
+ }
+ return buffer;
+ }
+ }
+
+ public Blob ReferenceTable (Tag table) =>
+ new Blob (HarfBuzzApi.hb_face_reference_table (Handle, table));
+
+ public bool IsImmutable => HarfBuzzApi.hb_face_is_immutable (Handle);
+
+ public void MakeImmutable () => HarfBuzzApi.hb_face_make_immutable (Handle);
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeHandler ()
+ {
+ if (Handle != IntPtr.Zero) {
+ HarfBuzzApi.hb_face_destroy (Handle);
+ }
+ }
+
+ private class StaticFace : Face
+ {
+ public StaticFace (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Buffers;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+
+namespace HarfBuzzSharp
+{
+ public class Font : NativeObject
+ {
+ internal const int NameBufferLength = 128;
+
+ public Font (Face face)
+ : base (IntPtr.Zero)
+ {
+ if (face == null)
+ throw new ArgumentNullException (nameof (face));
+
+ Handle = HarfBuzzApi.hb_font_create (face.Handle);
+ OpenTypeMetrics = new OpenTypeMetrics (Handle);
+ }
+
+ public Font (Font parent)
+ : base (IntPtr.Zero)
+ {
+ if (parent == null)
+ throw new ArgumentNullException (nameof (parent));
+ if (parent.Handle == IntPtr.Zero)
+ throw new ArgumentException (nameof (parent.Handle));
+
+ Parent = parent;
+ Handle = HarfBuzzApi.hb_font_create_sub_font (parent.Handle);
+ OpenTypeMetrics = new OpenTypeMetrics (Handle);
+ }
+
+ public Font Parent { get; }
+
+ public OpenTypeMetrics OpenTypeMetrics { get; }
+
+ public string[] SupportedShapers =>
+ PtrToStringArray (HarfBuzzApi.hb_shape_list_shapers ()).ToArray ();
+
+ public void SetFontFunctions (FontFunctions fontFunctions) =>
+ SetFontFunctions (fontFunctions, null, null);
+
+ public void SetFontFunctions (FontFunctions fontFunctions, object fontData) =>
+ SetFontFunctions (fontFunctions, fontData, null);
+
+ public void SetFontFunctions (FontFunctions fontFunctions, object fontData, ReleaseDelegate destroy)
+ {
+ _ = fontFunctions ?? throw new ArgumentNullException (nameof (fontFunctions));
+
+ var container = new FontUserData (this, fontData);
+ var ctx = DelegateProxies.CreateMultiUserData (destroy, container);
+ HarfBuzzApi.hb_font_set_funcs (Handle, fontFunctions.Handle, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void GetScale (out int xScale, out int yScale) =>
+ HarfBuzzApi.hb_font_get_scale (Handle, out xScale, out yScale);
+
+ public void SetScale (int xScale, int yScale) =>
+ HarfBuzzApi.hb_font_set_scale (Handle, xScale, yScale);
+
+ public bool TryGetHorizontalFontExtents (out FontExtents extents) =>
+ HarfBuzzApi.hb_font_get_h_extents (Handle, out extents);
+
+ public bool TryGetVerticalFontExtents (out FontExtents extents) =>
+ HarfBuzzApi.hb_font_get_v_extents (Handle, out extents);
+
+ public bool TryGetNominalGlyph (int unicode, out uint glyph) =>
+ TryGetNominalGlyph ((uint)unicode, out glyph);
+
+ public bool TryGetNominalGlyph (uint unicode, out uint glyph) =>
+ HarfBuzzApi.hb_font_get_nominal_glyph (Handle, unicode, out glyph);
+
+ public bool TryGetVariationGlyph (int unicode, out uint glyph) =>
+ TryGetVariationGlyph (unicode, 0, out glyph);
+
+ public bool TryGetVariationGlyph (uint unicode, out uint glyph) =>
+ HarfBuzzApi.hb_font_get_variation_glyph (Handle, unicode, 0, out glyph);
+
+ public bool TryGetVariationGlyph (int unicode, uint variationSelector, out uint glyph) =>
+ TryGetVariationGlyph ((uint)unicode, variationSelector, out glyph);
+
+ public bool TryGetVariationGlyph (uint unicode, uint variationSelector, out uint glyph) =>
+ HarfBuzzApi.hb_font_get_variation_glyph (Handle, unicode, variationSelector, out glyph);
+
+ public int GetHorizontalGlyphAdvance (uint glyph) =>
+ HarfBuzzApi.hb_font_get_glyph_h_advance (Handle, glyph);
+
+ public int GetVerticalGlyphAdvance (uint glyph) =>
+ HarfBuzzApi.hb_font_get_glyph_v_advance (Handle, glyph);
+
+ public unsafe int[] GetHorizontalGlyphAdvances (ReadOnlySpan<uint> glyphs)
+ {
+ fixed (uint* firstGlyph = glyphs) {
+ return GetHorizontalGlyphAdvances ((IntPtr)firstGlyph, glyphs.Length);
+ }
+ }
+
+ public unsafe int[] GetHorizontalGlyphAdvances (IntPtr firstGlyph, int count)
+ {
+ var advances = new int[count];
+
+ fixed (int* firstAdvance = advances) {
+ HarfBuzzApi.hb_font_get_glyph_h_advances (Handle, count, firstGlyph, 4, (IntPtr)firstAdvance, 4);
+ }
+
+ return advances;
+ }
+
+ public unsafe int[] GetVerticalGlyphAdvances (ReadOnlySpan<uint> glyphs)
+ {
+ fixed (uint* firstGlyph = glyphs) {
+ return GetVerticalGlyphAdvances ((IntPtr)firstGlyph, glyphs.Length);
+ }
+ }
+
+ public unsafe int[] GetVerticalGlyphAdvances (IntPtr firstGlyph, int count)
+ {
+ var advances = new int[count];
+
+ fixed (int* firstAdvance = advances) {
+ HarfBuzzApi.hb_font_get_glyph_v_advances (Handle, count, firstGlyph, 4, (IntPtr)firstAdvance, 4);
+ }
+
+ return advances;
+ }
+
+ public bool TryGetHorizontalGlyphOrigin (uint glyph, out int xOrigin, out int yOrigin) =>
+ HarfBuzzApi.hb_font_get_glyph_h_origin (Handle, glyph, out xOrigin, out yOrigin);
+
+ public bool TryGetVerticalGlyphOrigin (uint glyph, out int xOrigin, out int yOrigin) =>
+ HarfBuzzApi.hb_font_get_glyph_v_origin (Handle, glyph, out xOrigin, out yOrigin);
+
+ public int GetHorizontalGlyphKerning (uint leftGlyph, uint rightGlyph) =>
+ HarfBuzzApi.hb_font_get_glyph_h_kerning (Handle, leftGlyph, rightGlyph);
+
+ public bool TryGetGlyphExtents (uint glyph, out GlyphExtents extents) =>
+ HarfBuzzApi.hb_font_get_glyph_extents (Handle, glyph, out extents);
+
+ public bool TryGetGlyphContourPoint (uint glyph, uint pointIndex, out int x, out int y) =>
+ HarfBuzzApi.hb_font_get_glyph_contour_point (Handle, glyph, pointIndex, out x, out y);
+
+ public unsafe bool TryGetGlyphName (uint glyph, out string name)
+ {
+ var buffer = ArrayPool<byte>.Shared.Rent (NameBufferLength);
+ try {
+ fixed (byte* first = buffer) {
+ if (!HarfBuzzApi.hb_font_get_glyph_name (Handle, glyph, first, buffer.Length)) {
+ name = string.Empty;
+ return false;
+ }
+ name = Marshal.PtrToStringAnsi ((IntPtr)first);
+ return true;
+ }
+ } finally {
+ ArrayPool<byte>.Shared.Return (buffer);
+ }
+ }
+
+ public bool TryGetGlyphFromName (string name, out uint glyph) =>
+ HarfBuzzApi.hb_font_get_glyph_from_name (Handle, name, name.Length, out glyph);
+
+ public bool TryGetGlyph (int unicode, out uint glyph) =>
+ TryGetGlyph ((uint)unicode, 0, out glyph);
+
+ public bool TryGetGlyph (uint unicode, out uint glyph) =>
+ TryGetGlyph (unicode, 0, out glyph);
+
+ public bool TryGetGlyph (int unicode, uint variationSelector, out uint glyph) =>
+ TryGetGlyph ((uint)unicode, variationSelector, out glyph);
+
+ public bool TryGetGlyph (uint unicode, uint variationSelector, out uint glyph) =>
+ HarfBuzzApi.hb_font_get_glyph (Handle, unicode, variationSelector, out glyph);
+
+ public FontExtents GetFontExtentsForDirection (Direction direction)
+ {
+ HarfBuzzApi.hb_font_get_extents_for_direction (Handle, direction, out var extents);
+ return extents;
+ }
+
+ public void GetGlyphAdvanceForDirection (uint glyph, Direction direction, out int x, out int y) =>
+ HarfBuzzApi.hb_font_get_glyph_advance_for_direction (Handle, glyph, direction, out x, out y);
+
+ public unsafe int[] GetGlyphAdvancesForDirection (ReadOnlySpan<uint> glyphs, Direction direction)
+ {
+ fixed (uint* firstGlyph = glyphs) {
+ return GetGlyphAdvancesForDirection ((IntPtr)firstGlyph, glyphs.Length, direction);
+ }
+ }
+
+ public unsafe int[] GetGlyphAdvancesForDirection (IntPtr firstGlyph, int count, Direction direction)
+ {
+ var advances = new int[count];
+
+ fixed (int* firstAdvance = advances) {
+ HarfBuzzApi.hb_font_get_glyph_advances_for_direction (Handle, direction, count, firstGlyph, 4, (IntPtr)firstAdvance, 4);
+ }
+
+ return advances;
+ }
+
+ public bool TryGetGlyphContourPointForOrigin (uint glyph, uint pointIndex, Direction direction, out int x, out int y) =>
+ HarfBuzzApi.hb_font_get_glyph_contour_point_for_origin (Handle, glyph, pointIndex, direction, out x, out y);
+
+ public unsafe string GlyphToString (uint glyph)
+ {
+ var buffer = ArrayPool<byte>.Shared.Rent (NameBufferLength);
+ try {
+ fixed (byte* first = buffer) {
+ HarfBuzzApi.hb_font_glyph_to_string (Handle, glyph, first, buffer.Length);
+ return Marshal.PtrToStringAnsi ((IntPtr)first);
+ }
+ } finally {
+ ArrayPool<byte>.Shared.Return (buffer);
+ }
+ }
+
+ public bool TryGetGlyphFromString (string s, out uint glyph) =>
+ HarfBuzzApi.hb_font_glyph_from_string (Handle, s, -1, out glyph);
+
+ public void SetFunctionsOpenType () =>
+ HarfBuzzApi.hb_ot_font_set_funcs (Handle);
+
+ public void Shape (Buffer buffer, params Feature[] features) =>
+ Shape (buffer, features, null);
+
+ public void Shape (Buffer buffer, IReadOnlyList<Feature> features, IReadOnlyList<string> shapers)
+ {
+ if (buffer == null)
+ throw new ArgumentNullException (nameof (buffer));
+
+ if (buffer.Direction == Direction.Invalid)
+ throw new InvalidOperationException ("Buffer's Direction must be valid.");
+
+ if (buffer.ContentType != ContentType.Unicode) {
+ throw new InvalidOperationException ("Buffer's ContentType must of type Unicode.");
+ }
+
+ var featuresPtr = features == null || features.Count == 0 ? IntPtr.Zero : StructureArrayToPtr (features);
+ var shapersPtr = shapers == null || shapers.Count == 0 ? IntPtr.Zero : StructureArrayToPtr (shapers);
+
+ HarfBuzzApi.hb_shape_full (
+ Handle,
+ buffer.Handle,
+ featuresPtr,
+ features?.Count ?? 0,
+ shapersPtr);
+
+ if (featuresPtr != IntPtr.Zero)
+ Marshal.FreeCoTaskMem (featuresPtr);
+ if (shapersPtr != IntPtr.Zero)
+ Marshal.FreeCoTaskMem (shapersPtr);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeHandler ()
+ {
+ if (Handle != IntPtr.Zero) {
+ HarfBuzzApi.hb_font_destroy (Handle);
+ }
+ }
+ }
+
+ internal class FontUserData
+ {
+ public FontUserData (Font font, object fontData)
+ {
+ Font = font;
+ FontData = fontData;
+ }
+
+ public Font Font { get; }
+
+ public object FontData { get; }
+ }
+}
--- /dev/null
+using System;
+
+namespace HarfBuzzSharp
+{
+ public class FontFunctions : NativeObject
+ {
+ private static readonly Lazy<FontFunctions> emptyFontFunctions =
+ new Lazy<FontFunctions> (() => new StaticFontFunctions (HarfBuzzApi.hb_font_funcs_get_empty ()));
+
+ public FontFunctions ()
+ : this (HarfBuzzApi.hb_font_funcs_create ())
+ {
+ }
+
+ internal FontFunctions (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ public static FontFunctions Empty => emptyFontFunctions.Value;
+
+ public bool IsImmutable => HarfBuzzApi.hb_font_funcs_is_immutable (Handle);
+
+ public void MakeImmutable () => HarfBuzzApi.hb_font_funcs_make_immutable (Handle);
+
+ public void SetHorizontalFontExtentsDelegate (FontExtentsDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_font_h_extents_func (
+ Handle, DelegateProxies.FontExtentsProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetVerticalFontExtentsDelegate (FontExtentsDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_font_v_extents_func (
+ Handle, DelegateProxies.FontExtentsProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetNominalGlyphDelegate (NominalGlyphDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_nominal_glyph_func (
+ Handle, DelegateProxies.NominalGlyphProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetNominalGlyphsDelegate (NominalGlyphsDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_nominal_glyphs_func (
+ Handle, DelegateProxies.NominalGlyphsProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetVariationGlyphDelegate (VariationGlyphDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_variation_glyph_func (
+ Handle, DelegateProxies.VariationGlyphProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetHorizontalGlyphAdvanceDelegate (GlyphAdvanceDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_h_advance_func (
+ Handle, DelegateProxies.GlyphAdvanceProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetVerticalGlyphAdvanceDelegate (GlyphAdvanceDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_v_advance_func (
+ Handle, DelegateProxies.GlyphAdvanceProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetHorizontalGlyphAdvancesDelegate (GlyphAdvancesDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_h_advances_func (
+ Handle, DelegateProxies.GlyphAdvancesProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetVerticalGlyphAdvancesDelegate (GlyphAdvancesDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_v_advances_func (
+ Handle, DelegateProxies.GlyphAdvancesProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetHorizontalGlyphOriginDelegate (GlyphOriginDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_h_origin_func (
+ Handle, DelegateProxies.GlyphOriginProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetVerticalGlyphOriginDelegate (GlyphOriginDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_v_origin_func (
+ Handle, DelegateProxies.GlyphOriginProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetHorizontalGlyphKerningDelegate (GlyphKerningDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_h_kerning_func (
+ Handle, DelegateProxies.GlyphKerningProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetGlyphExtentsDelegate (GlyphExtentsDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_extents_func (
+ Handle, DelegateProxies.GlyphExtentsProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+ public void SetGlyphContourPointDelegate (GlyphContourPointDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_contour_point_func (
+ Handle, DelegateProxies.GlyphContourPointProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetGlyphNameDelegate (GlyphNameDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_name_func (
+ Handle, DelegateProxies.GlyphNameProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetGlyphFromNameDelegate (GlyphFromNameDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMulti (del, destroy);
+
+ HarfBuzzApi.hb_font_funcs_set_glyph_from_name_func (
+ Handle, DelegateProxies.GlyphFromNameProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeHandler ()
+ {
+ if (Handle != IntPtr.Zero) {
+ HarfBuzzApi.hb_font_funcs_destroy (Handle);
+ }
+ }
+
+ private void VerifyParameters (Delegate del)
+ {
+ _ = del ?? throw new ArgumentNullException (nameof (del));
+
+ if (IsImmutable)
+ throw new InvalidOperationException ($"{nameof (FontFunctions)} is immutable and can't be changed.");
+ }
+
+ private class StaticFontFunctions : FontFunctions
+ {
+ public StaticFontFunctions (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+#pragma warning disable IDE1006 // Naming Styles
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using hb_blob_t = System.IntPtr;
+using hb_bool_t = System.Boolean;
+using hb_buffer_t = System.IntPtr;
+using hb_codepoint_t = System.UInt32;
+using hb_destroy_func_t = HarfBuzzSharp.ReleaseDelegateProxyDelegate;
+using hb_direction_t = HarfBuzzSharp.Direction;
+using hb_face_t = System.IntPtr;
+using hb_font_extents_t = HarfBuzzSharp.FontExtents;
+using hb_font_funcs_t = System.IntPtr;
+using hb_font_t = System.IntPtr;
+using hb_position_t = System.Int32;
+using hb_script_t = System.UInt32;
+using hb_unicode_funcs_t = System.IntPtr;
+
+namespace HarfBuzzSharp
+{
+ internal unsafe class HarfBuzzApi
+ {
+ private const string HARFBUZZ = "libHarfBuzzSharp.2.6.1.so";
+
+ // hb_blob_t
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_blob_t hb_blob_create (IntPtr data, int length, MemoryMode mode, IntPtr user_data, ReleaseDelegateProxyDelegate destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_blob_destroy (hb_blob_t blob);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_blob_make_immutable (hb_blob_t blob);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_blob_is_immutable (hb_blob_t blob);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static int hb_blob_get_length (hb_blob_t blob);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static byte* hb_blob_get_data (hb_blob_t blob, out int length);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_blob_t hb_blob_create_from_file ([MarshalAs (UnmanagedType.LPStr)] string file_name);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_blob_t hb_blob_get_empty ();
+
+ // hb_face_t
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static int hb_face_count (hb_blob_t blob);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_face_t hb_face_create (hb_blob_t blob, int index);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_face_t hb_face_create_for_tables (GetTableDelegateProxyDelegate reference_table_func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_face_t hb_face_get_empty ();
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_face_destroy (hb_face_t face);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_face_set_index (hb_face_t face, int index);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static int hb_face_get_index (hb_face_t face);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_face_set_upem (hb_face_t face, int upem);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static int hb_face_get_upem (hb_face_t face);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_face_set_glyph_count (hb_face_t face, int glyph_count);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static int hb_face_get_glyph_count (hb_face_t face);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_face_make_immutable (hb_face_t face);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_face_is_immutable (hb_face_t face);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_blob_t hb_face_reference_table (hb_face_t face, Tag tag);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static int hb_face_get_table_tags (hb_face_t face, int start_offset, ref int table_count, IntPtr table_tags);
+
+ // hb_font_funcs_t
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_font_funcs_t hb_font_funcs_create ();
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_font_funcs_t hb_font_funcs_get_empty ();
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_destroy (hb_font_funcs_t ffuncs);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_make_immutable (hb_font_funcs_t ffuncs);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_funcs_is_immutable (hb_font_funcs_t ffuncs);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_font_h_extents_func (hb_font_funcs_t ffuncs, FontExtentsProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_font_v_extents_func (hb_font_funcs_t ffuncs, FontExtentsProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_nominal_glyph_func (hb_font_funcs_t ffuncs, NominalGlyphProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_nominal_glyphs_func (hb_font_funcs_t ffuncs, NominalGlyphsProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_variation_glyph_func (hb_font_funcs_t ffuncs, VariationGlyphProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_h_advance_func (hb_font_funcs_t ffuncs, GlyphAdvanceProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_v_advance_func (hb_font_funcs_t ffuncs, GlyphAdvanceProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_h_advances_func (hb_font_funcs_t ffuncs, GlyphAdvancesProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_v_advances_func (hb_font_funcs_t ffuncs, GlyphAdvancesProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_h_origin_func (hb_font_funcs_t ffuncs, GlyphOriginProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t ffuncs, GlyphOriginProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_h_kerning_func (hb_font_funcs_t ffuncs, GlyphKerningProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_extents_func (hb_font_funcs_t ffuncs, GlyphExtentsProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_contour_point_func (hb_font_funcs_t ffuncs, GlyphContourPointProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_name_func (hb_font_funcs_t ffuncs, GlyphNameProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t ffuncs, GlyphFromNameProxyDelegate func, IntPtr user_data, hb_destroy_func_t destroy);
+
+ // hb_font_t
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_font_t hb_font_create (hb_face_t face);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_font_t hb_font_create_sub_font (hb_font_t parent);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_destroy (hb_font_t font);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_set_funcs (hb_font_t font, hb_font_funcs_t klass, IntPtr font_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_set_scale (hb_font_t font, int x_scale, int y_scale);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_get_scale (hb_font_t font, out int x_scale, out int y_scale);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_h_extents (hb_font_t font, out hb_font_extents_t extents);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_v_extents (hb_font_t font, out hb_font_extents_t extents);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_nominal_glyph (hb_font_t font, hb_codepoint_t unicode, out hb_codepoint_t glyph);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_variation_glyph (hb_font_t font, hb_codepoint_t unicode, hb_codepoint_t variation_selector, out hb_codepoint_t glyph);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_position_t hb_font_get_glyph_h_advance (hb_font_t font, hb_codepoint_t glyph);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_position_t hb_font_get_glyph_v_advance (hb_font_t font, hb_codepoint_t glyph);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_get_glyph_h_advances (hb_font_t font, int count, IntPtr first_glyph, uint glyph_stride, IntPtr first_advance, uint advance_stride);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_get_glyph_v_advances (hb_font_t font, int count, IntPtr first_glyph, uint glyph_stride, IntPtr first_advance, uint advance_stride);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_glyph_h_origin (hb_font_t font, hb_codepoint_t glyph, out hb_position_t x, out hb_position_t y);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_glyph_v_origin (hb_font_t font, hb_codepoint_t glyph, out hb_position_t x, out hb_position_t y);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_position_t hb_font_get_glyph_h_kerning (hb_font_t font, hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_glyph_extents (hb_font_t font, hb_codepoint_t glyph, out GlyphExtents extents);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_glyph_contour_point (hb_font_t font, hb_codepoint_t glyph, uint point_index, out hb_position_t x, out hb_position_t y);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_glyph_name (hb_font_t font, hb_codepoint_t glyph, byte* nameBuffer, int size);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_glyph_from_name (hb_font_t font, [MarshalAs (UnmanagedType.LPStr)]string name, int len, out hb_codepoint_t glyph);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_glyph (hb_font_t font, hb_codepoint_t unicode, hb_codepoint_t variation_selector, out hb_codepoint_t glyph);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_get_extents_for_direction (hb_font_t font, hb_direction_t direction, out hb_font_extents_t extents);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_get_glyph_advance_for_direction (hb_font_t font, hb_codepoint_t glyph, hb_direction_t direction, out hb_position_t x, out hb_position_t y);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_get_glyph_advances_for_direction (hb_font_t font, hb_direction_t direction, int count, IntPtr first_glyph, uint glyph_stride, IntPtr first_advance, uint advance_stride);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_get_glyph_contour_point_for_origin (hb_font_t font, hb_codepoint_t glyph, uint point_index, hb_direction_t direction, out hb_position_t x, out hb_position_t y);
+ /* Generates gidDDD if glyph has no name. */
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_font_glyph_to_string (hb_font_t font, hb_codepoint_t glyph, byte* s, int size);
+ /* Parses gidDDD and uniUUUU strings automatically. */
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_font_glyph_from_string (hb_font_t font, [MarshalAs (UnmanagedType.LPStr)]string s, int len, /* -1 means nul-terminated */ out hb_codepoint_t glyph);
+
+ // hb_font_t (OT)
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_ot_font_set_funcs (hb_font_t font);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_ot_metrics_get_position (hb_font_t font, OpenTypeMetricsTag metrics_tag, out hb_position_t position /* OUT. May be NULL. */);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static float hb_ot_metrics_get_variation (hb_font_t font, OpenTypeMetricsTag metrics_tag);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_position_t hb_ot_metrics_get_x_variation (hb_font_t font, OpenTypeMetricsTag metrics_tag);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_position_t hb_ot_metrics_get_y_variation (hb_font_t font, OpenTypeMetricsTag metrics_tag);
+
+ // hb_buffer_t
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static hb_buffer_t hb_buffer_create ();
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_destroy (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_reset (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_append (hb_buffer_t buffer, hb_buffer_t source, int start, int end);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_add (hb_buffer_t buffer, hb_codepoint_t codepoint, hb_codepoint_t cluster);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_add_utf8 (hb_buffer_t buffer, IntPtr text, int text_length, int item_offset, int item_length);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_add_utf16 (hb_buffer_t buffer, IntPtr text, int text_length, int item_offset, int item_length);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_add_utf32 (hb_buffer_t buffer, IntPtr text, int text_length, int item_offset, int item_length);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_add_codepoints (hb_buffer_t buffer, IntPtr text, int text_length, int item_offset, int item_length);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_guess_segment_properties (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_set_length (hb_buffer_t buffer, int length);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static int hb_buffer_get_length (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_clear_contents (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void* hb_buffer_get_glyph_infos (hb_buffer_t buffer, out int length);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void* hb_buffer_get_glyph_positions (hb_buffer_t buffer, out int length);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_set_script (hb_buffer_t buffer, hb_script_t script);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_script_t hb_buffer_get_script (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static void hb_buffer_set_direction (hb_buffer_t buffer, hb_direction_t direction);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static Direction hb_buffer_get_direction (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_set_language (hb_buffer_t buffer, IntPtr language);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_buffer_get_language (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_set_content_type (hb_buffer_t buffer, ContentType content_type);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern ContentType hb_buffer_get_content_type (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_set_replacement_codepoint (hb_buffer_t buffer, hb_codepoint_t replacement);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_codepoint_t hb_buffer_get_replacement_codepoint (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_set_invisible_glyph (hb_buffer_t buffer, hb_codepoint_t invisible);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_codepoint_t hb_buffer_get_invisible_glyph (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_set_flags (hb_buffer_t buffer, BufferFlags flags);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern BufferFlags hb_buffer_get_flags (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_set_cluster_level (hb_buffer_t buffer, ClusterLevel cluster_level);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern ClusterLevel hb_buffer_get_cluster_level (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_normalize_glyphs (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_reverse (hb_buffer_t buffer);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_reverse_range (hb_buffer_t buffer, int start, int end);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_reverse_clusters (hb_buffer_t buffer);
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern int hb_buffer_serialize_glyphs (hb_buffer_t buffer, int start, int end, IntPtr buf, int buf_size, out int buf_consumed, hb_font_t font, SerializeFormat format, SerializeFlag flags);
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public static extern hb_bool_t hb_buffer_deserialize_glyphs (IntPtr buffer, [MarshalAs (UnmanagedType.LPStr)] string buf, int buf_len, out IntPtr end_ptr, hb_font_t font, SerializeFormat format);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_buffer_set_unicode_funcs (hb_buffer_t buffer, hb_unicode_funcs_t unicode_funcs);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_unicode_funcs_t hb_buffer_get_unicode_funcs (hb_buffer_t buffer);
+
+ // hb_shape
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public extern static hb_bool_t hb_shape_full (hb_font_t font, hb_buffer_t buffer, IntPtr features, int num_features, IntPtr shaper_list);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public extern static IntPtr hb_shape_list_shapers ();
+
+ // hb_language
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_language_from_string ([MarshalAs (UnmanagedType.LPStr)] string str, int len);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_language_to_string (IntPtr language);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr hb_language_get_default ();
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern GlyphFlags hb_glyph_info_get_glyph_flags (ref GlyphInfo info);
+
+ // hb_feature
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_feature_to_string (ref Feature feature, [MarshalAs (UnmanagedType.LPStr)] StringBuilder buf, uint size);
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public static extern hb_bool_t hb_feature_from_string ([MarshalAs (UnmanagedType.LPStr)] string str, int len, out Feature feature);
+
+ // hb_script
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_direction_t hb_script_get_horizontal_direction (hb_script_t script);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_script_t hb_script_from_string ([MarshalAs (UnmanagedType.LPStr)] string str, int len);
+
+ // hb_unicode
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_unicode_funcs_t hb_unicode_funcs_get_default ();
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_unicode_funcs_t hb_unicode_funcs_get_empty ();
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_unicode_funcs_t hb_unicode_funcs_create (hb_unicode_funcs_t parent);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_unicode_funcs_destroy (hb_unicode_funcs_t ufuncs);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_unicode_funcs_make_immutable (hb_unicode_funcs_t ufuncs);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public static extern hb_bool_t hb_unicode_funcs_is_immutable (hb_unicode_funcs_t ufuncs);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern UnicodeCombiningClass hb_unicode_combining_class (hb_unicode_funcs_t ufuncs, hb_codepoint_t unicode);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern UnicodeGeneralCategory hb_unicode_general_category (hb_unicode_funcs_t ufuncs, hb_codepoint_t unicode);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_codepoint_t hb_unicode_mirroring (hb_unicode_funcs_t ufuncs, hb_codepoint_t unicode);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern hb_script_t hb_unicode_script (hb_unicode_funcs_t ufuncs, hb_codepoint_t unicode);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public static extern hb_bool_t hb_unicode_compose (hb_unicode_funcs_t ufuncs, hb_codepoint_t a, hb_codepoint_t b, out hb_codepoint_t ab);
+
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ public static extern hb_bool_t hb_unicode_decompose (hb_unicode_funcs_t ufuncs, hb_codepoint_t ab, out hb_codepoint_t a, out hb_codepoint_t b);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_unicode_funcs_set_combining_class_func (hb_unicode_funcs_t ufuncs, hb_unicode_combining_class_func_t func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_unicode_funcs_set_general_category_func (hb_unicode_funcs_t ufuncs, hb_unicode_general_category_func_t func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_unicode_funcs_set_mirroring_func (hb_unicode_funcs_t ufuncs, hb_unicode_mirroring_func_t func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_unicode_funcs_set_script_func (hb_unicode_funcs_t ufuncs, hb_unicode_script_func_t func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_unicode_funcs_set_compose_func (hb_unicode_funcs_t ufuncs, hb_unicode_compose_func_t func, IntPtr user_data, hb_destroy_func_t destroy);
+ [DllImport (HARFBUZZ, CallingConvention = CallingConvention.Cdecl)]
+ public static extern void hb_unicode_funcs_set_decompose_func (hb_unicode_funcs_t ufuncs, hb_unicode_decompose_func_t func, IntPtr user_data, hb_destroy_func_t destroy);
+ }
+}
+#pragma warning restore IDE1006 // Naming Styles
--- /dev/null
+// Partial code copied from:
+// https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/HashCode.cs
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace HarfBuzzSharp
+{
+ internal unsafe struct HashCode
+ {
+ private static readonly uint s_seed = GenerateGlobalSeed ();
+
+ private const uint Prime1 = 2654435761U;
+ private const uint Prime2 = 2246822519U;
+ private const uint Prime3 = 3266489917U;
+ private const uint Prime4 = 668265263U;
+ private const uint Prime5 = 374761393U;
+
+ private uint _v1, _v2, _v3, _v4;
+ private uint _queue1, _queue2, _queue3;
+ private uint _length;
+
+ private static unsafe uint GenerateGlobalSeed ()
+ {
+ var rnd = new Random ();
+ var result = rnd.Next ();
+ return unchecked((uint)result);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static void Initialize (out uint v1, out uint v2, out uint v3, out uint v4)
+ {
+ v1 = s_seed + Prime1 + Prime2;
+ v2 = s_seed + Prime2;
+ v3 = s_seed;
+ v4 = s_seed - Prime1;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint Round (uint hash, uint input) =>
+ RotateLeft (hash + input * Prime2, 13) * Prime1;
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint QueueRound (uint hash, uint queuedValue) =>
+ RotateLeft (hash + queuedValue * Prime3, 17) * Prime4;
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint MixState (uint v1, uint v2, uint v3, uint v4) =>
+ RotateLeft (v1, 1) + RotateLeft (v2, 7) + RotateLeft (v3, 12) + RotateLeft (v4, 18);
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint RotateLeft (uint value, int offset) =>
+ (value << offset) | (value >> (32 - offset));
+
+ private static uint MixEmptyState () =>
+ s_seed + Prime5;
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint MixFinal (uint hash)
+ {
+ hash ^= hash >> 15;
+ hash *= Prime2;
+ hash ^= hash >> 13;
+ hash *= Prime3;
+ hash ^= hash >> 16;
+ return hash;
+ }
+
+ public void Add (void* value) =>
+ Add (value == null ? 0 : ((IntPtr)value).GetHashCode ());
+
+ public void Add<T> (T value) =>
+ Add (value?.GetHashCode () ?? 0);
+
+ private void Add (int value)
+ {
+ uint val = (uint)value;
+
+ // Storing the value of _length locally shaves of quite a few bytes
+ // in the resulting machine code.
+ uint previousLength = _length++;
+ uint position = previousLength % 4;
+
+ // Switch can't be inlined.
+
+ if (position == 0)
+ _queue1 = val;
+ else if (position == 1)
+ _queue2 = val;
+ else if (position == 2)
+ _queue3 = val;
+ else // position == 3
+ {
+ if (previousLength == 3)
+ Initialize (out _v1, out _v2, out _v3, out _v4);
+
+ _v1 = Round (_v1, _queue1);
+ _v2 = Round (_v2, _queue2);
+ _v3 = Round (_v3, _queue3);
+ _v4 = Round (_v4, val);
+ }
+ }
+
+ public int ToHashCode ()
+ {
+ // Storing the value of _length locally shaves of quite a few bytes
+ // in the resulting machine code.
+ uint length = _length;
+
+ // position refers to the *next* queue position in this method, so
+ // position == 1 means that _queue1 is populated; _queue2 would have
+ // been populated on the next call to Add.
+ uint position = length % 4;
+
+ // If the length is less than 4, _v1 to _v4 don't contain anything
+ // yet. xxHash32 treats this differently.
+
+ uint hash = length < 4 ? MixEmptyState () : MixState (_v1, _v2, _v3, _v4);
+
+ // _length is incremented once per Add(Int32) and is therefore 4
+ // times too small (xxHash length is in bytes, not ints).
+
+ hash += length * 4;
+
+ // Mix what remains in the queue
+
+ // Switch can't be inlined right now, so use as few branches as
+ // possible by manually excluding impossible scenarios (position > 1
+ // is always false if position is not > 0).
+ if (position > 0) {
+ hash = QueueRound (hash, _queue1);
+ if (position > 1) {
+ hash = QueueRound (hash, _queue2);
+ if (position > 2)
+ hash = QueueRound (hash, _queue3);
+ }
+ }
+
+ hash = MixFinal (hash);
+ return (int)hash;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Globalization;
+using System.Runtime.InteropServices;
+
+namespace HarfBuzzSharp
+{
+ public class Language : NativeObject
+ {
+ private static readonly Lazy<Language> defaultLanguage =
+ new Lazy<Language> (() => new StaticLanguage (HarfBuzzApi.hb_language_get_default ()));
+
+ public static Language Default => defaultLanguage.Value;
+
+ internal Language (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ public Language (CultureInfo culture)
+ : this (culture.TwoLetterISOLanguageName)
+ {
+ }
+
+ public Language (string name)
+ : base (IntPtr.Zero)
+ {
+ Handle = HarfBuzzApi.hb_language_from_string (name, -1);
+ Name = Marshal.PtrToStringAnsi (HarfBuzzApi.hb_language_to_string (Handle));
+ }
+
+ public string Name { get; }
+
+ public override string ToString () => Name;
+
+ public override bool Equals (object obj) =>
+ obj is Language language && Handle == language.Handle;
+
+ public override int GetHashCode () => Name != null ? Name.GetHashCode () : 0;
+
+ private class StaticLanguage : Language
+ {
+ public StaticLanguage (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace HarfBuzzSharp
+{
+ public class NativeObject : IDisposable
+ {
+ private bool isDisposed;
+ private readonly bool zero;
+
+ internal NativeObject (IntPtr handle)
+ {
+ Handle = handle;
+ zero = true;
+ }
+
+ internal NativeObject (IntPtr handle, bool zero)
+ {
+ Handle = handle;
+ this.zero = zero;
+ }
+
+ ~NativeObject ()
+ {
+ Dispose (false);
+ }
+
+ public virtual IntPtr Handle { get; protected set; }
+
+ // Dispose method - always called
+ protected virtual void Dispose (bool disposing)
+ {
+ if (isDisposed) {
+ return;
+ }
+
+ isDisposed = true;
+
+ if (!disposing) {
+ return;
+ }
+
+ DisposeHandler ();
+
+ if (zero) {
+ Handle = IntPtr.Zero;
+ }
+ }
+
+ // Intended to be overridden - always safe to use
+ // since it will never be called unless applicable
+ protected virtual void DisposeHandler ()
+ {
+ }
+
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+
+ internal static int SizeOf<T> ()
+ {
+ return Marshal.SizeOf (typeof (T));
+ }
+
+ internal static IntPtr StructureArrayToPtr<T> (IReadOnlyList<T> items)
+ {
+ var size = SizeOf<T> ();
+ var memory = Marshal.AllocCoTaskMem (size * items.Count);
+ for (var i = 0; i < items.Count; i++) {
+ var ptr = new IntPtr (memory.ToInt64 () + (i * size));
+ Marshal.StructureToPtr (items[i], ptr, true);
+ }
+ return memory;
+ }
+
+ internal static IEnumerable<string> PtrToStringArray (IntPtr intPtr)
+ {
+ if (intPtr != IntPtr.Zero) {
+ var ptr = Marshal.ReadIntPtr (intPtr);
+ while (ptr != IntPtr.Zero) {
+ var element = Marshal.PtrToStringAnsi (ptr);
+ yield return element;
+ intPtr = new IntPtr (intPtr.ToInt64 () + IntPtr.Size);
+ ptr = Marshal.ReadIntPtr (intPtr);
+ }
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace HarfBuzzSharp
+{
+ internal static class PlatformConfiguration
+ {
+ public static bool IsUnix { get; }
+ public static bool IsWindows { get; }
+
+ static PlatformConfiguration ()
+ {
+ IsUnix = Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix;
+ IsWindows = !IsUnix;
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace HarfBuzzSharp
+{
+ public partial struct Script : IEquatable<Script>
+ {
+ private readonly Tag tag;
+
+ private Script (Tag tag)
+ {
+ this.tag = tag;
+ }
+
+ public Direction HorizontalDirection =>
+ HarfBuzzApi.hb_script_get_horizontal_direction (tag);
+
+ public static Script Parse (string str) =>
+ HarfBuzzApi.hb_script_from_string (str, -1);
+
+ public static bool TryParse (string str, out Script script)
+ {
+ script = Parse (str);
+
+ return script != Unknown;
+ }
+
+ public override string ToString () => tag.ToString ();
+
+ public static implicit operator uint (Script script) => script.tag;
+
+ public static implicit operator Script (uint tag) => new Script (tag);
+
+ public override bool Equals (object obj) =>
+ obj is Script script && tag.Equals (script.tag);
+
+ public bool Equals (Script other) => tag.Equals (other.tag);
+
+ public override int GetHashCode () => tag.GetHashCode ();
+ }
+}
--- /dev/null
+using System;
+
+namespace HarfBuzzSharp
+{
+ public partial struct Script
+ {
+ public static readonly Script Invalid = new Script (Tag.None);
+
+ public static readonly Script MaxValue = new Script (Tag.Max);
+
+ public static readonly Script MaxValueSigned = new Script (Tag.MaxSigned);
+
+ // Special scripts
+
+ // 1.1
+ public static readonly Script Common = new Script (new Tag ('Z', 'y', 'y', 'y'));
+ // 1.1
+ public static readonly Script Inherited = new Script (new Tag ('Z', 'i', 'n', 'h'));
+ // 5.0
+ public static readonly Script Unknown = new Script (new Tag ('Z', 'z', 'z', 'z'));
+
+ // Scripts
+
+ // 1.1
+ public static readonly Script Arabic = new Script (new Tag ('A', 'r', 'a', 'b'));
+ // 1.1
+ public static readonly Script Armenian = new Script (new Tag ('A', 'r', 'm', 'n'));
+ // 1.1
+ public static readonly Script Bengali = new Script (new Tag ('B', 'e', 'n', 'g'));
+ // 1.1
+ public static readonly Script Cyrillic = new Script (new Tag ('C', 'y', 'r', 'l'));
+ // 1.1
+ public static readonly Script Devanagari = new Script (new Tag ('D', 'e', 'v', 'a'));
+ // 1.1
+ public static readonly Script Georgian = new Script (new Tag ('G', 'e', 'o', 'r'));
+ // 1.1
+ public static readonly Script Greek = new Script (new Tag ('G', 'r', 'e', 'k'));
+ // 1.1
+ public static readonly Script Gujarati = new Script (new Tag ('G', 'u', 'j', 'r'));
+ // 1.1
+ public static readonly Script Gurmukhi = new Script (new Tag ('G', 'u', 'r', 'u'));
+ // 1.1
+ public static readonly Script Hangul = new Script (new Tag ('H', 'a', 'n', 'g'));
+ // 1.1
+ public static readonly Script Han = new Script (new Tag ('H', 'a', 'n', 'i'));
+ // 1.1
+ public static readonly Script Hebrew = new Script (new Tag ('H', 'e', 'b', 'r'));
+ // 1.1
+ public static readonly Script Hiragana = new Script (new Tag ('H', 'i', 'r', 'a'));
+ // 1.1
+ public static readonly Script Kannada = new Script (new Tag ('K', 'n', 'd', 'a'));
+ // 1.1
+ public static readonly Script Katakana = new Script (new Tag ('K', 'a', 'n', 'a'));
+ // 1.1
+ public static readonly Script Lao = new Script (new Tag ('L', 'a', 'o', 'o'));
+ // 1.1
+ public static readonly Script Latin = new Script (new Tag ('L', 'a', 't', 'n'));
+ // 1.1
+ public static readonly Script Malayalam = new Script (new Tag ('M', 'l', 'y', 'm'));
+ // 1.1
+ public static readonly Script Oriya = new Script (new Tag ('O', 'r', 'y', 'a'));
+ // 1.1
+ public static readonly Script Tamil = new Script (new Tag ('T', 'a', 'm', 'l'));
+ // 1.1
+ public static readonly Script Telugu = new Script (new Tag ('T', 'e', 'l', 'u'));
+ // 1.1
+ public static readonly Script Thai = new Script (new Tag ('T', 'h', 'a', 'i'));
+ // 2.0
+ public static readonly Script Tibetan = new Script (new Tag ('T', 'i', 'b', 't'));
+ // 3.0
+ public static readonly Script Bopomofo = new Script (new Tag ('B', 'o', 'p', 'o'));
+ // 3.0
+ public static readonly Script Braille = new Script (new Tag ('B', 'r', 'a', 'i'));
+ // 3.0
+ public static readonly Script CanadianSyllabics = new Script (new Tag ('C', 'a', 'n', 's'));
+ // 3.0
+ public static readonly Script Cherokee = new Script (new Tag ('C', 'h', 'e', 'r'));
+ // 3.0
+ public static readonly Script Ethiopic = new Script (new Tag ('E', 't', 'h', 'i'));
+ // 3.0
+ public static readonly Script Khmer = new Script (new Tag ('K', 'h', 'm', 'r'));
+ // 3.0
+ public static readonly Script Mongolian = new Script (new Tag ('M', 'o', 'n', 'g'));
+ // 3.0
+ public static readonly Script Myanmar = new Script (new Tag ('M', 'y', 'm', 'r'));
+ // 3.0
+ public static readonly Script Ogham = new Script (new Tag ('O', 'g', 'a', 'm'));
+ // 3.0
+ public static readonly Script Runic = new Script (new Tag ('R', 'u', 'n', 'r'));
+ // 3.0
+ public static readonly Script Sinhala = new Script (new Tag ('S', 'i', 'n', 'h'));
+ // 3.0
+ public static readonly Script Syriac = new Script (new Tag ('S', 'y', 'r', 'c'));
+ // 3.0
+ public static readonly Script Thaana = new Script (new Tag ('T', 'h', 'a', 'a'));
+ // 3.0
+ public static readonly Script Yi = new Script (new Tag ('Y', 'i', 'i', 'i'));
+ // 3.1
+ public static readonly Script Deseret = new Script (new Tag ('D', 's', 'r', 't'));
+ // 3.1
+ public static readonly Script Gothic = new Script (new Tag ('G', 'o', 't', 'h'));
+ // 3.1
+ public static readonly Script OldItalic = new Script (new Tag ('I', 't', 'a', 'l'));
+ // 3.2
+ public static readonly Script Buhid = new Script (new Tag ('B', 'u', 'h', 'd'));
+ // 3.2
+ public static readonly Script Hanunoo = new Script (new Tag ('H', 'a', 'n', 'o'));
+ // 3.2
+ public static readonly Script Tagalog = new Script (new Tag ('T', 'g', 'l', 'g'));
+ // 3.2
+ public static readonly Script Tagbanwa = new Script (new Tag ('T', 'a', 'g', 'b'));
+ // 4.0
+ public static readonly Script Cypriot = new Script (new Tag ('C', 'p', 'r', 't'));
+ // 4.0
+ public static readonly Script Limbu = new Script (new Tag ('L', 'i', 'm', 'b'));
+ // 4.0
+ public static readonly Script LinearB = new Script (new Tag ('L', 'i', 'n', 'b'));
+ // 4.0
+ public static readonly Script Osmanya = new Script (new Tag ('O', 's', 'm', 'a'));
+ // 4.0
+ public static readonly Script Shavian = new Script (new Tag ('S', 'h', 'a', 'w'));
+ // 4.0
+ public static readonly Script TaiLe = new Script (new Tag ('T', 'a', 'l', 'e'));
+ // 4.0
+ public static readonly Script Ugaritic = new Script (new Tag ('U', 'g', 'a', 'r'));
+ // 4.1
+ public static readonly Script Buginese = new Script (new Tag ('B', 'u', 'g', 'i'));
+ // 4.1
+ public static readonly Script Coptic = new Script (new Tag ('C', 'o', 'p', 't'));
+ // 4.1
+ public static readonly Script Glagolitic = new Script (new Tag ('G', 'l', 'a', 'g'));
+ // 4.1
+ public static readonly Script Kharoshthi = new Script (new Tag ('K', 'h', 'a', 'r'));
+ // 4.1
+ public static readonly Script NewTaiLue = new Script (new Tag ('T', 'a', 'l', 'u'));
+ // 4.1
+ public static readonly Script OldPersian = new Script (new Tag ('X', 'p', 'e', 'o'));
+ // 4.1
+ public static readonly Script SylotiNagri = new Script (new Tag ('S', 'y', 'l', 'o'));
+ // 4.1
+ public static readonly Script Tifinagh = new Script (new Tag ('T', 'f', 'n', 'g'));
+ // 5.0
+ public static readonly Script Balinese = new Script (new Tag ('B', 'a', 'l', 'i'));
+ // 5.0
+ public static readonly Script Cuneiform = new Script (new Tag ('X', 's', 'u', 'x'));
+ // 5.0
+ public static readonly Script Nko = new Script (new Tag ('N', 'k', 'o', 'o'));
+ // 5.0
+ public static readonly Script PhagsPa = new Script (new Tag ('P', 'h', 'a', 'g'));
+ // 5.0
+ public static readonly Script Phoenician = new Script (new Tag ('P', 'h', 'n', 'x'));
+ // 5.1
+ public static readonly Script Carian = new Script (new Tag ('C', 'a', 'r', 'i'));
+ // 5.1
+ public static readonly Script Cham = new Script (new Tag ('C', 'h', 'a', 'm'));
+ // 5.1
+ public static readonly Script KayahLi = new Script (new Tag ('K', 'a', 'l', 'i'));
+ // 5.1
+ public static readonly Script Lepcha = new Script (new Tag ('L', 'e', 'p', 'c'));
+ // 5.1
+ public static readonly Script Lycian = new Script (new Tag ('L', 'y', 'c', 'i'));
+ // 5.1
+ public static readonly Script Lydian = new Script (new Tag ('L', 'y', 'd', 'i'));
+ // 5.1
+ public static readonly Script OlChiki = new Script (new Tag ('O', 'l', 'c', 'k'));
+ // 5.1
+ public static readonly Script Rejang = new Script (new Tag ('R', 'j', 'n', 'g'));
+ // 5.1
+ public static readonly Script Saurashtra = new Script (new Tag ('S', 'a', 'u', 'r'));
+ // 5.1
+ public static readonly Script Sundanese = new Script (new Tag ('S', 'u', 'n', 'd'));
+ // 5.1
+ public static readonly Script Vai = new Script (new Tag ('V', 'a', 'i', 'i'));
+ // 5.2
+ public static readonly Script Avestan = new Script (new Tag ('A', 'v', 's', 't'));
+ // 5.2
+ public static readonly Script Bamum = new Script (new Tag ('B', 'a', 'm', 'u'));
+ // 5.2
+ public static readonly Script EgyptianHieroglyphs = new Script (new Tag ('E', 'g', 'y', 'p'));
+ // 5.2
+ public static readonly Script ImperialAramaic = new Script (new Tag ('A', 'r', 'm', 'i'));
+ // 5.2
+ public static readonly Script InscriptionalPahlavi = new Script (new Tag ('P', 'h', 'l', 'i'));
+ // 5.2
+ public static readonly Script InscriptionalParthian = new Script (new Tag ('P', 'r', 't', 'i'));
+ // 5.2
+ public static readonly Script Javanese = new Script (new Tag ('J', 'a', 'v', 'a'));
+ // 5.2
+ public static readonly Script Kaithi = new Script (new Tag ('K', 't', 'h', 'i'));
+ // 5.2
+ public static readonly Script Lisu = new Script (new Tag ('L', 'i', 's', 'u'));
+ // 5.2
+ public static readonly Script MeeteiMayek = new Script (new Tag ('M', 't', 'e', 'i'));
+ // 5.2
+ public static readonly Script OldSouthArabian = new Script (new Tag ('S', 'a', 'r', 'b'));
+ // 5.2
+ public static readonly Script OldTurkic = new Script (new Tag ('O', 'r', 'k', 'h'));
+ // 5.2
+ public static readonly Script Samaritan = new Script (new Tag ('S', 'a', 'm', 'r'));
+ // 5.2
+ public static readonly Script TaiTham = new Script (new Tag ('L', 'a', 'n', 'a'));
+ // 5.2
+ public static readonly Script TaiViet = new Script (new Tag ('T', 'a', 'v', 't'));
+ // 6.0
+ public static readonly Script Batak = new Script (new Tag ('B', 'a', 't', 'k'));
+ // 6.0
+ public static readonly Script Brahmi = new Script (new Tag ('B', 'r', 'a', 'h'));
+ // 6.0
+ public static readonly Script Mandaic = new Script (new Tag ('M', 'a', 'n', 'd'));
+ // 6.1
+ public static readonly Script Chakma = new Script (new Tag ('C', 'a', 'k', 'm'));
+ // 6.1
+ public static readonly Script MeroiticCursive = new Script (new Tag ('M', 'e', 'r', 'c'));
+ // 6.1
+ public static readonly Script MeroiticHieroglyphs = new Script (new Tag ('M', 'e', 'r', 'o'));
+ // 6.1
+ public static readonly Script Miao = new Script (new Tag ('P', 'l', 'r', 'd'));
+ // 6.1
+ public static readonly Script Sharada = new Script (new Tag ('S', 'h', 'r', 'd'));
+ // 6.1
+ public static readonly Script SoraSompeng = new Script (new Tag ('S', 'o', 'r', 'a'));
+ // 6.1
+ public static readonly Script Takri = new Script (new Tag ('T', 'a', 'k', 'r'));
+
+ // Since: 0.9.30
+
+ // 7.0
+ public static readonly Script BassaVah = new Script (new Tag ('B', 'a', 's', 's'));
+ // 7.0
+ public static readonly Script CaucasianAlbanian = new Script (new Tag ('A', 'g', 'h', 'b'));
+ // 7.0
+ public static readonly Script Duployan = new Script (new Tag ('D', 'u', 'p', 'l'));
+ // 7.0
+ public static readonly Script Elbasan = new Script (new Tag ('E', 'l', 'b', 'a'));
+ // 7.0
+ public static readonly Script Grantha = new Script (new Tag ('G', 'r', 'a', 'n'));
+ // 7.0
+ public static readonly Script Khojki = new Script (new Tag ('K', 'h', 'o', 'j'));
+ // 7.0
+ public static readonly Script Khudawadi = new Script (new Tag ('S', 'i', 'n', 'd'));
+ // 7.0
+ public static readonly Script LinearA = new Script (new Tag ('L', 'i', 'n', 'a'));
+ // 7.0
+ public static readonly Script Mahajani = new Script (new Tag ('M', 'a', 'h', 'j'));
+ // 7.0
+ public static readonly Script Manichaean = new Script (new Tag ('M', 'a', 'n', 'i'));
+ // 7.0
+ public static readonly Script MendeKikakui = new Script (new Tag ('M', 'e', 'n', 'd'));
+ // 7.0
+ public static readonly Script Modi = new Script (new Tag ('M', 'o', 'd', 'i'));
+ // 7.0
+ public static readonly Script Mro = new Script (new Tag ('M', 'r', 'o', 'o'));
+ // 7.0
+ public static readonly Script Nabataean = new Script (new Tag ('N', 'b', 'a', 't'));
+ // 7.0
+ public static readonly Script OldNorthArabian = new Script (new Tag ('N', 'a', 'r', 'b'));
+ // 7.0
+ public static readonly Script OldPermic = new Script (new Tag ('P', 'e', 'r', 'm'));
+ // 7.0
+ public static readonly Script PahawhHmong = new Script (new Tag ('H', 'm', 'n', 'g'));
+ // 7.0
+ public static readonly Script Palmyrene = new Script (new Tag ('P', 'a', 'l', 'm'));
+ // 7.0
+ public static readonly Script PauCinHau = new Script (new Tag ('P', 'a', 'u', 'c'));
+ // 7.0
+ public static readonly Script PsalterPahlavi = new Script (new Tag ('P', 'h', 'l', 'p'));
+ // 7.0
+ public static readonly Script Siddham = new Script (new Tag ('S', 'i', 'd', 'd'));
+ // 7.0
+ public static readonly Script Tirhuta = new Script (new Tag ('T', 'i', 'r', 'h'));
+ // 7.0
+ public static readonly Script WarangCiti = new Script (new Tag ('W', 'a', 'r', 'a'));
+ // 8.0
+ public static readonly Script Ahom = new Script (new Tag ('A', 'h', 'o', 'm'));
+ // 8.0
+ public static readonly Script AnatolianHieroglyphs = new Script (new Tag ('H', 'l', 'u', 'w'));
+ // 8.0
+ public static readonly Script Hatran = new Script (new Tag ('H', 'a', 't', 'r'));
+ // 8.0
+ public static readonly Script Multani = new Script (new Tag ('M', 'u', 'l', 't'));
+ // 8.0
+ public static readonly Script OldHungarian = new Script (new Tag ('H', 'u', 'n', 'g'));
+ // 8.0
+ public static readonly Script Signwriting = new Script (new Tag ('S', 'g', 'n', 'w'));
+
+ // Since 1.3.0
+
+ // 9.0
+ public static readonly Script Adlam = new Script (new Tag ('A', 'd', 'l', 'm'));
+ // 9.0
+ public static readonly Script Bhaiksuki = new Script (new Tag ('B', 'h', 'k', 's'));
+ // 9.0
+ public static readonly Script Marchen = new Script (new Tag ('M', 'a', 'r', 'c'));
+ // 9.0
+ public static readonly Script Osage = new Script (new Tag ('O', 's', 'g', 'e'));
+ // 9.0
+ public static readonly Script Tangut = new Script (new Tag ('T', 'a', 'n', 'g'));
+ // 9.0
+ public static readonly Script Newa = new Script (new Tag ('N', 'e', 'w', 'a'));
+
+ // Since 1.6.0
+
+ // 10.0
+ public static readonly Script MasaramGondi = new Script (new Tag ('G', 'o', 'n', 'm'));
+ // 10.0
+ public static readonly Script Nushu = new Script (new Tag ('N', 's', 'h', 'u'));
+ // 10.0
+ public static readonly Script Soyombo = new Script (new Tag ('S', 'o', 'y', 'o'));
+ // 10.0
+ public static readonly Script ZanabazarSquare = new Script (new Tag ('Z', 'a', 'n', 'b'));
+
+ // Since 1.8.0
+
+ // 11.0
+ public static readonly Script Dogra = new Script (new Tag ('D', 'o', 'g', 'r'));
+ // 11.0
+ public static readonly Script GunjalaGondi = new Script (new Tag ('G', 'o', 'n', 'g'));
+ // 11.0
+ public static readonly Script HanifiRohingya = new Script (new Tag ('R', 'o', 'h', 'g'));
+ // 11.0
+ public static readonly Script Makasar = new Script (new Tag ('M', 'a', 'k', 'a'));
+ // 11.0
+ public static readonly Script Medefaidrin = new Script (new Tag ('M', 'e', 'd', 'f'));
+ // 11.0
+ public static readonly Script OldSogdian = new Script (new Tag ('S', 'o', 'g', 'o'));
+ // 11.0
+ public static readonly Script Sogdian = new Script (new Tag ('S', 'o', 'g', 'd'));
+ }
+}
--- /dev/null
+using System;
+
+namespace HarfBuzzSharp
+{
+ public struct Tag : IEquatable<Tag>
+ {
+ public static readonly Tag None = new Tag (0, 0, 0, 0);
+ public static readonly Tag Max = new Tag (byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
+ public static readonly Tag MaxSigned = new Tag ((byte)sbyte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue);
+
+ private readonly uint value;
+
+ private Tag (uint value)
+ {
+ this.value = value;
+ }
+
+ private Tag (byte c1, byte c2, byte c3, byte c4)
+ {
+ value = (uint)((c1 << 24) | (c2 << 16) | (c3 << 8) | c4);
+ }
+
+ public Tag (char c1, char c2, char c3, char c4)
+ {
+ value = (uint)(((byte)c1 << 24) | ((byte)c2 << 16) | ((byte)c3 << 8) | (byte)c4);
+ }
+
+ public static Tag Parse (string tag)
+ {
+ if (string.IsNullOrEmpty(tag))
+ return None;
+
+ var realTag = new char[4];
+
+ var len = Math.Min (4, tag.Length);
+ var i = 0;
+ for (; i < len; i++)
+ realTag[i] = tag[i];
+ for (; i < 4; i++)
+ realTag[i] = ' ';
+
+ return new Tag (realTag[0], realTag[1], realTag[2], realTag[3]);
+ }
+
+ public override string ToString ()
+ {
+ if (value == None) {
+ return nameof (None);
+ }
+ if (value == Max) {
+ return nameof (Max);
+ }
+ if (value == MaxSigned) {
+ return nameof (MaxSigned);
+ }
+
+ return string.Concat (
+ (char)(byte)(value >> 24),
+ (char)(byte)(value >> 16),
+ (char)(byte)(value >> 8),
+ (char)(byte)value);
+ }
+
+ public static implicit operator uint (Tag tag) => tag.value;
+
+ public static implicit operator Tag (uint tag) => new Tag (tag);
+
+ public override bool Equals (object obj) =>
+ obj is Tag tag && value.Equals (tag.value);
+
+ public bool Equals (Tag other) => value == other.value;
+
+ public override int GetHashCode () => (int)value;
+ }
+}
--- /dev/null
+using System;
+
+namespace HarfBuzzSharp
+{
+ public class UnicodeFunctions : NativeObject
+ {
+ private static readonly Lazy<UnicodeFunctions> defaultFunctions =
+ new Lazy<UnicodeFunctions> (() => new StaticUnicodeFunctions (HarfBuzzApi.hb_unicode_funcs_get_default ()));
+
+ private static readonly Lazy<UnicodeFunctions> emptyFunctions =
+ new Lazy<UnicodeFunctions> (() => new StaticUnicodeFunctions (HarfBuzzApi.hb_unicode_funcs_get_empty ()));
+
+ public static UnicodeFunctions Default => defaultFunctions.Value;
+
+ public static UnicodeFunctions Empty => emptyFunctions.Value;
+
+ internal UnicodeFunctions (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ public UnicodeFunctions (UnicodeFunctions parent) : base (IntPtr.Zero)
+ {
+ if (parent == null)
+ throw new ArgumentNullException (nameof (parent));
+ if (parent.Handle == IntPtr.Zero)
+ throw new ArgumentException (nameof (parent.Handle));
+
+ Parent = parent;
+ Handle = HarfBuzzApi.hb_unicode_funcs_create (parent.Handle);
+ }
+
+ public UnicodeFunctions Parent { get; }
+
+ public bool IsImmutable => HarfBuzzApi.hb_unicode_funcs_is_immutable (Handle);
+
+ public void MakeImmutable () => HarfBuzzApi.hb_unicode_funcs_make_immutable (Handle);
+
+ public UnicodeCombiningClass GetCombiningClass (int unicode) => GetCombiningClass ((uint)unicode);
+
+ public UnicodeCombiningClass GetCombiningClass (uint unicode) =>
+ HarfBuzzApi.hb_unicode_combining_class (Handle, unicode);
+
+ public UnicodeGeneralCategory GetGeneralCategory (int unicode) => GetGeneralCategory ((uint)unicode);
+
+ public UnicodeGeneralCategory GetGeneralCategory (uint unicode) =>
+ HarfBuzzApi.hb_unicode_general_category (Handle, unicode);
+
+ public int GetMirroring (int unicode) => (int)GetMirroring ((uint)unicode);
+
+ public uint GetMirroring (uint unicode) => HarfBuzzApi.hb_unicode_mirroring (Handle, unicode);
+
+ public Script GetScript (int unicode) => GetScript ((uint)unicode);
+
+ public Script GetScript (uint unicode) => HarfBuzzApi.hb_unicode_script (Handle, unicode);
+
+ public bool TryCompose (int a, int b, out int ab)
+ {
+ var result = TryCompose ((uint)a, (uint)b, out var composed);
+
+ ab = (int)composed;
+
+ return result;
+ }
+
+ public bool TryCompose (uint a, uint b, out uint ab) => HarfBuzzApi.hb_unicode_compose (Handle, a, b, out ab);
+
+ public bool TryDecompose (int ab, out int a, out int b)
+ {
+ var result = TryDecompose ((uint)ab, out var decomposedA, out var decomposedB);
+
+ a = (int)decomposedA;
+
+ b = (int)decomposedB;
+
+ return result;
+ }
+
+ public bool TryDecompose (uint ab, out uint a, out uint b) => HarfBuzzApi.hb_unicode_decompose (Handle, ab, out a, out b);
+
+ public void SetCombiningClassDelegate (CombiningClassDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMultiUserData (del, destroy, this);
+ HarfBuzzApi.hb_unicode_funcs_set_combining_class_func (
+ Handle, DelegateProxies.CombiningClassProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetGeneralCategoryDelegate (GeneralCategoryDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMultiUserData (del, destroy, this);
+ HarfBuzzApi.hb_unicode_funcs_set_general_category_func (
+ Handle, DelegateProxies.GeneralCategoryProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetMirroringDelegate (MirroringDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMultiUserData (del, destroy, this);
+ HarfBuzzApi.hb_unicode_funcs_set_mirroring_func (
+ Handle, DelegateProxies.MirroringProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetScriptDelegate (ScriptDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMultiUserData (del, destroy, this);
+ HarfBuzzApi.hb_unicode_funcs_set_script_func (
+ Handle, DelegateProxies.ScriptProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetComposeDelegate (ComposeDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMultiUserData (del, destroy, this);
+ HarfBuzzApi.hb_unicode_funcs_set_compose_func (
+ Handle, DelegateProxies.ComposeProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ public void SetDecomposeDelegate (DecomposeDelegate del, ReleaseDelegate destroy = null)
+ {
+ VerifyParameters (del);
+
+ var ctx = DelegateProxies.CreateMultiUserData (del, destroy, this);
+ HarfBuzzApi.hb_unicode_funcs_set_decompose_func (
+ Handle, DelegateProxies.DecomposeProxy, ctx, DelegateProxies.ReleaseDelegateProxyForMulti);
+ }
+
+ private void VerifyParameters (Delegate del)
+ {
+ _ = del ?? throw new ArgumentNullException (nameof (del));
+
+ if (IsImmutable)
+ throw new InvalidOperationException ($"{nameof (UnicodeFunctions)} is immutable and can't be changed.");
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeHandler ()
+ {
+ if (Handle != IntPtr.Zero) {
+ HarfBuzzApi.hb_unicode_funcs_destroy (Handle);
+ }
+ }
+
+ private class StaticUnicodeFunctions : UnicodeFunctions
+ {
+ public StaticUnicodeFunctions (IntPtr handle)
+ : base (handle)
+ {
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+using HarfBuzzSharp;
+
+namespace SkiaSharp.HarfBuzz
+{
+ public static class BlobExtensions
+ {
+ public static Blob ToHarfBuzzBlob(this SKStreamAsset asset)
+ {
+ if (asset == null)
+ {
+ throw new ArgumentNullException(nameof(asset));
+ }
+
+ var size = asset.Length;
+
+ Blob blob;
+
+ var memoryBase = asset.GetMemoryBase();
+ if (memoryBase != IntPtr.Zero)
+ {
+ blob = new Blob(memoryBase, size, MemoryMode.ReadOnly, () => asset.Dispose());
+ }
+ else
+ {
+ var ptr = Marshal.AllocCoTaskMem(size);
+ asset.Read(ptr, size);
+ blob = new Blob(ptr, size, MemoryMode.ReadOnly, () => Marshal.FreeCoTaskMem(ptr));
+ }
+
+ blob.MakeImmutable();
+
+ return blob;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Linq;
+
+using HarfBuzzSharp;
+
+namespace SkiaSharp.HarfBuzz
+{
+ public static class CanvasExtensions
+ {
+ public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, float x, float y, SKPaint paint)
+ {
+ if (canvas == null)
+ throw new ArgumentNullException(nameof(canvas));
+ if (shaper == null)
+ throw new ArgumentNullException(nameof(shaper));
+ if (text == null)
+ throw new ArgumentNullException(nameof(text));
+ if (paint == null)
+ throw new ArgumentNullException(nameof(paint));
+
+ if (string.IsNullOrEmpty(text))
+ return;
+
+ // shape the text
+ var result = shaper.Shape(text, x, y, paint);
+
+ // draw the text
+
+ using (var paintClone = paint.Clone())
+ {
+ paintClone.TextEncoding = SKTextEncoding.GlyphId;
+ paintClone.Typeface = shaper.Typeface;
+
+ var bytes = result.Codepoints.Select(cp => BitConverter.GetBytes((ushort)cp)).SelectMany(b => b).ToArray();
+ canvas.DrawPositionedText(bytes, result.Points, paintClone);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+
+using HarfBuzzSharp;
+
+namespace SkiaSharp.HarfBuzz
+{
+ public static class FontExtensions
+ {
+ public static SKSizeI GetScale(this Font font)
+ {
+ if (font == null)
+ {
+ throw new ArgumentNullException(nameof(font));
+ }
+
+ font.GetScale(out var scaleX, out var scaleY);
+ return new SKSizeI(scaleX, scaleY);
+ }
+
+ public static void SetScale(this Font font, SKSizeI scale)
+ {
+ if (font == null)
+ {
+ throw new ArgumentNullException(nameof(font));
+ }
+
+ font.SetScale(scale.Width, scale.Height);
+ }
+ }
+}
--- /dev/null
+using System;
+
+using HarfBuzzSharp;
+using Buffer = HarfBuzzSharp.Buffer;
+
+namespace SkiaSharp.HarfBuzz
+{
+ public class SKShaper : IDisposable
+ {
+ internal const int FONT_SIZE_SCALE = 512;
+
+ private Font font;
+ private Buffer buffer;
+
+ public SKShaper(SKTypeface typeface)
+ {
+ Typeface = typeface ?? throw new ArgumentNullException(nameof(typeface));
+
+ int index;
+ using (var blob = Typeface.OpenStream(out index).ToHarfBuzzBlob())
+ using (var face = new Face(blob, index))
+ {
+ face.Index = index;
+ face.UnitsPerEm = Typeface.UnitsPerEm;
+
+ font = new Font(face);
+ font.SetScale(FONT_SIZE_SCALE, FONT_SIZE_SCALE);
+
+ font.SetFunctionsOpenType();
+ }
+
+ buffer = new Buffer();
+ }
+
+ public SKTypeface Typeface { get; private set; }
+
+ public void Dispose()
+ {
+ font?.Dispose();
+ buffer?.Dispose();
+ }
+
+ public Result Shape(Buffer buffer, SKPaint paint) =>
+ Shape(buffer, 0, 0, paint);
+
+ public Result Shape(Buffer buffer, float xOffset, float yOffset, SKPaint paint)
+ {
+ if (buffer == null)
+ {
+ throw new ArgumentNullException(nameof(buffer));
+ }
+
+ if (paint == null)
+ {
+ throw new ArgumentNullException(nameof(paint));
+ }
+
+ // do the shaping
+ font.Shape(buffer);
+
+ // get the shaping results
+ var len = buffer.Length;
+ var info = buffer.GlyphInfos;
+ var pos = buffer.GlyphPositions;
+
+ // get the sizes
+ float textSizeY = paint.TextSize / FONT_SIZE_SCALE;
+ float textSizeX = textSizeY * paint.TextScaleX;
+
+ var points = new SKPoint[len];
+ var clusters = new uint[len];
+ var codepoints = new uint[len];
+
+ for (var i = 0; i < len; i++)
+ {
+ codepoints[i] = info[i].Codepoint;
+
+ clusters[i] = info[i].Cluster;
+
+ points[i] = new SKPoint(
+ xOffset + pos[i].XOffset * textSizeX,
+ yOffset - pos[i].YOffset * textSizeY);
+
+ // move the cursor
+ xOffset += pos[i].XAdvance * textSizeX;
+ yOffset += pos[i].YAdvance * textSizeY;
+ }
+
+ return new Result(codepoints, clusters, points);
+ }
+
+ public Result Shape(string text, SKPaint paint) =>
+ Shape(text, 0, 0, paint);
+
+ public Result Shape(string text, float xOffset, float yOffset, SKPaint paint)
+ {
+ if (string.IsNullOrEmpty(text))
+ {
+ return new Result();
+ }
+
+ using (var buffer = new Buffer())
+ {
+ switch (paint.TextEncoding)
+ {
+ case SKTextEncoding.Utf8:
+ buffer.AddUtf8(text);
+ break;
+ case SKTextEncoding.Utf16:
+ buffer.AddUtf16(text);
+ break;
+ case SKTextEncoding.Utf32:
+ buffer.AddUtf32(text);
+ break;
+ default:
+ throw new NotSupportedException("TextEncoding of type GlyphId is not supported.");
+ }
+
+ buffer.GuessSegmentProperties();
+
+ return Shape(buffer, xOffset, yOffset, paint);
+ }
+ }
+
+ public class Result
+ {
+ public Result()
+ {
+ Codepoints = new uint[0];
+ Clusters = new uint[0];
+ Points = new SKPoint[0];
+ }
+
+ public Result(uint[] codepoints, uint[] clusters, SKPoint[] points)
+ {
+ Codepoints = codepoints;
+ Clusters = clusters;
+ Points = points;
+ }
+
+ public uint[] Codepoints { get; private set; }
+
+ public uint[] Clusters { get; private set; }
+
+ public SKPoint[] Points { get; private set; }
+ }
+ }
+}
--- /dev/null
+using Xamarin.Forms;
+
+namespace SkiaSharp.Views.Forms
+{
+ public static class Extensions
+ {
+ public static Point ToFormsPoint(this SKPointI point)
+ {
+ return new Point(point.X, point.Y);
+ }
+
+ public static Point ToFormsPoint(this SKPoint point)
+ {
+ return new Point(point.X, point.Y);
+ }
+
+ public static SKPoint ToSKPoint(this Point point)
+ {
+ return new SKPoint((float)point.X, (float)point.Y);
+ }
+
+ // Xamarin.Forms.Point
+
+ public static Size ToFormsSize(this SKSizeI size)
+ {
+ return new Size(size.Width, size.Height);
+ }
+
+ public static Size ToFormsSize(this SKSize size)
+ {
+ return new Size(size.Width, size.Height);
+ }
+
+ public static SKSize ToSKSize(this Size size)
+ {
+ return new SKSize((float)size.Width, (float)size.Height);
+ }
+
+ // Xamarin.Forms.Size
+
+ public static Rectangle ToFormsRect(this SKRectI rect)
+ {
+ return new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height);
+ }
+
+ public static Rectangle ToFormsRect(this SKRect rect)
+ {
+ return new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height);
+ }
+
+ public static SKRect ToSKRect(this Rectangle rect)
+ {
+ return new SKRect((float)rect.Left, (float)rect.Top, (float)rect.Right, (float)rect.Bottom);
+ }
+
+ // Xamarin.Forms.Color
+
+ public static Color ToFormsColor(this SKColor color)
+ {
+ return new Color(color.Red / 255.0, color.Green / 255.0, color.Blue / 255.0, color.Alpha / 255.0);
+ }
+
+ public static SKColor ToSKColor(this Color color)
+ {
+ return new SKColor((byte)(color.R * 255), (byte)(color.G * 255), (byte)(color.B * 255), (byte)(color.A * 255));
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp.Views.Forms
+{
+ internal class Registrar
+ {
+ internal static void EnsureRegistered(Type type, Type handler)
+ {
+ var registered = Xamarin.Forms.Internals.Registrar.Registered;
+ if (registered.GetHandlerType(type) != null)
+ return;
+ registered.Register(type, handler);
+ }
+ }
+
+ public sealed partial class SKImageImageSource
+ {
+ static SKImageImageSource() =>
+ Registrar.EnsureRegistered(typeof(SKImageImageSource), typeof(SKImageSourceHandler));
+ }
+
+ public sealed partial class SKBitmapImageSource
+ {
+ static SKBitmapImageSource() =>
+ Registrar.EnsureRegistered(typeof(SKBitmapImageSource), typeof(SKImageSourceHandler));
+ }
+
+ public sealed partial class SKPixmapImageSource
+ {
+ static SKPixmapImageSource() =>
+ Registrar.EnsureRegistered(typeof(SKPixmapImageSource), typeof(SKImageSourceHandler));
+ }
+
+ public sealed partial class SKPictureImageSource
+ {
+ static SKPictureImageSource() =>
+ Registrar.EnsureRegistered(typeof(SKPictureImageSource), typeof(SKImageSourceHandler));
+ }
+
+ public partial class SKCanvasView
+ {
+ static SKCanvasView() =>
+ Registrar.EnsureRegistered(typeof(SKCanvasView), typeof(SKCanvasViewRenderer));
+ }
+
+ public partial class SKGLView
+ {
+ static SKGLView() =>
+ Registrar.EnsureRegistered(typeof(SKGLView), typeof(SKGLViewRenderer));
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp.Views.Forms
+{
+ public class GetPropertyValueEventArgs<T> : EventArgs
+ {
+ public T Value { get; set; }
+ }
+}
--- /dev/null
+using System;
+using Xamarin.Forms;
+
+namespace SkiaSharp.Views.Forms
+{
+ [RenderWith(typeof(SKCanvasViewRenderer))]
+ public partial class SKCanvasView : View, ISKCanvasViewController
+ {
+ public static readonly BindableProperty IgnorePixelScalingProperty =
+ BindableProperty.Create(nameof(IgnorePixelScaling), typeof(bool), typeof(SKCanvasView), false);
+
+ public static readonly BindableProperty EnableTouchEventsProperty =
+ BindableProperty.Create(nameof(EnableTouchEvents), typeof(bool), typeof(SKCanvasView), false);
+
+ // the user can subscribe to repaint
+ public event EventHandler<SKPaintSurfaceEventArgs> PaintSurface;
+
+ // the user can subscribe to touch events
+ public event EventHandler<SKTouchEventArgs> Touch;
+
+ // the native listens to this event
+ private event EventHandler SurfaceInvalidated;
+ private event EventHandler<GetPropertyValueEventArgs<SKSize>> GetCanvasSize;
+
+ // the user asks the for the size
+ public SKSize CanvasSize
+ {
+ get
+ {
+ // send a mesage to the native view
+ var args = new GetPropertyValueEventArgs<SKSize>();
+ GetCanvasSize?.Invoke(this, args);
+ return args.Value;
+ }
+ }
+
+ public bool IgnorePixelScaling
+ {
+ get { return (bool)GetValue(IgnorePixelScalingProperty); }
+ set { SetValue(IgnorePixelScalingProperty, value); }
+ }
+
+ public bool EnableTouchEvents
+ {
+ get { return (bool)GetValue(EnableTouchEventsProperty); }
+ set { SetValue(EnableTouchEventsProperty, value); }
+ }
+
+ // the user asks to repaint
+ public void InvalidateSurface()
+ {
+ // send a mesage to the native view
+ SurfaceInvalidated?.Invoke(this, EventArgs.Empty);
+ }
+
+ // the native view tells the user to repaint
+ protected virtual void OnPaintSurface(SKPaintSurfaceEventArgs e)
+ {
+ PaintSurface?.Invoke(this, e);
+ }
+
+ // the native view responds to a touch
+ protected virtual void OnTouch(SKTouchEventArgs e)
+ {
+ Touch?.Invoke(this, e);
+ }
+
+ // ISKViewController implementation
+
+ event EventHandler ISKCanvasViewController.SurfaceInvalidated
+ {
+ add { SurfaceInvalidated += value; }
+ remove { SurfaceInvalidated -= value; }
+ }
+
+ event EventHandler<GetPropertyValueEventArgs<SKSize>> ISKCanvasViewController.GetCanvasSize
+ {
+ add { GetCanvasSize += value; }
+ remove { GetCanvasSize -= value; }
+ }
+
+ void ISKCanvasViewController.OnPaintSurface(SKPaintSurfaceEventArgs e)
+ {
+ OnPaintSurface(e);
+ }
+
+ void ISKCanvasViewController.OnTouch(SKTouchEventArgs e)
+ {
+ OnTouch(e);
+ }
+
+ protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
+ {
+ return new SizeRequest(new Size(40.0, 40.0));
+ }
+ }
+
+ public interface ISKCanvasViewController : IViewController
+ {
+ // the native listens to this event
+ event EventHandler SurfaceInvalidated;
+ event EventHandler<GetPropertyValueEventArgs<SKSize>> GetCanvasSize;
+
+ // the native view tells the user to repaint
+ void OnPaintSurface(SKPaintSurfaceEventArgs e);
+
+ // the native view responds to a touch
+ void OnTouch(SKTouchEventArgs e);
+ }
+}
--- /dev/null
+using Xamarin.Forms;
+
+using SKFormsView = SkiaSharp.Views.Forms.SKCanvasView;
+using SKNativeView = SkiaSharp.Views.Tizen.SKCanvasView;
+
+[assembly: ExportRenderer(typeof(SKFormsView), typeof(SkiaSharp.Views.Forms.SKCanvasViewRenderer))]
+
+namespace SkiaSharp.Views.Forms
+{
+ public class SKCanvasViewRenderer : SKCanvasViewRendererBase<SKFormsView, SKNativeView>, IRegisterable
+ {
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using SKFormsView = SkiaSharp.Views.Forms.SKCanvasView;
+using Xamarin.Forms.Platform.Tizen;
+using SKNativeView = SkiaSharp.Views.Tizen.SKCanvasView;
+using SKNativePaintSurfaceEventArgs = SkiaSharp.Views.Tizen.SKPaintSurfaceEventArgs;
+using TForms = Xamarin.Forms.Forms;
+
+namespace SkiaSharp.Views.Forms
+{
+ public abstract class SKCanvasViewRendererBase<TFormsView, TNativeView> : ViewRenderer<TFormsView, TNativeView>
+ where TFormsView : SKFormsView
+ where TNativeView : SKNativeView
+ {
+ private SKTouchHandler touchHandler;
+
+ protected SKCanvasViewRendererBase()
+ {
+ Initialize();
+ }
+
+ private void Initialize()
+ {
+ touchHandler = new SKTouchHandler(
+ args => ((ISKCanvasViewController)Element).OnTouch(args),
+ (x, y) => GetScaledCoord(x, y));
+ }
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TFormsView> e)
+ {
+ if (e.OldElement != null)
+ {
+ var oldController = (ISKCanvasViewController)e.OldElement;
+
+ // unsubscribe from events
+ oldController.SurfaceInvalidated -= OnSurfaceInvalidated;
+ oldController.GetCanvasSize -= OnGetCanvasSize;
+ }
+
+ if (e.NewElement != null)
+ {
+ var newController = (ISKCanvasViewController)e.NewElement;
+
+ // create the native view
+ if (Control == null)
+ {
+ var view = CreateNativeControl();
+ view.PaintSurface += OnPaintSurface;
+ SetNativeControl(view);
+ }
+
+ // set the initial values
+ touchHandler.SetEnabled(Control, e.NewElement.EnableTouchEvents);
+
+ // TODO: implement this if it is actually supported
+ Control.IgnorePixelScaling = e.NewElement.IgnorePixelScaling;
+
+ // subscribe to events from the user
+ newController.SurfaceInvalidated += OnSurfaceInvalidated;
+ newController.GetCanvasSize += OnGetCanvasSize;
+
+ // paint for the first time
+ OnSurfaceInvalidated(newController, EventArgs.Empty);
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected virtual TNativeView CreateNativeControl()
+ {
+ TNativeView ret = (TNativeView)Activator.CreateInstance(typeof(TNativeView), new[] { TForms.NativeParent });
+ return ret;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ if (e.PropertyName == SKFormsView.IgnorePixelScalingProperty.PropertyName)
+ {
+ // TODO: implement this if it is actually supported
+ Control.IgnorePixelScaling = Element.IgnorePixelScaling;
+ }
+ else if (e.PropertyName == SKFormsView.EnableTouchEventsProperty.PropertyName)
+ {
+ touchHandler.SetEnabled(Control, Element.EnableTouchEvents);
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // detach all events before disposing
+ var controller = (ISKCanvasViewController)Element;
+ if (controller != null)
+ {
+ controller.SurfaceInvalidated -= OnSurfaceInvalidated;
+ controller.GetCanvasSize -= OnGetCanvasSize;
+ }
+
+ var control = Control;
+ if (control != null)
+ {
+ control.PaintSurface -= OnPaintSurface;
+ }
+
+ // detach, regardless of state
+ touchHandler.Detach(control);
+
+ base.Dispose(disposing);
+ }
+
+ private SKPoint GetScaledCoord(double x, double y)
+ {
+ if (Element.IgnorePixelScaling)
+ {
+ x = Tizen.ScalingInfo.FromPixel(x);
+ y = Tizen.ScalingInfo.FromPixel(y);
+ }
+ else
+ {
+ // Tizen and Android are the reverse of the other platforms
+ }
+
+ return new SKPoint((float)x, (float)y);
+ }
+
+ private void OnPaintSurface(object sender, SKNativePaintSurfaceEventArgs e)
+ {
+ var controller = Element as ISKCanvasViewController;
+
+ // the control is being repainted, let the user know
+ controller?.OnPaintSurface(new SKPaintSurfaceEventArgs(e.Surface, e.Info));
+ }
+
+ private void OnSurfaceInvalidated(object sender, EventArgs eventArgs)
+ {
+ // repaint the native control
+ Control.Invalidate();
+ }
+
+ // the user asked for the size
+ private void OnGetCanvasSize(object sender, GetPropertyValueEventArgs<SKSize> e)
+ {
+ e.Value = Control?.CanvasSize ?? SKSize.Empty;
+ }
+ }
+}
--- /dev/null
+using System;
+using Xamarin.Forms;
+
+namespace SkiaSharp.Views.Forms
+{
+ [RenderWith(typeof(SKGLViewRenderer))]
+ public partial class SKGLView : View, ISKGLViewController
+ {
+ public static readonly BindableProperty HasRenderLoopProperty =
+ BindableProperty.Create(nameof(HasRenderLoop), typeof(bool), typeof(SKGLView), false);
+
+ public static readonly BindableProperty EnableTouchEventsProperty =
+ BindableProperty.Create(nameof(EnableTouchEvents), typeof(bool), typeof(SKGLView), false);
+
+ public bool HasRenderLoop
+ {
+ get { return (bool)GetValue(HasRenderLoopProperty); }
+ set { SetValue(HasRenderLoopProperty, value); }
+ }
+
+ public bool EnableTouchEvents
+ {
+ get { return (bool)GetValue(EnableTouchEventsProperty); }
+ set { SetValue(EnableTouchEventsProperty, value); }
+ }
+
+ // the user can subscribe to repaint
+ public event EventHandler<SKPaintGLSurfaceEventArgs> PaintSurface;
+
+ // the user can subscribe to touch events
+ public event EventHandler<SKTouchEventArgs> Touch;
+
+ // the native listens to this event
+ private event EventHandler SurfaceInvalidated;
+ private event EventHandler<GetPropertyValueEventArgs<SKSize>> GetCanvasSize;
+ private event EventHandler<GetPropertyValueEventArgs<GRContext>> GetGRContext;
+
+ // the user asks the for the size
+ public SKSize CanvasSize
+ {
+ get
+ {
+ // send a mesage to the native view
+ var args = new GetPropertyValueEventArgs<SKSize>();
+ GetCanvasSize?.Invoke(this, args);
+ return args.Value;
+ }
+ }
+
+ // the user asks the for the current GRContext
+ public GRContext GRContext
+ {
+ get
+ {
+ // send a mesage to the native view
+ var args = new GetPropertyValueEventArgs<GRContext>();
+ GetGRContext?.Invoke(this, args);
+ return args.Value;
+ }
+ }
+
+ // the user asks to repaint
+ public void InvalidateSurface()
+ {
+ // send a mesage to the native view
+ SurfaceInvalidated?.Invoke(this, EventArgs.Empty);
+ }
+
+ // the native view tells the user to repaint
+ protected virtual void OnPaintSurface(SKPaintGLSurfaceEventArgs e)
+ {
+ PaintSurface?.Invoke(this, e);
+ }
+
+ // the native view responds to a touch
+ protected virtual void OnTouch(SKTouchEventArgs e)
+ {
+ Touch?.Invoke(this, e);
+ }
+
+ // ISKViewController implementation
+
+ event EventHandler ISKGLViewController.SurfaceInvalidated
+ {
+ add { SurfaceInvalidated += value; }
+ remove { SurfaceInvalidated -= value; }
+ }
+
+ event EventHandler<GetPropertyValueEventArgs<SKSize>> ISKGLViewController.GetCanvasSize
+ {
+ add { GetCanvasSize += value; }
+ remove { GetCanvasSize -= value; }
+ }
+
+ event EventHandler<GetPropertyValueEventArgs<GRContext>> ISKGLViewController.GetGRContext
+ {
+ add { GetGRContext += value; }
+ remove { GetGRContext -= value; }
+ }
+
+ void ISKGLViewController.OnPaintSurface(SKPaintGLSurfaceEventArgs e)
+ {
+ OnPaintSurface(e);
+ }
+
+ void ISKGLViewController.OnTouch(SKTouchEventArgs e)
+ {
+ OnTouch(e);
+ }
+
+ protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
+ {
+ return new SizeRequest(new Size(40.0, 40.0));
+ }
+ }
+
+ public interface ISKGLViewController : IViewController
+ {
+ // the native listens to this event
+ event EventHandler SurfaceInvalidated;
+ event EventHandler<GetPropertyValueEventArgs<SKSize>> GetCanvasSize;
+ event EventHandler<GetPropertyValueEventArgs<GRContext>> GetGRContext;
+
+ // the native view tells the user to repaint
+ void OnPaintSurface(SKPaintGLSurfaceEventArgs e);
+
+ // the native view responds to a touch
+ void OnTouch(SKTouchEventArgs e);
+ }
+}
--- /dev/null
+using SkiaSharp.Views.Tizen;
+using Xamarin.Forms;
+
+using SKFormsView = SkiaSharp.Views.Forms.SKGLView;
+using SKNativeView = SkiaSharp.Views.Tizen.SKGLSurfaceView;
+
+[assembly: ExportRenderer(typeof(SKFormsView), typeof(SkiaSharp.Views.Forms.SKGLViewRenderer))]
+
+namespace SkiaSharp.Views.Forms
+{
+ public class SKGLViewRenderer : SKGLViewRendererBase<SKFormsView, SKNativeView>
+ {
+ protected override void SetupRenderLoop(bool oneShot)
+ {
+ if (oneShot)
+ {
+ Control.Invalidate();
+ }
+
+ Control.RenderingMode = Element.HasRenderLoop ? RenderingMode.Continuously : RenderingMode.WhenDirty;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using Xamarin.Forms;
+using SKFormsView = SkiaSharp.Views.Forms.SKGLView;
+using Xamarin.Forms.Platform.Tizen;
+using SKNativeView = SkiaSharp.Views.Tizen.SKGLSurfaceView;
+using SKNativePaintGLSurfaceEventArgs = SkiaSharp.Views.Tizen.SKPaintGLSurfaceEventArgs;
+using TForms = Xamarin.Forms.Forms;
+
+namespace SkiaSharp.Views.Forms
+{
+ public abstract class SKGLViewRendererBase<TFormsView, TNativeView> : ViewRenderer<TFormsView, TNativeView>
+ where TFormsView : SKFormsView
+ where TNativeView : SKNativeView
+ {
+ private SKTouchHandler touchHandler;
+
+ protected SKGLViewRendererBase()
+ {
+ Initialize();
+ }
+
+ private void Initialize()
+ {
+ touchHandler = new SKTouchHandler(
+ args => ((ISKGLViewController)Element).OnTouch(args),
+ (x, y) => GetScaledCoord(x, y));
+ }
+
+ public GRContext GRContext => Control.GRContext;
+
+ protected override void OnElementChanged(ElementChangedEventArgs<TFormsView> e)
+ {
+ if (e.OldElement != null)
+ {
+ var oldController = (ISKGLViewController)e.OldElement;
+
+ // unsubscribe from events
+ oldController.SurfaceInvalidated -= OnSurfaceInvalidated;
+ oldController.GetCanvasSize -= OnGetCanvasSize;
+ oldController.GetGRContext -= OnGetGRContext;
+ }
+
+ if (e.NewElement != null)
+ {
+ var newController = (ISKGLViewController)e.NewElement;
+
+ // create the native view
+ if (Control == null)
+ {
+ var view = CreateNativeControl();
+ view.PaintSurface += OnPaintSurface;
+ SetNativeControl(view);
+ }
+
+ touchHandler.SetEnabled(Control, e.NewElement.EnableTouchEvents);
+
+ // subscribe to events from the user
+ newController.SurfaceInvalidated += OnSurfaceInvalidated;
+ newController.GetCanvasSize += OnGetCanvasSize;
+ newController.GetGRContext += OnGetGRContext;
+
+ // start the rendering
+ SetupRenderLoop(false);
+ }
+
+ base.OnElementChanged(e);
+ }
+
+ protected virtual TNativeView CreateNativeControl()
+ {
+ TNativeView ret = (TNativeView)Activator.CreateInstance(typeof(TNativeView), new[] { TForms.NativeParent });
+ return ret;
+ }
+
+ protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ base.OnElementPropertyChanged(sender, e);
+
+ // refresh the render loop
+ if (e.PropertyName == SKFormsView.HasRenderLoopProperty.PropertyName)
+ {
+ SetupRenderLoop(false);
+ }
+ else if (e.PropertyName == SKFormsView.EnableTouchEventsProperty.PropertyName)
+ {
+ touchHandler.SetEnabled(Control, Element.EnableTouchEvents);
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ // detach all events before disposing
+ var controller = (ISKGLViewController)Element;
+ if (controller != null)
+ {
+ controller.SurfaceInvalidated -= OnSurfaceInvalidated;
+ controller.GetCanvasSize -= OnGetCanvasSize;
+ controller.GetGRContext -= OnGetGRContext;
+ }
+
+ var control = Control;
+ if (control != null)
+ {
+ control.PaintSurface -= OnPaintSurface;
+ }
+
+ // detach, regardless of state
+ touchHandler.Detach(control);
+
+ base.Dispose(disposing);
+ }
+
+ protected abstract void SetupRenderLoop(bool oneShot);
+
+ private SKPoint GetScaledCoord(double x, double y)
+ {
+ // Android and Tizen are the reverse of the other platforms
+ return new SKPoint((float)x, (float)y);
+ }
+
+
+ // the user asked to repaint
+ private void OnSurfaceInvalidated(object sender, EventArgs eventArgs)
+ {
+ // if we aren't in a loop, then refresh once
+ if (!Element.HasRenderLoop)
+ {
+ SetupRenderLoop(true);
+ }
+ }
+
+ // the user asked for the size
+ private void OnGetCanvasSize(object sender, GetPropertyValueEventArgs<SKSize> e)
+ {
+ e.Value = Control?.CanvasSize ?? SKSize.Empty;
+ }
+
+ // the user asked for the current GRContext
+ private void OnGetGRContext(object sender, GetPropertyValueEventArgs<GRContext> e)
+ {
+ e.Value = Control?.GRContext;
+ }
+
+ private void OnPaintSurface(object sender, SKNativePaintGLSurfaceEventArgs e)
+ {
+ var controller = Element as ISKGLViewController;
+
+ // the control is being repainted, let the user know
+ controller?.OnPaintSurface(new SKPaintGLSurfaceEventArgs(e.Surface, e.BackendRenderTarget));
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System.Threading.Tasks;
+using Xamarin.Forms;
+
+namespace SkiaSharp.Views.Forms
+{
+ public sealed partial class SKImageImageSource : ImageSource
+ {
+ public static readonly BindableProperty ImageProperty = BindableProperty.Create(nameof(Image), typeof(SKImage), typeof(SKImageImageSource), default(SKImage));
+
+ public SKImage Image
+ {
+ get { return (SKImage)GetValue(ImageProperty); }
+ set { SetValue(ImageProperty, value); }
+ }
+
+ public override Task<bool> Cancel()
+ {
+ return Task.FromResult(false);
+ }
+
+ public static implicit operator SKImageImageSource(SKImage image)
+ {
+ return new SKImageImageSource
+ {
+ Image = image
+ };
+ }
+
+ public static implicit operator SKImage(SKImageImageSource source)
+ {
+ return source?.Image;
+ }
+
+ protected override void OnPropertyChanged(string propertyName = null)
+ {
+ if (propertyName == ImageProperty.PropertyName)
+ OnSourceChanged();
+ base.OnPropertyChanged(propertyName);
+ }
+ }
+
+ public sealed partial class SKBitmapImageSource : ImageSource
+ {
+ public static readonly BindableProperty BitmapProperty = BindableProperty.Create(nameof(Bitmap), typeof(SKBitmap), typeof(SKBitmapImageSource), default(SKBitmap));
+
+ public SKBitmap Bitmap
+ {
+ get { return (SKBitmap)GetValue(BitmapProperty); }
+ set { SetValue(BitmapProperty, value); }
+ }
+
+ public override Task<bool> Cancel()
+ {
+ return Task.FromResult(false);
+ }
+
+ public static implicit operator SKBitmapImageSource(SKBitmap bitmap)
+ {
+ return new SKBitmapImageSource
+ {
+ Bitmap = bitmap
+ };
+ }
+
+ public static implicit operator SKBitmap(SKBitmapImageSource source)
+ {
+ return source?.Bitmap;
+ }
+
+ protected override void OnPropertyChanged(string propertyName = null)
+ {
+ if (propertyName == BitmapProperty.PropertyName)
+ OnSourceChanged();
+ base.OnPropertyChanged(propertyName);
+ }
+ }
+
+ public sealed partial class SKPixmapImageSource : ImageSource
+ {
+ public static readonly BindableProperty PixmapProperty = BindableProperty.Create(nameof(Pixmap), typeof(SKPixmap), typeof(SKPixmapImageSource), default(SKPixmap));
+
+ public SKPixmap Pixmap
+ {
+ get { return (SKPixmap)GetValue(PixmapProperty); }
+ set { SetValue(PixmapProperty, value); }
+ }
+
+ public override Task<bool> Cancel()
+ {
+ return Task.FromResult(false);
+ }
+
+ public static implicit operator SKPixmapImageSource(SKPixmap pixmap)
+ {
+ return new SKPixmapImageSource
+ {
+ Pixmap = pixmap
+ };
+ }
+
+ public static implicit operator SKPixmap(SKPixmapImageSource source)
+ {
+ return source?.Pixmap;
+ }
+
+ protected override void OnPropertyChanged(string propertyName = null)
+ {
+ if (propertyName == PixmapProperty.PropertyName)
+ OnSourceChanged();
+ base.OnPropertyChanged(propertyName);
+ }
+ }
+
+ public sealed partial class SKPictureImageSource : ImageSource
+ {
+ public static readonly BindableProperty PictureProperty = BindableProperty.Create(nameof(Picture), typeof(SKPicture), typeof(SKPictureImageSource), default(SKPicture));
+
+ public static readonly BindableProperty DimensionsProperty = BindableProperty.Create(nameof(Dimensions), typeof(SKSizeI), typeof(SKPictureImageSource), default(SKSizeI));
+
+ public SKPicture Picture
+ {
+ get { return (SKPicture)GetValue(PictureProperty); }
+ set { SetValue(PictureProperty, value); }
+ }
+
+ public SKSizeI Dimensions
+ {
+ get { return (SKSizeI)GetValue(DimensionsProperty); }
+ set { SetValue(DimensionsProperty, value); }
+ }
+
+ public override Task<bool> Cancel()
+ {
+ return Task.FromResult(false);
+ }
+
+ public static explicit operator SKPicture(SKPictureImageSource source)
+ {
+ return source?.Picture;
+ }
+
+ protected override void OnPropertyChanged(string propertyName = null)
+ {
+ if (propertyName == PictureProperty.PropertyName)
+ OnSourceChanged();
+ base.OnPropertyChanged(propertyName);
+ }
+ }
+}
--- /dev/null
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+using Xamarin.Forms;
+using Xamarin.Forms.Platform.Tizen;
+
+using ElmImage = ElmSharp.Image;
+
+[assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKImageImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKBitmapImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKPixmapImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))]
+[assembly: ExportImageSourceHandler(typeof(SkiaSharp.Views.Forms.SKPictureImageSource), typeof(SkiaSharp.Views.Forms.SKImageSourceHandler))]
+
+namespace SkiaSharp.Views.Forms
+{
+ public sealed class SKImageSourceHandler : IImageSourceHandler
+ {
+ private StreamImageSourceHandler handler = new StreamImageSourceHandler();
+
+ public Task<bool> LoadImageAsync(ElmImage image, ImageSource imageSource, CancellationToken cancelationToken = default(CancellationToken))
+ {
+ ImageSource newSource = null;
+
+ switch (imageSource)
+ {
+ case SKImageImageSource imageImageSource:
+ newSource = ImageSource.FromStream(() => ToStream(imageImageSource.Image));
+ break;
+ case SKBitmapImageSource bitmapImageSource:
+ newSource = ImageSource.FromStream(() => ToStream(SKImage.FromBitmap(bitmapImageSource.Bitmap)));
+ break;
+ case SKPixmapImageSource pixmapImageSource:
+ newSource = ImageSource.FromStream(() => ToStream(SKImage.FromPixels(pixmapImageSource.Pixmap)));
+ break;
+ case SKPictureImageSource pictureImageSource:
+ newSource = ImageSource.FromStream(() => ToStream(SKImage.FromPicture(pictureImageSource.Picture, pictureImageSource.Dimensions)));
+ break;
+ }
+
+ return handler.LoadImageAsync(image, newSource, cancelationToken);
+ }
+
+ private static Stream ToStream(SKImage skiaImage)
+ {
+ return skiaImage.Encode().AsStream();
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp.Views.Forms
+{
+ public class SKPaintGLSurfaceEventArgs : EventArgs
+ {
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ private GRBackendRenderTargetDesc? rtDesc;
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete("Use SKPaintGLSurfaceEventArgs(SKSurface, GRBackendRenderTarget, SKColorType, GRSurfaceOrigin) instead.")]
+ public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
+ {
+ Surface = surface;
+ rtDesc = renderTarget;
+ BackendRenderTarget = new GRBackendRenderTarget(GRBackend.OpenGL, renderTarget);
+ ColorType = renderTarget.Config.ToColorType();
+ Origin = renderTarget.Origin;
+ }
+
+ public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget)
+ : this(surface, renderTarget, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888)
+ {
+ }
+
+ public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType)
+ {
+ Surface = surface;
+ BackendRenderTarget = renderTarget;
+ ColorType = colorType;
+ Origin = origin;
+ }
+
+ public SKSurface Surface { get; private set; }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete("Use BackendRenderTarget instead.")]
+ public GRBackendRenderTargetDesc RenderTarget
+ {
+ get
+ {
+ if (!rtDesc.HasValue)
+ {
+ var rth = IntPtr.Zero;
+ if (BackendRenderTarget.GetGlFramebufferInfo(out var glInfo))
+ {
+ rth = (IntPtr)glInfo.FramebufferObjectId;
+ }
+
+ rtDesc = new GRBackendRenderTargetDesc
+ {
+ Width = BackendRenderTarget.Width,
+ Height = BackendRenderTarget.Height,
+ RenderTargetHandle = rth,
+ SampleCount = BackendRenderTarget.SampleCount,
+ StencilBits = BackendRenderTarget.StencilBits,
+ Config = ColorType.ToPixelConfig(),
+ Origin = Origin,
+ };
+ }
+
+ return rtDesc.Value;
+ }
+ }
+
+ public GRBackendRenderTarget BackendRenderTarget { get; private set; }
+
+ public SKColorType ColorType { get; private set; }
+
+ public GRSurfaceOrigin Origin { get; private set; }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp.Views.Forms
+{
+ public class SKPaintSurfaceEventArgs : EventArgs
+ {
+ public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info)
+ {
+ Surface = surface;
+ Info = info;
+ }
+
+ public SKSurface Surface { get; private set; }
+
+ public SKImageInfo Info { get; private set; }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp.Views.Forms
+{
+ public class SKTouchEventArgs : EventArgs
+ {
+ public SKTouchEventArgs(long id, SKTouchAction type, SKPoint location, bool inContact)
+ : this(id, type, SKMouseButton.Left, SKTouchDeviceType.Touch, location, inContact, 0, 1)
+ {
+ }
+
+ public SKTouchEventArgs(long id, SKTouchAction type, SKMouseButton mouseButton, SKTouchDeviceType deviceType, SKPoint location, bool inContact)
+ : this(id, type, mouseButton, deviceType, location, inContact, 0, 1)
+ {
+ }
+
+ public SKTouchEventArgs(long id, SKTouchAction type, SKMouseButton mouseButton, SKTouchDeviceType deviceType, SKPoint location, bool inContact, int wheelDelta)
+ : this(id, type, mouseButton, deviceType, location, inContact, wheelDelta, 1)
+ {
+ }
+
+ public SKTouchEventArgs(long id, SKTouchAction type, SKMouseButton mouseButton, SKTouchDeviceType deviceType, SKPoint location, bool inContact, int wheelDelta, float pressure)
+ {
+ Id = id;
+ ActionType = type;
+ DeviceType = deviceType;
+ MouseButton = mouseButton;
+ Location = location;
+ InContact = inContact;
+ WheelDelta = wheelDelta;
+ Pressure = pressure;
+ }
+
+ public bool Handled { get; set; }
+
+ public long Id { get; private set; }
+
+ public SKTouchAction ActionType { get; private set; }
+
+ public SKTouchDeviceType DeviceType { get; private set; }
+
+ public SKMouseButton MouseButton { get; private set; }
+
+ public SKPoint Location { get; private set; }
+
+ public bool InContact { get; private set; }
+
+ public int WheelDelta { get; private set; }
+
+ public float Pressure { get; private set; }
+
+ public override string ToString()
+ {
+ return $"{{ActionType={ActionType}, DeviceType={DeviceType}, Handled={Handled}, Id={Id}, InContact={InContact}, Location={Location}, MouseButton={MouseButton}, WheelDelta={WheelDelta}, Pressure={Pressure}}}";
+ }
+ }
+
+ public enum SKTouchAction
+ {
+ Entered,
+ Pressed,
+ Moved,
+ Released,
+ Cancelled,
+ Exited,
+ WheelChanged,
+ }
+
+ public enum SKTouchDeviceType
+ {
+ Touch,
+ Mouse,
+ Pen
+ }
+
+ public enum SKMouseButton
+ {
+ Unknown,
+
+ Left,
+ Middle,
+ Right
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+
+namespace SkiaSharp.Views.Forms
+{
+ internal class SKTouchHandler
+ {
+ private readonly MomentumHandler momentumHandler;
+ private Action<SKTouchEventArgs> onTouchAction;
+ private Func<double, double, SKPoint> scalePixels;
+ private GestureLayer gestureLayer;
+
+ public SKTouchHandler(Action<SKTouchEventArgs> onTouchAction, Func<double, double, SKPoint> scalePixels)
+ {
+ this.onTouchAction = onTouchAction;
+ this.scalePixels = scalePixels;
+
+ momentumHandler = new MomentumHandler(this);
+ }
+
+ public void SetEnabled(EvasObject view, bool enableTouchEvents)
+ {
+ if (view != null)
+ {
+ if (enableTouchEvents)
+ CreateGestureLayer(view);
+ else
+ DestroyGestureLayer();
+ }
+ }
+
+ public void Detach(EvasObject view)
+ {
+ // clean the view
+ SetEnabled(view, false);
+
+ // remove references
+ onTouchAction = null;
+ scalePixels = null;
+ }
+
+ private void CreateGestureLayer(EvasObject parent)
+ {
+ if (gestureLayer == null)
+ {
+ gestureLayer = new GestureLayer(parent);
+ gestureLayer.Attach(parent);
+ gestureLayer.Deleted += (s, e) =>
+ {
+ gestureLayer = null;
+ DestroyGestureLayer();
+ };
+ gestureLayer.IsEnabled = true;
+
+ AddMomentumGesture();
+ }
+ }
+
+ private void DestroyGestureLayer()
+ {
+ if (gestureLayer != null)
+ {
+ gestureLayer.IsEnabled = false;
+ gestureLayer.Unrealize();
+ gestureLayer = null;
+ }
+ }
+
+ private void AddMomentumGesture()
+ {
+ gestureLayer.SetMomentumCallback(GestureLayer.GestureState.Start, (data) => { momentumHandler.OnStarted(); });
+ gestureLayer.SetMomentumCallback(GestureLayer.GestureState.Move, (data) => { momentumHandler.OnMoved(); });
+ gestureLayer.SetMomentumCallback(GestureLayer.GestureState.End, (data) => { momentumHandler.OnFinished(); });
+ gestureLayer.SetMomentumCallback(GestureLayer.GestureState.Abort, (data) => { momentumHandler.OnAborted(); });
+ }
+
+ private class MomentumHandler
+ {
+ private readonly SKTouchHandler handler;
+ private int currentId = 0;
+
+ public MomentumHandler(SKTouchHandler h)
+ {
+ handler = h;
+ }
+
+ public void OnStarted()
+ {
+ ++currentId;
+ PostEvent(SKTouchAction.Pressed);
+ }
+
+ public void OnMoved()
+ {
+ PostEvent(SKTouchAction.Moved);
+ }
+
+ public void OnFinished()
+ {
+ PostEvent(SKTouchAction.Released);
+ }
+
+ public void OnAborted()
+ {
+ PostEvent(SKTouchAction.Cancelled);
+ }
+
+ private void PostEvent(SKTouchAction action)
+ {
+ if (handler.onTouchAction == null || handler.scalePixels == null)
+ return;
+
+ var p = handler.gestureLayer.EvasCanvas.Pointer;
+ var coords = handler.scalePixels(p.X, p.Y);
+ var inContact = (action == SKTouchAction.Pressed || action == SKTouchAction.Moved) ? true : false;
+
+ handler.onTouchAction(new SKTouchEventArgs(currentId, action, coords, inContact));
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+using SkiaSharp.Views.Tizen.Interop;
+
+namespace SkiaSharp.Views.Tizen
+{
+ public abstract class CustomRenderingView : Widget
+ {
+ private readonly Evas.ImagePixelsSetCallback redrawCallback;
+
+ private IntPtr animator;
+ private RenderingMode renderingMode = RenderingMode.WhenDirty;
+
+ protected IntPtr evasImage;
+
+ public CustomRenderingView(EvasObject parent)
+ : base(parent)
+ {
+ Resized += (sender, e) => OnResized();
+ redrawCallback = (d, o) => OnDrawFrame();
+ }
+
+ public SKSize CanvasSize => GetSurfaceSize();
+
+ public RenderingMode RenderingMode
+ {
+ get { return renderingMode; }
+ set
+ {
+ if (renderingMode != value)
+ {
+ renderingMode = value;
+
+ if (renderingMode == RenderingMode.Continuously)
+ CreateAnimator();
+ else
+ DestroyAnimator();
+ }
+ }
+ }
+
+ public void Invalidate()
+ {
+ if (RenderingMode == RenderingMode.WhenDirty)
+ Evas.evas_object_image_pixels_dirty_set(evasImage, true);
+ }
+
+ protected virtual void CreateNativeResources(EvasObject parent)
+ {
+ // empty on purpose
+ }
+
+ protected virtual void DestroyNativeResources()
+ {
+ // empty on purpose
+ }
+
+ protected abstract void OnDrawFrame();
+
+ protected abstract bool UpdateSurfaceSize(Rect geometry);
+
+ protected abstract SKSizeI GetSurfaceSize();
+
+ protected virtual void CreateDrawingSurface()
+ {
+ // empty on purpose
+ }
+
+ protected virtual void DestroyDrawingSurface()
+ {
+ // empty on purpose
+ }
+
+ protected sealed override IntPtr CreateHandle(EvasObject parent)
+ {
+ var handle = Interop.Elementary.elm_layout_add(parent);
+ Interop.Elementary.elm_layout_theme_set(handle, "layout", "background", "default");
+
+ evasImage = Evas.evas_object_image_filled_add(Interop.Evas.evas_object_evas_get(handle));
+ Evas.evas_object_image_colorspace_set(evasImage, Evas.Colorspace.ARGB8888);
+ Evas.evas_object_image_smooth_scale_set(evasImage, true);
+ Evas.evas_object_image_alpha_set(evasImage, true);
+
+ Interop.Elementary.elm_object_part_content_set(handle, "elm.swallow.content", evasImage);
+
+ CreateNativeResources(parent);
+
+ return handle;
+ }
+
+ protected sealed override void OnUnrealize()
+ {
+ DestroyAnimator();
+ DestroyDrawingSurface();
+ DestroyNativeResources();
+
+ base.OnUnrealize();
+ }
+
+ protected void OnResized()
+ {
+ var geometry = Geometry;
+
+ // control is not yet fully initialized
+ if (geometry.Width <= 0 || geometry.Height <= 0)
+ return;
+
+ if (UpdateSurfaceSize(geometry))
+ {
+ // disconnect the callback
+ Evas.evas_object_image_native_surface_set(evasImage, IntPtr.Zero);
+
+ // recreate the drawing surface to match the new size
+ DestroyDrawingSurface();
+
+ var size = GetSurfaceSize();
+ Evas.evas_object_image_size_set(evasImage, size.Width, size.Height);
+
+ CreateDrawingSurface();
+
+ // set the image callback; will be invoked when image is marked as dirty
+ Evas.evas_object_image_pixels_get_callback_set(evasImage, redrawCallback, IntPtr.Zero);
+
+ // repaint
+ Invalidate();
+ }
+ }
+
+ private void CreateAnimator()
+ {
+ if (animator == IntPtr.Zero)
+ {
+ animator = EcoreAnimator.AddAnimator(() =>
+ {
+ Evas.evas_object_image_pixels_dirty_set(evasImage, true);
+ return true;
+ });
+ }
+ }
+
+ private void DestroyAnimator()
+ {
+ if (animator != IntPtr.Zero)
+ {
+ EcoreAnimator.RemoveAnimator(animator);
+ animator = IntPtr.Zero;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp.Views.Tizen
+{
+ public static class Extensions
+ {
+ private static readonly Lazy<bool> isValidEnvironment = new Lazy<bool>(() =>
+ {
+ try
+ {
+ // test an operation that requires the native library
+ SKPMColor.PreMultiply(SKColors.Black);
+ return true;
+ }
+ catch (DllNotFoundException)
+ {
+ // If we can't load the native library,
+ // we may be in some designer.
+ // We can make this assumption since any other member will fail
+ // at some point in the draw operation.
+ return false;
+ }
+ });
+
+ internal static bool IsValidEnvironment => isValidEnvironment.Value;
+ }
+}
--- /dev/null
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp.Views.GlesInterop
+{
+ internal static class Gles
+ {
+ private const string libGLESv2 = "libGLESv2.so";
+
+ public const int GL_FRAMEBUFFER_BINDING = 0x8CA6;
+ public const int GL_RENDERBUFFER_BINDING = 0x8CA7;
+
+ public const int GL_BGRA8_EXT = 0x93A1;
+ public const int GL_VERSION = 0x1F02;
+ public const int GL_EXTENSIONS = 0x1F03;
+
+ // GetPName
+ public const int GL_SUBPIXEL_BITS = 0x0D50;
+ public const int GL_RED_BITS = 0x0D52;
+ public const int GL_GREEN_BITS = 0x0D53;
+ public const int GL_BLUE_BITS = 0x0D54;
+ public const int GL_ALPHA_BITS = 0x0D55;
+ public const int GL_DEPTH_BITS = 0x0D56;
+ public const int GL_STENCIL_BITS = 0x0D57;
+ public const int GL_SAMPLES = 0x80A9;
+
+ // ClearBufferMask
+ public const int GL_DEPTH_BUFFER_BIT = 0x00000100;
+ public const int GL_STENCIL_BUFFER_BIT = 0x00000400;
+ public const int GL_COLOR_BUFFER_BIT = 0x00004000;
+
+ public const int GL_NEAREST = 0x2600;
+
+ public const int GL_READ_FRAMEBUFFER_ANGLE = 0x8CA8;
+ public const int GL_DRAW_FRAMEBUFFER_ANGLE = 0x8CA9;
+ public const int GL_DRAW_FRAMEBUFFER_BINDING_ANGLE = 0x8CA6;
+ public const int GL_READ_FRAMEBUFFER_BINDING_ANGLE = 0x8CAA;
+
+ // Framebuffer Object
+ public const int GL_FRAMEBUFFER = 0x8D40;
+ public const int GL_RENDERBUFFER = 0x8D41;
+
+ public const int GL_RENDERBUFFER_WIDTH = 0x8D42;
+ public const int GL_RENDERBUFFER_HEIGHT = 0x8D43;
+ public const int GL_RENDERBUFFER_INTERNAL_FORMAT = 0x8D44;
+ public const int GL_RENDERBUFFER_RED_SIZE = 0x8D50;
+ public const int GL_RENDERBUFFER_GREEN_SIZE = 0x8D51;
+ public const int GL_RENDERBUFFER_BLUE_SIZE = 0x8D52;
+ public const int GL_RENDERBUFFER_ALPHA_SIZE = 0x8D53;
+ public const int GL_RENDERBUFFER_DEPTH_SIZE = 0x8D54;
+ public const int GL_RENDERBUFFER_STENCIL_SIZE = 0x8D55;
+ public const int GL_COLOR_ATTACHMENT0 = 0x8CE0;
+ public const int GL_DEPTH_ATTACHMENT = 0x8D00;
+ public const int GL_STENCIL_ATTACHMENT = 0x8D20;
+
+ public const int GL_DEPTH_COMPONENT16 = 0x81A5;
+ public const int GL_DEPTH_STENCIL_OES = 0x84F9;
+ public const int GL_UNSIGNED_INT_24_8_OES = 0x84FA;
+ public const int GL_DEPTH24_STENCIL8_OES = 0x88F0;
+
+ [DllImport(libGLESv2)]
+ public static extern void glGenRenderbuffers(int n, [In, Out] uint[] buffers);
+ [DllImport(libGLESv2)]
+ public static extern void glGenRenderbuffers(int n, ref uint buffer);
+ [DllImport(libGLESv2)]
+ public static extern void glGenFramebuffers(int n, [In, Out] uint[] buffers);
+ [DllImport(libGLESv2)]
+ public static extern void glGenFramebuffers(int n, ref uint buffer);
+ [DllImport(libGLESv2)]
+ public static extern void glGetIntegerv(uint pname, out int data);
+ [DllImport(libGLESv2)]
+ public static extern void glGetRenderbufferParameteriv(uint target, int pname, out int param);
+ [DllImport(libGLESv2)]
+ public static extern void glBindRenderbuffer(uint target, uint buffer);
+ [DllImport(libGLESv2)]
+ public static extern void glViewport(int x, int y, int width, int height);
+ [DllImport(libGLESv2)]
+ public static extern void glClearColor(float red, float green, float blue, float alpha);
+ [DllImport(libGLESv2)]
+ public static extern void glClear(uint mask);
+ [DllImport(libGLESv2)]
+ public static extern void glBindFramebuffer(uint target, uint framebuffer);
+ [DllImport(libGLESv2)]
+ public static extern void glDeleteFramebuffers(int n, [In, Out] uint[] framebuffers);
+ [DllImport(libGLESv2)]
+ public static extern void glDeleteFramebuffers(int n, ref uint framebuffer);
+ [DllImport(libGLESv2)]
+ public static extern void glDeleteRenderbuffers(int n, [In, Out] uint[] renderbuffers);
+ [DllImport(libGLESv2)]
+ public static extern void glDeleteRenderbuffers(int n, ref uint renderbuffer);
+ [DllImport(libGLESv2)]
+ public static extern void glFramebufferRenderbuffer(uint target, uint attachment, uint renderbuffertarget, uint renderbuffer);
+ [DllImport(libGLESv2)]
+ public static extern System.IntPtr glGetString(uint value);
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp.Views.Tizen.Interop
+{
+ internal static class Elementary
+ {
+ [DllImport(Libraries.Elementary)]
+ internal static extern IntPtr elm_layout_add(IntPtr obj);
+
+ [DllImport(Libraries.Elementary)]
+ internal static extern bool elm_layout_theme_set(IntPtr obj, string klass, string group, string style);
+
+ [DllImport(Libraries.Elementary)]
+ internal static extern IntPtr elm_object_part_content_get(IntPtr obj, string part);
+
+ [DllImport(Libraries.Elementary)]
+ internal static extern void elm_object_part_content_set(IntPtr obj, string part, IntPtr content);
+
+ [DllImport(Libraries.Elementary)]
+ internal static extern IntPtr elm_image_object_get(IntPtr obj);
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp.Views.Tizen.Interop
+{
+ internal static class Evas
+ {
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_object_evas_get(IntPtr obj);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_gl_new(IntPtr evas);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_gl_free(IntPtr evas_gl);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_gl_context_create(IntPtr evas_gl, IntPtr share_ctx);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_gl_context_destroy(IntPtr evas_gl, IntPtr ctx);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_gl_surface_create(IntPtr evas_gl, IntPtr config, int width, int height);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_gl_surface_destroy(IntPtr evas_gl, IntPtr surf);
+
+ [DllImport(Libraries.Evas)]
+ [return: MarshalAs(UnmanagedType.U1)]
+ internal static extern bool evas_gl_native_surface_get(IntPtr evas_gl, IntPtr surf, out NativeSurfaceOpenGL ns);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_gl_proc_address_get(IntPtr evas_gl, string name);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_gl_api_get(IntPtr evas_gl);
+
+ [DllImport(Libraries.Evas)]
+ [return: MarshalAs(UnmanagedType.U1)]
+ internal static extern bool evas_gl_make_current(IntPtr evas_gl, IntPtr surf, IntPtr ctx);
+
+ internal struct Config
+ {
+ public ColorFormat color_format;
+ public DepthBits depth_bits;
+ public StencilBits stencil_bits;
+ public OptionsBits options_bits;
+ public MultisampleBits multisample_bits;
+ public ContextVersion gles_version;
+ }
+
+ // This structure is used to move data from one entity into another.
+ internal struct NativeSurfaceOpenGL
+ {
+ public uint texture_id;
+ public uint framebuffer_id;
+ public uint internal_format;
+ public uint format;
+ public uint x;
+ public uint y;
+ public uint w;
+ public uint h;
+ }
+
+ internal enum ColorFormat
+ {
+ RGB_888 = 0,
+ RGBA_8888 = 1,
+ NO_FBO = 2
+ }
+
+ internal enum DepthBits
+ {
+ NONE = 0,
+ BIT_8 = 1,
+ BIT_16 = 2,
+ BIT_24 = 3,
+ BIT_32 = 4
+ }
+
+ internal enum StencilBits
+ {
+ NONE = 0,
+ BIT_1 = 1,
+ BIT_2 = 2,
+ BIT_4 = 3,
+ BIT_8 = 4,
+ BIT_16 = 5
+ }
+
+ internal enum OptionsBits
+ {
+ NONE = 0,
+ DIRECT = (1 << 0),
+ CLIENT_SIDE_ROTATION = (1 << 1),
+ THREAD = (1 << 2)
+ }
+
+ internal enum MultisampleBits
+ {
+ NONE = 0,
+ LOW = 1,
+ MED = 2,
+ HIGH = 3
+ }
+
+ internal enum ContextVersion
+ {
+ GLES_1_X = 1,
+ GLES_2_X = 2,
+ GLES_3_X = 3,
+ DEBUG = 0x1000
+ }
+
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_object_image_add(IntPtr obj);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_object_image_filled_add(IntPtr obj);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_size_get(IntPtr obj, IntPtr x, out int y);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_size_get(IntPtr obj, out int x, IntPtr y);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_size_get(IntPtr obj, out int x, out int y);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_size_set(IntPtr obj, int w, int h);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern IntPtr evas_object_image_data_get(IntPtr obj, bool for_writing);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_data_set(IntPtr obj, IntPtr data);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_data_update_add(IntPtr obj, int x, int y, int w, int h);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_colorspace_set(IntPtr obj, Colorspace cspace);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_fill_set(IntPtr obj, int x, int y, int w, int h);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_native_surface_set(IntPtr obj, ref NativeSurfaceOpenGL surf);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_native_surface_set(IntPtr obj, IntPtr zero);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_pixels_dirty_set(IntPtr obj, bool dirty);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_pixels_get_callback_set(IntPtr obj, ImagePixelsSetCallback func, IntPtr data);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_pixels_get_callback_set(IntPtr obj, IntPtr zero, IntPtr data);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_smooth_scale_set(IntPtr obj, bool smooth_scale);
+
+ [DllImport(Libraries.Evas)]
+ internal static extern void evas_object_image_alpha_set(IntPtr obj, bool has_alpha);
+
+ public delegate void ImagePixelsSetCallback(IntPtr data, IntPtr o);
+
+ internal enum Colorspace
+ {
+ ARGB8888,
+ YCBCR422P601_PL,
+ YCBCR422P709_PL,
+ RGB565_A5P,
+ GRY8 = 4,
+ YCBCR422601_PL,
+ YCBCR420NV12601_PL,
+ YCBCR420TM12601_PL,
+ AGRY88 = 8,
+ ETC1 = 9,
+ RGB8_ETC2 = 10,
+ RGBA8_ETC2_EAC = 11,
+ ETC1_ALPHA = 12,
+ RGB_S3TC_DXT1 = 13,
+ RGBA_S3TC_DXT1 = 14,
+ RGBA_S3TC_DXT2 = 15,
+ RGBA_S3TC_DXT3 = 16,
+ RGBA_S3TC_DXT4 = 17,
+ RGBA_S3TC_DXT5 = 18,
+ }
+ }
+}
--- /dev/null
+
+namespace SkiaSharp.Views.Tizen.Interop
+{
+ internal static class Libraries
+ {
+ internal const string Libc = "libc.so.6";
+ internal const string Evas = "libevas.so.1";
+ internal const string Elementary = "libelementary.so.1";
+ internal const string Eina = "libeina.so.1";
+ internal const string Ecore = "libecore.so.1";
+ internal const string Eo = "libeo.so.1";
+ internal const string Eext = "libefl-extension.so.0";
+ }
+}
--- /dev/null
+namespace SkiaSharp.Views.Tizen
+{
+ public enum RenderingMode
+ {
+ Continuously,
+ WhenDirty,
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+using SkiaSharp.Views.Tizen.Interop;
+
+namespace SkiaSharp.Views.Tizen
+{
+ public class SKCanvasView : CustomRenderingView
+ {
+ private bool ignorePixelScaling;
+ private SKImageInfo info;
+
+ public SKCanvasView(EvasObject parent)
+ : base(parent)
+ {
+ info = new SKImageInfo(0, 0, SKImageInfo.PlatformColorType, SKAlphaType.Premul);
+ }
+
+ public bool IgnorePixelScaling
+ {
+ get { return ignorePixelScaling; }
+ set
+ {
+ if (ignorePixelScaling != value)
+ {
+ ignorePixelScaling = value;
+ OnResized();
+ }
+ }
+ }
+
+ public event EventHandler<SKPaintSurfaceEventArgs> PaintSurface;
+
+ protected override SKSizeI GetSurfaceSize() => info.Size;
+
+ protected virtual void OnDrawFrame(SKPaintSurfaceEventArgs e)
+ {
+ PaintSurface?.Invoke(this, e);
+ }
+
+ protected sealed override void OnDrawFrame()
+ {
+ if (info.Width == 0 || info.Height == 0)
+ return;
+
+ // draw directly into the EFL image data
+ using (var surface = SKSurface.Create(info, Evas.evas_object_image_data_get(evasImage, true), info.RowBytes))
+ {
+ // draw using SkiaSharp
+ OnDrawFrame(new SKPaintSurfaceEventArgs(surface, info));
+ surface.Canvas.Flush();
+ }
+ }
+
+ protected sealed override bool UpdateSurfaceSize(Rect geometry)
+ {
+ var w = info.Width;
+ var h = info.Height;
+
+ if (IgnorePixelScaling)
+ {
+ info.Width = (int)ScalingInfo.FromPixel(geometry.Width);
+ info.Height = (int)ScalingInfo.FromPixel(geometry.Height);
+ }
+ else
+ {
+ info.Width = geometry.Width;
+ info.Height = geometry.Height;
+ }
+
+ return (w != info.Width || h != info.Height);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using ElmSharp;
+using SkiaSharp.Views.GlesInterop;
+using SkiaSharp.Views.Tizen.Interop;
+
+namespace SkiaSharp.Views.Tizen
+{
+ public class SKGLSurfaceView : CustomRenderingView
+ {
+ private const GRSurfaceOrigin surfaceOrigin = GRSurfaceOrigin.BottomLeft;
+ private static readonly SKColorType colorType = SKImageInfo.PlatformColorType;
+
+ private readonly Evas.Config glConfig;
+
+ private IntPtr glConfigPtr;
+ private IntPtr glEvas;
+ private IntPtr glContext;
+ private IntPtr glSurface;
+
+ private GRContext context;
+ private GRGlFramebufferInfo glInfo;
+ private GRBackendRenderTarget renderTarget;
+ private SKSurface surface;
+ private SKCanvas canvas;
+ private SKSizeI surfaceSize;
+
+ public SKGLSurfaceView(EvasObject parent)
+ : base(parent)
+ {
+ glConfig = new Evas.Config
+ {
+ color_format = Evas.ColorFormat.RGBA_8888,
+ depth_bits = Evas.DepthBits.BIT_24,
+ stencil_bits = Evas.StencilBits.BIT_8,
+ options_bits = Evas.OptionsBits.NONE,
+ multisample_bits = Evas.MultisampleBits.HIGH,
+ gles_version = default(int)
+ };
+ }
+
+ public event EventHandler<SKPaintGLSurfaceEventArgs> PaintSurface;
+
+ public GRContext GRContext => context;
+
+ protected override SKSizeI GetSurfaceSize() => surfaceSize;
+
+ protected virtual void OnDrawFrame(SKPaintGLSurfaceEventArgs e)
+ {
+ PaintSurface?.Invoke(this, e);
+ }
+
+ protected sealed override void CreateNativeResources(EvasObject parent)
+ {
+ if (glEvas == IntPtr.Zero)
+ {
+ // initialize the OpenGL (the EFL way)
+ glEvas = Evas.evas_gl_new(Evas.evas_object_evas_get(parent));
+
+ // copy the configuration to the native side
+ glConfigPtr = Marshal.AllocHGlobal(Marshal.SizeOf(glConfig));
+ Marshal.StructureToPtr(glConfig, glConfigPtr, false);
+
+ // initialize the context
+ glContext = Evas.evas_gl_context_create(glEvas, IntPtr.Zero);
+ }
+ }
+
+ protected sealed override void DestroyNativeResources()
+ {
+ if (glEvas != IntPtr.Zero)
+ {
+ // destroy the context
+ Evas.evas_gl_context_destroy(glEvas, glContext);
+ glContext = IntPtr.Zero;
+
+ // release the unmanaged memory
+ Marshal.FreeHGlobal(glConfigPtr);
+ glConfigPtr = IntPtr.Zero;
+
+ // destroy the EFL wrapper
+ Evas.evas_gl_free(glEvas);
+ glEvas = IntPtr.Zero;
+ }
+ }
+
+ protected sealed override void OnDrawFrame()
+ {
+ if (glSurface != IntPtr.Zero)
+ {
+ Gles.glClear(Gles.GL_COLOR_BUFFER_BIT | Gles.GL_DEPTH_BUFFER_BIT | Gles.GL_STENCIL_BUFFER_BIT);
+
+ if (surface != null && renderTarget != null && context != null)
+ {
+ using (new SKAutoCanvasRestore(canvas, true))
+ {
+ // draw using SkiaSharp
+ OnDrawFrame(new SKPaintGLSurfaceEventArgs(surface, renderTarget, surfaceOrigin, colorType, glInfo));
+ }
+
+ // flush the SkiaSharp contents to GL
+ canvas.Flush();
+ context.Flush();
+ }
+ }
+ }
+
+ protected sealed override bool UpdateSurfaceSize(Rect geometry)
+ {
+ var changed =
+ geometry.Width != surfaceSize.Width ||
+ geometry.Height != surfaceSize.Height;
+
+ if (changed)
+ {
+ // size has changed, update geometry
+ surfaceSize.Width = geometry.Width;
+ surfaceSize.Height = geometry.Height;
+ }
+
+ return changed;
+ }
+
+ protected sealed override void CreateDrawingSurface()
+ {
+ if (glSurface == IntPtr.Zero)
+ {
+ // create the surface
+ glSurface = Evas.evas_gl_surface_create(glEvas, glConfigPtr, surfaceSize.Width, surfaceSize.Height);
+
+ // copy the native surface to the image
+ Evas.evas_gl_native_surface_get(glEvas, glSurface, out var nativeSurface);
+ Evas.evas_object_image_native_surface_set(evasImage, ref nativeSurface);
+
+ // switch to the current OpenGL context
+ Evas.evas_gl_make_current(glEvas, glSurface, glContext);
+
+ // resize the viewport
+ Gles.glViewport(0, 0, surfaceSize.Width, surfaceSize.Height);
+
+ // create the interface using the function pointers provided by the EFL
+ var glInterface = GRGlInterface.CreateNativeEvasInterface(glEvas);
+ context?.Dispose();
+ context = GRContext.Create(GRBackend.OpenGL, glInterface);
+
+ // create the render target
+ renderTarget?.Dispose();
+ Gles.glGetIntegerv(Gles.GL_FRAMEBUFFER_BINDING, out var framebuffer);
+ Gles.glGetIntegerv(Gles.GL_STENCIL_BITS, out var stencil);
+ Gles.glGetIntegerv(Gles.GL_SAMPLES, out var samples);
+ var maxSamples = context.GetMaxSurfaceSampleCount(colorType);
+ if (samples > maxSamples)
+ samples = maxSamples;
+ glInfo = new GRGlFramebufferInfo((uint)framebuffer, colorType.ToGlSizedFormat());
+ renderTarget = new GRBackendRenderTarget(surfaceSize.Width, surfaceSize.Height, samples, stencil, glInfo);
+
+ // create the surface
+ surface?.Dispose();
+ surface = SKSurface.Create(context, renderTarget, surfaceOrigin, colorType);
+ canvas = surface.Canvas;
+ }
+ }
+
+ protected sealed override void DestroyDrawingSurface()
+ {
+ if (glSurface != IntPtr.Zero)
+ {
+ // dispose the unmanaged memory
+ canvas = null;
+ surface?.Dispose();
+ surface = null;
+ renderTarget?.Dispose();
+ renderTarget = null;
+ context?.Dispose();
+ context = null;
+
+ // disconnect the surface from the image
+ Evas.evas_object_image_native_surface_set(evasImage, IntPtr.Zero);
+
+ // destroy the surface
+ Evas.evas_gl_surface_destroy(glEvas, glSurface);
+ glSurface = IntPtr.Zero;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp.Views.Tizen
+{
+ public class SKPaintGLSurfaceEventArgs : EventArgs
+ {
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete]
+ private GRBackendRenderTargetDesc? rtDesc;
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete("Use SKPaintGLSurfaceEventArgs(SKSurface, GRBackendRenderTarget, SKColorType, GRSurfaceOrigin) instead.")]
+ public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTargetDesc renderTarget)
+ {
+ Surface = surface;
+ rtDesc = renderTarget;
+ BackendRenderTarget = new GRBackendRenderTarget(GRBackend.OpenGL, renderTarget);
+ ColorType = renderTarget.Config.ToColorType();
+ Origin = renderTarget.Origin;
+ }
+
+ public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget)
+ : this(surface, renderTarget, GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888)
+ {
+ }
+
+ public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType)
+ {
+ Surface = surface;
+ BackendRenderTarget = renderTarget;
+ ColorType = colorType;
+ Origin = origin;
+ }
+
+ public SKPaintGLSurfaceEventArgs(SKSurface surface, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType, GRGlFramebufferInfo glInfo)
+ {
+ Surface = surface;
+ BackendRenderTarget = renderTarget;
+ ColorType = colorType;
+ Origin = origin;
+#pragma warning disable CS0612 // Type or member is obsolete
+ rtDesc = CreateDesc(glInfo);
+#pragma warning restore CS0612 // Type or member is obsolete
+ }
+
+ public SKSurface Surface { get; private set; }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete("Use BackendRenderTarget instead.")]
+ public GRBackendRenderTargetDesc RenderTarget => rtDesc ??= CreateDesc(BackendRenderTarget.GetGlFramebufferInfo());
+
+ [Obsolete]
+ private GRBackendRenderTargetDesc CreateDesc(GRGlFramebufferInfo glInfo) =>
+ new GRBackendRenderTargetDesc
+ {
+ Width = BackendRenderTarget.Width,
+ Height = BackendRenderTarget.Height,
+ RenderTargetHandle = (IntPtr)glInfo.FramebufferObjectId,
+ SampleCount = BackendRenderTarget.SampleCount,
+ StencilBits = BackendRenderTarget.StencilBits,
+ Config = ColorType.ToPixelConfig(),
+ Origin = Origin,
+ };
+
+ public GRBackendRenderTarget BackendRenderTarget { get; private set; }
+
+ public SKColorType ColorType { get; private set; }
+
+ public GRSurfaceOrigin Origin { get; private set; }
+ }
+}
\ No newline at end of file
--- /dev/null
+using System;
+
+namespace SkiaSharp.Views.Tizen
+{
+ public class SKPaintSurfaceEventArgs : EventArgs
+ {
+ public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info)
+ {
+ Surface = surface;
+ Info = info;
+ }
+
+ public SKSurface Surface { get; private set; }
+
+ public SKImageInfo Info { get; private set; }
+ }
+}
--- /dev/null
+using System;
+using ElmSharp;
+using Tizen.System;
+
+namespace SkiaSharp.Views.Tizen
+{
+ public static class ScalingInfo
+ {
+ private static readonly Lazy<string> profile = new Lazy<string>(() => Elementary.GetProfile());
+
+ private static readonly Lazy<int> dpi = new Lazy<int>(() =>
+ {
+ // TV has fixed DPI value (72)
+ if (Profile == "tv")
+ return 72;
+
+#pragma warning disable CS0618 // Type or member is obsolete
+ SystemInfo.TryGetValue("http://tizen.org/feature/screen.dpi", out int dpi);
+#pragma warning restore CS0618 // Type or member is obsolete
+ return dpi;
+ });
+
+ // allows to convert pixels to Android-style device-independent pixels
+ private static readonly Lazy<double> scalingFactor = new Lazy<double>(() => dpi.Value / 160.0);
+
+ public static string Profile => profile.Value;
+
+ public static int Dpi => dpi.Value;
+
+ public static double ScalingFactor => scalingFactor.Value;
+
+ public static double FromPixel(double v) => v / ScalingFactor;
+
+ public static double ToPixel(double v) => v * ScalingFactor;
+ }
+}
--- /dev/null
+using ElmSharp;
+
+namespace SkiaSharp.Views.Tizen
+{
+ public static class TizenExtensions
+ {
+ // Point
+
+ public static SKPoint ToSKPoint(this Point point)
+ {
+ return new SKPoint(point.X, point.Y);
+ }
+
+ public static SKPointI ToSKPointI(this Point point)
+ {
+ return new SKPointI(point.X, point.Y);
+ }
+
+ public static Point ToPoint(this SKPoint point)
+ {
+ return new Point { X = (int)point.X, Y = (int)point.Y };
+ }
+
+ public static Point ToPoint(this SKPointI point)
+ {
+ return new Point { X = point.X, Y = point.Y };
+ }
+
+ // Size
+
+ public static SKSize ToSKSize(this Size size)
+ {
+ return new SKSize(size.Width, size.Height);
+ }
+
+ public static SKSizeI ToSKSizeI(this Size size)
+ {
+ return new SKSizeI(size.Width, size.Height);
+ }
+
+ public static Size ToSize(this SKSize size)
+ {
+ return new Size((int)size.Width, (int)size.Height);
+ }
+
+ public static Size ToSize(this SKSizeI size)
+ {
+ return new Size(size.Width, size.Height);
+ }
+
+ // Rectangle
+
+ public static SKRect ToSKRect(this Rect rect)
+ {
+ return new SKRect(rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+
+ public static SKRectI ToSKRectI(this Rect rect)
+ {
+ return new SKRectI(rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+
+ public static Rect ToRect(this SKRect rect)
+ {
+ return new Rect((int)rect.Left, (int)rect.Top, (int)rect.Right, (int)rect.Bottom);
+ }
+
+ public static Rect ToRect(this SKRectI rect)
+ {
+ return new Rect(rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+
+ // Color
+
+ public static SKColor ToSKColor(this Color color)
+ {
+ return new SKColor((byte)color.R, (byte)color.G, (byte)color.B, (byte)color.A);
+ }
+
+ public static Color ToColor(this SKColor color)
+ {
+ return Color.FromRgba(color.Red, color.Green, color.Blue, color.Alpha);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use SKEncodedOrigin instead.")]
+ public enum SKCodecOrigin
+ {
+ TopLeft = 1,
+ TopRight = 2,
+ BottomRight = 3,
+ BottomLeft = 4,
+ LeftTop = 5,
+ RightTop = 6,
+ RightBottom = 7,
+ LeftBottom = 8,
+ }
+
+ public enum SKFontStyleWeight
+ {
+ Invisible = 0,
+ Thin = 100,
+ ExtraLight = 200,
+ Light = 300,
+ Normal = 400,
+ Medium = 500,
+ SemiBold = 600,
+ Bold = 700,
+ ExtraBold = 800,
+ Black = 900,
+ ExtraBlack = 1000,
+ }
+
+ public enum SKFontStyleWidth
+ {
+ UltraCondensed = 1,
+ ExtraCondensed = 2,
+ Condensed = 3,
+ SemiCondensed = 4,
+ Normal = 5,
+ SemiExpanded = 6,
+ Expanded = 7,
+ ExtraExpanded = 8,
+ UltraExpanded = 9,
+ }
+
+ public static partial class SkiaExtensions
+ {
+ public static bool IsBgr (this SKPixelGeometry pg) =>
+ pg == SKPixelGeometry.BgrHorizontal || pg == SKPixelGeometry.BgrVertical;
+
+ public static bool IsRgb (this SKPixelGeometry pg) =>
+ pg == SKPixelGeometry.RgbHorizontal || pg == SKPixelGeometry.RgbVertical;
+
+ public static bool IsVertical (this SKPixelGeometry pg) =>
+ pg == SKPixelGeometry.BgrVertical || pg == SKPixelGeometry.RgbVertical;
+
+ public static bool IsHorizontal (this SKPixelGeometry pg) =>
+ pg == SKPixelGeometry.BgrHorizontal || pg == SKPixelGeometry.RgbHorizontal;
+
+ public static SKTextEncoding ToTextEncoding (this SKEncoding encoding) =>
+ encoding switch
+ {
+ SKEncoding.Utf8 => SKTextEncoding.Utf8,
+ SKEncoding.Utf16 => SKTextEncoding.Utf16,
+ SKEncoding.Utf32 => SKTextEncoding.Utf32,
+ _ => throw new ArgumentOutOfRangeException (nameof (encoding)),
+ };
+
+ internal static SKEncoding ToEncoding (this SKTextEncoding encoding) =>
+ encoding switch
+ {
+ SKTextEncoding.Utf8 => SKEncoding.Utf8,
+ SKTextEncoding.Utf16 => SKEncoding.Utf16,
+ SKTextEncoding.Utf32 => SKEncoding.Utf32,
+ _ => throw new ArgumentOutOfRangeException (nameof (encoding)),
+ };
+
+ public static int GetBytesPerPixel (this SKColorType colorType) =>
+ colorType switch
+ {
+ SKColorType.Unknown => 0,
+ SKColorType.Alpha8 => 1,
+ SKColorType.Gray8 => 1,
+ SKColorType.Rgb565 => 2,
+ SKColorType.Argb4444 => 2,
+ SKColorType.Bgra8888 => 4,
+ SKColorType.Rgba8888 => 4,
+ SKColorType.Rgb888x => 4,
+ SKColorType.Rgba1010102 => 4,
+ SKColorType.Rgb101010x => 4,
+ SKColorType.RgbaF16 => 8,
+ _ => throw new ArgumentOutOfRangeException (nameof (colorType)),
+ };
+
+ public static SKAlphaType GetAlphaType (this SKColorType colorType, SKAlphaType alphaType = SKAlphaType.Premul) =>
+ colorType switch
+ {
+ SKColorType.Unknown => SKAlphaType.Unknown,
+ SKColorType.Alpha8 => SKAlphaType.Premul,
+ SKColorType.Gray8 => SKAlphaType.Opaque,
+ SKColorType.Rgb565 => SKAlphaType.Opaque,
+ SKColorType.Argb4444 => alphaType,
+ SKColorType.Bgra8888 => alphaType,
+ SKColorType.Rgba8888 => alphaType,
+ SKColorType.Rgb888x => SKAlphaType.Opaque,
+ SKColorType.Rgba1010102 => alphaType,
+ SKColorType.Rgb101010x => SKAlphaType.Opaque,
+ SKColorType.RgbaF16 => alphaType,
+ _ => throw new ArgumentOutOfRangeException (nameof (colorType)),
+ };
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use SKSurfaceProperties instead.")]
+ public struct SKSurfaceProps : IEquatable<SKSurfaceProps>
+ {
+ public SKPixelGeometry PixelGeometry { get; set; }
+ public SKSurfacePropsFlags Flags { get; set; }
+
+ public readonly bool Equals (SKSurfaceProps obj) =>
+ PixelGeometry == obj.PixelGeometry &&
+ Flags == obj.Flags;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKSurfaceProps f && Equals (f);
+
+ public static bool operator == (SKSurfaceProps left, SKSurfaceProps right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKSurfaceProps left, SKSurfaceProps right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (PixelGeometry);
+ hash.Add (Flags);
+ return hash.ToHashCode ();
+ }
+ }
+
+ public struct SKCodecOptions : IEquatable<SKCodecOptions>
+ {
+ public static readonly SKCodecOptions Default;
+
+ static SKCodecOptions ()
+ {
+ Default = new SKCodecOptions (SKZeroInitialized.No);
+ }
+
+ public SKCodecOptions (SKZeroInitialized zeroInitialized)
+ {
+ ZeroInitialized = zeroInitialized;
+ Subset = null;
+ FrameIndex = 0;
+ PriorFrame = -1;
+ PremulBehavior = SKTransferFunctionBehavior.Respect;
+ }
+ public SKCodecOptions (SKZeroInitialized zeroInitialized, SKRectI subset)
+ {
+ ZeroInitialized = zeroInitialized;
+ Subset = subset;
+ FrameIndex = 0;
+ PriorFrame = -1;
+ PremulBehavior = SKTransferFunctionBehavior.Respect;
+ }
+ public SKCodecOptions (SKRectI subset)
+ {
+ ZeroInitialized = SKZeroInitialized.No;
+ Subset = subset;
+ FrameIndex = 0;
+ PriorFrame = -1;
+ PremulBehavior = SKTransferFunctionBehavior.Respect;
+ }
+ public SKCodecOptions (int frameIndex)
+ {
+ ZeroInitialized = SKZeroInitialized.No;
+ Subset = null;
+ FrameIndex = frameIndex;
+ PriorFrame = -1;
+ PremulBehavior = SKTransferFunctionBehavior.Respect;
+ }
+ public SKCodecOptions (int frameIndex, int priorFrame)
+ {
+ ZeroInitialized = SKZeroInitialized.No;
+ Subset = null;
+ FrameIndex = frameIndex;
+ PriorFrame = priorFrame;
+ PremulBehavior = SKTransferFunctionBehavior.Respect;
+ }
+
+ public SKZeroInitialized ZeroInitialized { get; set; }
+ public SKRectI? Subset { get; set; }
+ public readonly bool HasSubset => Subset != null;
+ public int FrameIndex { get; set; }
+ public int PriorFrame { get; set; }
+ public SKTransferFunctionBehavior PremulBehavior { get; set; }
+
+ public readonly bool Equals (SKCodecOptions obj) =>
+ ZeroInitialized == obj.ZeroInitialized &&
+ Subset == obj.Subset &&
+ FrameIndex == obj.FrameIndex &&
+ PriorFrame == obj.PriorFrame &&
+ PremulBehavior == obj.PremulBehavior;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKCodecOptions f && Equals (f);
+
+ public static bool operator == (SKCodecOptions left, SKCodecOptions right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKCodecOptions left, SKCodecOptions right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (ZeroInitialized);
+ hash.Add (Subset);
+ hash.Add (FrameIndex);
+ hash.Add (PriorFrame);
+ hash.Add (PremulBehavior);
+ return hash.ToHashCode ();
+ }
+ }
+
+ public partial struct SKFontMetrics
+ {
+ private const uint flagsUnderlineThicknessIsValid = (1U << 0);
+ private const uint flagsUnderlinePositionIsValid = (1U << 1);
+ private const uint flagsStrikeoutThicknessIsValid = (1U << 2);
+ private const uint flagsStrikeoutPositionIsValid = (1U << 3);
+
+ public readonly float Top => fTop;
+
+ public readonly float Ascent => fAscent;
+
+ public readonly float Descent => fDescent;
+
+ public readonly float Bottom => fBottom;
+
+ public readonly float Leading => fLeading;
+
+ public readonly float AverageCharacterWidth => fAvgCharWidth;
+
+ public readonly float MaxCharacterWidth => fMaxCharWidth;
+
+ public readonly float XMin => fXMin;
+
+ public readonly float XMax => fXMax;
+
+ public readonly float XHeight => fXHeight;
+
+ public readonly float CapHeight => fCapHeight;
+
+ public readonly float? UnderlineThickness => GetIfValid (fUnderlineThickness, flagsUnderlineThicknessIsValid);
+ public readonly float? UnderlinePosition => GetIfValid (fUnderlinePosition, flagsUnderlinePositionIsValid);
+ public readonly float? StrikeoutThickness => GetIfValid (fStrikeoutThickness, flagsStrikeoutThicknessIsValid);
+ public readonly float? StrikeoutPosition => GetIfValid (fStrikeoutPosition, flagsStrikeoutPositionIsValid);
+
+ private readonly float? GetIfValid (float value, uint flag) =>
+ (fFlags & flag) == flag ? value : (float?)null;
+ }
+
+ public struct SKLattice : IEquatable<SKLattice>
+ {
+ public int[] XDivs { get; set; }
+ public int[] YDivs { get; set; }
+ public SKLatticeRectType[] RectTypes { get; set; }
+ public SKRectI? Bounds { get; set; }
+ public SKColor[] Colors { get; set; }
+
+ public readonly bool Equals (SKLattice obj) =>
+ XDivs == obj.XDivs &&
+ YDivs == obj.YDivs &&
+ RectTypes == obj.RectTypes &&
+ Bounds == obj.Bounds &&
+ Colors == obj.Colors;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKLattice f && Equals (f);
+
+ public static bool operator == (SKLattice left, SKLattice right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKLattice left, SKLattice right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (XDivs);
+ hash.Add (YDivs);
+ hash.Add (RectTypes);
+ hash.Add (Bounds);
+ hash.Add (Colors);
+ return hash.ToHashCode ();
+ }
+ }
+
+ internal partial struct SKTimeDateTimeInternal
+ {
+ public static SKTimeDateTimeInternal Create (DateTime datetime)
+ {
+ var zone = datetime.Hour - datetime.ToUniversalTime ().Hour;
+ return new SKTimeDateTimeInternal {
+ fTimeZoneMinutes = (Int16)(zone * 60),
+ fYear = (UInt16)datetime.Year,
+ fMonth = (Byte)datetime.Month,
+ fDayOfWeek = (Byte)datetime.DayOfWeek,
+ fDay = (Byte)datetime.Day,
+ fHour = (Byte)datetime.Hour,
+ fMinute = (Byte)datetime.Minute,
+ fSecond = (Byte)datetime.Second
+ };
+ }
+ }
+
+ public struct SKDocumentPdfMetadata : IEquatable<SKDocumentPdfMetadata>
+ {
+ public const float DefaultRasterDpi = SKDocument.DefaultRasterDpi;
+ public const int DefaultEncodingQuality = 101;
+
+ public static readonly SKDocumentPdfMetadata Default;
+
+ static SKDocumentPdfMetadata ()
+ {
+ Default = new SKDocumentPdfMetadata () {
+ RasterDpi = DefaultRasterDpi,
+ PdfA = false,
+ EncodingQuality = 101,
+ };
+ }
+
+ public SKDocumentPdfMetadata (float rasterDpi)
+ {
+ Title = null;
+ Author = null;
+ Subject = null;
+ Keywords = null;
+ Creator = null;
+ Producer = null;
+ Creation = null;
+ Modified = null;
+ RasterDpi = rasterDpi;
+ PdfA = false;
+ EncodingQuality = DefaultEncodingQuality;
+ }
+
+ public SKDocumentPdfMetadata (int encodingQuality)
+ {
+ Title = null;
+ Author = null;
+ Subject = null;
+ Keywords = null;
+ Creator = null;
+ Producer = null;
+ Creation = null;
+ Modified = null;
+ RasterDpi = DefaultRasterDpi;
+ PdfA = false;
+ EncodingQuality = encodingQuality;
+ }
+
+ public SKDocumentPdfMetadata (float rasterDpi, int encodingQuality)
+ {
+ Title = null;
+ Author = null;
+ Subject = null;
+ Keywords = null;
+ Creator = null;
+ Producer = null;
+ Creation = null;
+ Modified = null;
+ RasterDpi = rasterDpi;
+ PdfA = false;
+ EncodingQuality = encodingQuality;
+ }
+
+ public string Title { get; set; }
+ public string Author { get; set; }
+ public string Subject { get; set; }
+ public string Keywords { get; set; }
+ public string Creator { get; set; }
+ public string Producer { get; set; }
+ public DateTime? Creation { get; set; }
+ public DateTime? Modified { get; set; }
+ public float RasterDpi { get; set; }
+ public bool PdfA { get; set; }
+ public int EncodingQuality { get; set; }
+
+ public readonly bool Equals (SKDocumentPdfMetadata obj) =>
+ Title == obj.Title &&
+ Author == obj.Author &&
+ Subject == obj.Subject &&
+ Keywords == obj.Keywords &&
+ Creator == obj.Creator &&
+ Producer == obj.Producer &&
+ Creation == obj.Creation &&
+ Modified == obj.Modified &&
+ RasterDpi == obj.RasterDpi &&
+ PdfA == obj.PdfA &&
+ EncodingQuality == obj.EncodingQuality;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKDocumentPdfMetadata f && Equals (f);
+
+ public static bool operator == (SKDocumentPdfMetadata left, SKDocumentPdfMetadata right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKDocumentPdfMetadata left, SKDocumentPdfMetadata right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (Title);
+ hash.Add (Author);
+ hash.Add (Subject);
+ hash.Add (Keywords);
+ hash.Add (Creator);
+ hash.Add (Producer);
+ hash.Add (Creation);
+ hash.Add (Modified);
+ hash.Add (RasterDpi);
+ hash.Add (PdfA);
+ hash.Add (EncodingQuality);
+ return hash.ToHashCode ();
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ [Flags]
+ public enum SKColorSpaceFlags
+ {
+ None = 0,
+ NonLinearBlending = 0x1,
+ }
+
+ public partial struct SKHighContrastConfig
+ {
+ public static readonly SKHighContrastConfig Default;
+
+ static SKHighContrastConfig ()
+ {
+ Default = new SKHighContrastConfig (false, SKHighContrastConfigInvertStyle.NoInvert, 0.0f);
+ }
+
+ public SKHighContrastConfig (bool grayscale, SKHighContrastConfigInvertStyle invertStyle, float contrast)
+ {
+ fGrayscale = grayscale ? (byte)1 : (byte)0;
+ fInvertStyle = invertStyle;
+ fContrast = contrast;
+ }
+
+ public readonly bool IsValid =>
+ (int)fInvertStyle >= (int)SKHighContrastConfigInvertStyle.NoInvert &&
+ (int)fInvertStyle <= (int)SKHighContrastConfigInvertStyle.InvertLightness &&
+ fContrast >= -1.0 &&
+ fContrast <= 1.0;
+ }
+
+ public unsafe partial struct SKPngEncoderOptions
+ {
+ public static readonly SKPngEncoderOptions Default;
+
+ static SKPngEncoderOptions ()
+ {
+ Default = new SKPngEncoderOptions (SKPngEncoderFilterFlags.AllFilters, 6, SKTransferFunctionBehavior.Respect);
+ }
+
+ public SKPngEncoderOptions (SKPngEncoderFilterFlags filterFlags, int zLibLevel)
+ {
+ fFilterFlags = filterFlags;
+ fZLibLevel = zLibLevel;
+ fUnpremulBehavior = SKTransferFunctionBehavior.Respect;
+ fComments = null;
+ }
+
+ public SKPngEncoderOptions (SKPngEncoderFilterFlags filterFlags, int zLibLevel, SKTransferFunctionBehavior unpremulBehavior)
+ {
+ fFilterFlags = filterFlags;
+ fZLibLevel = zLibLevel;
+ fUnpremulBehavior = unpremulBehavior;
+ fComments = null;
+ }
+
+ public SKPngEncoderFilterFlags FilterFlags {
+ readonly get => fFilterFlags;
+ set => fFilterFlags = value;
+ }
+ public int ZLibLevel {
+ readonly get => fZLibLevel;
+ set => fZLibLevel = value;
+ }
+ public SKTransferFunctionBehavior UnpremulBehavior {
+ readonly get => fUnpremulBehavior;
+ set => fUnpremulBehavior = value;
+ }
+ }
+
+ public partial struct SKJpegEncoderOptions
+ {
+ public static readonly SKJpegEncoderOptions Default;
+
+ static SKJpegEncoderOptions ()
+ {
+ Default = new SKJpegEncoderOptions (100, SKJpegEncoderDownsample.Downsample420, SKJpegEncoderAlphaOption.Ignore, SKTransferFunctionBehavior.Respect);
+ }
+
+ public SKJpegEncoderOptions (int quality, SKJpegEncoderDownsample downsample, SKJpegEncoderAlphaOption alphaOption)
+ {
+ fQuality = quality;
+ fDownsample = downsample;
+ fAlphaOption = alphaOption;
+ fBlendBehavior = SKTransferFunctionBehavior.Respect;
+ }
+
+ public SKJpegEncoderOptions (int quality, SKJpegEncoderDownsample downsample, SKJpegEncoderAlphaOption alphaOption, SKTransferFunctionBehavior blendBehavior)
+ {
+ fQuality = quality;
+ fDownsample = downsample;
+ fAlphaOption = alphaOption;
+ fBlendBehavior = blendBehavior;
+ }
+ }
+
+ public partial struct SKWebpEncoderOptions
+ {
+ public static readonly SKWebpEncoderOptions Default;
+
+ static SKWebpEncoderOptions ()
+ {
+ Default = new SKWebpEncoderOptions (SKWebpEncoderCompression.Lossy, 100, SKTransferFunctionBehavior.Respect);
+ }
+
+ public SKWebpEncoderOptions (SKWebpEncoderCompression compression, float quality)
+ {
+ fCompression = compression;
+ fQuality = quality;
+ fUnpremulBehavior = SKTransferFunctionBehavior.Respect;
+ }
+
+ public SKWebpEncoderOptions (SKWebpEncoderCompression compression, float quality, SKTransferFunctionBehavior unpremulBehavior)
+ {
+ fCompression = compression;
+ fQuality = quality;
+ fUnpremulBehavior = unpremulBehavior;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ // public delegates
+
+ public delegate void SKBitmapReleaseDelegate (IntPtr address, object context);
+
+ public delegate void SKDataReleaseDelegate (IntPtr address, object context);
+
+ public delegate void SKImageRasterReleaseDelegate (IntPtr pixels, object context);
+
+ public delegate void SKImageTextureReleaseDelegate (object context);
+
+ public delegate void SKSurfaceReleaseDelegate (IntPtr address, object context);
+
+ public delegate IntPtr GRGlGetProcDelegate (object context, string name);
+
+ internal unsafe static partial class DelegateProxies
+ {
+ // references to the proxy implementations
+ public static readonly SKBitmapReleaseProxyDelegate SKBitmapReleaseDelegateProxy = SKBitmapReleaseDelegateProxyImplementation;
+ public static readonly SKDataReleaseProxyDelegate SKDataReleaseDelegateProxy = SKDataReleaseDelegateProxyImplementation;
+ public static readonly SKImageRasterReleaseProxyDelegate SKImageRasterReleaseDelegateProxy = SKImageRasterReleaseDelegateProxyImplementation;
+ public static readonly SKImageRasterReleaseProxyDelegate SKImageRasterReleaseDelegateProxyForCoTaskMem = SKImageRasterReleaseDelegateProxyImplementationForCoTaskMem;
+ public static readonly SKImageTextureReleaseProxyDelegate SKImageTextureReleaseDelegateProxy = SKImageTextureReleaseDelegateProxyImplementation;
+ public static readonly SKSurfaceRasterReleaseProxyDelegate SKSurfaceReleaseDelegateProxy = SKSurfaceReleaseDelegateProxyImplementation;
+ public static readonly GRGlGetProcProxyDelegate GRGlGetProcDelegateProxy = GRGlGetProcDelegateProxyImplementation;
+
+ // internal proxy implementations
+
+ [MonoPInvokeCallback (typeof (SKBitmapReleaseProxyDelegate))]
+ private static void SKBitmapReleaseDelegateProxyImplementation (void* address, void* context)
+ {
+ var del = Get<SKBitmapReleaseDelegate> ((IntPtr)context, out var gch);
+ try {
+ del.Invoke ((IntPtr)address, null);
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ [MonoPInvokeCallback (typeof (SKDataReleaseProxyDelegate))]
+ private static void SKDataReleaseDelegateProxyImplementation (void* address, void* context)
+ {
+ var del = Get<SKDataReleaseDelegate> ((IntPtr)context, out var gch);
+ try {
+ del.Invoke ((IntPtr)address, null);
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ [MonoPInvokeCallback (typeof (SKImageRasterReleaseProxyDelegate))]
+ private static void SKImageRasterReleaseDelegateProxyImplementationForCoTaskMem (void* pixels, void* context)
+ {
+ Marshal.FreeCoTaskMem ((IntPtr)pixels);
+ }
+
+ [MonoPInvokeCallback (typeof (SKImageRasterReleaseProxyDelegate))]
+ private static void SKImageRasterReleaseDelegateProxyImplementation (void* pixels, void* context)
+ {
+ var del = Get<SKImageRasterReleaseDelegate> ((IntPtr)context, out var gch);
+ try {
+ del.Invoke ((IntPtr)pixels, null);
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ [MonoPInvokeCallback (typeof (SKImageTextureReleaseProxyDelegate))]
+ private static void SKImageTextureReleaseDelegateProxyImplementation (void* context)
+ {
+ var del = Get<SKImageTextureReleaseDelegate> ((IntPtr)context, out var gch);
+ try {
+ del.Invoke (null);
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ [MonoPInvokeCallback (typeof (SKSurfaceRasterReleaseProxyDelegate))]
+ private static void SKSurfaceReleaseDelegateProxyImplementation (void* address, void* context)
+ {
+ var del = Get<SKSurfaceReleaseDelegate> ((IntPtr)context, out var gch);
+ try {
+ del.Invoke ((IntPtr)address, null);
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ [MonoPInvokeCallback (typeof (GRGlGetProcProxyDelegate))]
+ private static IntPtr GRGlGetProcDelegateProxyImplementation (void* context, string name)
+ {
+ var del = Get<GRGlGetProcDelegate> ((IntPtr)context, out _);
+ return del.Invoke (null, name);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Concurrent;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+#if THROW_OBJECT_EXCEPTIONS
+ using GCHandle = GCHandleProxy;
+#endif
+
+ // helper delegates
+
+ internal delegate Delegate GetMultiDelegateDelegate (Type index);
+
+ internal delegate object UserDataDelegate ();
+
+ internal static partial class DelegateProxies
+ {
+ // normal delegates
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static T Create<T> (object managedDel, T nativeDel, out GCHandle gch, out IntPtr contextPtr)
+ {
+ if (managedDel == null) {
+ gch = default (GCHandle);
+ contextPtr = IntPtr.Zero;
+ return default (T);
+ }
+
+ gch = GCHandle.Alloc (managedDel);
+ contextPtr = GCHandle.ToIntPtr (gch);
+ return nativeDel;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void Create (object managedDel, out GCHandle gch, out IntPtr contextPtr)
+ {
+ if (managedDel == null) {
+ gch = default (GCHandle);
+ contextPtr = IntPtr.Zero;
+ return;
+ }
+
+ gch = GCHandle.Alloc (managedDel);
+ contextPtr = GCHandle.ToIntPtr (gch);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static T Get<T> (IntPtr contextPtr, out GCHandle gch)
+ {
+ if (contextPtr == IntPtr.Zero) {
+ gch = default (GCHandle);
+ return default (T);
+ }
+
+ gch = GCHandle.FromIntPtr (contextPtr);
+ return (T)gch.Target;
+ }
+
+ // user data delegates
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateUserData (object userData, bool makeWeak = false)
+ {
+ userData = makeWeak ? new WeakReference (userData) : userData;
+ var del = new UserDataDelegate (() => userData);
+ Create (del, out _, out var ctx);
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static T GetUserData<T> (IntPtr contextPtr, out GCHandle gch)
+ {
+ var del = Get<UserDataDelegate> (contextPtr, out gch);
+ var value = del.Invoke ();
+ return value is WeakReference weak ? (T)weak.Target : (T)value;
+ }
+
+ // multi-value delegates
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMulti<T1, T2> (T1 wrappedDelegate1, T2 wrappedDelegate2)
+ where T1 : Delegate
+ where T2 : Delegate
+ {
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T1))
+ return wrappedDelegate1;
+ if (type == typeof (T2))
+ return wrappedDelegate2;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMulti<T1, T2, T3> (T1 wrappedDelegate1, T2 wrappedDelegate2, T3 wrappedDelegate3)
+ where T1 : Delegate
+ where T2 : Delegate
+ where T3 : Delegate
+ {
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T1))
+ return wrappedDelegate1;
+ if (type == typeof (T2))
+ return wrappedDelegate2;
+ if (type == typeof (T3))
+ return wrappedDelegate3;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static T GetMulti<T> (IntPtr contextPtr, out GCHandle gch)
+ where T : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ return (T)multi.Invoke (typeof (T));
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMulti<T1, T2> (IntPtr contextPtr, out T1 wrappedDelegate1, out T2 wrappedDelegate2, out GCHandle gch)
+ where T1 : Delegate
+ where T2 : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate1 = (T1)multi.Invoke (typeof (T1));
+ wrappedDelegate2 = (T2)multi.Invoke (typeof (T2));
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMulti<T1, T2, T3> (IntPtr contextPtr, out T1 wrappedDelegate1, out T2 wrappedDelegate2, out T3 wrappedDelegate3, out GCHandle gch)
+ where T1 : Delegate
+ where T2 : Delegate
+ where T3 : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate1 = (T1)multi.Invoke (typeof (T1));
+ wrappedDelegate2 = (T2)multi.Invoke (typeof (T2));
+ wrappedDelegate3 = (T3)multi.Invoke (typeof (T3));
+ }
+
+ // multi-value delegate with user data
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMultiUserData<T> (T wrappedDelegate, object userData, bool makeWeak = false)
+ where T : Delegate
+ {
+ userData = makeWeak ? new WeakReference (userData) : userData;
+ var userDataDelegate = new UserDataDelegate (() => userData);
+
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T))
+ return wrappedDelegate;
+ if (type == typeof (UserDataDelegate))
+ return userDataDelegate;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMultiUserData<T1, T2> (T1 wrappedDelegate1, T2 wrappedDelegate2, object userData, bool makeWeak = false)
+ where T1 : Delegate
+ where T2 : Delegate
+ {
+ userData = makeWeak ? new WeakReference (userData) : userData;
+ var userDataDelegate = new UserDataDelegate (() => userData);
+
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T1))
+ return wrappedDelegate1;
+ if (type == typeof (T2))
+ return wrappedDelegate2;
+ if (type == typeof (UserDataDelegate))
+ return userDataDelegate;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static IntPtr CreateMultiUserData<T1, T2, T3> (T1 wrappedDelegate1, T2 wrappedDelegate2, T3 wrappedDelegate3, object userData, bool makeWeak = false)
+ where T1 : Delegate
+ where T2 : Delegate
+ where T3 : Delegate
+ {
+ userData = makeWeak ? new WeakReference (userData) : userData;
+ var userDataDelegate = new UserDataDelegate (() => userData);
+
+ var del = new GetMultiDelegateDelegate ((type) => {
+ if (type == typeof (T1))
+ return wrappedDelegate1;
+ if (type == typeof (T2))
+ return wrappedDelegate2;
+ if (type == typeof (T3))
+ return wrappedDelegate3;
+ if (type == typeof (UserDataDelegate))
+ return userDataDelegate;
+ throw new ArgumentOutOfRangeException (nameof (type));
+ });
+
+ Create (del, out _, out var ctx);
+
+ return ctx;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static TUserData GetMultiUserData<TUserData> (IntPtr contextPtr, out GCHandle gch)
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ return GetUserData<TUserData> (multi);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMultiUserData<T, TUserData> (IntPtr contextPtr, out T wrappedDelegate, out TUserData userData, out GCHandle gch)
+ where T : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate = (T)multi.Invoke (typeof (T));
+ userData = GetUserData<TUserData> (multi);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMultiUserData<T1, T2, TUserData> (IntPtr contextPtr, out T1 wrappedDelegate1, out T2 wrappedDelegate2, out TUserData userData, out GCHandle gch)
+ where T1 : Delegate
+ where T2 : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate1 = (T1)multi.Invoke (typeof (T1));
+ wrappedDelegate2 = (T2)multi.Invoke (typeof (T2));
+ userData = GetUserData<TUserData> (multi);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ public static void GetMultiUserData<T1, T2, T3, TUserData> (IntPtr contextPtr, out T1 wrappedDelegate1, out T2 wrappedDelegate2, out T3 wrappedDelegate3, out TUserData userData, out GCHandle gch)
+ where T1 : Delegate
+ where T2 : Delegate
+ where T3 : Delegate
+ {
+ var multi = Get<GetMultiDelegateDelegate> (contextPtr, out gch);
+ wrappedDelegate1 = (T1)multi.Invoke (typeof (T1));
+ wrappedDelegate2 = (T2)multi.Invoke (typeof (T2));
+ wrappedDelegate3 = (T3)multi.Invoke (typeof (T3));
+ userData = GetUserData<TUserData> (multi);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static TUserData GetUserData<TUserData> (GetMultiDelegateDelegate multi)
+ {
+ var userDataDelegate = (UserDataDelegate)multi.Invoke (typeof (UserDataDelegate));
+ var value = userDataDelegate.Invoke ();
+ return value is WeakReference weak ? (TUserData)weak.Target : (TUserData)value;
+ }
+ }
+
+#if THROW_OBJECT_EXCEPTIONS
+ // an internal, debug-only proxy that we can use to make sure we are not
+ // leaking GC handles by accident
+ internal struct GCHandleProxy
+ {
+ internal static readonly ConcurrentDictionary<IntPtr, WeakReference> allocatedHandles = new ConcurrentDictionary<IntPtr, WeakReference> ();
+
+ private System.Runtime.InteropServices.GCHandle gch;
+
+ public GCHandleProxy (System.Runtime.InteropServices.GCHandle gcHandle)
+ {
+ gch = gcHandle;
+ }
+
+ public bool IsAllocated => gch.IsAllocated;
+
+ public object Target => gch.Target;
+
+ public void Free ()
+ {
+ if (!allocatedHandles.TryRemove (ToIntPtr (this), out _))
+ throw new InvalidOperationException ($"Allocated GC handle has already been freed.");
+
+ gch.Free ();
+ }
+
+ internal static GCHandleProxy Alloc (object value)
+ {
+ var gch = new GCHandleProxy (System.Runtime.InteropServices.GCHandle.Alloc (value));
+
+ var weak = new WeakReference (value);
+ var oldWeak = allocatedHandles.GetOrAdd (ToIntPtr (gch), weak);
+ if (weak != oldWeak)
+ throw new InvalidOperationException (
+ $"GC handle has already been allocated for this memory location. " +
+ $"Old: {oldWeak.Target} New: {value}");
+
+ return gch;
+ }
+
+ internal static GCHandleProxy FromIntPtr (IntPtr value) =>
+ new GCHandleProxy (System.Runtime.InteropServices.GCHandle.FromIntPtr (value));
+
+ internal static IntPtr ToIntPtr (GCHandleProxy value) =>
+ System.Runtime.InteropServices.GCHandle.ToIntPtr (value.gch);
+ }
+#endif
+
+ [AttributeUsage (AttributeTargets.Method)]
+ internal sealed class MonoPInvokeCallbackAttribute : Attribute
+ {
+ public MonoPInvokeCallbackAttribute (Type type)
+ {
+ Type = type;
+ }
+
+ public Type Type { get; private set; }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public unsafe class GRBackendRenderTarget : SKObject
+ {
+ [Preserve]
+ internal GRBackendRenderTarget (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GRBackendRenderTarget(int, int, int, int, GRGlFramebufferInfo) instead.")]
+ public GRBackendRenderTarget (GRBackend backend, GRBackendRenderTargetDesc desc)
+ : this (IntPtr.Zero, true)
+ {
+ switch (backend) {
+ case GRBackend.Metal:
+ throw new NotSupportedException ();
+ case GRBackend.OpenGL:
+ var glInfo = new GRGlFramebufferInfo ((uint)desc.RenderTargetHandle, desc.Config.ToGlSizedFormat ());
+ CreateGl (desc.Width, desc.Height, desc.SampleCount, desc.StencilBits, glInfo);
+ break;
+ case GRBackend.Vulkan:
+ throw new NotSupportedException ();
+ default:
+ throw new ArgumentOutOfRangeException (nameof (backend));
+ }
+ }
+
+ public GRBackendRenderTarget (int width, int height, int sampleCount, int stencilBits, GRGlFramebufferInfo glInfo)
+ : this (IntPtr.Zero, true)
+ {
+ CreateGl (width, height, sampleCount, stencilBits, glInfo);
+ }
+
+ private void CreateGl (int width, int height, int sampleCount, int stencilBits, GRGlFramebufferInfo glInfo)
+ {
+ Handle = SkiaApi.gr_backendrendertarget_new_gl (width, height, sampleCount, stencilBits, &glInfo);
+
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new GRBackendRenderTarget instance.");
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.gr_backendrendertarget_delete (Handle);
+
+ public bool IsValid => SkiaApi.gr_backendrendertarget_is_valid (Handle);
+ public int Width => SkiaApi.gr_backendrendertarget_get_width (Handle);
+ public int Height => SkiaApi.gr_backendrendertarget_get_height (Handle);
+ public int SampleCount => SkiaApi.gr_backendrendertarget_get_samples (Handle);
+ public int StencilBits => SkiaApi.gr_backendrendertarget_get_stencils (Handle);
+ public GRBackend Backend => SkiaApi.gr_backendrendertarget_get_backend (Handle);
+ public SKSizeI Size => new SKSizeI (Width, Height);
+ public SKRectI Rect => new SKRectI (0, 0, Width, Height);
+
+ public GRGlFramebufferInfo GetGlFramebufferInfo () =>
+ GetGlFramebufferInfo (out var info) ? info : default;
+
+ public bool GetGlFramebufferInfo (out GRGlFramebufferInfo glInfo)
+ {
+ fixed (GRGlFramebufferInfo* g = &glInfo) {
+ return SkiaApi.gr_backendrendertarget_get_gl_framebufferinfo (Handle, g);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ public unsafe class GRBackendTexture : SKObject
+ {
+ [Preserve]
+ internal GRBackendTexture (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GRBackendTexture(int, int, bool, GRGlTextureInfo) instead.")]
+ public GRBackendTexture (GRGlBackendTextureDesc desc)
+ : this (IntPtr.Zero, true)
+ {
+ var handle = desc.TextureHandle;
+ if (handle.Format == 0) {
+ handle.Format = desc.Config.ToGlSizedFormat ();
+ }
+ CreateGl (desc.Width, desc.Height, false, handle);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GRBackendTexture(int, int, bool, GRGlTextureInfo) instead.")]
+ public GRBackendTexture (GRBackendTextureDesc desc)
+ : this (IntPtr.Zero, true)
+ {
+ var handlePtr = desc.TextureHandle;
+ var oldHandle = PtrToStructure<GRTextureInfoObsolete> (handlePtr);
+
+ var handle = new GRGlTextureInfo (oldHandle.fTarget, oldHandle.fID, desc.Config.ToGlSizedFormat ());
+ CreateGl (desc.Width, desc.Height, false, handle);
+ }
+
+ public GRBackendTexture (int width, int height, bool mipmapped, GRGlTextureInfo glInfo)
+ : this (IntPtr.Zero, true)
+ {
+ CreateGl (width, height, mipmapped, glInfo);
+ }
+
+ private void CreateGl (int width, int height, bool mipmapped, GRGlTextureInfo glInfo)
+ {
+ Handle = SkiaApi.gr_backendtexture_new_gl (width, height, mipmapped, &glInfo);
+
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new GRBackendTexture instance.");
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.gr_backendtexture_delete (Handle);
+
+ public bool IsValid => SkiaApi.gr_backendtexture_is_valid (Handle);
+ public int Width => SkiaApi.gr_backendtexture_get_width (Handle);
+ public int Height => SkiaApi.gr_backendtexture_get_height (Handle);
+ public bool HasMipMaps => SkiaApi.gr_backendtexture_has_mipmaps (Handle);
+ public GRBackend Backend => SkiaApi.gr_backendtexture_get_backend (Handle);
+ public SKSizeI Size => new SKSizeI (Width, Height);
+ public SKRectI Rect => new SKRectI (0, 0, Width, Height);
+
+ public GRGlTextureInfo GetGlTextureInfo () =>
+ GetGlTextureInfo (out var info) ? info : default;
+
+ public bool GetGlTextureInfo (out GRGlTextureInfo glInfo)
+ {
+ fixed (GRGlTextureInfo* g = &glInfo) {
+ return SkiaApi.gr_backendtexture_get_gl_textureinfo (Handle, g);
+ }
+ }
+
+ [Obsolete]
+ [StructLayout (LayoutKind.Sequential)]
+ internal struct GRTextureInfoObsolete
+ {
+ public uint fTarget;
+ public uint fID;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public unsafe class GRContext : SKObject, ISKReferenceCounted
+ {
+ [Preserve]
+ internal GRContext (IntPtr h, bool owns)
+ : base (h, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ // Create
+
+ public static GRContext Create (GRBackend backend) =>
+ backend switch
+ {
+ GRBackend.Metal => throw new NotSupportedException (),
+ GRBackend.OpenGL => CreateGl (),
+ GRBackend.Vulkan => throw new NotSupportedException (),
+ _ => throw new ArgumentOutOfRangeException (nameof (backend)),
+ };
+
+ public static GRContext Create (GRBackend backend, GRGlInterface backendContext) =>
+ backend switch
+ {
+ GRBackend.Metal => throw new NotSupportedException (),
+ GRBackend.OpenGL => CreateGl (backendContext),
+ GRBackend.Vulkan => throw new NotSupportedException (),
+ _ => throw new ArgumentOutOfRangeException (nameof (backend)),
+ };
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(GRBackend, GRGlInterface) instead.")]
+ public static GRContext Create (GRBackend backend, IntPtr backendContext) =>
+ backend switch
+ {
+ GRBackend.Metal => throw new NotSupportedException (),
+ GRBackend.OpenGL => GetObject<GRContext> (SkiaApi.gr_context_make_gl (backendContext)),
+ GRBackend.Vulkan => throw new NotSupportedException (),
+ _ => throw new ArgumentOutOfRangeException (nameof (backend)),
+ };
+
+ // CreateGl
+
+ public static GRContext CreateGl () =>
+ CreateGl (null);
+
+ public static GRContext CreateGl (GRGlInterface backendContext) =>
+ GetObject<GRContext> (SkiaApi.gr_context_make_gl (backendContext == null ? IntPtr.Zero : backendContext.Handle));
+
+ //
+
+ public GRBackend Backend => SkiaApi.gr_context_get_backend (Handle);
+
+ public void AbandonContext (bool releaseResources = false)
+ {
+ if (releaseResources)
+ SkiaApi.gr_context_release_resources_and_abandon_context (Handle);
+ else
+ SkiaApi.gr_context_abandon_context (Handle);
+ }
+
+ public void GetResourceCacheLimits (out int maxResources, out long maxResourceBytes)
+ {
+ IntPtr maxResBytes;
+ fixed (int* maxRes = &maxResources) {
+ SkiaApi.gr_context_get_resource_cache_limits (Handle, maxRes, &maxResBytes);
+ }
+ maxResourceBytes = (long)maxResBytes;
+ }
+
+ public void SetResourceCacheLimits (int maxResources, long maxResourceBytes) =>
+ SkiaApi.gr_context_set_resource_cache_limits (Handle, maxResources, (IntPtr)maxResourceBytes);
+
+ public void GetResourceCacheUsage (out int maxResources, out long maxResourceBytes)
+ {
+ IntPtr maxResBytes;
+ fixed (int* maxRes = &maxResources) {
+ SkiaApi.gr_context_get_resource_cache_usage (Handle, maxRes, &maxResBytes);
+ }
+ maxResourceBytes = (long)maxResBytes;
+ }
+
+ 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);
+
+ public int GetMaxSurfaceSampleCount (SKColorType colorType) =>
+ SkiaApi.gr_context_get_max_surface_sample_count_for_color_type (Handle, colorType);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public int GetRecommendedSampleCount (GRPixelConfig config, float dpi) => 0;
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+using GRBackendObject = System.IntPtr;
+
+namespace SkiaSharp
+{
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GRBackendRenderTarget instead.")]
+ public struct GRBackendRenderTargetDesc : IEquatable<GRBackendRenderTargetDesc>
+ {
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public GRPixelConfig Config { get; set; }
+ public GRSurfaceOrigin Origin { get; set; }
+ public int SampleCount { get; set; }
+ public int StencilBits { get; set; }
+ public GRBackendObject RenderTargetHandle { get; set; }
+ public readonly SKSizeI Size => new SKSizeI (Width, Height);
+ public readonly SKRectI Rect => new SKRectI (0, 0, Width, Height);
+
+ public readonly bool Equals (GRBackendRenderTargetDesc obj) =>
+ Width == obj.Width &&
+ Height == obj.Height &&
+ Config == obj.Config &&
+ Origin == obj.Origin &&
+ SampleCount == obj.SampleCount &&
+ StencilBits == obj.StencilBits &&
+ RenderTargetHandle == obj.RenderTargetHandle;
+
+ public readonly override bool Equals (object obj) =>
+ obj is GRBackendRenderTargetDesc f && Equals (f);
+
+ public static bool operator == (GRBackendRenderTargetDesc left, GRBackendRenderTargetDesc right) =>
+ left.Equals (right);
+
+ public static bool operator != (GRBackendRenderTargetDesc left, GRBackendRenderTargetDesc right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (Width);
+ hash.Add (Height);
+ hash.Add (Config);
+ hash.Add (Origin);
+ hash.Add (SampleCount);
+ hash.Add (StencilBits);
+ hash.Add (RenderTargetHandle);
+ return hash.ToHashCode ();
+ }
+ }
+
+ [Flags]
+ public enum GRGlBackendState : UInt32
+ {
+ None = 0,
+ 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
+ {
+ None = 0,
+ All = 0xffffffff,
+ }
+
+ public partial struct GRGlFramebufferInfo
+ {
+ public GRGlFramebufferInfo (uint fboId)
+ {
+ fFBOID = fboId;
+ fFormat = 0;
+ }
+
+ public GRGlFramebufferInfo (uint fboId, uint format)
+ {
+ fFBOID = fboId;
+ fFormat = format;
+ }
+ }
+
+ public partial struct GRGlTextureInfo
+ {
+ public GRGlTextureInfo (uint target, uint id)
+ {
+ fTarget = target;
+ fID = id;
+ fFormat = 0;
+ }
+
+ public GRGlTextureInfo (uint target, uint id, uint format)
+ {
+ fTarget = target;
+ fID = id;
+ fFormat = format;
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Flags]
+ [Obsolete]
+ public enum GRBackendTextureDescFlags
+ {
+ None = 0,
+ RenderTarget = 1,
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GRBackendTexture instead.")]
+ [StructLayout (LayoutKind.Sequential)]
+ public struct GRBackendTextureDesc : IEquatable<GRBackendTextureDesc>
+ {
+ public GRBackendTextureDescFlags Flags { get; set; }
+ public GRSurfaceOrigin Origin { get; set; }
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public GRPixelConfig Config { get; set; }
+ public int SampleCount { get; set; }
+ public GRBackendObject TextureHandle { get; set; }
+ public readonly SKSizeI Size => new SKSizeI (Width, Height);
+ public readonly SKRectI Rect => new SKRectI (0, 0, Width, Height);
+
+ public readonly bool Equals (GRBackendTextureDesc obj) =>
+ Flags == obj.Flags &&
+ Origin == obj.Origin &&
+ Width == obj.Width &&
+ Height == obj.Height &&
+ Config == obj.Config &&
+ SampleCount == obj.SampleCount &&
+ TextureHandle == obj.TextureHandle;
+
+ public readonly override bool Equals (object obj) =>
+ obj is GRBackendTextureDesc f && Equals (f);
+
+ public static bool operator == (GRBackendTextureDesc left, GRBackendTextureDesc right) =>
+ left.Equals (right);
+
+ public static bool operator != (GRBackendTextureDesc left, GRBackendTextureDesc right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (Flags);
+ hash.Add (Origin);
+ hash.Add (Width);
+ hash.Add (Height);
+ hash.Add (Config);
+ hash.Add (SampleCount);
+ hash.Add (TextureHandle);
+ return hash.ToHashCode ();
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GRBackendTexture instead.")]
+ public struct GRGlBackendTextureDesc : IEquatable<GRGlBackendTextureDesc>
+ {
+ public GRBackendTextureDescFlags Flags { get; set; }
+ public GRSurfaceOrigin Origin { get; set; }
+ public int Width { get; set; }
+ public int Height { get; set; }
+ public GRPixelConfig Config { get; set; }
+ public int SampleCount { get; set; }
+ public GRGlTextureInfo TextureHandle { get; set; }
+ public readonly SKSizeI Size => new SKSizeI (Width, Height);
+ public readonly SKRectI Rect => new SKRectI (0, 0, Width, Height);
+
+ public readonly bool Equals (GRGlBackendTextureDesc obj) =>
+ Flags == obj.Flags &&
+ Origin == obj.Origin &&
+ Width == obj.Width &&
+ Height == obj.Height &&
+ Config == obj.Config &&
+ SampleCount == obj.SampleCount &&
+ TextureHandle == obj.TextureHandle;
+
+ public readonly override bool Equals (object obj) =>
+ obj is GRGlBackendTextureDesc f && Equals (f);
+
+ public static bool operator == (GRGlBackendTextureDesc left, GRGlBackendTextureDesc right) =>
+ left.Equals (right);
+
+ public static bool operator != (GRGlBackendTextureDesc left, GRGlBackendTextureDesc right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (Flags);
+ hash.Add (Origin);
+ hash.Add (Width);
+ hash.Add (Height);
+ hash.Add (Config);
+ hash.Add (SampleCount);
+ hash.Add (TextureHandle);
+ return hash.ToHashCode ();
+ }
+ }
+
+ public static partial class SkiaExtensions
+ {
+ public static uint ToGlSizedFormat (this SKColorType colorType) =>
+ colorType switch
+ {
+ SKColorType.Unknown => 0,
+ SKColorType.Alpha8 => GRGlSizedFormat.ALPHA8,
+ SKColorType.Rgb565 => GRGlSizedFormat.RGB565,
+ SKColorType.Argb4444 => GRGlSizedFormat.RGBA4,
+ SKColorType.Rgba8888 => GRGlSizedFormat.RGBA8,
+ SKColorType.Rgb888x => GRGlSizedFormat.RGB8,
+ SKColorType.Bgra8888 => GRGlSizedFormat.BGRA8,
+ SKColorType.Rgba1010102 => GRGlSizedFormat.RGB10_A2,
+ SKColorType.Rgb101010x => 0,
+ SKColorType.Gray8 => GRGlSizedFormat.LUMINANCE8,
+ SKColorType.RgbaF16 => GRGlSizedFormat.RGBA16F,
+ _ => throw new ArgumentOutOfRangeException (nameof (colorType)),
+ };
+
+ public static uint ToGlSizedFormat (this GRPixelConfig config) =>
+ config switch
+ {
+ GRPixelConfig.Alpha8 => GRGlSizedFormat.ALPHA8,
+ GRPixelConfig.Gray8 => GRGlSizedFormat.LUMINANCE8,
+ GRPixelConfig.Rgb565 => GRGlSizedFormat.RGB565,
+ GRPixelConfig.Rgba4444 => GRGlSizedFormat.RGBA4,
+ GRPixelConfig.Rgba8888 => GRGlSizedFormat.RGBA8,
+ GRPixelConfig.Rgb888 => GRGlSizedFormat.RGB8,
+ GRPixelConfig.Bgra8888 => GRGlSizedFormat.BGRA8,
+ GRPixelConfig.Srgba8888 => GRGlSizedFormat.SRGB8_ALPHA8,
+ GRPixelConfig.Sbgra8888 => GRGlSizedFormat.SRGB8_ALPHA8,
+ GRPixelConfig.Rgba1010102 => GRGlSizedFormat.RGB10_A2,
+ GRPixelConfig.RgbaFloat => GRGlSizedFormat.RGBA32F,
+ GRPixelConfig.RgFloat => GRGlSizedFormat.RG32F,
+ GRPixelConfig.AlphaHalf => GRGlSizedFormat.R16F,
+ GRPixelConfig.RgbaHalf => GRGlSizedFormat.RGBA16F,
+ GRPixelConfig.Unknown => 0,
+ _ => throw new ArgumentOutOfRangeException (nameof (config)),
+ };
+
+ public static GRPixelConfig ToPixelConfig (this SKColorType colorType) =>
+ colorType switch
+ {
+ SKColorType.Unknown => GRPixelConfig.Unknown,
+ SKColorType.Alpha8 => GRPixelConfig.Alpha8,
+ SKColorType.Gray8 => GRPixelConfig.Gray8,
+ SKColorType.Rgb565 => GRPixelConfig.Rgb565,
+ SKColorType.Argb4444 => GRPixelConfig.Rgba4444,
+ SKColorType.Rgba8888 => GRPixelConfig.Rgba8888,
+ SKColorType.Rgb888x => GRPixelConfig.Rgb888,
+ SKColorType.Bgra8888 => GRPixelConfig.Bgra8888,
+ SKColorType.Rgba1010102 => GRPixelConfig.Rgba1010102,
+ SKColorType.RgbaF16 => GRPixelConfig.RgbaHalf,
+ SKColorType.Rgb101010x => GRPixelConfig.Unknown,
+ _ => throw new ArgumentOutOfRangeException (nameof (colorType)),
+ };
+
+ public static SKColorType ToColorType (this GRPixelConfig config) =>
+ config switch
+ {
+ GRPixelConfig.Unknown => SKColorType.Unknown,
+ GRPixelConfig.Alpha8 => SKColorType.Alpha8,
+ GRPixelConfig.Gray8 => SKColorType.Gray8,
+ GRPixelConfig.Rgb565 => SKColorType.Rgb565,
+ GRPixelConfig.Rgba4444 => SKColorType.Argb4444,
+ GRPixelConfig.Rgba8888 => SKColorType.Rgba8888,
+ GRPixelConfig.Rgb888 => SKColorType.Rgb888x,
+ GRPixelConfig.Bgra8888 => SKColorType.Bgra8888,
+ GRPixelConfig.Srgba8888 => SKColorType.Rgba8888,
+ GRPixelConfig.Sbgra8888 => SKColorType.Bgra8888,
+ GRPixelConfig.Rgba1010102 => SKColorType.Rgba1010102,
+ GRPixelConfig.RgbaFloat => SKColorType.Unknown,
+ GRPixelConfig.RgFloat => SKColorType.Unknown,
+ GRPixelConfig.AlphaHalf => SKColorType.Unknown,
+ GRPixelConfig.RgbaHalf => SKColorType.RgbaF16,
+ _ => throw new ArgumentOutOfRangeException (nameof (config)),
+ };
+ }
+
+ internal static class GRGlSizedFormat
+ {
+ // Unsized formats
+ internal const uint STENCIL_INDEX = 0x1901;
+ internal const uint DEPTH_COMPONENT = 0x1902;
+ internal const uint DEPTH_STENCIL = 0x84F9;
+ internal const uint RED = 0x1903;
+ internal const uint RED_INTEGER = 0x8D94;
+ internal const uint GREEN = 0x1904;
+ internal const uint BLUE = 0x1905;
+ internal const uint ALPHA = 0x1906;
+ internal const uint LUMINANCE = 0x1909;
+ internal const uint LUMINANCE_ALPHA = 0x190A;
+ internal const uint RG_INTEGER = 0x8228;
+ internal const uint RGB = 0x1907;
+ internal const uint RGB_INTEGER = 0x8D98;
+ internal const uint SRGB = 0x8C40;
+ internal const uint RGBA = 0x1908;
+ internal const uint RG = 0x8227;
+ internal const uint SRGB_ALPHA = 0x8C42;
+ internal const uint RGBA_INTEGER = 0x8D99;
+ internal const uint BGRA = 0x80E1;
+
+ // Stencil index sized formats
+ internal const uint STENCIL_INDEX4 = 0x8D47;
+ internal const uint STENCIL_INDEX8 = 0x8D48;
+ internal const uint STENCIL_INDEX16 = 0x8D49;
+
+ // Depth component sized formats
+ internal const uint DEPTH_COMPONENT16 = 0x81A5;
+
+ // Depth stencil sized formats
+ internal const uint DEPTH24_STENCIL8 = 0x88F0;
+
+ // Red sized formats
+ internal const uint R8 = 0x8229;
+ internal const uint R16 = 0x822A;
+ internal const uint R16F = 0x822D;
+ internal const uint R32F = 0x822E;
+
+ // Red integer sized formats
+ internal const uint R8I = 0x8231;
+ internal const uint R8UI = 0x8232;
+ internal const uint R16I = 0x8233;
+ internal const uint R16UI = 0x8234;
+ internal const uint R32I = 0x8235;
+ internal const uint R32UI = 0x8236;
+
+ // Luminance sized formats
+ internal const uint LUMINANCE8 = 0x8040;
+
+ // Alpha sized formats
+ internal const uint ALPHA8 = 0x803C;
+ internal const uint ALPHA16 = 0x803E;
+ internal const uint ALPHA16F = 0x881C;
+ internal const uint ALPHA32F = 0x8816;
+
+ // Alpha integer sized formats
+ internal const uint ALPHA8I = 0x8D90;
+ internal const uint ALPHA8UI = 0x8D7E;
+ internal const uint ALPHA16I = 0x8D8A;
+ internal const uint ALPHA16UI = 0x8D78;
+ internal const uint ALPHA32I = 0x8D84;
+ internal const uint ALPHA32UI = 0x8D72;
+
+ // RG sized formats
+ internal const uint RG8 = 0x822B;
+ internal const uint RG16 = 0x822C;
+ //internal const uint R16F = 0x822D;
+ //internal const uint R32F = 0x822E;
+
+ // RG sized integer formats
+ internal const uint RG8I = 0x8237;
+ internal const uint RG8UI = 0x8238;
+ internal const uint RG16I = 0x8239;
+ internal const uint RG16UI = 0x823A;
+ internal const uint RG32I = 0x823B;
+ internal const uint RG32UI = 0x823C;
+
+ // RGB sized formats
+ internal const uint RGB5 = 0x8050;
+ internal const uint RGB565 = 0x8D62;
+ internal const uint RGB8 = 0x8051;
+ internal const uint SRGB8 = 0x8C41;
+
+ // RGB integer sized formats
+ internal const uint RGB8I = 0x8D8F;
+ internal const uint RGB8UI = 0x8D7D;
+ internal const uint RGB16I = 0x8D89;
+ internal const uint RGB16UI = 0x8D77;
+ internal const uint RGB32I = 0x8D83;
+ internal const uint RGB32UI = 0x8D71;
+
+ // RGBA sized formats
+ internal const uint RGBA4 = 0x8056;
+ internal const uint RGB5_A1 = 0x8057;
+ internal const uint RGBA8 = 0x8058;
+ internal const uint RGB10_A2 = 0x8059;
+ internal const uint SRGB8_ALPHA8 = 0x8C43;
+ internal const uint RGBA16F = 0x881A;
+ internal const uint RGBA32F = 0x8814;
+ internal const uint RG32F = 0x8230;
+
+ // RGBA integer sized formats
+ internal const uint RGBA8I = 0x8D8E;
+ internal const uint RGBA8UI = 0x8D7C;
+ internal const uint RGBA16I = 0x8D88;
+ internal const uint RGBA16UI = 0x8D76;
+ internal const uint RGBA32I = 0x8D82;
+ internal const uint RGBA32UI = 0x8D70;
+
+ // BGRA sized formats
+ internal const uint BGRA8 = 0x93A1;
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ public unsafe class GRGlInterface : SKObject, ISKReferenceCounted
+ {
+ [Preserve]
+ internal GRGlInterface (IntPtr h, bool owns)
+ : base (h, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public static GRGlInterface CreateDefaultInterface ()
+ {
+ // first try ANGLE, then fall back to the OpenGL-based
+ return CreateNativeAngleInterface () ?? CreateNativeGlInterface ();
+ }
+
+ public static GRGlInterface CreateNativeGlInterface ()
+ {
+ // the native code will automatically return null on non-OpenGL platforms, such as UWP
+ return GetObject<GRGlInterface> (SkiaApi.gr_glinterface_create_native_interface ());
+ }
+
+ public static GRGlInterface CreateNativeAngleInterface ()
+ {
+ if (PlatformConfiguration.IsWindows) {
+ return AssembleAngleInterface (AngleLoader.GetProc);
+ } else {
+ // return null on non-DirectX platforms: everything except Windows
+ return null;
+ }
+ }
+
+ public static GRGlInterface CreateNativeEvasInterface (IntPtr evas)
+ {
+ var evasLoader = new EvasGlLoader(evas);
+ return AssembleGlesInterface((ctx, name) => evasLoader.GetFunctionPointer(name));
+ }
+
+ public static GRGlInterface AssembleInterface (GRGlGetProcDelegate get)
+ {
+ return AssembleInterface (null, get);
+ }
+
+ public static GRGlInterface AssembleInterface (object context, GRGlGetProcDelegate get)
+ {
+ // if on Windows, try ANGLE
+ if (PlatformConfiguration.IsWindows) {
+ var angle = AssembleAngleInterface (context, get);
+ if (angle != null) {
+ return angle;
+ }
+ }
+
+ // try the native default
+ var del = get != null && context != null
+ ? new GRGlGetProcDelegate ((_, name) => get (context, name))
+ : get;
+ var proxy = DelegateProxies.Create (del, DelegateProxies.GRGlGetProcDelegateProxy, out var gch, out var ctx);
+ try {
+ return GetObject<GRGlInterface> (SkiaApi.gr_glinterface_assemble_interface ((void*)ctx, proxy));
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ public static GRGlInterface AssembleAngleInterface (GRGlGetProcDelegate get)
+ {
+ return AssembleAngleInterface (null, get);
+ }
+
+ public static GRGlInterface AssembleAngleInterface (object context, GRGlGetProcDelegate get)
+ {
+ // ANGLE is just a GLES v2 over DX v9+
+ return AssembleGlesInterface (context, get);
+ }
+
+ public static GRGlInterface AssembleGlInterface (GRGlGetProcDelegate get)
+ {
+ return AssembleGlInterface (null, get);
+ }
+
+ public static GRGlInterface AssembleGlInterface (object context, GRGlGetProcDelegate get)
+ {
+ var del = get != null && context != null
+ ? new GRGlGetProcDelegate ((_, name) => get (context, name))
+ : get;
+ var proxy = DelegateProxies.Create (del, DelegateProxies.GRGlGetProcDelegateProxy, out var gch, out var ctx);
+ try {
+ return GetObject<GRGlInterface> (SkiaApi.gr_glinterface_assemble_gl_interface ((void*)ctx, proxy));
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ public static GRGlInterface AssembleGlesInterface (GRGlGetProcDelegate get)
+ {
+ return AssembleGlesInterface (null, get);
+ }
+
+ public static GRGlInterface AssembleGlesInterface (object context, GRGlGetProcDelegate get)
+ {
+ var del = get != null && context != null
+ ? new GRGlGetProcDelegate ((_, name) => get (context, name))
+ : get;
+ var proxy = DelegateProxies.Create (del, DelegateProxies.GRGlGetProcDelegateProxy, out var gch, out var ctx);
+ try {
+ return GetObject<GRGlInterface> (SkiaApi.gr_glinterface_assemble_gles_interface ((void*)ctx, proxy));
+ } finally {
+ gch.Free ();
+ }
+ }
+
+ public bool Validate ()
+ {
+ return SkiaApi.gr_glinterface_validate (Handle);
+ }
+
+ public bool HasExtension (string extension)
+ {
+ return SkiaApi.gr_glinterface_has_extension (Handle, extension);
+ }
+
+ private static class AngleLoader
+ {
+ private static readonly IntPtr libEGL;
+ private static readonly IntPtr libGLESv2;
+
+ [DllImport ("Kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
+ private static extern IntPtr LoadLibrary ([MarshalAs (UnmanagedType.LPStr)] string lpFileName);
+
+ [DllImport ("Kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
+ private static extern IntPtr GetProcAddress (IntPtr hModule, [MarshalAs (UnmanagedType.LPStr)] string lpProcName);
+
+ [DllImport ("libEGL.dll")]
+ private static extern IntPtr eglGetProcAddress ([MarshalAs (UnmanagedType.LPStr)] string procname);
+
+ static AngleLoader()
+ {
+ // this is not supported at all on non-Windows platforms
+ if (!PlatformConfiguration.IsWindows) {
+ return;
+ }
+
+ libEGL = LoadLibrary ("libEGL.dll");
+ if (Marshal.GetLastWin32Error () != 0 || libEGL == IntPtr.Zero)
+ throw new DllNotFoundException ("Unable to load libEGL.dll.");
+
+ libGLESv2 = LoadLibrary ("libGLESv2.dll");
+ if (Marshal.GetLastWin32Error () != 0 || libGLESv2 == IntPtr.Zero)
+ throw new DllNotFoundException ("Unable to load libGLESv2.dll.");
+ }
+
+ // function to assemble the ANGLE interface
+ public static IntPtr GetProc (object context, string name)
+ {
+ // this is not supported at all on non-Windows platforms
+ if (!PlatformConfiguration.IsWindows) {
+ return IntPtr.Zero;
+ }
+
+ IntPtr proc = GetProcAddress (libGLESv2, name);
+ if (proc == IntPtr.Zero)
+ {
+ proc = GetProcAddress (libEGL, name);
+ }
+ if (proc == IntPtr.Zero)
+ {
+ proc = eglGetProcAddress (name);
+ }
+ return proc;
+ }
+ }
+
+ private class EvasGlLoader
+ {
+ private IntPtr glEvas;
+ private EvasGlApi api;
+
+ [DllImport ("libevas.so.1")]
+ internal static extern IntPtr evas_gl_api_get (IntPtr evas_gl);
+
+ [DllImport ("libevas.so.1")]
+ internal static extern IntPtr evas_gl_proc_address_get (IntPtr evas_gl, string name);
+
+ public EvasGlLoader (IntPtr evas)
+ {
+ glEvas = evas;
+
+ var unmanagedGlApi = evas_gl_api_get (glEvas);
+ api = Marshal.PtrToStructure<EvasGlApi> (unmanagedGlApi);
+ }
+
+ public IntPtr GetFunctionPointer(string name)
+ {
+ var ret = evas_gl_proc_address_get (glEvas, name);
+
+ if (ret == IntPtr.Zero) {
+ var field = typeof (EvasGlApi).GetField (name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
+
+ if (field?.FieldType == typeof (IntPtr))
+ ret = (IntPtr) field.GetValue (api);
+ }
+
+ return ret;
+ }
+ }
+
+ // this structure is initialized from a native pointer
+ [Preserve (AllMembers = true)]
+ private struct EvasGlApi
+ {
+ // DO NOT change the order, needs to be as specified in struct _Evas_GL_API (/platform/upstream/efl/src/lib/evas/Evas_GL.h)
+ // DO NOT change the names, they need to match the OpenGL API
+#pragma warning disable 0169
+ private int version;
+ private IntPtr glActiveTexture;
+ private IntPtr glAttachShader;
+ private IntPtr glBindAttribLocation;
+ private IntPtr glBindBuffer;
+ private IntPtr glBindFramebuffer;
+ private IntPtr glBindRenderbuffer;
+ private IntPtr glBindTexture;
+ private IntPtr glBlendColor;
+ private IntPtr glBlendEquation;
+ private IntPtr glBlendEquationSeparate;
+ private IntPtr glBlendFunc;
+ private IntPtr glBlendFuncSeparate;
+ private IntPtr glBufferData;
+ private IntPtr glBufferSubData;
+ private IntPtr glCheckFramebufferStatus;
+ private IntPtr glClear;
+ private IntPtr glClearColor;
+ private IntPtr glClearDepthf;
+ private IntPtr glClearStencil;
+ private IntPtr glColorMask;
+ private IntPtr glCompileShader;
+ private IntPtr glCompressedTexImage2D;
+ private IntPtr glCompressedTexSubImage2D;
+ private IntPtr glCopyTexImage2D;
+ private IntPtr glCopyTexSubImage2D;
+ private IntPtr glCreateProgram;
+ private IntPtr glCreateShader;
+ private IntPtr glCullFace;
+ private IntPtr glDeleteBuffers;
+ private IntPtr glDeleteFramebuffers;
+ private IntPtr glDeleteProgram;
+ private IntPtr glDeleteRenderbuffers;
+ private IntPtr glDeleteShader;
+ private IntPtr glDeleteTextures;
+ private IntPtr glDepthFunc;
+ private IntPtr glDepthMask;
+ private IntPtr glDepthRangef;
+ private IntPtr glDetachShader;
+ private IntPtr glDisable;
+ private IntPtr glDisableVertexAttribArray;
+ private IntPtr glDrawArrays;
+ private IntPtr glDrawElements;
+ private IntPtr glEnable;
+ private IntPtr glEnableVertexAttribArray;
+ private IntPtr glFinish;
+ private IntPtr glFlush;
+ private IntPtr glFramebufferRenderbuffer;
+ private IntPtr glFramebufferTexture2D;
+ private IntPtr glFrontFace;
+ private IntPtr glGenBuffers;
+ private IntPtr glGenerateMipmap;
+ private IntPtr glGenFramebuffers;
+ private IntPtr glGenRenderbuffers;
+ private IntPtr glGenTextures;
+ private IntPtr glGetActiveAttrib;
+ private IntPtr glGetActiveUniform;
+ private IntPtr glGetAttachedShaders;
+ private IntPtr glGetAttribLocation;
+ private IntPtr glGetBooleanv;
+ private IntPtr glGetBufferParameteriv;
+ private IntPtr glGetError;
+ private IntPtr glGetFloatv;
+ private IntPtr glGetFramebufferAttachmentParameteriv;
+ private IntPtr glGetIntegerv;
+ private IntPtr glGetProgramiv;
+ private IntPtr glGetProgramInfoLog;
+ private IntPtr glGetRenderbufferParameteriv;
+ private IntPtr glGetShaderiv;
+ private IntPtr glGetShaderInfoLog;
+ private IntPtr glGetShaderPrecisionFormat;
+ private IntPtr glGetShaderSource;
+ private IntPtr glGetString;
+ private IntPtr glGetTexParameterfv;
+ private IntPtr glGetTexParameteriv;
+ private IntPtr glGetUniformfv;
+ private IntPtr glGetUniformiv;
+ private IntPtr glGetUniformLocation;
+ private IntPtr glGetVertexAttribfv;
+ private IntPtr glGetVertexAttribiv;
+ private IntPtr glGetVertexAttribPointerv;
+ private IntPtr glHint;
+ private IntPtr glIsBuffer;
+ private IntPtr glIsEnabled;
+ private IntPtr glIsFramebuffer;
+ private IntPtr glIsProgram;
+ private IntPtr glIsRenderbuffer;
+ private IntPtr glIsShader;
+ private IntPtr glIsTexture;
+ private IntPtr glLineWidth;
+ private IntPtr glLinkProgram;
+ private IntPtr glPixelStorei;
+ private IntPtr glPolygonOffset;
+ private IntPtr glReadPixels;
+ private IntPtr glReleaseShaderCompiler;
+ private IntPtr glRenderbufferStorage;
+ private IntPtr glSampleCoverage;
+ private IntPtr glScissor;
+ private IntPtr glShaderBinary;
+ private IntPtr glShaderSource;
+ private IntPtr glStencilFunc;
+ private IntPtr glStencilFuncSeparate;
+ private IntPtr glStencilMask;
+ private IntPtr glStencilMaskSeparate;
+ private IntPtr glStencilOp;
+ private IntPtr glStencilOpSeparate;
+ private IntPtr glTexImage2D;
+ private IntPtr glTexParameterf;
+ private IntPtr glTexParameterfv;
+ private IntPtr glTexParameteri;
+ private IntPtr glTexParameteriv;
+ private IntPtr glTexSubImage2D;
+ private IntPtr glUniform1f;
+ private IntPtr glUniform1fv;
+ private IntPtr glUniform1i;
+ private IntPtr glUniform1iv;
+ private IntPtr glUniform2f;
+ private IntPtr glUniform2fv;
+ private IntPtr glUniform2i;
+ private IntPtr glUniform2iv;
+ private IntPtr glUniform3f;
+ private IntPtr glUniform3fv;
+ private IntPtr glUniform3i;
+ private IntPtr glUniform3iv;
+ private IntPtr glUniform4f;
+ private IntPtr glUniform4fv;
+ private IntPtr glUniform4i;
+ private IntPtr glUniform4iv;
+ private IntPtr glUniformMatrix2fv;
+ private IntPtr glUniformMatrix3fv;
+ private IntPtr glUniformMatrix4fv;
+ private IntPtr glUseProgram;
+ private IntPtr glValidateProgram;
+ private IntPtr glVertexAttrib1f;
+ private IntPtr glVertexAttrib1fv;
+ private IntPtr glVertexAttrib2f;
+ private IntPtr glVertexAttrib2fv;
+ private IntPtr glVertexAttrib3f;
+ private IntPtr glVertexAttrib3fv;
+ private IntPtr glVertexAttrib4f;
+ private IntPtr glVertexAttrib4fv;
+ private IntPtr glVertexAttribPointer;
+ private IntPtr glViewport;
+ private IntPtr glEvasGLImageTargetTexture2DOES;
+ private IntPtr glEvasGLImageTargetRenderbufferStorageOES;
+ private IntPtr glGetProgramBinaryOES;
+ private IntPtr glProgramBinaryOES;
+ private IntPtr glMapBufferOES;
+ private IntPtr glUnmapBufferOES;
+ private IntPtr glGetBufferPointervOES;
+ private IntPtr glTexImage3DOES;
+ private IntPtr glTexSubImage3DOES;
+ private IntPtr glCopyTexSubImage3DOES;
+ private IntPtr glCompressedTexImage3DOES;
+ private IntPtr glCompressedTexSubImage3DOES;
+ private IntPtr glFramebufferTexture3DOES;
+ private IntPtr glGetPerfMonitorGroupsAMD;
+ private IntPtr glGetPerfMonitorCountersAMD;
+ private IntPtr glGetPerfMonitorGroupStringAMD;
+ private IntPtr glGetPerfMonitorCounterStringAMD;
+ private IntPtr glGetPerfMonitorCounterInfoAMD;
+ private IntPtr glGenPerfMonitorsAMD;
+ private IntPtr glDeletePerfMonitorsAMD;
+ private IntPtr glSelectPerfMonitorCountersAMD;
+ private IntPtr glBeginPerfMonitorAMD;
+ private IntPtr glEndPerfMonitorAMD;
+ private IntPtr glGetPerfMonitorCounterDataAMD;
+ private IntPtr glDiscardFramebufferEXT;
+ private IntPtr glMultiDrawArraysEXT;
+ private IntPtr glMultiDrawElementsEXT;
+ private IntPtr glDeleteFencesNV;
+ private IntPtr glGenFencesNV;
+ private IntPtr glIsFenceNV;
+ private IntPtr glTestFenceNV;
+ private IntPtr glGetFenceivNV;
+ private IntPtr glFinishFenceNV;
+ private IntPtr glSetFenceNV;
+ private IntPtr glGetDriverControlsQCOM;
+ private IntPtr glGetDriverControlStringQCOM;
+ private IntPtr glEnableDriverControlQCOM;
+ private IntPtr glDisableDriverControlQCOM;
+ private IntPtr glExtGetTexturesQCOM;
+ private IntPtr glExtGetBuffersQCOM;
+ private IntPtr glExtGetRenderbuffersQCOM;
+ private IntPtr glExtGetFramebuffersQCOM;
+ private IntPtr glExtGetTexLevelParameterivQCOM;
+ private IntPtr glExtTexObjectStateOverrideiQCOM;
+ private IntPtr glExtGetTexSubImageQCOM;
+ private IntPtr glExtGetBufferPointervQCOM;
+ private IntPtr glExtGetShadersQCOM;
+ private IntPtr glExtGetProgramsQCOM;
+ private IntPtr glExtIsProgramBinaryQCOM;
+ private IntPtr glExtGetProgramBinarySourceQCOM;
+ private IntPtr evasglCreateImage;
+ private IntPtr evasglDestroyImage;
+ private IntPtr evasglCreateImageForContext;
+ private IntPtr glAlphaFunc;
+ private IntPtr glClipPlanef;
+ private IntPtr glColor4f;
+ private IntPtr glFogf;
+ private IntPtr glFogfv;
+ private IntPtr glFrustumf;
+ private IntPtr glGetClipPlanef;
+ private IntPtr glGetLightfv;
+ private IntPtr glGetMaterialfv;
+ private IntPtr glGetTexEnvfv;
+ private IntPtr glLightModelf;
+ private IntPtr glLightModelfv;
+ private IntPtr glLightf;
+ private IntPtr glLightfv;
+ private IntPtr glLoadMatrixf;
+ private IntPtr glMaterialf;
+ private IntPtr glMaterialfv;
+ private IntPtr glMultMatrixf;
+ private IntPtr glMultiTexCoord4f;
+ private IntPtr glNormal3f;
+ private IntPtr glOrthof;
+ private IntPtr glPointParameterf;
+ private IntPtr glPointParameterfv;
+ private IntPtr glPointSize;
+ private IntPtr glPointSizePointerOES;
+ private IntPtr glRotatef;
+ private IntPtr glScalef;
+ private IntPtr glTexEnvf;
+ private IntPtr glTexEnvfv;
+ private IntPtr glTranslatef;
+ private IntPtr glAlphaFuncx;
+ private IntPtr glClearColorx;
+ private IntPtr glClearDepthx;
+ private IntPtr glClientActiveTexture;
+ private IntPtr glClipPlanex;
+ private IntPtr glColor4ub;
+ private IntPtr glColor4x;
+ private IntPtr glColorPointer;
+ private IntPtr glDepthRangex;
+ private IntPtr glDisableClientState;
+ private IntPtr glEnableClientState;
+ private IntPtr glFogx;
+ private IntPtr glFogxv;
+ private IntPtr glFrustumx;
+ private IntPtr glGetClipPlanex;
+ private IntPtr glGetFixedv;
+ private IntPtr glGetLightxv;
+ private IntPtr glGetMaterialxv;
+ private IntPtr glGetPointerv;
+ private IntPtr glGetTexEnviv;
+ private IntPtr glGetTexEnvxv;
+ private IntPtr glGetTexParameterxv;
+ private IntPtr glLightModelx;
+ private IntPtr glLightModelxv;
+ private IntPtr glLightx;
+ private IntPtr glLightxv;
+ private IntPtr glLineWidthx;
+ private IntPtr glLoadIdentity;
+ private IntPtr glLoadMatrixx;
+ private IntPtr glLogicOp;
+ private IntPtr glMaterialx;
+ private IntPtr glMaterialxv;
+ private IntPtr glMatrixMode;
+ private IntPtr glMultMatrixx;
+ private IntPtr glMultiTexCoord4x;
+ private IntPtr glNormal3x;
+ private IntPtr glNormalPointer;
+ private IntPtr glOrthox;
+ private IntPtr glPointParameterx;
+ private IntPtr glPointParameterxv;
+ private IntPtr glPointSizex;
+ private IntPtr glPolygonOffsetx;
+ private IntPtr glPopMatrix;
+ private IntPtr glPushMatrix;
+ private IntPtr glRotatex;
+ private IntPtr glSampleCoveragex;
+ private IntPtr glScalex;
+ private IntPtr glShadeModel;
+ private IntPtr glTexCoordPointer;
+ private IntPtr glTexEnvi;
+ private IntPtr glTexEnvx;
+ private IntPtr glTexEnviv;
+ private IntPtr glTexEnvxv;
+ private IntPtr glTexParameterx;
+ private IntPtr glTexParameterxv;
+ private IntPtr glTranslatex;
+ private IntPtr glVertexPointer;
+ private IntPtr glBlendEquationSeparateOES;
+ private IntPtr glBlendFuncSeparateOES;
+ private IntPtr glBlendEquationOES;
+ private IntPtr glDrawTexsOES;
+ private IntPtr glDrawTexiOES;
+ private IntPtr glDrawTexxOES;
+ private IntPtr glDrawTexsvOES;
+ private IntPtr glDrawTexivOES;
+ private IntPtr glDrawTexxvOES;
+ private IntPtr glDrawTexfOES;
+ private IntPtr glDrawTexfvOES;
+ private IntPtr glAlphaFuncxOES;
+ private IntPtr glClearColorxOES;
+ private IntPtr glClearDepthxOES;
+ private IntPtr glClipPlanexOES;
+ private IntPtr glColor4xOES;
+ private IntPtr glDepthRangexOES;
+ private IntPtr glFogxOES;
+ private IntPtr glFogxvOES;
+ private IntPtr glFrustumxOES;
+ private IntPtr glGetClipPlanexOES;
+ private IntPtr glGetFixedvOES;
+ private IntPtr glGetLightxvOES;
+ private IntPtr glGetMaterialxvOES;
+ private IntPtr glGetTexEnvxvOES;
+ private IntPtr glGetTexParameterxvOES;
+ private IntPtr glLightModelxOES;
+ private IntPtr glLightModelxvOES;
+ private IntPtr glLightxOES;
+ private IntPtr glLightxvOES;
+ private IntPtr glLineWidthxOES;
+ private IntPtr glLoadMatrixxOES;
+ private IntPtr glMaterialxOES;
+ private IntPtr glMaterialxvOES;
+ private IntPtr glMultMatrixxOES;
+ private IntPtr glMultiTexCoord4xOES;
+ private IntPtr glNormal3xOES;
+ private IntPtr glOrthoxOES;
+ private IntPtr glPointParameterxOES;
+ private IntPtr glPointParameterxvOES;
+ private IntPtr glPointSizexOES;
+ private IntPtr glPolygonOffsetxOES;
+ private IntPtr glRotatexOES;
+ private IntPtr glSampleCoveragexOES;
+ private IntPtr glScalexOES;
+ private IntPtr glTexEnvxOES;
+ private IntPtr glTexEnvxvOES;
+ private IntPtr glTexParameterxOES;
+ private IntPtr glTexParameterxvOES;
+ private IntPtr glTranslatexOES;
+ private IntPtr glIsRenderbufferOES;
+ private IntPtr glBindRenderbufferOES;
+ private IntPtr glDeleteRenderbuffersOES;
+ private IntPtr glGenRenderbuffersOES;
+ private IntPtr glRenderbufferStorageOES;
+ private IntPtr glGetRenderbufferParameterivOES;
+ private IntPtr glIsFramebufferOES;
+ private IntPtr glBindFramebufferOES;
+ private IntPtr glDeleteFramebuffersOES;
+ private IntPtr glGenFramebuffersOES;
+ private IntPtr glCheckFramebufferStatusOES;
+ private IntPtr glFramebufferRenderbufferOES;
+ private IntPtr glFramebufferTexture2DOES;
+ private IntPtr glGetFramebufferAttachmentParameterivOES;
+ private IntPtr glGenerateMipmapOES;
+ private IntPtr glCurrentPaletteMatrixOES;
+ private IntPtr glLoadPaletteFromModelViewMatrixOES;
+ private IntPtr glMatrixIndexPointerOES;
+ private IntPtr glWeightPointerOES;
+ private IntPtr glQueryMatrixxOES;
+ private IntPtr glDepthRangefOES;
+ private IntPtr glFrustumfOES;
+ private IntPtr glOrthofOES;
+ private IntPtr glClipPlanefOES;
+ private IntPtr glGetClipPlanefOES;
+ private IntPtr glClearDepthfOES;
+ private IntPtr glTexGenfOES;
+ private IntPtr glTexGenfvOES;
+ private IntPtr glTexGeniOES;
+ private IntPtr glTexGenivOES;
+ private IntPtr glTexGenxOES;
+ private IntPtr glTexGenxvOES;
+ private IntPtr glGetTexGenfvOES;
+ private IntPtr glGetTexGenivOES;
+ private IntPtr glGetTexGenxvOES;
+ private IntPtr glBindVertexArrayOES;
+ private IntPtr glDeleteVertexArraysOES;
+ private IntPtr glGenVertexArraysOES;
+ private IntPtr glIsVertexArrayOES;
+ private IntPtr glCopyTextureLevelsAPPLE;
+ private IntPtr glRenderbufferStorageMultisampleAPPLE;
+ private IntPtr glResolveMultisampleFramebufferAPPLE;
+ private IntPtr glFenceSyncAPPLE;
+ private IntPtr glIsSyncAPPLE;
+ private IntPtr glDeleteSyncAPPLE;
+ private IntPtr glClientWaitSyncAPPLE;
+ private IntPtr glWaitSyncAPPLE;
+ private IntPtr glGetInteger64vAPPLE;
+ private IntPtr glGetSyncivAPPLE;
+ private IntPtr glMapBufferRangeEXT;
+ private IntPtr glFlushMappedBufferRangeEXT;
+ private IntPtr glRenderbufferStorageMultisampleEXT;
+ private IntPtr glFramebufferTexture2DMultisampleEXT;
+ private IntPtr glGetGraphicsResetStatusEXT;
+ private IntPtr glReadnPixelsEXT;
+ private IntPtr glGetnUniformfvEXT;
+ private IntPtr glGetnUniformivEXT;
+ private IntPtr glTexStorage1DEXT;
+ private IntPtr glTexStorage2DEXT;
+ private IntPtr glTexStorage3DEXT;
+ private IntPtr glTextureStorage1DEXT;
+ private IntPtr glTextureStorage2DEXT;
+ private IntPtr glTextureStorage3DEXT;
+ private IntPtr glClipPlanefIMG;
+ private IntPtr glClipPlanexIMG;
+ private IntPtr glRenderbufferStorageMultisampleIMG;
+ private IntPtr glFramebufferTexture2DMultisampleIMG;
+ private IntPtr glStartTilingQCOM;
+ private IntPtr glEndTilingQCOM;
+ private IntPtr evasglCreateSync;
+ private IntPtr evasglDestroySync;
+ private IntPtr evasglClientWaitSync;
+ private IntPtr evasglSignalSync;
+ private IntPtr evasglGetSyncAttrib;
+ private IntPtr evasglWaitSync;
+ private IntPtr evasglBindWaylandDisplay;
+ private IntPtr evasglUnbindWaylandDisplay;
+ private IntPtr evasglQueryWaylandBuffer;
+ private IntPtr glBeginQuery;
+ private IntPtr glBeginTransformFeedback;
+ private IntPtr glBindBufferBase;
+ private IntPtr glBindBufferRange;
+ private IntPtr glBindSampler;
+ private IntPtr glBindTransformFeedback;
+ private IntPtr glBindVertexArray;
+ private IntPtr glBlitFramebuffer;
+ private IntPtr glClearBufferfi;
+ private IntPtr glClearBufferfv;
+ private IntPtr glClearBufferiv;
+ private IntPtr glClearBufferuiv;
+ private IntPtr glClientWaitSync;
+ private IntPtr glCompressedTexImage3D;
+ private IntPtr glCompressedTexSubImage3D;
+ private IntPtr glCopyBufferSubData;
+ private IntPtr glCopyTexSubImage3D;
+ private IntPtr glDeleteQueries;
+ private IntPtr glDeleteSamplers;
+ private IntPtr glDeleteSync;
+ private IntPtr glDeleteTransformFeedbacks;
+ private IntPtr glDeleteVertexArrays;
+ private IntPtr glDrawArraysInstanced;
+ private IntPtr glDrawBuffers;
+ private IntPtr glDrawElementsInstanced;
+ private IntPtr glDrawRangeElements;
+ private IntPtr glEndQuery;
+ private IntPtr glEndTransformFeedback;
+ private IntPtr glFenceSync;
+ private IntPtr glFlushMappedBufferRange;
+ private IntPtr glFramebufferTextureLayer;
+ private IntPtr glGenQueries;
+ private IntPtr glGenSamplers;
+ private IntPtr glGenTransformFeedbacks;
+ private IntPtr glGenVertexArrays;
+ private IntPtr glGetActiveUniformBlockiv;
+ private IntPtr glGetActiveUniformBlockName;
+ private IntPtr glGetActiveUniformsiv;
+ private IntPtr glGetBufferParameteri64v;
+ private IntPtr glGetBufferPointerv;
+ private IntPtr glGetFragDataLocation;
+ private IntPtr glGetInteger64i_v;
+ private IntPtr glGetInteger64v;
+ private IntPtr glGetIntegeri_v;
+ private IntPtr glGetInternalformativ;
+ private IntPtr glGetProgramBinary;
+ private IntPtr glGetQueryiv;
+ private IntPtr glGetQueryObjectuiv;
+ private IntPtr glGetSamplerParameterfv;
+ private IntPtr glGetSamplerParameteriv;
+ private IntPtr glGetStringi;
+ private IntPtr glGetSynciv;
+ private IntPtr glGetTransformFeedbackVarying;
+ private IntPtr glGetUniformBlockIndex;
+ private IntPtr glGetUniformIndices;
+ private IntPtr glGetUniformuiv;
+ private IntPtr glGetVertexAttribIiv;
+ private IntPtr glGetVertexAttribIuiv;
+ private IntPtr glInvalidateFramebuffer;
+ private IntPtr glInvalidateSubFramebuffer;
+ private IntPtr glIsQuery;
+ private IntPtr glIsSampler;
+ private IntPtr glIsSync;
+ private IntPtr glIsTransformFeedback;
+ private IntPtr glIsVertexArray;
+ private IntPtr glMapBufferRange;
+ private IntPtr glPauseTransformFeedback;
+ private IntPtr glProgramBinary;
+ private IntPtr glProgramParameteri;
+ private IntPtr glReadBuffer;
+ private IntPtr glRenderbufferStorageMultisample;
+ private IntPtr glResumeTransformFeedback;
+ private IntPtr glSamplerParameterf;
+ private IntPtr glSamplerParameterfv;
+ private IntPtr glSamplerParameteri;
+ private IntPtr glSamplerParameteriv;
+ private IntPtr glTexImage3D;
+ private IntPtr glTexStorage2D;
+ private IntPtr glTexStorage3D;
+ private IntPtr glTexSubImage3D;
+ private IntPtr glTransformFeedbackVaryings;
+ private IntPtr glUniform1ui;
+ private IntPtr glUniform1uiv;
+ private IntPtr glUniform2ui;
+ private IntPtr glUniform2uiv;
+ private IntPtr glUniform3ui;
+ private IntPtr glUniform3uiv;
+ private IntPtr glUniform4ui;
+ private IntPtr glUniform4uiv;
+ private IntPtr glUniformBlockBinding;
+ private IntPtr glUniformMatrix2x3fv;
+ private IntPtr glUniformMatrix3x2fv;
+ private IntPtr glUniformMatrix2x4fv;
+ private IntPtr glUniformMatrix4x2fv;
+ private IntPtr glUniformMatrix3x4fv;
+ private IntPtr glUniformMatrix4x3fv;
+ private IntPtr glUnmapBuffer;
+ private IntPtr glVertexAttribDivisor;
+ private IntPtr glVertexAttribI4i;
+ private IntPtr glVertexAttribI4iv;
+ private IntPtr glVertexAttribI4ui;
+ private IntPtr glVertexAttribI4uiv;
+ private IntPtr glVertexAttribIPointer;
+ private IntPtr glWaitSync;
+ private IntPtr glDispatchCompute;
+ private IntPtr glDispatchComputeIndirect;
+ private IntPtr glDrawArraysIndirect;
+ private IntPtr glDrawElementsIndirect;
+ private IntPtr glFramebufferParameteri;
+ private IntPtr glGetFramebufferParameteriv;
+ private IntPtr glGetProgramInterfaceiv;
+ private IntPtr glGetProgramResourceIndex;
+ private IntPtr glGetProgramResourceName;
+ private IntPtr glGetProgramResourceiv;
+ private IntPtr glGetProgramResourceLocation;
+ private IntPtr glUseProgramStages;
+ private IntPtr glActiveShaderProgram;
+ private IntPtr glCreateShaderProgramv;
+ private IntPtr glBindProgramPipeline;
+ private IntPtr glDeleteProgramPipelines;
+ private IntPtr glGenProgramPipelines;
+ private IntPtr glIsProgramPipeline;
+ private IntPtr glGetProgramPipelineiv;
+ private IntPtr glProgramUniform1i;
+ private IntPtr glProgramUniform2i;
+ private IntPtr glProgramUniform3i;
+ private IntPtr glProgramUniform4i;
+ private IntPtr glProgramUniform1ui;
+ private IntPtr glProgramUniform2ui;
+ private IntPtr glProgramUniform3ui;
+ private IntPtr glProgramUniform4ui;
+ private IntPtr glProgramUniform1f;
+ private IntPtr glProgramUniform2f;
+ private IntPtr glProgramUniform3f;
+ private IntPtr glProgramUniform4f;
+ private IntPtr glProgramUniform1iv;
+ private IntPtr glProgramUniform2iv;
+ private IntPtr glProgramUniform3iv;
+ private IntPtr glProgramUniform4iv;
+ private IntPtr glProgramUniform1uiv;
+ private IntPtr glProgramUniform2uiv;
+ private IntPtr glProgramUniform3uiv;
+ private IntPtr glProgramUniform4uiv;
+ private IntPtr glProgramUniform1fv;
+ private IntPtr glProgramUniform2fv;
+ private IntPtr glProgramUniform3fv;
+ private IntPtr glProgramUniform4fv;
+ private IntPtr glProgramUniformMatrix2fv;
+ private IntPtr glProgramUniformMatrix3fv;
+ private IntPtr glProgramUniformMatrix4fv;
+ private IntPtr glProgramUniformMatrix2x3fv;
+ private IntPtr glProgramUniformMatrix3x2fv;
+ private IntPtr glProgramUniformMatrix2x4fv;
+ private IntPtr glProgramUniformMatrix4x2fv;
+ private IntPtr glProgramUniformMatrix3x4fv;
+ private IntPtr glProgramUniformMatrix4x3fv;
+ private IntPtr glValidateProgramPipeline;
+ private IntPtr glGetProgramPipelineInfoLog;
+ private IntPtr glBindImageTexture;
+ private IntPtr glGetBooleani_v;
+ private IntPtr glMemoryBarrier;
+ private IntPtr glMemoryBarrierByRegion;
+ private IntPtr glTexStorage2DMultisample;
+ private IntPtr glGetMultisamplefv;
+ private IntPtr glSampleMaski;
+ private IntPtr glGetTexLevelParameteriv;
+ private IntPtr glGetTexLevelParameterfv;
+ private IntPtr glBindVertexBuffer;
+ private IntPtr glVertexAttribFormat;
+ private IntPtr glVertexAttribIFormat;
+ private IntPtr glVertexAttribBinding;
+ private IntPtr glVertexBindingDivisor;
+ private IntPtr glBlendBarrier;
+ private IntPtr glCopyImageSubData;
+ private IntPtr glDebugMessageControl;
+ private IntPtr glDebugMessageInsert;
+ private IntPtr glDebugMessageCallback;
+ private IntPtr glGetDebugMessageLog;
+ private IntPtr glPushDebugGroup;
+ private IntPtr glPopDebugGroup;
+ private IntPtr glObjectLabel;
+ private IntPtr glGetObjectLabel;
+ private IntPtr glObjectPtrLabel;
+ private IntPtr glGetObjectPtrLabel;
+ private IntPtr glEnablei;
+ private IntPtr glDisablei;
+ private IntPtr glBlendEquationi;
+ private IntPtr glBlendEquationSeparatei;
+ private IntPtr glBlendFunci;
+ private IntPtr glBlendFuncSeparatei;
+ private IntPtr glColorMaski;
+ private IntPtr glIsEnabledi;
+ private IntPtr glDrawElementsBaseVertex;
+ private IntPtr glDrawRangeElementsBaseVertex;
+ private IntPtr glDrawElementsInstancedBaseVertex;
+ private IntPtr glFramebufferTexture;
+ private IntPtr glPrimitiveBoundingBox;
+ private IntPtr glGetGraphicsResetStatus;
+ private IntPtr glReadnPixels;
+ private IntPtr glGetnUniformfv;
+ private IntPtr glGetnUniformiv;
+ private IntPtr glGetnUniformuiv;
+ private IntPtr glMinSampleShading;
+ private IntPtr glPatchParameteri;
+ private IntPtr glTexParameterIiv;
+ private IntPtr glTexParameterIuiv;
+ private IntPtr glGetTexParameterIiv;
+ private IntPtr glGetTexParameterIuiv;
+ private IntPtr glSamplerParameterIiv;
+ private IntPtr glSamplerParameterIuiv;
+ private IntPtr glGetSamplerParameterIiv;
+ private IntPtr glGetSamplerParameterIuiv;
+ private IntPtr glTexBuffer;
+ private IntPtr glTexBufferRange;
+ private IntPtr glTexStorage3DMultisample;
+#pragma warning restore 0169
+ }
+ }
+}
+
--- /dev/null
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Threading;
+
+namespace SkiaSharp
+{
+ internal static class HandleDictionary
+ {
+ private static readonly Type IntPtrType = typeof (IntPtr);
+ private static readonly Type BoolType = typeof (bool);
+
+#if THROW_OBJECT_EXCEPTIONS
+ internal static readonly ConcurrentBag<Exception> exceptions = new ConcurrentBag<Exception> ();
+#endif
+
+ internal static readonly ConcurrentDictionary<Type, ConstructorInfo> constructors = new ConcurrentDictionary<Type, ConstructorInfo> ();
+ internal static readonly Dictionary<IntPtr, WeakReference> instances = new Dictionary<IntPtr, WeakReference> ();
+
+ internal static readonly ReaderWriterLockSlim instancesLock = new ReaderWriterLockSlim ();
+
+ /// <summary>
+ /// Retrieve the living instance if there is one, or null if not.
+ /// </summary>
+ /// <returns>The instance if it is alive, or null if there is none.</returns>
+ internal static bool GetInstance<TSkiaObject> (IntPtr handle, out TSkiaObject instance)
+ where TSkiaObject : SKObject
+ {
+ if (handle == IntPtr.Zero) {
+ instance = null;
+ return false;
+ }
+
+ instancesLock.EnterReadLock ();
+ try {
+ return GetInstanceNoLocks (handle, out instance);
+ } finally {
+ instancesLock.ExitReadLock ();
+ }
+ }
+
+ /// <summary>
+ /// Retrieve or create an instance for the native handle.
+ /// </summary>
+ /// <returns>The instance, or null if the handle was null.</returns>
+ internal static TSkiaObject GetObject<TSkiaObject, TSkiaImplementation> (IntPtr handle, bool owns = true, bool unrefExisting = true, bool refNew = false)
+ where TSkiaObject : SKObject
+ where TSkiaImplementation : SKObject, TSkiaObject
+ {
+ if (handle == IntPtr.Zero)
+ return null;
+
+ instancesLock.EnterUpgradeableReadLock ();
+ try {
+ if (GetInstanceNoLocks<TSkiaObject> (handle, out var instance)) {
+ // some object get automatically referenced on the native side,
+ // but managed code just has the same reference
+ if (unrefExisting && instance is ISKReferenceCounted refcnt) {
+#if THROW_OBJECT_EXCEPTIONS
+ if (refcnt.GetReferenceCount () == 1)
+ throw new InvalidOperationException (
+ $"About to unreference an object that has no references. " +
+ $"H: {handle.ToString ("x")} Type: {instance.GetType ()}");
+#endif
+ refcnt.SafeUnRef ();
+ }
+
+ return instance;
+ }
+
+ var type = typeof (TSkiaImplementation);
+ var constructor = constructors.GetOrAdd (type, t => GetConstructor (t));
+
+ // we don't need to go into a writable here as the object will do it in the Handle property
+ var obj = (TSkiaObject)constructor.Invoke (new object[] { handle, owns });
+ if (refNew && obj is ISKReferenceCounted toRef)
+ toRef.SafeRef ();
+ return obj;
+ } finally {
+ instancesLock.ExitUpgradeableReadLock ();
+ }
+
+ static ConstructorInfo GetConstructor (Type type)
+ {
+ var ctors = type.GetTypeInfo ().DeclaredConstructors;
+
+ foreach (var ctor in ctors) {
+ var param = ctor.GetParameters ();
+ if (param.Length == 2 && param[0].ParameterType == IntPtrType && param[1].ParameterType == BoolType)
+ return ctor;
+ }
+
+ throw new MissingMethodException ($"No constructor found for {type.FullName}.ctor(System.IntPtr, System.Boolean)");
+ }
+ }
+
+ /// <summary>
+ /// Retrieve the living instance if there is one, or null if not. This does not use locks.
+ /// </summary>
+ /// <returns>The instance if it is alive, or null if there is none.</returns>
+ private static bool GetInstanceNoLocks<TSkiaObject> (IntPtr handle, out TSkiaObject instance)
+ where TSkiaObject : SKObject
+ {
+ if (instances.TryGetValue (handle, out var weak) && weak.IsAlive) {
+ if (weak.Target is TSkiaObject match) {
+ if (!match.IsDisposed) {
+ instance = match;
+ return true;
+ }
+#if THROW_OBJECT_EXCEPTIONS
+ } else if (weak.Target is SKObject obj) {
+ if (!obj.IsDisposed && obj.OwnsHandle) {
+ throw new InvalidOperationException (
+ $"A managed object exists for the handle, but is not the expected type. " +
+ $"H: {handle.ToString ("x")} Type: ({obj.GetType ()}, {typeof (TSkiaObject)})");
+ }
+ } else if (weak.Target is object o) {
+ throw new InvalidOperationException (
+ $"An unknown object exists for the handle when trying to fetch an instance. " +
+ $"H: {handle.ToString ("x")} Type: ({o.GetType ()}, {typeof (TSkiaObject)})");
+#endif
+ }
+ }
+
+ instance = null;
+ return false;
+ }
+
+ /// <summary>
+ /// Registers the specified instance with the dictionary.
+ /// </summary>
+ internal static void RegisterHandle (IntPtr handle, SKObject instance)
+ {
+ if (handle == IntPtr.Zero || instance == null)
+ return;
+
+ SKObject objectToDispose = null;
+
+ instancesLock.EnterWriteLock ();
+ try {
+ if (instances.TryGetValue (handle, out var oldValue) && oldValue.Target is SKObject obj && !obj.IsDisposed) {
+#if THROW_OBJECT_EXCEPTIONS
+ if (obj.OwnsHandle) {
+ // a mostly recoverable error
+ // if there is a managed object, then maybe something happened and the native object is dead
+ throw new InvalidOperationException (
+ $"A managed object already exists for the specified native object. " +
+ $"H: {handle.ToString ("x")} Type: ({obj.GetType ()}, {instance.GetType ()})");
+ }
+#endif
+ // this means the ownership was handed off to a native object, so clean up the managed side
+ objectToDispose = obj;
+ }
+
+ instances[handle] = new WeakReference (instance);
+ } finally {
+ instancesLock.ExitWriteLock ();
+ }
+
+ // dispose the object we just replaced
+ objectToDispose?.DisposeInternal ();
+ }
+
+ /// <summary>
+ /// Removes the registered instance from the dictionary.
+ /// </summary>
+ internal static void DeregisterHandle (IntPtr handle, SKObject instance)
+ {
+ if (handle == IntPtr.Zero)
+ return;
+
+ instancesLock.EnterWriteLock ();
+ try {
+ var existed = instances.TryGetValue (handle, out var weak);
+ if (existed && (!weak.IsAlive || weak.Target == instance)) {
+ instances.Remove (handle);
+ } else {
+#if THROW_OBJECT_EXCEPTIONS
+ InvalidOperationException ex = null;
+ if (!existed) {
+ // the object may have been replaced
+
+ if (!instance.IsDisposed) {
+ // recoverable error
+ // there was no object there, but we are still alive
+ ex = new InvalidOperationException (
+ $"A managed object did not exist for the specified native object. " +
+ $"H: {handle.ToString ("x")} Type: {instance.GetType ()}");
+ }
+ } else if (weak.Target is SKObject o && o != instance) {
+ // there was an object in the dictionary, but it was NOT this object
+
+ if (!instance.IsDisposed) {
+ // recoverable error
+ // there was a new living object there, but we are still alive
+ ex = new InvalidOperationException (
+ $"Trying to remove a different object with the same native handle. " +
+ $"H: {handle.ToString ("x")} Type: ({o.GetType ()}, {instance.GetType ()})");
+ }
+ }
+ if (ex != null) {
+ if (instance.fromFinalizer)
+ exceptions.Add (ex);
+ else
+ throw ex;
+ }
+#endif
+ }
+ } finally {
+ instancesLock.ExitWriteLock ();
+ }
+ }
+ }
+}
--- /dev/null
+// Partial code copied from:
+// https://github.com/dotnet/runtime/blob/master/src/libraries/System.Private.CoreLib/src/System/HashCode.cs
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace SkiaSharp
+{
+ internal unsafe struct HashCode
+ {
+ private static readonly uint s_seed = GenerateGlobalSeed ();
+
+ private const uint Prime1 = 2654435761U;
+ private const uint Prime2 = 2246822519U;
+ private const uint Prime3 = 3266489917U;
+ private const uint Prime4 = 668265263U;
+ private const uint Prime5 = 374761393U;
+
+ private uint _v1, _v2, _v3, _v4;
+ private uint _queue1, _queue2, _queue3;
+ private uint _length;
+
+ private static unsafe uint GenerateGlobalSeed ()
+ {
+ var rnd = new Random ();
+ var result = rnd.Next ();
+ return unchecked((uint)result);
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static void Initialize (out uint v1, out uint v2, out uint v3, out uint v4)
+ {
+ v1 = s_seed + Prime1 + Prime2;
+ v2 = s_seed + Prime2;
+ v3 = s_seed;
+ v4 = s_seed - Prime1;
+ }
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint Round (uint hash, uint input) =>
+ RotateLeft (hash + input * Prime2, 13) * Prime1;
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint QueueRound (uint hash, uint queuedValue) =>
+ RotateLeft (hash + queuedValue * Prime3, 17) * Prime4;
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint MixState (uint v1, uint v2, uint v3, uint v4) =>
+ RotateLeft (v1, 1) + RotateLeft (v2, 7) + RotateLeft (v3, 12) + RotateLeft (v4, 18);
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint RotateLeft (uint value, int offset) =>
+ (value << offset) | (value >> (32 - offset));
+
+ private static uint MixEmptyState () =>
+ s_seed + Prime5;
+
+ [MethodImpl (MethodImplOptions.AggressiveInlining)]
+ private static uint MixFinal (uint hash)
+ {
+ hash ^= hash >> 15;
+ hash *= Prime2;
+ hash ^= hash >> 13;
+ hash *= Prime3;
+ hash ^= hash >> 16;
+ return hash;
+ }
+
+ public void Add (void* value) =>
+ Add (value == null ? 0 : ((IntPtr)value).GetHashCode ());
+
+ public void Add<T> (T value) =>
+ Add (value?.GetHashCode () ?? 0);
+
+ private void Add (int value)
+ {
+ uint val = (uint)value;
+
+ // Storing the value of _length locally shaves of quite a few bytes
+ // in the resulting machine code.
+ uint previousLength = _length++;
+ uint position = previousLength % 4;
+
+ // Switch can't be inlined.
+
+ if (position == 0)
+ _queue1 = val;
+ else if (position == 1)
+ _queue2 = val;
+ else if (position == 2)
+ _queue3 = val;
+ else // position == 3
+ {
+ if (previousLength == 3)
+ Initialize (out _v1, out _v2, out _v3, out _v4);
+
+ _v1 = Round (_v1, _queue1);
+ _v2 = Round (_v2, _queue2);
+ _v3 = Round (_v3, _queue3);
+ _v4 = Round (_v4, val);
+ }
+ }
+
+ public int ToHashCode ()
+ {
+ // Storing the value of _length locally shaves of quite a few bytes
+ // in the resulting machine code.
+ uint length = _length;
+
+ // position refers to the *next* queue position in this method, so
+ // position == 1 means that _queue1 is populated; _queue2 would have
+ // been populated on the next call to Add.
+ uint position = length % 4;
+
+ // If the length is less than 4, _v1 to _v4 don't contain anything
+ // yet. xxHash32 treats this differently.
+
+ uint hash = length < 4 ? MixEmptyState () : MixState (_v1, _v2, _v3, _v4);
+
+ // _length is incremented once per Add(Int32) and is therefore 4
+ // times too small (xxHash length is in bytes, not ints).
+
+ hash += length * 4;
+
+ // Mix what remains in the queue
+
+ // Switch can't be inlined right now, so use as few branches as
+ // possible by manually excluding impossible scenarios (position > 1
+ // is always false if position is not > 0).
+ if (position > 0) {
+ hash = QueueRound (hash, _queue1);
+ if (position > 1) {
+ hash = QueueRound (hash, _queue2);
+ if (position > 2)
+ hash = QueueRound (hash, _queue3);
+ }
+ }
+
+ hash = MixFinal (hash);
+ return (int)hash;
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public partial struct SKPoint
+ {
+ public static readonly SKPoint Empty;
+
+ public SKPoint (float x, float y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public readonly bool IsEmpty => this == Empty;
+
+ public readonly float Length => (float)Math.Sqrt (x * x + y * y);
+
+ public readonly float LengthSquared => x * x + y * y;
+
+ public void Offset (SKPoint p)
+ {
+ x += p.x;
+ y += p.y;
+ }
+
+ public void Offset (float dx, float dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ public readonly override string ToString () => $"{{X={x}, Y={y}}}";
+
+ public static SKPoint Normalize (SKPoint point)
+ {
+ var ls = point.x * point.x + point.y * point.y;
+ var invNorm = 1.0 / Math.Sqrt (ls);
+ return new SKPoint ((float)(point.x * invNorm), (float)(point.y * invNorm));
+ }
+
+ public static float Distance (SKPoint point, SKPoint other)
+ {
+ var dx = point.x - other.x;
+ var dy = point.y - other.y;
+ var ls = dx * dx + dy * dy;
+ return (float)Math.Sqrt (ls);
+ }
+
+ public static float DistanceSquared (SKPoint point, SKPoint other)
+ {
+ var dx = point.x - other.x;
+ var dy = point.y - other.y;
+ return dx * dx + dy * dy;
+ }
+
+ public static SKPoint Reflect (SKPoint point, SKPoint normal)
+ {
+ var dot = point.x * point.x + point.y * point.y;
+ return new SKPoint (
+ point.x - 2.0f * dot * normal.x,
+ point.y - 2.0f * dot * normal.y);
+ }
+
+ public static SKPoint Add (SKPoint pt, SKSizeI sz) => pt + sz;
+ public static SKPoint Add (SKPoint pt, SKSize sz) => pt + sz;
+ public static SKPoint Add (SKPoint pt, SKPointI sz) => pt + sz;
+ public static SKPoint Add (SKPoint pt, SKPoint sz) => pt + sz;
+
+ public static SKPoint Subtract (SKPoint pt, SKSizeI sz) => pt - sz;
+ public static SKPoint Subtract (SKPoint pt, SKSize sz) => pt - sz;
+ public static SKPoint Subtract (SKPoint pt, SKPointI sz) => pt - sz;
+ public static SKPoint Subtract (SKPoint pt, SKPoint sz) => pt - sz;
+
+ public static SKPoint operator + (SKPoint pt, SKSizeI sz) =>
+ new SKPoint (pt.x + sz.Width, pt.y + sz.Height);
+ public static SKPoint operator + (SKPoint pt, SKSize sz) =>
+ new SKPoint (pt.x + sz.Width, pt.y + sz.Height);
+ public static SKPoint operator + (SKPoint pt, SKPointI sz) =>
+ new SKPoint (pt.x + sz.X, pt.y + sz.Y);
+ public static SKPoint operator + (SKPoint pt, SKPoint sz) =>
+ new SKPoint (pt.x + sz.X, pt.y + sz.Y);
+
+ public static SKPoint operator - (SKPoint pt, SKSizeI sz) =>
+ new SKPoint (pt.X - sz.Width, pt.Y - sz.Height);
+ public static SKPoint operator - (SKPoint pt, SKSize sz) =>
+ new SKPoint (pt.X - sz.Width, pt.Y - sz.Height);
+ public static SKPoint operator - (SKPoint pt, SKPointI sz) =>
+ new SKPoint (pt.X - sz.X, pt.Y - sz.Y);
+ public static SKPoint operator - (SKPoint pt, SKPoint sz) =>
+ new SKPoint (pt.X - sz.X, pt.Y - sz.Y);
+ }
+
+ public partial struct SKPointI
+ {
+ public static readonly SKPointI Empty;
+
+ public SKPointI (SKSizeI sz)
+ {
+ x = sz.Width;
+ y = sz.Height;
+ }
+
+ public SKPointI (int x, int y)
+ {
+ this.x = x;
+ this.y = y;
+ }
+
+ public readonly bool IsEmpty => this == Empty;
+
+ public readonly int Length => (int)Math.Sqrt (x * x + y * y);
+
+ public readonly int LengthSquared => x * x + y * y;
+
+ public void Offset (SKPointI p)
+ {
+ x += p.X;
+ y += p.Y;
+ }
+
+ public void Offset (int dx, int dy)
+ {
+ x += dx;
+ y += dy;
+ }
+
+ public readonly override string ToString () => $"{{X={x},Y={y}}}";
+
+ public static SKPointI Normalize (SKPointI point)
+ {
+ var ls = point.x * point.x + point.y * point.y;
+ var invNorm = 1.0 / Math.Sqrt (ls);
+ return new SKPointI ((int)(point.x * invNorm), (int)(point.y * invNorm));
+ }
+
+ public static float Distance (SKPointI point, SKPointI other)
+ {
+ var dx = point.x - other.x;
+ var dy = point.y - other.y;
+ var ls = dx * dx + dy * dy;
+ return (float)Math.Sqrt (ls);
+ }
+
+ public static float DistanceSquared (SKPointI point, SKPointI other)
+ {
+ var dx = point.x - other.x;
+ var dy = point.y - other.y;
+ return dx * dx + dy * dy;
+ }
+
+ public static SKPointI Reflect (SKPointI point, SKPointI normal)
+ {
+ var dot = point.x * point.x + point.y * point.y;
+ return new SKPointI (
+ (int)(point.x - 2.0f * dot * normal.x),
+ (int)(point.y - 2.0f * dot * normal.y));
+ }
+
+ public static SKPointI Ceiling (SKPoint value)
+ {
+ int x, y;
+ checked {
+ x = (int)Math.Ceiling (value.X);
+ y = (int)Math.Ceiling (value.Y);
+ }
+
+ return new SKPointI (x, y);
+ }
+
+ public static SKPointI Round (SKPoint value)
+ {
+ int x, y;
+ checked {
+ x = (int)Math.Round (value.X);
+ y = (int)Math.Round (value.Y);
+ }
+
+ return new SKPointI (x, y);
+ }
+
+ public static SKPointI Truncate (SKPoint value)
+ {
+ int x, y;
+ checked {
+ x = (int)value.X;
+ y = (int)value.Y;
+ }
+
+ return new SKPointI (x, y);
+ }
+
+ public static SKPointI Add (SKPointI pt, SKSizeI sz) => pt + sz;
+ public static SKPointI Add (SKPointI pt, SKPointI sz) => pt + sz;
+
+ public static SKPointI Subtract (SKPointI pt, SKSizeI sz) => pt - sz;
+ public static SKPointI Subtract (SKPointI pt, SKPointI sz) => pt - sz;
+
+ public static SKPointI operator + (SKPointI pt, SKSizeI sz) =>
+ new SKPointI (pt.X + sz.Width, pt.Y + sz.Height);
+ public static SKPointI operator + (SKPointI pt, SKPointI sz) =>
+ new SKPointI (pt.X + sz.X, pt.Y + sz.Y);
+
+ public static SKPointI operator - (SKPointI pt, SKSizeI sz) =>
+ new SKPointI (pt.X - sz.Width, pt.Y - sz.Height);
+ public static SKPointI operator - (SKPointI pt, SKPointI sz) =>
+ new SKPointI (pt.X - sz.X, pt.Y - sz.Y);
+
+ public static explicit operator SKSizeI (SKPointI p) =>
+ new SKSizeI (p.X, p.Y);
+ public static implicit operator SKPoint (SKPointI p) =>
+ new SKPoint (p.X, p.Y);
+ }
+
+ public partial struct SKPoint3
+ {
+ public static readonly SKPoint3 Empty;
+
+ public SKPoint3 (float x, float y, float z)
+ {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public readonly bool IsEmpty => this == Empty;
+
+ public readonly override string ToString () => $"{{X={x}, Y={y}, Z={z}}}";
+
+ public static SKPoint3 Add (SKPoint3 pt, SKPoint3 sz) => pt + sz;
+
+ public static SKPoint3 Subtract (SKPoint3 pt, SKPoint3 sz) => pt - sz;
+
+ public static SKPoint3 operator + (SKPoint3 pt, SKPoint3 sz) =>
+ new SKPoint3 (pt.X + sz.X, pt.Y + sz.Y, pt.Z + sz.Z);
+
+ public static SKPoint3 operator - (SKPoint3 pt, SKPoint3 sz) =>
+ new SKPoint3 (pt.X - sz.X, pt.Y - sz.Y, pt.Z - sz.Z);
+ }
+
+ public partial struct SKSize
+ {
+ public static readonly SKSize Empty;
+
+ public SKSize (float width, float height)
+ {
+ w = width;
+ h = height;
+ }
+
+ public SKSize (SKPoint pt)
+ {
+ w = pt.X;
+ h = pt.Y;
+ }
+
+ public readonly bool IsEmpty => this == Empty;
+
+ public readonly SKPoint ToPoint () =>
+ new SKPoint (w, h);
+
+ public readonly SKSizeI ToSizeI ()
+ {
+ int w, h;
+ checked {
+ w = (int)this.w;
+ h = (int)this.h;
+ }
+
+ return new SKSizeI (w, h);
+ }
+
+ public readonly override string ToString () =>
+ $"{{Width={w}, Height={h}}}";
+
+ public static SKSize Add (SKSize sz1, SKSize sz2) => sz1 + sz2;
+
+ public static SKSize Subtract (SKSize sz1, SKSize sz2) => sz1 - sz2;
+
+ public static SKSize operator + (SKSize sz1, SKSize sz2) =>
+ new SKSize (sz1.Width + sz2.Width, sz1.Height + sz2.Height);
+
+ public static SKSize operator - (SKSize sz1, SKSize sz2) =>
+ new SKSize (sz1.Width - sz2.Width, sz1.Height - sz2.Height);
+
+ public static explicit operator SKPoint (SKSize size) =>
+ new SKPoint (size.Width, size.Height);
+ public static implicit operator SKSize (SKSizeI size) =>
+ new SKSize (size.Width, size.Height);
+ }
+
+ public partial struct SKSizeI
+ {
+ public static readonly SKSizeI Empty;
+
+ public SKSizeI (int width, int height)
+ {
+ w = width;
+ h = height;
+ }
+
+ public SKSizeI (SKPointI pt)
+ {
+ w = pt.X;
+ h = pt.Y;
+ }
+
+ public readonly bool IsEmpty => this == Empty;
+
+ public readonly SKPointI ToPointI () => new SKPointI (w, h);
+
+ public readonly override string ToString () =>
+ $"{{Width={w}, Height={h}}}";
+
+ public static SKSizeI Add (SKSizeI sz1, SKSizeI sz2) => sz1 + sz2;
+
+ public static SKSizeI Subtract (SKSizeI sz1, SKSizeI sz2) => sz1 - sz2;
+
+ public static SKSizeI operator + (SKSizeI sz1, SKSizeI sz2) =>
+ new SKSizeI (sz1.Width + sz2.Width, sz1.Height + sz2.Height);
+
+ public static SKSizeI operator - (SKSizeI sz1, SKSizeI sz2) =>
+ new SKSizeI (sz1.Width - sz2.Width, sz1.Height - sz2.Height);
+
+ public static explicit operator SKPointI (SKSizeI size) =>
+ new SKPointI (size.Width, size.Height);
+ }
+
+ public partial struct SKRect
+ {
+ public static readonly SKRect Empty;
+
+ public SKRect (float left, float top, float right, float bottom)
+ {
+ this.left = left;
+ this.right = right;
+ this.top = top;
+ this.bottom = bottom;
+ }
+
+ public readonly float MidX => left + (Width / 2f);
+
+ public readonly float MidY => top + (Height / 2f);
+
+ public readonly float Width => right - left;
+
+ public readonly float Height => bottom - top;
+
+ public readonly bool IsEmpty => this == Empty;
+
+ public SKSize Size {
+ readonly get => new SKSize (Width, Height);
+ set {
+ right = left + value.Width;
+ bottom = top + value.Height;
+ }
+ }
+
+ public SKPoint Location {
+ readonly get => new SKPoint (left, top);
+ set => this = SKRect.Create (value, Size);
+ }
+
+ public readonly SKRect Standardized {
+ get {
+ if (left > right) {
+ if (top > bottom) {
+ return new SKRect (right, bottom, left, top);
+ } else {
+ return new SKRect (right, top, left, bottom);
+ }
+ } else {
+ if (top > bottom) {
+ return new SKRect (left, bottom, right, top);
+ } else {
+ return new SKRect (left, top, right, bottom);
+ }
+ }
+ }
+ }
+
+ public readonly SKRect AspectFit (SKSize size) => AspectResize (size, true);
+
+ public readonly SKRect AspectFill (SKSize size) => AspectResize (size, false);
+
+ private readonly SKRect AspectResize (SKSize size, bool fit)
+ {
+ if (size.Width == 0 || size.Height == 0 || Width == 0 || Height == 0)
+ return Create (MidX, MidY, 0, 0);
+
+ var aspectWidth = size.Width;
+ var aspectHeight = size.Height;
+ var imgAspect = aspectWidth / aspectHeight;
+ var fullRectAspect = Width / Height;
+
+ var compare = fit ? (fullRectAspect > imgAspect) : (fullRectAspect < imgAspect);
+ if (compare) {
+ aspectHeight = Height;
+ aspectWidth = aspectHeight * imgAspect;
+ } else {
+ aspectWidth = Width;
+ aspectHeight = aspectWidth / imgAspect;
+ }
+ var aspectLeft = MidX - (aspectWidth / 2f);
+ var aspectTop = MidY - (aspectHeight / 2f);
+
+ return Create (aspectLeft, aspectTop, aspectWidth, aspectHeight);
+ }
+
+ public static SKRect Inflate (SKRect rect, float x, float y)
+ {
+ var r = new SKRect (rect.left, rect.top, rect.right, rect.bottom);
+ r.Inflate (x, y);
+ return r;
+ }
+
+ public void Inflate (SKSize size) =>
+ Inflate (size.Width, size.Height);
+
+ public void Inflate (float x, float y)
+ {
+ left -= x;
+ top -= y;
+ right += x;
+ bottom += y;
+ }
+
+ public static SKRect Intersect (SKRect a, SKRect b)
+ {
+ if (!a.IntersectsWithInclusive (b)) {
+ return Empty;
+ }
+ return new SKRect (
+ Math.Max (a.left, b.left),
+ Math.Max (a.top, b.top),
+ Math.Min (a.right, b.right),
+ Math.Min (a.bottom, b.bottom));
+ }
+
+ public void Intersect (SKRect rect) =>
+ this = Intersect (this, rect);
+
+ public static SKRect Union (SKRect a, SKRect b) =>
+ new SKRect (
+ Math.Min (a.left, b.left),
+ Math.Min (a.top, b.top),
+ Math.Max (a.right, b.right),
+ Math.Max (a.bottom, b.bottom));
+
+ public void Union (SKRect rect) =>
+ this = Union (this, rect);
+
+ public static implicit operator SKRect (SKRectI r) =>
+ new SKRect (r.Left, r.Top, r.Right, r.Bottom);
+
+ public readonly bool Contains (float x, float y) =>
+ (x >= left) && (x < right) && (y >= top) && (y < bottom);
+
+ public readonly bool Contains (SKPoint pt) =>
+ Contains (pt.X, pt.Y);
+
+ public readonly bool Contains (SKRect rect) =>
+ (left <= rect.left) && (right >= rect.right) &&
+ (top <= rect.top) && (bottom >= rect.bottom);
+
+ public readonly bool IntersectsWith (SKRect rect) =>
+ (left < rect.right) && (right > rect.left) && (top < rect.bottom) && (bottom > rect.top);
+
+ public readonly bool IntersectsWithInclusive (SKRect rect) =>
+ (left <= rect.right) && (right >= rect.left) && (top <= rect.bottom) && (bottom >= rect.top);
+
+ public void Offset (float x, float y)
+ {
+ left += x;
+ top += y;
+ right += x;
+ bottom += y;
+ }
+
+ public void Offset (SKPoint pos) => Offset (pos.X, pos.Y);
+
+ public readonly override string ToString () =>
+ $"{{Left={Left},Top={Top},Width={Width},Height={Height}}}";
+
+ public static SKRect Create (SKPoint location, SKSize size) =>
+ Create (location.X, location.Y, size.Width, size.Height);
+
+ public static SKRect Create (SKSize size) =>
+ Create (SKPoint.Empty, size);
+
+ public static SKRect Create (float width, float height) =>
+ new SKRect (SKPoint.Empty.X, SKPoint.Empty.Y, width, height);
+
+ public static SKRect Create (float x, float y, float width, float height) =>
+ new SKRect (x, y, x + width, y + height);
+ }
+
+ public partial struct SKRectI
+ {
+ public static readonly SKRectI Empty;
+
+ public SKRectI (int left, int top, int right, int bottom)
+ {
+ this.left = left;
+ this.right = right;
+ this.top = top;
+ this.bottom = bottom;
+ }
+
+ public readonly int MidX => left + (Width / 2);
+
+ public readonly int MidY => top + (Height / 2);
+
+ public readonly int Width => right - left;
+
+ public readonly int Height => bottom - top;
+
+ public readonly bool IsEmpty => this == Empty;
+
+ public SKSizeI Size {
+ readonly get => new SKSizeI (Width, Height);
+ set {
+ right = left + value.Width;
+ bottom = top + value.Height;
+ }
+ }
+
+ public SKPointI Location {
+ readonly get => new SKPointI (left, top);
+ set => this = SKRectI.Create (value, Size);
+ }
+
+ public readonly SKRectI Standardized {
+ get {
+ if (left > right) {
+ if (top > bottom) {
+ return new SKRectI (right, bottom, left, top);
+ } else {
+ return new SKRectI (right, top, left, bottom);
+ }
+ } else {
+ if (top > bottom) {
+ return new SKRectI (left, bottom, right, top);
+ } else {
+ return new SKRectI (left, top, right, bottom);
+ }
+ }
+ }
+ }
+
+ public readonly SKRectI AspectFit (SKSizeI size) =>
+ Truncate (((SKRect)this).AspectFit (size));
+
+ public readonly SKRectI AspectFill (SKSizeI size) =>
+ Truncate (((SKRect)this).AspectFill (size));
+
+ public static SKRectI Ceiling (SKRect value) =>
+ Ceiling (value, false);
+
+ public static SKRectI Ceiling (SKRect value, bool outwards)
+ {
+ int x, y, r, b;
+ checked {
+ x = (int)(outwards && value.Width > 0 ? Math.Floor (value.Left) : Math.Ceiling (value.Left));
+ y = (int)(outwards && value.Height > 0 ? Math.Floor (value.Top) : Math.Ceiling (value.Top));
+ r = (int)(outwards && value.Width < 0 ? Math.Floor (value.Right) : Math.Ceiling (value.Right));
+ b = (int)(outwards && value.Height < 0 ? Math.Floor (value.Bottom) : Math.Ceiling (value.Bottom));
+ }
+
+ return new SKRectI (x, y, r, b);
+ }
+
+ public static SKRectI Inflate (SKRectI rect, int x, int y)
+ {
+ var r = new SKRectI (rect.left, rect.top, rect.right, rect.bottom);
+ r.Inflate (x, y);
+ return r;
+ }
+
+ public void Inflate (SKSizeI size) =>
+ Inflate (size.Width, size.Height);
+
+ public void Inflate (int width, int height)
+ {
+ left -= width;
+ top -= height;
+ right += width;
+ bottom += height;
+ }
+
+ public static SKRectI Intersect (SKRectI a, SKRectI b)
+ {
+ if (!a.IntersectsWithInclusive (b))
+ return Empty;
+
+ return new SKRectI (
+ Math.Max (a.left, b.left),
+ Math.Max (a.top, b.top),
+ Math.Min (a.right, b.right),
+ Math.Min (a.bottom, b.bottom));
+ }
+
+ public void Intersect (SKRectI rect) =>
+ this = Intersect (this, rect);
+
+ public static SKRectI Round (SKRect value)
+ {
+ int x, y, r, b;
+ checked {
+ x = (int)Math.Round (value.Left);
+ y = (int)Math.Round (value.Top);
+ r = (int)Math.Round (value.Right);
+ b = (int)Math.Round (value.Bottom);
+ }
+
+ return new SKRectI (x, y, r, b);
+ }
+
+ public static SKRectI Floor (SKRect value) => Floor (value, false);
+
+ public static SKRectI Floor (SKRect value, bool inwards)
+ {
+ int x, y, r, b;
+ checked {
+ x = (int)(inwards && value.Width > 0 ? Math.Ceiling (value.Left) : Math.Floor (value.Left));
+ y = (int)(inwards && value.Height > 0 ? Math.Ceiling (value.Top) : Math.Floor (value.Top));
+ r = (int)(inwards && value.Width < 0 ? Math.Ceiling (value.Right) : Math.Floor (value.Right));
+ b = (int)(inwards && value.Height < 0 ? Math.Ceiling (value.Bottom) : Math.Floor (value.Bottom));
+ }
+
+ return new SKRectI (x, y, r, b);
+ }
+
+ public static SKRectI Truncate (SKRect value)
+ {
+ int x, y, r, b;
+ checked {
+ x = (int)value.Left;
+ y = (int)value.Top;
+ r = (int)value.Right;
+ b = (int)value.Bottom;
+ }
+
+ return new SKRectI (x, y, r, b);
+ }
+
+ public static SKRectI Union (SKRectI a, SKRectI b) =>
+ new SKRectI (
+ Math.Min (a.Left, b.Left),
+ Math.Min (a.Top, b.Top),
+ Math.Max (a.Right, b.Right),
+ Math.Max (a.Bottom, b.Bottom));
+
+ public void Union (SKRectI rect) =>
+ this = Union (this, rect);
+
+ public readonly bool Contains (int x, int y) =>
+ (x >= left) && (x < right) && (y >= top) && (y < bottom);
+
+ public readonly bool Contains (SKPointI pt) =>
+ Contains (pt.X, pt.Y);
+
+ public readonly bool Contains (SKRectI rect) =>
+ (left <= rect.left) && (right >= rect.right) &&
+ (top <= rect.top) && (bottom >= rect.bottom);
+
+ public readonly bool IntersectsWith (SKRectI rect) =>
+ (left < rect.right) && (right > rect.left) && (top < rect.bottom) && (bottom > rect.top);
+
+ public readonly bool IntersectsWithInclusive (SKRectI rect) =>
+ (left <= rect.right) && (right >= rect.left) && (top <= rect.bottom) && (bottom >= rect.top);
+
+ public void Offset (int x, int y)
+ {
+ left += x;
+ top += y;
+ right += x;
+ bottom += y;
+ }
+
+ public void Offset (SKPointI pos) => Offset (pos.X, pos.Y);
+
+ public readonly override string ToString () =>
+ $"{{Left={Left},Top={Top},Width={Width},Height={Height}}}";
+
+ public static SKRectI Create (SKSizeI size) =>
+ Create (SKPointI.Empty.X, SKPointI.Empty.Y, size.Width, size.Height);
+
+ public static SKRectI Create (SKPointI location, SKSizeI size) =>
+ Create (location.X, location.Y, size.Width, size.Height);
+
+ public static SKRectI Create (int width, int height) =>
+ new SKRectI (SKPointI.Empty.X, SKPointI.Empty.X, width, height);
+
+ public static SKRectI Create (int x, int y, int width, int height) =>
+ new SKRectI (x, y, x + width, y + height);
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ internal static class PlatformConfiguration
+ {
+ public static bool IsUnix { get; }
+ public static bool IsWindows { get; }
+
+ static PlatformConfiguration ()
+ {
+ IsUnix = Environment.OSVersion.Platform == PlatformID.MacOSX || Environment.OSVersion.Platform == PlatformID.Unix;
+ IsWindows = !IsUnix;
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ internal sealed class PreserveAttribute : Attribute
+ {
+ public bool AllMembers { get; set; }
+
+ public bool Conditional { get; set; }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SK3dView : SKObject
+ {
+ [Preserve]
+ internal SK3dView (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ public SK3dView ()
+ : this (SkiaApi.sk_3dview_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SK3dView instance.");
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_3dview_destroy (Handle);
+
+ // Matrix
+
+ public SKMatrix Matrix {
+ get {
+ var matrix = SKMatrix.MakeIdentity ();
+ GetMatrix (ref matrix);
+ return matrix;
+ }
+ }
+
+ public void GetMatrix (ref SKMatrix matrix)
+ {
+ fixed (SKMatrix* m = &matrix) {
+ SkiaApi.sk_3dview_get_matrix (Handle, m);
+ }
+ }
+
+ // Save
+
+ public void Save () =>
+ SkiaApi.sk_3dview_save (Handle);
+
+ // Restore
+
+ public void Restore () =>
+ SkiaApi.sk_3dview_restore (Handle);
+
+ // Translate
+
+ public void Translate (float x, float y, float z) =>
+ SkiaApi.sk_3dview_translate (Handle, x, y, z);
+
+ public void TranslateX (float x) =>
+ Translate (x, 0, 0);
+
+ public void TranslateY (float y) =>
+ Translate (0, y, 0);
+
+ public void TranslateZ (float z) =>
+ Translate (0, 0, z);
+
+ // Rotate*Degrees
+
+ public void RotateXDegrees (float degrees) =>
+ SkiaApi.sk_3dview_rotate_x_degrees (Handle, degrees);
+
+ public void RotateYDegrees (float degrees) =>
+ SkiaApi.sk_3dview_rotate_y_degrees (Handle, degrees);
+
+ public void RotateZDegrees (float degrees) =>
+ SkiaApi.sk_3dview_rotate_z_degrees (Handle, degrees);
+
+ // Rotate*Radians
+
+ public void RotateXRadians (float radians) =>
+ SkiaApi.sk_3dview_rotate_x_radians (Handle, radians);
+
+ public void RotateYRadians (float radians) =>
+ SkiaApi.sk_3dview_rotate_y_radians (Handle, radians);
+
+ public void RotateZRadians (float radians) =>
+ SkiaApi.sk_3dview_rotate_z_radians (Handle, radians);
+
+ // DotWithNormal
+
+ public float DotWithNormal (float dx, float dy, float dz) =>
+ SkiaApi.sk_3dview_dot_with_normal (Handle, dx, dy, dz);
+
+ // Apply
+
+ public void ApplyToCanvas (SKCanvas canvas)
+ {
+ if (canvas == null)
+ throw new ArgumentNullException (nameof (canvas));
+
+ SkiaApi.sk_3dview_apply_to_canvas (Handle, canvas.Handle);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace SkiaSharp
+{
+ public unsafe abstract class SKAbstractManagedStream : SKStreamAsset
+ {
+ private static readonly SKManagedStreamDelegates delegates;
+
+ private int fromNative;
+
+ static SKAbstractManagedStream ()
+ {
+ delegates = new SKManagedStreamDelegates {
+ fRead = ReadInternal,
+ fPeek = PeekInternal,
+ fIsAtEnd = IsAtEndInternal,
+ fHasPosition = HasPositionInternal,
+ fHasLength = HasLengthInternal,
+ fRewind = RewindInternal,
+ fGetPosition = GetPositionInternal,
+ fSeek = SeekInternal,
+ fMove = MoveInternal,
+ fGetLength = GetLengthInternal,
+ fDuplicate = DuplicateInternal,
+ fFork = ForkInternal,
+ fDestroy = DestroyInternal,
+ };
+ SkiaApi.sk_managedstream_set_procs (delegates);
+ }
+
+ protected SKAbstractManagedStream ()
+ : this (true)
+ {
+ }
+
+ protected SKAbstractManagedStream (bool owns)
+ : base (IntPtr.Zero, owns)
+ {
+ var ctx = DelegateProxies.CreateUserData (this, true);
+ Handle = SkiaApi.sk_managedstream_new ((void*)ctx);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative ()
+ {
+ if (Interlocked.CompareExchange (ref fromNative, 0, 0) == 0)
+ SkiaApi.sk_managedstream_destroy (Handle);
+ }
+
+ protected abstract IntPtr OnRead (IntPtr buffer, IntPtr size);
+
+ protected abstract IntPtr OnPeek (IntPtr buffer, IntPtr size);
+
+ protected abstract bool OnIsAtEnd ();
+
+ protected abstract bool OnHasPosition ();
+
+ protected abstract bool OnHasLength ();
+
+ protected abstract bool OnRewind ();
+
+ protected abstract IntPtr OnGetPosition ();
+
+ protected abstract IntPtr OnGetLength ();
+
+ protected abstract bool OnSeek (IntPtr position);
+
+ protected abstract bool OnMove (int offset);
+
+ protected abstract IntPtr OnCreateNew ();
+
+ protected virtual IntPtr OnFork ()
+ {
+ var stream = OnCreateNew ();
+ SkiaApi.sk_stream_seek (stream, SkiaApi.sk_stream_get_position (Handle));
+ return stream;
+ }
+
+ protected virtual IntPtr OnDuplicate () => OnCreateNew ();
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamReadProxyDelegate))]
+ private static IntPtr ReadInternal (IntPtr s, void* context, void* buffer, IntPtr size)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnRead ((IntPtr)buffer, size);
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamPeekProxyDelegate))]
+ private static IntPtr PeekInternal (IntPtr s, void* context, void* buffer, IntPtr size)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnPeek ((IntPtr)buffer, size);
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamIsAtEndProxyDelegate))]
+ private static bool IsAtEndInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnIsAtEnd ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamHasPositionProxyDelegate))]
+ private static bool HasPositionInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnHasPosition ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamHasLengthProxyDelegate))]
+ private static bool HasLengthInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnHasLength ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamRewindProxyDelegate))]
+ private static bool RewindInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnRewind ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamGetPositionProxyDelegate))]
+ private static IntPtr GetPositionInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnGetPosition ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamSeekProxyDelegate))]
+ private static bool SeekInternal (IntPtr s, void* context, IntPtr position)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnSeek (position);
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamMoveProxyDelegate))]
+ private static bool MoveInternal (IntPtr s, void* context, int offset)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnMove (offset);
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamGetLengthProxyDelegate))]
+ private static IntPtr GetLengthInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnGetLength ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamDuplicateProxyDelegate))]
+ private static IntPtr DuplicateInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnDuplicate ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamForkProxyDelegate))]
+ private static IntPtr ForkInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out _);
+ return stream.OnFork ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedStreamDestroyProxyDelegate))]
+ private static void DestroyInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedStream> ((IntPtr)context, out var gch);
+ if (stream != null) {
+ Interlocked.Exchange (ref stream.fromNative, 1);
+ stream.Dispose ();
+ }
+ gch.Free ();
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace SkiaSharp
+{
+ public unsafe abstract class SKAbstractManagedWStream : SKWStream
+ {
+ private static readonly SKManagedWStreamDelegates delegates;
+
+ private int fromNative;
+
+ static SKAbstractManagedWStream ()
+ {
+ delegates = new SKManagedWStreamDelegates {
+ fWrite = WriteInternal,
+ fFlush = FlushInternal,
+ fBytesWritten = BytesWrittenInternal,
+ fDestroy = DestroyInternal,
+ };
+
+ SkiaApi.sk_managedwstream_set_procs (delegates);
+ }
+
+ protected SKAbstractManagedWStream ()
+ : this (true)
+ {
+ }
+
+ protected SKAbstractManagedWStream (bool owns)
+ : base (IntPtr.Zero, owns)
+ {
+ var ctx = DelegateProxies.CreateUserData (this, true);
+ Handle = SkiaApi.sk_managedwstream_new ((void*)ctx);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative ()
+ {
+ if (Interlocked.CompareExchange (ref fromNative, 0, 0) == 0)
+ SkiaApi.sk_managedwstream_destroy (Handle);
+ }
+
+ protected abstract bool OnWrite (IntPtr buffer, IntPtr size);
+
+ protected abstract void OnFlush ();
+
+ protected abstract IntPtr OnBytesWritten ();
+
+ [MonoPInvokeCallback (typeof (SKManagedWStreamWriteProxyDelegate))]
+ private static bool WriteInternal (IntPtr s, void* context, void* buffer, IntPtr size)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedWStream> ((IntPtr)context, out _);
+ return stream.OnWrite ((IntPtr)buffer, size);
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedWStreamFlushProxyDelegate))]
+ private static void FlushInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedWStream> ((IntPtr)context, out _);
+ stream.OnFlush ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedWStreamBytesWrittenProxyDelegate))]
+ private static IntPtr BytesWrittenInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedWStream> ((IntPtr)context, out _);
+ return stream.OnBytesWritten ();
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedWStreamDestroyProxyDelegate))]
+ private static void DestroyInternal (IntPtr s, void* context)
+ {
+ var stream = DelegateProxies.GetUserData<SKAbstractManagedWStream> ((IntPtr)context, out var gch);
+ if (stream != null) {
+ Interlocked.Exchange (ref stream.fromNative, 1);
+ stream.Dispose ();
+ }
+ gch.Free ();
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ public class SKAutoCoInitialize : IDisposable
+ {
+ private long hResult;
+
+ public SKAutoCoInitialize()
+ {
+ if (PlatformConfiguration.IsWindows)
+ hResult = CoInitializeEx(IntPtr.Zero, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ else
+ hResult = S_OK;
+ }
+
+ public bool Initialized => hResult >= 0 || hResult == RPC_E_CHANGED_MODE;
+
+ public void Uninitialize()
+ {
+ if (hResult >= 0)
+ {
+ if (PlatformConfiguration.IsWindows)
+ CoUninitialize();
+
+ hResult = -1;
+ }
+ }
+
+ public void Dispose() => Uninitialize();
+
+ private const long S_OK = 0x00000000L;
+ private const long RPC_E_CHANGED_MODE = 0x80010106L;
+
+ private const uint COINIT_MULTITHREADED = 0x0;
+ private const uint COINIT_APARTMENTTHREADED = 0x2;
+ private const uint COINIT_DISABLE_OLE1DDE = 0x4;
+ private const uint COINIT_SPEED_OVER_MEMORY = 0x8;
+
+ [DllImport("ole32.dll", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
+ private static extern long CoInitializeEx([In, Optional] IntPtr pvReserved, [In] uint dwCoInit);
+
+ [DllImport("ole32.dll", CharSet = CharSet.Ansi, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
+ private static extern void CoUninitialize();
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.IO;
+
+namespace SkiaSharp
+{
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public enum SKBitmapResizeMethod
+ {
+ Box,
+ Triangle,
+ Lanczos3,
+ Hamming,
+ Mitchell
+ }
+
+ public static partial class SkiaExtensions
+ {
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public static SKFilterQuality ToFilterQuality (this SKBitmapResizeMethod method)
+ {
+ switch (method) {
+ case SKBitmapResizeMethod.Box:
+ case SKBitmapResizeMethod.Triangle:
+ return SKFilterQuality.Low;
+ case SKBitmapResizeMethod.Lanczos3:
+ return SKFilterQuality.Medium;
+ case SKBitmapResizeMethod.Hamming:
+ case SKBitmapResizeMethod.Mitchell:
+ return SKFilterQuality.High;
+ default:
+ return SKFilterQuality.Medium;
+ }
+ }
+ }
+
+ // TODO: keep in mind SKBitmap may be going away (according to Google)
+ // TODO: `ComputeIsOpaque` may be useful
+ // TODO: `GenerationID` may be useful
+ // TODO: `GetAddr` and `GetPixel` are confusing
+
+ public unsafe class SKBitmap : SKObject
+ {
+ private const string UnsupportedColorTypeMessage = "Setting the ColorTable is only supported for bitmaps with ColorTypes of Index8.";
+ private const string UnableToAllocatePixelsMessage = "Unable to allocate pixels for the bitmap.";
+
+ [Preserve]
+ internal SKBitmap (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKBitmap ()
+ : this (SkiaApi.sk_bitmap_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKBitmap instance.");
+ }
+ }
+
+ public SKBitmap (int width, int height, bool isOpaque = false)
+ : this (width, height, SKImageInfo.PlatformColorType, isOpaque ? SKAlphaType.Opaque : SKAlphaType.Premul)
+ {
+ }
+
+ public SKBitmap (int width, int height, SKColorType colorType, SKAlphaType alphaType)
+ : this (new SKImageInfo (width, height, colorType, alphaType))
+ {
+ }
+
+ public SKBitmap (SKImageInfo info)
+ : this (info, info.RowBytes)
+ {
+ }
+
+ public SKBitmap (SKImageInfo info, int rowBytes)
+ : this ()
+ {
+ if (!TryAllocPixels (info, rowBytes)) {
+ throw new Exception (UnableToAllocatePixelsMessage);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use SKBitmap(SKImageInfo, SKBitmapAllocFlags) instead.")]
+ public SKBitmap (SKImageInfo info, SKColorTable ctable, SKBitmapAllocFlags flags)
+ : this (info, SKBitmapAllocFlags.None)
+ {
+ }
+
+ public SKBitmap (SKImageInfo info, SKBitmapAllocFlags flags)
+ : this ()
+ {
+ if (!TryAllocPixels (info, flags)) {
+ throw new Exception (UnableToAllocatePixelsMessage);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use SKBitmap(SKImageInfo) instead.")]
+ public SKBitmap (SKImageInfo info, SKColorTable ctable)
+ : this (info, SKBitmapAllocFlags.None)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_bitmap_destructor (Handle);
+
+ // TryAllocPixels
+
+ public bool TryAllocPixels (SKImageInfo info)
+ {
+ return TryAllocPixels (info, info.RowBytes);
+ }
+
+ public bool TryAllocPixels (SKImageInfo info, int rowBytes)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ return SkiaApi.sk_bitmap_try_alloc_pixels (Handle, &cinfo, (IntPtr)rowBytes);
+ }
+
+ public bool TryAllocPixels (SKImageInfo info, SKBitmapAllocFlags flags)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ return SkiaApi.sk_bitmap_try_alloc_pixels_with_flags (Handle, &cinfo, (uint)flags);
+ }
+
+ // Reset
+
+ public void Reset ()
+ {
+ SkiaApi.sk_bitmap_reset (Handle);
+ }
+
+ // SetImmutable
+
+ public void SetImmutable ()
+ {
+ SkiaApi.sk_bitmap_set_immutable (Handle);
+ }
+
+ // Erase
+
+ public void Erase (SKColor color)
+ {
+ SkiaApi.sk_bitmap_erase (Handle, (uint)color);
+ }
+
+ public void Erase (SKColor color, SKRectI rect)
+ {
+ SkiaApi.sk_bitmap_erase_rect (Handle, (uint)color, &rect);
+ }
+
+ // GetAddr*
+
+ public byte GetAddr8 (int x, int y) => SkiaApi.sk_bitmap_get_addr_8 (Handle, x, y);
+
+ public UInt16 GetAddr16 (int x, int y) => SkiaApi.sk_bitmap_get_addr_16 (Handle, x, y);
+
+ public UInt32 GetAddr32 (int x, int y) => SkiaApi.sk_bitmap_get_addr_32 (Handle, x, y);
+
+ public IntPtr GetAddr (int x, int y) => (IntPtr)SkiaApi.sk_bitmap_get_addr (Handle, x, y);
+
+ // Pixels (color)
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use GetPixel(int, int) instead.")]
+ public SKPMColor GetIndex8Color (int x, int y)
+ {
+ return (SKPMColor)GetPixel (x, y);
+ }
+
+ public SKColor GetPixel (int x, int y)
+ {
+ return SkiaApi.sk_bitmap_get_pixel_color (Handle, x, y);
+ }
+
+ public void SetPixel (int x, int y, SKColor color)
+ {
+ SkiaApi.sk_bitmap_set_pixel_color (Handle, x, y, (uint)color);
+ }
+
+ // Copy
+
+ public bool CanCopyTo (SKColorType colorType)
+ {
+ // TODO: optimize as this does more work that we really want
+
+ if (colorType == SKColorType.Unknown)
+ return false;
+
+ using var bmp = new SKBitmap ();
+
+ var info = Info
+ .WithColorType (colorType)
+ .WithSize (1, 1);
+ return bmp.TryAllocPixels (info);
+ }
+
+ public SKBitmap Copy ()
+ {
+ return Copy (ColorType);
+ }
+
+ public SKBitmap Copy (SKColorType colorType)
+ {
+ var destination = new SKBitmap ();
+ if (!CopyTo (destination, colorType)) {
+ destination.Dispose ();
+ destination = null;
+ }
+ return destination;
+ }
+
+ public bool CopyTo (SKBitmap destination)
+ {
+ if (destination == null) {
+ throw new ArgumentNullException (nameof (destination));
+ }
+ return CopyTo (destination, ColorType);
+ }
+
+ public bool CopyTo (SKBitmap destination, SKColorType colorType)
+ {
+ if (destination == null)
+ throw new ArgumentNullException (nameof (destination));
+
+ if (colorType == SKColorType.Unknown)
+ return false;
+
+ using var srcPixmap = PeekPixels ();
+ if (srcPixmap == null)
+ return false;
+
+ using var temp = new SKBitmap ();
+
+ var dstInfo = srcPixmap.Info.WithColorType (colorType);
+ if (!temp.TryAllocPixels (dstInfo))
+ return false;
+
+ using var canvas = new SKCanvas (temp);
+
+ using var paint = new SKPaint {
+ Shader = ToShader (),
+ BlendMode = SKBlendMode.Src
+ };
+
+ canvas.DrawPaint (paint);
+
+ destination.Swap (temp);
+ return true;
+ }
+
+ // ExtractSubset
+
+ public bool ExtractSubset (SKBitmap destination, SKRectI subset)
+ {
+ if (destination == null) {
+ throw new ArgumentNullException (nameof (destination));
+ }
+ return SkiaApi.sk_bitmap_extract_subset (Handle, destination.Handle, &subset);
+ }
+
+ // ExtractAlpha
+
+ public bool ExtractAlpha (SKBitmap destination)
+ {
+ return ExtractAlpha (destination, null, out var offset);
+ }
+
+ public bool ExtractAlpha (SKBitmap destination, out SKPointI offset)
+ {
+ return ExtractAlpha (destination, null, out offset);
+ }
+
+ public bool ExtractAlpha (SKBitmap destination, SKPaint paint)
+ {
+ return ExtractAlpha (destination, paint, out var offset);
+ }
+
+ public bool ExtractAlpha (SKBitmap destination, SKPaint paint, out SKPointI offset)
+ {
+ if (destination == null) {
+ throw new ArgumentNullException (nameof (destination));
+ }
+ fixed (SKPointI* o = &offset) {
+ return SkiaApi.sk_bitmap_extract_alpha (Handle, destination.Handle, paint == null ? IntPtr.Zero : paint.Handle, o);
+ }
+ }
+
+ // properties
+
+ public bool ReadyToDraw => SkiaApi.sk_bitmap_ready_to_draw (Handle);
+
+ public SKImageInfo Info {
+ get {
+ SKImageInfoNative cinfo;
+ SkiaApi.sk_bitmap_get_info (Handle, &cinfo);
+ return SKImageInfoNative.ToManaged (ref cinfo);
+ }
+ }
+
+ public int Width {
+ get { return Info.Width; }
+ }
+
+ public int Height {
+ get { return Info.Height; }
+ }
+
+ public SKColorType ColorType {
+ get { return Info.ColorType; }
+ }
+
+ public SKAlphaType AlphaType {
+ get { return Info.AlphaType; }
+ }
+
+ public SKColorSpace ColorSpace {
+ get { return Info.ColorSpace; }
+ }
+
+ public int BytesPerPixel {
+ get { return Info.BytesPerPixel; }
+ }
+
+ public int RowBytes {
+ get { return (int)SkiaApi.sk_bitmap_get_row_bytes (Handle); }
+ }
+
+ public int ByteCount {
+ get { return (int)SkiaApi.sk_bitmap_get_byte_count (Handle); }
+ }
+
+ // *Pixels*
+
+ public IntPtr GetPixels () =>
+ GetPixels (out _);
+
+ public ReadOnlySpan<byte> GetPixelSpan ()
+ {
+ return new ReadOnlySpan<byte> ((void*)GetPixels (out var length), (int)length);
+ }
+
+ public IntPtr GetPixels (out IntPtr length)
+ {
+ fixed (IntPtr* l = &length) {
+ return (IntPtr)SkiaApi.sk_bitmap_get_pixels (Handle, l);
+ }
+ }
+
+ public void SetPixels (IntPtr pixels)
+ {
+ SkiaApi.sk_bitmap_set_pixels (Handle, (void*)pixels);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use SetPixels(IntPtr) instead.")]
+ public void SetPixels (IntPtr pixels, SKColorTable ct)
+ {
+ SetPixels (pixels);
+ }
+
+ // SetColorTable
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported.")]
+ public void SetColorTable (SKColorTable ct)
+ {
+ // no-op due to unsupperted action
+ }
+
+ // more properties
+
+ public byte[] Bytes {
+ get {
+ var array = GetPixelSpan ().ToArray ();
+ GC.KeepAlive (this);
+ return array;
+ }
+ }
+
+ public SKColor[] Pixels {
+ get {
+ var info = Info;
+ var pixels = new SKColor[info.Width * info.Height];
+ fixed (SKColor* p = pixels) {
+ SkiaApi.sk_bitmap_get_pixel_colors (Handle, (uint*)p);
+ }
+ return pixels;
+ }
+ set {
+ fixed (SKColor* v = value) {
+ SkiaApi.sk_bitmap_set_pixel_colors (Handle, (uint*)v);
+ }
+ }
+ }
+
+ public bool IsEmpty {
+ get { return Info.IsEmpty; }
+ }
+
+ public bool IsNull {
+ get { return SkiaApi.sk_bitmap_is_null (Handle); }
+ }
+
+ public bool DrawsNothing {
+ get { return IsEmpty || IsNull; }
+ }
+
+ public bool IsImmutable {
+ get { return SkiaApi.sk_bitmap_is_immutable (Handle); }
+ }
+
+ public bool IsVolatile {
+ get { return SkiaApi.sk_bitmap_is_volatile (Handle); }
+ set { SkiaApi.sk_bitmap_set_volatile (Handle, value); }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported.")]
+ public SKColorTable ColorTable => null;
+
+ // DecodeBounds
+
+ public static SKImageInfo DecodeBounds (Stream stream)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+ using (var codec = SKCodec.Create (stream)) {
+ return codec?.Info ?? SKImageInfo.Empty;
+ }
+ }
+
+ public static SKImageInfo DecodeBounds (SKStream stream)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+ using (var codec = SKCodec.Create (stream)) {
+ return codec?.Info ?? SKImageInfo.Empty;
+ }
+ }
+
+ public static SKImageInfo DecodeBounds (SKData data)
+ {
+ if (data == null) {
+ throw new ArgumentNullException (nameof (data));
+ }
+ using (var codec = SKCodec.Create (data)) {
+ return codec?.Info ?? SKImageInfo.Empty;
+ }
+ }
+
+ public static SKImageInfo DecodeBounds (string filename)
+ {
+ if (filename == null) {
+ throw new ArgumentNullException (nameof (filename));
+ }
+ using (var codec = SKCodec.Create (filename)) {
+ return codec?.Info ?? SKImageInfo.Empty;
+ }
+ }
+
+ public static SKImageInfo DecodeBounds (byte[] buffer) =>
+ DecodeBounds (buffer.AsSpan ());
+
+ public static SKImageInfo DecodeBounds (ReadOnlySpan<byte> buffer)
+ {
+ fixed (byte* b = buffer) {
+ using var skdata = SKData.Create ((IntPtr)b, buffer.Length);
+ using var codec = SKCodec.Create (skdata);
+ return codec?.Info ?? SKImageInfo.Empty;
+ }
+ }
+
+ // Decode
+
+ public static SKBitmap Decode (SKCodec codec)
+ {
+ if (codec == null) {
+ throw new ArgumentNullException (nameof (codec));
+ }
+ var info = codec.Info;
+ if (info.AlphaType == SKAlphaType.Unpremul) {
+ info.AlphaType = SKAlphaType.Premul;
+ }
+ // for backwards compatibility, remove the colorspace
+ info.ColorSpace = null;
+ return Decode (codec, info);
+ }
+
+ public static SKBitmap Decode (SKCodec codec, SKImageInfo bitmapInfo)
+ {
+ if (codec == null) {
+ throw new ArgumentNullException (nameof (codec));
+ }
+
+ var bitmap = new SKBitmap (bitmapInfo);
+ var result = codec.GetPixels (bitmapInfo, bitmap.GetPixels (out var length));
+ if (result != SKCodecResult.Success && result != SKCodecResult.IncompleteInput) {
+ bitmap.Dispose ();
+ bitmap = null;
+ }
+ return bitmap;
+ }
+
+ public static SKBitmap Decode (Stream stream)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+ using (var codec = SKCodec.Create (stream)) {
+ if (codec == null) {
+ return null;
+ }
+ return Decode (codec);
+ }
+ }
+
+ public static SKBitmap Decode (Stream stream, SKImageInfo bitmapInfo)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+ using (var codec = SKCodec.Create (stream)) {
+ if (codec == null) {
+ return null;
+ }
+ return Decode (codec, bitmapInfo);
+ }
+ }
+
+ public static SKBitmap Decode (SKStream stream)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+ using (var codec = SKCodec.Create (stream)) {
+ if (codec == null) {
+ return null;
+ }
+ return Decode (codec);
+ }
+ }
+
+ public static SKBitmap Decode (SKStream stream, SKImageInfo bitmapInfo)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+ using (var codec = SKCodec.Create (stream)) {
+ if (codec == null) {
+ return null;
+ }
+ return Decode (codec, bitmapInfo);
+ }
+ }
+
+ public static SKBitmap Decode (SKData data)
+ {
+ if (data == null) {
+ throw new ArgumentNullException (nameof (data));
+ }
+ using (var codec = SKCodec.Create (data)) {
+ if (codec == null) {
+ return null;
+ }
+ return Decode (codec);
+ }
+ }
+
+ public static SKBitmap Decode (SKData data, SKImageInfo bitmapInfo)
+ {
+ if (data == null) {
+ throw new ArgumentNullException (nameof (data));
+ }
+ using (var codec = SKCodec.Create (data)) {
+ if (codec == null) {
+ return null;
+ }
+ return Decode (codec, bitmapInfo);
+ }
+ }
+
+ public static SKBitmap Decode (string filename)
+ {
+ if (filename == null) {
+ throw new ArgumentNullException (nameof (filename));
+ }
+ using (var codec = SKCodec.Create (filename)) {
+ if (codec == null) {
+ return null;
+ }
+ return Decode (codec);
+ }
+ }
+
+ public static SKBitmap Decode (string filename, SKImageInfo bitmapInfo)
+ {
+ if (filename == null) {
+ throw new ArgumentNullException (nameof (filename));
+ }
+ using (var codec = SKCodec.Create (filename)) {
+ if (codec == null) {
+ return null;
+ }
+ return Decode (codec, bitmapInfo);
+ }
+ }
+
+ public static SKBitmap Decode (byte[] buffer) =>
+ Decode (buffer.AsSpan ());
+
+ public static SKBitmap Decode (byte[] buffer, SKImageInfo bitmapInfo) =>
+ Decode (buffer.AsSpan (), bitmapInfo);
+
+ public static SKBitmap Decode (ReadOnlySpan<byte> buffer)
+ {
+ fixed (byte* b = buffer) {
+ using var skdata = SKData.Create ((IntPtr)b, buffer.Length);
+ using var codec = SKCodec.Create (skdata);
+ return Decode (codec);
+ }
+ }
+
+ public static SKBitmap Decode (ReadOnlySpan<byte> buffer, SKImageInfo bitmapInfo)
+ {
+ fixed (byte* b = buffer) {
+ using var skdata = SKData.Create ((IntPtr)b, buffer.Length);
+ using var codec = SKCodec.Create (skdata);
+ return Decode (codec, bitmapInfo);
+ }
+ }
+
+ // InstallPixels
+
+ public bool InstallPixels (SKImageInfo info, IntPtr pixels)
+ {
+ return InstallPixels (info, pixels, info.RowBytes, null, null);
+ }
+
+ public bool InstallPixels (SKImageInfo info, IntPtr pixels, int rowBytes)
+ {
+ return InstallPixels (info, pixels, rowBytes, null, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use InstallPixels(SKImageInfo, IntPtr, int) instead.")]
+ public bool InstallPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKColorTable ctable)
+ {
+ return InstallPixels (info, pixels, rowBytes, null, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use InstallPixels(SKImageInfo, IntPtr, int, SKBitmapReleaseDelegate, object) instead.")]
+ public bool InstallPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKColorTable ctable, SKBitmapReleaseDelegate releaseProc, object context)
+ {
+ return InstallPixels (info, pixels, rowBytes, releaseProc, context);
+ }
+
+ public bool InstallPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKBitmapReleaseDelegate releaseProc)
+ {
+ return InstallPixels (info, pixels, rowBytes, releaseProc, null);
+ }
+
+ public bool InstallPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKBitmapReleaseDelegate releaseProc, object context)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ var del = releaseProc != null && context != null
+ ? new SKBitmapReleaseDelegate ((addr, _) => releaseProc (addr, context))
+ : releaseProc;
+ var proxy = DelegateProxies.Create (del, DelegateProxies.SKBitmapReleaseDelegateProxy, out _, out var ctx);
+ return SkiaApi.sk_bitmap_install_pixels (Handle, &cinfo, (void*)pixels, (IntPtr)rowBytes, proxy, (void*)ctx);
+ }
+
+ public bool InstallPixels (SKPixmap pixmap)
+ {
+ return SkiaApi.sk_bitmap_install_pixels_with_pixmap (Handle, pixmap.Handle);
+ }
+
+ // InstallMaskPixels
+
+ public bool InstallMaskPixels (SKMask mask)
+ {
+ return SkiaApi.sk_bitmap_install_mask_pixels (Handle, &mask);
+ }
+
+ // NotifyPixelsChanged
+
+ public void NotifyPixelsChanged ()
+ {
+ SkiaApi.sk_bitmap_notify_pixels_changed (Handle);
+ }
+
+ // PeekPixels
+
+ public SKPixmap PeekPixels ()
+ {
+ SKPixmap pixmap = new SKPixmap ();
+ var result = PeekPixels (pixmap);
+ if (result) {
+ return pixmap;
+ } else {
+ pixmap.Dispose ();
+ return null;
+ }
+ }
+
+ public bool PeekPixels (SKPixmap pixmap)
+ {
+ if (pixmap == null) {
+ throw new ArgumentNullException (nameof (pixmap));
+ }
+ var result = SkiaApi.sk_bitmap_peek_pixels (Handle, pixmap.Handle);
+ if (result)
+ pixmap.pixelSource = this;
+ return result;
+ }
+
+ // Resize
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Resize(SKImageInfo, SKFilterQuality) instead.")]
+ public SKBitmap Resize (SKImageInfo info, SKBitmapResizeMethod method) =>
+ Resize (info, method.ToFilterQuality ());
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use ScalePixels(SKBitmap, SKFilterQuality) instead.")]
+ public bool Resize (SKBitmap dst, SKBitmapResizeMethod method) =>
+ ScalePixels (dst, method.ToFilterQuality ());
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use ScalePixels(SKBitmap, SKFilterQuality) instead.")]
+ public static bool Resize (SKBitmap dst, SKBitmap src, SKBitmapResizeMethod method) =>
+ src.ScalePixels (dst, method.ToFilterQuality ());
+
+ public SKBitmap Resize (SKImageInfo info, SKFilterQuality quality)
+ {
+ var dst = new SKBitmap (info);
+ if (ScalePixels (dst, quality)) {
+ return dst;
+ } else {
+ dst.Dispose ();
+ return null;
+ }
+ }
+
+ public SKBitmap Resize (SKSizeI size, SKFilterQuality quality) =>
+ Resize (Info.WithSize (size), quality);
+
+ // ScalePixels
+
+ public bool ScalePixels (SKBitmap destination, SKFilterQuality quality)
+ {
+ if (destination == null) {
+ throw new ArgumentNullException (nameof (destination));
+ }
+
+ using (var dstPix = destination.PeekPixels ()) {
+ return ScalePixels (dstPix, quality);
+ }
+ }
+
+ public bool ScalePixels (SKPixmap destination, SKFilterQuality quality)
+ {
+ if (destination == null) {
+ throw new ArgumentNullException (nameof (destination));
+ }
+
+ using (var srcPix = PeekPixels ()) {
+ return srcPix.ScalePixels (destination, quality);
+ }
+ }
+
+ // From/ToImage
+
+ public static SKBitmap FromImage (SKImage image)
+ {
+ if (image == null) {
+ throw new ArgumentNullException (nameof (image));
+ }
+
+ var info = new SKImageInfo (image.Width, image.Height, SKImageInfo.PlatformColorType, image.AlphaType);
+ var bmp = new SKBitmap (info);
+ if (!image.ReadPixels (info, bmp.GetPixels (), info.RowBytes, 0, 0)) {
+ bmp.Dispose ();
+ bmp = null;
+ }
+ return bmp;
+ }
+
+ // Encode
+
+ public SKData Encode (SKEncodedImageFormat format, int quality)
+ {
+ using var pixmap = PeekPixels ();
+ return pixmap?.Encode (format, quality);
+ }
+
+ public bool Encode (Stream dst, SKEncodedImageFormat format, int quality)
+ {
+ using var wrapped = new SKManagedWStream (dst);
+ return Encode (wrapped, format, quality);
+ }
+
+ public bool Encode (SKWStream dst, SKEncodedImageFormat format, int quality)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ using var pixmap = PeekPixels ();
+ return pixmap?.Encode (dst, format, quality) ?? false;
+ }
+
+ // Swap
+
+ private void Swap (SKBitmap other)
+ {
+ SkiaApi.sk_bitmap_swap (Handle, other.Handle);
+ }
+
+ // ToShader
+
+ public SKShader ToShader () =>
+ ToShader (SKShaderTileMode.Clamp, SKShaderTileMode.Clamp);
+
+ public SKShader ToShader (SKShaderTileMode tmx, SKShaderTileMode tmy) =>
+ SKShader.CreateBitmap (this, tmx, tmy);
+
+ public SKShader ToShader (SKShaderTileMode tmx, SKShaderTileMode tmy, SKMatrix localMatrix) =>
+ SKShader.CreateBitmap (this, tmx, tmy, localMatrix);
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ // TODO: carefully consider the `PeekPixels`, `ReadPixels`
+
+ public unsafe class SKCanvas : SKObject
+ {
+ private const int PatchCornerCount = 4;
+ private const int PatchCubicsCount = 12;
+
+ [Preserve]
+ internal SKCanvas (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKCanvas (SKBitmap bitmap)
+ : this (IntPtr.Zero, true)
+ {
+ if (bitmap == null)
+ throw new ArgumentNullException (nameof (bitmap));
+ Handle = SkiaApi.sk_canvas_new_from_bitmap (bitmap.Handle);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_canvas_destroy (Handle);
+
+ public void Discard () =>
+ SkiaApi.sk_canvas_discard (Handle);
+
+ // QuickReject
+
+ public bool QuickReject (SKRect rect)
+ {
+ return SkiaApi.sk_canvas_quick_reject (Handle, &rect);
+ }
+
+ public bool QuickReject (SKPath path)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+ return path.IsEmpty || QuickReject (path.Bounds);
+ }
+
+ // Save*
+
+ public int Save ()
+ {
+ if (Handle == IntPtr.Zero)
+ throw new ObjectDisposedException ("SKCanvas");
+ return SkiaApi.sk_canvas_save (Handle);
+ }
+
+ public int SaveLayer (SKRect limit, SKPaint paint)
+ {
+ return SkiaApi.sk_canvas_save_layer (Handle, &limit, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ public int SaveLayer (SKPaint paint)
+ {
+ return SkiaApi.sk_canvas_save_layer (Handle, null, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ public int SaveLayer () =>
+ SaveLayer (null);
+
+ // DrawColor
+
+ public void DrawColor (SKColor color, SKBlendMode mode = SKBlendMode.Src)
+ {
+ SkiaApi.sk_canvas_draw_color (Handle, (uint)color, mode);
+ }
+
+ // DrawLine
+
+ public void DrawLine (SKPoint p0, SKPoint p1, SKPaint paint)
+ {
+ DrawLine (p0.X, p0.Y, p1.X, p1.Y, paint);
+ }
+
+ public void DrawLine (float x0, float y0, float x1, float y1, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_line (Handle, x0, y0, x1, y1, paint.Handle);
+ }
+
+ // Clear
+
+ public void Clear ()
+ {
+ DrawColor (SKColors.Empty, SKBlendMode.Src);
+ }
+
+ public void Clear (SKColor color)
+ {
+ DrawColor (color, SKBlendMode.Src);
+ }
+
+ // Restore*
+
+ public void Restore ()
+ {
+ SkiaApi.sk_canvas_restore (Handle);
+ }
+
+ public void RestoreToCount (int count)
+ {
+ SkiaApi.sk_canvas_restore_to_count (Handle, count);
+ }
+
+ // Translate
+
+ public void Translate (float dx, float dy)
+ {
+ SkiaApi.sk_canvas_translate (Handle, dx, dy);
+ }
+
+ public void Translate (SKPoint point)
+ {
+ SkiaApi.sk_canvas_translate (Handle, point.X, point.Y);
+ }
+
+ // Scale
+
+ public void Scale (float s)
+ {
+ SkiaApi.sk_canvas_scale (Handle, s, s);
+ }
+
+ public void Scale (float sx, float sy)
+ {
+ SkiaApi.sk_canvas_scale (Handle, sx, sy);
+ }
+
+ public void Scale (SKPoint size)
+ {
+ SkiaApi.sk_canvas_scale (Handle, size.X, size.Y);
+ }
+
+ public void Scale (float sx, float sy, float px, float py)
+ {
+ Translate (px, py);
+ Scale (sx, sy);
+ Translate (-px, -py);
+ }
+
+ // Rotate*
+
+ public void RotateDegrees (float degrees)
+ {
+ SkiaApi.sk_canvas_rotate_degrees (Handle, degrees);
+ }
+
+ public void RotateRadians (float radians)
+ {
+ SkiaApi.sk_canvas_rotate_radians (Handle, radians);
+ }
+
+ public void RotateDegrees (float degrees, float px, float py)
+ {
+ Translate (px, py);
+ RotateDegrees (degrees);
+ Translate (-px, -py);
+ }
+
+ public void RotateRadians (float radians, float px, float py)
+ {
+ Translate (px, py);
+ RotateRadians (radians);
+ Translate (-px, -py);
+ }
+
+ // Skew
+
+ public void Skew (float sx, float sy)
+ {
+ SkiaApi.sk_canvas_skew (Handle, sx, sy);
+ }
+
+ public void Skew (SKPoint skew)
+ {
+ SkiaApi.sk_canvas_skew (Handle, skew.X, skew.Y);
+ }
+
+ // Concat
+
+ public void Concat (ref SKMatrix m)
+ {
+ fixed (SKMatrix* ptr = &m) {
+ SkiaApi.sk_canvas_concat (Handle, ptr);
+ }
+ }
+
+ // Clip*
+
+ public void ClipRect (SKRect rect, SKClipOperation operation = SKClipOperation.Intersect, bool antialias = false)
+ {
+ SkiaApi.sk_canvas_clip_rect_with_operation (Handle, &rect, operation, antialias);
+ }
+
+ public void ClipRoundRect (SKRoundRect rect, SKClipOperation operation = SKClipOperation.Intersect, bool antialias = false)
+ {
+ if (rect == null)
+ throw new ArgumentNullException (nameof (rect));
+
+ SkiaApi.sk_canvas_clip_rrect_with_operation (Handle, rect.Handle, operation, antialias);
+ }
+
+ public void ClipPath (SKPath path, SKClipOperation operation = SKClipOperation.Intersect, bool antialias = false)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+
+ SkiaApi.sk_canvas_clip_path_with_operation (Handle, path.Handle, operation, antialias);
+ }
+
+ public void ClipRegion (SKRegion region, SKClipOperation operation = SKClipOperation.Intersect)
+ {
+ if (region == null)
+ throw new ArgumentNullException (nameof (region));
+
+ SkiaApi.sk_canvas_clip_region (Handle, region.Handle, operation);
+ }
+
+ public SKRect LocalClipBounds {
+ get {
+ GetLocalClipBounds (out var bounds);
+ return bounds;
+ }
+ }
+
+ public SKRectI DeviceClipBounds {
+ get {
+ GetDeviceClipBounds (out var bounds);
+ return bounds;
+ }
+ }
+
+ public bool IsClipEmpty => SkiaApi.sk_canvas_is_clip_empty (Handle);
+
+ public bool IsClipRect => SkiaApi.sk_canvas_is_clip_rect (Handle);
+
+ public bool GetLocalClipBounds (out SKRect bounds)
+ {
+ fixed (SKRect* b = &bounds) {
+ return SkiaApi.sk_canvas_get_local_clip_bounds (Handle, b);
+ }
+ }
+
+ public bool GetDeviceClipBounds (out SKRectI bounds)
+ {
+ fixed (SKRectI* b = &bounds) {
+ return SkiaApi.sk_canvas_get_device_clip_bounds (Handle, b);
+ }
+ }
+
+ // DrawPaint
+
+ public void DrawPaint (SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_paint (Handle, paint.Handle);
+ }
+
+ // DrawRegion
+
+ public void DrawRegion (SKRegion region, SKPaint paint)
+ {
+ if (region == null)
+ throw new ArgumentNullException (nameof (region));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_region (Handle, region.Handle, paint.Handle);
+ }
+
+ // DrawRect
+
+ public void DrawRect (float x, float y, float w, float h, SKPaint paint)
+ {
+ DrawRect (SKRect.Create (x, y, w, h), paint);
+ }
+
+ public void DrawRect (SKRect rect, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_rect (Handle, &rect, paint.Handle);
+ }
+
+ // DrawRoundRect
+
+ public void DrawRoundRect (SKRoundRect rect, SKPaint paint)
+ {
+ if (rect == null)
+ throw new ArgumentNullException (nameof (rect));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_rrect (Handle, rect.Handle, paint.Handle);
+ }
+
+ public void DrawRoundRect (float x, float y, float w, float h, float rx, float ry, SKPaint paint)
+ {
+ DrawRoundRect (SKRect.Create (x, y, w, h), rx, ry, paint);
+ }
+
+ public void DrawRoundRect (SKRect rect, float rx, float ry, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_round_rect (Handle, &rect, rx, ry, paint.Handle);
+ }
+
+ public void DrawRoundRect (SKRect rect, SKSize r, SKPaint paint)
+ {
+ DrawRoundRect (rect, r.Width, r.Height, paint);
+ }
+
+ // DrawOval
+
+ public void DrawOval (float cx, float cy, float rx, float ry, SKPaint paint)
+ {
+ DrawOval (new SKRect (cx - rx, cy - ry, cx + rx, cy + ry), paint);
+ }
+
+ public void DrawOval (SKPoint c, SKSize r, SKPaint paint)
+ {
+ DrawOval (c.X, c.Y, r.Width, r.Height, paint);
+ }
+
+ public void DrawOval (SKRect rect, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_oval (Handle, &rect, paint.Handle);
+ }
+
+ // DrawCircle
+
+ public void DrawCircle (float cx, float cy, float radius, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_circle (Handle, cx, cy, radius, paint.Handle);
+ }
+
+ public void DrawCircle (SKPoint c, float radius, SKPaint paint)
+ {
+ DrawCircle (c.X, c.Y, radius, paint);
+ }
+
+ // DrawPath
+
+ public void DrawPath (SKPath path, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+ SkiaApi.sk_canvas_draw_path (Handle, path.Handle, paint.Handle);
+ }
+
+ // DrawPoints
+
+ public void DrawPoints (SKPointMode mode, SKPoint[] points, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+ fixed (SKPoint* p = points) {
+ SkiaApi.sk_canvas_draw_points (Handle, mode, (IntPtr)points.Length, p, paint.Handle);
+ }
+ }
+
+ // DrawPoint
+
+ public void DrawPoint (SKPoint p, SKPaint paint)
+ {
+ DrawPoint (p.X, p.Y, paint);
+ }
+
+ public void DrawPoint (float x, float y, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_point (Handle, x, y, paint.Handle);
+ }
+
+ public void DrawPoint (SKPoint p, SKColor color)
+ {
+ DrawPoint (p.X, p.Y, color);
+ }
+
+ public void DrawPoint (float x, float y, SKColor color)
+ {
+ using (var paint = new SKPaint { Color = color }) {
+ DrawPoint (x, y, paint);
+ }
+ }
+
+ // DrawImage
+
+ public void DrawImage (SKImage image, SKPoint p, SKPaint paint = null)
+ {
+ DrawImage (image, p.X, p.Y, paint);
+ }
+
+ public void DrawImage (SKImage image, float x, float y, SKPaint paint = null)
+ {
+ if (image == null)
+ throw new ArgumentNullException (nameof (image));
+ SkiaApi.sk_canvas_draw_image (Handle, image.Handle, x, y, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ public void DrawImage (SKImage image, SKRect dest, SKPaint paint = null)
+ {
+ if (image == null)
+ throw new ArgumentNullException (nameof (image));
+ SkiaApi.sk_canvas_draw_image_rect (Handle, image.Handle, null, &dest, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ public void DrawImage (SKImage image, SKRect source, SKRect dest, SKPaint paint = null)
+ {
+ if (image == null)
+ throw new ArgumentNullException (nameof (image));
+ SkiaApi.sk_canvas_draw_image_rect (Handle, image.Handle, &source, &dest, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ // DrawPicture
+
+ public void DrawPicture (SKPicture picture, float x, float y, SKPaint paint = null)
+ {
+ var matrix = SKMatrix.MakeTranslation (x, y);
+ DrawPicture (picture, ref matrix, paint);
+ }
+
+ public void DrawPicture (SKPicture picture, SKPoint p, SKPaint paint = null)
+ {
+ DrawPicture (picture, p.X, p.Y, paint);
+ }
+
+ public void DrawPicture (SKPicture picture, ref SKMatrix matrix, SKPaint paint = null)
+ {
+ if (picture == null)
+ throw new ArgumentNullException (nameof (picture));
+ fixed (SKMatrix* m = &matrix) {
+ SkiaApi.sk_canvas_draw_picture (Handle, picture.Handle, m, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+ }
+
+ public void DrawPicture (SKPicture picture, SKPaint paint = null)
+ {
+ if (picture == null)
+ throw new ArgumentNullException (nameof (picture));
+ SkiaApi.sk_canvas_draw_picture (Handle, picture.Handle, null, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ // DrawDrawable
+
+ public void DrawDrawable (SKDrawable drawable, ref SKMatrix matrix)
+ {
+ if (drawable == null)
+ throw new ArgumentNullException (nameof (drawable));
+ fixed (SKMatrix* m = &matrix) {
+ SkiaApi.sk_canvas_draw_drawable (Handle, drawable.Handle, m);
+ }
+ }
+
+ public void DrawDrawable (SKDrawable drawable, float x, float y)
+ {
+ if (drawable == null)
+ throw new ArgumentNullException (nameof (drawable));
+ var matrix = SKMatrix.MakeTranslation (x, y);
+ DrawDrawable (drawable, ref matrix);
+ }
+
+ public void DrawDrawable (SKDrawable drawable, SKPoint p)
+ {
+ if (drawable == null)
+ throw new ArgumentNullException (nameof (drawable));
+ var matrix = SKMatrix.MakeTranslation (p.X, p.Y);
+ DrawDrawable (drawable, ref matrix);
+ }
+
+ // DrawBitmap
+
+ public void DrawBitmap (SKBitmap bitmap, SKPoint p, SKPaint paint = null)
+ {
+ DrawBitmap (bitmap, p.X, p.Y, paint);
+ }
+
+ public void DrawBitmap (SKBitmap bitmap, float x, float y, SKPaint paint = null)
+ {
+ if (bitmap == null)
+ throw new ArgumentNullException (nameof (bitmap));
+ SkiaApi.sk_canvas_draw_bitmap (Handle, bitmap.Handle, x, y, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ public void DrawBitmap (SKBitmap bitmap, SKRect dest, SKPaint paint = null)
+ {
+ if (bitmap == null)
+ throw new ArgumentNullException (nameof (bitmap));
+ SkiaApi.sk_canvas_draw_bitmap_rect (Handle, bitmap.Handle, null, &dest, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ public void DrawBitmap (SKBitmap bitmap, SKRect source, SKRect dest, SKPaint paint = null)
+ {
+ if (bitmap == null)
+ throw new ArgumentNullException (nameof (bitmap));
+ SkiaApi.sk_canvas_draw_bitmap_rect (Handle, bitmap.Handle, &source, &dest, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ // DrawSurface
+
+ public void DrawSurface (SKSurface surface, SKPoint p, SKPaint paint = null)
+ {
+ DrawSurface (surface, p.X, p.Y, paint);
+ }
+
+ public void DrawSurface (SKSurface surface, float x, float y, SKPaint paint = null)
+ {
+ if (surface == null)
+ throw new ArgumentNullException (nameof (surface));
+
+ surface.Draw (this, x, y, paint);
+ }
+
+ // DrawText (SKTextBlob)
+
+ public void DrawText (SKTextBlob text, float x, float y, SKPaint paint)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ SkiaApi.sk_canvas_draw_text_blob (Handle, text.Handle, x, y, paint.Handle);
+ }
+
+ // DrawText
+
+ public void DrawText (string text, SKPoint p, SKPaint paint)
+ {
+ DrawText (text, p.X, p.Y, paint);
+ }
+
+ public void DrawText (string text, float x, float y, SKPaint paint)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ var bytes = StringUtilities.GetEncodedText (text, paint.TextEncoding);
+ DrawText (bytes, x, y, paint);
+ }
+
+ public void DrawText (byte[] text, SKPoint p, SKPaint paint)
+ {
+ DrawText (text, p.X, p.Y, paint);
+ }
+
+ public void DrawText (byte[] text, float x, float y, SKPaint paint)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ fixed (byte* t = text) {
+ SkiaApi.sk_canvas_draw_text (Handle, t, (IntPtr)text.Length, x, y, paint.Handle);
+ }
+ }
+
+ public void DrawText (IntPtr buffer, int length, SKPoint p, SKPaint paint)
+ {
+ DrawText (buffer, length, p.X, p.Y, paint);
+ }
+
+ public void DrawText (IntPtr buffer, int length, float x, float y, SKPaint paint)
+ {
+ if (buffer == IntPtr.Zero && length != 0)
+ throw new ArgumentNullException (nameof (buffer));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ SkiaApi.sk_canvas_draw_text (Handle, (void*)buffer, (IntPtr)length, x, y, paint.Handle);
+ }
+
+ // DrawPositionedText
+
+ public void DrawPositionedText (string text, SKPoint[] points, SKPaint paint)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+
+ var bytes = StringUtilities.GetEncodedText (text, paint.TextEncoding);
+ DrawPositionedText (bytes, points, paint);
+ }
+
+ public void DrawPositionedText (byte[] text, SKPoint[] points, SKPaint paint)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+
+ fixed (byte* t = text)
+ fixed (SKPoint* p = points) {
+ SkiaApi.sk_canvas_draw_pos_text (Handle, t, (IntPtr)text.Length, p, paint.Handle);
+ }
+ }
+
+ public void DrawPositionedText (IntPtr buffer, int length, SKPoint[] points, SKPaint paint)
+ {
+ if (buffer == IntPtr.Zero && length != 0)
+ throw new ArgumentNullException (nameof (buffer));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+
+ fixed (SKPoint* p = points) {
+ SkiaApi.sk_canvas_draw_pos_text (Handle, (void*)buffer, (IntPtr)length, p, paint.Handle);
+ }
+ }
+
+ // DrawTextOnPath
+
+ public void DrawTextOnPath (string text, SKPath path, SKPoint offset, SKPaint paint)
+ {
+ DrawTextOnPath (text, path, offset.X, offset.Y, paint);
+ }
+
+ public void DrawTextOnPath (string text, SKPath path, float hOffset, float vOffset, SKPaint paint)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ var bytes = StringUtilities.GetEncodedText (text, paint.TextEncoding);
+ DrawTextOnPath (bytes, path, hOffset, vOffset, paint);
+ }
+
+ public void DrawTextOnPath (byte[] text, SKPath path, SKPoint offset, SKPaint paint)
+ {
+ DrawTextOnPath (text, path, offset.X, offset.Y, paint);
+ }
+
+ public void DrawTextOnPath (byte[] text, SKPath path, float hOffset, float vOffset, SKPaint paint)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ fixed (byte* t = text) {
+ SkiaApi.sk_canvas_draw_text_on_path (Handle, t, (IntPtr)text.Length, path.Handle, hOffset, vOffset, paint.Handle);
+ }
+ }
+
+ public void DrawTextOnPath (IntPtr buffer, int length, SKPath path, SKPoint offset, SKPaint paint)
+ {
+ DrawTextOnPath (buffer, length, path, offset.X, offset.Y, paint);
+ }
+
+ public void DrawTextOnPath (IntPtr buffer, int length, SKPath path, float hOffset, float vOffset, SKPaint paint)
+ {
+ if (buffer == IntPtr.Zero && length != 0)
+ throw new ArgumentNullException (nameof (buffer));
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ SkiaApi.sk_canvas_draw_text_on_path (Handle, (void*)buffer, (IntPtr)length, path.Handle, hOffset, vOffset, paint.Handle);
+ }
+
+ // Flush
+
+ public void Flush ()
+ {
+ SkiaApi.sk_canvas_flush (Handle);
+ }
+
+ // Draw*Annotation
+
+ public void DrawAnnotation (SKRect rect, string key, SKData value)
+ {
+ var bytes = StringUtilities.GetEncodedText (key, SKTextEncoding.Utf8);
+ fixed (byte* b = bytes) {
+ SkiaApi.sk_canvas_draw_annotation (base.Handle, &rect, b, value == null ? IntPtr.Zero : value.Handle);
+ }
+ }
+
+ public void DrawUrlAnnotation (SKRect rect, SKData value)
+ {
+ SkiaApi.sk_canvas_draw_url_annotation (Handle, &rect, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ public SKData DrawUrlAnnotation (SKRect rect, string value)
+ {
+ var data = SKData.FromCString (value);
+ DrawUrlAnnotation (rect, data);
+ return data;
+ }
+
+ public void DrawNamedDestinationAnnotation (SKPoint point, SKData value)
+ {
+ SkiaApi.sk_canvas_draw_named_destination_annotation (Handle, &point, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ public SKData DrawNamedDestinationAnnotation (SKPoint point, string value)
+ {
+ var data = SKData.FromCString (value);
+ DrawNamedDestinationAnnotation (point, data);
+ return data;
+ }
+
+ public void DrawLinkDestinationAnnotation (SKRect rect, SKData value)
+ {
+ SkiaApi.sk_canvas_draw_link_destination_annotation (Handle, &rect, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ public SKData DrawLinkDestinationAnnotation (SKRect rect, string value)
+ {
+ var data = SKData.FromCString (value);
+ DrawLinkDestinationAnnotation (rect, data);
+ return data;
+ }
+
+ // Draw*NinePatch
+
+ public void DrawBitmapNinePatch (SKBitmap bitmap, SKRectI center, SKRect dst, SKPaint paint = null)
+ {
+ if (bitmap == null)
+ throw new ArgumentNullException (nameof (bitmap));
+ // the "center" rect must fit inside the bitmap "rect"
+ if (!SKRect.Create (bitmap.Info.Size).Contains (center))
+ throw new ArgumentException ("Center rectangle must be contained inside the bitmap bounds.", nameof (center));
+
+ SkiaApi.sk_canvas_draw_bitmap_nine (Handle, bitmap.Handle, ¢er, &dst, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ public void DrawImageNinePatch (SKImage image, SKRectI center, SKRect dst, SKPaint paint = null)
+ {
+ if (image == null)
+ throw new ArgumentNullException (nameof (image));
+ // the "center" rect must fit inside the image "rect"
+ if (!SKRect.Create (image.Width, image.Height).Contains (center))
+ throw new ArgumentException ("Center rectangle must be contained inside the image bounds.", nameof (center));
+
+ SkiaApi.sk_canvas_draw_image_nine (Handle, image.Handle, ¢er, &dst, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ // Draw*Lattice
+
+ public void DrawBitmapLattice (SKBitmap bitmap, int[] xDivs, int[] yDivs, SKRect dst, SKPaint paint = null)
+ {
+ var lattice = new SKLattice {
+ XDivs = xDivs,
+ YDivs = yDivs
+ };
+ DrawBitmapLattice (bitmap, lattice, dst, paint);
+ }
+
+ public void DrawImageLattice (SKImage image, int[] xDivs, int[] yDivs, SKRect dst, SKPaint paint = null)
+ {
+ var lattice = new SKLattice {
+ XDivs = xDivs,
+ YDivs = yDivs
+ };
+ DrawImageLattice (image, lattice, dst, paint);
+ }
+
+ public void DrawBitmapLattice (SKBitmap bitmap, SKLattice lattice, SKRect dst, SKPaint paint = null)
+ {
+ if (bitmap == null)
+ throw new ArgumentNullException (nameof (bitmap));
+ if (lattice.XDivs == null)
+ throw new ArgumentNullException (nameof (lattice.XDivs));
+ if (lattice.YDivs == null)
+ throw new ArgumentNullException (nameof (lattice.YDivs));
+
+ fixed (int* x = lattice.XDivs)
+ fixed (int* y = lattice.YDivs)
+ fixed (SKLatticeRectType* r = lattice.RectTypes)
+ fixed (SKColor* c = lattice.Colors) {
+ var nativeLattice = new SKLatticeInternal {
+ fBounds = null,
+ fRectTypes = r,
+ fXCount = lattice.XDivs.Length,
+ fXDivs = x,
+ fYCount = lattice.YDivs.Length,
+ fYDivs = y,
+ fColors = (uint*)c,
+ };
+ if (lattice.Bounds != null) {
+ var bounds = lattice.Bounds.Value;
+ nativeLattice.fBounds = &bounds;
+ }
+ SkiaApi.sk_canvas_draw_bitmap_lattice (Handle, bitmap.Handle, &nativeLattice, &dst, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+ }
+
+ public void DrawImageLattice (SKImage image, SKLattice lattice, SKRect dst, SKPaint paint = null)
+ {
+ if (image == null)
+ throw new ArgumentNullException (nameof (image));
+ if (lattice.XDivs == null)
+ throw new ArgumentNullException (nameof (lattice.XDivs));
+ if (lattice.YDivs == null)
+ throw new ArgumentNullException (nameof (lattice.YDivs));
+
+ fixed (int* x = lattice.XDivs)
+ fixed (int* y = lattice.YDivs)
+ fixed (SKLatticeRectType* r = lattice.RectTypes)
+ fixed (SKColor* c = lattice.Colors) {
+ var nativeLattice = new SKLatticeInternal {
+ fBounds = null,
+ fRectTypes = r,
+ fXCount = lattice.XDivs.Length,
+ fXDivs = x,
+ fYCount = lattice.YDivs.Length,
+ fYDivs = y,
+ fColors = (uint*)c,
+ };
+ if (lattice.Bounds != null) {
+ var bounds = lattice.Bounds.Value;
+ nativeLattice.fBounds = &bounds;
+ }
+ SkiaApi.sk_canvas_draw_image_lattice (Handle, image.Handle, &nativeLattice, &dst, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+ }
+
+ // *Matrix
+
+ public void ResetMatrix ()
+ {
+ SkiaApi.sk_canvas_reset_matrix (Handle);
+ }
+
+ public void SetMatrix (SKMatrix matrix)
+ {
+ SkiaApi.sk_canvas_set_matrix (Handle, &matrix);
+ }
+
+ public SKMatrix TotalMatrix {
+ get {
+ SKMatrix matrix;
+ SkiaApi.sk_canvas_get_total_matrix (Handle, &matrix);
+ return matrix;
+ }
+ }
+
+ // SaveCount
+
+ public int SaveCount => SkiaApi.sk_canvas_get_save_count (Handle);
+
+ // DrawVertices
+
+ public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKColor[] colors, SKPaint paint)
+ {
+ var vert = SKVertices.CreateCopy (vmode, vertices, colors);
+ DrawVertices (vert, SKBlendMode.Modulate, paint);
+ }
+
+ public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKPaint paint)
+ {
+ var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors);
+ DrawVertices (vert, SKBlendMode.Modulate, paint);
+ }
+
+ public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, UInt16[] indices, SKPaint paint)
+ {
+ var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices);
+ DrawVertices (vert, SKBlendMode.Modulate, paint);
+ }
+
+ public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKBlendMode mode, UInt16[] indices, SKPaint paint)
+ {
+ var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices);
+ DrawVertices (vert, mode, paint);
+ }
+
+ public void DrawVertices (SKVertices vertices, SKBlendMode mode, SKPaint paint)
+ {
+ if (vertices == null)
+ throw new ArgumentNullException (nameof (vertices));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_vertices (Handle, vertices.Handle, mode, paint.Handle);
+ }
+
+ // DrawArc
+
+ public void DrawArc (SKRect oval, float startAngle, float sweepAngle, bool useCenter, SKPaint paint)
+ {
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+ SkiaApi.sk_canvas_draw_arc (Handle, &oval, startAngle, sweepAngle, useCenter, paint.Handle);
+ }
+
+ // DrawRoundRectDifference
+
+ public void DrawRoundRectDifference (SKRoundRect outer, SKRoundRect inner, SKPaint paint)
+ {
+ if (outer == null)
+ throw new ArgumentNullException (nameof (outer));
+ if (inner == null)
+ throw new ArgumentNullException (nameof (inner));
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ SkiaApi.sk_canvas_draw_drrect (Handle, outer.Handle, inner.Handle, paint.Handle);
+ }
+
+ // DrawAtlas
+
+ public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKPaint paint) =>
+ DrawAtlas (atlas, sprites, transforms, null, SKBlendMode.Dst, null, paint);
+
+ public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKPaint paint) =>
+ DrawAtlas (atlas, sprites, transforms, colors, mode, null, paint);
+
+ public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKRect cullRect, SKPaint paint) =>
+ DrawAtlas (atlas, sprites, transforms, colors, mode, &cullRect, paint);
+
+ private void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKRect* cullRect, SKPaint paint)
+ {
+ if (atlas == null)
+ throw new ArgumentNullException (nameof (atlas));
+ if (sprites == null)
+ throw new ArgumentNullException (nameof (sprites));
+ if (transforms == null)
+ throw new ArgumentNullException (nameof (transforms));
+
+ if (transforms.Length != sprites.Length)
+ throw new ArgumentException ("The number of transforms must match the number of sprites.", nameof (transforms));
+ if (colors != null && colors.Length != sprites.Length)
+ throw new ArgumentException ("The number of colors must match the number of sprites.", nameof (colors));
+
+ fixed (SKRect* s = sprites)
+ fixed (SKRotationScaleMatrix* t = transforms)
+ fixed (SKColor* c = colors) {
+ SkiaApi.sk_canvas_draw_atlas (Handle, atlas.Handle, t, s, (uint*)c, transforms.Length, mode, cullRect, paint.Handle);
+ }
+ }
+
+ // DrawPatch
+
+ public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPoint[] texCoords, SKPaint paint) =>
+ DrawPatch (cubics, colors, texCoords, SKBlendMode.Modulate, paint);
+
+ public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPoint[] texCoords, SKBlendMode mode, SKPaint paint)
+ {
+ if (cubics == null)
+ throw new ArgumentNullException (nameof (cubics));
+ if (cubics.Length != PatchCubicsCount)
+ throw new ArgumentException ($"Cubics must have a length of {PatchCubicsCount}.", nameof (cubics));
+
+ if (colors != null && colors.Length != PatchCornerCount)
+ throw new ArgumentException ($"Colors must have a length of {PatchCornerCount}.", nameof (colors));
+
+ if (texCoords != null && texCoords.Length != PatchCornerCount)
+ throw new ArgumentException ($"Texture coordinates must have a length of {PatchCornerCount}.", nameof (texCoords));
+
+ if (paint == null)
+ throw new ArgumentNullException (nameof (paint));
+
+ fixed (SKPoint* cubes = cubics)
+ fixed (SKColor* cols = colors)
+ fixed (SKPoint* coords = texCoords) {
+ SkiaApi.sk_canvas_draw_patch (Handle, cubes, (uint*)cols, coords, mode, paint.Handle);
+ }
+ }
+ }
+
+ public class SKAutoCanvasRestore : IDisposable
+ {
+ private SKCanvas canvas;
+ private readonly int saveCount;
+
+ public SKAutoCanvasRestore (SKCanvas canvas)
+ : this (canvas, true)
+ {
+ }
+
+ public SKAutoCanvasRestore (SKCanvas canvas, bool doSave)
+ {
+ this.canvas = canvas;
+ this.saveCount = 0;
+
+ if (canvas != null) {
+ saveCount = canvas.SaveCount;
+ if (doSave) {
+ canvas.Save ();
+ }
+ }
+ }
+
+ public void Dispose ()
+ {
+ Restore ();
+ }
+
+ /// <summary>
+ /// Perform the restore now, instead of waiting for the Dispose.
+ /// Will only do this once.
+ /// </summary>
+ public void Restore ()
+ {
+ if (canvas != null) {
+ canvas.RestoreToCount (saveCount);
+ canvas = null;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.IO;
+
+namespace SkiaSharp
+{
+ // TODO: `Create(...)` should have overloads that accept a SKPngChunkReader
+ // TODO: missing the `QueryYuv8` and `GetYuv8Planes` members
+
+ public unsafe class SKCodec : SKObject
+ {
+ [Preserve]
+ internal SKCodec (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_codec_destroy (Handle);
+
+ public static int MinBufferedBytesNeeded =>
+ (int)SkiaApi.sk_codec_min_buffered_bytes_needed ();
+
+ public SKImageInfo Info {
+ get {
+ SKImageInfoNative cinfo;
+ SkiaApi.sk_codec_get_info (Handle, &cinfo);
+ return SKImageInfoNative.ToManaged (ref cinfo);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use EncodedOrigin instead.")]
+ public SKCodecOrigin Origin =>
+ (SKCodecOrigin)EncodedOrigin;
+
+ public SKEncodedOrigin EncodedOrigin =>
+ SkiaApi.sk_codec_get_origin (Handle);
+
+ public SKEncodedImageFormat EncodedFormat =>
+ SkiaApi.sk_codec_get_encoded_format (Handle);
+
+ public SKSizeI GetScaledDimensions (float desiredScale)
+ {
+ SKSizeI dimensions;
+ SkiaApi.sk_codec_get_scaled_dimensions (Handle, desiredScale, &dimensions);
+ return dimensions;
+ }
+
+ public bool GetValidSubset (ref SKRectI desiredSubset)
+ {
+ fixed (SKRectI* ds = &desiredSubset) {
+ return SkiaApi.sk_codec_get_valid_subset (Handle, ds);
+ }
+ }
+
+ public byte[] Pixels {
+ get {
+ var result = GetPixels (out var pixels);
+ if (result != SKCodecResult.Success && result != SKCodecResult.IncompleteInput) {
+ throw new Exception (result.ToString ());
+ }
+ return pixels;
+ }
+ }
+
+ // frames
+
+ public int RepetitionCount =>
+ SkiaApi.sk_codec_get_repetition_count (Handle);
+
+ public int FrameCount =>
+ SkiaApi.sk_codec_get_frame_count (Handle);
+
+ public SKCodecFrameInfo[] FrameInfo {
+ get {
+ var length = SkiaApi.sk_codec_get_frame_count (Handle);
+ var info = new SKCodecFrameInfo[length];
+ fixed (SKCodecFrameInfo* i = info) {
+ SkiaApi.sk_codec_get_frame_info (Handle, i);
+ }
+ return info;
+ }
+ }
+
+ public bool GetFrameInfo (int index, out SKCodecFrameInfo frameInfo)
+ {
+ fixed (SKCodecFrameInfo* f = &frameInfo) {
+ return SkiaApi.sk_codec_get_frame_info_for_index (Handle, index, f);
+ }
+ }
+
+ // pixels
+
+ public SKCodecResult GetPixels (out byte[] pixels) =>
+ GetPixels (Info, out pixels);
+
+ public SKCodecResult GetPixels (SKImageInfo info, out byte[] pixels)
+ {
+ pixels = new byte[info.BytesSize];
+ return GetPixels (info, pixels);
+ }
+
+ public SKCodecResult GetPixels (SKImageInfo info, byte[] pixels)
+ {
+ if (pixels == null)
+ throw new ArgumentNullException (nameof (pixels));
+
+ fixed (byte* p = pixels) {
+ return GetPixels (info, (IntPtr)p, info.RowBytes, SKCodecOptions.Default);
+ }
+ }
+
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels) =>
+ GetPixels (info, pixels, info.RowBytes, SKCodecOptions.Default);
+
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels, SKCodecOptions options) =>
+ GetPixels (info, pixels, info.RowBytes, options);
+
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKCodecOptions options)
+ {
+ if (pixels == IntPtr.Zero)
+ throw new ArgumentNullException (nameof (pixels));
+
+ var nInfo = SKImageInfoNative.FromManaged (ref info);
+ var nOptions = new SKCodecOptionsInternal {
+ fZeroInitialized = options.ZeroInitialized,
+ fSubset = null,
+ fFrameIndex = options.FrameIndex,
+ fPriorFrame = options.PriorFrame,
+ fPremulBehavior = options.PremulBehavior,
+ };
+ var subset = default (SKRectI);
+ if (options.HasSubset) {
+ subset = options.Subset.Value;
+ nOptions.fSubset = ⊂
+ }
+ return SkiaApi.sk_codec_get_pixels (Handle, &nInfo, (void*)pixels, (IntPtr)rowBytes, &nOptions);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use GetPixels(SKImageInfo, IntPtr, int, SKCodecOptions) instead.")]
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKCodecOptions options, IntPtr colorTable, ref int colorTableCount) =>
+ GetPixels (info, pixels, rowBytes, options);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use GetPixels(SKImageInfo, IntPtr, SKCodecOptions) instead.")]
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels, SKCodecOptions options, IntPtr colorTable, ref int colorTableCount) =>
+ GetPixels (info, pixels, info.RowBytes, options);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use GetPixels(SKImageInfo, IntPtr) instead.")]
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels, IntPtr colorTable, ref int colorTableCount) =>
+ GetPixels (info, pixels, info.RowBytes, SKCodecOptions.Default);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use GetPixels(SKImageInfo, IntPtr, int, SKCodecOptions) instead.")]
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels, int rowBytes, SKCodecOptions options, SKColorTable colorTable, ref int colorTableCount) =>
+ GetPixels (info, pixels, rowBytes, options);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use GetPixels(SKImageInfo, IntPtr, SKCodecOptions) instead.")]
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels, SKCodecOptions options, SKColorTable colorTable, ref int colorTableCount) =>
+ GetPixels (info, pixels, info.RowBytes, options);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use GetPixels(SKImageInfo, IntPtr) instead.")]
+ public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels, SKColorTable colorTable, ref int colorTableCount) =>
+ GetPixels (info, pixels, info.RowBytes, SKCodecOptions.Default);
+
+ // incremental (start)
+
+ public SKCodecResult StartIncrementalDecode (SKImageInfo info, IntPtr pixels, int rowBytes, SKCodecOptions options)
+ {
+ if (pixels == IntPtr.Zero)
+ throw new ArgumentNullException (nameof (pixels));
+
+ var nInfo = SKImageInfoNative.FromManaged (ref info);
+ var nOptions = new SKCodecOptionsInternal {
+ fZeroInitialized = options.ZeroInitialized,
+ fSubset = null,
+ fFrameIndex = options.FrameIndex,
+ fPriorFrame = options.PriorFrame,
+ fPremulBehavior = options.PremulBehavior,
+ };
+ var subset = default (SKRectI);
+ if (options.HasSubset) {
+ subset = options.Subset.Value;
+ nOptions.fSubset = ⊂
+ }
+
+ return SkiaApi.sk_codec_start_incremental_decode (Handle, &nInfo, (void*)pixels, (IntPtr)rowBytes, &nOptions);
+ }
+
+ public SKCodecResult StartIncrementalDecode (SKImageInfo info, IntPtr pixels, int rowBytes)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ return SkiaApi.sk_codec_start_incremental_decode (Handle, &cinfo, (void*)pixels, (IntPtr)rowBytes, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use StartIncrementalDecode(SKImageInfo, IntPtr, int, SKCodecOptions) instead.")]
+ public SKCodecResult StartIncrementalDecode (SKImageInfo info, IntPtr pixels, int rowBytes, SKCodecOptions options, IntPtr colorTable, ref int colorTableCount) =>
+ StartIncrementalDecode (info, pixels, rowBytes, options);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use StartIncrementalDecode(SKImageInfo, IntPtr, int, SKCodecOptions) instead.")]
+ public SKCodecResult StartIncrementalDecode (SKImageInfo info, IntPtr pixels, int rowBytes, SKCodecOptions options, SKColorTable colorTable, ref int colorTableCount) =>
+ StartIncrementalDecode (info, pixels, rowBytes, options);
+
+ // incremental (step)
+
+ public SKCodecResult IncrementalDecode (out int rowsDecoded)
+ {
+ fixed (int* r = &rowsDecoded) {
+ return SkiaApi.sk_codec_incremental_decode (Handle, r);
+ }
+ }
+
+ public SKCodecResult IncrementalDecode () =>
+ SkiaApi.sk_codec_incremental_decode (Handle, null);
+
+ // scanline (start)
+
+ public SKCodecResult StartScanlineDecode (SKImageInfo info, SKCodecOptions options)
+ {
+ var nInfo = SKImageInfoNative.FromManaged (ref info);
+ var nOptions = new SKCodecOptionsInternal {
+ fZeroInitialized = options.ZeroInitialized,
+ fSubset = null,
+ fFrameIndex = options.FrameIndex,
+ fPriorFrame = options.PriorFrame,
+ fPremulBehavior = options.PremulBehavior,
+ };
+ var subset = default (SKRectI);
+ if (options.HasSubset) {
+ subset = options.Subset.Value;
+ nOptions.fSubset = ⊂
+ }
+
+ return SkiaApi.sk_codec_start_scanline_decode (Handle, &nInfo, &nOptions);
+ }
+
+ public SKCodecResult StartScanlineDecode (SKImageInfo info)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ return SkiaApi.sk_codec_start_scanline_decode (Handle, &cinfo, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use StartScanlineDecode(SKImageInfo, SKCodecOptions) instead.")]
+ public SKCodecResult StartScanlineDecode (SKImageInfo info, SKCodecOptions options, IntPtr colorTable, ref int colorTableCount) =>
+ StartScanlineDecode (info, options);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use StartScanlineDecode(SKImageInfo, SKCodecOptions) instead.")]
+ public SKCodecResult StartScanlineDecode (SKImageInfo info, SKCodecOptions options, SKColorTable colorTable, ref int colorTableCount) =>
+ StartScanlineDecode (info, options);
+
+ // scanline (step)
+
+ public int GetScanlines (IntPtr dst, int countLines, int rowBytes)
+ {
+ if (dst == IntPtr.Zero)
+ throw new ArgumentNullException (nameof (dst));
+
+ return SkiaApi.sk_codec_get_scanlines (Handle, (void*)dst, countLines, (IntPtr)rowBytes);
+ }
+
+ public bool SkipScanlines (int countLines) =>
+ SkiaApi.sk_codec_skip_scanlines (Handle, countLines);
+
+ public SKCodecScanlineOrder ScanlineOrder =>
+ SkiaApi.sk_codec_get_scanline_order (Handle);
+
+ public int NextScanline => SkiaApi.sk_codec_next_scanline (Handle);
+
+ public int GetOutputScanline (int inputScanline) =>
+ SkiaApi.sk_codec_output_scanline (Handle, inputScanline);
+
+ // create (streams)
+
+ public static SKCodec Create (string filename) =>
+ Create (filename, out var result);
+
+ public static SKCodec Create (string filename, out SKCodecResult result)
+ {
+ var stream = SKFileStream.OpenStream (filename);
+ if (stream == null) {
+ result = SKCodecResult.InternalError;
+ return null;
+ }
+
+ return Create (stream, out result);
+ }
+
+ public static SKCodec Create (Stream stream) =>
+ Create (stream, out var result);
+
+ public static SKCodec Create (Stream stream, out SKCodecResult result) =>
+ Create (WrapManagedStream (stream), out result);
+
+ public static SKCodec Create (SKStream stream) =>
+ Create (stream, out var result);
+
+ public static SKCodec Create (SKStream stream, out SKCodecResult result)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ fixed (SKCodecResult* r = &result) {
+ var codec = GetObject<SKCodec> (SkiaApi.sk_codec_new_from_stream (stream.Handle, r));
+ stream.RevokeOwnership (codec);
+ return codec;
+ }
+ }
+
+ // create (data)
+
+ public static SKCodec Create (SKData data)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+
+ return GetObject<SKCodec> (SkiaApi.sk_codec_new_from_data (data.Handle));
+ }
+
+ // utils
+
+ internal static SKStream WrapManagedStream (Stream stream)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+
+ // we will need a seekable stream, so buffer it if need be
+ if (stream.CanSeek) {
+ return new SKManagedStream (stream, true);
+ } else {
+ return new SKFrontBufferedManagedStream (stream, MinBufferedBytesNeeded, true);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Globalization;
+
+namespace SkiaSharp
+{
+ public readonly struct SKColor : IEquatable<SKColor>
+ {
+ public static readonly SKColor Empty;
+
+ private readonly uint color;
+
+ public SKColor (uint value)
+ {
+ color = value;
+ }
+
+ public SKColor (byte red, byte green, byte blue, byte alpha)
+ {
+ color = (uint)((alpha << 24) | (red << 16) | (green << 8) | blue);
+ }
+
+ public SKColor (byte red, byte green, byte blue)
+ {
+ color = (0xff000000u | (uint)(red << 16) | (uint)(green << 8) | blue);
+ }
+
+ public readonly SKColor WithRed (byte red) =>
+ new SKColor (red, Green, Blue, Alpha);
+
+ public readonly SKColor WithGreen (byte green) =>
+ new SKColor (Red, green, Blue, Alpha);
+
+ public readonly SKColor WithBlue (byte blue) =>
+ new SKColor (Red, Green, blue, Alpha);
+
+ public readonly SKColor WithAlpha (byte alpha) =>
+ new SKColor (Red, Green, Blue, alpha);
+
+ public readonly byte Alpha => (byte)((color >> 24) & 0xff);
+ public readonly byte Red => (byte)((color >> 16) & 0xff);
+ public readonly byte Green => (byte)((color >> 8) & 0xff);
+ public readonly byte Blue => (byte)((color) & 0xff);
+
+ public readonly float Hue {
+ get {
+ ToHsv (out var h, out _, out _);
+ return h;
+ }
+ }
+
+ public static SKColor FromHsl (float h, float s, float l, byte a = 255)
+ {
+ var colorf = SKColorF.FromHsl (h, s, l);
+
+ // RGB results from 0 to 255
+ var r = colorf.Red * 255f;
+ var g = colorf.Green * 255f;
+ var b = colorf.Blue * 255f;
+
+ return new SKColor ((byte)r, (byte)g, (byte)b, a);
+ }
+
+ public static SKColor FromHsv (float h, float s, float v, byte a = 255)
+ {
+ var colorf = SKColorF.FromHsv (h, s, v);
+
+ // RGB results from 0 to 255
+ var r = colorf.Red * 255f;
+ var g = colorf.Green * 255f;
+ var b = colorf.Blue * 255f;
+
+ return new SKColor ((byte)r, (byte)g, (byte)b, a);
+ }
+
+ public readonly void ToHsl (out float h, out float s, out float l)
+ {
+ // RGB from 0 to 255
+ var r = Red / 255f;
+ var g = Green / 255f;
+ var b = Blue / 255f;
+
+ var colorf = new SKColorF (r, g, b);
+ colorf.ToHsl (out h, out s, out l);
+ }
+
+ public readonly void ToHsv (out float h, out float s, out float v)
+ {
+ // RGB from 0 to 255
+ var r = Red / 255f;
+ var g = Green / 255f;
+ var b = Blue / 255f;
+
+ var colorf = new SKColorF (r, g, b);
+ colorf.ToHsv (out h, out s, out v);
+ }
+
+ public readonly override string ToString () =>
+ $"#{Alpha:x2}{Red:x2}{Green:x2}{Blue:x2}";
+
+ public readonly bool Equals (SKColor obj) =>
+ obj.color == color;
+
+ public readonly override bool Equals (object other) =>
+ other is SKColor f && Equals (f);
+
+ public static bool operator == (SKColor left, SKColor right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKColor left, SKColor right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode () =>
+ color.GetHashCode ();
+
+ public static implicit operator SKColor (uint color) =>
+ new SKColor (color);
+
+ public static explicit operator uint (SKColor color) =>
+ color.color;
+
+ public static SKColor Parse (string hexString)
+ {
+ if (!TryParse (hexString, out var color))
+ throw new ArgumentException ("Invalid hexadecimal color string.", nameof (hexString));
+ return color;
+ }
+
+ public static bool TryParse (string hexString, out SKColor color)
+ {
+ if (string.IsNullOrWhiteSpace (hexString)) {
+ // error
+ color = SKColor.Empty;
+ return false;
+ }
+
+ // clean up string
+ hexString = hexString.Trim ().ToUpperInvariant ();
+ if (hexString[0] == '#')
+ hexString = hexString.Substring (1);
+
+ var len = hexString.Length;
+ if (len == 3 || len == 4) {
+ byte a;
+ // parse [A]
+ if (len == 4) {
+ if (!byte.TryParse (string.Concat (hexString[len - 4], hexString[len - 4]), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out a)) {
+ // error
+ color = SKColor.Empty;
+ return false;
+ }
+ } else {
+ a = 255;
+ }
+
+ // parse RGB
+ if (!byte.TryParse (string.Concat (hexString[len - 3], hexString[len - 3]), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var r) ||
+ !byte.TryParse (string.Concat (hexString[len - 2], hexString[len - 2]), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var g) ||
+ !byte.TryParse (string.Concat (hexString[len - 1], hexString[len - 1]), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var b)) {
+ // error
+ color = SKColor.Empty;
+ return false;
+ }
+
+ // success
+ color = new SKColor (r, g, b, a);
+ return true;
+ }
+
+ if (len == 6 || len == 8) {
+ // parse [AA]RRGGBB
+ if (!uint.TryParse (hexString, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var number)) {
+ // error
+ color = SKColor.Empty;
+ return false;
+ }
+
+ // success
+ color = (SKColor)number;
+
+ // alpha was not provided, so use 255
+ if (len == 6) {
+ color = color.WithAlpha (255);
+ }
+ return true;
+ }
+
+ // error
+ color = SKColor.Empty;
+ return false;
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public readonly unsafe partial struct SKColorF
+ {
+ private const float EPSILON = 0.001f;
+
+ public static readonly SKColorF Empty;
+
+ public SKColorF (float red, float green, float blue)
+ {
+ fR = red;
+ fG = green;
+ fB = blue;
+ fA = 1f;
+ }
+
+ public SKColorF (float red, float green, float blue, float alpha)
+ {
+ fR = red;
+ fG = green;
+ fB = blue;
+ fA = alpha;
+ }
+
+ public readonly SKColorF WithRed (float red) =>
+ new SKColorF (red, fG, fB, fA);
+
+ public readonly SKColorF WithGreen (float green) =>
+ new SKColorF (fR, green, fB, fA);
+
+ public readonly SKColorF WithBlue (float blue) =>
+ new SKColorF (fR, fG, blue, fA);
+
+ public readonly SKColorF WithAlpha (float alpha) =>
+ new SKColorF (fR, fG, fB, alpha);
+
+ public readonly float Hue {
+ get {
+ ToHsv (out var h, out _, out _);
+ return h;
+ }
+ }
+
+ public readonly SKColorF Clamp ()
+ {
+ return new SKColorF (Clamp (fR), Clamp (fG), Clamp (fB), Clamp (fA));
+
+ static float Clamp (float v)
+ {
+ if (v > 1f)
+ return 1f;
+ if (v < 0f)
+ return 0f;
+ return v;
+ }
+ }
+
+ public static SKColorF FromHsl (float h, float s, float l, float a = 1f)
+ {
+ // convert from percentages
+ h = h / 360f;
+ s = s / 100f;
+ l = l / 100f;
+
+ // RGB results from 0 to 1
+ var r = l;
+ var g = l;
+ var b = l;
+
+ // HSL from 0 to 1
+ if (Math.Abs (s) > EPSILON) {
+ float v2;
+ if (l < 0.5f)
+ v2 = l * (1f + s);
+ else
+ v2 = (l + s) - (s * l);
+
+ var v1 = 2f * l - v2;
+
+ r = HueToRgb (v1, v2, h + (1f / 3f));
+ g = HueToRgb (v1, v2, h);
+ b = HueToRgb (v1, v2, h - (1f / 3f));
+ }
+
+ return new SKColorF (r, g, b, a);
+ }
+
+ private static float HueToRgb (float v1, float v2, float vH)
+ {
+ if (vH < 0f)
+ vH += 1f;
+ if (vH > 1f)
+ vH -= 1f;
+
+ if ((6f * vH) < 1f)
+ return (v1 + (v2 - v1) * 6f * vH);
+ if ((2f * vH) < 1f)
+ return (v2);
+ if ((3f * vH) < 2f)
+ return (v1 + (v2 - v1) * ((2f / 3f) - vH) * 6f);
+ return (v1);
+ }
+
+ public static SKColorF FromHsv (float h, float s, float v, float a = 1f)
+ {
+ // convert from percentages
+ h = h / 360f;
+ s = s / 100f;
+ v = v / 100f;
+
+ // RGB results from 0 to 1
+ var r = v;
+ var g = v;
+ var b = v;
+
+ // HSL from 0 to 1
+ if (Math.Abs (s) > EPSILON) {
+ h = h * 6f;
+ if (Math.Abs (h - 6f) < EPSILON)
+ h = 0f; // H must be < 1
+
+ var hInt = (int)h;
+ var v1 = v * (1f - s);
+ var v2 = v * (1f - s * (h - hInt));
+ var v3 = v * (1f - s * (1f - (h - hInt)));
+
+ if (hInt == 0) {
+ r = v;
+ g = v3;
+ b = v1;
+ } else if (hInt == 1) {
+ r = v2;
+ g = v;
+ b = v1;
+ } else if (hInt == 2) {
+ r = v1;
+ g = v;
+ b = v3;
+ } else if (hInt == 3) {
+ r = v1;
+ g = v2;
+ b = v;
+ } else if (hInt == 4) {
+ r = v3;
+ g = v1;
+ b = v;
+ } else {
+ r = v;
+ g = v1;
+ b = v2;
+ }
+ }
+
+ return new SKColorF (r, g, b, a);
+ }
+
+ public readonly void ToHsl (out float h, out float s, out float l)
+ {
+ // RGB from 0 to 1
+ var r = fR;
+ var g = fG;
+ var b = fB;
+
+ var min = Math.Min (Math.Min (r, g), b); // min value of RGB
+ var max = Math.Max (Math.Max (r, g), b); // max value of RGB
+ var delta = max - min; // delta RGB value
+
+ // default to a gray, no chroma...
+ h = 0f;
+ s = 0f;
+ l = (max + min) / 2f;
+
+ // chromatic data...
+ if (Math.Abs (delta) > EPSILON) {
+ if (l < 0.5f)
+ s = delta / (max + min);
+ else
+ s = delta / (2f - max - min);
+
+ var deltaR = (((max - r) / 6f) + (delta / 2f)) / delta;
+ var deltaG = (((max - g) / 6f) + (delta / 2f)) / delta;
+ var deltaB = (((max - b) / 6f) + (delta / 2f)) / delta;
+
+ if (Math.Abs (r - max) < EPSILON) // r == max
+ h = deltaB - deltaG;
+ else if (Math.Abs (g - max) < EPSILON) // g == max
+ h = (1f / 3f) + deltaR - deltaB;
+ else // b == max
+ h = (2f / 3f) + deltaG - deltaR;
+
+ if (h < 0f)
+ h += 1f;
+ if (h > 1f)
+ h -= 1f;
+ }
+
+ // convert to percentages
+ h = h * 360f;
+ s = s * 100f;
+ l = l * 100f;
+ }
+
+ public readonly void ToHsv (out float h, out float s, out float v)
+ {
+ // RGB from 0 to 1
+ var r = fR;
+ var g = fG;
+ var b = fB;
+
+ var min = Math.Min (Math.Min (r, g), b); // min value of RGB
+ var max = Math.Max (Math.Max (r, g), b); // max value of RGB
+ var delta = max - min; // delta RGB value
+
+ // default to a gray, no chroma...
+ h = 0;
+ s = 0;
+ v = max;
+
+ // chromatic data...
+ if (Math.Abs (delta) > EPSILON) {
+ s = delta / max;
+
+ var deltaR = (((max - r) / 6f) + (delta / 2f)) / delta;
+ var deltaG = (((max - g) / 6f) + (delta / 2f)) / delta;
+ var deltaB = (((max - b) / 6f) + (delta / 2f)) / delta;
+
+ if (Math.Abs (r - max) < EPSILON) // r == max
+ h = deltaB - deltaG;
+ else if (Math.Abs (g - max) < EPSILON) // g == max
+ h = (1f / 3f) + deltaR - deltaB;
+ else // b == max
+ h = (2f / 3f) + deltaG - deltaR;
+
+ if (h < 0f)
+ h += 1f;
+ if (h > 1f)
+ h -= 1f;
+ }
+
+ // convert to percentages
+ h = h * 360f;
+ s = s * 100f;
+ v = v * 100f;
+ }
+
+ public readonly override string ToString () =>
+ ((SKColor)this).ToString ();
+
+ public static implicit operator SKColorF (SKColor color)
+ {
+ SKColorF colorF;
+ SkiaApi.sk_color4f_from_color ((uint)color, &colorF);
+ return colorF;
+ }
+
+ public static explicit operator SKColor (SKColorF color) =>
+ SkiaApi.sk_color4f_to_color (&color);
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ // TODO: `FilterColor` may be useful
+
+ public unsafe class SKColorFilter : SKObject, ISKReferenceCounted
+ {
+ public const int ColorMatrixSize = 20;
+ public const int TableMaxLength = 256;
+
+ [Preserve]
+ internal SKColorFilter(IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public static SKColorFilter CreateBlendMode(SKColor c, SKBlendMode mode)
+ {
+ return GetObject<SKColorFilter>(SkiaApi.sk_colorfilter_new_mode((uint)c, mode));
+ }
+
+ public static SKColorFilter CreateLighting(SKColor mul, SKColor add)
+ {
+ return GetObject<SKColorFilter>(SkiaApi.sk_colorfilter_new_lighting((uint)mul, (uint)add));
+ }
+
+ public static SKColorFilter CreateCompose(SKColorFilter outer, SKColorFilter inner)
+ {
+ if (outer == null)
+ throw new ArgumentNullException(nameof(outer));
+ if (inner == null)
+ throw new ArgumentNullException(nameof(inner));
+ return GetObject<SKColorFilter>(SkiaApi.sk_colorfilter_new_compose(outer.Handle, inner.Handle));
+ }
+
+ public static SKColorFilter CreateColorMatrix(float[] matrix)
+ {
+ if (matrix == null)
+ throw new ArgumentNullException(nameof(matrix));
+ if (matrix.Length != 20)
+ throw new ArgumentException("Matrix must have a length of 20.", nameof(matrix));
+ fixed (float* m = matrix) {
+ return GetObject<SKColorFilter> (SkiaApi.sk_colorfilter_new_color_matrix (m));
+ }
+ }
+
+ public static SKColorFilter CreateLumaColor()
+ {
+ return GetObject<SKColorFilter>(SkiaApi.sk_colorfilter_new_luma_color());
+ }
+
+ public static SKColorFilter CreateTable(byte[] table)
+ {
+ if (table == null)
+ throw new ArgumentNullException(nameof(table));
+ if (table.Length != TableMaxLength)
+ throw new ArgumentException($"Table must have a length of {TableMaxLength}.", nameof(table));
+ fixed (byte* t = table) {
+ return GetObject<SKColorFilter> (SkiaApi.sk_colorfilter_new_table (t));
+ }
+ }
+
+ public static SKColorFilter CreateTable(byte[] tableA, byte[] tableR, byte[] tableG, byte[] tableB)
+ {
+ if (tableA != null && tableA.Length != TableMaxLength)
+ throw new ArgumentException($"Table A must have a length of {TableMaxLength}.", nameof(tableA));
+ if (tableR != null && tableR.Length != TableMaxLength)
+ throw new ArgumentException($"Table R must have a length of {TableMaxLength}.", nameof(tableR));
+ if (tableG != null && tableG.Length != TableMaxLength)
+ throw new ArgumentException($"Table G must have a length of {TableMaxLength}.", nameof(tableG));
+ if (tableB != null && tableB.Length != TableMaxLength)
+ throw new ArgumentException($"Table B must have a length of {TableMaxLength}.", nameof(tableB));
+
+ fixed (byte* a = tableA)
+ fixed (byte* r = tableR)
+ fixed (byte* g = tableG)
+ fixed (byte* b = tableB) {
+ return GetObject<SKColorFilter> (SkiaApi.sk_colorfilter_new_table_argb (a, r, g, b));
+ }
+ }
+
+ public static SKColorFilter CreateHighContrast(SKHighContrastConfig config)
+ {
+ return GetObject<SKColorFilter>(SkiaApi.sk_colorfilter_new_high_contrast(&config));
+ }
+
+ public static SKColorFilter CreateHighContrast(bool grayscale, SKHighContrastConfigInvertStyle invertStyle, float contrast)
+ {
+ return CreateHighContrast(new SKHighContrastConfig(grayscale, invertStyle, contrast));
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public unsafe class SKColorSpace : SKObject, ISKReferenceCounted
+ {
+ private static readonly SKColorSpace srgb;
+ private static readonly SKColorSpace srgbLinear;
+
+ static SKColorSpace ()
+ {
+ srgb = new SKColorSpaceStatic (SkiaApi.sk_colorspace_new_srgb ());
+ srgbLinear = new SKColorSpaceStatic (SkiaApi.sk_colorspace_new_srgb_linear ());
+ }
+
+ internal static void EnsureStaticInstanceAreInitialized ()
+ {
+ // IMPORTANT: do not remove to ensure that the static instances
+ // are initialized before any access is made to them
+ }
+
+ [Preserve]
+ internal SKColorSpace (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ // properties
+
+ public bool GammaIsCloseToSrgb =>
+ SkiaApi.sk_colorspace_gamma_close_to_srgb (Handle);
+
+ public bool GammaIsLinear =>
+ SkiaApi.sk_colorspace_gamma_is_linear (Handle);
+
+ public bool IsSrgb =>
+ SkiaApi.sk_colorspace_is_srgb (Handle);
+
+ public SKColorSpaceType Type =>
+ SkiaApi.sk_colorspace_gamma_get_type (Handle);
+
+ public SKNamedGamma NamedGamma =>
+ SkiaApi.sk_colorspace_gamma_get_gamma_named (Handle);
+
+ public bool IsNumericalTransferFunction =>
+ GetNumericalTransferFunction (out _);
+
+ public static bool Equal (SKColorSpace left, SKColorSpace right)
+ {
+ if (left == null)
+ throw new ArgumentNullException (nameof (left));
+ if (right == null)
+ throw new ArgumentNullException (nameof (right));
+
+ return SkiaApi.sk_colorspace_equals (left.Handle, right.Handle);
+ }
+
+ // CreateSrgb
+
+ public static SKColorSpace CreateSrgb () => srgb;
+
+ // CreateSrgbLinear
+
+ public static SKColorSpace CreateSrgbLinear () => srgbLinear;
+
+ // CreateIcc
+
+ public static SKColorSpace CreateIcc (IntPtr input, long length)
+ {
+ if (input == IntPtr.Zero)
+ throw new ArgumentNullException (nameof (input));
+
+ return GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_icc ((void*)input, (IntPtr)length));
+ }
+
+ public static SKColorSpace CreateIcc (byte[] input, long length)
+ {
+ if (input == null)
+ throw new ArgumentNullException (nameof (input));
+
+ fixed (byte* i = input) {
+ return GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_icc (i, (IntPtr)length));
+ }
+ }
+
+ public static SKColorSpace CreateIcc (byte[] input)
+ {
+ if (input == null)
+ throw new ArgumentNullException (nameof (input));
+
+ fixed (byte* i = input) {
+ return GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_icc (i, (IntPtr)input.Length));
+ }
+ }
+
+ // CreateRgb
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateRgb(SKColorSpaceRenderTargetGamma, SKMatrix44) instead.")]
+ public static SKColorSpace CreateRgb (SKColorSpaceRenderTargetGamma gamma, SKMatrix44 toXyzD50, SKColorSpaceFlags flags) =>
+ CreateRgb (gamma, toXyzD50);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateRgb(SKColorSpaceRenderTargetGamma, SKColorSpaceGamut) instead.")]
+ public static SKColorSpace CreateRgb (SKColorSpaceRenderTargetGamma gamma, SKColorSpaceGamut gamut, SKColorSpaceFlags flags) =>
+ CreateRgb (gamma, gamut);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateRgb(SKColorSpaceTransferFn, SKMatrix44) instead.")]
+ public static SKColorSpace CreateRgb (SKColorSpaceTransferFn coeffs, SKMatrix44 toXyzD50, SKColorSpaceFlags flags) =>
+ CreateRgb (coeffs, toXyzD50);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateRgb(SKColorSpaceTransferFn, SKColorSpaceGamut) instead.")]
+ public static SKColorSpace CreateRgb (SKColorSpaceTransferFn coeffs, SKColorSpaceGamut gamut, SKColorSpaceFlags flags) =>
+ CreateRgb (coeffs, gamut);
+
+ public static SKColorSpace CreateRgb (SKColorSpaceRenderTargetGamma gamma, SKMatrix44 toXyzD50)
+ {
+ if (toXyzD50 == null)
+ throw new ArgumentNullException (nameof (toXyzD50));
+
+ return GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_rgb_with_gamma (gamma, toXyzD50.Handle));
+ }
+
+ public static SKColorSpace CreateRgb (SKColorSpaceRenderTargetGamma gamma, SKColorSpaceGamut gamut) =>
+ GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_rgb_with_gamma_and_gamut (gamma, gamut));
+
+ public static SKColorSpace CreateRgb (SKColorSpaceTransferFn coeffs, SKMatrix44 toXyzD50)
+ {
+ if (toXyzD50 == null)
+ throw new ArgumentNullException (nameof (toXyzD50));
+
+ return GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_rgb_with_coeffs (&coeffs, toXyzD50.Handle));
+ }
+
+ public static SKColorSpace CreateRgb (SKColorSpaceTransferFn coeffs, SKColorSpaceGamut gamut) =>
+ GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_rgb_with_coeffs_and_gamut (&coeffs, gamut));
+
+ public static SKColorSpace CreateRgb (SKNamedGamma gamma, SKMatrix44 toXyzD50)
+ {
+ if (toXyzD50 == null)
+ throw new ArgumentNullException (nameof (toXyzD50));
+
+ return GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_rgb_with_gamma_named (gamma, toXyzD50.Handle));
+ }
+
+ public static SKColorSpace CreateRgb (SKNamedGamma gamma, SKColorSpaceGamut gamut) =>
+ GetObject<SKColorSpace> (SkiaApi.sk_colorspace_new_rgb_with_gamma_named_and_gamut (gamma, gamut));
+
+ // GetNumericalTransferFunction
+
+ public bool GetNumericalTransferFunction (out SKColorSpaceTransferFn fn)
+ {
+ fixed (SKColorSpaceTransferFn* f = &fn) {
+ return SkiaApi.sk_colorspace_is_numerical_transfer_fn (Handle, f);
+ }
+ }
+
+ // *XyzD50
+
+ public SKMatrix44 ToXyzD50 () =>
+ OwnedBy (GetObject<SKMatrix44> (SkiaApi.sk_colorspace_as_to_xyzd50 (Handle), false), this);
+
+ public bool ToXyzD50 (SKMatrix44 toXyzD50)
+ {
+ if (toXyzD50 == null)
+ throw new ArgumentNullException (nameof (toXyzD50));
+
+ return SkiaApi.sk_colorspace_to_xyzd50 (Handle, toXyzD50.Handle);
+ }
+
+ public SKMatrix44 FromXyzD50 () =>
+ OwnedBy (GetObject<SKMatrix44> (SkiaApi.sk_colorspace_as_from_xyzd50 (Handle), false), this);
+
+ //
+
+ private sealed class SKColorSpaceStatic : SKColorSpace
+ {
+ internal SKColorSpaceStatic (IntPtr x)
+ : base (x, false)
+ {
+ IgnorePublicDispose = true;
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe partial struct SKColorSpacePrimaries
+ {
+ public static readonly SKColorSpacePrimaries Empty;
+
+ public SKColorSpacePrimaries (float[] values)
+ {
+ if (values == null)
+ throw new ArgumentNullException (nameof (values));
+ if (values.Length != 8)
+ throw new ArgumentException ("The values must have exactly 8 items, one for each of [RX, RY, GX, GY, BX, BY, WX, WY].", nameof (values));
+
+ fRX = values[0];
+ fRY = values[1];
+ fGX = values[2];
+ fGY = values[3];
+ fBX = values[4];
+ fBY = values[5];
+ fWX = values[6];
+ fWY = values[7];
+ }
+
+ public SKColorSpacePrimaries (float rx, float ry, float gx, float gy, float bx, float by, float wx, float wy)
+ {
+ fRX = rx;
+ fRY = ry;
+ fGX = gx;
+ fGY = gy;
+ fBX = bx;
+ fBY = by;
+ fWX = wx;
+ fWY = wy;
+ }
+
+ public readonly float[] Values =>
+ new[] { fRX, fRY, fGX, fGY, fBX, fBY, fWX, fWY };
+
+ public readonly SKMatrix44 ToXyzD50 ()
+ {
+ var xyzD50 = new SKMatrix44 ();
+ if (!ToXyzD50 (xyzD50)) {
+ xyzD50.Dispose ();
+ xyzD50 = null;
+ }
+ return xyzD50;
+ }
+
+ public readonly bool ToXyzD50 (SKMatrix44 toXyzD50)
+ {
+ if (toXyzD50 == null)
+ throw new ArgumentNullException (nameof (toXyzD50));
+
+ fixed (SKColorSpacePrimaries* t = &this) {
+ return SkiaApi.sk_colorspaceprimaries_to_xyzd50 (t, toXyzD50.Handle);
+ }
+ }
+ }
+
+ public unsafe partial struct SKColorSpaceTransferFn
+ {
+ public static readonly SKColorSpaceTransferFn Empty;
+
+ public SKColorSpaceTransferFn (float[] values)
+ {
+ if (values == null)
+ throw new ArgumentNullException (nameof (values));
+ if (values.Length != 7)
+ throw new ArgumentException ("The values must have exactly 7 items, one for each of [G, A, B, C, D, E, F].", nameof (values));
+
+ fG = values[0];
+ fA = values[1];
+ fB = values[2];
+ fC = values[3];
+ fD = values[4];
+ fE = values[5];
+ fF = values[6];
+ }
+
+ public SKColorSpaceTransferFn (float g, float a, float b, float c, float d, float e, float f)
+ {
+ fG = g;
+ fA = a;
+ fB = b;
+ fC = c;
+ fD = d;
+ fE = e;
+ fF = f;
+ }
+
+ public readonly float[] Values =>
+ new[] { fG, fA, fB, fC, fD, fE, fF };
+
+ public readonly SKColorSpaceTransferFn Invert ()
+ {
+ SKColorSpaceTransferFn inverted;
+ fixed (SKColorSpaceTransferFn* t = &this) {
+ SkiaApi.sk_colorspace_transfer_fn_invert (t, &inverted);
+ }
+ return inverted;
+ }
+
+ public readonly float Transform (float x)
+ {
+ fixed (SKColorSpaceTransferFn* t = &this) {
+ return SkiaApi.sk_colorspace_transfer_fn_transform (t, x);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported.")]
+ public unsafe class SKColorTable : SKObject, ISKReferenceCounted
+ {
+ public const int MaxLength = 256;
+
+ [Preserve]
+ internal SKColorTable (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ public SKColorTable ()
+ : this (new SKPMColor[MaxLength])
+ {
+ }
+
+ public SKColorTable (int count)
+ : this (new SKPMColor[count])
+ {
+ }
+
+ public SKColorTable (SKColor[] colors)
+ : this (colors, colors.Length)
+ {
+ }
+
+ public SKColorTable (SKColor[] colors, int count)
+ : this (SKPMColor.PreMultiply (colors), count)
+ {
+ }
+
+ public SKColorTable (SKPMColor[] colors)
+ : this (colors, colors.Length)
+ {
+ }
+
+ public SKColorTable (SKPMColor[] colors, int count)
+ : this (CreateNew (colors, count), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKColorTable instance.");
+ }
+ }
+
+ private static IntPtr CreateNew (SKPMColor[] colors, int count)
+ {
+ fixed (SKPMColor* c = colors) {
+ return SkiaApi.sk_colortable_new ((uint*)c, count);
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public int Count => SkiaApi.sk_colortable_count (Handle);
+
+ public SKPMColor[] Colors {
+ get {
+ var count = Count;
+ var pointer = ReadColors ();
+
+ if (count == 0 || pointer == IntPtr.Zero) {
+ return new SKPMColor[0];
+ }
+
+ return PtrToStructureArray<SKPMColor> (pointer, count);
+ }
+ }
+
+ public SKColor[] UnPreMultipledColors => SKPMColor.UnPreMultiply (Colors);
+
+ public SKPMColor this[int index] {
+ get {
+ var count = Count;
+ var pointer = ReadColors ();
+
+ if (index < 0 || index >= count || pointer == IntPtr.Zero) {
+ throw new ArgumentOutOfRangeException (nameof (index));
+ }
+
+ return PtrToStructure<SKPMColor> (pointer, index);
+ }
+ }
+
+ public SKColor GetUnPreMultipliedColor (int index) => SKPMColor.UnPreMultiply (this[index]);
+
+ public IntPtr ReadColors ()
+ {
+ uint* colors;
+ SkiaApi.sk_colortable_read_colors (Handle, &colors);
+ return (IntPtr)colors;
+ }
+ }
+}
+
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public struct SKColors
+ {
+ public static SKColor Empty => new SKColor (0x00000000);
+ public static SKColor AliceBlue = new SKColor (0xFFF0F8FF);
+ public static SKColor AntiqueWhite = new SKColor (0xFFFAEBD7);
+ public static SKColor Aqua = new SKColor (0xFF00FFFF);
+ public static SKColor Aquamarine = new SKColor (0xFF7FFFD4);
+ public static SKColor Azure = new SKColor (0xFFF0FFFF);
+ public static SKColor Beige = new SKColor (0xFFF5F5DC);
+ public static SKColor Bisque = new SKColor (0xFFFFE4C4);
+ public static SKColor Black = new SKColor (0xFF000000);
+ public static SKColor BlanchedAlmond = new SKColor (0xFFFFEBCD);
+ public static SKColor Blue = new SKColor (0xFF0000FF);
+ public static SKColor BlueViolet = new SKColor (0xFF8A2BE2);
+ public static SKColor Brown = new SKColor (0xFFA52A2A);
+ public static SKColor BurlyWood = new SKColor (0xFFDEB887);
+ public static SKColor CadetBlue = new SKColor (0xFF5F9EA0);
+ public static SKColor Chartreuse = new SKColor (0xFF7FFF00);
+ public static SKColor Chocolate = new SKColor (0xFFD2691E);
+ public static SKColor Coral = new SKColor (0xFFFF7F50);
+ public static SKColor CornflowerBlue = new SKColor (0xFF6495ED);
+ public static SKColor Cornsilk = new SKColor (0xFFFFF8DC);
+ public static SKColor Crimson = new SKColor (0xFFDC143C);
+ public static SKColor Cyan = new SKColor (0xFF00FFFF);
+ public static SKColor DarkBlue = new SKColor (0xFF00008B);
+ public static SKColor DarkCyan = new SKColor (0xFF008B8B);
+ public static SKColor DarkGoldenrod = new SKColor (0xFFB8860B);
+ public static SKColor DarkGray = new SKColor (0xFFA9A9A9);
+ public static SKColor DarkGreen = new SKColor (0xFF006400);
+ public static SKColor DarkKhaki = new SKColor (0xFFBDB76B);
+ public static SKColor DarkMagenta = new SKColor (0xFF8B008B);
+ public static SKColor DarkOliveGreen = new SKColor (0xFF556B2F);
+ public static SKColor DarkOrange = new SKColor (0xFFFF8C00);
+ public static SKColor DarkOrchid = new SKColor (0xFF9932CC);
+ public static SKColor DarkRed = new SKColor (0xFF8B0000);
+ public static SKColor DarkSalmon = new SKColor (0xFFE9967A);
+ public static SKColor DarkSeaGreen = new SKColor (0xFF8FBC8B);
+ public static SKColor DarkSlateBlue = new SKColor (0xFF483D8B);
+ public static SKColor DarkSlateGray = new SKColor (0xFF2F4F4F);
+ public static SKColor DarkTurquoise = new SKColor (0xFF00CED1);
+ public static SKColor DarkViolet = new SKColor (0xFF9400D3);
+ public static SKColor DeepPink = new SKColor (0xFFFF1493);
+ public static SKColor DeepSkyBlue = new SKColor (0xFF00BFFF);
+ public static SKColor DimGray = new SKColor (0xFF696969);
+ public static SKColor DodgerBlue = new SKColor (0xFF1E90FF);
+ public static SKColor Firebrick = new SKColor (0xFFB22222);
+ public static SKColor FloralWhite = new SKColor (0xFFFFFAF0);
+ public static SKColor ForestGreen = new SKColor (0xFF228B22);
+ public static SKColor Fuchsia = new SKColor (0xFFFF00FF);
+ public static SKColor Gainsboro = new SKColor (0xFFDCDCDC);
+ public static SKColor GhostWhite = new SKColor (0xFFF8F8FF);
+ public static SKColor Gold = new SKColor (0xFFFFD700);
+ public static SKColor Goldenrod = new SKColor (0xFFDAA520);
+ public static SKColor Gray = new SKColor (0xFF808080);
+ public static SKColor Green = new SKColor (0xFF008000);
+ public static SKColor GreenYellow = new SKColor (0xFFADFF2F);
+ public static SKColor Honeydew = new SKColor (0xFFF0FFF0);
+ public static SKColor HotPink = new SKColor (0xFFFF69B4);
+ public static SKColor IndianRed = new SKColor (0xFFCD5C5C);
+ public static SKColor Indigo = new SKColor (0xFF4B0082);
+ public static SKColor Ivory = new SKColor (0xFFFFFFF0);
+ public static SKColor Khaki = new SKColor (0xFFF0E68C);
+ public static SKColor Lavender = new SKColor (0xFFE6E6FA);
+ public static SKColor LavenderBlush = new SKColor (0xFFFFF0F5);
+ public static SKColor LawnGreen = new SKColor (0xFF7CFC00);
+ public static SKColor LemonChiffon = new SKColor (0xFFFFFACD);
+ public static SKColor LightBlue = new SKColor (0xFFADD8E6);
+ public static SKColor LightCoral = new SKColor (0xFFF08080);
+ public static SKColor LightCyan = new SKColor (0xFFE0FFFF);
+ public static SKColor LightGoldenrodYellow = new SKColor (0xFFFAFAD2);
+ public static SKColor LightGray = new SKColor (0xFFD3D3D3);
+ public static SKColor LightGreen = new SKColor (0xFF90EE90);
+ public static SKColor LightPink = new SKColor (0xFFFFB6C1);
+ public static SKColor LightSalmon = new SKColor (0xFFFFA07A);
+ public static SKColor LightSeaGreen = new SKColor (0xFF20B2AA);
+ public static SKColor LightSkyBlue = new SKColor (0xFF87CEFA);
+ public static SKColor LightSlateGray = new SKColor (0xFF778899);
+ public static SKColor LightSteelBlue = new SKColor (0xFFB0C4DE);
+ public static SKColor LightYellow = new SKColor (0xFFFFFFE0);
+ public static SKColor Lime = new SKColor (0xFF00FF00);
+ public static SKColor LimeGreen = new SKColor (0xFF32CD32);
+ public static SKColor Linen = new SKColor (0xFFFAF0E6);
+ public static SKColor Magenta = new SKColor (0xFFFF00FF);
+ public static SKColor Maroon = new SKColor (0xFF800000);
+ public static SKColor MediumAquamarine = new SKColor (0xFF66CDAA);
+ public static SKColor MediumBlue = new SKColor (0xFF0000CD);
+ public static SKColor MediumOrchid = new SKColor (0xFFBA55D3);
+ public static SKColor MediumPurple = new SKColor (0xFF9370DB);
+ public static SKColor MediumSeaGreen = new SKColor (0xFF3CB371);
+ public static SKColor MediumSlateBlue = new SKColor (0xFF7B68EE);
+ public static SKColor MediumSpringGreen = new SKColor (0xFF00FA9A);
+ public static SKColor MediumTurquoise = new SKColor (0xFF48D1CC);
+ public static SKColor MediumVioletRed = new SKColor (0xFFC71585);
+ public static SKColor MidnightBlue = new SKColor (0xFF191970);
+ public static SKColor MintCream = new SKColor (0xFFF5FFFA);
+ public static SKColor MistyRose = new SKColor (0xFFFFE4E1);
+ public static SKColor Moccasin = new SKColor (0xFFFFE4B5);
+ public static SKColor NavajoWhite = new SKColor (0xFFFFDEAD);
+ public static SKColor Navy = new SKColor (0xFF000080);
+ public static SKColor OldLace = new SKColor (0xFFFDF5E6);
+ public static SKColor Olive = new SKColor (0xFF808000);
+ public static SKColor OliveDrab = new SKColor (0xFF6B8E23);
+ public static SKColor Orange = new SKColor (0xFFFFA500);
+ public static SKColor OrangeRed = new SKColor (0xFFFF4500);
+ public static SKColor Orchid = new SKColor (0xFFDA70D6);
+ public static SKColor PaleGoldenrod = new SKColor (0xFFEEE8AA);
+ public static SKColor PaleGreen = new SKColor (0xFF98FB98);
+ public static SKColor PaleTurquoise = new SKColor (0xFFAFEEEE);
+ public static SKColor PaleVioletRed = new SKColor (0xFFDB7093);
+ public static SKColor PapayaWhip = new SKColor (0xFFFFEFD5);
+ public static SKColor PeachPuff = new SKColor (0xFFFFDAB9);
+ public static SKColor Peru = new SKColor (0xFFCD853F);
+ public static SKColor Pink = new SKColor (0xFFFFC0CB);
+ public static SKColor Plum = new SKColor (0xFFDDA0DD);
+ public static SKColor PowderBlue = new SKColor (0xFFB0E0E6);
+ public static SKColor Purple = new SKColor (0xFF800080);
+ public static SKColor Red = new SKColor (0xFFFF0000);
+ public static SKColor RosyBrown = new SKColor (0xFFBC8F8F);
+ public static SKColor RoyalBlue = new SKColor (0xFF4169E1);
+ public static SKColor SaddleBrown = new SKColor (0xFF8B4513);
+ public static SKColor Salmon = new SKColor (0xFFFA8072);
+ public static SKColor SandyBrown = new SKColor (0xFFF4A460);
+ public static SKColor SeaGreen = new SKColor (0xFF2E8B57);
+ public static SKColor SeaShell = new SKColor (0xFFFFF5EE);
+ public static SKColor Sienna = new SKColor (0xFFA0522D);
+ public static SKColor Silver = new SKColor (0xFFC0C0C0);
+ public static SKColor SkyBlue = new SKColor (0xFF87CEEB);
+ public static SKColor SlateBlue = new SKColor (0xFF6A5ACD);
+ public static SKColor SlateGray = new SKColor (0xFF708090);
+ public static SKColor Snow = new SKColor (0xFFFFFAFA);
+ public static SKColor SpringGreen = new SKColor (0xFF00FF7F);
+ public static SKColor SteelBlue = new SKColor (0xFF4682B4);
+ public static SKColor Tan = new SKColor (0xFFD2B48C);
+ public static SKColor Teal = new SKColor (0xFF008080);
+ public static SKColor Thistle = new SKColor (0xFFD8BFD8);
+ public static SKColor Tomato = new SKColor (0xFFFF6347);
+ public static SKColor Turquoise = new SKColor (0xFF40E0D0);
+ public static SKColor Violet = new SKColor (0xFFEE82EE);
+ public static SKColor Wheat = new SKColor (0xFFF5DEB3);
+ public static SKColor White = new SKColor (0xFFFFFFFF);
+ public static SKColor WhiteSmoke = new SKColor (0xFFF5F5F5);
+ public static SKColor Yellow = new SKColor (0xFFFFFF00);
+ public static SKColor YellowGreen = new SKColor (0xFF9ACD32);
+ public static SKColor Transparent = new SKColor (0x00FFFFFF);
+
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using System.IO;
+using System.Text;
+using System.ComponentModel;
+using System.Buffers;
+
+namespace SkiaSharp
+{
+ public unsafe class SKData : SKObject, ISKNonVirtualReferenceCounted
+ {
+ // We pick a value that is the largest multiple of 4096 that is still smaller than the large object heap threshold (85K).
+ // The CopyTo/CopyToAsync buffer is short-lived and is likely to be collected at Gen0, and it offers a significant
+ // improvement in Copy performance.
+ internal const int CopyBufferSize = 81920;
+
+ private static readonly Lazy<SKData> empty;
+
+ static SKData()
+ {
+ empty = new Lazy<SKData> (() => new SKDataStatic (SkiaApi.sk_data_new_empty ()));
+ }
+
+ internal static void EnsureStaticInstanceAreInitialized ()
+ {
+ // IMPORTANT: do not remove to ensure that the static instances
+ // are initialized before any access is made to them
+ }
+
+ [Preserve]
+ internal SKData (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ void ISKNonVirtualReferenceCounted.ReferenceNative () => SkiaApi.sk_data_ref (Handle);
+
+ void ISKNonVirtualReferenceCounted.UnreferenceNative () => SkiaApi.sk_data_unref (Handle);
+
+ public static SKData Empty => empty.Value;
+
+ // CreateCopy
+
+ public static SKData CreateCopy (IntPtr bytes, ulong length)
+ {
+ if (SizeOf <IntPtr> () == 4 && length > UInt32.MaxValue)
+ throw new ArgumentOutOfRangeException (nameof (length), "The length exceeds the size of pointers.");
+ return GetObject<SKData> (SkiaApi.sk_data_new_with_copy ((void*)bytes, (IntPtr) length));
+ }
+
+ public static SKData CreateCopy (byte[] bytes) =>
+ CreateCopy (bytes, (ulong)bytes.Length);
+
+ public static SKData CreateCopy (byte[] bytes, ulong length)
+ {
+ fixed (byte* b = bytes) {
+ return GetObject<SKData> (SkiaApi.sk_data_new_with_copy (b, (IntPtr)length));
+ }
+ }
+
+ public static SKData CreateCopy (ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* b = bytes) {
+ return CreateCopy ((IntPtr)b, (ulong)bytes.Length);
+ }
+ }
+
+ // Create
+
+ public static SKData Create (int size)
+ {
+ return GetObject<SKData> (SkiaApi.sk_data_new_uninitialized ((IntPtr) size));
+ }
+
+ public static SKData Create (ulong size)
+ {
+ if (SizeOf <IntPtr> () == 4 && size > UInt32.MaxValue)
+ throw new ArgumentOutOfRangeException (nameof (size), "The size exceeds the size of pointers.");
+
+ return GetObject<SKData> (SkiaApi.sk_data_new_uninitialized ((IntPtr) size));
+ }
+
+ public static SKData Create (string filename)
+ {
+ if (string.IsNullOrEmpty (filename))
+ throw new ArgumentException ("The filename cannot be empty.", nameof (filename));
+
+ var utf8path = StringUtilities.GetEncodedText (filename, SKTextEncoding.Utf8);
+ fixed (byte* u = utf8path) {
+ return GetObject<SKData> (SkiaApi.sk_data_new_from_file (u));
+ }
+ }
+
+ public static SKData Create (Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+ return Create (stream, stream.Length);
+ }
+
+ public static SKData Create (Stream stream, int length)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ using (var managed = new SKManagedStream (stream))
+ return Create (managed, length);
+ }
+
+ public static SKData Create (Stream stream, ulong length)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ using (var managed = new SKManagedStream (stream))
+ return Create (managed, length);
+ }
+
+ public static SKData Create (Stream stream, long length)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ using (var managed = new SKManagedStream (stream))
+ return Create (managed, length);
+ }
+
+ public static SKData Create (SKStream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ return Create (stream, stream.Length);
+ }
+
+ public static SKData Create (SKStream stream, int length)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ return GetObject<SKData> (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr) length));
+ }
+
+ public static SKData Create (SKStream stream, ulong length)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ return GetObject<SKData> (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr) length));
+ }
+
+ public static SKData Create (SKStream stream, long length)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ return GetObject<SKData> (SkiaApi.sk_data_new_from_stream (stream.Handle, (IntPtr) length));
+ }
+
+ public static SKData Create (IntPtr address, int length)
+ {
+ return Create (address, length, null, null);
+ }
+
+ public static SKData Create (IntPtr address, int length, SKDataReleaseDelegate releaseProc)
+ {
+ return Create (address, length, releaseProc, null);
+ }
+
+ public static SKData Create (IntPtr address, int length, SKDataReleaseDelegate releaseProc, object context)
+ {
+ var del = releaseProc != null && context != null
+ ? new SKDataReleaseDelegate ((addr, _) => releaseProc (addr, context))
+ : releaseProc;
+ var proxy = DelegateProxies.Create (del, DelegateProxies.SKDataReleaseDelegateProxy, out _, out var ctx);
+ return GetObject<SKData> (SkiaApi.sk_data_new_with_proc ((void*)address, (IntPtr)length, proxy, (void*)ctx));
+ }
+
+ internal static SKData FromCString (string str)
+ {
+ var bytes = Encoding.ASCII.GetBytes (str ?? string.Empty);
+ return SKData.CreateCopy (bytes, (ulong)(bytes.Length + 1)); // + 1 for the terminating char
+ }
+
+ // Subset
+
+ public SKData Subset (ulong offset, ulong length)
+ {
+ if (SizeOf <IntPtr> () == 4) {
+ if (length > UInt32.MaxValue)
+ throw new ArgumentOutOfRangeException (nameof (length), "The length exceeds the size of pointers.");
+ if (offset > UInt32.MaxValue)
+ throw new ArgumentOutOfRangeException (nameof (offset), "The offset exceeds the size of pointers.");
+ }
+ return GetObject<SKData> (SkiaApi.sk_data_new_subset (Handle, (IntPtr) offset, (IntPtr) length));
+ }
+
+ // ToArray
+
+ public byte[] ToArray ()
+ {
+ var array = AsSpan ().ToArray ();
+ GC.KeepAlive (this);
+ return array;
+ }
+
+ // properties
+
+ public bool IsEmpty => Size == 0;
+
+ public long Size => (long)SkiaApi.sk_data_get_size (Handle);
+
+ public IntPtr Data => (IntPtr)SkiaApi.sk_data_get_data (Handle);
+
+ // AsStream
+
+ public Stream AsStream () =>
+ new SKDataStream (this, false);
+
+ public Stream AsStream (bool streamDisposesData) =>
+ new SKDataStream (this, streamDisposesData);
+
+ // AsSpan
+
+ public ReadOnlySpan<byte> AsSpan ()
+ {
+ return new ReadOnlySpan<byte> ((void*)Data, (int)Size);
+ }
+
+ // SaveTo
+
+ public void SaveTo (Stream target)
+ {
+ if (target == null)
+ throw new ArgumentNullException (nameof (target));
+
+ var ptr = Data;
+ var total = Size;
+ var buffer = ArrayPool<byte>.Shared.Rent (CopyBufferSize);
+ try {
+ for (var left = total; left > 0;) {
+ var copyCount = (int)Math.Min (CopyBufferSize, left);
+ Marshal.Copy (ptr, buffer, 0, copyCount);
+ left -= copyCount;
+ ptr += copyCount;
+ target.Write (buffer, 0, copyCount);
+ }
+ } finally {
+ ArrayPool<byte>.Shared.Return (buffer);
+ }
+ GC.KeepAlive (this);
+ }
+
+ //
+
+ private class SKDataStream : UnmanagedMemoryStream
+ {
+ private SKData host;
+ private readonly bool disposeHost;
+
+ public unsafe SKDataStream (SKData host, bool disposeHost = false)
+ : base((byte *) host.Data, host.Size)
+ {
+ this.host = host;
+ this.disposeHost = disposeHost;
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ base.Dispose (disposing);
+
+ if (disposeHost) {
+ host?.Dispose ();
+ }
+ host = null;
+ }
+ }
+
+ private sealed class SKDataStatic : SKData
+ {
+ internal SKDataStatic (IntPtr x)
+ : base (x, false)
+ {
+ IgnorePublicDispose = true;
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.IO;
+
+namespace SkiaSharp
+{
+ public unsafe class SKDocument : SKObject, ISKReferenceCounted
+ {
+ public const float DefaultRasterDpi = 72.0f;
+
+ [Preserve]
+ internal SKDocument (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public void Abort () =>
+ SkiaApi.sk_document_abort (Handle);
+
+ public SKCanvas BeginPage (float width, float height) =>
+ OwnedBy (GetObject<SKCanvas> (SkiaApi.sk_document_begin_page (Handle, width, height, null), false), this);
+
+ public SKCanvas BeginPage (float width, float height, SKRect content) =>
+ OwnedBy (GetObject<SKCanvas> (SkiaApi.sk_document_begin_page (Handle, width, height, &content), false), this);
+
+ public void EndPage () =>
+ SkiaApi.sk_document_end_page (Handle);
+
+ public void Close () =>
+ SkiaApi.sk_document_close (Handle);
+
+ // CreateXps
+
+ public static SKDocument CreateXps (string path) =>
+ CreateXps (path, DefaultRasterDpi);
+
+ public static SKDocument CreateXps (Stream stream) =>
+ CreateXps (stream, DefaultRasterDpi);
+
+ public static SKDocument CreateXps (SKWStream stream) =>
+ CreateXps (stream, DefaultRasterDpi);
+
+ public static SKDocument CreateXps (string path, float dpi)
+ {
+ if (path == null) {
+ throw new ArgumentNullException (nameof (path));
+ }
+
+ var stream = SKFileWStream.OpenStream (path);
+ return Owned (CreateXps (stream, dpi), stream);
+ }
+
+ public static SKDocument CreateXps (Stream stream, float dpi)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+
+ var managed = new SKManagedWStream (stream);
+ return Owned (CreateXps (managed, dpi), managed);
+ }
+
+ public static SKDocument CreateXps (SKWStream stream, float dpi)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+
+ return Referenced (GetObject<SKDocument> (SkiaApi.sk_document_create_xps_from_stream (stream.Handle, dpi)), stream);
+ }
+
+ // CreatePdf
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreatePdf(SKWStream, SKDocumentPdfMetadata) instead.")]
+ public static SKDocument CreatePdf (SKWStream stream, SKDocumentPdfMetadata metadata, float dpi)
+ {
+ metadata.RasterDpi = dpi;
+ return CreatePdf (stream, metadata);
+ }
+
+ public static SKDocument CreatePdf (string path)
+ {
+ if (path == null) {
+ throw new ArgumentNullException (nameof (path));
+ }
+
+ var stream = SKFileWStream.OpenStream (path);
+ return Owned (CreatePdf (stream), stream);
+ }
+
+ public static SKDocument CreatePdf (Stream stream)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+
+ var managed = new SKManagedWStream (stream);
+ return Owned (CreatePdf (managed), managed);
+ }
+
+ public static SKDocument CreatePdf (SKWStream stream)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+
+ return Referenced (GetObject<SKDocument> (SkiaApi.sk_document_create_pdf_from_stream (stream.Handle)), stream);
+ }
+
+ public static SKDocument CreatePdf (string path, float dpi) =>
+ CreatePdf (path, new SKDocumentPdfMetadata (dpi));
+
+ public static SKDocument CreatePdf (Stream stream, float dpi) =>
+ CreatePdf (stream, new SKDocumentPdfMetadata (dpi));
+
+ public static SKDocument CreatePdf (SKWStream stream, float dpi) =>
+ CreatePdf (stream, new SKDocumentPdfMetadata (dpi));
+
+ public static SKDocument CreatePdf (string path, SKDocumentPdfMetadata metadata)
+ {
+ if (path == null) {
+ throw new ArgumentNullException (nameof (path));
+ }
+
+ var stream = SKFileWStream.OpenStream (path);
+ return Owned (CreatePdf (stream, metadata), stream);
+ }
+
+ public static SKDocument CreatePdf (Stream stream, SKDocumentPdfMetadata metadata)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+
+ var managed = new SKManagedWStream (stream);
+ return Owned (CreatePdf (managed, metadata), managed);
+ }
+
+ public static SKDocument CreatePdf (SKWStream stream, SKDocumentPdfMetadata metadata)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+
+ using (var title = SKString.Create (metadata.Title))
+ using (var author = SKString.Create (metadata.Author))
+ using (var subject = SKString.Create (metadata.Subject))
+ using (var keywords = SKString.Create (metadata.Keywords))
+ using (var creator = SKString.Create (metadata.Creator))
+ using (var producer = SKString.Create (metadata.Producer)) {
+ var cmetadata = new SKDocumentPdfMetadataInternal {
+ fTitle = title?.Handle ?? IntPtr.Zero,
+ fAuthor = author?.Handle ?? IntPtr.Zero,
+ fSubject = subject?.Handle ?? IntPtr.Zero,
+ fKeywords = keywords?.Handle ?? IntPtr.Zero,
+ fCreator = creator?.Handle ?? IntPtr.Zero,
+ fProducer = producer?.Handle ?? IntPtr.Zero,
+ fRasterDPI = metadata.RasterDpi,
+ fPDFA = metadata.PdfA ? (byte)1 : (byte)0,
+ fEncodingQuality = metadata.EncodingQuality,
+ };
+
+ SKTimeDateTimeInternal creation;
+ if (metadata.Creation != null) {
+ creation = SKTimeDateTimeInternal.Create (metadata.Creation.Value);
+ cmetadata.fCreation = &creation;
+ }
+ SKTimeDateTimeInternal modified;
+ if (metadata.Modified != null) {
+ modified = SKTimeDateTimeInternal.Create (metadata.Modified.Value);
+ cmetadata.fModified = &modified;
+ }
+
+ return Referenced (GetObject<SKDocument> (SkiaApi.sk_document_create_pdf_from_stream_with_metadata (stream.Handle, &cmetadata)), stream);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace SkiaSharp
+{
+ public unsafe class SKDrawable : SKObject, ISKReferenceCounted
+ {
+ private static readonly SKManagedDrawableDelegates delegates;
+
+ private int fromNative;
+
+ static SKDrawable ()
+ {
+ delegates = new SKManagedDrawableDelegates {
+ fDraw = DrawInternal,
+ fGetBounds = GetBoundsInternal,
+ fNewPictureSnapshot = NewPictureSnapshotInternal,
+ fDestroy = DestroyInternal,
+ };
+
+ SkiaApi.sk_manageddrawable_set_procs (delegates);
+ }
+
+ protected SKDrawable ()
+ : this (true)
+ {
+ }
+
+ protected SKDrawable (bool owns)
+ : base (IntPtr.Zero, owns)
+ {
+ var ctx = DelegateProxies.CreateUserData (this, true);
+ Handle = SkiaApi.sk_manageddrawable_new ((void*)ctx);
+
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKDrawable instance.");
+ }
+ }
+
+ [Preserve]
+ internal SKDrawable (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative ()
+ {
+ if (Interlocked.CompareExchange (ref fromNative, 0, 0) == 0)
+ SkiaApi.sk_drawable_unref (Handle);
+ }
+
+ public uint GenerationId => SkiaApi.sk_drawable_get_generation_id (Handle);
+
+ public SKRect Bounds {
+ get {
+ SKRect bounds;
+ SkiaApi.sk_drawable_get_bounds (Handle, &bounds);
+ return bounds;
+ }
+ }
+
+ public void Draw (SKCanvas canvas, ref SKMatrix matrix)
+ {
+ fixed (SKMatrix* m = &matrix) {
+ SkiaApi.sk_drawable_draw (Handle, canvas.Handle, m);
+ }
+ }
+
+ public void Draw (SKCanvas canvas, float x, float y)
+ {
+ var matrix = SKMatrix.MakeTranslation (x, y);
+ Draw (canvas, ref matrix);
+ }
+
+ // do not unref as this is a plain pointer return, not a reference counted pointer
+ public SKPicture Snapshot () =>
+ GetObject<SKPicture> (SkiaApi.sk_drawable_new_picture_snapshot (Handle), unrefExisting: false);
+
+ public void NotifyDrawingChanged () =>
+ SkiaApi.sk_drawable_notify_drawing_changed (Handle);
+
+ protected virtual void OnDraw (SKCanvas canvas)
+ {
+ }
+
+ protected virtual SKRect OnGetBounds () => SKRect.Empty;
+
+ protected virtual SKPicture OnSnapshot ()
+ {
+ using (var recorder = new SKPictureRecorder ()) {
+ var canvas = recorder.BeginRecording (Bounds);
+ Draw (canvas, 0, 0);
+ return recorder.EndRecording ();
+ }
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedDrawableDrawProxyDelegate))]
+ private static void DrawInternal (IntPtr d, void* context, IntPtr canvas)
+ {
+ var drawable = DelegateProxies.GetUserData<SKDrawable> ((IntPtr)context, out _);
+ drawable.OnDraw (GetObject<SKCanvas> (canvas, false));
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedDrawableGetBoundsProxyDelegate))]
+ private static void GetBoundsInternal (IntPtr d, void* context, SKRect* rect)
+ {
+ var drawable = DelegateProxies.GetUserData<SKDrawable> ((IntPtr)context, out _);
+ var bounds = drawable.OnGetBounds ();
+ *rect = bounds;
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedDrawableNewPictureSnapshotProxyDelegate))]
+ private static IntPtr NewPictureSnapshotInternal (IntPtr d, void* context)
+ {
+ var drawable = DelegateProxies.GetUserData<SKDrawable> ((IntPtr)context, out _);
+ return drawable.OnSnapshot ()?.Handle ?? IntPtr.Zero;
+ }
+
+ [MonoPInvokeCallback (typeof (SKManagedDrawableDestroyProxyDelegate))]
+ private static void DestroyInternal (IntPtr d, void* context)
+ {
+ var drawable = DelegateProxies.GetUserData<SKDrawable> ((IntPtr)context, out var gch);
+ if (drawable != null) {
+ Interlocked.Exchange (ref drawable.fromNative, 1);
+ drawable.Dispose ();
+ }
+ gch.Free ();
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace SkiaSharp
+{
+ public unsafe class SKFontManager : SKObject, ISKReferenceCounted
+ {
+ private static readonly Lazy<SKFontManager> defaultManager;
+
+ static SKFontManager()
+ {
+ defaultManager = new Lazy<SKFontManager> (() => new SKFontManagerStatic (SkiaApi.sk_fontmgr_ref_default ()));
+ }
+
+ internal static void EnsureStaticInstanceAreInitialized ()
+ {
+ // IMPORTANT: do not remove to ensure that the static instances
+ // are initialized before any access is made to them
+ }
+
+ [Preserve]
+ internal SKFontManager (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public static SKFontManager Default => defaultManager.Value;
+
+ public int FontFamilyCount => SkiaApi.sk_fontmgr_count_families (Handle);
+
+ public IEnumerable<string> FontFamilies {
+ get {
+ var count = FontFamilyCount;
+ for (var i = 0; i < count; i++) {
+ yield return GetFamilyName (i);
+ }
+ }
+ }
+
+ public string GetFamilyName (int index)
+ {
+ using (var str = new SKString ()) {
+ SkiaApi.sk_fontmgr_get_family_name (Handle, index, str.Handle);
+ return (string)str;
+ }
+ }
+
+ public string[] GetFontFamilies () => FontFamilies.ToArray ();
+
+ public SKFontStyleSet GetFontStyles (int index)
+ {
+ return GetObject<SKFontStyleSet> (SkiaApi.sk_fontmgr_create_styleset (Handle, index));
+ }
+
+ public SKFontStyleSet GetFontStyles (string familyName)
+ {
+ return GetObject<SKFontStyleSet> (SkiaApi.sk_fontmgr_match_family (Handle, familyName));
+ }
+
+ public SKTypeface MatchFamily (string familyName, SKFontStyle style)
+ {
+ if (style == null)
+ throw new ArgumentNullException (nameof (style));
+
+ return GetObject<SKTypeface> (SkiaApi.sk_fontmgr_match_family_style (Handle, familyName, style.Handle));
+ }
+
+ public SKTypeface MatchTypeface (SKTypeface face, SKFontStyle style)
+ {
+ if (face == null)
+ throw new ArgumentNullException (nameof (face));
+ if (style == null)
+ throw new ArgumentNullException (nameof (style));
+
+ return GetObject<SKTypeface> (SkiaApi.sk_fontmgr_match_face_style (Handle, face.Handle, style.Handle));
+ }
+
+ public SKTypeface CreateTypeface (string path, int index = 0)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+
+ var utf8path = StringUtilities.GetEncodedText (path, SKTextEncoding.Utf8);
+ fixed (byte* u = utf8path) {
+ return GetObject<SKTypeface> (SkiaApi.sk_fontmgr_create_from_file (Handle, u, index));
+ }
+ }
+
+ public SKTypeface CreateTypeface (Stream stream, int index = 0)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ return CreateTypeface (new SKManagedStream (stream, true), index);
+ }
+
+ public SKTypeface CreateTypeface (SKStreamAsset stream, int index = 0)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ if (stream is SKManagedStream managed) {
+ stream = managed.ToMemoryStream ();
+ managed.Dispose ();
+ }
+
+ var typeface = GetObject<SKTypeface> (SkiaApi.sk_fontmgr_create_from_stream (Handle, stream.Handle, index));
+ stream.RevokeOwnership (typeface);
+ return typeface;
+ }
+
+ public SKTypeface CreateTypeface (SKData data, int index = 0)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+
+ return GetObject<SKTypeface> (SkiaApi.sk_fontmgr_create_from_data (Handle, data.Handle, index));
+ }
+
+ public SKTypeface MatchCharacter (char character)
+ {
+ return MatchCharacter (null, SKFontStyle.Normal, null, character);
+ }
+
+ public SKTypeface MatchCharacter (int character)
+ {
+ return MatchCharacter (null, SKFontStyle.Normal, null, character);
+ }
+
+ public SKTypeface MatchCharacter (string familyName, char character)
+ {
+ return MatchCharacter (familyName, SKFontStyle.Normal, null, character);
+ }
+
+ public SKTypeface MatchCharacter (string familyName, int character)
+ {
+ return MatchCharacter (familyName, SKFontStyle.Normal, null, character);
+ }
+
+ public SKTypeface MatchCharacter (string familyName, string[] bcp47, char character)
+ {
+ return MatchCharacter (familyName, SKFontStyle.Normal, bcp47, character);
+ }
+
+ public SKTypeface MatchCharacter (string familyName, string[] bcp47, int character)
+ {
+ return MatchCharacter (familyName, SKFontStyle.Normal, bcp47, character);
+ }
+
+ public SKTypeface MatchCharacter (string familyName, SKFontStyleWeight weight, SKFontStyleWidth width, SKFontStyleSlant slant, string[] bcp47, char character)
+ {
+ return MatchCharacter (familyName, new SKFontStyle (weight, width, slant), bcp47, character);
+ }
+
+ public SKTypeface MatchCharacter (string familyName, SKFontStyleWeight weight, SKFontStyleWidth width, SKFontStyleSlant slant, string[] bcp47, int character)
+ {
+ return MatchCharacter (familyName, new SKFontStyle (weight, width, slant), bcp47, character);
+ }
+
+ public SKTypeface MatchCharacter (string familyName, int weight, int width, SKFontStyleSlant slant, string[] bcp47, int character)
+ {
+ return MatchCharacter (familyName, new SKFontStyle (weight, width, slant), bcp47, character);
+ }
+
+ public SKTypeface MatchCharacter (string familyName, SKFontStyle style, string[] bcp47, int character)
+ {
+ if (style == null)
+ throw new ArgumentNullException (nameof (style));
+
+ // TODO: work around for https://bugs.chromium.org/p/skia/issues/detail?id=6196
+ if (familyName == null)
+ familyName = string.Empty;
+
+ return GetObject<SKTypeface> (SkiaApi.sk_fontmgr_match_family_style_character (Handle, familyName, style.Handle, bcp47, bcp47?.Length ?? 0, character));
+ }
+
+ public static SKFontManager CreateDefault ()
+ {
+ return GetObject<SKFontManager> (SkiaApi.sk_fontmgr_create_default ());
+ }
+
+ private sealed class SKFontManagerStatic : SKFontManager
+ {
+ internal SKFontManagerStatic (IntPtr x)
+ : base (x, false)
+ {
+ IgnorePublicDispose = true;
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public class SKFontStyle : SKObject
+ {
+ private static readonly Lazy<SKFontStyle> normal;
+ private static readonly Lazy<SKFontStyle> bold;
+ private static readonly Lazy<SKFontStyle> italic;
+ private static readonly Lazy<SKFontStyle> boldItalic;
+
+ static SKFontStyle()
+ {
+ normal = new Lazy<SKFontStyle> (() => new SKFontStyleStatic (SKFontStyleWeight.Normal, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright));
+ bold = new Lazy<SKFontStyle> (() => new SKFontStyleStatic (SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright));
+ italic = new Lazy<SKFontStyle> (() => new SKFontStyleStatic (SKFontStyleWeight.Normal, SKFontStyleWidth.Normal, SKFontStyleSlant.Italic));
+ boldItalic = new Lazy<SKFontStyle> (() => new SKFontStyleStatic (SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Italic));
+ }
+
+ [Preserve]
+ internal SKFontStyle (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKFontStyle ()
+ : this (SKFontStyleWeight.Normal, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright)
+ {
+ }
+
+ public SKFontStyle (SKFontStyleWeight weight, SKFontStyleWidth width, SKFontStyleSlant slant)
+ : this ((int)weight, (int)width, slant)
+ {
+ }
+
+ public SKFontStyle (int weight, int width, SKFontStyleSlant slant)
+ : this (SkiaApi.sk_fontstyle_new (weight, width, slant), true)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_fontstyle_delete (Handle);
+
+ public int Weight => SkiaApi.sk_fontstyle_get_weight (Handle);
+
+ public int Width => SkiaApi.sk_fontstyle_get_width (Handle);
+
+ public SKFontStyleSlant Slant => SkiaApi.sk_fontstyle_get_slant (Handle);
+
+ public static SKFontStyle Normal => normal.Value;
+
+ public static SKFontStyle Bold => bold.Value;
+
+ public static SKFontStyle Italic => italic.Value;
+
+ public static SKFontStyle BoldItalic => boldItalic.Value;
+
+ private sealed class SKFontStyleStatic : SKFontStyle
+ {
+ internal SKFontStyleStatic (SKFontStyleWeight weight, SKFontStyleWidth width, SKFontStyleSlant slant)
+ : base (weight, width, slant)
+ {
+ IgnorePublicDispose = true;
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace SkiaSharp
+{
+ public class SKFontStyleSet : SKObject, ISKReferenceCounted, IEnumerable<SKFontStyle>, IReadOnlyCollection<SKFontStyle>, IReadOnlyList<SKFontStyle>
+ {
+ [Preserve]
+ internal SKFontStyleSet (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKFontStyleSet ()
+ : this (SkiaApi.sk_fontstyleset_create_empty (), true)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public int Count => SkiaApi.sk_fontstyleset_get_count (Handle);
+
+ public SKFontStyle this[int index] => GetStyle (index);
+
+ public string GetStyleName (int index)
+ {
+ using (var str = new SKString ()) {
+ SkiaApi.sk_fontstyleset_get_style (Handle, index, IntPtr.Zero, str.Handle);
+ return (string)str;
+ }
+ }
+
+ public SKTypeface CreateTypeface (int index)
+ {
+ if (index < 0 || index >= Count)
+ throw new ArgumentOutOfRangeException ($"Index was out of range. Must be non-negative and less than the size of the set.", nameof (index));
+
+ return GetObject<SKTypeface> (SkiaApi.sk_fontstyleset_create_typeface (Handle, index));
+ }
+
+ public SKTypeface CreateTypeface (SKFontStyle style)
+ {
+ if (style == null)
+ throw new ArgumentNullException (nameof (style));
+
+ return GetObject<SKTypeface> (SkiaApi.sk_fontstyleset_match_style (Handle, style.Handle));
+ }
+
+ public IEnumerator<SKFontStyle> GetEnumerator () => GetStyles ().GetEnumerator ();
+
+ IEnumerator IEnumerable.GetEnumerator () => GetStyles ().GetEnumerator ();
+
+ private IEnumerable<SKFontStyle> GetStyles ()
+ {
+ var count = Count;
+ for (var i = 0; i < count; i++) {
+ yield return GetStyle (i);
+ }
+ }
+
+ private SKFontStyle GetStyle (int index)
+ {
+ var fontStyle = new SKFontStyle ();
+ SkiaApi.sk_fontstyleset_get_style (Handle, index, fontStyle.Handle, IntPtr.Zero);
+ return fontStyle;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using System.IO;
+
+namespace SkiaSharp
+{
+ public class SKFrontBufferedManagedStream : SKAbstractManagedStream
+ {
+ private SKStream stream;
+ private bool disposeStream;
+
+ private readonly bool hasLength;
+ private readonly int streamLength;
+ private readonly int bufferLength;
+ private byte[] frontBuffer;
+ private int bufferedSoFar;
+ private int offset;
+
+ public SKFrontBufferedManagedStream (Stream managedStream, int bufferSize)
+ : this (managedStream, bufferSize, false)
+ {
+ }
+
+ public SKFrontBufferedManagedStream (Stream managedStream, int bufferSize, bool disposeUnderlyingStream)
+ : this (new SKManagedStream (managedStream, disposeUnderlyingStream), bufferSize, true)
+ {
+ }
+
+ public SKFrontBufferedManagedStream (SKStream nativeStream, int bufferSize)
+ : this (nativeStream, bufferSize, false)
+ {
+ }
+
+ public SKFrontBufferedManagedStream (SKStream nativeStream, int bufferSize, bool disposeUnderlyingStream)
+ {
+ var length = nativeStream.HasLength ? nativeStream.Length : 0;
+ var position = nativeStream.HasPosition ? nativeStream.Position : 0;
+
+ disposeStream = disposeUnderlyingStream;
+ stream = nativeStream;
+ hasLength = nativeStream.HasPosition && nativeStream.HasLength;
+ streamLength = length - position;
+ offset = 0;
+ bufferedSoFar = 0;
+ bufferLength = bufferSize;
+ frontBuffer = new byte[bufferSize];
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeManaged ()
+ {
+ if (disposeStream && stream != null) {
+ stream.Dispose ();
+ stream = null;
+ }
+
+ base.DisposeManaged ();
+ }
+
+ protected override IntPtr OnRead (IntPtr buffer, IntPtr size)
+ {
+ var start = offset;
+
+ // 1. read any data that was previously buffered
+ if ((int)size > 0 && offset < bufferedSoFar)
+ {
+ var copied = Math.Min ((int)size, bufferedSoFar - offset);
+
+ if (buffer != IntPtr.Zero)
+ {
+ Marshal.Copy (frontBuffer, offset, buffer, copied);
+ buffer += copied;
+ }
+
+ offset += copied;
+ size -= copied;
+ }
+
+ bool isAtEnd = false;
+
+ // 2. buffer any more data, and then read it
+ if ((int)size > 0 && bufferedSoFar < bufferLength)
+ {
+ var bytesToBuffer = Math.Min ((int)size, bufferLength - bufferedSoFar);
+
+ var tempBuffer = Marshal.AllocCoTaskMem (bytesToBuffer);
+ var bytesRead = stream.Read (tempBuffer, bytesToBuffer);
+ Marshal.Copy (tempBuffer, frontBuffer, offset, bytesRead);
+ Marshal.FreeCoTaskMem (tempBuffer);
+
+ isAtEnd = bytesRead < bytesToBuffer;
+
+ bufferedSoFar += bytesRead;
+ if (buffer != IntPtr.Zero)
+ {
+ Marshal.Copy (frontBuffer, offset, buffer, bytesRead);
+ buffer += bytesRead;
+ }
+
+ offset += bytesRead;
+ size -= bytesRead;
+ }
+
+ // 3. read the rest directly
+ if ((int)size > 0 && !isAtEnd)
+ {
+ var bytesRead = stream.Read (buffer, (int)size);
+
+ // past the buffer, so dispose it
+ if (bytesRead > 0)
+ {
+ frontBuffer = null;
+ }
+
+ offset += bytesRead;
+ size -= bytesRead;
+ }
+
+ return (IntPtr)(offset - start);
+ }
+
+ protected override IntPtr OnPeek (IntPtr buffer, IntPtr size)
+ {
+ if (offset >= bufferLength)
+ {
+ // this stream is not able to buffer.
+ return (IntPtr)0;
+ }
+
+ // keep track of the offset so we can return to it.
+ var start = offset;
+
+ var bytesToCopy = Math.Min ((int)size, bufferLength - offset);
+ var bytesRead = Read (buffer, bytesToCopy);
+
+ // return to the original position
+ offset = start;
+
+ return (IntPtr)bytesRead;
+ }
+
+ protected override bool OnIsAtEnd ()
+ {
+ if (offset < bufferedSoFar)
+ {
+ // even if the underlying stream is at the end, this stream has been
+ // rewound after buffering, so it is not at the end.
+ return false;
+ }
+
+ return stream.IsAtEnd;
+ }
+
+ protected override bool OnRewind ()
+ {
+ // only allow a rewind if we have not exceeded the buffer.
+ if (offset <= bufferLength)
+ {
+ offset = 0;
+ return true;
+ }
+
+ return false;
+ }
+
+ protected override bool OnHasLength () => hasLength;
+
+ protected override IntPtr OnGetLength () => (IntPtr)streamLength;
+
+ // seeking is not supported
+ protected override bool OnHasPosition () => false;
+
+ // seeking is not supported
+ protected override IntPtr OnGetPosition () => (IntPtr)0;
+
+ // seeking is not supported
+ protected override bool OnSeek (IntPtr position) => false;
+
+ // seeking is not supported
+ protected override bool OnMove (int offset) => false;
+
+ // duplicating or forking is not supported
+ protected override IntPtr OnCreateNew () => IntPtr.Zero;
+ }
+}
--- /dev/null
+using System;
+using System.IO;
+
+namespace SkiaSharp
+{
+ public class SKFrontBufferedStream : Stream
+ {
+ public const int DefaultBufferSize = 4096;
+
+ private readonly long totalBufferSize;
+ private readonly long totalLength;
+ private readonly bool disposeStream;
+ private Stream underlyingStream;
+
+ private long currentOffset;
+ private long bufferedSoFar;
+ private byte[] internalBuffer;
+
+ public SKFrontBufferedStream(Stream stream)
+ : this(stream, DefaultBufferSize, false)
+ {
+ }
+
+ public SKFrontBufferedStream(Stream stream, long bufferSize)
+ : this(stream, bufferSize, false)
+ {
+ }
+
+ public SKFrontBufferedStream(Stream stream, bool disposeUnderlyingStream)
+ : this(stream, DefaultBufferSize, disposeUnderlyingStream)
+ {
+ }
+
+ public SKFrontBufferedStream(Stream stream, long bufferSize, bool disposeUnderlyingStream)
+ {
+ underlyingStream = stream;
+ totalBufferSize = bufferSize;
+ totalLength = stream.CanSeek ? stream.Length : -1;
+ disposeStream = disposeUnderlyingStream;
+ }
+
+ public override bool CanRead => true;
+
+ public override bool CanSeek => true; // we can seek if we are in the buffer
+
+ public override bool CanWrite => false; // we don't write
+
+ public override long Length => totalLength;
+
+ public override long Position
+ {
+ get { return currentOffset; }
+ set { Seek(value, SeekOrigin.Begin); }
+ }
+
+ public override void Flush()
+ {
+ // we don't write
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ var start = currentOffset;
+
+ if (internalBuffer == null && currentOffset < totalBufferSize)
+ {
+ // create the buffer now, since we are going to be writing to it
+ internalBuffer = new byte[totalBufferSize];
+ }
+
+ // try read any data from the buffer
+ if (currentOffset < bufferedSoFar)
+ {
+ var bytesCopied = ReadFromBuffer(buffer, offset, count);
+ count -= bytesCopied;
+ offset += bytesCopied;
+ }
+
+ // read from the stream and buffer that
+ if (count > 0 && bufferedSoFar < totalBufferSize)
+ {
+ var buffered = BufferAndWriteTo(buffer, offset, count);
+ count -= buffered;
+ offset += buffered;
+ }
+
+ // just read from the stream
+ if (count > 0)
+ {
+ var direct = ReadDirectlyFromStream(buffer, offset, count);
+ count -= direct;
+ offset += direct;
+
+ if (direct > 0)
+ {
+ // if we are here, we are past the buffer and can't go back
+ internalBuffer = null;
+ }
+ }
+
+ return (int)(currentOffset - start);
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ // we are outside the buffer, so throw
+ if (currentOffset > totalBufferSize)
+ {
+ throw new InvalidOperationException("The position cannot be changed once the stream has moved past the buffer.");
+ }
+
+ // find the absolute position
+ var absolute = offset;
+ if (origin == SeekOrigin.Current)
+ {
+ absolute = Position + offset;
+ }
+ else if (origin == SeekOrigin.End)
+ {
+ if (Length == -1)
+ {
+ throw new InvalidOperationException("Can't seek from end as the underlying stream is not seekable.");
+ }
+ absolute = Length + offset;
+ }
+
+ // move to the position
+ if (absolute <= currentOffset)
+ {
+ // we are moving back, so just move the local cursor
+ currentOffset = absolute;
+ }
+ else
+ {
+ // we are moving forward, so we have to read into the buffer
+ var toMove = absolute - currentOffset;
+ currentOffset += Read(null, 0, (int)toMove);
+ }
+
+ return Position;
+ }
+
+ public override void SetLength(long value)
+ {
+ // we don't write
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ // we don't write
+ }
+
+ private int ReadFromBuffer(byte[] dst, int offset, int size)
+ {
+ var bytesToCopy = Math.Min(size, (int)(bufferedSoFar - currentOffset));
+
+ if (dst != null && offset < dst.Length)
+ {
+ Buffer.BlockCopy(internalBuffer, (int)currentOffset, dst, offset, bytesToCopy);
+ }
+
+ currentOffset += bytesToCopy;
+
+ return bytesToCopy;
+ }
+
+ private int BufferAndWriteTo(byte[] dst, int offset, int size)
+ {
+ var bytesToBuffer = Math.Min(size, (int)(totalBufferSize - bufferedSoFar));
+ var buffered = underlyingStream.Read(internalBuffer, (int)currentOffset, bytesToBuffer);
+
+ if (dst != null && offset < dst.Length)
+ {
+ Buffer.BlockCopy(internalBuffer, (int)currentOffset, dst, offset, buffered);
+ }
+
+ bufferedSoFar += buffered;
+ currentOffset = bufferedSoFar;
+
+ return buffered;
+ }
+
+ private int ReadDirectlyFromStream(byte[] dst, int offset, int size)
+ {
+ long bytesReadDirectly = 0;
+
+ if (dst == null)
+ {
+ bytesReadDirectly = underlyingStream.Seek(size, SeekOrigin.Current);
+ }
+ else
+ {
+ bytesReadDirectly = underlyingStream.Read(dst, offset, size);
+ }
+
+ currentOffset += bytesReadDirectly;
+
+ return (int)bytesReadDirectly;
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ internalBuffer = null;
+ if (disposeStream && underlyingStream != null)
+ {
+ underlyingStream.Dispose();
+ }
+ underlyingStream = null;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ // TODO: `MakeCrossContextFromEncoded`
+ // TODO: `MakeFromYUVTexturesCopy` and `MakeFromNV12TexturesCopy`
+ // TODO: `FromPicture` with bit depth and color space
+ // TODO: `GetTextureHandle`
+ // TODO: `MakeColorSpace`
+
+ public unsafe class SKImage : SKObject, ISKReferenceCounted
+ {
+ [Preserve]
+ internal SKImage (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ // create brand new image
+
+ public static SKImage Create (SKImageInfo info)
+ {
+ var pixels = Marshal.AllocCoTaskMem (info.BytesSize);
+ using (var pixmap = new SKPixmap (info, pixels)) {
+ // don't use the managed version as that is just extra overhead which isn't necessary
+ return GetObject<SKImage> (SkiaApi.sk_image_new_raster (pixmap.Handle, DelegateProxies.SKImageRasterReleaseDelegateProxyForCoTaskMem, null));
+ }
+ }
+
+ // create a new image from a copy of pixel data
+
+ public static SKImage FromPixelCopy (SKImageInfo info, SKStream pixels) =>
+ FromPixelCopy (info, pixels, info.RowBytes);
+
+ public static SKImage FromPixelCopy (SKImageInfo info, SKStream pixels, int rowBytes)
+ {
+ if (pixels == null)
+ throw new ArgumentNullException (nameof (pixels));
+ using (var data = SKData.Create (pixels)) {
+ return FromPixels (info, data, rowBytes);
+ }
+ }
+
+ public static SKImage FromPixelCopy (SKImageInfo info, Stream pixels) =>
+ FromPixelCopy (info, pixels, info.RowBytes);
+
+ public static SKImage FromPixelCopy (SKImageInfo info, Stream pixels, int rowBytes)
+ {
+ if (pixels == null)
+ throw new ArgumentNullException (nameof (pixels));
+ using (var data = SKData.Create (pixels)) {
+ return FromPixels (info, data, rowBytes);
+ }
+ }
+
+ public static SKImage FromPixelCopy (SKImageInfo info, byte[] pixels) =>
+ FromPixelCopy (info, pixels, info.RowBytes);
+
+ public static SKImage FromPixelCopy (SKImageInfo info, byte[] pixels, int rowBytes)
+ {
+ if (pixels == null)
+ throw new ArgumentNullException (nameof (pixels));
+ using (var data = SKData.CreateCopy (pixels)) {
+ return FromPixels (info, data, rowBytes);
+ }
+ }
+
+ public static SKImage FromPixelCopy (SKImageInfo info, IntPtr pixels) =>
+ FromPixelCopy (info, pixels, info.RowBytes);
+
+ public static SKImage FromPixelCopy (SKImageInfo info, IntPtr pixels, int rowBytes)
+ {
+ if (pixels == IntPtr.Zero)
+ throw new ArgumentNullException (nameof (pixels));
+
+ var nInfo = SKImageInfoNative.FromManaged (ref info);
+ return GetObject<SKImage> (SkiaApi.sk_image_new_raster_copy (&nInfo, (void*)pixels, (IntPtr)rowBytes));
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use FromPixelCopy(SKImageInfo, IntPtr, int) instead.")]
+ public static SKImage FromPixelCopy (SKImageInfo info, IntPtr pixels, int rowBytes, SKColorTable ctable) =>
+ FromPixelCopy (info, pixels, rowBytes);
+
+ public static SKImage FromPixelCopy (SKPixmap pixmap)
+ {
+ if (pixmap == null)
+ throw new ArgumentNullException (nameof (pixmap));
+ return GetObject<SKImage> (SkiaApi.sk_image_new_raster_copy_with_pixmap (pixmap.Handle));
+ }
+
+ public static SKImage FromPixelCopy (SKImageInfo info, ReadOnlySpan<byte> pixels) =>
+ FromPixelCopy (info, pixels, info.RowBytes);
+
+ public static SKImage FromPixelCopy (SKImageInfo info, ReadOnlySpan<byte> pixels, int rowBytes)
+ {
+ if (pixels == null)
+ throw new ArgumentNullException (nameof (pixels));
+ using (var data = SKData.CreateCopy (pixels)) {
+ return FromPixels (info, data, rowBytes);
+ }
+ }
+
+ // create a new image around existing pixel data
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromPixels (SKImageInfo, SKData, int) instead.")]
+ public static SKImage FromPixelData (SKImageInfo info, SKData data, int rowBytes)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ return GetObject<SKImage> (SkiaApi.sk_image_new_raster_data (&cinfo, data.Handle, (IntPtr)rowBytes));
+ }
+
+ public static SKImage FromPixels (SKImageInfo info, SKData data) =>
+ FromPixels (info, data, info.RowBytes);
+
+ public static SKImage FromPixels (SKImageInfo info, SKData data, int rowBytes)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ return GetObject<SKImage> (SkiaApi.sk_image_new_raster_data (&cinfo, data.Handle, (IntPtr)rowBytes));
+ }
+
+ public static SKImage FromPixels (SKImageInfo info, IntPtr pixels)
+ {
+ using (var pixmap = new SKPixmap (info, pixels, info.RowBytes)) {
+ return FromPixels (pixmap, null, null);
+ }
+ }
+
+ public static SKImage FromPixels (SKImageInfo info, IntPtr pixels, int rowBytes)
+ {
+ using (var pixmap = new SKPixmap (info, pixels, rowBytes)) {
+ return FromPixels (pixmap, null, null);
+ }
+ }
+
+ public static SKImage FromPixels (SKPixmap pixmap)
+ {
+ return FromPixels (pixmap, null, null);
+ }
+
+ public static SKImage FromPixels (SKPixmap pixmap, SKImageRasterReleaseDelegate releaseProc)
+ {
+ return FromPixels (pixmap, releaseProc, null);
+ }
+
+ public static SKImage FromPixels (SKPixmap pixmap, SKImageRasterReleaseDelegate releaseProc, object releaseContext)
+ {
+ if (pixmap == null)
+ throw new ArgumentNullException (nameof (pixmap));
+
+ var del = releaseProc != null && releaseContext != null
+ ? new SKImageRasterReleaseDelegate ((addr, _) => releaseProc (addr, releaseContext))
+ : releaseProc;
+ var proxy = DelegateProxies.Create (del, DelegateProxies.SKImageRasterReleaseDelegateProxy, out _, out var ctx);
+ return GetObject<SKImage> (SkiaApi.sk_image_new_raster (pixmap.Handle, proxy, (void*)ctx));
+ }
+
+ // create a new image from encoded data
+
+ public static SKImage FromEncodedData (SKData data, SKRectI subset)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+
+ var handle = SkiaApi.sk_image_new_from_encoded (data.Handle, &subset);
+ return GetObject<SKImage> (handle);
+ }
+
+ public static SKImage FromEncodedData (SKData data)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+
+ var handle = SkiaApi.sk_image_new_from_encoded (data.Handle, null);
+ return GetObject<SKImage> (handle);
+ }
+
+ public static SKImage FromEncodedData (ReadOnlySpan<byte> data)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+ if (data.Length == 0)
+ throw new ArgumentException ("The data buffer was empty.");
+
+ using (var skdata = SKData.CreateCopy (data)) {
+ return FromEncodedData (skdata);
+ }
+ }
+
+ public static SKImage FromEncodedData (byte[] data)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+ if (data.Length == 0)
+ throw new ArgumentException ("The data buffer was empty.");
+
+ using (var skdata = SKData.CreateCopy (data)) {
+ return FromEncodedData (skdata);
+ }
+ }
+
+ public static SKImage FromEncodedData (SKStream data)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+
+ using (var skdata = SKData.Create (data)) {
+ if (skdata == null)
+ return null;
+ return FromEncodedData (skdata);
+ }
+ }
+
+ public static SKImage FromEncodedData (Stream data)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+
+ using (var skdata = SKData.Create (data)) {
+ if (skdata == null)
+ return null;
+ return FromEncodedData (skdata);
+ }
+ }
+
+ public static SKImage FromEncodedData (string filename)
+ {
+ if (filename == null)
+ throw new ArgumentNullException (nameof (filename));
+
+ using (var skdata = SKData.Create (filename)) {
+ if (skdata == null)
+ return null;
+ return FromEncodedData (skdata);
+ }
+ }
+
+ // create a new image from a bitmap
+
+ public static SKImage FromBitmap (SKBitmap bitmap)
+ {
+ if (bitmap == null)
+ throw new ArgumentNullException (nameof (bitmap));
+
+ var image = GetObject<SKImage> (SkiaApi.sk_image_new_from_bitmap (bitmap.Handle));
+ GC.KeepAlive (bitmap);
+ return image;
+ }
+
+ // create a new image from a GPU texture
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType) instead.")]
+ public static SKImage FromTexture (GRContext context, GRBackendTextureDesc desc)
+ {
+ return FromTexture (context, desc, SKAlphaType.Premul, null, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType, SKAlphaType) instead.")]
+ public static SKImage FromTexture (GRContext context, GRBackendTextureDesc desc, SKAlphaType alpha)
+ {
+ return FromTexture (context, desc, alpha, null, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType, SKAlphaType, SKColorSpace, SKImageTextureReleaseDelegate) instead.")]
+ public static SKImage FromTexture (GRContext context, GRBackendTextureDesc desc, SKAlphaType alpha, SKImageTextureReleaseDelegate releaseProc)
+ {
+ return FromTexture (context, desc, alpha, releaseProc, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType, SKAlphaType, SKColorSpace, SKImageTextureReleaseDelegate, object) instead.")]
+ public static SKImage FromTexture (GRContext context, GRBackendTextureDesc desc, SKAlphaType alpha, SKImageTextureReleaseDelegate releaseProc, object releaseContext)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+
+ var texture = new GRBackendTexture (desc);
+ return FromTexture (context, texture, desc.Origin, desc.Config.ToColorType (), alpha, null, releaseProc, releaseContext);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType) instead.")]
+ public static SKImage FromTexture (GRContext context, GRGlBackendTextureDesc desc)
+ {
+ return FromTexture (context, desc, SKAlphaType.Premul, null, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType, SKAlphaType) instead.")]
+ public static SKImage FromTexture (GRContext context, GRGlBackendTextureDesc desc, SKAlphaType alpha)
+ {
+ return FromTexture (context, desc, alpha, null, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType, SKAlphaType, SKColorSpace, SKImageTextureReleaseDelegate) instead.")]
+ public static SKImage FromTexture (GRContext context, GRGlBackendTextureDesc desc, SKAlphaType alpha, SKImageTextureReleaseDelegate releaseProc)
+ {
+ return FromTexture (context, desc, alpha, releaseProc, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType, SKAlphaType, SKColorSpace, SKImageTextureReleaseDelegate, object) instead.")]
+ public static SKImage FromTexture (GRContext context, GRGlBackendTextureDesc desc, SKAlphaType alpha, SKImageTextureReleaseDelegate releaseProc, object releaseContext)
+ {
+ var texture = new GRBackendTexture (desc);
+ return FromTexture (context, texture, desc.Origin, desc.Config.ToColorType (), alpha, null, releaseProc, releaseContext);
+ }
+
+ public static SKImage FromTexture (GRContext context, GRBackendTexture texture, SKColorType colorType)
+ {
+ return FromTexture (context, texture, GRSurfaceOrigin.BottomLeft, colorType, SKAlphaType.Premul, null, null, null);
+ }
+
+ public static SKImage FromTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType)
+ {
+ return FromTexture (context, texture, origin, colorType, SKAlphaType.Premul, null, null, null);
+ }
+
+ public static SKImage FromTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha)
+ {
+ return FromTexture (context, texture, origin, colorType, alpha, null, null, null);
+ }
+
+ public static SKImage FromTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, SKColorSpace colorspace)
+ {
+ return FromTexture (context, texture, origin, colorType, alpha, colorspace, null, null);
+ }
+
+ public static SKImage FromTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, SKColorSpace colorspace, SKImageTextureReleaseDelegate releaseProc)
+ {
+ return FromTexture (context, texture, origin, colorType, alpha, colorspace, releaseProc, null);
+ }
+
+ public static SKImage FromTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, SKColorSpace colorspace, SKImageTextureReleaseDelegate releaseProc, object releaseContext)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+ if (texture == null)
+ throw new ArgumentNullException (nameof (texture));
+
+ var cs = colorspace == null ? IntPtr.Zero : colorspace.Handle;
+ var del = releaseProc != null && releaseContext != null
+ ? new SKImageTextureReleaseDelegate ((_) => releaseProc (releaseContext))
+ : releaseProc;
+ var proxy = DelegateProxies.Create (del, DelegateProxies.SKImageTextureReleaseDelegateProxy, out _, out var ctx);
+ return GetObject<SKImage> (SkiaApi.sk_image_new_from_texture (context.Handle, texture.Handle, origin, colorType, alpha, cs, proxy, (void*)ctx));
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromAdoptedTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType) instead.")]
+ public static SKImage FromAdoptedTexture (GRContext context, GRBackendTextureDesc desc)
+ {
+ return FromAdoptedTexture (context, desc, SKAlphaType.Premul);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromAdoptedTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType, SKAlphaType) instead.")]
+ public static SKImage FromAdoptedTexture (GRContext context, GRBackendTextureDesc desc, SKAlphaType alpha)
+ {
+ var texture = new GRBackendTexture (desc);
+ return FromAdoptedTexture (context, texture, desc.Origin, desc.Config.ToColorType (), alpha, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromAdoptedTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType) instead.")]
+ public static SKImage FromAdoptedTexture (GRContext context, GRGlBackendTextureDesc desc)
+ {
+ return FromAdoptedTexture (context, desc, SKAlphaType.Premul);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromAdoptedTexture(GRContext, GRBackendTexture, GRSurfaceOrigin, SKColorType, SKAlphaType) instead.")]
+ public static SKImage FromAdoptedTexture (GRContext context, GRGlBackendTextureDesc desc, SKAlphaType alpha)
+ {
+ var texture = new GRBackendTexture (desc);
+ return FromAdoptedTexture (context, texture, desc.Origin, desc.Config.ToColorType (), alpha, null);
+ }
+
+ public static SKImage FromAdoptedTexture (GRContext context, GRBackendTexture texture, SKColorType colorType)
+ {
+ return FromAdoptedTexture (context, texture, GRSurfaceOrigin.BottomLeft, colorType, SKAlphaType.Premul, null);
+ }
+
+ public static SKImage FromAdoptedTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType)
+ {
+ return FromAdoptedTexture (context, texture, origin, colorType, SKAlphaType.Premul, null);
+ }
+
+ public static SKImage FromAdoptedTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha)
+ {
+ return FromAdoptedTexture (context, texture, origin, colorType, alpha, null);
+ }
+
+ public static SKImage FromAdoptedTexture (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, SKColorSpace colorspace)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+ if (texture == null)
+ throw new ArgumentNullException (nameof (texture));
+
+ var cs = colorspace == null ? IntPtr.Zero : colorspace.Handle;
+ return GetObject<SKImage> (SkiaApi.sk_image_new_from_adopted_texture (context.Handle, texture.Handle, origin, colorType, alpha, cs));
+ }
+
+ // create a new image from a picture
+
+ public static SKImage FromPicture (SKPicture picture, SKSizeI dimensions) =>
+ FromPicture (picture, dimensions, null, null);
+
+ public static SKImage FromPicture (SKPicture picture, SKSizeI dimensions, SKMatrix matrix) =>
+ FromPicture (picture, dimensions, &matrix, null);
+
+ public static SKImage FromPicture (SKPicture picture, SKSizeI dimensions, SKPaint paint) =>
+ FromPicture (picture, dimensions, null, paint);
+
+ public static SKImage FromPicture (SKPicture picture, SKSizeI dimensions, SKMatrix matrix, SKPaint paint) =>
+ FromPicture (picture, dimensions, &matrix, paint);
+
+ private static SKImage FromPicture (SKPicture picture, SKSizeI dimensions, SKMatrix* matrix, SKPaint paint)
+ {
+ if (picture == null)
+ throw new ArgumentNullException (nameof (picture));
+
+ var p = paint?.Handle ?? IntPtr.Zero;
+ return GetObject<SKImage> (SkiaApi.sk_image_new_from_picture (picture.Handle, &dimensions, matrix, p));
+ }
+
+ public SKData Encode () =>
+ GetObject<SKData> (SkiaApi.sk_image_encode (Handle));
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public SKData Encode (SKPixelSerializer serializer)
+ {
+ if (serializer == null)
+ throw new ArgumentNullException (nameof (serializer));
+
+ // try old data
+ var encoded = EncodedData;
+ if (encoded != null) {
+ if (serializer.UseEncodedData (encoded.Data, (ulong)encoded.Size)) {
+ return encoded;
+ } else {
+ encoded.Dispose ();
+ encoded = null;
+ }
+ }
+
+ // get new data (raster)
+ if (!IsTextureBacked) {
+ using (var pixmap = PeekPixels ()) {
+ return serializer.Encode (pixmap);
+ }
+ }
+
+ // get new data (texture / gpu)
+ // this involves a copy from gpu to cpu first
+ if (IsTextureBacked) {
+ var info = new SKImageInfo (Width, Height, ColorType, AlphaType, ColorSpace);
+ using (var temp = new SKBitmap (info))
+ using (var pixmap = temp.PeekPixels ()) {
+ if (pixmap != null && ReadPixels (pixmap, 0, 0)) {
+ return serializer.Encode (pixmap);
+ }
+ }
+ }
+
+ // some error
+ return null;
+ }
+
+ public SKData Encode (SKEncodedImageFormat format, int quality)
+ {
+ return GetObject<SKData> (SkiaApi.sk_image_encode_specific (Handle, format, quality));
+ }
+
+ public int Width =>
+ SkiaApi.sk_image_get_width (Handle);
+
+ public int Height =>
+ SkiaApi.sk_image_get_height (Handle);
+
+ public uint UniqueId =>
+ SkiaApi.sk_image_get_unique_id (Handle);
+
+ public SKAlphaType AlphaType =>
+ SkiaApi.sk_image_get_alpha_type (Handle);
+
+ public SKColorType ColorType =>
+ SkiaApi.sk_image_get_color_type (Handle);
+
+ public SKColorSpace ColorSpace =>
+ GetObject<SKColorSpace> (SkiaApi.sk_image_get_colorspace (Handle));
+
+ public bool IsAlphaOnly =>
+ SkiaApi.sk_image_is_alpha_only (Handle);
+
+ public SKData EncodedData =>
+ GetObject<SKData> (SkiaApi.sk_image_ref_encoded (Handle));
+
+ // ToShader
+
+ public SKShader ToShader () =>
+ ToShader (SKShaderTileMode.Clamp, SKShaderTileMode.Clamp);
+
+ public SKShader ToShader (SKShaderTileMode tileX, SKShaderTileMode tileY) =>
+ GetObject<SKShader> (SkiaApi.sk_image_make_shader (Handle, tileX, tileY, null));
+
+ public SKShader ToShader (SKShaderTileMode tileX, SKShaderTileMode tileY, SKMatrix localMatrix) =>
+ GetObject<SKShader> (SkiaApi.sk_image_make_shader (Handle, tileX, tileY, &localMatrix));
+
+ // PeekPixels
+
+ public bool PeekPixels (SKPixmap pixmap)
+ {
+ if (pixmap == null)
+ throw new ArgumentNullException (nameof (pixmap));
+
+ var result = SkiaApi.sk_image_peek_pixels (Handle, pixmap.Handle);
+ if (result)
+ pixmap.pixelSource = this;
+ return result;
+ }
+
+ public SKPixmap PeekPixels ()
+ {
+ var pixmap = new SKPixmap ();
+ if (!PeekPixels (pixmap)) {
+ pixmap.Dispose ();
+ pixmap = null;
+ }
+ return pixmap;
+ }
+
+ public bool IsTextureBacked =>
+ SkiaApi.sk_image_is_texture_backed (Handle);
+
+ public bool IsLazyGenerated =>
+ SkiaApi.sk_image_is_lazy_generated (Handle);
+
+ public bool IsValid (GRContext context) =>
+ SkiaApi.sk_image_is_valid (Handle, context?.Handle ?? IntPtr.Zero);
+
+ // ReadPixels
+
+ public bool ReadPixels (SKImageInfo dstInfo, IntPtr dstPixels) =>
+ ReadPixels (dstInfo, dstPixels, dstInfo.RowBytes, 0, 0, SKImageCachingHint.Allow);
+
+ public bool ReadPixels (SKImageInfo dstInfo, IntPtr dstPixels, int dstRowBytes) =>
+ ReadPixels (dstInfo, dstPixels, dstRowBytes, 0, 0, SKImageCachingHint.Allow);
+
+ public bool ReadPixels (SKImageInfo dstInfo, IntPtr dstPixels, int dstRowBytes, int srcX, int srcY) =>
+ ReadPixels (dstInfo, dstPixels, dstRowBytes, srcX, srcY, SKImageCachingHint.Allow);
+
+ public bool ReadPixels (SKImageInfo dstInfo, IntPtr dstPixels, int dstRowBytes, int srcX, int srcY, SKImageCachingHint cachingHint)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref dstInfo);
+ return SkiaApi.sk_image_read_pixels (Handle, &cinfo, (void*)dstPixels, (IntPtr)dstRowBytes, srcX, srcY, cachingHint);
+ }
+
+ public bool ReadPixels (SKPixmap pixmap) =>
+ ReadPixels (pixmap, 0, 0, SKImageCachingHint.Allow);
+
+ public bool ReadPixels (SKPixmap pixmap, int srcX, int srcY) =>
+ ReadPixels (pixmap, srcX, srcY, SKImageCachingHint.Allow);
+
+ public bool ReadPixels (SKPixmap pixmap, int srcX, int srcY, SKImageCachingHint cachingHint)
+ {
+ if (pixmap == null)
+ throw new ArgumentNullException (nameof (pixmap));
+
+ return SkiaApi.sk_image_read_pixels_into_pixmap (Handle, pixmap.Handle, srcX, srcY, cachingHint);
+ }
+
+ // ScalePixels
+
+ public bool ScalePixels (SKPixmap dst, SKFilterQuality quality)
+ {
+ return ScalePixels (dst, quality, SKImageCachingHint.Allow);
+ }
+
+ public bool ScalePixels (SKPixmap dst, SKFilterQuality quality, SKImageCachingHint cachingHint)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ return SkiaApi.sk_image_scale_pixels (Handle, dst.Handle, quality, cachingHint);
+ }
+
+ // Subset
+
+ public SKImage Subset (SKRectI subset)
+ {
+ return GetObject<SKImage> (SkiaApi.sk_image_make_subset (Handle, &subset));
+ }
+
+ // ToRasterImage
+
+ public SKImage ToRasterImage () =>
+ ToRasterImage (false);
+
+ public SKImage ToRasterImage (bool ensurePixelData) =>
+ ensurePixelData
+ ? GetObject<SKImage> (SkiaApi.sk_image_make_raster_image (Handle))
+ : GetObject<SKImage> (SkiaApi.sk_image_make_non_texture_image (Handle));
+
+ // ToTextureImage
+
+ public SKImage ToTextureImage (GRContext context) =>
+ ToTextureImage (context, null);
+
+ public SKImage ToTextureImage (GRContext context, SKColorSpace colorspace)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+
+ return GetObject<SKImage> (SkiaApi.sk_image_make_texture_image (Handle, context.Handle, colorspace?.Handle ?? IntPtr.Zero));
+ }
+
+ // ApplyImageFilter
+
+ public SKImage ApplyImageFilter (SKImageFilter filter, SKRectI subset, SKRectI clipBounds, out SKRectI outSubset, out SKPoint outOffset)
+ {
+ var image = ApplyImageFilter (filter, subset, clipBounds, out outSubset, out SKPointI outOffsetActual);
+ outOffset = outOffsetActual;
+ return image;
+ }
+
+ public SKImage ApplyImageFilter (SKImageFilter filter, SKRectI subset, SKRectI clipBounds, out SKRectI outSubset, out SKPointI outOffset)
+ {
+ if (filter == null)
+ throw new ArgumentNullException (nameof (filter));
+
+ fixed (SKRectI* os = &outSubset)
+ fixed (SKPointI* oo = &outOffset) {
+ return GetObject<SKImage> (SkiaApi.sk_image_make_with_filter (Handle, filter.Handle, &subset, &clipBounds, os, oo));
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ // TODO: `asAColorFilter`
+ // TODO: `countInputs`, `getInput`
+ // TODO: `cropRectIsSet`, `getCropRect`
+ // TODO: `computeFastBounds`, `canComputeFastBounds`
+
+ public unsafe class SKImageFilter : SKObject, ISKReferenceCounted
+ {
+ [Preserve]
+ internal SKImageFilter(IntPtr handle, bool owns)
+ : base(handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ // CreateMatrix
+
+ public static SKImageFilter CreateMatrix(SKMatrix matrix, SKFilterQuality quality, SKImageFilter input = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_matrix(&matrix, quality, input == null ? IntPtr.Zero : input.Handle));
+ }
+
+ // CreateAlphaThreshold
+
+ public static SKImageFilter CreateAlphaThreshold(SKRectI region, float innerThreshold, float outerThreshold, SKImageFilter input = null)
+ {
+ var reg = new SKRegion ();
+ reg.SetRect (region);
+ return CreateAlphaThreshold (reg, innerThreshold, outerThreshold, input);
+
+ }
+
+ public static SKImageFilter CreateAlphaThreshold(SKRegion region, float innerThreshold, float outerThreshold, SKImageFilter input = null)
+ {
+ if (region == null)
+ throw new ArgumentNullException (nameof (region));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_alpha_threshold(region.Handle, innerThreshold, outerThreshold, input == null ? IntPtr.Zero : input.Handle));
+ }
+
+ // CreateBlur
+
+ public static SKImageFilter CreateBlur(float sigmaX, float sigmaY, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_blur(sigmaX, sigmaY, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateColorFilter
+
+ public static SKImageFilter CreateColorFilter(SKColorFilter cf, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ if (cf == null)
+ throw new ArgumentNullException(nameof(cf));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_color_filter(cf.Handle, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateCompose
+
+ public static SKImageFilter CreateCompose(SKImageFilter outer, SKImageFilter inner)
+ {
+ if (outer == null)
+ throw new ArgumentNullException(nameof(outer));
+ if (inner == null)
+ throw new ArgumentNullException(nameof(inner));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_compose(outer.Handle, inner.Handle));
+ }
+
+ // CreateDisplacementMapEffect
+
+ public static SKImageFilter CreateDisplacementMapEffect(SKDisplacementMapEffectChannelSelectorType xChannelSelector, SKDisplacementMapEffectChannelSelectorType yChannelSelector, float scale, SKImageFilter displacement, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ if (displacement == null)
+ throw new ArgumentNullException(nameof(displacement));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_displacement_map_effect(xChannelSelector, yChannelSelector, scale, displacement.Handle, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateDropShadow
+
+ public static SKImageFilter CreateDropShadow(float dx, float dy, float sigmaX, float sigmaY, SKColor color, SKDropShadowImageFilterShadowMode shadowMode, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_drop_shadow(dx, dy, sigmaX, sigmaY, (uint)color, shadowMode, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // Create*LitDiffuse
+
+ public static SKImageFilter CreateDistantLitDiffuse(SKPoint3 direction, SKColor lightColor, float surfaceScale, float kd, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_distant_lit_diffuse(&direction, (uint)lightColor, surfaceScale, kd, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ public static SKImageFilter CreatePointLitDiffuse(SKPoint3 location, SKColor lightColor, float surfaceScale, float kd, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_point_lit_diffuse(&location, (uint)lightColor, surfaceScale, kd, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ public static SKImageFilter CreateSpotLitDiffuse(SKPoint3 location, SKPoint3 target, float specularExponent, float cutoffAngle, SKColor lightColor, float surfaceScale, float kd, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_spot_lit_diffuse(&location, &target, specularExponent, cutoffAngle, (uint)lightColor, surfaceScale, kd, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // Create*LitSpecular
+
+ public static SKImageFilter CreateDistantLitSpecular(SKPoint3 direction, SKColor lightColor, float surfaceScale, float ks, float shininess, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_distant_lit_specular(&direction, (uint)lightColor, surfaceScale, ks, shininess, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ public static SKImageFilter CreatePointLitSpecular(SKPoint3 location, SKColor lightColor, float surfaceScale, float ks, float shininess, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_point_lit_specular(&location, (uint)lightColor, surfaceScale, ks, shininess, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ public static SKImageFilter CreateSpotLitSpecular(SKPoint3 location, SKPoint3 target, float specularExponent, float cutoffAngle, SKColor lightColor, float surfaceScale, float ks, float shininess, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_spot_lit_specular(&location, &target, specularExponent, cutoffAngle, (uint)lightColor, surfaceScale, ks, shininess, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateMagnifier
+
+ public static SKImageFilter CreateMagnifier(SKRect src, float inset, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_magnifier(&src, inset, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateMatrixConvolution
+
+ public static SKImageFilter CreateMatrixConvolution(SKSizeI kernelSize, float[] kernel, float gain, float bias, SKPointI kernelOffset, SKMatrixConvolutionTileMode tileMode, bool convolveAlpha, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ if (kernel == null)
+ throw new ArgumentNullException(nameof(kernel));
+ if (kernel.Length != kernelSize.Width * kernelSize.Height)
+ throw new ArgumentException("Kernel length must match the dimensions of the kernel size (Width * Height).", nameof(kernel));
+ fixed (float* k = kernel) {
+ return GetObject<SKImageFilter> (SkiaApi.sk_imagefilter_new_matrix_convolution (&kernelSize, k, gain, bias, &kernelOffset, tileMode, convolveAlpha, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+ }
+
+ // CreateMerge
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete("Use CreateMerge(SKImageFilter, SKImageFilter, SKImageFilter.CropRect) instead.")]
+ public static SKImageFilter CreateMerge(SKImageFilter first, SKImageFilter second, SKBlendMode mode, SKImageFilter.CropRect cropRect = null)
+ {
+ return CreateMerge(new [] { first, second }, cropRect);
+ }
+
+ public static SKImageFilter CreateMerge(SKImageFilter first, SKImageFilter second, SKImageFilter.CropRect cropRect = null)
+ {
+ return CreateMerge(new [] { first, second }, cropRect);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete("Use CreateMerge(SKImageFilter[], SKImageFilter.CropRect) instead.")]
+ public static SKImageFilter CreateMerge(SKImageFilter[] filters, SKBlendMode[] modes, SKImageFilter.CropRect cropRect = null)
+ {
+ return CreateMerge (filters, cropRect);
+ }
+
+ public static SKImageFilter CreateMerge(SKImageFilter[] filters, SKImageFilter.CropRect cropRect = null)
+ {
+ if (filters == null)
+ throw new ArgumentNullException(nameof(filters));
+ var handles = new IntPtr[filters.Length];
+ for (int i = 0; i < filters.Length; i++)
+ {
+ handles[i] = filters[i]?.Handle ?? IntPtr.Zero;
+ }
+ fixed (IntPtr* h = handles) {
+ return GetObject<SKImageFilter> (SkiaApi.sk_imagefilter_new_merge (h, filters.Length, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+ }
+
+ // CreateDilate
+
+ public static SKImageFilter CreateDilate(int radiusX, int radiusY, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_dilate(radiusX, radiusY, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateErode
+
+ public static SKImageFilter CreateErode(int radiusX, int radiusY, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_erode(radiusX, radiusY, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateOffset
+
+ public static SKImageFilter CreateOffset(float dx, float dy, SKImageFilter input = null, SKImageFilter.CropRect cropRect = null)
+ {
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_offset(dx, dy, input == null ? IntPtr.Zero : input.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreatePicture
+
+ public static SKImageFilter CreatePicture(SKPicture picture)
+ {
+ if (picture == null)
+ throw new ArgumentNullException(nameof(picture));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_picture(picture.Handle));
+ }
+
+ public static SKImageFilter CreatePicture(SKPicture picture, SKRect cropRect)
+ {
+ if (picture == null)
+ throw new ArgumentNullException(nameof(picture));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_picture_with_croprect(picture.Handle, &cropRect));
+ }
+
+ // CreateTile
+
+ public static SKImageFilter CreateTile(SKRect src, SKRect dst, SKImageFilter input)
+ {
+ if (input == null)
+ throw new ArgumentNullException(nameof(input));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_tile(&src, &dst, input.Handle));
+ }
+
+ // CreateBlendMode
+
+ public static SKImageFilter CreateBlendMode(SKBlendMode mode, SKImageFilter background, SKImageFilter foreground = null, SKImageFilter.CropRect cropRect = null)
+ {
+ if (background == null)
+ throw new ArgumentNullException(nameof(background));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_xfermode(mode, background.Handle, foreground == null ? IntPtr.Zero : foreground.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateArithmetic
+
+ public static SKImageFilter CreateArithmetic(float k1, float k2, float k3, float k4, bool enforcePMColor, SKImageFilter background, SKImageFilter foreground = null, SKImageFilter.CropRect cropRect = null)
+ {
+ if (background == null)
+ throw new ArgumentNullException(nameof(background));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_arithmetic(k1, k2, k3, k4, enforcePMColor, background.Handle, foreground == null ? IntPtr.Zero : foreground.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ // CreateImage
+
+ public static SKImageFilter CreateImage(SKImage image)
+ {
+ if (image == null)
+ throw new ArgumentNullException(nameof(image));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_image_source_default(image.Handle));
+ }
+
+ public static SKImageFilter CreateImage(SKImage image, SKRect src, SKRect dst, SKFilterQuality filterQuality)
+ {
+ if (image == null)
+ throw new ArgumentNullException(nameof(image));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_image_source(image.Handle, &src, &dst, filterQuality));
+ }
+
+ // CreatePaint
+
+ public static SKImageFilter CreatePaint(SKPaint paint, SKImageFilter.CropRect cropRect = null)
+ {
+ if (paint == null)
+ throw new ArgumentNullException(nameof(paint));
+ return GetObject<SKImageFilter>(SkiaApi.sk_imagefilter_new_paint(paint.Handle, cropRect == null ? IntPtr.Zero : cropRect.Handle));
+ }
+
+ //
+
+ public class CropRect : SKObject
+ {
+ internal CropRect(IntPtr handle, bool owns)
+ : base(handle, owns)
+ {
+ }
+
+ public CropRect()
+ : this(SkiaApi.sk_imagefilter_croprect_new(), true)
+ {
+ }
+
+ public CropRect(SKRect rect, SKCropRectFlags flags = SKCropRectFlags.HasAll)
+ : this(SkiaApi.sk_imagefilter_croprect_new_with_rect(&rect, (uint)flags), true)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_imagefilter_croprect_destructor (Handle);
+
+ public SKRect Rect
+ {
+ get
+ {
+ SKRect rect;
+ SkiaApi.sk_imagefilter_croprect_get_rect (Handle, &rect);
+ return rect;
+ }
+ }
+
+ public SKCropRectFlags Flags =>
+ (SKCropRectFlags)SkiaApi.sk_imagefilter_croprect_get_flags (Handle);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ internal partial struct SKImageInfoNative
+ {
+ public static void UpdateNative (ref SKImageInfo managed, ref SKImageInfoNative native)
+ {
+ native.colorspace = managed.ColorSpace?.Handle ?? IntPtr.Zero;
+ native.width = managed.Width;
+ native.height = managed.Height;
+ native.colorType = managed.ColorType;
+ native.alphaType = managed.AlphaType;
+ }
+
+ public static SKImageInfoNative FromManaged (ref SKImageInfo managed) =>
+ new SKImageInfoNative {
+ colorspace = managed.ColorSpace?.Handle ?? IntPtr.Zero,
+ width = managed.Width,
+ height = managed.Height,
+ colorType = managed.ColorType,
+ alphaType = managed.AlphaType,
+ };
+
+ public static SKImageInfo ToManaged (ref SKImageInfoNative native) =>
+ new SKImageInfo {
+ ColorSpace = SKObject.GetObject<SKColorSpace> (native.colorspace),
+ Width = native.width,
+ Height = native.height,
+ ColorType = native.colorType,
+ AlphaType = native.alphaType,
+ };
+ }
+
+ public unsafe struct SKImageInfo : IEquatable<SKImageInfo>
+ {
+ public static readonly SKImageInfo Empty;
+ public static readonly SKColorType PlatformColorType;
+ public static readonly int PlatformColorAlphaShift;
+ public static readonly int PlatformColorRedShift;
+ public static readonly int PlatformColorGreenShift;
+ public static readonly int PlatformColorBlueShift;
+
+ static SKImageInfo ()
+ {
+ PlatformColorType = SkiaApi.sk_colortype_get_default_8888 ();
+
+ fixed (int* a = &PlatformColorAlphaShift)
+ fixed (int* r = &PlatformColorRedShift)
+ fixed (int* g = &PlatformColorGreenShift)
+ fixed (int* b = &PlatformColorBlueShift) {
+ SkiaApi.sk_color_get_bit_shift (a, r, g, b);
+ }
+ }
+
+ public int Width { get; set; }
+
+ public int Height { get; set; }
+
+ public SKColorType ColorType { get; set; }
+
+ public SKAlphaType AlphaType { get; set; }
+
+ public SKColorSpace ColorSpace { get; set; }
+
+ public SKImageInfo (int width, int height)
+ {
+ Width = width;
+ Height = height;
+ ColorType = PlatformColorType;
+ AlphaType = SKAlphaType.Premul;
+ ColorSpace = null;
+ }
+
+ public SKImageInfo (int width, int height, SKColorType colorType)
+ {
+ Width = width;
+ Height = height;
+ ColorType = colorType;
+ AlphaType = SKAlphaType.Premul;
+ ColorSpace = null;
+ }
+
+ public SKImageInfo (int width, int height, SKColorType colorType, SKAlphaType alphaType)
+ {
+ Width = width;
+ Height = height;
+ ColorType = colorType;
+ AlphaType = alphaType;
+ ColorSpace = null;
+ }
+
+ public SKImageInfo (int width, int height, SKColorType colorType, SKAlphaType alphaType, SKColorSpace colorspace)
+ {
+ Width = width;
+ Height = height;
+ ColorType = colorType;
+ AlphaType = alphaType;
+ ColorSpace = colorspace;
+ }
+
+ public readonly int BytesPerPixel =>
+ ColorType.GetBytesPerPixel ();
+
+ public readonly int BitsPerPixel => BytesPerPixel * 8;
+
+ public readonly int BytesSize => Width * Height * BytesPerPixel;
+
+ public readonly long BytesSize64 => (long)Width * (long)Height * (long)BytesPerPixel;
+
+ public readonly int RowBytes => Width * BytesPerPixel;
+
+ public readonly long RowBytes64 => (long)Width * (long)BytesPerPixel;
+
+ public readonly bool IsEmpty => Width <= 0 || Height <= 0;
+
+ public readonly bool IsOpaque => AlphaType == SKAlphaType.Opaque;
+
+ public readonly SKSizeI Size => new SKSizeI (Width, Height);
+
+ public readonly SKRectI Rect => SKRectI.Create (Width, Height);
+
+ public readonly SKImageInfo WithSize (SKSizeI size) =>
+ WithSize (size.Width, size.Height);
+
+ public readonly SKImageInfo WithSize (int width, int height)
+ {
+ var copy = this;
+ copy.Width = width;
+ copy.Height = height;
+ return copy;
+ }
+
+ public readonly SKImageInfo WithColorType (SKColorType newColorType)
+ {
+ var copy = this;
+ copy.ColorType = newColorType;
+ return copy;
+ }
+
+ public readonly SKImageInfo WithColorSpace (SKColorSpace newColorSpace)
+ {
+ var copy = this;
+ copy.ColorSpace = newColorSpace;
+ return copy;
+ }
+
+ public readonly SKImageInfo WithAlphaType (SKAlphaType newAlphaType)
+ {
+ var copy = this;
+ copy.AlphaType = newAlphaType;
+ return copy;
+ }
+
+ public readonly bool Equals (SKImageInfo obj) =>
+ ColorSpace == obj.ColorSpace &&
+ Width == obj.Width &&
+ Height == obj.Height &&
+ ColorType == obj.ColorType &&
+ AlphaType == obj.AlphaType;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKImageInfo f && Equals (f);
+
+ public static bool operator == (SKImageInfo left, SKImageInfo right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKImageInfo left, SKImageInfo right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (ColorSpace);
+ hash.Add (Width);
+ hash.Add (Height);
+ hash.Add (ColorType);
+ hash.Add (AlphaType);
+ return hash.ToHashCode ();
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Buffers;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace SkiaSharp
+{
+ public class SKManagedStream : SKAbstractManagedStream
+ {
+ private Stream stream;
+
+ private bool isAsEnd;
+ private bool disposeStream;
+ private bool wasCopied;
+
+ private WeakReference parent;
+ private WeakReference child;
+
+ public SKManagedStream (Stream managedStream)
+ : this (managedStream, false)
+ {
+ }
+
+ public SKManagedStream (Stream managedStream, bool disposeManagedStream)
+ : base (true)
+ {
+ stream = managedStream ?? throw new ArgumentNullException (nameof (managedStream));
+ disposeStream = disposeManagedStream;
+ }
+
+ public int CopyTo (SKWStream destination)
+ {
+ if (destination == null)
+ throw new ArgumentNullException (nameof (destination));
+
+ var total = 0;
+ int len;
+ var buffer = ArrayPool<byte>.Shared.Rent (SKData.CopyBufferSize);
+ try {
+ while ((len = stream.Read (buffer, 0, buffer.Length)) > 0) {
+ destination.Write (buffer, len);
+ total += len;
+ }
+ } finally {
+ ArrayPool<byte>.Shared.Return (buffer);
+ }
+ destination.Flush ();
+ return total;
+ }
+
+ public SKStreamAsset ToMemoryStream ()
+ {
+ using (var native = new SKDynamicMemoryWStream ()) {
+ CopyTo (native);
+ return native.DetachAsStream ();
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeManaged ()
+ {
+ var childStream = child?.Target as SKManagedStream;
+ var parentStream = parent?.Target as SKManagedStream;
+
+ if (childStream != null && parentStream != null) {
+ // remove this stream from the list by connecting the parent with the child
+ childStream.parent = parent;
+ parentStream.child = child;
+ } else if (childStream != null) {
+ // transfer ownership to child
+ childStream.parent = null;
+ } else if (parentStream != null) {
+ // transfer ownership back to parent
+ parentStream.child = null;
+ parentStream.wasCopied = false;
+ parentStream.disposeStream = disposeStream;
+
+ disposeStream = false;
+ }
+
+ parent = null;
+ child = null;
+
+ if (disposeStream && stream != null) {
+ stream.Dispose ();
+ stream = null;
+ }
+
+ base.DisposeManaged ();
+ }
+
+ private IntPtr OnReadManagedStream (IntPtr buffer, IntPtr size)
+ {
+ byte[] managedBuffer;
+ using (var reader = new BinaryReader (stream, Encoding.UTF8, true)) {
+ managedBuffer = reader.ReadBytes ((int)size);
+ }
+ var result = managedBuffer.Length;
+ if (buffer != IntPtr.Zero) {
+ Marshal.Copy (managedBuffer, 0, buffer, result);
+ }
+ if (!stream.CanSeek && (int)size > 0 && result <= (int)size) {
+ isAsEnd = true;
+ }
+ return (IntPtr)result;
+ }
+
+ protected override IntPtr OnRead (IntPtr buffer, IntPtr size)
+ {
+ VerifyOriginal ();
+
+ return OnReadManagedStream (buffer, size);
+ }
+
+ protected override IntPtr OnPeek (IntPtr buffer, IntPtr size)
+ {
+ VerifyOriginal ();
+
+ if (!stream.CanSeek) {
+ return (IntPtr)0;
+ }
+ var oldPos = stream.Position;
+ var result = OnReadManagedStream (buffer, size);
+ stream.Position = oldPos;
+ return result;
+ }
+
+ protected override bool OnIsAtEnd ()
+ {
+ VerifyOriginal ();
+
+ if (!stream.CanSeek) {
+ return isAsEnd;
+ }
+ return stream.Position >= stream.Length;
+ }
+
+ protected override bool OnHasPosition ()
+ {
+ VerifyOriginal ();
+
+ return stream.CanSeek;
+ }
+
+ protected override bool OnHasLength ()
+ {
+ VerifyOriginal ();
+
+ return stream.CanSeek;
+ }
+
+ protected override bool OnRewind ()
+ {
+ VerifyOriginal ();
+
+ if (!stream.CanSeek) {
+ return false;
+ }
+ stream.Position = 0;
+ return true;
+ }
+
+ protected override IntPtr OnGetPosition ()
+ {
+ VerifyOriginal ();
+
+ if (!stream.CanSeek) {
+ return (IntPtr)0;
+ }
+ return (IntPtr)stream.Position;
+ }
+
+ protected override IntPtr OnGetLength ()
+ {
+ VerifyOriginal ();
+
+ if (!stream.CanSeek) {
+ return (IntPtr)0;
+ }
+ return (IntPtr)stream.Length;
+ }
+
+ protected override bool OnSeek (IntPtr position)
+ {
+ VerifyOriginal ();
+
+ if (!stream.CanSeek) {
+ return false;
+ }
+ stream.Position = (long)position;
+ return true;
+ }
+
+ protected override bool OnMove (int offset)
+ {
+ VerifyOriginal ();
+
+ if (!stream.CanSeek) {
+ return false;
+ }
+ stream.Position += offset;
+ return true;
+ }
+
+ protected override IntPtr OnCreateNew ()
+ {
+ VerifyOriginal ();
+
+ return IntPtr.Zero;
+ }
+
+ protected override IntPtr OnDuplicate ()
+ {
+ VerifyOriginal ();
+
+ if (!stream.CanSeek)
+ return IntPtr.Zero;
+
+ var newStream = new SKManagedStream (stream, disposeStream);
+ newStream.parent = new WeakReference (this);
+
+ wasCopied = true;
+ disposeStream = false;
+ child = new WeakReference (newStream);
+
+ stream.Position = 0;
+
+ return newStream.Handle;
+ }
+
+ protected override IntPtr OnFork ()
+ {
+ VerifyOriginal ();
+
+ var newStream = new SKManagedStream (stream, disposeStream);
+
+ wasCopied = true;
+ disposeStream = false;
+
+ return newStream.Handle;
+ }
+
+ private void VerifyOriginal ()
+ {
+ if (wasCopied)
+ throw new InvalidOperationException ("This stream was duplicated or forked and cannot be read anymore.");
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Buffers;
+using System.IO;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ public class SKManagedWStream : SKAbstractManagedWStream
+ {
+ private Stream stream;
+ private readonly bool disposeStream;
+
+ public SKManagedWStream (Stream managedStream)
+ : this (managedStream, false)
+ {
+ }
+
+ public SKManagedWStream (Stream managedStream, bool disposeManagedStream)
+ : this (managedStream, disposeManagedStream, true)
+ {
+ }
+
+ private SKManagedWStream (Stream managedStream, bool disposeManagedStream, bool owns)
+ : base (owns)
+ {
+ stream = managedStream;
+ disposeStream = disposeManagedStream;
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeManaged ()
+ {
+ if (disposeStream && stream != null) {
+ stream.Dispose ();
+ stream = null;
+ }
+
+ base.DisposeManaged ();
+ }
+
+ protected override bool OnWrite (IntPtr buffer, IntPtr size)
+ {
+ var count = (int)size;
+ var managedBuffer = ArrayPool<byte>.Shared.Rent (count);
+ try {
+ if (buffer != IntPtr.Zero) {
+ Marshal.Copy (buffer, managedBuffer, 0, count);
+ }
+ stream.Write (managedBuffer, 0, count);
+ } finally {
+ ArrayPool<byte>.Shared.Return (managedBuffer);
+ }
+ return true;
+ }
+
+ protected override void OnFlush ()
+ {
+ stream.Flush ();
+ }
+
+ protected override IntPtr OnBytesWritten ()
+ {
+ return (IntPtr)stream.Position;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ public unsafe partial struct SKMask
+ {
+ public SKMask (IntPtr image, SKRectI bounds, UInt32 rowBytes, SKMaskFormat format)
+ {
+ fBounds = bounds;
+ fRowBytes = rowBytes;
+ fFormat = format;
+ fImage = (byte*)image;
+ }
+
+ public SKMask (SKRectI bounds, UInt32 rowBytes, SKMaskFormat format)
+ {
+ fBounds = bounds;
+ fRowBytes = rowBytes;
+ fFormat = format;
+ fImage = null;
+ }
+
+ // properties
+
+ public IntPtr Image {
+ readonly get => (IntPtr)fImage;
+ set => fImage = (byte*)value;
+ }
+
+ public Span<byte> GetImageSpan () =>
+ new Span<byte> ((void*)Image, (int)ComputeTotalImageSize ());
+
+ public SKRectI Bounds {
+ readonly get => fBounds;
+ set => fBounds = value;
+ }
+
+ public UInt32 RowBytes {
+ readonly get => fRowBytes;
+ set => fRowBytes = value;
+ }
+
+ public SKMaskFormat Format {
+ readonly get => fFormat;
+ set => fFormat = value;
+ }
+
+ public readonly bool IsEmpty {
+ get {
+ fixed (SKMask* t = &this) {
+ return SkiaApi.sk_mask_is_empty (t);
+ }
+ }
+ }
+
+ // allocate / free
+
+ public long AllocateImage ()
+ {
+ fixed (SKMask* t = &this) {
+ var size = SkiaApi.sk_mask_compute_total_image_size (t);
+ fImage = SkiaApi.sk_mask_alloc_image (size);
+ return (long)size;
+ }
+ }
+
+ public void FreeImage ()
+ {
+ if (fImage != null) {
+ SKMask.FreeImage ((IntPtr)fImage);
+ fImage = null;
+ }
+ }
+
+ // Compute*
+
+ public readonly long ComputeImageSize ()
+ {
+ fixed (SKMask* t = &this) {
+ return (long)SkiaApi.sk_mask_compute_image_size (t);
+ }
+ }
+
+ public readonly long ComputeTotalImageSize ()
+ {
+ fixed (SKMask* t = &this) {
+ return (long)SkiaApi.sk_mask_compute_total_image_size (t);
+ }
+ }
+
+ // GetAddr*
+
+ public readonly byte GetAddr1 (int x, int y)
+ {
+ fixed (SKMask* t = &this) {
+ return SkiaApi.sk_mask_get_addr_1 (t, x, y);
+ }
+ }
+
+ public readonly byte GetAddr8 (int x, int y)
+ {
+ fixed (SKMask* t = &this) {
+ return SkiaApi.sk_mask_get_addr_8 (t, x, y);
+ }
+ }
+
+ public readonly UInt16 GetAddr16 (int x, int y)
+ {
+ fixed (SKMask* t = &this) {
+ return SkiaApi.sk_mask_get_addr_lcd_16 (t, x, y);
+ }
+ }
+
+ public readonly UInt32 GetAddr32 (int x, int y)
+ {
+ fixed (SKMask* t = &this) {
+ return SkiaApi.sk_mask_get_addr_32 (t, x, y);
+ }
+ }
+
+ public readonly IntPtr GetAddr (int x, int y)
+ {
+ fixed (SKMask* t = &this) {
+ return (IntPtr)SkiaApi.sk_mask_get_addr (t, x, y);
+ }
+ }
+
+ // statics
+
+ public static IntPtr AllocateImage (long size) =>
+ (IntPtr)SkiaApi.sk_mask_alloc_image ((IntPtr)size);
+
+ public static void FreeImage (IntPtr image) =>
+ SkiaApi.sk_mask_free_image ((byte*)image);
+
+ public static SKMask Create (byte[] image, SKRectI bounds, UInt32 rowBytes, SKMaskFormat format) =>
+ Create (image.AsSpan (), bounds, rowBytes, format);
+
+ public static SKMask Create (ReadOnlySpan<byte> image, SKRectI bounds, UInt32 rowBytes, SKMaskFormat format)
+ {
+ // create the mask
+ var mask = new SKMask (bounds, rowBytes, format);
+
+ // calculate the size
+ var imageSize = (int)mask.ComputeTotalImageSize ();
+
+ // is there the right amount of space in the mask
+ if (image.Length != imageSize) {
+ // Note: buffer.Length must match bounds.Height * rowBytes
+ var expectedSize = bounds.Height * rowBytes;
+ var message = $"Length of image ({image.Length}) does not match the computed size of the mask ({expectedSize}). Check the {nameof (bounds)} and {nameof (rowBytes)}.";
+ throw new ArgumentException (message);
+ }
+
+ // allocate and copy the image data
+ mask.AllocateImage ();
+ image.CopyTo (new Span<byte> ((void*)mask.Image, imageSize));
+
+ // return the mask
+ return mask;
+ }
+ }
+
+ public class SKAutoMaskFreeImage : IDisposable
+ {
+ private IntPtr image;
+
+ public SKAutoMaskFreeImage (IntPtr maskImage)
+ {
+ image = maskImage;
+ }
+
+ public void Dispose ()
+ {
+ if (image != IntPtr.Zero) {
+ SKMask.FreeImage (image);
+ image = IntPtr.Zero;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Flags]
+ [Obsolete]
+ public enum SKBlurMaskFilterFlags
+ {
+ None = 0x00,
+ IgnoreTransform = 0x01,
+ HighQuality = 0x02,
+ All = IgnoreTransform | HighQuality,
+ }
+
+
+ // TODO: `getFormat`
+ // TODO: `computeFastBounds`
+
+ public unsafe class SKMaskFilter : SKObject, ISKReferenceCounted
+ {
+ private const float BlurSigmaScale = 0.57735f;
+ public const int TableMaxLength = 256;
+
+ [Preserve]
+ internal SKMaskFilter (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public static float ConvertRadiusToSigma (float radius)
+ {
+ return radius > 0 ? BlurSigmaScale * radius + 0.5f : 0.0f;
+ }
+
+ public static float ConvertSigmaToRadius (float sigma)
+ {
+ return sigma > 0.5f ? (sigma - 0.5f) / BlurSigmaScale : 0.0f;
+ }
+
+ public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma)
+ {
+ return GetObject<SKMaskFilter> (SkiaApi.sk_maskfilter_new_blur (blurStyle, sigma));
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateBlur(SKBlurStyle, float) instead.")]
+ public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma, SKBlurMaskFilterFlags flags)
+ {
+ return CreateBlur (blurStyle, sigma, SKRect.Empty, true);
+ }
+
+ public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma, SKRect occluder)
+ {
+ return CreateBlur (blurStyle, sigma, occluder, true);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateBlur(SKBlurStyle, float, SKRect) instead.")]
+ public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma, SKRect occluder, SKBlurMaskFilterFlags flags)
+ {
+ return CreateBlur (blurStyle, sigma, occluder, true);
+ }
+
+ public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma, SKRect occluder, bool respectCTM)
+ {
+ return GetObject<SKMaskFilter> (SkiaApi.sk_maskfilter_new_blur_with_flags (blurStyle, sigma, &occluder, respectCTM));
+ }
+
+ public static SKMaskFilter CreateTable (byte[] table)
+ {
+ if (table == null)
+ throw new ArgumentNullException (nameof (table));
+ if (table.Length != TableMaxLength)
+ throw new ArgumentException ("Table must have a length of {SKColorTable.MaxLength}.", nameof (table));
+ fixed (byte* t = table) {
+ return GetObject<SKMaskFilter> (SkiaApi.sk_maskfilter_new_table (t));
+ }
+ }
+
+ public static SKMaskFilter CreateGamma (float gamma)
+ {
+ return GetObject<SKMaskFilter> (SkiaApi.sk_maskfilter_new_gamma (gamma));
+ }
+
+ public static SKMaskFilter CreateClip (byte min, byte max)
+ {
+ return GetObject<SKMaskFilter> (SkiaApi.sk_maskfilter_new_clip (min, max));
+ }
+ }
+}
+
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public unsafe partial struct SKMatrix
+ {
+ internal const float DegreesToRadians = (float)Math.PI / 180.0f;
+
+ public readonly static SKMatrix Empty;
+
+ public readonly static SKMatrix Identity = new SKMatrix { scaleX = 1, scaleY = 1, persp2 = 1 };
+
+ private class Indices
+ {
+ public const int ScaleX = 0;
+ public const int SkewX = 1;
+ public const int TransX = 2;
+ public const int SkewY = 3;
+ public const int ScaleY = 4;
+ public const int TransY = 5;
+ public const int Persp0 = 6;
+ public const int Persp1 = 7;
+ public const int Persp2 = 8;
+
+ public const int Count = 9;
+ }
+
+ public SKMatrix (float[] values)
+ {
+ if (values == null)
+ throw new ArgumentNullException (nameof (values));
+ if (values.Length != Indices.Count)
+ throw new ArgumentException ($"The matrix array must have a length of {Indices.Count}.", nameof (values));
+
+ scaleX = values[Indices.ScaleX];
+ skewX = values[Indices.SkewX];
+ transX = values[Indices.TransX];
+
+ skewY = values[Indices.SkewY];
+ scaleY = values[Indices.ScaleY];
+ transY = values[Indices.TransY];
+
+ persp0 = values[Indices.Persp0];
+ persp1 = values[Indices.Persp1];
+ persp2 = values[Indices.Persp2];
+ }
+
+ public SKMatrix (
+ float scaleX, float skewX, float transX,
+ float skewY, float scaleY, float transY,
+ float persp0, float persp1, float persp2)
+ {
+ this.scaleX = scaleX;
+ this.skewX = skewX;
+ this.transX = transX;
+ this.skewY = skewY;
+ this.scaleY = scaleY;
+ this.transY = transY;
+ this.persp0 = persp0;
+ this.persp1 = persp1;
+ this.persp2 = persp2;
+ }
+
+ public readonly bool IsIdentity => Equals (Identity);
+
+ // Values
+
+ public float[] Values {
+ readonly get =>
+ new float[9] {
+ scaleX, skewX, transX,
+ skewY, scaleY, transY,
+ persp0, persp1, persp2
+ };
+ set {
+ if (value == null)
+ throw new ArgumentNullException (nameof (Values));
+ if (value.Length != Indices.Count)
+ throw new ArgumentException ($"The matrix array must have a length of {Indices.Count}.", nameof (Values));
+
+ scaleX = value[Indices.ScaleX];
+ skewX = value[Indices.SkewX];
+ transX = value[Indices.TransX];
+
+ skewY = value[Indices.SkewY];
+ scaleY = value[Indices.ScaleY];
+ transY = value[Indices.TransY];
+
+ persp0 = value[Indices.Persp0];
+ persp1 = value[Indices.Persp1];
+ persp2 = value[Indices.Persp2];
+ }
+ }
+
+ public readonly void GetValues (float[] values)
+ {
+ if (values == null)
+ throw new ArgumentNullException (nameof (values));
+ if (values.Length != Indices.Count)
+ throw new ArgumentException ($"The matrix array must have a length of {Indices.Count}.", nameof (values));
+
+ values[Indices.ScaleX] = scaleX;
+ values[Indices.SkewX] = skewX;
+ values[Indices.TransX] = transX;
+
+ values[Indices.SkewY] = skewY;
+ values[Indices.ScaleY] = scaleY;
+ values[Indices.TransY] = transY;
+
+ values[Indices.Persp0] = persp0;
+ values[Indices.Persp1] = persp1;
+ values[Indices.Persp2] = persp2;
+ }
+
+ // Create*
+
+ public static SKMatrix CreateIdentity () =>
+ new SKMatrix { scaleX = 1, scaleY = 1, persp2 = 1 };
+
+ public static SKMatrix CreateTranslation (float x, float y)
+ {
+ if (x == 0 && y == 0)
+ return Identity;
+
+ return new SKMatrix {
+ scaleX = 1,
+ scaleY = 1,
+ transX = x,
+ transY = y,
+ persp2 = 1,
+ };
+ }
+
+ public static SKMatrix CreateScale (float x, float y)
+ {
+ if (x == 1 && y == 1)
+ return Identity;
+
+ return new SKMatrix {
+ scaleX = x,
+ scaleY = y,
+ persp2 = 1,
+ };
+ }
+
+ public static SKMatrix CreateScale (float x, float y, float pivotX, float pivotY)
+ {
+ if (x == 1 && y == 1)
+ return Identity;
+
+ var tx = pivotX - x * pivotX;
+ var ty = pivotY - y * pivotY;
+
+ return new SKMatrix {
+ scaleX = x,
+ scaleY = y,
+ transX = tx,
+ transY = ty,
+ persp2 = 1,
+ };
+ }
+
+ public static SKMatrix CreateRotation (float radians)
+ {
+ if (radians == 0)
+ return Identity;
+
+ var sin = (float)Math.Sin (radians);
+ var cos = (float)Math.Cos (radians);
+
+ var matrix = Identity;
+ SetSinCos (ref matrix, sin, cos);
+ return matrix;
+ }
+
+ public static SKMatrix CreateRotation (float radians, float pivotX, float pivotY)
+ {
+ if (radians == 0)
+ return Identity;
+
+ var sin = (float)Math.Sin (radians);
+ var cos = (float)Math.Cos (radians);
+
+ var matrix = Identity;
+ SetSinCos (ref matrix, sin, cos, pivotX, pivotY);
+ return matrix;
+ }
+
+ public static SKMatrix CreateRotationDegrees (float degrees)
+ {
+ if (degrees == 0)
+ return Identity;
+
+ return CreateRotation (degrees * DegreesToRadians);
+ }
+
+ public static SKMatrix CreateRotationDegrees (float degrees, float pivotX, float pivotY)
+ {
+ if (degrees == 0)
+ return Identity;
+
+ return CreateRotation (degrees * DegreesToRadians, pivotX, pivotY);
+ }
+
+ public static SKMatrix CreateSkew (float x, float y)
+ {
+ if (x == 0 && y == 0)
+ return Identity;
+
+ return new SKMatrix {
+ scaleX = 1,
+ skewX = x,
+ skewY = y,
+ scaleY = 1,
+ persp2 = 1,
+ };
+ }
+
+ // Make*
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeIdentity () =>
+ CreateIdentity ();
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeScale (float sx, float sy) =>
+ CreateScale (sx, sy);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeScale (float sx, float sy, float pivotX, float pivotY) =>
+ CreateScale (sx, sy, pivotX, pivotY);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeTranslation (float dx, float dy) =>
+ CreateTranslation (dx, dy);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeRotation (float radians) =>
+ CreateRotation (radians);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeRotation (float radians, float pivotx, float pivoty) =>
+ CreateRotation (radians, pivotx, pivoty);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeRotationDegrees (float degrees) =>
+ CreateRotationDegrees (degrees);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeRotationDegrees (float degrees, float pivotx, float pivoty) =>
+ CreateRotationDegrees (degrees, pivotx, pivoty);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix MakeSkew (float sx, float sy) =>
+ CreateSkew (sx, sy);
+
+ // Set*
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public void SetScaleTranslate (float sx, float sy, float tx, float ty)
+ {
+ scaleX = sx;
+ skewX = 0;
+ transX = tx;
+
+ skewY = 0;
+ scaleY = sy;
+ transY = ty;
+
+ persp0 = 0;
+ persp1 = 0;
+ persp2 = 1;
+ }
+
+ // Rotate
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateRotation(float, float, float) instead.")]
+ public static void Rotate (ref SKMatrix matrix, float radians, float pivotx, float pivoty)
+ {
+ var sin = (float)Math.Sin (radians);
+ var cos = (float)Math.Cos (radians);
+ SetSinCos (ref matrix, sin, cos, pivotx, pivoty);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateRotationDegrees(float, float, float) instead.")]
+ public static void RotateDegrees (ref SKMatrix matrix, float degrees, float pivotx, float pivoty)
+ {
+ var sin = (float)Math.Sin (degrees * DegreesToRadians);
+ var cos = (float)Math.Cos (degrees * DegreesToRadians);
+ SetSinCos (ref matrix, sin, cos, pivotx, pivoty);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateRotation(float) instead.")]
+ public static void Rotate (ref SKMatrix matrix, float radians)
+ {
+ var sin = (float)Math.Sin (radians);
+ var cos = (float)Math.Cos (radians);
+ SetSinCos (ref matrix, sin, cos);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateRotationDegrees(float) instead.")]
+ public static void RotateDegrees (ref SKMatrix matrix, float degrees)
+ {
+ var sin = (float)Math.Sin (degrees * DegreesToRadians);
+ var cos = (float)Math.Cos (degrees * DegreesToRadians);
+ SetSinCos (ref matrix, sin, cos);
+ }
+
+ // Invert
+
+ public readonly bool IsInvertible {
+ get {
+ fixed (SKMatrix* t = &this) {
+ return SkiaApi.sk_matrix_try_invert (t, null);
+ }
+ }
+ }
+
+ public readonly bool TryInvert (out SKMatrix inverse)
+ {
+ fixed (SKMatrix* i = &inverse)
+ fixed (SKMatrix* t = &this) {
+ return SkiaApi.sk_matrix_try_invert (t, i);
+ }
+ }
+
+ public readonly SKMatrix Invert ()
+ {
+ if (TryInvert (out var matrix))
+ return matrix;
+
+ return Empty;
+ }
+
+ // *Concat
+
+ public static SKMatrix Concat (SKMatrix first, SKMatrix second)
+ {
+ SKMatrix target;
+ SkiaApi.sk_matrix_concat (&target, &first, &second);
+ return target;
+ }
+
+ public readonly SKMatrix PreConcat (SKMatrix matrix)
+ {
+ var target = this;
+ SkiaApi.sk_matrix_pre_concat (&target, &matrix);
+ return target;
+ }
+
+ public readonly SKMatrix PostConcat (SKMatrix matrix)
+ {
+ var target = this;
+ SkiaApi.sk_matrix_post_concat (&target, &matrix);
+ return target;
+ }
+
+ public static void Concat (ref SKMatrix target, SKMatrix first, SKMatrix second)
+ {
+ fixed (SKMatrix* t = &target) {
+ SkiaApi.sk_matrix_concat (t, &first, &second);
+ }
+ }
+
+ public static void Concat (ref SKMatrix target, ref SKMatrix first, ref SKMatrix second)
+ {
+ fixed (SKMatrix* t = &target)
+ fixed (SKMatrix* f = &first)
+ fixed (SKMatrix* s = &second) {
+ SkiaApi.sk_matrix_concat (t, f, s);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use PreConcat(SKMatrix) instead.")]
+ public static void PreConcat (ref SKMatrix target, SKMatrix matrix)
+ {
+ fixed (SKMatrix* t = &target) {
+ SkiaApi.sk_matrix_pre_concat (t, &matrix);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use PreConcat(SKMatrix) instead.")]
+ public static void PreConcat (ref SKMatrix target, ref SKMatrix matrix)
+ {
+ fixed (SKMatrix* t = &target)
+ fixed (SKMatrix* m = &matrix) {
+ SkiaApi.sk_matrix_pre_concat (t, m);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use PostConcat(SKMatrix) instead.")]
+ public static void PostConcat (ref SKMatrix target, SKMatrix matrix)
+ {
+ fixed (SKMatrix* t = &target) {
+ SkiaApi.sk_matrix_post_concat (t, &matrix);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use PostConcat(SKMatrix) instead.")]
+ public static void PostConcat (ref SKMatrix target, ref SKMatrix matrix)
+ {
+ fixed (SKMatrix* t = &target)
+ fixed (SKMatrix* m = &matrix) {
+ SkiaApi.sk_matrix_post_concat (t, m);
+ }
+ }
+
+ // MapRect
+
+ public readonly SKRect MapRect (SKRect source)
+ {
+ SKRect dest;
+ fixed (SKMatrix* m = &this) {
+ SkiaApi.sk_matrix_map_rect (m, &dest, &source);
+ }
+ return dest;
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use MapRect(SKRect) instead.")]
+ public static void MapRect (ref SKMatrix matrix, out SKRect dest, ref SKRect source)
+ {
+ fixed (SKMatrix* m = &matrix)
+ fixed (SKRect* d = &dest)
+ fixed (SKRect* s = &source) {
+ SkiaApi.sk_matrix_map_rect (m, d, s);
+ }
+ }
+
+ // MapPoints
+
+ public readonly SKPoint MapPoint (SKPoint point) =>
+ MapPoint (point.X, point.Y);
+
+ public readonly SKPoint MapPoint (float x, float y)
+ {
+ SKPoint result;
+ fixed (SKMatrix* t = &this) {
+ SkiaApi.sk_matrix_map_xy (t, x, y, &result);
+ }
+ return result;
+ }
+
+ public readonly void MapPoints (SKPoint[] result, SKPoint[] points)
+ {
+ if (result == null)
+ throw new ArgumentNullException (nameof (result));
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+ if (result.Length != points.Length)
+ throw new ArgumentException ("Buffers must be the same size.");
+
+ fixed (SKMatrix* t = &this)
+ fixed (SKPoint* rp = result)
+ fixed (SKPoint* pp = points) {
+ SkiaApi.sk_matrix_map_points (t, rp, pp, result.Length);
+ }
+ }
+
+ public readonly SKPoint[] MapPoints (SKPoint[] points)
+ {
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+
+ var res = new SKPoint[points.Length];
+ MapPoints (res, points);
+ return res;
+ }
+
+ // MapVectors
+
+ public readonly SKPoint MapVector (SKPoint vector) =>
+ MapVector (vector.X, vector.Y);
+
+ public readonly SKPoint MapVector (float x, float y)
+ {
+ SKPoint result;
+ fixed (SKMatrix* t = &this) {
+ SkiaApi.sk_matrix_map_vector (t, x, y, &result);
+ }
+ return result;
+ }
+
+ public readonly void MapVectors (SKPoint[] result, SKPoint[] vectors)
+ {
+ if (result == null)
+ throw new ArgumentNullException (nameof (result));
+ if (vectors == null)
+ throw new ArgumentNullException (nameof (vectors));
+ if (result.Length != vectors.Length)
+ throw new ArgumentException ("Buffers must be the same size.");
+
+ fixed (SKMatrix* t = &this)
+ fixed (SKPoint* rp = result)
+ fixed (SKPoint* pp = vectors) {
+ SkiaApi.sk_matrix_map_vectors (t, rp, pp, result.Length);
+ }
+ }
+
+ public readonly SKPoint[] MapVectors (SKPoint[] vectors)
+ {
+ if (vectors == null)
+ throw new ArgumentNullException (nameof (vectors));
+
+ var res = new SKPoint[vectors.Length];
+ MapVectors (res, vectors);
+ return res;
+ }
+
+ // MapRadius
+
+ public readonly float MapRadius (float radius)
+ {
+ fixed (SKMatrix* t = &this) {
+ return SkiaApi.sk_matrix_map_radius (t, radius);
+ }
+ }
+
+ // private
+
+ private static void SetSinCos (ref SKMatrix matrix, float sin, float cos)
+ {
+ matrix.scaleX = cos;
+ matrix.skewX = -sin;
+ matrix.transX = 0;
+ matrix.skewY = sin;
+ matrix.scaleY = cos;
+ matrix.transY = 0;
+ matrix.persp0 = 0;
+ matrix.persp1 = 0;
+ matrix.persp2 = 1;
+ }
+
+ private static void SetSinCos (ref SKMatrix matrix, float sin, float cos, float pivotx, float pivoty)
+ {
+ float oneMinusCos = 1 - cos;
+
+ matrix.scaleX = cos;
+ matrix.skewX = -sin;
+ matrix.transX = Dot (sin, pivoty, oneMinusCos, pivotx);
+ matrix.skewY = sin;
+ matrix.scaleY = cos;
+ matrix.transY = Dot (-sin, pivotx, oneMinusCos, pivoty);
+ matrix.persp0 = 0;
+ matrix.persp1 = 0;
+ matrix.persp2 = 1;
+ }
+
+ private static float Dot (float a, float b, float c, float d) =>
+ a * b + c * d;
+
+ private static float Cross (float a, float b, float c, float d) =>
+ a * b - c * d;
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public unsafe class SKMatrix44 : SKObject
+ {
+ [Preserve]
+ internal SKMatrix44 (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_matrix44_destroy (Handle);
+
+ 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 (&src), true)
+ {
+ if (Handle == IntPtr.Zero)
+ throw new InvalidOperationException ("Unable to create a new SKMatrix44 instance.");
+ }
+
+ // properties
+
+ public SKMatrix Matrix {
+ get {
+ SKMatrix matrix;
+ SkiaApi.sk_matrix44_to_matrix (Handle, &matrix);
+ return matrix;
+ }
+ }
+
+ public SKMatrix44TypeMask Type =>
+ SkiaApi.sk_matrix44_get_type (Handle);
+
+ public float this[int row, int column] {
+ get => SkiaApi.sk_matrix44_get (Handle, row, column);
+ set => SkiaApi.sk_matrix44_set (Handle, row, column, value);
+ }
+
+ // Create*
+
+ public static SKMatrix44 CreateIdentity ()
+ {
+ var matrix = new SKMatrix44 ();
+ matrix.SetIdentity ();
+ return matrix;
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public static SKMatrix44 CreateTranslate (float x, float y, float z) =>
+ CreateTranslation (x, y, z);
+
+ public static SKMatrix44 CreateTranslation (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;
+ }
+
+ // From
+
+ 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;
+ }
+
+ // To*
+
+ 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));
+
+ fixed (float* d = dst) {
+ SkiaApi.sk_matrix44_as_col_major (Handle, d);
+ }
+ }
+
+ 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));
+
+ fixed (float* d = dst) {
+ SkiaApi.sk_matrix44_as_row_major (Handle, d);
+ }
+ }
+
+ // Equal
+
+ 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);
+ }
+
+ // Set*
+
+ public void SetIdentity () =>
+ SkiaApi.sk_matrix44_set_identity (Handle);
+
+ 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));
+
+ fixed (float* s = src) {
+ SkiaApi.sk_matrix44_set_col_major (Handle, s);
+ }
+ }
+
+ 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));
+
+ fixed (float* s = src) {
+ SkiaApi.sk_matrix44_set_row_major (Handle, s);
+ }
+ }
+
+ public void Set3x3ColumnMajor (float[] src)
+ {
+ if (src.Length != 9)
+ throw new ArgumentException ("The source array must be 9 entries.", nameof (src));
+
+ var row = stackalloc float[9] { src[0], src[3], src[6], src[1], src[4], src[7], src[2], src[5], src[8] };
+ SkiaApi.sk_matrix44_set_3x3_row_major (Handle, row);
+ }
+
+ public void Set3x3RowMajor (float[] src)
+ {
+ if (src.Length != 9)
+ throw new ArgumentException ("The source array must be 9 entries.", nameof (src));
+
+ fixed (float* s = src) {
+ SkiaApi.sk_matrix44_set_3x3_row_major (Handle, s);
+ }
+ }
+
+ public void SetTranslate (float dx, float dy, float dz) =>
+ SkiaApi.sk_matrix44_set_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 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);
+ }
+
+ // Pre* / Post*
+
+ 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 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 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);
+ }
+
+ // Invert
+
+ public bool IsInvertible =>
+ SkiaApi.sk_matrix44_invert (Handle, IntPtr.Zero);
+
+ public SKMatrix44 Invert ()
+ {
+ var inverse = new SKMatrix44 ();
+ if (!Invert (inverse)) {
+ inverse.Dispose ();
+ inverse = null;
+ }
+ return inverse;
+ }
+
+ public bool Invert (SKMatrix44 inverse)
+ {
+ if (inverse == null)
+ throw new ArgumentNullException (nameof (inverse));
+
+ return SkiaApi.sk_matrix44_invert (Handle, inverse.Handle);
+ }
+
+ // Transpose
+
+ public void Transpose () =>
+ SkiaApi.sk_matrix44_transpose (Handle);
+
+ // MapScalars
+
+ 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));
+
+ fixed (float* s = srcVector4)
+ fixed (float* d = dstVector4) {
+ SkiaApi.sk_matrix44_map_scalars (Handle, s, d);
+ }
+ }
+
+ // MapPoints
+
+ public SKPoint MapPoint (SKPoint src) =>
+ 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;
+ }
+
+ // MapVector2
+
+ 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));
+
+ fixed (float* s = src2)
+ fixed (float* d = dst4) {
+ SkiaApi.sk_matrix44_map2 (Handle, s, src2.Length / 2, d);
+ }
+ }
+
+ // Preserves2DAxisAlignment
+
+ public bool Preserves2DAxisAlignment (float epsilon) =>
+ SkiaApi.sk_matrix44_preserves_2d_axis_alignment (Handle, epsilon);
+
+ // Determinant
+
+ public double Determinant () =>
+ SkiaApi.sk_matrix44_determinant (Handle);
+
+ // operators
+
+ public static implicit operator SKMatrix44 (SKMatrix matrix) =>
+ new SKMatrix44 (matrix);
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public class SKNWayCanvas : SKNoDrawCanvas
+ {
+ [Preserve]
+ internal SKNWayCanvas (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKNWayCanvas (int width, int height)
+ : this (IntPtr.Zero, true)
+ {
+ Handle = SkiaApi.sk_nway_canvas_new (width, height);
+ }
+
+ public void AddCanvas (SKCanvas canvas)
+ {
+ if (canvas == null)
+ throw new ArgumentNullException (nameof (canvas));
+
+ SkiaApi.sk_nway_canvas_add_canvas (Handle, canvas.Handle);
+ }
+
+ public void RemoveCanvas (SKCanvas canvas)
+ {
+ if (canvas == null)
+ throw new ArgumentNullException (nameof (canvas));
+
+ SkiaApi.sk_nway_canvas_remove_canvas (Handle, canvas.Handle);
+ }
+
+ public void RemoveAll ()
+ {
+ SkiaApi.sk_nway_canvas_remove_all (Handle);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public class SKNoDrawCanvas : SKCanvas
+ {
+ [Preserve]
+ internal SKNoDrawCanvas (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKNoDrawCanvas (int width, int height)
+ : this (IntPtr.Zero, true)
+ {
+ Handle = SkiaApi.sk_nodraw_canvas_new (width, height);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Collections.Concurrent;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace SkiaSharp
+{
+ public abstract class SKObject : SKNativeObject
+ {
+ private readonly object locker = new object ();
+
+ private ConcurrentDictionary<IntPtr, SKObject> ownedObjects;
+ private ConcurrentDictionary<IntPtr, SKObject> keepAliveObjects;
+
+ internal ConcurrentDictionary<IntPtr, SKObject> OwnedObjects {
+ get {
+ if (ownedObjects == null) {
+ lock (locker) {
+ ownedObjects ??= new ConcurrentDictionary<IntPtr, SKObject> ();
+ }
+ }
+ return ownedObjects;
+ }
+ }
+
+ internal ConcurrentDictionary<IntPtr, SKObject> KeepAliveObjects {
+ get {
+ if (keepAliveObjects == null) {
+ lock (locker) {
+ keepAliveObjects ??= new ConcurrentDictionary<IntPtr, SKObject> ();
+ }
+ }
+ return keepAliveObjects;
+ }
+ }
+
+ static SKObject ()
+ {
+ SKColorSpace.EnsureStaticInstanceAreInitialized ();
+ SKData.EnsureStaticInstanceAreInitialized ();
+ SKFontManager.EnsureStaticInstanceAreInitialized ();
+ SKTypeface.EnsureStaticInstanceAreInitialized ();
+ }
+
+ [Preserve]
+ internal SKObject (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public override IntPtr Handle {
+ get => base.Handle;
+ protected set {
+ if (value == IntPtr.Zero) {
+ DeregisterHandle (Handle, this);
+ base.Handle = value;
+ } else {
+ base.Handle = value;
+ RegisterHandle (Handle, this);
+ }
+ }
+ }
+
+ protected override void DisposeManaged ()
+ {
+ if (ownedObjects is ConcurrentDictionary<IntPtr, SKObject> dic) {
+ foreach (var child in dic) {
+ child.Value.DisposeInternal ();
+ }
+ dic.Clear ();
+ }
+ KeepAliveObjects?.Clear ();
+ }
+
+ protected override void DisposeNative ()
+ {
+ if (this is ISKReferenceCounted refcnt)
+ refcnt.SafeUnRef ();
+ }
+
+ internal static TSkiaObject GetObject<TSkiaObject> (IntPtr handle, bool owns = true, bool unrefExisting = true, bool refNew = false)
+ where TSkiaObject : SKObject
+ {
+ if (handle == IntPtr.Zero)
+ return null;
+
+ return HandleDictionary.GetObject<TSkiaObject, TSkiaObject> (handle, owns, unrefExisting, refNew);
+ }
+
+ internal static TSkiaObject GetObject<TSkiaObject, TSkiaImplementation> (IntPtr handle, bool owns = true, bool unrefExisting = true, bool refNew = false)
+ where TSkiaObject : SKObject
+ where TSkiaImplementation : SKObject, TSkiaObject
+ {
+ if (handle == IntPtr.Zero)
+ return null;
+
+ return HandleDictionary.GetObject<TSkiaObject, TSkiaImplementation> (handle, owns, unrefExisting, refNew);
+ }
+
+ internal static void RegisterHandle (IntPtr handle, SKObject instance)
+ {
+ if (handle == IntPtr.Zero || instance == null)
+ return;
+
+ HandleDictionary.RegisterHandle (handle, instance);
+ }
+
+ internal static void DeregisterHandle (IntPtr handle, SKObject instance)
+ {
+ if (handle == IntPtr.Zero)
+ return;
+
+ HandleDictionary.DeregisterHandle (handle, instance);
+ }
+
+ internal static bool GetInstance<TSkiaObject> (IntPtr handle, out TSkiaObject instance)
+ where TSkiaObject : SKObject
+ {
+ if (handle == IntPtr.Zero) {
+ instance = null;
+ return false;
+ }
+
+ return HandleDictionary.GetInstance<TSkiaObject> (handle, out instance);
+ }
+
+ // indicate that the ownership of this object is now in the hands of
+ // the native object
+ internal void RevokeOwnership (SKObject newOwner)
+ {
+ OwnsHandle = false;
+ IgnorePublicDispose = true;
+
+ if (newOwner == null)
+ DisposeInternal ();
+ else
+ newOwner.OwnedObjects[Handle] = this;
+ }
+
+ // indicate that the child is controlled by the native code and
+ // the managed wrapper should be disposed when the owner is
+ internal static T OwnedBy<T> (T child, SKObject owner)
+ where T : SKObject
+ {
+ if (child != null) {
+ owner.OwnedObjects[child.Handle] = child;
+ }
+
+ return child;
+ }
+
+ // indicate that the child was created by the managed code and
+ // should be disposed when the owner is
+ internal static T Owned<T> (T owner, SKObject child)
+ where T : SKObject
+ {
+ if (child != null) {
+ if (owner != null)
+ owner.OwnedObjects[child.Handle] = child;
+ else
+ child.Dispose ();
+ }
+
+ return owner;
+ }
+
+ // indicate that the chile should not be garbage collected while
+ // the owner still lives
+ internal static T Referenced<T> (T owner, SKObject child)
+ where T : SKObject
+ {
+ if (child != null && owner != null)
+ owner.KeepAliveObjects[child.Handle] = child;
+
+ return owner;
+ }
+
+ internal static int SizeOf<T> () =>
+ Marshal.SizeOf(typeof(T));
+
+ internal static T PtrToStructure<T> (IntPtr intPtr) =>
+ (T)Marshal.PtrToStructure(intPtr, typeof(T));
+
+ internal static T[] PtrToStructureArray<T> (IntPtr intPtr, int count)
+ {
+ var items = new T[count];
+ var size = SizeOf<T> ();
+ for (var i = 0; i < count; i++) {
+ var newPtr = new IntPtr (intPtr.ToInt64 () + (i * size));
+ items[i] = PtrToStructure<T> (newPtr);
+ }
+ return items;
+ }
+
+ internal static T PtrToStructure<T> (IntPtr intPtr, int index)
+ {
+ var size = SizeOf<T> ();
+ var newPtr = new IntPtr (intPtr.ToInt64 () + (index * size));
+ return PtrToStructure<T> (newPtr);
+ }
+ }
+
+ public abstract class SKNativeObject : IDisposable
+ {
+ internal bool fromFinalizer = false;
+
+ private int isDisposed = 0;
+
+ internal SKNativeObject (IntPtr handle)
+ : this (handle, true)
+ {
+ }
+
+ internal SKNativeObject (IntPtr handle, bool ownsHandle)
+ {
+ Handle = handle;
+ OwnsHandle = ownsHandle;
+ }
+
+ ~SKNativeObject ()
+ {
+ fromFinalizer = true;
+
+ Dispose (false);
+ }
+
+ public virtual IntPtr Handle { get; protected set; }
+
+ protected internal virtual bool OwnsHandle { get; protected set; }
+
+ protected internal bool IgnorePublicDispose { get; protected set; }
+
+ protected internal bool IsDisposed => isDisposed == 1;
+
+ protected virtual void DisposeManaged ()
+ {
+ // dispose of any managed resources
+ }
+
+ protected virtual void DisposeNative ()
+ {
+ // dispose of any unmanaged resources
+ }
+
+ protected virtual void Dispose (bool disposing)
+ {
+ if (Interlocked.CompareExchange (ref isDisposed, 1, 0) != 0)
+ return;
+
+ if (Handle != IntPtr.Zero && OwnsHandle)
+ DisposeNative ();
+
+ if (disposing)
+ DisposeManaged ();
+
+ Handle = IntPtr.Zero;
+ }
+
+ public void Dispose ()
+ {
+ if (IgnorePublicDispose)
+ return;
+
+ DisposeInternal ();
+ }
+
+ protected internal void DisposeInternal ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+ }
+
+ internal static class SKObjectExtensions
+ {
+ public static bool IsUnique (this IntPtr handle, bool isVirtual)
+ {
+ if (isVirtual)
+ return SkiaApi.sk_refcnt_unique (handle);
+ else
+ return SkiaApi.sk_nvrefcnt_unique (handle);
+ }
+
+ public static int GetReferenceCount (this IntPtr handle, bool isVirtual)
+ {
+ if (isVirtual)
+ return SkiaApi.sk_refcnt_get_ref_count (handle);
+ else
+ return SkiaApi.sk_nvrefcnt_get_ref_count (handle);
+ }
+
+ public static void SafeRef (this ISKReferenceCounted obj)
+ {
+ if (obj is ISKNonVirtualReferenceCounted nvrefcnt)
+ nvrefcnt.ReferenceNative ();
+ else
+ SkiaApi.sk_refcnt_safe_unref(obj.Handle);
+ }
+
+ public static void SafeUnRef (this ISKReferenceCounted obj)
+ {
+ if (obj is ISKNonVirtualReferenceCounted nvrefcnt)
+ nvrefcnt.UnreferenceNative ();
+ else
+ SkiaApi.sk_refcnt_safe_unref(obj.Handle);
+ }
+
+ public static int GetReferenceCount (this ISKReferenceCounted obj)
+ {
+ if (obj is ISKNonVirtualReferenceCounted)
+ return SkiaApi.sk_nvrefcnt_get_ref_count (obj.Handle);
+ else
+ return SkiaApi.sk_refcnt_get_ref_count (obj.Handle);
+ }
+ }
+
+ internal interface ISKReferenceCounted
+ {
+ IntPtr Handle { get; }
+ }
+
+ internal interface ISKNonVirtualReferenceCounted : ISKReferenceCounted
+ {
+ void ReferenceNative ();
+
+ void UnreferenceNative ();
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public class SKOverdrawCanvas : SKNWayCanvas
+ {
+ [Preserve]
+ internal SKOverdrawCanvas (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKOverdrawCanvas (SKCanvas canvas)
+ : this (IntPtr.Zero, true)
+ {
+ if (canvas == null)
+ throw new ArgumentNullException (nameof (canvas));
+
+ Handle = SkiaApi.sk_overdraw_canvas_new (canvas.Handle);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public readonly unsafe struct SKPMColor : IEquatable<SKPMColor>
+ {
+ private readonly uint color;
+
+ public SKPMColor (uint value)
+ {
+ color = value;
+ }
+
+ public readonly byte Alpha => (byte)((color >> SKImageInfo.PlatformColorAlphaShift) & 0xff);
+ public readonly byte Red => (byte)((color >> SKImageInfo.PlatformColorRedShift) & 0xff);
+ public readonly byte Green => (byte)((color >> SKImageInfo.PlatformColorGreenShift) & 0xff);
+ public readonly byte Blue => (byte)((color >> SKImageInfo.PlatformColorBlueShift) & 0xff);
+
+ // PreMultiply
+
+ public static SKPMColor PreMultiply (SKColor color) =>
+ SkiaApi.sk_color_premultiply ((uint)color);
+
+ public static SKPMColor[] PreMultiply (SKColor[] colors)
+ {
+ var pmcolors = new SKPMColor[colors.Length];
+ fixed (SKColor* c = colors)
+ fixed (SKPMColor* pm = pmcolors) {
+ SkiaApi.sk_color_premultiply_array ((uint*)c, colors.Length, (uint*)pm);
+ }
+ return pmcolors;
+ }
+
+ // UnPreMultiply
+
+ public static SKColor UnPreMultiply (SKPMColor pmcolor) =>
+ SkiaApi.sk_color_unpremultiply ((uint)pmcolor);
+
+ public static SKColor[] UnPreMultiply (SKPMColor[] pmcolors)
+ {
+ var colors = new SKColor[pmcolors.Length];
+ fixed (SKColor* c = colors)
+ fixed (SKPMColor* pm = pmcolors) {
+ SkiaApi.sk_color_unpremultiply_array ((uint*)pm, pmcolors.Length, (uint*)c);
+ }
+ return colors;
+ }
+
+ public static explicit operator SKPMColor (SKColor color) =>
+ SKPMColor.PreMultiply (color);
+
+ public static explicit operator SKColor (SKPMColor color) =>
+ SKPMColor.UnPreMultiply (color);
+
+ public readonly override string ToString () =>
+ $"#{Alpha:x2}{Red:x2}{Green:x2}{Blue:x2}";
+
+ public readonly bool Equals (SKPMColor obj) =>
+ obj.color == color;
+
+ public readonly override bool Equals (object other) =>
+ other is SKPMColor f && Equals (f);
+
+ public static bool operator == (SKPMColor left, SKPMColor right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKPMColor left, SKPMColor right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode () =>
+ color.GetHashCode ();
+
+ public static implicit operator SKPMColor (uint color) =>
+ new SKPMColor (color);
+
+ public static explicit operator uint (SKPMColor color) =>
+ color.color;
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKPaint : SKObject
+ {
+ [Preserve]
+ internal SKPaint (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKPaint ()
+ : this (SkiaApi.sk_paint_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKPaint instance.");
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_paint_delete (Handle);
+
+ // Reset
+
+ public void Reset ()
+ {
+ SkiaApi.sk_paint_reset (Handle);
+ }
+
+ // properties
+
+ public bool IsAntialias {
+ get => SkiaApi.sk_paint_is_antialias (Handle);
+ set => SkiaApi.sk_paint_set_antialias (Handle, value);
+ }
+
+ public bool IsDither {
+ get => SkiaApi.sk_paint_is_dither (Handle);
+ set => SkiaApi.sk_paint_set_dither (Handle, value);
+ }
+
+ public bool IsVerticalText {
+ get => SkiaApi.sk_paint_is_verticaltext (Handle);
+ set => SkiaApi.sk_paint_set_verticaltext (Handle, value);
+ }
+
+ public bool IsLinearText {
+ get => SkiaApi.sk_paint_is_linear_text (Handle);
+ set => SkiaApi.sk_paint_set_linear_text (Handle, value);
+ }
+
+ public bool SubpixelText {
+ get => SkiaApi.sk_paint_is_subpixel_text (Handle);
+ set => SkiaApi.sk_paint_set_subpixel_text (Handle, value);
+ }
+
+ public bool LcdRenderText {
+ get => SkiaApi.sk_paint_is_lcd_render_text (Handle);
+ set => SkiaApi.sk_paint_set_lcd_render_text (Handle, value);
+ }
+
+ public bool IsEmbeddedBitmapText {
+ get => SkiaApi.sk_paint_is_embedded_bitmap_text (Handle);
+ set => SkiaApi.sk_paint_set_embedded_bitmap_text (Handle, value);
+ }
+
+ public bool IsAutohinted {
+ get => SkiaApi.sk_paint_is_autohinted (Handle);
+ set => SkiaApi.sk_paint_set_autohinted (Handle, value);
+ }
+
+ public SKPaintHinting HintingLevel {
+ get => SkiaApi.sk_paint_get_hinting (Handle);
+ set => SkiaApi.sk_paint_set_hinting (Handle, value);
+ }
+
+ public bool FakeBoldText {
+ get => SkiaApi.sk_paint_is_fake_bold_text (Handle);
+ set => SkiaApi.sk_paint_set_fake_bold_text (Handle, value);
+ }
+
+ public bool DeviceKerningEnabled {
+ get => SkiaApi.sk_paint_is_dev_kern_text (Handle);
+ set => SkiaApi.sk_paint_set_dev_kern_text (Handle, value);
+ }
+
+ public bool IsStroke {
+ get => Style != SKPaintStyle.Fill;
+ set => Style = value ? SKPaintStyle.Stroke : SKPaintStyle.Fill;
+ }
+
+ public SKPaintStyle Style {
+ get => SkiaApi.sk_paint_get_style (Handle);
+ set => SkiaApi.sk_paint_set_style (Handle, value);
+ }
+
+ public SKColor Color {
+ get => SkiaApi.sk_paint_get_color (Handle);
+ set => SkiaApi.sk_paint_set_color (Handle, (uint)value);
+ }
+
+ public float StrokeWidth {
+ get => SkiaApi.sk_paint_get_stroke_width (Handle);
+ set => SkiaApi.sk_paint_set_stroke_width (Handle, value);
+ }
+
+ public float StrokeMiter {
+ get => SkiaApi.sk_paint_get_stroke_miter (Handle);
+ set => SkiaApi.sk_paint_set_stroke_miter (Handle, value);
+ }
+
+ public SKStrokeCap StrokeCap {
+ get => SkiaApi.sk_paint_get_stroke_cap (Handle);
+ set => SkiaApi.sk_paint_set_stroke_cap (Handle, value);
+ }
+
+ public SKStrokeJoin StrokeJoin {
+ get => SkiaApi.sk_paint_get_stroke_join (Handle);
+ set => SkiaApi.sk_paint_set_stroke_join (Handle, value);
+ }
+
+ public SKShader Shader {
+ get => GetObject<SKShader> (SkiaApi.sk_paint_get_shader (Handle));
+ set => SkiaApi.sk_paint_set_shader (Handle, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ public SKMaskFilter MaskFilter {
+ get => GetObject<SKMaskFilter> (SkiaApi.sk_paint_get_maskfilter (Handle));
+ set => SkiaApi.sk_paint_set_maskfilter (Handle, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ public SKColorFilter ColorFilter {
+ get => GetObject<SKColorFilter> (SkiaApi.sk_paint_get_colorfilter (Handle));
+ set => SkiaApi.sk_paint_set_colorfilter (Handle, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ public SKImageFilter ImageFilter {
+ get => GetObject<SKImageFilter> (SkiaApi.sk_paint_get_imagefilter (Handle));
+ set => SkiaApi.sk_paint_set_imagefilter (Handle, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ public SKBlendMode BlendMode {
+ get => SkiaApi.sk_paint_get_blendmode (Handle);
+ set => SkiaApi.sk_paint_set_blendmode (Handle, value);
+ }
+
+ public SKFilterQuality FilterQuality {
+ get => SkiaApi.sk_paint_get_filter_quality (Handle);
+ set => SkiaApi.sk_paint_set_filter_quality (Handle, value);
+ }
+
+ public SKTypeface Typeface {
+ get => GetObject<SKTypeface> (SkiaApi.sk_paint_get_typeface (Handle));
+ set => SkiaApi.sk_paint_set_typeface (Handle, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ public float TextSize {
+ get => SkiaApi.sk_paint_get_textsize (Handle);
+ set => SkiaApi.sk_paint_set_textsize (Handle, value);
+ }
+
+ public SKTextAlign TextAlign {
+ get => SkiaApi.sk_paint_get_text_align (Handle);
+ set => SkiaApi.sk_paint_set_text_align (Handle, value);
+ }
+
+ public SKTextEncoding TextEncoding {
+ get => SkiaApi.sk_paint_get_text_encoding (Handle);
+ set => SkiaApi.sk_paint_set_text_encoding (Handle, value);
+ }
+
+ public float TextScaleX {
+ get => SkiaApi.sk_paint_get_text_scale_x (Handle);
+ set => SkiaApi.sk_paint_set_text_scale_x (Handle, value);
+ }
+
+ public float TextSkewX {
+ get => SkiaApi.sk_paint_get_text_skew_x (Handle);
+ set => SkiaApi.sk_paint_set_text_skew_x (Handle, value);
+ }
+
+ public SKPathEffect PathEffect {
+ get => GetObject<SKPathEffect> (SkiaApi.sk_paint_get_path_effect (Handle));
+ set => SkiaApi.sk_paint_set_path_effect (Handle, value == null ? IntPtr.Zero : value.Handle);
+ }
+
+ // FontSpacing
+
+ public float FontSpacing =>
+ SkiaApi.sk_paint_get_fontmetrics (Handle, null, 0);
+
+ // FontMetrics
+
+ public SKFontMetrics FontMetrics {
+ get {
+ GetFontMetrics (out var metrics);
+ return metrics;
+ }
+ }
+
+ public float GetFontMetrics (out SKFontMetrics metrics, float scale = 0f)
+ {
+ fixed (SKFontMetrics* m = &metrics) {
+ return SkiaApi.sk_paint_get_fontmetrics (Handle, m, scale);
+ }
+ }
+
+ // Clone
+
+ public SKPaint Clone () =>
+ GetObject<SKPaint> (SkiaApi.sk_paint_clone (Handle));
+
+ // MeasureText
+
+ public float MeasureText (string text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return MeasureText (bytes);
+ }
+
+ public float MeasureText (byte[] text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* t = text) {
+ return MeasureText ((IntPtr)t, (IntPtr)text.Length);
+ }
+ }
+
+ public float MeasureText (IntPtr buffer, int length) =>
+ MeasureText (buffer, (IntPtr)length);
+
+ public float MeasureText (IntPtr buffer, IntPtr length)
+ {
+ if (buffer == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (buffer));
+
+ return SkiaApi.sk_paint_measure_text (Handle, (void*)buffer, length, null);
+ }
+
+ public float MeasureText (string text, ref SKRect bounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return MeasureText (bytes, ref bounds);
+ }
+
+ public float MeasureText (byte[] text, ref SKRect bounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* t = text) {
+ return MeasureText ((IntPtr)t, (IntPtr)text.Length, ref bounds);
+ }
+ }
+
+ public float MeasureText (IntPtr buffer, int length, ref SKRect bounds) =>
+ MeasureText (buffer, (IntPtr)length, ref bounds);
+
+ public float MeasureText (IntPtr buffer, IntPtr length, ref SKRect bounds)
+ {
+ if (buffer == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (buffer));
+
+ fixed (SKRect* b = &bounds) {
+ return SkiaApi.sk_paint_measure_text (Handle, (void*)buffer, length, b);
+ }
+ }
+
+ // BreakText
+
+ public long BreakText (string text, float maxWidth) =>
+ BreakText (text, maxWidth, out _, out _);
+
+ public long BreakText (string text, float maxWidth, out float measuredWidth) =>
+ BreakText (text, maxWidth, out measuredWidth, out _);
+
+ public long BreakText (string text, float maxWidth, out float measuredWidth, out string measuredText)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ var byteLength = (int)BreakText (bytes, maxWidth, out measuredWidth);
+ if (byteLength == 0) {
+ measuredText = string.Empty;
+ return 0;
+ }
+ if (byteLength == bytes.Length) {
+ measuredText = text;
+ return text.Length;
+ }
+ measuredText = StringUtilities.GetString (bytes, 0, byteLength, TextEncoding);
+ return measuredText.Length;
+ }
+
+ public long BreakText (byte[] text, float maxWidth) =>
+ BreakText (text, maxWidth, out _);
+
+ public long BreakText (byte[] text, float maxWidth, out float measuredWidth)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* t = text) {
+ return BreakText ((IntPtr)t, (IntPtr)text.Length, maxWidth, out measuredWidth);
+ }
+ }
+
+ public long BreakText (IntPtr buffer, int length, float maxWidth) =>
+ BreakText (buffer, (IntPtr)length, maxWidth, out _);
+
+ public long BreakText (IntPtr buffer, IntPtr length, float maxWidth) =>
+ BreakText (buffer, length, maxWidth, out _);
+
+ public long BreakText (IntPtr buffer, int length, float maxWidth, out float measuredWidth) =>
+ BreakText (buffer, (IntPtr)length, maxWidth, out measuredWidth);
+
+ public long BreakText (IntPtr buffer, IntPtr length, float maxWidth, out float measuredWidth)
+ {
+ if (buffer == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (buffer));
+
+ fixed (float* mw = &measuredWidth) {
+ return (long)SkiaApi.sk_paint_break_text (Handle, (void*)buffer, length, maxWidth, mw);
+ }
+ }
+
+ // GetTextPath
+
+ public SKPath GetTextPath (string text, float x, float y)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return GetTextPath (bytes, x, y);
+ }
+
+ public SKPath GetTextPath (byte[] text, float x, float y)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* t = text) {
+ return GetTextPath ((IntPtr)t, (IntPtr)text.Length, x, y);
+ }
+ }
+
+ public SKPath GetTextPath (IntPtr buffer, int length, float x, float y) =>
+ GetTextPath (buffer, (IntPtr)length, x, y);
+
+ public SKPath GetTextPath (IntPtr buffer, IntPtr length, float x, float y)
+ {
+ if (buffer == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (buffer));
+
+ return GetObject<SKPath> (SkiaApi.sk_paint_get_text_path (Handle, (void*)buffer, length, x, y));
+ }
+
+ public SKPath GetTextPath (string text, SKPoint[] points)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return GetTextPath (bytes, points);
+ }
+
+ public SKPath GetTextPath (byte[] text, SKPoint[] points)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* t = text) {
+ return GetTextPath ((IntPtr)t, (IntPtr)text.Length, points);
+ }
+ }
+
+ public SKPath GetTextPath (IntPtr buffer, int length, SKPoint[] points) =>
+ GetTextPath (buffer, (IntPtr)length, points);
+
+ public SKPath GetTextPath (IntPtr buffer, IntPtr length, SKPoint[] points)
+ {
+ if (buffer == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (buffer));
+
+ fixed (SKPoint* p = points) {
+ return GetObject<SKPath> (SkiaApi.sk_paint_get_pos_text_path (Handle, (void*)buffer, length, p));
+ }
+ }
+
+ // GetFillPath
+
+ public SKPath GetFillPath (SKPath src)
+ => GetFillPath (src, 1f);
+
+ public SKPath GetFillPath (SKPath src, float resScale)
+ {
+ var dst = new SKPath ();
+
+ if (GetFillPath (src, dst, resScale)) {
+ return dst;
+ } else {
+ dst.Dispose ();
+ return null;
+ }
+ }
+
+ public SKPath GetFillPath (SKPath src, SKRect cullRect)
+ => GetFillPath (src, cullRect, 1f);
+
+ public SKPath GetFillPath (SKPath src, SKRect cullRect, float resScale)
+ {
+ var dst = new SKPath ();
+
+ if (GetFillPath (src, dst, cullRect, resScale)) {
+ return dst;
+ } else {
+ dst.Dispose ();
+ return null;
+ }
+ }
+
+ public bool GetFillPath (SKPath src, SKPath dst)
+ => GetFillPath (src, dst, 1f);
+
+ public bool GetFillPath (SKPath src, SKPath dst, float resScale)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ return SkiaApi.sk_paint_get_fill_path (Handle, src.Handle, dst.Handle, null, resScale);
+ }
+
+ public bool GetFillPath (SKPath src, SKPath dst, SKRect cullRect)
+ => GetFillPath (src, dst, cullRect, 1f);
+
+ public bool GetFillPath (SKPath src, SKPath dst, SKRect cullRect, float resScale)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ return SkiaApi.sk_paint_get_fill_path (Handle, src.Handle, dst.Handle, &cullRect, resScale);
+ }
+
+ // CountGlyphs
+
+ public int CountGlyphs (string text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return CountGlyphs (bytes);
+ }
+
+ public int CountGlyphs (byte[] text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* p = text) {
+ return CountGlyphs ((IntPtr)p, (IntPtr)text.Length);
+ }
+ }
+
+ public int CountGlyphs (IntPtr text, int length) =>
+ CountGlyphs (text, (IntPtr)length);
+
+ public int CountGlyphs (IntPtr text, IntPtr length)
+ {
+ if (text == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (text));
+
+ return SkiaApi.sk_paint_count_text (Handle, (void*)text, length);
+ }
+
+ // GetGlyphs
+
+ public ushort[] GetGlyphs (string text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return GetGlyphs (bytes);
+ }
+
+ public ushort[] GetGlyphs (byte[] text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* p = text) {
+ return GetGlyphs ((IntPtr)p, (IntPtr)text.Length);
+ }
+ }
+
+ public ushort[] GetGlyphs (IntPtr text, int length) =>
+ GetGlyphs (text, (IntPtr)length);
+
+ public ushort[] GetGlyphs (IntPtr text, IntPtr length)
+ {
+ if (text == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (text));
+
+ var n = SkiaApi.sk_paint_text_to_glyphs (Handle, (void*)text, length, null);
+
+ if (n <= 0) {
+ return new ushort[0];
+ }
+
+ var glyphs = new ushort[n];
+ fixed (ushort* gp = glyphs) {
+ SkiaApi.sk_paint_text_to_glyphs (Handle, (void*)text, length, gp);
+ }
+ return glyphs;
+ }
+
+ // ContainsGlyphs
+
+ public bool ContainsGlyphs (string text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return ContainsGlyphs (bytes);
+ }
+
+ public bool ContainsGlyphs (byte[] text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* p = text) {
+ return ContainsGlyphs ((IntPtr)p, (IntPtr)text.Length);
+ }
+ }
+
+ public bool ContainsGlyphs (IntPtr text, int length) =>
+ ContainsGlyphs (text, (IntPtr)length);
+
+ public bool ContainsGlyphs (IntPtr text, IntPtr length)
+ {
+ if (text == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (text));
+
+ return SkiaApi.sk_paint_contains_text (Handle, (void*)text, length);
+ }
+
+ // GetGlyphWidths
+
+ public float[] GetGlyphWidths (string text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return GetGlyphWidths (bytes);
+ }
+
+ public float[] GetGlyphWidths (byte[] text)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* p = text) {
+ return GetGlyphWidths ((IntPtr)p, (IntPtr)text.Length);
+ }
+ }
+
+ public float[] GetGlyphWidths (IntPtr text, int length) =>
+ GetGlyphWidths (text, (IntPtr)length);
+
+ public float[] GetGlyphWidths (IntPtr text, IntPtr length)
+ {
+ if (text == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (text));
+
+ var n = SkiaApi.sk_paint_get_text_widths (Handle, (void*)text, length, null, null);
+
+ if (n <= 0) {
+ return new float[0];
+ }
+
+ var widths = new float[n];
+ fixed (float* wp = widths) {
+ SkiaApi.sk_paint_get_text_widths (Handle, (void*)text, length, wp, null);
+ }
+ return widths;
+ }
+
+ public float[] GetGlyphWidths (string text, out SKRect[] bounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return GetGlyphWidths (bytes, out bounds);
+ }
+
+ public float[] GetGlyphWidths (byte[] text, out SKRect[] bounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* p = text) {
+ return GetGlyphWidths ((IntPtr)p, (IntPtr)text.Length, out bounds);
+ }
+ }
+
+ public float[] GetGlyphWidths (IntPtr text, int length, out SKRect[] bounds) =>
+ GetGlyphWidths (text, (IntPtr)length, out bounds);
+
+ public float[] GetGlyphWidths (IntPtr text, IntPtr length, out SKRect[] bounds)
+ {
+ if (text == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (text));
+
+ var n = SkiaApi.sk_paint_get_text_widths (Handle, (void*)text, length, null, null);
+
+ if (n <= 0) {
+ bounds = new SKRect[0];
+ return new float[0];
+ }
+
+ var widths = new float[n];
+ bounds = new SKRect[n];
+ fixed (float* wp = widths)
+ fixed (SKRect* bp = bounds) {
+ SkiaApi.sk_paint_get_text_widths (Handle, (void*)text, length, wp, bp);
+ }
+ return widths;
+ }
+
+ // GetTextIntercepts
+
+ public float[] GetTextIntercepts (string text, float x, float y, float upperBounds, float lowerBounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return GetTextIntercepts (bytes, x, y, upperBounds, lowerBounds);
+ }
+
+ public float[] GetTextIntercepts (byte[] text, float x, float y, float upperBounds, float lowerBounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* p = text) {
+ return GetTextIntercepts ((IntPtr)p, (IntPtr)text.Length, x, y, upperBounds, lowerBounds);
+ }
+ }
+
+ public float[] GetTextIntercepts (IntPtr text, int length, float x, float y, float upperBounds, float lowerBounds) =>
+ GetTextIntercepts (text, (IntPtr)length, x, y, upperBounds, lowerBounds);
+
+
+ public float[] GetTextIntercepts (IntPtr text, IntPtr length, float x, float y, float upperBounds, float lowerBounds)
+ {
+ if (text == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (text));
+
+ var bounds = new[] { upperBounds, lowerBounds };
+
+ fixed (float* b = bounds) {
+ var n = SkiaApi.sk_paint_get_text_intercepts (Handle, (void*)text, length, x, y, b, null);
+
+ if (n <= 0) {
+ return new float[0];
+ }
+
+ var intervals = new float[n];
+ fixed (float* ip = intervals) {
+ SkiaApi.sk_paint_get_text_intercepts (Handle, (void*)text, length, x, y, b, ip);
+ }
+ return intervals;
+ }
+ }
+
+ // GetTextIntercepts (SKTextBlob)
+
+ public float[] GetTextIntercepts (SKTextBlob text, float upperBounds, float lowerBounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bounds = new[] { upperBounds, lowerBounds };
+
+ fixed (float* b = bounds) {
+ var n = SkiaApi.sk_paint_get_pos_text_blob_intercepts (Handle, text.Handle, b, null);
+
+ if (n <= 0) {
+ return new float[0];
+ }
+
+ var intervals = new float[n];
+ fixed (float* ip = intervals) {
+ SkiaApi.sk_paint_get_pos_text_blob_intercepts (Handle, text.Handle, b, ip);
+ }
+ return intervals;
+ }
+ }
+
+ // GetPositionedTextIntercepts
+
+ public float[] GetPositionedTextIntercepts (string text, SKPoint[] positions, float upperBounds, float lowerBounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return GetPositionedTextIntercepts (bytes, positions, upperBounds, lowerBounds);
+ }
+
+ public float[] GetPositionedTextIntercepts (byte[] text, SKPoint[] positions, float upperBounds, float lowerBounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* p = text) {
+ return GetPositionedTextIntercepts ((IntPtr)p, (IntPtr)text.Length, positions, upperBounds, lowerBounds);
+ }
+ }
+
+ public float[] GetPositionedTextIntercepts (IntPtr text, int length, SKPoint[] positions, float upperBounds, float lowerBounds) =>
+ GetPositionedTextIntercepts (text, (IntPtr)length, positions, upperBounds, lowerBounds);
+
+
+ public float[] GetPositionedTextIntercepts (IntPtr text, IntPtr length, SKPoint[] positions, float upperBounds, float lowerBounds)
+ {
+ if (text == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (text));
+
+ var bounds = new[] { upperBounds, lowerBounds };
+
+ fixed (float* b = bounds)
+ fixed (SKPoint* p = positions) {
+ var n = SkiaApi.sk_paint_get_pos_text_intercepts (Handle, (void*)text, length, p, b, null);
+
+ if (n <= 0) {
+ return new float[0];
+ }
+
+ var intervals = new float[n];
+ fixed (float* ip = intervals) {
+ SkiaApi.sk_paint_get_pos_text_intercepts (Handle, (void*)text, length, p, b, ip);
+ }
+ return intervals;
+ }
+ }
+
+ // GetHorizontalTextIntercepts
+
+ public float[] GetHorizontalTextIntercepts (string text, float[] xpositions, float y, float upperBounds, float lowerBounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ var bytes = StringUtilities.GetEncodedText (text, TextEncoding);
+ return GetHorizontalTextIntercepts (bytes, xpositions, y, upperBounds, lowerBounds);
+ }
+
+ public float[] GetHorizontalTextIntercepts (byte[] text, float[] xpositions, float y, float upperBounds, float lowerBounds)
+ {
+ if (text == null)
+ throw new ArgumentNullException (nameof (text));
+
+ fixed (byte* p = text) {
+ return GetHorizontalTextIntercepts ((IntPtr)p, (IntPtr)text.Length, xpositions, y, upperBounds, lowerBounds);
+ }
+ }
+
+ public float[] GetHorizontalTextIntercepts (IntPtr text, int length, float[] xpositions, float y, float upperBounds, float lowerBounds) =>
+ GetHorizontalTextIntercepts (text, (IntPtr)length, xpositions, y, upperBounds, lowerBounds);
+
+ public float[] GetHorizontalTextIntercepts (IntPtr text, IntPtr length, float[] xpositions, float y, float upperBounds, float lowerBounds)
+ {
+ if (text == IntPtr.Zero && length != IntPtr.Zero)
+ throw new ArgumentNullException (nameof (text));
+
+ var bounds = new[] { upperBounds, lowerBounds };
+
+ fixed (float* x = xpositions)
+ fixed (float* b = bounds) {
+ var n = SkiaApi.sk_paint_get_pos_text_h_intercepts (Handle, (void*)text, length, x, y, b, null);
+
+ if (n <= 0) {
+ return new float[0];
+ }
+
+ var intervals = new float[n];
+ fixed (float* ip = intervals) {
+ SkiaApi.sk_paint_get_pos_text_h_intercepts (Handle, (void*)text, length, x, y, b, ip);
+ }
+ return intervals;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public unsafe class SKPath : SKObject
+ {
+ [Preserve]
+ internal SKPath (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKPath ()
+ : this (SkiaApi.sk_path_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKPath instance.");
+ }
+ }
+
+ public SKPath (SKPath path)
+ : this (SkiaApi.sk_path_clone (path.Handle), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to copy the SKPath instance.");
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_path_delete (Handle);
+
+ public SKPathFillType FillType {
+ get => SkiaApi.sk_path_get_filltype (Handle);
+ set => SkiaApi.sk_path_set_filltype (Handle, value);
+ }
+
+ public SKPathConvexity Convexity {
+ get => SkiaApi.sk_path_get_convexity (Handle);
+ set => SkiaApi.sk_path_set_convexity (Handle, value);
+ }
+
+ public bool IsConvex => Convexity == SKPathConvexity.Convex;
+
+ public bool IsConcave => Convexity == SKPathConvexity.Concave;
+
+ public bool IsEmpty => VerbCount == 0;
+
+ public bool IsOval => SkiaApi.sk_path_is_oval (Handle, null);
+
+ public bool IsRoundRect => SkiaApi.sk_path_is_rrect (Handle, IntPtr.Zero);
+
+ public bool IsLine => SkiaApi.sk_path_is_line (Handle, null);
+
+ public bool IsRect => SkiaApi.sk_path_is_rect (Handle, null, null, null);
+
+ public SKPathSegmentMask SegmentMasks => (SKPathSegmentMask)SkiaApi.sk_path_get_segment_masks (Handle);
+
+ public int VerbCount => SkiaApi.sk_path_count_verbs (Handle);
+
+ public int PointCount => SkiaApi.sk_path_count_points (Handle);
+
+ public SKPoint this[int index] => GetPoint (index);
+
+ public SKPoint[] Points => GetPoints (PointCount);
+
+ public SKPoint LastPoint {
+ get {
+ SKPoint point;
+ SkiaApi.sk_path_get_last_point (Handle, &point);
+ return point;
+ }
+ }
+
+ public SKRect Bounds {
+ get {
+ SKRect rect;
+ SkiaApi.sk_path_get_bounds (Handle, &rect);
+ return rect;
+ }
+ }
+
+ public SKRect TightBounds {
+ get {
+ if (GetTightBounds (out var rect)) {
+ return rect;
+ } else {
+ return SKRect.Empty;
+ }
+ }
+ }
+
+ public SKRect GetOvalBounds ()
+ {
+ SKRect bounds;
+ if (SkiaApi.sk_path_is_oval (Handle, &bounds)) {
+ return bounds;
+ } else {
+ return SKRect.Empty;
+ }
+ }
+
+ public SKRoundRect GetRoundRect ()
+ {
+ var rrect = new SKRoundRect ();
+ var result = SkiaApi.sk_path_is_rrect (Handle, rrect.Handle);
+ if (result) {
+ return rrect;
+ } else {
+ rrect.Dispose ();
+ return null;
+ }
+ }
+
+ public SKPoint[] GetLine ()
+ {
+ var temp = new SKPoint[2];
+ fixed (SKPoint* t = temp) {
+ var result = SkiaApi.sk_path_is_line (Handle, t);
+ if (result) {
+ return temp;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ public SKRect GetRect () =>
+ GetRect (out var isClosed, out var direction);
+
+ public SKRect GetRect (out bool isClosed, out SKPathDirection direction)
+ {
+ byte c;
+ fixed (SKPathDirection* d = &direction) {
+ SKRect rect;
+ var result = SkiaApi.sk_path_is_rect (Handle, &rect, &c, d);
+ isClosed = c > 0;
+ if (result) {
+ return rect;
+ } else {
+ return SKRect.Empty;
+ }
+ }
+ }
+
+ public SKPoint GetPoint (int index)
+ {
+ if (index < 0 || index >= PointCount)
+ throw new ArgumentOutOfRangeException (nameof (index));
+
+ SKPoint point;
+ SkiaApi.sk_path_get_point (Handle, index, &point);
+ return point;
+ }
+
+ public SKPoint[] GetPoints (int max)
+ {
+ var points = new SKPoint[max];
+ GetPoints (points, max);
+ return points;
+ }
+
+ public int GetPoints (SKPoint[] points, int max)
+ {
+ fixed (SKPoint* p = points) {
+ return SkiaApi.sk_path_get_points (Handle, p, max);
+ }
+ }
+
+ public bool Contains (float x, float y) =>
+ SkiaApi.sk_path_contains (Handle, x, y);
+
+ public void Offset (SKPoint offset) =>
+ Offset (offset.X, offset.Y);
+
+ public void Offset (float dx, float dy) =>
+ Transform (SKMatrix.MakeTranslation (dx, dy));
+
+ public void MoveTo (SKPoint point) =>
+ SkiaApi.sk_path_move_to (Handle, point.X, point.Y);
+
+ public void MoveTo (float x, float y) =>
+ SkiaApi.sk_path_move_to (Handle, x, y);
+
+ public void RMoveTo (SKPoint point) =>
+ SkiaApi.sk_path_rmove_to (Handle, point.X, point.Y);
+
+ public void RMoveTo (float dx, float dy) =>
+ SkiaApi.sk_path_rmove_to (Handle, dx, dy);
+
+ public void LineTo (SKPoint point) =>
+ SkiaApi.sk_path_line_to (Handle, point.X, point.Y);
+
+ public void LineTo (float x, float y) =>
+ SkiaApi.sk_path_line_to (Handle, x, y);
+
+ public void RLineTo (SKPoint point) =>
+ SkiaApi.sk_path_rline_to (Handle, point.X, point.Y);
+
+ public void RLineTo (float dx, float dy) =>
+ SkiaApi.sk_path_rline_to (Handle, dx, dy);
+
+ public void QuadTo (SKPoint point0, SKPoint point1) =>
+ SkiaApi.sk_path_quad_to (Handle, point0.X, point0.Y, point1.X, point1.Y);
+
+ public void QuadTo (float x0, float y0, float x1, float y1) =>
+ SkiaApi.sk_path_quad_to (Handle, x0, y0, x1, y1);
+
+ public void RQuadTo (SKPoint point0, SKPoint point1) =>
+ SkiaApi.sk_path_rquad_to (Handle, point0.X, point0.Y, point1.X, point1.Y);
+
+ public void RQuadTo (float dx0, float dy0, float dx1, float dy1) =>
+ SkiaApi.sk_path_rquad_to (Handle, dx0, dy0, dx1, dy1);
+
+ public void ConicTo (SKPoint point0, SKPoint point1, float w) =>
+ SkiaApi.sk_path_conic_to (Handle, point0.X, point0.Y, point1.X, point1.Y, w);
+
+ public void ConicTo (float x0, float y0, float x1, float y1, float w) =>
+ SkiaApi.sk_path_conic_to (Handle, x0, y0, x1, y1, w);
+
+ public void RConicTo (SKPoint point0, SKPoint point1, float w) =>
+ SkiaApi.sk_path_rconic_to (Handle, point0.X, point0.Y, point1.X, point1.Y, w);
+
+ public void RConicTo (float dx0, float dy0, float dx1, float dy1, float w) =>
+ SkiaApi.sk_path_rconic_to (Handle, dx0, dy0, dx1, dy1, w);
+
+ public void CubicTo (SKPoint point0, SKPoint point1, SKPoint point2) =>
+ SkiaApi.sk_path_cubic_to (Handle, point0.X, point0.Y, point1.X, point1.Y, point2.X, point2.Y);
+
+ public void CubicTo (float x0, float y0, float x1, float y1, float x2, float y2) =>
+ SkiaApi.sk_path_cubic_to (Handle, x0, y0, x1, y1, x2, y2);
+
+ public void RCubicTo (SKPoint point0, SKPoint point1, SKPoint point2) =>
+ SkiaApi.sk_path_rcubic_to (Handle, point0.X, point0.Y, point1.X, point1.Y, point2.X, point2.Y);
+
+ public void RCubicTo (float dx0, float dy0, float dx1, float dy1, float dx2, float dy2) =>
+ SkiaApi.sk_path_rcubic_to (Handle, dx0, dy0, dx1, dy1, dx2, dy2);
+
+ public void ArcTo (SKPoint r, float xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, SKPoint xy) =>
+ SkiaApi.sk_path_arc_to (Handle, r.X, r.Y, xAxisRotate, largeArc, sweep, xy.X, xy.Y);
+
+ public void ArcTo (float rx, float ry, float xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, float x, float y) =>
+ SkiaApi.sk_path_arc_to (Handle, rx, ry, xAxisRotate, largeArc, sweep, x, y);
+
+ public void ArcTo (SKRect oval, float startAngle, float sweepAngle, bool forceMoveTo) =>
+ SkiaApi.sk_path_arc_to_with_oval (Handle, &oval, startAngle, sweepAngle, forceMoveTo);
+
+ public void ArcTo (SKPoint point1, SKPoint point2, float radius) =>
+ SkiaApi.sk_path_arc_to_with_points (Handle, point1.X, point1.Y, point2.X, point2.Y, radius);
+
+ public void ArcTo (float x1, float y1, float x2, float y2, float radius) =>
+ SkiaApi.sk_path_arc_to_with_points (Handle, x1, y1, x2, y2, radius);
+
+ public void RArcTo (SKPoint r, float xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, SKPoint xy) =>
+ SkiaApi.sk_path_rarc_to (Handle, r.X, r.Y, xAxisRotate, largeArc, sweep, xy.X, xy.Y);
+
+ public void RArcTo (float rx, float ry, float xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, float x, float y) =>
+ SkiaApi.sk_path_rarc_to (Handle, rx, ry, xAxisRotate, largeArc, sweep, x, y);
+
+ public void Close () =>
+ SkiaApi.sk_path_close (Handle);
+
+ public void Rewind () =>
+ SkiaApi.sk_path_rewind (Handle);
+
+ public void Reset () =>
+ SkiaApi.sk_path_reset (Handle);
+
+ public void AddRect (SKRect rect, SKPathDirection direction = SKPathDirection.Clockwise) =>
+ SkiaApi.sk_path_add_rect (Handle, &rect, direction);
+
+ public void AddRect (SKRect rect, SKPathDirection direction, uint startIndex)
+ {
+ if (startIndex > 3)
+ throw new ArgumentOutOfRangeException (nameof (startIndex), "Starting index must be in the range of 0..3 (inclusive).");
+
+ SkiaApi.sk_path_add_rect_start (Handle, &rect, direction, startIndex);
+ }
+
+ public void AddRoundRect (SKRoundRect rect, SKPathDirection direction = SKPathDirection.Clockwise)
+ {
+ if (rect == null)
+ throw new ArgumentNullException (nameof (rect));
+ SkiaApi.sk_path_add_rrect (Handle, rect.Handle, direction);
+ }
+
+ public void AddRoundRect (SKRoundRect rect, SKPathDirection direction, uint startIndex)
+ {
+ if (rect == null)
+ throw new ArgumentNullException (nameof (rect));
+ SkiaApi.sk_path_add_rrect_start (Handle, rect.Handle, direction, startIndex);
+ }
+
+ public void AddOval (SKRect rect, SKPathDirection direction = SKPathDirection.Clockwise) =>
+ SkiaApi.sk_path_add_oval (Handle, &rect, direction);
+
+ public void AddArc (SKRect oval, float startAngle, float sweepAngle) =>
+ SkiaApi.sk_path_add_arc (Handle, &oval, startAngle, sweepAngle);
+
+ public bool GetBounds (out SKRect rect)
+ {
+ var isEmpty = IsEmpty;
+ if (isEmpty) {
+ rect = SKRect.Empty;
+ } else {
+ fixed (SKRect* r = &rect) {
+ SkiaApi.sk_path_get_bounds (Handle, r);
+ }
+ }
+ return !isEmpty;
+ }
+
+ public SKRect ComputeTightBounds ()
+ {
+ SKRect rect;
+ SkiaApi.sk_path_compute_tight_bounds (Handle, &rect);
+ return rect;
+ }
+
+ public void Transform (SKMatrix matrix) =>
+ SkiaApi.sk_path_transform (Handle, &matrix);
+
+ public void Transform (SKMatrix matrix, SKPath destination)
+ {
+ if (destination == null)
+ throw new ArgumentNullException (nameof (destination));
+
+ SkiaApi.sk_path_transform_to_dest (Handle, &matrix, destination.Handle);
+ }
+
+ public void AddPath (SKPath other, float dx, float dy, SKPathAddMode mode = SKPathAddMode.Append)
+ {
+ if (other == null)
+ throw new ArgumentNullException (nameof (other));
+
+ SkiaApi.sk_path_add_path_offset (Handle, other.Handle, dx, dy, mode);
+ }
+
+ public void AddPath (SKPath other, ref SKMatrix matrix, SKPathAddMode mode = SKPathAddMode.Append)
+ {
+ if (other == null)
+ throw new ArgumentNullException (nameof (other));
+
+ fixed (SKMatrix* m = &matrix) {
+ SkiaApi.sk_path_add_path_matrix (Handle, other.Handle, m, mode);
+ }
+ }
+
+ public void AddPath (SKPath other, SKPathAddMode mode = SKPathAddMode.Append)
+ {
+ if (other == null)
+ throw new ArgumentNullException (nameof (other));
+
+ SkiaApi.sk_path_add_path (Handle, other.Handle, mode);
+ }
+
+ public void AddPathReverse (SKPath other)
+ {
+ if (other == null)
+ throw new ArgumentNullException (nameof (other));
+
+ SkiaApi.sk_path_add_path_reverse (Handle, other.Handle);
+ }
+
+ public void AddRoundRect (SKRect rect, float rx, float ry, SKPathDirection dir = SKPathDirection.Clockwise) =>
+ SkiaApi.sk_path_add_rounded_rect (Handle, &rect, rx, ry, dir);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use AddRoundRect instead.")]
+ public void AddRoundedRect (SKRect rect, float rx, float ry, SKPathDirection dir = SKPathDirection.Clockwise) =>
+ AddRoundRect (rect, rx, ry, dir);
+
+ public void AddCircle (float x, float y, float radius, SKPathDirection dir = SKPathDirection.Clockwise) =>
+ SkiaApi.sk_path_add_circle (Handle, x, y, radius, dir);
+
+ public void AddPoly (SKPoint[] points, bool close = true)
+ {
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+ fixed (SKPoint* p = points) {
+ SkiaApi.sk_path_add_poly (Handle, p, points.Length, close);
+ }
+ }
+
+ public Iterator CreateIterator (bool forceClose) =>
+ new Iterator (this, forceClose);
+
+ public RawIterator CreateRawIterator () =>
+ new RawIterator (this);
+
+ public bool Op (SKPath other, SKPathOp op, SKPath result)
+ {
+ if (other == null)
+ throw new ArgumentNullException (nameof (other));
+ if (result == null)
+ throw new ArgumentNullException (nameof (result));
+
+ return SkiaApi.sk_pathop_op (Handle, other.Handle, op, result.Handle);
+ }
+
+ public SKPath Op (SKPath other, SKPathOp op)
+ {
+ var result = new SKPath ();
+ if (Op (other, op, result)) {
+ return result;
+ } else {
+ result.Dispose ();
+ return null;
+ }
+ }
+
+ public bool Simplify (SKPath result)
+ {
+ if (result == null)
+ throw new ArgumentNullException (nameof (result));
+
+ return SkiaApi.sk_pathop_simplify (Handle, result.Handle);
+ }
+
+ public SKPath Simplify ()
+ {
+ var result = new SKPath ();
+ if (Simplify (result)) {
+ return result;
+ } else {
+ result.Dispose ();
+ return null;
+ }
+ }
+
+ public bool GetTightBounds (out SKRect result)
+ {
+ fixed (SKRect* r = &result) {
+ return SkiaApi.sk_pathop_tight_bounds (Handle, r);
+ }
+ }
+
+ public string ToSvgPathData ()
+ {
+ using (var str = new SKString ()) {
+ SkiaApi.sk_path_to_svg_string (Handle, str.Handle);
+ return (string)str;
+ }
+ }
+
+ public static SKPath ParseSvgPathData (string svgPath)
+ {
+ var path = new SKPath ();
+ var success = SkiaApi.sk_path_parse_svg_string (path.Handle, svgPath);
+ if (!success) {
+ path.Dispose ();
+ path = null;
+ }
+ return path;
+ }
+
+ public static SKPoint[] ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, int pow2)
+ {
+ ConvertConicToQuads (p0, p1, p2, w, out var pts, pow2);
+ return pts;
+ }
+
+ public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, out SKPoint[] pts, int pow2)
+ {
+ var quadCount = 1 << pow2;
+ var ptCount = 2 * quadCount + 1;
+ pts = new SKPoint[ptCount];
+ return ConvertConicToQuads (p0, p1, p2, w, pts, pow2);
+ }
+
+ public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, SKPoint[] pts, int pow2)
+ {
+ if (pts == null)
+ throw new ArgumentNullException (nameof (pts));
+ fixed (SKPoint* ptsptr = pts) {
+ return SkiaApi.sk_path_convert_conic_to_quads (&p0, &p1, &p2, w, ptsptr, pow2);
+ }
+ }
+
+ public class Iterator : SKObject
+ {
+ private readonly SKPath path;
+
+ internal Iterator (SKPath path, bool forceClose)
+ : base (SkiaApi.sk_path_create_iter (path.Handle, forceClose ? 1 : 0), true)
+ {
+ this.path = path;
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_path_iter_destroy (Handle);
+
+ public SKPathVerb Next (SKPoint[] points, bool doConsumeDegenerates = true, bool exact = false)
+ {
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+ if (points.Length != 4)
+ throw new ArgumentException ("Must be an array of four elements.", nameof (points));
+ fixed (SKPoint* p = points) {
+ return SkiaApi.sk_path_iter_next (Handle, p, doConsumeDegenerates ? 1 : 0, exact ? 1 : 0);
+ }
+ }
+
+ public float ConicWeight () =>
+ SkiaApi.sk_path_iter_conic_weight (Handle);
+ public bool IsCloseLine () =>
+ SkiaApi.sk_path_iter_is_close_line (Handle) != 0;
+ public bool IsCloseContour () =>
+ SkiaApi.sk_path_iter_is_closed_contour (Handle) != 0;
+ }
+
+ public class RawIterator : SKObject
+ {
+ private readonly SKPath path;
+
+ internal RawIterator (SKPath path)
+ : base (SkiaApi.sk_path_create_rawiter (path.Handle), true)
+ {
+ this.path = path;
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_path_rawiter_destroy (Handle);
+
+ public SKPathVerb Next (SKPoint[] points)
+ {
+ if (points == null)
+ throw new ArgumentNullException (nameof (points));
+ if (points.Length != 4)
+ throw new ArgumentException ("Must be an array of four elements.", nameof (points));
+ fixed (SKPoint* p = points) {
+ return SkiaApi.sk_path_rawiter_next (Handle, p);
+ }
+ }
+
+ public float ConicWeight () =>
+ SkiaApi.sk_path_rawiter_conic_weight (Handle);
+ public SKPathVerb Peek () =>
+ SkiaApi.sk_path_rawiter_peek (Handle);
+ }
+
+ public class OpBuilder : SKObject
+ {
+ public OpBuilder ()
+ : base (SkiaApi.sk_opbuilder_new (), true)
+ {
+ }
+
+ public void Add (SKPath path, SKPathOp op) =>
+ SkiaApi.sk_opbuilder_add (Handle, path.Handle, op);
+
+ public bool Resolve (SKPath result)
+ {
+ if (result == null)
+ throw new ArgumentNullException (nameof (result));
+
+ return SkiaApi.sk_opbuilder_resolve (Handle, result.Handle);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_opbuilder_destroy (Handle);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKPathEffect : SKObject, ISKReferenceCounted
+ {
+ [Preserve]
+ internal SKPathEffect (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public static SKPathEffect CreateCompose(SKPathEffect outer, SKPathEffect inner)
+ {
+ if (outer == null)
+ throw new ArgumentNullException(nameof(outer));
+ if (inner == null)
+ throw new ArgumentNullException(nameof(inner));
+ return GetObject<SKPathEffect>(SkiaApi.sk_path_effect_create_compose(outer.Handle, inner.Handle));
+ }
+
+ public static SKPathEffect CreateSum(SKPathEffect first, SKPathEffect second)
+ {
+ if (first == null)
+ throw new ArgumentNullException(nameof(first));
+ if (second == null)
+ throw new ArgumentNullException(nameof(second));
+ return GetObject<SKPathEffect>(SkiaApi.sk_path_effect_create_sum(first.Handle, second.Handle));
+ }
+
+ public static SKPathEffect CreateDiscrete(float segLength, float deviation, UInt32 seedAssist = 0)
+ {
+ return GetObject<SKPathEffect>(SkiaApi.sk_path_effect_create_discrete(segLength, deviation, seedAssist));
+ }
+
+ public static SKPathEffect CreateCorner(float radius)
+ {
+ return GetObject<SKPathEffect>(SkiaApi.sk_path_effect_create_corner(radius));
+ }
+
+ public static SKPathEffect Create1DPath(SKPath path, float advance, float phase, SKPath1DPathEffectStyle style)
+ {
+ if (path == null)
+ throw new ArgumentNullException(nameof(path));
+ return GetObject<SKPathEffect>(SkiaApi.sk_path_effect_create_1d_path(path.Handle, advance, phase, style));
+ }
+
+ public static SKPathEffect Create2DLine(float width, SKMatrix matrix)
+ {
+ return GetObject<SKPathEffect>(SkiaApi.sk_path_effect_create_2d_line(width, &matrix));
+ }
+
+ public static SKPathEffect Create2DPath(SKMatrix matrix, SKPath path)
+ {
+ if (path == null)
+ throw new ArgumentNullException(nameof(path));
+ return GetObject<SKPathEffect>(SkiaApi.sk_path_effect_create_2d_path(&matrix, path.Handle));
+ }
+
+ public static SKPathEffect CreateDash(float[] intervals, float phase)
+ {
+ if (intervals == null)
+ throw new ArgumentNullException(nameof(intervals));
+ if (intervals.Length % 2 != 0)
+ throw new ArgumentException("The intervals must have an even number of entries.", nameof(intervals));
+ fixed (float* i = intervals) {
+ return GetObject<SKPathEffect> (SkiaApi.sk_path_effect_create_dash (i, intervals.Length, phase));
+ }
+ }
+
+ public static SKPathEffect CreateTrim(float start, float stop)
+ {
+ return CreateTrim(start, stop, SKTrimPathEffectMode.Normal);
+ }
+
+ public static SKPathEffect CreateTrim(float start, float stop, SKTrimPathEffectMode mode)
+ {
+ return GetObject<SKPathEffect>(SkiaApi.sk_path_effect_create_trim(start, stop, mode));
+ }
+ }
+}
+
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKPathMeasure : SKObject
+ {
+ [Preserve]
+ internal SKPathMeasure (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKPathMeasure ()
+ : this (SkiaApi.sk_pathmeasure_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKPathMeasure instance.");
+ }
+ }
+
+ public SKPathMeasure (SKPath path, bool forceClosed = false, float resScale = 1)
+ : this (IntPtr.Zero, true)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+
+ Handle = SkiaApi.sk_pathmeasure_new_with_path (path.Handle, forceClosed, resScale);
+
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKPathMeasure instance.");
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_pathmeasure_destroy (Handle);
+
+ // properties
+
+ public float Length {
+ get {
+ return SkiaApi.sk_pathmeasure_get_length (Handle);
+ }
+ }
+
+ public bool IsClosed {
+ get {
+ return SkiaApi.sk_pathmeasure_is_closed (Handle);
+ }
+ }
+
+ // SetPath
+
+ public void SetPath (SKPath path) =>
+ SetPath (path, false);
+
+ public void SetPath (SKPath path, bool forceClosed)
+ {
+ SkiaApi.sk_pathmeasure_set_path (Handle, path == null ? IntPtr.Zero : path.Handle, forceClosed);
+ }
+
+ // GetPositionAndTangent
+
+ public bool GetPositionAndTangent (float distance, out SKPoint position, out SKPoint tangent)
+ {
+ fixed (SKPoint* p = &position)
+ fixed (SKPoint* t = &tangent) {
+ return SkiaApi.sk_pathmeasure_get_pos_tan (Handle, distance, p, t);
+ }
+ }
+
+ // GetPosition
+
+ public SKPoint GetPosition (float distance)
+ {
+ if (!GetPosition (distance, out var position))
+ position = SKPoint.Empty;
+ return position;
+ }
+
+ public bool GetPosition (float distance, out SKPoint position)
+ {
+ fixed (SKPoint* p = &position) {
+ return SkiaApi.sk_pathmeasure_get_pos_tan (Handle, distance, p, null);
+ }
+ }
+
+ // GetTangent
+
+ public SKPoint GetTangent (float distance)
+ {
+ if (!GetTangent (distance, out var tangent))
+ tangent = SKPoint.Empty;
+ return tangent;
+ }
+
+ public bool GetTangent (float distance, out SKPoint tangent)
+ {
+ fixed (SKPoint* t = &tangent) {
+ return SkiaApi.sk_pathmeasure_get_pos_tan (Handle, distance, null, t);
+ }
+ }
+
+ // GetMatrix
+
+ public SKMatrix GetMatrix (float distance, SKPathMeasureMatrixFlags flags)
+ {
+ if (!GetMatrix (distance, out var matrix, flags))
+ matrix = SKMatrix.Empty;
+ return matrix;
+ }
+
+ public bool GetMatrix (float distance, out SKMatrix matrix, SKPathMeasureMatrixFlags flags)
+ {
+ fixed (SKMatrix* m = &matrix) {
+ return SkiaApi.sk_pathmeasure_get_matrix (Handle, distance, m, flags);
+ }
+ }
+
+ // GetSegment
+
+ public bool GetSegment (float start, float stop, SKPath dst, bool startWithMoveTo)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ return SkiaApi.sk_pathmeasure_get_segment (Handle, start, stop, dst.Handle, startWithMoveTo);
+ }
+
+ public SKPath GetSegment (float start, float stop, bool startWithMoveTo)
+ {
+ var dst = new SKPath ();
+ if (!GetSegment (start, stop, dst, startWithMoveTo)) {
+ dst.Dispose ();
+ dst = null;
+ }
+ return dst;
+ }
+
+ // NextContour
+
+ public bool NextContour ()
+ {
+ return SkiaApi.sk_pathmeasure_next_contour (Handle);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKPicture : SKObject, ISKReferenceCounted
+ {
+ [Preserve]
+ internal SKPicture (IntPtr h, bool owns)
+ : base (h, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public uint UniqueId =>
+ SkiaApi.sk_picture_get_unique_id (Handle);
+
+ public SKRect CullRect {
+ get {
+ SKRect rect;
+ SkiaApi.sk_picture_get_cull_rect (Handle, &rect);
+ return rect;
+ }
+ }
+
+ // ToShader
+
+ public SKShader ToShader () =>
+ ToShader (SKShaderTileMode.Clamp, SKShaderTileMode.Clamp);
+
+ public SKShader ToShader (SKShaderTileMode tmx, SKShaderTileMode tmy) =>
+ SKShader.CreatePicture (this, tmx, tmy);
+
+ public SKShader ToShader (SKShaderTileMode tmx, SKShaderTileMode tmy, SKRect tile) =>
+ SKShader.CreatePicture (this, tmx, tmy, tile);
+
+ public SKShader ToShader (SKShaderTileMode tmx, SKShaderTileMode tmy, SKMatrix localMatrix, SKRect tile) =>
+ SKShader.CreatePicture (this, tmx, tmy, localMatrix, tile);
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKPictureRecorder : SKObject
+ {
+ [Preserve]
+ internal SKPictureRecorder (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKPictureRecorder ()
+ : this (SkiaApi.sk_picture_recorder_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKPictureRecorder instance.");
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_picture_recorder_delete (Handle);
+
+ public SKCanvas BeginRecording (SKRect cullRect)
+ {
+ return OwnedBy (GetObject<SKCanvas> (SkiaApi.sk_picture_recorder_begin_recording (Handle, &cullRect), false), this);
+ }
+
+ public SKPicture EndRecording ()
+ {
+ return GetObject<SKPicture> (SkiaApi.sk_picture_recorder_end_recording (Handle));
+ }
+
+ public SKDrawable EndRecordingAsDrawable ()
+ {
+ return GetObject<SKDrawable> (SkiaApi.sk_picture_recorder_end_recording_as_drawable (Handle));
+ }
+
+ public SKCanvas RecordingCanvas =>
+ OwnedBy (GetObject<SKCanvas> (SkiaApi.sk_picture_get_recording_canvas (Handle), false), this);
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public abstract class SKPixelSerializer : SKObject
+ {
+ protected SKPixelSerializer ()
+ : base (IntPtr.Zero, false)
+ {
+ }
+
+ public bool UseEncodedData (IntPtr data, ulong length)
+ {
+ if (SKObject.SizeOf<IntPtr> () == 4 && length > UInt32.MaxValue)
+ throw new ArgumentOutOfRangeException (nameof (length), "The length exceeds the size of pointers.");
+
+ return OnUseEncodedData (data, (IntPtr)length);
+ }
+
+ public SKData Encode (SKPixmap pixmap)
+ {
+ if (pixmap == null)
+ throw new ArgumentNullException (nameof (pixmap));
+
+ return OnEncode (pixmap);
+ }
+
+ protected abstract bool OnUseEncodedData (IntPtr data, IntPtr length);
+
+ protected abstract SKData OnEncode (SKPixmap pixmap);
+
+ public static SKPixelSerializer Create (Func<SKPixmap, SKData> onEncode)
+ {
+ return new SKSimplePixelSerializer (null, onEncode);
+ }
+
+ public static SKPixelSerializer Create (Func<IntPtr, IntPtr, bool> onUseEncodedData, Func<SKPixmap, SKData> onEncode)
+ {
+ return new SKSimplePixelSerializer (onUseEncodedData, onEncode);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ internal class SKSimplePixelSerializer : SKPixelSerializer
+ {
+ private readonly Func<IntPtr, IntPtr, bool> onUseEncodedData;
+ private readonly Func<SKPixmap, SKData> onEncode;
+
+ public SKSimplePixelSerializer (Func<IntPtr, IntPtr, bool> onUseEncodedData, Func<SKPixmap, SKData> onEncode)
+ {
+ this.onUseEncodedData = onUseEncodedData;
+ this.onEncode = onEncode;
+ }
+
+ protected override SKData OnEncode (SKPixmap pixmap)
+ {
+ return onEncode?.Invoke (pixmap) ?? null;
+ }
+
+ protected override bool OnUseEncodedData (IntPtr data, IntPtr length)
+ {
+ return onUseEncodedData?.Invoke (data, length) ?? false;
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public abstract class SKManagedPixelSerializer : SKPixelSerializer
+ {
+ public SKManagedPixelSerializer ()
+ {
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.IO;
+
+namespace SkiaSharp
+{
+ public unsafe class SKPixmap : SKObject
+ {
+ private const string UnableToCreateInstanceMessage = "Unable to create a new SKPixmap instance.";
+
+ // this is not meant to be anything but a GC reference to keep the actual pixel data alive
+ internal SKObject pixelSource;
+
+ [Preserve]
+ internal SKPixmap (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKPixmap ()
+ : this (SkiaApi.sk_pixmap_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException (UnableToCreateInstanceMessage);
+ }
+ }
+
+ public SKPixmap (SKImageInfo info, IntPtr addr)
+ : this (info, addr, info.RowBytes)
+ {
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use SKPixmap(SKImageInfo, IntPtr, int) instead.")]
+ public SKPixmap (SKImageInfo info, IntPtr addr, int rowBytes, SKColorTable ctable)
+ : this (info, addr, info.RowBytes)
+ {
+ }
+
+ public SKPixmap (SKImageInfo info, IntPtr addr, int rowBytes)
+ : this (IntPtr.Zero, true)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ Handle = SkiaApi.sk_pixmap_new_with_params (&cinfo, (void*)addr, (IntPtr)rowBytes);
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException (UnableToCreateInstanceMessage);
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_pixmap_destructor (Handle);
+
+ protected override void DisposeManaged ()
+ {
+ base.DisposeManaged ();
+
+ pixelSource = null;
+ }
+
+ // Reset
+
+ public void Reset ()
+ {
+ SkiaApi.sk_pixmap_reset (Handle);
+ pixelSource = null;
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported. Use Reset(SKImageInfo, IntPtr, int) instead.")]
+ public void Reset (SKImageInfo info, IntPtr addr, int rowBytes, SKColorTable ctable)
+ {
+ Reset (info, addr, rowBytes);
+ }
+
+ public void Reset (SKImageInfo info, IntPtr addr, int rowBytes)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ SkiaApi.sk_pixmap_reset_with_params (Handle, &cinfo, (void*)addr, (IntPtr)rowBytes);
+ pixelSource = null;
+ }
+
+ // properties
+
+ public SKImageInfo Info {
+ get {
+ SKImageInfoNative cinfo;
+ SkiaApi.sk_pixmap_get_info (Handle, &cinfo);
+ return SKImageInfoNative.ToManaged (ref cinfo);
+ }
+ }
+
+ public int Width => Info.Width;
+
+ public int Height => Info.Height;
+
+ public SKSizeI Size => new SKSizeI (Width, Height);
+
+ public SKRectI Rect => SKRectI.Create (Width, Height);
+
+ public SKColorType ColorType => Info.ColorType;
+
+ public SKAlphaType AlphaType => Info.AlphaType;
+
+ public SKColorSpace ColorSpace => Info.ColorSpace;
+
+ public int BytesPerPixel => Info.BytesPerPixel;
+
+ public int RowBytes => (int)SkiaApi.sk_pixmap_get_row_bytes (Handle);
+
+ public int BytesSize => Info.BytesSize;
+
+ // pixels
+
+ public IntPtr GetPixels () =>
+ (IntPtr)SkiaApi.sk_pixmap_get_pixels (Handle);
+
+ public IntPtr GetPixels (int x, int y) =>
+ (IntPtr)SkiaApi.sk_pixmap_get_pixels_with_xy (Handle, x, y);
+
+ public ReadOnlySpan<byte> GetPixelSpan ()
+ {
+ return new ReadOnlySpan<byte> ((void*)GetPixels (), BytesSize);
+ }
+
+ public SKColor GetPixelColor (int x, int y)
+ {
+ return SkiaApi.sk_pixmap_get_pixel_color (Handle, x, y);
+ }
+
+ // ColorTable
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("The Index8 color type and color table is no longer supported.")]
+ public SKColorTable ColorTable => null;
+
+ // Resize
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use ScalePixels(SKPixmap, SKFilterQuality) instead.")]
+ public static bool Resize (SKPixmap dst, SKPixmap src, SKBitmapResizeMethod method)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return src.ScalePixels (dst, method.ToFilterQuality ());
+ }
+
+ // ScalePixels
+
+ public bool ScalePixels (SKPixmap destination, SKFilterQuality quality)
+ {
+ if (destination == null)
+ throw new ArgumentNullException (nameof (destination));
+
+ return SkiaApi.sk_pixmap_scale_pixels (Handle, destination.Handle, quality);
+ }
+
+ // ReadPixels
+
+ public bool ReadPixels (SKImageInfo dstInfo, IntPtr dstPixels, int dstRowBytes, int srcX, int srcY, SKTransferFunctionBehavior behavior)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref dstInfo);
+ return SkiaApi.sk_pixmap_read_pixels (Handle, &cinfo, (void*)dstPixels, (IntPtr)dstRowBytes, srcX, srcY, behavior);
+ }
+
+ public bool ReadPixels (SKImageInfo dstInfo, IntPtr dstPixels, int dstRowBytes, int srcX, int srcY)
+ {
+ return ReadPixels (dstInfo, dstPixels, dstRowBytes, 0, 0, SKTransferFunctionBehavior.Respect);
+ }
+
+ public bool ReadPixels (SKImageInfo dstInfo, IntPtr dstPixels, int dstRowBytes)
+ {
+ return ReadPixels (dstInfo, dstPixels, dstRowBytes, 0, 0, SKTransferFunctionBehavior.Respect);
+ }
+
+ public bool ReadPixels (SKPixmap pixmap, int srcX, int srcY)
+ {
+ return ReadPixels (pixmap.Info, pixmap.GetPixels (), pixmap.RowBytes, srcX, srcY, SKTransferFunctionBehavior.Respect);
+ }
+
+ public bool ReadPixels (SKPixmap pixmap)
+ {
+ return ReadPixels (pixmap.Info, pixmap.GetPixels (), pixmap.RowBytes, 0, 0, SKTransferFunctionBehavior.Respect);
+ }
+
+ // Encode
+
+ public SKData Encode (SKEncodedImageFormat encoder, int quality)
+ {
+ using var stream = new SKDynamicMemoryWStream ();
+ var result = Encode (stream, encoder, quality);
+ return result ? stream.DetachAsData () : null;
+ }
+
+ public bool Encode (Stream dst, SKEncodedImageFormat encoder, int quality)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ using var wrapped = new SKManagedWStream (dst);
+ return Encode (wrapped, encoder, quality);
+ }
+
+ public bool Encode (SKWStream dst, SKEncodedImageFormat encoder, int quality)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ return SkiaApi.sk_pixmap_encode_image (dst.Handle, Handle, encoder, quality);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Encode(SKWStream, SKEncodedImageFormat, int) instead.")]
+ public static bool Encode (SKWStream dst, SKBitmap src, SKEncodedImageFormat format, int quality)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return src.Encode (dst, format, quality);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Encode(SKWStream, SKEncodedImageFormat, int) instead.")]
+ public static bool Encode (SKWStream dst, SKPixmap src, SKEncodedImageFormat encoder, int quality)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return src.Encode (dst, encoder, quality);
+ }
+
+ // Encode (webp)
+
+ public SKData Encode (SKWebpEncoderOptions options)
+ {
+ using var stream = new SKDynamicMemoryWStream ();
+ var result = Encode (stream, options);
+ return result ? stream.DetachAsData () : null;
+ }
+
+ public bool Encode (Stream dst, SKWebpEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ using var wrapped = new SKManagedWStream (dst);
+ return Encode (wrapped, options);
+ }
+
+ public bool Encode (SKWStream dst, SKWebpEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ return SkiaApi.sk_webpencoder_encode (dst.Handle, Handle, &options);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Encode(SKWStream, SKWebpEncoderOptions) instead.")]
+ public static bool Encode (SKWStream dst, SKPixmap src, SKWebpEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return src.Encode (dst, options);
+ }
+
+ // Encode (jpeg)
+
+ public SKData Encode (SKJpegEncoderOptions options)
+ {
+ using var stream = new SKDynamicMemoryWStream ();
+ var result = Encode (stream, options);
+ return result ? stream.DetachAsData () : null;
+ }
+
+ public bool Encode (Stream dst, SKJpegEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ using var wrapped = new SKManagedWStream (dst);
+ return Encode (wrapped, options);
+ }
+
+ public bool Encode (SKWStream dst, SKJpegEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ return SkiaApi.sk_jpegencoder_encode (dst.Handle, Handle, &options);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Encode(SKWStream, SKJpegEncoderOptions) instead.")]
+ public static bool Encode (SKWStream dst, SKPixmap src, SKJpegEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return src.Encode (dst, options);
+ }
+
+ // Encode (png)
+
+ public SKData Encode (SKPngEncoderOptions options)
+ {
+ using var stream = new SKDynamicMemoryWStream ();
+ var result = Encode (stream, options);
+ return result ? stream.DetachAsData () : null;
+ }
+
+ public bool Encode (Stream dst, SKPngEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ using var wrapped = new SKManagedWStream (dst);
+ return Encode (wrapped, options);
+ }
+
+ public bool Encode (SKWStream dst, SKPngEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ return SkiaApi.sk_pngencoder_encode (dst.Handle, Handle, &options);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Encode(SKWStream, SKPngEncoderOptions) instead.")]
+ public static bool Encode (SKWStream dst, SKPixmap src, SKPngEncoderOptions options)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return src.Encode (dst, options);
+ }
+
+ // ExtractSubset
+
+ public SKPixmap ExtractSubset (SKRectI subset)
+ {
+ var result = new SKPixmap ();
+ if (!ExtractSubset (result, subset)) {
+ result.Dispose ();
+ result = null;
+ }
+ return result;
+ }
+
+ public bool ExtractSubset (SKPixmap result, SKRectI subset)
+ {
+ if (result == null)
+ throw new ArgumentNullException (nameof (result));
+
+ return SkiaApi.sk_pixmap_extract_subset (Handle, result.Handle, &subset);
+ }
+
+ // Erase
+
+ public bool Erase (SKColor color)
+ {
+ return Erase (color, Rect);
+ }
+
+ public bool Erase (SKColor color, SKRectI subset)
+ {
+ return SkiaApi.sk_pixmap_erase_color (Handle, (uint)color, &subset);
+ }
+
+ public bool Erase (SKColorF color) =>
+ Erase (color, Rect);
+
+ public bool Erase (SKColorF color, SKRectI subset) =>
+ SkiaApi.sk_pixmap_erase_color4f (Handle, &color, &subset);
+
+ // With*
+
+ public SKPixmap WithColorType (SKColorType newColorType)
+ {
+ return new SKPixmap (Info.WithColorType (newColorType), GetPixels (), RowBytes);
+ }
+
+ public SKPixmap WithColorSpace (SKColorSpace newColorSpace)
+ {
+ return new SKPixmap (Info.WithColorSpace (newColorSpace), GetPixels (), RowBytes);
+ }
+
+ public SKPixmap WithAlphaType (SKAlphaType newAlphaType)
+ {
+ return new SKPixmap (Info.WithAlphaType (newAlphaType), GetPixels (), RowBytes);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKRegion : SKObject
+ {
+ [Preserve]
+ internal SKRegion (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKRegion ()
+ : this (SkiaApi.sk_region_new (), true)
+ {
+ }
+
+ public SKRegion (SKRegion region)
+ : this ()
+ {
+ SetRegion (region);
+ }
+
+ public SKRegion (SKRectI rect)
+ : this ()
+ {
+ SetRect (rect);
+ }
+
+ public SKRegion (SKPath path)
+ : this ()
+ {
+ SetPath (path);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_region_delete (Handle);
+
+ // properties
+
+ public bool IsEmpty =>
+ SkiaApi.sk_region_is_empty (Handle);
+
+ public bool IsRect =>
+ SkiaApi.sk_region_is_rect (Handle);
+
+ public bool IsComplex =>
+ SkiaApi.sk_region_is_complex (Handle);
+
+ public SKRectI Bounds {
+ get {
+ SKRectI rect;
+ SkiaApi.sk_region_get_bounds (Handle, &rect);
+ return rect;
+ }
+ }
+
+ // GetBoundaryPath
+
+ public SKPath GetBoundaryPath ()
+ {
+ var path = new SKPath ();
+ if (!SkiaApi.sk_region_get_boundary_path (Handle, path.Handle)) {
+ path.Dispose ();
+ path = null;
+ }
+ return path;
+ }
+
+ // Contains
+
+ public bool Contains (SKPath path)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+
+ using var pathRegion = new SKRegion (path);
+ return Contains (pathRegion);
+ }
+
+ public bool Contains (SKRegion src)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return SkiaApi.sk_region_contains (Handle, src.Handle);
+ }
+
+ public bool Contains (SKPointI xy) =>
+ SkiaApi.sk_region_contains_point (Handle, xy.X, xy.Y);
+
+ public bool Contains (int x, int y) =>
+ SkiaApi.sk_region_contains_point (Handle, x, y);
+
+ public bool Contains (SKRectI rect) =>
+ SkiaApi.sk_region_contains_rect (Handle, &rect);
+
+ // QuickContains
+
+ public bool QuickContains (SKRectI rect) =>
+ SkiaApi.sk_region_quick_contains (Handle, &rect);
+
+ // QuickReject
+
+ public bool QuickReject (SKRectI rect) =>
+ SkiaApi.sk_region_quick_reject_rect (Handle, &rect);
+
+ public bool QuickReject (SKRegion region)
+ {
+ if (region == null)
+ throw new ArgumentNullException (nameof (region));
+
+ return SkiaApi.sk_region_quick_reject (Handle, region.Handle);
+ }
+
+ public bool QuickReject (SKPath path)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+
+ using var pathRegion = new SKRegion (path);
+ return QuickReject (pathRegion);
+ }
+
+ // Intersects
+
+ public bool Intersects (SKPath path)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+
+ using var pathRegion = new SKRegion (path);
+ return Intersects (pathRegion);
+ }
+
+ public bool Intersects (SKRegion region)
+ {
+ if (region == null)
+ throw new ArgumentNullException (nameof (region));
+
+ return SkiaApi.sk_region_intersects (Handle, region.Handle);
+ }
+
+ public bool Intersects (SKRectI rect) =>
+ SkiaApi.sk_region_intersects_rect (Handle, &rect);
+
+ // Set*
+
+ public void SetEmpty () =>
+ SkiaApi.sk_region_set_empty (Handle);
+
+ public bool SetRegion (SKRegion region)
+ {
+ if (region == null)
+ throw new ArgumentNullException (nameof (region));
+
+ return SkiaApi.sk_region_set_region (Handle, region.Handle);
+ }
+
+ public bool SetRect (SKRectI rect) =>
+ SkiaApi.sk_region_set_rect (Handle, &rect);
+
+ public bool SetRects (SKRectI[] rects)
+ {
+ if (rects == null)
+ throw new ArgumentNullException (nameof (rects));
+
+ fixed (SKRectI* r = rects) {
+ return SkiaApi.sk_region_set_rects (Handle, r, rects.Length);
+ }
+ }
+
+ public bool SetPath (SKPath path, SKRegion clip)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+ if (clip == null)
+ throw new ArgumentNullException (nameof (clip));
+
+ return SkiaApi.sk_region_set_path (Handle, path.Handle, clip.Handle);
+ }
+
+ public bool SetPath (SKPath path)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+
+ using var clip = new SKRegion ();
+ var rect = SKRectI.Ceiling (path.Bounds);
+ if (!rect.IsEmpty)
+ clip.SetRect (rect);
+
+ return SkiaApi.sk_region_set_path (Handle, path.Handle, clip.Handle);
+ }
+
+ // Translate
+
+ public void Translate (int x, int y) =>
+ SkiaApi.sk_region_translate (Handle, x, y);
+
+ // Op
+
+ public bool Op (SKRectI rect, SKRegionOperation op) =>
+ SkiaApi.sk_region_op_rect (Handle, &rect, op);
+
+ public bool Op (int left, int top, int right, int bottom, SKRegionOperation op) =>
+ Op (new SKRectI (left, top, right, bottom), op);
+
+ public bool Op (SKRegion region, SKRegionOperation op) =>
+ SkiaApi.sk_region_op (Handle, region.Handle, op);
+
+ public bool Op (SKPath path, SKRegionOperation op)
+ {
+ using var pathRegion = new SKRegion (path);
+ return Op (pathRegion, op);
+ }
+
+ // Iterators
+
+ public RectIterator CreateRectIterator () =>
+ new RectIterator (this);
+
+ public ClipIterator CreateClipIterator (SKRectI clip) =>
+ new ClipIterator (this, clip);
+
+ public SpanIterator CreateSpanIterator (int y, int left, int right) =>
+ new SpanIterator (this, y, left, right);
+
+ // classes
+
+ public class RectIterator : SKObject
+ {
+ private readonly SKRegion region;
+
+ internal RectIterator (SKRegion region)
+ : base (SkiaApi.sk_region_iterator_new (region.Handle), true)
+ {
+ this.region = region;
+ }
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_region_iterator_delete (Handle);
+
+ public bool Next (out SKRectI rect)
+ {
+ if (SkiaApi.sk_region_iterator_done (Handle)) {
+ rect = SKRectI.Empty;
+ return false;
+ }
+
+ fixed (SKRectI* r = &rect) {
+ SkiaApi.sk_region_iterator_rect (Handle, r);
+ }
+
+ SkiaApi.sk_region_iterator_next (Handle);
+
+ return true;
+ }
+ }
+
+ public class ClipIterator : SKObject
+ {
+ private readonly SKRegion region;
+ private readonly SKRectI clip;
+
+ internal ClipIterator (SKRegion region, SKRectI clip)
+ : base (SkiaApi.sk_region_cliperator_new (region.Handle, &clip), true)
+ {
+ this.region = region;
+ this.clip = clip;
+ }
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_region_cliperator_delete (Handle);
+
+ public bool Next (out SKRectI rect)
+ {
+ if (SkiaApi.sk_region_cliperator_done (Handle)) {
+ rect = SKRectI.Empty;
+ return false;
+ }
+
+ fixed (SKRectI* r = &rect) {
+ SkiaApi.sk_region_iterator_rect (Handle, r);
+ }
+
+ SkiaApi.sk_region_cliperator_next (Handle);
+
+ return true;
+ }
+ }
+
+ public class SpanIterator : SKObject
+ {
+ private readonly SKRegion region;
+ private readonly int y;
+ private readonly int left;
+ private readonly int right;
+
+ internal SpanIterator (SKRegion region, int y, int left, int right)
+ : base (SkiaApi.sk_region_spanerator_new (region.Handle, y, left, right), true)
+ {
+ this.region = region;
+ this.y = y;
+ this.left = left;
+ this.right = right;
+ }
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_region_spanerator_delete (Handle);
+
+ public bool Next (out int left, out int right)
+ {
+ int l;
+ int r;
+ if (SkiaApi.sk_region_spanerator_next (Handle, &l, &r)) {
+ left = l;
+ right = r;
+ return true;
+ }
+
+ left = 0;
+ right = 0;
+ return false;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe partial struct SKRotationScaleMatrix
+ {
+ public static readonly SKRotationScaleMatrix Empty;
+
+ public static readonly SKRotationScaleMatrix Identity = new SKRotationScaleMatrix (1, 0, 0, 0);
+
+ public SKRotationScaleMatrix (float scos, float ssin, float tx, float ty)
+ {
+ fSCos = scos;
+ fSSin = ssin;
+ fTX = tx;
+ fTY = ty;
+ }
+
+ public readonly SKMatrix ToMatrix () =>
+ new SKMatrix (fSCos, -fSSin, fTX, fSSin, fSCos, fTY, 0, 0, 1);
+
+ public static SKRotationScaleMatrix FromDegrees (float scale, float degrees, float tx, float ty, float anchorX, float anchorY) =>
+ FromRadians (scale, degrees * SKMatrix.DegreesToRadians, tx, ty, anchorX, anchorY);
+
+ public static SKRotationScaleMatrix FromRadians (float scale, float radians, float tx, float ty, float anchorX, float anchorY)
+ {
+ var s = (float)Math.Sin (radians) * scale;
+ var c = (float)Math.Cos (radians) * scale;
+ var x = tx + -c * anchorX + s * anchorY;
+ var y = ty + -s * anchorX - c * anchorY;
+
+ return new SKRotationScaleMatrix (c, s, x, y);
+ }
+
+ public static SKRotationScaleMatrix CreateIdentity () =>
+ new SKRotationScaleMatrix (1, 0, 0, 0);
+
+ public static SKRotationScaleMatrix CreateTranslation (float x, float y) =>
+ new SKRotationScaleMatrix (1, 0, x, y);
+
+ public static SKRotationScaleMatrix CreateScale (float s) =>
+ new SKRotationScaleMatrix (s, 0, 0, 0);
+
+ public static SKRotationScaleMatrix CreateRotation (float radians, float anchorX, float anchorY) =>
+ FromRadians (1, radians, 0, 0, anchorX, anchorY);
+
+ public static SKRotationScaleMatrix CreateRotationDegrees (float degrees, float anchorX, float anchorY) =>
+ FromDegrees (1, degrees, 0, 0, anchorX, anchorY);
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKRoundRect : SKObject
+ {
+ [Preserve]
+ internal SKRoundRect (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKRoundRect ()
+ : this (SkiaApi.sk_rrect_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKRoundRect instance.");
+ }
+ SetEmpty ();
+ }
+
+ public SKRoundRect (SKRect rect)
+ : this (SkiaApi.sk_rrect_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKRoundRect instance.");
+ }
+ SetRect (rect);
+ }
+
+ public SKRoundRect (SKRect rect, float radius)
+ : this (rect, radius, radius)
+ {
+ }
+
+ public SKRoundRect (SKRect rect, float xRadius, float yRadius)
+ : this (SkiaApi.sk_rrect_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKRoundRect instance.");
+ }
+ SetRect (rect, xRadius, yRadius);
+ }
+
+ public SKRoundRect (SKRoundRect rrect)
+ : this (SkiaApi.sk_rrect_new_copy (rrect.Handle), true)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_rrect_delete (Handle);
+
+ public SKRect Rect {
+ get {
+ SKRect rect;
+ SkiaApi.sk_rrect_get_rect (Handle, &rect);
+ return rect;
+ }
+ }
+
+ public SKPoint[] Radii => new[] {
+ GetRadii(SKRoundRectCorner.UpperLeft),
+ GetRadii(SKRoundRectCorner.UpperRight),
+ GetRadii(SKRoundRectCorner.LowerRight),
+ GetRadii(SKRoundRectCorner.LowerLeft),
+ };
+
+ public SKRoundRectType Type => SkiaApi.sk_rrect_get_type (Handle);
+
+ public float Width => SkiaApi.sk_rrect_get_width (Handle);
+
+ public float Height => SkiaApi.sk_rrect_get_height (Handle);
+
+ public bool IsValid => SkiaApi.sk_rrect_is_valid (Handle);
+
+ public bool AllCornersCircular => CheckAllCornersCircular (Utils.NearlyZero);
+
+ public bool CheckAllCornersCircular (float tolerance)
+ {
+ var ul = GetRadii (SKRoundRectCorner.UpperLeft);
+ var ur = GetRadii (SKRoundRectCorner.UpperRight);
+ var lr = GetRadii (SKRoundRectCorner.LowerRight);
+ var ll = GetRadii (SKRoundRectCorner.LowerLeft);
+
+ return
+ Utils.NearlyEqual (ul.X, ul.Y, tolerance) &&
+ Utils.NearlyEqual (ur.X, ur.Y, tolerance) &&
+ Utils.NearlyEqual (lr.X, lr.Y, tolerance) &&
+ Utils.NearlyEqual (ll.X, ll.Y, tolerance);
+ }
+
+ public void SetEmpty ()
+ {
+ SkiaApi.sk_rrect_set_empty (Handle);
+ }
+
+ public void SetRect (SKRect rect)
+ {
+ SkiaApi.sk_rrect_set_rect (Handle, &rect);
+ }
+
+ public void SetRect (SKRect rect, float xRadius, float yRadius)
+ {
+ SkiaApi.sk_rrect_set_rect_xy (Handle, &rect, xRadius, yRadius);
+ }
+
+ public void SetOval (SKRect rect)
+ {
+ SkiaApi.sk_rrect_set_oval (Handle, &rect);
+ }
+
+ public void SetNinePatch (SKRect rect, float leftRadius, float topRadius, float rightRadius, float bottomRadius)
+ {
+ SkiaApi.sk_rrect_set_nine_patch (Handle, &rect, leftRadius, topRadius, rightRadius, bottomRadius);
+ }
+
+ public void SetRectRadii (SKRect rect, SKPoint[] radii)
+ {
+ if (radii == null)
+ throw new ArgumentNullException (nameof (radii));
+ if (radii.Length != 4)
+ throw new ArgumentException ("Radii must have a length of 4.", nameof (radii));
+
+ fixed (SKPoint* r = radii) {
+ SkiaApi.sk_rrect_set_rect_radii (Handle, &rect, r);
+ }
+ }
+
+ public bool Contains (SKRect rect)
+ {
+ return SkiaApi.sk_rrect_contains (Handle, &rect);
+ }
+
+ public SKPoint GetRadii (SKRoundRectCorner corner)
+ {
+ SKPoint radii;
+ SkiaApi.sk_rrect_get_radii (Handle, corner, &radii);
+ return radii;
+ }
+
+ public void Deflate (SKSize size)
+ {
+ Deflate (size.Width, size.Height);
+ }
+
+ public void Deflate (float dx, float dy)
+ {
+ SkiaApi.sk_rrect_inset (Handle, dx, dy);
+ }
+
+ public void Inflate (SKSize size)
+ {
+ Inflate (size.Width, size.Height);
+ }
+
+ public void Inflate (float dx, float dy)
+ {
+ SkiaApi.sk_rrect_outset (Handle, dx, dy);
+ }
+
+ public void Offset (SKPoint pos)
+ {
+ Offset (pos.X, pos.Y);
+ }
+
+ public void Offset (float dx, float dy)
+ {
+ SkiaApi.sk_rrect_offset (Handle, dx, dy);
+ }
+
+ public bool TryTransform (SKMatrix matrix, out SKRoundRect transformed)
+ {
+ var destHandle = SkiaApi.sk_rrect_new ();
+ if (SkiaApi.sk_rrect_transform (Handle, &matrix, destHandle)) {
+ transformed = new SKRoundRect (destHandle, true);
+ return true;
+ }
+ SkiaApi.sk_rrect_delete (destHandle);
+ transformed = null;
+ return false;
+ }
+
+ public SKRoundRect Transform (SKMatrix matrix)
+ {
+ if (TryTransform (matrix, out var transformed)) {
+ return transformed;
+ }
+ return null;
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ public unsafe class SKRunBuffer
+ {
+ internal readonly SKRunBufferInternal internalBuffer;
+
+ internal SKRunBuffer (SKRunBufferInternal buffer, int size, int textSize)
+ {
+ internalBuffer = buffer;
+ Size = size;
+ TextSize = textSize;
+ }
+
+ public int Size { get; }
+
+ public int TextSize { get; }
+
+ public Span<ushort> GetGlyphSpan () =>
+ new Span<ushort> (internalBuffer.glyphs, internalBuffer.glyphs == null ? 0 : Size);
+
+ public Span<byte> GetTextSpan () =>
+ new Span<byte> (internalBuffer.utf8text, internalBuffer.utf8text == null ? 0 : TextSize);
+
+ public Span<uint> GetClusterSpan () =>
+ new Span<uint> (internalBuffer.clusters, internalBuffer.clusters == null ? 0 : Size);
+
+ public void SetGlyphs (ReadOnlySpan<ushort> glyphs) =>
+ glyphs.CopyTo (GetGlyphSpan ());
+
+ public void SetText (ReadOnlySpan<byte> text) =>
+ text.CopyTo (GetTextSpan ());
+
+ public void SetClusters (ReadOnlySpan<uint> clusters) =>
+ clusters.CopyTo (GetClusterSpan ());
+ }
+
+ public sealed unsafe class SKHorizontalRunBuffer : SKRunBuffer
+ {
+ internal SKHorizontalRunBuffer (SKRunBufferInternal buffer, int count, int textSize)
+ : base (buffer, count, textSize)
+ {
+ }
+
+ public Span<float> GetPositionSpan () =>
+ new Span<float> (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size);
+
+ public void SetPositions (ReadOnlySpan<float> positions) =>
+ positions.CopyTo (GetPositionSpan ());
+ }
+
+ public sealed unsafe class SKPositionedRunBuffer : SKRunBuffer
+ {
+ internal SKPositionedRunBuffer (SKRunBufferInternal buffer, int count, int textSize)
+ : base (buffer, count, textSize)
+ {
+ }
+
+ public Span<SKPoint> GetPositionSpan () =>
+ new Span<SKPoint> (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size);
+
+ public void SetPositions (ReadOnlySpan<SKPoint> positions) =>
+ positions.CopyTo (GetPositionSpan ());
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.IO;
+
+namespace SkiaSharp
+{
+ public unsafe class SKSvgCanvas
+ {
+ private SKSvgCanvas ()
+ {
+ }
+
+ // Create
+
+ public static SKCanvas Create (SKRect bounds, Stream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ var managed = new SKManagedWStream (stream);
+ return SKObject.Owned (Create (bounds, managed), managed);
+ }
+
+ public static SKCanvas Create (SKRect bounds, SKWStream stream)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ // TODO: there seems to be a memory issue with things getting destroyed in the incorrect order
+ //return SKObject.Referenced (SKObject.GetObject<SKCanvas> (SkiaApi.sk_svgcanvas_create_with_stream (&bounds, stream.Handle)), stream);
+
+ var writer = new SKXmlStreamWriter (stream);
+ return SKObject.Owned (SKObject.GetObject<SKCanvas> (SkiaApi.sk_svgcanvas_create_with_writer (&bounds, writer.Handle)), writer);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(SKRect, Stream) instead.")]
+ public static SKCanvas Create (SKRect bounds, SKXmlWriter writer)
+ {
+ if (writer == null)
+ throw new ArgumentNullException (nameof (writer));
+
+ return SKObject.Referenced (SKObject.GetObject<SKCanvas> (SkiaApi.sk_svgcanvas_create_with_writer (&bounds, writer.Handle)), writer);
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKShader : SKObject, ISKReferenceCounted
+ {
+ [Preserve]
+ internal SKShader (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ // WithColorFilter
+
+ public SKShader WithColorFilter (SKColorFilter filter)
+ {
+ if (filter == null)
+ throw new ArgumentNullException (nameof (filter));
+
+ return GetObject<SKShader> (SkiaApi.sk_shader_with_color_filter (Handle, filter.Handle));
+ }
+
+ // WithLocalMatrix
+
+ public SKShader WithLocalMatrix (SKMatrix localMatrix) =>
+ GetObject<SKShader> (SkiaApi.sk_shader_with_local_matrix (Handle, &localMatrix));
+
+ // CreateEmpty
+
+ public static SKShader CreateEmpty () =>
+ GetObject<SKShader> (SkiaApi.sk_shader_new_empty ());
+
+ // CreateColor
+
+ public static SKShader CreateColor (SKColor color) =>
+ GetObject<SKShader> (SkiaApi.sk_shader_new_color ((uint)color));
+
+ public static SKShader CreateColor (SKColorF color, SKColorSpace colorspace)
+ {
+ if (colorspace == null)
+ throw new ArgumentNullException (nameof (colorspace));
+
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_color4f (&color, colorspace.Handle));
+ }
+
+ // CreateBitmap
+
+ public static SKShader CreateBitmap (SKBitmap src) =>
+ CreateBitmap (src, SKShaderTileMode.Clamp, SKShaderTileMode.Clamp);
+
+ public static SKShader CreateBitmap (SKBitmap src, SKShaderTileMode tmx, SKShaderTileMode tmy)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_bitmap (src.Handle, tmx, tmy, null));
+ }
+
+ public static SKShader CreateBitmap (SKBitmap src, SKShaderTileMode tmx, SKShaderTileMode tmy, SKMatrix localMatrix)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_bitmap (src.Handle, tmx, tmy, &localMatrix));
+ }
+
+ // CreateImage
+
+ public static SKShader CreateImage (SKImage src) =>
+ CreateImage (src, SKShaderTileMode.Clamp, SKShaderTileMode.Clamp);
+
+ public static SKShader CreateImage (SKImage src, SKShaderTileMode tmx, SKShaderTileMode tmy)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return src.ToShader (tmx, tmy);
+ }
+
+ public static SKShader CreateImage (SKImage src, SKShaderTileMode tmx, SKShaderTileMode tmy, SKMatrix localMatrix)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return src.ToShader (tmx, tmy, localMatrix);
+ }
+
+ // CreatePicture
+
+ public static SKShader CreatePicture (SKPicture src) =>
+ CreatePicture (src, SKShaderTileMode.Clamp, SKShaderTileMode.Clamp);
+
+ public static SKShader CreatePicture (SKPicture src, SKShaderTileMode tmx, SKShaderTileMode tmy)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_picture (src.Handle, tmx, tmy, null, null));
+ }
+
+ public static SKShader CreatePicture (SKPicture src, SKShaderTileMode tmx, SKShaderTileMode tmy, SKRect tile)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_picture (src.Handle, tmx, tmy, null, &tile));
+ }
+
+ public static SKShader CreatePicture (SKPicture src, SKShaderTileMode tmx, SKShaderTileMode tmy, SKMatrix localMatrix, SKRect tile)
+ {
+ if (src == null)
+ throw new ArgumentNullException (nameof (src));
+
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_picture (src.Handle, tmx, tmy, &localMatrix, &tile));
+ }
+
+ // CreateLinearGradient
+
+ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, SKShaderTileMode mode) =>
+ CreateLinearGradient (start, end, colors, null, mode);
+
+ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, float[] colorPos, SKShaderTileMode mode)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ var points = stackalloc SKPoint[] { start, end };
+ fixed (SKColor* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_linear_gradient (points, (uint*)c, cp, colors.Length, mode, null));
+ }
+ }
+
+ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ var points = stackalloc SKPoint[] { start, end };
+ fixed (SKColor* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_linear_gradient (points, (uint*)c, cp, colors.Length, mode, &localMatrix));
+ }
+ }
+
+ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) =>
+ CreateLinearGradient (start, end, colors, colorspace, null, mode);
+
+ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ var points = stackalloc SKPoint[] { start, end };
+ fixed (SKColorF* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_linear_gradient_color4f (points, c, colorspace?.Handle ?? IntPtr.Zero, cp, colors.Length, mode, null));
+ }
+ }
+
+ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ var points = stackalloc SKPoint[] { start, end };
+ fixed (SKColorF* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_linear_gradient_color4f (points, c, colorspace?.Handle ?? IntPtr.Zero, cp, colors.Length, mode, &localMatrix));
+ }
+ }
+
+ // CreateRadialGradient
+
+ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, SKShaderTileMode mode) =>
+ CreateRadialGradient (center, radius, colors, null, mode);
+
+ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColor* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_radial_gradient (¢er, radius, (uint*)c, cp, colors.Length, mode, null));
+ }
+ }
+
+ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColor* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_radial_gradient (¢er, radius, (uint*)c, cp, colors.Length, mode, &localMatrix));
+ }
+ }
+
+ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) =>
+ CreateRadialGradient (center, radius, colors, colorspace, null, mode);
+
+ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColorF* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_radial_gradient_color4f (¢er, radius, c, colorspace?.Handle ?? IntPtr.Zero, cp, colors.Length, mode, null));
+ }
+ }
+
+ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColorF* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_radial_gradient_color4f (¢er, radius, c, colorspace?.Handle ?? IntPtr.Zero, cp, colors.Length, mode, &localMatrix));
+ }
+ }
+
+ // CreateSweepGradient
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors) =>
+ CreateSweepGradient (center, colors, null, SKShaderTileMode.Clamp, 0, 360);
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos) =>
+ CreateSweepGradient (center, colors, colorPos, SKShaderTileMode.Clamp, 0, 360);
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos, SKMatrix localMatrix) =>
+ CreateSweepGradient (center, colors, colorPos, SKShaderTileMode.Clamp, 0, 360, localMatrix);
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, SKShaderTileMode tileMode, float startAngle, float endAngle) =>
+ CreateSweepGradient (center, colors, null, tileMode, startAngle, endAngle);
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColor* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_sweep_gradient (¢er, (uint*)c, cp, colors.Length, tileMode, startAngle, endAngle, null));
+ }
+ }
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle, SKMatrix localMatrix)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColor* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_sweep_gradient (¢er, (uint*)c, cp, colors.Length, tileMode, startAngle, endAngle, &localMatrix));
+ }
+ }
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace) =>
+ CreateSweepGradient (center, colors, colorspace, null, SKShaderTileMode.Clamp, 0, 360);
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos) =>
+ CreateSweepGradient (center, colors, colorspace, colorPos, SKShaderTileMode.Clamp, 0, 360);
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKMatrix localMatrix) =>
+ CreateSweepGradient (center, colors, colorspace, colorPos, SKShaderTileMode.Clamp, 0, 360, localMatrix);
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode tileMode, float startAngle, float endAngle) =>
+ CreateSweepGradient (center, colors, colorspace, null, tileMode, startAngle, endAngle);
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColorF* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_sweep_gradient_color4f (¢er, c, colorspace?.Handle ?? IntPtr.Zero, cp, colors.Length, tileMode, startAngle, endAngle, null));
+ }
+ }
+
+ public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle, SKMatrix localMatrix)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColorF* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_sweep_gradient_color4f (¢er, c, colorspace?.Handle ?? IntPtr.Zero, cp, colors.Length, tileMode, startAngle, endAngle, &localMatrix));
+ }
+ }
+
+ // CreateTwoPointConicalGradient
+
+ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColor[] colors, SKShaderTileMode mode) =>
+ CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors, null, mode);
+
+ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColor* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_two_point_conical_gradient (&start, startRadius, &end, endRadius, (uint*)c, cp, colors.Length, mode, null));
+ }
+ }
+
+ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColor* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_two_point_conical_gradient (&start, startRadius, &end, endRadius, (uint*)c, cp, colors.Length, mode, &localMatrix));
+ }
+ }
+
+ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) =>
+ CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors, colorspace, null, mode);
+
+ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColorF* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_two_point_conical_gradient_color4f (&start, startRadius, &end, endRadius, c, colorspace?.Handle ?? IntPtr.Zero, cp, colors.Length, mode, null));
+ }
+ }
+
+ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix)
+ {
+ if (colors == null)
+ throw new ArgumentNullException (nameof (colors));
+ if (colorPos != null && colors.Length != colorPos.Length)
+ throw new ArgumentException ("The number of colors must match the number of color positions.");
+
+ fixed (SKColorF* c = colors)
+ fixed (float* cp = colorPos) {
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_two_point_conical_gradient_color4f (&start, startRadius, &end, endRadius, c, colorspace?.Handle ?? IntPtr.Zero, cp, colors.Length, mode, &localMatrix));
+ }
+ }
+
+ // CreatePerlinNoiseFractalNoise
+
+ public static SKShader CreatePerlinNoiseFractalNoise (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed) =>
+ GetObject<SKShader> (SkiaApi.sk_shader_new_perlin_noise_fractal_noise (baseFrequencyX, baseFrequencyY, numOctaves, seed, null));
+
+ public static SKShader CreatePerlinNoiseFractalNoise (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, SKPointI tileSize) =>
+ CreatePerlinNoiseFractalNoise (baseFrequencyX, baseFrequencyY, numOctaves, seed, (SKSizeI)tileSize);
+
+ public static SKShader CreatePerlinNoiseFractalNoise (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, SKSizeI tileSize) =>
+ GetObject<SKShader> (SkiaApi.sk_shader_new_perlin_noise_fractal_noise (baseFrequencyX, baseFrequencyY, numOctaves, seed, &tileSize));
+
+ // CreatePerlinNoiseImprovedNoise
+
+ public static SKShader CreatePerlinNoiseImprovedNoise (float baseFrequencyX, float baseFrequencyY, int numOctaves, float z) =>
+ GetObject<SKShader> (SkiaApi.sk_shader_new_perlin_noise_improved_noise (baseFrequencyX, baseFrequencyY, numOctaves, z));
+
+ // CreatePerlinNoiseTurbulence
+
+ public static SKShader CreatePerlinNoiseTurbulence (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed) =>
+ GetObject<SKShader> (SkiaApi.sk_shader_new_perlin_noise_turbulence (baseFrequencyX, baseFrequencyY, numOctaves, seed, null));
+
+ public static SKShader CreatePerlinNoiseTurbulence (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, SKPointI tileSize) =>
+ CreatePerlinNoiseTurbulence (baseFrequencyX, baseFrequencyY, numOctaves, seed, (SKSizeI)tileSize);
+
+ public static SKShader CreatePerlinNoiseTurbulence (float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, SKSizeI tileSize) =>
+ GetObject<SKShader> (SkiaApi.sk_shader_new_perlin_noise_turbulence (baseFrequencyX, baseFrequencyY, numOctaves, seed, &tileSize));
+
+ // CreateCompose
+
+ public static SKShader CreateCompose (SKShader shaderA, SKShader shaderB) =>
+ CreateCompose (shaderA, shaderB, SKBlendMode.SrcOver);
+
+ public static SKShader CreateCompose (SKShader shaderA, SKShader shaderB, SKBlendMode mode)
+ {
+ if (shaderA == null)
+ throw new ArgumentNullException (nameof (shaderA));
+ if (shaderB == null)
+ throw new ArgumentNullException (nameof (shaderB));
+
+ return GetObject<SKShader> (SkiaApi.sk_shader_new_compose (shaderA.Handle, shaderB.Handle, mode));
+ }
+
+ // CreateColorFilter
+
+ public static SKShader CreateColorFilter (SKShader shader, SKColorFilter filter)
+ {
+ if (shader == null)
+ throw new ArgumentNullException (nameof (shader));
+ if (filter == null)
+ throw new ArgumentNullException (nameof (filter));
+
+ return shader.WithColorFilter (filter);
+ }
+
+ // CreateLocalMatrix
+
+ public static SKShader CreateLocalMatrix (SKShader shader, SKMatrix localMatrix)
+ {
+ if (shader == null)
+ throw new ArgumentNullException (nameof (shader));
+
+ return shader.WithLocalMatrix (localMatrix);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.IO;
+
+namespace SkiaSharp
+{
+ public unsafe abstract class SKStream : SKObject
+ {
+ internal SKStream (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public bool IsAtEnd {
+ get {
+ return SkiaApi.sk_stream_is_at_end (Handle);
+ }
+ }
+
+ public SByte ReadSByte ()
+ {
+ if (ReadSByte (out var buffer))
+ return buffer;
+ return default (SByte);
+ }
+
+ public Int16 ReadInt16 ()
+ {
+ if (ReadInt16 (out var buffer))
+ return buffer;
+ return default (Int16);
+ }
+
+ public Int32 ReadInt32 ()
+ {
+ if (ReadInt32 (out var buffer))
+ return buffer;
+ return default (Int32);
+ }
+
+ public Byte ReadByte ()
+ {
+ if (ReadByte (out var buffer))
+ return buffer;
+ return default (Byte);
+ }
+
+ public UInt16 ReadUInt16 ()
+ {
+ if (ReadUInt16 (out var buffer))
+ return buffer;
+ return default (UInt16);
+ }
+
+ public UInt32 ReadUInt32 ()
+ {
+ if (ReadUInt32 (out var buffer))
+ return buffer;
+ return default (UInt32);
+ }
+
+ public bool ReadBool ()
+ {
+ if (ReadBool (out var buffer))
+ return buffer;
+ return default (bool);
+ }
+
+ public bool ReadSByte (out SByte buffer)
+ {
+ fixed (SByte* b = &buffer) {
+ return SkiaApi.sk_stream_read_s8 (Handle, b);
+ }
+ }
+
+ public bool ReadInt16 (out Int16 buffer)
+ {
+ fixed (Int16* b = &buffer) {
+ return SkiaApi.sk_stream_read_s16 (Handle, b);
+ }
+ }
+
+ public bool ReadInt32 (out Int32 buffer)
+ {
+ fixed (Int32* b = &buffer) {
+ return SkiaApi.sk_stream_read_s32 (Handle, b);
+ }
+ }
+
+ public bool ReadByte (out Byte buffer)
+ {
+ fixed (Byte* b = &buffer) {
+ return SkiaApi.sk_stream_read_u8 (Handle, b);
+ }
+ }
+
+ public bool ReadUInt16 (out UInt16 buffer)
+ {
+ fixed (UInt16* b = &buffer) {
+ return SkiaApi.sk_stream_read_u16 (Handle, b);
+ }
+ }
+
+ public bool ReadUInt32 (out UInt32 buffer)
+ {
+ fixed (UInt32* b = &buffer) {
+ return SkiaApi.sk_stream_read_u32 (Handle, b);
+ }
+ }
+
+ public bool ReadBool (out Boolean buffer)
+ {
+ byte b;
+ var result = SkiaApi.sk_stream_read_bool (Handle, &b);
+ buffer = b > 0;
+ return result;
+ }
+
+ public int Read (byte[] buffer, int size)
+ {
+ fixed (byte* b = buffer) {
+ return Read ((IntPtr)b, size);
+ }
+ }
+
+ public int Read (IntPtr buffer, int size)
+ {
+ return (int)SkiaApi.sk_stream_read (Handle, (void*)buffer, (IntPtr)size);
+ }
+
+ public int Peek (IntPtr buffer, int size)
+ {
+ return (int)SkiaApi.sk_stream_peek (Handle, (void*)buffer, (IntPtr)size);
+ }
+
+ public int Skip (int size)
+ {
+ return (int)SkiaApi.sk_stream_skip (Handle, (IntPtr)size);
+ }
+
+ public bool Rewind ()
+ {
+ return SkiaApi.sk_stream_rewind (Handle);
+ }
+
+ public bool Seek (int position)
+ {
+ return SkiaApi.sk_stream_seek (Handle, (IntPtr)position);
+ }
+
+ public bool Move (long offset) => Move ((int)offset);
+
+ public bool Move (int offset)
+ {
+ return SkiaApi.sk_stream_move (Handle, offset);
+ }
+
+ public IntPtr GetMemoryBase ()
+ {
+ return (IntPtr)SkiaApi.sk_stream_get_memory_base (Handle);
+ }
+
+ internal SKStream Fork () =>
+ GetObject<SKStream, SKStreamImplementation> (SkiaApi.sk_stream_fork (Handle));
+
+ internal SKStream Duplicate () =>
+ GetObject<SKStream, SKStreamImplementation> (SkiaApi.sk_stream_duplicate (Handle));
+
+ public bool HasPosition {
+ get {
+ return SkiaApi.sk_stream_has_position (Handle);
+ }
+ }
+
+ public int Position {
+ get {
+ return (int)SkiaApi.sk_stream_get_position (Handle);
+ }
+ set {
+ Seek (value);
+ }
+ }
+
+ public bool HasLength {
+ get {
+ return SkiaApi.sk_stream_has_length (Handle);
+ }
+ }
+
+ public int Length {
+ get {
+ return (int)SkiaApi.sk_stream_get_length (Handle);
+ }
+ }
+ }
+
+ internal class SKStreamImplementation : SKStream
+ {
+ [Preserve]
+ internal SKStreamImplementation (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_stream_destroy (Handle);
+ }
+
+ public abstract class SKStreamRewindable : SKStream
+ {
+ internal SKStreamRewindable (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+ }
+
+ public abstract class SKStreamSeekable : SKStreamRewindable
+ {
+ internal SKStreamSeekable (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+ }
+
+ public abstract class SKStreamAsset : SKStreamSeekable
+ {
+ internal SKStreamAsset (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+ }
+
+ internal class SKStreamAssetImplementation : SKStreamAsset
+ {
+ [Preserve]
+ internal SKStreamAssetImplementation (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_stream_asset_destroy (Handle);
+ }
+
+ public abstract class SKStreamMemory : SKStreamAsset
+ {
+ internal SKStreamMemory (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+ }
+
+ public unsafe class SKFileStream : SKStreamAsset
+ {
+ [Preserve]
+ internal SKFileStream (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKFileStream (string path)
+ : base (CreateNew (path), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKFileStream instance.");
+ }
+ }
+
+ private static IntPtr CreateNew (string path)
+ {
+ var bytes = StringUtilities.GetEncodedText (path, SKTextEncoding.Utf8);
+ fixed (byte* p = bytes) {
+ return SkiaApi.sk_filestream_new (p);
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_filestream_destroy (Handle);
+
+ public bool IsValid => SkiaApi.sk_filestream_is_valid (Handle);
+
+ public static bool IsPathSupported (string path) => true;
+
+ public static SKStreamAsset OpenStream (string path)
+ {
+ var stream = new SKFileStream (path);
+ if (!stream.IsValid) {
+ stream.Dispose ();
+ stream = null;
+ }
+ return stream;
+ }
+ }
+
+ public unsafe class SKMemoryStream : SKStreamMemory
+ {
+ [Preserve]
+ internal SKMemoryStream (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKMemoryStream ()
+ : this (SkiaApi.sk_memorystream_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKMemoryStream instance.");
+ }
+ }
+
+ public SKMemoryStream (ulong length)
+ : this(SkiaApi.sk_memorystream_new_with_length ((IntPtr)length), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKMemoryStream instance.");
+ }
+ }
+
+ internal SKMemoryStream (IntPtr data, IntPtr length, bool copyData = false)
+ : this(SkiaApi.sk_memorystream_new_with_data ((void*)data, length, copyData), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKMemoryStream instance.");
+ }
+ }
+
+ public SKMemoryStream (SKData data)
+ : this(SkiaApi.sk_memorystream_new_with_skdata (data.Handle), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKMemoryStream instance.");
+ }
+ }
+
+ public SKMemoryStream (byte[] data)
+ : this ()
+ {
+ SetMemory (data);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_memorystream_destroy (Handle);
+
+ internal void SetMemory (IntPtr data, IntPtr length, bool copyData = false)
+ {
+ SkiaApi.sk_memorystream_set_memory (Handle, (void*)data, length, copyData);
+ }
+
+ internal void SetMemory (byte[] data, IntPtr length, bool copyData = false)
+ {
+ fixed (byte* d = data) {
+ SkiaApi.sk_memorystream_set_memory (Handle, d, length, copyData);
+ }
+ }
+
+ public void SetMemory (byte[] data)
+ {
+ SetMemory (data, (IntPtr)data.Length, true);
+ }
+ }
+
+ public unsafe abstract class SKWStream : SKObject
+ {
+ internal SKWStream (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public virtual int BytesWritten {
+ get {
+ return (int)SkiaApi.sk_wstream_bytes_written (Handle);
+ }
+ }
+
+ public virtual bool Write (byte[] buffer, int size)
+ {
+ fixed (byte* b = buffer) {
+ return SkiaApi.sk_wstream_write (Handle, (void*)b, (IntPtr)size);
+ }
+ }
+
+ public bool NewLine ()
+ {
+ return SkiaApi.sk_wstream_newline (Handle);
+ }
+
+ public virtual void Flush ()
+ {
+ SkiaApi.sk_wstream_flush (Handle);
+ }
+
+ public bool Write8 (Byte value)
+ {
+ return SkiaApi.sk_wstream_write_8 (Handle, value);
+ }
+
+ public bool Write16 (UInt16 value)
+ {
+ return SkiaApi.sk_wstream_write_16 (Handle, value);
+ }
+
+ public bool Write32 (UInt32 value)
+ {
+ return SkiaApi.sk_wstream_write_32 (Handle, value);
+ }
+
+ public bool WriteText (string value)
+ {
+ return SkiaApi.sk_wstream_write_text (Handle, value);
+ }
+
+ public bool WriteDecimalAsTest (Int32 value)
+ {
+ return SkiaApi.sk_wstream_write_dec_as_text (Handle, value);
+ }
+
+ public bool WriteBigDecimalAsText (Int64 value, int digits)
+ {
+ return SkiaApi.sk_wstream_write_bigdec_as_text (Handle, value, digits);
+ }
+
+ public bool WriteHexAsText (UInt32 value, int digits)
+ {
+ return SkiaApi.sk_wstream_write_hex_as_text (Handle, value, digits);
+ }
+
+ public bool WriteScalarAsText (float value)
+ {
+ return SkiaApi.sk_wstream_write_scalar_as_text (Handle, value);
+ }
+
+ public bool WriteBool (bool value)
+ {
+ return SkiaApi.sk_wstream_write_bool (Handle, value);
+ }
+
+ public bool WriteScalar (float value)
+ {
+ return SkiaApi.sk_wstream_write_scalar (Handle, value);
+ }
+
+ public bool WritePackedUInt32 (UInt32 value)
+ {
+ return SkiaApi.sk_wstream_write_packed_uint (Handle, (IntPtr)value);
+ }
+
+ public bool WriteStream (SKStream input, int length)
+ {
+ if (input == null) {
+ throw new ArgumentNullException (nameof(input));
+ }
+
+ return SkiaApi.sk_wstream_write_stream (Handle, input.Handle, (IntPtr)length);
+ }
+
+ public static int GetSizeOfPackedUInt32 (UInt32 value)
+ {
+ return SkiaApi.sk_wstream_get_size_of_packed_uint ((IntPtr) value);
+ }
+ }
+
+ public unsafe class SKFileWStream : SKWStream
+ {
+ [Preserve]
+ internal SKFileWStream (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKFileWStream (string path)
+ : base (CreateNew (path), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKFileWStream instance.");
+ }
+ }
+
+ private static IntPtr CreateNew (string path)
+ {
+ var bytes = StringUtilities.GetEncodedText (path, SKTextEncoding.Utf8);
+ fixed (byte* p = bytes) {
+ return SkiaApi.sk_filewstream_new (p);
+ }
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_filewstream_destroy (Handle);
+
+ public bool IsValid => SkiaApi.sk_filewstream_is_valid (Handle);
+
+ public static bool IsPathSupported (string path) => true;
+
+ public static SKWStream OpenStream (string path)
+ {
+ var stream = new SKFileWStream (path);
+ if (!stream.IsValid) {
+ stream.Dispose ();
+ stream = null;
+ }
+ return stream;
+ }
+ }
+
+ public unsafe class SKDynamicMemoryWStream : SKWStream
+ {
+ [Preserve]
+ internal SKDynamicMemoryWStream (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKDynamicMemoryWStream ()
+ : base (SkiaApi.sk_dynamicmemorywstream_new (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKDynamicMemoryWStream instance.");
+ }
+ }
+
+ public SKData CopyToData ()
+ {
+ var data = SKData.Create (BytesWritten);
+ CopyTo (data.Data);
+ return data;
+ }
+
+ public SKStreamAsset DetachAsStream ()
+ {
+ return GetObject<SKStreamAsset, SKStreamAssetImplementation> (SkiaApi.sk_dynamicmemorywstream_detach_as_stream (Handle));
+ }
+
+ public SKData DetachAsData ()
+ {
+ return GetObject<SKData> (SkiaApi.sk_dynamicmemorywstream_detach_as_data (Handle));
+ }
+
+ public void CopyTo (IntPtr data)
+ {
+ SkiaApi.sk_dynamicmemorywstream_copy_to (Handle, (void*)data);
+ }
+
+ public void CopyTo (Span<byte> data)
+ {
+ var size = BytesWritten;
+ if (data.Length < size)
+ throw new Exception ($"Not enough space to copy. Expected at least {size}, but received {data.Length}.");
+
+ fixed (void* d = data) {
+ SkiaApi.sk_dynamicmemorywstream_copy_to (Handle, d);
+ }
+ }
+
+ public bool CopyTo (SKWStream dst)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+ return SkiaApi.sk_dynamicmemorywstream_write_to_stream (Handle, dst.Handle);
+ }
+
+ public bool CopyTo (Stream dst)
+ {
+ if (dst == null)
+ throw new ArgumentNullException (nameof (dst));
+
+ using var wrapped = new SKManagedWStream (dst);
+ return CopyTo (wrapped);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_dynamicmemorywstream_destroy (Handle);
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ internal unsafe class SKString : SKObject
+ {
+ [Preserve]
+ internal SKString (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ public SKString ()
+ : base (SkiaApi.sk_string_new_empty (), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to create a new SKString instance.");
+ }
+ }
+
+ public SKString (byte [] src, long length)
+ : base (CreateCopy (src, length), true)
+ {
+ if (Handle == IntPtr.Zero) {
+ throw new InvalidOperationException ("Unable to copy the SKString instance.");
+ }
+ }
+
+ private static IntPtr CreateCopy (byte [] src, long length)
+ {
+ fixed (byte* s = src) {
+ return SkiaApi.sk_string_new_with_copy (s, (IntPtr)length);
+ }
+ }
+
+ public SKString (byte [] src)
+ : this (src, src.Length)
+ {
+ }
+
+ public SKString (string str)
+ : this (StringUtilities.GetEncodedText (str, SKTextEncoding.Utf8))
+ {
+ }
+
+ public override string ToString ()
+ {
+ var cstr = SkiaApi.sk_string_get_c_str (Handle);
+ var clen = SkiaApi.sk_string_get_size (Handle);
+ return StringUtilities.GetString ((IntPtr)cstr, (int)clen, SKTextEncoding.Utf8);
+ }
+
+ public static explicit operator string (SKString skString)
+ {
+ return skString.ToString ();
+ }
+
+ internal static SKString Create (string str)
+ {
+ if (str == null) {
+ return null;
+ }
+ return new SKString (str);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_string_destructor (Handle);
+ }
+}
+
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public unsafe class SKSurface : SKObject, ISKReferenceCounted
+ {
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(SKImageInfo) instead.")]
+ public static SKSurface Create (int width, int height, SKColorType colorType, SKAlphaType alphaType) => Create (new SKImageInfo (width, height, colorType, alphaType));
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(SKImageInfo, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (int width, int height, SKColorType colorType, SKAlphaType alphaType, SKSurfaceProps props) => Create (new SKImageInfo (width, height, colorType, alphaType), props);
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(SKImageInfo, IntPtr, int) instead.")]
+ public static SKSurface Create (int width, int height, SKColorType colorType, SKAlphaType alphaType, IntPtr pixels, int rowBytes) => Create (new SKImageInfo (width, height, colorType, alphaType), pixels, rowBytes);
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(SKImageInfo, IntPtr, int, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (int width, int height, SKColorType colorType, SKAlphaType alphaType, IntPtr pixels, int rowBytes, SKSurfaceProps props) => Create (new SKImageInfo (width, height, colorType, alphaType), pixels, rowBytes, props);
+
+ [Preserve]
+ internal SKSurface (IntPtr h, bool owns)
+ : base (h, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ // RASTER surface
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(SKImageInfo, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (SKImageInfo info, SKSurfaceProps props) =>
+ Create (info, 0, new SKSurfaceProperties (props));
+
+ public static SKSurface Create (SKImageInfo info) =>
+ Create (info, 0, null);
+
+ public static SKSurface Create (SKImageInfo info, int rowBytes) =>
+ Create (info, rowBytes, null);
+
+ public static SKSurface Create (SKImageInfo info, SKSurfaceProperties props) =>
+ Create (info, 0, props);
+
+ public static SKSurface Create (SKImageInfo info, int rowBytes, SKSurfaceProperties props)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ return GetObject<SKSurface> (SkiaApi.sk_surface_new_raster (&cinfo, (IntPtr)rowBytes, props?.Handle ?? IntPtr.Zero));
+ }
+
+ // convenience RASTER DIRECT to use a SKPixmap instead of SKImageInfo and IntPtr
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(SKPixmap, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (SKPixmap pixmap, SKSurfaceProps props) =>
+ Create (pixmap, new SKSurfaceProperties (props));
+
+ public static SKSurface Create (SKPixmap pixmap) =>
+ Create (pixmap, null);
+
+ public static SKSurface Create (SKPixmap pixmap, SKSurfaceProperties props)
+ {
+ if (pixmap == null) {
+ throw new ArgumentNullException (nameof (pixmap));
+ }
+ return Create (pixmap.Info, pixmap.GetPixels (), pixmap.RowBytes, null, null, props);
+ }
+
+ // RASTER DIRECT surface
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(SKImageInfo, IntPtr, rowBytes, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (SKImageInfo info, IntPtr pixels, int rowBytes, SKSurfaceProps props) =>
+ Create (info, pixels, rowBytes, null, null, new SKSurfaceProperties (props));
+
+ public static SKSurface Create (SKImageInfo info, IntPtr pixels) =>
+ Create (info, pixels, info.RowBytes, null, null, null);
+
+ public static SKSurface Create (SKImageInfo info, IntPtr pixels, int rowBytes) =>
+ Create (info, pixels, rowBytes, null, null, null);
+
+ public static SKSurface Create (SKImageInfo info, IntPtr pixels, int rowBytes, SKSurfaceReleaseDelegate releaseProc, object context) =>
+ Create (info, pixels, rowBytes, releaseProc, context, null);
+
+ public static SKSurface Create (SKImageInfo info, IntPtr pixels, SKSurfaceProperties props) =>
+ Create (info, pixels, info.RowBytes, null, null, props);
+
+ public static SKSurface Create (SKImageInfo info, IntPtr pixels, int rowBytes, SKSurfaceProperties props) =>
+ Create (info, pixels, rowBytes, null, null, props);
+
+ public static SKSurface Create (SKImageInfo info, IntPtr pixels, int rowBytes, SKSurfaceReleaseDelegate releaseProc, object context, SKSurfaceProperties props)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ var del = releaseProc != null && context != null
+ ? new SKSurfaceReleaseDelegate ((addr, _) => releaseProc (addr, context))
+ : releaseProc;
+ var proxy = DelegateProxies.Create (del, DelegateProxies.SKSurfaceReleaseDelegateProxy, out _, out var ctx);
+ return GetObject<SKSurface> (SkiaApi.sk_surface_new_raster_direct (&cinfo, (void*)pixels, (IntPtr)rowBytes, proxy, (void*)ctx, props?.Handle ?? IntPtr.Zero));
+ }
+
+ // GPU BACKEND RENDER TARGET surface
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(GRContext, GRBackendRenderTarget, GRSurfaceOrigin, SKColorType) instead.")]
+ public static SKSurface Create (GRContext context, GRBackendRenderTargetDesc desc)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+
+ var renderTarget = new GRBackendRenderTarget (context.Backend, desc);
+ return Create (context, renderTarget, desc.Origin, desc.Config.ToColorType (), null, null);
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(GRContext, GRBackendRenderTarget, GRSurfaceOrigin, SKColorType, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (GRContext context, GRBackendRenderTargetDesc desc, SKSurfaceProps props)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+
+ var renderTarget = new GRBackendRenderTarget (context.Backend, desc);
+ return Create (context, renderTarget, desc.Origin, desc.Config.ToColorType (), null, new SKSurfaceProperties (props));
+ }
+
+ public static SKSurface Create (GRContext context, GRBackendRenderTarget renderTarget, SKColorType colorType) =>
+ Create (context, renderTarget, GRSurfaceOrigin.BottomLeft, colorType, null, null);
+
+ public static SKSurface Create (GRContext context, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType) =>
+ Create (context, renderTarget, origin, colorType, null, null);
+
+ public static SKSurface Create (GRContext context, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType, SKColorSpace colorspace) =>
+ Create (context, renderTarget, origin, colorType, colorspace, null);
+
+ public static SKSurface Create (GRContext context, GRBackendRenderTarget renderTarget, SKColorType colorType, SKSurfaceProperties props) =>
+ Create (context, renderTarget, GRSurfaceOrigin.BottomLeft, colorType, null, props);
+
+ public static SKSurface Create (GRContext context, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType, SKSurfaceProperties props) =>
+ Create (context, renderTarget, origin, colorType, null, props);
+
+ public static SKSurface Create (GRContext context, GRBackendRenderTarget renderTarget, GRSurfaceOrigin origin, SKColorType colorType, SKColorSpace colorspace, SKSurfaceProperties props)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+ if (renderTarget == null)
+ throw new ArgumentNullException (nameof (renderTarget));
+
+ return GetObject<SKSurface> (SkiaApi.sk_surface_new_backend_render_target (context.Handle, renderTarget.Handle, origin, colorType, colorspace?.Handle ?? IntPtr.Zero, props?.Handle ?? IntPtr.Zero));
+ }
+
+ // GPU BACKEND TEXTURE surface
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(GRContext, GRBackendTexture, GRSurfaceOrigin, int, SKColorType) instead.")]
+ public static SKSurface Create (GRContext context, GRGlBackendTextureDesc desc) =>
+ Create (context, new GRBackendTexture (desc), desc.Origin, desc.SampleCount, desc.Config.ToColorType (), null, null);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(GRContext, GRBackendTexture, GRSurfaceOrigin, int, SKColorType) instead.")]
+ public static SKSurface Create (GRContext context, GRBackendTextureDesc desc) =>
+ Create (context, new GRBackendTexture (desc), desc.Origin, desc.SampleCount, desc.Config.ToColorType (), null, null);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(GRContext, GRBackendTexture, GRSurfaceOrigin, int, SKColorType, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (GRContext context, GRGlBackendTextureDesc desc, SKSurfaceProps props) =>
+ Create (context, new GRBackendTexture (desc), desc.Origin, desc.SampleCount, desc.Config.ToColorType (), null, new SKSurfaceProperties (props));
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(GRContext, GRBackendTexture, GRSurfaceOrigin, int, SKColorType, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (GRContext context, GRBackendTextureDesc desc, SKSurfaceProps props) =>
+ Create (context, new GRBackendTexture (desc), desc.Origin, desc.SampleCount, desc.Config.ToColorType (), null, new SKSurfaceProperties (props));
+
+ public static SKSurface Create (GRContext context, GRBackendTexture texture, SKColorType colorType) =>
+ Create (context, texture, GRSurfaceOrigin.BottomLeft, 0, colorType, null, null);
+
+ public static SKSurface Create (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType) =>
+ Create (context, texture, origin, 0, colorType, null, null);
+
+ public static SKSurface Create (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, int sampleCount, SKColorType colorType) =>
+ Create (context, texture, origin, sampleCount, colorType, null, null);
+
+ public static SKSurface Create (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, int sampleCount, SKColorType colorType, SKColorSpace colorspace) =>
+ Create (context, texture, origin, sampleCount, colorType, colorspace, null);
+
+ public static SKSurface Create (GRContext context, GRBackendTexture texture, SKColorType colorType, SKSurfaceProperties props) =>
+ Create (context, texture, GRSurfaceOrigin.BottomLeft, 0, colorType, null, props);
+
+ public static SKSurface Create (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKSurfaceProperties props) =>
+ Create (context, texture, origin, 0, colorType, null, props);
+
+ public static SKSurface Create (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, int sampleCount, SKColorType colorType, SKSurfaceProperties props) =>
+ Create (context, texture, origin, sampleCount, colorType, null, props);
+
+ public static SKSurface Create (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, int sampleCount, SKColorType colorType, SKColorSpace colorspace, SKSurfaceProperties props)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+ if (texture == null)
+ throw new ArgumentNullException (nameof (texture));
+
+ return GetObject<SKSurface> (SkiaApi.sk_surface_new_backend_texture (context.Handle, texture.Handle, origin, sampleCount, colorType, colorspace?.Handle ?? IntPtr.Zero, props?.Handle ?? IntPtr.Zero));
+ }
+
+ // GPU BACKEND TEXTURE AS RENDER TARGET surface
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateAsRenderTarget(GRContext, GRBackendTexture, GRSurfaceOrigin, int, SKColorType) instead.")]
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRGlBackendTextureDesc desc) =>
+ CreateAsRenderTarget (context, new GRBackendTexture (desc), desc.Origin, desc.SampleCount, desc.Config.ToColorType (), null, null);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateAsRenderTarget(GRContext, GRBackendTexture, GRSurfaceOrigin, int, SKColorType) instead.")]
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTextureDesc desc) =>
+ CreateAsRenderTarget (context, new GRBackendTexture (desc), desc.Origin, desc.SampleCount, desc.Config.ToColorType (), null, null);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateAsRenderTarget(GRContext, GRBackendTexture, GRSurfaceOrigin, int, SKColorType, SKSurfaceProperties) instead.")]
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRGlBackendTextureDesc desc, SKSurfaceProps props) =>
+ CreateAsRenderTarget (context, new GRBackendTexture (desc), desc.Origin, desc.SampleCount, desc.Config.ToColorType (), null, new SKSurfaceProperties (props));
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CreateAsRenderTarget(GRContext, GRBackendTexture, GRSurfaceOrigin, int, SKColorType, SKSurfaceProperties) instead.")]
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTextureDesc desc, SKSurfaceProps props) =>
+ CreateAsRenderTarget (context, new GRBackendTexture (desc), desc.Origin, desc.SampleCount, desc.Config.ToColorType (), null, new SKSurfaceProperties (props));
+
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTexture texture, SKColorType colorType) =>
+ CreateAsRenderTarget (context, texture, GRSurfaceOrigin.BottomLeft, 0, colorType, null, null);
+
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType) =>
+ CreateAsRenderTarget (context, texture, origin, 0, colorType, null, null);
+
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, int sampleCount, SKColorType colorType) =>
+ CreateAsRenderTarget (context, texture, origin, sampleCount, colorType, null, null);
+
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, int sampleCount, SKColorType colorType, SKColorSpace colorspace) =>
+ CreateAsRenderTarget (context, texture, origin, sampleCount, colorType, colorspace, null);
+
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTexture texture, SKColorType colorType, SKSurfaceProperties props) =>
+ CreateAsRenderTarget (context, texture, GRSurfaceOrigin.BottomLeft, 0, colorType, null, props);
+
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, SKColorType colorType, SKSurfaceProperties props) =>
+ CreateAsRenderTarget (context, texture, origin, 0, colorType, null, props);
+
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, int sampleCount, SKColorType colorType, SKSurfaceProperties props) =>
+ CreateAsRenderTarget (context, texture, origin, sampleCount, colorType, null, props);
+
+ public static SKSurface CreateAsRenderTarget (GRContext context, GRBackendTexture texture, GRSurfaceOrigin origin, int sampleCount, SKColorType colorType, SKColorSpace colorspace, SKSurfaceProperties props)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+ if (texture == null)
+ throw new ArgumentNullException (nameof (texture));
+
+ return GetObject<SKSurface> (SkiaApi.sk_surface_new_backend_texture_as_render_target (context.Handle, texture.Handle, origin, sampleCount, colorType, colorspace?.Handle ?? IntPtr.Zero, props?.Handle ?? IntPtr.Zero));
+ }
+
+ // GPU NEW surface
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use Create(GRContext, bool, SKImageInfo, int, SKSurfaceProperties) instead.")]
+ public static SKSurface Create (GRContext context, bool budgeted, SKImageInfo info, int sampleCount, SKSurfaceProps props) =>
+ Create (context, budgeted, info, sampleCount, GRSurfaceOrigin.BottomLeft, new SKSurfaceProperties (props), false);
+
+ public static SKSurface Create (GRContext context, bool budgeted, SKImageInfo info) =>
+ Create (context, budgeted, info, 0, GRSurfaceOrigin.BottomLeft, null, false);
+
+ public static SKSurface Create (GRContext context, bool budgeted, SKImageInfo info, int sampleCount) =>
+ Create (context, budgeted, info, sampleCount, GRSurfaceOrigin.BottomLeft, null, false);
+
+ public static SKSurface Create (GRContext context, bool budgeted, SKImageInfo info, int sampleCount, GRSurfaceOrigin origin) =>
+ Create (context, budgeted, info, sampleCount, GRSurfaceOrigin.BottomLeft, null, false);
+
+ public static SKSurface Create (GRContext context, bool budgeted, SKImageInfo info, SKSurfaceProperties props) =>
+ Create (context, budgeted, info, 0, GRSurfaceOrigin.BottomLeft, props, false);
+
+ public static SKSurface Create (GRContext context, bool budgeted, SKImageInfo info, int sampleCount, SKSurfaceProperties props) =>
+ Create (context, budgeted, info, sampleCount, GRSurfaceOrigin.BottomLeft, props, false);
+
+ public static SKSurface Create (GRContext context, bool budgeted, SKImageInfo info, int sampleCount, GRSurfaceOrigin origin, SKSurfaceProperties props, bool shouldCreateWithMips)
+ {
+ if (context == null)
+ throw new ArgumentNullException (nameof (context));
+
+ var cinfo = SKImageInfoNative.FromManaged (ref info);
+ return GetObject<SKSurface> (SkiaApi.sk_surface_new_render_target (context.Handle, budgeted, &cinfo, sampleCount, origin, props?.Handle ?? IntPtr.Zero, shouldCreateWithMips));
+ }
+
+ // NULL surface
+
+ public static SKSurface CreateNull (int width, int height) =>
+ GetObject<SKSurface> (SkiaApi.sk_surface_new_null (width, height));
+
+ //
+
+ public SKCanvas Canvas =>
+ OwnedBy (GetObject<SKCanvas> (SkiaApi.sk_surface_get_canvas (Handle), false, unrefExisting: false), this);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use SurfaceProperties instead.")]
+ public SKSurfaceProps SurfaceProps {
+ get {
+ var props = SurfaceProperties;
+ return new SKSurfaceProps {
+ Flags = props.Flags,
+ PixelGeometry = props.PixelGeometry
+ };
+ }
+ }
+
+ public SKSurfaceProperties SurfaceProperties =>
+ OwnedBy (GetObject<SKSurfaceProperties> (SkiaApi.sk_surface_get_props (Handle), false), this);
+
+ public SKImage Snapshot () =>
+ GetObject<SKImage> (SkiaApi.sk_surface_new_image_snapshot (Handle));
+
+ public void Draw (SKCanvas canvas, float x, float y, SKPaint paint)
+ {
+ if (canvas == null)
+ throw new ArgumentNullException (nameof (canvas));
+
+ SkiaApi.sk_surface_draw (Handle, canvas.Handle, x, y, paint == null ? IntPtr.Zero : paint.Handle);
+ }
+
+ public SKPixmap PeekPixels ()
+ {
+ var pixmap = new SKPixmap ();
+ var result = PeekPixels (pixmap);
+ if (result) {
+ return pixmap;
+ } else {
+ pixmap.Dispose ();
+ return null;
+ }
+ }
+
+ public bool PeekPixels (SKPixmap pixmap)
+ {
+ if (pixmap == null)
+ throw new ArgumentNullException (nameof (pixmap));
+
+ var result = SkiaApi.sk_surface_peek_pixels (Handle, pixmap.Handle);
+ if (result)
+ pixmap.pixelSource = this;
+ return result;
+ }
+
+ public bool ReadPixels (SKImageInfo dstInfo, IntPtr dstPixels, int dstRowBytes, int srcX, int srcY)
+ {
+ var cinfo = SKImageInfoNative.FromManaged (ref dstInfo);
+ return SkiaApi.sk_surface_read_pixels (Handle, &cinfo, (void*)dstPixels, (IntPtr)dstRowBytes, srcX, srcY);
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public class SKSurfaceProperties : SKObject
+ {
+ [Preserve]
+ internal SKSurfaceProperties (IntPtr h, bool owns)
+ : base (h, owns)
+ {
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public SKSurfaceProperties (SKSurfaceProps props)
+ : this (props.Flags, props.PixelGeometry)
+ {
+ }
+
+ public SKSurfaceProperties (SKPixelGeometry pixelGeometry)
+ : this ((uint)0, pixelGeometry)
+ {
+ }
+
+ public SKSurfaceProperties (uint flags, SKPixelGeometry pixelGeometry)
+ : this (SkiaApi.sk_surfaceprops_new (flags, pixelGeometry), true)
+ {
+ }
+
+ public SKSurfaceProperties (SKSurfacePropsFlags flags, SKPixelGeometry pixelGeometry)
+ : this (SkiaApi.sk_surfaceprops_new ((uint)flags, pixelGeometry), true)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_surfaceprops_delete (Handle);
+
+ public SKSurfacePropsFlags Flags =>
+ (SKSurfacePropsFlags)SkiaApi.sk_surfaceprops_get_flags (Handle);
+
+ public SKPixelGeometry PixelGeometry =>
+ SkiaApi.sk_surfaceprops_get_pixel_geometry (Handle);
+
+ public bool IsUseDeviceIndependentFonts =>
+ Flags.HasFlag (SKSurfacePropsFlags.UseDeviceIndependentFonts);
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public static unsafe class SKSwizzle
+ {
+ public static void SwapRedBlue (IntPtr pixels, int count) =>
+ SwapRedBlue (pixels, pixels, count);
+
+ public static void SwapRedBlue (IntPtr dest, IntPtr src, int count)
+ {
+ if (dest == IntPtr.Zero) {
+ throw new ArgumentException (nameof (dest));
+ }
+ if (src == IntPtr.Zero) {
+ throw new ArgumentException (nameof (src));
+ }
+
+ SkiaApi.sk_swizzle_swap_rb ((uint*)dest, (uint*)src, count);
+ }
+
+ public static void SwapRedBlue (Span<byte> pixels) =>
+ SwapRedBlue (pixels, pixels, pixels.Length);
+
+ public static void SwapRedBlue (ReadOnlySpan<byte> pixels, int count) =>
+ SwapRedBlue (pixels, pixels, count);
+
+ public static void SwapRedBlue (ReadOnlySpan<byte> dest, ReadOnlySpan<byte> src, int count)
+ {
+ if (dest == null) {
+ throw new ArgumentNullException (nameof (dest));
+ }
+ if (src == null) {
+ throw new ArgumentNullException (nameof (src));
+ }
+
+ fixed (byte* d = dest)
+ fixed (byte* s = src) {
+ SkiaApi.sk_swizzle_swap_rb ((uint*)d, (uint*)s, count);
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public unsafe class SKTextBlob : SKObject, ISKNonVirtualReferenceCounted
+ {
+ [Preserve]
+ internal SKTextBlob (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ void ISKNonVirtualReferenceCounted.ReferenceNative () => SkiaApi.sk_textblob_ref (Handle);
+
+ void ISKNonVirtualReferenceCounted.UnreferenceNative () => SkiaApi.sk_textblob_unref (Handle);
+
+ public SKRect Bounds {
+ get {
+ SKRect bounds;
+ SkiaApi.sk_textblob_get_bounds (Handle, &bounds);
+ return bounds;
+ }
+ }
+
+ public uint UniqueId => SkiaApi.sk_textblob_get_unique_id (Handle);
+ }
+
+ public unsafe class SKTextBlobBuilder : SKObject
+ {
+ [Preserve]
+ internal SKTextBlobBuilder (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ public SKTextBlobBuilder ()
+ : this (SkiaApi.sk_textblob_builder_new (), true)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_textblob_builder_delete (Handle);
+
+ // Build
+
+ public SKTextBlob Build () =>
+ GetObject<SKTextBlob> (SkiaApi.sk_textblob_builder_make (Handle));
+
+ // AddRun
+
+ public void AddRun (SKPaint font, float x, float y, ushort[] glyphs, string text, uint[] clusters)
+ {
+ var utf8Text = StringUtilities.GetEncodedText (text, SKTextEncoding.Utf8);
+ AddRun (font, x, y, glyphs, utf8Text, clusters, null);
+ }
+
+ public void AddRun (SKPaint font, float x, float y, ushort[] glyphs, string text, uint[] clusters, SKRect bounds)
+ {
+ var utf8Text = StringUtilities.GetEncodedText (text, SKTextEncoding.Utf8);
+ AddRun (font, x, y, glyphs, utf8Text, clusters, (SKRect?)bounds);
+ }
+
+ public void AddRun (SKPaint font, float x, float y, ushort[] glyphs) =>
+ AddRun (font, x, y, glyphs, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, null);
+
+ public void AddRun (SKPaint font, float x, float y, ushort[] glyphs, SKRect bounds) =>
+ AddRun (font, x, y, glyphs, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, bounds);
+
+ public void AddRun (SKPaint font, float x, float y, ushort[] glyphs, byte[] text, uint[] clusters) =>
+ AddRun (font, x, y, glyphs, text, clusters, null);
+
+ public void AddRun (SKPaint font, float x, float y, ushort[] glyphs, byte[] text, uint[] clusters, SKRect bounds) =>
+ AddRun (font, x, y, glyphs, text, clusters, (SKRect?)bounds);
+
+ // AddRun (spans)
+
+ public void AddRun (SKPaint font, float x, float y, ReadOnlySpan<ushort> glyphs) =>
+ AddRun (font, x, y, glyphs, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, null);
+
+ public void AddRun (SKPaint font, float x, float y, ReadOnlySpan<ushort> glyphs, SKRect? bounds) =>
+ AddRun (font, x, y, glyphs, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, bounds);
+
+ public void AddRun (SKPaint font, float x, float y, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<byte> text, ReadOnlySpan<uint> clusters) =>
+ AddRun (font, x, y, glyphs, text, clusters, null);
+
+ public void AddRun (SKPaint font, float x, float y, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<byte> text, ReadOnlySpan<uint> clusters, SKRect? bounds)
+ {
+ if (font == null)
+ throw new ArgumentNullException (nameof (font));
+ if (glyphs.IsEmpty)
+ throw new ArgumentNullException (nameof (glyphs));
+
+ if (!text.IsEmpty) {
+ if (clusters.IsEmpty)
+ throw new ArgumentNullException (nameof (clusters));
+ if (glyphs.Length != clusters.Length)
+ throw new ArgumentException ("The number of glyphs and clusters must be the same.");
+ }
+
+ var run = AllocateRun (font, glyphs.Length, x, y, text.IsEmpty ? 0 : text.Length, bounds);
+ run.SetGlyphs (glyphs);
+
+ if (!text.IsEmpty) {
+ run.SetText (text);
+ run.SetClusters (clusters);
+ }
+ }
+
+ // AddHorizontalRun
+
+ public void AddHorizontalRun (SKPaint font, float y, ushort[] glyphs, float[] positions, string text, uint[] clusters)
+ {
+ var utf8Text = StringUtilities.GetEncodedText (text, SKTextEncoding.Utf8);
+ AddHorizontalRun (font, y, glyphs, positions, utf8Text, clusters, null);
+ }
+
+ public void AddHorizontalRun (SKPaint font, float y, ushort[] glyphs, float[] positions, string text, uint[] clusters, SKRect bounds)
+ {
+ var utf8Text = StringUtilities.GetEncodedText (text, SKTextEncoding.Utf8);
+ AddHorizontalRun (font, y, glyphs, positions, utf8Text, clusters, (SKRect?)bounds);
+ }
+
+ public void AddHorizontalRun (SKPaint font, float y, ushort[] glyphs, float[] positions) =>
+ AddHorizontalRun (font, y, glyphs, positions, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, null);
+
+ public void AddHorizontalRun (SKPaint font, float y, ushort[] glyphs, float[] positions, SKRect bounds) =>
+ AddHorizontalRun (font, y, glyphs, positions, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, bounds);
+
+ public void AddHorizontalRun (SKPaint font, float y, ushort[] glyphs, float[] positions, byte[] text, uint[] clusters) =>
+ AddHorizontalRun (font, y, glyphs, positions, text, clusters, null);
+
+ public void AddHorizontalRun (SKPaint font, float y, ushort[] glyphs, float[] positions, byte[] text, uint[] clusters, SKRect bounds) =>
+ AddHorizontalRun (font, y, glyphs, positions, text, clusters, (SKRect?)bounds);
+
+ // AddHorizontalRun (spans)
+
+ public void AddHorizontalRun (SKPaint font, float y, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<float> positions) =>
+ AddHorizontalRun (font, y, glyphs, positions, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, null);
+
+ public void AddHorizontalRun (SKPaint font, float y, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<float> positions, SKRect? bounds) =>
+ AddHorizontalRun (font, y, glyphs, positions, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, bounds);
+
+ public void AddHorizontalRun (SKPaint font, float y, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<float> positions, ReadOnlySpan<byte> text, ReadOnlySpan<uint> clusters) =>
+ AddHorizontalRun (font, y, glyphs, positions, text, clusters, null);
+
+ public void AddHorizontalRun (SKPaint font, float y, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<float> positions, ReadOnlySpan<byte> text, ReadOnlySpan<uint> clusters, SKRect? bounds)
+ {
+ if (font == null)
+ throw new ArgumentNullException (nameof (font));
+ if (glyphs.IsEmpty)
+ throw new ArgumentNullException (nameof (glyphs));
+ if (positions.IsEmpty)
+ throw new ArgumentNullException (nameof (positions));
+ if (glyphs.Length != positions.Length)
+ throw new ArgumentException ("The number of glyphs and positions must be the same.");
+
+ if (!text.IsEmpty) {
+ if (clusters.IsEmpty)
+ throw new ArgumentNullException (nameof (clusters));
+ if (glyphs.Length != clusters.Length)
+ throw new ArgumentException ("The number of glyphs and clusters must be the same.");
+ }
+
+ var run = AllocateHorizontalRun (font, glyphs.Length, y, text.IsEmpty ? 0 : text.Length, bounds);
+ run.SetGlyphs (glyphs);
+ run.SetPositions (positions);
+
+ if (!text.IsEmpty) {
+ run.SetText (text);
+ run.SetClusters (clusters);
+ }
+ }
+
+ // AddPositionedRun
+
+ public void AddPositionedRun (SKPaint font, ushort[] glyphs, SKPoint[] positions, string text, uint[] clusters)
+ {
+ var utf8Text = StringUtilities.GetEncodedText (text, SKTextEncoding.Utf8);
+ AddPositionedRun (font, glyphs, positions, utf8Text, clusters, null);
+ }
+
+ public void AddPositionedRun (SKPaint font, ushort[] glyphs, SKPoint[] positions, string text, uint[] clusters, SKRect bounds)
+ {
+ var utf8Text = StringUtilities.GetEncodedText (text, SKTextEncoding.Utf8);
+ AddPositionedRun (font, glyphs, positions, utf8Text, clusters, (SKRect?)bounds);
+ }
+
+ public void AddPositionedRun (SKPaint font, ushort[] glyphs, SKPoint[] positions) =>
+ AddPositionedRun (font, glyphs, positions, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, null);
+
+ public void AddPositionedRun (SKPaint font, ushort[] glyphs, SKPoint[] positions, SKRect bounds) =>
+ AddPositionedRun (font, glyphs, positions, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, bounds);
+
+ public void AddPositionedRun (SKPaint font, ushort[] glyphs, SKPoint[] positions, byte[] text, uint[] clusters) =>
+ AddPositionedRun (font, glyphs, positions, text, clusters, null);
+
+ public void AddPositionedRun (SKPaint font, ushort[] glyphs, SKPoint[] positions, byte[] text, uint[] clusters, SKRect bounds) =>
+ AddPositionedRun (font, glyphs, positions, text, clusters, (SKRect?)bounds);
+
+ // AddPositionedRun (spans)
+
+ public void AddPositionedRun (SKPaint font, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<SKPoint> positions) =>
+ AddPositionedRun (font, glyphs, positions, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, null);
+
+ public void AddPositionedRun (SKPaint font, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<SKPoint> positions, SKRect? bounds) =>
+ AddPositionedRun (font, glyphs, positions, ReadOnlySpan<byte>.Empty, ReadOnlySpan<uint>.Empty, bounds);
+
+ public void AddPositionedRun (SKPaint font, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<SKPoint> positions, ReadOnlySpan<byte> text, ReadOnlySpan<uint> clusters) =>
+ AddPositionedRun (font, glyphs, positions, text, clusters, null);
+
+ public void AddPositionedRun (SKPaint font, ReadOnlySpan<ushort> glyphs, ReadOnlySpan<SKPoint> positions, ReadOnlySpan<byte> text, ReadOnlySpan<uint> clusters, SKRect? bounds)
+ {
+ if (font == null)
+ throw new ArgumentNullException (nameof (font));
+ if (glyphs.IsEmpty)
+ throw new ArgumentNullException (nameof (glyphs));
+ if (positions.IsEmpty)
+ throw new ArgumentNullException (nameof (positions));
+ if (glyphs.Length != positions.Length)
+ throw new ArgumentException ("The number of glyphs and positions must be the same.");
+
+ if (!text.IsEmpty) {
+ if (clusters.IsEmpty)
+ throw new ArgumentNullException (nameof (clusters));
+ if (glyphs.Length != clusters.Length)
+ throw new ArgumentException ("The number of glyphs and clusters must be the same.");
+ }
+
+ var run = AllocatePositionedRun (font, glyphs.Length, text.IsEmpty ? 0 : text.Length, bounds);
+ run.SetGlyphs (glyphs);
+ run.SetPositions (positions);
+
+ if (!text.IsEmpty) {
+ run.SetText (text);
+ run.SetClusters (clusters);
+ }
+ }
+
+ // AllocateRun
+
+ public SKRunBuffer AllocateRun (SKPaint font, int count, float x, float y) =>
+ AllocateRun (font, count, x, y, 0, null);
+
+ public SKRunBuffer AllocateRun (SKPaint font, int count, float x, float y, SKRect? bounds) =>
+ AllocateRun (font, count, x, y, 0, bounds);
+
+ public SKRunBuffer AllocateRun (SKPaint font, int count, float x, float y, int textByteCount) =>
+ AllocateRun (font, count, x, y, textByteCount, null);
+
+ public SKRunBuffer AllocateRun (SKPaint font, int count, float x, float y, int textByteCount, SKRect? bounds)
+ {
+ if (font == null)
+ throw new ArgumentNullException (nameof (font));
+
+ var originalEncoding = font.TextEncoding;
+ try {
+ font.TextEncoding = SKTextEncoding.GlyphId;
+
+ SKRunBufferInternal runbuffer;
+ if (bounds is SKRect b) {
+ SkiaApi.sk_textblob_builder_alloc_run_text (Handle, font.Handle, count, x, y, textByteCount, &b, &runbuffer);
+ } else {
+ SkiaApi.sk_textblob_builder_alloc_run_text (Handle, font.Handle, count, x, y, textByteCount, null, &runbuffer);
+ }
+
+ return new SKRunBuffer (runbuffer, count, textByteCount);
+
+ } finally {
+ font.TextEncoding = originalEncoding;
+ }
+ }
+
+ // AllocateHorizontalRun
+
+ public SKHorizontalRunBuffer AllocateHorizontalRun (SKPaint font, int count, float y) =>
+ AllocateHorizontalRun (font, count, y, 0, null);
+
+ public SKHorizontalRunBuffer AllocateHorizontalRun (SKPaint font, int count, float y, SKRect? bounds) =>
+ AllocateHorizontalRun (font, count, y, 0, bounds);
+
+ public SKHorizontalRunBuffer AllocateHorizontalRun (SKPaint font, int count, float y, int textByteCount) =>
+ AllocateHorizontalRun (font, count, y, textByteCount, null);
+
+ public SKHorizontalRunBuffer AllocateHorizontalRun (SKPaint font, int count, float y, int textByteCount, SKRect? bounds)
+ {
+ if (font == null)
+ throw new ArgumentNullException (nameof (font));
+
+ var originalEncoding = font.TextEncoding;
+ try {
+ font.TextEncoding = SKTextEncoding.GlyphId;
+
+ SKRunBufferInternal runbuffer;
+ if (bounds is SKRect b) {
+ SkiaApi.sk_textblob_builder_alloc_run_text_pos_h (Handle, font.Handle, count, y, textByteCount, &b, &runbuffer);
+ } else {
+ SkiaApi.sk_textblob_builder_alloc_run_text_pos_h (Handle, font.Handle, count, y, textByteCount, null, &runbuffer);
+ }
+
+ return new SKHorizontalRunBuffer (runbuffer, count, textByteCount);
+ } finally {
+ font.TextEncoding = originalEncoding;
+ }
+ }
+
+ // AllocatePositionedRun
+
+ public SKPositionedRunBuffer AllocatePositionedRun (SKPaint font, int count) =>
+ AllocatePositionedRun (font, count, 0, null);
+
+ public SKPositionedRunBuffer AllocatePositionedRun (SKPaint font, int count, SKRect? bounds) =>
+ AllocatePositionedRun (font, count, 0, bounds);
+
+ public SKPositionedRunBuffer AllocatePositionedRun (SKPaint font, int count, int textByteCount) =>
+ AllocatePositionedRun (font, count, textByteCount, null);
+
+ public SKPositionedRunBuffer AllocatePositionedRun (SKPaint font, int count, int textByteCount, SKRect? bounds)
+ {
+ if (font == null)
+ throw new ArgumentNullException (nameof (font));
+
+ var originalEncoding = font.TextEncoding;
+ try {
+ font.TextEncoding = SKTextEncoding.GlyphId;
+
+ SKRunBufferInternal runbuffer;
+ if (bounds is SKRect b) {
+ SkiaApi.sk_textblob_builder_alloc_run_text_pos (Handle, font.Handle, count, textByteCount, &b, &runbuffer);
+ } else {
+ SkiaApi.sk_textblob_builder_alloc_run_text_pos (Handle, font.Handle, count, textByteCount, null, &runbuffer);
+ }
+
+ return new SKPositionedRunBuffer (runbuffer, count, textByteCount);
+ } finally {
+ font.TextEncoding = originalEncoding;
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.IO;
+
+namespace SkiaSharp
+{
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Flags]
+ [Obsolete ("Use SKFontStyleWeight and SKFontStyleSlant instead.")]
+ public enum SKTypefaceStyle
+ {
+ Normal = 0,
+ Bold = 0x01,
+ Italic = 0x02,
+ BoldItalic = 0x03
+ }
+
+ public unsafe class SKTypeface : SKObject, ISKReferenceCounted
+ {
+ private static readonly Lazy<SKTypeface> defaultTypeface;
+
+ static SKTypeface ()
+ {
+ defaultTypeface = new Lazy<SKTypeface> (() => new SKTypefaceStatic (SkiaApi.sk_typeface_ref_default ()));
+ }
+
+ internal static void EnsureStaticInstanceAreInitialized ()
+ {
+ // IMPORTANT: do not remove to ensure that the static instances
+ // are initialized before any access is made to them
+ }
+
+ [Preserve]
+ internal SKTypeface (IntPtr handle, bool owns)
+ : base (handle, owns)
+ {
+ }
+
+ // Default
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ public static SKTypeface Default => defaultTypeface.Value;
+
+ public static SKTypeface CreateDefault ()
+ {
+ return GetObject<SKTypeface> (SkiaApi.sk_typeface_create_default ());
+ }
+
+ // FromFamilyName
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FromFamilyName(string, SKFontStyleWeight, SKFontStyleWidth, SKFontStyleSlant) instead.")]
+ public static SKTypeface FromFamilyName (string familyName, SKTypefaceStyle style)
+ {
+ var weight = style.HasFlag (SKTypefaceStyle.Bold) ? SKFontStyleWeight.Bold : SKFontStyleWeight.Normal;
+ var slant = style.HasFlag (SKTypefaceStyle.Italic) ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright;
+
+ return FromFamilyName (familyName, weight, SKFontStyleWidth.Normal, slant);
+ }
+
+ public static SKTypeface FromFamilyName (string familyName, int weight, int width, SKFontStyleSlant slant)
+ {
+ return FromFamilyName (familyName, new SKFontStyle (weight, width, slant));
+ }
+
+ public static SKTypeface FromFamilyName (string familyName)
+ {
+ return FromFamilyName (familyName, SKFontStyle.Normal);
+ }
+
+ public static SKTypeface FromFamilyName (string familyName, SKFontStyle style)
+ {
+ if (style == null)
+ throw new ArgumentNullException (nameof (style));
+
+ return GetObject<SKTypeface> (SkiaApi.sk_typeface_create_from_name_with_font_style (familyName, style.Handle));
+ }
+
+ public static SKTypeface FromFamilyName (string familyName, SKFontStyleWeight weight, SKFontStyleWidth width, SKFontStyleSlant slant)
+ {
+ return FromFamilyName (familyName, (int)weight, (int)width, slant);
+ }
+
+ // From*
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete]
+ public static SKTypeface FromTypeface (SKTypeface typeface, SKTypefaceStyle style)
+ {
+ if (typeface == null)
+ throw new ArgumentNullException (nameof (typeface));
+
+ var weight = style.HasFlag (SKTypefaceStyle.Bold) ? SKFontStyleWeight.Bold : SKFontStyleWeight.Normal;
+ var width = SKFontStyleWidth.Normal;
+ var slant = style.HasFlag (SKTypefaceStyle.Italic) ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright;
+
+ return SKFontManager.Default.MatchTypeface (typeface, new SKFontStyle (weight, width, slant));
+ }
+
+ public static SKTypeface FromFile (string path, int index = 0)
+ {
+ if (path == null)
+ throw new ArgumentNullException (nameof (path));
+
+ var utf8path = StringUtilities.GetEncodedText (path, SKTextEncoding.Utf8);
+ fixed (byte* u = utf8path) {
+ return GetObject<SKTypeface> (SkiaApi.sk_typeface_create_from_file (u, index));
+ }
+ }
+
+ public static SKTypeface FromStream (Stream stream, int index = 0)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ return FromStream (new SKManagedStream (stream, true), index);
+ }
+
+ public static SKTypeface FromStream (SKStreamAsset stream, int index = 0)
+ {
+ if (stream == null)
+ throw new ArgumentNullException (nameof (stream));
+
+ if (stream is SKManagedStream managed) {
+ stream = managed.ToMemoryStream ();
+ managed.Dispose ();
+ }
+
+ var typeface = GetObject<SKTypeface> (SkiaApi.sk_typeface_create_from_stream (stream.Handle, index));
+ stream.RevokeOwnership (typeface);
+ return typeface;
+ }
+
+ public static SKTypeface FromData (SKData data, int index = 0)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+
+ return FromStream (new SKMemoryStream (data), index);
+ }
+
+ // CharsToGlyphs
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(string, out ushort[]) instead.")]
+ public int CharsToGlyphs (string chars, out ushort[] glyphs) =>
+ GetGlyphs (chars, out glyphs);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(IntPtr, int, SKTextEncoding, out ushort[]) instead.")]
+ public int CharsToGlyphs (IntPtr str, int strlen, SKEncoding encoding, out ushort[] glyphs) =>
+ GetGlyphs (str, strlen, encoding, out glyphs);
+
+ // Properties
+
+ public string FamilyName => (string)GetObject<SKString> (SkiaApi.sk_typeface_get_family_name (Handle));
+
+ public SKFontStyle FontStyle => GetObject<SKFontStyle> (SkiaApi.sk_typeface_get_fontstyle (Handle));
+
+ public int FontWeight => SkiaApi.sk_typeface_get_font_weight (Handle);
+
+ public int FontWidth => SkiaApi.sk_typeface_get_font_width (Handle);
+
+ public SKFontStyleSlant FontSlant => SkiaApi.sk_typeface_get_font_slant (Handle);
+
+ public bool IsBold => FontStyle.Weight >= (int)SKFontStyleWeight.SemiBold;
+
+ public bool IsItalic => FontStyle.Slant != SKFontStyleSlant.Upright;
+
+ public bool IsFixedPitch => SkiaApi.sk_typeface_is_fixed_pitch (Handle);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use FontWeight and FontSlant instead.")]
+ public SKTypefaceStyle Style {
+ get {
+ var style = SKTypefaceStyle.Normal;
+ if (FontWeight >= (int)SKFontStyleWeight.SemiBold)
+ style |= SKTypefaceStyle.Bold;
+ if (FontSlant != (int)SKFontStyleSlant.Upright)
+ style |= SKTypefaceStyle.Italic;
+ return style;
+ }
+ }
+
+ public int UnitsPerEm => SkiaApi.sk_typeface_get_units_per_em (Handle);
+
+ public int GlyphCount => SkiaApi.sk_typeface_count_glyphs (Handle);
+
+ // GetTableTags
+
+ public int TableCount => SkiaApi.sk_typeface_count_tables (Handle);
+
+ public UInt32[] GetTableTags ()
+ {
+ if (!TryGetTableTags (out var result)) {
+ throw new Exception ("Unable to read the tables for the file.");
+ }
+ return result;
+ }
+
+ public bool TryGetTableTags (out UInt32[] tags)
+ {
+ var buffer = new UInt32[TableCount];
+ fixed (UInt32* b = buffer) {
+ if (SkiaApi.sk_typeface_get_table_tags (Handle, b) == 0) {
+ tags = null;
+ return false;
+ }
+ }
+ tags = buffer;
+ return true;
+ }
+
+ // GetTableSize
+
+ public int GetTableSize (UInt32 tag) =>
+ (int)SkiaApi.sk_typeface_get_table_size (Handle, tag);
+
+ // GetTableData
+
+ public byte[] GetTableData (UInt32 tag)
+ {
+ if (!TryGetTableData (tag, out var result)) {
+ throw new Exception ("Unable to read the data table.");
+ }
+ return result;
+ }
+
+ public bool TryGetTableData (UInt32 tag, out byte[] tableData)
+ {
+ var length = GetTableSize (tag);
+ var buffer = new byte[length];
+ fixed (byte* b = buffer) {
+ if (!TryGetTableData (tag, 0, length, (IntPtr)b)) {
+ tableData = null;
+ return false;
+ }
+ }
+ tableData = buffer;
+ return true;
+ }
+
+ public bool TryGetTableData (UInt32 tag, int offset, int length, IntPtr tableData)
+ {
+ var actual = SkiaApi.sk_typeface_get_table_data (Handle, tag, (IntPtr)offset, (IntPtr)length, (byte*)tableData);
+ return actual != IntPtr.Zero;
+ }
+
+ // CountGlyphs (string/char)
+
+ public int CountGlyphs (string str) =>
+ CountGlyphs (str.AsSpan ());
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CountGlyphs(string) instead.")]
+ public int CountGlyphs (string str, SKEncoding encoding) =>
+ CountGlyphs (str.AsSpan ());
+
+ public int CountGlyphs (ReadOnlySpan<char> str)
+ {
+ var bytes = StringUtilities.GetEncodedText (str, SKTextEncoding.Utf16);
+ return CountGlyphs (bytes, SKTextEncoding.Utf16);
+ }
+
+ // CountGlyphs (byte[])
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CountGlyphs(byte[], SKTextEncoding) instead.")]
+ public int CountGlyphs (byte[] str, SKEncoding encoding) =>
+ CountGlyphs (str.AsSpan (), encoding.ToTextEncoding ());
+
+ public int CountGlyphs (byte[] str, SKTextEncoding encoding) =>
+ CountGlyphs (str.AsSpan (), encoding);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CountGlyphs(ReadOnlySpan<byte>, SKTextEncoding) instead.")]
+ public int CountGlyphs (ReadOnlySpan<byte> str, SKEncoding encoding) =>
+ CountGlyphs (str, encoding.ToTextEncoding ());
+
+ public int CountGlyphs (ReadOnlySpan<byte> str, SKTextEncoding encoding)
+ {
+ fixed (byte* p = str) {
+ return CountGlyphs ((IntPtr)p, str.Length, encoding);
+ }
+ }
+
+ // CountGlyphs (IntPtr)
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use CountGlyphs(ReadOnlySpan<byte>, SKTextEncoding) instead.")]
+ public int CountGlyphs (IntPtr str, int strLen, SKEncoding encoding) =>
+ CountGlyphs (str, strLen, encoding.ToTextEncoding ());
+
+ public int CountGlyphs (IntPtr str, int strLen, SKTextEncoding encoding)
+ {
+ if (str == IntPtr.Zero && strLen != 0)
+ throw new ArgumentNullException (nameof (str));
+
+ return SkiaApi.sk_typeface_chars_to_glyphs (Handle, (byte*)str, encoding.ToEncoding (), null, strLen);
+ }
+
+ // GetGlyphs (string/char, out)
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(string) instead.")]
+ public int GetGlyphs (string text, out ushort[] glyphs)
+ {
+ glyphs = GetGlyphs (text);
+ return glyphs.Length;
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(string) instead.")]
+ public int GetGlyphs (string text, SKEncoding encoding, out ushort[] glyphs) =>
+ GetGlyphs (text, out glyphs);
+
+ // GetGlyphs (byte[], out)
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(byte[], SKTextEncoding) instead.")]
+ public int GetGlyphs (byte[] text, SKEncoding encoding, out ushort[] glyphs) =>
+ GetGlyphs (text.AsSpan (), encoding, out glyphs);
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(ReadOnlySpan<byte>, SKTextEncoding) instead.")]
+ public int GetGlyphs (ReadOnlySpan<byte> text, SKEncoding encoding, out ushort[] glyphs)
+ {
+ glyphs = GetGlyphs (text, encoding);
+ return glyphs.Length;
+ }
+
+ // GetGlyphs (IntPtr, out)
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(IntPtr, int, SKTextEncoding) instead.")]
+ public int GetGlyphs (IntPtr text, int length, SKEncoding encoding, out ushort[] glyphs)
+ {
+ glyphs = GetGlyphs (text, length, encoding);
+ return glyphs.Length;
+ }
+
+ // GetGlyphs (string/char, out)
+
+ public ushort[] GetGlyphs (string text) =>
+ GetGlyphs (text.AsSpan ());
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(string) instead.")]
+ public ushort[] GetGlyphs (string text, SKEncoding encoding) =>
+ GetGlyphs (text.AsSpan ());
+
+ public ushort[] GetGlyphs (ReadOnlySpan<char> text)
+ {
+ fixed (void* t = text) {
+ return GetGlyphs ((IntPtr)t, text.Length, SKTextEncoding.Utf16);
+ }
+ }
+
+ // GetGlyphs (byte[], out)
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(ReadOnlySpan<byte>, SKTextEncoding) instead.")]
+ public ushort[] GetGlyphs (byte[] text, SKEncoding encoding) =>
+ GetGlyphs (text.AsSpan (), encoding.ToTextEncoding ());
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(ReadOnlySpan<byte>, SKTextEncoding) instead.")]
+ public ushort[] GetGlyphs (ReadOnlySpan<byte> text, SKEncoding encoding) =>
+ GetGlyphs (text, encoding.ToTextEncoding ());
+
+ public ushort[] GetGlyphs (ReadOnlySpan<byte> text, SKTextEncoding encoding)
+ {
+ fixed (void* t = text) {
+ return GetGlyphs ((IntPtr)t, text.Length, encoding);
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetGlyphs(IntPtr, int, SKTextEncoding) instead.")]
+ public ushort[] GetGlyphs (IntPtr text, int length, SKEncoding encoding) =>
+ GetGlyphs (text, length, encoding.ToTextEncoding ());
+
+ public ushort[] GetGlyphs (IntPtr text, int length, SKTextEncoding encoding)
+ {
+ if (text == IntPtr.Zero && length != 0)
+ throw new ArgumentNullException (nameof (text));
+
+ var n = SkiaApi.sk_typeface_chars_to_glyphs (Handle, (void*)text, encoding.ToEncoding (), null, length);
+ if (n <= 0)
+ return new ushort[0];
+
+ var glyphs = new ushort[n];
+ fixed (ushort* gp = glyphs) {
+ SkiaApi.sk_typeface_chars_to_glyphs (Handle, (void*)text, encoding.ToEncoding (), gp, n);
+ }
+ return glyphs;
+ }
+
+ // ContainsGlyphs
+
+ public bool ContainsGlyphs (string text) =>
+ ContainsGlyphs (GetGlyphs (text));
+
+ public bool ContainsGlyphs (ReadOnlySpan<char> text) =>
+ ContainsGlyphs (GetGlyphs (text));
+
+ public bool ContainsGlyphs (ReadOnlySpan<byte> text, SKTextEncoding encoding) =>
+ ContainsGlyphs (GetGlyphs (text, encoding));
+
+ public bool ContainsGlyphs (IntPtr text, int length, SKTextEncoding encoding) =>
+ ContainsGlyphs (GetGlyphs (text, length, encoding));
+
+ private bool ContainsGlyphs (ushort[] glyphs) =>
+ Array.IndexOf (glyphs, 0) != -1;
+
+ // OpenStream
+
+ public SKStreamAsset OpenStream () =>
+ OpenStream (out _);
+
+ public SKStreamAsset OpenStream (out int ttcIndex)
+ {
+ fixed (int* ttc = &ttcIndex) {
+ return GetObject<SKStreamAssetImplementation> (SkiaApi.sk_typeface_open_stream (Handle, ttc));
+ }
+ }
+
+ // GetKerningPairAdjustments
+
+ public int[] GetKerningPairAdjustments (ReadOnlySpan<ushort> glyphs)
+ {
+ var adjustments = new int[glyphs.Length];
+ fixed (ushort* gp = glyphs)
+ fixed (int* ap = adjustments) {
+ SkiaApi.sk_typeface_get_kerning_pair_adjustments (Handle, gp, glyphs.Length, ap);
+ }
+ return adjustments;
+ }
+
+ //
+
+ private sealed class SKTypefaceStatic : SKTypeface
+ {
+ internal SKTypefaceStatic (IntPtr x)
+ : base (x, false)
+ {
+ IgnorePublicDispose = true;
+ }
+
+ protected override void Dispose (bool disposing)
+ {
+ // do not dispose
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+using System.IO;
+using System.Text;
+using System.ComponentModel;
+
+namespace SkiaSharp
+{
+ public unsafe class SKVertices : SKObject, ISKNonVirtualReferenceCounted
+ {
+ [Preserve]
+ internal SKVertices (IntPtr x, bool owns)
+ : base (x, owns)
+ {
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ void ISKNonVirtualReferenceCounted.ReferenceNative () => SkiaApi.sk_vertices_ref (Handle);
+
+ void ISKNonVirtualReferenceCounted.UnreferenceNative () => SkiaApi.sk_vertices_unref (Handle);
+
+ public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKColor[] colors)
+ {
+ return CreateCopy (vmode, positions, null, colors, null);
+ }
+
+ public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKPoint[] texs, SKColor[] colors)
+ {
+ return CreateCopy (vmode, positions, texs, colors, null);
+ }
+
+ public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKPoint[] texs, SKColor[] colors, UInt16[] indices)
+ {
+ if (positions == null)
+ throw new ArgumentNullException (nameof (positions));
+
+ if (texs != null && positions.Length != texs.Length)
+ throw new ArgumentException ("The number of texture coordinates must match the number of vertices.", nameof (texs));
+ if (colors != null && positions.Length != colors.Length)
+ throw new ArgumentException ("The number of colors must match the number of vertices.", nameof (colors));
+
+ var vertexCount = positions.Length;
+ var indexCount = indices?.Length ?? 0;
+
+ fixed (SKPoint* p = positions)
+ fixed (SKPoint* t = texs)
+ fixed (SKColor* c = colors)
+ fixed (UInt16* i = indices) {
+ return GetObject<SKVertices> (SkiaApi.sk_vertices_make_copy (vmode, vertexCount, p, t, (uint*)c, indexCount, i));
+ }
+ }
+ }
+}
--- /dev/null
+using System;
+
+namespace SkiaSharp
+{
+ public abstract class SKXmlWriter : SKObject
+ {
+ internal SKXmlWriter (IntPtr h, bool owns)
+ : base (h, owns)
+ {
+ }
+ }
+
+ public class SKXmlStreamWriter : SKXmlWriter
+ {
+ [Preserve]
+ internal SKXmlStreamWriter (IntPtr h, bool owns)
+ : base (h, owns)
+ {
+ }
+
+ public SKXmlStreamWriter (SKWStream stream)
+ : this (IntPtr.Zero, true)
+ {
+ if (stream == null) {
+ throw new ArgumentNullException (nameof (stream));
+ }
+
+ Handle = SkiaApi.sk_xmlstreamwriter_new (stream.Handle);
+ }
+
+ protected override void Dispose (bool disposing) =>
+ base.Dispose (disposing);
+
+ protected override void DisposeNative () =>
+ SkiaApi.sk_xmlstreamwriter_delete (Handle);
+ }
+}
--- /dev/null
+namespace SkiaSharp
+{
+ internal partial class SkiaApi
+ {
+ private const string SKIA = "libSkiaSharp.1.68.2.so";
+ }
+}
--- /dev/null
+using System;
+using System.Runtime.InteropServices;
+
+namespace SkiaSharp
+{
+ #region Class declarations
+
+ using gr_backendrendertarget_t = IntPtr;
+ using gr_backendtexture_t = IntPtr;
+ using gr_context_t = IntPtr;
+ using gr_glinterface_t = IntPtr;
+ using sk_3dview_t = IntPtr;
+ using sk_bitmap_t = IntPtr;
+ using sk_canvas_t = IntPtr;
+ using sk_codec_t = IntPtr;
+ using sk_colorfilter_t = IntPtr;
+ using sk_colorspace_t = IntPtr;
+ using sk_colortable_t = IntPtr;
+ using sk_data_t = IntPtr;
+ using sk_document_t = IntPtr;
+ using sk_drawable_t = IntPtr;
+ using sk_fontmgr_t = IntPtr;
+ using sk_fontstyle_t = IntPtr;
+ using sk_fontstyleset_t = IntPtr;
+ using sk_image_t = IntPtr;
+ using sk_imagefilter_croprect_t = IntPtr;
+ using sk_imagefilter_t = IntPtr;
+ using sk_manageddrawable_t = IntPtr;
+ using sk_maskfilter_t = IntPtr;
+ using sk_matrix44_t = IntPtr;
+ using sk_nodraw_canvas_t = IntPtr;
+ using sk_nvrefcnt_t = IntPtr;
+ using sk_nway_canvas_t = IntPtr;
+ using sk_opbuilder_t = IntPtr;
+ using sk_overdraw_canvas_t = IntPtr;
+ using sk_paint_t = IntPtr;
+ using sk_path_effect_t = IntPtr;
+ using sk_path_iterator_t = IntPtr;
+ using sk_path_rawiterator_t = IntPtr;
+ using sk_path_t = IntPtr;
+ using sk_pathmeasure_t = IntPtr;
+ using sk_picture_recorder_t = IntPtr;
+ using sk_picture_t = IntPtr;
+ using sk_pixelref_factory_t = IntPtr;
+ using sk_pixmap_t = IntPtr;
+ using sk_refcnt_t = IntPtr;
+ using sk_region_cliperator_t = IntPtr;
+ using sk_region_iterator_t = IntPtr;
+ using sk_region_spanerator_t = IntPtr;
+ using sk_region_t = IntPtr;
+ using sk_rrect_t = IntPtr;
+ using sk_shader_t = IntPtr;
+ using sk_stream_asset_t = IntPtr;
+ using sk_stream_filestream_t = IntPtr;
+ using sk_stream_managedstream_t = IntPtr;
+ using sk_stream_memorystream_t = IntPtr;
+ using sk_stream_streamrewindable_t = IntPtr;
+ using sk_stream_t = IntPtr;
+ using sk_string_t = IntPtr;
+ using sk_surface_t = IntPtr;
+ using sk_surfaceprops_t = IntPtr;
+ using sk_svgcanvas_t = IntPtr;
+ using sk_textblob_builder_t = IntPtr;
+ using sk_textblob_t = IntPtr;
+ using sk_typeface_t = IntPtr;
+ using sk_vertices_t = IntPtr;
+ using sk_wstream_dynamicmemorystream_t = IntPtr;
+ using sk_wstream_filestream_t = IntPtr;
+ using sk_wstream_managedstream_t = IntPtr;
+ using sk_wstream_t = IntPtr;
+ using sk_xmlstreamwriter_t = IntPtr;
+ using sk_xmlwriter_t = IntPtr;
+
+ #endregion
+
+ internal unsafe partial class SkiaApi
+ {
+ #region gr_context.h
+
+ // void gr_backendrendertarget_delete(gr_backendrendertarget_t* rendertarget)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_backendrendertarget_delete (gr_backendrendertarget_t rendertarget);
+
+ // gr_backend_t gr_backendrendertarget_get_backend(const gr_backendrendertarget_t* rendertarget)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern GRBackend gr_backendrendertarget_get_backend (gr_backendrendertarget_t rendertarget);
+
+ // bool gr_backendrendertarget_get_gl_framebufferinfo(const gr_backendrendertarget_t* rendertarget, gr_gl_framebufferinfo_t* glInfo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool gr_backendrendertarget_get_gl_framebufferinfo (gr_backendrendertarget_t rendertarget, GRGlFramebufferInfo* glInfo);
+
+ // int gr_backendrendertarget_get_height(const gr_backendrendertarget_t* rendertarget)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 gr_backendrendertarget_get_height (gr_backendrendertarget_t rendertarget);
+
+ // int gr_backendrendertarget_get_samples(const gr_backendrendertarget_t* rendertarget)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 gr_backendrendertarget_get_samples (gr_backendrendertarget_t rendertarget);
+
+ // int gr_backendrendertarget_get_stencils(const gr_backendrendertarget_t* rendertarget)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 gr_backendrendertarget_get_stencils (gr_backendrendertarget_t rendertarget);
+
+ // int gr_backendrendertarget_get_width(const gr_backendrendertarget_t* rendertarget)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 gr_backendrendertarget_get_width (gr_backendrendertarget_t rendertarget);
+
+ // bool gr_backendrendertarget_is_valid(const gr_backendrendertarget_t* rendertarget)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool gr_backendrendertarget_is_valid (gr_backendrendertarget_t rendertarget);
+
+ // gr_backendrendertarget_t* gr_backendrendertarget_new_gl(int width, int height, int samples, int stencils, const gr_gl_framebufferinfo_t* glInfo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern gr_backendrendertarget_t gr_backendrendertarget_new_gl (Int32 width, Int32 height, Int32 samples, Int32 stencils, GRGlFramebufferInfo* glInfo);
+
+ // void gr_backendtexture_delete(gr_backendtexture_t* texture)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_backendtexture_delete (gr_backendtexture_t texture);
+
+ // gr_backend_t gr_backendtexture_get_backend(const gr_backendtexture_t* texture)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern GRBackend gr_backendtexture_get_backend (gr_backendtexture_t texture);
+
+ // bool gr_backendtexture_get_gl_textureinfo(const gr_backendtexture_t* texture, gr_gl_textureinfo_t* glInfo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool gr_backendtexture_get_gl_textureinfo (gr_backendtexture_t texture, GRGlTextureInfo* glInfo);
+
+ // int gr_backendtexture_get_height(const gr_backendtexture_t* texture)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 gr_backendtexture_get_height (gr_backendtexture_t texture);
+
+ // int gr_backendtexture_get_width(const gr_backendtexture_t* texture)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 gr_backendtexture_get_width (gr_backendtexture_t texture);
+
+ // bool gr_backendtexture_has_mipmaps(const gr_backendtexture_t* texture)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool gr_backendtexture_has_mipmaps (gr_backendtexture_t texture);
+
+ // bool gr_backendtexture_is_valid(const gr_backendtexture_t* texture)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool gr_backendtexture_is_valid (gr_backendtexture_t texture);
+
+ // gr_backendtexture_t* gr_backendtexture_new_gl(int width, int height, bool mipmapped, const gr_gl_textureinfo_t* glInfo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern gr_backendtexture_t gr_backendtexture_new_gl (Int32 width, Int32 height, [MarshalAs (UnmanagedType.I1)] bool mipmapped, GRGlTextureInfo* glInfo);
+
+ // void gr_context_abandon_context(gr_context_t* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_context_abandon_context (gr_context_t context);
+
+ // void gr_context_flush(gr_context_t* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_context_flush (gr_context_t context);
+
+ // gr_backend_t gr_context_get_backend(gr_context_t* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern GRBackend gr_context_get_backend (gr_context_t context);
+
+ // int gr_context_get_max_surface_sample_count_for_color_type(gr_context_t* context, sk_colortype_t colorType)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 gr_context_get_max_surface_sample_count_for_color_type (gr_context_t context, SKColorType colorType);
+
+ // void gr_context_get_resource_cache_limits(gr_context_t* context, int* maxResources, size_t* maxResourceBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_context_get_resource_cache_limits (gr_context_t context, Int32* maxResources, /* size_t */ IntPtr* maxResourceBytes);
+
+ // void gr_context_get_resource_cache_usage(gr_context_t* context, int* maxResources, size_t* maxResourceBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_context_get_resource_cache_usage (gr_context_t context, Int32* maxResources, /* size_t */ IntPtr* maxResourceBytes);
+
+ // gr_context_t* gr_context_make_gl(const gr_glinterface_t* glInterface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern gr_context_t gr_context_make_gl (gr_glinterface_t glInterface);
+
+ // void gr_context_release_resources_and_abandon_context(gr_context_t* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_context_release_resources_and_abandon_context (gr_context_t context);
+
+ // void gr_context_reset_context(gr_context_t* context, uint32_t state)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_context_reset_context (gr_context_t context, UInt32 state);
+
+ // void gr_context_set_resource_cache_limits(gr_context_t* context, int maxResources, size_t maxResourceBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_context_set_resource_cache_limits (gr_context_t context, Int32 maxResources, /* size_t */ IntPtr maxResourceBytes);
+
+ // void gr_context_unref(gr_context_t* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_context_unref (gr_context_t context);
+
+ // const gr_glinterface_t* gr_glinterface_assemble_gl_interface(void* ctx, gr_gl_get_proc get)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern gr_glinterface_t gr_glinterface_assemble_gl_interface (void* ctx, GRGlGetProcProxyDelegate get);
+
+ // const gr_glinterface_t* gr_glinterface_assemble_gles_interface(void* ctx, gr_gl_get_proc get)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern gr_glinterface_t gr_glinterface_assemble_gles_interface (void* ctx, GRGlGetProcProxyDelegate get);
+
+ // const gr_glinterface_t* gr_glinterface_assemble_interface(void* ctx, gr_gl_get_proc get)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern gr_glinterface_t gr_glinterface_assemble_interface (void* ctx, GRGlGetProcProxyDelegate get);
+
+ // const gr_glinterface_t* gr_glinterface_create_native_interface()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern gr_glinterface_t gr_glinterface_create_native_interface ();
+
+ // bool gr_glinterface_has_extension(const gr_glinterface_t* glInterface, const char* extension)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool gr_glinterface_has_extension (gr_glinterface_t glInterface, [MarshalAs (UnmanagedType.LPStr)] String extension);
+
+ // void gr_glinterface_unref(const gr_glinterface_t* glInterface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void gr_glinterface_unref (gr_glinterface_t glInterface);
+
+ // bool gr_glinterface_validate(const gr_glinterface_t* glInterface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool gr_glinterface_validate (gr_glinterface_t glInterface);
+
+ #endregion
+
+ #region sk_bitmap.h
+
+ // void sk_bitmap_destructor(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_destructor (sk_bitmap_t cbitmap);
+
+ // void sk_bitmap_erase(sk_bitmap_t* cbitmap, sk_color_t color)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_erase (sk_bitmap_t cbitmap, UInt32 color);
+
+ // void sk_bitmap_erase_rect(sk_bitmap_t* cbitmap, sk_color_t color, sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_erase_rect (sk_bitmap_t cbitmap, UInt32 color, SKRectI* rect);
+
+ // bool sk_bitmap_extract_alpha(sk_bitmap_t* cbitmap, sk_bitmap_t* dst, const sk_paint_t* paint, sk_ipoint_t* offset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_extract_alpha (sk_bitmap_t cbitmap, sk_bitmap_t dst, sk_paint_t paint, SKPointI* offset);
+
+ // bool sk_bitmap_extract_subset(sk_bitmap_t* cbitmap, sk_bitmap_t* dst, sk_irect_t* subset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_extract_subset (sk_bitmap_t cbitmap, sk_bitmap_t dst, SKRectI* subset);
+
+ // void* sk_bitmap_get_addr(sk_bitmap_t* cbitmap, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void* sk_bitmap_get_addr (sk_bitmap_t cbitmap, Int32 x, Int32 y);
+
+ // uint16_t sk_bitmap_get_addr_16(sk_bitmap_t* cbitmap, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt16 sk_bitmap_get_addr_16 (sk_bitmap_t cbitmap, Int32 x, Int32 y);
+
+ // uint32_t sk_bitmap_get_addr_32(sk_bitmap_t* cbitmap, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_bitmap_get_addr_32 (sk_bitmap_t cbitmap, Int32 x, Int32 y);
+
+ // uint8_t sk_bitmap_get_addr_8(sk_bitmap_t* cbitmap, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Byte sk_bitmap_get_addr_8 (sk_bitmap_t cbitmap, Int32 x, Int32 y);
+
+ // size_t sk_bitmap_get_byte_count(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_bitmap_get_byte_count (sk_bitmap_t cbitmap);
+
+ // void sk_bitmap_get_info(sk_bitmap_t* cbitmap, sk_imageinfo_t* info)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_get_info (sk_bitmap_t cbitmap, SKImageInfoNative* info);
+
+ // sk_color_t sk_bitmap_get_pixel_color(sk_bitmap_t* cbitmap, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_bitmap_get_pixel_color (sk_bitmap_t cbitmap, Int32 x, Int32 y);
+
+ // void sk_bitmap_get_pixel_colors(sk_bitmap_t* cbitmap, sk_color_t* colors)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_get_pixel_colors (sk_bitmap_t cbitmap, UInt32* colors);
+
+ // void* sk_bitmap_get_pixels(sk_bitmap_t* cbitmap, size_t* length)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void* sk_bitmap_get_pixels (sk_bitmap_t cbitmap, /* size_t */ IntPtr* length);
+
+ // size_t sk_bitmap_get_row_bytes(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_bitmap_get_row_bytes (sk_bitmap_t cbitmap);
+
+ // bool sk_bitmap_install_mask_pixels(sk_bitmap_t* cbitmap, const sk_mask_t* cmask)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_install_mask_pixels (sk_bitmap_t cbitmap, SKMask* cmask);
+
+ // bool sk_bitmap_install_pixels(sk_bitmap_t* cbitmap, const sk_imageinfo_t* cinfo, void* pixels, size_t rowBytes, const sk_bitmap_release_proc releaseProc, void* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_install_pixels (sk_bitmap_t cbitmap, SKImageInfoNative* cinfo, void* pixels, /* size_t */ IntPtr rowBytes, SKBitmapReleaseProxyDelegate releaseProc, void* context);
+
+ // bool sk_bitmap_install_pixels_with_pixmap(sk_bitmap_t* cbitmap, const sk_pixmap_t* cpixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_install_pixels_with_pixmap (sk_bitmap_t cbitmap, sk_pixmap_t cpixmap);
+
+ // bool sk_bitmap_is_immutable(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_is_immutable (sk_bitmap_t cbitmap);
+
+ // bool sk_bitmap_is_null(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_is_null (sk_bitmap_t cbitmap);
+
+ // bool sk_bitmap_is_volatile(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_is_volatile (sk_bitmap_t cbitmap);
+
+ // sk_bitmap_t* sk_bitmap_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_bitmap_t sk_bitmap_new ();
+
+ // void sk_bitmap_notify_pixels_changed(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_notify_pixels_changed (sk_bitmap_t cbitmap);
+
+ // bool sk_bitmap_peek_pixels(sk_bitmap_t* cbitmap, sk_pixmap_t* cpixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_peek_pixels (sk_bitmap_t cbitmap, sk_pixmap_t cpixmap);
+
+ // bool sk_bitmap_ready_to_draw(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_ready_to_draw (sk_bitmap_t cbitmap);
+
+ // void sk_bitmap_reset(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_reset (sk_bitmap_t cbitmap);
+
+ // void sk_bitmap_set_immutable(sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_set_immutable (sk_bitmap_t cbitmap);
+
+ // void sk_bitmap_set_pixel_color(sk_bitmap_t* cbitmap, int x, int y, sk_color_t color)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_set_pixel_color (sk_bitmap_t cbitmap, Int32 x, Int32 y, UInt32 color);
+
+ // void sk_bitmap_set_pixel_colors(sk_bitmap_t* cbitmap, const sk_color_t* colors)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_set_pixel_colors (sk_bitmap_t cbitmap, UInt32* colors);
+
+ // void sk_bitmap_set_pixels(sk_bitmap_t* cbitmap, void* pixels)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_set_pixels (sk_bitmap_t cbitmap, void* pixels);
+
+ // void sk_bitmap_set_volatile(sk_bitmap_t* cbitmap, bool value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_set_volatile (sk_bitmap_t cbitmap, [MarshalAs (UnmanagedType.I1)] bool value);
+
+ // void sk_bitmap_swap(sk_bitmap_t* cbitmap, sk_bitmap_t* cother)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_bitmap_swap (sk_bitmap_t cbitmap, sk_bitmap_t cother);
+
+ // bool sk_bitmap_try_alloc_pixels(sk_bitmap_t* cbitmap, const sk_imageinfo_t* requestedInfo, size_t rowBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_try_alloc_pixels (sk_bitmap_t cbitmap, SKImageInfoNative* requestedInfo, /* size_t */ IntPtr rowBytes);
+
+ // bool sk_bitmap_try_alloc_pixels_with_flags(sk_bitmap_t* cbitmap, const sk_imageinfo_t* requestedInfo, uint32_t flags)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_bitmap_try_alloc_pixels_with_flags (sk_bitmap_t cbitmap, SKImageInfoNative* requestedInfo, UInt32 flags);
+
+ #endregion
+
+ #region sk_canvas.h
+
+ // void sk_canvas_clear(sk_canvas_t*, sk_color_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_clear (sk_canvas_t param0, UInt32 param1);
+
+ // void sk_canvas_clip_path_with_operation(sk_canvas_t* t, const sk_path_t* crect, sk_clipop_t op, bool doAA)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_clip_path_with_operation (sk_canvas_t t, sk_path_t crect, SKClipOperation op, [MarshalAs (UnmanagedType.I1)] bool doAA);
+
+ // void sk_canvas_clip_rect_with_operation(sk_canvas_t* t, const sk_rect_t* crect, sk_clipop_t op, bool doAA)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_clip_rect_with_operation (sk_canvas_t t, SKRect* crect, SKClipOperation op, [MarshalAs (UnmanagedType.I1)] bool doAA);
+
+ // void sk_canvas_clip_region(sk_canvas_t* canvas, const sk_region_t* region, sk_clipop_t op)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_clip_region (sk_canvas_t canvas, sk_region_t region, SKClipOperation op);
+
+ // void sk_canvas_clip_rrect_with_operation(sk_canvas_t* t, const sk_rrect_t* crect, sk_clipop_t op, bool doAA)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_clip_rrect_with_operation (sk_canvas_t t, sk_rrect_t crect, SKClipOperation op, [MarshalAs (UnmanagedType.I1)] bool doAA);
+
+ // void sk_canvas_concat(sk_canvas_t*, const sk_matrix_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_concat (sk_canvas_t param0, SKMatrix* param1);
+
+ // void sk_canvas_destroy(sk_canvas_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_destroy (sk_canvas_t param0);
+
+ // void sk_canvas_discard(sk_canvas_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_discard (sk_canvas_t param0);
+
+ // void sk_canvas_draw_annotation(sk_canvas_t* t, const sk_rect_t* rect, const char* key, sk_data_t* value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_annotation (sk_canvas_t t, SKRect* rect, /* char */ void* key, sk_data_t value);
+
+ // void sk_canvas_draw_arc(sk_canvas_t* ccanvas, const sk_rect_t* oval, float startAngle, float sweepAngle, bool useCenter, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_arc (sk_canvas_t ccanvas, SKRect* oval, Single startAngle, Single sweepAngle, [MarshalAs (UnmanagedType.I1)] bool useCenter, sk_paint_t paint);
+
+ // void sk_canvas_draw_atlas(sk_canvas_t* ccanvas, const sk_image_t* atlas, const sk_rsxform_t* xform, const sk_rect_t* tex, const sk_color_t* colors, int count, sk_blendmode_t mode, const sk_rect_t* cullRect, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_atlas (sk_canvas_t ccanvas, sk_image_t atlas, SKRotationScaleMatrix* xform, SKRect* tex, UInt32* colors, Int32 count, SKBlendMode mode, SKRect* cullRect, sk_paint_t paint);
+
+ // void sk_canvas_draw_bitmap(sk_canvas_t* ccanvas, const sk_bitmap_t* bitmap, float left, float top, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_bitmap (sk_canvas_t ccanvas, sk_bitmap_t bitmap, Single left, Single top, sk_paint_t paint);
+
+ // void sk_canvas_draw_bitmap_lattice(sk_canvas_t* t, const sk_bitmap_t* bitmap, const sk_lattice_t* lattice, const sk_rect_t* dst, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_bitmap_lattice (sk_canvas_t t, sk_bitmap_t bitmap, SKLatticeInternal* lattice, SKRect* dst, sk_paint_t paint);
+
+ // void sk_canvas_draw_bitmap_nine(sk_canvas_t* t, const sk_bitmap_t* bitmap, const sk_irect_t* center, const sk_rect_t* dst, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_bitmap_nine (sk_canvas_t t, sk_bitmap_t bitmap, SKRectI* center, SKRect* dst, sk_paint_t paint);
+
+ // void sk_canvas_draw_bitmap_rect(sk_canvas_t* ccanvas, const sk_bitmap_t* bitmap, const sk_rect_t* src, const sk_rect_t* dst, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_bitmap_rect (sk_canvas_t ccanvas, sk_bitmap_t bitmap, SKRect* src, SKRect* dst, sk_paint_t paint);
+
+ // void sk_canvas_draw_circle(sk_canvas_t*, float cx, float cy, float rad, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_circle (sk_canvas_t param0, Single cx, Single cy, Single rad, sk_paint_t param4);
+
+ // void sk_canvas_draw_color(sk_canvas_t* ccanvas, sk_color_t color, sk_blendmode_t mode)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_color (sk_canvas_t ccanvas, UInt32 color, SKBlendMode mode);
+
+ // void sk_canvas_draw_drawable(sk_canvas_t*, sk_drawable_t*, const sk_matrix_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_drawable (sk_canvas_t param0, sk_drawable_t param1, SKMatrix* param2);
+
+ // void sk_canvas_draw_drrect(sk_canvas_t* ccanvas, const sk_rrect_t* outer, const sk_rrect_t* inner, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_drrect (sk_canvas_t ccanvas, sk_rrect_t outer, sk_rrect_t inner, sk_paint_t paint);
+
+ // void sk_canvas_draw_image(sk_canvas_t*, const sk_image_t*, float x, float y, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_image (sk_canvas_t param0, sk_image_t param1, Single x, Single y, sk_paint_t param4);
+
+ // void sk_canvas_draw_image_lattice(sk_canvas_t* t, const sk_image_t* image, const sk_lattice_t* lattice, const sk_rect_t* dst, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_image_lattice (sk_canvas_t t, sk_image_t image, SKLatticeInternal* lattice, SKRect* dst, sk_paint_t paint);
+
+ // void sk_canvas_draw_image_nine(sk_canvas_t* t, const sk_image_t* image, const sk_irect_t* center, const sk_rect_t* dst, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_image_nine (sk_canvas_t t, sk_image_t image, SKRectI* center, SKRect* dst, sk_paint_t paint);
+
+ // void sk_canvas_draw_image_rect(sk_canvas_t*, const sk_image_t*, const sk_rect_t* src, const sk_rect_t* dst, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_image_rect (sk_canvas_t param0, sk_image_t param1, SKRect* src, SKRect* dst, sk_paint_t param4);
+
+ // void sk_canvas_draw_line(sk_canvas_t* ccanvas, float x0, float y0, float x1, float y1, sk_paint_t* cpaint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_line (sk_canvas_t ccanvas, Single x0, Single y0, Single x1, Single y1, sk_paint_t cpaint);
+
+ // void sk_canvas_draw_link_destination_annotation(sk_canvas_t* t, const sk_rect_t* rect, sk_data_t* value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_link_destination_annotation (sk_canvas_t t, SKRect* rect, sk_data_t value);
+
+ // void sk_canvas_draw_named_destination_annotation(sk_canvas_t* t, const sk_point_t* point, sk_data_t* value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_named_destination_annotation (sk_canvas_t t, SKPoint* point, sk_data_t value);
+
+ // void sk_canvas_draw_oval(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_oval (sk_canvas_t param0, SKRect* param1, sk_paint_t param2);
+
+ // void sk_canvas_draw_paint(sk_canvas_t*, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_paint (sk_canvas_t param0, sk_paint_t param1);
+
+ // void sk_canvas_draw_patch(sk_canvas_t* ccanvas, const sk_point_t* cubics, const sk_color_t* colors, const sk_point_t* texCoords, sk_blendmode_t mode, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_patch (sk_canvas_t ccanvas, SKPoint* cubics, UInt32* colors, SKPoint* texCoords, SKBlendMode mode, sk_paint_t paint);
+
+ // void sk_canvas_draw_path(sk_canvas_t*, const sk_path_t*, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_path (sk_canvas_t param0, sk_path_t param1, sk_paint_t param2);
+
+ // void sk_canvas_draw_picture(sk_canvas_t*, const sk_picture_t*, const sk_matrix_t*, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_picture (sk_canvas_t param0, sk_picture_t param1, SKMatrix* param2, sk_paint_t param3);
+
+ // void sk_canvas_draw_point(sk_canvas_t*, float, float, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_point (sk_canvas_t param0, Single param1, Single param2, sk_paint_t param3);
+
+ // void sk_canvas_draw_points(sk_canvas_t*, sk_point_mode_t, size_t, const sk_point_t[-1], const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_points (sk_canvas_t param0, SKPointMode param1, /* size_t */ IntPtr param2, SKPoint* param3, sk_paint_t param4);
+
+ // void sk_canvas_draw_pos_text(sk_canvas_t*, const char* text, size_t byteLength, const sk_point_t[-1], const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_pos_text (sk_canvas_t param0, /* char */ void* text, /* size_t */ IntPtr byteLength, SKPoint* param3, sk_paint_t paint);
+
+ // void sk_canvas_draw_rect(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_rect (sk_canvas_t param0, SKRect* param1, sk_paint_t param2);
+
+ // void sk_canvas_draw_region(sk_canvas_t*, const sk_region_t*, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_region (sk_canvas_t param0, sk_region_t param1, sk_paint_t param2);
+
+ // void sk_canvas_draw_round_rect(sk_canvas_t*, const sk_rect_t*, float rx, float ry, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_round_rect (sk_canvas_t param0, SKRect* param1, Single rx, Single ry, sk_paint_t param4);
+
+ // void sk_canvas_draw_rrect(sk_canvas_t*, const sk_rrect_t*, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_rrect (sk_canvas_t param0, sk_rrect_t param1, sk_paint_t param2);
+
+ // void sk_canvas_draw_text(sk_canvas_t*, const char* text, size_t byteLength, float x, float y, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_text (sk_canvas_t param0, /* char */ void* text, /* size_t */ IntPtr byteLength, Single x, Single y, sk_paint_t paint);
+
+ // void sk_canvas_draw_text_blob(sk_canvas_t*, sk_textblob_t* text, float x, float y, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_text_blob (sk_canvas_t param0, sk_textblob_t text, Single x, Single y, sk_paint_t paint);
+
+ // void sk_canvas_draw_text_on_path(sk_canvas_t*, const char* text, size_t byteLength, const sk_path_t* path, float hOffset, float vOffset, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_text_on_path (sk_canvas_t param0, /* char */ void* text, /* size_t */ IntPtr byteLength, sk_path_t path, Single hOffset, Single vOffset, sk_paint_t paint);
+
+ // void sk_canvas_draw_url_annotation(sk_canvas_t* t, const sk_rect_t* rect, sk_data_t* value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_url_annotation (sk_canvas_t t, SKRect* rect, sk_data_t value);
+
+ // void sk_canvas_draw_vertices(sk_canvas_t* ccanvas, const sk_vertices_t* vertices, sk_blendmode_t mode, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_draw_vertices (sk_canvas_t ccanvas, sk_vertices_t vertices, SKBlendMode mode, sk_paint_t paint);
+
+ // void sk_canvas_flush(sk_canvas_t* ccanvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_flush (sk_canvas_t ccanvas);
+
+ // bool sk_canvas_get_device_clip_bounds(sk_canvas_t* t, sk_irect_t* cbounds)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_canvas_get_device_clip_bounds (sk_canvas_t t, SKRectI* cbounds);
+
+ // bool sk_canvas_get_local_clip_bounds(sk_canvas_t* t, sk_rect_t* cbounds)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_canvas_get_local_clip_bounds (sk_canvas_t t, SKRect* cbounds);
+
+ // int sk_canvas_get_save_count(sk_canvas_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_canvas_get_save_count (sk_canvas_t param0);
+
+ // void sk_canvas_get_total_matrix(sk_canvas_t* ccanvas, sk_matrix_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_get_total_matrix (sk_canvas_t ccanvas, SKMatrix* matrix);
+
+ // bool sk_canvas_is_clip_empty(sk_canvas_t* ccanvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_canvas_is_clip_empty (sk_canvas_t ccanvas);
+
+ // bool sk_canvas_is_clip_rect(sk_canvas_t* ccanvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_canvas_is_clip_rect (sk_canvas_t ccanvas);
+
+ // sk_canvas_t* sk_canvas_new_from_bitmap(const sk_bitmap_t* bitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_canvas_t sk_canvas_new_from_bitmap (sk_bitmap_t bitmap);
+
+ // bool sk_canvas_quick_reject(sk_canvas_t*, const sk_rect_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_canvas_quick_reject (sk_canvas_t param0, SKRect* param1);
+
+ // void sk_canvas_reset_matrix(sk_canvas_t* ccanvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_reset_matrix (sk_canvas_t ccanvas);
+
+ // void sk_canvas_restore(sk_canvas_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_restore (sk_canvas_t param0);
+
+ // void sk_canvas_restore_to_count(sk_canvas_t*, int saveCount)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_restore_to_count (sk_canvas_t param0, Int32 saveCount);
+
+ // void sk_canvas_rotate_degrees(sk_canvas_t*, float degrees)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_rotate_degrees (sk_canvas_t param0, Single degrees);
+
+ // void sk_canvas_rotate_radians(sk_canvas_t*, float radians)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_rotate_radians (sk_canvas_t param0, Single radians);
+
+ // int sk_canvas_save(sk_canvas_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_canvas_save (sk_canvas_t param0);
+
+ // int sk_canvas_save_layer(sk_canvas_t*, const sk_rect_t*, const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_canvas_save_layer (sk_canvas_t param0, SKRect* param1, sk_paint_t param2);
+
+ // void sk_canvas_scale(sk_canvas_t*, float sx, float sy)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_scale (sk_canvas_t param0, Single sx, Single sy);
+
+ // void sk_canvas_set_matrix(sk_canvas_t* ccanvas, const sk_matrix_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_set_matrix (sk_canvas_t ccanvas, SKMatrix* matrix);
+
+ // void sk_canvas_skew(sk_canvas_t*, float sx, float sy)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_skew (sk_canvas_t param0, Single sx, Single sy);
+
+ // void sk_canvas_translate(sk_canvas_t*, float dx, float dy)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_canvas_translate (sk_canvas_t param0, Single dx, Single dy);
+
+ // void sk_nodraw_canvas_destroy(sk_nodraw_canvas_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_nodraw_canvas_destroy (sk_nodraw_canvas_t param0);
+
+ // sk_nodraw_canvas_t* sk_nodraw_canvas_new(int width, int height)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_nodraw_canvas_t sk_nodraw_canvas_new (Int32 width, Int32 height);
+
+ // void sk_nway_canvas_add_canvas(sk_nway_canvas_t*, sk_canvas_t* canvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_nway_canvas_add_canvas (sk_nway_canvas_t param0, sk_canvas_t canvas);
+
+ // void sk_nway_canvas_destroy(sk_nway_canvas_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_nway_canvas_destroy (sk_nway_canvas_t param0);
+
+ // sk_nway_canvas_t* sk_nway_canvas_new(int width, int height)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_nway_canvas_t sk_nway_canvas_new (Int32 width, Int32 height);
+
+ // void sk_nway_canvas_remove_all(sk_nway_canvas_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_nway_canvas_remove_all (sk_nway_canvas_t param0);
+
+ // void sk_nway_canvas_remove_canvas(sk_nway_canvas_t*, sk_canvas_t* canvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_nway_canvas_remove_canvas (sk_nway_canvas_t param0, sk_canvas_t canvas);
+
+ // void sk_overdraw_canvas_destroy(sk_overdraw_canvas_t* canvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_overdraw_canvas_destroy (sk_overdraw_canvas_t canvas);
+
+ // sk_overdraw_canvas_t* sk_overdraw_canvas_new(sk_canvas_t* canvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_overdraw_canvas_t sk_overdraw_canvas_new (sk_canvas_t canvas);
+
+ #endregion
+
+ #region sk_codec.h
+
+ // void sk_codec_destroy(sk_codec_t* codec)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_codec_destroy (sk_codec_t codec);
+
+ // sk_encoded_image_format_t sk_codec_get_encoded_format(sk_codec_t* codec)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKEncodedImageFormat sk_codec_get_encoded_format (sk_codec_t codec);
+
+ // int sk_codec_get_frame_count(sk_codec_t* codec)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_codec_get_frame_count (sk_codec_t codec);
+
+ // void sk_codec_get_frame_info(sk_codec_t* codec, sk_codec_frameinfo_t* frameInfo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_codec_get_frame_info (sk_codec_t codec, SKCodecFrameInfo* frameInfo);
+
+ // bool sk_codec_get_frame_info_for_index(sk_codec_t* codec, int index, sk_codec_frameinfo_t* frameInfo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_codec_get_frame_info_for_index (sk_codec_t codec, Int32 index, SKCodecFrameInfo* frameInfo);
+
+ // void sk_codec_get_info(sk_codec_t* codec, sk_imageinfo_t* info)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_codec_get_info (sk_codec_t codec, SKImageInfoNative* info);
+
+ // sk_encodedorigin_t sk_codec_get_origin(sk_codec_t* codec)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKEncodedOrigin sk_codec_get_origin (sk_codec_t codec);
+
+ // sk_codec_result_t sk_codec_get_pixels(sk_codec_t* codec, const sk_imageinfo_t* info, void* pixels, size_t rowBytes, const sk_codec_options_t* options)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKCodecResult sk_codec_get_pixels (sk_codec_t codec, SKImageInfoNative* info, void* pixels, /* size_t */ IntPtr rowBytes, SKCodecOptionsInternal* options);
+
+ // int sk_codec_get_repetition_count(sk_codec_t* codec)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_codec_get_repetition_count (sk_codec_t codec);
+
+ // void sk_codec_get_scaled_dimensions(sk_codec_t* codec, float desiredScale, sk_isize_t* dimensions)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_codec_get_scaled_dimensions (sk_codec_t codec, Single desiredScale, SKSizeI* dimensions);
+
+ // sk_codec_scanline_order_t sk_codec_get_scanline_order(sk_codec_t* codec)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKCodecScanlineOrder sk_codec_get_scanline_order (sk_codec_t codec);
+
+ // int sk_codec_get_scanlines(sk_codec_t* codec, void* dst, int countLines, size_t rowBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_codec_get_scanlines (sk_codec_t codec, void* dst, Int32 countLines, /* size_t */ IntPtr rowBytes);
+
+ // bool sk_codec_get_valid_subset(sk_codec_t* codec, sk_irect_t* desiredSubset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_codec_get_valid_subset (sk_codec_t codec, SKRectI* desiredSubset);
+
+ // sk_codec_result_t sk_codec_incremental_decode(sk_codec_t* codec, int* rowsDecoded)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKCodecResult sk_codec_incremental_decode (sk_codec_t codec, Int32* rowsDecoded);
+
+ // size_t sk_codec_min_buffered_bytes_needed()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_codec_min_buffered_bytes_needed ();
+
+ // sk_codec_t* sk_codec_new_from_data(sk_data_t* data)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_codec_t sk_codec_new_from_data (sk_data_t data);
+
+ // sk_codec_t* sk_codec_new_from_stream(sk_stream_t* stream, sk_codec_result_t* result)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_codec_t sk_codec_new_from_stream (sk_stream_t stream, SKCodecResult* result);
+
+ // int sk_codec_next_scanline(sk_codec_t* codec)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_codec_next_scanline (sk_codec_t codec);
+
+ // int sk_codec_output_scanline(sk_codec_t* codec, int inputScanline)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_codec_output_scanline (sk_codec_t codec, Int32 inputScanline);
+
+ // bool sk_codec_skip_scanlines(sk_codec_t* codec, int countLines)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_codec_skip_scanlines (sk_codec_t codec, Int32 countLines);
+
+ // sk_codec_result_t sk_codec_start_incremental_decode(sk_codec_t* codec, const sk_imageinfo_t* info, void* pixels, size_t rowBytes, const sk_codec_options_t* options)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKCodecResult sk_codec_start_incremental_decode (sk_codec_t codec, SKImageInfoNative* info, void* pixels, /* size_t */ IntPtr rowBytes, SKCodecOptionsInternal* options);
+
+ // sk_codec_result_t sk_codec_start_scanline_decode(sk_codec_t* codec, const sk_imageinfo_t* info, const sk_codec_options_t* options)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKCodecResult sk_codec_start_scanline_decode (sk_codec_t codec, SKImageInfoNative* info, SKCodecOptionsInternal* options);
+
+ #endregion
+
+ #region sk_colorfilter.h
+
+ // sk_colorfilter_t* sk_colorfilter_new_color_matrix(const float[20] array = 20)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_colorfilter_new_color_matrix (Single* array);
+
+ // sk_colorfilter_t* sk_colorfilter_new_compose(sk_colorfilter_t* outer, sk_colorfilter_t* inner)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_colorfilter_new_compose (sk_colorfilter_t outer, sk_colorfilter_t inner);
+
+ // sk_colorfilter_t* sk_colorfilter_new_high_contrast(const sk_highcontrastconfig_t* config)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_colorfilter_new_high_contrast (SKHighContrastConfig* config);
+
+ // sk_colorfilter_t* sk_colorfilter_new_lighting(sk_color_t mul, sk_color_t add)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_colorfilter_new_lighting (UInt32 mul, UInt32 add);
+
+ // sk_colorfilter_t* sk_colorfilter_new_luma_color()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_colorfilter_new_luma_color ();
+
+ // sk_colorfilter_t* sk_colorfilter_new_mode(sk_color_t c, sk_blendmode_t mode)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_colorfilter_new_mode (UInt32 c, SKBlendMode mode);
+
+ // sk_colorfilter_t* sk_colorfilter_new_table(const uint8_t[256] table = 256)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_colorfilter_new_table (Byte* table);
+
+ // sk_colorfilter_t* sk_colorfilter_new_table_argb(const uint8_t[256] tableA = 256, const uint8_t[256] tableR = 256, const uint8_t[256] tableG = 256, const uint8_t[256] tableB = 256)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_colorfilter_new_table_argb (Byte* tableA, Byte* tableR, Byte* tableG, Byte* tableB);
+
+ // void sk_colorfilter_unref(sk_colorfilter_t* filter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_colorfilter_unref (sk_colorfilter_t filter);
+
+ #endregion
+
+ #region sk_colorspace.h
+
+ // void sk_color4f_from_color(sk_color_t color, sk_color4f_t* color4f)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_color4f_from_color (UInt32 color, SKColorF* color4f);
+
+ // void sk_color4f_pin(const sk_color4f_t* color4f, sk_color4f_t* pinned)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_color4f_pin (SKColorF* color4f, SKColorF* pinned);
+
+ // sk_color_t sk_color4f_to_color(const sk_color4f_t* color4f)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_color4f_to_color (SKColorF* color4f);
+
+ // const sk_matrix44_t* sk_colorspace_as_from_xyzd50(const sk_colorspace_t* cColorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_matrix44_t sk_colorspace_as_from_xyzd50 (sk_colorspace_t cColorSpace);
+
+ // const sk_matrix44_t* sk_colorspace_as_to_xyzd50(const sk_colorspace_t* cColorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_matrix44_t sk_colorspace_as_to_xyzd50 (sk_colorspace_t cColorSpace);
+
+ // bool sk_colorspace_equals(const sk_colorspace_t* src, const sk_colorspace_t* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_colorspace_equals (sk_colorspace_t src, sk_colorspace_t dst);
+
+ // bool sk_colorspace_gamma_close_to_srgb(const sk_colorspace_t* cColorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_colorspace_gamma_close_to_srgb (sk_colorspace_t cColorSpace);
+
+ // sk_gamma_named_t sk_colorspace_gamma_get_gamma_named(const sk_colorspace_t* cColorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKNamedGamma sk_colorspace_gamma_get_gamma_named (sk_colorspace_t cColorSpace);
+
+ // sk_colorspace_type_t sk_colorspace_gamma_get_type(const sk_colorspace_t* cColorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKColorSpaceType sk_colorspace_gamma_get_type (sk_colorspace_t cColorSpace);
+
+ // bool sk_colorspace_gamma_is_linear(const sk_colorspace_t* cColorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_colorspace_gamma_is_linear (sk_colorspace_t cColorSpace);
+
+ // bool sk_colorspace_is_numerical_transfer_fn(const sk_colorspace_t* cColorSpace, sk_colorspace_transfer_fn_t* fn)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_colorspace_is_numerical_transfer_fn (sk_colorspace_t cColorSpace, SKColorSpaceTransferFn* fn);
+
+ // bool sk_colorspace_is_srgb(const sk_colorspace_t* cColorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_colorspace_is_srgb (sk_colorspace_t cColorSpace);
+
+ // sk_colorspace_t* sk_colorspace_new_icc(const void* input, size_t len)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_icc (void* input, /* size_t */ IntPtr len);
+
+ // sk_colorspace_t* sk_colorspace_new_rgb_with_coeffs(const sk_colorspace_transfer_fn_t* coeffs, const sk_matrix44_t* toXYZD50)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_rgb_with_coeffs (SKColorSpaceTransferFn* coeffs, sk_matrix44_t toXYZD50);
+
+ // sk_colorspace_t* sk_colorspace_new_rgb_with_coeffs_and_gamut(const sk_colorspace_transfer_fn_t* coeffs, sk_colorspace_gamut_t gamut)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_rgb_with_coeffs_and_gamut (SKColorSpaceTransferFn* coeffs, SKColorSpaceGamut gamut);
+
+ // sk_colorspace_t* sk_colorspace_new_rgb_with_gamma(sk_colorspace_render_target_gamma_t gamma, const sk_matrix44_t* toXYZD50)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_rgb_with_gamma (SKColorSpaceRenderTargetGamma gamma, sk_matrix44_t toXYZD50);
+
+ // sk_colorspace_t* sk_colorspace_new_rgb_with_gamma_and_gamut(sk_colorspace_render_target_gamma_t gamma, sk_colorspace_gamut_t gamut)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_rgb_with_gamma_and_gamut (SKColorSpaceRenderTargetGamma gamma, SKColorSpaceGamut gamut);
+
+ // sk_colorspace_t* sk_colorspace_new_rgb_with_gamma_named(sk_gamma_named_t gamma, const sk_matrix44_t* toXYZD50)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_rgb_with_gamma_named (SKNamedGamma gamma, sk_matrix44_t toXYZD50);
+
+ // sk_colorspace_t* sk_colorspace_new_rgb_with_gamma_named_and_gamut(sk_gamma_named_t gamma, sk_colorspace_gamut_t gamut)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_rgb_with_gamma_named_and_gamut (SKNamedGamma gamma, SKColorSpaceGamut gamut);
+
+ // sk_colorspace_t* sk_colorspace_new_srgb()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_srgb ();
+
+ // sk_colorspace_t* sk_colorspace_new_srgb_linear()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_colorspace_new_srgb_linear ();
+
+ // bool sk_colorspace_to_xyzd50(const sk_colorspace_t* cColorSpace, sk_matrix44_t* toXYZD50)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_colorspace_to_xyzd50 (sk_colorspace_t cColorSpace, sk_matrix44_t toXYZD50);
+
+ // void sk_colorspace_transfer_fn_invert(const sk_colorspace_transfer_fn_t* transfer, sk_colorspace_transfer_fn_t* inverted)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_colorspace_transfer_fn_invert (SKColorSpaceTransferFn* transfer, SKColorSpaceTransferFn* inverted);
+
+ // float sk_colorspace_transfer_fn_transform(const sk_colorspace_transfer_fn_t* transfer, float x)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_colorspace_transfer_fn_transform (SKColorSpaceTransferFn* transfer, Single x);
+
+ // void sk_colorspace_unref(sk_colorspace_t* cColorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_colorspace_unref (sk_colorspace_t cColorSpace);
+
+ // bool sk_colorspaceprimaries_to_xyzd50(const sk_colorspaceprimaries_t* primaries, sk_matrix44_t* toXYZD50)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_colorspaceprimaries_to_xyzd50 (SKColorSpacePrimaries* primaries, sk_matrix44_t toXYZD50);
+
+ #endregion
+
+ #region sk_colortable.h
+
+ // int sk_colortable_count(const sk_colortable_t* ctable)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_colortable_count (sk_colortable_t ctable);
+
+ // sk_colortable_t* sk_colortable_new(const sk_pmcolor_t* colors, int count)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colortable_t sk_colortable_new (UInt32* colors, Int32 count);
+
+ // void sk_colortable_read_colors(const sk_colortable_t* ctable, sk_pmcolor_t** colors)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_colortable_read_colors (sk_colortable_t ctable, UInt32** colors);
+
+ // void sk_colortable_unref(sk_colortable_t* ctable)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_colortable_unref (sk_colortable_t ctable);
+
+ #endregion
+
+ #region sk_data.h
+
+ // const uint8_t* sk_data_get_bytes(const sk_data_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Byte* sk_data_get_bytes (sk_data_t param0);
+
+ // const void* sk_data_get_data(const sk_data_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void* sk_data_get_data (sk_data_t param0);
+
+ // size_t sk_data_get_size(const sk_data_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_data_get_size (sk_data_t param0);
+
+ // sk_data_t* sk_data_new_empty()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_data_new_empty ();
+
+ // sk_data_t* sk_data_new_from_file(const char* path)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_data_new_from_file (/* char */ void* path);
+
+ // sk_data_t* sk_data_new_from_stream(sk_stream_t* stream, size_t length)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_data_new_from_stream (sk_stream_t stream, /* size_t */ IntPtr length);
+
+ // sk_data_t* sk_data_new_subset(const sk_data_t* src, size_t offset, size_t length)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_data_new_subset (sk_data_t src, /* size_t */ IntPtr offset, /* size_t */ IntPtr length);
+
+ // sk_data_t* sk_data_new_uninitialized(size_t size)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_data_new_uninitialized (/* size_t */ IntPtr size);
+
+ // sk_data_t* sk_data_new_with_copy(const void* src, size_t length)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_data_new_with_copy (void* src, /* size_t */ IntPtr length);
+
+ // sk_data_t* sk_data_new_with_proc(const void* ptr, size_t length, sk_data_release_proc proc, void* ctx)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_data_new_with_proc (void* ptr, /* size_t */ IntPtr length, SKDataReleaseProxyDelegate proc, void* ctx);
+
+ // void sk_data_ref(const sk_data_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_data_ref (sk_data_t param0);
+
+ // void sk_data_unref(const sk_data_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_data_unref (sk_data_t param0);
+
+ #endregion
+
+ #region sk_document.h
+
+ // void sk_document_abort(sk_document_t* document)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_document_abort (sk_document_t document);
+
+ // sk_canvas_t* sk_document_begin_page(sk_document_t* document, float width, float height, const sk_rect_t* content)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_canvas_t sk_document_begin_page (sk_document_t document, Single width, Single height, SKRect* content);
+
+ // void sk_document_close(sk_document_t* document)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_document_close (sk_document_t document);
+
+ // sk_document_t* sk_document_create_pdf_from_stream(sk_wstream_t* stream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_document_t sk_document_create_pdf_from_stream (sk_wstream_t stream);
+
+ // sk_document_t* sk_document_create_pdf_from_stream_with_metadata(sk_wstream_t* stream, const sk_document_pdf_metadata_t* metadata)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_document_t sk_document_create_pdf_from_stream_with_metadata (sk_wstream_t stream, SKDocumentPdfMetadataInternal* metadata);
+
+ // sk_document_t* sk_document_create_xps_from_stream(sk_wstream_t* stream, float dpi)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_document_t sk_document_create_xps_from_stream (sk_wstream_t stream, Single dpi);
+
+ // void sk_document_end_page(sk_document_t* document)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_document_end_page (sk_document_t document);
+
+ // void sk_document_unref(sk_document_t* document)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_document_unref (sk_document_t document);
+
+ #endregion
+
+ #region sk_drawable.h
+
+ // void sk_drawable_draw(sk_drawable_t*, sk_canvas_t*, const sk_matrix_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_drawable_draw (sk_drawable_t param0, sk_canvas_t param1, SKMatrix* param2);
+
+ // void sk_drawable_get_bounds(sk_drawable_t*, sk_rect_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_drawable_get_bounds (sk_drawable_t param0, SKRect* param1);
+
+ // uint32_t sk_drawable_get_generation_id(sk_drawable_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_drawable_get_generation_id (sk_drawable_t param0);
+
+ // sk_picture_t* sk_drawable_new_picture_snapshot(sk_drawable_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_picture_t sk_drawable_new_picture_snapshot (sk_drawable_t param0);
+
+ // void sk_drawable_notify_drawing_changed(sk_drawable_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_drawable_notify_drawing_changed (sk_drawable_t param0);
+
+ // void sk_drawable_unref(sk_drawable_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_drawable_unref (sk_drawable_t param0);
+
+ #endregion
+
+ #region sk_general.h
+
+ // sk_colortype_t sk_colortype_get_default_8888()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKColorType sk_colortype_get_default_8888 ();
+
+ // int sk_nvrefcnt_get_ref_count(const sk_nvrefcnt_t* refcnt)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_nvrefcnt_get_ref_count (sk_nvrefcnt_t refcnt);
+
+ // void sk_nvrefcnt_safe_ref(sk_nvrefcnt_t* refcnt)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_nvrefcnt_safe_ref (sk_nvrefcnt_t refcnt);
+
+ // void sk_nvrefcnt_safe_unref(sk_nvrefcnt_t* refcnt)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_nvrefcnt_safe_unref (sk_nvrefcnt_t refcnt);
+
+ // bool sk_nvrefcnt_unique(const sk_nvrefcnt_t* refcnt)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_nvrefcnt_unique (sk_nvrefcnt_t refcnt);
+
+ // int sk_refcnt_get_ref_count(const sk_refcnt_t* refcnt)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_refcnt_get_ref_count (sk_refcnt_t refcnt);
+
+ // void sk_refcnt_safe_ref(sk_refcnt_t* refcnt)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_refcnt_safe_ref (sk_refcnt_t refcnt);
+
+ // void sk_refcnt_safe_unref(sk_refcnt_t* refcnt)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_refcnt_safe_unref (sk_refcnt_t refcnt);
+
+ // bool sk_refcnt_unique(const sk_refcnt_t* refcnt)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_refcnt_unique (sk_refcnt_t refcnt);
+
+ #endregion
+
+ #region sk_image.h
+
+ // sk_data_t* sk_image_encode(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_image_encode (sk_image_t param0);
+
+ // sk_data_t* sk_image_encode_specific(const sk_image_t* cimage, sk_encoded_image_format_t encoder, int quality)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_image_encode_specific (sk_image_t cimage, SKEncodedImageFormat encoder, Int32 quality);
+
+ // sk_alphatype_t sk_image_get_alpha_type(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKAlphaType sk_image_get_alpha_type (sk_image_t param0);
+
+ // sk_colortype_t sk_image_get_color_type(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKColorType sk_image_get_color_type (sk_image_t param0);
+
+ // sk_colorspace_t* sk_image_get_colorspace(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorspace_t sk_image_get_colorspace (sk_image_t param0);
+
+ // int sk_image_get_height(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_image_get_height (sk_image_t param0);
+
+ // uint32_t sk_image_get_unique_id(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_image_get_unique_id (sk_image_t param0);
+
+ // int sk_image_get_width(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_image_get_width (sk_image_t param0);
+
+ // bool sk_image_is_alpha_only(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_image_is_alpha_only (sk_image_t param0);
+
+ // bool sk_image_is_lazy_generated(const sk_image_t* image)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_image_is_lazy_generated (sk_image_t image);
+
+ // bool sk_image_is_texture_backed(const sk_image_t* image)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_image_is_texture_backed (sk_image_t image);
+
+ // bool sk_image_is_valid(const sk_image_t* image, gr_context_t* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_image_is_valid (sk_image_t image, gr_context_t context);
+
+ // sk_image_t* sk_image_make_non_texture_image(const sk_image_t* cimage)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_make_non_texture_image (sk_image_t cimage);
+
+ // sk_image_t* sk_image_make_raster_image(const sk_image_t* cimage)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_make_raster_image (sk_image_t cimage);
+
+ // sk_shader_t* sk_image_make_shader(const sk_image_t*, sk_shader_tilemode_t tileX, sk_shader_tilemode_t tileY, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_image_make_shader (sk_image_t param0, SKShaderTileMode tileX, SKShaderTileMode tileY, SKMatrix* localMatrix);
+
+ // sk_image_t* sk_image_make_subset(const sk_image_t* cimage, const sk_irect_t* subset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_make_subset (sk_image_t cimage, SKRectI* subset);
+
+ // sk_image_t* sk_image_make_texture_image(const sk_image_t* cimage, gr_context_t* context, sk_colorspace_t* colorspace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_make_texture_image (sk_image_t cimage, gr_context_t context, sk_colorspace_t colorspace);
+
+ // sk_image_t* sk_image_make_with_filter(const sk_image_t* cimage, const sk_imagefilter_t* filter, const sk_irect_t* subset, const sk_irect_t* clipBounds, sk_irect_t* outSubset, sk_ipoint_t* outOffset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_make_with_filter (sk_image_t cimage, sk_imagefilter_t filter, SKRectI* subset, SKRectI* clipBounds, SKRectI* outSubset, SKPointI* outOffset);
+
+ // sk_image_t* sk_image_new_from_adopted_texture(gr_context_t* context, const gr_backendtexture_t* texture, gr_surfaceorigin_t origin, sk_colortype_t colorType, sk_alphatype_t alpha, sk_colorspace_t* colorSpace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_from_adopted_texture (gr_context_t context, gr_backendtexture_t texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, sk_colorspace_t colorSpace);
+
+ // sk_image_t* sk_image_new_from_bitmap(const sk_bitmap_t* cbitmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_from_bitmap (sk_bitmap_t cbitmap);
+
+ // sk_image_t* sk_image_new_from_encoded(sk_data_t* encoded, const sk_irect_t* subset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_from_encoded (sk_data_t encoded, SKRectI* subset);
+
+ // sk_image_t* sk_image_new_from_picture(sk_picture_t* picture, const sk_isize_t* dimensions, const sk_matrix_t* matrix, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_from_picture (sk_picture_t picture, SKSizeI* dimensions, SKMatrix* matrix, sk_paint_t paint);
+
+ // sk_image_t* sk_image_new_from_texture(gr_context_t* context, const gr_backendtexture_t* texture, gr_surfaceorigin_t origin, sk_colortype_t colorType, sk_alphatype_t alpha, sk_colorspace_t* colorSpace, sk_image_texture_release_proc releaseProc, void* releaseContext)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_from_texture (gr_context_t context, gr_backendtexture_t texture, GRSurfaceOrigin origin, SKColorType colorType, SKAlphaType alpha, sk_colorspace_t colorSpace, SKImageTextureReleaseProxyDelegate releaseProc, void* releaseContext);
+
+ // sk_image_t* sk_image_new_raster(const sk_pixmap_t* pixmap, sk_image_raster_release_proc releaseProc, void* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_raster (sk_pixmap_t pixmap, SKImageRasterReleaseProxyDelegate releaseProc, void* context);
+
+ // sk_image_t* sk_image_new_raster_copy(const sk_imageinfo_t*, const void* pixels, size_t rowBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_raster_copy (SKImageInfoNative* param0, void* pixels, /* size_t */ IntPtr rowBytes);
+
+ // sk_image_t* sk_image_new_raster_copy_with_pixmap(const sk_pixmap_t* pixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_raster_copy_with_pixmap (sk_pixmap_t pixmap);
+
+ // sk_image_t* sk_image_new_raster_data(const sk_imageinfo_t* cinfo, sk_data_t* pixels, size_t rowBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_image_new_raster_data (SKImageInfoNative* cinfo, sk_data_t pixels, /* size_t */ IntPtr rowBytes);
+
+ // bool sk_image_peek_pixels(const sk_image_t* image, sk_pixmap_t* pixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_image_peek_pixels (sk_image_t image, sk_pixmap_t pixmap);
+
+ // bool sk_image_read_pixels(const sk_image_t* image, const sk_imageinfo_t* dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY, sk_image_caching_hint_t cachingHint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_image_read_pixels (sk_image_t image, SKImageInfoNative* dstInfo, void* dstPixels, /* size_t */ IntPtr dstRowBytes, Int32 srcX, Int32 srcY, SKImageCachingHint cachingHint);
+
+ // bool sk_image_read_pixels_into_pixmap(const sk_image_t* image, const sk_pixmap_t* dst, int srcX, int srcY, sk_image_caching_hint_t cachingHint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_image_read_pixels_into_pixmap (sk_image_t image, sk_pixmap_t dst, Int32 srcX, Int32 srcY, SKImageCachingHint cachingHint);
+
+ // void sk_image_ref(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_image_ref (sk_image_t param0);
+
+ // sk_data_t* sk_image_ref_encoded(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_image_ref_encoded (sk_image_t param0);
+
+ // bool sk_image_scale_pixels(const sk_image_t* image, const sk_pixmap_t* dst, sk_filter_quality_t quality, sk_image_caching_hint_t cachingHint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_image_scale_pixels (sk_image_t image, sk_pixmap_t dst, SKFilterQuality quality, SKImageCachingHint cachingHint);
+
+ // void sk_image_unref(const sk_image_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_image_unref (sk_image_t param0);
+
+ #endregion
+
+ #region sk_imagefilter.h
+
+ // void sk_imagefilter_croprect_destructor(sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_imagefilter_croprect_destructor (sk_imagefilter_croprect_t cropRect);
+
+ // uint32_t sk_imagefilter_croprect_get_flags(sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_imagefilter_croprect_get_flags (sk_imagefilter_croprect_t cropRect);
+
+ // void sk_imagefilter_croprect_get_rect(sk_imagefilter_croprect_t* cropRect, sk_rect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_imagefilter_croprect_get_rect (sk_imagefilter_croprect_t cropRect, SKRect* rect);
+
+ // sk_imagefilter_croprect_t* sk_imagefilter_croprect_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_croprect_t sk_imagefilter_croprect_new ();
+
+ // sk_imagefilter_croprect_t* sk_imagefilter_croprect_new_with_rect(const sk_rect_t* rect, uint32_t flags)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_croprect_t sk_imagefilter_croprect_new_with_rect (SKRect* rect, UInt32 flags);
+
+ // sk_imagefilter_t* sk_imagefilter_new_alpha_threshold(const sk_region_t* region, float innerThreshold, float outerThreshold, sk_imagefilter_t* input)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_alpha_threshold (sk_region_t region, Single innerThreshold, Single outerThreshold, sk_imagefilter_t input);
+
+ // sk_imagefilter_t* sk_imagefilter_new_arithmetic(float k1, float k2, float k3, float k4, bool enforcePMColor, sk_imagefilter_t* background, sk_imagefilter_t* foreground, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_arithmetic (Single k1, Single k2, Single k3, Single k4, [MarshalAs (UnmanagedType.I1)] bool enforcePMColor, sk_imagefilter_t background, sk_imagefilter_t foreground, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_blur(float sigmaX, float sigmaY, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_blur (Single sigmaX, Single sigmaY, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_color_filter(sk_colorfilter_t* cf, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_color_filter (sk_colorfilter_t cf, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_compose(sk_imagefilter_t* outer, sk_imagefilter_t* inner)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_compose (sk_imagefilter_t outer, sk_imagefilter_t inner);
+
+ // sk_imagefilter_t* sk_imagefilter_new_dilate(int radiusX, int radiusY, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_dilate (Int32 radiusX, Int32 radiusY, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_displacement_map_effect(sk_displacement_map_effect_channel_selector_type_t xChannelSelector, sk_displacement_map_effect_channel_selector_type_t yChannelSelector, float scale, sk_imagefilter_t* displacement, sk_imagefilter_t* color, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_displacement_map_effect (SKDisplacementMapEffectChannelSelectorType xChannelSelector, SKDisplacementMapEffectChannelSelectorType yChannelSelector, Single scale, sk_imagefilter_t displacement, sk_imagefilter_t color, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_distant_lit_diffuse(const sk_point3_t* direction, sk_color_t lightColor, float surfaceScale, float kd, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_distant_lit_diffuse (SKPoint3* direction, UInt32 lightColor, Single surfaceScale, Single kd, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_distant_lit_specular(const sk_point3_t* direction, sk_color_t lightColor, float surfaceScale, float ks, float shininess, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_distant_lit_specular (SKPoint3* direction, UInt32 lightColor, Single surfaceScale, Single ks, Single shininess, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_drop_shadow(float dx, float dy, float sigmaX, float sigmaY, sk_color_t color, sk_drop_shadow_image_filter_shadow_mode_t shadowMode, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_drop_shadow (Single dx, Single dy, Single sigmaX, Single sigmaY, UInt32 color, SKDropShadowImageFilterShadowMode shadowMode, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_erode(int radiusX, int radiusY, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_erode (Int32 radiusX, Int32 radiusY, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_image_source(sk_image_t* image, const sk_rect_t* srcRect, const sk_rect_t* dstRect, sk_filter_quality_t filterQuality)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_image_source (sk_image_t image, SKRect* srcRect, SKRect* dstRect, SKFilterQuality filterQuality);
+
+ // sk_imagefilter_t* sk_imagefilter_new_image_source_default(sk_image_t* image)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_image_source_default (sk_image_t image);
+
+ // sk_imagefilter_t* sk_imagefilter_new_magnifier(const sk_rect_t* src, float inset, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_magnifier (SKRect* src, Single inset, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_matrix(const sk_matrix_t* matrix, sk_filter_quality_t quality, sk_imagefilter_t* input)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_matrix (SKMatrix* matrix, SKFilterQuality quality, sk_imagefilter_t input);
+
+ // sk_imagefilter_t* sk_imagefilter_new_matrix_convolution(const sk_isize_t* kernelSize, const float[-1] kernel, float gain, float bias, const sk_ipoint_t* kernelOffset, sk_matrix_convolution_tilemode_t tileMode, bool convolveAlpha, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_matrix_convolution (SKSizeI* kernelSize, Single* kernel, Single gain, Single bias, SKPointI* kernelOffset, SKMatrixConvolutionTileMode tileMode, [MarshalAs (UnmanagedType.I1)] bool convolveAlpha, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_merge(sk_imagefilter_t*[-1] filters, int count, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_merge (sk_imagefilter_t* filters, Int32 count, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_offset(float dx, float dy, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_offset (Single dx, Single dy, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_paint(const sk_paint_t* paint, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_paint (sk_paint_t paint, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_picture(sk_picture_t* picture)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_picture (sk_picture_t picture);
+
+ // sk_imagefilter_t* sk_imagefilter_new_picture_with_croprect(sk_picture_t* picture, const sk_rect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_picture_with_croprect (sk_picture_t picture, SKRect* cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_point_lit_diffuse(const sk_point3_t* location, sk_color_t lightColor, float surfaceScale, float kd, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_point_lit_diffuse (SKPoint3* location, UInt32 lightColor, Single surfaceScale, Single kd, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_point_lit_specular(const sk_point3_t* location, sk_color_t lightColor, float surfaceScale, float ks, float shininess, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_point_lit_specular (SKPoint3* location, UInt32 lightColor, Single surfaceScale, Single ks, Single shininess, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_spot_lit_diffuse(const sk_point3_t* location, const sk_point3_t* target, float specularExponent, float cutoffAngle, sk_color_t lightColor, float surfaceScale, float kd, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_spot_lit_diffuse (SKPoint3* location, SKPoint3* target, Single specularExponent, Single cutoffAngle, UInt32 lightColor, Single surfaceScale, Single kd, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_spot_lit_specular(const sk_point3_t* location, const sk_point3_t* target, float specularExponent, float cutoffAngle, sk_color_t lightColor, float surfaceScale, float ks, float shininess, sk_imagefilter_t* input, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_spot_lit_specular (SKPoint3* location, SKPoint3* target, Single specularExponent, Single cutoffAngle, UInt32 lightColor, Single surfaceScale, Single ks, Single shininess, sk_imagefilter_t input, sk_imagefilter_croprect_t cropRect);
+
+ // sk_imagefilter_t* sk_imagefilter_new_tile(const sk_rect_t* src, const sk_rect_t* dst, sk_imagefilter_t* input)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_tile (SKRect* src, SKRect* dst, sk_imagefilter_t input);
+
+ // sk_imagefilter_t* sk_imagefilter_new_xfermode(sk_blendmode_t mode, sk_imagefilter_t* background, sk_imagefilter_t* foreground, const sk_imagefilter_croprect_t* cropRect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_imagefilter_new_xfermode (SKBlendMode mode, sk_imagefilter_t background, sk_imagefilter_t foreground, sk_imagefilter_croprect_t cropRect);
+
+ // void sk_imagefilter_unref(sk_imagefilter_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_imagefilter_unref (sk_imagefilter_t param0);
+
+ #endregion
+
+ #region sk_mask.h
+
+ // uint8_t* sk_mask_alloc_image(size_t bytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Byte* sk_mask_alloc_image (/* size_t */ IntPtr bytes);
+
+ // size_t sk_mask_compute_image_size(sk_mask_t* cmask)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_mask_compute_image_size (SKMask* cmask);
+
+ // size_t sk_mask_compute_total_image_size(sk_mask_t* cmask)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_mask_compute_total_image_size (SKMask* cmask);
+
+ // void sk_mask_free_image(void* image)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_mask_free_image (void* image);
+
+ // void* sk_mask_get_addr(sk_mask_t* cmask, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void* sk_mask_get_addr (SKMask* cmask, Int32 x, Int32 y);
+
+ // uint8_t sk_mask_get_addr_1(sk_mask_t* cmask, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Byte sk_mask_get_addr_1 (SKMask* cmask, Int32 x, Int32 y);
+
+ // uint32_t sk_mask_get_addr_32(sk_mask_t* cmask, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_mask_get_addr_32 (SKMask* cmask, Int32 x, Int32 y);
+
+ // uint8_t sk_mask_get_addr_8(sk_mask_t* cmask, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Byte sk_mask_get_addr_8 (SKMask* cmask, Int32 x, Int32 y);
+
+ // uint16_t sk_mask_get_addr_lcd_16(sk_mask_t* cmask, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt16 sk_mask_get_addr_lcd_16 (SKMask* cmask, Int32 x, Int32 y);
+
+ // bool sk_mask_is_empty(sk_mask_t* cmask)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_mask_is_empty (SKMask* cmask);
+
+ #endregion
+
+ #region sk_maskfilter.h
+
+ // sk_maskfilter_t* sk_maskfilter_new_blur(sk_blurstyle_t, float sigma)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_maskfilter_t sk_maskfilter_new_blur (SKBlurStyle param0, Single sigma);
+
+ // sk_maskfilter_t* sk_maskfilter_new_blur_with_flags(sk_blurstyle_t, float sigma, const sk_rect_t* occluder, bool respectCTM)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_maskfilter_t sk_maskfilter_new_blur_with_flags (SKBlurStyle param0, Single sigma, SKRect* occluder, [MarshalAs (UnmanagedType.I1)] bool respectCTM);
+
+ // sk_maskfilter_t* sk_maskfilter_new_clip(uint8_t min, uint8_t max)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_maskfilter_t sk_maskfilter_new_clip (Byte min, Byte max);
+
+ // sk_maskfilter_t* sk_maskfilter_new_gamma(float gamma)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_maskfilter_t sk_maskfilter_new_gamma (Single gamma);
+
+ // sk_maskfilter_t* sk_maskfilter_new_table(const uint8_t[256] table = 256)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_maskfilter_t sk_maskfilter_new_table (Byte* table);
+
+ // void sk_maskfilter_ref(sk_maskfilter_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_maskfilter_ref (sk_maskfilter_t param0);
+
+ // void sk_maskfilter_unref(sk_maskfilter_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_maskfilter_unref (sk_maskfilter_t param0);
+
+ #endregion
+
+ #region sk_matrix.h
+
+ // void sk_3dview_apply_to_canvas(sk_3dview_t* cview, sk_canvas_t* ccanvas)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_apply_to_canvas (sk_3dview_t cview, sk_canvas_t ccanvas);
+
+ // void sk_3dview_destroy(sk_3dview_t* cview)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_destroy (sk_3dview_t cview);
+
+ // float sk_3dview_dot_with_normal(sk_3dview_t* cview, float dx, float dy, float dz)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_3dview_dot_with_normal (sk_3dview_t cview, Single dx, Single dy, Single dz);
+
+ // void sk_3dview_get_matrix(sk_3dview_t* cview, sk_matrix_t* cmatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_get_matrix (sk_3dview_t cview, SKMatrix* cmatrix);
+
+ // sk_3dview_t* sk_3dview_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_3dview_t sk_3dview_new ();
+
+ // void sk_3dview_restore(sk_3dview_t* cview)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_restore (sk_3dview_t cview);
+
+ // void sk_3dview_rotate_x_degrees(sk_3dview_t* cview, float degrees)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_rotate_x_degrees (sk_3dview_t cview, Single degrees);
+
+ // void sk_3dview_rotate_x_radians(sk_3dview_t* cview, float radians)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_rotate_x_radians (sk_3dview_t cview, Single radians);
+
+ // void sk_3dview_rotate_y_degrees(sk_3dview_t* cview, float degrees)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_rotate_y_degrees (sk_3dview_t cview, Single degrees);
+
+ // void sk_3dview_rotate_y_radians(sk_3dview_t* cview, float radians)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_rotate_y_radians (sk_3dview_t cview, Single radians);
+
+ // void sk_3dview_rotate_z_degrees(sk_3dview_t* cview, float degrees)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_rotate_z_degrees (sk_3dview_t cview, Single degrees);
+
+ // void sk_3dview_rotate_z_radians(sk_3dview_t* cview, float radians)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_rotate_z_radians (sk_3dview_t cview, Single radians);
+
+ // void sk_3dview_save(sk_3dview_t* cview)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_save (sk_3dview_t cview);
+
+ // void sk_3dview_translate(sk_3dview_t* cview, float x, float y, float z)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_3dview_translate (sk_3dview_t cview, Single x, Single y, Single z);
+
+ // void sk_matrix_concat(sk_matrix_t* result, sk_matrix_t* first, sk_matrix_t* second)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix_concat (SKMatrix* result, SKMatrix* first, SKMatrix* second);
+
+ // void sk_matrix_map_points(sk_matrix_t* matrix, sk_point_t* dst, sk_point_t* src, int count)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix_map_points (SKMatrix* matrix, SKPoint* dst, SKPoint* src, Int32 count);
+
+ // float sk_matrix_map_radius(sk_matrix_t* matrix, float radius)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_matrix_map_radius (SKMatrix* matrix, Single radius);
+
+ // void sk_matrix_map_rect(sk_matrix_t* matrix, sk_rect_t* dest, sk_rect_t* source)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix_map_rect (SKMatrix* matrix, SKRect* dest, SKRect* source);
+
+ // void sk_matrix_map_vector(sk_matrix_t* matrix, float x, float y, sk_point_t* result)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix_map_vector (SKMatrix* matrix, Single x, Single y, SKPoint* result);
+
+ // void sk_matrix_map_vectors(sk_matrix_t* matrix, sk_point_t* dst, sk_point_t* src, int count)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix_map_vectors (SKMatrix* matrix, SKPoint* dst, SKPoint* src, Int32 count);
+
+ // void sk_matrix_map_xy(sk_matrix_t* matrix, float x, float y, sk_point_t* result)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix_map_xy (SKMatrix* matrix, Single x, Single y, SKPoint* result);
+
+ // void sk_matrix_post_concat(sk_matrix_t* result, sk_matrix_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix_post_concat (SKMatrix* result, SKMatrix* matrix);
+
+ // void sk_matrix_pre_concat(sk_matrix_t* result, sk_matrix_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix_pre_concat (SKMatrix* result, SKMatrix* matrix);
+
+ // bool sk_matrix_try_invert(sk_matrix_t* matrix, sk_matrix_t* result)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_matrix_try_invert (SKMatrix* matrix, SKMatrix* result);
+
+ // void sk_matrix44_as_col_major(sk_matrix44_t* matrix, float* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_as_col_major (sk_matrix44_t matrix, Single* dst);
+
+ // void sk_matrix44_as_row_major(sk_matrix44_t* matrix, float* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_as_row_major (sk_matrix44_t matrix, Single* dst);
+
+ // void sk_matrix44_destroy(sk_matrix44_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_destroy (sk_matrix44_t matrix);
+
+ // double sk_matrix44_determinant(sk_matrix44_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Double sk_matrix44_determinant (sk_matrix44_t matrix);
+
+ // bool sk_matrix44_equals(sk_matrix44_t* matrix, const sk_matrix44_t* other)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_matrix44_equals (sk_matrix44_t matrix, sk_matrix44_t other);
+
+ // float sk_matrix44_get(sk_matrix44_t* matrix, int row, int col)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_matrix44_get (sk_matrix44_t matrix, Int32 row, Int32 col);
+
+ // sk_matrix44_type_mask_t sk_matrix44_get_type(sk_matrix44_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKMatrix44TypeMask sk_matrix44_get_type (sk_matrix44_t matrix);
+
+ // bool sk_matrix44_invert(sk_matrix44_t* matrix, sk_matrix44_t* inverse)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_matrix44_invert (sk_matrix44_t matrix, sk_matrix44_t inverse);
+
+ // void sk_matrix44_map_scalars(sk_matrix44_t* matrix, const float* src, float* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_map_scalars (sk_matrix44_t matrix, Single* src, Single* dst);
+
+ // void sk_matrix44_map2(sk_matrix44_t* matrix, const float* src2, int count, float* dst4)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_map2 (sk_matrix44_t matrix, Single* src2, Int32 count, Single* dst4);
+
+ // sk_matrix44_t* sk_matrix44_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_matrix44_t sk_matrix44_new ();
+
+ // sk_matrix44_t* sk_matrix44_new_concat(const sk_matrix44_t* a, const sk_matrix44_t* b)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_matrix44_t sk_matrix44_new_concat (sk_matrix44_t a, sk_matrix44_t b);
+
+ // sk_matrix44_t* sk_matrix44_new_copy(const sk_matrix44_t* src)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_matrix44_t sk_matrix44_new_copy (sk_matrix44_t src);
+
+ // sk_matrix44_t* sk_matrix44_new_identity()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_matrix44_t sk_matrix44_new_identity ();
+
+ // sk_matrix44_t* sk_matrix44_new_matrix(const sk_matrix_t* src)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_matrix44_t sk_matrix44_new_matrix (SKMatrix* src);
+
+ // void sk_matrix44_post_concat(sk_matrix44_t* matrix, const sk_matrix44_t* m)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_post_concat (sk_matrix44_t matrix, sk_matrix44_t m);
+
+ // void sk_matrix44_post_scale(sk_matrix44_t* matrix, float sx, float sy, float sz)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_post_scale (sk_matrix44_t matrix, Single sx, Single sy, Single sz);
+
+ // void sk_matrix44_post_translate(sk_matrix44_t* matrix, float dx, float dy, float dz)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_post_translate (sk_matrix44_t matrix, Single dx, Single dy, Single dz);
+
+ // void sk_matrix44_pre_concat(sk_matrix44_t* matrix, const sk_matrix44_t* m)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_pre_concat (sk_matrix44_t matrix, sk_matrix44_t m);
+
+ // void sk_matrix44_pre_scale(sk_matrix44_t* matrix, float sx, float sy, float sz)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_pre_scale (sk_matrix44_t matrix, Single sx, Single sy, Single sz);
+
+ // void sk_matrix44_pre_translate(sk_matrix44_t* matrix, float dx, float dy, float dz)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_pre_translate (sk_matrix44_t matrix, Single dx, Single dy, Single dz);
+
+ // bool sk_matrix44_preserves_2d_axis_alignment(sk_matrix44_t* matrix, float epsilon)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_matrix44_preserves_2d_axis_alignment (sk_matrix44_t matrix, Single epsilon);
+
+ // void sk_matrix44_set(sk_matrix44_t* matrix, int row, int col, float value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set (sk_matrix44_t matrix, Int32 row, Int32 col, Single value);
+
+ // void sk_matrix44_set_3x3_row_major(sk_matrix44_t* matrix, float* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_3x3_row_major (sk_matrix44_t matrix, Single* dst);
+
+ // void sk_matrix44_set_col_major(sk_matrix44_t* matrix, float* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_col_major (sk_matrix44_t matrix, Single* dst);
+
+ // void sk_matrix44_set_concat(sk_matrix44_t* matrix, const sk_matrix44_t* a, const sk_matrix44_t* b)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_concat (sk_matrix44_t matrix, sk_matrix44_t a, sk_matrix44_t b);
+
+ // void sk_matrix44_set_identity(sk_matrix44_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_identity (sk_matrix44_t matrix);
+
+ // void sk_matrix44_set_rotate_about_degrees(sk_matrix44_t* matrix, float x, float y, float z, float degrees)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_rotate_about_degrees (sk_matrix44_t matrix, Single x, Single y, Single z, Single degrees);
+
+ // void sk_matrix44_set_rotate_about_radians(sk_matrix44_t* matrix, float x, float y, float z, float radians)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_rotate_about_radians (sk_matrix44_t matrix, Single x, Single y, Single z, Single radians);
+
+ // 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)]
+ internal static extern void sk_matrix44_set_rotate_about_radians_unit (sk_matrix44_t matrix, Single x, Single y, Single z, Single radians);
+
+ // void sk_matrix44_set_row_major(sk_matrix44_t* matrix, float* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_row_major (sk_matrix44_t matrix, Single* dst);
+
+ // void sk_matrix44_set_scale(sk_matrix44_t* matrix, float sx, float sy, float sz)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_scale (sk_matrix44_t matrix, Single sx, Single sy, Single sz);
+
+ // void sk_matrix44_set_translate(sk_matrix44_t* matrix, float dx, float dy, float dz)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_set_translate (sk_matrix44_t matrix, Single dx, Single dy, Single dz);
+
+ // void sk_matrix44_to_matrix(sk_matrix44_t* matrix, sk_matrix_t* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_to_matrix (sk_matrix44_t matrix, SKMatrix* dst);
+
+ // void sk_matrix44_transpose(sk_matrix44_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_matrix44_transpose (sk_matrix44_t matrix);
+
+ #endregion
+
+ #region sk_paint.h
+
+ // size_t sk_paint_break_text(const sk_paint_t* cpaint, const void* text, size_t length, float maxWidth, float* measuredWidth)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_paint_break_text (sk_paint_t cpaint, void* text, /* size_t */ IntPtr length, Single maxWidth, Single* measuredWidth);
+
+ // sk_paint_t* sk_paint_clone(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_paint_t sk_paint_clone (sk_paint_t param0);
+
+ // bool sk_paint_contains_text(const sk_paint_t* cpaint, const void* text, size_t byteLength)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_contains_text (sk_paint_t cpaint, void* text, /* size_t */ IntPtr byteLength);
+
+ // int sk_paint_count_text(const sk_paint_t* cpaint, const void* text, size_t byteLength)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_paint_count_text (sk_paint_t cpaint, void* text, /* size_t */ IntPtr byteLength);
+
+ // void sk_paint_delete(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_delete (sk_paint_t param0);
+
+ // sk_blendmode_t sk_paint_get_blendmode(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKBlendMode sk_paint_get_blendmode (sk_paint_t param0);
+
+ // sk_color_t sk_paint_get_color(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_paint_get_color (sk_paint_t param0);
+
+ // sk_colorfilter_t* sk_paint_get_colorfilter(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_colorfilter_t sk_paint_get_colorfilter (sk_paint_t param0);
+
+ // bool sk_paint_get_fill_path(const sk_paint_t*, const sk_path_t* src, sk_path_t* dst, const sk_rect_t* cullRect, float resScale)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_get_fill_path (sk_paint_t param0, sk_path_t src, sk_path_t dst, SKRect* cullRect, Single resScale);
+
+ // sk_filter_quality_t sk_paint_get_filter_quality(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKFilterQuality sk_paint_get_filter_quality (sk_paint_t param0);
+
+ // float sk_paint_get_fontmetrics(sk_paint_t* cpaint, sk_fontmetrics_t* cfontmetrics, float scale)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_paint_get_fontmetrics (sk_paint_t cpaint, SKFontMetrics* cfontmetrics, Single scale);
+
+ // sk_paint_hinting_t sk_paint_get_hinting(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKPaintHinting sk_paint_get_hinting (sk_paint_t param0);
+
+ // sk_imagefilter_t* sk_paint_get_imagefilter(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_imagefilter_t sk_paint_get_imagefilter (sk_paint_t param0);
+
+ // sk_maskfilter_t* sk_paint_get_maskfilter(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_maskfilter_t sk_paint_get_maskfilter (sk_paint_t param0);
+
+ // sk_path_effect_t* sk_paint_get_path_effect(sk_paint_t* cpaint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_paint_get_path_effect (sk_paint_t cpaint);
+
+ // int sk_paint_get_pos_text_blob_intercepts(const sk_paint_t* cpaint, sk_textblob_t* blob, const float[2] bounds = 2, float* intervals)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_paint_get_pos_text_blob_intercepts (sk_paint_t cpaint, sk_textblob_t blob, Single* bounds, Single* intervals);
+
+ // int sk_paint_get_pos_text_h_intercepts(const sk_paint_t* cpaint, const void* text, size_t byteLength, float* xpos, float y, const float[2] bounds = 2, float* intervals)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_paint_get_pos_text_h_intercepts (sk_paint_t cpaint, void* text, /* size_t */ IntPtr byteLength, Single* xpos, Single y, Single* bounds, Single* intervals);
+
+ // int sk_paint_get_pos_text_intercepts(const sk_paint_t* cpaint, const void* text, size_t byteLength, sk_point_t* pos, const float[2] bounds = 2, float* intervals)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_paint_get_pos_text_intercepts (sk_paint_t cpaint, void* text, /* size_t */ IntPtr byteLength, SKPoint* pos, Single* bounds, Single* intervals);
+
+ // sk_path_t* sk_paint_get_pos_text_path(sk_paint_t* cpaint, const void* text, size_t length, const sk_point_t[-1] pos)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_t sk_paint_get_pos_text_path (sk_paint_t cpaint, void* text, /* size_t */ IntPtr length, SKPoint* pos);
+
+ // sk_shader_t* sk_paint_get_shader(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_paint_get_shader (sk_paint_t param0);
+
+ // sk_stroke_cap_t sk_paint_get_stroke_cap(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKStrokeCap sk_paint_get_stroke_cap (sk_paint_t param0);
+
+ // sk_stroke_join_t sk_paint_get_stroke_join(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKStrokeJoin sk_paint_get_stroke_join (sk_paint_t param0);
+
+ // float sk_paint_get_stroke_miter(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_paint_get_stroke_miter (sk_paint_t param0);
+
+ // float sk_paint_get_stroke_width(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_paint_get_stroke_width (sk_paint_t param0);
+
+ // sk_paint_style_t sk_paint_get_style(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKPaintStyle sk_paint_get_style (sk_paint_t param0);
+
+ // sk_text_align_t sk_paint_get_text_align(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKTextAlign sk_paint_get_text_align (sk_paint_t param0);
+
+ // sk_text_encoding_t sk_paint_get_text_encoding(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKTextEncoding sk_paint_get_text_encoding (sk_paint_t param0);
+
+ // int sk_paint_get_text_intercepts(const sk_paint_t* cpaint, const void* text, size_t byteLength, float x, float y, const float[2] bounds = 2, float* intervals)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_paint_get_text_intercepts (sk_paint_t cpaint, void* text, /* size_t */ IntPtr byteLength, Single x, Single y, Single* bounds, Single* intervals);
+
+ // sk_path_t* sk_paint_get_text_path(sk_paint_t* cpaint, const void* text, size_t length, float x, float y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_t sk_paint_get_text_path (sk_paint_t cpaint, void* text, /* size_t */ IntPtr length, Single x, Single y);
+
+ // float sk_paint_get_text_scale_x(const sk_paint_t* cpaint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_paint_get_text_scale_x (sk_paint_t cpaint);
+
+ // float sk_paint_get_text_skew_x(const sk_paint_t* cpaint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_paint_get_text_skew_x (sk_paint_t cpaint);
+
+ // int sk_paint_get_text_widths(const sk_paint_t* cpaint, const void* text, size_t byteLength, float* widths, sk_rect_t* bounds)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_paint_get_text_widths (sk_paint_t cpaint, void* text, /* size_t */ IntPtr byteLength, Single* widths, SKRect* bounds);
+
+ // float sk_paint_get_textsize(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_paint_get_textsize (sk_paint_t param0);
+
+ // sk_typeface_t* sk_paint_get_typeface(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_paint_get_typeface (sk_paint_t param0);
+
+ // bool sk_paint_is_antialias(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_antialias (sk_paint_t param0);
+
+ // bool sk_paint_is_autohinted(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_autohinted (sk_paint_t param0);
+
+ // bool sk_paint_is_dev_kern_text(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_dev_kern_text (sk_paint_t param0);
+
+ // bool sk_paint_is_dither(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_dither (sk_paint_t param0);
+
+ // bool sk_paint_is_embedded_bitmap_text(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_embedded_bitmap_text (sk_paint_t param0);
+
+ // bool sk_paint_is_fake_bold_text(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_fake_bold_text (sk_paint_t param0);
+
+ // bool sk_paint_is_lcd_render_text(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_lcd_render_text (sk_paint_t param0);
+
+ // bool sk_paint_is_linear_text(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_linear_text (sk_paint_t param0);
+
+ // bool sk_paint_is_subpixel_text(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_subpixel_text (sk_paint_t param0);
+
+ // bool sk_paint_is_verticaltext(const sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_paint_is_verticaltext (sk_paint_t param0);
+
+ // float sk_paint_measure_text(const sk_paint_t* cpaint, const void* text, size_t length, sk_rect_t* cbounds)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_paint_measure_text (sk_paint_t cpaint, void* text, /* size_t */ IntPtr length, SKRect* cbounds);
+
+ // sk_paint_t* sk_paint_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_paint_t sk_paint_new ();
+
+ // void sk_paint_reset(sk_paint_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_reset (sk_paint_t param0);
+
+ // void sk_paint_set_antialias(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_antialias (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_autohinted(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_autohinted (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_blendmode(sk_paint_t*, sk_blendmode_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_blendmode (sk_paint_t param0, SKBlendMode param1);
+
+ // void sk_paint_set_color(sk_paint_t*, sk_color_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_color (sk_paint_t param0, UInt32 param1);
+
+ // void sk_paint_set_colorfilter(sk_paint_t*, sk_colorfilter_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_colorfilter (sk_paint_t param0, sk_colorfilter_t param1);
+
+ // void sk_paint_set_dev_kern_text(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_dev_kern_text (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_dither(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_dither (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_embedded_bitmap_text(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_embedded_bitmap_text (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_fake_bold_text(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_fake_bold_text (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_filter_quality(sk_paint_t*, sk_filter_quality_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_filter_quality (sk_paint_t param0, SKFilterQuality param1);
+
+ // void sk_paint_set_hinting(sk_paint_t*, sk_paint_hinting_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_hinting (sk_paint_t param0, SKPaintHinting param1);
+
+ // void sk_paint_set_imagefilter(sk_paint_t*, sk_imagefilter_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_imagefilter (sk_paint_t param0, sk_imagefilter_t param1);
+
+ // void sk_paint_set_lcd_render_text(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_lcd_render_text (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_linear_text(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_linear_text (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_maskfilter(sk_paint_t*, sk_maskfilter_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_maskfilter (sk_paint_t param0, sk_maskfilter_t param1);
+
+ // void sk_paint_set_path_effect(sk_paint_t* cpaint, sk_path_effect_t* effect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_path_effect (sk_paint_t cpaint, sk_path_effect_t effect);
+
+ // void sk_paint_set_shader(sk_paint_t*, sk_shader_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_shader (sk_paint_t param0, sk_shader_t param1);
+
+ // void sk_paint_set_stroke_cap(sk_paint_t*, sk_stroke_cap_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_stroke_cap (sk_paint_t param0, SKStrokeCap param1);
+
+ // void sk_paint_set_stroke_join(sk_paint_t*, sk_stroke_join_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_stroke_join (sk_paint_t param0, SKStrokeJoin param1);
+
+ // void sk_paint_set_stroke_miter(sk_paint_t*, float miter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_stroke_miter (sk_paint_t param0, Single miter);
+
+ // void sk_paint_set_stroke_width(sk_paint_t*, float width)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_stroke_width (sk_paint_t param0, Single width);
+
+ // void sk_paint_set_style(sk_paint_t*, sk_paint_style_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_style (sk_paint_t param0, SKPaintStyle param1);
+
+ // void sk_paint_set_subpixel_text(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_subpixel_text (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // void sk_paint_set_text_align(sk_paint_t*, sk_text_align_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_text_align (sk_paint_t param0, SKTextAlign param1);
+
+ // void sk_paint_set_text_encoding(sk_paint_t*, sk_text_encoding_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_text_encoding (sk_paint_t param0, SKTextEncoding param1);
+
+ // void sk_paint_set_text_scale_x(sk_paint_t* cpaint, float scale)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_text_scale_x (sk_paint_t cpaint, Single scale);
+
+ // void sk_paint_set_text_skew_x(sk_paint_t* cpaint, float skew)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_text_skew_x (sk_paint_t cpaint, Single skew);
+
+ // void sk_paint_set_textsize(sk_paint_t*, float)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_textsize (sk_paint_t param0, Single param1);
+
+ // void sk_paint_set_typeface(sk_paint_t*, sk_typeface_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_typeface (sk_paint_t param0, sk_typeface_t param1);
+
+ // void sk_paint_set_verticaltext(sk_paint_t*, bool)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_paint_set_verticaltext (sk_paint_t param0, [MarshalAs (UnmanagedType.I1)] bool param1);
+
+ // int sk_paint_text_to_glyphs(const sk_paint_t* cpaint, const void* text, size_t byteLength, uint16_t* glyphs)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_paint_text_to_glyphs (sk_paint_t cpaint, void* text, /* size_t */ IntPtr byteLength, UInt16* glyphs);
+
+ #endregion
+
+ #region sk_path.h
+
+ // void sk_opbuilder_add(sk_opbuilder_t* builder, const sk_path_t* path, sk_pathop_t op)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_opbuilder_add (sk_opbuilder_t builder, sk_path_t path, SKPathOp op);
+
+ // void sk_opbuilder_destroy(sk_opbuilder_t* builder)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_opbuilder_destroy (sk_opbuilder_t builder);
+
+ // sk_opbuilder_t* sk_opbuilder_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_opbuilder_t sk_opbuilder_new ();
+
+ // bool sk_opbuilder_resolve(sk_opbuilder_t* builder, sk_path_t* result)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_opbuilder_resolve (sk_opbuilder_t builder, sk_path_t result);
+
+ // void sk_path_add_arc(sk_path_t* cpath, const sk_rect_t* crect, float startAngle, float sweepAngle)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_arc (sk_path_t cpath, SKRect* crect, Single startAngle, Single sweepAngle);
+
+ // void sk_path_add_circle(sk_path_t*, float x, float y, float radius, sk_path_direction_t dir)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_circle (sk_path_t param0, Single x, Single y, Single radius, SKPathDirection dir);
+
+ // void sk_path_add_oval(sk_path_t*, const sk_rect_t*, sk_path_direction_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_oval (sk_path_t param0, SKRect* param1, SKPathDirection param2);
+
+ // void sk_path_add_path(sk_path_t* cpath, sk_path_t* other, sk_path_add_mode_t add_mode)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_path (sk_path_t cpath, sk_path_t other, SKPathAddMode add_mode);
+
+ // void sk_path_add_path_matrix(sk_path_t* cpath, sk_path_t* other, sk_matrix_t* matrix, sk_path_add_mode_t add_mode)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_path_matrix (sk_path_t cpath, sk_path_t other, SKMatrix* matrix, SKPathAddMode add_mode);
+
+ // void sk_path_add_path_offset(sk_path_t* cpath, sk_path_t* other, float dx, float dy, sk_path_add_mode_t add_mode)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_path_offset (sk_path_t cpath, sk_path_t other, Single dx, Single dy, SKPathAddMode add_mode);
+
+ // void sk_path_add_path_reverse(sk_path_t* cpath, sk_path_t* other)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_path_reverse (sk_path_t cpath, sk_path_t other);
+
+ // void sk_path_add_poly(sk_path_t* cpath, const sk_point_t* points, int count, bool close)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_poly (sk_path_t cpath, SKPoint* points, Int32 count, [MarshalAs (UnmanagedType.I1)] bool close);
+
+ // void sk_path_add_rect(sk_path_t*, const sk_rect_t*, sk_path_direction_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_rect (sk_path_t param0, SKRect* param1, SKPathDirection param2);
+
+ // void sk_path_add_rect_start(sk_path_t* cpath, const sk_rect_t* crect, sk_path_direction_t cdir, uint32_t startIndex)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_rect_start (sk_path_t cpath, SKRect* crect, SKPathDirection cdir, UInt32 startIndex);
+
+ // void sk_path_add_rounded_rect(sk_path_t*, const sk_rect_t*, float, float, sk_path_direction_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_rounded_rect (sk_path_t param0, SKRect* param1, Single param2, Single param3, SKPathDirection param4);
+
+ // void sk_path_add_rrect(sk_path_t*, const sk_rrect_t*, sk_path_direction_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_rrect (sk_path_t param0, sk_rrect_t param1, SKPathDirection param2);
+
+ // void sk_path_add_rrect_start(sk_path_t*, const sk_rrect_t*, sk_path_direction_t, uint32_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_add_rrect_start (sk_path_t param0, sk_rrect_t param1, SKPathDirection param2, UInt32 param3);
+
+ // void sk_path_arc_to(sk_path_t*, float rx, float ry, float xAxisRotate, sk_path_arc_size_t largeArc, sk_path_direction_t sweep, float x, float y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_arc_to (sk_path_t param0, Single rx, Single ry, Single xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, Single x, Single y);
+
+ // void sk_path_arc_to_with_oval(sk_path_t*, const sk_rect_t* oval, float startAngle, float sweepAngle, bool forceMoveTo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_arc_to_with_oval (sk_path_t param0, SKRect* oval, Single startAngle, Single sweepAngle, [MarshalAs (UnmanagedType.I1)] bool forceMoveTo);
+
+ // void sk_path_arc_to_with_points(sk_path_t*, float x1, float y1, float x2, float y2, float radius)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_arc_to_with_points (sk_path_t param0, Single x1, Single y1, Single x2, Single y2, Single radius);
+
+ // sk_path_t* sk_path_clone(const sk_path_t* cpath)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_t sk_path_clone (sk_path_t cpath);
+
+ // void sk_path_close(sk_path_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_close (sk_path_t param0);
+
+ // void sk_path_compute_tight_bounds(const sk_path_t*, sk_rect_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_compute_tight_bounds (sk_path_t param0, SKRect* param1);
+
+ // void sk_path_conic_to(sk_path_t*, float x0, float y0, float x1, float y1, float w)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_conic_to (sk_path_t param0, Single x0, Single y0, Single x1, Single y1, Single w);
+
+ // bool sk_path_contains(const sk_path_t* cpath, float x, float y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_path_contains (sk_path_t cpath, Single x, Single y);
+
+ // int sk_path_convert_conic_to_quads(const sk_point_t* p0, const sk_point_t* p1, const sk_point_t* p2, float w, sk_point_t* pts, int pow2)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_path_convert_conic_to_quads (SKPoint* p0, SKPoint* p1, SKPoint* p2, Single w, SKPoint* pts, Int32 pow2);
+
+ // int sk_path_count_points(const sk_path_t* cpath)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_path_count_points (sk_path_t cpath);
+
+ // int sk_path_count_verbs(const sk_path_t* cpath)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_path_count_verbs (sk_path_t cpath);
+
+ // sk_path_iterator_t* sk_path_create_iter(sk_path_t* cpath, int forceClose)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_iterator_t sk_path_create_iter (sk_path_t cpath, Int32 forceClose);
+
+ // sk_path_rawiterator_t* sk_path_create_rawiter(sk_path_t* cpath)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_rawiterator_t sk_path_create_rawiter (sk_path_t cpath);
+
+ // void sk_path_cubic_to(sk_path_t*, float x0, float y0, float x1, float y1, float x2, float y2)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_cubic_to (sk_path_t param0, Single x0, Single y0, Single x1, Single y1, Single x2, Single y2);
+
+ // void sk_path_delete(sk_path_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_delete (sk_path_t param0);
+
+ // void sk_path_get_bounds(const sk_path_t*, sk_rect_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_get_bounds (sk_path_t param0, SKRect* param1);
+
+ // sk_path_convexity_t sk_path_get_convexity(const sk_path_t* cpath)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKPathConvexity sk_path_get_convexity (sk_path_t cpath);
+
+ // sk_path_filltype_t sk_path_get_filltype(sk_path_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKPathFillType sk_path_get_filltype (sk_path_t param0);
+
+ // bool sk_path_get_last_point(const sk_path_t* cpath, sk_point_t* point)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_path_get_last_point (sk_path_t cpath, SKPoint* point);
+
+ // void sk_path_get_point(const sk_path_t* cpath, int index, sk_point_t* point)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_get_point (sk_path_t cpath, Int32 index, SKPoint* point);
+
+ // int sk_path_get_points(const sk_path_t* cpath, sk_point_t* points, int max)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_path_get_points (sk_path_t cpath, SKPoint* points, Int32 max);
+
+ // uint32_t sk_path_get_segment_masks(sk_path_t* cpath)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_path_get_segment_masks (sk_path_t cpath);
+
+ // bool sk_path_is_line(sk_path_t* cpath, sk_point_t[2] line = 2)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_path_is_line (sk_path_t cpath, SKPoint* line);
+
+ // bool sk_path_is_oval(sk_path_t* cpath, sk_rect_t* bounds)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_path_is_oval (sk_path_t cpath, SKRect* bounds);
+
+ // bool sk_path_is_rect(sk_path_t* cpath, sk_rect_t* rect, bool* isClosed, sk_path_direction_t* direction)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_path_is_rect (sk_path_t cpath, SKRect* rect, Byte* isClosed, SKPathDirection* direction);
+
+ // bool sk_path_is_rrect(sk_path_t* cpath, sk_rrect_t* bounds)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_path_is_rrect (sk_path_t cpath, sk_rrect_t bounds);
+
+ // float sk_path_iter_conic_weight(sk_path_iterator_t* iterator)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_path_iter_conic_weight (sk_path_iterator_t iterator);
+
+ // void sk_path_iter_destroy(sk_path_iterator_t* iterator)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_iter_destroy (sk_path_iterator_t iterator);
+
+ // int sk_path_iter_is_close_line(sk_path_iterator_t* iterator)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_path_iter_is_close_line (sk_path_iterator_t iterator);
+
+ // int sk_path_iter_is_closed_contour(sk_path_iterator_t* iterator)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_path_iter_is_closed_contour (sk_path_iterator_t iterator);
+
+ // sk_path_verb_t sk_path_iter_next(sk_path_iterator_t* iterator, sk_point_t[4] points = 4, int doConsumeDegenerates, int exact)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKPathVerb sk_path_iter_next (sk_path_iterator_t iterator, SKPoint* points, Int32 doConsumeDegenerates, Int32 exact);
+
+ // void sk_path_line_to(sk_path_t*, float x, float y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_line_to (sk_path_t param0, Single x, Single y);
+
+ // void sk_path_move_to(sk_path_t*, float x, float y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_move_to (sk_path_t param0, Single x, Single y);
+
+ // sk_path_t* sk_path_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_t sk_path_new ();
+
+ // bool sk_path_parse_svg_string(sk_path_t* cpath, const char* str)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_path_parse_svg_string (sk_path_t cpath, [MarshalAs (UnmanagedType.LPStr)] String str);
+
+ // void sk_path_quad_to(sk_path_t*, float x0, float y0, float x1, float y1)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_quad_to (sk_path_t param0, Single x0, Single y0, Single x1, Single y1);
+
+ // void sk_path_rarc_to(sk_path_t*, float rx, float ry, float xAxisRotate, sk_path_arc_size_t largeArc, sk_path_direction_t sweep, float x, float y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_rarc_to (sk_path_t param0, Single rx, Single ry, Single xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, Single x, Single y);
+
+ // float sk_path_rawiter_conic_weight(sk_path_rawiterator_t* iterator)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_path_rawiter_conic_weight (sk_path_rawiterator_t iterator);
+
+ // void sk_path_rawiter_destroy(sk_path_rawiterator_t* iterator)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_rawiter_destroy (sk_path_rawiterator_t iterator);
+
+ // sk_path_verb_t sk_path_rawiter_next(sk_path_rawiterator_t* iterator, sk_point_t[4] points = 4)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKPathVerb sk_path_rawiter_next (sk_path_rawiterator_t iterator, SKPoint* points);
+
+ // sk_path_verb_t sk_path_rawiter_peek(sk_path_rawiterator_t* iterator)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKPathVerb sk_path_rawiter_peek (sk_path_rawiterator_t iterator);
+
+ // void sk_path_rconic_to(sk_path_t*, float dx0, float dy0, float dx1, float dy1, float w)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_rconic_to (sk_path_t param0, Single dx0, Single dy0, Single dx1, Single dy1, Single w);
+
+ // void sk_path_rcubic_to(sk_path_t*, float dx0, float dy0, float dx1, float dy1, float dx2, float dy2)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_rcubic_to (sk_path_t param0, Single dx0, Single dy0, Single dx1, Single dy1, Single dx2, Single dy2);
+
+ // void sk_path_reset(sk_path_t* cpath)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_reset (sk_path_t cpath);
+
+ // void sk_path_rewind(sk_path_t* cpath)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_rewind (sk_path_t cpath);
+
+ // void sk_path_rline_to(sk_path_t*, float dx, float yd)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_rline_to (sk_path_t param0, Single dx, Single yd);
+
+ // void sk_path_rmove_to(sk_path_t*, float dx, float dy)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_rmove_to (sk_path_t param0, Single dx, Single dy);
+
+ // void sk_path_rquad_to(sk_path_t*, float dx0, float dy0, float dx1, float dy1)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_rquad_to (sk_path_t param0, Single dx0, Single dy0, Single dx1, Single dy1);
+
+ // void sk_path_set_convexity(sk_path_t* cpath, sk_path_convexity_t convexity)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_set_convexity (sk_path_t cpath, SKPathConvexity convexity);
+
+ // void sk_path_set_filltype(sk_path_t*, sk_path_filltype_t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_set_filltype (sk_path_t param0, SKPathFillType param1);
+
+ // void sk_path_to_svg_string(const sk_path_t* cpath, sk_string_t* str)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_to_svg_string (sk_path_t cpath, sk_string_t str);
+
+ // void sk_path_transform(sk_path_t* cpath, const sk_matrix_t* cmatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_transform (sk_path_t cpath, SKMatrix* cmatrix);
+
+ // void sk_path_transform_to_dest(sk_path_t* cpath, const sk_matrix_t* cmatrix, sk_path_t* destination)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_transform_to_dest (sk_path_t cpath, SKMatrix* cmatrix, sk_path_t destination);
+
+ // void sk_pathmeasure_destroy(sk_pathmeasure_t* pathMeasure)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_pathmeasure_destroy (sk_pathmeasure_t pathMeasure);
+
+ // float sk_pathmeasure_get_length(sk_pathmeasure_t* pathMeasure)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_pathmeasure_get_length (sk_pathmeasure_t pathMeasure);
+
+ // bool sk_pathmeasure_get_matrix(sk_pathmeasure_t* pathMeasure, float distance, sk_matrix_t* matrix, sk_pathmeasure_matrixflags_t flags)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pathmeasure_get_matrix (sk_pathmeasure_t pathMeasure, Single distance, SKMatrix* matrix, SKPathMeasureMatrixFlags flags);
+
+ // bool sk_pathmeasure_get_pos_tan(sk_pathmeasure_t* pathMeasure, float distance, sk_point_t* position, sk_vector_t* tangent)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pathmeasure_get_pos_tan (sk_pathmeasure_t pathMeasure, Single distance, SKPoint* position, SKPoint* tangent);
+
+ // bool sk_pathmeasure_get_segment(sk_pathmeasure_t* pathMeasure, float start, float stop, sk_path_t* dst, bool startWithMoveTo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pathmeasure_get_segment (sk_pathmeasure_t pathMeasure, Single start, Single stop, sk_path_t dst, [MarshalAs (UnmanagedType.I1)] bool startWithMoveTo);
+
+ // bool sk_pathmeasure_is_closed(sk_pathmeasure_t* pathMeasure)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pathmeasure_is_closed (sk_pathmeasure_t pathMeasure);
+
+ // sk_pathmeasure_t* sk_pathmeasure_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_pathmeasure_t sk_pathmeasure_new ();
+
+ // sk_pathmeasure_t* sk_pathmeasure_new_with_path(const sk_path_t* path, bool forceClosed, float resScale)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_pathmeasure_t sk_pathmeasure_new_with_path (sk_path_t path, [MarshalAs (UnmanagedType.I1)] bool forceClosed, Single resScale);
+
+ // bool sk_pathmeasure_next_contour(sk_pathmeasure_t* pathMeasure)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pathmeasure_next_contour (sk_pathmeasure_t pathMeasure);
+
+ // void sk_pathmeasure_set_path(sk_pathmeasure_t* pathMeasure, const sk_path_t* path, bool forceClosed)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_pathmeasure_set_path (sk_pathmeasure_t pathMeasure, sk_path_t path, [MarshalAs (UnmanagedType.I1)] bool forceClosed);
+
+ // bool sk_pathop_op(const sk_path_t* one, const sk_path_t* two, sk_pathop_t op, sk_path_t* result)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pathop_op (sk_path_t one, sk_path_t two, SKPathOp op, sk_path_t result);
+
+ // bool sk_pathop_simplify(const sk_path_t* path, sk_path_t* result)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pathop_simplify (sk_path_t path, sk_path_t result);
+
+ // bool sk_pathop_tight_bounds(const sk_path_t* path, sk_rect_t* result)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pathop_tight_bounds (sk_path_t path, SKRect* result);
+
+ #endregion
+
+ #region sk_patheffect.h
+
+ // sk_path_effect_t* sk_path_effect_create_1d_path(const sk_path_t* path, float advance, float phase, sk_path_effect_1d_style_t style)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_1d_path (sk_path_t path, Single advance, Single phase, SKPath1DPathEffectStyle style);
+
+ // sk_path_effect_t* sk_path_effect_create_2d_line(float width, const sk_matrix_t* matrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_2d_line (Single width, SKMatrix* matrix);
+
+ // sk_path_effect_t* sk_path_effect_create_2d_path(const sk_matrix_t* matrix, const sk_path_t* path)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_2d_path (SKMatrix* matrix, sk_path_t path);
+
+ // sk_path_effect_t* sk_path_effect_create_compose(sk_path_effect_t* outer, sk_path_effect_t* inner)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_compose (sk_path_effect_t outer, sk_path_effect_t inner);
+
+ // sk_path_effect_t* sk_path_effect_create_corner(float radius)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_corner (Single radius);
+
+ // sk_path_effect_t* sk_path_effect_create_dash(const float[-1] intervals, int count, float phase)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_dash (Single* intervals, Int32 count, Single phase);
+
+ // sk_path_effect_t* sk_path_effect_create_discrete(float segLength, float deviation, uint32_t seedAssist)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_discrete (Single segLength, Single deviation, UInt32 seedAssist);
+
+ // sk_path_effect_t* sk_path_effect_create_sum(sk_path_effect_t* first, sk_path_effect_t* second)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_sum (sk_path_effect_t first, sk_path_effect_t second);
+
+ // sk_path_effect_t* sk_path_effect_create_trim(float start, float stop, sk_path_effect_trim_mode_t mode)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_path_effect_t sk_path_effect_create_trim (Single start, Single stop, SKTrimPathEffectMode mode);
+
+ // void sk_path_effect_unref(sk_path_effect_t* t)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_path_effect_unref (sk_path_effect_t t);
+
+ #endregion
+
+ #region sk_picture.h
+
+ // void sk_picture_get_cull_rect(sk_picture_t*, sk_rect_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_picture_get_cull_rect (sk_picture_t param0, SKRect* param1);
+
+ // sk_canvas_t* sk_picture_get_recording_canvas(sk_picture_recorder_t* crec)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_canvas_t sk_picture_get_recording_canvas (sk_picture_recorder_t crec);
+
+ // uint32_t sk_picture_get_unique_id(sk_picture_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_picture_get_unique_id (sk_picture_t param0);
+
+ // sk_canvas_t* sk_picture_recorder_begin_recording(sk_picture_recorder_t*, const sk_rect_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_canvas_t sk_picture_recorder_begin_recording (sk_picture_recorder_t param0, SKRect* param1);
+
+ // void sk_picture_recorder_delete(sk_picture_recorder_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_picture_recorder_delete (sk_picture_recorder_t param0);
+
+ // sk_picture_t* sk_picture_recorder_end_recording(sk_picture_recorder_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_picture_t sk_picture_recorder_end_recording (sk_picture_recorder_t param0);
+
+ // sk_drawable_t* sk_picture_recorder_end_recording_as_drawable(sk_picture_recorder_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_drawable_t sk_picture_recorder_end_recording_as_drawable (sk_picture_recorder_t param0);
+
+ // sk_picture_recorder_t* sk_picture_recorder_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_picture_recorder_t sk_picture_recorder_new ();
+
+ // void sk_picture_ref(sk_picture_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_picture_ref (sk_picture_t param0);
+
+ // void sk_picture_unref(sk_picture_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_picture_unref (sk_picture_t param0);
+
+ #endregion
+
+ #region sk_pixmap.h
+
+ // void sk_color_get_bit_shift(int* a, int* r, int* g, int* b)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_color_get_bit_shift (Int32* a, Int32* r, Int32* g, Int32* b);
+
+ // sk_pmcolor_t sk_color_premultiply(const sk_color_t color)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_color_premultiply (UInt32 color);
+
+ // void sk_color_premultiply_array(const sk_color_t* colors, int size, sk_pmcolor_t* pmcolors)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_color_premultiply_array (UInt32* colors, Int32 size, UInt32* pmcolors);
+
+ // sk_color_t sk_color_unpremultiply(const sk_pmcolor_t pmcolor)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_color_unpremultiply (UInt32 pmcolor);
+
+ // void sk_color_unpremultiply_array(const sk_pmcolor_t* pmcolors, int size, sk_color_t* colors)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_color_unpremultiply_array (UInt32* pmcolors, Int32 size, UInt32* colors);
+
+ // bool sk_jpegencoder_encode(sk_wstream_t* dst, const sk_pixmap_t* src, const sk_jpegencoder_options_t* options)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_jpegencoder_encode (sk_wstream_t dst, sk_pixmap_t src, SKJpegEncoderOptions* options);
+
+ // void sk_pixmap_destructor(sk_pixmap_t* cpixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_pixmap_destructor (sk_pixmap_t cpixmap);
+
+ // bool sk_pixmap_encode_image(sk_wstream_t* dst, const sk_pixmap_t* src, sk_encoded_image_format_t encoder, int quality)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pixmap_encode_image (sk_wstream_t dst, sk_pixmap_t src, SKEncodedImageFormat encoder, Int32 quality);
+
+ // bool sk_pixmap_erase_color(const sk_pixmap_t* cpixmap, sk_color_t color, const sk_irect_t* subset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pixmap_erase_color (sk_pixmap_t cpixmap, UInt32 color, SKRectI* subset);
+
+ // bool sk_pixmap_erase_color4f(const sk_pixmap_t* cpixmap, const sk_color4f_t* color, const sk_irect_t* subset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pixmap_erase_color4f (sk_pixmap_t cpixmap, SKColorF* color, SKRectI* subset);
+
+ // bool sk_pixmap_extract_subset(const sk_pixmap_t* cpixmap, sk_pixmap_t* result, const sk_irect_t* subset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pixmap_extract_subset (sk_pixmap_t cpixmap, sk_pixmap_t result, SKRectI* subset);
+
+ // void sk_pixmap_get_info(const sk_pixmap_t* cpixmap, sk_imageinfo_t* cinfo)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_pixmap_get_info (sk_pixmap_t cpixmap, SKImageInfoNative* cinfo);
+
+ // sk_color_t sk_pixmap_get_pixel_color(const sk_pixmap_t* cpixmap, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_pixmap_get_pixel_color (sk_pixmap_t cpixmap, Int32 x, Int32 y);
+
+ // const void* sk_pixmap_get_pixels(const sk_pixmap_t* cpixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void* sk_pixmap_get_pixels (sk_pixmap_t cpixmap);
+
+ // const void* sk_pixmap_get_pixels_with_xy(const sk_pixmap_t* cpixmap, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void* sk_pixmap_get_pixels_with_xy (sk_pixmap_t cpixmap, Int32 x, Int32 y);
+
+ // size_t sk_pixmap_get_row_bytes(const sk_pixmap_t* cpixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_pixmap_get_row_bytes (sk_pixmap_t cpixmap);
+
+ // sk_pixmap_t* sk_pixmap_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_pixmap_t sk_pixmap_new ();
+
+ // sk_pixmap_t* sk_pixmap_new_with_params(const sk_imageinfo_t* cinfo, const void* addr, size_t rowBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_pixmap_t sk_pixmap_new_with_params (SKImageInfoNative* cinfo, void* addr, /* size_t */ IntPtr rowBytes);
+
+ // bool sk_pixmap_read_pixels(const sk_pixmap_t* cpixmap, const sk_imageinfo_t* dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY, sk_transfer_function_behavior_t behavior)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pixmap_read_pixels (sk_pixmap_t cpixmap, SKImageInfoNative* dstInfo, void* dstPixels, /* size_t */ IntPtr dstRowBytes, Int32 srcX, Int32 srcY, SKTransferFunctionBehavior behavior);
+
+ // void sk_pixmap_reset(sk_pixmap_t* cpixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_pixmap_reset (sk_pixmap_t cpixmap);
+
+ // void sk_pixmap_reset_with_params(sk_pixmap_t* cpixmap, const sk_imageinfo_t* cinfo, const void* addr, size_t rowBytes)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_pixmap_reset_with_params (sk_pixmap_t cpixmap, SKImageInfoNative* cinfo, void* addr, /* size_t */ IntPtr rowBytes);
+
+ // bool sk_pixmap_scale_pixels(const sk_pixmap_t* cpixmap, const sk_pixmap_t* dst, sk_filter_quality_t quality)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pixmap_scale_pixels (sk_pixmap_t cpixmap, sk_pixmap_t dst, SKFilterQuality quality);
+
+ // bool sk_pngencoder_encode(sk_wstream_t* dst, const sk_pixmap_t* src, const sk_pngencoder_options_t* options)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_pngencoder_encode (sk_wstream_t dst, sk_pixmap_t src, SKPngEncoderOptions* options);
+
+ // void sk_swizzle_swap_rb(uint32_t* dest, const uint32_t* src, int count)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_swizzle_swap_rb (UInt32* dest, UInt32* src, Int32 count);
+
+ // bool sk_webpencoder_encode(sk_wstream_t* dst, const sk_pixmap_t* src, const sk_webpencoder_options_t* options)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_webpencoder_encode (sk_wstream_t dst, sk_pixmap_t src, SKWebpEncoderOptions* options);
+
+ #endregion
+
+ #region sk_region.h
+
+ // void sk_region_cliperator_delete(sk_region_cliperator_t* iter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_cliperator_delete (sk_region_cliperator_t iter);
+
+ // bool sk_region_cliperator_done(sk_region_cliperator_t* iter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_cliperator_done (sk_region_cliperator_t iter);
+
+ // sk_region_cliperator_t* sk_region_cliperator_new(const sk_region_t* region, const sk_irect_t* clip)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_region_cliperator_t sk_region_cliperator_new (sk_region_t region, SKRectI* clip);
+
+ // void sk_region_cliperator_next(sk_region_cliperator_t* iter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_cliperator_next (sk_region_cliperator_t iter);
+
+ // void sk_region_cliperator_rect(const sk_region_cliperator_t* iter, sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_cliperator_rect (sk_region_cliperator_t iter, SKRectI* rect);
+
+ // bool sk_region_contains(const sk_region_t* r, const sk_region_t* region)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_contains (sk_region_t r, sk_region_t region);
+
+ // bool sk_region_contains_point(const sk_region_t* r, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_contains_point (sk_region_t r, Int32 x, Int32 y);
+
+ // bool sk_region_contains_rect(const sk_region_t* r, const sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_contains_rect (sk_region_t r, SKRectI* rect);
+
+ // void sk_region_delete(sk_region_t* r)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_delete (sk_region_t r);
+
+ // bool sk_region_get_boundary_path(const sk_region_t* r, sk_path_t* path)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_get_boundary_path (sk_region_t r, sk_path_t path);
+
+ // void sk_region_get_bounds(const sk_region_t* r, sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_get_bounds (sk_region_t r, SKRectI* rect);
+
+ // bool sk_region_intersects(const sk_region_t* r, const sk_region_t* src)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_intersects (sk_region_t r, sk_region_t src);
+
+ // bool sk_region_intersects_rect(const sk_region_t* r, const sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_intersects_rect (sk_region_t r, SKRectI* rect);
+
+ // bool sk_region_is_complex(const sk_region_t* r)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_is_complex (sk_region_t r);
+
+ // bool sk_region_is_empty(const sk_region_t* r)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_is_empty (sk_region_t r);
+
+ // bool sk_region_is_rect(const sk_region_t* r)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_is_rect (sk_region_t r);
+
+ // void sk_region_iterator_delete(sk_region_iterator_t* iter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_iterator_delete (sk_region_iterator_t iter);
+
+ // bool sk_region_iterator_done(const sk_region_iterator_t* iter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_iterator_done (sk_region_iterator_t iter);
+
+ // sk_region_iterator_t* sk_region_iterator_new(const sk_region_t* region)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_region_iterator_t sk_region_iterator_new (sk_region_t region);
+
+ // void sk_region_iterator_next(sk_region_iterator_t* iter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_iterator_next (sk_region_iterator_t iter);
+
+ // void sk_region_iterator_rect(const sk_region_iterator_t* iter, sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_iterator_rect (sk_region_iterator_t iter, SKRectI* rect);
+
+ // bool sk_region_iterator_rewind(sk_region_iterator_t* iter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_iterator_rewind (sk_region_iterator_t iter);
+
+ // sk_region_t* sk_region_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_region_t sk_region_new ();
+
+ // bool sk_region_op(sk_region_t* r, const sk_region_t* region, sk_region_op_t op)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_op (sk_region_t r, sk_region_t region, SKRegionOperation op);
+
+ // bool sk_region_op_rect(sk_region_t* r, const sk_irect_t* rect, sk_region_op_t op)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_op_rect (sk_region_t r, SKRectI* rect, SKRegionOperation op);
+
+ // bool sk_region_quick_contains(const sk_region_t* r, const sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_quick_contains (sk_region_t r, SKRectI* rect);
+
+ // bool sk_region_quick_reject(const sk_region_t* r, const sk_region_t* region)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_quick_reject (sk_region_t r, sk_region_t region);
+
+ // bool sk_region_quick_reject_rect(const sk_region_t* r, const sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_quick_reject_rect (sk_region_t r, SKRectI* rect);
+
+ // bool sk_region_set_empty(sk_region_t* r)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_set_empty (sk_region_t r);
+
+ // bool sk_region_set_path(sk_region_t* r, const sk_path_t* t, const sk_region_t* clip)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_set_path (sk_region_t r, sk_path_t t, sk_region_t clip);
+
+ // bool sk_region_set_rect(sk_region_t* r, const sk_irect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_set_rect (sk_region_t r, SKRectI* rect);
+
+ // bool sk_region_set_rects(sk_region_t* r, const sk_irect_t* rects, int count)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_set_rects (sk_region_t r, SKRectI* rects, Int32 count);
+
+ // bool sk_region_set_region(sk_region_t* r, const sk_region_t* region)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_set_region (sk_region_t r, sk_region_t region);
+
+ // void sk_region_spanerator_delete(sk_region_spanerator_t* iter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_spanerator_delete (sk_region_spanerator_t iter);
+
+ // sk_region_spanerator_t* sk_region_spanerator_new(const sk_region_t* region, int y, int left, int right)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_region_spanerator_t sk_region_spanerator_new (sk_region_t region, Int32 y, Int32 left, Int32 right);
+
+ // bool sk_region_spanerator_next(sk_region_spanerator_t* iter, int* left, int* right)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_region_spanerator_next (sk_region_spanerator_t iter, Int32* left, Int32* right);
+
+ // void sk_region_translate(sk_region_t* r, int x, int y)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_region_translate (sk_region_t r, Int32 x, Int32 y);
+
+ #endregion
+
+ #region sk_rrect.h
+
+ // bool sk_rrect_contains(const sk_rrect_t* rrect, const sk_rect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_rrect_contains (sk_rrect_t rrect, SKRect* rect);
+
+ // void sk_rrect_delete(const sk_rrect_t* rrect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_delete (sk_rrect_t rrect);
+
+ // float sk_rrect_get_height(const sk_rrect_t* rrect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_rrect_get_height (sk_rrect_t rrect);
+
+ // void sk_rrect_get_radii(const sk_rrect_t* rrect, sk_rrect_corner_t corner, sk_vector_t* radii)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_get_radii (sk_rrect_t rrect, SKRoundRectCorner corner, SKPoint* radii);
+
+ // void sk_rrect_get_rect(const sk_rrect_t* rrect, sk_rect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_get_rect (sk_rrect_t rrect, SKRect* rect);
+
+ // sk_rrect_type_t sk_rrect_get_type(const sk_rrect_t* rrect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKRoundRectType sk_rrect_get_type (sk_rrect_t rrect);
+
+ // float sk_rrect_get_width(const sk_rrect_t* rrect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Single sk_rrect_get_width (sk_rrect_t rrect);
+
+ // void sk_rrect_inset(sk_rrect_t* rrect, float dx, float dy)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_inset (sk_rrect_t rrect, Single dx, Single dy);
+
+ // bool sk_rrect_is_valid(const sk_rrect_t* rrect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_rrect_is_valid (sk_rrect_t rrect);
+
+ // sk_rrect_t* sk_rrect_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_rrect_t sk_rrect_new ();
+
+ // sk_rrect_t* sk_rrect_new_copy(const sk_rrect_t* rrect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_rrect_t sk_rrect_new_copy (sk_rrect_t rrect);
+
+ // void sk_rrect_offset(sk_rrect_t* rrect, float dx, float dy)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_offset (sk_rrect_t rrect, Single dx, Single dy);
+
+ // void sk_rrect_outset(sk_rrect_t* rrect, float dx, float dy)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_outset (sk_rrect_t rrect, Single dx, Single dy);
+
+ // void sk_rrect_set_empty(sk_rrect_t* rrect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_set_empty (sk_rrect_t rrect);
+
+ // void sk_rrect_set_nine_patch(sk_rrect_t* rrect, const sk_rect_t* rect, float leftRad, float topRad, float rightRad, float bottomRad)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_set_nine_patch (sk_rrect_t rrect, SKRect* rect, Single leftRad, Single topRad, Single rightRad, Single bottomRad);
+
+ // void sk_rrect_set_oval(sk_rrect_t* rrect, const sk_rect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_set_oval (sk_rrect_t rrect, SKRect* rect);
+
+ // void sk_rrect_set_rect(sk_rrect_t* rrect, const sk_rect_t* rect)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_set_rect (sk_rrect_t rrect, SKRect* rect);
+
+ // void sk_rrect_set_rect_radii(sk_rrect_t* rrect, const sk_rect_t* rect, const sk_vector_t* radii)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_set_rect_radii (sk_rrect_t rrect, SKRect* rect, SKPoint* radii);
+
+ // void sk_rrect_set_rect_xy(sk_rrect_t* rrect, const sk_rect_t* rect, float xRad, float yRad)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_rrect_set_rect_xy (sk_rrect_t rrect, SKRect* rect, Single xRad, Single yRad);
+
+ // bool sk_rrect_transform(sk_rrect_t* rrect, const sk_matrix_t* matrix, sk_rrect_t* dest)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_rrect_transform (sk_rrect_t rrect, SKMatrix* matrix, sk_rrect_t dest);
+
+ #endregion
+
+ #region sk_shader.h
+
+ // sk_shader_t* sk_shader_new_bitmap(const sk_bitmap_t* src, sk_shader_tilemode_t tmx, sk_shader_tilemode_t tmy, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_bitmap (sk_bitmap_t src, SKShaderTileMode tmx, SKShaderTileMode tmy, SKMatrix* localMatrix);
+
+ // sk_shader_t* sk_shader_new_color(sk_color_t color)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_color (UInt32 color);
+
+ // sk_shader_t* sk_shader_new_color4f(const sk_color4f_t* color, const sk_colorspace_t* colorspace)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_color4f (SKColorF* color, sk_colorspace_t colorspace);
+
+ // sk_shader_t* sk_shader_new_compose(const sk_shader_t* shaderA, const sk_shader_t* shaderB, sk_blendmode_t mode)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_compose (sk_shader_t shaderA, sk_shader_t shaderB, SKBlendMode mode);
+
+ // sk_shader_t* sk_shader_new_empty()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_empty ();
+
+ // sk_shader_t* sk_shader_new_linear_gradient(const sk_point_t[2] points = 2, const sk_color_t[-1] colors, const float[-1] colorPos, int colorCount, sk_shader_tilemode_t tileMode, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_linear_gradient (SKPoint* points, UInt32* colors, Single* colorPos, Int32 colorCount, SKShaderTileMode tileMode, SKMatrix* localMatrix);
+
+ // sk_shader_t* sk_shader_new_linear_gradient_color4f(const sk_point_t[2] points = 2, const sk_color4f_t* colors, const sk_colorspace_t* colorspace, const float[-1] colorPos, int colorCount, sk_shader_tilemode_t tileMode, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_linear_gradient_color4f (SKPoint* points, SKColorF* colors, sk_colorspace_t colorspace, Single* colorPos, Int32 colorCount, SKShaderTileMode tileMode, SKMatrix* localMatrix);
+
+ // sk_shader_t* sk_shader_new_perlin_noise_fractal_noise(float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, const sk_isize_t* tileSize)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_perlin_noise_fractal_noise (Single baseFrequencyX, Single baseFrequencyY, Int32 numOctaves, Single seed, SKSizeI* tileSize);
+
+ // sk_shader_t* sk_shader_new_perlin_noise_improved_noise(float baseFrequencyX, float baseFrequencyY, int numOctaves, float z)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_perlin_noise_improved_noise (Single baseFrequencyX, Single baseFrequencyY, Int32 numOctaves, Single z);
+
+ // sk_shader_t* sk_shader_new_perlin_noise_turbulence(float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, const sk_isize_t* tileSize)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_perlin_noise_turbulence (Single baseFrequencyX, Single baseFrequencyY, Int32 numOctaves, Single seed, SKSizeI* tileSize);
+
+ // sk_shader_t* sk_shader_new_picture(sk_picture_t* src, sk_shader_tilemode_t tmx, sk_shader_tilemode_t tmy, const sk_matrix_t* localMatrix, const sk_rect_t* tile)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_picture (sk_picture_t src, SKShaderTileMode tmx, SKShaderTileMode tmy, SKMatrix* localMatrix, SKRect* tile);
+
+ // sk_shader_t* sk_shader_new_radial_gradient(const sk_point_t* center, float radius, const sk_color_t[-1] colors, const float[-1] colorPos, int colorCount, sk_shader_tilemode_t tileMode, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_radial_gradient (SKPoint* center, Single radius, UInt32* colors, Single* colorPos, Int32 colorCount, SKShaderTileMode tileMode, SKMatrix* localMatrix);
+
+ // sk_shader_t* sk_shader_new_radial_gradient_color4f(const sk_point_t* center, float radius, const sk_color4f_t* colors, const sk_colorspace_t* colorspace, const float[-1] colorPos, int colorCount, sk_shader_tilemode_t tileMode, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_radial_gradient_color4f (SKPoint* center, Single radius, SKColorF* colors, sk_colorspace_t colorspace, Single* colorPos, Int32 colorCount, SKShaderTileMode tileMode, SKMatrix* localMatrix);
+
+ // sk_shader_t* sk_shader_new_sweep_gradient(const sk_point_t* center, const sk_color_t[-1] colors, const float[-1] colorPos, int colorCount, sk_shader_tilemode_t tileMode, float startAngle, float endAngle, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_sweep_gradient (SKPoint* center, UInt32* colors, Single* colorPos, Int32 colorCount, SKShaderTileMode tileMode, Single startAngle, Single endAngle, SKMatrix* localMatrix);
+
+ // sk_shader_t* sk_shader_new_sweep_gradient_color4f(const sk_point_t* center, const sk_color4f_t* colors, const sk_colorspace_t* colorspace, const float[-1] colorPos, int colorCount, sk_shader_tilemode_t tileMode, float startAngle, float endAngle, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_sweep_gradient_color4f (SKPoint* center, SKColorF* colors, sk_colorspace_t colorspace, Single* colorPos, Int32 colorCount, SKShaderTileMode tileMode, Single startAngle, Single endAngle, SKMatrix* localMatrix);
+
+ // sk_shader_t* sk_shader_new_two_point_conical_gradient(const sk_point_t* start, float startRadius, const sk_point_t* end, float endRadius, const sk_color_t[-1] colors, const float[-1] colorPos, int colorCount, sk_shader_tilemode_t tileMode, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_two_point_conical_gradient (SKPoint* start, Single startRadius, SKPoint* end, Single endRadius, UInt32* colors, Single* colorPos, Int32 colorCount, SKShaderTileMode tileMode, SKMatrix* localMatrix);
+
+ // sk_shader_t* sk_shader_new_two_point_conical_gradient_color4f(const sk_point_t* start, float startRadius, const sk_point_t* end, float endRadius, const sk_color4f_t* colors, const sk_colorspace_t* colorspace, const float[-1] colorPos, int colorCount, sk_shader_tilemode_t tileMode, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_new_two_point_conical_gradient_color4f (SKPoint* start, Single startRadius, SKPoint* end, Single endRadius, SKColorF* colors, sk_colorspace_t colorspace, Single* colorPos, Int32 colorCount, SKShaderTileMode tileMode, SKMatrix* localMatrix);
+
+ // void sk_shader_ref(sk_shader_t* shader)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_shader_ref (sk_shader_t shader);
+
+ // void sk_shader_unref(sk_shader_t* shader)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_shader_unref (sk_shader_t shader);
+
+ // sk_shader_t* sk_shader_with_color_filter(const sk_shader_t* shader, const sk_colorfilter_t* filter)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_with_color_filter (sk_shader_t shader, sk_colorfilter_t filter);
+
+ // sk_shader_t* sk_shader_with_local_matrix(const sk_shader_t* shader, const sk_matrix_t* localMatrix)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_shader_t sk_shader_with_local_matrix (sk_shader_t shader, SKMatrix* localMatrix);
+
+ #endregion
+
+ #region sk_stream.h
+
+ // void sk_dynamicmemorywstream_copy_to(sk_wstream_dynamicmemorystream_t* cstream, void* data)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_dynamicmemorywstream_copy_to (sk_wstream_dynamicmemorystream_t cstream, void* data);
+
+ // void sk_dynamicmemorywstream_destroy(sk_wstream_dynamicmemorystream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_dynamicmemorywstream_destroy (sk_wstream_dynamicmemorystream_t cstream);
+
+ // sk_data_t* sk_dynamicmemorywstream_detach_as_data(sk_wstream_dynamicmemorystream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_data_t sk_dynamicmemorywstream_detach_as_data (sk_wstream_dynamicmemorystream_t cstream);
+
+ // sk_stream_asset_t* sk_dynamicmemorywstream_detach_as_stream(sk_wstream_dynamicmemorystream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_asset_t sk_dynamicmemorywstream_detach_as_stream (sk_wstream_dynamicmemorystream_t cstream);
+
+ // sk_wstream_dynamicmemorystream_t* sk_dynamicmemorywstream_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_wstream_dynamicmemorystream_t sk_dynamicmemorywstream_new ();
+
+ // bool sk_dynamicmemorywstream_write_to_stream(sk_wstream_dynamicmemorystream_t* cstream, sk_wstream_t* dst)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_dynamicmemorywstream_write_to_stream (sk_wstream_dynamicmemorystream_t cstream, sk_wstream_t dst);
+
+ // void sk_filestream_destroy(sk_stream_filestream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_filestream_destroy (sk_stream_filestream_t cstream);
+
+ // bool sk_filestream_is_valid(sk_stream_filestream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_filestream_is_valid (sk_stream_filestream_t cstream);
+
+ // sk_stream_filestream_t* sk_filestream_new(const char* path)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_filestream_t sk_filestream_new (/* char */ void* path);
+
+ // void sk_filewstream_destroy(sk_wstream_filestream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_filewstream_destroy (sk_wstream_filestream_t cstream);
+
+ // bool sk_filewstream_is_valid(sk_wstream_filestream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_filewstream_is_valid (sk_wstream_filestream_t cstream);
+
+ // sk_wstream_filestream_t* sk_filewstream_new(const char* path)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_wstream_filestream_t sk_filewstream_new (/* char */ void* path);
+
+ // void sk_memorystream_destroy(sk_stream_memorystream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_memorystream_destroy (sk_stream_memorystream_t cstream);
+
+ // sk_stream_memorystream_t* sk_memorystream_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_memorystream_t sk_memorystream_new ();
+
+ // sk_stream_memorystream_t* sk_memorystream_new_with_data(const void* data, size_t length, bool copyData)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_memorystream_t sk_memorystream_new_with_data (void* data, /* size_t */ IntPtr length, [MarshalAs (UnmanagedType.I1)] bool copyData);
+
+ // sk_stream_memorystream_t* sk_memorystream_new_with_length(size_t length)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_memorystream_t sk_memorystream_new_with_length (/* size_t */ IntPtr length);
+
+ // sk_stream_memorystream_t* sk_memorystream_new_with_skdata(sk_data_t* data)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_memorystream_t sk_memorystream_new_with_skdata (sk_data_t data);
+
+ // void sk_memorystream_set_memory(sk_stream_memorystream_t* cmemorystream, const void* data, size_t length, bool copyData)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_memorystream_set_memory (sk_stream_memorystream_t cmemorystream, void* data, /* size_t */ IntPtr length, [MarshalAs (UnmanagedType.I1)] bool copyData);
+
+ // void sk_stream_asset_destroy(sk_stream_asset_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_stream_asset_destroy (sk_stream_asset_t cstream);
+
+ // void sk_stream_destroy(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_stream_destroy (sk_stream_t cstream);
+
+ // sk_stream_t* sk_stream_duplicate(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_t sk_stream_duplicate (sk_stream_t cstream);
+
+ // sk_stream_t* sk_stream_fork(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_t sk_stream_fork (sk_stream_t cstream);
+
+ // size_t sk_stream_get_length(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_stream_get_length (sk_stream_t cstream);
+
+ // const void* sk_stream_get_memory_base(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void* sk_stream_get_memory_base (sk_stream_t cstream);
+
+ // size_t sk_stream_get_position(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_stream_get_position (sk_stream_t cstream);
+
+ // bool sk_stream_has_length(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_has_length (sk_stream_t cstream);
+
+ // bool sk_stream_has_position(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_has_position (sk_stream_t cstream);
+
+ // bool sk_stream_is_at_end(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_is_at_end (sk_stream_t cstream);
+
+ // bool sk_stream_move(sk_stream_t* cstream, int offset)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_move (sk_stream_t cstream, Int32 offset);
+
+ // size_t sk_stream_peek(sk_stream_t* cstream, void* buffer, size_t size)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_stream_peek (sk_stream_t cstream, void* buffer, /* size_t */ IntPtr size);
+
+ // size_t sk_stream_read(sk_stream_t* cstream, void* buffer, size_t size)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_stream_read (sk_stream_t cstream, void* buffer, /* size_t */ IntPtr size);
+
+ // bool sk_stream_read_bool(sk_stream_t* cstream, bool* buffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_read_bool (sk_stream_t cstream, Byte* buffer);
+
+ // bool sk_stream_read_s16(sk_stream_t* cstream, int16_t* buffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_read_s16 (sk_stream_t cstream, Int16* buffer);
+
+ // bool sk_stream_read_s32(sk_stream_t* cstream, int32_t* buffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_read_s32 (sk_stream_t cstream, Int32* buffer);
+
+ // bool sk_stream_read_s8(sk_stream_t* cstream, int8_t* buffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_read_s8 (sk_stream_t cstream, SByte* buffer);
+
+ // bool sk_stream_read_u16(sk_stream_t* cstream, uint16_t* buffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_read_u16 (sk_stream_t cstream, UInt16* buffer);
+
+ // bool sk_stream_read_u32(sk_stream_t* cstream, uint32_t* buffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_read_u32 (sk_stream_t cstream, UInt32* buffer);
+
+ // bool sk_stream_read_u8(sk_stream_t* cstream, uint8_t* buffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_read_u8 (sk_stream_t cstream, Byte* buffer);
+
+ // bool sk_stream_rewind(sk_stream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_rewind (sk_stream_t cstream);
+
+ // bool sk_stream_seek(sk_stream_t* cstream, size_t position)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_stream_seek (sk_stream_t cstream, /* size_t */ IntPtr position);
+
+ // size_t sk_stream_skip(sk_stream_t* cstream, size_t size)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_stream_skip (sk_stream_t cstream, /* size_t */ IntPtr size);
+
+ // size_t sk_wstream_bytes_written(sk_wstream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_wstream_bytes_written (sk_wstream_t cstream);
+
+ // void sk_wstream_flush(sk_wstream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_wstream_flush (sk_wstream_t cstream);
+
+ // int sk_wstream_get_size_of_packed_uint(size_t value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_wstream_get_size_of_packed_uint (/* size_t */ IntPtr value);
+
+ // bool sk_wstream_newline(sk_wstream_t* cstream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_newline (sk_wstream_t cstream);
+
+ // bool sk_wstream_write(sk_wstream_t* cstream, const void* buffer, size_t size)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write (sk_wstream_t cstream, void* buffer, /* size_t */ IntPtr size);
+
+ // bool sk_wstream_write_16(sk_wstream_t* cstream, uint16_t value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_16 (sk_wstream_t cstream, UInt16 value);
+
+ // bool sk_wstream_write_32(sk_wstream_t* cstream, uint32_t value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_32 (sk_wstream_t cstream, UInt32 value);
+
+ // bool sk_wstream_write_8(sk_wstream_t* cstream, uint8_t value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_8 (sk_wstream_t cstream, Byte value);
+
+ // bool sk_wstream_write_bigdec_as_text(sk_wstream_t* cstream, int64_t value, int minDigits)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_bigdec_as_text (sk_wstream_t cstream, Int64 value, Int32 minDigits);
+
+ // bool sk_wstream_write_bool(sk_wstream_t* cstream, bool value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_bool (sk_wstream_t cstream, [MarshalAs (UnmanagedType.I1)] bool value);
+
+ // bool sk_wstream_write_dec_as_text(sk_wstream_t* cstream, int32_t value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_dec_as_text (sk_wstream_t cstream, Int32 value);
+
+ // bool sk_wstream_write_hex_as_text(sk_wstream_t* cstream, uint32_t value, int minDigits)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_hex_as_text (sk_wstream_t cstream, UInt32 value, Int32 minDigits);
+
+ // bool sk_wstream_write_packed_uint(sk_wstream_t* cstream, size_t value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_packed_uint (sk_wstream_t cstream, /* size_t */ IntPtr value);
+
+ // bool sk_wstream_write_scalar(sk_wstream_t* cstream, float value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_scalar (sk_wstream_t cstream, Single value);
+
+ // bool sk_wstream_write_scalar_as_text(sk_wstream_t* cstream, float value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_scalar_as_text (sk_wstream_t cstream, Single value);
+
+ // bool sk_wstream_write_stream(sk_wstream_t* cstream, sk_stream_t* input, size_t length)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_stream (sk_wstream_t cstream, sk_stream_t input, /* size_t */ IntPtr length);
+
+ // bool sk_wstream_write_text(sk_wstream_t* cstream, const char* value)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_wstream_write_text (sk_wstream_t cstream, [MarshalAs (UnmanagedType.LPStr)] String value);
+
+ #endregion
+
+ #region sk_string.h
+
+ // void sk_string_destructor(const sk_string_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_string_destructor (sk_string_t param0);
+
+ // const char* sk_string_get_c_str(const sk_string_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* char */ void* sk_string_get_c_str (sk_string_t param0);
+
+ // size_t sk_string_get_size(const sk_string_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_string_get_size (sk_string_t param0);
+
+ // sk_string_t* sk_string_new_empty()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_string_t sk_string_new_empty ();
+
+ // sk_string_t* sk_string_new_with_copy(const char* src, size_t length)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_string_t sk_string_new_with_copy (/* char */ void* src, /* size_t */ IntPtr length);
+
+ #endregion
+
+ #region sk_surface.h
+
+ // void sk_surface_draw(sk_surface_t* surface, sk_canvas_t* canvas, float x, float y, const sk_paint_t* paint)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_surface_draw (sk_surface_t surface, sk_canvas_t canvas, Single x, Single y, sk_paint_t paint);
+
+ // sk_canvas_t* sk_surface_get_canvas(sk_surface_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_canvas_t sk_surface_get_canvas (sk_surface_t param0);
+
+ // const sk_surfaceprops_t* sk_surface_get_props(sk_surface_t* surface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surfaceprops_t sk_surface_get_props (sk_surface_t surface);
+
+ // sk_surface_t* sk_surface_new_backend_render_target(gr_context_t* context, const gr_backendrendertarget_t* target, gr_surfaceorigin_t origin, sk_colortype_t colorType, sk_colorspace_t* colorspace, const sk_surfaceprops_t* props)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surface_t sk_surface_new_backend_render_target (gr_context_t context, gr_backendrendertarget_t target, GRSurfaceOrigin origin, SKColorType colorType, sk_colorspace_t colorspace, sk_surfaceprops_t props);
+
+ // sk_surface_t* sk_surface_new_backend_texture(gr_context_t* context, const gr_backendtexture_t* texture, gr_surfaceorigin_t origin, int samples, sk_colortype_t colorType, sk_colorspace_t* colorspace, const sk_surfaceprops_t* props)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surface_t sk_surface_new_backend_texture (gr_context_t context, gr_backendtexture_t texture, GRSurfaceOrigin origin, Int32 samples, SKColorType colorType, sk_colorspace_t colorspace, sk_surfaceprops_t props);
+
+ // sk_surface_t* sk_surface_new_backend_texture_as_render_target(gr_context_t* context, const gr_backendtexture_t* texture, gr_surfaceorigin_t origin, int samples, sk_colortype_t colorType, sk_colorspace_t* colorspace, const sk_surfaceprops_t* props)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surface_t sk_surface_new_backend_texture_as_render_target (gr_context_t context, gr_backendtexture_t texture, GRSurfaceOrigin origin, Int32 samples, SKColorType colorType, sk_colorspace_t colorspace, sk_surfaceprops_t props);
+
+ // sk_image_t* sk_surface_new_image_snapshot(sk_surface_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_image_t sk_surface_new_image_snapshot (sk_surface_t param0);
+
+ // sk_surface_t* sk_surface_new_null(int width, int height)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surface_t sk_surface_new_null (Int32 width, Int32 height);
+
+ // sk_surface_t* sk_surface_new_raster(const sk_imageinfo_t*, size_t rowBytes, const sk_surfaceprops_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surface_t sk_surface_new_raster (SKImageInfoNative* param0, /* size_t */ IntPtr rowBytes, sk_surfaceprops_t param2);
+
+ // sk_surface_t* sk_surface_new_raster_direct(const sk_imageinfo_t*, void* pixels, size_t rowBytes, const sk_surface_raster_release_proc releaseProc, void* context, const sk_surfaceprops_t* props)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surface_t sk_surface_new_raster_direct (SKImageInfoNative* param0, void* pixels, /* size_t */ IntPtr rowBytes, SKSurfaceRasterReleaseProxyDelegate releaseProc, void* context, sk_surfaceprops_t props);
+
+ // sk_surface_t* sk_surface_new_render_target(gr_context_t* context, bool budgeted, const sk_imageinfo_t* cinfo, int sampleCount, gr_surfaceorigin_t origin, const sk_surfaceprops_t* props, bool shouldCreateWithMips)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surface_t sk_surface_new_render_target (gr_context_t context, [MarshalAs (UnmanagedType.I1)] bool budgeted, SKImageInfoNative* cinfo, Int32 sampleCount, GRSurfaceOrigin origin, sk_surfaceprops_t props, [MarshalAs (UnmanagedType.I1)] bool shouldCreateWithMips);
+
+ // bool sk_surface_peek_pixels(sk_surface_t* surface, sk_pixmap_t* pixmap)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_surface_peek_pixels (sk_surface_t surface, sk_pixmap_t pixmap);
+
+ // bool sk_surface_read_pixels(sk_surface_t* surface, sk_imageinfo_t* dstInfo, void* dstPixels, size_t dstRowBytes, int srcX, int srcY)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_surface_read_pixels (sk_surface_t surface, SKImageInfoNative* dstInfo, void* dstPixels, /* size_t */ IntPtr dstRowBytes, Int32 srcX, Int32 srcY);
+
+ // void sk_surface_unref(sk_surface_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_surface_unref (sk_surface_t param0);
+
+ // void sk_surfaceprops_delete(sk_surfaceprops_t* props)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_surfaceprops_delete (sk_surfaceprops_t props);
+
+ // uint32_t sk_surfaceprops_get_flags(sk_surfaceprops_t* props)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_surfaceprops_get_flags (sk_surfaceprops_t props);
+
+ // sk_pixelgeometry_t sk_surfaceprops_get_pixel_geometry(sk_surfaceprops_t* props)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKPixelGeometry sk_surfaceprops_get_pixel_geometry (sk_surfaceprops_t props);
+
+ // sk_surfaceprops_t* sk_surfaceprops_new(uint32_t flags, sk_pixelgeometry_t geometry)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_surfaceprops_t sk_surfaceprops_new (UInt32 flags, SKPixelGeometry geometry);
+
+ #endregion
+
+ #region sk_svg.h
+
+ // sk_canvas_t* sk_svgcanvas_create_with_stream(const sk_rect_t* bounds, sk_wstream_t* stream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_canvas_t sk_svgcanvas_create_with_stream (SKRect* bounds, sk_wstream_t stream);
+
+ // sk_canvas_t* sk_svgcanvas_create_with_writer(const sk_rect_t* bounds, sk_xmlwriter_t* writer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_canvas_t sk_svgcanvas_create_with_writer (SKRect* bounds, sk_xmlwriter_t writer);
+
+ #endregion
+
+ #region sk_textblob.h
+
+ // void sk_textblob_builder_alloc_run_text(sk_textblob_builder_t* builder, const sk_paint_t* font, int count, float x, float y, int textByteCount, const sk_rect_t* bounds, sk_textblob_builder_runbuffer_t* runbuffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_textblob_builder_alloc_run_text (sk_textblob_builder_t builder, sk_paint_t font, Int32 count, Single x, Single y, Int32 textByteCount, SKRect* bounds, SKRunBufferInternal* runbuffer);
+
+ // void sk_textblob_builder_alloc_run_text_pos(sk_textblob_builder_t* builder, const sk_paint_t* font, int count, int textByteCount, const sk_rect_t* bounds, sk_textblob_builder_runbuffer_t* runbuffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_textblob_builder_alloc_run_text_pos (sk_textblob_builder_t builder, sk_paint_t font, Int32 count, Int32 textByteCount, SKRect* bounds, SKRunBufferInternal* runbuffer);
+
+ // void sk_textblob_builder_alloc_run_text_pos_h(sk_textblob_builder_t* builder, const sk_paint_t* font, int count, float y, int textByteCount, const sk_rect_t* bounds, sk_textblob_builder_runbuffer_t* runbuffer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_textblob_builder_alloc_run_text_pos_h (sk_textblob_builder_t builder, sk_paint_t font, Int32 count, Single y, Int32 textByteCount, SKRect* bounds, SKRunBufferInternal* runbuffer);
+
+ // void sk_textblob_builder_delete(sk_textblob_builder_t* builder)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_textblob_builder_delete (sk_textblob_builder_t builder);
+
+ // sk_textblob_t* sk_textblob_builder_make(sk_textblob_builder_t* builder)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_textblob_t sk_textblob_builder_make (sk_textblob_builder_t builder);
+
+ // sk_textblob_builder_t* sk_textblob_builder_new()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_textblob_builder_t sk_textblob_builder_new ();
+
+ // void sk_textblob_get_bounds(const sk_textblob_t* blob, sk_rect_t* bounds)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_textblob_get_bounds (sk_textblob_t blob, SKRect* bounds);
+
+ // uint32_t sk_textblob_get_unique_id(const sk_textblob_t* blob)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern UInt32 sk_textblob_get_unique_id (sk_textblob_t blob);
+
+ // void sk_textblob_ref(const sk_textblob_t* blob)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_textblob_ref (sk_textblob_t blob);
+
+ // void sk_textblob_unref(const sk_textblob_t* blob)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_textblob_unref (sk_textblob_t blob);
+
+ #endregion
+
+ #region sk_typeface.h
+
+ // int sk_fontmgr_count_families(sk_fontmgr_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_fontmgr_count_families (sk_fontmgr_t param0);
+
+ // sk_fontmgr_t* sk_fontmgr_create_default()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_fontmgr_t sk_fontmgr_create_default ();
+
+ // sk_typeface_t* sk_fontmgr_create_from_data(sk_fontmgr_t*, sk_data_t* data, int index)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_fontmgr_create_from_data (sk_fontmgr_t param0, sk_data_t data, Int32 index);
+
+ // sk_typeface_t* sk_fontmgr_create_from_file(sk_fontmgr_t*, const char* path, int index)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_fontmgr_create_from_file (sk_fontmgr_t param0, /* char */ void* path, Int32 index);
+
+ // sk_typeface_t* sk_fontmgr_create_from_stream(sk_fontmgr_t*, sk_stream_asset_t* stream, int index)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_fontmgr_create_from_stream (sk_fontmgr_t param0, sk_stream_asset_t stream, Int32 index);
+
+ // sk_fontstyleset_t* sk_fontmgr_create_styleset(sk_fontmgr_t*, int index)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_fontstyleset_t sk_fontmgr_create_styleset (sk_fontmgr_t param0, Int32 index);
+
+ // void sk_fontmgr_get_family_name(sk_fontmgr_t*, int index, sk_string_t* familyName)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_fontmgr_get_family_name (sk_fontmgr_t param0, Int32 index, sk_string_t familyName);
+
+ // sk_typeface_t* sk_fontmgr_match_face_style(sk_fontmgr_t*, const sk_typeface_t* face, sk_fontstyle_t* style)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_fontmgr_match_face_style (sk_fontmgr_t param0, sk_typeface_t face, sk_fontstyle_t style);
+
+ // sk_fontstyleset_t* sk_fontmgr_match_family(sk_fontmgr_t*, const char* familyName)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_fontstyleset_t sk_fontmgr_match_family (sk_fontmgr_t param0, [MarshalAs (UnmanagedType.LPStr)] String familyName);
+
+ // sk_typeface_t* sk_fontmgr_match_family_style(sk_fontmgr_t*, const char* familyName, sk_fontstyle_t* style)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_fontmgr_match_family_style (sk_fontmgr_t param0, [MarshalAs (UnmanagedType.LPStr)] String familyName, sk_fontstyle_t style);
+
+ // sk_typeface_t* sk_fontmgr_match_family_style_character(sk_fontmgr_t*, const char* familyName, sk_fontstyle_t* style, const char** bcp47, int bcp47Count, int32_t character)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_fontmgr_match_family_style_character (sk_fontmgr_t param0, [MarshalAs (UnmanagedType.LPStr)] String familyName, sk_fontstyle_t style, [MarshalAs (UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr)] String[] bcp47, Int32 bcp47Count, Int32 character);
+
+ // sk_fontmgr_t* sk_fontmgr_ref_default()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_fontmgr_t sk_fontmgr_ref_default ();
+
+ // void sk_fontmgr_unref(sk_fontmgr_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_fontmgr_unref (sk_fontmgr_t param0);
+
+ // void sk_fontstyle_delete(sk_fontstyle_t* fs)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_fontstyle_delete (sk_fontstyle_t fs);
+
+ // sk_font_style_slant_t sk_fontstyle_get_slant(const sk_fontstyle_t* fs)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKFontStyleSlant sk_fontstyle_get_slant (sk_fontstyle_t fs);
+
+ // int sk_fontstyle_get_weight(const sk_fontstyle_t* fs)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_fontstyle_get_weight (sk_fontstyle_t fs);
+
+ // int sk_fontstyle_get_width(const sk_fontstyle_t* fs)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_fontstyle_get_width (sk_fontstyle_t fs);
+
+ // sk_fontstyle_t* sk_fontstyle_new(int weight, int width, sk_font_style_slant_t slant)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_fontstyle_t sk_fontstyle_new (Int32 weight, Int32 width, SKFontStyleSlant slant);
+
+ // sk_fontstyleset_t* sk_fontstyleset_create_empty()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_fontstyleset_t sk_fontstyleset_create_empty ();
+
+ // sk_typeface_t* sk_fontstyleset_create_typeface(sk_fontstyleset_t* fss, int index)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_fontstyleset_create_typeface (sk_fontstyleset_t fss, Int32 index);
+
+ // int sk_fontstyleset_get_count(sk_fontstyleset_t* fss)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_fontstyleset_get_count (sk_fontstyleset_t fss);
+
+ // void sk_fontstyleset_get_style(sk_fontstyleset_t* fss, int index, sk_fontstyle_t* fs, sk_string_t* style)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_fontstyleset_get_style (sk_fontstyleset_t fss, Int32 index, sk_fontstyle_t fs, sk_string_t style);
+
+ // sk_typeface_t* sk_fontstyleset_match_style(sk_fontstyleset_t* fss, sk_fontstyle_t* style)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_fontstyleset_match_style (sk_fontstyleset_t fss, sk_fontstyle_t style);
+
+ // void sk_fontstyleset_unref(sk_fontstyleset_t* fss)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_fontstyleset_unref (sk_fontstyleset_t fss);
+
+ // int sk_typeface_chars_to_glyphs(sk_typeface_t* typeface, const char* chars, sk_encoding_t encoding, uint16_t[-1] glyphs, int glyphCount)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_typeface_chars_to_glyphs (sk_typeface_t typeface, /* char */ void* chars, SKEncoding encoding, UInt16* glyphs, Int32 glyphCount);
+
+ // int sk_typeface_count_glyphs(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_typeface_count_glyphs (sk_typeface_t typeface);
+
+ // int sk_typeface_count_tables(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_typeface_count_tables (sk_typeface_t typeface);
+
+ // sk_typeface_t* sk_typeface_create_default()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_typeface_create_default ();
+
+ // sk_typeface_t* sk_typeface_create_from_file(const char* path, int index)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_typeface_create_from_file (/* char */ void* path, Int32 index);
+
+ // sk_typeface_t* sk_typeface_create_from_name_with_font_style(const char* familyName, sk_fontstyle_t* style)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_typeface_create_from_name_with_font_style ([MarshalAs (UnmanagedType.LPStr)] String familyName, sk_fontstyle_t style);
+
+ // sk_typeface_t* sk_typeface_create_from_stream(sk_stream_asset_t* stream, int index)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_typeface_create_from_stream (sk_stream_asset_t stream, Int32 index);
+
+ // sk_string_t* sk_typeface_get_family_name(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_string_t sk_typeface_get_family_name (sk_typeface_t typeface);
+
+ // sk_font_style_slant_t sk_typeface_get_font_slant(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern SKFontStyleSlant sk_typeface_get_font_slant (sk_typeface_t typeface);
+
+ // int sk_typeface_get_font_weight(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_typeface_get_font_weight (sk_typeface_t typeface);
+
+ // int sk_typeface_get_font_width(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_typeface_get_font_width (sk_typeface_t typeface);
+
+ // sk_fontstyle_t* sk_typeface_get_fontstyle(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_fontstyle_t sk_typeface_get_fontstyle (sk_typeface_t typeface);
+
+ // bool sk_typeface_get_kerning_pair_adjustments(sk_typeface_t* typeface, const uint16_t* glyphs, int count, int32_t* adjustments)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_typeface_get_kerning_pair_adjustments (sk_typeface_t typeface, UInt16* glyphs, Int32 count, Int32* adjustments);
+
+ // size_t sk_typeface_get_table_data(sk_typeface_t* typeface, sk_font_table_tag_t tag, size_t offset, size_t length, void* data)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_typeface_get_table_data (sk_typeface_t typeface, UInt32 tag, /* size_t */ IntPtr offset, /* size_t */ IntPtr length, void* data);
+
+ // size_t sk_typeface_get_table_size(sk_typeface_t* typeface, sk_font_table_tag_t tag)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern /* size_t */ IntPtr sk_typeface_get_table_size (sk_typeface_t typeface, UInt32 tag);
+
+ // int sk_typeface_get_table_tags(sk_typeface_t* typeface, sk_font_table_tag_t[-1] tags)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_typeface_get_table_tags (sk_typeface_t typeface, UInt32* tags);
+
+ // int sk_typeface_get_units_per_em(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern Int32 sk_typeface_get_units_per_em (sk_typeface_t typeface);
+
+ // bool sk_typeface_is_fixed_pitch(sk_typeface_t* typeface)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal static extern bool sk_typeface_is_fixed_pitch (sk_typeface_t typeface);
+
+ // sk_stream_asset_t* sk_typeface_open_stream(sk_typeface_t* typeface, int* ttcIndex)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_asset_t sk_typeface_open_stream (sk_typeface_t typeface, Int32* ttcIndex);
+
+ // sk_typeface_t* sk_typeface_ref_default()
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_typeface_t sk_typeface_ref_default ();
+
+ // void sk_typeface_unref(sk_typeface_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_typeface_unref (sk_typeface_t param0);
+
+ #endregion
+
+ #region sk_vertices.h
+
+ // sk_vertices_t* sk_vertices_make_copy(sk_vertices_vertex_mode_t vmode, int vertexCount, const sk_point_t* positions, const sk_point_t* texs, const sk_color_t* colors, int indexCount, const uint16_t* indices)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_vertices_t sk_vertices_make_copy (SKVertexMode vmode, Int32 vertexCount, SKPoint* positions, SKPoint* texs, UInt32* colors, Int32 indexCount, UInt16* indices);
+
+ // void sk_vertices_ref(sk_vertices_t* cvertices)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_vertices_ref (sk_vertices_t cvertices);
+
+ // void sk_vertices_unref(sk_vertices_t* cvertices)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_vertices_unref (sk_vertices_t cvertices);
+
+ #endregion
+
+ #region sk_xml.h
+
+ // void sk_xmlstreamwriter_delete(sk_xmlstreamwriter_t* writer)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_xmlstreamwriter_delete (sk_xmlstreamwriter_t writer);
+
+ // sk_xmlstreamwriter_t* sk_xmlstreamwriter_new(sk_wstream_t* stream)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_xmlstreamwriter_t sk_xmlstreamwriter_new (sk_wstream_t stream);
+
+ #endregion
+
+ #region sk_manageddrawable.h
+
+ // sk_manageddrawable_t* sk_manageddrawable_new(void* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_manageddrawable_t sk_manageddrawable_new (void* context);
+
+ // void sk_manageddrawable_set_procs(sk_manageddrawable_procs_t procs)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_manageddrawable_set_procs (SKManagedDrawableDelegates procs);
+
+ // void sk_manageddrawable_unref(sk_manageddrawable_t*)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_manageddrawable_unref (sk_manageddrawable_t param0);
+
+ #endregion
+
+ #region sk_managedstream.h
+
+ // void sk_managedstream_destroy(sk_stream_managedstream_t* s)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_managedstream_destroy (sk_stream_managedstream_t s);
+
+ // sk_stream_managedstream_t* sk_managedstream_new(void* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_stream_managedstream_t sk_managedstream_new (void* context);
+
+ // void sk_managedstream_set_procs(sk_managedstream_procs_t procs)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_managedstream_set_procs (SKManagedStreamDelegates procs);
+
+ // void sk_managedwstream_destroy(sk_wstream_managedstream_t* s)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_managedwstream_destroy (sk_wstream_managedstream_t s);
+
+ // sk_wstream_managedstream_t* sk_managedwstream_new(void* context)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern sk_wstream_managedstream_t sk_managedwstream_new (void* context);
+
+ // void sk_managedwstream_set_procs(sk_managedwstream_procs_t procs)
+ [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void sk_managedwstream_set_procs (SKManagedWStreamDelegates procs);
+
+ #endregion
+
+ }
+
+ #region Delegates
+
+ // typedef void (*)()* gr_gl_func_ptr
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void GRGlFuncPtr();
+
+ // typedef gr_gl_func_ptr (*)(void* ctx, const char* name)* gr_gl_get_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate IntPtr GRGlGetProcProxyDelegate(void* ctx, [MarshalAs (UnmanagedType.LPStr)] String name);
+
+ // typedef void (*)(void* addr, void* context)* sk_bitmap_release_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKBitmapReleaseProxyDelegate(void* addr, void* context);
+
+ // typedef void (*)(const void* ptr, void* context)* sk_data_release_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKDataReleaseProxyDelegate(void* ptr, void* context);
+
+ // typedef void (*)(const void* addr, void* context)* sk_image_raster_release_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKImageRasterReleaseProxyDelegate(void* addr, void* context);
+
+ // typedef void (*)(void* context)* sk_image_texture_release_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKImageTextureReleaseProxyDelegate(void* context);
+
+ // typedef void (*)(sk_manageddrawable_t* d, void* context)* sk_manageddrawable_destroy_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKManagedDrawableDestroyProxyDelegate(sk_manageddrawable_t d, void* context);
+
+ // typedef void (*)(sk_manageddrawable_t* d, void* context, sk_canvas_t* ccanvas)* sk_manageddrawable_draw_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKManagedDrawableDrawProxyDelegate(sk_manageddrawable_t d, void* context, sk_canvas_t ccanvas);
+
+ // typedef void (*)(sk_manageddrawable_t* d, void* context, sk_rect_t* rect)* sk_manageddrawable_getBounds_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKManagedDrawableGetBoundsProxyDelegate(sk_manageddrawable_t d, void* context, SKRect* rect);
+
+ // typedef sk_picture_t* (*)(sk_manageddrawable_t* d, void* context)* sk_manageddrawable_newPictureSnapshot_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate sk_picture_t SKManagedDrawableNewPictureSnapshotProxyDelegate(sk_manageddrawable_t d, void* context);
+
+ // typedef void (*)(sk_stream_managedstream_t* s, void* context)* sk_managedstream_destroy_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKManagedStreamDestroyProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef sk_stream_managedstream_t* (*)(const sk_stream_managedstream_t* s, void* context)* sk_managedstream_duplicate_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate sk_stream_managedstream_t SKManagedStreamDuplicateProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef sk_stream_managedstream_t* (*)(const sk_stream_managedstream_t* s, void* context)* sk_managedstream_fork_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate sk_stream_managedstream_t SKManagedStreamForkProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef size_t (*)(const sk_stream_managedstream_t* s, void* context)* sk_managedstream_getLength_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate /* size_t */ IntPtr SKManagedStreamGetLengthProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef size_t (*)(const sk_stream_managedstream_t* s, void* context)* sk_managedstream_getPosition_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate /* size_t */ IntPtr SKManagedStreamGetPositionProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef bool (*)(const sk_stream_managedstream_t* s, void* context)* sk_managedstream_hasLength_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool SKManagedStreamHasLengthProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef bool (*)(const sk_stream_managedstream_t* s, void* context)* sk_managedstream_hasPosition_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool SKManagedStreamHasPositionProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef bool (*)(const sk_stream_managedstream_t* s, void* context)* sk_managedstream_isAtEnd_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool SKManagedStreamIsAtEndProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef bool (*)(sk_stream_managedstream_t* s, void* context, int offset)* sk_managedstream_move_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool SKManagedStreamMoveProxyDelegate(sk_stream_managedstream_t s, void* context, Int32 offset);
+
+ // typedef size_t (*)(const sk_stream_managedstream_t* s, void* context, void* buffer, size_t size)* sk_managedstream_peek_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate /* size_t */ IntPtr SKManagedStreamPeekProxyDelegate(sk_stream_managedstream_t s, void* context, void* buffer, /* size_t */ IntPtr size);
+
+ // typedef size_t (*)(sk_stream_managedstream_t* s, void* context, void* buffer, size_t size)* sk_managedstream_read_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate /* size_t */ IntPtr SKManagedStreamReadProxyDelegate(sk_stream_managedstream_t s, void* context, void* buffer, /* size_t */ IntPtr size);
+
+ // typedef bool (*)(sk_stream_managedstream_t* s, void* context)* sk_managedstream_rewind_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool SKManagedStreamRewindProxyDelegate(sk_stream_managedstream_t s, void* context);
+
+ // typedef bool (*)(sk_stream_managedstream_t* s, void* context, size_t position)* sk_managedstream_seek_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool SKManagedStreamSeekProxyDelegate(sk_stream_managedstream_t s, void* context, /* size_t */ IntPtr position);
+
+ // typedef size_t (*)(const sk_wstream_managedstream_t* s, void* context)* sk_managedwstream_bytesWritten_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate /* size_t */ IntPtr SKManagedWStreamBytesWrittenProxyDelegate(sk_wstream_managedstream_t s, void* context);
+
+ // typedef void (*)(sk_wstream_managedstream_t* s, void* context)* sk_managedwstream_destroy_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKManagedWStreamDestroyProxyDelegate(sk_wstream_managedstream_t s, void* context);
+
+ // typedef void (*)(sk_wstream_managedstream_t* s, void* context)* sk_managedwstream_flush_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKManagedWStreamFlushProxyDelegate(sk_wstream_managedstream_t s, void* context);
+
+ // typedef bool (*)(sk_wstream_managedstream_t* s, void* context, const void* buffer, size_t size)* sk_managedwstream_write_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ [return: MarshalAs (UnmanagedType.I1)]
+ internal unsafe delegate bool SKManagedWStreamWriteProxyDelegate(sk_wstream_managedstream_t s, void* context, void* buffer, /* size_t */ IntPtr size);
+
+ // typedef void (*)(void* addr, void* context)* sk_surface_raster_release_proc
+ [UnmanagedFunctionPointer (CallingConvention.Cdecl)]
+ internal unsafe delegate void SKSurfaceRasterReleaseProxyDelegate(void* addr, void* context);
+
+ #endregion
+
+ #region Structs
+
+ // gr_gl_framebufferinfo_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct GRGlFramebufferInfo : IEquatable<GRGlFramebufferInfo> {
+ // public unsigned int fFBOID
+ private UInt32 fFBOID;
+ public UInt32 FramebufferObjectId {
+ readonly get => fFBOID;
+ set => fFBOID = value;
+ }
+
+ // public unsigned int fFormat
+ private UInt32 fFormat;
+ public UInt32 Format {
+ readonly get => fFormat;
+ set => fFormat = value;
+ }
+
+ public readonly bool Equals (GRGlFramebufferInfo obj) =>
+ fFBOID == obj.fFBOID && fFormat == obj.fFormat;
+
+ public readonly override bool Equals (object obj) =>
+ obj is GRGlFramebufferInfo f && Equals (f);
+
+ public static bool operator == (GRGlFramebufferInfo left, GRGlFramebufferInfo right) =>
+ left.Equals (right);
+
+ public static bool operator != (GRGlFramebufferInfo left, GRGlFramebufferInfo right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fFBOID);
+ hash.Add (fFormat);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // gr_gl_textureinfo_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct GRGlTextureInfo : IEquatable<GRGlTextureInfo> {
+ // public unsigned int fTarget
+ private UInt32 fTarget;
+ public UInt32 Target {
+ readonly get => fTarget;
+ set => fTarget = value;
+ }
+
+ // public unsigned int fID
+ private UInt32 fID;
+ public UInt32 Id {
+ readonly get => fID;
+ set => fID = value;
+ }
+
+ // public unsigned int fFormat
+ private UInt32 fFormat;
+ public UInt32 Format {
+ readonly get => fFormat;
+ set => fFormat = value;
+ }
+
+ public readonly bool Equals (GRGlTextureInfo obj) =>
+ fTarget == obj.fTarget && fID == obj.fID && fFormat == obj.fFormat;
+
+ public readonly override bool Equals (object obj) =>
+ obj is GRGlTextureInfo f && Equals (f);
+
+ public static bool operator == (GRGlTextureInfo left, GRGlTextureInfo right) =>
+ left.Equals (right);
+
+ public static bool operator != (GRGlTextureInfo left, GRGlTextureInfo right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fTarget);
+ hash.Add (fID);
+ hash.Add (fFormat);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_codec_frameinfo_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKCodecFrameInfo : IEquatable<SKCodecFrameInfo> {
+ // public int fRequiredFrame
+ private Int32 fRequiredFrame;
+ public Int32 RequiredFrame {
+ readonly get => fRequiredFrame;
+ set => fRequiredFrame = value;
+ }
+
+ // public int fDuration
+ private Int32 fDuration;
+ public Int32 Duration {
+ readonly get => fDuration;
+ set => fDuration = value;
+ }
+
+ // public bool fFullyReceived
+ private Byte fFullyReceived;
+ public bool FullyRecieved {
+ readonly get => fFullyReceived > 0;
+ set => fFullyReceived = value ? (byte)1 : (byte)0;
+ }
+
+ // public sk_alphatype_t fAlphaType
+ private SKAlphaType fAlphaType;
+ public SKAlphaType AlphaType {
+ readonly get => fAlphaType;
+ set => fAlphaType = value;
+ }
+
+ // public sk_codecanimation_disposalmethod_t fDisposalMethod
+ private SKCodecAnimationDisposalMethod fDisposalMethod;
+ public SKCodecAnimationDisposalMethod DisposalMethod {
+ readonly get => fDisposalMethod;
+ set => fDisposalMethod = value;
+ }
+
+ public readonly bool Equals (SKCodecFrameInfo obj) =>
+ fRequiredFrame == obj.fRequiredFrame && fDuration == obj.fDuration && fFullyReceived == obj.fFullyReceived && fAlphaType == obj.fAlphaType && fDisposalMethod == obj.fDisposalMethod;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKCodecFrameInfo f && Equals (f);
+
+ public static bool operator == (SKCodecFrameInfo left, SKCodecFrameInfo right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKCodecFrameInfo left, SKCodecFrameInfo right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fRequiredFrame);
+ hash.Add (fDuration);
+ hash.Add (fFullyReceived);
+ hash.Add (fAlphaType);
+ hash.Add (fDisposalMethod);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_codec_options_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKCodecOptionsInternal : IEquatable<SKCodecOptionsInternal> {
+ // public sk_codec_zero_initialized_t fZeroInitialized
+ public SKZeroInitialized fZeroInitialized;
+
+ // public sk_irect_t* fSubset
+ public SKRectI* fSubset;
+
+ // public int fFrameIndex
+ public Int32 fFrameIndex;
+
+ // public int fPriorFrame
+ public Int32 fPriorFrame;
+
+ // public sk_transfer_function_behavior_t fPremulBehavior
+ public SKTransferFunctionBehavior fPremulBehavior;
+
+ public readonly bool Equals (SKCodecOptionsInternal obj) =>
+ fZeroInitialized == obj.fZeroInitialized && fSubset == obj.fSubset && fFrameIndex == obj.fFrameIndex && fPriorFrame == obj.fPriorFrame && fPremulBehavior == obj.fPremulBehavior;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKCodecOptionsInternal f && Equals (f);
+
+ public static bool operator == (SKCodecOptionsInternal left, SKCodecOptionsInternal right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKCodecOptionsInternal left, SKCodecOptionsInternal right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fZeroInitialized);
+ hash.Add (fSubset);
+ hash.Add (fFrameIndex);
+ hash.Add (fPriorFrame);
+ hash.Add (fPremulBehavior);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_color4f_t
+ [StructLayout (LayoutKind.Sequential)]
+ public readonly unsafe partial struct SKColorF : IEquatable<SKColorF> {
+ // public float fR
+ private readonly Single fR;
+ public readonly Single Red => fR;
+
+ // public float fG
+ private readonly Single fG;
+ public readonly Single Green => fG;
+
+ // public float fB
+ private readonly Single fB;
+ public readonly Single Blue => fB;
+
+ // public float fA
+ private readonly Single fA;
+ public readonly Single Alpha => fA;
+
+ public readonly bool Equals (SKColorF obj) =>
+ fR == obj.fR && fG == obj.fG && fB == obj.fB && fA == obj.fA;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKColorF f && Equals (f);
+
+ public static bool operator == (SKColorF left, SKColorF right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKColorF left, SKColorF right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fR);
+ hash.Add (fG);
+ hash.Add (fB);
+ hash.Add (fA);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_colorspace_transfer_fn_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKColorSpaceTransferFn : IEquatable<SKColorSpaceTransferFn> {
+ // public float fG
+ private Single fG;
+ public Single G {
+ readonly get => fG;
+ set => fG = value;
+ }
+
+ // public float fA
+ private Single fA;
+ public Single A {
+ readonly get => fA;
+ set => fA = value;
+ }
+
+ // public float fB
+ private Single fB;
+ public Single B {
+ readonly get => fB;
+ set => fB = value;
+ }
+
+ // public float fC
+ private Single fC;
+ public Single C {
+ readonly get => fC;
+ set => fC = value;
+ }
+
+ // public float fD
+ private Single fD;
+ public Single D {
+ readonly get => fD;
+ set => fD = value;
+ }
+
+ // public float fE
+ private Single fE;
+ public Single E {
+ readonly get => fE;
+ set => fE = value;
+ }
+
+ // public float fF
+ private Single fF;
+ public Single F {
+ readonly get => fF;
+ set => fF = value;
+ }
+
+ public readonly bool Equals (SKColorSpaceTransferFn obj) =>
+ fG == obj.fG && fA == obj.fA && fB == obj.fB && fC == obj.fC && fD == obj.fD && fE == obj.fE && fF == obj.fF;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKColorSpaceTransferFn f && Equals (f);
+
+ public static bool operator == (SKColorSpaceTransferFn left, SKColorSpaceTransferFn right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKColorSpaceTransferFn left, SKColorSpaceTransferFn right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fG);
+ hash.Add (fA);
+ hash.Add (fB);
+ hash.Add (fC);
+ hash.Add (fD);
+ hash.Add (fE);
+ hash.Add (fF);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_colorspaceprimaries_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKColorSpacePrimaries : IEquatable<SKColorSpacePrimaries> {
+ // public float fRX
+ private Single fRX;
+ public Single RX {
+ readonly get => fRX;
+ set => fRX = value;
+ }
+
+ // public float fRY
+ private Single fRY;
+ public Single RY {
+ readonly get => fRY;
+ set => fRY = value;
+ }
+
+ // public float fGX
+ private Single fGX;
+ public Single GX {
+ readonly get => fGX;
+ set => fGX = value;
+ }
+
+ // public float fGY
+ private Single fGY;
+ public Single GY {
+ readonly get => fGY;
+ set => fGY = value;
+ }
+
+ // public float fBX
+ private Single fBX;
+ public Single BX {
+ readonly get => fBX;
+ set => fBX = value;
+ }
+
+ // public float fBY
+ private Single fBY;
+ public Single BY {
+ readonly get => fBY;
+ set => fBY = value;
+ }
+
+ // public float fWX
+ private Single fWX;
+ public Single WX {
+ readonly get => fWX;
+ set => fWX = value;
+ }
+
+ // public float fWY
+ private Single fWY;
+ public Single WY {
+ readonly get => fWY;
+ set => fWY = value;
+ }
+
+ public readonly bool Equals (SKColorSpacePrimaries obj) =>
+ fRX == obj.fRX && fRY == obj.fRY && fGX == obj.fGX && fGY == obj.fGY && fBX == obj.fBX && fBY == obj.fBY && fWX == obj.fWX && fWY == obj.fWY;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKColorSpacePrimaries f && Equals (f);
+
+ public static bool operator == (SKColorSpacePrimaries left, SKColorSpacePrimaries right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKColorSpacePrimaries left, SKColorSpacePrimaries right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fRX);
+ hash.Add (fRY);
+ hash.Add (fGX);
+ hash.Add (fGY);
+ hash.Add (fBX);
+ hash.Add (fBY);
+ hash.Add (fWX);
+ hash.Add (fWY);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_document_pdf_metadata_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKDocumentPdfMetadataInternal : IEquatable<SKDocumentPdfMetadataInternal> {
+ // public sk_string_t* fTitle
+ public sk_string_t fTitle;
+
+ // public sk_string_t* fAuthor
+ public sk_string_t fAuthor;
+
+ // public sk_string_t* fSubject
+ public sk_string_t fSubject;
+
+ // public sk_string_t* fKeywords
+ public sk_string_t fKeywords;
+
+ // public sk_string_t* fCreator
+ public sk_string_t fCreator;
+
+ // public sk_string_t* fProducer
+ public sk_string_t fProducer;
+
+ // public sk_time_datetime_t* fCreation
+ public SKTimeDateTimeInternal* fCreation;
+
+ // public sk_time_datetime_t* fModified
+ public SKTimeDateTimeInternal* fModified;
+
+ // public float fRasterDPI
+ public Single fRasterDPI;
+
+ // public bool fPDFA
+ public Byte fPDFA;
+
+ // public int fEncodingQuality
+ public Int32 fEncodingQuality;
+
+ public readonly bool Equals (SKDocumentPdfMetadataInternal obj) =>
+ fTitle == obj.fTitle && fAuthor == obj.fAuthor && fSubject == obj.fSubject && fKeywords == obj.fKeywords && fCreator == obj.fCreator && fProducer == obj.fProducer && fCreation == obj.fCreation && fModified == obj.fModified && fRasterDPI == obj.fRasterDPI && fPDFA == obj.fPDFA && fEncodingQuality == obj.fEncodingQuality;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKDocumentPdfMetadataInternal f && Equals (f);
+
+ public static bool operator == (SKDocumentPdfMetadataInternal left, SKDocumentPdfMetadataInternal right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKDocumentPdfMetadataInternal left, SKDocumentPdfMetadataInternal right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fTitle);
+ hash.Add (fAuthor);
+ hash.Add (fSubject);
+ hash.Add (fKeywords);
+ hash.Add (fCreator);
+ hash.Add (fProducer);
+ hash.Add (fCreation);
+ hash.Add (fModified);
+ hash.Add (fRasterDPI);
+ hash.Add (fPDFA);
+ hash.Add (fEncodingQuality);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_fontmetrics_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKFontMetrics : IEquatable<SKFontMetrics> {
+ // public uint32_t fFlags
+ private UInt32 fFlags;
+
+ // public float fTop
+ private Single fTop;
+
+ // public float fAscent
+ private Single fAscent;
+
+ // public float fDescent
+ private Single fDescent;
+
+ // public float fBottom
+ private Single fBottom;
+
+ // public float fLeading
+ private Single fLeading;
+
+ // public float fAvgCharWidth
+ private Single fAvgCharWidth;
+
+ // public float fMaxCharWidth
+ private Single fMaxCharWidth;
+
+ // public float fXMin
+ private Single fXMin;
+
+ // public float fXMax
+ private Single fXMax;
+
+ // public float fXHeight
+ private Single fXHeight;
+
+ // public float fCapHeight
+ private Single fCapHeight;
+
+ // public float fUnderlineThickness
+ private Single fUnderlineThickness;
+
+ // public float fUnderlinePosition
+ private Single fUnderlinePosition;
+
+ // public float fStrikeoutThickness
+ private Single fStrikeoutThickness;
+
+ // public float fStrikeoutPosition
+ private Single fStrikeoutPosition;
+
+ public readonly bool Equals (SKFontMetrics obj) =>
+ fFlags == obj.fFlags && fTop == obj.fTop && fAscent == obj.fAscent && fDescent == obj.fDescent && fBottom == obj.fBottom && fLeading == obj.fLeading && fAvgCharWidth == obj.fAvgCharWidth && fMaxCharWidth == obj.fMaxCharWidth && fXMin == obj.fXMin && fXMax == obj.fXMax && fXHeight == obj.fXHeight && fCapHeight == obj.fCapHeight && fUnderlineThickness == obj.fUnderlineThickness && fUnderlinePosition == obj.fUnderlinePosition && fStrikeoutThickness == obj.fStrikeoutThickness && fStrikeoutPosition == obj.fStrikeoutPosition;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKFontMetrics f && Equals (f);
+
+ public static bool operator == (SKFontMetrics left, SKFontMetrics right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKFontMetrics left, SKFontMetrics right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fFlags);
+ hash.Add (fTop);
+ hash.Add (fAscent);
+ hash.Add (fDescent);
+ hash.Add (fBottom);
+ hash.Add (fLeading);
+ hash.Add (fAvgCharWidth);
+ hash.Add (fMaxCharWidth);
+ hash.Add (fXMin);
+ hash.Add (fXMax);
+ hash.Add (fXHeight);
+ hash.Add (fCapHeight);
+ hash.Add (fUnderlineThickness);
+ hash.Add (fUnderlinePosition);
+ hash.Add (fStrikeoutThickness);
+ hash.Add (fStrikeoutPosition);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_highcontrastconfig_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKHighContrastConfig : IEquatable<SKHighContrastConfig> {
+ // public bool fGrayscale
+ private Byte fGrayscale;
+ public bool Grayscale {
+ readonly get => fGrayscale > 0;
+ set => fGrayscale = value ? (byte)1 : (byte)0;
+ }
+
+ // public sk_highcontrastconfig_invertstyle_t fInvertStyle
+ private SKHighContrastConfigInvertStyle fInvertStyle;
+ public SKHighContrastConfigInvertStyle InvertStyle {
+ readonly get => fInvertStyle;
+ set => fInvertStyle = value;
+ }
+
+ // public float fContrast
+ private Single fContrast;
+ public Single Contrast {
+ readonly get => fContrast;
+ set => fContrast = value;
+ }
+
+ public readonly bool Equals (SKHighContrastConfig obj) =>
+ fGrayscale == obj.fGrayscale && fInvertStyle == obj.fInvertStyle && fContrast == obj.fContrast;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKHighContrastConfig f && Equals (f);
+
+ public static bool operator == (SKHighContrastConfig left, SKHighContrastConfig right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKHighContrastConfig left, SKHighContrastConfig right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fGrayscale);
+ hash.Add (fInvertStyle);
+ hash.Add (fContrast);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_imageinfo_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKImageInfoNative : IEquatable<SKImageInfoNative> {
+ // public sk_colorspace_t* colorspace
+ public sk_colorspace_t colorspace;
+
+ // public int32_t width
+ public Int32 width;
+
+ // public int32_t height
+ public Int32 height;
+
+ // public sk_colortype_t colorType
+ public SKColorType colorType;
+
+ // public sk_alphatype_t alphaType
+ public SKAlphaType alphaType;
+
+ public readonly bool Equals (SKImageInfoNative obj) =>
+ colorspace == obj.colorspace && width == obj.width && height == obj.height && colorType == obj.colorType && alphaType == obj.alphaType;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKImageInfoNative f && Equals (f);
+
+ public static bool operator == (SKImageInfoNative left, SKImageInfoNative right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKImageInfoNative left, SKImageInfoNative right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (colorspace);
+ hash.Add (width);
+ hash.Add (height);
+ hash.Add (colorType);
+ hash.Add (alphaType);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_ipoint_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKPointI : IEquatable<SKPointI> {
+ // public int32_t x
+ private Int32 x;
+ public Int32 X {
+ readonly get => x;
+ set => x = value;
+ }
+
+ // public int32_t y
+ private Int32 y;
+ public Int32 Y {
+ readonly get => y;
+ set => y = value;
+ }
+
+ public readonly bool Equals (SKPointI obj) =>
+ x == obj.x && y == obj.y;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKPointI f && Equals (f);
+
+ public static bool operator == (SKPointI left, SKPointI right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKPointI left, SKPointI right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (x);
+ hash.Add (y);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_irect_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKRectI : IEquatable<SKRectI> {
+ // public int32_t left
+ private Int32 left;
+ public Int32 Left {
+ readonly get => left;
+ set => left = value;
+ }
+
+ // public int32_t top
+ private Int32 top;
+ public Int32 Top {
+ readonly get => top;
+ set => top = value;
+ }
+
+ // public int32_t right
+ private Int32 right;
+ public Int32 Right {
+ readonly get => right;
+ set => right = value;
+ }
+
+ // public int32_t bottom
+ private Int32 bottom;
+ public Int32 Bottom {
+ readonly get => bottom;
+ set => bottom = value;
+ }
+
+ public readonly bool Equals (SKRectI obj) =>
+ left == obj.left && top == obj.top && right == obj.right && bottom == obj.bottom;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKRectI f && Equals (f);
+
+ public static bool operator == (SKRectI left, SKRectI right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKRectI left, SKRectI right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (left);
+ hash.Add (top);
+ hash.Add (right);
+ hash.Add (bottom);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_isize_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKSizeI : IEquatable<SKSizeI> {
+ // public int32_t w
+ private Int32 w;
+ public Int32 Width {
+ readonly get => w;
+ set => w = value;
+ }
+
+ // public int32_t h
+ private Int32 h;
+ public Int32 Height {
+ readonly get => h;
+ set => h = value;
+ }
+
+ public readonly bool Equals (SKSizeI obj) =>
+ w == obj.w && h == obj.h;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKSizeI f && Equals (f);
+
+ public static bool operator == (SKSizeI left, SKSizeI right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKSizeI left, SKSizeI right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (w);
+ hash.Add (h);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_jpegencoder_options_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKJpegEncoderOptions : IEquatable<SKJpegEncoderOptions> {
+ // public int fQuality
+ private Int32 fQuality;
+ public Int32 Quality {
+ readonly get => fQuality;
+ set => fQuality = value;
+ }
+
+ // public sk_jpegencoder_downsample_t fDownsample
+ private SKJpegEncoderDownsample fDownsample;
+ public SKJpegEncoderDownsample Downsample {
+ readonly get => fDownsample;
+ set => fDownsample = value;
+ }
+
+ // public sk_jpegencoder_alphaoption_t fAlphaOption
+ private SKJpegEncoderAlphaOption fAlphaOption;
+ public SKJpegEncoderAlphaOption AlphaOption {
+ readonly get => fAlphaOption;
+ set => fAlphaOption = value;
+ }
+
+ // public sk_transfer_function_behavior_t fBlendBehavior
+ private SKTransferFunctionBehavior fBlendBehavior;
+ public SKTransferFunctionBehavior BlendBehavior {
+ readonly get => fBlendBehavior;
+ set => fBlendBehavior = value;
+ }
+
+ public readonly bool Equals (SKJpegEncoderOptions obj) =>
+ fQuality == obj.fQuality && fDownsample == obj.fDownsample && fAlphaOption == obj.fAlphaOption && fBlendBehavior == obj.fBlendBehavior;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKJpegEncoderOptions f && Equals (f);
+
+ public static bool operator == (SKJpegEncoderOptions left, SKJpegEncoderOptions right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKJpegEncoderOptions left, SKJpegEncoderOptions right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fQuality);
+ hash.Add (fDownsample);
+ hash.Add (fAlphaOption);
+ hash.Add (fBlendBehavior);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_lattice_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKLatticeInternal : IEquatable<SKLatticeInternal> {
+ // public const int* fXDivs
+ public Int32* fXDivs;
+
+ // public const int* fYDivs
+ public Int32* fYDivs;
+
+ // public const sk_lattice_recttype_t* fRectTypes
+ public SKLatticeRectType* fRectTypes;
+
+ // public int fXCount
+ public Int32 fXCount;
+
+ // public int fYCount
+ public Int32 fYCount;
+
+ // public const sk_irect_t* fBounds
+ public SKRectI* fBounds;
+
+ // public const sk_color_t* fColors
+ public UInt32* fColors;
+
+ public readonly bool Equals (SKLatticeInternal obj) =>
+ fXDivs == obj.fXDivs && fYDivs == obj.fYDivs && fRectTypes == obj.fRectTypes && fXCount == obj.fXCount && fYCount == obj.fYCount && fBounds == obj.fBounds && fColors == obj.fColors;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKLatticeInternal f && Equals (f);
+
+ public static bool operator == (SKLatticeInternal left, SKLatticeInternal right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKLatticeInternal left, SKLatticeInternal right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fXDivs);
+ hash.Add (fYDivs);
+ hash.Add (fRectTypes);
+ hash.Add (fXCount);
+ hash.Add (fYCount);
+ hash.Add (fBounds);
+ hash.Add (fColors);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_manageddrawable_procs_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKManagedDrawableDelegates : IEquatable<SKManagedDrawableDelegates> {
+ // public sk_manageddrawable_draw_proc fDraw
+ public SKManagedDrawableDrawProxyDelegate fDraw;
+
+ // public sk_manageddrawable_getBounds_proc fGetBounds
+ public SKManagedDrawableGetBoundsProxyDelegate fGetBounds;
+
+ // public sk_manageddrawable_newPictureSnapshot_proc fNewPictureSnapshot
+ public SKManagedDrawableNewPictureSnapshotProxyDelegate fNewPictureSnapshot;
+
+ // public sk_manageddrawable_destroy_proc fDestroy
+ public SKManagedDrawableDestroyProxyDelegate fDestroy;
+
+ public readonly bool Equals (SKManagedDrawableDelegates obj) =>
+ fDraw == obj.fDraw && fGetBounds == obj.fGetBounds && fNewPictureSnapshot == obj.fNewPictureSnapshot && fDestroy == obj.fDestroy;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKManagedDrawableDelegates f && Equals (f);
+
+ public static bool operator == (SKManagedDrawableDelegates left, SKManagedDrawableDelegates right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKManagedDrawableDelegates left, SKManagedDrawableDelegates right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fDraw);
+ hash.Add (fGetBounds);
+ hash.Add (fNewPictureSnapshot);
+ hash.Add (fDestroy);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_managedstream_procs_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKManagedStreamDelegates : IEquatable<SKManagedStreamDelegates> {
+ // public sk_managedstream_read_proc fRead
+ public SKManagedStreamReadProxyDelegate fRead;
+
+ // public sk_managedstream_peek_proc fPeek
+ public SKManagedStreamPeekProxyDelegate fPeek;
+
+ // public sk_managedstream_isAtEnd_proc fIsAtEnd
+ public SKManagedStreamIsAtEndProxyDelegate fIsAtEnd;
+
+ // public sk_managedstream_hasPosition_proc fHasPosition
+ public SKManagedStreamHasPositionProxyDelegate fHasPosition;
+
+ // public sk_managedstream_hasLength_proc fHasLength
+ public SKManagedStreamHasLengthProxyDelegate fHasLength;
+
+ // public sk_managedstream_rewind_proc fRewind
+ public SKManagedStreamRewindProxyDelegate fRewind;
+
+ // public sk_managedstream_getPosition_proc fGetPosition
+ public SKManagedStreamGetPositionProxyDelegate fGetPosition;
+
+ // public sk_managedstream_seek_proc fSeek
+ public SKManagedStreamSeekProxyDelegate fSeek;
+
+ // public sk_managedstream_move_proc fMove
+ public SKManagedStreamMoveProxyDelegate fMove;
+
+ // public sk_managedstream_getLength_proc fGetLength
+ public SKManagedStreamGetLengthProxyDelegate fGetLength;
+
+ // public sk_managedstream_duplicate_proc fDuplicate
+ public SKManagedStreamDuplicateProxyDelegate fDuplicate;
+
+ // public sk_managedstream_fork_proc fFork
+ public SKManagedStreamForkProxyDelegate fFork;
+
+ // public sk_managedstream_destroy_proc fDestroy
+ public SKManagedStreamDestroyProxyDelegate fDestroy;
+
+ public readonly bool Equals (SKManagedStreamDelegates obj) =>
+ fRead == obj.fRead && fPeek == obj.fPeek && fIsAtEnd == obj.fIsAtEnd && fHasPosition == obj.fHasPosition && fHasLength == obj.fHasLength && fRewind == obj.fRewind && fGetPosition == obj.fGetPosition && fSeek == obj.fSeek && fMove == obj.fMove && fGetLength == obj.fGetLength && fDuplicate == obj.fDuplicate && fFork == obj.fFork && fDestroy == obj.fDestroy;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKManagedStreamDelegates f && Equals (f);
+
+ public static bool operator == (SKManagedStreamDelegates left, SKManagedStreamDelegates right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKManagedStreamDelegates left, SKManagedStreamDelegates right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fRead);
+ hash.Add (fPeek);
+ hash.Add (fIsAtEnd);
+ hash.Add (fHasPosition);
+ hash.Add (fHasLength);
+ hash.Add (fRewind);
+ hash.Add (fGetPosition);
+ hash.Add (fSeek);
+ hash.Add (fMove);
+ hash.Add (fGetLength);
+ hash.Add (fDuplicate);
+ hash.Add (fFork);
+ hash.Add (fDestroy);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_managedwstream_procs_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKManagedWStreamDelegates : IEquatable<SKManagedWStreamDelegates> {
+ // public sk_managedwstream_write_proc fWrite
+ public SKManagedWStreamWriteProxyDelegate fWrite;
+
+ // public sk_managedwstream_flush_proc fFlush
+ public SKManagedWStreamFlushProxyDelegate fFlush;
+
+ // public sk_managedwstream_bytesWritten_proc fBytesWritten
+ public SKManagedWStreamBytesWrittenProxyDelegate fBytesWritten;
+
+ // public sk_managedwstream_destroy_proc fDestroy
+ public SKManagedWStreamDestroyProxyDelegate fDestroy;
+
+ public readonly bool Equals (SKManagedWStreamDelegates obj) =>
+ fWrite == obj.fWrite && fFlush == obj.fFlush && fBytesWritten == obj.fBytesWritten && fDestroy == obj.fDestroy;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKManagedWStreamDelegates f && Equals (f);
+
+ public static bool operator == (SKManagedWStreamDelegates left, SKManagedWStreamDelegates right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKManagedWStreamDelegates left, SKManagedWStreamDelegates right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fWrite);
+ hash.Add (fFlush);
+ hash.Add (fBytesWritten);
+ hash.Add (fDestroy);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_mask_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKMask : IEquatable<SKMask> {
+ // public uint8_t* fImage
+ private Byte* fImage;
+
+ // public sk_irect_t fBounds
+ private SKRectI fBounds;
+
+ // public uint32_t fRowBytes
+ private UInt32 fRowBytes;
+
+ // public sk_mask_format_t fFormat
+ private SKMaskFormat fFormat;
+
+ public readonly bool Equals (SKMask obj) =>
+ fImage == obj.fImage && fBounds == obj.fBounds && fRowBytes == obj.fRowBytes && fFormat == obj.fFormat;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKMask f && Equals (f);
+
+ public static bool operator == (SKMask left, SKMask right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKMask left, SKMask right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fImage);
+ hash.Add (fBounds);
+ hash.Add (fRowBytes);
+ hash.Add (fFormat);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_matrix_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKMatrix : IEquatable<SKMatrix> {
+ // public float scaleX
+ private Single scaleX;
+ public Single ScaleX {
+ readonly get => scaleX;
+ set => scaleX = value;
+ }
+
+ // public float skewX
+ private Single skewX;
+ public Single SkewX {
+ readonly get => skewX;
+ set => skewX = value;
+ }
+
+ // public float transX
+ private Single transX;
+ public Single TransX {
+ readonly get => transX;
+ set => transX = value;
+ }
+
+ // public float skewY
+ private Single skewY;
+ public Single SkewY {
+ readonly get => skewY;
+ set => skewY = value;
+ }
+
+ // public float scaleY
+ private Single scaleY;
+ public Single ScaleY {
+ readonly get => scaleY;
+ set => scaleY = value;
+ }
+
+ // public float transY
+ private Single transY;
+ public Single TransY {
+ readonly get => transY;
+ set => transY = value;
+ }
+
+ // public float persp0
+ private Single persp0;
+ public Single Persp0 {
+ readonly get => persp0;
+ set => persp0 = value;
+ }
+
+ // public float persp1
+ private Single persp1;
+ public Single Persp1 {
+ readonly get => persp1;
+ set => persp1 = value;
+ }
+
+ // public float persp2
+ private Single persp2;
+ public Single Persp2 {
+ readonly get => persp2;
+ set => persp2 = value;
+ }
+
+ public readonly bool Equals (SKMatrix obj) =>
+ scaleX == obj.scaleX && skewX == obj.skewX && transX == obj.transX && skewY == obj.skewY && scaleY == obj.scaleY && transY == obj.transY && persp0 == obj.persp0 && persp1 == obj.persp1 && persp2 == obj.persp2;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKMatrix f && Equals (f);
+
+ public static bool operator == (SKMatrix left, SKMatrix right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKMatrix left, SKMatrix right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (scaleX);
+ hash.Add (skewX);
+ hash.Add (transX);
+ hash.Add (skewY);
+ hash.Add (scaleY);
+ hash.Add (transY);
+ hash.Add (persp0);
+ hash.Add (persp1);
+ hash.Add (persp2);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_pngencoder_options_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKPngEncoderOptions : IEquatable<SKPngEncoderOptions> {
+ // public sk_pngencoder_filterflags_t fFilterFlags
+ private SKPngEncoderFilterFlags fFilterFlags;
+
+ // public int fZLibLevel
+ private Int32 fZLibLevel;
+
+ // public sk_transfer_function_behavior_t fUnpremulBehavior
+ private SKTransferFunctionBehavior fUnpremulBehavior;
+
+ // public void* fComments
+ private void* fComments;
+
+ public readonly bool Equals (SKPngEncoderOptions obj) =>
+ fFilterFlags == obj.fFilterFlags && fZLibLevel == obj.fZLibLevel && fUnpremulBehavior == obj.fUnpremulBehavior && fComments == obj.fComments;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKPngEncoderOptions f && Equals (f);
+
+ public static bool operator == (SKPngEncoderOptions left, SKPngEncoderOptions right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKPngEncoderOptions left, SKPngEncoderOptions right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fFilterFlags);
+ hash.Add (fZLibLevel);
+ hash.Add (fUnpremulBehavior);
+ hash.Add (fComments);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_point_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKPoint : IEquatable<SKPoint> {
+ // public float x
+ private Single x;
+ public Single X {
+ readonly get => x;
+ set => x = value;
+ }
+
+ // public float y
+ private Single y;
+ public Single Y {
+ readonly get => y;
+ set => y = value;
+ }
+
+ public readonly bool Equals (SKPoint obj) =>
+ x == obj.x && y == obj.y;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKPoint f && Equals (f);
+
+ public static bool operator == (SKPoint left, SKPoint right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKPoint left, SKPoint right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (x);
+ hash.Add (y);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_point3_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKPoint3 : IEquatable<SKPoint3> {
+ // public float x
+ private Single x;
+ public Single X {
+ readonly get => x;
+ set => x = value;
+ }
+
+ // public float y
+ private Single y;
+ public Single Y {
+ readonly get => y;
+ set => y = value;
+ }
+
+ // public float z
+ private Single z;
+ public Single Z {
+ readonly get => z;
+ set => z = value;
+ }
+
+ public readonly bool Equals (SKPoint3 obj) =>
+ x == obj.x && y == obj.y && z == obj.z;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKPoint3 f && Equals (f);
+
+ public static bool operator == (SKPoint3 left, SKPoint3 right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKPoint3 left, SKPoint3 right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (x);
+ hash.Add (y);
+ hash.Add (z);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_rect_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKRect : IEquatable<SKRect> {
+ // public float left
+ private Single left;
+ public Single Left {
+ readonly get => left;
+ set => left = value;
+ }
+
+ // public float top
+ private Single top;
+ public Single Top {
+ readonly get => top;
+ set => top = value;
+ }
+
+ // public float right
+ private Single right;
+ public Single Right {
+ readonly get => right;
+ set => right = value;
+ }
+
+ // public float bottom
+ private Single bottom;
+ public Single Bottom {
+ readonly get => bottom;
+ set => bottom = value;
+ }
+
+ public readonly bool Equals (SKRect obj) =>
+ left == obj.left && top == obj.top && right == obj.right && bottom == obj.bottom;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKRect f && Equals (f);
+
+ public static bool operator == (SKRect left, SKRect right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKRect left, SKRect right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (left);
+ hash.Add (top);
+ hash.Add (right);
+ hash.Add (bottom);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_rsxform_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKRotationScaleMatrix : IEquatable<SKRotationScaleMatrix> {
+ // public float fSCos
+ private Single fSCos;
+ public Single SCos {
+ readonly get => fSCos;
+ set => fSCos = value;
+ }
+
+ // public float fSSin
+ private Single fSSin;
+ public Single SSin {
+ readonly get => fSSin;
+ set => fSSin = value;
+ }
+
+ // public float fTX
+ private Single fTX;
+ public Single TX {
+ readonly get => fTX;
+ set => fTX = value;
+ }
+
+ // public float fTY
+ private Single fTY;
+ public Single TY {
+ readonly get => fTY;
+ set => fTY = value;
+ }
+
+ public readonly bool Equals (SKRotationScaleMatrix obj) =>
+ fSCos == obj.fSCos && fSSin == obj.fSSin && fTX == obj.fTX && fTY == obj.fTY;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKRotationScaleMatrix f && Equals (f);
+
+ public static bool operator == (SKRotationScaleMatrix left, SKRotationScaleMatrix right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKRotationScaleMatrix left, SKRotationScaleMatrix right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fSCos);
+ hash.Add (fSSin);
+ hash.Add (fTX);
+ hash.Add (fTY);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_size_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKSize : IEquatable<SKSize> {
+ // public float w
+ private Single w;
+ public Single Width {
+ readonly get => w;
+ set => w = value;
+ }
+
+ // public float h
+ private Single h;
+ public Single Height {
+ readonly get => h;
+ set => h = value;
+ }
+
+ public readonly bool Equals (SKSize obj) =>
+ w == obj.w && h == obj.h;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKSize f && Equals (f);
+
+ public static bool operator == (SKSize left, SKSize right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKSize left, SKSize right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (w);
+ hash.Add (h);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_textblob_builder_runbuffer_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKRunBufferInternal : IEquatable<SKRunBufferInternal> {
+ // public void* glyphs
+ public void* glyphs;
+
+ // public void* pos
+ public void* pos;
+
+ // public void* utf8text
+ public void* utf8text;
+
+ // public void* clusters
+ public void* clusters;
+
+ public readonly bool Equals (SKRunBufferInternal obj) =>
+ glyphs == obj.glyphs && pos == obj.pos && utf8text == obj.utf8text && clusters == obj.clusters;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKRunBufferInternal f && Equals (f);
+
+ public static bool operator == (SKRunBufferInternal left, SKRunBufferInternal right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKRunBufferInternal left, SKRunBufferInternal right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (glyphs);
+ hash.Add (pos);
+ hash.Add (utf8text);
+ hash.Add (clusters);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_time_datetime_t
+ [StructLayout (LayoutKind.Sequential)]
+ internal unsafe partial struct SKTimeDateTimeInternal : IEquatable<SKTimeDateTimeInternal> {
+ // public int16_t fTimeZoneMinutes
+ public Int16 fTimeZoneMinutes;
+
+ // public uint16_t fYear
+ public UInt16 fYear;
+
+ // public uint8_t fMonth
+ public Byte fMonth;
+
+ // public uint8_t fDayOfWeek
+ public Byte fDayOfWeek;
+
+ // public uint8_t fDay
+ public Byte fDay;
+
+ // public uint8_t fHour
+ public Byte fHour;
+
+ // public uint8_t fMinute
+ public Byte fMinute;
+
+ // public uint8_t fSecond
+ public Byte fSecond;
+
+ public readonly bool Equals (SKTimeDateTimeInternal obj) =>
+ fTimeZoneMinutes == obj.fTimeZoneMinutes && fYear == obj.fYear && fMonth == obj.fMonth && fDayOfWeek == obj.fDayOfWeek && fDay == obj.fDay && fHour == obj.fHour && fMinute == obj.fMinute && fSecond == obj.fSecond;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKTimeDateTimeInternal f && Equals (f);
+
+ public static bool operator == (SKTimeDateTimeInternal left, SKTimeDateTimeInternal right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKTimeDateTimeInternal left, SKTimeDateTimeInternal right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fTimeZoneMinutes);
+ hash.Add (fYear);
+ hash.Add (fMonth);
+ hash.Add (fDayOfWeek);
+ hash.Add (fDay);
+ hash.Add (fHour);
+ hash.Add (fMinute);
+ hash.Add (fSecond);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ // sk_webpencoder_options_t
+ [StructLayout (LayoutKind.Sequential)]
+ public unsafe partial struct SKWebpEncoderOptions : IEquatable<SKWebpEncoderOptions> {
+ // public sk_webpencoder_compression_t fCompression
+ private SKWebpEncoderCompression fCompression;
+ public SKWebpEncoderCompression Compression {
+ readonly get => fCompression;
+ set => fCompression = value;
+ }
+
+ // public float fQuality
+ private Single fQuality;
+ public Single Quality {
+ readonly get => fQuality;
+ set => fQuality = value;
+ }
+
+ // public sk_transfer_function_behavior_t fUnpremulBehavior
+ private SKTransferFunctionBehavior fUnpremulBehavior;
+ public SKTransferFunctionBehavior UnpremulBehavior {
+ readonly get => fUnpremulBehavior;
+ set => fUnpremulBehavior = value;
+ }
+
+ public readonly bool Equals (SKWebpEncoderOptions obj) =>
+ fCompression == obj.fCompression && fQuality == obj.fQuality && fUnpremulBehavior == obj.fUnpremulBehavior;
+
+ public readonly override bool Equals (object obj) =>
+ obj is SKWebpEncoderOptions f && Equals (f);
+
+ public static bool operator == (SKWebpEncoderOptions left, SKWebpEncoderOptions right) =>
+ left.Equals (right);
+
+ public static bool operator != (SKWebpEncoderOptions left, SKWebpEncoderOptions right) =>
+ !left.Equals (right);
+
+ public readonly override int GetHashCode ()
+ {
+ var hash = new HashCode ();
+ hash.Add (fCompression);
+ hash.Add (fQuality);
+ hash.Add (fUnpremulBehavior);
+ return hash.ToHashCode ();
+ }
+
+ }
+
+ #endregion
+
+ #region Enums
+
+ // gr_backend_t
+ public enum GRBackend {
+ // METAL_GR_BACKEND = 0
+ Metal = 0,
+ // OPENGL_GR_BACKEND = 1
+ OpenGL = 1,
+ // VULKAN_GR_BACKEND = 2
+ Vulkan = 2,
+ }
+
+ // gr_pixelconfig_t
+ public enum GRPixelConfig {
+ // UNKNOWN_GR_PIXEL_CONFIG = 0
+ Unknown = 0,
+ // ALPHA_8_GR_PIXEL_CONFIG = 1
+ Alpha8 = 1,
+ // GRAY_8_GR_PIXEL_CONFIG = 2
+ Gray8 = 2,
+ // RGB_565_GR_PIXEL_CONFIG = 3
+ Rgb565 = 3,
+ // RGBA_4444_GR_PIXEL_CONFIG = 4
+ Rgba4444 = 4,
+ // RGBA_8888_GR_PIXEL_CONFIG = 5
+ Rgba8888 = 5,
+ // RGB_888_GR_PIXEL_CONFIG = 6
+ Rgb888 = 6,
+ // BGRA_8888_GR_PIXEL_CONFIG = 7
+ Bgra8888 = 7,
+ // SRGBA_8888_GR_PIXEL_CONFIG = 8
+ Srgba8888 = 8,
+ // SBGRA_8888_GR_PIXEL_CONFIG = 9
+ Sbgra8888 = 9,
+ // RGBA_1010102_GR_PIXEL_CONFIG = 10
+ Rgba1010102 = 10,
+ // RGBA_FLOAT_GR_PIXEL_CONFIG = 11
+ RgbaFloat = 11,
+ // RG_FLOAT_GR_PIXEL_CONFIG = 12
+ RgFloat = 12,
+ // ALPHA_HALF_GR_PIXEL_CONFIG = 13
+ AlphaHalf = 13,
+ // RGBA_HALF_GR_PIXEL_CONFIG = 14
+ RgbaHalf = 14,
+ }
+
+ // gr_surfaceorigin_t
+ public enum GRSurfaceOrigin {
+ // TOP_LEFT_GR_SURFACE_ORIGIN = 0
+ TopLeft = 0,
+ // BOTTOM_LEFT_GR_SURFACE_ORIGIN = 1
+ BottomLeft = 1,
+ }
+
+ // sk_alphatype_t
+ public enum SKAlphaType {
+ // UNKNOWN_SK_ALPHATYPE = 0
+ Unknown = 0,
+ // OPAQUE_SK_ALPHATYPE = 1
+ Opaque = 1,
+ // PREMUL_SK_ALPHATYPE = 2
+ Premul = 2,
+ // UNPREMUL_SK_ALPHATYPE = 3
+ Unpremul = 3,
+ }
+
+ // sk_bitmap_allocflags_t
+ [Flags]
+ public enum SKBitmapAllocFlags {
+ // NONE_SK_BITMAP_ALLOC_FLAGS = 0
+ None = 0,
+ // ZERO_PIXELS_SK_BITMAP_ALLOC_FLAGS = 1 << 0
+ ZeroPixels = 1,
+ }
+
+ // sk_blendmode_t
+ public enum SKBlendMode {
+ // CLEAR_SK_BLENDMODE = 0
+ Clear = 0,
+ // SRC_SK_BLENDMODE = 1
+ Src = 1,
+ // DST_SK_BLENDMODE = 2
+ Dst = 2,
+ // SRCOVER_SK_BLENDMODE = 3
+ SrcOver = 3,
+ // DSTOVER_SK_BLENDMODE = 4
+ DstOver = 4,
+ // SRCIN_SK_BLENDMODE = 5
+ SrcIn = 5,
+ // DSTIN_SK_BLENDMODE = 6
+ DstIn = 6,
+ // SRCOUT_SK_BLENDMODE = 7
+ SrcOut = 7,
+ // DSTOUT_SK_BLENDMODE = 8
+ DstOut = 8,
+ // SRCATOP_SK_BLENDMODE = 9
+ SrcATop = 9,
+ // DSTATOP_SK_BLENDMODE = 10
+ DstATop = 10,
+ // XOR_SK_BLENDMODE = 11
+ Xor = 11,
+ // PLUS_SK_BLENDMODE = 12
+ Plus = 12,
+ // MODULATE_SK_BLENDMODE = 13
+ Modulate = 13,
+ // SCREEN_SK_BLENDMODE = 14
+ Screen = 14,
+ // OVERLAY_SK_BLENDMODE = 15
+ Overlay = 15,
+ // DARKEN_SK_BLENDMODE = 16
+ Darken = 16,
+ // LIGHTEN_SK_BLENDMODE = 17
+ Lighten = 17,
+ // COLORDODGE_SK_BLENDMODE = 18
+ ColorDodge = 18,
+ // COLORBURN_SK_BLENDMODE = 19
+ ColorBurn = 19,
+ // HARDLIGHT_SK_BLENDMODE = 20
+ HardLight = 20,
+ // SOFTLIGHT_SK_BLENDMODE = 21
+ SoftLight = 21,
+ // DIFFERENCE_SK_BLENDMODE = 22
+ Difference = 22,
+ // EXCLUSION_SK_BLENDMODE = 23
+ Exclusion = 23,
+ // MULTIPLY_SK_BLENDMODE = 24
+ Multiply = 24,
+ // HUE_SK_BLENDMODE = 25
+ Hue = 25,
+ // SATURATION_SK_BLENDMODE = 26
+ Saturation = 26,
+ // COLOR_SK_BLENDMODE = 27
+ Color = 27,
+ // LUMINOSITY_SK_BLENDMODE = 28
+ Luminosity = 28,
+ }
+
+ // sk_blurstyle_t
+ public enum SKBlurStyle {
+ // NORMAL_SK_BLUR_STYLE = 0
+ Normal = 0,
+ // SOLID_SK_BLUR_STYLE = 1
+ Solid = 1,
+ // OUTER_SK_BLUR_STYLE = 2
+ Outer = 2,
+ // INNER_SK_BLUR_STYLE = 3
+ Inner = 3,
+ }
+
+ // sk_clipop_t
+ public enum SKClipOperation {
+ // DIFFERENCE_SK_CLIPOP = 0
+ Difference = 0,
+ // INTERSECT_SK_CLIPOP = 1
+ Intersect = 1,
+ }
+
+ // sk_codec_result_t
+ public enum SKCodecResult {
+ // SUCCESS_SK_CODEC_RESULT = 0
+ Success = 0,
+ // INCOMPLETE_INPUT_SK_CODEC_RESULT = 1
+ IncompleteInput = 1,
+ // ERROR_IN_INPUT_SK_CODEC_RESULT = 2
+ ErrorInInput = 2,
+ // INVALID_CONVERSION_SK_CODEC_RESULT = 3
+ InvalidConversion = 3,
+ // INVALID_SCALE_SK_CODEC_RESULT = 4
+ InvalidScale = 4,
+ // INVALID_PARAMETERS_SK_CODEC_RESULT = 5
+ InvalidParameters = 5,
+ // INVALID_INPUT_SK_CODEC_RESULT = 6
+ InvalidInput = 6,
+ // COULD_NOT_REWIND_SK_CODEC_RESULT = 7
+ CouldNotRewind = 7,
+ // INTERNAL_ERROR_SK_CODEC_RESULT = 8
+ InternalError = 8,
+ // UNIMPLEMENTED_SK_CODEC_RESULT = 9
+ Unimplemented = 9,
+ }
+
+ // sk_codec_scanline_order_t
+ public enum SKCodecScanlineOrder {
+ // TOP_DOWN_SK_CODEC_SCANLINE_ORDER = 0
+ TopDown = 0,
+ // BOTTOM_UP_SK_CODEC_SCANLINE_ORDER = 1
+ BottomUp = 1,
+ }
+
+ // sk_codec_zero_initialized_t
+ public enum SKZeroInitialized {
+ // YES_SK_CODEC_ZERO_INITIALIZED = 0
+ Yes = 0,
+ // NO_SK_CODEC_ZERO_INITIALIZED = 1
+ No = 1,
+ }
+
+ // sk_codecanimation_disposalmethod_t
+ public enum SKCodecAnimationDisposalMethod {
+ // KEEP_SK_CODEC_ANIMATION_DISPOSAL_METHOD = 1
+ Keep = 1,
+ // RESTORE_BG_COLOR_SK_CODEC_ANIMATION_DISPOSAL_METHOD = 2
+ RestoreBackgroundColor = 2,
+ // RESTORE_PREVIOUS_SK_CODEC_ANIMATION_DISPOSAL_METHOD = 3
+ RestorePrevious = 3,
+ }
+
+ // sk_colorspace_gamut_t
+ public enum SKColorSpaceGamut {
+ // SRGB_SK_COLORSPACE_GAMUT = 0
+ Srgb = 0,
+ // ADOBE_RGB_SK_COLORSPACE_GAMUT = 1
+ AdobeRgb = 1,
+ // DCIP3_D65_SK_COLORSPACE_GAMUT = 2
+ Dcip3D65 = 2,
+ // REC2020_SK_COLORSPACE_GAMUT = 3
+ Rec2020 = 3,
+ }
+
+ // sk_colorspace_render_target_gamma_t
+ public enum SKColorSpaceRenderTargetGamma {
+ // LINEAR_SK_COLORSPACE_RENDER_TARGET_GAMMA = 0
+ Linear = 0,
+ // SRGB_SK_COLORSPACE_RENDER_TARGET_GAMMA = 1
+ Srgb = 1,
+ }
+
+ // sk_colorspace_type_t
+ public enum SKColorSpaceType {
+ // RGB_SK_COLORSPACE_TYPE = 0
+ Rgb = 0,
+ // CMYK_SK_COLORSPACE_TYPE = 1
+ Cmyk = 1,
+ // GRAY_SK_COLORSPACE_TYPE = 2
+ Gray = 2,
+ }
+
+ // sk_colortype_t
+ public enum SKColorType {
+ // UNKNOWN_SK_COLORTYPE = 0
+ Unknown = 0,
+ // ALPHA_8_SK_COLORTYPE = 1
+ Alpha8 = 1,
+ // RGB_565_SK_COLORTYPE = 2
+ Rgb565 = 2,
+ // ARGB_4444_SK_COLORTYPE = 3
+ Argb4444 = 3,
+ // RGBA_8888_SK_COLORTYPE = 4
+ Rgba8888 = 4,
+ // RGB_888X_SK_COLORTYPE = 5
+ Rgb888x = 5,
+ // BGRA_8888_SK_COLORTYPE = 6
+ Bgra8888 = 6,
+ // RGBA_1010102_SK_COLORTYPE = 7
+ Rgba1010102 = 7,
+ // RGB_101010X_SK_COLORTYPE = 8
+ Rgb101010x = 8,
+ // GRAY_8_SK_COLORTYPE = 9
+ Gray8 = 9,
+ // RGBA_F16_SK_COLORTYPE = 10
+ RgbaF16 = 10,
+ }
+
+ // sk_crop_rect_flags_t
+ [Flags]
+ public enum SKCropRectFlags {
+ // HAS_NONE_SK_CROP_RECT_FLAG = 0x00
+ HasNone = 0,
+ // HAS_LEFT_SK_CROP_RECT_FLAG = 0x01
+ HasLeft = 1,
+ // HAS_TOP_SK_CROP_RECT_FLAG = 0x02
+ HasTop = 2,
+ // HAS_WIDTH_SK_CROP_RECT_FLAG = 0x04
+ HasWidth = 4,
+ // HAS_HEIGHT_SK_CROP_RECT_FLAG = 0x08
+ HasHeight = 8,
+ // HAS_ALL_SK_CROP_RECT_FLAG = 0x0F
+ HasAll = 15,
+ }
+
+ // sk_displacement_map_effect_channel_selector_type_t
+ public enum SKDisplacementMapEffectChannelSelectorType {
+ // UNKNOWN_SK_DISPLACEMENT_MAP_EFFECT_CHANNEL_SELECTOR_TYPE = 0
+ Unknown = 0,
+ // R_SK_DISPLACEMENT_MAP_EFFECT_CHANNEL_SELECTOR_TYPE = 1
+ R = 1,
+ // G_SK_DISPLACEMENT_MAP_EFFECT_CHANNEL_SELECTOR_TYPE = 2
+ G = 2,
+ // B_SK_DISPLACEMENT_MAP_EFFECT_CHANNEL_SELECTOR_TYPE = 3
+ B = 3,
+ // A_SK_DISPLACEMENT_MAP_EFFECT_CHANNEL_SELECTOR_TYPE = 4
+ A = 4,
+ }
+
+ // sk_drop_shadow_image_filter_shadow_mode_t
+ public enum SKDropShadowImageFilterShadowMode {
+ // DRAW_SHADOW_AND_FOREGROUND_SK_DROP_SHADOW_IMAGE_FILTER_SHADOW_MODE = 0
+ DrawShadowAndForeground = 0,
+ // DRAW_SHADOW_ONLY_SK_DROP_SHADOW_IMAGE_FILTER_SHADOW_MODE = 1
+ DrawShadowOnly = 1,
+ }
+
+ // sk_encoded_image_format_t
+ public enum SKEncodedImageFormat {
+ // BMP_SK_ENCODED_FORMAT = 0
+ Bmp = 0,
+ // GIF_SK_ENCODED_FORMAT = 1
+ Gif = 1,
+ // ICO_SK_ENCODED_FORMAT = 2
+ Ico = 2,
+ // JPEG_SK_ENCODED_FORMAT = 3
+ Jpeg = 3,
+ // PNG_SK_ENCODED_FORMAT = 4
+ Png = 4,
+ // WBMP_SK_ENCODED_FORMAT = 5
+ Wbmp = 5,
+ // WEBP_SK_ENCODED_FORMAT = 6
+ Webp = 6,
+ // PKM_SK_ENCODED_FORMAT = 7
+ Pkm = 7,
+ // KTX_SK_ENCODED_FORMAT = 8
+ Ktx = 8,
+ // ASTC_SK_ENCODED_FORMAT = 9
+ Astc = 9,
+ // DNG_SK_ENCODED_FORMAT = 10
+ Dng = 10,
+ // HEIF_SK_ENCODED_FORMAT = 11
+ Heif = 11,
+ }
+
+ // sk_encodedorigin_t
+ public enum SKEncodedOrigin {
+ // TOP_LEFT_SK_ENCODED_ORIGIN = 1
+ TopLeft = 1,
+ // TOP_RIGHT_SK_ENCODED_ORIGIN = 2
+ TopRight = 2,
+ // BOTTOM_RIGHT_SK_ENCODED_ORIGIN = 3
+ BottomRight = 3,
+ // BOTTOM_LEFT_SK_ENCODED_ORIGIN = 4
+ BottomLeft = 4,
+ // LEFT_TOP_SK_ENCODED_ORIGIN = 5
+ LeftTop = 5,
+ // RIGHT_TOP_SK_ENCODED_ORIGIN = 6
+ RightTop = 6,
+ // RIGHT_BOTTOM_SK_ENCODED_ORIGIN = 7
+ RightBottom = 7,
+ // LEFT_BOTTOM_SK_ENCODED_ORIGIN = 8
+ LeftBottom = 8,
+ // DEFAULT_SK_ENCODED_ORIGIN = TOP_LEFT_SK_ENCODED_ORIGIN
+ Default = 1,
+ }
+
+ // sk_encoding_t
+ public enum SKEncoding {
+ // UTF8_SK_ENCODING = 0
+ Utf8 = 0,
+ // UTF16_SK_ENCODING = 1
+ Utf16 = 1,
+ // UTF32_SK_ENCODING = 2
+ Utf32 = 2,
+ }
+
+ // sk_filter_quality_t
+ public enum SKFilterQuality {
+ // NONE_SK_FILTER_QUALITY = 0
+ None = 0,
+ // LOW_SK_FILTER_QUALITY = 1
+ Low = 1,
+ // MEDIUM_SK_FILTER_QUALITY = 2
+ Medium = 2,
+ // HIGH_SK_FILTER_QUALITY = 3
+ High = 3,
+ }
+
+ // sk_font_style_slant_t
+ public enum SKFontStyleSlant {
+ // UPRIGHT_SK_FONT_STYLE_SLANT = 0
+ Upright = 0,
+ // ITALIC_SK_FONT_STYLE_SLANT = 1
+ Italic = 1,
+ // OBLIQUE_SK_FONT_STYLE_SLANT = 2
+ Oblique = 2,
+ }
+
+ // sk_gamma_named_t
+ public enum SKNamedGamma {
+ // LINEAR_SK_GAMMA_NAMED = 0
+ Linear = 0,
+ // SRGB_SK_GAMMA_NAMED = 1
+ Srgb = 1,
+ // TWO_DOT_TWO_CURVE_SK_GAMMA_NAMED = 2
+ TwoDotTwoCurve = 2,
+ // NON_STANDARD_SK_GAMMA_NAMED = 3
+ NonStandard = 3,
+ }
+
+ // sk_highcontrastconfig_invertstyle_t
+ public enum SKHighContrastConfigInvertStyle {
+ // NO_INVERT_SK_HIGH_CONTRAST_CONFIG_INVERT_STYLE = 0
+ NoInvert = 0,
+ // INVERT_BRIGHTNESS_SK_HIGH_CONTRAST_CONFIG_INVERT_STYLE = 1
+ InvertBrightness = 1,
+ // INVERT_LIGHTNESS_SK_HIGH_CONTRAST_CONFIG_INVERT_STYLE = 2
+ InvertLightness = 2,
+ }
+
+ // sk_image_caching_hint_t
+ public enum SKImageCachingHint {
+ // ALLOW_SK_IMAGE_CACHING_HINT = 0
+ Allow = 0,
+ // DISALLOW_SK_IMAGE_CACHING_HINT = 1
+ Disallow = 1,
+ }
+
+ // sk_jpegencoder_alphaoption_t
+ public enum SKJpegEncoderAlphaOption {
+ // IGNORE_SK_JPEGENCODER_ALPHA_OPTION = 0
+ Ignore = 0,
+ // BLEND_ON_BLACK_SK_JPEGENCODER_ALPHA_OPTION = 1
+ BlendOnBlack = 1,
+ }
+
+ // sk_jpegencoder_downsample_t
+ public enum SKJpegEncoderDownsample {
+ // DOWNSAMPLE_420_SK_JPEGENCODER_DOWNSAMPLE = 0
+ Downsample420 = 0,
+ // DOWNSAMPLE_422_SK_JPEGENCODER_DOWNSAMPLE = 1
+ Downsample422 = 1,
+ // DOWNSAMPLE_444_SK_JPEGENCODER_DOWNSAMPLE = 2
+ Downsample444 = 2,
+ }
+
+ // sk_lattice_recttype_t
+ public enum SKLatticeRectType {
+ // DEFAULT_SK_LATTICE_RECT_TYPE = 0
+ Default = 0,
+ // TRANSPARENT_SK_LATTICE_RECT_TYPE = 1
+ Transparent = 1,
+ // FIXED_COLOR_SK_LATTICE_RECT_TYPE = 2
+ FixedColor = 2,
+ }
+
+ // sk_mask_format_t
+ public enum SKMaskFormat {
+ // BW_SK_MASK_FORMAT = 0
+ BW = 0,
+ // A8_SK_MASK_FORMAT = 1
+ A8 = 1,
+ // THREE_D_SK_MASK_FORMAT = 2
+ ThreeD = 2,
+ // ARGB32_SK_MASK_FORMAT = 3
+ Argb32 = 3,
+ // LCD16_SK_MASK_FORMAT = 4
+ Lcd16 = 4,
+ }
+
+ // sk_matrix_convolution_tilemode_t
+ public enum SKMatrixConvolutionTileMode {
+ // CLAMP_SK_MATRIX_CONVOLUTION_TILEMODE = 0
+ Clamp = 0,
+ // REPEAT_SK_MATRIX_CONVOLUTION_TILEMODE = 1
+ Repeat = 1,
+ // CLAMP_TO_BLACK_SK_MATRIX_CONVOLUTION_TILEMODE = 2
+ ClampToBlack = 2,
+ }
+
+ // sk_matrix44_type_mask_t
+ [Flags]
+ public enum SKMatrix44TypeMask {
+ // IDENTITY_SK_MATRIX44_TYPE_MASK = 0
+ Identity = 0,
+ // TRANSLATE_SK_MATRIX44_TYPE_MASK = 0x01
+ Translate = 1,
+ // SCALE_SK_MATRIX44_TYPE_MASK = 0x02
+ Scale = 2,
+ // AFFINE_SK_MATRIX44_TYPE_MASK = 0x04
+ Affine = 4,
+ // PERSPECTIVE_SK_MATRIX44_TYPE_MASK = 0x08
+ Perspective = 8,
+ }
+
+ // sk_paint_hinting_t
+ public enum SKPaintHinting {
+ // NO_HINTING_SK_PAINT_HINTING = 0
+ NoHinting = 0,
+ // SLIGHT_HINTING_SK_PAINT_HINTING = 1
+ Slight = 1,
+ // NORMAL_HINTING_SK_PAINT_HINTING = 2
+ Normal = 2,
+ // FULL_HINTING_SK_PAINT_HINTING = 3
+ Full = 3,
+ }
+
+ // sk_paint_style_t
+ public enum SKPaintStyle {
+ // FILL_SK_PAINT_STYLE = 0
+ Fill = 0,
+ // STROKE_SK_PAINT_STYLE = 1
+ Stroke = 1,
+ // STROKE_AND_FILL_SK_PAINT_STYLE = 2
+ StrokeAndFill = 2,
+ }
+
+ // sk_path_add_mode_t
+ public enum SKPathAddMode {
+ // APPEND_SK_PATH_ADD_MODE = 0
+ Append = 0,
+ // EXTEND_SK_PATH_ADD_MODE = 1
+ Extend = 1,
+ }
+
+ // sk_path_arc_size_t
+ public enum SKPathArcSize {
+ // SMALL_SK_PATH_ARC_SIZE = 0
+ Small = 0,
+ // LARGE_SK_PATH_ARC_SIZE = 1
+ Large = 1,
+ }
+
+ // sk_path_convexity_t
+ public enum SKPathConvexity {
+ // UNKNOWN_SK_PATH_CONVEXITY = 0
+ Unknown = 0,
+ // CONVEX_SK_PATH_CONVEXITY = 1
+ Convex = 1,
+ // CONCAVE_SK_PATH_CONVEXITY = 2
+ Concave = 2,
+ }
+
+ // sk_path_direction_t
+ public enum SKPathDirection {
+ // CW_SK_PATH_DIRECTION = 0
+ Clockwise = 0,
+ // CCW_SK_PATH_DIRECTION = 1
+ CounterClockwise = 1,
+ }
+
+ // sk_path_effect_1d_style_t
+ public enum SKPath1DPathEffectStyle {
+ // TRANSLATE_SK_PATH_EFFECT_1D_STYLE = 0
+ Translate = 0,
+ // ROTATE_SK_PATH_EFFECT_1D_STYLE = 1
+ Rotate = 1,
+ // MORPH_SK_PATH_EFFECT_1D_STYLE = 2
+ Morph = 2,
+ }
+
+ // sk_path_effect_trim_mode_t
+ public enum SKTrimPathEffectMode {
+ // NORMAL_SK_PATH_EFFECT_TRIM_MODE = 0
+ Normal = 0,
+ // INVERTED_SK_PATH_EFFECT_TRIM_MODE = 1
+ Inverted = 1,
+ }
+
+ // sk_path_filltype_t
+ public enum SKPathFillType {
+ // WINDING_SK_PATH_FILLTYPE = 0
+ Winding = 0,
+ // EVENODD_SK_PATH_FILLTYPE = 1
+ EvenOdd = 1,
+ // INVERSE_WINDING_SK_PATH_FILLTYPE = 2
+ InverseWinding = 2,
+ // INVERSE_EVENODD_SK_PATH_FILLTYPE = 3
+ InverseEvenOdd = 3,
+ }
+
+ // sk_path_segment_mask_t
+ [Flags]
+ public enum SKPathSegmentMask {
+ // LINE_SK_PATH_SEGMENT_MASK = 1 << 0
+ Line = 1,
+ // QUAD_SK_PATH_SEGMENT_MASK = 1 << 1
+ Quad = 2,
+ // CONIC_SK_PATH_SEGMENT_MASK = 1 << 2
+ Conic = 4,
+ // CUBIC_SK_PATH_SEGMENT_MASK = 1 << 3
+ Cubic = 8,
+ }
+
+ // sk_path_verb_t
+ public enum SKPathVerb {
+ // MOVE_SK_PATH_VERB = 0
+ Move = 0,
+ // LINE_SK_PATH_VERB = 1
+ Line = 1,
+ // QUAD_SK_PATH_VERB = 2
+ Quad = 2,
+ // CONIC_SK_PATH_VERB = 3
+ Conic = 3,
+ // CUBIC_SK_PATH_VERB = 4
+ Cubic = 4,
+ // CLOSE_SK_PATH_VERB = 5
+ Close = 5,
+ // DONE_SK_PATH_VERB = 6
+ Done = 6,
+ }
+
+ // sk_pathmeasure_matrixflags_t
+ [Flags]
+ public enum SKPathMeasureMatrixFlags {
+ // GET_POSITION_SK_PATHMEASURE_MATRIXFLAGS = 0x01
+ GetPosition = 1,
+ // GET_TANGENT_SK_PATHMEASURE_MATRIXFLAGS = 0x02
+ GetTangent = 2,
+ // GET_POS_AND_TAN_SK_PATHMEASURE_MATRIXFLAGS = GET_POSITION_SK_PATHMEASURE_MATRIXFLAGS | GET_TANGENT_SK_PATHMEASURE_MATRIXFLAGS
+ GetPositionAndTangent = 3,
+ }
+
+ // sk_pathop_t
+ public enum SKPathOp {
+ // DIFFERENCE_SK_PATHOP = 0
+ Difference = 0,
+ // INTERSECT_SK_PATHOP = 1
+ Intersect = 1,
+ // UNION_SK_PATHOP = 2
+ Union = 2,
+ // XOR_SK_PATHOP = 3
+ Xor = 3,
+ // REVERSE_DIFFERENCE_SK_PATHOP = 4
+ ReverseDifference = 4,
+ }
+
+ // sk_pixelgeometry_t
+ public enum SKPixelGeometry {
+ // UNKNOWN_SK_PIXELGEOMETRY = 0
+ Unknown = 0,
+ // RGB_H_SK_PIXELGEOMETRY = 1
+ RgbHorizontal = 1,
+ // BGR_H_SK_PIXELGEOMETRY = 2
+ BgrHorizontal = 2,
+ // RGB_V_SK_PIXELGEOMETRY = 3
+ RgbVertical = 3,
+ // BGR_V_SK_PIXELGEOMETRY = 4
+ BgrVertical = 4,
+ }
+
+ // sk_pngencoder_filterflags_t
+ [Flags]
+ public enum SKPngEncoderFilterFlags {
+ // ZERO_SK_PNGENCODER_FILTER_FLAGS = 0x00
+ NoFilters = 0,
+ // NONE_SK_PNGENCODER_FILTER_FLAGS = 0x08
+ None = 8,
+ // SUB_SK_PNGENCODER_FILTER_FLAGS = 0x10
+ Sub = 16,
+ // UP_SK_PNGENCODER_FILTER_FLAGS = 0x20
+ Up = 32,
+ // AVG_SK_PNGENCODER_FILTER_FLAGS = 0x40
+ Avg = 64,
+ // PAETH_SK_PNGENCODER_FILTER_FLAGS = 0x80
+ Paeth = 128,
+ // ALL_SK_PNGENCODER_FILTER_FLAGS = NONE_SK_PNGENCODER_FILTER_FLAGS | SUB_SK_PNGENCODER_FILTER_FLAGS | UP_SK_PNGENCODER_FILTER_FLAGS | AVG_SK_PNGENCODER_FILTER_FLAGS | PAETH_SK_PNGENCODER_FILTER_FLAGS
+ AllFilters = 248,
+ }
+
+ // sk_point_mode_t
+ public enum SKPointMode {
+ // POINTS_SK_POINT_MODE = 0
+ Points = 0,
+ // LINES_SK_POINT_MODE = 1
+ Lines = 1,
+ // POLYGON_SK_POINT_MODE = 2
+ Polygon = 2,
+ }
+
+ // sk_region_op_t
+ public enum SKRegionOperation {
+ // DIFFERENCE_SK_REGION_OP = 0
+ Difference = 0,
+ // INTERSECT_SK_REGION_OP = 1
+ Intersect = 1,
+ // UNION_SK_REGION_OP = 2
+ Union = 2,
+ // XOR_SK_REGION_OP = 3
+ XOR = 3,
+ // REVERSE_DIFFERENCE_SK_REGION_OP = 4
+ ReverseDifference = 4,
+ // REPLACE_SK_REGION_OP = 5
+ Replace = 5,
+ }
+
+ // sk_rrect_corner_t
+ public enum SKRoundRectCorner {
+ // UPPER_LEFT_SK_RRECT_CORNER = 0
+ UpperLeft = 0,
+ // UPPER_RIGHT_SK_RRECT_CORNER = 1
+ UpperRight = 1,
+ // LOWER_RIGHT_SK_RRECT_CORNER = 2
+ LowerRight = 2,
+ // LOWER_LEFT_SK_RRECT_CORNER = 3
+ LowerLeft = 3,
+ }
+
+ // sk_rrect_type_t
+ public enum SKRoundRectType {
+ // EMPTY_SK_RRECT_TYPE = 0
+ Empty = 0,
+ // RECT_SK_RRECT_TYPE = 1
+ Rect = 1,
+ // OVAL_SK_RRECT_TYPE = 2
+ Oval = 2,
+ // SIMPLE_SK_RRECT_TYPE = 3
+ Simple = 3,
+ // NINE_PATCH_SK_RRECT_TYPE = 4
+ NinePatch = 4,
+ // COMPLEX_SK_RRECT_TYPE = 5
+ Complex = 5,
+ }
+
+ // sk_shader_tilemode_t
+ public enum SKShaderTileMode {
+ // CLAMP_SK_SHADER_TILEMODE = 0
+ Clamp = 0,
+ // REPEAT_SK_SHADER_TILEMODE = 1
+ Repeat = 1,
+ // MIRROR_SK_SHADER_TILEMODE = 2
+ Mirror = 2,
+ }
+
+ // sk_stroke_cap_t
+ public enum SKStrokeCap {
+ // BUTT_SK_STROKE_CAP = 0
+ Butt = 0,
+ // ROUND_SK_STROKE_CAP = 1
+ Round = 1,
+ // SQUARE_SK_STROKE_CAP = 2
+ Square = 2,
+ }
+
+ // sk_stroke_join_t
+ public enum SKStrokeJoin {
+ // MITER_SK_STROKE_JOIN = 0
+ Miter = 0,
+ // ROUND_SK_STROKE_JOIN = 1
+ Round = 1,
+ // BEVEL_SK_STROKE_JOIN = 2
+ Bevel = 2,
+ }
+
+ // sk_surfaceprops_flags_t
+ [Flags]
+ public enum SKSurfacePropsFlags {
+ // NONE_SK_SURFACE_PROPS_FLAGS = 0
+ None = 0,
+ // USE_DEVICE_INDEPENDENT_FONTS_SK_SURFACE_PROPS_FLAGS = 1 << 0
+ UseDeviceIndependentFonts = 1,
+ }
+
+ // sk_text_align_t
+ public enum SKTextAlign {
+ // LEFT_SK_TEXT_ALIGN = 0
+ Left = 0,
+ // CENTER_SK_TEXT_ALIGN = 1
+ Center = 1,
+ // RIGHT_SK_TEXT_ALIGN = 2
+ Right = 2,
+ }
+
+ // sk_text_encoding_t
+ public enum SKTextEncoding {
+ // UTF8_SK_TEXT_ENCODING = 0
+ Utf8 = 0,
+ // UTF16_SK_TEXT_ENCODING = 1
+ Utf16 = 1,
+ // UTF32_SK_TEXT_ENCODING = 2
+ Utf32 = 2,
+ // GLYPH_ID_SK_TEXT_ENCODING = 3
+ GlyphId = 3,
+ }
+
+ // sk_transfer_function_behavior_t
+ public enum SKTransferFunctionBehavior {
+ // RESPECT_SK_TRANSFER_FUNCTION_BEHAVIOR = 0
+ Respect = 0,
+ // IGNORE_SK_TRANSFER_FUNCTION_BEHAVIOR = 1
+ Ignore = 1,
+ }
+
+ // sk_vertices_vertex_mode_t
+ public enum SKVertexMode {
+ // TRIANGLES_SK_VERTICES_VERTEX_MODE = 0
+ Triangles = 0,
+ // TRIANGLE_STRIP_SK_VERTICES_VERTEX_MODE = 1
+ TriangleStrip = 1,
+ // TRIANGLE_FAN_SK_VERTICES_VERTEX_MODE = 2
+ TriangleFan = 2,
+ }
+
+ // sk_webpencoder_compression_t
+ public enum SKWebpEncoderCompression {
+ // LOSSY_SK_WEBPENCODER_COMPTRESSION = 0
+ Lossy = 0,
+ // LOSSLESS_SK_WEBPENCODER_COMPTRESSION = 1
+ Lossless = 1,
+ }
+
+ #endregion
+}
--- /dev/null
+using System;
+using System.ComponentModel;
+using System.Text;
+
+namespace SkiaSharp
+{
+ internal unsafe static class Utils
+ {
+ internal const float NearlyZero = 1.0f / (1 << 12);
+
+ internal static Span<byte> AsSpan (this IntPtr ptr, int size) =>
+ new Span<byte> ((void*)ptr, size);
+
+ internal static ReadOnlySpan<byte> AsReadOnlySpan (this IntPtr ptr, int size) =>
+ new ReadOnlySpan<byte> ((void*)ptr, size);
+
+ internal static bool NearlyEqual (float a, float b, float tolerance) =>
+ Math.Abs (a - b) <= tolerance;
+
+ internal static byte[] GetBytes (this Encoding encoding, ReadOnlySpan<char> text)
+ {
+ if (text.Length == 0)
+ return new byte[0];
+
+ fixed (char* t = text) {
+ var byteCount = encoding.GetByteCount (t, text.Length);
+ if (byteCount == 0)
+ return new byte[0];
+
+ var bytes = new byte[byteCount];
+ fixed (byte* b = bytes) {
+ encoding.GetBytes (t, text.Length, b, byteCount);
+ }
+ return bytes;
+ }
+ }
+ }
+
+ public unsafe static class StringUtilities
+ {
+ // GetUnicodeStringLength
+
+ private static int GetUnicodeStringLength (SKTextEncoding encoding) =>
+ encoding switch
+ {
+ SKTextEncoding.Utf8 => 1,
+ SKTextEncoding.Utf16 => 1,
+ SKTextEncoding.Utf32 => 2,
+ _ => throw new ArgumentOutOfRangeException (nameof (encoding), $"Encoding {encoding} is not supported.")
+ };
+
+ // GetUnicodeCharacterCode
+
+ public static int GetUnicodeCharacterCode (string character, SKTextEncoding encoding)
+ {
+ if (character == null)
+ throw new ArgumentNullException (nameof (character));
+ if (GetUnicodeStringLength (encoding) != character.Length)
+ throw new ArgumentException (nameof (character), $"Only a single character can be specified.");
+
+ var bytes = GetEncodedText (character, encoding);
+ return BitConverter.ToInt32 (bytes, 0);
+ }
+
+ // GetEncodedText
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Obsolete ("Use GetEncodedText(string, SKTextEncoding) instead.")]
+ public static byte[] GetEncodedText (string text, SKEncoding encoding) =>
+ GetEncodedText (text.AsSpan (), encoding.ToTextEncoding ());
+
+ public static byte[] GetEncodedText (string text, SKTextEncoding encoding) =>
+ GetEncodedText (text.AsSpan (), encoding);
+
+ public static byte[] GetEncodedText (ReadOnlySpan<char> text, SKTextEncoding encoding) =>
+ encoding switch
+ {
+ SKTextEncoding.Utf8 => Encoding.UTF8.GetBytes (text),
+ SKTextEncoding.Utf16 => Encoding.Unicode.GetBytes (text),
+ SKTextEncoding.Utf32 => Encoding.UTF32.GetBytes (text),
+ _ => throw new ArgumentOutOfRangeException (nameof (encoding), $"Encoding {encoding} is not supported."),
+ };
+
+ // GetString
+
+ public static string GetString (IntPtr data, int dataLength, SKTextEncoding encoding) =>
+ GetString (data.AsReadOnlySpan (dataLength), 0, dataLength, encoding);
+
+ public static string GetString (byte[] data, SKTextEncoding encoding) =>
+ GetString (data, 0, data.Length, encoding);
+
+ public static string GetString (byte[] data, int index, int count, SKTextEncoding encoding)
+ {
+ if (data == null)
+ throw new ArgumentNullException (nameof (data));
+
+ return encoding switch
+ {
+ SKTextEncoding.Utf8 => Encoding.UTF8.GetString (data, index, count),
+ SKTextEncoding.Utf16 => Encoding.Unicode.GetString (data, index, count),
+ SKTextEncoding.Utf32 => Encoding.UTF32.GetString (data, index, count),
+ _ => throw new ArgumentOutOfRangeException (nameof (encoding), $"Encoding {encoding} is not supported."),
+ };
+ }
+
+ public static string GetString (ReadOnlySpan<byte> data, SKTextEncoding encoding) =>
+ GetString (data, 0, data.Length, encoding);
+
+ public static string GetString (ReadOnlySpan<byte> data, int index, int count, SKTextEncoding encoding)
+ {
+ data = data.Slice (index, count);
+
+ if (data.Length == 0)
+ return string.Empty;
+
+ fixed (byte* bp = data) {
+ return encoding switch
+ {
+ SKTextEncoding.Utf8 => Encoding.UTF8.GetString (bp, data.Length),
+ SKTextEncoding.Utf16 => Encoding.Unicode.GetString (bp, data.Length),
+ SKTextEncoding.Utf32 => Encoding.UTF32.GetString (bp, data.Length),
+ _ => throw new ArgumentOutOfRangeException (nameof (encoding), $"Encoding {encoding} is not supported."),
+ };
+ }
+ }
+ }
+}
<AssemblyOriginatorKeyFile>..\XSF.snk</AssemblyOriginatorKeyFile>
<Deterministic>True</Deterministic>
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>
+ <LangVersion>8.0</LangVersion>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Tizen.NET" Version="6.0.0.14995" />
+ <PackageReference Include="System.Memory" Version="4.5.3" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources\circle.png" />
<EmbeddedResource Include="Resources\wc_visual_cue.png" />
</ItemGroup>
-
- <ItemGroup>
- <None Include="lib/x86/liblottie-player.so.0">
- <Pack>true</Pack>
- <PackagePath>runtimes/linux-x86/native/liblottie-player.so.0</PackagePath>
- </None>
- </ItemGroup>
</Project>
\ No newline at end of file