summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@l3000.localdomain>2010-11-28 23:22:54 -0500
committerSøren Sandmann Pedersen <ssp@l3000.localdomain>2010-11-28 23:22:54 -0500
commitd579a3316aacc6f314dd5a37795ae41f2bd7d5aa (patch)
tree9eb95a148223cebec2f01afe7b270f372103fa1e
parent248be4d1ea1b00496d3b49c1293bb646a6a744db (diff)
build
-rw-r--r--region-iter.c182
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 (&region1, 100, 100, 200, 200);
pixman_region32_init_rect (&region2, 200, 200, 200, 200);
- region_op (UNION, NULL, &region1, &region2);
+ region_op (UNION, &region, &region1, &region2);
printf ("-=- op2\n");
pixman_region32_init_rect (&region1, 100, 100, 200, 200);
@@ -954,7 +972,7 @@ main ()
pixman_region32_init_rect (&region2, 150, 50, 10, 520);
- region_op (INTERSECT, NULL, &region1, &region2);
+ region_op (INTERSECT, &region, &region1, &region2);
printf ("-=- op2\n");
pixman_region32_init_rect (&region1, 100, 100, 200, 200);
@@ -963,7 +981,7 @@ main ()
pixman_region32_init_rect (&region2, 150, 50, 10, 520);
pixman_region32_union_rect (&region2, &region2, 10, 10, 342, 23);
- region_op (XOR, NULL, &region1, &region2);
+ region_op (XOR, &region, &region1, &region2);
printf ("-=- path\n");
pixman_region32_init_rect (&region1, 100, 100, 200, 200);