Subversion Repositories Kolibri OS

Rev

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

Rev 1892 Rev 3959
Line 37... Line 37...
37
 * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth
37
 * 2002-07-15: Converted from XRenderCompositeDoublePoly to #cairo_trap_t. Carl D. Worth
38
 */
38
 */
Line 39... Line 39...
39
 
39
 
Line -... Line 40...
-
 
40
#include "cairoint.h"
40
#include "cairoint.h"
41
 
41
 
42
#include "cairo-box-inline.h"
42
#include "cairo-boxes-private.h"
43
#include "cairo-boxes-private.h"
43
#include "cairo-error-private.h"
44
#include "cairo-error-private.h"
-
 
45
#include "cairo-region-private.h"
-
 
46
#include "cairo-slope-private.h"
Line 44... Line 47...
44
#include "cairo-region-private.h"
47
#include "cairo-traps-private.h"
Line 45... Line 48...
45
#include "cairo-slope-private.h"
48
#include "cairo-spans-private.h"
46
 
49
 
Line 69... Line 72...
69
void
72
void
70
_cairo_traps_limit (cairo_traps_t	*traps,
73
_cairo_traps_limit (cairo_traps_t	*traps,
71
		    const cairo_box_t	*limits,
74
		    const cairo_box_t	*limits,
72
		    int			 num_limits)
75
		    int			 num_limits)
73
{
76
{
-
 
77
    int i;
-
 
78
 
74
    traps->limits = limits;
79
    traps->limits = limits;
75
    traps->num_limits = num_limits;
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]);
-
 
85
}
-
 
86
 
-
 
87
void
-
 
88
_cairo_traps_init_with_clip (cairo_traps_t *traps,
-
 
89
			     const cairo_clip_t *clip)
-
 
90
{
-
 
91
    _cairo_traps_init (traps);
-
 
92
    if (clip)
-
 
93
	_cairo_traps_limit (traps, clip->boxes, clip->num_boxes);
76
}
94
}
Line 77... Line 95...
77
 
95
 
78
void
96
void
79
_cairo_traps_clear (cairo_traps_t *traps)
97
_cairo_traps_clear (cairo_traps_t *traps)
Line 145... Line 163...
145
    trap->bottom = bottom;
163
    trap->bottom = bottom;
146
    trap->left = *left;
164
    trap->left = *left;
147
    trap->right = *right;
165
    trap->right = *right;
148
}
166
}
Line -... Line 167...
-
 
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
 
149
 
406
 
150
/**
407
/**
151
 * _cairo_traps_init_box:
408
 * _cairo_traps_init_boxes:
152
 * @traps: a #cairo_traps_t
409
 * @traps: a #cairo_traps_t
153
 * @box: an array box that will each be converted to a single trapezoid
410
 * @box: an array box that will each be converted to a single trapezoid
154
 *       to store in @traps.
411
 *       to store in @traps.
155
 *
412
 *
Line 227... Line 484...
227
 
484
 
228
    if (traps->num_limits) {
485
    if (traps->num_limits) {
229
	cairo_bool_t reversed;
486
	cairo_bool_t reversed;
Line -... Line 487...
-
 
487
	int n;
-
 
488
 
-
 
489
	if (top >= traps->bounds.p2.y || bottom <= traps->bounds.p1.y)
230
	int n;
490
	    return CAIRO_STATUS_SUCCESS;
231
 
491
 
232
	/* support counter-clockwise winding for rectangular tessellation */
492
	/* support counter-clockwise winding for rectangular tessellation */
233
	reversed = top_left->x > bottom_right->x;
493
	reversed = top_left->x > bottom_right->x;
234
	if (reversed) {
494
	if (reversed) {
235
	    right.p1.x = right.p2.x = top_left->x;
495
	    right.p1.x = right.p2.x = top_left->x;
Line -... Line 496...
-
 
496
	    left.p1.x = left.p2.x = bottom_right->x;
-
 
497
	}
-
 
498
 
236
	    left.p1.x = left.p2.x = bottom_right->x;
499
	if (left.p1.x >= traps->bounds.p2.x || right.p1.x <= traps->bounds.p1.x)
237
	}
500
	    return CAIRO_STATUS_SUCCESS;
238
 
501
 
239
	for (n = 0; n < traps->num_limits; n++) {
502
	for (n = 0; n < traps->num_limits; n++) {
Line 483... Line 746...
483
		extents->p2.x = x;
746
		extents->p2.x = x;
484
	}
747
	}
485
    }
748
    }
486
}
749
}
Line -... Line 750...
-
 
750
 
-
 
751
static cairo_bool_t
-
 
752
_mono_edge_is_vertical (const cairo_line_t *line)
-
 
753
{
-
 
754
    return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
-
 
755
}
-
 
756
 
-
 
757
static cairo_bool_t
-
 
758
_traps_are_pixel_aligned (cairo_traps_t *traps,
-
 
759
			  cairo_antialias_t antialias)
-
 
760
{
-
 
761
    int i;
-
 
762
 
-
 
763
    if (antialias == CAIRO_ANTIALIAS_NONE) {
-
 
764
	for (i = 0; i < traps->num_traps; i++) {
-
 
765
	    if (! _mono_edge_is_vertical (&traps->traps[i].left)   ||
-
 
766
		! _mono_edge_is_vertical (&traps->traps[i].right))
-
 
767
	    {
-
 
768
		traps->maybe_region = FALSE;
-
 
769
		return FALSE;
-
 
770
	    }
-
 
771
	}
-
 
772
    } else {
-
 
773
	for (i = 0; i < traps->num_traps; i++) {
-
 
774
	    if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
-
 
775
		traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
-
 
776
		! _cairo_fixed_is_integer (traps->traps[i].top)          ||
-
 
777
		! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
-
 
778
		! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
-
 
779
		! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
-
 
780
	    {
-
 
781
		traps->maybe_region = FALSE;
-
 
782
		return FALSE;
-
 
783
	    }
-
 
784
	}
-
 
785
    }
-
 
786
 
-
 
787
    return TRUE;
Line 487... Line 788...
487
 
788
}
488
 
789
 
489
/**
790
/**
490
 * _cairo_traps_extract_region:
791
 * _cairo_traps_extract_region:
Line 500... Line 801...
500
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
801
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED
501
 * or %CAIRO_STATUS_NO_MEMORY
802
 * or %CAIRO_STATUS_NO_MEMORY
502
 **/
803
 **/
503
cairo_int_status_t
804
cairo_int_status_t
504
_cairo_traps_extract_region (cairo_traps_t   *traps,
805
_cairo_traps_extract_region (cairo_traps_t   *traps,
-
 
806
			     cairo_antialias_t antialias,
505
			     cairo_region_t **region)
807
			     cairo_region_t **region)
506
{
808
{
507
    cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
809
    cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
508
    cairo_rectangle_int_t *rects = stack_rects;
810
    cairo_rectangle_int_t *rects = stack_rects;
509
    cairo_int_status_t status;
811
    cairo_int_status_t status;
510
    int i, rect_count;
812
    int i, rect_count;
Line 511... Line 813...
511
 
813
 
512
    /* we only treat this a hint... */
814
    /* we only treat this a hint... */
513
    if (! traps->maybe_region)
815
    if (antialias != CAIRO_ANTIALIAS_NONE && ! traps->maybe_region)
Line 514... Line -...
514
	return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
515
 
-
 
516
    for (i = 0; i < traps->num_traps; i++) {
-
 
517
	if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
-
 
518
	    traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
-
 
519
	    ! _cairo_fixed_is_integer (traps->traps[i].top)          ||
-
 
520
	    ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
816
	return CAIRO_INT_STATUS_UNSUPPORTED;
521
	    ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
-
 
522
	    ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
817
 
523
	{
818
    if (! _traps_are_pixel_aligned (traps, antialias)) {
524
	    traps->maybe_region = FALSE;
819
	traps->maybe_region = FALSE;
525
	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
Line 526... Line 820...
526
	}
820
	return CAIRO_INT_STATUS_UNSUPPORTED;
527
    }
821
    }
Line 528... Line 822...
528
 
822
 
529
    if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
823
    if (traps->num_traps > ARRAY_LENGTH (stack_rects)) {
530
	rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
824
	rects = _cairo_malloc_ab (traps->num_traps, sizeof (cairo_rectangle_int_t));
Line 531... Line 825...
531
 
825
 
532
	if (unlikely (rects == NULL))
826
	if (unlikely (rects == NULL))
533
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
534
    }
827
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
535
 
-
 
536
    rect_count = 0;
-
 
Line -... Line 828...
-
 
828
    }
-
 
829
 
-
 
830
    rect_count = 0;
-
 
831
    for (i = 0; i < traps->num_traps; i++) {
-
 
832
	int x1, y1, x2, y2;
-
 
833
 
-
 
834
	if (antialias == CAIRO_ANTIALIAS_NONE) {
-
 
835
	    x1 = _cairo_fixed_integer_round_down (traps->traps[i].left.p1.x);
-
 
836
	    y1 = _cairo_fixed_integer_round_down (traps->traps[i].top);
-
 
837
	    x2 = _cairo_fixed_integer_round_down (traps->traps[i].right.p1.x);
-
 
838
	    y2 = _cairo_fixed_integer_round_down (traps->traps[i].bottom);
-
 
839
	} else {
-
 
840
	    x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
537
    for (i = 0; i < traps->num_traps; i++) {
841
	    y1 = _cairo_fixed_integer_part (traps->traps[i].top);
538
	int x1 = _cairo_fixed_integer_part (traps->traps[i].left.p1.x);
842
	    x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
539
	int y1 = _cairo_fixed_integer_part (traps->traps[i].top);
843
	    y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
540
	int x2 = _cairo_fixed_integer_part (traps->traps[i].right.p1.x);
844
	}
541
	int y2 = _cairo_fixed_integer_part (traps->traps[i].bottom);
-
 
542
 
845
 
543
	rects[rect_count].x = x1;
846
	if (x2 > x1 && y2 > y1) {
-
 
847
	    rects[rect_count].x = x1;
-
 
848
	    rects[rect_count].y = y1;
Line 544... Line 849...
544
	rects[rect_count].y = y1;
849
	    rects[rect_count].width  = x2 - x1;
545
	rects[rect_count].width = x2 - x1;
850
	    rects[rect_count].height = y2 - y1;
Line 546... Line 851...
546
	rects[rect_count].height = y2 - y1;
851
	    rect_count++;
547
 
852
	}
Line 548... Line 853...
548
	rect_count++;
853
    }
549
    }
854
 
Line -... Line 855...
-
 
855
 
-
 
856
    *region = cairo_region_create_rectangles (rects, rect_count);
-
 
857
    status = (*region)->status;
-
 
858
 
-
 
859
    if (rects != stack_rects)
-
 
860
	free (rects);
-
 
861
 
-
 
862
    return status;
-
 
863
}
-
 
864
 
-
 
865
cairo_bool_t
-
 
866
_cairo_traps_to_boxes (cairo_traps_t *traps,
-
 
867
		       cairo_antialias_t antialias,
-
 
868
		       cairo_boxes_t *boxes)
-
 
869
{
-
 
870
    int i;
-
 
871
 
-
 
872
    for (i = 0; i < traps->num_traps; i++) {
-
 
873
	if (traps->traps[i].left.p1.x  != traps->traps[i].left.p2.x ||
-
 
874
	    traps->traps[i].right.p1.x != traps->traps[i].right.p2.x)
-
 
875
	    return FALSE;
-
 
876
    }
-
 
877
 
-
 
878
    _cairo_boxes_init (boxes);
-
 
879
 
-
 
880
    boxes->num_boxes    = traps->num_traps;
-
 
881
    boxes->chunks.base  = (cairo_box_t *) traps->traps;
-
 
882
    boxes->chunks.count = traps->num_traps;
-
 
883
    boxes->chunks.size  = traps->num_traps;
-
 
884
 
-
 
885
    if (antialias != CAIRO_ANTIALIAS_NONE) {
-
 
886
	for (i = 0; i < traps->num_traps; i++) {
-
 
887
	    /* Note the traps and boxes alias so we need to take the local copies first. */
-
 
888
	    cairo_fixed_t x1 = traps->traps[i].left.p1.x;
-
 
889
	    cairo_fixed_t x2 = traps->traps[i].right.p1.x;
-
 
890
	    cairo_fixed_t y1 = traps->traps[i].top;
-
 
891
	    cairo_fixed_t y2 = traps->traps[i].bottom;
-
 
892
 
-
 
893
	    boxes->chunks.base[i].p1.x = x1;
-
 
894
	    boxes->chunks.base[i].p1.y = y1;
-
 
895
	    boxes->chunks.base[i].p2.x = x2;
-
 
896
	    boxes->chunks.base[i].p2.y = y2;
-
 
897
 
-
 
898
	    if (boxes->is_pixel_aligned) {
-
 
899
		boxes->is_pixel_aligned =
-
 
900
		    _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
-
 
901
		    _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
-
 
902
	    }
-
 
903
	}
-
 
904
    } else {
-
 
905
	boxes->is_pixel_aligned = TRUE;
-
 
906
 
-
 
907
	for (i = 0; i < traps->num_traps; i++) {
-
 
908
	    /* Note the traps and boxes alias so we need to take the local copies first. */
-
 
909
	    cairo_fixed_t x1 = traps->traps[i].left.p1.x;
-
 
910
	    cairo_fixed_t x2 = traps->traps[i].right.p1.x;
-
 
911
	    cairo_fixed_t y1 = traps->traps[i].top;
-
 
912
	    cairo_fixed_t y2 = traps->traps[i].bottom;
-
 
913
 
-
 
914
	    /* round down here to match Pixman's behavior when using traps. */
550
 
915
	    boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
551
    *region = cairo_region_create_rectangles (rects, rect_count);
916
	    boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
552
    status = (*region)->status;
917
	    boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
553
 
918
	    boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
554
    if (rects != stack_rects)
919
	}
Line 601... Line 966...
601
	if (unlikely (status)) return status;
966
	if (unlikely (status)) return status;
602
    }
967
    }
Line 603... Line 968...
603
 
968
 
604
    return CAIRO_STATUS_SUCCESS;
969
    return CAIRO_STATUS_SUCCESS;
-
 
970
}
-
 
971
 
-
 
972
void
-
 
973
_cairo_debug_print_traps (FILE *file, const cairo_traps_t *traps)
-
 
974
{
-
 
975
    cairo_box_t extents;
-
 
976
    int n;
-
 
977
 
-
 
978
#if 0
-
 
979
    if (traps->has_limits) {
-
 
980
	printf ("%s: limits=(%d, %d, %d, %d)\n",
-
 
981
		filename,
-
 
982
		traps->limits.p1.x, traps->limits.p1.y,
-
 
983
		traps->limits.p2.x, traps->limits.p2.y);
-
 
984
    }
-
 
985
#endif
-
 
986
 
-
 
987
    _cairo_traps_extents (traps, &extents);
-
 
988
    fprintf (file, "extents=(%d, %d, %d, %d)\n",
-
 
989
	     extents.p1.x, extents.p1.y,
-
 
990
	     extents.p2.x, extents.p2.y);
-
 
991
 
-
 
992
    for (n = 0; n < traps->num_traps; n++) {
-
 
993
	fprintf (file, "%d %d L:(%d, %d), (%d, %d) R:(%d, %d), (%d, %d)\n",
-
 
994
		 traps->traps[n].top,
-
 
995
		 traps->traps[n].bottom,
-
 
996
		 traps->traps[n].left.p1.x,
-
 
997
		 traps->traps[n].left.p1.y,
-
 
998
		 traps->traps[n].left.p2.x,
-
 
999
		 traps->traps[n].left.p2.y,
-
 
1000
		 traps->traps[n].right.p1.x,
-
 
1001
		 traps->traps[n].right.p1.y,
-
 
1002
		 traps->traps[n].right.p2.x,
-
 
1003
		 traps->traps[n].right.p2.y);
-
 
1004
    }
-
 
1005
}
-
 
1006
 
-
 
1007
struct cairo_trap_renderer {
-
 
1008
    cairo_span_renderer_t base;
-
 
1009
    cairo_traps_t *traps;
-
 
1010
};
-
 
1011
 
-
 
1012
static cairo_status_t
-
 
1013
span_to_traps (void *abstract_renderer, int y, int h,
-
 
1014
	       const cairo_half_open_span_t *spans, unsigned num_spans)
-
 
1015
{
-
 
1016
    struct cairo_trap_renderer *r = abstract_renderer;
-
 
1017
    cairo_fixed_t top, bot;
-
 
1018
 
-
 
1019
    if (num_spans == 0)
-
 
1020
	return CAIRO_STATUS_SUCCESS;
-
 
1021
 
-
 
1022
    top = _cairo_fixed_from_int (y);
-
 
1023
    bot = _cairo_fixed_from_int (y + h);
-
 
1024
    do {
-
 
1025
	if (spans[0].coverage) {
-
 
1026
	    cairo_fixed_t x0 = _cairo_fixed_from_int(spans[0].x);
-
 
1027
	    cairo_fixed_t x1 = _cairo_fixed_from_int(spans[1].x);
-
 
1028
	    cairo_line_t left = { { x0, top }, { x0, bot } },
-
 
1029
			 right = { { x1, top }, { x1, bot } };
-
 
1030
	    _cairo_traps_add_trap (r->traps, top, bot, &left, &right);
-
 
1031
	}
-
 
1032
	spans++;
-
 
1033
    } while (--num_spans > 1);
-
 
1034
 
-
 
1035
    return CAIRO_STATUS_SUCCESS;
-
 
1036
}
-
 
1037
 
-
 
1038
cairo_int_status_t
-
 
1039
_cairo_rasterise_polygon_to_traps (cairo_polygon_t			*polygon,
-
 
1040
				   cairo_fill_rule_t			 fill_rule,
-
 
1041
				   cairo_antialias_t			 antialias,
-
 
1042
				   cairo_traps_t *traps)
-
 
1043
{
-
 
1044
    struct cairo_trap_renderer renderer;
-
 
1045
    cairo_scan_converter_t *converter;
-
 
1046
    cairo_int_status_t status;
-
 
1047
    cairo_rectangle_int_t r;
-
 
1048
 
-
 
1049
    TRACE ((stderr, "%s: fill_rule=%d, antialias=%d\n",
-
 
1050
	    __FUNCTION__, fill_rule, antialias));
-
 
1051
    assert(antialias == CAIRO_ANTIALIAS_NONE);
-
 
1052
 
-
 
1053
    renderer.traps = traps;
-
 
1054
    renderer.base.render_rows = span_to_traps;
-
 
1055
 
-
 
1056
    _cairo_box_round_to_rectangle (&polygon->extents, &r);
-
 
1057
    converter = _cairo_mono_scan_converter_create (r.x, r.y,
-
 
1058
						   r.x + r.width,
-
 
1059
						   r.y + r.height,
-
 
1060
						   fill_rule);
-
 
1061
    status = _cairo_mono_scan_converter_add_polygon (converter, polygon);
-
 
1062
    if (likely (status == CAIRO_INT_STATUS_SUCCESS))
-
 
1063
	status = converter->generate (converter, &renderer.base);
-
 
1064
    converter->destroy (converter);
-
 
1065
    return status;