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

M Joonas Pihlaja jpihlaja at cc.helsinki.fi
Fri Aug 20 15:47:38 PDT 2010


On Fri, 20 Aug 2010, Daniel Goldman wrote:

> 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

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

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

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

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

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

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


More information about the cairo mailing list