1 /* cairo - a vector graphics library with display and print output
2 *
3 * Copyright © 2005 Red Hat, Inc
4 *
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.
12 *
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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
18 *
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/
23 *
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.
27 *
28 * The Original Code is the cairo graphics library.
29 *
30 * The Initial Developer of the Original Code is Red Hat, Inc.
31 *
32 * Contributor(s):
33 * Carl Worth <cworth@cworth.org>
34 */
35
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.
38 *
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.
42 *
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.
46 */
47
48 #include "cairoint.h"
49
50 #include "test-paginated-surface.h"
51
52 #include "cairo-error-private.h"
53 #include "cairo-paginated-private.h"
54
55 typedef struct _test_paginated_surface {
56 cairo_surface_t base;
57 cairo_surface_t *target;
58 cairo_paginated_mode_t paginated_mode;
59 } test_paginated_surface_t;
60
61 static const cairo_surface_backend_t test_paginated_surface_backend;
62 static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend;
63
64 cairo_surface_t *
_cairo_test_paginated_surface_create(cairo_surface_t * target)65 _cairo_test_paginated_surface_create (cairo_surface_t *target)
66 {
67 cairo_status_t status;
68 cairo_surface_t *paginated;
69 test_paginated_surface_t *surface;
70
71 status = cairo_surface_status (target);
72 if (unlikely (status))
73 return _cairo_surface_create_in_error (status);
74
75 surface = malloc (sizeof (test_paginated_surface_t));
76 if (unlikely (surface == NULL))
77 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
78
79 _cairo_surface_init (&surface->base,
80 &test_paginated_surface_backend,
81 NULL, /* device */
82 target->content);
83
84 surface->target = cairo_surface_reference (target);
85
86 paginated = _cairo_paginated_surface_create (&surface->base,
87 target->content,
88 &test_paginated_surface_paginated_backend);
89 status = paginated->status;
90 if (status == CAIRO_STATUS_SUCCESS) {
91 /* paginated keeps the only reference to surface now, drop ours */
92 cairo_surface_destroy (&surface->base);
93 return paginated;
94 }
95
96 cairo_surface_destroy (target);
97 free (surface);
98 return _cairo_surface_create_in_error (status);
99 }
100
101 static cairo_status_t
_test_paginated_surface_finish(void * abstract_surface)102 _test_paginated_surface_finish (void *abstract_surface)
103 {
104 test_paginated_surface_t *surface = abstract_surface;
105
106 cairo_surface_destroy (surface->target);
107
108 return CAIRO_STATUS_SUCCESS;
109 }
110
111 static cairo_bool_t
_test_paginated_surface_get_extents(void * abstract_surface,cairo_rectangle_int_t * rectangle)112 _test_paginated_surface_get_extents (void *abstract_surface,
113 cairo_rectangle_int_t *rectangle)
114 {
115 test_paginated_surface_t *surface = abstract_surface;
116
117 return _cairo_surface_get_extents (surface->target, rectangle);
118 }
119
120 static cairo_int_status_t
_test_paginated_surface_paint(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_clip_t * clip)121 _test_paginated_surface_paint (void *abstract_surface,
122 cairo_operator_t op,
123 const cairo_pattern_t *source,
124 cairo_clip_t *clip)
125 {
126 test_paginated_surface_t *surface = abstract_surface;
127
128 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
129 return CAIRO_STATUS_SUCCESS;
130
131 return _cairo_surface_paint (surface->target, op, source, clip);
132 }
133
134 static cairo_int_status_t
_test_paginated_surface_mask(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,const cairo_pattern_t * mask,cairo_clip_t * clip)135 _test_paginated_surface_mask (void *abstract_surface,
136 cairo_operator_t op,
137 const cairo_pattern_t *source,
138 const cairo_pattern_t *mask,
139 cairo_clip_t *clip)
140 {
141 test_paginated_surface_t *surface = abstract_surface;
142
143 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
144 return CAIRO_STATUS_SUCCESS;
145
146 return _cairo_surface_mask (surface->target,
147 op, source, mask, clip);
148 }
149
150 static cairo_int_status_t
_test_paginated_surface_stroke(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,const cairo_stroke_style_t * style,const cairo_matrix_t * ctm,const cairo_matrix_t * ctm_inverse,double tolerance,cairo_antialias_t antialias,cairo_clip_t * clip)151 _test_paginated_surface_stroke (void *abstract_surface,
152 cairo_operator_t op,
153 const cairo_pattern_t *source,
154 cairo_path_fixed_t *path,
155 const cairo_stroke_style_t *style,
156 const cairo_matrix_t *ctm,
157 const cairo_matrix_t *ctm_inverse,
158 double tolerance,
159 cairo_antialias_t antialias,
160 cairo_clip_t *clip)
161 {
162 test_paginated_surface_t *surface = abstract_surface;
163
164 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
165 return CAIRO_STATUS_SUCCESS;
166
167 return _cairo_surface_stroke (surface->target, op, source,
168 path, style,
169 ctm, ctm_inverse,
170 tolerance, antialias,
171 clip);
172 }
173
174 static cairo_int_status_t
_test_paginated_surface_fill(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule,double tolerance,cairo_antialias_t antialias,cairo_clip_t * clip)175 _test_paginated_surface_fill (void *abstract_surface,
176 cairo_operator_t op,
177 const cairo_pattern_t *source,
178 cairo_path_fixed_t *path,
179 cairo_fill_rule_t fill_rule,
180 double tolerance,
181 cairo_antialias_t antialias,
182 cairo_clip_t *clip)
183 {
184 test_paginated_surface_t *surface = abstract_surface;
185
186 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
187 return CAIRO_STATUS_SUCCESS;
188
189 return _cairo_surface_fill (surface->target, op, source,
190 path, fill_rule,
191 tolerance, antialias,
192 clip);
193 }
194
195 static cairo_bool_t
_test_paginated_surface_has_show_text_glyphs(void * abstract_surface)196 _test_paginated_surface_has_show_text_glyphs (void *abstract_surface)
197 {
198 test_paginated_surface_t *surface = abstract_surface;
199
200 return cairo_surface_has_show_text_glyphs (surface->target);
201 }
202
203 static cairo_int_status_t
_test_paginated_surface_show_text_glyphs(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,const char * utf8,int utf8_len,cairo_glyph_t * glyphs,int num_glyphs,const cairo_text_cluster_t * clusters,int num_clusters,cairo_text_cluster_flags_t cluster_flags,cairo_scaled_font_t * scaled_font,cairo_clip_t * clip)204 _test_paginated_surface_show_text_glyphs (void *abstract_surface,
205 cairo_operator_t op,
206 const cairo_pattern_t *source,
207 const char *utf8,
208 int utf8_len,
209 cairo_glyph_t *glyphs,
210 int num_glyphs,
211 const cairo_text_cluster_t *clusters,
212 int num_clusters,
213 cairo_text_cluster_flags_t cluster_flags,
214 cairo_scaled_font_t *scaled_font,
215 cairo_clip_t *clip)
216 {
217 test_paginated_surface_t *surface = abstract_surface;
218
219 if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
220 return CAIRO_STATUS_SUCCESS;
221
222 return _cairo_surface_show_text_glyphs (surface->target, op, source,
223 utf8, utf8_len,
224 glyphs, num_glyphs,
225 clusters, num_clusters,
226 cluster_flags,
227 scaled_font,
228 clip);
229 }
230
231
232 static void
_test_paginated_surface_set_paginated_mode(void * abstract_surface,cairo_paginated_mode_t mode)233 _test_paginated_surface_set_paginated_mode (void *abstract_surface,
234 cairo_paginated_mode_t mode)
235 {
236 test_paginated_surface_t *surface = abstract_surface;
237
238 surface->paginated_mode = mode;
239 }
240
241 static const cairo_surface_backend_t test_paginated_surface_backend = {
242 CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
243
244 /* Since we are a paginated user, we get to regard most of the
245 * surface backend interface as historical cruft and ignore it. */
246
247 NULL, /* create_similar */
248 _test_paginated_surface_finish,
249 NULL, /* acquire_source_image */
250 NULL, /* release_source_image */
251 NULL, /* acquire_dest_image */
252 NULL, /* release_dest_image */
253 NULL, /* clone_similar */
254 NULL, /* composite */
255 NULL, /* fill_rectangles */
256 NULL, /* composite_trapezoids */
257 NULL, /* create_span_renderer */
258 NULL, /* check_span_renderer */
259 NULL, /* copy_page */
260 NULL, /* show_page */
261 _test_paginated_surface_get_extents,
262 NULL, /* old_show_glyphs */
263 NULL, /* get_font_options */
264 NULL, /* flush */
265 NULL, /* mark_dirty_rectangle */
266 NULL, /* scaled_font_fini */
267 NULL, /* scaled_glyph_fini */
268
269 /* Here is the more "modern" section of the surface backend
270 * interface which is mostly just drawing functions */
271
272 _test_paginated_surface_paint,
273 _test_paginated_surface_mask,
274 _test_paginated_surface_stroke,
275 _test_paginated_surface_fill,
276 NULL, /* replaced by show_text_glyphs */
277
278 NULL, /* snapshot */
279 NULL, /* is_similar */
280 NULL, /* fill_stroke */
281 NULL, /* create_solid_pattern_surface */
282 NULL, /* can_repaint_solid_pattern_surface */
283
284 _test_paginated_surface_has_show_text_glyphs,
285 _test_paginated_surface_show_text_glyphs
286 };
287
288 static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend = {
289 NULL, /* start_page */
290 _test_paginated_surface_set_paginated_mode
291 };
292