[cairo] API proposal: Damage Tracking

Soeren Sandmann sandmann at daimi.au.dk
Wed Apr 30 17:58:39 PDT 2008


Hi,

In a canvas/toolkit type project I am playing around with, I need the
ability to track the 'damage' done by painting with a cairo context. 

This is useful to generate repaint areas, ie., the area that the
application needs to repaint. When something happens that causes a
canvas item to change it appearance, damage tracking would allow the
application to simply do this:

        static void
        invalidate (Item *item, cairo_t *cr)
        {
                cairo_begin_damage_tracking (cr);

                <paint the item>

                damaged = cairo_end_damage_tracking (cr);

                add_to_repaint_region (damaged);

                free (damaged);
        }

        void
        on_event ()
        {
                cairo_t *cr = create_cr();

                /* Invalidate old position */
                invalidate (item, cr);

                <update item information>

                /* Invalidate new position */
                invalidate (item, cr);

                cairo_destroy();
        }

The big benefit is that this frees the application from keeping track
of the exact region that is covering the item. Instead it can just
compute it as needed.

Currently the best an application can do is call
cairo_stroke/fill_extents() after before each paint operation, but (a)
this is inconvenient, (b) the extent rectangles are too pessimistic in
many cases, and (c) it may not be possible to do if the painting is
being done by a library.

So I am proposing this new API:

        void                        cairo_begin_damage_tracking (cr);
        cairo_rectangle_list_t *    cairo_end_damage_tracking (cr);

Cairo would keep track of a stack of rectangle lists corresponding to
the nesting level. Whenever cairo_end_damage_tracking() is called, a
the topmost list is returned after a copy of it was unioned with the
next list on the stack.

Open question: In the proposal above, nothing is actually painted when
tracking damage. I think it could potentially be useful to allow
damage tracking and painting to go on at the same time, say for
applications that would like to keep track of the last thing they
painted.

A way to accomplish that would be to simply have
begin_damage_tracking() not turn off painting, but then also provide
begin/end_disable_painting() calls.


Soren


More information about the cairo mailing list