Opensource Compliance Issue.
[platform/core/graphics/cairo.git] / test / ps-eps.c
1 /*
2  * Copyright © 2006 Red Hat, Inc.
3  * Copyright © 2009 Adrian Johnson
4  * Copyright © 2008 Chris Wilson
5  *
6  * Permission to use, copy, modify, distribute, and sell this software
7  * and its documentation for any purpose is hereby granted without
8  * fee, provided that the above copyright notice appear in all copies
9  * and that both that copyright notice and this permission notice
10  * appear in supporting documentation, and that the name of
11  * Red Hat, Inc. not be used in advertising or publicity pertaining to
12  * distribution of the software without specific, written prior
13  * permission. Red Hat, Inc. makes no representations about the
14  * suitability of this software for any purpose.  It is provided "as
15  * is" without express or implied warranty.
16  *
17  * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19  * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
20  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
23  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  * Author: Carl D. Worth <cworth@cworth.org>
26  *         Adrian Johnson <ajohnson@redneon.com>
27  *         Chris Wilson <chris@chris-wilson.co.uk>
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <math.h>
37 #include <cairo.h>
38 #include <cairo-ps.h>
39
40 #ifdef HAVE_UNISTD_H
41 #include <unistd.h>
42 #include <errno.h>
43 #endif
44 #if HAVE_SYS_STAT_H
45 #include <sys/stat.h>
46 #endif
47
48 #include "cairo-test.h"
49 #include "buffer-diff.h"
50
51 /* Test EPS output.
52  */
53
54 #define WIDTH 595
55 #define HEIGHT 842
56
57 /* Reference Bounding Box */
58 #define LLX  95
59 #define LLY 687
60 #define URX 155
61 #define URY 747
62
63 static void
64 _xunlink (const cairo_test_context_t *ctx, const char *pathname)
65 {
66     if (unlink (pathname) < 0 && errno != ENOENT) {
67         cairo_test_log (ctx, "Error: Cannot remove %s: %s\n",
68                         pathname, strerror (errno));
69         exit (1);
70     }
71 }
72
73 static cairo_bool_t
74 check_result (cairo_test_context_t *ctx,
75               const cairo_boilerplate_target_t *target,
76               const char *test_name,
77               const char *base_name,
78               cairo_surface_t *surface)
79 {
80     const char *format;
81     char *ref_name;
82     char *png_name;
83     char *diff_name;
84     cairo_surface_t *test_image, *ref_image, *diff_image;
85     buffer_diff_result_t result;
86     cairo_status_t status;
87     cairo_bool_t ret;
88
89     /* XXX log target, OUTPUT, REFERENCE, DIFFERENCE for index.html */
90
91     if (target->finish_surface != NULL) {
92         status = target->finish_surface (surface);
93         if (status) {
94             cairo_test_log (ctx, "Error: Failed to finish surface: %s\n",
95                     cairo_status_to_string (status));
96             cairo_surface_destroy (surface);
97             return FALSE;
98         }
99     }
100
101     xasprintf (&png_name,  "%s.out.png", base_name);
102     xasprintf (&diff_name, "%s.diff.png", base_name);
103
104     test_image = target->get_image_surface (surface, 0, WIDTH, HEIGHT);
105     if (cairo_surface_status (test_image)) {
106         cairo_test_log (ctx, "Error: Failed to extract page: %s\n",
107                         cairo_status_to_string (cairo_surface_status (test_image)));
108         cairo_surface_destroy (test_image);
109         free (png_name);
110         free (diff_name);
111         return FALSE;
112     }
113
114     _xunlink (ctx, png_name);
115     status = cairo_surface_write_to_png (test_image, png_name);
116     if (status) {
117         cairo_test_log (ctx, "Error: Failed to write output image: %s\n",
118                 cairo_status_to_string (status));
119         cairo_surface_destroy (test_image);
120         free (png_name);
121         free (diff_name);
122         return FALSE;
123     }
124
125     format = cairo_boilerplate_content_name (target->content);
126     ref_name = cairo_test_reference_filename (ctx,
127                                               base_name,
128                                               test_name,
129                                               target->name,
130                                               target->basename,
131                                               format,
132                                               CAIRO_TEST_REF_SUFFIX,
133                                               CAIRO_TEST_PNG_EXTENSION);
134     if (ref_name == NULL) {
135         cairo_test_log (ctx, "Error: Cannot find reference image for %s\n",
136                         base_name);
137         cairo_surface_destroy (test_image);
138         free (png_name);
139         free (diff_name);
140         return FALSE;
141     }
142
143     ref_image = cairo_test_get_reference_image (ctx, ref_name,
144             target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED);
145     if (cairo_surface_status (ref_image)) {
146         cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n",
147                         ref_name,
148                 cairo_status_to_string (cairo_surface_status (ref_image)));
149         cairo_surface_destroy (ref_image);
150         cairo_surface_destroy (test_image);
151         free (png_name);
152         free (diff_name);
153         free (ref_name);
154         return FALSE;
155     }
156
157     diff_image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
158             WIDTH, HEIGHT);
159
160     ret = TRUE;
161     status = image_diff (ctx,
162             test_image, ref_image, diff_image,
163             &result);
164     _xunlink (ctx, diff_name);
165     if (status) {
166         cairo_test_log (ctx, "Error: Failed to compare images: %s\n",
167                         cairo_status_to_string (status));
168         ret = FALSE;
169     } else if (image_diff_is_failure (&result, target->error_tolerance))
170     {
171         ret = FALSE;
172
173         status = cairo_surface_write_to_png (diff_image, diff_name);
174         if (status) {
175             cairo_test_log (ctx, "Error: Failed to write differences image: %s\n",
176                     cairo_status_to_string (status));
177         }
178     }
179
180     cairo_surface_destroy (test_image);
181     cairo_surface_destroy (diff_image);
182     free (png_name);
183     free (diff_name);
184     free (ref_name);
185
186     return ret;
187 }
188
189
190 #define DOCUMENT_BBOX  "%%BoundingBox:"
191 #define PAGE_BBOX      "%%PageBoundingBox:"
192
193 static cairo_bool_t
194 check_bbox (cairo_test_context_t *ctx,
195             const char *base_name)
196 {
197     char *filename;
198     FILE *f;
199     char buf[256];
200     cairo_bool_t bbox_pass, page_bbox_pass;
201     int llx, lly, urx, ury;
202     int ret;
203
204     xasprintf (&filename,  "%s.out.ps", base_name);
205     f = fopen (filename, "r");
206     if (!f) {
207         cairo_test_log (ctx, "Error: Cannot open EPS output: %s\n",
208                         base_name);
209         free (filename);
210         return FALSE;
211     }
212
213     bbox_pass = FALSE;
214     page_bbox_pass = FALSE;
215     while (!feof(f)) {
216         if (fgets (buf, sizeof(buf), f) == (char *)EOF) {
217             cairo_test_log (ctx, "Error: Unexpected EOF in %s\n",
218                             filename);
219             break;
220         }
221
222         if (strncmp (buf, DOCUMENT_BBOX, strlen (DOCUMENT_BBOX)) == 0) {
223             ret = sscanf (buf+strlen (DOCUMENT_BBOX), "%d %d %d %d", &llx, &lly, &urx, &ury);
224             if (ret == 4 && llx == LLX && lly == LLY && urx == URX && ury == URY)
225                 bbox_pass = TRUE;
226         }
227
228         if (strncmp (buf, PAGE_BBOX, strlen (PAGE_BBOX)) == 0) {
229             ret = sscanf (buf+strlen (PAGE_BBOX), "%d %d %d %d", &llx, &lly, &urx, &ury);
230             if (ret == 4 && llx == LLX && lly == LLY && urx == URX && ury == URY)
231                 page_bbox_pass = TRUE;
232         }
233     }
234     fclose (f);
235
236     if (!bbox_pass || !page_bbox_pass) {
237         cairo_test_log (ctx, "Error: EPS Bounding Box does not match reference Bounding Box\n");
238         return FALSE;
239     }
240
241     free (filename);
242
243     return TRUE;
244 }
245
246 static cairo_test_status_t
247 preamble (cairo_test_context_t *ctx)
248 {
249     cairo_t *cr;
250     cairo_test_status_t ret = CAIRO_TEST_UNTESTED;
251     unsigned int i;
252     const char *path = cairo_test_mkdir (CAIRO_TEST_OUTPUT_DIR) ? CAIRO_TEST_OUTPUT_DIR : ".";
253
254     for (i = 0; i < ctx->num_targets; i++) {
255         const cairo_boilerplate_target_t *target = ctx->targets_to_test[i];
256         cairo_surface_t *surface = NULL;
257         char *base_name;
258         void *closure;
259         const char *format;
260         cairo_status_t status;
261         cairo_bool_t pass;
262         char *test_name;
263
264         if (! cairo_test_is_target_enabled (ctx, target->name))
265             continue;
266
267         format = cairo_boilerplate_content_name (target->content);
268         xasprintf (&test_name, "ps-eps");
269         xasprintf (&base_name, "%s/ps-eps.%s.%s",
270                    path, target->name, format);
271
272         surface = (target->create_surface) (base_name,
273                                             target->content,
274                                             WIDTH, HEIGHT,
275                                             WIDTH, HEIGHT,
276                                             CAIRO_BOILERPLATE_MODE_TEST,
277                                             &closure);
278
279         if (surface == NULL) {
280             free (base_name);
281             free (test_name);
282             continue;
283         }
284
285         cairo_ps_surface_set_eps (surface, TRUE);
286         if (!cairo_ps_surface_get_eps (surface)) {
287             cairo_surface_destroy (surface);
288             if (target->cleanup)
289                 target->cleanup (closure);
290
291             free (base_name);
292             free (test_name);
293             continue;
294         }
295         
296         cairo_test_log (ctx,
297                         "Testing ps-eps with %s target\n",
298                         target->name);
299         printf ("%s:\t", base_name);
300         fflush (stdout);
301
302         cairo_surface_set_device_offset (surface, 25, 25);
303         cr = cairo_create (surface);
304
305         cairo_new_sub_path (cr);
306         cairo_arc (cr, 100, 100, 25, 0, 2*M_PI);
307         cairo_set_line_width (cr, 10);
308         cairo_stroke (cr);
309
310         cairo_show_page (cr);
311
312         status = cairo_status (cr);
313         cairo_destroy (cr);
314
315         if (status) {
316             cairo_test_log (ctx, "Error: Failed to create target surface: %s\n",
317                             cairo_status_to_string (status));
318             pass = FALSE;
319         } else {
320             pass = TRUE;
321             /* extract the image and compare it to our reference */
322             if (! check_result (ctx, target, test_name, base_name, surface))
323                 pass = FALSE;
324
325             /* check the bounding box of the EPS file and compare it to our reference */
326             if (! check_bbox (ctx, base_name))
327                 pass = FALSE;
328         }
329         cairo_surface_destroy (surface);
330         if (target->cleanup)
331             target->cleanup (closure);
332
333         free (base_name);
334         free (test_name);
335
336         if (pass) {
337             printf ("PASS\n");
338             ret = CAIRO_TEST_SUCCESS;
339         } else {
340             printf ("FAIL\n");
341             ret = CAIRO_TEST_FAILURE;
342         }
343         fflush (stdout);
344     }
345
346     return ret;
347 }
348
349 CAIRO_TEST (ps_eps,
350             "Check EPS output from PS surface",
351             "ps, api", /* keywords */
352             NULL, /* requirements */
353             0, 0,
354             preamble, NULL)