/work/workdir/UnpackedTarball/cairo/src/cairo-raster-source-pattern.c
Line | Count | Source (jump to first uncovered line) |
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 | | |
62 | | cairo_surface_t * |
63 | | _cairo_raster_source_pattern_acquire (const cairo_pattern_t *abstract_pattern, |
64 | | cairo_surface_t *target, |
65 | | const cairo_rectangle_int_t *extents) |
66 | 0 | { |
67 | 0 | cairo_raster_source_pattern_t *pattern = |
68 | 0 | (cairo_raster_source_pattern_t *) abstract_pattern; |
69 | |
|
70 | 0 | if (pattern->acquire == NULL) |
71 | 0 | return NULL; |
72 | | |
73 | 0 | if (extents == NULL) |
74 | 0 | extents = &pattern->extents; |
75 | |
|
76 | 0 | return pattern->acquire (&pattern->base, pattern->user_data, |
77 | 0 | target, extents); |
78 | 0 | } |
79 | | |
80 | | void |
81 | | _cairo_raster_source_pattern_release (const cairo_pattern_t *abstract_pattern, |
82 | | cairo_surface_t *surface) |
83 | 0 | { |
84 | 0 | cairo_raster_source_pattern_t *pattern = |
85 | 0 | (cairo_raster_source_pattern_t *) abstract_pattern; |
86 | |
|
87 | 0 | if (pattern->release == NULL) |
88 | 0 | return; |
89 | | |
90 | 0 | pattern->release (&pattern->base, pattern->user_data, surface); |
91 | 0 | } |
92 | | |
93 | | cairo_status_t |
94 | | _cairo_raster_source_pattern_init_copy (cairo_pattern_t *abstract_pattern, |
95 | | const cairo_pattern_t *other) |
96 | 0 | { |
97 | 0 | cairo_raster_source_pattern_t *pattern = |
98 | 0 | (cairo_raster_source_pattern_t *) abstract_pattern; |
99 | 0 | cairo_status_t status; |
100 | |
|
101 | 0 | VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_raster_source_pattern_t))); |
102 | 0 | memcpy(pattern, other, sizeof (cairo_raster_source_pattern_t)); |
103 | |
|
104 | 0 | status = CAIRO_STATUS_SUCCESS; |
105 | 0 | if (pattern->copy) |
106 | 0 | status = pattern->copy (&pattern->base, pattern->user_data, other); |
107 | |
|
108 | 0 | return status; |
109 | 0 | } |
110 | | |
111 | | cairo_status_t |
112 | | _cairo_raster_source_pattern_snapshot (cairo_pattern_t *abstract_pattern) |
113 | 0 | { |
114 | 0 | cairo_raster_source_pattern_t *pattern = |
115 | 0 | (cairo_raster_source_pattern_t *) abstract_pattern; |
116 | |
|
117 | 0 | if (pattern->snapshot == NULL) |
118 | 0 | return CAIRO_STATUS_SUCCESS; |
119 | | |
120 | 0 | return pattern->snapshot (&pattern->base, pattern->user_data); |
121 | 0 | } |
122 | | |
123 | | void |
124 | | _cairo_raster_source_pattern_finish (cairo_pattern_t *abstract_pattern) |
125 | 0 | { |
126 | 0 | cairo_raster_source_pattern_t *pattern = |
127 | 0 | (cairo_raster_source_pattern_t *) abstract_pattern; |
128 | |
|
129 | 0 | if (pattern->finish == NULL) |
130 | 0 | return; |
131 | | |
132 | 0 | pattern->finish (&pattern->base, pattern->user_data); |
133 | 0 | } |
134 | | |
135 | | /* Public interface */ |
136 | | |
137 | | /** |
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 |
145 | | * |
146 | | * Creates a new user pattern for providing pixel data. |
147 | | * |
148 | | * Use the setter functions to associate callbacks with the returned |
149 | | * pattern. The only mandatory callback is acquire. |
150 | | * |
151 | | * Return value: a newly created #cairo_pattern_t. Free with |
152 | | * cairo_pattern_destroy() when you are done using it. |
153 | | * |
154 | | * Since: 1.12 |
155 | | **/ |
156 | | cairo_pattern_t * |
157 | | cairo_pattern_create_raster_source (void *user_data, |
158 | | cairo_content_t content, |
159 | | int width, int height) |
160 | 0 | { |
161 | 0 | cairo_raster_source_pattern_t *pattern; |
162 | |
|
163 | 0 | CAIRO_MUTEX_INITIALIZE (); |
164 | |
|
165 | 0 | if (width < 0 || height < 0) |
166 | 0 | return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_SIZE); |
167 | | |
168 | 0 | if (! CAIRO_CONTENT_VALID (content)) |
169 | 0 | return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_CONTENT); |
170 | | |
171 | 0 | pattern = calloc (1, sizeof (*pattern)); |
172 | 0 | if (unlikely (pattern == NULL)) |
173 | 0 | return _cairo_pattern_create_in_error (CAIRO_STATUS_NO_MEMORY); |
174 | | |
175 | 0 | _cairo_pattern_init (&pattern->base, |
176 | 0 | CAIRO_PATTERN_TYPE_RASTER_SOURCE); |
177 | 0 | CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1); |
178 | |
|
179 | 0 | pattern->content = content; |
180 | |
|
181 | 0 | pattern->extents.x = 0; |
182 | 0 | pattern->extents.y = 0; |
183 | 0 | pattern->extents.width = width; |
184 | 0 | pattern->extents.height = height; |
185 | |
|
186 | 0 | pattern->user_data = user_data; |
187 | |
|
188 | 0 | return &pattern->base; |
189 | 0 | } |
190 | | |
191 | | /** |
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 |
195 | | * |
196 | | * Updates the user data that is provided to all callbacks. |
197 | | * |
198 | | * Since: 1.12 |
199 | | **/ |
200 | | void |
201 | | cairo_raster_source_pattern_set_callback_data (cairo_pattern_t *abstract_pattern, |
202 | | void *data) |
203 | 0 | { |
204 | 0 | cairo_raster_source_pattern_t *pattern; |
205 | |
|
206 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
207 | 0 | return; |
208 | | |
209 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
210 | 0 | pattern->user_data = data; |
211 | 0 | } |
212 | | |
213 | | /** |
214 | | * cairo_raster_source_pattern_get_callback_data: |
215 | | * @pattern: the pattern to update |
216 | | * |
217 | | * Queries the current user data. |
218 | | * |
219 | | * Return value: the current user-data passed to each callback |
220 | | * |
221 | | * Since: 1.12 |
222 | | **/ |
223 | | void * |
224 | | cairo_raster_source_pattern_get_callback_data (cairo_pattern_t *abstract_pattern) |
225 | 0 | { |
226 | 0 | cairo_raster_source_pattern_t *pattern; |
227 | |
|
228 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
229 | 0 | return NULL; |
230 | | |
231 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
232 | 0 | return pattern->user_data; |
233 | 0 | } |
234 | | |
235 | | /** |
236 | | * cairo_raster_source_pattern_set_acquire: |
237 | | * @pattern: the pattern to update |
238 | | * @acquire: acquire callback |
239 | | * @release: release callback |
240 | | * |
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. |
243 | | * |
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(). |
251 | | * |
252 | | * Since: 1.12 |
253 | | **/ |
254 | | void |
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) |
258 | 0 | { |
259 | 0 | cairo_raster_source_pattern_t *pattern; |
260 | |
|
261 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
262 | 0 | return; |
263 | | |
264 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
265 | 0 | pattern->acquire = acquire; |
266 | 0 | pattern->release = release; |
267 | 0 | } |
268 | | |
269 | | /** |
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 |
274 | | * |
275 | | * Queries the current acquire and release callbacks. |
276 | | * |
277 | | * Since: 1.12 |
278 | | **/ |
279 | | void |
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) |
283 | 0 | { |
284 | 0 | cairo_raster_source_pattern_t *pattern; |
285 | |
|
286 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
287 | 0 | return; |
288 | | |
289 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
290 | 0 | if (acquire) |
291 | 0 | *acquire = pattern->acquire; |
292 | 0 | if (release) |
293 | 0 | *release = pattern->release; |
294 | 0 | } |
295 | | |
296 | | /** |
297 | | * cairo_raster_source_pattern_set_snapshot: |
298 | | * @pattern: the pattern to update |
299 | | * @snapshot: snapshot callback |
300 | | * |
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. |
304 | | * |
305 | | * Since: 1.12 |
306 | | **/ |
307 | | void |
308 | | cairo_raster_source_pattern_set_snapshot (cairo_pattern_t *abstract_pattern, |
309 | | cairo_raster_source_snapshot_func_t snapshot) |
310 | 0 | { |
311 | 0 | cairo_raster_source_pattern_t *pattern; |
312 | |
|
313 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
314 | 0 | return; |
315 | | |
316 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
317 | 0 | pattern->snapshot = snapshot; |
318 | 0 | } |
319 | | |
320 | | /** |
321 | | * cairo_raster_source_pattern_get_snapshot: |
322 | | * @pattern: the pattern to query |
323 | | * |
324 | | * Queries the current snapshot callback. |
325 | | * |
326 | | * Return value: the current snapshot callback |
327 | | * |
328 | | * Since: 1.12 |
329 | | **/ |
330 | | cairo_raster_source_snapshot_func_t |
331 | | cairo_raster_source_pattern_get_snapshot (cairo_pattern_t *abstract_pattern) |
332 | 0 | { |
333 | 0 | cairo_raster_source_pattern_t *pattern; |
334 | |
|
335 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
336 | 0 | return NULL; |
337 | | |
338 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
339 | 0 | return pattern->snapshot; |
340 | 0 | } |
341 | | |
342 | | /** |
343 | | * cairo_raster_source_pattern_set_copy: |
344 | | * @pattern: the pattern to update |
345 | | * @copy: the copy callback |
346 | | * |
347 | | * Updates the copy callback which is used whenever a temporary copy of the |
348 | | * pattern is taken. |
349 | | * |
350 | | * Since: 1.12 |
351 | | **/ |
352 | | void |
353 | | cairo_raster_source_pattern_set_copy (cairo_pattern_t *abstract_pattern, |
354 | | cairo_raster_source_copy_func_t copy) |
355 | 0 | { |
356 | 0 | cairo_raster_source_pattern_t *pattern; |
357 | |
|
358 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
359 | 0 | return; |
360 | | |
361 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
362 | 0 | pattern->copy = copy; |
363 | 0 | } |
364 | | |
365 | | /** |
366 | | * cairo_raster_source_pattern_get_copy: |
367 | | * @pattern: the pattern to query |
368 | | * |
369 | | * Queries the current copy callback. |
370 | | * |
371 | | * Return value: the current copy callback |
372 | | * |
373 | | * Since: 1.12 |
374 | | **/ |
375 | | cairo_raster_source_copy_func_t |
376 | | cairo_raster_source_pattern_get_copy (cairo_pattern_t *abstract_pattern) |
377 | 0 | { |
378 | 0 | cairo_raster_source_pattern_t *pattern; |
379 | |
|
380 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
381 | 0 | return NULL; |
382 | | |
383 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
384 | 0 | return pattern->copy; |
385 | 0 | } |
386 | | |
387 | | /** |
388 | | * cairo_raster_source_pattern_set_finish: |
389 | | * @pattern: the pattern to update |
390 | | * @finish: the finish callback |
391 | | * |
392 | | * Updates the finish callback which is used whenever a pattern (or a copy |
393 | | * thereof) will no longer be used. |
394 | | * |
395 | | * Since: 1.12 |
396 | | **/ |
397 | | void |
398 | | cairo_raster_source_pattern_set_finish (cairo_pattern_t *abstract_pattern, |
399 | | cairo_raster_source_finish_func_t finish) |
400 | 0 | { |
401 | 0 | cairo_raster_source_pattern_t *pattern; |
402 | |
|
403 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
404 | 0 | return; |
405 | | |
406 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
407 | 0 | pattern->finish = finish; |
408 | 0 | } |
409 | | |
410 | | /** |
411 | | * cairo_raster_source_pattern_get_finish: |
412 | | * @pattern: the pattern to query |
413 | | * |
414 | | * Queries the current finish callback. |
415 | | * |
416 | | * Return value: the current finish callback |
417 | | * |
418 | | * Since: 1.12 |
419 | | **/ |
420 | | cairo_raster_source_finish_func_t |
421 | | cairo_raster_source_pattern_get_finish (cairo_pattern_t *abstract_pattern) |
422 | 0 | { |
423 | 0 | cairo_raster_source_pattern_t *pattern; |
424 | |
|
425 | 0 | if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) |
426 | 0 | return NULL; |
427 | | |
428 | 0 | pattern = (cairo_raster_source_pattern_t *) abstract_pattern; |
429 | 0 | return pattern->finish; |
430 | 0 | } |