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

		IMCGraphicContext.h

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

		Author:	Joshua
		Date:	4/21/98

		Graphic Context COM interface

		Revision History

		when		who			what & why
		==========	==========	======================================================
		10/29/99	Ian			Reverted StringWidth() to return an integer value, and added
								StringWidthReal() to get fractional string widths.
		8/1/99		Ian			CMCSavedPen() save the transparency.
		6/24/99		Ian			Added a FitStringInWidth that takes a TMCTextStyle, made
								all instances of it const.
		6/16/99		Ian			Removed Benjamin's uncommented change to the API.
		6/10/99		Yann		Removed unneeded #include to GCTypes.h. 
								Replaced the API* types by TMC* types and removed the #include "MCAPITypes.h"
		4/28/99		Ian			StringWidth() now returns a real32.
		4/2/99		Ian			Added BlitBucket().
		03/24/99	pbk			renamed DrawGraphicsContext to Blit and changed params
		03/01/99	pbk			added the GetSystemGCPtr call
		02/26/99	Mathieu		Added GetBucket() for direct blitting
		1/20/99		Pbk			Changed SetOrigin && GetOrigin
		12/4/98		cph			Added include for MCGCTypes.h
		7/16/98		Greg		Added GetOrigin()
		5/26/98		Joshua		Added COM API calls

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

#ifndef __IMCGRAPHICCONTEXT__
#define __IMCGRAPHICCONTEXT__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCBasicDefines.h"
#include "MCTextStyle.h"
#include "MCPublicGCTypes.h"
#include "MCCountedPtr.h"
#include "MCRGBColor.h"
#include "MCRect.h"
#include "MCPoint.h"
#include "MCPixelFX.h"

class  TMCPixelBucket;
class  TMCPolygon;
class  TMCOffscreen;
class  TMCRLEPixels;
struct DoPixelFXData;
class  TMCRectRegion;

//******************************** Globally Unique Id ****************************************

MCDEFINE_GUID_H(IID_IMCGraphicContext);

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

//Note: the CMCSaved* classes below can be used to automatically restore some properties of IMCGraphicContext 
//when you change them

/// \addtogroup MCCore
/// \{

/// IMCGraphicContext is the interface to access graphic contexts. Graphic contexts allow you to draw in
/// the backbuffer and one the screen. A typical place where you can use a graphic context is in
/// IMFPart::SelfDraw().
///
struct IMCGraphicContext : public IMCUnknown
{
	virtual void	 MCCOMAPI	SetOrigin					(const TMCPoint& inOrigin) = 0;
	virtual void	 MCCOMAPI	GetOrigin					(TMCPoint& outPoint) const = 0;

	virtual void	 MCCOMAPI	ClearClip					(void) = 0;
	virtual void	 MCCOMAPI	IntersectWithCurrentClip	(const TMCRect& inRect) = 0;
	virtual void	 MCCOMAPI	RemoveFromCurrentClip		(const TMCRect& inRect) = 0;
	virtual void	 MCCOMAPI	GetClipRect					(TMCRect& clipRect) const = 0;

	virtual void	MCCOMAPI	SetClipRegion				(TMCRectRegion* clipRgn) = 0;
	virtual TMCRectRegion* MCCOMAPI GetClipRegion			(boolean clone = false) const = 0;

	virtual void	 MCCOMAPI	ScrollRect					(const TMCRect& arect, MCXYPos dX, MCXYPos dY,
															 TMCRect& outHorizontalInval, TMCRect& outVerticalInval) = 0;

	virtual boolean  MCCOMAPI	GetPixelColor				(TMCRGBColor& outColor, MCXYPos xPos, MCXYPos yPos) const = 0;
	virtual void	 MCCOMAPI	SetPixel					(MCXYPos xPos, MCXYPos yPos, const TMCRGBColor& acolor) = 0;

	virtual void	 MCCOMAPI	SetPen						(MCPenMode aPenMode, MCPenType aPenType, MCPenSize size, const TMCRGBColor& inColor) = 0;
	virtual void	 MCCOMAPI	GetPen						(MCPenMode& outPenMode, MCPenType& outPenType, MCPenSize& outSize, TMCRGBColor& outColor) = 0;
	virtual void	 MCCOMAPI	ResetPen					(void) = 0;

	virtual void	 MCCOMAPI	GetFillColor				(TMCRGBColor& inColor) = 0;
	virtual void	 MCCOMAPI	GetEraseColor				(TMCRGBColor& inColor) = 0;
	virtual void	 MCCOMAPI	GetPenColor					(TMCRGBColor& inColor) = 0;
	virtual void	 MCCOMAPI	SetFillColor				(const TMCRGBColor& inColor) = 0;
	virtual void	 MCCOMAPI	SetEraseColor				(const TMCRGBColor& inColor) = 0;
	virtual void	 MCCOMAPI	SetPenColor					(const TMCRGBColor& inColor) = 0;


	virtual void	 MCCOMAPI	DrawLine					(MCXYPos x1, MCXYPos y1, MCXYPos x2, MCXYPos y2) = 0;
	virtual void	 MCCOMAPI	Move						(const MCXYPos xDelta, const MCXYPos yDelta) = 0;
	virtual void	 MCCOMAPI	MoveTo						(int32 xPos, int32 yPos)=0;
	virtual void	 MCCOMAPI	Line						(const MCXYPos xDelta, const MCXYPos yDelta) = 0;
	virtual void	 MCCOMAPI	LineTo						(int32 xPos, int32 yPos)=0;

	virtual void	 MCCOMAPI	EraseRect					(const TMCRect& theRect) = 0;
	virtual void	 MCCOMAPI	InvertRect					(const TMCRect& theRect) = 0;
	virtual void	 MCCOMAPI	InvertHiliteRect			(const TMCRect& theRect) = 0;
	virtual void	 MCCOMAPI	FrameRect					(const TMCRect& theRect)=0;
	virtual void	 MCCOMAPI	FillRect					(const TMCRect& theRect, const TMCRGBColor& inColor)=0;
	virtual void	 MCCOMAPI	PaintRect					(const TMCRect& theRect) = 0;
	virtual void	 MCCOMAPI	DimRect						(const TMCRect& theRect) = 0;

	virtual void	 MCCOMAPI	FrameRoundRect				(const TMCRect& theRect, int16 radius) = 0;
	virtual void	 MCCOMAPI	FillRoundRect				(const TMCRect& theRect, const TMCRGBColor& inColor, int16 radius) = 0;
	virtual void	 MCCOMAPI	PaintRoundRect				(const TMCRect& theRect, int16 radius) = 0;

	virtual void	 MCCOMAPI	FrameOval					(const TMCRect& theRect) = 0;
	virtual void	 MCCOMAPI	FillOval					(const TMCRect& theRect, const TMCRGBColor& inColor)=0;
	virtual void	 MCCOMAPI	PaintOval					(const TMCRect& theRect) = 0;

	virtual void	 MCCOMAPI	FrameOvalArc				(const TMCRect& theRect, real32 begin, real32 delta) = 0;
	virtual void	 MCCOMAPI	PaintOvalArc				(const TMCRect& theRect, real32 begin, real32 delta) = 0;
	virtual void	 MCCOMAPI	FillOvalArc					(const TMCRect& theRect, real32 begin, real32 delta, const TMCRGBColor& inColor) = 0;

	virtual void	 MCCOMAPI	FramePoly					(const TMCPolygon& apoly) = 0;
	virtual void	 MCCOMAPI	FillPoly					(const TMCPolygon& apoly, const TMCRGBColor& inColor) = 0;
	virtual void	 MCCOMAPI	PaintPoly					(const TMCPolygon& apoly) = 0;

	virtual void	 MCCOMAPI	DrawString					(const TMCRect& theRect, const TMCString& astring, MCTextJustification just, MCTextMode mode) = 0;
	virtual void	 MCCOMAPI	FitStringInWidth			(TMCString&	string,	int16 maxWidth, MCTextJustification	method) const = 0;
	virtual void	 MCCOMAPI	FitStringInWidth			(TMCString& string, int16 maxWidth, MCTextJustification	method, const TMCTextStyle&	inStyle) const = 0;
	virtual uint32	 MCCOMAPI	StringWidth					(const TMCString& astring) const = 0;  
	virtual uint32	 MCCOMAPI	StringWidth					(const TMCString& astring, const TMCTextStyle& inStyle) const = 0;  
	virtual real32	 MCCOMAPI	StringWidthReal				(const TMCString& astring) const = 0;  
	virtual real32	 MCCOMAPI	StringWidthReal				(const TMCString& astring, const TMCTextStyle& inStyle) const = 0;  
	virtual uint32	 MCCOMAPI	PixelWidthToStringIndex		(const int32 inPixelWidth, const TMCString&	inString, const TMCTextStyle& inStyle) const = 0;

	virtual uint32	 MCCOMAPI	PixelWidthToStringIndex		(const int32 inPixelWidth,const TMCString& inString) const = 0;

	virtual void	 MCCOMAPI	SetTextStyle				(const TMCTextStyle& newStyle) = 0;
	virtual void	 MCCOMAPI	SetTextColor				(const TMCRGBColor& color)=0;  
	virtual void	 MCCOMAPI	GetTextStyle				(TMCTextStyle& newStyle) = 0;
	virtual void	 MCCOMAPI	GetTextColor				(TMCRGBColor& color) const = 0;
	virtual void	 MCCOMAPI	GetMCTextMetrics			(TMCTextMetrics& outMetrics) const = 0;
	virtual void	 MCCOMAPI	GetMCTextMetrics			(const TMCTextStyle& inStyle, TMCTextMetrics& outMetrics) const = 0;

	virtual void	 MCCOMAPI	Blit						(IMCGraphicContext* aGD, const TMCRect& srcRect,
															 const TMCRect& dstRect, TMCPixelFX* pixelFX = NULL,
															 boolean inDither = false, boolean inRespectAlpha = false ) = 0;

	virtual void	 MCCOMAPI	Blit						(	TMCOffscreen&	aGD,
																const TMCRect&	srcRect,
																const TMCRect&	dstRect) = 0;

	virtual void	 MCCOMAPI	BlitOffscreen				(	TMCOffscreen&	src,
																const TMCRect&	srcRect,
																const TMCRect&	dstRect,
																const TMCRect&	clipRect,
																TMCPixelFX*		pixelFX = NULL,
																boolean			inDither = false,
																boolean			inRespectAlpha = false) = 0;

	// ****************************************************************************
	//								BlitBucket
	// 
	/// Blits the content of a pixel bucket. Not that you need to pass a pixelFX if
	/// you expect the clipping to work properly.
	/// 
	/// \param src              Pixel bucket that contains the image to blit.
	/// \param srcRect          The sub rectangle of the pixel bucket that needs to be blitted (to blit the full pixel bucket use TMCPixelBucket::Rect() )
	/// \param dstRect          The destination rect in the context coordinates
	/// \param clipRect         A rectangle used to clip the destination (does not work when there no pixelFX!)
	/// \param pixelFX          A pixel effect used to blit
	/// \param inDither         Apply dithering
	/// \param inRespectAlpha   Respect alpha channel if any (not that it will only work if you pass a pixelFX)
	/// 
	virtual void	 MCCOMAPI	BlitBucket					(TMCPixelBucket& src, const TMCRect& srcRect,
															 const TMCRect&	dstRect, const TMCRect&	clipRect,
															 TMCPixelFX* pixelFX = NULL, boolean inDither = false,
															 boolean inRespectAlpha = false) = 0;
	

	virtual void	 MCCOMAPI	BlitCompressedBits			(	TMCRLEPixels&		src,
																const TMCRect&		srcRect,
																const TMCRect&		dstRect,
																const TMCRGBColor&	inGrayscaleColor,
																TMCPixelFX&			pixelFX,
																const TMCRect&		clipRect) = 0;


	virtual void	 MCCOMAPI	DoPixelFX					(	TMCPixelFX&			pixelFX, 
																const TMCRect&		clipTo,
																const TMCRect&		imageRect,
																boolean (TMCPixelFX::*function)(DoPixelFXData *), 
																DoPixelFXData *data ) = 0 ;	

	virtual void	 MCCOMAPI	GetClosestColor				(const TMCRGBColor& acolor, TMCRGBColor& closest) = 0;

	virtual void	 MCCOMAPI	SetTransparency				(real32 inTransparency) = 0;
	virtual real32	 MCCOMAPI	GetTransparency				() const = 0;
	
	virtual void	 MCCOMAPI	FillRectWithTransparency	(const TMCRect& theRect, const TMCRGBColor& inColor,real32 inTransparency) = 0;

	virtual SystemGCPtr	MCCOMAPI GetSystemGCPtr				(void) const = 0;

	virtual void	 MCCOMAPI	GetBucket					(TMCPixelBucket*&) = 0;

	virtual MCCOMErr MCCOMAPI	GetNewGraphicContext		(uint32 width, uint32 height,  IMCGraphicContext** outContext) = 0;
	
	// ****************************************************************************
	//								FlushOnScreen
	// 
	/// Call Only implemented on MacOsX (for now)
	/// Sends the given flushZone on screen (or the whole context if the pointer is null
	///
	/// \param flushZone  
	/// 
	virtual void	 MCCOMAPI	FlushOnScreen				(const TMCRect* flushZone) = 0;


	///Same than SetClipRegion, but the context will own the region (and delete it)
	virtual void	MCCOMAPI	RestoreClipRegion			(TMCRectRegion* clipRgn) = 0;
};

/// \}

//	SAVE/RESTORE ------------------------------------------

class CMCSavedPen
{
public:
	CMCSavedPen		(IMCGraphicContext* inContext)			{ fContext = inContext;  Save(); }
	CMCSavedPen		(IMCGraphicContext& inContext)			{ fContext = &inContext; Save(); }
	~CMCSavedPen	()										{ Restore(); }
	
private:
	inline void Save		();
	inline void Restore		();
private:
	IMCGraphicContext*	fContext;	//no need to count
	
	MCPenType			fSavedPenType;
	MCPenMode			fSavedPenMode;
	MCPenSize			fSavedPenSize;
	TMCRGBColor			fSavedPenColor;
	real32				fSavedTransparency;
};


class CMCSavedRGBs
{
public:
	CMCSavedRGBs		(IMCGraphicContext* inContext)		{ fContext = inContext;  Save(); }
	CMCSavedRGBs		(IMCGraphicContext& inContext)		{ fContext = &inContext; Save(); }
	~CMCSavedRGBs		(void)								{ Restore(); }

	inline const TMCRGBColor& GetSavedFillColor	() const	{ return fSavedFill; }
	inline const TMCRGBColor& GetSavedEraseColor() const	{ return fSavedErase; }
	inline const TMCRGBColor& GetSavedPenColor	() const	{ return fSavedErase; }

private:	   
	inline void Save		();
	inline void Restore		();
private:
	IMCGraphicContext*	fContext;
	TMCRGBColor			fSavedFill;
	TMCRGBColor			fSavedErase;
	TMCRGBColor			fSavedPenColor;
};


class CMCSavedFont
{
public:
	inline CMCSavedFont		(IMCGraphicContext* inContext)	{ fContext = inContext;  Save(); }
	inline CMCSavedFont		(IMCGraphicContext& inContext)	{ fContext = &inContext; Save(); }		
	inline ~CMCSavedFont	()								{ Restore(); }
	
	inline void Restore		(); //In case you need to restore by hand before the destructor is called
private:
	inline void Save		();	
private:
	IMCGraphicContext*	fContext;
	TMCTextStyle		fSavedStyle;
	TMCRGBColor			fSavedTextColor;
};


class CMCSavedOriginAndClip
{
public:
	inline CMCSavedOriginAndClip	(IMCGraphicContext* inContext)	{ fContext = inContext;  Save(); }
	inline CMCSavedOriginAndClip	(IMCGraphicContext& inContext)	{ fContext = &inContext; Save(); }			
	inline ~CMCSavedOriginAndClip	()								{ Restore(); }
	
private:
	inline void Save				();
	inline void Restore				();
private:
	IMCGraphicContext*	fContext;
	TMCPoint			fSavedOrigin;
	TMCRect				fSavedClip;
	TMCRectRegion*		fClipRegion;
};




/////////////////////////////////////////////////
inline void CMCSavedPen::Save(void)
{
	MCAssert(fContext);
	fContext->GetPen(fSavedPenMode, fSavedPenType, fSavedPenSize, fSavedPenColor);
	fSavedTransparency = fContext->GetTransparency();
}

inline void CMCSavedPen::Restore(void)
{
	MCAssert(fContext);
	fContext->SetPen(fSavedPenMode, fSavedPenType, fSavedPenSize, fSavedPenColor);
	fContext->SetTransparency(fSavedTransparency);
}

/////////////////////////////////////////////////
inline void CMCSavedRGBs::Save()
{
	MCAssert(fContext);
	fContext->GetFillColor(fSavedFill);
	fContext->GetEraseColor(fSavedErase);
	fContext->GetPenColor(fSavedPenColor);
}

inline void CMCSavedRGBs::Restore()
{
	MCAssert(fContext);
	fContext->SetFillColor(fSavedFill);
	fContext->SetEraseColor(fSavedErase);
	fContext->SetPenColor(fSavedPenColor);
}

/////////////////////////////////////////////////
inline void CMCSavedFont::Save(void)
{
	fContext->GetTextStyle(fSavedStyle);
	fContext->GetTextColor(fSavedTextColor);
}

inline void CMCSavedFont::Restore(void)
{
	fContext->SetTextStyle(fSavedStyle);
	fContext->SetTextColor(fSavedTextColor);
}

/////////////////////////////////////////////////
inline void CMCSavedOriginAndClip::Save(void)
{
	fContext->GetOrigin(fSavedOrigin);
	fContext->GetClipRect(fSavedClip);
	fClipRegion= fContext->GetClipRegion(true);
}

inline void CMCSavedOriginAndClip::Restore(void)
{
	fContext->SetOrigin(fSavedOrigin);
	fContext->ClearClip();
	if (fClipRegion)
	{
		fContext->RestoreClipRegion(fClipRegion);
		fClipRegion= NULL; //GetClipRegion clones the region, RestoreClipRegion takes back the ownership
	}
	else
		fContext->IntersectWithCurrentClip(fSavedClip);
}

#endif