~ubuntu-branches/ubuntu/raring/cairo/raring

« back to all changes in this revision

Viewing changes to src/cairo-traps.c

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2013-01-23 21:19:34 UTC
  • mfrom: (1.3.11) (28.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20130123211934-q9qb538ujcmkliic
Tags: 1.12.10-1ubuntu1
* Merge from Debian, remaining changes:
* debian/patches/server_side_gradients.patch:
  - Don't use server side gradients, most drivers don't handle those and
    are really slow
* debian/control: Add missing libxext-dev dependency to libcairo2-dev.
  Spotted by autopkgtest.
* debian/patches/git_evince_rendering_fix.patch:
  Backport GIT commit to fix a rendering bug in evince
* debian/control, debian/libcairo2.symbols, debian/rules:
  - Disable GL backend due to LP: #725434

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
 
40
40
#include "cairoint.h"
41
41
 
 
42
#include "cairo-box-inline.h"
42
43
#include "cairo-boxes-private.h"
43
44
#include "cairo-error-private.h"
44
45
#include "cairo-region-private.h"
73
74
                    const cairo_box_t   *limits,
74
75
                    int                  num_limits)
75
76
{
 
77
    int i;
 
78
 
76
79
    traps->limits = limits;
77
80
    traps->num_limits = num_limits;
 
81
 
 
82
    traps->bounds = limits[0];
 
83
    for (i = 1; i < num_limits; i++)
 
84
        _cairo_box_add_box (&traps->bounds, &limits[i]);
78
85
}
79
86
 
80
87
void
158
165
    trap->right = *right;
159
166
}
160
167
 
 
168
static void
 
169
_cairo_traps_add_clipped_trap (cairo_traps_t *traps,
 
170
                               cairo_fixed_t _top, cairo_fixed_t _bottom,
 
171
                               cairo_line_t *_left, cairo_line_t *_right)
 
172
{
 
173
    /* Note: With the goofy trapezoid specification, (where an
 
174
     * arbitrary two points on the lines can specified for the left
 
175
     * and right edges), these limit checks would not work in
 
176
     * general. For example, one can imagine a trapezoid entirely
 
177
     * within the limits, but with two points used to specify the left
 
178
     * edge entirely to the right of the limits.  Fortunately, for our
 
179
     * purposes, cairo will never generate such a crazy
 
180
     * trapezoid. Instead, cairo always uses for its points the
 
181
     * extreme positions of the edge that are visible on at least some
 
182
     * trapezoid. With this constraint, it's impossible for both
 
183
     * points to be outside the limits while the relevant edge is
 
184
     * entirely inside the limits.
 
185
     */
 
186
    if (traps->num_limits) {
 
187
        const cairo_box_t *b = &traps->bounds;
 
188
        cairo_fixed_t top = _top, bottom = _bottom;
 
189
        cairo_line_t left = *_left, right = *_right;
 
190
 
 
191
        /* Trivially reject if trapezoid is entirely to the right or
 
192
         * to the left of the limits. */
 
193
        if (left.p1.x >= b->p2.x && left.p2.x >= b->p2.x)
 
194
            return;
 
195
 
 
196
        if (right.p1.x <= b->p1.x && right.p2.x <= b->p1.x)
 
197
            return;
 
198
 
 
199
        /* And reject if the trapezoid is entirely above or below */
 
200
        if (top >= b->p2.y || bottom <= b->p1.y)
 
201
            return;
 
202
 
 
203
        /* Otherwise, clip the trapezoid to the limits. We only clip
 
204
         * where an edge is entirely outside the limits. If we wanted
 
205
         * to be more clever, we could handle cases where a trapezoid
 
206
         * edge intersects the edge of the limits, but that would
 
207
         * require slicing this trapezoid into multiple trapezoids,
 
208
         * and I'm not sure the effort would be worth it. */
 
209
        if (top < b->p1.y)
 
210
            top = b->p1.y;
 
211
 
 
212
        if (bottom > b->p2.y)
 
213
            bottom = b->p2.y;
 
214
 
 
215
        if (left.p1.x <= b->p1.x && left.p2.x <= b->p1.x)
 
216
            left.p1.x = left.p2.x = b->p1.x;
 
217
 
 
218
        if (right.p1.x >= b->p2.x && right.p2.x >= b->p2.x)
 
219
            right.p1.x = right.p2.x = b->p2.x;
 
220
 
 
221
        /* Trivial discards for empty trapezoids that are likely to
 
222
         * be produced by our tessellators (most notably convex_quad
 
223
         * when given a simple rectangle).
 
224
         */
 
225
        if (top >= bottom)
 
226
            return;
 
227
 
 
228
        /* cheap colinearity check */
 
229
        if (right.p1.x <= left.p1.x && right.p1.y == left.p1.y &&
 
230
            right.p2.x <= left.p2.x && right.p2.y == left.p2.y)
 
231
            return;
 
232
 
 
233
        _cairo_traps_add_trap (traps, top, bottom, &left, &right);
 
234
    } else
 
235
        _cairo_traps_add_trap (traps, _top, _bottom, _left, _right);
 
236
}
 
237
 
 
238
static int
 
239
_compare_point_fixed_by_y (const void *av, const void *bv)
 
240
{
 
241
    const cairo_point_t *a = av, *b = bv;
 
242
    int ret = a->y - b->y;
 
243
    if (ret == 0)
 
244
        ret = a->x - b->x;
 
245
    return ret;
 
246
}
 
247
 
 
248
void
 
249
_cairo_traps_tessellate_convex_quad (cairo_traps_t *traps,
 
250
                                     const cairo_point_t q[4])
 
251
{
 
252
    int a, b, c, d;
 
253
    int i;
 
254
    cairo_slope_t ab, ad;
 
255
    cairo_bool_t b_left_of_d;
 
256
    cairo_line_t left;
 
257
    cairo_line_t right;
 
258
 
 
259
    /* Choose a as a point with minimal y */
 
260
    a = 0;
 
261
    for (i = 1; i < 4; i++)
 
262
        if (_compare_point_fixed_by_y (&q[i], &q[a]) < 0)
 
263
            a = i;
 
264
 
 
265
    /* b and d are adjacent to a, while c is opposite */
 
266
    b = (a + 1) % 4;
 
267
    c = (a + 2) % 4;
 
268
    d = (a + 3) % 4;
 
269
 
 
270
    /* Choose between b and d so that b.y is less than d.y */
 
271
    if (_compare_point_fixed_by_y (&q[d], &q[b]) < 0) {
 
272
        b = (a + 3) % 4;
 
273
        d = (a + 1) % 4;
 
274
    }
 
275
 
 
276
    /* Without freedom left to choose anything else, we have four
 
277
     * cases to tessellate.
 
278
     *
 
279
     * First, we have to determine the Y-axis sort of the four
 
280
     * vertices, (either abcd or abdc). After that we need to detemine
 
281
     * which edges will be "left" and which will be "right" in the
 
282
     * resulting trapezoids. This can be determined by computing a
 
283
     * slope comparison of ab and ad to determine if b is left of d or
 
284
     * not.
 
285
     *
 
286
     * Note that "left of" here is in the sense of which edges should
 
287
     * be the left vs. right edges of the trapezoid. In particular, b
 
288
     * left of d does *not* mean that b.x is less than d.x.
 
289
     *
 
290
     * This should hopefully be made clear in the lame ASCII art
 
291
     * below. Since the same slope comparison is used in all cases, we
 
292
     * compute it before testing for the Y-value sort. */
 
293
 
 
294
    /* Note: If a == b then the ab slope doesn't give us any
 
295
     * information. In that case, we can replace it with the ac (or
 
296
     * equivalenly the bc) slope which gives us exactly the same
 
297
     * information we need. At worst the names of the identifiers ab
 
298
     * and b_left_of_d are inaccurate in this case, (would be ac, and
 
299
     * c_left_of_d). */
 
300
    if (q[a].x == q[b].x && q[a].y == q[b].y)
 
301
        _cairo_slope_init (&ab, &q[a], &q[c]);
 
302
    else
 
303
        _cairo_slope_init (&ab, &q[a], &q[b]);
 
304
 
 
305
    _cairo_slope_init (&ad, &q[a], &q[d]);
 
306
 
 
307
    b_left_of_d = _cairo_slope_compare (&ab, &ad) > 0;
 
308
 
 
309
    if (q[c].y <= q[d].y) {
 
310
        if (b_left_of_d) {
 
311
            /* Y-sort is abcd and b is left of d, (slope(ab) > slope (ad))
 
312
             *
 
313
             *                      top bot left right
 
314
             *        _a  a  a
 
315
             *      / /  /|  |\      a.y b.y  ab   ad
 
316
             *     b /  b |  b \
 
317
             *    / /   | |   \ \    b.y c.y  bc   ad
 
318
             *   c /    c |    c \
 
319
             *  | /      \|     \ \  c.y d.y  cd   ad
 
320
             *  d         d       d
 
321
             */
 
322
            left.p1  = q[a]; left.p2  = q[b];
 
323
            right.p1 = q[a]; right.p2 = q[d];
 
324
            _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right);
 
325
            left.p1  = q[b]; left.p2  = q[c];
 
326
            _cairo_traps_add_clipped_trap (traps, q[b].y, q[c].y, &left, &right);
 
327
            left.p1  = q[c]; left.p2  = q[d];
 
328
            _cairo_traps_add_clipped_trap (traps, q[c].y, q[d].y, &left, &right);
 
329
        } else {
 
330
            /* Y-sort is abcd and b is right of d, (slope(ab) <= slope (ad))
 
331
             *
 
332
             *       a  a  a_
 
333
             *      /|  |\  \ \     a.y b.y  ad  ab
 
334
             *     / b  | b  \ b
 
335
             *    / /   | |   \ \   b.y c.y  ad  bc
 
336
             *   / c    | c    \ c
 
337
             *  / /     |/      \ | c.y d.y  ad  cd
 
338
             *  d       d         d
 
339
             */
 
340
            left.p1  = q[a]; left.p2  = q[d];
 
341
            right.p1 = q[a]; right.p2 = q[b];
 
342
            _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right);
 
343
            right.p1 = q[b]; right.p2 = q[c];
 
344
            _cairo_traps_add_clipped_trap (traps, q[b].y, q[c].y, &left, &right);
 
345
            right.p1 = q[c]; right.p2 = q[d];
 
346
            _cairo_traps_add_clipped_trap (traps, q[c].y, q[d].y, &left, &right);
 
347
        }
 
348
    } else {
 
349
        if (b_left_of_d) {
 
350
            /* Y-sort is abdc and b is left of d, (slope (ab) > slope (ad))
 
351
             *
 
352
             *        a   a     a
 
353
             *       //  / \    |\     a.y b.y  ab  ad
 
354
             *     /b/  b   \   b \
 
355
             *    / /    \   \   \ \   b.y d.y  bc  ad
 
356
             *   /d/      \   d   \ d
 
357
             *  //         \ /     \|  d.y c.y  bc  dc
 
358
             *  c           c       c
 
359
             */
 
360
            left.p1  = q[a]; left.p2  = q[b];
 
361
            right.p1 = q[a]; right.p2 = q[d];
 
362
            _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right);
 
363
            left.p1  = q[b]; left.p2  = q[c];
 
364
            _cairo_traps_add_clipped_trap (traps, q[b].y, q[d].y, &left, &right);
 
365
            right.p1 = q[d]; right.p2 = q[c];
 
366
            _cairo_traps_add_clipped_trap (traps, q[d].y, q[c].y, &left, &right);
 
367
        } else {
 
368
            /* Y-sort is abdc and b is right of d, (slope (ab) <= slope (ad))
 
369
             *
 
370
             *      a     a   a
 
371
             *     /|    / \  \\       a.y b.y  ad  ab
 
372
             *    / b   /   b  \b\
 
373
             *   / /   /   /    \ \    b.y d.y  ad  bc
 
374
             *  d /   d   /      \d\
 
375
             *  |/     \ /         \\  d.y c.y  dc  bc
 
376
             *  c       c          c
 
377
             */
 
378
            left.p1  = q[a]; left.p2  = q[d];
 
379
            right.p1 = q[a]; right.p2 = q[b];
 
380
            _cairo_traps_add_clipped_trap (traps, q[a].y, q[b].y, &left, &right);
 
381
            right.p1 = q[b]; right.p2 = q[c];
 
382
            _cairo_traps_add_clipped_trap (traps, q[b].y, q[d].y, &left, &right);
 
383
            left.p1  = q[d]; left.p2  = q[c];
 
384
            _cairo_traps_add_clipped_trap (traps, q[d].y, q[c].y, &left, &right);
 
385
        }
 
386
    }
 
387
}
 
388
 
 
389
/* A triangle is simply a degenerate case of a convex
 
390
 * quadrilateral. We would not benefit from having any distinct
 
391
 * implementation of triangle vs. quadrilateral tessellation here. */
 
392
void
 
393
_cairo_traps_tessellate_triangle (cairo_traps_t *traps,
 
394
                                  const cairo_point_t t[3])
 
395
{
 
396
    cairo_point_t quad[4];
 
397
 
 
398
    quad[0] = t[0];
 
399
    quad[1] = t[0];
 
400
    quad[2] = t[1];
 
401
    quad[3] = t[2];
 
402
 
 
403
    _cairo_traps_tessellate_convex_quad (traps, quad);
 
404
}
 
405
 
 
406
 
161
407
/**
162
408
 * _cairo_traps_init_boxes:
163
409
 * @traps: a #cairo_traps_t
240
486
        cairo_bool_t reversed;
241
487
        int n;
242
488
 
 
489
        if (top >= traps->bounds.p2.y || bottom <= traps->bounds.p1.y)
 
490
            return CAIRO_STATUS_SUCCESS;
 
491
 
243
492
        /* support counter-clockwise winding for rectangular tessellation */
244
493
        reversed = top_left->x > bottom_right->x;
245
494
        if (reversed) {
247
496
            left.p1.x = left.p2.x = bottom_right->x;
248
497
        }
249
498
 
 
499
        if (left.p1.x >= traps->bounds.p2.x || right.p1.x <= traps->bounds.p1.x)
 
500
            return CAIRO_STATUS_SUCCESS;
 
501
 
250
502
        for (n = 0; n < traps->num_limits; n++) {
251
503
            const cairo_box_t *limits = &traps->limits[n];
252
504
            cairo_line_t _left, _right;