Search code examples
cairoradial-gradients

Cairo Radial Gradient


I'm using a radial gradient in Cairo, but I'm not getting the expected results. The radial gradient I'm getting is much less fuzzy than I'd expect and I can't seem to fiddle with the color stops in order to get the desired results. Here is the code:

cairo_pattern_t *pat;

pat = cairo_pattern_create_radial(100.0, 100.0, 0.0, 100.0, 100.0, 20.0);
cairo_pattern_add_color_stop_rgba(pat, 0, 0, 0, 0, 1);
cairo_pattern_add_color_stop_rgba(pat, 1, 0, 0, 0, 0);

Here is an image of what I'm talking about.

radial gradient


Solution

  • The #cairo IRC channel suggested (Thanks Company!) to use cairo_mask() instead of cairo_paint() to draw the gradient. That results in a squared instead of linear progression.

    I did the following in lua. Sorry for the language, but it's easier to prototype something. This maps 1:1 to the C API and shouldn't be hard to translate:

    cairo = require("lgi").cairo
    
    s = cairo.ImageSurface(cairo.Format.ARGB32, 200, 100)
    c = cairo.Context(s)
    c:set_source_rgb(1, 1, 1)
    c:paint()
    
    p = cairo.Pattern.create_radial(50, 50, 0, 50, 50, 20)
    p:add_color_stop_rgba(0, 0, 0, 0, 1)
    p:add_color_stop_rgba(1, 0, 0, 0, 0)
    
    c:save()
    c:rectangle(0, 0, 100, 100)
    c:clip()
    c.source = p
    c:paint()
    c:restore()
    
    p = cairo.Pattern.create_radial(50, 50, 2, 50, 50, 25)
    p:add_color_stop_rgba(0, 0, 0, 0, 1)
    p:add_color_stop_rgba(1, 0, 0, 0, 0)
    
    c:translate(100, 0)
    c:save()
    c:rectangle(0, 0, 100, 100)
    c:clip()
    c.source = p
    c:mask(p)
    c:restore()
    
    s:write_to_png("test.png")
    

    To me, the second circle (The one that was cairo_mask()'d with a black source) looks a lot more like what you want:

    The image that the lua code produces