#ifndef _gdiDC_
#define _gdiDC_
/*<<<***************************************************************************
The MIT License (MIT)

Copyright(C) 2013 - 2015 Marc Mirti Mancinelli, Christophe Lardau and Philippe Pamart (xdcube.org)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
////////////////////////////////////////////////////////////////////////////////
#Title: gdiDC
#Project: xdcGdi
////////////////////////////////////////////////////////////////////////////////
#Author: Marc MIRTI MANCINELLI
#History:
<17/09/2013: creation.
12/02/2014: this notice inserted.
***************************************************************************>>>*/

#ifndef _gdiITF_
#	include "gdiItf.h"
#endif

class gdiEXPORT __declspec(uuid("{68660D24-88EB-4eab-9F5C-C22950589ECD}"))
	gdiDClow:public xbObjectBase, public IgdiDC
{
public:
	xbImplObject();

	virtual bool GetInterface(REFIID riid, void ** ppInterf)
	{
		xbImplInterface(IgdiDC);
		xbImplInterface(gdiDClow);
		return xbObjectBase::GetInterface(riid,ppInterf);
	}

	HDC GetHandle() const {return m_hDC;}

	//IgdiDC methods
	virtual void Select(const gdiFont &font);
	virtual void Select(const gdiFontObject &font);
	virtual void Select(const gdiPen &pen);
	virtual void Select(IgdiBitmap *pBmp);
	virtual void SelectClear();

	virtual long GetPixelPerInchX() const;
	virtual long GetPixelPerInchY() const;

	virtual gdiBkMode GetBkMode() const;
	virtual void SetBkMode(gdiBkMode bkmode);

	gdiSizeLow GetTextSizeLow(const xbStringW &str) const
	{
		return GetTextSizeLow(str,str.Length);
	}
	virtual gdiSizeLow GetTextSizeLow(LPCWSTR pStr,int len) const;
	virtual xbStringW GetTextFace() const;
	virtual void SetTextColor(const gdiColor &clr);
	virtual void TextOut(long x,long y,gdiTextMode textMode,const gdiRectLow *pRect,LPCWSTR pStr,int len,const int *lpDX = NULL);
	void TextOut(long x,long y,gdiTextMode textMode,const gdiRectLow *pRect,const xbStringW &str,const int *lpDX = NULL)
	{
		TextOut(x,y,textMode,pRect,str,str.Length,lpDX);
	}
	virtual void GetTextExtentLow(LPCWSTR pStr,int len,long maxWidth,int *plenFit,gdiSizeLow *pSize,int *lpDX = NULL) const;
	void GetTextExtentLow(const xbStringW &str,long maxWidth,int *plenFit,gdiSizeLow *pSize,int *lpDX = NULL) const
	{
		GetTextExtentLow(str,str.Length,maxWidth,plenFit,pSize,lpDX);
	}
	virtual void TextMetrics(TEXTMETRICW *pMetrics) const;

	virtual void MoveToLow(long x,long y);
	virtual void LineToLow(long x,long y);
	virtual void VideoInvert(const gdiRectLow &rect);

	virtual xbRefPtr<IgdiDC> CreateCompatibleDC() const;
	virtual void AlphaDraw(long xDst,long yDst,long widthDst,long heightDst,
		IgdiDC &dcSrc,long xSrc,long ySrc,long widthSrc,long heightSrc,
		int cAlpha);
	virtual void StdDraw(long xDst,long yDst,long widthDst,long heightDst,
		IgdiDC &dcSrc,long xSrc,long ySrc,long widthSrc,long heightSrc);

	virtual bool HasAlpha() const {return m_bHasAlpha;}
	virtual bool DrawIcon(long xDst,long yDst,long widthDst,long heightDst,HICON hIcon,int nAni,gdiBrush *pBrush,xbOpMode opm = xbOp_Required);
	virtual void FillRect(const gdiRectLow *pRect,gdiBrush *pBrush);
protected:
	virtual void onBeforeDestruction(bool /*bInDestroy*/) 
	{
		eProtectTrace(SelectClear());
	}
	HGDIOBJ select(HGDIOBJ hObj);

	gdiDClow()
	{
		m_hDC = NULL;
		m_bHasAlpha = false;
		init();
	}
	gdiDClow(HDC hDC)
	{
		m_hDC = hDC;
		m_bHasAlpha = false;
		init();
	}
	virtual ~gdiDClow() {eProtectTrace(SelectClear(););}

	HDC m_hDC;
	bool	m_bSelectFont;
	HGDIOBJ	m_hSelectFont;
	bool	m_bSelectPen;
	HGDIOBJ	m_hSelectPen;
	bool	m_bSelectBmp;
	HGDIOBJ	m_hSelectBmp;
	xbRefPtr<IgdiBitmap> m_prSelectedBmp;
	xbLock				m_lckSelectedBmp;
	bool				m_bHasAlpha;

	void unselectBmp();

	void init()
	{
		m_bSelectFont = false;
		m_bSelectPen = false;
		m_bSelectBmp = false;
	}
private:
	xbDclNoCopyForObject(gdiDClow);
};

class gdiEXPORT __declspec(uuid("{1E5264D4-6467-4b34-92A0-DE65D9B05A5E}"))
	gdiScreenDC:public gdiDClow
{
public:
	gdiScreenDC(xbCtorMode ctorMode = xbCtor_CallCreate)
	{
		m_hDC = NULL;
		if (ctorMode == xbCtor_CallCreate)
			Create();
	}
	virtual bool GetInterface(REFIID riid, void ** ppInterf)
	{
		xbImplInterface(gdiScreenDC);
		return gdiDClow::GetInterface(riid,ppInterf);
	}
	virtual void Create()
	{
		gdiDClow::Create();
		if (!m_hDC)
			m_hDC = ::GetDC(NULL);
	}

	virtual ~gdiScreenDC() 
	{
		eProtectTrace(Destroy(););
	}
protected:
	virtual void onBeforeDestruction(bool bInDestroy) 
	{
		gdiDClow::onBeforeDestruction(bInDestroy);
		eProtectBegin();
		if (m_hDC != NULL)
		{
			::ReleaseDC(NULL,m_hDC);
			m_hDC = NULL;
		}
		eProtectEndTrace();
	}
private:
	xbDclNoCopyForObject(gdiScreenDC);
};

class gdiEXPORT __declspec(uuid("{679D97DD-CA72-48d0-B06A-3A4FDF0AB3D1}")) 
	gdiCompatibleDC:public gdiDClow
{
public:
	gdiCompatibleDC()
	{
		m_hDC = NULL;
	}
	virtual bool GetInterface(REFIID riid, void ** ppInterf)
	{
		xbImplInterface(gdiCompatibleDC);
		return gdiDClow::GetInterface(riid,ppInterf);
	}
	xbImplCreateObject(gdiCompatibleDC,gdiCompatibleDC);

	virtual ~gdiCompatibleDC() 
	{
		eProtectTrace(Destroy(););
	}
	void Init(HDC hDC)
	{
		Create();
		m_hDC = hDC;
	}
protected:
	virtual void onBeforeDestruction(bool bInDestroy) 
	{
		gdiDClow::onBeforeDestruction(bInDestroy);
		eProtectBegin();
		if (m_hDC != NULL)
		{
			::DeleteDC(m_hDC);
			m_hDC = NULL;
		}
		eProtectEndTrace();
	}
private:
	xbDclNoCopyForObject(gdiCompatibleDC);
};

#endif
