2 * Copyright © 2007 Chris Wilson
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Chris Wilson not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior
11 * permission. Chris Wilson makes no representations about the
12 * suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
15 * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
18 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
21 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: Chris Wilson <chris@chris-wilson.co.uk>
25 * Inspiration (and path!) taken from
26 * http://labs.trolltech.com/blogs/2007/08/31/rasterizing-dragons/
29 #include "cairo-perf.h"
32 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
36 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
60 np2 = next_pot (i + 1);
65 return ! direction (2 * pivot - i);
69 path (cairo_t *cr, int step, int dir, int iterations)
76 case 0: dx = step; dy = 0; break;
77 case 1: dx = -step; dy = 0; break;
78 case 2: dx = 0; dy = step; break;
79 case 3: dx = 0; dy = -step; break;
82 for (i = 0; i < iterations; i++) {
83 cairo_rel_line_to (cr, dx, dy);
98 do_dragon (cairo_t *cr, int width, int height, int loops)
100 cairo_pattern_t *pattern;
103 cx = cy = .5 * MAX (width, height);
104 r = .5 * MIN (width, height);
106 cairo_perf_timer_start ();
107 cairo_perf_set_thread_aware (cr, FALSE);
111 cairo_perf_set_thread_aware (cr, TRUE);
112 pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
113 cairo_pattern_add_color_stop_rgb (pattern, 0., .0, .0, .0);
114 cairo_pattern_add_color_stop_rgb (pattern, 0.25, .5, .4, .4);
115 cairo_pattern_add_color_stop_rgb (pattern, .5, .8, .8, .9);
116 cairo_pattern_add_color_stop_rgb (pattern, 1., .9, .9, 1.);
117 cairo_set_source (cr, pattern);
118 cairo_pattern_destroy (pattern);
121 cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
122 cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
123 cairo_set_line_width (cr, 4.);
125 cairo_move_to (cr, cx, cy);
126 path (cr, 12, 0, 2048);
127 pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
128 cairo_pattern_add_color_stop_rgb (pattern, 0., 1., 1., 1.);
129 cairo_pattern_add_color_stop_rgb (pattern, 1., 0., 0., 0.);
130 cairo_set_source (cr, pattern);
131 cairo_pattern_destroy (pattern);
134 cairo_move_to (cr, cx, cy);
135 path (cr, 12, 1, 2048);
136 pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
137 cairo_pattern_add_color_stop_rgb (pattern, 1., 1., 1., 0.);
138 cairo_pattern_add_color_stop_rgb (pattern, 0., 1., 0., 0.);
139 cairo_set_source (cr, pattern);
140 cairo_pattern_destroy (pattern);
143 cairo_move_to (cr, cx, cy);
144 path (cr, 12, 2, 2048);
145 pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
146 cairo_pattern_add_color_stop_rgb (pattern, 1., 0., 1., 1.);
147 cairo_pattern_add_color_stop_rgb (pattern, 0., 0., 1., 0.);
148 cairo_set_source (cr, pattern);
149 cairo_pattern_destroy (pattern);
152 cairo_move_to (cr, cx, cy);
153 path (cr, 12, 3, 2048);
154 pattern = cairo_pattern_create_radial (cx, cy, 0., cx, cy, r);
155 cairo_pattern_add_color_stop_rgb (pattern, 1., 1., 0., 1.);
156 cairo_pattern_add_color_stop_rgb (pattern, 0., 0., 0., 1.);
157 cairo_set_source (cr, pattern);
158 cairo_pattern_destroy (pattern);
162 cairo_perf_timer_stop ();
164 return cairo_perf_timer_elapsed ();
168 do_dragon_solid (cairo_t *cr, int width, int height, int loops)
172 cx = cy = .5 * MAX (width, height);
174 cairo_perf_timer_start ();
175 cairo_perf_set_thread_aware (cr, FALSE);
179 cairo_perf_set_thread_aware (cr, TRUE);
180 cairo_set_source_rgb (cr, 0, 0, 0);
183 cairo_set_line_width (cr, 4.);
185 cairo_move_to (cr, cx, cy);
186 path (cr, 12, 0, 2048);
187 cairo_set_source_rgb (cr, 1, 0, 0);
190 cairo_move_to (cr, cx, cy);
191 path (cr, 12, 1, 2048);
192 cairo_set_source_rgb (cr, 0, 1, 0);
195 cairo_move_to (cr, cx, cy);
196 path (cr, 12, 2, 2048);
197 cairo_set_source_rgb (cr, 0, 0, 1);
200 cairo_move_to (cr, cx, cy);
201 path (cr, 12, 3, 2048);
202 cairo_set_source_rgb (cr, 1, 1, 1);
206 cairo_perf_timer_stop ();
208 return cairo_perf_timer_elapsed ();
212 do_dragon_solid_unaligned (cairo_t *cr, int width, int height, int loops)
214 cairo_translate (cr, 0.01, 0.01);
215 return do_dragon_solid (cr, width, height, loops);
219 do_dragon_solid_aligned_clip (cairo_t *cr, int width, int height, int loops)
221 cairo_reset_clip (cr);
222 cairo_rectangle (cr, 10, 10, width/2 + 10, height/2 + 10);
223 cairo_rectangle (cr, width/2-20, height/2-20, width/2 + 10, height/2 + 10);
226 return do_dragon_solid (cr, width, height, loops);
230 do_dragon_unaligned_solid_aligned_clip (cairo_t *cr, int width, int height, int loops)
232 cairo_translate (cr, 0.01, 0.01);
233 cairo_reset_clip (cr);
234 cairo_rectangle (cr, 10, 10, width/2 + 10, height/2 + 10);
235 cairo_rectangle (cr, width/2-20, height/2-20, width/2 + 10, height/2 + 10);
238 return do_dragon_solid (cr, width, height, loops);
242 do_dragon_solid_unaligned_clip (cairo_t *cr, int width, int height, int loops)
244 cairo_reset_clip (cr);
245 cairo_rectangle (cr, 10.5, 10.5, width/2 + 10, height/2 + 10);
246 cairo_rectangle (cr, width/2-20, height/2-20, width/2 + 9.5, height/2 + 9.5);
249 return do_dragon_solid (cr, width, height, loops);
253 do_dragon_unaligned_solid_unaligned_clip (cairo_t *cr, int width, int height, int loops)
255 cairo_translate (cr, 0.01, 0.01);
256 cairo_reset_clip (cr);
257 cairo_rectangle (cr, 10.5, 10.5, width/2 + 10, height/2 + 10);
258 cairo_rectangle (cr, width/2-20, height/2-20, width/2 + 9.5, height/2 + 9.5);
261 return do_dragon_solid (cr, width, height, loops);
265 do_dragon_solid_circle_clip (cairo_t *cr, int width, int height, int loops)
267 cairo_reset_clip (cr);
268 cairo_arc (cr, width/2., height/2., MIN (width, height)/2. - 10, 0, 2 * M_PI);
271 return do_dragon_solid (cr, width, height, loops);
275 dragon_enabled (cairo_perf_t *perf)
277 return cairo_perf_can_run (perf, "dragon", NULL);
281 dragon (cairo_perf_t *perf, cairo_t *cr, int width, int height)
283 cairo_perf_run (perf, "dragon-solid", do_dragon_solid, NULL);
284 cairo_perf_run (perf, "dragon-unaligned-solid", do_dragon_solid_unaligned, NULL);
285 cairo_perf_run (perf, "dragon-solid-aligned-clip", do_dragon_solid_aligned_clip, NULL);
286 cairo_perf_run (perf, "dragon-unaligned-solid-aligned-clip", do_dragon_unaligned_solid_aligned_clip, NULL);
287 cairo_perf_run (perf, "dragon-solid-unaligned-clip", do_dragon_solid_unaligned_clip, NULL);
288 cairo_perf_run (perf, "dragon-unaligned-solid-unaligned-clip", do_dragon_unaligned_solid_unaligned_clip, NULL);
289 cairo_perf_run (perf, "dragon-solid-circle-clip", do_dragon_solid_circle_clip, NULL);
290 cairo_perf_run (perf, "dragon", do_dragon, NULL);