[cairo] [RFC] Cairo operators expressed in shader syntax

Daniel Amelang daniel.amelang at gmail.com
Fri May 11 16:22:11 PDT 2007


Hey guys,

At part of a pixman rewrite project that I'm working on, I've come
across the need to express the semantics of the cairo operators in
some succinct, expressive, and easily parsable format. For now, I've
chosen to borrow from the opengl shader language (glsl) for a variety
of reasons. I'm fairly certain that I've expressed them right, but I
thought it would be nice to get them peer-reviewed just in case.

In addition, I thought I'd mention how this exercise has exposed the
nastiness of how component alpha was chosen to be implemented. I find
it awkward that the semantics of the IN operator is quite different
depending on if a certain flag is set. It seems to me that it would
have been wiser to define a whole new operator instead of
jerry-rigging an existing operator to behave like two distinct
operators, depending upon the environment, which in this case is just
a flag you set on an image.

As you can see below, I define a new operator "COMPONENT_IN", and
illustrate its behavior by example. It's likely that I'll just use
this new operator internally for the purposes of this project, but I
thought it might be worth discussing. If you follow the reasoning
further, you'll notice that COMPONENT_OUT and COMPONENT_DEST_OUT
operators are also possible, although I don't know how useful they
would be.

Dan Amelang

; src IN dst
result = src * dst.a
; src IN mask IN dst
result = src * mask.a * dst.a
; src COMPONENT_IN mask IN dst
result = src * mask * dst.a

; src COMPONENT_IN dst
result = src * dst
; src IN mask COMPONENT_IN dst
result = src * mask.a * dst
; src COMPONENT_IN mask COMPONENT_IN dst
result = src * mask * dst

; CLEAR
result = 0.0

; SOURCE
result = src
; src IN mask SOURCE dst
result = src * mask.a
; src COMPONENT_IN mask SOURCE dst
result = src * mask

; DEST
; src IN mask DEST dst
; src COMPONENT_IN mask DEST dst
result = dst

; src OVER dst
result = src + dst * (1.0 - src.a)
; src IN mask OVER dst
result = src * mask.a + dst * (1.0 - src.a * mask.a)
; src COMPONENT_IN mask OVER dst
result = src * mask + dst * (1.0 - src.a * mask.a)

; src DEST_OVER dst
result = src * (1.0 - dst.a) + dst
; src IN mask DEST_OVER dst
result = src * mask.a * (1.0 - dst.a) + dst
; src COMPONENT_IN mask DEST_OVER dst
result = src * mask * (1.0 - dst.a) + dst

; src DEST_IN dst
result = src.a * dst
; src IN mask DEST_IN dst
result = src.a * mask.a * dst
; src COMPONENT_IN mask DEST_IN dst
result = src.a * mask * dst

; src OUT dst
result = src * (1.0 - dst.a)
; src IN mask OUT dst
result = src * mask.a * (1.0 - dst.a)
; src COMPONENT_IN mask OUT dst
result = src * mask * (1.0 - dst.a)

; src DEST_OUT dst
result = (1.0 - src.a) * dst
; src IN mask DEST_OUT dst
result = (1.0 - src.a * mask.a) * dst
; src COMPONENT_IN mask DEST_OUT dst
result = (1.0 - src.a * mask) * dst

; src ATOP dst
result = src * dst.a + dst * (1.0 - src.a)
; src IN mask ATOP dst
result = src * mask.a * dst.a + dst * (1.0 - src.a * mask.a)
; src COMPONENT_IN mask ATOP dst
result = src * mask * dst.a + dst * (1.0 - src.a * mask.a)

; src DEST_ATOP dst
result = src * (1.0 - dst.a) + dst * src.a
; src IN mask DEST_ATOP dst
result = src * mask.a * (1.0 - dst.a) + dst * (src.a * mask.a)
; src COMPONENT_IN mask DEST_ATOP dst
result = src * mask * (1.0 - dst.a) + dst * (src.a * mask.a)

; src XOR dst
result = saturate (src * (1.0 - dst.a) + dst * (1.0 - src.a))
; src IN mask XOR dst
result = saturate (src * mask.a * (1.0 - dst.a) + dst * (1.0 - src.a * mask.a))
; src COMPONENT_IN mask XOR dst
result = saturate (src * mask * (1.0 - dst.a) + dst * (1.0 - src.a * mask.a))

; src ADD dst
result = saturate (src + dst)
; src IN mask ADD dst
result = saturate (src * mask.a + dst)
; src COMPONENT_IN mask ADD dst
result = saturate (src * mask + dst)

; src SATURATE dst
result = saturate (src * saturate ((1.0 - dst.a) / src.a) + dst)
; src IN mask SATURATE dst
result = saturate (src * mask.a * saturate ((1.0 - dst.a) / (src.a *
mask.a)) + dst)
; src COMPONENT_IN mask SATURATE dst
result = saturate (src * mask * saturate ((1.0 - dst.a) / (src.a *
mask.a)) + dst)


More information about the cairo mailing list