To Draw | ! To Draw in an Expose Handler



splitting this out into its own thread...

    >
    >   2) option 2 is simply impossible to make a one-to-one calculation
as to
    > which pixels must be refreshed, programmatically.

    for many (perhaps even for an overwhelming majority of applications (2)
    works just fine. if you application can't do this cheaply, then your
    approach is the right way.

Sorry, I can't think of a single application responsible for making its
own drawings by hand where option 2 is not crazy hard.  (If anybody has an
example of this in real-world application, please post?)

(Paul, would you be willing to take the scribble code from gtk-demo and do
this, including any user additions?  Surely for such a trivial example of
drawing option 2 should be easy?)

Taking my very simple example of two lines at the midpoints and two
diagonals corner to corner, taking option 2 makes our expose handler:

gboolean exposeME(GtkWidget *da, GdkEventExpose *event, gpointer *nil)
{
 int w = da->allocation.width;
 int h = da->allocation.height;
 GdkGC *gc = da->style->fg_gc[GTK_WIDGET_STATE(widget)]

 if (event->width == w && event->height = h)
 { // draw entire area
   gdk_draw_line(da->window, gc, w/2, 0, w/2, h);  // vertical
   gdk_draw_line(da->window, gc, 0, h/2, w, h/2);  // horizontal
   gdk_draw_line(da->window, gc, 0, 0, w, h);      // diagonal
   gdk_draw_line(da->window, gc, 0, h, w, 0);      // diagonal
 }
 else
 { // only a partial invalidation
   // figure out what drawing commands to issue according
   // to event->x, event->y, event->width, and event->height
   // (for every combination possibility)
   // not so hard for our mid-point lines, but for the diagonals?
   // INSANE!

   // don't forget to include any user additions
 }
 return TRUE;
}

This solution will cost us:
  1) programming time to manage all possibilities and debug, with no real
guarantee that it will work everywhere all the time.
  2) extra CPU usage to make all computations to determine what should be
redrawn.
  3) extra CPU usage to re-draw what was already once drawn.

(And in the case where the entire drawing area is obscured and re-exposed,
we have to draw the whole thing all over again!)

And you're saying that, for some reason I still don't quite understand,
the above is proper GTK+ programming while the following is not?:

gboolean exposeME(GtkWidget *da, GdkEventExpose *event, gpointer *nil)
{
 GdkGC *gc = da->style->fg_gc[GTK_WIDGET_STATE(widget)]

 gdk_draw_drawable(da->window, gc, pmap,  // pmap = our own bg pixmap
                   event->area.x, event->area.y,
                   event->area.width, event->area.height);
 return TRUE;
}

Oh yeah, and when taking this option we have covered all possibilities
100% of the time with 100% accuracy and 100% efficiency.  Really?  This
isn't the preferred solution?

    > If the third option is how GTK+ handles this scenario (more kudos...),
    > then the expose handler would look something like?:

    no, GTK discards the bg pixmaps between exposes. they exist primarily to
    improve the visual appearance of the GUI (by avoid tearing and other
    artifacts of the drawing process).

... and is also used to reduce screen flicker, it is not necessarily
intended to make drawing as efficient as possible (as evidenced by its
throwing away the buffer pixmap).

I will restate my general rule:

  1) Do no drawing in the expose handler, at all, ever.
  2) Managing your own background pixmaps will make your application as
efficient as possible, with very little overhead cost (pixmaps are
cheap).

Corollary: Any solution whereby drawing is managed in the expose handler
itself will reduce its efficiency, by definition.

Paul, you started this thread by stating that my proposed paradigm was
opposite to GTK+ programming and that my statement re: the power gained
was simply false.  But in challenging me to better state my case, you have
succeeded in convincing me even more that this paradigm is, in the real
world, the most efficient method going, and that it is patently not
opposite to GTK+ design intent.

thanks,

richard



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]