diff --git a/docs/reference/gtk/images/drawingarea.png b/docs/reference/gtk/images/drawingarea.png
new file mode 100644
index 0000000000..7ab304522b
Binary files /dev/null and b/docs/reference/gtk/images/drawingarea.png differ
diff --git a/docs/reference/gtk/images/glarea.png b/docs/reference/gtk/images/glarea.png
index 1325afcab0..50bf77c062 100644
Binary files a/docs/reference/gtk/images/glarea.png and b/docs/reference/gtk/images/glarea.png differ
diff --git a/docs/reference/gtk/meson.build b/docs/reference/gtk/meson.build
index 4e72c167da..30d7737339 100644
--- a/docs/reference/gtk/meson.build
+++ b/docs/reference/gtk/meson.build
@@ -259,6 +259,7 @@ images = [
'images/down-start.png',
'images/drop-down.png',
'images/drawing.png',
+ 'images/drawingarea.png',
'images/ease-in-out.png',
'images/ease-in.png',
'images/ease-out.png',
diff --git a/docs/reference/gtk/visual_index.xml b/docs/reference/gtk/visual_index.xml
index 82fc571465..664d3922fe 100644
--- a/docs/reference/gtk/visual_index.xml
+++ b/docs/reference/gtk/visual_index.xml
@@ -20,6 +20,7 @@
+
diff --git a/docs/tools/widgets.c b/docs/tools/widgets.c
index c99cef1d06..3cb08a3410 100644
--- a/docs/tools/widgets.c
+++ b/docs/tools/widgets.c
@@ -1497,6 +1497,7 @@ create_flow_box (void)
static WidgetInfo *
create_gl_area (void)
{
+ GtkWidget *vbox;
WidgetInfo *info;
GtkWidget *widget;
GtkWidget *gears;
@@ -1513,12 +1514,15 @@ create_gl_area (void)
gtk_style_context_add_provider (gtk_widget_get_style_context (gears), GTK_STYLE_PROVIDER (provider), 800);
g_object_unref (provider);
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 3);
gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
gtk_widget_set_valign (widget, GTK_ALIGN_FILL);
+ gtk_box_append (GTK_BOX (vbox), widget);
+ gtk_box_append (GTK_BOX (vbox), gtk_label_new ("GL Area"));
- add_margin (widget);
+ add_margin (vbox);
- info = new_widget_info ("glarea", widget, MEDIUM);
+ info = new_widget_info ("glarea", vbox, MEDIUM);
return info;
}
@@ -1741,6 +1745,185 @@ create_shortcuts_window (void)
return new_widget_info ("shortcuts-window", overlay, ASIS);
}
+static void
+oval_path (cairo_t *cr,
+ double xc, double yc,
+ double xr, double yr)
+{
+ cairo_save (cr);
+
+ cairo_translate (cr, xc, yc);
+ cairo_scale (cr, 1.0, yr / xr);
+ cairo_move_to (cr, xr, 0.0);
+ cairo_arc (cr,
+ 0, 0,
+ xr,
+ 0, 2 * G_PI);
+ cairo_close_path (cr);
+
+ cairo_restore (cr);
+}
+
+static void
+fill_checks (cairo_t *cr,
+ int x, int y,
+ int width, int height)
+{
+ int i, j;
+
+#define CHECK_SIZE 16
+
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_set_source_rgb (cr, 0.4, 0.4, 0.4);
+ cairo_fill (cr);
+
+ /* Only works for CHECK_SIZE a power of 2 */
+ j = x & (-CHECK_SIZE);
+
+ for (; j < height; j += CHECK_SIZE)
+ {
+ i = y & (-CHECK_SIZE);
+ for (; i < width; i += CHECK_SIZE)
+ if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0)
+ cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE);
+ }
+
+ cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
+ cairo_fill (cr);
+
+#undef CHECK_SIZE
+}
+
+static void
+draw_3circles (cairo_t *cr,
+ double xc, double yc,
+ double radius,
+ double alpha)
+{
+ double subradius = radius * (2 / 3. - 0.1);
+
+ cairo_set_source_rgba (cr, 1., 0., 0., alpha);
+ oval_path (cr,
+ xc + radius / 3. * cos (G_PI * (0.5)),
+ yc - radius / 3. * sin (G_PI * (0.5)),
+ subradius, subradius);
+ cairo_fill (cr);
+
+ cairo_set_source_rgba (cr, 0., 1., 0., alpha);
+ oval_path (cr,
+ xc + radius / 3. * cos (G_PI * (0.5 + 2/.3)),
+ yc - radius / 3. * sin (G_PI * (0.5 + 2/.3)),
+ subradius, subradius);
+ cairo_fill (cr);
+
+ cairo_set_source_rgba (cr, 0., 0., 1., alpha);
+ oval_path (cr,
+ xc + radius / 3. * cos (G_PI * (0.5 + 4/.3)),
+ yc - radius / 3. * sin (G_PI * (0.5 + 4/.3)),
+ subradius, subradius);
+ cairo_fill (cr);
+}
+
+static void
+groups_draw (GtkDrawingArea *darea,
+ cairo_t *cr,
+ int width,
+ int height,
+ gpointer data)
+{
+ cairo_surface_t *overlay, *punch, *circles;
+ cairo_t *overlay_cr, *punch_cr, *circles_cr;
+
+ /* Fill the background */
+ double radius = 0.5 * (width < height ? width : height) - 10;
+ double xc = width / 2.;
+ double yc = height / 2.;
+
+ overlay = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ width, height);
+
+ punch = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_ALPHA,
+ width, height);
+
+ circles = cairo_surface_create_similar (cairo_get_target (cr),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ width, height);
+
+ fill_checks (cr, 0, 0, width, height);
+
+ /* Draw a black circle on the overlay
+ */
+ overlay_cr = cairo_create (overlay);
+ cairo_set_source_rgb (overlay_cr, 0., 0., 0.);
+ oval_path (overlay_cr, xc, yc, radius, radius);
+ cairo_fill (overlay_cr);
+
+ /* Draw 3 circles to the punch surface, then cut
+ * that out of the main circle in the overlay
+ */
+ punch_cr = cairo_create (punch);
+ draw_3circles (punch_cr, xc, yc, radius, 1.0);
+ cairo_destroy (punch_cr);
+
+ cairo_set_operator (overlay_cr, CAIRO_OPERATOR_DEST_OUT);
+ cairo_set_source_surface (overlay_cr, punch, 0, 0);
+ cairo_paint (overlay_cr);
+
+ /* Now draw the 3 circles in a subgroup again
+ * at half intensity, and use OperatorAdd to join up
+ * without seams.
+ */
+ circles_cr = cairo_create (circles);
+
+ cairo_set_operator (circles_cr, CAIRO_OPERATOR_OVER);
+ draw_3circles (circles_cr, xc, yc, radius, 0.5);
+ cairo_destroy (circles_cr);
+
+ cairo_set_operator (overlay_cr, CAIRO_OPERATOR_ADD);
+ cairo_set_source_surface (overlay_cr, circles, 0, 0);
+ cairo_paint (overlay_cr);
+
+ cairo_destroy (overlay_cr);
+
+ cairo_set_source_surface (cr, overlay, 0, 0);
+ cairo_paint (cr);
+
+ cairo_surface_destroy (overlay);
+ cairo_surface_destroy (punch);
+ cairo_surface_destroy (circles);
+}
+
+
+static WidgetInfo *
+create_drawing_area (void)
+{
+ GtkWidget *vbox;
+ WidgetInfo *info;
+ GtkWidget *widget;
+ GtkWidget *da;
+
+ widget = gtk_frame_new (NULL);
+ da = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (da, 96, 96);
+ gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), groups_draw, NULL, NULL);
+ gtk_frame_set_child (GTK_FRAME (widget), da);
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+ gtk_widget_set_halign (widget, GTK_ALIGN_FILL);
+ gtk_widget_set_valign (widget, GTK_ALIGN_FILL);
+
+ gtk_box_append (GTK_BOX (vbox), widget);
+ gtk_box_append (GTK_BOX (vbox), gtk_label_new ("Drawing Area"));
+
+ add_margin (vbox);
+
+ info = new_widget_info ("drawingarea", vbox, MEDIUM);
+
+ return info;
+}
+
GList *
get_all_widgets (void)
{
@@ -1814,6 +1997,7 @@ get_all_widgets (void)
retval = g_list_prepend (retval, create_popover ());
retval = g_list_prepend (retval, create_menu ());
retval = g_list_prepend (retval, create_shortcuts_window ());
+ retval = g_list_prepend (retval, create_drawing_area());
return retval;
}