1
/*
2
 * Copyright © 2007 Chris Wilson.
3
 *
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.
14
 *
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.
22
 *
23
 * Author: Chris Wilson <chris at chris-wilson.co.uk>
24
 */
25

            
26
#include "config.h"
27

            
28
#include "cairo-test.h"
29
#include <stdlib.h> /* drand48() */
30

            
31
#define LOOPS 10
32
#define NRAND 100
33

            
34
#ifndef HAVE_DRAND48
35
#define drand48() (rand () / (double) RAND_MAX)
36
#endif
37

            
38
static cairo_scaled_font_t *scaled_font;
39

            
40
static cairo_t *
41
5400
_cairo_create_similar (cairo_t *cr, int width, int height)
42
{
43
    cairo_surface_t *similar;
44

            
45
5400
    similar = cairo_surface_create_similar (cairo_get_target (cr),
46
	                                    cairo_surface_get_content (cairo_get_target (cr)),
47
				            width, height);
48
5400
    cr = cairo_create (similar);
49
5400
    cairo_surface_destroy (similar);
50

            
51
5400
    return cr;
52
}
53

            
54
static cairo_t *
55
21600
_cairo_create_image (cairo_t *cr, cairo_format_t format, int width, int height)
56
{
57
    cairo_surface_t *image;
58

            
59
21600
    image = cairo_image_surface_create (format, width, height);
60
21600
    cr = cairo_create (image);
61
21600
    cairo_surface_destroy (image);
62

            
63
21600
    return cr;
64
}
65

            
66
static void
67
27000
_propagate_status (cairo_t *dst, cairo_t *src)
68
{
69
    cairo_path_t path;
70

            
71
27000
    path.status = cairo_status (src);
72
27000
    if (path.status) {
73
	path.num_data = 0;
74
	path.data = NULL;
75
	cairo_append_path (dst, &path);
76
    }
77
27000
}
78

            
79
static void
80
32400
_draw (cairo_t *cr,
81
       double red,
82
       double green,
83
       double blue)
84
{
85
    cairo_text_extents_t extents;
86

            
87
32400
    cairo_set_source_rgb (cr, red, green, blue);
88
32400
    cairo_paint (cr);
89

            
90
32400
    cairo_move_to (cr, 0, 0);
91
32400
    cairo_line_to (cr, 1, 1);
92
32400
    cairo_stroke (cr);
93

            
94
32400
    cairo_mask (cr, cairo_get_source (cr));
95

            
96
32400
    cairo_set_scaled_font (cr, scaled_font);
97
32400
    cairo_text_extents (cr, "cairo", &extents);
98
32400
    cairo_move_to (cr,
99
32400
	           -extents.x_bearing - .5 * extents.width,
100
32400
		   -extents.y_bearing - .5 * extents.height);
101
32400
    cairo_show_text (cr, "cairo");
102
32400
}
103

            
104
static void
105
5400
use_similar (cairo_t *cr,
106
	    double red,
107
	    double green,
108
	    double blue)
109
{
110
    cairo_t *cr2;
111

            
112
5400
    if (cairo_status (cr))
113
	return;
114

            
115
5400
    cr2 = _cairo_create_similar (cr, 1, 1);
116

            
117
5400
    _draw (cr2, red, green, blue);
118

            
119
5400
    _propagate_status (cr, cr2);
120
5400
    cairo_destroy (cr2);
121
}
122

            
123
static void
124
21600
use_image (cairo_t *cr,
125
	   cairo_format_t format,
126
	   double red,
127
	   double green,
128
	   double blue)
129
{
130
    cairo_t *cr2;
131

            
132
21600
    if (cairo_status (cr))
133
	return;
134

            
135
21600
    cr2 = _cairo_create_image (cr, format, 1, 1);
136

            
137
21600
    _draw (cr2, red, green, blue);
138

            
139
21600
    _propagate_status (cr, cr2);
140
21600
    cairo_destroy (cr2);
141
}
142

            
143
static void
144
5400
use_solid (cairo_t *cr,
145
	   double red,
146
	   double green,
147
	   double blue)
148
{
149
    /* mix in dissimilar solids */
150
5400
    use_image (cr, CAIRO_FORMAT_A1, red, green, blue);
151
5400
    use_image (cr, CAIRO_FORMAT_A8, red, green, blue);
152
5400
    use_image (cr, CAIRO_FORMAT_RGB24, red, green, blue);
153
5400
    use_image (cr, CAIRO_FORMAT_ARGB32, red, green, blue);
154

            
155
5400
    use_similar (cr, red, green, blue);
156

            
157
5400
    _draw (cr, red, green, blue);
158
5400
}
159

            
160
static cairo_test_status_t
161
3
draw (cairo_t *cr, int width, int height)
162
{
163
3
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
164
    cairo_status_t status;
165
3
    const double colors[8][3] = {
166
	{ 1.0, 0.0, 0.0 }, /* red */
167
	{ 0.0, 1.0, 0.0 }, /* green */
168
	{ 1.0, 1.0, 0.0 }, /* yellow */
169
	{ 0.0, 0.0, 1.0 }, /* blue */
170
	{ 1.0, 0.0, 1.0 }, /* magenta */
171
	{ 0.0, 1.0, 1.0 }, /* cyan */
172
	{ 1.0, 1.0, 1.0 }, /* white */
173
	{ 0.0, 0.0, 0.0 }, /* black */
174
    };
175
    int i, j, loop;
176

            
177
    /* cache a resolved scaled-font */
178
3
    scaled_font = cairo_get_scaled_font (cr);
179

            
180
33
    for (loop = 0; loop < LOOPS; loop++) {
181
330
	for (i = 0; i < LOOPS; i++) {
182
2700
	    for (j = 0; j < 8; j++) {
183
2400
		use_solid (cr, colors[j][0], colors[j][1], colors[j][2]);
184
2400
		status = cairo_status (cr);
185
2400
		if (status)
186
		    return cairo_test_status_from_status (ctx, status);
187
	    }
188
	}
189

            
190
3030
	for (i = 0; i < NRAND; i++) {
191
3000
	    use_solid (cr, drand48 (), drand48 (), drand48 ());
192
3000
	    status = cairo_status (cr);
193
3000
	    if (status)
194
		return cairo_test_status_from_status (ctx, status);
195
	}
196
    }
197

            
198
    /* stress test only, so clear the surface before comparing */
199
3
    cairo_set_source_rgb (cr, 0, 0, 1);
200
3
    cairo_paint (cr);
201

            
202
3
    return CAIRO_TEST_SUCCESS;
203
}
204

            
205
1
CAIRO_TEST (solid_pattern_cache_stress,
206
	    "Stress the solid pattern cache and ensure it behaves",
207
	    "stress", /* keywords */
208
	    NULL, /* requirements */
209
	    1, 1,
210
	    NULL, draw)