~reviczky/luatex/texlive-bin-git

« back to all changes in this revision

Viewing changes to libs/cairo/cairo-1.12.16/src/cairo-spans-compositor.c

  • Committer: Adam Reviczky
  • Date: 2015-04-26 22:40:47 UTC
  • Revision ID: adam.reviczky@kclalumni.net-20150426224047-i2p26n3wqphupq6z
TeX Live 2015 import (rev. 37052)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
 
/* cairo - a vector graphics library with display and print output
3
 
 *
4
 
 * Copyright © 2002 University of Southern California
5
 
 * Copyright © 2005 Red Hat, Inc.
6
 
 * Copyright © 2011 Intel Corporation
7
 
 *
8
 
 * This library is free software; you can redistribute it and/or
9
 
 * modify it either under the terms of the GNU Lesser General Public
10
 
 * License version 2.1 as published by the Free Software Foundation
11
 
 * (the "LGPL") or, at your option, under the terms of the Mozilla
12
 
 * Public License Version 1.1 (the "MPL"). If you do not alter this
13
 
 * notice, a recipient may use your version of this file under either
14
 
 * the MPL or the LGPL.
15
 
 *
16
 
 * You should have received a copy of the LGPL along with this library
17
 
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18
 
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
19
 
 * You should have received a copy of the MPL along with this library
20
 
 * in the file COPYING-MPL-1.1
21
 
 *
22
 
 * The contents of this file are subject to the Mozilla Public License
23
 
 * Version 1.1 (the "License"); you may not use this file except in
24
 
 * compliance with the License. You may obtain a copy of the License at
25
 
 * http://www.mozilla.org/MPL/
26
 
 *
27
 
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
28
 
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
29
 
 * the specific language governing rights and limitations.
30
 
 *
31
 
 * The Original Code is the cairo graphics library.
32
 
 *
33
 
 * The Initial Developer of the Original Code is University of Southern
34
 
 * California.
35
 
 *
36
 
 * Contributor(s):
37
 
 *      Carl D. Worth <cworth@cworth.org>
38
 
 *      Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
39
 
 *      Chris Wilson <chris@chris-wilson.co.uk>
40
 
 */
41
 
 
42
 
#include "cairoint.h"
43
 
 
44
 
#include "cairo-compositor-private.h"
45
 
#include "cairo-clip-inline.h"
46
 
#include "cairo-clip-private.h"
47
 
#include "cairo-image-surface-private.h"
48
 
#include "cairo-paginated-private.h"
49
 
#include "cairo-pattern-inline.h"
50
 
#include "cairo-region-private.h"
51
 
#include "cairo-recording-surface-inline.h"
52
 
#include "cairo-spans-compositor-private.h"
53
 
#include "cairo-surface-subsurface-private.h"
54
 
#include "cairo-surface-snapshot-private.h"
55
 
#include "cairo-surface-observer-private.h"
56
 
 
57
 
typedef struct {
58
 
    cairo_polygon_t     *polygon;
59
 
    cairo_fill_rule_t    fill_rule;
60
 
    cairo_antialias_t    antialias;
61
 
} composite_spans_info_t;
62
 
 
63
 
static cairo_int_status_t
64
 
composite_polygon (const cairo_spans_compositor_t       *compositor,
65
 
                   cairo_composite_rectangles_t          *extents,
66
 
                   cairo_polygon_t                      *polygon,
67
 
                   cairo_fill_rule_t                     fill_rule,
68
 
                   cairo_antialias_t                     antialias);
69
 
 
70
 
static cairo_int_status_t
71
 
composite_boxes (const cairo_spans_compositor_t *compositor,
72
 
                 cairo_composite_rectangles_t *extents,
73
 
                 cairo_boxes_t          *boxes);
74
 
 
75
 
static cairo_int_status_t
76
 
clip_and_composite_polygon (const cairo_spans_compositor_t      *compositor,
77
 
                            cairo_composite_rectangles_t         *extents,
78
 
                            cairo_polygon_t                     *polygon,
79
 
                            cairo_fill_rule_t                    fill_rule,
80
 
                            cairo_antialias_t                    antialias);
81
 
static cairo_surface_t *
82
 
get_clip_surface (const cairo_spans_compositor_t *compositor,
83
 
                  cairo_surface_t *dst,
84
 
                  const cairo_clip_t *clip,
85
 
                  const cairo_rectangle_int_t *extents)
86
 
{
87
 
    cairo_composite_rectangles_t composite;
88
 
    cairo_surface_t *surface;
89
 
    cairo_box_t box;
90
 
    cairo_polygon_t polygon;
91
 
    const cairo_clip_path_t *clip_path;
92
 
    cairo_antialias_t antialias;
93
 
    cairo_fill_rule_t fill_rule;
94
 
    cairo_int_status_t status;
95
 
 
96
 
    assert (clip->path);
97
 
 
98
 
    surface = _cairo_surface_create_similar_solid (dst,
99
 
                                                   CAIRO_CONTENT_ALPHA,
100
 
                                                   extents->width,
101
 
                                                   extents->height,
102
 
                                                   CAIRO_COLOR_TRANSPARENT);
103
 
 
104
 
    _cairo_box_from_rectangle (&box, extents);
105
 
    _cairo_polygon_init (&polygon, &box, 1);
106
 
 
107
 
    clip_path = clip->path;
108
 
    status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
109
 
                                                clip_path->tolerance,
110
 
                                                &polygon);
111
 
    if (unlikely (status))
112
 
        goto cleanup_polygon;
113
 
 
114
 
    polygon.num_limits = 0;
115
 
 
116
 
    antialias = clip_path->antialias;
117
 
    fill_rule = clip_path->fill_rule;
118
 
 
119
 
    if (clip->boxes) {
120
 
        cairo_polygon_t intersect;
121
 
        cairo_boxes_t tmp;
122
 
 
123
 
        _cairo_boxes_init_for_array (&tmp, clip->boxes, clip->num_boxes);
124
 
        status= _cairo_polygon_init_boxes (&intersect, &tmp);
125
 
        if (unlikely (status))
126
 
            goto cleanup_polygon;
127
 
 
128
 
        status = _cairo_polygon_intersect (&polygon, fill_rule,
129
 
                                           &intersect, CAIRO_FILL_RULE_WINDING);
130
 
        _cairo_polygon_fini (&intersect);
131
 
 
132
 
        if (unlikely (status))
133
 
            goto cleanup_polygon;
134
 
 
135
 
        fill_rule = CAIRO_FILL_RULE_WINDING;
136
 
    }
137
 
 
138
 
    polygon.limits = NULL;
139
 
    polygon.num_limits = 0;
140
 
 
141
 
    clip_path = clip_path->prev;
142
 
    while (clip_path) {
143
 
        if (clip_path->antialias == antialias) {
144
 
            cairo_polygon_t next;
145
 
 
146
 
            _cairo_polygon_init (&next, NULL, 0);
147
 
            status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
148
 
                                                        clip_path->tolerance,
149
 
                                                        &next);
150
 
            if (likely (status == CAIRO_INT_STATUS_SUCCESS))
151
 
                status = _cairo_polygon_intersect (&polygon, fill_rule,
152
 
                                                   &next, clip_path->fill_rule);
153
 
            _cairo_polygon_fini (&next);
154
 
            if (unlikely (status))
155
 
                goto cleanup_polygon;
156
 
 
157
 
            fill_rule = CAIRO_FILL_RULE_WINDING;
158
 
        }
159
 
 
160
 
        clip_path = clip_path->prev;
161
 
    }
162
 
 
163
 
    _cairo_polygon_translate (&polygon, -extents->x, -extents->y);
164
 
    status = _cairo_composite_rectangles_init_for_polygon (&composite, surface,
165
 
                                                           CAIRO_OPERATOR_ADD,
166
 
                                                           &_cairo_pattern_white.base,
167
 
                                                           &polygon,
168
 
                                                           NULL);
169
 
    if (unlikely (status))
170
 
        goto cleanup_polygon;
171
 
 
172
 
    status = composite_polygon (compositor, &composite,
173
 
                                &polygon, fill_rule, antialias);
174
 
    _cairo_composite_rectangles_fini (&composite);
175
 
    _cairo_polygon_fini (&polygon);
176
 
    if (unlikely (status))
177
 
        goto error;
178
 
 
179
 
    _cairo_polygon_init (&polygon, &box, 1);
180
 
 
181
 
    clip_path = clip->path;
182
 
    antialias = clip_path->antialias == CAIRO_ANTIALIAS_DEFAULT ? CAIRO_ANTIALIAS_NONE : CAIRO_ANTIALIAS_DEFAULT;
183
 
    clip_path = clip_path->prev;
184
 
    while (clip_path) {
185
 
        if (clip_path->antialias == antialias) {
186
 
            if (polygon.num_edges == 0) {
187
 
                status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
188
 
                                                            clip_path->tolerance,
189
 
                                                            &polygon);
190
 
 
191
 
                fill_rule = clip_path->fill_rule;
192
 
                polygon.limits = NULL;
193
 
                polygon.num_limits = 0;
194
 
            } else {
195
 
                cairo_polygon_t next;
196
 
 
197
 
                _cairo_polygon_init (&next, NULL, 0);
198
 
                status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
199
 
                                                            clip_path->tolerance,
200
 
                                                            &next);
201
 
                if (likely (status == CAIRO_INT_STATUS_SUCCESS))
202
 
                    status = _cairo_polygon_intersect (&polygon, fill_rule,
203
 
                                                       &next, clip_path->fill_rule);
204
 
                _cairo_polygon_fini (&next);
205
 
                fill_rule = CAIRO_FILL_RULE_WINDING;
206
 
            }
207
 
            if (unlikely (status))
208
 
                goto error;
209
 
        }
210
 
 
211
 
        clip_path = clip_path->prev;
212
 
    }
213
 
 
214
 
    if (polygon.num_edges) {
215
 
        _cairo_polygon_translate (&polygon, -extents->x, -extents->y);
216
 
        status = _cairo_composite_rectangles_init_for_polygon (&composite, surface,
217
 
                                                               CAIRO_OPERATOR_IN,
218
 
                                                               &_cairo_pattern_white.base,
219
 
                                                               &polygon,
220
 
                                                               NULL);
221
 
        if (unlikely (status))
222
 
            goto cleanup_polygon;
223
 
 
224
 
        status = composite_polygon (compositor, &composite,
225
 
                                    &polygon, fill_rule, antialias);
226
 
        _cairo_composite_rectangles_fini (&composite);
227
 
        _cairo_polygon_fini (&polygon);
228
 
        if (unlikely (status))
229
 
            goto error;
230
 
    }
231
 
 
232
 
    return surface;
233
 
 
234
 
cleanup_polygon:
235
 
    _cairo_polygon_fini (&polygon);
236
 
error:
237
 
    cairo_surface_destroy (surface);
238
 
    return _cairo_int_surface_create_in_error (status);
239
 
}
240
 
 
241
 
static cairo_int_status_t
242
 
fixup_unbounded_mask (const cairo_spans_compositor_t *compositor,
243
 
                      const cairo_composite_rectangles_t *extents,
244
 
                      cairo_boxes_t *boxes)
245
 
{
246
 
    cairo_composite_rectangles_t composite;
247
 
    cairo_surface_t *clip;
248
 
    cairo_int_status_t status;
249
 
 
250
 
    TRACE((stderr, "%s\n", __FUNCTION__));
251
 
 
252
 
    clip = get_clip_surface (compositor, extents->surface, extents->clip,
253
 
                             &extents->unbounded);
254
 
    if (unlikely (clip->status)) {
255
 
        if ((cairo_int_status_t)clip->status == CAIRO_INT_STATUS_NOTHING_TO_DO)
256
 
            return CAIRO_STATUS_SUCCESS;
257
 
 
258
 
        return clip->status;
259
 
    }
260
 
 
261
 
    status = _cairo_composite_rectangles_init_for_boxes (&composite,
262
 
                                                         extents->surface,
263
 
                                                         CAIRO_OPERATOR_CLEAR,
264
 
                                                         &_cairo_pattern_clear.base,
265
 
                                                         boxes,
266
 
                                                         NULL);
267
 
    if (unlikely (status))
268
 
        goto cleanup_clip;
269
 
 
270
 
    _cairo_pattern_init_for_surface (&composite.mask_pattern.surface, clip);
271
 
    composite.mask_pattern.base.filter = CAIRO_FILTER_NEAREST;
272
 
    composite.mask_pattern.base.extend = CAIRO_EXTEND_NONE;
273
 
 
274
 
    status = composite_boxes (compositor, &composite, boxes);
275
 
 
276
 
    _cairo_pattern_fini (&composite.mask_pattern.base);
277
 
    _cairo_composite_rectangles_fini (&composite);
278
 
 
279
 
cleanup_clip:
280
 
    cairo_surface_destroy (clip);
281
 
    return status;
282
 
}
283
 
 
284
 
static cairo_int_status_t
285
 
fixup_unbounded_polygon (const cairo_spans_compositor_t *compositor,
286
 
                         const cairo_composite_rectangles_t *extents,
287
 
                         cairo_boxes_t *boxes)
288
 
{
289
 
    cairo_polygon_t polygon, intersect;
290
 
    cairo_composite_rectangles_t composite;
291
 
    cairo_fill_rule_t fill_rule;
292
 
    cairo_antialias_t antialias;
293
 
    cairo_int_status_t status;
294
 
 
295
 
    TRACE((stderr, "%s\n", __FUNCTION__));
296
 
 
297
 
    /* Can we treat the clip as a regular clear-polygon and use it to fill? */
298
 
    status = _cairo_clip_get_polygon (extents->clip, &polygon,
299
 
                                      &fill_rule, &antialias);
300
 
    if (status == CAIRO_INT_STATUS_UNSUPPORTED)
301
 
        return status;
302
 
 
303
 
    status= _cairo_polygon_init_boxes (&intersect, boxes);
304
 
    if (unlikely (status))
305
 
        goto cleanup_polygon;
306
 
 
307
 
    status = _cairo_polygon_intersect (&polygon, fill_rule,
308
 
                                       &intersect, CAIRO_FILL_RULE_WINDING);
309
 
    _cairo_polygon_fini (&intersect);
310
 
 
311
 
    if (unlikely (status))
312
 
        goto cleanup_polygon;
313
 
 
314
 
    status = _cairo_composite_rectangles_init_for_polygon (&composite,
315
 
                                                           extents->surface,
316
 
                                                           CAIRO_OPERATOR_CLEAR,
317
 
                                                           &_cairo_pattern_clear.base,
318
 
                                                           &polygon,
319
 
                                                           NULL);
320
 
    if (unlikely (status))
321
 
        goto cleanup_polygon;
322
 
 
323
 
    status = composite_polygon (compositor, &composite,
324
 
                                &polygon, fill_rule, antialias);
325
 
 
326
 
    _cairo_composite_rectangles_fini (&composite);
327
 
cleanup_polygon:
328
 
    _cairo_polygon_fini (&polygon);
329
 
 
330
 
    return status;
331
 
}
332
 
 
333
 
static cairo_int_status_t
334
 
fixup_unbounded_boxes (const cairo_spans_compositor_t *compositor,
335
 
                       const cairo_composite_rectangles_t *extents,
336
 
                       cairo_boxes_t *boxes)
337
 
{
338
 
    cairo_boxes_t tmp, clear;
339
 
    cairo_box_t box;
340
 
    cairo_int_status_t status;
341
 
 
342
 
    assert (boxes->is_pixel_aligned);
343
 
 
344
 
    TRACE ((stderr, "%s\n", __FUNCTION__));
345
 
    if (extents->bounded.width  == extents->unbounded.width &&
346
 
        extents->bounded.height == extents->unbounded.height)
347
 
    {
348
 
        return CAIRO_STATUS_SUCCESS;
349
 
    }
350
 
 
351
 
    /* subtract the drawn boxes from the unbounded area */
352
 
    _cairo_boxes_init (&clear);
353
 
 
354
 
    box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
355
 
    box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
356
 
    box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
357
 
    box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
358
 
 
359
 
    if (boxes->num_boxes) {
360
 
        _cairo_boxes_init (&tmp);
361
 
 
362
 
        status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
363
 
        assert (status == CAIRO_INT_STATUS_SUCCESS);
364
 
 
365
 
        tmp.chunks.next = &boxes->chunks;
366
 
        tmp.num_boxes += boxes->num_boxes;
367
 
 
368
 
        status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
369
 
                                                          CAIRO_FILL_RULE_WINDING,
370
 
                                                          &clear);
371
 
        tmp.chunks.next = NULL;
372
 
        if (unlikely (status))
373
 
            goto error;
374
 
    } else {
375
 
        box.p1.x = _cairo_fixed_from_int (extents->unbounded.x);
376
 
        box.p2.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
377
 
 
378
 
        status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
379
 
        assert (status == CAIRO_INT_STATUS_SUCCESS);
380
 
    }
381
 
 
382
 
    /* If we have a clip polygon, we need to intersect with that as well */
383
 
    if (extents->clip->path) {
384
 
        status = fixup_unbounded_polygon (compositor, extents, &clear);
385
 
        if (status == CAIRO_INT_STATUS_UNSUPPORTED)
386
 
            status = fixup_unbounded_mask (compositor, extents, &clear);
387
 
    } else {
388
 
        /* Otherwise just intersect with the clip boxes */
389
 
        if (extents->clip->num_boxes) {
390
 
            _cairo_boxes_init_for_array (&tmp,
391
 
                                         extents->clip->boxes,
392
 
                                         extents->clip->num_boxes);
393
 
            status = _cairo_boxes_intersect (&clear, &tmp, &clear);
394
 
            if (unlikely (status))
395
 
                goto error;
396
 
        }
397
 
 
398
 
        if (clear.is_pixel_aligned) {
399
 
            status = compositor->fill_boxes (extents->surface,
400
 
                                             CAIRO_OPERATOR_CLEAR,
401
 
                                             CAIRO_COLOR_TRANSPARENT,
402
 
                                             &clear);
403
 
        } else {
404
 
            cairo_composite_rectangles_t composite;
405
 
 
406
 
            status = _cairo_composite_rectangles_init_for_boxes (&composite,
407
 
                                                                 extents->surface,
408
 
                                                                 CAIRO_OPERATOR_CLEAR,
409
 
                                                                 &_cairo_pattern_clear.base,
410
 
                                                                 &clear,
411
 
                                                                 NULL);
412
 
            if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
413
 
                status = composite_boxes (compositor, &composite, &clear);
414
 
                _cairo_composite_rectangles_fini (&composite);
415
 
            }
416
 
        }
417
 
    }
418
 
 
419
 
error:
420
 
    _cairo_boxes_fini (&clear);
421
 
    return status;
422
 
}
423
 
 
424
 
static cairo_surface_t *
425
 
unwrap_source (const cairo_pattern_t *pattern)
426
 
{
427
 
    cairo_rectangle_int_t limit;
428
 
 
429
 
    return _cairo_pattern_get_source ((cairo_surface_pattern_t *)pattern,
430
 
                                      &limit);
431
 
}
432
 
 
433
 
static cairo_bool_t
434
 
is_recording_pattern (const cairo_pattern_t *pattern)
435
 
{
436
 
    cairo_surface_t *surface;
437
 
 
438
 
    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
439
 
        return FALSE;
440
 
 
441
 
    surface = ((const cairo_surface_pattern_t *) pattern)->surface;
442
 
    return _cairo_surface_is_recording (surface);
443
 
}
444
 
 
445
 
static cairo_bool_t
446
 
recording_pattern_contains_sample (const cairo_pattern_t *pattern,
447
 
                                   const cairo_rectangle_int_t *sample)
448
 
{
449
 
    cairo_recording_surface_t *surface;
450
 
 
451
 
    if (! is_recording_pattern (pattern))
452
 
        return FALSE;
453
 
 
454
 
    if (pattern->extend == CAIRO_EXTEND_NONE)
455
 
        return TRUE;
456
 
 
457
 
    surface = (cairo_recording_surface_t *) unwrap_source (pattern);
458
 
    if (surface->unbounded)
459
 
        return TRUE;
460
 
 
461
 
    return _cairo_rectangle_contains_rectangle (&surface->extents, sample);
462
 
}
463
 
 
464
 
static cairo_bool_t
465
 
op_reduces_to_source (const cairo_composite_rectangles_t *extents,
466
 
                      cairo_bool_t no_mask)
467
 
{
468
 
    if (extents->op == CAIRO_OPERATOR_SOURCE)
469
 
        return TRUE;
470
 
 
471
 
    if (extents->surface->is_clear)
472
 
        return extents->op == CAIRO_OPERATOR_OVER || extents->op == CAIRO_OPERATOR_ADD;
473
 
 
474
 
    if (no_mask && extents->op == CAIRO_OPERATOR_OVER)
475
 
        return _cairo_pattern_is_opaque (&extents->source_pattern.base,
476
 
                                         &extents->source_sample_area);
477
 
 
478
 
    return FALSE;
479
 
}
480
 
 
481
 
static cairo_status_t
482
 
upload_boxes (const cairo_spans_compositor_t *compositor,
483
 
              const cairo_composite_rectangles_t *extents,
484
 
              cairo_boxes_t *boxes)
485
 
{
486
 
    cairo_surface_t *dst = extents->surface;
487
 
    const cairo_surface_pattern_t *source = &extents->source_pattern.surface;
488
 
    cairo_surface_t *src;
489
 
    cairo_rectangle_int_t limit;
490
 
    cairo_int_status_t status;
491
 
    int tx, ty;
492
 
 
493
 
    TRACE ((stderr, "%s\n", __FUNCTION__));
494
 
 
495
 
    src = _cairo_pattern_get_source(source, &limit);
496
 
    if (!(src->type == CAIRO_SURFACE_TYPE_IMAGE || src->type == dst->type))
497
 
        return CAIRO_INT_STATUS_UNSUPPORTED;
498
 
 
499
 
    if (! _cairo_matrix_is_integer_translation (&source->base.matrix, &tx, &ty))
500
 
        return CAIRO_INT_STATUS_UNSUPPORTED;
501
 
 
502
 
    /* Check that the data is entirely within the image */
503
 
    if (extents->bounded.x + tx < limit.x || extents->bounded.y + ty < limit.y)
504
 
        return CAIRO_INT_STATUS_UNSUPPORTED;
505
 
 
506
 
    if (extents->bounded.x + extents->bounded.width  + tx > limit.x + limit.width ||
507
 
        extents->bounded.y + extents->bounded.height + ty > limit.y + limit.height)
508
 
        return CAIRO_INT_STATUS_UNSUPPORTED;
509
 
 
510
 
    tx += limit.x;
511
 
    ty += limit.y;
512
 
 
513
 
    if (src->type == CAIRO_SURFACE_TYPE_IMAGE)
514
 
        status = compositor->draw_image_boxes (dst,
515
 
                                               (cairo_image_surface_t *)src,
516
 
                                               boxes, tx, ty);
517
 
    else
518
 
        status = compositor->copy_boxes (dst, src, boxes, &extents->bounded,
519
 
                                         tx, ty);
520
 
 
521
 
    return status;
522
 
}
523
 
 
524
 
static cairo_bool_t
525
 
_clip_is_region (const cairo_clip_t *clip)
526
 
{
527
 
    int i;
528
 
 
529
 
    if (clip->is_region)
530
 
        return TRUE;
531
 
 
532
 
    if (clip->path)
533
 
        return FALSE;
534
 
 
535
 
    for (i = 0; i < clip->num_boxes; i++) {
536
 
        const cairo_box_t *b = &clip->boxes[i];
537
 
        if (!_cairo_fixed_is_integer (b->p1.x | b->p1.y |  b->p2.x | b->p2.y))
538
 
            return FALSE;
539
 
    }
540
 
 
541
 
    return TRUE;
542
 
}
543
 
 
544
 
static cairo_int_status_t
545
 
composite_aligned_boxes (const cairo_spans_compositor_t         *compositor,
546
 
                         const cairo_composite_rectangles_t     *extents,
547
 
                         cairo_boxes_t                          *boxes)
548
 
{
549
 
    cairo_surface_t *dst = extents->surface;
550
 
    cairo_operator_t op = extents->op;
551
 
    const cairo_pattern_t *source = &extents->source_pattern.base;
552
 
    cairo_int_status_t status;
553
 
    cairo_bool_t need_clip_mask = ! _clip_is_region (extents->clip);
554
 
    cairo_bool_t op_is_source;
555
 
    cairo_bool_t no_mask;
556
 
    cairo_bool_t inplace;
557
 
 
558
 
    TRACE ((stderr, "%s: need_clip_mask=%d, is-bounded=%d\n",
559
 
            __FUNCTION__, need_clip_mask, extents->is_bounded));
560
 
    if (need_clip_mask && ! extents->is_bounded) {
561
 
        TRACE ((stderr, "%s: unsupported clip\n", __FUNCTION__));
562
 
        return CAIRO_INT_STATUS_UNSUPPORTED;
563
 
    }
564
 
 
565
 
    no_mask = extents->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
566
 
        CAIRO_COLOR_IS_OPAQUE (&extents->mask_pattern.solid.color);
567
 
    op_is_source = op_reduces_to_source (extents, no_mask);
568
 
    inplace = ! need_clip_mask && op_is_source && no_mask;
569
 
 
570
 
    TRACE ((stderr, "%s: op-is-source=%d [op=%d], no-mask=%d, inplace=%d\n",
571
 
            __FUNCTION__, op_is_source, op, no_mask, inplace));
572
 
 
573
 
    if (op == CAIRO_OPERATOR_SOURCE && (need_clip_mask || ! no_mask)) {
574
 
        /* SOURCE with a mask is actually a LERP in cairo semantics */
575
 
        if ((compositor->flags & CAIRO_SPANS_COMPOSITOR_HAS_LERP) == 0) {
576
 
            TRACE ((stderr, "%s: unsupported lerp\n", __FUNCTION__));
577
 
            return CAIRO_INT_STATUS_UNSUPPORTED;
578
 
        }
579
 
    }
580
 
 
581
 
    /* Are we just copying a recording surface? */
582
 
    if (inplace &&
583
 
        recording_pattern_contains_sample (&extents->source_pattern.base,
584
 
                                           &extents->source_sample_area))
585
 
    {
586
 
        cairo_clip_t *recording_clip;
587
 
        const cairo_pattern_t *source = &extents->source_pattern.base;
588
 
 
589
 
        /* XXX could also do tiling repeat modes... */
590
 
 
591
 
        /* first clear the area about to be overwritten */
592
 
        if (! dst->is_clear) {
593
 
            status = compositor->fill_boxes (dst,
594
 
                                             CAIRO_OPERATOR_CLEAR,
595
 
                                             CAIRO_COLOR_TRANSPARENT,
596
 
                                             boxes);
597
 
            if (unlikely (status))
598
 
                return status;
599
 
 
600
 
            dst->is_clear = TRUE;
601
 
        }
602
 
 
603
 
        recording_clip = _cairo_clip_from_boxes (boxes);
604
 
        status = _cairo_recording_surface_replay_with_clip (unwrap_source (source),
605
 
                                                            &source->matrix,
606
 
                                                            dst, recording_clip);
607
 
        _cairo_clip_destroy (recording_clip);
608
 
 
609
 
        return status;
610
 
    }
611
 
 
612
 
    status = CAIRO_INT_STATUS_UNSUPPORTED;
613
 
    if (! need_clip_mask && no_mask && source->type == CAIRO_PATTERN_TYPE_SOLID) {
614
 
        const cairo_color_t *color;
615
 
 
616
 
        color = &((cairo_solid_pattern_t *) source)->color;
617
 
        if (op_is_source)
618
 
            op = CAIRO_OPERATOR_SOURCE;
619
 
        status = compositor->fill_boxes (dst, op, color, boxes);
620
 
    } else if (inplace && source->type == CAIRO_PATTERN_TYPE_SURFACE) {
621
 
        status = upload_boxes (compositor, extents, boxes);
622
 
    }
623
 
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
624
 
        cairo_surface_t *src;
625
 
        cairo_surface_t *mask = NULL;
626
 
        int src_x, src_y;
627
 
        int mask_x = 0, mask_y = 0;
628
 
 
629
 
        /* All typical cases will have been resolved before now... */
630
 
        if (need_clip_mask) {
631
 
            mask = get_clip_surface (compositor, dst, extents->clip,
632
 
                                     &extents->bounded);
633
 
            if (unlikely (mask->status))
634
 
                return mask->status;
635
 
 
636
 
            mask_x = -extents->bounded.x;
637
 
            mask_y = -extents->bounded.y;
638
 
        }
639
 
 
640
 
        /* XXX but this is still ugly */
641
 
        if (! no_mask) {
642
 
            src = compositor->pattern_to_surface (dst,
643
 
                                                  &extents->mask_pattern.base,
644
 
                                                  TRUE,
645
 
                                                  &extents->bounded,
646
 
                                                  &extents->mask_sample_area,
647
 
                                                  &src_x, &src_y);
648
 
            if (unlikely (src->status)) {
649
 
                cairo_surface_destroy (mask);
650
 
                return src->status;
651
 
            }
652
 
 
653
 
            if (mask != NULL) {
654
 
                status = compositor->composite_boxes (mask, CAIRO_OPERATOR_IN,
655
 
                                                      src, NULL,
656
 
                                                      src_x, src_y,
657
 
                                                      0, 0,
658
 
                                                      mask_x, mask_y,
659
 
                                                      boxes, &extents->bounded);
660
 
 
661
 
                cairo_surface_destroy (src);
662
 
            } else {
663
 
                mask = src;
664
 
                mask_x = src_x;
665
 
                mask_y = src_y;
666
 
            }
667
 
        }
668
 
 
669
 
        src = compositor->pattern_to_surface (dst, source, FALSE,
670
 
                                              &extents->bounded,
671
 
                                              &extents->source_sample_area,
672
 
                                              &src_x, &src_y);
673
 
        if (likely (src->status == CAIRO_STATUS_SUCCESS)) {
674
 
            status = compositor->composite_boxes (dst, op, src, mask,
675
 
                                                  src_x, src_y,
676
 
                                                  mask_x, mask_y,
677
 
                                                  0, 0,
678
 
                                                  boxes, &extents->bounded);
679
 
            cairo_surface_destroy (src);
680
 
        } else
681
 
            status = src->status;
682
 
 
683
 
        cairo_surface_destroy (mask);
684
 
    }
685
 
 
686
 
    if (status == CAIRO_INT_STATUS_SUCCESS && ! extents->is_bounded)
687
 
        status = fixup_unbounded_boxes (compositor, extents, boxes);
688
 
 
689
 
    return status;
690
 
}
691
 
 
692
 
static cairo_bool_t
693
 
composite_needs_clip (const cairo_composite_rectangles_t *composite,
694
 
                      const cairo_box_t *extents)
695
 
{
696
 
    return !_cairo_clip_contains_box (composite->clip, extents);
697
 
}
698
 
 
699
 
static cairo_int_status_t
700
 
composite_boxes (const cairo_spans_compositor_t *compositor,
701
 
                 cairo_composite_rectangles_t *extents,
702
 
                 cairo_boxes_t          *boxes)
703
 
{
704
 
    cairo_abstract_span_renderer_t renderer;
705
 
    cairo_rectangular_scan_converter_t converter;
706
 
    const struct _cairo_boxes_chunk *chunk;
707
 
    cairo_int_status_t status;
708
 
    cairo_box_t box;
709
 
 
710
 
    TRACE ((stderr, "%s\n", __FUNCTION__));
711
 
    _cairo_box_from_rectangle (&box, &extents->unbounded);
712
 
    if (composite_needs_clip (extents, &box)) {
713
 
        TRACE ((stderr, "%s: unsupported clip\n", __FUNCTION__));
714
 
        return CAIRO_INT_STATUS_UNSUPPORTED;
715
 
    }
716
 
 
717
 
    _cairo_rectangular_scan_converter_init (&converter, &extents->unbounded);
718
 
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
719
 
        const cairo_box_t *box = chunk->base;
720
 
        int i;
721
 
 
722
 
        for (i = 0; i < chunk->count; i++) {
723
 
            status = _cairo_rectangular_scan_converter_add_box (&converter, &box[i], 1);
724
 
            if (unlikely (status))
725
 
                goto cleanup_converter;
726
 
        }
727
 
    }
728
 
 
729
 
    status = compositor->renderer_init (&renderer, extents,
730
 
                                        CAIRO_ANTIALIAS_DEFAULT, FALSE);
731
 
    if (likely (status == CAIRO_INT_STATUS_SUCCESS))
732
 
        status = converter.base.generate (&converter.base, &renderer.base);
733
 
    compositor->renderer_fini (&renderer, status);
734
 
 
735
 
cleanup_converter:
736
 
    converter.base.destroy (&converter.base);
737
 
    return status;
738
 
}
739
 
 
740
 
static cairo_int_status_t
741
 
composite_polygon (const cairo_spans_compositor_t       *compositor,
742
 
                   cairo_composite_rectangles_t          *extents,
743
 
                   cairo_polygon_t                      *polygon,
744
 
                   cairo_fill_rule_t                     fill_rule,
745
 
                   cairo_antialias_t                     antialias)
746
 
{
747
 
    cairo_abstract_span_renderer_t renderer;
748
 
    cairo_scan_converter_t *converter;
749
 
    cairo_bool_t needs_clip;
750
 
    cairo_int_status_t status;
751
 
 
752
 
    if (extents->is_bounded)
753
 
        needs_clip = extents->clip->path != NULL;
754
 
    else
755
 
        needs_clip = !_clip_is_region (extents->clip) || extents->clip->num_boxes > 1;
756
 
    TRACE ((stderr, "%s - needs_clip=%d\n", __FUNCTION__, needs_clip));
757
 
    if (needs_clip) {
758
 
        TRACE ((stderr, "%s: unsupported clip\n", __FUNCTION__));
759
 
        return CAIRO_INT_STATUS_UNSUPPORTED;
760
 
        converter = _cairo_clip_tor_scan_converter_create (extents->clip,
761
 
                                                           polygon,
762
 
                                                           fill_rule, antialias);
763
 
    } else {
764
 
        const cairo_rectangle_int_t *r = &extents->unbounded;
765
 
 
766
 
        if (antialias == CAIRO_ANTIALIAS_FAST) {
767
 
            converter = _cairo_tor22_scan_converter_create (r->x, r->y,
768
 
                                                            r->x + r->width,
769
 
                                                            r->y + r->height,
770
 
                                                            fill_rule, antialias);
771
 
            status = _cairo_tor22_scan_converter_add_polygon (converter, polygon);
772
 
        } else if (antialias == CAIRO_ANTIALIAS_NONE) {
773
 
            converter = _cairo_mono_scan_converter_create (r->x, r->y,
774
 
                                                           r->x + r->width,
775
 
                                                           r->y + r->height,
776
 
                                                           fill_rule);
777
 
            status = _cairo_mono_scan_converter_add_polygon (converter, polygon);
778
 
        } else {
779
 
            converter = _cairo_tor_scan_converter_create (r->x, r->y,
780
 
                                                          r->x + r->width,
781
 
                                                          r->y + r->height,
782
 
                                                          fill_rule, antialias);
783
 
            status = _cairo_tor_scan_converter_add_polygon (converter, polygon);
784
 
        }
785
 
    }
786
 
    if (unlikely (status))
787
 
        goto cleanup_converter;
788
 
 
789
 
    status = compositor->renderer_init (&renderer, extents,
790
 
                                        antialias, needs_clip);
791
 
    if (likely (status == CAIRO_INT_STATUS_SUCCESS))
792
 
        status = converter->generate (converter, &renderer.base);
793
 
    compositor->renderer_fini (&renderer, status);
794
 
 
795
 
cleanup_converter:
796
 
    converter->destroy (converter);
797
 
    return status;
798
 
}
799
 
 
800
 
static cairo_int_status_t
801
 
trim_extents_to_boxes (cairo_composite_rectangles_t *extents,
802
 
                       cairo_boxes_t *boxes)
803
 
{
804
 
    cairo_box_t box;
805
 
 
806
 
    _cairo_boxes_extents (boxes, &box);
807
 
    return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
808
 
}
809
 
 
810
 
static cairo_int_status_t
811
 
trim_extents_to_polygon (cairo_composite_rectangles_t *extents,
812
 
                         cairo_polygon_t *polygon)
813
 
{
814
 
    return _cairo_composite_rectangles_intersect_mask_extents (extents,
815
 
                                                               &polygon->extents);
816
 
}
817
 
 
818
 
static cairo_int_status_t
819
 
clip_and_composite_boxes (const cairo_spans_compositor_t        *compositor,
820
 
                          cairo_composite_rectangles_t          *extents,
821
 
                          cairo_boxes_t                         *boxes)
822
 
{
823
 
    cairo_int_status_t status;
824
 
    cairo_polygon_t polygon;
825
 
 
826
 
    TRACE ((stderr, "%s\n", __FUNCTION__));
827
 
    status = trim_extents_to_boxes (extents, boxes);
828
 
    if (unlikely (status))
829
 
        return status;
830
 
 
831
 
    if (boxes->num_boxes == 0) {
832
 
        if (extents->is_bounded)
833
 
            return CAIRO_STATUS_SUCCESS;
834
 
 
835
 
        return fixup_unbounded_boxes (compositor, extents, boxes);
836
 
    }
837
 
 
838
 
    /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
839
 
    if (extents->clip->path != NULL && extents->is_bounded) {
840
 
        cairo_polygon_t polygon;
841
 
        cairo_fill_rule_t fill_rule;
842
 
        cairo_antialias_t antialias;
843
 
        cairo_clip_t *clip;
844
 
 
845
 
        clip = _cairo_clip_copy (extents->clip);
846
 
        clip = _cairo_clip_intersect_boxes (clip, boxes);
847
 
        if (_cairo_clip_is_all_clipped (clip))
848
 
            return CAIRO_INT_STATUS_NOTHING_TO_DO;
849
 
 
850
 
        status = _cairo_clip_get_polygon (clip, &polygon,
851
 
                                          &fill_rule, &antialias);
852
 
        _cairo_clip_path_destroy (clip->path);
853
 
        clip->path = NULL;
854
 
        if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
855
 
            cairo_clip_t *saved_clip = extents->clip;
856
 
            extents->clip = clip;
857
 
 
858
 
            status = clip_and_composite_polygon (compositor, extents, &polygon,
859
 
                                                 fill_rule, antialias);
860
 
 
861
 
            clip = extents->clip;
862
 
            extents->clip = saved_clip;
863
 
 
864
 
            _cairo_polygon_fini (&polygon);
865
 
        }
866
 
        _cairo_clip_destroy (clip);
867
 
 
868
 
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
869
 
            return status;
870
 
    }
871
 
 
872
 
    if (boxes->is_pixel_aligned) {
873
 
        status = composite_aligned_boxes (compositor, extents, boxes);
874
 
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
875
 
            return status;
876
 
    }
877
 
 
878
 
    status = composite_boxes (compositor, extents, boxes);
879
 
    if (status != CAIRO_INT_STATUS_UNSUPPORTED)
880
 
        return status;
881
 
 
882
 
    status = _cairo_polygon_init_boxes (&polygon, boxes);
883
 
    if (unlikely (status))
884
 
        return status;
885
 
 
886
 
    status = composite_polygon (compositor, extents, &polygon,
887
 
                                CAIRO_FILL_RULE_WINDING,
888
 
                                CAIRO_ANTIALIAS_DEFAULT);
889
 
    _cairo_polygon_fini (&polygon);
890
 
 
891
 
    return status;
892
 
}
893
 
 
894
 
static cairo_int_status_t
895
 
clip_and_composite_polygon (const cairo_spans_compositor_t      *compositor,
896
 
                            cairo_composite_rectangles_t         *extents,
897
 
                            cairo_polygon_t                     *polygon,
898
 
                            cairo_fill_rule_t                    fill_rule,
899
 
                            cairo_antialias_t                    antialias)
900
 
{
901
 
    cairo_int_status_t status;
902
 
 
903
 
    TRACE ((stderr, "%s\n", __FUNCTION__));
904
 
 
905
 
    /* XXX simply uses polygon limits.point extemities, tessellation? */
906
 
    status = trim_extents_to_polygon (extents, polygon);
907
 
    if (unlikely (status))
908
 
        return status;
909
 
 
910
 
    if (_cairo_polygon_is_empty (polygon)) {
911
 
        cairo_boxes_t boxes;
912
 
 
913
 
        if (extents->is_bounded)
914
 
            return CAIRO_STATUS_SUCCESS;
915
 
 
916
 
        _cairo_boxes_init (&boxes);
917
 
        extents->bounded.width = extents->bounded.height = 0;
918
 
        return fixup_unbounded_boxes (compositor, extents, &boxes);
919
 
    }
920
 
 
921
 
    if (extents->is_bounded && extents->clip->path) {
922
 
        cairo_polygon_t clipper;
923
 
        cairo_antialias_t clip_antialias;
924
 
        cairo_fill_rule_t clip_fill_rule;
925
 
 
926
 
        TRACE((stderr, "%s - combining shape with clip polygon\n",
927
 
               __FUNCTION__));
928
 
 
929
 
        status = _cairo_clip_get_polygon (extents->clip,
930
 
                                          &clipper,
931
 
                                          &clip_fill_rule,
932
 
                                          &clip_antialias);
933
 
        if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
934
 
            cairo_clip_t *old_clip;
935
 
 
936
 
            if (clip_antialias == antialias) {
937
 
                status = _cairo_polygon_intersect (polygon, fill_rule,
938
 
                                                   &clipper, clip_fill_rule);
939
 
                _cairo_polygon_fini (&clipper);
940
 
                if (unlikely (status))
941
 
                    return status;
942
 
 
943
 
                old_clip = extents->clip;
944
 
                extents->clip = _cairo_clip_copy_region (extents->clip);
945
 
                _cairo_clip_destroy (old_clip);
946
 
 
947
 
                status = trim_extents_to_polygon (extents, polygon);
948
 
                if (unlikely (status))
949
 
                    return status;
950
 
 
951
 
                fill_rule = CAIRO_FILL_RULE_WINDING;
952
 
            } else {
953
 
                _cairo_polygon_fini (&clipper);
954
 
            }
955
 
        }
956
 
    }
957
 
 
958
 
    return composite_polygon (compositor, extents,
959
 
                              polygon, fill_rule, antialias);
960
 
}
961
 
 
962
 
/* high-level compositor interface */
963
 
 
964
 
static cairo_int_status_t
965
 
_cairo_spans_compositor_paint (const cairo_compositor_t         *_compositor,
966
 
                               cairo_composite_rectangles_t     *extents)
967
 
{
968
 
    const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
969
 
    cairo_boxes_t boxes;
970
 
    cairo_int_status_t status;
971
 
 
972
 
    TRACE ((stderr, "%s\n", __FUNCTION__));
973
 
    _cairo_clip_steal_boxes (extents->clip, &boxes);
974
 
    status = clip_and_composite_boxes (compositor, extents, &boxes);
975
 
    _cairo_clip_unsteal_boxes (extents->clip, &boxes);
976
 
 
977
 
    return status;
978
 
}
979
 
 
980
 
static cairo_int_status_t
981
 
_cairo_spans_compositor_mask (const cairo_compositor_t          *_compositor,
982
 
                              cairo_composite_rectangles_t      *extents)
983
 
{
984
 
    const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
985
 
    cairo_int_status_t status;
986
 
    cairo_boxes_t boxes;
987
 
 
988
 
    TRACE ((stderr, "%s\n", __FUNCTION__));
989
 
    _cairo_clip_steal_boxes (extents->clip, &boxes);
990
 
    status = clip_and_composite_boxes (compositor, extents, &boxes);
991
 
    _cairo_clip_unsteal_boxes (extents->clip, &boxes);
992
 
 
993
 
    return status;
994
 
}
995
 
 
996
 
static cairo_int_status_t
997
 
_cairo_spans_compositor_stroke (const cairo_compositor_t        *_compositor,
998
 
                                cairo_composite_rectangles_t     *extents,
999
 
                                const cairo_path_fixed_t        *path,
1000
 
                                const cairo_stroke_style_t      *style,
1001
 
                                const cairo_matrix_t            *ctm,
1002
 
                                const cairo_matrix_t            *ctm_inverse,
1003
 
                                double                           tolerance,
1004
 
                                cairo_antialias_t                antialias)
1005
 
{
1006
 
    const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
1007
 
    cairo_int_status_t status;
1008
 
 
1009
 
    TRACE ((stderr, "%s\n", __FUNCTION__));
1010
 
    TRACE_ (_cairo_debug_print_path (stderr, path));
1011
 
    TRACE_ (_cairo_debug_print_clip (stderr, extents->clip));
1012
 
 
1013
 
    status = CAIRO_INT_STATUS_UNSUPPORTED;
1014
 
    if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
1015
 
        cairo_boxes_t boxes;
1016
 
 
1017
 
        _cairo_boxes_init (&boxes);
1018
 
        if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask))
1019
 
            _cairo_boxes_limit (&boxes,
1020
 
                                extents->clip->boxes,
1021
 
                                extents->clip->num_boxes);
1022
 
 
1023
 
        status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
1024
 
                                                                style,
1025
 
                                                                ctm,
1026
 
                                                                antialias,
1027
 
                                                                &boxes);
1028
 
        if (likely (status == CAIRO_INT_STATUS_SUCCESS))
1029
 
            status = clip_and_composite_boxes (compositor, extents, &boxes);
1030
 
        _cairo_boxes_fini (&boxes);
1031
 
    }
1032
 
 
1033
 
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1034
 
        cairo_polygon_t polygon;
1035
 
        cairo_fill_rule_t fill_rule = CAIRO_FILL_RULE_WINDING;
1036
 
 
1037
 
        if (! _cairo_rectangle_contains_rectangle (&extents->unbounded,
1038
 
                                                   &extents->mask))
1039
 
        {
1040
 
            if (extents->clip->num_boxes == 1) {
1041
 
                _cairo_polygon_init (&polygon, extents->clip->boxes, 1);
1042
 
            } else {
1043
 
                cairo_box_t limits;
1044
 
                _cairo_box_from_rectangle (&limits, &extents->unbounded);
1045
 
                _cairo_polygon_init (&polygon, &limits, 1);
1046
 
            }
1047
 
        }
1048
 
        else
1049
 
        {
1050
 
            _cairo_polygon_init (&polygon, NULL, 0);
1051
 
        }
1052
 
        status = _cairo_path_fixed_stroke_to_polygon (path,
1053
 
                                                      style,
1054
 
                                                      ctm, ctm_inverse,
1055
 
                                                      tolerance,
1056
 
                                                      &polygon);
1057
 
        TRACE_ (_cairo_debug_print_polygon (stderr, &polygon));
1058
 
        polygon.num_limits = 0;
1059
 
 
1060
 
        if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) {
1061
 
            status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
1062
 
                                                          extents->clip->boxes,
1063
 
                                                          extents->clip->num_boxes);
1064
 
        }
1065
 
        if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1066
 
            cairo_clip_t *saved_clip = extents->clip;
1067
 
 
1068
 
            if (extents->is_bounded) {
1069
 
                extents->clip = _cairo_clip_copy_path (extents->clip);
1070
 
                extents->clip = _cairo_clip_intersect_box(extents->clip,
1071
 
                                                          &polygon.extents);
1072
 
            }
1073
 
 
1074
 
            status = clip_and_composite_polygon (compositor, extents, &polygon,
1075
 
                                                 fill_rule, antialias);
1076
 
 
1077
 
            if (extents->is_bounded) {
1078
 
                _cairo_clip_destroy (extents->clip);
1079
 
                extents->clip = saved_clip;
1080
 
            }
1081
 
        }
1082
 
        _cairo_polygon_fini (&polygon);
1083
 
    }
1084
 
 
1085
 
    return status;
1086
 
}
1087
 
 
1088
 
static cairo_int_status_t
1089
 
_cairo_spans_compositor_fill (const cairo_compositor_t          *_compositor,
1090
 
                              cairo_composite_rectangles_t       *extents,
1091
 
                              const cairo_path_fixed_t          *path,
1092
 
                              cairo_fill_rule_t                  fill_rule,
1093
 
                              double                             tolerance,
1094
 
                              cairo_antialias_t                  antialias)
1095
 
{
1096
 
    const cairo_spans_compositor_t *compositor = (cairo_spans_compositor_t*)_compositor;
1097
 
    cairo_int_status_t status;
1098
 
 
1099
 
    TRACE((stderr, "%s op=%d, antialias=%d\n", __FUNCTION__, extents->op, antialias));
1100
 
 
1101
 
    status = CAIRO_INT_STATUS_UNSUPPORTED;
1102
 
    if (_cairo_path_fixed_fill_is_rectilinear (path)) {
1103
 
        cairo_boxes_t boxes;
1104
 
 
1105
 
        TRACE((stderr, "%s - rectilinear\n", __FUNCTION__));
1106
 
 
1107
 
        _cairo_boxes_init (&boxes);
1108
 
        if (! _cairo_clip_contains_rectangle (extents->clip, &extents->mask))
1109
 
            _cairo_boxes_limit (&boxes,
1110
 
                                extents->clip->boxes,
1111
 
                                extents->clip->num_boxes);
1112
 
        status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
1113
 
                                                              fill_rule,
1114
 
                                                              antialias,
1115
 
                                                              &boxes);
1116
 
        if (likely (status == CAIRO_INT_STATUS_SUCCESS))
1117
 
            status = clip_and_composite_boxes (compositor, extents, &boxes);
1118
 
        _cairo_boxes_fini (&boxes);
1119
 
    }
1120
 
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1121
 
        cairo_polygon_t polygon;
1122
 
 
1123
 
        TRACE((stderr, "%s - polygon\n", __FUNCTION__));
1124
 
 
1125
 
        if (! _cairo_rectangle_contains_rectangle (&extents->unbounded,
1126
 
                                                   &extents->mask))
1127
 
        {
1128
 
            TRACE((stderr, "%s - clipping to bounds\n", __FUNCTION__));
1129
 
            if (extents->clip->num_boxes == 1) {
1130
 
                _cairo_polygon_init (&polygon, extents->clip->boxes, 1);
1131
 
            } else {
1132
 
                cairo_box_t limits;
1133
 
                _cairo_box_from_rectangle (&limits, &extents->unbounded);
1134
 
                _cairo_polygon_init (&polygon, &limits, 1);
1135
 
            }
1136
 
        }
1137
 
        else
1138
 
        {
1139
 
            _cairo_polygon_init (&polygon, NULL, 0);
1140
 
        }
1141
 
 
1142
 
        status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
1143
 
        TRACE_ (_cairo_debug_print_polygon (stderr, &polygon));
1144
 
        polygon.num_limits = 0;
1145
 
 
1146
 
        if (status == CAIRO_INT_STATUS_SUCCESS && extents->clip->num_boxes > 1) {
1147
 
            TRACE((stderr, "%s - polygon intersect with %d clip boxes\n",
1148
 
                   __FUNCTION__, extents->clip->num_boxes));
1149
 
            status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
1150
 
                                                          extents->clip->boxes,
1151
 
                                                          extents->clip->num_boxes);
1152
 
        }
1153
 
        TRACE_ (_cairo_debug_print_polygon (stderr, &polygon));
1154
 
        if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
1155
 
            cairo_clip_t *saved_clip = extents->clip;
1156
 
 
1157
 
            if (extents->is_bounded) {
1158
 
                TRACE((stderr, "%s - polygon discard clip boxes\n",
1159
 
                       __FUNCTION__));
1160
 
                extents->clip = _cairo_clip_copy_path (extents->clip);
1161
 
                extents->clip = _cairo_clip_intersect_box(extents->clip,
1162
 
                                                          &polygon.extents);
1163
 
            }
1164
 
 
1165
 
            status = clip_and_composite_polygon (compositor, extents, &polygon,
1166
 
                                                 fill_rule, antialias);
1167
 
 
1168
 
            if (extents->is_bounded) {
1169
 
                _cairo_clip_destroy (extents->clip);
1170
 
                extents->clip = saved_clip;
1171
 
            }
1172
 
        }
1173
 
        _cairo_polygon_fini (&polygon);
1174
 
 
1175
 
        TRACE((stderr, "%s - polygon status=%d\n", __FUNCTION__, status));
1176
 
    }
1177
 
 
1178
 
    return status;
1179
 
}
1180
 
 
1181
 
void
1182
 
_cairo_spans_compositor_init (cairo_spans_compositor_t *compositor,
1183
 
                              const cairo_compositor_t  *delegate)
1184
 
{
1185
 
    compositor->base.delegate = delegate;
1186
 
 
1187
 
    compositor->base.paint  = _cairo_spans_compositor_paint;
1188
 
    compositor->base.mask   = _cairo_spans_compositor_mask;
1189
 
    compositor->base.fill   = _cairo_spans_compositor_fill;
1190
 
    compositor->base.stroke = _cairo_spans_compositor_stroke;
1191
 
    compositor->base.glyphs = NULL;
1192
 
}