用于EagleEye3.0 规则集漏报和误报测试的示例项目,项目收集于github和gitee
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1248 lines
38 KiB

// render-gdi.cpp : Defines the exported functions for the DLL application.
//
#include "render-gdi.h"
#include "GradientFillHelper.h"
#include <gdialpha.h>
#include <math.h>
#include <trace.h>
#include <tchar.h>
#include <algorithm>
namespace SOUI
{
//////////////////////////////////////////////////////////////////////////
// SRenderFactory_GDI
BOOL SRenderFactory_GDI::CreateRenderTarget( IRenderTarget ** ppRenderTarget ,int nWid,int nHei)
{
*ppRenderTarget = new SRenderTarget_GDI(this, nWid, nHei);
return TRUE;
}
BOOL SRenderFactory_GDI::CreateFont( IFont ** ppFont , const LOGFONT &lf)
{
*ppFont = new SFont_GDI(this,&lf);
return TRUE;
}
BOOL SRenderFactory_GDI::CreateBitmap( IBitmap ** ppBitmap )
{
*ppBitmap = new SBitmap_GDI(this);
return TRUE;
}
BOOL SRenderFactory_GDI::CreateRegion( IRegion **ppRgn )
{
*ppRgn = new SRegion_GDI(this);
return TRUE;
}
BOOL SRenderFactory_GDI::CreatePath(IPath ** ppPath)
{
return FALSE;
}
BOOL SRenderFactory_GDI::CreatePathEffect(REFGUID guidEffect,IPathEffect ** ppPathEffect)
{
return FALSE;
}
BOOL SRenderFactory_GDI::CreatePathMeasure(IPathMeasure ** ppPathMeasure)
{
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
// SBitmap_GDI
HBITMAP SBitmap_GDI::CreateGDIBitmap( int nWid,int nHei,void ** ppBits )
{
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(bmi));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = nWid;
bmi.bmiHeader.biHeight = -nHei; // top-down image
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
HDC hdc=GetDC(NULL);
HBITMAP hBmp=CreateDIBSection(hdc,&bmi,DIB_RGB_COLORS,ppBits,0,0);
ReleaseDC(NULL,hdc);
return hBmp;
}
HRESULT SBitmap_GDI::Init( int nWid,int nHei ,const LPVOID pBits/*=NULL*/)
{
if(m_hBmp) DeleteObject(m_hBmp);
LPVOID pBmpBits=NULL;
m_hBmp = CreateGDIBitmap(nWid,nHei,&pBmpBits);
if(m_hBmp)
{
m_sz.cx=nWid,m_sz.cy=nHei;
const int stride = m_sz.cx*4;
if(pBits)
{
memcpy(pBmpBits,pBits,stride*m_sz.cy);
}else
{
memset(pBmpBits,0,stride*m_sz.cy);
}
}
return m_hBmp?S_OK:E_OUTOFMEMORY;
}
HRESULT SBitmap_GDI::Init(IImgFrame *pFrame )
{
UINT nWid,nHei;
pFrame->GetSize(&nWid,&nHei);
if(m_hBmp) DeleteObject(m_hBmp);
void * pBits=NULL;
m_hBmp = CreateGDIBitmap(nWid,nHei,&pBits);
if(!m_hBmp) return E_OUTOFMEMORY;
m_sz.cx=nWid,m_sz.cy=nHei;
const int stride = m_sz.cx*4;
pFrame->CopyPixels(NULL, stride, stride * m_sz.cy,
reinterpret_cast<BYTE*>(pBits));
return S_OK;
}
HRESULT SBitmap_GDI::LoadFromFile( LPCTSTR pszFileName)
{
SAutoRefPtr<IImgX> imgDecoder;
GetRenderFactory()->GetImgDecoderFactory()->CreateImgX(&imgDecoder);
if(imgDecoder->LoadFromFile(S_CT2W(pszFileName))==0) return S_FALSE;
return ImgFromDecoder(imgDecoder);
}
HRESULT SBitmap_GDI::LoadFromMemory(LPBYTE pBuf,size_t szLen)
{
SAutoRefPtr<IImgX> imgDecoder;
GetRenderFactory()->GetImgDecoderFactory()->CreateImgX(&imgDecoder);
if(imgDecoder->LoadFromMemory(pBuf,szLen)==0) return S_FALSE;
return ImgFromDecoder(imgDecoder);
}
HRESULT SBitmap_GDI::ImgFromDecoder(IImgX *imgDecoder)
{
IImgFrame *pFrame=imgDecoder->GetFrame(0);
UINT nWid,nHei;
pFrame->GetSize(&nWid,&nHei);
m_sz.cx=nWid,m_sz.cy=nHei;
if(m_hBmp) DeleteObject(m_hBmp);
void * pBits=NULL;
m_hBmp = CreateGDIBitmap(m_sz.cx,m_sz.cy,&pBits);
if(!m_hBmp) return E_OUTOFMEMORY;
const int stride = m_sz.cx*4;
pFrame->CopyPixels(NULL, stride, stride * m_sz.cy,
reinterpret_cast<BYTE*>(pBits));
return S_OK;
}
UINT SBitmap_GDI::Width() const
{
return m_sz.cx;
}
UINT SBitmap_GDI::Height() const
{
return m_sz.cy;
}
SIZE SBitmap_GDI::Size() const
{
return m_sz;
}
LPVOID SBitmap_GDI::LockPixelBits()
{
BITMAP bm;
GetObject(m_hBmp,sizeof(bm),&bm);
return bm.bmBits;
}
void SBitmap_GDI::UnlockPixelBits( LPVOID pBuf)
{
}
const LPVOID SBitmap_GDI::GetPixelBits() const
{
BITMAP bm;
GetObject(m_hBmp,sizeof(bm),&bm);
return bm.bmBits;
}
//////////////////////////////////////////////////////////////////////////
// SRegion_GDI
SRegion_GDI::SRegion_GDI( IRenderFactory *pRenderFac )
:TGdiRenderObjImpl<IRegion>(pRenderFac)
{
m_hRgn = ::CreateRectRgn(0,0,0,0);
}
/*
int CombineRgn( HRGN hrgnDest, // handle to destination region
HRGN hrgnSrc1, // handle to source region
HRGN hrgnSrc2, // handle to source region
int fnCombineMode // region combining mode);
RGN_AND Creates the intersection of the two combined regions.
RGN_COPY Creates a copy of the region identified by hrgnSrc1.
RGN_DIFF Combines the parts of hrgnSrc1 that are not part of hrgnSrc2.
RGN_OR Creates the union of two combined regions.
RGN_XOR Creates the union of two combined regions except for any overlapping areas.
注意 RGN_DIFF 和 RGN_COPY对于hrgnSrc1的使用差异
*/
void SRegion_GDI::CombineRect( LPCRECT lprect,int nCombineMode )
{
HRGN hRgn=::CreateRectRgnIndirect(lprect);
_CombineRgn(hRgn,nCombineMode);
DeleteObject(hRgn);
}
void SRegion_GDI::CombinePolygon(const POINT * pts, int count, int nPolygonMode, int nCombineMode)
{
HRGN hRgn = ::CreatePolygonRgn(pts, count, nPolygonMode);
_CombineRgn(hRgn, nCombineMode);
DeleteObject(hRgn);
}
void SRegion_GDI::CombineRgn(const IRegion * pRgnSrc,int nCombineMode)
{
const SRegion_GDI *pRgnSrcGdi = (const SRegion_GDI*)pRgnSrc;
HRGN hRgn = pRgnSrcGdi->GetRegion();
_CombineRgn(hRgn,nCombineMode);
}
void SRegion_GDI::_CombineRgn(HRGN hRgn,int nCombineMode)
{
if(nCombineMode == RGN_DIFF)
{
::CombineRgn(m_hRgn,m_hRgn,hRgn,RGN_DIFF);
}else
{
::CombineRgn(m_hRgn,hRgn,m_hRgn,nCombineMode);
}
}
BOOL SRegion_GDI::PtInRegion( POINT pt ) const
{
return ::PtInRegion(m_hRgn,pt.x,pt.y);
}
BOOL SRegion_GDI::RectInRegion( LPCRECT lprect ) const
{
SASSERT(lprect);
return ::RectInRegion(m_hRgn,lprect);
}
void SRegion_GDI::GetRgnBox( LPRECT lprect ) const
{
SASSERT(lprect);
::GetRgnBox(m_hRgn,lprect);
}
BOOL SRegion_GDI::IsEmpty() const
{
RECT rcBox;
GetRgnBox(&rcBox);
return (rcBox.left == rcBox.right) || (rcBox.top== rcBox.bottom);
}
BOOL SRegion_GDI::IsEqual(const IRegion * testRgn) const
{
const SRegion_GDI *pRgnTestGdi = (const SRegion_GDI*)testRgn;
return ::EqualRgn(m_hRgn,pRgnTestGdi->m_hRgn);
}
void SRegion_GDI::Offset( POINT pt )
{
::OffsetRgn(m_hRgn,pt.x,pt.y);
}
HRGN SRegion_GDI::GetRegion() const
{
return m_hRgn;
}
void SRegion_GDI::Clear()
{
::SetRectRgn(m_hRgn,0,0,0,0);
}
void SRegion_GDI::CombineRoundRect(LPCRECT lprect, POINT ptRadius, int nCombineMode)
{
HRGN hRgn = ::CreateRoundRectRgn(lprect->left,lprect->top,lprect->right,lprect->bottom,ptRadius.x,ptRadius.y);
::CombineRgn(m_hRgn,hRgn,NULL,nCombineMode);
DeleteObject(hRgn);
}
void SRegion_GDI::CombineEllipse(LPCRECT lprect , int nCombineMode)
{
HRGN hRgn = ::CreateEllipticRgnIndirect(lprect);
::CombineRgn(m_hRgn,hRgn,NULL,nCombineMode);
DeleteObject(hRgn);
}
//////////////////////////////////////////////////////////////////////////
// DCBuffer
//////////////////////////////////////////////////////////////////////////
class DCBuffer
{
public:
DCBuffer(HDC hdc,LPCRECT pRect,BYTE byAlpha,BOOL bCopyBits=TRUE)
:m_hdc(hdc)
,m_byAlpha(byAlpha)
,m_pRc(pRect)
,m_bCopyBits(bCopyBits)
{
m_nWid = pRect->right-pRect->left;
m_nHei = pRect->bottom-pRect->top;
m_hBmp = SBitmap_GDI::CreateGDIBitmap(m_nWid,m_nHei,(void**)&m_pBits);
m_hMemDC = ::CreateCompatibleDC(hdc);
::SetBkMode(m_hMemDC,TRANSPARENT);
::SelectObject(m_hMemDC,m_hBmp);
::SetViewportOrgEx(m_hMemDC,-pRect->left,-pRect->top,NULL);
//从原DC中获得画笔,画刷,字体,颜色等
m_hCurPen = ::SelectObject(hdc,GetStockObject(BLACK_PEN));
m_hCurBrush = ::SelectObject(hdc,GetStockObject(BLACK_BRUSH));
m_hCurFont = ::SelectObject(hdc,GetStockObject(DEFAULT_GUI_FONT));
COLORREF crCur = ::GetTextColor(hdc);
//将画笔,画刷,字体设置到memdc里
::SelectObject(m_hMemDC,m_hCurPen);
::SelectObject(m_hMemDC,m_hCurBrush);
::SelectObject(m_hMemDC,m_hCurFont);
::SetTextColor(m_hMemDC,crCur);
if(m_bCopyBits) ::BitBlt(m_hMemDC,pRect->left,pRect->top,m_nWid,m_nHei,m_hdc,pRect->left,pRect->top,SRCCOPY);
//将alpha全部强制修改为0xFF。
BYTE * p= m_pBits+3;
for(int i=0;i<m_nHei;i++)for(int j=0;j<m_nWid;j++,p+=4) *p=0xFF;
}
~DCBuffer()
{
//将alpha为0xFF的改为0,同时将rgb值也清0(XP系统下不清0会导致背景变成白色),为0的改为0xFF
BYTE * p= m_pBits+3;
for(int i=0;i<m_nHei;i++)for(int j=0;j<m_nWid;j++,p+=4)
{
if(*p==0) *p=0xff;
else
{
memset(p-3,0,4);
}
}
BLENDFUNCTION bf={AC_SRC_OVER,0,m_byAlpha,AC_SRC_ALPHA };
BOOL bRet=::AlphaBlend(m_hdc,m_pRc->left,m_pRc->top,m_nWid,m_nHei,m_hMemDC,m_pRc->left,m_pRc->top,m_nWid,m_nHei,bf);
(void)bRet;
::DeleteDC(m_hMemDC);
::DeleteObject(m_hBmp);
//恢复原DC的画笔,画刷,字体
::SelectObject(m_hdc,m_hCurPen);
::SelectObject(m_hdc,m_hCurBrush);
::SelectObject(m_hdc,m_hCurFont);
}
operator HDC()
{
return m_hMemDC;
}
protected:
HDC m_hdc;
HDC m_hMemDC;
HBITMAP m_hBmp;
LPBYTE m_pBits;
BYTE m_byAlpha;
LPCRECT m_pRc;
int m_nWid,m_nHei;
BOOL m_bCopyBits;
HGDIOBJ m_hCurPen;
HGDIOBJ m_hCurBrush;
HGDIOBJ m_hCurFont;
};
//////////////////////////////////////////////////////////////////////////
// SRenderTarget_GDI
//////////////////////////////////////////////////////////////////////////
SRenderTarget_GDI::SRenderTarget_GDI( IRenderFactory* pRenderFactory ,int nWid,int nHei)
:m_hdc(NULL)
,m_curColor(0xFF000000)//默认黑色
,m_uGetDCFlag(0)
{
m_pRenderFactory = pRenderFactory;
m_ptOrg.x=m_ptOrg.y=0;
HDC hdc=::GetDC(NULL);
m_hdc = CreateCompatibleDC(hdc);
::ReleaseDC(NULL,hdc);
::SetBkMode(m_hdc,TRANSPARENT);
::SetGraphicsMode(m_hdc,GM_ADVANCED);
CreatePen(PS_SOLID,SColor(0,0,0).toCOLORREF(),1,&m_defPen);
SelectObject(m_defPen);
CreateSolidColorBrush(SColor(0,0,0).toCOLORREF(),&m_defBrush);
SelectObject(m_defBrush);
LOGFONT lf={0};
lf.lfHeight=20;
_tcscpy(lf.lfFaceName,_T("宋体"));
pRenderFactory->CreateFont(&m_defFont,lf);
SelectObject(m_defFont);
pRenderFactory->CreateBitmap(&m_defBmp);
m_defBmp->Init(nWid,nHei);
SelectObject(m_defBmp);
}
SRenderTarget_GDI::~SRenderTarget_GDI()
{
DeleteDC(m_hdc);
}
HRESULT SRenderTarget_GDI::CreateCompatibleRenderTarget( SIZE szTarget,IRenderTarget **ppRenderTarget )
{
SRenderTarget_GDI *pRT = new SRenderTarget_GDI(m_pRenderFactory,szTarget.cx,szTarget.cy);
*ppRenderTarget = pRT;
return S_OK;
}
HRESULT SRenderTarget_GDI::CreatePen( int iStyle,COLORREF cr,int cWidth,IPen ** ppPen )
{
*ppPen = new SPen_GDI(m_pRenderFactory,iStyle,cr,cWidth);
return S_OK;
}
HRESULT SRenderTarget_GDI::CreateSolidColorBrush( COLORREF cr,IBrush ** ppBrush )
{
*ppBrush = SBrush_GDI::CreateSolidBrush(m_pRenderFactory,cr);
return S_OK;
}
HRESULT SRenderTarget_GDI::CreateBitmapBrush( IBitmap *pBmp,IBrush ** ppBrush )
{
SBitmap_GDI *pBmpSkia = (SBitmap_GDI*)pBmp;
*ppBrush = SBrush_GDI::CreateBitmapBrush(m_pRenderFactory,pBmpSkia->GetBitmap());
return S_OK;
}
HRESULT SRenderTarget_GDI::Resize( SIZE sz )
{
HBITMAP hBmp=CreateCompatibleBitmap(m_hdc,0,0);
::SelectObject(m_hdc,hBmp);
m_curBmp->Init(sz.cx,sz.cy);
::SelectObject(m_hdc,m_curBmp->GetBitmap());
::DeleteObject(hBmp);
return S_OK;
}
HRESULT SRenderTarget_GDI::PushClipRect( LPCRECT pRect ,UINT mode/*=RGN_AND*/)
{
RECT rc=*pRect;
::OffsetRect(&rc,m_ptOrg.x,m_ptOrg.y);
HRGN hRgn=::CreateRectRgnIndirect(&rc);
::SaveDC(m_hdc);
::ExtSelectClipRgn(m_hdc,hRgn,mode);
::DeleteObject(hRgn);
return S_OK;
}
HRESULT SRenderTarget_GDI::PopClip()
{
::RestoreDC(m_hdc,-1);
return S_OK;
}
HRESULT SRenderTarget_GDI::ExcludeClipRect( LPCRECT pRc )
{
::ExcludeClipRect(m_hdc,pRc->left,pRc->top,pRc->right,pRc->bottom);
return S_OK;
}
HRESULT SRenderTarget_GDI::IntersectClipRect( LPCRECT pRc )
{
::IntersectClipRect(m_hdc,pRc->left,pRc->top,pRc->right,pRc->bottom);
return S_OK;
}
HRESULT SRenderTarget_GDI::SaveClip( int *pnState )
{
int nState=::SaveDC(m_hdc);
if(pnState) *pnState=nState;
return S_OK;
}
HRESULT SRenderTarget_GDI::RestoreClip( int nState/*=-1*/ )
{
::RestoreDC(m_hdc,nState);
return S_OK;
}
HRESULT SRenderTarget_GDI::PushClipRegion( IRegion *pRegion ,UINT mode/*=RGN_AND*/)
{
SRegion_GDI *pRgnGDI=(SRegion_GDI*)pRegion;
HRGN hRgn=::CreateRectRgn(0,0,0,0);
::CombineRgn(hRgn,pRgnGDI->GetRegion(),NULL,RGN_COPY);
::OffsetRgn(hRgn,m_ptOrg.x,m_ptOrg.y);
::SaveDC(m_hdc);
::ExtSelectClipRgn(m_hdc,hRgn,mode);
::DeleteObject(hRgn);
return S_OK;
}
HRESULT SRenderTarget_GDI::GetClipRegion( IRegion **ppRegion )
{
SRegion_GDI *pRgn=new SRegion_GDI(m_pRenderFactory);
::GetClipRgn(m_hdc,pRgn->GetRegion());
POINT pt={-m_ptOrg.x,-m_ptOrg.y};
pRgn->Offset(pt);
*ppRegion = pRgn;
return S_OK;
}
HRESULT SRenderTarget_GDI::GetClipBox(LPRECT prc)
{
::GetClipBox(m_hdc,prc);
return S_OK;
}
HRESULT SRenderTarget_GDI::BitBlt( LPCRECT pRcDest,IRenderTarget *pRTSour,int xSrc,int ySrc,DWORD dwRop/*=SRCCOPY*/)
{
switch(dwRop)
{
case kSrcCopy:
case kDstInvert:
case kSrcInvert:
case kSrcAnd:
break;
default:
return E_INVALIDARG;
}
SRenderTarget_GDI *pRTSrc_GDI=(SRenderTarget_GDI*)pRTSour;
ALPHAINFO ai;
// if(dwRop!=SRCCOPY)
CGdiAlpha::AlphaBackup(m_hdc,pRcDest,ai);
::BitBlt(m_hdc,pRcDest->left,pRcDest->top,pRcDest->right-pRcDest->left,pRcDest->bottom-pRcDest->top,pRTSrc_GDI->m_hdc,xSrc,ySrc,dwRop);
// if(dwRop!=SRCCOPY)
CGdiAlpha::AlphaRestore(ai);
return S_OK;
}
HRESULT SRenderTarget_GDI::DrawText( LPCTSTR pszText,int cchLen,LPRECT pRc,UINT uFormat)
{
if(uFormat & DT_CALCRECT)
{
int nRet = ::DrawText(m_hdc,pszText,cchLen,pRc,uFormat);
if(!nRet)
{
pRc->right = pRc->left;
pRc->bottom = pRc->top;
}
return S_OK;
}
if(cchLen == 0) return S_OK;
{
DCBuffer dcBuf(m_hdc,pRc,m_curColor.a);
::DrawText(dcBuf,pszText,cchLen,pRc,uFormat);
}
return S_OK;
}
HRESULT SRenderTarget_GDI::MeasureText( LPCTSTR pszText,int cchLen, SIZE *psz )
{
if(cchLen<0) cchLen = _tcslen(pszText);
::GetTextExtentPoint32(m_hdc,pszText,cchLen,psz);
return S_OK;
}
HRESULT SRenderTarget_GDI::DrawRectangle(LPCRECT pRect)
{
if(!m_curPen) return E_INVALIDARG;
RECT rcBuf = *pRect;
if (m_curPen->GetWidth() == 1)
{
rcBuf.right--;
rcBuf.bottom--;
}
else
{
::InflateRect(&rcBuf, -m_curPen->GetWidth() / 2, -m_curPen->GetWidth() / 2);
}
ALPHAINFO ai;
CGdiAlpha::AlphaBackup(m_hdc, pRect,ai);
HGDIOBJ oldBr=::SelectObject(m_hdc,GetStockObject(NULL_BRUSH));
::Rectangle(m_hdc, rcBuf.left, rcBuf.top, rcBuf.right, rcBuf.bottom);
CGdiAlpha::AlphaRestore(ai);
::SelectObject(m_hdc,oldBr);
return S_OK;
}
HRESULT SRenderTarget_GDI::FillRectangle(LPCRECT pRect)
{
BYTE byAlpha=0xFF;
if(!m_curBrush->IsBitmap()) byAlpha = GetAValue(m_curBrush->GetColor());
DCBuffer dcBuf(m_hdc,pRect,byAlpha,FALSE);
HGDIOBJ oldPen=::SelectObject(dcBuf,GetStockObject(NULL_PEN));
::Rectangle(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom);
::SelectObject(dcBuf,oldPen);
return S_OK;
}
HRESULT SRenderTarget_GDI::DrawRoundRect( LPCRECT pRect,POINT pt )
{
DCBuffer dcBuf(m_hdc,pRect,GetAValue(m_curPen->GetColor()));
HGDIOBJ oldBr=::SelectObject(dcBuf,GetStockObject(NULL_BRUSH));
::RoundRect(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom,pt.x*2,pt.y*2);
::SelectObject(dcBuf,oldBr);
return S_OK;
}
HRESULT SRenderTarget_GDI::FillRoundRect( LPCRECT pRect,POINT pt )
{
BYTE byAlpha=0xFF;
if(!m_curBrush->IsBitmap()) byAlpha = GetAValue(m_curBrush->GetColor());
DCBuffer dcBuf(m_hdc,pRect,byAlpha);
HGDIOBJ oldPen=::SelectObject(dcBuf,GetStockObject(NULL_PEN));
::RoundRect(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom,pt.x,pt.y);
::SelectObject(dcBuf,oldPen);
return S_OK;
}
HRESULT SRenderTarget_GDI::FillSolidRoundRect(LPCRECT pRect,POINT pt,COLORREF cr)
{
DCBuffer dcBuf(m_hdc,pRect,GetAValue(cr),FALSE);
HBRUSH br=::CreateSolidBrush(cr&0x00ffffff);
HGDIOBJ oldObj=::SelectObject(dcBuf,br);
HGDIOBJ oldPen = ::SelectObject(dcBuf, GetStockObject(NULL_PEN));
::RoundRect(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom,pt.x*2,pt.y*2);
::SelectObject(dcBuf, oldPen);
::SelectObject(dcBuf,oldObj);
::DeleteObject(br);
return S_OK;
}
HRESULT SRenderTarget_GDI::DrawLines(LPPOINT pPt,size_t nCount)
{
RECT rc={100000,100000,0,0};
for(size_t i=0;i<nCount;i++)
{
if(pPt[i].x<rc.left) rc.left=pPt[i].x;
if(pPt[i].x>rc.right) rc.right=pPt[i].x;
if(pPt[i].y<rc.top) rc.top=pPt[i].y;
if(pPt[i].y>rc.bottom) rc.bottom=pPt[i].y;
}
rc.left -= 1;
rc.top -=1;
int nPenWidth = 1;
if(m_curPen) nPenWidth = m_curPen->GetWidth();
rc.bottom+=nPenWidth;
rc.right+=nPenWidth;
DCBuffer dcBuf(m_hdc,&rc,GetAValue(m_curPen->GetColor()));
::Polyline(dcBuf,pPt,(int)nCount);
return S_OK;
}
HRESULT SRenderTarget_GDI::TextOut( int x, int y, LPCTSTR lpszString, int nCount)
{
if(nCount<0) nCount = _tcslen(lpszString);
SIZE sz;
MeasureText(lpszString,nCount,&sz);
RECT rc={x,y,x+sz.cx,y+sz.cy};
return DrawText(lpszString,nCount,&rc,DT_LEFT|DT_SINGLELINE);
}
HRESULT SRenderTarget_GDI::DrawIconEx( int xLeft, int yTop, HICON hIcon, int cxWidth,int cyWidth,UINT diFlags )
{
ICONINFO ii={0};
::GetIconInfo(hIcon,&ii);
SASSERT(ii.hbmColor);
BITMAP bm;
::GetObject(ii.hbmColor,sizeof(bm),&bm);
ALPHAINFO ai;
RECT rc={xLeft,yTop,xLeft+cxWidth,yTop+cyWidth};
if(bm.bmBitsPixel!=32)
{
CGdiAlpha::AlphaBackup(m_hdc,&rc,ai);
}
BOOL bRet=::DrawIconEx(m_hdc,xLeft,yTop,hIcon,cxWidth,cyWidth,0,NULL,diFlags);
if(bm.bmBitsPixel!=32)
{
CGdiAlpha::AlphaRestore(ai);
}
if(ii.hbmColor) DeleteObject(ii.hbmColor);
if(ii.hbmMask) DeleteObject(ii.hbmMask);
return bRet?S_OK:S_FALSE;
}
HRESULT SRenderTarget_GDI::DrawBitmap(LPCRECT pRcDest,IBitmap *pBitmap,int xSrc,int ySrc,BYTE byAlpha/*=0xFF*/ )
{
SBitmap_GDI *pBmp = (SBitmap_GDI*)pBitmap;
HBITMAP bmp=pBmp->GetBitmap();
HDC hmemdc=CreateCompatibleDC(m_hdc);
::SelectObject(hmemdc,bmp);
SIZE szBmp = pBmp->Size();
BLENDFUNCTION bf={ AC_SRC_OVER,0,byAlpha,AC_SRC_ALPHA};
int nWid= (std::min)(pRcDest->right-pRcDest->left,szBmp.cx);
int nHei= (std::min)(pRcDest->bottom-pRcDest->top,szBmp.cy);
BOOL bOK=::AlphaBlend(m_hdc,pRcDest->left,pRcDest->top,nWid,nHei,
hmemdc,xSrc,ySrc,nWid,nHei,bf);
DeleteDC(hmemdc);
return bOK?S_OK:E_FAIL;
}
HRESULT SRenderTarget_GDI::AlphaBlend( LPCRECT pRcDest,IRenderTarget *pRTSrc,LPCRECT pRcSrc,BYTE byAlpha )
{
BLENDFUNCTION bf={ AC_SRC_OVER,0,byAlpha,AC_SRC_ALPHA};
SRenderTarget_GDI *pRTGdiSrc=(SRenderTarget_GDI*)pRTSrc;
BOOL bOK=::AlphaBlend(m_hdc,pRcDest->left,pRcDest->top,pRcDest->right-pRcDest->left,pRcDest->bottom-pRcDest->top,
pRTGdiSrc->m_hdc,pRcSrc->left,pRcSrc->top,pRcSrc->right-pRcSrc->left,pRcSrc->bottom-pRcSrc->top,
bf);
return bOK?S_OK:E_FAIL;
}
HRESULT SRenderTarget_GDI::DrawBitmapEx( LPCRECT pRcDest,IBitmap *pBitmap,LPCRECT pRcSrc,UINT expendMode, BYTE byAlpha/*=0xFF*/ )
{
UINT expandModeLow = LOWORD(expendMode);
if(expandModeLow == EM_NULL)
return DrawBitmap(pRcDest,pBitmap,pRcSrc->left,pRcSrc->top,byAlpha);
SBitmap_GDI *pBmp = (SBitmap_GDI*)pBitmap;
HBITMAP bmp=pBmp->GetBitmap();
HDC hmemdc=CreateCompatibleDC(m_hdc);
::SelectObject(hmemdc,bmp);
BLENDFUNCTION bf={ AC_SRC_OVER,0,byAlpha,AC_SRC_ALPHA};
if(expandModeLow == EM_STRETCH)
{
::AlphaBlend(m_hdc,pRcDest->left,pRcDest->top,pRcDest->right-pRcDest->left,pRcDest->bottom-pRcDest->top,
hmemdc,pRcSrc->left,pRcSrc->top,pRcSrc->right-pRcSrc->left,pRcSrc->bottom-pRcSrc->top,bf);
}else
{
::SaveDC(m_hdc);
::IntersectClipRect(m_hdc,pRcDest->left,pRcDest->top,pRcDest->right,pRcDest->bottom);
int nWid=pRcSrc->right-pRcSrc->left;
int nHei=pRcSrc->bottom-pRcSrc->top;
for(int y=pRcDest->top ;y<pRcDest->bottom;y+=nHei)
{
for(int x=pRcDest->left; x<pRcDest->right; x+=nWid)
{
::AlphaBlend(m_hdc,x,y,nWid,nHei,
hmemdc,pRcSrc->left,pRcSrc->top,nWid,nHei,
bf);
}
}
::RestoreDC(m_hdc,-1);
}
DeleteDC(hmemdc);
return S_OK;
}
HRESULT SRenderTarget_GDI::DrawBitmap9Patch( LPCRECT pRcDest,IBitmap *pBitmap,LPCRECT pRcSrc,LPCRECT pRcSourMargin,UINT expendMode,BYTE byAlpha/*=0xFF*/ )
{
int xDest[4] = {pRcDest->left,pRcDest->left+pRcSourMargin->left,pRcDest->right-pRcSourMargin->right,pRcDest->right};
int xSrc[4] = {pRcSrc->left,pRcSrc->left+pRcSourMargin->left,pRcSrc->right-pRcSourMargin->right,pRcSrc->right};
int yDest[4] = {pRcDest->top,pRcDest->top+pRcSourMargin->top,pRcDest->bottom-pRcSourMargin->bottom,pRcDest->bottom};
int ySrc[4] = {pRcSrc->top,pRcSrc->top+pRcSourMargin->top,pRcSrc->bottom-pRcSourMargin->bottom,pRcSrc->bottom};
//首先保证九宫分割正常
if(!(xSrc[0] <= xSrc[1] && xSrc[1] <= xSrc[2] && xSrc[2] <= xSrc[3])) return S_FALSE;
if(!(ySrc[0] <= ySrc[1] && ySrc[1] <= ySrc[2] && ySrc[2] <= ySrc[3])) return S_FALSE;
//调整目标位置
int nDestWid=pRcDest->right-pRcDest->left;
int nDestHei=pRcDest->bottom-pRcDest->top;
if((pRcSourMargin->left + pRcSourMargin->right) > nDestWid)
{//边缘宽度大于目标宽度的处理
if(pRcSourMargin->left >= nDestWid)
{//只绘制左边部分
xSrc[1] = xSrc[2] = xSrc[3] = xSrc[0]+nDestWid;
xDest[1] = xDest[2] = xDest[3] = xDest[0]+nDestWid;
}else if(pRcSourMargin->right >= nDestWid)
{//只绘制右边部分
xSrc[0] = xSrc[1] = xSrc[2] = xSrc[3]-nDestWid;
xDest[0] = xDest[1] = xDest[2] = xDest[3]-nDestWid;
}else
{//先绘制左边部分,剩余的用右边填充
int nRemain=xDest[3]-xDest[1];
xSrc[2] = xSrc[3]-nRemain;
xDest[2] = xDest[3]-nRemain;
}
}
if(pRcSourMargin->top + pRcSourMargin->bottom > nDestHei)
{
if(pRcSourMargin->top >= nDestHei)
{//只绘制上边部分
ySrc[1] = ySrc[2] = ySrc[3] = ySrc[0]+nDestHei;
yDest[1] = yDest[2] = yDest[3] = yDest[0]+nDestHei;
}else if(pRcSourMargin->bottom >= nDestHei)
{//只绘制下边部分
ySrc[0] = ySrc[1] = ySrc[2] = ySrc[3]-nDestHei;
yDest[0] = yDest[1] = yDest[2] = yDest[3]-nDestHei;
}else
{//先绘制左边部分,剩余的用右边填充
int nRemain=yDest[3]-yDest[1];
ySrc[2] = ySrc[3]-nRemain;
yDest[2] = yDest[3]-nRemain;
}
}
//定义绘制模式
UINT mode[3][3]={
{EM_NULL,expendMode,EM_NULL},
{expendMode,expendMode,expendMode},
{EM_NULL,expendMode,EM_NULL}
};
for(int y=0;y<3;y++)
{
if(ySrc[y] == ySrc[y+1]) continue;
for(int x=0;x<3;x++)
{
if(xSrc[x] == xSrc[x+1]) continue;
RECT rcSrc = {xSrc[x],ySrc[y],xSrc[x+1],ySrc[y+1]};
RECT rcDest ={xDest[x],yDest[y],xDest[x+1],yDest[y+1]};
DrawBitmapEx(&rcDest,pBitmap,&rcSrc,mode[y][x],byAlpha);
}
}
return S_OK;
}
IRenderObj * SRenderTarget_GDI::GetCurrentObject( OBJTYPE uType )
{
IRenderObj *pRet=NULL;
switch(uType)
{
case OT_BITMAP:
pRet=m_curBmp;
break;
case OT_PEN:
pRet=m_curPen;
break;
case OT_BRUSH:
pRet=m_curBrush;
break;
case OT_FONT:
pRet=m_curFont;
break;
}
return pRet;
}
HRESULT SRenderTarget_GDI::SelectDefaultObject(OBJTYPE objType, IRenderObj ** ppOldObj)
{
IRenderObj *pDefObj = NULL;
switch(objType)
{
case OT_BITMAP: pDefObj = m_defBmp;break;
case OT_PEN: pDefObj = m_defPen;break;
case OT_BRUSH: pDefObj = m_defBrush;break;
case OT_FONT: pDefObj = m_defFont;break;
default:return E_INVALIDARG;
}
if(pDefObj == GetCurrentObject(objType))
return S_FALSE;
return SelectObject(pDefObj,ppOldObj);
}
HRESULT SRenderTarget_GDI::SelectObject( IRenderObj *pObj,IRenderObj ** ppOldObj /*= NULL*/ )
{
SAutoRefPtr<IRenderObj> pRet;
switch(pObj->ObjectType())
{
case OT_BITMAP:
pRet=m_curBmp;
m_curBmp=(SBitmap_GDI*)pObj;
::SelectObject(m_hdc,m_curBmp->GetBitmap());
break;
case OT_PEN:
pRet=m_curPen;
m_curPen=(SPen_GDI*)pObj;
::SelectObject(m_hdc,m_curPen->GetPen());
break;
case OT_BRUSH:
pRet=m_curBrush;
m_curBrush=(SBrush_GDI*)pObj;
::SelectObject(m_hdc,m_curBrush->GetBrush());
break;
case OT_FONT:
pRet=m_curFont;
m_curFont=(SFont_GDI*)pObj;
::SelectObject(m_hdc,m_curFont->GetFont());
break;
}
if(pRet && ppOldObj)
{//由调用者调用Release释放该RenderObj
pRet->AddRef();
*ppOldObj = pRet;
}
return S_OK;
}
HRESULT SRenderTarget_GDI::OffsetViewportOrg( int xOff, int yOff, LPPOINT lpPoint )
{
if(lpPoint)
{
*lpPoint=m_ptOrg;
}
m_ptOrg.x+=xOff;
m_ptOrg.y+=yOff;
::SetViewportOrgEx(m_hdc,m_ptOrg.x,m_ptOrg.y,NULL);
return S_OK;
}
HRESULT SRenderTarget_GDI::GetViewportOrg( LPPOINT lpPoint )
{
if(lpPoint)
{
*lpPoint=m_ptOrg;
}
return S_OK;
}
HRESULT SRenderTarget_GDI::SetViewportOrg( POINT pt )
{
m_ptOrg = pt;
::SetViewportOrgEx(m_hdc,m_ptOrg.x,m_ptOrg.y,NULL);
return S_OK;
}
HDC SRenderTarget_GDI::GetDC( UINT uFlag )
{
m_uGetDCFlag = uFlag;
return m_hdc;
}
void SRenderTarget_GDI::ReleaseDC( HDC hdc )
{
if(hdc == m_hdc)
{
m_uGetDCFlag =0;
}
}
HRESULT SRenderTarget_GDI::GradientFill( LPCRECT pRect,BOOL bVert,COLORREF crBegin,COLORREF crEnd,BYTE byAlpha/*=0xFF*/ )
{
if(byAlpha!=0xFF)
{
DCBuffer dcBuf(m_hdc,pRect,byAlpha,FALSE);
GradientFillRect(dcBuf,pRect,crBegin,crEnd,bVert);
}else
{
GradientFillRect(m_hdc,pRect,crBegin,crEnd,bVert);
}
return S_OK;
}
HRESULT SRenderTarget_GDI::GradientFillEx( LPCRECT pRect,const POINT* pts,COLORREF *colors,float *pos,int nCount,BYTE byAlpha/*=0xFF */ )
{
(pRect);
(pts);
(colors);
(pos);
(nCount);
(byAlpha);
return E_NOTIMPL;
}
//通过一个内存位图来填充位置的alpha值
HRESULT SRenderTarget_GDI::FillSolidRect( LPCRECT pRect,COLORREF cr )
{
DCBuffer dcBuf(m_hdc,pRect,GetAValue(cr),FALSE);
HBRUSH br=::CreateSolidBrush(cr&0x00ffffff);
::FillRect(dcBuf,pRect,br);
::DeleteObject(br);
return S_OK;
}
HRESULT SRenderTarget_GDI::ClearRect( LPCRECT pRect,COLORREF cr )
{
int nWid=pRect->right-pRect->left;
int nHei=pRect->bottom-pRect->top;
if(nWid == 0 || nHei == 0)
return S_OK;
LPDWORD pBits;
HBITMAP hBmp=SBitmap_GDI::CreateGDIBitmap(nWid,nHei,(void**)&pBits);
HDC hMemDC=CreateCompatibleDC(m_hdc);
::SelectObject(hMemDC,hBmp);
SColor color(cr);
DWORD dwColor=color.toARGB();
for(int i=0;i<nHei;i++)for(int j=0;j<nWid;j++)
*pBits++ = dwColor;
::BitBlt(m_hdc,pRect->left,pRect->top,nWid,nHei,hMemDC,0,0,SRCCOPY);
::DeleteDC(hMemDC);
::DeleteObject(hBmp);
return S_OK;
}
HRESULT SRenderTarget_GDI::InvertRect(LPCRECT pRect)
{
return ::InvertRect(m_hdc,pRect)?S_OK:E_UNEXPECTED;
}
HRESULT SRenderTarget_GDI::DrawEllipse( LPCRECT pRect )
{
if(!m_curPen) return E_INVALIDARG;
RECT rcBuf = *pRect;
::InflateRect(&rcBuf,m_curPen->GetWidth()/2,m_curPen->GetWidth()/2);
DCBuffer dcBuf(m_hdc,&rcBuf,GetAValue(m_curPen->GetColor()));
::SelectObject(dcBuf, (HBRUSH)GetStockObject(NULL_BRUSH));
::Ellipse(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom);
return S_OK;
}
HRESULT SRenderTarget_GDI::FillEllipse( LPCRECT pRect )
{
BYTE byAlpha=0xFF;
if(!m_curBrush->IsBitmap()) byAlpha = GetAValue(m_curBrush->GetColor());
DCBuffer dcBuf(m_hdc,pRect,byAlpha);
HGDIOBJ oldPen = ::SelectObject(dcBuf, GetStockObject(NULL_PEN));
::Ellipse(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom);
::SelectObject(dcBuf, oldPen);
return S_OK;
}
HRESULT SRenderTarget_GDI::FillSolidEllipse(LPCRECT pRect,COLORREF cr)
{
DCBuffer dcBuf(m_hdc,pRect,GetAValue(cr),FALSE);
HBRUSH br=::CreateSolidBrush(cr&0x00ffffff);
HGDIOBJ oldObj=::SelectObject(dcBuf,br);
HGDIOBJ oldPen = ::SelectObject(dcBuf, GetStockObject(NULL_PEN));
::Ellipse(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom);
::SelectObject(dcBuf, oldPen);
::SelectObject(dcBuf,oldObj);
::DeleteObject(br);
return S_OK;
}
const float PI = 3.1415926f;
HRESULT SRenderTarget_GDI::DrawArc( LPCRECT pRect,float startAngle,float sweepAngle,bool useCenter )
{
if(!m_curPen) return E_INVALIDARG;
RECT rcBuf = *pRect;
::InflateRect(&rcBuf,m_curPen->GetWidth()/2,m_curPen->GetWidth()/2);
DCBuffer dcBuf(m_hdc,&rcBuf,GetAValue(m_curPen->GetColor()));
HGDIOBJ oldBr=::SelectObject(dcBuf,GetStockObject(NULL_BRUSH));
POINT ptCenter = {(pRect->left+pRect->right)/2,(pRect->top+pRect->bottom)/2};
int a=ptCenter.x-pRect->left,b=ptCenter.y-pRect->top;
POINT pt1,pt2;
float startAngle2 =startAngle*PI/180.0f;
float endAngle2 = (startAngle+sweepAngle)*PI/180.0f;
pt1.x=ptCenter.x+(int)(a*cos(startAngle2));
pt1.y=ptCenter.y+(int)(b*sin(startAngle2));
pt2.x=ptCenter.x+(int)(a*cos(endAngle2));
pt2.y=ptCenter.y+(int)(b*sin(endAngle2));
if (useCenter)
::Pie(dcBuf, pRect->left, pRect->top, pRect->right, pRect->bottom, pt2.x, pt2.y, pt1.x, pt1.y);
else
::Arc(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom,pt2.x,pt2.y,pt1.x,pt1.y);
::SelectObject(dcBuf,oldBr);
return S_OK;
}
HRESULT SRenderTarget_GDI::FillArc( LPCRECT pRect,float startAngle,float sweepAngle )
{
BYTE byAlpha=0xFF;
if(!m_curBrush->IsBitmap()) byAlpha = GetAValue(m_curBrush->GetColor());
DCBuffer dcBuf(m_hdc,pRect,byAlpha);
HGDIOBJ oldPen=::SelectObject(dcBuf,GetStockObject(NULL_PEN));
POINT ptCenter = {(pRect->left+pRect->right)/2,(pRect->top+pRect->bottom)/2};
int a=ptCenter.x-pRect->left,b=ptCenter.y-pRect->top;
POINT pt1,pt2;
float startAngle2 =startAngle*PI/180.0f;
float endAngle2 = (startAngle+sweepAngle)*PI/180.0f;
pt1.x=ptCenter.x+(int)(a*cos(startAngle2));
pt1.y=ptCenter.y+(int)(b*sin(startAngle2));
pt2.x=ptCenter.x+(int)(a*cos(endAngle2));
pt2.y=ptCenter.y+(int)(b*sin(endAngle2));
::Pie(dcBuf,pRect->left,pRect->top,pRect->right,pRect->bottom,pt2.x,pt2.y,pt1.x,pt1.y);
::SelectObject(dcBuf,oldPen);
return S_OK;
}
HRESULT SRenderTarget_GDI::SetTransform(const float matrix[9], float oldMatrix[9])
{
XFORM xForm = { matrix[IxForm::kMScaleX],matrix[IxForm::kMSkewY],
matrix[IxForm::kMSkewX],matrix[IxForm::kMScaleY],
matrix[IxForm::kMTransX],matrix[IxForm::kMTransY] };
if(oldMatrix)
{
GetTransform(oldMatrix);
}
return ::SetWorldTransform(m_hdc,&xForm)?S_OK:E_FAIL;
}
HRESULT SRenderTarget_GDI::GetTransform( float matrix[9]) const
{
SASSERT(matrix);
XFORM xForm;
if(!::GetWorldTransform(m_hdc,&xForm))
return E_FAIL;
matrix[IxForm::kMScaleX]=xForm.eM11;
matrix[IxForm::kMSkewX]=xForm.eM21;
matrix[IxForm::kMTransX]=xForm.eDx;
matrix[IxForm::kMSkewY]=xForm.eM12;
matrix[IxForm::kMScaleY]=xForm.eM22;
matrix[IxForm::kMTransY] = xForm.eDy;
matrix[IxForm::kMPersp0] = 0.0f;
matrix[IxForm::kMPersp1] = 0.0f;
matrix[IxForm::kMPersp2] = 1.0f;
return S_OK;
}
COLORREF SRenderTarget_GDI::GetPixel( int x, int y )
{
if(!m_curBmp) return CR_INVALID;
const COLORREF *pBits = (const COLORREF*)m_curBmp->GetPixelBits();
POINT pt;
GetViewportOrg(&pt);
x += pt.x;
y += pt.y;
if(x<0 || x >= (int)m_curBmp->Width() || y<0 || y>= (int)m_curBmp->Height())
return CR_INVALID;
return pBits[y*m_curBmp->Width()+x];
}
COLORREF SRenderTarget_GDI::SetPixel( int x, int y, COLORREF cr )
{
if(!m_curBmp) return CR_INVALID;
COLORREF *pBits = (COLORREF*)m_curBmp->LockPixelBits();
POINT pt;
GetViewportOrg(&pt);
x += pt.x;
y += pt.y;
if(x >= (int)m_curBmp->Width() || y>= (int)m_curBmp->Height())
return CR_INVALID;
COLORREF crRet = pBits[y*m_curBmp->Width()+x];
pBits[y*m_curBmp->Width()+x] = cr;
m_curBmp->UnlockPixelBits(pBits);
return crRet;
}
HRESULT SRenderTarget_GDI::GradientFill2(LPCRECT pRect,GradientType type,COLORREF crStart,COLORREF crCenter,COLORREF crEnd,float fLinearAngle,float fCenterX,float fCenterY,int nRadius,BYTE byAlpha/*=0xff*/)
{
(pRect), (type), (crStart), (crCenter), (crEnd), (fLinearAngle), (fCenterX), (fCenterY), (nRadius), (byAlpha);
return E_NOTIMPL;
}
HRESULT SRenderTarget_GDI::CreateRegion(IRegion ** ppRegion)
{
return m_pRenderFactory->CreateRegion(ppRegion)?S_OK:E_OUTOFMEMORY;
}
HRESULT SRenderTarget_GDI::PushClipPath(const IPath * path, UINT mode, bool doAntiAlias /*= false*/)
{
return E_NOTIMPL;
}
HRESULT SRenderTarget_GDI::DrawPath(const IPath * path,IPathEffect * pathEffect)
{
return E_NOTIMPL;
}
HRESULT SRenderTarget_GDI::FillPath(const IPath * path)
{
return E_NOTIMPL;
}
HRESULT SRenderTarget_GDI::PushLayer(const RECT * pRect,BYTE byAlpha)
{
return E_NOTIMPL;
}
HRESULT SRenderTarget_GDI::PopLayer()
{
return E_NOTIMPL;
}
HRESULT SRenderTarget_GDI::SetXfermode(int mode,int *pOldMode)
{
switch (mode)
{
case kSrcCopy:
case kDstInvert:
case kSrcInvert:
case kSrcAnd:
break;
default:
return E_INVALIDARG;
}
int nOldMode = ::SetROP2(m_hdc,mode);
if(pOldMode) *pOldMode = nOldMode;
return S_OK;
}
BOOL SRenderTarget_GDI::SetAntiAlias(BOOL bAntiAlias)
{
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
namespace RENDER_GDI
{
BOOL SCreateInstance(IObjRef ** ppRenderFactory)
{
*ppRenderFactory = new SRenderFactory_GDI;
return TRUE;
}
}
}