/* images.c -- image utiltity routines :ts=4 */

/*
Copyright (c) 1989 Commodore-Amiga, Inc.

Executables based on this information may be used in software
for Commodore Amiga computers. All other rights reserved.
This information is provided "as is"; no warranties are made.
All use is at your own risk, and no liability or responsibility
is assumed.
*/

#include "sysall.h"

#define D(x)	;
#define DI(x)	;

/*
 * will set up Image.Depth.  Feel free
 * to change the PlanePick and PlaneOnOff fields
 */
struct Image	*
CreateImage( width, height, depth )
{
    struct Image	*im;
    int	rassize;

    im = (struct Image *) AllocMem( sizeof (struct Image),
	    	MEMF_PUBLIC | MEMF_CLEAR );

    D( printf("CE: w %d h %d, im %lx, next %lx\n", width, height, im,
		im->NextImage ) );

    if ( im )
    {
		rassize = RASSIZE( (long) width, (long) height );
		D( printf( "CreateImage: rassize: %d\n", rassize ) );

    	im->ImageData = (USHORT *) AllocVec( (long) rassize * depth,
			(long) MEMF_CHIP | MEMF_CLEAR );

		if ( im->ImageData )
		{
		    im->Width = width;
		    im->Height = height;
		    im->Depth = depth;
		    im->PlanePick = ( 1 << depth ) - 1;
		}
		else
		{
		    D( printf("CI free abort\n") );
		    FreeMem( im, (long) (sizeof *im) );
		    im = NULL;
		}
    }
    return ( im );
}

/*
 * dont' rely on depth for raster size, since he's allowed to
 * change that to pull mask tricks
 */
DeleteImage( im )
struct Image	*im;
{
    D( printf("DeleteImage\n") );
    FreeVec( im->ImageData );
    FreeMem( im, (long) sizeof ( *im ) );
}

/* area info capacity (MODIFY if you need more space)	*/
#define MAXAVECTORS	(20)
#define AIBUFFSIZE	(5 * MAXAVECTORS)

#define IRP_SIZE ( (long) sizeof ( struct RastPort ) + \
	sizeof ( struct BitMap ) + \
	sizeof ( struct TmpRas ) + \
	sizeof ( struct AreaInfo )  + AIBUFFSIZE )

/*
 * create a rastport for drawing into an Intuition Image structure
 * creates it with an initialized TmpRas and AreaInfo.
 * modify this if you need more space in the AreaInfo.
 */
struct RastPort	*
CreateImageRPort( im )
struct Image	*im;
{
   /** These are all allocated contiguously	**/
   struct RastPort	*rp;
   struct BitMap	*bmap;
   struct TmpRas	*tmpras;
   struct AreaInfo	*ainfo;
   char			*abuffer;

   int	i;
   int	rassize;
   UBYTE	*planeptr;
   UBYTE	*tmpraster;


   /* allocate rport and bmap contiguously	*/
   rp = (struct RastPort *) AllocMem( (long) IRP_SIZE, (long) MEMF_CLEAR );

   rassize = RASSIZE( (long) im->Width, (long) im->Height );

   D( printf( "CIRP: irpsize: %ld, rassize: %d\n", IRP_SIZE, rassize ) );

   if ( rp )
   {
	D( printf("cirp: rastport at: %lx\n", rp ) );
	InitRastPort( rp );

	bmap = (struct BitMap *) &rp[1];
	tmpras = (struct TmpRas *) &bmap[1];
	ainfo = (struct AreaInfo *) &tmpras[1];
	abuffer = (char *) &ainfo[1];

	/*** init the BitMap ***/

	D( printf( "cirp: init the bmap\n") );

	InitBitMap(  bmap, (long) im->Depth, 
		(long) im->Width, (long) im->Height );

	/* point rastport at bitmap	*/
	rp->BitMap = bmap;

	/* point bitmap at image data	*/
	planeptr = (UBYTE *) im->ImageData;
	for ( i = 0; i < im->Depth; ++i )
	{
	    bmap->Planes[ i ] = (PLANEPTR) planeptr;
	    D( printf( "cirp: init plane: %lx\n", planeptr) );
	    planeptr += rassize;
	}

	/*** init the AreaInfo ***/
	D( printf("init the AInfo\n") );
	InitArea( ainfo, abuffer, (long) MAXAVECTORS );
	rp->AreaInfo = ainfo;

	/*** init the TmpRas ***/
	D( printf("init the TmpRas\n") );
	tmpraster = (UBYTE *) AllocMem( (long) rassize, (LONG) MEMF_CHIP );
	if ( tmpraster )
	{
	    D( printf("TR: %d bytes at %lx\n", rassize, tmpraster ) );
	    InitTmpRas( tmpras, tmpraster, (long) rassize );
	    rp->TmpRas = tmpras;
	    rp->RP_User = (APTR *) tmpraster;	/* for later freeing	*/
	}
	else
	{
	    D( printf("no tmpraster\n") );
	    FreeMem( rp, IRP_SIZE );
	    rp = NULL;
	}
   }
   D( else printf("no rastport bundle\n") );

   D( printf("cirp: returning rastport %lx\n", rp ) );
   return ( rp );
}

/*
 * only use on rastports created by CreateImageRPort
 */
DeleteImageRPort( rp )
struct RastPort	*rp;
{
    WaitBlit();		/* tmpras no longer in use	*/

    D( printf("DIRP: %lx\n", rp ) );

    D( printf("delete tmpraster at %lx\n", rp->RP_User ) );
    D( printf("trsize: %d\n", rp->BitMap->Rows * rp->BitMap->BytesPerRow ) );

    /* tmpraster is same size as rastport bitmap	*/
    FreeMem( rp->RP_User, (long) rp->BitMap->Rows * rp->BitMap->BytesPerRow );

    D( printf("delete rastport at %lx\n", rp ) );

    FreeMem( rp, (long) IRP_SIZE );
}

/*
 * return pointer to one of the image planes
 */
UWORD	*
ImagePlane( im, plane )
struct Image	*im;
{
	int	planesize = RASSIZE( im->Width, im->Height );

	DI( printf("IP: planesize: %d\n", planesize ) );

	return ( im->ImageData + plane * (planesize/2) );
}

clearWords( buff, numwords )
WORD	*buff;
{
    while ( numwords-- ) *buff++ = 0;
}

/* fancy this up later	*/
drawBox( rp, width, height, fieldcolor, bordercolor, vthick, hthick )
struct RastPort	*rp;
{
	DI( printf("w %d h %d vthick %d hthick %d\n",
		width, height, vthick, hthick ) );
	SetAPen( rp, (long) bordercolor );
	RectFill( rp, 0L, 0L, (long) width-1, (long) height-1 );

	SetAPen( rp, (long) fieldcolor );
	RectFill( rp, (long) vthick, (long) hthick, (long) width-1 - vthick,
		(long) height - 1 - hthick );

	DI( printf("outer rect: %d %d %d %d\n", 0, 0, width-1,
		height - 1) );

	DI( printf("inner rect %d %d %d %d\n",
		vthick, hthick, width-1 - vthick, height - 1 - hthick ) );
}
