This commit is contained in:
Matthew Leibowitz 2024-04-15 23:50:36 +02:00 коммит произвёл GitHub
Родитель a0f3767c96
Коммит aa4f2ffedb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
18 изменённых файлов: 567 добавлений и 2 удалений

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

@ -18,6 +18,7 @@ using gr_vk_extensions_t = System.IntPtr;
using gr_vk_memory_allocator_t = System.IntPtr;
using gr_vkinterface_t = System.IntPtr;
using sk_bitmap_t = System.IntPtr;
using sk_blender_t = System.IntPtr;
using sk_canvas_t = System.IntPtr;
using sk_codec_t = System.IntPtr;
using sk_colorfilter_t = System.IntPtr;

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

@ -18,6 +18,7 @@ using gr_vk_extensions_t = System.IntPtr;
using gr_vk_memory_allocator_t = System.IntPtr;
using gr_vkinterface_t = System.IntPtr;
using sk_bitmap_t = System.IntPtr;
using sk_blender_t = System.IntPtr;
using sk_canvas_t = System.IntPtr;
using sk_codec_t = System.IntPtr;
using sk_colorfilter_t = System.IntPtr;

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

@ -18,6 +18,7 @@ using gr_vk_extensions_t = System.IntPtr;
using gr_vk_memory_allocator_t = System.IntPtr;
using gr_vkinterface_t = System.IntPtr;
using sk_bitmap_t = System.IntPtr;
using sk_blender_t = System.IntPtr;
using sk_canvas_t = System.IntPtr;
using sk_codec_t = System.IntPtr;
using sk_colorfilter_t = System.IntPtr;

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

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
namespace SkiaSharp;
public unsafe class SKBlender : SKObject, ISKReferenceCounted
{
private static readonly Dictionary<SKBlendMode, SKBlender> blendModeBlenders;
static SKBlender ()
{
// TODO: This is not the best way to do this as it will create a lot of objects that
// might not be needed, but it is the only way to ensure that the static
// instances are created before any access is made to them.
// See more info: SKObject.EnsureStaticInstanceAreInitialized()
var modes = Enum.GetValues (typeof (SKBlendMode));
blendModeBlenders = new Dictionary<SKBlendMode, SKBlender> (modes.Length);
foreach (SKBlendMode mode in modes)
{
blendModeBlenders [mode] = new SKBlenderStatic (SkiaApi.sk_blender_new_mode (mode));
}
}
internal static void EnsureStaticInstanceAreInitialized ()
{
// IMPORTANT: do not remove to ensure that the static instances
// are initialized before any access is made to them
}
internal SKBlender(IntPtr handle, bool owns)
: base (handle, owns)
{
}
protected override void Dispose (bool disposing) =>
base.Dispose (disposing);
public static SKBlender CreateBlendMode (SKBlendMode mode)
{
if (!blendModeBlenders.TryGetValue (mode, out var value))
throw new ArgumentOutOfRangeException (nameof (mode));
return value;
}
public static SKBlender CreateArithmetic (float k1, float k2, float k3, float k4, bool enforcePMColor) =>
GetObject (SkiaApi.sk_blender_new_arithmetic (k1, k2, k3, k4, enforcePMColor));
internal static SKBlender GetObject (IntPtr handle) =>
GetOrAddObject (handle, (h, o) => new SKBlender (h, o));
//
private sealed class SKBlenderStatic : SKBlender
{
internal SKBlenderStatic (IntPtr x)
: base (x, false)
{
}
protected override void Dispose (bool disposing) { }
}
}

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

@ -12,6 +12,11 @@ namespace SkiaSharp
static SKColorSpace ()
{
// TODO: This is not the best way to do this as it will create a lot of objects that
// might not be needed, but it is the only way to ensure that the static
// instances are created before any access is made to them.
// See more info: SKObject.EnsureStaticInstanceAreInitialized()
srgb = new SKColorSpaceStatic (SkiaApi.sk_colorspace_new_srgb ());
srgbLinear = new SKColorSpaceStatic (SkiaApi.sk_colorspace_new_srgb_linear ());
}

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

@ -19,6 +19,11 @@ namespace SkiaSharp
static SKData ()
{
// TODO: This is not the best way to do this as it will create a lot of objects that
// might not be needed, but it is the only way to ensure that the static
// instances are created before any access is made to them.
// See more info: SKObject.EnsureStaticInstanceAreInitialized()
empty = new SKDataStatic (SkiaApi.sk_data_new_empty ());
}

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

@ -14,6 +14,11 @@ namespace SkiaSharp
static SKFontManager ()
{
// TODO: This is not the best way to do this as it will create a lot of objects that
// might not be needed, but it is the only way to ensure that the static
// instances are created before any access is made to them.
// See more info: SKObject.EnsureStaticInstanceAreInitialized()
defaultManager = new SKFontManagerStatic (SkiaApi.sk_fontmgr_ref_default ());
}

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

@ -341,6 +341,23 @@ namespace SkiaSharp
private static SKImageFilter CreateBlendMode (SKBlendMode mode, SKImageFilter? background, SKImageFilter? foreground, SKRect* cropRect) =>
GetObject (SkiaApi.sk_imagefilter_new_blend (mode, background?.Handle ?? IntPtr.Zero, foreground?.Handle ?? IntPtr.Zero, cropRect));
// CreateBlendMode (Blender)
public static SKImageFilter CreateBlendMode (SKBlender blender, SKImageFilter? background) =>
CreateBlendMode (blender, background, null, null);
public static SKImageFilter CreateBlendMode (SKBlender blender, SKImageFilter? background, SKImageFilter? foreground) =>
CreateBlendMode (blender, background, foreground, null);
public static SKImageFilter CreateBlendMode (SKBlender blender, SKImageFilter? background, SKImageFilter? foreground, SKRect cropRect) =>
CreateBlendMode (blender, background, foreground, &cropRect);
private static SKImageFilter CreateBlendMode (SKBlender blender, SKImageFilter? background, SKImageFilter? foreground, SKRect* cropRect)
{
_ = blender ?? throw new ArgumentNullException (nameof (blender));
return GetObject (SkiaApi.sk_imagefilter_new_blender (blender.Handle, background?.Handle ?? IntPtr.Zero, foreground?.Handle ?? IntPtr.Zero, cropRect));
}
// CreateArithmetic
public static SKImageFilter CreateArithmetic (float k1, float k2, float k3, float k4, bool enforcePMColor, SKImageFilter? background) =>

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

@ -44,6 +44,7 @@ namespace SkiaSharp
SKData.EnsureStaticInstanceAreInitialized ();
SKFontManager.EnsureStaticInstanceAreInitialized ();
SKTypeface.EnsureStaticInstanceAreInitialized ();
SKBlender.EnsureStaticInstanceAreInitialized ();
}
internal SKObject (IntPtr handle, bool owns)

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

@ -203,6 +203,11 @@ namespace SkiaSharp
set => SkiaApi.sk_paint_set_blendmode (Handle, value);
}
public SKBlender Blender {
get => SKBlender.GetObject (SkiaApi.sk_paint_get_blender (Handle));
set => SkiaApi.sk_paint_set_blender (Handle, value == null ? IntPtr.Zero : value.Handle);
}
[Obsolete ($"Use {nameof (SKSamplingOptions)} instead.")]
public SKFilterQuality FilterQuality {
get => (SKFilterQuality)SkiaApi.sk_compatpaint_get_filter_quality (Handle);

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

@ -41,6 +41,17 @@ namespace SkiaSharp
return effect;
}
public static SKRuntimeEffect CreateBlender (string sksl, out string errors)
{
using var s = new SKString (sksl);
using var errorString = new SKString ();
var effect = GetObject (SkiaApi.sk_runtimeeffect_make_for_blender (s.Handle, errorString.Handle));
errors = errorString?.ToString ();
if (errors?.Length == 0)
errors = null;
return effect;
}
// Build*
public static SKRuntimeShaderBuilder BuildShader (string sksl)
@ -57,6 +68,13 @@ namespace SkiaSharp
return new SKRuntimeColorFilterBuilder (effect);
}
public static SKRuntimeBlenderBuilder BuildBlender (string sksl)
{
var effect = CreateBlender (sksl, out var errors);
ValidateResult (effect, errors);
return new SKRuntimeBlenderBuilder (effect);
}
private static void ValidateResult (SKRuntimeEffect effect, string errors)
{
if (effect is null) {
@ -148,6 +166,30 @@ namespace SkiaSharp
}
}
// ToBlender
public SKBlender ToBlender () =>
ToBlender ((SKData)null, null);
public SKBlender ToBlender (SKRuntimeEffectUniforms uniforms) =>
ToBlender (uniforms.ToData (), null);
private SKBlender ToBlender (SKData uniforms) =>
ToBlender (uniforms, null);
public SKBlender ToBlender (SKRuntimeEffectUniforms uniforms, SKRuntimeEffectChildren children) =>
ToBlender (uniforms.ToData (), children.ToArray ());
private SKBlender ToBlender (SKData uniforms, SKObject[] children)
{
var uniformsHandle = uniforms?.Handle ?? IntPtr.Zero;
using var childrenHandles = Utils.RentHandlesArray (children, true);
fixed (IntPtr* ch = childrenHandles) {
return SKBlender.GetObject (SkiaApi.sk_runtimeeffect_make_blender (Handle, uniformsHandle, ch, (IntPtr)childrenHandles.Length));
}
}
//
internal static SKRuntimeEffect GetObject (IntPtr handle) =>
@ -560,15 +602,24 @@ namespace SkiaSharp
value = colorFilter;
}
public SKRuntimeEffectChild (SKBlender blender)
{
value = blender;
}
public SKObject Value => value;
public SKShader Shader => value as SKShader;
public SKColorFilter ColorFilter => value as SKColorFilter;
public SKBlender Blender => value as SKBlender;
public static implicit operator SKRuntimeEffectChild (SKShader shader) => new (shader);
public static implicit operator SKRuntimeEffectChild (SKColorFilter colorFilter) => new (colorFilter);
public static implicit operator SKRuntimeEffectChild (SKBlender blender) => new (blender);
}
public class SKRuntimeEffectBuilderException : ApplicationException
@ -627,4 +678,15 @@ namespace SkiaSharp
public SKColorFilter Build () =>
Effect.ToColorFilter (Uniforms, Children);
}
public class SKRuntimeBlenderBuilder : SKRuntimeEffectBuilder
{
public SKRuntimeBlenderBuilder (SKRuntimeEffect effect)
: base (effect)
{
}
public SKBlender Build () =>
Effect.ToBlender (Uniforms, Children);
}
}

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

@ -408,6 +408,23 @@ namespace SkiaSharp
return GetObject (SkiaApi.sk_shader_new_blend (mode, shaderA.Handle, shaderB.Handle));
}
// CreateBlend
public static SKShader CreateBlend (SKBlendMode mode, SKShader shaderA, SKShader shaderB)
{
_ = shaderA ?? throw new ArgumentNullException (nameof (shaderA));
_ = shaderB ?? throw new ArgumentNullException (nameof (shaderB));
return GetObject (SkiaApi.sk_shader_new_blend (mode, shaderA.Handle, shaderB.Handle));
}
public static SKShader CreateBlend (SKBlender blender, SKShader shaderA, SKShader shaderB)
{
_ = shaderA ?? throw new ArgumentNullException (nameof (shaderA));
_ = shaderB ?? throw new ArgumentNullException (nameof (shaderB));
_ = blender ?? throw new ArgumentNullException (nameof (blender));
return GetObject (SkiaApi.sk_shader_new_blender (blender.Handle, shaderA.Handle, shaderB.Handle));
}
// CreateColorFilter
public static SKShader CreateColorFilter (SKShader shader, SKColorFilter filter)

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

@ -14,6 +14,11 @@ namespace SkiaSharp
static SKTypeface ()
{
// TODO: This is not the best way to do this as it will create a lot of objects that
// might not be needed, but it is the only way to ensure that the static
// instances are created before any access is made to them.
// See more info: SKObject.EnsureStaticInstanceAreInitialized()
defaultTypeface = new SKTypefaceStatic (SkiaApi.sk_typeface_ref_default ());
}

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

@ -17,6 +17,7 @@ using gr_vk_extensions_t = System.IntPtr;
using gr_vk_memory_allocator_t = System.IntPtr;
using gr_vkinterface_t = System.IntPtr;
using sk_bitmap_t = System.IntPtr;
using sk_blender_t = System.IntPtr;
using sk_canvas_t = System.IntPtr;
using sk_codec_t = System.IntPtr;
using sk_colorfilter_t = System.IntPtr;
@ -1414,6 +1415,66 @@ namespace SkiaSharp
#endregion
#region sk_blender.h
// sk_blender_t* sk_blender_new_arithmetic(float k1, float k2, float k3, float k4, bool enforcePremul)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern sk_blender_t sk_blender_new_arithmetic (Single k1, Single k2, Single k3, Single k4, [MarshalAs (UnmanagedType.I1)] bool enforcePremul);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate sk_blender_t sk_blender_new_arithmetic (Single k1, Single k2, Single k3, Single k4, [MarshalAs (UnmanagedType.I1)] bool enforcePremul);
}
private static Delegates.sk_blender_new_arithmetic sk_blender_new_arithmetic_delegate;
internal static sk_blender_t sk_blender_new_arithmetic (Single k1, Single k2, Single k3, Single k4, [MarshalAs (UnmanagedType.I1)] bool enforcePremul) =>
(sk_blender_new_arithmetic_delegate ??= GetSymbol<Delegates.sk_blender_new_arithmetic> ("sk_blender_new_arithmetic")).Invoke (k1, k2, k3, k4, enforcePremul);
#endif
// sk_blender_t* sk_blender_new_mode(sk_blendmode_t mode)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern sk_blender_t sk_blender_new_mode (SKBlendMode mode);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate sk_blender_t sk_blender_new_mode (SKBlendMode mode);
}
private static Delegates.sk_blender_new_mode sk_blender_new_mode_delegate;
internal static sk_blender_t sk_blender_new_mode (SKBlendMode mode) =>
(sk_blender_new_mode_delegate ??= GetSymbol<Delegates.sk_blender_new_mode> ("sk_blender_new_mode")).Invoke (mode);
#endif
// void sk_blender_ref(sk_blender_t* blender)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern void sk_blender_ref (sk_blender_t blender);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate void sk_blender_ref (sk_blender_t blender);
}
private static Delegates.sk_blender_ref sk_blender_ref_delegate;
internal static void sk_blender_ref (sk_blender_t blender) =>
(sk_blender_ref_delegate ??= GetSymbol<Delegates.sk_blender_ref> ("sk_blender_ref")).Invoke (blender);
#endif
// void sk_blender_unref(sk_blender_t* blender)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern void sk_blender_unref (sk_blender_t blender);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate void sk_blender_unref (sk_blender_t blender);
}
private static Delegates.sk_blender_unref sk_blender_unref_delegate;
internal static void sk_blender_unref (sk_blender_t blender) =>
(sk_blender_unref_delegate ??= GetSymbol<Delegates.sk_blender_unref> ("sk_blender_unref")).Invoke (blender);
#endif
#endregion
#region sk_canvas.h
// void sk_canvas_clear(sk_canvas_t* ccanvas, sk_color_t color)
@ -5326,6 +5387,20 @@ namespace SkiaSharp
(sk_imagefilter_new_blend_delegate ??= GetSymbol<Delegates.sk_imagefilter_new_blend> ("sk_imagefilter_new_blend")).Invoke (mode, background, foreground, cropRect);
#endif
// sk_imagefilter_t* sk_imagefilter_new_blender(sk_blender_t* blender, const sk_imagefilter_t* background, const sk_imagefilter_t* foreground, const sk_rect_t* cropRect)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern sk_imagefilter_t sk_imagefilter_new_blender (sk_blender_t blender, sk_imagefilter_t background, sk_imagefilter_t foreground, SKRect* cropRect);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate sk_imagefilter_t sk_imagefilter_new_blender (sk_blender_t blender, sk_imagefilter_t background, sk_imagefilter_t foreground, SKRect* cropRect);
}
private static Delegates.sk_imagefilter_new_blender sk_imagefilter_new_blender_delegate;
internal static sk_imagefilter_t sk_imagefilter_new_blender (sk_blender_t blender, sk_imagefilter_t background, sk_imagefilter_t foreground, SKRect* cropRect) =>
(sk_imagefilter_new_blender_delegate ??= GetSymbol<Delegates.sk_imagefilter_new_blender> ("sk_imagefilter_new_blender")).Invoke (blender, background, foreground, cropRect);
#endif
// sk_imagefilter_t* sk_imagefilter_new_blur(float sigmaX, float sigmaY, sk_shader_tilemode_t tileMode, const sk_imagefilter_t* input, const sk_rect_t* cropRect)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@ -5706,6 +5781,24 @@ namespace SkiaSharp
#endregion
#region sk_linker.h
// void sk_linker_keep_alive()
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern void sk_linker_keep_alive ();
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate void sk_linker_keep_alive ();
}
private static Delegates.sk_linker_keep_alive sk_linker_keep_alive_delegate;
internal static void sk_linker_keep_alive () =>
(sk_linker_keep_alive_delegate ??= GetSymbol<Delegates.sk_linker_keep_alive> ("sk_linker_keep_alive")).Invoke ();
#endif
#endregion
#region sk_maskfilter.h
// sk_maskfilter_t* sk_maskfilter_new_blur(sk_blurstyle_t, float sigma)
@ -5998,6 +6091,20 @@ namespace SkiaSharp
(sk_paint_delete_delegate ??= GetSymbol<Delegates.sk_paint_delete> ("sk_paint_delete")).Invoke (param0);
#endif
// sk_blender_t* sk_paint_get_blender(sk_paint_t* cpaint)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern sk_blender_t sk_paint_get_blender (sk_paint_t cpaint);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate sk_blender_t sk_paint_get_blender (sk_paint_t cpaint);
}
private static Delegates.sk_paint_get_blender sk_paint_get_blender_delegate;
internal static sk_blender_t sk_paint_get_blender (sk_paint_t cpaint) =>
(sk_paint_get_blender_delegate ??= GetSymbol<Delegates.sk_paint_get_blender> ("sk_paint_get_blender")).Invoke (cpaint);
#endif
// sk_blendmode_t sk_paint_get_blendmode(sk_paint_t*)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@ -6270,6 +6377,20 @@ namespace SkiaSharp
(sk_paint_set_antialias_delegate ??= GetSymbol<Delegates.sk_paint_set_antialias> ("sk_paint_set_antialias")).Invoke (param0, param1);
#endif
// void sk_paint_set_blender(sk_paint_t* paint, sk_blender_t* blender)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern void sk_paint_set_blender (sk_paint_t paint, sk_blender_t blender);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate void sk_paint_set_blender (sk_paint_t paint, sk_blender_t blender);
}
private static Delegates.sk_paint_set_blender sk_paint_set_blender_delegate;
internal static void sk_paint_set_blender (sk_paint_t paint, sk_blender_t blender) =>
(sk_paint_set_blender_delegate ??= GetSymbol<Delegates.sk_paint_set_blender> ("sk_paint_set_blender")).Invoke (paint, blender);
#endif
// void sk_paint_set_blendmode(sk_paint_t*, sk_blendmode_t)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@ -9456,6 +9577,20 @@ namespace SkiaSharp
(sk_runtimeeffect_get_uniforms_size_delegate ??= GetSymbol<Delegates.sk_runtimeeffect_get_uniforms_size> ("sk_runtimeeffect_get_uniforms_size")).Invoke (effect);
#endif
// sk_blender_t* sk_runtimeeffect_make_blender(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern sk_blender_t sk_runtimeeffect_make_blender (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate sk_blender_t sk_runtimeeffect_make_blender (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount);
}
private static Delegates.sk_runtimeeffect_make_blender sk_runtimeeffect_make_blender_delegate;
internal static sk_blender_t sk_runtimeeffect_make_blender (sk_runtimeeffect_t effect, sk_data_t uniforms, sk_flattenable_t* children, /* size_t */ IntPtr childCount) =>
(sk_runtimeeffect_make_blender_delegate ??= GetSymbol<Delegates.sk_runtimeeffect_make_blender> ("sk_runtimeeffect_make_blender")).Invoke (effect, uniforms, children, childCount);
#endif
// sk_colorfilter_t* sk_runtimeeffect_make_color_filter(sk_runtimeeffect_t* effect, sk_data_t* uniforms, sk_flattenable_t** children, size_t childCount)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@ -9470,6 +9605,20 @@ namespace SkiaSharp
(sk_runtimeeffect_make_color_filter_delegate ??= GetSymbol<Delegates.sk_runtimeeffect_make_color_filter> ("sk_runtimeeffect_make_color_filter")).Invoke (effect, uniforms, children, childCount);
#endif
// sk_runtimeeffect_t* sk_runtimeeffect_make_for_blender(sk_string_t* sksl, sk_string_t* error)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern sk_runtimeeffect_t sk_runtimeeffect_make_for_blender (sk_string_t sksl, sk_string_t error);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate sk_runtimeeffect_t sk_runtimeeffect_make_for_blender (sk_string_t sksl, sk_string_t error);
}
private static Delegates.sk_runtimeeffect_make_for_blender sk_runtimeeffect_make_for_blender_delegate;
internal static sk_runtimeeffect_t sk_runtimeeffect_make_for_blender (sk_string_t sksl, sk_string_t error) =>
(sk_runtimeeffect_make_for_blender_delegate ??= GetSymbol<Delegates.sk_runtimeeffect_make_for_blender> ("sk_runtimeeffect_make_for_blender")).Invoke (sksl, error);
#endif
// sk_runtimeeffect_t* sk_runtimeeffect_make_for_color_filter(sk_string_t* sksl, sk_string_t* error)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
@ -9544,6 +9693,20 @@ namespace SkiaSharp
(sk_shader_new_blend_delegate ??= GetSymbol<Delegates.sk_shader_new_blend> ("sk_shader_new_blend")).Invoke (mode, dst, src);
#endif
// sk_shader_t* sk_shader_new_blender(sk_blender_t* blender, const sk_shader_t* dst, const sk_shader_t* src)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
internal static extern sk_shader_t sk_shader_new_blender (sk_blender_t blender, sk_shader_t dst, sk_shader_t src);
#else
private partial class Delegates {
[UnmanagedFunctionPointer (CallingConvention.Cdecl)]
internal delegate sk_shader_t sk_shader_new_blender (sk_blender_t blender, sk_shader_t dst, sk_shader_t src);
}
private static Delegates.sk_shader_new_blender sk_shader_new_blender_delegate;
internal static sk_shader_t sk_shader_new_blender (sk_blender_t blender, sk_shader_t dst, sk_shader_t src) =>
(sk_shader_new_blender_delegate ??= GetSymbol<Delegates.sk_shader_new_blender> ("sk_shader_new_blender")).Invoke (blender, dst, src);
#endif
// sk_shader_t* sk_shader_new_color(sk_color_t color)
#if !USE_DELEGATES
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]

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

@ -32,7 +32,7 @@ There are some small improvements in the initial release of 3.x, and many more w
* `SKPoint3` is now implicitly compatible with `System.Numerics.Vector3` in both directions.
* `SKPointI` is now implicitly cast to `System.Numerics.Vector3`.
* `SKRuntimeEffect` now works on both CPU and GPU:
* GPU is accelerated and support more targets: `SKColorFilter` and `SKShader` (there is also a new `SKBlender` that is not yet exposed in SkiaSharp).
* GPU is accelerated and support more targets: `SKColorFilter`, `SKShader` and the new `SKBlender`.
* CPU is NOT accelerated and may be very slow.
* `SKMatrix44` is now a high-performance struct that can be used on any `SKCanvas`.

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

@ -1 +1 @@
Subproject commit 8684edb4e68d2bbf0d56a600633f5d4c44a16a36
Subproject commit f1c2f7b4246141c6037820dc75d89496ac4aa8b3

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

@ -16,6 +16,7 @@ namespace SkiaSharp.Tests
"SkiaSharp.SKFontStyle+SKFontStyleStatic",
"SkiaSharp.SKTypeface+SKTypefaceStatic",
"SkiaSharp.SKColorSpace+SKColorSpaceStatic",
"SkiaSharp.SKBlender+SKBlenderStatic",
};
public GarbageCleanupFixture()

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

@ -0,0 +1,213 @@
using System;
using System.Collections.Generic;
using Xunit;
namespace SkiaSharp.Tests;
public class SKBlenderTest
{
[SkippableFact]
public void SameBlendModeReturnsSameBlenderInstance()
{
var blender1 = SKBlender.CreateBlendMode(SKBlendMode.Src);
var blender2 = SKBlender.CreateBlendMode(SKBlendMode.Src);
Assert.Same(blender1, blender2);
}
[SkippableFact]
public void BlendModeBlenderIsNotDisposed()
{
var blender = SKBlender.CreateBlendMode(SKBlendMode.Src);
Assert.True(SKObject.GetInstance<SKBlender>(blender.Handle, out _));
blender.Dispose();
Assert.True(SKObject.GetInstance<SKBlender>(blender.Handle, out _));
}
[SkippableFact]
public void ArithmeticBlendModeBlenderIsBlendModeBlender()
{
var blendmode = SKBlender.CreateBlendMode(SKBlendMode.Src);
var arithmetic = SKBlender.CreateArithmetic(0, 1, 0, 0, false);
Assert.Same(blendmode, arithmetic);
}
[SkippableFact]
public void InvalidBlendModeThrowsArgumentException()
{
Assert.Throws<ArgumentOutOfRangeException>(() => SKBlender.CreateBlendMode((SKBlendMode)100));
}
public abstract class SurfaceTestBase : SKTest
{
protected SKSurface Surface { get; set; }
protected SKImageInfo Info { get; set; }
protected abstract void CreateSurface(int width, int height);
[SkippableTheory]
[MemberData(nameof(GetAllBlendModes))]
public void BlenderMatchesBlendModeWhenUsingOpaqueColor(SKBlendMode mode)
{
var blendModeColor = GetColor(p => ApplyColor(p, false), p => ApplyBlendMode(p, mode));
var blenderColor = GetColor(p => ApplyColor(p, false), p => ApplyBlender(p, mode));
Assert.Equal(blendModeColor, blenderColor);
}
[SkippableTheory]
[MemberData(nameof(GetAllBlendModes))]
public void BlenderMatchesBlendModeWhenUsingransparentColor(SKBlendMode mode)
{
var blendModeColor = GetColor(p => ApplyColor(p, true), p => ApplyBlendMode(p, mode));
var blenderColor = GetColor(p => ApplyColor(p, true), p => ApplyBlender(p, mode));
Assert.Equal(blendModeColor, blenderColor);
}
[SkippableTheory]
[MemberData(nameof(GetAllBlendModes))]
public void BlenderMatchesBlendModeWhenUsingOpaqueShader(SKBlendMode mode)
{
var blendModeColor = GetColor(p => ApplyColorShader(p, false), p => ApplyBlendMode(p, mode));
var blenderColor = GetColor(p => ApplyColorShader(p, false), p => ApplyBlender(p, mode));
Assert.Equal(blendModeColor, blenderColor);
}
[SkippableTheory]
[MemberData(nameof(GetAllBlendModes))]
public void BlenderMatchesBlendModeWhenUsingransparentShader(SKBlendMode mode)
{
var blendModeColor = GetColor(p => ApplyColorShader(p, true), p => ApplyBlendMode(p, mode));
var blenderColor = GetColor(p => ApplyColorShader(p, true), p => ApplyBlender(p, mode));
Assert.Equal(blendModeColor, blenderColor);
}
private SKColor GetColor(Action<SKPaint> applyColor, Action<SKPaint> applyBlend)
{
// Draw a solid red pixel.
using var paint = new SKPaint
{
Shader = null,
Color = SKColors.Red,
Blender = null,
BlendMode = SKBlendMode.Src,
};
Surface.Canvas.DrawRect(SKRect.Create(1, 1), paint);
// Draw a blue pixel on top of it, using the passed-in blend mode.
applyColor(paint);
applyBlend(paint);
Surface.Canvas.DrawRect(SKRect.Create(1, 1), paint);
// Read the pixels out of the surface and into the bitmap.
using var bmp = new SKBitmap(new SKImageInfo(1, 1));
Surface.ReadPixels(bmp.Info, bmp.GetPixels(), bmp.RowBytes, 0, 0);
// Get the pixel color.
return bmp.GetPixel(0, 0);
}
private static void ApplyBlendMode(SKPaint paint, SKBlendMode mode) =>
paint.BlendMode = mode;
private static void ApplyBlender(SKPaint paint, SKBlendMode mode) =>
paint.Blender = GetRuntimeBlenderForBlendMode(mode);
private static void ApplyColor(SKPaint paint, bool useTransparent)
{
var alpha = GetAlpha(useTransparent);
paint.Color = new SKColor(0x00, 0x00, 0xFF, alpha);
}
private static void ApplyColorShader(SKPaint paint, bool useTransparent)
{
// Install a different color in the paint, to ensure we're using the shader
paint.Color = SKColors.Green;
var alpha = GetAlpha(useTransparent);
paint.Shader = SKShader.CreateColor(new SKColor(0x00, 0x00, 0xFF, alpha));
}
private static byte GetAlpha(bool useTransparent) =>
useTransparent ? (byte)0x80 : (byte)0xFF;
public static IEnumerable<object[]> GetAllBlendModes()
{
foreach (SKBlendMode mode in Enum.GetValues(typeof(SKBlendMode)))
yield return new object[] { mode };
}
private static SKBlender GetRuntimeBlenderForBlendMode(SKBlendMode mode)
{
using var builder = SKRuntimeEffect.BuildBlender(
"""
uniform blender b;
half4 main(half4 src, half4 dst) {
return b.eval(src, dst);
}
""");
Assert.NotNull(builder.Effect);
builder.Children["b"] = SKBlender.CreateBlendMode(mode);
return builder.Build();
}
}
[Trait(Traits.Category.Key, Traits.Category.Values.Gpu)]
public unsafe class Gpu : SurfaceTestBase, IDisposable
{
GlContext glContext;
GRContext grContext;
public Gpu()
{
glContext = CreateGlContext();
glContext.MakeCurrent();
grContext = GRContext.CreateGl();
CreateSurface(1, 1);
}
protected override void CreateSurface(int width, int height)
{
Surface?.Dispose();
Info = new SKImageInfo(width, height, SKColorType.Rgba8888);
Surface = SKSurface.Create(grContext, false, Info);
}
public void Dispose()
{
Surface.Dispose();
grContext.Dispose();
glContext.Destroy();
}
}
public unsafe class Raster : SurfaceTestBase, IDisposable
{
public Raster()
{
CreateSurface(1, 1);
}
protected override void CreateSurface(int width, int height)
{
Surface?.Dispose();
Info = new SKImageInfo(width, height, SKColorType.Rgba8888);
Surface = SKSurface.Create(Info);
}
public void Dispose()
{
Surface.Dispose();
}
}
}