[cairo] Path Gradients

Behdad Esfahbod behdad at behdad.org
Fri Jan 4 11:43:43 PST 2008

On Fri, 2008-01-04 at 11:12 -0800, Bill Spitzak wrote:
> Behdad Esfahbod wrote:
> >> It was unclear what happens with multiple-step gradients, which some
> >> of 
> >> the examples show. Does it only change the last step, or is there an
> >> api 
> >> to change all the steps?
> > 
> > The actual radial stops where done in the code using a Blend object,
> > that's like just having stops for alpha value.  That is, instead of the
> > linear interpolation between the two ends, user can provide a detailed
> > blend function.  No separate color stops.
> I'm sorry, I thought you were talking about the example where the color 
> along the edge changes, as shown by the top-left triangle in this picture:
> http://www.java2s.com/Code/VBImages/PathGradientBrushesDiamondRectangleCirlceandquad.PNG
> It is apparent from the examples that they support multi-stop gradients, 
> but there is no example of what happens if you specify *both* this and 
> if you change the colors along the path. Does it only change the last 
> stop? Or is there an api to change all the stops? Or does it just not work?

IIUC the multiple stops are one per path point.  That's for the conical
part of the thing.  AFAIU you can't do cairo radial gradients using it
because on the radial side it just accepts a blend function.  No
separate color data.

That is, given path P, color stops S, center C, center color Cc, and
blend function F, the color at x0,y0 will be computed as:

  - Find where the line passing by C and x0,y0 intersects with P (take
the one with smallest/largest parameter based on path orientation or
something), call it x1,y1

  - Find the color at x1,y1 by linearly interpolating colors in S using
path information P.  That is, find the segment on P that x1,y1 lies,
linearly/cubically/whatever interpolate the color from respective stops
in S to get color for x1,y1

  - Compute normalized distance of x0,y0 from the path.  That is:

    d = |x0,y0 - C| / |x1,y1 - C|

  - If F is not set, blend factor is simply d, otherwise blend factor is

    bf = F ? F(d) : d

  - color at x0,y0 = (1 - bf) * Cc + bf * color at x1,y1

> >> I am still very interested in any explanation why the path needs to
> >> be 
> >> specified twice and what happens if the two paths are different.
> > 
> > What do you mean by twice?  Where?
> > 
> All the examples in this paper send the path twice, once to construct 
> the "path gradient brush" and again to fill the shape:
> http://www.bobpowell.net/pgb.htm
> My best guess is that this really is similar to how Cairo does the 
> radial brush. The "path gradient" specifies a pattern that can then be 
> masked by a different path. Unfortunately it appears that they define 
> the pattern as transparent outside the path, which makes it pretty 
> useless for any path that is outside the source path. I think defining 
> the outside as being equal to the last stop would be much more useful.

Yes, that's really a matter of using a cairo_*_preserve() version or


"Those who would give up Essential Liberty to purchase a little
 Temporary Safety, deserve neither Liberty nor Safety."
        -- Benjamin Franklin, 1759

More information about the cairo mailing list