Canvas is-an Encoder?

Marcel Weiher 320089961391-0001 at t-online.de
Wed Jun 28 09:35:49 UTC 2000


> From: "Lex Spoon" <lex at cc.gatech.edu>

>
> Why is Canvas a subclass of NullEncoder and FlattenEncoder, lately?  It 
> seems to be something added to make the Postscript support work,  
but the
> solution seems kinda strang--Encoding and drawing really seem like 
> separate issues to me.  For example, should the same class implement 
> drawCircle: and initWithTarget:?  fillRectangle: and writeObject: ? 

Ahem, yes, it should, but the isa relationship could still be  
removed as things are right now.

The ping-pong double-dispatch mechanism that the encoders make  
available is actually very useful for a display situation, so useful  
that a less generic version of the same mechanism has been  
independently added to Canvas.  Of course, IMNSHO it would be much  
cooler to just reuse the encoder's version, because that's why I put  
it there!

On the history of the mechanism, Dan's paper describing this  
mechanism (early 80ies, I think) actually used graphical 'ports' as  
its running example, IIRC.

When you think about the display process more closely, it starts to  
make a lot of sense, because how to display an object is something  
that actually has to be "negotiated" between a specific display and a  
specific object, and it is also an encoding task.  Descriptions of  
graphical objects are encoded into commands to drive a display,  
wether these commands happen to be direct calls to routines, encoded  
commands to display accelerators.

The "negotiation" phase also makes a lot of sense because often  
times an optimization that is vital for one type of display yields to  
unacceptable output for a different type.  Encoding all this behind  
an opaque interface is possible, but letting display and/or object  
adapt is a much more squeaky solution.  What's more, specialized  
algorithms/capabilities/hardware can be taken advantage of between  
specific objects and specific displays (always taking "display" to  
mean some sort of graphical output device or format).

The generic #writeObject: interface makes it possible to reuse code  
in a wide variety of different circumstances.  For example,  
Canvas/Morph currently have specific code to render the submorhs,  
traversing the collection.  This code is redundant because  
'flattening' object hierarchies is what the FlattenEncoder does,  
except that it does it for all sorts of different applications, not  
just a canvas.  It can do this for all these different circumstances  
because #writeObject: will automatically do the right thing for the  
subobjects and the actual encoder.  It's not a big thing, but these  
'flattening' patterns occur all over the image, whereas this one  
implementation would actually suffice.

> With multiple inheritance, it would seem reasonalbe to have
> PostScriptCanvas be a subclass of both Canvas and Encoder.  But as 
> things are, making Canvas a subclass of Encoder just for Postscript's 
> sake seems strange.  Why not just have an 'encoder' instance  
variable in
> PostscriptCanvas?

It's not really just for Postscript's sake, although at present it  
looks that way because the functionality that is provided is not  
used, but rather duplicated.  Call me biased, but it makes more sense  
to me to remove the duplication...

Marcel





More information about the Squeak-dev mailing list