1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
3 * Copyright (c) 2011 Intel Corporation
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation
7 * files (the "Software"), to deal in the Software without
8 * restriction, including without limitation the rights to use,
9 * copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
27 #include "cairo-spans-private.h"
28 #include "cairo-error-private.h"
40 struct edge
*next
, *prev
;
51 /* A collection of sorted and vertically clipped edges of the polygon.
52 * Edges are moved from the polygon to an active list while scan
55 /* The vertical clip extents. */
61 /* Array of edges all starting in the same bucket. An edge is put
62 * into bucket EDGE_BUCKET_INDEX(edge->ytop, polygon->ymin) when
63 * it is added to the polygon. */
64 struct edge
**y_buckets
;
66 struct edge
*y_buckets_embedded
[64];
67 struct edge edges_embedded
[32];
70 struct mono_scan_converter
{
71 struct polygon polygon
[1];
73 /* Leftmost edge on the current scan line. */
74 struct edge head
, tail
;
77 cairo_half_open_span_t
*spans
;
78 cairo_half_open_span_t spans_embedded
[64];
86 #define I(x) _cairo_fixed_integer_round_down(x)
88 /* Compute the floored division a/b. Assumes / and % perform symmetric
90 inline static struct quorem
91 floored_divrem(int a
, int b
)
96 if ((a
^b
)<0 && qr
.rem
) {
103 /* Compute the floored division (x*a)/b. Assumes / and % perform symmetric
106 floored_muldivrem(int x
, int a
, int b
)
109 long long xa
= (long long)x
*a
;
112 if ((xa
>=0) != (b
>=0) && qr
.rem
) {
119 static cairo_status_t
120 polygon_init (struct polygon
*polygon
, int ymin
, int ymax
)
122 unsigned h
= ymax
- ymin
+ 1;
124 polygon
->y_buckets
= polygon
->y_buckets_embedded
;
125 if (h
> ARRAY_LENGTH (polygon
->y_buckets_embedded
)) {
126 polygon
->y_buckets
= _cairo_malloc_ab (h
, sizeof (struct edge
*));
127 if (unlikely (NULL
== polygon
->y_buckets
))
128 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
130 memset (polygon
->y_buckets
, 0, h
* sizeof (struct edge
*));
131 polygon
->y_buckets
[h
-1] = (void *)-1;
133 polygon
->ymin
= ymin
;
134 polygon
->ymax
= ymax
;
135 return CAIRO_STATUS_SUCCESS
;
139 polygon_fini (struct polygon
*polygon
)
141 if (polygon
->y_buckets
!= polygon
->y_buckets_embedded
)
142 free (polygon
->y_buckets
);
144 if (polygon
->edges
!= polygon
->edges_embedded
)
145 free (polygon
->edges
);
149 _polygon_insert_edge_into_its_y_bucket(struct polygon
*polygon
,
153 struct edge
**ptail
= &polygon
->y_buckets
[y
- polygon
->ymin
];
162 polygon_add_edge (struct polygon
*polygon
,
163 const cairo_edge_t
*edge
)
169 int ymin
= polygon
->ymin
;
170 int ymax
= polygon
->ymax
;
181 e
= polygon
->edges
+ polygon
->num_edges
++;
182 e
->height_left
= ybot
- ytop
;
185 dx
= edge
->line
.p2
.x
- edge
->line
.p1
.x
;
186 dy
= edge
->line
.p2
.y
- edge
->line
.p1
.y
;
190 e
->x
.quo
= edge
->line
.p1
.x
;
197 e
->dxdy
= floored_muldivrem (dx
, CAIRO_FIXED_ONE
, dy
);
200 e
->x
= floored_muldivrem (ytop
* CAIRO_FIXED_ONE
+ CAIRO_FIXED_FRAC_MASK
/2 - edge
->line
.p1
.y
,
202 e
->x
.quo
+= edge
->line
.p1
.x
;
206 _polygon_insert_edge_into_its_y_bucket (polygon
, e
, ytop
);
210 merge_sorted_edges (struct edge
*head_a
, struct edge
*head_b
)
212 struct edge
*head
, **next
, *prev
;
217 if (head_a
->x
.quo
<= head_b
->x
.quo
) {
227 while (head_a
!= NULL
&& head_a
->x
.quo
<= x
) {
229 next
= &head_a
->next
;
230 head_a
= head_a
->next
;
240 while (head_b
!= NULL
&& head_b
->x
.quo
<= x
) {
242 next
= &head_b
->next
;
243 head_b
= head_b
->next
;
254 sort_edges (struct edge
*list
,
256 struct edge
**head_out
)
258 struct edge
*head_other
, *remaining
;
261 head_other
= list
->next
;
263 if (head_other
== NULL
) {
268 remaining
= head_other
->next
;
269 if (list
->x
.quo
<= head_other
->x
.quo
) {
271 head_other
->next
= NULL
;
273 *head_out
= head_other
;
274 head_other
->prev
= list
->prev
;
275 head_other
->next
= list
;
276 list
->prev
= head_other
;
280 for (i
= 0; i
< level
&& remaining
; i
++) {
281 remaining
= sort_edges (remaining
, i
, &head_other
);
282 *head_out
= merge_sorted_edges (*head_out
, head_other
);
289 merge_unsorted_edges (struct edge
*head
, struct edge
*unsorted
)
291 sort_edges (unsorted
, UINT_MAX
, &unsorted
);
292 return merge_sorted_edges (head
, unsorted
);
296 active_list_merge_edges (struct mono_scan_converter
*c
, struct edge
*edges
)
300 for (e
= edges
; c
->is_vertical
&& e
; e
= e
->next
)
301 c
->is_vertical
= e
->vertical
;
303 c
->head
.next
= merge_unsorted_edges (c
->head
.next
, edges
);
307 add_span (struct mono_scan_converter
*c
, int x1
, int x2
)
320 c
->spans
[n
].coverage
= 255;
324 c
->spans
[n
].coverage
= 0;
328 row (struct mono_scan_converter
*c
, unsigned int mask
)
330 struct edge
*edge
= c
->head
.next
;
331 int xstart
= INT_MIN
, prev_x
= INT_MIN
;
335 while (&c
->tail
!= edge
) {
336 struct edge
*next
= edge
->next
;
337 int xend
= I(edge
->x
.quo
);
339 if (--edge
->height_left
) {
340 if (!edge
->vertical
) {
341 edge
->x
.quo
+= edge
->dxdy
.quo
;
342 edge
->x
.rem
+= edge
->dxdy
.rem
;
343 if (edge
->x
.rem
>= 0) {
345 edge
->x
.rem
-= edge
->dy
;
349 if (edge
->x
.quo
< prev_x
) {
350 struct edge
*pos
= edge
->prev
;
355 } while (edge
->x
.quo
< pos
->x
.quo
);
356 pos
->next
->prev
= edge
;
357 edge
->next
= pos
->next
;
361 prev_x
= edge
->x
.quo
;
363 edge
->prev
->next
= next
;
364 next
->prev
= edge
->prev
;
367 winding
+= edge
->dir
;
368 if ((winding
& mask
) == 0) {
369 if (I(next
->x
.quo
) > xend
+ 1) {
370 add_span (c
, xstart
, xend
);
373 } else if (xstart
== INT_MIN
)
380 inline static void dec (struct edge
*e
, int h
)
383 if (e
->height_left
== 0) {
384 e
->prev
->next
= e
->next
;
385 e
->next
->prev
= e
->prev
;
389 static cairo_status_t
390 _mono_scan_converter_init(struct mono_scan_converter
*c
,
394 cairo_status_t status
;
397 status
= polygon_init (c
->polygon
, ymin
, ymax
);
398 if (unlikely (status
))
401 max_num_spans
= xmax
- xmin
+ 1;
402 if (max_num_spans
> ARRAY_LENGTH(c
->spans_embedded
)) {
403 c
->spans
= _cairo_malloc_ab (max_num_spans
,
404 sizeof (cairo_half_open_span_t
));
405 if (unlikely (c
->spans
== NULL
)) {
406 polygon_fini (c
->polygon
);
407 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
410 c
->spans
= c
->spans_embedded
;
417 c
->head
.vertical
= 1;
418 c
->head
.height_left
= INT_MAX
;
419 c
->head
.x
.quo
= _cairo_fixed_from_int (_cairo_fixed_integer_part (INT_MIN
));
421 c
->head
.next
= &c
->tail
;
422 c
->tail
.prev
= &c
->head
;
424 c
->tail
.x
.quo
= _cairo_fixed_from_int (_cairo_fixed_integer_part (INT_MAX
));
425 c
->tail
.height_left
= INT_MAX
;
426 c
->tail
.vertical
= 1;
429 return CAIRO_STATUS_SUCCESS
;
433 _mono_scan_converter_fini(struct mono_scan_converter
*self
)
435 if (self
->spans
!= self
->spans_embedded
)
438 polygon_fini(self
->polygon
);
441 static cairo_status_t
442 mono_scan_converter_allocate_edges(struct mono_scan_converter
*c
,
446 c
->polygon
->num_edges
= 0;
447 c
->polygon
->edges
= c
->polygon
->edges_embedded
;
448 if (num_edges
> ARRAY_LENGTH (c
->polygon
->edges_embedded
)) {
449 c
->polygon
->edges
= _cairo_malloc_ab (num_edges
, sizeof (struct edge
));
450 if (unlikely (c
->polygon
->edges
== NULL
))
451 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
454 return CAIRO_STATUS_SUCCESS
;
458 mono_scan_converter_add_edge (struct mono_scan_converter
*c
,
459 const cairo_edge_t
*edge
)
461 polygon_add_edge (c
->polygon
, edge
);
465 step_edges (struct mono_scan_converter
*c
, int count
)
469 for (edge
= c
->head
.next
; edge
!= &c
->tail
; edge
= edge
->next
) {
470 edge
->height_left
-= count
;
471 if (! edge
->height_left
) {
472 edge
->prev
->next
= edge
->next
;
473 edge
->next
->prev
= edge
->prev
;
478 static cairo_status_t
479 mono_scan_converter_render(struct mono_scan_converter
*c
,
480 unsigned int winding_mask
,
481 cairo_span_renderer_t
*renderer
)
483 struct polygon
*polygon
= c
->polygon
;
484 int i
, j
, h
= c
->ymax
- c
->ymin
;
485 cairo_status_t status
;
487 for (i
= 0; i
< h
; i
= j
) {
490 if (polygon
->y_buckets
[i
])
491 active_list_merge_edges (c
, polygon
->y_buckets
[i
]);
493 if (c
->is_vertical
) {
498 min_height
= e
->height_left
;
499 while (e
!= &c
->tail
) {
500 if (e
->height_left
< min_height
)
501 min_height
= e
->height_left
;
505 while (--min_height
>= 1 && polygon
->y_buckets
[j
] == NULL
)
508 step_edges (c
, j
- (i
+ 1));
511 row (c
, winding_mask
);
513 status
= renderer
->render_rows (renderer
, c
->ymin
+i
, j
-i
,
514 c
->spans
, c
->num_spans
);
515 if (unlikely (status
))
519 /* XXX recompute after dropping edges? */
520 if (c
->head
.next
== &c
->tail
)
524 return CAIRO_STATUS_SUCCESS
;
527 struct _cairo_mono_scan_converter
{
528 cairo_scan_converter_t base
;
530 struct mono_scan_converter converter
[1];
531 cairo_fill_rule_t fill_rule
;
534 typedef struct _cairo_mono_scan_converter cairo_mono_scan_converter_t
;
537 _cairo_mono_scan_converter_destroy (void *converter
)
539 cairo_mono_scan_converter_t
*self
= converter
;
540 _mono_scan_converter_fini (self
->converter
);
545 _cairo_mono_scan_converter_add_polygon (void *converter
,
546 const cairo_polygon_t
*polygon
)
548 cairo_mono_scan_converter_t
*self
= converter
;
549 cairo_status_t status
;
553 FILE *file
= fopen ("polygon.txt", "w");
554 _cairo_debug_print_polygon (file
, polygon
);
558 status
= mono_scan_converter_allocate_edges (self
->converter
,
560 if (unlikely (status
))
563 for (i
= 0; i
< polygon
->num_edges
; i
++)
564 mono_scan_converter_add_edge (self
->converter
, &polygon
->edges
[i
]);
566 return CAIRO_STATUS_SUCCESS
;
569 static cairo_status_t
570 _cairo_mono_scan_converter_generate (void *converter
,
571 cairo_span_renderer_t
*renderer
)
573 cairo_mono_scan_converter_t
*self
= converter
;
575 return mono_scan_converter_render (self
->converter
,
576 self
->fill_rule
== CAIRO_FILL_RULE_WINDING
? ~0 : 1,
580 cairo_scan_converter_t
*
581 _cairo_mono_scan_converter_create (int xmin
,
585 cairo_fill_rule_t fill_rule
)
587 cairo_mono_scan_converter_t
*self
;
588 cairo_status_t status
;
590 self
= malloc (sizeof(struct _cairo_mono_scan_converter
));
591 if (unlikely (self
== NULL
)) {
592 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
596 self
->base
.destroy
= _cairo_mono_scan_converter_destroy
;
597 self
->base
.generate
= _cairo_mono_scan_converter_generate
;
599 status
= _mono_scan_converter_init (self
->converter
,
600 xmin
, ymin
, xmax
, ymax
);
601 if (unlikely (status
))
604 self
->fill_rule
= fill_rule
;
609 self
->base
.destroy(&self
->base
);
611 return _cairo_scan_converter_create_in_error (status
);