[cairo] [RFC] Color space API (partial proposal)

Adrian Johnson ajohnson at redneon.com
Tue Feb 23 02:45:58 PST 2010

Andrea Canciani wrote:
> The attached changes to cairo.h are the base of what will probably be
> my API change proposal for color space handling.

This looks to be very close to what we need to be able to create PDF 
files with ICC based colors.

> Basically all surfaces and patterns will have a color space in which
> all the "math" related to them happens (compositing/blending for
> surfaces, interpolation for patterns) and their colors are
> interpreted. I think that after the creation the color space should
> not be changed so I didn't write functions to permit it as this
> operation seems to have no meaning in terms of colors.

Changing the color space of surfaces after creation is not compatible 
with PDF and probably other vector backends.

> Are there use cases where the proposed API is inadequate?

We a need way to specify the color space when creating a surface. In PDF 
each page can have a different color space for the top level page group. 
So something like:

  cairo_pdf_surface_set_color_space (cairo_surface_t     *surface,
                                     cairo_color_space_t *color_space);

or a generic function for all surfaces:

  cairo_surface_set_color_space (cairo_surface_t     *surface,
                                 cairo_color_space_t *color_space);

While the proposed API supports ICC CMYK colors, some users may want 
device CMYK colors. This is easy to add.

  cairo_color_space_t *
  cairo_color_space_create_device_cmyk ()

  cairo_color_t *
  cairo_color_create_cmyka (double cyan,
                            double magenta,
                            double yellow,
                            double black,
                            double alpha);

Also missing are spot and DeviceN colors.

In PDF spot colors are known as separation color spaces. A separation 
color space is defined by a name object that specifies the colorant, an 
alternative color space, and tint transform.

A color value in a separation color space consists of a tint value 
between 0 and 1. Zero means the minimum amount of colorant. One means 
the maximum amount of colorant.

Name objects can be up to 127 8-bit characters excluding NULL. If the 
device does not support the colorant the alternative color is used. This 
color is in the alternate color space and is obtained by transforming 
the tint value by the tint transform function. The alternative color 
space must not be a DeviceN or separation color space.

Specifying a transform function in an API is complicated and probably 
not necessary for supporting spot colors. We could just specify an 
alternative color for the separation color space and use the tint value 
as an alpha value for the alternative color.

A DeviceN color space allows multiple colorants in the color space. 
Specify a color in a DeviceN color space requires specifying the tint 
value of each component.

The DeviceN API could look something like:

/* Create a Device N color space. alternate_color_space specifies
  * the color space to be used for the alternative colors for each
  * component
  cairo_color_space_t *
  cairo_color_space_create_device_n (
                      cairo_color_space_t *alternate_color_space)

/* Add a colorant to the DeviceN color space. "name" is the name of the
  * colorant. alternate_color is an array of components specifying the
  * a color in the alternate_color_space.
  cairo_color_space_add_colorant (cairo_space_color_t *color_space,
                                  const char          *name,
                                  double              *alternate_color)

To create a DeviceN color, use the
   cairo_color_create (cairo_color_t *color_space, double *components)
function and specify the tint value of each component.

Spot color spaces are the same as a DeviceN color space with one 
component. We could provide a convenience function for creating DeviceN 
color space with one color:

  cairo_color_space_t *
  cairo_color_space_create_spot (const char    *name,
                                 cairo_color_t *alternate);

This allows the alternative color space and color to be specified with a 

More information about the cairo mailing list