1
/*
2
 * Copyright © 2005 Red Hat, Inc.
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
 * Red Hat, Inc. not be used in advertising or publicity pertaining to
10
 * distribution of the software without specific, written prior
11
 * permission. Red Hat, Inc. 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
 * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17
 * FITNESS, IN NO EVENT SHALL RED HAT, INC. 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: Kristian Høgsberg <krh@redhat.com>
24
 */
25

            
26
#include "cairo-test.h"
27
#include <math.h>
28
#include <stdio.h>
29

            
30
#define WIDTH 16
31
#define HEIGHT 16
32
#define PAD 2
33

            
34
static const char *png_filename = "romedalen.png";
35
static cairo_surface_t *image;
36

            
37
static void
38
36
set_solid_pattern (const cairo_test_context_t *ctx, cairo_t *cr, int x, int y)
39
{
40
36
    cairo_set_source_rgb (cr, 0, 0, 0.6);
41
36
}
42

            
43
static void
44
36
set_translucent_pattern (const cairo_test_context_t *ctx, cairo_t *cr, int x, int y)
45
{
46
36
    cairo_set_source_rgba (cr, 0, 0, 0.6, 0.5);
47
36
}
48

            
49
static void
50
36
set_gradient_pattern (const cairo_test_context_t *ctx, cairo_t *cr, int x, int y)
51
{
52
    cairo_pattern_t *pattern;
53

            
54
    pattern =
55
36
	cairo_pattern_create_linear (x, y, x + WIDTH, y + HEIGHT);
56
36
    cairo_pattern_add_color_stop_rgba (pattern, 0, 1, 1, 1, 1);
57
36
    cairo_pattern_add_color_stop_rgba (pattern, 1, 0, 0, 0.4, 1);
58
36
    cairo_set_source (cr, pattern);
59
36
    cairo_pattern_destroy (pattern);
60
36
}
61

            
62
static void
63
36
set_image_pattern (const cairo_test_context_t *ctx, cairo_t *cr, int x, int y)
64
{
65
    cairo_pattern_t *pattern;
66

            
67
36
    if (image == NULL || cairo_surface_status (image)) {
68
3
	cairo_surface_destroy (image);
69
3
	image = cairo_test_create_surface_from_png (ctx, png_filename);
70
    }
71

            
72
36
    pattern = cairo_pattern_create_for_surface (image);
73
36
    cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
74
36
    cairo_set_source (cr, pattern);
75
36
    cairo_pattern_destroy (pattern);
76
36
}
77

            
78
static void
79
48
draw_rect (cairo_t *cr, int x, int y)
80
{
81
48
    cairo_new_path (cr);
82
48
    cairo_rectangle (cr, x, y, WIDTH, HEIGHT);
83
48
    cairo_fill (cr);
84
48
}
85

            
86
static void
87
48
draw_rects (cairo_t *cr, int x, int y)
88
{
89
48
    int width = WIDTH / 3;
90
48
    int height = HEIGHT / 2;
91

            
92
48
    cairo_new_path (cr);
93
48
    cairo_rectangle (cr, x, y, width, height);
94
48
    cairo_rectangle (cr, x + width, y + height, width, height);
95
48
    cairo_rectangle (cr, x + 2 * width, y, width, height);
96
48
    cairo_fill (cr);
97
48
}
98

            
99
static void
100
48
draw_polygon (cairo_t *cr, int x, int y)
101
{
102
48
    cairo_new_path (cr);
103
48
    cairo_move_to (cr, x, y);
104
48
    cairo_line_to (cr, x, y + HEIGHT);
105
48
    cairo_line_to (cr, x + WIDTH / 2, y + 3 * HEIGHT / 4);
106
48
    cairo_line_to (cr, x + WIDTH, y + HEIGHT);
107
48
    cairo_line_to (cr, x + WIDTH, y);
108
48
    cairo_line_to (cr, x + WIDTH / 2, y + HEIGHT / 4);
109
48
    cairo_close_path (cr);
110
48
    cairo_fill (cr);
111
48
}
112

            
113
static void
114
36
clip_none (cairo_t *cr, int x, int y)
115
{
116
36
}
117

            
118
static void
119
36
clip_rect (cairo_t *cr, int x, int y)
120
{
121
36
    cairo_new_path (cr);
122
36
    cairo_rectangle (cr, x + (int)WIDTH / 6, y + (int)HEIGHT / 6,
123
		     4 * ((int)WIDTH  / 6), 4 * ((int)WIDTH / 6));
124
36
    cairo_clip (cr);
125
36
    cairo_new_path (cr);
126
36
}
127

            
128
static void
129
36
clip_rects (cairo_t *cr, int x, int y)
130
{
131
36
    int height = HEIGHT / 3;
132

            
133
36
    cairo_new_path (cr);
134
36
    cairo_rectangle (cr, x, y, WIDTH, height);
135
36
    cairo_rectangle (cr, x, y + 2 * height, WIDTH, height);
136
36
    cairo_clip (cr);
137
36
    cairo_new_path (cr);
138
36
}
139

            
140
static void
141
36
clip_circle (cairo_t *cr, int x, int y)
142
{
143
36
    cairo_new_path (cr);
144
36
    cairo_arc (cr, x + WIDTH / 2, y + HEIGHT / 2,
145
	       WIDTH / 3, 0, 2 * M_PI);
146
36
    cairo_clip (cr);
147
36
    cairo_new_path (cr);
148
36
}
149

            
150
static void (* const pattern_funcs[])(const cairo_test_context_t *ctx, cairo_t *cr, int x, int y) = {
151
    set_solid_pattern,
152
    set_translucent_pattern,
153
    set_gradient_pattern,
154
    set_image_pattern,
155
};
156

            
157
static void (* const draw_funcs[])(cairo_t *cr, int x, int y) = {
158
    draw_rect,
159
    draw_rects,
160
    draw_polygon,
161
};
162

            
163
static void (* const clip_funcs[])(cairo_t *cr, int x, int y) = {
164
    clip_none,
165
    clip_rect,
166
    clip_rects,
167
    clip_circle,
168
};
169

            
170
#define IMAGE_WIDTH (ARRAY_LENGTH (pattern_funcs) * (WIDTH + PAD) + PAD)
171
#define IMAGE_HEIGHT (ARRAY_LENGTH (draw_funcs) * ARRAY_LENGTH (clip_funcs) * (HEIGHT + PAD) + PAD)
172

            
173
static cairo_test_status_t
174
3
draw (cairo_t *cr, int width, int height)
175
{
176
3
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
177
    size_t i, j, k, x, y;
178

            
179
15
    for (k = 0; k < ARRAY_LENGTH (clip_funcs); k++) {
180
48
	for (j = 0; j < ARRAY_LENGTH (draw_funcs); j++) {
181
180
	    for (i = 0; i < ARRAY_LENGTH (pattern_funcs); i++) {
182
144
		x = i * (WIDTH + PAD) + PAD;
183
144
		y = (ARRAY_LENGTH (draw_funcs) * k + j) * (HEIGHT + PAD) + PAD;
184

            
185
144
		cairo_save (cr);
186

            
187
144
		cairo_move_to (cr, x, y);
188
144
		clip_funcs[k] (cr, x, y);
189
144
		pattern_funcs[i] (ctx, cr, x, y);
190
144
		draw_funcs[j] (cr, x, y);
191
144
		if (cairo_status (cr))
192
		    cairo_test_log (ctx, "%d %d HERE!\n", (int)i, (int)j);
193

            
194
144
		cairo_restore (cr);
195
	    }
196
	}
197
    }
198

            
199
3
    if (cairo_status (cr) != CAIRO_STATUS_SUCCESS)
200
	cairo_test_log (ctx, "%d %d .HERE!\n", (int)i, (int)j);
201

            
202
3
    cairo_surface_destroy (image);
203
3
    image = NULL;
204

            
205
3
    return CAIRO_TEST_SUCCESS;
206
}
207

            
208
1
CAIRO_TEST (trap_clip,
209
	    "Trapezoid clipping",
210
	    "clip, trap", /* keywords */
211
	    NULL, /* requirements */
212
	    IMAGE_WIDTH, IMAGE_HEIGHT,
213
	    NULL, draw)