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 95... Line 95...
95
 */
95
 */
96
#include "cairoint.h"
96
#include "cairoint.h"
97
#include "cairo-spans-private.h"
97
#include "cairo-spans-private.h"
98
#include "cairo-error-private.h"
98
#include "cairo-error-private.h"
Line 99... Line -...
99
 
-
 
100
#include 
99
 
101
#include 
100
#include 
102
#include 
101
#include 
-
 
102
#include 
Line 103... Line 103...
103
#include 
103
#include 
104
 
104
 
105
/*-------------------------------------------------------------------------
105
/*-------------------------------------------------------------------------
106
 * cairo specific config
106
 * cairo specific config
Line 121... Line 121...
121
/* Set glitter up to use a cairo span renderer to do the coverage
121
/* Set glitter up to use a cairo span renderer to do the coverage
122
 * blitting. */
122
 * blitting. */
123
struct pool;
123
struct pool;
124
struct cell_list;
124
struct cell_list;
Line 125... Line -...
125
 
-
 
126
static glitter_status_t
-
 
127
blit_with_span_renderer(
-
 
128
    struct cell_list		*coverages,
-
 
129
    cairo_span_renderer_t	*span_renderer,
-
 
130
    struct pool			*span_pool,
-
 
131
    int				 y,
-
 
132
    int				 height,
-
 
133
    int				 xmin,
-
 
134
    int				 xmax);
-
 
135
 
-
 
136
static glitter_status_t
-
 
137
blit_empty_with_span_renderer (cairo_span_renderer_t *renderer, int y, int height);
-
 
138
 
-
 
139
#define GLITTER_BLIT_COVERAGES_ARGS \
-
 
140
	cairo_span_renderer_t *span_renderer, \
-
 
141
	struct pool *span_pool
-
 
142
 
-
 
143
#define GLITTER_BLIT_COVERAGES(cells, y, height,xmin, xmax) do {	\
-
 
144
    cairo_status_t status = blit_with_span_renderer (cells,		\
-
 
145
						     span_renderer,	\
-
 
146
						     span_pool,		\
-
 
147
						     y, height,		\
-
 
148
						     xmin, xmax);	\
-
 
149
    if (unlikely (status))						\
-
 
150
	return status;							\
-
 
151
} while (0)
-
 
152
 
-
 
153
#define GLITTER_BLIT_COVERAGES_EMPTY(y, height, xmin, xmax) do {		\
-
 
154
    cairo_status_t status = blit_empty_with_span_renderer (span_renderer, y, height); \
-
 
155
    if (unlikely (status))						\
-
 
156
	return status;							\
-
 
157
} while (0)
-
 
158
 
125
 
159
/*-------------------------------------------------------------------------
126
/*-------------------------------------------------------------------------
160
 * glitter-paths.h
127
 * glitter-paths.h
Line 161... Line 128...
161
 */
128
 */
Line 194... Line 161...
194
glitter_scan_converter_reset(
161
glitter_scan_converter_reset(
195
    glitter_scan_converter_t *converter,
162
    glitter_scan_converter_t *converter,
196
    int xmin, int ymin,
163
    int xmin, int ymin,
197
    int xmax, int ymax);
164
    int xmax, int ymax);
Line 198... Line -...
198
 
-
 
199
/* Add a new polygon edge from pixel (x1,y1) to (x2,y2) to the scan
-
 
200
 * converter.  The coordinates represent pixel positions scaled by
-
 
201
 * 2**GLITTER_PIXEL_BITS.  If this function fails then the scan
-
 
202
 * converter should be reset or destroyed.  Dir must be +1 or -1,
-
 
203
 * with the latter reversing the orientation of the edge. */
-
 
204
I glitter_status_t
-
 
205
glitter_scan_converter_add_edge (glitter_scan_converter_t *converter,
-
 
206
				 const cairo_edge_t *edge);
-
 
207
 
165
 
208
/* Render the polygon in the scan converter to the given A8 format
166
/* Render the polygon in the scan converter to the given A8 format
209
 * image raster.  Only the pixels accessible as pixels[y*stride+x] for
167
 * image raster.  Only the pixels accessible as pixels[y*stride+x] for
210
 * x,y inside the clip box are written to, where xmin <= x < xmax,
168
 * x,y inside the clip box are written to, where xmin <= x < xmax,
211
 * ymin <= y < ymax.  The image is assumed to be clear on input.
169
 * ymin <= y < ymax.  The image is assumed to be clear on input.
212
 *
170
 *
213
 * If nonzero_fill is true then the interior of the polygon is
171
 * If nonzero_fill is true then the interior of the polygon is
214
 * computed with the non-zero fill rule.  Otherwise the even-odd fill
172
 * computed with the non-zero fill rule.  Otherwise the even-odd fill
215
 * rule is used.
173
 * rule is used.
216
 *
174
 *
217
 * The scan converter must be reset or destroyed after this call. */
-
 
218
#ifndef GLITTER_BLIT_COVERAGES_ARGS
-
 
219
# define GLITTER_BLIT_COVERAGES_ARGS unsigned char *raster_pixels, long raster_stride
-
 
220
#endif
-
 
221
I glitter_status_t
-
 
222
glitter_scan_converter_render(
-
 
223
    glitter_scan_converter_t *converter,
-
 
224
    int nonzero_fill,
-
 
Line 225... Line 175...
225
    GLITTER_BLIT_COVERAGES_ARGS);
175
 * The scan converter must be reset or destroyed after this call. */
226
 
176
 
227
/*-------------------------------------------------------------------------
177
/*-------------------------------------------------------------------------
228
 * glitter-paths.c: Implementation internal types
178
 * glitter-paths.c: Implementation internal types
Line 285... Line 235...
285
/* A grid area is a real in [0,1] scaled by 2*GRID_X*GRID_Y.  We want
235
/* A grid area is a real in [0,1] scaled by 2*GRID_X*GRID_Y.  We want
286
 * to be able to represent exactly areas of subpixel trapezoids whose
236
 * to be able to represent exactly areas of subpixel trapezoids whose
287
 * vertices are given in grid scaled coordinates.  The scale factor
237
 * vertices are given in grid scaled coordinates.  The scale factor
288
 * comes from needing to accurately represent the area 0.5*dx*dy of a
238
 * comes from needing to accurately represent the area 0.5*dx*dy of a
289
 * triangle with base dx and height dy in grid scaled numbers. */
239
 * triangle with base dx and height dy in grid scaled numbers. */
290
typedef int grid_area_t;
-
 
291
#define GRID_XY (2*GRID_X*GRID_Y) /* Unit area on the grid. */
240
#define GRID_XY (2*GRID_X*GRID_Y) /* Unit area on the grid. */
Line 292... Line 241...
292
 
241
 
293
/* GRID_AREA_TO_ALPHA(area): map [0,GRID_XY] to [0,255]. */
242
/* GRID_AREA_TO_ALPHA(area): map [0,GRID_XY] to [0,255]. */
294
#if GRID_XY == 510
243
#if GRID_XY == 510
Line 337... Line 286...
337
 * malloc needs to be called to allocate a first real chunk. */
286
 * malloc needs to be called to allocate a first real chunk. */
338
struct pool {
287
struct pool {
339
    /* Chunk we're allocating from. */
288
    /* Chunk we're allocating from. */
340
    struct _pool_chunk *current;
289
    struct _pool_chunk *current;
Line -... Line 290...
-
 
290
 
-
 
291
    jmp_buf *jmp;
341
 
292
 
342
    /* Free list of previously allocated chunks.  All have >= default
293
    /* Free list of previously allocated chunks.  All have >= default
343
     * capacity. */
294
     * capacity. */
Line 344... Line 295...
344
    struct _pool_chunk *first_free;
295
    struct _pool_chunk *first_free;
Line 353... Line 304...
353
};
304
};
Line 354... Line 305...
354
 
305
 
355
/* A polygon edge. */
306
/* A polygon edge. */
356
struct edge {
307
struct edge {
357
    /* Next in y-bucket or active list. */
308
    /* Next in y-bucket or active list. */
-
 
309
    struct edge *next, *prev;
-
 
310
 
-
 
311
    /* Number of subsample rows remaining to scan convert of this
-
 
312
     * edge. */
-
 
313
    grid_scaled_y_t height_left;
-
 
314
 
-
 
315
    /* Original sign of the edge: +1 for downwards, -1 for upwards
-
 
316
     * edges.  */
-
 
317
    int dir;
Line 358... Line 318...
358
    struct edge *next;
318
    int vertical;
359
 
319
 
360
    /* Current x coordinate while the edge is on the active
320
    /* Current x coordinate while the edge is on the active
361
     * list. Initialised to the x coordinate of the top of the
321
     * list. Initialised to the x coordinate of the top of the
Line 375... Line 335...
375
    /* The clipped y of the top of the edge. */
335
    /* The clipped y of the top of the edge. */
376
    grid_scaled_y_t ytop;
336
    grid_scaled_y_t ytop;
Line 377... Line 337...
377
 
337
 
378
    /* y2-y1 after orienting the edge downwards.  */
338
    /* y2-y1 after orienting the edge downwards.  */
379
    grid_scaled_y_t dy;
-
 
380
 
-
 
381
    /* Number of subsample rows remaining to scan convert of this
-
 
382
     * edge. */
-
 
383
    grid_scaled_y_t height_left;
-
 
384
 
-
 
385
    /* Original sign of the edge: +1 for downwards, -1 for upwards
-
 
386
     * edges.  */
-
 
387
    int dir;
-
 
388
    int vertical;
339
    grid_scaled_y_t dy;
Line 389... Line -...
389
};
-
 
390
 
-
 
391
/* Number of subsample rows per y-bucket. Must be GRID_Y. */
-
 
392
#define EDGE_Y_BUCKET_HEIGHT GRID_Y
340
};
Line 393... Line 341...
393
 
341
 
394
#define EDGE_Y_BUCKET_INDEX(y, ymin) (((y) - (ymin))/EDGE_Y_BUCKET_HEIGHT)
342
#define EDGE_Y_BUCKET_INDEX(y, ymin) (((y) - (ymin))/GRID_Y)
395
 
343
 
396
/* A collection of sorted and vertically clipped edges of the polygon.
344
/* A collection of sorted and vertically clipped edges of the polygon.
Line 454... Line 402...
454
 * contribution above and below the intersection point must be
402
 * contribution above and below the intersection point must be
455
 * computed separately. */
403
 * computed separately. */
456
struct cell {
404
struct cell {
457
    struct cell		*next;
405
    struct cell		*next;
458
    int			 x;
406
    int			 x;
459
    grid_area_t		 uncovered_area;
407
    int16_t		 uncovered_area;
460
    grid_scaled_y_t	 covered_height;
408
    int16_t		 covered_height;
461
};
409
};
Line 462... Line 410...
462
 
410
 
463
/* A cell list represents the scan line sparsely as cells ordered by
411
/* A cell list represents the scan line sparsely as cells ordered by
464
 * ascending x.  It is geared towards scanning the cells in order
412
 * ascending x.  It is geared towards scanning the cells in order
465
 * using an internal cursor. */
413
 * using an internal cursor. */
466
struct cell_list {
-
 
467
    /* Points to the left-most cell in the scan line. */
-
 
468
    struct cell *head;
414
struct cell_list {
469
    /* Sentinel node */
415
    /* Sentinel nodes */
470
    struct cell tail;
416
    struct cell head, tail;
471
 
417
 
472
    /* Cursor state for iterating through the cell list.  Points to
-
 
473
     * a pointer to the current cell: either &cell_list->head or the next
-
 
474
     * field of the previous cell. */
418
    /* Cursor state for iterating through the cell list. */
Line 475... Line 419...
475
    struct cell **cursor;
419
    struct cell *cursor, *rewind;
476
 
420
 
477
    /* Cells in the cell list are owned by the cell list and are
421
    /* Cells in the cell list are owned by the cell list and are
478
     * allocated from this pool.  */
422
     * allocated from this pool.  */
Line 489... Line 433...
489
 
433
 
490
/* The active list contains edges in the current scan line ordered by
434
/* The active list contains edges in the current scan line ordered by
491
 * the x-coordinate of the intercept of the edge and the scan line. */
435
 * the x-coordinate of the intercept of the edge and the scan line. */
492
struct active_list {
436
struct active_list {
493
    /* Leftmost edge on the current scan line. */
437
    /* Leftmost edge on the current scan line. */
Line 494... Line 438...
494
    struct edge *head;
438
    struct edge head, tail;
495
 
439
 
496
    /* A lower bound on the height of the active edges is used to
440
    /* A lower bound on the height of the active edges is used to
497
     * estimate how soon some active edge ends.	 We can't advance the
441
     * estimate how soon some active edge ends.	 We can't advance the
498
     * scan conversion by a full pixel row if an edge ends somewhere
442
     * scan conversion by a full pixel row if an edge ends somewhere
-
 
443
     * within it. */
499
     * within it. */
444
    grid_scaled_y_t min_height;
Line 500... Line 445...
500
    grid_scaled_y_t min_height;
445
    int is_vertical;
501
};
446
};
502
 
447
 
503
struct glitter_scan_converter {
448
struct glitter_scan_converter {
Line -... Line 449...
-
 
449
    struct polygon	polygon[1];
-
 
450
    struct active_list	active[1];
-
 
451
    struct cell_list	coverages[1];
504
    struct polygon	polygon[1];
452
 
505
    struct active_list	active[1];
453
    cairo_half_open_span_t *spans;
506
    struct cell_list	coverages[1];
454
    cairo_half_open_span_t spans_embedded[64];
507
 
455
 
Line 539... Line 487...
539
	qr.rem += b;
487
	qr.rem += b;
540
    }
488
    }
541
    return qr;
489
    return qr;
542
}
490
}
Line 543... Line 491...
543
 
491
 
544
static void
492
static struct _pool_chunk *
545
_pool_chunk_init(
493
_pool_chunk_init(
546
    struct _pool_chunk *p,
494
    struct _pool_chunk *p,
547
    struct _pool_chunk *prev_chunk,
495
    struct _pool_chunk *prev_chunk,
548
    size_t capacity)
496
    size_t capacity)
549
{
497
{
550
    p->prev_chunk = prev_chunk;
498
    p->prev_chunk = prev_chunk;
551
    p->size = 0;
499
    p->size = 0;
-
 
500
    p->capacity = capacity;
552
    p->capacity = capacity;
501
    return p;
Line 553... Line 502...
553
}
502
}
554
 
503
 
555
static struct _pool_chunk *
-
 
556
_pool_chunk_create(
-
 
557
    struct _pool_chunk *prev_chunk,
504
static struct _pool_chunk *
558
    size_t size)
505
_pool_chunk_create(struct pool *pool, size_t size)
-
 
506
{
559
{
507
    struct _pool_chunk *p;
560
    struct _pool_chunk *p;
508
 
561
    size_t size_with_head = size + sizeof(struct _pool_chunk);
-
 
562
    if (size_with_head < size)
509
    p = malloc(size + sizeof(struct _pool_chunk));
563
	return NULL;
510
    if (unlikely (NULL == p))
564
    p = malloc(size_with_head);
511
	longjmp (*pool->jmp, _cairo_error (CAIRO_STATUS_NO_MEMORY));
565
    if (p)
-
 
566
	_pool_chunk_init(p, prev_chunk, size);
512
 
Line 567... Line 513...
567
    return p;
513
    return _pool_chunk_init(p, pool->current, size);
568
}
514
}
569
 
515
 
570
static void
516
static void
571
pool_init(
517
pool_init(struct pool *pool,
572
    struct pool *pool,
518
	  jmp_buf *jmp,
-
 
519
	  size_t default_capacity,
573
    size_t default_capacity,
520
	  size_t embedded_capacity)
574
    size_t embedded_capacity)
521
{
575
{
522
    pool->jmp = jmp;
576
    pool->current = pool->sentinel;
523
    pool->current = pool->sentinel;
577
    pool->first_free = NULL;
524
    pool->first_free = NULL;
Line 591... Line 538...
591
	    p = prev;
538
	    p = prev;
592
	}
539
	}
593
	p = pool->first_free;
540
	p = pool->first_free;
594
	pool->first_free = NULL;
541
	pool->first_free = NULL;
595
    } while (NULL != p);
542
    } while (NULL != p);
596
    pool_init(pool, 0, 0);
-
 
597
}
543
}
Line 598... Line 544...
598
 
544
 
599
/* Satisfy an allocation by first allocating a new large enough chunk
545
/* Satisfy an allocation by first allocating a new large enough chunk
600
 * and adding it to the head of the pool's chunk list. This function
546
 * and adding it to the head of the pool's chunk list. This function
Line 621... Line 567...
621
	    pool->first_free = chunk->prev_chunk;
567
	    pool->first_free = chunk->prev_chunk;
622
	    _pool_chunk_init(chunk, pool->current, chunk->capacity);
568
	    _pool_chunk_init(chunk, pool->current, chunk->capacity);
623
	}
569
	}
624
    }
570
    }
Line 625... Line 571...
625
 
571
 
626
    if (NULL == chunk) {
572
    if (NULL == chunk)
627
	chunk = _pool_chunk_create (pool->current, capacity);
-
 
628
	if (unlikely (NULL == chunk))
-
 
629
	    return NULL;
-
 
630
    }
573
	chunk = _pool_chunk_create (pool, capacity);
Line 631... Line 574...
631
    pool->current = chunk;
574
    pool->current = chunk;
632
 
575
 
633
    obj = ((unsigned char*)chunk + sizeof(*chunk) + chunk->size);
576
    obj = ((unsigned char*)chunk + sizeof(*chunk) + chunk->size);
Line 679... Line 622...
679
cell_list_rewind (struct cell_list *cells)
622
cell_list_rewind (struct cell_list *cells)
680
{
623
{
681
    cells->cursor = &cells->head;
624
    cells->cursor = &cells->head;
682
}
625
}
Line 683... Line -...
683
 
-
 
684
/* Rewind the cell list if its cursor has been advanced past x. */
626
 
685
inline static void
627
inline static void
686
cell_list_maybe_rewind (struct cell_list *cells, int x)
628
cell_list_maybe_rewind (struct cell_list *cells, int x)
-
 
629
{
-
 
630
    if (x < cells->cursor->x) {
-
 
631
	cells->cursor = cells->rewind;
687
{
632
	if (x < cells->cursor->x)
-
 
633
	    cells->cursor = &cells->head;
-
 
634
    }
-
 
635
}
688
    struct cell *tail = *cells->cursor;
636
 
-
 
637
inline static void
-
 
638
cell_list_set_rewind (struct cell_list *cells)
689
    if (tail->x > x)
639
{
690
	cell_list_rewind (cells);
640
    cells->rewind = cells->cursor;
Line 691... Line 641...
691
}
641
}
692
 
642
 
693
static void
643
static void
694
cell_list_init(struct cell_list *cells)
644
cell_list_init(struct cell_list *cells, jmp_buf *jmp)
695
{
645
{
696
    pool_init(cells->cell_pool.base,
646
    pool_init(cells->cell_pool.base, jmp,
697
	      256*sizeof(struct cell),
647
	      256*sizeof(struct cell),
698
	      sizeof(cells->cell_pool.embedded));
648
	      sizeof(cells->cell_pool.embedded));
-
 
649
    cells->tail.next = NULL;
699
    cells->tail.next = NULL;
650
    cells->tail.x = INT_MAX;
700
    cells->tail.x = INT_MAX;
651
    cells->head.x = INT_MIN;
701
    cells->head = &cells->tail;
652
    cells->head.next = &cells->tail;
Line 702... Line 653...
702
    cell_list_rewind (cells);
653
    cell_list_rewind (cells);
703
}
654
}
Line 712... Line 663...
712
 * row. */
663
 * row. */
713
inline static void
664
inline static void
714
cell_list_reset (struct cell_list *cells)
665
cell_list_reset (struct cell_list *cells)
715
{
666
{
716
    cell_list_rewind (cells);
667
    cell_list_rewind (cells);
717
    cells->head = &cells->tail;
668
    cells->head.next = &cells->tail;
718
    pool_reset (cells->cell_pool.base);
669
    pool_reset (cells->cell_pool.base);
719
}
670
}
Line 720... Line 671...
720
 
671
 
721
static struct cell *
672
inline static struct cell *
722
cell_list_alloc (struct cell_list *cells,
-
 
723
		 struct cell **cursor,
673
cell_list_alloc (struct cell_list *cells,
724
		 struct cell *tail,
674
		 struct cell *tail,
725
		 int x)
675
		 int x)
726
{
676
{
Line 727... Line 677...
727
    struct cell *cell;
677
    struct cell *cell;
728
 
-
 
729
    cell = pool_alloc (cells->cell_pool.base, sizeof (struct cell));
-
 
730
    if (unlikely (NULL == cell))
-
 
731
	return NULL;
678
 
732
 
679
    cell = pool_alloc (cells->cell_pool.base, sizeof (struct cell));
733
    *cursor = cell;
680
    cell->next = tail->next;
734
    cell->next = tail;
681
    tail->next = cell;
735
    cell->x = x;
-
 
-
 
682
    cell->x = x;
736
    cell->uncovered_area = 0;
683
    *(uint32_t *)&cell->uncovered_area = 0;
737
    cell->covered_height = 0;
684
 
Line 738... Line 685...
738
    return cell;
685
    return cell;
739
}
686
}
Line 744... Line 691...
744
 * cell_list_rewind(). Ownership of the returned cell is retained by
691
 * cell_list_rewind(). Ownership of the returned cell is retained by
745
 * the cell list. */
692
 * the cell list. */
746
inline static struct cell *
693
inline static struct cell *
747
cell_list_find (struct cell_list *cells, int x)
694
cell_list_find (struct cell_list *cells, int x)
748
{
695
{
749
    struct cell **cursor = cells->cursor;
696
    struct cell *tail = cells->cursor;
-
 
697
 
-
 
698
    if (tail->x == x)
750
    struct cell *tail;
699
	return tail;
Line 751... Line 700...
751
 
700
 
752
    while (1) {
701
    while (1) {
753
	UNROLL3({
-
 
754
	    tail = *cursor;
702
	UNROLL3({
755
	    if (tail->x >= x) {
703
		if (tail->next->x > x)
756
		break;
-
 
757
	    }
704
			break;
758
	    cursor = &tail->next;
705
		tail = tail->next;
759
	});
706
	});
760
    }
-
 
Line 761... Line 707...
761
    cells->cursor = cursor;
707
    }
-
 
708
 
762
 
709
    if (tail->x != x)
Line 763... Line -...
763
    if (tail->x == x)
-
 
764
	return tail;
710
	tail = cell_list_alloc (cells, tail, x);
Line 765... Line 711...
765
 
711
    return cells->cursor = tail;
766
    return cell_list_alloc (cells, cursor, tail, x);
712
 
767
}
713
}
Line 775... Line 721...
775
 * except with less function call overhead. */
721
 * except with less function call overhead. */
776
inline static struct cell_pair
722
inline static struct cell_pair
777
cell_list_find_pair(struct cell_list *cells, int x1, int x2)
723
cell_list_find_pair(struct cell_list *cells, int x1, int x2)
778
{
724
{
779
    struct cell_pair pair;
725
    struct cell_pair pair;
780
    struct cell **cursor = cells->cursor;
-
 
781
    struct cell *cell1;
-
 
782
    struct cell *cell2;
-
 
783
    struct cell *newcell;
-
 
Line 784... Line 726...
784
 
726
 
785
    /* Find first cell at x1. */
727
    pair.cell1 = cells->cursor;
786
    while (1) {
728
    while (1) {
787
	UNROLL3({
-
 
788
	    cell1 = *cursor;
729
	UNROLL3({
789
	    if (cell1->x > x1)
730
		if (pair.cell1->next->x > x1)
790
		break;
-
 
791
 
-
 
792
	    if (cell1->x == x1)
-
 
793
		goto found_first;
-
 
794
 
731
			break;
795
	    cursor = &cell1->next;
732
		pair.cell1 = pair.cell1->next;
796
	});
733
	});
-
 
734
    }
-
 
735
    if (pair.cell1->x != x1)
Line 797... Line -...
797
    }
-
 
798
 
-
 
799
    /* New first cell at x1. */
-
 
800
    newcell = pool_alloc (cells->cell_pool.base,
-
 
801
			  sizeof (struct cell));
-
 
802
    if (likely (NULL != newcell)) {
-
 
803
	*cursor = newcell;
-
 
804
	newcell->next = cell1;
-
 
805
	newcell->x = x1;
-
 
806
	newcell->uncovered_area = 0;
-
 
807
	newcell->covered_height = 0;
736
	pair.cell1 = cell_list_alloc (cells, pair.cell1, x1);
808
    }
-
 
809
    cell1 = newcell;
-
 
810
 found_first:
-
 
811
 
737
 
812
    /* Find second cell at x2. */
738
    pair.cell2 = pair.cell1;
813
    while (1) {
-
 
814
	UNROLL3({
739
    while (1) {
815
	    cell2 = *cursor;
740
	UNROLL3({
816
	    if (cell2->x > x2)
-
 
817
		break;
-
 
818
	    if (cell2->x == x2)
741
		if (pair.cell2->next->x > x2)
819
		goto found_second;
742
			break;
820
	    cursor = &cell2->next;
743
		pair.cell2 = pair.cell2->next;
-
 
744
	});
-
 
745
    }
Line 821... Line -...
821
	});
-
 
822
    }
-
 
823
 
-
 
824
    /* New second cell at x2. */
-
 
825
    newcell = pool_alloc (cells->cell_pool.base,
-
 
826
			 sizeof (struct cell));
-
 
827
    if (likely (NULL != newcell)) {
-
 
828
	*cursor = newcell;
-
 
829
	newcell->next = cell2;
-
 
830
	newcell->x = x2;
-
 
831
	newcell->uncovered_area = 0;
-
 
832
	newcell->covered_height = 0;
-
 
833
    }
-
 
834
    cell2 = newcell;
746
    if (pair.cell2->x != x2)
835
 found_second:
-
 
836
 
-
 
837
    cells->cursor = cursor;
747
	pair.cell2 = cell_list_alloc (cells, pair.cell2, x2);
838
    pair.cell1 = cell1;
748
 
Line 839... Line -...
839
    pair.cell2 = cell2;
-
 
840
    return pair;
-
 
841
}
-
 
842
 
-
 
843
/* Add an unbounded subpixel span covering subpixels >= x to the
-
 
844
 * coverage cells. */
-
 
845
static glitter_status_t
-
 
846
cell_list_add_unbounded_subspan (struct cell_list *cells,
-
 
847
				 grid_scaled_x_t x)
-
 
848
{
-
 
849
    struct cell *cell;
-
 
850
    int ix, fx;
-
 
851
 
-
 
852
    GRID_X_TO_INT_FRAC(x, ix, fx);
-
 
853
 
-
 
854
    cell = cell_list_find (cells, ix);
-
 
855
    if (likely (cell != NULL)) {
-
 
856
	cell->uncovered_area += 2*fx;
-
 
857
	cell->covered_height++;
-
 
858
	return GLITTER_STATUS_SUCCESS;
-
 
859
    }
-
 
860
 
749
    cells->cursor = pair.cell2;
861
    return GLITTER_STATUS_NO_MEMORY;
750
    return pair;
862
}
-
 
863
 
751
}
864
/* Add a subpixel span covering [x1, x2) to the coverage cells. */
752
 
865
inline static glitter_status_t
753
/* Add a subpixel span covering [x1, x2) to the coverage cells. */
866
cell_list_add_subspan(
754
inline static void
867
    struct cell_list *cells,
755
cell_list_add_subspan(struct cell_list *cells,
868
    grid_scaled_x_t x1,
756
		      grid_scaled_x_t x1,
Line -... Line 757...
-
 
757
		      grid_scaled_x_t x2)
-
 
758
{
-
 
759
    int ix1, fx1;
869
    grid_scaled_x_t x2)
760
    int ix2, fx2;
870
{
761
 
Line 871... Line 762...
871
    int ix1, fx1;
762
    if (x1 == x2)
872
    int ix2, fx2;
763
	return;
873
 
764
 
874
    GRID_X_TO_INT_FRAC(x1, ix1, fx1);
-
 
875
    GRID_X_TO_INT_FRAC(x2, ix2, fx2);
765
    GRID_X_TO_INT_FRAC(x1, ix1, fx1);
876
 
766
    GRID_X_TO_INT_FRAC(x2, ix2, fx2);
877
    if (ix1 != ix2) {
767
 
878
	struct cell_pair p;
768
    if (ix1 != ix2) {
879
	p = cell_list_find_pair(cells, ix1, ix2);
-
 
880
	if (likely (p.cell1 != NULL && p.cell2 != NULL)) {
-
 
881
	    p.cell1->uncovered_area += 2*fx1;
769
	struct cell_pair p;
882
	    ++p.cell1->covered_height;
770
	p = cell_list_find_pair(cells, ix1, ix2);
883
	    p.cell2->uncovered_area -= 2*fx2;
-
 
884
	    --p.cell2->covered_height;
771
	p.cell1->uncovered_area += 2*fx1;
885
	    return GLITTER_STATUS_SUCCESS;
-
 
886
	}
772
	++p.cell1->covered_height;
887
    } else {
773
	p.cell2->uncovered_area -= 2*fx2;
888
	struct cell *cell = cell_list_find(cells, ix1);
-
 
889
	if (likely (cell != NULL)) {
-
 
Line 890... Line 774...
890
	    cell->uncovered_area += 2*(fx1-fx2);
774
	--p.cell2->covered_height;
891
	    return GLITTER_STATUS_SUCCESS;
775
    } else {
892
	}
776
	struct cell *cell = cell_list_find(cells, ix1);
893
    }
777
	cell->uncovered_area += 2*(fx1-fx2);
Line 909... Line 793...
909
 * 3) No existing edges end mid-row.
793
 * 3) No existing edges end mid-row.
910
 *
794
 *
911
 * This function depends on being called with all edges from the
795
 * This function depends on being called with all edges from the
912
 * active list in the order they appear on the list (i.e. with
796
 * active list in the order they appear on the list (i.e. with
913
 * non-decreasing x-coordinate.)  */
797
 * non-decreasing x-coordinate.)  */
914
static glitter_status_t
798
static void
915
cell_list_render_edge(
-
 
916
    struct cell_list *cells,
799
cell_list_render_edge(struct cell_list *cells,
917
    struct edge *edge,
800
		      struct edge *edge,
918
    int sign)
801
		      int sign)
919
{
802
{
920
    grid_scaled_y_t y1, y2, dy;
803
    grid_scaled_y_t y1, y2, dy;
921
    grid_scaled_x_t dx;
804
    grid_scaled_x_t dx;
Line 942... Line 825...
942
    /* Edge is entirely within a column? */
825
    /* Edge is entirely within a column? */
943
    if (ix1 == ix2) {
826
    if (ix1 == ix2) {
944
	/* We always know that ix1 is >= the cell list cursor in this
827
	/* We always know that ix1 is >= the cell list cursor in this
945
	 * case due to the no-intersections precondition.  */
828
	 * case due to the no-intersections precondition.  */
946
	struct cell *cell = cell_list_find(cells, ix1);
829
	struct cell *cell = cell_list_find(cells, ix1);
947
	if (unlikely (NULL == cell))
-
 
948
	    return GLITTER_STATUS_NO_MEMORY;
-
 
949
 
-
 
950
	cell->covered_height += sign*GRID_Y;
830
	cell->covered_height += sign*GRID_Y;
951
	cell->uncovered_area += sign*(fx1 + fx2)*GRID_Y;
831
	cell->uncovered_area += sign*(fx1 + fx2)*GRID_Y;
952
	return GLITTER_STATUS_SUCCESS;
832
	return;
953
    }
833
    }
Line 954... Line 834...
954
 
834
 
955
    /* Orient the edge left-to-right. */
835
    /* Orient the edge left-to-right. */
956
    dx = x2.quo - x1.quo;
836
    dx = x2.quo - x1.quo;
Line 993... Line 873...
993
	 * within a single column because we've checked before calling
873
	 * within a single column because we've checked before calling
994
	 * this function that the active list order won't change. */
874
	 * this function that the active list order won't change. */
995
	cell_list_maybe_rewind(cells, ix1);
875
	cell_list_maybe_rewind(cells, ix1);
Line 996... Line 876...
996
 
876
 
997
	pair = cell_list_find_pair(cells, ix1, ix1+1);
-
 
998
	if (unlikely (!pair.cell1 || !pair.cell2))
-
 
999
	    return GLITTER_STATUS_NO_MEMORY;
-
 
1000
 
877
	pair = cell_list_find_pair(cells, ix1, ix1+1);
1001
	pair.cell1->uncovered_area += sign*y.quo*(GRID_X + fx1);
878
	pair.cell1->uncovered_area += sign*y.quo*(GRID_X + fx1);
1002
	pair.cell1->covered_height += sign*y.quo;
879
	pair.cell1->covered_height += sign*y.quo;
Line 1003... Line 880...
1003
	y.quo += y1;
880
	y.quo += y1;
Line 1021... Line 898...
1021
		cell->uncovered_area += y_skip*GRID_X;
898
		cell->uncovered_area += y_skip*GRID_X;
1022
		cell->covered_height += y_skip;
899
		cell->covered_height += y_skip;
Line 1023... Line 900...
1023
 
900
 
1024
		++ix1;
901
		++ix1;
1025
		cell = cell_list_find(cells, ix1);
-
 
1026
		if (unlikely (NULL == cell))
-
 
1027
		    return GLITTER_STATUS_NO_MEMORY;
902
		cell = cell_list_find(cells, ix1);
Line 1028... Line 903...
1028
	    } while (ix1 != ix2);
903
	    } while (ix1 != ix2);
1029
 
904
 
1030
	    pair.cell2 = cell;
905
	    pair.cell2 = cell;
1031
	}
906
	}
1032
	pair.cell2->uncovered_area += sign*(y2 - y.quo)*fx2;
907
	pair.cell2->uncovered_area += sign*(y2 - y.quo)*fx2;
1033
	pair.cell2->covered_height += sign*(y2 - y.quo);
-
 
1034
    }
-
 
1035
 
908
	pair.cell2->covered_height += sign*(y2 - y.quo);
Line 1036... Line 909...
1036
    return GLITTER_STATUS_SUCCESS;
909
    }
1037
}
910
}
1038
 
911
 
1039
static void
912
static void
1040
polygon_init (struct polygon *polygon)
913
polygon_init (struct polygon *polygon, jmp_buf *jmp)
1041
{
914
{
1042
    polygon->ymin = polygon->ymax = 0;
915
    polygon->ymin = polygon->ymax = 0;
1043
    polygon->y_buckets = polygon->y_buckets_embedded;
916
    polygon->y_buckets = polygon->y_buckets_embedded;
1044
    pool_init (polygon->edge_pool.base,
917
    pool_init (polygon->edge_pool.base, jmp,
Line 1045... Line 918...
1045
	       8192 - sizeof (struct _pool_chunk),
918
	       8192 - sizeof (struct _pool_chunk),
Line 1062... Line 935...
1062
polygon_reset (struct polygon *polygon,
935
polygon_reset (struct polygon *polygon,
1063
	       grid_scaled_y_t ymin,
936
	       grid_scaled_y_t ymin,
1064
	       grid_scaled_y_t ymax)
937
	       grid_scaled_y_t ymax)
1065
{
938
{
1066
    unsigned h = ymax - ymin;
939
    unsigned h = ymax - ymin;
1067
    unsigned num_buckets = EDGE_Y_BUCKET_INDEX(ymax + EDGE_Y_BUCKET_HEIGHT-1,
940
    unsigned num_buckets = EDGE_Y_BUCKET_INDEX(ymax + GRID_Y-1, ymin);
1068
					       ymin);
-
 
Line 1069... Line 941...
1069
 
941
 
Line 1070... Line 942...
1070
    pool_reset(polygon->edge_pool.base);
942
    pool_reset(polygon->edge_pool.base);
1071
 
943
 
Line 1072... Line 944...
1072
    if (unlikely (h > 0x7FFFFFFFU - EDGE_Y_BUCKET_HEIGHT))
944
    if (unlikely (h > 0x7FFFFFFFU - GRID_Y))
1073
	goto bail_no_mem; /* even if you could, you wouldn't want to. */
945
	goto bail_no_mem; /* even if you could, you wouldn't want to. */
Line 1093... Line 965...
1093
    polygon->ymax = 0;
965
    polygon->ymax = 0;
1094
    return GLITTER_STATUS_NO_MEMORY;
966
    return GLITTER_STATUS_NO_MEMORY;
1095
}
967
}
Line 1096... Line 968...
1096
 
968
 
1097
static void
969
static void
1098
_polygon_insert_edge_into_its_y_bucket(
-
 
1099
    struct polygon *polygon,
970
_polygon_insert_edge_into_its_y_bucket(struct polygon *polygon,
1100
    struct edge *e)
971
				       struct edge *e)
1101
{
972
{
1102
    unsigned ix = EDGE_Y_BUCKET_INDEX(e->ytop, polygon->ymin);
973
    unsigned ix = EDGE_Y_BUCKET_INDEX(e->ytop, polygon->ymin);
1103
    struct edge **ptail = &polygon->y_buckets[ix];
974
    struct edge **ptail = &polygon->y_buckets[ix];
1104
    e->next = *ptail;
975
    e->next = *ptail;
1105
    *ptail = e;
976
    *ptail = e;
Line 1106... Line 977...
1106
}
977
}
1107
 
978
 
1108
inline static glitter_status_t
979
inline static void
1109
polygon_add_edge (struct polygon *polygon,
980
polygon_add_edge (struct polygon *polygon,
1110
		  const cairo_edge_t *edge)
981
		  const cairo_edge_t *edge)
1111
{
982
{
1112
    struct edge *e;
983
    struct edge *e;
1113
    grid_scaled_x_t dx;
984
    grid_scaled_x_t dx;
1114
    grid_scaled_y_t dy;
985
    grid_scaled_y_t dy;
1115
    grid_scaled_y_t ytop, ybot;
986
    grid_scaled_y_t ytop, ybot;
Line 1116... Line -...
1116
    grid_scaled_y_t ymin = polygon->ymin;
-
 
1117
    grid_scaled_y_t ymax = polygon->ymax;
-
 
1118
 
987
    grid_scaled_y_t ymin = polygon->ymin;
1119
    assert (edge->bottom > edge->top);
988
    grid_scaled_y_t ymax = polygon->ymax;
Line 1120... Line 989...
1120
 
989
 
1121
    if (unlikely (edge->top >= ymax || edge->bottom <= ymin))
-
 
1122
	return GLITTER_STATUS_SUCCESS;
-
 
Line 1123... Line 990...
1123
 
990
    if (unlikely (edge->top >= ymax || edge->bottom <= ymin))
1124
    e = pool_alloc (polygon->edge_pool.base, sizeof (struct edge));
991
	return;
1125
    if (unlikely (NULL == e))
992
 
1126
	return GLITTER_STATUS_NO_MEMORY;
993
    e = pool_alloc (polygon->edge_pool.base, sizeof (struct edge));
Line 1164... Line 1031...
1164
 
1031
 
Line 1165... Line 1032...
1165
    _polygon_insert_edge_into_its_y_bucket (polygon, e);
1032
    _polygon_insert_edge_into_its_y_bucket (polygon, e);
1166
 
1033
 
1167
    e->x.rem -= dy;		/* Bias the remainder for faster
-
 
1168
				 * edge advancement. */
1034
    e->x.rem -= dy;		/* Bias the remainder for faster
Line 1169... Line 1035...
1169
    return GLITTER_STATUS_SUCCESS;
1035
				 * edge advancement. */
1170
}
1036
}
1171
 
1037
 
-
 
1038
static void
-
 
1039
active_list_reset (struct active_list *active)
-
 
1040
{
1172
static void
1041
    active->head.vertical = 1;
-
 
1042
    active->head.height_left = INT_MAX;
-
 
1043
    active->head.x.quo = INT_MIN;
-
 
1044
    active->head.prev = NULL;
-
 
1045
    active->head.next = &active->tail;
-
 
1046
    active->tail.prev = &active->head;
-
 
1047
    active->tail.next = NULL;
1173
active_list_reset (struct active_list *active)
1048
    active->tail.x.quo = INT_MAX;
-
 
1049
    active->tail.height_left = INT_MAX;
1174
{
1050
    active->tail.vertical = 1;
Line 1175... Line 1051...
1175
    active->head = NULL;
1051
    active->min_height = 0;
1176
    active->min_height = 0;
1052
    active->is_vertical = 1;
1177
}
1053
}
Line 1201... Line 1077...
1201
 * to attach the last non-empty list.
1077
 * to attach the last non-empty list.
1202
 */
1078
 */
1203
static struct edge *
1079
static struct edge *
1204
merge_sorted_edges (struct edge *head_a, struct edge *head_b)
1080
merge_sorted_edges (struct edge *head_a, struct edge *head_b)
1205
{
1081
{
1206
    struct edge *head, **next;
1082
    struct edge *head, **next, *prev;
-
 
1083
    int32_t x;
Line 1207... Line 1084...
1207
 
1084
 
1208
    head = head_a;
1085
    prev = head_a->prev;
-
 
1086
    next = &head;
-
 
1087
    if (head_a->x.quo <= head_b->x.quo) {
-
 
1088
	head = head_a;
-
 
1089
    } else {
-
 
1090
	head = head_b;
-
 
1091
	head_b->prev = prev;
-
 
1092
	goto start_with_b;
Line 1209... Line 1093...
1209
    next = &head;
1093
    }
-
 
1094
 
1210
 
1095
    do {
-
 
1096
	x = head_b->x.quo;
1211
    while (1) {
1097
	while (head_a != NULL && head_a->x.quo <= x) {
1212
	while (head_a != NULL && head_a->x.quo <= head_b->x.quo) {
1098
	    prev = head_a;
1213
	    next = &head_a->next;
1099
	    next = &head_a->next;
Line -... Line 1100...
-
 
1100
	    head_a = head_a->next;
1214
	    head_a = head_a->next;
1101
	}
1215
	}
1102
 
1216
 
1103
	head_b->prev = prev;
Line -... Line 1104...
-
 
1104
	*next = head_b;
-
 
1105
	if (head_a == NULL)
1217
	*next = head_b;
1106
	    return head;
-
 
1107
 
1218
	if (head_a == NULL)
1108
start_with_b:
1219
	    return head;
1109
	x = head_a->x.quo;
1220
 
1110
	while (head_b != NULL && head_b->x.quo <= x) {
Line -... Line 1111...
-
 
1111
	    prev = head_b;
1221
	while (head_b != NULL && head_b->x.quo <= head_a->x.quo) {
1112
	    next = &head_b->next;
1222
	    next = &head_b->next;
1113
	    head_b = head_b->next;
1223
	    head_b = head_b->next;
1114
	}
1224
	}
1115
 
1225
 
1116
	head_a->prev = prev;
Line 1226... Line 1117...
1226
	*next = head_a;
1117
	*next = head_a;
1227
	if (head_b == NULL)
1118
	if (head_b == NULL)
1228
	    return head;
1119
	    return head;
Line 1254... Line 1145...
1254
    struct edge *head_other, *remaining;
1145
    struct edge *head_other, *remaining;
1255
    unsigned int i;
1146
    unsigned int i;
Line 1256... Line 1147...
1256
 
1147
 
Line 1257... Line -...
1257
    head_other = list->next;
-
 
1258
 
1148
    head_other = list->next;
1259
    /* Single element list -> return */
1149
 
1260
    if (head_other == NULL) {
1150
    if (head_other == NULL) {
1261
	*head_out = list;
1151
	*head_out = list;
Line 1262... Line -...
1262
	return NULL;
-
 
1263
    }
-
 
1264
 
-
 
1265
    /* Unroll the first iteration of the following loop (halves the number of calls to merge_sorted_edges):
-
 
1266
     *  - Initialize remaining to be the list containing the elements after the second in the input list.
1152
	return NULL;
1267
     *  - Initialize *head_out to be the sorted list containing the first two element.
1153
    }
1268
     */
1154
 
1269
    remaining = head_other->next;
-
 
1270
    if (list->x.quo <= head_other->x.quo) {
1155
    remaining = head_other->next;
1271
	*head_out = list;
1156
    if (list->x.quo <= head_other->x.quo) {
1272
	/* list->next = head_other; */ /* The input list is already like this. */
1157
	*head_out = list;
-
 
1158
	head_other->next = NULL;
1273
	head_other->next = NULL;
1159
    } else {
-
 
1160
	*head_out = head_other;
1274
    } else {
1161
	head_other->prev = list->prev;
1275
	*head_out = head_other;
1162
	head_other->next = list;
Line 1276... Line 1163...
1276
	head_other->next = list;
1163
	list->prev = head_other;
1277
	list->next = NULL;
-
 
1278
    }
-
 
1279
 
1164
	list->next = NULL;
1280
    for (i = 0; i < level && remaining; i++) {
1165
    }
1281
	/* Extract a sorted list of the same size as *head_out
1166
 
Line 1282... Line -...
1282
	 * (2^(i+1) elements) from the list of remaining elements. */
-
 
1283
	remaining = sort_edges (remaining, i, &head_other);
-
 
1284
	*head_out = merge_sorted_edges (*head_out, head_other);
1167
    for (i = 0; i < level && remaining; i++) {
1285
    }
1168
	remaining = sort_edges (remaining, i, &head_other);
Line -... Line 1169...
-
 
1169
	*head_out = merge_sorted_edges (*head_out, head_other);
-
 
1170
    }
-
 
1171
 
-
 
1172
    return remaining;
-
 
1173
}
-
 
1174
 
-
 
1175
 static struct edge *
1286
 
1176
merge_unsorted_edges (struct edge *head, struct edge *unsorted)
1287
    /* *head_out now contains (at most) 2^(level+1) elements. */
1177
{
1288
 
1178
    sort_edges (unsorted, UINT_MAX, &unsorted);
1289
    return remaining;
1179
    return merge_sorted_edges (head, unsorted);
1290
}
1180
}
1291
 
1181
 
1292
/* Test if the edges on the active list can be safely advanced by a
1182
/* Test if the edges on the active list can be safely advanced by a
Line 1293... Line 1183...
1293
 * full row without intersections or any edges ending. */
1183
 * full row without intersections or any edges ending. */
1294
inline static int
1184
inline static int
1295
active_list_can_step_full_row (struct active_list *active)
1185
can_do_full_row (struct active_list *active)
1296
{
1186
{
-
 
1187
    const struct edge *e;
Line 1297... Line 1188...
1297
    const struct edge *e;
1188
    int prev_x = INT_MIN;
1298
    int prev_x = INT_MIN;
1189
 
1299
 
1190
    /* Recomputes the minimum height of all edges on the active
1300
    /* Recomputes the minimum height of all edges on the active
1191
     * list if we have been dropping edges. */
-
 
1192
    if (active->min_height <= 0) {
1301
     * list if we have been dropping edges. */
1193
	int min_height = INT_MAX;
1302
    if (active->min_height <= 0) {
1194
	int is_vertical = 1;
Line -... Line 1195...
-
 
1195
 
1303
	int min_height = INT_MAX;
1196
	e = active->head.next;
1304
 
1197
	while (NULL != e) {
Line 1305... Line 1198...
1305
	e = active->head;
1198
	    if (e->height_left < min_height)
1306
	while (NULL != e) {
1199
		min_height = e->height_left;
Line 1307... Line 1200...
1307
	    if (e->height_left < min_height)
1200
	    is_vertical &= e->vertical;
1308
		min_height = e->height_left;
1201
	    e = e->next;
1309
	    e = e->next;
-
 
1310
	}
1202
	}
Line 1311... Line 1203...
1311
 
1203
 
1312
	active->min_height = min_height;
1204
	active->is_vertical = is_vertical;
1313
    }
1205
	active->min_height = min_height;
1314
 
1206
    }
1315
    if (active->min_height < GRID_Y)
1207
 
1316
	return 0;
1208
    if (active->min_height < GRID_Y)
Line 1317... Line 1209...
1317
 
1209
	return 0;
1318
    /* Check for intersections as no edges end during the next row. */
1210
 
Line 1319... Line 1211...
1319
    e = active->head;
1211
    /* Check for intersections as no edges end during the next row. */
1320
    while (NULL != e) {
-
 
1321
	struct quorem x = e->x;
1212
    for (e = active->head.next; e != &active->tail; e = e->next) {
Line 1322... Line 1213...
1322
 
1213
	struct quorem x = e->x;
1323
	if (! e->vertical) {
1214
 
Line 1324... Line 1215...
1324
	    x.quo += e->dxdy_full.quo;
1215
	if (! e->vertical) {
1325
	    x.rem += e->dxdy_full.rem;
1216
	    x.quo += e->dxdy_full.quo;
1326
	    if (x.rem >= 0)
1217
	    x.rem += e->dxdy_full.rem;
1327
		++x.quo;
1218
	    if (x.rem >= 0)
1328
	}
-
 
1329
 
-
 
1330
	if (x.quo <= prev_x)
1219
		++x.quo;
1331
	    return 0;
1220
	}
1332
 
1221
 
1333
	prev_x = x.quo;
-
 
1334
	e = e->next;
-
 
1335
    }
-
 
1336
 
-
 
1337
    return 1;
-
 
-
 
1222
	if (x.quo < prev_x)
Line -... Line 1223...
-
 
1223
	    return 0;
-
 
1224
 
-
 
1225
	prev_x = x.quo;
1338
}
1226
    }
1339
 
1227
 
-
 
1228
    return 1;
-
 
1229
}
1340
/* Merges edges on the given subpixel row from the polygon to the
1230
 
Line -... Line 1231...
-
 
1231
/* Merges edges on the given subpixel row from the polygon to the
-
 
1232
 * active_list. */
1341
 * active_list. */
1233
inline static void
-
 
1234
active_list_merge_edges_from_bucket(struct active_list *active,
1342
inline static void
1235
				    struct edge *edges)
1343
active_list_merge_edges_from_polygon(
1236
{
1344
    struct active_list *active,
1237
    active->head.next = merge_unsorted_edges (active->head.next, edges);
-
 
1238
}
1345
    grid_scaled_y_t y,
1239
 
1346
    struct polygon *polygon)
1240
inline static void
1347
{
-
 
1348
    /* Split off the edges on the current subrow and merge them into
1241
polygon_fill_buckets (struct active_list *active,
1349
     * the active list. */
1242
		      struct edge *edge,
1350
    unsigned ix = EDGE_Y_BUCKET_INDEX(y, polygon->ymin);
1243
		      int y,
-
 
1244
		      struct edge **buckets)
1351
    int min_height = active->min_height;
1245
{
1352
    struct edge *subrow_edges = NULL;
-
 
1353
    struct edge **ptail = &polygon->y_buckets[ix];
-
 
1354
 
1246
    grid_scaled_y_t min_height = active->min_height;
1355
    while (1) {
1247
    int is_vertical = active->is_vertical;
1356
	struct edge *tail = *ptail;
-
 
Line 1357... Line -...
1357
	if (NULL == tail) break;
-
 
1358
 
-
 
1359
	if (y == tail->ytop) {
1248
 
1360
	    *ptail = tail->next;
1249
    while (edge) {
1361
	    tail->next = subrow_edges;
1250
	struct edge *next = edge->next;
-
 
1251
	int suby = edge->ytop - y;
1362
	    subrow_edges = tail;
1252
	if (buckets[suby])
1363
	    if (tail->height_left < min_height)
1253
	    buckets[suby]->prev = edge;
1364
		min_height = tail->height_left;
1254
	edge->next = buckets[suby];
1365
	} else {
1255
	edge->prev = NULL;
Line 1366... Line -...
1366
	    ptail = &tail->next;
-
 
1367
	}
1256
	buckets[suby] = edge;
Line 1368... Line -...
1368
    }
-
 
1369
    if (subrow_edges) {
1257
	if (edge->height_left < min_height)
1370
	sort_edges (subrow_edges, UINT_MAX, &subrow_edges);
1258
	    min_height = edge->height_left;
1371
	active->head = merge_sorted_edges (active->head, subrow_edges);
1259
	is_vertical &= edge->vertical;
Line 1372... Line 1260...
1372
	active->min_height = min_height;
1260
	edge = next;
1373
    }
1261
    }
1374
}
1262
 
1375
 
1263
    active->is_vertical = is_vertical;
1376
/* Advance the edges on the active list by one subsample row by
1264
    active->min_height = min_height;
1377
 * updating their x positions.  Drop edges from the list that end. */
1265
}
1378
inline static void
1266
 
Line 1379... Line 1267...
1379
active_list_substep_edges(
1267
inline static void
-
 
1268
sub_row (struct active_list *active,
-
 
1269
	 struct cell_list *coverages,
-
 
1270
	 unsigned int mask)
-
 
1271
{
1380
    struct active_list *active)
1272
    struct edge *edge = active->head.next;
-
 
1273
    int xstart = INT_MIN, prev_x = INT_MIN;
-
 
1274
    int winding = 0;
1381
{
1275
 
-
 
1276
    cell_list_rewind (coverages);
1382
    struct edge **cursor = &active->head;
1277
 
1383
    grid_scaled_x_t prev_x = INT_MIN;
1278
    while (&active->tail != edge) {
1384
    struct edge *unsorted = NULL;
1279
	struct edge *next = edge->next;
1385
 
1280
	int xend = edge->x.quo;
1386
    while (1) {
-
 
1387
	struct edge *edge;
-
 
1388
 
1281
 
-
 
1282
	if (--edge->height_left) {
1389
	UNROLL3({
1283
	    edge->x.quo += edge->dxdy.quo;
1390
	    edge = *cursor;
1284
	    edge->x.rem += edge->dxdy.rem;
1391
	    if (NULL == edge)
-
 
1392
		break;
-
 
1393
 
-
 
1394
	    if (0 != --edge->height_left) {
-
 
1395
		edge->x.quo += edge->dxdy.quo;
-
 
1396
		edge->x.rem += edge->dxdy.rem;
-
 
1397
		if (edge->x.rem >= 0) {
-
 
1398
		    ++edge->x.quo;
-
 
1399
		    edge->x.rem -= edge->dy;
-
 
1400
		}
-
 
1401
 
-
 
1402
		if (edge->x.quo < prev_x) {
-
 
1403
		    *cursor = edge->next;
-
 
1404
		    edge->next = unsorted;
-
 
1405
		    unsorted = edge;
-
 
1406
		} else {
-
 
1407
		    prev_x = edge->x.quo;
-
 
1408
		    cursor = &edge->next;
-
 
1409
		}
-
 
1410
 
-
 
1411
	    } else {
-
 
1412
		*cursor = edge->next;
-
 
1413
	    }
-
 
1414
	});
-
 
1415
    }
-
 
1416
 
-
 
1417
    if (unsorted) {
-
 
1418
	sort_edges (unsorted, UINT_MAX, &unsorted);
-
 
Line 1419... Line 1285...
1419
	active->head = merge_sorted_edges (active->head, unsorted);
1285
	    if (edge->x.rem >= 0) {
-
 
1286
		++edge->x.quo;
1420
    }
1287
		edge->x.rem -= edge->dy;
1421
}
1288
	    }
1422
 
1289
 
1423
inline static glitter_status_t
-
 
1424
apply_nonzero_fill_rule_for_subrow (struct active_list *active,
1290
	    if (edge->x.quo < prev_x) {
-
 
1291
		struct edge *pos = edge->prev;
-
 
1292
		pos->next = next;
Line 1425... Line -...
1425
				    struct cell_list *coverages)
-
 
1426
{
-
 
1427
    struct edge *edge = active->head;
-
 
1428
    int winding = 0;
-
 
1429
    int xstart;
-
 
1430
    int xend;
1293
		next->prev = pos;
1431
    int status;
1294
		do {
1432
 
-
 
1433
    cell_list_rewind (coverages);
-
 
1434
 
1295
		    pos = pos->prev;
Line 1435... Line -...
1435
    while (NULL != edge) {
-
 
1436
	xstart = edge->x.quo;
1296
		} while (edge->x.quo < pos->x.quo);
1437
	winding = edge->dir;
-
 
1438
	while (1) {
1297
		pos->next->prev = edge;
1439
	    edge = edge->next;
-
 
1440
	    if (NULL == edge)
-
 
1441
		return cell_list_add_unbounded_subspan (coverages, xstart);
-
 
1442
 
1298
		edge->next = pos->next;
1443
	    winding += edge->dir;
-
 
1444
	    if (0 == winding) {
-
 
1445
		if (edge->next == NULL || edge->next->x.quo != edge->x.quo)
-
 
1446
		    break;
1299
		edge->prev = pos;
1447
	    }
-
 
1448
	}
-
 
1449
 
-
 
1450
	xend = edge->x.quo;
1300
		pos->next = edge;
1451
	status = cell_list_add_subspan (coverages, xstart, xend);
1301
	    } else
1452
	if (unlikely (status))
-
 
1453
	    return status;
-
 
1454
 
-
 
1455
	edge = edge->next;
-
 
1456
    }
-
 
1457
 
1302
		prev_x = edge->x.quo;
1458
    return GLITTER_STATUS_SUCCESS;
1303
	    active->min_height = -1;
1459
}
-
 
1460
 
-
 
1461
static glitter_status_t
-
 
1462
apply_evenodd_fill_rule_for_subrow (struct active_list *active,
-
 
1463
				    struct cell_list *coverages)
-
 
1464
{
-
 
1465
    struct edge *edge = active->head;
-
 
1466
    int xstart;
1304
	} else {
Line 1467... Line -...
1467
    int xend;
-
 
1468
    int status;
-
 
1469
 
-
 
1470
    cell_list_rewind (coverages);
-
 
1471
 
-
 
1472
    while (NULL != edge) {
1305
	    edge->prev->next = next;
1473
	xstart = edge->x.quo;
-
 
1474
 
-
 
1475
	while (1) {
-
 
1476
	    edge = edge->next;
-
 
1477
	    if (NULL == edge)
-
 
1478
		return cell_list_add_unbounded_subspan (coverages, xstart);
-
 
1479
 
-
 
1480
	    if (edge->next == NULL || edge->next->x.quo != edge->x.quo)
-
 
1481
		break;
-
 
1482
 
-
 
1483
	    edge = edge->next;
-
 
1484
	}
-
 
1485
 
-
 
1486
	xend = edge->x.quo;
-
 
1487
	status = cell_list_add_subspan (coverages, xstart, xend);
-
 
1488
	if (unlikely (status))
-
 
1489
	    return status;
-
 
1490
 
-
 
1491
	edge = edge->next;
-
 
1492
    }
-
 
1493
 
-
 
1494
    return GLITTER_STATUS_SUCCESS;
-
 
1495
}
-
 
1496
 
-
 
1497
static glitter_status_t
-
 
1498
apply_nonzero_fill_rule_and_step_edges (struct active_list *active,
-
 
1499
					struct cell_list *coverages)
-
 
1500
{
-
 
1501
    struct edge **cursor = &active->head;
-
 
1502
    struct edge *left_edge;
-
 
1503
    int status;
-
 
1504
 
1306
	    next->prev = edge->prev;
1505
    left_edge = *cursor;
-
 
1506
    while (NULL != left_edge) {
-
 
1507
	struct edge *right_edge;
-
 
1508
	int winding = left_edge->dir;
-
 
1509
 
1307
	}
1510
	left_edge->height_left -= GRID_Y;
1308
 
1511
	if (left_edge->height_left)
1309
	winding += edge->dir;
1512
	    cursor = &left_edge->next;
1310
	if ((winding & mask) == 0) {
1513
	else
1311
	    if (next->x.quo != xend) {
1514
	    *cursor = left_edge->next;
1312
		cell_list_add_subspan (coverages, xstart, xend);
1515
 
-
 
1516
	while (1) {
-
 
1517
	    right_edge = *cursor;
1313
		xstart = INT_MIN;
1518
	    if (NULL == right_edge)
-
 
1519
		return cell_list_render_edge (coverages, left_edge, +1);
-
 
1520
 
-
 
1521
	    right_edge->height_left -= GRID_Y;
-
 
1522
	    if (right_edge->height_left)
-
 
1523
		cursor = &right_edge->next;
-
 
1524
	    else
-
 
1525
		*cursor = right_edge->next;
-
 
1526
 
-
 
1527
	    winding += right_edge->dir;
-
 
1528
	    if (0 == winding) {
1314
	    }
1529
		if (right_edge->next == NULL ||
-
 
1530
		    right_edge->next->x.quo != right_edge->x.quo)
-
 
1531
		{
1315
	} else if (xstart == INT_MIN)
Line 1532... Line 1316...
1532
		    break;
1316
	    xstart = xend;
1533
		}
1317
 
1534
	    }
1318
	edge = next;
1535
 
-
 
1536
	    if (! right_edge->vertical) {
-
 
1537
		right_edge->x.quo += right_edge->dxdy_full.quo;
-
 
1538
		right_edge->x.rem += right_edge->dxdy_full.rem;
-
 
1539
		if (right_edge->x.rem >= 0) {
-
 
1540
		    ++right_edge->x.quo;
-
 
1541
		    right_edge->x.rem -= right_edge->dy;
-
 
1542
		}
-
 
1543
	    }
-
 
1544
	}
-
 
1545
 
-
 
1546
	status = cell_list_render_edge (coverages, left_edge, +1);
-
 
1547
	if (unlikely (status))
-
 
1548
	    return status;
-
 
1549
 
-
 
1550
	status = cell_list_render_edge (coverages, right_edge, -1);
-
 
1551
	if (unlikely (status))
1319
    }
1552
	    return status;
-
 
1553
 
-
 
1554
	left_edge = *cursor;
-
 
1555
    }
-
 
1556
 
-
 
1557
    return GLITTER_STATUS_SUCCESS;
-
 
1558
}
-
 
1559
 
-
 
1560
static glitter_status_t
-
 
1561
apply_evenodd_fill_rule_and_step_edges (struct active_list *active,
-
 
1562
					struct cell_list *coverages)
-
 
1563
{
1320
}
1564
    struct edge **cursor = &active->head;
-
 
1565
    struct edge *left_edge;
-
 
1566
    int status;
-
 
1567
 
-
 
1568
    left_edge = *cursor;
-
 
1569
    while (NULL != left_edge) {
-
 
1570
	struct edge *right_edge;
-
 
1571
 
-
 
1572
	left_edge->height_left -= GRID_Y;
1321
 
1573
	if (left_edge->height_left)
-
 
1574
	    cursor = &left_edge->next;
-
 
1575
	else
-
 
Line 1576... Line 1322...
1576
	    *cursor = left_edge->next;
1322
inline static void dec (struct active_list *a, struct edge *e, int h)
1577
 
1323
{
1578
	while (1) {
1324
    e->height_left -= h;
Line 1579... Line -...
1579
	    right_edge = *cursor;
-
 
1580
	    if (NULL == right_edge)
1325
    if (e->height_left == 0) {
1581
		return cell_list_render_edge (coverages, left_edge, +1);
-
 
Line 1582... Line 1326...
1582
 
1326
	e->prev->next = e->next;
1583
	    right_edge->height_left -= GRID_Y;
-
 
1584
	    if (right_edge->height_left)
-
 
1585
		cursor = &right_edge->next;
-
 
1586
	    else
-
 
1587
		*cursor = right_edge->next;
-
 
1588
 
-
 
1589
	    if (right_edge->next == NULL ||
-
 
1590
		right_edge->next->x.quo != right_edge->x.quo)
-
 
1591
	    {
-
 
1592
		break;
-
 
1593
	    }
-
 
1594
 
-
 
1595
	    if (! right_edge->vertical) {
-
 
1596
		right_edge->x.quo += right_edge->dxdy_full.quo;
-
 
1597
		right_edge->x.rem += right_edge->dxdy_full.rem;
-
 
1598
		if (right_edge->x.rem >= 0) {
-
 
1599
		    ++right_edge->x.quo;
-
 
1600
		    right_edge->x.rem -= right_edge->dy;
-
 
1601
		}
-
 
1602
	    }
-
 
1603
	}
-
 
1604
 
-
 
1605
	status = cell_list_render_edge (coverages, left_edge, +1);
-
 
1606
	if (unlikely (status))
-
 
1607
	    return status;
-
 
1608
 
-
 
1609
	status = cell_list_render_edge (coverages, right_edge, -1);
-
 
1610
	if (unlikely (status))
1327
	e->next->prev = e->prev;
1611
	    return status;
1328
	a->min_height = -1;
1612
 
-
 
1613
	left_edge = *cursor;
-
 
1614
    }
1329
    }
Line 1615... Line -...
1615
 
-
 
1616
    return GLITTER_STATUS_SUCCESS;
-
 
1617
}
-
 
1618
 
-
 
1619
/* If the user hasn't configured a coverage blitter, use a default one
1330
}
1620
 * that blits spans directly to an A8 raster. */
-
 
1621
#ifndef GLITTER_BLIT_COVERAGES
1331
 
1622
 
-
 
1623
inline static void
-
 
1624
blit_span(
-
 
1625
    unsigned char *row_pixels,
1332
inline static void full_step (struct edge *e)
Line 1626... Line -...
1626
    int x, unsigned len,
-
 
1627
    grid_area_t coverage)
-
 
1628
{
-
 
1629
    int alpha = GRID_AREA_TO_ALPHA(coverage);
-
 
1630
    if (1 == len) {
1333
{
Line 1631... Line -...
1631
	row_pixels[x] = alpha;
-
 
1632
    }
1334
    if (! e->vertical) {
1633
    else {
-
 
1634
	memset(row_pixels + x, alpha, len);
-
 
1635
    }
1335
	e->x.quo += e->dxdy_full.quo;
1636
}
-
 
1637
 
-
 
1638
#define GLITTER_BLIT_COVERAGES(coverages, y, height, xmin, xmax) \
-
 
Line 1639... Line 1336...
1639
    do { \
1336
	e->x.rem += e->dxdy_full.rem;
1640
	int __y = y; \
1337
	if (e->x.rem >= 0) {
1641
	int __h = height; \
-
 
1642
	do { \
1338
	    ++e->x.quo;
1643
	    blit_cells(coverages, raster_pixels + (__y)*raster_stride, xmin, xmax); \
-
 
1644
	} while (--__h); \
-
 
1645
    } while (0)
-
 
Line 1646... Line 1339...
1646
 
1339
	    e->x.rem -= e->dy;
1647
static void
-
 
1648
blit_cells(
1340
	}
1649
    struct cell_list *cells,
1341
    }
1650
    unsigned char *row_pixels,
-
 
Line 1651... Line 1342...
1651
    int xmin, int xmax)
1342
}
1652
{
1343
 
1653
    struct cell *cell = cells->head;
1344
static void
1654
    int prev_x = xmin;
1345
full_row (struct active_list *active,
1655
    int coverage = 0;
1346
	  struct cell_list *coverages,
1656
    if (NULL == cell)
1347
	  unsigned int mask)
1657
	return;
1348
{
1658
 
1349
    struct edge *left = active->head.next;
1659
    while (NULL != cell && cell->x < xmin) {
1350
 
1660
	coverage += cell->covered_height;
1351
    while (&active->tail != left) {
1661
	cell = cell->next;
1352
	struct edge *right;
Line 1662... Line 1353...
1662
    }
1353
	int winding;
1663
    coverage *= GRID_X*2;
1354
 
1664
 
1355
	dec (active, left, GRID_Y);
-
 
1356
 
-
 
1357
	winding = left->dir;
-
 
1358
	right = left->next;
1665
    for (; NULL != cell; cell = cell->next) {
1359
	do {
1666
	int x = cell->x;
1360
	    dec (active, right, GRID_Y);
-
 
1361
 
1667
	int area;
1362
	    winding += right->dir;
1668
	if (x >= xmax)
1363
	    if ((winding & mask) == 0 && right->next->x.quo != right->x.quo)
1669
	    break;
1364
		break;
1670
	if (x > prev_x && 0 != coverage) {
1365
 
1671
	    blit_span(row_pixels, prev_x, x - prev_x, coverage);
1366
	    full_step (right);
Line 1672... Line 1367...
1672
	}
1367
 
1673
 
1368
	    right = right->next;
1674
	coverage += cell->covered_height * GRID_X*2;
1369
	} while (1);
Line 1731... Line 1426...
1731
    glitter_scan_converter_t *converter,
1426
			     glitter_scan_converter_t *converter,
1732
    int xmin, int ymin,
1427
			     int xmin, int ymin,
1733
    int xmax, int ymax)
1428
			     int xmax, int ymax)
1734
{
1429
{
1735
    glitter_status_t status;
1430
    glitter_status_t status;
-
 
1431
    int max_num_spans;
Line 1736... Line 1432...
1736
 
1432
 
1737
    converter->xmin = 0; converter->xmax = 0;
1433
    converter->xmin = 0; converter->xmax = 0;
Line -... Line 1434...
-
 
1434
    converter->ymin = 0; converter->ymax = 0;
-
 
1435
 
-
 
1436
    max_num_spans = xmax - xmin + 1;
-
 
1437
 
-
 
1438
    if (max_num_spans > ARRAY_LENGTH(converter->spans_embedded)) {
-
 
1439
	converter->spans = _cairo_malloc_ab (max_num_spans,
-
 
1440
					     sizeof (cairo_half_open_span_t));
-
 
1441
	if (unlikely (converter->spans == NULL))
-
 
1442
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1443
    } else
1738
    converter->ymin = 0; converter->ymax = 0;
1444
	converter->spans = converter->spans_embedded;
1739
 
1445
 
1740
    xmin = int_to_grid_scaled_x(xmin);
1446
    xmin = int_to_grid_scaled_x(xmin);
1741
    ymin = int_to_grid_scaled_y(ymin);
1447
    ymin = int_to_grid_scaled_y(ymin);
Line 1778... Line 1484...
1778
	long long tmp__ = (long long)(grid_scale) * (in);	\
1484
    long long tmp__ = (long long)(grid_scale) * (in);	\
1779
	tmp__ >>= GLITTER_INPUT_BITS;				\
1485
    tmp__ >>= GLITTER_INPUT_BITS;				\
1780
	(out) = tmp__;						\
1486
    (out) = tmp__;						\
1781
} while (0)
1487
} while (0)
Line -... Line 1488...
-
 
1488
 
-
 
1489
/* Add a new polygon edge from pixel (x1,y1) to (x2,y2) to the scan
-
 
1490
 * converter.  The coordinates represent pixel positions scaled by
-
 
1491
 * 2**GLITTER_PIXEL_BITS.  If this function fails then the scan
-
 
1492
 * converter should be reset or destroyed.  Dir must be +1 or -1,
1782
 
1493
 * with the latter reversing the orientation of the edge. */
1783
I glitter_status_t
1494
I void
1784
glitter_scan_converter_add_edge (glitter_scan_converter_t *converter,
1495
glitter_scan_converter_add_edge (glitter_scan_converter_t *converter,
1785
				 const cairo_edge_t *edge)
1496
				 const cairo_edge_t *edge)
1786
{
1497
{
Line 1787... Line 1498...
1787
    cairo_edge_t e;
1498
    cairo_edge_t e;
1788
 
1499
 
1789
    INPUT_TO_GRID_Y (edge->top, e.top);
1500
    INPUT_TO_GRID_Y (edge->top, e.top);
1790
    INPUT_TO_GRID_Y (edge->bottom, e.bottom);
1501
    INPUT_TO_GRID_Y (edge->bottom, e.bottom);
Line 1791... Line 1502...
1791
    if (e.top >= e.bottom)
1502
    if (e.top >= e.bottom)
1792
	return GLITTER_STATUS_SUCCESS;
1503
	return;
1793
 
1504
 
1794
    /* XXX: possible overflows if GRID_X/Y > 2**GLITTER_INPUT_BITS */
1505
    /* XXX: possible overflows if GRID_X/Y > 2**GLITTER_INPUT_BITS */
1795
    INPUT_TO_GRID_Y (edge->line.p1.y, e.line.p1.y);
1506
    INPUT_TO_GRID_Y (edge->line.p1.y, e.line.p1.y);
Line 1796... Line 1507...
1796
    INPUT_TO_GRID_Y (edge->line.p2.y, e.line.p2.y);
1507
    INPUT_TO_GRID_Y (edge->line.p2.y, e.line.p2.y);
1797
    if (e.line.p1.y == e.line.p2.y)
1508
    if (e.line.p1.y == e.line.p2.y)
Line 1798... Line 1509...
1798
	return GLITTER_STATUS_SUCCESS;
1509
	e.line.p2.y++; /* little fudge to prevent a div-by-zero */
Line 1799... Line 1510...
1799
 
1510
 
1800
    INPUT_TO_GRID_X (edge->line.p1.x, e.line.p1.x);
-
 
1801
    INPUT_TO_GRID_X (edge->line.p2.x, e.line.p2.x);
-
 
1802
 
-
 
1803
    e.dir = edge->dir;
-
 
1804
 
-
 
1805
    return polygon_add_edge (converter->polygon, &e);
-
 
1806
}
-
 
1807
 
-
 
1808
#ifndef GLITTER_BLIT_COVERAGES_BEGIN
-
 
1809
# define GLITTER_BLIT_COVERAGES_BEGIN
-
 
1810
#endif
-
 
1811
 
-
 
1812
#ifndef GLITTER_BLIT_COVERAGES_END
-
 
1813
# define GLITTER_BLIT_COVERAGES_END
-
 
1814
#endif
-
 
1815
 
-
 
1816
#ifndef GLITTER_BLIT_COVERAGES_EMPTY
-
 
1817
# define GLITTER_BLIT_COVERAGES_EMPTY(y0, y1, xmin, xmax)
-
 
1818
#endif
-
 
1819
 
-
 
1820
static cairo_bool_t
-
 
1821
active_list_is_vertical (struct active_list *active)
-
 
1822
{
-
 
1823
    struct edge *e;
-
 
1824
 
-
 
1825
    for (e = active->head; e != NULL; e = e->next) {
1511
    INPUT_TO_GRID_X (edge->line.p1.x, e.line.p1.x);
Line 1826... Line 1512...
1826
	if (! e->vertical)
1512
    INPUT_TO_GRID_X (edge->line.p2.x, e.line.p2.x);
1827
	    return FALSE;
1513
 
1828
    }
1514
    e.dir = edge->dir;
1829
 
-
 
1830
    return TRUE;
1515
 
Line -... Line 1516...
-
 
1516
    polygon_add_edge (converter->polygon, &e);
1831
}
1517
}
1832
 
1518
 
1833
static void
1519
static void
1834
step_edges (struct active_list *active, int count)
1520
step_edges (struct active_list *active, int count)
1835
{
1521
{
1836
    struct edge **cursor = &active->head;
1522
    struct edge *edge;
-
 
1523
 
1837
    struct edge *edge;
1524
    count *= GRID_Y;
1838
 
1525
    for (edge = active->head.next; edge != &active->tail; edge = edge->next) {
Line 1839... Line 1526...
1839
    for (edge = *cursor; edge != NULL; edge = *cursor) {
1526
	edge->height_left -= count;
1840
	edge->height_left -= GRID_Y * count;
1527
	if (! edge->height_left) {
1841
	if (edge->height_left)
1528
	    edge->prev->next = edge->next;
-
 
1529
	    edge->next->prev = edge->prev;
1842
	    cursor = &edge->next;
1530
	    active->min_height = -1;
1843
	else
1531
	}
1844
	    *cursor = edge->next;
1532
    }
1845
    }
-
 
1846
}
-
 
1847
 
-
 
1848
I glitter_status_t
-
 
1849
glitter_scan_converter_render(
-
 
1850
    glitter_scan_converter_t *converter,
-
 
1851
    int nonzero_fill,
1533
}
1852
    GLITTER_BLIT_COVERAGES_ARGS)
-
 
1853
{
-
 
1854
    int i, j;
1534
 
1855
    int ymax_i = converter->ymax / GRID_Y;
1535
static glitter_status_t
1856
    int ymin_i = converter->ymin / GRID_Y;
1536
blit_a8 (struct cell_list *cells,
1857
    int xmin_i, xmax_i;
-
 
1858
    int h = ymax_i - ymin_i;
-
 
1859
    struct polygon *polygon = converter->polygon;
-
 
1860
    struct cell_list *coverages = converter->coverages;
-
 
1861
    struct active_list *active = converter->active;
-
 
1862
 
-
 
1863
    xmin_i = converter->xmin / GRID_X;
-
 
1864
    xmax_i = converter->xmax / GRID_X;
-
 
1865
    if (xmin_i >= xmax_i)
-
 
1866
	return GLITTER_STATUS_SUCCESS;
-
 
1867
 
-
 
Line 1868... Line -...
1868
    /* Let the coverage blitter initialise itself. */
-
 
1869
    GLITTER_BLIT_COVERAGES_BEGIN;
-
 
1870
 
-
 
1871
    /* Render each pixel row. */
1537
	 cairo_span_renderer_t *renderer,
1872
    for (i = 0; i < h; i = j) {
1538
	 cairo_half_open_span_t *spans,
1873
	int do_full_step = 0;
-
 
1874
	glitter_status_t status = 0;
-
 
1875
 
-
 
1876
	j = i + 1;
-
 
Line 1877... Line 1539...
1877
 
1539
	 int y, int height,
-
 
1540
	 int xmin, int xmax)
-
 
1541
{
-
 
1542
    struct cell *cell = cells->head.next;
1878
	/* Determine if we can ignore this row or use the full pixel
1543
    int prev_x = xmin, last_x = -1;
-
 
1544
    int16_t cover = 0, last_cover = 0;
Line 1879... Line -...
1879
	 * stepper. */
-
 
1880
	if (GRID_Y == EDGE_Y_BUCKET_HEIGHT && ! polygon->y_buckets[i]) {
1545
    unsigned num_spans;
1881
	    if (! active->head) {
1546
 
1882
		for (; j < h && ! polygon->y_buckets[j]; j++)
1547
    if (cell == &cells->tail)
1883
		    ;
-
 
1884
		GLITTER_BLIT_COVERAGES_EMPTY (i+ymin_i, j-i, xmin_i, xmax_i);
1548
	return CAIRO_STATUS_SUCCESS;
1885
		continue;
-
 
1886
	    }
1549
 
1887
 
-
 
Line 1888... Line 1550...
1888
	    do_full_step = active_list_can_step_full_row (active);
1550
    /* Skip cells to the left of the clip region. */
1889
	}
-
 
1890
 
1551
    while (cell->x < xmin) {
1891
	if (do_full_step) {
1552
	cover += cell->covered_height;
1892
	    /* Step by a full pixel row's worth. */
-
 
1893
	    if (nonzero_fill) {
1553
	cell = cell->next;
1894
		status = apply_nonzero_fill_rule_and_step_edges (active,
1554
    }
1895
								 coverages);
-
 
1896
	    } else {
1555
    cover *= GRID_X*2;
1897
		status = apply_evenodd_fill_rule_and_step_edges (active,
-
 
1898
								 coverages);
1556
 
1899
	    }
-
 
1900
 
-
 
1901
	    if (active_list_is_vertical (active)) {
-
 
1902
		while (j < h &&
-
 
1903
		       polygon->y_buckets[j] == NULL &&
-
 
1904
		       active->min_height >= 2*GRID_Y)
-
 
Line 1905... Line 1557...
1905
		{
1557
    /* Form the spans from the coverages and areas. */
-
 
1558
    num_spans = 0;
Line 1906... Line 1559...
1906
		    active->min_height -= GRID_Y;
1559
    for (; cell->x < xmax; cell = cell->next) {
-
 
1560
	int x = cell->x;
1907
		    j++;
1561
	int16_t area;
1908
		}
1562
 
1909
		if (j != i + 1)
1563
	if (x > prev_x && cover != last_cover) {
1910
		    step_edges (active, j - (i + 1));
-
 
1911
	    }
1564
	    spans[num_spans].x = prev_x;
1912
	} else {
1565
	    spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
Line 1913... Line -...
1913
	    grid_scaled_y_t suby;
-
 
1914
 
1566
	    last_cover = cover;
1915
	    /* Subsample this row. */
1567
	    last_x = prev_x;
Line 1916... Line 1568...
1916
	    for (suby = 0; suby < GRID_Y; suby++) {
1568
	    ++num_spans;
1917
		grid_scaled_y_t y = (i+ymin_i)*GRID_Y + suby;
1569
	}
1918
 
-
 
1919
		active_list_merge_edges_from_polygon (active, y, polygon);
1570
 
1920
 
1571
	cover += cell->covered_height*GRID_X*2;
1921
		if (nonzero_fill) {
-
 
1922
		    status |= apply_nonzero_fill_rule_for_subrow (active,
1572
	area = cover - cell->uncovered_area;
1923
								  coverages);
-
 
1924
		} else {
1573
 
1925
		    status |= apply_evenodd_fill_rule_for_subrow (active,
-
 
1926
								  coverages);
1574
	if (area != last_cover) {
Line 1927... Line 1575...
1927
		}
1575
	    spans[num_spans].x = x;
1928
 
1576
	    spans[num_spans].coverage = GRID_AREA_TO_ALPHA (area);
1929
		active_list_substep_edges(active);
-
 
1930
	    }
1577
	    last_cover = area;
-
 
1578
	    last_x = x;
1931
	}
1579
	    ++num_spans;
Line 1932... Line -...
1932
 
-
 
1933
	if (unlikely (status))
1580
	}
1934
	    return status;
1581
 
-
 
1582
	prev_x = x+1;
Line -... Line 1583...
-
 
1583
    }
1935
 
1584
 
1936
	GLITTER_BLIT_COVERAGES(coverages, i+ymin_i, j-i, xmin_i, xmax_i);
1585
    if (prev_x <= xmax && cover != last_cover) {
1937
	cell_list_reset (coverages);
1586
	spans[num_spans].x = prev_x;
1938
 
1587
	spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
1939
	if (! active->head)
1588
	last_cover = cover;
1940
	    active->min_height = INT_MAX;
1589
	last_x = prev_x;
1941
	else
1590
	++num_spans;
1942
	    active->min_height -= GRID_Y;
1591
    }
1943
    }
1592
 
1944
 
1593
    if (last_x < xmax && last_cover) {
1945
    /* Clean up the coverage blitter. */
1594
	spans[num_spans].x = xmax;
1946
    GLITTER_BLIT_COVERAGES_END;
1595
	spans[num_spans].coverage = 0;
Line 1947... Line 1596...
1947
 
1596
	++num_spans;
1948
    return GLITTER_STATUS_SUCCESS;
1597
    }
Line 1949... Line 1598...
1949
}
1598
 
1950
 
1599
    /* Dump them into the renderer. */
1951
/*-------------------------------------------------------------------------
1600
    return renderer->render_rows (renderer, y, height, spans, num_spans);
1952
 * cairo specific implementation: the coverage blitter and
1601
}
1953
 * scan converter subclass. */
1602
 
1954
 
1603
#define GRID_AREA_TO_A1(A)  ((GRID_AREA_TO_ALPHA (A) > 127) ? 255 : 0)
Line 1955... Line -...
1955
static glitter_status_t
-
 
1956
blit_with_span_renderer (struct cell_list *cells,
-
 
1957
			 cairo_span_renderer_t *renderer,
-
 
1958
			 struct pool *span_pool,
-
 
1959
			 int y, int height,
-
 
1960
			 int xmin, int xmax)
-
 
1961
{
-
 
1962
    struct cell *cell = cells->head;
-
 
1963
    int prev_x = xmin;
-
 
1964
    int cover = 0;
-
 
1965
    cairo_half_open_span_t *spans;
-
 
1966
    unsigned num_spans;
-
 
1967
 
-
 
1968
    if (cell == NULL)
-
 
1969
	return blit_empty_with_span_renderer (renderer, y, height);
-
 
1970
 
-
 
1971
    /* Skip cells to the left of the clip region. */
-
 
1972
    while (cell != NULL && cell->x < xmin) {
-
 
1973
	cover += cell->covered_height;
-
 
1974
	cell = cell->next;
1604
static glitter_status_t
-
 
1605
blit_a1 (struct cell_list *cells,
1975
    }
1606
	 cairo_span_renderer_t *renderer,
1976
    cover *= GRID_X*2;
1607
	 cairo_half_open_span_t *spans,
1977
 
1608
	 int y, int height,
1978
    /* Count number of cells remaining. */
-
 
1979
    {
-
 
1980
	struct cell *next = cell;
-
 
Line -... Line 1609...
-
 
1609
	 int xmin, int xmax)
1981
	num_spans = 1;
1610
{
1982
	while (next != NULL) {
1611
    struct cell *cell = cells->head.next;
1983
	    next = next->next;
1612
    int prev_x = xmin, last_x = -1;
1984
	    ++num_spans;
1613
    int16_t cover = 0;
1985
	}
1614
    uint8_t coverage, last_cover = 0;
Line 1986... Line 1615...
1986
	num_spans = 2*num_spans;
1615
    unsigned num_spans;
1987
    }
1616
 
Line -... Line 1617...
-
 
1617
    if (cell == &cells->tail)
-
 
1618
	return CAIRO_STATUS_SUCCESS;
1988
 
1619
 
1989
    /* Allocate enough spans for the row. */
1620
    /* Skip cells to the left of the clip region. */
1990
    pool_reset (span_pool);
1621
    while (cell->x < xmin) {
-
 
1622
	cover += cell->covered_height;
Line 1991... Line 1623...
1991
    spans = pool_alloc (span_pool, sizeof(spans[0])*num_spans);
1623
	cell = cell->next;
1992
    if (unlikely (spans == NULL))
1624
    }
Line -... Line 1625...
-
 
1625
    cover *= GRID_X*2;
1993
	return GLITTER_STATUS_NO_MEMORY;
1626
 
1994
 
1627
    /* Form the spans from the coverages and areas. */
1995
    num_spans = 0;
1628
    num_spans = 0;
1996
 
1629
    for (; cell->x < xmax; cell = cell->next) {
1997
    /* Form the spans from the coverages and areas. */
1630
	int x = cell->x;
Line 1998... Line 1631...
1998
    for (; cell != NULL; cell = cell->next) {
1631
	int16_t area;
1999
	int x = cell->x;
1632
 
2000
	int area;
1633
	coverage = GRID_AREA_TO_A1 (cover);
2001
 
1634
	if (x > prev_x && coverage != last_cover) {
2002
	if (x >= xmax)
1635
	    last_x = spans[num_spans].x = prev_x;
-
 
1636
	    last_cover = spans[num_spans].coverage = coverage;
-
 
1637
	    ++num_spans;
Line 2003... Line 1638...
2003
	    break;
1638
	}
2004
 
1639
 
2005
	if (x > prev_x) {
1640
	cover += cell->covered_height*GRID_X*2;
Line -... Line 1641...
-
 
1641
	area = cover - cell->uncovered_area;
-
 
1642
 
-
 
1643
	coverage = GRID_AREA_TO_A1 (area);
-
 
1644
	if (coverage != last_cover) {
2006
	    spans[num_spans].x = prev_x;
1645
	    last_x = spans[num_spans].x = x;
2007
	    spans[num_spans].coverage = GRID_AREA_TO_ALPHA (cover);
1646
	    last_cover = spans[num_spans].coverage = coverage;
2008
	    ++num_spans;
1647
	    ++num_spans;
-
 
1648
	}
-
 
1649
 
-
 
1650
	prev_x = x+1;
-
 
1651
    }
-
 
1652
 
-
 
1653
    coverage = GRID_AREA_TO_A1 (cover);
-
 
1654
    if (prev_x <= xmax && coverage != last_cover) {
-
 
1655
	last_x = spans[num_spans].x = prev_x;
-
 
1656
	last_cover = spans[num_spans].coverage = coverage;
-
 
1657
	++num_spans;
-
 
1658
    }
-
 
1659
 
-
 
1660
    if (last_x < xmax && last_cover) {
-
 
1661
	spans[num_spans].x = xmax;
-
 
1662
	spans[num_spans].coverage = 0;
-
 
1663
	++num_spans;
-
 
1664
    }
-
 
1665
    if (num_spans == 1)
-
 
1666
	return CAIRO_STATUS_SUCCESS;
-
 
1667
 
-
 
1668
    /* Dump them into the renderer. */
-
 
1669
    return renderer->render_rows (renderer, y, height, spans, num_spans);
-
 
1670
}
-
 
1671
 
-
 
1672
 
-
 
1673
I void
-
 
1674
glitter_scan_converter_render(glitter_scan_converter_t *converter,
-
 
1675
			      unsigned int winding_mask,
-
 
1676
			      int antialias,
-
 
1677
			      cairo_span_renderer_t *renderer)
-
 
1678
{
-
 
1679
    int i, j;
-
 
1680
    int ymax_i = converter->ymax / GRID_Y;
-
 
1681
    int ymin_i = converter->ymin / GRID_Y;
-
 
1682
    int xmin_i, xmax_i;
-
 
1683
    int h = ymax_i - ymin_i;
-
 
1684
    struct polygon *polygon = converter->polygon;
-
 
1685
    struct cell_list *coverages = converter->coverages;
-
 
1686
    struct active_list *active = converter->active;
-
 
1687
    struct edge *buckets[GRID_Y] = { 0 };
-
 
1688
 
-
 
1689
    xmin_i = converter->xmin / GRID_X;
-
 
1690
    xmax_i = converter->xmax / GRID_X;
-
 
1691
    if (xmin_i >= xmax_i)
-
 
1692
	return;
-
 
1693
 
-
 
1694
    /* Render each pixel row. */
-
 
1695
    for (i = 0; i < h; i = j) {
-
 
1696
	int do_full_row = 0;
-
 
1697
 
-
 
1698
	j = i + 1;
-
 
1699
 
-
 
1700
	/* Determine if we can ignore this row or use the full pixel
-
 
1701
	 * stepper. */
-
 
1702
	if (! polygon->y_buckets[i]) {
-
 
1703
	    if (active->head.next == &active->tail) {
-
 
1704
		active->min_height = INT_MAX;
-
 
1705
		active->is_vertical = 1;
-
 
1706
		for (; j < h && ! polygon->y_buckets[j]; j++)
-
 
1707
		    ;
-
 
1708
		continue;
-
 
1709
	    }
-
 
1710
 
-
 
1711
	    do_full_row = can_do_full_row (active);
-
 
1712
	}
-
 
1713
 
-
 
1714
	if (do_full_row) {
-
 
1715
	    /* Step by a full pixel row's worth. */
-
 
1716
	    full_row (active, coverages, winding_mask);
-
 
1717
 
-
 
1718
	    if (active->is_vertical) {
-
 
1719
		while (j < h &&
-
 
1720
		       polygon->y_buckets[j] == NULL &&
2009
	}
1721
		       active->min_height >= 2*GRID_Y)
-
 
1722
		{
-
 
1723
		    active->min_height -= GRID_Y;
-
 
1724
		    j++;
-
 
1725
		}
-
 
1726
		if (j != i + 1)
2010
 
1727
		    step_edges (active, j - (i + 1));
Line 2011... Line 1728...
2011
	cover += cell->covered_height*GRID_X*2;
1728
	    }
2012
	area = cover - cell->uncovered_area;
1729
	} else {
Line 2013... Line 1730...
2013
 
1730
	    int sub;
2014
	spans[num_spans].x = x;
1731
 
-
 
1732
	    polygon_fill_buckets (active,
Line 2015... Line -...
2015
	spans[num_spans].coverage = GRID_AREA_TO_ALPHA (area);
-
 
2016
	++num_spans;
-
 
2017
 
-
 
2018
	prev_x = x+1;
1733
				  polygon->y_buckets[i],
2019
    }
1734
				  (i+ymin_i)*GRID_Y,
Line 2020... Line 1735...
2020
 
1735
				  buckets);
Line 2021... Line 1736...
2021
    if (prev_x <= xmax) {
1736
 
Line 2060... Line 1775...
2060
    cairo_tor_scan_converter_t *self = converter;
1775
    cairo_tor_scan_converter_t *self = converter;
2061
    if (self == NULL) {
1776
    if (self == NULL) {
2062
	return;
1777
	return;
2063
    }
1778
    }
2064
    _glitter_scan_converter_fini (self->converter);
1779
    _glitter_scan_converter_fini (self->converter);
2065
    pool_fini (self->span_pool.base);
-
 
2066
    free(self);
1780
    free(self);
2067
}
1781
}
Line 2068... Line 1782...
2068
 
1782
 
2069
static cairo_status_t
-
 
2070
_cairo_tor_scan_converter_add_edge (void		*converter,
-
 
2071
				    const cairo_point_t *p1,
-
 
2072
				    const cairo_point_t *p2,
-
 
2073
				    int top, int bottom,
-
 
2074
				    int dir)
-
 
2075
{
-
 
2076
    cairo_tor_scan_converter_t *self = converter;
-
 
2077
    cairo_status_t status;
-
 
2078
    cairo_edge_t edge;
-
 
2079
 
-
 
2080
    edge.line.p1 = *p1;
-
 
2081
    edge.line.p2 = *p2;
-
 
2082
    edge.top = top;
-
 
2083
    edge.bottom = bottom;
-
 
2084
    edge.dir = dir;
-
 
2085
 
-
 
2086
    status = glitter_scan_converter_add_edge (self->converter, &edge);
-
 
2087
    if (unlikely (status))
-
 
2088
	return _cairo_scan_converter_set_error (self, _cairo_error (status));
-
 
2089
 
-
 
2090
    return CAIRO_STATUS_SUCCESS;
-
 
2091
}
-
 
2092
 
-
 
2093
static cairo_status_t
1783
cairo_status_t
2094
_cairo_tor_scan_converter_add_polygon (void		*converter,
1784
_cairo_tor_scan_converter_add_polygon (void		*converter,
2095
				       const cairo_polygon_t *polygon)
1785
				       const cairo_polygon_t *polygon)
2096
{
1786
{
2097
    cairo_tor_scan_converter_t *self = converter;
-
 
2098
    cairo_status_t status;
1787
    cairo_tor_scan_converter_t *self = converter;
Line -... Line 1788...
-
 
1788
    int i;
2099
    int i;
1789
 
2100
 
1790
#if 0
2101
    for (i = 0; i < polygon->num_edges; i++) {
1791
    FILE *file = fopen ("polygon.txt", "w");
2102
	status = glitter_scan_converter_add_edge (self->converter,
1792
    _cairo_debug_print_polygon (file, polygon);
-
 
1793
    fclose (file);
2103
						  &polygon->edges[i]);
1794
#endif
2104
	if (unlikely (status)) {
1795
 
2105
	    return _cairo_scan_converter_set_error (self,
-
 
2106
						    _cairo_error (status));
-
 
Line 2107... Line 1796...
2107
	}
1796
    for (i = 0; i < polygon->num_edges; i++)
2108
    }
1797
	 glitter_scan_converter_add_edge (self->converter, &polygon->edges[i]);
Line 2109... Line 1798...
2109
 
1798
 
Line 2115... Line 1804...
2115
				    cairo_span_renderer_t	*renderer)
1804
				    cairo_span_renderer_t	*renderer)
2116
{
1805
{
2117
    cairo_tor_scan_converter_t *self = converter;
1806
    cairo_tor_scan_converter_t *self = converter;
2118
    cairo_status_t status;
1807
    cairo_status_t status;
Line 2119... Line -...
2119
 
-
 
2120
   status = glitter_scan_converter_render (self->converter,
-
 
2121
					   self->fill_rule == CAIRO_FILL_RULE_WINDING,
-
 
2122
					   renderer,
-
 
2123
					   self->span_pool.base);
1808
 
2124
    if (unlikely (status))
1809
    if ((status = setjmp (self->jmp)))
Line -... Line 1810...
-
 
1810
	return _cairo_scan_converter_set_error (self, _cairo_error (status));
-
 
1811
 
-
 
1812
    glitter_scan_converter_render (self->converter,
-
 
1813
				   self->fill_rule == CAIRO_FILL_RULE_WINDING ? ~0 : 1,
2125
	return _cairo_scan_converter_set_error (self, _cairo_error (status));
1814
				   self->antialias != CAIRO_ANTIALIAS_NONE,
2126
 
1815
				   renderer);
Line 2127... Line 1816...
2127
    return CAIRO_STATUS_SUCCESS;
1816
    return CAIRO_STATUS_SUCCESS;
2128
}
1817
}
2129
 
1818
 
2130
cairo_scan_converter_t *
1819
cairo_scan_converter_t *
2131
_cairo_tor_scan_converter_create (int			xmin,
1820
_cairo_tor_scan_converter_create (int			xmin,
2132
				  int			ymin,
1821
				  int			ymin,
-
 
1822
				  int			xmax,
2133
				  int			xmax,
1823
				  int			ymax,
2134
				  int			ymax,
1824
				  cairo_fill_rule_t	fill_rule,
2135
				  cairo_fill_rule_t	fill_rule)
1825
				  cairo_antialias_t	antialias)
Line 2136... Line 1826...
2136
{
1826
{
2137
    cairo_tor_scan_converter_t *self;
1827
    cairo_tor_scan_converter_t *self;
2138
    cairo_status_t status;
1828
    cairo_status_t status;
2139
 
1829
 
2140
    self = calloc (1, sizeof(struct _cairo_tor_scan_converter));
1830
    self = malloc (sizeof(struct _cairo_tor_scan_converter));
Line 2141... Line 1831...
2141
    if (unlikely (self == NULL)) {
1831
    if (unlikely (self == NULL)) {
2142
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
2143
	goto bail_nomem;
-
 
2144
    }
1832
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
Line 2145... Line -...
2145
 
-
 
2146
    self->base.destroy = _cairo_tor_scan_converter_destroy;
-
 
2147
    self->base.add_edge = _cairo_tor_scan_converter_add_edge;
-
 
2148
    self->base.add_polygon = _cairo_tor_scan_converter_add_polygon;
-
 
2149
    self->base.generate = _cairo_tor_scan_converter_generate;
1833
	goto bail_nomem;
2150
 
1834
    }
2151
    pool_init (self->span_pool.base,
1835
 
2152
	      250 * sizeof(self->span_pool.embedded[0]),
1836
    self->base.destroy = _cairo_tor_scan_converter_destroy;
2153
	      sizeof(self->span_pool.embedded));
1837
    self->base.generate = _cairo_tor_scan_converter_generate;
Line 2154... Line 1838...
2154
 
1838
 
-
 
1839
    _glitter_scan_converter_init (self->converter, &self->jmp);
Line 2155... Line 1840...
2155
    _glitter_scan_converter_init (self->converter);
1840
    status = glitter_scan_converter_reset (self->converter,
Line 2156... Line 1841...
2156
    status = glitter_scan_converter_reset (self->converter,
1841
					   xmin, ymin, xmax, ymax);
2157
					   xmin, ymin, xmax, ymax);
1842
    if (unlikely (status))