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);
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 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 #else
973 static pixman_image_t *
_pixman_transparent_image(void)974 _pixman_transparent_image (void)
975 {
976     return _pixman_image_for_solid (&_cairo_pattern_clear);
977 }
978 static pixman_image_t *
_pixman_black_image(void)979 _pixman_black_image (void)
980 {
981     return _pixman_image_for_solid (&_cairo_pattern_black);
982 }
983 static pixman_image_t *
_pixman_white_image(void)984 _pixman_white_image (void)
985 {
986     return _pixman_image_for_solid (&_cairo_pattern_white);
987 }
988 #endif
989 
990 static uint32_t
hars_petruska_f54_1_random(void)991 hars_petruska_f54_1_random (void)
992 {
993 #define rol(x,k) ((x << k) | (x >> (32-k)))
994     static uint32_t x;
995     return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
996 #undef rol
997 }
998 
999 static struct {
1000     cairo_color_t color;
1001     pixman_image_t *image;
1002 } cache[16];
1003 static int n_cached;
1004 
1005 void
_cairo_image_reset_static_data(void)1006 _cairo_image_reset_static_data (void)
1007 {
1008     while (n_cached)
1009 	pixman_image_unref (cache[--n_cached].image);
1010 
1011 #if HAS_ATOMIC_OPS
1012     if (__pixman_transparent_image) {
1013 	pixman_image_unref (__pixman_transparent_image);
1014 	__pixman_transparent_image = NULL;
1015     }
1016 
1017     if (__pixman_black_image) {
1018 	pixman_image_unref (__pixman_black_image);
1019 	__pixman_black_image = NULL;
1020     }
1021 
1022     if (__pixman_white_image) {
1023 	pixman_image_unref (__pixman_white_image);
1024 	__pixman_white_image = NULL;
1025     }
1026 #endif
1027 }
1028 
1029 static pixman_image_t *
_pixman_image_for_solid(const cairo_solid_pattern_t * pattern)1030 _pixman_image_for_solid (const cairo_solid_pattern_t *pattern)
1031 {
1032     pixman_color_t color;
1033     pixman_image_t *image;
1034     int i;
1035 
1036 #if HAS_ATOMIC_OPS
1037     if (pattern->color.alpha_short <= 0x00ff)
1038 	return _pixman_transparent_image ();
1039 
1040     if (pattern->color.alpha_short >= 0xff00) {
1041 	if (pattern->color.red_short <= 0x00ff &&
1042 	    pattern->color.green_short <= 0x00ff &&
1043 	    pattern->color.blue_short <= 0x00ff)
1044 	{
1045 	    return _pixman_black_image ();
1046 	}
1047 
1048 	if (pattern->color.red_short >= 0xff00 &&
1049 	    pattern->color.green_short >= 0xff00 &&
1050 	    pattern->color.blue_short >= 0xff00)
1051 	{
1052 	    return _pixman_white_image ();
1053 	}
1054     }
1055 #endif
1056 
1057     CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex);
1058     for (i = 0; i < n_cached; i++) {
1059 	if (_cairo_color_equal (&cache[i].color, &pattern->color)) {
1060 	    image = pixman_image_ref (cache[i].image);
1061 	    goto UNLOCK;
1062 	}
1063     }
1064 
1065     color.red   = pattern->color.red_short;
1066     color.green = pattern->color.green_short;
1067     color.blue  = pattern->color.blue_short;
1068     color.alpha = pattern->color.alpha_short;
1069 
1070     image = pixman_image_create_solid_fill (&color);
1071     if (image == NULL)
1072 	goto UNLOCK;
1073 
1074     if (n_cached < ARRAY_LENGTH (cache)) {
1075 	i = n_cached++;
1076     } else {
1077 	i = hars_petruska_f54_1_random () % ARRAY_LENGTH (cache);
1078 	pixman_image_unref (cache[i].image);
1079     }
1080     cache[i].image = pixman_image_ref (image);
1081     cache[i].color = pattern->color;
1082 
1083 UNLOCK:
1084     CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
1085     return image;
1086 }
1087 
1088 static pixman_image_t *
_pixman_image_for_gradient(const cairo_gradient_pattern_t * pattern,const cairo_rectangle_int_t * extents,int * ix,int * iy)1089 _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
1090 			    const cairo_rectangle_int_t *extents,
1091 			    int *ix, int *iy)
1092 {
1093     pixman_image_t	  *pixman_image;
1094     pixman_gradient_stop_t pixman_stops_static[2];
1095     pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
1096     cairo_matrix_t matrix = pattern->base.matrix;
1097     double tx, ty;
1098     unsigned int i;
1099 
1100     if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
1101 	pixman_stops = _cairo_malloc_ab (pattern->n_stops,
1102 					 sizeof(pixman_gradient_stop_t));
1103 	if (unlikely (pixman_stops == NULL))
1104 	    return NULL;
1105     }
1106 
1107     for (i = 0; i < pattern->n_stops; i++) {
1108 	pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
1109 	pixman_stops[i].color.red   = pattern->stops[i].color.red_short;
1110 	pixman_stops[i].color.green = pattern->stops[i].color.green_short;
1111 	pixman_stops[i].color.blue  = pattern->stops[i].color.blue_short;
1112 	pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
1113     }
1114 
1115     if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
1116 	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
1117 	pixman_point_fixed_t p1, p2;
1118 	cairo_fixed_t xdim, ydim;
1119 
1120 	xdim = fabs (linear->p2.x - linear->p1.x);
1121 	ydim = fabs (linear->p2.y - linear->p1.y);
1122 
1123 	/*
1124 	 * Transform the matrix to avoid overflow when converting between
1125 	 * cairo_fixed_t and pixman_fixed_t (without incurring performance
1126 	 * loss when the transformation is unnecessary).
1127 	 *
1128 	 * XXX: Consider converting out-of-range co-ordinates and transforms.
1129 	 * Having a function to compute the required transformation to
1130 	 * "normalize" a given bounding box would be generally useful -
1131 	 * cf linear patterns, gradient patterns, surface patterns...
1132 	 */
1133 	if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT ||
1134 	    _cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT)
1135 	{
1136 	    double sf;
1137 
1138 	    if (xdim > ydim)
1139 		sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim);
1140 	    else
1141 		sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim);
1142 
1143 	    p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
1144 	    p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
1145 	    p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
1146 	    p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
1147 
1148 	    cairo_matrix_scale (&matrix, sf, sf);
1149 	}
1150 	else
1151 	{
1152 	    p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
1153 	    p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
1154 	    p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
1155 	    p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
1156 	}
1157 
1158 	pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
1159 							    pixman_stops,
1160 							    pattern->n_stops);
1161     } else {
1162 	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
1163 	pixman_point_fixed_t c1, c2;
1164 	pixman_fixed_t r1, r2;
1165 
1166 	c1.x = _cairo_fixed_to_16_16 (radial->c1.x);
1167 	c1.y = _cairo_fixed_to_16_16 (radial->c1.y);
1168 	r1   = _cairo_fixed_to_16_16 (radial->r1);
1169 
1170 	c2.x = _cairo_fixed_to_16_16 (radial->c2.x);
1171 	c2.y = _cairo_fixed_to_16_16 (radial->c2.y);
1172 	r2   = _cairo_fixed_to_16_16 (radial->r2);
1173 
1174 	pixman_image = pixman_image_create_radial_gradient (&c1, &c2, r1, r2,
1175 							    pixman_stops,
1176 							    pattern->n_stops);
1177     }
1178 
1179     if (pixman_stops != pixman_stops_static)
1180 	free (pixman_stops);
1181 
1182     if (unlikely (pixman_image == NULL))
1183 	return NULL;
1184 
1185     tx = pattern->base.matrix.x0;
1186     ty = pattern->base.matrix.y0;
1187     if (! _cairo_matrix_is_translation (&pattern->base.matrix) ||
1188 	! _nearest_sample (pattern->base.filter, &tx, &ty))
1189     {
1190 	pixman_transform_t pixman_transform;
1191 
1192 	if (tx != 0. || ty != 0.) {
1193 	    cairo_matrix_t m, inv;
1194 	    cairo_status_t status;
1195 	    double x, y;
1196 
1197 	    /* pixman also limits the [xy]_offset to 16 bits so evenly
1198 	     * spread the bits between the two.
1199 	     */
1200 	    inv = pattern->base.matrix;
1201 	    status = cairo_matrix_invert (&inv);
1202 	    assert (status == CAIRO_STATUS_SUCCESS);
1203 
1204 	    x = floor (inv.x0 / 2);
1205 	    y = floor (inv.y0 / 2);
1206 	    tx = -x;
1207 	    ty = -y;
1208 	    cairo_matrix_init_translate (&inv, x, y);
1209 	    cairo_matrix_multiply (&m, &inv, &pattern->base.matrix);
1210 	    _cairo_matrix_to_pixman_matrix (&m, &pixman_transform,
1211 					    extents->x + extents->width/2.,
1212 					    extents->y + extents->height/2.);
1213 	} else {
1214 	    tx = ty = 0;
1215 	    _cairo_matrix_to_pixman_matrix (&pattern->base.matrix,
1216 					    &pixman_transform,
1217 					    extents->x + extents->width/2.,
1218 					    extents->y + extents->height/2.);
1219 	}
1220 
1221 	if (! pixman_image_set_transform (pixman_image, &pixman_transform)) {
1222 	    pixman_image_unref (pixman_image);
1223 	    return NULL;
1224 	}
1225     }
1226     *ix = tx;
1227     *iy = ty;
1228 
1229     {
1230 	pixman_repeat_t pixman_repeat;
1231 
1232 	switch (pattern->base.extend) {
1233 	default:
1234 	case CAIRO_EXTEND_NONE:
1235 	    pixman_repeat = PIXMAN_REPEAT_NONE;
1236 	    break;
1237 	case CAIRO_EXTEND_REPEAT:
1238 	    pixman_repeat = PIXMAN_REPEAT_NORMAL;
1239 	    break;
1240 	case CAIRO_EXTEND_REFLECT:
1241 	    pixman_repeat = PIXMAN_REPEAT_REFLECT;
1242 	    break;
1243 	case CAIRO_EXTEND_PAD:
1244 	    pixman_repeat = PIXMAN_REPEAT_PAD;
1245 	    break;
1246 	}
1247 
1248 	pixman_image_set_repeat (pixman_image, pixman_repeat);
1249     }
1250 
1251     return pixman_image;
1252 }
1253 
1254 struct acquire_source_cleanup {
1255     cairo_surface_t *surface;
1256     cairo_image_surface_t *image;
1257     void *image_extra;
1258 };
1259 
1260 static void
_acquire_source_cleanup(pixman_image_t * pixman_image,void * closure)1261 _acquire_source_cleanup (pixman_image_t *pixman_image,
1262 			 void *closure)
1263 {
1264     struct acquire_source_cleanup *data = closure;
1265 
1266     _cairo_surface_release_source_image (data->surface,
1267 					 data->image,
1268 					 data->image_extra);
1269     free (data);
1270 }
1271 
1272 static cairo_filter_t
sampled_area(const cairo_surface_pattern_t * pattern,const cairo_rectangle_int_t * extents,cairo_rectangle_int_t * sample)1273 sampled_area (const cairo_surface_pattern_t *pattern,
1274 	      const cairo_rectangle_int_t *extents,
1275 	      cairo_rectangle_int_t *sample)
1276 {
1277     cairo_filter_t filter;
1278     double x1, x2, y1, y2;
1279     double pad;
1280 
1281     x1 = extents->x;
1282     y1 = extents->y;
1283     x2 = extents->x + (int) extents->width;
1284     y2 = extents->y + (int) extents->height;
1285 
1286     _cairo_matrix_transform_bounding_box (&pattern->base.matrix,
1287                                           &x1, &y1, &x2, &y2,
1288                                           NULL);
1289 
1290     filter = _cairo_pattern_analyze_filter (&pattern->base, &pad);
1291     sample->x = floor (x1 - pad);
1292     sample->y = floor (y1 - pad);
1293     sample->width  = ceil (x2 + pad) - sample->x;
1294     sample->height = ceil (y2 + pad) - sample->y;
1295 
1296     return filter;
1297 }
1298 
1299 static uint16_t
expand_channel(uint16_t v,uint32_t bits)1300 expand_channel (uint16_t v, uint32_t bits)
1301 {
1302     int offset = 16 - bits;
1303     while (offset > 0) {
1304 	v |= v >> bits;
1305 	offset -= bits;
1306 	bits += bits;
1307     }
1308     return v;
1309 }
1310 
1311 static pixman_image_t *
_pixel_to_solid(cairo_image_surface_t * image,int x,int y)1312 _pixel_to_solid (cairo_image_surface_t *image, int x, int y)
1313 {
1314     uint32_t pixel;
1315     pixman_color_t color;
1316 
1317     switch (image->format) {
1318     default:
1319     case CAIRO_FORMAT_INVALID:
1320 	ASSERT_NOT_REACHED;
1321 	return NULL;
1322 
1323     case CAIRO_FORMAT_A1:
1324 	pixel = *(uint8_t *) (image->data + y * image->stride + x/8);
1325 	return pixel & (1 << (x&7)) ? _pixman_white_image () : _pixman_transparent_image ();
1326 
1327     case CAIRO_FORMAT_A8:
1328 	color.alpha = *(uint8_t *) (image->data + y * image->stride + x);
1329 	color.alpha |= color.alpha << 8;
1330 	if (color.alpha == 0)
1331 	    return _pixman_transparent_image ();
1332 
1333 	color.red = color.green = color.blue = 0;
1334 	return pixman_image_create_solid_fill (&color);
1335 
1336     case CAIRO_FORMAT_RGB16_565:
1337 	pixel = *(uint16_t *) (image->data + y * image->stride + 2 * x);
1338 	if (pixel == 0)
1339 	    return _pixman_black_image ();
1340 	if (pixel == 0xffff)
1341 	    return _pixman_white_image ();
1342 
1343 	color.alpha = 0xffff;
1344 	color.red = expand_channel ((pixel >> 11 & 0x1f) << 11, 5);
1345 	color.green = expand_channel ((pixel >> 5 & 0x3f) << 10, 6);
1346 	color.blue = expand_channel ((pixel & 0x1f) << 11, 5);
1347 	return pixman_image_create_solid_fill (&color);
1348 
1349     case CAIRO_FORMAT_ARGB32:
1350     case CAIRO_FORMAT_RGB24:
1351 	pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
1352 	color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
1353 	if (color.alpha == 0)
1354 	    return _pixman_transparent_image ();
1355 	if (pixel == 0xffffffff)
1356 	    return _pixman_white_image ();
1357 	if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
1358 	    return _pixman_black_image ();
1359 
1360 	color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
1361 	color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
1362 	color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
1363 	return pixman_image_create_solid_fill (&color);
1364     }
1365 }
1366 
1367 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)1368 _pixman_image_for_surface (const cairo_surface_pattern_t *pattern,
1369 			   cairo_bool_t is_mask,
1370 			   const cairo_rectangle_int_t *extents,
1371 			   int *ix, int *iy)
1372 {
1373     pixman_image_t *pixman_image;
1374     cairo_rectangle_int_t sample;
1375     cairo_extend_t extend;
1376     cairo_filter_t filter;
1377     double tx, ty;
1378 
1379     tx = pattern->base.matrix.x0;
1380     ty = pattern->base.matrix.y0;
1381 
1382     extend = pattern->base.extend;
1383     filter = sampled_area (pattern, extents, &sample);
1384 
1385     pixman_image = NULL;
1386     if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
1387 	(! is_mask || ! pattern->base.has_component_alpha ||
1388 	 (pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
1389     {
1390 	cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
1391 	cairo_surface_type_t type;
1392 
1393 	if (source->base.backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT)
1394 	    source = (cairo_image_surface_t *) ((cairo_surface_snapshot_t *) pattern->surface)->target;
1395 
1396 	type = source->base.backend->type;
1397 	if (type == CAIRO_SURFACE_TYPE_IMAGE) {
1398 	    if (extend != CAIRO_EXTEND_NONE &&
1399 		sample.x >= 0 &&
1400 		sample.y >= 0 &&
1401 		sample.x + sample.width  <= source->width &&
1402 		sample.y + sample.height <= source->height)
1403 	    {
1404 		extend = CAIRO_EXTEND_NONE;
1405 	    }
1406 
1407 	    if (sample.width == 1 && sample.height == 1) {
1408 		if (sample.x < 0 ||
1409 		    sample.y < 0 ||
1410 		    sample.x >= source->width ||
1411 		    sample.y >= source->height)
1412 		{
1413 		    if (extend == CAIRO_EXTEND_NONE)
1414 			return _pixman_transparent_image ();
1415 		}
1416 		else
1417 		{
1418 		    return _pixel_to_solid (source, sample.x, sample.y);
1419 		}
1420 	    }
1421 
1422 	    /* avoid allocating a 'pattern' image if we can reuse the original */
1423 	    if (extend == CAIRO_EXTEND_NONE &&
1424 		_cairo_matrix_is_translation (&pattern->base.matrix) &&
1425 		_nearest_sample (filter, &tx, &ty))
1426 	    {
1427 		*ix = tx;
1428 		*iy = ty;
1429 		return pixman_image_ref (source->pixman_image);
1430 	    }
1431 
1432 	    pixman_image = pixman_image_create_bits (source->pixman_format,
1433 						     source->width,
1434 						     source->height,
1435 						     (uint32_t *) source->data,
1436 						     source->stride);
1437 	    if (unlikely (pixman_image == NULL))
1438 		return NULL;
1439 	} else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1440 	    cairo_surface_subsurface_t *sub;
1441 	    cairo_bool_t is_contained = FALSE;
1442 
1443 	    sub = (cairo_surface_subsurface_t *) source;
1444 	    source = (cairo_image_surface_t *) sub->target;
1445 
1446 	    if (sample.x >= 0 &&
1447 		sample.y >= 0 &&
1448 		sample.x + sample.width  <= sub->extents.width &&
1449 		sample.y + sample.height <= sub->extents.height)
1450 	    {
1451 		is_contained = TRUE;
1452 	    }
1453 
1454 	    if (sample.width == 1 && sample.height == 1) {
1455 		if (is_contained) {
1456 		    return _pixel_to_solid (source,
1457 					    sub->extents.x + sample.x,
1458 					    sub->extents.y + sample.y);
1459 		} else {
1460 		    if (extend == CAIRO_EXTEND_NONE)
1461 			return _pixman_transparent_image ();
1462 		}
1463 	    }
1464 
1465 	    if (is_contained &&
1466 		_cairo_matrix_is_translation (&pattern->base.matrix) &&
1467 		_nearest_sample (filter, &tx, &ty))
1468 	    {
1469 		*ix = tx + sub->extents.x;
1470 		*iy = ty + sub->extents.y;
1471 		return pixman_image_ref (source->pixman_image);
1472 	    }
1473 
1474 	    /* Avoid sub-byte offsets, force a copy in that case. */
1475 	    if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
1476 		pixman_image = pixman_image_create_bits (source->pixman_format,
1477 							 sub->extents.width,
1478 							 sub->extents.height,
1479 							 (uint32_t *) (source->data + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8 + sub->extents.y * source->stride),
1480 							 source->stride);
1481 		if (unlikely (pixman_image == NULL))
1482 		    return NULL;
1483 	    }
1484 	}
1485     }
1486 
1487     if (pixman_image == NULL) {
1488 	struct acquire_source_cleanup *cleanup;
1489 	cairo_image_surface_t *image;
1490 	void *extra;
1491 	cairo_status_t status;
1492 
1493 	status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra);
1494 	if (unlikely (status))
1495 	    return NULL;
1496 
1497 	if (sample.width == 1 && sample.height == 1) {
1498 	    if (sample.x < 0 ||
1499 		sample.y < 0 ||
1500 		sample.x >= image->width ||
1501 		sample.y >= image->height)
1502 	    {
1503 		if (extend == CAIRO_EXTEND_NONE) {
1504 		    pixman_image = _pixman_transparent_image ();
1505 		    _cairo_surface_release_source_image (pattern->surface, image, extra);
1506 		    return pixman_image;
1507 		}
1508 	    }
1509 	    else
1510 	    {
1511 		pixman_image = _pixel_to_solid (image, sample.x, sample.y);
1512 		_cairo_surface_release_source_image (pattern->surface, image, extra);
1513 		return pixman_image;
1514 	    }
1515 	}
1516 
1517 	pixman_image = pixman_image_create_bits (image->pixman_format,
1518 						 image->width,
1519 						 image->height,
1520 						 (uint32_t *) image->data,
1521 						 image->stride);
1522 	if (unlikely (pixman_image == NULL)) {
1523 	    _cairo_surface_release_source_image (pattern->surface, image, extra);
1524 	    return NULL;
1525 	}
1526 
1527 	cleanup = malloc (sizeof (*cleanup));
1528 	if (unlikely (cleanup == NULL)) {
1529 	    _cairo_surface_release_source_image (pattern->surface, image, extra);
1530 	    pixman_image_unref (pixman_image);
1531 	    return NULL;
1532 	}
1533 
1534 	cleanup->surface = pattern->surface;
1535 	cleanup->image = image;
1536 	cleanup->image_extra = extra;
1537 	pixman_image_set_destroy_function (pixman_image,
1538 					   _acquire_source_cleanup, cleanup);
1539     }
1540 
1541     if (! _cairo_matrix_is_translation (&pattern->base.matrix) ||
1542 	! _nearest_sample (filter, &tx, &ty))
1543     {
1544 	pixman_transform_t pixman_transform;
1545 	cairo_matrix_t m;
1546 
1547 	m = pattern->base.matrix;
1548 	if (m.x0 != 0. || m.y0 != 0.) {
1549 	    cairo_matrix_t inv;
1550 	    cairo_status_t status;
1551 	    double x, y;
1552 
1553 	    /* pixman also limits the [xy]_offset to 16 bits so evenly
1554 	     * spread the bits between the two.
1555 	     */
1556 	    inv = m;
1557 	    status = cairo_matrix_invert (&inv);
1558 	    assert (status == CAIRO_STATUS_SUCCESS);
1559 
1560 	    x = floor (inv.x0 / 2);
1561 	    y = floor (inv.y0 / 2);
1562 	    tx = -x;
1563 	    ty = -y;
1564 	    cairo_matrix_init_translate (&inv, x, y);
1565 	    cairo_matrix_multiply (&m, &inv, &m);
1566 	} else {
1567 	    tx = ty = 0;
1568 	}
1569 
1570 	_cairo_matrix_to_pixman_matrix (&m, &pixman_transform,
1571 					extents->x + extents->width/2.,
1572 					extents->y + extents->height/2.);
1573 	if (! pixman_image_set_transform (pixman_image, &pixman_transform)) {
1574 	    pixman_image_unref (pixman_image);
1575 	    return NULL;
1576 	}
1577     }
1578     *ix = tx;
1579     *iy = ty;
1580 
1581     if (_cairo_matrix_has_unity_scale (&pattern->base.matrix) &&
1582 	tx == pattern->base.matrix.x0 &&
1583 	ty == pattern->base.matrix.y0)
1584     {
1585 	pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0);
1586     }
1587     else
1588     {
1589 	pixman_filter_t pixman_filter;
1590 
1591 	switch (filter) {
1592 	case CAIRO_FILTER_FAST:
1593 	    pixman_filter = PIXMAN_FILTER_FAST;
1594 	    break;
1595 	case CAIRO_FILTER_GOOD:
1596 	    pixman_filter = PIXMAN_FILTER_GOOD;
1597 	    break;
1598 	case CAIRO_FILTER_BEST:
1599 	    pixman_filter = PIXMAN_FILTER_BEST;
1600 	    break;
1601 	case CAIRO_FILTER_NEAREST:
1602 	    pixman_filter = PIXMAN_FILTER_NEAREST;
1603 	    break;
1604 	case CAIRO_FILTER_BILINEAR:
1605 	    pixman_filter = PIXMAN_FILTER_BILINEAR;
1606 	    break;
1607 	case CAIRO_FILTER_GAUSSIAN:
1608 	    /* XXX: The GAUSSIAN value has no implementation in cairo
1609 	     * whatsoever, so it was really a mistake to have it in the
1610 	     * API. We could fix this by officially deprecating it, or
1611 	     * else inventing semantics and providing an actual
1612 	     * implementation for it. */
1613 	default:
1614 	    pixman_filter = PIXMAN_FILTER_BEST;
1615 	}
1616 
1617 	pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
1618     }
1619 
1620     {
1621 	pixman_repeat_t pixman_repeat;
1622 
1623 	switch (extend) {
1624 	default:
1625 	case CAIRO_EXTEND_NONE:
1626 	    pixman_repeat = PIXMAN_REPEAT_NONE;
1627 	    break;
1628 	case CAIRO_EXTEND_REPEAT:
1629 	    pixman_repeat = PIXMAN_REPEAT_NORMAL;
1630 	    break;
1631 	case CAIRO_EXTEND_REFLECT:
1632 	    pixman_repeat = PIXMAN_REPEAT_REFLECT;
1633 	    break;
1634 	case CAIRO_EXTEND_PAD:
1635 	    pixman_repeat = PIXMAN_REPEAT_PAD;
1636 	    break;
1637 	}
1638 
1639 	pixman_image_set_repeat (pixman_image, pixman_repeat);
1640     }
1641 
1642     if (pattern->base.has_component_alpha)
1643 	pixman_image_set_component_alpha (pixman_image, TRUE);
1644 
1645     return pixman_image;
1646 }
1647 
1648 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)1649 _pixman_image_for_pattern (const cairo_pattern_t *pattern,
1650 			   cairo_bool_t is_mask,
1651 			   const cairo_rectangle_int_t *extents,
1652 			   int *tx, int *ty)
1653 {
1654     *tx = *ty = 0;
1655 
1656     if (pattern == NULL)
1657 	return _pixman_white_image ();
1658 
1659     switch (pattern->type) {
1660     default:
1661 	ASSERT_NOT_REACHED;
1662     case CAIRO_PATTERN_TYPE_SOLID:
1663 	return _pixman_image_for_solid ((const cairo_solid_pattern_t *) pattern);
1664 
1665     case CAIRO_PATTERN_TYPE_RADIAL:
1666     case CAIRO_PATTERN_TYPE_LINEAR:
1667 	return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
1668 					   extents, tx, ty);
1669 
1670     case CAIRO_PATTERN_TYPE_SURFACE:
1671 	return _pixman_image_for_surface ((const cairo_surface_pattern_t *) pattern,
1672 					  is_mask, extents, tx, ty);
1673     }
1674 }
1675 
1676 static cairo_status_t
_cairo_image_surface_fixup_unbounded(cairo_image_surface_t * dst,const cairo_composite_rectangles_t * rects,cairo_clip_t * clip)1677 _cairo_image_surface_fixup_unbounded (cairo_image_surface_t *dst,
1678 				      const cairo_composite_rectangles_t *rects,
1679 				      cairo_clip_t *clip)
1680 {
1681     pixman_image_t *mask = NULL;
1682     pixman_box32_t boxes[4];
1683     int i, mask_x = 0, mask_y = 0, n_boxes = 0;
1684 
1685     if (clip != NULL) {
1686 	cairo_surface_t *clip_surface;
1687 	int clip_x, clip_y;
1688 
1689 	clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
1690 	if (unlikely (clip_surface->status))
1691 	    return clip_surface->status;
1692 
1693 	mask = ((cairo_image_surface_t *) clip_surface)->pixman_image;
1694 	mask_x = -clip_x;
1695 	mask_y = -clip_y;
1696     } else {
1697 	if (rects->bounded.width  == rects->unbounded.width &&
1698 	    rects->bounded.height == rects->unbounded.height)
1699 	{
1700 	    return CAIRO_STATUS_SUCCESS;
1701 	}
1702     }
1703 
1704     /* wholly unbounded? */
1705     if (rects->bounded.width == 0 || rects->bounded.height == 0) {
1706 	int x = rects->unbounded.x;
1707 	int y = rects->unbounded.y;
1708 	int width = rects->unbounded.width;
1709 	int height = rects->unbounded.height;
1710 
1711 	if (mask != NULL) {
1712 	    pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
1713                                       mask, NULL, dst->pixman_image,
1714                                       x + mask_x, y + mask_y,
1715                                       0, 0,
1716                                       x, y,
1717                                       width, height);
1718 	} else {
1719             pixman_color_t color = { 0, };
1720             pixman_box32_t box = { x, y, x + width, y + height };
1721 
1722             if (! pixman_image_fill_boxes (PIXMAN_OP_CLEAR,
1723 					   dst->pixman_image,
1724 					   &color,
1725 					   1, &box))
1726 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1727 	}
1728 
1729 	return CAIRO_STATUS_SUCCESS;
1730     }
1731 
1732     /* top */
1733     if (rects->bounded.y != rects->unbounded.y) {
1734         boxes[n_boxes].x1 = rects->unbounded.x;
1735         boxes[n_boxes].y1 = rects->unbounded.y;
1736         boxes[n_boxes].x2 = rects->unbounded.x + rects->unbounded.width;
1737         boxes[n_boxes].y2 = rects->bounded.y;
1738         n_boxes++;
1739     }
1740 
1741     /* left */
1742     if (rects->bounded.x != rects->unbounded.x) {
1743         boxes[n_boxes].x1 = rects->unbounded.x;
1744         boxes[n_boxes].y1 = rects->bounded.y;
1745         boxes[n_boxes].x2 = rects->bounded.x;
1746         boxes[n_boxes].y2 = rects->bounded.y + rects->bounded.height;
1747         n_boxes++;
1748     }
1749 
1750     /* right */
1751     if (rects->bounded.x + rects->bounded.width != rects->unbounded.x + rects->unbounded.width) {
1752         boxes[n_boxes].x1 = rects->bounded.x + rects->bounded.width;
1753         boxes[n_boxes].y1 = rects->bounded.y;
1754         boxes[n_boxes].x2 = rects->unbounded.x + rects->unbounded.width;
1755         boxes[n_boxes].y2 = rects->bounded.y + rects->bounded.height;
1756         n_boxes++;
1757     }
1758 
1759     /* bottom */
1760     if (rects->bounded.y + rects->bounded.height != rects->unbounded.y + rects->unbounded.height) {
1761         boxes[n_boxes].x1 = rects->unbounded.x;
1762         boxes[n_boxes].y1 = rects->bounded.y + rects->bounded.height;
1763         boxes[n_boxes].x2 = rects->unbounded.x + rects->unbounded.width;
1764         boxes[n_boxes].y2 = rects->unbounded.y + rects->unbounded.height;
1765         n_boxes++;
1766     }
1767 
1768     if (mask != NULL) {
1769         for (i = 0; i < n_boxes; i++) {
1770             pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
1771                                       mask, NULL, dst->pixman_image,
1772                                       boxes[i].x1 + mask_x, boxes[i].y1 + mask_y,
1773                                       0, 0,
1774                                       boxes[i].x1, boxes[i].y1,
1775                                       boxes[i].x2 - boxes[i].x1, boxes[i].y2 - boxes[i].y1);
1776         }
1777     } else {
1778         pixman_color_t color = { 0, };
1779 
1780         if (! pixman_image_fill_boxes (PIXMAN_OP_CLEAR,
1781 				       dst->pixman_image,
1782 				       &color,
1783 				       n_boxes,
1784 				       boxes))
1785 	{
1786 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1787 	}
1788     }
1789 
1790     return CAIRO_STATUS_SUCCESS;
1791 }
1792 
1793 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)1794 _cairo_image_surface_fixup_unbounded_boxes (cairo_image_surface_t *dst,
1795 					    const cairo_composite_rectangles_t *extents,
1796 					    cairo_region_t *clip_region,
1797 					    cairo_boxes_t *boxes)
1798 {
1799     cairo_boxes_t clear;
1800     cairo_box_t box;
1801     cairo_status_t status;
1802     struct _cairo_boxes_chunk *chunk;
1803     int i;
1804 
1805     if (boxes->num_boxes <= 1 && clip_region == NULL)
1806 	return _cairo_image_surface_fixup_unbounded (dst, extents, NULL);
1807 
1808     _cairo_boxes_init (&clear);
1809 
1810     box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
1811     box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
1812     box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
1813     box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
1814 
1815     if (clip_region == NULL) {
1816 	cairo_boxes_t tmp;
1817 
1818 	_cairo_boxes_init (&tmp);
1819 
1820 	status = _cairo_boxes_add (&tmp, &box);
1821 	assert (status == CAIRO_STATUS_SUCCESS);
1822 
1823 	tmp.chunks.next = &boxes->chunks;
1824 	tmp.num_boxes += boxes->num_boxes;
1825 
1826 	status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
1827 							  CAIRO_FILL_RULE_WINDING,
1828 							  &clear);
1829 
1830 	tmp.chunks.next = NULL;
1831     } else {
1832 	pixman_box32_t *pbox;
1833 
1834 	pbox = pixman_region32_rectangles (&clip_region->rgn, &i);
1835 	_cairo_boxes_limit (&clear, (cairo_box_t *) pbox, i);
1836 
1837 	status = _cairo_boxes_add (&clear, &box);
1838 	assert (status == CAIRO_STATUS_SUCCESS);
1839 
1840 	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1841 	    for (i = 0; i < chunk->count; i++) {
1842 		status = _cairo_boxes_add (&clear, &chunk->base[i]);
1843 		if (unlikely (status)) {
1844 		    _cairo_boxes_fini (&clear);
1845 		    return status;
1846 		}
1847 	    }
1848 	}
1849 
1850 	status = _cairo_bentley_ottmann_tessellate_boxes (&clear,
1851 							  CAIRO_FILL_RULE_WINDING,
1852 							  &clear);
1853     }
1854 
1855     if (likely (status == CAIRO_STATUS_SUCCESS)) {
1856 	for (chunk = &clear.chunks; chunk != NULL; chunk = chunk->next) {
1857 	    for (i = 0; i < chunk->count; i++) {
1858 		int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
1859 		int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
1860 		int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
1861 		int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
1862 
1863 		pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
1864 			     PIXMAN_FORMAT_BPP (dst->pixman_format),
1865 			     x1, y1, x2 - x1, y2 - y1,
1866 			     0);
1867 	    }
1868 	}
1869     }
1870 
1871     _cairo_boxes_fini (&clear);
1872 
1873     return status;
1874 }
1875 
1876 static cairo_bool_t
can_reduce_alpha_op(cairo_operator_t op)1877 can_reduce_alpha_op (cairo_operator_t op)
1878 {
1879     int iop = op;
1880     switch (iop) {
1881     case CAIRO_OPERATOR_OVER:
1882     case CAIRO_OPERATOR_SOURCE:
1883     case CAIRO_OPERATOR_ADD:
1884 	return TRUE;
1885     default:
1886 	return FALSE;
1887     }
1888 }
1889 
1890 static cairo_bool_t
reduce_alpha_op(cairo_image_surface_t * dst,cairo_operator_t op,const cairo_pattern_t * pattern)1891 reduce_alpha_op (cairo_image_surface_t *dst,
1892 		 cairo_operator_t op,
1893 		 const cairo_pattern_t *pattern)
1894 {
1895     return dst->base.is_clear &&
1896 	   dst->base.content == CAIRO_CONTENT_ALPHA &&
1897 	   _cairo_pattern_is_opaque_solid (pattern) &&
1898 	   can_reduce_alpha_op (op);
1899 }
1900 
1901 /* low level compositor */
1902 typedef cairo_status_t
1903 (*image_draw_func_t) (void				*closure,
1904 		      pixman_image_t			*dst,
1905 		      pixman_format_code_t		 dst_format,
1906 		      cairo_operator_t			 op,
1907 		      const cairo_pattern_t		*src,
1908 		      int				 dst_x,
1909 		      int				 dst_y,
1910 		      const cairo_rectangle_int_t	*extents,
1911 		      cairo_region_t			*clip_region);
1912 
1913 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)1914 _create_composite_mask_pattern (cairo_clip_t                  *clip,
1915 				image_draw_func_t              draw_func,
1916 				void                          *draw_closure,
1917 				cairo_image_surface_t         *dst,
1918 				const cairo_rectangle_int_t   *extents)
1919 {
1920     cairo_region_t *clip_region = NULL;
1921     pixman_image_t *mask;
1922     cairo_status_t status;
1923     cairo_bool_t need_clip_surface = FALSE;
1924 
1925     if (clip != NULL) {
1926 	status = _cairo_clip_get_region (clip, &clip_region);
1927 	assert (! _cairo_status_is_error (status));
1928 
1929 	/* The all-clipped state should never propagate this far. */
1930 	assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
1931 
1932 	need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
1933 
1934 	if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
1935 	    clip_region = NULL;
1936     }
1937 
1938     mask = pixman_image_create_bits (PIXMAN_a8, extents->width, extents->height,
1939 				     NULL, 0);
1940     if (unlikely (mask == NULL))
1941 	return NULL;
1942 
1943     /* Is it worth setting the clip region here? */
1944     if (clip_region != NULL) {
1945 	pixman_bool_t ret;
1946 
1947 	pixman_region32_translate (&clip_region->rgn, -extents->x, -extents->y);
1948 	ret = pixman_image_set_clip_region32 (mask, &clip_region->rgn);
1949 	pixman_region32_translate (&clip_region->rgn, extents->x, extents->y);
1950 
1951 	if (! ret) {
1952 	    pixman_image_unref (mask);
1953 	    return NULL;
1954 	}
1955     }
1956 
1957     status = draw_func (draw_closure,
1958 			mask, PIXMAN_a8,
1959 			CAIRO_OPERATOR_ADD, NULL,
1960 			extents->x, extents->y,
1961 			extents, NULL);
1962     if (unlikely (status)) {
1963 	pixman_image_unref (mask);
1964 	return NULL;
1965     }
1966 
1967     if (need_clip_surface) {
1968 	cairo_surface_t *tmp;
1969 
1970 	tmp = _cairo_image_surface_create_for_pixman_image (mask, PIXMAN_a8);
1971 	if (unlikely (tmp->status)) {
1972 	    pixman_image_unref (mask);
1973 	    return NULL;
1974 	}
1975 
1976 	pixman_image_ref (mask);
1977 
1978 	status = _cairo_clip_combine_with_surface (clip, tmp, extents->x, extents->y);
1979 	cairo_surface_destroy (tmp);
1980 	if (unlikely (status)) {
1981 	    pixman_image_unref (mask);
1982 	    return NULL;
1983 	}
1984     }
1985 
1986     if (clip_region != NULL)
1987 	pixman_image_set_clip_region (mask, NULL);
1988 
1989     return mask;
1990 }
1991 
1992 /* Handles compositing with a clip surface when the operator allows
1993  * us to combine the clip with the mask
1994  */
1995 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)1996 _clip_and_composite_with_mask (cairo_clip_t                  *clip,
1997 			       cairo_operator_t               op,
1998 			       const cairo_pattern_t         *pattern,
1999 			       image_draw_func_t              draw_func,
2000 			       void                          *draw_closure,
2001 			       cairo_image_surface_t         *dst,
2002 			       const cairo_rectangle_int_t   *extents)
2003 {
2004     pixman_image_t *mask;
2005 
2006     mask = _create_composite_mask_pattern (clip, draw_func, draw_closure, dst, extents);
2007     if (unlikely (mask == NULL))
2008 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2009 
2010     if (pattern == NULL) {
2011 	if (dst->pixman_format == PIXMAN_a8) {
2012 	    pixman_image_composite32 (_pixman_operator (op),
2013                                       mask, NULL, dst->pixman_image,
2014                                       0, 0, 0, 0,
2015                                       extents->x,      extents->y,
2016                                       extents->width,  extents->height);
2017 	} else {
2018 	    pixman_image_t *src;
2019 
2020 	    src = _pixman_white_image ();
2021 	    if (unlikely (src == NULL)) {
2022 		pixman_image_unref (mask);
2023 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2024 	    }
2025 
2026 	    pixman_image_composite32 (_pixman_operator (op),
2027                                       src, mask, dst->pixman_image,
2028                                       0, 0, 0, 0,
2029                                       extents->x,      extents->y,
2030                                       extents->width,  extents->height);
2031 	    pixman_image_unref (src);
2032 	}
2033     } else {
2034 	pixman_image_t *src;
2035 	int src_x, src_y;
2036 
2037 	src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
2038 	if (unlikely (src == NULL)) {
2039 	    pixman_image_unref (mask);
2040 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2041 	}
2042 
2043 	pixman_image_composite32 (_pixman_operator (op),
2044                                   src, mask, dst->pixman_image,
2045                                   extents->x + src_x,  extents->y + src_y,
2046                                   0, 0,
2047                                   extents->x,          extents->y,
2048                                   extents->width,      extents->height);
2049 	pixman_image_unref (src);
2050     }
2051 
2052     pixman_image_unref (mask);
2053 
2054     return CAIRO_STATUS_SUCCESS;
2055 }
2056 
2057 /* Handles compositing with a clip surface when we have to do the operation
2058  * in two pieces and combine them together.
2059  */
2060 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)2061 _clip_and_composite_combine (cairo_clip_t                  *clip,
2062 			     cairo_operator_t               op,
2063 			     const cairo_pattern_t         *src,
2064 			     image_draw_func_t              draw_func,
2065 			     void                          *draw_closure,
2066 			     cairo_image_surface_t               *dst,
2067 			     const cairo_rectangle_int_t   *extents)
2068 {
2069     pixman_image_t *tmp;
2070     cairo_surface_t *clip_surface;
2071     int clip_x, clip_y;
2072     cairo_status_t status;
2073 
2074     tmp  = pixman_image_create_bits (dst->pixman_format,
2075 				     extents->width, extents->height,
2076 				     NULL, 0);
2077     if (unlikely (tmp == NULL))
2078 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2079 
2080     if (src == NULL) {
2081 	status = (*draw_func) (draw_closure,
2082 			       tmp, dst->pixman_format,
2083 			       CAIRO_OPERATOR_ADD, NULL,
2084 			       extents->x, extents->y,
2085 			       extents, NULL);
2086     } else {
2087 	/* Initialize the temporary surface from the destination surface */
2088 	if (! dst->base.is_clear) {
2089 	    pixman_image_composite32 (PIXMAN_OP_SRC,
2090                                       dst->pixman_image, NULL, tmp,
2091                                       extents->x, extents->y,
2092                                       0, 0,
2093                                       0, 0,
2094                                       extents->width, extents->height);
2095 	}
2096 
2097 	status = (*draw_func) (draw_closure,
2098 			       tmp, dst->pixman_format,
2099 			       op, src,
2100 			       extents->x, extents->y,
2101 			       extents, NULL);
2102     }
2103     if (unlikely (status))
2104 	goto CLEANUP_SURFACE;
2105 
2106     assert (clip->path != NULL);
2107     clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
2108     if (unlikely (clip_surface->status))
2109 	goto CLEANUP_SURFACE;
2110 
2111     if (! dst->base.is_clear) {
2112 #if PIXMAN_HAS_OP_LERP
2113 	pixman_image_composite32 (PIXMAN_OP_LERP,
2114                                   tmp,
2115                                   ((cairo_image_surface_t *) clip_surface)->pixman_image,
2116                                   dst->pixman_image,
2117                                   0, 0,
2118                                   extents->x - clip_x,
2119                                   extents->y - clip_y,
2120                                   extents->x, extents->y,
2121                                   extents->width, extents->height);
2122 #else
2123 	/* Punch the clip out of the destination */
2124 	pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2125                                   ((cairo_image_surface_t *) clip_surface)->pixman_image,
2126                                   NULL, dst->pixman_image,
2127                                   extents->x - clip_x,
2128                                   extents->y - clip_y,
2129                                   0, 0,
2130                                   extents->x, extents->y,
2131                                   extents->width, extents->height);
2132 
2133 	/* Now add the two results together */
2134 	pixman_image_composite32 (PIXMAN_OP_ADD,
2135                                   tmp,
2136                                   ((cairo_image_surface_t *) clip_surface)->pixman_image,
2137                                   dst->pixman_image,
2138                                   0, 0,
2139                                   extents->x - clip_x,
2140                                   extents->y - clip_y,
2141                                   extents->x, extents->y,
2142                                   extents->width, extents->height);
2143 #endif
2144     } else {
2145 	pixman_image_composite32 (PIXMAN_OP_SRC,
2146                                   tmp,
2147                                   ((cairo_image_surface_t *) clip_surface)->pixman_image,
2148                                   dst->pixman_image,
2149                                   0, 0,
2150                                   extents->x - clip_x,
2151                                   extents->y - clip_y,
2152                                   extents->x, extents->y,
2153                                   extents->width, extents->height);
2154     }
2155 
2156  CLEANUP_SURFACE:
2157     pixman_image_unref (tmp);
2158 
2159     return status;
2160 }
2161 
2162 /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
2163  * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
2164  */
2165 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)2166 _clip_and_composite_source (cairo_clip_t                  *clip,
2167 			    const cairo_pattern_t         *pattern,
2168 			    image_draw_func_t              draw_func,
2169 			    void                          *draw_closure,
2170 			    cairo_image_surface_t         *dst,
2171 			    const cairo_rectangle_int_t   *extents)
2172 {
2173     pixman_image_t *mask, *src;
2174     int src_x, src_y;
2175 
2176     if (pattern == NULL) {
2177 	cairo_region_t *clip_region;
2178 	cairo_status_t status;
2179 
2180 	status = draw_func (draw_closure,
2181 			    dst->pixman_image, dst->pixman_format,
2182 			    CAIRO_OPERATOR_SOURCE, NULL,
2183 			    extents->x, extents->y,
2184 			    extents, NULL);
2185 	if (unlikely (status))
2186 	    return status;
2187 
2188 	if (_cairo_clip_get_region (clip, &clip_region) == CAIRO_INT_STATUS_UNSUPPORTED)
2189 	    status = _cairo_clip_combine_with_surface (clip, &dst->base, 0, 0);
2190 
2191 	return status;
2192     }
2193 
2194     /* Create a surface that is mask IN clip */
2195     mask = _create_composite_mask_pattern (clip, draw_func, draw_closure, dst, extents);
2196     if (unlikely (mask == NULL))
2197 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2198 
2199     src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
2200     if (unlikely (src == NULL)) {
2201 	pixman_image_unref (mask);
2202 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2203     }
2204 
2205     if (! dst->base.is_clear) {
2206 #if PIXMAN_HAS_OP_LERP
2207 	pixman_image_composite32 (PIXMAN_OP_LERP,
2208                                   src, mask, dst->pixman_image,
2209                                   extents->x + src_x, extents->y + src_y,
2210                                   0, 0,
2211                                   extents->x,     extents->y,
2212                                   extents->width, extents->height);
2213 #else
2214 	/* Compute dest' = dest OUT (mask IN clip) */
2215 	pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2216                                   mask, NULL, dst->pixman_image,
2217                                   0, 0, 0, 0,
2218                                   extents->x,     extents->y,
2219                                   extents->width, extents->height);
2220 
2221 	/* Now compute (src IN (mask IN clip)) ADD dest' */
2222 	pixman_image_composite32 (PIXMAN_OP_ADD,
2223                                   src, mask, dst->pixman_image,
2224                                   extents->x + src_x, extents->y + src_y,
2225                                   0, 0,
2226                                   extents->x,     extents->y,
2227                                   extents->width, extents->height);
2228 #endif
2229     } else {
2230 	pixman_image_composite32 (PIXMAN_OP_SRC,
2231                                   src, mask, dst->pixman_image,
2232                                   extents->x + src_x, extents->y + src_y,
2233                                   0, 0,
2234                                   extents->x,     extents->y,
2235                                   extents->width, extents->height);
2236     }
2237 
2238     pixman_image_unref (src);
2239     pixman_image_unref (mask);
2240 
2241     return CAIRO_STATUS_SUCCESS;
2242 }
2243 
2244 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)2245 _clip_and_composite (cairo_image_surface_t	*dst,
2246 		     cairo_operator_t		 op,
2247 		     const cairo_pattern_t	*src,
2248 		     image_draw_func_t		 draw_func,
2249 		     void			*draw_closure,
2250 		     cairo_composite_rectangles_t*extents,
2251 		     cairo_clip_t		*clip)
2252 {
2253     cairo_status_t status;
2254     cairo_region_t *clip_region = NULL;
2255     cairo_bool_t need_clip_surface = FALSE;
2256 
2257     if (clip != NULL) {
2258 	status = _cairo_clip_get_region (clip, &clip_region);
2259 	if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
2260 	    return CAIRO_STATUS_SUCCESS;
2261 	if (unlikely (_cairo_status_is_error (status)))
2262 	    return status;
2263 
2264 	need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
2265 
2266 	if (clip_region != NULL) {
2267 	    cairo_rectangle_int_t rect;
2268 	    cairo_bool_t is_empty;
2269 
2270 	    cairo_region_get_extents (clip_region, &rect);
2271 	    is_empty = ! _cairo_rectangle_intersect (&extents->unbounded, &rect);
2272 	    if (unlikely (is_empty))
2273 		return CAIRO_STATUS_SUCCESS;
2274 
2275 	    is_empty = ! _cairo_rectangle_intersect (&extents->bounded, &rect);
2276 	    if (unlikely (is_empty && extents->is_bounded))
2277 		return CAIRO_STATUS_SUCCESS;
2278 
2279 	    if (cairo_region_num_rectangles (clip_region) == 1)
2280 		clip_region = NULL;
2281 	}
2282     }
2283 
2284     if (clip_region != NULL) {
2285 	status = _cairo_image_surface_set_clip_region (dst, clip_region);
2286 	if (unlikely (status))
2287 	    return status;
2288     }
2289 
2290     if (reduce_alpha_op (dst, op, src)) {
2291 	op = CAIRO_OPERATOR_ADD;
2292 	src = NULL;
2293     }
2294 
2295     if (op == CAIRO_OPERATOR_SOURCE) {
2296 	status = _clip_and_composite_source (clip, src,
2297 					     draw_func, draw_closure,
2298 					     dst, &extents->bounded);
2299     } else {
2300 	if (op == CAIRO_OPERATOR_CLEAR) {
2301 	    src = NULL;
2302 	    op = CAIRO_OPERATOR_DEST_OUT;
2303 	}
2304 
2305 	if (need_clip_surface) {
2306 	    if (extents->is_bounded) {
2307 		status = _clip_and_composite_with_mask (clip, op, src,
2308 							draw_func, draw_closure,
2309 							dst, &extents->bounded);
2310 	    } else {
2311 		status = _clip_and_composite_combine (clip, op, src,
2312 						      draw_func, draw_closure,
2313 						      dst, &extents->bounded);
2314 	    }
2315 	} else {
2316 	    status = draw_func (draw_closure,
2317 				dst->pixman_image, dst->pixman_format,
2318 				op, src,
2319 				0, 0,
2320 				&extents->bounded,
2321 				clip_region);
2322 	}
2323     }
2324 
2325     if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
2326 	status = _cairo_image_surface_fixup_unbounded (dst, extents,
2327 						       need_clip_surface ? clip : NULL);
2328     }
2329 
2330     if (clip_region != NULL)
2331 	_cairo_image_surface_unset_clip_region (dst);
2332 
2333     return status;
2334 }
2335 
2336 #define CAIRO_FIXED_16_16_MIN _cairo_fixed_from_int (-32768)
2337 #define CAIRO_FIXED_16_16_MAX _cairo_fixed_from_int (32767)
2338 
2339 static cairo_bool_t
_line_exceeds_16_16(const cairo_line_t * line)2340 _line_exceeds_16_16 (const cairo_line_t *line)
2341 {
2342     return
2343 	line->p1.x <= CAIRO_FIXED_16_16_MIN ||
2344 	line->p1.x >= CAIRO_FIXED_16_16_MAX ||
2345 
2346 	line->p2.x <= CAIRO_FIXED_16_16_MIN ||
2347 	line->p2.x >= CAIRO_FIXED_16_16_MAX ||
2348 
2349 	line->p1.y <= CAIRO_FIXED_16_16_MIN ||
2350 	line->p1.y >= CAIRO_FIXED_16_16_MAX ||
2351 
2352 	line->p2.y <= CAIRO_FIXED_16_16_MIN ||
2353 	line->p2.y >= CAIRO_FIXED_16_16_MAX;
2354 }
2355 
2356 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)2357 _project_line_x_onto_16_16 (const cairo_line_t *line,
2358 			    cairo_fixed_t top,
2359 			    cairo_fixed_t bottom,
2360 			    pixman_line_fixed_t *out)
2361 {
2362     cairo_point_double_t p1, p2;
2363     double m;
2364 
2365     p1.x = _cairo_fixed_to_double (line->p1.x);
2366     p1.y = _cairo_fixed_to_double (line->p1.y);
2367 
2368     p2.x = _cairo_fixed_to_double (line->p2.x);
2369     p2.y = _cairo_fixed_to_double (line->p2.y);
2370 
2371     m = (p2.x - p1.x) / (p2.y - p1.y);
2372     out->p1.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (top - line->p1.y));
2373     out->p2.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (bottom - line->p1.y));
2374 }
2375 
2376 
2377 typedef struct {
2378     cairo_trapezoid_t *traps;
2379     int num_traps;
2380     cairo_antialias_t antialias;
2381 } composite_traps_info_t;
2382 
2383 static void
_pixman_image_add_traps(pixman_image_t * image,int dst_x,int dst_y,composite_traps_info_t * info)2384 _pixman_image_add_traps (pixman_image_t *image,
2385 			 int dst_x, int dst_y,
2386 			 composite_traps_info_t *info)
2387 {
2388     cairo_trapezoid_t *t = info->traps;
2389     int num_traps = info->num_traps;
2390     while (num_traps--) {
2391 	pixman_trapezoid_t trap;
2392 
2393 	/* top/bottom will be clamped to surface bounds */
2394 	trap.top = _cairo_fixed_to_16_16 (t->top);
2395 	trap.bottom = _cairo_fixed_to_16_16 (t->bottom);
2396 
2397 	/* However, all the other coordinates will have been left untouched so
2398 	 * as not to introduce numerical error. Recompute them if they
2399 	 * exceed the 16.16 limits.
2400 	 */
2401 	if (unlikely (_line_exceeds_16_16 (&t->left))) {
2402 	    _project_line_x_onto_16_16 (&t->left, t->top, t->bottom, &trap.left);
2403 	    trap.left.p1.y = trap.top;
2404 	    trap.left.p2.y = trap.bottom;
2405 	} else {
2406 	    trap.left.p1.x = _cairo_fixed_to_16_16 (t->left.p1.x);
2407 	    trap.left.p1.y = _cairo_fixed_to_16_16 (t->left.p1.y);
2408 	    trap.left.p2.x = _cairo_fixed_to_16_16 (t->left.p2.x);
2409 	    trap.left.p2.y = _cairo_fixed_to_16_16 (t->left.p2.y);
2410 	}
2411 
2412 	if (unlikely (_line_exceeds_16_16 (&t->right))) {
2413 	    _project_line_x_onto_16_16 (&t->right, t->top, t->bottom, &trap.right);
2414 	    trap.right.p1.y = trap.top;
2415 	    trap.right.p2.y = trap.bottom;
2416 	} else {
2417 	    trap.right.p1.x = _cairo_fixed_to_16_16 (t->right.p1.x);
2418 	    trap.right.p1.y = _cairo_fixed_to_16_16 (t->right.p1.y);
2419 	    trap.right.p2.x = _cairo_fixed_to_16_16 (t->right.p2.x);
2420 	    trap.right.p2.y = _cairo_fixed_to_16_16 (t->right.p2.y);
2421 	}
2422 
2423 	pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y);
2424 
2425 	t++;
2426     }
2427 }
2428 
2429 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)2430 _composite_traps (void                          *closure,
2431 		  pixman_image_t		*dst,
2432 		  pixman_format_code_t		 dst_format,
2433 		  cairo_operator_t               op,
2434 		  const cairo_pattern_t         *pattern,
2435 		  int                            dst_x,
2436 		  int                            dst_y,
2437 		  const cairo_rectangle_int_t   *extents,
2438 		  cairo_region_t		*clip_region)
2439 {
2440     composite_traps_info_t *info = closure;
2441     pixman_image_t *src, *mask;
2442     pixman_format_code_t format;
2443     int src_x = 0, src_y = 0;
2444     cairo_status_t status;
2445 
2446     /* Special case adding trapezoids onto a mask surface; we want to avoid
2447      * creating an intermediate temporary mask unnecessarily.
2448      *
2449      * We make the assumption here that the portion of the trapezoids
2450      * contained within the surface is bounded by [dst_x,dst_y,width,height];
2451      * the Cairo core code passes bounds based on the trapezoid extents.
2452      */
2453     format = info->antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8;
2454     if (dst_format == format &&
2455 	(pattern == NULL ||
2456 	 (op == CAIRO_OPERATOR_ADD && _cairo_pattern_is_opaque_solid (pattern))))
2457     {
2458 	_pixman_image_add_traps (dst, dst_x, dst_y, info);
2459 	return CAIRO_STATUS_SUCCESS;
2460     }
2461 
2462     src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
2463     if (unlikely (src == NULL))
2464 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2465 
2466     mask = pixman_image_create_bits (format, extents->width, extents->height,
2467 				     NULL, 0);
2468     if (unlikely (mask == NULL)) {
2469 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2470 	goto CLEANUP_SOURCE;
2471     }
2472 
2473     _pixman_image_add_traps (mask, extents->x, extents->y, info);
2474     pixman_image_composite32 (_pixman_operator (op),
2475                               src, mask, dst,
2476                               extents->x + src_x, extents->y + src_y,
2477                               0, 0,
2478                               extents->x - dst_x, extents->y - dst_y,
2479                               extents->width, extents->height);
2480 
2481     pixman_image_unref (mask);
2482 
2483     status = CAIRO_STATUS_SUCCESS;
2484  CLEANUP_SOURCE:
2485     pixman_image_unref (src);
2486 
2487     return status;
2488 }
2489 
2490 static inline uint32_t
color_to_uint32(const cairo_color_t * color)2491 color_to_uint32 (const cairo_color_t *color)
2492 {
2493     return
2494         (color->alpha_short >> 8 << 24) |
2495         (color->red_short >> 8 << 16)   |
2496         (color->green_short & 0xff00)   |
2497         (color->blue_short >> 8);
2498 }
2499 
2500 static inline cairo_bool_t
color_to_pixel(const cairo_color_t * color,pixman_format_code_t format,uint32_t * pixel)2501 color_to_pixel (const cairo_color_t	*color,
2502                 pixman_format_code_t	 format,
2503                 uint32_t		*pixel)
2504 {
2505     uint32_t c;
2506 
2507     if (!(format == PIXMAN_a8r8g8b8     ||
2508           format == PIXMAN_x8r8g8b8     ||
2509           format == PIXMAN_a8b8g8r8     ||
2510           format == PIXMAN_x8b8g8r8     ||
2511           format == PIXMAN_b8g8r8a8     ||
2512           format == PIXMAN_b8g8r8x8     ||
2513           format == PIXMAN_r5g6b5       ||
2514           format == PIXMAN_b5g6r5       ||
2515           format == PIXMAN_a8))
2516     {
2517 	return FALSE;
2518     }
2519 
2520     c = color_to_uint32 (color);
2521 
2522     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) {
2523 	c = ((c & 0xff000000) >>  0) |
2524 	    ((c & 0x00ff0000) >> 16) |
2525 	    ((c & 0x0000ff00) >>  0) |
2526 	    ((c & 0x000000ff) << 16);
2527     }
2528 
2529     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) {
2530 	c = ((c & 0xff000000) >> 24) |
2531 	    ((c & 0x00ff0000) >>  8) |
2532 	    ((c & 0x0000ff00) <<  8) |
2533 	    ((c & 0x000000ff) << 24);
2534     }
2535 
2536     if (format == PIXMAN_a8) {
2537 	c = c >> 24;
2538     } else if (format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5) {
2539 	c = ((((c) >> 3) & 0x001f) |
2540 	     (((c) >> 5) & 0x07e0) |
2541 	     (((c) >> 8) & 0xf800));
2542     }
2543 
2544     *pixel = c;
2545     return TRUE;
2546 }
2547 
2548 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)2549 pattern_to_pixel (const cairo_solid_pattern_t *solid,
2550 		  cairo_operator_t op,
2551 		  pixman_format_code_t format,
2552 		  uint32_t *pixel)
2553 {
2554     if (op == CAIRO_OPERATOR_CLEAR) {
2555 	*pixel = 0;
2556 	return TRUE;
2557     }
2558 
2559     if (solid->base.type != CAIRO_PATTERN_TYPE_SOLID)
2560 	return FALSE;
2561 
2562     if (op == CAIRO_OPERATOR_OVER) {
2563 	if (solid->color.alpha_short >= 0xff00)
2564 	    op = CAIRO_OPERATOR_SOURCE;
2565     }
2566 
2567     if (op != CAIRO_OPERATOR_SOURCE)
2568 	return FALSE;
2569 
2570     return color_to_pixel (&solid->color, format, pixel);
2571 }
2572 
2573 typedef struct _fill_span {
2574     cairo_span_renderer_t base;
2575 
2576     uint8_t *mask_data;
2577     pixman_image_t *src, *dst, *mask;
2578 } fill_span_renderer_t;
2579 
2580 static cairo_status_t
_fill_span(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * spans,unsigned num_spans)2581 _fill_span (void *abstract_renderer,
2582 	    int y, int height,
2583 	    const cairo_half_open_span_t *spans,
2584 	    unsigned num_spans)
2585 {
2586     fill_span_renderer_t *renderer = abstract_renderer;
2587     uint8_t *row;
2588     unsigned i;
2589 
2590     if (num_spans == 0)
2591 	return CAIRO_STATUS_SUCCESS;
2592 
2593     row = renderer->mask_data - spans[0].x;
2594     for (i = 0; i < num_spans - 1; i++) {
2595 	/* We implement setting the most common single pixel wide
2596 	 * span case to avoid the overhead of a memset call.
2597 	 * Open coding setting longer spans didn't show a
2598 	 * noticeable improvement over memset.
2599 	 */
2600 	if (spans[i+1].x == spans[i].x + 1) {
2601 	    row[spans[i].x] = spans[i].coverage;
2602 	} else {
2603 	    memset (row + spans[i].x,
2604 		    spans[i].coverage,
2605 		    spans[i+1].x - spans[i].x);
2606 	}
2607     }
2608 
2609     do {
2610 	pixman_image_composite32 (PIXMAN_OP_OVER,
2611                                   renderer->src, renderer->mask, renderer->dst,
2612                                   0, 0, 0, 0,
2613                                   spans[0].x, y++,
2614                                   spans[i].x - spans[0].x, 1);
2615     } while (--height);
2616 
2617     return CAIRO_STATUS_SUCCESS;
2618 }
2619 
2620 /* avoid using region code to re-validate boxes */
2621 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)2622 _fill_unaligned_boxes (cairo_image_surface_t *dst,
2623 		       const cairo_pattern_t *pattern,
2624 		       uint32_t pixel,
2625 		       const cairo_boxes_t *boxes,
2626 		       const cairo_composite_rectangles_t *extents)
2627 {
2628     uint8_t buf[CAIRO_STACK_BUFFER_SIZE];
2629     fill_span_renderer_t renderer;
2630     cairo_rectangular_scan_converter_t converter;
2631     const struct _cairo_boxes_chunk *chunk;
2632     cairo_status_t status;
2633     int i;
2634 
2635     /* XXX
2636      * using composite for fill:
2637      *   spiral-box-nonalign-evenodd-fill.512    2201957    2.202
2638      *   spiral-box-nonalign-nonzero-fill.512     336726    0.337
2639      *   spiral-box-pixalign-evenodd-fill.512     352256    0.352
2640      *   spiral-box-pixalign-nonzero-fill.512     147056    0.147
2641      * using fill:
2642      *   spiral-box-nonalign-evenodd-fill.512    3174565    3.175
2643      *   spiral-box-nonalign-nonzero-fill.512     182710    0.183
2644      *   spiral-box-pixalign-evenodd-fill.512     353863    0.354
2645      *   spiral-box-pixalign-nonzero-fill.512     147402    0.147
2646      *
2647      * cairo-perf-trace seems to favour using fill.
2648      */
2649 
2650     renderer.base.render_rows = _fill_span;
2651     renderer.dst = dst->pixman_image;
2652 
2653     if ((unsigned) extents->bounded.width <= sizeof (buf)) {
2654 	renderer.mask = pixman_image_create_bits (PIXMAN_a8,
2655 						  extents->bounded.width, 1,
2656 						  (uint32_t *) buf,
2657 						  sizeof (buf));
2658     } else {
2659 	renderer.mask = pixman_image_create_bits (PIXMAN_a8,
2660 						  extents->bounded.width, 1,
2661 						  NULL,  0);
2662     }
2663     if (unlikely (renderer.mask == NULL))
2664 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2665 
2666     renderer.mask_data = (uint8_t *) pixman_image_get_data (renderer.mask);
2667 
2668     renderer.src = _pixman_image_for_solid ((const cairo_solid_pattern_t *) pattern);
2669     if (unlikely (renderer.src == NULL)) {
2670 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2671 	goto CLEANUP_MASK;
2672     }
2673 
2674     _cairo_rectangular_scan_converter_init (&converter, &extents->bounded);
2675 
2676     /* first blit any aligned part of the boxes */
2677     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2678 	const cairo_box_t *box = chunk->base;
2679 
2680 	for (i = 0; i < chunk->count; i++) {
2681 	    int x1 = _cairo_fixed_integer_ceil (box[i].p1.x);
2682 	    int y1 = _cairo_fixed_integer_ceil (box[i].p1.y);
2683 	    int x2 = _cairo_fixed_integer_floor (box[i].p2.x);
2684 	    int y2 = _cairo_fixed_integer_floor (box[i].p2.y);
2685 
2686 	    if (x2 > x1 && y2 > y1) {
2687 		cairo_box_t b;
2688 
2689 		pixman_fill ((uint32_t *) dst->data,
2690 			     dst->stride / sizeof (uint32_t),
2691 			     PIXMAN_FORMAT_BPP (dst->pixman_format),
2692 			     x1, y1, x2 - x1, y2 - y1,
2693 			     pixel);
2694 
2695 		/*
2696 		 * Corners have to be included only once if the rects
2697 		 * are passed to the rectangular scan converter
2698 		 * because it can only handle disjoint rectangles.
2699 		*/
2700 
2701 		/* top (including top-left and top-right corners) */
2702 		if (! _cairo_fixed_is_integer (box[i].p1.y)) {
2703 		    b.p1.x = box[i].p1.x;
2704 		    b.p1.y = box[i].p1.y;
2705 		    b.p2.x = box[i].p2.x;
2706 		    b.p2.y = _cairo_fixed_from_int (y1);
2707 
2708 		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
2709 		    if (unlikely (status))
2710 			goto CLEANUP_CONVERTER;
2711 		}
2712 
2713 		/* left (no corners) */
2714 		if (! _cairo_fixed_is_integer (box[i].p1.x)) {
2715 		    b.p1.x = box[i].p1.x;
2716 		    b.p1.y = _cairo_fixed_from_int (y1);
2717 		    b.p2.x = _cairo_fixed_from_int (x1);
2718 		    b.p2.y = _cairo_fixed_from_int (y2);
2719 
2720 		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
2721 		    if (unlikely (status))
2722 			goto CLEANUP_CONVERTER;
2723 		}
2724 
2725 		/* right (no corners) */
2726 		if (! _cairo_fixed_is_integer (box[i].p2.x)) {
2727 		    b.p1.x = _cairo_fixed_from_int (x2);
2728 		    b.p1.y = _cairo_fixed_from_int (y1);
2729 		    b.p2.x = box[i].p2.x;
2730 		    b.p2.y = _cairo_fixed_from_int (y2);
2731 
2732 		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
2733 		    if (unlikely (status))
2734 			goto CLEANUP_CONVERTER;
2735 		}
2736 
2737 		/* bottom (including bottom-left and bottom-right corners) */
2738 		if (! _cairo_fixed_is_integer (box[i].p2.y)) {
2739 		    b.p1.x = box[i].p1.x;
2740 		    b.p1.y = _cairo_fixed_from_int (y2);
2741 		    b.p2.x = box[i].p2.x;
2742 		    b.p2.y = box[i].p2.y;
2743 
2744 		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
2745 		    if (unlikely (status))
2746 			goto CLEANUP_CONVERTER;
2747 		}
2748 	    } else {
2749 		status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
2750 		if (unlikely (status))
2751 		    goto CLEANUP_CONVERTER;
2752 	    }
2753 	}
2754     }
2755 
2756     status = converter.base.generate (&converter.base, &renderer.base);
2757 
2758   CLEANUP_CONVERTER:
2759     converter.base.destroy (&converter.base);
2760     pixman_image_unref (renderer.src);
2761   CLEANUP_MASK:
2762     pixman_image_unref (renderer.mask);
2763 
2764     return status;
2765 }
2766 
2767 typedef struct _cairo_image_surface_span_renderer {
2768     cairo_span_renderer_t base;
2769 
2770     uint8_t *mask_data;
2771     uint32_t mask_stride;
2772 } cairo_image_surface_span_renderer_t;
2773 
2774 static cairo_status_t
_cairo_image_surface_span(void * abstract_renderer,int y,int height,const cairo_half_open_span_t * spans,unsigned num_spans)2775 _cairo_image_surface_span (void *abstract_renderer,
2776 			   int y, int height,
2777 			   const cairo_half_open_span_t *spans,
2778 			   unsigned num_spans)
2779 {
2780     cairo_image_surface_span_renderer_t *renderer = abstract_renderer;
2781     uint8_t *row;
2782     unsigned i;
2783 
2784     if (num_spans == 0)
2785 	return CAIRO_STATUS_SUCCESS;
2786 
2787     /* XXX will it be quicker to repeat the sparse memset,
2788      * or perform a simpler memcpy?
2789      * The fairly dense spiral benchmarks suggests that the sparse
2790      * memset is a win there as well.
2791      */
2792     row = renderer->mask_data + y * renderer->mask_stride;
2793     do {
2794 	for (i = 0; i < num_spans - 1; i++) {
2795 	    if (! spans[i].coverage)
2796 		continue;
2797 
2798 	    /* We implement setting rendering the most common single
2799 	     * pixel wide span case to avoid the overhead of a memset
2800 	     * call.  Open coding setting longer spans didn't show a
2801 	     * noticeable improvement over memset. */
2802 	    if (spans[i+1].x == spans[i].x + 1) {
2803 		row[spans[i].x] = spans[i].coverage;
2804 	    } else {
2805 		memset (row + spans[i].x,
2806 			spans[i].coverage,
2807 			spans[i+1].x - spans[i].x);
2808 	    }
2809 	}
2810 	row += renderer->mask_stride;
2811     } while (--height);
2812 
2813     return CAIRO_STATUS_SUCCESS;
2814 }
2815 
2816 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)2817 _composite_unaligned_boxes (cairo_image_surface_t *dst,
2818 			    cairo_operator_t op,
2819 			    const cairo_pattern_t *pattern,
2820 			    const cairo_boxes_t *boxes,
2821 			    const cairo_composite_rectangles_t *extents)
2822 {
2823     uint8_t buf[CAIRO_STACK_BUFFER_SIZE];
2824     cairo_image_surface_span_renderer_t renderer;
2825     cairo_rectangular_scan_converter_t converter;
2826     pixman_image_t *mask, *src;
2827     cairo_status_t status;
2828     const struct _cairo_boxes_chunk *chunk;
2829     int i, src_x, src_y;
2830 
2831     i = CAIRO_STRIDE_FOR_WIDTH_BPP (extents->bounded.width, 8) * extents->bounded.height;
2832     if ((unsigned) i <= sizeof (buf)) {
2833 	mask = pixman_image_create_bits (PIXMAN_a8,
2834 					 extents->bounded.width,
2835 					 extents->bounded.height,
2836 					 (uint32_t *) buf,
2837 					 CAIRO_STRIDE_FOR_WIDTH_BPP (extents->bounded.width, 8));
2838 	memset (buf, 0, i);
2839     } else {
2840 	mask = pixman_image_create_bits (PIXMAN_a8,
2841 					 extents->bounded.width,
2842 					 extents->bounded.height,
2843 					 NULL,  0);
2844     }
2845     if (unlikely (mask == NULL))
2846 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2847 
2848     renderer.base.render_rows = _cairo_image_surface_span;
2849     renderer.mask_stride = pixman_image_get_stride (mask);
2850     renderer.mask_data = (uint8_t *) pixman_image_get_data (mask);
2851     renderer.mask_data -= extents->bounded.y * renderer.mask_stride + extents->bounded.x;
2852 
2853     _cairo_rectangular_scan_converter_init (&converter, &extents->bounded);
2854 
2855     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2856 	const cairo_box_t *box = chunk->base;
2857 
2858 	for (i = 0; i < chunk->count; i++) {
2859 	    status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
2860 	    if (unlikely (status))
2861 		goto CLEANUP;
2862 	}
2863     }
2864 
2865     status = converter.base.generate (&converter.base, &renderer.base);
2866     if (unlikely (status))
2867 	goto CLEANUP;
2868 
2869     src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &src_x, &src_y);
2870     if (unlikely (src == NULL)) {
2871 	status =  _cairo_error (CAIRO_STATUS_NO_MEMORY);
2872 	goto CLEANUP;
2873     }
2874 
2875     pixman_image_composite32 (_pixman_operator (op),
2876                               src, mask, dst->pixman_image,
2877                               extents->bounded.x + src_x, extents->bounded.y + src_y,
2878                               0, 0,
2879                               extents->bounded.x, extents->bounded.y,
2880                               extents->bounded.width, extents->bounded.height);
2881     pixman_image_unref (src);
2882 
2883   CLEANUP:
2884     converter.base.destroy (&converter.base);
2885     pixman_image_unref (mask);
2886 
2887     return status;
2888 }
2889 
2890 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)2891 _composite_boxes (cairo_image_surface_t *dst,
2892 		  cairo_operator_t op,
2893 		  const cairo_pattern_t *pattern,
2894 		  cairo_boxes_t *boxes,
2895 		  cairo_antialias_t antialias,
2896 		  cairo_clip_t *clip,
2897 		  const cairo_composite_rectangles_t *extents)
2898 {
2899     cairo_region_t *clip_region = NULL;
2900     cairo_bool_t need_clip_mask = FALSE;
2901     cairo_status_t status;
2902     struct _cairo_boxes_chunk *chunk;
2903     uint32_t pixel;
2904     int i;
2905 
2906     if (clip != NULL) {
2907 	status = _cairo_clip_get_region (clip, &clip_region);
2908 	need_clip_mask = status == CAIRO_INT_STATUS_UNSUPPORTED;
2909 	if (need_clip_mask &&
2910 	    (op == CAIRO_OPERATOR_SOURCE || ! extents->is_bounded))
2911 	{
2912 	    return CAIRO_INT_STATUS_UNSUPPORTED;
2913 	}
2914 
2915 	if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
2916 	    clip_region = NULL;
2917     }
2918 
2919     if (antialias != CAIRO_ANTIALIAS_NONE) {
2920 	if (! boxes->is_pixel_aligned) {
2921 	    if (need_clip_mask)
2922 		return CAIRO_INT_STATUS_UNSUPPORTED;
2923 
2924 	    if (pattern_to_pixel ((cairo_solid_pattern_t *) pattern, op,
2925 				  dst->pixman_format, &pixel))
2926 	    {
2927 		return _fill_unaligned_boxes (dst, pattern, pixel, boxes, extents);
2928 	    }
2929 	    else
2930 	    {
2931 		return _composite_unaligned_boxes (dst, op, pattern, boxes, extents);
2932 	    }
2933 	}
2934     }
2935 
2936     status = CAIRO_STATUS_SUCCESS;
2937     if (! need_clip_mask &&
2938 	pattern_to_pixel ((cairo_solid_pattern_t *) pattern, op, dst->pixman_format,
2939 			  &pixel))
2940     {
2941 	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2942 	    cairo_box_t *box = chunk->base;
2943 
2944 	    for (i = 0; i < chunk->count; i++) {
2945 		int x1 = _cairo_fixed_integer_round_down (box[i].p1.x);
2946 		int y1 = _cairo_fixed_integer_round_down (box[i].p1.y);
2947 		int x2 = _cairo_fixed_integer_round_down (box[i].p2.x);
2948 		int y2 = _cairo_fixed_integer_round_down (box[i].p2.y);
2949 
2950 		if (x2 == x1 || y2 == y1)
2951 		    continue;
2952 
2953 		pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
2954 			     PIXMAN_FORMAT_BPP (dst->pixman_format),
2955 			     x1, y1, x2 - x1, y2 - y1,
2956 			     pixel);
2957 	    }
2958 	}
2959     }
2960     else
2961     {
2962 	pixman_image_t *src = NULL, *mask = NULL;
2963 	int src_x, src_y, mask_x = 0, mask_y = 0;
2964 	pixman_op_t pixman_op = _pixman_operator (op);
2965 
2966 	if (need_clip_mask) {
2967 	    cairo_surface_t *clip_surface;
2968 	    int clip_x, clip_y;
2969 
2970 	    clip_surface = _cairo_clip_get_surface (clip, &dst->base, &clip_x, &clip_y);
2971 	    if (unlikely (clip_surface->status))
2972 		return clip_surface->status;
2973 
2974 	    mask_x = -clip_x;
2975 	    mask_y = -clip_y;
2976 
2977 	    if (op == CAIRO_OPERATOR_CLEAR) {
2978 		pattern = NULL;
2979 		pixman_op = PIXMAN_OP_OUT_REVERSE;
2980 	    }
2981 
2982 	    mask = ((cairo_image_surface_t *) clip_surface)->pixman_image;
2983 	}
2984 
2985 	if (pattern != NULL) {
2986 	    src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &src_x, &src_y);
2987 	    if (unlikely (src == NULL))
2988 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2989 	} else {
2990 	    src = mask;
2991 	    src_x = mask_x;
2992 	    src_y = mask_y;
2993 	    mask = NULL;
2994 	}
2995 
2996 	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2997 	    const cairo_box_t *box = chunk->base;
2998 
2999 	    for (i = 0; i < chunk->count; i++) {
3000 		int x1 = _cairo_fixed_integer_round_down (box[i].p1.x);
3001 		int y1 = _cairo_fixed_integer_round_down (box[i].p1.y);
3002 		int x2 = _cairo_fixed_integer_round_down (box[i].p2.x);
3003 		int y2 = _cairo_fixed_integer_round_down (box[i].p2.y);
3004 
3005 		if (x2 == x1 || y2 == y1)
3006 		    continue;
3007 
3008 		pixman_image_composite32 (pixman_op,
3009                                           src, mask, dst->pixman_image,
3010                                           x1 + src_x,  y1 + src_y,
3011                                           x1 + mask_x, y1 + mask_y,
3012                                           x1, y1,
3013                                           x2 - x1, y2 - y1);
3014 	    }
3015 	}
3016 
3017 	if (pattern != NULL)
3018 	    pixman_image_unref (src);
3019 
3020 	if (! extents->is_bounded) {
3021 	    status =
3022 		_cairo_image_surface_fixup_unbounded_boxes (dst, extents,
3023 							    clip_region, boxes);
3024 	}
3025     }
3026 
3027     return status;
3028 }
3029 
3030 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)3031 _clip_and_composite_boxes (cairo_image_surface_t *dst,
3032 			   cairo_operator_t op,
3033 			   const cairo_pattern_t *src,
3034 			   cairo_boxes_t *boxes,
3035 			   cairo_antialias_t antialias,
3036 			   cairo_composite_rectangles_t *extents,
3037 			   cairo_clip_t *clip)
3038 {
3039     cairo_traps_t traps;
3040     cairo_status_t status;
3041     composite_traps_info_t info;
3042 
3043     if (boxes->num_boxes == 0 && extents->is_bounded)
3044 	return CAIRO_STATUS_SUCCESS;
3045 
3046     /* Use a fast path if the boxes are pixel aligned */
3047     status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents);
3048     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3049 	return status;
3050 
3051     /* Otherwise render via a mask and composite in the usual fashion.  */
3052     status = _cairo_traps_init_boxes (&traps, boxes);
3053     if (unlikely (status))
3054 	return status;
3055 
3056     info.num_traps = traps.num_traps;
3057     info.traps = traps.traps;
3058     info.antialias = antialias;
3059     status = _clip_and_composite (dst, op, src,
3060 				  _composite_traps, &info,
3061 				  extents, clip);
3062 
3063     _cairo_traps_fini (&traps);
3064     return status;
3065 }
3066 
3067 static cairo_bool_t
_mono_edge_is_vertical(const cairo_line_t * line)3068 _mono_edge_is_vertical (const cairo_line_t *line)
3069 {
3070     return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
3071 }
3072 
3073 static cairo_bool_t
_traps_are_pixel_aligned(cairo_traps_t * traps,cairo_antialias_t antialias)3074 _traps_are_pixel_aligned (cairo_traps_t *traps,
3075 			  cairo_antialias_t antialias)
3076 {
3077     int i;
3078 
3079     if (antialias == CAIRO_ANTIALIAS_NONE) {
3080 	for (i = 0; i < traps->num_traps; i++) {
3081 	    if (! _mono_edge_is_vertical (&traps->traps[i].left)   ||
3082 		! _mono_edge_is_vertical (&traps->traps[i].right))
3083 	    {
3084 		traps->maybe_region = FALSE;
3085 		return FALSE;
3086 	    }
3087 	}
3088     } else {
3089 	for (i = 0; i < traps->num_traps; i++) {
3090 	    if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
3091 		traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
3092 		! _cairo_fixed_is_integer (traps->traps[i].top)          ||
3093 		! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
3094 		! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
3095 		! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
3096 	    {
3097 		traps->maybe_region = FALSE;
3098 		return FALSE;
3099 	    }
3100 	}
3101     }
3102 
3103     return TRUE;
3104 }
3105 
3106 static void
_boxes_for_traps(cairo_boxes_t * boxes,cairo_traps_t * traps,cairo_antialias_t antialias)3107 _boxes_for_traps (cairo_boxes_t *boxes,
3108 		  cairo_traps_t *traps,
3109 		  cairo_antialias_t antialias)
3110 {
3111     int i;
3112 
3113     _cairo_boxes_init (boxes);
3114 
3115     boxes->num_boxes    = traps->num_traps;
3116     boxes->chunks.base  = (cairo_box_t *) traps->traps;
3117     boxes->chunks.count = traps->num_traps;
3118     boxes->chunks.size  = traps->num_traps;
3119 
3120     if (antialias != CAIRO_ANTIALIAS_NONE) {
3121 	for (i = 0; i < traps->num_traps; i++) {
3122 	    /* Note the traps and boxes alias so we need to take the local copies first. */
3123 	    cairo_fixed_t x1 = traps->traps[i].left.p1.x;
3124 	    cairo_fixed_t x2 = traps->traps[i].right.p1.x;
3125 	    cairo_fixed_t y1 = traps->traps[i].top;
3126 	    cairo_fixed_t y2 = traps->traps[i].bottom;
3127 
3128 	    boxes->chunks.base[i].p1.x = x1;
3129 	    boxes->chunks.base[i].p1.y = y1;
3130 	    boxes->chunks.base[i].p2.x = x2;
3131 	    boxes->chunks.base[i].p2.y = y2;
3132 
3133 	    if (boxes->is_pixel_aligned) {
3134 		boxes->is_pixel_aligned =
3135 		    _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
3136 		    _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
3137 	    }
3138 	}
3139     } else {
3140 	boxes->is_pixel_aligned = TRUE;
3141 
3142 	for (i = 0; i < traps->num_traps; i++) {
3143 	    /* Note the traps and boxes alias so we need to take the local copies first. */
3144 	    cairo_fixed_t x1 = traps->traps[i].left.p1.x;
3145 	    cairo_fixed_t x2 = traps->traps[i].right.p1.x;
3146 	    cairo_fixed_t y1 = traps->traps[i].top;
3147 	    cairo_fixed_t y2 = traps->traps[i].bottom;
3148 
3149 	    /* round down here to match Pixman's behavior when using traps. */
3150 	    boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
3151 	    boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
3152 	    boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
3153 	    boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
3154 	}
3155     }
3156 }
3157 
3158 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)3159 _clip_and_composite_trapezoids (cairo_image_surface_t *dst,
3160 				cairo_operator_t op,
3161 				const cairo_pattern_t *src,
3162 				cairo_traps_t *traps,
3163 				cairo_antialias_t antialias,
3164 				cairo_composite_rectangles_t *extents,
3165 				cairo_clip_t *clip)
3166 {
3167     composite_traps_info_t info;
3168     cairo_bool_t need_clip_surface = FALSE;
3169     cairo_status_t status;
3170 
3171     if (traps->num_traps == 0 && extents->is_bounded)
3172 	return CAIRO_STATUS_SUCCESS;
3173 
3174     if (clip != NULL) {
3175 	cairo_region_t *clip_region;
3176 
3177 	status = _cairo_clip_get_region (clip, &clip_region);
3178 	need_clip_surface = status == CAIRO_INT_STATUS_UNSUPPORTED;
3179     }
3180 
3181     if (traps->has_intersections) {
3182 	if (traps->is_rectangular)
3183 	    status = _cairo_bentley_ottmann_tessellate_rectangular_traps (traps, CAIRO_FILL_RULE_WINDING);
3184 	else if (traps->is_rectilinear)
3185 	    status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (traps, CAIRO_FILL_RULE_WINDING);
3186 	else
3187 	    status = _cairo_bentley_ottmann_tessellate_traps (traps, CAIRO_FILL_RULE_WINDING);
3188 	if (unlikely (status))
3189 	    return status;
3190     }
3191 
3192     /* Use a fast path if the trapezoids consist of a simple region,
3193      * but we can only do this if we do not have a clip surface, or can
3194      * substitute the mask with the clip.
3195      */
3196     if (traps->maybe_region && _traps_are_pixel_aligned (traps, antialias) &&
3197 	(! need_clip_surface ||
3198 	 (extents->is_bounded && op != CAIRO_OPERATOR_SOURCE)))
3199     {
3200 	cairo_boxes_t boxes;
3201 
3202 	_boxes_for_traps (&boxes, traps, antialias);
3203 	return _clip_and_composite_boxes (dst, op, src,
3204 					  &boxes, antialias,
3205 					  extents, clip);
3206     }
3207 
3208     /* No fast path, exclude self-intersections and clip trapezoids. */
3209     /* Otherwise render the trapezoids to a mask and composite in the usual
3210      * fashion.
3211      */
3212     info.traps = traps->traps;
3213     info.num_traps = traps->num_traps;
3214     info.antialias = antialias;
3215     return _clip_and_composite (dst, op, src,
3216 				_composite_traps, &info,
3217 				extents, clip);
3218 }
3219 
3220 static cairo_clip_path_t *
_clip_get_single_path(cairo_clip_t * clip)3221 _clip_get_single_path (cairo_clip_t *clip)
3222 {
3223     cairo_clip_path_t *iter = clip->path;
3224     cairo_clip_path_t *path = NULL;
3225 
3226     do {
3227 	if ((iter->flags & CAIRO_CLIP_PATH_IS_BOX) == 0) {
3228 	    if (path != NULL)
3229 		return FALSE;
3230 
3231 	    path = iter;
3232 	}
3233 	iter = iter->prev;
3234     } while (iter != NULL);
3235 
3236     return path;
3237 }
3238 
3239 /* high level image interface */
3240 
3241 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)3242 _cairo_image_surface_paint (void			*abstract_surface,
3243 			    cairo_operator_t		 op,
3244 			    const cairo_pattern_t	*source,
3245 			    cairo_clip_t		*clip)
3246 {
3247     cairo_image_surface_t *surface = abstract_surface;
3248     cairo_composite_rectangles_t extents;
3249     cairo_clip_path_t *clip_path;
3250     cairo_clip_t local_clip;
3251     cairo_bool_t have_clip = FALSE;
3252     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
3253     int num_boxes = ARRAY_LENGTH (boxes_stack);
3254     cairo_status_t status;
3255 
3256     status = _cairo_composite_rectangles_init_for_paint (&extents,
3257 							 surface->width,
3258 							 surface->height,
3259 							 op, source,
3260 							 clip);
3261     if (unlikely (status))
3262 	return status;
3263 
3264     if (_cairo_clip_contains_extents (clip, &extents))
3265 	clip = NULL;
3266 
3267     if (clip != NULL) {
3268 	clip = _cairo_clip_init_copy (&local_clip, clip);
3269 	have_clip = TRUE;
3270     }
3271 
3272     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
3273     if (unlikely (status)) {
3274 	if (have_clip)
3275 	    _cairo_clip_fini (&local_clip);
3276 
3277 	return status;
3278     }
3279 
3280     /* If the clip cannot be reduced to a set of boxes, we will need to
3281      * use a clipmask. Paint is special as it is the only operation that
3282      * does not implicitly use a mask, so we may be able to reduce this
3283      * operation to a fill...
3284      */
3285     if (clip != NULL &&
3286 	extents.is_bounded &&
3287 	(clip_path = _clip_get_single_path (clip)) != NULL)
3288     {
3289 	status = _cairo_image_surface_fill (surface, op, source,
3290 					    &clip_path->path,
3291 					    clip_path->fill_rule,
3292 					    clip_path->tolerance,
3293 					    clip_path->antialias,
3294 					    NULL);
3295     }
3296     else
3297     {
3298 	cairo_boxes_t boxes;
3299 
3300 	_cairo_boxes_init_for_array (&boxes, clip_boxes, num_boxes);
3301 	status = _clip_and_composite_boxes (surface, op, source,
3302 					    &boxes, CAIRO_ANTIALIAS_DEFAULT,
3303 					    &extents, clip);
3304     }
3305 
3306     if (clip_boxes != boxes_stack)
3307 	free (clip_boxes);
3308 
3309     if (have_clip)
3310 	_cairo_clip_fini (&local_clip);
3311 
3312     return status;
3313 }
3314 
3315 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)3316 _composite_mask (void				*closure,
3317 		 pixman_image_t			*dst,
3318 		 pixman_format_code_t		 dst_format,
3319 		 cairo_operator_t		 op,
3320 		 const cairo_pattern_t		*src_pattern,
3321 		 int				 dst_x,
3322 		 int				 dst_y,
3323 		 const cairo_rectangle_int_t	*extents,
3324 		 cairo_region_t			*clip_region)
3325 {
3326     const cairo_pattern_t *mask_pattern = closure;
3327     pixman_image_t *src, *mask = NULL;
3328     int src_x = 0, src_y = 0;
3329     int mask_x = 0, mask_y = 0;
3330 
3331     if (src_pattern != NULL) {
3332 	src = _pixman_image_for_pattern (src_pattern, FALSE, extents, &src_x, &src_y);
3333 	if (unlikely (src == NULL))
3334 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3335 
3336 	mask = _pixman_image_for_pattern (mask_pattern, TRUE, extents, &mask_x, &mask_y);
3337 	if (unlikely (mask == NULL)) {
3338 	    pixman_image_unref (src);
3339 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3340 	}
3341 
3342 	if (mask_pattern->has_component_alpha)
3343 	    pixman_image_set_component_alpha (mask, TRUE);
3344     } else {
3345 	src = _pixman_image_for_pattern (mask_pattern, FALSE, extents, &src_x, &src_y);
3346 	if (unlikely (src == NULL))
3347 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3348     }
3349 
3350     pixman_image_composite32 (_pixman_operator (op), src, mask, dst,
3351                               extents->x + src_x,  extents->y + src_y,
3352                               extents->x + mask_x, extents->y + mask_y,
3353                               extents->x - dst_x,  extents->y - dst_y,
3354                               extents->width,      extents->height);
3355 
3356     if (mask != NULL)
3357 	pixman_image_unref (mask);
3358     pixman_image_unref (src);
3359 
3360     return CAIRO_STATUS_SUCCESS;
3361 }
3362 
3363 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)3364 _cairo_image_surface_mask (void				*abstract_surface,
3365 			   cairo_operator_t		 op,
3366 			   const cairo_pattern_t	*source,
3367 			   const cairo_pattern_t	*mask,
3368 			   cairo_clip_t			*clip)
3369 {
3370     cairo_image_surface_t *surface = abstract_surface;
3371     cairo_composite_rectangles_t extents;
3372     cairo_clip_t local_clip;
3373     cairo_bool_t have_clip = FALSE;
3374     cairo_status_t status;
3375 
3376     status = _cairo_composite_rectangles_init_for_mask (&extents,
3377 							surface->width, surface->height,
3378 							op, source, mask, clip);
3379     if (unlikely (status))
3380 	return status;
3381 
3382     if (_cairo_clip_contains_extents (clip, &extents))
3383 	clip = NULL;
3384 
3385     if (clip != NULL && extents.is_bounded) {
3386 	clip = _cairo_clip_init_copy (&local_clip, clip);
3387 	status = _cairo_clip_rectangle (clip, &extents.bounded);
3388 	if (unlikely (status)) {
3389 	    _cairo_clip_fini (&local_clip);
3390 	    return status;
3391 	}
3392 
3393 	have_clip = TRUE;
3394     }
3395 
3396     status = _clip_and_composite (surface, op, source,
3397 				  _composite_mask, (void *) mask,
3398 				  &extents, clip);
3399 
3400     if (have_clip)
3401 	_cairo_clip_fini (&local_clip);
3402 
3403     return status;
3404 }
3405 
3406 typedef struct {
3407     cairo_polygon_t		*polygon;
3408     cairo_fill_rule_t		 fill_rule;
3409     cairo_antialias_t		 antialias;
3410 } composite_spans_info_t;
3411 
3412 //#define USE_BOTOR_SCAN_CONVERTER
3413 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)3414 _composite_spans (void                          *closure,
3415 		  pixman_image_t		*dst,
3416 		  pixman_format_code_t		 dst_format,
3417 		  cairo_operator_t               op,
3418 		  const cairo_pattern_t         *pattern,
3419 		  int                            dst_x,
3420 		  int                            dst_y,
3421 		  const cairo_rectangle_int_t   *extents,
3422 		  cairo_region_t		*clip_region)
3423 {
3424     uint8_t mask_buf[CAIRO_STACK_BUFFER_SIZE];
3425     composite_spans_info_t *info = closure;
3426     cairo_image_surface_span_renderer_t renderer;
3427 #if USE_BOTOR_SCAN_CONVERTER
3428     cairo_box_t box;
3429     cairo_botor_scan_converter_t converter;
3430 #else
3431     cairo_scan_converter_t *converter;
3432 #endif
3433     pixman_image_t *mask;
3434     cairo_status_t status;
3435 
3436 #if USE_BOTOR_SCAN_CONVERTER
3437     box.p1.x = _cairo_fixed_from_int (extents->x);
3438     box.p1.y = _cairo_fixed_from_int (extents->y);
3439     box.p2.x = _cairo_fixed_from_int (extents->x + extents->width);
3440     box.p2.y = _cairo_fixed_from_int (extents->y + extents->height);
3441     _cairo_botor_scan_converter_init (&converter, &box, info->fill_rule);
3442     status = converter.base.add_polygon (&converter.base, info->polygon);
3443 #else
3444     converter = _cairo_tor_scan_converter_create (extents->x, extents->y,
3445 						  extents->x + extents->width,
3446 						  extents->y + extents->height,
3447 						  info->fill_rule);
3448     status = converter->add_polygon (converter, info->polygon);
3449 #endif
3450     if (unlikely (status))
3451 	goto CLEANUP_CONVERTER;
3452 
3453     /* TODO: support rendering to A1 surfaces (or: go add span
3454      * compositing to pixman.) */
3455 
3456     if (pattern == NULL &&
3457 	dst_format == PIXMAN_a8 &&
3458 	op == CAIRO_OPERATOR_SOURCE)
3459     {
3460 	mask = dst;
3461 	dst = NULL;
3462     }
3463     else
3464     {
3465 	int stride = CAIRO_STRIDE_FOR_WIDTH_BPP (extents->width, 8);
3466 	uint8_t *data = mask_buf;
3467 
3468 	if (extents->height * stride <= (int) sizeof (mask_buf))
3469 	    memset (data, 0, extents->height * stride);
3470 	else
3471 	    data = NULL, stride = 0;
3472 
3473 	mask = pixman_image_create_bits (PIXMAN_a8,
3474 					 extents->width,
3475 					 extents->height,
3476 					 (uint32_t *) data,
3477 					 stride);
3478 	if (unlikely (mask == NULL)) {
3479 	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3480 	    goto CLEANUP_CONVERTER;
3481 	}
3482     }
3483 
3484     renderer.base.render_rows = _cairo_image_surface_span;
3485     renderer.mask_stride = pixman_image_get_stride (mask);
3486     renderer.mask_data = (uint8_t *) pixman_image_get_data (mask);
3487     if (dst != NULL)
3488 	renderer.mask_data -= extents->y * renderer.mask_stride + extents->x;
3489     else
3490 	renderer.mask_data -= dst_y * renderer.mask_stride + dst_x;
3491 
3492 #if USE_BOTOR_SCAN_CONVERTER
3493     status = converter.base.generate (&converter.base, &renderer.base);
3494 #else
3495     status = converter->generate (converter, &renderer.base);
3496 #endif
3497     if (unlikely (status))
3498 	goto CLEANUP_RENDERER;
3499 
3500     if (dst != NULL) {
3501 	pixman_image_t *src;
3502 	int src_x, src_y;
3503 
3504 	src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
3505 	if (unlikely (src == NULL)) {
3506 	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3507 	    goto CLEANUP_RENDERER;
3508 	}
3509 
3510 	pixman_image_composite32 (_pixman_operator (op), src, mask, dst,
3511                                   extents->x + src_x, extents->y + src_y,
3512                                   0, 0, /* mask.x, mask.y */
3513                                   extents->x - dst_x, extents->y - dst_y,
3514                                   extents->width, extents->height);
3515 	pixman_image_unref (src);
3516     }
3517 
3518  CLEANUP_RENDERER:
3519     if (dst != NULL)
3520 	pixman_image_unref (mask);
3521  CLEANUP_CONVERTER:
3522 #if USE_BOTOR_SCAN_CONVERTER
3523     converter.base.destroy (&converter.base);
3524 #else
3525     converter->destroy (converter);
3526 #endif
3527     return status;
3528 }
3529 
3530 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)3531 _clip_and_composite_polygon (cairo_image_surface_t *dst,
3532 			     cairo_operator_t op,
3533 			     const cairo_pattern_t *src,
3534 			     cairo_polygon_t *polygon,
3535 			     cairo_fill_rule_t fill_rule,
3536 			     cairo_antialias_t antialias,
3537 			     cairo_composite_rectangles_t *extents,
3538 			     cairo_clip_t *clip)
3539 {
3540     cairo_status_t status;
3541 
3542     if (polygon->num_edges == 0) {
3543 	cairo_traps_t traps;
3544 
3545 	if (extents->is_bounded)
3546 	    return CAIRO_STATUS_SUCCESS;
3547 
3548 	_cairo_traps_init (&traps);
3549 	status = _clip_and_composite_trapezoids (dst, op, src,
3550 						 &traps, antialias,
3551 						 extents, clip);
3552 	_cairo_traps_fini (&traps);
3553 
3554 	return status;
3555     }
3556 
3557     _cairo_box_round_to_rectangle (&polygon->extents, &extents->mask);
3558     if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask))
3559 	return CAIRO_STATUS_SUCCESS;
3560 
3561     if (antialias != CAIRO_ANTIALIAS_NONE) {
3562 	composite_spans_info_t info;
3563 
3564 	info.polygon = polygon;
3565 	info.fill_rule = fill_rule;
3566 	info.antialias = antialias;
3567 
3568 	status = _clip_and_composite (dst, op, src,
3569 				      _composite_spans, &info,
3570 				      extents, clip);
3571     } else {
3572 	cairo_traps_t traps;
3573 
3574 	_cairo_traps_init (&traps);
3575 
3576 	/* Fall back to trapezoid fills. */
3577 	status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
3578 							    polygon,
3579 							    fill_rule);
3580 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3581 	    status = _clip_and_composite_trapezoids (dst, op, src,
3582 						     &traps, antialias,
3583 						     extents, clip);
3584 	}
3585 
3586 	_cairo_traps_fini (&traps);
3587     }
3588 
3589     return status;
3590 }
3591 
3592 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)3593 _cairo_image_surface_stroke (void			*abstract_surface,
3594 			     cairo_operator_t		 op,
3595 			     const cairo_pattern_t	*source,
3596 			     cairo_path_fixed_t		*path,
3597 			     const cairo_stroke_style_t	*style,
3598 			     const cairo_matrix_t	*ctm,
3599 			     const cairo_matrix_t	*ctm_inverse,
3600 			     double			 tolerance,
3601 			     cairo_antialias_t		 antialias,
3602 			     cairo_clip_t		*clip)
3603 {
3604     cairo_image_surface_t *surface = abstract_surface;
3605     cairo_composite_rectangles_t extents;
3606     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
3607     int num_boxes = ARRAY_LENGTH (boxes_stack);
3608     cairo_clip_t local_clip;
3609     cairo_bool_t have_clip = FALSE;
3610     cairo_status_t status;
3611 
3612     status = _cairo_composite_rectangles_init_for_stroke (&extents,
3613 							  surface->width,
3614 							  surface->height,
3615 							  op, source,
3616 							  path, style, ctm,
3617 							  clip);
3618     if (unlikely (status))
3619 	return status;
3620 
3621     if (_cairo_clip_contains_extents (clip, &extents))
3622 	clip = NULL;
3623 
3624     if (clip != NULL) {
3625 	clip = _cairo_clip_init_copy (&local_clip, clip);
3626 	have_clip = TRUE;
3627     }
3628 
3629     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
3630     if (unlikely (status)) {
3631 	if (have_clip)
3632 	    _cairo_clip_fini (&local_clip);
3633 
3634 	return status;
3635     }
3636 
3637     status = CAIRO_INT_STATUS_UNSUPPORTED;
3638     if (path->is_rectilinear) {
3639 	cairo_boxes_t boxes;
3640 
3641 	_cairo_boxes_init (&boxes);
3642 	_cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
3643 
3644 	status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
3645 								style,
3646 								ctm,
3647 								&boxes);
3648 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3649 	    status = _clip_and_composite_boxes (surface, op, source,
3650 						&boxes, antialias,
3651 						&extents, clip);
3652 	}
3653 
3654 	_cairo_boxes_fini (&boxes);
3655     }
3656 
3657     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
3658 	cairo_polygon_t polygon;
3659 
3660 	_cairo_polygon_init (&polygon);
3661 	_cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
3662 
3663 	status = _cairo_path_fixed_stroke_to_polygon (path,
3664 						      style,
3665 						      ctm, ctm_inverse,
3666 						      tolerance,
3667 						      &polygon);
3668 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3669 	    status = _clip_and_composite_polygon (surface, op, source, &polygon,
3670 						  CAIRO_FILL_RULE_WINDING, antialias,
3671 						  &extents, clip);
3672 	}
3673 
3674 	_cairo_polygon_fini (&polygon);
3675     }
3676 
3677     if (clip_boxes != boxes_stack)
3678 	free (clip_boxes);
3679 
3680     if (have_clip)
3681 	_cairo_clip_fini (&local_clip);
3682 
3683     return status;
3684 }
3685 
3686 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)3687 _cairo_image_surface_fill (void				*abstract_surface,
3688 			   cairo_operator_t		 op,
3689 			   const cairo_pattern_t	*source,
3690 			   cairo_path_fixed_t		*path,
3691 			   cairo_fill_rule_t		 fill_rule,
3692 			   double			 tolerance,
3693 			   cairo_antialias_t		 antialias,
3694 			   cairo_clip_t			*clip)
3695 {
3696     cairo_image_surface_t *surface = abstract_surface;
3697     cairo_composite_rectangles_t extents;
3698     cairo_box_t boxes_stack[32], *clip_boxes = boxes_stack;
3699     cairo_clip_t local_clip;
3700     cairo_bool_t have_clip = FALSE;
3701     int num_boxes = ARRAY_LENGTH (boxes_stack);
3702     cairo_status_t status;
3703 
3704     status = _cairo_composite_rectangles_init_for_fill (&extents,
3705 							surface->width,
3706 							surface->height,
3707 							op, source, path,
3708 							clip);
3709     if (unlikely (status))
3710 	return status;
3711 
3712     if (_cairo_clip_contains_extents (clip, &extents))
3713 	clip = NULL;
3714 
3715     if (extents.is_bounded && clip != NULL) {
3716 	cairo_clip_path_t *clip_path;
3717 
3718 	if (((clip_path = _clip_get_single_path (clip)) != NULL) &&
3719 	    _cairo_path_fixed_equal (&clip_path->path, path))
3720 	{
3721 	    clip = NULL;
3722 	}
3723     }
3724 
3725     if (clip != NULL) {
3726 	clip = _cairo_clip_init_copy (&local_clip, clip);
3727 	have_clip = TRUE;
3728     }
3729 
3730     status = _cairo_clip_to_boxes (&clip, &extents, &clip_boxes, &num_boxes);
3731     if (unlikely (status)) {
3732 	if (have_clip)
3733 	    _cairo_clip_fini (&local_clip);
3734 
3735 	return status;
3736     }
3737 
3738     if (_cairo_path_fixed_is_rectilinear_fill (path)) {
3739 	cairo_boxes_t boxes;
3740 
3741 	_cairo_boxes_init (&boxes);
3742 	_cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
3743 
3744 	status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
3745 							      fill_rule,
3746 							      &boxes);
3747 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3748 	    status = _clip_and_composite_boxes (surface, op, source,
3749 						&boxes, antialias,
3750 						&extents, clip);
3751 	}
3752 
3753 	_cairo_boxes_fini (&boxes);
3754     } else {
3755 	cairo_polygon_t polygon;
3756 
3757 	assert (! path->is_empty_fill);
3758 
3759 	_cairo_polygon_init (&polygon);
3760 	_cairo_polygon_limit (&polygon, clip_boxes, num_boxes);
3761 
3762 	status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
3763 	if (likely (status == CAIRO_STATUS_SUCCESS)) {
3764 	    status = _clip_and_composite_polygon (surface, op, source, &polygon,
3765 						  fill_rule, antialias,
3766 						  &extents, clip);
3767 	}
3768 
3769 	_cairo_polygon_fini (&polygon);
3770     }
3771 
3772     if (clip_boxes != boxes_stack)
3773 	free (clip_boxes);
3774 
3775     if (have_clip)
3776 	_cairo_clip_fini (&local_clip);
3777 
3778     return status;
3779 }
3780 
3781 typedef struct {
3782     cairo_scaled_font_t *font;
3783     cairo_glyph_t *glyphs;
3784     int num_glyphs;
3785 } composite_glyphs_info_t;
3786 
3787 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)3788 _composite_glyphs_via_mask (void			*closure,
3789 			    pixman_image_t		*dst,
3790 			    pixman_format_code_t	 dst_format,
3791 			    cairo_operator_t		 op,
3792 			    const cairo_pattern_t	*pattern,
3793 			    int				 dst_x,
3794 			    int				 dst_y,
3795 			    const cairo_rectangle_int_t	*extents,
3796 			    cairo_region_t		*clip_region)
3797 {
3798     composite_glyphs_info_t *info = closure;
3799     cairo_scaled_font_t *font = info->font;
3800     cairo_glyph_t *glyphs = info->glyphs;
3801     int num_glyphs = info->num_glyphs;
3802     pixman_image_t *mask = NULL;
3803     pixman_image_t *src;
3804     pixman_image_t *white;
3805     pixman_format_code_t mask_format = 0; /* silence gcc */
3806     cairo_status_t status;
3807     int src_x, src_y;
3808     int i;
3809 
3810     src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
3811     if (unlikely (src == NULL))
3812 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3813 
3814     white = _pixman_white_image ();
3815     if (unlikely (white == NULL)) {
3816 	pixman_image_unref (src);
3817 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3818     }
3819 
3820     _cairo_scaled_font_freeze_cache (font);
3821 
3822     for (i = 0; i < num_glyphs; i++) {
3823 	int x, y;
3824 	cairo_image_surface_t *glyph_surface;
3825 	cairo_scaled_glyph_t *scaled_glyph;
3826 
3827 	status = _cairo_scaled_glyph_lookup (font, glyphs[i].index,
3828 					     CAIRO_SCALED_GLYPH_INFO_SURFACE,
3829 					     &scaled_glyph);
3830 
3831 	if (unlikely (status))
3832 	    goto CLEANUP;
3833 
3834 	glyph_surface = scaled_glyph->surface;
3835 
3836 	if (glyph_surface->width == 0 || glyph_surface->height == 0)
3837 	    continue;
3838 
3839 	/* To start, create the mask using the format from the first
3840 	 * glyph. Later we'll deal with different formats. */
3841 	if (mask == NULL) {
3842 	    mask_format = glyph_surface->pixman_format;
3843 	    mask = pixman_image_create_bits (mask_format,
3844 					     extents->width, extents->height,
3845 					     NULL, 0);
3846 	    if (unlikely (mask == NULL)) {
3847 		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3848 		goto CLEANUP;
3849 	    }
3850 
3851 	    if (PIXMAN_FORMAT_RGB (mask_format))
3852 		pixman_image_set_component_alpha (mask, TRUE);
3853 	}
3854 
3855 	/* If we have glyphs of different formats, we "upgrade" the mask
3856 	 * to the wider of the formats. */
3857 	if (glyph_surface->pixman_format != mask_format &&
3858 	    PIXMAN_FORMAT_BPP (mask_format) <
3859 	    PIXMAN_FORMAT_BPP (glyph_surface->pixman_format))
3860 	{
3861 	    pixman_image_t *new_mask;
3862 
3863 	    mask_format = glyph_surface->pixman_format;
3864 	    new_mask = pixman_image_create_bits (mask_format,
3865 						 extents->width, extents->height,
3866 						 NULL, 0);
3867 	    if (unlikely (new_mask == NULL)) {
3868 		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3869 		goto CLEANUP;
3870 	    }
3871 
3872 	    pixman_image_composite32 (PIXMAN_OP_SRC,
3873                                       white, mask, new_mask,
3874                                       0, 0, 0, 0, 0, 0,
3875                                       extents->width, extents->height);
3876 
3877 	    pixman_image_unref (mask);
3878 	    mask = new_mask;
3879 	    if (PIXMAN_FORMAT_RGB (mask_format))
3880 		pixman_image_set_component_alpha (mask, TRUE);
3881 	}
3882 
3883 	/* round glyph locations to the nearest pixel */
3884 	/* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
3885 	x = _cairo_lround (glyphs[i].x -
3886 			   glyph_surface->base.device_transform.x0);
3887 	y = _cairo_lround (glyphs[i].y -
3888 			   glyph_surface->base.device_transform.y0);
3889 	if (glyph_surface->pixman_format == mask_format) {
3890 	    pixman_image_composite32 (PIXMAN_OP_ADD,
3891                                       glyph_surface->pixman_image, NULL, mask,
3892                                       0, 0, 0, 0,
3893                                       x - extents->x, y - extents->y,
3894                                       glyph_surface->width,
3895                                       glyph_surface->height);
3896 	} else {
3897 	    pixman_image_composite32 (PIXMAN_OP_ADD,
3898                                       white, glyph_surface->pixman_image, mask,
3899                                       0, 0, 0, 0,
3900                                       x - extents->x, y - extents->y,
3901                                       glyph_surface->width,
3902                                       glyph_surface->height);
3903 	}
3904     }
3905 
3906     pixman_image_composite32 (_pixman_operator (op),
3907                               src, mask, dst,
3908                               extents->x + src_x, extents->y + src_y,
3909                               0, 0,
3910                               extents->x - dst_x, extents->y - dst_y,
3911                               extents->width,     extents->height);
3912 
3913 CLEANUP:
3914     _cairo_scaled_font_thaw_cache (font);
3915     if (mask != NULL)
3916 	pixman_image_unref (mask);
3917     pixman_image_unref (src);
3918     pixman_image_unref (white);
3919 
3920     return status;
3921 }
3922 
3923 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)3924 _composite_glyphs (void				*closure,
3925 		   pixman_image_t		*dst,
3926 		   pixman_format_code_t		 dst_format,
3927 		   cairo_operator_t		 op,
3928 		   const cairo_pattern_t	*pattern,
3929 		   int				 dst_x,
3930 		   int				 dst_y,
3931 		   const cairo_rectangle_int_t	*extents,
3932 		   cairo_region_t		*clip_region)
3933 {
3934     composite_glyphs_info_t *info = closure;
3935     cairo_scaled_glyph_t *glyph_cache[64];
3936     pixman_op_t pixman_op = _pixman_operator (op);
3937     pixman_image_t *src = NULL;
3938     int src_x = 0, src_y = 0;
3939     cairo_status_t status;
3940     int i;
3941 
3942     if (pattern != NULL) {
3943 	src = _pixman_image_for_pattern (pattern, FALSE, extents, &src_x, &src_y);
3944 	src_x -= dst_x;
3945 	src_y -= dst_y;
3946     } else {
3947 	src = _pixman_white_image ();
3948     }
3949     if (unlikely (src == NULL))
3950 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3951 
3952     memset (glyph_cache, 0, sizeof (glyph_cache));
3953     status = CAIRO_STATUS_SUCCESS;
3954 
3955     _cairo_scaled_font_freeze_cache (info->font);
3956     for (i = 0; i < info->num_glyphs; i++) {
3957 	int x, y;
3958 	cairo_image_surface_t *glyph_surface;
3959 	cairo_scaled_glyph_t *scaled_glyph;
3960 	unsigned long glyph_index = info->glyphs[i].index;
3961 	int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
3962 
3963 	scaled_glyph = glyph_cache[cache_index];
3964 	if (scaled_glyph == NULL ||
3965 	    _cairo_scaled_glyph_index (scaled_glyph) != glyph_index)
3966 	{
3967 	    status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
3968 						 CAIRO_SCALED_GLYPH_INFO_SURFACE,
3969 						 &scaled_glyph);
3970 
3971 	    if (unlikely (status))
3972 		break;
3973 
3974 	    glyph_cache[cache_index] = scaled_glyph;
3975 	}
3976 
3977 	glyph_surface = scaled_glyph->surface;
3978 	if (glyph_surface->width && glyph_surface->height) {
3979 	    int x1, y1, x2, y2;
3980 
3981 	    /* round glyph locations to the nearest pixel */
3982 	    /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
3983 	    x = _cairo_lround (info->glyphs[i].x -
3984 			       glyph_surface->base.device_transform.x0);
3985 	    y = _cairo_lround (info->glyphs[i].y -
3986 			       glyph_surface->base.device_transform.y0);
3987 
3988 	    x1 = x;
3989 	    if (x1 < extents->x)
3990 		x1 = extents->x;
3991 	    x2 = x + glyph_surface->width;
3992 	    if (x2 > extents->x + extents->width)
3993 		x2 = extents->x + extents->width;
3994 
3995 	    y1 = y;
3996 	    if (y1 < extents->y)
3997 		y1 = extents->y;
3998 	    y2 = y + glyph_surface->height;
3999 	    if (y2 > extents->y + extents->height)
4000 		y2 = extents->y + extents->height;
4001 
4002 	    pixman_image_composite32 (pixman_op,
4003                                       src, glyph_surface->pixman_image, dst,
4004                                       x1 + src_x,  y1 + src_y,
4005                                       x1 - x, y1 - y,
4006                                       x1 - dst_x, y1 - dst_y,
4007                                       x2 - x1, y2 - y1);
4008 	}
4009     }
4010     _cairo_scaled_font_thaw_cache (info->font);
4011 
4012     pixman_image_unref (src);
4013 
4014     return status;
4015 }
4016 
4017 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)4018 _cairo_image_surface_glyphs (void			*abstract_surface,
4019 			     cairo_operator_t		 op,
4020 			     const cairo_pattern_t	*source,
4021 			     cairo_glyph_t		*glyphs,
4022 			     int			 num_glyphs,
4023 			     cairo_scaled_font_t	*scaled_font,
4024 			     cairo_clip_t		*clip,
4025 			     int *num_remaining)
4026 {
4027     cairo_image_surface_t *surface = abstract_surface;
4028     cairo_composite_rectangles_t extents;
4029     composite_glyphs_info_t glyph_info;
4030     cairo_clip_t local_clip;
4031     cairo_bool_t have_clip = FALSE;
4032     cairo_bool_t overlap;
4033     cairo_status_t status;
4034 
4035     status = _cairo_composite_rectangles_init_for_glyphs (&extents,
4036 							  surface->width,
4037 							  surface->height,
4038 							  op, source,
4039 							  scaled_font,
4040 							  glyphs, num_glyphs,
4041 							  clip,
4042 							  &overlap);
4043     if (unlikely (status))
4044 	return status;
4045 
4046     if (_cairo_clip_contains_rectangle (clip, &extents.mask))
4047 	clip = NULL;
4048 
4049     if (clip != NULL && extents.is_bounded) {
4050 	clip = _cairo_clip_init_copy (&local_clip, clip);
4051 	status = _cairo_clip_rectangle (clip, &extents.bounded);
4052 	if (unlikely (status))
4053 	    return status;
4054 
4055 	have_clip = TRUE;
4056     }
4057 
4058     glyph_info.font = scaled_font;
4059     glyph_info.glyphs = glyphs;
4060     glyph_info.num_glyphs = num_glyphs;
4061 
4062     status = _clip_and_composite (surface, op, source,
4063 				  overlap || extents.is_bounded == 0 ? _composite_glyphs_via_mask : _composite_glyphs,
4064 				  &glyph_info,
4065 				  &extents, clip);
4066 
4067     if (have_clip)
4068 	_cairo_clip_fini (&local_clip);
4069 
4070     *num_remaining = 0;
4071     return status;
4072 }
4073 
4074 static cairo_bool_t
_cairo_image_surface_get_extents(void * abstract_surface,cairo_rectangle_int_t * rectangle)4075 _cairo_image_surface_get_extents (void			  *abstract_surface,
4076 				  cairo_rectangle_int_t   *rectangle)
4077 {
4078     cairo_image_surface_t *surface = abstract_surface;
4079 
4080     rectangle->x = 0;
4081     rectangle->y = 0;
4082     rectangle->width  = surface->width;
4083     rectangle->height = surface->height;
4084 
4085     return TRUE;
4086 }
4087 
4088 static void
_cairo_image_surface_get_font_options(void * abstract_surface,cairo_font_options_t * options)4089 _cairo_image_surface_get_font_options (void                  *abstract_surface,
4090 				       cairo_font_options_t  *options)
4091 {
4092     _cairo_font_options_init_default (options);
4093 
4094     cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
4095 }
4096 
4097 /* legacy interface kept for compatibility until surface-fallback is removed */
4098 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)4099 _cairo_image_surface_acquire_dest_image (void                    *abstract_surface,
4100 					 cairo_rectangle_int_t   *interest_rect,
4101 					 cairo_image_surface_t  **image_out,
4102 					 cairo_rectangle_int_t   *image_rect_out,
4103 					 void                   **image_extra)
4104 {
4105     cairo_image_surface_t *surface = abstract_surface;
4106 
4107     image_rect_out->x = 0;
4108     image_rect_out->y = 0;
4109     image_rect_out->width = surface->width;
4110     image_rect_out->height = surface->height;
4111 
4112     *image_out = surface;
4113     *image_extra = NULL;
4114 
4115     return CAIRO_STATUS_SUCCESS;
4116 }
4117 
4118 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)4119 _cairo_image_surface_release_dest_image (void                    *abstract_surface,
4120                                         cairo_rectangle_int_t   *interest_rect,
4121                                         cairo_image_surface_t   *image,
4122                                         cairo_rectangle_int_t   *image_rect,
4123                                         void                    *image_extra)
4124 {
4125 }
4126 
4127 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)4128 _cairo_image_surface_clone_similar (void               *abstract_surface,
4129 				    cairo_surface_t     *src,
4130 				    int                  src_x,
4131 				    int                  src_y,
4132 				    int                  width,
4133 				    int                  height,
4134 				    int                 *clone_offset_x,
4135 				    int                 *clone_offset_y,
4136 				    cairo_surface_t    **clone_out)
4137 {
4138     cairo_image_surface_t *surface = abstract_surface;
4139 
4140     if (src->backend == surface->base.backend) {
4141 	*clone_offset_x = *clone_offset_y = 0;
4142 	*clone_out = cairo_surface_reference (src);
4143 
4144 	return CAIRO_STATUS_SUCCESS;
4145     }
4146 
4147     return CAIRO_INT_STATUS_UNSUPPORTED;
4148 }
4149 
4150 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)4151 _cairo_image_surface_composite (cairo_operator_t	 op,
4152 				const cairo_pattern_t	*src_pattern,
4153 				const cairo_pattern_t	*mask_pattern,
4154 				void			*abstract_dst,
4155 				int			 src_x,
4156 				int			 src_y,
4157 				int			 mask_x,
4158 				int			 mask_y,
4159 				int			 dst_x,
4160 				int			 dst_y,
4161 				unsigned int		 width,
4162 				unsigned int		 height,
4163 				cairo_region_t		*clip_region)
4164 {
4165     cairo_image_surface_t *dst = abstract_dst;
4166     cairo_composite_rectangles_t extents;
4167     pixman_image_t *src;
4168     int src_offset_x, src_offset_y;
4169     cairo_status_t status;
4170 
4171     if (clip_region != NULL) {
4172 	status = _cairo_image_surface_set_clip_region (dst, clip_region);
4173 	if (unlikely (status))
4174 	    return status;
4175     }
4176 
4177     extents.source.x = src_x;
4178     extents.source.y = src_y;
4179     extents.source.width  = width;
4180     extents.source.height = height;
4181 
4182     extents.mask.x = mask_x;
4183     extents.mask.y = mask_y;
4184     extents.mask.width  = width;
4185     extents.mask.height = height;
4186 
4187     extents.bounded.x = dst_x;
4188     extents.bounded.y = dst_y;
4189     extents.bounded.width  = width;
4190     extents.bounded.height = height;
4191 
4192     extents.unbounded.x = 0;
4193     extents.unbounded.y = 0;
4194     extents.unbounded.width  = dst->width;
4195     extents.unbounded.height = dst->height;
4196 
4197     if (clip_region != NULL) {
4198 	cairo_rectangle_int_t rect;
4199 
4200 	cairo_region_get_extents (clip_region, &rect);
4201 	if (! _cairo_rectangle_intersect (&extents.unbounded, &rect))
4202 	    return CAIRO_STATUS_SUCCESS;
4203     }
4204 
4205     extents.is_bounded = _cairo_operator_bounded_by_either (op);
4206 
4207     src = _pixman_image_for_pattern (src_pattern, FALSE, &extents.source, &src_offset_x, &src_offset_y);
4208     if (unlikely (src == NULL))
4209 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4210 
4211     status = CAIRO_STATUS_SUCCESS;
4212     if (mask_pattern != NULL) {
4213 	pixman_image_t *mask;
4214 	int mask_offset_x, mask_offset_y;
4215 
4216 	mask = _pixman_image_for_pattern (mask_pattern, TRUE, &extents.mask, &mask_offset_x, &mask_offset_y);
4217 	if (unlikely (mask == NULL)) {
4218 	    pixman_image_unref (src);
4219 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4220 	}
4221 
4222 	pixman_image_composite32 (_pixman_operator (op),
4223                                   src, mask, dst->pixman_image,
4224                                   src_x + src_offset_x,
4225                                   src_y + src_offset_y,
4226                                   mask_x + mask_offset_x,
4227                                   mask_y + mask_offset_y,
4228 				  dst_x, dst_y, width, height);
4229 
4230 	pixman_image_unref (mask);
4231     } else {
4232 	pixman_image_composite32 (_pixman_operator (op),
4233                                   src, NULL, dst->pixman_image,
4234                                   src_x + src_offset_x,
4235                                   src_y + src_offset_y,
4236                                   0, 0,
4237                                   dst_x, dst_y, width, height);
4238     }
4239 
4240     pixman_image_unref (src);
4241 
4242     if (! extents.is_bounded)
4243 	status = _cairo_image_surface_fixup_unbounded (dst, &extents, NULL);
4244 
4245     if (clip_region != NULL)
4246 	_cairo_image_surface_unset_clip_region (dst);
4247 
4248     return status;
4249 }
4250 
4251 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)4252 _cairo_image_surface_fill_rectangles (void		      *abstract_surface,
4253 				      cairo_operator_t	       op,
4254 				      const cairo_color_t     *color,
4255 				      cairo_rectangle_int_t   *rects,
4256 				      int		       num_rects)
4257 {
4258     cairo_image_surface_t *surface = abstract_surface;
4259 
4260     pixman_color_t pixman_color;
4261     pixman_box32_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
4262     pixman_box32_t *pixman_boxes = stack_boxes;
4263     int i;
4264 
4265     cairo_int_status_t status;
4266 
4267     if (CAIRO_INJECT_FAULT ())
4268 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4269 
4270     pixman_color.red   = color->red_short;
4271     pixman_color.green = color->green_short;
4272     pixman_color.blue  = color->blue_short;
4273     pixman_color.alpha = color->alpha_short;
4274 
4275     if (num_rects > ARRAY_LENGTH (stack_boxes)) {
4276 	pixman_boxes = _cairo_malloc_ab (num_rects, sizeof (pixman_box32_t));
4277 	if (unlikely (pixman_boxes == NULL))
4278 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4279     }
4280 
4281     for (i = 0; i < num_rects; i++) {
4282 	pixman_boxes[i].x1 = rects[i].x;
4283 	pixman_boxes[i].y1 = rects[i].y;
4284 	pixman_boxes[i].x2 = rects[i].x + rects[i].width;
4285 	pixman_boxes[i].y2 = rects[i].y + rects[i].height;
4286     }
4287 
4288     status = CAIRO_STATUS_SUCCESS;
4289     if (! pixman_image_fill_boxes (_pixman_operator (op),
4290                                    surface->pixman_image,
4291                                    &pixman_color,
4292                                    num_rects,
4293                                    pixman_boxes))
4294     {
4295 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
4296     }
4297 
4298     if (pixman_boxes != stack_boxes)
4299 	free (pixman_boxes);
4300 
4301     return status;
4302 }
4303 
4304 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)4305 _cairo_image_surface_composite_trapezoids (cairo_operator_t	op,
4306 					   const cairo_pattern_t *pattern,
4307 					   void			*abstract_dst,
4308 					   cairo_antialias_t	antialias,
4309 					   int			src_x,
4310 					   int			src_y,
4311 					   int			dst_x,
4312 					   int			dst_y,
4313 					   unsigned int		width,
4314 					   unsigned int		height,
4315 					   cairo_trapezoid_t	*traps,
4316 					   int			num_traps,
4317 					   cairo_region_t	*clip_region)
4318 {
4319     cairo_image_surface_t	*dst = abstract_dst;
4320     cairo_composite_rectangles_t extents;
4321     cairo_pattern_union_t        source_pattern;
4322     composite_traps_info_t	 info;
4323     cairo_status_t		 status;
4324 
4325     if (height == 0 || width == 0)
4326 	return CAIRO_STATUS_SUCCESS;
4327 
4328     if (CAIRO_INJECT_FAULT ())
4329 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4330 
4331     extents.source.x = src_x;
4332     extents.source.y = src_y;
4333     extents.source.width  = width;
4334     extents.source.height = height;
4335 
4336     extents.mask.x = dst_x;
4337     extents.mask.y = dst_y;
4338     extents.mask.width  = width;
4339     extents.mask.height = height;
4340 
4341     extents.bounded.x = dst_x;
4342     extents.bounded.y = dst_y;
4343     extents.bounded.width  = width;
4344     extents.bounded.height = height;
4345 
4346     extents.unbounded.x = 0;
4347     extents.unbounded.y = 0;
4348     extents.unbounded.width  = dst->width;
4349     extents.unbounded.height = dst->height;
4350 
4351     if (clip_region != NULL) {
4352 	cairo_rectangle_int_t rect;
4353 
4354 	cairo_region_get_extents (clip_region, &rect);
4355 	if (! _cairo_rectangle_intersect (&extents.unbounded, &rect))
4356 	    return CAIRO_STATUS_SUCCESS;
4357     }
4358 
4359     extents.is_bounded = _cairo_operator_bounded_by_either (op);
4360 
4361     if (clip_region != NULL) {
4362 	status = _cairo_image_surface_set_clip_region (dst, clip_region);
4363 	if (unlikely (status))
4364 	    return status;
4365     }
4366 
4367     _cairo_pattern_init_static_copy (&source_pattern.base, pattern);
4368     cairo_matrix_translate (&source_pattern.base.matrix,
4369                             src_x - extents.bounded.x,
4370                             src_y - extents.bounded.y);
4371 
4372     info.traps = traps;
4373     info.num_traps = num_traps;
4374     info.antialias = antialias;
4375     status = _composite_traps (&info,
4376 			       dst->pixman_image,
4377 			       dst->pixman_format,
4378 			       op,
4379 			       &source_pattern.base,
4380 			       0, 0,
4381 			       &extents.bounded,
4382 			       clip_region);
4383 
4384     if (status == CAIRO_STATUS_SUCCESS && ! extents.is_bounded)
4385 	status = _cairo_image_surface_fixup_unbounded (dst, &extents, NULL);
4386 
4387     if (clip_region != NULL)
4388 	_cairo_image_surface_unset_clip_region (dst);
4389 
4390     return status;
4391 }
4392 
4393 typedef struct _legacy_image_surface_span_renderer {
4394     cairo_span_renderer_t base;
4395 
4396     cairo_operator_t op;
4397     const cairo_pattern_t *pattern;
4398     cairo_antialias_t antialias;
4399     cairo_region_t *clip_region;
4400 
4401     pixman_image_t *mask;
4402     uint8_t *mask_data;
4403     uint32_t mask_stride;
4404 
4405     cairo_image_surface_t *dst;
4406     cairo_composite_rectangles_t composite_rectangles;
4407 } legacy_image_surface_span_renderer_t;
4408 
4409 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)4410 _cairo_image_surface_span_render_row (
4411     int                                  y,
4412     const cairo_half_open_span_t        *spans,
4413     unsigned                             num_spans,
4414     uint8_t				*data,
4415     uint32_t				 stride)
4416 {
4417     uint8_t *row;
4418     unsigned i;
4419 
4420     if (num_spans == 0)
4421 	return;
4422 
4423     row = data + y * stride;
4424     for (i = 0; i < num_spans - 1; i++) {
4425 	if (! spans[i].coverage)
4426 	    continue;
4427 
4428 	/* We implement setting the most common single pixel wide
4429 	 * span case to avoid the overhead of a memset call.
4430 	 * Open coding setting longer spans didn't show a
4431 	 * noticeable improvement over memset.
4432 	 */
4433 	if (spans[i+1].x == spans[i].x + 1) {
4434 	    row[spans[i].x] = spans[i].coverage;
4435 	} else {
4436 	    memset (row + spans[i].x,
4437 		    spans[i].coverage,
4438 		    spans[i+1].x - spans[i].x);
4439 	}
4440     }
4441 }
4442 
4443 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)4444 _cairo_image_surface_span_renderer_render_rows (
4445     void				*abstract_renderer,
4446     int					 y,
4447     int					 height,
4448     const cairo_half_open_span_t	*spans,
4449     unsigned				 num_spans)
4450 {
4451     legacy_image_surface_span_renderer_t *renderer = abstract_renderer;
4452     while (height--)
4453 	_cairo_image_surface_span_render_row (y++, spans, num_spans, renderer->mask_data, renderer->mask_stride);
4454     return CAIRO_STATUS_SUCCESS;
4455 }
4456 
4457 static void
_cairo_image_surface_span_renderer_destroy(void * abstract_renderer)4458 _cairo_image_surface_span_renderer_destroy (void *abstract_renderer)
4459 {
4460     legacy_image_surface_span_renderer_t *renderer = abstract_renderer;
4461     if (renderer == NULL)
4462 	return;
4463 
4464     pixman_image_unref (renderer->mask);
4465 
4466     free (renderer);
4467 }
4468 
4469 static cairo_status_t
_cairo_image_surface_span_renderer_finish(void * abstract_renderer)4470 _cairo_image_surface_span_renderer_finish (void *abstract_renderer)
4471 {
4472     legacy_image_surface_span_renderer_t *renderer = abstract_renderer;
4473     cairo_composite_rectangles_t *rects = &renderer->composite_rectangles;
4474     cairo_image_surface_t *dst = renderer->dst;
4475     pixman_image_t *src;
4476     int src_x, src_y;
4477     cairo_status_t status;
4478 
4479     if (renderer->clip_region != NULL) {
4480 	status = _cairo_image_surface_set_clip_region (dst, renderer->clip_region);
4481 	if (unlikely (status))
4482 	    return status;
4483     }
4484 
4485     src = _pixman_image_for_pattern (renderer->pattern, FALSE, &rects->bounded, &src_x, &src_y);
4486     if (src == NULL)
4487 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4488 
4489     status = CAIRO_STATUS_SUCCESS;
4490     pixman_image_composite32 (_pixman_operator (renderer->op),
4491                               src,
4492                               renderer->mask,
4493                               dst->pixman_image,
4494                               rects->bounded.x + src_x,
4495                               rects->bounded.y + src_y,
4496                               0, 0,
4497                               rects->bounded.x, rects->bounded.y,
4498                               rects->bounded.width, rects->bounded.height);
4499 
4500     if (! rects->is_bounded)
4501 	status = _cairo_image_surface_fixup_unbounded (dst, rects, NULL);
4502 
4503     if (renderer->clip_region != NULL)
4504 	 _cairo_image_surface_unset_clip_region (dst);
4505 
4506     return status;
4507 }
4508 
4509 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)4510 _cairo_image_surface_check_span_renderer (cairo_operator_t	  op,
4511 					  const cairo_pattern_t  *pattern,
4512 					  void			 *abstract_dst,
4513 					  cairo_antialias_t	  antialias)
4514 {
4515     return TRUE;
4516     (void) op;
4517     (void) pattern;
4518     (void) abstract_dst;
4519     (void) antialias;
4520 }
4521 
4522 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)4523 _cairo_image_surface_create_span_renderer (cairo_operator_t	 op,
4524 					   const cairo_pattern_t  *pattern,
4525 					   void			*abstract_dst,
4526 					   cairo_antialias_t	 antialias,
4527 					   const cairo_composite_rectangles_t *rects,
4528 					   cairo_region_t *clip_region)
4529 {
4530     cairo_image_surface_t *dst = abstract_dst;
4531     legacy_image_surface_span_renderer_t *renderer;
4532 
4533     renderer = calloc(1, sizeof(*renderer));
4534     if (unlikely (renderer == NULL))
4535 	return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
4536 
4537     renderer->base.destroy = _cairo_image_surface_span_renderer_destroy;
4538     renderer->base.finish = _cairo_image_surface_span_renderer_finish;
4539     renderer->base.render_rows = _cairo_image_surface_span_renderer_render_rows;
4540     renderer->op = op;
4541     renderer->pattern = pattern;
4542     renderer->antialias = antialias;
4543     renderer->dst = dst;
4544     renderer->clip_region = clip_region;
4545 
4546     renderer->composite_rectangles = *rects;
4547 
4548     /* TODO: support rendering to A1 surfaces (or: go add span
4549      * compositing to pixman.) */
4550     renderer->mask = pixman_image_create_bits (PIXMAN_a8,
4551 					       rects->bounded.width,
4552 					       rects->bounded.height,
4553 					       NULL, 0);
4554     if (renderer->mask == NULL) {
4555 	free (renderer);
4556 	return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
4557     }
4558 
4559     renderer->mask_stride = pixman_image_get_stride (renderer->mask);
4560     renderer->mask_data = (uint8_t *) pixman_image_get_data (renderer->mask) - rects->bounded.x - rects->bounded.y * renderer->mask_stride;
4561 
4562     return &renderer->base;
4563 }
4564 
4565 /**
4566  * _cairo_surface_is_image:
4567  * @surface: a #cairo_surface_t
4568  *
4569  * Checks if a surface is an #cairo_image_surface_t
4570  *
4571  * Return value: %TRUE if the surface is an image surface
4572  **/
4573 cairo_bool_t
_cairo_surface_is_image(const cairo_surface_t * surface)4574 _cairo_surface_is_image (const cairo_surface_t *surface)
4575 {
4576     return surface->backend == &_cairo_image_surface_backend;
4577 }
4578 
4579 const cairo_surface_backend_t _cairo_image_surface_backend = {
4580     CAIRO_SURFACE_TYPE_IMAGE,
4581     _cairo_image_surface_create_similar,
4582     _cairo_image_surface_finish,
4583     _cairo_image_surface_acquire_source_image,
4584     _cairo_image_surface_release_source_image,
4585     _cairo_image_surface_acquire_dest_image,
4586     _cairo_image_surface_release_dest_image,
4587     _cairo_image_surface_clone_similar,
4588     _cairo_image_surface_composite,
4589     _cairo_image_surface_fill_rectangles,
4590     _cairo_image_surface_composite_trapezoids,
4591     _cairo_image_surface_create_span_renderer,
4592     _cairo_image_surface_check_span_renderer,
4593 
4594     NULL, /* copy_page */
4595     NULL, /* show_page */
4596     _cairo_image_surface_get_extents,
4597     NULL, /* old_show_glyphs */
4598     _cairo_image_surface_get_font_options,
4599     NULL, /* flush */
4600     NULL, /* mark dirty */
4601     NULL, /* font_fini */
4602     NULL, /* glyph_fini */
4603 
4604     _cairo_image_surface_paint,
4605     _cairo_image_surface_mask,
4606     _cairo_image_surface_stroke,
4607     _cairo_image_surface_fill,
4608     _cairo_image_surface_glyphs,
4609     NULL, /* show_text_glyphs */
4610     NULL, /* snapshot */
4611     NULL, /* is_similar */
4612 };
4613 
4614 /* A convenience function for when one needs to coerce an image
4615  * surface to an alternate format. */
4616 cairo_image_surface_t *
_cairo_image_surface_coerce(cairo_image_surface_t * surface)4617 _cairo_image_surface_coerce (cairo_image_surface_t *surface)
4618 {
4619     return _cairo_image_surface_coerce_to_format (surface,
4620 		                                  _cairo_format_from_content (surface->base.content));
4621 
4622 }
4623 
4624 /* A convenience function for when one needs to coerce an image
4625  * surface to an alternate format. */
4626 cairo_image_surface_t *
_cairo_image_surface_coerce_to_format(cairo_image_surface_t * surface,cairo_format_t format)4627 _cairo_image_surface_coerce_to_format (cairo_image_surface_t *surface,
4628 			               cairo_format_t	      format)
4629 {
4630     cairo_image_surface_t *clone;
4631     cairo_status_t status;
4632 
4633     status = surface->base.status;
4634     if (unlikely (status))
4635 	return (cairo_image_surface_t *)_cairo_surface_create_in_error (status);
4636 
4637     if (surface->format == format)
4638 	return (cairo_image_surface_t *)cairo_surface_reference(&surface->base);
4639 
4640     clone = (cairo_image_surface_t *)
4641 	cairo_image_surface_create (format, surface->width, surface->height);
4642     if (unlikely (clone->base.status))
4643 	return clone;
4644 
4645     pixman_image_composite32 (PIXMAN_OP_SRC,
4646                               surface->pixman_image, NULL, clone->pixman_image,
4647                               0, 0,
4648                               0, 0,
4649                               0, 0,
4650                               surface->width, surface->height);
4651     clone->base.is_clear = FALSE;
4652 
4653     clone->base.device_transform =
4654 	surface->base.device_transform;
4655     clone->base.device_transform_inverse =
4656 	surface->base.device_transform_inverse;
4657 
4658     return clone;
4659 }
4660 
4661 cairo_image_transparency_t
_cairo_image_analyze_transparency(cairo_image_surface_t * image)4662 _cairo_image_analyze_transparency (cairo_image_surface_t      *image)
4663 {
4664     int x, y;
4665 
4666     if (image->transparency != CAIRO_IMAGE_UNKNOWN)
4667 	return image->transparency;
4668 
4669     if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0)
4670 	return image->transparency = CAIRO_IMAGE_IS_OPAQUE;
4671 
4672     if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) {
4673 	if (image->format == CAIRO_FORMAT_A1)
4674 	    return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
4675 	else
4676 	    return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
4677     }
4678 
4679     if (image->format == CAIRO_FORMAT_RGB16_565) {
4680 	image->transparency = CAIRO_IMAGE_IS_OPAQUE;
4681 	return CAIRO_IMAGE_IS_OPAQUE;
4682     }
4683 
4684     if (image->format != CAIRO_FORMAT_ARGB32)
4685 	return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
4686 
4687     image->transparency = CAIRO_IMAGE_IS_OPAQUE;
4688     for (y = 0; y < image->height; y++) {
4689 	uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
4690 
4691 	for (x = 0; x < image->width; x++, pixel++) {
4692 	    int a = (*pixel & 0xff000000) >> 24;
4693 	    if (a > 0 && a < 255) {
4694 		return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
4695 	    } else if (a == 0) {
4696 		image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
4697 	    }
4698 	}
4699     }
4700 
4701     return image->transparency;
4702 }
4703