Skip to content

Instantly share code, notes, and snippets.

@flowernert
Created January 26, 2019 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save flowernert/8a61866b432b03ff21022f504a730016 to your computer and use it in GitHub Desktop.
Save flowernert/8a61866b432b03ff21022f504a730016 to your computer and use it in GitHub Desktop.
Draw polar gradients for arcs and circle in Cairo as no native function in the library handles it. Done by drawing portions of arcs with incremental color steps.
/**
* Draws an arc with a B&W gradient following the arc path.
* cr: the Cairo object to draw to
* lw: the linewidth
* nb_steps: the number of segments/color increments in which the arc will be splitted
* x_center: the x coordinate of the center of the arc
* y_center: the y coordinate of the center of the arc
* radius: the radius of the arc
* angle_from: the angle from which the arc will begin
* angle_to: the angle at which the arc will end
* color_from: the B&W starting color of the gradient, between 0.0 and 1.0
* color_to: the B&W ending color of the gradient, between 0.0 and 1.0
*
* nb_steps must be adjusted to have a smooth gradient rendering depending on the displayed size of the element
* Usage example:
* gradient_arc(cr, 0.125, 16, 0.5, 0.5, 0.5, -M_PI / 3.0, M_PI + M_PI / 3.0, 0.3, 0.9);
*
*/
void cairo_gradient_arc(cairo_t *cr, double lw, int nb_steps, double x_center, double y_center, double radius,
double angle_from, double angle_to, double color_from, double color_to)
{
cairo_set_line_width(cr, lw);
double *portions = malloc((1 + nb_steps) * sizeof(double));
// note: cairo angles seems to be shifted by M_PI relatively to the unit circle
angle_from = angle_from + M_PI;
angle_to = angle_to + M_PI;
double step = (angle_to - angle_from) / nb_steps;
for(int i = 0; i < nb_steps; i++) portions[i] = angle_from + i * step;
portions[nb_steps] = angle_to;
for(int i = 0; i < nb_steps; i++)
{
double color = color_from + i * (color_to - color_from) / nb_steps;
cairo_set_source_rgb(cr, color, color, color);
cairo_arc(cr, x_center, y_center, radius, portions[i], portions[i + 1]);
cairo_stroke(cr);
}
free(portions);
}
@flowernert
Copy link
Author

flowernert commented Jan 26, 2019

image

Sample produced by
gradient_arc(cr, 0.125, 16, 0.5, 0.5, 0.5, -M_PI / 3.0, M_PI + M_PI / 3.0, 0.3, 0.9);
to create a button decoration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment