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
35 * Carl D. Worth <cworth@cworth.org>
41 _cairo_format_from_pixman_format (pixman_format_code_t pixman_format
)
43 switch (pixman_format
) {
45 return CAIRO_FORMAT_ARGB32
;
47 return CAIRO_FORMAT_RGB24
;
49 return CAIRO_FORMAT_A8
;
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
:
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
) {
88 #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
89 case PIXMAN_a2b10g10r10
:
91 return CAIRO_CONTENT_COLOR_ALPHA
;
100 case PIXMAN_x4r4g4b4
:
101 case PIXMAN_x4b4g4r4
:
113 #if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
114 case PIXMAN_x2b10g10r10
:
116 return CAIRO_CONTENT_COLOR
;
121 return CAIRO_CONTENT_ALPHA
;
124 return CAIRO_CONTENT_COLOR_ALPHA
;
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
));
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
;
158 _pixman_format_from_masks (cairo_format_masks_t
*masks
,
159 pixman_format_code_t
*format_ret
)
161 pixman_format_code_t format
;
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
;
175 format_type
= PIXMAN_TYPE_ABGR
;
176 } else if (masks
->alpha_mask
) {
177 format_type
= PIXMAN_TYPE_A
;
182 format
= PIXMAN_FORMAT (masks
->bpp
, format_type
, a
, r
, g
, b
);
184 if (! pixman_format_supported_destination (format
))
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,
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
)
201 *format_ret
= format
;
205 /* A mask consisting of N bits set to 1. */
206 #define MASK(N) ((1 << (N))-1)
209 _pixman_format_to_masks (pixman_format_code_t format
,
210 cairo_format_masks_t
*masks
)
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
);
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
);
236 masks
->alpha_mask
= MASK (a
);
238 masks
->green_mask
= 0;
239 masks
->blue_mask
= 0;
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
:
247 masks
->alpha_mask
= 0;
249 masks
->green_mask
= 0;
250 masks
->blue_mask
= 0;
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. */
260 _cairo_image_surface_create_with_masks (unsigned char *data
,
261 cairo_format_masks_t
*masks
,
266 pixman_format_code_t pixman_format
;
268 if (! _pixman_format_from_masks (masks
, &pixman_format
)) {
270 "Error: Cairo %s does not yet support the requested image format:\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"
281 cairo_version_string (),
282 masks
->bpp
, masks
->alpha_mask
,
283 masks
->red_mask
, masks
->green_mask
, masks
->blue_mask
);
288 return _cairo_image_surface_create_with_pixman_format (data
,
295 static pixman_format_code_t
296 _cairo_format_to_pixman_format_code (cairo_format_t format
)
298 pixman_format_code_t ret
;
300 case CAIRO_FORMAT_A1
:
303 case CAIRO_FORMAT_A8
:
306 case CAIRO_FORMAT_RGB24
:
307 ret
= PIXMAN_x8r8g8b8
;
309 case CAIRO_FORMAT_ARGB32
:
311 ret
= PIXMAN_a8r8g8b8
;
318 _cairo_image_surface_create_with_pixman_format (unsigned char *data
,
319 pixman_format_code_t pixman_format
,
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
,
335 if (cairo_surface_status (surface
))
336 pixman_image_unref (pixman_image
);
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
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.
362 cairo_image_surface_create (cairo_format_t format
,
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
,
376 slim_hidden_def (cairo_image_surface_create
);
379 _cairo_image_surface_create_with_content (cairo_content_t content
,
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
),
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>
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,
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
418 cairo_format_stride_for_width (cairo_format_t format
,
423 if (! CAIRO_FORMAT_VALID (format
)) {
424 _cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT
);
428 bpp
= _cairo_format_bits_per_pixel (format
);
429 if ((unsigned) (width
) >= (INT32_MAX
- 7) / (unsigned) (bpp
))
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
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
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.
480 cairo_image_surface_create_for_data (unsigned char *data
,
481 cairo_format_t format
,
486 pixman_format_code_t pixman_format
;
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
);
497 if (stride
> -minstride
) {
498 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE
));
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
);
514 _cairo_image_surface_create_for_data_with_content (unsigned char *data
,
515 cairo_content_t content
,
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()
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
);
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
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
);
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
);
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
);
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.
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
);
646 return image_surface
->stride
;
648 slim_hidden_def (cairo_image_surface_get_stride
);
651 _cairo_format_from_content (cairo_content_t 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
;
663 return CAIRO_FORMAT_ARGB32
;
667 _cairo_content_from_format (cairo_format_t 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
;
680 return CAIRO_CONTENT_COLOR_ALPHA
;
684 _cairo_format_bits_per_pixel (cairo_format_t format
)
687 case CAIRO_FORMAT_ARGB32
:
689 case CAIRO_FORMAT_RGB24
:
691 case CAIRO_FORMAT_A8
:
693 case CAIRO_FORMAT_A1
:
701 static cairo_surface_t
*
702 _cairo_image_surface_create_similar (void *abstract_src
,
703 cairo_content_t content
,
707 assert (CAIRO_CONTENT_VALID (content
));
709 return _cairo_image_surface_create_with_content (content
,
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
;
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
,
742 *image_out
= abstract_surface
;
745 return CAIRO_STATUS_SUCCESS
;
749 _cairo_image_surface_release_source_image (void *abstract_surface
,
750 cairo_image_surface_t
*image
,
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
,
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
;
772 return CAIRO_STATUS_SUCCESS
;
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
,
784 static cairo_status_t
785 _cairo_image_surface_clone_similar (void *abstract_surface
,
786 cairo_surface_t
*src
,
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
;
828 case CAIRO_FILTER_FAST
:
829 pixman_filter
= PIXMAN_FILTER_FAST
;
831 case CAIRO_FILTER_GOOD
:
832 pixman_filter
= PIXMAN_FILTER_GOOD
;
834 case CAIRO_FILTER_BEST
:
835 pixman_filter
= PIXMAN_FILTER_BEST
;
837 case CAIRO_FILTER_NEAREST
:
838 pixman_filter
= PIXMAN_FILTER_NEAREST
;
840 case CAIRO_FILTER_BILINEAR
:
841 pixman_filter
= PIXMAN_FILTER_BILINEAR
;
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. */
850 pixman_filter
= PIXMAN_FILTER_BEST
;
853 if (! pixman_image_set_filter (surface
->pixman_image
,
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
);
873 switch (attributes
->extend
) {
874 case CAIRO_EXTEND_NONE
:
875 pixman_image_set_repeat (surface
->pixman_image
, PIXMAN_REPEAT_NONE
);
877 case CAIRO_EXTEND_REPEAT
:
878 pixman_image_set_repeat (surface
->pixman_image
, PIXMAN_REPEAT_NORMAL
);
880 case CAIRO_EXTEND_REFLECT
:
881 pixman_image_set_repeat (surface
->pixman_image
, PIXMAN_REPEAT_REFLECT
);
883 case CAIRO_EXTEND_PAD
:
884 pixman_image_set_repeat (surface
->pixman_image
, PIXMAN_REPEAT_PAD
);
888 status
= _cairo_image_surface_set_filter (surface
, attributes
->filter
);
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).
901 _pixman_operator (cairo_operator_t 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
:
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
;
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
,
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
,
965 (cairo_surface_t
**) &src
,
966 (cairo_surface_t
**) &mask
,
967 &src_attr
, &mask_attr
);
971 status
= _cairo_image_surface_set_attributes (src
, &src_attr
);
973 goto CLEANUP_SURFACES
;
977 status
= _cairo_image_surface_set_attributes (mask
, &mask_attr
);
979 goto CLEANUP_SURFACES
;
981 pixman_image_composite (_pixman_operator (op
),
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
,
994 pixman_image_composite (_pixman_operator (op
),
998 src_x
+ src_attr
.x_offset
,
999 src_y
+ src_attr
.y_offset
,
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,
1013 dst_x
, dst_y
, width
, height
);
1017 _cairo_pattern_release_surface (mask_pattern
, &mask
->base
, &mask_attr
);
1019 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &src_attr
);
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
,
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
;
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
,
1064 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1067 if (pixman_rects
!= stack_rects
)
1068 free (pixman_rects
);
1073 static cairo_int_status_t
1074 _cairo_image_surface_composite_trapezoids (cairo_operator_t op
,
1075 cairo_pattern_t
*pattern
,
1077 cairo_antialias_t antialias
,
1083 unsigned int height
,
1084 cairo_trapezoid_t
*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
;
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
&&
1139 antialias
!= CAIRO_ANTIALIAS_NONE
)
1141 pixman_add_trapezoids (dst
->pixman_image
, 0, 0,
1142 num_traps
, pixman_traps
);
1143 status
= CAIRO_STATUS_SUCCESS
;
1147 status
= _cairo_pattern_acquire_surface (pattern
, &dst
->base
,
1148 src_x
, src_y
, width
, height
,
1149 (cairo_surface_t
**) &src
,
1154 status
= _cairo_image_surface_set_attributes (src
, &attributes
);
1156 goto CLEANUP_SOURCE
;
1158 switch (antialias
) {
1159 case CAIRO_ANTIALIAS_NONE
:
1161 mask_stride
= ((width
+ 31) / 8) & ~0x03;
1163 case CAIRO_ANTIALIAS_GRAY
:
1164 case CAIRO_ANTIALIAS_SUBPIXEL
:
1165 case CAIRO_ANTIALIAS_DEFAULT
:
1168 mask_stride
= (width
+ 3) & ~3;
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
);
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
),
1193 src_x
+ attributes
.x_offset
,
1194 src_y
+ attributes
.y_offset
,
1199 if (! _cairo_operator_bounded_by_mask (op
))
1200 status
= _cairo_surface_composite_shape_fixup_unbounded (&dst
->base
,
1201 &attributes
, src
->width
, src
->height
,
1205 dst_x
, dst_y
, width
, height
);
1206 pixman_image_unref (mask
);
1212 _cairo_pattern_release_surface (pattern
, &src
->base
, &attributes
);
1215 if (pixman_traps
!= stack_traps
)
1216 free (pixman_traps
);
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
, ®ion
->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
;
1243 rectangle
->width
= surface
->width
;
1244 rectangle
->height
= surface
->height
;
1246 return CAIRO_STATUS_SUCCESS
;
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
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
,
1304 NULL
, /* mark_dirty_rectangle */
1305 NULL
, /* font_fini */
1306 NULL
, /* glyph_fini */
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
;
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
);
1343 status
= cairo_status (cr
);
1347 cairo_surface_destroy (&clone
->base
);
1348 return (cairo_image_surface_t
*) _cairo_surface_create_in_error (status
);
1354 cairo_image_transparency_t
1355 _cairo_image_analyze_transparency (cairo_image_surface_t
*image
)
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
;