/// <summary>Rounded axis-aligned rectangle shape.</summary> /// <remarks>If the radius is 0, will create a normal rectangle instead. If the radius is too large compared to the rectangle, will create an ellipse instead. /// Depending on the arguments, may also create oval shape, 2 half circles joined by a rectangle.</remarks> public static iPathData roundedRectangle(Rect rect, Vector2 radius) { if (radius.X < 0 || radius.Y < 0) { throw new ArgumentException("Rounded rectangle radius must be non-negative"); } if (radius.X < 1E-4f || radius.Y < 1E-4f) { return(rectangle(rect)); } int collapsedFlags = 0; if (radius.X * 2 >= rect.width) { radius.X = rect.width * 0.5f; collapsedFlags |= 1; } if (radius.Y * 2 >= rect.width) { radius.Y = rect.height * 0.5f; collapsedFlags |= 2; } if (collapsedFlags == 3) { // Both horizontal and vertical sides are collapsed. This turns rounded rectangle into an ellipse. return(ellipse(rect.center, radius)); } eArcFlags af = eArcFlags.ArcSmall | eArcFlags.DirCounterClockwise; if (collapsedFlags == 0) { // Rounded rectangle PathBuilder builder = new PathBuilder(4 * 5 + 3 * 2, 4 + 3); using (var fb = builder.newFigure()) { // Starting fb.move(v2(rect.left + radius.X, rect.top)); // Top left fb.arc(v2(rect.left, rect.top + radius.Y), radius, 90, af); // Left fb.line(v2(rect.left, rect.bottom - radius.Y)); // Bottom left fb.arc(v2(rect.left + radius.X, rect.bottom), radius, 90, af); // Bottom fb.line(v2(rect.right - radius.X, rect.bottom)); // Bottom right fb.arc(v2(rect.right, rect.bottom - radius.Y), radius, 90, af); // Right fb.line(v2(rect.right, rect.top + radius.Y)); // Top right fb.arc(v2(rect.right - radius.X, rect.top), radius, 90, af); // No top line, close the figure instead fb.closeFigure(); } return(builder.build()); } if (collapsedFlags == 1) { // Oval with vertical lines float xCenter = (rect.left + rect.right) * 0.5f; PathBuilder builder = new PathBuilder(4 * 5 + 2, 4 + 1); using (var fb = builder.newFigure()) { // Starting fb.move(v2(rect.right, rect.top + radius.Y)); // Top right fb.arc(v2(xCenter, rect.top), radius, 90, af); // Top left fb.arc(v2(rect.left, rect.top + radius.Y), radius, 90, af); // Left fb.line(v2(rect.left, rect.bottom - radius.Y)); // Bottom left fb.arc(v2(xCenter, rect.bottom), radius, 90, af); // Bottom right fb.arc(v2(rect.right, rect.bottom - radius.Y), radius, 90, af); // No right line, close the figure instead fb.closeFigure(); } return(builder.build()); } if (collapsedFlags == 2) { // Oval with horizontal lines float yc = (rect.top + rect.bottom) * 0.5f; PathBuilder builder = new PathBuilder(4 * 5 + 2, 4 + 1); using (var fb = builder.newFigure()) { // Starting fb.move(v2(rect.left + radius.X, rect.top)); // Top left fb.arc(v2(rect.left, yc), radius, 90, af); // Bottom left fb.arc(v2(rect.left + radius.X, rect.bottom), radius, 90, af); // Bottom fb.line(v2(rect.right - radius.X, rect.bottom)); // Bottom right fb.arc(v2(rect.right, yc), radius, 90, af); // Top right fb.arc(v2(rect.right - radius.X, rect.top), radius, 90, af); // No top line, close the figure instead fb.closeFigure(); } return(builder.build()); } throw new ApplicationException("Unexpected"); }
void iFigureBuilder.arc(Vector2 endpoint, Vector2 size, float angleDegrees, eArcFlags flags) { ensureStart(); pb.addVec2(endpoint); pb.addVec2(size); pb.data.Add(angleDegrees); addPoint(eSegmentKind.Arc, (byte)flags); }