Search code examples
cgtk3cairo

How to draw chessboard like pattern using cairo on gtk3 drawing area?


I am trying to create a color picker widget in gtk3, in this widget, while changing the alpha color value from the scale/spin button; I want to show alpha color status in a drawing area. Although the alpha color is drawn in the drawing area, but the status is not clearly understood by looking at it. So i want to show the alpha color with chessboard like (background) surface. enter image description here

My expectation like this: enter image description here

my script -- (Gtk3)

#include <cairo.h>
#include <gtk/gtk.h>

void draw_gradient(cairo_t *);
static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data)
{         
  draw_gradient(cr);
  return FALSE;
}

void draw_gradient(cairo_t *cr)
{
    int width = 300;
    int height = 100;

    cairo_pattern_t *gradient;

    gradient =cairo_pattern_create_linear(0.0, 0.0, width, 0.0); 
    cairo_pattern_add_color_stop_rgba (gradient, 0, 75,0,130, 0.3); //Purple with alpha 
    cairo_pattern_add_color_stop_rgba (gradient, 1, 75,0,130, 1); //Purple


    cairo_set_source (cr, gradient);

    cairo_paint (cr);

    cairo_pattern_destroy (gradient);
}

int main(int argc, char *argv[])
{
  GtkWidget *window;
  GtkWidget *darea;  

  gtk_init(&argc, &argv);

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

  darea = gtk_drawing_area_new();
  gtk_container_add(GTK_CONTAINER (window), darea);

  g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL);  
  g_signal_connect(G_OBJECT(window), "destroy",G_CALLBACK(gtk_main_quit), NULL);

  gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
  gtk_window_set_default_size(GTK_WINDOW(window), 300, 100); 
  gtk_window_set_title(GTK_WINDOW(window), "Linear gradients");

  gtk_widget_set_app_paintable(window, TRUE);
  gtk_widget_show_all(window);

  gtk_main();

  return 0;
}

but result: enter image description here

Can anyone help, how to show the alpha color with chessboard like background?


Solution

  • I took your code and turned it into a cairo-only program that saves an image.

    As already noted in comments by G.M., you don't seem to be drawing any checkerboard, so you do not get one.

    Also, you still have the same problem as in How to draw rainbow cairo linear gradient using rgb values from an array?: Cairo still expects colors between 0.0 and 1.0 and not between 0.0 and 256.0.

    Program:

    #include <cairo.h>
    #include <stdint.h>
    #include <stdio.h>
    
    #define WIDTH 300
    #define HEIGHT 100
    
    cairo_surface_t *create_2x2_checkerboard(void)
    {
        cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 2, 2);
        cairo_t *cr = cairo_create(s);
    
        cairo_set_source_rgb(cr, 0.75, 0.75, 0.75);
        cairo_paint(cr);
    
        cairo_set_source_rgb(cr, 0.25, 0.25, 0.25);
        cairo_rectangle(cr, 1, 0, 1, 1);
        cairo_rectangle(cr, 0, 1, 1, 1);
        cairo_fill(cr);
    
        cairo_destroy(cr);
        return s;
    }
    
    void draw_checkerboard(cairo_t *cr)
    {
        cairo_matrix_t matrix;
        cairo_surface_t *checkerboard = create_2x2_checkerboard();
    
        cairo_matrix_init_scale(&matrix, 1.0/12.0, 1.0/12.0);
    
        cairo_save(cr);
        cairo_set_source_surface(cr, checkerboard, 0, 0);
        cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REPEAT);
        cairo_pattern_set_matrix(cairo_get_source(cr), &matrix);
        cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
        cairo_paint(cr);
        cairo_restore(cr);
    
        cairo_surface_destroy(checkerboard);
    }
    
    void draw_gradient(cairo_t *cr)
    {
        cairo_pattern_t *gradient;
    
        draw_checkerboard(cr);
    
        gradient =cairo_pattern_create_linear(0.0, 0.0, WIDTH, 0.0); 
        cairo_pattern_add_color_stop_rgba (gradient, 0, 75.0/256.0,0,130.0/256.0, 0.3); //Purple with alpha 
        cairo_pattern_add_color_stop_rgba (gradient, 1, 75.0/256.0,0,130.0/256.0, 1); //Purple
    
        cairo_set_source (cr, gradient);
    
        cairo_paint (cr);
    
        cairo_pattern_destroy (gradient);
    }
    
    int main(int argc, char *argv[])
    {
        cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, WIDTH, HEIGHT);
        cairo_t *cr = cairo_create(s);
        draw_gradient(cr);
        cairo_surface_write_to_png(s, "gradient.png");
        cairo_surface_destroy(s);
        cairo_destroy(cr);
    
      return 0;
    }
    

    Output: Output of the program