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 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-error-private.h"
46 #include "cairo-region-private.h"
47 #include "cairo-scaled-font-private.h"
48 #include "cairo-surface-snapshot-private.h"
49 #include "cairo-surface-subsurface-private.h"
50 
51 /* Limit on the width / height of an image surface in pixels.  This is
52  * mainly determined by coordinates of things sent to pixman at the
53  * moment being in 16.16 format. */
54 #define MAX_IMAGE_SIZE 32767
55 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
56 
57 /**
58  * SECTION:cairo-image
59  * @Title: Image Surfaces
60  * @Short_Description: Rendering to memory buffers
61  * @See_Also: #cairo_surface_t
62  *
63  * Image surfaces provide the ability to render to memory buffers
64  * either allocated by cairo or by the calling code.  The supported
65  * image formats are those defined in #cairo_format_t.
66  */
67 
68 /**
69  * CAIRO_HAS_IMAGE_SURFACE:
70  *
71  * Defined if the image surface backend is available.
72  * The image surface backend is always built in.
73  * This macro was added for completeness in cairo 1.8.
74  *
75  * @Since: 1.8
76  */
77 
78 static cairo_int_status_t
79 _cairo_image_surface_fill (void *dst,
80 			   cairo_operator_t		 op,
81 			   const cairo_pattern_t	*source,
82 			   cairo_path_fixed_t	*path,
83 			   cairo_fill_rule_t		 fill_rule,
84 			   double			 tolerance,
85 			   cairo_antialias_t		 antialias,
86 			   cairo_clip_t		*clip);
87 
88 static pixman_image_t *
89 _pixman_image_for_solid (const cairo_solid_pattern_t *pattern);
90 
91 static cairo_bool_t
_cairo_image_surface_is_size_valid(int width,int height)92 _cairo_image_surface_is_size_valid (int width, int height)
93 {
94     return 0 <= width  &&  width <= MAX_IMAGE_SIZE &&
95 	   0 <= height && height <= MAX_IMAGE_SIZE;
96 }
97 
98 cairo_format_t
_cairo_format_from_pixman_format(pixman_format_code_t pixman_format)99 _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
100 {
101     switch (pixman_format) {
102     case PIXMAN_a8r8g8b8:
103 	return CAIRO_FORMAT_ARGB32;
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     case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
113     case PIXMAN_b8g8r8:   case PIXMAN_b5g6r5:
114     case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
115     case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
116     case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2:
117     case PIXMAN_b2g3r3:   case PIXMAN_a2r2g2b2: case PIXMAN_a2b2g2r2:
118     case PIXMAN_c8:       case PIXMAN_g8:       case PIXMAN_x4a4:
119     case PIXMAN_a4:       case PIXMAN_r1g2b1:   case PIXMAN_b1g2r1:
120     case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
121     case PIXMAN_g4:       case PIXMAN_g1:
122     case PIXMAN_yuy2:     case PIXMAN_yv12:
123     case PIXMAN_b8g8r8x8:
124     case PIXMAN_b8g8r8a8:
125     case PIXMAN_x2b10g10r10:
126     case PIXMAN_a2b10g10r10:
127     case PIXMAN_x2r10g10b10:
128     case PIXMAN_a2r10g10b10:
129     default:
130 	return CAIRO_FORMAT_INVALID;
131     }
132 
133     return CAIRO_FORMAT_INVALID;
134 }
135 
136 cairo_content_t
_cairo_content_from_pixman_format(pixman_format_code_t pixman_format)137 _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
138 {
139     cairo_content_t content;
140 
141     content = 0;
142     if (PIXMAN_FORMAT_RGB (pixman_format))
143 	content |= CAIRO_CONTENT_COLOR;
144     if (PIXMAN_FORMAT_A (pixman_format))
145 	content |= CAIRO_CONTENT_ALPHA;
146 
147     return content;
148 }
149 
150 cairo_surface_t *
_cairo_image_surface_create_for_pixman_image(pixman_image_t * pixman_image,pixman_format_code_t pixman_format)151 _cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
152 					      pixman_format_code_t	 pixman_format)
153 {
154     cairo_image_surface_t *surface;
155     int width = pixman_image_get_width (pixman_image);
156     int height = pixman_image_get_height (pixman_image);
157 
158     surface = malloc (sizeof (cairo_image_surface_t));
159     if (unlikely (surface == NULL))
160 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
161 
162     _cairo_surface_init (&surface->base,
163 			 &_cairo_image_surface_backend,
164 			 NULL, /* device */
165 			 _cairo_content_from_pixman_format (pixman_format));
166 
167     surface->pixman_image = pixman_image;
168 
169     surface->pixman_format = pixman_format;
170     surface->format = _cairo_format_from_pixman_format (pixman_format);
171     surface->data = (uint8_t *) pixman_image_get_data (pixman_image);
172     surface->owns_data = FALSE;
173     surface->transparency = CAIRO_IMAGE_UNKNOWN;
174 
175     surface->width = width;
176     surface->height = height;
177     surface->stride = pixman_image_get_stride (pixman_image);
178     surface->depth = pixman_image_get_depth (pixman_image);
179 
180     return &surface->base;
181 }
182 
183 cairo_bool_t
_pixman_format_from_masks(cairo_format_masks_t * masks,pixman_format_code_t * format_ret)184 _pixman_format_from_masks (cairo_format_masks_t *masks,
185 			   pixman_format_code_t *format_ret)
186 {
187     pixman_format_code_t format;
188     int format_type;
189     int a, r, g, b;
190     cairo_format_masks_t format_masks;
191 
192     a = _cairo_popcount (masks->alpha_mask);
193     r = _cairo_popcount (masks->red_mask);
194     g = _cairo_popcount (masks->green_mask);
195     b = _cairo_popcount (masks->blue_mask);
196 
197     if (masks->red_mask) {
198 	if (masks->red_mask > masks->blue_mask)
199 	    format_type = PIXMAN_TYPE_ARGB;
200 	else
201 	    format_type = PIXMAN_TYPE_ABGR;
202     } else if (masks->alpha_mask) {
203 	format_type = PIXMAN_TYPE_A;
204     } else {
205 	return FALSE;
206     }
207 
208     format = PIXMAN_FORMAT (masks->bpp, format_type, a, r, g, b);
209 
210     if (! pixman_format_supported_destination (format))
211 	return FALSE;
212 
213     /* Sanity check that we got out of PIXMAN_FORMAT exactly what we
214      * expected. This avoid any problems from something bizarre like
215      * alpha in the least-significant bits, or insane channel order,
216      * or whatever. */
217      if (!_pixman_format_to_masks (format, &format_masks) ||
218          masks->bpp        != format_masks.bpp            ||
219 	 masks->red_mask   != format_masks.red_mask       ||
220 	 masks->green_mask != format_masks.green_mask     ||
221 	 masks->blue_mask  != format_masks.blue_mask)
222      {
223 	 return FALSE;
224      }
225 
226     *format_ret = format;
227     return TRUE;
228 }
229 
230 /* A mask consisting of N bits set to 1. */
231 #define MASK(N) ((1UL << (N))-1)
232 
233 cairo_bool_t
_pixman_format_to_masks(pixman_format_code_t format,cairo_format_masks_t * masks)234 _pixman_format_to_masks (pixman_format_code_t	 format,
235 			 cairo_format_masks_t	*masks)
236 {
237     int a, r, g, b;
238 
239     masks->bpp = PIXMAN_FORMAT_BPP (format);
240 
241     /* Number of bits in each channel */
242     a = PIXMAN_FORMAT_A (format);
243     r = PIXMAN_FORMAT_R (format);
244     g = PIXMAN_FORMAT_G (format);
245     b = PIXMAN_FORMAT_B (format);
246 
247     switch (PIXMAN_FORMAT_TYPE (format)) {
248     case PIXMAN_TYPE_ARGB:
249         masks->alpha_mask = MASK (a) << (r + g + b);
250         masks->red_mask   = MASK (r) << (g + b);
251         masks->green_mask = MASK (g) << (b);
252         masks->blue_mask  = MASK (b);
253         return TRUE;
254     case PIXMAN_TYPE_ABGR:
255         masks->alpha_mask = MASK (a) << (b + g + r);
256         masks->blue_mask  = MASK (b) << (g + r);
257         masks->green_mask = MASK (g) << (r);
258         masks->red_mask   = MASK (r);
259         return TRUE;
260 #ifdef PIXMAN_TYPE_BGRA
261     case PIXMAN_TYPE_BGRA:
262         masks->blue_mask  = MASK (b) << (masks->bpp - b);
263         masks->green_mask = MASK (g) << (masks->bpp - b - g);
264         masks->red_mask   = MASK (r) << (masks->bpp - b - g - r);
265         masks->alpha_mask = MASK (a);
266         return TRUE;
267 #endif
268     case PIXMAN_TYPE_A:
269         masks->alpha_mask = MASK (a);
270         masks->red_mask   = 0;
271         masks->green_mask = 0;
272         masks->blue_mask  = 0;
273         return TRUE;
274     case PIXMAN_TYPE_OTHER:
275     case PIXMAN_TYPE_COLOR:
276     case PIXMAN_TYPE_GRAY:
277     case PIXMAN_TYPE_YUY2:
278     case PIXMAN_TYPE_YV12:
279     default:
280         masks->alpha_mask = 0;
281         masks->red_mask   = 0;
282         masks->green_mask = 0;
283         masks->blue_mask  = 0;
284         return FALSE;
285     }
286 }
287 
288 pixman_format_code_t
_cairo_format_to_pixman_format_code(cairo_format_t format)289 _cairo_format_to_pixman_format_code (cairo_format_t format)
290 {
291     pixman_format_code_t ret;
292     switch (format) {
293     case CAIRO_FORMAT_A1:
294 	ret = PIXMAN_a1;
295 	break;
296     case CAIRO_FORMAT_A8:
297 	ret = PIXMAN_a8;
298 	break;
299     case CAIRO_FORMAT_RGB24:
300 	ret = PIXMAN_x8r8g8b8;
301 	break;
302     case CAIRO_FORMAT_RGB16_565:
303 	ret = PIXMAN_r5g6b5;
304 	break;
305     case CAIRO_FORMAT_ARGB32:
306     case CAIRO_FORMAT_INVALID:
307     default:
308 	ret = PIXMAN_a8r8g8b8;
309 	break;
310     }
311     return ret;
312 }
313 
314 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)315 _cairo_image_surface_create_with_pixman_format (unsigned char		*data,
316 						pixman_format_code_t	 pixman_format,
317 						int			 width,
318 						int			 height,
319 						int			 stride)
320 {
321     cairo_surface_t *surface;
322     pixman_image_t *pixman_image;
323 
324     if (! _cairo_image_surface_is_size_valid (width, height))
325     {
326 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
327     }
328 
329     pixman_image = pixman_image_create_bits (pixman_format, width, height,
330 					     (uint32_t *) data, stride ? stride : 4);
331 
332     if (unlikely (pixman_image == NULL))
333 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
334 
335     surface = _cairo_image_surface_create_for_pixman_image (pixman_image,
336 							    pixman_format);
337     if (unlikely (surface->status)) {
338 	pixman_image_unref (pixman_image);
339 	return surface;
340     }
341 
342     /* we can not make any assumptions about the initial state of user data */
343     surface->is_clear = data == NULL;
344     return surface;
345 }
346 
347 /**
348  * cairo_image_surface_create:
349  * @format: format of pixels in the surface to create
350  * @width: width of the surface, in pixels
351  * @height: height of the surface, in pixels
352  *
353  * Creates an image surface of the specified format and
354  * dimensions. Initially the surface contents are all
355  * 0. (Specifically, within each pixel, each color or alpha channel
356  * belonging to format will be 0. The contents of bits within a pixel,
357  * but not belonging to the given format are undefined).
358  *
359  * Return value: a pointer to the newly created surface. The caller
360  * owns the surface and should call cairo_surface_destroy() when done
361  * with it.
362  *
363  * This function always returns a valid pointer, but it will return a
364  * pointer to a "nil" surface if an error such as out of memory
365  * occurs. You can use cairo_surface_status() to check for this.
366  **/
367 cairo_surface_t *
cairo_image_surface_create(cairo_format_t format,int width,int height)368 cairo_image_surface_create (cairo_format_t	format,
369 			    int			width,
370 			    int			height)
371 {
372     pixman_format_code_t pixman_format;
373 
374     if (! CAIRO_FORMAT_VALID (format))
375 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
376 
377     pixman_format = _cairo_format_to_pixman_format_code (format);
378 
379     return _cairo_image_surface_create_with_pixman_format (NULL, pixman_format,
380 							   width, height, -1);
381 }
382 slim_hidden_def (cairo_image_surface_create);
383 
384 cairo_surface_t *
_cairo_image_surface_create_with_content(cairo_content_t content,int width,int height)385 _cairo_image_surface_create_with_content (cairo_content_t	content,
386 					  int			width,
387 					  int			height)
388 {
389     return cairo_image_surface_create (_cairo_format_from_content (content),
390 				       width, height);
391 }
392 
393 /**
394  * cairo_format_stride_for_width:
395  * @format: A #cairo_format_t value
396  * @width: The desired width of an image surface to be created.
397  *
398  * This function provides a stride value that will respect all
399  * alignment requirements of the accelerated image-rendering code
400  * within cairo. Typical usage will be of the form:
401  *
402  * <informalexample><programlisting>
403  * int stride;
404  * unsigned char *data;
405  * #cairo_surface_t *surface;
406  *
407  * stride = cairo_format_stride_for_width (format, width);
408  * data = malloc (stride * height);
409  * surface = cairo_image_surface_create_for_data (data, format,
410  *						  width, height,
411  *						  stride);
412  * </programlisting></informalexample>
413  *
414  * Return value: the appropriate stride to use given the desired
415  * format and width, or -1 if either the format is invalid or the width
416  * too large.
417  *
418  * Since: 1.6
419  **/
420 int
cairo_format_stride_for_width(cairo_format_t format,int width)421 cairo_format_stride_for_width (cairo_format_t	format,
422 			       int		width)
423 {
424     int bpp;
425 
426     if (! CAIRO_FORMAT_VALID (format)) {
427 	_cairo_error_throw (CAIRO_STATUS_INVALID_FORMAT);
428 	return -1;
429     }
430 
431     bpp = _cairo_format_bits_per_pixel (format);
432     if ((unsigned) (width) >= (INT32_MAX - 7) / (unsigned) (bpp))
433 	return -1;
434 
435     return CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp);
436 }
437 slim_hidden_def (cairo_format_stride_for_width);
438 
439 /**
440  * cairo_image_surface_create_for_data:
441  * @data: a pointer to a buffer supplied by the application in which
442  *     to write contents. This pointer must be suitably aligned for any
443  *     kind of variable, (for example, a pointer returned by malloc).
444  * @format: the format of pixels in the buffer
445  * @width: the width of the image to be stored in the buffer
446  * @height: the height of the image to be stored in the buffer
447  * @stride: the number of bytes between the start of rows in the
448  *     buffer as allocated. This value should always be computed by
449  *     cairo_format_stride_for_width() before allocating the data
450  *     buffer.
451  *
452  * Creates an image surface for the provided pixel data. The output
453  * buffer must be kept around until the #cairo_surface_t is destroyed
454  * or cairo_surface_finish() is called on the surface.  The initial
455  * contents of @data will be used as the initial image contents; you
456  * must explicitly clear the buffer, using, for example,
457  * cairo_rectangle() and cairo_fill() if you want it cleared.
458  *
459  * Note that the stride may be larger than
460  * width*bytes_per_pixel to provide proper alignment for each pixel
461  * and row. This alignment is required to allow high-performance rendering
462  * within cairo. The correct way to obtain a legal stride value is to
463  * call cairo_format_stride_for_width() with the desired format and
464  * maximum image width value, and then use the resulting stride value
465  * to allocate the data and to create the image surface. See
466  * cairo_format_stride_for_width() for example code.
467  *
468  * Return value: a pointer to the newly created surface. The caller
469  * owns the surface and should call cairo_surface_destroy() when done
470  * with it.
471  *
472  * This function always returns a valid pointer, but it will return a
473  * pointer to a "nil" surface in the case of an error such as out of
474  * memory or an invalid stride value. In case of invalid stride value
475  * the error status of the returned surface will be
476  * %CAIRO_STATUS_INVALID_STRIDE.  You can use
477  * cairo_surface_status() to check for this.
478  *
479  * See cairo_surface_set_user_data() for a means of attaching a
480  * destroy-notification fallback to the surface if necessary.
481  **/
482 cairo_surface_t *
cairo_image_surface_create_for_data(unsigned char * data,cairo_format_t format,int width,int height,int stride)483 cairo_image_surface_create_for_data (unsigned char     *data,
484 				     cairo_format_t	format,
485 				     int		width,
486 				     int		height,
487 				     int		stride)
488 {
489     pixman_format_code_t pixman_format;
490     int minstride;
491 
492     if (! CAIRO_FORMAT_VALID (format))
493 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
494 
495     if ((stride & (CAIRO_STRIDE_ALIGNMENT-1)) != 0)
496 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
497 
498     if (! _cairo_image_surface_is_size_valid (width, height))
499 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
500 
501     minstride = cairo_format_stride_for_width (format, width);
502     if (stride < 0) {
503 	if (stride > -minstride) {
504 	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
505 	}
506     } else {
507 	if (stride < minstride) {
508 	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_STRIDE));
509 	}
510     }
511 
512     pixman_format = _cairo_format_to_pixman_format_code (format);
513     return _cairo_image_surface_create_with_pixman_format (data,
514 							   pixman_format,
515 							   width, height,
516 							   stride);
517 }
518 slim_hidden_def (cairo_image_surface_create_for_data);
519 
520 /**
521  * cairo_image_surface_get_data:
522  * @surface: a #cairo_image_surface_t
523  *
524  * Get a pointer to the data of the image surface, for direct
525  * inspection or modification.
526  *
527  * Return value: a pointer to the image data of this surface or %NULL
528  * if @surface is not an image surface, or if cairo_surface_finish()
529  * has been called.
530  *
531  * Since: 1.2
532  **/
533 unsigned char *
cairo_image_surface_get_data(cairo_surface_t * surface)534 cairo_image_surface_get_data (cairo_surface_t *surface)
535 {
536     cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
537 
538     if (! _cairo_surface_is_image (surface)) {
539 	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
540 	return NULL;
541     }
542 
543     return image_surface->data;
544 }
545 slim_hidden_def (cairo_image_surface_get_data);
546 
547 /**
548  * cairo_image_surface_get_format:
549  * @surface: a #cairo_image_surface_t
550  *
551  * Get the format of the surface.
552  *
553  * Return value: the format of the surface
554  *
555  * Since: 1.2
556  **/
557 cairo_format_t
cairo_image_surface_get_format(cairo_surface_t * surface)558 cairo_image_surface_get_format (cairo_surface_t *surface)
559 {
560     cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
561 
562     if (! _cairo_surface_is_image (surface)) {
563 	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
564 	return CAIRO_FORMAT_INVALID;
565     }
566 
567     return image_surface->format;
568 }
569 slim_hidden_def (cairo_image_surface_get_format);
570 
571 /**
572  * cairo_image_surface_get_width:
573  * @surface: a #cairo_image_surface_t
574  *
575  * Get the width of the image surface in pixels.
576  *
577  * Return value: the width of the surface in pixels.
578  **/
579 int
cairo_image_surface_get_width(cairo_surface_t * surface)580 cairo_image_surface_get_width (cairo_surface_t *surface)
581 {
582     cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
583 
584     if (! _cairo_surface_is_image (surface)) {
585 	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
586 	return 0;
587     }
588 
589     return image_surface->width;
590 }
591 slim_hidden_def (cairo_image_surface_get_width);
592 
593 /**
594  * cairo_image_surface_get_height:
595  * @surface: a #cairo_image_surface_t
596  *
597  * Get the height of the image surface in pixels.
598  *
599  * Return value: the height of the surface in pixels.
600  **/
601 int
cairo_image_surface_get_height(cairo_surface_t * surface)602 cairo_image_surface_get_height (cairo_surface_t *surface)
603 {
604     cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
605 
606     if (! _cairo_surface_is_image (surface)) {
607 	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
608 	return 0;
609     }
610 
611     return image_surface->height;
612 }
613 slim_hidden_def (cairo_image_surface_get_height);
614 
615 /**
616  * cairo_image_surface_get_stride:
617  * @surface: a #cairo_image_surface_t
618  *
619  * Get the stride of the image surface in bytes
620  *
621  * Return value: the stride of the image surface in bytes (or 0 if
622  * @surface is not an image surface). The stride is the distance in
623  * bytes from the beginning of one row of the image data to the
624  * beginning of the next row.
625  *
626  * Since: 1.2
627  **/
628 int
cairo_image_surface_get_stride(cairo_surface_t * surface)629 cairo_image_surface_get_stride (cairo_surface_t *surface)
630 {
631 
632     cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
633 
634     if (! _cairo_surface_is_image (surface)) {
635 	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
636 	return 0;
637     }
638 
639     return image_surface->stride;
640 }
641 slim_hidden_def (cairo_image_surface_get_stride);
642 
643 cairo_format_t
_cairo_format_from_content(cairo_content_t content)644 _cairo_format_from_content (cairo_content_t content)
645 {
646     switch (content) {
647     case CAIRO_CONTENT_COLOR:
648 	return CAIRO_FORMAT_RGB24;
649     case CAIRO_CONTENT_ALPHA:
650 	return CAIRO_FORMAT_A8;
651     case CAIRO_CONTENT_COLOR_ALPHA:
652 	return CAIRO_FORMAT_ARGB32;
653     }
654 
655     ASSERT_NOT_REACHED;
656     return CAIRO_FORMAT_INVALID;
657 }
658 
659 cairo_content_t
_cairo_content_from_format(cairo_format_t format)660 _cairo_content_from_format (cairo_format_t format)
661 {
662     switch (format) {
663     case CAIRO_FORMAT_ARGB32:
664 	return CAIRO_CONTENT_COLOR_ALPHA;
665     case CAIRO_FORMAT_RGB24:
666 	return CAIRO_CONTENT_COLOR;
667     case CAIRO_FORMAT_RGB16_565:
668 	return CAIRO_CONTENT_COLOR;
669     case CAIRO_FORMAT_A8:
670     case CAIRO_FORMAT_A1:
671 	return CAIRO_CONTENT_ALPHA;
672     case CAIRO_FORMAT_INVALID:
673 	break;
674     }
675 
676     ASSERT_NOT_REACHED;
677     return CAIRO_CONTENT_COLOR_ALPHA;
678 }
679 
680 int
_cairo_format_bits_per_pixel(cairo_format_t format)681 _cairo_format_bits_per_pixel (cairo_format_t format)
682 {
683     switch (format) {
684     case CAIRO_FORMAT_ARGB32:
685 	return 32;
686     case CAIRO_FORMAT_RGB24:
687 	return 32;
688     case CAIRO_FORMAT_RGB16_565:
689 	return 16;
690     case CAIRO_FORMAT_A8:
691 	return 8;
692     case CAIRO_FORMAT_A1:
693 	return 1;
694     case CAIRO_FORMAT_INVALID:
695     default:
696 	ASSERT_NOT_REACHED;
697 	return 0;
698     }
699 }
700 
701 static cairo_surface_t *
_cairo_image_surface_create_similar(void * abstract_other,cairo_content_t content,int width,int height)702 _cairo_image_surface_create_similar (void	       *abstract_other,
703 				     cairo_content_t	content,
704 				     int		width,
705 				     int		height)
706 {
707     cairo_image_surface_t *other = abstract_other;
708 
709     if (! _cairo_image_surface_is_size_valid (width, height))
710 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
711 
712     if (content == other->base.content) {
713 	return _cairo_image_surface_create_with_pixman_format (NULL,
714 							       other->pixman_format,
715 							       width, height,
716 							       0);
717     }
718 
719     return _cairo_image_surface_create_with_content (content,
720 						     width, height);
721 }
722 
723 static cairo_status_t
_cairo_image_surface_finish(void * abstract_surface)724 _cairo_image_surface_finish (void *abstract_surface)
725 {
726     cairo_image_surface_t *surface = abstract_surface;
727 
728     if (surface->pixman_image) {
729 	pixman_image_unref (surface->pixman_image);
730 	surface->pixman_image = NULL;
731     }
732 
733     if (surface->owns_data) {
734 	free (surface->data);
735 	surface->data = NULL;
736     }
737 
738     return CAIRO_STATUS_SUCCESS;
739 }
740 
741 void
_cairo_image_surface_assume_ownership_of_data(cairo_image_surface_t * surface)742 _cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface)
743 {
744     surface->owns_data = TRUE;
745 }
746 
747 static cairo_status_t
_cairo_image_surface_acquire_source_image(void * abstract_surface,cairo_image_surface_t ** image_out,void ** image_extra)748 _cairo_image_surface_acquire_source_image (void                    *abstract_surface,
749 					   cairo_image_surface_t  **image_out,
750 					   void                   **image_extra)
751 {
752     *image_out = abstract_surface;
753     *image_extra = NULL;
754 
755     return CAIRO_STATUS_SUCCESS;
756 }
757 
758 static void
_cairo_image_surface_release_source_image(void * abstract_surface,cairo_image_surface_t * image,void * image_extra)759 _cairo_image_surface_release_source_image (void                   *abstract_surface,
760 					   cairo_image_surface_t  *image,
761 					   void                   *image_extra)
762 {
763 }
764 
765 /* XXX: I think we should fix pixman to match the names/order of the
766  * cairo operators, but that will likely be better done at the same
767  * time the X server is ported to pixman, (which will change a lot of
768  * things in pixman I think).
769  */
770 static pixman_op_t
_pixman_operator(cairo_operator_t op)771 _pixman_operator (cairo_operator_t op)
772 {
773     switch (op) {
774     case CAIRO_OPERATOR_CLEAR:
775 	return PIXMAN_OP_CLEAR;
776 
777     case CAIRO_OPERATOR_SOURCE:
778 	return PIXMAN_OP_SRC;
779     case CAIRO_OPERATOR_OVER:
780 	return PIXMAN_OP_OVER;
781     case CAIRO_OPERATOR_IN:
782 	return PIXMAN_OP_IN;
783     case CAIRO_OPERATOR_OUT:
784 	return PIXMAN_OP_OUT;
785     case CAIRO_OPERATOR_ATOP:
786 	return PIXMAN_OP_ATOP;
787 
788     case CAIRO_OPERATOR_DEST:
789 	return PIXMAN_OP_DST;
790     case CAIRO_OPERATOR_DEST_OVER:
791 	return PIXMAN_OP_OVER_REVERSE;
792     case CAIRO_OPERATOR_DEST_IN:
793 	return PIXMAN_OP_IN_REVERSE;
794     case CAIRO_OPERATOR_DEST_OUT:
795 	return PIXMAN_OP_OUT_REVERSE;
796     case CAIRO_OPERATOR_DEST_ATOP:
797 	return PIXMAN_OP_ATOP_REVERSE;
798 
799     case CAIRO_OPERATOR_XOR:
800 	return PIXMAN_OP_XOR;
801     case CAIRO_OPERATOR_ADD:
802 	return PIXMAN_OP_ADD;
803     case CAIRO_OPERATOR_SATURATE:
804 	return PIXMAN_OP_SATURATE;
805 
806     case CAIRO_OPERATOR_MULTIPLY:
807 	return PIXMAN_OP_MULTIPLY;
808     case CAIRO_OPERATOR_SCREEN:
809 	return PIXMAN_OP_SCREEN;
810     case CAIRO_OPERATOR_OVERLAY:
811 	return PIXMAN_OP_OVERLAY;
812     case CAIRO_OPERATOR_DARKEN:
813 	return PIXMAN_OP_DARKEN;
814     case CAIRO_OPERATOR_LIGHTEN:
815 	return PIXMAN_OP_LIGHTEN;
816     case CAIRO_OPERATOR_COLOR_DODGE:
817 	return PIXMAN_OP_COLOR_DODGE;
818     case CAIRO_OPERATOR_COLOR_BURN:
819 	return PIXMAN_OP_COLOR_BURN;
820     case CAIRO_OPERATOR_HARD_LIGHT:
821 	return PIXMAN_OP_HARD_LIGHT;
822     case CAIRO_OPERATOR_SOFT_LIGHT:
823 	return PIXMAN_OP_SOFT_LIGHT;
824     case CAIRO_OPERATOR_DIFFERENCE:
825 	return PIXMAN_OP_DIFFERENCE;
826     case CAIRO_OPERATOR_EXCLUSION:
827 	return PIXMAN_OP_EXCLUSION;
828     case CAIRO_OPERATOR_HSL_HUE:
829 	return PIXMAN_OP_HSL_HUE;
830     case CAIRO_OPERATOR_HSL_SATURATION:
831 	return PIXMAN_OP_HSL_SATURATION;
832     case CAIRO_OPERATOR_HSL_COLOR:
833 	return PIXMAN_OP_HSL_COLOR;
834     case CAIRO_OPERATOR_HSL_LUMINOSITY:
835 	return PIXMAN_OP_HSL_LUMINOSITY;
836 
837     default:
838 	ASSERT_NOT_REACHED;
839 	return PIXMAN_OP_OVER;
840     }
841 }
842 
843 static cairo_status_t
_cairo_image_surface_set_clip_region(cairo_image_surface_t * surface,cairo_region_t * region)844 _cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
845 				      cairo_region_t *region)
846 {
847     if (! pixman_image_set_clip_region32 (surface->pixman_image, &region->rgn))
848 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
849 
850     return CAIRO_STATUS_SUCCESS;
851 }
852 
853 static void
_cairo_image_surface_unset_clip_region(cairo_image_surface_t * surface)854 _cairo_image_surface_unset_clip_region (cairo_image_surface_t *surface)
855 {
856     pixman_image_set_clip_region32 (surface->pixman_image, NULL);
857 }
858 
859 static double
_pixman_nearest_sample(double d)860 _pixman_nearest_sample (double d)
861 {
862     return ceil (d - .5);
863 }
864 
865 static cairo_bool_t
_nearest_sample(cairo_filter_t filter,double * tx,double * ty)866 _nearest_sample (cairo_filter_t filter, double *tx, double *ty)
867 {
868     if (filter == CAIRO_FILTER_FAST || filter == CAIRO_FILTER_NEAREST) {
869 	*tx = _pixman_nearest_sample (*tx);
870 	*ty = _pixman_nearest_sample (*ty);
871     } else {
872 	if (*tx != floor (*tx) || *ty != floor (*ty))
873 	    return FALSE;
874     }
875     return fabs (*tx) < PIXMAN_MAX_INT && fabs (*ty) < PIXMAN_MAX_INT;
876 }
877 
878 #if PIXMAN_HAS_ATOMIC_OPS
879 static pixman_image_t *__pixman_transparent_image;
880 static pixman_image_t *__pixman_black_image;
881 static pixman_image_t *__pixman_white_image;
882 
883 static pixman_image_t *
_pixman_transparent_image(void)884 _pixman_transparent_image (void)
885 {
886     pixman_image_t *image;
887 
888     image = __pixman_transparent_image;
889     if (unlikely (image == NULL)) {
890 	pixman_color_t color;
891 
892 	color.red   = 0x00;
893 	color.green = 0x00;
894 	color.blue  = 0x00;
895 	color.alpha = 0x00;
896 
897 	image = pixman_image_create_solid_fill (&color);
898 	if (unlikely (image == NULL))
899 	    return NULL;
900 
901 	if (_cairo_atomic_ptr_cmpxchg (&__pixman_transparent_image,
902 				       NULL, image))
903 	{
904 	    pixman_image_ref (image);
905 	}
906     } else {
907 	pixman_image_ref (image);
908     }
909 
910     return image;
911 }
912 
913 static pixman_image_t *
_pixman_black_image(void)914 _pixman_black_image (void)
915 {
916     pixman_image_t *image;
917 
918     image = __pixman_black_image;
919     if (unlikely (image == NULL)) {
920 	pixman_color_t color;
921 
922 	color.red   = 0x00;
923 	color.green = 0x00;
924 	color.blue  = 0x00;
925 	color.alpha = 0xffff;
926 
927 	image = pixman_image_create_solid_fill (&color);
928 	if (unlikely (image == NULL))
929 	    return NULL;
930 
931 	if (_cairo_atomic_ptr_cmpxchg (&__pixman_black_image,
932 				       NULL, image))
933 	{
934 	    pixman_image_ref (image);
935 	}
936     } else {
937 	pixman_image_ref (image);
938     }
939 
940     return image;
941 }
942 
943 static pixman_image_t *
_pixman_white_image(void)944 _pixman_white_image (void)
945 {
946     pixman_image_t *image;
947 
948     image = __pixman_white_image;
949     if (unlikely (image == NULL)) {
950 	pixman_color_t color;
951 
952 	color.red   = 0xffff;
953 	color.green = 0xffff;
954 	color.blue  = 0xffff;
955 	color.alpha = 0xffff;
956 
957 	image = pixman_image_create_solid_fill (&color);
958 	if (unlikely (image == NULL))
959 	    return NULL;
960 
961 	if (_cairo_atomic_ptr_cmpxchg (&__pixman_white_image,
962 				       NULL, image))
963 	{
964 	    pixman_image_ref (image);
965 	}
966     } else {
967 	pixman_image_ref (image);
968     }
969 
970     return image;
971 }
972 
973 static uint32_t
hars_petruska_f54_1_random(void)974 hars_petruska_f54_1_random (void)
975 {
976 #define rol(x,k) ((x << k) | (x >> (32-k)))
977     static uint32_t x;
978     return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
979 #undef rol
980 }
981 
982 static struct {
983     cairo_color_t color;
984     pixman_image_t *image;
985 } cache[16];
986 static int n_cached;
987 
988 #else  /* !PIXMAN_HAS_ATOMIC_OPS */
989 static pixman_image_t *
_pixman_transparent_image(void)990 _pixman_transparent_image (void)
991 {
992     return _pixman_image_for_solid (&_cairo_pattern_clear);
993 }
994 
995 static pixman_image_t *
_pixman_black_image(void)996 _pixman_black_image (void)
997 {
998     return _pixman_image_for_solid (&_cairo_pattern_black);
999 }
1000 
1001 static pixman_image_t *
_pixman_white_image(void)1002 _pixman_white_image (void)
1003 {
1004     return _pixman_image_for_solid (&_cairo_pattern_white);
1005 }
1006 #endif /* !PIXMAN_HAS_ATOMIC_OPS */
1007 
1008 void
_cairo_image_reset_static_data(void)1009 _cairo_image_reset_static_data (void)
1010 {
1011 #if PIXMAN_HAS_ATOMIC_OPS
1012     while (n_cached)
1013 	pixman_image_unref (cache[--n_cached].image);
1014 
1015     if (__pixman_transparent_image) {
1016 	pixman_image_unref (__pixman_transparent_image);
1017 	__pixman_transparent_image = NULL;
1018     }
1019 
1020     if (__pixman_black_image) {
1021 	pixman_image_unref (__pixman_black_image);
1022 	__pixman_black_image = NULL;
1023     }
1024 
1025     if (__pixman_white_image) {
1026 	pixman_image_unref (__pixman_white_image);
1027 	__pixman_white_image = NULL;
1028     }
1029 #endif
1030 }
1031 
1032 static pixman_image_t *
_pixman_image_for_solid(const cairo_solid_pattern_t * pattern)1033 _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
1034 {
1035     pixman_color_t color;
1036     pixman_image_t *image;
1037 
1038 #if PIXMAN_HAS_ATOMIC_OPS
1039     int i;
1040 
1041     if (pattern->color.alpha_short <= 0x00ff)
1042 	return _pixman_transparent_image ();
1043 
1044     if (pattern->color.alpha_short >= 0xff00) {
1045 	if (pattern->color.red_short <= 0x00ff &&
1046 	    pattern->color.green_short <= 0x00ff &&
1047 	    pattern->color.blue_short <= 0x00ff)
1048 	{
1049 	    return _pixman_black_image ();
1050 	}
1051 
1052 	if (pattern->color.red_short >= 0xff00 &&
1053 	    pattern->color.green_short >= 0xff00 &&
1054 	    pattern->color.blue_short >= 0xff00)
1055 	{
1056 	    return _pixman_white_image ();
1057 	}
1058     }
1059 
1060     CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex);
1061     for (i = 0; i < n_cached; i++) {
1062 	if (_cairo_color_equal (&cache[i].color, &pattern->color)) {
1063 	    image = pixman_image_ref (cache[i].image);
1064 	    goto UNLOCK;
1065 	}
1066     }
1067 #endif
1068 
1069     color.red   = pattern->color.red_short;
1070     color.green = pattern->color.green_short;
1071     color.blue  = pattern->color.blue_short;
1072     color.alpha = pattern->color.alpha_short;
1073 
1074     image = pixman_image_create_solid_fill (&color);
1075 #if PIXMAN_HAS_ATOMIC_OPS
1076     if (image == NULL)
1077 	goto UNLOCK;
1078 
1079     if (n_cached < ARRAY_LENGTH (cache)) {
1080 	i = n_cached++;
1081     } else {
1082 	i = hars_petruska_f54_1_random () % ARRAY_LENGTH (cache);
1083 	pixman_image_unref (cache[i].image);
1084     }
1085     cache[i].image = pixman_image_ref (image);
1086     cache[i].color = pattern->color;
1087 
1088 UNLOCK:
1089     CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
1090 #endif
1091     return image;
1092 }
1093 
1094 static double
clamp(double val,double min,double max)1095 clamp (double val, double min, double max)
1096 {
1097     return val < min ? min : (val > max ? max : val);
1098 }
1099 
1100 static pixman_image_t *
_pixman_image_for_gradient(const cairo_gradient_pattern_t * pattern,const cairo_rectangle_int_t * extents,int * ix,int * iy)1101 _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
1102 			    const cairo_rectangle_int_t *extents,
1103 			    int *ix, int *iy)
1104 {
1105     pixman_image_t	  *pixman_image;
1106     pixman_gradient_stop_t pixman_stops_static[2];
1107     pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
1108     cairo_matrix_t matrix = pattern->base.matrix;
1109     double tx, ty;
1110     unsigned int i;
1111 
1112     if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
1113 	pixman_stops = _cairo_malloc_ab (pattern->n_stops,
1114 					 sizeof(pixman_gradient_stop_t));
1115 	if (unlikely (pixman_stops == NULL))
1116 	    return NULL;
1117     }
1118 
1119     for (i = 0; i < pattern->n_stops; i++) {
1120 	pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
1121 	pixman_stops[i].color.red   = pattern->stops[i].color.red_short;
1122 	pixman_stops[i].color.green = pattern->stops[i].color.green_short;
1123 	pixman_stops[i].color.blue  = pattern->stops[i].color.blue_short;
1124 	pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
1125     }
1126 
1127     if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
1128 	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
1129 	pixman_point_fixed_t p1, p2;
1130 	double x0, y0, x1, y1, maxabs;
1131 
1132 	/*
1133 	 * Transform the matrix to avoid overflow when converting between
1134 	 * cairo_fixed_t and pixman_fixed_t (without incurring performance
1135 	 * loss when the transformation is unnecessary).
1136 	 *
1137 	 * Having a function to compute the required transformation to
1138 	 * "normalize" a given bounding box would be generally useful -
1139 	 * cf linear patterns, gradient patterns, surface patterns...
1140 	 */
1141 	x0 = _cairo_fixed_to_double (linear->p1.x);
1142 	y0 = _cairo_fixed_to_double (linear->p1.y);
1143 	x1 = _cairo_fixed_to_double (linear->p2.x);
1144 	y1 = _cairo_fixed_to_double (linear->p2.y);
1145 	cairo_matrix_transform_point (&matrix, &x0, &y0);
1146 	cairo_matrix_transform_point (&matrix, &x1, &y1);
1147 	maxabs = MAX (MAX (fabs (x0), fabs (x1)), MAX (fabs (y0), fabs (y1)));
1148 
1149 	if (maxabs > PIXMAN_MAX_INT)
1150 	{
1151 	    double sf;
1152 	    cairo_matrix_t scale;
1153 
1154 	    sf = PIXMAN_MAX_INT / maxabs;
1155 
1156 	    p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
1157 	    p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
1158 	    p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
1159 	    p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
1160 
1161 	    /* cairo_matrix_scale does a pre-scale, we want a post-scale */
1162 	    cairo_matrix_init_scale (&scale, sf, sf);
1163 	    cairo_matrix_multiply (&matrix, &matrix, &scale);
1164 	}
1165 	else
1166 	{
1167 	    p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
1168 	    p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
1169 	    p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
1170 	    p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
1171 	}
1172 
1173 	pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
1174 							    pixman_stops,
1175 							    pattern->n_stops);
1176     } else {
1177 	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
1178 	pixman_point_fixed_t c1, c2;
1179 	pixman_fixed_t r1, r2;
1180 
1181 	c1.x = _cairo_fixed_to_16_16 (radial->c1.x);
1182 	c1.y = _cairo_fixed_to_16_16 (radial->c1.y);
1183 	r1   = _cairo_fixed_to_16_16 (radial->r1);
1184 
1185 	c2.x = _cairo_fixed_to_16_16 (radial->c2.x);
1186 	c2.y = _cairo_fixed_to_16_16 (radial->c2.y);
1187 	r2   = _cairo_fixed_to_16_16 (radial->r2);
1188 
1189 	pixman_image = pixman_image_create_radial_gradient (&c1, &c2, r1, r2,
1190 							    pixman_stops,
1191 							    pattern->n_stops);
1192     }
1193 
1194     if (pixman_stops != pixman_stops_static)
1195 	free (pixman_stops);
1196 
1197     if (unlikely (pixman_image == NULL))
1198 	return NULL;
1199 
1200     tx = matrix.x0;
1201     ty = matrix.y0;
1202     if (! _cairo_matrix_is_translation (&matrix) ||
1203 	! _nearest_sample (pattern->base.filter, &tx, &ty))
1204     {
1205 	pixman_transform_t pixman_transform;
1206 
1207 	if (tx != 0. || ty != 0.) {
1208 	    cairo_matrix_t m, inv;
1209 	    cairo_status_t status;
1210 	    double x, y, max_x, max_y;
1211 
1212 	    /* Pixman also limits the [xy]_offset to 16 bits. We try to evenly
1213 	     * spread the bits between the two, but we need to ensure that
1214 	     * fabs (tx + extents->x + extents->width) < PIXMAN_MAX_INT &&
1215 	     * fabs (ty + extents->y + extents->height) < PIXMAN_MAX_INT,
1216 	     * otherwise the gradient won't render.
1217 	     */
1218 	    inv = matrix;
1219 	    status = cairo_matrix_invert (&inv);
1220 	    assert (status == CAIRO_STATUS_SUCCESS);
1221 
1222 	    x = _cairo_lround (inv.x0 / 2);
1223 	    y = _cairo_lround (inv.y0 / 2);
1224 
1225 	    max_x = PIXMAN_MAX_INT - 1 - fabs (extents->x + extents->width);
1226 	    x = clamp(x, -max_x, max_x);
1227 	    max_y = PIXMAN_MAX_INT - 1 - fabs (extents->y + extents->height);
1228 	    y = clamp(y, -max_y, max_y);
1229 
1230 	    tx = -x;
1231 	    ty = -y;
1232 	    cairo_matrix_init_translate (&inv, x, y);
1233 	    cairo_matrix_multiply (&m, &inv, &matrix);
1234 	    _cairo_matrix_to_pixman_matrix (&m, &pixman_transform,
1235 					    extents->x + extents->width/2.,
1236 					    extents->y + extents->height/2.);
1237 	} else {
1238 	    tx = ty = 0;
1239 	    _cairo_matrix_to_pixman_matrix (&pattern->base.matrix,
1240 					    &pixman_transform,
1241 					    extents->x + extents->width/2.,
1242 					    extents->y + extents->height/2.);
1243 	}
1244 
1245 	if (! pixman_image_set_transform (pixman_image, &pixman_transform)) {
1246 	    pixman_image_unref (pixman_image);
1247 	    return NULL;
1248 	}
1249     }
1250     *ix = tx;
1251     *iy = ty;
1252 
1253     {
1254 	pixman_repeat_t pixman_repeat;
1255 
1256 	switch (pattern->base.extend) {
1257 	default:
1258 	case CAIRO_EXTEND_NONE:
1259 	    pixman_repeat = PIXMAN_REPEAT_NONE;
1260 	    break;
1261 	case CAIRO_EXTEND_REPEAT:
1262 	    pixman_repeat = PIXMAN_REPEAT_NORMAL;
1263 	    break;
1264 	case CAIRO_EXTEND_REFLECT:
1265 	    pixman_repeat = PIXMAN_REPEAT_REFLECT;
1266 	    break;
1267 	case CAIRO_EXTEND_PAD:
1268 	    pixman_repeat = PIXMAN_REPEAT_PAD;
1269 	    break;
1270 	}
1271 
1272 	pixman_image_set_repeat (pixman_image, pixman_repeat);
1273     }
1274 
1275     return pixman_image;
1276 }
1277 
1278 struct acquire_source_cleanup {
1279     cairo_surface_t *surface;
1280     cairo_image_surface_t *image;
1281     void *image_extra;
1282 };
1283 
1284 static void
_acquire_source_cleanup(pixman_image_t * pixman_image,void * closure)1285 _acquire_source_cleanup (pixman_image_t *pixman_image,
1286 			 void *closure)
1287 {
1288     struct acquire_source_cleanup *data = closure;
1289 
1290     _cairo_surface_release_source_image (data->surface,
1291 					 data->image,
1292 					 data->image_extra);
1293     free (data);
1294 }
1295 
1296 static cairo_filter_t
sampled_area(const cairo_surface_pattern_t * pattern,const cairo_rectangle_int_t * extents,cairo_rectangle_int_t * sample)1297 sampled_area (const cairo_surface_pattern_t *pattern,
1298 	      const cairo_rectangle_int_t *extents,
1299 	      cairo_rectangle_int_t *sample)
1300 {
1301     cairo_filter_t filter;
1302     double x1, x2, y1, y2;
1303     double pad;
1304 
1305     x1 = extents->x;
1306     y1 = extents->y;
1307     x2 = extents->x + (int) extents->width;
1308     y2 = extents->y + (int) extents->height;
1309 
1310     _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
1311                                           &x1, &y1, &x2, &y2,
1312                                           NULL);
1313 
1314     filter = _cairo_pattern_analyze_filter (&pattern->base, &pad);
1315     sample->x = floor (x1 - pad);
1316     sample->y = floor (y1 - pad);
1317     sample->width  = ceil (x2 + pad) - sample->x;
1318     sample->height = ceil (y2 + pad) - sample->y;
1319 
1320     return filter;
1321 }
1322 
1323 static uint16_t
expand_channel(uint16_t v,uint32_t bits)1324 expand_channel (uint16_t v, uint32_t bits)
1325 {
1326     int offset = 16 - bits;
1327     while (offset > 0) {
1328 	v |= v >> bits;
1329 	offset -= bits;
1330 	bits += bits;
1331     }
1332     return v;
1333 }
1334 
1335 static pixman_image_t *
_pixel_to_solid(cairo_image_surface_t * image,int x,int y)1336 _pixel_to_solid (cairo_image_surface_t *image, int x, int y)
1337 {
1338     uint32_t pixel;
1339     pixman_color_t color;
1340 
1341     switch (image->format) {
1342     default:
1343     case CAIRO_FORMAT_INVALID:
1344 	ASSERT_NOT_REACHED;
1345 	return NULL;
1346 
1347     case CAIRO_FORMAT_A1:
1348 	pixel = *(uint8_t *) (image->data + y * image->stride + x/8);
1349 	return pixel & (1 << (x&7)) ? _pixman_white_image () : _pixman_transparent_image ();
1350 
1351     case CAIRO_FORMAT_A8:
1352 	color.alpha = *(uint8_t *) (image->data + y * image->stride + x);
1353 	color.alpha |= color.alpha << 8;
1354 	if (color.alpha == 0)
1355 	    return _pixman_transparent_image ();
1356 
1357 	color.red = color.green = color.blue = 0;
1358 	return pixman_image_create_solid_fill (&color);
1359 
1360     case CAIRO_FORMAT_RGB16_565:
1361 	pixel = *(uint16_t *) (image->data + y * image->stride + 2 * x);
1362 	if (pixel == 0)
1363 	    return _pixman_black_image ();
1364 	if (pixel == 0xffff)
1365 	    return _pixman_white_image ();
1366 
1367 	color.alpha = 0xffff;
1368 	color.red = expand_channel ((pixel >> 11 & 0x1f) << 11, 5);
1369 	color.green = expand_channel ((pixel >> 5 & 0x3f) << 10, 6);
1370 	color.blue = expand_channel ((pixel & 0x1f) << 11, 5);
1371 	return pixman_image_create_solid_fill (&color);
1372 
1373     case CAIRO_FORMAT_ARGB32:
1374     case CAIRO_FORMAT_RGB24:
1375 	pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
1376 	color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
1377 	if (color.alpha == 0)
1378 	    return _pixman_transparent_image ();
1379 	if (pixel == 0xffffffff)
1380 	    return _pixman_white_image ();
1381 	if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
1382 	    return _pixman_black_image ();
1383 
1384 	color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
1385 	color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
1386 	color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
1387 	return pixman_image_create_solid_fill (&color);
1388     }
1389 }
1390 
1391 static pixman_image_t *
_pixman_image_for_surface(const cairo_surface_pattern_t * pattern,cairo_bool_t is_mask,const cairo_rectangle_int_t * extents,int * ix,int * iy)1392 _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
1393 			   cairo_bool_t is_mask,
1394 			   const cairo_rectangle_int_t *extents,
1395 			   int *ix, int *iy)
1396 {
1397     pixman_image_t *pixman_image;
1398     cairo_rectangle_int_t sample;
1399     cairo_extend_t extend;
1400     cairo_filter_t filter;
1401     double tx, ty;
1402 
1403     tx = pattern->base.matrix.x0;
1404     ty = pattern->base.matrix.y0;
1405 
1406     extend = pattern->base.extend;
1407     filter = sampled_area (pattern, extents, &sample);
1408 
1409     pixman_image = NULL;
1410     if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
1411 	(! is_mask || ! pattern->base.has_component_alpha ||
1412 	 (pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
1413     {
1414 	cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
1415 	cairo_surface_type_t type;
1416 
1417 	if (source->base.backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT)
1418 	    source = (cairo_image_surface_t *) ((cairo_surface_snapshot_t *) pattern->surface)->target;
1419 
1420 	type = source->base.backend->type;
1421 	if (type == CAIRO_SURFACE_TYPE_IMAGE) {
1422 	    if (sample.width == 1 && sample.height == 1) {
1423 		if (sample.x < 0 ||
1424 		    sample.y < 0 ||
1425 		    sample.x >= source->width ||
1426 		    sample.y >= source->height)
1427 		{
1428 		    if (extend == CAIRO_EXTEND_NONE)
1429 			return _pixman_transparent_image ();
1430 		}
1431 		else
1432 		{
1433 		    return _pixel_to_solid (source, sample.x, sample.y);
1434 		}
1435 	    }
1436 
1437 #if PIXMAN_HAS_ATOMIC_OPS
1438 	    /* avoid allocating a 'pattern' image if we can reuse the original */
1439 	    if (extend == CAIRO_EXTEND_NONE &&
1440 		_cairo_matrix_is_translation (&pattern->base.matrix) &&
1441 		_nearest_sample (filter, &tx, &ty))
1442 	    {
1443 		*ix = tx;
1444 		*iy = ty;
1445 		return pixman_image_ref (source->pixman_image);
1446 	    }
1447 #endif
1448 
1449 	    pixman_image = pixman_image_create_bits (source->pixman_format,
1450 						     source->width,
1451 						     source->height,
1452 						     (uint32_t *) source->data,
1453 						     source->stride);
1454 	    if (unlikely (pixman_image == NULL))
1455 		return NULL;
1456 	} else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1457 	    cairo_surface_subsurface_t *sub;
1458 	    cairo_bool_t is_contained = FALSE;
1459 
1460 	    sub = (cairo_surface_subsurface_t *) source;
1461 	    source = (cairo_image_surface_t *) sub->target;
1462 
1463 	    if (sample.x >= 0 &&
1464 		sample.y >= 0 &&
1465 		sample.x + sample.width  <= sub->extents.width &&
1466 		sample.y + sample.height <= sub->extents.height)
1467 	    {
1468 		is_contained = TRUE;
1469 	    }
1470 
1471 	    if (sample.width == 1 && sample.height == 1) {
1472 		if (is_contained) {
1473 		    return _pixel_to_solid (source,
1474 					    sub->extents.x + sample.x,
1475 					    sub->extents.y + sample.y);
1476 		} else {
1477 		    if (extend == CAIRO_EXTEND_NONE)
1478 			return _pixman_transparent_image ();
1479 		}
1480 	    }
1481 
1482 #if PIXMAN_HAS_ATOMIC_OPS
1483 	    if (is_contained &&
1484 		_cairo_matrix_is_translation (&pattern->base.matrix) &&
1485 		_nearest_sample (filter, &tx, &ty))
1486 	    {
1487 		*ix = tx + sub->extents.x;
1488 		*iy = ty + sub->extents.y;
1489 		return pixman_image_ref (source->pixman_image);
1490 	    }
1491 #endif
1492 
1493 	    /* Avoid sub-byte offsets, force a copy in that case. */
1494 	    if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
1495 		void *data = source->data
1496 		    + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8
1497 		    + sub->extents.y * source->stride;
1498 		pixman_image = pixman_image_create_bits (source->pixman_format,
1499 							 sub->extents.width,
1500 							 sub->extents.height,
1501 							 data,
1502 							 source->stride);
1503 		if (unlikely (pixman_image == NULL))
1504 		    return NULL;
1505 	    }
1506 	}
1507     }
1508 
1509     if (pixman_image == NULL) {
1510 	struct acquire_source_cleanup *cleanup;
1511 	cairo_image_surface_t *image;
1512 	void *extra;
1513 	cairo_status_t status;
1514 
1515 	status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra);
1516 	if (unlikely (status))
1517 	    return NULL;
1518 
1519 	if (sample.width == 1 && sample.height == 1) {
1520 	    if (sample.x < 0 ||
1521 		sample.y < 0 ||
1522 		sample.x >= image->width ||
1523 		sample.y >= image->height)
1524 	    {
1525 		if (extend == CAIRO_EXTEND_NONE) {
1526 		    pixman_image = _pixman_transparent_image ();
1527 		    _cairo_surface_release_source_image (pattern->surface, image, extra);
1528 		    return pixman_image;
1529 		}
1530 	    }
1531 	    else
1532 	    {
1533 		pixman_image = _pixel_to_solid (image, sample.x, sample.y);
1534 		_cairo_surface_release_source_image (pattern->surface, image, extra);
1535 		return pixman_image;
1536 	    }
1537 	}
1538 
1539 	pixman_image = pixman_image_create_bits (image->pixman_format,
1540 						 image->width,
1541 						 image->height,
1542 						 (uint32_t *) image->data,
1543 						 image->stride);
1544 	if (unlikely (pixman_image == NULL)) {
1545 	    _cairo_surface_release_source_image (pattern->surface, image, extra);
1546 	    return NULL;
1547 	}
1548 
1549 	cleanup = malloc (sizeof (*cleanup));
1550 	if (unlikely (cleanup == NULL)) {
1551 	    _cairo_surface_release_source_image (pattern->surface, image, extra);
1552 	    pixman_image_unref (pixman_image);
1553 	    return NULL;
1554 	}
1555 
1556 	cleanup->surface = pattern->surface;
1557 	cleanup->image = image;
1558 	cleanup->image_extra = extra;
1559 	pixman_image_set_destroy_function (pixman_image,
1560 					   _acquire_source_cleanup, cleanup);
1561     }
1562 
1563     if (! _cairo_matrix_is_translation (&pattern->base.matrix) ||
1564 	! _nearest_sample (filter, &tx, &ty))
1565     {
1566 	pixman_transform_t pixman_transform;
1567 	cairo_matrix_t m;
1568 
1569 	m = pattern->base.matrix;
1570 	if (m.x0 != 0. || m.y0 != 0.) {
1571 	    cairo_matrix_t inv;
1572 	    cairo_status_t status;
1573 	    double x, y;
1574 
1575 	    /* pixman also limits the [xy]_offset to 16 bits so evenly
1576 	     * spread the bits between the two.
1577 	     */
1578 	    inv = m;
1579 	    status = cairo_matrix_invert (&inv);
1580 	    assert (status == CAIRO_STATUS_SUCCESS);
1581 
1582 	    x = floor (inv.x0 / 2);
1583 	    y = floor (inv.y0 / 2);
1584 	    tx = -x;
1585 	    ty = -y;
1586 	    cairo_matrix_init_translate (&inv, x, y);
1587 	    cairo_matrix_multiply (&m, &inv, &m);
1588 	} else {
1589 	    tx = ty = 0;
1590 	}
1591 
1592 	_cairo_matrix_to_pixman_matrix (&m, &pixman_transform,
1593 					extents->x + extents->width/2.,
1594 					extents->y + extents->height/2.);
1595 	if (! pixman_image_set_transform (pixman_image, &pixman_transform)) {
1596 	    pixman_image_unref (pixman_image);
1597 	    return NULL;
1598 	}
1599     }
1600     *ix = tx;
1601     *iy = ty;
1602 
1603     if (_cairo_matrix_has_unity_scale (&pattern->base.matrix) &&
1604 	tx == pattern->base.matrix.x0 &&
1605 	ty == pattern->base.matrix.y0)
1606     {
1607 	pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0);
1608     }
1609     else
1610     {
1611 	pixman_filter_t pixman_filter;
1612 
1613 	switch (filter) {
1614 	case CAIRO_FILTER_FAST:
1615 	    pixman_filter = PIXMAN_FILTER_FAST;
1616 	    break;
1617 	case CAIRO_FILTER_GOOD:
1618 	    pixman_filter = PIXMAN_FILTER_GOOD;
1619 	    break;
1620 	case CAIRO_FILTER_BEST:
1621 	    pixman_filter = PIXMAN_FILTER_BEST;
1622 	    break;
1623 	case CAIRO_FILTER_NEAREST:
1624 	    pixman_filter = PIXMAN_FILTER_NEAREST;
1625 	    break;
1626 	case CAIRO_FILTER_BILINEAR:
1627 	    pixman_filter = PIXMAN_FILTER_BILINEAR;
1628 	    break;
1629 	case CAIRO_FILTER_GAUSSIAN:
1630 	    /* XXX: The GAUSSIAN value has no implementation in cairo
1631 	     * whatsoever, so it was really a mistake to have it in the
1632 	     * API. We could fix this by officially deprecating it, or
1633 	     * else inventing semantics and providing an actual
1634 	     * implementation for it. */
1635 	default:
1636 	    pixman_filter = PIXMAN_FILTER_BEST;
1637 	}
1638 
1639 	pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
1640     }
1641 
1642     {
1643 	pixman_repeat_t pixman_repeat;
1644 
1645 	switch (extend) {
1646 	default:
1647 	case CAIRO_EXTEND_NONE:
1648 	    pixman_repeat = PIXMAN_REPEAT_NONE;
1649 	    break;
1650 	case CAIRO_EXTEND_REPEAT:
1651 	    pixman_repeat = PIXMAN_REPEAT_NORMAL;
1652 	    break;
1653 	case CAIRO_EXTEND_REFLECT:
1654 	    pixman_repeat = PIXMAN_REPEAT_REFLECT;
1655 	    break;
1656 	case CAIRO_EXTEND_PAD:
1657 	    pixman_repeat = PIXMAN_REPEAT_PAD;
1658 	    break;
1659 	}
1660 
1661 	pixman_image_set_repeat (pixman_image, pixman_repeat);
1662     }
1663 
1664     if (pattern->base.has_component_alpha)
1665 	pixman_image_set_component_alpha (pixman_image, TRUE);
1666 
1667     return pixman_image;
1668 }
1669 
1670 static pixman_image_t *
_pixman_image_for_pattern(const cairo_pattern_t * pattern,cairo_bool_t is_mask,const cairo_rectangle_int_t * extents,int * tx,int * ty)1671 _pixman_image_for_pattern (const cairo_pattern_t *pattern,
1672 			   cairo_bool_t is_mask,
1673 			   const cairo_rectangle_int_t *extents,
1674 			   int *tx, int *ty)
1675 {
1676     *tx = *ty = 0;
1677 
1678     if (pattern == NULL)
1679 	return _pixman_white_image ();
1680 
1681     switch (pattern->type) {
1682     default:
1683 	ASSERT_NOT_REACHED;
1684     case CAIRO_PATTERN_TYPE_SOLID:
1685 	return _pixman_image_for_solid ((const cairo_solid_pattern_t *) pattern);
1686 
1687     case CAIRO_PATTERN_TYPE_RADIAL:
1688     case CAIRO_PATTERN_TYPE_LINEAR:
1689 	return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
1690 					   extents, tx, ty);
1691 
1692     case CAIRO_PATTERN_TYPE_SURFACE:
1693 	return _pixman_image_for_surface ((const cairo_surface_pattern_t *) pattern,
1694 					  is_mask, extents, tx, ty);
1695     }
1696 }
1697 
1698 static cairo_status_t
_cairo_image_surface_fixup_unbounded(cairo_image_surface_t * dst,const cairo_composite_rectangles_t * rects,cairo_clip_t * clip)1699 _cairo_image_surface_fixup_unbounded (cairo_image_surface_t *dst,
1700 				      const cairo_composite_rectangles_t *rects,
1701 				      cairo_clip_t *clip)
1702 {
1703     pixman_image_t *mask = NULL;
1704     pixman_box32_t boxes[4];
1705     int i, mask_x = 0, mask_y = 0, n_boxes = 0;
1706 
1707     if (clip != NULL) {
1708 	cairo_surface_t *clip_surface;
1709 	int clip_x, clip_y;
1710 
1711 	clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
1712 	if (unlikely (clip_surface->status))
1713 	    return clip_surface->status;
1714 
1715 	mask = ((cairo_image_surface_t *) clip_surface)->pixman_image;
1716 	mask_x = -clip_x;
1717 	mask_y = -clip_y;
1718     } else {
1719 	if (rects->bounded.width  == rects->unbounded.width &&
1720 	    rects->bounded.height == rects->unbounded.height)
1721 	{
1722 	    return CAIRO_STATUS_SUCCESS;
1723 	}
1724     }
1725 
1726     /* wholly unbounded? */
1727     if (rects->bounded.width == 0 || rects->bounded.height == 0) {
1728 	int x = rects->unbounded.x;
1729 	int y = rects->unbounded.y;
1730 	int width = rects->unbounded.width;
1731 	int height = rects->unbounded.height;
1732 
1733 	if (mask != NULL) {
1734 	    pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
1735                                       mask, NULL, dst->pixman_image,
1736                                       x + mask_x, y + mask_y,
1737                                       0, 0,
1738                                       x, y,
1739                                       width, height);
1740 	} else {
1741             pixman_color_t color = { 0, };
1742             pixman_box32_t box = { x, y, x + width, y + height };
1743 
1744             if (! pixman_image_fill_boxes (PIXMAN_OP_CLEAR,
1745 					   dst->pixman_image,
1746 					   &color,
1747 					   1, &box))
1748 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1749 	}
1750 
1751 	return CAIRO_STATUS_SUCCESS;
1752     }
1753 
1754     /* top */
1755     if (rects->bounded.y != rects->unbounded.y) {
1756         boxes[n_boxes].x1 = rects->unbounded.x;
1757         boxes[n_boxes].y1 = rects->unbounded.y;
1758         boxes[n_boxes].x2 = rects->unbounded.x + rects->unbounded.width;
1759         boxes[n_boxes].y2 = rects->bounded.y;
1760         n_boxes++;
1761     }
1762 
1763     /* left */
1764     if (rects->bounded.x != rects->unbounded.x) {
1765         boxes[n_boxes].x1 = rects->unbounded.x;
1766         boxes[n_boxes].y1 = rects->bounded.y;
1767         boxes[n_boxes].x2 = rects->bounded.x;
1768         boxes[n_boxes].y2 = rects->bounded.y + rects->bounded.height;
1769         n_boxes++;
1770     }
1771 
1772     /* right */
1773     if (rects->bounded.x + rects->bounded.width != rects->unbounded.x + rects->unbounded.width) {
1774         boxes[n_boxes].x1 = rects->bounded.x + rects->bounded.width;
1775         boxes[n_boxes].y1 = rects->bounded.y;
1776         boxes[n_boxes].x2 = rects->unbounded.x + rects->unbounded.width;
1777         boxes[n_boxes].y2 = rects->bounded.y + rects->bounded.height;
1778         n_boxes++;
1779     }
1780 
1781     /* bottom */
1782     if (rects->bounded.y + rects->bounded.height != rects->unbounded.y + rects->unbounded.height) {
1783         boxes[n_boxes].x1 = rects->unbounded.x;
1784         boxes[n_boxes].y1 = rects->bounded.y + rects->bounded.height;
1785         boxes[n_boxes].x2 = rects->unbounded.x + rects->unbounded.width;
1786         boxes[n_boxes].y2 = rects->unbounded.y + rects->unbounded.height;
1787         n_boxes++;
1788     }
1789 
1790     if (mask != NULL) {
1791         for (i = 0; i < n_boxes; i++) {
1792             pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
1793                                       mask, NULL, dst->pixman_image,
1794                                       boxes[i].x1 + mask_x, boxes[i].y1 + mask_y,
1795                                       0, 0,
1796                                       boxes[i].x1, boxes[i].y1,
1797                                       boxes[i].x2 - boxes[i].x1, boxes[i].y2 - boxes[i].y1);
1798         }
1799     } else {
1800         pixman_color_t color = { 0, };
1801 
1802         if (! pixman_image_fill_boxes (PIXMAN_OP_CLEAR,
1803 				       dst->pixman_image,
1804 				       &color,
1805 				       n_boxes,
1806 				       boxes))
1807 	{
1808 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1809 	}
1810     }
1811 
1812     return CAIRO_STATUS_SUCCESS;
1813 }
1814 
1815 static cairo_status_t
_cairo_image_surface_fixup_unbounded_boxes(cairo_image_surface_t * dst,const cairo_composite_rectangles_t * extents,cairo_region_t * clip_region,cairo_boxes_t * boxes)1816 _cairo_image_surface_fixup_unbounded_boxes (cairo_image_surface_t *dst,
1817 					    const cairo_composite_rectangles_t *extents,
1818 					    cairo_region_t *clip_region,
1819 					    cairo_boxes_t *boxes)
1820 {
1821     cairo_boxes_t clear;
1822     cairo_box_t box;
1823     cairo_status_t status;
1824     struct _cairo_boxes_chunk *chunk;
1825     int i;
1826 
1827     // If we have no boxes then we need to clear the entire extents
1828     // because we have nothing to draw.
1829     if (boxes->num_boxes < 1 && clip_region == NULL) {
1830         int x = extents->unbounded.x;
1831         int y = extents->unbounded.y;
1832         int width = extents->unbounded.width;
1833         int height = extents->unbounded.height;
1834 
1835         pixman_color_t color = { 0 };
1836         pixman_box32_t box = { x, y, x + width, y + height };
1837 
1838         if (! pixman_image_fill_boxes (PIXMAN_OP_CLEAR,
1839                                        dst->pixman_image,
1840                                        &color,
1841                                        1, &box)) {
1842             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1843         }
1844         return CAIRO_STATUS_SUCCESS;
1845     }
1846 
1847     _cairo_boxes_init (&clear);
1848 
1849     box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
1850     box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
1851     box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
1852     box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
1853 
1854     if (clip_region == NULL) {
1855 	cairo_boxes_t tmp;
1856 
1857 	_cairo_boxes_init (&tmp);
1858 
1859 	status = _cairo_boxes_add (&tmp, &box);
1860 	assert (status == CAIRO_STATUS_SUCCESS);
1861 
1862 	tmp.chunks.next = &boxes->chunks;
1863 	tmp.num_boxes += boxes->num_boxes;
1864 
1865 	status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
1866 							  CAIRO_FILL_RULE_WINDING,
1867 							  &clear);
1868 
1869 	tmp.chunks.next = NULL;
1870     } else {
1871 	pixman_box32_t *pbox;
1872 
1873 	pbox = pixman_region32_rectangles (&clip_region->rgn, &i);
1874 	_cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i);
1875 
1876 	status = _cairo_boxes_add (&clear, &box);
1877 	assert (status == CAIRO_STATUS_SUCCESS);
1878 
1879 	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1880 	    for (i = 0; i < chunk->count; i++) {
1881 		status = _cairo_boxes_add (&clear, &chunk->base[i]);
1882 		if (unlikely (status)) {
1883 		    _cairo_boxes_fini (&clear);
1884 		    return status;
1885 		}
1886 	    }
1887 	}
1888 
1889 	status = _cairo_bentley_ottmann_tessellate_boxes (&clear,
1890 							  CAIRO_FILL_RULE_WINDING,
1891 							  &clear);
1892     }
1893 
1894     if (likely (status == CAIRO_STATUS_SUCCESS)) {
1895 	for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) {
1896 	    for (i = 0; i < chunk->count; i++) {
1897 		int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
1898 		int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
1899 		int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
1900 		int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
1901 
1902 		x1 = (x1 < 0 ? 0 : x1);
1903 		y1 = (y1 < 0 ? 0 : y1);
1904 		if (x2 <= x1 || y2 <= y1)
1905 		    continue;
1906 		pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
1907 			     PIXMAN_FORMAT_BPP (dst->pixman_format),
1908 			     x1, y1, x2 - x1, y2 - y1,
1909 			     0);
1910 	    }
1911 	}
1912     }
1913 
1914     _cairo_boxes_fini (&clear);
1915 
1916     return status;
1917 }
1918 
1919 static cairo_bool_t
can_reduce_alpha_op(cairo_operator_t op)1920 can_reduce_alpha_op (cairo_operator_t op)
1921 {
1922     int iop = op;
1923     switch (iop) {
1924     case CAIRO_OPERATOR_OVER:
1925     case CAIRO_OPERATOR_SOURCE:
1926     case CAIRO_OPERATOR_ADD:
1927 	return TRUE;
1928     default:
1929 	return FALSE;
1930     }
1931 }
1932 
1933 static cairo_bool_t
reduce_alpha_op(cairo_image_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * pattern)1934 reduce_alpha_op (cairo_image_surface_t *dst,
1935 		 cairo_operator_t op,
1936 		 const cairo_pattern_t *pattern)
1937 {
1938     return dst->base.is_clear &&
1939 	   dst->base.content == CAIRO_CONTENT_ALPHA &&
1940 	   _cairo_pattern_is_opaque_solid (pattern) &&
1941 	   can_reduce_alpha_op (op);
1942 }
1943 
1944 /* low level compositor */
1945 typedef cairo_status_t
1946 (*image_draw_func_t) (void				*closure,
1947 		      pixman_image_t			*dst,
1948 		      pixman_format_code_t		 dst_format,
1949 		      cairo_operator_t			 op,
1950 		      const cairo_pattern_t		*src,
1951 		      int				 dst_x,
1952 		      int				 dst_y,
1953 		      const cairo_rectangle_int_t	*extents,
1954 		      cairo_region_t			*clip_region);
1955 
1956 static pixman_image_t *
_create_composite_mask_pattern(cairo_clip_t * clip,image_draw_func_t draw_func,void * draw_closure,cairo_image_surface_t * dst,const cairo_rectangle_int_t * extents)1957 _create_composite_mask_pattern (cairo_clip_t                  *clip,
1958 				image_draw_func_t              draw_func,
1959 				void                          *draw_closure,
1960 				cairo_image_surface_t         *dst,
1961 				const cairo_rectangle_int_t   *extents)
1962 {
1963     cairo_region_t *clip_region = NULL;
1964     pixman_image_t *mask;
1965     cairo_status_t status;
1966     cairo_bool_t need_clip_surface = FALSE;
1967 
1968     if (clip != NULL) {
1969 	status = _cairo_clip_get_region (clip, &clip_region);
1970 	assert (! _cairo_status_is_error (status));
1971 
1972 	/* The all-clipped state should never propagate this far. */
1973 	assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
1974 
1975 	need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
1976 
1977 	if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
1978 	    clip_region = NULL;
1979     }
1980 
1981     mask = pixman_image_create_bits (PIXMAN_a8, extents->width, extents->height,
1982 				     NULL, 0);
1983     if (unlikely (mask == NULL))
1984 	return NULL;
1985 
1986     /* Is it worth setting the clip region here? */
1987     if (clip_region != NULL) {
1988 	pixman_bool_t ret;
1989 
1990 	pixman_region32_translate (&clip_region->rgn, -extents->x, -extents->y);
1991 	ret = pixman_image_set_clip_region32 (mask, &clip_region->rgn);
1992 	pixman_region32_translate (&clip_region->rgn, extents->x, extents->y);
1993 
1994 	if (! ret) {
1995 	    pixman_image_unref (mask);
1996 	    return NULL;
1997 	}
1998     }
1999 
2000     status = draw_func (draw_closure,
2001 			mask, PIXMAN_a8,
2002 			CAIRO_OPERATOR_ADD, NULL,
2003 			extents->x, extents->y,
2004 			extents, NULL);
2005     if (unlikely (status)) {
2006 	pixman_image_unref (mask);
2007 	return NULL;
2008     }
2009 
2010     if (need_clip_surface) {
2011 	cairo_surface_t *tmp;
2012 
2013 	tmp = _cairo_image_surface_create_for_pixman_image (mask, PIXMAN_a8);
2014 	if (unlikely (tmp->status)) {
2015 	    pixman_image_unref (mask);
2016 	    return NULL;
2017 	}
2018 
2019 	pixman_image_ref (mask);
2020 
2021 	status = _cairo_clip_combine_with_surface (clip, tmp, extents->x, extents->y);
2022 	cairo_surface_destroy (tmp);
2023 	if (unlikely (status)) {
2024 	    pixman_image_unref (mask);
2025 	    return NULL;
2026 	}
2027     }
2028 
2029     if (clip_region != NULL)
2030 	pixman_image_set_clip_region (mask, NULL);
2031 
2032     return mask;
2033 }
2034 
2035 /* Handles compositing with a clip surface when the operator allows
2036  * us to combine the clip with the mask
2037  */
2038 static cairo_status_t
_clip_and_composite_with_mask(cairo_clip_t * clip,cairo_operator_t op,const cairo_pattern_t * pattern,image_draw_func_t draw_func,void * draw_closure,cairo_image_surface_t * dst,const cairo_rectangle_int_t * extents)2039 _clip_and_composite_with_mask (cairo_clip_t                  *clip,
2040 			       cairo_operator_t               op,
2041 			       const cairo_pattern_t         *pattern,
2042 			       image_draw_func_t              draw_func,
2043 			       void                          *draw_closure,
2044 			       cairo_image_surface_t         *dst,
2045 			       const cairo_rectangle_int_t   *extents)
2046 {
2047     pixman_image_t *mask;
2048 
2049     mask = _create_composite_mask_pattern (clip, draw_func, draw_closure, dst, extents);
2050     if (unlikely (mask == NULL))
2051 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2052 
2053     if (pattern == NULL) {
2054 	if (dst->pixman_format == PIXMAN_a8) {
2055 	    pixman_image_composite32 (_pixman_operator (op),
2056                                       mask, NULL, dst->pixman_image,
2057                                       0, 0, 0, 0,
2058                                       extents->x,      extents->y,
2059                                       extents->width,  extents->height);
2060 	} else {
2061 	    pixman_image_t *src;
2062 
2063 	    src = _pixman_white_image ();
2064 	    if (unlikely (src == NULL)) {
2065 		pixman_image_unref (mask);
2066 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2067 	    }
2068 
2069 	    pixman_image_composite32 (_pixman_operator (op),
2070                                       src, mask, dst->pixman_image,
2071                                       0, 0, 0, 0,
2072                                       extents->x,      extents->y,
2073                                       extents->width,  extents->height);
2074 	    pixman_image_unref (src);
2075 	}
2076     } else {
2077 	pixman_image_t *src;
2078 	int src_x, src_y;
2079 
2080 	src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
2081 	if (unlikely (src == NULL)) {
2082 	    pixman_image_unref (mask);
2083 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2084 	}
2085 
2086 	pixman_image_composite32 (_pixman_operator (op),
2087                                   src, mask, dst->pixman_image,
2088                                   extents->x + src_x,  extents->y + src_y,
2089                                   0, 0,
2090                                   extents->x,          extents->y,
2091                                   extents->width,      extents->height);
2092 	pixman_image_unref (src);
2093     }
2094 
2095     pixman_image_unref (mask);
2096 
2097     return CAIRO_STATUS_SUCCESS;
2098 }
2099 
2100 /* Handles compositing with a clip surface when we have to do the operation
2101  * in two pieces and combine them together.
2102  */
2103 static cairo_status_t
_clip_and_composite_combine(cairo_clip_t * clip,cairo_operator_t op,const cairo_pattern_t * src,image_draw_func_t draw_func,void * draw_closure,cairo_image_surface_t * dst,const cairo_rectangle_int_t * extents)2104 _clip_and_composite_combine (cairo_clip_t                  *clip,
2105 			     cairo_operator_t               op,
2106 			     const cairo_pattern_t         *src,
2107 			     image_draw_func_t              draw_func,
2108 			     void                          *draw_closure,
2109 			     cairo_image_surface_t               *dst,
2110 			     const cairo_rectangle_int_t   *extents)
2111 {
2112     pixman_image_t *tmp;
2113     cairo_surface_t *clip_surface;
2114     int clip_x, clip_y;
2115     cairo_status_t status;
2116 
2117     tmp  = pixman_image_create_bits (dst->pixman_format,
2118 				     extents->width, extents->height,
2119 				     NULL, 0);
2120     if (unlikely (tmp == NULL))
2121 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2122 
2123     if (src == NULL) {
2124 	status = (*draw_func) (draw_closure,
2125 			       tmp, dst->pixman_format,
2126 			       CAIRO_OPERATOR_ADD, NULL,
2127 			       extents->x, extents->y,
2128 			       extents, NULL);
2129     } else {
2130 	/* Initialize the temporary surface from the destination surface */
2131 	if (! dst->base.is_clear) {
2132 	    pixman_image_composite32 (PIXMAN_OP_SRC,
2133                                       dst->pixman_image, NULL, tmp,
2134                                       extents->x, extents->y,
2135                                       0, 0,
2136                                       0, 0,
2137                                       extents->width, extents->height);
2138 	}
2139 
2140 	status = (*draw_func) (draw_closure,
2141 			       tmp, dst->pixman_format,
2142 			       op, src,
2143 			       extents->x, extents->y,
2144 			       extents, NULL);
2145     }
2146     if (unlikely (status))
2147 	goto CLEANUP_SURFACE;
2148 
2149     assert (clip->path != NULL);
2150     clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
2151     if (unlikely (clip_surface->status))
2152 	goto CLEANUP_SURFACE;
2153 
2154     if (! dst->base.is_clear) {
2155 #if PIXMAN_HAS_OP_LERP
2156 	pixman_image_composite32 (PIXMAN_OP_LERP,
2157                                   tmp,
2158                                   ((cairo_image_surface_t *) clip_surface)->pixman_image,
2159                                   dst->pixman_image,
2160                                   0, 0,
2161                                   extents->x - clip_x,
2162                                   extents->y - clip_y,
2163                                   extents->x, extents->y,
2164                                   extents->width, extents->height);
2165 #else
2166 	/* Punch the clip out of the destination */
2167 	pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2168                                   ((cairo_image_surface_t *) clip_surface)->pixman_image,
2169                                   NULL, dst->pixman_image,
2170                                   extents->x - clip_x,
2171                                   extents->y - clip_y,
2172                                   0, 0,
2173                                   extents->x, extents->y,
2174                                   extents->width, extents->height);
2175 
2176 	/* Now add the two results together */
2177 	pixman_image_composite32 (PIXMAN_OP_ADD,
2178                                   tmp,
2179                                   ((cairo_image_surface_t *) clip_surface)->pixman_image,
2180                                   dst->pixman_image,
2181                                   0, 0,
2182                                   extents->x - clip_x,
2183                                   extents->y - clip_y,
2184                                   extents->x, extents->y,
2185                                   extents->width, extents->height);
2186 #endif
2187     } else {
2188 	pixman_image_composite32 (PIXMAN_OP_SRC,
2189                                   tmp,
2190                                   ((cairo_image_surface_t *) clip_surface)->pixman_image,
2191                                   dst->pixman_image,
2192                                   0, 0,
2193                                   extents->x - clip_x,
2194                                   extents->y - clip_y,
2195                                   extents->x, extents->y,
2196                                   extents->width, extents->height);
2197     }
2198 
2199  CLEANUP_SURFACE:
2200     pixman_image_unref (tmp);
2201 
2202     return status;
2203 }
2204 
2205 /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
2206  * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
2207  */
2208 static cairo_status_t
_clip_and_composite_source(cairo_clip_t * clip,const cairo_pattern_t * pattern,image_draw_func_t draw_func,void * draw_closure,cairo_image_surface_t * dst,const cairo_rectangle_int_t * extents)2209 _clip_and_composite_source (cairo_clip_t                  *clip,
2210 			    const cairo_pattern_t         *pattern,
2211 			    image_draw_func_t              draw_func,
2212 			    void                          *draw_closure,
2213 			    cairo_image_surface_t         *dst,
2214 			    const cairo_rectangle_int_t   *extents)
2215 {
2216     pixman_image_t *mask, *src;
2217     int src_x, src_y;
2218 
2219     if (pattern == NULL) {
2220 	cairo_region_t *clip_region;
2221 	cairo_status_t status;
2222 
2223 	status = draw_func (draw_closure,
2224 			    dst->pixman_image, dst->pixman_format,
2225 			    CAIRO_OPERATOR_SOURCE, NULL,
2226 			    extents->x, extents->y,
2227 			    extents, NULL);
2228 	if (unlikely (status))
2229 	    return status;
2230 
2231 	if (_cairo_clip_get_region (clip, &clip_region) == CAIRO_INT_STATUS_UNSUPPORTED)
2232 	    status = _cairo_clip_combine_with_surface (clip, &dst->base, 0, 0);
2233 
2234 	return status;
2235     }
2236 
2237     /* Create a surface that is mask IN clip */
2238     mask = _create_composite_mask_pattern (clip, draw_func, draw_closure, dst, extents);
2239     if (unlikely (mask == NULL))
2240 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2241 
2242     src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
2243     if (unlikely (src == NULL)) {
2244 	pixman_image_unref (mask);
2245 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2246     }
2247 
2248     if (! dst->base.is_clear) {
2249 #if PIXMAN_HAS_OP_LERP
2250 	pixman_image_composite32 (PIXMAN_OP_LERP,
2251                                   src, mask, dst->pixman_image,
2252                                   extents->x + src_x, extents->y + src_y,
2253                                   0, 0,
2254                                   extents->x,     extents->y,
2255                                   extents->width, extents->height);
2256 #else
2257 	/* Compute dest' = dest OUT (mask IN clip) */
2258 	pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2259                                   mask, NULL, dst->pixman_image,
2260                                   0, 0, 0, 0,
2261                                   extents->x,     extents->y,
2262                                   extents->width, extents->height);
2263 
2264 	/* Now compute (src IN (mask IN clip)) ADD dest' */
2265 	pixman_image_composite32 (PIXMAN_OP_ADD,
2266                                   src, mask, dst->pixman_image,
2267                                   extents->x + src_x, extents->y + src_y,
2268                                   0, 0,
2269                                   extents->x,     extents->y,
2270                                   extents->width, extents->height);
2271 #endif
2272     } else {
2273 	pixman_image_composite32 (PIXMAN_OP_SRC,
2274                                   src, mask, dst->pixman_image,
2275                                   extents->x + src_x, extents->y + src_y,
2276                                   0, 0,
2277                                   extents->x,     extents->y,
2278                                   extents->width, extents->height);
2279     }
2280 
2281     pixman_image_unref (src);
2282     pixman_image_unref (mask);
2283 
2284     return CAIRO_STATUS_SUCCESS;
2285 }
2286 
2287 static cairo_status_t
_clip_and_composite(cairo_image_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * src,image_draw_func_t draw_func,void * draw_closure,cairo_composite_rectangles_t * extents,cairo_clip_t * clip)2288 _clip_and_composite (cairo_image_surface_t	*dst,
2289 		     cairo_operator_t		 op,
2290 		     const cairo_pattern_t	*src,
2291 		     image_draw_func_t		 draw_func,
2292 		     void			*draw_closure,
2293 		     cairo_composite_rectangles_t*extents,
2294 		     cairo_clip_t		*clip)
2295 {
2296     cairo_status_t status;
2297     cairo_region_t *clip_region = NULL;
2298     cairo_bool_t need_clip_surface = FALSE;
2299 
2300     if (clip != NULL) {
2301 	status = _cairo_clip_get_region (clip, &clip_region);
2302 	if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
2303 	    return CAIRO_STATUS_SUCCESS;
2304 	if (unlikely (_cairo_status_is_error (status)))
2305 	    return status;
2306 
2307 	need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
2308 
2309 	if (clip_region != NULL) {
2310 	    cairo_rectangle_int_t rect;
2311 	    cairo_bool_t is_empty;
2312 
2313 	    cairo_region_get_extents (clip_region, &rect);
2314 	    is_empty = ! _cairo_rectangle_intersect (&extents->unbounded, &rect);
2315 	    if (unlikely (is_empty))
2316 		return CAIRO_STATUS_SUCCESS;
2317 
2318 	    is_empty = ! _cairo_rectangle_intersect (&extents->bounded, &rect);
2319 	    if (unlikely (is_empty && extents->is_bounded))
2320 		return CAIRO_STATUS_SUCCESS;
2321 
2322 	    if (cairo_region_num_rectangles (clip_region) == 1)
2323 		clip_region = NULL;
2324 	}
2325     }
2326 
2327     if (clip_region != NULL) {
2328 	status = _cairo_image_surface_set_clip_region (dst, clip_region);
2329 	if (unlikely (status))
2330 	    return status;
2331     }
2332 
2333     if (reduce_alpha_op (dst, op, src)) {
2334 	op = CAIRO_OPERATOR_ADD;
2335 	src = NULL;
2336     }
2337 
2338     if (op == CAIRO_OPERATOR_SOURCE) {
2339 	status = _clip_and_composite_source (clip, src,
2340 					     draw_func, draw_closure,
2341 					     dst, &extents->bounded);
2342     } else {
2343 	if (op == CAIRO_OPERATOR_CLEAR) {
2344 	    src = NULL;
2345 	    op = CAIRO_OPERATOR_DEST_OUT;
2346 	}
2347 
2348 	if (need_clip_surface) {
2349 	    if (extents->is_bounded) {
2350 		status = _clip_and_composite_with_mask (clip, op, src,
2351 							draw_func, draw_closure,
2352 							dst, &extents->bounded);
2353 	    } else {
2354 		status = _clip_and_composite_combine (clip, op, src,
2355 						      draw_func, draw_closure,
2356 						      dst, &extents->bounded);
2357 	    }
2358 	} else {
2359 	    status = draw_func (draw_closure,
2360 				dst->pixman_image, dst->pixman_format,
2361 				op, src,
2362 				0, 0,
2363 				&extents->bounded,
2364 				clip_region);
2365 	}
2366     }
2367 
2368     if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
2369 	status = _cairo_image_surface_fixup_unbounded (dst, extents,
2370 						       need_clip_surface ? clip : NULL);
2371     }
2372 
2373     if (clip_region != NULL)
2374 	_cairo_image_surface_unset_clip_region (dst);
2375 
2376     return status;
2377 }
2378 
2379 #define CAIRO_FIXED_16_16_MIN _cairo_fixed_from_int (-32768)
2380 #define CAIRO_FIXED_16_16_MAX _cairo_fixed_from_int (32767)
2381 
2382 static cairo_bool_t
_line_exceeds_16_16(const cairo_line_t * line)2383 _line_exceeds_16_16 (const cairo_line_t *line)
2384 {
2385     return
2386 	line->p1.x <= CAIRO_FIXED_16_16_MIN ||
2387 	line->p1.x >= CAIRO_FIXED_16_16_MAX ||
2388 
2389 	line->p2.x <= CAIRO_FIXED_16_16_MIN ||
2390 	line->p2.x >= CAIRO_FIXED_16_16_MAX ||
2391 
2392 	line->p1.y <= CAIRO_FIXED_16_16_MIN ||
2393 	line->p1.y >= CAIRO_FIXED_16_16_MAX ||
2394 
2395 	line->p2.y <= CAIRO_FIXED_16_16_MIN ||
2396 	line->p2.y >= CAIRO_FIXED_16_16_MAX;
2397 }
2398 
2399 static void
_project_line_x_onto_16_16(const cairo_line_t * line,cairo_fixed_t top,cairo_fixed_t bottom,pixman_line_fixed_t * out)2400 _project_line_x_onto_16_16 (const cairo_line_t *line,
2401 			    cairo_fixed_t top,
2402 			    cairo_fixed_t bottom,
2403 			    pixman_line_fixed_t *out)
2404 {
2405     cairo_point_double_t p1, p2;
2406     double m;
2407 
2408     p1.x = _cairo_fixed_to_double (line->p1.x);
2409     p1.y = _cairo_fixed_to_double (line->p1.y);
2410 
2411     p2.x = _cairo_fixed_to_double (line->p2.x);
2412     p2.y = _cairo_fixed_to_double (line->p2.y);
2413 
2414     m = (p2.x - p1.x) / (p2.y - p1.y);
2415     out->p1.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (top - line->p1.y));
2416     out->p2.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (bottom - line->p1.y));
2417 }
2418 
2419 
2420 typedef struct {
2421     cairo_trapezoid_t *traps;
2422     int num_traps;
2423     cairo_antialias_t antialias;
2424 } composite_traps_info_t;
2425 
2426 static void
_pixman_image_add_traps(pixman_image_t * image,int dst_x,int dst_y,composite_traps_info_t * info)2427 _pixman_image_add_traps (pixman_image_t *image,
2428 			 int dst_x, int dst_y,
2429 			 composite_traps_info_t *info)
2430 {
2431     cairo_trapezoid_t *t = info->traps;
2432     int num_traps = info->num_traps;
2433     while (num_traps--) {
2434 	pixman_trapezoid_t trap;
2435 
2436 	/* top/bottom will be clamped to surface bounds */
2437 	trap.top = _cairo_fixed_to_16_16 (t->top);
2438 	trap.bottom = _cairo_fixed_to_16_16 (t->bottom);
2439 
2440 	/* However, all the other coordinates will have been left untouched so
2441 	 * as not to introduce numerical error. Recompute them if they
2442 	 * exceed the 16.16 limits.
2443 	 */
2444 	if (unlikely (_line_exceeds_16_16 (&t->left))) {
2445 	    _project_line_x_onto_16_16 (&t->left, t->top, t->bottom, &trap.left);
2446 	    trap.left.p1.y = trap.top;
2447 	    trap.left.p2.y = trap.bottom;
2448 	} else {
2449 	    trap.left.p1.x = _cairo_fixed_to_16_16 (t->left.p1.x);
2450 	    trap.left.p1.y = _cairo_fixed_to_16_16 (t->left.p1.y);
2451 	    trap.left.p2.x = _cairo_fixed_to_16_16 (t->left.p2.x);
2452 	    trap.left.p2.y = _cairo_fixed_to_16_16 (t->left.p2.y);
2453 	}
2454 
2455 	if (unlikely (_line_exceeds_16_16 (&t->right))) {
2456 	    _project_line_x_onto_16_16 (&t->right, t->top, t->bottom, &trap.right);
2457 	    trap.right.p1.y = trap.top;
2458 	    trap.right.p2.y = trap.bottom;
2459 	} else {
2460 	    trap.right.p1.x = _cairo_fixed_to_16_16 (t->right.p1.x);
2461 	    trap.right.p1.y = _cairo_fixed_to_16_16 (t->right.p1.y);
2462 	    trap.right.p2.x = _cairo_fixed_to_16_16 (t->right.p2.x);
2463 	    trap.right.p2.y = _cairo_fixed_to_16_16 (t->right.p2.y);
2464 	}
2465 
2466 	pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y);
2467 
2468 	t++;
2469     }
2470 }
2471 
2472 static cairo_status_t
_composite_traps(void * closure,pixman_image_t * dst,pixman_format_code_t dst_format,cairo_operator_t op,const cairo_pattern_t * pattern,int dst_x,int dst_y,const cairo_rectangle_int_t * extents,cairo_region_t * clip_region)2473 _composite_traps (void                          *closure,
2474 		  pixman_image_t		*dst,
2475 		  pixman_format_code_t		 dst_format,
2476 		  cairo_operator_t               op,
2477 		  const cairo_pattern_t         *pattern,
2478 		  int                            dst_x,
2479 		  int                            dst_y,
2480 		  const cairo_rectangle_int_t   *extents,
2481 		  cairo_region_t		*clip_region)
2482 {
2483     composite_traps_info_t *info = closure;
2484     pixman_image_t *src, *mask;
2485     pixman_format_code_t format;
2486     int src_x = 0, src_y = 0;
2487     cairo_status_t status;
2488 
2489     /* Special case adding trapezoids onto a mask surface; we want to avoid
2490      * creating an intermediate temporary mask unnecessarily.
2491      *
2492      * We make the assumption here that the portion of the trapezoids
2493      * contained within the surface is bounded by [dst_x,dst_y,width,height];
2494      * the Cairo core code passes bounds based on the trapezoid extents.
2495      */
2496     format = info->antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8;
2497     if (dst_format == format &&
2498 	(pattern == NULL ||
2499 	 (op == CAIRO_OPERATOR_ADD && _cairo_pattern_is_opaque_solid (pattern))))
2500     {
2501 	_pixman_image_add_traps (dst, dst_x, dst_y, info);
2502 	return CAIRO_STATUS_SUCCESS;
2503     }
2504 
2505     src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
2506     if (unlikely (src == NULL))
2507 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2508 
2509     mask = pixman_image_create_bits (format, extents->width, extents->height,
2510 				     NULL, 0);
2511     if (unlikely (mask == NULL)) {
2512 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2513 	goto CLEANUP_SOURCE;
2514     }
2515 
2516     _pixman_image_add_traps (mask, extents->x, extents->y, info);
2517     pixman_image_composite32 (_pixman_operator (op),
2518                               src, mask, dst,
2519                               extents->x + src_x, extents->y + src_y,
2520                               0, 0,
2521                               extents->x - dst_x, extents->y - dst_y,
2522                               extents->width, extents->height);
2523 
2524     pixman_image_unref (mask);
2525 
2526     status = CAIRO_STATUS_SUCCESS;
2527  CLEANUP_SOURCE:
2528     pixman_image_unref (src);
2529 
2530     return status;
2531 }
2532 
2533 static inline uint32_t
color_to_uint32(const cairo_color_t * color)2534 color_to_uint32 (const cairo_color_t *color)
2535 {
2536     return
2537         (color->alpha_short >> 8 << 24) |
2538         (color->red_short >> 8 << 16)   |
2539         (color->green_short & 0xff00)   |
2540         (color->blue_short >> 8);
2541 }
2542 
2543 static inline cairo_bool_t
color_to_pixel(const cairo_color_t * color,pixman_format_code_t format,uint32_t * pixel)2544 color_to_pixel (const cairo_color_t	*color,
2545                 pixman_format_code_t	 format,
2546                 uint32_t		*pixel)
2547 {
2548     uint32_t c;
2549 
2550     if (!(format == PIXMAN_a8r8g8b8     ||
2551           format == PIXMAN_x8r8g8b8     ||
2552           format == PIXMAN_a8b8g8r8     ||
2553           format == PIXMAN_x8b8g8r8     ||
2554           format == PIXMAN_b8g8r8a8     ||
2555           format == PIXMAN_b8g8r8x8     ||
2556           format == PIXMAN_r5g6b5       ||
2557           format == PIXMAN_b5g6r5       ||
2558           format == PIXMAN_a8))
2559     {
2560 	return FALSE;
2561     }
2562 
2563     c = color_to_uint32 (color);
2564 
2565     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) {
2566 	c = ((c & 0xff000000) >>  0) |
2567 	    ((c & 0x00ff0000) >> 16) |
2568 	    ((c & 0x0000ff00) >>  0) |
2569 	    ((c & 0x000000ff) << 16);
2570     }
2571 
2572     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) {
2573 	c = ((c & 0xff000000) >> 24) |
2574 	    ((c & 0x00ff0000) >>  8) |
2575 	    ((c & 0x0000ff00) <<  8) |
2576 	    ((c & 0x000000ff) << 24);
2577     }
2578 
2579     if (format == PIXMAN_a8) {
2580 	c = c >> 24;
2581     } else if (format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5) {
2582 	c = ((((c) >> 3) & 0x001f) |
2583 	     (((c) >> 5) & 0x07e0) |
2584 	     (((c) >> 8) & 0xf800));
2585     }
2586 
2587     *pixel = c;
2588     return TRUE;
2589 }
2590 
2591 static inline cairo_bool_t
pattern_to_pixel(const cairo_solid_pattern_t * solid,cairo_operator_t op,pixman_format_code_t format,uint32_t * pixel)2592 pattern_to_pixel (const cairo_solid_pattern_t *solid,
2593 		  cairo_operator_t op,
2594 		  pixman_format_code_t format,
2595 		  uint32_t *pixel)
2596 {
2597     if (op == CAIRO_OPERATOR_CLEAR) {
2598 	*pixel = 0;
2599 	return TRUE;
2600     }
2601 
2602     if (solid->base.type != CAIRO_PATTERN_TYPE_SOLID)
2603 	return FALSE;
2604 
2605     if (op == CAIRO_OPERATOR_OVER) {
2606 	if (solid->color.alpha_short >= 0xff00)
2607 	    op = CAIRO_OPERATOR_SOURCE;
2608     }
2609 
2610     if (op != CAIRO_OPERATOR_SOURCE)
2611 	return FALSE;
2612 
2613     return color_to_pixel (&solid->color, format, pixel);
2614 }
2615 
2616 typedef struct _fill_span {
2617     cairo_span_renderer_t base;
2618 
2619     uint8_t *mask_data;
2620     pixman_image_t *src, *dst, *mask;
2621 } fill_span_renderer_t;
2622 
2623 static cairo_status_t
_fill_span(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * spans,unsigned num_spans)2624 _fill_span (void *abstract_renderer,
2625 	    int y, int height,
2626 	    const cairo_half_open_span_t *spans,
2627 	    unsigned num_spans)
2628 {
2629     fill_span_renderer_t *renderer = abstract_renderer;
2630     uint8_t *row;
2631     unsigned i;
2632 
2633     if (num_spans == 0)
2634 	return CAIRO_STATUS_SUCCESS;
2635 
2636     row = renderer->mask_data - spans[0].x;
2637     for (i = 0; i < num_spans - 1; i++) {
2638 	/* We implement setting the most common single pixel wide
2639 	 * span case to avoid the overhead of a memset call.
2640 	 * Open coding setting longer spans didn't show a
2641 	 * noticeable improvement over memset.
2642 	 */
2643 	if (spans[i+1].x == spans[i].x + 1) {
2644 	    row[spans[i].x] = spans[i].coverage;
2645 	} else {
2646 	    memset (row + spans[i].x,
2647 		    spans[i].coverage,
2648 		    spans[i+1].x - spans[i].x);
2649 	}
2650     }
2651 
2652     do {
2653 	pixman_image_composite32 (PIXMAN_OP_OVER,
2654                                   renderer->src, renderer->mask, renderer->dst,
2655                                   0, 0, 0, 0,
2656                                   spans[0].x, y++,
2657                                   spans[i].x - spans[0].x, 1);
2658     } while (--height);
2659 
2660     return CAIRO_STATUS_SUCCESS;
2661 }
2662 
2663 /* avoid using region code to re-validate boxes */
2664 static cairo_status_t
_fill_unaligned_boxes(cairo_image_surface_t * dst,const cairo_pattern_t * pattern,uint32_t pixel,const cairo_boxes_t * boxes,const cairo_composite_rectangles_t * extents)2665 _fill_unaligned_boxes (cairo_image_surface_t *dst,
2666 		       const cairo_pattern_t *pattern,
2667 		       uint32_t pixel,
2668 		       const cairo_boxes_t *boxes,
2669 		       const cairo_composite_rectangles_t *extents)
2670 {
2671     uint8_t buf[CAIRO_STACK_BUFFER_SIZE];
2672     fill_span_renderer_t renderer;
2673     cairo_rectangular_scan_converter_t converter;
2674     const struct _cairo_boxes_chunk *chunk;
2675     cairo_status_t status;
2676     int i;
2677 
2678     /* XXX
2679      * using composite for fill:
2680      *   spiral-box-nonalign-evenodd-fill.512    2201957    2.202
2681      *   spiral-box-nonalign-nonzero-fill.512     336726    0.337
2682      *   spiral-box-pixalign-evenodd-fill.512     352256    0.352
2683      *   spiral-box-pixalign-nonzero-fill.512     147056    0.147
2684      * using fill:
2685      *   spiral-box-nonalign-evenodd-fill.512    3174565    3.175
2686      *   spiral-box-nonalign-nonzero-fill.512     182710    0.183
2687      *   spiral-box-pixalign-evenodd-fill.512     353863    0.354
2688      *   spiral-box-pixalign-nonzero-fill.512     147402    0.147
2689      *
2690      * cairo-perf-trace seems to favour using fill.
2691      */
2692 
2693     renderer.base.render_rows = _fill_span;
2694     renderer.dst = dst->pixman_image;
2695 
2696     if ((unsigned) extents->bounded.width <= sizeof (buf)) {
2697 	renderer.mask = pixman_image_create_bits (PIXMAN_a8,
2698 						  extents->bounded.width, 1,
2699 						  (uint32_t *) buf,
2700 						  sizeof (buf));
2701     } else {
2702 	renderer.mask = pixman_image_create_bits (PIXMAN_a8,
2703 						  extents->bounded.width, 1,
2704 						  NULL,  0);
2705     }
2706     if (unlikely (renderer.mask == NULL))
2707 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2708 
2709     renderer.mask_data = (uint8_t *) pixman_image_get_data (renderer.mask);
2710 
2711     renderer.src = _pixman_image_for_solid ((const cairo_solid_pattern_t *) pattern);
2712     if (unlikely (renderer.src == NULL)) {
2713 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2714 	goto CLEANUP_MASK;
2715     }
2716 
2717     _cairo_rectangular_scan_converter_init (&converter, &extents->bounded);
2718 
2719     /* first blit any aligned part of the boxes */
2720     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2721 	const cairo_box_t *box = chunk->base;
2722 
2723 	for (i = 0; i < chunk->count; i++) {
2724 	    int x1 = _cairo_fixed_integer_ceil (box[i].p1.x);
2725 	    int y1 = _cairo_fixed_integer_ceil (box[i].p1.y);
2726 	    int x2 = _cairo_fixed_integer_floor (box[i].p2.x);
2727 	    int y2 = _cairo_fixed_integer_floor (box[i].p2.y);
2728 
2729 	    x1 = (x1 < 0 ? 0 : x1);
2730 	    y1 = (y1 < 0 ? 0 : y1);
2731 	    if (x2 > x1 && y2 > y1) {
2732 		cairo_box_t b;
2733 
2734 		pixman_fill ((uint32_t *) dst->data,
2735 			     dst->stride / sizeof (uint32_t),
2736 			     PIXMAN_FORMAT_BPP (dst->pixman_format),
2737 			     x1, y1, x2 - x1, y2 - y1,
2738 			     pixel);
2739 
2740 		/* top */
2741 		if (! _cairo_fixed_is_integer (box[i].p1.y)) {
2742 		    b.p1.x = box[i].p1.x;
2743 		    b.p1.y = box[i].p1.y;
2744 		    b.p2.x = box[i].p2.x;
2745 		    b.p2.y = _cairo_fixed_from_int (y1);
2746 
2747 		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
2748 		    if (unlikely (status))
2749 			goto CLEANUP_CONVERTER;
2750 		}
2751 
2752 		/* left */
2753 		if (! _cairo_fixed_is_integer (box[i].p1.x)) {
2754 		    b.p1.x = box[i].p1.x;
2755 		    b.p1.y = box[i].p1.y;
2756 		    b.p2.x = _cairo_fixed_from_int (x1);
2757 		    b.p2.y = box[i].p2.y;
2758 
2759 		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
2760 		    if (unlikely (status))
2761 			goto CLEANUP_CONVERTER;
2762 		}
2763 
2764 		/* right */
2765 		if (! _cairo_fixed_is_integer (box[i].p2.x)) {
2766 		    b.p1.x = _cairo_fixed_from_int (x2);
2767 		    b.p1.y = box[i].p1.y;
2768 		    b.p2.x = box[i].p2.x;
2769 		    b.p2.y = box[i].p2.y;
2770 
2771 		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
2772 		    if (unlikely (status))
2773 			goto CLEANUP_CONVERTER;
2774 		}
2775 
2776 		/* bottom */
2777 		if (! _cairo_fixed_is_integer (box[i].p2.y)) {
2778 		    b.p1.x = box[i].p1.x;
2779 		    b.p1.y = _cairo_fixed_from_int (y2);
2780 		    b.p2.x = box[i].p2.x;
2781 		    b.p2.y = box[i].p2.y;
2782 
2783 		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
2784 		    if (unlikely (status))
2785 			goto CLEANUP_CONVERTER;
2786 		}
2787 	    } else {
2788 		status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
2789 		if (unlikely (status))
2790 		    goto CLEANUP_CONVERTER;
2791 	    }
2792 	}
2793     }
2794 
2795     status = converter.base.generate (&converter.base, &renderer.base);
2796 
2797   CLEANUP_CONVERTER:
2798     converter.base.destroy (&converter.base);
2799     pixman_image_unref (renderer.src);
2800   CLEANUP_MASK:
2801     pixman_image_unref (renderer.mask);
2802 
2803     return status;
2804 }
2805 
2806 typedef struct _cairo_image_surface_span_renderer {
2807     cairo_span_renderer_t base;
2808 
2809     uint8_t *mask_data;
2810     uint32_t mask_stride;
2811 } cairo_image_surface_span_renderer_t;
2812 
2813 cairo_status_t
_cairo_image_surface_span(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * spans,unsigned num_spans)2814 _cairo_image_surface_span (void *abstract_renderer,
2815 			   int y, int height,
2816 			   const cairo_half_open_span_t *spans,
2817 			   unsigned num_spans)
2818 {
2819     cairo_image_surface_span_renderer_t *renderer = abstract_renderer;
2820     uint8_t *row;
2821     unsigned i;
2822 
2823     if (num_spans == 0)
2824 	return CAIRO_STATUS_SUCCESS;
2825 
2826     /* XXX will it be quicker to repeat the sparse memset,
2827      * or perform a simpler memcpy?
2828      * The fairly dense spiral benchmarks suggests that the sparse
2829      * memset is a win there as well.
2830      */
2831     row = renderer->mask_data + y * renderer->mask_stride;
2832     do {
2833 	for (i = 0; i < num_spans - 1; i++) {
2834 	    if (! spans[i].coverage)
2835 		continue;
2836 
2837 	    /* We implement setting rendering the most common single
2838 	     * pixel wide span case to avoid the overhead of a memset
2839 	     * call.  Open coding setting longer spans didn't show a
2840 	     * noticeable improvement over memset. */
2841 	    if (spans[i+1].x == spans[i].x + 1) {
2842 		row[spans[i].x] = spans[i].coverage;
2843 	    } else {
2844 		memset (row + spans[i].x,
2845 			spans[i].coverage,
2846 			spans[i+1].x - spans[i].x);
2847 	    }
2848 	}
2849 	row += renderer->mask_stride;
2850     } while (--height);
2851 
2852     return CAIRO_STATUS_SUCCESS;
2853 }
2854 
2855 static cairo_status_t
_composite_unaligned_boxes(cairo_image_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * pattern,const cairo_boxes_t * boxes,const cairo_composite_rectangles_t * extents)2856 _composite_unaligned_boxes (cairo_image_surface_t *dst,
2857 			    cairo_operator_t op,
2858 			    const cairo_pattern_t *pattern,
2859 			    const cairo_boxes_t *boxes,
2860 			    const cairo_composite_rectangles_t *extents)
2861 {
2862     uint8_t buf[CAIRO_STACK_BUFFER_SIZE];
2863     cairo_image_surface_span_renderer_t renderer;
2864     cairo_rectangular_scan_converter_t converter;
2865     pixman_image_t *mask, *src;
2866     cairo_status_t status;
2867     const struct _cairo_boxes_chunk *chunk;
2868     int i, src_x, src_y;
2869 
2870     i = CAIRO_STRIDE_FOR_WIDTH_BPP (extents->bounded.width, 8) * extents->bounded.height;
2871     if ((unsigned) i <= sizeof (buf)) {
2872 	mask = pixman_image_create_bits (PIXMAN_a8,
2873 					 extents->bounded.width,
2874 					 extents->bounded.height,
2875 					 (uint32_t *) buf,
2876 					 CAIRO_STRIDE_FOR_WIDTH_BPP (extents->bounded.width, 8));
2877 	memset (buf, 0, i);
2878     } else {
2879 	mask = pixman_image_create_bits (PIXMAN_a8,
2880 					 extents->bounded.width,
2881 					 extents->bounded.height,
2882 					 NULL,  0);
2883     }
2884     if (unlikely (mask == NULL))
2885 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2886 
2887     renderer.base.render_rows = _cairo_image_surface_span;
2888     renderer.mask_stride = pixman_image_get_stride (mask);
2889     renderer.mask_data = (uint8_t *) pixman_image_get_data (mask);
2890     renderer.mask_data -= extents->bounded.y * renderer.mask_stride + extents->bounded.x;
2891 
2892     _cairo_rectangular_scan_converter_init (&converter, &extents->bounded);
2893 
2894     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2895 	const cairo_box_t *box = chunk->base;
2896 
2897 	for (i = 0; i < chunk->count; i++) {
2898 	    status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
2899 	    if (unlikely (status))
2900 		goto CLEANUP;
2901 	}
2902     }
2903 
2904     status = converter.base.generate (&converter.base, &renderer.base);
2905     if (unlikely (status))
2906 	goto CLEANUP;
2907 
2908     src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &src_x, &src_y);
2909     if (unlikely (src == NULL)) {
2910 	status =  _cairo_error (CAIRO_STATUS_NO_MEMORY);
2911 	goto CLEANUP;
2912     }
2913 
2914     pixman_image_composite32 (_pixman_operator (op),
2915                               src, mask, dst->pixman_image,
2916                               extents->bounded.x + src_x, extents->bounded.y + src_y,
2917                               0, 0,
2918                               extents->bounded.x, extents->bounded.y,
2919                               extents->bounded.width, extents->bounded.height);
2920     pixman_image_unref (src);
2921 
2922   CLEANUP:
2923     converter.base.destroy (&converter.base);
2924     pixman_image_unref (mask);
2925 
2926     return status;
2927 }
2928 
2929 static cairo_status_t
_composite_boxes(cairo_image_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * pattern,cairo_boxes_t * boxes,cairo_antialias_t antialias,cairo_clip_t * clip,const cairo_composite_rectangles_t * extents)2930 _composite_boxes (cairo_image_surface_t *dst,
2931 		  cairo_operator_t op,
2932 		  const cairo_pattern_t *pattern,
2933 		  cairo_boxes_t *boxes,
2934 		  cairo_antialias_t antialias,
2935 		  cairo_clip_t *clip,
2936 		  const cairo_composite_rectangles_t *extents)
2937 {
2938     cairo_region_t *clip_region = NULL;
2939     cairo_bool_t need_clip_mask = FALSE;
2940     cairo_status_t status;
2941     struct _cairo_boxes_chunk *chunk;
2942     uint32_t pixel;
2943     int i;
2944 
2945     if (clip != NULL) {
2946 	status = _cairo_clip_get_region (clip, &clip_region);
2947 	if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
2948 	    return CAIRO_STATUS_SUCCESS;
2949 	need_clip_mask = status == CAIRO_INT_STATUS_UNSUPPORTED;
2950 	if (need_clip_mask &&
2951 	    (op == CAIRO_OPERATOR_SOURCE || ! extents->is_bounded))
2952 	{
2953 	    return CAIRO_INT_STATUS_UNSUPPORTED;
2954 	}
2955 
2956 	if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
2957 	    clip_region = NULL;
2958     }
2959 
2960     if (antialias != CAIRO_ANTIALIAS_NONE) {
2961 	if (! boxes->is_pixel_aligned) {
2962 	    if (need_clip_mask)
2963 		return CAIRO_INT_STATUS_UNSUPPORTED;
2964 
2965 	    if (pattern_to_pixel ((cairo_solid_pattern_t *) pattern, op,
2966 				  dst->pixman_format, &pixel))
2967 	    {
2968 		return _fill_unaligned_boxes (dst, pattern, pixel, boxes, extents);
2969 	    }
2970 	    else
2971 	    {
2972 		return _composite_unaligned_boxes (dst, op, pattern, boxes, extents);
2973 	    }
2974 	}
2975     }
2976 
2977     status = CAIRO_STATUS_SUCCESS;
2978     if (! need_clip_mask &&
2979 	pattern_to_pixel ((cairo_solid_pattern_t *) pattern, op, dst->pixman_format,
2980 			  &pixel))
2981     {
2982 	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2983 	    cairo_box_t *box = chunk->base;
2984 
2985 	    for (i = 0; i < chunk->count; i++) {
2986 		int x1 = _cairo_fixed_integer_round_down (box[i].p1.x);
2987 		int y1 = _cairo_fixed_integer_round_down (box[i].p1.y);
2988 		int x2 = _cairo_fixed_integer_round_down (box[i].p2.x);
2989 		int y2 = _cairo_fixed_integer_round_down (box[i].p2.y);
2990 
2991 		x1 = (x1 < 0 ? 0 : x1);
2992 		y1 = (y1 < 0 ? 0 : y1);
2993 		if (x2 <= x1 || y2 <= y1)
2994 		    continue;
2995 
2996 		pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
2997 			     PIXMAN_FORMAT_BPP (dst->pixman_format),
2998 			     x1, y1, x2 - x1, y2 - y1,
2999 			     pixel);
3000 	    }
3001 	}
3002     }
3003     else
3004     {
3005 	pixman_image_t *src = NULL, *mask = NULL;
3006 	int src_x, src_y, mask_x = 0, mask_y = 0;
3007 	pixman_op_t pixman_op = _pixman_operator (op);
3008 
3009 	if (need_clip_mask) {
3010 	    cairo_surface_t *clip_surface;
3011 	    int clip_x, clip_y;
3012 
3013 	    clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
3014 	    if (unlikely (clip_surface->status))
3015 		return clip_surface->status;
3016 
3017 	    mask_x = -clip_x;
3018 	    mask_y = -clip_y;
3019 
3020 	    if (op == CAIRO_OPERATOR_CLEAR) {
3021 		pattern = NULL;
3022 		pixman_op = PIXMAN_OP_OUT_REVERSE;
3023 	    }
3024 
3025 	    mask = ((cairo_image_surface_t *) clip_surface)->pixman_image;
3026 	}
3027 
3028 	if (pattern != NULL) {
3029 	    src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &src_x, &src_y);
3030 	    if (unlikely (src == NULL))
3031 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3032 	} else {
3033 	    src = mask;
3034 	    src_x = mask_x;
3035 	    src_y = mask_y;
3036 	    mask = NULL;
3037 	}
3038 
3039 	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
3040 	    const cairo_box_t *box = chunk->base;
3041 
3042 	    for (i = 0; i < chunk->count; i++) {
3043 		int x1 = _cairo_fixed_integer_round_down (box[i].p1.x);
3044 		int y1 = _cairo_fixed_integer_round_down (box[i].p1.y);
3045 		int x2 = _cairo_fixed_integer_round_down (box[i].p2.x);
3046 		int y2 = _cairo_fixed_integer_round_down (box[i].p2.y);
3047 
3048 		if (x2 == x1 || y2 == y1)
3049 		    continue;
3050 
3051 		pixman_image_composite32 (pixman_op,
3052                                           src, mask, dst->pixman_image,
3053                                           x1 + src_x,  y1 + src_y,
3054                                           x1 + mask_x, y1 + mask_y,
3055                                           x1, y1,
3056                                           x2 - x1, y2 - y1);
3057 	    }
3058 	}
3059 
3060 	if (pattern != NULL)
3061 	    pixman_image_unref (src);
3062 
3063 	if (! extents->is_bounded) {
3064 	    status =
3065 		_cairo_image_surface_fixup_unbounded_boxes (dst, extents,
3066 							    clip_region, boxes);
3067 	}
3068     }
3069 
3070     return status;
3071 }
3072 
3073 static cairo_status_t
_clip_and_composite_boxes(cairo_image_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * src,cairo_boxes_t * boxes,cairo_antialias_t antialias,cairo_composite_rectangles_t * extents,cairo_clip_t * clip)3074 _clip_and_composite_boxes (cairo_image_surface_t *dst,
3075 			   cairo_operator_t op,
3076 			   const cairo_pattern_t *src,
3077 			   cairo_boxes_t *boxes,
3078 			   cairo_antialias_t antialias,
3079 			   cairo_composite_rectangles_t *extents,
3080 			   cairo_clip_t *clip)
3081 {
3082     cairo_traps_t traps;
3083     cairo_status_t status;
3084     composite_traps_info_t info;
3085 
3086     if (boxes->num_boxes == 0 && extents->is_bounded)
3087 	return CAIRO_STATUS_SUCCESS;
3088 
3089     /* Use a fast path if the boxes are pixel aligned */
3090     status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents);
3091     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3092 	return status;
3093 
3094     /* Otherwise render via a mask and composite in the usual fashion.  */
3095     status = _cairo_traps_init_boxes (&traps, boxes);
3096     if (unlikely (status))
3097 	return status;
3098 
3099     info.num_traps = traps.num_traps;
3100     info.traps = traps.traps;
3101     info.antialias = antialias;
3102     status = _clip_and_composite (dst, op, src,
3103 				  _composite_traps, &info,
3104 				  extents, clip);
3105 
3106     _cairo_traps_fini (&traps);
3107     return status;
3108 }
3109 
3110 static cairo_bool_t
_mono_edge_is_vertical(const cairo_line_t * line)3111 _mono_edge_is_vertical (const cairo_line_t *line)
3112 {
3113     return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
3114 }
3115 
3116 static cairo_bool_t
_traps_are_pixel_aligned(cairo_traps_t * traps,cairo_antialias_t antialias)3117 _traps_are_pixel_aligned (cairo_traps_t *traps,
3118 			  cairo_antialias_t antialias)
3119 {
3120     int i;
3121 
3122     if (antialias == CAIRO_ANTIALIAS_NONE) {
3123 	for (i = 0; i < traps->num_traps; i++) {
3124 	    if (! _mono_edge_is_vertical (&traps->traps[i].left)   ||
3125 		! _mono_edge_is_vertical (&traps->traps[i].right))
3126 	    {
3127 		traps->maybe_region = FALSE;
3128 		return FALSE;
3129 	    }
3130 	}
3131     } else {
3132 	for (i = 0; i < traps->num_traps; i++) {
3133 	    if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
3134 		traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
3135 		! _cairo_fixed_is_integer (traps->traps[i].top)          ||
3136 		! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
3137 		! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
3138 		! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
3139 	    {
3140 		traps->maybe_region = FALSE;
3141 		return FALSE;
3142 	    }
3143 	}
3144     }
3145 
3146     return TRUE;
3147 }
3148 
3149 static void
_boxes_for_traps(cairo_boxes_t * boxes,cairo_traps_t * traps,cairo_antialias_t antialias)3150 _boxes_for_traps (cairo_boxes_t *boxes,
3151 		  cairo_traps_t *traps,
3152 		  cairo_antialias_t antialias)
3153 {
3154     int i;
3155 
3156     _cairo_boxes_init (boxes);
3157 
3158     boxes->num_boxes    = traps->num_traps;
3159     boxes->chunks.base  = (cairo_box_t *) traps->traps;
3160     boxes->chunks.count = traps->num_traps;
3161     boxes->chunks.size  = traps->num_traps;
3162 
3163     if (antialias != CAIRO_ANTIALIAS_NONE) {
3164 	for (i = 0; i < traps->num_traps; i++) {
3165 	    /* Note the traps and boxes alias so we need to take the local copies first. */
3166 	    cairo_fixed_t x1 = traps->traps[i].left.p1.x;
3167 	    cairo_fixed_t x2 = traps->traps[i].right.p1.x;
3168 	    cairo_fixed_t y1 = traps->traps[i].top;
3169 	    cairo_fixed_t y2 = traps->traps[i].bottom;
3170 
3171 	    boxes->chunks.base[i].p1.x = x1;
3172 	    boxes->chunks.base[i].p1.y = y1;
3173 	    boxes->chunks.base[i].p2.x = x2;
3174 	    boxes->chunks.base[i].p2.y = y2;
3175 
3176 	    if (boxes->is_pixel_aligned) {
3177 		boxes->is_pixel_aligned =
3178 		    _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
3179 		    _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
3180 	    }
3181 	}
3182     } else {
3183 	boxes->is_pixel_aligned = TRUE;
3184 
3185 	for (i = 0; i < traps->num_traps; i++) {
3186 	    /* Note the traps and boxes alias so we need to take the local copies first. */
3187 	    cairo_fixed_t x1 = traps->traps[i].left.p1.x;
3188 	    cairo_fixed_t x2 = traps->traps[i].right.p1.x;
3189 	    cairo_fixed_t y1 = traps->traps[i].top;
3190 	    cairo_fixed_t y2 = traps->traps[i].bottom;
3191 
3192 	    /* round down here to match Pixman's behavior when using traps. */
3193 	    boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
3194 	    boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
3195 	    boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
3196 	    boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
3197 	}
3198     }
3199 }
3200 
3201 static cairo_status_t
_clip_and_composite_trapezoids(cairo_image_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * src,cairo_traps_t * traps,cairo_antialias_t antialias,cairo_composite_rectangles_t * extents,cairo_clip_t * clip)3202 _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
3203 				cairo_operator_t op,
3204 				const cairo_pattern_t *src,
3205 				cairo_traps_t *traps,
3206 				cairo_antialias_t antialias,
3207 				cairo_composite_rectangles_t *extents,
3208 				cairo_clip_t *clip)
3209 {
3210     composite_traps_info_t info;
3211     cairo_bool_t need_clip_surface = FALSE;
3212     cairo_status_t status;
3213 
3214     if (traps->num_traps == 0 && extents->is_bounded)
3215 	return CAIRO_STATUS_SUCCESS;
3216 
3217     if (clip != NULL) {
3218 	cairo_region_t *clip_region;
3219 
3220 	status = _cairo_clip_get_region (clip, &clip_region);
3221 	need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
3222     }
3223 
3224     if (traps->has_intersections) {
3225 	if (traps->is_rectangular)
3226 	    status = _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, CAIRO_FILL_RULE_WINDING);
3227 	else if (traps->is_rectilinear)
3228 	    status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, CAIRO_FILL_RULE_WINDING);
3229 	else
3230 	    status = _cairo_bentley_ottmann_tessellate_traps (traps, CAIRO_FILL_RULE_WINDING);
3231 	if (unlikely (status))
3232 	    return status;
3233     }
3234 
3235     /* Use a fast path if the trapezoids consist of a simple region,
3236      * but we can only do this if we do not have a clip surface, or can
3237      * substitute the mask with the clip.
3238      */
3239     if (traps->maybe_region && _traps_are_pixel_aligned (traps, antialias) &&
3240 	(! need_clip_surface ||
3241 	 (extents->is_bounded && op != CAIRO_OPERATOR_SOURCE)))
3242     {
3243 	cairo_boxes_t boxes;
3244 
3245 	_boxes_for_traps (&boxes, traps, antialias);
3246 	return _clip_and_composite_boxes (dst, op, src,
3247 					  &boxes, antialias,
3248 					  extents, clip);
3249     }
3250 
3251     /* No fast path, exclude self-intersections and clip trapezoids. */
3252     /* Otherwise render the trapezoids to a mask and composite in the usual
3253      * fashion.
3254      */
3255     info.traps = traps->traps;
3256     info.num_traps = traps->num_traps;
3257     info.antialias = antialias;
3258     return _clip_and_composite (dst, op, src,
3259 				_composite_traps, &info,
3260 				extents, clip);
3261 }
3262 
3263 static cairo_clip_path_t *
_clip_get_single_path(cairo_clip_t * clip)3264 _clip_get_single_path (cairo_clip_t *clip)
3265 {
3266     if (clip->path->prev == NULL)
3267       return clip->path;
3268 
3269     return NULL;
3270 }
3271 
3272 /* high level image interface */
3273 
3274 static cairo_int_status_t
_cairo_image_surface_paint(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_clip_t * clip)3275 _cairo_image_surface_paint (void			*abstract_surface,
3276 			    cairo_operator_t		 op,
3277 			    const cairo_pattern_t	*source,
3278 			    cairo_clip_t		*clip)
3279 {
3280     cairo_image_surface_t *surface = abstract_surface;
3281     cairo_composite_rectangles_t extents;
3282     cairo_clip_path_t *clip_path;
3283     cairo_clip_t local_clip;
3284     cairo_bool_t have_clip = FALSE;
3285     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
3286     int num_boxes = ARRAY_LENGTH (boxes_stack);
3287     cairo_status_t status;
3288 
3289     cairo_rectangle_int_t rect;
3290     rect.x = rect.y = 0;
3291     rect.width = surface->width;
3292     rect.height = surface->height;
3293 
3294     status = _cairo_composite_rectangles_init_for_paint (&extents,
3295 							 &rect,
3296 							 op, source,
3297 							 clip);
3298     if (unlikely (status))
3299 	return status;
3300 
3301     if (_cairo_clip_contains_extents (clip, &extents))
3302 	clip = NULL;
3303 
3304     if (clip != NULL) {
3305 	clip = _cairo_clip_init_copy (&local_clip, clip);
3306 	have_clip = TRUE;
3307     }
3308 
3309     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
3310     if (unlikely (status)) {
3311 	if (have_clip)
3312 	    _cairo_clip_fini (&local_clip);
3313 
3314 	return status;
3315     }
3316 
3317     /* If the clip cannot be reduced to a set of boxes, we will need to
3318      * use a clipmask. Paint is special as it is the only operation that
3319      * does not implicitly use a mask, so we may be able to reduce this
3320      * operation to a fill...
3321      */
3322     if (clip != NULL &&
3323 	extents.is_bounded &&
3324 	(clip_path = _clip_get_single_path (clip)) != NULL)
3325     {
3326 	status = _cairo_image_surface_fill (surface, op, source,
3327 					    &clip_path->path,
3328 					    clip_path->fill_rule,
3329 					    clip_path->tolerance,
3330 					    clip_path->antialias,
3331 					    NULL);
3332     }
3333     else
3334     {
3335 	cairo_boxes_t boxes;
3336 
3337 	_cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
3338 	status = _clip_and_composite_boxes (surface, op, source,
3339 					    &boxes, CAIRO_ANTIALIAS_DEFAULT,
3340 					    &extents, clip);
3341     }
3342 
3343     if (clip_boxes != boxes_stack)
3344 	free (clip_boxes);
3345 
3346     if (have_clip)
3347 	_cairo_clip_fini (&local_clip);
3348 
3349     return status;
3350 }
3351 
3352 static cairo_status_t
_composite_mask(void * closure,pixman_image_t * dst,pixman_format_code_t dst_format,cairo_operator_t op,const cairo_pattern_t * src_pattern,int dst_x,int dst_y,const cairo_rectangle_int_t * extents,cairo_region_t * clip_region)3353 _composite_mask (void				*closure,
3354 		 pixman_image_t			*dst,
3355 		 pixman_format_code_t		 dst_format,
3356 		 cairo_operator_t		 op,
3357 		 const cairo_pattern_t		*src_pattern,
3358 		 int				 dst_x,
3359 		 int				 dst_y,
3360 		 const cairo_rectangle_int_t	*extents,
3361 		 cairo_region_t			*clip_region)
3362 {
3363     const cairo_pattern_t *mask_pattern = closure;
3364     pixman_image_t *src, *mask = NULL;
3365     int src_x = 0, src_y = 0;
3366     int mask_x = 0, mask_y = 0;
3367 
3368     if (src_pattern != NULL) {
3369 	src = _pixman_image_for_pattern (src_pattern, FALSE, extents, &src_x, &src_y);
3370 	if (unlikely (src == NULL))
3371 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3372 
3373 	mask = _pixman_image_for_pattern (mask_pattern, TRUE, extents, &mask_x, &mask_y);
3374 	if (unlikely (mask == NULL)) {
3375 	    pixman_image_unref (src);
3376 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3377 	}
3378 
3379 	if (mask_pattern->has_component_alpha)
3380 	    pixman_image_set_component_alpha (mask, TRUE);
3381     } else {
3382 	src = _pixman_image_for_pattern (mask_pattern, FALSE, extents, &src_x, &src_y);
3383 	if (unlikely (src == NULL))
3384 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3385     }
3386 
3387     pixman_image_composite32 (_pixman_operator (op), src, mask, dst,
3388                               extents->x + src_x,  extents->y + src_y,
3389                               extents->x + mask_x, extents->y + mask_y,
3390                               extents->x - dst_x,  extents->y - dst_y,
3391                               extents->width,      extents->height);
3392 
3393     if (mask != NULL)
3394 	pixman_image_unref (mask);
3395     pixman_image_unref (src);
3396 
3397     return CAIRO_STATUS_SUCCESS;
3398 }
3399 
3400 static 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,cairo_clip_t * clip)3401 _cairo_image_surface_mask (void				*abstract_surface,
3402 			   cairo_operator_t		 op,
3403 			   const cairo_pattern_t	*source,
3404 			   const cairo_pattern_t	*mask,
3405 			   cairo_clip_t			*clip)
3406 {
3407     cairo_image_surface_t *surface = abstract_surface;
3408     cairo_composite_rectangles_t extents;
3409     cairo_clip_t local_clip;
3410     cairo_bool_t have_clip = FALSE;
3411     cairo_status_t status;
3412 
3413     cairo_rectangle_int_t rect;
3414     rect.x = rect.y = 0;
3415     rect.width = surface->width;
3416     rect.height = surface->height;
3417 
3418     status = _cairo_composite_rectangles_init_for_mask (&extents,
3419 							&rect,
3420 							op, source, mask, clip);
3421     if (unlikely (status))
3422 	return status;
3423 
3424     if (_cairo_clip_contains_extents (clip, &extents))
3425 	clip = NULL;
3426 
3427     if (clip != NULL && extents.is_bounded) {
3428 	clip = _cairo_clip_init_copy (&local_clip, clip);
3429 	status = _cairo_clip_rectangle (clip, &extents.bounded);
3430 	if (unlikely (status)) {
3431 	    _cairo_clip_fini (&local_clip);
3432 	    return status;
3433 	}
3434 
3435 	have_clip = TRUE;
3436     }
3437 
3438     status = _clip_and_composite (surface, op, source,
3439 				  _composite_mask, (void *) mask,
3440 				  &extents, clip);
3441 
3442     if (have_clip)
3443 	_cairo_clip_fini (&local_clip);
3444 
3445     return status;
3446 }
3447 
3448 typedef struct {
3449     cairo_polygon_t		*polygon;
3450     cairo_fill_rule_t		 fill_rule;
3451     cairo_antialias_t		 antialias;
3452 } composite_spans_info_t;
3453 
3454 //#define USE_BOTOR_SCAN_CONVERTER
3455 static cairo_status_t
_composite_spans(void * closure,pixman_image_t * dst,pixman_format_code_t dst_format,cairo_operator_t op,const cairo_pattern_t * pattern,int dst_x,int dst_y,const cairo_rectangle_int_t * extents,cairo_region_t * clip_region)3456 _composite_spans (void                          *closure,
3457 		  pixman_image_t		*dst,
3458 		  pixman_format_code_t		 dst_format,
3459 		  cairo_operator_t               op,
3460 		  const cairo_pattern_t         *pattern,
3461 		  int                            dst_x,
3462 		  int                            dst_y,
3463 		  const cairo_rectangle_int_t   *extents,
3464 		  cairo_region_t		*clip_region)
3465 {
3466     uint8_t mask_buf[CAIRO_STACK_BUFFER_SIZE];
3467     composite_spans_info_t *info = closure;
3468     cairo_image_surface_span_renderer_t renderer;
3469 #if USE_BOTOR_SCAN_CONVERTER
3470     cairo_box_t box;
3471     cairo_botor_scan_converter_t converter;
3472 #else
3473     cairo_scan_converter_t *converter;
3474 #endif
3475     pixman_image_t *mask;
3476     cairo_status_t status;
3477 
3478 #if USE_BOTOR_SCAN_CONVERTER
3479     box.p1.x = _cairo_fixed_from_int (extents->x);
3480     box.p1.y = _cairo_fixed_from_int (extents->y);
3481     box.p2.x = _cairo_fixed_from_int (extents->x + extents->width);
3482     box.p2.y = _cairo_fixed_from_int (extents->y + extents->height);
3483     _cairo_botor_scan_converter_init (&converter, &box, info->fill_rule);
3484     status = converter.base.add_polygon (&converter.base, info->polygon);
3485 #else
3486     converter = _cairo_tor_scan_converter_create (extents->x, extents->y,
3487 						  extents->x + extents->width,
3488 						  extents->y + extents->height,
3489 						  info->fill_rule);
3490     status = converter->add_polygon (converter, info->polygon);
3491 #endif
3492     if (unlikely (status))
3493 	goto CLEANUP_CONVERTER;
3494 
3495     /* TODO: support rendering to A1 surfaces (or: go add span
3496      * compositing to pixman.) */
3497 
3498     if (pattern == NULL &&
3499 	dst_format == PIXMAN_a8 &&
3500 	op == CAIRO_OPERATOR_SOURCE)
3501     {
3502 	mask = dst;
3503 	dst = NULL;
3504     }
3505     else
3506     {
3507 	int stride = CAIRO_STRIDE_FOR_WIDTH_BPP (extents->width, 8);
3508 	uint8_t *data = mask_buf;
3509 
3510 	if (extents->height * stride <= (int) sizeof (mask_buf))
3511 	    memset (data, 0, extents->height * stride);
3512 	else
3513 	    data = NULL, stride = 0;
3514 
3515 	mask = pixman_image_create_bits (PIXMAN_a8,
3516 					 extents->width,
3517 					 extents->height,
3518 					 (uint32_t *) data,
3519 					 stride);
3520 	if (unlikely (mask == NULL)) {
3521 	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3522 	    goto CLEANUP_CONVERTER;
3523 	}
3524     }
3525 
3526     renderer.base.render_rows = _cairo_image_surface_span;
3527     renderer.mask_stride = pixman_image_get_stride (mask);
3528     renderer.mask_data = (uint8_t *) pixman_image_get_data (mask);
3529     if (dst != NULL)
3530 	renderer.mask_data -= extents->y * renderer.mask_stride + extents->x;
3531     else
3532 	renderer.mask_data -= dst_y * renderer.mask_stride + dst_x;
3533 
3534 #if USE_BOTOR_SCAN_CONVERTER
3535     status = converter.base.generate (&converter.base, &renderer.base);
3536 #else
3537     status = converter->generate (converter, &renderer.base);
3538 #endif
3539     if (unlikely (status))
3540 	goto CLEANUP_RENDERER;
3541 
3542     if (dst != NULL) {
3543 	pixman_image_t *src;
3544 	int src_x, src_y;
3545 
3546 	src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
3547 	if (unlikely (src == NULL)) {
3548 	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3549 	    goto CLEANUP_RENDERER;
3550 	}
3551 
3552 	pixman_image_composite32 (_pixman_operator (op), src, mask, dst,
3553                                   extents->x + src_x, extents->y + src_y,
3554                                   0, 0, /* mask.x, mask.y */
3555                                   extents->x - dst_x, extents->y - dst_y,
3556                                   extents->width, extents->height);
3557 	pixman_image_unref (src);
3558     }
3559 
3560  CLEANUP_RENDERER:
3561     if (dst != NULL)
3562 	pixman_image_unref (mask);
3563  CLEANUP_CONVERTER:
3564 #if USE_BOTOR_SCAN_CONVERTER
3565     converter.base.destroy (&converter.base);
3566 #else
3567     converter->destroy (converter);
3568 #endif
3569     return status;
3570 }
3571 
3572 static cairo_status_t
_clip_and_composite_polygon(cairo_image_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * src,cairo_polygon_t * polygon,cairo_fill_rule_t fill_rule,cairo_antialias_t antialias,cairo_composite_rectangles_t * extents,cairo_clip_t * clip)3573 _clip_and_composite_polygon (cairo_image_surface_t *dst,
3574 			     cairo_operator_t op,
3575 			     const cairo_pattern_t *src,
3576 			     cairo_polygon_t *polygon,
3577 			     cairo_fill_rule_t fill_rule,
3578 			     cairo_antialias_t antialias,
3579 			     cairo_composite_rectangles_t *extents,
3580 			     cairo_clip_t *clip)
3581 {
3582     cairo_status_t status;
3583 
3584     if (polygon->num_edges == 0) {
3585 	cairo_traps_t traps;
3586 
3587 	if (extents->is_bounded)
3588 	    return CAIRO_STATUS_SUCCESS;
3589 
3590 	_cairo_traps_init (&traps);
3591 	status = _clip_and_composite_trapezoids (dst, op, src,
3592 						 &traps, antialias,
3593 						 extents, clip);
3594 	_cairo_traps_fini (&traps);
3595 
3596 	return status;
3597     }
3598 
3599     if (_cairo_operator_bounded_by_mask(op)) {
3600 	_cairo_box_round_to_rectangle (&polygon->extents, &extents->mask);
3601 	if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask))
3602 	    return CAIRO_STATUS_SUCCESS;
3603     }
3604 
3605     if (antialias != CAIRO_ANTIALIAS_NONE) {
3606 	composite_spans_info_t info;
3607 
3608 	info.polygon = polygon;
3609 	info.fill_rule = fill_rule;
3610 	info.antialias = antialias;
3611 
3612 	status = _clip_and_composite (dst, op, src,
3613 				      _composite_spans, &info,
3614 				      extents, clip);
3615     } else {
3616 	cairo_traps_t traps;
3617 
3618 	_cairo_traps_init (&traps);
3619 
3620 	/* Fall back to trapezoid fills. */
3621 	status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
3622 							    polygon,
3623 							    fill_rule);
3624 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3625 	    status = _clip_and_composite_trapezoids (dst, op, src,
3626 						     &traps, antialias,
3627 						     extents, clip);
3628 	}
3629 
3630 	_cairo_traps_fini (&traps);
3631     }
3632 
3633     return status;
3634 }
3635 
3636 static cairo_int_status_t
_cairo_image_surface_stroke(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,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,cairo_clip_t * clip)3637 _cairo_image_surface_stroke (void			*abstract_surface,
3638 			     cairo_operator_t		 op,
3639 			     const cairo_pattern_t	*source,
3640 			     cairo_path_fixed_t		*path,
3641 			     const cairo_stroke_style_t	*style,
3642 			     const cairo_matrix_t	*ctm,
3643 			     const cairo_matrix_t	*ctm_inverse,
3644 			     double			 tolerance,
3645 			     cairo_antialias_t		 antialias,
3646 			     cairo_clip_t		*clip)
3647 {
3648     cairo_image_surface_t *surface = abstract_surface;
3649     cairo_composite_rectangles_t extents;
3650     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
3651     int num_boxes = ARRAY_LENGTH (boxes_stack);
3652     cairo_clip_t local_clip;
3653     cairo_bool_t have_clip = FALSE;
3654     cairo_status_t status;
3655 
3656     cairo_rectangle_int_t rect;
3657     rect.x = rect.y = 0;
3658     rect.width = surface->width;
3659     rect.height = surface->height;
3660 
3661     status = _cairo_composite_rectangles_init_for_stroke (&extents,
3662 							  &rect,
3663 							  op, source,
3664 							  path, style, ctm,
3665 							  clip);
3666     if (unlikely (status))
3667 	return status;
3668 
3669     if (_cairo_clip_contains_extents (clip, &extents))
3670 	clip = NULL;
3671 
3672     if (clip != NULL) {
3673 	clip = _cairo_clip_init_copy (&local_clip, clip);
3674 	have_clip = TRUE;
3675     }
3676 
3677     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
3678     if (unlikely (status)) {
3679 	if (have_clip)
3680 	    _cairo_clip_fini (&local_clip);
3681 
3682 	return status;
3683     }
3684 
3685     status = CAIRO_INT_STATUS_UNSUPPORTED;
3686     if (path->is_rectilinear) {
3687 	cairo_boxes_t boxes;
3688 
3689 	_cairo_boxes_init (&boxes);
3690 	_cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
3691 
3692 	status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
3693 								style,
3694 								ctm,
3695 								&boxes);
3696 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3697 	    status = _clip_and_composite_boxes (surface, op, source,
3698 						&boxes, antialias,
3699 						&extents, clip);
3700 	}
3701 
3702 	_cairo_boxes_fini (&boxes);
3703     }
3704 
3705     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
3706 	cairo_polygon_t polygon;
3707 
3708 	_cairo_polygon_init (&polygon);
3709 	_cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
3710 
3711 	status = _cairo_path_fixed_stroke_to_polygon (path,
3712 						      style,
3713 						      ctm, ctm_inverse,
3714 						      tolerance,
3715 						      &polygon);
3716 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3717 	    status = _clip_and_composite_polygon (surface, op, source, &polygon,
3718 						  CAIRO_FILL_RULE_WINDING, antialias,
3719 						  &extents, clip);
3720 	}
3721 
3722 	_cairo_polygon_fini (&polygon);
3723     }
3724 
3725     if (clip_boxes != boxes_stack)
3726 	free (clip_boxes);
3727 
3728     if (have_clip)
3729 	_cairo_clip_fini (&local_clip);
3730 
3731     return status;
3732 }
3733 
3734 static cairo_int_status_t
_cairo_image_surface_fill(void * abstract_surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_path_fixed_t * path,cairo_fill_rule_t fill_rule,double tolerance,cairo_antialias_t antialias,cairo_clip_t * clip)3735 _cairo_image_surface_fill (void				*abstract_surface,
3736 			   cairo_operator_t		 op,
3737 			   const cairo_pattern_t	*source,
3738 			   cairo_path_fixed_t		*path,
3739 			   cairo_fill_rule_t		 fill_rule,
3740 			   double			 tolerance,
3741 			   cairo_antialias_t		 antialias,
3742 			   cairo_clip_t			*clip)
3743 {
3744     cairo_image_surface_t *surface = abstract_surface;
3745     cairo_composite_rectangles_t extents;
3746     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
3747     cairo_clip_t local_clip;
3748     cairo_bool_t have_clip = FALSE;
3749     int num_boxes = ARRAY_LENGTH (boxes_stack);
3750     cairo_status_t status;
3751 
3752     cairo_rectangle_int_t rect;
3753     rect.x = rect.y = 0;
3754     rect.width = surface->width;
3755     rect.height = surface->height;
3756 
3757     status = _cairo_composite_rectangles_init_for_fill (&extents,
3758 							&rect,
3759 							op, source, path,
3760 							clip);
3761     if (unlikely (status))
3762 	return status;
3763 
3764     if (_cairo_clip_contains_extents (clip, &extents))
3765 	clip = NULL;
3766 
3767     if (extents.is_bounded && clip != NULL) {
3768 	cairo_clip_path_t *clip_path;
3769 
3770 	if (((clip_path = _clip_get_single_path (clip)) != NULL) &&
3771 	    _cairo_path_fixed_equal (&clip_path->path, path))
3772 	{
3773 	    clip = NULL;
3774 	}
3775     }
3776 
3777     if (clip != NULL) {
3778 	clip = _cairo_clip_init_copy (&local_clip, clip);
3779 	have_clip = TRUE;
3780     }
3781 
3782     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
3783     if (unlikely (status)) {
3784 	if (have_clip)
3785 	    _cairo_clip_fini (&local_clip);
3786 
3787 	return status;
3788     }
3789 
3790     if (_cairo_path_fixed_is_rectilinear_fill (path)) {
3791 	cairo_boxes_t boxes;
3792 
3793 	_cairo_boxes_init (&boxes);
3794 	_cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
3795 
3796 	status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
3797 							      fill_rule,
3798 							      &boxes);
3799 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3800 	    status = _clip_and_composite_boxes (surface, op, source,
3801 						&boxes, antialias,
3802 						&extents, clip);
3803 	}
3804 
3805 	_cairo_boxes_fini (&boxes);
3806     } else {
3807 	cairo_polygon_t polygon;
3808 
3809 	assert (! path->is_empty_fill);
3810 
3811 	_cairo_polygon_init (&polygon);
3812 	_cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
3813 
3814 	status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
3815 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3816 	    status = _clip_and_composite_polygon (surface, op, source, &polygon,
3817 						  fill_rule, antialias,
3818 						  &extents, clip);
3819 	}
3820 
3821 	_cairo_polygon_fini (&polygon);
3822     }
3823 
3824     if (clip_boxes != boxes_stack)
3825 	free (clip_boxes);
3826 
3827     if (have_clip)
3828 	_cairo_clip_fini (&local_clip);
3829 
3830     return status;
3831 }
3832 
3833 typedef struct {
3834     cairo_scaled_font_t *font;
3835     cairo_glyph_t *glyphs;
3836     int num_glyphs;
3837 } composite_glyphs_info_t;
3838 
3839 static cairo_status_t
_composite_glyphs_via_mask(void * closure,pixman_image_t * dst,pixman_format_code_t dst_format,cairo_operator_t op,const cairo_pattern_t * pattern,int dst_x,int dst_y,const cairo_rectangle_int_t * extents,cairo_region_t * clip_region)3840 _composite_glyphs_via_mask (void			*closure,
3841 			    pixman_image_t		*dst,
3842 			    pixman_format_code_t	 dst_format,
3843 			    cairo_operator_t		 op,
3844 			    const cairo_pattern_t	*pattern,
3845 			    int				 dst_x,
3846 			    int				 dst_y,
3847 			    const cairo_rectangle_int_t	*extents,
3848 			    cairo_region_t		*clip_region)
3849 {
3850     composite_glyphs_info_t *info = closure;
3851     cairo_scaled_font_t *font = info->font;
3852     cairo_glyph_t *glyphs = info->glyphs;
3853     int num_glyphs = info->num_glyphs;
3854     pixman_image_t *mask = NULL;
3855     pixman_image_t *src;
3856     pixman_image_t *white;
3857     pixman_format_code_t mask_format = 0; /* silence gcc */
3858     cairo_status_t status;
3859     int src_x, src_y;
3860     int i;
3861 
3862     src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
3863     if (unlikely (src == NULL))
3864 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3865 
3866     white = _pixman_white_image ();
3867     if (unlikely (white == NULL)) {
3868 	pixman_image_unref (src);
3869 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3870     }
3871 
3872     _cairo_scaled_font_freeze_cache (font);
3873 
3874     for (i = 0; i < num_glyphs; i++) {
3875 	int x, y;
3876 	cairo_image_surface_t *glyph_surface;
3877 	cairo_scaled_glyph_t *scaled_glyph;
3878 
3879 	status = _cairo_scaled_glyph_lookup (font, glyphs[i].index,
3880 					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
3881 					     &scaled_glyph);
3882 
3883 	if (unlikely (status))
3884 	    goto CLEANUP;
3885 
3886 	glyph_surface = scaled_glyph->surface;
3887 
3888 	if (glyph_surface->width == 0 || glyph_surface->height == 0)
3889 	    continue;
3890 
3891 	/* To start, create the mask using the format from the first
3892 	 * glyph. Later we'll deal with different formats. */
3893 	if (mask == NULL) {
3894 	    mask_format = glyph_surface->pixman_format;
3895 	    mask = pixman_image_create_bits (mask_format,
3896 					     extents->width, extents->height,
3897 					     NULL, 0);
3898 	    if (unlikely (mask == NULL)) {
3899 		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3900 		goto CLEANUP;
3901 	    }
3902 
3903 	    if (PIXMAN_FORMAT_RGB (mask_format))
3904 		pixman_image_set_component_alpha (mask, TRUE);
3905 	}
3906 
3907 	/* If we have glyphs of different formats, we "upgrade" the mask
3908 	 * to the wider of the formats. */
3909 	if (glyph_surface->pixman_format != mask_format &&
3910 	    PIXMAN_FORMAT_BPP (mask_format) <
3911 	    PIXMAN_FORMAT_BPP (glyph_surface->pixman_format))
3912 	{
3913 	    pixman_image_t *new_mask;
3914 
3915 	    mask_format = glyph_surface->pixman_format;
3916 	    new_mask = pixman_image_create_bits (mask_format,
3917 						 extents->width, extents->height,
3918 						 NULL, 0);
3919 	    if (unlikely (new_mask == NULL)) {
3920 		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3921 		goto CLEANUP;
3922 	    }
3923 
3924 	    pixman_image_composite32 (PIXMAN_OP_SRC,
3925                                       white, mask, new_mask,
3926                                       0, 0, 0, 0, 0, 0,
3927                                       extents->width, extents->height);
3928 
3929 	    pixman_image_unref (mask);
3930 	    mask = new_mask;
3931 	    if (PIXMAN_FORMAT_RGB (mask_format))
3932 		pixman_image_set_component_alpha (mask, TRUE);
3933 	}
3934 
3935 	/* round glyph locations to the nearest pixel */
3936 	/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
3937 	x = _cairo_lround (glyphs[i].x -
3938 			   glyph_surface->base.device_transform.x0);
3939 	y = _cairo_lround (glyphs[i].y -
3940 			   glyph_surface->base.device_transform.y0);
3941 	if (glyph_surface->pixman_format == mask_format) {
3942 	    pixman_image_composite32 (PIXMAN_OP_ADD,
3943                                       glyph_surface->pixman_image, NULL, mask,
3944                                       0, 0, 0, 0,
3945                                       x - extents->x, y - extents->y,
3946                                       glyph_surface->width,
3947                                       glyph_surface->height);
3948 	} else {
3949 	    pixman_image_composite32 (PIXMAN_OP_ADD,
3950                                       white, glyph_surface->pixman_image, mask,
3951                                       0, 0, 0, 0,
3952                                       x - extents->x, y - extents->y,
3953                                       glyph_surface->width,
3954                                       glyph_surface->height);
3955 	}
3956     }
3957 
3958     pixman_image_composite32 (_pixman_operator (op),
3959                               src, mask, dst,
3960                               extents->x + src_x, extents->y + src_y,
3961                               0, 0,
3962                               extents->x - dst_x, extents->y - dst_y,
3963                               extents->width,     extents->height);
3964 
3965 CLEANUP:
3966     _cairo_scaled_font_thaw_cache (font);
3967     if (mask != NULL)
3968 	pixman_image_unref (mask);
3969     pixman_image_unref (src);
3970     pixman_image_unref (white);
3971 
3972     return status;
3973 }
3974 
3975 static cairo_status_t
_composite_glyphs(void * closure,pixman_image_t * dst,pixman_format_code_t dst_format,cairo_operator_t op,const cairo_pattern_t * pattern,int dst_x,int dst_y,const cairo_rectangle_int_t * extents,cairo_region_t * clip_region)3976 _composite_glyphs (void				*closure,
3977 		   pixman_image_t		*dst,
3978 		   pixman_format_code_t		 dst_format,
3979 		   cairo_operator_t		 op,
3980 		   const cairo_pattern_t	*pattern,
3981 		   int				 dst_x,
3982 		   int				 dst_y,
3983 		   const cairo_rectangle_int_t	*extents,
3984 		   cairo_region_t		*clip_region)
3985 {
3986     composite_glyphs_info_t *info = closure;
3987     cairo_scaled_glyph_t *glyph_cache[64];
3988     pixman_op_t pixman_op = _pixman_operator (op);
3989     pixman_image_t *src = NULL;
3990     int src_x = 0, src_y = 0;
3991     cairo_status_t status;
3992     int i;
3993 
3994     memset (glyph_cache, 0, sizeof (glyph_cache));
3995     status = CAIRO_STATUS_SUCCESS;
3996 
3997     _cairo_scaled_font_freeze_cache (info->font);
3998     for (i = 0; i < info->num_glyphs; i++) {
3999 	int x, y;
4000 	cairo_image_surface_t *glyph_surface;
4001 	cairo_scaled_glyph_t *scaled_glyph;
4002 	unsigned long glyph_index = info->glyphs[i].index;
4003 	int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
4004 
4005 	scaled_glyph = glyph_cache[cache_index];
4006 	if (scaled_glyph == NULL ||
4007 	    _cairo_scaled_glyph_index (scaled_glyph) != glyph_index)
4008 	{
4009 	    status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
4010 						 CAIRO_SCALED_GLYPH_INFO_SURFACE,
4011 						 &scaled_glyph);
4012 
4013 	    if (unlikely (status))
4014 		break;
4015 
4016 	    glyph_cache[cache_index] = scaled_glyph;
4017 	}
4018 
4019 	glyph_surface = scaled_glyph->surface;
4020 	if (glyph_surface->width && glyph_surface->height) {
4021 	    int x1, y1, x2, y2;
4022 
4023 	    /* round glyph locations to the nearest pixel */
4024 	    /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
4025 	    x = _cairo_lround (info->glyphs[i].x -
4026 			       glyph_surface->base.device_transform.x0);
4027 	    y = _cairo_lround (info->glyphs[i].y -
4028 			       glyph_surface->base.device_transform.y0);
4029 
4030 	    x1 = x;
4031 	    if (x1 < extents->x)
4032 		x1 = extents->x;
4033 	    x2 = x + glyph_surface->width;
4034 	    if (x2 > extents->x + extents->width)
4035 		x2 = extents->x + extents->width;
4036 
4037 	    y1 = y;
4038 	    if (y1 < extents->y)
4039 		y1 = extents->y;
4040 	    y2 = y + glyph_surface->height;
4041 	    if (y2 > extents->y + extents->height)
4042 		y2 = extents->y + extents->height;
4043 
4044 	    if (glyph_surface->format == CAIRO_FORMAT_A8 ||
4045 	        glyph_surface->format == CAIRO_FORMAT_A1 ||
4046 	        (glyph_surface->format == CAIRO_FORMAT_ARGB32 &&
4047 	         pixman_image_get_component_alpha (glyph_surface->pixman_image)))
4048 	    {
4049 		if (unlikely (src == NULL)) {
4050 		    if (pattern != NULL) {
4051 			src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
4052 			src_x -= dst_x;
4053 			src_y -= dst_y;
4054 		    } else {
4055 			src = _pixman_white_image ();
4056 		    }
4057 		    if (unlikely (src == NULL)) {
4058 			status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
4059 			break;
4060 		    }
4061 		}
4062 
4063 		pixman_image_composite32 (pixman_op,
4064 					  src, glyph_surface->pixman_image, dst,
4065 					  x1 + src_x, y1 + src_y,
4066 					  x1 - x, y1 - y,
4067 					  x1 - dst_x, y1 - dst_y,
4068 					  x2 - x1, y2 - y1);
4069 	    } else {
4070 		pixman_image_composite32 (pixman_op,
4071 					  glyph_surface->pixman_image, NULL, dst,
4072 					  x1 - x, y1 - y,
4073 					  0, 0,
4074 					  x1 - dst_x, y1 - dst_y,
4075 					  x2 - x1, y2 - y1);
4076 	    }
4077 	}
4078     }
4079     _cairo_scaled_font_thaw_cache (info->font);
4080 
4081     if (src != NULL)
4082 	pixman_image_unref (src);
4083 
4084     return status;
4085 }
4086 
4087 static 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,cairo_clip_t * clip,int * num_remaining)4088 _cairo_image_surface_glyphs (void			*abstract_surface,
4089 			     cairo_operator_t		 op,
4090 			     const cairo_pattern_t	*source,
4091 			     cairo_glyph_t		*glyphs,
4092 			     int			 num_glyphs,
4093 			     cairo_scaled_font_t	*scaled_font,
4094 			     cairo_clip_t		*clip,
4095 			     int *num_remaining)
4096 {
4097     cairo_image_surface_t *surface = abstract_surface;
4098     cairo_composite_rectangles_t extents;
4099     composite_glyphs_info_t glyph_info;
4100     cairo_clip_t local_clip;
4101     cairo_bool_t have_clip = FALSE;
4102 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
4103     // For performance reasons we don't want to use two passes for overlapping glyphs
4104     // on mobile
4105     cairo_bool_t overlap = FALSE;
4106 #else
4107     cairo_bool_t overlap;
4108 #endif
4109     cairo_status_t status;
4110 
4111     cairo_rectangle_int_t rect;
4112     rect.x = rect.y = 0;
4113     rect.width = surface->width;
4114     rect.height = surface->height;
4115 
4116     status = _cairo_composite_rectangles_init_for_glyphs (&extents,
4117 							  &rect,
4118 							  op, source,
4119 							  scaled_font,
4120 							  glyphs, num_glyphs,
4121 							  clip,
4122 #ifdef MOZ_GFX_OPTIMIZE_MOBILE
4123 							  NULL);
4124 #else
4125 							  &overlap);
4126 #endif
4127 
4128     if (unlikely (status))
4129 	return status;
4130 
4131     if (_cairo_clip_contains_rectangle (clip, &extents.mask))
4132 	clip = NULL;
4133 
4134     if (clip != NULL && extents.is_bounded) {
4135 	clip = _cairo_clip_init_copy (&local_clip, clip);
4136 	status = _cairo_clip_rectangle (clip, &extents.bounded);
4137 	if (unlikely (status))
4138 	    return status;
4139 
4140 	have_clip = TRUE;
4141     }
4142 
4143     glyph_info.font = scaled_font;
4144     glyph_info.glyphs = glyphs;
4145     glyph_info.num_glyphs = num_glyphs;
4146 
4147     status = _clip_and_composite (surface, op, source,
4148 				  overlap || extents.is_bounded == 0 ? _composite_glyphs_via_mask : _composite_glyphs,
4149 				  &glyph_info,
4150 				  &extents, clip);
4151 
4152     if (have_clip)
4153 	_cairo_clip_fini (&local_clip);
4154 
4155     *num_remaining = 0;
4156     return status;
4157 }
4158 
4159 static cairo_bool_t
_cairo_image_surface_get_extents(void * abstract_surface,cairo_rectangle_int_t * rectangle)4160 _cairo_image_surface_get_extents (void			  *abstract_surface,
4161 				  cairo_rectangle_int_t   *rectangle)
4162 {
4163     cairo_image_surface_t *surface = abstract_surface;
4164 
4165     rectangle->x = 0;
4166     rectangle->y = 0;
4167     rectangle->width  = surface->width;
4168     rectangle->height = surface->height;
4169 
4170     return TRUE;
4171 }
4172 
4173 static void
_cairo_image_surface_get_font_options(void * abstract_surface,cairo_font_options_t * options)4174 _cairo_image_surface_get_font_options (void                  *abstract_surface,
4175 				       cairo_font_options_t  *options)
4176 {
4177     _cairo_font_options_init_default (options);
4178 
4179     cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
4180     _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
4181 }
4182 
4183 /* legacy interface kept for compatibility until surface-fallback is removed */
4184 static cairo_status_t
_cairo_image_surface_acquire_dest_image(void * abstract_surface,cairo_rectangle_int_t * interest_rect,cairo_image_surface_t ** image_out,cairo_rectangle_int_t * image_rect_out,void ** image_extra)4185 _cairo_image_surface_acquire_dest_image (void                    *abstract_surface,
4186 					 cairo_rectangle_int_t   *interest_rect,
4187 					 cairo_image_surface_t  **image_out,
4188 					 cairo_rectangle_int_t   *image_rect_out,
4189 					 void                   **image_extra)
4190 {
4191     cairo_image_surface_t *surface = abstract_surface;
4192 
4193     image_rect_out->x = 0;
4194     image_rect_out->y = 0;
4195     image_rect_out->width = surface->width;
4196     image_rect_out->height = surface->height;
4197 
4198     *image_out = surface;
4199     *image_extra = NULL;
4200 
4201     return CAIRO_STATUS_SUCCESS;
4202 }
4203 
4204 static void
_cairo_image_surface_release_dest_image(void * abstract_surface,cairo_rectangle_int_t * interest_rect,cairo_image_surface_t * image,cairo_rectangle_int_t * image_rect,void * image_extra)4205 _cairo_image_surface_release_dest_image (void                    *abstract_surface,
4206                                         cairo_rectangle_int_t   *interest_rect,
4207                                         cairo_image_surface_t   *image,
4208                                         cairo_rectangle_int_t   *image_rect,
4209                                         void                    *image_extra)
4210 {
4211 }
4212 
4213 static cairo_status_t
_cairo_image_surface_clone_similar(void * abstract_surface,cairo_surface_t * src,int src_x,int src_y,int width,int height,int * clone_offset_x,int * clone_offset_y,cairo_surface_t ** clone_out)4214 _cairo_image_surface_clone_similar (void               *abstract_surface,
4215 				    cairo_surface_t     *src,
4216 				    int                  src_x,
4217 				    int                  src_y,
4218 				    int                  width,
4219 				    int                  height,
4220 				    int                 *clone_offset_x,
4221 				    int                 *clone_offset_y,
4222 				    cairo_surface_t    **clone_out)
4223 {
4224     cairo_image_surface_t *surface = abstract_surface;
4225 
4226     if (src->backend == surface->base.backend) {
4227 	*clone_offset_x = *clone_offset_y = 0;
4228 	*clone_out = cairo_surface_reference (src);
4229 
4230 	return CAIRO_STATUS_SUCCESS;
4231     }
4232 
4233     return CAIRO_INT_STATUS_UNSUPPORTED;
4234 }
4235 
4236 static cairo_int_status_t
_cairo_image_surface_composite(cairo_operator_t op,const cairo_pattern_t * src_pattern,const cairo_pattern_t * mask_pattern,void * abstract_dst,int src_x,int src_y,int mask_x,int mask_y,int dst_x,int dst_y,unsigned int width,unsigned int height,cairo_region_t * clip_region)4237 _cairo_image_surface_composite (cairo_operator_t	 op,
4238 				const cairo_pattern_t	*src_pattern,
4239 				const cairo_pattern_t	*mask_pattern,
4240 				void			*abstract_dst,
4241 				int			 src_x,
4242 				int			 src_y,
4243 				int			 mask_x,
4244 				int			 mask_y,
4245 				int			 dst_x,
4246 				int			 dst_y,
4247 				unsigned int		 width,
4248 				unsigned int		 height,
4249 				cairo_region_t		*clip_region)
4250 {
4251     cairo_image_surface_t *dst = abstract_dst;
4252     cairo_composite_rectangles_t extents;
4253     pixman_image_t *src;
4254     int src_offset_x, src_offset_y;
4255     cairo_status_t status;
4256 
4257     if (clip_region != NULL) {
4258 	status = _cairo_image_surface_set_clip_region (dst, clip_region);
4259 	if (unlikely (status))
4260 	    return status;
4261     }
4262 
4263     extents.source.x = src_x;
4264     extents.source.y = src_y;
4265     extents.source.width  = width;
4266     extents.source.height = height;
4267 
4268     extents.mask.x = mask_x;
4269     extents.mask.y = mask_y;
4270     extents.mask.width  = width;
4271     extents.mask.height = height;
4272 
4273     extents.bounded.x = dst_x;
4274     extents.bounded.y = dst_y;
4275     extents.bounded.width  = width;
4276     extents.bounded.height = height;
4277 
4278     extents.unbounded.x = 0;
4279     extents.unbounded.y = 0;
4280     extents.unbounded.width  = dst->width;
4281     extents.unbounded.height = dst->height;
4282 
4283     if (clip_region != NULL) {
4284 	cairo_rectangle_int_t rect;
4285 
4286 	cairo_region_get_extents (clip_region, &rect);
4287 	if (! _cairo_rectangle_intersect (&extents.unbounded, &rect))
4288 	    return CAIRO_STATUS_SUCCESS;
4289     }
4290 
4291     extents.is_bounded = _cairo_operator_bounded_by_either (op);
4292 
4293     src = _pixman_image_for_pattern (src_pattern, FALSE, &extents.source, &src_offset_x, &src_offset_y);
4294     if (unlikely (src == NULL))
4295 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4296 
4297     status = CAIRO_STATUS_SUCCESS;
4298     if (mask_pattern != NULL) {
4299 	pixman_image_t *mask;
4300 	int mask_offset_x, mask_offset_y;
4301 
4302 	mask = _pixman_image_for_pattern (mask_pattern, TRUE, &extents.mask, &mask_offset_x, &mask_offset_y);
4303 	if (unlikely (mask == NULL)) {
4304 	    pixman_image_unref (src);
4305 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4306 	}
4307 
4308 	pixman_image_composite32 (_pixman_operator (op),
4309                                   src, mask, dst->pixman_image,
4310                                   src_x + src_offset_x,
4311                                   src_y + src_offset_y,
4312                                   mask_x + mask_offset_x,
4313                                   mask_y + mask_offset_y,
4314 				  dst_x, dst_y, width, height);
4315 
4316 	pixman_image_unref (mask);
4317     } else {
4318 	pixman_image_composite32 (_pixman_operator (op),
4319                                   src, NULL, dst->pixman_image,
4320                                   src_x + src_offset_x,
4321                                   src_y + src_offset_y,
4322                                   0, 0,
4323                                   dst_x, dst_y, width, height);
4324     }
4325 
4326     pixman_image_unref (src);
4327 
4328     if (! extents.is_bounded)
4329 	status = _cairo_image_surface_fixup_unbounded (dst, &extents, NULL);
4330 
4331     if (clip_region != NULL)
4332 	_cairo_image_surface_unset_clip_region (dst);
4333 
4334     return status;
4335 }
4336 
4337 static cairo_int_status_t
_cairo_image_surface_fill_rectangles(void * abstract_surface,cairo_operator_t op,const cairo_color_t * color,cairo_rectangle_int_t * rects,int num_rects)4338 _cairo_image_surface_fill_rectangles (void		      *abstract_surface,
4339 				      cairo_operator_t	       op,
4340 				      const cairo_color_t     *color,
4341 				      cairo_rectangle_int_t   *rects,
4342 				      int		       num_rects)
4343 {
4344     cairo_image_surface_t *surface = abstract_surface;
4345 
4346     pixman_color_t pixman_color;
4347     pixman_box32_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
4348     pixman_box32_t *pixman_boxes = stack_boxes;
4349     int i;
4350 
4351     cairo_int_status_t status;
4352 
4353     if (CAIRO_INJECT_FAULT ())
4354 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4355 
4356     pixman_color.red   = color->red_short;
4357     pixman_color.green = color->green_short;
4358     pixman_color.blue  = color->blue_short;
4359     pixman_color.alpha = color->alpha_short;
4360 
4361     if (num_rects > ARRAY_LENGTH (stack_boxes)) {
4362 	pixman_boxes = _cairo_malloc_ab (num_rects, sizeof (pixman_box32_t));
4363 	if (unlikely (pixman_boxes == NULL))
4364 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4365     }
4366 
4367     for (i = 0; i < num_rects; i++) {
4368 	pixman_boxes[i].x1 = rects[i].x;
4369 	pixman_boxes[i].y1 = rects[i].y;
4370 	pixman_boxes[i].x2 = rects[i].x + rects[i].width;
4371 	pixman_boxes[i].y2 = rects[i].y + rects[i].height;
4372     }
4373 
4374     status = CAIRO_STATUS_SUCCESS;
4375     if (! pixman_image_fill_boxes (_pixman_operator (op),
4376                                    surface->pixman_image,
4377                                    &pixman_color,
4378                                    num_rects,
4379                                    pixman_boxes))
4380     {
4381 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
4382     }
4383 
4384     if (pixman_boxes != stack_boxes)
4385 	free (pixman_boxes);
4386 
4387     return status;
4388 }
4389 
4390 static cairo_int_status_t
_cairo_image_surface_composite_trapezoids(cairo_operator_t op,const cairo_pattern_t * pattern,void * abstract_dst,cairo_antialias_t antialias,int src_x,int src_y,int dst_x,int dst_y,unsigned int width,unsigned int height,cairo_trapezoid_t * traps,int num_traps,cairo_region_t * clip_region)4391 _cairo_image_surface_composite_trapezoids (cairo_operator_t	op,
4392 					   const cairo_pattern_t *pattern,
4393 					   void			*abstract_dst,
4394 					   cairo_antialias_t	antialias,
4395 					   int			src_x,
4396 					   int			src_y,
4397 					   int			dst_x,
4398 					   int			dst_y,
4399 					   unsigned int		width,
4400 					   unsigned int		height,
4401 					   cairo_trapezoid_t	*traps,
4402 					   int			num_traps,
4403 					   cairo_region_t	*clip_region)
4404 {
4405     cairo_image_surface_t	*dst = abstract_dst;
4406     cairo_composite_rectangles_t extents;
4407     cairo_pattern_union_t        source_pattern;
4408     composite_traps_info_t	 info;
4409     cairo_status_t		 status;
4410 
4411     if (height == 0 || width == 0)
4412 	return CAIRO_STATUS_SUCCESS;
4413 
4414     if (CAIRO_INJECT_FAULT ())
4415 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4416 
4417     extents.source.x = src_x;
4418     extents.source.y = src_y;
4419     extents.source.width  = width;
4420     extents.source.height = height;
4421 
4422     extents.mask.x = dst_x;
4423     extents.mask.y = dst_y;
4424     extents.mask.width  = width;
4425     extents.mask.height = height;
4426 
4427     extents.bounded.x = dst_x;
4428     extents.bounded.y = dst_y;
4429     extents.bounded.width  = width;
4430     extents.bounded.height = height;
4431 
4432     extents.unbounded.x = 0;
4433     extents.unbounded.y = 0;
4434     extents.unbounded.width  = dst->width;
4435     extents.unbounded.height = dst->height;
4436 
4437     if (clip_region != NULL) {
4438 	cairo_rectangle_int_t rect;
4439 
4440 	cairo_region_get_extents (clip_region, &rect);
4441 	if (! _cairo_rectangle_intersect (&extents.unbounded, &rect))
4442 	    return CAIRO_STATUS_SUCCESS;
4443     }
4444 
4445     extents.is_bounded = _cairo_operator_bounded_by_either (op);
4446 
4447     if (clip_region != NULL) {
4448 	status = _cairo_image_surface_set_clip_region (dst, clip_region);
4449 	if (unlikely (status))
4450 	    return status;
4451     }
4452 
4453     _cairo_pattern_init_static_copy (&source_pattern.base, pattern);
4454     cairo_matrix_translate (&source_pattern.base.matrix,
4455                             src_x - extents.bounded.x,
4456                             src_y - extents.bounded.y);
4457 
4458     info.traps = traps;
4459     info.num_traps = num_traps;
4460     info.antialias = antialias;
4461     status = _composite_traps (&info,
4462 			       dst->pixman_image,
4463 			       dst->pixman_format,
4464 			       op,
4465 			       &source_pattern.base,
4466 			       0, 0,
4467 			       &extents.bounded,
4468 			       clip_region);
4469 
4470     if (status == CAIRO_STATUS_SUCCESS && ! extents.is_bounded)
4471 	status = _cairo_image_surface_fixup_unbounded (dst, &extents, NULL);
4472 
4473     if (clip_region != NULL)
4474 	_cairo_image_surface_unset_clip_region (dst);
4475 
4476     return status;
4477 }
4478 
4479 typedef struct _legacy_image_surface_span_renderer {
4480     cairo_span_renderer_t base;
4481 
4482     cairo_operator_t op;
4483     const cairo_pattern_t *pattern;
4484     cairo_antialias_t antialias;
4485     cairo_region_t *clip_region;
4486 
4487     pixman_image_t *mask;
4488     uint8_t *mask_data;
4489     uint32_t mask_stride;
4490 
4491     cairo_image_surface_t *dst;
4492     cairo_composite_rectangles_t composite_rectangles;
4493 } legacy_image_surface_span_renderer_t;
4494 
4495 void
_cairo_image_surface_span_render_row(int y,const cairo_half_open_span_t * spans,unsigned num_spans,uint8_t * data,uint32_t stride)4496 _cairo_image_surface_span_render_row (
4497     int                                  y,
4498     const cairo_half_open_span_t        *spans,
4499     unsigned                             num_spans,
4500     uint8_t				*data,
4501     uint32_t				 stride)
4502 {
4503     uint8_t *row;
4504     unsigned i;
4505 
4506     if (num_spans == 0)
4507 	return;
4508 
4509     row = data + y * stride;
4510     for (i = 0; i < num_spans - 1; i++) {
4511 	if (! spans[i].coverage)
4512 	    continue;
4513 
4514 	/* We implement setting the most common single pixel wide
4515 	 * span case to avoid the overhead of a memset call.
4516 	 * Open coding setting longer spans didn't show a
4517 	 * noticeable improvement over memset.
4518 	 */
4519 	if (spans[i+1].x == spans[i].x + 1) {
4520 	    row[spans[i].x] = spans[i].coverage;
4521 	} else {
4522 	    memset (row + spans[i].x,
4523 		    spans[i].coverage,
4524 		    spans[i+1].x - spans[i].x);
4525 	}
4526     }
4527 }
4528 
4529 static cairo_status_t
_cairo_image_surface_span_renderer_render_rows(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * spans,unsigned num_spans)4530 _cairo_image_surface_span_renderer_render_rows (
4531     void				*abstract_renderer,
4532     int					 y,
4533     int					 height,
4534     const cairo_half_open_span_t	*spans,
4535     unsigned				 num_spans)
4536 {
4537     legacy_image_surface_span_renderer_t *renderer = abstract_renderer;
4538     while (height--)
4539 	_cairo_image_surface_span_render_row (y++, spans, num_spans, renderer->mask_data, renderer->mask_stride);
4540     return CAIRO_STATUS_SUCCESS;
4541 }
4542 
4543 static void
_cairo_image_surface_span_renderer_destroy(void * abstract_renderer)4544 _cairo_image_surface_span_renderer_destroy (void *abstract_renderer)
4545 {
4546     legacy_image_surface_span_renderer_t *renderer = abstract_renderer;
4547     if (renderer == NULL)
4548 	return;
4549 
4550     pixman_image_unref (renderer->mask);
4551 
4552     free (renderer);
4553 }
4554 
4555 static cairo_status_t
_cairo_image_surface_span_renderer_finish(void * abstract_renderer)4556 _cairo_image_surface_span_renderer_finish (void *abstract_renderer)
4557 {
4558     legacy_image_surface_span_renderer_t *renderer = abstract_renderer;
4559     cairo_composite_rectangles_t *rects = &renderer->composite_rectangles;
4560     cairo_image_surface_t *dst = renderer->dst;
4561     pixman_image_t *src;
4562     int src_x, src_y;
4563     cairo_status_t status;
4564 
4565     if (renderer->clip_region != NULL) {
4566 	status = _cairo_image_surface_set_clip_region (dst, renderer->clip_region);
4567 	if (unlikely (status))
4568 	    return status;
4569     }
4570 
4571     src = _pixman_image_for_pattern (renderer->pattern, FALSE, &rects->bounded, &src_x, &src_y);
4572     if (src == NULL)
4573 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4574 
4575     status = CAIRO_STATUS_SUCCESS;
4576     pixman_image_composite32 (_pixman_operator (renderer->op),
4577                               src,
4578                               renderer->mask,
4579                               dst->pixman_image,
4580                               rects->bounded.x + src_x,
4581                               rects->bounded.y + src_y,
4582                               0, 0,
4583                               rects->bounded.x, rects->bounded.y,
4584                               rects->bounded.width, rects->bounded.height);
4585 
4586     if (! rects->is_bounded)
4587 	status = _cairo_image_surface_fixup_unbounded (dst, rects, NULL);
4588 
4589     if (renderer->clip_region != NULL)
4590 	 _cairo_image_surface_unset_clip_region (dst);
4591 
4592     return status;
4593 }
4594 
4595 static cairo_bool_t
_cairo_image_surface_check_span_renderer(cairo_operator_t op,const cairo_pattern_t * pattern,void * abstract_dst,cairo_antialias_t antialias)4596 _cairo_image_surface_check_span_renderer (cairo_operator_t	  op,
4597 					  const cairo_pattern_t  *pattern,
4598 					  void			 *abstract_dst,
4599 					  cairo_antialias_t	  antialias)
4600 {
4601     return TRUE;
4602     (void) op;
4603     (void) pattern;
4604     (void) abstract_dst;
4605     (void) antialias;
4606 }
4607 
4608 static cairo_span_renderer_t *
_cairo_image_surface_create_span_renderer(cairo_operator_t op,const cairo_pattern_t * pattern,void * abstract_dst,cairo_antialias_t antialias,const cairo_composite_rectangles_t * rects,cairo_region_t * clip_region)4609 _cairo_image_surface_create_span_renderer (cairo_operator_t	 op,
4610 					   const cairo_pattern_t  *pattern,
4611 					   void			*abstract_dst,
4612 					   cairo_antialias_t	 antialias,
4613 					   const cairo_composite_rectangles_t *rects,
4614 					   cairo_region_t *clip_region)
4615 {
4616     cairo_image_surface_t *dst = abstract_dst;
4617     legacy_image_surface_span_renderer_t *renderer;
4618 
4619     renderer = calloc(1, sizeof(*renderer));
4620     if (unlikely (renderer == NULL))
4621 	return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
4622 
4623     renderer->base.destroy = _cairo_image_surface_span_renderer_destroy;
4624     renderer->base.finish = _cairo_image_surface_span_renderer_finish;
4625     renderer->base.render_rows = _cairo_image_surface_span_renderer_render_rows;
4626     renderer->op = op;
4627     renderer->pattern = pattern;
4628     renderer->antialias = antialias;
4629     renderer->dst = dst;
4630     renderer->clip_region = clip_region;
4631 
4632     renderer->composite_rectangles = *rects;
4633 
4634     /* TODO: support rendering to A1 surfaces (or: go add span
4635      * compositing to pixman.) */
4636     renderer->mask = pixman_image_create_bits (PIXMAN_a8,
4637 					       rects->bounded.width,
4638 					       rects->bounded.height,
4639 					       NULL, 0);
4640     if (renderer->mask == NULL) {
4641 	free (renderer);
4642 	return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
4643     }
4644 
4645     renderer->mask_stride = pixman_image_get_stride (renderer->mask);
4646     renderer->mask_data = (uint8_t *) pixman_image_get_data (renderer->mask) - rects->bounded.x - rects->bounded.y * renderer->mask_stride;
4647 
4648     return &renderer->base;
4649 }
4650 
4651 /**
4652  * _cairo_surface_is_image:
4653  * @surface: a #cairo_surface_t
4654  *
4655  * Checks if a surface is an #cairo_image_surface_t
4656  *
4657  * Return value: %TRUE if the surface is an image surface
4658  **/
4659 cairo_bool_t
_cairo_surface_is_image(const cairo_surface_t * surface)4660 _cairo_surface_is_image (const cairo_surface_t *surface)
4661 {
4662     return surface->backend == &_cairo_image_surface_backend;
4663 }
4664 
4665 const cairo_surface_backend_t _cairo_image_surface_backend = {
4666     CAIRO_SURFACE_TYPE_IMAGE,
4667     _cairo_image_surface_create_similar,
4668     _cairo_image_surface_finish,
4669     _cairo_image_surface_acquire_source_image,
4670     _cairo_image_surface_release_source_image,
4671     _cairo_image_surface_acquire_dest_image,
4672     _cairo_image_surface_release_dest_image,
4673     _cairo_image_surface_clone_similar,
4674     _cairo_image_surface_composite,
4675     _cairo_image_surface_fill_rectangles,
4676     _cairo_image_surface_composite_trapezoids,
4677     _cairo_image_surface_create_span_renderer,
4678     _cairo_image_surface_check_span_renderer,
4679 
4680     NULL, /* copy_page */
4681     NULL, /* show_page */
4682     _cairo_image_surface_get_extents,
4683     NULL, /* old_show_glyphs */
4684     _cairo_image_surface_get_font_options,
4685     NULL, /* flush */
4686     NULL, /* mark dirty */
4687     NULL, /* font_fini */
4688     NULL, /* glyph_fini */
4689 
4690     _cairo_image_surface_paint,
4691     _cairo_image_surface_mask,
4692     _cairo_image_surface_stroke,
4693     _cairo_image_surface_fill,
4694     _cairo_image_surface_glyphs,
4695     NULL, /* show_text_glyphs */
4696     NULL, /* snapshot */
4697     NULL, /* is_similar */
4698 };
4699 
4700 /* A convenience function for when one needs to coerce an image
4701  * surface to an alternate format. */
4702 cairo_image_surface_t *
_cairo_image_surface_coerce(cairo_image_surface_t * surface)4703 _cairo_image_surface_coerce (cairo_image_surface_t *surface)
4704 {
4705     return _cairo_image_surface_coerce_to_format (surface,
4706 		                                  _cairo_format_from_content (surface->base.content));
4707 
4708 }
4709 
4710 /* A convenience function for when one needs to coerce an image
4711  * surface to an alternate format. */
4712 cairo_image_surface_t *
_cairo_image_surface_coerce_to_format(cairo_image_surface_t * surface,cairo_format_t format)4713 _cairo_image_surface_coerce_to_format (cairo_image_surface_t *surface,
4714 			               cairo_format_t	      format)
4715 {
4716     cairo_image_surface_t *clone;
4717     cairo_status_t status;
4718 
4719     status = surface->base.status;
4720     if (unlikely (status))
4721 	return (cairo_image_surface_t *)_cairo_surface_create_in_error (status);
4722 
4723     if (surface->format == format)
4724 	return (cairo_image_surface_t *)cairo_surface_reference(&surface->base);
4725 
4726     clone = (cairo_image_surface_t *)
4727 	cairo_image_surface_create (format, surface->width, surface->height);
4728     if (unlikely (clone->base.status))
4729 	return clone;
4730 
4731     pixman_image_composite32 (PIXMAN_OP_SRC,
4732                               surface->pixman_image, NULL, clone->pixman_image,
4733                               0, 0,
4734                               0, 0,
4735                               0, 0,
4736                               surface->width, surface->height);
4737     clone->base.is_clear = FALSE;
4738 
4739     clone->base.device_transform =
4740 	surface->base.device_transform;
4741     clone->base.device_transform_inverse =
4742 	surface->base.device_transform_inverse;
4743 
4744     return clone;
4745 }
4746 
4747 cairo_image_transparency_t
_cairo_image_analyze_transparency(cairo_image_surface_t * image)4748 _cairo_image_analyze_transparency (cairo_image_surface_t      *image)
4749 {
4750     int x, y;
4751 
4752     if (image->transparency != CAIRO_IMAGE_UNKNOWN)
4753 	return image->transparency;
4754 
4755     if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0)
4756 	return image->transparency = CAIRO_IMAGE_IS_OPAQUE;
4757 
4758     if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) {
4759 	if (image->format == CAIRO_FORMAT_A1)
4760 	    return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
4761 	else
4762 	    return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
4763     }
4764 
4765     if (image->format == CAIRO_FORMAT_RGB16_565) {
4766 	image->transparency = CAIRO_IMAGE_IS_OPAQUE;
4767 	return CAIRO_IMAGE_IS_OPAQUE;
4768     }
4769 
4770     if (image->format != CAIRO_FORMAT_ARGB32)
4771 	return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
4772 
4773     image->transparency = CAIRO_IMAGE_IS_OPAQUE;
4774     for (y = 0; y < image->height; y++) {
4775 	uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
4776 
4777 	for (x = 0; x < image->width; x++, pixel++) {
4778 	    int a = (*pixel & 0xff000000) >> 24;
4779 	    if (a > 0 && a < 255) {
4780 		return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
4781 	    } else if (a == 0) {
4782 		image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
4783 	    }
4784 	}
4785     }
4786 
4787     return image->transparency;
4788 }
4789