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