Can I specify the radius of each corner of a rounded rectangle?

Viewed 76

In Direct2D, rounded rectangle geometry can be created this way:

D2D1_ROUNDED_RECT rq = {0};
rq.rect.left = 0;
rq.rect.top = 0;
rq.rect.right = 100;
rq.rect.bottom = 100;
rq.radiusX = 5;
rq.radiusY = 5;

factory->CreateRoundedRectangleGeometry(rq, &geometry);

Where radiusX and radiusY are confusing me, because I can't understand how two values can independently describe 4 (4 rectangle corners radiuses).

Can I set each corner's radius separately like that, or do I need to do it manually using CreatePathGeometry() instead?

2 Answers

According to the documentation, radiusX and radiusY are the radii for the quarter ellipse that are drawn in every corner.

You are not specifying the radius for every corner but for all of them at once. When radiusX is larger than radiusY, it's essentially a rounded rectangle that looks "squished".


If the radii are larger or equal to the half size of the rectangle, it'll be drawn like a regular ellipse that you would draw with D2D1_ELLIPSE.

Here is code for rounded rectangle with ability to specify each corner separately

ID2D1PathGeometry *CreateRoundRect(int x, int y, int width, int height, int leftTop, int rightTop, int rightBottom, int leftBottom)
{
    ID2D1GeometrySink* sink = nullptr;
    ID2D1PathGeometry* path = nullptr;

    factory->CreatePathGeometry(&path);
    path->Open(&sink);
    
    D2D1_POINT_2F p[2];

    p[0].x = x + leftTop;
    p[0].y = y;
    sink->BeginFigure(p[0], D2D1_FIGURE_BEGIN::D2D1_FIGURE_BEGIN_FILLED);
    p[1].x = x + width - rightTop;
    p[1].y = y;
    sink->AddLines(p, 2);

    p[0].x = x + width;
    p[0].y = y + rightTop;

    if (rightTop)
    {
        D2D1_POINT_2F p2 = D2D1::Matrix3x2F::Rotation(0, p[1]).TransformPoint(p[0]);
        sink->AddArc(D2D1::ArcSegment(p2, D2D1::SizeF(rightTop, rightTop), 0, D2D1_SWEEP_DIRECTION_CLOCKWISE, D2D1_ARC_SIZE_SMALL));
    }

    p[1].x = x + width;
    p[1].y = y + height - rightBottom;
    sink->AddLines(p, 2);
    
    p[0].x = x + width - rightBottom;
    p[0].y = y + height;

    if (rightBottom)
    {
        D2D1_POINT_2F p2 = D2D1::Matrix3x2F::Rotation(0, p[1]).TransformPoint(p[0]);
        sink->AddArc(D2D1::ArcSegment(p2, D2D1::SizeF(rightBottom, rightBottom), 0, D2D1_SWEEP_DIRECTION_CLOCKWISE, D2D1_ARC_SIZE_SMALL));
    }

    p[1].x = x + leftBottom;
    p[1].y = y + height;
    sink->AddLines(p, 2);

    p[0].x = x;
    p[0].y = y + height - leftBottom;
    if (leftBottom)
    {
        D2D1_POINT_2F p2 = D2D1::Matrix3x2F::Rotation(0, p[1]).TransformPoint(p[0]);
        sink->AddArc(D2D1::ArcSegment(p2, D2D1::SizeF(leftBottom, leftBottom), 0, D2D1_SWEEP_DIRECTION_CLOCKWISE, D2D1_ARC_SIZE_SMALL));
    }


    p[1].x = x ;
    p[1].y = y + leftTop;
    sink->AddLines(p, 2);
    p[0].x = x + leftTop;
    p[0].y = y;
    if (leftTop)
    {
        D2D1_POINT_2F p2 = D2D1::Matrix3x2F::Rotation(0, p[1]).TransformPoint(p[0]);
        sink->AddArc(D2D1::ArcSegment(p2, D2D1::SizeF(leftTop, leftTop), 0, D2D1_SWEEP_DIRECTION_CLOCKWISE, D2D1_ARC_SIZE_SMALL));
    }
    
    sink->EndFigure(D2D1_FIGURE_END::D2D1_FIGURE_END_CLOSED);
    sink->Close();
    SafeRelease(&sink);

    return path;
}
Related