Skip to content

Commit

Permalink
Expose SKBlender (#2830)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattleibow authored Apr 15, 2024
1 parent a0f3767 commit aa4f2ff
Show file tree
Hide file tree
Showing 18 changed files with 567 additions and 2 deletions.
1 change: 1 addition & 0 deletions binding/SkiaSharp.Resources/ResourcesApi.generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
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;
Expand Down
1 change: 1 addition & 0 deletions binding/SkiaSharp.SceneGraph/SceneGraphApi.generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
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;
Expand Down
1 change: 1 addition & 0 deletions binding/SkiaSharp.Skottie/SkottieApi.generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
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;
Expand Down
63 changes: 63 additions & 0 deletions binding/SkiaSharp/SKBlender.cs
Original file line number Diff line number Diff line change
@@ -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) { }
}
}
5 changes: 5 additions & 0 deletions binding/SkiaSharp/SKColorSpace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ public unsafe class SKColorSpace : SKObject, ISKNonVirtualReferenceCounted

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 ());
}
Expand Down
5 changes: 5 additions & 0 deletions binding/SkiaSharp/SKData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public unsafe class SKData : SKObject, ISKNonVirtualReferenceCounted

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 ());
}

Expand Down
5 changes: 5 additions & 0 deletions binding/SkiaSharp/SKFontManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public unsafe class SKFontManager : SKObject, ISKReferenceCounted

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 ());
}

Expand Down
17 changes: 17 additions & 0 deletions binding/SkiaSharp/SKImageFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,23 @@ public static SKImageFilter CreateBlendMode (SKBlendMode mode, SKImageFilter? ba
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) =>
Expand Down
1 change: 1 addition & 0 deletions binding/SkiaSharp/SKObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ static SKObject ()
SKData.EnsureStaticInstanceAreInitialized ();
SKFontManager.EnsureStaticInstanceAreInitialized ();
SKTypeface.EnsureStaticInstanceAreInitialized ();
SKBlender.EnsureStaticInstanceAreInitialized ();
}

internal SKObject (IntPtr handle, bool owns)
Expand Down
5 changes: 5 additions & 0 deletions binding/SkiaSharp/SKPaint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ public SKBlendMode BlendMode {
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);
Expand Down
62 changes: 62 additions & 0 deletions binding/SkiaSharp/SKRuntimeEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ public static SKRuntimeEffect CreateColorFilter (string sksl, out string errors)
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)
Expand All @@ -57,6 +68,13 @@ public static SKRuntimeColorFilterBuilder BuildColorFilter (string sksl)
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) {
Expand Down Expand Up @@ -148,6 +166,30 @@ private SKColorFilter ToColorFilter (SKData uniforms, SKObject[] children)
}
}

// 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) =>
Expand Down Expand Up @@ -560,15 +602,24 @@ public SKRuntimeEffectChild (SKColorFilter colorFilter)
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
Expand Down Expand Up @@ -627,4 +678,15 @@ public SKRuntimeColorFilterBuilder (SKRuntimeEffect effect)
public SKColorFilter Build () =>
Effect.ToColorFilter (Uniforms, Children);
}

public class SKRuntimeBlenderBuilder : SKRuntimeEffectBuilder
{
public SKRuntimeBlenderBuilder (SKRuntimeEffect effect)
: base (effect)
{
}

public SKBlender Build () =>
Effect.ToBlender (Uniforms, Children);
}
}
17 changes: 17 additions & 0 deletions binding/SkiaSharp/SKShader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,23 @@ public static SKShader CreateCompose (SKShader shaderA, SKShader shaderB, SKBlen
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)
Expand Down
5 changes: 5 additions & 0 deletions binding/SkiaSharp/SKTypeface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ public unsafe class SKTypeface : SKObject, ISKReferenceCounted

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 ());
}

Expand Down
Loading

0 comments on commit aa4f2ff

Please sign in to comment.