更新整理
This commit is contained in:
229
WPFluent/Controls/SplashWindow/Border.cs
Normal file
229
WPFluent/Controls/SplashWindow/Border.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace WPFluent.Controls;
|
||||
|
||||
public class Border : System.Windows.Controls.Border
|
||||
{
|
||||
protected override Geometry? GetLayoutClip(Size layoutSlotSize)
|
||||
{
|
||||
if (!ClipToBounds)
|
||||
{
|
||||
return base.GetLayoutClip(layoutSlotSize);
|
||||
}
|
||||
|
||||
var borderThickness = BorderThickness;
|
||||
var cornerRadius = CornerRadius;
|
||||
var renderSize = RenderSize;
|
||||
|
||||
if (renderSize.Width <= 0 || renderSize.Height <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var rect = new Rect(0, 0, renderSize.Width, renderSize.Height);
|
||||
var radii = new Radii(cornerRadius, borderThickness, true);
|
||||
|
||||
var layoutGeometry = new StreamGeometry();
|
||||
using var ctx = layoutGeometry.Open();
|
||||
GenerateGeometry(ctx, rect, radii);
|
||||
|
||||
layoutGeometry.Freeze();
|
||||
return layoutGeometry;
|
||||
}
|
||||
|
||||
internal static void GenerateGeometry(StreamGeometryContext ctx, Rect rect, Radii radii)
|
||||
{
|
||||
//
|
||||
// compute the coordinates of the key points
|
||||
//
|
||||
|
||||
Point topLeft = new(radii.LeftTop, 0);
|
||||
Point topRight = new(rect.Width - radii.RightTop, 0);
|
||||
Point rightTop = new(rect.Width, radii.TopRight);
|
||||
Point rightBottom = new(rect.Width, rect.Height - radii.BottomRight);
|
||||
Point bottomRight = new(rect.Width - radii.RightBottom, rect.Height);
|
||||
Point bottomLeft = new(radii.LeftBottom, rect.Height);
|
||||
Point leftBottom = new(0, rect.Height - radii.BottomLeft);
|
||||
Point leftTop = new(0, radii.TopLeft);
|
||||
|
||||
//
|
||||
// check key points for overlap and resolve by partitioning radii according to
|
||||
// the percentage of each one.
|
||||
//
|
||||
|
||||
// top edge is handled here
|
||||
if (topLeft.X > topRight.X)
|
||||
{
|
||||
var v = radii.LeftTop / (radii.LeftTop + radii.RightTop) * rect.Width;
|
||||
topLeft.X = v;
|
||||
topRight.X = v;
|
||||
}
|
||||
|
||||
// right edge
|
||||
if (rightTop.Y > rightBottom.Y)
|
||||
{
|
||||
var v = radii.TopRight / (radii.TopRight + radii.BottomRight) * rect.Height;
|
||||
rightTop.Y = v;
|
||||
rightBottom.Y = v;
|
||||
}
|
||||
|
||||
// bottom edge
|
||||
if (bottomRight.X < bottomLeft.X)
|
||||
{
|
||||
var v = radii.LeftBottom / (radii.LeftBottom + radii.RightBottom) * rect.Width;
|
||||
bottomRight.X = v;
|
||||
bottomLeft.X = v;
|
||||
}
|
||||
|
||||
// left edge
|
||||
if (leftBottom.Y < leftTop.Y)
|
||||
{
|
||||
var v = radii.TopLeft / (radii.TopLeft + radii.BottomLeft) * rect.Height;
|
||||
leftBottom.Y = v;
|
||||
leftTop.Y = v;
|
||||
}
|
||||
|
||||
//
|
||||
// add on offsets
|
||||
//
|
||||
|
||||
Vector offset = new(rect.TopLeft.X, rect.TopLeft.Y);
|
||||
topLeft += offset;
|
||||
topRight += offset;
|
||||
rightTop += offset;
|
||||
rightBottom += offset;
|
||||
bottomRight += offset;
|
||||
bottomLeft += offset;
|
||||
leftBottom += offset;
|
||||
leftTop += offset;
|
||||
|
||||
//
|
||||
// create the border geometry
|
||||
//
|
||||
ctx.BeginFigure(topLeft, true /* is filled */, true /* is closed */);
|
||||
|
||||
// Top line
|
||||
ctx.LineTo(topRight, true /* is stroked */, false /* is smooth join */);
|
||||
|
||||
// Upper-right corner
|
||||
var radiusX = rect.TopRight.X - topRight.X;
|
||||
var radiusY = rightTop.Y - rect.TopRight.Y;
|
||||
if (!MathHelper.IsZero(radiusX) || !MathHelper.IsZero(radiusY))
|
||||
{
|
||||
ctx.ArcTo(rightTop, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
|
||||
}
|
||||
|
||||
// Right line
|
||||
ctx.LineTo(rightBottom, true /* is stroked */, false /* is smooth join */);
|
||||
|
||||
// Lower-right corner
|
||||
radiusX = rect.BottomRight.X - bottomRight.X;
|
||||
radiusY = rect.BottomRight.Y - rightBottom.Y;
|
||||
if (!MathHelper.IsZero(radiusX) || !MathHelper.IsZero(radiusY))
|
||||
{
|
||||
ctx.ArcTo(bottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
|
||||
}
|
||||
|
||||
// Bottom line
|
||||
ctx.LineTo(bottomLeft, true /* is stroked */, false /* is smooth join */);
|
||||
|
||||
// Lower-left corner
|
||||
radiusX = bottomLeft.X - rect.BottomLeft.X;
|
||||
radiusY = rect.BottomLeft.Y - leftBottom.Y;
|
||||
if (!MathHelper.IsZero(radiusX) || !MathHelper.IsZero(radiusY))
|
||||
{
|
||||
ctx.ArcTo(leftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
|
||||
}
|
||||
|
||||
// Left line
|
||||
ctx.LineTo(leftTop, true /* is stroked */, false /* is smooth join */);
|
||||
|
||||
// Upper-left corner
|
||||
radiusX = topLeft.X - rect.TopLeft.X;
|
||||
radiusY = leftTop.Y - rect.TopLeft.Y;
|
||||
if (!MathHelper.IsZero(radiusX) || !MathHelper.IsZero(radiusY))
|
||||
{
|
||||
ctx.ArcTo(topLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
internal struct Radii
|
||||
{
|
||||
internal Radii(CornerRadius radii, Thickness borders, bool outer)
|
||||
{
|
||||
var left = 0.5 * borders.Left;
|
||||
var top = 0.5 * borders.Top;
|
||||
var right = 0.5 * borders.Right;
|
||||
var bottom = 0.5 * borders.Bottom;
|
||||
|
||||
if (outer)
|
||||
{
|
||||
if (MathHelper.IsZero(radii.TopLeft))
|
||||
{
|
||||
LeftTop = TopLeft = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LeftTop = radii.TopLeft + left;
|
||||
TopLeft = radii.TopLeft + top;
|
||||
}
|
||||
if (MathHelper.IsZero(radii.TopRight))
|
||||
{
|
||||
TopRight = RightTop = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
TopRight = radii.TopRight + top;
|
||||
RightTop = radii.TopRight + right;
|
||||
}
|
||||
if (MathHelper.IsZero(radii.BottomRight))
|
||||
{
|
||||
RightBottom = BottomRight = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
RightBottom = radii.BottomRight + right;
|
||||
BottomRight = radii.BottomRight + bottom;
|
||||
}
|
||||
if (MathHelper.IsZero(radii.BottomLeft))
|
||||
{
|
||||
BottomLeft = LeftBottom = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
BottomLeft = radii.BottomLeft + bottom;
|
||||
LeftBottom = radii.BottomLeft + left;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LeftTop = Math.Max(0.0, radii.TopLeft - left);
|
||||
TopLeft = Math.Max(0.0, radii.TopLeft - top);
|
||||
TopRight = Math.Max(0.0, radii.TopRight - top);
|
||||
RightTop = Math.Max(0.0, radii.TopRight - right);
|
||||
RightBottom = Math.Max(0.0, radii.BottomRight - right);
|
||||
BottomRight = Math.Max(0.0, radii.BottomRight - bottom);
|
||||
BottomLeft = Math.Max(0.0, radii.BottomLeft - bottom);
|
||||
LeftBottom = Math.Max(0.0, radii.BottomLeft - left);
|
||||
}
|
||||
}
|
||||
|
||||
internal double LeftTop;
|
||||
internal double TopLeft;
|
||||
internal double TopRight;
|
||||
internal double RightTop;
|
||||
internal double RightBottom;
|
||||
internal double BottomRight;
|
||||
internal double BottomLeft;
|
||||
internal double LeftBottom;
|
||||
}
|
||||
}
|
||||
|
||||
file static class MathHelper
|
||||
{
|
||||
internal const double DBL_EPSILON = 2.2204460492503131e-016;
|
||||
|
||||
public static bool IsZero(double value) => Math.Abs(value) < 10.0 * DBL_EPSILON;
|
||||
}
|
||||
Reference in New Issue
Block a user