//==========================================================================
//			Draws 2D using hardware acceleration without slow GDI calls.
//==========================================================================
#ifndef __D3D11PAD_H
#define __D3D11PAD_H

#include "Resources.h"

extern oapi::Font *def_Font;
extern oapi::Pen *def_Pen;

class Texture;

inline void D3DXCOLORSWAP(D3DXCOLOR *x) {
	float a = x->r;
	x->r = x->b;
	x->b = a;
}

class D3D11Pad : public oapi::Sketchpad
{
public:
	static void GlobalInit();
	static void GlobalExit();

	D3D11Pad( SURFHANDLE surf, bool _static = false );
	~D3D11Pad();

	oapi::Font *SetFont( oapi::Font *font ) const;
	oapi::Pen *SetPen( oapi::Pen *pen ) const;
	oapi::Brush *SetBrush( oapi::Brush *brush ) const;

	void SetTextAlign( TAlign_horizontal TA_h = LEFT, TAlign_vertical TA_v = TOP );

	DWORD SetTextColor( DWORD color );
	DWORD SetBackgroundColor( DWORD color );
	void SetBackgroundMode( BkgMode bk_mode );

	DWORD GetCharSize();
	DWORD GetTextWidth( const char *str, int len = 0 );

	void SetOrigin( int x, int y );
	bool Text( int x, int y, const char *str, int len );
	void Pixel( int x, int y, DWORD color );
	void MoveTo( int x, int y );
	void LineTo( int x, int y );
	void Line( int x0, int y0, int x1, int y1 );
	void Rectangle( int x0, int y0, int x1, int y1 );
	void Ellipse( int x0, int y0, int x1, int y1 );
	void Polygon( const oapi::IVECTOR2 *pt, int npt );
	void Polyline( const oapi::IVECTOR2 *pt, int npt );
	HDC GetDC();
private:
	HDC hDC;

	bool HasPen();
	bool HasBrush();
	bool HasWidePen();
	bool IsDashed();

	void Ellipse2( float x, float y, float w, float h );
	void Rectangle2( float x, float y, float w, float h );
	void Rectangle3( float x, float y, float w, float h, int width );
	void Lines( D3DXVECTOR3 *pVert, int count );

	int CheckTriangle( short x, const D3DXVECTOR3 *pt, const WORD *Idx, float hd, short npt, bool bSharp );
	int CreatePolyIndexList( const D3DXVECTOR3 *pt, short npt, WORD *Out );

	mutable oapi::Font *cfont;
	mutable oapi::Pen *cpen;
	mutable oapi::Brush *cbrush;

	mutable D3DXCOLOR
		TextColor,
		PenColor,
		BrushColor,
		BkColor;

	DWORD
		BkMode,
		HAlign, VAlign;

	int	origx, origy, cx, cy;

	DWORD
		width,
		height;
	Texture *TEX;
	ID3D11Texture2D *Tex;
//	ID3D11ShaderResourceView *SRV_Tex;		//?
	ID3D11RenderTargetView *RTV_Tex;		//?

	void ExtendVertexBuffer( UINT new_size );
	void ExtendIndexBuffer( UINT new_size );
	void SetRParams( D3DXVECTOR4 *data = NULL );

	static UINT
		vb_size,
		ib_size;

	static ID3D11InputLayout
		*IL_D3DXVECTOR3;

	static ID3D11Buffer
		*Circle_low,
		*Circle_high,
		*VB,
		*IB,
		*cb_VS,
		*cb_PS;
		

	static ID3D11VertexShader
		*VS_Ellipse,
		*VS_WideRect,
		*VS_Line,
		*VS_Fill;

	static ID3D11PixelShader
		*PS_Draw,
		*PS_Fill;

	static const UINT
		SkpStride,
		VBOffset;

	static const float	BlendFactors[4];

	struct cbuffer0 {
		D3DXMATRIX M;
		D3DXVECTOR4 Data;
	} VSCB;

	struct cbuffer1 {
		D3DXCOLOR COL;
		UINT32 Dash;
		float nodata[3];
	} PSCB;
};

class D3D11PadFont : public oapi::Font
{
	friend class GDIPad;
	friend class D3D11Pad;
public:
	D3D11PadFont( int height, bool prop, const char *face, Style style, int orientation );
	~D3D11PadFont();

private:
	class D3D11Text *pFont;
	HFONT hFont;
	bool bDelete;
	float rotation;
};

class D3D11PadPen : public oapi::Pen
{
	friend class GDIPad;
	friend class D3D11Pad;
public:
	//tech init ?
	D3D11PadPen( int style, int width, DWORD col );
	~D3D11PadPen();
private:
	int style, width;
	D3DXCOLOR fcolor;
	HPEN hPen;
};

class D3D11PadBrush : public oapi::Brush
{
	friend class GDIPad;
	friend class D3D11Pad;
public:
	D3D11PadBrush( DWORD col );
	~D3D11PadBrush();
private:
	D3DXCOLOR fcolor;
	HBRUSH hBrush;
};

//====================================================================
//====================================================================

typedef struct {
	float x, y;
	float tu, tv;
} TEXTVERTEX;

struct D3D11FontData {
	float w, h;		// X,Y position of the charter baseline
	float sp;
	float tx0, ty0;
	float tx1, ty1;
	BYTE s, e;		// s=special charter flag, e=extend charter height
};

class D3D11Text {
public:
	static void GlobalInit();
	static void GlobalExit();

	D3D11Text();
	~D3D11Text();

	void SetCharSet( int _CharSet = ANSI_CHARSET );	// Must be set before Init

	bool Init( HFONT hFont, int final = 255 );
	bool Init( LOGFONTA *fnt, int final = 255 );
	bool Init( int size = 24, int Style = FIXED_PITCH | FF_MODERN, int weight = 500, int last = 255 );
	bool Init( int size = 24, char *fontname = NULL, int weight = 500, int last = 255 );

	void SetLineSpace( int percent = 10 );
	void SetTextSpace( int space = 0 );		// Percent of average width (default=0)
	void SetTextShare( int percent = 0 );	// Percent of average width (default=0)

	void SetColor( DWORD c );				// 0xAARRGGBB
	void SetColor( float _red, float _green, float _blue, float _alpha = 1.0f );
	void SetRotation( float deg );
	
	void Reset();
	float Width();
	int GetLineSpace();

	float Length( const char *format, ... );
	float Length2( const char *str, int le = -1 );
	float Length( char c );

	void SetTextHAlign( int x ); // 0-left, 1=center, 2=right
	void SetTextVAlign( int x ); // 0-top, 1=base, 2=bottom
	float Print( D3DXCOLOR *color, int x, int y, const char *str, int len = -1, D3DXMATRIX *pVP = NULL, D3DXCOLOR *bbox = NULL );

	void GetD3D11TextMetrics( TEXTMETRICA *t ) {	memcpy( t, &tm, sizeof(TEXTMETRICA) );	}
private:
	char *Buffer;

	float red, green, blue, alpha;

	int tex_w, tex_h, sharing, spacing, linespacing;
	float
		max,			// If several strings are printed. This is the wide of the widest one
		rotation;
	int last, CharSet, HAlign, VAlign;

	ID3D11Texture2D *Tex;
	IDXGISurface1 *Surf;
	ID3D11ShaderResourceView *SRV;

	D3D11FontData *Data;
	_ABC *Abc;
	TEXTMETRICA tm;

	static ID3D11InputLayout *IL_TextVertex;
	static ID3D11Buffer
		*VB,
		*IB,
		*cb_COLOR;
	static ID3D11VertexShader *VS_Fill_Font;
	static ID3D11PixelShader *PS_Fill, *PS_Font;
};

//====================================================================
//====================================================================
//2D label
class Labels {
public:
	Labels();
	~Labels();
};

#endif