Check out the new USENIX Web site. next up previous
Next: The Libart Imaging Model Up: Delayed Update/Redraw Model Previous: Delayed Update/Redraw Model

Delayed Updates

We have not explained how the canvas actually figures out the area that needs to be repainted. Let us consider a few simple cases:

  1. A solid-colored rectangle with dimensions $(w, h)$ is translated with offsets $(dx, dy)$ such that $\vert dx\vert < w$ and $\vert dy\vert < h$. In this case, the minimal redraw area consists of two L-shaped regions that are the symmetric difference between the old and the new rectangles (see Figure 1).

    Figure 1: When a solid-colored rectangle moves, the redraw area consists of two L-shaped regions.
    \begin{figure}
\begin{center}
\psfig {file=rect-move.eps,width=3.0in} \end{center}\end{figure}

  2. A solid-colored rectangle changes color. In this case, the whole area occupied by the rectangle needs to be redrawn.

  3. A solid-colored circle changes radius. The minimal redraw area thus consists of the donut-shaped region which is, again, the symmetric difference between the old and new circles.

  4. Some characters in a string of text are changed, for example, when the user is editing a label. If the string is drawn using a monospaced font, the minimal redraw area consists of the area occupied by the characters that changed. If the string is drawn using a proportional font, the redraw area will be more complicated.

One of the goals of the canvas is to compute the minimal redraw area for each operation. This is important because we wish to make the final bitblt operations as small as possible; experiments have shown that memory bandwidth tends to be a bigger problem than CPU speed.

Canvas items have two important methods, ::update() and ::draw()1. The former is reponsible for calculating the area that needs to be redrawn when the item's attributes change, and the latter gets called when the final redraw area has been computed by the canvas and an item needs to paint itself.

The full sequence of operations that starts when an item's attributes are changed and ends when the canvas paints to the screen is as follows:

  1. A state change happens in a canvas item, usually from direct manipulation through the user interface. An item may thus change attributes like color or position.

  2. The canvas item stores an iternal flag saying that it needs to change one of its attributes, and also stores the necessary information to change that attribute. For example, an item may store ``I need to change my fill color to blue'', or ``my radius changed to 7.5 units''.

  3. The canvas item then queues an update from the canvas using the gnome_canvas_item_request_update() function. The canvas installs an idle handler on the GTK+ main loop.

  4. The application keeps running, possibly requesting attribute changes from other items, until it finishes its work and all its interaction-related tasks, and gets back to the idle loop.

  5. The idle handler for the canvas is run. The canvas calls the ::update() method of each item that requested an update.

  6. The ::update() method for an item flags the item as no longer needing an update. It should recalculate the item's internal state based on the flags set in step 2, for example, by changing colors or line styles in an X graphics context (GC). This method is also responsible for recomputing the item's bounding box if the item's bounds changed. Then, it should queue a redraw from the canvas based on its new state. We will later describe how this area is represented.

  7. After all items that need it have been updated, and as such they have recomputed their bounding boxes and queued the appropriate redraws, the canvas calls the ::draw() or ::render() method of items that need it. This method is passed a temporary pixmap in the case of a canvas in GDK mode, or an RGB pixel buffer in the case of an antialiased canvas.

  8. The canvas is now fully updated and redrawn, and the application continues to run.

As we have seen, the ::update() method is responsible for doing housekeeping work like changing GC colors and line styles, recomputing an item's bounding box, and queueing the proper redraws. This method is called from the canvas' idle handler. The reason for delaying GC updates and the like to the idle loop is that an application may change many attributes of a canvas item before getting back to the idle loop; if the item changed GCs or recomputed its bounding box for every time an attribute was changed, this could turn into a performance problem, since many such operations are expensive. Delaying all the updating work until the idle loop means that the application's interaction with items has finished, so the items know their final state at that point and can compute the most efficient way to do their respective updates.


next up previous
Next: The Libart Imaging Model Up: Delayed Update/Redraw Model Previous: Delayed Update/Redraw Model
Federico Mena Quintero
2000-05-08