A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

173 lines
5.2 KiB

using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
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; }
public bool IsInset { get; set; }
public bool Equals(in 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;
}
}
private readonly static char[] s_Separator = new char[] { ' ', '\t' };
struct ArrayReader
{
private int _index;
private string[] _arr;
public ArrayReader(string[] arr)
{
_arr = arr;
_index = 0;
}
public bool TryReadString([MaybeNullWhen(false)] out string s)
{
s = null;
if (_index >= _arr.Length)
return false;
s = _arr[_index];
_index++;
return true;
}
public string ReadString()
{
if(!TryReadString(out var rv))
throw new FormatException();
return rv;
}
}
public override string ToString()
{
var sb = StringBuilderCache.Acquire();
if (this == default)
{
return "none";
}
if (IsInset)
{
sb.Append("inset");
}
if (OffsetX != 0.0)
{
sb.AppendFormat(" {0}", OffsetX.ToString(CultureInfo.InvariantCulture));
}
if (OffsetY != 0.0)
{
sb.AppendFormat(" {0}", OffsetY.ToString(CultureInfo.InvariantCulture));
}
if (Blur != 0.0)
{
sb.AppendFormat(" {0}", Blur.ToString(CultureInfo.InvariantCulture));
}
if (Spread != 0.0)
{
sb.AppendFormat(" {0}", Spread.ToString(CultureInfo.InvariantCulture));
}
sb.AppendFormat(" {0}", Color.ToString());
return StringBuilderCache.GetStringAndRelease(sb);
}
public static unsafe BoxShadow Parse(string s)
{
if(s == null)
throw new ArgumentNullException();
if (s.Length == 0)
throw new FormatException();
var p = s.Split(s_Separator, StringSplitOptions.RemoveEmptyEntries);
if (p.Length == 1 && p[0] == "none")
return default;
if (p.Length < 3 || p.Length > 6)
throw new FormatException();
bool inset = false;
var tokenizer = new ArrayReader(p);
string firstToken = tokenizer.ReadString();
if (firstToken == "inset")
{
inset = true;
firstToken = tokenizer.ReadString();
}
var offsetX = double.Parse(firstToken, CultureInfo.InvariantCulture);
var offsetY = double.Parse(tokenizer.ReadString(), CultureInfo.InvariantCulture);
double blur = 0;
double spread = 0;
tokenizer.TryReadString(out var token3);
tokenizer.TryReadString(out var token4);
tokenizer.TryReadString(out var token5);
if (token4 != null)
blur = double.Parse(token3!, CultureInfo.InvariantCulture);
if (token5 != null)
spread = double.Parse(token4!, CultureInfo.InvariantCulture);
var color = Color.Parse(token5 ?? token4 ?? token3!);
return new BoxShadow
{
IsInset = inset,
OffsetX = offsetX,
OffsetY = offsetY,
Blur = blur,
Spread = spread,
Color = color
};
}
public Rect TransformBounds(in Rect rect)
=> IsInset ? rect : rect.Translate(new Vector(OffsetX, OffsetY)).Inflate(Spread + Blur);
public static bool operator ==(BoxShadow left, BoxShadow right) =>
left.Equals(right);
public static bool operator !=(BoxShadow left, BoxShadow right) =>
!(left == right);
}
}