diff --git a/src/Avalonia.Visuals/Media/AcrylicBackgroundSource.cs b/src/Avalonia.Visuals/Media/AcrylicBackgroundSource.cs
new file mode 100644
index 0000000000..d902752f85
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/AcrylicBackgroundSource.cs
@@ -0,0 +1,8 @@
+namespace Avalonia.Media
+{
+ public enum AcrylicBackgroundSource
+ {
+ None,
+ Digger
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/ExperimentalAcrylicBrush.cs b/src/Avalonia.Visuals/Media/ExperimentalAcrylicBrush.cs
new file mode 100644
index 0000000000..2ab2701c9d
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/ExperimentalAcrylicBrush.cs
@@ -0,0 +1,17 @@
+namespace Avalonia.Media
+{
+ public class ExperimentalAcrylicBrush : IExperimentalAcrylicBrush
+ {
+ public AcrylicBackgroundSource BackgroundSource { get; set; }
+
+ public Color TintColor { get; set; }
+
+ public double TintOpacity { get; set; }
+
+ public Color FallbackColor { get; set; }
+
+ public double TintLuminosityOpacity { get; set; }
+
+ public double Opacity { get; set; }
+ }
+}
diff --git a/src/Avalonia.Visuals/Media/IBrush.cs b/src/Avalonia.Visuals/Media/IBrush.cs
index 7756e94598..15b7681be4 100644
--- a/src/Avalonia.Visuals/Media/IBrush.cs
+++ b/src/Avalonia.Visuals/Media/IBrush.cs
@@ -13,4 +13,4 @@ namespace Avalonia.Media
///
double Opacity { get; }
}
-}
\ No newline at end of file
+}
diff --git a/src/Avalonia.Visuals/Media/IExperimentalAcrylicBrush.cs b/src/Avalonia.Visuals/Media/IExperimentalAcrylicBrush.cs
new file mode 100644
index 0000000000..ae202b58ae
--- /dev/null
+++ b/src/Avalonia.Visuals/Media/IExperimentalAcrylicBrush.cs
@@ -0,0 +1,15 @@
+namespace Avalonia.Media
+{
+ public interface IExperimentalAcrylicBrush : IBrush
+ {
+ AcrylicBackgroundSource BackgroundSource { get; set; }
+
+ Color TintColor { get; set; }
+
+ double TintOpacity { get; set; }
+
+ double TintLuminosityOpacity { get; set; }
+
+ Color FallbackColor { get; set; }
+ }
+}
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index 26fdb08a4b..0d628d6b21 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -227,6 +227,13 @@ namespace Avalonia.Skia
return bounds;
}
+ private static bool IsLight (Color c)
+ {
+ double lightness = (0.299 * c.R + 0.587 * c.G + 0.114 * c.B) / 255;
+
+ return lightness > 0.5;
+ }
+
///
public void DrawRectangle(IBrush brush, IPen pen, RoundedRect rect, BoxShadows boxShadows = default)
@@ -238,6 +245,17 @@ namespace Avalonia.Skia
if (rect.Rect.Height > 8192 || rect.Rect.Width > 8192)
boxShadows = default;
+ if (brush is IExperimentalAcrylicBrush acrylic && IsLight(acrylic.TintColor))
+ {
+ boxShadows = new BoxShadows(new BoxShadow
+ {
+ Blur = 2,
+ OffsetX = 1,
+ Color = Colors.White,
+ IsInset = true
+ });
+ }
+
var rc = rect.Rect.ToSKRect();
var isRounded = rect.IsRounded;
var needRoundRect = rect.IsRounded || (boxShadows.HasInsetShadows);
@@ -653,6 +671,36 @@ namespace Avalonia.Skia
}
}
+ static SKColor SimpleColorBurn(SKColor bg, SKColor fg)
+ {
+ using (var bmp = new SKBitmap(1, 1))
+ {
+ bmp.SetPixel(0, 0, bg);
+ using (var canvas = new SKCanvas(bmp))
+ using (var paint = new SKPaint
+ {
+ Color = fg
+ })
+ canvas.DrawRect(-1, -1, 3, 3, paint);
+ return bmp.GetPixel(0, 0);
+ }
+ }
+
+ static SKColorFilter CreateAlphaColorFilter(double opacity)
+ {
+ if (opacity > 1)
+ opacity = 1;
+ var c = new byte[256];
+ var a = new byte[256];
+ for (var i = 0; i < 256; i++)
+ {
+ c[i] = 255;
+ a[i] = (byte)(i * opacity);
+ }
+
+ return SKColorFilter.CreateTable(a, c, c, c);
+ }
+
///
/// Creates paint wrapper for given brush.
///
@@ -676,6 +724,32 @@ namespace Avalonia.Skia
return paintWrapper;
}
+ if(brush is IExperimentalAcrylicBrush acrylicBrush)
+ {
+ var tintOpacity = acrylicBrush.TintOpacity;
+ var noiseOpcity = 0.12;
+
+ var excl = new SKColor(255, 255, 255, (byte)(255 * acrylicBrush.TintLuminosityOpacity));
+ var tint = new SKColor(acrylicBrush.TintColor.R, acrylicBrush.TintColor.G, acrylicBrush.TintColor.B, (byte)(255 * tintOpacity));
+
+ tint = SimpleColorBurn(excl, tint);
+
+ var tintShader = SKShader.CreateColor(tint);
+ var noiseShader =
+ SKShader.CreatePerlinNoiseTurbulence(12.876f, 12.876f, 2, 0.76829314f)
+ .WithColorFilter(CreateAlphaColorFilter(noiseOpcity));
+
+ var compose = SKShader.CreateCompose(tintShader, noiseShader);
+ paint.Shader = compose;
+
+ if (acrylicBrush.BackgroundSource == AcrylicBackgroundSource.Digger)
+ {
+ paint.BlendMode = SKBlendMode.Src;
+ }
+
+ return paintWrapper;
+ }
+
paint.Color = new SKColor(255, 255, 255, (byte) (255 * opacity));
if (brush is IGradientBrush gradient)