The idea of allowing a step where the geometry is preprocessed is a good one.
The SE 1.1 specification expands the number of well known transformations that can be applied (such as allowing a buffer in ground units in order to turn a point into a polygon). The ground units really establishes this as a geometry transformation rather than just a simple styling option (previously you would set up an interesting buffer expression based on the scale of the map; and even that would just be approximate).
A second example comes from the mapserver community where they have defined a set of well known transformations:
In particular the idea of getting the first and last point from a line string is interesting (rather than just asking for a line to be rendered with a point symbolizer and getting the a point at the midway along the line as per the SLD 1.0 specification). This approach paves the way for using a "percentage" along a line; finally offering a way to treat "linear referencing system" data as a rendering time option which would be great.
There are two sensible places this can be integrated:
at the feature type style level; we could define a well known transformation and have it apply to an entire block of symbolizers
* at the symbolizer level - by introducing Symbolizer.getGeometry()
This approach is consistent with how property name is handled in filters; and allows for:
Expression.NIL - to be used to indicate the default geometry
* PropertyName - to be used to indicate the indicated geometry
* Function - used to transform a geometry prior to be drawn
One consequence of this approach is that the rendering system may have difficulty figuring out the area to request data for.
Please note this is not a new problem: Any renderer implementation has already encountered this problem in the case of handling a point symbolizer buffer; the size of the buffer must be considered. An implementation will need to buffer the area of the screen in order to request all the points that may be visible on the screen after the buffer operation has been applied.
By setting up a function expression implementations should be able to account for this kind of adjustment by using the expression against a polygon the size of the screen. While this will not work with functions like "centroid" it should work with functions like "buffer".
apply the expression to the screen area; and union the result with the current screen area
* detect functions that are well known to your implementation
* mark functions that you expect to behave with an additional method:
Extent prepairQueryExtent( Extent )