/* newmenu-dirty.m,
 */

#include <allegro.h>
#include <stdio.h>
#include "newmenu-dirty.h"


#define MAX_RECTANGLES			16
#define RECTANGLE_IN_USE(r)		(menu_rectangles[r].w > 0 && menu_rectangles[r].h > 0)
#define foreach_rectangle(r)		for (r = 0; r < MAX_RECTANGLES; r++)


static dirty_rectangle_t menu_rectangles[MAX_RECTANGLES];


static int rect_encloses_rect(dirty_rectangle_t *a, dirty_rectangle_t *b)
{
    return (a->x <= b->x && a->x+a->w >= b->x+b->w &&
	    a->y <= b->y && a->y+a->h >= b->y+b->h);
}

void mark_entire_screen_dirty(void)
{
    int r;

    foreach_rectangle (r) {
	menu_rectangles[r].w = 0;
	menu_rectangles[r].h = 0;
    }

    menu_rectangles[0].x = 0;
    menu_rectangles[0].y = 0;
    menu_rectangles[0].w = SCREEN_W;
    menu_rectangles[0].h = SCREEN_H;
}

void mark_dirty_rectangle(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
{
    int r;
    dirty_rectangle_t dummy;

    dummy.x = x;
    dummy.y = y;
    dummy.w = w;
    dummy.h = h;

    foreach_rectangle (r) {
	if (RECTANGLE_IN_USE(r)) {
	    if (rect_encloses_rect(&menu_rectangles[r], &dummy))
		return;
	    if (!rect_encloses_rect(&dummy, &menu_rectangles[r]))
		continue;
	}

	menu_rectangles[r].x = x;
	menu_rectangles[r].y = y;
	menu_rectangles[r].w = w;
	menu_rectangles[r].h = h;
	return;
    }

    /* Ran out of rectangles!  Mark the whole screen dirty. */
    fprintf(stderr, "[Menu] Out of dirty rectangles!\n");
    mark_entire_screen_dirty();
}

void blit_dirty_rectangles(BITMAP *src, BITMAP *dest)
{
    int i;

    acquire_bitmap(dest);
    foreach_rectangle (i) {
	if (RECTANGLE_IN_USE(i)) {
	    dirty_rectangle_t *r = &menu_rectangles[i];
	    blit(src, dest, r->x, r->y, r->x, r->y, r->w, r->h);

#if 0
	    /* Debug. */
	    int c = rand() % 255;
	    rect(dest, r->x, r->y, r->x+r->w-1, r->y+r->h-1, makecol(c, 0x00, 0x00));
#endif

	    r->w = r->h = 0;
	}
    }
    release_bitmap(dest);
}
