Normally, you will be using cairo to draw objects on top of each other. But cairo can do differently, if you need it! In fact, you can use all the Porter/Duff compositing operators.
Fourteen different operators are available since cairo 1.0; more operators have been added in cairo 1.10. This page is a try to describe them. It may contain errors and is possibly incomplete. Please help to improve it!
Example images
It is probably best to describe the effect of compositing operators by showing example images, so that's what is done below. The images show the result of drawing an object (a translucent blue rectangle) onto a surface which already contains another image (a translucent red rectangle).
The operator names try to describe what the operators mean. Two words need to be mentioned: the source and the destination (or dest). In this context, these provide the two objects which contribute to the graphical output of the drawing operation. The destination is the name of the surface before the drawing operation, the source is the name of what is added while drawing.
The Destination
To create the example images, the red rectangle is first drawn to the (empty) destination surface with the default operator:
cairo_rectangle (cr, 0, 0, 120, 90);
cairo_set_source_rgba (cr, 0.7, 0, 0, 0.8);
cairo_fill (cr);
The surface is now a transparent plane with a partially transparent rectangle in it. This represents the destination to which the next drawing operation will be performed. Both the red and the fully transparent part of the surface are now natural parts of the destination.
Setting the compositing operator
The current operator is now set using
cairo_set_operator()
.
The Source
The tutorial describes how drawing works in cairo:
"Cairo internally draws with one fundamental drawing operation: the source and mask are freely placed somewhere over the destination. Then the layers are all pressed together and the paint from the source is transferred to the destination wherever the mask allows it."
However, there is no mention of a mask in the names of the compositing operators. They refer to a source and a destination only. This allows for two different interpretations with regard to what should be regarded as the source for the compositing operation:
Since the mask determines where the paint from the source is transferred, it also determines the area in which the compositing operation is performed. This interpretation can be called bounded.
The area where the compositing operation is performed is not bounded by the mask. Instead, any parts where the source layer is not transferred are considered to be fully transparent. We call this interpretation of the source unbounded.
For some of the operators, both interpretations lead to the same result, for others they do not. In cairo, the actual interpretation depends on the operator. The unbounded operators modify destination outside of the bounds of the mask. However, their effect can still be limited by way of clipping. See the section on clipping and masking for those details.
The blue rectangle is drawn with the new operator in effect:
cairo_rectangle (cr, 40, 30, 120, 90);
cairo_set_source_rgba (cr, 0, 0, 0.9, 0.4);
cairo_fill (cr);
The results can be seen in the images below. Note that both rectangles are drawn with transparency. When studying the images, you may be able to guess how they would look for opaque objects, too. For reference, the code to create the images is also available.
Operators
For the mathematical description, it is convenient to use the following conventions:
The index A (assigned to color components and transparency factor) refers to the source, while the index B refers to the destination. The index R refers to the result of the compositing operation.
Each pixel in both the source and the destination is fully described by a tuple (r, g, b, a). We will use "x" as a shorthand for any color component, since they are always treated the same. "a" describes the alpha value (opacity) and is treated differently.
The product of xA and aA is described by xaA. xaB and xaR have analogous meaning.
The color computations equations contain a division by aR, which cannot be done where aR is zero. But in this case the color doesn't matter anyway (full transparency) and can also be set to zero. (Internally, the colors may be handled differently, so this might or might not be necessary.)
CAIRO_OPERATOR_CLEAR
Where the second object is drawn, the first is completely removed. Anywhere else it is left intact. The second object itself is not drawn.
The effect of the CLEAR
operator depends on the interpretation of the
source. In cairo, this operator is bounded.
Resulting alpha (aR) | Resulting color (xR) |
0 | 0 |
CAIRO_OPERATOR_SOURCE
The second object is drawn as if nothing else were below. Only outside of the blue rectangle the red one is left intact.
The effect of the SOURCE
operator depends on the interpretation of the
source. In cairo, this operator is bounded.
Resulting alpha (aR) | Resulting color (xR) |
aA | xA |
CAIRO_OPERATOR_OVER
The image shows what you would expect if you held two semi-transparent slides on top of each other. This operator is cairo's default operator.
The output of the OVER
operator is the same for both bounded and
unbounded source.
Resulting alpha (aR) | Resulting color (xR) |
aA + aB·(1−aA) | (xaA + xaB·(1−aA))/aR |
CAIRO_OPERATOR_IN
The first object is removed completely, the second is only drawn where the first was.
Note that the transparency of the first object is taken into account. That is, the small blue rectangle is slightly lighter than it would have been, had the first object been opaque.
The effect of the IN
operator depends on the interpretation of the
source. In cairo, this operator is unbounded.
Resulting alpha (aR) | Resulting color (xR) |
aA·aB | xA |
CAIRO_OPERATOR_OUT
The blue rectangle is drawn only where the red one wasn't. Since the red one was partially transparent, you can see a blue shadow in the overlapping area. Otherwise, the red object is completely removed.
The effect of the OUT
operator depends on the interpretation of the
source. In cairo, this operator is unbounded.
Resulting alpha (aR) | Resulting color (xR) |
aA·(1−aB) | xA |
CAIRO_OPERATOR_ATOP
This leaves the first object mostly intact, but mixes both objects in the overlapping area. The second object object is not drawn except there.
If you look closely, you will notice that the resulting color in the
overlapping area is different from what the OVER
operator produces.
Any two operators produce different output in the overlapping area!
The output of the ATOP
operator is the same for both bounded and
unbounded source.
Resulting alpha (aR) | Resulting color (xR) |
aB | xaA + xB·(1−aA) |
CAIRO_OPERATOR_DEST
Leaves the first object untouched, the second is discarded completely.
The output of the DEST
operator is the same for both bounded and
unbounded source.
Resulting alpha (aR) | Resulting color (xR) |
aB | xB |
CAIRO_OPERATOR_DEST_OVER
The result is similar to the OVER
operator. Except that the "order" of
the objects is reversed, so the second is drawn below the first.
The output of the DEST_OVER
operator is the same for both bounded and
unbounded source.
Resulting alpha (aR) | Resulting color (xR) |
(1−aB)·aA + aB | (xaA·(1−aB) + xaB)/aR |
CAIRO_OPERATOR_DEST_IN
The blue rectangle is used to determine which part of the red one is left intact. Anything outside the overlapping area is removed.
This works like the IN
operator, but again with the second object
"below" the first.
Similar to the two interpretations of the source, it is possible to
imagine the same distinction with regard to the destination. In cairo,
the DEST_IN
operator is unbounded.
Resulting alpha (aR) | Resulting color (xR) |
aA·aB | xB |
CAIRO_OPERATOR_DEST_OUT
The second object is used to reduce the visibility of the first in the overlapping area. Its transparency/opacity is taken into account. The second object is not drawn itself.
The output of the DEST_OUT
operator is the same for both bounded and
unbounded interpretations.
Resulting alpha (aR) | Resulting color (xR) |
(1−aA)·aB | xB |
CAIRO_OPERATOR_DEST_ATOP
Same as the ATOP
operator, but again as if the order of the drawing
operations had been reversed.
In cairo, the DEST_ATOP
operator is unbounded.
Resulting alpha (aR) | Resulting color (xR) |
aA | xA·(1−aB) + xaB |
CAIRO_OPERATOR_XOR
The output of the XOR
operator is the same for both bounded and
unbounded source interpretations.
Resulting alpha (aR) | Resulting color (xR) |
aA + aB − 2·aA·aB | (xaA·(1−aB) + xaB·(1−aA))/aR |
CAIRO_OPERATOR_ADD
The output of the ADD
operator is the same for both bounded and
unbounded source interpretations.
Resulting alpha (aR) | Resulting color (xR) |
min(1, aA+aB) | (xaA + xaB)/aR |
CAIRO_OPERATOR_SATURATE
The output of the SATURATE
operator is the same for both bounded and
unbounded source interpretations.
Resulting alpha (aR) | Resulting color (xR) |
min(1, aA+aB) | (min(aA, 1−aB)·xA + xaB)/aR |
Blend Modes
Since cairo 1.10, the set of operators is extended by 15 additional
operators. These originate from the PDF specification and extend the
range of available color computation equations. All of them share the
same alpha computation equation, which is identical to the one from
CAIRO_OPERATOR_OVER
. The output of the new operators is the same for
both bounded and unbounded source.
The color computations are more complicated than for the previous operators, so a different presentation is used for the mathematical details. The resulting alpha (aR) is:
The equation for the color components follows this form:
where the operators differ only in the blend mode function f(xA,xB). The respective blend mode functions used are given below. The result color is undefined when aR is zero (full transparency).
CAIRO_OPERATOR_MULTIPLY
Blend mode function:
The result color is at least as dark as the darker of the two input colors.
CAIRO_OPERATOR_SCREEN
Blend mode function:
Input colors are complemented and multiplied, the product is complemented again. The result is at least as light as the lighter of the input colors.
CAIRO_OPERATOR_OVERLAY
Blend mode function:
Multiplies or screens colors, depending on the lightness of the destination color.
CAIRO_OPERATOR_DARKEN
Blend mode function:
Selects the darker of the color values in each component.
CAIRO_OPERATOR_LIGHTEN
Blend mode function:
Selects the lighter of the color values in each component.
CAIRO_OPERATOR_COLOR_DODGE
Blend mode function:
Brightens the destination color by a factor depending on the source color.
CAIRO_OPERATOR_COLOR_BURN
Blend mode function:
Darkens the destination color by a factor depending on the source color.
CAIRO_OPERATOR_HARD_LIGHT
Blend mode function:
Multiplies or screens colors, depending on the lightness of the source color.
CAIRO_OPERATOR_SOFT_LIGHT
Blend mode function:
where
Darkens or lightens, depending on the source color.
CAIRO_OPERATOR_DIFFERENCE
Blend mode function:
Takes the difference of the destination and source colors.
CAIRO_OPERATOR_EXCLUSION
Blend mode function:
The effect is similar to DIFFERENCE
, but has lower contrast.
Non-separable Blend Modes
The following blend modes are non-separable, i.e., they consider all
color components in combination. The blend mode functions f(xA,xB)
become f(cA,cB)
. A few more functions are necessary to describe
them. "c
" is the color defined by the tuple (r,g,b).
The original functions are provided in the PDF specfication (see Links below).
In the following function "cmax
" and "cmin
" serve as aliases for the
colors with the highest and lowest values. "cmid
" is the third
(remaining) color.
CAIRO_OPERATOR_HSL_HUE
Blend mode function:
Creates a color with the hue of the source and the saturation and luminosity of the destination.
CAIRO_OPERATOR_HSL_SATURATION
Blend mode function:
Creates a color with the saturation of the source and the hue and luminosity of the destination. Painting with this mode onto a gray area produces no change.
CAIRO_OPERATOR_HSL_COLOR
Blend mode function:
Creates a color with the hue and saturation of the source and the luminosity of the destination. This preserves the gray levels of the destination and is useful for coloring monochrome images or tinting color images.
CAIRO_OPERATOR_HSL_LUMINOSITY
Blend mode function:
Creates a color with the luminosity of the source and the hue and
saturation of the destination. This produces an inverse effect to
CAIRO_OPERATOR_HSL_COLOR
.
Clipping and masking
This section augments the documentation of cairo's compositing model by describing how clipping and masking are taken into account when rendering. In this context the clip and mask are treated as cairo surfaces with alpha content that both default to full opaqueness when not explicitly given. The basic approach to clipping in cairo is to first perform the operation without clipping and then interpolating by the clip pointwise between the unclipped result and the destination. In the descriptions below this is achieved using a ternary operator A LERPT B that is defined here as:
The approach to masking is to combine it using operator IN with either the clip, for the bounded operators, or with the source for the unbounded ones.
There are three distinct rendering equations used within cairo to implement clipping and masking, which can be described using the (unclipped, unmasked) operators IN, OUT and ADD operators as primitives.
Kind | Equation |
---|---|
XRender | ((src IN mask) OP dst) LERPclip dst |
Bounded | (src OP dst) LERP(clip IN mask) dst |
Simple | (src IN (clip IN mask)) OP dst |
The XRender-kind definition most closely matches the letter of the XRender specification as it reduces to XRender's equation when clip is binary valued – the only kind of clip talked about in the spec. The Simple-kind definition is the fastest to execute and was conceived of as an optimisation of the XRender-kind definition to take advantage of the fact that for many operators the two coincide. The Bounded definition is a variation of the XRender-kind definition where the mask is considered to be a part of the clip. It is used for the SOURCE and CLEAR operators only, and is used to make those operators be explicitly bounded by mask. The following table gives the rendering equation used by each of cairo's operators. The entries marked with Any are operators for which all three variants coincide.
Operator | Kind |
---|---|
CLEAR | Bounded |
SOURCE | Bounded |
OVER | Any |
IN | XRender |
OUT | XRender |
ATOP | Any |
DEST | Any |
DEST_OVER | Any |
DEST_IN | XRender |
DEST_OUT | Any |
DEST_ATOP | XRender |
XOR | Any |
ADD | Any |
SATURATE | Simple |
Links
The original paper by Thomas Porter and Tom Duff: http://keithp.com/~keithp/porterduff/p253-porter.pdf,
The description of the X Rendering Extension by Keith Packard is where the information about the
ADD
andSATURATE
operators comes from: http://keithp.com/~keithp/render/protocol.htmlA description of compositing in SVG 1.2 by Craig Northway: http://www.svgopen.org/2005/papers/abstractsvgopen/
The PDF specification is available from Adobe at http://www.adobe.com/devnet/pdf/pdf_reference.html