summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2010-11-07 22:59:34 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-11-07 22:59:34 -0500
commit56376288d796e9b4b4cd9405fd14d03b8d0f2d00 (patch)
tree35941e367aa01f3ae8d6870a9aa0c79f9df8eab4
parent48d3e602ca9e978ccf3aa0d44817a26ec2f3ea73 (diff)
State machine
-rw-r--r--demo.c2
-rw-r--r--region-iter.c163
2 files changed, 93 insertions, 72 deletions
diff --git a/demo.c b/demo.c
index d3de027..66e3e8d 100644
--- a/demo.c
+++ b/demo.c
@@ -6,6 +6,7 @@
#include "region-iter.c"
static const pixman_rectangle32_t rects[] = {
+#if 0
{ 0, 50, 200, 100 },
{ 250, 0, 200, 100 },
{ 500, 0, 50, 350 },
@@ -20,6 +21,7 @@ static const pixman_rectangle32_t rects[] = {
{ 450, 350, 50, 50 },
{ 50, 450, 400, 50 },
{ 25, 135, 600, 25 }
+#endif
};
static corner_t *
diff --git a/region-iter.c b/region-iter.c
index 0d8d1ff..8efb395 100644
--- a/region-iter.c
+++ b/region-iter.c
@@ -11,21 +11,37 @@
#define FALSE 0
#endif
-static const pixman_box32_t sentinel =
-{
- INT_MAX, INT_MAX, INT_MAX, INT_MAX
-};
-
typedef struct region_iter_t region_iter_t;
typedef struct row_t row_t;
+typedef enum
+{
+ FIRST,
+ MIDDLE,
+ FINAL,
+ DONE
+} state_t;
+
struct region_iter_t
{
- int y;
- const pixman_box32_t * first;
- const pixman_box32_t * last;
- unsigned int first_row : 1;
- unsigned int final_row : 1;
+ state_t state;
+
+ union
+ {
+ struct
+ {
+ pixman_region32_t * region;
+ } first;
+ struct
+ {
+ pixman_box32_t * first;
+ pixman_box32_t * last;
+ } middle;
+ struct
+ {
+ int y1;
+ } final;
+ } u;
};
struct row_t
@@ -37,6 +53,7 @@ struct row_t
};
/* region_data manipulation */
+
static size_t
next_power (size_t n)
{
@@ -77,86 +94,88 @@ region_data_append (pixman_region32_data_t *data, int n, pixman_box32_t *boxes)
static void
region_iter_init (region_iter_t *iter, pixman_region32_t *region)
{
- iter->y = INT_MIN;
- iter->first_row = TRUE;
- iter->final_row = FALSE;
-
- if (!region->data)
- {
- iter->first = &(region->extents);
- iter->last = &(region->extents) + 1;
- }
- else if (region->data->numRects == 0)
- {
- iter->first = &sentinel;
- iter->last = &sentinel + 1;
- }
- else
- {
- iter->first = (pixman_box32_t *)(region->data + 1);
- iter->last = iter->first + region->data->numRects;
- }
+ iter->state = FIRST;
+ iter->u.first.region = region;
}
static pixman_bool_t
region_iter_get_row (region_iter_t *iter, row_t *row)
{
- if (!iter->first)
- {
- return FALSE;
- }
- else if (iter->final_row)
- {
- row->first = NULL;
- row->last = NULL;
- row->y1 = iter->y;
- row->y2 = INT_MAX;
-
- iter->final_row = FALSE;
- iter->first = NULL;
-
- return TRUE;
- }
- else if (iter->first_row || iter->y < iter->first->y1)
+ pixman_box32_t *first;
+ pixman_box32_t *last;
+ pixman_box32_t *box;
+
+ switch (iter->state)
{
+ case FIRST:
+ row->y1 = INT_MIN;
row->first = NULL;
row->last = NULL;
- row->y1 = iter->y;
- row->y2 = iter->first->y1;
-
- iter->y = iter->first->y1;
- iter->first_row = FALSE;
-
- return TRUE;
- }
- else
- {
- const pixman_box32_t *box;
-
- for (box = iter->first; box != iter->last; box++)
+
+ if (!iter->u.first.region->data)
+ {
+ iter->state = MIDDLE;
+ first = &(iter->u.first.region->extents);
+ last = &(iter->u.first.region->extents) + 1;
+ }
+ else if (iter->u.first.region->data->numRects == 0)
+ {
+ row->y2 = INT_MAX;
+ iter->state = DONE;
+ }
+ else
{
- if (box->y1 != iter->y)
+ iter->state = MIDDLE;
+ first = (pixman_box32_t *)(iter->u.first.region->data + 1);
+ last = first + iter->u.first.region->data->numRects;
+ }
+
+ if (iter->state == MIDDLE)
+ {
+ row->y2 = first->y1;
+ iter->u.middle.first = first;
+ iter->u.middle.last = last;
+ }
+ break;
+
+ case MIDDLE:
+ assert (iter->u.middle.last - iter->u.middle.first > 0);
+
+ for (box = iter->u.middle.first; box != iter->u.middle.last; ++box)
+ {
+ if (box->y1 != iter->u.middle.first->y1)
break;
}
-
- row->first = iter->first;
+
+ row->y1 = iter->u.middle.first->y1;
+ row->y2 = iter->u.middle.first->y2;
+ row->first = iter->u.middle.first;
row->last = box;
- row->y1 = iter->y;
- row->y2 = iter->first->y2;
-
- iter->y = iter->first->y2;
-
- if (box == iter->last)
+
+ if (box != iter->u.middle.last)
{
- iter->final_row = TRUE;
+ iter->u.middle.first = box;
}
else
{
- iter->first = box;
+ iter->state = FINAL;
+ iter->u.final.y1 = row->y2;
}
-
- return TRUE;
+ break;
+
+ case FINAL:
+ row->first = NULL;
+ row->last = NULL;
+ row->y1 = iter->u.final.y1;
+ row->y2 = INT_MAX;
+ iter->state = DONE;
+ break;
+
+ case DONE:
+ return FALSE;
}
+
+ return TRUE;
}
/* Overlapped iter */