[cairo] API proposal: Damage Tracking

Behdad Esfahbod behdad at behdad.org
Thu May 8 13:58:50 PDT 2008


On Thu, 2008-05-08 at 16:55 -0400, Behdad Esfahbod wrote:
> Hi Soeren,
> 
> This is all very interesting.  But I think we should think a bit more
> about it and definitely improve the naming.  A very similar
> functionality is to be able to compute the bounds of drawing operations.
> So we have:
> 
>   - actual drawing
>   - bounds
>   - update region
>   - hit testing?
> 
> The way OpenGL does it is that you can switch between drawing and hit
> testing.  In cairo, may be better to be able to turn each on/off.  So
> you can do all of:
> 
>   - Draw to a local buffer, get update region and push that to your
> remote.  It can be used internally to improve xlib fallback backend as
> well as directfb kind of backends.  We were talking about this recently.
> 
>   - Don't draw, just compute bounds.  Right now for this kind of needs
> you have to create a similar surface and draw to it.  You have to use a
> similar surface to get the same font options, etc.  Though most of the
> times when you need the bounds you need it to create a surface of the
> right size.  So I'm not sure how useful this will be.

Forgot to say.  I do need this in user-fonts.  The way I do it now is
that I added a "null" surface.  One that does nothing.  Then I replay
back my meta-surface to an analysis surface connected to a null surface,
then ask the analysis surface for extents.  Would have been much easier
if I could simply ask my cairo_t for the extents.

One complexity of this all to keep in mind is the space that the
region/bounds are kept in.  Simplest would be to track in device space.
But in user-font and in PS/PDF we do need extents in a different space.
Right now analysis surface converts extents of individual operations to
the target space and takes the union of those.  That's quite suboptimal
for something like rotated text...


behdad

>   - No draw, just get update region for purposes like yours?
> 
> And tracking bounds/region per cairo_save() level would be really cool,
> yeah.
> 
> Cheers,
> 
> behdad
> 
> On Thu, 2008-05-01 at 02:58 +0200, Soeren Sandmann wrote:
> > 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
> > _______________________________________________
> > cairo mailing list
> > cairo at cairographics.org
> > http://lists.cairographics.org/mailman/listinfo/cairo
-- 
behdad
http://behdad.org/

"Those who would give up Essential Liberty to purchase a little
 Temporary Safety, deserve neither Liberty nor Safety."
        -- Benjamin Franklin, 1759



More information about the cairo mailing list