/// <summary> /// Border computes the position of its single child and applies its child's alignments to the child. /// </summary> /// <param name="finalSize">The size reserved for this element by the parent</param> /// <returns>The actual ink area of the element, typically the same as finalSize</returns> protected override Size ArrangeOverride(Size finalSize) { var borders = BorderThickness; if (UseLayoutRounding) { var dpi = DpiUtil.GetDpi(this); borders = new Thickness(UIElementUtil.RoundLayoutValue(borders.Left, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Top, dpi.DpiScaleY), UIElementUtil.RoundLayoutValue(borders.Right, dpi.DpiScaleX), UIElementUtil.RoundLayoutValue(borders.Bottom, dpi.DpiScaleY)); } var boundRect = new Rect(finalSize); var innerRect = RectUtil.Deflate(boundRect, borders); // arrange child var child = Child; if (child != null) { Rect childRect = RectUtil.Deflate(innerRect, Padding); child.Arrange(childRect); } var radius = CornerRadius; useComplexRender = !CornerRadiusUtil.IsUniform(radius) || !ThicknessUtil.IsUniform(borders); backgroundGeometryCache = upperLeftCache = upperRightCache = lowerRightCache = lowerLeftCache = null; if (useComplexRender) { // calculate border / background rendering geometry if (!DoubleUtil.IsZero(boundRect.Width) && !DoubleUtil.IsZero(boundRect.Height)) { var outerRadii = new Radii(boundRect, radius, borders, true); // Upper-right corner var radiusX = boundRect.TopRight.X - outerRadii.TopRight.X; var radiusY = outerRadii.RightTop.Y - boundRect.TopRight.Y; if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY)) { upperRightCache = GenerateRoundedGeometry(outerRadii.TopRight, outerRadii.RightTop, new Size(radiusX, radiusY)); } // Lower-right corner radiusX = boundRect.BottomRight.X - outerRadii.BottomRight.X; radiusY = boundRect.BottomRight.Y - outerRadii.RightBottom.Y; if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY)) { lowerRightCache = GenerateRoundedGeometry(outerRadii.RightBottom, outerRadii.BottomRight, new Size(radiusX, radiusY)); } // Lower-left corner radiusX = outerRadii.BottomLeft.X - boundRect.BottomLeft.X; radiusY = boundRect.BottomLeft.Y - outerRadii.LeftBottom.Y; if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY)) { lowerLeftCache = GenerateRoundedGeometry(outerRadii.BottomLeft, outerRadii.LeftBottom, new Size(radiusX, radiusY)); } // Upper-left corner radiusX = outerRadii.TopLeft.X - boundRect.TopLeft.X; radiusY = outerRadii.LeftTop.Y - boundRect.TopLeft.Y; if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY)) { upperLeftCache = GenerateRoundedGeometry(outerRadii.LeftTop, outerRadii.TopLeft, new Size(radiusX, radiusY)); } } if (!DoubleUtil.IsZero(innerRect.Width) && !DoubleUtil.IsZero(innerRect.Height)) { var innerRadii = new Radii(innerRect, radius, borders, false); var backgroundGeometry = new StreamGeometry(); using (StreamGeometryContext sc = backgroundGeometry.Open()) { // create the border geometry sc.BeginFigure(innerRadii.TopLeft, true /* is filled */, true /* is closed */); // Top line sc.LineTo(innerRadii.TopRight, true /* is stroked */, false /* is smooth join */); // Upper-right corners var radiusX = innerRect.TopRight.X - innerRadii.TopRight.X; var radiusY = innerRadii.RightTop.Y - innerRect.TopRight.Y; if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY)) { sc.ArcTo(innerRadii.RightTop, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false); } // Right line sc.LineTo(innerRadii.RightBottom, true /* is stroked */, false /* is smooth join */); // Lower-right corners radiusX = innerRect.BottomRight.X - innerRadii.BottomRight.X; radiusY = innerRect.BottomRight.Y - innerRadii.RightBottom.Y; if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY)) { sc.ArcTo(innerRadii.BottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false); } // Bottom line sc.LineTo(innerRadii.BottomLeft, true /* is stroked */, false /* is smooth join */); // Lower-left corners radiusX = innerRadii.BottomLeft.X - innerRect.BottomLeft.X; radiusY = innerRect.BottomLeft.Y - innerRadii.LeftBottom.Y; if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY)) { sc.ArcTo(innerRadii.LeftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false); } // Left line sc.LineTo(innerRadii.LeftTop, true /* is stroked */, false /* is smooth join */); // Upper-left corners radiusX = innerRadii.TopLeft.X - innerRect.TopLeft.X; radiusY = innerRadii.LeftTop.Y - innerRect.TopLeft.Y; if (!DoubleUtil.IsZero(radiusX) || !DoubleUtil.IsZero(radiusY)) { sc.ArcTo(innerRadii.TopLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false); } } backgroundGeometry.Freeze(); backgroundGeometryCache = backgroundGeometry; } } return(finalSize); }
private static bool IsCornerRadiusValid(object value) { return(CornerRadiusUtil.IsValid((CornerRadius)value, false, false, false, false)); }