text: #include "Gwen/BaseRender.h"
  #include "Gwen/Gwen.h"
  #include "Gwen/Utility.h"
  #include "Gwen/Font.h"
  #include "Gwen/Texture.h"
  
  #include <windows.h>
  #include <gdiplus.h>
  #include <math.h>
  using namespace Gdiplus;
  
  //
  // Without double buffering it's flickery
  // With double buffering it gets slow at high resolutions
  //
  #define USE_GDIPLUS_DOUBLE_BUFFERING
  
  class GWENRENDER_Windows : public Gwen::Gwen::Renderer::Base
  {
  	public:
  
  		GWENRENDER_Windows( HWND pHWND )
  		{
  			m_HWND = pHWND;
  
  			m_hDC = NULL;
  			m_iWidth = 0;
  			m_iHeight = 0;
  			#ifdef USE_GDIPLUS_DOUBLE_BUFFERING
  			m_Bitmap = NULL;
  			m_CachedBitmap = NULL;
  			#endif
  			graphics = NULL;
  
  			// Initialize GDI+.
  			GdiplusStartupInput gdiplusStartupInput;
  			GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
  		}
  
  		~GWENRENDER_Windows()
  		{
  			#ifdef USE_GDIPLUS_DOUBLE_BUFFERING
  			DestroyOffscreenBitmap();
  			#endif
  			GdiplusShutdown(m_gdiplusToken);
  		}
  
  		void CreateOffscreenBitmap()
  		{
  			RECT rect;
  			GetClientRect( m_HWND, &rect );
  
  			int width = rect.right - rect.left;
  			int height = rect.bottom - rect.top;
  
  			if ( m_iWidth != width ) DestroyOffscreenBitmap();
  			if ( m_iHeight != height ) DestroyOffscreenBitmap();
  
  			#ifdef USE_GDIPLUS_DOUBLE_BUFFERING
  			if ( m_Bitmap ) return;
  
  			m_iWidth = width;
  			m_iHeight = height;
  
  			Graphics gfx( m_hDC );
  			m_Bitmap = new Bitmap( m_iWidth, m_iHeight, &gfx );
  			graphics = Graphics::FromImage( m_Bitmap );
  			#endif
  		}
  
  		void DestroyOffscreenBitmap()
  		{
  			#ifdef USE_GDIPLUS_DOUBLE_BUFFERING
  			if ( m_Bitmap ){ delete m_Bitmap; m_Bitmap = NULL; }
  			graphics = NULL;
  			#endif
  		}
  
  		virtual void Begin()
  		{
  			m_hDC = BeginPaint( m_HWND, &m_PaintStruct );
  
  			// Create the backbuffer if it doesn't exist 
  			// (or recreate if the size has changed)
  			CreateOffscreenBitmap();
  
  			#ifndef USE_GDIPLUS_DOUBLE_BUFFERING
  			graphics = Graphics::FromHDC( m_hDC );
  			#endif
  		}
  
  		virtual void End()
  		{
  
  			#ifdef USE_GDIPLUS_DOUBLE_BUFFERING
  			Graphics gfx( m_hDC );
  			gfx.DrawImage( m_Bitmap, 0, 0 );
  			#endif
  
  			#ifndef USE_GDIPLUS_DOUBLE_BUFFERING
  			if ( graphics )
  			{
  				delete graphics;
  				graphics = NULL;
  			}
  			#endif
  
  			m_hDC = NULL;
  			EndPaint( m_HWND, &m_PaintStruct );
  		}
  
  		virtual void DrawLine( int x, int y, int a, int b )
  		{
  			Translate( x, y );
  			Translate( a, b );
  
  			Pen      pen( GetGDIColor(), 1.0f );
  			graphics->DrawLine( &pen, x, y, a, b );			
  		}
  
  		virtual void DrawFilledRect( Gwen::Rect rect )
  		{
  			Translate( rect );
  
  			SolidBrush solidBrush( GetGDIColor() );
  			graphics->FillRectangle( &solidBrush, rect.x, rect.y, rect.w, rect.h );
  		}
  
  		virtual void DrawRectRotated( const Gwen::Rect &rect, float fAngle, const Gwen::Point& pntHandle )
  		{
  
  		}
  		virtual void PushMaterial( const char* material )
  		{
  
  		}
  		virtual void PushMaterial(const void* material)
  		{
  		//	IGet::Render()->PushMaterial((IMaterial*)material);
  		}
  
  		virtual void PopMaterial(void)
  		{
  		//	IGet::Render()->PopMaterial();
  		}
  		//Why is this here
  		virtual const char* GetMaterial(void)
  		{
  			return "";
  		}
  
  		virtual void* ImagePointer(const char* image)
  		{
  		//	return IGet::Render()->LoadMaterial( image );
  			return NULL;
  		}
  
  		virtual void SetDrawColor(Gwen::Color color)
  		{
  			m_Col = Color( color.a, color.r, color.g, color.b );
  		}
  
  		Color GetGDIColor()
  		{
  			return m_Col;
  		}
  
  		virtual void LoadFont( Gwen::Font* font )
  		{
  			Gwen::Debug::Msg( "LOAD FONT %s\n", font->facename.c_str() );
  
  			FontStyle fs = FontStyleRegular;
  
  			font->realsize = font->size * Scale();
  			Font* pFont = new Font( Gwen::Utility::StringToUnicode( font->facename ).c_str(), font->realsize, fs, UnitPixel, NULL );
  			font->data = pFont;
  		}
  
  		virtual void FreeFont( Gwen::Font* pFont )
  		{
  			Gwen::Debug::Msg( "FREE FONT %s\n", pFont->facename.c_str() );
  			if ( !pFont->data ) return;
  
  			Font* font = ((Font*)pFont->data);
  			delete font;
  			pFont->data = NULL;
  		}
  
  		virtual void RenderText( Gwen::Font* pFont, Gwen::Rect rect, const Gwen::UnicodeString& text )
  		{
  			/*
  			SetDrawColor( Gwen::Color( 255, 0, 0, 100 ) );
  			DrawFilledRect( rect );
  			SetDrawColor( Gwen::Color( 0, 0, 0, 255 ) );
  			*/
  
  
  			Translate( rect );
  
  			if ( !pFont->data || fabs( pFont->realsize - pFont->size * Scale() ) > 2 )
  			{
  				FreeFont( pFont );
  				LoadFont( pFont );
  			}
  
  			StringFormat strFormat( StringFormat::GenericDefault() );
  
  			SolidBrush solidBrush( GetGDIColor() );
  			RectF r( rect.x, rect.y, rect.w, rect.h );
  			Font* pGDIFont = (Font*)pFont->data;
  			graphics->DrawString( text.c_str(), text.length()+1, pGDIFont, r, &strFormat, &solidBrush );
  		}
  
  		virtual Gwen::Point MeasureText( Gwen::Font* pFont, const Gwen::UnicodeString& text )
  		{
  			Gwen::Point p( 32, 32 );
  
  			if ( !pFont->data || fabs( pFont->realsize - pFont->size * Scale() ) > 2 )
  			{
  				FreeFont( pFont );
  				LoadFont( pFont );
  			}
  
  			StringFormat strFormat( StringFormat::GenericDefault() );
  			strFormat.SetFormatFlags( StringFormatFlagsMeasureTrailingSpaces | strFormat.GetFormatFlags() );
  
  			SizeF size;
  
  			Graphics g( m_HWND );
  			Font* pGDIFont = (Font*)pFont->data;
  			Status s = g.MeasureString( text.c_str(), -1, pGDIFont, &strFormat, &size );
  			return Gwen::Point( size.Width+1, size.Height+1 );
  		}
  
  		void StartClip()
  		{
  			const Gwen::Rect& rect = ClipRegion();
  
  			graphics->SetClip( Rect( rect.x * Scale(), rect.y* Scale(), rect.w* Scale(), rect.h* Scale() ), CombineMode::CombineModeReplace );
  
  			//Pen      pen( Color( 100, 255, 0, 255 ) );
  			//graphics->DrawRectangle( &pen, Rect( rect.x*Scale(), rect.y*Scale(), rect.w*Scale(), rect.h*Scale() ) );
  		}
  
  		void EndClip()
  		{
  			graphics->ResetClip();
  		}
  
  		bool ProcessTexture( Gwen::Texture* pTexture )
  		{
  
  
  			return true;
  		}
  
  		void DrawMissingImage( Gwen::Rect pTargetRect )
  		{
  			SetDrawColor( Gwen::Colors::Red );
  			DrawFilledRect( pTargetRect );
  		}
  
  		void DrawTexturedRect( Gwen::Texture* pTexture, Gwen::Rect pTargetRect, float u1=0.0f, float v1=0.0f, float u2=1.0f, float v2=1.0f )
  		{
  			Image* pImage = (Image*) pTexture->data;
  
  			// Missing image, not loaded properly?
  			if ( pImage->GetType() == ImageTypeUnknown ) return DrawMissingImage( pTargetRect );
  
  			Translate( pTargetRect );
  
  			RectF TargetRect( pTargetRect.x, pTargetRect.y, pTargetRect.w, pTargetRect.h );
  
  			if ( u1 == 0.0f && v1 == 0.0f && u2 == 1.0f && v2 == 1.0f )
  			{
  				graphics->DrawImage( pImage, TargetRect );
  				return;
  			}
  
  			float fW = pImage->GetWidth();
  			float fH = pImage->GetHeight();
  
  			u1 *= fW;
  			v1 *= fH;
  
  			u2 *= fW;
  			u2 -= u1;
  
  			v2 *= fH;
  			v2 -= v1;
  
  			graphics->DrawImage( pImage, TargetRect, u1, v1, u2, v2, UnitPixel );
  			
  		}
  
  		void LoadTexture( Gwen::Texture* pTexture )
  		{
  			Gwen::Debug::Msg( "LOAD TEXTURE %s\n", pTexture->name.c_str() );
  			Image* pImage = new Image( Gwen::Utility::StringToUnicode( pTexture->name ).c_str() );
  			pTexture->data = pImage;
  
  			pTexture->width = pImage->GetWidth();
  			pTexture->height = pImage->GetHeight();
  		}
  
  		void FreeTexture( Gwen::Texture* pTexture )
  		{
  			Gwen::Debug::Msg( "RELEASED TEXTURE %s\n", pTexture->name.c_str() );
  			Image* pImage = (Image*) pTexture->data;
  			if ( !pImage ) return;
  
  			delete pImage;
  		}
  
  	private:
  
  		Color			m_Col;
  
  		HWND			m_HWND;
  		HDC				m_hDC;
  		PAINTSTRUCT		m_PaintStruct;
  
  		int m_iWidth;
  		int m_iHeight;
  
  		ULONG_PTR          m_gdiplusToken;
  
  		#ifdef USE_GDIPLUS_DOUBLE_BUFFERING
  		Bitmap*			m_Bitmap;
  		CachedBitmap*	m_CachedBitmap;
  		#endif
  
  		Graphics*		graphics;
  };