#include <stdio.h>

#include <proto/utility.h>

#include "graffiti_rect.h"

void Graffiti_DrawRect_x (struct GraffitiData * gd, WORD x1, WORD y1,
    WORD x2, WORD y2)
{
    UWORD t;

    if (x1 > x2)
	x1 ^= x2 ^= x1 ^= x2;

    if (y1 > y2)
	y1 ^= y2 ^= y1 ^= y2;

    if (x1 < gd->ClipLeft)
	x1 = -1;

    if (y1 < gd->ClipTop)
	y1 = -1;

    if (x2 > gd->ClipRight)
	x2 = 0x7FFF;

    if (y2 > gd->ClipBottom)
	y2 = 0x7FFF;

    if (x1 > x2 || y1 > y2)
	return;

    if (y1 != -1 && y1 != 0x7FFF)
    {
	if (y2 != -1 && y2 != 0x7FFF)
	{
	    for (t=x1; t<=x2; t++)
	    {
		Graffiti_SetPixel (GH(gd), t, y1);
		Graffiti_SetPixel (GH(gd), t, y2);
	    }
	}
	else
	{
	    for (t=x1; t<=x2; t++)
	    {
		Graffiti_SetPixel (GH(gd), t, y1);
	    }
	}
    }
    else if (y2 != -1 && y2 != 0x7FFF)
    {
	for (t=x1; t<=x2; t++)
	{
	    Graffiti_SetPixel (GH(gd), t, y2);
	}
    }

    for (t=y1+1; t<y2; t++)
    {
	Graffiti_SetPixel (GH(gd), x1, t);
	Graffiti_SetPixel (GH(gd), x2, t);
    }

} /* Graffiti_DrawRect_x */

void Graffiti_FillRect_x (struct GraffitiData * gd, WORD x1, WORD y1,
    WORD x2, WORD y2)
{
    UWORD x, y;

    if (x1 > x2)
	x1 ^= x2 ^= x1 ^= x2;

    if (y1 > y2)
	y1 ^= y2 ^= y1 ^= y2;

    if (x1 < gd->ClipLeft)
	x1 = gd->ClipLeft;

    if (y1 < gd->ClipTop)
	y1 = gd->ClipTop;

    if (x2 > gd->ClipRight)
	x2 = gd->ClipRight;

    if (y2 > gd->ClipBottom)
	y2 = gd->ClipBottom;

    if (x1 > x2 || y1 > y2)
	return;

    if (gd->gh.FilterList)
    {
	struct GraffitiHookData ghd;
	UWORD xpos, ypos;

	ghd.x1 = x1;
	ghd.y1 = y1;
	ghd.x2 = x2;
	ghd.y2 = y2;
	ypos = 0;

	for (y=y1; y<=y2; y++)
	{
	    xpos = 0;

	    for (x=x1; x<=x2; x++)
	    {
		ghd.col = gd->gh.FG;

		Graffiti_DrawPixel (GH(gd), xpos, ypos, &ghd);

		xpos ++;
	    }

	    ypos ++;
	}
    }
    else
    {
	for (y=y1; y<=y2; y++)
	{
	    for (x=x1; x<=x2; x++)
		Graffiti_SetPixel (GH(gd), x, y);
	}
    }
} /* Graffiti_FillRect_x */

void Graffiti_FillRect_4 (struct GraffitiData * gd, WORD x1, WORD y1,
    WORD x2, WORD y2)
{
    register UBYTE * bptr;
    register UWORD * wptr;
    register ULONG * lptr;
    register UBYTE * ptr;
    UWORD   xl, xr, x, y, w;
    UWORD   inc;
    ULONG   yoff = (ULONG)y1 * gd->BPR;
    UWORD   wcol;
    ULONG   lcol;

    /* printf ("FillRect (%d,%d, %d,%d, %d)\n", x1, y1, x2, y2); */

    if (x1 > x2)
	x1 ^= x2 ^= x1 ^= x2;

    if (y1 > y2)
	y1 ^= y2 ^= y1 ^= y2;

    if (x1 < gd->ClipLeft)
	x1 = gd->ClipLeft;

    if (y1 < gd->ClipTop)
	y1 = gd->ClipTop;

    if (x2 > gd->ClipRight)
	x2 = gd->ClipRight;

    if (y2 > gd->ClipBottom)
	y2 = gd->ClipBottom;

    if (x1 > x2 || y1 > y2)
	return;

    if (gd->gh.FilterList)
    {
	struct GraffitiHookData ghd;
	UWORD xpos, ypos;

	ghd.x1 = x1;
	ghd.y1 = y1;
	ghd.x2 = x2;
	ghd.y2 = y2;
	ypos = 0;

	for (y=y1; y<=y2; y++)
	{
	    xpos = 0;

	    for (x=x1; x<=x2; x++)
	    {
		ghd.col = gd->gh.FG;

		Graffiti_DrawPixel (GH(gd), xpos, ypos, &ghd);

		xpos ++;
	    }

	    ypos ++;
	}
    }
    else
    {
	wcol = (gd->gh.FG << 8) | gd->gh.FG;

#define RectFillPlane(n)                                        \
	if (xl <= xr)                                           \
	{							\
	    w = xr - xl + 1;					\
								\
	    ptr = gd->Plane[n] + yoff + xl;			\
								\
								\
	    if (xl & 1)                                         \
	    {							\
		bptr = ptr;					\
		inc = gd->BPR;					\
								\
		for (y=y1; y<=y2; y++)                          \
		{						\
		    *bptr = wcol;				\
								\
		    bptr += inc;				\
		}						\
								\
		ptr ++; 					\
		w --;						\
	    }							\
								\
	    /* ptr is now even */				\
	    if (w >= 4)                                         \
	    {							\
		lcol = (wcol << 16) | wcol;                     \
		inc = gd->BPR >> 2;				\
								\
		while (w >= 4)                                  \
		{						\
		    lptr = (ULONG *)ptr;                        \
								\
		    for (y=y1; y<=y2; y++)                      \
		    {						\
			*lptr = lcol;				\
								\
			lptr += inc;				\
		    }						\
								\
		    ptr += 4;					\
		    w -= 4;					\
		}						\
	    }							\
								\
	    if (w >= 2)                                         \
	    {							\
		inc = gd->BPR >> 1;				\
		wptr = (UWORD *)ptr;                            \
								\
		for (y=y1; y<=y2; y++)                          \
		{						\
		    *wptr = wcol;				\
								\
		    wptr += inc;				\
		}						\
								\
		ptr += 2;					\
		w -= 2; 					\
	    }							\
								\
	    if (w)                                              \
	    {							\
		inc = gd->BPR;					\
								\
		for (y=y1; y<=y2; y++)                          \
		{						\
		    *ptr = wcol;				\
								\
		    ptr += inc; 				\
		}						\
	    }							\
	}

	/* Fill plane 0 */
	xl = (x1+3) >> 2;
	xr = x2 >> 2;

	RectFillPlane(0)

	/* Fill plane 1 */
	xl = (x1+2) >> 2;
	xr = (x2-1) >> 2;

	RectFillPlane(1)

	/* Fill plane 2 */
	xl = (x1+1) >> 2;
	xr = (x2-2) >> 2;

	RectFillPlane(2)

	/* Fill plane 3 */
	xl = x1 >> 2;
	xr = (x2-3) >> 2;

	RectFillPlane(3)
    }

} /* Graffiti_FillRect_4 */

