1
votes

I have been trying to use the code below to set up a gradient, but it displays a gradient from black to white (which are not the colors, obviously).

cairo_t *cr;
cr = gdk_cairo_create(widget->window);
cairo_pattern_t *pat1;  
pat1 = cairo_pattern_create_linear(0.0, 0.0,  50.0, 512);
cairo_pattern_add_color_stop_rgb(pat1, 0, 0, 0, 0);
cairo_pattern_add_color_stop_rgb(pat1, 1, 1, 254, 255);
cairo_pattern_add_color_stop_rgb(pat1, 2, 2, 253, 255);
cairo_pattern_add_color_stop_rgb(pat1, 3, 3, 252, 255);
cairo_pattern_add_color_stop_rgb(pat1, 4, 4, 251, 255);
cairo_pattern_add_color_stop_rgb(pat1, 5, 5, 250, 255);
cairo_pattern_add_color_stop_rgb(pat1, 6, 6, 249, 255);
cairo_pattern_add_color_stop_rgb(pat1, 7, 6, 249, 255);
cairo_pattern_add_color_stop_rgb(pat1, 8, 7, 248, 255);
cairo_pattern_add_color_stop_rgb(pat1, 9, 8, 247, 255);
cairo_rectangle(cr, 0, 0, 50, 512);
cairo_set_source(cr, pat1);
cairo_fill(cr);  
cairo_pattern_destroy(pat1);
cairo_destroy(cr);

However, this code displays a gradient from red to purple to blue:

cairo_t *cr;
cr = gdk_cairo_create(widget->window);
cairo_pattern_t *pat1;  
pat1 = cairo_pattern_create_linear(0.0, 0.0,  50.0, 512);
cairo_pattern_add_color_stop_rgb(pat1, 0, 256, 0, 0);
cairo_pattern_add_color_stop_rgb(pat1, 1, 0, 0, 256);
cairo_pattern_add_color_stop_rgb(pat1, 2, 0, 256, 256);
cairo_rectangle(cr, 0, 0, 50, 512);
cairo_set_source(cr, pat1);
cairo_fill(cr);  
cairo_pattern_destroy(pat1);
cairo_destroy(cr);

Why does the first one display a grayscale, while the second one does not? The top has non-grayscale colors, so I have no clue why it wouldn't work.

EDIT: An answer explained that values above 1 are clamped so I changed my code to this:

cairo_pattern_add_color_stop_rgb(pat1, 0, 0, 0, 0);
cairo_pattern_add_color_stop_rgb(pat1, 1, (1/256), (254/256), (255/256));
cairo_pattern_add_color_stop_rgb(pat1, 2, (2/256), (253/256), (255/256));
cairo_pattern_add_color_stop_rgb(pat1, 3, (3/256), (252/256), (255/256));
cairo_pattern_add_color_stop_rgb(pat1, 4, (4/256), (251/256), (255/256));
cairo_pattern_add_color_stop_rgb(pat1, 5, (5/256), (250/256), (255/256));
cairo_pattern_add_color_stop_rgb(pat1, 6, (6/256), (249/256), (255/256));
cairo_pattern_add_color_stop_rgb(pat1, 7, (6/256), (249/256), (255/256));
cairo_pattern_add_color_stop_rgb(pat1, 8, (7/256), (248/256), (255/256));
cairo_pattern_add_color_stop_rgb(pat1, 9, (8/256), (247/256), (255/256));

The bar is now completely black.

1
integer division in C results in an integer: in your last set of examples every fraction truncates to 0. Use something like 1.0/256 instead: this way floating point division is used instead. - Jussi Kukkonen

1 Answers

3
votes

https://www.cairographics.org/manual/cairo-cairo-t.html#cairo-set-source-rgb

The color and alpha components are floating point numbers in the range 0 to 1. If the values passed in are outside that range, they will be clamped.

The 256s in the one that work are clamped to 1. So you get (1,0,0) to (0,0,1) to (0,1,1).

In the one that doesn't work, the first one remains (0,0,0) and every other stop is clamped to (1,1,1). In short, black to white are the colors used in the first one. So cairo displays black to white.