1
/*
2
 * Copyright © 2010 Red Hat, Inc.
3
 *
4
 * Permission is hereby granted, free of charge, to any person
5
 * obtaining a copy of this software and associated documentation
6
 * files (the "Software"), to deal in the Software without
7
 * restriction, including without limitation the rights to use, copy,
8
 * modify, merge, publish, distribute, sublicense, and/or sell copies
9
 * of the Software, and to permit persons to whom the Software is
10
 * furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
 * SOFTWARE.
23
 *
24
 * Author: Benjamin Otte <otte@gnome.org>
25
 */
26

            
27
#include "cairo-test.h"
28

            
29
#define RECT 10
30
#define SPACE 5
31

            
32
static void
33
21
paint_with_alpha (cairo_t *cr)
34
{
35
21
    cairo_paint_with_alpha (cr, 0.0);
36
21
}
37

            
38
static void
39
21
mask_with_solid (cairo_t *cr)
40
{
41
21
    cairo_pattern_t *pattern = cairo_pattern_create_rgba (1, 0, 0, 0);
42

            
43
21
    cairo_mask (cr, pattern);
44
    
45
21
    cairo_pattern_destroy (pattern);
46
21
}
47

            
48
static void
49
21
mask_with_empty_gradient (cairo_t *cr)
50
{
51
21
    cairo_pattern_t *pattern = cairo_pattern_create_linear (1, 2, 3, 4);
52

            
53
21
    cairo_mask (cr, pattern);
54
    
55
21
    cairo_pattern_destroy (pattern);
56
21
}
57

            
58
static void
59
21
mask_with_gradient (cairo_t *cr)
60
{
61
21
    cairo_pattern_t *pattern = cairo_pattern_create_radial (1, 2, 3, 4, 5, 6);
62

            
63
21
    cairo_pattern_add_color_stop_rgba (pattern, 0, 1, 0, 0, 0);
64
21
    cairo_pattern_add_color_stop_rgba (pattern, 0, 0, 0, 1, 0);
65

            
66
21
    cairo_mask (cr, pattern);
67
    
68
21
    cairo_pattern_destroy (pattern);
69
21
}
70

            
71
static void
72
21
mask_with_surface (cairo_t *cr)
73
{
74
21
    cairo_surface_t *surface = cairo_surface_create_similar (cairo_get_target (cr),
75
                                                             CAIRO_CONTENT_COLOR_ALPHA,
76
                                                             RECT,
77
                                                             RECT);
78

            
79
21
    cairo_mask_surface (cr, surface, 0, 0);
80
    
81
21
    cairo_surface_destroy (surface);
82
21
}
83

            
84
static void
85
21
mask_with_alpha_surface (cairo_t *cr)
86
{
87
21
    cairo_surface_t *surface = cairo_surface_create_similar (cairo_get_target (cr),
88
                                                             CAIRO_CONTENT_ALPHA,
89
                                                             RECT / 2,
90
                                                             RECT / 2);
91
21
    cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
92
21
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT);
93

            
94
21
    cairo_mask (cr, pattern);
95

            
96
21
    cairo_pattern_destroy (pattern);
97
21
    cairo_surface_destroy (surface);
98
21
}
99

            
100
static void
101
21
mask_with_nonclear_surface (cairo_t *cr)
102
{
103
    static unsigned char data[8 * 4] = { 0, };
104
21
    cairo_surface_t *surface = cairo_image_surface_create_for_data (data,
105
                                                                    CAIRO_FORMAT_A1,
106
                                                                    16, 8, 4);
107

            
108
21
    cairo_mask_surface (cr, surface, 0, 0);
109

            
110
21
    cairo_surface_destroy (surface);
111
21
}
112

            
113
static void
114
21
mask_with_0x0_surface (cairo_t *cr)
115
{
116
21
    cairo_surface_t *surface = cairo_surface_create_similar (cairo_get_target (cr),
117
                                                             CAIRO_CONTENT_COLOR_ALPHA,
118
                                                             0, 0);
119

            
120
21
    cairo_mask_surface (cr, surface, 0, 0);
121
    
122
21
    cairo_surface_destroy (surface);
123
21
}
124

            
125
static void
126
21
mask_with_extend_none (cairo_t *cr)
127
{
128
21
    cairo_surface_t *surface = cairo_surface_create_similar (cairo_get_target (cr),
129
                                                             CAIRO_CONTENT_COLOR_ALPHA,
130
                                                             RECT,
131
                                                             RECT);
132

            
133
21
    cairo_mask_surface (cr, surface, 2 * RECT, 2 * RECT);
134
    
135
21
    cairo_surface_destroy (surface);
136
21
}
137

            
138
typedef void (* mask_func_t) (cairo_t *);
139

            
140
static mask_func_t mask_funcs[] = {
141
  paint_with_alpha,
142
  mask_with_solid,
143
  mask_with_empty_gradient,
144
  mask_with_gradient,
145
  mask_with_surface,
146
  mask_with_alpha_surface,
147
  mask_with_nonclear_surface,
148
  mask_with_0x0_surface,
149
  mask_with_extend_none
150
};
151

            
152
static cairo_operator_t operators[] = {
153
  CAIRO_OPERATOR_CLEAR,
154
  CAIRO_OPERATOR_SOURCE,
155
  CAIRO_OPERATOR_OVER,
156
  CAIRO_OPERATOR_IN,
157
  CAIRO_OPERATOR_DEST_ATOP,
158
  CAIRO_OPERATOR_SATURATE,
159
  CAIRO_OPERATOR_MULTIPLY
160
};
161

            
162
static cairo_test_status_t
163
3
draw (cairo_t *cr, int width, int height)
164
{
165
    unsigned int i, op;
166

            
167
    /* 565-compatible gray background */
168
3
    cairo_set_source_rgb (cr, 0.51613, 0.55555, 0.51613);
169
3
    cairo_paint (cr);
170

            
171
3
    cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); /* green */
172
    /* mask with zero-alpha in several ways */
173

            
174
3
    cairo_translate (cr, SPACE, SPACE);
175

            
176
24
    for (op = 0; op < ARRAY_LENGTH (operators); op++) {
177
21
        cairo_set_operator (cr, operators[op]);
178

            
179
210
        for (i = 0; i < ARRAY_LENGTH (mask_funcs); i++) {
180
189
            cairo_save (cr);
181
189
            cairo_translate (cr, i * (RECT + SPACE), op * (RECT + SPACE));
182
189
            cairo_rectangle (cr, 0, 0, RECT, RECT);
183
189
            cairo_clip (cr);
184
189
            mask_funcs[i] (cr);
185
189
            cairo_restore (cr);
186
        }
187
    }
188

            
189
3
    return CAIRO_TEST_SUCCESS;
190
}
191

            
192
1
CAIRO_TEST (zero_mask,
193
	    "Testing that masking with zero alpha works",
194
	    "alpha, mask", /* keywords */
195
	    NULL, /* requirements */
196
	    SPACE + (RECT + SPACE) * ARRAY_LENGTH (mask_funcs),
197
	    SPACE + (RECT + SPACE) * ARRAY_LENGTH (operators),
198
	    NULL, draw)