Hi there,
i am working on a Cairo[1] backend for mcclim. While doing so i noticed two issues with the current implementation of displayed-output-records:
a) displayed-output-records want to store transformed graphics. It however is not always possible to fully transform a graphics request. This most notably is the case with DRAW-TEXT* while :transform-glyphs is non-NIL.
Also line styles are hard to transform.
I recognize that that storing transformed graphics request seems easier from the perspective of the CLX backend, since CLX itself can't do transformations; so you need to transform the graphics request anyway before hitting the backend. This however looks different from the perspective of the Cairo backend (and also of the PS backend and a possible OpenGL), as these graphics systems can perfectly well transform graphics requests.
[In case of OpenGL they perhaps can do this even faster than we will ever be due to HW acceleration].
b) the bounding boxes are not always quite correct. Which I believe is because of anti-aliasing, since some pixels at the border of a shape spill over.
PROPOSAL
I propose that we open an opportunity for the backend to implement its own output recording classes. Which would have the following benefits:
- bounding boxes are likely to be correct (E.g. the Cairo backend can tell me the bounding box of graphics requests).
- the backend can decide if it is more economic to store transformed or untransformed coordinates.
- the backend perhaps has a faster way to capture, save and restore the drawing options of a medium than we can have sticking to the medium protocol.
- the backend can decide on the representation of the graphics request. E.g. it might want to save the fully tessellated representation of a shape, it might want to keep references to rasterizied ink in case of drawing with patterns, it might construct display lists. etc.
PROTOCOL
We could specify MEDIUM-RECORD-xyz* methods to complement MEDIUM-DRAW-xyz, like this:
MEDIUM-RECORD-LINE* medium x1 y1 x2 y2 drawp recordp [Generic Function]
If /drawp/ is non-NIL, behave as MEDIUM-DRAW-LINE*.
If /recordp/ is non-NIL, return a displayed output record which, when replayed has the effect or MEDIUM-DRAW-LINE* with the given arguments and the current drawing options installed in /medium/.
Since some work to be done on recording and drawing perhaps is similar, i chose to go with this combined record and/or draw protocol function.
We could specify that an implementation of MEDIUM-RECORD-LINE* for a medium is optional and that a default implementation is provided by CLIM.
So the implementation of MEDIUM-DRAW-LINE* on output recording streams would look like this:
(defmethod medium-draw-line* ((stream output-record-stream) x1 y1 x2 y2) (let ((record (medium-record-line* stream x1 y1 x2 y2 (stream-drawing-p stream) (stream-recording-p stream)))) (when (stream-recording-p stream) (stream-add-output-record stream record))))
Before heading to implement this, i wanted to gather some comments on this.