csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
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.
147 lines
4.9 KiB
147 lines
4.9 KiB
using System;
|
|
|
|
namespace Avalonia
|
|
{
|
|
public struct RoundedRect
|
|
{
|
|
public bool Equals(RoundedRect other)
|
|
{
|
|
return Rect.Equals(other.Rect) && RadiiTopLeft.Equals(other.RadiiTopLeft) && RadiiTopRight.Equals(other.RadiiTopRight) && RadiiBottomLeft.Equals(other.RadiiBottomLeft) && RadiiBottomRight.Equals(other.RadiiBottomRight);
|
|
}
|
|
|
|
public override bool Equals(object? obj)
|
|
{
|
|
return obj is RoundedRect other && Equals(other);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
unchecked
|
|
{
|
|
var hashCode = Rect.GetHashCode();
|
|
hashCode = (hashCode * 397) ^ RadiiTopLeft.GetHashCode();
|
|
hashCode = (hashCode * 397) ^ RadiiTopRight.GetHashCode();
|
|
hashCode = (hashCode * 397) ^ RadiiBottomLeft.GetHashCode();
|
|
hashCode = (hashCode * 397) ^ RadiiBottomRight.GetHashCode();
|
|
return hashCode;
|
|
}
|
|
}
|
|
|
|
public static bool operator ==(RoundedRect left, RoundedRect right) => left.Equals(right);
|
|
|
|
public static bool operator !=(RoundedRect left, RoundedRect right) => !left.Equals(right);
|
|
|
|
public Rect Rect { get; }
|
|
public Vector RadiiTopLeft { get; }
|
|
public Vector RadiiTopRight { get; }
|
|
public Vector RadiiBottomLeft { get; }
|
|
public Vector RadiiBottomRight { get; }
|
|
|
|
public RoundedRect(Rect rect, Vector radiiTopLeft, Vector radiiTopRight, Vector radiiBottomRight, Vector radiiBottomLeft)
|
|
{
|
|
Rect = rect;
|
|
RadiiTopLeft = radiiTopLeft;
|
|
RadiiTopRight = radiiTopRight;
|
|
RadiiBottomRight = radiiBottomRight;
|
|
RadiiBottomLeft = radiiBottomLeft;
|
|
}
|
|
|
|
public RoundedRect(Rect rect, double radiusTopLeft, double radiusTopRight, double radiusBottomRight,
|
|
double radiusBottomLeft)
|
|
: this(rect,
|
|
new Vector(radiusTopLeft, radiusTopLeft),
|
|
new Vector(radiusTopRight, radiusTopRight),
|
|
new Vector(radiusBottomRight, radiusBottomRight),
|
|
new Vector(radiusBottomLeft, radiusBottomLeft)
|
|
)
|
|
{
|
|
|
|
}
|
|
|
|
public RoundedRect(Rect rect, Vector radii) : this(rect, radii, radii, radii, radii)
|
|
{
|
|
|
|
}
|
|
|
|
public RoundedRect(Rect rect, double radiusX, double radiusY) : this(rect, new Vector(radiusX, radiusY))
|
|
{
|
|
|
|
}
|
|
|
|
public RoundedRect(Rect rect, double radius) : this(rect, radius, radius)
|
|
{
|
|
|
|
}
|
|
|
|
public RoundedRect(Rect rect) : this(rect, 0)
|
|
{
|
|
|
|
}
|
|
|
|
public RoundedRect(in Rect bounds, in CornerRadius radius) : this(bounds,
|
|
radius.TopLeft, radius.TopRight,
|
|
radius.BottomRight, radius.BottomLeft)
|
|
{
|
|
|
|
}
|
|
|
|
public static implicit operator RoundedRect(Rect r) => new RoundedRect(r);
|
|
|
|
public bool IsRounded => RadiiTopLeft != default || RadiiTopRight != default || RadiiBottomRight != default ||
|
|
RadiiBottomLeft != default;
|
|
|
|
public bool IsUniform =>
|
|
RadiiTopLeft.Equals(RadiiTopRight) &&
|
|
RadiiTopLeft.Equals(RadiiBottomRight) &&
|
|
RadiiTopLeft.Equals(RadiiBottomLeft);
|
|
|
|
public RoundedRect Inflate(double dx, double dy)
|
|
{
|
|
return Deflate(-dx, -dy);
|
|
}
|
|
|
|
public unsafe RoundedRect Deflate(double dx, double dy)
|
|
{
|
|
if (!IsRounded)
|
|
return new RoundedRect(Rect.Deflate(new Thickness(dx, dy)));
|
|
|
|
// Ported from SKRRect
|
|
var left = Rect.X + dx;
|
|
var top = Rect.Y + dy;
|
|
var right = left + Rect.Width - dx * 2;
|
|
var bottom = top + Rect.Height - dy * 2;
|
|
var radii = stackalloc Vector[4];
|
|
radii[0] = RadiiTopLeft;
|
|
radii[1] = RadiiTopRight;
|
|
radii[2] = RadiiBottomRight;
|
|
radii[3] = RadiiBottomLeft;
|
|
|
|
bool degenerate = false;
|
|
if (right <= left) {
|
|
degenerate = true;
|
|
left = right = (left + right)*0.5;
|
|
}
|
|
if (bottom <= top) {
|
|
degenerate = true;
|
|
top = bottom = (top + bottom) * 0.5;
|
|
}
|
|
if (degenerate)
|
|
{
|
|
return new RoundedRect(new Rect(left, top, right - left, bottom - top));
|
|
}
|
|
|
|
for (var c = 0; c < 4; c++)
|
|
{
|
|
var rx = Math.Max(0, radii[c].X - dx);
|
|
var ry = Math.Max(0, radii[c].Y - dy);
|
|
if (rx == 0 || ry == 0)
|
|
radii[c] = default;
|
|
else
|
|
radii[c] = new Vector(rx, ry);
|
|
}
|
|
|
|
return new RoundedRect(new Rect(left, top, right - left, bottom - top),
|
|
radii[0], radii[1], radii[2], radii[3]);
|
|
}
|
|
}
|
|
}
|
|
|