diff options
Diffstat (limited to 'engines/toltecs/microtiles.cpp')
-rw-r--r-- | engines/toltecs/microtiles.cpp | 797 |
1 files changed, 797 insertions, 0 deletions
diff --git a/engines/toltecs/microtiles.cpp b/engines/toltecs/microtiles.cpp new file mode 100644 index 0000000000..3cd5facfa6 --- /dev/null +++ b/engines/toltecs/microtiles.cpp @@ -0,0 +1,797 @@ +/* + SEL - Simple DirectMedia Layer Extension Library + Copyright (C) 2002 Matej Knopp <knopp@users.sf.net> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* microtile arrays implementation */ + +/* + * This is a microtile array implementation similiar to the one + * from LibArt_LGPL. First, I wanted to use that one but unfortunately + * I fount out that it suffered from a bad design and simply didn't meet + * my requirements so I decided to write the implementation on my own. + */ + +#include "toltecs/microtiles.h" +#include "common/scummsys.h" +#include "common/endian.h" +#include "common/util.h" + +namespace Toltecs { + +typedef struct _GemUta GemUta; +typedef struct _GemRect GemRect; + +typedef uint32 GemUtaBBox; + +#define GEM_UTA_BBOX_CONS(x0, y0, x1, y1) (((x0) << 24) | ((y0) << 16) | \ + ((x1) << 8) | (y1)) + +#define GEM_UTILE_EMPTY 0x00000000 +#define GEM_UTILE_FULL 0x01012020 + +#define GEM_UTA_BBOX_X0(ub) ((ub) >> 24) +#define GEM_UTA_BBOX_Y0(ub) (((ub) >> 16) & 0xff) +#define GEM_UTA_BBOX_X1(ub) (((ub) >> 8) & 0xff) +#define GEM_UTA_BBOX_Y1(ub) ((ub) & 0xff) + +#define GEM_UTILE_SHIFT 5 +#define GEM_UTILE_SIZE (1 << GEM_UTILE_SHIFT) + +#define GEM_MIN(a,b) ((a) < (b) ? (a) : (b)) +#define GEM_MAX(a,b) ((a) > (b) ? (a) : (b)) + +struct _GemUta { + int x; + int y; + int width; /* number of tiles in one line */ + int height; /* number of tiles in one row */ + GemUtaBBox *tiles; +}; + +struct _GemRect { + int x0; + int x1; + int y0; + int y1; +}; + + +static GemUta * gem_uta_new (int x, int y, int width, int height); +static GemUta * gem_uta_new_coords (int x, int y, int width, int height); +static void gem_uta_free (GemUta *uta); +static void gem_uta_union (GemUta *uta1, const GemUta *uta2); +static void gem_uta_add_rect (GemUta *uta, const GemRect * rect); + +#define GEM_UTA_QUERY_CONTAIN 0 +#define GEM_UTA_QUERY_INTERSECT 1 + +static int gem_uta_query_rect (const GemUta *uta, const GemRect * rect, int query); + +static Common::Rect * gem_uta_get_rects (const GemUta *uta, int * num_rects, + int min_x, int min_y, int max_x, int max_y); + +/************** UTA IMPLEMENTATION **************/ + +#define GEM_UTILE_UNION(b1, b2) \ + { \ + if (b1 == GEM_UTILE_FULL || b2 == GEM_UTILE_EMPTY) \ + { } \ + else if (b1 == GEM_UTILE_EMPTY || b2 == GEM_UTILE_FULL) \ + { b1 = b2; } \ + else { \ + b1 = GEM_UTA_BBOX_CONS ( \ + GEM_MIN(GEM_UTA_BBOX_X0(b1), \ + GEM_UTA_BBOX_X0(b2)), \ + GEM_MIN(GEM_UTA_BBOX_Y0(b1), \ + GEM_UTA_BBOX_Y0(b2)), \ + GEM_MAX(GEM_UTA_BBOX_X1(b1), \ + GEM_UTA_BBOX_X1(b2)), \ + GEM_MAX(GEM_UTA_BBOX_Y1(b1), \ + GEM_UTA_BBOX_Y1(b2))); \ + } \ + } + +static GemUta * gem_uta_new (int x, int y, int width, int height) { + GemUta *uta; + + uta = (GemUta *) malloc (sizeof (GemUta)); + uta->x = x; + uta->y = y; + uta->width = width; + uta->height = height; + + uta->tiles = (GemUtaBBox *) + malloc (sizeof (GemUtaBBox) * width * height); + + memset (uta->tiles, 0, sizeof (GemUtaBBox) * width * height); + + return uta; +} + +static GemUta * gem_uta_new_coords (int x, int y, int width, int height) { + return gem_uta_new (x >> GEM_UTILE_SHIFT, y >> GEM_UTILE_SHIFT, + (width >> GEM_UTILE_SHIFT) + 1, + (height >> GEM_UTILE_SHIFT) + 1); +} + +static void gem_uta_free (GemUta *uta) { + if (uta) { + if (uta->tiles) + free (uta->tiles); + free(uta); + } +} + +static void gem_uta_union (GemUta *uta1, const GemUta *uta2) { + int32 x0, y0, x1, y1; + int x, y; + GemUtaBBox *_b1; + const GemUtaBBox *_b2; + + if (!uta1 || !uta2) + return; + + x0 = GEM_MAX (uta1->x, uta2->x); + y0 = GEM_MAX (uta2->y, uta2->y); + x1 = GEM_MIN (uta1->x + uta1->width - 1, + uta2->x + uta2->width - 1); + y1 = GEM_MIN (uta1->y + uta1->height - 1, + uta2->y + uta2->height - 1); + + if (x0 > x1 || y0 > y1) + return; + + _b1 = & (uta1->tiles [(y0 - uta1->y) * uta1->width + (x0 - uta1->x)]); + _b2 = & (uta2->tiles [(y0 - uta2->y) * uta2->width + (x0 - uta2->x)]); + + for (y = y0; y <= y1; ++y) + { + GemUtaBBox *b1 = _b1; + const GemUtaBBox *b2 = _b2; + + for (x = x0; x <= x1; ++x) + { + GEM_UTILE_UNION (*b1, *b2); + + b1 ++; + b2 ++; + } + _b1 += uta1->width; + _b2 += uta2->width; + } +} + +/* + * Add a rectangle to the microtile array. + * The coordinates of the rectangle are considered absolute. + */ + +static void gem_uta_add_rect (GemUta *uta, const GemRect * _rect) { + int xf0, xf1, yf0, yf1; + int width, height; + int x0, y0, x1, y1; + int x, y; + GemUtaBBox *_b; + GemUtaBBox *b; + GemUtaBBox bbox; + GemRect rect; + + if (!uta || !_rect) + return; + + rect = *_rect; + + rect.x0 -= uta->x << GEM_UTILE_SHIFT; + rect.y0 -= uta->y << GEM_UTILE_SHIFT; + rect.x1 -= uta->x << GEM_UTILE_SHIFT; + rect.y1 -= uta->y << GEM_UTILE_SHIFT; + + if (rect.x0 < 0) + rect.x0 = 0; + if (rect.y0 < 0) + rect.y0 = 0; + if (rect.x1 > (uta->width << GEM_UTILE_SHIFT)) + rect.x1 = (uta->width << GEM_UTILE_SHIFT); + if (rect.y1 > (uta->height << GEM_UTILE_SHIFT)) + rect.y1 = (uta->height << GEM_UTILE_SHIFT); + + if (rect.x0 > rect.x1 || rect.y0 > rect.y1) + return; + + width = ((rect.x1 + GEM_UTILE_SIZE) >> GEM_UTILE_SHIFT) + - (rect.x0 >> GEM_UTILE_SHIFT); + height = ((rect.y1 + GEM_UTILE_SIZE) >> GEM_UTILE_SHIFT) + - (rect.y0 >> GEM_UTILE_SHIFT); + + xf0 = rect.x0 % (GEM_UTILE_SIZE); + yf0 = rect.y0 % (GEM_UTILE_SIZE); + xf1 = rect.x1 % (GEM_UTILE_SIZE); + yf1 = rect.y1 % (GEM_UTILE_SIZE); + + x0 = rect.x0 >> GEM_UTILE_SHIFT; + y0 = rect.y0 >> GEM_UTILE_SHIFT; + x1 = rect.x1 >> GEM_UTILE_SHIFT; + y1 = rect.y1 >> GEM_UTILE_SHIFT; + + _b = & (uta->tiles [(y0 * uta->width) + x0]); + + if (width == 1 && height == 1) { + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, yf0 + 1, xf1 + 1, yf1 + 1); + GEM_UTILE_UNION (*_b, bbox); + return; + } + if (width == 1) { + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, yf0 + 1, xf1 + 1, + GEM_UTILE_SIZE); + GEM_UTILE_UNION (*_b, bbox); + _b += uta->width; + if (height > 2) { + for (y = y0 + 1; y <= (y1 - 1); ++y) { + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, 1, xf1 + 1, GEM_UTILE_SIZE); + GEM_UTILE_UNION (*_b, bbox); + _b += uta->width; + } + } + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, 1, xf1 + 1, yf1 + 1); + GEM_UTILE_UNION (*_b, bbox); + return; + } else if (height == 1) { + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, yf0 + 1, GEM_UTILE_SIZE, yf1 + 1); + GEM_UTILE_UNION (*_b, bbox); + ++_b; + if (width > 2) { + for (x = x0 + 1; x <= (x1 - 1); ++x) { + bbox = GEM_UTA_BBOX_CONS (1, yf0 + 1, GEM_UTILE_SIZE, xf1 + 1); + GEM_UTILE_UNION (*_b, bbox); + ++_b; + } + } + bbox = GEM_UTA_BBOX_CONS (1, yf0 + 1, xf1 + 1, yf1 + 1); + GEM_UTILE_UNION (*_b, bbox); + return; + } + + b = _b; + + /* top-left corner */ + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, yf0 + 1, GEM_UTILE_SIZE, GEM_UTILE_SIZE); + GEM_UTILE_UNION (*b, bbox); + ++b; + + /* top edge */ + if (width > 2) { + for (x = x0 + 1; x <= (x1 - 1); ++x) { + bbox = GEM_UTA_BBOX_CONS (1, yf0 + 1, GEM_UTILE_SIZE, GEM_UTILE_SIZE); + GEM_UTILE_UNION (*b, bbox); + ++b; + } + } + + /* top-right corner */ + bbox = GEM_UTA_BBOX_CONS (1, yf0 + 1, xf1 + 1, GEM_UTILE_SIZE); + GEM_UTILE_UNION (*b, bbox); + + _b += uta->width; + + /* left edge, content, right edge */ + if (height > 2) { + for (y = y0 + 1; y <= (y1 - 1); ++y) { + b = _b; + + /* left edge */ + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, 1, GEM_UTILE_SIZE, GEM_UTILE_SIZE); + GEM_UTILE_UNION (*b, bbox); + ++b; + + /* content */ + if (width > 2) { + for (x = x0 + 1; x <= (x1 - 1); ++x) { + *b = GEM_UTILE_FULL; + ++b; + } + } + + /* right edge */ + bbox = GEM_UTA_BBOX_CONS (1, 1, xf1 + 1, GEM_UTILE_SIZE); + GEM_UTILE_UNION (*b, bbox); + + _b += uta->width; + } + } + + b = _b; + + /* bottom-left corner */ + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, 1, GEM_UTILE_SIZE, yf1 + 1); + GEM_UTILE_UNION (*b, bbox); + ++b; + + /* bottom edge */ + if (width > 2) { + for (x = x0 + 1; x <= (x1 - 1); ++x) { + bbox = GEM_UTA_BBOX_CONS (1, 1, GEM_UTILE_SIZE, yf1 + 1); + GEM_UTILE_UNION (*b, bbox); + ++b; + } + } + + /* bottom-left corner */ + bbox = GEM_UTA_BBOX_CONS (1, 1, xf1 + 1, yf1 + 1); + GEM_UTILE_UNION (*b, bbox); + + /* done. */ +} + +#define GEM_UTILE_CONTAINS(b1, b2) \ + ( !(GEM_UTA_BBOX_X0 (b1) > GEM_UTA_BBOX_X0 (b2) || \ + GEM_UTA_BBOX_Y0 (b1) > GEM_UTA_BBOX_Y0 (b2) || \ + GEM_UTA_BBOX_X1 (b1) < GEM_UTA_BBOX_X1 (b2) || \ + GEM_UTA_BBOX_Y1 (b1) < GEM_UTA_BBOX_Y1 (b2)) ) + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +static inline int gem_utile_intersects (GemUtaBBox b1, GemUtaBBox b2) { + GemUtaBBox b3; + b3 = GEM_UTA_BBOX_CONS ( + MAX (GEM_UTA_BBOX_X0 (b1), GEM_UTA_BBOX_X0 (b2)), + MAX (GEM_UTA_BBOX_Y0 (b1), GEM_UTA_BBOX_Y0 (b2)), + MIN (GEM_UTA_BBOX_X1 (b1), GEM_UTA_BBOX_X1 (b2)), + MIN (GEM_UTA_BBOX_Y1 (b1), GEM_UTA_BBOX_Y1 (b2)) + ); + return (GEM_UTA_BBOX_X0 (b3) <= GEM_UTA_BBOX_X1 (b3) && + GEM_UTA_BBOX_Y0 (b3) <= GEM_UTA_BBOX_Y1 (b3)); +} + +#define GEM_UTILE_INTERSECTS(b1, b2) \ + gem_utile_intersects (b1, b2) +/* + * Return if the uta contains the rectangle. + */ + +static int gem_uta_query_rect (const GemUta *uta, const GemRect * _rect, int query) { + int xf0, xf1, yf0, yf1; + int width, height; + int x0, y0, x1, y1; + int x, y; + GemUtaBBox *_b; + GemUtaBBox *b; + GemUtaBBox bbox; + GemRect rect; + + if (!uta || !_rect) + return 0; + + rect = *_rect; + + rect.x0 -= uta->x << GEM_UTILE_SHIFT; + rect.y0 -= uta->y << GEM_UTILE_SHIFT; + rect.x1 -= uta->x << GEM_UTILE_SHIFT; + rect.y1 -= uta->y << GEM_UTILE_SHIFT; + + if (rect.x0 < 0) + rect.x0 = 0; + if (rect.y0 < 0) + rect.y0 = 0; + if (rect.x1 > (uta->width << GEM_UTILE_SHIFT)) + rect.x1 = (uta->width << GEM_UTILE_SHIFT); + if (rect.y1 > (uta->height << GEM_UTILE_SHIFT)) + rect.y1 = (uta->height << GEM_UTILE_SHIFT); + + if (rect.x0 > rect.x1 || rect.y0 > rect.y1) + return 0; + + width = ((rect.x1 + GEM_UTILE_SIZE) >> GEM_UTILE_SHIFT) + - (rect.x0 >> GEM_UTILE_SHIFT); + height = ((rect.y1 + GEM_UTILE_SIZE) >> GEM_UTILE_SHIFT) + - (rect.y0 >> GEM_UTILE_SHIFT); + + xf0 = rect.x0 % (GEM_UTILE_SIZE); + yf0 = rect.y0 % (GEM_UTILE_SIZE); + xf1 = rect.x1 % (GEM_UTILE_SIZE); + yf1 = rect.y1 % (GEM_UTILE_SIZE); + + x0 = rect.x0 >> GEM_UTILE_SHIFT; + y0 = rect.y0 >> GEM_UTILE_SHIFT; + x1 = rect.x1 >> GEM_UTILE_SHIFT; + y1 = rect.y1 >> GEM_UTILE_SHIFT; + + _b = & (uta->tiles [(y0 * uta->width) + x0]); + + if (width == 1 && height == 1) { + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, yf0 + 1, xf1 + 1, yf1 + 1); + if (query == GEM_UTA_QUERY_INTERSECT && + GEM_UTILE_INTERSECTS (*_b, bbox)) + return 1; + else if (query == GEM_UTA_QUERY_CONTAIN && + GEM_UTILE_CONTAINS (*_b, bbox)) + return 1; + return 0; + + } +#define CHECK(b1,b2) \ + { \ + if (query == GEM_UTA_QUERY_INTERSECT && \ + GEM_UTILE_INTERSECTS (b1, b2)) \ + return 1; \ + else if (query == GEM_UTA_QUERY_CONTAIN && \ + !(GEM_UTILE_CONTAINS (b1, b2))) \ + return 0; \ + } + if (width == 1) { + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, yf0 + 1, xf1 + 1, GEM_UTILE_SIZE); + CHECK (*_b, bbox); + _b += uta->width; + if (height > 2) { + for (y = y0 + 1; y <= (y1 - 1); ++y) { + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, 1, xf1 + 1, GEM_UTILE_SIZE); + CHECK (*_b, bbox); + _b += uta->width; + } + } + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, 1, xf1 + 1, yf1 + 1); + CHECK (*_b, bbox); + if (query == GEM_UTA_QUERY_INTERSECT) + return 0; + else if (query == GEM_UTA_QUERY_CONTAIN) + return 1; + } else if (height == 1) { + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, yf0 + 1, GEM_UTILE_SIZE, yf1 + 1); + CHECK (*_b, bbox); + ++_b; + if (width > 2) { + for (x = x0 + 1; x <= (x1 - 1); ++x) { + bbox = GEM_UTA_BBOX_CONS (1, yf0 + 1, GEM_UTILE_SIZE, xf1 + 1); + CHECK (*_b, bbox); + ++_b; + } + } + bbox = GEM_UTA_BBOX_CONS (1, yf0 + 1, xf1 + 1, yf1 + 1); + CHECK (*_b, bbox); + if (query == GEM_UTA_QUERY_INTERSECT) + return 0; + else if (query == GEM_UTA_QUERY_CONTAIN) + return 1; + } + + b = _b; + + /* top-left corner */ + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, yf0 + 1, GEM_UTILE_SIZE, GEM_UTILE_SIZE); + CHECK (*b, bbox); + ++b; + + /* top edge */ + if (width > 2) { + for (x = x0 + 1; x <= (x1 - 1); ++x) { + bbox = GEM_UTA_BBOX_CONS (1, yf0 + 1, GEM_UTILE_SIZE, GEM_UTILE_SIZE); + CHECK (*b, bbox); + ++b; + } + } + + /* top-right corner */ + bbox = GEM_UTA_BBOX_CONS (1, yf0 + 1, xf1 + 1, GEM_UTILE_SIZE); + CHECK (*b, bbox); + + _b += uta->width; + + /* left edge, content, right edge */ + if (height > 2) { + for (y = y0 + 1; y <= (y1 - 1); ++y) { + b = _b; + + /* left edge */ + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, 1, GEM_UTILE_SIZE, GEM_UTILE_SIZE); + CHECK (*b, bbox); + ++b; + + /* content */ + if (width > 2) { + for (x = x0 + 1; x <= (x1 - 1); ++x) { + CHECK (*b, GEM_UTILE_FULL); + ++b; + } + } + + /* right edge */ + bbox = GEM_UTA_BBOX_CONS (1, 1, xf1 + 1, GEM_UTILE_SIZE); + CHECK (*b, bbox); + + _b += uta->width; + } + } + + b = _b; + + /* bottom-left corner */ + bbox = GEM_UTA_BBOX_CONS (xf0 + 1, 1, GEM_UTILE_SIZE, yf1 + 1); + CHECK (*b, bbox); + ++b; + + /* bottom edge */ + if (width > 2) { + for (x = x0 + 1; x <= (x1 - 1); ++x) { + bbox = GEM_UTA_BBOX_CONS (1, 1, GEM_UTILE_SIZE, yf1 + 1); + CHECK (*b, bbox); + ++b; + } + } + + /* bottom-left corner */ + bbox = GEM_UTA_BBOX_CONS (1, 1, xf1 + 1, yf1 + 1); + CHECK (*b, bbox); + +#undef CHECK + + /* done. */ + if (query == GEM_UTA_QUERY_CONTAIN) + return 1; + return 0; +} + + +#undef CLAMP +#define CLAMP(a,min,max) (a = (a < min ? min : (a > max ? max : a))) + +static Common::Rect * gem_uta_get_rects (const GemUta *uta, int * num_rects, + int min_x, int min_y, int max_x, int max_y) { + +#if 1 + + + GemRect *rects = new GemRect[uta->width * uta->height]; + Common::Rect *result = NULL; + int n_rects = 0; + int x, y; + int x0, y0, x1, y1; + + int *glom = new int[uta->width * uta->height]; + int i; /* current */ + + for (i = 0; i < uta->width * uta->height; ++i) + glom [i] = -1; + + i = 0; + + for (y = 0; y < uta->height; ++y) { + for (x = 0; x < uta->width; ++x) { +#define TILE uta->tiles [i] + int start; + int finish = 0; + GemUtaBBox b; + + b = uta->tiles [i]; + + if (TILE == GEM_UTILE_EMPTY) + goto next; + + x0 = ((uta->x + x) << GEM_UTILE_SHIFT) + GEM_UTA_BBOX_X0 (TILE) - 1; + y0 = ((uta->y + y) << GEM_UTILE_SHIFT) + GEM_UTA_BBOX_Y0 (TILE) - 1; + y1 = ((uta->y + y) << GEM_UTILE_SHIFT) + GEM_UTA_BBOX_Y1 (TILE) - 1; + + CLAMP (x0, min_x, max_x); + CLAMP (y0, min_y, max_y); + CLAMP (y1, min_y, max_y); + + start = i; + + if (GEM_UTA_BBOX_X1 (TILE) != GEM_UTILE_SIZE || x == uta->width - 1) { + /* the tile does not continue */ + goto done; + } + + while (!finish) { + ++x; + ++i; + + if (x == uta->width || + GEM_UTA_BBOX_Y0 (TILE) != GEM_UTA_BBOX_Y0 (b) || + GEM_UTA_BBOX_Y1 (TILE) != GEM_UTA_BBOX_Y1 (b) || + GEM_UTA_BBOX_X0 (TILE) != 1) + { + --x; + --i; + finish = 1; + } + } + + done: + x1 = ((uta->x + x) << GEM_UTILE_SHIFT) + GEM_UTA_BBOX_X1 (TILE) - 1; + + CLAMP (x1, min_x, max_x); + + if (glom [start] != -1 && /* try to glom */ + rects [glom [start]].x0 == x0 && + rects [glom [start]].x1 == x1 && + rects [glom [start]].y1 == y0 - 1) + { + rects [glom [start]].y1 = y1; + if (y != uta->height - 1) { + glom [start + uta->width] = glom [start]; + } + } else { + rects [n_rects].x0 = x0; + rects [n_rects].y0 = y0; + rects [n_rects].x1 = x1; + rects [n_rects].y1 = y1; + if (y != uta->height - 1) { + glom [start + uta->width] = n_rects; + } + n_rects ++; + } + next: + ++i; +#undef TILE + } + } + + result = new Common::Rect[n_rects]; + + for (i = 0; i < n_rects; ++i) { + result[i].left = rects [i].x0; + result[i].top = rects [i].y0; + result[i].right = rects[i].x1; // CHECK + result[i].bottom = rects[i].y1; // CHECK + } + + *num_rects = n_rects; + + delete rects; + delete glom; + + return result; + +#else + return NULL; +#endif + +} + +MicroTileArray::MicroTileArray() + : m_uta (NULL) +{ +} + +MicroTileArray::MicroTileArray(int x, int y, int w, int h) + : m_x (x), m_y (y), m_w (w), m_h (h) +{ + m_uta = gem_uta_new_coords (x, y, w, h); + if (!m_uta) + error("MicroTileArray::MicroTileArray() Out of memory"); +} + +MicroTileArray::~MicroTileArray() { + if (m_uta) + gem_uta_free (m_uta); +} + +void MicroTileArray::clear() { + if (!m_uta) + return; + + memset (m_uta->tiles, 0, m_uta->width * m_uta->height * sizeof(GemUtaBBox)); +} + +void MicroTileArray::init(int x, int y, int w, int h) { + if (m_uta) + gem_uta_free (m_uta); + m_uta = gem_uta_new_coords (x, y, w, h); + m_x = x; + m_y = y; + m_w = w; + m_h = h; + if (!m_uta) + error("Out of memory"); +} + +int MicroTileArray::getRectangles(Common::Rect * & rects, int min_x, int max_x, int min_y, int max_y) const { + if (!m_uta) + return 0; + + int n_rects; + + rects = gem_uta_get_rects (m_uta, &n_rects, min_x, max_x, min_y, max_y); + + return n_rects; +} + +int MicroTileArray::getRectangles(Common::Rect * & rects) const { + if (!m_uta) + return 0; + + int n_rects; + + rects = gem_uta_get_rects (m_uta, &n_rects, + m_x, m_y, m_x + m_w - 1, m_y + m_h - 1); + + return n_rects; +} + +bool MicroTileArray::contains(const Common::Rect & rect) const { + if (!m_uta) + return false; + + GemRect r; + r.x0 = rect.left; + r.y0 = rect.top; + r.x1 = rect.right; // CHECK + r.y1 = rect.bottom; // CHECK + + return gem_uta_query_rect (m_uta, &r, GEM_UTA_QUERY_CONTAIN); +} + +bool MicroTileArray::intersects(const Common::Rect & rect) const { + if (!m_uta) + return false; + + GemRect r; + r.x0 = rect.left; + r.y0 = rect.top; + r.x1 = rect.right; // CHECK + r.y1 = rect.bottom; // CHECK + + return gem_uta_query_rect (m_uta, &r, GEM_UTA_QUERY_INTERSECT); +} + +void MicroTileArray::unite(const Common::Rect & rect) { + if (!m_uta || rect.width() == 0 || rect.height() == 0) + return; + + GemRect r; + r.x0 = rect.left; + r.y0 = rect.top; + r.x1 = rect.right; // CHECK + r.y1 = rect.bottom; // CHECK + + gem_uta_add_rect (m_uta, &r); +} + +MicroTileArray & MicroTileArray::operator += (const Common::Rect & rect) { + if (!m_uta || rect.width() == 0 || rect.height() == 0) + return *this; + + GemRect r; + r.x0 = rect.left; + r.y0 = rect.top; + r.x1 = rect.right; // CHECK + r.y1 = rect.bottom; // CHECK + + gem_uta_add_rect (m_uta, &r); + + return *this; +} + +void MicroTileArray::unite (const MicroTileArray & uta) { + if (m_uta) + gem_uta_union (m_uta, uta.m_uta); +} + +MicroTileArray & MicroTileArray::operator += (const MicroTileArray & uta) { + if (m_uta) + gem_uta_union (m_uta, uta.m_uta); + return *this; +} + +} // namespace Toltecs + |