Updated: Sudoku no longer crashes
[moon.git] / cairo / src / test-paginated-surface.c
blob354f95d1adf1803c53a31db6cfb68872afc628ac
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2005 Red Hat, Inc
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Red Hat, Inc.
32 * Contributor(s):
33 * Carl Worth <cworth@cworth.org>
36 /* This isn't a "real" surface, but just something to be used by the
37 * test suite to help exercise the paginated-surface paths in cairo.
39 * The defining feature of this backend is that it uses a paginated
40 * surface to record all operations, and then replays everything to an
41 * image surface.
43 * It's possible that this code might serve as a good starting point
44 * for someone working on bringing up a new paginated-surface-based
45 * backend.
48 #include "cairoint.h"
50 #include "test-paginated-surface.h"
52 #include "cairo-paginated-private.h"
54 typedef struct _test_paginated_surface {
55 cairo_surface_t base;
56 cairo_surface_t *target;
57 cairo_paginated_mode_t paginated_mode;
58 } test_paginated_surface_t;
60 static const cairo_surface_backend_t test_paginated_surface_backend;
61 static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend;
63 cairo_surface_t *
64 _cairo_test_paginated_surface_create_for_data (unsigned char *data,
65 cairo_content_t content,
66 int width,
67 int height,
68 int stride)
70 cairo_status_t status;
71 cairo_surface_t *target;
72 cairo_surface_t *paginated;
73 test_paginated_surface_t *surface;
75 target = _cairo_image_surface_create_for_data_with_content (data, content,
76 width, height,
77 stride);
78 status = cairo_surface_status (target);
79 if (status)
80 return target;
82 surface = malloc (sizeof (test_paginated_surface_t));
83 if (surface == NULL) {
84 cairo_surface_destroy (target);
85 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
88 _cairo_surface_init (&surface->base, &test_paginated_surface_backend,
89 content);
91 surface->target = target;
93 paginated = _cairo_paginated_surface_create (&surface->base,
94 content, width, height,
95 &test_paginated_surface_paginated_backend);
96 status = paginated->status;
97 if (status == CAIRO_STATUS_SUCCESS) {
98 /* paginated keeps the only reference to surface now, drop ours */
99 cairo_surface_destroy (&surface->base);
100 return paginated;
103 cairo_surface_destroy (target);
104 free (surface);
105 return _cairo_surface_create_in_error (status);
108 static cairo_status_t
109 _test_paginated_surface_finish (void *abstract_surface)
111 test_paginated_surface_t *surface = abstract_surface;
113 cairo_surface_destroy (surface->target);
115 return CAIRO_STATUS_SUCCESS;
118 static cairo_int_status_t
119 _test_paginated_surface_set_clip_region (void *abstract_surface,
120 cairo_region_t *region)
122 test_paginated_surface_t *surface = abstract_surface;
124 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
125 return CAIRO_STATUS_SUCCESS;
127 /* XXX: The whole surface backend clipping interface is a giant
128 * disaster right now. In particular, its uncleanness shows up
129 * when trying to implement one surface that wraps another one (as
130 * we are doing here).
132 * Here are two of the problems that show up:
134 * 1. The most critical piece of information in all this stuff,
135 * the "clip" isn't getting passed to the backend
136 * functions. Instead the generic surface layer is caching that as
137 * surface->clip. This is a problem for surfaces like this one
138 * that do wrapping. Our base surface will have the clip set, but
139 * our target's surface will not.
141 * 2. We're here in our backend's set_clip_region function, and we
142 * want to call into our target surface's set_clip_region.
143 * Generally, we would do this by calling an equivalent
144 * _cairo_surface function, but _cairo_surface_set_clip_region
145 * does not have the same signature/semantics, (it has the
146 * clip_serial stuff as well).
148 * We kludge around each of these by manually copying the clip
149 * object from our base surface into the target's base surface
150 * (yuck!) and by reaching directly into the image surface's
151 * set_clip_region instead of calling into the generic
152 * _cairo_surface_set_clip_region (double yuck!).
155 surface->target->clip = surface->base.clip;
157 return _cairo_image_surface_set_clip_region (surface->target, region);
160 static cairo_int_status_t
161 _test_paginated_surface_get_extents (void *abstract_surface,
162 cairo_rectangle_int_t *rectangle)
164 test_paginated_surface_t *surface = abstract_surface;
166 return _cairo_surface_get_extents (surface->target, rectangle);
169 static cairo_int_status_t
170 _test_paginated_surface_paint (void *abstract_surface,
171 cairo_operator_t op,
172 cairo_pattern_t *source)
174 test_paginated_surface_t *surface = abstract_surface;
176 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
177 return CAIRO_STATUS_SUCCESS;
179 return _cairo_surface_paint (surface->target, op, source);
182 static cairo_int_status_t
183 _test_paginated_surface_mask (void *abstract_surface,
184 cairo_operator_t op,
185 cairo_pattern_t *source,
186 cairo_pattern_t *mask)
188 test_paginated_surface_t *surface = abstract_surface;
190 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
191 return CAIRO_STATUS_SUCCESS;
193 return _cairo_surface_mask (surface->target, op, source, mask);
196 static cairo_int_status_t
197 _test_paginated_surface_stroke (void *abstract_surface,
198 cairo_operator_t op,
199 cairo_pattern_t *source,
200 cairo_path_fixed_t *path,
201 cairo_stroke_style_t *style,
202 cairo_matrix_t *ctm,
203 cairo_matrix_t *ctm_inverse,
204 double tolerance,
205 cairo_antialias_t antialias)
207 test_paginated_surface_t *surface = abstract_surface;
209 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
210 return CAIRO_STATUS_SUCCESS;
212 return _cairo_surface_stroke (surface->target, op, source,
213 path, style,
214 ctm, ctm_inverse,
215 tolerance, antialias);
218 static cairo_int_status_t
219 _test_paginated_surface_fill (void *abstract_surface,
220 cairo_operator_t op,
221 cairo_pattern_t *source,
222 cairo_path_fixed_t *path,
223 cairo_fill_rule_t fill_rule,
224 double tolerance,
225 cairo_antialias_t antialias)
227 test_paginated_surface_t *surface = abstract_surface;
229 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
230 return CAIRO_STATUS_SUCCESS;
232 return _cairo_surface_fill (surface->target, op, source,
233 path, fill_rule,
234 tolerance, antialias);
237 static cairo_bool_t
238 _test_paginated_surface_has_show_text_glyphs (void *abstract_surface)
240 test_paginated_surface_t *surface = abstract_surface;
242 return cairo_surface_has_show_text_glyphs (surface->target);
245 static cairo_int_status_t
246 _test_paginated_surface_show_text_glyphs (void *abstract_surface,
247 cairo_operator_t op,
248 cairo_pattern_t *source,
249 const char *utf8,
250 int utf8_len,
251 cairo_glyph_t *glyphs,
252 int num_glyphs,
253 const cairo_text_cluster_t *clusters,
254 int num_clusters,
255 cairo_text_cluster_flags_t cluster_flags,
256 cairo_scaled_font_t *scaled_font)
258 test_paginated_surface_t *surface = abstract_surface;
260 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
261 return CAIRO_STATUS_SUCCESS;
263 return _cairo_surface_show_text_glyphs (surface->target, op, source,
264 utf8, utf8_len,
265 glyphs, num_glyphs,
266 clusters, num_clusters, cluster_flags,
267 scaled_font);
271 static void
272 _test_paginated_surface_set_paginated_mode (void *abstract_surface,
273 cairo_paginated_mode_t mode)
275 test_paginated_surface_t *surface = abstract_surface;
277 surface->paginated_mode = mode;
280 static const cairo_surface_backend_t test_paginated_surface_backend = {
281 CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
283 /* Since we are a paginated user, we get to regard most of the
284 * surface backend interface as historical cruft and ignore it. */
286 NULL, /* create_similar */
287 _test_paginated_surface_finish,
288 NULL, /* acquire_source_image */
289 NULL, /* release_source_image */
290 NULL, /* acquire_dest_image */
291 NULL, /* release_dest_image */
292 NULL, /* clone_similar */
293 NULL, /* composite */
294 NULL, /* fill_rectangles */
295 NULL, /* composite_trapezoids */
296 NULL, /* copy_page */
297 NULL, /* show_page */
298 _test_paginated_surface_set_clip_region,
299 NULL, /* intersect_clip_path */
300 _test_paginated_surface_get_extents,
301 NULL, /* old_show_glyphs */
302 NULL, /* get_font_options */
303 NULL, /* flush */
304 NULL, /* mark_dirty_rectangle */
305 NULL, /* scaled_font_fini */
306 NULL, /* scaled_glyph_fini */
308 /* Here is the more "modern" section of the surface backend
309 * interface which is mostly just drawing functions */
311 _test_paginated_surface_paint,
312 _test_paginated_surface_mask,
313 _test_paginated_surface_stroke,
314 _test_paginated_surface_fill,
315 NULL, /* show_glyphs */
317 NULL, /* snapshot */
318 NULL, /* is_similar */
319 NULL, /* reset */
320 NULL, /* fill_stroke */
321 NULL, /* create_solid_pattern_surface */
323 _test_paginated_surface_has_show_text_glyphs,
324 _test_paginated_surface_show_text_glyphs
327 static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend = {
328 NULL, /* start_page */
329 _test_paginated_surface_set_paginated_mode