Вот пример программы, которая рисует более поздние линии сначала белым цветом с большей шириной линии, а затем снова черным цветом с фактической шириной линии:
#include <cairo.h>
int main()
{
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 200, 200);
cairo_t *cr = cairo_create(s);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr);
cairo_move_to(cr, 50, 20);
cairo_line_to(cr, 110, 160);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_move_to(cr, 200, 0);
cairo_line_to(cr, 60, 160);
cairo_set_line_width(cr, 15);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_stroke_preserve(cr);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_move_to(cr, 10, 100);
cairo_line_to(cr, 220, 50);
cairo_set_line_width(cr, 15);
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_stroke_preserve(cr);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_surface_write_to_png(s, "out.png");
cairo_destroy(cr);
cairo_surface_destroy(s);
}
Выход:

Хорошо, теперь на задний план. Вариант 1 - нарисовать линии с прозрачным фоном, а затем нарисовать фон под ним с помощью оператора DEST_OVER:
#include <cairo.h>
int main()
{
/* I changed this to ARGB32 */
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 200, 200);
cairo_t *cr = cairo_create(s);
cairo_pattern_t *p = cairo_pattern_create_linear(0, 0, 200, 200);
/* Draw the lines */
cairo_move_to(cr, 50, 20);
cairo_line_to(cr, 110, 160);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_move_to(cr, 200, 0);
cairo_line_to(cr, 60, 160);
cairo_set_line_width(cr, 15);
/* I changed all "drawing white" to "drawing transparency" */
cairo_save(cr);
cairo_set_source_rgba(cr, 0, 0, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_stroke_preserve(cr);
cairo_restore(cr);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_move_to(cr, 10, 100);
cairo_line_to(cr, 220, 50);
cairo_set_line_width(cr, 15);
cairo_save(cr);
cairo_set_source_rgba(cr, 0, 0, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_stroke_preserve(cr);
cairo_restore(cr);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
/* Draw a background below what we drew so far */
cairo_pattern_add_color_stop_rgb(p, 0, 1, 0, 0);
cairo_pattern_add_color_stop_rgb(p, 1, 0, 0, 1);
cairo_set_source(cr, p);
/* Actually, I mean DEST_OVER instead of ATOP (which I wrote in my comment) */
cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OVER);
cairo_paint(cr);
cairo_surface_write_to_png(s, "out.png");
cairo_pattern_destroy(p);
cairo_destroy(cr);
cairo_surface_destroy(s);
}
Выход:

Вариант 2 - использовать временную поверхность. Линии нарисованы с прозрачным фоном для этого. После этого он рисуется поверх существующего фона:
#include <cairo.h>
int main()
{
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 200, 200);
cairo_t *cr = cairo_create(s);
cairo_pattern_t *p = cairo_pattern_create_linear(0, 0, 200, 200);
/* Draw a background */
cairo_pattern_add_color_stop_rgb(p, 0, 1, 0, 0);
cairo_pattern_add_color_stop_rgb(p, 1, 0, 0, 1);
cairo_set_source(cr, p);
cairo_paint(cr);
cairo_pattern_destroy(p);
/* Draw the lines */
/* but draw them to a temporary surface */
cairo_push_group_with_content(cr, CAIRO_CONTENT_COLOR_ALPHA);
cairo_move_to(cr, 50, 20);
cairo_line_to(cr, 110, 160);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_move_to(cr, 200, 0);
cairo_line_to(cr, 60, 160);
cairo_set_line_width(cr, 15);
/* I changed all "drawing white" to "drawing transparency" */
cairo_save(cr);
cairo_set_source_rgba(cr, 0, 0, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_stroke_preserve(cr);
cairo_restore(cr);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
cairo_move_to(cr, 10, 100);
cairo_line_to(cr, 220, 50);
cairo_set_line_width(cr, 15);
cairo_save(cr);
cairo_set_source_rgba(cr, 0, 0, 0, 0);
cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
cairo_stroke_preserve(cr);
cairo_restore(cr);
cairo_set_line_width(cr, 4);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_stroke(cr);
/* Now draw the temporary surface to the target surface */
cairo_pop_group_to_source(cr);
cairo_paint(cr);
cairo_surface_write_to_png(s, "out.png");
cairo_destroy(cr);
cairo_surface_destroy(s);
}
Выход:
