In the olden days, we used to build all these on top of a drawing abstraction layer with a very simple interface: put a point of color c at point x,y.
Then we wrote drawing classes for each type of object that were based on the low level API.
So there was a Point class that held a PointDrawer that it used when someone called its 'draw()' method. The PointDrawer knew about the Point internals to the extent that it could get the color, x and y and called the low level API to place the point on the display or the paper or to chisel it out of the granite block.
Then there was a Line calls that had a color and two x,y endpoints. The corresponding LineDrawer knew the internals of the Line object and could either create Point objects and tell them to draw themselves or it could call the low level API. This choice lay with the implementer. An alternative was that a new low level method could be added to the API to draw a line. So that made three choices, at three different levels, of how the LineDrawer would work to get the image up on the display.
For each new drawable object, Circle, Arc, Ellipse, Box, FilledBox, etc, there was a corresponding XxxDrawer held inside that did the drawing using some combination of the three levels.
Note that some displays had built in capability to draw arcs and some didn't. This made the choice a device dependent one so there would be a group of 'drawer' subclasses, usually, that would do it. So instead of a LineDrawer there might be a XyzSystems4453DeviceLineDrawer class, amoung others.
This is very confusing but it does allow drawing each thing to have maximum performance (useful if doing animation and you need 24 images per second times however 1000 many arcs there are in the image) plus it makes it pretty easy to add another device thats just like an existing one "except for ...". (You subclass and override the changed stuff, perhaps calling the overriden methods at times.) And if you keep your naming and packaging organized, you can keep the code organized as it grows.
This is all important given that we still, even with the increaed speed available in processors and graphics co-processors, can't draw all the details we need, in the time we have, without being very careful.