/****************************************************************************************

		IShChannel.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		IShChannel definition

		Revision History

		when		who			what & why
		==========	==========	======================================================
		11/23/99	Nba			added optimized tile storage to channel API
		05/17/99	scooper		add GetInterpolatedPixel
		04/28/99	Nba			Added inTile parameter to GetTile
		04/28/99	Frh			added clone methods
		04/19/99	dsm			modified PutTile
		04/06/99	del			Added MightBeChanged
		03/29/99	dsm			channel and layer are using the same change channel
		03/26/99	Mathieu		Test for dynamic channels
		03/16/99	dsm			Channel iterator GetTileIndex
		03/11/99	scooper		move GetChangeChannel to API, add Get/SetActive
		03/08/99	scooper		add optional bucket space rect parameter
		03/04/99	dsm			access by tile index
		03/03/99	scooper		add TChannelUpdateInfo
		03/02/99	Nba			added eDataReplicateBorders
		2/22/99		tsh			add new flag eDataUseDestBucket
		2/17/99		psq			Channel/Bucket/Layer API changes
		1/29/99		psq			TileAccessFlags
		12/04/98	Nba			GetTileSize
		11/25/98	cph			changed APIRects to TMCRects
		11/19/98	tsh			changed PutData and PutTile to be passed TChannelDataBucket*
		11/3/98		tsh			allow TChannelDataBucket to constructed from an existing TMCPixelBucket
		10/30/98	dsm			added uniform value tile support
		10/29/98	Nba			replaced TMCPixelBucket with TChannelDataBucket
		10/29/98	cph			added #include "MCImageStatusCode.h"
		10/27/98	tsh			fixed warning
		10/27/98	cph			added GetMemorySize()
		10/27/98	cph			removed IShRectIterator.h
		10/27/98	cph			new API for layers and channels
		10/15/98	Nba			added GetByteFormat
		09/28/98	Nba			new API for layers and channels
		09/02/98	cph			cleaned up API
		08/28/98	cph			added methods to IShChannel and Iterator
		08/26/98	cph			clean-up
		08/24/98	cph			added IShChannelIterator
		08/19/98	cph			changed I2DShChannel to IShChannel

*****************************************************************************************/
#ifndef __IShChannel__
#define __IShChannel__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "COMTypes.h"
#include "MCPixelBucket.h"
#include "LayerTypes.h"
#include "MCImageStatusCode.h"
#include "ColorRGB214.h"
#include "Vector2Fwd.h"

class TMCString;
class TGray16;
struct IShChannel;
struct IChangeChannel;
struct IShRasterLayer;
struct IYeildCallBackFunc;


//****** Globally Unique Ids *************************************************

MCDEFINE_GUID(IID_IShChannel, 0x4c23a50, 0x361e, 0x11d2, 0xb8, 0x7f, 0x0, 0x10, 0x4b, 0x2c, 0x90, 0x11);
MCDEFINE_GUID(IID_IShChannelTileIterator, 0x5fcfcd90, 0x67b7, 0x11d2, 0xb8, 0xa2, 0x0, 0x10, 0x4b, 0x2c, 0x90, 0x11);


//****** Type Defines ********************************************************

/// These flags are used in IShChannel::GetData() and IShChannel::PutData(). 
/// If the Channel is in wrap-mode, then rects outside the 
/// image are filled in, unless you specify eNeverWrap. 
///
enum EDataAccessFlags
{
	kDataRead		= eTileRead,		///< read access only
	kDataWrite		= eTileWrite,		///< write access only
	kDataReadWrite	= eTileReadWrite,
	kDataDisplay	= eTileDisplay,
	kDataNeverCopy	= 8,				///< if a copy is nec. (for instance the rect covers multiple tiles) then fail
	kDataForceCopy	= 16,				///< always get a copy of the data
	kDataReplicateBorders	= 32,		///< when specified, the data outside the channel is generated by duplicating
										///< the border insetad of doing wrap around
	kDataUseDestBucket		= 64,		///< [use with eDataForceCopy] destination pixel bucket is
										///< setup by caller to GetData.
	kDataSeamlessTiling		= 128		///< if you are outside the image, the image is flipped every tile
};
typedef uint32 TDataAccessFlags;


/// \addtogroup MCImage
/// \{

/// TChannelDataBucket is used to access part of the data of an IShChannel. Here is an example:
/// \code
///
///	//allocate a memory block that will receive a copy of the channel's data
/// //use a TMCArray as buffer so we get asserts if we go outside the bounds
///	TMCArray<real> distanceBuffer; 
///	distanceBuffer.SetElemCount( (tileRect.GetWidth()+fMaxRadius*4) * (tileRect.GetHeight()+fMaxRadius*4) );
///
///	int32 rmax= fMaxRadius;
///	TMCRect rect(outputRect.left-2*rmax,outputRect.top-2*rmax,outputRect.right+2*rmax,outputRect.bottom+2*rmax);
///
///	//fZBuffer is a TMCCountedPtr <IShChannel>
///	TChannelDataBucket distanceBucket;
///	fZBuffer->GetData(rect, &distanceBucket,(void*)distanceBuffer.BaseAddress(), eTileRead | kDataReplicateBorders);
///
///	const uint32 width  = outputRect.GetWidth();
///	const uint32 height = outputRect.GetHeight();
///	
///	real* dist= NULL;
///	for (uint32 y= rmax; y < (height+3*rmax); y++)
///	{
///		dist= (real*)distanceBucket.RowPtr32(y);
///		for (uint32 x= rmax; x < (width+3*rmax); x++)
///		{
///			// for each pixel in the buffer
///			gShellThreadUtilities->YieldProcesses(15);
///			const real pixelDistance= dist[x];
///			// Now do something with it...
///		}
///	}
///
///	fZBuffer->UnGetData(&distanceBucket,false); //Don't forget this !!!!
/// \endcode
///
class TChannelDataBucket : public TMCPixelBucket
{
protected:
	TMCPoint		fOrigin;				///< origin of the pixelbucket
	void*			fPrivateData;			///< private data used by MCImage channel API
	real32			fGamma;					///< gamma used to interpret 8-bit data
public:
	// constructors
	TChannelDataBucket()						{ fPrivateData = NULL; fGamma = 0.0; }
	TChannelDataBucket(TMCPixelBucket* pbuck) : TMCPixelBucket(pbuck)
												{ fPrivateData = NULL; fGamma = 0.0; }

	// methods
	TMCPoint	GetOrigin(void)	const			{ return fOrigin; }
	void		SetOrigin(const TMCPoint &p)	{ fOrigin = p; }

	void*		GetPrivateData(void) const		{ return fPrivateData; }
	void		SetPrivateData(void* data)		{ fPrivateData	= data;	 }

	real32		GetGamma(void) const			{ return fGamma; }
	void		SetGamma(const real32 g)		{ fGamma = g; }

	TMCRect		OffsetRect(void) const			{ TMCRect r = Rect(); return r+=fOrigin; }

};

/// \}

/*****************************************************************************\
*                                                                             *
*  IShChannelTileIterator                                                     *
*                                                                             *
\*****************************************************************************/

// This iterator takes a large target rect, splits it into sub-rects that overlap with tiles
// in the channel, and iterates over the sub-rects.

struct IShChannelTileIterator : IMCUnknown
{
public:
		// target is clipped if the channel does not support wrap-around
	virtual MCCOMErr		MCCOMAPI	First()=0;
	virtual boolean			MCCOMAPI	More(void)=0;
	virtual MCCOMErr		MCCOMAPI	Next()=0;

	// Rect coordinates in channel without wrapping
	virtual const TMCRect&	MCCOMAPI	GetRectInTarget()=0;
	// Rect coordinates in channel with wrapping
	virtual const TMCRect&	MCCOMAPI	GetRectInBounds()=0;
	// Rect coordinates in the tile
	virtual const TMCRect&	MCCOMAPI	GetRectInTile()=0;

	virtual uint			MCCOMAPI	GetTileIndex(TMCPoint *out_offset = NULL) const = 0;
	virtual MCCOMErr		MCCOMAPI	GetTile(const TChannelDataBucket** bucket, ETileAccess flags, TMCRect* out_localSource = NULL)=0;
	virtual MCCOMErr		MCCOMAPI	UnGetTile(const TChannelDataBucket** bucket, boolean dirty)=0;
};


/*****************************************************************************\
*                                                                             *
*  IShChannelUpdateInfo														  *
*                                                                             *
\*****************************************************************************/
struct IShChannelUpdateInfo : public IMCUnknown
{
public:
	virtual MCCOMErr MCCOMAPI GetUpdatedRect(TMCRect& out_rect) = 0;
	virtual MCCOMErr MCCOMAPI GetChannel(IShChannel** channel) = 0;
};

class TMCImageTileHeader;


/*****************************************************************************\
*                                                                             *
*  IShChannel                                                                 *
*                                                                             *
\*****************************************************************************/

struct IShChannel: public IMCUnknown
{   
	virtual uint32 MCCOMAPI		GetType()=0;
	virtual uint16 MCCOMAPI		GetBitDepth()=0;
	virtual uint16 MCCOMAPI		GetByteDepth()=0;
	virtual uint32 MCCOMAPI		GetMemorySize(uint32 width, uint32 height)=0; 
	virtual MCCOMErr MCCOMAPI	GetContentChangeChannel(IChangeChannel** changeChannel)=0;
	virtual MCCOMErr MCCOMAPI	GetPropertyChangeChannel(IChangeChannel** changeChannel)=0;
	virtual MCCOMErr MCCOMAPI	Clone(IShChannel** clone) = 0;
	virtual MCCOMErr MCCOMAPI	GenerateRGBRaster(IShRasterLayer **rasterLayer)= 0;

	virtual MCCOMErr MCCOMAPI	GetBounds(TMCRect& out_bounds)=0;
	// adjusted using wrap around
	virtual MCCOMErr MCCOMAPI	GetExtendedBounds(TMCRect& out_bounds)=0; 
	 // maximum size for a target rect used by IShRectIterator
	virtual MCCOMErr MCCOMAPI	GetTileSize(TMCRect& out_size)=0;

	// given a tile index, gives the tile bounds in the image
	virtual MCCOMErr MCCOMAPI	GetRectFromTileIndex(uint32 index, TMCRect &outTileBounds, const TMCRect *inTileBounds = NULL) const = 0;
	virtual uint32	 MCCOMAPI	GetTileIndexFromPoint(const TMCPoint& point, TMCPoint *out_offset = NULL) const = 0;

	// ---------------- optimal routine for accessing channel data
	virtual MCCOMErr MCCOMAPI	GetChannelTileIterator(IShChannelTileIterator** out_iter, const TMCRect& in_target)=0;	

	// --------------------- custom routines ------------------
	virtual MCCOMErr MCCOMAPI	GetData(const TMCRect& in_rect, TChannelDataBucket* dest, void* in_buffer, TDataAccessFlags flags, IYeildCallBackFunc* callBack)=0;
	// copy if nec. and release the data allocated using GetData()
	virtual MCCOMErr MCCOMAPI	UnGetData(TChannelDataBucket* bucket, boolean dirty)=0;
	// shortcut for a GetData() and UnGetData(); source is copied into channel
	virtual MCCOMErr MCCOMAPI	PutData(TChannelDataBucket * in_source, const TMCRect& in_dest, TDataAccessFlags flags)=0; // only valid flags like eNoWrap

	virtual MCCOMErr MCCOMAPI	Invalidate(const TMCRect& inRect) = 0;
	// direct tile access - eNoCopy and eNoWrap assumed
	virtual MCCOMErr MCCOMAPI	GetTile(const TMCRect& in_rect, const TChannelDataBucket** bucket, ETileAccess flags, TMCRect* out_localSource = NULL)=0;
	virtual MCCOMErr MCCOMAPI	GetTile(uint32 tileIndex, const TChannelDataBucket** bucket, ETileAccess flags, const TMCRect &inTile)=0;
	virtual MCCOMErr MCCOMAPI	UnGetTile(const TChannelDataBucket** bucket, boolean dirty)=0;
	virtual MCCOMErr MCCOMAPI	PutTile(const TMCRect& dest, const TChannelDataBucket * in_source, ETileAccess flags)=0;
	virtual MCCOMErr MCCOMAPI	PutTile(uint32 tileIndex, const TChannelDataBucket * in_source, ETileAccess flags, const TMCRect &inTile)=0;

	// Image data acces by pixel
	virtual uint8*	 MCCOMAPI	GetPixel(int32 x,int32 y,TMCImageTileHeader *&tileHeader)=0;
	virtual void	 MCCOMAPI	UnGetPixel(TMCImageTileHeader *tileHeader)=0;

	virtual MCCOMErr MCCOMAPI	GetTileUniformValue(const TMCRect& in_rect, boolean& is_uniform, uint32& value)=0;
	virtual MCCOMErr MCCOMAPI	GetInterpolatedPixel(const TVector2& inXY, TGray16& dest) = 0;

	virtual MCCOMErr MCCOMAPI	GetName(TMCString& name) = 0;
	virtual MCCOMErr MCCOMAPI	SetName(const TMCString& name) = 0;

	virtual boolean MCCOMAPI	GetVisibility() = 0;
	virtual MCCOMErr MCCOMAPI	SetVisibility(boolean visibility) = 0;

	virtual boolean MCCOMAPI	GetIsActive() = 0;
	virtual MCCOMErr MCCOMAPI	SetActive(boolean isActive) = 0;

	virtual boolean MCCOMAPI	GetEditability() = 0;
	virtual MCCOMErr MCCOMAPI	SetEditability(boolean editable) = 0;

	virtual MCCOMErr MCCOMAPI	GetDisplayColor(TColorRGB214& color, TGray16& opacity) = 0;
	virtual MCCOMErr MCCOMAPI	SetDisplayColor(const TColorRGB214& color, const TGray16& opacity) = 0;

	virtual MCCOMErr MCCOMAPI	GetID(TChannelID& id)=0;
	virtual MCCOMErr MCCOMAPI	SetID(TChannelID& id)=0;
	virtual boolean MCCOMAPI	MightBeChanged(IDType changeKind)=0; // Depending on its ID the channel might be concerned or not by changeKind

	virtual MCCOMErr MCCOMAPI	FillWithUniformValue(uint32 value)=0;
	virtual MCCOMErr MCCOMAPI	FillWithZeros()=0;
	virtual MCCOMErr MCCOMAPI	FillWithOnes()=0;

	virtual boolean  MCCOMAPI	IsDynamic() = 0;

	virtual void	MCCOMAPI	OptimizeTileStorage(uint32 tileIndex) = 0;
};


#endif
