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 38... Line 38...
38
 *	Kristian Høgsberg 
38
 *	Kristian Høgsberg 
39
 *	Chris Wilson 
39
 *	Chris Wilson 
40
 */
40
 */
Line 41... Line 41...
41
 
41
 
-
 
42
#include "cairoint.h"
42
#include "cairoint.h"
43
#include "cairo-clip-inline.h"
43
#include "cairo-clip-private.h"
44
#include "cairo-clip-private.h"
44
#include "cairo-error-private.h"
45
#include "cairo-error-private.h"
45
#include "cairo-freed-pool-private.h"
46
#include "cairo-freed-pool-private.h"
46
#include "cairo-gstate-private.h"
47
#include "cairo-gstate-private.h"
-
 
48
#include "cairo-path-fixed-private.h"
47
#include "cairo-path-fixed-private.h"
49
#include "cairo-pattern-private.h"
48
#include "cairo-composite-rectangles-private.h"
50
#include "cairo-composite-rectangles-private.h"
Line 49... Line -...
49
#include "cairo-region-private.h"
-
 
50
 
51
#include "cairo-region-private.h"
-
 
52
 
51
#if HAS_FREED_POOL
53
static freed_pool_t clip_path_pool;
-
 
54
static freed_pool_t clip_pool;
Line 52... Line 55...
52
static freed_pool_t clip_path_pool;
55
 
53
#endif
56
const cairo_clip_t __cairo_clip_all;
54
 
57
 
55
static cairo_clip_path_t *
58
static cairo_clip_path_t *
Line 64... Line 67...
64
	    return NULL;
67
	    return NULL;
65
    }
68
    }
Line 66... Line 69...
66
 
69
 
Line 67... Line -...
67
    CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
-
 
68
 
-
 
69
    clip_path->flags = 0;
-
 
70
    clip_path->region = NULL;
-
 
71
    clip_path->surface = NULL;
70
    CAIRO_REFERENCE_COUNT_INIT (&clip_path->ref_count, 1);
72
 
71
 
Line 73... Line 72...
73
    clip_path->prev = clip->path;
72
    clip_path->prev = clip->path;
74
    clip->path = clip_path;
73
    clip->path = clip_path;
Line 75... Line 74...
75
 
74
 
76
    return clip_path;
75
    return clip_path;
77
}
76
}
78
 
77
 
Line 79... Line 78...
79
static cairo_clip_path_t *
78
cairo_clip_path_t *
Line 80... Line 79...
80
_cairo_clip_path_reference (cairo_clip_path_t *clip_path)
79
_cairo_clip_path_reference (cairo_clip_path_t *clip_path)
81
{
80
{
Line 82... Line 81...
82
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
81
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
83
 
82
 
84
    _cairo_reference_count_inc (&clip_path->ref_count);
83
    _cairo_reference_count_inc (&clip_path->ref_count);
85
 
84
 
Line 86... Line 85...
86
    return clip_path;
85
    return clip_path;
87
}
86
}
Line 88... Line 87...
88
 
87
 
89
static void
-
 
90
_cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
-
 
91
{
-
 
92
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
-
 
Line 93... Line 88...
93
 
88
void
94
    if (! _cairo_reference_count_dec_and_test (&clip_path->ref_count))
89
_cairo_clip_path_destroy (cairo_clip_path_t *clip_path)
Line 95... Line 90...
95
	return;
90
{
96
 
91
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&clip_path->ref_count));
Line 97... Line 92...
97
    _cairo_path_fixed_fini (&clip_path->path);
92
 
98
    if (clip_path->region != NULL)
93
    if (! _cairo_reference_count_dec_and_test (&clip_path->ref_count))
99
	cairo_region_destroy (clip_path->region);
94
	return;
100
    if (clip_path->surface != NULL)
95
 
-
 
96
    _cairo_path_fixed_fini (&clip_path->path);
-
 
97
 
-
 
98
    if (clip_path->prev != NULL)
-
 
99
	_cairo_clip_path_destroy (clip_path->prev);
-
 
100
 
-
 
101
    _freed_pool_put (&clip_path_pool, clip_path);
-
 
102
}
-
 
103
 
-
 
104
cairo_clip_t *
-
 
105
_cairo_clip_create (void)
101
	cairo_surface_destroy (clip_path->surface);
106
{
-
 
107
    cairo_clip_t *clip;
-
 
108
 
-
 
109
    clip = _freed_pool_get (&clip_pool);
-
 
110
    if (unlikely (clip == NULL)) {
-
 
111
	clip = malloc (sizeof (cairo_clip_t));
-
 
112
	if (unlikely (clip == NULL))
102
 
113
	    return NULL;
Line 103... Line 114...
103
    if (clip_path->prev != NULL)
114
    }
104
	_cairo_clip_path_destroy (clip_path->prev);
115
 
105
 
116
    clip->extents = _cairo_unbounded_rectangle;
106
    _freed_pool_put (&clip_path_pool, clip_path);
117
 
-
 
118
    clip->path = NULL;
-
 
119
    clip->boxes = NULL;
107
}
120
    clip->num_boxes = 0;
108
 
121
    clip->region = NULL;
-
 
122
    clip->is_region = FALSE;
-
 
123
 
109
void
124
    return clip;
-
 
125
}
110
_cairo_clip_init (cairo_clip_t *clip)
126
 
-
 
127
void
111
{
128
_cairo_clip_destroy (cairo_clip_t *clip)
Line 112... Line 129...
112
    clip->all_clipped = FALSE;
129
{
113
    clip->path = NULL;
130
    if (clip == NULL || _cairo_clip_is_all_clipped (clip))
114
}
-
 
115
 
131
	return;
116
static void
132
 
117
_cairo_clip_set_all_clipped (cairo_clip_t *clip)
-
 
Line 118... Line -...
118
{
-
 
119
    clip->all_clipped = TRUE;
-
 
120
    if (clip->path != NULL) {
133
    if (clip->path != NULL)
121
	_cairo_clip_path_destroy (clip->path);
-
 
122
	clip->path = NULL;
-
 
123
    }
-
 
124
}
134
	_cairo_clip_path_destroy (clip->path);
125
 
-
 
126
static cairo_status_t
-
 
Line 127... Line 135...
127
_cairo_clip_intersect_rectangle (cairo_clip_t *clip,
135
 
128
				 const cairo_rectangle_int_t *rect)
-
 
129
{
-
 
Line -... Line 136...
-
 
136
    if (clip->boxes != &clip->embedded_box)
130
    cairo_clip_path_t *clip_path;
137
	free (clip->boxes);
Line 131... Line -...
131
    cairo_status_t status;
-
 
132
 
-
 
133
    if (clip->path != NULL) {
-
 
134
	if (rect->x <= clip->path->extents.x &&
-
 
135
	    rect->y <= clip->path->extents.y &&
-
 
136
	    rect->x + rect->width >= clip->path->extents.x + clip->path->extents.width &&
-
 
137
	    rect->y + rect->height >= clip->path->extents.y + clip->path->extents.height)
138
    cairo_region_destroy (clip->region);
138
	{
-
 
139
	    return CAIRO_STATUS_SUCCESS;
-
 
140
	}
139
 
141
    }
140
    _freed_pool_put (&clip_pool, clip);
142
 
-
 
143
    clip_path = _cairo_clip_path_create (clip);
-
 
144
    if (unlikely (clip_path == NULL))
-
 
145
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
141
}
146
 
-
 
147
    _cairo_path_fixed_init (&clip_path->path);
142
 
148
 
-
 
149
    status = _cairo_path_fixed_move_to (&clip_path->path,
-
 
150
					_cairo_fixed_from_int (rect->x),
-
 
151
					_cairo_fixed_from_int (rect->y));
-
 
152
    assert (status == CAIRO_STATUS_SUCCESS);
-
 
153
    status = _cairo_path_fixed_rel_line_to (&clip_path->path,
-
 
154
					    _cairo_fixed_from_int (rect->width),
-
 
155
					    _cairo_fixed_from_int (0));
-
 
156
    assert (status == CAIRO_STATUS_SUCCESS);
143
cairo_clip_t *
157
    status = _cairo_path_fixed_rel_line_to (&clip_path->path,
-
 
158
					    _cairo_fixed_from_int (0),
-
 
159
					    _cairo_fixed_from_int (rect->height));
-
 
160
    assert (status == CAIRO_STATUS_SUCCESS);
144
_cairo_clip_copy (const cairo_clip_t *clip)
161
    status = _cairo_path_fixed_rel_line_to (&clip_path->path,
145
{
-
 
146
    cairo_clip_t *copy;
-
 
147
 
-
 
148
    if (clip == NULL || _cairo_clip_is_all_clipped (clip))
-
 
149
	return (cairo_clip_t *) clip;
162
					    _cairo_fixed_from_int (-rect->width),
150
 
Line -... Line 151...
-
 
151
    copy = _cairo_clip_create ();
163
					    _cairo_fixed_from_int (0));
152
 
-
 
153
    if (clip->path)
Line 164... Line 154...
164
    assert (status == CAIRO_STATUS_SUCCESS);
154
	copy->path = _cairo_clip_path_reference (clip->path);
165
    status = _cairo_path_fixed_close_path (&clip_path->path);
155
 
Line 166... Line 156...
166
    assert (status == CAIRO_STATUS_SUCCESS);
156
    if (clip->num_boxes) {
167
 
157
	if (clip->num_boxes == 1) {
168
    clip_path->fill_rule = CAIRO_FILL_RULE_WINDING;
158
	    copy->boxes = ©->embedded_box;
169
    clip_path->tolerance = 1;
159
	} else {
-
 
160
	    copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
170
    clip_path->antialias = CAIRO_ANTIALIAS_DEFAULT;
161
	    if (unlikely (copy->boxes == NULL))
171
    clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
162
		return _cairo_clip_set_all_clipped (copy);
-
 
163
	}
172
 
164
 
-
 
165
	memcpy (copy->boxes, clip->boxes,
173
    clip_path->extents = *rect;
166
		clip->num_boxes * sizeof (cairo_box_t));
174
    if (clip_path->prev != NULL) {
167
	copy->num_boxes = clip->num_boxes;
175
	if (! _cairo_rectangle_intersect (&clip_path->extents,
168
    }
176
					  &clip_path->prev->extents))
169
 
-
 
170
    copy->extents = clip->extents;
-
 
171
    copy->region = cairo_region_reference (clip->region);
177
	{
172
    copy->is_region = clip->is_region;
-
 
173
 
-
 
174
    return copy;
-
 
175
}
-
 
176
 
-
 
177
cairo_clip_t *
-
 
178
_cairo_clip_copy_path (const cairo_clip_t *clip)
-
 
179
{
-
 
180
    cairo_clip_t *copy;
-
 
181
 
-
 
182
    if (clip == NULL || _cairo_clip_is_all_clipped (clip))
-
 
183
	return (cairo_clip_t *) clip;
-
 
184
 
-
 
185
    assert (clip->num_boxes);
-
 
186
 
-
 
187
    copy = _cairo_clip_create ();
-
 
188
    copy->extents = clip->extents;
-
 
189
    if (clip->path)
178
	    _cairo_clip_set_all_clipped (clip);
190
	copy->path = _cairo_clip_path_reference (clip->path);
179
	}
191
 
180
    }
192
    return copy;
-
 
193
}
181
 
194
 
Line 182... Line 195...
182
    /* could preallocate the region if it proves worthwhile */
195
cairo_clip_t *
-
 
196
_cairo_clip_copy_region (const cairo_clip_t *clip)
-
 
197
{
-
 
198
    cairo_clip_t *copy;
-
 
199
    int i;
183
 
200
 
-
 
201
    if (clip == NULL || _cairo_clip_is_all_clipped (clip))
Line 184... Line -...
184
    return CAIRO_STATUS_SUCCESS;
-
 
185
}
202
	return (cairo_clip_t *) clip;
-
 
203
 
186
 
204
    assert (clip->num_boxes);
187
cairo_clip_t *
-
 
188
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other)
-
 
189
{
-
 
190
    if (other != NULL) {
205
 
191
	clip->all_clipped = other->all_clipped;
-
 
192
	if (other->path == NULL) {
206
    copy = _cairo_clip_create ();
Line 193... Line 207...
193
	    clip->path = NULL;
207
    copy->extents = clip->extents;
194
	    if (! clip->all_clipped)
208
 
195
		clip = NULL;
209
    if (clip->num_boxes == 1) {
196
	} else {
210
	copy->boxes = ©->embedded_box;
197
	    clip->path = _cairo_clip_path_reference (other->path);
211
    } else {
198
	}
212
	copy->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
199
    } else {
213
	if (unlikely (copy->boxes == NULL))
200
	_cairo_clip_init (clip);
214
	    return _cairo_clip_set_all_clipped (copy);
201
	clip = NULL;
215
    }
202
    }
216
 
203
 
217
    for (i = 0; i < clip->num_boxes; i++) {
204
    return clip;
-
 
Line 205... Line -...
205
}
-
 
206
 
-
 
207
void
-
 
208
_cairo_clip_reset (cairo_clip_t *clip)
-
 
209
{
218
	copy->boxes[i].p1.x = _cairo_fixed_floor (clip->boxes[i].p1.x);
210
    clip->all_clipped = FALSE;
-
 
211
    if (clip->path != NULL) {
219
	copy->boxes[i].p1.y = _cairo_fixed_floor (clip->boxes[i].p1.y);
212
	_cairo_clip_path_destroy (clip->path);
-
 
213
	clip->path = NULL;
-
 
Line 214... Line 220...
214
    }
220
	copy->boxes[i].p2.x = _cairo_fixed_ceil (clip->boxes[i].p2.x);
215
}
221
	copy->boxes[i].p2.y = _cairo_fixed_ceil (clip->boxes[i].p2.y);
216
 
222
    }
217
static cairo_status_t
-
 
218
_cairo_clip_intersect_path (cairo_clip_t       *clip,
-
 
Line 219... Line 223...
219
			    const cairo_path_fixed_t *path,
223
    copy->num_boxes = clip->num_boxes;
220
			    cairo_fill_rule_t   fill_rule,
224
 
221
			    double              tolerance,
225
    copy->region = cairo_region_reference (clip->region);
222
			    cairo_antialias_t   antialias)
226
    copy->is_region = TRUE;
223
{
227
 
-
 
228
    return copy;
224
    cairo_clip_path_t *clip_path;
229
}
-
 
230
 
-
 
231
cairo_clip_t *
-
 
232
_cairo_clip_intersect_path (cairo_clip_t       *clip,
-
 
233
			    const cairo_path_fixed_t *path,
-
 
234
			    cairo_fill_rule_t   fill_rule,
-
 
235
			    double              tolerance,
Line 225... Line -...
225
    cairo_status_t status;
-
 
226
    cairo_rectangle_int_t extents;
-
 
227
    cairo_box_t box;
236
			    cairo_antialias_t   antialias)
228
    cairo_bool_t is_box = FALSE;
237
{
229
 
238
    cairo_clip_path_t *clip_path;
230
    if (clip->path != NULL) {
-
 
231
	if (clip->path->fill_rule == fill_rule &&
239
    cairo_status_t status;
-
 
240
    cairo_rectangle_int_t extents;
232
	    (path->is_rectilinear || tolerance == clip->path->tolerance) &&
241
    cairo_box_t box;
233
	    antialias == clip->path->antialias &&
-
 
234
	    _cairo_path_fixed_equal (&clip->path->path, path))
242
 
Line 235... Line 243...
235
	{
243
    if (_cairo_clip_is_all_clipped (clip))
236
	    return CAIRO_STATUS_SUCCESS;
244
	return clip;
237
	}
245
 
Line 238... Line 246...
238
    }
246
    /* catch the empty clip path */
239
 
247
    if (_cairo_path_fixed_fill_is_empty (path))
240
    _cairo_path_fixed_approximate_clip_extents (path, &extents);
-
 
241
    if (extents.width == 0 || extents.height == 0) {
248
	return _cairo_clip_set_all_clipped (clip);
242
	_cairo_clip_set_all_clipped (clip);
-
 
243
	return CAIRO_STATUS_SUCCESS;
-
 
Line 244... Line -...
244
    }
-
 
245
 
249
 
246
    is_box = _cairo_path_fixed_is_box (path, &box);
250
    if (_cairo_path_fixed_is_box (path, &box)) {
247
    if (clip->path != NULL) {
251
	if (antialias == CAIRO_ANTIALIAS_NONE) {
248
	if (! _cairo_rectangle_intersect (&extents, &clip->path->extents)) {
-
 
249
	    _cairo_clip_set_all_clipped (clip);
-
 
Line -... Line 252...
-
 
252
	    box.p1.x = _cairo_fixed_round_down (box.p1.x);
250
	    return CAIRO_STATUS_SUCCESS;
253
	    box.p1.y = _cairo_fixed_round_down (box.p1.y);
-
 
254
	    box.p2.x = _cairo_fixed_round_down (box.p2.x);
251
	}
255
	    box.p2.y = _cairo_fixed_round_down (box.p2.y);
Line -... Line 256...
-
 
256
	}
-
 
257
 
-
 
258
	return _cairo_clip_intersect_box (clip, &box);
-
 
259
    }
252
 
260
    if (_cairo_path_fixed_fill_is_rectilinear (path))
253
	/* does this clip wholly subsume the others? */
261
	return _cairo_clip_intersect_rectilinear_path (clip, path,
254
	if (is_box &&
262
						       fill_rule, antialias);
255
	    box.p1.x <= _cairo_fixed_from_int (clip->path->extents.x) &&
263
 
-
 
264
    _cairo_path_fixed_approximate_clip_extents (path, &extents);
256
	    box.p2.x >= _cairo_fixed_from_int (clip->path->extents.x + clip->path->extents.width) &&
265
    if (extents.width == 0 || extents.height == 0)
Line -... Line 266...
-
 
266
	return _cairo_clip_set_all_clipped (clip);
257
	    box.p1.y <= _cairo_fixed_from_int (clip->path->extents.y) &&
267
 
-
 
268
    clip = _cairo_clip_intersect_rectangle (clip, &extents);
-
 
269
    if (_cairo_clip_is_all_clipped (clip))
258
	    box.p2.y >= _cairo_fixed_from_int (clip->path->extents.y + clip->path->extents.height))
270
	return clip;
-
 
271
 
Line -... Line 272...
-
 
272
    clip_path = _cairo_clip_path_create (clip);
259
	{
273
    if (unlikely (clip_path == NULL))
260
	    return CAIRO_STATUS_SUCCESS;
274
	return _cairo_clip_set_all_clipped (clip);
-
 
275
 
-
 
276
    status = _cairo_path_fixed_init_copy (&clip_path->path, path);
261
	}
277
    if (unlikely (status))
Line 262... Line 278...
262
    }
278
	return _cairo_clip_set_all_clipped (clip);
263
 
279
 
Line 264... Line 280...
264
    clip_path = _cairo_clip_path_create (clip);
280
    clip_path->fill_rule = fill_rule;
265
    if (unlikely (clip_path == NULL))
281
    clip_path->tolerance = tolerance;
Line 266... Line 282...
266
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
282
    clip_path->antialias = antialias;
267
 
283
 
Line 268... Line 284...
268
    status = _cairo_path_fixed_init_copy (&clip_path->path, path);
284
    if (clip->region) {
269
    if (unlikely (status)) {
285
	cairo_region_destroy (clip->region);
Line 270... Line 286...
270
	clip->path = clip->path->prev;
286
	clip->region = NULL;
271
	_cairo_clip_path_destroy (clip_path);
287
    }
272
	return status;
-
 
Line -... Line 288...
-
 
288
 
273
    }
289
    clip->is_region = FALSE;
274
 
290
    return clip;
Line 275... Line -...
275
    clip_path->extents = extents;
-
 
276
    clip_path->fill_rule = fill_rule;
291
}
277
    clip_path->tolerance = tolerance;
292
 
278
    clip_path->antialias = antialias;
293
static cairo_clip_t *
279
    if (is_box)
294
_cairo_clip_intersect_clip_path (cairo_clip_t *clip,
-
 
295
				 const cairo_clip_path_t *clip_path)
280
	clip_path->flags |= CAIRO_CLIP_PATH_IS_BOX;
296
{
281
 
297
    if (clip_path->prev)
282
    return CAIRO_STATUS_SUCCESS;
298
	clip = _cairo_clip_intersect_clip_path (clip, clip_path->prev);
283
}
-
 
Line 284... Line 299...
284
 
299
 
285
cairo_bool_t
-
 
286
_cairo_clip_equal (const cairo_clip_t *clip_a,
300
    return _cairo_clip_intersect_path (clip,
287
		   const cairo_clip_t *clip_b)
301
				       &clip_path->path,
288
{
302
				       clip_path->fill_rule,
-
 
303
				       clip_path->tolerance,
Line 289... Line -...
289
    const cairo_clip_path_t *clip_path_a, *clip_path_b;
-
 
290
 
-
 
291
    clip_path_a = clip_a->path;
304
				       clip_path->antialias);
292
    clip_path_b = clip_b->path;
305
}
Line 293... Line 306...
293
 
306
 
294
    while (clip_path_a && clip_path_b) {
307
cairo_clip_t *
295
	if (clip_path_a == clip_path_b)
308
_cairo_clip_intersect_clip (cairo_clip_t *clip,
296
	    return TRUE;
309
			    const cairo_clip_t *other)
297
 
310
{
298
	if (clip_path_a->fill_rule != clip_path_b->fill_rule)
-
 
Line 299... Line 311...
299
	    return FALSE;
311
    if (_cairo_clip_is_all_clipped (clip))
300
 
312
	return clip;
301
	if (clip_path_a->tolerance != clip_path_b->tolerance)
313
 
302
	    return FALSE;
-
 
Line 303... Line 314...
303
 
314
    if (other == NULL)
304
	if (clip_path_a->antialias != clip_path_b->antialias)
315
	return clip;
305
	    return FALSE;
316
 
306
 
317
    if (clip == NULL)
307
	if (! _cairo_path_fixed_equal (&clip_path_a->path, &clip_path_b->path))
-
 
308
	    return FALSE;
-
 
309
 
318
	return _cairo_clip_copy (other);
310
	clip_path_a = clip_path_a->prev;
319
 
311
	clip_path_b = clip_path_b->prev;
-
 
312
    }
320
    if (_cairo_clip_is_all_clipped (other))
Line 313... Line 321...
313
 
321
	return _cairo_clip_set_all_clipped (clip);
314
    return clip_path_a == clip_path_b; /* ie both NULL */
-
 
Line 315... Line -...
315
}
-
 
316
 
-
 
317
cairo_status_t
-
 
318
_cairo_clip_clip (cairo_clip_t       *clip,
-
 
319
		  const cairo_path_fixed_t *path,
-
 
320
		  cairo_fill_rule_t   fill_rule,
-
 
321
		  double              tolerance,
322
 
322
		  cairo_antialias_t   antialias)
323
    if (! _cairo_rectangle_intersect (&clip->extents, &other->extents))
Line 323... Line 324...
323
{
324
	return _cairo_clip_set_all_clipped (clip);
324
    if (clip->all_clipped)
325
 
325
	return CAIRO_STATUS_SUCCESS;
-
 
326
 
-
 
327
    /* catch the empty clip path */
-
 
328
    if (_cairo_path_fixed_fill_is_empty (path)) {
326
    if (other->num_boxes) {
329
	_cairo_clip_set_all_clipped (clip);
-
 
Line 330... Line 327...
330
	return CAIRO_STATUS_SUCCESS;
327
	cairo_boxes_t boxes;
-
 
328
 
331
    }
329
	_cairo_boxes_init_for_array (&boxes, other->boxes, other->num_boxes);
-
 
330
	clip = _cairo_clip_intersect_boxes (clip, &boxes);
332
 
331
    }
Line 333... Line -...
333
    return _cairo_clip_intersect_path (clip,
-
 
334
				       path, fill_rule, tolerance,
-
 
335
				       antialias);
-
 
336
}
-
 
337
 
332
 
338
cairo_status_t
-
 
339
_cairo_clip_rectangle (cairo_clip_t       *clip,
-
 
Line 340... Line 333...
340
		       const cairo_rectangle_int_t *rectangle)
333
    if (! _cairo_clip_is_all_clipped (clip)) {
341
{
-
 
342
    if (clip->all_clipped)
-
 
343
	return CAIRO_STATUS_SUCCESS;
334
	if (other->path) {
344
 
-
 
345
    if (rectangle->width == 0 || rectangle->height == 0) {
-
 
346
	_cairo_clip_set_all_clipped (clip);
-
 
Line 347... Line -...
347
	return CAIRO_STATUS_SUCCESS;
-
 
348
    }
335
	    if (clip->path == NULL)
349
 
336
		clip->path = _cairo_clip_path_reference (other->path);
Line -... Line 337...
-
 
337
	    else
-
 
338
		clip = _cairo_clip_intersect_clip_path (clip, other->path);
-
 
339
	}
-
 
340
    }
-
 
341
 
350
    /* if a smaller clip has already been set, ignore the new path */
342
    if (clip->region) {
-
 
343
	cairo_region_destroy (clip->region);
-
 
344
	clip->region = NULL;
-
 
345
    }
351
    if (clip->path != NULL) {
346
    clip->is_region = FALSE;
Line -... Line 347...
-
 
347
 
-
 
348
    return clip;
-
 
349
}
352
	if (rectangle->x <= clip->path->extents.x &&
350
 
353
	    rectangle->y <= clip->path->extents.y &&
351
cairo_bool_t
354
	    rectangle->x + rectangle->width  >= clip->path->extents.x + clip->path->extents.width &&
352
_cairo_clip_equal (const cairo_clip_t *clip_a,
355
	    rectangle->y + rectangle->height >= clip->path->extents.y + clip->path->extents.height)
353
		   const cairo_clip_t *clip_b)
356
	{
354
{
357
	    return CAIRO_STATUS_SUCCESS;
355
    const cairo_clip_path_t *cp_a, *cp_b;
358
	}
356
 
Line 359... Line 357...
359
    }
357
    /* are both all-clipped or no-clip? */
360
 
358
    if (clip_a == clip_b)
361
    return _cairo_clip_intersect_rectangle (clip, rectangle);
-
 
362
}
359
	return TRUE;
363
 
360
 
364
static cairo_status_t
361
    /* or just one of them? */
365
_cairo_clip_path_reapply_clip_path_transform (cairo_clip_t      *clip,
-
 
Line 366... Line 362...
366
					      cairo_clip_path_t *other_path,
362
    if (clip_a == NULL || clip_b == NULL ||
367
					      const cairo_matrix_t *matrix)
363
	_cairo_clip_is_all_clipped (clip_a) ||
368
{
364
	_cairo_clip_is_all_clipped (clip_b))
Line 369... Line 365...
369
    cairo_status_t status;
365
    {
370
    cairo_clip_path_t *clip_path;
366
	return FALSE;
371
    cairo_bool_t is_empty;
367
    }
372
 
-
 
373
    if (other_path->prev != NULL) {
368
 
374
        status = _cairo_clip_path_reapply_clip_path_transform (clip,
-
 
375
							       other_path->prev,
-
 
Line 376... Line 369...
376
							       matrix);
369
    /* We have a pair of normal clips, check their contents */
377
	if (unlikely (status))
-
 
378
	    return status;
-
 
Line 379... Line 370...
379
    }
370
 
380
 
371
    if (clip_a->num_boxes != clip_b->num_boxes)
381
    clip_path = _cairo_clip_path_create (clip);
372
	return FALSE;
Line 382... Line -...
382
    if (unlikely (clip_path == NULL))
-
 
383
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
384
 
-
 
385
    status = _cairo_path_fixed_init_copy (&clip_path->path,
-
 
386
					  &other_path->path);
-
 
387
    if (unlikely (status)) {
-
 
388
	clip->path = clip->path->prev;
-
 
389
	_cairo_clip_path_destroy (clip_path);
-
 
390
	return status;
-
 
391
    }
-
 
392
 
-
 
393
    _cairo_path_fixed_transform (&clip_path->path, matrix);
-
 
394
    _cairo_path_fixed_approximate_clip_extents (&clip_path->path,
-
 
395
						&clip_path->extents);
-
 
396
    if (clip_path->prev != NULL) {
-
 
397
	is_empty = _cairo_rectangle_intersect (&clip_path->extents,
-
 
398
					       &clip_path->prev->extents);
-
 
399
    }
-
 
400
 
-
 
401
    clip_path->fill_rule = other_path->fill_rule;
-
 
402
    clip_path->tolerance = other_path->tolerance;
-
 
403
    clip_path->antialias = other_path->antialias;
-
 
404
 
-
 
405
    return CAIRO_STATUS_SUCCESS;
-
 
406
}
-
 
407
 
-
 
408
static cairo_status_t
-
 
409
_cairo_clip_path_reapply_clip_path_translate (cairo_clip_t      *clip,
-
 
410
					      cairo_clip_path_t *other_path,
-
 
411
					      int tx, int ty)
-
 
412
{
-
 
413
    cairo_status_t status;
-
 
414
    cairo_clip_path_t *clip_path;
-
 
415
 
-
 
416
    if (other_path->prev != NULL) {
-
 
417
        status = _cairo_clip_path_reapply_clip_path_translate (clip,
-
 
418
							       other_path->prev,
-
 
419
							       tx, ty);
-
 
420
	if (unlikely (status))
-
 
421
	    return status;
-
 
422
    }
-
 
423
 
-
 
424
    clip_path = _cairo_clip_path_create (clip);
-
 
425
    if (unlikely (clip_path == NULL))
-
 
426
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
427
 
-
 
428
    status = _cairo_path_fixed_init_copy (&clip_path->path,
-
 
429
					  &other_path->path);
-
 
430
    if (unlikely (status)) {
-
 
431
	clip->path = clip->path->prev;
-
 
432
	_cairo_clip_path_destroy (clip_path);
-
 
433
	return status;
-
 
434
    }
-
 
435
 
-
 
436
    _cairo_path_fixed_translate (&clip_path->path,
-
 
437
				 _cairo_fixed_from_int (tx),
-
 
438
				 _cairo_fixed_from_int (ty));
-
 
439
 
-
 
440
    clip_path->fill_rule = other_path->fill_rule;
-
 
441
    clip_path->tolerance = other_path->tolerance;
-
 
442
    clip_path->antialias = other_path->antialias;
-
 
443
 
-
 
444
    clip_path->flags = other_path->flags;
-
 
445
    if (other_path->region != NULL) {
-
 
446
	clip_path->region = cairo_region_copy (other_path->region);
-
 
447
	status = clip_path->region->status;
-
 
448
	if (unlikely (status)) {
-
 
449
	    clip->path = clip->path->prev;
-
 
450
	    _cairo_clip_path_destroy (clip_path);
373
 
451
	    return status;
374
    if (memcmp (clip_a->boxes, clip_b->boxes,
Line 452... Line 375...
452
	}
375
		sizeof (cairo_box_t) * clip_a->num_boxes))
453
 
376
	return FALSE;
454
	cairo_region_translate (clip_path->region, tx, ty);
-
 
455
    }
377
 
456
    clip_path->surface = cairo_surface_reference (other_path->surface);
378
    cp_a = clip_a->path;
457
 
-
 
458
    clip_path->extents = other_path->extents;
-
 
459
    clip_path->extents.x += tx;
379
    cp_b = clip_b->path;
Line 460... Line 380...
460
    clip_path->extents.y += ty;
380
    while (cp_a && cp_b) {
461
 
-
 
462
    return CAIRO_STATUS_SUCCESS;
-
 
463
}
-
 
464
 
381
	if (cp_a == cp_b)
465
cairo_status_t
-
 
Line 466... Line -...
466
_cairo_clip_init_copy_transformed (cairo_clip_t    *clip,
-
 
467
				   cairo_clip_t    *other,
-
 
468
				   const cairo_matrix_t *matrix)
382
	    return TRUE;
469
{
-
 
470
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
383
 
Line 471... Line 384...
471
    int tx, ty;
384
	/* XXX compare reduced polygons? */
472
 
385
 
Line 473... Line 386...
473
    if (other == NULL) {
386
	if (cp_a->antialias != cp_b->antialias)
-
 
387
	    return FALSE;
-
 
388
 
474
	_cairo_clip_init (clip);
389
	if (cp_a->tolerance != cp_b->tolerance)
475
	return CAIRO_STATUS_SUCCESS;
390
	    return FALSE;
476
    }
391
 
Line 477... Line -...
477
 
-
 
478
    if (other->all_clipped) {
392
	if (cp_a->fill_rule != cp_b->fill_rule)
479
	_cairo_clip_init (clip);
-
 
480
	clip->all_clipped = TRUE;
-
 
481
	return CAIRO_STATUS_SUCCESS;
393
	    return FALSE;
482
    }
-
 
Line 483... Line -...
483
 
-
 
484
    if (_cairo_matrix_is_identity (matrix)) {
-
 
485
	_cairo_clip_init_copy (clip, other);
-
 
486
	return CAIRO_STATUS_SUCCESS;
394
 
487
    }
-
 
488
 
395
	if (! _cairo_path_fixed_equal (&cp_a->path,
Line 489... Line 396...
489
    if (other->path != NULL) {
396
				       &cp_b->path))
490
	_cairo_clip_init (clip);
397
	    return FALSE;
-
 
398
 
-
 
399
	cp_a = cp_a->prev;
Line 491... Line 400...
491
 
400
	cp_b = cp_b->prev;
492
	/* if we only need to translate, so we can reuse the caches... */
401
    }
Line 493... Line 402...
493
	/* XXX we still loose the benefit of constructs when the copy is
402
 
494
	 * deleted though. Indirect clip_paths?
403
    return cp_a == NULL && cp_b == NULL;
-
 
404
}
495
	 */
405
 
496
	if (_cairo_matrix_is_integer_translation (matrix, &tx, &ty)) {
-
 
497
	    status = _cairo_clip_path_reapply_clip_path_translate (clip,
-
 
498
								   other->path,
-
 
499
								   tx, ty);
406
static cairo_clip_t *
500
	} else {
-
 
501
	    status = _cairo_clip_path_reapply_clip_path_transform (clip,
-
 
502
								   other->path,
-
 
503
								   matrix);
-
 
504
	    if (clip->path->extents.width == 0 &&
-
 
505
		clip->path->extents.height == 0)
-
 
506
	    {
-
 
507
		_cairo_clip_set_all_clipped (clip);
-
 
508
	    }
-
 
509
	}
-
 
510
    }
-
 
511
 
-
 
512
    return status;
-
 
513
}
-
 
514
 
-
 
515
static cairo_status_t
-
 
516
_cairo_clip_apply_clip_path (cairo_clip_t *clip,
-
 
517
			     const cairo_clip_path_t *path)
-
 
518
{
-
 
519
    cairo_status_t status;
-
 
520
 
-
 
521
    if (path->prev != NULL)
-
 
522
	status = _cairo_clip_apply_clip_path (clip, path->prev);
-
 
523
 
-
 
524
    return _cairo_clip_intersect_path (clip,
-
 
525
				       &path->path,
-
 
526
				       path->fill_rule,
-
 
527
				       path->tolerance,
-
 
528
				       path->antialias);
-
 
529
}
-
 
530
 
-
 
531
cairo_status_t
-
 
532
_cairo_clip_apply_clip (cairo_clip_t *clip,
-
 
533
			const cairo_clip_t *other)
-
 
534
{
-
 
535
    cairo_status_t status;
-
 
536
 
-
 
537
    if (clip->all_clipped)
-
 
538
	return CAIRO_STATUS_SUCCESS;
-
 
539
 
-
 
540
    if (other->all_clipped) {
-
 
541
	_cairo_clip_set_all_clipped (clip);
-
 
542
	return CAIRO_STATUS_SUCCESS;
-
 
543
    }
-
 
544
 
-
 
545
    status = CAIRO_STATUS_SUCCESS;
-
 
546
    if (other->path != NULL)
-
 
Line -... Line 407...
-
 
407
_cairo_clip_path_copy_with_translation (cairo_clip_t      *clip,
547
	status = _cairo_clip_apply_clip_path (clip, other->path);
408
					cairo_clip_path_t *other_path,
548
 
409
					int fx, int fy)
Line 549... Line 410...
549
    return status;
410
{
550
}
-
 
551
 
-
 
552
static inline cairo_bool_t
-
 
553
_clip_paths_are_rectilinear (cairo_clip_path_t *clip_path)
-
 
554
{
411
    cairo_status_t status;
555
    while (clip_path != NULL) {
412
    cairo_clip_path_t *clip_path;
Line 556... Line -...
556
	if (! clip_path->path.is_rectilinear)
-
 
557
	    return FALSE;
-
 
558
 
-
 
559
	clip_path = clip_path->prev;
-
 
560
    }
-
 
561
 
-
 
562
    return TRUE;
-
 
563
}
-
 
564
 
-
 
565
static cairo_int_status_t
-
 
566
_cairo_clip_path_to_region_geometric (cairo_clip_path_t *clip_path)
-
 
567
{
-
 
568
    cairo_traps_t traps;
-
 
569
    cairo_box_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_t)];
-
 
570
    cairo_box_t *boxes = stack_boxes;
-
 
571
    cairo_status_t status;
-
 
572
    int n;
-
 
573
 
-
 
574
    /* If we have nothing to intersect with this path, then it cannot
-
 
575
     * magically be reduced into a region.
-
 
576
     */
-
 
577
    if (clip_path->prev == NULL)
-
 
578
	goto UNSUPPORTED;
-
 
579
 
-
 
580
    /* Start simple... Intersect some boxes with an arbitrary path. */
-
 
581
    if (! clip_path->path.is_rectilinear)
-
 
582
	goto UNSUPPORTED;
-
 
583
    if (clip_path->prev->prev != NULL)
-
 
584
	goto UNSUPPORTED;
413
 
585
 
-
 
586
    _cairo_traps_init (&traps);
-
 
587
    _cairo_box_from_rectangle (&boxes[0], &clip_path->extents);
-
 
588
    _cairo_traps_limit (&traps, boxes, 1);
-
 
589
 
-
 
590
    status = _cairo_path_fixed_fill_rectilinear_to_traps (&clip_path->path,
-
 
591
							  clip_path->fill_rule,
-
 
592
							  &traps);
-
 
593
    if (unlikely (_cairo_status_is_error (status)))
-
 
594
	return status;
-
 
595
    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-
 
596
	goto UNSUPPORTED;
-
 
597
 
-
 
598
    if (traps.num_traps > ARRAY_LENGTH (stack_boxes)) {
-
 
599
	boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
-
 
600
	if (unlikely (boxes == NULL))
-
 
601
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
602
    }
-
 
603
 
414
    if (other_path->prev != NULL)
604
    for (n = 0; n < traps.num_traps; n++) {
415
	clip = _cairo_clip_path_copy_with_translation (clip, other_path->prev,
Line 605... Line -...
605
	boxes[n].p1.x = traps.traps[n].left.p1.x;
-
 
606
	boxes[n].p1.y = traps.traps[n].top;
416
						       fx, fy);
607
	boxes[n].p2.x = traps.traps[n].right.p1.x;
417
    if (_cairo_clip_is_all_clipped (clip))
608
	boxes[n].p2.y = traps.traps[n].bottom;
418
	return clip;
609
    }
-
 
610
 
-
 
611
    _cairo_traps_clear (&traps);
-
 
612
    _cairo_traps_limit (&traps, boxes, n);
-
 
613
    status = _cairo_path_fixed_fill_to_traps (&clip_path->prev->path,
-
 
614
					      clip_path->prev->fill_rule,
-
 
615
					      clip_path->prev->tolerance,
-
 
616
					      &traps);
-
 
617
    if (boxes != stack_boxes)
-
 
618
	free (boxes);
-
 
619
 
-
 
620
    if (unlikely (status))
-
 
621
	return status;
-
 
622
 
-
 
623
    status = _cairo_traps_extract_region (&traps, &clip_path->region);
-
 
624
    _cairo_traps_fini (&traps);
-
 
625
 
-
 
626
    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-
 
627
	goto UNSUPPORTED;
-
 
628
    if (unlikely (status))
-
 
629
	return status;
-
 
630
 
-
 
631
    clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
-
 
632
    return CAIRO_STATUS_SUCCESS;
-
 
633
 
-
 
634
UNSUPPORTED:
-
 
635
    clip_path->flags |= CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED;
-
 
636
    return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
637
}
-
 
638
 
-
 
639
static cairo_int_status_t
-
 
640
_cairo_clip_path_to_region (cairo_clip_path_t *clip_path)
-
 
641
{
-
 
642
    cairo_int_status_t status;
-
 
643
    cairo_region_t *prev = NULL;
-
 
644
 
-
 
645
    if (clip_path->flags &
-
 
646
	(CAIRO_CLIP_PATH_HAS_REGION |
-
 
647
	 CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED))
-
 
648
    {
-
 
649
	return clip_path->flags & CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED ?
-
 
650
	    CAIRO_INT_STATUS_UNSUPPORTED :
-
 
651
	    CAIRO_STATUS_SUCCESS;
-
 
652
    }
-
 
653
 
-
 
654
    if (! clip_path->path.maybe_fill_region)
-
 
655
	return _cairo_clip_path_to_region_geometric (clip_path);
-
 
656
 
-
 
657
    /* first retrieve the region for our antecedents */
-
 
658
    if (clip_path->prev != NULL) {
-
 
659
	status = _cairo_clip_path_to_region (clip_path->prev);
-
 
660
	if (status) {
-
 
661
	    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
-
 
662
		return _cairo_clip_path_to_region_geometric (clip_path);
-
 
663
 
-
 
664
	    return status;
-
 
665
	}
-
 
666
 
-
 
667
	prev = clip_path->prev->region;
-
 
668
    }
-
 
669
 
-
 
670
    /* now extract the region for ourselves */
-
 
671
    clip_path->region =
-
 
672
	_cairo_path_fixed_fill_rectilinear_to_region (&clip_path->path,
-
 
673
						      clip_path->fill_rule,
-
 
674
						      &clip_path->extents);
-
 
675
    assert (clip_path->region != NULL);
-
 
676
 
-
 
677
    status = clip_path->region->status;
-
 
678
    if (unlikely (status))
-
 
679
	return status;
-
 
680
 
-
 
681
    if (prev != NULL) {
-
 
682
	status = cairo_region_intersect (clip_path->region, prev);
-
 
683
	if (unlikely (status))
-
 
684
	    return status;
-
 
685
    }
-
 
686
 
-
 
687
    clip_path->flags |= CAIRO_CLIP_PATH_HAS_REGION;
-
 
688
    return CAIRO_STATUS_SUCCESS;
-
 
689
}
-
 
690
 
-
 
691
static inline int
-
 
692
pot (int v)
-
 
693
{
-
 
694
    v--;
-
 
Line 695... Line 419...
695
    v |= v >> 1;
419
 
696
    v |= v >> 2;
420
    clip_path = _cairo_clip_path_create (clip);
Line 697... Line 421...
697
    v |= v >> 4;
421
    if (unlikely (clip_path == NULL))
698
    v |= v >> 8;
422
	return _cairo_clip_set_all_clipped (clip);
699
    v |= v >> 16;
-
 
700
    v++;
423
 
701
    return v;
-
 
702
}
-
 
703
 
424
    status = _cairo_path_fixed_init_copy (&clip_path->path,
704
/* XXX there is likely a faster method! ;-) */
-
 
705
static cairo_status_t
-
 
706
_region_clip_to_boxes (const cairo_region_t *region,
425
					  &other_path->path);
707
		       cairo_box_t **boxes,
-
 
708
		       int *num_boxes,
-
 
709
		       int *size_boxes)
-
 
710
{
-
 
711
    cairo_traps_t traps;
-
 
712
    cairo_status_t status;
-
 
713
    int n, num_rects;
-
 
714
 
-
 
715
    _cairo_traps_init (&traps);
-
 
716
    _cairo_traps_limit (&traps, *boxes, *num_boxes);
-
 
717
    traps.is_rectilinear = TRUE;
426
    if (unlikely (status))
718
    traps.is_rectangular = TRUE;
-
 
719
 
-
 
720
    num_rects = cairo_region_num_rectangles (region);
-
 
721
    for (n = 0; n < num_rects; n++) {
-
 
722
	cairo_rectangle_int_t rect;
-
 
723
	cairo_point_t p1, p2;
-
 
724
 
-
 
725
	cairo_region_get_rectangle (region, n, &rect);
-
 
726
 
-
 
727
	p1.x = _cairo_fixed_from_int (rect.x);
-
 
728
	p1.y = _cairo_fixed_from_int (rect.y);
-
 
729
	p2.x = _cairo_fixed_from_int (rect.x + rect.width);
-
 
730
	p2.y = _cairo_fixed_from_int (rect.y + rect.height);
-
 
731
 
-
 
732
	status = _cairo_traps_tessellate_rectangle (&traps, &p1, &p2);
-
 
733
	if (unlikely (status))
-
 
734
	    goto CLEANUP;
427
	return _cairo_clip_set_all_clipped (clip);
Line 735... Line -...
735
    }
-
 
736
 
428
 
737
    status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps, CAIRO_FILL_RULE_WINDING);
-
 
738
    if (unlikely (status))
-
 
739
	goto CLEANUP;
-
 
740
 
429
    _cairo_path_fixed_translate (&clip_path->path, fx, fy);
741
    n = *size_boxes;
-
 
742
    if (n < 0)
-
 
743
	n = -n;
-
 
744
 
-
 
745
    if (traps.num_traps > n) {
-
 
746
	cairo_box_t *new_boxes;
-
 
747
 
430
 
748
	new_boxes = _cairo_malloc_ab (traps.num_traps, sizeof (cairo_box_t));
-
 
749
	if (unlikely (new_boxes == NULL)) {
-
 
750
	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
751
	    goto CLEANUP;
-
 
752
	}
-
 
753
 
-
 
754
	if (*size_boxes > 0)
-
 
755
	    free (*boxes);
-
 
756
 
-
 
Line -... Line 431...
-
 
431
    clip_path->fill_rule = other_path->fill_rule;
757
	*boxes = new_boxes;
432
    clip_path->tolerance = other_path->tolerance;
758
	*size_boxes = traps.num_traps;
433
    clip_path->antialias = other_path->antialias;
759
    }
434
 
760
 
435
    return clip;
761
    for (n = 0; n < traps.num_traps; n++) {
436
}
762
	(*boxes)[n].p1.x = traps.traps[n].left.p1.x;
437
 
763
	(*boxes)[n].p1.y = traps.traps[n].top;
-
 
764
	(*boxes)[n].p2.x = traps.traps[n].right.p1.x;
438
cairo_clip_t *
765
	(*boxes)[n].p2.y = traps.traps[n].bottom;
439
_cairo_clip_translate (cairo_clip_t *clip, int tx, int ty)
Line 766... Line -...
766
    }
-
 
767
    *num_boxes = n;
-
 
768
 
-
 
769
  CLEANUP:
-
 
770
    _cairo_traps_fini (&traps);
440
{
771
 
441
    int fx, fy, i;
Line 772... Line 442...
772
    return status;
442
    cairo_clip_path_t *clip_path;
773
}
443
 
774
 
444
    if (clip == NULL || _cairo_clip_is_all_clipped (clip))
775
static cairo_status_t
445
	return clip;
776
_rectilinear_clip_to_boxes (const cairo_path_fixed_t *path,
446
 
777
			    cairo_fill_rule_t fill_rule,
-
 
778
			    cairo_box_t **boxes,
-
 
779
			    int *num_boxes,
447
    if (tx == 0 && ty == 0)
780
			    int *size_boxes)
-
 
781
{
-
 
782
    cairo_polygon_t polygon;
-
 
783
    cairo_traps_t traps;
-
 
784
    cairo_status_t status;
-
 
785
 
-
 
786
    _cairo_traps_init (&traps);
-
 
787
    _cairo_traps_limit (&traps, *boxes, *num_boxes);
-
 
788
 
-
 
789
    _cairo_polygon_init (&polygon);
-
 
790
    _cairo_polygon_limit (&polygon, *boxes, *num_boxes);
-
 
Line 791... Line 448...
791
 
448
	return clip;
792
    status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
-
 
793
							  fill_rule,
-
 
794
							  &traps);
449
 
795
    if (unlikely (_cairo_status_is_error (status)))
450
    fx = _cairo_fixed_from_int (tx);
-
 
451
    fy = _cairo_fixed_from_int (ty);
Line 796... Line 452...
796
	goto CLEANUP;
452
 
797
    if (status == CAIRO_STATUS_SUCCESS)
453
    for (i = 0; i < clip->num_boxes; i++) {
798
	goto BOXES;
-
 
799
 
-
 
800
    /* tolerance will be ignored as the path is rectilinear */
-
 
801
    status = _cairo_path_fixed_fill_to_polygon (path, 0., &polygon);
-
 
Line 802... Line -...
802
    if (unlikely (status))
-
 
803
	goto CLEANUP;
454
	clip->boxes[i].p1.x += fx;
804
 
-
 
Line 805... Line -...
805
    if (polygon.num_edges == 0) {
-
 
806
	*num_boxes = 0;
455
	clip->boxes[i].p2.x += fx;
807
    } else {
-
 
808
	status = _cairo_bentley_ottmann_tessellate_rectilinear_polygon (&traps,
-
 
809
									&polygon,
-
 
810
									fill_rule);
-
 
811
	if (likely (status == CAIRO_STATUS_SUCCESS)) {
-
 
812
	    int i;
456
	clip->boxes[i].p1.y += fy;
813
 
-
 
814
          BOXES:
457
	clip->boxes[i].p2.y += fy;
815
	    i = *size_boxes;
458
    }
816
	    if (i < 0)
-
 
817
		i = -i;
-
 
818
 
-
 
819
	    if (traps.num_traps > i) {
-
 
820
		cairo_box_t *new_boxes;
-
 
821
		int new_size;
-
 
822
 
-
 
823
		new_size = pot (traps.num_traps);
-
 
824
		new_boxes = _cairo_malloc_ab (new_size, sizeof (cairo_box_t));
-
 
825
		if (unlikely (new_boxes == NULL)) {
459
 
826
		    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
827
		    goto CLEANUP;
-
 
828
		}
-
 
829
 
-
 
830
		if (*size_boxes > 0)
460
    clip->extents.x += tx;
831
		    free (*boxes);
-
 
Line 832... Line -...
832
 
-
 
833
		*boxes = new_boxes;
461
    clip->extents.y += ty;
834
		*size_boxes = new_size;
-
 
-
 
462
 
Line 835... Line 463...
835
	    }
463
    if (clip->path == NULL)
836
 
-
 
837
	    for (i = 0; i < traps.num_traps; i++) {
464
	return clip;
-
 
465
 
838
		(*boxes)[i].p1.x = traps.traps[i].left.p1.x;
466
    clip_path = clip->path;
Line 839... Line 467...
839
		(*boxes)[i].p1.y = traps.traps[i].top;
467
    clip->path = NULL;
840
		(*boxes)[i].p2.x = traps.traps[i].right.p1.x;
468
    clip = _cairo_clip_path_copy_with_translation (clip, clip_path, fx, fy);
841
		(*boxes)[i].p2.y = traps.traps[i].bottom;
-
 
842
	    }
-
 
Line 843... Line 469...
843
	    *num_boxes = i;
469
    _cairo_clip_path_destroy (clip_path);
844
	}
470
 
845
    }
-
 
Line 846... Line -...
846
 
-
 
847
  CLEANUP:
-
 
848
    _cairo_polygon_fini (&polygon);
-
 
849
    _cairo_traps_fini (&traps);
-
 
850
 
-
 
851
    return status;
471
    return clip;
852
}
-
 
853
 
-
 
854
static cairo_int_status_t
-
 
Line 855... Line 472...
855
_cairo_clip_path_to_boxes (cairo_clip_path_t *clip_path,
472
}
856
			   cairo_box_t **boxes,
473
 
857
			   int *count)
-
 
-
 
474
static cairo_status_t
Line 858... Line -...
858
{
-
 
859
    int size = -*count;
475
_cairo_path_fixed_add_box (cairo_path_fixed_t *path,
860
    int num_boxes = 0;
-
 
861
    cairo_status_t status;
-
 
862
 
-
 
863
    if (clip_path->region != NULL) {
476
			   const cairo_box_t *box)
864
	int num_rects, n;
477
{
865
 
-
 
866
	num_rects = cairo_region_num_rectangles (clip_path->region);
-
 
867
	if (num_rects > -size) {
-
 
Line 868... Line -...
868
	    cairo_box_t *new_boxes;
-
 
869
 
-
 
870
	    new_boxes = _cairo_malloc_ab (num_rects, sizeof (cairo_box_t));
-
 
871
	    if (unlikely (new_boxes == NULL))
-
 
872
		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
873
 
-
 
874
	    *boxes = new_boxes;
-
 
875
	}
-
 
876
 
-
 
877
	for (n = 0; n < num_rects; n++) {
-
 
878
	    cairo_rectangle_int_t rect;
-
 
879
 
-
 
880
	    cairo_region_get_rectangle (clip_path->region, n, &rect);
-
 
881
	    (*boxes)[n].p1.x = _cairo_fixed_from_int (rect.x);
-
 
882
	    (*boxes)[n].p1.y = _cairo_fixed_from_int (rect.y);
-
 
883
	    (*boxes)[n].p2.x = _cairo_fixed_from_int (rect.x + rect.width);
-
 
884
	    (*boxes)[n].p2.y = _cairo_fixed_from_int (rect.y + rect.height);
-
 
885
	}
-
 
886
 
-
 
887
	*count = num_rects;
-
 
888
	return CAIRO_STATUS_SUCCESS;
-
 
889
    }
-
 
890
 
-
 
891
    /* keep it simple at first */
-
 
892
    if (! _clip_paths_are_rectilinear (clip_path))
-
 
893
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
894
 
-
 
895
    assert (-size >= 1);
-
 
896
    if (_cairo_path_fixed_is_box (&clip_path->path, *boxes)) {
-
 
897
	num_boxes = 1;
-
 
898
    } else {
-
 
899
	status = _rectilinear_clip_to_boxes (&clip_path->path,
-
 
900
					     clip_path->fill_rule,
478
    cairo_status_t status;
901
					     boxes, &num_boxes, &size);
479
 
902
	if (unlikely (status))
-
 
903
	    return status;
480
    status = _cairo_path_fixed_move_to (path, box->p1.x, box->p1.y);
904
    }
-
 
905
 
-
 
906
    while (num_boxes > 0 && (clip_path = clip_path->prev) != NULL) {
-
 
907
	cairo_box_t box;
-
 
908
 
-
 
909
	if (clip_path->region != NULL) {
-
 
910
	    status = _region_clip_to_boxes (clip_path->region,
481
    if (unlikely (status))
911
					    boxes, &num_boxes, &size);
-
 
912
	    if (unlikely (status))
-
 
913
		return status;
-
 
914
 
-
 
Line 915... Line -...
915
	    break;
-
 
916
	} else if (_cairo_path_fixed_is_box (&clip_path->path, &box)) {
482
	return status;
917
	    int i, j;
-
 
918
 
-
 
919
	    for (i = j = 0; i < num_boxes; i++) {
-
 
920
		if (j != i)
-
 
921
		    (*boxes)[j] = (*boxes)[i];
-
 
922
 
-
 
923
		if (box.p1.x > (*boxes)[j].p1.x)
-
 
924
		    (*boxes)[j].p1.x = box.p1.x;
-
 
925
		if (box.p2.x < (*boxes)[j].p2.x)
-
 
926
		    (*boxes)[j].p2.x = box.p2.x;
-
 
927
 
-
 
928
		if (box.p1.y > (*boxes)[j].p1.y)
-
 
929
		    (*boxes)[j].p1.y = box.p1.y;
-
 
930
		if (box.p2.y < (*boxes)[j].p2.y)
-
 
931
		    (*boxes)[j].p2.y = box.p2.y;
-
 
932
 
483
 
Line 933... Line 484...
933
		j += (*boxes)[j].p2.x > (*boxes)[j].p1.x &&
484
    status = _cairo_path_fixed_line_to (path, box->p2.x, box->p1.y);
934
		     (*boxes)[j].p2.y > (*boxes)[j].p1.y;
485
    if (unlikely (status))
935
	    }
-
 
Line 936... Line 486...
936
 
486
	return status;
937
	    num_boxes = j;
-
 
938
	} else {
-
 
939
	    status = _rectilinear_clip_to_boxes (&clip_path->path,
-
 
940
						 clip_path->fill_rule,
-
 
941
						 boxes, &num_boxes, &size);
-
 
942
	    if (unlikely (status))
-
 
943
		return status;
-
 
944
	}
-
 
945
    }
-
 
946
 
-
 
947
    *count = num_boxes;
487
 
948
    return CAIRO_STATUS_SUCCESS;
-
 
949
}
-
 
950
 
-
 
951
static cairo_surface_t *
-
 
952
_cairo_clip_path_get_surface (cairo_clip_path_t *clip_path,
-
 
953
			      cairo_surface_t *target,
-
 
954
			      int *tx, int *ty)
-
 
955
{
-
 
956
    const cairo_rectangle_int_t *clip_extents = &clip_path->extents;
-
 
957
    cairo_bool_t need_translate;
-
 
958
    cairo_surface_t *surface;
-
 
959
    cairo_clip_path_t *prev;
-
 
960
    cairo_status_t status;
-
 
961
 
-
 
962
    while (clip_path->prev != NULL &&
-
 
963
	   clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
-
 
964
	   clip_path->path.maybe_fill_region)
488
    status = _cairo_path_fixed_line_to (path, box->p2.x, box->p2.y);
Line 965... Line -...
965
    {
-
 
966
	clip_path = clip_path->prev;
489
    if (unlikely (status))
967
    }
-
 
968
 
-
 
-
 
490
	return status;
969
    clip_extents = &clip_path->extents;
491
 
970
    if (clip_path->surface != NULL &&
-
 
971
	clip_path->surface->backend == target->backend)
492
    status = _cairo_path_fixed_line_to (path, box->p1.x, box->p2.y);
972
    {
493
    if (unlikely (status))
Line 973... Line 494...
973
	*tx = clip_extents->x;
494
	return status;
974
	*ty = clip_extents->y;
-
 
975
	return clip_path->surface;
495
 
976
    }
-
 
Line 977... Line -...
977
 
-
 
978
    surface = _cairo_surface_create_similar_scratch (target,
-
 
979
						     CAIRO_CONTENT_ALPHA,
-
 
980
						     clip_extents->width,
-
 
981
						     clip_extents->height);
496
    return _cairo_path_fixed_close_path (path);
982
    if (surface == NULL) {
497
}
983
	surface = cairo_image_surface_create (CAIRO_FORMAT_A8,
-
 
984
					      clip_extents->width,
-
 
985
					      clip_extents->height);
-
 
986
    }
-
 
Line 987... Line 498...
987
    if (unlikely (surface->status))
498
 
988
	return surface;
499
static cairo_status_t
-
 
500
_cairo_path_fixed_init_from_boxes (cairo_path_fixed_t *path,
Line 989... Line 501...
989
 
501
				   const cairo_boxes_t *boxes)
990
    need_translate = clip_extents->x | clip_extents->y;
-
 
-
 
502
{
Line -... Line 503...
-
 
503
    cairo_status_t status;
-
 
504
    const struct _cairo_boxes_chunk *chunk;
991
    if (clip_path->flags & CAIRO_CLIP_PATH_IS_BOX &&
505
    int i;
-
 
506
 
-
 
507
    _cairo_path_fixed_init (path);
-
 
508
    if (boxes->num_boxes == 0)
-
 
509
	return CAIRO_STATUS_SUCCESS;
992
	clip_path->path.maybe_fill_region)
510
 
Line 993... Line -...
993
    {
-
 
994
	status = _cairo_surface_paint (surface,
511
    for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
995
				       CAIRO_OPERATOR_SOURCE,
512
	for (i = 0; i < chunk->count; i++) {
996
				       &_cairo_pattern_white.base,
513
	    status = _cairo_path_fixed_add_box (path, &chunk->base[i]);
997
				       NULL);
-
 
998
	if (unlikely (status))
-
 
999
	    goto BAIL;
514
	    if (unlikely (status)) {
1000
    }
515
		_cairo_path_fixed_fini (path);
1001
    else
516
		return status;
1002
    {
-
 
1003
	status = _cairo_surface_paint (surface,
-
 
1004
				       CAIRO_OPERATOR_CLEAR,
-
 
1005
				       &_cairo_pattern_clear.base,
-
 
1006
				       NULL);
-
 
1007
	if (unlikely (status))
-
 
1008
	    goto BAIL;
-
 
1009
 
-
 
1010
	if (need_translate) {
-
 
1011
	    _cairo_path_fixed_translate (&clip_path->path,
-
 
1012
					 _cairo_fixed_from_int (-clip_extents->x),
517
	    }
1013
					 _cairo_fixed_from_int (-clip_extents->y));
-
 
1014
	}
-
 
1015
	status = _cairo_surface_fill (surface,
-
 
1016
				      CAIRO_OPERATOR_ADD,
-
 
1017
				      &_cairo_pattern_white.base,
-
 
1018
				      &clip_path->path,
-
 
1019
				      clip_path->fill_rule,
518
	}
Line 1020... Line -...
1020
				      clip_path->tolerance,
-
 
1021
				      clip_path->antialias,
519
    }
1022
				      NULL);
-
 
1023
	if (need_translate) {
-
 
1024
	    _cairo_path_fixed_translate (&clip_path->path,
520
 
1025
					 _cairo_fixed_from_int (clip_extents->x),
-
 
1026
					 _cairo_fixed_from_int (clip_extents->y));
-
 
1027
	}
521
    return CAIRO_STATUS_SUCCESS;
Line 1028... Line -...
1028
 
-
 
1029
	if (unlikely (status))
522
}
1030
	    goto BAIL;
-
 
1031
    }
-
 
1032
 
-
 
1033
    prev = clip_path->prev;
523
 
1034
    while (prev != NULL) {
-
 
1035
	if (prev->flags & CAIRO_CLIP_PATH_IS_BOX &&
-
 
Line 1036... Line 524...
1036
	    prev->path.maybe_fill_region)
524
static cairo_clip_t *
1037
	{
525
_cairo_clip_intersect_clip_path_transformed (cairo_clip_t *clip,
Line 1038... Line 526...
1038
	    /* a simple box only affects the extents */
526
					     const cairo_clip_path_t *clip_path,
1039
	}
527
					     const cairo_matrix_t *m)
1040
	else if (prev->path.is_rectilinear ||
528
{
1041
		prev->surface == NULL ||
529
    cairo_path_fixed_t path;
1042
		prev->surface->backend != target->backend)
530
 
Line 1043... Line -...
1043
	{
-
 
1044
	    if (need_translate) {
-
 
1045
		_cairo_path_fixed_translate (&prev->path,
-
 
1046
					     _cairo_fixed_from_int (-clip_extents->x),
531
    if (clip_path->prev)
1047
					     _cairo_fixed_from_int (-clip_extents->y));
532
	clip = _cairo_clip_intersect_clip_path_transformed (clip,
1048
	    }
533
							    clip_path->prev,
Line 1049... Line 534...
1049
	    status = _cairo_surface_fill (surface,
534
							    m);
1050
					  CAIRO_OPERATOR_IN,
535
 
1051
					  &_cairo_pattern_white.base,
536
    if (_cairo_path_fixed_init_copy (&path, &clip_path->path))
1052
					  &prev->path,
537
	return _cairo_clip_set_all_clipped (clip);
Line 1053... Line 538...
1053
					  prev->fill_rule,
538
 
1054
					  prev->tolerance,
539
    _cairo_path_fixed_transform (&path, m);
1055
					  prev->antialias,
540
 
1056
					  NULL);
541
    clip =  _cairo_clip_intersect_path (clip,
Line 1057... Line 542...
1057
	    if (need_translate) {
542
				       &path,
1058
		_cairo_path_fixed_translate (&prev->path,
543
				       clip_path->fill_rule,
1059
					     _cairo_fixed_from_int (clip_extents->x),
544
				       clip_path->tolerance,
1060
					     _cairo_fixed_from_int (clip_extents->y));
545
				       clip_path->antialias);
Line 1061... Line -...
1061
	    }
-
 
1062
 
-
 
1063
	    if (unlikely (status))
-
 
1064
		goto BAIL;
-
 
1065
	}
-
 
1066
	else
546
    _cairo_path_fixed_fini (&path);
-
 
547
 
-
 
548
    return clip;
-
 
549
}
-
 
550
 
-
 
551
cairo_clip_t *
-
 
552
_cairo_clip_transform (cairo_clip_t *clip, const cairo_matrix_t *m)
-
 
553
{
-
 
554
    cairo_clip_t *copy;
-
 
555
 
-
 
556
    if (clip == NULL || _cairo_clip_is_all_clipped (clip))
-
 
557
	return clip;
-
 
558
 
-
 
559
    if (_cairo_matrix_is_translation (m))
Line 1067... Line 560...
1067
	{
560
	return _cairo_clip_translate (clip, m->x0, m->y0);
-
 
561
 
1068
	    cairo_surface_pattern_t pattern;
562
    copy = _cairo_clip_create ();
1069
	    cairo_surface_t *prev_surface;
563
 
1070
	    int prev_tx, prev_ty;
-
 
1071
 
-
 
1072
	    prev_surface = _cairo_clip_path_get_surface (prev, target, &prev_tx, &prev_ty);
564
    if (clip->num_boxes) {
1073
	    status = prev_surface->status;
565
	cairo_path_fixed_t path;
1074
	    if (unlikely (status))
566
	cairo_boxes_t boxes;
1075
		goto BAIL;
567
 
1076
 
568
	_cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
1077
	    _cairo_pattern_init_for_surface (&pattern, prev_surface);
569
	_cairo_path_fixed_init_from_boxes (&path, &boxes);
1078
	    pattern.base.filter = CAIRO_FILTER_NEAREST;
570
	_cairo_path_fixed_transform (&path, m);
1079
	    cairo_matrix_init_translate (&pattern.base.matrix,
-
 
1080
					 clip_extents->x - prev_tx,
-
 
1081
					 clip_extents->y - prev_ty);
-
 
1082
	    status = _cairo_surface_paint (surface,
-
 
1083
					   CAIRO_OPERATOR_IN,
-
 
1084
					   &pattern.base,
-
 
1085
					   NULL);
-
 
1086
	    _cairo_pattern_fini (&pattern.base);
-
 
1087
 
-
 
1088
	    if (unlikely (status))
-
 
1089
		goto BAIL;
-
 
1090
 
-
 
1091
	    break;
-
 
1092
	}
-
 
1093
 
-
 
1094
	prev = prev->prev;
-
 
1095
    }
-
 
1096
 
-
 
1097
    *tx = clip_extents->x;
-
 
1098
    *ty = clip_extents->y;
-
 
1099
    cairo_surface_destroy (clip_path->surface);
-
 
1100
    return clip_path->surface = surface;
-
 
1101
 
-
 
1102
  BAIL:
-
 
1103
    cairo_surface_destroy (surface);
-
 
1104
    return _cairo_surface_create_in_error (status);
-
 
1105
}
-
 
1106
 
-
 
1107
cairo_bool_t
-
 
1108
_cairo_clip_contains_rectangle (cairo_clip_t *clip,
-
 
1109
				const cairo_rectangle_int_t *rect)
-
 
1110
{
-
 
1111
    cairo_clip_path_t *clip_path;
-
 
1112
 
-
 
1113
    if (clip == NULL)
-
 
1114
	return FALSE;
-
 
1115
 
-
 
1116
    clip_path = clip->path;
-
 
1117
    if (clip_path->extents.x > rect->x ||
-
 
1118
	clip_path->extents.y > rect->y ||
-
 
1119
	clip_path->extents.x + clip_path->extents.width  < rect->x + rect->width ||
-
 
1120
	clip_path->extents.y + clip_path->extents.height < rect->y + rect->height)
-
 
1121
    {
-
 
1122
	return FALSE;
-
 
1123
    }
-
 
1124
 
-
 
1125
    do {
-
 
1126
	cairo_box_t box;
-
 
1127
 
-
 
1128
	if ((clip_path->flags & CAIRO_CLIP_PATH_IS_BOX) == 0)
-
 
1129
	    return FALSE;
-
 
1130
 
-
 
1131
	if (! _cairo_path_fixed_is_box (&clip_path->path, &box))
-
 
1132
	    return FALSE;
-
 
1133
 
-
 
1134
	if (box.p1.x > _cairo_fixed_from_int (rect->x) ||
-
 
1135
	    box.p1.y > _cairo_fixed_from_int (rect->y) ||
-
 
1136
	    box.p2.x < _cairo_fixed_from_int (rect->x + rect->width) ||
-
 
1137
	    box.p2.y < _cairo_fixed_from_int (rect->y + rect->height))
-
 
1138
	{
-
 
1139
	    return FALSE;
-
 
1140
	}
-
 
1141
    } while ((clip_path = clip_path->prev) != NULL);
-
 
1142
 
-
 
1143
    return TRUE;
-
 
1144
}
-
 
1145
 
-
 
1146
cairo_bool_t
-
 
1147
_cairo_clip_contains_extents (cairo_clip_t *clip,
-
 
1148
			      const cairo_composite_rectangles_t *extents)
-
 
1149
{
-
 
1150
    const cairo_rectangle_int_t *rect;
-
 
1151
 
571
 
Line 1152... Line -...
1152
    if (clip == NULL)
-
 
1153
	return FALSE;
-
 
1154
 
572
	copy = _cairo_clip_intersect_path (copy, &path,
1155
    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
573
					   CAIRO_FILL_RULE_WINDING,
1156
    return _cairo_clip_contains_rectangle (clip, rect);
574
					   0.1,
1157
}
575
					   CAIRO_ANTIALIAS_DEFAULT);
1158
 
576
 
1159
void
-
 
1160
_cairo_debug_print_clip (FILE *stream, cairo_clip_t *clip)
-
 
1161
{
-
 
1162
    cairo_clip_path_t *clip_path;
-
 
1163
 
-
 
1164
    if (clip == NULL) {
-
 
1165
	fprintf (stream, "no clip\n");
-
 
1166
	return;
-
 
1167
    }
-
 
1168
 
-
 
1169
    if (clip->all_clipped) {
-
 
1170
	fprintf (stream, "clip: all-clipped\n");
-
 
1171
	return;
-
 
1172
    }
-
 
Line 1173... Line -...
1173
 
-
 
1174
    if (clip->path == NULL) {
-
 
1175
	fprintf (stream, "clip: empty\n");
-
 
1176
	return;
577
	_cairo_path_fixed_fini (&path);
1177
    }
578
    }
1178
 
-
 
Line 1179... Line -...
1179
    fprintf (stream, "clip:\n");
-
 
1180
 
-
 
1181
    clip_path = clip->path;
579
 
1182
    do {
-
 
1183
	fprintf (stream, "path: has region? %s, has surface? %s, aa=%d, tolerance=%f, rule=%d: ",
-
 
1184
		 clip_path->region == NULL ? "no" : "yes",
-
 
1185
		 clip_path->surface == NULL ? "no" : "yes",
-
 
1186
		 clip_path->antialias,
580
    if (clip->path)
Line 1187... Line 581...
1187
		 clip_path->tolerance,
581
	copy = _cairo_clip_intersect_clip_path_transformed (copy, clip->path,m);
1188
		 clip_path->fill_rule);
582
 
1189
	_cairo_debug_print_path (stream, &clip_path->path);
583
    _cairo_clip_destroy (clip);
Line 1329... Line 723...
1329
    user_rect->height = y2 - y1;
723
    user_rect->height = y2 - y1;
Line 1330... Line 724...
1330
 
724
 
1331
    return is_tight;
725
    return is_tight;
Line 1332... Line -...
1332
}
-
 
1333
 
-
 
1334
cairo_int_status_t
-
 
1335
_cairo_clip_get_region (cairo_clip_t *clip,
-
 
1336
			cairo_region_t **region)
-
 
1337
{
-
 
1338
    cairo_int_status_t status;
-
 
1339
 
-
 
1340
    if (clip->all_clipped)
-
 
1341
	goto CLIPPED;
-
 
1342
 
-
 
1343
    assert (clip->path != NULL);
-
 
1344
 
-
 
1345
    status = _cairo_clip_path_to_region (clip->path);
-
 
1346
    if (status)
-
 
1347
	return status;
-
 
1348
 
-
 
1349
    if (cairo_region_is_empty (clip->path->region)) {
-
 
1350
	_cairo_clip_set_all_clipped (clip);
-
 
1351
	goto CLIPPED;
-
 
1352
    }
-
 
1353
 
-
 
1354
    if (region)
-
 
1355
	*region = clip->path->region;
-
 
1356
    return CAIRO_STATUS_SUCCESS;
-
 
1357
 
-
 
1358
  CLIPPED:
-
 
1359
    if (region)
-
 
1360
	*region = NULL;
-
 
1361
    return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
 
1362
}
-
 
1363
 
-
 
1364
cairo_int_status_t
-
 
1365
_cairo_clip_get_boxes (cairo_clip_t *clip,
-
 
1366
		       cairo_box_t **boxes,
-
 
1367
		       int *count)
-
 
1368
{
-
 
1369
    cairo_int_status_t status;
-
 
1370
 
-
 
1371
    if (clip->all_clipped)
-
 
1372
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
 
1373
 
-
 
1374
    assert (clip->path != NULL);
-
 
1375
 
-
 
1376
    status = _cairo_clip_path_to_boxes (clip->path, boxes, count);
-
 
1377
    if (status)
-
 
1378
	return status;
-
 
1379
 
-
 
1380
    if (*count == 0) {
-
 
1381
	_cairo_clip_set_all_clipped (clip);
-
 
1382
	return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
 
1383
    }
-
 
1384
 
-
 
1385
    return CAIRO_STATUS_SUCCESS;
-
 
1386
}
-
 
1387
 
-
 
1388
static cairo_bool_t
-
 
1389
box_is_aligned (const cairo_box_t *box)
-
 
1390
{
-
 
1391
    return
-
 
1392
	_cairo_fixed_is_integer (box->p1.x) &&
-
 
1393
	_cairo_fixed_is_integer (box->p1.y) &&
-
 
1394
	_cairo_fixed_is_integer (box->p2.x) &&
-
 
1395
	_cairo_fixed_is_integer (box->p2.y);
-
 
1396
}
-
 
1397
 
-
 
1398
static void
-
 
1399
intersect_with_boxes (cairo_composite_rectangles_t *extents,
-
 
1400
		      cairo_box_t *boxes,
-
 
1401
		      int num_boxes)
-
 
1402
{
-
 
1403
    cairo_rectangle_int_t rect;
-
 
1404
    cairo_box_t box;
-
 
1405
    cairo_bool_t is_empty;
-
 
1406
 
-
 
1407
    box.p1.x = box.p1.y = INT_MIN;
-
 
1408
    box.p2.x = box.p2.y = INT_MAX;
-
 
1409
    while (num_boxes--) {
-
 
1410
	if (boxes->p1.x < box.p1.x)
-
 
1411
	    box.p1.x = boxes->p1.x;
-
 
1412
	if (boxes->p1.y < box.p1.y)
-
 
1413
	    box.p1.y = boxes->p1.y;
-
 
1414
 
-
 
1415
	if (boxes->p2.x > box.p2.x)
-
 
1416
	    box.p2.x = boxes->p2.x;
-
 
1417
	if (boxes->p2.y > box.p2.y)
-
 
1418
	    box.p2.y = boxes->p2.y;
-
 
1419
    }
-
 
1420
 
-
 
1421
    _cairo_box_round_to_rectangle (&box, &rect);
-
 
1422
    is_empty = _cairo_rectangle_intersect (&extents->bounded, &rect);
-
 
1423
    is_empty = _cairo_rectangle_intersect (&extents->unbounded, &rect);
-
 
1424
}
-
 
1425
 
-
 
1426
cairo_status_t
-
 
1427
_cairo_clip_to_boxes (cairo_clip_t **clip,
-
 
1428
		      cairo_composite_rectangles_t *extents,
-
 
1429
		      cairo_box_t **boxes,
-
 
1430
		      int *num_boxes)
-
 
1431
{
-
 
1432
    cairo_status_t status;
-
 
1433
    const cairo_rectangle_int_t *rect;
-
 
1434
 
-
 
1435
    rect = extents->is_bounded ? &extents->bounded : &extents->unbounded;
-
 
1436
 
-
 
1437
    if (*clip == NULL)
-
 
1438
	goto EXTENTS;
-
 
1439
 
-
 
1440
    status = _cairo_clip_rectangle (*clip, rect);
-
 
1441
    if (unlikely (status))
-
 
1442
	return status;
-
 
1443
 
-
 
1444
    status = _cairo_clip_get_boxes (*clip, boxes, num_boxes);
-
 
1445
    switch ((int) status) {
-
 
1446
    case CAIRO_STATUS_SUCCESS:
-
 
1447
	intersect_with_boxes (extents, *boxes, *num_boxes);
-
 
1448
	if (rect->width == 0 || rect->height == 0 ||
-
 
1449
	    extents->is_bounded ||
-
 
1450
	    (*num_boxes == 1 && box_is_aligned (*boxes)))
-
 
1451
	{
-
 
1452
	    *clip = NULL;
-
 
1453
	}
-
 
1454
	goto DONE;
-
 
1455
 
-
 
1456
    case CAIRO_INT_STATUS_UNSUPPORTED:
-
 
1457
	goto EXTENTS;
-
 
1458
 
-
 
1459
    default:
-
 
1460
	return status;
-
 
1461
    }
-
 
1462
 
-
 
1463
  EXTENTS:
-
 
1464
    status = CAIRO_STATUS_SUCCESS;
-
 
1465
    _cairo_box_from_rectangle (&(*boxes)[0], rect);
-
 
1466
    *num_boxes = 1;
-
 
1467
  DONE:
-
 
1468
    return status;
-
 
1469
}
-
 
1470
 
726
}
1471
 
727
 
1472
static cairo_rectangle_list_t *
728
cairo_rectangle_list_t *
1473
_cairo_rectangle_list_create_in_error (cairo_status_t status)
729
_cairo_rectangle_list_create_in_error (cairo_status_t status)
Line 1474... Line 730...
1474
{
730
{
Line 1479... Line 735...
1479
    if (status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
735
    if (status == CAIRO_STATUS_CLIP_NOT_REPRESENTABLE)
1480
	return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
736
	return (cairo_rectangle_list_t*) &_cairo_rectangles_not_representable;
Line 1481... Line 737...
1481
 
737
 
1482
    list = malloc (sizeof (*list));
738
    list = malloc (sizeof (*list));
1483
    if (unlikely (list == NULL)) {
739
    if (unlikely (list == NULL)) {
1484
	_cairo_error_throw (status);
740
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1485
	return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
741
	return (cairo_rectangle_list_t*) &_cairo_rectangles_nil;
Line 1486... Line 742...
1486
    }
742
    }
1487
 
743
 
Line 1498... Line 754...
1498
#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S))
754
#define ERROR_LIST(S) _cairo_rectangle_list_create_in_error (_cairo_error (S))
Line 1499... Line 755...
1499
 
755
 
1500
    cairo_rectangle_list_t *list;
756
    cairo_rectangle_list_t *list;
1501
    cairo_rectangle_t *rectangles = NULL;
757
    cairo_rectangle_t *rectangles = NULL;
1502
    cairo_region_t *region = NULL;
-
 
1503
    cairo_int_status_t status;
758
    cairo_region_t *region = NULL;
1504
    int n_rects = 0;
759
    int n_rects = 0;
Line 1505... Line -...
1505
    int i;
-
 
1506
 
-
 
1507
    if (clip->all_clipped)
-
 
1508
	goto DONE;
760
    int i;
1509
 
761
 
Line 1510... Line 762...
1510
    if (!clip->path)
762
    if (clip == NULL)
1511
	return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
-
 
1512
 
763
	return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
-
 
764
 
1513
    status = _cairo_clip_get_region (clip, ®ion);
765
    if (_cairo_clip_is_all_clipped (clip))
1514
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
766
	goto DONE;
-
 
767
 
-
 
768
    if (! _cairo_clip_is_region (clip))
1515
	goto DONE;
769
	return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
1516
    } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
770
 
1517
	return ERROR_LIST (CAIRO_STATUS_CLIP_NOT_REPRESENTABLE);
-
 
Line 1518... Line 771...
1518
    } else if (unlikely (status)) {
771
    region = _cairo_clip_get_region (clip);
1519
	return ERROR_LIST (status);
772
    if (region == NULL)
1520
    }
773
	return ERROR_LIST (CAIRO_STATUS_NO_MEMORY);
1521
 
774
 
Line 1556... Line 809...
1556
#undef ERROR_LIST
809
#undef ERROR_LIST
1557
}
810
}
Line 1558... Line 811...
1558
 
811
 
1559
/**
812
/**
1560
 * cairo_rectangle_list_destroy:
813
 * cairo_rectangle_list_destroy:
1561
 * @rectangle_list: a rectangle list, as obtained from cairo_copy_clip_rectangles()
814
 * @rectangle_list: a rectangle list, as obtained from cairo_copy_clip_rectangle_list()
1562
 *
815
 *
1563
 * Unconditionally frees @rectangle_list and all associated
816
 * Unconditionally frees @rectangle_list and all associated
1564
 * references. After this call, the @rectangle_list pointer must not
817
 * references. After this call, the @rectangle_list pointer must not
1565
 * be dereferenced.
818
 * be dereferenced.
Line 1579... Line 832...
1579
 
832
 
1580
void
833
void
1581
_cairo_clip_reset_static_data (void)
834
_cairo_clip_reset_static_data (void)
1582
{
835
{
-
 
836
    _freed_pool_reset (&clip_path_pool);
1583
    _freed_pool_reset (&clip_path_pool);
837
    _freed_pool_reset (&clip_pool);