~ubuntu-branches/ubuntu/intrepid/cairo/intrepid-updates

« back to all changes in this revision

Viewing changes to test/imagediff.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-09-25 16:22:33 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20080925162233-btx61ymk181i7mcc
Tags: 1.7.6-0ubuntu1
* New upstream version. Most noticable changes are:
  - some API changes with especially the removal of
    cairo_font_options_set_lcd_filter and cairo_font_options_get_lcd_filter
  - xlib: Faster bookkeeping
  - PS: Fix gradients with non-constant alpha
  - Fix deadlock in user-font code
* debian/patches/00list: Remove 03_from_git_fix_lcd_filter_default.dpatch,
  add debian/patches/03_fix_ftbfs_withing_xcb.dpatch
* debian/libcairo2.symbols, debian/libcairo-directfb2.symbols: update
  list of symbols

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
 *
24
24
 * Author: Richard D. Worth <richard@theworths.org> */
25
25
 
 
26
#ifdef HAVE_CONFIG_H
 
27
#include "config.h"
 
28
#endif
 
29
 
26
30
#include <stdio.h>
27
31
#include <stdlib.h>
 
32
#ifdef HAVE_UNISTD_H
 
33
#include <unistd.h>
 
34
#endif
 
35
#include <errno.h>
28
36
 
29
37
#include "buffer-diff.h"
30
 
#include "xmalloc.h"
 
38
 
 
39
static void
 
40
_xunlink (const char *pathname)
 
41
{
 
42
    if (unlink (pathname) < 0 && errno != ENOENT) {
 
43
        fprintf (stderr, "  Error: Cannot remove %s: %s\n",
 
44
                        pathname, strerror (errno));
 
45
        exit (1);
 
46
    }
 
47
}
 
48
 
 
49
/* Flatten an ARGB surface by blending it over white. The resulting
 
50
 * surface, (still in ARGB32 format, but with only alpha==1.0
 
51
 * everywhere) is returned in the same surface pointer.
 
52
 *
 
53
 * The original surface will be destroyed.
 
54
 *
 
55
 * The (x,y) value specify an origin of interest for the original
 
56
 * image. The flattened image will be generated only from the box
 
57
 * extending from (x,y) to (width,height).
 
58
 */
 
59
static void
 
60
flatten_surface (cairo_surface_t **surface, int x, int y)
 
61
{
 
62
    cairo_surface_t *flat;
 
63
    cairo_t *cr;
 
64
 
 
65
    flat = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
 
66
                                       cairo_image_surface_get_width (*surface) - x,
 
67
                                       cairo_image_surface_get_height (*surface) - y);
 
68
    cairo_surface_set_device_offset (flat, -x, -y);
 
69
 
 
70
    cr = cairo_create (flat);
 
71
    cairo_surface_destroy (flat);
 
72
 
 
73
    cairo_set_source_rgb (cr, 1, 1, 1);
 
74
    cairo_paint (cr);
 
75
 
 
76
    cairo_set_source_surface (cr, *surface, 0, 0);
 
77
    cairo_surface_destroy (*surface);
 
78
    cairo_paint (cr);
 
79
 
 
80
    *surface = cairo_surface_reference (cairo_get_target (cr));
 
81
    cairo_destroy (cr);
 
82
}
 
83
 
 
84
/* Given an image surface, create a new surface that has the same
 
85
 * contents as the sub-surface with its origin at x,y.
 
86
 *
 
87
 * The original surface will be destroyed.
 
88
 */
 
89
static void
 
90
extract_sub_surface (cairo_surface_t **surface, int x, int y)
 
91
{
 
92
    cairo_surface_t *sub;
 
93
    cairo_t *cr;
 
94
 
 
95
    sub = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
 
96
                                      cairo_image_surface_get_width (*surface) - x,
 
97
                                      cairo_image_surface_get_height (*surface) - y);
 
98
 
 
99
    /* We don't use a device offset like flatten_surface. That's not
 
100
     * for any important reason, (the results should be
 
101
     * identical). This style just seemed more natural to me this
 
102
     * time, so I'm leaving both here so I can look at both to see
 
103
     * which I like better. */
 
104
    cr = cairo_create (sub);
 
105
    cairo_surface_destroy (sub);
 
106
 
 
107
    cairo_set_source_surface (cr, *surface, -x, -y);
 
108
    cairo_surface_destroy (*surface);
 
109
    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 
110
    cairo_paint (cr);
 
111
 
 
112
    *surface = cairo_surface_reference (cairo_get_target (cr));
 
113
    cairo_destroy (cr);
 
114
}
 
115
 
 
116
static cairo_status_t
 
117
stdio_write_func (void *closure, const unsigned char *data, unsigned int length)
 
118
{
 
119
    FILE *file = closure;
 
120
 
 
121
    if (fwrite (data, 1, length, file) != length)
 
122
        return CAIRO_STATUS_WRITE_ERROR;
 
123
 
 
124
    return CAIRO_STATUS_SUCCESS;
 
125
}
 
126
 
 
127
static cairo_status_t
 
128
write_png (cairo_surface_t *surface, const char *filename)
 
129
{
 
130
    cairo_status_t status;
 
131
    FILE *png_file;
 
132
 
 
133
    if (filename != NULL) {
 
134
        png_file = fopen (filename, "wb");
 
135
        if (png_file == NULL) {
 
136
            switch (errno) {
 
137
            case ENOMEM:
 
138
                return CAIRO_STATUS_NO_MEMORY;
 
139
            default:
 
140
                return CAIRO_STATUS_WRITE_ERROR;
 
141
            }
 
142
        }
 
143
    } else
 
144
        png_file = stdout;
 
145
 
 
146
    status = cairo_surface_write_to_png_stream (surface,
 
147
                                                stdio_write_func,
 
148
                                                png_file);
 
149
 
 
150
    if (png_file != stdout)
 
151
        fclose (png_file);
 
152
 
 
153
    return status;
 
154
}
 
155
 
 
156
static cairo_status_t
 
157
png_diff (const char *filename_a,
 
158
          const char *filename_b,
 
159
          const char *filename_diff,
 
160
          int           ax,
 
161
          int           ay,
 
162
          int           bx,
 
163
          int           by,
 
164
          buffer_diff_result_t *result)
 
165
{
 
166
    cairo_surface_t *surface_a;
 
167
    cairo_surface_t *surface_b;
 
168
    cairo_surface_t *surface_diff;
 
169
    cairo_status_t status;
 
170
 
 
171
    surface_a = cairo_image_surface_create_from_png (filename_a);
 
172
    status = cairo_surface_status (surface_a);
 
173
    if (status) {
 
174
        fprintf (stderr, "Error: Failed to create surface from %s: %s\n",
 
175
                 filename_a, cairo_status_to_string (status));
 
176
        return status;
 
177
    }
 
178
 
 
179
    surface_b = cairo_image_surface_create_from_png (filename_b);
 
180
    status = cairo_surface_status (surface_b);
 
181
    if (status) {
 
182
        fprintf (stderr, "Error: Failed to create surface from %s: %s\n",
 
183
                 filename_b, cairo_status_to_string (status));
 
184
        cairo_surface_destroy (surface_a);
 
185
        return status;
 
186
    }
 
187
 
 
188
    if (ax || ay) {
 
189
        extract_sub_surface (&surface_a, ax, ay);
 
190
        ax = ay = 0;
 
191
    }
 
192
 
 
193
    if (bx || by) {
 
194
        extract_sub_surface (&surface_b, bx, by);
 
195
        bx = by = 0;
 
196
    }
 
197
 
 
198
    status = cairo_surface_status (surface_a);
 
199
    if (status) {
 
200
        fprintf (stderr, "Error: Failed to extract surface from %s: %s\n",
 
201
                 filename_a, cairo_status_to_string (status));
 
202
        cairo_surface_destroy (surface_a);
 
203
        cairo_surface_destroy (surface_b);
 
204
        return status;
 
205
    }
 
206
    status = cairo_surface_status (surface_b);
 
207
    if (status) {
 
208
        fprintf (stderr, "Error: Failed to extract surface from %s: %s\n",
 
209
                 filename_b, cairo_status_to_string (status));
 
210
        cairo_surface_destroy (surface_a);
 
211
        cairo_surface_destroy (surface_b);
 
212
        return status;
 
213
    }
 
214
 
 
215
    surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
 
216
                                               cairo_image_surface_get_width (surface_a),
 
217
                                               cairo_image_surface_get_height (surface_a));
 
218
    status = cairo_surface_status (surface_diff);
 
219
    if (status) {
 
220
        fprintf (stderr,
 
221
                 "Error: Failed to allocate surface to hold differences\n");
 
222
        cairo_surface_destroy (surface_a);
 
223
        cairo_surface_destroy (surface_b);
 
224
        return CAIRO_STATUS_NO_MEMORY;
 
225
    }
 
226
 
 
227
    status = image_diff (NULL,
 
228
                         surface_a, surface_b, surface_diff,
 
229
                         result);
 
230
 
 
231
    cairo_surface_destroy (surface_a);
 
232
    cairo_surface_destroy (surface_b);
 
233
    cairo_surface_destroy (surface_diff);
 
234
 
 
235
    _xunlink (filename_diff);
 
236
    if (status == CAIRO_STATUS_SUCCESS &&
 
237
        result->pixels_changed)
 
238
    {
 
239
        status = write_png (surface_diff, filename_diff);
 
240
    }
 
241
 
 
242
 
 
243
    return status;
 
244
}
31
245
 
32
246
int
33
247
main (int argc, char *argv[])
54
268
        ax = ay = bx = by = 0;
55
269
    }
56
270
 
57
 
    status = image_diff (argv[1], argv[2], NULL, ax, ay, bx, by, &result);
 
271
    status = png_diff (argv[1], argv[2], NULL, ax, ay, bx, by, &result);
58
272
 
59
273
    if (status) {
60
274
        fprintf (stderr, "Error comparing images: %s\n",