I have a few dozen rounded rectangles which I draw but frequently need to change the width of. I'm currently using the following (heavily simplified) class:
class RRPath
{
std::unique_ptr<GraphicsPath> pth;
bool newWidth{};
float xPos{};
PathData pd;
public:
RRPath()
{
GraphicsPath path;
path.AddArc(0.f, 12.f, 24.f, 24.f, 90, 90);
path.AddArc(0.f, 0.f, 24.f, 24.f, 180, 90);
path.AddArc(0.f, 0.f, 24.f, 24.f, 270, 90);
path.AddArc(0.f, 12.f, 24.f, 24.f, 0, 90);
path.GetPathData(&pd);
}
void setWidth(float tabW) { tabWidth = tabW; newWidth = true; }
GraphicsPath *getPath(float x) // return a GraphicsPath*, adjusted for starting position `x`
{
if (newWidth) mkNewPath();
Matrix m{ 1, 0, 0, 1, x - xPos, 0 };
pth->Transform(&m);
xPos = x;
return pth.get();
}
private:
void mkNewPath()
{
for (int i = 8; i < 19; i++) pd.Points[i].X += tabWidth;
pth = std::make_unique<GraphicsPath>(pd.Points, pd.Types, pd.Count);
for (int i = 8; i < 19; i++) pd.Points[i].X -= tabWidth;
xPos = 0.f;
}
};
It creates the PathData
in the contructor and creates a new path every time the width changes (which is frequently) Now, this works fine but it bugs me that it needs to delete and create a new path (on the heap) every time. The number of points in the path never changes so I'm thinking there should be a way to use only one path, created in the contructor, and adjust it as needed to increase the width without having to create a new path every time. The only thing done with the path is FillPath
.
Ok, seems like there's not much interest in this area, or at least not in this question. But I have been able to resolve it so I will post the answer here in case anyone is curious. I wasn't able to find a way to modify a GraphicsPath
however I was able to achieve the main result that being getting rid of the heap allocations.
The code below enables me to create a single rounded rectangle path and use it for numerous paths with different widths and horizontal positioning. It also runs around 20% faster.
class RRPath
{
GraphicsPath pth;
float prevW{}, prevX{};
protected:
GraphicsPath pS, pE;
public:
RRPath()
{
pS.AddArc(0.f, 12.f, 24.f, 24.f, 90, 90);
pS.AddArc(0.f, 0.f, 24.f, 24.f, 180, 90);
pE.AddArc(0.f, 0.f, 24.f, 24.f, 270, 90);
pE.AddArc(0.f, 12.f, 24.f, 24.f, 0, 90);
};
void setWidth(float w)
{
pth.Reset();
pth.AddPath(&pS, false);
Matrix m{ 1, 0, 0, 1, w - prevW, 0 };
pE.Transform(&m);
pth.AddPath(&pE, true);
prevX = 0.f;
prevW = w;
};
GraphicsPath *getPath(float offsetX)
{
Matrix m{ 1, 0, 0, 1, offsetX - prevX, 0 };
pth.Transform(&m);
prevX = offsetX;
return &pth;
};
};