Code:
// first off, behold! A region!
typedef struct TAGregion {
SDL_Rect rcRegion; // Using an SDL Rect for fast passing to SDL blit function
short sRight; // These ease calculations a bit
short sBottom;
struct TAGregion *next;
} t_region;
// Find the difference (A - B) of two rectangles
t_region *difference(short sX, short sY, short sRight, short sBottom, short sX1, short sY1, short sRight1, short sBottom1)
{
t_region *regions = NULL;
if (sX < sX1)
{
create_rect_region(®ions, sX, sY, sX1, sBottom);
sX += sX1 - sX;
}
if (sY < sY1)
{
create_rect_region(®ions, sX, sY, sRight, sY1);
sY += sY1 - sY;
}
if (sRight > sRight1)
{
create_rect_region(®ions, (sX > sRight1) ? sX : sRight1, sY, sRight, sBottom);
sRight -= sRight - sRight1;
}
if (sBottom > sBottom1)
create_rect_region(®ions, sX, (sY > sBottom1) ? sY : sBottom1, sRight, sBottom);
return regions;
}
// find the difference of two lists (regions)
t_region *difference_regions(t_region *region1, t_region *region2)
{
t_region *rgn2, *rgnRet = NULL;
while (region1)
{
rgn2 = region2;
while (rgn2)
{
rgnRet = append_regions(rgnRet, difference(region1->rcRegion.x, region1->rcRegion.y, region1->sRight, region1->sBottom, rgn2->rcRegion.x, rgn2->rcRegion.y, rgn2->sRight, rgn2->sBottom));
rgn2 = rgn2->next;
}
region1 = region1->next;
}
return rgnRet;
}
// find the intersection (A & B) of two rectangles
t_region *intersection(short sX, short sY, short sRight, short sBottom, short sX1, short sY1, short sRight1, short sBottom1)
{
if ((sX > sX1) ? sX : sX1 >= (sRight < sRight1) ? sRight : sRight1 || (sY > sY1) ? sY : sY1 >= (sBottom < sBottom1) ? sBottom : sBottom1)
return NULL;
else
return create_rect_region(NULL, (sX > sX1) ? sX : sX1, (sY > sY1) ? sY : sY1, (sRight < sRight1) ? sRight : sRight1, (sBottom < sBottom1) ? sBottom : sBottom1);
}
// find the intersection of two regions
t_region *intersection_regions(t_region *region1, t_region *region2)
{
t_region *rgn2, *rgnRet = NULL;
while (region1)
{
rgn2 = region2;
while (rgn2)
{
rgnRet = append_regions(rgnRet, intersection(region1->rcRegion.x, region1->rcRegion.y, region1->sRight, region1->sBottom, rgn2->rcRegion.x, rgn2->rcRegion.y, rgn2->sRight, rgn2->sBottom));
rgn2 = rgn2->next;
}
region1 = region1->next;
}
return rgnRet;
}