/*************************************************************************
  *                                                                      *
  *                            Preliminary                               *
  *                        Amiga AppShell (tm)                           *
  *                                                                      *
  *  Copyright (c) 1990,1991 Commodore-Amiga, Inc. All Rights Reserved.  *
  *                                                                      *
  *   This software and information is proprietary, preliminary, and     *
  *   subject to change without notice.                                  *
  *                                                                      *
  *                            DISCLAIMER                                *
  *                                                                      *
  *   THIS SOFTWARE IS PROVIDED "AS IS".                                 *
  *   NO REPRESENTATIONS OR WARRANTIES ARE MADE WITH RESPECT TO THE      *
  *   ACCURACY, RELIABILITY, PERFORMANCE, CURRENTNESS, OR OPERATION      *
  *   OF THIS SOFTWARE, AND ALL USE IS AT YOUR OWN RISK.                 *
  *   NEITHER COMMODORE NOR THE AUTHORS ASSUME ANY RESPONSIBILITY OR     *
  *   LIABILITY WHATSOEVER WITH RESPECT TO YOUR USE OF THIS SOFTWARE.    *
  *                                                                      *
  *                          Non-Disclosure                              *
  *                                                                      *
  *   This information is not to be disclosed to any other company,      *
  *   individual or party.  Discussion is to be restricted to CBM        *
  *   approved discussion areas, such as the closed conferences on bix;  *
  *   amiga.cert, amiga.com, amiga.beta/appshell.                        *
  *                                                                      *
  ************************************************************************
  * Copyright (C) 1990 Commodore-Amiga, Inc.
  * written by David N. Junod
  */

/*
**	$Filename: dynamicimages.c $
**	$Release: 1.4 $
**	$Version: 3 $
**
**	images that can be drawn, filled, area filled and properly
**	clipped.
**
**	(C) Copyright 1989 Commodore-Amiga, Inc.
**	    All Rights Reserved Worldwide
**
**	Revision History:
**
**	01-Dec-89  Created this file.			David N. Junod ~DNJ~
**	09-Dec-89  Cleaned up for distribution.		~DNJ~
**	20-Dec-89  Added Application Flags		~DNJ~
**
*/

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <graphics/rastport.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <clib/layers_protos.h>

#define AREA_SIZE 200

struct DynamicImage
{
    struct Image di_image;	/* Image structure to draw/display */
    struct BitMap di_bmap;	/* Image's BitMap */
    struct RastPort di_rport;	/* Image's RastPort */
    ULONG di_size;		/* Size of ImageData */

    struct TmpRas di_tmpras;	/* Flood Fill TmpRas */
    UBYTE *di_workspace;	/* Flood Fill workspace */

    struct AreaInfo di_area;	/* Area Fill AreaInfo */
    WORD di_array[AREA_SIZE];	/* Area Fill workspace */

    struct Layer_Info *di_li;	/* Layer_Info for layer manipulations */
    struct Layer *di_layer;	/* Layer structure */
    ULONG Flags;		/* Application Flags -- see defines */
};

/* Application Flags.
 * Used to indicate what parts of the DynamicImage need
 * to be initialized.
 */
#define DI_FILL		(1L<<0)
#define	DI_LAYER	(1L<<1)

/* DynamicImages.c: Function Prototypes */
VOID InitDynamicImage (struct DynamicImage *, USHORT, USHORT, USHORT);
BOOL AllocDynamicImage (struct DynamicImage *);
VOID FreeDynamicImage (struct DynamicImage *);

/* Private allocation functions */
static BOOL DIAllocFill (struct DynamicImages *, USHORT, USHORT);
static BOOL DIAllocLayer (struct DynamicImage *, USHORT, USHORT);

/****** DynamicImages/InitDynamicImage *******************************
*
*   NAME
*       InitDynamicImage - Initialize DynamicImage structure.
*
*   SYNOPSIS
*       InitDynamicImage (di, depth, width, height)
*
*       struct DynamicImage *di;
*       USHORT depth, width, height;
*
*   FUNCTION
*       Initializes various fields of the DynamicImage structure
*       to correctly reflect the size of the dynamically allocated
*       image.
*
*   INPUTS
*       di     - Pointer to the DynamicImage structure.
*       depth  - Depth of the desired image.
*       width  - Width of the desired image.
*       height - Height of the desired image.
*
*   BUGS
*
*   SEE ALSO
*
*       AllocDynamicImage(), FreeDynamicImage()
*
**********************************************************************
*
* Created:  01-Dec-89, David N. Junod
*
*/

VOID InitDynamicImage (struct DynamicImage * di,
		        USHORT d, USHORT w, USHORT h)
{
    register SHORT i;

    /* Initialize Image Structure */
    di->di_image.LeftEdge = 0;
    di->di_image.TopEdge = 0;
    di->di_image.Width = w;
    di->di_image.Height = h;
    di->di_image.Depth = d;
    di->di_image.ImageData = NULL;
    di->di_image.PlanePick = (1 << d) - 1;
    di->di_image.PlaneOnOff = 0;
    di->di_image.NextImage = NULL;
    di->di_workspace = NULL;

    /*
     * Initialize BitMap.
     */
    InitBitMap (&di->di_bmap, (BYTE) d, (SHORT) w, (SHORT) h);

    /*
     * Initialize RastPort to draw into.
     */
    InitRastPort (&di->di_rport);
    di->di_rport.BitMap = &di->di_bmap;

    /*
     * Initialize Area Fill.
     */
    for (i = 0; i < AREA_SIZE; i++)
	di->di_array[i] = 0;
    InitArea (&di->di_area, &di->di_array[0], AREA_SIZE / 5);
    di->di_rport.AreaInfo = &di->di_area;

    /*
     * Clear Layer Information
     */
    di->di_li = NULL;
    di->di_layer = NULL;
}

/****** DynamicImages/AllocDynamicImage ******************************
*
*   NAME
*       AllocDynamicImage - Allocates memory required for DynamicImage
*
*   SYNOPSIS
*       AllocDynamicImage (di)
*
*       struct DynamicImage *di;
*
*   FUNCTION
*       Allocates the image data and other work areas required for
*       dynamic images.
*
*   INPUTS
*       di     - Pointer to the DynamicImage structure.
*
*   BUGS
*
*   SEE ALSO
*
*       InitDynamicImage(), FreeDynamicImage()
*
**********************************************************************
*
* Created:  01-Dec-89, David N. Junod
*
*/

BOOL AllocDynamicImage (struct DynamicImage * di)
{
    struct BitMap *bm = &di->di_bmap;
    USHORT depth = di->di_image.Depth;
    USHORT width = di->di_image.Width;
    USHORT height = di->di_image.Height;
    SHORT i, planes;
    LONG image_data;

    planes = RASSIZE (width, height);
    di->di_size = (depth * planes);
    if (di->di_image.ImageData =
	(USHORT *) AllocMem (di->di_size, MEMF_CHIP | MEMF_CLEAR))
    {
	image_data = (LONG) di->di_image.ImageData;
	for (i = 0L; i < depth; ++i)
	    bm->Planes[i] = (PLANEPTR) (image_data + i * planes);

	if (di->Flags & DI_FILL)
	    if (!(DIAllocFill (di, width, height)))
	    {
		FreeDynamicImage (di);
		return (FALSE);
	    }

	if (di->Flags & DI_LAYER)
	    if (!(DIAllocLayer (di, width, height)))
	    {
		FreeDynamicImage (di);
		return (FALSE);
	    }

	return (TRUE);
    }
    return (FALSE);
}

/****** DynamicImages/FreeDynamicImage *******************************
*
*   NAME
*       FreeDynamicImage - Deallocates memory required for DynamicImage
*
*   SYNOPSIS
*       FreeDynamicImage (di)
*
*       struct DynamicImage *di;
*
*   FUNCTION
*       Deallocates the image data and other work areas required for
*       dynamic images.  The DynamicImage image structure that was
*       passed, can now be passed backed thru another
*       AllocDynamicImage() or it's resources can be freed up.
*
*   INPUTS
*       di     - Pointer to the DynamicImage structure.
*
*   BUGS
*
*   SEE ALSO
*
*       InitDynamicImage(), AllocDynamicImage()
*
**********************************************************************
*
* Created:  01-Dec-89, David N. Junod
*
*/

VOID FreeDynamicImage (struct DynamicImage * di)
{
    USHORT width = di->di_image.Width;
    USHORT height = di->di_image.Height;

    if (di)
    {
	if (di->di_li)
	{
	    if (di->di_layer)
		DeleteLayer (NULL, di->di_layer);
	    DisposeLayerInfo (di->di_li);
	}
	if (di->di_workspace)
	{
	    di->di_rport.TmpRas = NULL;
	    FreeRaster ((PLANEPTR) di->di_workspace, width, height);
	}
	if (di->di_image.ImageData)
	    FreeMem (di->di_image.ImageData, di->di_size);
	di->di_layer = NULL;
	di->di_li = NULL;
	di->di_image.ImageData = NULL;
	di->di_workspace = NULL;
    }
}

/* PRIVATE Initialization Routines */

static BOOL
DIAllocFill (struct DynamicImage * di, USHORT width, USHORT height)
{

    if (di->di_workspace = (UBYTE *) AllocRaster (width, height))
    {
	/* Initialize Flood Fill Area */
	di->di_rport.TmpRas = (struct TmpRas *)
	InitTmpRas (&di->di_tmpras, di->di_workspace,
		    RASSIZE (width, height));
	di->di_rport.TmpRas = &di->di_tmpras;
	return (TRUE);
    }
    return (FALSE);
}

static BOOL
DIAllocLayer (struct DynamicImage * di, USHORT width, USHORT height)
{

    if (di->di_li = NewLayerInfo ())
    {
	if (di->di_layer =
	    CreateUpfrontLayer (di->di_li, &di->di_bmap,
				0, 0, (width - 1), (height - 1),
				LAYERSIMPLE, NULL))
	{
	    di->di_rport.Layer = di->di_layer;
	    return (TRUE);
	}
	DisposeLayerInfo (di->di_li);
    }
    return (FALSE);
}

