Add powerbox hook
[gtk-with-powerbox.git] / tests / testcairo.c
blobb2a232b0265da6498c08287789c273c6aed6ebbb
1 /* testimage.c
2 * Copyright (C) 2005 Red Hat, Inc.
3 * Based on cairo-demo/X11/cairo-knockout.c
5 * Author: Owen Taylor
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.
23 #include <math.h>
25 #include <gtk/gtk.h>
27 static void
28 oval_path (cairo_t *cr,
29 double xc, double yc,
30 double xr, double yr)
32 cairo_save (cr);
34 cairo_translate (cr, xc, yc);
35 cairo_scale (cr, 1.0, yr / xr);
36 cairo_move_to (cr, xr, 0.0);
37 cairo_arc (cr,
38 0, 0,
39 xr,
40 0, 2 * G_PI);
41 cairo_close_path (cr);
43 cairo_restore (cr);
46 /* Create a path that is a circular oval with radii xr, yr at xc,
47 * yc.
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.
57 static void
58 fill_checks (cairo_t *cr,
59 int x, int y,
60 int width, int height)
62 int i, j;
64 #define CHECK_SIZE 32
66 cairo_rectangle (cr, x, y, width, height);
67 cairo_set_source_rgb (cr, 0.4, 0.4, 0.4);
68 cairo_fill (cr);
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);
82 cairo_fill (cr);
85 /* Draw a red, green, and blue circle equally spaced inside
86 * the larger circle of radius r at (xc, yc)
88 static void
89 draw_3circles (cairo_t *cr,
90 double xc, double yc,
91 double radius,
92 double alpha)
94 double subradius = radius * (2 / 3. - 0.1);
96 cairo_set_source_rgba (cr, 1., 0., 0., alpha);
97 oval_path (cr,
98 xc + radius / 3. * cos (G_PI * (0.5)),
99 yc - radius / 3. * sin (G_PI * (0.5)),
100 subradius, subradius);
101 cairo_fill (cr);
103 cairo_set_source_rgba (cr, 0., 1., 0., alpha);
104 oval_path (cr,
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);
108 cairo_fill (cr);
110 cairo_set_source_rgba (cr, 0., 0., 1., alpha);
111 oval_path (cr,
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);
115 cairo_fill (cr);
118 static void
119 draw (cairo_t *cr,
120 int width,
121 int height)
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,
133 width, height);
134 if (overlay == NULL)
135 return;
137 punch = cairo_surface_create_similar (cairo_get_target (cr),
138 CAIRO_CONTENT_ALPHA,
139 width, height);
140 if (punch == NULL)
141 return;
143 circles = cairo_surface_create_similar (cairo_get_target (cr),
144 CAIRO_CONTENT_COLOR_ALPHA,
145 width, height);
146 if (circles == NULL)
147 return;
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
171 * without seams.
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);
186 cairo_paint (cr);
188 cairo_surface_destroy (overlay);
189 cairo_surface_destroy (punch);
190 cairo_surface_destroy (circles);
193 static gboolean
194 on_expose_event (GtkWidget *widget,
195 GdkEventExpose *event,
196 gpointer data)
198 cairo_t *cr;
200 cr = gdk_cairo_create (widget->window);
202 draw (cr, widget->allocation.width, widget->allocation.height);
204 cairo_destroy (cr);
206 return FALSE;
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);
231 gtk_main ();
233 return 0;