Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1892 Rev 3959
Line 1... Line 1...
1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
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
2
/* cairo - a vector graphics library with display and print output
3
 *
3
 *
4
 * Copyright © 2003 University of Southern California
4
 * Copyright © 2003 University of Southern California
5
 * Copyright © 2009,2010 Intel Corporation
5
 * Copyright © 2009,2010,2011 Intel Corporation
6
 *
6
 *
7
 * This library is free software; you can redistribute it and/or
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
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
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
10
 * (the "LGPL") or, at your option, under the terms of the Mozilla
Line 40... Line 40...
40
#include "cairoint.h"
40
#include "cairoint.h"
Line 41... Line 41...
41
 
41
 
42
#include "cairo-boxes-private.h"
42
#include "cairo-boxes-private.h"
43
#include "cairo-clip-private.h"
43
#include "cairo-clip-private.h"
-
 
44
#include "cairo-composite-rectangles-private.h"
-
 
45
#include "cairo-compositor-private.h"
44
#include "cairo-composite-rectangles-private.h"
46
#include "cairo-default-context-private.h"
-
 
47
#include "cairo-error-private.h"
-
 
48
#include "cairo-image-surface-inline.h"
-
 
49
#include "cairo-paginated-private.h"
-
 
50
#include "cairo-pattern-private.h"
-
 
51
#include "cairo-pixman-private.h"
45
#include "cairo-error-private.h"
52
#include "cairo-recording-surface-private.h"
46
#include "cairo-region-private.h"
53
#include "cairo-region-private.h"
47
#include "cairo-scaled-font-private.h"
54
#include "cairo-scaled-font-private.h"
48
#include "cairo-surface-snapshot-private.h"
55
#include "cairo-surface-snapshot-private.h"
Line 49... Line 56...
49
#include "cairo-surface-subsurface-private.h"
56
#include "cairo-surface-subsurface-private.h"
50
 
57
 
51
/* Limit on the width / height of an image surface in pixels.  This is
58
/* 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
59
 * mainly determined by coordinates of things sent to pixman at the
53
 * moment being in 16.16 format. */
-
 
Line 54... Line 60...
54
#define MAX_IMAGE_SIZE 32767
60
 * moment being in 16.16 format. */
55
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
61
#define MAX_IMAGE_SIZE 32767
56
 
62
 
57
/**
63
/**
58
 * SECTION:cairo-image
64
 * SECTION:cairo-image
59
 * @Title: Image Surfaces
65
 * @Title: Image Surfaces
60
 * @Short_Description: Rendering to memory buffers
66
 * @Short_Description: Rendering to memory buffers
61
 * @See_Also: #cairo_surface_t
67
 * @See_Also: #cairo_surface_t
62
 *
68
 *
63
 * Image surfaces provide the ability to render to memory buffers
69
 * Image surfaces provide the ability to render to memory buffers
Line 64... Line 70...
64
 * either allocated by cairo or by the calling code.  The supported
70
 * either allocated by cairo or by the calling code.  The supported
65
 * image formats are those defined in #cairo_format_t.
71
 * image formats are those defined in #cairo_format_t.
66
 */
72
 **/
67
 
73
 
68
/**
74
/**
69
 * CAIRO_HAS_IMAGE_SURFACE:
75
 * CAIRO_HAS_IMAGE_SURFACE:
70
 *
76
 *
71
 * Defined if the image surface backend is available.
77
 * Defined if the image surface backend is available.
72
 * The image surface backend is always built in.
78
 * 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,
-
 
Line 86... Line 79...
86
			   cairo_clip_t		*clip);
79
 * This macro was added for completeness in cairo 1.8.
87
 
80
 *
88
static pixman_image_t *
81
 * Since: 1.8
89
_pixman_image_for_solid (const cairo_solid_pattern_t *pattern);
82
 **/
Line 99... Line 92...
99
_cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
92
_cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
100
{
93
{
101
    switch (pixman_format) {
94
    switch (pixman_format) {
102
    case PIXMAN_a8r8g8b8:
95
    case PIXMAN_a8r8g8b8:
103
	return CAIRO_FORMAT_ARGB32;
96
	return CAIRO_FORMAT_ARGB32;
-
 
97
    case PIXMAN_x2r10g10b10:
-
 
98
	return CAIRO_FORMAT_RGB30;
104
    case PIXMAN_x8r8g8b8:
99
    case PIXMAN_x8r8g8b8:
105
	return CAIRO_FORMAT_RGB24;
100
	return CAIRO_FORMAT_RGB24;
106
    case PIXMAN_a8:
101
    case PIXMAN_a8:
107
	return CAIRO_FORMAT_A8;
102
	return CAIRO_FORMAT_A8;
108
    case PIXMAN_a1:
103
    case PIXMAN_a1:
109
	return CAIRO_FORMAT_A1;
104
	return CAIRO_FORMAT_A1;
110
    case PIXMAN_r5g6b5:
105
    case PIXMAN_r5g6b5:
111
	return CAIRO_FORMAT_RGB16_565;
106
	return CAIRO_FORMAT_RGB16_565;
-
 
107
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
-
 
108
    case PIXMAN_r8g8b8a8: case PIXMAN_r8g8b8x8:
-
 
109
#endif
112
    case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
110
    case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: case PIXMAN_r8g8b8:
113
    case PIXMAN_b8g8r8:   case PIXMAN_b5g6r5:
111
    case PIXMAN_b8g8r8:   case PIXMAN_b5g6r5:
114
    case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
112
    case PIXMAN_a1r5g5b5: case PIXMAN_x1r5g5b5: case PIXMAN_a1b5g5r5:
115
    case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
113
    case PIXMAN_x1b5g5r5: case PIXMAN_a4r4g4b4: case PIXMAN_x4r4g4b4:
116
    case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2:
114
    case PIXMAN_a4b4g4r4: case PIXMAN_x4b4g4r4: case PIXMAN_r3g3b2:
Line 120... Line 118...
120
    case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
118
    case PIXMAN_a1r1g1b1: case PIXMAN_a1b1g1r1: case PIXMAN_c4:
121
    case PIXMAN_g4:       case PIXMAN_g1:
119
    case PIXMAN_g4:       case PIXMAN_g1:
122
    case PIXMAN_yuy2:     case PIXMAN_yv12:
120
    case PIXMAN_yuy2:     case PIXMAN_yv12:
123
    case PIXMAN_b8g8r8x8:
121
    case PIXMAN_b8g8r8x8:
124
    case PIXMAN_b8g8r8a8:
122
    case PIXMAN_b8g8r8a8:
125
    case PIXMAN_x2b10g10r10:
-
 
126
    case PIXMAN_a2b10g10r10:
123
    case PIXMAN_a2b10g10r10:
127
    case PIXMAN_x2r10g10b10:
124
    case PIXMAN_x2b10g10r10:
128
    case PIXMAN_a2r10g10b10:
125
    case PIXMAN_a2r10g10b10:
-
 
126
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
-
 
127
    case PIXMAN_x14r6g6b6:
-
 
128
#endif
129
    default:
129
    default:
130
	return CAIRO_FORMAT_INVALID;
130
	return CAIRO_FORMAT_INVALID;
131
    }
131
    }
Line 132... Line 132...
132
 
132
 
Line 145... Line 145...
145
	content |= CAIRO_CONTENT_ALPHA;
145
	content |= CAIRO_CONTENT_ALPHA;
Line 146... Line 146...
146
 
146
 
147
    return content;
147
    return content;
Line -... Line 148...
-
 
148
}
-
 
149
 
-
 
150
void
-
 
151
_cairo_image_surface_init (cairo_image_surface_t *surface,
-
 
152
			   pixman_image_t	*pixman_image,
-
 
153
			   pixman_format_code_t	 pixman_format)
-
 
154
{
-
 
155
    surface->parent = NULL;
-
 
156
    surface->pixman_image = pixman_image;
-
 
157
 
-
 
158
    surface->pixman_format = pixman_format;
-
 
159
    surface->format = _cairo_format_from_pixman_format (pixman_format);
-
 
160
    surface->data = (uint8_t *) pixman_image_get_data (pixman_image);
-
 
161
    surface->owns_data = FALSE;
-
 
162
    surface->transparency = CAIRO_IMAGE_UNKNOWN;
-
 
163
    surface->color = CAIRO_IMAGE_UNKNOWN_COLOR;
-
 
164
 
-
 
165
    surface->width = pixman_image_get_width (pixman_image);
-
 
166
    surface->height = pixman_image_get_height (pixman_image);
-
 
167
    surface->stride = pixman_image_get_stride (pixman_image);
-
 
168
    surface->depth = pixman_image_get_depth (pixman_image);
-
 
169
 
-
 
170
    surface->base.is_clear = surface->width == 0 || surface->height == 0;
-
 
171
 
-
 
172
    surface->compositor = _cairo_image_spans_compositor_get ();
148
}
173
}
149
 
174
 
150
cairo_surface_t *
175
cairo_surface_t *
151
_cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
176
_cairo_image_surface_create_for_pixman_image (pixman_image_t		*pixman_image,
152
					      pixman_format_code_t	 pixman_format)
177
					      pixman_format_code_t	 pixman_format)
153
{
-
 
154
    cairo_image_surface_t *surface;
-
 
Line 155... Line 178...
155
    int width = pixman_image_get_width (pixman_image);
178
{
156
    int height = pixman_image_get_height (pixman_image);
179
    cairo_image_surface_t *surface;
157
 
180
 
Line 158... Line 181...
158
    surface = malloc (sizeof (cairo_image_surface_t));
181
    surface = malloc (sizeof (cairo_image_surface_t));
159
    if (unlikely (surface == NULL))
182
    if (unlikely (surface == NULL))
160
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
183
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
161
 
184
 
Line 162... Line -...
162
    _cairo_surface_init (&surface->base,
-
 
163
			 &_cairo_image_surface_backend,
-
 
164
			 NULL, /* device */
-
 
165
			 _cairo_content_from_pixman_format (pixman_format));
185
    _cairo_surface_init (&surface->base,
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;
-
 
Line 174... Line 186...
174
 
186
			 &_cairo_image_surface_backend,
175
    surface->width = width;
187
			 NULL, /* device */
Line 176... Line 188...
176
    surface->height = height;
188
			 _cairo_content_from_pixman_format (pixman_format));
Line 297... Line 309...
297
	ret = PIXMAN_a8;
309
	ret = PIXMAN_a8;
298
	break;
310
	break;
299
    case CAIRO_FORMAT_RGB24:
311
    case CAIRO_FORMAT_RGB24:
300
	ret = PIXMAN_x8r8g8b8;
312
	ret = PIXMAN_x8r8g8b8;
301
	break;
313
	break;
-
 
314
    case CAIRO_FORMAT_RGB30:
-
 
315
	ret = PIXMAN_x2r10g10b10;
-
 
316
	break;
302
    case CAIRO_FORMAT_RGB16_565:
317
    case CAIRO_FORMAT_RGB16_565:
303
	ret = PIXMAN_r5g6b5;
318
	ret = PIXMAN_r5g6b5;
304
	break;
319
	break;
305
    case CAIRO_FORMAT_ARGB32:
320
    case CAIRO_FORMAT_ARGB32:
306
    case CAIRO_FORMAT_INVALID:
321
    case CAIRO_FORMAT_INVALID:
Line 361... Line 376...
361
 * with it.
376
 * with it.
362
 *
377
 *
363
 * This function always returns a valid pointer, but it will return a
378
 * 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
379
 * 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.
380
 * occurs. You can use cairo_surface_status() to check for this.
-
 
381
 *
-
 
382
 * Since: 1.0
366
 **/
383
 **/
367
cairo_surface_t *
384
cairo_surface_t *
368
cairo_image_surface_create (cairo_format_t	format,
385
cairo_image_surface_create (cairo_format_t	format,
369
			    int			width,
386
			    int			width,
370
			    int			height)
387
			    int			height)
Line 476... Line 493...
476
 * %CAIRO_STATUS_INVALID_STRIDE.  You can use
493
 * %CAIRO_STATUS_INVALID_STRIDE.  You can use
477
 * cairo_surface_status() to check for this.
494
 * cairo_surface_status() to check for this.
478
 *
495
 *
479
 * See cairo_surface_set_user_data() for a means of attaching a
496
 * See cairo_surface_set_user_data() for a means of attaching a
480
 * destroy-notification fallback to the surface if necessary.
497
 * destroy-notification fallback to the surface if necessary.
-
 
498
 *
-
 
499
 * Since: 1.0
481
 **/
500
 **/
482
cairo_surface_t *
501
    cairo_surface_t *
483
cairo_image_surface_create_for_data (unsigned char     *data,
502
cairo_image_surface_create_for_data (unsigned char     *data,
484
				     cairo_format_t	format,
503
				     cairo_format_t	format,
485
				     int		width,
504
				     int		width,
Line 522... Line 541...
522
 * @surface: a #cairo_image_surface_t
541
 * @surface: a #cairo_image_surface_t
523
 *
542
 *
524
 * Get a pointer to the data of the image surface, for direct
543
 * Get a pointer to the data of the image surface, for direct
525
 * inspection or modification.
544
 * inspection or modification.
526
 *
545
 *
-
 
546
 * A call to cairo_surface_flush() is required before accessing the
-
 
547
 * pixel data to ensure that all pending drawing operations are
-
 
548
 * finished. A call to cairo_surface_mark_dirty() is required after
-
 
549
 * the data is modified.
-
 
550
 *
527
 * Return value: a pointer to the image data of this surface or %NULL
551
 * 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()
552
 * if @surface is not an image surface, or if cairo_surface_finish()
529
 * has been called.
553
 * has been called.
530
 *
554
 *
531
 * Since: 1.2
555
 * Since: 1.2
Line 573... Line 597...
573
 * @surface: a #cairo_image_surface_t
597
 * @surface: a #cairo_image_surface_t
574
 *
598
 *
575
 * Get the width of the image surface in pixels.
599
 * Get the width of the image surface in pixels.
576
 *
600
 *
577
 * Return value: the width of the surface in pixels.
601
 * Return value: the width of the surface in pixels.
-
 
602
 *
-
 
603
 * Since: 1.0
578
 **/
604
 **/
579
int
605
int
580
cairo_image_surface_get_width (cairo_surface_t *surface)
606
cairo_image_surface_get_width (cairo_surface_t *surface)
581
{
607
{
582
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
608
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
Line 595... Line 621...
595
 * @surface: a #cairo_image_surface_t
621
 * @surface: a #cairo_image_surface_t
596
 *
622
 *
597
 * Get the height of the image surface in pixels.
623
 * Get the height of the image surface in pixels.
598
 *
624
 *
599
 * Return value: the height of the surface in pixels.
625
 * Return value: the height of the surface in pixels.
-
 
626
 *
-
 
627
 * Since: 1.0
600
 **/
628
 **/
601
int
629
int
602
cairo_image_surface_get_height (cairo_surface_t *surface)
630
cairo_image_surface_get_height (cairo_surface_t *surface)
603
{
631
{
604
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
632
    cairo_image_surface_t *image_surface = (cairo_image_surface_t *) surface;
Line 660... Line 688...
660
_cairo_content_from_format (cairo_format_t format)
688
_cairo_content_from_format (cairo_format_t format)
661
{
689
{
662
    switch (format) {
690
    switch (format) {
663
    case CAIRO_FORMAT_ARGB32:
691
    case CAIRO_FORMAT_ARGB32:
664
	return CAIRO_CONTENT_COLOR_ALPHA;
692
	return CAIRO_CONTENT_COLOR_ALPHA;
-
 
693
    case CAIRO_FORMAT_RGB30:
-
 
694
	return CAIRO_CONTENT_COLOR;
665
    case CAIRO_FORMAT_RGB24:
695
    case CAIRO_FORMAT_RGB24:
666
	return CAIRO_CONTENT_COLOR;
696
	return CAIRO_CONTENT_COLOR;
667
    case CAIRO_FORMAT_RGB16_565:
697
    case CAIRO_FORMAT_RGB16_565:
668
	return CAIRO_CONTENT_COLOR;
698
	return CAIRO_CONTENT_COLOR;
669
    case CAIRO_FORMAT_A8:
699
    case CAIRO_FORMAT_A8:
Line 680... Line 710...
680
int
710
    int
681
_cairo_format_bits_per_pixel (cairo_format_t format)
711
_cairo_format_bits_per_pixel (cairo_format_t format)
682
{
712
{
683
    switch (format) {
713
    switch (format) {
684
    case CAIRO_FORMAT_ARGB32:
714
    case CAIRO_FORMAT_ARGB32:
685
	return 32;
715
    case CAIRO_FORMAT_RGB30:
686
    case CAIRO_FORMAT_RGB24:
716
    case CAIRO_FORMAT_RGB24:
687
	return 32;
717
	return 32;
688
    case CAIRO_FORMAT_RGB16_565:
718
    case CAIRO_FORMAT_RGB16_565:
689
	return 16;
719
	return 16;
690
    case CAIRO_FORMAT_A8:
720
    case CAIRO_FORMAT_A8:
Line 696... Line 726...
696
	ASSERT_NOT_REACHED;
726
	ASSERT_NOT_REACHED;
697
	return 0;
727
	return 0;
698
    }
728
    }
699
}
729
}
Line 700... Line 730...
700
 
730
 
701
static cairo_surface_t *
731
cairo_surface_t *
702
_cairo_image_surface_create_similar (void	       *abstract_other,
732
_cairo_image_surface_create_similar (void	       *abstract_other,
703
				     cairo_content_t	content,
733
				     cairo_content_t	content,
704
				     int		width,
734
				     int		width,
705
				     int		height)
735
				     int		height)
706
{
736
{
Line -... Line 737...
-
 
737
    cairo_image_surface_t *other = abstract_other;
-
 
738
 
707
    cairo_image_surface_t *other = abstract_other;
739
    TRACE ((stderr, "%s (other=%u)\n", __FUNCTION__, other->base.unique_id));
708
 
740
 
Line 709... Line 741...
709
    if (! _cairo_image_surface_is_size_valid (width, height))
741
    if (! _cairo_image_surface_is_size_valid (width, height))
710
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
742
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
Line 718... Line 750...
718
 
750
 
719
    return _cairo_image_surface_create_with_content (content,
751
    return _cairo_image_surface_create_with_content (content,
720
						     width, height);
752
						     width, height);
Line 721... Line 753...
721
}
753
}
722
 
754
 
723
static cairo_status_t
-
 
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
-
 
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
-
 
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
-
 
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
-
 
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
-
 
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, ®ion->rgn))
-
 
848
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
849
 
-
 
850
    return CAIRO_STATUS_SUCCESS;
-
 
851
}
-
 
852
 
-
 
853
static void
-
 
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
-
 
860
_pixman_nearest_sample (double d)
-
 
861
{
-
 
862
    return ceil (d - .5);
-
 
863
}
-
 
864
 
-
 
865
static cairo_bool_t
-
 
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 *
-
 
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 *
-
 
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 *
-
 
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 *
-
 
974
_pixman_transparent_image (void)
-
 
975
{
-
 
976
    return _pixman_image_for_solid (&_cairo_pattern_clear);
-
 
977
}
-
 
978
static pixman_image_t *
-
 
979
_pixman_black_image (void)
-
 
980
{
-
 
981
    return _pixman_image_for_solid (&_cairo_pattern_black);
-
 
982
}
-
 
983
static pixman_image_t *
-
 
984
_pixman_white_image (void)
-
 
985
{
-
 
986
    return _pixman_image_for_solid (&_cairo_pattern_white);
-
 
987
}
-
 
988
#endif
-
 
989
 
-
 
990
static uint32_t
-
 
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
-
 
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 *
-
 
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 *
-
 
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
-
 
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
-
 
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
-
 
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 *
-
 
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 *
-
 
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) &&
755
cairo_surface_t *
1467
		_nearest_sample (filter, &tx, &ty))
-
 
1468
	    {
756
_cairo_image_surface_snapshot (void *abstract_surface)
1469
		*ix = tx + sub->extents.x;
757
{
1470
		*iy = ty + sub->extents.y;
-
 
Line 1471... Line 758...
1471
		return pixman_image_ref (source->pixman_image);
758
    cairo_image_surface_t *image = abstract_surface;
1472
	    }
759
    cairo_image_surface_t *clone;
1473
 
-
 
1474
	    /* Avoid sub-byte offsets, force a copy in that case. */
-
 
1475
	    if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
760
 
1476
		pixman_image = pixman_image_create_bits (source->pixman_format,
761
    /* If we own the image, we can simply steal the memory for the snapshot */
1477
							 sub->extents.width,
762
    if (image->owns_data && image->base._finishing) {
1478
							 sub->extents.height,
763
	clone = (cairo_image_surface_t *)
1479
							 (uint32_t *) (source->data + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8 + sub->extents.y * source->stride),
764
	    _cairo_image_surface_create_for_pixman_image (image->pixman_image,
1480
							 source->stride);
-
 
1481
		if (unlikely (pixman_image == NULL))
-
 
1482
		    return NULL;
-
 
Line 1483... Line 765...
1483
	    }
765
							  image->pixman_format);
1484
	}
-
 
1485
    }
-
 
1486
 
-
 
1487
    if (pixman_image == NULL) {
766
	if (unlikely (clone->base.status))
Line 1488... Line 767...
1488
	struct acquire_source_cleanup *cleanup;
767
	    return &clone->base;
1489
	cairo_image_surface_t *image;
768
 
1490
	void *extra;
-
 
Line 1491... Line -...
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 ||
769
	image->pixman_image = NULL;
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
		}
770
	image->owns_data = FALSE;
1508
	    }
-
 
1509
	    else
771
 
Line -... Line 772...
-
 
772
	clone->transparency = image->transparency;
1510
	    {
773
	clone->color = image->color;
-
 
774
 
1511
		pixman_image = _pixel_to_solid (image, sample.x, sample.y);
775
	clone->owns_data = TRUE;
1512
		_cairo_surface_release_source_image (pattern->surface, image, extra);
776
	return &clone->base;
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 *
-
 
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
-
 
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
-
 
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);
777
    }
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
-
 
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
-
 
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 *
-
 
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
    }
778
 
1956
 
-
 
1957
    status = draw_func (draw_closure,
779
    clone = (cairo_image_surface_t *)
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
-
 
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
-
 
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,
-
 
Line 2066... Line -...
2066
			     cairo_image_surface_t               *dst,
-
 
2067
			     const cairo_rectangle_int_t   *extents)
-
 
2068
{
-
 
2069
    pixman_image_t *tmp;
780
	_cairo_image_surface_create_with_pixman_format (NULL,
2070
    cairo_surface_t *clip_surface;
781
							image->pixman_format,
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);
782
							image->width,
2079
 
-
 
2080
    if (src == NULL) {
-
 
2081
	status = (*draw_func) (draw_closure,
783
							image->height,
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))
784
							0);
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);
785
    if (unlikely (clone->base.status))
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,
786
	return &clone->base;
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,
787
 
2142
                                  extents->width, extents->height);
-
 
2143
#endif
-
 
2144
    } else {
-
 
2145
	pixman_image_composite32 (PIXMAN_OP_SRC,
788
    if (clone->stride == image->stride) {
2146
                                  tmp,
789
	memcpy (clone->data, image->data, clone->stride * clone->height);
2147
                                  ((cairo_image_surface_t *) clip_surface)->pixman_image,
-
 
2148
                                  dst->pixman_image,
-
 
2149
                                  0, 0,
790
    } else {
2150
                                  extents->x - clip_x,
-
 
2151
                                  extents->y - clip_y,
791
	pixman_image_composite32 (PIXMAN_OP_SRC,
2152
                                  extents->x, extents->y,
792
				  image->pixman_image, NULL, clone->pixman_image,
Line 2153... Line -...
2153
                                  extents->width, extents->height);
-
 
2154
    }
-
 
2155
 
-
 
2156
 CLEANUP_SURFACE:
793
				  0, 0,
2157
    pixman_image_unref (tmp);
-
 
2158
 
-
 
2159
    return status;
-
 
2160
}
-
 
2161
 
794
				  0, 0,
2162
/* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
795
				  0, 0,
2163
 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
796
				  image->width, image->height);
2164
 */
-
 
2165
static cairo_status_t
-
 
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
-
 
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
	}
797
    }
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
-
 
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
-
 
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);
798
    clone->base.is_clear = FALSE;
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
-
 
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
-
 
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
-
 
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)   |
799
    return &clone->base;
2497
        (color->blue_short >> 8);
-
 
2498
}
-
 
2499
 
-
 
2500
static inline cairo_bool_t
-
 
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
    }
-
 
Line 2519... Line -...
2519
 
-
 
2520
    c = color_to_uint32 (color);
800
}
2521
 
801
 
2522
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) {
802
cairo_image_surface_t *
2523
	c = ((c & 0xff000000) >>  0) |
-
 
2524
	    ((c & 0x00ff0000) >> 16) |
-
 
Line 2525... Line -...
2525
	    ((c & 0x0000ff00) >>  0) |
-
 
2526
	    ((c & 0x000000ff) << 16);
803
_cairo_image_surface_map_to_image (void *abstract_other,
2527
    }
804
				   const cairo_rectangle_int_t *extents)
2528
 
805
{
2529
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) {
806
    cairo_image_surface_t *other = abstract_other;
2530
	c = ((c & 0xff000000) >> 24) |
807
    cairo_surface_t *surface;
2531
	    ((c & 0x00ff0000) >>  8) |
808
    uint8_t *data;
Line 2532... Line 809...
2532
	    ((c & 0x0000ff00) <<  8) |
809
 
2533
	    ((c & 0x000000ff) << 24);
810
    data = other->data;
2534
    }
811
    data += extents->y * other->stride;
Line 2535... Line 812...
2535
 
812
    data += extents->x * PIXMAN_FORMAT_BPP (other->pixman_format)/ 8;
2536
    if (format == PIXMAN_a8) {
813
 
2537
	c = c >> 24;
814
    surface =
2538
    } else if (format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5) {
-
 
2539
	c = ((((c) >> 3) & 0x001f) |
-
 
2540
	     (((c) >> 5) & 0x07e0) |
815
	_cairo_image_surface_create_with_pixman_format (data,
2541
	     (((c) >> 8) & 0xf800));
816
							other->pixman_format,
2542
    }
-
 
2543
 
-
 
2544
    *pixel = c;
-
 
2545
    return TRUE;
-
 
2546
}
817
							extents->width,
2547
 
-
 
Line 2548... Line -...
2548
static inline cairo_bool_t
-
 
2549
pattern_to_pixel (const cairo_solid_pattern_t *solid,
-
 
2550
		  cairo_operator_t op,
818
							extents->height,
2551
		  pixman_format_code_t format,
819
							other->stride);
Line 2552... Line -...
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
    }
820
 
2566
 
821
    cairo_surface_set_device_offset (surface, -extents->x, -extents->y);
2567
    if (op != CAIRO_OPERATOR_SOURCE)
-
 
2568
	return FALSE;
-
 
2569
 
-
 
2570
    return color_to_pixel (&solid->color, format, pixel);
822
    return (cairo_image_surface_t *) surface;
2571
}
823
}
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
-
 
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
-
 
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);
-
 
Line 2728... Line -...
2728
		    b.p1.y = _cairo_fixed_from_int (y1);
-
 
2729
		    b.p2.x = box[i].p2.x;
824
 
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;
825
cairo_int_status_t
2735
		}
826
_cairo_image_surface_unmap_image (void *abstract_surface,
2736
 
-
 
2737
		/* bottom (including bottom-left and bottom-right corners) */
-
 
2738
		if (! _cairo_fixed_is_integer (box[i].p2.y)) {
827
				  cairo_image_surface_t *image)
Line 2739... Line -...
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
 
828
{
2744
		    status = _cairo_rectangular_scan_converter_add_box (&converter, &b, 1);
-
 
2745
		    if (unlikely (status))
829
    cairo_surface_finish (&image->base);
2746
			goto CLEANUP_CONVERTER;
-
 
2747
		}
830
    cairo_surface_destroy (&image->base);
2748
	    } else {
831
 
Line 2749... Line -...
2749
		status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
-
 
2750
		if (unlikely (status))
-
 
2751
		    goto CLEANUP_CONVERTER;
-
 
2752
	    }
-
 
2753
	}
-
 
2754
    }
832
    return CAIRO_INT_STATUS_SUCCESS;
2755
 
-
 
2756
    status = converter.base.generate (&converter.base, &renderer.base);
-
 
2757
 
833
}
2758
  CLEANUP_CONVERTER:
834
 
2759
    converter.base.destroy (&converter.base);
-
 
2760
    pixman_image_unref (renderer.src);
835
cairo_status_t
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
-
 
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
     */
836
_cairo_image_surface_finish (void *abstract_surface)
2792
    row = renderer->mask_data + y * renderer->mask_stride;
-
 
2793
    do {
-
 
Line 2794... Line 837...
2794
	for (i = 0; i < num_spans - 1; i++) {
837
{
2795
	    if (! spans[i].coverage)
838
    cairo_image_surface_t *surface = abstract_surface;
Line 2796... Line -...
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
-
 
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;
839
 
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;
840
    if (surface->pixman_image) {
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
-
 
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))
841
	pixman_image_unref (surface->pixman_image);
2911
	{
842
	surface->pixman_image = NULL;
2912
	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
2913
	}
-
 
2914
 
843
    }
Line 2915... Line -...
2915
	if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1)
-
 
2916
	    clip_region = NULL;
-
 
2917
    }
-
 
2918
 
844
 
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);
845
    if (surface->owns_data) {
2928
	    }
-
 
2929
	    else
-
 
2930
	    {
-
 
2931
		return _composite_unaligned_boxes (dst, op, pattern, boxes, extents);
-
 
2932
	    }
-
 
2933
	}
846
	free (surface->data);
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
    {
847
	surface->data = NULL;
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
    {
848
    }
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) {
-
 
Line 2986... Line 849...
2986
	    src = _pixman_image_for_pattern (pattern, FALSE, &extents->bounded, &src_x, &src_y);
849
 
2987
	    if (unlikely (src == NULL))
-
 
2988
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
850
    if (surface->parent) {
2989
	} else {
-
 
2990
	    src = mask;
851
	cairo_surface_t *parent = surface->parent;
2991
	    src_x = mask_x;
852
	surface->parent = NULL;
2992
	    src_y = mask_y;
-
 
2993
	    mask = NULL;
853
	cairo_surface_destroy (parent);
Line 2994... Line -...
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
 
854
    }
3005
		if (x2 == x1 || y2 == y1)
855
 
Line 3006... Line 856...
3006
		    continue;
856
    return CAIRO_STATUS_SUCCESS;
3007
 
857
}
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,
858
 
3012
                                          x1, y1,
859
void
3013
                                          x2 - x1, y2 - y1);
-
 
3014
	    }
860
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface)
3015
	}
861
{
3016
 
-
 
3017
	if (pattern != NULL)
862
    surface->owns_data = TRUE;
Line 3018... Line -...
3018
	    pixman_image_unref (src);
-
 
3019
 
863
}
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
-
 
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;
864
 
Line -... Line 865...
-
 
865
cairo_surface_t *
-
 
866
_cairo_image_surface_source (void			*abstract_surface,
3041
    composite_traps_info_t info;
867
			     cairo_rectangle_int_t	*extents)
3042
 
868
{
3043
    if (boxes->num_boxes == 0 && extents->is_bounded)
869
    cairo_image_surface_t *surface = abstract_surface;
3044
	return CAIRO_STATUS_SUCCESS;
-
 
3045
 
870
 
Line -... Line 871...
-
 
871
    if (extents) {
3046
    /* Use a fast path if the boxes are pixel aligned */
872
	extents->x = extents->y = 0;
3047
    status = _composite_boxes (dst, op, src, boxes, antialias, clip, extents);
873
	extents->width = surface->width;
3048
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
874
	extents->height = surface->height;
3049
	return status;
875
    }
3050
 
876
 
Line 3051... Line -...
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;
877
    return &surface->base;
3058
    info.antialias = antialias;
-
 
3059
    status = _clip_and_composite (dst, op, src,
-
 
3060
				  _composite_traps, &info,
878
}
3061
				  extents, clip);
879
 
3062
 
-
 
3063
    _cairo_traps_fini (&traps);
-
 
3064
    return status;
-
 
3065
}
-
 
3066
 
-
 
3067
static cairo_bool_t
880
cairo_status_t
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
-
 
Line 3074... Line 881...
3074
_traps_are_pixel_aligned (cairo_traps_t *traps,
881
_cairo_image_surface_acquire_source_image (void                    *abstract_surface,
3075
			  cairo_antialias_t antialias)
882
					   cairo_image_surface_t  **image_out,
Line 3076... Line -...
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
-
 
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
-
 
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
     */
883
					   void                   **image_extra)
3212
    info.traps = traps->traps;
884
{
3213
    info.num_traps = traps->num_traps;
885
    *image_out = abstract_surface;
3214
    info.antialias = antialias;
886
    *image_extra = NULL;
3215
    return _clip_and_composite (dst, op, src,
887
 
3216
				_composite_traps, &info,
888
    return CAIRO_STATUS_SUCCESS;
3217
				extents, clip);
889
}
3218
}
-
 
3219
 
-
 
3220
static cairo_clip_path_t *
-
 
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;
-
 
Line 3225... Line -...
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
-
 
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
890
 
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
 
891
void
3309
    if (have_clip)
-
 
Line 3310... Line -...
3310
	_cairo_clip_fini (&local_clip);
-
 
3311
 
892
_cairo_image_surface_release_source_image (void                   *abstract_surface,
3312
    return status;
-
 
3313
}
-
 
3314
 
-
 
3315
static cairo_status_t
893
					   cairo_image_surface_t  *image,
3316
_composite_mask (void				*closure,
894
					   void                   *image_extra)
Line 3317... Line -...
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
 
895
{
3331
    if (src_pattern != NULL) {
896
}
3332
	src = _pixman_image_for_pattern (src_pattern, FALSE, extents, &src_x, &src_y);
897
 
3333
	if (unlikely (src == NULL))
898
/* high level image interface */
3334
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
899
cairo_bool_t
3335
 
900
_cairo_image_surface_get_extents (void			  *abstract_surface,
3336
	mask = _pixman_image_for_pattern (mask_pattern, TRUE, extents, &mask_x, &mask_y);
901
				  cairo_rectangle_int_t   *rectangle)
3337
	if (unlikely (mask == NULL)) {
902
{
3338
	    pixman_image_unref (src);
-
 
3339
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
3340
	}
-
 
3341
 
-
 
Line 3342... Line -...
3342
	if (mask_pattern->has_component_alpha)
-
 
3343
	    pixman_image_set_component_alpha (mask, TRUE);
903
    cairo_image_surface_t *surface = abstract_surface;
3344
    } else {
904
 
3345
	src = _pixman_image_for_pattern (mask_pattern, FALSE, extents, &src_x, &src_y);
-
 
3346
	if (unlikely (src == NULL))
-
 
Line 3347... Line 905...
3347
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
905
    rectangle->x = 0;
3348
    }
-
 
3349
 
-
 
3350
    pixman_image_composite32 (_pixman_operator (op), src, mask, dst,
-
 
3351
                              extents->x + src_x,  extents->y + src_y,
906
    rectangle->y = 0;
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)
907
    rectangle->width  = surface->width;
Line 3357... Line -...
3357
	pixman_image_unref (mask);
-
 
3358
    pixman_image_unref (src);
-
 
3359
 
-
 
3360
    return CAIRO_STATUS_SUCCESS;
-
 
3361
}
-
 
3362
 
-
 
3363
static cairo_int_status_t
-
 
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
-
 
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
-
 
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
 
908
    rectangle->height = surface->height;
3557
    _cairo_box_round_to_rectangle (&polygon->extents, &extents->mask);
909
 
3558
    if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask))
910
    return TRUE;
3559
	return CAIRO_STATUS_SUCCESS;
911
}
3560
 
912
 
3561
    if (antialias != CAIRO_ANTIALIAS_NONE) {
913
cairo_int_status_t
3562
	composite_spans_info_t info;
914
_cairo_image_surface_paint (void			*abstract_surface,
3563
 
915
			    cairo_operator_t		 op,
3564
	info.polygon = polygon;
916
			    const cairo_pattern_t	*source,
3565
	info.fill_rule = fill_rule;
917
			    const cairo_clip_t		*clip)
3566
	info.antialias = antialias;
918
{
3567
 
919
    cairo_image_surface_t *surface = abstract_surface;
3568
	status = _clip_and_composite (dst, op, src,
920
 
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
-
 
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,
-
 
Line 3597... Line -...
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,
921
    TRACE ((stderr, "%s (surface=%d)\n",
3602
			     cairo_clip_t		*clip)
-
 
3603
{
-
 
3604
    cairo_image_surface_t *surface = abstract_surface;
-
 
3605
    cairo_composite_rectangles_t extents;
922
	    __FUNCTION__, surface->base.unique_id));
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
    }
-
 
Line 3636... Line -...
3636
 
-
 
3637
    status = CAIRO_INT_STATUS_UNSUPPORTED;
-
 
3638
    if (path->is_rectilinear) {
-
 
3639
	cairo_boxes_t boxes;
923
 
3640
 
924
    return _cairo_compositor_paint (surface->compositor,
3641
	_cairo_boxes_init (&boxes);
-
 
3642
	_cairo_boxes_limit (&boxes, clip_boxes, num_boxes);
925
				    &surface->base, op, source, clip);
3643
 
926
}
3644
	status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
-
 
3645
								style,
-
 
3646
								ctm,
927
 
Line 3647... Line 928...
3647
								&boxes);
928
cairo_int_status_t
3648
	if (likely (status == CAIRO_STATUS_SUCCESS)) {
929
_cairo_image_surface_mask (void				*abstract_surface,
3649
	    status = _clip_and_composite_boxes (surface, op, source,
930
			   cairo_operator_t		 op,
3650
						&boxes, antialias,
931
			   const cairo_pattern_t	*source,
3651
						&extents, clip);
932
			   const cairo_pattern_t	*mask,
3652
	}
933
			   const cairo_clip_t		*clip)
3653
 
934
{
3654
	_cairo_boxes_fini (&boxes);
935
    cairo_image_surface_t *surface = abstract_surface;
3655
    }
936
 
3656
 
937
    TRACE ((stderr, "%s (surface=%d)\n",
3657
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
938
	    __FUNCTION__, surface->base.unique_id));
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,
-
 
Line 3664... Line 939...
3664
						      style,
939
 
3665
						      ctm, ctm_inverse,
940
    return _cairo_compositor_mask (surface->compositor,
-
 
941
				   &surface->base, op, source, mask, clip);
3666
						      tolerance,
942
}
3667
						      &polygon);
943
 
-
 
944
cairo_int_status_t
3668
	if (likely (status == CAIRO_STATUS_SUCCESS)) {
945
_cairo_image_surface_stroke (void			*abstract_surface,
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
-
 
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
 
946
			     cairo_operator_t		 op,
Line 3712... Line -...
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
-
 
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
-
 
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
 
947
			     const cairo_pattern_t	*source,
3977
	glyph_surface = scaled_glyph->surface;
948
			     const cairo_path_fixed_t	*path,
3978
	if (glyph_surface->width && glyph_surface->height) {
949
			     const cairo_stroke_style_t	*style,
3979
	    int x1, y1, x2, y2;
950
			     const cairo_matrix_t	*ctm,
3980
 
951
			     const cairo_matrix_t	*ctm_inverse,
3981
	    /* round glyph locations to the nearest pixel */
952
			     double			 tolerance,
3982
	    /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
953
			     cairo_antialias_t		 antialias,
3983
	    x = _cairo_lround (info->glyphs[i].x -
954
			     const cairo_clip_t		*clip)
3984
			       glyph_surface->base.device_transform.x0);
-
 
3985
	    y = _cairo_lround (info->glyphs[i].y -
955
{
3986
			       glyph_surface->base.device_transform.y0);
956
    cairo_image_surface_t *surface = abstract_surface;
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)
-
 
Line 3993... Line -...
3993
		x2 = extents->x + extents->width;
-
 
3994
 
957
 
3995
	    y1 = y;
958
    TRACE ((stderr, "%s (surface=%d)\n",
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,
-
 
Line 4003... Line 959...
4003
                                      src, glyph_surface->pixman_image, dst,
959
	    __FUNCTION__, surface->base.unique_id));
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);
960
 
4011
 
-
 
4012
    pixman_image_unref (src);
-
 
4013
 
-
 
4014
    return status;
-
 
4015
}
961
    return _cairo_compositor_stroke (surface->compositor, &surface->base,
4016
 
-
 
4017
static cairo_int_status_t
-
 
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,
962
				     op, source, path,
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))
963
				     style, ctm, ctm_inverse,
Line 4044... Line 964...
4044
	return status;
964
				     tolerance, antialias, clip);
4045
 
965
}
4046
    if (_cairo_clip_contains_rectangle (clip, &extents.mask))
966
 
4047
	clip = NULL;
967
cairo_int_status_t
4048
 
968
_cairo_image_surface_fill (void				*abstract_surface,
Line 4049... Line 969...
4049
    if (clip != NULL && extents.is_bounded) {
969
			   cairo_operator_t		 op,
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
-
 
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
-
 
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
-
 
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
-
 
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
-
 
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
-
 
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
-
 
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
-
 
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
-
 
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
970
			   const cairo_pattern_t	*source,
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
-
 
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
-
 
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
-
 
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
-
 
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 *
-
 
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
 
971
			   const cairo_path_fixed_t	*path,
Line 4533... Line 972...
4533
    renderer = calloc(1, sizeof(*renderer));
972
			   cairo_fill_rule_t		 fill_rule,
4534
    if (unlikely (renderer == NULL))
973
			   double			 tolerance,
4535
	return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
-
 
4536
 
974
			   cairo_antialias_t		 antialias,
-
 
975
			   const cairo_clip_t		*clip)
-
 
976
{
-
 
977
    cairo_image_surface_t *surface = abstract_surface;
-
 
978
 
-
 
979
    TRACE ((stderr, "%s (surface=%d)\n",
-
 
980
	    __FUNCTION__, surface->base.unique_id));
-
 
981
 
-
 
982
    return _cairo_compositor_fill (surface->compositor, &surface->base,
-
 
983
				   op, source, path,
4537
    renderer->base.destroy = _cairo_image_surface_span_renderer_destroy;
984
				   fill_rule, tolerance, antialias,
4538
    renderer->base.finish = _cairo_image_surface_span_renderer_finish;
985
				   clip);
4539
    renderer->base.render_rows = _cairo_image_surface_span_renderer_render_rows;
-
 
4540
    renderer->op = op;
-
 
4541
    renderer->pattern = pattern;
-
 
4542
    renderer->antialias = antialias;
986
}
4543
    renderer->dst = dst;
-
 
4544
    renderer->clip_region = clip_region;
-
 
4545
 
-
 
4546
    renderer->composite_rectangles = *rects;
-
 
Line 4547... Line 987...
4547
 
987
 
4548
    /* TODO: support rendering to A1 surfaces (or: go add span
988
cairo_int_status_t
-
 
989
_cairo_image_surface_glyphs (void			*abstract_surface,
4549
     * compositing to pixman.) */
990
			     cairo_operator_t		 op,
4550
    renderer->mask = pixman_image_create_bits (PIXMAN_a8,
-
 
4551
					       rects->bounded.width,
991
			     const cairo_pattern_t	*source,
-
 
992
			     cairo_glyph_t		*glyphs,
4552
					       rects->bounded.height,
993
			     int			 num_glyphs,
4553
					       NULL, 0);
-
 
4554
    if (renderer->mask == NULL) {
994
			     cairo_scaled_font_t	*scaled_font,
4555
	free (renderer);
-
 
Line 4556... Line 995...
4556
	return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
995
			     const cairo_clip_t		*clip)
4557
    }
996
{
4558
 
997
    cairo_image_surface_t *surface = abstract_surface;
4559
    renderer->mask_stride = pixman_image_get_stride (renderer->mask);
998
 
-
 
999
    TRACE ((stderr, "%s (surface=%d)\n",
4560
    renderer->mask_data = (uint8_t *) pixman_image_get_data (renderer->mask) - rects->bounded.x - rects->bounded.y * renderer->mask_stride;
1000
	    __FUNCTION__, surface->base.unique_id));
4561
 
-
 
4562
    return &renderer->base;
-
 
4563
}
-
 
4564
 
1001
 
Line 4565... Line 1002...
4565
/**
1002
    return _cairo_compositor_glyphs (surface->compositor, &surface->base,
4566
 * _cairo_surface_is_image:
1003
				     op, source,
4567
 * @surface: a #cairo_surface_t
1004
				     glyphs, num_glyphs, scaled_font,
4568
 *
1005
				     clip);
4569
 * Checks if a surface is an #cairo_image_surface_t
1006
}
4570
 *
1007
 
4571
 * Return value: %TRUE if the surface is an image surface
1008
void
4572
 **/
-
 
4573
cairo_bool_t
1009
_cairo_image_surface_get_font_options (void                  *abstract_surface,
Line 4574... Line 1010...
4574
_cairo_surface_is_image (const cairo_surface_t *surface)
1010
				       cairo_font_options_t  *options)
4575
{
1011
{
4576
    return surface->backend == &_cairo_image_surface_backend;
1012
    _cairo_font_options_init_default (options);
Line 4656... Line 1092...
4656
	surface->base.device_transform_inverse;
1092
	surface->base.device_transform_inverse;
Line 4657... Line 1093...
4657
 
1093
 
4658
    return clone;
1094
    return clone;
Line -... Line 1095...
-
 
1095
}
-
 
1096
 
-
 
1097
cairo_image_surface_t *
-
 
1098
_cairo_image_surface_create_from_image (cairo_image_surface_t *other,
-
 
1099
					pixman_format_code_t format,
-
 
1100
					int x, int y,
-
 
1101
					int width, int height, int stride)
-
 
1102
{
-
 
1103
    cairo_image_surface_t *surface;
-
 
1104
    cairo_status_t status;
-
 
1105
    pixman_image_t *image;
-
 
1106
    void *mem = NULL;
-
 
1107
 
-
 
1108
    status = other->base.status;
-
 
1109
    if (unlikely (status))
-
 
1110
	goto cleanup;
-
 
1111
 
-
 
1112
    if (stride) {
-
 
1113
	mem = _cairo_malloc_ab (height, stride);
-
 
1114
	if (unlikely (mem == NULL)) {
-
 
1115
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1116
	    goto cleanup;
-
 
1117
	}
-
 
1118
    }
-
 
1119
 
-
 
1120
    image = pixman_image_create_bits (format, width, height, mem, stride);
-
 
1121
    if (unlikely (image == NULL)) {
-
 
1122
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1123
	goto cleanup_mem;
-
 
1124
    }
-
 
1125
 
-
 
1126
    surface = (cairo_image_surface_t *)
-
 
1127
	_cairo_image_surface_create_for_pixman_image (image, format);
-
 
1128
    if (unlikely (surface->base.status)) {
-
 
1129
	status = surface->base.status;
-
 
1130
	goto cleanup_image;
-
 
1131
    }
-
 
1132
 
-
 
1133
    pixman_image_composite32 (PIXMAN_OP_SRC,
-
 
1134
                              other->pixman_image, NULL, image,
-
 
1135
                              x, y,
-
 
1136
                              0, 0,
-
 
1137
                              0, 0,
-
 
1138
                              width, height);
-
 
1139
    surface->base.is_clear = FALSE;
-
 
1140
    surface->owns_data = mem != NULL;
-
 
1141
 
-
 
1142
    return surface;
-
 
1143
 
-
 
1144
cleanup_image:
-
 
1145
    pixman_image_unref (image);
-
 
1146
cleanup_mem:
-
 
1147
    free (mem);
-
 
1148
cleanup:
-
 
1149
    return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
4659
}
1150
}
4660
 
1151
 
4661
cairo_image_transparency_t
1152
cairo_image_transparency_t
4662
_cairo_image_analyze_transparency (cairo_image_surface_t      *image)
1153
_cairo_image_analyze_transparency (cairo_image_surface_t *image)
Line 4667... Line 1158...
4667
	return image->transparency;
1158
	return image->transparency;
Line 4668... Line 1159...
4668
 
1159
 
4669
    if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0)
1160
    if ((image->base.content & CAIRO_CONTENT_ALPHA) == 0)
Line -... Line 1161...
-
 
1161
	return image->transparency = CAIRO_IMAGE_IS_OPAQUE;
-
 
1162
 
-
 
1163
    if (image->base.is_clear)
4670
	return image->transparency = CAIRO_IMAGE_IS_OPAQUE;
1164
	return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
4671
 
1165
 
4672
    if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) {
1166
    if ((image->base.content & CAIRO_CONTENT_COLOR) == 0) {
-
 
1167
	if (image->format == CAIRO_FORMAT_A1) {
-
 
1168
	    return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
-
 
1169
	} else if (image->format == CAIRO_FORMAT_A8) {
-
 
1170
	    for (y = 0; y < image->height; y++) {
-
 
1171
		uint8_t *alpha = (uint8_t *) (image->data + y * image->stride);
-
 
1172
 
-
 
1173
		for (x = 0; x < image->width; x++, alpha++) {
-
 
1174
		    if (*alpha > 0 && *alpha < 255)
-
 
1175
			return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
-
 
1176
		}
4673
	if (image->format == CAIRO_FORMAT_A1)
1177
	    }
4674
	    return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
1178
	    return image->transparency = CAIRO_IMAGE_HAS_BILEVEL_ALPHA;
4675
	else
1179
	} else {
-
 
1180
	    return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
Line 4676... Line 1181...
4676
	    return image->transparency = CAIRO_IMAGE_HAS_ALPHA;
1181
	}
4677
    }
1182
    }
4678
 
1183
 
4679
    if (image->format == CAIRO_FORMAT_RGB16_565) {
1184
    if (image->format == CAIRO_FORMAT_RGB16_565) {
Line 4698... Line 1203...
4698
	}
1203
	}
4699
    }
1204
    }
Line 4700... Line 1205...
4700
 
1205
 
4701
    return image->transparency;
1206
    return image->transparency;
-
 
1207
}
-
 
1208
 
-
 
1209
cairo_image_color_t
-
 
1210
_cairo_image_analyze_color (cairo_image_surface_t      *image)
-
 
1211
{
-
 
1212
    int x, y;
-
 
1213
 
-
 
1214
    if (image->color != CAIRO_IMAGE_UNKNOWN_COLOR)
-
 
1215
	return image->color;
-
 
1216
 
-
 
1217
    if (image->format == CAIRO_FORMAT_A1)
-
 
1218
	return image->color = CAIRO_IMAGE_IS_MONOCHROME;
-
 
1219
 
-
 
1220
    if (image->format == CAIRO_FORMAT_A8)
-
 
1221
	return image->color = CAIRO_IMAGE_IS_GRAYSCALE;
-
 
1222
 
-
 
1223
    if (image->format == CAIRO_FORMAT_ARGB32) {
-
 
1224
	image->color = CAIRO_IMAGE_IS_MONOCHROME;
-
 
1225
	for (y = 0; y < image->height; y++) {
-
 
1226
	    uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
-
 
1227
 
-
 
1228
	    for (x = 0; x < image->width; x++, pixel++) {
-
 
1229
		int a = (*pixel & 0xff000000) >> 24;
-
 
1230
		int r = (*pixel & 0x00ff0000) >> 16;
-
 
1231
		int g = (*pixel & 0x0000ff00) >> 8;
-
 
1232
		int b = (*pixel & 0x000000ff);
-
 
1233
		if (a == 0) {
-
 
1234
		    r = g = b = 0;
-
 
1235
		} else {
-
 
1236
		    r = (r * 255 + a / 2) / a;
-
 
1237
		    g = (g * 255 + a / 2) / a;
-
 
1238
		    b = (b * 255 + a / 2) / a;
-
 
1239
		}
-
 
1240
		if (!(r == g && g == b))
-
 
1241
		    return image->color = CAIRO_IMAGE_IS_COLOR;
-
 
1242
		else if (r > 0 && r < 255)
-
 
1243
		    image->color = CAIRO_IMAGE_IS_GRAYSCALE;
-
 
1244
	    }
-
 
1245
	}
-
 
1246
	return image->color;
-
 
1247
    }
-
 
1248
 
-
 
1249
    if (image->format == CAIRO_FORMAT_RGB24) {
-
 
1250
	image->color = CAIRO_IMAGE_IS_MONOCHROME;
-
 
1251
	for (y = 0; y < image->height; y++) {
-
 
1252
	    uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
-
 
1253
 
-
 
1254
	    for (x = 0; x < image->width; x++, pixel++) {
-
 
1255
		int r = (*pixel & 0x00ff0000) >> 16;
-
 
1256
		int g = (*pixel & 0x0000ff00) >>  8;
-
 
1257
		int b = (*pixel & 0x000000ff);
-
 
1258
		if (!(r == g && g == b))
-
 
1259
		    return image->color = CAIRO_IMAGE_IS_COLOR;
-
 
1260
		else if (r > 0 && r < 255)
-
 
1261
		    image->color = CAIRO_IMAGE_IS_GRAYSCALE;
-
 
1262
	    }
-
 
1263
	}
-
 
1264
	return image->color;
-
 
1265
    }
-
 
1266
 
-
 
1267
    return image->color = CAIRO_IMAGE_IS_COLOR;
-
 
1268
}
-
 
1269
 
-
 
1270
cairo_image_surface_t *
-
 
1271
_cairo_image_surface_clone_subimage (cairo_surface_t             *surface,
-
 
1272
				     const cairo_rectangle_int_t *extents)
-
 
1273
{
-
 
1274
    cairo_surface_t *image;
-
 
1275
    cairo_surface_pattern_t pattern;
-
 
1276
    cairo_status_t status;
-
 
1277
 
-
 
1278
    image = cairo_surface_create_similar_image (surface,
-
 
1279
						_cairo_format_from_content (surface->content),
-
 
1280
						extents->width,
-
 
1281
						extents->height);
-
 
1282
    if (image->status)
-
 
1283
	return to_image_surface (image);
-
 
1284
 
-
 
1285
    /* TODO: check me with non-identity device_transform. Should we
-
 
1286
     * clone the scaling, too? */
-
 
1287
    cairo_surface_set_device_offset (image,
-
 
1288
				     -extents->x,
-
 
1289
				     -extents->y);
-
 
1290
 
-
 
1291
    _cairo_pattern_init_for_surface (&pattern, surface);
-
 
1292
    pattern.base.filter = CAIRO_FILTER_NEAREST;
-
 
1293
 
-
 
1294
    status = _cairo_surface_paint (image,
-
 
1295
				   CAIRO_OPERATOR_SOURCE,
-
 
1296
				   &pattern.base,
-
 
1297
				   NULL);
-
 
1298
 
-
 
1299
    _cairo_pattern_fini (&pattern.base);
-
 
1300
 
-
 
1301
    if (unlikely (status))
-
 
1302
	goto error;
-
 
1303
 
-
 
1304
    /* We use the parent as a flag during map-to-image/umap-image that the
-
 
1305
     * resultant image came from a fallback rather than as direct call
-
 
1306
     * to the backend's map_to_image(). Whilst we use it as a simple flag,
-
 
1307
     * we need to make sure the parent surface obeys the reference counting
-
 
1308
     * semantics and is consistent for all callers.
-
 
1309
     */
-
 
1310
    _cairo_image_surface_set_parent (to_image_surface (image),
-
 
1311
				     cairo_surface_reference (surface));
-
 
1312
 
-
 
1313
    return to_image_surface (image);
-
 
1314
 
-
 
1315
error:
-
 
1316
    cairo_surface_destroy (image);
-
 
1317
    return to_image_surface (_cairo_surface_create_in_error (status));