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.
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
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
50 #include "test-paginated-surface.h"
52 #include "cairo-paginated-private.h"
54 typedef struct _test_paginated_surface
{
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
;
64 _cairo_test_paginated_surface_create_for_data (unsigned char *data
,
65 cairo_content_t content
,
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
,
78 status
= cairo_surface_status (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
,
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
);
103 cairo_surface_destroy (target
);
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
,
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
,
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
,
199 cairo_pattern_t
*source
,
200 cairo_path_fixed_t
*path
,
201 cairo_stroke_style_t
*style
,
203 cairo_matrix_t
*ctm_inverse
,
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
,
215 tolerance
, antialias
);
218 static cairo_int_status_t
219 _test_paginated_surface_fill (void *abstract_surface
,
221 cairo_pattern_t
*source
,
222 cairo_path_fixed_t
*path
,
223 cairo_fill_rule_t fill_rule
,
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
,
234 tolerance
, antialias
);
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
,
248 cairo_pattern_t
*source
,
251 cairo_glyph_t
*glyphs
,
253 const cairo_text_cluster_t
*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
,
266 clusters
, num_clusters
, cluster_flags
,
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 */
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 */
318 NULL
, /* is_similar */
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