I've been working on graphics support in my backend code and have a couple questions.
What are the intended side effects of the TEXT-STYLE-*** methods, if any? Are they solely intended to answer "what-if" questions, e.g., "what would the ascent be if the font was :fixed and :bold ?" Or are they also meant to update the medium's text style attributes, as I see the gtkairo backend doing? Since one can add :before/:after methods on (SETF MEDIUM-TEXT-STYLE) to synchronize the underlying graphics context -- and presumably such a style attribute update necessitates repainting -- is that sufficient or should I really be planning on synchronizing attributes anywhere that styles are passed as arguments?
MEDIUM-DRAW-TEXT* appears to be called for each character in the string to be rendered. I gather that a backend is expected to be able to buffer such operations (see next question). But from looking at backtraces, the cause seems to be CL:WRITE-STRING processing the output stream one char at a time. I'm running on CLISP, so perhaps you lucky SBCL folks have your string output processed in batches. I take it that the use of WRITE-STRING is a consequence of CLIM's stream output model?
More generally regarding output buffering, I see the MEDIUM-FINISH-OUTPUT and MEDIUM-FORCE-OUTPUT methods and can easily imagine how my backend code might implement those. I also notice the public WITH-OUTPUT-BUFFERED macro and that it communicates with the backend by way of MEDIUM-OUTPUT-BUFFERING-P. Based on what I'm seeing so far just with text output, I'm sort of inclined to implement double-buffering unconditionally. Is that a bad idea, or am I missing a level of abstraction between McCLIM's idea of buffering and my backend's idea of buffering?
Thanks.
Quoting Jack Unrue (jdunrue@gmail.com):
What are the intended side effects of the TEXT-STYLE-*** methods, if any? Are they solely intended to answer "what-if" questions, e.g., "what would the ascent be if the font was :fixed and :bold ?" Or are they also meant to update the medium's text style attributes, as I see the gtkairo backend doing? Since one can add :before/:after methods
Those are "what-if" functions. All the SYNC-* operations in Gtkairo update the cairo context state for the current medium state before using cairo only as a matter of principle. (In this case, it is not even the current medium's cairo context, these operations get directed to an extra cairo context.)
The medium is probably just an argument to this function because it serves as the class to dispatch on. The existing backends do not even take the medium's transformation into account.
on (SETF MEDIUM-TEXT-STYLE) to synchronize the underlying graphics context -- and presumably such a style attribute update necessitates repainting -- is that sufficient or should I really be planning on synchronizing attributes anywhere that styles are passed as arguments?
Well, the font metric functions are the only special case where there is such an argument.
But for all other functions, synchronizing the graphics context should be possible in the way you are suggesting. Gilbert tried to explain to me why the cairo medium does not do that, and I have to admit that I did not understand his explanation. It had something to do with DO-GRAPHICS-WITH-OPTIONS-INTERNAL.
More generally regarding output buffering, I see the MEDIUM-FINISH-OUTPUT and MEDIUM-FORCE-OUTPUT methods and can easily imagine how my backend code might implement those. I also notice the public WITH-OUTPUT-BUFFERED macro and that it communicates with the backend by way of MEDIUM-OUTPUT-BUFFERING-P. Based on what I'm seeing so far just with text output, I'm sort of inclined to implement double-buffering unconditionally. Is that a bad idea, or am I missing a level of abstraction between McCLIM's idea of buffering and my backend's idea of buffering?
Your backend would be in good company. ;-) Gtkairo also assumes that any sort of buffering is always okay and completely ignores MEDIUM-OUTPUT-BUFFERING-P. Since MEDIUM-FORCE-OUTPUT and PORT-FORCE-OUTPUT get called by the frontend, things tend to work anyway. Gtkairo keeps track of the mediums that have been touched and processes them all in PORT-FORCE-OUTPUT.
The current double buffering implementation in Gtkairo (enabled only on Windows because it creates those huge pixmaps and ends up being rather slow for large panes) never draws to windows directly at all. It always draws to the pixmaps, then bitblts the pixmap to the window in the event loop. That was necessary because GTK+ didn't seem to like all that drawing happening outside of the event loop.
David