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 test a mythical backend that uses nothing but
38  * fallbacks.
39  *
40  * The defining feature of this backend is that it has as many %NULL
41  * backend function entries as possible. The ones that aren't %NULL are
42  * simply those that must be implemented to have working fallbacks.
43  * (Except for create_similar---fallbacks would work fine without
44  * that---I implemented it here in order to create as many surfaces as
45  * possible of type test_fallback_surface_t during the test suite
46  * run).
47  *
48  * It's possible that this code might serve as a good starting point
49  * for someone working on bringing up a new backend, starting with the
50  * minimal all-fallbacks approach and working up gradually from
51  * there.
52  */
53 
54 #include "cairoint.h"
55 
56 #include "test-fallback-surface.h"
57 #include "cairo-error-private.h"
58 
59 typedef struct _test_fallback_surface {
60     cairo_surface_t base;
61 
62     /* This is a cairo_image_surface to hold the actual contents. */
63     cairo_surface_t *backing;
64 } test_fallback_surface_t;
65 
66 static const cairo_surface_backend_t test_fallback_surface_backend;
67 
68 slim_hidden_proto (_cairo_test_fallback_surface_create);
69 
70 cairo_surface_t *
_cairo_test_fallback_surface_create(cairo_content_t content,int width,int height)71 _cairo_test_fallback_surface_create (cairo_content_t	content,
72 			       int		width,
73 			       int		height)
74 {
75     test_fallback_surface_t *surface;
76     cairo_surface_t *backing;
77 
78     backing = _cairo_image_surface_create_with_content (content, width, height);
79     if (cairo_surface_status (backing))
80 	return backing;
81 
82     surface = malloc (sizeof (test_fallback_surface_t));
83     if (unlikely (surface == NULL)) {
84 	cairo_surface_destroy (backing);
85 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
86     }
87 
88     _cairo_surface_init (&surface->base,
89 			 &test_fallback_surface_backend,
90 			 NULL, /* device */
91 			 content);
92 
93     surface->backing = backing;
94 
95     return &surface->base;
96 }
97 slim_hidden_def (_cairo_test_fallback_surface_create);
98 
99 static cairo_surface_t *
_test_fallback_surface_create_similar(void * abstract_surface,cairo_content_t content,int width,int height)100 _test_fallback_surface_create_similar (void		*abstract_surface,
101 				       cairo_content_t	 content,
102 				       int		 width,
103 				       int		 height)
104 {
105     assert (CAIRO_CONTENT_VALID (content));
106 
107     return _cairo_test_fallback_surface_create (content,
108 					  width, height);
109 }
110 
111 static cairo_status_t
_test_fallback_surface_finish(void * abstract_surface)112 _test_fallback_surface_finish (void *abstract_surface)
113 {
114     test_fallback_surface_t *surface = abstract_surface;
115 
116     cairo_surface_destroy (surface->backing);
117 
118     return CAIRO_STATUS_SUCCESS;
119 }
120 
121 static cairo_status_t
_test_fallback_surface_acquire_source_image(void * abstract_surface,cairo_image_surface_t ** image_out,void ** image_extra)122 _test_fallback_surface_acquire_source_image (void	     *abstract_surface,
123 					     cairo_image_surface_t **image_out,
124 					     void		 **image_extra)
125 {
126     test_fallback_surface_t *surface = abstract_surface;
127 
128     return _cairo_surface_acquire_source_image (surface->backing,
129 						image_out, image_extra);
130 }
131 
132 static void
_test_fallback_surface_release_source_image(void * abstract_surface,cairo_image_surface_t * image,void * image_extra)133 _test_fallback_surface_release_source_image (void	     *abstract_surface,
134 					     cairo_image_surface_t	*image,
135 					     void		  *image_extra)
136 {
137     test_fallback_surface_t *surface = abstract_surface;
138 
139     _cairo_surface_release_source_image (surface->backing,
140 					 image, image_extra);
141 }
142 
143 static cairo_status_t
_test_fallback_surface_acquire_dest_image(void * abstract_surface,cairo_rectangle_int_t * interest_rect,cairo_image_surface_t ** image_out,cairo_rectangle_int_t * image_rect_out,void ** image_extra)144 _test_fallback_surface_acquire_dest_image (void		           *abstract_surface,
145 					   cairo_rectangle_int_t   *interest_rect,
146 					   cairo_image_surface_t  **image_out,
147 					   cairo_rectangle_int_t   *image_rect_out,
148 					   void			  **image_extra)
149 {
150     test_fallback_surface_t *surface = abstract_surface;
151 
152     return _cairo_surface_acquire_dest_image (surface->backing,
153 					      interest_rect,
154 					      image_out,
155 					      image_rect_out,
156 					      image_extra);
157 }
158 
159 static void
_test_fallback_surface_release_dest_image(void * abstract_surface,cairo_rectangle_int_t * interest_rect,cairo_image_surface_t * image,cairo_rectangle_int_t * image_rect,void * image_extra)160 _test_fallback_surface_release_dest_image (void			   *abstract_surface,
161 					   cairo_rectangle_int_t   *interest_rect,
162 					   cairo_image_surface_t   *image,
163 					   cairo_rectangle_int_t   *image_rect,
164 					   void			   *image_extra)
165 {
166     test_fallback_surface_t *surface = abstract_surface;
167 
168     _cairo_surface_release_dest_image (surface->backing,
169 				       interest_rect,
170 				       image,
171 				       image_rect,
172 				       image_extra);
173 }
174 
175 static cairo_status_t
_test_fallback_surface_clone_similar(void * abstract_surface,cairo_surface_t * src,int src_x,int src_y,int width,int height,int * clone_offset_x,int * clone_offset_y,cairo_surface_t ** clone_out)176 _test_fallback_surface_clone_similar (void		  *abstract_surface,
177 				      cairo_surface_t     *src,
178 				      int                  src_x,
179 				      int                  src_y,
180 				      int                  width,
181 				      int                  height,
182 				      int                 *clone_offset_x,
183 				      int                 *clone_offset_y,
184 				      cairo_surface_t    **clone_out)
185 {
186     test_fallback_surface_t *surface = abstract_surface;
187 
188     if (src->backend == surface->base.backend) {
189 	*clone_offset_x = 0;
190 	*clone_offset_y = 0;
191 	*clone_out = cairo_surface_reference (src);
192 
193 	return CAIRO_STATUS_SUCCESS;
194     }
195 
196     return CAIRO_INT_STATUS_UNSUPPORTED;
197 }
198 
199 static cairo_bool_t
_test_fallback_surface_get_extents(void * abstract_surface,cairo_rectangle_int_t * rectangle)200 _test_fallback_surface_get_extents (void		  *abstract_surface,
201 				    cairo_rectangle_int_t *rectangle)
202 {
203     test_fallback_surface_t *surface = abstract_surface;
204 
205     return _cairo_surface_get_extents (surface->backing, rectangle);
206 }
207 
208 static const cairo_surface_backend_t test_fallback_surface_backend = {
209     CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
210     _test_fallback_surface_create_similar,
211     _test_fallback_surface_finish,
212     _test_fallback_surface_acquire_source_image,
213     _test_fallback_surface_release_source_image,
214     _test_fallback_surface_acquire_dest_image,
215     _test_fallback_surface_release_dest_image,
216     _test_fallback_surface_clone_similar,
217     NULL, /* composite */
218     NULL, /* fill_rectangles */
219     NULL, /* composite_trapezoids */
220     NULL, /* create_span_renderer */
221     NULL, /* check_span_renderer */
222     NULL, /* copy_page */
223     NULL, /* show_page */
224     _test_fallback_surface_get_extents,
225     NULL, /* old_show_glyphs */
226     NULL, /* get_font_options */
227     NULL, /* flush */
228     NULL, /* mark_dirty_rectangle */
229     NULL, /* scaled_font_fini */
230     NULL, /* scaled_glyph_fini */
231     NULL, /* paint */
232     NULL, /* mask */
233     NULL, /* stroke */
234     NULL, /* fill */
235     NULL, /* show_glyphs */
236     NULL  /* snapshot */
237 };
238