17 changed files with 337 additions and 43 deletions
@ -0,0 +1,21 @@ |
|||
using Avalonia.Media; |
|||
|
|||
namespace Avalonia.Animation.Animators |
|||
{ |
|||
public class BoxShadowAnimator : Animator<BoxShadow> |
|||
{ |
|||
static ColorAnimator s_colorAnimator = new ColorAnimator(); |
|||
static DoubleAnimator s_doubleAnimator = new DoubleAnimator(); |
|||
public override BoxShadow Interpolate(double progress, BoxShadow oldValue, BoxShadow newValue) |
|||
{ |
|||
return new BoxShadow |
|||
{ |
|||
OffsetX = s_doubleAnimator.Interpolate(progress, oldValue.OffsetX, newValue.OffsetX), |
|||
OffsetY = s_doubleAnimator.Interpolate(progress, oldValue.OffsetY, newValue.OffsetY), |
|||
Blur = s_doubleAnimator.Interpolate(progress, oldValue.Blur, newValue.Blur), |
|||
Spread = s_doubleAnimator.Interpolate(progress, oldValue.Spread, newValue.Spread), |
|||
Color = s_colorAnimator.Interpolate(progress, oldValue.Color, newValue.Color) |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,88 @@ |
|||
using System; |
|||
using Avalonia.Animation.Animators; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Media |
|||
{ |
|||
public struct BoxShadow |
|||
{ |
|||
public double OffsetX { get; set; } |
|||
public double OffsetY { get; set; } |
|||
public double Blur { get; set; } |
|||
public double Spread { get; set; } |
|||
public Color Color { get; set; } |
|||
|
|||
static BoxShadow() |
|||
{ |
|||
Animation.Animation.RegisterAnimator<BoxShadowAnimator>(prop => |
|||
typeof(BoxShadow).IsAssignableFrom(prop.PropertyType)); |
|||
} |
|||
|
|||
public bool Equals(BoxShadow other) |
|||
{ |
|||
return OffsetX.Equals(other.OffsetX) && OffsetY.Equals(other.OffsetY) && Blur.Equals(other.Blur) && Spread.Equals(other.Spread) && Color.Equals(other.Color); |
|||
} |
|||
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj is BoxShadow other && Equals(other); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
var hashCode = OffsetX.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ OffsetY.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ Blur.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ Spread.GetHashCode(); |
|||
hashCode = (hashCode * 397) ^ Color.GetHashCode(); |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
public bool IsEmpty => OffsetX == 0 && OffsetY == 0 && Blur == 0 && Spread == 0; |
|||
|
|||
public static unsafe BoxShadow Parse(string s) |
|||
{ |
|||
if (s == "none") |
|||
return default; |
|||
|
|||
var separatorCount = 0; |
|||
var separators = stackalloc char[4]; |
|||
for(var c = 0; c<s.Length; c++) |
|||
if (s[c] == ',' || s[c] == ' ') |
|||
{ |
|||
if (separatorCount == 4) |
|||
throw new FormatException("Invalid box-shadow format"); |
|||
separators[separatorCount] = s[c]; |
|||
separatorCount++; |
|||
} |
|||
|
|||
if (separatorCount != 2 && separatorCount > 4) |
|||
throw new FormatException("Invalid box-shadow format"); |
|||
|
|||
var tokenizer = new StringTokenizer(s); |
|||
var offsetX = tokenizer.ReadDouble(separators[0]); |
|||
var offsetY = tokenizer.ReadDouble(separators[1]); |
|||
double blur = 0; |
|||
double spread = 0; |
|||
if (separatorCount > 2) |
|||
blur = tokenizer.ReadDouble(separators[2]); |
|||
if (separatorCount > 3) |
|||
spread = tokenizer.ReadDouble(separators[3]); |
|||
var color = Media.Color.Parse(tokenizer.ReadString()); |
|||
return new BoxShadow |
|||
{ |
|||
OffsetX = offsetX, |
|||
OffsetY = offsetY, |
|||
Blur = blur, |
|||
Spread = spread, |
|||
Color = color |
|||
}; |
|||
} |
|||
|
|||
public Rect TransformBounds(in Rect rect) |
|||
=> rect.Translate(new Vector(OffsetX, OffsetY)).Inflate(Spread + Blur); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue