1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2011 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Red Hat, Inc.
34 * Chris Wilson <chris@chris-wilson.co.uk>
38 #include "cairo-error-private.h"
39 #include "cairo-pattern-private.h"
42 * SECTION:cairo-raster-source
43 * @Title: Raster Sources
44 * @Short_Description: Supplying arbitrary image data
45 * @See_Also: #cairo_pattern_t
47 * The raster source provides the ability to supply arbitrary pixel data
48 * whilst rendering. The pixels are queried at the time of rasterisation
49 * by means of user callback functions, allowing for the ultimate
50 * flexibility. For example, in handling compressed image sources, you
51 * may keep a MRU cache of decompressed images and decompress sources on the
52 * fly and discard old ones to conserve memory.
54 * For the raster source to be effective, you must at least specify
55 * the acquire and release callbacks which are used to retrieve the pixel
56 * data for the region of interest and demark when it can be freed afterwards.
57 * Other callbacks are provided for when the pattern is copied temporarily
58 * during rasterisation, or more permanently as a snapshot in order to keep
59 * the pixel data available for printing.
63 _cairo_raster_source_pattern_acquire (const cairo_pattern_t
*abstract_pattern
,
64 cairo_surface_t
*target
,
65 const cairo_rectangle_int_t
*extents
)
67 cairo_raster_source_pattern_t
*pattern
=
68 (cairo_raster_source_pattern_t
*) abstract_pattern
;
70 if (pattern
->acquire
== NULL
)
74 extents
= &pattern
->extents
;
76 return pattern
->acquire (&pattern
->base
, pattern
->user_data
,
81 _cairo_raster_source_pattern_release (const cairo_pattern_t
*abstract_pattern
,
82 cairo_surface_t
*surface
)
84 cairo_raster_source_pattern_t
*pattern
=
85 (cairo_raster_source_pattern_t
*) abstract_pattern
;
87 if (pattern
->release
== NULL
)
90 pattern
->release (&pattern
->base
, pattern
->user_data
, surface
);
94 _cairo_raster_source_pattern_init_copy (cairo_pattern_t
*abstract_pattern
,
95 const cairo_pattern_t
*other
)
97 cairo_raster_source_pattern_t
*pattern
=
98 (cairo_raster_source_pattern_t
*) abstract_pattern
;
99 cairo_status_t status
;
101 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern
, sizeof (cairo_raster_source_pattern_t
)));
102 memcpy(pattern
, other
, sizeof (cairo_raster_source_pattern_t
));
104 status
= CAIRO_STATUS_SUCCESS
;
106 status
= pattern
->copy (&pattern
->base
, pattern
->user_data
, other
);
112 _cairo_raster_source_pattern_snapshot (cairo_pattern_t
*abstract_pattern
)
114 cairo_raster_source_pattern_t
*pattern
=
115 (cairo_raster_source_pattern_t
*) abstract_pattern
;
117 if (pattern
->snapshot
== NULL
)
118 return CAIRO_STATUS_SUCCESS
;
120 return pattern
->snapshot (&pattern
->base
, pattern
->user_data
);
124 _cairo_raster_source_pattern_finish (cairo_pattern_t
*abstract_pattern
)
126 cairo_raster_source_pattern_t
*pattern
=
127 (cairo_raster_source_pattern_t
*) abstract_pattern
;
129 if (pattern
->finish
== NULL
)
132 pattern
->finish (&pattern
->base
, pattern
->user_data
);
135 /* Public interface */
138 * cairo_pattern_create_raster_source:
139 * @user_data: the user data to be passed to all callbacks
140 * @content: content type for the pixel data that will be returned. Knowing
141 * the content type ahead of time is used for analysing the operation and
142 * picking the appropriate rendering path.
143 * @width: maximum size of the sample area
144 * @height: maximum size of the sample area
146 * Creates a new user pattern for providing pixel data.
148 * Use the setter functions to associate callbacks with the returned
149 * pattern. The only mandatory callback is acquire.
151 * Return value: a newly created #cairo_pattern_t. Free with
152 * cairo_pattern_destroy() when you are done using it.
157 cairo_pattern_create_raster_source (void *user_data
,
158 cairo_content_t content
,
159 int width
, int height
)
161 cairo_raster_source_pattern_t
*pattern
;
163 CAIRO_MUTEX_INITIALIZE ();
165 if (width
< 0 || height
< 0)
166 return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_SIZE
);
168 if (! CAIRO_CONTENT_VALID (content
))
169 return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_CONTENT
);
171 pattern
= calloc (1, sizeof (*pattern
));
172 if (unlikely (pattern
== NULL
))
173 return _cairo_pattern_create_in_error (CAIRO_STATUS_NO_MEMORY
);
175 _cairo_pattern_init (&pattern
->base
,
176 CAIRO_PATTERN_TYPE_RASTER_SOURCE
);
177 CAIRO_REFERENCE_COUNT_INIT (&pattern
->base
.ref_count
, 1);
179 pattern
->content
= content
;
181 pattern
->extents
.x
= 0;
182 pattern
->extents
.y
= 0;
183 pattern
->extents
.width
= width
;
184 pattern
->extents
.height
= height
;
186 pattern
->user_data
= user_data
;
188 return &pattern
->base
;
192 * cairo_raster_source_pattern_set_callback_data:
193 * @pattern: the pattern to update
194 * @data: the user data to be passed to all callbacks
196 * Updates the user data that is provided to all callbacks.
201 cairo_raster_source_pattern_set_callback_data (cairo_pattern_t
*abstract_pattern
,
204 cairo_raster_source_pattern_t
*pattern
;
206 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
209 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
210 pattern
->user_data
= data
;
214 * cairo_raster_source_pattern_get_callback_data:
215 * @pattern: the pattern to update
217 * Queries the current user data.
219 * Return value: the current user-data passed to each callback
224 cairo_raster_source_pattern_get_callback_data (cairo_pattern_t
*abstract_pattern
)
226 cairo_raster_source_pattern_t
*pattern
;
228 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
231 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
232 return pattern
->user_data
;
236 * cairo_raster_source_pattern_set_acquire:
237 * @pattern: the pattern to update
238 * @acquire: acquire callback
239 * @release: release callback
241 * Specifies the callbacks used to generate the image surface for a rendering
242 * operation (acquire) and the function used to cleanup that surface afterwards.
244 * The @acquire callback should create a surface (preferably an image
245 * surface created to match the target using
246 * cairo_surface_create_similar_image()) that defines at least the region
247 * of interest specified by extents. The surface is allowed to be the entire
248 * sample area, but if it does contain a subsection of the sample area,
249 * the surface extents should be provided by setting the device offset (along
250 * with its width and height) using cairo_surface_set_device_offset().
255 cairo_raster_source_pattern_set_acquire (cairo_pattern_t
*abstract_pattern
,
256 cairo_raster_source_acquire_func_t acquire
,
257 cairo_raster_source_release_func_t release
)
259 cairo_raster_source_pattern_t
*pattern
;
261 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
264 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
265 pattern
->acquire
= acquire
;
266 pattern
->release
= release
;
270 * cairo_raster_source_pattern_get_acquire:
271 * @pattern: the pattern to query
272 * @acquire: return value for the current acquire callback
273 * @release: return value for the current release callback
275 * Queries the current acquire and release callbacks.
280 cairo_raster_source_pattern_get_acquire (cairo_pattern_t
*abstract_pattern
,
281 cairo_raster_source_acquire_func_t
*acquire
,
282 cairo_raster_source_release_func_t
*release
)
284 cairo_raster_source_pattern_t
*pattern
;
286 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
289 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
291 *acquire
= pattern
->acquire
;
293 *release
= pattern
->release
;
297 * cairo_raster_source_pattern_set_snapshot:
298 * @pattern: the pattern to update
299 * @snapshot: snapshot callback
301 * Sets the callback that will be used whenever a snapshot is taken of the
302 * pattern, that is whenever the current contents of the pattern should be
303 * preserved for later use. This is typically invoked whilst printing.
308 cairo_raster_source_pattern_set_snapshot (cairo_pattern_t
*abstract_pattern
,
309 cairo_raster_source_snapshot_func_t snapshot
)
311 cairo_raster_source_pattern_t
*pattern
;
313 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
316 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
317 pattern
->snapshot
= snapshot
;
321 * cairo_raster_source_pattern_get_snapshot:
322 * @pattern: the pattern to query
324 * Queries the current snapshot callback.
326 * Return value: the current snapshot callback
330 cairo_raster_source_snapshot_func_t
331 cairo_raster_source_pattern_get_snapshot (cairo_pattern_t
*abstract_pattern
)
333 cairo_raster_source_pattern_t
*pattern
;
335 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
338 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
339 return pattern
->snapshot
;
343 * cairo_raster_source_pattern_set_copy:
344 * @pattern: the pattern to update
345 * @copy: the copy callback
347 * Updates the copy callback which is used whenever a temporary copy of the
353 cairo_raster_source_pattern_set_copy (cairo_pattern_t
*abstract_pattern
,
354 cairo_raster_source_copy_func_t copy
)
356 cairo_raster_source_pattern_t
*pattern
;
358 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
361 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
362 pattern
->copy
= copy
;
366 * cairo_raster_source_pattern_get_copy:
367 * @pattern: the pattern to query
369 * Queries the current copy callback.
371 * Return value: the current copy callback
375 cairo_raster_source_copy_func_t
376 cairo_raster_source_pattern_get_copy (cairo_pattern_t
*abstract_pattern
)
378 cairo_raster_source_pattern_t
*pattern
;
380 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
383 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
384 return pattern
->copy
;
388 * cairo_raster_source_pattern_set_finish:
389 * @pattern: the pattern to update
390 * @finish: the finish callback
392 * Updates the finish callback which is used whenever a pattern (or a copy
393 * thereof) will no longer be used.
398 cairo_raster_source_pattern_set_finish (cairo_pattern_t
*abstract_pattern
,
399 cairo_raster_source_finish_func_t finish
)
401 cairo_raster_source_pattern_t
*pattern
;
403 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
406 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
407 pattern
->finish
= finish
;
411 * cairo_raster_source_pattern_get_finish:
412 * @pattern: the pattern to query
414 * Queries the current finish callback.
416 * Return value: the current finish callback
420 cairo_raster_source_finish_func_t
421 cairo_raster_source_pattern_get_finish (cairo_pattern_t
*abstract_pattern
)
423 cairo_raster_source_pattern_t
*pattern
;
425 if (abstract_pattern
->type
!= CAIRO_PATTERN_TYPE_RASTER_SOURCE
)
428 pattern
= (cairo_raster_source_pattern_t
*) abstract_pattern
;
429 return pattern
->finish
;