summaryrefslogtreecommitdiff
path: root/test/a1-mask.c
blob: 946b62209a185b456482bcb8496f7f185e170e9e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
 * Copyright © Jeff Muizelaar
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * and its documentation for any purpose is hereby granted without
 * fee, provided that the above copyright notice appear in all copies
 * and that both that copyright notice and this permission notice
 * appear in supporting documentation, and that the name of
 * Red Hat, Inc. not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission. Red Hat, Inc. makes no representations about the
 * suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * JEFF MUIZELAAR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * Authors: Jeff Muizelaar <jeff@infidigm.net>
 *	    Carl Worth <cworth@cworth.org>
 *	    Chris Wilson <chris@chris-wilson.co.uk>
 */

#include "cairo-test.h"

static cairo_test_draw_function_t draw;

#define MASK_WIDTH 10
#define MASK_HEIGHT 8

#ifdef WORDS_BIGENDIAN
#define MASK 0x28, 0x55
#else
#define MASK 0x14, 0xAA
#endif
static unsigned char mask[(MASK_WIDTH + 7) / 8 * MASK_HEIGHT] = {
    MASK,
    MASK,
    MASK,
    MASK,
    MASK,
    MASK,
    MASK,
    MASK,
};

cairo_test_t test = {
    "a1-mask",
    "test masks of CAIRO_FORMAT_A1",
    MASK_WIDTH, MASK_HEIGHT,
    draw
};


static cairo_test_status_t
check_status (cairo_status_t status, cairo_status_t expected)
{
    if (status == expected)
	return CAIRO_TEST_SUCCESS;

    cairo_test_log ("Error: Expected status value %d (%s), received %d (%s)\n",
		    expected,
		    cairo_status_to_string (expected),
		    status,
		    cairo_status_to_string (status));
    return CAIRO_TEST_FAILURE;
}

static cairo_test_status_t
test_surface_with_width_and_stride (int width, int stride,
				    cairo_status_t expected)
{
    cairo_test_status_t status;
    cairo_surface_t *surface;
    cairo_t *cr;
    int len;
    unsigned char *data;

    cairo_test_log ("Creating surface with width %d and stride %d\n",
		    width, stride);

    len = stride;
    if (len < 0)
	len = -len;
    data = xmalloc (len);

    surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_A1,
						   width, 1, stride);
    cr = cairo_create (surface);

    cairo_paint (cr);

    status = check_status (cairo_surface_status (surface), expected);
    if (status)
	goto BAIL;

    status = check_status (cairo_status (cr), expected);
    if (status)
	goto BAIL;

  BAIL:
    cairo_destroy (cr);
    cairo_surface_destroy (surface);
    free (data);
    return status;
}

static cairo_test_status_t
draw (cairo_t *cr, int dst_width, int dst_height)
{
    unsigned char *mask_aligned;
    cairo_surface_t *surface;

    surface = cairo_image_surface_create (CAIRO_FORMAT_A1,
					  MASK_WIDTH,
					  MASK_HEIGHT);

    mask_aligned = cairo_image_surface_get_data (surface);
    if (mask_aligned != NULL) {
	int stride = cairo_image_surface_get_stride (surface), row;
	const unsigned char *src = mask;
	unsigned char *dst = mask_aligned;
	for (row = 0; row < MASK_HEIGHT; row++) {
	    memcpy (dst, src, (MASK_WIDTH + 7) / 8);
	    src += (MASK_WIDTH + 7) / 8;
	    dst += stride;
	}
    }

    /* Paint background blue */
    cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
    cairo_paint (cr);

    /* Then paint red through our mask */
    cairo_set_source_rgb (cr, 1, 0, 0); /* red */
    cairo_mask_surface (cr, surface, 0, 0);
    cairo_surface_destroy (surface);

    return CAIRO_TEST_SUCCESS;
}

int
main (void)
{
    int test_width;

    cairo_test_init ("a1-mask");

    /* first check the API strictness */
    for (test_width = 0; test_width < 40; test_width++) {
	int test_stride = (test_width + 7) / 8;
	int stride = cairo_format_stride_for_width (CAIRO_FORMAT_A1,
						    test_width);
	cairo_test_status_t status;
	cairo_status_t expected;

	/* First create a surface using the width as the stride,
	 * (most of these should fail).
	 */
	expected = (stride == test_stride) ?
	    CAIRO_STATUS_SUCCESS : CAIRO_STATUS_INVALID_STRIDE;

	status = test_surface_with_width_and_stride (test_width,
						     test_stride,
						     expected);
	if (status)
	    return status;

	status = test_surface_with_width_and_stride (test_width,
						     -test_stride,
						     expected);
	if (status)
	    return status;


	/* Then create a surface using the correct stride,
	 * (should always succeed).
	 */
	status = test_surface_with_width_and_stride (test_width,
						     stride,
						     CAIRO_STATUS_SUCCESS);
	if (status)
	    return status;

	status = test_surface_with_width_and_stride (test_width,
						     -stride,
						     CAIRO_STATUS_SUCCESS);
	if (status)
	    return status;
    }

    cairo_test_fini ();

    return cairo_test (&test);
}