Hey Andrea,
Follow some comments, in particular I think that what you wrote about transformations is wrong.
I'm pretty certain about my interpretation of how mediums behave (it is reinforced by hours of tinkering with the console backend). As of sheets and their transformations -- I think it that the topic is underspecified; it might be that my understanding is lacking and/or incorrect. IMO it is important to keep a separation between mediums and sheets in mind. That is: medium is an entity on its own rights and the sheet interface is built on top of it (that is when interpeting mediums we should not into account sheet specification).
- with-output-to-pdf-stream
- with-output-to-ps-stream
- with-output-to-raster-image-stream
Ok so your suggestion is to modify the actual WITH-OUTPUT-TO-PDF-STREAM macro without introduce new WITH-OUTPUT-TO-PDF-FILE macro, I will try to do it.
Preciesly. Thank you.
- transformation and region machinery
Is it the transformation and region machinery correct? Or it is works only in some standard situaions? For example I think that we could obtain a Zoom effect simply by: (setf (sheet-transformation some-sheet) (make-scaling-transformation 1.5 1.5)) but this doesn't work on McCLIM (I try it in the listener demo of clim-tos and there it works). Follow some more specific topics:
I did not investigate how the zooming effect could be conformingly achieved, but I think that modifying the SHEET-TRANSFORMATION is not the way to do that. If I were speculating I'd be more inclined to tinker with the medium transformation. No guarantees it will work (even if it is allowed by the spec which I'm not sure it is).
Why not? If you change the medium-transformation instead of sheet-transformation you can not obtain zoom effect because in the replay of output-record the medium-transformation is not take in account. The Spec. (16.2) says for replay-output-record:
"Displays the output captured by the output record record on the output recording stream stream, exactly as it was originally captured (subject to subsequent modifications). The current user transformation, line style, text style, ink, and clipping region of stream are all ignored during the replay operation. Instead, these are gotten from the output record."
The "user transformation" *is* the medium-transformation as stated in the Spec (10.1):
" medium-transformation medium [Generic Function]
The current user transformation for the medium medium. This transformation is used to transform the coordinates supplied as arguments to drawing functions to the coordinate system of the drawing plane. See Chapter 5 for a complete description of transformations. The :transformation drawing option temporarily changes the value of medium-transformation. "
10.1 talks about drawing on the sheet. medium-transformation transforms coordinates supplied to the drawing function to coordinates of the mirror on which we draw (putting aside the question that are device coordinates or native coordinates). When drawing operation is performed on the output recording stream, then medium-transformation is recorded and then it is reinstationed when we replay the output record (so the current transformation is indeed ignored).
(with-drawing-options (stream :transformation *drawing-transformation*) (draw-rectangle* stream 0 0 10 10))
(with-drawing-options (medium :transformation *ignored-transformation*) (replay stream))
That does not mean that replaying output records is done with the medium-transformation set to +identity-transformation+. It means, that the transformation from the *time of drawing* is used. So when we replay the output record, medium-transformation is *drawing-transformation*. Same goes for other recorded medium components. What exactly is recorded depends on the output record class.
It is implemented as an around method on replay-output-record specialized on gs-transformation-mixin. There is a catch though: basic-medium eagerly transforms coordinates, so backends are not expected to apply the medium-transformation to coordinates (unless their medium does not inherit from the basic-medium[1]). That's why zooming is not easy to achieve. That's also why hardware transformations would require custom medium. I'm positive though that both could be implemented (and zooming would be easier).
[1] "An :around on basic-medium for each of the drawing functions will have already transformed the user coordinates to medium coordinates before the most specific, implementation-dependent method is called." -- 12.7.2 Medium-specific Drawing Functions.
4a) Setting sheet-native-transformation:
McCLIM set directly the SHEET-NATIVE-TRANSFORMATION with %%SET-SHEET-NATIVE-TRANSFORMATION. I think this is not correct the sheet-native-transformation must be computated and only cached never set directly, otherwise you can lost the parent trasformation.
It is an internal interface which makes possible to update a native transformation when we update the mirror geometry. You are right that it should never be used to change the native transformation, it is only used to update it when it changes (when we know what we are doing). %% prefix means "dangerous".
the sheet-native-transformation method already have the caching mechanism. I think that the only things to do when we update the mirror geometry is to invalidate-cached-transformations and invalidate-cached-regions. The next call of sheet-native-transformation will recompute it.
You are right that invalidating cache would be correct. %%set-sheet-native-transformation is used as an optimization. i.e docstring of update-mirror-geometry which uses it:
"This function reflects the current sheet region and sheet transformation to the mirror. It also sets up the native transformation. This function is supposed to be called whenever one of the following happens:
- the sheet's transformation changed - the sheet's region changed - the parent's native transformation changed - the parent's transformation changed - the parent's mirror region changed
Also if the sheet's native transformation changes, the mirror's contents need to be redrawn, which is achieved by calling PORT-DIRTY-MIRROR-REGION. TODO is this true?
Since changing the sheet's native transformation might thus be expensive, this function tries to minimize changes to it. (although it does not try very hard)."
This writer method is also used in a macro which allows swapping mirrors (which is an ugly hack w which should go!).
I think this is not right respect to Spec and certainly is not what McCLIM does. Try yourself open a clim-listener move the window in some place of the screen and try: (sheet-native-tranformation (frame-top-level-sheet *application-frame*)) I always have the identity transformation as answer.
Thank you for elaborating on parts. You've certainly convinced me that my rationale about transformations has holes, I'm not sure what is the right behavior anymore. If you create an issue on github we may move he discussion there. Before we move forward with code changes we need to get a common understanding of which coordinate system does what. I need to do some reading on my part (most notably 8, 10 and 12 chapters of the spec), but currently we have some open PRs and I don't think I have enough energy to jump at that now.
Best regards, Daniel
-- Daniel Kochmański ;; aka jackdaniel | Przemyśl, Poland TurtleWare - Daniel Kochmański | www.turtleware.eu
"Be the change that you wish to see in the world." - Mahatma Gandhi