1
/*
2
 * Copyright © 2008 Chris Wilson
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
 * Chris Wilson not be used in advertising or publicity pertaining to
10
 * distribution of the software without specific, written prior
11
 * permission. Chris Wilson 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
 * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17
 * FITNESS, IN NO EVENT SHALL CHRIS WILSON 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: Chris Wilson <chris@chris-wilson.co.uk>
24
 */
25

            
26
#include "cairo-test.h"
27

            
28
#include <stdio.h>
29
#include <errno.h>
30

            
31
/* Basic test to exercise the new mime-data embedding. */
32

            
33
static cairo_status_t
34
21
read_file (const cairo_test_context_t *ctx,
35
	   const char *filename,
36
	   unsigned char **data_out,
37
	   unsigned int *length_out)
38
{
39
    FILE *file;
40
    unsigned char *buf;
41
    unsigned int len;
42

            
43
21
    file = fopen (filename, "rb");
44
21
    if (file == NULL) {
45
	char path[4096];
46

            
47
21
	if (errno == ENOMEM)
48
	    return CAIRO_STATUS_NO_MEMORY;
49

            
50
	/* try again with srcdir */
51
21
	snprintf (path, sizeof (path),
52
21
		  "%s/%s", ctx->srcdir, filename);
53
21
	file = fopen (path, "rb");
54
    }
55
21
    if (file == NULL) {
56
	switch (errno) {
57
	case ENOMEM:
58
	    return CAIRO_STATUS_NO_MEMORY;
59
	default:
60
	    return CAIRO_STATUS_FILE_NOT_FOUND;
61
	}
62
    }
63

            
64
21
    fseek (file, 0, SEEK_END);
65
21
    len = ftell (file);
66
21
    fseek (file, 0, SEEK_SET);
67

            
68
21
    buf = xmalloc (len);
69
21
    *length_out = fread (buf, 1, len, file);
70
21
    fclose (file);
71
21
    if (*length_out != len) {
72
	free (buf);
73
	return CAIRO_STATUS_READ_ERROR;
74
    }
75

            
76
21
    *data_out = buf;
77
21
    return CAIRO_STATUS_SUCCESS;
78
}
79

            
80
static cairo_test_status_t
81
9
paint_file (cairo_t *cr,
82
	    const char *filename, const char *mime_type,
83
	    int x, int y)
84
{
85
9
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
86
    cairo_surface_t *image;
87
    unsigned char *mime_data;
88
    unsigned int mime_length;
89
    cairo_status_t status;
90

            
91
    /* Deliberately use a non-matching MIME images, so that we can identify
92
     * when the MIME representation is used in preference to the plain image
93
     * surface.
94
     */
95
9
    status = read_file (ctx, filename, &mime_data, &mime_length);
96
9
    if (status)
97
	return cairo_test_status_from_status (ctx, status);
98

            
99
9
    image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 200, 50);
100

            
101
9
    status = cairo_surface_set_mime_data (image, mime_type,
102
					  mime_data, mime_length,
103
					  free, mime_data);
104
9
    if (status) {
105
	cairo_surface_destroy (image);
106
	free (mime_data);
107
	return cairo_test_status_from_status (ctx, status);
108
    }
109

            
110
9
    cairo_set_source_surface (cr, image, x, y);
111
9
    cairo_surface_destroy (image);
112

            
113
9
    cairo_paint (cr);
114

            
115
9
    return CAIRO_TEST_SUCCESS;
116
}
117

            
118
static cairo_test_status_t
119
3
paint_jbig2_file (cairo_t *cr, int x, int y)
120
{
121
3
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
122
    cairo_surface_t *image;
123
    unsigned char *mime_data;
124
    unsigned int mime_length;
125
    cairo_status_t status;
126
3
    const char jbig2_image1_filename[] = "image1.jb2";
127
3
    const char jbig2_image2_filename[] = "image2.jb2";
128
3
    const char jbig2_global_filename[] = "global.jb2";
129

            
130
    /* Deliberately use a non-matching MIME images, so that we can identify
131
     * when the MIME representation is used in preference to the plain image
132
     * surface.
133
     */
134

            
135
    /* Image 1 */
136

            
137
3
    status = read_file (ctx, jbig2_image1_filename, &mime_data, &mime_length);
138
3
    if (status)
139
	return cairo_test_status_from_status (ctx, status);
140

            
141
3
    image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 200, 50);
142

            
143
3
    status = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
144
					  (unsigned char *)"global", 6, NULL, NULL);
145
3
    if (status) {
146
	cairo_surface_destroy (image);
147
	return cairo_test_status_from_status (ctx, status);
148
    }
149

            
150
3
    status = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JBIG2,
151
					  mime_data, mime_length,
152
					  free, mime_data);
153
3
    if (status) {
154
	cairo_surface_destroy (image);
155
	free (mime_data);
156
	return cairo_test_status_from_status (ctx, status);
157
    }
158

            
159
3
    cairo_set_source_surface (cr, image, x, y);
160
3
    cairo_surface_destroy (image);
161

            
162
3
    cairo_paint (cr);
163

            
164
    /* Image 2 */
165

            
166
3
    status = read_file (ctx, jbig2_image2_filename, &mime_data, &mime_length);
167
3
    if (status)
168
	return cairo_test_status_from_status (ctx, status);
169

            
170
3
    image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 200, 50);
171

            
172
3
    status = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JBIG2_GLOBAL_ID,
173
					  (unsigned char *)"global", 6, NULL, NULL);
174
3
    if (status) {
175
	cairo_surface_destroy (image);
176
	return cairo_test_status_from_status (ctx, status);
177
    }
178

            
179
3
    status = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JBIG2,
180
					  mime_data, mime_length,
181
					  free, mime_data);
182
3
    if (status) {
183
	cairo_surface_destroy (image);
184
	free (mime_data);
185
	return cairo_test_status_from_status (ctx, status);
186
    }
187

            
188
    /* Set the global data */
189
3
    status = read_file (ctx, jbig2_global_filename, &mime_data, &mime_length);
190
3
    if (status)
191
	return cairo_test_status_from_status (ctx, status);
192

            
193
3
    status = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_JBIG2_GLOBAL,
194
					  mime_data, mime_length,
195
					  free, mime_data);
196
3
    if (status) {
197
	cairo_surface_destroy (image);
198
	free (mime_data);
199
	return cairo_test_status_from_status (ctx, status);
200
    }
201

            
202
3
    cairo_set_source_surface (cr, image, x, y + 50);
203
3
    cairo_surface_destroy (image);
204

            
205
3
    cairo_paint (cr);
206
3
    return CAIRO_TEST_SUCCESS;
207
}
208

            
209
static cairo_test_status_t
210
3
paint_ccitt_file (cairo_t *cr, int x, int y)
211
{
212
3
    const cairo_test_context_t *ctx = cairo_test_get_context (cr);
213
    cairo_surface_t *image;
214
    unsigned char *mime_data;
215
    unsigned int mime_length;
216
    cairo_status_t status;
217
3
    const char *ccitt_image_filename = "ccitt.g3";
218
3
    const char *ccitt_image_params = "Columns=200 Rows=50 K=-1";
219

            
220
    /* Deliberately use a non-matching MIME images, so that we can identify
221
     * when the MIME representation is used in preference to the plain image
222
     * surface.
223
     */
224

            
225
3
    status = read_file (ctx, ccitt_image_filename, &mime_data, &mime_length);
226
3
    if (status)
227
	return cairo_test_status_from_status (ctx, status);
228

            
229
3
    image = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 200, 50);
230

            
231
    /* Set the CCITT image data */
232
3
    status = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_CCITT_FAX,
233
					  mime_data, mime_length,
234
					  free, mime_data);
235
3
    if (status) {
236
	cairo_surface_destroy (image);
237
	free (mime_data);
238
	return cairo_test_status_from_status (ctx, status);
239
    }
240

            
241
    /* Set the CCITT image parameters */
242
3
    status = cairo_surface_set_mime_data (image, CAIRO_MIME_TYPE_CCITT_FAX_PARAMS,
243
					  (unsigned char *)ccitt_image_params,
244
					  strlen (ccitt_image_params),
245
					  NULL, NULL);
246
3
    if (status) {
247
	cairo_surface_destroy (image);
248
	return cairo_test_status_from_status (ctx, status);
249
    }
250

            
251
3
    cairo_set_source_surface (cr, image, x, y);
252
3
    cairo_surface_destroy (image);
253

            
254
3
    cairo_paint (cr);
255

            
256
3
    return CAIRO_TEST_SUCCESS;
257
}
258

            
259
static cairo_test_status_t
260
3
draw (cairo_t *cr, int width, int height)
261
{
262
3
    const char jpg_filename[] = "jpeg.jpg";
263
3
    const char png_filename[] = "png.png";
264
3
    const char jp2_filename[] = "jp2.jp2";
265
    cairo_test_status_t status;
266

            
267
3
    status = paint_file (cr, jpg_filename, CAIRO_MIME_TYPE_JPEG, 0, 0);
268
3
    if (status)
269
	return status;
270

            
271
3
    status = paint_file (cr, png_filename, CAIRO_MIME_TYPE_PNG, 0, 50);
272
3
    if (status)
273
	return status;
274

            
275
3
    status = paint_file (cr, jp2_filename, CAIRO_MIME_TYPE_JP2, 0, 100);
276
3
    if (status)
277
	return status;
278

            
279
3
    status = paint_jbig2_file (cr, 0, 150);
280
3
    if (status)
281
	return status;
282

            
283
3
    status = paint_ccitt_file (cr, 0, 250);
284
3
    if (status)
285
	return status;
286

            
287
3
    return CAIRO_TEST_SUCCESS;
288
}
289

            
290
1
CAIRO_TEST (mime_data,
291
	    "Check that the mime-data embedding works",
292
	    "jpeg, api", /* keywords */
293
	    NULL, /* requirements */
294
	    200, 300,
295
	    NULL, draw)