|
|
@ -1,8 +1,10 @@ |
|
|
using System; |
|
|
using System; |
|
|
|
|
|
using Avalonia.Collections; |
|
|
using Avalonia.Media; |
|
|
using Avalonia.Media; |
|
|
using Avalonia.Media.Immutable; |
|
|
using Avalonia.Media.Immutable; |
|
|
using Avalonia.Platform; |
|
|
using Avalonia.Platform; |
|
|
using Avalonia.Utilities; |
|
|
using Avalonia.Utilities; |
|
|
|
|
|
using JetBrains.Annotations; |
|
|
|
|
|
|
|
|
namespace Avalonia.Controls.Utils |
|
|
namespace Avalonia.Controls.Utils |
|
|
{ |
|
|
{ |
|
|
@ -15,8 +17,13 @@ namespace Avalonia.Controls.Utils |
|
|
private Size _size; |
|
|
private Size _size; |
|
|
private Thickness _borderThickness; |
|
|
private Thickness _borderThickness; |
|
|
private CornerRadius _cornerRadius; |
|
|
private CornerRadius _cornerRadius; |
|
|
|
|
|
private AvaloniaList<double> _borderDashArray; |
|
|
|
|
|
private double _borderDashOffset; |
|
|
|
|
|
private PenLineCap _borderLineCap; |
|
|
|
|
|
private PenLineJoin _borderJoin; |
|
|
private bool _initialized; |
|
|
private bool _initialized; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Update(Size finalSize, Thickness borderThickness, CornerRadius cornerRadius) |
|
|
void Update(Size finalSize, Thickness borderThickness, CornerRadius cornerRadius) |
|
|
{ |
|
|
{ |
|
|
_backendSupportsIndividualCorners ??= AvaloniaLocator.Current.GetService<IPlatformRenderInterface>() |
|
|
_backendSupportsIndividualCorners ??= AvaloniaLocator.Current.GetService<IPlatformRenderInterface>() |
|
|
@ -60,7 +67,8 @@ namespace Avalonia.Controls.Utils |
|
|
|
|
|
|
|
|
if (boundRect.Width != 0 && innerRect.Height != 0) |
|
|
if (boundRect.Width != 0 && innerRect.Height != 0) |
|
|
{ |
|
|
{ |
|
|
var borderGeometryKeypoints = new BorderGeometryKeypoints(boundRect, borderThickness, cornerRadius, false); |
|
|
var borderGeometryKeypoints = |
|
|
|
|
|
new BorderGeometryKeypoints(boundRect, borderThickness, cornerRadius, false); |
|
|
var borderGeometry = new StreamGeometry(); |
|
|
var borderGeometry = new StreamGeometry(); |
|
|
|
|
|
|
|
|
using (var ctx = borderGeometry.Open()) |
|
|
using (var ctx = borderGeometry.Open()) |
|
|
@ -84,17 +92,22 @@ namespace Avalonia.Controls.Utils |
|
|
|
|
|
|
|
|
public void Render(DrawingContext context, |
|
|
public void Render(DrawingContext context, |
|
|
Size finalSize, Thickness borderThickness, CornerRadius cornerRadius, |
|
|
Size finalSize, Thickness borderThickness, CornerRadius cornerRadius, |
|
|
IBrush background, IBrush borderBrush, BoxShadows boxShadows) |
|
|
IBrush background, IBrush borderBrush, BoxShadows boxShadows, double borderDashOffset = 0, |
|
|
|
|
|
PenLineCap borderLineCap = PenLineCap.Flat, PenLineJoin borderLineJoin = PenLineJoin.Miter, |
|
|
|
|
|
AvaloniaList<double> borderDashArray = null) |
|
|
{ |
|
|
{ |
|
|
if (_size != finalSize |
|
|
if (_size != finalSize |
|
|
|| _borderThickness != borderThickness |
|
|
|| _borderThickness != borderThickness |
|
|
|| _cornerRadius != cornerRadius |
|
|
|| _cornerRadius != cornerRadius |
|
|
|| !_initialized) |
|
|
|| !_initialized) |
|
|
Update(finalSize, borderThickness, cornerRadius); |
|
|
Update(finalSize, borderThickness, cornerRadius); |
|
|
RenderCore(context, background, borderBrush, boxShadows); |
|
|
RenderCore(context, background, borderBrush, boxShadows, borderDashOffset, borderLineCap, borderLineJoin, |
|
|
|
|
|
borderDashArray); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void RenderCore(DrawingContext context, IBrush background, IBrush borderBrush, BoxShadows boxShadows) |
|
|
void RenderCore(DrawingContext context, IBrush background, IBrush borderBrush, BoxShadows boxShadows, |
|
|
|
|
|
double borderDashOffset, PenLineCap borderLineCap, PenLineJoin borderLineJoin, |
|
|
|
|
|
AvaloniaList<double> borderDashArray) |
|
|
{ |
|
|
{ |
|
|
if (_useComplexRendering) |
|
|
if (_useComplexRendering) |
|
|
{ |
|
|
{ |
|
|
@ -115,11 +128,25 @@ namespace Avalonia.Controls.Utils |
|
|
var borderThickness = _borderThickness.Top; |
|
|
var borderThickness = _borderThickness.Top; |
|
|
IPen pen = null; |
|
|
IPen pen = null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ImmutableDashStyle? dashStyle = null; |
|
|
|
|
|
|
|
|
|
|
|
if (borderDashArray != null && borderDashArray.Count > 0) |
|
|
|
|
|
{ |
|
|
|
|
|
dashStyle = new ImmutableDashStyle(borderDashArray, borderDashOffset); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (borderBrush != null && borderThickness > 0) |
|
|
if (borderBrush != null && borderThickness > 0) |
|
|
{ |
|
|
{ |
|
|
pen = new ImmutablePen(borderBrush.ToImmutable(), borderThickness); |
|
|
pen = new ImmutablePen( |
|
|
|
|
|
borderBrush.ToImmutable(), |
|
|
|
|
|
borderThickness, |
|
|
|
|
|
dashStyle, |
|
|
|
|
|
borderLineCap, |
|
|
|
|
|
borderLineJoin); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var rect = new Rect(_size); |
|
|
var rect = new Rect(_size); |
|
|
if (!MathUtilities.IsZero(borderThickness)) |
|
|
if (!MathUtilities.IsZero(borderThickness)) |
|
|
rect = rect.Deflate(borderThickness * 0.5); |
|
|
rect = rect.Deflate(borderThickness * 0.5); |
|
|
@ -130,7 +157,8 @@ namespace Avalonia.Controls.Utils |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderGeometryKeypoints keypoints) |
|
|
private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, |
|
|
|
|
|
BorderGeometryKeypoints keypoints) |
|
|
{ |
|
|
{ |
|
|
context.BeginFigure(keypoints.TopLeft, true); |
|
|
context.BeginFigure(keypoints.TopLeft, true); |
|
|
|
|
|
|
|
|
@ -184,7 +212,8 @@ namespace Avalonia.Controls.Utils |
|
|
|
|
|
|
|
|
private class BorderGeometryKeypoints |
|
|
private class BorderGeometryKeypoints |
|
|
{ |
|
|
{ |
|
|
internal BorderGeometryKeypoints(Rect boundRect, Thickness borderThickness, CornerRadius cornerRadius, bool inner) |
|
|
internal BorderGeometryKeypoints(Rect boundRect, Thickness borderThickness, CornerRadius cornerRadius, |
|
|
|
|
|
bool inner) |
|
|
{ |
|
|
{ |
|
|
var left = 0.5 * borderThickness.Left; |
|
|
var left = 0.5 * borderThickness.Left; |
|
|
var top = 0.5 * borderThickness.Top; |
|
|
var top = 0.5 * borderThickness.Top; |
|
|
@ -206,10 +235,13 @@ namespace Avalonia.Controls.Utils |
|
|
topLeftX = Math.Max(0, cornerRadius.TopLeft - left) + boundRect.TopLeft.X; |
|
|
topLeftX = Math.Max(0, cornerRadius.TopLeft - left) + boundRect.TopLeft.X; |
|
|
topRightX = boundRect.Width - Math.Max(0, cornerRadius.TopRight - top) + boundRect.TopLeft.X; |
|
|
topRightX = boundRect.Width - Math.Max(0, cornerRadius.TopRight - top) + boundRect.TopLeft.X; |
|
|
rightTopY = Math.Max(0, cornerRadius.TopRight - right) + boundRect.TopLeft.Y; |
|
|
rightTopY = Math.Max(0, cornerRadius.TopRight - right) + boundRect.TopLeft.Y; |
|
|
rightBottomY = boundRect.Height - Math.Max(0, cornerRadius.BottomRight - bottom) + boundRect.TopLeft.Y; |
|
|
rightBottomY = boundRect.Height - Math.Max(0, cornerRadius.BottomRight - bottom) + |
|
|
bottomRightX = boundRect.Width - Math.Max(0, cornerRadius.BottomRight - right) + boundRect.TopLeft.X; |
|
|
boundRect.TopLeft.Y; |
|
|
|
|
|
bottomRightX = boundRect.Width - Math.Max(0, cornerRadius.BottomRight - right) + |
|
|
|
|
|
boundRect.TopLeft.X; |
|
|
bottomLeftX = Math.Max(0, cornerRadius.BottomLeft - left) + boundRect.TopLeft.X; |
|
|
bottomLeftX = Math.Max(0, cornerRadius.BottomLeft - left) + boundRect.TopLeft.X; |
|
|
leftBottomY = boundRect.Height - Math.Max(0, cornerRadius.BottomLeft - bottom) + boundRect.TopLeft.Y; |
|
|
leftBottomY = boundRect.Height - Math.Max(0, cornerRadius.BottomLeft - bottom) + |
|
|
|
|
|
boundRect.TopLeft.Y; |
|
|
} |
|
|
} |
|
|
else |
|
|
else |
|
|
{ |
|
|
{ |
|
|
|