[cairo] cairo_set_user_data () and other "set_user_data" functions

Daniel Goldman dagoldman at yahoo.com
Fri Aug 20 16:26:29 PDT 2010


> > I already understood  what the function does. What I'm looking for asking is 
>a 
>

> > specific  example. What kind of resource might typically get attached in a 
> >  real-world case? Yes, the search results show real world use on the API, but 
>
> > they shed little or no light on my general question.
> 
> Did you  actually read any of the functions
> 
> > >  http://www.koders.com/default.aspx?s="cairo_surface_set_user_data"
> 
> pointed  you at?  Let's take the results and apply some mindful code 
> reading  skills.  Skipping the first few results from the cairo library 
> source  itself, the first search result  is
> 
>http://www.koders.com/c/fid8F95E6BFAA83A308AD102E365AAE13ADC9FA682A.aspx?s="cairo_surface_set_user_data"#L34
>4
> 
> In  the function f_image_surface_create(), you see that it is 
> allocating a  pixel buffer, creating an image surface for it, and then 
> attaching both the  pixel format and pixel buffers to the image 
> surface.  Clearly the  purpose of this is to use glib's g_malloc() to 
> allocate the large pixel  buffer so that the caller doesn't have to 
> check for allocation errors  (however, it's not careful about 
> arithmetic overflow when computing the  size, so don't do this.)
> 
> The second search result  is
> 
>http://www.koders.com/cpp/fid5BDE65224ED2830DCED6AFFD8956B029C2396699.aspx?s="cairo_surface_set_user_data"#L48
>8
> 
> In  the function TestNewSurface(), it is creating an image surface and 
> attaching an integer counter value (&destroyed) to it using a dummy 
> key (&destruction_key), for the sole purpose of getting a callback to 
> SurfaceDestroyNotifier when the surface is destroyed.  The 
> SurfaceDestroyNotifier sets the value of the destroyed variable to 1 
> when it is called.  The purpose of the user data in this case is to 
> unit test the reference counting mechanism to make sure that indeed, 
> the  SurfaceDestroyNotifier is called when the last reference to the 
> surface has  been destroyed.
> 
> Skipping past duplicates again, the third result  is
> 
>http://www.koders.com/csharp/fidEF55CE573B71D4AE98D1F20975C069E72045C435.aspx?s="cairo_surface_set_user_data"#L178
>8
> 
> This  case is similar to the first case in usage, except the code is a 
> C# class,  and the pixel buffer allocation mechanism is different 
> (Marshal.AllocHGlobal  / FreeHGlobal instead of g_malloc/g_free.)
> 
> The next result is merely an  Ada language binding to the 
> cairo_surface_set_user_data() function, so  that's not helpful wrt. 
> usae. The next result is again managing the lifetime  of a pixel 
> buffer, as is the next one, and the next one.  Skipping  ahead to some 
> interesting use cases, we  find
> 
>http://www.koders.com/c/fid69CD1B67619C208294D43A44FEFCBB3109B59FF9.aspx?s="cairo_surface_set_user_data"#L1498
>8
> 
> This  is gdk_x11_ref_cairo_surface() inside GDK, and what it's doing is 
> attaching  a cairo surface to a GDK X11 Drawable, so you can draw onto 
> the Drawable  using cairo.  Nifty, no?  The purpose of the 
> set_user_data call is  to set a notifier on surface destruction to 
> detach the surface from the  drawable.
> 
> Skipping ahead over some more duplicates, we see another  similar case 
> inside  GDK
> 
>http://www.koders.com/c/fidADDA5A368114609CF9092A6336B27CE9909930AD.aspx?s="cairo_surface_set_user_data"#L70
>0
> 
> This  is gdk_quartz_ref_cairo_surface(), where the basic usage is 
> similar to the  x11 case, only it's adding a slightly more complex 
> structure (a SurfaceInfo  object) to the surface, to track both the 
> Drawable and the Quartz context  object CGContextRef.
> 
> Moving along, we see  create_preview_surface_platform() in moo (which 
> seems to be some sort of UI  framework using  cairo)
> 
>http://www.koders.com/c/fid7494FC2222E3A5A2770B0103D3354E9763BB497C.aspx?s="cairo_surface_set_user_data"#L228
>8
> 
> This  function is attaching a windows metafile to a win32 printing 
> surface so  that the metafile is closed and its handled deleted when 
> the last surface  reference causes the surface to be destroyed.
> 
> The next one is a java  binding, so let's skip that.  The next one is a 
> pixel destructor again,  and we've had a lot of those already, so let's 
> skip that.  More  auxiliary resource destruction in GDK, we've had 
> those, so skip.   Another language binding, skip.  Closing a file at 
> surface destruction,  skip.  Killing a pixel buffer, skip.  There are 
> seven pages of  results here which continue in essentially the same 
> vein.
> 
> Hope that  helps,
> 
> Joonas
>

Yes, that helps more than I could have expected. I really appreciate your 
detailed response. 


I did look at the code some, but not nearly in the depth or detail you did. It's 
not an efficient way to learn an API, especially a rich and complex API like 
cairo. The problem is the cairo API reference docs are somewhat lacking in 
providing insight and any kind of big picture. The API reference tells me the 
name of the function is "set_user_data" for some object. OK. Then, the parameter 
is called "user_data". All right. Finally, the documentation for the parameter 
is "user data to attach". Wow! I hope you get the point. A fair amount of the 
cairo API reference docs similarly kind of misses the boat. Even if the missing 
content were found in tutorials (it's mostly not), it should not be left out of 
the API docs. Good, useful API docs explain more about the intention and 
usefulness of functions, like the great examples you've provided. Good docs 
don't just tersely repeat the names of self-explanatory function and parameter 
names.

Thanks,
Daniel


More information about the cairo mailing list