void Graphics::SetHighQuality(bool t) {
    Gdiplus::Graphics* g = reinterpret_cast<Gdiplus::Graphics*>(_private);
    if(t) {
        g->SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
        g->SetCompositingQuality(Gdiplus::CompositingQualityHighQuality);
    }
    else {
        g->SetSmoothingMode(Gdiplus::SmoothingModeHighSpeed);
        g->SetCompositingQuality(Gdiplus::CompositingQualityHighSpeed);
    }
}
bool PngOutlineText::DrawString(
	Gdiplus::Graphics* pGraphics, 
	Gdiplus::FontFamily* pFontFamily,
	Gdiplus::FontStyle fontStyle,
	int nfontSize,
	const wchar_t*pszText, 
	Gdiplus::Rect rtDraw, 
	Gdiplus::StringFormat* pStrFormat)
{
	if(!pGraphics) return false;

	if(m_bEnableShadow&&m_pBkgdBitmap&&m_pFontBodyShadow&&m_pShadowStrategy&&m_pShadowStrategyMask)
	{
		Gdiplus::Graphics* pGraphicsMask=NULL;
		Gdiplus::Bitmap* pBmpMask=NULL;
		Gdiplus::Graphics* pGraphicsDrawn=NULL;
		Gdiplus::Bitmap* pBmpDrawn=NULL;

		bool b = RenderTransShadowA( pGraphics, &pGraphicsMask, &pBmpMask, &pGraphicsDrawn, &pBmpDrawn);

		if(!b) return false;

		b = RenderFontShadow(
			pGraphicsDrawn,
			pGraphicsMask,
			pBmpDrawn,
			pBmpMask,
			pFontFamily,
			fontStyle,
			nfontSize,
			pszText, 
			Gdiplus::Rect(rtDraw.X+m_ptShadowOffset.X, rtDraw.Y+m_ptShadowOffset.Y,rtDraw.Width,rtDraw.Height),
			pStrFormat);

		if(!b) 
		{
			delete pGraphicsMask;
			delete pGraphicsDrawn;
			delete pBmpDrawn;
			return false;
		}

		b = RenderTransShadowB( pGraphics, pGraphicsMask, pBmpMask, pGraphicsDrawn, pBmpDrawn);

		delete pGraphicsMask;
		delete pGraphicsDrawn;
		delete pBmpDrawn;

		if(!b) return false;
	}

	if(m_pTextStrategy&&m_pTextStrategyMask)
	{
		Gdiplus::Graphics* pGraphicsPng = new Gdiplus::Graphics((Gdiplus::Image*)(m_pPngBitmap));

		pGraphicsPng->SetCompositingMode(pGraphics->GetCompositingMode());
		pGraphicsPng->SetCompositingQuality(pGraphics->GetCompositingQuality());
		pGraphicsPng->SetInterpolationMode(pGraphics->GetInterpolationMode());
		pGraphicsPng->SetSmoothingMode(pGraphics->GetSmoothingMode());
		pGraphicsPng->SetTextRenderingHint(pGraphics->GetTextRenderingHint());
		pGraphicsPng->SetPageUnit(pGraphics->GetPageUnit());
		pGraphicsPng->SetPageScale(pGraphics->GetPageScale());

		bool b = m_pTextStrategy->DrawString(
			pGraphicsPng, 
			pFontFamily,
			fontStyle,
			nfontSize,
			pszText, 
			rtDraw, 
			pStrFormat);

		delete pGraphicsPng;

		if(!b)
			return false;
	}

	//pGraphics->DrawImage(m_pPngBitmap,0,0,m_pPngBitmap->GetWidth(),m_pPngBitmap->GetHeight());

	return true;
}
bool PngOutlineText::RenderFontShadow(	
	Gdiplus::Graphics* pGraphicsDrawn, 
	Gdiplus::Graphics* pGraphicsMask,
	Gdiplus::Bitmap* pBitmapDrawn,
	Gdiplus::Bitmap* pBitmapMask,
	Gdiplus::FontFamily* pFontFamily,
	Gdiplus::FontStyle fontStyle,
	int nfontSize,
	const wchar_t*pszText, 
	Gdiplus::Rect rtDraw, 
	Gdiplus::StringFormat* pStrFormat)
{
	if(!pGraphicsDrawn||!pGraphicsMask||!pBitmapDrawn||!pBitmapMask) return false;

	Gdiplus::Bitmap* pBitmapShadowMask = 
		m_pPngBitmap->Clone(0, 0, m_pPngBitmap->GetWidth(), m_pPngBitmap->GetHeight(), PixelFormat32bppARGB);

	Gdiplus::Graphics* pGraphicsShadowMask = new Gdiplus::Graphics((Gdiplus::Image*)(pBitmapShadowMask));
	Gdiplus::SolidBrush brushBlack(Gdiplus::Color(0,0,0));
	pGraphicsShadowMask->FillRectangle(&brushBlack, 0, 0, m_pPngBitmap->GetWidth(), m_pPngBitmap->GetHeight() );

	pGraphicsShadowMask->SetCompositingMode(pGraphicsDrawn->GetCompositingMode());
	pGraphicsShadowMask->SetCompositingQuality(pGraphicsDrawn->GetCompositingQuality());
	pGraphicsShadowMask->SetInterpolationMode(pGraphicsDrawn->GetInterpolationMode());
	pGraphicsShadowMask->SetSmoothingMode(pGraphicsDrawn->GetSmoothingMode());
	pGraphicsShadowMask->SetTextRenderingHint(pGraphicsDrawn->GetTextRenderingHint());
	pGraphicsShadowMask->SetPageUnit(pGraphicsDrawn->GetPageUnit());
	pGraphicsShadowMask->SetPageScale(pGraphicsDrawn->GetPageScale());

	bool b = false;

	b = m_pFontBodyShadowMask->DrawString(
		pGraphicsMask, 
		pFontFamily,
		fontStyle,
		nfontSize,
		pszText, 
		rtDraw, 
		pStrFormat);

	if(!b) return false;

	b = m_pShadowStrategyMask->DrawString(		
		pGraphicsShadowMask, 
		pFontFamily,
		fontStyle,
		nfontSize,
		pszText, 
		rtDraw, 
		pStrFormat);

	if(!b) return false;

	b = m_pFontBodyShadow->DrawString(
		pGraphicsDrawn, 
		pFontFamily,
		fontStyle,
		nfontSize,
		pszText, 
		rtDraw, 
		pStrFormat);

	if(!b) return false;

	b = m_pShadowStrategy->DrawString(		
		pGraphicsDrawn, 
		pFontFamily,
		fontStyle,
		nfontSize,
		pszText, 
		rtDraw, 
		pStrFormat);

	if(!b) return false;

	UINT* pixelsDest = NULL;
	UINT* pixelsMask = NULL;
	UINT* pixelsShadowMask = NULL;

	using namespace Gdiplus;

	BitmapData bitmapDataDest;
	BitmapData bitmapDataMask;
	BitmapData bitmapDataShadowMask;
	Rect rect(0, 0, m_pBkgdBitmap->GetWidth(), m_pBkgdBitmap->GetHeight() );

	pBitmapDrawn->LockBits(
		&rect,
		ImageLockModeWrite,
		PixelFormat32bppARGB,
		&bitmapDataDest );

	pBitmapMask->LockBits(
		&rect,
		ImageLockModeWrite,
		PixelFormat32bppARGB,
		&bitmapDataMask );

	pBitmapShadowMask->LockBits(
		&rect,
		ImageLockModeWrite,
		PixelFormat32bppARGB,
		&bitmapDataShadowMask );

	pixelsDest = (UINT*)bitmapDataDest.Scan0;
	pixelsMask = (UINT*)bitmapDataMask.Scan0;
	pixelsShadowMask = (UINT*)bitmapDataShadowMask.Scan0;

	if( !pixelsDest || !pixelsMask || !pixelsShadowMask )
		return false;

	UINT col = 0;
	int stride = bitmapDataDest.Stride >> 2;
	for(UINT row = 0; row < bitmapDataDest.Height; ++row)
	{
		for(col = 0; col < bitmapDataDest.Width; ++col)
		{
			using namespace Gdiplus;
			UINT index = row * stride + col;
			BYTE nAlpha = pixelsMask[index] & 0xff;
			BYTE nAlphaShadow = pixelsShadowMask[index] & 0xff;
			if(nAlpha>0&&nAlpha>nAlphaShadow)
			{
				pixelsDest[index] = nAlpha << 24 | m_clrShadow.GetR()<<16 | m_clrShadow.GetG()<<8 | m_clrShadow.GetB();
			}
			else if(nAlphaShadow>0)
			{
				pixelsDest[index] = nAlphaShadow << 24 | m_clrShadow.GetR()<<16 | m_clrShadow.GetG()<<8 | m_clrShadow.GetB();
				pixelsMask[index] = pixelsShadowMask[index];
			}
		}
	}

	pBitmapShadowMask->UnlockBits(&bitmapDataShadowMask);
	pBitmapMask->UnlockBits(&bitmapDataMask);
	pBitmapDrawn->UnlockBits(&bitmapDataDest);

	if(pGraphicsShadowMask)
	{
		delete pGraphicsShadowMask;
		pGraphicsShadowMask = NULL;
	}

	if(pBitmapShadowMask)
	{
		delete pBitmapShadowMask;
		pBitmapShadowMask = NULL;
	}

	return true;
}
Graphics::Graphics(HDC dc) {
    Gdiplus::Graphics* g = new Gdiplus::Graphics(dc);
    g->SetSmoothingMode(Gdiplus::SmoothingModeHighQuality);
    g->SetCompositingQuality(Gdiplus::CompositingQualityHighQuality);
    _private = reinterpret_cast<void*>(g);
}