2 * Copyright (C) 2005 Red Hat, Inc.
3 * Based on cairo-demo/X11/cairo-knockout.c
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
28 oval_path (cairo_t *cr,
32 cairo_matrix_t *matrix;
34 matrix = cairo_matrix_create ();
35 cairo_current_matrix (cr, matrix);
37 cairo_translate (cr, xc, yc);
38 cairo_scale (cr, 1.0, yr / xr);
39 cairo_move_to (cr, xr, 0.0);
44 cairo_close_path (cr);
46 cairo_set_matrix (cr, matrix);
47 cairo_matrix_destroy (matrix);
50 /* Create a path that is a circular oval with radii xr, yr at xc,
53 /* Fill the given area with checks in the standard style
54 * for showing compositing effects.
56 * It would make sense to do this as a repeating surface,
57 * but most implementations of RENDER currently have broken
58 * implementations of repeat + transform, even when the
59 * transform is a translation.
62 fill_checks (cairo_t *cr,
64 int width, int height)
70 cairo_rectangle (cr, x, y, width, height);
71 cairo_set_rgb_color (cr, 0.4, 0.4, 0.4);
74 /* Only works for CHECK_SIZE a power of 2 */
75 j = x & (-CHECK_SIZE);
77 for (; j < height; j += CHECK_SIZE)
79 i = y & (-CHECK_SIZE);
80 for (; i < width; i += CHECK_SIZE)
81 if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0)
82 cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE);
85 cairo_set_rgb_color (cr, 0.7, 0.7, 0.7);
89 /* Draw a red, green, and blue circle equally spaced inside
90 * the larger circle of radius r at (xc, yc)
93 draw_3circles (cairo_t *cr,
97 double subradius = radius * (2 / 3. - 0.1);
99 cairo_set_rgb_color (cr, 1., 0., 0.);
101 xc + radius / 3. * cos (G_PI * (0.5)),
102 yc - radius / 3. * sin (G_PI * (0.5)),
103 subradius, subradius);
106 cairo_set_rgb_color (cr, 0., 1., 0.);
108 xc + radius / 3. * cos (G_PI * (0.5 + 2/.3)),
109 yc - radius / 3. * sin (G_PI * (0.5 + 2/.3)),
110 subradius, subradius);
113 cairo_set_rgb_color (cr, 0., 0., 1.);
115 xc + radius / 3. * cos (G_PI * (0.5 + 4/.3)),
116 yc - radius / 3. * sin (G_PI * (0.5 + 4/.3)),
117 subradius, subradius);
126 cairo_surface_t *overlay, *punch, *circles;
128 /* Fill the background */
129 double radius = 0.5 * (width < height ? width : height) - 10;
130 double xc = width / 2.;
131 double yc = height / 2.;
133 overlay = cairo_surface_create_similar (cairo_current_target_surface (cr),
139 punch = cairo_surface_create_similar (cairo_current_target_surface (cr),
145 circles = cairo_surface_create_similar (cairo_current_target_surface (cr),
151 fill_checks (cr, 0, 0, width, height);
154 cairo_set_target_surface (cr, overlay);
155 cairo_identity_matrix (cr);
157 /* Draw a black circle on the overlay
159 cairo_set_rgb_color (cr, 0., 0., 0.);
160 oval_path (cr, xc, yc, radius, radius);
164 cairo_set_target_surface (cr, punch);
166 /* Draw 3 circles to the punch surface, then cut
167 * that out of the main circle in the overlay
169 draw_3circles (cr, xc, yc, radius);
173 cairo_set_operator (cr, CAIRO_OPERATOR_OUT_REVERSE);
174 cairo_show_surface (cr, punch, width, height);
176 /* Now draw the 3 circles in a subgroup again
177 * at half intensity, and use OperatorAdd to join up
181 cairo_set_target_surface (cr, circles);
183 cairo_set_alpha (cr, 0.5);
184 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
185 draw_3circles (cr, xc, yc, radius);
189 cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
190 cairo_show_surface (cr, circles, width, height);
194 cairo_show_surface (cr, overlay, width, height);
196 cairo_surface_destroy (overlay);
197 cairo_surface_destroy (punch);
198 cairo_surface_destroy (circles);
202 on_expose_event (GtkWidget *widget,
203 GdkEventExpose *event,
208 cr = cairo_create ();
209 gdk_drawable_set_cairo_target (GDK_DRAWABLE (widget->window), cr);
211 draw (cr, widget->allocation.width, widget->allocation.height);
219 main (int argc, char **argv)
221 GtkWidget *window, *darea;
223 gtk_init (&argc, &argv);
225 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
227 gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
228 gtk_window_set_title (GTK_WINDOW (window), "cairo: Knockout Groups");
230 darea = gtk_drawing_area_new ();
231 gtk_container_add (GTK_CONTAINER (window), darea);
233 g_signal_connect (darea, "expose-event",
234 G_CALLBACK (on_expose_event), NULL);
235 g_signal_connect (window, "destroy-event",
236 G_CALLBACK (gtk_main_quit), NULL);
238 gtk_widget_show_all (window);