www.pudn.com > GameEngine_src.rar > CSurface.cpp
#include "CSurface.h" #include "CEasyDraw.h" #include "BaseUtil.h" #include "normal.h" #include//------------------------------------------------CSurface函数-------------------------------------------------------- int CSurface::g_TextOutX; int CSurface::g_TextOutY; HDC CSurface::g_hdc; HFONT CSurface::g_hFont; RECT CSurface::g_TextRect; ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// CSurface::CSurface() { Init(); } CSurface::~CSurface() { FreeSurface(); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::OnCreateSurface( bool isSysMemory, bool isColorKey ) { if ( m_lpDDSurface == NULL ) return false; GetWH( &m_iWidth, &m_iHeight ); if ( isColorKey ) { m_ColorKeyType = DDBLTFAST_SRCCOLORKEY; } if ( !isSysMemory ) return CreateCopySurface(); else return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::Init() { m_ColorKeyType = DDBLTFAST_NOCOLORKEY; m_lpDDSurface = NULL; m_lpDDSurfaceCopy = NULL; m_iWidth = 0; m_iHeight = 0; return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::FreeSurface() { SafeRelease( m_lpDDSurface ); SafeRelease( m_lpDDSurfaceCopy ); m_ColorKeyType = DDBLTFAST_NOCOLORKEY; m_iWidth = 0; m_iHeight = 0; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::CreateImageSurface( char *szFileName, bool isSysMemory, bool isColorKey, DWORD ColorKey ) { if ( szFileName != NULL ) { int len = strlen(szFileName); char szNameEx[3]; strcpy( szNameEx, &szFileName[len-3] ); if ( strcmp( szNameEx, "BMP" ) == 0 || strcmp( szNameEx, "bmp" ) == 0 ) { return CreateBmpSurface( szFileName, isSysMemory, isColorKey, ColorKey ); } /*else if ( strcmp( szNameEx, "JPG" ) == 0 || strcmp( szNameEx, "jpg" ) == 0 ) { return CreateJpegSurface( szFileName, isSysMemory, isColorKey, ColorKey ); }*/ else if ( strcmp( szNameEx, "ECP" ) == 0 || strcmp( szNameEx, "ecp" ) == 0 ) { return CreateEcpSurface( szFileName, isSysMemory ); } else return false; } return false; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::CreateBmpSurface( char *szFileName, bool isSysMemory, bool isColorKey, DWORD ColorKey ) { FreeSurface(); LPDIRECTDRAW7 lpdd = GetEasyDrawPointer()->GetLPDD(); HRESULT hr = CreateSurfaceOfBmp( lpdd, &m_lpDDSurface, szFileName, isSysMemory, isColorKey, ColorKey ); if ( hr == DDERR_OUTOFVIDEOMEMORY ) isSysMemory = true; return OnCreateSurface( isSysMemory, isColorKey ); } /* ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// inline bool CSurface::CreateJpegSurface( char *szFileName, bool isSysMemory, bool isColorKey, DWORD ColorKey ) { FreeSurface(); HRESULT hr = LoadJpegHelp( GetEasyDrawPointer()->GetLPDD(), &m_lpDDSurface, szFileName, m_lpDDSurface, isSysMemory, isColorKey, ColorKey, GetEasyDrawPointer()->Is565() ); if ( hr == DDERR_OUTOFVIDEOMEMORY ) isSysMemory = true; if ( m_lpDDSurface == NULL ) return false; GetWH( &m_iWidth, &m_iHeight ); if ( isColorKey ) { m_ColorKeyType = DDBLTFAST_SRCCOLORKEY; } if ( !isSysMemory ) return CreateCopySurface(); else return true; }*/ ////////////////////////////////////////////////////////////////////// //从ECP文件中载入,并创建一个页面 ////////////////////////////////////////////////////////////////////// inline bool CSurface::CreateEcpSurface( char *filename, bool isSysMemory ) { FreeSurface(); FILE *fp; fp = fopen(filename, "rb"); if ( fp == NULL ) return false; bool b = CreateEcpSurfaceHelp( fp, 0, NULL, isSysMemory ); fclose(fp); return true; } ////////////////////////////////////////////////////////////////////// //从ECP文件中载入,并创建一个页面 ////////////////////////////////////////////////////////////////////// bool CSurface::CreateEcpSurfaceHelp( FILE *fp, int offset, POINT *pPoint, bool isSysMemory ) { /******************************************************** *为了保护游戏资源,此函数内容省略 ********************************************************/ return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::CreateBmpSurfaceFromMemory( BYTE *pData, bool isSysMemory ) { if ( pData == NULL ) return false; BYTE *pOldData = pData; FreeSurface(); m_lpDDSurface = LoadBmpFromMemory( pData, GetEasyDrawPointer()->GetLPDD(), NULL, NULL, isSysMemory ); if ( m_lpDDSurface == 0 ) return false; return OnCreateSurface( isSysMemory, false ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::CreateEcpSurfaceFromMemory( BYTE *pData, bool isSysMemory, POINT *point ) { /******************************************************** *为了保护游戏资源,此函数内容省略 ********************************************************/ return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::CreateNullSurface( int iw, int ih, bool isSysMemory, bool isColorKey, DWORD ColorKey ) { FreeSurface(); HRESULT hr = CreateSurfaceHelp( GetEasyDrawPointer()->GetLPDD(), &m_lpDDSurface, iw, ih, isSysMemory, isColorKey, ColorKey ); if ( hr == DDERR_OUTOFVIDEOMEMORY ) { isSysMemory = true; } return OnCreateSurface( isSysMemory, isColorKey ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::CreateCopySurface() { if ( m_lpDDSurface == NULL ) return false; SafeRelease( m_lpDDSurfaceCopy ); CreateSurfaceHelp( GetEasyDrawPointer()->GetLPDD(), &m_lpDDSurfaceCopy, m_iWidth, m_iHeight, true, false, 0 ); if ( m_lpDDSurfaceCopy == NULL ) return false; m_lpDDSurfaceCopy->BltFast( 0, 0, m_lpDDSurface, NULL, DDBLTFAST_NOCOLORKEY ); return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::DrawSurface( int x, int y, RECT *pRect ) { LPDIRECTDRAWSURFACE7 lpDDBack = GetEasyDrawPointer()->GetBackSurface(); if ( m_lpDDSurface != NULL ) { lpDDBack->BltFast( x, y, m_lpDDSurface, pRect, m_ColorKeyType ); } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::DrawAutoClip( int x, int y ) { int iSW = GetEasyDrawPointer()->GetDeviceWidth(); int iSH = GetEasyDrawPointer()->GetDeviceHeight(); RECT rc; rc.left = 0; rc.top = 0; rc.right= m_iWidth; rc.bottom=m_iHeight; if ( x + m_iWidth > iSW ) { rc.right -= x + m_iWidth - iSW; } else if ( x < 0 ) { rc.left -= x; x = 0; } if ( y + m_iHeight > iSH ) { rc.bottom -= y + m_iHeight - iSH; } else if ( y < 0 ) { rc.top -= y; y = 0; } LPDIRECTDRAWSURFACE7 lpDDBack = GetEasyDrawPointer()->GetBackSurface(); lpDDBack->BltFast( x, y, m_lpDDSurface, &rc, m_ColorKeyType ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::DrawAlphaShadow( int x, int y ) { //if ( m_lpDDSurface == NULL ) //return; RECT rc_src; //temp页面上要锁定的矩形区域 RECT rc; //temp页面上要blt的区域 RECT rc_dest; //目标页面上的矩形区域 rc_src.left = 0; rc_src.top = 0; rc_src.right= m_iWidth; rc_src.bottom=m_iHeight; rc = rc_src; int iSW = GetEasyDrawPointer()->GetDeviceWidth(); int iSH = GetEasyDrawPointer()->GetDeviceHeight(); if ( x + m_iWidth > iSW ) rc.right -= x + m_iWidth - iSW; if ( x < 0 ) { rc.left -= x; x = 0; } if ( y + m_iHeight > iSH ) rc.bottom -= y + m_iHeight - iSH; if ( y < 0 ) { rc.top -= y; y = 0; } rc_dest.left = x; rc_dest.top = y; rc_dest.right= x + rc.right - rc.left; rc_dest.bottom=y + rc.bottom- rc.top; LPDIRECTDRAWSURFACE7 back, temp; back = GetEasyDrawPointer()->GetBackSurface(); temp = GetEasyDrawPointer()->GetTempSurface(); //把后台页面的矩形拷贝到特效页面上 temp->BltFast( rc.left, rc.top, back, &rc_dest, DDBLTFAST_NOCOLORKEY ); //锁定特效页面 DDSURFACEDESC2 ddsd; WORD *buf_temp, *buf_surf; int pitch_temp; ddsd.dwSize = sizeof(ddsd); if ( temp->Lock( &rc_src, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK ) return; buf_temp = (WORD *)ddsd.lpSurface; pitch_temp = ddsd.lPitch >> 1; //锁定内存页面 ddsd.dwSize = sizeof(ddsd); if ( m_lpDDSurface->Lock( NULL, &ddsd, DDLOCK_READONLY, NULL ) != DD_OK ) { temp->Unlock(0); return; } buf_surf = (WORD *)ddsd.lpSurface; WORD *buf = buf_temp; __int64 _0x7befx4 = 0x7bef7bef7bef7bef; WORD data = 0; while ( 1 ) { data = (*buf_surf); buf_surf++; if ( data == 0xffff ) { data = (*buf_surf); buf_surf++; buf += data; } else if ( data == 0xfffe ) { data = (*buf_surf); buf_surf++; int len = data; len = len - len % 4; int k = 0; __asm { mov eax, k; mov edx, buf; _for_k_begin: cmp eax, len; jge _for_k_end; movq mm0, [edx]; psrlw mm0, 1; pand mm0, _0x7befx4; movq [edx], mm0; add edx, 8; add eax, 4; jmp _for_k_begin; _for_k_end: mov k, eax; mov buf, edx; } for ( ; k < data; ++k ) { (*buf) = ( (*buf) >> 1 ) & 0x7bef; //565 mask ++buf; } } else if ( data == 0xfffd ) { buf_temp += pitch_temp; buf = buf_temp; } else { goto _exit; } } _exit: __asm emms; m_lpDDSurface->Unlock(0); temp->Unlock(0); back->BltFast( x, y, temp, &rc, DDBLTFAST_NOCOLORKEY ); } ////////////////////////////////////////////////////////////////////// //画带精灵轮廓的图片 ////////////////////////////////////////////////////////////////////// void CSurface::DrawContour( int x, int y ) { if ( m_lpDDSurface == NULL ) return; RECT rc_src; //temp页面上要锁定的矩形区域 rc_src.left = 0; rc_src.top = 0; rc_src.right= m_iWidth; rc_src.bottom=m_iHeight; int iSW = GetEasyDrawPointer()->GetDeviceWidth(); int iSH = GetEasyDrawPointer()->GetDeviceHeight(); if ( x + m_iWidth > iSW ) rc_src.right -= x + m_iWidth - iSW; else if ( x < 0 ) { rc_src.left -= x; x = 0; } if ( y + m_iHeight > iSH ) rc_src.bottom -= y + m_iHeight - iSH; else if ( y < 0 ) { rc_src.top -= y; y = 0; } LPDIRECTDRAWSURFACE7 back, temp; back = GetEasyDrawPointer()->GetBackSurface(); temp = GetEasyDrawPointer()->GetTempSurface(); WORD colorkey = (WORD)GetColorKey(); //把页面全部拷贝到temp上 LPDIRECTDRAWSURFACE7 surf = m_lpDDSurfaceCopy; if ( surf == NULL ) surf = m_lpDDSurface; temp->BltFast( 0, 0, surf, 0, DDBLTFAST_NOCOLORKEY ); //锁定temp,绘制精灵轮廓 RECT rc = {0, 0, m_iWidth, m_iHeight}; DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); if ( temp->Lock( &rc, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK ) return; WORD * buf_temp = (WORD *)ddsd.lpSurface; int pitch_temp = ddsd.lPitch >> 1; //绘制精灵轮廓 int i, j; for ( i = 0; i < m_iHeight; ++i ) { for ( j = 0; j < m_iWidth; ++j ) { if ( buf_temp[i * pitch_temp + j] != colorkey ) { buf_temp[i * pitch_temp + j] = 0xffff; // colorkey; break; } } } for ( i = 0; i < m_iHeight; ++i ) { for ( j = m_iWidth-1; j >= 0; --j ) { if ( buf_temp[i * pitch_temp + j] != colorkey ) { buf_temp[i * pitch_temp + j] = 0xffff; break; } } } for ( i = 0; i < m_iWidth; ++i ) { for ( j = 0; j < m_iHeight; ++j ) { if ( buf_temp[j * pitch_temp + i] != colorkey ) { buf_temp[j * pitch_temp + i] = 0xffff; break; } } } for ( i = 0; i < m_iWidth; ++i ) { for ( j = m_iHeight-1; j >= 0; --j ) { if ( buf_temp[j * pitch_temp + i] != colorkey ) { buf_temp[j * pitch_temp + i] = 0xffff; break; } } } temp->Unlock(0); SetColorKeyHelp( temp, colorkey ); back->BltFast( x, y, temp, &rc_src, DDBLTFAST_SRCCOLORKEY ); } ////////////////////////////////////////////////////////////////////// //MMX半透明混合,注意页面宽度整除4,无关健色 ////////////////////////////////////////////////////////////////////// void CSurface::DrawAlphaMMX( int x, int y ) { if ( m_lpDDSurface == NULL ) return; RECT rc_src; //temp页面上要锁定的矩形区域 RECT rc; //temp页面上要blt的区域 RECT rc_dest; //目标页面上的矩形区域 rc_src.left = 0; rc_src.top = 0; rc_src.right= m_iWidth; rc_src.bottom=m_iHeight; rc = rc_src; int iSW = GetEasyDrawPointer()->GetDeviceWidth(); int iSH = GetEasyDrawPointer()->GetDeviceHeight(); if ( x + m_iWidth > iSW ) rc.right -= x + m_iWidth - iSW; if ( x < 0 ) { rc.left -= x; x = 0; } if ( y + m_iHeight > iSH ) rc.bottom -= y + m_iHeight - iSH; if ( y < 0 ) { rc.top -= y; y = 0; } rc_dest.left = x; rc_dest.top = y; rc_dest.right= x + rc.right - rc.left; rc_dest.bottom=y + rc.bottom- rc.top; LPDIRECTDRAWSURFACE7 back, temp; back = GetEasyDrawPointer()->GetBackSurface(); temp = GetEasyDrawPointer()->GetTempSurface(); //把后台页面的矩形拷贝到特效页面上 temp->BltFast( rc.left, rc.top, back, &rc_dest, DDBLTFAST_NOCOLORKEY ); //锁定特效页面 DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); if ( temp->Lock( &rc_src, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK ) return; WORD *buf_temp = (WORD *)ddsd.lpSurface; int pitch_temp = ddsd.lPitch; //锁定内存页面 ddsd.dwSize = sizeof(ddsd); if ( m_lpDDSurface->Lock( NULL, &ddsd, DDLOCK_READONLY, NULL ) != DD_OK ) { temp->Unlock(0); return; } WORD *buf_surf = (WORD *)ddsd.lpSurface; ddsd.dwWidth *= 2; int pitch_surf = ddsd.lPitch - ddsd.dwWidth; pitch_temp -= ddsd.dwWidth; __int64 _0x7befx4 = 0x7bef7bef7bef7bef; __asm { mov edx, buf_temp; //edx 目标页面指针 mov ecx, buf_surf; //ecx 源页面指针 xor ebx, ebx; _for_h_begin: cmp ebx, ddsd.dwHeight; jnb _for_h_end; xor eax, eax; _for_w_begin: cmp eax, ddsd.dwWidth; jnb _for_w_end; movq mm0, [edx]; movq mm1, [ecx]; psrlw mm0, 1; psrlw mm1, 1; pand mm0, _0x7befx4; pand mm1, _0x7befx4; paddusw mm0, mm1; //注意要用paddusw无符号饱和压缩加法 movq [edx], mm0; add edx, 8; add ecx, 8; add eax, 8; jmp _for_w_begin; _for_w_end: inc ebx; add edx, pitch_temp; add ecx, pitch_surf; jmp _for_h_begin; _for_h_end: emms; } m_lpDDSurface->Unlock(0); temp->Unlock(0); back->BltFast( x, y, temp, &rc, DDBLTFAST_NOCOLORKEY ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::BltTo( int destX, int destY, CSurface *pDestSurf, RECT *rcSrc ) { if ( pDestSurf->m_lpDDSurface != NULL && m_lpDDSurface != NULL ) { pDestSurf->m_lpDDSurface->BltFast( destX, destY, m_lpDDSurface, rcSrc, m_ColorKeyType ); if ( pDestSurf->m_lpDDSurfaceCopy != NULL ) pDestSurf->m_lpDDSurfaceCopy->BltFast( destX, destY, m_lpDDSurface, rcSrc, m_ColorKeyType ); } } ////////////////////////////////////////////////////////////////////// //判断一个带关键色的页面上的(x,y)点是否非关健色 ////////////////////////////////////////////////////////////////////// bool CSurface::IsSurfaceSelected( int x, int y ) { WORD colorkey = (WORD)GetColorKey(); bool re = false; LPDIRECTDRAWSURFACE7 surf = m_lpDDSurfaceCopy; if ( surf == NULL ) surf = m_lpDDSurface; DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); if ( surf->Lock( 0, &ddsd, DDLOCK_READONLY, NULL ) != DD_OK ) return false; WORD * buf = (WORD *)ddsd.lpSurface; int pitch = ddsd.lPitch >> 1; if ( buf[y * pitch + x] != colorkey ) re = true; surf->Unlock(0); return re; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::Restore() { if ( m_lpDDSurface == NULL ) return false; HRESULT hr; hr = m_lpDDSurface->IsLost(); if ( hr != DD_OK ) { hr = m_lpDDSurface->Restore(); if ( hr != DD_OK ) return false; } if ( m_lpDDSurfaceCopy != NULL ) m_lpDDSurface->BltFast( 0, 0, m_lpDDSurfaceCopy, NULL, DDBLTFAST_NOCOLORKEY ); return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// DWORD CSurface::GetColorKey() { DDCOLORKEY ddck; ddck.dwColorSpaceHighValue = 0x0000; //if ( m_lpDDSurface != NULL ) m_lpDDSurface->GetColorKey( DDCKEY_SRCBLT, &ddck ); return ddck.dwColorSpaceHighValue & 0xffff; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::SetSurfaceColorKey( DWORD ColorKey ) { if ( !m_lpDDSurface == NULL ) { ColorKey = GetEasyDrawPointer()->ChangeColorKey( ColorKey ); SetColorKeyHelp( m_lpDDSurface, ColorKey ); m_ColorKeyType = DDBLTFAST_SRCCOLORKEY; } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::AutoSetColorKey() { WORD *buf = BeginDraw( 0, 0, 0, 0 ); WORD colorkey; if ( buf != NULL ) { colorkey = buf[0]; EndDraw(); SetSurfaceColorKey( colorkey ); } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::AutoClip() { if ( m_ColorKeyType == DDBLTFAST_NOCOLORKEY ) return; WORD colorkey = (WORD)GetColorKey(); LPDIRECTDRAWSURFACE7 temp = GetEasyDrawPointer()->GetTempSurface(); int width, height, pitch; WORD *buf = BeginDraw( &width, &height, &pitch, 0 ); RECT rc = {width, height, 0, 0 }; int i,j; //找出最靠左边的点 for ( i = 0; i < height; ++i ) { for ( j = 0; j < width; ++j ) { if ( buf[i*pitch + j] != colorkey ) { if ( j > rc.right ) rc.right = j; } } } for ( i = 0; i < height; ++i ) { for ( j = width-1; j >= 0; --j ) { if ( buf[i*pitch + j] != colorkey ) { if ( j < rc.left ) rc.left = j; } } } for ( i = 0; i < width; ++i ) { for ( j = 0; j < height; ++j ) { if ( buf[j*pitch + i] != colorkey ) { if ( j > rc.bottom ) rc.bottom = j; } } } for ( i = 0; i < width; ++i ) { for ( j = height-1; j >= 0; --j ) { if ( buf[j*pitch + i] != colorkey ) { if ( j < rc.top ) rc.top = j; } } } EndDraw(); if ( rc.right != 0 && rc.bottom != 0 ) { rc.right += 1; rc.bottom += 1; temp->BltFast( rc.left, rc.top, m_lpDDSurface, &rc, DDBLTFAST_NOCOLORKEY | DDBLTFAST_WAIT ); CreateNullSurface( rc.right-rc.left, rc.bottom-rc.top, false, true, colorkey ); m_lpDDSurface->BltFast( 0, 0, temp, &rc, DDBLTFAST_NOCOLORKEY ); if ( m_lpDDSurfaceCopy != NULL ) m_lpDDSurfaceCopy->BltFast( 0, 0, temp, &rc, DDBLTFAST_NOCOLORKEY ); } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::GetWH( int *pWidth, int *pHeight ) { DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof( DDSURFACEDESC2 ); if ( m_lpDDSurface != NULL ) { if ( m_lpDDSurface->GetSurfaceDesc( &ddsd ) != DD_OK ) return false; } else return false; if ( pWidth != NULL ) *pWidth = ddsd.dwWidth; if ( pHeight != NULL ) *pHeight= ddsd.dwHeight; return true; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// int CSurface::GetWidth() { return m_iWidth; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// int CSurface::GetHeight( ) { return m_iHeight; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::AlphaBlendSurface( CSurface *pSrcSurf, RECT *rcSrc, RECT *rcDest, DWORD alpha ) { if ( pSrcSurf != NULL && pSrcSurf->m_lpDDSurface != NULL ) { LPDIRECTDRAWSURFACE7 surfDest = m_lpDDSurfaceCopy; if ( surfDest == NULL ) surfDest = m_lpDDSurface; LPDIRECTDRAWSURFACE7 surfSrc = pSrcSurf->m_lpDDSurfaceCopy; if ( surfSrc == NULL ) surfSrc = pSrcSurf->m_lpDDSurface; if ( surfDest != NULL && surfSrc != NULL ) { AlphaSurfaceRect16( surfSrc, surfDest, rcSrc, rcDest, GetEasyDrawPointer()->Is565(), false, 0, alpha ); } } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::WriteText( const char *szText, int TextLen, int x, int y, DWORD Color ) { if ( m_lpDDSurfaceCopy != NULL ) { DrawTextOnSurface( m_lpDDSurfaceCopy, szText, TextLen, x, y, Color ); Restore(); } else if ( m_lpDDSurface != NULL ) { DrawTextOnSurface( m_lpDDSurface, szText, TextLen, x, y, Color ); } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::WriteTextCenter( const char *szText, DWORD Color ) { HDC hDC; if ( m_lpDDSurface && m_lpDDSurface->GetDC( &hDC ) == DD_OK ) { //SetBkColor( hDCBack, NULL ); SetBkMode( hDC, TRANSPARENT ); //背景透明 SetTextColor( hDC, Color ); SetTextAlign( hDC, TA_CENTER ); HFONT hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT); SelectObject(g_hdc, hFont); int y = m_iHeight/2 - CEasyDraw::g_CharHeight/2; TextOut( hDC, m_iWidth/2, y, szText, strlen(szText) ); DeleteObject( hFont ); m_lpDDSurface->ReleaseDC( hDC ); } } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::BeginDrawText( int x, int y ) { if ( m_lpDDSurface->GetDC( &g_hdc ) != DD_OK ) return false; g_hFont = (HFONT)GetStockObject(SYSTEM_FIXED_FONT); if ( g_hFont == NULL ) return false; SelectObject(g_hdc, g_hFont); g_TextOutX = x; g_TextOutY = y; g_TextRect.left = x; g_TextRect.top = y; return true; } ////////////////////////////////////////////////////////////////////// //绘制多行文本 ////////////////////////////////////////////////////////////////////// void CSurface::DrawText( const char *sz, DWORD color, bool isNextLine ) { int len_all = strlen(sz); if ( isNextLine ) g_TextOutY += CEasyDraw::g_CharHeight; SetBkMode( g_hdc, TRANSPARENT ); //背景透明 SetTextColor( g_hdc, color ); int last = len_all; while ( len_all > 0 ) { int len = last; if ( (g_TextOutX + last * CEasyDraw::g_CharWidth) - m_iWidth > 0 ) len = (m_iWidth - g_TextOutX) / CEasyDraw::g_CharWidth; TextOut( g_hdc, g_TextOutX, g_TextOutY, sz, len ); last = len_all - len; len_all -= len; sz += len; g_TextOutY += CEasyDraw::g_CharHeight; } g_TextRect.right = m_iWidth; g_TextRect.bottom= g_TextOutY; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::EndDrawText() { DeleteObject( g_hFont ); m_lpDDSurface->ReleaseDC( g_hdc ); g_hdc = NULL; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::ClearSurface( DWORD color, RECT *pRect ) { if ( m_lpDDSurface != NULL ) ClearSurfaceHelp( m_lpDDSurface, pRect, color ); if ( m_lpDDSurfaceCopy != NULL ) ClearSurfaceHelp( m_lpDDSurfaceCopy, pRect, color ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::ClearCopySurface( DWORD color, RECT *pRect ) { if ( m_lpDDSurfaceCopy != NULL ) ClearSurfaceHelp( m_lpDDSurfaceCopy, pRect, color ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::CopySurfaceToBmp( char *szBmpName, RECT *pRect ) { if ( m_lpDDSurface != NULL ) { return CopySurfaceToBmp16( m_lpDDSurface, szBmpName, pRect, GetEasyDrawPointer()->Is565() ); } else return false; } ////////////////////////////////////////////////////////////////////// //把一个页面保存到ECP文件中 ////////////////////////////////////////////////////////////////////// bool CSurface::SaveSurfaceToEcp( char *filename, RECT *pRect ) { FILE *fp = fopen( filename, "wb+" ); if ( fp == NULL ) { return false; } bool b = (SaveSurfaceToEcpHelp( fp, 0, NULL, pRect ) != 0 ); fclose(fp); return b; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// int CSurface::SaveSurfaceToEcpHelp( FILE *fp, int offset, const POINT *pPoint, RECT *pRect ) { WORD colorkey = 0; if ( m_ColorKeyType == DDBLTFAST_SRCCOLORKEY ) colorkey = (WORD)GetColorKey(); int width, height, pitch; WORD *buf16 = BeginDraw( &width, &height, &pitch, pRect ); if ( buf16 == NULL ) { return 0; } fseek( fp, offset, SEEK_SET ); ECPFILEHEADER efh; efh.ecpFileType = ECP; efh.ecpFileSize = 0; efh.ecpHeight = m_iHeight; efh.ecpWidth = m_iWidth; efh.ecpColorKeyType = m_ColorKeyType; efh.ecpColorKey = colorkey; efh.ecpBaseOffset.x = 0; efh.ecpBaseOffset.y = 0; efh.ecpIsCompress = FALSE; //压缩过的阴影图 if ( width != m_iWidth && height != m_iHeight) { efh.ecpFileType = ECP_SHADOW; efh.ecpWidth = ( ( m_iWidth << 16 ) & 0xffff0000 ) | ( width & 0xffff ); efh.ecpHeight= ( ( m_iHeight<< 16 ) & 0xffff0000 ) | ( height & 0xffff ); } if ( pPoint != NULL ) { efh.ecpBaseOffset.x = pPoint->x; efh.ecpBaseOffset.y = pPoint->y; } if ( m_ColorKeyType == DDBLTFAST_SRCCOLORKEY ) { efh.ecpIsCompress = TRUE; if ( GetEasyDrawPointer()->Is565() == false ) efh.ecpColorKey = CHANGE_555_TO_565( colorkey ); //存储的是565关健色 } fwrite( &efh, sizeof(efh), 1, fp ); //写入文件头 offset = sizeof(efh); if ( efh.ecpIsCompress ) { bool is_check_colorkey = false; int offset_colorkey = 0; int offset_pixel = 0; int num_colorkey = 0; //检测第一个像素是否是关键色 WORD pixel = buf16[0]; if ( pixel == colorkey ) { is_check_colorkey = true; } COMPRESS_DATA cd; WORD *pixel_buf = new WORD[256]; if ( pixel_buf == NULL ) { return 0; } for ( int i = 0; i < height; ++i ) { for ( int j = 0; j < width; ++j ) { pixel = buf16[i * pitch + j]; if ( is_check_colorkey ) { if ( pixel == colorkey ) { ++offset_colorkey; if ( offset_colorkey == 255 ) { cd.byte1 = COLORKEY_COUNT; cd.byte2 = (BYTE)offset_colorkey; fwrite( &cd, 2, 1, fp ); offset_colorkey = 0; } } else { if ( offset_colorkey != 0 ) { cd.byte1 = COLORKEY_COUNT; cd.byte2 = (BYTE)offset_colorkey; fwrite( &cd, 2, 1, fp ); offset_colorkey = 0; } is_check_colorkey = false; pixel_buf[offset_pixel++] = pixel; } } else { if ( pixel == colorkey ) { if ( offset_pixel != 0 ) { cd.byte1 = PIXEL_COUNT; cd.byte2 = offset_pixel; fwrite( &cd, 2, 1, fp ); fwrite( pixel_buf, offset_pixel * 2, 1, fp ); offset_pixel = 0; } is_check_colorkey = true; offset_colorkey = 1; } else { pixel_buf[offset_pixel++] = pixel; if ( offset_pixel == 255 ) { cd.byte1 = PIXEL_COUNT; cd.byte2 = offset_pixel; fwrite( &cd, 2, 1, fp ); fwrite( pixel_buf, offset_pixel * 2, 1, fp ); offset_pixel = 0; } } } }//for each pixel in a line if ( is_check_colorkey && offset_colorkey != 0 ) { cd.byte1 = COLORKEY_COUNT; cd.byte2 = (BYTE)offset_colorkey; fwrite( &cd, 2, 1, fp ); offset_colorkey = 0; } else if ( !is_check_colorkey && offset_pixel != 0 ) { cd.byte1 = PIXEL_COUNT; cd.byte2 = offset_pixel; fwrite( &cd, 2, 1, fp ); fwrite( pixel_buf, offset_pixel * 2, 1, fp ); offset_pixel = 0; } cd.byte1 = LINE_END; cd.byte2 = 0x00; fwrite( &cd, 2, 1, fp ); //写入行结束符 }// for every line cd.byte1 = ECP_FILE_END; cd.byte2 = ECP_FILE_END; fwrite( &cd, 2, 1, fp ); //写入文件结束符 delete [] pixel_buf; } //非压缩数据 else { WORD *pline = buf16; for ( int i = 0; i < height; ++i ) { fwrite( pline, width * 2, 1, fp ); pline += pitch; } } EndDraw(); fpos_t pos = 0; fgetpos(fp, &pos ); return (int)pos; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// WORD * CSurface::BeginDraw( int *iWidthOut, int *iHeightOut, int *iPitchOut, RECT *pRectIn ) { if ( m_lpDDSurface == NULL ) return NULL; LPDIRECTDRAWSURFACE7 surf; surf = m_lpDDSurface; if ( m_lpDDSurfaceCopy != NULL ) surf = m_lpDDSurfaceCopy; DDSURFACEDESC2 ddsd; ddsd.dwSize = sizeof(ddsd); if ( surf->Lock( pRectIn, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL ) != DD_OK ) return NULL; if ( iWidthOut != NULL ) { if ( pRectIn == NULL ) *iWidthOut = ddsd.dwWidth; else *iWidthOut = pRectIn->right - pRectIn->left; } if ( iHeightOut != NULL ) { if ( pRectIn == NULL ) *iHeightOut= ddsd.dwHeight; else *iHeightOut = pRectIn->bottom - pRectIn->top; } if ( iPitchOut != NULL ) *iPitchOut = ddsd.lPitch >> 1; return (WORD*)ddsd.lpSurface; } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::EndDraw() { if ( m_lpDDSurfaceCopy != NULL ) { m_lpDDSurfaceCopy->Unlock( 0 ); Restore(); } else m_lpDDSurface->Unlock( 0 ); } ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// void CSurface::CopySurface( CSurface *psurf ) { CreateNullSurface( psurf->GetWidth(), psurf->GetHeight(), false, psurf->IsColorKey(), psurf->GetColorKey() ); m_lpDDSurface->BltFast( 0, 0, psurf->m_lpDDSurface, 0, DDBLTFAST_NOCOLORKEY ); CreateCopySurface(); } const WORD MASK_R_565 = 0xf800; const WORD MASK_G_565 = 0x07e0; const WORD MASK_B_565 = 0x001f; const WORD MASK_R_555 = 0x7c00; const WORD MASK_G_555 = 0x03e0; const WORD MASK_B_555 = 0x001f; ////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// bool CSurface::MagicSurface( enum SURF_MAGIC magic, WORD colorkey, WORD MaskColor, RECT *pRect ) { if ( m_lpDDSurface == NULL ) return false; colorkey = (WORD)GetEasyDrawPointer()->ChangeColorKey( colorkey ); bool is565 = GetEasyDrawPointer()->Is565(); int iw, ih, ipitch; WORD *surf = NULL; WORD colorkey2; if ( m_ColorKeyType == DDBLTFAST_SRCCOLORKEY ) colorkey2 = (WORD)GetColorKey(); if ( magic == HALF_ALPHA ) //半透明页面 { if ( m_ColorKeyType == DDBLTFAST_NOCOLORKEY ) { return false; } surf = BeginDraw( &iw, &ih, &ipitch, pRect ); if ( surf == NULL ) return false; WORD mask = 0x7bef; if ( !is565 ) mask = 0x3def; int i, j; colorkey2 = ( ( colorkey2 >> 1 ) & mask ); for ( i = 0; i < ih; i++ ) { for ( j = 0; j < iw; j++ ) surf[i * ipitch + j] = ( ( surf[i * ipitch + j] >> 1 ) & mask ); } EndDraw(); SetSurfaceColorKey( colorkey2 ); } else if ( magic == ALPHA_SHADOW ) { surf = BeginDraw( &iw, &ih, &ipitch, 0 ); if ( surf == NULL ) return false; WORD *buf_temp = new WORD[iw * ih]; int index = 0; if ( buf_temp == NULL ) { return false; EndDraw(); } bool is_check_color_key = false; int num_shadow = 0; int num_color_key = 0; if ( (*surf) == colorkey2 ) is_check_color_key = true; //压缩阴影 for ( int i = 0; i < ih; ++i ) { for ( int j = 0; j < iw; ++j ) { WORD data = surf[i * ipitch + j]; if ( is_check_color_key ) { if ( data == colorkey2 ) ++num_color_key; else { if ( num_color_key > 0 ) { buf_temp[index++] = 0xffff; //0xffff后跟的是透明色像素偏移 buf_temp[index++] = num_color_key; //写入非阴影像素偏移 } is_check_color_key = false; num_color_key = 0; num_shadow = 1; } } else { if ( data != colorkey2 ) ++num_shadow; else { if ( num_shadow > 0 ) { buf_temp[index++] = 0xfffe; //0xfffe表示后面跟的是阴影像素 buf_temp[index++] = num_shadow; } is_check_color_key = true; num_shadow = 0; num_color_key = 1; } } } // for every pixel in line if ( is_check_color_key ) { if ( num_color_key > 0 ) { buf_temp[index++] = 0xffff; buf_temp[index++] = num_color_key; num_color_key = 0; } } else { if ( num_shadow > 0 ) { buf_temp[index++] = 0xfffe; buf_temp[index++] = num_shadow; num_shadow = 0; } } buf_temp[index++] = 0xfffd; //换行符 } //for every line buf_temp[index++] = 0x0000; //结束符 EndDraw(); FreeSurface(); int w_new = index; int h_new = 1;//index / w_new; //if ( index % 16 != 0 ) h_new += 1; if ( CreateNullSurface( w_new, h_new, true, false, 0 ) == false ) return false; surf = BeginDraw( &w_new, &h_new, &ipitch, 0 ); if ( surf == NULL ) return false; int k = 0; for ( i = 0; i < h_new; ++i ) { for ( int j = 0; j < w_new; ++j ) { if ( k < index ) surf[i * ipitch + j] = buf_temp[k++]; else surf[i * ipitch + j] = 0x0000; } } EndDraw(); delete [] buf_temp; m_iWidth = iw; //宽和高还是原页面的宽高! m_iHeight= ih; } else if ( magic == CONTOUR_IMAGE ) //带精灵轮廓的图片: { surf = BeginDraw( &iw, &ih, &ipitch, pRect ); if ( surf == NULL ) return false; int i, j; for ( i = 0; i < ih; ++i ) { for ( j = 0; j < iw; ++j ) { if ( surf[i * ipitch + j] != colorkey2 ) { surf[i * ipitch + j] = colorkey; // colorkey; break; } } } for ( i = 0; i < ih; ++i ) { for ( j = iw-1; j >= 0; --j ) { if ( surf[i * ipitch + j] != colorkey2 ) { surf[i * ipitch + j] = colorkey; break; } } } for ( i = 0; i < iw; ++i ) { for ( j = 0; j < ih; ++j ) { if ( surf[j * ipitch + i] != colorkey2 ) { surf[j * ipitch + i] = colorkey; break; } } } for ( i = 0; i < iw; ++i ) { for ( j = ih-1; j >= 0; --j ) { if ( surf[j * ipitch + i] != colorkey2 ) { surf[j * ipitch + i] = colorkey; break; } } } EndDraw(); } else if ( magic == GRAY_IMAGE ) //灰度图制作#define RGB_TO_565(r,g,b) ( (r << 11) | (g << 6 ) | b ) { surf = BeginDraw( &iw, &ih, &ipitch, pRect ); if ( surf == NULL ) return false; WORD r, g, b, t; if ( is565 ) { for ( int i = 0; i < ih; ++i ) { for ( int j = 0; j < iw; ++j ) { t = surf[i * ipitch + j]; r = ( t >> 11 ); g = ( t & MASK_G_565 ) >> 6; b = ( t & MASK_B_565 ); t = (r*3 + b*6+ g ) / 10; //t = ( r + g + b ) / 3; surf[i * ipitch + j] = ( (t << 11) | (t << 6 ) | t ); } } } else { for ( int i = 0; i < ih; ++i ) { for ( int j = 0; j < iw; ++j ) { t = surf[i * ipitch + j]; r = ( t >> 10 ); g = ( t & MASK_G_555 ) >> 5; b = ( t & MASK_B_555 ); t = (r*3 + b*6+ g ) / 10; //t = ( r + g + b ) / 3; surf[i * ipitch + j] = ( (t << 10) | (t << 5 ) | t ); } } } EndDraw(); if ( m_ColorKeyType == DDBLTFAST_SRCCOLORKEY ) { if ( is565 ) { r = colorkey2 >> 11; g = ( colorkey2 & MASK_G_565 ) >> 6; b = ( colorkey2 & MASK_B_565 ); t = (r*3 + b*6+ g ) / 10; colorkey2 = ( (t << 11) | (t << 6 ) | t ); } else { r = colorkey2 >> 10; g = ( colorkey2 & MASK_G_555 ) >> 5; b = ( colorkey2 & MASK_B_555 ); t = (r*3 + b*6+ g ) / 10; colorkey2 = ( (t << 10) | (t << 5 ) | t ); } SetSurfaceColorKey( colorkey2 ); } } else if ( magic >= 4 && magic <= 7 ) { WORD mask; switch ( magic ) { case RED_IMAGE: mask = MASK_R_565; if ( !is565 ) mask = MASK_R_555; break; case GREEN_IMAGE: mask = 0x3e0; //MASK_G_565; if ( !is565 ) mask = MASK_G_555; break; case BLUE_IMAGE: mask = 0x1f; break; case MASK_OR: mask = MaskColor; break; } surf = BeginDraw( &iw, &ih, &ipitch, pRect ); if ( surf == NULL ) return false; for ( int i = 0; i < ih; ++i ) { for ( int j = 0; j < iw; ++j ) surf[i * ipitch + j] |= mask; } EndDraw(); colorkey2 = colorkey2 | mask; SetSurfaceColorKey( colorkey2 ); } else if ( magic == MASK_AND ) { surf = BeginDraw( &iw, &ih, &ipitch, pRect ); if ( surf == NULL ) return false; for ( int i = 0; i < ih; ++i ) { for ( int j = 0; j < iw; ++j ) surf[i * ipitch + j] &= MaskColor; } EndDraw(); colorkey2 = colorkey2 & MaskColor; SetSurfaceColorKey( colorkey2 ); } return true; } ////////////////////////////////////////////////////////////////////// //从ECP文件中载入不透明阴影,专门为低配置机器而写 ////////////////////////////////////////////////////////////////////// bool CSurface::LoadEcpShadowFromMemory( BYTE *pData, POINT *point ) { FreeSurface(); ECPFILEHEADER efh; efh = READ_MEMORY( pData, ECPFILEHEADER ); pData += sizeof(efh); int width, height; if ( efh.ecpFileType == ECP_SHADOW ) { width = ( efh.ecpWidth >> 16 ) & 0xffff; height= ( efh.ecpHeight>> 16 ) & 0xffff; } else { return false; } if ( CreateNullSurface( width, height, 0, true, 0xffff ) == false ) return false; ClearSurface( 0xffffff, 0 ); if ( point != 0 ) { point->x = efh.ecpBaseOffset.x; point->y = efh.ecpBaseOffset.y; } int pitch; WORD *buf = BeginDraw( &width, &height, &pitch, NULL ); if ( buf == NULL ) return false; WORD *pline = buf; WORD *pixel = buf; while ( 1 ) { WORD data = READ_MEMORY( pData, WORD ); pData += sizeof(WORD); switch ( data ) { case 0xffff: data = READ_MEMORY( pData, WORD ); pData += sizeof(WORD); pixel += data; break; case 0xfffe: data = READ_MEMORY( pData, WORD ); pData += sizeof(WORD); memset( pixel, 0, data * 2 ); pixel += data; break; case 0xfffd: pline += pitch; pixel = pline; break; case 0x0000: goto exit_line; } } exit_line: EndDraw(); return true; }