#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <functions.h>
#include "pdefines.h"
#include "globals.h"

#define	CHEAT	1

struct Picture *CreateStencilPic (rp, stencilcolor)
	struct RastPort *rp;
	UBYTE  stencilcolor;
{
	struct	RastPort *mrp;
	struct	Picture *newpic;
	WORD	height, width;
	WORD	left, top;
	WORD	depth;
	int	i;
	UBYTE	oldmask;

	if (( newpic = (struct Picture *)AllocMem (sizeof (struct Picture), MEMF_CLEAR)) == NULL) {
		SYSMESS ("Couldn't allocate an Picture");
		return (NULL);
	}

	InitRastPort (&newpic->RastPort);
	newpic->RastPort.BitMap = &newpic->BitMap;

	if (rp->Layer) {
		left   = rp->Layer->bounds.MinX;
		top    = rp->Layer->bounds.MinY;
		width  = rp->Layer->bounds.MaxX - left + 1;
		height = rp->Layer->bounds.MaxY - top + 1;
	} else {
		left   = 0;
		top    = 0;
		width  = rp->BitMap->BytesPerRow * 8;
		height = rp->BitMap->Rows;
	}
	depth = rp->BitMap->Depth;

	newpic->ilbmframe.bmHdr.nPlanes = depth;	
	newpic->ilbmframe.bmHdr.w = width;
	newpic->ilbmframe.bmHdr.h = height;

	InitBitMap (&newpic->BitMap, rp->BitMap->Depth, width, height);

	if (!(newpic->BitMap.Planes[0] = AllocRaster(width, height))) {
		DeleteStencilPic (newpic);
		SYSMESS ("Couldn't allocate stencil mem");
		return NULL;
	}

	for (i=1; i<depth; i++) {
		newpic->BitMap.Planes[i] = newpic->BitMap.Planes[0];
	}

	mrp = &newpic->RastPort;
	oldmask   = mrp->Mask;
	mrp->Mask = 0x01;
	ClipCopy (rp, left, top,
		  newpic, 0, 0, width, height, 0xFF, USECLIPBLIT);
	mrp->Mask = stencilcolor;
	ClipCopy (rp, left, top,
		  newpic, 0, 0, width, height, 0x80, USECLIPBLIT);
	mrp->Mask = 0xFF^stencilcolor;
	ClipCopy (rp, left, top,
		  newpic, 0, 0, width, height, 0x20, USECLIPBLIT);
	mrp->Mask = oldmask;

	return (newpic);
}	

DeleteStencilPic (pic)
struct Picture *pic;
{
	if (pic) {
		if (pic->BitMap.Planes[0]) {
			FreeMem (pic->BitMap.Planes[0],
				 pic->BitMap.BytesPerRow * 
				 pic->BitMap.Rows);
		}
		FreeMem (pic, sizeof (struct Picture));
	}
}

struct Shape *CreateStencil (rp, color)
	struct RastPort *rp;
	UBYTE color;
{
	struct Shape *newshape;
	struct Picture *newpic;
	struct BitMap *bm;
	int depth, width, height;
	int i;
	UBYTE tcolor;

	if (( newshape = (struct Shape *)AllocMem (sizeof (struct Shape), MEMF_CLEAR)) == NULL) {
		SYSMESS ("Couldn't allocate a Shape");
		return (NULL);
	}

	if (!( newpic = CreateStencilPic (rp, color))) {
		DeleteStencil (newshape);
		return (NULL);
	}

	newshape->Pic = newpic;

	depth  = newpic->ilbmframe.bmHdr.nPlanes;	
	width  = newpic->ilbmframe.bmHdr.w;
	height = newpic->ilbmframe.bmHdr.h;
	tcolor = newpic->ilbmframe.bmHdr.transparentColor;

	/*** Create a bitmap for mask ***/

	bm = &newshape->MaskBm;

	InitBitMap (bm, depth, width, height);

	bm->Planes[0] = newpic->BitMap.Planes[0];

	for (i = 1; i < depth; i++) {
		bm->Planes[i] = bm->Planes[0];
	}

#if NOT CHEAT
	/*** the mask is inverted so fix it			***/
	/*** Now the mask will have ones were the shapes are	***/
	/*** and zeros everywhere else				***/
	BltBitMap (bm, 0, 0,
		   bm, 0, 0,
		   width, height,
		   0x30, 0x01, NULL);

#endif
	/*** Finally Create a RastPort for the mask ***/

	InitRastPort (&newshape->MaskRp);
	newshape->MaskRp.BitMap = bm;

	return (newshape);
}

DeleteStencil (shape)
struct Shape *shape;
{
	if (shape) {
		DeleteStencilPic (shape->Pic);
		FreeMem (shape, sizeof (struct Shape));
	}
}
