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

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

		MOVED FROM MCCore\Include

		Author:	Arnaud
		Date:	10/1/2003

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

#ifndef __MCOffscreen__
#define __MCOffscreen__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCBasicTypes.h"
#include "MCPixelBucket.h"
#include "MCGCTypes.h"

struct IMCGraphicContext;
class TMCGraphicContext;
class TMCPoint;
class TMCRect;

/// \addtogroup MCCore
/// \{

/// TMCOffscreen is a platform specific block of pixels (bitmap) that can be sent quickly to the screen.
/// The block is generally padded for alignment, so you must use GetBaseAddress() + rowIndex * GetRowBytes()
/// to find the begining of a row. 
///
/// The PixelBucket() method returns a TMCPixelBucket that references the memory of the offscreen,
/// and that you can either manipulate directly, or pass to other functions.
///
/// TMCOffscreen owns its memory and will delete it. But since TMCOffscreen is not a counted object, 
/// you'll need to explicitely delete the offscreen. So it is a good idea to use a smart pointer:
/// TMCSmartPtr<TMCOffscreen> offscreen;
///
class TMCOffscreen
{
public:
		static TMCOffscreen*	Create(uint32 width, uint32 height, uint32 bitDepth,
									int32 inLeft = 0, int32 inTop = 0,
									boolean rightSideUp = true, boolean allowGCDrawing = true);

		static TMCOffscreen*	Create(const TMCOffscreen& inOffscreen);

		static MCCOMErr			CreateCompatiblePixelBucket(
									int32 widthParam,
									int32 heightParam,
									int32 depthParam,
									TMCCompatiblePixelBucket** outBucket);

		static MCCOMErr			DestroyCompatiblePixelBucket(TMCCompatiblePixelBucket* inBucket);


		enum EBlitMode
		{
			kBitBltCopy			= 0,
			kBitBltAnd			= 1,
			kBitBltOr			= 2,
			kBitBltColorize		= 3,
			kBitBltXor			= 4,
			kBitBltDitherCopy	= 5,
			kBitBltNotSrcBic	= 6,
			kInvalidBlitMode 	= 0xFFFFFFFF // to force 4 bytes
		};

		enum EJustification
		{
			kJustTopLeft		=0,
			kJustFullCenter		=1,
			kInvalidJustification = 0xFFFFFFFF // to force 4 bytes
		};

		enum EBlitType
		{
			eBlitNormal			= 0, 
			eBlitDithered 		= 1,
			eInvalidBlitType 	= 0xFFFFFFFF // to force 4 bytes
		};

		// =================================================================================================================
		// BlitLocations
		// =================================================================================================================
		enum EBlitLocation
		{
			eUpperLeft = 0,		eUpperCenter,		eUpperRight,
			eLeftCenter,		eCenter,			eRightCenter,
			eBottomLeft,		eBottomCenter,		eBottomRight
		};
		
	protected:
		// =================================================================================================================
		// Protected Cross Platform
		// =================================================================================================================
		boolean			fValid;
		EBlitType		fBlitType;
		TMCPixelBucket	fPixelBucket;
		int32			fTop;
		int32			fLeft;
		uint32			fWidth;
		uint32			fHeight;
		uint8*			fBaseAddress;
		uint32			fBitDepth;										
		uint32			fRowBytes;
		uint32			fPadding;
		uint32			fPlanes;
		PixelBucketType	fBucketType;
		boolean			fRightSideUp;
		boolean			fAllowGCDrawing;

		int32			fPrepared;
		SystemGCPtr		fGCDrawPtr;

		// =================================================================================================================
		// Default setup for all constructors
		// =================================================================================================================
		
		//Arnaud: the following 3 virtuals have been DEPRECATED. Do NOT call them
		//Do NOT remove them either so that the virtual table stays the same (for the interactiverenderer...)

		/// DEPRECATED
		virtual boolean	DefaultInitBegin(void);

		/// DEPRECATED
		virtual void	DefaultInitEnd(void);

		/// DEPRECATED
		virtual void	ClearAllPointers(void);
		
		//Arnaud: Instead, use the following methods. 
		//They are non virtual because they are called in constructors (didn't work anymore in CW6).
		void	DefaultInitMCOffscreenBegin(void);
		void	DefaultInitMCOffscreenEnd(void);
		void	ClearAllMCOffscreenPointers(void);

		// =================================================================================================================
		// Protected blit, implemented by the derived platform specific class.
		// =================================================================================================================
		virtual boolean	Blit(SystemGCPtr destGC, const TMCRect& dstRect, const TMCRect& srcRect) const;

		//Handles blit's outside the offscreen (proportional clipping).
		boolean 		AdjustRectsForBlit(
							const TMCRect&	totalsrc,
							const TMCRect&	totaldst,
							TMCRect&		srcRect,
							TMCRect&		ioDstRect) const;

		

	public:
		// =================================================================================================================
		// =================================================================================================================
		// Constructors
		// =================================================================================================================
		// =================================================================================================================
						TMCOffscreen(	uint32 width,
										uint32 height,
										uint32 bitDepth,
										int32 left,
										int32 top,
										boolean rightSideUp = true,
										boolean allowGCDrawing = true);

						/// Deprecated (not implemented)
						TMCOffscreen(IMCGraphicContext& hDC, const TMCRect& rect, uint32 bitDepth,
									boolean rightSideUp = true, boolean allowGCDrawing = true);

						TMCOffscreen(const TMCOffscreen& existingOffscreen);

		// =================================================================================================================
		// Destructor
		// =================================================================================================================
		virtual			~TMCOffscreen(void);

		// =================================================================================================================
		// Validity
		// =================================================================================================================
		boolean			IsValid(void) const 	{ return fValid; }

		// =================================================================================================================
		// Platform independent methods
		// =================================================================================================================
		virtual TMCPixelBucket&			PixelBucket(void)				{ return fPixelBucket;	}
		virtual const TMCPixelBucket&	PixelBucket(void) const			{ return fPixelBucket;	}
		uint32							GetWidth(void) const			{ return fWidth;		}
		uint32							GetHeight(void) const			{ return fHeight;		}
		int32							GetLeft(void) const				{ return fLeft;			}
		int32							GetTop(void) const				{ return fTop;			}
		uint8*							GetBaseAddress(void)			{ return fBaseAddress;	}
		const uint8*					GetBaseAddress(void) const		{ return fBaseAddress;	}
		uint32							GetBitDepth(void) const			{ return fBitDepth;		}										
		uint32							GetRowBytes(void) const			{ return fRowBytes;		}
		uint32							GetPadding(void) const			{ return fPadding;		}
		uint32							GetPlanes(void) const			{ return fPlanes;		}
		boolean							GetRightSideUp(void) const		{ return fRightSideUp;	}
		EBlitType						GetBlitType(void) const			{ return fBlitType; 	}
		boolean							GetAllowGCDrawing(void) const	{ return fAllowGCDrawing; }
		virtual TMCRect					GetRect(void) const;
		virtual boolean					GetRect(TMCRect& rect) const;
		virtual SystemGCPtr				PrepareForGraphicContextDraw(void);
		virtual void					FinishedGraphicContextDraw(void);
		virtual void					SetOrigin(MCXYPos xPos, MCXYPos yPos);

		virtual void	FillMCInformation(void); ///< DEPRECATED

		uint32			CalcRowBytes(uint32 width, uint32 bitDepth)
						{return ((width * bitDepth) + 31) / 32 * 4;}

		virtual boolean	SetBlitType(TMCOffscreen::EBlitType type);

		// =================================================================================================================
		// Pixel stuff - just for convenience
		// =================================================================================================================
		virtual void	GetPixel(int32 xLoc, int32 yLoc, TMCARGBColor& pixel) const;

		virtual void	SetPixel(int32 xLoc, int32 yLoc, const TMCARGBColor& pixel);
		
		// =================================================================================================================
		// =================================================================================================================
		// Blitting methods
		// =================================================================================================================
		// =================================================================================================================
		boolean	Blit(TMCOffscreen& destOffscreen) const;
		boolean	Blit(TMCOffscreen& destOffscreen, const TMCRect& dstRect) const;
		boolean	Blit(TMCOffscreen& destOffscreen, const TMCRect& dstRect, const TMCRect& srcRect) const;
		boolean	Blit(IMCGraphicContext& destContext, const TMCRect& dstRect) const;
		boolean	Blit(IMCGraphicContext& destContext, const TMCRect& dstRect, const TMCRect& srcRect) const;

		//Blit the offscreen starting at the destination point dstPt.
		virtual boolean BlitAtPoint(TMCOffscreen& destOffscreen, const TMCPoint& dstPt,
									EBlitLocation blitLocation)const;

		//This returns what the destination rect would be if we blitted ourselves at xLoc, yLoc.
		virtual boolean	GetBlitAtPointRect( const TMCPoint& dstPt, EBlitLocation blitLocation,
									TMCRect& rect) const;
};

/// \}

#endif
