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