diff options
author | Søren Sandmann Pedersen <ssp@l3000.localdomain> | 2010-11-28 23:22:54 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@l3000.localdomain> | 2010-11-28 23:22:54 -0500 |
commit | d579a3316aacc6f314dd5a37795ae41f2bd7d5aa (patch) | |
tree | 9eb95a148223cebec2f01afe7b270f372103fa1e | |
parent | 248be4d1ea1b00496d3b49c1293bb646a6a744db (diff) |
build
-rw-r--r-- | region-iter.c | 182 |
1 files changed, 100 insertions, 82 deletions
diff --git a/region-iter.c b/region-iter.c index 489aa86..b066e58 100644 --- a/region-iter.c +++ b/region-iter.c @@ -62,6 +62,7 @@ typedef struct region_builder_t region_builder_t; struct region_builder_t { pixman_region32_data_t * data; + int second_last_row; int last_row; }; @@ -79,18 +80,29 @@ next_power (size_t n) static pixman_region32_data_t * region_data_append (pixman_region32_data_t *data, int n) { - if (!data || data->size < data->numRects + n) - { - size_t new_size = next_power (n + data? data->numRects : 0); + size_t new_size = next_power ((data? data->numRects : 0) + n); + + new_size = + sizeof (pixman_region32_data_t) + sizeof (pixman_box32_t) * new_size; - data = realloc (data, sizeof (pixman_region32_data_t) + new_size); + if (!data) + { + data = malloc (new_size); if (!data) return NULL; - data->size = new_size; + data->numRects = 0; } + else + { + data = realloc (data, new_size); + if (!data) + return NULL; + } + + data->size = new_size; return data; } @@ -98,109 +110,105 @@ static void region_builder_init (region_builder_t *builder) { builder->data = NULL; - builder->last_row = -1; + builder->second_last_row = -1; + builder->last_row = 0; } -static pixman_bool_t -region_builder_add_row (region_builder_t *builder, - int n, pixman_box32_t *boxes) +static void +region_builder_coalesce_rows (region_builder_t *builder) { - pixman_region32_data_t *data; - pixman_box32_t *box, *end; - int first_new; + pixman_region32_data_t *data = builder->data; + pixman_box32_t *old, *new; + pixman_bool_t coalesce; + int i, n; - data = builder->data; - if (data == BROKEN_DATA) - return FALSE; + if (!data) + return; - first_new = data? data->numRects : 0; - end = boxes + n; - box = boxes; - while (box < end) + n = builder->last_row - builder->second_last_row; + if (builder->second_last_row == -1 || + data->numRects - builder->last_row != n) { - pixman_box32_t *next = box + 1; - pixman_box32_t *b; + coalesce = FALSE; + } + else + { + old = (pixman_box32_t *)(data + 1) + builder->second_last_row; + new = (pixman_box32_t *)(data + 1) + builder->last_row; - /* Coalesce adjacent boxes */ - if (next == end || next->x1 > box->x2) + coalesce = TRUE; + for (i = 0; i < n; ++i) { - int n_rects; - - if (!(data = region_data_append (data, 1))) + if (new[i].y1 != old[i].y2 || + new[i].x1 != old[i].x1 || + new[i].x2 != old[i].x2) { - free (builder->data); - builder->data = BROKEN_DATA; - return FALSE; + coalesce = FALSE; + break; } - - n_rects = data->numRects; - b = (pixman_box32_t *)(data + 1); - b[n_rects].y1 = boxes->y1; - b[n_rects].y2 = boxes->y2; - b[n_rects].x1 = boxes->x1; - b[n_rects].x2 = box->x2; - data->numRects++; - - boxes = next; } - - box = next; } - builder->data = data; - - /* Coalesce adjacent rows */ - if (builder->last_row < 0) + if (coalesce) { - builder->last_row = first_new; - return TRUE; + for (i = 0; i < n; ++i) + old[i].y2 = new[i].y2; + + data->numRects -= n; } else { - pixman_bool_t coalesce; - int n = first_new - builder->last_row; - pixman_box32_t *old = (pixman_box32_t *)(data + 1) + builder->last_row; - pixman_box32_t *new = (pixman_box32_t *)(data + 1) + first_new; - int i; + builder->second_last_row = builder->last_row; + builder->last_row = data->numRects; + } +} - if (data->numRects - first_new != n) - { - coalesce = FALSE; - } - else - { - coalesce = TRUE; - for (i = 0; i < n; ++i) - { - if (new[i].y1 != old[i].y2 || - new[i].x1 != old[i].x1 || - new[i].x2 != old[i].x2) - { - coalesce = FALSE; - break; - } - } - } +static pixman_bool_t +region_builder_add_box (region_builder_t *builder, + int x1, int y1, int x2, int y2) +{ + pixman_box32_t *last_box; + pixman_region32_data_t *data; - if (coalesce) - { - for (i = 0; i < n; ++i) - old[i].y2 = new[i].y2; + data = builder->data; + if (data == BROKEN_DATA) + return FALSE; - data->numRects -= n; - } - else + if (!(data = region_data_append (data, 1))) + { + free (builder->data); + builder->data = BROKEN_DATA; + return FALSE; + } + + if (data->numRects == 0) + last_box = NULL; + else + last_box = ((pixman_box32_t *)(data + 1)) + data->numRects - 1; + + if (last_box) + { + if (y1 != last_box->y1) + region_builder_coalesce_rows (builder); + else if (x1 == last_box->x2) { - builder->last_row = first_new; + last_box->x2 = x2; + return; } } - return TRUE; + last_box = (pixman_box32_t *)(data + 1 + data->numRects++); + last_box->x1 = x1; + last_box->y1 = y1; + last_box->x2 = x2; + last_box->y2 = y2; } static pixman_bool_t region_builder_finish (region_builder_t *builder, pixman_region32_t *region) { + region_builder_coalesce_rows (builder); + pixman_region32_fini (region); if (!builder->data || builder->data->numRects == 0) @@ -580,6 +588,9 @@ region_op (ops_t op, { overlapped_iter_t iter; row_t row1, row2; + region_builder_t builder; + + region_builder_init (&builder); overlapped_iter_init (&iter, src1, src2); while (overlapped_iter_get_rows (&iter, &row1, &row2)) @@ -592,13 +603,20 @@ region_op (ops_t op, { if (op & (1 << segment.type)) { + region_builder_add_box ( + &builder, segment.x1, row1.y1, segment.x2, row1.y2); +#if 0 printf ("box at %d %d %d %d %s\n", segment.x1, row1.y1, segment.x2, row1.y2, (segment.x1 == segment.x2 || row1.y1 == row2.y2)? "[empty]" : ""); +#endif } } } + + pixman_region32_fini (dst); + region_builder_finish (&builder, dst); } static int @@ -944,7 +962,7 @@ main () pixman_region32_init_rect (®ion1, 100, 100, 200, 200); pixman_region32_init_rect (®ion2, 200, 200, 200, 200); - region_op (UNION, NULL, ®ion1, ®ion2); + region_op (UNION, ®ion, ®ion1, ®ion2); printf ("-=- op2\n"); pixman_region32_init_rect (®ion1, 100, 100, 200, 200); @@ -954,7 +972,7 @@ main () pixman_region32_init_rect (®ion2, 150, 50, 10, 520); - region_op (INTERSECT, NULL, ®ion1, ®ion2); + region_op (INTERSECT, ®ion, ®ion1, ®ion2); printf ("-=- op2\n"); pixman_region32_init_rect (®ion1, 100, 100, 200, 200); @@ -963,7 +981,7 @@ main () pixman_region32_init_rect (®ion2, 150, 50, 10, 520); pixman_region32_union_rect (®ion2, ®ion2, 10, 10, 342, 23); - region_op (XOR, NULL, ®ion1, ®ion2); + region_op (XOR, ®ion, ®ion1, ®ion2); printf ("-=- path\n"); pixman_region32_init_rect (®ion1, 100, 100, 200, 200); |