Skip to content

Commit

Permalink
feat: Added support for shadows on SkiaSharp
Browse files Browse the repository at this point in the history
  • Loading branch information
VitezslavImrysek authored and MartinZikmund committed Nov 9, 2021
1 parent 29e73f1 commit 5822668
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
14 changes: 11 additions & 3 deletions src/Uno.UI/UI/Xaml/UIElement.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public partial class UIElement : DependencyObject
internal double _canvasTop;
internal double _canvasLeft;
private Rect _currentFinalRect;
private Vector3 _translation;

public UIElement()
{
Expand All @@ -44,6 +45,12 @@ public UIElement()
UpdateHitTest();
}

public Vector3 Translation
{
get { return _translation; }
set { _translation = value; }
}

partial void InitializeKeyboard();

private void OnPropertyChanged(ManagedWeakReference instance, DependencyProperty property, DependencyPropertyChangedEventArgs args)
Expand Down Expand Up @@ -253,9 +260,10 @@ internal virtual void OnArrangeVisual(Rect rect, Rect? clip)
{
var roundedRect = LayoutRound(rect);

Visual.Offset = new Vector3((float)roundedRect.X, (float)roundedRect.Y, 0);
Visual.Size = new Vector2((float)roundedRect.Width, (float)roundedRect.Height);
Visual.CenterPoint = new Vector3((float)RenderTransformOrigin.X, (float)RenderTransformOrigin.Y, 0);
var visual = Visual;
visual.Offset = new Vector3((float)roundedRect.X, (float)roundedRect.Y, 0) + _translation;
visual.Size = new Vector2((float)roundedRect.Width, (float)roundedRect.Height);
visual.CenterPoint = new Vector3((float)RenderTransformOrigin.X, (float)RenderTransformOrigin.Y, 0);

ApplyNativeClip(clip ?? Rect.Empty);
}
Expand Down
39 changes: 38 additions & 1 deletion src/Uno.UWP/UI/Composition/Compositor.skia.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,16 @@ private void RenderVisual(SKSurface surface, SKImageInfo info, Visual visual)
{
if (visual.Opacity != 0 && visual.IsVisible)
{
surface.Canvas.Save();
var offsetZ = visual.Offset.Z;
if (offsetZ > 0)
{
ComputeDropShadowValues(offsetZ, out float dx, out float dy, out float sigmaX, out float sigmaY, out SKColor shadowColor);
surface.Canvas.SaveLayer(new SKPaint() { ImageFilter = SKImageFilter.CreateDropShadow(dx, dy, sigmaX, sigmaY, shadowColor) });
}
else
{
surface.Canvas.Save();
}

var visualMatrix = surface.Canvas.TotalMatrix;

Expand Down Expand Up @@ -152,5 +161,33 @@ partial void InvalidateRenderPartial()
CoreWindow.QueueInvalidateRender();
}
}

private void ComputeDropShadowValues(float offsetZ, out float dx, out float dy, out float sigmaX, out float sigmaY, out SKColor shadowColor)
{
// Following math magic seems to follow UWP ThemeShadow quite nicely.
const float SHADOW_OFFSET_MAX = 150;
const byte SHADOW_ALPHA_FALLBACK = 150;
const float SHADOW_ALPHA_MODIFIER = 1f / 650f;
const float SHADOW_SIGMA_X_MODIFIER = 1f / 5f;
const float SHADOW_SIGMA_Y_MODIFIER = 1f / 3.5f;

byte alpha;
if (offsetZ <= SHADOW_OFFSET_MAX)
{
// Alpha should slightly decrease as the offset increases
alpha = (byte)((1.0f - (offsetZ * SHADOW_ALPHA_MODIFIER)) * 255);
}
else
{
alpha = SHADOW_ALPHA_FALLBACK;
offsetZ = SHADOW_OFFSET_MAX;
}

dx = 0;
dy = offsetZ / 2 - offsetZ * SHADOW_SIGMA_Y_MODIFIER;
sigmaX = offsetZ * SHADOW_SIGMA_X_MODIFIER;
sigmaY = offsetZ * SHADOW_SIGMA_Y_MODIFIER;
shadowColor = SKColor.Parse("ACACAC").WithAlpha(alpha);
}
}
}

0 comments on commit 5822668

Please sign in to comment.