1 /*
2  * Copyright © 2006 Red Hat, Inc.
3  *
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use, copy,
9  * modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  *
25  * Author: Carl D. Worth <cworth@cworth.org>
26  */
27 
28 #include "cairo-perf.h"
29 
30 /* This test case is designed to illustrate a performance bug that
31  * exists in cairo in which using cairo_stroke is much slower than
32  * cairo_fill to draw an identical figure, (and in particular a figure
33  * that is much more natural to draw with cairo_stroke). The figure is
34  * a 100x100 square outline 1-pixel wide, nicely pixel aligned.
35  *
36  * The performance bug should affect any path whose resulting contour
37  * consists only of pixel-aligned horizontal and vertical elements.
38  *
39  * Initial testing on on machine shows stroke as 5x slower than fill
40  * for the xlib backend and 16x slower for the image backend.
41  */
42 
43 static cairo_time_t
box_outline_stroke(cairo_t * cr,int width,int height,int loops)44 box_outline_stroke (cairo_t *cr, int width, int height, int loops)
45 {
46     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
47     cairo_paint (cr);
48 
49     cairo_rectangle (cr,
50 		     1.5, 1.5,
51 		     width - 3, height - 3);
52     cairo_set_line_width (cr, 1.0);
53     cairo_set_source_rgb (cr, 1, 0, 0); /* red */
54 
55     cairo_perf_timer_start ();
56 
57     while (loops--)
58 	cairo_stroke_preserve (cr);
59 
60     cairo_perf_timer_stop ();
61 
62     cairo_new_path (cr);
63 
64     return cairo_perf_timer_elapsed ();
65 }
66 
67 static cairo_time_t
box_outline_alpha_stroke(cairo_t * cr,int width,int height,int loops)68 box_outline_alpha_stroke (cairo_t *cr, int width, int height, int loops)
69 {
70     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
71     cairo_paint (cr);
72 
73     cairo_rectangle (cr,
74 		     1.5, 1.5,
75 		     width - 3, height - 3);
76     cairo_set_line_width (cr, 1.0);
77     cairo_set_source_rgba (cr, 1, 0, 0, .5); /* red */
78 
79     cairo_perf_timer_start ();
80 
81     while (loops--)
82 	cairo_stroke_preserve (cr);
83 
84     cairo_perf_timer_stop ();
85 
86     cairo_new_path (cr);
87 
88     return cairo_perf_timer_elapsed ();
89 }
90 
91 static cairo_time_t
box_outline_aa_stroke(cairo_t * cr,int width,int height,int loops)92 box_outline_aa_stroke (cairo_t *cr, int width, int height, int loops)
93 {
94     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
95     cairo_paint (cr);
96 
97     cairo_translate (cr, .5, .5);
98     cairo_rectangle (cr,
99 		     1.5, 1.5,
100 		     width - 3, height - 3);
101     cairo_set_line_width (cr, 1.0);
102     cairo_set_source_rgb (cr, 1, 0, 0); /* red */
103 
104     cairo_perf_timer_start ();
105 
106     while (loops--)
107 	cairo_stroke_preserve (cr);
108 
109     cairo_perf_timer_stop ();
110 
111     cairo_new_path (cr);
112 
113     return cairo_perf_timer_elapsed ();
114 }
115 
116 static cairo_time_t
box_outline_fill(cairo_t * cr,int width,int height,int loops)117 box_outline_fill (cairo_t *cr, int width, int height, int loops)
118 {
119     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
120     cairo_paint (cr);
121 
122     cairo_rectangle (cr,
123 		     1.0, 1.0,
124 		     width - 2, height - 2);
125     cairo_rectangle (cr,
126 		     2.0, 2.0,
127 		     width - 4, height - 4);
128     cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
129     cairo_set_source_rgb (cr, 0, 1, 0); /* green */
130 
131     cairo_perf_timer_start ();
132 
133     while (loops--)
134 	cairo_fill_preserve (cr);
135 
136     cairo_perf_timer_stop ();
137 
138     cairo_new_path (cr);
139 
140     return cairo_perf_timer_elapsed ();
141 }
142 
143 static cairo_time_t
box_outline_alpha_fill(cairo_t * cr,int width,int height,int loops)144 box_outline_alpha_fill (cairo_t *cr, int width, int height, int loops)
145 {
146     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
147     cairo_paint (cr);
148 
149     cairo_rectangle (cr,
150 		     1.0, 1.0,
151 		     width - 2, height - 2);
152     cairo_rectangle (cr,
153 		     2.0, 2.0,
154 		     width - 4, height - 4);
155     cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
156     cairo_set_source_rgba (cr, 0, 1, 0, .5); /* green */
157 
158     cairo_perf_timer_start ();
159 
160     while (loops--)
161 	cairo_fill_preserve (cr);
162 
163     cairo_perf_timer_stop ();
164 
165     cairo_new_path (cr);
166 
167     return cairo_perf_timer_elapsed ();
168 }
169 
170 static cairo_time_t
box_outline_aa_fill(cairo_t * cr,int width,int height,int loops)171 box_outline_aa_fill (cairo_t *cr, int width, int height, int loops)
172 {
173     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
174     cairo_paint (cr);
175 
176     cairo_translate (cr, .5, .5);
177     cairo_rectangle (cr,
178 		     1.0, 1.0,
179 		     width - 2, height - 2);
180     cairo_rectangle (cr,
181 		     2.0, 2.0,
182 		     width - 4, height - 4);
183     cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
184     cairo_set_source_rgb (cr, 0, 1, 0); /* green */
185 
186     cairo_perf_timer_start ();
187 
188     while (loops--)
189 	cairo_fill_preserve (cr);
190 
191     cairo_perf_timer_stop ();
192 
193     cairo_new_path (cr);
194 
195     return cairo_perf_timer_elapsed ();
196 }
197 
198 cairo_bool_t
box_outline_enabled(cairo_perf_t * perf)199 box_outline_enabled (cairo_perf_t *perf)
200 {
201     return cairo_perf_can_run (perf, "box-outline", NULL);
202 }
203 
204 void
box_outline(cairo_perf_t * perf,cairo_t * cr,int width,int height)205 box_outline (cairo_perf_t *perf, cairo_t *cr, int width, int height)
206 {
207     cairo_perf_run (perf, "box-outline-stroke", box_outline_stroke, NULL);
208     cairo_perf_run (perf, "box-outline-fill", box_outline_fill, NULL);
209 
210     cairo_perf_run (perf, "box-outline-alpha-stroke", box_outline_alpha_stroke, NULL);
211     cairo_perf_run (perf, "box-outline-alpha-fill", box_outline_alpha_fill, NULL);
212 
213     cairo_perf_run (perf, "box-outline-aa-stroke", box_outline_aa_stroke, NULL);
214     cairo_perf_run (perf, "box-outline-aa-fill", box_outline_aa_fill, NULL);
215 }
216