Click here to Skip to main content
16,016,962 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
My vector graphics in my graphics library includes a canvas that can be bound to a draw target like a bitmap.

Accessed off the canvas, you perform drawing operations like arcs and paths.

Here's the trouble. Each drawing operation has numerous options:

The stroke (which is the outline of the shape basically) - it has a color a width, line join, and line cap. Or the "color" can be a linear gradient, a radial gradient or a texture.

Then there's the fill, which has the same kind of properties on it, minus line join, stroke width and line cap.

I could
a) take all of this information as parameters to each draw arc, line, path, etc function. This is my least desirable option because it requires more work on behalf of the developer/user + more stack

b) create complex structs with unions in them for the colors, line caps, textures, and gradients.

c) have a "current stroke color", "current fill color", "current line cap" etc as accessors/"properties" off the canvas.

I'm torn between b and c, although if anyone has other ideas I'm open to hearing them, as long as you're not suggesting I redesign everything, as I worked on the design for days, and it's got some important compromises in it that I don't want to have to explain.

What I have tried:

I'll put an example of what I mean

a) canvas.arc(..., stroke_color, stroke_width, line_cap, line_join, fill_color, texture, gradient)


b) canvas.arc(..., const paint_info&) where paint_info is a complex struct that covers all the parameters.


c) canvas.stroke_color(color_t::green);canvas.stroke_width(10); etc.
Posted
Updated 7-Sep-24 11:28am
v2
Comments
0x01AA 7-Sep-24 11:23am    
Maybe the 'fluent api pattern' can help?
honey the codewitch 7-Sep-24 11:26am    
I had to look it up. I don't understand how separating it into two classes, one for setting the properties, and one for getting them makes anything easier, ever. It seems like an anti-pattern someone decided was a pattern. I noticed Microsoft came up with it, which doesn't help my estimation of it. I believe in KISS. I must be missing something about it, but I can't tell what. Edit: I guess it can be used to make it so only things that can access the setter class can change the data, but that's what access modifiers are for?
0x01AA 7-Sep-24 12:11pm    
You are right. I was only focused on Setters which is completely stupid from my side.
honey the codewitch 7-Sep-24 12:12pm    
No worries! I thought I was missing something big.

If I were using this as a consumer, I would rather use a union of options so I have the flexibility to layer things together in ways that you might not think of as the library author.
 
Share this answer
 
You could also mix (b) with (c). I mean you could use a complex struct to initialize the canvas and then use simpler structs (or just parameters) as arguments to the methods.
 
Share this answer
 
Comments
honey the codewitch 6-Sep-24 15:57pm    
This is what I ended up doing so I accepted this solution. Thank you.
CPallini 8-Sep-24 4:48am    
You are very welcome.
Or you create an interface or base class which has a
C++
void draw(Canvas &canvas)
So every object is drawing itself.
When you have a common base class than you can use an array or container to store the objects.

tip: when transfering objects or structs take care to use reference or pointer syntax to not create new instances in calls.
 
Share this answer
 
Comments
honey the codewitch 7-Sep-24 17:25pm    
No. I told you I'm not accepting redesigns. Can you not read?

Tip: I was already passing const references to structs. Edit: I updated the typo in my question. It wasn't relevant to the solution at hand.

I asked you not to respond to any more of my questions. I wasn't kidding.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900