public void Update(Size finalSize, Thickness borderThickness, CornerRadius cornerRadius) { if (borderThickness.IsUniform && cornerRadius.IsUniform) { _backgroundGeometryCache = null; _borderGeometryCache = null; _useComplexRendering = false; } else { _useComplexRendering = true; var boundRect = new Rect(finalSize); var innerRect = boundRect.Deflate(borderThickness); var innerCoordinates = new BorderCoordinates(cornerRadius, borderThickness, false); StreamGeometry backgroundGeometry = null; if (innerRect.Width != 0 && innerRect.Height != 0) { backgroundGeometry = new StreamGeometry(); using (var ctx = backgroundGeometry.Open()) { CreateGeometry(ctx, innerRect, innerCoordinates); } _backgroundGeometryCache = backgroundGeometry; } else { _backgroundGeometryCache = null; } if (boundRect.Width != 0 && innerRect.Height != 0) { var outerCoordinates = new BorderCoordinates(cornerRadius, borderThickness, true); var borderGeometry = new StreamGeometry(); using (var ctx = borderGeometry.Open()) { CreateGeometry(ctx, boundRect, outerCoordinates); if (backgroundGeometry != null) { CreateGeometry(ctx, innerRect, innerCoordinates); } } _borderGeometryCache = borderGeometry; } else { _borderGeometryCache = null; } } }
private static void CreateGeometry(StreamGeometryContext context, Rect boundRect, BorderCoordinates borderCoordinates) { var topLeft = new Point(borderCoordinates.LeftTop, 0); var topRight = new Point(boundRect.Width - borderCoordinates.RightTop, 0); var rightTop = new Point(boundRect.Width, borderCoordinates.TopRight); var rightBottom = new Point(boundRect.Width, boundRect.Height - borderCoordinates.BottomRight); var bottomRight = new Point(boundRect.Width - borderCoordinates.RightBottom, boundRect.Height); var bottomLeft = new Point(borderCoordinates.LeftBottom, boundRect.Height); var leftBottom = new Point(0, boundRect.Height - borderCoordinates.BottomLeft); var leftTop = new Point(0, borderCoordinates.TopLeft); if (topLeft.X > topRight.X) { var scaledX = borderCoordinates.LeftTop / (borderCoordinates.LeftTop + borderCoordinates.RightTop) * boundRect.Width; topLeft = new Point(scaledX, topLeft.Y); topRight = new Point(scaledX, topRight.Y); } if (rightTop.Y > rightBottom.Y) { var scaledY = borderCoordinates.TopRight / (borderCoordinates.TopRight + borderCoordinates.BottomRight) * boundRect.Height; rightTop = new Point(rightTop.X, scaledY); rightBottom = new Point(rightBottom.X, scaledY); } if (bottomRight.X < bottomLeft.X) { var scaledX = borderCoordinates.LeftBottom / (borderCoordinates.LeftBottom + borderCoordinates.RightBottom) * boundRect.Width; bottomRight = new Point(scaledX, bottomRight.Y); bottomLeft = new Point(scaledX, bottomLeft.Y); } if (leftBottom.Y < leftTop.Y) { var scaledY = borderCoordinates.TopLeft / (borderCoordinates.TopLeft + borderCoordinates.BottomLeft) * boundRect.Height; leftBottom = new Point(leftBottom.X, scaledY); leftTop = new Point(leftTop.X, scaledY); } var offset = new Vector(boundRect.TopLeft.X, boundRect.TopLeft.Y); topLeft += offset; topRight += offset; rightTop += offset; rightBottom += offset; bottomRight += offset; bottomLeft += offset; leftBottom += offset; leftTop += offset; context.BeginFigure(topLeft, true); //Top context.LineTo(topRight); //TopRight corner var radiusX = boundRect.TopRight.X - topRight.X; var radiusY = rightTop.Y - boundRect.TopRight.Y; if (radiusX != 0 || radiusY != 0) { context.ArcTo(rightTop, new Size(radiusY, radiusY), 0, false, SweepDirection.Clockwise); } //Right context.LineTo(rightBottom); //BottomRight corner radiusX = boundRect.BottomRight.X - bottomRight.X; radiusY = boundRect.BottomRight.Y - rightBottom.Y; if (radiusX != 0 || radiusY != 0) { context.ArcTo(bottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); } //Bottom context.LineTo(bottomLeft); //BottomLeft corner radiusX = bottomLeft.X - boundRect.BottomLeft.X; radiusY = boundRect.BottomLeft.Y - leftBottom.Y; if (radiusX != 0 || radiusY != 0) { context.ArcTo(leftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); } //Left context.LineTo(leftTop); //TopLeft corner radiusX = topLeft.X - boundRect.TopLeft.X; radiusY = leftTop.Y - boundRect.TopLeft.Y; if (radiusX != 0 || radiusY != 0) { context.ArcTo(topLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise); } context.EndFigure(true); }