~ubuntu-branches/ubuntu/natty/moon/natty

« back to all changes in this revision

Viewing changes to cairo/src/cairo-traps.c

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-14 12:01:08 UTC
  • Revision ID: james.westby@ubuntu.com-20090214120108-06539vb25vhbd8bn
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

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
/*
 
3
 * Copyright Ā© 2002 Keith Packard
 
4
 * Copyright Ā© 2007 Red Hat, Inc.
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it either under the terms of the GNU Lesser General Public
 
8
 * License version 2.1 as published by the Free Software Foundation
 
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
 
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
 
11
 * notice, a recipient may use your version of this file under either
 
12
 * the MPL or the LGPL.
 
13
 *
 
14
 * You should have received a copy of the LGPL along with this library
 
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
 
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 
17
 * You should have received a copy of the MPL along with this library
 
18
 * in the file COPYING-MPL-1.1
 
19
 *
 
20
 * The contents of this file are subject to the Mozilla Public License
 
21
 * Version 1.1 (the "License"); you may not use this file except in
 
22
 * compliance with the License. You may obtain a copy of the License at
 
23
 * http://www.mozilla.org/MPL/
 
24
 *
 
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 
27
 * the specific language governing rights and limitations.
 
28
 *
 
29
 * The Original Code is the cairo graphics library.
 
30
 *
 
31
 * The Initial Developer of the Original Code is Keith Packard
 
32
 *
 
33
 * Contributor(s):
 
34
 *      Keith R. Packard <keithp@keithp.com>
 
35
 *      Carl D. Worth <cworth@cworth.org>
 
36
 *
 
37
 * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth
 
38
 */
 
39
 
 
40
#include "cairoint.h"
 
41
 
 
42
/* private functions */
 
43
 
 
44
static int
 
45
_compare_point_fixed_by_y (const void *av, const void *bv);
 
46
 
 
47
void
 
48
_cairo_traps_init (cairo_traps_t *traps)
 
49
{
 
50
    traps->status = CAIRO_STATUS_SUCCESS;
 
51
 
 
52
    traps->num_traps = 0;
 
53
 
 
54
    traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
 
55
    traps->traps = traps->traps_embedded;
 
56
    traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
 
57
    traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
 
58
 
 
59
    traps->has_limits = FALSE;
 
60
}
 
61
 
 
62
void
 
63
_cairo_traps_limit (cairo_traps_t       *traps,
 
64
                    cairo_box_t         *limits)
 
65
{
 
66
    traps->has_limits = TRUE;
 
67
 
 
68
    traps->limits = *limits;
 
69
}
 
70
 
 
71
cairo_bool_t
 
72
_cairo_traps_get_limit (cairo_traps_t *traps,
 
73
                        cairo_box_t   *limits)
 
74
{
 
75
    *limits = traps->limits;
 
76
    return traps->has_limits;
 
77
}
 
78
 
 
79
void
 
80
_cairo_traps_clear (cairo_traps_t *traps)
 
81
{
 
82
    traps->status = CAIRO_STATUS_SUCCESS;
 
83
 
 
84
    traps->num_traps = 0;
 
85
}
 
86
 
 
87
void
 
88
_cairo_traps_fini (cairo_traps_t *traps)
 
89
{
 
90
    if (traps->traps != traps->traps_embedded)
 
91
        free (traps->traps);
 
92
}
 
93
 
 
94
/**
 
95
 * _cairo_traps_init_box:
 
96
 * @traps: a #cairo_traps_t
 
97
 * @box: a box that will be converted to a single trapezoid
 
98
 *       to store in @traps.
 
99
 *
 
100
 * Initializes a #cairo_traps_t to contain a single rectangular
 
101
 * trapezoid.
 
102
 **/
 
103
void
 
104
_cairo_traps_init_box (cairo_traps_t *traps,
 
105
                       const cairo_box_t   *box)
 
106
{
 
107
    _cairo_traps_init (traps);
 
108
 
 
109
    assert (traps->traps_size >= 1);
 
110
 
 
111
    traps->num_traps = 1;
 
112
 
 
113
    traps->traps[0].top = box->p1.y;
 
114
    traps->traps[0].bottom = box->p2.y;
 
115
    traps->traps[0].left.p1 = box->p1;
 
116
    traps->traps[0].left.p2.x = box->p1.x;
 
117
    traps->traps[0].left.p2.y = box->p2.y;
 
118
    traps->traps[0].right.p1.x = box->p2.x;
 
119
    traps->traps[0].right.p1.y = box->p1.y;
 
120
    traps->traps[0].right.p2 = box->p2;
 
121
 
 
122
    traps->extents = *box;
 
123
}
 
124
 
 
125
/* make room for at least one more trap */
 
126
static cairo_bool_t
 
127
_cairo_traps_grow (cairo_traps_t *traps)
 
128
{
 
129
    cairo_trapezoid_t *new_traps;
 
130
    int new_size = 2 * MAX (traps->traps_size, 16);
 
131
 
 
132
    if (traps->traps == traps->traps_embedded) {
 
133
        new_traps = _cairo_malloc_ab (new_size, sizeof (cairo_trapezoid_t));
 
134
        if (new_traps != NULL)
 
135
            memcpy (new_traps, traps->traps, sizeof (traps->traps_embedded));
 
136
    } else {
 
137
        new_traps = _cairo_realloc_ab (traps->traps,
 
138
                                       new_size, sizeof (cairo_trapezoid_t));
 
139
    }
 
140
 
 
141
    if (new_traps == NULL) {
 
142
        traps->status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
143
        return FALSE;
 
144
    }
 
145
 
 
146
    traps->traps = new_traps;
 
147
    traps->traps_size = new_size;
 
148
    return TRUE;
 
149
}
 
150
 
 
151
void
 
152
_cairo_traps_add_trap (cairo_traps_t *traps,
 
153
                       cairo_fixed_t top, cairo_fixed_t bottom,
 
154
                       cairo_line_t *left, cairo_line_t *right)
 
155
{
 
156
    cairo_trapezoid_t *trap;
 
157
 
 
158
    /* Note: With the goofy trapezoid specification, (where an
 
159
     * arbitrary two points on the lines can specified for the left
 
160
     * and right edges), these limit checks would not work in
 
161
     * general. For example, one can imagine a trapezoid entirely
 
162
     * within the limits, but with two points used to specify the left
 
163
     * edge entirely to the right of the limits.  Fortunately, for our
 
164
     * purposes, cairo will never generate such a crazy
 
165
     * trapezoid. Instead, cairo always uses for its points the
 
166
     * extreme positions of the edge that are visible on at least some
 
167
     * trapezoid. With this constraint, it's impossible for both
 
168
     * points to be outside the limits while the relevant edge is
 
169
     * entirely inside the limits.
 
170
     */
 
171
    if (traps->has_limits) {
 
172
        /* Trivially reject if trapezoid is entirely to the right or
 
173
         * to the left of the limits. */
 
174
        if (left->p1.x >= traps->limits.p2.x &&
 
175
            left->p2.x >= traps->limits.p2.x)
 
176
        {
 
177
            return;
 
178
        }
 
179
 
 
180
        if (right->p1.x <= traps->limits.p1.x &&
 
181
            right->p2.x <= traps->limits.p1.x)
 
182
        {
 
183
            return;
 
184
        }
 
185
 
 
186
        /* And reject if the trapezoid is entirely above or below */
 
187
        if (top > traps->limits.p2.y || bottom < traps->limits.p1.y)
 
188
            return;
 
189
 
 
190
        /* Otherwise, clip the trapezoid to the limits. We only clip
 
191
         * where an edge is entirely outside the limits. If we wanted
 
192
         * to be more clever, we could handle cases where a trapezoid
 
193
         * edge intersects the edge of the limits, but that would
 
194
         * require slicing this trapezoid into multiple trapezoids,
 
195
         * and I'm not sure the effort would be worth it. */
 
196
        if (top < traps->limits.p1.y)
 
197
            top = traps->limits.p1.y;
 
198
 
 
199
        if (bottom > traps->limits.p2.y)
 
200
            bottom = traps->limits.p2.y;
 
201
 
 
202
        if (left->p1.x <= traps->limits.p1.x &&
 
203
            left->p2.x <= traps->limits.p1.x)
 
204
        {
 
205
            left->p1.x = traps->limits.p1.x;
 
206
            left->p2.x = traps->limits.p1.x;
 
207
        }
 
208
 
 
209
        if (right->p1.x >= traps->limits.p2.x &&
 
210
            right->p2.x >= traps->limits.p2.x)
 
211
        {
 
212
            right->p1.x = traps->limits.p2.x;
 
213
            right->p2.x = traps->limits.p2.x;
 
214
        }
 
215
    }
 
216
 
 
217
    if (top >= bottom) {
 
218
        return;
 
219
    }
 
220
 
 
221
    if (traps->num_traps == traps->traps_size) {
 
222
        if (! _cairo_traps_grow (traps))
 
223
            return;
 
224
    }
 
225
 
 
226
    trap = &traps->traps[traps->num_traps];
 
227
    trap->top = top;
 
228
    trap->bottom = bottom;
 
229
    trap->left = *left;
 
230
    trap->right = *right;
 
231
 
 
232
    if (top < traps->extents.p1.y)
 
233
        traps->extents.p1.y = top;
 
234
    if (bottom > traps->extents.p2.y)
 
235
        traps->extents.p2.y = bottom;
 
236
    /*
 
237
     * This isn't generally accurate, but it is close enough for
 
238
     * this purpose.  Assuming that the left and right segments always
 
239
     * contain the trapezoid vertical extents, these compares will
 
240
     * yield a containing box.  Assuming that the points all come from
 
241
     * the same figure which will eventually be completely drawn, then
 
242
     * the compares will yield the correct overall extents
 
243
     */
 
244
    if (left->p1.x < traps->extents.p1.x)
 
245
        traps->extents.p1.x = left->p1.x;
 
246
    if (left->p2.x < traps->extents.p1.x)
 
247
        traps->extents.p1.x = left->p2.x;
 
248
 
 
249
    if (right->p1.x > traps->extents.p2.x)
 
250
        traps->extents.p2.x = right->p1.x;
 
251
    if (right->p2.x > traps->extents.p2.x)
 
252
        traps->extents.p2.x = right->p2.x;
 
253
 
 
254
    traps->num_traps++;
 
255
}
 
256
 
 
257
static int
 
258
_compare_point_fixed_by_y (const void *av, const void *bv)
 
259
{
 
260
    const cairo_point_t *a = av, *b = bv;
 
261
 
 
262
    int ret = a->y - b->y;
 
263
    if (ret == 0) {
 
264
        ret = a->x - b->x;
 
265
    }
 
266
    return ret;
 
267
}
 
268
 
 
269
void
 
270
_cairo_traps_translate (cairo_traps_t *traps, int x, int y)
 
271
{
 
272
    cairo_fixed_t xoff, yoff;
 
273
    cairo_trapezoid_t *t;
 
274
    int i;
 
275
 
 
276
    /* Ugh. The cairo_composite/(Render) interface doesn't allow
 
277
       an offset for the trapezoids. Need to manually shift all
 
278
       the coordinates to align with the offset origin of the
 
279
       intermediate surface. */
 
280
 
 
281
    xoff = _cairo_fixed_from_int (x);
 
282
    yoff = _cairo_fixed_from_int (y);
 
283
 
 
284
    for (i = 0, t = traps->traps; i < traps->num_traps; i++, t++) {
 
285
        t->top += yoff;
 
286
        t->bottom += yoff;
 
287
        t->left.p1.x += xoff;
 
288
        t->left.p1.y += yoff;
 
289
        t->left.p2.x += xoff;
 
290
        t->left.p2.y += yoff;
 
291
        t->right.p1.x += xoff;
 
292
        t->right.p1.y += yoff;
 
293
        t->right.p2.x += xoff;
 
294
        t->right.p2.y += yoff;
 
295
    }
 
296
}
 
297
 
 
298
void
 
299
_cairo_trapezoid_array_translate_and_scale (cairo_trapezoid_t *offset_traps,
 
300
                                            cairo_trapezoid_t *src_traps,
 
301
                                            int num_traps,
 
302
                                            double tx, double ty,
 
303
                                            double sx, double sy)
 
304
{
 
305
    int i;
 
306
    cairo_fixed_t xoff = _cairo_fixed_from_double (tx);
 
307
    cairo_fixed_t yoff = _cairo_fixed_from_double (ty);
 
308
 
 
309
    if (sx == 1.0 && sy == 1.0) {
 
310
        for (i = 0; i < num_traps; i++) {
 
311
            offset_traps[i].top = src_traps[i].top + yoff;
 
312
            offset_traps[i].bottom = src_traps[i].bottom + yoff;
 
313
            offset_traps[i].left.p1.x = src_traps[i].left.p1.x + xoff;
 
314
            offset_traps[i].left.p1.y = src_traps[i].left.p1.y + yoff;
 
315
            offset_traps[i].left.p2.x = src_traps[i].left.p2.x + xoff;
 
316
            offset_traps[i].left.p2.y = src_traps[i].left.p2.y + yoff;
 
317
            offset_traps[i].right.p1.x = src_traps[i].right.p1.x + xoff;
 
318
            offset_traps[i].right.p1.y = src_traps[i].right.p1.y + yoff;
 
319
            offset_traps[i].right.p2.x = src_traps[i].right.p2.x + xoff;
 
320
            offset_traps[i].right.p2.y = src_traps[i].right.p2.y + yoff;
 
321
        }
 
322
    } else {
 
323
        cairo_fixed_t xsc = _cairo_fixed_from_double (sx);
 
324
        cairo_fixed_t ysc = _cairo_fixed_from_double (sy);
 
325
 
 
326
        for (i = 0; i < num_traps; i++) {
 
327
            offset_traps[i].top = _cairo_fixed_mul (src_traps[i].top + yoff, ysc);
 
328
            offset_traps[i].bottom = _cairo_fixed_mul (src_traps[i].bottom + yoff, ysc);
 
329
            offset_traps[i].left.p1.x = _cairo_fixed_mul (src_traps[i].left.p1.x + xoff, xsc);
 
330
            offset_traps[i].left.p1.y = _cairo_fixed_mul (src_traps[i].left.p1.y + yoff, ysc);
 
331
            offset_traps[i].left.p2.x = _cairo_fixed_mul (src_traps[i].left.p2.x + xoff, xsc);
 
332
            offset_traps[i].left.p2.y = _cairo_fixed_mul (src_traps[i].left.p2.y + yoff, ysc);
 
333
            offset_traps[i].right.p1.x = _cairo_fixed_mul (src_traps[i].right.p1.x + xoff, xsc);
 
334
            offset_traps[i].right.p1.y = _cairo_fixed_mul (src_traps[i].right.p1.y + yoff, ysc);
 
335
            offset_traps[i].right.p2.x = _cairo_fixed_mul (src_traps[i].right.p2.x + xoff, xsc);
 
336
            offset_traps[i].right.p2.y = _cairo_fixed_mul (src_traps[i].right.p2.y + yoff, ysc);
 
337
        }
 
338
    }
 
339
}
 
340
 
 
341
/* A triangle is simply a degenerate case of a convex
 
342
 * quadrilateral. We would not benefit from having any distinct
 
343
 * implementation of triangle vs. quadrilateral tessellation here. */
 
344
cairo_status_t
 
345
_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
 
346
                                  const cairo_point_t t[3])
 
347
{
 
348
    cairo_point_t quad[4];
 
349
 
 
350
    quad[0] = t[0];
 
351
    quad[1] = t[0];
 
352
    quad[2] = t[1];
 
353
    quad[3] = t[2];
 
354
 
 
355
    return _cairo_traps_tessellate_convex_quad (traps, quad);
 
356
}
 
357
 
 
358
cairo_status_t
 
359
_cairo_traps_tessellate_rectangle (cairo_traps_t *traps,
 
360
                                   const cairo_point_t *top_left,
 
361
                                   const cairo_point_t *bottom_right)
 
362
{
 
363
    cairo_line_t left;
 
364
    cairo_line_t right;
 
365
 
 
366
     left.p1.x =  left.p2.x = top_left->x;
 
367
     left.p1.y = right.p1.y = top_left->y;
 
368
    right.p1.x = right.p2.x = bottom_right->x;
 
369
     left.p2.y = right.p2.y = bottom_right->y;
 
370
 
 
371
    _cairo_traps_add_trap (traps, top_left->y, bottom_right->y, &left, &right);
 
372
 
 
373
    return traps->status;
 
374
}
 
375
 
 
376
cairo_status_t
 
377
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
 
378
                                     const cairo_point_t q[4])
 
379
{
 
380
    int a, b, c, d;
 
381
    int i;
 
382
    cairo_slope_t ab, ad;
 
383
    cairo_bool_t b_left_of_d;
 
384
    cairo_line_t left;
 
385
    cairo_line_t right;
 
386
 
 
387
    /* Choose a as a point with minimal y */
 
388
    a = 0;
 
389
    for (i = 1; i < 4; i++)
 
390
        if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0)
 
391
            a = i;
 
392
 
 
393
    /* b and d are adjacent to a, while c is opposite */
 
394
    b = (a + 1) % 4;
 
395
    c = (a + 2) % 4;
 
396
    d = (a + 3) % 4;
 
397
 
 
398
    /* Choose between b and d so that b.y is less than d.y */
 
399
    if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) {
 
400
        b = (a + 3) % 4;
 
401
        d = (a + 1) % 4;
 
402
    }
 
403
 
 
404
    /* Without freedom left to choose anything else, we have four
 
405
     * cases to tessellate.
 
406
     *
 
407
     * First, we have to determine the Y-axis sort of the four
 
408
     * vertices, (either abcd or abdc). After that we need to detemine
 
409
     * which edges will be "left" and which will be "right" in the
 
410
     * resulting trapezoids. This can be determined by computing a
 
411
     * slope comparison of ab and ad to determine if b is left of d or
 
412
     * not.
 
413
     *
 
414
     * Note that "left of" here is in the sense of which edges should
 
415
     * be the left vs. right edges of the trapezoid. In particular, b
 
416
     * left of d does *not* mean that b.x is less than d.x.
 
417
     *
 
418
     * This should hopefully be made clear in the lame ASCII art
 
419
     * below. Since the same slope comparison is used in all cases, we
 
420
     * compute it before testing for the Y-value sort. */
 
421
 
 
422
    /* Note: If a == b then the ab slope doesn't give us any
 
423
     * information. In that case, we can replace it with the ac (or
 
424
     * equivalenly the bc) slope which gives us exactly the same
 
425
     * information we need. At worst the names of the identifiers ab
 
426
     * and b_left_of_d are inaccurate in this case, (would be ac, and
 
427
     * c_left_of_d). */
 
428
    if (q[a].x == q[b].x && q[a].y == q[b].y)
 
429
        _cairo_slope_init (&ab, &q[a], &q[c]);
 
430
    else
 
431
        _cairo_slope_init (&ab, &q[a], &q[b]);
 
432
 
 
433
    _cairo_slope_init (&ad, &q[a], &q[d]);
 
434
 
 
435
    b_left_of_d = (_cairo_slope_compare (&ab, &ad) > 0);
 
436
 
 
437
    if (q[c].y <= q[d].y) {
 
438
        if (b_left_of_d) {
 
439
            /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad))
 
440
             *
 
441
             *                      top bot left right
 
442
             *        _a  a  a
 
443
             *      / /  /|  |\      a.y b.y  ab   ad
 
444
             *     b /  b |  b \
 
445
             *    / /   | |   \ \    b.y c.y  bc   ad
 
446
             *   c /    c |    c \
 
447
             *  | /      \|     \ \  c.y d.y  cd   ad
 
448
             *  d         d       d
 
449
             */
 
450
            left.p1  = q[a]; left.p2  = q[b];
 
451
            right.p1 = q[a]; right.p2 = q[d];
 
452
            _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
 
453
            left.p1  = q[b]; left.p2  = q[c];
 
454
            _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
 
455
            left.p1  = q[c]; left.p2  = q[d];
 
456
            _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
 
457
        } else {
 
458
            /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
 
459
             *
 
460
             *       a  a  a_
 
461
             *      /|  |\  \ \     a.y b.y  ad  ab
 
462
             *     / b  | b  \ b
 
463
             *    / /   | |   \ \   b.y c.y  ad  bc
 
464
             *   / c    | c    \ c
 
465
             *  / /     |/      \ | c.y d.y  ad  cd
 
466
             *  d       d         d
 
467
             */
 
468
            left.p1  = q[a]; left.p2  = q[d];
 
469
            right.p1 = q[a]; right.p2 = q[b];
 
470
            _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
 
471
            right.p1 = q[b]; right.p2 = q[c];
 
472
            _cairo_traps_add_trap (traps, q[b].y, q[c].y, &left, &right);
 
473
            right.p1 = q[c]; right.p2 = q[d];
 
474
            _cairo_traps_add_trap (traps, q[c].y, q[d].y, &left, &right);
 
475
        }
 
476
    } else {
 
477
        if (b_left_of_d) {
 
478
            /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad))
 
479
             *
 
480
             *        a   a     a
 
481
             *       //  / \    |\     a.y b.y  ab  ad
 
482
             *     /b/  b   \   b \
 
483
             *    / /    \   \   \ \   b.y d.y  bc  ad
 
484
             *   /d/      \   d   \ d
 
485
             *  //         \ /     \|  d.y c.y  bc  dc
 
486
             *  c           c       c
 
487
             */
 
488
            left.p1  = q[a]; left.p2  = q[b];
 
489
            right.p1 = q[a]; right.p2 = q[d];
 
490
            _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
 
491
            left.p1  = q[b]; left.p2  = q[c];
 
492
            _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
 
493
            right.p1 = q[d]; right.p2 = q[c];
 
494
            _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
 
495
        } else {
 
496
            /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
 
497
             *
 
498
             *      a     a   a
 
499
             *     /|    / \  \\       a.y b.y  ad  ab
 
500
             *    / b   /   b  \b\
 
501
             *   / /   /   /    \ \    b.y d.y  ad  bc
 
502
             *  d /   d   /      \d\
 
503
             *  |/     \ /         \\  d.y c.y  dc  bc
 
504
             *  c       c          c
 
505
             */
 
506
            left.p1  = q[a]; left.p2  = q[d];
 
507
            right.p1 = q[a]; right.p2 = q[b];
 
508
            _cairo_traps_add_trap (traps, q[a].y, q[b].y, &left, &right);
 
509
            right.p1 = q[b]; right.p2 = q[c];
 
510
            _cairo_traps_add_trap (traps, q[b].y, q[d].y, &left, &right);
 
511
            left.p1  = q[d]; left.p2  = q[c];
 
512
            _cairo_traps_add_trap (traps, q[d].y, q[c].y, &left, &right);
 
513
        }
 
514
    }
 
515
 
 
516
    return traps->status;
 
517
}
 
518
 
 
519
static cairo_bool_t
 
520
_cairo_trap_contains (cairo_trapezoid_t *t, cairo_point_t *pt)
 
521
{
 
522
    cairo_slope_t slope_left, slope_pt, slope_right;
 
523
 
 
524
    if (t->top > pt->y)
 
525
        return FALSE;
 
526
    if (t->bottom < pt->y)
 
527
        return FALSE;
 
528
 
 
529
    _cairo_slope_init (&slope_left, &t->left.p1, &t->left.p2);
 
530
    _cairo_slope_init (&slope_pt, &t->left.p1, pt);
 
531
 
 
532
    if (_cairo_slope_compare (&slope_left, &slope_pt) < 0)
 
533
        return FALSE;
 
534
 
 
535
    _cairo_slope_init (&slope_right, &t->right.p1, &t->right.p2);
 
536
    _cairo_slope_init (&slope_pt, &t->right.p1, pt);
 
537
 
 
538
    if (_cairo_slope_compare (&slope_pt, &slope_right) < 0)
 
539
        return FALSE;
 
540
 
 
541
    return TRUE;
 
542
}
 
543
 
 
544
cairo_bool_t
 
545
_cairo_traps_contain (const cairo_traps_t *traps,
 
546
                      double x, double y)
 
547
{
 
548
    int i;
 
549
    cairo_point_t point;
 
550
 
 
551
    point.x = _cairo_fixed_from_double (x);
 
552
    point.y = _cairo_fixed_from_double (y);
 
553
 
 
554
    for (i = 0; i < traps->num_traps; i++) {
 
555
        if (_cairo_trap_contains (&traps->traps[i], &point))
 
556
            return TRUE;
 
557
    }
 
558
 
 
559
    return FALSE;
 
560
}
 
561
 
 
562
void
 
563
_cairo_traps_extents (const cairo_traps_t *traps,
 
564
                      cairo_box_t         *extents)
 
565
{
 
566
    if (traps->num_traps == 0) {
 
567
        extents->p1.x = extents->p1.y = _cairo_fixed_from_int (0);
 
568
        extents->p2.x = extents->p2.y = _cairo_fixed_from_int (0);
 
569
    } else {
 
570
        *extents = traps->extents;
 
571
        if (traps->has_limits) {
 
572
            /* clip the traps to the imposed limits */
 
573
            if (extents->p1.x < traps->limits.p1.x)
 
574
                extents->p1.x = traps->limits.p1.x;
 
575
            if (extents->p2.x > traps->limits.p2.x)
 
576
                extents->p2.x = traps->limits.p2.x;
 
577
 
 
578
            if (extents->p1.y < traps->limits.p1.y)
 
579
                extents->p1.y = traps->limits.p1.y;
 
580
            if (extents->p2.y > traps->limits.p2.y)
 
581
                extents->p2.y = traps->limits.p2.y;
 
582
        }
 
583
    }
 
584
}
 
585
 
 
586
/**
 
587
 * _cairo_traps_extract_region:
 
588
 * @traps: a #cairo_traps_t
 
589
 * @region: a #cairo_region_t
 
590
 *
 
591
 * Determines if a set of trapezoids are exactly representable as a
 
592
 * cairo region.  If so, the passed-in region is initialized to
 
593
 * the area representing the given traps.  It should be finalized
 
594
 * with _cairo_region_fini().  If not, %CAIRO_INT_STATUS_UNSUPPORTED
 
595
 * is returned.
 
596
 *
 
597
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
 
598
 * or %CAIRO_STATUS_NO_MEMORY
 
599
 **/
 
600
cairo_int_status_t
 
601
_cairo_traps_extract_region (const cairo_traps_t  *traps,
 
602
                             cairo_region_t       *region)
 
603
{
 
604
    cairo_box_int_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (cairo_box_int_t)];
 
605
    cairo_box_int_t *boxes = stack_boxes;
 
606
    int i, box_count;
 
607
    cairo_int_status_t status;
 
608
 
 
609
    for (i = 0; i < traps->num_traps; i++)
 
610
        if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x
 
611
              && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x
 
612
              && _cairo_fixed_is_integer(traps->traps[i].top)
 
613
              && _cairo_fixed_is_integer(traps->traps[i].bottom)
 
614
              && _cairo_fixed_is_integer(traps->traps[i].left.p1.x)
 
615
              && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) {
 
616
            return CAIRO_INT_STATUS_UNSUPPORTED;
 
617
        }
 
618
 
 
619
    if (traps->num_traps > ARRAY_LENGTH(stack_boxes)) {
 
620
        boxes = _cairo_malloc_ab (traps->num_traps, sizeof(cairo_box_int_t));
 
621
 
 
622
        if (boxes == NULL)
 
623
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
624
    }
 
625
 
 
626
    box_count = 0;
 
627
 
 
628
    for (i = 0; i < traps->num_traps; i++) {
 
629
        int x1 = _cairo_fixed_integer_part(traps->traps[i].left.p1.x);
 
630
        int y1 = _cairo_fixed_integer_part(traps->traps[i].top);
 
631
        int x2 = _cairo_fixed_integer_part(traps->traps[i].right.p1.x);
 
632
        int y2 = _cairo_fixed_integer_part(traps->traps[i].bottom);
 
633
 
 
634
        /* XXX: Sometimes we get degenerate trapezoids from the tesellator;
 
635
         * skip these.
 
636
         */
 
637
        if (x1 == x2 || y1 == y2)
 
638
            continue;
 
639
 
 
640
        boxes[box_count].p1.x = x1;
 
641
        boxes[box_count].p1.y = y1;
 
642
        boxes[box_count].p2.x = x2;
 
643
        boxes[box_count].p2.y = y2;
 
644
 
 
645
        box_count++;
 
646
    }
 
647
 
 
648
    status = _cairo_region_init_boxes (region, boxes, box_count);
 
649
 
 
650
    if (boxes != stack_boxes)
 
651
        free (boxes);
 
652
 
 
653
    if (status)
 
654
        _cairo_region_fini (region);
 
655
 
 
656
    return status;
 
657
}
 
658
 
 
659
/* moves trap points such that they become the actual corners of the trapezoid */
 
660
static void
 
661
_sanitize_trap (cairo_trapezoid_t *t)
 
662
{
 
663
    cairo_trapezoid_t s = *t;
 
664
 
 
665
#define FIX(lr, tb, p) \
 
666
    if (t->lr.p.y != t->tb) { \
 
667
        t->lr.p.x = s.lr.p2.x + _cairo_fixed_mul_div (s.lr.p1.x - s.lr.p2.x, s.tb - s.lr.p2.y, s.lr.p1.y - s.lr.p2.y); \
 
668
        t->lr.p.y = s.tb; \
 
669
    }
 
670
    FIX (left,  top,    p1);
 
671
    FIX (left,  bottom, p2);
 
672
    FIX (right, top,    p1);
 
673
    FIX (right, bottom, p2);
 
674
}
 
675
 
 
676
cairo_private cairo_status_t
 
677
_cairo_traps_path (const cairo_traps_t *traps,
 
678
                   cairo_path_fixed_t  *path)
 
679
{
 
680
    int i;
 
681
 
 
682
    for (i = 0; i < traps->num_traps; i++) {
 
683
        cairo_status_t status;
 
684
        cairo_trapezoid_t trap = traps->traps[i];
 
685
 
 
686
        if (trap.top == trap.bottom)
 
687
            continue;
 
688
 
 
689
        _sanitize_trap (&trap);
 
690
 
 
691
        status = _cairo_path_fixed_move_to (path, trap.left.p1.x, trap.top);
 
692
        if (status) return status;
 
693
        status = _cairo_path_fixed_line_to (path, trap.right.p1.x, trap.top);
 
694
        if (status) return status;
 
695
        status = _cairo_path_fixed_line_to (path, trap.right.p2.x, trap.bottom);
 
696
        if (status) return status;
 
697
        status = _cairo_path_fixed_line_to (path, trap.left.p2.x, trap.bottom);
 
698
        if (status) return status;
 
699
        status = _cairo_path_fixed_close_path (path);
 
700
        if (status) return status;
 
701
    }
 
702
 
 
703
    return CAIRO_STATUS_SUCCESS;
 
704
}