Morphic graphics, Displaying fonts & canvases

Andreas Raab andreas.raab at gmx.de
Fri Apr 20 17:04:18 UTC 2007


You are looking at the problem from the wrong angle. If you want to 
change the way morphs are drawn you need to be looking at replacing 
Canvas, not DisplayMedium.

Canvases generally make little to no assumptions about their medium; 
they use abstract drawing commands (lines, rectangles, polygons) instead 
of using BitBlt directly. They also encapsulate their backend (which may 
or may not be a DisplayMedium). Some canvases (like the one used by the 
remote Nebraska sharing protocol) don't even have DisplayMedium to 
operate on. Etc.

In short: If you look to change the way morphs are drawn, look at Canvas 
and its subclasses. DisplayMedium is the wrong place for that.

Cheers,
   - Andreas

sig wrote:
> Hello squeak-dev,
> 
>  during my struggle to make morphic world be OpenGL ready i found
>  that current drawing protocols not providing a freedom in
>  selecting a methods on how the text/images is drawn on display.
> 
>  As i can see, the current graphics classes
>  (Canvas/DisplayScreen/Morph) is heavily relying on blitting
>  operations and (wrongly) assume that canvases and/or their display
>  mediums supporting them by default.
> 
>  First of all, DisplayScreen is a subclass of Form which is a
>  subclass of DisplayMedium.
>  A DisplayMedium comment reads:
>    I am a display object which can both paint myself on a medium
> (displayOn: messages),
>    and can act as a medium myself. My chief subclass is Form.
> 
>  This is wrong. I can give you tons of exapmles when display medium
>  represents a hard copy (take a look at the paper on you desk) and
>  can't be painted on other medium.
>  The printer can be considered as such medium to which you can draw
>  but can't draw a printed contents on other medium.
>  And i strongly presume that the DisplayScreen is such kind of
>  medium.
>  Even more, not all mediums can be represented as rectangular
>  area of pixels. Some of them can be presented as set of vectors
>  (vector displays) or other forms of drawings, and even have
> non-rectangular display surface.
>  And thats where we need a Canvas to draw on it.
> 
>  The drawing process by its nature is one way road and assuming that
>  we can freely draw between different mediums is totally wrong.
> 
>  So, at abstract level we must think of a Medium to which we can draw
>  by issuing commands through its Canvas. Nothing more.
> 
>  To simulate drawings from one medium into another we can use caching
>  canvas, which will collect all drawing commands and then pass them
>  to another canvas of target medium.
> 
>  All morphic drawing is built on top of this wrong assumption,
>  which prevents me to make a nice and clean replacement of Display to
>  allow morphs drawn using OpenGL.
> 
>  For making this possible there is need to make changes in many
>  places to conform different protocol(s).
> 
>  And here is my proposals:
>      Fix the DisplayMedium protocol by revoking assumption that it
>      can be drawn on other medium.
>      DisplayScreen class:
>      - make it a subclass of DisplayMedium, not Form.
> 
>      Canvas class:
>      - remove methods which based on assumtion that canvas is drawing
>      on top of Form. Refactor code which assumes such behavior.
> 
>      Since canvas represents capabilities of DisplayMedium i think
>      that first references to Canvas must appear there, and any drawing
>      on medium must be a drawing using canvas received from #getCanvas
>      message.
>      The method #defaultCanvasClass must be removed. You cannot
>      connect a canvas to different medium and cannot use two
>      independent canvases for drawing on the same medium because this
>      leads to breaking its current internal state.
>      For caching/clipping purposes there are protocol in canvas itself,
>      which can give you instances for such uses and since they refer to
>      the main canvas, the risk of breaking the medium internal state
> is minimal.
> 
>      For example, if morph wants to use a Form to draw itself into (as in
>      Morph>>#imageForm:forRectangle:), then it must
>      directly instantiate a Form and use #getCanvas to draw on it.
>      If there is need in a form having same depth as screen - use
>      Display>>depth. But note, message #depth for DisplayScreen must
>      be considered as a hint, not a part of Form protocol.
> 
>      In most cases, drawing in to independent form used for caching
>      purposes, when resulting image is then _blitted_ on the screen.
>      There is a class named CachingCanvas designed specially for
>      such purposes, and showing 0 references in my 3.9 image. Make a
>      conclusion :)
> 
>      So, returning back to the needs pre-cached drawing i think the
>      best way is to use Canvas protocol, so it can return an
>      instance of CachingCanvas or its subclass to cache the incoming
>      drawing operations.
> 
>      The caching canvas MUST be used by morphs and fonts.
>      Take a look at the TTCFont implementation, i cant look at it without
>      pain.. What do you think, is this the best way of drawing
>      true type glyphs using pre-cached bitmaps?
>      The authors of true type package made a great job by providing
>      TTF's for a squeak, but failed to make it in a really nice
>      fashion when glyphs are coming to draw on the screen.
>      This is another design flaw to which I would like to pay
>      attention. The protocol between Canvas and AbstractFont is need
>      to be redesigned in the way of using CachingCanvas for this
>      purposes.
>      Then there will be no need to introduce own bitmap cache what
>      is currently done in TTCFont class. And moreover, in case of
>      OpenGL a caching canvas is stored in video memory which greatly
>      improves performance when you need to copy it on the screen.
>      Displaying a string is simple set of commands which
>      draw part(s) of cached canvas(es) on the main canvas.
>      Comparing to Form(s), a caching canvas can store a list of
>      commands issued to it, instead of bitmap. And this can reduce
>      the memory usage and greatly improve speed, because of reducing
>      an excessive blitting operations.
> 
> 
>  I'd like to discuss all above metioned with you :)
> 
>  Meanwhile my current implementation of GLCanvas draws a World from 3 to 8
>  times faster than current Display. And i think it can be even faster.
>  I think that performance can be increased to such level to make it
> possible to draw
>  entire World in back buffer and still have decent frame rates.
> 




More information about the Squeak-dev mailing list