Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Optional rounded corner in RectangularPolygon #9

Open
Spawnkid opened this issue Dec 21, 2018 · 12 comments
Open

Feature Request: Optional rounded corner in RectangularPolygon #9

Spawnkid opened this issue Dec 21, 2018 · 12 comments

Comments

@Spawnkid
Copy link

Though this would work on images https://github.com/SixLabors/Samples/blob/master/ImageSharp/AvatarWithRoundedCorner/Program.cs this is not possible in Shapes where you need to use Pen (all paths should be closed). See attached sample
rounded dashed rectangle

It might be a good idea to add an optional parameter in RectangularPolygon constructor to have a radius value of the rounded corner. Thank You.

@ThaDaVos
Copy link

ThaDaVos commented Feb 5, 2019

Also really want something like this!
Any ETA

@antonfirsov antonfirsov changed the title Feature Request: Optional rounded corner in RectangularPolygon Shapes: Feature Request: Optional rounded corner in RectangularPolygon Jan 17, 2020
@antonfirsov antonfirsov changed the title Shapes: Feature Request: Optional rounded corner in RectangularPolygon Feature Request: Optional rounded corner in RectangularPolygon Jan 17, 2020
@antonfirsov antonfirsov transferred this issue from SixLabors/Shapes Jan 17, 2020
@JackSteel97
Copy link

Any progress on this? Or is there a workaround for drawing rectangles with rounded corners someone can point me to?

@antonfirsov antonfirsov added this to the Future milestone Dec 18, 2020
@JackSteel97
Copy link

JackSteel97 commented Dec 18, 2020

@antonfirsov This provides no options for positioning the new rectangle and no option to fill the rectangle either??

@antonfirsov
Copy link
Member

antonfirsov commented Dec 18, 2020

Positioning the new rectangle

You can transform IPathCollection with IPathCollection.Transform. Use it in tandem with Matrix3x.CreateTranslation

Fill the rectangle

Sorry second link was wrong in my previous comment. You can use imageProcessingContext.Draw(IPen pen, IPath path) for drawing the outline, and imageProcessingContext.Fill(IBrush brush, IPath path) to fill it.

@ggolda
Copy link

ggolda commented Mar 2, 2022

@antonfirsov could you please explain how to make those corners transparent? I need to draw one image atop of another and it should have rounded corners.

The only result that I can achieve using example above is colored corners. If Color.Transparent is provided they are not visible at all (obviously). Is there a way to use those corners as a mask and hide parts of image that they overlap?

@AndrewShepherd
Copy link

AndrewShepherd commented Jun 27, 2022

Here is method that converts a RectangularPolygon to a path with rounded corners.

Personally, I feel that implementing this as a user is straightforward enough, and this functionality needn't be baked into the core library.

private static IPath ApplyRoundCorners(RectangularPolygon rectangularPolygon, float radius)
{
	var squareSize = new SizeF(radius, radius);
	var ellipseSize = new SizeF(radius * 2, radius * 2);
	var offsets = new[]
	{
		(0, 0),
		(1, 0),
		(0, 1),
		(1, 1),
	};
	var holes = offsets.Select(
		offset =>
		{
			var squarePos = new PointF(
				offset.Item1 == 0 ? rectangularPolygon.Left : rectangularPolygon.Right - radius,
				offset.Item2 == 0 ? rectangularPolygon.Top : rectangularPolygon.Bottom - radius
			);
			var circlePos = new PointF(
				offset.Item1 == 0 ? rectangularPolygon.Left + radius : rectangularPolygon.Right - radius,
				offset.Item2 == 0 ? rectangularPolygon.Top + radius : rectangularPolygon.Bottom - radius
			);
			return new RectangularPolygon(squarePos, squareSize)
				.Clip(new EllipsePolygon(circlePos, ellipseSize));
		}
	);
	return rectangularPolygon.Clip(holes);
}

@inernoro
Copy link

inernoro commented Dec 11, 2023

Here is method that converts a RectangularPolygon to a path with rounded corners.

Personally, I feel that implementing this as a user is straightforward enough, and this functionality needn't be baked into the core library.

private static IPath ApplyRoundCorners(RectangularPolygon rectangularPolygon, float radius)
{
	var squareSize = new SizeF(radius, radius);
	var ellipseSize = new SizeF(radius * 2, radius * 2);
	var offsets = new[]
	{
		(0, 0),
		(1, 0),
		(0, 1),
		(1, 1),
	};
	var holes = offsets.Select(
		offset =>
		{
			var squarePos = new PointF(
				offset.Item1 == 0 ? rectangularPolygon.Left : rectangularPolygon.Right - radius,
				offset.Item2 == 0 ? rectangularPolygon.Top : rectangularPolygon.Bottom - radius
			);
			var circlePos = new PointF(
				offset.Item1 == 0 ? rectangularPolygon.Left + radius : rectangularPolygon.Right - radius,
				offset.Item2 == 0 ? rectangularPolygon.Top + radius : rectangularPolygon.Bottom - radius
			);
			return new RectangularPolygon(squarePos, squareSize)
				.Clip(new EllipsePolygon(circlePos, ellipseSize));
		}
	);
	return rectangularPolygon.Clip(holes);
}

this my test code

[Fact]
    public void ApplyRoundCornersTest()
    {
        var rect = new RectangularPolygon(0, 0, 100, 100);
        var path = ApplyRoundCorners(rect, 15f);
        var img = GetSquareRgba32(200, Color.Black);
        img.Mutate(w => w.Draw(Color.White, 1, path.Transform(Matrix3x2.CreateTranslation(50, 50))));
        img.ShowWithCoordinates();
    }

this your result

image

It is obvious that errors are inevitable in user code, even among experts

This is the rounded rectangle code I wrote, and I'm not sure if there might be any exceptions


    /// <summary>
    /// rounded rectangle
    /// </summary>
    /// <param name="width"></param>
    /// <param name="height"></param>
    /// <param name="cornerRadius"></param>
    /// <returns></returns>
    public static IPath CreateRoundedRectanglePath(int width, int height, float cornerRadius)
    {
        var pathBuilder = new PathBuilder();
        width--;
        height--;

        var radius = 2 * cornerRadius;

        // Make sure the rounded corners are no larger than half the size of the rectangle
        cornerRadius = Math.Min(width * 0.5f, Math.Min(height * 0.5f, cornerRadius));

        // Start drawing path
        pathBuilder.StartFigure();

        // upperBorder
        pathBuilder.AddLine(cornerRadius, 0, width - cornerRadius, 0);

        // Upper right rounded corner
        pathBuilder.AddArc(new RectangleF(width - radius, 0, radius, radius), 0, 270, 90);

        // right line
        pathBuilder.AddLine(width, cornerRadius, width, height - cornerRadius);

        // Lower right rounded corner
        pathBuilder.AddArc(new RectangleF(width - radius, height - radius, radius, radius), 0, 0, 90);

        // lower border
        pathBuilder.AddLine(width - cornerRadius, height, cornerRadius, height);

        // Lower left rounded corner
        pathBuilder.AddArc(new RectangleF(0, height - radius, radius, radius), 0, 90, 90);

        // left line
        pathBuilder.AddLine(0, height - cornerRadius, 0, cornerRadius);

        // Upper left rounded corner
        pathBuilder.AddArc(new RectangleF(0, 0, radius, radius), 0, 180, 90);

        // Close the path to form a complete rectangle
        pathBuilder.CloseFigure();

        return pathBuilder.Build();
    }

this my result

image

In today's UI design, the code for rounded rectangles is evident everywhere, omnipresent. I believe that a good core framework indeed needs to embed such codes that, despite appearing particularly simplistic or even foolish, are widely used. Though simple, their widespread usage is undeniable.

@JimBobSquarePants
Copy link
Member

Why are you shouting?

@inernoro
Copy link

Why are you shouting?

I'm merely stating the facts objectively. If you feel offended by what I said, I'm sorry

@inernoro
Copy link

It is indeed my issue, as the need to submit various styles can easily disrupt the layout, leading to some misunderstandings. In fact, my text is translated using translation software. I do not have an aggressive demeanor. Most of the time, what I state are things I already know. There are matters that I think could be handled more smoothly and flexibly, and I often consult others for advice, rather than instructing them on what to do. At this point, any answers or opinions given to me are reasonable. I apologize to you once again

@JimBobSquarePants
Copy link
Member

All good! I was very confused! 🤣

if someone has the time to provide a PR with tests let’s add the feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants