[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