diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-11-07 22:59:34 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-11-07 22:59:34 -0500 |
commit | 56376288d796e9b4b4cd9405fd14d03b8d0f2d00 (patch) | |
tree | 35941e367aa01f3ae8d6870a9aa0c79f9df8eab4 | |
parent | 48d3e602ca9e978ccf3aa0d44817a26ec2f3ea73 (diff) |
State machine
-rw-r--r-- | demo.c | 2 | ||||
-rw-r--r-- | region-iter.c | 163 |
2 files changed, 93 insertions, 72 deletions
@@ -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 */ |