Surfaces

Like patterns, surfaces, which use only the cairo_surface_t type in the C API should be broken up into a hierarchy of types in a language binding.

cairo_surface_t
    cairo_image_surface_t
    cairo_atsui_surface_t
    cairo_win32_surface_t
    cairo_xlib_surface_t
    cairo_beos_surface_t
    

Unlike patterns, the constructors and methods on these types are clearly named, and can be trivially associated with the appropriate subtype. Many language bindings will want to avoid binding the platform-specific subtypes at all, since the methods on these types are not useful without passing in native C types. Unless there is a language binding for Xlib available, there is no way to represent a XLib Display * in that language.

This doesn't mean that platform-specific surface types can't be used in a language binding that doesn't bind the constructor. A very common situation is to use a cairo language binding in combination with a binding for a higher level system like the GTK+ widget toolkit. In such a situation, the higher level toolkit provides ways to get references to platform specific surfaces.

The cairo_surface_set_user_data(), and cairo_surface_get_user_data() methods are provided for use in language bindings, and should not be directly exposed to applications. One example of the use of these functions in a language binding is creating a binding for:

cairo_surface_t *
cairo_image_surface_create_for_data (unsigned char	       *data,
				     cairo_format_t		format,
				     int			width,
				     int			height,
				     int			stride);

The memory block passed in for data must be kept around until the surface is destroyed, so the language binding must have some way of determining when that happens. The way to do this is to use the destroy argument to cairo_surface_set_user_data().

Some languages may not have a suitable “pointer to a block of data” type to pass in for data. And even where a language does have such a type, the user will be frequently able to cause the backing store to be reallocated to a different location or truncated. Should we recommend a standard type name and binding for a buffer object here?