Ejemplo n.º 1
0
        /// <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");
        }
Ejemplo n.º 2
0
 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);
 }