added MouseWheel event support for Silverlight 3.0
[moon.git] / cairo / src / cairo-image-surface.c
blob4aad77f051de23911886591bf7da14dbd219f091
1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2003 University of Southern California
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is University of Southern
32 * California.
34 * Contributor(s):
35 * Carl D. Worth <cworth@cworth.org>
38 #include "cairoint.h"
40 static cairo_format_t
41 _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
43 switch (pixman_format) {
44 case PIXMAN_a8r8g8b8:
45 return CAIRO_FORMAT_ARGB32;
46 case PIXMAN_x8r8g8b8:
47 return CAIRO_FORMAT_RGB24;
48 case PIXMAN_a8:
49 return CAIRO_FORMAT_A8;
50 case PIXMAN_a1:
51 return CAIRO_FORMAT_A1;
52 case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
53 case PIXMAN_b8g8r8: case PIXMAN_r5g6b5: case PIXMAN_b5g6r5:
54 case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
55 case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
56 case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2:
57 case PIXMAN_b2g3r3: case PIXMAN_a2r2g2b2: case PIXMAN_a2b2g2r2:
58 case PIXMAN_c8: case PIXMAN_g8: case PIXMAN_x4a4:
59 case PIXMAN_a4: case PIXMAN_r1g2b1: case PIXMAN_b1g2r1:
60 case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
61 case PIXMAN_g4: case PIXMAN_g1:
62 case PIXMAN_yuy2: case PIXMAN_yv12:
63 #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
64 case PIXMAN_x2b10g10r10:
65 case PIXMAN_a2b10g10r10:
66 #endif
67 default:
68 return CAIRO_FORMAT_INVALID;
71 return CAIRO_FORMAT_INVALID;
74 static cairo_content_t
75 _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
77 switch (pixman_format) {
78 case PIXMAN_a8r8g8b8:
79 case PIXMAN_a8b8g8r8:
80 case PIXMAN_a1r5g5b5:
81 case PIXMAN_a1b5g5r5:
82 case PIXMAN_a4r4g4b4:
83 case PIXMAN_a4b4g4r4:
84 case PIXMAN_a2r2g2b2:
85 case PIXMAN_a2b2g2r2:
86 case PIXMAN_a1r1g1b1:
87 case PIXMAN_a1b1g1r1:
88 #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
89 case PIXMAN_a2b10g10r10:
90 #endif
91 return CAIRO_CONTENT_COLOR_ALPHA;
92 case PIXMAN_x8r8g8b8:
93 case PIXMAN_x8b8g8r8:
94 case PIXMAN_r8g8b8:
95 case PIXMAN_b8g8r8:
96 case PIXMAN_r5g6b5:
97 case PIXMAN_b5g6r5:
98 case PIXMAN_x1r5g5b5:
99 case PIXMAN_x1b5g5r5:
100 case PIXMAN_x4r4g4b4:
101 case PIXMAN_x4b4g4r4:
102 case PIXMAN_r3g3b2:
103 case PIXMAN_b2g3r3:
104 case PIXMAN_c8:
105 case PIXMAN_g8:
106 case PIXMAN_r1g2b1:
107 case PIXMAN_b1g2r1:
108 case PIXMAN_c4:
109 case PIXMAN_g4:
110 case PIXMAN_g1:
111 case PIXMAN_yuy2:
112 case PIXMAN_yv12:
113 #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
114 case PIXMAN_x2b10g10r10:
115 #endif
116 return CAIRO_CONTENT_COLOR;
117 case PIXMAN_a8:
118 case PIXMAN_a1:
119 case PIXMAN_x4a4:
120 case PIXMAN_a4:
121 return CAIRO_CONTENT_ALPHA;
124 return CAIRO_CONTENT_COLOR_ALPHA;
127 cairo_surface_t *
128 _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
129 pixman_format_code_t pixman_format)
131 cairo_image_surface_t *surface;
133 surface = malloc (sizeof (cairo_image_surface_t));
134 if (surface == NULL)
135 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
137 _cairo_surface_init (&surface->base, &_cairo_image_surface_backend,
138 _cairo_content_from_pixman_format (pixman_format));
140 surface->pixman_image = pixman_image;
142 surface->pixman_format = pixman_format;
143 surface->format = _cairo_format_from_pixman_format (pixman_format);
144 surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
145 surface->owns_data = FALSE;
146 surface->has_clip = FALSE;
147 surface->transparency = CAIRO_IMAGE_UNKNOWN;
149 surface->width = pixman_image_get_width (pixman_image);
150 surface->height = pixman_image_get_height (pixman_image);
151 surface->stride = pixman_image_get_stride (pixman_image);
152 surface->depth = pixman_image_get_depth (pixman_image);
154 return &surface->base;
157 cairo_bool_t
158 _pixman_format_from_masks (cairo_format_masks_t *masks,
159 pixman_format_code_t *format_ret)
161 pixman_format_code_t format;
162 int format_type;
163 int a, r, g, b;
164 cairo_format_masks_t format_masks;
166 a = _cairo_popcount (masks->alpha_mask);
167 r = _cairo_popcount (masks->red_mask);
168 g = _cairo_popcount (masks->green_mask);
169 b = _cairo_popcount (masks->blue_mask);
171 if (masks->red_mask) {
172 if (masks->red_mask > masks->blue_mask)
173 format_type = PIXMAN_TYPE_ARGB;
174 else
175 format_type = PIXMAN_TYPE_ABGR;
176 } else if (masks->alpha_mask) {
177 format_type = PIXMAN_TYPE_A;
178 } else {
179 return FALSE;
182 format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b);
184 if (! pixman_format_supported_destination (format))
185 return FALSE;
187 /* Sanity check that we got out of PIXMAN_FORMAT exactly what we
188 * expected. This avoid any problems from something bizarre like
189 * alpha in the least-significant bits, or insane channel order,
190 * or whatever. */
191 _pixman_format_to_masks (format, &format_masks);
193 if (masks->bpp != format_masks.bpp ||
194 masks->red_mask != format_masks.red_mask ||
195 masks->green_mask != format_masks.green_mask ||
196 masks->blue_mask != format_masks.blue_mask)
198 return FALSE;
201 *format_ret = format;
202 return TRUE;
205 /* A mask consisting of N bits set to 1. */
206 #define MASK(N) ((1 << (N))-1)
208 void
209 _pixman_format_to_masks (pixman_format_code_t format,
210 cairo_format_masks_t *masks)
212 int a, r, g, b;
214 masks->bpp = PIXMAN_FORMAT_BPP (format);
216 /* Number of bits in each channel */
217 a = PIXMAN_FORMAT_A (format);
218 r = PIXMAN_FORMAT_R (format);
219 g = PIXMAN_FORMAT_G (format);
220 b = PIXMAN_FORMAT_B (format);
222 switch (PIXMAN_FORMAT_TYPE (format)) {
223 case PIXMAN_TYPE_ARGB:
224 masks->alpha_mask = MASK (a) << (r + g + b);
225 masks->red_mask = MASK (r) << (g + b);
226 masks->green_mask = MASK (g) << (b);
227 masks->blue_mask = MASK (b);
228 return;
229 case PIXMAN_TYPE_ABGR:
230 masks->alpha_mask = MASK (a) << (b + g + r);
231 masks->blue_mask = MASK (b) << (g +r);
232 masks->green_mask = MASK (g) << (r);
233 masks->red_mask = MASK (r);
234 return;
235 case PIXMAN_TYPE_A:
236 masks->alpha_mask = MASK (a);
237 masks->red_mask = 0;
238 masks->green_mask = 0;
239 masks->blue_mask = 0;
240 return;
241 case PIXMAN_TYPE_OTHER:
242 case PIXMAN_TYPE_COLOR:
243 case PIXMAN_TYPE_GRAY:
244 case PIXMAN_TYPE_YUY2:
245 case PIXMAN_TYPE_YV12:
246 default:
247 masks->alpha_mask = 0;
248 masks->red_mask = 0;
249 masks->green_mask = 0;
250 masks->blue_mask = 0;
251 return;
255 /* XXX: This function really should be eliminated. We don't really
256 * want to advertise a cairo image surface that supports any possible
257 * format. A minimal step would be to replace this function with one
258 * that accepts a #cairo_internal_format_t rather than mask values. */
259 cairo_surface_t *
260 _cairo_image_surface_create_with_masks (unsigned char *data,
261 cairo_format_masks_t *masks,
262 int width,
263 int height,
264 int stride)
266 pixman_format_code_t pixman_format;
268 if (! _pixman_format_from_masks (masks, &pixman_format)) {
269 fprintf (stderr,
270 "Error: Cairo %s does not yet support the requested image format:\n"
271 "\tDepth: %d\n"
272 "\tAlpha mask: 0x%08lx\n"
273 "\tRed mask: 0x%08lx\n"
274 "\tGreen mask: 0x%08lx\n"
275 "\tBlue mask: 0x%08lx\n"
276 #ifdef PACKAGE_BUGGREPORT
277 "Please file an enhancement request (quoting the above) at:\n"
278 PACKAGE_BUGREPORT"\n"
279 #endif
281 cairo_version_string (),
282 masks->bpp, masks->alpha_mask,
283 masks->red_mask, masks->green_mask, masks->blue_mask);
285 ASSERT_NOT_REACHED;
288 return _cairo_image_surface_create_with_pixman_format (data,
289 pixman_format,
290 width,
291 height,
292 stride);
295 static pixman_format_code_t
296 _cairo_format_to_pixman_format_code (cairo_format_t format)
298 pixman_format_code_t ret;
299 switch (format) {
300 case CAIRO_FORMAT_A1:
301 ret = PIXMAN_a1;
302 break;
303 case CAIRO_FORMAT_A8:
304 ret = PIXMAN_a8;
305 break;
306 case CAIRO_FORMAT_RGB24:
307 ret = PIXMAN_x8r8g8b8;
308 break;
309 case CAIRO_FORMAT_ARGB32:
310 default:
311 ret = PIXMAN_a8r8g8b8;
312 break;
314 return ret;
317 cairo_surface_t *
318 _cairo_image_surface_create_with_pixman_format (unsigned char *data,
319 pixman_format_code_t pixman_format,
320 int width,
321 int height,
322 int stride)
324 cairo_surface_t *surface;
325 pixman_image_t *pixman_image;
327 pixman_image = pixman_image_create_bits (pixman_format, width, height,
328 (uint32_t *) data, stride);
330 if (pixman_image == NULL)
331 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
333 surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
334 pixman_format);
335 if (cairo_surface_status (surface))
336 pixman_image_unref (pixman_image);
338 return surface;
342 * cairo_image_surface_create:
343 * @format: format of pixels in the surface to create
344 * @width: width of the surface, in pixels
345 * @height: height of the surface, in pixels
347 * Creates an image surface of the specified format and
348 * dimensions. Initially the surface contents are all
349 * 0. (Specifically, within each pixel, each color or alpha channel
350 * belonging to format will be 0. The contents of bits within a pixel,
351 * but not belonging to the given format are undefined).
353 * Return value: a pointer to the newly created surface. The caller
354 * owns the surface and should call cairo_surface_destroy() when done
355 * with it.
357 * This function always returns a valid pointer, but it will return a
358 * pointer to a "nil" surface if an error such as out of memory
359 * occurs. You can use cairo_surface_status() to check for this.
361 cairo_surface_t *
362 cairo_image_surface_create (cairo_format_t format,
363 int width,
364 int height)
366 pixman_format_code_t pixman_format;
368 if (! CAIRO_FORMAT_VALID (format))
369 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
371 pixman_format = _cairo_format_to_pixman_format_code (format);
373 return _cairo_image_surface_create_with_pixman_format (NULL, pixman_format,
374 width, height, -1);
376 slim_hidden_def (cairo_image_surface_create);
378 cairo_surface_t *
379 _cairo_image_surface_create_with_content (cairo_content_t content,
380 int width,
381 int height)
383 if (! CAIRO_CONTENT_VALID (content))
384 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
386 return cairo_image_surface_create (_cairo_format_from_content (content),
387 width, height);
391 * cairo_format_stride_for_width:
392 * @format: A #cairo_format_t value
393 * @width: The desired width of an image surface to be created.
395 * This function provides a stride value that will respect all
396 * alignment requirements of the accelerated image-rendering code
397 * within cairo. Typical usage will be of the form:
399 * <informalexample><programlisting>
400 * int stride;
401 * unsigned char *data;
402 * #cairo_surface_t *surface;
404 * stride = cairo_format_stride_for_width (format, width);
405 * data = malloc (stride * height);
406 * surface = cairo_image_surface_create_for_data (data, format,
407 * width, height,
408 * stride);
409 * </programlisting></informalexample>
411 * Return value: the appropriate stride to use given the desired
412 * format and width, or -1 if either the format is invalid or the width
413 * too large.
415 * Since: 1.6
418 cairo_format_stride_for_width (cairo_format_t format,
419 int width)
421 int bpp;
423 if (! CAIRO_FORMAT_VALID (format)) {
424 _cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT);
425 return -1;
428 bpp = _cairo_format_bits_per_pixel (format);
429 if ((unsigned) (width) >= (INT32_MAX - 7) / (unsigned) (bpp))
430 return -1;
432 return CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp);
434 slim_hidden_def (cairo_format_stride_for_width);
437 * cairo_image_surface_create_for_data:
438 * @data: a pointer to a buffer supplied by the application in which
439 * to write contents. This pointer must be suitably aligned for any
440 * kind of variable, (for example, a pointer returned by malloc).
441 * @format: the format of pixels in the buffer
442 * @width: the width of the image to be stored in the buffer
443 * @height: the height of the image to be stored in the buffer
444 * @stride: the number of bytes between the start of rows in the
445 * buffer as allocated. This value should always be computed by
446 * cairo_format_stride_for_width() before allocating the data
447 * buffer.
449 * Creates an image surface for the provided pixel data. The output
450 * buffer must be kept around until the #cairo_surface_t is destroyed
451 * or cairo_surface_finish() is called on the surface. The initial
452 * contents of @buffer will be used as the initial image contents; you
453 * must explicitly clear the buffer, using, for example,
454 * cairo_rectangle() and cairo_fill() if you want it cleared.
456 * Note that the stride may be larger than
457 * width*bytes_per_pixel to provide proper alignment for each pixel
458 * and row. This alignment is required to allow high-performance rendering
459 * within cairo. The correct way to obtain a legal stride value is to
460 * call cairo_format_stride_for_width() with the desired format and
461 * maximum image width value, and the use the resulting stride value
462 * to allocate the data and to create the image surface. See
463 * cairo_format_stride_for_width() for example code.
465 * Return value: a pointer to the newly created surface. The caller
466 * owns the surface and should call cairo_surface_destroy() when done
467 * with it.
469 * This function always returns a valid pointer, but it will return a
470 * pointer to a "nil" surface in the case of an error such as out of
471 * memory or an invalid stride value. In case of invalid stride value
472 * the error status of the returned surface will be
473 * %CAIRO_STATUS_INVALID_STRIDE. You can use
474 * cairo_surface_status() to check for this.
476 * See cairo_surface_set_user_data() for a means of attaching a
477 * destroy-notification fallback to the surface if necessary.
479 cairo_surface_t *
480 cairo_image_surface_create_for_data (unsigned char *data,
481 cairo_format_t format,
482 int width,
483 int height,
484 int stride)
486 pixman_format_code_t pixman_format;
487 int minstride;
489 if (! CAIRO_FORMAT_VALID (format))
490 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
492 if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0)
493 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
495 minstride = cairo_format_stride_for_width (format, width);
496 if (stride < 0) {
497 if (stride > -minstride) {
498 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
500 } else {
501 if (stride < minstride) {
502 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
506 pixman_format = _cairo_format_to_pixman_format_code (format);
508 return _cairo_image_surface_create_with_pixman_format (data, pixman_format,
509 width, height, stride);
511 slim_hidden_def (cairo_image_surface_create_for_data);
513 cairo_surface_t *
514 _cairo_image_surface_create_for_data_with_content (unsigned char *data,
515 cairo_content_t content,
516 int width,
517 int height,
518 int stride)
520 if (! CAIRO_CONTENT_VALID (content))
521 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
523 return cairo_image_surface_create_for_data (data,
524 _cairo_format_from_content (content),
525 width, height, stride);
529 * cairo_image_surface_get_data:
530 * @surface: a #cairo_image_surface_t
532 * Get a pointer to the data of the image surface, for direct
533 * inspection or modification.
535 * Return value: a pointer to the image data of this surface or %NULL
536 * if @surface is not an image surface, or if cairo_surface_finish()
537 * has been called.
539 * Since: 1.2
541 unsigned char *
542 cairo_image_surface_get_data (cairo_surface_t *surface)
544 cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
546 if (! _cairo_surface_is_image (surface)) {
547 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
548 return NULL;
551 return image_surface->data;
553 slim_hidden_def (cairo_image_surface_get_data);
556 * cairo_image_surface_get_format:
557 * @surface: a #cairo_image_surface_t
559 * Get the format of the surface.
561 * Return value: the format of the surface
563 * Since: 1.2
565 cairo_format_t
566 cairo_image_surface_get_format (cairo_surface_t *surface)
568 cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
570 if (! _cairo_surface_is_image (surface)) {
571 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
572 return 0;
575 return image_surface->format;
579 * cairo_image_surface_get_width:
580 * @surface: a #cairo_image_surface_t
582 * Get the width of the image surface in pixels.
584 * Return value: the width of the surface in pixels.
587 cairo_image_surface_get_width (cairo_surface_t *surface)
589 cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
591 if (! _cairo_surface_is_image (surface)) {
592 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
593 return 0;
596 return image_surface->width;
598 slim_hidden_def (cairo_image_surface_get_width);
601 * cairo_image_surface_get_height:
602 * @surface: a #cairo_image_surface_t
604 * Get the height of the image surface in pixels.
606 * Return value: the height of the surface in pixels.
609 cairo_image_surface_get_height (cairo_surface_t *surface)
611 cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
613 if (! _cairo_surface_is_image (surface)) {
614 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
615 return 0;
618 return image_surface->height;
620 slim_hidden_def (cairo_image_surface_get_height);
623 * cairo_image_surface_get_stride:
624 * @surface: a #cairo_image_surface_t
626 * Get the stride of the image surface in bytes
628 * Return value: the stride of the image surface in bytes (or 0 if
629 * @surface is not an image surface). The stride is the distance in
630 * bytes from the beginning of one row of the image data to the
631 * beginning of the next row.
633 * Since: 1.2
636 cairo_image_surface_get_stride (cairo_surface_t *surface)
639 cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
641 if (! _cairo_surface_is_image (surface)) {
642 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
643 return 0;
646 return image_surface->stride;
648 slim_hidden_def (cairo_image_surface_get_stride);
650 cairo_format_t
651 _cairo_format_from_content (cairo_content_t content)
653 switch (content) {
654 case CAIRO_CONTENT_COLOR:
655 return CAIRO_FORMAT_RGB24;
656 case CAIRO_CONTENT_ALPHA:
657 return CAIRO_FORMAT_A8;
658 case CAIRO_CONTENT_COLOR_ALPHA:
659 return CAIRO_FORMAT_ARGB32;
662 ASSERT_NOT_REACHED;
663 return CAIRO_FORMAT_ARGB32;
666 cairo_content_t
667 _cairo_content_from_format (cairo_format_t format)
669 switch (format) {
670 case CAIRO_FORMAT_ARGB32:
671 return CAIRO_CONTENT_COLOR_ALPHA;
672 case CAIRO_FORMAT_RGB24:
673 return CAIRO_CONTENT_COLOR;
674 case CAIRO_FORMAT_A8:
675 case CAIRO_FORMAT_A1:
676 return CAIRO_CONTENT_ALPHA;
679 ASSERT_NOT_REACHED;
680 return CAIRO_CONTENT_COLOR_ALPHA;
684 _cairo_format_bits_per_pixel (cairo_format_t format)
686 switch (format) {
687 case CAIRO_FORMAT_ARGB32:
688 return 32;
689 case CAIRO_FORMAT_RGB24:
690 return 32;
691 case CAIRO_FORMAT_A8:
692 return 8;
693 case CAIRO_FORMAT_A1:
694 return 1;
695 default:
696 ASSERT_NOT_REACHED;
697 return 0;
701 static cairo_surface_t *
702 _cairo_image_surface_create_similar (void *abstract_src,
703 cairo_content_t content,
704 int width,
705 int height)
707 assert (CAIRO_CONTENT_VALID (content));
709 return _cairo_image_surface_create_with_content (content,
710 width, height);
713 static cairo_status_t
714 _cairo_image_surface_finish (void *abstract_surface)
716 cairo_image_surface_t *surface = abstract_surface;
718 if (surface->pixman_image) {
719 pixman_image_unref (surface->pixman_image);
720 surface->pixman_image = NULL;
723 if (surface->owns_data) {
724 free (surface->data);
725 surface->data = NULL;
728 return CAIRO_STATUS_SUCCESS;
731 void
732 _cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface)
734 surface->owns_data = 1;
737 static cairo_status_t
738 _cairo_image_surface_acquire_source_image (void *abstract_surface,
739 cairo_image_surface_t **image_out,
740 void **image_extra)
742 *image_out = abstract_surface;
743 *image_extra = NULL;
745 return CAIRO_STATUS_SUCCESS;
748 static void
749 _cairo_image_surface_release_source_image (void *abstract_surface,
750 cairo_image_surface_t *image,
751 void *image_extra)
755 static cairo_status_t
756 _cairo_image_surface_acquire_dest_image (void *abstract_surface,
757 cairo_rectangle_int_t *interest_rect,
758 cairo_image_surface_t **image_out,
759 cairo_rectangle_int_t *image_rect_out,
760 void **image_extra)
762 cairo_image_surface_t *surface = abstract_surface;
764 image_rect_out->x = 0;
765 image_rect_out->y = 0;
766 image_rect_out->width = surface->width;
767 image_rect_out->height = surface->height;
769 *image_out = surface;
770 *image_extra = NULL;
772 return CAIRO_STATUS_SUCCESS;
775 static void
776 _cairo_image_surface_release_dest_image (void *abstract_surface,
777 cairo_rectangle_int_t *interest_rect,
778 cairo_image_surface_t *image,
779 cairo_rectangle_int_t *image_rect,
780 void *image_extra)
784 static cairo_status_t
785 _cairo_image_surface_clone_similar (void *abstract_surface,
786 cairo_surface_t *src,
787 int src_x,
788 int src_y,
789 int width,
790 int height,
791 int *clone_offset_x,
792 int *clone_offset_y,
793 cairo_surface_t **clone_out)
795 cairo_image_surface_t *surface = abstract_surface;
797 if (src->backend == surface->base.backend) {
798 *clone_offset_x = *clone_offset_y = 0;
799 *clone_out = cairo_surface_reference (src);
801 return CAIRO_STATUS_SUCCESS;
804 return CAIRO_INT_STATUS_UNSUPPORTED;
807 static cairo_status_t
808 _cairo_image_surface_set_matrix (cairo_image_surface_t *surface,
809 const cairo_matrix_t *matrix)
811 pixman_transform_t pixman_transform;
813 _cairo_matrix_to_pixman_matrix (matrix, &pixman_transform);
815 if (! pixman_image_set_transform (surface->pixman_image, &pixman_transform))
816 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
818 return CAIRO_STATUS_SUCCESS;
821 static cairo_status_t
822 _cairo_image_surface_set_filter (cairo_image_surface_t *surface,
823 cairo_filter_t filter)
825 pixman_filter_t pixman_filter;
827 switch (filter) {
828 case CAIRO_FILTER_FAST:
829 pixman_filter = PIXMAN_FILTER_FAST;
830 break;
831 case CAIRO_FILTER_GOOD:
832 pixman_filter = PIXMAN_FILTER_GOOD;
833 break;
834 case CAIRO_FILTER_BEST:
835 pixman_filter = PIXMAN_FILTER_BEST;
836 break;
837 case CAIRO_FILTER_NEAREST:
838 pixman_filter = PIXMAN_FILTER_NEAREST;
839 break;
840 case CAIRO_FILTER_BILINEAR:
841 pixman_filter = PIXMAN_FILTER_BILINEAR;
842 break;
843 case CAIRO_FILTER_GAUSSIAN:
844 /* XXX: The GAUSSIAN value has no implementation in cairo
845 * whatsoever, so it was really a mistake to have it in the
846 * API. We could fix this by officially deprecating it, or
847 * else inventing semantics and providing an actual
848 * implementation for it. */
849 default:
850 pixman_filter = PIXMAN_FILTER_BEST;
853 if (! pixman_image_set_filter (surface->pixman_image,
854 pixman_filter,
855 NULL, 0))
857 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
860 return CAIRO_STATUS_SUCCESS;
863 static cairo_status_t
864 _cairo_image_surface_set_attributes (cairo_image_surface_t *surface,
865 cairo_surface_attributes_t *attributes)
867 cairo_int_status_t status;
869 status = _cairo_image_surface_set_matrix (surface, &attributes->matrix);
870 if (status)
871 return status;
873 switch (attributes->extend) {
874 case CAIRO_EXTEND_NONE:
875 pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NONE);
876 break;
877 case CAIRO_EXTEND_REPEAT:
878 pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_NORMAL);
879 break;
880 case CAIRO_EXTEND_REFLECT:
881 pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_REFLECT);
882 break;
883 case CAIRO_EXTEND_PAD:
884 pixman_image_set_repeat (surface->pixman_image, PIXMAN_REPEAT_PAD);
885 break;
888 status = _cairo_image_surface_set_filter (surface, attributes->filter);
889 if (status)
890 return status;
892 return CAIRO_STATUS_SUCCESS;
895 /* XXX: I think we should fix pixman to match the names/order of the
896 * cairo operators, but that will likely be better done at the same
897 * time the X server is ported to pixman, (which will change a lot of
898 * things in pixman I think).
900 static pixman_op_t
901 _pixman_operator (cairo_operator_t op)
903 switch (op) {
904 case CAIRO_OPERATOR_CLEAR:
905 return PIXMAN_OP_CLEAR;
907 case CAIRO_OPERATOR_SOURCE:
908 return PIXMAN_OP_SRC;
909 case CAIRO_OPERATOR_OVER:
910 return PIXMAN_OP_OVER;
911 case CAIRO_OPERATOR_IN:
912 return PIXMAN_OP_IN;
913 case CAIRO_OPERATOR_OUT:
914 return PIXMAN_OP_OUT;
915 case CAIRO_OPERATOR_ATOP:
916 return PIXMAN_OP_ATOP;
918 case CAIRO_OPERATOR_DEST:
919 return PIXMAN_OP_DST;
920 case CAIRO_OPERATOR_DEST_OVER:
921 return PIXMAN_OP_OVER_REVERSE;
922 case CAIRO_OPERATOR_DEST_IN:
923 return PIXMAN_OP_IN_REVERSE;
924 case CAIRO_OPERATOR_DEST_OUT:
925 return PIXMAN_OP_OUT_REVERSE;
926 case CAIRO_OPERATOR_DEST_ATOP:
927 return PIXMAN_OP_ATOP_REVERSE;
929 case CAIRO_OPERATOR_XOR:
930 return PIXMAN_OP_XOR;
931 case CAIRO_OPERATOR_ADD:
932 return PIXMAN_OP_ADD;
933 case CAIRO_OPERATOR_SATURATE:
934 return PIXMAN_OP_SATURATE;
935 default:
936 return PIXMAN_OP_OVER;
940 static cairo_int_status_t
941 _cairo_image_surface_composite (cairo_operator_t op,
942 cairo_pattern_t *src_pattern,
943 cairo_pattern_t *mask_pattern,
944 void *abstract_dst,
945 int src_x,
946 int src_y,
947 int mask_x,
948 int mask_y,
949 int dst_x,
950 int dst_y,
951 unsigned int width,
952 unsigned int height)
954 cairo_surface_attributes_t src_attr, mask_attr;
955 cairo_image_surface_t *dst = abstract_dst;
956 cairo_image_surface_t *src;
957 cairo_image_surface_t *mask;
958 cairo_int_status_t status;
960 status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern,
961 &dst->base,
962 src_x, src_y,
963 mask_x, mask_y,
964 width, height,
965 (cairo_surface_t **) &src,
966 (cairo_surface_t **) &mask,
967 &src_attr, &mask_attr);
968 if (status)
969 return status;
971 status = _cairo_image_surface_set_attributes (src, &src_attr);
972 if (status)
973 goto CLEANUP_SURFACES;
975 if (mask)
977 status = _cairo_image_surface_set_attributes (mask, &mask_attr);
978 if (status)
979 goto CLEANUP_SURFACES;
981 pixman_image_composite (_pixman_operator (op),
982 src->pixman_image,
983 mask->pixman_image,
984 dst->pixman_image,
985 src_x + src_attr.x_offset,
986 src_y + src_attr.y_offset,
987 mask_x + mask_attr.x_offset,
988 mask_y + mask_attr.y_offset,
989 dst_x, dst_y,
990 width, height);
992 else
994 pixman_image_composite (_pixman_operator (op),
995 src->pixman_image,
996 NULL,
997 dst->pixman_image,
998 src_x + src_attr.x_offset,
999 src_y + src_attr.y_offset,
1000 0, 0,
1001 dst_x, dst_y,
1002 width, height);
1005 if (! _cairo_operator_bounded_by_source (op))
1006 status = _cairo_surface_composite_fixup_unbounded (&dst->base,
1007 &src_attr, src->width, src->height,
1008 mask ? &mask_attr : NULL,
1009 mask ? mask->width : 0,
1010 mask ? mask->height : 0,
1011 src_x, src_y,
1012 mask_x, mask_y,
1013 dst_x, dst_y, width, height);
1015 CLEANUP_SURFACES:
1016 if (mask)
1017 _cairo_pattern_release_surface (mask_pattern, &mask->base, &mask_attr);
1019 _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
1021 return status;
1024 static cairo_int_status_t
1025 _cairo_image_surface_fill_rectangles (void *abstract_surface,
1026 cairo_operator_t op,
1027 const cairo_color_t *color,
1028 cairo_rectangle_int_t *rects,
1029 int num_rects)
1031 cairo_image_surface_t *surface = abstract_surface;
1033 pixman_color_t pixman_color;
1034 pixman_rectangle16_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (pixman_rectangle16_t)];
1035 pixman_rectangle16_t *pixman_rects = stack_rects;
1036 int i;
1038 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
1040 pixman_color.red = color->red_short;
1041 pixman_color.green = color->green_short;
1042 pixman_color.blue = color->blue_short;
1043 pixman_color.alpha = color->alpha_short;
1045 if (num_rects > ARRAY_LENGTH (stack_rects)) {
1046 pixman_rects = _cairo_malloc_ab (num_rects, sizeof (pixman_rectangle16_t));
1047 if (pixman_rects == NULL)
1048 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1051 for (i = 0; i < num_rects; i++) {
1052 pixman_rects[i].x = rects[i].x;
1053 pixman_rects[i].y = rects[i].y;
1054 pixman_rects[i].width = rects[i].width;
1055 pixman_rects[i].height = rects[i].height;
1058 /* XXX: pixman_fill_rectangles() should be implemented */
1059 if (! pixman_image_fill_rectangles (_pixman_operator (op),
1060 surface->pixman_image,
1061 &pixman_color,
1062 num_rects,
1063 pixman_rects)) {
1064 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1067 if (pixman_rects != stack_rects)
1068 free (pixman_rects);
1070 return status;
1073 static cairo_int_status_t
1074 _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
1075 cairo_pattern_t *pattern,
1076 void *abstract_dst,
1077 cairo_antialias_t antialias,
1078 int src_x,
1079 int src_y,
1080 int dst_x,
1081 int dst_y,
1082 unsigned int width,
1083 unsigned int height,
1084 cairo_trapezoid_t *traps,
1085 int num_traps)
1087 cairo_surface_attributes_t attributes;
1088 cairo_image_surface_t *dst = abstract_dst;
1089 cairo_image_surface_t *src;
1090 cairo_int_status_t status;
1091 pixman_image_t *mask;
1092 pixman_format_code_t format;
1093 uint32_t *mask_data;
1094 pixman_trapezoid_t stack_traps[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t)];
1095 pixman_trapezoid_t *pixman_traps = stack_traps;
1096 int mask_stride;
1097 int i;
1099 if (height == 0 || width == 0)
1100 return CAIRO_STATUS_SUCCESS;
1102 /* Convert traps to pixman traps */
1103 if (num_traps > ARRAY_LENGTH (stack_traps)) {
1104 pixman_traps = _cairo_malloc_ab (num_traps, sizeof (pixman_trapezoid_t));
1105 if (pixman_traps == NULL)
1106 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1109 for (i = 0; i < num_traps; i++) {
1110 pixman_traps[i].top = _cairo_fixed_to_16_16 (traps[i].top);
1111 pixman_traps[i].bottom = _cairo_fixed_to_16_16 (traps[i].bottom);
1112 pixman_traps[i].left.p1.x = _cairo_fixed_to_16_16 (traps[i].left.p1.x);
1113 pixman_traps[i].left.p1.y = _cairo_fixed_to_16_16 (traps[i].left.p1.y);
1114 pixman_traps[i].left.p2.x = _cairo_fixed_to_16_16 (traps[i].left.p2.x);
1115 pixman_traps[i].left.p2.y = _cairo_fixed_to_16_16 (traps[i].left.p2.y);
1116 pixman_traps[i].right.p1.x = _cairo_fixed_to_16_16 (traps[i].right.p1.x);
1117 pixman_traps[i].right.p1.y = _cairo_fixed_to_16_16 (traps[i].right.p1.y);
1118 pixman_traps[i].right.p2.x = _cairo_fixed_to_16_16 (traps[i].right.p2.x);
1119 pixman_traps[i].right.p2.y = _cairo_fixed_to_16_16 (traps[i].right.p2.y);
1122 /* Special case adding trapezoids onto a mask surface; we want to avoid
1123 * creating an intermediate temporary mask unnecessarily.
1125 * We make the assumption here that the portion of the trapezoids
1126 * contained within the surface is bounded by [dst_x,dst_y,width,height];
1127 * the Cairo core code passes bounds based on the trapezoid extents.
1129 * Currently the check surface->has_clip is needed for correct
1130 * functioning, since pixman_add_trapezoids() doesn't obey the
1131 * surface clip, which is a libpixman bug , but there's no harm in
1132 * falling through to the general case when the surface is clipped
1133 * since libpixman would have to generate an intermediate mask anyways.
1135 if (op == CAIRO_OPERATOR_ADD &&
1136 _cairo_pattern_is_opaque_solid (pattern) &&
1137 dst->base.content == CAIRO_CONTENT_ALPHA &&
1138 ! dst->has_clip &&
1139 antialias != CAIRO_ANTIALIAS_NONE)
1141 pixman_add_trapezoids (dst->pixman_image, 0, 0,
1142 num_traps, pixman_traps);
1143 status = CAIRO_STATUS_SUCCESS;
1144 goto finish;
1147 status = _cairo_pattern_acquire_surface (pattern, &dst->base,
1148 src_x, src_y, width, height,
1149 (cairo_surface_t **) &src,
1150 &attributes);
1151 if (status)
1152 goto finish;
1154 status = _cairo_image_surface_set_attributes (src, &attributes);
1155 if (status)
1156 goto CLEANUP_SOURCE;
1158 switch (antialias) {
1159 case CAIRO_ANTIALIAS_NONE:
1160 format = PIXMAN_a1;
1161 mask_stride = ((width + 31) / 8) & ~0x03;
1162 break;
1163 case CAIRO_ANTIALIAS_GRAY:
1164 case CAIRO_ANTIALIAS_SUBPIXEL:
1165 case CAIRO_ANTIALIAS_DEFAULT:
1166 default:
1167 format = PIXMAN_a8;
1168 mask_stride = (width + 3) & ~3;
1169 break;
1172 /* The image must be initially transparent */
1173 mask_data = calloc (mask_stride, height);
1174 if (mask_data == NULL) {
1175 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1176 goto CLEANUP_SOURCE;
1179 mask = pixman_image_create_bits (format, width, height,
1180 mask_data, mask_stride);
1181 if (mask == NULL) {
1182 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1183 goto CLEANUP_IMAGE_DATA;
1186 pixman_add_trapezoids (mask, - dst_x, - dst_y,
1187 num_traps, pixman_traps);
1189 pixman_image_composite (_pixman_operator (op),
1190 src->pixman_image,
1191 mask,
1192 dst->pixman_image,
1193 src_x + attributes.x_offset,
1194 src_y + attributes.y_offset,
1195 0, 0,
1196 dst_x, dst_y,
1197 width, height);
1199 if (! _cairo_operator_bounded_by_mask (op))
1200 status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
1201 &attributes, src->width, src->height,
1202 width, height,
1203 src_x, src_y,
1204 0, 0,
1205 dst_x, dst_y, width, height);
1206 pixman_image_unref (mask);
1208 CLEANUP_IMAGE_DATA:
1209 free (mask_data);
1211 CLEANUP_SOURCE:
1212 _cairo_pattern_release_surface (pattern, &src->base, &attributes);
1214 finish:
1215 if (pixman_traps != stack_traps)
1216 free (pixman_traps);
1218 return status;
1221 cairo_int_status_t
1222 _cairo_image_surface_set_clip_region (void *abstract_surface,
1223 cairo_region_t *region)
1225 cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
1227 if (! pixman_image_set_clip_region32 (surface->pixman_image, &region->rgn))
1228 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1230 surface->has_clip = region != NULL;
1232 return CAIRO_STATUS_SUCCESS;
1235 static cairo_int_status_t
1236 _cairo_image_surface_get_extents (void *abstract_surface,
1237 cairo_rectangle_int_t *rectangle)
1239 cairo_image_surface_t *surface = abstract_surface;
1241 rectangle->x = 0;
1242 rectangle->y = 0;
1243 rectangle->width = surface->width;
1244 rectangle->height = surface->height;
1246 return CAIRO_STATUS_SUCCESS;
1249 static void
1250 _cairo_image_surface_get_font_options (void *abstract_surface,
1251 cairo_font_options_t *options)
1253 _cairo_font_options_init_default (options);
1255 cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
1258 static cairo_status_t
1259 _cairo_image_surface_reset (void *abstract_surface)
1261 cairo_image_surface_t *surface = abstract_surface;
1262 cairo_status_t status;
1264 status = _cairo_image_surface_set_clip_region (surface, NULL);
1265 assert (status == CAIRO_STATUS_SUCCESS);
1267 return CAIRO_STATUS_SUCCESS;
1271 * _cairo_surface_is_image:
1272 * @surface: a #cairo_surface_t
1274 * Checks if a surface is an #cairo_image_surface_t
1276 * Return value: %TRUE if the surface is an image surface
1278 cairo_bool_t
1279 _cairo_surface_is_image (const cairo_surface_t *surface)
1281 return surface->backend == &_cairo_image_surface_backend;
1284 const cairo_surface_backend_t _cairo_image_surface_backend = {
1285 CAIRO_SURFACE_TYPE_IMAGE,
1286 _cairo_image_surface_create_similar,
1287 _cairo_image_surface_finish,
1288 _cairo_image_surface_acquire_source_image,
1289 _cairo_image_surface_release_source_image,
1290 _cairo_image_surface_acquire_dest_image,
1291 _cairo_image_surface_release_dest_image,
1292 _cairo_image_surface_clone_similar,
1293 _cairo_image_surface_composite,
1294 _cairo_image_surface_fill_rectangles,
1295 _cairo_image_surface_composite_trapezoids,
1296 NULL, /* copy_page */
1297 NULL, /* show_page */
1298 _cairo_image_surface_set_clip_region,
1299 NULL, /* intersect_clip_path */
1300 _cairo_image_surface_get_extents,
1301 NULL, /* old_show_glyphs */
1302 _cairo_image_surface_get_font_options,
1303 NULL, /* flush */
1304 NULL, /* mark_dirty_rectangle */
1305 NULL, /* font_fini */
1306 NULL, /* glyph_fini */
1308 NULL, /* paint */
1309 NULL, /* mask */
1310 NULL, /* stroke */
1311 NULL, /* fill */
1312 NULL, /* show_glyphs */
1313 NULL, /* snapshot */
1314 NULL, /* is_similar */
1316 _cairo_image_surface_reset
1319 /* A convenience function for when one needs to coerce an image
1320 * surface to an alternate format. */
1321 cairo_image_surface_t *
1322 _cairo_image_surface_clone (cairo_image_surface_t *surface,
1323 cairo_format_t format)
1325 cairo_image_surface_t *clone;
1326 cairo_status_t status;
1327 cairo_t *cr;
1328 double x, y;
1330 clone = (cairo_image_surface_t *)
1331 cairo_image_surface_create (format,
1332 surface->width, surface->height);
1334 cairo_surface_get_device_offset (&surface->base, &x, &y);
1335 cairo_surface_set_device_offset (&clone->base, x, y);
1336 clone->transparency = CAIRO_IMAGE_UNKNOWN;
1338 /* XXX Use _cairo_surface_composite directly */
1339 cr = cairo_create (&clone->base);
1340 cairo_set_source_surface (cr, &surface->base, 0, 0);
1341 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
1342 cairo_paint (cr);
1343 status = cairo_status (cr);
1344 cairo_destroy (cr);
1346 if (status) {
1347 cairo_surface_destroy (&clone->base);
1348 return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
1351 return clone;
1354 cairo_image_transparency_t
1355 _cairo_image_analyze_transparency (cairo_image_surface_t *image)
1357 int x, y;
1359 if (image->transparency != CAIRO_IMAGE_UNKNOWN)
1360 return image->transparency;
1362 if (image->format == CAIRO_FORMAT_RGB24) {
1363 image->transparency = CAIRO_IMAGE_IS_OPAQUE;
1364 return CAIRO_IMAGE_IS_OPAQUE;
1367 if (image->format != CAIRO_FORMAT_ARGB32) {
1368 image->transparency = CAIRO_IMAGE_HAS_ALPHA;
1369 return CAIRO_IMAGE_HAS_ALPHA;
1372 image->transparency = CAIRO_IMAGE_IS_OPAQUE;
1373 for (y = 0; y < image->height; y++) {
1374 uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
1376 for (x = 0; x < image->width; x++, pixel++) {
1377 int a = (*pixel & 0xff000000) >> 24;
1378 if (a > 0 && a < 255) {
1379 image->transparency = CAIRO_IMAGE_HAS_ALPHA;
1380 return CAIRO_IMAGE_HAS_ALPHA;
1381 } else if (a == 0) {
1382 image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
1387 return image->transparency;