From 8280bd533c8bce415ff56af105779b6ba5806e3d Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Mon, 17 Jul 2017 14:48:34 +0200 Subject: [PATCH] Added tests for the marshaling api - private bool is now byte - structs are blittable - all bools are marshaled as I1 - all strings are LPStr --- binding/Binding/Definitions.cs | 143 +++++++++--------- binding/Binding/SKCodec.cs | 36 +---- binding/Binding/SkiaApi.cs | 56 +++---- tests/Tests/SKApiTests.cs | 88 +++++++++++ tests/Tests/SKDataTest.cs | 10 ++ .../{SKPixmapTests.cs => SKPixmapTest.cs} | 0 6 files changed, 201 insertions(+), 132 deletions(-) create mode 100644 tests/Tests/SKApiTests.cs rename tests/Tests/{SKPixmapTests.cs => SKPixmapTest.cs} (100%) diff --git a/binding/Binding/Definitions.cs b/binding/Binding/Definitions.cs index 7ef2bbc7..ce60fd98 100644 --- a/binding/Binding/Definitions.cs +++ b/binding/Binding/Definitions.cs @@ -437,9 +437,24 @@ namespace SkiaSharp public SKZeroInitialized fZeroInitialized; public SKRectI* fSubset; public IntPtr fFrameIndex; - [MarshalAs(UnmanagedType.I1)] - public bool fHasPriorFrame; + public byte fHasPriorFrame; public SKTransferFunctionBehavior fPremulBehavior; + + public static unsafe SKCodecOptionsInternal FromManaged (ref SKCodecOptions managed) + { + var nativeOptions = new SKCodecOptionsInternal { + fZeroInitialized = managed.ZeroInitialized, + fSubset = null, + fFrameIndex = (IntPtr) managed.FrameIndex, + fHasPriorFrame = managed.HasPriorFrame ? (byte) 1 : (byte) 0, + fPremulBehavior = managed.PremulBehavior, + }; + if (managed.HasSubset) { + var subset = managed.Subset.Value; + nativeOptions.fSubset = ⊂ + } + return nativeOptions; + } } public struct SKCodecOptions { @@ -489,8 +504,7 @@ namespace SkiaSharp public struct SKCodecFrameInfo { private IntPtr requiredFrame; private IntPtr duration; - [MarshalAs (UnmanagedType.I1)] - private bool fullyRecieved; + private byte fullyRecieved; private SKAlphaType alphaType; public int RequiredFrame { @@ -504,8 +518,8 @@ namespace SkiaSharp } public bool FullyRecieved { - get { return fullyRecieved; } - set { fullyRecieved = value; } + get { return fullyRecieved != 0; } + set { fullyRecieved = value ? (byte)1 : (byte)0; } } public SKAlphaType AlphaType { @@ -1883,40 +1897,28 @@ namespace SkiaSharp [StructLayout(LayoutKind.Sequential)] public struct GRContextOptions { - [MarshalAs(UnmanagedType.I1)] - private bool fSuppressPrints; + private byte fSuppressPrints; private int fMaxTextureSizeOverride; private int fMaxTileSizeOverride; - [MarshalAs(UnmanagedType.I1)] - private bool fSuppressDualSourceBlending; + private byte fSuppressDualSourceBlending; private int fBufferMapThreshold; - [MarshalAs(UnmanagedType.I1)] - private bool fUseDrawInsteadOfPartialRenderTargetWrite; - [MarshalAs(UnmanagedType.I1)] - private bool fImmediateMode; + private byte fUseDrawInsteadOfPartialRenderTargetWrite; + private byte fImmediateMode; private int fMaxOpCombineLookback; private int fMaxOpCombineLookahead; - [MarshalAs(UnmanagedType.I1)] - private bool fUseShaderSwizzling; - [MarshalAs(UnmanagedType.I1)] - private bool fDoManualMipmapping; - [MarshalAs(UnmanagedType.I1)] - private bool fEnableInstancedRendering; - [MarshalAs(UnmanagedType.I1)] - private bool fAllowPathMaskCaching; - [MarshalAs(UnmanagedType.I1)] - private bool fRequireDecodeDisableForSRGB; - [MarshalAs(UnmanagedType.I1)] - private bool fDisableGpuYUVConversion; - [MarshalAs(UnmanagedType.I1)] - private bool fSuppressPathRendering; + private byte fUseShaderSwizzling; + private byte fDoManualMipmapping; + private byte fEnableInstancedRendering; + private byte fAllowPathMaskCaching; + private byte fRequireDecodeDisableForSRGB; + private byte fDisableGpuYUVConversion; + private byte fSuppressPathRendering; private GRContextOptionsGpuPathRenderers fGpuPathRenderers; - [MarshalAs(UnmanagedType.I1)] - private bool fAvoidStencilBuffers; + private byte fAvoidStencilBuffers; public bool SuppressPrints { - get { return fSuppressPrints; } - set { fSuppressPrints = value; } + get { return fSuppressPrints != 0; } + set { fSuppressPrints = value ? (byte)1 : (byte)0; } } public int MaxTextureSizeOverride { get { return fMaxTextureSizeOverride; } @@ -1927,20 +1929,20 @@ namespace SkiaSharp set { fMaxTileSizeOverride = value; } } public bool SuppressDualSourceBlending { - get { return fSuppressDualSourceBlending; } - set { fSuppressDualSourceBlending = value; } + get { return fSuppressDualSourceBlending != 0; } + set { fSuppressDualSourceBlending = value ? (byte)1 : (byte)0; } } public int BufferMapThreshold { get { return fBufferMapThreshold; } set { fBufferMapThreshold = value; } } public bool UseDrawInsteadOfPartialRenderTargetWrite { - get { return fUseDrawInsteadOfPartialRenderTargetWrite; } - set { fUseDrawInsteadOfPartialRenderTargetWrite = value; } + get { return fUseDrawInsteadOfPartialRenderTargetWrite != 0; } + set { fUseDrawInsteadOfPartialRenderTargetWrite = value ? (byte)1 : (byte)0; } } public bool ImmediateMode { - get { return fImmediateMode; } - set { fImmediateMode = value; } + get { return fImmediateMode != 0; } + set { fImmediateMode = value ? (byte)1 : (byte)0; } } public int MaxOpCombineLookback { get { return fMaxOpCombineLookback; } @@ -1951,63 +1953,63 @@ namespace SkiaSharp set { fMaxOpCombineLookahead = value; } } public bool UseShaderSwizzling { - get { return fUseShaderSwizzling; } - set { fUseShaderSwizzling = value; } + get { return fUseShaderSwizzling != 0; } + set { fUseShaderSwizzling = value ? (byte)1 : (byte)0; } } public bool DoManualMipmapping { - get { return fDoManualMipmapping; } - set { fDoManualMipmapping = value; } + get { return fDoManualMipmapping != 0; } + set { fDoManualMipmapping = value ? (byte)1 : (byte)0; } } public bool EnableInstancedRendering { - get { return fEnableInstancedRendering; } - set { fEnableInstancedRendering = value; } + get { return fEnableInstancedRendering != 0; } + set { fEnableInstancedRendering = value ? (byte)1 : (byte)0; } } public bool AllowPathMaskCaching { - get { return fAllowPathMaskCaching; } - set { fAllowPathMaskCaching = value; } + get { return fAllowPathMaskCaching != 0; } + set { fAllowPathMaskCaching = value ? (byte)1 : (byte)0; } } public bool RequireDecodeDisableForSrgb { - get { return fRequireDecodeDisableForSRGB; } - set { fRequireDecodeDisableForSRGB = value; } + get { return fRequireDecodeDisableForSRGB != 0; } + set { fRequireDecodeDisableForSRGB = value ? (byte)1 : (byte)0; } } public bool DisableGpuYuvConversion { - get { return fDisableGpuYUVConversion; } - set { fDisableGpuYUVConversion = value; } + get { return fDisableGpuYUVConversion != 0; } + set { fDisableGpuYUVConversion = value ? (byte)1 : (byte)0; } } public bool SuppressPathRendering { - get { return fSuppressPathRendering; } - set { fSuppressPathRendering = value; } + get { return fSuppressPathRendering != 0; } + set { fSuppressPathRendering = value ? (byte)1 : (byte)0; } } public GRContextOptionsGpuPathRenderers GpuPathRenderers { get { return fGpuPathRenderers; } set { fGpuPathRenderers = value; } } public bool AvoidStencilBuffers { - get { return fAvoidStencilBuffers; } - set { fAvoidStencilBuffers = value; } + get { return fAvoidStencilBuffers != 0; } + set { fAvoidStencilBuffers = value ? (byte)1 : (byte)0; } } public static GRContextOptions Default { get { return new GRContextOptions { - fSuppressPrints = false, + fSuppressPrints = 0, fMaxTextureSizeOverride = 0x7FFFFFFF, fMaxTileSizeOverride = 0, - fSuppressDualSourceBlending = false, + fSuppressDualSourceBlending = 0, fBufferMapThreshold = -1, - fUseDrawInsteadOfPartialRenderTargetWrite = false, - fImmediateMode = false, + fUseDrawInsteadOfPartialRenderTargetWrite = 0, + fImmediateMode = 0, fMaxOpCombineLookback = -1, fMaxOpCombineLookahead = -1, - fUseShaderSwizzling = false, - fDoManualMipmapping = false, - fEnableInstancedRendering = false, - fAllowPathMaskCaching = false, - fRequireDecodeDisableForSRGB = true, - fDisableGpuYUVConversion = false, - fSuppressPathRendering = false, + fUseShaderSwizzling = 0, + fDoManualMipmapping = 0, + fEnableInstancedRendering = 0, + fAllowPathMaskCaching = 0, + fRequireDecodeDisableForSRGB = 1, + fDisableGpuYUVConversion = 0, + fSuppressPathRendering = 0, fGpuPathRenderers = GRContextOptionsGpuPathRenderers.All, - fAvoidStencilBuffers = false, + fAvoidStencilBuffers = 0, }; } } @@ -2296,8 +2298,7 @@ namespace SkiaSharp [StructLayout(LayoutKind.Sequential)] public struct SKHighContrastConfig { - [MarshalAs (UnmanagedType.I1)] - private bool fGrayscale; + private byte fGrayscale; private SKHighContrastConfigInvertStyle fInvertStyle; private float fContrast; @@ -2310,14 +2311,14 @@ namespace SkiaSharp public SKHighContrastConfig (bool grayscale, SKHighContrastConfigInvertStyle invertStyle, float contrast) { - fGrayscale = grayscale; + fGrayscale = grayscale ? (byte)1 : (byte)0; fInvertStyle = invertStyle; fContrast = contrast; } public bool Grayscale { - get { return fGrayscale; } - set { fGrayscale = value; } + get { return fGrayscale != 0; } + set { fGrayscale = value ? (byte)1 : (byte)0; } } public SKHighContrastConfigInvertStyle InvertStyle { get { return fInvertStyle; } diff --git a/binding/Binding/SKCodec.cs b/binding/Binding/SKCodec.cs index 092dc127..6e8c71f8 100644 --- a/binding/Binding/SKCodec.cs +++ b/binding/Binding/SKCodec.cs @@ -131,17 +131,7 @@ namespace SkiaSharp if (pixels == IntPtr.Zero) throw new ArgumentNullException (nameof (pixels)); - var nativeOptions = new SKCodecOptionsInternal { - fZeroInitialized = options.ZeroInitialized, - fSubset = null, - fFrameIndex = (IntPtr) options.FrameIndex, - fHasPriorFrame = options.HasPriorFrame, - fPremulBehavior = options.PremulBehavior, - }; - if (options.HasSubset) { - var subset = options.Subset.Value; - nativeOptions.fSubset = ⊂ - } + var nativeOptions = SKCodecOptionsInternal.FromManaged (ref options); var cinfo = SKImageInfoNative.FromManaged (ref info); return SkiaApi.sk_codec_get_pixels (Handle, ref cinfo, pixels, (IntPtr)rowBytes, ref nativeOptions, colorTable, ref colorTableCount); } @@ -188,17 +178,7 @@ namespace SkiaSharp if (pixels == IntPtr.Zero) throw new ArgumentNullException (nameof (pixels)); - var nativeOptions = new SKCodecOptionsInternal { - fZeroInitialized = options.ZeroInitialized, - fSubset = null, - fFrameIndex = (IntPtr) options.FrameIndex, - fHasPriorFrame = options.HasPriorFrame, - fPremulBehavior = options.PremulBehavior, - }; - if (options.HasSubset) { - var subset = options.Subset.Value; - nativeOptions.fSubset = ⊂ - } + var nativeOptions = SKCodecOptionsInternal.FromManaged (ref options); var cinfo = SKImageInfoNative.FromManaged (ref info); return SkiaApi.sk_codec_start_incremental_decode (Handle, ref cinfo, pixels, (IntPtr)rowBytes, ref nativeOptions, colorTable, ref colorTableCount); } @@ -233,17 +213,7 @@ namespace SkiaSharp public unsafe SKCodecResult StartScanlineDecode (SKImageInfo info, SKCodecOptions options, IntPtr colorTable, ref int colorTableCount) { - var nativeOptions = new SKCodecOptionsInternal { - fZeroInitialized = options.ZeroInitialized, - fSubset = null, - fFrameIndex = (IntPtr) options.FrameIndex, - fHasPriorFrame = options.HasPriorFrame, - fPremulBehavior = options.PremulBehavior, - }; - if (options.HasSubset) { - var subset = options.Subset.Value; - nativeOptions.fSubset = ⊂ - } + var nativeOptions = SKCodecOptionsInternal.FromManaged (ref options); var cinfo = SKImageInfoNative.FromManaged (ref info); return SkiaApi.sk_codec_start_scanline_decode (Handle, ref cinfo, ref nativeOptions, colorTable, ref colorTableCount); } diff --git a/binding/Binding/SkiaApi.cs b/binding/Binding/SkiaApi.cs index a4747afb..9fc0a45a 100755 --- a/binding/Binding/SkiaApi.cs +++ b/binding/Binding/SkiaApi.cs @@ -158,9 +158,9 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_surface_t sk_surface_new_backend_texture_as_render_target (gr_context_t context, ref GRBackendTextureDesc desc, IntPtr propsZero); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static sk_surface_t sk_surface_new_render_target (gr_context_t context, bool budgeted, ref SKImageInfoNative info, int sampleCount, ref SKSurfaceProps props); + public extern static sk_surface_t sk_surface_new_render_target (gr_context_t context, [MarshalAs(UnmanagedType.I1)] bool budgeted, ref SKImageInfoNative info, int sampleCount, ref SKSurfaceProps props); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static sk_surface_t sk_surface_new_render_target (gr_context_t context, bool budgeted, ref SKImageInfoNative info, int sampleCount, IntPtr propsZero); + public extern static sk_surface_t sk_surface_new_render_target (gr_context_t context, [MarshalAs(UnmanagedType.I1)] bool budgeted, ref SKImageInfoNative info, int sampleCount, IntPtr propsZero); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_surface_draw(sk_surface_t surface, sk_canvas_t canvas, float x, float y, sk_paint_t paint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -276,9 +276,9 @@ namespace SkiaSharp public extern static void sk_canvas_draw_link_destination_annotation(sk_canvas_t t, ref SKRect rect, sk_data_t value); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_canvas_clip_rect_with_operation(sk_canvas_t t, ref SKRect crect, SKClipOperation op, bool doAA); + public extern static void sk_canvas_clip_rect_with_operation(sk_canvas_t t, ref SKRect crect, SKClipOperation op, [MarshalAs(UnmanagedType.I1)] bool doAA); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_canvas_clip_path_with_operation(sk_canvas_t t, sk_path_t cpath, SKClipOperation op, bool doAA); + public extern static void sk_canvas_clip_path_with_operation(sk_canvas_t t, sk_path_t cpath, SKClipOperation op, [MarshalAs(UnmanagedType.I1)] bool doAA); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_canvas_clip_region(sk_canvas_t t, sk_region_t region, SKClipOperation op); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -310,17 +310,17 @@ namespace SkiaSharp [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_antialias(sk_paint_t t); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_antialias(sk_paint_t t, bool v); + public extern static void sk_paint_set_antialias(sk_paint_t t, [MarshalAs(UnmanagedType.I1)] bool v); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_dither(sk_paint_t t); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_dither(sk_paint_t t, bool v); + public extern static void sk_paint_set_dither(sk_paint_t t, [MarshalAs(UnmanagedType.I1)] bool v); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_verticaltext(sk_paint_t t); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_verticaltext(sk_paint_t t, bool v); + public extern static void sk_paint_set_verticaltext(sk_paint_t t, [MarshalAs(UnmanagedType.I1)] bool v); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_color_t sk_paint_get_color(sk_paint_t t); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -432,27 +432,27 @@ namespace SkiaSharp [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_linear_text(sk_paint_t cpaint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_linear_text(sk_paint_t cpaint, bool linearText); + public extern static void sk_paint_set_linear_text(sk_paint_t cpaint, [MarshalAs(UnmanagedType.I1)] bool linearText); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_subpixel_text(sk_paint_t cpaint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_subpixel_text(sk_paint_t cpaint, bool subpixelText); + public extern static void sk_paint_set_subpixel_text(sk_paint_t cpaint, [MarshalAs(UnmanagedType.I1)] bool subpixelText); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_lcd_render_text(sk_paint_t cpaint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_lcd_render_text(sk_paint_t cpaint, bool lcdText); + public extern static void sk_paint_set_lcd_render_text(sk_paint_t cpaint, [MarshalAs(UnmanagedType.I1)] bool lcdText); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_embedded_bitmap_text(sk_paint_t cpaint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_embedded_bitmap_text(sk_paint_t cpaint, bool useEmbeddedBitmapText); + public extern static void sk_paint_set_embedded_bitmap_text(sk_paint_t cpaint, [MarshalAs(UnmanagedType.I1)] bool useEmbeddedBitmapText); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_autohinted(sk_paint_t cpaint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_autohinted(sk_paint_t cpaint, bool useAutohinter); + public extern static void sk_paint_set_autohinted(sk_paint_t cpaint, [MarshalAs(UnmanagedType.I1)] bool useAutohinter); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static SKPaintHinting sk_paint_get_hinting(sk_paint_t cpaint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -461,12 +461,12 @@ namespace SkiaSharp [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_fake_bold_text(sk_paint_t cpaint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_fake_bold_text(sk_paint_t cpaint, bool fakeBoldText); + public extern static void sk_paint_set_fake_bold_text(sk_paint_t cpaint, [MarshalAs(UnmanagedType.I1)] bool fakeBoldText); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_is_dev_kern_text(sk_paint_t cpaint); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_paint_set_dev_kern_text(sk_paint_t cpaint, bool devKernText); + public extern static void sk_paint_set_dev_kern_text(sk_paint_t cpaint, [MarshalAs(UnmanagedType.I1)] bool devKernText); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_paint_get_fill_path(sk_paint_t paint, sk_path_t src, sk_path_t dst, ref SKRect cullRect, float resScale); @@ -619,7 +619,7 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_path_rarc_to (sk_path_t t, float rx, float ry, float xAxisRotate, SKPathArcSize largeArc, SKPathDirection sweep, float x, float y); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_path_arc_to_with_oval (sk_path_t t, ref SKRect oval, float startAngle, float sweepAngle, bool forceMoveTo); + public extern static void sk_path_arc_to_with_oval (sk_path_t t, ref SKRect oval, float startAngle, float sweepAngle, [MarshalAs(UnmanagedType.I1)] bool forceMoveTo); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_path_arc_to_with_points (sk_path_t t, float x1, float y1, float x2, float y2, float radius); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -646,7 +646,7 @@ namespace SkiaSharp [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static int sk_path_convert_conic_to_quads(ref SKPoint p0, ref SKPoint p1, ref SKPoint p2, float w, [Out] SKPoint[] pts, int pow2); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_path_add_poly (sk_path_t cpath, [In] SKPoint[] points, int count, bool close); + public extern static void sk_path_add_poly (sk_path_t cpath, [In] SKPoint[] points, int count, [MarshalAs(UnmanagedType.I1)] bool close); [DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static SKPathSegmentMask sk_path_get_segment_masks (sk_path_t t); @@ -654,11 +654,11 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_pathmeasure_t sk_pathmeasure_new(); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static sk_pathmeasure_t sk_pathmeasure_new_with_path(sk_path_t path, bool forceClosed, float resScale); + public extern static sk_pathmeasure_t sk_pathmeasure_new_with_path(sk_path_t path, [MarshalAs(UnmanagedType.I1)]bool forceClosed, float resScale); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_pathmeasure_destroy(sk_pathmeasure_t pathMeasure); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_pathmeasure_set_path(sk_pathmeasure_t pathMeasure, sk_path_t path, bool forceClosed); + public extern static void sk_pathmeasure_set_path(sk_pathmeasure_t pathMeasure, sk_path_t path, [MarshalAs(UnmanagedType.I1)] bool forceClosed); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static float sk_pathmeasure_get_length(sk_pathmeasure_t pathMeasure); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -675,7 +675,7 @@ namespace SkiaSharp public extern static bool sk_pathmeasure_get_matrix(sk_pathmeasure_t pathMeasure, float distance, out SKMatrix matrix, SKPathMeasureMatrixFlags flags); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] - public extern static bool sk_pathmeasure_get_segment(sk_pathmeasure_t pathMeasure, float start, float stop, sk_path_t dst, bool startWithMoveTo); + public extern static bool sk_pathmeasure_get_segment(sk_pathmeasure_t pathMeasure, float start, float stop, sk_path_t dst, [MarshalAs(UnmanagedType.I1)] bool startWithMoveTo); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_pathmeasure_is_closed(sk_pathmeasure_t pathMeasure); @@ -789,7 +789,7 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_imagefilter_t sk_imagefilter_new_magnifier(ref SKRect src, float inset, sk_imagefilter_t input /*NULL*/, sk_imagefilter_croprect_t cropRect /*NULL*/); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static sk_imagefilter_t sk_imagefilter_new_matrix_convolution(ref SKSizeI kernelSize, float[] kernel, float gain, float bias, ref SKPointI kernelOffset, SKMatrixConvolutionTileMode tileMode, bool convolveAlpha, sk_imagefilter_t input /*NULL*/, sk_imagefilter_croprect_t cropRect /*NULL*/); + public extern static sk_imagefilter_t sk_imagefilter_new_matrix_convolution(ref SKSizeI kernelSize, float[] kernel, float gain, float bias, ref SKPointI kernelOffset, SKMatrixConvolutionTileMode tileMode, [MarshalAs(UnmanagedType.I1)] bool convolveAlpha, sk_imagefilter_t input /*NULL*/, sk_imagefilter_croprect_t cropRect /*NULL*/); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_imagefilter_t sk_imagefilter_new_merge(sk_imagefilter_t[] filters, int count, SKBlendMode[] modes /*NULL*/, sk_imagefilter_croprect_t cropRect /*NULL*/); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -809,7 +809,7 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_imagefilter_t sk_imagefilter_new_xfermode(SKBlendMode mode, sk_imagefilter_t background, sk_imagefilter_t foreground /*NULL*/, sk_imagefilter_croprect_t cropRect /*NULL*/); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static 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 /*NULL*/, sk_imagefilter_croprect_t cropRect /*NULL*/); + public extern static sk_imagefilter_t sk_imagefilter_new_arithmetic(float k1, float k2, float k3, float k4, [MarshalAs(UnmanagedType.I1)] bool enforcePMColor, sk_imagefilter_t background, sk_imagefilter_t foreground /*NULL*/, sk_imagefilter_croprect_t cropRect /*NULL*/); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_imagefilter_t sk_imagefilter_new_image_source(sk_image_t image, ref SKRect srcRect, ref SKRect dstRect, SKFilterQuality filterQuality); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -852,7 +852,7 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_data_t sk_data_new_subset(sk_data_t src, IntPtr offset, IntPtr length); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static sk_data_t sk_data_new_from_file(string path); + public extern static sk_data_t sk_data_new_from_file([MarshalAs(UnmanagedType.LPStr)] string path); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_data_t sk_data_new_from_stream(sk_stream_t stream, IntPtr length); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -1073,15 +1073,15 @@ namespace SkiaSharp [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_stream_memorystream_t sk_memorystream_new_with_length(IntPtr length); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static sk_stream_memorystream_t sk_memorystream_new_with_data(IntPtr data, IntPtr length, bool copyData); + public extern static sk_stream_memorystream_t sk_memorystream_new_with_data(IntPtr data, IntPtr length, [MarshalAs(UnmanagedType.I1)] bool copyData); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static sk_stream_memorystream_t sk_memorystream_new_with_data(byte[] data, IntPtr length, bool copyData); + public extern static sk_stream_memorystream_t sk_memorystream_new_with_data(byte[] data, IntPtr length, [MarshalAs(UnmanagedType.I1)] bool copyData); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static sk_stream_memorystream_t sk_memorystream_new_with_skdata(IntPtr data); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_memorystream_set_memory(sk_stream_memorystream_t s, IntPtr data, IntPtr length, bool copyData); + public extern static void sk_memorystream_set_memory(sk_stream_memorystream_t s, IntPtr data, IntPtr length, [MarshalAs(UnmanagedType.I1)] bool copyData); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_memorystream_set_memory(sk_stream_memorystream_t s, byte[] data, IntPtr length, bool copyData); + public extern static void sk_memorystream_set_memory(sk_stream_memorystream_t s, byte[] data, IntPtr length, [MarshalAs(UnmanagedType.I1)] bool copyData); // Managed streams [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] @@ -1154,7 +1154,7 @@ namespace SkiaSharp public extern static bool sk_wstream_write_scalar_as_text(sk_wstream_t cstream, float value); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] - public extern static bool sk_wstream_write_bool(sk_wstream_t cstream, bool value); + public extern static bool sk_wstream_write_bool(sk_wstream_t cstream, [MarshalAs(UnmanagedType.I1)] bool value); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_wstream_write_scalar(sk_wstream_t cstream, float value); @@ -1278,7 +1278,7 @@ namespace SkiaSharp [return: MarshalAs(UnmanagedType.I1)] public extern static bool sk_bitmap_is_volatile(sk_bitmap_t b); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] - public extern static void sk_bitmap_set_volatile(sk_bitmap_t b, bool value); + public extern static void sk_bitmap_set_volatile(sk_bitmap_t b, [MarshalAs(UnmanagedType.I1)] bool value); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] public extern static void sk_bitmap_erase(sk_bitmap_t cbitmap, SKColor color); [DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)] diff --git a/tests/Tests/SKApiTests.cs b/tests/Tests/SKApiTests.cs new file mode 100644 index 00000000..85295814 --- /dev/null +++ b/tests/Tests/SKApiTests.cs @@ -0,0 +1,88 @@ +using System; +using System.IO; +using System.Reflection; +using System.Linq; +using NUnit.Framework; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +namespace SkiaSharp.Tests +{ + public class SKApiTest : SKTest + { + private static IEnumerable GetApi() + { + var ass = typeof(SKImageInfo).GetTypeInfo().Assembly; + var api = ass.GetType("SkiaSharp.SkiaApi").GetMethods().Where(a => a.GetCustomAttribute() != null); + return api; + } + + [Test] + public void ApiTypesAreMarshalledCorrectly() + { + var api = GetApi(); + + foreach (var method in api) + { + foreach (var param in method.GetParameters()) + { + var paramType = param.ParameterType; + + if (paramType == typeof(bool)) + { + //check string + var marshal = param.GetCustomAttribute(); + Assert.NotNull(marshal, $"{method.Name}({paramType})"); + Assert.AreEqual(UnmanagedType.I1, marshal.Value, $"{method.Name}({paramType})"); + } + if (paramType == typeof(string)) + { + //check string + var marshal = param.GetCustomAttribute(); + Assert.NotNull(marshal, $"{method.Name}({paramType})"); + Assert.AreEqual(UnmanagedType.LPStr, marshal.Value, $"{method.Name}({paramType})"); + } + else if (paramType == typeof(string[])) + { + // check array of strings + var marshal = param.GetCustomAttribute(); + Assert.NotNull(marshal, $"{method.Name}({paramType})"); + Assert.AreEqual(UnmanagedType.LPArray, marshal.Value, $"{method.Name}({paramType})"); + Assert.AreEqual(UnmanagedType.LPStr, marshal.ArraySubType, $"{method.Name}({paramType})"); + } + else + { + if (param.ParameterType.IsByRef || param.ParameterType.IsArray) + { + paramType = param.ParameterType.GetElementType(); + } + + // make sure only structs + Assert.False(paramType.GetTypeInfo().IsClass, $"{method.Name}({paramType})"); + + // make sure our structs have a layout type + if (!paramType.GetTypeInfo().IsEnum && paramType.Namespace == "SkiaSharp") + { + // check blittable + try + { + GCHandle.Alloc(Activator.CreateInstance(paramType), GCHandleType.Pinned).Free(); + } + catch + { + Assert.Fail($"not blittable : {method.Name}({paramType})"); + } + } + } + } + + if (method.ReturnParameter.ParameterType == typeof(bool)) + { + var marshal = method.ReturnParameter.GetCustomAttribute(); + Assert.NotNull(marshal, $"{method.Name}(return)"); + Assert.AreEqual(UnmanagedType.I1, marshal.Value, $"{method.Name}(return)"); + } + } + } + } +} diff --git a/tests/Tests/SKDataTest.cs b/tests/Tests/SKDataTest.cs index bc5e78e5..a4e36477 100644 --- a/tests/Tests/SKDataTest.cs +++ b/tests/Tests/SKDataTest.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.InteropServices; using NUnit.Framework; +using System.IO; namespace SkiaSharp.Tests { @@ -17,6 +18,15 @@ namespace SkiaSharp.Tests Assert.AreEqual(OddData, data.ToArray()); } + [Test] + public void DataCanBeCreatedFromFile() + { + var data = SKData.Create(Path.Combine(PathToImages, "baboon.jpg")); + + Assert.NotNull(data); + Assert.True(data.Size > 0); + } + [Test] public void ReleaseDataWasInvoked() { diff --git a/tests/Tests/SKPixmapTests.cs b/tests/Tests/SKPixmapTest.cs similarity index 100% rename from tests/Tests/SKPixmapTests.cs rename to tests/Tests/SKPixmapTest.cs