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

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

		MOVED FROM MCCore\Include

		Author:	Arnaud
		Date:	10/1/2003

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

#ifndef __MCPixelFX__
#define __MCPixelFX__

#if CP_PRAGMA_ONCE
#pragma once
#endif


#include "MCAssert.h"
#include "MCBasicTypes.h"
#include "MCRect.h"

#if __MWERKS__
#pragma global_optimizer on
#pragma optimization_level 4
#endif

/// Represents a Run Length Encoded image
///
class TMCRLEPixels
{
public:
	int32	fRowBytes;				///< Width and RowBytes are same in compressed data.
	int32	fHeight;
	uint8*	fCompressedPixels;
	uint32	fCompressedPixelsSize;
};


class TMCPixelBucket;

/// Undocumented (used by TMCPixelFX)
///
struct DoPixelFXData
{
	TMCPixelBucket* bucketDst;
	TMCRect       * translatedClip;
	TMCRect       * translatedRect;
};


// =================================================================================================================
// ChopProc Definition 
// =================================================================================================================	
typedef uint32	(*ChopProc) (register uint32 src, register uint32 dst);

/// \addtogroup MCCore
/// \{

/// TMCPixelFX is a class used to help the blit of TMCPixelBucket(s) (with different effects including resizing).
/// It is generally used to blit a TMCPixelBucket into an IMCGraphicContext. Here is an example:
/// \code
///	void MCCOMAPI TPreviewPart::SelfDraw(IMCGraphicContext* graphicContext, const TMCRect& inZone)
///	{
///		//fOffscreen is a TMCOffscreen*
///		if (MCVerify(graphicContext != NULL && fOffscreen != NULL))
///		{
///			uint32 dstX = inZone.GetWidth ();
///			uint32 dstY = inZone.GetHeight();
///		
///			if ( (dstX > 1) && (dstY > 1) ) //TMCPixelFX::BucketBlitResize32 doesn't work
///			{
///				TMCRect srcRect= fOffscreen->GetRect();
///				TMCRect dstRect;
///				TMCPoint offScreenSize( fOffscreen->GetWidth(), fOffscreen->GetHeight() );
///				dstRect.MaximizeInside(TMCRect(0, 0, fBounds.GetWidth(), fBounds.GetHeight()), offScreenSize);
///
///				TMCPixelFX pixelFX;
///				graphicContext->BlitBucket(fOffscreen->PixelBucket(), srcRect, dstRect, inZone, &pixelFX);
///			}
///		}
///	}
/// \endcode
///
class TMCPixelFX
{
public:
	 /// deprecated
	 ///
	 struct SGaussTable
	 {
  		int32	valid;			// boolean - table valid

 		int32	maxradius;
		int32	radius;
 		int32	isigma;			// ceil (radius) - number of "radius" pixels affected
 		int32	scratchsize;	// internal stuff
 		uint32	*scratchspace;	// internal stuff

		boolean	horizontal;		// blur horizontally?
		boolean	vertical;		// blur vertically?
	 };
	
public:
	// =================================================================================================================
	// Constructor/Destructor 
	// =================================================================================================================	
	TMCPixelFX  ();
	virtual ~TMCPixelFX ();
	boolean	IsValid()	{ return true; }

	// =================================================================================================================
	// Access Functions 
	// ================================	=================================================================================	
	void 		ClipRect 	(const TMCRect* _clip)	{MCAssertIfFalse (_clip);	fRectClip	=* _clip;}
	TMCRect		GetClipRect ()						{return fRectClip;}

	void 		SetChopProc (ChopProc proc)			{fChopproc	= proc;}
	ChopProc 	GetChopProc ()						{return fChopproc;}

	void 		SetTransparency (real32 amt)		{fTransparency = amt;}
	real32	 	GetTransparency ()					{return fTransparency;}

	void		SetTranslateTable (void* xlate)		{ fXlateTable = xlate; }
	void*		GetTranslateTable ()				{ return fXlateTable; }
	
	// =================================================================================================================
	// Functions 
	// =================================================================================================================	
	boolean	AdjustBlitRects			(TMCRect* totalsrc, TMCRect* totaldst, TMCRect* srcRect, TMCRect* dstRect);
	
	boolean BucketInvertRect 		(TMCPixelBucket* bucket, const TMCRect* rect, boolean colorblit, boolean alphablit);
	boolean BucketFillAlphaRect		(TMCPixelBucket* bucket, const TMCRect* rect, uint32 color);
	boolean BucketFillColorRect		(TMCPixelBucket* bucket, const TMCRect* rect, uint32 color);
	boolean BucketFillRect		 	(TMCPixelBucket* bucket, const TMCRect* rect, uint32 color);
	boolean BucketScrollRect 		(TMCPixelBucket* bucket, const TMCRect* rectptr, int32 x, int32 y);


	boolean BucketBlit 				(TMCPixelBucket* dst, const TMCRect* origDstRect, 	//only supports 32 to 32 right now
									 const TMCPixelBucket* src, const TMCRect* origSrcRect, 
									 boolean dither, boolean useSrcAlpha);

	boolean	BucketBlitDecompress	(TMCPixelBucket& inDestBucket, const TMCRect& inDstRect,
									 const TMCRLEPixels* inSrcPixels, const TMCRect& inSrcRect,
									 uint32 inColor);

	/// blit a pixel bucket to a bucket with the same rect
	///
	static void FastBucketBlit		(const TMCPixelBucket& dst, const TMCPixelBucket& src, const TMCRect& rect) {FastBucketBlit(dst, rect, src, rect);}

	/// blit bucket to bucket
	///
	static void FastBucketBlit		(const TMCPixelBucket& dst, const TMCRect& dstRect, const TMCPixelBucket& src, const TMCRect& srcRect);

	/// fill an entire pixel bucket with a color
	///
	static void FastBucketFill		(const TMCPixelBucket& pixelBucket, uint32 color);

	/// blit an entire pixel bucket to a bucket with the same size
	///
	static void FullBucketBlit		(const TMCPixelBucket& dst, const TMCPixelBucket& src);
									 	

	// =================================================================================================================
	// 8 Bits Functions 
	// =================================================================================================================	
	boolean BucketBlit32FromGray8			(TMCPixelBucket* dst, const TMCRect* dstrectptr, 
											 const TMCPixelBucket* src, const TMCRect* srcrectptr, 
									 		 uint32 color);

	boolean BucketBlit32FromGray8WNoResample(TMCPixelBucket* dst, const TMCPoint* dstrecttopleftptr, 
											 const TMCPixelBucket* src, const TMCRect* srcrectptr, 
									 		 uint32 color);

	boolean BucketBlitExtractAlpha8From32	(TMCPixelBucket* dst, const TMCRect* dstrectptr, 
									 		 const TMCPixelBucket* src, const TMCRect* srcrectptr);

	boolean BucketBlitExtractAlpha8From32WNoResample(TMCPixelBucket* dst, const TMCPoint* dstrecttopleftptr, 
									 		 const TMCPixelBucket* src, const TMCRect* srcrectptr);

	boolean BucketBlit8FromGray8	 (TMCPixelBucket* dst, const TMCRect* dstrectptr, 
									  const TMCPixelBucket* src, const TMCRect* srcrectptr, 
									  uint32 color);


	// =================================================================================================================
	// Gaussian Functions 
	// =================================================================================================================	
	boolean AllocGaussTable 		(SGaussTable* gauss, real32 maxradius, int32 width, int32 height);
	boolean ComputeGaussTable 		(SGaussTable* gauss, real32 radius, boolean horizontal, boolean vertical);
	void DestroyGaussTable 			(SGaussTable* gauss);

	boolean BucketGauss32 			(TMCPixelBucket* bucket, const TMCRect* rectptr, real32 radius, SGaussTable* gauss);
	boolean BucketGauss8 			(TMCPixelBucket* bucket, const TMCRect* rectptr, real32 radius, SGaussTable* gauss);


	// =================================================================================================================
	// Low Level Functions 
	// =================================================================================================================	

	void FlipBlitRect						(TMCPixelBucket* bucket, TMCRect* rect);

	boolean CompatiblePixelBuckets			(const TMCPixelBucket* src, const TMCPixelBucket* dst);	

	boolean EqualBuckets 					(const TMCPixelBucket* src, const TMCPixelBucket*  dst);

	boolean BucketFillRectAlphaOrColor		(TMCPixelBucket* bucket, const TMCRect* rect, uint32 color, 
											 boolean colorblit, boolean alphablt, 
											 real32 transparency, ChopProc chopproc);

	// =================================================================================================================
	// BucketBlit Functions 
	// =================================================================================================================	

	boolean BucketBlitEqualRect32 			(      TMCPixelBucket* dst, const TMCRect* dstRect, 
											 const TMCPixelBucket* src, const TMCRect* srcRect, 
											 int32 alpha = 256 , boolean useSrcAlpha = false , ChopProc chopproc = (ChopProc) 0);

	boolean BucketBlitNotEqualRect32	 	(      TMCPixelBucket* dst, const TMCRect* dstRect, 
									 		 const TMCPixelBucket* src, const TMCRect* srcRect, 
									 		 int32 alpha = 256 , boolean useSrcAlpha = false , ChopProc chopproc = (ChopProc) 0);

	boolean BucketBlitSampledRect32 		(      TMCPixelBucket* dst, const TMCRect* dstRect, 
											 const TMCPixelBucket* src, const TMCRect* srcRect, 
											 int32 alpha = 256 , boolean useSrcAlpha = false , ChopProc chopproc = (ChopProc) 0);

	/// BucketBlitResize32 = BucketBlitNotEqualRect32 with alpha=256 useSrcAlpha=false chopproc=0
	///
	boolean BucketBlitResize32				(	   TMCPixelBucket* dst, const TMCRect& dstRect , 
											 const TMCPixelBucket* src, const TMCRect& srcRect);

	/// == BucketBlitResize32 = BucketBlitResize32 with srcRect = 2*dstRect
	///
	boolean BucketBlitDown2x				(      TMCPixelBucket* dst,
											 const TMCPixelBucket* src);

	// =================================================================================================================
	// ScanLine Functions 
	// =================================================================================================================	

	void DrawScanLineWithAlpha 				(const register uint32* src, register uint32* dst, uint32 dstw);
	void DrawScanLineWithAlphaTransparent 	(const register uint32* src, register uint32* dst, uint32 dstw, int32* alphaarray);
	void LinearBlendScanLine				(uint32* dstptr, const uint32* srcptr, const uint32* srcrownext, int32 cursrcx, int32 srcw, int32 dstw, int32 errV, int32 hscale);
	void LinearBlendScanLineWithAlpha 		(uint32* dstptr, const uint32* srcptr, const uint32* srcrownext, int32 cursrcx, int32 srcw, int32 dstw, int32 errV, int32 hscale);

	// =================================================================================================================
	// Gradient Functions 
	// =================================================================================================================	

	/// preform gradient of src & color put result on dst
	///
	boolean BucketBlitEqualRect32VerticalGradient	
											(TMCPixelBucket* dst, const TMCRect* dstRect, 
											 const TMCPixelBucket* src, const TMCRect* srcRect, 
											 uint32 alphaStart , const uint32 alphaEnd , const uint32 color = 0x00000000);

	boolean BucketBlitEqualRect32VerticalGradient( DoPixelFXData *data );

	/// perform Vertical gradient on dst & color put result on dst
	///
	boolean BucketBlit32VerticalGradient	(TMCPixelBucket* dst, const TMCRect* dstRect, 											 
											 uint32 alphaStart, const uint32 alphaEnd  , const uint32 colorStart, const uint32 colorEnd);
	
	boolean BucketBlit32VerticalGradient	(DoPixelFXData *data );

	/// perform Horizontal gradient on dst & color put result on dst
	///
	boolean BucketBlit32HorizontalGradient	(TMCPixelBucket* dst, const TMCRect* dstRect, 											 
											 uint32 alphaStart, const uint32 alphaEnd  , const uint32 colorStart, const uint32 colorEnd);	
	
	boolean BucketBlit32HorizontalGradient	(DoPixelFXData *data );

	
	// =================================================================================================================
	// Draw Functions 
	// =================================================================================================================	

	boolean DrawLine32						  (TMCPixelBucket* dst, TMCPoint &pA, TMCPoint &pB , uint32 color = 0x00000000 , const TMCRect *clipRect=(TMCRect*)0);
	boolean DrawLine32Antialiased			  (TMCPixelBucket* dst, TMCPoint &pA, TMCPoint &pB , uint32 color = 0x00000000 , const TMCRect *clipRect=(TMCRect*)0);
	boolean DrawLine32AntialiasedAlphaChopProc(TMCPixelBucket* dst, TMCPoint &pA, TMCPoint &pB , uint32 color = 0x00000000 , const TMCRect *clipRect=(TMCRect*)0, int32 alpha = 0xff , ChopProc chopproc = (ChopProc) 0); /* alpha = 0-256*/

	boolean DrawLine32						(DoPixelFXData *data );
	boolean DrawLine32Antialiased			(DoPixelFXData *data );

protected:
	// =================================================================================================================
	// Data 
	// =================================================================================================================	
	TMCRect		fRectSrc;	//internal use
	TMCRect		fRectDst;	//internal use
	TMCRect		fRectClip;

	ChopProc	fChopproc;
	real32		fTransparency;	
	void*		fXlateTable;

};
/// \}

// =================================================================================================================
// ChopProcs
// =================================================================================================================	
uint32 MCXChopInvert 		(register uint32 src, register uint32 dst);
uint32 MCXChopInvertColor	(register uint32 src, register uint32 dst);
uint32 MCXChopInvertAlpha	(register uint32 src, register uint32 dst);
uint32 MCXChopAdd			(register uint32 src, register uint32 dst);
uint32 MCXChopSubtract		(register uint32 src, register uint32 dst);
uint32 MCXChopMultiply		(register uint32 src, register uint32 dst);
uint32 MCXChopScreen		(register uint32 src, register uint32 dst);
uint32 MCXChopOverlay		(register uint32 src, register uint32 dst);
uint32 MCXChopAlphaOnly		(register uint32 src, register uint32 dst);
uint32 MCXChopColorOnly		(register uint32 src, register uint32 dst);

enum EMCXChopID
{
	kNoChop,
	kChopInvert,
	kChopInvertColor,
	kChopInvertAlpha,
	kChopAdd,
	kChopSubtract,
	kChopMultiply,
	kChopScreen,
	kChopAlphaOnly,
	kChopColorOnly,
	kChopOverlay
};
extern ChopProc ChopProcIDToProc(EMCXChopID inProcID);

// =================================================================================================================
// Downsample
// =================================================================================================================	
boolean MC2XDownSample (const TMCPixelBucket* src, TMCPixelBucket* dst);

#if __MWERKS__
#pragma optimization_level reset
#pragma global_optimizer reset
#endif

#endif // for entire file



