c52aa9dd9f37aa13096a22f790db2f60af726e7b
[framework/graphics/cairo.git] / test / a1-mask.c
1 /*
2  * Copyright © Jeff Muizelaar
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  * JEFF MUIZELAAR 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  * Authors: Jeff Muizelaar <jeff@infidigm.net>
24  *          Carl Worth <cworth@cworth.org>
25  *          Chris Wilson <chris@chris-wilson.co.uk>
26  */
27
28 #include "cairo-test.h"
29
30 #define MASK_WIDTH 10
31 #define MASK_HEIGHT 8
32
33 #ifdef WORDS_BIGENDIAN
34 #define MASK 0x28, 0x55
35 #else
36 #define MASK 0x14, 0xAA
37 #endif
38 static unsigned char mask[(MASK_WIDTH + 7) / 8 * MASK_HEIGHT] = {
39     MASK,
40     MASK,
41     MASK,
42     MASK,
43     MASK,
44     MASK,
45     MASK,
46     MASK,
47 };
48
49 static cairo_test_status_t
50 check_status (const cairo_test_context_t *ctx,
51               cairo_status_t status,
52               cairo_status_t expected)
53 {
54     if (status == expected)
55         return CAIRO_TEST_SUCCESS;
56
57     cairo_test_log (ctx,
58                     "Error: Expected status value %d (%s), received %d (%s)\n",
59                     expected,
60                     cairo_status_to_string (expected),
61                     status,
62                     cairo_status_to_string (status));
63     return CAIRO_TEST_FAILURE;
64 }
65
66 static cairo_test_status_t
67 test_surface_with_width_and_stride (const cairo_test_context_t *ctx,
68                                     int width, int stride,
69                                     cairo_status_t expected)
70 {
71     cairo_test_status_t status;
72     cairo_surface_t *surface;
73     cairo_t *cr;
74     int len;
75     unsigned char *data;
76
77     cairo_test_log (ctx,
78                     "Creating surface with width %d and stride %d\n",
79                     width, stride);
80
81     len = stride;
82     if (len < 0)
83         len = -len;
84     data = xmalloc (len);
85
86     surface = cairo_image_surface_create_for_data (data, CAIRO_FORMAT_A1,
87                                                    width, 1, stride);
88     cr = cairo_create (surface);
89
90     cairo_paint (cr);
91
92     status = check_status (ctx, cairo_surface_status (surface), expected);
93     if (status)
94         goto BAIL;
95
96     status = check_status (ctx, cairo_status (cr), expected);
97     if (status)
98         goto BAIL;
99
100   BAIL:
101     cairo_destroy (cr);
102     cairo_surface_destroy (surface);
103     free (data);
104     return status;
105 }
106
107 static cairo_test_status_t
108 draw (cairo_t *cr, int dst_width, int dst_height)
109 {
110     unsigned char *mask_aligned;
111     cairo_surface_t *surface;
112
113     surface = cairo_image_surface_create (CAIRO_FORMAT_A1,
114                                           MASK_WIDTH,
115                                           MASK_HEIGHT);
116
117     mask_aligned = cairo_image_surface_get_data (surface);
118     if (mask_aligned != NULL) {
119         int stride = cairo_image_surface_get_stride (surface), row;
120         const unsigned char *src = mask;
121         unsigned char *dst = mask_aligned;
122         for (row = 0; row < MASK_HEIGHT; row++) {
123             memcpy (dst, src, (MASK_WIDTH + 7) / 8);
124             src += (MASK_WIDTH + 7) / 8;
125             dst += stride;
126         }
127     }
128     cairo_surface_mark_dirty (surface);
129
130     /* Paint background blue */
131     cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
132     cairo_paint (cr);
133
134     /* Then paint red through our mask */
135     cairo_set_source_rgb (cr, 1, 0, 0); /* red */
136     cairo_mask_surface (cr, surface, 0, 0);
137     cairo_surface_destroy (surface);
138
139     return CAIRO_TEST_SUCCESS;
140 }
141
142 static cairo_test_status_t
143 preamble (cairo_test_context_t *ctx)
144 {
145     cairo_test_status_t status = CAIRO_TEST_SUCCESS;
146     int test_width;
147
148     /* first check the API strictness */
149     for (test_width = 0; test_width < 40; test_width++) {
150         int test_stride = (test_width + 7) / 8;
151         int stride = cairo_format_stride_for_width (CAIRO_FORMAT_A1,
152                                                     test_width);
153         cairo_status_t expected;
154
155         /* First create a surface using the width as the stride,
156          * (most of these should fail).
157          */
158         expected = (stride == test_stride) ?
159             CAIRO_STATUS_SUCCESS : CAIRO_STATUS_INVALID_STRIDE;
160
161         status = test_surface_with_width_and_stride (ctx,
162                                                      test_width,
163                                                      test_stride,
164                                                      expected);
165         if (status)
166             return status;
167
168         status = test_surface_with_width_and_stride (ctx,
169                                                      test_width,
170                                                      -test_stride,
171                                                      expected);
172         if (status)
173             return status;
174
175
176         /* Then create a surface using the correct stride,
177          * (should always succeed).
178          */
179         status = test_surface_with_width_and_stride (ctx,
180                                                      test_width,
181                                                      stride,
182                                                      CAIRO_STATUS_SUCCESS);
183         if (status)
184             return status;
185
186         status = test_surface_with_width_and_stride (ctx,
187                                                      test_width,
188                                                      -stride,
189                                                      CAIRO_STATUS_SUCCESS);
190         if (status)
191             return status;
192     }
193
194     return status;
195 }
196
197 CAIRO_TEST (a1_mask,
198             "test masks of CAIRO_FORMAT_A1",
199             "alpha, mask", /* keywords */
200             NULL, /* requirements */
201             MASK_WIDTH, MASK_HEIGHT,
202             preamble, draw)