601fe60ff63708b22a5e2040e1732f3e0cf52aa1
[framework/graphics/cairo.git] / src / cairo-raster-source-pattern.c
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
3  *
4  * Copyright © 2011 Intel Corporation
5  *
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.
13  *
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
19  *
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/
24  *
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.
28  *
29  * The Original Code is the cairo graphics library.
30  *
31  * The Initial Developer of the Original Code is Red Hat, Inc.
32  *
33  * Contributor(s):
34  *      Chris Wilson <chris@chris-wilson.co.uk>
35  */
36
37 #include "cairoint.h"
38 #include "cairo-error-private.h"
39 #include "cairo-pattern-private.h"
40
41 /**
42  * SECTION:cairo-raster-source
43  * @Title: Raster Sources
44  * @Short_Description: Supplying arbitrary image data
45  * @See_Also: #cairo_pattern_t
46  *
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.
53  *
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.
60  *
61  * Since: 1.12
62  **/
63
64 cairo_surface_t *
65 _cairo_raster_source_pattern_acquire (const cairo_pattern_t *abstract_pattern,
66                                       cairo_surface_t *target,
67                                       const cairo_rectangle_int_t *extents)
68 {
69     cairo_raster_source_pattern_t *pattern =
70         (cairo_raster_source_pattern_t *) abstract_pattern;
71
72     if (pattern->acquire == NULL)
73         return NULL;
74
75     if (extents == NULL)
76         extents = &pattern->extents;
77
78     return pattern->acquire (&pattern->base, pattern->user_data,
79                              target, extents);
80 }
81
82 void
83 _cairo_raster_source_pattern_release (const cairo_pattern_t *abstract_pattern,
84                                       cairo_surface_t *surface)
85 {
86     cairo_raster_source_pattern_t *pattern =
87         (cairo_raster_source_pattern_t *) abstract_pattern;
88
89     if (pattern->release == NULL)
90         return;
91
92     pattern->release (&pattern->base, pattern->user_data, surface);
93 }
94
95 cairo_status_t
96 _cairo_raster_source_pattern_init_copy (cairo_pattern_t *abstract_pattern,
97                                         const cairo_pattern_t *other)
98 {
99     cairo_raster_source_pattern_t *pattern =
100         (cairo_raster_source_pattern_t *) abstract_pattern;
101     cairo_status_t status;
102
103     VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_raster_source_pattern_t)));
104     memcpy(pattern, other, sizeof (cairo_raster_source_pattern_t));
105
106     status = CAIRO_STATUS_SUCCESS;
107     if (pattern->copy)
108         status = pattern->copy (&pattern->base, pattern->user_data, other);
109
110     return status;
111 }
112
113 cairo_status_t
114 _cairo_raster_source_pattern_snapshot (cairo_pattern_t *abstract_pattern)
115 {
116     cairo_raster_source_pattern_t *pattern =
117         (cairo_raster_source_pattern_t *) abstract_pattern;
118
119     if (pattern->snapshot == NULL)
120         return CAIRO_STATUS_SUCCESS;
121
122     return pattern->snapshot (&pattern->base, pattern->user_data);
123 }
124
125 void
126 _cairo_raster_source_pattern_finish (cairo_pattern_t *abstract_pattern)
127 {
128     cairo_raster_source_pattern_t *pattern =
129         (cairo_raster_source_pattern_t *) abstract_pattern;
130
131     if (pattern->finish == NULL)
132         return;
133
134     pattern->finish (&pattern->base, pattern->user_data);
135 }
136
137 /* Public interface */
138
139 /**
140  * cairo_pattern_create_raster_source:
141  * @user_data: the user data to be passed to all callbacks
142  * @content: content type for the pixel data that will be returned. Knowing
143  * the content type ahead of time is used for analysing the operation and
144  * picking the appropriate rendering path.
145  * @width: maximum size of the sample area
146  * @height: maximum size of the sample area
147  *
148  * Creates a new user pattern for providing pixel data.
149  *
150  * Use the setter functions to associate callbacks with the returned
151  * pattern.  The only mandatory callback is acquire.
152  *
153  * Return value: a newly created #cairo_pattern_t. Free with
154  *  cairo_pattern_destroy() when you are done using it.
155  *
156  * Since: 1.12
157  **/
158 cairo_pattern_t *
159 cairo_pattern_create_raster_source (void *user_data,
160                                     cairo_content_t content,
161                                     int width, int height)
162 {
163     cairo_raster_source_pattern_t *pattern;
164
165     CAIRO_MUTEX_INITIALIZE ();
166
167     if (width < 0 || height < 0)
168         return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_SIZE);
169
170     if (! CAIRO_CONTENT_VALID (content))
171         return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_CONTENT);
172
173     pattern = calloc (1, sizeof (*pattern));
174     if (unlikely (pattern == NULL))
175         return _cairo_pattern_create_in_error (CAIRO_STATUS_NO_MEMORY);
176
177     _cairo_pattern_init (&pattern->base,
178                          CAIRO_PATTERN_TYPE_RASTER_SOURCE);
179     CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
180
181     pattern->content = content;
182
183     pattern->extents.x = 0;
184     pattern->extents.y = 0;
185     pattern->extents.width  = width;
186     pattern->extents.height = height;
187
188     pattern->user_data = user_data;
189
190     return &pattern->base;
191 }
192
193 /**
194  * cairo_raster_source_pattern_set_callback_data:
195  * @pattern: the pattern to update
196  * @data: the user data to be passed to all callbacks
197  *
198  * Updates the user data that is provided to all callbacks.
199  *
200  * Since: 1.12
201  **/
202 void
203 cairo_raster_source_pattern_set_callback_data (cairo_pattern_t *abstract_pattern,
204                                                void *data)
205 {
206     cairo_raster_source_pattern_t *pattern;
207
208     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
209         return;
210
211     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
212     pattern->user_data = data;
213 }
214
215 /**
216  * cairo_raster_source_pattern_get_callback_data:
217  * @pattern: the pattern to update
218  *
219  * Queries the current user data.
220  *
221  * Return value: the current user-data passed to each callback
222  *
223  * Since: 1.12
224  **/
225 void *
226 cairo_raster_source_pattern_get_callback_data (cairo_pattern_t *abstract_pattern)
227 {
228     cairo_raster_source_pattern_t *pattern;
229
230     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
231         return NULL;
232
233     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
234     return pattern->user_data;
235 }
236
237 /**
238  * cairo_raster_source_pattern_set_acquire:
239  * @pattern: the pattern to update
240  * @acquire: acquire callback
241  * @release: release callback
242  *
243  * Specifies the callbacks used to generate the image surface for a rendering
244  * operation (acquire) and the function used to cleanup that surface afterwards.
245  *
246  * The @acquire callback should create a surface (preferably an image
247  * surface created to match the target using
248  * cairo_surface_create_similar_image()) that defines at least the region
249  * of interest specified by extents. The surface is allowed to be the entire
250  * sample area, but if it does contain a subsection of the sample area,
251  * the surface extents should be provided by setting the device offset (along
252  * with its width and height) using cairo_surface_set_device_offset().
253  *
254  * Since: 1.12
255  **/
256 void
257 cairo_raster_source_pattern_set_acquire (cairo_pattern_t *abstract_pattern,
258                                          cairo_raster_source_acquire_func_t acquire,
259                                          cairo_raster_source_release_func_t release)
260 {
261     cairo_raster_source_pattern_t *pattern;
262
263     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
264         return;
265
266     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
267     pattern->acquire = acquire;
268     pattern->release = release;
269 }
270
271 /**
272  * cairo_raster_source_pattern_get_acquire:
273  * @pattern: the pattern to query
274  * @acquire: return value for the current acquire callback
275  * @release: return value for the current release callback
276  *
277  * Queries the current acquire and release callbacks.
278  *
279  * Since: 1.12
280  **/
281 void
282 cairo_raster_source_pattern_get_acquire (cairo_pattern_t *abstract_pattern,
283                                          cairo_raster_source_acquire_func_t *acquire,
284                                          cairo_raster_source_release_func_t *release)
285 {
286     cairo_raster_source_pattern_t *pattern;
287
288     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
289         return;
290
291     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
292     if (acquire)
293         *acquire = pattern->acquire;
294     if (release)
295         *release = pattern->release;
296 }
297
298 /**
299  * cairo_raster_source_pattern_set_snapshot:
300  * @pattern: the pattern to update
301  * @snapshot: snapshot callback
302  *
303  * Sets the callback that will be used whenever a snapshot is taken of the
304  * pattern, that is whenever the current contents of the pattern should be
305  * preserved for later use. This is typically invoked whilst printing.
306  *
307  * Since: 1.12
308  **/
309 void
310 cairo_raster_source_pattern_set_snapshot (cairo_pattern_t *abstract_pattern,
311                                           cairo_raster_source_snapshot_func_t snapshot)
312 {
313     cairo_raster_source_pattern_t *pattern;
314
315     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
316         return;
317
318     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
319     pattern->snapshot = snapshot;
320 }
321
322 /**
323  * cairo_raster_source_pattern_get_snapshot:
324  * @pattern: the pattern to query
325  *
326  * Queries the current snapshot callback.
327  *
328  * Return value: the current snapshot callback
329  *
330  * Since: 1.12
331  **/
332 cairo_raster_source_snapshot_func_t
333 cairo_raster_source_pattern_get_snapshot (cairo_pattern_t *abstract_pattern)
334 {
335     cairo_raster_source_pattern_t *pattern;
336
337     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
338         return NULL;
339
340     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
341     return pattern->snapshot;
342 }
343
344 /**
345  * cairo_raster_source_pattern_set_copy:
346  * @pattern: the pattern to update
347  * @copy: the copy callback
348  *
349  * Updates the copy callback which is used whenever a temporary copy of the
350  * pattern is taken.
351  *
352  * Since: 1.12
353  **/
354 void
355 cairo_raster_source_pattern_set_copy (cairo_pattern_t *abstract_pattern,
356                                       cairo_raster_source_copy_func_t copy)
357 {
358     cairo_raster_source_pattern_t *pattern;
359
360     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
361         return;
362
363     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
364     pattern->copy = copy;
365 }
366
367 /**
368  * cairo_raster_source_pattern_get_copy:
369  * @pattern: the pattern to query
370  *
371  * Queries the current copy callback.
372  *
373  * Return value: the current copy callback
374  *
375  * Since: 1.12
376  **/
377 cairo_raster_source_copy_func_t
378 cairo_raster_source_pattern_get_copy (cairo_pattern_t *abstract_pattern)
379 {
380     cairo_raster_source_pattern_t *pattern;
381
382     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
383         return NULL;
384
385     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
386     return pattern->copy;
387 }
388
389 /**
390  * cairo_raster_source_pattern_set_finish:
391  * @pattern: the pattern to update
392  * @finish: the finish callback
393  *
394  * Updates the finish callback which is used whenever a pattern (or a copy
395  * thereof) will no longer be used.
396  *
397  * Since: 1.12
398  **/
399 void
400 cairo_raster_source_pattern_set_finish (cairo_pattern_t *abstract_pattern,
401                                         cairo_raster_source_finish_func_t finish)
402 {
403     cairo_raster_source_pattern_t *pattern;
404
405     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
406         return;
407
408     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
409     pattern->finish = finish;
410 }
411
412 /**
413  * cairo_raster_source_pattern_get_finish:
414  * @pattern: the pattern to query
415  *
416  * Queries the current finish callback.
417  *
418  * Return value: the current finish callback
419  *
420  * Since: 1.12
421  **/
422 cairo_raster_source_finish_func_t
423 cairo_raster_source_pattern_get_finish (cairo_pattern_t *abstract_pattern)
424 {
425     cairo_raster_source_pattern_t *pattern;
426
427     if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE)
428         return NULL;
429
430     pattern = (cairo_raster_source_pattern_t *) abstract_pattern;
431     return pattern->finish;
432 }