History and design
There was a great need for a canvas in the wxWidgets Library. Robert Roebling started something called wxCanvas and soon I took over. The original wxCanvas was pixel based and the idea was to render the primitives directly into an RGB buffer. However I realized that this path would be difficult to follow.
Abstract Drawing Context for vector drawings
I therefore decided to create an abstract Drawing Context that uses the native API for drawing, but be implemented in a way that catered for different drawing methods. So now it is a matter of implementing another derived drawing context in order to draw to a different device, window or pixel buffer. The drawing context is specifically designed for drawing vectors in relative world coordinates. The relative here means that an affine transform can be set to the drawing context. Everything drawn will be transformed with that matrix first. To achieve speed, this is combined with the world to device coordinates transformation. The style properties of primitives are pointer based, reference counted and derived from abstract classes. This makes it easy to add new style types. More importantly style changes can be quickly compared, and updated if a change in style is required.
Multi Document Multi View
After a while I decided to build the a2dCanvas and other classes on top of the wxWidgets DocView classes, but soon realized, I would not be able to do that with the existing wxWidgets DocView classes. After a lot of developmet and experimentation the new revolutionary wxArt2D document/view/commandprocessor framework came to life. This change made it possible to add views like a2dCanvasView to a library, and let the user application display a desired View to a Window. Moreover, an extensive range of events are distributed, which help the application in having them handled within the framework. The main idea of the DocView framework, is that the drawing primitives are stored in a document and that several views can be created to view desired parts of the document. The a2dCanvasDocument is a document containing the graphical data and consists of a display list of graphical primitives. Each Graphical object is derived from a a2dCanvasObject class, and this class can have child objects and properties. A document contains one root a2dCanvasObject, and the rest of the document's graphical content is included by adding nested children to this root object. Each a2dCanvasObject has a transform matrix to place itself in the world coordinate system relative to its parent object, with each child object placed relative to the object itself.
The drawing context, which is a derived view, and the document, interact in such a manner that changed objects are redrawn automatically and efficiently. The key is bounding boxes which are maintained throughout the drawing hierarchy. Only objects overlapping the drawing boxes of the changed objects will be redrawn.
Another required need was in being able to draw the same sub drawing in several places without having to duplicate the drawing, this is achieved by reference counting pointers to a2dCanvasObject. In this way it is possible to add the same a2dCanvasObject ( and its children) to two parent objects. During the rendering, paths from both parents will be followed and this will result in the same object being drawn at two positions.
The same reference counting system is used for properties to a2dCanvasObjects. All style properties like colour for filling and stroking are implemented as dynamic properties, and objects that have no properties will not use memory space for them.
From the beginning, I wanted to be able to place objects on layers, and have the layers drawn in a set order. In this way the layer order defines how objects are stacked. All objects on a layer (and nested objects if desired) are drawn in a row, followed by the next layer etc.
Every a2dCanvas which displays part of a document, can have tools plugged into it. The events are redirected from the canvas to the tools. There are a broad range of tools to interactively draw primitives and change views. They are stacked based, making it possible to pan and zoom whilst busy drawing.
Object can have editing implemented, all editing data needed is implemented using dynamic properties, and therefore only uses memory space when the object is being edited. Because of the stack based nature of the tools, editing tools can also recursively edit children of a2dCanvasObject. This makes it possible to implement editing of complex object like curves in a plot.