/work/workdir/UnpackedTarball/cairo/src/cairo-image-surface.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 © 2003 University of Southern California |
5 | | * Copyright © 2009,2010,2011 Intel Corporation |
6 | | * |
7 | | * This library is free software; you can redistribute it and/or |
8 | | * modify it either under the terms of the GNU Lesser General Public |
9 | | * License version 2.1 as published by the Free Software Foundation |
10 | | * (the "LGPL") or, at your option, under the terms of the Mozilla |
11 | | * Public License Version 1.1 (the "MPL"). If you do not alter this |
12 | | * notice, a recipient may use your version of this file under either |
13 | | * the MPL or the LGPL. |
14 | | * |
15 | | * You should have received a copy of the LGPL along with this library |
16 | | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
17 | | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
18 | | * You should have received a copy of the MPL along with this library |
19 | | * in the file COPYING-MPL-1.1 |
20 | | * |
21 | | * The contents of this file are subject to the Mozilla Public License |
22 | | * Version 1.1 (the "License"); you may not use this file except in |
23 | | * compliance with the License. You may obtain a copy of the License at |
24 | | * http://www.mozilla.org/MPL/ |
25 | | * |
26 | | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
27 | | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
28 | | * the specific language governing rights and limitations. |
29 | | * |
30 | | * The Original Code is the cairo graphics library. |
31 | | * |
32 | | * The Initial Developer of the Original Code is University of Southern |
33 | | * California. |
34 | | * |
35 | | * Contributor(s): |
36 | | * Carl D. Worth <cworth@cworth.org> |
37 | | * Chris Wilson <chris@chris-wilson.co.uk> |
38 | | */ |
39 | | |
40 | | #include "cairoint.h" |
41 | | |
42 | | #include "cairo-boxes-private.h" |
43 | | #include "cairo-clip-private.h" |
44 | | #include "cairo-composite-rectangles-private.h" |
45 | | #include "cairo-compositor-private.h" |
46 | | #include "cairo-default-context-private.h" |
47 | | #include "cairo-error-private.h" |
48 | | #include "cairo-image-surface-inline.h" |
49 | | #include "cairo-paginated-private.h" |
50 | | #include "cairo-pattern-private.h" |
51 | | #include "cairo-pixman-private.h" |
52 | | #include "cairo-recording-surface-private.h" |
53 | | #include "cairo-region-private.h" |
54 | | #include "cairo-scaled-font-private.h" |
55 | | #include "cairo-surface-snapshot-inline.h" |
56 | | #include "cairo-surface-snapshot-private.h" |
57 | | #include "cairo-surface-subsurface-private.h" |
58 | | |
59 | | /* Limit on the width / height of an image surface in pixels. This is |
60 | | * mainly determined by coordinates of things sent to pixman at the |
61 | | * moment being in 16.16 format. */ |
62 | 7.35M | #define MAX_IMAGE_SIZE 32767 |
63 | | |
64 | | /** |
65 | | * SECTION:cairo-image |
66 | | * @Title: Image Surfaces |
67 | | * @Short_Description: Rendering to memory buffers |
68 | | * @See_Also: #cairo_surface_t |
69 | | * |
70 | | * Image surfaces provide the ability to render to memory buffers |
71 | | * either allocated by cairo or by the calling code. The supported |
72 | | * image formats are those defined in #cairo_format_t. |
73 | | **/ |
74 | | |
75 | | /** |
76 | | * CAIRO_HAS_IMAGE_SURFACE: |
77 | | * |
78 | | * Defined if the image surface backend is available. |
79 | | * The image surface backend is always built in. |
80 | | * This macro was added for completeness in cairo 1.8. |
81 | | * |
82 | | * Since: 1.8 |
83 | | **/ |
84 | | |
85 | | static cairo_bool_t |
86 | | _cairo_image_surface_is_size_valid (int width, int height) |
87 | 2.45M | { |
88 | 2.45M | return 0 <= width && width <= MAX_IMAGE_SIZE && |
89 | 2.45M | 0 <= height && height <= MAX_IMAGE_SIZE; |
90 | 2.45M | } |
91 | | |
92 | | cairo_format_t |
93 | | _cairo_format_from_pixman_format (pixman_format_code_t pixman_format) |
94 | 2.39M | { |
95 | 2.39M | switch (pixman_format) { |
96 | 0 | case PIXMAN_rgba_float: |
97 | 0 | return CAIRO_FORMAT_RGBA128F; |
98 | 0 | case PIXMAN_rgb_float: |
99 | 0 | return CAIRO_FORMAT_RGB96F; |
100 | 2.36M | case PIXMAN_a8r8g8b8: |
101 | 2.36M | return CAIRO_FORMAT_ARGB32; |
102 | 0 | case PIXMAN_x2r10g10b10: |
103 | 0 | return CAIRO_FORMAT_RGB30; |
104 | 3 | case PIXMAN_x8r8g8b8: |
105 | 3 | return CAIRO_FORMAT_RGB24; |
106 | 25.7k | case PIXMAN_a8: |
107 | 25.7k | return CAIRO_FORMAT_A8; |
108 | 58 | case PIXMAN_a1: |
109 | 58 | return CAIRO_FORMAT_A1; |
110 | 0 | case PIXMAN_r5g6b5: |
111 | 0 | return CAIRO_FORMAT_RGB16_565; |
112 | 2.14k | case PIXMAN_r8g8b8: |
113 | 2.14k | return CAIRO_FORMAT_RGB24_888; |
114 | 0 | #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0) |
115 | 0 | case PIXMAN_r8g8b8a8: case PIXMAN_r8g8b8x8: |
116 | 0 | #endif |
117 | 0 | #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,27,2) |
118 | 0 | case PIXMAN_a8r8g8b8_sRGB: |
119 | 0 | #endif |
120 | 0 | case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: |
121 | 0 | case PIXMAN_b8g8r8: case PIXMAN_b5g6r5: |
122 | 0 | case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5: |
123 | 0 | case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4: |
124 | 0 | case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2: |
125 | 0 | case PIXMAN_b2g3r3: case PIXMAN_a2r2g2b2: case PIXMAN_a2b2g2r2: |
126 | 0 | case PIXMAN_c8: case PIXMAN_g8: case PIXMAN_x4a4: |
127 | 0 | case PIXMAN_a4: case PIXMAN_r1g2b1: case PIXMAN_b1g2r1: |
128 | 0 | case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4: |
129 | 0 | case PIXMAN_g4: case PIXMAN_g1: |
130 | 0 | case PIXMAN_yuy2: case PIXMAN_yv12: |
131 | 0 | case PIXMAN_b8g8r8x8: |
132 | 0 | case PIXMAN_b8g8r8a8: |
133 | 0 | case PIXMAN_a2b10g10r10: |
134 | 0 | case PIXMAN_x2b10g10r10: |
135 | 0 | case PIXMAN_a2r10g10b10: |
136 | 0 | #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0) |
137 | 0 | case PIXMAN_x14r6g6b6: |
138 | 0 | #endif |
139 | 0 | default: |
140 | 0 | return CAIRO_FORMAT_INVALID; |
141 | 2.39M | } |
142 | | |
143 | 0 | return CAIRO_FORMAT_INVALID; |
144 | 2.39M | } |
145 | | |
146 | | cairo_content_t |
147 | | _cairo_content_from_pixman_format (pixman_format_code_t pixman_format) |
148 | 2.39M | { |
149 | 2.39M | cairo_content_t content; |
150 | | |
151 | 2.39M | content = 0; |
152 | 2.39M | if (PIXMAN_FORMAT_RGB (pixman_format)) |
153 | 2.36M | content |= CAIRO_CONTENT_COLOR; |
154 | 2.39M | if (PIXMAN_FORMAT_A (pixman_format)) |
155 | 2.39M | content |= CAIRO_CONTENT_ALPHA; |
156 | | |
157 | 2.39M | return content; |
158 | 2.39M | } |
159 | | |
160 | | void |
161 | | _cairo_image_surface_init (cairo_image_surface_t *surface, |
162 | | pixman_image_t *pixman_image, |
163 | | pixman_format_code_t pixman_format) |
164 | 2.39M | { |
165 | 2.39M | surface->parent = NULL; |
166 | 2.39M | surface->pixman_image = pixman_image; |
167 | | |
168 | 2.39M | surface->pixman_format = pixman_format; |
169 | 2.39M | surface->format = _cairo_format_from_pixman_format (pixman_format); |
170 | 2.39M | surface->data = (uint8_t *) pixman_image_get_data (pixman_image); |
171 | 2.39M | surface->owns_data = FALSE; |
172 | 2.39M | surface->transparency = CAIRO_IMAGE_UNKNOWN; |
173 | 2.39M | surface->color = CAIRO_IMAGE_UNKNOWN_COLOR; |
174 | | |
175 | 2.39M | surface->width = pixman_image_get_width (pixman_image); |
176 | 2.39M | surface->height = pixman_image_get_height (pixman_image); |
177 | 2.39M | surface->stride = pixman_image_get_stride (pixman_image); |
178 | 2.39M | surface->depth = pixman_image_get_depth (pixman_image); |
179 | | |
180 | 2.39M | surface->base.is_clear = surface->width == 0 || surface->height == 0; |
181 | | |
182 | 2.39M | surface->compositor = _cairo_image_spans_compositor_get (); |
183 | 2.39M | } |
184 | | |
185 | | cairo_surface_t * |
186 | | _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image, |
187 | | pixman_format_code_t pixman_format) |
188 | 2.39M | { |
189 | 2.39M | cairo_image_surface_t *surface; |
190 | | |
191 | 2.39M | surface = _cairo_malloc (sizeof (cairo_image_surface_t)); |
192 | 2.39M | if (unlikely (surface == NULL)) |
193 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
194 | | |
195 | 2.39M | _cairo_surface_init (&surface->base, |
196 | 2.39M | &_cairo_image_surface_backend, |
197 | 2.39M | NULL, /* device */ |
198 | 2.39M | _cairo_content_from_pixman_format (pixman_format), |
199 | 2.39M | FALSE); /* is_vector */ |
200 | | |
201 | 2.39M | _cairo_image_surface_init (surface, pixman_image, pixman_format); |
202 | | |
203 | 2.39M | return &surface->base; |
204 | 2.39M | } |
205 | | |
206 | | cairo_bool_t |
207 | | _pixman_format_from_masks (cairo_format_masks_t *masks, |
208 | | pixman_format_code_t *format_ret) |
209 | 0 | { |
210 | 0 | pixman_format_code_t format; |
211 | 0 | int format_type; |
212 | 0 | int a, r, g, b; |
213 | 0 | cairo_format_masks_t format_masks; |
214 | |
|
215 | 0 | a = _cairo_popcount (masks->alpha_mask); |
216 | 0 | r = _cairo_popcount (masks->red_mask); |
217 | 0 | g = _cairo_popcount (masks->green_mask); |
218 | 0 | b = _cairo_popcount (masks->blue_mask); |
219 | |
|
220 | 0 | if (masks->red_mask) { |
221 | 0 | if (masks->red_mask > masks->blue_mask) |
222 | 0 | format_type = PIXMAN_TYPE_ARGB; |
223 | 0 | else |
224 | 0 | format_type = PIXMAN_TYPE_ABGR; |
225 | 0 | } else if (masks->alpha_mask) { |
226 | 0 | format_type = PIXMAN_TYPE_A; |
227 | 0 | } else { |
228 | 0 | return FALSE; |
229 | 0 | } |
230 | | |
231 | 0 | format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b); |
232 | |
|
233 | 0 | if (! pixman_format_supported_destination (format)) |
234 | 0 | return FALSE; |
235 | | |
236 | | /* Sanity check that we got out of PIXMAN_FORMAT exactly what we |
237 | | * expected. This avoid any problems from something bizarre like |
238 | | * alpha in the least-significant bits, or insane channel order, |
239 | | * or whatever. */ |
240 | 0 | if (!_pixman_format_to_masks (format, &format_masks) || |
241 | 0 | masks->bpp != format_masks.bpp || |
242 | 0 | masks->red_mask != format_masks.red_mask || |
243 | 0 | masks->green_mask != format_masks.green_mask || |
244 | 0 | masks->blue_mask != format_masks.blue_mask) |
245 | 0 | { |
246 | 0 | return FALSE; |
247 | 0 | } |
248 | | |
249 | 0 | *format_ret = format; |
250 | 0 | return TRUE; |
251 | 0 | } |
252 | | |
253 | | /* A mask consisting of N bits set to 1. */ |
254 | 0 | #define MASK(N) ((1UL << (N))-1) |
255 | | |
256 | | cairo_bool_t |
257 | | _pixman_format_to_masks (pixman_format_code_t format, |
258 | | cairo_format_masks_t *masks) |
259 | 0 | { |
260 | 0 | int a, r, g, b; |
261 | |
|
262 | 0 | masks->bpp = PIXMAN_FORMAT_BPP (format); |
263 | | |
264 | | /* Number of bits in each channel */ |
265 | 0 | a = PIXMAN_FORMAT_A (format); |
266 | 0 | r = PIXMAN_FORMAT_R (format); |
267 | 0 | g = PIXMAN_FORMAT_G (format); |
268 | 0 | b = PIXMAN_FORMAT_B (format); |
269 | |
|
270 | 0 | switch (PIXMAN_FORMAT_TYPE (format)) { |
271 | 0 | case PIXMAN_TYPE_ARGB: |
272 | 0 | masks->alpha_mask = MASK (a) << (r + g + b); |
273 | 0 | masks->red_mask = MASK (r) << (g + b); |
274 | 0 | masks->green_mask = MASK (g) << (b); |
275 | 0 | masks->blue_mask = MASK (b); |
276 | 0 | return TRUE; |
277 | 0 | case PIXMAN_TYPE_ABGR: |
278 | 0 | masks->alpha_mask = MASK (a) << (b + g + r); |
279 | 0 | masks->blue_mask = MASK (b) << (g + r); |
280 | 0 | masks->green_mask = MASK (g) << (r); |
281 | 0 | masks->red_mask = MASK (r); |
282 | 0 | return TRUE; |
283 | 0 | #ifdef PIXMAN_TYPE_BGRA |
284 | 0 | case PIXMAN_TYPE_BGRA: |
285 | 0 | masks->blue_mask = MASK (b) << (masks->bpp - b); |
286 | 0 | masks->green_mask = MASK (g) << (masks->bpp - b - g); |
287 | 0 | masks->red_mask = MASK (r) << (masks->bpp - b - g - r); |
288 | 0 | masks->alpha_mask = MASK (a); |
289 | 0 | return TRUE; |
290 | 0 | #endif |
291 | 0 | case PIXMAN_TYPE_A: |
292 | 0 | masks->alpha_mask = MASK (a); |
293 | 0 | masks->red_mask = 0; |
294 | 0 | masks->green_mask = 0; |
295 | 0 | masks->blue_mask = 0; |
296 | 0 | return TRUE; |
297 | 0 | case PIXMAN_TYPE_OTHER: |
298 | 0 | case PIXMAN_TYPE_COLOR: |
299 | 0 | case PIXMAN_TYPE_GRAY: |
300 | 0 | case PIXMAN_TYPE_YUY2: |
301 | 0 | case PIXMAN_TYPE_YV12: |
302 | 0 | default: |
303 | 0 | masks->alpha_mask = 0; |
304 | 0 | masks->red_mask = 0; |
305 | 0 | masks->green_mask = 0; |
306 | 0 | masks->blue_mask = 0; |
307 | 0 | return FALSE; |
308 | 0 | } |
309 | 0 | } |
310 | | |
311 | | pixman_format_code_t |
312 | | _cairo_format_to_pixman_format_code (cairo_format_t format) |
313 | 2.38M | { |
314 | 2.38M | pixman_format_code_t ret; |
315 | 2.38M | switch (format) { |
316 | 58 | case CAIRO_FORMAT_A1: |
317 | 58 | ret = PIXMAN_a1; |
318 | 58 | break; |
319 | 25.7k | case CAIRO_FORMAT_A8: |
320 | 25.7k | ret = PIXMAN_a8; |
321 | 25.7k | break; |
322 | 3 | case CAIRO_FORMAT_RGB24: |
323 | 3 | ret = PIXMAN_x8r8g8b8; |
324 | 3 | break; |
325 | 0 | case CAIRO_FORMAT_RGB30: |
326 | 0 | ret = PIXMAN_x2r10g10b10; |
327 | 0 | break; |
328 | 0 | case CAIRO_FORMAT_RGB16_565: |
329 | 0 | ret = PIXMAN_r5g6b5; |
330 | 0 | break; |
331 | 0 | case CAIRO_FORMAT_RGB96F: |
332 | 0 | ret = PIXMAN_rgb_float; |
333 | 0 | break; |
334 | 0 | case CAIRO_FORMAT_RGBA128F: |
335 | 0 | ret = PIXMAN_rgba_float; |
336 | 0 | break; |
337 | 2.14k | case CAIRO_FORMAT_RGB24_888: |
338 | 2.14k | ret = PIXMAN_r8g8b8; |
339 | 2.14k | break; |
340 | 2.35M | case CAIRO_FORMAT_ARGB32: |
341 | 2.35M | case CAIRO_FORMAT_INVALID: |
342 | 2.35M | default: |
343 | 2.35M | ret = PIXMAN_a8r8g8b8; |
344 | 2.35M | break; |
345 | 2.38M | } |
346 | 2.38M | return ret; |
347 | 2.38M | } |
348 | | |
349 | | cairo_surface_t * |
350 | | _cairo_image_surface_create_with_pixman_format (unsigned char *data, |
351 | | pixman_format_code_t pixman_format, |
352 | | int width, |
353 | | int height, |
354 | | int stride) |
355 | 2.39M | { |
356 | 2.39M | cairo_surface_t *surface; |
357 | 2.39M | pixman_image_t *pixman_image; |
358 | | |
359 | 2.39M | if (! _cairo_image_surface_is_size_valid (width, height)) |
360 | 0 | { |
361 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); |
362 | 0 | } |
363 | | |
364 | 2.39M | pixman_image = pixman_image_create_bits (pixman_format, width, height, |
365 | 2.39M | (uint32_t *) data, stride); |
366 | | |
367 | 2.39M | if (unlikely (pixman_image == NULL)) |
368 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
369 | | |
370 | 2.39M | surface = _cairo_image_surface_create_for_pixman_image (pixman_image, |
371 | 2.39M | pixman_format); |
372 | 2.39M | if (unlikely (surface->status)) { |
373 | 0 | pixman_image_unref (pixman_image); |
374 | 0 | return surface; |
375 | 0 | } |
376 | | |
377 | | /* we can not make any assumptions about the initial state of user data */ |
378 | 2.39M | surface->is_clear = data == NULL; |
379 | 2.39M | return surface; |
380 | 2.39M | } |
381 | | |
382 | | /** |
383 | | * cairo_image_surface_create: |
384 | | * @format: format of pixels in the surface to create |
385 | | * @width: width of the surface, in pixels |
386 | | * @height: height of the surface, in pixels |
387 | | * |
388 | | * Creates an image surface of the specified format and |
389 | | * dimensions. Initially the surface contents are set to 0. |
390 | | * (Specifically, within each pixel, each color or alpha channel |
391 | | * belonging to format will be 0. The contents of bits within a pixel, |
392 | | * but not belonging to the given format are undefined). |
393 | | * |
394 | | * Return value: a pointer to the newly created surface. The caller |
395 | | * owns the surface and should call cairo_surface_destroy() when done |
396 | | * with it. |
397 | | * |
398 | | * This function always returns a valid pointer, but it will return a |
399 | | * pointer to a "nil" surface if an error such as out of memory |
400 | | * occurs. You can use cairo_surface_status() to check for this. |
401 | | * |
402 | | * Since: 1.0 |
403 | | **/ |
404 | | cairo_surface_t * |
405 | | cairo_image_surface_create (cairo_format_t format, |
406 | | int width, |
407 | | int height) |
408 | 2.34M | { |
409 | 2.34M | pixman_format_code_t pixman_format; |
410 | | |
411 | 2.34M | if (! CAIRO_FORMAT_VALID (format)) |
412 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); |
413 | | |
414 | 2.34M | pixman_format = _cairo_format_to_pixman_format_code (format); |
415 | | |
416 | 2.34M | return _cairo_image_surface_create_with_pixman_format (NULL, pixman_format, |
417 | 2.34M | width, height, -1); |
418 | 2.34M | } |
419 | | slim_hidden_def (cairo_image_surface_create); |
420 | | |
421 | | cairo_surface_t * |
422 | | _cairo_image_surface_create_with_content (cairo_content_t content, |
423 | | int width, |
424 | | int height) |
425 | 0 | { |
426 | 0 | return cairo_image_surface_create (_cairo_format_from_content (content), |
427 | 0 | width, height); |
428 | 0 | } |
429 | | |
430 | | /** |
431 | | * cairo_format_stride_for_width: |
432 | | * @format: A #cairo_format_t value |
433 | | * @width: The desired width of an image surface to be created. |
434 | | * |
435 | | * This function provides a stride value that will respect all |
436 | | * alignment requirements of the accelerated image-rendering code |
437 | | * within cairo. Typical usage will be of the form: |
438 | | * |
439 | | * <informalexample><programlisting> |
440 | | * int stride; |
441 | | * unsigned char *data; |
442 | | * cairo_surface_t *surface; |
443 | | * |
444 | | * stride = cairo_format_stride_for_width (format, width); |
445 | | * data = malloc (stride * height); |
446 | | * surface = cairo_image_surface_create_for_data (data, format, |
447 | | * width, height, |
448 | | * stride); |
449 | | * </programlisting></informalexample> |
450 | | * |
451 | | * Return value: the appropriate stride to use given the desired |
452 | | * format and width, or -1 if either the format is invalid or the width |
453 | | * too large. |
454 | | * |
455 | | * Since: 1.6 |
456 | | **/ |
457 | | int |
458 | | cairo_format_stride_for_width (cairo_format_t format, |
459 | | int width) |
460 | 72.5k | { |
461 | 72.5k | int bpp; |
462 | | |
463 | 72.5k | if (! CAIRO_FORMAT_VALID (format)) { |
464 | 0 | _cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT); |
465 | 0 | return -1; |
466 | 0 | } |
467 | | |
468 | 72.5k | bpp = _cairo_format_bits_per_pixel (format); |
469 | 72.5k | if ((unsigned) (width) >= (INT32_MAX - 7) / (unsigned) (bpp)) |
470 | 0 | return -1; |
471 | | |
472 | 72.5k | return CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp); |
473 | 72.5k | } |
474 | | slim_hidden_def (cairo_format_stride_for_width); |
475 | | |
476 | | /** |
477 | | * cairo_image_surface_create_for_data: |
478 | | * @data: a pointer to a buffer supplied by the application in which |
479 | | * to write contents. This pointer must be suitably aligned for any |
480 | | * kind of variable, (for example, a pointer returned by malloc). |
481 | | * @format: the format of pixels in the buffer |
482 | | * @width: the width of the image to be stored in the buffer |
483 | | * @height: the height of the image to be stored in the buffer |
484 | | * @stride: the number of bytes between the start of rows in the |
485 | | * buffer as allocated. This value should always be computed by |
486 | | * cairo_format_stride_for_width() before allocating the data |
487 | | * buffer. |
488 | | * |
489 | | * Creates an image surface for the provided pixel data. The output |
490 | | * buffer must be kept around until the #cairo_surface_t is destroyed |
491 | | * or cairo_surface_finish() is called on the surface. The initial |
492 | | * contents of @data will be used as the initial image contents; you |
493 | | * must explicitly clear the buffer, using, for example, |
494 | | * cairo_rectangle() and cairo_fill() if you want it cleared. |
495 | | * |
496 | | * Note that the stride may be larger than |
497 | | * width*bytes_per_pixel to provide proper alignment for each pixel |
498 | | * and row. This alignment is required to allow high-performance rendering |
499 | | * within cairo. The correct way to obtain a legal stride value is to |
500 | | * call cairo_format_stride_for_width() with the desired format and |
501 | | * maximum image width value, and then use the resulting stride value |
502 | | * to allocate the data and to create the image surface. See |
503 | | * cairo_format_stride_for_width() for example code. |
504 | | * |
505 | | * Return value: a pointer to the newly created surface. The caller |
506 | | * owns the surface and should call cairo_surface_destroy() when done |
507 | | * with it. |
508 | | * |
509 | | * This function always returns a valid pointer, but it will return a |
510 | | * pointer to a "nil" surface in the case of an error such as out of |
511 | | * memory or an invalid stride value. In case of invalid stride value |
512 | | * the error status of the returned surface will be |
513 | | * %CAIRO_STATUS_INVALID_STRIDE. You can use |
514 | | * cairo_surface_status() to check for this. |
515 | | * |
516 | | * See cairo_surface_set_user_data() for a means of attaching a |
517 | | * destroy-notification fallback to the surface if necessary. |
518 | | * |
519 | | * Since: 1.0 |
520 | | **/ |
521 | | cairo_surface_t * |
522 | | cairo_image_surface_create_for_data (unsigned char *data, |
523 | | cairo_format_t format, |
524 | | int width, |
525 | | int height, |
526 | | int stride) |
527 | 46.7k | { |
528 | 46.7k | pixman_format_code_t pixman_format; |
529 | 46.7k | int minstride; |
530 | | |
531 | 46.7k | if (! CAIRO_FORMAT_VALID (format)) |
532 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); |
533 | | |
534 | 46.7k | if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0) |
535 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); |
536 | | |
537 | 46.7k | if (! _cairo_image_surface_is_size_valid (width, height)) |
538 | 1 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); |
539 | | |
540 | 46.7k | minstride = cairo_format_stride_for_width (format, width); |
541 | 46.7k | if (stride < 0) { |
542 | 0 | if (stride > -minstride) { |
543 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); |
544 | 0 | } |
545 | 46.7k | } else { |
546 | 46.7k | if (stride < minstride) { |
547 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE)); |
548 | 0 | } |
549 | 46.7k | } |
550 | | |
551 | 46.7k | pixman_format = _cairo_format_to_pixman_format_code (format); |
552 | 46.7k | return _cairo_image_surface_create_with_pixman_format (data, |
553 | 46.7k | pixman_format, |
554 | 46.7k | width, height, |
555 | 46.7k | stride); |
556 | 46.7k | } |
557 | | slim_hidden_def (cairo_image_surface_create_for_data); |
558 | | |
559 | | /** |
560 | | * cairo_image_surface_get_data: |
561 | | * @surface: a #cairo_image_surface_t |
562 | | * |
563 | | * Get a pointer to the data of the image surface, for direct |
564 | | * inspection or modification. |
565 | | * |
566 | | * A call to cairo_surface_flush() is required before accessing the |
567 | | * pixel data to ensure that all pending drawing operations are |
568 | | * finished. A call to cairo_surface_mark_dirty() is required after |
569 | | * the data is modified. |
570 | | * |
571 | | * Return value: a pointer to the image data of this surface or %NULL |
572 | | * if @surface is not an image surface, or if cairo_surface_finish() |
573 | | * has been called. |
574 | | * |
575 | | * Since: 1.2 |
576 | | **/ |
577 | | unsigned char * |
578 | | cairo_image_surface_get_data (cairo_surface_t *surface) |
579 | 529k | { |
580 | 529k | cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; |
581 | | |
582 | 529k | if (! _cairo_surface_is_image (surface)) { |
583 | 0 | _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); |
584 | 0 | return NULL; |
585 | 0 | } |
586 | | |
587 | 529k | return image_surface->data; |
588 | 529k | } |
589 | | slim_hidden_def (cairo_image_surface_get_data); |
590 | | |
591 | | /** |
592 | | * cairo_image_surface_get_format: |
593 | | * @surface: a #cairo_image_surface_t |
594 | | * |
595 | | * Get the format of the surface. |
596 | | * |
597 | | * Return value: the format of the surface |
598 | | * |
599 | | * Since: 1.2 |
600 | | **/ |
601 | | cairo_format_t |
602 | | cairo_image_surface_get_format (cairo_surface_t *surface) |
603 | 4.84k | { |
604 | 4.84k | cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; |
605 | | |
606 | 4.84k | if (! _cairo_surface_is_image (surface)) { |
607 | 0 | _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); |
608 | 0 | return CAIRO_FORMAT_INVALID; |
609 | 0 | } |
610 | | |
611 | 4.84k | return image_surface->format; |
612 | 4.84k | } |
613 | | slim_hidden_def (cairo_image_surface_get_format); |
614 | | |
615 | | /** |
616 | | * cairo_image_surface_get_width: |
617 | | * @surface: a #cairo_image_surface_t |
618 | | * |
619 | | * Get the width of the image surface in pixels. |
620 | | * |
621 | | * Return value: the width of the surface in pixels. |
622 | | * |
623 | | * Since: 1.0 |
624 | | **/ |
625 | | int |
626 | | cairo_image_surface_get_width (cairo_surface_t *surface) |
627 | 16.3k | { |
628 | 16.3k | cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; |
629 | | |
630 | 16.3k | if (! _cairo_surface_is_image (surface)) { |
631 | 0 | _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); |
632 | 0 | return 0; |
633 | 0 | } |
634 | | |
635 | 16.3k | return image_surface->width; |
636 | 16.3k | } |
637 | | slim_hidden_def (cairo_image_surface_get_width); |
638 | | |
639 | | /** |
640 | | * cairo_image_surface_get_height: |
641 | | * @surface: a #cairo_image_surface_t |
642 | | * |
643 | | * Get the height of the image surface in pixels. |
644 | | * |
645 | | * Return value: the height of the surface in pixels. |
646 | | * |
647 | | * Since: 1.0 |
648 | | **/ |
649 | | int |
650 | | cairo_image_surface_get_height (cairo_surface_t *surface) |
651 | 14.0k | { |
652 | 14.0k | cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; |
653 | | |
654 | 14.0k | if (! _cairo_surface_is_image (surface)) { |
655 | 0 | _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); |
656 | 0 | return 0; |
657 | 0 | } |
658 | | |
659 | 14.0k | return image_surface->height; |
660 | 14.0k | } |
661 | | slim_hidden_def (cairo_image_surface_get_height); |
662 | | |
663 | | /** |
664 | | * cairo_image_surface_get_stride: |
665 | | * @surface: a #cairo_image_surface_t |
666 | | * |
667 | | * Get the stride of the image surface in bytes |
668 | | * |
669 | | * Return value: the stride of the image surface in bytes (or 0 if |
670 | | * @surface is not an image surface). The stride is the distance in |
671 | | * bytes from the beginning of one row of the image data to the |
672 | | * beginning of the next row. |
673 | | * |
674 | | * Since: 1.2 |
675 | | **/ |
676 | | int |
677 | | cairo_image_surface_get_stride (cairo_surface_t *surface) |
678 | 142 | { |
679 | | |
680 | 142 | cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface; |
681 | | |
682 | 142 | if (! _cairo_surface_is_image (surface)) { |
683 | 0 | _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); |
684 | 0 | return 0; |
685 | 0 | } |
686 | | |
687 | 142 | return image_surface->stride; |
688 | 142 | } |
689 | | slim_hidden_def (cairo_image_surface_get_stride); |
690 | | |
691 | | cairo_format_t |
692 | | _cairo_format_from_content (cairo_content_t content) |
693 | 0 | { |
694 | 0 | switch (content) { |
695 | 0 | case CAIRO_CONTENT_COLOR: |
696 | 0 | return CAIRO_FORMAT_RGB24; |
697 | 0 | case CAIRO_CONTENT_ALPHA: |
698 | 0 | return CAIRO_FORMAT_A8; |
699 | 0 | case CAIRO_CONTENT_COLOR_ALPHA: |
700 | 0 | return CAIRO_FORMAT_ARGB32; |
701 | 0 | } |
702 | | |
703 | 0 | ASSERT_NOT_REACHED; |
704 | 0 | return CAIRO_FORMAT_INVALID; |
705 | 0 | } |
706 | | |
707 | | cairo_content_t |
708 | | _cairo_content_from_format (cairo_format_t format) |
709 | 0 | { |
710 | 0 | switch (format) { |
711 | 0 | case CAIRO_FORMAT_RGBA128F: |
712 | 0 | case CAIRO_FORMAT_ARGB32: |
713 | 0 | return CAIRO_CONTENT_COLOR_ALPHA; |
714 | 0 | case CAIRO_FORMAT_RGB96F: |
715 | 0 | case CAIRO_FORMAT_RGB30: |
716 | 0 | return CAIRO_CONTENT_COLOR; |
717 | 0 | case CAIRO_FORMAT_RGB24: |
718 | 0 | return CAIRO_CONTENT_COLOR; |
719 | 0 | case CAIRO_FORMAT_RGB16_565: |
720 | 0 | return CAIRO_CONTENT_COLOR; |
721 | 0 | case CAIRO_FORMAT_A8: |
722 | 0 | case CAIRO_FORMAT_A1: |
723 | 0 | return CAIRO_CONTENT_ALPHA; |
724 | 0 | case CAIRO_FORMAT_INVALID: |
725 | 0 | break; |
726 | 0 | } |
727 | | |
728 | 0 | ASSERT_NOT_REACHED; |
729 | 0 | return CAIRO_CONTENT_COLOR_ALPHA; |
730 | 0 | } |
731 | | |
732 | | int |
733 | | _cairo_format_bits_per_pixel (cairo_format_t format) |
734 | 72.5k | { |
735 | 72.5k | switch (format) { |
736 | 0 | case CAIRO_FORMAT_RGBA128F: |
737 | 0 | return 128; |
738 | 0 | case CAIRO_FORMAT_RGB96F: |
739 | 0 | return 96; |
740 | 42.4k | case CAIRO_FORMAT_ARGB32: |
741 | 42.4k | case CAIRO_FORMAT_RGB30: |
742 | 42.4k | case CAIRO_FORMAT_RGB24: |
743 | 42.4k | return 32; |
744 | 4.28k | case CAIRO_FORMAT_RGB24_888: |
745 | 4.28k | return 24; |
746 | 0 | case CAIRO_FORMAT_RGB16_565: |
747 | 0 | return 16; |
748 | 25.7k | case CAIRO_FORMAT_A8: |
749 | 25.7k | return 8; |
750 | 0 | case CAIRO_FORMAT_A1: |
751 | 0 | return 1; |
752 | 0 | case CAIRO_FORMAT_INVALID: |
753 | 0 | default: |
754 | 0 | ASSERT_NOT_REACHED; |
755 | 0 | return 0; |
756 | 72.5k | } |
757 | 72.5k | } |
758 | | |
759 | | cairo_surface_t * |
760 | | _cairo_image_surface_create_similar (void *abstract_other, |
761 | | cairo_content_t content, |
762 | | int width, |
763 | | int height) |
764 | 8.47k | { |
765 | 8.47k | cairo_image_surface_t *other = abstract_other; |
766 | | |
767 | 8.47k | TRACE ((stderr, "%s (other=%u)\n", __FUNCTION__, other->base.unique_id)); |
768 | | |
769 | 8.47k | if (! _cairo_image_surface_is_size_valid (width, height)) |
770 | 0 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); |
771 | | |
772 | 8.47k | if (content == other->base.content) { |
773 | 8.47k | return _cairo_image_surface_create_with_pixman_format (NULL, |
774 | 8.47k | other->pixman_format, |
775 | 8.47k | width, height, |
776 | 8.47k | 0); |
777 | 8.47k | } |
778 | | |
779 | 0 | return _cairo_image_surface_create_with_content (content, |
780 | 0 | width, height); |
781 | 8.47k | } |
782 | | |
783 | | cairo_surface_t * |
784 | | _cairo_image_surface_snapshot (void *abstract_surface) |
785 | 0 | { |
786 | 0 | cairo_image_surface_t *image = abstract_surface; |
787 | 0 | cairo_image_surface_t *clone; |
788 | | |
789 | | /* If we own the image, we can simply steal the memory for the snapshot */ |
790 | 0 | if (image->owns_data && image->base._finishing) { |
791 | 0 | clone = (cairo_image_surface_t *) |
792 | 0 | _cairo_image_surface_create_for_pixman_image (image->pixman_image, |
793 | 0 | image->pixman_format); |
794 | 0 | if (unlikely (clone->base.status)) |
795 | 0 | return &clone->base; |
796 | | |
797 | 0 | image->pixman_image = NULL; |
798 | 0 | image->owns_data = FALSE; |
799 | |
|
800 | 0 | clone->transparency = image->transparency; |
801 | 0 | clone->color = image->color; |
802 | |
|
803 | 0 | clone->owns_data = TRUE; |
804 | 0 | return &clone->base; |
805 | 0 | } |
806 | | |
807 | 0 | clone = (cairo_image_surface_t *) |
808 | 0 | _cairo_image_surface_create_with_pixman_format (NULL, |
809 | 0 | image->pixman_format, |
810 | 0 | image->width, |
811 | 0 | image->height, |
812 | 0 | 0); |
813 | 0 | if (unlikely (clone->base.status)) |
814 | 0 | return &clone->base; |
815 | | |
816 | 0 | if (clone->stride == image->stride) { |
817 | 0 | memcpy (clone->data, image->data, clone->stride * clone->height); |
818 | 0 | } else { |
819 | 0 | pixman_image_composite32 (PIXMAN_OP_SRC, |
820 | 0 | image->pixman_image, NULL, clone->pixman_image, |
821 | 0 | 0, 0, |
822 | 0 | 0, 0, |
823 | 0 | 0, 0, |
824 | 0 | image->width, image->height); |
825 | 0 | } |
826 | 0 | clone->base.is_clear = FALSE; |
827 | 0 | return &clone->base; |
828 | 0 | } |
829 | | |
830 | | cairo_image_surface_t * |
831 | | _cairo_image_surface_map_to_image (void *abstract_other, |
832 | | const cairo_rectangle_int_t *extents) |
833 | 0 | { |
834 | 0 | cairo_image_surface_t *other = abstract_other; |
835 | 0 | cairo_surface_t *surface; |
836 | 0 | uint8_t *data; |
837 | |
|
838 | 0 | data = other->data; |
839 | 0 | data += extents->y * other->stride; |
840 | 0 | data += extents->x * PIXMAN_FORMAT_BPP (other->pixman_format)/ 8; |
841 | |
|
842 | 0 | surface = |
843 | 0 | _cairo_image_surface_create_with_pixman_format (data, |
844 | 0 | other->pixman_format, |
845 | 0 | extents->width, |
846 | 0 | extents->height, |
847 | 0 | other->stride); |
848 | |
|
849 | 0 | cairo_surface_set_device_offset (surface, -extents->x, -extents->y); |
850 | 0 | return (cairo_image_surface_t *) surface; |
851 | 0 | } |
852 | | |
853 | | cairo_int_status_t |
854 | | _cairo_image_surface_unmap_image (void *abstract_surface, |
855 | | cairo_image_surface_t *image) |
856 | 0 | { |
857 | 0 | cairo_surface_finish (&image->base); |
858 | 0 | cairo_surface_destroy (&image->base); |
859 | |
|
860 | 0 | return CAIRO_INT_STATUS_SUCCESS; |
861 | 0 | } |
862 | | |
863 | | cairo_status_t |
864 | | _cairo_image_surface_finish (void *abstract_surface) |
865 | 2.37M | { |
866 | 2.37M | cairo_image_surface_t *surface = abstract_surface; |
867 | | |
868 | 2.37M | if (surface->pixman_image) { |
869 | 2.37M | pixman_image_unref (surface->pixman_image); |
870 | 2.37M | surface->pixman_image = NULL; |
871 | 2.37M | } |
872 | | |
873 | 2.37M | if (surface->owns_data) { |
874 | 14.2k | free (surface->data); |
875 | 14.2k | surface->data = NULL; |
876 | 14.2k | } |
877 | | |
878 | 2.37M | if (surface->parent) { |
879 | 0 | cairo_surface_t *parent = surface->parent; |
880 | 0 | surface->parent = NULL; |
881 | 0 | cairo_surface_destroy (parent); |
882 | 0 | } |
883 | | |
884 | 2.37M | return CAIRO_STATUS_SUCCESS; |
885 | 2.37M | } |
886 | | |
887 | | void |
888 | | _cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface) |
889 | 25.3k | { |
890 | 25.3k | surface->owns_data = TRUE; |
891 | 25.3k | } |
892 | | |
893 | | cairo_surface_t * |
894 | | _cairo_image_surface_source (void *abstract_surface, |
895 | | cairo_rectangle_int_t *extents) |
896 | 539k | { |
897 | 539k | cairo_image_surface_t *surface = abstract_surface; |
898 | | |
899 | 539k | if (extents) { |
900 | 539k | extents->x = extents->y = 0; |
901 | 539k | extents->width = surface->width; |
902 | 539k | extents->height = surface->height; |
903 | 539k | } |
904 | | |
905 | 539k | return &surface->base; |
906 | 539k | } |
907 | | |
908 | | cairo_status_t |
909 | | _cairo_image_surface_acquire_source_image (void *abstract_surface, |
910 | | cairo_image_surface_t **image_out, |
911 | | void **image_extra) |
912 | 0 | { |
913 | 0 | *image_out = abstract_surface; |
914 | 0 | *image_extra = NULL; |
915 | |
|
916 | 0 | return CAIRO_STATUS_SUCCESS; |
917 | 0 | } |
918 | | |
919 | | void |
920 | | _cairo_image_surface_release_source_image (void *abstract_surface, |
921 | | cairo_image_surface_t *image, |
922 | | void *image_extra) |
923 | 0 | { |
924 | 0 | } |
925 | | |
926 | | /* high level image interface */ |
927 | | cairo_bool_t |
928 | | _cairo_image_surface_get_extents (void *abstract_surface, |
929 | | cairo_rectangle_int_t *rectangle) |
930 | 26.9M | { |
931 | 26.9M | cairo_image_surface_t *surface = abstract_surface; |
932 | | |
933 | 26.9M | rectangle->x = 0; |
934 | 26.9M | rectangle->y = 0; |
935 | 26.9M | rectangle->width = surface->width; |
936 | 26.9M | rectangle->height = surface->height; |
937 | | |
938 | 26.9M | return TRUE; |
939 | 26.9M | } |
940 | | |
941 | | cairo_int_status_t |
942 | | _cairo_image_surface_paint (void *abstract_surface, |
943 | | cairo_operator_t op, |
944 | | const cairo_pattern_t *source, |
945 | | const cairo_clip_t *clip) |
946 | 689k | { |
947 | 689k | cairo_image_surface_t *surface = abstract_surface; |
948 | | |
949 | 689k | TRACE ((stderr, "%s (surface=%d)\n", |
950 | 689k | __FUNCTION__, surface->base.unique_id)); |
951 | | |
952 | 689k | return _cairo_compositor_paint (surface->compositor, |
953 | 689k | &surface->base, op, source, clip); |
954 | 689k | } |
955 | | |
956 | | cairo_int_status_t |
957 | | _cairo_image_surface_mask (void *abstract_surface, |
958 | | cairo_operator_t op, |
959 | | const cairo_pattern_t *source, |
960 | | const cairo_pattern_t *mask, |
961 | | const cairo_clip_t *clip) |
962 | 4 | { |
963 | 4 | cairo_image_surface_t *surface = abstract_surface; |
964 | | |
965 | 4 | TRACE ((stderr, "%s (surface=%d)\n", |
966 | 4 | __FUNCTION__, surface->base.unique_id)); |
967 | | |
968 | 4 | return _cairo_compositor_mask (surface->compositor, |
969 | 4 | &surface->base, op, source, mask, clip); |
970 | 4 | } |
971 | | |
972 | | cairo_int_status_t |
973 | | _cairo_image_surface_stroke (void *abstract_surface, |
974 | | cairo_operator_t op, |
975 | | const cairo_pattern_t *source, |
976 | | const cairo_path_fixed_t *path, |
977 | | const cairo_stroke_style_t *style, |
978 | | const cairo_matrix_t *ctm, |
979 | | const cairo_matrix_t *ctm_inverse, |
980 | | double tolerance, |
981 | | cairo_antialias_t antialias, |
982 | | const cairo_clip_t *clip) |
983 | 834k | { |
984 | 834k | cairo_image_surface_t *surface = abstract_surface; |
985 | | |
986 | 834k | TRACE ((stderr, "%s (surface=%d)\n", |
987 | 834k | __FUNCTION__, surface->base.unique_id)); |
988 | | |
989 | 834k | return _cairo_compositor_stroke (surface->compositor, &surface->base, |
990 | 834k | op, source, path, |
991 | 834k | style, ctm, ctm_inverse, |
992 | 834k | tolerance, antialias, clip); |
993 | 834k | } |
994 | | |
995 | | cairo_int_status_t |
996 | | _cairo_image_surface_fill (void *abstract_surface, |
997 | | cairo_operator_t op, |
998 | | const cairo_pattern_t *source, |
999 | | const cairo_path_fixed_t *path, |
1000 | | cairo_fill_rule_t fill_rule, |
1001 | | double tolerance, |
1002 | | cairo_antialias_t antialias, |
1003 | | const cairo_clip_t *clip) |
1004 | 6.57M | { |
1005 | 6.57M | cairo_image_surface_t *surface = abstract_surface; |
1006 | | |
1007 | 6.57M | TRACE ((stderr, "%s (surface=%d)\n", |
1008 | 6.57M | __FUNCTION__, surface->base.unique_id)); |
1009 | | |
1010 | 6.57M | return _cairo_compositor_fill (surface->compositor, &surface->base, |
1011 | 6.57M | op, source, path, |
1012 | 6.57M | fill_rule, tolerance, antialias, |
1013 | 6.57M | clip); |
1014 | 6.57M | } |
1015 | | |
1016 | | cairo_int_status_t |
1017 | | _cairo_image_surface_glyphs (void *abstract_surface, |
1018 | | cairo_operator_t op, |
1019 | | const cairo_pattern_t *source, |
1020 | | cairo_glyph_t *glyphs, |
1021 | | int num_glyphs, |
1022 | | cairo_scaled_font_t *scaled_font, |
1023 | | const cairo_clip_t *clip) |
1024 | 396k | { |
1025 | 396k | cairo_image_surface_t *surface = abstract_surface; |
1026 | | |
1027 | 396k | TRACE ((stderr, "%s (surface=%d)\n", |
1028 | 396k | __FUNCTION__, surface->base.unique_id)); |
1029 | | |
1030 | 396k | return _cairo_compositor_glyphs (surface->compositor, &surface->base, |
1031 | 396k | op, source, |
1032 | 396k | glyphs, num_glyphs, scaled_font, |
1033 | 396k | clip); |
1034 | 396k | } |
1035 | | |
1036 | | void |
1037 | | _cairo_image_surface_get_font_options (void *abstract_surface, |
1038 | | cairo_font_options_t *options) |
1039 | 843 | { |
1040 | 843 | _cairo_font_options_init_default (options); |
1041 | | |
1042 | 843 | cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON); |
1043 | 843 | _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON); |
1044 | 843 | } |
1045 | | |
1046 | | const cairo_surface_backend_t _cairo_image_surface_backend = { |
1047 | | CAIRO_SURFACE_TYPE_IMAGE, |
1048 | | _cairo_image_surface_finish, |
1049 | | |
1050 | | _cairo_default_context_create, |
1051 | | |
1052 | | _cairo_image_surface_create_similar, |
1053 | | NULL, /* create similar image */ |
1054 | | _cairo_image_surface_map_to_image, |
1055 | | _cairo_image_surface_unmap_image, |
1056 | | |
1057 | | _cairo_image_surface_source, |
1058 | | _cairo_image_surface_acquire_source_image, |
1059 | | _cairo_image_surface_release_source_image, |
1060 | | _cairo_image_surface_snapshot, |
1061 | | |
1062 | | NULL, /* copy_page */ |
1063 | | NULL, /* show_page */ |
1064 | | |
1065 | | _cairo_image_surface_get_extents, |
1066 | | _cairo_image_surface_get_font_options, |
1067 | | |
1068 | | NULL, /* flush */ |
1069 | | NULL, |
1070 | | |
1071 | | _cairo_image_surface_paint, |
1072 | | _cairo_image_surface_mask, |
1073 | | _cairo_image_surface_stroke, |
1074 | | _cairo_image_surface_fill, |
1075 | | NULL, /* fill-stroke */ |
1076 | | _cairo_image_surface_glyphs, |
1077 | | }; |
1078 | | |
1079 | | /* A convenience function for when one needs to coerce an image |
1080 | | * surface to an alternate format. */ |
1081 | | cairo_image_surface_t * |
1082 | | _cairo_image_surface_coerce (cairo_image_surface_t *surface) |
1083 | 0 | { |
1084 | 0 | return _cairo_image_surface_coerce_to_format (surface, |
1085 | 0 | _cairo_format_from_content (surface->base.content)); |
1086 | 0 | } |
1087 | | |
1088 | | /* A convenience function for when one needs to coerce an image |
1089 | | * surface to an alternate format. */ |
1090 | | cairo_image_surface_t * |
1091 | | _cairo_image_surface_coerce_to_format (cairo_image_surface_t *surface, |
1092 | | cairo_format_t format) |
1093 | 0 | { |
1094 | 0 | cairo_image_surface_t *clone; |
1095 | 0 | cairo_status_t status; |
1096 | |
|
1097 | 0 | status = surface->base.status; |
1098 | 0 | if (unlikely (status)) |
1099 | 0 | return (cairo_image_surface_t *)_cairo_surface_create_in_error (status); |
1100 | | |
1101 | 0 | if (surface->format == format) |
1102 | 0 | return (cairo_image_surface_t *)cairo_surface_reference(&surface->base); |
1103 | | |
1104 | 0 | clone = (cairo_image_surface_t *) |
1105 | 0 | cairo_image_surface_create (format, surface->width, surface->height); |
1106 | 0 | if (unlikely (clone->base.status)) |
1107 | 0 | return clone; |
1108 | | |
1109 | 0 | pixman_image_composite32 (PIXMAN_OP_SRC, |
1110 | 0 | surface->pixman_image, NULL, clone->pixman_image, |
1111 | 0 | 0, 0, |
1112 | 0 | 0, 0, |
1113 | 0 | 0, 0, |
1114 | 0 | surface->width, surface->height); |
1115 | 0 | clone->base.is_clear = FALSE; |
1116 | |
|
1117 | 0 | clone->base.device_transform = |
1118 | 0 | surface->base.device_transform; |
1119 | 0 | clone->base.device_transform_inverse = |
1120 | 0 | surface->base.device_transform_inverse; |
1121 | |
|
1122 | 0 | return clone; |
1123 | 0 | } |
1124 | | |
1125 | | cairo_image_surface_t * |
1126 | | _cairo_image_surface_create_from_image (cairo_image_surface_t *other, |
1127 | | pixman_format_code_t format, |
1128 | | int x, int y, |
1129 | | int width, int height, int stride) |
1130 | 0 | { |
1131 | 0 | cairo_image_surface_t *surface; |
1132 | 0 | cairo_status_t status; |
1133 | 0 | pixman_image_t *image; |
1134 | 0 | void *mem = NULL; |
1135 | |
|
1136 | 0 | status = other->base.status; |
1137 | 0 | if (unlikely (status)) |
1138 | 0 | goto cleanup; |
1139 | | |
1140 | 0 | if (stride) { |
1141 | 0 | mem = _cairo_malloc_ab (height, stride); |
1142 | 0 | if (unlikely (mem == NULL)) { |
1143 | 0 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1144 | 0 | goto cleanup; |
1145 | 0 | } |
1146 | 0 | } |
1147 | | |
1148 | 0 | image = pixman_image_create_bits (format, width, height, mem, stride); |
1149 | 0 | if (unlikely (image == NULL)) { |
1150 | 0 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); |
1151 | 0 | goto cleanup_mem; |
1152 | 0 | } |
1153 | | |
1154 | 0 | surface = (cairo_image_surface_t *) |
1155 | 0 | _cairo_image_surface_create_for_pixman_image (image, format); |
1156 | 0 | if (unlikely (surface->base.status)) { |
1157 | 0 | status = surface->base.status; |
1158 | 0 | goto cleanup_image; |
1159 | 0 | } |
1160 | | |
1161 | 0 | pixman_image_composite32 (PIXMAN_OP_SRC, |
1162 | 0 | other->pixman_image, NULL, image, |
1163 | 0 | x, y, |
1164 | 0 | 0, 0, |
1165 | 0 | 0, 0, |
1166 | 0 | width, height); |
1167 | 0 | surface->base.is_clear = FALSE; |
1168 | 0 | surface->owns_data = mem != NULL; |
1169 | |
|
1170 | 0 | return surface; |
1171 | | |
1172 | 0 | cleanup_image: |
1173 | 0 | pixman_image_unref (image); |
1174 | 0 | cleanup_mem: |
1175 | 0 | free (mem); |
1176 | 0 | cleanup: |
1177 | 0 | return (cairo_image_surface_t *) _cairo_surface_create_in_error (status); |
1178 | 0 | } |
1179 | | |
1180 | | static cairo_image_transparency_t |
1181 | | _cairo_image_compute_transparency (cairo_image_surface_t *image) |
1182 | 0 | { |
1183 | 0 | int x, y; |
1184 | 0 | cairo_image_transparency_t transparency; |
1185 | |
|
1186 | 0 | if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0) |
1187 | 0 | return CAIRO_IMAGE_IS_OPAQUE; |
1188 | | |
1189 | 0 | if (image->base.is_clear) |
1190 | 0 | return CAIRO_IMAGE_HAS_BILEVEL_ALPHA; |
1191 | | |
1192 | 0 | if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) { |
1193 | 0 | if (image->format == CAIRO_FORMAT_A1) { |
1194 | 0 | return CAIRO_IMAGE_HAS_BILEVEL_ALPHA; |
1195 | 0 | } else if (image->format == CAIRO_FORMAT_A8) { |
1196 | 0 | for (y = 0; y < image->height; y++) { |
1197 | 0 | uint8_t *alpha = (uint8_t *) (image->data + y * image->stride); |
1198 | |
|
1199 | 0 | for (x = 0; x < image->width; x++, alpha++) { |
1200 | 0 | if (*alpha > 0 && *alpha < 255) |
1201 | 0 | return CAIRO_IMAGE_HAS_ALPHA; |
1202 | 0 | } |
1203 | 0 | } |
1204 | 0 | return CAIRO_IMAGE_HAS_BILEVEL_ALPHA; |
1205 | 0 | } else { |
1206 | 0 | return CAIRO_IMAGE_HAS_ALPHA; |
1207 | 0 | } |
1208 | 0 | } |
1209 | | |
1210 | 0 | if (image->format == CAIRO_FORMAT_RGB16_565) { |
1211 | 0 | return CAIRO_IMAGE_IS_OPAQUE; |
1212 | 0 | } |
1213 | | |
1214 | 0 | if (image->format != CAIRO_FORMAT_ARGB32) |
1215 | 0 | return CAIRO_IMAGE_HAS_ALPHA; |
1216 | | |
1217 | 0 | transparency = CAIRO_IMAGE_IS_OPAQUE; |
1218 | 0 | for (y = 0; y < image->height; y++) { |
1219 | 0 | uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); |
1220 | |
|
1221 | 0 | for (x = 0; x < image->width; x++, pixel++) { |
1222 | 0 | int a = (*pixel & 0xff000000) >> 24; |
1223 | 0 | if (a > 0 && a < 255) { |
1224 | 0 | return CAIRO_IMAGE_HAS_ALPHA; |
1225 | 0 | } else if (a == 0) { |
1226 | 0 | transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA; |
1227 | 0 | } |
1228 | 0 | } |
1229 | 0 | } |
1230 | | |
1231 | 0 | return transparency; |
1232 | 0 | } |
1233 | | |
1234 | | cairo_image_transparency_t |
1235 | | _cairo_image_analyze_transparency (cairo_image_surface_t *image) |
1236 | 0 | { |
1237 | 0 | if (_cairo_surface_is_snapshot (&image->base)) { |
1238 | 0 | if (image->transparency == CAIRO_IMAGE_UNKNOWN) |
1239 | 0 | image->transparency = _cairo_image_compute_transparency (image); |
1240 | |
|
1241 | 0 | return image->transparency; |
1242 | 0 | } |
1243 | | |
1244 | 0 | return _cairo_image_compute_transparency (image); |
1245 | 0 | } |
1246 | | |
1247 | | static cairo_image_color_t |
1248 | | _cairo_image_compute_color (cairo_image_surface_t *image) |
1249 | 0 | { |
1250 | 0 | int x, y; |
1251 | 0 | cairo_image_color_t color; |
1252 | |
|
1253 | 0 | if (image->width == 0 || image->height == 0) |
1254 | 0 | return CAIRO_IMAGE_IS_MONOCHROME; |
1255 | | |
1256 | 0 | if (image->format == CAIRO_FORMAT_A1) |
1257 | 0 | return CAIRO_IMAGE_IS_MONOCHROME; |
1258 | | |
1259 | 0 | if (image->format == CAIRO_FORMAT_A8) |
1260 | 0 | return CAIRO_IMAGE_IS_GRAYSCALE; |
1261 | | |
1262 | 0 | if (image->format == CAIRO_FORMAT_ARGB32) { |
1263 | 0 | color = CAIRO_IMAGE_IS_MONOCHROME; |
1264 | 0 | for (y = 0; y < image->height; y++) { |
1265 | 0 | uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); |
1266 | |
|
1267 | 0 | for (x = 0; x < image->width; x++, pixel++) { |
1268 | 0 | int a = (*pixel & 0xff000000) >> 24; |
1269 | 0 | int r = (*pixel & 0x00ff0000) >> 16; |
1270 | 0 | int g = (*pixel & 0x0000ff00) >> 8; |
1271 | 0 | int b = (*pixel & 0x000000ff); |
1272 | 0 | if (a == 0) { |
1273 | 0 | r = g = b = 0; |
1274 | 0 | } else { |
1275 | 0 | r = (r * 255 + a / 2) / a; |
1276 | 0 | g = (g * 255 + a / 2) / a; |
1277 | 0 | b = (b * 255 + a / 2) / a; |
1278 | 0 | } |
1279 | 0 | if (!(r == g && g == b)) |
1280 | 0 | return CAIRO_IMAGE_IS_COLOR; |
1281 | 0 | else if (r > 0 && r < 255) |
1282 | 0 | color = CAIRO_IMAGE_IS_GRAYSCALE; |
1283 | 0 | } |
1284 | 0 | } |
1285 | 0 | return color; |
1286 | 0 | } |
1287 | | |
1288 | 0 | if (image->format == CAIRO_FORMAT_RGB24) { |
1289 | 0 | color = CAIRO_IMAGE_IS_MONOCHROME; |
1290 | 0 | for (y = 0; y < image->height; y++) { |
1291 | 0 | uint32_t *pixel = (uint32_t *) (image->data + y * image->stride); |
1292 | |
|
1293 | 0 | for (x = 0; x < image->width; x++, pixel++) { |
1294 | 0 | int r = (*pixel & 0x00ff0000) >> 16; |
1295 | 0 | int g = (*pixel & 0x0000ff00) >> 8; |
1296 | 0 | int b = (*pixel & 0x000000ff); |
1297 | 0 | if (!(r == g && g == b)) |
1298 | 0 | return CAIRO_IMAGE_IS_COLOR; |
1299 | 0 | else if (r > 0 && r < 255) |
1300 | 0 | color = CAIRO_IMAGE_IS_GRAYSCALE; |
1301 | 0 | } |
1302 | 0 | } |
1303 | 0 | return color; |
1304 | 0 | } |
1305 | | |
1306 | 0 | return CAIRO_IMAGE_IS_COLOR; |
1307 | 0 | } |
1308 | | |
1309 | | cairo_image_color_t |
1310 | | _cairo_image_analyze_color (cairo_image_surface_t *image) |
1311 | 0 | { |
1312 | 0 | if (_cairo_surface_is_snapshot (&image->base)) { |
1313 | 0 | if (image->color == CAIRO_IMAGE_UNKNOWN_COLOR) |
1314 | 0 | image->color = _cairo_image_compute_color (image); |
1315 | |
|
1316 | 0 | return image->color; |
1317 | 0 | } |
1318 | | |
1319 | 0 | return _cairo_image_compute_color (image); |
1320 | 0 | } |
1321 | | |
1322 | | cairo_image_surface_t * |
1323 | | _cairo_image_surface_clone_subimage (cairo_surface_t *surface, |
1324 | | const cairo_rectangle_int_t *extents) |
1325 | 0 | { |
1326 | 0 | cairo_surface_t *image; |
1327 | 0 | cairo_surface_pattern_t pattern; |
1328 | 0 | cairo_status_t status; |
1329 | |
|
1330 | 0 | image = cairo_surface_create_similar_image (surface, |
1331 | 0 | _cairo_format_from_content (surface->content), |
1332 | 0 | extents->width, |
1333 | 0 | extents->height); |
1334 | 0 | if (image->status) |
1335 | 0 | return to_image_surface (image); |
1336 | | |
1337 | | /* TODO: check me with non-identity device_transform. Should we |
1338 | | * clone the scaling, too? */ |
1339 | 0 | cairo_surface_set_device_offset (image, |
1340 | 0 | -extents->x, |
1341 | 0 | -extents->y); |
1342 | |
|
1343 | 0 | _cairo_pattern_init_for_surface (&pattern, surface); |
1344 | 0 | pattern.base.filter = CAIRO_FILTER_NEAREST; |
1345 | |
|
1346 | 0 | status = _cairo_surface_paint (image, |
1347 | 0 | CAIRO_OPERATOR_SOURCE, |
1348 | 0 | &pattern.base, |
1349 | 0 | NULL); |
1350 | |
|
1351 | 0 | _cairo_pattern_fini (&pattern.base); |
1352 | |
|
1353 | 0 | if (unlikely (status)) |
1354 | 0 | goto error; |
1355 | | |
1356 | | /* We use the parent as a flag during map-to-image/umap-image that the |
1357 | | * resultant image came from a fallback rather than as direct call |
1358 | | * to the backend's map_to_image(). Whilst we use it as a simple flag, |
1359 | | * we need to make sure the parent surface obeys the reference counting |
1360 | | * semantics and is consistent for all callers. |
1361 | | */ |
1362 | 0 | _cairo_image_surface_set_parent (to_image_surface (image), |
1363 | 0 | cairo_surface_reference (surface)); |
1364 | |
|
1365 | 0 | return to_image_surface (image); |
1366 | | |
1367 | 0 | error: |
1368 | 0 | cairo_surface_destroy (image); |
1369 | 0 | return to_image_surface (_cairo_surface_create_in_error (status)); |
1370 | 0 | } |