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,
34
cairo_translate (cr, xc, yc);
35
cairo_scale (cr, 1.0, yr / xr);
36
cairo_move_to (cr, xr, 0.0);
41
cairo_close_path (cr);
46
/* Create a path that is a circular oval with radii xr, yr at xc,
49
/* Fill the given area with checks in the standard style
50
* for showing compositing effects.
52
* It would make sense to do this as a repeating surface,
53
* but most implementations of RENDER currently have broken
54
* implementations of repeat + transform, even when the
55
* transform is a translation.
58
fill_checks (cairo_t *cr,
60
int width, int height)
66
cairo_rectangle (cr, x, y, width, height);
67
cairo_set_source_rgb (cr, 0.4, 0.4, 0.4);
70
/* Only works for CHECK_SIZE a power of 2 */
71
j = x & (-CHECK_SIZE);
73
for (; j < height; j += CHECK_SIZE)
75
i = y & (-CHECK_SIZE);
76
for (; i < width; i += CHECK_SIZE)
77
if ((i / CHECK_SIZE + j / CHECK_SIZE) % 2 == 0)
78
cairo_rectangle (cr, i, j, CHECK_SIZE, CHECK_SIZE);
81
cairo_set_source_rgb (cr, 0.7, 0.7, 0.7);
85
/* Draw a red, green, and blue circle equally spaced inside
86
* the larger circle of radius r at (xc, yc)
89
draw_3circles (cairo_t *cr,
94
double subradius = radius * (2 / 3. - 0.1);
96
cairo_set_source_rgba (cr, 1., 0., 0., alpha);
98
xc + radius / 3. * cos (G_PI * (0.5)),
99
yc - radius / 3. * sin (G_PI * (0.5)),
100
subradius, subradius);
103
cairo_set_source_rgba (cr, 0., 1., 0., alpha);
105
xc + radius / 3. * cos (G_PI * (0.5 + 2/.3)),
106
yc - radius / 3. * sin (G_PI * (0.5 + 2/.3)),
107
subradius, subradius);
110
cairo_set_source_rgba (cr, 0., 0., 1., alpha);
112
xc + radius / 3. * cos (G_PI * (0.5 + 4/.3)),
113
yc - radius / 3. * sin (G_PI * (0.5 + 4/.3)),
114
subradius, subradius);
123
cairo_surface_t *overlay, *punch, *circles;
124
cairo_t *overlay_cr, *punch_cr, *circles_cr;
126
/* Fill the background */
127
double radius = 0.5 * (width < height ? width : height) - 10;
128
double xc = width / 2.;
129
double yc = height / 2.;
131
overlay = cairo_surface_create_similar (cairo_get_target (cr),
132
CAIRO_CONTENT_COLOR_ALPHA,
137
punch = cairo_surface_create_similar (cairo_get_target (cr),
143
circles = cairo_surface_create_similar (cairo_get_target (cr),
144
CAIRO_CONTENT_COLOR_ALPHA,
149
fill_checks (cr, 0, 0, width, height);
151
/* Draw a black circle on the overlay
153
overlay_cr = cairo_create (overlay);
154
cairo_set_source_rgb (overlay_cr, 0., 0., 0.);
155
oval_path (overlay_cr, xc, yc, radius, radius);
156
cairo_fill (overlay_cr);
158
/* Draw 3 circles to the punch surface, then cut
159
* that out of the main circle in the overlay
161
punch_cr = cairo_create (punch);
162
draw_3circles (punch_cr, xc, yc, radius, 1.0);
163
cairo_destroy (punch_cr);
165
cairo_set_operator (overlay_cr, CAIRO_OPERATOR_DEST_OUT);
166
cairo_set_source_surface (overlay_cr, punch, 0, 0);
167
cairo_paint (overlay_cr);
169
/* Now draw the 3 circles in a subgroup again
170
* at half intensity, and use OperatorAdd to join up
173
circles_cr = cairo_create (circles);
175
cairo_set_operator (circles_cr, CAIRO_OPERATOR_OVER);
176
draw_3circles (circles_cr, xc, yc, radius, 0.5);
177
cairo_destroy (circles_cr);
179
cairo_set_operator (overlay_cr, CAIRO_OPERATOR_ADD);
180
cairo_set_source_surface (overlay_cr, circles, 0, 0);
181
cairo_paint (overlay_cr);
183
cairo_destroy (overlay_cr);
185
cairo_set_source_surface (cr, overlay, 0, 0);
188
cairo_surface_destroy (overlay);
189
cairo_surface_destroy (punch);
190
cairo_surface_destroy (circles);
194
on_expose_event (GtkWidget *widget,
195
GdkEventExpose *event,
200
cr = gdk_cairo_create (widget->window);
202
draw (cr, widget->allocation.width, widget->allocation.height);
210
main (int argc, char **argv)
212
GtkWidget *window, *darea;
214
gtk_init (&argc, &argv);
216
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
218
gtk_window_set_default_size (GTK_WINDOW (window), 400, 400);
219
gtk_window_set_title (GTK_WINDOW (window), "cairo: Knockout Groups");
221
darea = gtk_drawing_area_new ();
222
gtk_container_add (GTK_CONTAINER (window), darea);
224
g_signal_connect (darea, "expose-event",
225
G_CALLBACK (on_expose_event), NULL);
226
g_signal_connect (window, "destroy-event",
227
G_CALLBACK (gtk_main_quit), NULL);
229
gtk_widget_show_all (window);