1
/*
2
 * Copyright © 2005 Red Hat, Inc.
3
 * Copyright © 2007 Emmanuel Pacaud
4
 * Copyright © 2008 Benjamin Otte
5
 *
6
 * Permission to use, copy, modify, distribute, and sell this software
7
 * and its documentation for any purpose is hereby granted without
8
 * fee, provided that the above copyright notice appear in all copies
9
 * and that both that copyright notice and this permission notice
10
 * appear in supporting documentation, and that the name of
11
 * Red Hat, Inc. not be used in advertising or publicity pertaining to
12
 * distribution of the software without specific, written prior
13
 * permission. Red Hat, Inc. makes no representations about the
14
 * suitability of this software for any purpose.  It is provided "as
15
 * is" without express or implied warranty.
16
 *
17
 * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19
 * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
20
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
23
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
 *
25
 * Authors: Owen Taylor <otaylor@redhat.com>
26
 *          Kristian Høgsberg <krh@redhat.com>
27
 *          Emmanuel Pacaud <emmanuel.pacaud@lapp.in2p3.fr>
28
 */
29

            
30
#include "cairo-test.h"
31
#include <math.h>
32
#include <stdio.h>
33

            
34
#define STEPS 16
35
#define START_OPERATOR	CAIRO_OPERATOR_MULTIPLY
36
#define STOP_OPERATOR	CAIRO_OPERATOR_HSL_LUMINOSITY
37

            
38
#define SIZE 5
39
#define COUNT 4
40
#define FULL_WIDTH  ((STEPS + 1) * COUNT - 1)
41
#define FULL_HEIGHT ((COUNT + STOP_OPERATOR - START_OPERATOR) / COUNT) * (STEPS + 1)
42

            
43
static void
44
14400
set_solid_pattern (cairo_t *cr,
45
		   int step,
46
		   cairo_bool_t bg,
47
		   cairo_bool_t alpha)
48
{
49
    double c, a;
50

            
51
14400
    a = ((double) step) / (STEPS - 1);
52
14400
    if (alpha) {
53
7200
	c = 1;
54
    } else {
55
7200
	c = a;
56
7200
	a = 1;
57
    }
58

            
59
14400
    if (bg) /* draw a yellow background fading in using discrete steps */
60
7200
	cairo_set_source_rgba (cr, c, c, 0, a);
61
    else /* draw a teal foreground pattern fading in using discrete steps */
62
7200
	cairo_set_source_rgba (cr, 0, c, c, a);
63
14400
}
64

            
65
/* expects a STEP*STEP pixel rectangle */
66
static void
67
450
do_blend_solid (cairo_t *cr, cairo_operator_t op, cairo_bool_t alpha)
68
{
69
    int x;
70

            
71
450
    cairo_save (cr);
72
450
    cairo_scale (cr, SIZE, SIZE);
73

            
74
450
    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
75
7650
    for (x = 0; x < STEPS; x++) {
76
	/* draw the background using discrete steps */
77
7200
	set_solid_pattern (cr, x, TRUE, alpha);
78
7200
	cairo_rectangle (cr, x, 0, 1, STEPS);
79
7200
	cairo_fill (cr);
80
    }
81

            
82
450
    cairo_set_operator (cr, op);
83
7650
    for (x = 0; x < STEPS; x++) {
84
	/* draw an orthogonal foreground pattern using discrete steps */
85
7200
	set_solid_pattern (cr, x, FALSE, alpha);
86
7200
	cairo_rectangle (cr, 0, x, STEPS, 1);
87
7200
	cairo_fill (cr);
88
    }
89

            
90
450
    cairo_restore (cr);
91
450
}
92

            
93
static void
94
180
create_patterns (cairo_t *cr,
95
		 cairo_surface_t **bg,
96
		 cairo_surface_t **fg,
97
		 cairo_bool_t alpha)
98
{
99
    cairo_t *bgcr, *fgcr;
100

            
101
180
    *bg = cairo_surface_create_similar (cairo_get_target (cr),
102
					CAIRO_CONTENT_COLOR_ALPHA,
103
					SIZE * STEPS,
104
					SIZE * STEPS);
105
180
    *fg = cairo_surface_create_similar (cairo_get_target (cr),
106
					CAIRO_CONTENT_COLOR_ALPHA,
107
					SIZE * STEPS,
108
					SIZE * STEPS);
109

            
110
180
    bgcr = cairo_create (*bg);
111
180
    fgcr = cairo_create (*fg);
112

            
113
180
    do_blend_solid (bgcr, CAIRO_OPERATOR_DEST, alpha);
114
180
    do_blend_solid (fgcr, CAIRO_OPERATOR_SOURCE, alpha);
115

            
116
180
    cairo_destroy (bgcr);
117
180
    cairo_destroy (fgcr);
118
180
}
119

            
120
/* expects a STEP*STEP pixel rectangle */
121
static void
122
90
do_blend (cairo_t *cr, cairo_operator_t op, cairo_bool_t alpha)
123
{
124
    cairo_surface_t *bg, *fg;
125

            
126
90
    create_patterns (cr, &bg, &fg, alpha);
127

            
128
90
    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
129
90
    cairo_set_source_surface (cr, bg, 0, 0);
130
90
    cairo_paint (cr);
131

            
132
90
    cairo_set_operator (cr, op);
133
90
    cairo_set_source_surface (cr, fg, 0, 0);
134
90
    cairo_paint (cr);
135

            
136
90
    cairo_surface_destroy (fg);
137
90
    cairo_surface_destroy (bg);
138
90
}
139

            
140
static void
141
90
do_blend_mask (cairo_t *cr, cairo_operator_t op, cairo_bool_t alpha)
142
{
143
    cairo_surface_t *bg, *fg;
144

            
145
90
    create_patterns (cr, &bg, &fg, alpha);
146

            
147
90
    cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
148
90
    cairo_set_source_surface (cr, bg, 0, 0);
149
90
    cairo_paint (cr);
150

            
151
90
    cairo_set_operator (cr, op);
152
90
    cairo_set_source_surface (cr, fg, 0, 0);
153
90
    cairo_paint_with_alpha (cr, .5);
154

            
155
90
    cairo_surface_destroy (fg);
156
90
    cairo_surface_destroy (bg);
157
90
}
158

            
159
static cairo_test_status_t
160
18
draw (cairo_t *cr, cairo_bool_t alpha,
161
      void (*blend)(cairo_t *, cairo_operator_t, cairo_bool_t))
162
{
163
18
    size_t i = 0;
164
    cairo_operator_t op;
165

            
166
288
    for (op = START_OPERATOR; op <= STOP_OPERATOR; op++, i++) {
167
270
	cairo_save (cr);
168
270
	cairo_translate (cr,
169
270
		SIZE * (STEPS + 1) * (i % COUNT),
170
270
		SIZE * (STEPS + 1) * (i / COUNT));
171
270
	blend (cr, op, alpha);
172
270
	cairo_restore (cr);
173
    }
174

            
175
18
    return CAIRO_TEST_SUCCESS;
176
}
177

            
178
static cairo_test_status_t
179
3
draw_extended_blend (cairo_t *cr, int width, int height)
180
{
181
3
    return draw (cr, FALSE, do_blend);
182
}
183

            
184
static cairo_test_status_t
185
3
draw_extended_blend_alpha (cairo_t *cr, int width, int height)
186
{
187
3
    return draw (cr, TRUE, do_blend);
188
}
189

            
190
static cairo_test_status_t
191
3
draw_extended_blend_solid (cairo_t *cr, int width, int height)
192
{
193
3
    return draw (cr, FALSE, do_blend_solid);
194
}
195

            
196
static cairo_test_status_t
197
3
draw_extended_blend_solid_alpha (cairo_t *cr, int width, int height)
198
{
199
3
    return draw (cr, TRUE, do_blend_solid);
200
}
201

            
202
static cairo_test_status_t
203
3
draw_extended_blend_mask (cairo_t *cr, int width, int height)
204
{
205
3
    return draw (cr, FALSE, do_blend_mask);
206
}
207
static cairo_test_status_t
208
3
draw_extended_blend_alpha_mask (cairo_t *cr, int width, int height)
209
{
210
3
    return draw (cr, TRUE, do_blend_mask);
211
}
212

            
213
1
CAIRO_TEST (extended_blend,
214
	    "Tests extended blend modes without alpha",
215
	    "operator", /* keywords */
216
	    NULL, /* requirements */
217
	    FULL_WIDTH * SIZE, FULL_HEIGHT * SIZE,
218
	    NULL, draw_extended_blend)
219

            
220
1
CAIRO_TEST (extended_blend_alpha,
221
	    "Tests extended blend modes with alpha",
222
	    "operator", /* keywords */
223
	    NULL, /* requirements */
224
	    FULL_WIDTH * SIZE, FULL_HEIGHT * SIZE,
225
	    NULL, draw_extended_blend_alpha)
226

            
227
1
CAIRO_TEST (extended_blend_mask,
228
	    "Tests extended blend modes with an alpha mask",
229
	    "operator,mask", /* keywords */
230
	    NULL, /* requirements */
231
	    FULL_WIDTH * SIZE, FULL_HEIGHT * SIZE,
232
	    NULL, draw_extended_blend_mask)
233
1
CAIRO_TEST (extended_blend_alpha_mask,
234
	    "Tests extended blend modes with an alpha mask",
235
	    "operator,mask", /* keywords */
236
	    NULL, /* requirements */
237
	    FULL_WIDTH * SIZE, FULL_HEIGHT * SIZE,
238
	    NULL, draw_extended_blend_alpha_mask)
239

            
240

            
241
1
CAIRO_TEST (extended_blend_solid,
242
	    "Tests extended blend modes on solid patterns without alpha",
243
	    "operator", /* keywords */
244
	    NULL, /* requirements */
245
	    FULL_WIDTH * SIZE, FULL_HEIGHT * SIZE,
246
	    NULL, draw_extended_blend_solid)
247

            
248
1
CAIRO_TEST (extended_blend_solid_alpha,
249
	    "Tests extended blend modes on solid patterns with alpha",
250
	    "operator", /* keywords */
251
	    NULL, /* requirements */
252
	    FULL_WIDTH * SIZE, FULL_HEIGHT * SIZE,
253
	    NULL, draw_extended_blend_solid_alpha)